adding Ludo's gnunet-download-manager.scm back to SVN HEAD
[oweals/gnunet.git] / src / core / gnunet-service-core_sessions.c
index 61532ac9cf31c0e48256a5468ba9f2ab0ca78a4d..1f697cf160d2d04e2cc2a1d5839808db0c21c67f 100644 (file)
@@ -20,7 +20,7 @@
 
 /**
  * @file core/gnunet-service-core_sessions.c
- * @brief code for managing of 'encrypted' sessions (key exchange done) 
+ * @brief code for managing of 'encrypted' sessions (key exchange done)
  * @author Christian Grothoff
  */
 #include "platform.h"
@@ -133,7 +133,7 @@ struct Session
 
   /**
    * Is the neighbour queue empty and thus ready for us
-   * to transmit an encrypted message?  
+   * to transmit an encrypted message?
    */
   int ready_to_transmit;
 
@@ -162,7 +162,7 @@ find_session (const struct GNUNET_PeerIdentity *peer)
 
 /**
  * End the session with the given peer (we are no longer
- * connected). 
+ * connected).
  *
  * @param pid identity of peer to kill session with
  */
@@ -171,13 +171,13 @@ GSC_SESSIONS_end (const struct GNUNET_PeerIdentity *pid)
 {
   struct Session *session;
   struct GSC_ClientActiveRequest *car;
+  struct SessionMessageEntry *sme;
 
   session = find_session (pid);
   if (NULL == session)
     return;
 #if DEBUG_CORE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Destroying session for peer `%4s'\n",
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying session for peer `%4s'\n",
               GNUNET_i2s (&session->peer));
 #endif
   if (GNUNET_SCHEDULER_NO_TASK != session->cork_task)
@@ -188,23 +188,28 @@ GSC_SESSIONS_end (const struct GNUNET_PeerIdentity *pid)
   while (NULL != (car = session->active_client_request_head))
   {
     GNUNET_CONTAINER_DLL_remove (session->active_client_request_head,
-                                session->active_client_request_tail,
-                                car);
+                                 session->active_client_request_tail, car);
     GSC_CLIENTS_reject_request (car);
   }
+  while (NULL != (sme = session->sme_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (session->sme_head, session->sme_tail, sme);
+    GNUNET_free (sme);
+  }
   GNUNET_SCHEDULER_cancel (session->typemap_task);
+  GSC_CLIENTS_notify_clients_about_neighbour (&session->peer, NULL,
+                                              0 /* FIXME: ATSI */ ,
+                                              session->tmap, NULL);
   GNUNET_assert (GNUNET_YES ==
                  GNUNET_CONTAINER_multihashmap_remove (sessions,
-                                                       &session->peer.hashPubKey, session));
-  GNUNET_STATISTICS_set (GSC_stats, 
-                        gettext_noop ("# entries in session map"),
-                        GNUNET_CONTAINER_multihashmap_size (sessions), 
-                        GNUNET_NO);
-  if (NULL != session->tmap)
-  {
-    GSC_TYPEMAP_destroy (session->tmap);
-    session->tmap = NULL;
-  }
+                                                       &session->
+                                                       peer.hashPubKey,
+                                                       session));
+  GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# entries in session map"),
+                         GNUNET_CONTAINER_multihashmap_size (sessions),
+                         GNUNET_NO);
+  GSC_TYPEMAP_destroy (session->tmap);
+  session->tmap = NULL;
   GNUNET_free (session);
 }
 
@@ -215,10 +220,9 @@ GSC_SESSIONS_end (const struct GNUNET_PeerIdentity *pid)
  *
  * @param cls the 'struct Session*'
  * @param tc unused
- */ 
+ */
 static void
-transmit_typemap_task (void *cls,
-                      const struct GNUNET_SCHEDULER_TaskContext *tc)
+transmit_typemap_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct Session *session = cls;
   struct GNUNET_MessageHeader *hdr;
@@ -226,19 +230,15 @@ transmit_typemap_task (void *cls,
 
   delay = TYPEMAP_FREQUENCY;
   /* randomize a bit to avoid spont. sync */
-  delay.rel_value += GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                              1000);
-  session->typemap_task = GNUNET_SCHEDULER_add_delayed (delay,
-                                                       &transmit_typemap_task,
-                                                       session);
-  GNUNET_STATISTICS_update (GSC_stats, 
-                           gettext_noop ("# type map refreshes sent"),
-                           1,
-                           GNUNET_NO);
+  delay.rel_value +=
+      GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000);
+  session->typemap_task =
+      GNUNET_SCHEDULER_add_delayed (delay, &transmit_typemap_task, session);
+  GNUNET_STATISTICS_update (GSC_stats,
+                            gettext_noop ("# type map refreshes sent"), 1,
+                            GNUNET_NO);
   hdr = GSC_TYPEMAP_compute_type_map_message ();
-  GSC_KX_encrypt_and_transmit (session->kxinfo, 
-                              hdr,
-                              ntohs (hdr->size));
+  GSC_KX_encrypt_and_transmit (session->kxinfo, hdr, ntohs (hdr->size));
   GNUNET_free (hdr);
 }
 
@@ -251,28 +251,30 @@ transmit_typemap_task (void *cls,
  */
 void
 GSC_SESSIONS_create (const struct GNUNET_PeerIdentity *peer,
-                    struct GSC_KeyExchangeInfo *kx)
+                     struct GSC_KeyExchangeInfo *kx)
 {
   struct Session *session;
 
 #if DEBUG_CORE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Creating session for peer `%4s'\n", GNUNET_i2s (peer));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating session for peer `%4s'\n",
+              GNUNET_i2s (peer));
 #endif
   session = GNUNET_malloc (sizeof (struct Session));
+  session->tmap = GSC_TYPEMAP_create ();
   session->peer = *peer;
   session->kxinfo = kx;
   session->time_established = GNUNET_TIME_absolute_get ();
-  session->typemap_task = GNUNET_SCHEDULER_add_now (&transmit_typemap_task,
-                                                   session);
+  session->typemap_task =
+      GNUNET_SCHEDULER_add_now (&transmit_typemap_task, session);
   GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONTAINER_multihashmap_put (sessions,
-                                                    &peer->hashPubKey, session,
+                 GNUNET_CONTAINER_multihashmap_put (sessions, &peer->hashPubKey,
+                                                    session,
                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-  GNUNET_STATISTICS_set (GSC_stats, 
-                        gettext_noop ("# entries in session map"),
-                        GNUNET_CONTAINER_multihashmap_size (sessions), 
-                        GNUNET_NO);
+  GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# entries in session map"),
+                         GNUNET_CONTAINER_multihashmap_size (sessions),
+                         GNUNET_NO);
+  GSC_CLIENTS_notify_clients_about_neighbour (peer, NULL, 0 /* FIXME: ATSI */ ,
+                                              NULL, session->tmap);
 }
 
 
@@ -280,23 +282,20 @@ GSC_SESSIONS_create (const struct GNUNET_PeerIdentity *peer,
  * Notify the given client about the session (client is new).
  *
  * @param cls the 'struct GSC_Client'
- * @param key peer identity 
+ * @param key peer identity
  * @param value the 'struct Session'
  * @return GNUNET_OK (continue to iterate)
  */
 static int
-notify_client_about_session (void *cls,
-                            const GNUNET_HashCode *key,
-                            void *value)
+notify_client_about_session (void *cls, const GNUNET_HashCode * key,
+                             void *value)
 {
   struct GSC_Client *client = cls;
   struct Session *session = value;
 
-  GSC_CLIENTS_notify_client_about_neighbour (client,
-                                            &session->peer,
-                                            NULL, 0, /* FIXME: ATS!? */
-                                            NULL, /* old TMAP: none */
-                                            session->tmap);
+  GSC_CLIENTS_notify_client_about_neighbour (client, &session->peer, NULL, 0,   /* FIXME: ATS!? */
+                                             NULL,      /* old TMAP: none */
+                                             session->tmap);
   return GNUNET_OK;
 }
 
@@ -310,8 +309,8 @@ void
 GSC_SESSIONS_notify_client_about_sessions (struct GSC_Client *client)
 {
   /* notify new client about existing sessions */
-  GNUNET_CONTAINER_multihashmap_iterate (sessions,
-                                        &notify_client_about_session, client);
+  GNUNET_CONTAINER_multihashmap_iterate (sessions, &notify_client_about_session,
+                                         client);
 }
 
 
@@ -342,17 +341,11 @@ GSC_SESSIONS_queue_request (struct GSC_ClientActiveRequest *car)
   session = find_session (&car->target);
   if (session == NULL)
   {
-    /* neighbour must have disconnected since request was issued,
-     * ignore (client will realize it once it processes the
-     * disconnect notification) */
 #if DEBUG_CORE
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Dropped client request for transmission (am disconnected)\n");
 #endif
-    GNUNET_STATISTICS_update (GSC_stats,
-                              gettext_noop
-                              ("# send requests dropped (disconnected)"), 1,
-                              GNUNET_NO);
+    GNUNET_break (0);           /* should have been rejected earlier */
     GSC_CLIENTS_reject_request (car);
     return;
   }
@@ -367,7 +360,7 @@ GSC_SESSIONS_queue_request (struct GSC_ClientActiveRequest *car)
               "Received client transmission request. queueing\n");
 #endif
   GNUNET_CONTAINER_DLL_insert (session->active_client_request_head,
-                              session->active_client_request_tail, car);
+                               session->active_client_request_tail, car);
   try_transmission (session);
 }
 
@@ -383,11 +376,11 @@ GSC_SESSIONS_dequeue_request (struct GSC_ClientActiveRequest *car)
 {
   struct Session *s;
 
-  if (0 == memcmp (&car->target,
-                  &GSC_my_identity,
-                  sizeof (struct GNUNET_PeerIdentity)))
+  if (0 ==
+      memcmp (&car->target, &GSC_my_identity,
+              sizeof (struct GNUNET_PeerIdentity)))
     return;
-  s = find_session (&car->target);  
+  s = find_session (&car->target);
   GNUNET_assert (NULL != s);
   GNUNET_CONTAINER_DLL_remove (s->active_client_request_head,
                                s->active_client_request_tail, car);
@@ -405,7 +398,7 @@ discard_expired_requests (struct Session *session)
   struct GSC_ClientActiveRequest *pos;
   struct GSC_ClientActiveRequest *nxt;
   struct GNUNET_TIME_Absolute now;
-  
+
   now = GNUNET_TIME_absolute_get ();
   pos = NULL;
   nxt = session->active_client_request_head;
@@ -413,16 +406,15 @@ discard_expired_requests (struct Session *session)
   {
     pos = nxt;
     nxt = pos->next;
-    if ( (pos->deadline.abs_value < now.abs_value) &&
-        (GNUNET_YES != pos->was_solicited) )
+    if ((pos->deadline.abs_value < now.abs_value) &&
+        (GNUNET_YES != pos->was_solicited))
     {
       GNUNET_STATISTICS_update (GSC_stats,
                                 gettext_noop
                                 ("# messages discarded (expired prior to transmission)"),
                                 1, GNUNET_NO);
       GNUNET_CONTAINER_DLL_remove (session->active_client_request_head,
-                                  session->active_client_request_tail,
-                                  pos);
+                                   session->active_client_request_tail, pos);
       GSC_CLIENTS_reject_request (pos);
     }
   }
@@ -438,12 +430,15 @@ static void
 solicit_messages (struct Session *session)
 {
   struct GSC_ClientActiveRequest *car;
+  struct GSC_ClientActiveRequest *nxt;
   size_t so_size;
 
-  discard_expired_requests (session); 
+  discard_expired_requests (session);
   so_size = 0;
-  for (car = session->active_client_request_head; NULL != car; car = car->next)
+  nxt = session->active_client_request_head;
+  while (NULL != (car = nxt))
   {
+    nxt = car->next;
     if (so_size + car->msize > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
       break;
     so_size += car->msize;
@@ -456,15 +451,14 @@ solicit_messages (struct Session *session)
 
 
 /**
- * Some messages were delayed (corked), but the timeout has now expired.  
+ * Some messages were delayed (corked), but the timeout has now expired.
  * Send them now.
  *
  * @param cls 'struct Session' with the messages to transmit now
  * @param tc scheduler context (unused)
  */
 static void
-pop_cork_task (void *cls,
-              const struct GNUNET_SCHEDULER_TaskContext *tc)
+pop_cork_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct Session *session = cls;
 
@@ -493,31 +487,31 @@ try_transmission (struct Session *session)
   min_deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
   /* check 'ready' messages */
   pos = session->sme_head;
-  while ( (NULL != pos) &&
-         (msize + pos->size <= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) )
+  while ((NULL != pos) &&
+         (msize + pos->size <= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE))
   {
     GNUNET_assert (pos->size < GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE);
     msize += pos->size;
-    min_deadline = GNUNET_TIME_absolute_min (min_deadline,
-                                            pos->deadline);
+    min_deadline = GNUNET_TIME_absolute_min (min_deadline, pos->deadline);
     pos = pos->next;
   }
   now = GNUNET_TIME_absolute_get ();
-  if ( (msize == 0) ||
-       ( (msize < GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE / 2) &&
-        (min_deadline.abs_value > now.abs_value) ) )
+  if ((msize == 0) ||
+      ((msize < GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE / 2) &&
+       (min_deadline.abs_value > now.abs_value)))
   {
     /* not enough ready yet, try to solicit more */
     solicit_messages (session);
     if (msize > 0)
     {
       /* if there is data to send, just not yet, make sure we do transmit
-        it once the deadline is reached */
+       * it once the deadline is reached */
       if (session->cork_task != GNUNET_SCHEDULER_NO_TASK)
-       GNUNET_SCHEDULER_cancel (session->cork_task);
-      session->cork_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (min_deadline),
-                                                        &pop_cork_task,
-                                                        session);
+        GNUNET_SCHEDULER_cancel (session->cork_task);
+      session->cork_task =
+          GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
+                                        (min_deadline), &pop_cork_task,
+                                        session);
     }
     return;
   }
@@ -525,18 +519,15 @@ try_transmission (struct Session *session)
   {
     static unsigned long long total_bytes;
     static unsigned int total_msgs;
-    char pbuf[msize];    /* plaintext */
+    char pbuf[msize];           /* plaintext */
     size_t used;
 
     used = 0;
-    while ( (NULL != (pos = session->sme_head)) &&
-           (used + pos->size <= msize) )
+    while ((NULL != (pos = session->sme_head)) && (used + pos->size <= msize))
     {
       memcpy (&pbuf[used], &pos[1], pos->size);
       used += pos->size;
-      GNUNET_CONTAINER_DLL_remove (session->sme_head,
-                                  session->sme_tail,
-                                  pos);      
+      GNUNET_CONTAINER_DLL_remove (session->sme_head, session->sme_tail, pos);
       GNUNET_free (pos);
     }
     /* compute average payload size */
@@ -548,15 +539,11 @@ try_transmission (struct Session *session)
       total_msgs = 1;
       total_bytes = used;
     }
-    GNUNET_STATISTICS_set (GSC_stats, 
-                          "# avg payload per encrypted message",
-                          total_bytes / total_msgs,
-                          GNUNET_NO);
+    GNUNET_STATISTICS_set (GSC_stats, "# avg payload per encrypted message",
+                           total_bytes / total_msgs, GNUNET_NO);
     /* now actually transmit... */
     session->ready_to_transmit = GNUNET_NO;
-    GSC_KX_encrypt_and_transmit (session->kxinfo,
-                                pbuf,
-                                used);
+    GSC_KX_encrypt_and_transmit (session->kxinfo, pbuf, used);
   }
 }
 
@@ -581,9 +568,7 @@ do_send_message (void *cls, const GNUNET_HashCode * key, void *value)
   m = GNUNET_malloc (sizeof (struct SessionMessageEntry) + size);
   memcpy (&m[1], hdr, size);
   m->size = size;
-  GNUNET_CONTAINER_DLL_insert (session->sme_head,
-                              session->sme_tail,
-                              m);
+  GNUNET_CONTAINER_DLL_insert (session->sme_head, session->sme_tail, m);
   try_transmission (session);
   return GNUNET_OK;
 }
@@ -599,8 +584,8 @@ GSC_SESSIONS_broadcast (const struct GNUNET_MessageHeader *msg)
 {
   if (NULL == sessions)
     return;
-  GNUNET_CONTAINER_multihashmap_iterate (sessions,
-                                         &do_send_message, (void*) msg);
+  GNUNET_CONTAINER_multihashmap_iterate (sessions, &do_send_message,
+                                         (void *) msg);
 }
 
 
@@ -634,8 +619,7 @@ GSC_SESSIONS_solicit (const struct GNUNET_PeerIdentity *pid)
  */
 void
 GSC_SESSIONS_transmit (struct GSC_ClientActiveRequest *car,
-                      const struct GNUNET_MessageHeader *msg,
-                      int cork)
+                       const struct GNUNET_MessageHeader *msg, int cork)
 {
   struct Session *session;
   struct SessionMessageEntry *sme;
@@ -649,10 +633,9 @@ GSC_SESSIONS_transmit (struct GSC_ClientActiveRequest *car,
   memcpy (&sme[1], msg, msize);
   sme->size = msize;
   if (GNUNET_YES == cork)
-    sme->deadline = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_MAX_CORK_DELAY);
-  GNUNET_CONTAINER_DLL_insert_tail (session->sme_head,
-                                   session->sme_tail,
-                                   sme);
+    sme->deadline =
+        GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_MAX_CORK_DELAY);
+  GNUNET_CONTAINER_DLL_insert_tail (session->sme_head, session->sme_tail, sme);
   try_transmission (session);
 }
 
@@ -672,7 +655,7 @@ queue_connect_message (void *cls, const GNUNET_HashCode * key, void *value)
   struct GNUNET_SERVER_TransmitContext *tc = cls;
   struct Session *session = value;
   struct ConnectNotifyMessage cnm;
+
   /* FIXME: code duplication with clients... */
   cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
   cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
@@ -687,23 +670,23 @@ queue_connect_message (void *cls, const GNUNET_HashCode * key, void *value)
 /**
  * Handle CORE_ITERATE_PEERS request. For this request type, the client
  * does not have to have transmitted an INIT request.  All current peers
- * are returned, regardless of which message types they accept. 
+ * are returned, regardless of which message types they accept.
  *
  * @param cls unused
  * @param client client sending the iteration request
  * @param message iteration request message
  */
 void
-GSC_SESSIONS_handle_client_iterate_peers (void *cls, struct GNUNET_SERVER_Client *client,
-                                         const struct GNUNET_MessageHeader *message)
+GSC_SESSIONS_handle_client_iterate_peers (void *cls,
+                                          struct GNUNET_SERVER_Client *client,
+                                          const struct GNUNET_MessageHeader
+                                          *message)
 {
   struct GNUNET_MessageHeader done_msg;
   struct GNUNET_SERVER_TransmitContext *tc;
 
   tc = GNUNET_SERVER_transmit_context_create (client);
-  GNUNET_CONTAINER_multihashmap_iterate (sessions, 
-                                        &queue_connect_message,
-                                        tc);
+  GNUNET_CONTAINER_multihashmap_iterate (sessions, &queue_connect_message, tc);
   done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
   done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END);
   GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
@@ -722,14 +705,16 @@ GSC_SESSIONS_handle_client_iterate_peers (void *cls, struct GNUNET_SERVER_Client
  * @param message iteration request message
  */
 void
-GSC_SESSIONS_handle_client_have_peer (void *cls, struct GNUNET_SERVER_Client *client,
-                                     const struct GNUNET_MessageHeader *message)
+GSC_SESSIONS_handle_client_have_peer (void *cls,
+                                      struct GNUNET_SERVER_Client *client,
+                                      const struct GNUNET_MessageHeader
+                                      *message)
 {
   struct GNUNET_MessageHeader done_msg;
   struct GNUNET_SERVER_TransmitContext *tc;
   const struct GNUNET_PeerIdentity *peer;
 
-  peer = (const struct GNUNET_PeerIdentity *) &message[1]; // YUCK!
+  peer = (const struct GNUNET_PeerIdentity *) &message[1];      // YUCK!
   tc = GNUNET_SERVER_transmit_context_create (client);
   GNUNET_CONTAINER_multihashmap_get_multiple (sessions, &peer->hashPubKey,
                                               &queue_connect_message, tc);
@@ -749,26 +734,23 @@ GSC_SESSIONS_handle_client_have_peer (void *cls, struct GNUNET_SERVER_Client *cl
  */
 void
 GSC_SESSIONS_set_typemap (const struct GNUNET_PeerIdentity *peer,
-                         const struct GNUNET_MessageHeader *msg)
+                          const struct GNUNET_MessageHeader *msg)
 {
   struct Session *session;
   struct GSC_TypeMap *nmap;
 
   nmap = GSC_TYPEMAP_get_from_message (msg);
   if (NULL == nmap)
-    return; /* malformed */
+    return;                     /* malformed */
   session = find_session (peer);
   if (NULL == session)
   {
     GNUNET_break (0);
     return;
   }
-  GSC_CLIENTS_notify_clients_about_neighbour (peer,
-                                             NULL, 0, /* FIXME: ATS */
-                                             session->tmap,
-                                             nmap);
-  if (NULL != session->tmap)
-    GSC_TYPEMAP_destroy (session->tmap);
+  GSC_CLIENTS_notify_clients_about_neighbour (peer, NULL, 0,    /* FIXME: ATS */
+                                              session->tmap, nmap);
+  GSC_TYPEMAP_destroy (session->tmap);
   session->tmap = nmap;
 }
 
@@ -783,7 +765,7 @@ GSC_SESSIONS_set_typemap (const struct GNUNET_PeerIdentity *peer,
  */
 void
 GSC_SESSIONS_add_to_typemap (const struct GNUNET_PeerIdentity *peer,
-                            uint16_t type)
+                             uint16_t type)
 {
   struct Session *session;
   struct GSC_TypeMap *nmap;
@@ -792,18 +774,12 @@ GSC_SESSIONS_add_to_typemap (const struct GNUNET_PeerIdentity *peer,
     return;
   session = find_session (peer);
   GNUNET_assert (NULL != session);
-  if (GNUNET_YES ==
-      GSC_TYPEMAP_test_match (session->tmap,
-                             &type, 1))
-    return; /* already in it */
-  nmap = GSC_TYPEMAP_extend (session->tmap,
-                            &type, 1);
-  GSC_CLIENTS_notify_clients_about_neighbour (peer,
-                                             NULL, 0, /* FIXME: ATS */
-                                             session->tmap,
-                                             nmap);
-  if (NULL != session->tmap)
-    GSC_TYPEMAP_destroy (session->tmap);
+  if (GNUNET_YES == GSC_TYPEMAP_test_match (session->tmap, &type, 1))
+    return;                     /* already in it */
+  nmap = GSC_TYPEMAP_extend (session->tmap, &type, 1);
+  GSC_CLIENTS_notify_clients_about_neighbour (peer, NULL, 0,    /* FIXME: ATS */
+                                              session->tmap, nmap);
+  GSC_TYPEMAP_destroy (session->tmap);
   session->tmap = nmap;
 }
 
@@ -842,12 +818,9 @@ free_session_helper (void *cls, const GNUNET_HashCode * key, void *value)
 void
 GSC_SESSIONS_done ()
 {
-  GNUNET_CONTAINER_multihashmap_iterate (sessions,
-                                        &free_session_helper,
-                                         NULL);
+  GNUNET_CONTAINER_multihashmap_iterate (sessions, &free_session_helper, NULL);
   GNUNET_CONTAINER_multihashmap_destroy (sessions);
   sessions = NULL;
 }
 
 /* end of gnunet-service-core_sessions.c */
-