fix memleak
[oweals/gnunet.git] / src / chat / gnunet-service-chat.c
index 69318e4e848ae9b98b07466df71ed0804fdb4940..ec988e8fd1d427f7d0e0cec901e26b97bb36e747 100644 (file)
@@ -20,7 +20,7 @@
 
 /**
  * @file chat/gnunet-service-chat.c
- * @brief service providing chat functionality 
+ * @brief service providing chat functionality
  * @author Christian Grothoff
  * @author Vitaly Minko
  */
@@ -33,9 +33,9 @@
 #include "gnunet_signatures.h"
 #include "chat.h"
 
-#define DEBUG_CHAT_SERVICE GNUNET_NO
+#define DEBUG_CHAT_SERVICE GNUNET_EXTRA_LOGGING
 #define MAX_TRANSMIT_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
-#define QUEUE_SIZE 16
+#define EXPECTED_NEIGHBOUR_COUNT 16
 #define MAX_ANONYMOUS_MSG_LIST_LENGTH 16
 
 
@@ -69,7 +69,7 @@ struct ChatClient
   /**
    * Hash of the public key (for convenience).
    */
-  GNUNET_HashCode id;
+  struct GNUNET_HashCode id;
 
   /**
    * Options which the client is willing to receive.
@@ -94,6 +94,19 @@ struct ChatClient
 
 };
 
+/**
+ * Information about a peer that we are connected to.
+ * We track data that is useful for determining which
+ * peers should receive our requests.
+ */
+struct ConnectedPeer
+{
+  /**
+   * The peer's identity.
+   */
+  GNUNET_PEER_Id pid;
+};
+
 /**
  * Linked list of recent anonymous messages.
  */
@@ -104,7 +117,7 @@ struct AnonymousMessage
   /**
    * Hash of the message.
    */
-  GNUNET_HashCode hash;
+  struct GNUNET_HashCode hash;
 
 };
 
@@ -122,7 +135,7 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg;
 /**
  * The identity of this host.
  */
-static const struct GNUNET_PeerIdentity *me;
+static struct GNUNET_PeerIdentity me;
 
 /**
  * Head of the list of current clients.
@@ -138,12 +151,18 @@ struct GNUNET_SERVER_NotificationContext *nc = NULL;
  * Head of the list of recent anonymous messages.
  */
 static struct AnonymousMessage *anonymous_list_head = NULL;
+
+/**
+ * Map of peer identifiers to "struct ConnectedPeer" (for that peer).
+ */
+static struct GNUNET_CONTAINER_MultiHashMap *connected_peers;
+
 
 static void
-remember_anonymous_message (const struct P2PReceiveNotificationMessage *p2p_rnmsg)
+remember_anonymous_message (const struct P2PReceiveNotificationMessage
+                            *p2p_rnmsg)
 {
-  static GNUNET_HashCode hash;
+  static struct GNUNET_HashCode hash;
   struct AnonymousMessage *anon_msg;
   struct AnonymousMessage *prev;
   int anon_list_len;
@@ -156,30 +175,30 @@ remember_anonymous_message (const struct P2PReceiveNotificationMessage *p2p_rnms
   anon_list_len = 1;
   prev = NULL;
   while ((NULL != anon_msg->next))
-    {
-      prev = anon_msg;
-      anon_msg = anon_msg->next;
-      anon_list_len++;
-    }
+  {
+    prev = anon_msg;
+    anon_msg = anon_msg->next;
+    anon_list_len++;
+  }
   if (anon_list_len == MAX_ANONYMOUS_MSG_LIST_LENGTH)
-    {
-      GNUNET_free (anon_msg);
-      if (NULL != prev)
-       prev->next = NULL;
-    }
+  {
+    GNUNET_free (anon_msg);
+    if (NULL != prev)
+      prev->next = NULL;
+  }
 }
 
 
 static int
 lookup_anonymous_message (const struct P2PReceiveNotificationMessage *p2p_rnmsg)
 {
-  static GNUNET_HashCode hash;
+  static struct GNUNET_HashCode hash;
   struct AnonymousMessage *anon_msg;
 
   GNUNET_CRYPTO_hash (p2p_rnmsg, ntohs (p2p_rnmsg->header.size), &hash);
   anon_msg = anonymous_list_head;
   while ((NULL != anon_msg) &&
-        (0 != memcmp (&anon_msg->hash, &hash, sizeof (GNUNET_HashCode))))
+         (0 != memcmp (&anon_msg->hash, &hash, sizeof (struct GNUNET_HashCode))))
     anon_msg = anon_msg->next;
   return (NULL != anon_msg);
 }
@@ -194,9 +213,7 @@ lookup_anonymous_message (const struct P2PReceiveNotificationMessage *p2p_rnmsg)
  * @return number of bytes written to buf
  */
 static size_t
-transmit_message_notification_to_peer (void *cls,
-                                      size_t size,
-                                      void *buf)
+transmit_message_notification_to_peer (void *cls, size_t size, void *buf)
 {
   struct P2PReceiveNotificationMessage *my_msg = cls;
   struct P2PReceiveNotificationMessage *m = buf;
@@ -204,17 +221,17 @@ transmit_message_notification_to_peer (void *cls,
 
 #if DEBUG_CHAT_SERVICE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Transmitting P2P message notification\n");
+              "Transmitting P2P message notification\n");
 #endif
   if (buf == NULL)
-    {
-      /* client disconnected */
+  {
+    /* client disconnected */
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Buffer is NULL, dropping the message\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Buffer is NULL, dropping the message\n");
 #endif
-      return 0;
-    }
+    return 0;
+  }
   msg_size = ntohs (my_msg->header.size);
   GNUNET_assert (size >= msg_size);
   memcpy (m, my_msg, msg_size);
@@ -226,33 +243,28 @@ transmit_message_notification_to_peer (void *cls,
 /**
  * Ask to send a message notification to the peer.
  */
-static void
-send_message_noficiation (void *cls,
-                         const struct GNUNET_PeerIdentity *peer,
-                         const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+static int
+send_message_noficiation (void *cls, const struct GNUNET_HashCode * key, void *value)
 {
   struct P2PReceiveNotificationMessage *msg = cls;
+  struct ConnectedPeer *cp = value;
+  struct GNUNET_PeerIdentity pid;
   struct P2PReceiveNotificationMessage *my_msg;
-  struct GNUNET_CORE_TransmitHandle *th;
 
-  if (NULL == peer)
-    GNUNET_free (msg);
-  else
-    {
+  GNUNET_PEER_resolve (cp->pid, &pid);
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Sending message notification to `%s'\n", GNUNET_i2s (peer));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message notification to `%s'\n",
+              GNUNET_i2s (&pid));
 #endif
-      my_msg = GNUNET_memdup (msg, ntohs (msg->header.size));
-      th = GNUNET_CORE_notify_transmit_ready (core,
-                                             1,
-                                             MAX_TRANSMIT_DELAY,
-                                             peer,
-                                             ntohs (msg->header.size),
-                                             &transmit_message_notification_to_peer,
-                                             my_msg);
-      GNUNET_assert (NULL != th);
-    }
+  my_msg = GNUNET_memdup (msg, ntohs (msg->header.size));
+  if (NULL ==
+      GNUNET_CORE_notify_transmit_ready (core, GNUNET_NO, 1, MAX_TRANSMIT_DELAY,
+                                         &pid, ntohs (msg->header.size),
+                                         &transmit_message_notification_to_peer,
+                                         my_msg))
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("Failed to queue a message notification\n"));
+  return GNUNET_YES;
 }
 
 
@@ -265,11 +277,10 @@ send_message_noficiation (void *cls,
  * @param message the actual message
  */
 static void
-handle_transmit_request (void *cls,
-                        struct GNUNET_SERVER_Client *client,
-                        const struct GNUNET_MessageHeader *message)
+handle_transmit_request (void *cls, struct GNUNET_SERVER_Client *client,
+                         const struct GNUNET_MessageHeader *message)
 {
-  static GNUNET_HashCode all_zeros;
+  static struct GNUNET_HashCode all_zeros;
   const struct TransmitRequestMessage *trmsg;
   struct ReceiveNotificationMessage *rnmsg;
   struct P2PReceiveNotificationMessage *p2p_rnmsg;
@@ -285,38 +296,38 @@ handle_transmit_request (void *cls,
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client sent a chat message\n");
   if (ntohs (message->size) <= sizeof (struct TransmitRequestMessage))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed message: wrong size\n");
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed message: wrong size\n");
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
   trmsg = (const struct TransmitRequestMessage *) message;
   msg_len = ntohs (trmsg->header.size) - sizeof (struct TransmitRequestMessage);
   is_priv = (0 != (ntohl (trmsg->msg_options) & GNUNET_CHAT_MSG_PRIVATE));
   if (is_priv)
-    {
+  {
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting the message text\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting the message text\n");
 #endif
-      GNUNET_CRYPTO_aes_create_session_key (&key);
-      msg_len = GNUNET_CRYPTO_aes_encrypt (&trmsg[1],
-                                          msg_len,
-                                          &key,
-                                          (const struct GNUNET_CRYPTO_AesInitializationVector *) INITVALUE,
-                                          encrypted_msg);
-      if (-1 == msg_len)
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     "Could not encrypt the message text\n");
-         GNUNET_break (0);
-         GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-         return;
-       }
+    GNUNET_CRYPTO_aes_create_session_key (&key);
+    msg_len =
+        GNUNET_CRYPTO_aes_encrypt (&trmsg[1], msg_len, &key,
+                                   (const struct
+                                    GNUNET_CRYPTO_AesInitializationVector *)
+                                   INITVALUE, encrypted_msg);
+    if (-1 == msg_len)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not encrypt the message text\n");
+      GNUNET_break (0);
+      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+      return;
     }
+  }
   rnmsg = GNUNET_malloc (sizeof (struct ReceiveNotificationMessage) + msg_len);
-  rnmsg->header.size = htons (sizeof (struct ReceiveNotificationMessage) +
-                             msg_len);
+  rnmsg->header.size =
+      htons (sizeof (struct ReceiveNotificationMessage) + msg_len);
   rnmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_MESSAGE_NOTIFICATION);
   rnmsg->msg_options = trmsg->msg_options;
   rnmsg->timestamp = trmsg->timestamp;
@@ -324,145 +335,141 @@ handle_transmit_request (void *cls,
   while ((NULL != pos) && (pos->client != client))
     pos = pos->next;
   if (NULL == pos)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "The client is not a member of a chat room. Client has to "
+                "join a chat room first\n");
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_free (rnmsg);
+    return;
+  }
+  room = pos->room;
+  pos->msg_sequence_number = ntohl (trmsg->sequence_number);
+  is_anon = (0 != (ntohl (trmsg->msg_options) & GNUNET_CHAT_MSG_ANONYMOUS));
+  if (is_anon)
+  {
+    memset (&rnmsg->sender, 0, sizeof (struct GNUNET_HashCode));
+    rnmsg->sequence_number = 0;
+  }
+  else
+  {
+    rnmsg->sender = pos->id;
+    rnmsg->sequence_number = trmsg->sequence_number;
+  }
+  if (is_priv)
+  {
+#if DEBUG_CHAT_SERVICE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Encrypting the session key using the public key of '%s'\n",
+                GNUNET_h2s (&trmsg->target));
+#endif
+    if (0 == memcmp (&all_zeros, &trmsg->target, sizeof (struct GNUNET_HashCode)))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "The client is not a member of a chat room. Client has to "
-                 "join a chat room first\n");
+                  "Malformed message: private, but no target\n");
       GNUNET_break (0);
       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
       GNUNET_free (rnmsg);
       return;
     }
-  room = pos->room;
-  pos->msg_sequence_number = ntohl (trmsg->sequence_number);
-  is_anon = (0 != (ntohl (trmsg->msg_options) & GNUNET_CHAT_MSG_ANONYMOUS));
-  if (is_anon)
+    memcpy (&rnmsg[1], encrypted_msg, msg_len);
+    target = client_list_head;
+    while ((NULL != target) &&
+           (0 !=
+            memcmp (&target->id, &trmsg->target, sizeof (struct GNUNET_HashCode))))
+      target = target->next;
+    if (NULL == target)
     {
-    memset (&rnmsg->sender, 0, sizeof (GNUNET_HashCode));
-      rnmsg->sequence_number = 0;
-    }
-  else
-    {
-      rnmsg->sender = pos->id;
-      rnmsg->sequence_number = trmsg->sequence_number;
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Unknown target of the private message\n");
+      GNUNET_break (0);
+      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+      GNUNET_free (rnmsg);
+      return;
     }
-  if (is_priv)
+    if (GNUNET_SYSERR ==
+        GNUNET_CRYPTO_rsa_encrypt (&key,
+                                   sizeof (struct GNUNET_CRYPTO_AesSessionKey),
+                                   &target->public_key, &rnmsg->encrypted_key))
     {
-#if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Encrypting the session key using the public key of '%s'\n",
-                 GNUNET_h2s (&trmsg->target));
-#endif
-      if (0 == memcmp (&all_zeros, &trmsg->target, sizeof (GNUNET_HashCode)))
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     "Malformed message: private, but no target\n");
-         GNUNET_break (0);
-         GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-         GNUNET_free (rnmsg);
-         return;
-       }
-      memcpy (&rnmsg[1], encrypted_msg, msg_len);
-      target = client_list_head;
-      while ((NULL != target) &&
-            (0 != memcmp (&target->id,
-                          &trmsg->target,
-                          sizeof (GNUNET_HashCode))))
-       target = target->next;
-      if (NULL == target)
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     "Unknown target of the private message\n");
-         GNUNET_break (0);
-         GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-         GNUNET_free (rnmsg);
-         return;
-       }
-      if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_encrypt (&key,
-                                                     sizeof (struct GNUNET_CRYPTO_AesSessionKey),
-                                                     &target->public_key,
-                                                     &rnmsg->encrypted_key))
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     "Could not encrypt the session key\n");
-         GNUNET_break (0);
-         GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-         GNUNET_free (rnmsg);
-         return;
-       }
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not encrypt the session key\n");
+      GNUNET_break (0);
+      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+      GNUNET_free (rnmsg);
+      return;
     }
+  }
   else
-    {
-      memcpy (&rnmsg[1], &trmsg[1], msg_len);
-    }
+  {
+    memcpy (&rnmsg[1], &trmsg[1], msg_len);
+  }
   pos = client_list_head;
 #if DEBUG_CHAT_SERVICE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message to local room members\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending message to local room members\n");
 #endif
   while (NULL != pos)
+  {
+    if ((0 == strcmp (room, pos->room)) && (NULL != pos->client) &&
+        (pos->client != client))
     {
-      if ((0 == strcmp (room, pos->room)) &&
-         (NULL != pos->client) &&
-         (pos->client != client))
-       {
-         if (((!is_priv) ||
-              (0 == memcmp (&trmsg->target,
-                            &pos->id,
-                            sizeof (GNUNET_HashCode)))) &&
-             (0 == (ntohl (trmsg->msg_options) & (~pos->msg_options))))
-           {
-             GNUNET_SERVER_notification_context_unicast (nc,
-                                                         pos->client,
-                                                         &rnmsg->header,
-                                                         GNUNET_NO);
-           }
-       }
-      pos = pos->next;
+      if (((!is_priv) ||
+           (0 == memcmp (&trmsg->target, &pos->id, sizeof (struct GNUNET_HashCode))))
+          && (0 == (ntohl (trmsg->msg_options) & (~pos->msg_options))))
+      {
+        GNUNET_SERVER_notification_context_unicast (nc, pos->client,
+                                                    &rnmsg->header, GNUNET_NO);
+      }
     }
+    pos = pos->next;
+  }
 #if DEBUG_CHAT_SERVICE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Broadcasting message to neighbour peers\n");
+              "Broadcasting message to neighbour peers\n");
 #endif
   if (is_anon)
-    {
-      room_len = strlen (room);
-      p2p_rnmsg = GNUNET_malloc (sizeof (struct P2PReceiveNotificationMessage) +
-                                msg_len + room_len);
-      p2p_rnmsg->header.size =
-       htons (sizeof (struct P2PReceiveNotificationMessage) + msg_len +
-              room_len);
-      p2p_rnmsg->room_name_len = htons (room_len);
-      memcpy ((char *) &p2p_rnmsg[1], room, room_len);
-      memcpy ((char *) &p2p_rnmsg[1] + room_len, &trmsg[1], msg_len);
-    }
+  {
+    room_len = strlen (room);
+    p2p_rnmsg =
+        GNUNET_malloc (sizeof (struct P2PReceiveNotificationMessage) + msg_len +
+                       room_len);
+    p2p_rnmsg->header.size =
+        htons (sizeof (struct P2PReceiveNotificationMessage) + msg_len +
+               room_len);
+    p2p_rnmsg->room_name_len = htons (room_len);
+    memcpy ((char *) &p2p_rnmsg[1], room, room_len);
+    memcpy ((char *) &p2p_rnmsg[1] + room_len, &trmsg[1], msg_len);
+  }
   else
-    {
-  p2p_rnmsg = GNUNET_malloc (sizeof (struct P2PReceiveNotificationMessage) +
-                            msg_len);
-      p2p_rnmsg->header.size =
-       htons (sizeof (struct P2PReceiveNotificationMessage) + msg_len);
-      if (is_priv)
+  {
+    p2p_rnmsg =
+        GNUNET_malloc (sizeof (struct P2PReceiveNotificationMessage) + msg_len);
+    p2p_rnmsg->header.size =
+        htons (sizeof (struct P2PReceiveNotificationMessage) + msg_len);
+    if (is_priv)
     {
       memcpy (&p2p_rnmsg[1], encrypted_msg, msg_len);
-      memcpy (&p2p_rnmsg->encrypted_key,
-             &rnmsg->encrypted_key,
-             sizeof (struct GNUNET_CRYPTO_RsaEncryptedData));
+      memcpy (&p2p_rnmsg->encrypted_key, &rnmsg->encrypted_key,
+              sizeof (struct GNUNET_CRYPTO_RsaEncryptedData));
     }
-  else
+    else
       memcpy (&p2p_rnmsg[1], &trmsg[1], msg_len);
-    }
-  p2p_rnmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_P2P_MESSAGE_NOTIFICATION);
+  }
+  p2p_rnmsg->header.type =
+      htons (GNUNET_MESSAGE_TYPE_CHAT_P2P_MESSAGE_NOTIFICATION);
   p2p_rnmsg->msg_options = trmsg->msg_options;
   p2p_rnmsg->sequence_number = trmsg->sequence_number;
   p2p_rnmsg->timestamp = trmsg->timestamp;
-  p2p_rnmsg->reserved = 0;
+  p2p_rnmsg->reserved = htons (0);
   p2p_rnmsg->sender = rnmsg->sender;
   p2p_rnmsg->target = trmsg->target;
   if (is_anon)
     remember_anonymous_message (p2p_rnmsg);
-  GNUNET_CORE_iterate_peers (cfg,
-                            &send_message_noficiation,
-                            p2p_rnmsg);
+  GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
+                                         &send_message_noficiation, p2p_rnmsg);
+  GNUNET_free (p2p_rnmsg);
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
   GNUNET_free (rnmsg);
 }
@@ -477,9 +484,7 @@ handle_transmit_request (void *cls,
  * @return number of bytes written to buf
  */
 static size_t
-transmit_join_notification_to_peer (void *cls,
-                                   size_t size,
-                                   void *buf)
+transmit_join_notification_to_peer (void *cls, size_t size, void *buf)
 {
   struct ChatClient *entry = cls;
   struct P2PJoinNotificationMessage *m = buf;
@@ -489,8 +494,7 @@ transmit_join_notification_to_peer (void *cls,
   char *roomptr;
 
 #if DEBUG_CHAT_SERVICE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Transmitting P2P join notification\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting P2P join notification\n");
 #endif
   room_len = strlen (entry->room);
   meta_len = entry->meta_len;
@@ -503,6 +507,7 @@ transmit_join_notification_to_peer (void *cls,
   m->msg_options = htonl (entry->msg_options);
   m->room_name_len = htons (room_len);
   m->reserved = htons (0);
+  m->reserved2 = htonl (0);
   m->public_key = entry->public_key;
   roomptr = (char *) &m[1];
   memcpy (roomptr, entry->room, room_len);
@@ -515,33 +520,30 @@ transmit_join_notification_to_peer (void *cls,
 /**
  * Ask to send a join notification to the peer.
  */
-static void
-send_join_noficiation (void *cls,
-                      const struct GNUNET_PeerIdentity *peer,
-                      const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+static int
+send_join_noficiation (void *cls, const struct GNUNET_HashCode * key, void *value)
 {
   struct ChatClient *entry = cls;
-  struct GNUNET_CORE_TransmitHandle *th;
+  struct ConnectedPeer *cp = value;
+  struct GNUNET_PeerIdentity pid;
   size_t msg_size;
 
-  if (NULL != peer)
-    {
+  GNUNET_PEER_resolve (cp->pid, &pid);
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Sending join notification to `%s'\n", GNUNET_i2s (peer));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending join notification to `%s'\n",
+              GNUNET_i2s (&pid));
 #endif
-      msg_size = sizeof (struct P2PJoinNotificationMessage) +
-       strlen (entry->room) + 
-       entry->meta_len;
-      th = GNUNET_CORE_notify_transmit_ready (core,
-                                             1,
-                                             MAX_TRANSMIT_DELAY,
-                                             peer,
-                                             msg_size,
-                                             &transmit_join_notification_to_peer,
-                                             entry);
-      GNUNET_assert (NULL != th);
-    }
+  msg_size =
+      sizeof (struct P2PJoinNotificationMessage) + strlen (entry->room) +
+      entry->meta_len;
+  if (NULL ==
+      GNUNET_CORE_notify_transmit_ready (core, GNUNET_NO, 1, MAX_TRANSMIT_DELAY,
+                                         &pid, msg_size,
+                                         &transmit_join_notification_to_peer,
+                                         entry))
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("Failed to queue a join notification\n"));
+  return GNUNET_YES;
 }
 
 
@@ -554,9 +556,8 @@ send_join_noficiation (void *cls,
  * @param message the actual message
  */
 static void
-handle_join_request (void *cls,
-                    struct GNUNET_SERVER_Client *client,
-                    const struct GNUNET_MessageHeader *message)
+handle_join_request (void *cls, struct GNUNET_SERVER_Client *client,
+                     const struct GNUNET_MessageHeader *message)
 {
   const struct JoinRequestMessage *jrmsg;
   char *room_name;
@@ -571,26 +572,24 @@ handle_join_request (void *cls,
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client sent a join request\n");
   if (ntohs (message->size) <= sizeof (struct JoinRequestMessage))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed message: wrong size\n");
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed message: wrong size\n");
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
   jrmsg = (const struct JoinRequestMessage *) message;
   header_size = ntohs (jrmsg->header.size);
   room_name_len = ntohs (jrmsg->room_name_len);
-  if (header_size - sizeof (struct JoinRequestMessage) <=
-      room_name_len)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "Malformed message: wrong length of the room name\n");
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
-  meta_len =
-    header_size - sizeof (struct JoinRequestMessage) - room_name_len;
+  if (header_size - sizeof (struct JoinRequestMessage) <= room_name_len)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed message: wrong length of the room name\n");
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  meta_len = header_size - sizeof (struct JoinRequestMessage) - room_name_len;
   roomptr = (const char *) &jrmsg[1];
   room_name = GNUNET_malloc (room_name_len + 1);
   memcpy (room_name, roomptr, room_name_len);
@@ -602,69 +601,64 @@ handle_join_request (void *cls,
   new_entry->public_key = jrmsg->public_key;
   new_entry->meta_len = meta_len;
   if (meta_len > 0)
-    {
-      new_entry->member_info = GNUNET_malloc (meta_len);
-      memcpy (new_entry->member_info, &roomptr[room_name_len], meta_len);
-    }
+  {
+    new_entry->member_info = GNUNET_malloc (meta_len);
+    memcpy (new_entry->member_info, &roomptr[room_name_len], meta_len);
+  }
   else
     new_entry->member_info = NULL;
   GNUNET_CRYPTO_hash (&new_entry->public_key,
-                     sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                     &new_entry->id);
+                      sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                      &new_entry->id);
   new_entry->msg_options = ntohl (jrmsg->msg_options);
   new_entry->next = client_list_head;
   client_list_head = new_entry;
 #if DEBUG_CHAT_SERVICE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Synchronizing room members between local clients\n");
+              "Synchronizing room members between local clients\n");
 #endif
   jnmsg = GNUNET_malloc (sizeof (struct JoinNotificationMessage) + meta_len);
   jnmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_JOIN_NOTIFICATION);
   jnmsg->header.size =
-    htons (sizeof (struct JoinNotificationMessage) + meta_len);
+      htons (sizeof (struct JoinNotificationMessage) + meta_len);
   jnmsg->msg_options = jrmsg->msg_options;
   jnmsg->public_key = new_entry->public_key;
   memcpy (&jnmsg[1], &roomptr[room_name_len], meta_len);
   GNUNET_SERVER_notification_context_add (nc, client);
   entry = client_list_head;
   while (NULL != entry)
+  {
+    if (0 == strcmp (room_name, entry->room))
     {
-      if (0 == strcmp (room_name, entry->room))
-       {
-         if (NULL != entry->client)
-           GNUNET_SERVER_notification_context_unicast (nc,
-                                                       entry->client,
-                                                       &jnmsg->header,
-                                                       GNUNET_NO);
-         if (entry->client != client)
-           {
-             entry_jnmsg =
-               GNUNET_malloc (sizeof (struct JoinNotificationMessage) +
-                              entry->meta_len);
-             entry_jnmsg->header.type =
-               htons (GNUNET_MESSAGE_TYPE_CHAT_JOIN_NOTIFICATION);
-             entry_jnmsg->header.size =
-               htons (sizeof (struct JoinNotificationMessage) +
-                      entry->meta_len);
-             entry_jnmsg->msg_options = entry->msg_options;
-             entry_jnmsg->public_key = entry->public_key;
-             memcpy (&entry_jnmsg[1], entry->member_info, entry->meta_len);
-             GNUNET_SERVER_notification_context_unicast (nc,
-                                                         client,
-                                                         &entry_jnmsg->header,
-                                                         GNUNET_NO);
-             GNUNET_free (entry_jnmsg);
-           }
-       }
-      entry = entry->next;
+      if (NULL != entry->client)
+        GNUNET_SERVER_notification_context_unicast (nc, entry->client,
+                                                    &jnmsg->header, GNUNET_NO);
+      if (entry->client != client)
+      {
+        entry_jnmsg =
+            GNUNET_malloc (sizeof (struct JoinNotificationMessage) +
+                           entry->meta_len);
+        entry_jnmsg->header.type =
+            htons (GNUNET_MESSAGE_TYPE_CHAT_JOIN_NOTIFICATION);
+        entry_jnmsg->header.size =
+            htons (sizeof (struct JoinNotificationMessage) + entry->meta_len);
+        entry_jnmsg->msg_options = entry->msg_options;
+        entry_jnmsg->public_key = entry->public_key;
+        memcpy (&entry_jnmsg[1], entry->member_info, entry->meta_len);
+        GNUNET_SERVER_notification_context_unicast (nc, client,
+                                                    &entry_jnmsg->header,
+                                                    GNUNET_NO);
+        GNUNET_free (entry_jnmsg);
+      }
     }
+    entry = entry->next;
+  }
 #if DEBUG_CHAT_SERVICE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Broadcasting join notification to neighbour peers\n");
+              "Broadcasting join notification to neighbour peers\n");
 #endif
-  GNUNET_CORE_iterate_peers (cfg,
-                            &send_join_noficiation,
-                            new_entry);
+  GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
+                                         &send_join_noficiation, new_entry);
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
   GNUNET_free (jnmsg);
 }
@@ -678,27 +672,25 @@ handle_join_request (void *cls,
  * @return number of bytes written to buf
  */
 static size_t
-transmit_confirmation_receipt_to_peer (void *cls,
-                                      size_t size,
-                                      void *buf)
+transmit_confirmation_receipt_to_peer (void *cls, size_t size, void *buf)
 {
   struct P2PConfirmationReceiptMessage *receipt = cls;
   size_t msg_size;
 
 #if DEBUG_CHAT_SERVICE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Transmitting P2P confirmation receipt to '%s'\n",
-             GNUNET_h2s (&receipt->target));
+              "Transmitting P2P confirmation receipt to '%s'\n",
+              GNUNET_h2s (&receipt->target));
 #endif
   if (buf == NULL)
-    {
-      /* client disconnected */
+  {
+    /* client disconnected */
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Buffer is NULL, dropping the message\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Buffer is NULL, dropping the message\n");
 #endif
-      return 0;
-    }
+    return 0;
+  }
   msg_size = sizeof (struct P2PConfirmationReceiptMessage);
   GNUNET_assert (size >= msg_size);
   memcpy (buf, receipt, msg_size);
@@ -710,36 +702,31 @@ transmit_confirmation_receipt_to_peer (void *cls,
 /**
  * Ask to send a confirmation receipt to the peer.
  */
-static void
-send_confirmation_receipt (void *cls,
-                          const struct GNUNET_PeerIdentity *peer,
-                          const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+static int
+send_confirmation_receipt (void *cls, const struct GNUNET_HashCode * key, void *value)
 {
   struct P2PConfirmationReceiptMessage *receipt = cls;
+  struct ConnectedPeer *cp = value;
+  struct GNUNET_PeerIdentity pid;
   struct P2PConfirmationReceiptMessage *my_receipt;
-  struct GNUNET_CORE_TransmitHandle *th;
   size_t msg_size;
 
-  if (NULL == peer)
-    GNUNET_free (receipt);
-  else
-    {
+  GNUNET_PEER_resolve (cp->pid, &pid);
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Sending confirmation receipt to `%s'\n", GNUNET_i2s (peer));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending confirmation receipt to `%s'\n",
+              GNUNET_i2s (&pid));
 #endif
-      msg_size = sizeof (struct P2PConfirmationReceiptMessage);
-      my_receipt = GNUNET_memdup (receipt,
-                                 sizeof (struct P2PConfirmationReceiptMessage));
-      th = GNUNET_CORE_notify_transmit_ready (core,
-                                             1,
-                                             MAX_TRANSMIT_DELAY,
-                                             peer,
-                                             msg_size,
-                                             &transmit_confirmation_receipt_to_peer,
-                                             my_receipt);
-      GNUNET_assert (NULL != th);
-    }
+  msg_size = sizeof (struct P2PConfirmationReceiptMessage);
+  my_receipt =
+      GNUNET_memdup (receipt, sizeof (struct P2PConfirmationReceiptMessage));
+  if (NULL ==
+      GNUNET_CORE_notify_transmit_ready (core, GNUNET_YES, 1,
+                                         MAX_TRANSMIT_DELAY, &pid, msg_size,
+                                         &transmit_confirmation_receipt_to_peer,
+                                         my_receipt))
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("Failed to queue a confirmation receipt\n"));
+  return GNUNET_YES;
 }
 
 
@@ -753,9 +740,8 @@ send_confirmation_receipt (void *cls,
  * @param message the actual message
  */
 static void
-handle_acknowledge_request (void *cls,
-                           struct GNUNET_SERVER_Client *client,
-                           const struct GNUNET_MessageHeader *message)
+handle_acknowledge_request (void *cls, struct GNUNET_SERVER_Client *client,
+                            const struct GNUNET_MessageHeader *message)
 {
   const struct ConfirmationReceiptMessage *receipt;
   struct ConfirmationReceiptMessage *crmsg;
@@ -767,85 +753,85 @@ handle_acknowledge_request (void *cls,
   receipt = (const struct ConfirmationReceiptMessage *) message;
   author = client_list_head;
   while ((NULL != author) &&
-        (0 != memcmp (&receipt->author,
-                      &author->id,
-                      sizeof (GNUNET_HashCode))))
+         (0 !=
+          memcmp (&receipt->author, &author->id, sizeof (struct GNUNET_HashCode))))
     author = author->next;
   if (NULL == author)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "Unknown author of the original message\n");
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unknown author of the original message\n");
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
   target = client_list_head;
   while ((NULL != target) &&
-        (0 != memcmp (&receipt->target,
-                      &target->id,
-                      sizeof (GNUNET_HashCode))))
+         (0 !=
+          memcmp (&receipt->target, &target->id, sizeof (struct GNUNET_HashCode))))
     target = target->next;
   if (NULL == target)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "Unknown target of the confirmation receipt\n");
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unknown target of the confirmation receipt\n");
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
   if (NULL == author->client)
-    {
-      target->rcpt_sequence_number++;
+  {
+    target->rcpt_sequence_number++;
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Broadcasting %s's receipt #%u to neighbour peers\n",
-                 GNUNET_h2s (&target->id), target->rcpt_sequence_number);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Broadcasting %s's receipt #%u to neighbour peers\n",
+                GNUNET_h2s (&target->id), target->rcpt_sequence_number);
 #endif
-      p2p_crmsg = GNUNET_malloc (sizeof (struct P2PConfirmationReceiptMessage));
-      p2p_crmsg->header.size = htons (sizeof (struct P2PConfirmationReceiptMessage));
-      p2p_crmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_P2P_CONFIRMATION_RECEIPT);
-      p2p_crmsg->signature = receipt->signature;
-      p2p_crmsg->purpose = receipt->purpose;
-      p2p_crmsg->msg_sequence_number = receipt->sequence_number;
-      p2p_crmsg->timestamp = receipt->timestamp;
-      p2p_crmsg->target = receipt->target;
-      p2p_crmsg->author = receipt->author;
-      p2p_crmsg->content = receipt->content;
-      p2p_crmsg->sequence_number = htonl (target->rcpt_sequence_number);
-      GNUNET_CORE_iterate_peers (cfg,
-                                &send_confirmation_receipt,
-                                p2p_crmsg);
-    }
+    p2p_crmsg = GNUNET_malloc (sizeof (struct P2PConfirmationReceiptMessage));
+    p2p_crmsg->header.size =
+        htons (sizeof (struct P2PConfirmationReceiptMessage));
+    p2p_crmsg->header.type =
+        htons (GNUNET_MESSAGE_TYPE_CHAT_P2P_CONFIRMATION_RECEIPT);
+    p2p_crmsg->reserved = htonl (0);
+    p2p_crmsg->signature = receipt->signature;
+    p2p_crmsg->purpose = receipt->purpose;
+    p2p_crmsg->msg_sequence_number = receipt->sequence_number;
+    p2p_crmsg->timestamp = receipt->timestamp;
+    p2p_crmsg->target = receipt->target;
+    p2p_crmsg->author = receipt->author;
+    p2p_crmsg->content = receipt->content;
+    p2p_crmsg->sequence_number = htonl (target->rcpt_sequence_number);
+    GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
+                                           &send_confirmation_receipt,
+                                           p2p_crmsg);
+    GNUNET_free (p2p_crmsg);
+  }
   else
-    {
+  {
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Verifying signature of the receipt\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Verifying signature of the receipt\n");
 #endif
-      if (GNUNET_OK !=
-         GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_CHAT_RECEIPT,
-                                   &receipt->purpose,
-                                   &receipt->signature,
-                                   &target->public_key))
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     "Invalid signature of the receipt\n");
-         GNUNET_break (0);
-         GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-         return;
-       }
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_CHAT_RECEIPT,
+                                  &receipt->purpose, &receipt->signature,
+                                  &target->public_key))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Invalid signature of the receipt\n");
+      GNUNET_break (0);
+      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+      return;
+    }
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Sending receipt to the client which sent the original message\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Sending receipt to the client which sent the original message\n");
 #endif
-      crmsg = GNUNET_memdup (receipt, sizeof (struct ConfirmationReceiptMessage));
-      crmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_CONFIRMATION_NOTIFICATION);
-      GNUNET_SERVER_notification_context_unicast (nc,
-                                                 author->client,
-                                                 &crmsg->header,
-                                                 GNUNET_NO);
-      GNUNET_free (crmsg);
-    }
+    crmsg = GNUNET_memdup (receipt, sizeof (struct ConfirmationReceiptMessage));
+    crmsg->header.type =
+        htons (GNUNET_MESSAGE_TYPE_CHAT_CONFIRMATION_NOTIFICATION);
+    GNUNET_SERVER_notification_context_unicast (nc, author->client,
+                                                &crmsg->header, GNUNET_NO);
+    GNUNET_free (crmsg);
+  }
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
 }
 
@@ -860,33 +846,30 @@ handle_acknowledge_request (void *cls,
  * @return number of bytes written to buf
  */
 static size_t
-transmit_leave_notification_to_peer (void *cls,
-                                    size_t size,
-                                    void *buf)
+transmit_leave_notification_to_peer (void *cls, size_t size, void *buf)
 {
   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key = cls;
   struct P2PLeaveNotificationMessage *m = buf;
   size_t msg_size;
 
 #if DEBUG_CHAT_SERVICE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Transmitting P2P leave notification\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting P2P leave notification\n");
 #endif
   if (buf == NULL)
-    {
-      /* client disconnected */
+  {
+    /* client disconnected */
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Buffer is NULL, dropping the message\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Buffer is NULL, dropping the message\n");
 #endif
-      return 0;
-    }
+    return 0;
+  }
   msg_size = sizeof (struct P2PLeaveNotificationMessage);
   GNUNET_assert (size >= msg_size);
   m = buf;
   m->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_P2P_LEAVE_NOTIFICATION);
   m->header.size = htons (msg_size);
-  m->reserved = htons (0);
+  m->reserved = htonl (0);
   m->user = *public_key;
   GNUNET_free (public_key);
   return msg_size;
@@ -896,40 +879,32 @@ transmit_leave_notification_to_peer (void *cls,
 /**
  * Ask to send a leave notification to the peer.
  */
-static void
-send_leave_noficiation (void *cls,
-                       const struct GNUNET_PeerIdentity *peer,
-                       const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+static int
+send_leave_noficiation (void *cls, const struct GNUNET_HashCode * key, void *value)
 {
   struct ChatClient *entry = cls;
+  struct ConnectedPeer *cp = value;
+  struct GNUNET_PeerIdentity pid;
   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key;
   size_t msg_size;
 
-  if (NULL == peer)
-    {
-      GNUNET_free (entry->room);
-      GNUNET_free_non_null (entry->member_info);
-      GNUNET_free (entry);
-    }
-  else
-    {
+  GNUNET_PEER_resolve (cp->pid, &pid);
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Sending leave notification to `%s'\n", GNUNET_i2s (peer));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending leave notification to `%s'\n",
+              GNUNET_i2s (&pid));
 #endif
-      msg_size = sizeof (struct P2PLeaveNotificationMessage);
-      public_key = GNUNET_memdup (&entry->public_key,
-                                 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
-      if (NULL == GNUNET_CORE_notify_transmit_ready (core,
-                                             1,
-                                             MAX_TRANSMIT_DELAY,
-                                             peer,
-                                             msg_size,
-                                             &transmit_leave_notification_to_peer,
-                                                    public_key))
-       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                   _("Failed to queue a leave notification\n"));
-    }
+  msg_size = sizeof (struct P2PLeaveNotificationMessage);
+  public_key =
+      GNUNET_memdup (&entry->public_key,
+                     sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
+  if (NULL ==
+      GNUNET_CORE_notify_transmit_ready (core, GNUNET_YES, 1,
+                                         MAX_TRANSMIT_DELAY, &pid, msg_size,
+                                         &transmit_leave_notification_to_peer,
+                                         public_key))
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("Failed to queue a leave notification\n"));
+  return GNUNET_YES;
 }
 
 
@@ -941,8 +916,7 @@ send_leave_noficiation (void *cls,
  * @param client identification of the client
  */
 static void
-handle_client_disconnect (void *cls,
-                         struct GNUNET_SERVER_Client *client)
+handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
 {
   struct ChatClient *entry;
   struct ChatClient *pos;
@@ -953,18 +927,18 @@ handle_client_disconnect (void *cls,
   pos = client_list_head;
   prev = NULL;
   while ((NULL != pos) && (pos->client != client))
-    {
-      prev = pos;
-      pos = pos->next;
-    }
+  {
+    prev = pos;
+    pos = pos->next;
+  }
   if (NULL == pos)
-    {
+  {
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "No such client. There is nothing to do\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "No such client. There is nothing to do\n");
 #endif
-      return;
-    }
+    return;
+  }
   if (NULL == prev)
     client_list_head = pos->next;
   else
@@ -972,31 +946,30 @@ handle_client_disconnect (void *cls,
   entry = client_list_head;
 #if DEBUG_CHAT_SERVICE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Notifying local room members that the client has disconnected\n");
+              "Notifying local room members that the client has disconnected\n");
 #endif
   lnmsg.header.size = htons (sizeof (struct LeaveNotificationMessage));
   lnmsg.header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_LEAVE_NOTIFICATION);
   lnmsg.reserved = htonl (0);
   lnmsg.user = pos->public_key;
   while (NULL != entry)
+  {
+    if ((0 == strcmp (pos->room, entry->room)) && (NULL != entry->client))
     {
-      if ((0 == strcmp (pos->room, entry->room)) &&
-         (NULL != entry->client))
-       {
-         GNUNET_SERVER_notification_context_unicast (nc,
-                                                     entry->client,
-                                                     &lnmsg.header,
-                                                     GNUNET_NO);
-       }
-      entry = entry->next;
+      GNUNET_SERVER_notification_context_unicast (nc, entry->client,
+                                                  &lnmsg.header, GNUNET_NO);
     }
+    entry = entry->next;
+  }
 #if DEBUG_CHAT_SERVICE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Broadcasting leave notification to neighbour peers\n");
+              "Broadcasting leave notification to neighbour peers\n");
 #endif
-  GNUNET_CORE_iterate_peers (cfg,
-                            &send_leave_noficiation,
-                            pos);
+  GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
+                                         &send_leave_noficiation, pos);
+  GNUNET_free (pos->room);
+  GNUNET_free_non_null (pos->member_info);
+  GNUNET_free (pos);
 }
 
 
@@ -1007,14 +980,16 @@ handle_client_disconnect (void *cls,
  * @param other the other peer involved
  * @param message the actual message
  * @param atsi performance information
+ * @param atsi_count number of entries in atsi
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 handle_p2p_join_notification (void *cls,
-                             const struct GNUNET_PeerIdentity *other,
-                             const struct GNUNET_MessageHeader *message,
-                             const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+                              const struct GNUNET_PeerIdentity *other,
+                              const struct GNUNET_MessageHeader *message,
+                              const struct GNUNET_ATS_Information *atsi,
+                              unsigned int atsi_count)
 {
   const struct P2PJoinNotificationMessage *p2p_jnmsg;
   char *room_name;
@@ -1025,44 +1000,43 @@ handle_p2p_join_notification (void *cls,
   struct ChatClient *new_entry;
   struct ChatClient *entry;
   struct JoinNotificationMessage *jnmsg;
-  GNUNET_HashCode id;
+  struct GNUNET_HashCode id;
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got P2P join notification\n");
   if (ntohs (message->size) <= sizeof (struct P2PJoinNotificationMessage))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed message: wrong size\n");
-      GNUNET_break_op (0);
-      return GNUNET_SYSERR;
-    }
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed message: wrong size\n");
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
   p2p_jnmsg = (const struct P2PJoinNotificationMessage *) message;
   header_size = ntohs (p2p_jnmsg->header.size);
   room_name_len = ntohs (p2p_jnmsg->room_name_len);
-  if (header_size - sizeof (struct P2PJoinNotificationMessage) <=
-      room_name_len)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "Malformed message: wrong length of the room name\n");
-      GNUNET_break_op (0);
-      return GNUNET_SYSERR;
-    }
+  if (header_size - sizeof (struct P2PJoinNotificationMessage) <= room_name_len)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed message: wrong length of the room name\n");
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
   GNUNET_CRYPTO_hash (&p2p_jnmsg->public_key,
-                     sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                     &id);
+                      sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                      &id);
   entry = client_list_head;
   while (NULL != entry)
+  {
+    if (0 == memcmp (&entry->id, &id, sizeof (struct GNUNET_HashCode)))
     {
-      if (0 == memcmp (&entry->id, &id, sizeof (GNUNET_HashCode)))
-       {
 #if DEBUG_CHAT_SERVICE
-         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                     "The client has already joined. There is nothing to do\n");
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "The client has already joined. There is nothing to do\n");
 #endif
-         return GNUNET_OK;
-       }
-      entry = entry->next;
+      return GNUNET_OK;
     }
+    entry = entry->next;
+  }
   meta_len =
-    header_size - sizeof (struct P2PJoinNotificationMessage) - room_name_len;
+      header_size - sizeof (struct P2PJoinNotificationMessage) - room_name_len;
   roomptr = (const char *) &p2p_jnmsg[1];
   room_name = GNUNET_malloc (room_name_len + 1);
   memcpy (room_name, roomptr, room_name_len);
@@ -1075,10 +1049,10 @@ handle_p2p_join_notification (void *cls,
   new_entry->public_key = p2p_jnmsg->public_key;
   new_entry->meta_len = meta_len;
   if (meta_len > 0)
-    {
-      new_entry->member_info = GNUNET_malloc (meta_len);
-      memcpy (new_entry->member_info, &roomptr[room_name_len], meta_len);
-    }
+  {
+    new_entry->member_info = GNUNET_malloc (meta_len);
+    memcpy (new_entry->member_info, &roomptr[room_name_len], meta_len);
+  }
   else
     new_entry->member_info = NULL;
   new_entry->msg_options = ntohl (p2p_jnmsg->msg_options);
@@ -1086,35 +1060,31 @@ handle_p2p_join_notification (void *cls,
   client_list_head = new_entry;
 #if DEBUG_CHAT_SERVICE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Notifying local room members that we have a new client\n");
+              "Notifying local room members that we have a new client\n");
 #endif
   jnmsg = GNUNET_malloc (sizeof (struct JoinNotificationMessage) + meta_len);
   jnmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_JOIN_NOTIFICATION);
   jnmsg->header.size =
-    htons (sizeof (struct JoinNotificationMessage) + meta_len);
+      htons (sizeof (struct JoinNotificationMessage) + meta_len);
   jnmsg->msg_options = p2p_jnmsg->msg_options;
   jnmsg->public_key = new_entry->public_key;
   memcpy (&jnmsg[1], &roomptr[room_name_len], meta_len);
   entry = client_list_head;
   while (NULL != entry)
+  {
+    if ((0 == strcmp (room_name, entry->room)) && (NULL != entry->client))
     {
-      if ((0 == strcmp (room_name, entry->room)) &&
-         (NULL != entry->client))
-       {
-         GNUNET_SERVER_notification_context_unicast (nc,
-                                                     entry->client,
-                                                     &jnmsg->header,
-                                                     GNUNET_NO);
-       }
-      entry = entry->next;
+      GNUNET_SERVER_notification_context_unicast (nc, entry->client,
+                                                  &jnmsg->header, GNUNET_NO);
     }
+    entry = entry->next;
+  }
 #if DEBUG_CHAT_SERVICE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Broadcasting join notification to neighbour peers\n");
+              "Broadcasting join notification to neighbour peers\n");
 #endif
-  GNUNET_CORE_iterate_peers (cfg,
-                            &send_join_noficiation,
-                            new_entry);
+  GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
+                                         &send_join_noficiation, new_entry);
   GNUNET_free (jnmsg);
   return GNUNET_OK;
 }
@@ -1127,17 +1097,19 @@ handle_p2p_join_notification (void *cls,
  * @param other the other peer involved
  * @param message the actual message
  * @param atsi performance information
+ * @param atsi_count number of entries in atsi
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 handle_p2p_leave_notification (void *cls,
-                              const struct GNUNET_PeerIdentity *other,
-                              const struct GNUNET_MessageHeader *message,
-                              const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+                               const struct GNUNET_PeerIdentity *other,
+                               const struct GNUNET_MessageHeader *message,
+                               const struct GNUNET_ATS_Information *atsi,
+                               unsigned int atsi_count)
 {
   const struct P2PLeaveNotificationMessage *p2p_lnmsg;
-  GNUNET_HashCode id;
+  struct GNUNET_HashCode id;
   struct ChatClient *pos;
   struct ChatClient *prev;
   struct ChatClient *entry;
@@ -1146,32 +1118,32 @@ handle_p2p_leave_notification (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got P2P leave notification\n");
   p2p_lnmsg = (const struct P2PLeaveNotificationMessage *) message;
   GNUNET_CRYPTO_hash (&p2p_lnmsg->user,
-                     sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                     &id);
+                      sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                      &id);
   pos = client_list_head;
   prev = NULL;
   while (NULL != pos)
-    {
-      if (0 == memcmp (&pos->id, &id, sizeof (GNUNET_HashCode)))
-       break;
-      prev = pos;
-      pos = pos->next;
-    }
+  {
+    if (0 == memcmp (&pos->id, &id, sizeof (struct GNUNET_HashCode)))
+      break;
+    prev = pos;
+    pos = pos->next;
+  }
   if (NULL == pos)
-    {
+  {
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "No such client. There is nothing to do\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "No such client. There is nothing to do\n");
 #endif
-      return GNUNET_OK;
-    }
+    return GNUNET_OK;
+  }
   if (NULL == prev)
     client_list_head = pos->next;
   else
     prev->next = pos->next;
 #if DEBUG_CHAT_SERVICE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Notifying local room members that the client has gone away\n");
+              "Notifying local room members that the client has gone away\n");
 #endif
   lnmsg.header.size = htons (sizeof (struct LeaveNotificationMessage));
   lnmsg.header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_LEAVE_NOTIFICATION);
@@ -1179,24 +1151,23 @@ handle_p2p_leave_notification (void *cls,
   lnmsg.user = pos->public_key;
   entry = client_list_head;
   while (NULL != entry)
+  {
+    if (0 == strcmp (pos->room, entry->room) && (NULL != entry->client))
     {
-      if (0 == strcmp (pos->room, entry->room) &&
-         (NULL != entry->client))
-       {
-         GNUNET_SERVER_notification_context_unicast (nc,
-                                                     entry->client,
-                                                     &lnmsg.header,
-                                                     GNUNET_NO);
-       }
-      entry = entry->next;
+      GNUNET_SERVER_notification_context_unicast (nc, entry->client,
+                                                  &lnmsg.header, GNUNET_NO);
     }
+    entry = entry->next;
+  }
 #if DEBUG_CHAT_SERVICE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Broadcasting leave notification to neighbour peers\n");
+              "Broadcasting leave notification to neighbour peers\n");
 #endif
-  GNUNET_CORE_iterate_peers (cfg,
-                            &send_leave_noficiation,
-                            pos);
+  GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
+                                         &send_leave_noficiation, pos);
+  GNUNET_free (pos->room);
+  GNUNET_free_non_null (pos->member_info);
+  GNUNET_free (pos);
   return GNUNET_OK;
 }
 
@@ -1208,21 +1179,23 @@ handle_p2p_leave_notification (void *cls,
  * @param other the other peer involved
  * @param message the actual message
  * @param atsi performance information
+ * @param atsi_count number of entries in atsi
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 handle_p2p_message_notification (void *cls,
-                                const struct GNUNET_PeerIdentity *other,
-                                const struct GNUNET_MessageHeader *message,
-                                const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+                                 const struct GNUNET_PeerIdentity *other,
+                                 const struct GNUNET_MessageHeader *message,
+                                 const struct GNUNET_ATS_Information *atsi,
+                                 unsigned int atsi_count)
 {
   const struct P2PReceiveNotificationMessage *p2p_rnmsg;
   struct P2PReceiveNotificationMessage *my_p2p_rnmsg;
   struct ReceiveNotificationMessage *rnmsg;
   struct ChatClient *sender;
   struct ChatClient *pos;
-  static GNUNET_HashCode all_zeros;
+  static struct GNUNET_HashCode all_zeros;
   int is_priv;
   int is_anon;
   uint16_t msg_len;
@@ -1232,124 +1205,120 @@ handle_p2p_message_notification (void *cls,
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got P2P message notification\n");
   if (ntohs (message->size) <= sizeof (struct P2PReceiveNotificationMessage))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed message: wrong size\n");
-      GNUNET_break_op (0);
-      return GNUNET_SYSERR;
-    }
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed message: wrong size\n");
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
   p2p_rnmsg = (const struct P2PReceiveNotificationMessage *) message;
-  msg_len = ntohs (p2p_rnmsg->header.size) -
-    sizeof (struct P2PReceiveNotificationMessage);
+  msg_len =
+      ntohs (p2p_rnmsg->header.size) -
+      sizeof (struct P2PReceiveNotificationMessage);
 
   is_anon = (0 != (ntohl (p2p_rnmsg->msg_options) & GNUNET_CHAT_MSG_ANONYMOUS));
   if (is_anon)
+  {
+    room_name_len = ntohs (p2p_rnmsg->room_name_len);
+    if (msg_len <= room_name_len)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Malformed message: wrong length of the room name\n");
+      GNUNET_break_op (0);
+      return GNUNET_SYSERR;
+    }
+    msg_len -= room_name_len;
+    if (lookup_anonymous_message (p2p_rnmsg))
     {
-      room_name_len = ntohs (p2p_rnmsg->room_name_len);
-      if (msg_len <= room_name_len)
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     "Malformed message: wrong length of the room name\n");
-         GNUNET_break_op (0);
-         return GNUNET_SYSERR;
-       }
-      msg_len -= room_name_len;
-      if (lookup_anonymous_message (p2p_rnmsg))
-       {
 #if DEBUG_CHAT_SERVICE
-         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                     "This anonymous message has already been handled.");
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "This anonymous message has already been handled.");
 #endif
-         return GNUNET_OK;
-       }
-      remember_anonymous_message (p2p_rnmsg);
-      room_name = GNUNET_malloc (room_name_len + 1);
-      memcpy (room_name, (char *) &p2p_rnmsg[1], room_name_len);
-      room_name[room_name_len] = '\0';
-      text = (char *) &p2p_rnmsg[1] + room_name_len;
+      return GNUNET_OK;
     }
+    remember_anonymous_message (p2p_rnmsg);
+    room_name = GNUNET_malloc (room_name_len + 1);
+    memcpy (room_name, (char *) &p2p_rnmsg[1], room_name_len);
+    room_name[room_name_len] = '\0';
+    text = (char *) &p2p_rnmsg[1] + room_name_len;
+  }
   else
+  {
+    sender = client_list_head;
+    while ((NULL != sender) &&
+           (0 !=
+            memcmp (&sender->id, &p2p_rnmsg->sender, sizeof (struct GNUNET_HashCode))))
+      sender = sender->next;
+    if (NULL == sender)
     {
-  sender = client_list_head;
-  while ((NULL != sender) &&
-        (0 != memcmp (&sender->id,
-                      &p2p_rnmsg->sender,
-                      sizeof (GNUNET_HashCode))))
-    sender = sender->next;
-  if (NULL == sender)
-    {
-         /* not an error since the sender may have left before we got the
-            message */
+      /* not an error since the sender may have left before we got the
+       * message */
 #if DEBUG_CHAT_SERVICE
-         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Unknown source. Rejecting the message\n");
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Unknown source. Rejecting the message\n");
 #endif
-         return GNUNET_OK;
+      return GNUNET_OK;
     }
-  if (sender->msg_sequence_number >= ntohl (p2p_rnmsg->sequence_number))
+    if (sender->msg_sequence_number >= ntohl (p2p_rnmsg->sequence_number))
     {
 #if DEBUG_CHAT_SERVICE
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "This message has already been handled."
-                 " Sequence numbers (msg/sender): %u/%u\n",
-                     ntohl (p2p_rnmsg->sequence_number),
-                     sender->msg_sequence_number);
+                  "This message has already been handled."
+                  " Sequence numbers (msg/sender): %u/%u\n",
+                  ntohl (p2p_rnmsg->sequence_number),
+                  sender->msg_sequence_number);
 #endif
       return GNUNET_OK;
     }
-  sender->msg_sequence_number = ntohl (p2p_rnmsg->sequence_number);
-      room_name = sender->room;
-      text = (char *) &p2p_rnmsg[1];
-    }
+    sender->msg_sequence_number = ntohl (p2p_rnmsg->sequence_number);
+    room_name = sender->room;
+    text = (char *) &p2p_rnmsg[1];
+  }
 
 #if DEBUG_CHAT_SERVICE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Sending message to local room members\n");
+              "Sending message to local room members\n");
 #endif
   rnmsg = GNUNET_malloc (sizeof (struct ReceiveNotificationMessage) + msg_len);
-  rnmsg->header.size = htons (sizeof (struct ReceiveNotificationMessage) +
-                             msg_len);
+  rnmsg->header.size =
+      htons (sizeof (struct ReceiveNotificationMessage) + msg_len);
   rnmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_MESSAGE_NOTIFICATION);
   rnmsg->msg_options = p2p_rnmsg->msg_options;
   rnmsg->sequence_number = p2p_rnmsg->sequence_number;
+  rnmsg->reserved = htonl (0);
   rnmsg->timestamp = p2p_rnmsg->timestamp;
-  is_priv = (0 != memcmp (&all_zeros,
-                          &p2p_rnmsg->target, sizeof (GNUNET_HashCode)));
+  is_priv =
+      (0 != memcmp (&all_zeros, &p2p_rnmsg->target, sizeof (struct GNUNET_HashCode)));
   if (is_priv)
-    memcpy (&rnmsg->encrypted_key,
-           &p2p_rnmsg->encrypted_key,
-           sizeof (struct GNUNET_CRYPTO_RsaEncryptedData));
+    memcpy (&rnmsg->encrypted_key, &p2p_rnmsg->encrypted_key,
+            sizeof (struct GNUNET_CRYPTO_RsaEncryptedData));
   rnmsg->sender = p2p_rnmsg->sender;
   memcpy (&rnmsg[1], text, msg_len);
   pos = client_list_head;
   while (NULL != pos)
+  {
+    if ((0 == strcmp (room_name, pos->room)) && (NULL != pos->client))
     {
-      if ((0 == strcmp (room_name, pos->room)) &&
-         (NULL != pos->client))
-       {
-         if (((!is_priv) ||
-              (0 == memcmp (&p2p_rnmsg->target,
-                            &pos->id,
-                            sizeof (GNUNET_HashCode)))) &&
-             (0 == (ntohl (p2p_rnmsg->msg_options) & (~pos->msg_options))))
-           {
-             GNUNET_SERVER_notification_context_unicast (nc,
-                                                         pos->client,
-                                                         &rnmsg->header,
-                                                         GNUNET_NO);
-           }
-       }
-      pos = pos->next;
+      if (((!is_priv) ||
+           (0 ==
+            memcmp (&p2p_rnmsg->target, &pos->id, sizeof (struct GNUNET_HashCode)))) &&
+          (0 == (ntohl (p2p_rnmsg->msg_options) & (~pos->msg_options))))
+      {
+        GNUNET_SERVER_notification_context_unicast (nc, pos->client,
+                                                    &rnmsg->header, GNUNET_NO);
+      }
     }
+    pos = pos->next;
+  }
   if (is_anon)
     GNUNET_free (room_name);
 #if DEBUG_CHAT_SERVICE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Broadcasting message notification to neighbour peers\n");
+              "Broadcasting message notification to neighbour peers\n");
 #endif
   my_p2p_rnmsg = GNUNET_memdup (p2p_rnmsg, ntohs (p2p_rnmsg->header.size));
-  GNUNET_CORE_iterate_peers (cfg,
-                            &send_message_noficiation,
-                            my_p2p_rnmsg);
+  GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
+                                         &send_message_noficiation,
+                                         my_p2p_rnmsg);
   GNUNET_free (rnmsg);
   return GNUNET_OK;
 }
@@ -1362,14 +1331,15 @@ handle_p2p_message_notification (void *cls,
  * @param other the other peer involved
  * @param message the actual message
  * @param atsi performance information
+ * @param atsi_count number of entries in atsi
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
-handle_p2p_sync_request (void *cls,
-                        const struct GNUNET_PeerIdentity *other,
-                        const struct GNUNET_MessageHeader *message,
-                        const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+handle_p2p_sync_request (void *cls, const struct GNUNET_PeerIdentity *other,
+                         const struct GNUNET_MessageHeader *message,
+                         const struct GNUNET_ATS_Information *atsi,
+                         unsigned int atsi_count)
 {
   struct ChatClient *entry;
   struct GNUNET_CORE_TransmitHandle *th;
@@ -1378,24 +1348,21 @@ handle_p2p_sync_request (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got P2P sync request\n");
 #if DEBUG_CHAT_SERVICE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Notifying the requester of all known clients\n");
+              "Notifying the requester of all known clients\n");
 #endif
   entry = client_list_head;
   while (NULL != entry)
-    {
-      msg_size = sizeof (struct P2PJoinNotificationMessage) +
-       strlen (entry->room) + 
-       entry->meta_len;
-      th = GNUNET_CORE_notify_transmit_ready (core,
-                                             1,
-                                             MAX_TRANSMIT_DELAY,
-                                             other,
-                                             msg_size,
-                                             &transmit_join_notification_to_peer,
-                                             entry);
-      GNUNET_assert (NULL != th);
-      entry = entry->next;
-    }
+  {
+    msg_size =
+        sizeof (struct P2PJoinNotificationMessage) + strlen (entry->room) +
+        entry->meta_len;
+    th = GNUNET_CORE_notify_transmit_ready (core, GNUNET_NO, 1,
+                                            MAX_TRANSMIT_DELAY, other, msg_size,
+                                            &transmit_join_notification_to_peer,
+                                            entry);
+    GNUNET_assert (NULL != th);
+    entry = entry->next;
+  }
   return GNUNET_OK;
 }
 
@@ -1407,14 +1374,16 @@ handle_p2p_sync_request (void *cls,
  * @param other the other peer involved
  * @param message the actual message
  * @param atsi performance information
+ * @param atsi_count number of entries in atsi
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 handle_p2p_confirmation_receipt (void *cls,
-                                const struct GNUNET_PeerIdentity *other,
-                                const struct GNUNET_MessageHeader *message,
-                                const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+                                 const struct GNUNET_PeerIdentity *other,
+                                 const struct GNUNET_MessageHeader *message,
+                                 const struct GNUNET_ATS_Information *atsi,
+                                 unsigned int atsi_count)
 {
   const struct P2PConfirmationReceiptMessage *p2p_crmsg;
   struct P2PConfirmationReceiptMessage *my_p2p_crmsg;
@@ -1426,94 +1395,94 @@ handle_p2p_confirmation_receipt (void *cls,
   p2p_crmsg = (const struct P2PConfirmationReceiptMessage *) message;
   target = client_list_head;
   while ((NULL != target) &&
-        (0 != memcmp (&target->id,
-                      &p2p_crmsg->target,
-                      sizeof (GNUNET_HashCode))))
+         (0 !=
+          memcmp (&target->id, &p2p_crmsg->target, sizeof (struct GNUNET_HashCode))))
     target = target->next;
   if (NULL == target)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "Unknown source of the receipt. Rejecting the message\n");
-      GNUNET_break_op (0);
-      return GNUNET_SYSERR;
-    }
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unknown source of the receipt. Rejecting the message\n");
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
   if (target->rcpt_sequence_number >= ntohl (p2p_crmsg->sequence_number))
-    {
+  {
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "This receipt has already been handled."
-                 " Sequence numbers (msg/sender): %u/%u\n",
-                 ntohl (p2p_crmsg->sequence_number), target->rcpt_sequence_number);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "This receipt has already been handled."
+                " Sequence numbers (msg/sender): %u/%u\n",
+                ntohl (p2p_crmsg->sequence_number),
+                target->rcpt_sequence_number);
 #endif
-      return GNUNET_OK;
-    }
+    return GNUNET_OK;
+  }
   target->rcpt_sequence_number = ntohl (p2p_crmsg->sequence_number);
   author = client_list_head;
   while ((NULL != author) &&
-        (0 != memcmp (&author->id,
-                      &p2p_crmsg->author,
-                      sizeof (GNUNET_HashCode))))
+         (0 !=
+          memcmp (&author->id, &p2p_crmsg->author, sizeof (struct GNUNET_HashCode))))
     author = author->next;
   if (NULL == author)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "Unknown addressee. Rejecting the receipt\n");
-      GNUNET_break_op (0);
-      return GNUNET_SYSERR;
-    }
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unknown addressee. Rejecting the receipt\n");
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
 
   if (NULL == author->client)
-    {
+  {
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "The author of the original message is not a local client."
-                 " Broadcasting receipt to neighbour peers\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "The author of the original message is not a local client."
+                " Broadcasting receipt to neighbour peers\n");
 #endif
-      my_p2p_crmsg = GNUNET_memdup (p2p_crmsg, sizeof (struct P2PConfirmationReceiptMessage));
-      GNUNET_CORE_iterate_peers (cfg,
-                                &send_confirmation_receipt,
-                                my_p2p_crmsg);
-    }
+    my_p2p_crmsg =
+        GNUNET_memdup (p2p_crmsg,
+                       sizeof (struct P2PConfirmationReceiptMessage));
+    GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
+                                           &send_confirmation_receipt,
+                                           my_p2p_crmsg);
+    GNUNET_free (my_p2p_crmsg);
+  }
   else
-    {
+  {
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "The author of the original message is a local client."
-                 " Verifying signature of the receipt\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "The author of the original message is a local client."
+                " Verifying signature of the receipt\n");
 #endif
-      crmsg = GNUNET_malloc (sizeof (struct ConfirmationReceiptMessage));
-      crmsg->header.size = htons (sizeof (struct ConfirmationReceiptMessage));
-      crmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_CONFIRMATION_NOTIFICATION);
-      crmsg->signature = p2p_crmsg->signature;
-      crmsg->purpose = p2p_crmsg->purpose;
-      crmsg->sequence_number = p2p_crmsg->msg_sequence_number;
-      crmsg->reserved2 = 0;
-      crmsg->timestamp = p2p_crmsg->timestamp;
-      crmsg->target = p2p_crmsg->target;
-      crmsg->author = p2p_crmsg->author;
-      crmsg->content = p2p_crmsg->content;
-      if (GNUNET_OK !=
-         GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_CHAT_RECEIPT,
-                                   &crmsg->purpose,
-                                   &crmsg->signature,
-                                   &target->public_key))
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     "Invalid signature of the receipt\n");
-         GNUNET_break_op (0);
-         return GNUNET_SYSERR;
-       }
+    crmsg = GNUNET_malloc (sizeof (struct ConfirmationReceiptMessage));
+    crmsg->header.size = htons (sizeof (struct ConfirmationReceiptMessage));
+    crmsg->header.type =
+        htons (GNUNET_MESSAGE_TYPE_CHAT_CONFIRMATION_NOTIFICATION);
+    crmsg->signature = p2p_crmsg->signature;
+    crmsg->purpose = p2p_crmsg->purpose;
+    crmsg->sequence_number = p2p_crmsg->msg_sequence_number;
+    crmsg->reserved2 = 0;
+    crmsg->timestamp = p2p_crmsg->timestamp;
+    crmsg->target = p2p_crmsg->target;
+    crmsg->author = p2p_crmsg->author;
+    crmsg->content = p2p_crmsg->content;
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_CHAT_RECEIPT,
+                                  &crmsg->purpose, &crmsg->signature,
+                                  &target->public_key))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Invalid signature of the receipt\n");
+      GNUNET_break_op (0);
+      return GNUNET_SYSERR;
+    }
 #if DEBUG_CHAT_SERVICE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "The author of the original message is a local client."
-                 " Sending receipt to the client\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "The author of the original message is a local client."
+                " Sending receipt to the client\n");
 #endif
-      GNUNET_SERVER_notification_context_unicast (nc,
-                                                 author->client,
-                                                 &crmsg->header,
-                                                 GNUNET_NO);
-      GNUNET_free (crmsg);
-    }
+    GNUNET_SERVER_notification_context_unicast (nc, author->client,
+                                                &crmsg->header, GNUNET_NO);
+    GNUNET_free (crmsg);
+  }
   return GNUNET_OK;
 }
 
@@ -1527,9 +1496,7 @@ handle_p2p_confirmation_receipt (void *cls,
  * @return number of bytes written to buf
  */
 static size_t
-transmit_sync_request_to_peer (void *cls,
-                              size_t size,
-                              void *buf)
+transmit_sync_request_to_peer (void *cls, size_t size, void *buf)
 {
   struct GNUNET_MessageHeader *m = buf;
   size_t msg_size;
@@ -1553,26 +1520,64 @@ transmit_sync_request_to_peer (void *cls,
  * @param cls closure
  * @param peer peer identity this notification is about
  * @param atsi performance data
+ * @param atsi_count number of entries in atsi
  */
-static void 
-peer_connect_handler (void *cls,
-                     const struct GNUNET_PeerIdentity *peer,
-                     const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+static void
+peer_connect_handler (void *cls, const struct GNUNET_PeerIdentity *peer,
+                      const struct GNUNET_ATS_Information *atsi,
+                      unsigned int atsi_count)
 {
+  struct ConnectedPeer *cp;
   struct GNUNET_CORE_TransmitHandle *th;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             "Peer connected: %s\n", GNUNET_i2s (peer));
-  if (0 == memcmp (peer, me, sizeof (struct GNUNET_PeerIdentity)))
+  if (0 == memcmp (peer, &me, sizeof (struct GNUNET_PeerIdentity)))
     return;
-  th = GNUNET_CORE_notify_transmit_ready (core,
-                                         1,
-                                         MAX_TRANSMIT_DELAY,
-                                         peer,
-                                         sizeof (struct GNUNET_MessageHeader),
-                                         &transmit_sync_request_to_peer,
-                                         NULL);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer connected: %s\n",
+              GNUNET_i2s (peer));
+  th = GNUNET_CORE_notify_transmit_ready (core, GNUNET_YES, 1,
+                                          MAX_TRANSMIT_DELAY, peer,
+                                          sizeof (struct GNUNET_MessageHeader),
+                                          &transmit_sync_request_to_peer, NULL);
   GNUNET_assert (NULL != th);
+  cp = GNUNET_CONTAINER_multihashmap_get (connected_peers, &peer->hashPubKey);
+  if (NULL != cp)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  cp = GNUNET_malloc (sizeof (struct ConnectedPeer));
+  cp->pid = GNUNET_PEER_intern (peer);
+  GNUNET_break (GNUNET_OK ==
+                GNUNET_CONTAINER_multihashmap_put (connected_peers,
+                                                   &peer->hashPubKey, cp,
+                                                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+}
+
+
+/**
+ * Iterator to free peer entries.
+ *
+ * @param cls closure, unused
+ * @param key current key code
+ * @param value value in the hash map (peer entry)
+ * @return GNUNET_YES (we should continue to iterate)
+ */
+static int
+clean_peer (void *cls, const struct GNUNET_HashCode * key, void *value)
+{
+  struct ConnectedPeer *cp;
+  const struct GNUNET_PeerIdentity *peer =
+      (const struct GNUNET_PeerIdentity *) key;
+
+  cp = GNUNET_CONTAINER_multihashmap_get (connected_peers, &peer->hashPubKey);
+  if (cp == NULL)
+    return GNUNET_YES;
+  GNUNET_break (GNUNET_YES ==
+                GNUNET_CONTAINER_multihashmap_remove (connected_peers,
+                                                      &peer->hashPubKey, cp));
+  GNUNET_PEER_change_rc (cp->pid, -1);
+  GNUNET_free (cp);
+  return GNUNET_YES;
 }
 
 
@@ -1583,11 +1588,14 @@ peer_connect_handler (void *cls,
  * @param peer peer identity this notification is about
  */
 static void
-peer_disconnect_handler (void *cls,
-                        const struct GNUNET_PeerIdentity *peer)
+peer_disconnect_handler (void *cls, const struct GNUNET_PeerIdentity *peer)
 {
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             "Peer disconnected: %s\n", GNUNET_i2s (peer));
+
+  if (0 == memcmp (peer, &me, sizeof (struct GNUNET_PeerIdentity)))
+    return;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer disconnected: %s\n",
+              GNUNET_i2s (peer));
+  clean_peer (NULL, (const struct GNUNET_HashCode *) peer, NULL);
 }
 
 
@@ -1598,37 +1606,39 @@ peer_disconnect_handler (void *cls,
  * @param tc unused
  */
 static void
-cleanup_task (void *cls,
-             const struct GNUNET_SCHEDULER_TaskContext *tc)
+cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct AnonymousMessage *next_msg;
   struct ChatClient *next_client;
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Cleaning up\n");
   if (NULL != core)
-    {
-      GNUNET_CORE_disconnect (core);
-      core = NULL;
-    }
+  {
+    GNUNET_CORE_disconnect (core);
+    core = NULL;
+  }
   if (NULL != nc)
-    {
-      GNUNET_SERVER_notification_context_destroy (nc);
-      nc = NULL;
-    }
+  {
+    GNUNET_SERVER_notification_context_destroy (nc);
+    nc = NULL;
+  }
   while (NULL != client_list_head)
-    {
-      next_client = client_list_head->next;
-      GNUNET_free (client_list_head->room);
-      GNUNET_free_non_null (client_list_head->member_info);
-      GNUNET_free (client_list_head);
-      client_list_head = next_client;
-    }
+  {
+    next_client = client_list_head->next;
+    GNUNET_free (client_list_head->room);
+    GNUNET_free_non_null (client_list_head->member_info);
+    GNUNET_free (client_list_head);
+    client_list_head = next_client;
+  }
   while (NULL != anonymous_list_head)
-    {
-      next_msg = anonymous_list_head->next;
-      GNUNET_free (anonymous_list_head);
-      anonymous_list_head = next_msg;
-    }
+  {
+    next_msg = anonymous_list_head->next;
+    GNUNET_free (anonymous_list_head);
+    anonymous_list_head = next_msg;
+  }
+  GNUNET_CONTAINER_multihashmap_iterate (connected_peers, &clean_peer, NULL);
+  GNUNET_CONTAINER_multihashmap_destroy (connected_peers);
+  connected_peers = NULL;
 }
 
 
@@ -1638,16 +1648,13 @@ cleanup_task (void *cls,
  * @param cls closure, NULL
  * @param server handle to the server for this service
  * @param my_identity the public identity of this peer
- * @param publicKey the public key of this peer
  */
 static void
-core_init (void *cls,
-          struct GNUNET_CORE_Handle *server,
-          const struct GNUNET_PeerIdentity *my_identity,
-          const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
+core_init (void *cls, struct GNUNET_CORE_Handle *server,
+           const struct GNUNET_PeerIdentity *my_identity)
 {
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Core initialized\n");
-  me = my_identity;
+  me = *my_identity;
 }
 
 
@@ -1659,65 +1666,55 @@ core_init (void *cls,
  * @param c configuration to use
  */
 static void
-run (void *cls,
-     struct GNUNET_SERVER_Handle *server,
+run (void *cls, struct GNUNET_SERVER_Handle *server,
      const struct GNUNET_CONFIGURATION_Handle *c)
 {
-  static const struct GNUNET_SERVER_MessageHandler handlers[] =
-    {
-      { &handle_join_request, NULL,
-       GNUNET_MESSAGE_TYPE_CHAT_JOIN_REQUEST, 0 },
-      { &handle_transmit_request, NULL,
-       GNUNET_MESSAGE_TYPE_CHAT_TRANSMIT_REQUEST, 0 },
-      { &handle_acknowledge_request, NULL,
-       GNUNET_MESSAGE_TYPE_CHAT_CONFIRMATION_RECEIPT,
-       sizeof (struct ConfirmationReceiptMessage) },
-      { NULL, NULL, 0, 0 }
-    };
-  static const struct GNUNET_CORE_MessageHandler p2p_handlers[] =
-    {
-      { &handle_p2p_join_notification,
-       GNUNET_MESSAGE_TYPE_CHAT_P2P_JOIN_NOTIFICATION, 0 },
-      { &handle_p2p_leave_notification,
-       GNUNET_MESSAGE_TYPE_CHAT_P2P_LEAVE_NOTIFICATION,
-       sizeof (struct P2PLeaveNotificationMessage) },
-      { &handle_p2p_message_notification,
-       GNUNET_MESSAGE_TYPE_CHAT_P2P_MESSAGE_NOTIFICATION, 0 },
-      { &handle_p2p_sync_request,
-       GNUNET_MESSAGE_TYPE_CHAT_P2P_SYNC_REQUEST,
-       sizeof (struct GNUNET_MessageHeader) },
-      { &handle_p2p_confirmation_receipt,
-       GNUNET_MESSAGE_TYPE_CHAT_P2P_CONFIRMATION_RECEIPT,
-       sizeof (struct P2PConfirmationReceiptMessage) },
-      { NULL, 0, 0 }
-    };
+  static const struct GNUNET_SERVER_MessageHandler handlers[] = {
+    {&handle_join_request, NULL,
+     GNUNET_MESSAGE_TYPE_CHAT_JOIN_REQUEST, 0},
+    {&handle_transmit_request, NULL,
+     GNUNET_MESSAGE_TYPE_CHAT_TRANSMIT_REQUEST, 0},
+    {&handle_acknowledge_request, NULL,
+     GNUNET_MESSAGE_TYPE_CHAT_CONFIRMATION_RECEIPT,
+     sizeof (struct ConfirmationReceiptMessage)},
+    {NULL, NULL, 0, 0}
+  };
+  static const struct GNUNET_CORE_MessageHandler p2p_handlers[] = {
+    {&handle_p2p_join_notification,
+     GNUNET_MESSAGE_TYPE_CHAT_P2P_JOIN_NOTIFICATION, 0},
+    {&handle_p2p_leave_notification,
+     GNUNET_MESSAGE_TYPE_CHAT_P2P_LEAVE_NOTIFICATION,
+     sizeof (struct P2PLeaveNotificationMessage)},
+    {&handle_p2p_message_notification,
+     GNUNET_MESSAGE_TYPE_CHAT_P2P_MESSAGE_NOTIFICATION, 0},
+    {&handle_p2p_sync_request,
+     GNUNET_MESSAGE_TYPE_CHAT_P2P_SYNC_REQUEST,
+     sizeof (struct GNUNET_MessageHeader)},
+    {&handle_p2p_confirmation_receipt,
+     GNUNET_MESSAGE_TYPE_CHAT_P2P_CONFIRMATION_RECEIPT,
+     sizeof (struct P2PConfirmationReceiptMessage)},
+    {NULL, 0, 0}
+  };
 
   GNUNET_log_setup ("gnunet-service-chat",
 #if DEBUG_CHAT_SERVICE
-                   "DEBUG",
+                    "DEBUG",
 #else
-                   "WARNING",
+                    "WARNING",
 #endif
-                   NULL);
+                    NULL);
   cfg = c;
   nc = GNUNET_SERVER_notification_context_create (server, 16);
+  connected_peers =
+    GNUNET_CONTAINER_multihashmap_create (EXPECTED_NEIGHBOUR_COUNT, GNUNET_NO);
   GNUNET_SERVER_add_handlers (server, handlers);
-  core = GNUNET_CORE_connect (cfg,
-                             QUEUE_SIZE,
-                             NULL,
-                             &core_init,
-                             &peer_connect_handler,
-                             &peer_disconnect_handler,
-                             NULL,
-                             NULL, GNUNET_NO,
-                             NULL, GNUNET_NO,
-                             p2p_handlers);
-  GNUNET_SERVER_disconnect_notify (server, 
-                                  &handle_client_disconnect,
-                                  NULL);
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
-                               &cleanup_task,
-                               NULL);
+  core =
+      GNUNET_CORE_connect (cfg, NULL, &core_init,
+                           &peer_connect_handler, &peer_disconnect_handler,
+                           NULL, GNUNET_NO, NULL, GNUNET_NO, p2p_handlers);
+  GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
+                                NULL);
 }
 
 
@@ -1732,11 +1729,8 @@ int
 main (int argc, char *const *argv)
 {
   return (GNUNET_OK ==
-         GNUNET_SERVICE_run (argc,
-                             argv,
-                             "chat",
-                             GNUNET_SERVICE_OPTION_NONE,
-                             &run, NULL)) ? 0 : 1;
+          GNUNET_SERVICE_run (argc, argv, "chat", GNUNET_SERVICE_OPTION_NONE,
+                              &run, NULL)) ? 0 : 1;
 }
 
 /* end of gnunet-service-chat.c */