static void try_transmission_to_peer (struct NeighbourList *neighbour);
+/**
+ * The peer specified by the given neighbour has timed-out. Update
+ * our state and do the necessary notifications. Also notifies
+ * our clients that the neighbour is now officially gone.
+ *
+ * @param n the neighbour list entry for the peer
+ */
+static void
+disconnect_neighbour (struct NeighbourList *n);
+
+
/**
* Function called by the GNUNET_TRANSPORT_TransmitFunction
* upon "completion" of a send request. This tells the API
GNUNET_free (mq);
/* one plugin just became ready again, try transmitting
another message (if available) */
- try_transmission_to_peer (n);
+ if (result == GNUNET_OK)
+ try_transmission_to_peer (n);
+ else
+ disconnect_neighbour (n);
}
}
+/**
+ * FIXME: document.
+ */
struct GeneratorContext
{
struct TransportPlugin *plug_pos;
};
+/**
+ * FIXME: document.
+ */
static size_t
address_generator (void *cls, size_t max, void *buf)
{
}
+/**
+ * FIXME: document.
+ */
struct LookupHelloContext
{
GNUNET_TRANSPORT_AddressCallback iterator;
};
+/**
+ * FIXME: document.
+ */
static int
lookup_address_callback (void *cls,
const char *tname,
}
+/**
+ * FIXME: document.
+ */
static void
lookup_hello_callback (void *cls,
const struct GNUNET_PeerIdentity *peer,
}
-
/**
* The peer specified by the given neighbour has timed-out. Update
* our state and do the necessary notifications. Also notifies
#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
- "Disconnecting from neighbour\n");
+ "Disconnecting from `%4s'\n",
+ GNUNET_i2s(&n->id));
#endif
/* remove n from neighbours list */
nprev = NULL;
#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
- "Neighbour has timed out!\n");
+ "Neighbour `%4s' has timed out!\n",
+ GNUNET_i2s(&n->id));
#endif
n->timeout_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
disconnect_neighbour (n);
}
-
/**
* Create a fresh entry in our neighbour list for the given peer.
* Will try to transmit our current HELLO to the new neighbour. Also
#endif
if (NULL == find_neighbour (&tcm->peer))
setup_new_neighbour (&tcm->peer);
+#if DEBUG_TRANSPORT
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Client asked to connect to `%4s', but connection already exists\n",
+ "TRY_CONNECT",
+ GNUNET_i2s (&tcm->peer));
+#endif
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
*/
#define OFFER_HELLO_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
+/**
+ * After how long do we give automatically retry an unsuccessful
+ * CONNECT request?
+ */
+#define CONNECT_RETRY_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 750)
+
/**
* How long should ARM wait when starting up the
* transport service before reporting back?
}
+/**
+ * Schedule a request to connect to the given
+ * neighbour (and if successful, add the specified
+ * handle to the wait list).
+ *
+ * @param th handle for a request to transmit once we
+ * have connected
+ */
+static void
+try_connect (struct GNUNET_TRANSPORT_TransmitHandle *th);
+
+
/**
* Called when our transmit request timed out before any transport
* reported success connecting to the desired peer or before the
GNUNET_NO,
GNUNET_SCHEDULER_PRIORITY_KEEP,
GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
- GNUNET_TIME_absolute_get_remaining
- (th->timeout), &transmit_timeout, th);
+ GNUNET_TIME_absolute_get_remaining
+ (th->timeout),
+ &transmit_timeout, th);
insert_transmit_handle (&h->connect_wait_head, th);
return sizeof (struct TryConnectMessage);
}
/**
- * Remove neighbour from our list
+ * Task for delayed attempts to reconnect to a peer.
+ *
+ * @param cls must be a transmit handle that determines the peer
+ * to which we will try to connect
+ * @param tc scheduler information about why we were triggered (not used)
+ */
+static void
+try_connect_task (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GNUNET_TRANSPORT_TransmitHandle *th = cls;
+
+ th->notify_delay_task
+ = GNUNET_SCHEDULER_add_delayed (th->handle->sched,
+ GNUNET_NO,
+ GNUNET_SCHEDULER_PRIORITY_KEEP,
+ GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
+ GNUNET_TIME_absolute_get_remaining
+ (th->timeout), &transmit_timeout, th);
+ try_connect (th);
+}
+
+
+/**
+ * Remove neighbour from our list. Will automatically
+ * trigger a re-connect attempt if we have messages pending
+ * for this peer.
+ *
+ * @param h our state
+ * @param peer the peer to remove
*/
static void
remove_neighbour (struct GNUNET_TRANSPORT_Handle *h,
prev = NULL;
pos = h->neighbours;
while ((pos != NULL) &&
- (0 != memcmp (peer, &pos->id, sizeof (struct GNUNET_PeerIdentity))))
+ (0 != memcmp (peer,
+ &pos->id,
+ sizeof (struct GNUNET_PeerIdentity))))
{
prev = pos;
pos = pos->next;
pos->transmit_handle = NULL;
th->neighbour = NULL;
remove_from_any_list (th);
- try_connect (th);
+ if (GNUNET_TIME_absolute_get_remaining (th->timeout).value > CONNECT_RETRY_TIMEOUT.value)
+ {
+ /* signal error */
+ GNUNET_SCHEDULER_cancel (h->sched,
+ th->notify_delay_task);
+ transmit_timeout (th, NULL);
+ }
+ else
+ {
+ /* try again in a bit */
+ GNUNET_SCHEDULER_cancel (h->sched,
+ th->notify_delay_task);
+ th->notify_delay_task
+ = GNUNET_SCHEDULER_add_delayed (h->sched,
+ GNUNET_NO,
+ GNUNET_SCHEDULER_PRIORITY_KEEP,
+ GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
+ CONNECT_RETRY_TIMEOUT,
+ &try_connect_task,
+ th);
+ }
}
if (h->nc_cb != NULL)
h->nd_cb (h->cls, peer);
"Receiving `%s' message, transmission %s.\n", "SEND_OK",
ntohl(okm->success) == GNUNET_OK ? "succeeded" : "failed");
#endif
+ /* FIXME: need to check status code and change action accordingly,
+ especially if the error was for CONNECT */
n = find_neighbour (h, &okm->peer);
GNUNET_assert (n != NULL);
n->transmit_ok = GNUNET_YES;