#include "gnunet_util_lib.h"
+/**
+ * Minimum required delay between calls to GNUNET_TRANSPORT_try_connect.
+ */
+#define MAX_CONNECT_FREQUENCY_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250)
+
/**
* For how long do we blacklist a peer after a failed connection
* attempt? This is the baseline factor which is then multiplied by
*/
GNUNET_SCHEDULER_TaskIdentifier hello_delay_task;
+ /**
+ * Task for issuing GNUNET_TRANSPORT_try_connect for this peer.
+ */
+ GNUNET_SCHEDULER_TaskIdentifier attempt_connect_task;
+
/**
* ID of task we use to clear peers from the greylist.
*/
*/
static struct GNUNET_TRANSPORT_Blacklist *blacklist;
+/**
+ * When can we next ask transport to create a connection?
+ */
+static struct GNUNET_TIME_Absolute next_connect_attempt;
+
/**
* Task scheduled to try to add peers.
*/
GNUNET_CORE_notify_transmit_ready_cancel (pos->hello_req);
if (pos->hello_delay_task != GNUNET_SCHEDULER_NO_TASK)
GNUNET_SCHEDULER_cancel (pos->hello_delay_task);
+ if (pos->attempt_connect_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (pos->hello_delay_task);
if (pos->greylist_clean_task != GNUNET_SCHEDULER_NO_TASK)
GNUNET_SCHEDULER_cancel (pos->greylist_clean_task);
GNUNET_free_non_null (pos->hello);
}
+/**
+ * Try to connect to the specified peer.
+ *
+ * @param pos peer to connect to
+ */
+static void
+do_attempt_connect (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct Peer *pos = cls;
+ struct GNUNET_TIME_Relative delay;
+
+ pos->attempt_connect_task = GNUNET_SCHEDULER_NO_TASK;
+ if (GNUNET_YES == pos->is_connected)
+ return;
+ delay = GNUNET_TIME_absolute_get_remaining (next_connect_attempt);
+ if (delay.rel_value > 0)
+ {
+ pos->attempt_connect_task = GNUNET_SCHEDULER_add_delayed (delay,
+ &do_attempt_connect,
+ pos);
+ return;
+ }
+ next_connect_attempt = GNUNET_TIME_relative_to_absolute (MAX_CONNECT_FREQUENCY_DELAY);
+ attempt_connect (pos);
+}
+
+
+/**
+ * Schedule a task to try to connect to the specified peer.
+ *
+ * @param pos peer to connect to
+ */
+static void
+schedule_attempt_connect (struct Peer *pos)
+{
+ if (GNUNET_SCHEDULER_NO_TASK != pos->attempt_connect_task)
+ return;
+ pos->attempt_connect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (next_connect_attempt),
+ &do_attempt_connect,
+ pos);
+}
+
+
/**
* Discard peer entries for greylisted peers
* where the greylisting has expired.
rem = GNUNET_TIME_absolute_get_remaining (pos->greylisted_until);
if (rem.rel_value == 0)
{
- attempt_connect (pos);
+ schedule_attempt_connect (pos);
}
else
{
{
struct Peer *pos = value;
- attempt_connect (pos);
+ schedule_attempt_connect (pos);
return GNUNET_YES;
}
GNUNET_CONTAINER_multihashmap_iterate (peers, &try_add_peers, NULL);
}
+
/**
* Method called whenever a peer disconnects.
*
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Considering connecting to peer `%s'\n",
GNUNET_i2s (peer));
- attempt_connect (pos);
+ schedule_attempt_connect (pos);
}