+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "ATS tells us to switch to address '%s' for peer `%s'\n",
+ (address->address_length != 0) ? GST_plugins_a2s (address): "<inbound>",
+ GNUNET_i2s (peer));
+ switch (n->state)
+ {
+ case S_NOT_CONNECTED:
+ GNUNET_break (0);
+ free_neighbour (n, GNUNET_NO);
+ return;
+ case S_INIT_ATS:
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->state = S_INIT_BLACKLIST;
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_INIT_BLACKLIST:
+ /* ATS suggests a different address, switch again */
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_CONNECT_SENT:
+ /* ATS suggests a different address, switch again */
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->state = S_INIT_BLACKLIST;
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_CONNECT_RECV_ATS:
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->state = S_CONNECT_RECV_BLACKLIST;
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_CONNECT_RECV_BLACKLIST:
+ case S_CONNECT_RECV_ACK:
+ /* ATS asks us to switch while we were trying to connect; switch to new
+ address and check blacklist again */
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_CONNECTED:
+ GNUNET_assert (NULL != n->primary_address.address);
+ GNUNET_assert (NULL != n->primary_address.session);
+ if (n->primary_address.session == session)
+ {
+ /* not an address change, just a quota change */
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_YES);
+ break;
+ }
+ /* ATS asks us to switch a life connection; see if we can get
+ a CONNECT_ACK on it before we actually do this! */
+ set_address (&n->alternative_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->state = S_CONNECTED_SWITCHING_BLACKLIST;
+ check_blacklist (&n->id,
+ GNUNET_TIME_absolute_get (),
+ address, session, ats, ats_count);
+ break;
+ case S_RECONNECT_ATS:
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->state = S_RECONNECT_BLACKLIST;
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_RECONNECT_BLACKLIST:
+ /* ATS asks us to switch while we were trying to reconnect; switch to new
+ address and check blacklist again */
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_RECONNECT_SENT:
+ /* ATS asks us to switch while we were trying to reconnect; switch to new
+ address and check blacklist again */
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->state = S_RECONNECT_BLACKLIST;
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_CONNECTED_SWITCHING_BLACKLIST:
+ if (n->primary_address.session == session)
+ {
+ /* ATS switches back to still-active session */
+ free_address (&n->alternative_address);
+ n->state = S_CONNECTED;
+ break;
+ }
+ /* ATS asks us to switch a life connection, update blacklist check */
+ set_address (&n->alternative_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ check_blacklist (&n->id,
+ GNUNET_TIME_absolute_get (),
+ address, session, ats, ats_count);
+ break;
+ case S_CONNECTED_SWITCHING_CONNECT_SENT:
+ if (n->primary_address.session == session)
+ {
+ /* ATS switches back to still-active session */
+ free_address (&n->alternative_address);
+ n->state = S_CONNECTED;
+ break;
+ }
+ /* ATS asks us to switch a life connection, update blacklist check */
+ set_address (&n->alternative_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->state = S_CONNECTED_SWITCHING_BLACKLIST;
+ check_blacklist (&n->id,
+ GNUNET_TIME_absolute_get (),
+ address, session, ats, ats_count);
+ break;
+ case S_DISCONNECT:
+ /* not going to switch addresses while disconnecting */
+ return;
+ case S_DISCONNECT_FINISHED:
+ GNUNET_assert (0);
+ break;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s' \n",print_state (n->state));
+ GNUNET_break (0);
+ break;
+ }