+ * Discard peer entries for greylisted peers
+ * where the greylisting has expired.
+ *
+ * @param cls 'struct Peer' to greylist
+ * @param tc scheduler context
+ */
+static void
+remove_from_greylist (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct Peer *pos = cls;
+ struct GNUNET_TIME_Relative rem;
+
+ pos->greylist_clean_task = GNUNET_SCHEDULER_NO_TASK;
+ rem = GNUNET_TIME_absolute_get_remaining (pos->greylisted_until);
+ if (rem.rel_value == 0)
+ {
+ attempt_connect (pos);
+ }
+ else
+ {
+ pos->greylist_clean_task
+ = GNUNET_SCHEDULER_add_delayed (rem,
+ &remove_from_greylist,
+ pos);
+ }
+ if ( (GNUNET_NO == pos->is_friend) &&
+ (GNUNET_NO == pos->is_connected) )
+ {
+ free_peer (NULL, &pos->pid.hashPubKey, pos);
+ return;
+ }
+}
+
+
+/**
+ * Create a new entry in the peer list.
+ *
+ * @param peer identity of the new entry
+ * @param hello hello message, can be NULL
+ * @param is_friend is the new entry for a friend?
+ * @return the new entry
+ */
+static struct Peer *
+make_peer (const struct
+ GNUNET_PeerIdentity * peer,
+ const struct GNUNET_HELLO_Message *hello,
+ int is_friend)
+{
+ struct Peer *ret;
+
+ ret = GNUNET_malloc (sizeof (struct Peer));
+ ret->pid = *peer;
+ ret->is_friend = is_friend;
+ if (hello != NULL)
+ {
+ ret->hello = GNUNET_malloc (GNUNET_HELLO_size (hello));
+ memcpy (ret->hello, hello,
+ GNUNET_HELLO_size (hello));
+ }
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_put (peers,
+ &peer->hashPubKey,
+ ret,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+ return ret;
+}
+
+
+/**
+ * Setup bloom filter for the given peer entry.
+ *
+ * @param peer entry to initialize
+ */
+static void
+setup_filter (struct Peer *peer)
+{
+ /* 2^{-5} chance of not sending a HELLO to a peer is
+ acceptably small (if the filter is 50% full);
+ 64 bytes of memory are small compared to the rest
+ of the data structure and would only really become
+ "useless" once a HELLO has been passed on to ~100
+ other peers, which is likely more than enough in
+ any case; hence 64, 5 as bloomfilter parameters. */
+ peer->filter = GNUNET_CONTAINER_bloomfilter_load (NULL, 64, 5);
+ peer->filter_expiration = GNUNET_TIME_relative_to_absolute (HELLO_ADVERTISEMENT_MIN_REPEAT_FREQUENCY);
+ /* never send a peer its own HELLO */
+ GNUNET_CONTAINER_bloomfilter_add (peer->filter, &peer->pid.hashPubKey);
+}
+
+
+/**
+ * Function to fill send buffer with HELLO.
+ *
+ * @param cls 'struct Peer' of the target peer
+ * @param size number of bytes available in buf
+ * @param buf where the callee should write the message
+ * @return number of bytes written to buf
+ */
+static size_t
+hello_advertising_ready (void *cls,
+ size_t size,
+ void *buf);
+
+
+
+
+/**
+ * Closure for 'find_advertisable_hello'.
+ */
+struct FindAdvHelloContext {
+
+ /**
+ * Peer we want to advertise to.
+ */
+ struct Peer *peer;
+
+ /**
+ * Where to store the result (peer selected for advertising).
+ */
+ struct Peer *result;
+
+ /**
+ * Maximum HELLO size we can use right now.
+ */
+ size_t max_size;
+
+ struct GNUNET_TIME_Relative next_adv;
+};
+
+
+/**
+ * Find a peer that would be reasonable for advertising.
+ *
+ * @param cls closure
+ * @param pid identity of a peer
+ * @param value 'struct Peer*' for the peer we are considering
+ * @return GNUNET_YES (continue iteration)