more code cleanup
[oweals/gnunet.git] / src / transport / gnunet-service-transport.c
index 56480d02009b31f6b8b860b1b124314e2816bec0..ae88b4f6f0fdb6be094f188f41db7548989ac7b1 100644 (file)
@@ -4,7 +4,7 @@
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
@@ -43,9 +43,7 @@
 
 #define DEBUG_PING_PONG GNUNET_NO
 
-#define SIGN_USELESS GNUNET_NO
-
-#define DEBUG_TRANSPORT_HELLO GNUNET_YES
+#define DEBUG_TRANSPORT_HELLO GNUNET_NO
 
 /**
  * Should we do some additional checks (to validate behavior
@@ -2010,6 +2008,63 @@ remove_session_validations (void *cls,
 }
 
 
+/**
+ * We've been disconnected from the other peer (for some
+ * connection-oriented transport).  Either quickly 
+ * re-establish the connection or signal the disconnect
+ * to the CORE.
+ *
+ * Only signal CORE level disconnect if ALL addresses
+ * for the peer are exhausted.
+ *
+ * @param p overall plugin context
+ * @param nl neighbour that was disconnected
+ */
+static void
+try_fast_reconnect (struct TransportPlugin *p,
+                   struct NeighbourList *nl)
+{
+  /* FIXME-MW: fast reconnect / transport switching not implemented... */
+  /* Note: the idea here is to hide problems with transports (or
+     switching between plugins) from the core to eliminate the need to
+     re-negotiate session keys and the like; OTOH, we should tell core
+     quickly (much faster than timeout) `if a connection was lost and
+     could not be re-established (i.e. other peer went down or is
+     unable / refuses to communicate);
+
+     So we should consider:
+     1) ideally: our own willingness / need to connect
+     2) prior failures to connect to this peer (by plugin)
+     3) ideally: reasons why other peer terminated (as far as knowable)
+     
+     Most importantly, it must be POSSIBLE for another peer to terminate
+     a connection for a while (without us instantly re-establishing it).
+     Similarly, if another peer is gone we should quickly notify CORE.
+     OTOH, if there was a minor glitch (i.e. crash of gnunet-service-transport
+     on the other end), we should reconnect in such a way that BOTH CORE
+     services never even notice.
+     Furthermore, the same mechanism (or small variation) could be used
+     to switch to a better-performing plugin (ATS).     
+
+     Finally, this needs to be tested throughly... */                                                          
+
+  /*
+   * GNUNET_NO in the call below makes transport disconnect the peer,
+   * even if only a single address (out of say, six) went away.  This
+   * function must be careful to ONLY disconnect if the peer is gone,
+   * not just a specifi address.
+   *
+   * More specifically, half the places it was used had it WRONG.
+   */
+
+  /* No reconnect, signal disconnect instead! */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+            "Disconnecting peer `%4s', %s\n", GNUNET_i2s(&nl->id),
+            "try_fast_reconnect");
+  disconnect_neighbour (nl, GNUNET_YES);
+}
+
+
 /**
  * Function that will be called whenever the plugin internally
  * cleans up a session pointer and hence the service needs to
@@ -2037,7 +2092,7 @@ plugin_env_session_end  (void *cls,
                                         session);
   nl = find_neighbour (peer);
   if (nl == NULL)
-    return;
+    return; /* was never marked as connected */
   rl = nl->plugins;
   while (rl != NULL)
     {
@@ -2046,7 +2101,7 @@ plugin_env_session_end  (void *cls,
       rl = rl->next;
     }
   if (rl == NULL)
-    return;
+    return; /* was never marked as connected */
   prev = NULL;
   pos = rl->addresses;
   while ( (pos != NULL) &&
@@ -2056,10 +2111,15 @@ plugin_env_session_end  (void *cls,
       pos = pos->next;
     }
   if (pos == NULL)
-    return;
+    return; /* was never marked as connected */
   pos->session = NULL;
   if (pos->addrlen != 0)
-    return;
+    {
+      if (nl->received_pong != GNUNET_NO)
+       try_fast_reconnect (p, nl);
+      return;
+    }
+  /* was inbound connection, free 'pos' */
   if (prev == NULL)
     rl->addresses = pos->next;
   else
@@ -2072,17 +2132,31 @@ plugin_env_session_end  (void *cls,
     }
   GNUNET_free (pos);
   if (nl->received_pong == GNUNET_NO)
-    return; /* nothing to do */
+    return; /* nothing to do, never connected... */
   /* check if we have any validated addresses left */
   pos = rl->addresses;
   while (pos != NULL)
     {
       if (pos->validated)
-       return;
+       {
+         try_fast_reconnect (p, nl);
+         return;
+       }
       pos = pos->next;
     }
   /* no valid addresses left, signal disconnect! */
-  disconnect_neighbour (nl, GNUNET_NO);  
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+            "Disconnecting peer `%4s', %s\n", GNUNET_i2s(&nl->id),
+            "plugin_env_session_end");
+  /* FIXME: This doesn't mean there are no addresses left for this PEER,
+   * it means there aren't any left for this PLUGIN/PEER combination! So
+   * calling disconnect_neighbor here with GNUNET_NO forces disconnect
+   * when it isn't necessary. Using GNUNET_YES at least checks to see
+   * if there are any addresses that work first, so as not to overdo it.
+   * --NE
+   */
+  disconnect_neighbour (nl, GNUNET_YES);
 }
 
 
@@ -2612,18 +2686,20 @@ add_to_foreign_address_list (void *cls,
  * @param cls closure ('struct NeighbourList*')
  * @param peer id of the peer, NULL for last call
  * @param h hello message for the peer (can be NULL)
- * @param trust amount of trust we have in the peer (not used)
  */
 static void
 add_hello_for_peer (void *cls,
                    const struct GNUNET_PeerIdentity *peer,
-                   const struct GNUNET_HELLO_Message *h, 
-                   uint32_t trust)
+                   const struct GNUNET_HELLO_Message *h)
 {
   struct NeighbourList *n = cls;
 
   if (peer == NULL)
     {
+      GNUNET_STATISTICS_update (stats,
+                                gettext_noop ("# outstanding peerinfo iterate requests"),
+                                -1,
+                                GNUNET_NO);
       n->piter = NULL;
       return;
     } 
@@ -2705,8 +2781,16 @@ setup_new_neighbour (const struct GNUNET_PeerIdentity *peer,
                                                   &neighbour_timeout_task, n);
   if (do_hello)
     {
+      GNUNET_STATISTICS_update (stats,
+                                gettext_noop ("# peerinfo iterate requests"),
+                                1,
+                                GNUNET_NO);
+      GNUNET_STATISTICS_update (stats,
+                                gettext_noop ("# outstanding peerinfo iterate requests"),
+                                1,
+                                GNUNET_NO);
       n->piter = GNUNET_PEERINFO_iterate (peerinfo, peer,
-                                         0, GNUNET_TIME_UNIT_FOREVER_REL,
+                                         GNUNET_TIME_UNIT_FOREVER_REL,
                                          &add_hello_for_peer, n);
       transmit_to_peer (NULL, NULL, 0,
                        HELLO_ADDRESS_EXPIRATION,
@@ -2975,7 +3059,12 @@ confirm_or_drop_neighbour (void *cls,
   struct NeighbourList * orig = cls;
 
   if (n == NULL)
-    disconnect_neighbour (orig, GNUNET_NO);
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Disconnecting peer `%4s', %s\n", GNUNET_i2s(&orig->id),
+              "confirm_or_drop_neighboUr");
+      disconnect_neighbour (orig, GNUNET_NO);
+    }
 }
 
 
@@ -3176,6 +3265,10 @@ send_periodic_ping (void *cls,
       slen = strlen (tp->short_name) + 1;
       tsize += slen + peer_address->addrlen;
     }
+  else
+    {
+      slen = 0; /* make gcc happy */
+    }
   message_buf = GNUNET_malloc(tsize);
   ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
   ping.challenge = htonl(va->challenge);
@@ -3289,13 +3382,19 @@ handle_payload_message (const struct GNUNET_MessageHeader *message,
   msize = ntohs (message->size);
   if (n->received_pong == GNUNET_NO)
     {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Received message of type %u and size %u from `%4s', but no pong yet!!\n",
+                  ntohs (message->type),
+                  ntohs (message->size),
+                  GNUNET_i2s (&n->id));
       GNUNET_free_non_null (n->pre_connect_message_buffer);
       n->pre_connect_message_buffer = GNUNET_malloc (msize);
       memcpy (n->pre_connect_message_buffer, message, msize);
       return;
     }
+
 #if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
              "Received message of type %u and size %u from `%4s', sending to all clients.\n",
              ntohs (message->type), 
              ntohs (message->size), 
@@ -3387,7 +3486,7 @@ check_pending_validation (void *cls,
   addr = (const char*) &pong[1];
   slen = strlen (ve->transport_name) + 1;
   if ( (ps - sizeof (struct TransportPongMessage) != ve->addrlen + slen) ||
-       (ve->challenge != challenge) ||       
+       (ve->challenge != challenge) ||
        (addr[slen-1] != '\0') ||
        (0 != strcmp (addr, ve->transport_name)) || 
        (ntohl (pong->purpose.size) 
@@ -3395,7 +3494,10 @@ check_pending_validation (void *cls,
        sizeof (uint32_t) +
        sizeof (struct GNUNET_TIME_AbsoluteNBO) +
        sizeof (struct GNUNET_PeerIdentity) + ve->addrlen + slen) )
-    return GNUNET_YES;
+    {
+      return GNUNET_YES;
+    }
+
   alen = ps - sizeof (struct TransportPongMessage) - slen;
   switch (ntohl (pong->purpose.purpose))
     {
@@ -3404,7 +3506,9 @@ check_pending_validation (void *cls,
           (0 != memcmp (&addr[slen],
                         ve->addr,
                         ve->addrlen)) )
-       return GNUNET_YES; /* different entry, keep trying! */
+        {
+          return GNUNET_YES; /* different entry, keep trying! */
+        }
       if (0 != memcmp (&pong->pid,
                       key,
                       sizeof (struct GNUNET_PeerIdentity))) 
@@ -3421,6 +3525,7 @@ check_pending_validation (void *cls,
          GNUNET_break_op (0);
          return GNUNET_NO;
        }
+
 #if DEBUG_TRANSPORT
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                  "Confirmed validity of address, peer `%4s' has address `%s' (%s).\n",
@@ -3433,7 +3538,9 @@ check_pending_validation (void *cls,
       break;
     case GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING:
       if (ve->addrlen != 0) 
-       return GNUNET_YES; /* different entry, keep trying */
+        {
+          return GNUNET_YES; /* different entry, keep trying */
+        }
       if ( (0 != memcmp (&pong->pid,
                         &my_identity,
                         sizeof (struct GNUNET_PeerIdentity))) ||
@@ -3460,7 +3567,7 @@ check_pending_validation (void *cls,
        }
       if (oal == NULL)
        {
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                      _("Not accepting PONG with address `%s' since I cannot confirm having this address.\n"),
                      a2s (ve->transport_name,
                           &addr[slen],
@@ -3476,6 +3583,7 @@ check_pending_validation (void *cls,
          GNUNET_break_op (0);
          return GNUNET_NO;
        }
+
 #if DEBUG_TRANSPORT
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                  "Confirmed that peer `%4s' is talking to us using address `%s' (%s) for us.\n",
@@ -3866,13 +3974,11 @@ run_validation (void *cls,
  * @param cls closure
  * @param peer id of the peer, NULL for last call
  * @param h hello message for the peer (can be NULL)
- * @param trust amount of trust we have in the peer (not used)
  */
 static void
 check_hello_validated (void *cls,
                        const struct GNUNET_PeerIdentity *peer,
-                       const struct GNUNET_HELLO_Message *h, 
-                      uint32_t trust)
+                       const struct GNUNET_HELLO_Message *h)
 {
   struct CheckHelloValidatedContext *chvc = cls;
   struct GNUNET_HELLO_Message *plain_hello;
@@ -3882,6 +3988,10 @@ check_hello_validated (void *cls,
 
   if (peer == NULL)
     {
+      GNUNET_STATISTICS_update (stats,
+                                gettext_noop ("# outstanding peerinfo iterate requests"),
+                                -1,
+                                GNUNET_NO);
       chvc->piter = NULL;
       if (GNUNET_NO == chvc->hello_known)
        {
@@ -3995,9 +4105,7 @@ process_hello (struct TransportPlugin *plugin,
                            gettext_noop ("# HELLOs received for validation"),
                            1,
                            GNUNET_NO);      
-  GNUNET_CRYPTO_hash (&publicKey,
-                      sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                      &target.hashPubKey);
+
   /* first, check if load is too high */
   if (GNUNET_SCHEDULER_get_load (sched,
                                 GNUNET_SCHEDULER_PRIORITY_BACKGROUND) > MAX_HELLO_LOAD)
@@ -4026,6 +4134,11 @@ process_hello (struct TransportPlugin *plugin,
       GNUNET_break_op (0);
       return GNUNET_SYSERR;
     }
+
+  GNUNET_CRYPTO_hash (&publicKey,
+                      sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                      &target.hashPubKey);
+
   if (0 == memcmp (&my_identity,
                   &target,
                   sizeof (struct GNUNET_PeerIdentity)))
@@ -4079,9 +4192,16 @@ process_hello (struct TransportPlugin *plugin,
                               chvc);
   /* finally, check if HELLO was previously validated
      (continuation will then schedule actual validation) */
+  GNUNET_STATISTICS_update (stats,
+                            gettext_noop ("# peerinfo iterate requests"),
+                            1,
+                            GNUNET_NO);
+  GNUNET_STATISTICS_update (stats,
+                            gettext_noop ("# outstanding peerinfo iterate requests"),
+                            1,
+                            GNUNET_NO);
   chvc->piter = GNUNET_PEERINFO_iterate (peerinfo,
                                          &target,
-                                         0,
                                          HELLO_VERIFICATION_TIMEOUT,
                                          &check_hello_validated, chvc);
   return GNUNET_OK;
@@ -4097,9 +4217,9 @@ process_hello (struct TransportPlugin *plugin,
  * gone.
  *
  * @param n the neighbour list entry for the peer
- * @param check should we just check if all plugins
- *        disconnected or must we ask all plugins to
- *        disconnect?
+ * @param check GNUNET_YES to check if ALL addresses for this peer
+ *              are gone, GNUNET_NO to force a disconnect of the peer
+ *              regardless of whether other addresses exist.
  */
 static void
 disconnect_neighbour (struct NeighbourList *n, int check)
@@ -4120,7 +4240,12 @@ disconnect_neighbour (struct NeighbourList *n, int check)
           while (peer_addresses != NULL)
             {
               if (GNUNET_YES == peer_addresses->connected)
-                return;             /* still connected */
+                {
+                  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                            "NOT Disconnecting from `%4s', still have live addresses!\n",
+                            GNUNET_i2s (&n->id));
+                  return;             /* still connected */
+                }
               peer_addresses = peer_addresses->next;
             }
           rpos = rpos->next;
@@ -4211,6 +4336,10 @@ disconnect_neighbour (struct NeighbourList *n, int check)
   if (n->piter != NULL)
     {
       GNUNET_PEERINFO_iterate_cancel (n->piter);
+      GNUNET_STATISTICS_update (stats,
+                                gettext_noop ("# outstanding peerinfo iterate requests"),
+                                -1,
+                                GNUNET_NO);
       n->piter = NULL;
     }
   /* finally, free n itself */
@@ -4338,6 +4467,18 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
       /* peer wants to confirm that this is one of our addresses */
       addr += slen;
       alen -= slen;
+      if (GNUNET_OK !=
+         plugin->api->check_address (plugin->api->cls,
+                                     addr,
+                                     alen))
+       {
+         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                     _("Not confirming PING with address `%s' since I cannot confirm having this address.\n"),
+                     a2s (plugin->short_name,
+                          addr,
+                          alen));
+         return GNUNET_NO;
+       }
       oal = plugin->addresses;
       while (NULL != oal)
        {
@@ -4348,15 +4489,6 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
            break;
          oal = oal->next;
        }
-      if (oal == NULL)
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                     _("Not confirming PING with address `%s' since I cannot confirm having this address.\n"),
-                     a2s (plugin->short_name,
-                          addr,
-                          alen));
-         return GNUNET_NO;
-       }
       pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + alen + slen);
       pong->header.size = htons (sizeof (struct TransportPongMessage) + alen + slen);
       pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
@@ -4372,8 +4504,9 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
             &my_identity, 
             sizeof(struct GNUNET_PeerIdentity));
       memcpy (&pong[1], plugin->short_name, slen);
-      memcpy (&((char*)&pong[1])[slen], &oal[1], alen);
-      if (GNUNET_TIME_absolute_get_remaining (oal->pong_sig_expires).value < PONG_SIGNATURE_LIFETIME.value / 4)
+      memcpy (&((char*)&pong[1])[slen], addr, alen);
+      if ( (oal != NULL) &&
+          (GNUNET_TIME_absolute_get_remaining (oal->pong_sig_expires).value < PONG_SIGNATURE_LIFETIME.value / 4) )
        {
          /* create / update cached sig */
 #if DEBUG_TRANSPORT
@@ -4386,15 +4519,28 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
          GNUNET_assert (GNUNET_OK ==
                         GNUNET_CRYPTO_rsa_sign (my_private_key,
                                                 &pong->purpose,
-                                                &oal->pong_signature));
+                                                &oal->pong_signature));            
+         memcpy (&pong->signature,
+                 &oal->pong_signature,
+                 sizeof (struct GNUNET_CRYPTO_RsaSignature));    
+       }
+      else if (oal == NULL)
+       {
+         /* not using cache (typically DV-only) */
+         pong->expiration = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME));
+         GNUNET_assert (GNUNET_OK ==
+                        GNUNET_CRYPTO_rsa_sign (my_private_key,
+                                                &pong->purpose,
+                                                &pong->signature));        
        }
       else
        {
+         /* can used cached version */
          pong->expiration = GNUNET_TIME_absolute_hton (oal->pong_sig_expires);
+         memcpy (&pong->signature,
+                 &oal->pong_signature,
+                 sizeof (struct GNUNET_CRYPTO_RsaSignature));    
        }
-      memcpy (&pong->signature,
-             &oal->pong_signature,
-             sizeof (struct GNUNET_CRYPTO_RsaSignature));    
     }
   n = find_neighbour(peer);
   GNUNET_assert (n != NULL);
@@ -4487,7 +4633,6 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
   uint16_t msize;
   struct NeighbourList *n;
   struct GNUNET_TIME_Relative ret;
-
   if (is_blacklisted (peer, plugin))
     return GNUNET_TIME_UNIT_FOREVER_REL;
 
@@ -4550,6 +4695,7 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
                                    GNUNET_NO);
          return GNUNET_CONSTANTS_QUOTA_VIOLATION_TIMEOUT;
        }
+
 #if DEBUG_PING_PONG
           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                       "Received message of type %u and size %u from `%4s', sending to all clients.\n",
@@ -4580,7 +4726,7 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
   ret = GNUNET_BANDWIDTH_tracker_get_delay (&n->in_tracker, 0);
   if (ret.value > 0)
     {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                  "Throttling read (%llu bytes excess at %u b/s), waiting %llums before reading more.\n",
                  (unsigned long long) n->in_tracker.consumption_since_last_update__,
                  (unsigned int) n->in_tracker.available_bytes_per_s__,
@@ -4606,10 +4752,12 @@ handle_start (void *cls,
               struct GNUNET_SERVER_Client *client,
               const struct GNUNET_MessageHeader *message)
 {
+  const struct StartMessage *start;
   struct TransportClient *c;
   struct ConnectInfoMessage cim;
   struct NeighbourList *n;
 
+  start = (const struct StartMessage*) message;
 #if DEBUG_TRANSPORT
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Received `%s' request from client\n", "START");
@@ -4626,6 +4774,17 @@ handle_start (void *cls,
         }
       c = c->next;
     }
+  if ( (GNUNET_NO != ntohl (start->do_check)) &&
+       (0 != memcmp (&start->self,
+                    &my_identity,
+                    sizeof (struct GNUNET_PeerIdentity))) )
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 _("Rejecting control connection from peer `%s', which is not me!\n"),
+                 GNUNET_i2s (&start->self));
+      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+      return;      
+    }
   c = GNUNET_malloc (sizeof (struct TransportClient));
   c->next = clients;
   clients = c;
@@ -4835,7 +4994,12 @@ handle_set_quota (void *cls,
   GNUNET_BANDWIDTH_tracker_update_quota (&n->in_tracker,
                                         qsm->quota);
   if (0 == ntohl (qsm->quota.value__)) 
-    disconnect_neighbour (n, GNUNET_NO);    
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Disconnecting peer `%4s', %s\n", GNUNET_i2s(&n->id),
+                "SET_QUOTA");
+      disconnect_neighbour (n, GNUNET_NO);
+    }
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
 }
 
@@ -4942,6 +5106,7 @@ create_environment (struct TransportPlugin *plug)
   plug->env.cfg = cfg;
   plug->env.sched = sched;
   plug->env.my_identity = &my_identity;
+  plug->env.our_hello = &our_hello;
   plug->env.cls = plug;
   plug->env.receive = &plugin_env_receive;
   plug->env.notify_address = &plugin_env_notify_address;
@@ -5092,7 +5257,12 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   struct CheckHelloValidatedContext *chvc;
 
   while (neighbours != NULL)
-    disconnect_neighbour (neighbours, GNUNET_NO);
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Disconnecting peer `%4s', %s\n", GNUNET_i2s(&neighbours->id),
+              "SHUTDOWN_TASK");
+      disconnect_neighbour (neighbours, GNUNET_NO);
+    }
 #if DEBUG_TRANSPORT
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Transport service is unloading plugins...\n");
@@ -5131,7 +5301,13 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     {
       chvc_head = chvc->next;
       if (chvc->piter != NULL)
-       GNUNET_PEERINFO_iterate_cancel (chvc->piter);      
+        {
+          GNUNET_PEERINFO_iterate_cancel (chvc->piter);
+          GNUNET_STATISTICS_update (stats,
+                                    gettext_noop ("# outstanding peerinfo iterate requests"),
+                                    -1,
+                                    GNUNET_NO);
+        }
       else
        GNUNET_break (0);
       GNUNET_assert (chvc->ve_count == 0);
@@ -5172,7 +5348,7 @@ run (void *cls,
 {
   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
     {&handle_start, NULL,
-     GNUNET_MESSAGE_TYPE_TRANSPORT_START, 0},
+     GNUNET_MESSAGE_TYPE_TRANSPORT_START, sizeof (struct StartMessage)},
     {&handle_hello, NULL,
      GNUNET_MESSAGE_TYPE_HELLO, 0},
     {&handle_send, NULL,