+ * Calculate when we would like to send the next HELLO to this
+ * peer and ask for it.
+ *
+ * @param cls for which peer to schedule the HELLO
+ * @param tc task context
+ */
+static void
+schedule_next_hello (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct Peer *pl = cls;
+ struct FindAdvHelloContext fah;
+ size_t next_want;
+ struct GNUNET_TIME_Relative delay;
+
+ pl->hello_delay_task = GNUNET_SCHEDULER_NO_TASK;
+ if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+ return; /* we're out of here */
+ if (pl->hello_req != NULL)
+ return; /* did not finish sending the previous one */
+ /* find applicable HELLOs */
+ fah.peer = pl;
+ fah.result = NULL;
+ fah.max_size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1;
+ fah.next_adv = GNUNET_TIME_UNIT_FOREVER_REL;
+ GNUNET_CONTAINER_multihashmap_iterate (peers,
+ &find_advertisable_hello,
+ &fah);
+ pl->hello_delay_task
+ = GNUNET_SCHEDULER_add_delayed (fah.next_adv,
+ &schedule_next_hello,
+ pl);
+ if (fah.result == NULL)
+ return;
+ next_want = GNUNET_HELLO_size (fah.result->hello);
+ delay = GNUNET_TIME_absolute_get_remaining (pl->next_hello_allowed);
+ if (delay.rel_value == 0)
+ {
+ /* now! */
+ pl->hello_req = GNUNET_CORE_notify_transmit_ready (handle, 0,
+ GNUNET_CONSTANTS_SERVICE_TIMEOUT,
+ &pl->pid,
+ next_want,
+ &hello_advertising_ready,
+ pl);
+ }
+}
+
+
+/**
+ * Cancel existing requests for sending HELLOs to this peer
+ * and recalculate when we should send HELLOs to it based
+ * on our current state (something changed!).
+ *
+ * @param cls closure, 'struct Peer' to skip, or NULL
+ * @param pid identity of a peer
+ * @param value 'struct Peer*' for the peer
+ * @return GNUNET_YES (always)
+ */
+static int
+reschedule_hellos (void *cls,
+ const GNUNET_HashCode *pid,
+ void *value)
+{
+ struct Peer *peer = value;
+ struct Peer *skip = cls;
+
+ if (skip == peer)
+ return GNUNET_YES;
+ if (! peer->is_connected)
+ return GNUNET_YES;
+ if (peer->hello_req != NULL)
+ {
+ GNUNET_CORE_notify_transmit_ready_cancel (peer->hello_req);
+ peer->hello_req = NULL;
+ }
+ if (peer->hello_delay_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (peer->hello_delay_task);
+ peer->hello_delay_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ peer->hello_delay_task
+ = GNUNET_SCHEDULER_add_now (&schedule_next_hello,
+ peer);
+ return GNUNET_YES;
+}
+
+
+/**
+ * Method called whenever a peer connects.