retry faster
[oweals/gnunet.git] / src / topology / gnunet-daemon-topology.c
index 3aa518fa1797f3683880042409fd27b90dd99859..08b1ba1c3c0effb852fa29cbd34b8880afc645ca 100644 (file)
@@ -4,7 +4,7 @@
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
 #include "gnunet_util_lib.h"
 
 
 #include "gnunet_util_lib.h"
 
 
-#define DEBUG_TOPOLOGY GNUNET_NO
+#define DEBUG_TOPOLOGY GNUNET_YES
 
 /**
  * For how long do we blacklist a peer after a failed connection
  * attempt?
  */
 
 /**
  * For how long do we blacklist a peer after a failed connection
  * attempt?
  */
-#define GREYLIST_AFTER_ATTEMPT GNUNET_TIME_UNIT_HOURS
+#define GREYLIST_AFTER_ATTEMPT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
 
 /**
  * For how long do we blacklist a friend after a failed connection
  * attempt?
  */
 
 /**
  * For how long do we blacklist a friend after a failed connection
  * attempt?
  */
-#define GREYLIST_AFTER_ATTEMPT_FRIEND GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
+#define GREYLIST_AFTER_ATTEMPT_FRIEND GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
+
+/**
+ * For how long do we blacklist anyone under any cirumstances after a failed connection
+ * attempt?
+ */
+#define GREYLIST_AFTER_ATTEMPT_MIN GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
+
+/**
+ * For how long do we blacklist anyone under any cirumstances after a failed connection
+ * attempt?
+ */
+#define GREYLIST_AFTER_ATTEMPT_MAX GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 1)
 
 /**
  * How often do we at most advertise any HELLO to a peer?
 
 /**
  * How often do we at most advertise any HELLO to a peer?
@@ -93,12 +105,6 @@ struct Peer
    */
   struct GNUNET_CONTAINER_BloomFilter *filter;
 
    */
   struct GNUNET_CONTAINER_BloomFilter *filter;
 
-  /**
-   * Our request handle for *whitelisting* this peer (NULL if
-   * no whitelisting request is pending).
-   */
-  struct GNUNET_TRANSPORT_BlacklistRequest *wh;
-
   /**
    * Until what time should we not try to connect again
    * to this peer?
   /**
    * Until what time should we not try to connect again
    * to this peer?
@@ -126,6 +132,11 @@ struct Peer
    */
   GNUNET_SCHEDULER_TaskIdentifier greylist_clean_task;
 
    */
   GNUNET_SCHEDULER_TaskIdentifier greylist_clean_task;
 
+  /**
+   * How often have we tried so far?
+   */
+  unsigned int connect_attempts;
+
   /**
    * Is this peer listed here because he is a friend?
    */
   /**
    * Is this peer listed here because he is a friend?
    */
@@ -136,39 +147,6 @@ struct Peer
    */
   int is_connected;
 
    */
   int is_connected;
 
-  /**
-   * Are we currently blocking this peer (via blacklist)?
-   */
-  int is_blocked;
-
-};
-
-
-/**
- * Entry in linked list of active 'disconnect' requests that we have issued.
- */
-struct DisconnectList
-{
-  /**
-   * This is a doubly-linked list.
-   */
-  struct DisconnectList *next;
-
-  /**
-   * This is a doubly-linked list.
-   */
-  struct DisconnectList *prev;
-  
-  /**
-   * Our request handle.
-   */
-  struct GNUNET_TRANSPORT_BlacklistRequest *rh;
-  
-  /**
-   * Peer we tried to disconnect.
-   */
-  struct GNUNET_PeerIdentity peer;
-
 };
 
 
 };
 
 
@@ -178,11 +156,6 @@ struct DisconnectList
  */
 static struct GNUNET_PEERINFO_NotifyContext *peerinfo_notify;
 
  */
 static struct GNUNET_PEERINFO_NotifyContext *peerinfo_notify;
 
-/**
- * Our scheduler.
- */
-static struct GNUNET_SCHEDULER_Handle *sched;
-
 /**
  * Our configuration.
  */
 /**
  * Our configuration.
  */
@@ -215,6 +188,11 @@ static struct GNUNET_CONTAINER_MultiHashMap *peers;
  */
 static struct GNUNET_STATISTICS_Handle *stats;
 
  */
 static struct GNUNET_STATISTICS_Handle *stats;
 
+/**
+ * Blacklist (NULL if we have none).
+ */
+static struct GNUNET_TRANSPORT_Blacklist *blacklist;
+
 /**
  * Flag to disallow non-friend connections (pure F2F mode).
  */
 /**
  * Flag to disallow non-friend connections (pure F2F mode).
  */
@@ -246,119 +224,31 @@ static unsigned int friend_count;
  */
 static int autoconnect;
 
  */
 static int autoconnect;
 
-/**
- * Head of doubly-linked list of active 'disconnect' requests that we have issued.
- */
-static struct DisconnectList *disconnect_head;
-
-/**
- * Head of doubly-linked list of active 'disconnect' requests that we have issued.
- */
-static struct DisconnectList *disconnect_tail;
-
 
 /**
 
 /**
- * Function called once our request to 'disconnect' a peer
- * has completed.
+ * Function that decides if a connection is acceptable or not.  
+ * If we have a blacklist, only friends are allowed, so the check
+ * is rather simple.
  *
  *
- * @param cls our 'struct DisconnectList'
- * @param tc unused
+ * @param cls closure
+ * @param pid peer to approve or disapproave
+ * @return GNUNET_OK if the connection is allowed
  */
  */
-static void
-disconnect_done (void *cls,
-                const struct GNUNET_SCHEDULER_TaskContext *tc)
+static int
+blacklist_check (void *cls,
+                const struct GNUNET_PeerIdentity *pid)
 {
 {
-  struct DisconnectList *dl = cls;
+  struct Peer *pos;
 
 
+  pos = GNUNET_CONTAINER_multihashmap_get (peers, &pid->hashPubKey);
+  if ( (pos != NULL) &&
+       (pos->is_friend == GNUNET_YES) )
+    return GNUNET_OK;
   GNUNET_STATISTICS_update (stats,
                            gettext_noop ("# peers blacklisted"),
                            1,
                            GNUNET_NO);
   GNUNET_STATISTICS_update (stats,
                            gettext_noop ("# peers blacklisted"),
                            1,
                            GNUNET_NO);
-  GNUNET_CONTAINER_DLL_remove (disconnect_head,
-                              disconnect_tail,
-                              dl);
-  GNUNET_free (dl);
-}
-
-
-/**
- * Force a disconnect from the specified peer. 
- *
- * @param pl peer to disconnect
- */
-static void
-force_disconnect (struct Peer *pl)
-{
-  const struct GNUNET_PeerIdentity *peer = &pl->pid;
-  struct DisconnectList *dl;
-
-  if (NULL != pl->wh)
-    {
-      GNUNET_TRANSPORT_blacklist_cancel (pl->wh);
-      pl->wh = NULL;
-    }
-  pl->is_blocked = GNUNET_YES;
-  dl = GNUNET_malloc (sizeof (struct DisconnectList));
-  dl->peer = *peer;
-  GNUNET_CONTAINER_DLL_insert (disconnect_head,
-                              disconnect_tail,
-                              dl);
-  dl->rh = GNUNET_TRANSPORT_blacklist (sched, cfg,                                             
-                                      peer,
-                                      GNUNET_TIME_UNIT_FOREVER_REL,
-                                      GNUNET_TIME_UNIT_FOREVER_REL,
-                                      &disconnect_done,
-                                      dl);
-}
-
-
-
-/**
- * Function called once our request to 'whitelist' a peer
- * has completed.
- *
- * @param cls our 'struct Peer'
- * @param tc unused
- */
-static void
-whitelist_done (void *cls,
-               const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct Peer *pl = cls;
-
-  pl->wh = NULL;
-  GNUNET_STATISTICS_update (stats,
-                           gettext_noop ("# peers blacklisted"),
-                           -1,
-                           GNUNET_NO);
-}
-
-
-/**
- * Whitelist the given peer (if it was blacklisted before).
- *
- * @param cls closure (not used)
- * @param pid identity of the peer
- * @param value peer to free
- * @return GNUNET_YES (always: continue to iterate)
- */
-static int
-whitelist_peer (void *cls,
-               const GNUNET_HashCode *pid,
-               void *value)
-{
-  struct Peer *pl = value;
-
-  if (! pl->is_blocked)
-    return GNUNET_YES;
-  pl->wh = GNUNET_TRANSPORT_blacklist (sched, cfg,                                             
-                                      &pl->pid,
-                                      GNUNET_TIME_UNIT_ZERO,
-                                      GNUNET_TIME_UNIT_FOREVER_REL,
-                                      &whitelist_done,
-                                      pl);
-  pl->is_blocked = GNUNET_NO;
-  return GNUNET_YES;
+  return GNUNET_SYSERR;
 }
 
 
 }
 
 
@@ -369,22 +259,11 @@ whitelist_peer (void *cls,
 static void
 whitelist_peers ()
 {
 static void
 whitelist_peers ()
 {
-  struct DisconnectList *dl;
-
-  /* first, cancel all blacklisting requests */
-  while (NULL != (dl = disconnect_head))
+  if (blacklist != NULL)
     {
     {
-      GNUNET_CONTAINER_DLL_remove (disconnect_head,
-                                  disconnect_tail,
-                                  dl);
-      GNUNET_TRANSPORT_blacklist_cancel (dl->rh);
-      GNUNET_free (dl);
+      GNUNET_TRANSPORT_blacklist_cancel (blacklist);
+      blacklist = NULL;
     }
     }
-  /* then, specifically whitelist all peers that we
-     know to have blacklisted */
-  GNUNET_CONTAINER_multihashmap_iterate (peers,
-                                        &whitelist_peer,
-                                        NULL);
 }
 
 
 }
 
 
@@ -392,11 +271,11 @@ whitelist_peers ()
  * Function called by core when our attempt to connect succeeded.
  *
  * @param cls the 'struct Peer' for which we issued the connect request
  * Function called by core when our attempt to connect succeeded.
  *
  * @param cls the 'struct Peer' for which we issued the connect request
- * @param tc scheduler context
+ * @param success was the request transmitted
  */
 static void
 connect_completed_callback (void *cls,
  */
 static void
 connect_completed_callback (void *cls,
-                           const struct GNUNET_SCHEDULER_TaskContext *tc)
+                           int success)
 {
   struct Peer *pos = cls;
 
 {
   struct Peer *pos = cls;
 
@@ -460,13 +339,12 @@ free_peer (void *cls,
                                                      pos));
   if (pos->hello_req != NULL)
     GNUNET_CORE_notify_transmit_ready_cancel (pos->hello_req);
                                                      pos));
   if (pos->hello_req != NULL)
     GNUNET_CORE_notify_transmit_ready_cancel (pos->hello_req);
-  if (pos->wh != NULL)
-    GNUNET_TRANSPORT_blacklist_cancel (pos->wh);
   if (pos->connect_req != NULL)
     GNUNET_CORE_peer_request_connect_cancel (pos->connect_req);              
   if (pos->hello_delay_task != GNUNET_SCHEDULER_NO_TASK)
   if (pos->connect_req != NULL)
     GNUNET_CORE_peer_request_connect_cancel (pos->connect_req);              
   if (pos->hello_delay_task != GNUNET_SCHEDULER_NO_TASK)
-    GNUNET_SCHEDULER_cancel (sched,
-                            pos->hello_delay_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);   
   if (pos->filter != NULL)
     GNUNET_CONTAINER_bloomfilter_free (pos->filter);
   GNUNET_free_non_null (pos->hello);   
   if (pos->filter != NULL)
     GNUNET_CONTAINER_bloomfilter_free (pos->filter);
@@ -504,22 +382,26 @@ attempt_connect (struct Peer *pos)
     return;
   if (GNUNET_OK != is_connection_allowed (pos))
     return;
     return;
   if (GNUNET_OK != is_connection_allowed (pos))
     return;
-  if (GNUNET_YES == pos->is_blocked)
-    return;
-  if (GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).value > 0)
+  if (GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).rel_value > 0)
     return;
   if (GNUNET_YES == pos->is_friend)
     rem = GREYLIST_AFTER_ATTEMPT_FRIEND;
   else
     rem = GREYLIST_AFTER_ATTEMPT;
     return;
   if (GNUNET_YES == pos->is_friend)
     rem = GREYLIST_AFTER_ATTEMPT_FRIEND;
   else
     rem = GREYLIST_AFTER_ATTEMPT;
-  /* FIXME: do exponential back-off? */
+  rem = GNUNET_TIME_relative_multiply (rem, connection_count);
+  rem = GNUNET_TIME_relative_divide (rem, target_connection_count);
+  if (pos->connect_attempts > 30)
+    pos->connect_attempts = 30;
+  rem = GNUNET_TIME_relative_multiply (rem, 1 << (++pos->connect_attempts));
+  rem = GNUNET_TIME_relative_max (rem,
+                                 GREYLIST_AFTER_ATTEMPT_MIN);
+  rem = GNUNET_TIME_relative_min (rem,
+                                 GREYLIST_AFTER_ATTEMPT_MAX);
   pos->greylisted_until = GNUNET_TIME_relative_to_absolute (rem);
   if (pos->greylist_clean_task != GNUNET_SCHEDULER_NO_TASK)
   pos->greylisted_until = GNUNET_TIME_relative_to_absolute (rem);
   if (pos->greylist_clean_task != GNUNET_SCHEDULER_NO_TASK)
-    GNUNET_SCHEDULER_cancel (sched,
-                            pos->greylist_clean_task);
+    GNUNET_SCHEDULER_cancel (pos->greylist_clean_task);
   pos->greylist_clean_task 
   pos->greylist_clean_task 
-    = GNUNET_SCHEDULER_add_delayed (sched,
-                                   rem,
+    = GNUNET_SCHEDULER_add_delayed (rem,
                                    &remove_from_greylist,
                                    pos);
 #if DEBUG_TOPOLOGY
                                    &remove_from_greylist,
                                    pos);
 #if DEBUG_TOPOLOGY
@@ -531,7 +413,7 @@ attempt_connect (struct Peer *pos)
                            gettext_noop ("# connect requests issued to core"),
                            1,
                            GNUNET_NO);
                            gettext_noop ("# connect requests issued to core"),
                            1,
                            GNUNET_NO);
-  pos->connect_req = GNUNET_CORE_peer_request_connect (sched, cfg,
+  pos->connect_req = GNUNET_CORE_peer_request_connect (handle,
                                                       GNUNET_TIME_UNIT_MINUTES,
                                                       &pos->pid,
                                                       &connect_completed_callback,
                                                       GNUNET_TIME_UNIT_MINUTES,
                                                       &pos->pid,
                                                       &connect_completed_callback,
@@ -555,20 +437,18 @@ remove_from_greylist (void *cls,
 
   pos->greylist_clean_task = GNUNET_SCHEDULER_NO_TASK;
   rem = GNUNET_TIME_absolute_get_remaining (pos->greylisted_until);
 
   pos->greylist_clean_task = GNUNET_SCHEDULER_NO_TASK;
   rem = GNUNET_TIME_absolute_get_remaining (pos->greylisted_until);
-  if (rem.value == 0)
+  if (rem.rel_value == 0)
     {
       attempt_connect (pos);
     }
   else
     {
       pos->greylist_clean_task 
     {
       attempt_connect (pos);
     }
   else
     {
       pos->greylist_clean_task 
-       = GNUNET_SCHEDULER_add_delayed (sched,
-                                       rem,
+       = GNUNET_SCHEDULER_add_delayed (rem,
                                        &remove_from_greylist,
                                        pos);
     }
   if ( (GNUNET_NO == pos->is_friend) &&
                                        &remove_from_greylist,
                                        pos);
     }
   if ( (GNUNET_NO == pos->is_friend) &&
-       (GNUNET_NO == pos->is_blocked) &&
        (GNUNET_NO == pos->is_connected) )
     {
       free_peer (NULL, &pos->pid.hashPubKey, pos);
        (GNUNET_NO == pos->is_connected) )
     {
       free_peer (NULL, &pos->pid.hashPubKey, pos);
@@ -602,10 +482,11 @@ make_peer (const struct
       memcpy (ret->hello, hello,
              GNUNET_HELLO_size (hello));
     }
       memcpy (ret->hello, hello,
              GNUNET_HELLO_size (hello));
     }
-  GNUNET_CONTAINER_multihashmap_put (peers,
-                                    &peer->hashPubKey,
-                                    ret,
-                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+  GNUNET_break (GNUNET_OK ==
+               GNUNET_CONTAINER_multihashmap_put (peers,
+                                                  &peer->hashPubKey,
+                                                  ret,
+                                                  GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
   return ret;
 }
 
   return ret;
 }
 
@@ -695,7 +576,7 @@ find_advertisable_hello (void *cls,
   if (pos->hello == NULL)
     return GNUNET_YES;
   rst_time = GNUNET_TIME_absolute_get_remaining (pos->filter_expiration);
   if (pos->hello == NULL)
     return GNUNET_YES;
   rst_time = GNUNET_TIME_absolute_get_remaining (pos->filter_expiration);
-  if (0 == rst_time.value)
+  if (0 == rst_time.rel_value)
     {
       /* time to discard... */
       GNUNET_CONTAINER_bloomfilter_free (pos->filter);
     {
       /* time to discard... */
       GNUNET_CONTAINER_bloomfilter_free (pos->filter);
@@ -738,21 +619,20 @@ schedule_next_hello (void *cls,
   /* find applicable HELLOs */
   fah.peer = pl;
   fah.result = NULL;
   /* find applicable HELLOs */
   fah.peer = pl;
   fah.result = NULL;
-  fah.max_size = GNUNET_SERVER_MAX_MESSAGE_SIZE;
+  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 
   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 (sched,
-                                   fah.next_adv,
+    = 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);
                                    &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.value == 0)
+  if (delay.rel_value == 0)
     {
       /* now! */
       pl->hello_req = GNUNET_CORE_notify_transmit_ready (handle, 0,
     {
       /* now! */
       pl->hello_req = GNUNET_CORE_notify_transmit_ready (handle, 0,
@@ -761,7 +641,6 @@ schedule_next_hello (void *cls,
                                                         next_want,
                                                         &hello_advertising_ready,
                                                         pl);
                                                         next_want,
                                                         &hello_advertising_ready,
                                                         pl);
-      return;
     }
 }
 
     }
 }
 
@@ -795,13 +674,11 @@ reschedule_hellos (void *cls,
     }
   if (peer->hello_delay_task != GNUNET_SCHEDULER_NO_TASK)
     {
     }
   if (peer->hello_delay_task != GNUNET_SCHEDULER_NO_TASK)
     {
-      GNUNET_SCHEDULER_cancel (sched,
-                              peer->hello_delay_task);
+      GNUNET_SCHEDULER_cancel (peer->hello_delay_task);
       peer->hello_delay_task = GNUNET_SCHEDULER_NO_TASK;
     }
   peer->hello_delay_task 
       peer->hello_delay_task = GNUNET_SCHEDULER_NO_TASK;
     }
   peer->hello_delay_task 
-    = GNUNET_SCHEDULER_add_now (sched,
-                               &schedule_next_hello,
+    = GNUNET_SCHEDULER_add_now (&schedule_next_hello,
                                peer);
   return GNUNET_YES;
 }
                                peer);
   return GNUNET_YES;
 }
@@ -812,15 +689,13 @@ reschedule_hellos (void *cls,
  *
  * @param cls closure
  * @param peer peer identity this notification is about
  *
  * @param cls closure
  * @param peer peer identity this notification is about
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other' 
+ * @param atsi performance data
  */
 static void 
 connect_notify (void *cls,
                const struct
                GNUNET_PeerIdentity * peer,
  */
 static void 
 connect_notify (void *cls,
                const struct
                GNUNET_PeerIdentity * peer,
-               struct GNUNET_TIME_Relative latency,
-               uint32_t distance)
+               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct Peer *pos;
 
 {
   struct Peer *pos;
 
@@ -829,6 +704,9 @@ connect_notify (void *cls,
              "Core told us that we are connecting to `%s'\n",
              GNUNET_i2s (peer));
 #endif
              "Core told us that we are connecting to `%s'\n",
              GNUNET_i2s (peer));
 #endif
+  if (0 == memcmp(&my_identity, peer, sizeof(struct GNUNET_PeerIdentity)))
+    return;
+
   connection_count++;
   GNUNET_STATISTICS_set (stats,
                         gettext_noop ("# peers connected"),
   connection_count++;
   GNUNET_STATISTICS_set (stats,
                         gettext_noop ("# peers connected"),
@@ -838,25 +716,15 @@ connect_notify (void *cls,
   if (pos == NULL)    
     {
       pos = make_peer (peer, NULL, GNUNET_NO);
   if (pos == NULL)    
     {
       pos = make_peer (peer, NULL, GNUNET_NO);
-      if (GNUNET_OK != is_connection_allowed (pos))
-       {
-         GNUNET_assert (pos->is_friend == GNUNET_NO);
-         pos->is_connected = GNUNET_YES;
-#if DEBUG_TOPOLOGY
-         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                     "Connection to `%s' is forbidden, forcing disconnect!\n",
-                     GNUNET_i2s (peer));
-#endif       
-         force_disconnect (pos);
-         return;
-       }
+      GNUNET_break (GNUNET_OK == is_connection_allowed (pos));
     }
   else
     {
       GNUNET_assert (GNUNET_NO == pos->is_connected);
     }
   else
     {
       GNUNET_assert (GNUNET_NO == pos->is_connected);
-      pos->greylisted_until.value = 0; /* remove greylisting */
+      pos->greylisted_until.abs_value = 0; /* remove greylisting */
     }
   pos->is_connected = GNUNET_YES;
     }
   pos->is_connected = GNUNET_YES;
+  pos->connect_attempts = 0; /* re-set back-off factor */
   if (pos->is_friend)
     {
       if ( (friend_count == minimum_friend_count - 1) &&
   if (pos->is_friend)
     {
       if ( (friend_count == minimum_friend_count - 1) &&
@@ -865,42 +733,13 @@ connect_notify (void *cls,
       friend_count++;
       GNUNET_STATISTICS_set (stats,
                             gettext_noop ("# friends connected"),
       friend_count++;
       GNUNET_STATISTICS_set (stats,
                             gettext_noop ("# friends connected"),
-                            connection_count,
+                            friend_count,
                             GNUNET_NO);
     }
   reschedule_hellos (NULL, &peer->hashPubKey, pos);
 }
 
 
                             GNUNET_NO);
     }
   reschedule_hellos (NULL, &peer->hashPubKey, pos);
 }
 
 
-/**
- * Disconnect from all non-friends (we're below quota).
- *
- * @param cls closure, not used
- * @param pid identity of a peer
- * @param value 'struct Peer*' for the peer
- * @return GNUNET_YES (continue to iterate)
- */
-static int
-drop_non_friends (void *cls,
-                 const GNUNET_HashCode *pid,
-                 void *value)
-{
-  struct Peer *pos = value;
-
-  if ( (GNUNET_NO == pos->is_friend) &&
-       (GNUNET_YES == pos->is_connected) )
-    {
-#if DEBUG_TOPOLOGY
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Connection to `%s' is not from a friend, forcing disconnect!\n",
-                 GNUNET_i2s (&pos->pid));
-#endif       
-      force_disconnect (pos);
-    }
-  return GNUNET_YES;
-}
-
-
 /**
  * Try to add more peers to our connection set.
  *
 /**
  * Try to add more peers to our connection set.
  *
@@ -933,7 +772,9 @@ disconnect_notify (void *cls,
                   GNUNET_PeerIdentity * peer)
 {
   struct Peer *pos;
                   GNUNET_PeerIdentity * peer)
 {
   struct Peer *pos;
+
+  if (0 == memcmp(&my_identity, peer, sizeof(struct GNUNET_PeerIdentity)))
+    return;
 #if DEBUG_TOPOLOGY
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Core told us that we disconnected from `%s'\n",
 #if DEBUG_TOPOLOGY
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Core told us that we disconnected from `%s'\n",
@@ -961,7 +802,7 @@ disconnect_notify (void *cls,
       friend_count--; 
       GNUNET_STATISTICS_set (stats,
                             gettext_noop ("# friends connected"),
       friend_count--; 
       GNUNET_STATISTICS_set (stats,
                             gettext_noop ("# friends connected"),
-                            connection_count,
+                            friend_count,
                             GNUNET_NO);
     }
   if ( (connection_count < target_connection_count) ||
                             GNUNET_NO);
     }
   if ( (connection_count < target_connection_count) ||
@@ -969,17 +810,10 @@ disconnect_notify (void *cls,
     GNUNET_CONTAINER_multihashmap_iterate (peers,
                                           &try_add_peers,
                                           NULL);
     GNUNET_CONTAINER_multihashmap_iterate (peers,
                                           &try_add_peers,
                                           NULL);
-  if (friend_count < minimum_friend_count)
-    {
-      /* disconnect from all non-friends */
-#if DEBUG_TOPOLOGY
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Not enough friendly connections, dropping all non-friend connections\n");
-#endif       
-      GNUNET_CONTAINER_multihashmap_iterate (peers,
-                                            &drop_non_friends,
-                                            NULL);
-    }
+  if ( (friend_count < minimum_friend_count) &&
+       (blacklist == NULL) )
+    blacklist = GNUNET_TRANSPORT_blacklist (cfg,
+                                           &blacklist_check, NULL);
 }
 
 
 }
 
 
@@ -997,7 +831,8 @@ static int
 address_iterator (void *cls,
                  const char *tname,
                  struct GNUNET_TIME_Absolute expiration,
 address_iterator (void *cls,
                  const char *tname,
                  struct GNUNET_TIME_Absolute expiration,
-                 const void *addr, size_t addrlen)
+                 const void *addr, 
+                 uint16_t addrlen)
 {
   int *flag = cls;
   *flag = GNUNET_YES;
 {
   int *flag = cls;
   *flag = GNUNET_YES;
@@ -1016,10 +851,16 @@ consider_for_advertising (const struct GNUNET_HELLO_Message *hello)
 {
   int have_address;
   struct GNUNET_PeerIdentity pid;
 {
   int have_address;
   struct GNUNET_PeerIdentity pid;
+  struct GNUNET_TIME_Absolute dt;
+  struct GNUNET_HELLO_Message *nh;
   struct Peer *peer;
   uint16_t size;
 
   struct Peer *peer;
   uint16_t size;
 
-  GNUNET_break (GNUNET_OK == GNUNET_HELLO_get_id (hello, &pid));
+  if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid))
+    {
+       GNUNET_break (0);
+       return;
+    }
   if (0 == memcmp (&pid,
                   &my_identity,
                   sizeof (struct GNUNET_PeerIdentity)))
   if (0 == memcmp (&pid,
                   &my_identity,
                   sizeof (struct GNUNET_PeerIdentity)))
@@ -1034,17 +875,36 @@ consider_for_advertising (const struct GNUNET_HELLO_Message *hello)
   peer = GNUNET_CONTAINER_multihashmap_get (peers,
                                            &pid.hashPubKey);
   if (peer == NULL)
   peer = GNUNET_CONTAINER_multihashmap_get (peers,
                                            &pid.hashPubKey);
   if (peer == NULL)
-    peer = make_peer (&pid, hello, GNUNET_NO);
+    {
+      peer = make_peer (&pid, hello, GNUNET_NO);
+    }
+  else if (peer->hello != NULL)
+    {
+      dt = GNUNET_HELLO_equals (peer->hello,
+                               hello,
+                               GNUNET_TIME_absolute_get());
+      if (dt.abs_value == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value)
+       return; /* nothing new here */
+    }
 #if DEBUG_TOPOLOGY
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Found `%s' from peer `%s' for advertising\n",
              "HELLO",
              GNUNET_i2s (&pid));
 #endif 
 #if DEBUG_TOPOLOGY
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Found `%s' from peer `%s' for advertising\n",
              "HELLO",
              GNUNET_i2s (&pid));
 #endif 
-  size = GNUNET_HELLO_size (hello);
-  GNUNET_free_non_null (peer->hello);
-  peer->hello = GNUNET_malloc (size);
-  memcpy (peer->hello, hello, size);
+  if (peer->hello != NULL)
+    {
+      nh = GNUNET_HELLO_merge (peer->hello,
+                              hello);
+      GNUNET_free (peer->hello);
+      peer->hello = nh;
+    }
+  else
+    {
+      size = GNUNET_HELLO_size (hello);
+      peer->hello = GNUNET_malloc (size);
+      memcpy (peer->hello, hello, size);
+    }
   if (peer->filter != NULL)
     GNUNET_CONTAINER_bloomfilter_free (peer->filter);
   setup_filter (peer);
   if (peer->filter != NULL)
     GNUNET_CONTAINER_bloomfilter_free (peer->filter);
   setup_filter (peer);
@@ -1063,13 +923,11 @@ consider_for_advertising (const struct GNUNET_HELLO_Message *hello)
  * @param cls closure (not used)
  * @param peer potential peer to connect to
  * @param hello HELLO for this peer (or NULL)
  * @param cls closure (not used)
  * @param peer potential peer to connect to
  * @param hello HELLO for this peer (or NULL)
- * @param trust how much we trust the peer (not used)
  */
 static void
 process_peer (void *cls,
              const struct GNUNET_PeerIdentity *peer,
  */
 static void
 process_peer (void *cls,
              const struct GNUNET_PeerIdentity *peer,
-             const struct GNUNET_HELLO_Message *hello,
-             uint32_t trust)
+             const struct GNUNET_HELLO_Message *hello)
 {
   struct Peer *pos;
 
 {
   struct Peer *pos;
 
@@ -1093,7 +951,7 @@ process_peer (void *cls,
            }
          if ( (! pos->is_connected) &&
               (! pos->is_friend) &&
            }
          if ( (! pos->is_connected) &&
               (! pos->is_friend) &&
-              (0 == GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).value) )
+              (0 == GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).rel_value) )
            free_peer (NULL, &pos->pid.hashPubKey, pos);
        }
       return;
            free_peer (NULL, &pos->pid.hashPubKey, pos);
        }
       return;
@@ -1113,7 +971,7 @@ process_peer (void *cls,
 #endif 
       return;
     }
 #endif 
       return;
     }
-  if (GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).value > 0)
+  if (GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).rel_value > 0)
     {
 #if DEBUG_TOPOLOGY
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     {
 #if DEBUG_TOPOLOGY
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1153,7 +1011,7 @@ core_init (void *cls,
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                  _("Failed to connect to core service, can not manage topology!\n"));
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                  _("Failed to connect to core service, can not manage topology!\n"));
-      GNUNET_SCHEDULER_shutdown (sched);
+      GNUNET_SCHEDULER_shutdown ();
       return;
     }
   handle = server;
       return;
     }
   handle = server;
@@ -1163,8 +1021,7 @@ core_init (void *cls,
              "I am peer `%s'\n",
              GNUNET_i2s (my_id));
 #endif         
              "I am peer `%s'\n",
              GNUNET_i2s (my_id));
 #endif         
-  peerinfo_notify = GNUNET_PEERINFO_notify (cfg, sched,
-                                           &process_peer,
+  peerinfo_notify = GNUNET_PEERINFO_notify (cfg, &process_peer,
                                            NULL);
 }
 
                                            NULL);
 }
 
@@ -1197,17 +1054,16 @@ read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg)
       return;
     }
   if (GNUNET_OK != GNUNET_DISK_file_test (fn))
       return;
     }
   if (GNUNET_OK != GNUNET_DISK_file_test (fn))
-    GNUNET_DISK_fn_write (fn, NULL, 0, GNUNET_DISK_PERM_USER_READ
-        | GNUNET_DISK_PERM_USER_WRITE);
+    GNUNET_DISK_fn_write (fn, NULL, 0, 
+                         GNUNET_DISK_PERM_USER_READ
+                         | GNUNET_DISK_PERM_USER_WRITE);
   if (0 != STAT (fn, &frstat))
     {
       if ((friends_only) || (minimum_friend_count > 0))
   if (0 != STAT (fn, &frstat))
     {
       if ((friends_only) || (minimum_friend_count > 0))
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     _("Could not read friends list `%s'\n"), fn);
-         GNUNET_free (fn);
-          return;
-        }
+       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                   _("Could not read friends list `%s'\n"), fn);
+      GNUNET_free (fn);
+      return;
     }
   if (frstat.st_size == 0)
     {
     }
   if (frstat.st_size == 0)
     {
@@ -1218,6 +1074,13 @@ read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg)
       return;
     }
   data = GNUNET_malloc_large (frstat.st_size);
       return;
     }
   data = GNUNET_malloc_large (frstat.st_size);
+  if (data == NULL)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 _("Failed to read friends list from `%s': out of memory\n"), fn);
+      GNUNET_free (fn);
+      return;
+    }
   if (frstat.st_size !=
       GNUNET_DISK_fn_read (fn, data, frstat.st_size))
     {
   if (frstat.st_size !=
       GNUNET_DISK_fn_read (fn, data, frstat.st_size))
     {
@@ -1229,19 +1092,19 @@ read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg)
     }
   entries_found = 0;
   pos = 0;
     }
   entries_found = 0;
   pos = 0;
-  while ((pos < frstat.st_size) && isspace (data[pos]))
+  while ((pos < frstat.st_size) && isspace ( (unsigned char) data[pos]))
     pos++;
   while ((frstat.st_size >= sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) &&
         (pos <= frstat.st_size - sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)))
     {
       memcpy (&enc, &data[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
     pos++;
   while ((frstat.st_size >= sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) &&
         (pos <= frstat.st_size - sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)))
     {
       memcpy (&enc, &data[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
-      if (!isspace (enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1]))
+      if (!isspace ( (unsigned char) enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1]))
        {
          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                      _("Syntax error in topology specification at offset %llu, skipping bytes.\n"),
                      (unsigned long long) pos);
          pos++;
        {
          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                      _("Syntax error in topology specification at offset %llu, skipping bytes.\n"),
                      (unsigned long long) pos);
          pos++;
-         while ((pos < frstat.st_size) && (!isspace (data[pos])))
+         while ((pos < frstat.st_size) && (!isspace ( (unsigned char) data[pos])))
            pos++;
          continue;
        }
            pos++;
          continue;
        }
@@ -1275,7 +1138,7 @@ read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg)
            }
        }
       pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded);
            }
        }
       pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded);
-      while ((pos < frstat.st_size) && isspace (data[pos]))
+      while ((pos < frstat.st_size) && isspace ( (unsigned char) data[pos]))
        pos++;
     }
   GNUNET_free (data);
        pos++;
     }
   GNUNET_free (data);
@@ -1307,8 +1170,7 @@ read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg)
  * @param other the other peer involved (sender or receiver, NULL
  *        for loopback messages where we are both sender and receiver)
  * @param message the actual HELLO message
  * @param other the other peer involved (sender or receiver, NULL
  *        for loopback messages where we are both sender and receiver)
  * @param message the actual HELLO message
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other' 
+ * @param atsi performance data
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -1317,8 +1179,7 @@ handle_encrypted_hello (void *cls,
                        const struct GNUNET_PeerIdentity * other,
                        const struct GNUNET_MessageHeader *
                        message,
                        const struct GNUNET_PeerIdentity * other,
                        const struct GNUNET_MessageHeader *
                        message,
-                       struct GNUNET_TIME_Relative latency,
-                       uint32_t distance)
+                       const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct Peer *peer;
   struct GNUNET_PeerIdentity pid;
 {
   struct Peer *peer;
   struct GNUNET_PeerIdentity pid;
@@ -1342,13 +1203,21 @@ handle_encrypted_hello (void *cls,
                            GNUNET_NO);
   peer = GNUNET_CONTAINER_multihashmap_get (peers,
                                            &pid.hashPubKey);
                            GNUNET_NO);
   peer = GNUNET_CONTAINER_multihashmap_get (peers,
                                            &pid.hashPubKey);
-  if ( (peer != NULL) &&
-       (peer->is_blocked) )
-    return GNUNET_OK; /* ignore: currently blocked */
-  if ( (GNUNET_YES == friends_only) &&
-       ( (peer == NULL) ||
-        (GNUNET_YES != peer->is_friend) ) )
-    return GNUNET_OK; /* ignore: not a friend */
+  if (peer == NULL)
+    {
+      if ( (GNUNET_YES == friends_only) ||
+          (friend_count < minimum_friend_count) )
+       return GNUNET_OK;      
+    }
+  else
+    {
+      if ( (GNUNET_YES != peer->is_friend) &&
+          (GNUNET_YES == friends_only) )
+       return GNUNET_OK;
+      if ( (GNUNET_YES != peer->is_friend) &&
+          (friend_count < minimum_friend_count) )
+       return GNUNET_OK;      
+    }
   if (transport != NULL)
     GNUNET_TRANSPORT_offer_hello (transport,
                                  message);
   if (transport != NULL)
     GNUNET_TRANSPORT_offer_hello (transport,
                                  message);
@@ -1393,7 +1262,7 @@ hello_advertising_ready (void *cls,
 #if DEBUG_TOPOLOGY
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                  "Sending `%s' with %u bytes",
 #if DEBUG_TOPOLOGY
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                  "Sending `%s' with %u bytes",
-                 "HELLO"
+                 "HELLO",
                  (unsigned int) want);
 #endif         
       GNUNET_STATISTICS_update (stats,
                  (unsigned int) want);
 #endif         
       GNUNET_STATISTICS_update (stats,
@@ -1403,8 +1272,7 @@ hello_advertising_ready (void *cls,
     }
   pl->next_hello_allowed = GNUNET_TIME_relative_to_absolute (HELLO_ADVERTISEMENT_MIN_FREQUENCY);
   pl->hello_delay_task 
     }
   pl->next_hello_allowed = GNUNET_TIME_relative_to_absolute (HELLO_ADVERTISEMENT_MIN_FREQUENCY);
   pl->hello_delay_task 
-    = GNUNET_SCHEDULER_add_now (sched,
-                               &schedule_next_hello,
+    = GNUNET_SCHEDULER_add_now (&schedule_next_hello,
                                pl);
   return want;
 }
                                pl);
   return want;
 }
@@ -1421,8 +1289,6 @@ static void
 cleaning_task (void *cls, 
               const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
 cleaning_task (void *cls, 
               const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct DisconnectList *dl;
-
   if (NULL != peerinfo_notify)
     {
       GNUNET_PEERINFO_notify_cancel (peerinfo_notify);
   if (NULL != peerinfo_notify)
     {
       GNUNET_PEERINFO_notify_cancel (peerinfo_notify);
@@ -1439,14 +1305,7 @@ cleaning_task (void *cls,
       GNUNET_CORE_disconnect (handle);
       handle = NULL;
     }
       GNUNET_CORE_disconnect (handle);
       handle = NULL;
     }
-  while (NULL != (dl = disconnect_head))
-    {
-      GNUNET_CONTAINER_DLL_remove (disconnect_head,
-                                  disconnect_tail,
-                                  dl);
-      GNUNET_TRANSPORT_blacklist_cancel (dl->rh);
-      GNUNET_free (dl);
-    }
+  whitelist_peers ();
   if (stats != NULL)
     {
       GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
   if (stats != NULL)
     {
       GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
@@ -1459,14 +1318,12 @@ cleaning_task (void *cls,
  * Main function that will be run.
  *
  * @param cls closure
  * Main function that will be run.
  *
  * @param cls closure
- * @param s the scheduler to use
  * @param args remaining command-line arguments
  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  * @param c configuration
  */
 static void
 run (void *cls,
  * @param args remaining command-line arguments
  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  * @param c configuration
  */
 static void
 run (void *cls,
-     struct GNUNET_SCHEDULER_Handle * s,
      char *const *args,
      const char *cfgfile,
      const struct GNUNET_CONFIGURATION_Handle * c)
      char *const *args,
      const char *cfgfile,
      const struct GNUNET_CONFIGURATION_Handle * c)
@@ -1478,9 +1335,8 @@ run (void *cls,
     };
   unsigned long long opt;
 
     };
   unsigned long long opt;
 
-  sched = s;
   cfg = c;
   cfg = c;
-  stats = GNUNET_STATISTICS_create (sched, "topology", cfg);
+  stats = GNUNET_STATISTICS_create ("topology", cfg);
   autoconnect = GNUNET_CONFIGURATION_get_value_yesno (cfg,
                                                      "TOPOLOGY",
                                                      "AUTOCONNECT");
   autoconnect = GNUNET_CONFIGURATION_get_value_yesno (cfg,
                                                      "TOPOLOGY",
                                                      "AUTOCONNECT");
@@ -1513,32 +1369,33 @@ run (void *cls,
              minimum_friend_count,
              autoconnect ? "autoconnect enabled" : "autoconnect disabled");
 #endif       
              minimum_friend_count,
              autoconnect ? "autoconnect enabled" : "autoconnect disabled");
 #endif       
-  transport = GNUNET_TRANSPORT_connect (sched,
-                                       cfg,
+  if (friend_count < minimum_friend_count) 
+    blacklist = GNUNET_TRANSPORT_blacklist (cfg,
+                                           &blacklist_check, NULL);
+  transport = GNUNET_TRANSPORT_connect (cfg,
+                                       NULL,
                                        NULL,
                                        NULL,
                                        NULL,
                                        NULL);
                                        NULL,
                                        NULL,
                                        NULL,
                                        NULL);
-  handle = GNUNET_CORE_connect (sched,
-                               cfg,
-                               GNUNET_TIME_UNIT_FOREVER_REL,
+  handle = GNUNET_CORE_connect (cfg,
+                               1,
                                NULL,
                                &core_init,
                                NULL,
                                &core_init,
-                               NULL,
                                &connect_notify,
                                &connect_notify,
-                               &disconnect_notify,
+                               &disconnect_notify, 
+                               NULL,
                                NULL, GNUNET_NO,
                                NULL, GNUNET_NO,
                                handlers);
                                NULL, GNUNET_NO,
                                NULL, GNUNET_NO,
                                handlers);
-  GNUNET_SCHEDULER_add_delayed (sched,
-                                GNUNET_TIME_UNIT_FOREVER_REL,
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
                                 &cleaning_task, NULL);
   if (NULL == transport)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                  _("Failed to connect to `%s' service.\n"),
                  "transport");
                                 &cleaning_task, NULL);
   if (NULL == transport)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                  _("Failed to connect to `%s' service.\n"),
                  "transport");
-      GNUNET_SCHEDULER_shutdown (sched);
+      GNUNET_SCHEDULER_shutdown ();
       return;
     }
   if (NULL == handle)
       return;
     }
   if (NULL == handle)
@@ -1546,20 +1403,12 @@ run (void *cls,
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                  _("Failed to connect to `%s' service.\n"),
                  "core");
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                  _("Failed to connect to `%s' service.\n"),
                  "core");
-      GNUNET_SCHEDULER_shutdown (sched);
+      GNUNET_SCHEDULER_shutdown ();
       return;
     }
 }
 
 
       return;
     }
 }
 
 
-/**
- * gnunet-daemon-topology command line options.
- */
-static struct GNUNET_GETOPT_CommandLineOption options[] = {
-  GNUNET_GETOPT_OPTION_END
-};
-
-
 /**
  * The main function for the topology daemon.
  *
 /**
  * The main function for the topology daemon.
  *
@@ -1570,6 +1419,9 @@ static struct GNUNET_GETOPT_CommandLineOption options[] = {
 int
 main (int argc, char *const *argv)
 {
 int
 main (int argc, char *const *argv)
 {
+  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
   int ret;
 
   ret = (GNUNET_OK ==
   int ret;
 
   ret = (GNUNET_OK ==