- * For an existing neighbour record, set the active connection to
- * use the given address.
- *
- * @param peer identity of the peer to switch the address for
- * @param address address of the other peer, NULL if other peer
- * connected to us
- * @param session session to use (or NULL)
- * @param ats performance data
- * @param ats_count number of entries in ats
- * @param bandwidth_in inbound quota to be used when connection is up
- * @param bandwidth_out outbound quota to be used when connection is up
- * @return GNUNET_YES if we are currently connected, GNUNET_NO if the
- * connection is not up (yet)
- */
-int
-GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_HELLO_Address
- *address,
- struct Session *session,
- const struct GNUNET_ATS_Information *ats,
- uint32_t ats_count,
- struct GNUNET_BANDWIDTH_Value32NBO
- bandwidth_in,
- struct GNUNET_BANDWIDTH_Value32NBO
- bandwidth_out)
-{
- struct NeighbourMapEntry *n;
- struct SessionConnectMessage connect_msg;
- struct ContinutionContext *cc;
- size_t msg_len;
- size_t ret;
-
- if (neighbours == NULL)
- {
- /* This can happen during shutdown */
- return GNUNET_NO;
- }
- n = lookup_neighbour (peer);
- if (NULL == n)
- return GNUNET_NO;
- if (n->state == S_DISCONNECT)
- {
- /* We are disconnecting, nothing to do here */
- return GNUNET_NO;
- }
- GNUNET_assert (address->transport_name != NULL);
- if ((session == NULL) && (0 == address->address_length))
- {
- GNUNET_break_op (0);
- /* FIXME: is this actually possible? When does this happen? */
- if (strlen (address->transport_name) > 0)
- GNUNET_ATS_address_destroyed (GST_ats, address, session);
- GNUNET_ATS_suggest_address (GST_ats, peer);
- return GNUNET_NO;
- }
-
- /* checks successful and neighbour != NULL */
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "ATS tells us to switch to address '%s' session %p for peer `%s' in state `%s'\n",
- GST_plugins_a2s (address), session, GNUNET_i2s (peer),
- print_state (n->state));
-#endif
- if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (n->ats_suggest);
- n->ats_suggest = GNUNET_SCHEDULER_NO_TASK;
- }
- /* do not switch addresses just update quotas */
- if ((n->state == S_CONNECTED) && (NULL != n->address) &&
- (0 == GNUNET_HELLO_address_cmp (address, n->address)) &&
- (n->session == session))
- {
- n->bandwidth_in = bandwidth_in;
- n->bandwidth_out = bandwidth_out;
- GST_neighbours_set_incoming_quota (&n->id, n->bandwidth_in);
- send_outbound_quota (peer, n->bandwidth_out);
- return GNUNET_NO;
- }
- if (n->state == S_CONNECTED)
- {
- /* mark old address as no longer used */
- GNUNET_assert (NULL != n->address);
- if (n->address_state == USED)
- {
- GST_validation_set_address_use (n->address, n->session, GNUNET_NO);
- GNUNET_ATS_address_in_use (GST_ats, n->address, n->session, GNUNET_NO);
- n->address_state = UNUSED;
- }
- }
-
- /* set new address */
- if (NULL != n->address)
- GNUNET_HELLO_address_free (n->address);
- n->address = GNUNET_HELLO_address_copy (address);
- n->address_state = FRESH;
- n->bandwidth_in = bandwidth_in;
- n->bandwidth_out = bandwidth_out;
- GNUNET_SCHEDULER_cancel (n->timeout_task);
- n->timeout_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
- &neighbour_timeout_task, n);
-
- if (NULL != address_change_cb && n->state == S_CONNECTED)
- address_change_cb (callback_cls, &n->id, n->address);
-
- /* Obtain an session for this address from plugin */
- struct GNUNET_TRANSPORT_PluginFunctions *papi;
- papi = GST_plugins_find (address->transport_name);
- GNUNET_assert (papi != NULL);
- if (session == NULL)
- {
- n->session = papi->get_session (papi->cls, address);
- /* Session could not be initiated */
- if (n->session == NULL)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to obtain new session %p for peer `%s' and address '%s'\n",
- n->session, GNUNET_i2s (&n->id), GST_plugins_a2s (n->address));
-
- GNUNET_ATS_address_destroyed (GST_ats, n->address, NULL);
-
- if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (n->ats_suggest);
- n->ats_suggest = GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT,
- ats_suggest_cancel,
- n);
- GNUNET_ATS_suggest_address (GST_ats, &n->id);
- GNUNET_HELLO_address_free (n->address);
- n->address = NULL;
- return GNUNET_NO;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Obtained new session %p for peer `%s' and address '%s'\n",
- n->session, GNUNET_i2s (&n->id), GST_plugins_a2s (n->address));
- /* Telling ATS about new session */
- GNUNET_ATS_address_update (GST_ats, n->address, n->session, NULL, 0);
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Using existing session %p for peer `%s' and address '%s'\n",
- n->session, GNUNET_i2s (&n->id), GST_plugins_a2s (n->address));
- n->session = session;
- }
-
- switch (n->state)
- {
- case S_NOT_CONNECTED:
- case S_CONNECT_SENT:
- msg_len = sizeof (struct SessionConnectMessage);
- connect_msg.header.size = htons (msg_len);
- connect_msg.header.type =
- htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT);
- connect_msg.reserved = htonl (0);
- connect_msg.timestamp =
- GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
-
- cc = GNUNET_malloc (sizeof (struct ContinutionContext));
- cc->session = session;
- cc->address = GNUNET_HELLO_address_copy (address);
-
- ret = send_with_session (n,
- (const char *) &connect_msg, msg_len,
- UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
- &send_connect_continuation, cc);
-
- return GNUNET_NO;
- case S_CONNECT_RECV:
- /* We received a CONNECT message and asked ATS for an address */
- msg_len = sizeof (struct SessionConnectMessage);
- connect_msg.header.size = htons (msg_len);
- connect_msg.header.type =
- htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT_ACK);
- connect_msg.reserved = htonl (0);
- connect_msg.timestamp =
- GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
- cc = GNUNET_malloc (sizeof (struct ContinutionContext));
- cc->session = session;
- cc->address = GNUNET_HELLO_address_copy (address);
-
- ret = send_with_session(n,
- (const void *) &connect_msg, msg_len,
- UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
- &send_connect_ack_continuation,
- cc);
- return GNUNET_NO;
- case S_CONNECTED:
- case S_FAST_RECONNECT:
- /* connected peer is switching addresses or tries fast reconnect */
- msg_len = sizeof (struct SessionConnectMessage);
- connect_msg.header.size = htons (msg_len);
- connect_msg.header.type =
- htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT);
- connect_msg.reserved = htonl (0);
- connect_msg.timestamp =
- GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
- cc = GNUNET_malloc (sizeof (struct ContinutionContext));
- cc->session = session;
- cc->address = GNUNET_HELLO_address_copy (address);
- ret = send_with_session(n,
- (const void *) &connect_msg, msg_len,
- UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
- &send_switch_address_continuation, cc);
- if (ret == GNUNET_SYSERR)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Failed to send CONNECT_MESSAGE to `%4s' using address '%s' session %X\n",
- GNUNET_i2s (peer), GST_plugins_a2s (address), session);
- }
- return GNUNET_NO;
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Invalid connection state to switch addresses %u \n", n->state);
- GNUNET_break_op (0);
- return GNUNET_NO;
- }
-}
-
-
-/**
- * Obtain current latency information for the given neighbour.
- *
- * @param peer
- * @return observed latency of the address, FOREVER if the address was
- * never successfully validated
- */
-struct GNUNET_TIME_Relative
-GST_neighbour_get_latency (const struct GNUNET_PeerIdentity *peer)
-{
- struct NeighbourMapEntry *n;
-
- n = lookup_neighbour (peer);
- if ((NULL == n) || ((n->address == NULL) && (n->session == NULL)))
- return GNUNET_TIME_UNIT_FOREVER_REL;
-
- return n->latency;
-}
-
-/**
- * Obtain current address information for the given neighbour.
- *
- * @param peer
- * @return address currently used
- */
-struct GNUNET_HELLO_Address *
-GST_neighbour_get_current_address (const struct GNUNET_PeerIdentity *peer)
-{
- struct NeighbourMapEntry *n;
-
- n = lookup_neighbour (peer);
- if ((NULL == n) || ((n->address == NULL) && (n->session == NULL)))
- return NULL;
-
- return n->address;
-}
-
-
-
-/**
- * Create an entry in the neighbour map for the given peer