#define KEEPALIVE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
-#define ATS_RESPONSE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)
+#define ATS_RESPONSE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
+
+#define FAST_RECONNECT_RATE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100)
#define FAST_RECONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
#define SETUP_CONNECTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
-
#define TEST_NEW_CODE GNUNET_NO
/**
*/
struct GNUNET_HELLO_Address *address;
+ /**
+ * Address we currently use.
+ */
+ struct GNUNET_HELLO_Address *fast_reconnect_address;
+
+
/**
* Identity of this neighbour.
*/
*/
GNUNET_SCHEDULER_TaskIdentifier ats_suggest;
+ /**
+ * Delay for ATS request
+ */
+ GNUNET_SCHEDULER_TaskIdentifier ats_request;
+
/**
* Task the resets the peer state after due to an pending
* unsuccessful connection setup
* Did we sent an KEEP_ALIVE message and are we expecting a response?
*/
int expect_latency_response;
+
+ /**
+ * Was the address used successfully
+ */
int address_state;
+
+ /**
+ * Fast reconnect attempts for identical address
+ */
+ unsigned int fast_reconnect_attempts;
};
static struct GNUNET_CONTAINER_MultiHashMap *neighbours;
/**
- * Closure for connect_notify_cb and disconnect_notify_cb
+ * Closure for connect_notify_cb, disconnect_notify_cb and address_change_cb
*/
static void *callback_cls;
*/
static GNUNET_TRANSPORT_NotifyDisconnect disconnect_notify_cb;
+/**
+ * Function to call when we changed an active address of a neighbour.
+ */
+static GNUNET_TRANSPORT_PeerIterateCallback address_change_cb;
+
/**
* counter for connected neighbours
*/
return GNUNET_CONTAINER_multihashmap_get (neighbours, &pid->hashPubKey);
}
+/**
+ * Disconnect from the given neighbour, clean up the record.
+ *
+ * @param n neighbour to disconnect from
+ */
+static void
+disconnect_neighbour (struct NeighbourMapEntry *n);
+
#define change_state(n, state, ...) change (n, state, __LINE__)
static int
#endif
/* resetting state */
+
+ if (n->state == S_FAST_RECONNECT)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Fast reconnect time out, disconnecting peer `%s'\n",
+ GNUNET_i2s (&n->id));
+ disconnect_neighbour(n);
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "State for neighbour `%s' %X changed from `%s' to `%s' in line %u\n",
+ GNUNET_i2s (&n->id), n, print_state(n->state), "S_NOT_CONNECTED", __LINE__);
+
n->state = S_NOT_CONNECTED;
/* destroying address */
static int
change (struct NeighbourMapEntry *n, int state, int line)
{
+ int previous_state;
/* allowed transitions */
int allowed = GNUNET_NO;
+ previous_state = n->state;
+
switch (n->state)
{
case S_NOT_CONNECTED:
GNUNET_free (new);
return GNUNET_SYSERR;
}
-#if DEBUG_TRANSPORT
{
char *old = GNUNET_strdup (print_state (n->state));
char *new = GNUNET_strdup (print_state (state));
GNUNET_free (old);
GNUNET_free (new);
}
-#endif
n->state = state;
switch (n->state)
GNUNET_assert (0);
}
-
+ if (NULL != address_change_cb)
+ {
+ if (n->state == S_CONNECTED)
+ address_change_cb (callback_cls, &n->id, n->address);
+ else if (previous_state == S_CONNECTED)
+ address_change_cb (callback_cls, &n->id, NULL);
+ }
return GNUNET_OK;
}
static ssize_t
send_with_session (struct NeighbourMapEntry *n,
- struct Session *session,
const char *msgbuf, size_t msgbuf_size,
uint32_t priority,
struct GNUNET_TIME_Relative timeout,
struct GNUNET_TRANSPORT_PluginFunctions *papi;
size_t ret = GNUNET_SYSERR;
+ GNUNET_assert (n != NULL);
+ GNUNET_assert (n->session != NULL);
+
papi = GST_plugins_find (n->address->transport_name);
if (papi == NULL)
{
return GNUNET_SYSERR;
}
- ret = papi->send_with_session (papi->cls,
- session,
- msgbuf, msgbuf_size,
- 0,
- timeout,
- cont, cont_cls);
+ ret = papi->send (papi->cls,
+ n->session,
+ msgbuf, msgbuf_size,
+ 0,
+ timeout,
+ cont, cont_cls);
if ((ret == -1) && (cont != NULL))
cont (cont_cls, &n->id, GNUNET_SYSERR);
return ret;
}
-
-
-static ssize_t
-send_with_plugin (const struct GNUNET_PeerIdentity *target, const char *msgbuf,
- size_t msgbuf_size, uint32_t priority,
- struct GNUNET_TIME_Relative timeout, struct Session *session,
- const struct GNUNET_HELLO_Address *address, int force_address,
- GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
-{
- struct GNUNET_TRANSPORT_PluginFunctions *papi;
- size_t ret = GNUNET_SYSERR;
-
- /* FIXME : ats returns an address with all values 0 */
- if (address == NULL)
- {
- if (cont != NULL)
- cont (cont_cls, target, GNUNET_SYSERR);
- return GNUNET_SYSERR;
- }
-
- if ((session == NULL) && (address->address_length == 0))
- {
- if (cont != NULL)
- cont (cont_cls, target, GNUNET_SYSERR);
- return GNUNET_SYSERR;
- }
-
- papi = GST_plugins_find (address->transport_name);
- if (papi == NULL)
- {
- if (cont != NULL)
- cont (cont_cls, target, GNUNET_SYSERR);
- return GNUNET_SYSERR;
- }
-
- ret =
- papi->send (papi->cls, target, msgbuf, msgbuf_size, 0, timeout, session,
- address->address, address->address_length, GNUNET_YES, cont,
- cont_cls);
-
- if (ret == -1)
- {
- if (cont != NULL)
- cont (cont_cls, target, GNUNET_SYSERR);
- }
- return ret;
-}
-
-
/**
* Task invoked to start a transmission to another peer.
*
return;
}
- ret =
- send_with_plugin (&n->id, mq->message_buf, mq->message_buf_size, 0,
- timeout, n->session, n->address, GNUNET_YES,
- &transmit_send_continuation, mq);
+ ret = send_with_session(n,
+ mq->message_buf, mq->message_buf_size,
+ 0, timeout,
+ &transmit_send_continuation, mq);
+
if (ret == -1)
{
/* failure, but 'send' would not call continuation in this case,
* @param cls closure for callbacks
* @param connect_cb function to call if we connect to a peer
* @param disconnect_cb function to call if we disconnect from a peer
+ * @param peer_address_cb function to call if we change an active address
+ * of a neighbour
*/
void
-GST_neighbours_start (void *cls, GNUNET_TRANSPORT_NotifyConnect connect_cb,
- GNUNET_TRANSPORT_NotifyDisconnect disconnect_cb)
+GST_neighbours_start (void *cls,
+ GNUNET_TRANSPORT_NotifyConnect connect_cb,
+ GNUNET_TRANSPORT_NotifyDisconnect disconnect_cb,
+ GNUNET_TRANSPORT_PeerIterateCallback peer_address_cb)
{
callback_cls = cls;
connect_notify_cb = connect_cb;
disconnect_notify_cb = disconnect_cb;
+ address_change_cb = peer_address_cb;
neighbours = GNUNET_CONTAINER_multihashmap_create (NEIGHBOUR_TABLE_SIZE);
}
static int
-send_disconnect (const struct GNUNET_PeerIdentity *target,
- const struct GNUNET_HELLO_Address *address,
- struct Session *session)
+send_disconnect (struct NeighbourMapEntry * n)
{
size_t ret;
struct SessionDisconnectMessage disconnect_msg;
#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Sending DISCONNECT message to peer `%4s'\n",
- GNUNET_i2s (target));
+ GNUNET_i2s (&n->id));
#endif
disconnect_msg.header.size = htons (sizeof (struct SessionDisconnectMessage));
&disconnect_msg.purpose,
&disconnect_msg.signature));
- ret =
- send_with_plugin (target, (const char *) &disconnect_msg,
- sizeof (disconnect_msg), UINT32_MAX,
- GNUNET_TIME_UNIT_FOREVER_REL, session, address,
- GNUNET_YES, &send_disconnect_cont, NULL);
+ ret = send_with_session (n,
+ (const char *) &disconnect_msg, sizeof (disconnect_msg),
+ UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
+ &send_disconnect_cont, NULL);
if (ret == GNUNET_SYSERR)
return GNUNET_SYSERR;
/* send DISCONNECT MESSAGE */
if (previous_state == S_CONNECTED)
{
- if (GNUNET_OK == send_disconnect (&n->id, n->address, n->session))
+ if (GNUNET_OK == send_disconnect (n))
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent DISCONNECT_MSG to `%s'\n",
GNUNET_i2s (&n->id));
else
GNUNET_assert (NULL != n->address);
if (n->address_state == USED)
{
- GST_validation_set_address_use (n->address, n->session, GNUNET_NO);
+ GST_validation_set_address_use (n->address, n->session, GNUNET_NO, __LINE__);
GNUNET_ATS_address_in_use (GST_ats, n->address, n->session, GNUNET_NO);
n->address_state = UNUSED;
}
GNUNET_SCHEDULER_cancel (n->ats_suggest);
n->ats_suggest = GNUNET_SCHEDULER_NO_TASK;
}
+ if (n->ats_request != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (n->ats_request);
+ n->ats_request = GNUNET_SCHEDULER_NO_TASK;
+ }
+
if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task)
{
GNUNET_SCHEDULER_cancel (n->timeout_task);
GNUNET_SCHEDULER_cancel (n->transmission_task);
n->transmission_task = GNUNET_SCHEDULER_NO_TASK;
}
+ if (NULL != n->fast_reconnect_address)
+ {
+ GNUNET_HELLO_address_free (n->fast_reconnect_address);
+ n->fast_reconnect_address = NULL;
+ }
if (NULL != n->address)
{
GNUNET_HELLO_address_free (n->address);
struct NeighbourMapEntry *n = cls;
n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer`%4s' disconnected due to timeout\n",
+ GNUNET_i2s (&n->id));
GNUNET_STATISTICS_update (GST_stats,
gettext_noop
m.size = htons (sizeof (struct GNUNET_MessageHeader));
m.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE);
-
- ret =
- send_with_plugin (&n->id, (const void *) &m, sizeof (m),
- UINT32_MAX /* priority */ ,
- GNUNET_TIME_UNIT_FOREVER_REL, n->session, n->address,
- GNUNET_YES, NULL, NULL);
+ ret = send_with_session (n,
+ (const void *) &m, sizeof (m),
+ UINT32_MAX /* priority */ ,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ NULL, NULL);
n->expect_latency_response = GNUNET_NO;
n->keep_alive_sent = GNUNET_TIME_absolute_get_zero ();
"ATS did not suggested address to connect to peer `%s'\n",
GNUNET_i2s (&n->id));
+ GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# ATS address suggestions failed"), 1,
+ GNUNET_NO);
+
+
disconnect_neighbour (n);
}
callback_cls = NULL;
connect_notify_cb = NULL;
disconnect_notify_cb = NULL;
+ address_change_cb = NULL;
}
struct ContinutionContext
}
+static void
+ats_request (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct NeighbourMapEntry *n = cls;
+ n->ats_request = GNUNET_SCHEDULER_NO_TASK;
+
+ n->ats_suggest =
+ GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT, ats_suggest_cancel,
+ n);
+}
+
+
/**
* We tried to switch addresses with an peer already connected. If it failed,
* we should tell ATS to not use this address anymore (until it is re-validated).
GNUNET_assert ((n->state == S_CONNECTED) || (n->state == S_FAST_RECONNECT));
if (GNUNET_YES != success)
{
-#if DEBUG_TRANSPORT
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Failed to switch connected peer `%s' to address '%s' session %X, asking ATS for new address \n",
- GNUNET_i2s (&n->id), GST_plugins_a2s (n->address), n->session);
-#endif
+ "Failed to switch connected peer `%s' in state %s to address '%s' session %X, asking ATS for new address \n",
+ GNUNET_i2s (&n->id), print_state(n->state), GST_plugins_a2s (cc->address), cc->session);
+
GNUNET_assert (strlen (cc->address->transport_name) > 0);
GNUNET_ATS_address_destroyed (GST_ats, cc->address, cc->session);
if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
+ {
GNUNET_SCHEDULER_cancel (n->ats_suggest);
- n->ats_suggest =
+ n->ats_suggest = GNUNET_SCHEDULER_NO_TASK;
+ }
+
+ if (n->state == S_FAST_RECONNECT)
+ {
+ if (GNUNET_SCHEDULER_NO_TASK == n->ats_request)
+ {
+ /* Throtteled ATS request for fast reconnect */
+ struct GNUNET_TIME_Relative delay = GNUNET_TIME_relative_multiply(FAST_RECONNECT_RATE, n->fast_reconnect_attempts);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Fast reconnect attempt %u failed, delay ATS request for %llu ms\n", n->fast_reconnect_attempts, delay.rel_value);
+ n->ats_request =
+ GNUNET_SCHEDULER_add_delayed (delay,
+ ats_request,
+ n);
+ }
+ }
+ else
+ {
+ /* Immediate ATS request for connected peers */
+ n->ats_suggest =
GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT, ats_suggest_cancel,
n);
- GNUNET_ATS_suggest_address (GST_ats, &n->id);
+ GNUNET_ATS_suggest_address (GST_ats, &n->id);
+ }
GNUNET_HELLO_address_free (cc->address);
GNUNET_free (cc);
return;
case S_CONNECTED:
if (n->address_state == FRESH)
{
- GST_validation_set_address_use (cc->address, cc->session, GNUNET_YES);
+ GST_validation_set_address_use (cc->address, cc->session, GNUNET_YES, __LINE__);
GNUNET_ATS_address_update (GST_ats, cc->address, cc->session, NULL, 0);
+ if (cc->session != n->session)
+ GNUNET_break (0);
GNUNET_ATS_address_in_use (GST_ats, cc->address, cc->session, GNUNET_YES);
n->address_state = USED;
}
if (n->address_state == FRESH)
{
- GST_validation_set_address_use (cc->address, cc->session, GNUNET_YES);
+ GST_validation_set_address_use (cc->address, cc->session, GNUNET_YES, __LINE__);
GNUNET_ATS_address_update (GST_ats, cc->address, cc->session, NULL, 0);
GNUNET_ATS_address_in_use (GST_ats, cc->address, cc->session, GNUNET_YES);
n->address_state = USED;
/**
* For an existing neighbour record, set the active connection to
- * the given address.
+ * 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
* @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_3way (const struct GNUNET_PeerIdentity *peer,
+GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
const struct GNUNET_HELLO_Address
*address,
struct Session *session,
}
/* 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),
+ (address->address_length != 0) ? GST_plugins_a2s (address): "<inbound>",
+ 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;
}
+
+
+ if (n->state == S_FAST_RECONNECT)
+ {
+ /* Throtteled fast reconnect */
+
+ if (NULL == n->fast_reconnect_address)
+ {
+ n->fast_reconnect_address = GNUNET_HELLO_address_copy (address);
+
+ }
+ else if (0 == GNUNET_HELLO_address_cmp(address, n->fast_reconnect_address))
+ {
+ n->fast_reconnect_attempts ++;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "FAST RECONNECT to peer `%s' and address '%s' with identical address attempt %u\n",
+ GNUNET_i2s (&n->id), GST_plugins_a2s (address), n->fast_reconnect_attempts);
+ }
+ }
+ else
+ {
+ n->fast_reconnect_attempts = 0;
+ }
+
/* do not switch addresses just update quotas */
if ((n->state == S_CONNECTED) && (NULL != n->address) &&
(0 == GNUNET_HELLO_address_cmp (address, n->address)) &&
GNUNET_assert (NULL != n->address);
if (n->address_state == USED)
{
- GST_validation_set_address_use (n->address, n->session, GNUNET_NO);
+ GST_validation_set_address_use (n->address, n->session, GNUNET_NO, __LINE__);
GNUNET_ATS_address_in_use (GST_ats, n->address, n->session, GNUNET_NO);
n->address_state = UNUSED;
}
-
}
/* set new address */
GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
&neighbour_timeout_task, n);
-#if TEST_NEW_CODE
+ 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 (papi == NULL)
+ {
+ /* we don't have the plugin for this 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;
+ n->session = NULL;
+ return GNUNET_NO;
+ }
+
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,
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"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_suggest_address (GST_ats, &n->id);
GNUNET_HELLO_address_free (n->address);
n->address = NULL;
+ n->session = NULL;
return GNUNET_NO;
}
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Obtained new session %p for peer `%s' and address '%s'\n",
- n->session, GNUNET_i2s (&n->id), GST_plugins_a2s (n->address));
- }
+
+ 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_ERROR,
- "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;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Using existing session %p for peer `%s' and address '%s'\n",
+ n->session,
+ GNUNET_i2s (&n->id),
+ (address->address_length != 0) ? GST_plugins_a2s (address): "<inbound>");
}
-#else
- n->session = session;
-
- /* dummy */
- if (NULL != NULL) send_with_session(NULL, NULL, NULL, 0, 0, GNUNET_TIME_relative_get_zero(), NULL, NULL);
-#endif
switch (n->state)
{
GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
cc = GNUNET_malloc (sizeof (struct ContinutionContext));
- cc->session = session;
+ cc->session = n->session;
cc->address = GNUNET_HELLO_address_copy (address);
- ret =
- send_with_plugin (peer, (const char *) &connect_msg, msg_len,
- UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL, session,
- address, GNUNET_YES, &send_connect_continuation, cc);
+
+ 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 */
connect_msg.timestamp =
GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
cc = GNUNET_malloc (sizeof (struct ContinutionContext));
- cc->session = session;
+ cc->session = n->session;
cc->address = GNUNET_HELLO_address_copy (address);
-#if TEST_NEW_CODE
- ret = send_with_session(n, n->session,
+
+ ret = send_with_session(n,
(const void *) &connect_msg, msg_len,
UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
&send_connect_ack_continuation,
cc);
-#else
- ret =
- send_with_plugin (&n->id, (const void *) &connect_msg, msg_len,
- UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL, session,
- address, GNUNET_YES, &send_connect_ack_continuation,
- cc);
-#endif
return GNUNET_NO;
case S_CONNECTED:
case S_FAST_RECONNECT:
connect_msg.timestamp =
GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
cc = GNUNET_malloc (sizeof (struct ContinutionContext));
- cc->session = session;
+ cc->session = n->session;
cc->address = GNUNET_HELLO_address_copy (address);
- ret =
- send_with_plugin (peer, (const char *) &connect_msg, msg_len,
- UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL, session,
- address, GNUNET_YES,
- &send_switch_address_continuation, cc);
+ 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,
{
if (n->address_state == USED)
{
- GST_validation_set_address_use (n->address, n->session, GNUNET_NO);
+ GST_validation_set_address_use (n->address, n->session, GNUNET_NO, __LINE__);
GNUNET_ATS_address_in_use (GST_ats, n->address, n->session, GNUNET_NO);
n->address_state = UNUSED;
+
}
}
* neighbours_connected -= 1
* BUT: no disconnect_cb to notify clients about disconnect
*/
-#if DEBUG_TRANSPORT
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying fast reconnect to peer `%s'\n",
GNUNET_i2s (peer));
-#endif
+
GNUNET_assert (neighbours_connected > 0);
change_state (n, S_FAST_RECONNECT);
neighbours_connected--;
/* try QUICKLY to re-establish a connection, reduce timeout! */
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->ats_suggest = GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT,
+ &ats_suggest_cancel,
n);
GNUNET_ATS_suggest_address (GST_ats, peer);
}
m.size = htons (sizeof (struct GNUNET_MessageHeader));
m.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE);
- send_with_plugin (&n->id, (const void *) &m, sizeof (m),
- UINT32_MAX /* priority */ ,
- GNUNET_TIME_UNIT_FOREVER_REL, n->session, n->address,
- GNUNET_YES, NULL, NULL);
+ send_with_session(n,
+ (const void *) &m, sizeof (m),
+ UINT32_MAX,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ NULL, NULL);
}
/**
size_t msg_len;
size_t ret;
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received CONNECT_ACK message from peer `%s'\n",
GNUNET_i2s (peer));
-#endif
if (ntohs (message->size) != sizeof (struct SessionConnectMessage))
{
* We also received an CONNECT message, switched from SENDT to RECV and
* ATS already suggested us an address after a successful blacklist check
*/
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received CONNECT_ACK message from peer `%s' in state `%s'\n",
+ GNUNET_i2s (peer),
+ print_state(n->state));
+
+ if ((n->address != NULL) && (n->state == S_CONNECTED))
+ {
+ /* After fast reconnect: send ACK (ACK) even when we are connected */
+ msg_len = sizeof (msg);
+ msg.size = htons (msg_len);
+ msg.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK);
+
+ ret = send_with_session(n,
+ (const char *) &msg, msg_len,
+ UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
+ NULL, NULL);
+
+ if (ret == GNUNET_SYSERR)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Failed to send SESSION_ACK to `%4s' using address '%s' session %X\n",
+ GNUNET_i2s (&n->id), GST_plugins_a2s (n->address), n->session);
+ return;
+ }
+
if ((n->state != S_CONNECT_SENT) &&
((n->state != S_CONNECT_RECV) && (n->address != NULL)))
{
GNUNET_NO);
return;
}
-
- change_state (n, S_CONNECTED);
+ if (n->state != S_CONNECTED)
+ change_state (n, S_CONNECTED);
if (NULL != session)
{
}
GNUNET_ATS_address_update (GST_ats, address, session, ats, ats_count);
GNUNET_assert (NULL != n->address);
+
if ((n->address_state == FRESH) && (0 == GNUNET_HELLO_address_cmp(address, n->address)))
{
- if (n->session == NULL)
- n->session = session;
- GST_validation_set_address_use (n->address, n->session, GNUNET_YES);
+ GST_validation_set_address_use (n->address, n->session, GNUNET_YES, __LINE__);
GNUNET_ATS_address_in_use (GST_ats, n->address, n->session, GNUNET_YES);
n->address_state = USED;
-
}
GST_neighbours_set_incoming_quota (&n->id, n->bandwidth_in);
msg.size = htons (msg_len);
msg.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK);
- ret =
- send_with_plugin (&n->id, (const char *) &msg, msg_len, UINT32_MAX,
- GNUNET_TIME_UNIT_FOREVER_REL, n->session, n->address,
- GNUNET_YES, NULL, NULL);
+ ret = send_with_session(n,
+ (const char *) &msg, msg_len,
+ UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
+ NULL, NULL);
if (ret == GNUNET_SYSERR)
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
n = lookup_neighbour (peer);
if (NULL == n)
{
- send_disconnect (peer, address, session);
GNUNET_break (0);
return;
}
session, address->transport_name, GNUNET_i2s (peer));
GNUNET_ATS_address_update (GST_ats, address, session, ats, ats_count);
GNUNET_assert (n->address != NULL);
+
if ((n->address_state == FRESH) && (0 == GNUNET_HELLO_address_cmp(address, n->address)))
{
- if (n->session == NULL)
- n->session = session;
- GST_validation_set_address_use (n->address, n->session, GNUNET_YES);
+ GST_validation_set_address_use (n->address, n->session, GNUNET_YES, __LINE__);
GNUNET_ATS_address_in_use (GST_ats, n->address, n->session, GNUNET_YES);
n->address_state = USED;
}
+
neighbours_connected++;
GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# peers connected"), 1,
GNUNET_NO);
GNUNET_ATS_address_update (GST_ats, address, session, ats, ats_count);
n = lookup_neighbour (peer);
- if ((n != NULL) && (S_CONNECTED == n->state))
+ if ((n != NULL) && ((S_CONNECTED == n->state) || (S_FAST_RECONNECT == n->state)))
{
- /* connected peer switches addresses */
+ /* connected peer switches addresses or is trying to do a fast reconnect*/
return;
}
bcc->ats[ats_count].value =
htonl ((uint32_t) GST_neighbour_get_latency (peer).rel_value);
GST_blacklist_test_allowed (peer, address->transport_name,
- handle_connect_blacklist_cont, bcc);
+ &handle_connect_blacklist_cont, bcc);
}