stuff
[oweals/gnunet.git] / src / transport / gnunet-service-transport.c
index 1ba2bacb6e95d3ee580c0d1efd35126411b038f5..cf02d14b26653156a92bf49dbdefacbef8671eff 100644 (file)
@@ -37,7 +37,7 @@
 #include "gnunet_service_lib.h"
 #include "gnunet_signatures.h"
 #include "gnunet_transport_plugin.h"
-#include "gnunet_transport_ats.h"
+#include "gnunet-service-transport_ats.h"
 #include "transport.h"
 
 
@@ -333,7 +333,7 @@ struct TransportPlugin
   struct GNUNET_CONTAINER_MultiHashMap *blacklist;
 };
 
-struct NeighbourList;
+struct NeighbourMapEntry;
 
 /**
  * For each neighbour we keep a list of messages
@@ -434,21 +434,16 @@ struct ReadyList
   /**
    * To which neighbour does this ready list belong to?
    */
-  struct NeighbourList *neighbour;
+  struct NeighbourMapEntry *neighbour;
 };
 
 
 /**
- * Entry in linked list of all of our current neighbours.
+ * Entry in neighbours. 
  */
-struct NeighbourList
+struct NeighbourMapEntry
 {
 
-  /**
-   * This is a linked list.
-   */
-  struct NeighbourList *next;
-
   /**
    * Which of our transports is connected to this peer
    * and what is their status?
@@ -882,7 +877,7 @@ static struct GNUNET_PEERINFO_Handle *peerinfo;
 /**
  * All known neighbours and their HELLOs.
  */
-static struct NeighbourList *neighbours;
+static struct GNUNET_CONTAINER_MultiHashMap *neighbours;
 
 /**
  * Number of neighbours we'd like to have.
@@ -956,7 +951,7 @@ struct GNUNET_TIME_Relative ats_regular_interval;
  *        disconnected or must we ask all plugins to
  *        disconnect?
  */
-static void disconnect_neighbour (struct NeighbourList *n, int check);
+static void disconnect_neighbour (struct NeighbourMapEntry *n, int check);
 
 /**
  * Check the ready list for the given neighbour and if a plugin is
@@ -964,25 +959,20 @@ static void disconnect_neighbour (struct NeighbourList *n, int check);
  *
  * @param nexi target peer for which to transmit
  */
-static void try_transmission_to_peer (struct NeighbourList *n);
+static void try_transmission_to_peer (struct NeighbourMapEntry *n);
 
 struct ForeignAddressList * get_preferred_ats_address (
-               struct NeighbourList *n);
+               struct NeighbourMapEntry *n);
 
 /**
  * Find an entry in the neighbour list for a particular peer.
  *
  * @return NULL if not found.
  */
-static struct NeighbourList *
+static struct NeighbourMapEntry *
 find_neighbour (const struct GNUNET_PeerIdentity *key)
 {
-  struct NeighbourList *head = neighbours;
-
-  while ((head != NULL) &&
-        (0 != memcmp (key, &head->id, sizeof (struct GNUNET_PeerIdentity))))
-    head = head->next;
-  return head;
+  return GNUNET_CONTAINER_multihashmap_get (neighbours, &key->hashPubKey);
 }
 
 static int update_addr_value (struct ForeignAddressList *fal, uint32_t value , int ats_index)
@@ -997,7 +987,9 @@ static int update_addr_value (struct ForeignAddressList *fal, uint32_t value , i
       fal->quality[c].values[1] = fal->quality[c].values[2];
       fal->quality[c].values[2] = value;
       set = GNUNET_YES;
+#if HAVE_LIBGLPK
       ats_modify_problem_state (ats, ATS_QUALITY_UPDATED);
+#endif
     }
   }
   if (set == GNUNET_NO)
@@ -1008,7 +1000,9 @@ static int update_addr_value (struct ForeignAddressList *fal, uint32_t value , i
       {
         fal->ressources[c].c = value;
         set = GNUNET_YES;
+#if HAVE_LIBGLPK
         ats_modify_problem_state (ats, ATS_COST_UPDATED);
+#endif
       }
     }
   }
@@ -1362,11 +1356,9 @@ a2s (const char *plugin,
   p = find_transport (plugin);
   if ((p == NULL) || (addr_len == 0) || (addr == NULL))
     return NULL;
-
   return p->api->address_to_string (NULL,
                                    addr,
                                    addr_len);
-  return NULL;
 }
 
 
@@ -1454,6 +1446,15 @@ transmit_to_client (struct TransportClient *client,
   struct ClientMessageQueueEntry *q;
   uint16_t msize;
 
+  /* Client==NULL when GNUNET_SERVER_Client disconnected and was
+   * freed in client_disconnect_notification
+   */
+  if (client->client == NULL)
+    {
+      GNUNET_break (0);
+      return;
+    }
+
   if ((client->message_count >= MAX_PENDING) && (GNUNET_YES == may_drop))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -1500,7 +1501,7 @@ transmit_to_client (struct TransportClient *client,
  */
 static void
 transmit_send_ok (struct TransportClient *client,
-                 struct NeighbourList *n,
+                 struct NeighbourMapEntry *n,
                  const struct GNUNET_PeerIdentity *target,
                  int result)
 {
@@ -1538,7 +1539,7 @@ static void
 retry_transmission_task (void *cls,
                         const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct NeighbourList *n = cls;
+  struct NeighbourMapEntry *n = cls;
 
   n->retry_task = GNUNET_SCHEDULER_NO_TASK;
   try_transmission_to_peer (n);
@@ -1565,7 +1566,7 @@ transmit_send_continuation (void *cls,
                             int result)
 {
   struct MessageQueue *mq = cls;
-  struct NeighbourList *n;
+  struct NeighbourMapEntry *n;
 
   GNUNET_STATISTICS_update (stats,
                            gettext_noop ("# bytes pending with plugins"),
@@ -1597,7 +1598,7 @@ transmit_send_continuation (void *cls,
        }
       else
        {
-         if (mq->specific_address->connected != GNUNET_NO)
+         if (mq->specific_address->connected == GNUNET_YES)
            {
 #if DEBUG_TRANSPORT
              GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1639,7 +1640,7 @@ transmit_send_continuation (void *cls,
  * @param neighbour target peer for which to transmit
  */
 static void
-try_transmission_to_peer (struct NeighbourList *n)
+try_transmission_to_peer (struct NeighbourMapEntry *n)
 {
   struct ReadyList *rl;
   struct MessageQueue *mq;
@@ -1796,7 +1797,7 @@ transmit_to_peer (struct TransportClient *client,
                  struct GNUNET_TIME_Relative timeout,
                   const char *message_buf,
                   size_t message_buf_size,
-                  int is_internal, struct NeighbourList *neighbour)
+                  int is_internal, struct NeighbourMapEntry *neighbour)
 {
   struct MessageQueue *mq;
 
@@ -1854,7 +1855,7 @@ transmit_to_peer (struct TransportClient *client,
  * @param n neighbour to PING
  */
 static void
-transmit_plain_ping (struct NeighbourList *n)
+transmit_plain_ping (struct NeighbourMapEntry *n)
 {
   struct ValidationEntry *ve;
   struct TransportPingMessage ping;
@@ -1934,12 +1935,10 @@ mark_address_connected(struct ForeignAddressList *fal)
   struct ForeignAddressList *pos;
   struct ForeignAddressList *inbound;
   struct ForeignAddressList *outbound;
-  int cnt;
 
   GNUNET_assert (GNUNET_YES == fal->validated);
   if (fal->connected == GNUNET_YES)
     return; /* nothing to do */
-  cnt = GNUNET_YES;
   inbound = NULL;
   outbound = NULL;
 
@@ -1947,10 +1946,12 @@ mark_address_connected(struct ForeignAddressList *fal)
   while (pos != NULL)
     {
       /* Already have inbound address, and this is also an inbound address, don't switch!! */
-      if ((GNUNET_YES == pos->connected) && (0 == pos->addrlen) && (0
-          == fal->addrlen))
+      if ( (GNUNET_YES == pos->connected) && 
+          (0 == pos->addrlen) && 
+          (0 == fal->addrlen) )
         return;
-      else if ((0 == pos->addrlen) && (GNUNET_YES == pos->connected))
+      if ( (0 == pos->addrlen) && 
+          (GNUNET_YES == pos->connected) )
         inbound = pos;
       pos = pos->next;
     }
@@ -1959,10 +1960,11 @@ mark_address_connected(struct ForeignAddressList *fal)
   while (pos != NULL)
     {
       /* Already have outbound address, and this is also an outbound address, don't switch!! */
-      if ((GNUNET_YES == pos->connected) && (0 < pos->addrlen) && (0
-          < fal->addrlen))
+      if ( (GNUNET_YES == pos->connected) && 
+          (0 < pos->addrlen) && 
+          (0 < fal->addrlen) )
         return;
-      else if ((0 < pos->addrlen) && (GNUNET_YES == pos->connected))
+      if ( (0 < pos->addrlen) && (GNUNET_YES == pos->connected) )
         outbound = pos;
       pos = pos->next;
     }
@@ -2000,16 +2002,16 @@ mark_address_connected(struct ForeignAddressList *fal)
       if ((GNUNET_YES == pos->connected) && (0 < pos->addrlen))
         {
 #if DEBUG_TRANSPORT
-          GNUNET_log (
-                      GNUNET_ERROR_TYPE_DEBUG,
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                       "Marking address `%s' as no longer connected (due to connect on other address)\n",
                       a2s (pos->ready_list->plugin->short_name, pos->addr,
                            pos->addrlen));
 #endif
-          GNUNET_break (cnt == GNUNET_YES);
-          cnt = GNUNET_NO;
 #if DEBUG_INBOUND
-          fprintf(stderr, "Peer: %s, setting %s connection to disconnected.\n", GNUNET_i2s(&my_identity), (0 == pos->addrlen) ? "INBOUND" : "OUTBOUND");
+          fprintf(stderr, 
+                 "Peer: %s, setting %s connection to disconnected.\n", 
+                 GNUNET_i2s(&my_identity),
+                 (0 == pos->addrlen) ? "INBOUND" : "OUTBOUND");
 #endif
           pos->connected = GNUNET_NO;
           GNUNET_STATISTICS_update (stats,
@@ -2018,13 +2020,10 @@ mark_address_connected(struct ForeignAddressList *fal)
         }
       pos = pos->next;
     }
-
+  GNUNET_assert (GNUNET_NO == fal->connected);
   fal->connected = GNUNET_YES;
-  if (GNUNET_YES == cnt)
-    {
-      GNUNET_STATISTICS_update (stats, gettext_noop ("# connected addresses"),
-                                1, GNUNET_NO);
-    }
+  GNUNET_STATISTICS_update (stats, gettext_noop ("# connected addresses"),
+                           1, GNUNET_NO);
 }
 
 
@@ -2038,7 +2037,7 @@ mark_address_connected(struct ForeignAddressList *fal)
  * @return selected address, NULL if we have none
  */
 struct ForeignAddressList *
-find_ready_address(struct NeighbourList *neighbour)
+find_ready_address(struct NeighbourMapEntry *neighbour)
 {
   struct ReadyList *head = neighbour->plugins;
   struct ForeignAddressList *addresses;
@@ -2183,6 +2182,34 @@ address_generator (void *cls, size_t max, void *buf)
 }
 
 
+
+static int
+transmit_our_hello_if_pong (void *cls,
+                           const GNUNET_HashCode *key,
+                           void *value)
+{
+  struct NeighbourMapEntry *npos = value;
+
+  if (GNUNET_YES != npos->received_pong)
+    return GNUNET_OK;
+#if DEBUG_TRANSPORT
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
+             "Transmitting updated `%s' to neighbour `%4s'\n",
+             "HELLO", GNUNET_i2s (&npos->id));
+#endif
+  GNUNET_STATISTICS_update (stats,
+                           gettext_noop ("# transmitted my HELLO to other peers"),
+                           1,
+                           GNUNET_NO);
+  transmit_to_peer (NULL, NULL, 0,
+                   HELLO_ADDRESS_EXPIRATION,
+                   (const char *) our_hello,
+                   GNUNET_HELLO_size(our_hello),
+                   GNUNET_NO, npos);
+  return GNUNET_OK;
+}
+
+
 /**
  * Construct our HELLO message from all of the addresses of
  * all of the transports.
@@ -2196,7 +2223,6 @@ refresh_hello_task (void *cls,
 {
   struct GNUNET_HELLO_Message *hello;
   struct TransportClient *cpos;
-  struct NeighbourList *npos;
   struct GeneratorContext gc;
 
   hello_task = GNUNET_SCHEDULER_NO_TASK;
@@ -2226,25 +2252,9 @@ refresh_hello_task (void *cls,
   GNUNET_free_non_null (our_hello);
   our_hello = hello;
   GNUNET_PEERINFO_add_peer (peerinfo, our_hello);
-  for (npos = neighbours; npos != NULL; npos = npos->next)
-    {
-      if (! npos->received_pong)
-       continue;
-#if DEBUG_TRANSPORT
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
-                  "Transmitting updated `%s' to neighbour `%4s'\n",
-                  "HELLO", GNUNET_i2s (&npos->id));
-#endif
-      GNUNET_STATISTICS_update (stats,
-                               gettext_noop ("# transmitted my HELLO to other peers"),
-                               1,
-                               GNUNET_NO);
-      transmit_to_peer (NULL, NULL, 0,
-                       HELLO_ADDRESS_EXPIRATION,
-                        (const char *) our_hello,
-                       GNUNET_HELLO_size(our_hello),
-                        GNUNET_NO, npos);
-    }
+  GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+                                        &transmit_our_hello_if_pong,
+                                        NULL);
 }
 
 
@@ -2304,7 +2314,7 @@ remove_session_validations (void *cls,
  */
 static void
 try_fast_reconnect (struct TransportPlugin *p,
-                   struct NeighbourList *nl)
+                   struct NeighbourMapEntry *nl)
 {
   /* FIXME-MW: fast reconnect / transport switching not implemented... */
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -2375,7 +2385,7 @@ plugin_env_session_end  (void *cls,
                         struct Session *session)
 {
   struct TransportPlugin *p = cls;
-  struct NeighbourList *nl;
+  struct NeighbourMapEntry *nl;
   struct ReadyList *rl;
   struct ForeignAddressList *pos;
   struct ForeignAddressList *prev;
@@ -2458,7 +2468,14 @@ plugin_env_session_end  (void *cls,
       return; /* was never marked as connected */
     }
   pos->session = NULL;
-  pos->connected = GNUNET_NO;
+  if (GNUNET_YES == pos->connected)
+    {
+      pos->connected = GNUNET_NO;      
+      GNUNET_STATISTICS_update (stats,
+                               gettext_noop ("# connected addresses"),
+                               -1,
+                               GNUNET_NO);
+    }
   if (GNUNET_SCHEDULER_NO_TASK != pos->revalidate_task)
     {
       GNUNET_SCHEDULER_cancel (pos->revalidate_task);
@@ -2489,11 +2506,6 @@ plugin_env_session_end  (void *cls,
       return;
     }
 
-  GNUNET_STATISTICS_update (stats,
-                              gettext_noop ("# connected addresses"),
-                              -1,
-                              GNUNET_NO);
-
   /* was inbound connection, free 'pos' */
   if (prev == NULL)
     rl->addresses = pos->next;
@@ -2504,16 +2516,22 @@ plugin_env_session_end  (void *cls,
       GNUNET_SCHEDULER_cancel (pos->revalidate_task);
       pos->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
     }
-  GNUNET_free_non_null(pos->ressources);
-  GNUNET_free_non_null(pos->quality);
+  GNUNET_free_non_null (pos->ressources);
+  GNUNET_free_non_null (pos->quality);
+#if HAVE_LIBGLPK
   ats_modify_problem_state (ats, ATS_MODIFIED);
-
+#endif
   if (GNUNET_YES != pos->connected)
     {
       /* nothing else to do, connection was never up... */
       GNUNET_free (pos);
       return; 
     }
+  pos->connected = GNUNET_NO;
+  GNUNET_STATISTICS_update (stats,
+                           gettext_noop ("# connected addresses"),
+                           -1,
+                           GNUNET_NO);
   GNUNET_free (pos);
 
   if (nl->received_pong == GNUNET_NO)
@@ -2659,10 +2677,7 @@ notify_clients_connect (const struct GNUNET_PeerIdentity *peer,
 
   ats_count = 2;
   size  = sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
-  if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
-    {
-      GNUNET_break(0);
-    }
+  GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
   cim = GNUNET_malloc (size);
   cim->header.size = htons (size);
   cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
@@ -2678,8 +2693,10 @@ notify_clients_connect (const struct GNUNET_PeerIdentity *peer,
   /* notify ats about connecting peer */
   if ((ats != NULL) && (shutdown_in_progress == GNUNET_NO))
     {
+#if HAVE_LIBGLPK
       ats_modify_problem_state(ats, ATS_MODIFIED);
-      ats_calculate_bandwidth_distribution (ats, stats);
+      ats_calculate_bandwidth_distribution (ats);
+#endif
     }
   cpos = clients;
   while (cpos != NULL)
@@ -2724,8 +2741,10 @@ notify_clients_disconnect (const struct GNUNET_PeerIdentity *peer)
   /* notify ats about connecting peer */
   if ((ats != NULL) && (shutdown_in_progress == GNUNET_NO))
   {
+#if HAVE_LIBGLPK
     ats_modify_problem_state(ats, ATS_MODIFIED);
-    ats_calculate_bandwidth_distribution (ats, stats);
+    ats_calculate_bandwidth_distribution (ats);
+#endif
   }
 
   cpos = clients;
@@ -2751,7 +2770,7 @@ notify_clients_disconnect (const struct GNUNET_PeerIdentity *peer)
  * @return NULL if no such entry exists
  */
 static struct ForeignAddressList *
-find_peer_address(struct NeighbourList *neighbour,
+find_peer_address(struct NeighbourMapEntry *neighbour,
                  const char *tname,
                  struct Session *session,
                  const char *addr,
@@ -2797,7 +2816,7 @@ find_peer_address(struct NeighbourList *neighbour,
  * @return NULL if we do not have a transport plugin for 'tname'
  */
 static struct ForeignAddressList *
-add_peer_address (struct NeighbourList *neighbour,
+add_peer_address (struct NeighbourMapEntry *neighbour,
                  const char *tname,
                  struct Session *session,
                  const char *addr,
@@ -3012,7 +3031,7 @@ static void
 neighbour_timeout_task (void *cls,
                       const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct NeighbourList *n = cls;
+  struct NeighbourMapEntry *n = cls;
 
 #if DEBUG_TRANSPORT
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
@@ -3041,7 +3060,7 @@ schedule_next_ping (struct ForeignAddressList *fal);
  * Add the given address to the list of foreign addresses
  * available for the given peer (check for duplicates).
  *
- * @param cls the respective 'struct NeighbourList' to update
+ * @param cls the respective 'struct NeighbourMapEntry' to update
  * @param tname name of the transport
  * @param expiration expiration time
  * @param addr the address
@@ -3055,7 +3074,7 @@ add_to_foreign_address_list (void *cls,
                             const void *addr,
                             uint16_t addrlen)
 {
-  struct NeighbourList *n = cls;
+  struct NeighbourMapEntry *n = cls;
   struct ForeignAddressList *fal;
   int try;
 
@@ -3129,7 +3148,7 @@ add_to_foreign_address_list (void *cls,
  * Add addresses in validated HELLO "h" to the set of addresses
  * we have for this peer.
  *
- * @param cls closure ('struct NeighbourList*')
+ * @param cls closure ('struct NeighbourMapEntry*')
  * @param peer id of the peer, NULL for last call
  * @param h hello message for the peer (can be NULL)
  * @param err_msg NULL if successful, otherwise contains error message
@@ -3140,7 +3159,7 @@ add_hello_for_peer (void *cls,
                    const struct GNUNET_HELLO_Message *h,
                    const char *err_msg)
 {
-  struct NeighbourList *n = cls;
+  struct NeighbourMapEntry *n = cls;
 
   if (err_msg != NULL)
     {
@@ -3189,11 +3208,11 @@ add_hello_for_peer (void *cls,
  * @param do_hello should we schedule transmitting a HELLO
  * @return the new neighbour list entry
  */
-static struct NeighbourList *
+static struct NeighbourMapEntry *
 setup_new_neighbour (const struct GNUNET_PeerIdentity *peer,
                     int do_hello)
 {
-  struct NeighbourList *n;
+  struct NeighbourMapEntry *n;
   struct TransportPlugin *tp;
   struct ReadyList *rl;
 
@@ -3209,9 +3228,7 @@ setup_new_neighbour (const struct GNUNET_PeerIdentity *peer,
                            gettext_noop ("# active neighbours"),
                            1,
                            GNUNET_NO);
-  n = GNUNET_malloc (sizeof (struct NeighbourList));
-  n->next = neighbours;
-  neighbours = n;
+  n = GNUNET_malloc (sizeof (struct NeighbourMapEntry));
   n->id = *peer;
   n->peer_timeout =
     GNUNET_TIME_relative_to_absolute
@@ -3237,6 +3254,10 @@ setup_new_neighbour (const struct GNUNET_PeerIdentity *peer,
   n->distance = -1;
   n->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
                                                   &neighbour_timeout_task, n);
+  GNUNET_CONTAINER_multihashmap_put (neighbours,
+                                    &n->id.hashPubKey,
+                                    n,
+                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
   if (do_hello)
     {
       GNUNET_STATISTICS_update (stats,
@@ -3273,7 +3294,7 @@ setup_new_neighbour (const struct GNUNET_PeerIdentity *peer,
  * @param n NULL if communication is not acceptable
  */
 typedef void (*SetupContinuation)(void *cls,
-                                 struct NeighbourList *n);
+                                 struct NeighbourMapEntry *n);
 
 
 /**
@@ -3475,12 +3496,12 @@ do_blacklist_check (void *cls,
 
 
 /**
- * Obtain a 'struct NeighbourList' for the given peer.  If such an entry
+ * Obtain a 'struct NeighbourMapEntry' for the given peer.  If such an entry
  * does not yet exist, check the blacklist.  If the blacklist says creating
  * one is acceptable, create one and call the continuation; otherwise
  * call the continuation with NULL.
  *
- * @param peer peer to setup or look up a struct NeighbourList for
+ * @param peer peer to setup or look up a struct NeighbourMapEntry for
  * @param do_hello should we also schedule sending our HELLO to the peer
  *        if this is a new record
  * @param cont function to call with the 'struct NeigbhbourList*'
@@ -3492,7 +3513,7 @@ setup_peer_check_blacklist (const struct GNUNET_PeerIdentity *peer,
                            SetupContinuation cont,
                            void *cont_cls)
 {
-  struct NeighbourList *n;
+  struct NeighbourMapEntry *n;
   struct BlacklistCheck *bc;
 
   n = find_neighbour(peer);
@@ -3531,14 +3552,14 @@ setup_peer_check_blacklist (const struct GNUNET_PeerIdentity *peer,
  * Function called with the result of querying a new blacklister about
  * it being allowed (or not) to continue to talk to an existing neighbour.
  *
- * @param cls the original 'struct NeighbourList'
+ * @param cls the original 'struct NeighbourMapEntry'
  * @param n NULL if we need to disconnect
  */
 static void
 confirm_or_drop_neighbour (void *cls,
-                          struct NeighbourList *n)
+                          struct NeighbourMapEntry *n)
 {
-  struct NeighbourList * orig = cls;
+  struct NeighbourMapEntry * orig = cls;
 
   if (n == NULL)
     {
@@ -3556,6 +3577,43 @@ confirm_or_drop_neighbour (void *cls,
 }
 
 
+struct TestConnectionContext
+{
+  int first;
+
+  struct Blacklisters *bl;
+};
+
+
+static int
+test_connection_ok (void *cls,
+                   const GNUNET_HashCode *key,
+                   void *value)
+{
+  struct TestConnectionContext *tcc = cls;
+  struct NeighbourMapEntry *n = value;
+  struct BlacklistCheck *bc;
+
+  
+  bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
+  GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
+  bc->peer = n->id;
+  bc->do_hello = GNUNET_NO;
+  bc->cont = &confirm_or_drop_neighbour;
+  bc->cont_cls = n;
+  bc->bl_pos = tcc->bl;
+  if (GNUNET_YES == tcc->first)
+    { 
+      /* all would wait for the same client, no need to
+        create more than just the first task right now */
+      bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
+                                          bc);
+      tcc->first = GNUNET_NO;
+    }
+  return GNUNET_OK;
+}
+
+
 /**
  * Handle a request to start a blacklist.
  *
@@ -3569,8 +3627,7 @@ handle_blacklist_init (void *cls,
                       const struct GNUNET_MessageHeader *message)
 {
   struct Blacklisters *bl;
-  struct BlacklistCheck *bc;
-  struct NeighbourList *n;
+  struct TestConnectionContext tcc;
 
   bl = bl_head;
   while (bl != NULL)
@@ -3588,22 +3645,11 @@ handle_blacklist_init (void *cls,
   GNUNET_SERVER_client_keep (client);
   GNUNET_CONTAINER_DLL_insert_after (bl_head, bl_tail, bl_tail, bl);
   /* confirm that all existing connections are OK! */
-  n = neighbours;
-  while (NULL != n)
-    {
-      bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
-      GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
-      bc->peer = n->id;
-      bc->do_hello = GNUNET_NO;
-      bc->cont = &confirm_or_drop_neighbour;
-      bc->cont_cls = n;
-      bc->bl_pos = bl;
-      if (n == neighbours) /* all would wait for the same client, no need to
-                             create more than just the first task right now */
-       bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
-                                            bc);
-      n = n->next;
-    }
+  tcc.bl = bl;
+  tcc.first = GNUNET_YES;
+  GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+                                        &test_connection_ok,
+                                        &tcc);
 }
 
 
@@ -3685,7 +3731,7 @@ send_periodic_ping (void *cls,
   struct ForeignAddressList *peer_address = cls;
   struct TransportPlugin *tp;
   struct ValidationEntry *va;
-  struct NeighbourList *neighbour;
+  struct NeighbourMapEntry *neighbour;
   struct TransportPingMessage ping;
   struct CheckAddressExistsClosure caec;
   char * message_buf;
@@ -3693,12 +3739,10 @@ send_periodic_ping (void *cls,
   size_t slen;
   size_t tsize;
 
+  peer_address->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
   if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
     return;
-
   GNUNET_assert (peer_address != NULL);
-  peer_address->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
-
   tp = peer_address->ready_list->plugin;
   neighbour = peer_address->ready_list->neighbour;
   if (GNUNET_YES != neighbour->public_key_valid)
@@ -3838,7 +3882,7 @@ send_periodic_ping (void *cls,
                     HELLO_VERIFICATION_TIMEOUT,
                     message_buf, tsize,
                     GNUNET_YES, neighbour);
-  GNUNET_free(message_buf);
+  GNUNET_free (message_buf);
   schedule_next_ping (peer_address);
 }
 
@@ -3900,7 +3944,7 @@ schedule_next_ping (struct ForeignAddressList *fal)
  */
 static void
 handle_payload_message (const struct GNUNET_MessageHeader *message,
-                       struct NeighbourList *n)
+                       struct NeighbourMapEntry *n)
 {
   struct InboundMessage *im;
   struct TransportClient *cpos;
@@ -4008,7 +4052,7 @@ check_pending_validation (void *cls,
   unsigned int challenge = ntohl(pong->challenge);
   struct GNUNET_HELLO_Message *hello;
   struct GNUNET_PeerIdentity target;
-  struct NeighbourList *n;
+  struct NeighbourMapEntry *n;
   struct ForeignAddressList *fal;
   struct OwnAddressList *oal;
   struct TransportPlugin *tp;
@@ -4311,7 +4355,7 @@ handle_pong (void *cls, const struct GNUNET_MessageHeader *message,
  */
 static void
 transmit_hello_and_ping (void *cls,
-                        struct NeighbourList *neighbour)
+                        struct NeighbourMapEntry *neighbour)
 {
   struct ValidationEntry *va = cls;
   struct ForeignAddressList *peer_address;
@@ -4396,7 +4440,7 @@ transmit_hello_and_ping (void *cls,
                    HELLO_VERIFICATION_TIMEOUT,
                    message_buf, tsize,
                    GNUNET_YES, neighbour);
-  GNUNET_free(message_buf);
+  GNUNET_free (message_buf);
 }
 
 
@@ -4554,7 +4598,7 @@ check_hello_validated (void *cls,
   struct GNUNET_HELLO_Message *plain_hello;
   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
   struct GNUNET_PeerIdentity target;
-  struct NeighbourList *n;
+  struct NeighbourMapEntry *n;
 
   if (err_msg != NULL)
     {
@@ -4681,7 +4725,7 @@ process_hello (struct TransportPlugin *plugin,
   const struct GNUNET_HELLO_Message *hello;
   struct CheckHelloValidatedContext *chvc;
   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
-  struct NeighbourList *n;
+  struct NeighbourMapEntry *n;
 #if DEBUG_TRANSPORT_HELLO > 2
   char *my_id;
 #endif
@@ -4777,7 +4821,7 @@ process_hello (struct TransportPlugin *plugin,
     }
 
 #if BREAK_TESTS
-  struct NeighbourList *temp_neighbor = find_neighbour(&target);
+  struct NeighbourMapEntry *temp_neighbor = find_neighbour(&target);
   if ((NULL != temp_neighbor))
     {
       fprintf(stderr, "Already know peer, ignoring hello\n");
@@ -4788,8 +4832,8 @@ process_hello (struct TransportPlugin *plugin,
 #if DEBUG_TRANSPORT_HELLO > 2
   if (plugin != NULL)
     {
-      my_id = GNUNET_strdup(GNUNET_i2s(plugin->env.my_identity));
 #if DEBUG_TRANSPORT
+      my_id = GNUNET_strdup(GNUNET_i2s(plugin->env.my_identity));
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "%s: Starting validation of `%s' message for `%4s' via '%s' of size %u\n",
                   my_id,
@@ -4797,8 +4841,8 @@ process_hello (struct TransportPlugin *plugin,
                   GNUNET_i2s (&target),
                   plugin->short_name,
                   GNUNET_HELLO_size(hello));
+      GNUNET_free (my_id);
 #endif
-      GNUNET_free(my_id);
     }
 #endif
   chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize);
@@ -4840,11 +4884,9 @@ process_hello (struct TransportPlugin *plugin,
  *              regardless of whether other addresses exist.
  */
 static void
-disconnect_neighbour (struct NeighbourList *n, int check)
+disconnect_neighbour (struct NeighbourMapEntry *n, int check)
 {
   struct ReadyList *rpos;
-  struct NeighbourList *npos;
-  struct NeighbourList *nprev;
   struct MessageQueue *mq;
   struct ForeignAddressList *peer_addresses;
   struct ForeignAddressList *peer_pos;
@@ -4886,10 +4928,13 @@ disconnect_neighbour (struct NeighbourList *n, int check)
 
   /* notify all clients about disconnect */
   if (GNUNET_YES == n->received_pong)
-    notify_clients_disconnect (&n->id);
-
+    {
+      n->received_pong = GNUNET_NO;
+      notify_clients_disconnect (&n->id);
+    }
+#if HAVE_LIBGLPK
   ats_modify_problem_state(ats, ATS_MODIFIED);
-
+#endif
   /* clean up all plugins, cancel connections and pending transmissions */
   while (NULL != (rpos = n->plugins))
     {
@@ -4900,10 +4945,13 @@ disconnect_neighbour (struct NeighbourList *n, int check)
           peer_pos = rpos->addresses;
           rpos->addresses = peer_pos->next;
          if (peer_pos->connected == GNUNET_YES)
-           GNUNET_STATISTICS_update (stats,
-                                     gettext_noop ("# connected addresses"),
-                                     -1,
-                                     GNUNET_NO);
+           {
+             GNUNET_STATISTICS_update (stats,
+                                       gettext_noop ("# connected addresses"),
+                                       -1,
+                                       GNUNET_NO);
+             peer_pos->connected = GNUNET_NO;
+           }
          if (GNUNET_YES == peer_pos->validated)
            GNUNET_STATISTICS_update (stats,
                                      gettext_noop ("# peer addresses considered valid"),
@@ -4914,11 +4962,11 @@ disconnect_neighbour (struct NeighbourList *n, int check)
              GNUNET_SCHEDULER_cancel (peer_pos->revalidate_task);
              peer_pos->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
            }
-         GNUNET_free(peer_pos->ressources);
+         GNUNET_free (peer_pos->ressources);
          peer_pos->ressources = NULL;
-         GNUNET_free(peer_pos->quality);
+         GNUNET_free (peer_pos->quality);
          peer_pos->ressources = NULL;
-         GNUNET_free(peer_pos);
+         GNUNET_free (peer_pos);
         }
       GNUNET_free (rpos);
     }
@@ -4975,20 +5023,10 @@ disconnect_neighbour (struct NeighbourList *n, int check)
       n->piter = NULL;
     }
 
-  /* remove n from neighbours list */
-  nprev = NULL;
-  npos = neighbours;
-  while ((npos != NULL) && (npos != n))
-    {
-      nprev = npos;
-      npos = npos->next;
-    }
-  GNUNET_assert (npos != NULL);
-  if (nprev == NULL)
-    neighbours = n->next;
-  else
-    nprev->next = n->next;
-
+  GNUNET_assert (GNUNET_OK ==
+                GNUNET_CONTAINER_multihashmap_remove (neighbours,
+                                                      &n->id.hashPubKey,
+                                                      n));
   /* finally, free n itself */
   GNUNET_STATISTICS_update (stats,
                            gettext_noop ("# active neighbours"),
@@ -5014,7 +5052,7 @@ handle_ping (void *cls, const struct GNUNET_MessageHeader *message,
   struct SessionHeader *session_header = (struct SessionHeader*) session;
   struct TransportPingMessage *ping;
   struct TransportPongMessage *pong;
-  struct NeighbourList *n;
+  struct NeighbourMapEntry *n;
   struct ReadyList *rl;
   struct ForeignAddressList *fal;
   struct OwnAddressList *oal;
@@ -5319,7 +5357,7 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
   struct ReadyList *service_context;
   struct ForeignAddressList *peer_address;
   uint16_t msize;
-  struct NeighbourList *n;
+  struct NeighbourMapEntry *n;
   struct GNUNET_TIME_Relative ret;
   uint32_t distance;
   int c;
@@ -5419,6 +5457,7 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
     if ((ntohs(message->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_ATS) &&
        (ntohs(message->size) == (sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t))))
       {
+#if HAVE_LIBGLPK
        uint32_t value =  ntohl(*((uint32_t *) &message[1]));
        //GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "GNUNET_MESSAGE_TYPE_TRANSPORT_ATS: %i \n", value);
        /* Force ressource and quality update */
@@ -5433,6 +5472,7 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
        /* Force full rebuild */
        if ((value == 1) && (ats != NULL))
           ats_modify_problem_state(ats, ATS_MODIFIED);
+#endif
       }
     
 #if DEBUG_PING_PONG
@@ -5453,7 +5493,7 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
          break;
        case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
          handle_ping (plugin, message, peer, session, sender_address, sender_address_len);
-         if (! n->received_pong)
+         if (GNUNET_YES != n->received_pong)
            transmit_plain_ping (n);
          break;
        case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
@@ -5484,6 +5524,44 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
   return ret;
 }
 
+
+static int
+notify_client_about_neighbour (void *cls,
+                              const GNUNET_HashCode *key,
+                              void *value)
+{
+  struct TransportClient *c = cls;
+  struct NeighbourMapEntry *n = value;
+  struct ConnectInfoMessage * cim;
+  uint32_t ats_count;
+  size_t size;
+
+  if (GNUNET_YES != n->received_pong)
+    return GNUNET_OK;
+
+  ats_count = 2;
+  size  = sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+  GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
+  cim = GNUNET_malloc (size);
+  cim->header.size = htons (size);
+  cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
+  cim->ats_count = htonl(ats_count);
+  (&(cim->ats))[2].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
+  (&(cim->ats))[2].value = htonl (0); 
+  if (GNUNET_YES == n->received_pong)
+    {
+      (&cim->ats)[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
+      (&cim->ats)[0].value = htonl (n->distance);
+      (&cim->ats)[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
+      (&cim->ats)[1].value = htonl ((uint32_t) n->latency.rel_value);
+      cim->id = n->id;
+      transmit_to_client (c, &cim->header, GNUNET_NO);
+    }
+  GNUNET_free (cim);
+  return GNUNET_OK;
+}
+
+
 /**
  * Handle START-message.  This is the first message sent to us
  * by any client which causes us to add it to our list.
@@ -5499,10 +5577,6 @@ handle_start (void *cls,
 {
   const struct StartMessage *start;
   struct TransportClient *c;
-  struct ConnectInfoMessage * cim;
-  struct NeighbourList *n;
-  uint32_t ats_count;
-  size_t size;
 
   start = (const struct StartMessage*) message;
 #if DEBUG_TRANSPORT
@@ -5546,33 +5620,9 @@ handle_start (void *cls,
                           (const struct GNUNET_MessageHeader *) our_hello,
                           GNUNET_NO);
       /* tell new client about all existing connections */
-      ats_count = 2;
-      size  = sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
-      if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
-       {
-         GNUNET_break(0);
-       }
-      cim = GNUNET_malloc (size);
-      cim->header.size = htons (size);
-      cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
-      cim->ats_count = htonl(ats_count);
-      (&(cim->ats))[2].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
-      (&(cim->ats))[2].value = htonl (0);
-      n = neighbours;
-      while (n != NULL)
-       {
-         if (GNUNET_YES == n->received_pong)
-           {
-             (&(cim->ats))[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
-             (&(cim->ats))[0].value = htonl (n->distance);
-             (&(cim->ats))[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
-             (&(cim->ats))[1].value = htonl ((uint32_t) n->latency.rel_value);
-             cim->id = n->id;
-             transmit_to_client (c, &cim->header, GNUNET_NO);
-           }
-         n = n->next;
-       }
-      GNUNET_free (cim);
+      GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+                                            &notify_client_about_neighbour,
+                                            c);
     }
   else
     {
@@ -5645,7 +5695,7 @@ struct TransmitClientMessageContext
  */
 static void
 transmit_client_message (void *cls,
-                        struct NeighbourList *n)
+                        struct NeighbourMapEntry *n)
 {
   struct TransmitClientMessageContext *tcmc = cls;
   struct TransportClient *tc;
@@ -5765,7 +5815,7 @@ handle_set_quota (void *cls,
 {
   const struct QuotaSetMessage *qsm =
     (const struct QuotaSetMessage *) message;
-  struct NeighbourList *n;
+  struct NeighbourMapEntry *n;
 
   GNUNET_STATISTICS_update (stats,
                            gettext_noop ("# SET QUOTA messages received"),
@@ -5829,6 +5879,8 @@ transmit_address_to_client (void *cls, const char *address)
     }
   else
     {
+      GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
+                                                 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
       GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
     }
 }
@@ -5852,7 +5904,6 @@ handle_address_lookup (void *cls,
   const char *address;
   uint16_t size;
   struct GNUNET_SERVER_TransmitContext *tc;
-  struct GNUNET_TIME_Absolute timeout;
   struct GNUNET_TIME_Relative rtimeout;
   int32_t numeric;
 
@@ -5880,8 +5931,7 @@ handle_address_lookup (void *cls,
       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
       return;
     }
-  timeout = GNUNET_TIME_absolute_ntoh (alum->timeout);
-  rtimeout = GNUNET_TIME_absolute_get_remaining (timeout);
+  rtimeout = GNUNET_TIME_relative_ntoh (alum->timeout);
   numeric = ntohl (alum->numeric_only);
   lsPlugin = find_transport (nameTransport);
   if (NULL == lsPlugin)
@@ -5915,14 +5965,13 @@ handle_peer_address_lookup (void *cls,
                        const struct GNUNET_MessageHeader *message)
 {
   const struct PeerAddressLookupMessage *peer_address_lookup;
-  struct NeighbourList *neighbor_iterator;
+  struct NeighbourMapEntry *neighbor_iterator;
   struct ReadyList *ready_iterator;
   struct ForeignAddressList *foreign_address_iterator;
   struct TransportPlugin *transport_plugin;
 
   uint16_t size;
   struct GNUNET_SERVER_TransmitContext *tc;
-  struct GNUNET_TIME_Absolute timeout;
   struct GNUNET_TIME_Relative rtimeout;
   char *addr_buf;
 
@@ -5935,16 +5984,9 @@ handle_peer_address_lookup (void *cls,
     }
   peer_address_lookup = (const struct PeerAddressLookupMessage *) message;
 
-  timeout = GNUNET_TIME_absolute_ntoh (peer_address_lookup->timeout);
-  rtimeout = GNUNET_TIME_absolute_get_remaining (timeout);
+  rtimeout = GNUNET_TIME_relative_ntoh (peer_address_lookup->timeout);
 
-  neighbor_iterator = neighbours;
-  while (neighbor_iterator != NULL)
-    {
-      if (0 == memcmp(&neighbor_iterator->id, &peer_address_lookup->peer, sizeof(struct GNUNET_PeerIdentity)))
-        break;
-      neighbor_iterator = neighbor_iterator->next;
-    }
+  neighbor_iterator = find_neighbour (&peer_address_lookup->peer);
 
   /* Found no neighbor matching this peer id (shouldn't be possible, but...) */
   if (neighbor_iterator == NULL)
@@ -5968,7 +6010,7 @@ handle_peer_address_lookup (void *cls,
           transport_plugin = foreign_address_iterator->ready_list->plugin;
           if (foreign_address_iterator->addr != NULL)
             {
-              GNUNET_asprintf (&addr_buf, "%s --- %s",
+              GNUNET_asprintf (&addr_buf, "%s --- %s, %s",
                                a2s (transport_plugin->short_name,
                                     foreign_address_iterator->addr,
                                     foreign_address_iterator->addrlen),
@@ -5979,7 +6021,7 @@ handle_peer_address_lookup (void *cls,
                                    == GNUNET_YES) ? "VALIDATED"
                                    : "UNVALIDATED");
               transmit_address_to_client(tc, addr_buf);
-              GNUNET_free(addr_buf);
+              GNUNET_free (addr_buf);
             }
           else if (foreign_address_iterator->addrlen == 0)
             {
@@ -5991,7 +6033,7 @@ handle_peer_address_lookup (void *cls,
                                    == GNUNET_YES) ? "VALIDATED"
                                    : "UNVALIDATED");
               transmit_address_to_client (tc, addr_buf);
-              GNUNET_free(addr_buf);
+              GNUNET_free (addr_buf);
             }
 
           foreign_address_iterator = foreign_address_iterator->next;
@@ -6003,6 +6045,66 @@ handle_peer_address_lookup (void *cls,
   GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
 }
 
+
+
+static int
+output_addresses (void *cls,
+                 const GNUNET_HashCode *key,
+                 void *value)
+{
+  struct GNUNET_SERVER_TransmitContext *tc = cls;
+  struct NeighbourMapEntry *neighbor_iterator = value;
+  struct ForeignAddressList *foreign_address_iterator;
+  struct TransportPlugin *transport_plugin;
+  struct ReadyList *ready_iterator;
+  char *addr_buf;
+
+  ready_iterator = neighbor_iterator->plugins;
+  while (ready_iterator != NULL)
+    {
+      foreign_address_iterator = ready_iterator->addresses;
+      while (foreign_address_iterator != NULL)
+       {
+         transport_plugin = foreign_address_iterator->ready_list->plugin;
+         if (foreign_address_iterator->addr != NULL)
+           {
+             GNUNET_asprintf (&addr_buf, "%s:%s --- %s, %s",
+                              GNUNET_i2s(&neighbor_iterator->id),
+                              a2s (transport_plugin->short_name,
+                                   foreign_address_iterator->addr,
+                                   foreign_address_iterator->addrlen),
+                              (foreign_address_iterator->connected
+                               == GNUNET_YES) ? "CONNECTED"
+                              : "DISCONNECTED",
+                              (foreign_address_iterator->validated
+                               == GNUNET_YES) ? "VALIDATED"
+                              : "UNVALIDATED");
+             transmit_address_to_client (tc, addr_buf);
+             GNUNET_free (addr_buf);
+           }
+         else if (foreign_address_iterator->addrlen == 0)
+           {
+             GNUNET_asprintf (&addr_buf, "%s:%s --- %s, %s",
+                              GNUNET_i2s (&neighbor_iterator->id),
+                              "<inbound>",
+                              (foreign_address_iterator->connected
+                               == GNUNET_YES) ? "CONNECTED"
+                              : "DISCONNECTED",
+                              (foreign_address_iterator->validated
+                               == GNUNET_YES) ? "VALIDATED"
+                              : "UNVALIDATED");
+             transmit_address_to_client (tc, addr_buf);
+             GNUNET_free (addr_buf);
+           }
+         
+         foreign_address_iterator = foreign_address_iterator->next;
+       }
+      ready_iterator = ready_iterator->next;
+    }
+  return GNUNET_OK;
+}
+
+
 /**
  * Handle AddressIterateMessage
  *
@@ -6015,17 +6117,8 @@ handle_address_iterate (void *cls,
                         struct GNUNET_SERVER_Client *client,
                         const struct GNUNET_MessageHeader *message)
 {
-  const struct AddressIterateMessage *address_iterate;
-  struct NeighbourList *neighbor_iterator;
-  struct ReadyList *ready_iterator;
-  struct ForeignAddressList *foreign_address_iterator;
-  struct TransportPlugin *transport_plugin;
-
-  uint16_t size;
   struct GNUNET_SERVER_TransmitContext *tc;
-  struct GNUNET_TIME_Absolute timeout;
-  struct GNUNET_TIME_Relative rtimeout;
-  char *addr_buf;
+  uint16_t size;
 
   size = ntohs (message->size);
   if (size < sizeof (struct AddressIterateMessage))
@@ -6034,68 +6127,24 @@ handle_address_iterate (void *cls,
       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
       return;
     }
-  address_iterate = (const struct AddressIterateMessage *) message;
-
-  timeout = GNUNET_TIME_absolute_ntoh (address_iterate->timeout);
-  rtimeout = GNUNET_TIME_absolute_get_remaining (timeout);
-
   GNUNET_SERVER_disable_receive_done_warning (client);
   tc = GNUNET_SERVER_transmit_context_create (client);
-
-  neighbor_iterator = neighbours;
-  while (neighbor_iterator != NULL)
-    {
-      ready_iterator = neighbor_iterator->plugins;
-      while (ready_iterator != NULL)
-        {
-          foreign_address_iterator = ready_iterator->addresses;
-          while (foreign_address_iterator != NULL)
-            {
-              transport_plugin = foreign_address_iterator->ready_list->plugin;
-              if (foreign_address_iterator->addr != NULL)
-                {
-                  GNUNET_asprintf (&addr_buf, "%s:%s --- %s, %s",
-                                   GNUNET_i2s(&neighbor_iterator->id),
-                                   a2s (transport_plugin->short_name,
-                                        foreign_address_iterator->addr,
-                                        foreign_address_iterator->addrlen),
-                                   (foreign_address_iterator->connected
-                                       == GNUNET_YES) ? "CONNECTED"
-                                       : "DISCONNECTED",
-                                   (foreign_address_iterator->validated
-                                       == GNUNET_YES) ? "VALIDATED"
-                                       : "UNVALIDATED");
-                  transmit_address_to_client (tc, addr_buf);
-                  GNUNET_free(addr_buf);
-                }
-              else if (foreign_address_iterator->addrlen == 0)
-                {
-                  GNUNET_asprintf (&addr_buf, "%s:%s --- %s, %s",
-                                     GNUNET_i2s (&neighbor_iterator->id),
-                                     "<inbound>",
-                                     (foreign_address_iterator->connected
-                                         == GNUNET_YES) ? "CONNECTED"
-                                         : "DISCONNECTED",
-                                     (foreign_address_iterator->validated
-                                         == GNUNET_YES) ? "VALIDATED"
-                                         : "UNVALIDATED");
-                  transmit_address_to_client (tc, addr_buf);
-                  GNUNET_free(addr_buf);
-                }
-
-              foreign_address_iterator = foreign_address_iterator->next;
-            }
-          ready_iterator = ready_iterator->next;
-        }
-      neighbor_iterator = neighbor_iterator->next;
-    }
-
+  GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+                                        &output_addresses,
+                                        tc);
   GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
                                               GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
   GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
 }
 
 
+static const struct GNUNET_MessageHeader *
+do_get_our_hello ()
+{
+  return (const struct GNUNET_MessageHeader*) our_hello;
+}
+
+
 /**
  * Setup the environment for this plugin.
  */
@@ -6104,7 +6153,7 @@ create_environment (struct TransportPlugin *plug)
 {
   plug->env.cfg = cfg;
   plug->env.my_identity = &my_identity;
-  plug->env.our_hello = &our_hello;
+  plug->env.get_our_hello = &do_get_our_hello;
   plug->env.cls = plug;
   plug->env.receive = &plugin_env_receive;
   plug->env.notify_address = &plugin_env_notify_address;
@@ -6146,6 +6195,24 @@ start_transport (struct GNUNET_SERVER_Handle *server,
 }
 
 
+static int
+null_mq_client_pointers (void *cls,
+                        const GNUNET_HashCode *key,
+                        void *value)
+{
+  struct TransportClient *pos = cls;
+  struct NeighbourMapEntry *n = value;
+  struct MessageQueue *mq;
+
+  for (mq = n->messages_head; mq != NULL; mq = mq->next)
+    {
+      if (mq->client == pos)
+       mq->client = NULL; /* do not use anymore! */
+    }
+  return GNUNET_OK;
+}
+
+
 /**
  * Called whenever a client is disconnected.  Frees our
  * resources associated with that client.
@@ -6162,8 +6229,6 @@ client_disconnect_notification (void *cls,
   struct ClientMessageQueueEntry *mqe;
   struct Blacklisters *bl;
   struct BlacklistCheck *bc;
-  struct NeighbourList *n;
-  struct MessageQueue *mq;
 
   if (client == NULL)
     return;
@@ -6222,14 +6287,10 @@ client_disconnect_notification (void *cls,
       pos->message_count--;
       GNUNET_free (mqe);
     }
-  for (n = neighbours; n != NULL; n = n->next)
-    {
-      for (mq = n->messages_head; mq != NULL; mq = mq->next)
-       {
-         if (mq->client == pos)
-           mq->client = NULL; /* do not use anymore! */
-       }
-    }
+  if (NULL != neighbours)
+    GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+                                          &null_mq_client_pointers,
+                                          pos);
   if (prev == NULL)
     clients = pos->next;
   else
@@ -6249,6 +6310,24 @@ client_disconnect_notification (void *cls,
 }
 
 
+static int
+disconnect_all_neighbours (void *cls,
+                          const GNUNET_HashCode *key,
+                          void *value)
+{
+  struct NeighbourMapEntry *n = value;
+
+#if DEBUG_TRANSPORT
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Disconnecting peer `%4s', %s\n",
+             GNUNET_i2s(&n->id),
+             "SHUTDOWN_TASK");
+#endif
+  disconnect_neighbour (n, GNUNET_NO);
+  return GNUNET_OK;
+}
+
+
 /**
  * Function called when the service shuts down.  Unloads our plugins
  * and cancels pending validations.
@@ -6260,26 +6339,18 @@ static void
 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct TransportPlugin *plug;
-  struct TransportPlugin *tmp;
   struct OwnAddressList *al;
   struct CheckHelloValidatedContext *chvc;
 
   shutdown_in_progress = GNUNET_YES;
-  while (neighbours != NULL)
-    {
-#if DEBUG_TRANSPORT
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Disconnecting peer `%4s', %s\n", GNUNET_i2s(&neighbours->id),
-                 "SHUTDOWN_TASK");
-#endif
-      disconnect_neighbour (neighbours, GNUNET_NO);
-    }
+  GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+                                        &disconnect_all_neighbours,
+                                        NULL);
 #if DEBUG_TRANSPORT
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Transport service is unloading plugins...\n");
 #endif
-  plug = plugins;
-  while (plug != NULL)
+  while (NULL != (plug = plugins))
     {
       if (plug->address_update_task != GNUNET_SCHEDULER_NO_TASK)
        {
@@ -6294,9 +6365,8 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
           plug->addresses = al->next;
           GNUNET_free (al);
         }
-      tmp = plug->next;
+      plugins = plug->next;
       GNUNET_free (plug);
-      plug = tmp;
     }
   if (my_private_key != NULL)
     GNUNET_CRYPTO_rsa_key_free (my_private_key);
@@ -6314,8 +6384,10 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     GNUNET_SCHEDULER_cancel(ats_task);
     ats_task = GNUNET_SCHEDULER_NO_TASK;
   }
+#if HAVE_LIBGLPK
   if (ats != NULL)
     ats_shutdown (ats);
+#endif
 
   /* free 'chvc' data structure */
   while (NULL != (chvc = chvc_head))
@@ -6356,6 +6428,8 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
      explicitly!? */
   GNUNET_break (bl_head == NULL);
   GNUNET_break (bc_head == NULL);
+  GNUNET_CONTAINER_multihashmap_destroy (neighbours);
+  neighbours = NULL;
 }
 
 
@@ -6366,117 +6440,134 @@ void ats_result_cb ()
 }
 
 
-void create_ats_information ( struct ATS_peer **p,
-                              int * c_p,
-                              struct ATS_mechanism ** m,
-                              int * c_m )
+#if HAVE_LIBGLPK
+struct AtsBuildContext
 {
-#if VERBOSE_ATS
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-      "ATS requires clean address information\n");
-#endif
   struct ATS_mechanism * mechanisms;
   struct ATS_peer *peers;
+  int c_peers;
+  int c_mechs;
+};
 
-  int connected_addresses = 0;
-  int c_peers = 0;
-  int c_mechs = 0;
-  struct NeighbourList *next = neighbours;
 
-  while (next!=NULL)
-  {
-    int found_addresses = GNUNET_NO;
-    struct ReadyList *r_next = next->plugins;
-    while (r_next != NULL)
-    {
-        struct ForeignAddressList * a_next = r_next->addresses;
-        while (a_next != NULL)
+static int
+find_and_count_addresses (void *cls,
+                         const GNUNET_HashCode *key,
+                         void *value)
+{
+  struct AtsBuildContext *abc = cls;
+  struct NeighbourMapEntry *next = value;  
+  int found_addresses = GNUNET_NO;
+  
+  struct ReadyList *r_next = next->plugins;
+  while (r_next != NULL)
+    {
+      struct ForeignAddressList * a_next = r_next->addresses;
+      while (a_next != NULL)
         {
-            c_mechs++;
-            found_addresses = GNUNET_YES;
-            a_next = a_next->next;
+         abc->c_mechs++;
+         found_addresses = GNUNET_YES;
+         a_next = a_next->next;
         }
-        r_next = r_next->next;
+      r_next = r_next->next;
     }
-    if (found_addresses) c_peers++;
-    next = next->next;
-  }
+  if (found_addresses) 
+    abc->c_peers++;
+  return GNUNET_OK;
+}
+
+
+static int
+setup_ats_problem (void *cls,
+                  const GNUNET_HashCode *key,
+                  void *value)
+{
+  struct AtsBuildContext *abc = cls;
+  struct NeighbourMapEntry *next = value;  
+
+  int found_addresses = GNUNET_NO;
+  struct ReadyList *r_next = next->plugins;
+  while (r_next != NULL)
+    {
+      struct ForeignAddressList * a_next = r_next->addresses;
+      while (a_next != NULL)
+       {
+         if (found_addresses == GNUNET_NO)
+           {
+             abc->peers[abc->c_peers].peer = next->id;
+             abc->peers[abc->c_peers].m_head = NULL;
+             abc->peers[abc->c_peers].m_tail = NULL;
+             abc->peers[abc->c_peers].f = 1.0 / abc->c_mechs;
+           }
+         abc->mechanisms[abc->c_mechs].addr = a_next;
+         abc->mechanisms[abc->c_mechs].col_index = abc->c_mechs;
+         abc->mechanisms[abc->c_mechs].peer = &abc->peers[abc->c_peers];
+         abc->mechanisms[abc->c_mechs].next = NULL;
+         abc->mechanisms[abc->c_mechs].plugin = r_next->plugin;
+         abc->mechanisms[abc->c_mechs].ressources = a_next->ressources;
+         abc->mechanisms[abc->c_mechs].quality = a_next->quality;
+         GNUNET_CONTAINER_DLL_insert_tail(abc->peers[abc->c_peers].m_head,
+                                          abc->peers[abc->c_peers].m_tail,
+                                          &abc->mechanisms[abc->c_mechs]);
+         found_addresses = GNUNET_YES;
+         abc->c_mechs++;             
+         a_next = a_next->next;
+       }
+      r_next = r_next->next;
+    }
+  if (found_addresses == GNUNET_YES)
+    abc->c_peers++;
+  return GNUNET_OK;
+}
+
+
+static void
+create_ats_information ( struct ATS_peer **p,
+                        int * c_p,
+                        struct ATS_mechanism ** m,
+                        int * c_m )
+{
+  struct AtsBuildContext abc;
 
+#if VERBOSE_ATS
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+      "ATS requires clean address information\n");
+#endif
+  abc.c_peers = 0;
+  abc.c_mechs = 0;
+  GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+                                        &find_and_count_addresses,
+                                        &abc);
 #if VERBOSE_ATS
   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
       "Found %u peers with % u transport mechanisms\n", c_peers, c_mechs);
 #endif
 
-  if ((c_peers == 0) && (c_mechs == 0))
-  {
-    peers = NULL;
-    (*c_p) = 0;
-    mechanisms = NULL;
-    (*c_m) = 0;
-    return;
-  }
-
-  mechanisms = GNUNET_malloc((1+c_mechs) * sizeof (struct ATS_mechanism));
-  peers =  GNUNET_malloc((1+c_peers) * sizeof (struct ATS_peer));
-
-  c_mechs = 1;
-  c_peers = 1;
-
-  next = neighbours;
-  while (next!=NULL)
-  {
-    int found_addresses = GNUNET_NO;
-    struct ReadyList *r_next = next->plugins;
-    while (r_next != NULL)
+  if ( (abc.c_peers == 0) && (abc.c_mechs == 0) )
     {
-        struct ForeignAddressList * a_next = r_next->addresses;
-        while (a_next != NULL)
-        {
-            if (a_next->connected == GNUNET_YES)
-              connected_addresses ++;
-            if (found_addresses == GNUNET_NO)
-            {
-              peers[c_peers].peer = next->id;
-              peers[c_peers].m_head = NULL;
-              peers[c_peers].m_tail = NULL;
-              peers[c_peers].f = 1.0 / c_mechs;
-            }
-
-            mechanisms[c_mechs].addr = a_next;
-            mechanisms[c_mechs].col_index = c_mechs;
-            mechanisms[c_mechs].peer = &peers[c_peers];
-            mechanisms[c_mechs].next = NULL;
-            mechanisms[c_mechs].plugin = r_next->plugin;
-            mechanisms[c_mechs].ressources = a_next->ressources;
-            mechanisms[c_mechs].quality = a_next->quality;
-
-            GNUNET_CONTAINER_DLL_insert_tail(peers[c_peers].m_head,
-                                             peers[c_peers].m_tail,
-                                             &mechanisms[c_mechs]);
-            found_addresses = GNUNET_YES;
-            c_mechs++;
-
-            a_next = a_next->next;
-        }
-        r_next = r_next->next;
+      *p = NULL;
+      (*c_p) = 0;
+      *m = NULL;
+      (*c_m) = 0;
+      return;
     }
-    if (found_addresses == GNUNET_YES)
-        c_peers++;
-    next = next->next;
-  }
-  c_mechs--;
-  c_peers--;
-  (*c_m) = c_mechs;
-  (*c_p) = c_peers;
-  (*p) = peers;
-  (*m) = mechanisms;
-
-  GNUNET_STATISTICS_set(stats,
-                        gettext_noop ("# connected addresses"),
-                        connected_addresses,
-                        GNUNET_NO);
+
+  abc.mechanisms = GNUNET_malloc((1+abc.c_mechs) * sizeof (struct ATS_mechanism));
+  abc.peers =  GNUNET_malloc((1+abc.c_peers) * sizeof (struct ATS_peer));
+  abc.c_mechs = 1;
+  abc.c_peers = 1;
+  GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+                                        &setup_ats_problem,
+                                        &abc);
+  abc.c_mechs--;
+  abc.c_peers--;
+  (*c_m) = abc.c_mechs;
+  (*c_p) = abc.c_peers;
+  (*p) = abc.peers;
+  (*m) = abc.mechanisms;
 }
 
+
 static void
 schedule_ats (void *cls,
               const struct GNUNET_SCHEDULER_TaskContext *tc)
@@ -6506,15 +6597,19 @@ schedule_ats (void *cls,
 #if DEBUG_ATS
   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Running scheduled calculation\n");
 #endif
-  ats_calculate_bandwidth_distribution (ats, stats);
+#if HAVE_LIBGLPK
+  ats_calculate_bandwidth_distribution (ats);
+#endif
   last_ats_execution = GNUNET_TIME_absolute_get();
 
   ats_task = GNUNET_SCHEDULER_add_delayed (ats_regular_interval,
                                   &schedule_ats, ats);
 }
+#endif
+
 
 struct ForeignAddressList * get_preferred_ats_address (
-               struct NeighbourList *n)
+               struct NeighbourMapEntry *n)
 {
   // TODO get ATS prefered address
   return find_ready_address(n);
@@ -6568,6 +6663,7 @@ run (void *cls,
   cfg = c;
   stats = GNUNET_STATISTICS_create ("transport", cfg);
   validation_map = GNUNET_CONTAINER_multihashmap_create (64);
+  neighbours = GNUNET_CONTAINER_multihashmap_create (256);
   /* parse configuration */
   if ((GNUNET_OK !=
        GNUNET_CONFIGURATION_get_value_number (c,
@@ -6590,6 +6686,8 @@ run (void *cls,
        }
       GNUNET_CONTAINER_multihashmap_destroy (validation_map);
       validation_map = NULL;
+      GNUNET_CONTAINER_multihashmap_destroy (neighbours);
+      neighbours = NULL;
       return;
     }
 
@@ -6607,6 +6705,8 @@ run (void *cls,
        }
       GNUNET_CONTAINER_multihashmap_destroy (validation_map);
       validation_map = NULL;
+      GNUNET_CONTAINER_multihashmap_destroy (neighbours);
+      neighbours = NULL;
       GNUNET_free (keyfile);
       return;
     }
@@ -6625,6 +6725,8 @@ run (void *cls,
        }
       GNUNET_CONTAINER_multihashmap_destroy (validation_map);
       validation_map = NULL;
+      GNUNET_CONTAINER_multihashmap_destroy (neighbours);
+      neighbours = NULL;
       return;
     }
   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
@@ -6659,12 +6761,13 @@ run (void *cls,
   int co;
   char * section;
   unsigned long long  value;
-
+#if HAVE_LIBGLPK
   double D = 1.0;
   double U = 1.0;
   double R = 1.0;
   int v_b_min = 64000;
   int v_n_min = 5;
+#endif
 
   ats_minimum_interval = ATS_MIN_INTERVAL;
   ats_regular_interval = ATS_EXEC_INTERVAL;
@@ -6707,82 +6810,27 @@ run (void *cls,
     }
     GNUNET_free (section);
   }
-
+#if HAVE_LIBGLPK
   ats = ats_init (D, U, R, v_b_min, v_n_min,
                   ATS_MAX_ITERATIONS, ATS_MAX_EXEC_DURATION,
-                  create_ats_information,
+                  &create_ats_information,
                   ats_result_cb);
-
-  int log_problem = GNUNET_NO;
-  int log_solution = GNUNET_NO;
-  int overwrite_dump = GNUNET_NO;
-  int minimum_peers = 0;
-  int minimum_addresses = 0;
-
-  if (GNUNET_CONFIGURATION_have_value(cfg, "transport", "DUMP_MLP"))
-    log_problem = GNUNET_CONFIGURATION_get_value_yesno (cfg,
-                             "transport","DUMP_MLP");
-
-  if (GNUNET_CONFIGURATION_have_value(cfg, "transport", "DUMP_SOLUTION"))
-    log_solution = GNUNET_CONFIGURATION_get_value_yesno (cfg,
-                                  "transport","DUMP_SOLUTION");
-  if (GNUNET_CONFIGURATION_have_value(cfg, "transport", "DUMP_OVERWRITE"))
-    overwrite_dump = GNUNET_CONFIGURATION_get_value_yesno (cfg,
-                                  "transport","DUMP_OVERWRITE");
-  if (GNUNET_CONFIGURATION_have_value(cfg, "transport", "DUMP_MIN_PEERS"))
-  {
-          GNUNET_CONFIGURATION_get_value_number(cfg,
-              "transport","DUMP_MIN_PEERS", &value);
-          minimum_peers = value;
-  }
-  if (GNUNET_CONFIGURATION_have_value(cfg,
-      "transport", "DUMP_MIN_ADDRS"))
-  {
-      GNUNET_CONFIGURATION_get_value_number(cfg,
-        "transport","DUMP_MIN_ADDRS", &value);
-      minimum_addresses= value;
-  }
-  if (GNUNET_CONFIGURATION_have_value(cfg,
-      "transport", "DUMP_OVERWRITE"))
-  {
-      GNUNET_CONFIGURATION_get_value_number(cfg,
-          "transport","DUMP_OVERWRITE", &value);
-      overwrite_dump = value;
-  }
-
-  if (GNUNET_CONFIGURATION_have_value(cfg,
-      "transport", "ATS_MIN_INTERVAL"))
-  {
-      GNUNET_CONFIGURATION_get_value_number(cfg,
-          "transport","ATS_MIN_INTERVAL", &value);
-      ats_minimum_interval.rel_value = value;
-  }
-
-  if (GNUNET_CONFIGURATION_have_value(cfg,
-      "transport", "ATS_EXEC_INTERVAL"))
-  {
-      GNUNET_CONFIGURATION_get_value_number(cfg,
-          "transport","ATS_EXEC_INTERVAL", &value);
-      ats_regular_interval.rel_value = value;
-  }
-  if (GNUNET_CONFIGURATION_have_value(cfg, "transport", "ATS_MIN_INTERVAL"))
-  {
-      GNUNET_CONFIGURATION_get_value_number(cfg,
-          "transport","ATS_MIN_INTERVAL", &value);
-      ats_minimum_interval.rel_value = value;
-  }
-
   ats_set_logging_options (ats,
-                          minimum_addresses,
-                          minimum_peers,
-                          overwrite_dump,
-                          log_solution,
-                          log_problem);
-
+                          stats,
+                          cfg);
+  GNUNET_break (GNUNET_OK ==
+               GNUNET_CONFIGURATION_get_value_time (cfg,
+                                                    "transport",
+                                                    "ATS_EXEC_INTERVAL", 
+                                                    &ats_regular_interval));
+  GNUNET_break (GNUNET_OK ==
+               GNUNET_CONFIGURATION_get_value_time (cfg,
+                                                    "transport",
+                                                    "ATS_MIN_INTERVAL", 
+                                                    &ats_minimum_interval));
   if (ats != NULL)
     ats_task = GNUNET_SCHEDULER_add_now (&schedule_ats, ats);
-
-
+#endif
 
 
 #if DEBUG_TRANSPORT