+ /* valid new address, let ATS know! */
+ GNUNET_ATS_address_update (GST_ats,
+ bcc->na.address,
+ bcc->na.session,
+ bcc->ats, bcc->ats_count);
+ }
+ if (NULL == (n = lookup_neighbour (peer)))
+ goto cleanup; /* nobody left to care about new address */
+ switch (n->state)
+ {
+ case S_NOT_CONNECTED:
+ /* this should not be possible */
+ GNUNET_break (0);
+ free_neighbour (n, GNUNET_NO);
+ break;
+ case S_INIT_ATS:
+ /* still waiting on ATS suggestion */
+ break;
+ case S_INIT_BLACKLIST:
+ /* check if the address the blacklist was fine with matches
+ ATS suggestion, if so, we can move on! */
+ if ( (GNUNET_OK == result) &&
+ (1 == n->send_connect_ack) )
+ {
+ n->send_connect_ack = 2;
+ send_session_connect_ack_message (bcc->na.address,
+ bcc->na.session,
+ n->connect_ack_timestamp);
+ }
+ if (GNUNET_YES != address_matches (&bcc->na, &n->primary_address))
+ break; /* result for an address we currently don't care about */
+ if (GNUNET_OK == result)
+ {
+ n->timeout = GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT);
+ n->state = S_CONNECT_SENT;
+ send_session_connect (&n->primary_address);
+ }
+ else
+ {
+ GNUNET_ATS_address_destroyed (GST_ats,
+ bcc->na.address,
+ NULL);
+ n->state = S_INIT_ATS;
+ n->timeout = GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT);
+ // FIXME: do we need to ask ATS again for suggestions?
+ GNUNET_ATS_suggest_address (GST_ats, &n->id);
+ }
+ break;
+ case S_CONNECT_SENT:
+ /* waiting on CONNECT_ACK, send ACK if one is pending */
+ if ( (GNUNET_OK == result) &&
+ (1 == n->send_connect_ack) )
+ {
+ n->send_connect_ack = 2;
+ send_session_connect_ack_message (n->primary_address.address,
+ n->primary_address.session,
+ n->connect_ack_timestamp);
+ }
+ break;
+ case S_CONNECT_RECV_ATS:
+ /* still waiting on ATS suggestion, don't care about blacklist */
+ break;
+ case S_CONNECT_RECV_BLACKLIST:
+ if (GNUNET_YES != address_matches (&bcc->na, &n->primary_address))
+ break; /* result for an address we currently don't care about */
+ if (GNUNET_OK == result)
+ {
+ n->timeout = GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT);
+ n->state = S_CONNECT_RECV_ACK;
+ send_session_connect_ack_message (bcc->na.address,
+ bcc->na.session,
+ n->connect_ack_timestamp);
+ if (1 == n->send_connect_ack)
+ n->send_connect_ack = 2;
+ }
+ else
+ {
+ GNUNET_ATS_address_destroyed (GST_ats,
+ bcc->na.address,
+ NULL);
+ n->state = S_INIT_ATS;
+ n->timeout = GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT);
+ // FIXME: do we need to ask ATS again for suggestions?
+ GNUNET_ATS_reset_backoff (GST_ats, peer);
+ GNUNET_ATS_suggest_address (GST_ats, &n->id);
+ }
+ break;
+ case S_CONNECT_RECV_ACK:
+ /* waiting on SESSION_ACK, send ACK if one is pending */
+ if ( (GNUNET_OK == result) &&
+ (1 == n->send_connect_ack) )
+ {
+ n->send_connect_ack = 2;
+ send_session_connect_ack_message (n->primary_address.address,
+ n->primary_address.session,
+ n->connect_ack_timestamp);
+ }
+ break;
+ case S_CONNECTED:
+ /* already connected, don't care about blacklist */
+ break;
+ case S_RECONNECT_ATS:
+ /* still waiting on ATS suggestion, don't care about blacklist */
+ break;
+ case S_RECONNECT_BLACKLIST:
+ if ( (GNUNET_OK == result) &&
+ (1 == n->send_connect_ack) )
+ {
+ n->send_connect_ack = 2;
+ send_session_connect_ack_message (bcc->na.address,
+ bcc->na.session,
+ n->connect_ack_timestamp);
+ }
+ if (GNUNET_YES != address_matches (&bcc->na, &n->primary_address))
+ break; /* result for an address we currently don't care about */
+ if (GNUNET_OK == result)
+ {
+ send_session_connect (&n->primary_address);
+ n->timeout = GNUNET_TIME_relative_to_absolute (FAST_RECONNECT_TIMEOUT);
+ n->state = S_RECONNECT_SENT;
+ }
+ else
+ {
+ GNUNET_ATS_address_destroyed (GST_ats,
+ bcc->na.address,
+ NULL);
+ n->state = S_RECONNECT_ATS;
+ n->timeout = GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT);
+ // FIXME: do we need to ask ATS again for suggestions?
+ GNUNET_ATS_suggest_address (GST_ats, &n->id);
+ }
+ break;
+ case S_RECONNECT_SENT:
+ /* waiting on CONNECT_ACK, don't care about blacklist */
+ if ( (GNUNET_OK == result) &&
+ (1 == n->send_connect_ack) )
+ {
+ n->send_connect_ack = 2;
+ send_session_connect_ack_message (n->primary_address.address,
+ n->primary_address.session,
+ n->connect_ack_timestamp);
+ }
+ break;
+ case S_CONNECTED_SWITCHING_BLACKLIST:
+ if (GNUNET_YES != address_matches (&bcc->na, &n->alternative_address))
+ break; /* result for an address we currently don't care about */
+ if (GNUNET_OK == result)
+ {
+ send_session_connect (&n->alternative_address);
+ n->state = S_CONNECTED_SWITCHING_CONNECT_SENT;
+ }
+ else
+ {
+ GNUNET_ATS_address_destroyed (GST_ats,
+ bcc->na.address,
+ NULL);
+ free_address (&n->alternative_address);
+ n->state = S_CONNECTED;
+ }
+ break;
+ case S_CONNECTED_SWITCHING_CONNECT_SENT:
+ /* waiting on CONNECT_ACK, don't care about blacklist */
+ if ( (GNUNET_OK == result) &&
+ (1 == n->send_connect_ack) )
+ {
+ n->send_connect_ack = 2;
+ send_session_connect_ack_message (n->primary_address.address,
+ n->primary_address.session,
+ n->connect_ack_timestamp);
+ }
+ break;
+ case S_DISCONNECT:
+ /* Nothing to do here, ATS will already do what can be done */
+ break;
+ case S_DISCONNECT_FINISHED:
+ /* should not be possible */
+ GNUNET_assert (0);
+ break;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s' \n",print_state (n->state));
+ GNUNET_break (0);
+ free_neighbour (n, GNUNET_NO);
+ break;