fixes
[oweals/gnunet.git] / src / dv / gnunet-service-dv.c
index c1f5ec8c5c42608b7a2bb084db54aadacb4ea6bf..844e44b6ffb4573962a6cdb5b9920bb3655c669b 100644 (file)
@@ -4,7 +4,7 @@
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
@@ -27,9 +27,6 @@
  * @author Christian Grothoff
  * @author Nathan Evans
  *
  * @author Christian Grothoff
  * @author Nathan Evans
  *
- * TODO: The gossip rates need to be worked out.  Probably many other things
- * as well.
- *
  */
 #include "platform.h"
 #include "gnunet_client_lib.h"
  */
 #include "platform.h"
 #include "gnunet_client_lib.h"
@@ -43,6 +40,7 @@
 #include "gnunet_hello_lib.h"
 #include "gnunet_peerinfo_service.h"
 #include "gnunet_crypto_lib.h"
 #include "gnunet_hello_lib.h"
 #include "gnunet_peerinfo_service.h"
 #include "gnunet_crypto_lib.h"
+#include "gnunet_statistics_service.h"
 #include "dv.h"
 
 /**
 #include "dv.h"
 
 /**
@@ -564,10 +562,6 @@ static struct GNUNET_PeerIdentity my_identity;
  */
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
 
  */
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
 
-/**
- * The scheduler for this service.
- */
-static struct GNUNET_SCHEDULER_Handle *sched;
 
 /**
  * The client, the DV plugin connected to us.  Hopefully
 
 /**
  * The client, the DV plugin connected to us.  Hopefully
@@ -647,6 +641,11 @@ static struct GNUNET_CONTAINER_Heap *neighbor_min_heap;
  */
 static struct GNUNET_CONTAINER_Heap *neighbor_max_heap;
 
  */
 static struct GNUNET_CONTAINER_Heap *neighbor_max_heap;
 
+/**
+ * Handle for the statistics service.
+ */
+struct GNUNET_STATISTICS_Handle *stats;
+
 /**
  * How far out to keep peers we learn about.
  */
 /**
  * How far out to keep peers we learn about.
  */
@@ -814,7 +813,6 @@ void send_to_plugin(const struct GNUNET_PeerIdentity * sender,
   received_msg = GNUNET_malloc(size);
   received_msg->header.size = htons(size);
   received_msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE);
   received_msg = GNUNET_malloc(size);
   received_msg->header.size = htons(size);
   received_msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE);
-  received_msg->sender_address_len = htonl(sender_address_len);
   received_msg->distance = htonl(cost);
   received_msg->msg_len = htonl(message_size);
   /* Set the sender in this message to be the original sender! */
   received_msg->distance = htonl(cost);
   received_msg->msg_len = htonl(message_size);
   /* Set the sender in this message to be the original sender! */
@@ -857,7 +855,7 @@ size_t core_transmit_notify (void *cls,
  */
 static void
 try_core_send (void *cls,
  */
 static void
 try_core_send (void *cls,
-                 const struct GNUNET_SCHEDULER_TaskContext *tc)
+               const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct PendingMessage *pending;
   pending = core_pending_head;
 {
   struct PendingMessage *pending;
   pending = core_pending_head;
@@ -865,10 +863,17 @@ try_core_send (void *cls,
   if (core_transmit_handle != NULL)
     return; /* Message send already in progress */
 
   if (core_transmit_handle != NULL)
     return; /* Message send already in progress */
 
-  if (pending != NULL)
-    core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, pending->importance, pending->timeout, &pending->recipient, pending->msg_size, &core_transmit_notify, NULL);
+  if ((pending != NULL) && (coreAPI != NULL))
+    core_transmit_handle = GNUNET_CORE_notify_transmit_ready (coreAPI,
+                                                             GNUNET_YES,
+                                                             pending->importance,
+                                                             pending->timeout, 
+                                                             &pending->recipient,
+                                                             pending->msg_size,
+                                                             &core_transmit_notify, NULL);
 }
 
 }
 
+
 /**
  * Function called to notify a client about the socket
  * being ready to queue more data.  "buf" will be
 /**
  * Function called to notify a client about the socket
  * being ready to queue more data.  "buf" will be
@@ -939,9 +944,9 @@ size_t core_transmit_notify (void *cls,
     }
   /*reply = core_pending_head;*/
 
     }
   /*reply = core_pending_head;*/
 
-  GNUNET_SCHEDULER_add_now(sched, &try_core_send, NULL);
+  GNUNET_SCHEDULER_add_now(&try_core_send, NULL);
   /*if (reply != NULL)
   /*if (reply != NULL)
-    core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, reply->importance, reply->timeout, &reply->recipient, reply->msg_size, &core_transmit_notify, NULL);*/
+    core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, GNUNET_YES,  reply->importance, reply->timeout, &reply->recipient, reply->msg_size, &core_transmit_notify, NULL);*/
 
   return off;
 }
 
   return off;
 }
@@ -1038,7 +1043,7 @@ send_message_via (const struct GNUNET_PeerIdentity *sender,
                                      core_pending_tail,
                                      pending_message);
 
                                      core_pending_tail,
                                      pending_message);
 
-  GNUNET_SCHEDULER_add_now(sched, try_core_send, NULL);
+  GNUNET_SCHEDULER_add_now(try_core_send, NULL);
 
   return GNUNET_YES;
 }
 
   return GNUNET_YES;
 }
@@ -1184,7 +1189,7 @@ send_message (const struct GNUNET_PeerIdentity * recipient,
   memcpy (&toSend[1], message, message_size);
   if ((source != NULL) && (source->pkey == NULL)) /* Test our hypothesis about message failures! */
     {
   memcpy (&toSend[1], message, message_size);
   if ((source != NULL) && (source->pkey == NULL)) /* Test our hypothesis about message failures! */
     {
-      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s: Sending message, but anticipate recipient will not know sender!!!\n\n\n");
+      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s: Sending message, but anticipate recipient will not know sender!!!\n\n\n", my_short_id);
     }
   GNUNET_CONTAINER_DLL_insert_after (core_pending_head,
                                      core_pending_tail,
     }
   GNUNET_CONTAINER_DLL_insert_after (core_pending_head,
                                      core_pending_tail,
@@ -1194,7 +1199,7 @@ send_message (const struct GNUNET_PeerIdentity * recipient,
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Notifying core of send size %d to destination `%s'\n", "DV SEND MESSAGE", msg_size, GNUNET_i2s(recipient));
 #endif
 
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Notifying core of send size %d to destination `%s'\n", "DV SEND MESSAGE", msg_size, GNUNET_i2s(recipient));
 #endif
 
-  GNUNET_SCHEDULER_add_now(sched, try_core_send, NULL);
+  GNUNET_SCHEDULER_add_now(try_core_send, NULL);
   return (int) cost;
 }
 
   return (int) cost;
 }
 
@@ -1297,6 +1302,48 @@ void send_message_delayed (void *cls,
 }
 #endif
 
 }
 #endif
 
+/**
+ * Get distance information from 'atsi'.
+ *
+ * @param atsi performance data
+ * @return connected transport distance
+ */
+static uint32_t
+get_atsi_distance (const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+{
+  while ( (ntohl (atsi->type) != GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR) &&
+          (ntohl (atsi->type) != GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE) )
+    atsi++;
+  if (ntohl (atsi->type) == GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR)
+    {
+      GNUNET_break (0);
+      /* FIXME: we do not have distance data? Assume direct neighbor. */
+      return DIRECT_NEIGHBOR_COST;
+    }
+  return ntohl (atsi->value);
+}
+
+/**
+ * Find latency information in 'atsi'.
+ *
+ * @param atsi performance data
+ * @return connection latency
+ */
+static struct GNUNET_TIME_Relative
+get_atsi_latency (const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+{
+  while ( (ntohl (atsi->type) != GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR) &&
+          (ntohl (atsi->type) != GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY) )
+    atsi++;
+  if (ntohl (atsi->type) == GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR)
+    {
+      GNUNET_break (0);
+      /* how can we not have latency data? */
+      return GNUNET_TIME_UNIT_SECONDS;
+    }
+  /* FIXME: Multiply by GNUNET_TIME_UNIT_MILLISECONDS (1) to get as a GNUNET_TIME_Relative */
+  return GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, ntohl (atsi->value));
+}
 
 /**
  * Core handler for dv data messages.  Whatever this message
 
 /**
  * Core handler for dv data messages.  Whatever this message
@@ -1307,14 +1354,13 @@ void send_message_delayed (void *cls,
  * @param cls closure
  * @param peer peer which sent the message (immediate sender)
  * @param message the message
  * @param cls closure
  * @param peer peer which sent the message (immediate sender)
  * @param message the message
- * @param latency the latency of the connection we received the message from
- * @param distance the distance to the immediate peer
- */
-static int handle_dv_data_message (void *cls,
-                                   const struct GNUNET_PeerIdentity * peer,
-                                   const struct GNUNET_MessageHeader * message,
-                                   struct GNUNET_TIME_Relative latency,
-                                   uint32_t distance)
+ * @param atsi transport ATS information (latency, distance, etc.)
+ */
+static int 
+handle_dv_data_message (void *cls,
+                       const struct GNUNET_PeerIdentity * peer,
+                       const struct GNUNET_MessageHeader * message,
+                       const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   const p2p_dv_MESSAGE_Data *incoming = (const p2p_dv_MESSAGE_Data *) message;
   const struct GNUNET_MessageHeader *packed_message;
 {
   const p2p_dv_MESSAGE_Data *incoming = (const p2p_dv_MESSAGE_Data *) message;
   const struct GNUNET_MessageHeader *packed_message;
@@ -1340,6 +1386,8 @@ static int handle_dv_data_message (void *cls,
   int ret;
   size_t packed_message_size;
   char *cbuf;
   int ret;
   size_t packed_message_size;
   char *cbuf;
+  uint32_t distance; /* Distance information */
+  struct GNUNET_TIME_Relative latency; /* Latency information */
 
   packed_message_size = ntohs(incoming->header.size) - sizeof(p2p_dv_MESSAGE_Data);
 #if DEBUG_DV
 
   packed_message_size = ntohs(incoming->header.size) - sizeof(p2p_dv_MESSAGE_Data);
 #if DEBUG_DV
@@ -1349,7 +1397,6 @@ static int handle_dv_data_message (void *cls,
 
   if (ntohs (incoming->header.size) <  sizeof (p2p_dv_MESSAGE_Data) + sizeof (struct GNUNET_MessageHeader))
     {
 
   if (ntohs (incoming->header.size) <  sizeof (p2p_dv_MESSAGE_Data) + sizeof (struct GNUNET_MessageHeader))
     {
-
 #if DEBUG_DV
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "`%s': Message sizes don't add up, total size %u, expected at least %u!\n", "dv service", ntohs(incoming->header.size), sizeof (p2p_dv_MESSAGE_Data) + sizeof (struct GNUNET_MessageHeader));
 #if DEBUG_DV
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "`%s': Message sizes don't add up, total size %u, expected at least %u!\n", "dv service", ntohs(incoming->header.size), sizeof (p2p_dv_MESSAGE_Data) + sizeof (struct GNUNET_MessageHeader));
@@ -1357,6 +1404,9 @@ static int handle_dv_data_message (void *cls,
       return GNUNET_SYSERR;
     }
 
       return GNUNET_SYSERR;
     }
 
+  /* Iterate over ATS_Information to get distance and latency */
+  latency = get_atsi_latency(atsi);
+  distance = get_atsi_distance(atsi);
   dn = GNUNET_CONTAINER_multihashmap_get (direct_neighbors,
                                           &peer->hashPubKey);
   if (dn == NULL)
   dn = GNUNET_CONTAINER_multihashmap_get (direct_neighbors,
                                           &peer->hashPubKey);
   if (dn == NULL)
@@ -1386,7 +1436,7 @@ static int handle_dv_data_message (void *cls,
     {
 #if DEBUG_DV_MESSAGES
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     {
 #if DEBUG_DV_MESSAGES
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "%s: unknown sender (%u), Message uid %llu from %s!\n", my_short_id, ntohl(incoming->sender), ntohl(incoming->uid), GNUNET_i2s(&dn->identity));
+                  "%s: unknown sender (%u), Message uid %u from %s!\n", my_short_id, ntohl(incoming->sender), ntohl(incoming->uid), GNUNET_i2s(&dn->identity));
       pos = dn->referee_head;
       while ((NULL != pos) && (pos->referrer_id != sid))
       {
       pos = dn->referee_head;
       while ((NULL != pos) && (pos->referrer_id != sid))
       {
@@ -1396,8 +1446,6 @@ static int handle_dv_data_message (void *cls,
         pos = pos->next;
       }
 #endif
         pos = pos->next;
       }
 #endif
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "%s: unknown sender (%u), Message uid %llu from %s!\n", my_short_id, ntohl(incoming->sender), ntohl(incoming->uid), GNUNET_i2s(&dn->identity));
 
       found_pos = -1;
       for (i = 0; i< MAX_OUTSTANDING_MESSAGES; i++)
 
       found_pos = -1;
       for (i = 0; i< MAX_OUTSTANDING_MESSAGES; i++)
@@ -1480,9 +1528,6 @@ static int handle_dv_data_message (void *cls,
   if (0 == memcmp (destination, peer, sizeof (struct GNUNET_PeerIdentity)))
     {
       /* FIXME: create stat: routing loop-discard! */
   if (0 == memcmp (destination, peer, sizeof (struct GNUNET_PeerIdentity)))
     {
       /* FIXME: create stat: routing loop-discard! */
-#if DEBUG_DV_PEER_NUMBERS
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "\n\n\nLoopy loo message\n\n\n");
-#endif
 
 #if DEBUG_DV_MESSAGES
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
 
 #if DEBUG_DV_MESSAGES
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1500,7 +1545,7 @@ static int handle_dv_data_message (void *cls,
 #endif
 
 #if DELAY_FORWARDS
 #endif
 
 #if DELAY_FORWARDS
-  if (GNUNET_TIME_absolute_get_duration(pos->last_gossip).value < GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 2).value)
+  if (GNUNET_TIME_absolute_get_duration(pos->last_gossip).abs_value < GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 2).abs_value)
     {
       delayed_context = GNUNET_malloc(sizeof(struct DelayedMessageContext));
       memcpy(&delayed_context->dest, destination, sizeof(struct GNUNET_PeerIdentity));
     {
       delayed_context = GNUNET_malloc(sizeof(struct DelayedMessageContext));
       memcpy(&delayed_context->dest, destination, sizeof(struct GNUNET_PeerIdentity));
@@ -1509,7 +1554,7 @@ static int handle_dv_data_message (void *cls,
       memcpy(delayed_context->message, packed_message, packed_message_size);
       delayed_context->message_size = packed_message_size;
       delayed_context->uid = ntohl(incoming->uid);
       memcpy(delayed_context->message, packed_message, packed_message_size);
       delayed_context->message_size = packed_message_size;
       delayed_context->uid = ntohl(incoming->uid);
-      GNUNET_SCHEDULER_add_delayed(sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 2500), &send_message_delayed, delayed_context);
+      GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 2500), &send_message_delayed, delayed_context);
       return GNUNET_OK;
     }
   else
       return GNUNET_OK;
     }
   else
@@ -1529,9 +1574,10 @@ static int handle_dv_data_message (void *cls,
   else
     {
 #if DEBUG_MESSAGE_DROP
   else
     {
 #if DEBUG_MESSAGE_DROP
-      direct_id = GNUNET_strdup(GNUNET_i2s(&dn->identity));
+      char *direct_id = GNUNET_strdup(GNUNET_i2s(&dn->identity));
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "%s: DROPPING MESSAGE type %d, forwarding failed! Message immediately from %s!\n", GNUNET_i2s(&my_identity), ntohs(((struct GNUNET_MessageHeader *)&incoming[1])->type), direct_id);
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "%s: DROPPING MESSAGE type %d, forwarding failed! Message immediately from %s!\n", GNUNET_i2s(&my_identity), ntohs(((struct GNUNET_MessageHeader *)&incoming[1])->type), direct_id);
+      GNUNET_free (direct_id);
 #endif
       return GNUNET_SYSERR;
     }
 #endif
       return GNUNET_SYSERR;
     }
@@ -1550,9 +1596,9 @@ static int handle_dv_data_message (void *cls,
  */
 int print_neighbors (void *cls,
                      const GNUNET_HashCode * key,
  */
 int print_neighbors (void *cls,
                      const GNUNET_HashCode * key,
-                     void *value)
+                     void *abs_value)
 {
 {
-  struct DistantNeighbor *distant_neighbor = value;
+  struct DistantNeighbor *distant_neighbor = abs_value;
   char my_shortname[5];
   char referrer_shortname[5];
   memcpy(&my_shortname, GNUNET_i2s(&my_identity), 4);
   char my_shortname[5];
   char referrer_shortname[5];
   memcpy(&my_shortname, GNUNET_i2s(&my_identity), 4);
@@ -1585,15 +1631,15 @@ neighbor_send_task (void *cls,
   p2p_dv_MESSAGE_NeighborInfo *message;
   struct PendingMessage *pending_message;
 
   p2p_dv_MESSAGE_NeighborInfo *message;
   struct PendingMessage *pending_message;
 
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
-  {
+  if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+    {
 #if DEBUG_DV_GOSSIP
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "%s: Called with reason shutdown, shutting down!\n",
               GNUNET_i2s(&my_identity));
 #endif
 #if DEBUG_DV_GOSSIP
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "%s: Called with reason shutdown, shutting down!\n",
               GNUNET_i2s(&my_identity));
 #endif
-    return;
-  }
+      return;
+    }
 
   if (send_context->fast_gossip_list_head != NULL)
     {
 
   if (send_context->fast_gossip_list_head != NULL)
     {
@@ -1663,9 +1709,9 @@ neighbor_send_task (void *cls,
                                          core_pending_tail,
                                          pending_message);
 
                                          core_pending_tail,
                                          pending_message);
 
-      GNUNET_SCHEDULER_add_now(sched, try_core_send, NULL);
+      GNUNET_SCHEDULER_add_now(try_core_send, NULL);
       /*if (core_transmit_handle == NULL)
       /*if (core_transmit_handle == NULL)
-        core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, default_dv_priority, GNUNET_TIME_relative_get_forever(), &to->identity, sizeof(p2p_dv_MESSAGE_NeighborInfo), &core_transmit_notify, NULL);*/
+        core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, GNUNET_YES,  default_dv_priority, GNUNET_TIME_relative_get_forever(), &to->identity, sizeof(p2p_dv_MESSAGE_NeighborInfo), &core_transmit_notify, NULL);*/
 
     }
 
 
     }
 
@@ -1674,14 +1720,14 @@ neighbor_send_task (void *cls,
 #if DEBUG_DV_PEER_NUMBERS
       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "DV SERVICE: still in fast send mode\n");
 #endif
 #if DEBUG_DV_PEER_NUMBERS
       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "DV SERVICE: still in fast send mode\n");
 #endif
-      send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, send_context);
+      send_context->task = GNUNET_SCHEDULER_add_now(&neighbor_send_task, send_context);
     }
   else
     {
 #if DEBUG_DV_PEER_NUMBERS
       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "DV SERVICE: entering slow send mode\n");
 #endif
     }
   else
     {
 #if DEBUG_DV_PEER_NUMBERS
       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "DV SERVICE: entering slow send mode\n");
 #endif
-      send_context->task = GNUNET_SCHEDULER_add_delayed(sched, GNUNET_DV_DEFAULT_SEND_INTERVAL, &neighbor_send_task, send_context);
+      send_context->task = GNUNET_SCHEDULER_add_delayed(GNUNET_DV_DEFAULT_SEND_INTERVAL, &neighbor_send_task, send_context);
     }
 
   return;
     }
 
   return;
@@ -1727,10 +1773,10 @@ handle_start (void *cls,
  */
 int send_iterator (void *cls,
                    const GNUNET_HashCode * key,
  */
 int send_iterator (void *cls,
                    const GNUNET_HashCode * key,
-                   void *value)
+                   void *abs_value)
 {
   struct DV_SendContext *send_context = cls;
 {
   struct DV_SendContext *send_context = cls;
-  struct DistantNeighbor *distant_neighbor = value;
+  struct DistantNeighbor *distant_neighbor = abs_value;
 
   if (memcmp(distant_neighbor->referrer, send_context->direct_peer, sizeof(struct GNUNET_PeerIdentity)) == 0) /* They match, send and free */
     {
 
   if (memcmp(distant_neighbor->referrer, send_context->direct_peer, sizeof(struct GNUNET_PeerIdentity)) == 0) /* They match, send and free */
     {
@@ -1917,14 +1963,12 @@ void handle_dv_send_message (void *cls,
 static int handle_dv_gossip_message (void *cls,
                                      const struct GNUNET_PeerIdentity *peer,
                                      const struct GNUNET_MessageHeader *message,
 static int handle_dv_gossip_message (void *cls,
                                      const struct GNUNET_PeerIdentity *peer,
                                      const struct GNUNET_MessageHeader *message,
-                                     struct GNUNET_TIME_Relative latency,
-                                     uint32_t distance);
+                                     const struct GNUNET_TRANSPORT_ATS_Information *atsi);
 
 static int handle_dv_disconnect_message (void *cls,
                                          const struct GNUNET_PeerIdentity *peer,
                                          const struct GNUNET_MessageHeader *message,
 
 static int handle_dv_disconnect_message (void *cls,
                                          const struct GNUNET_PeerIdentity *peer,
                                          const struct GNUNET_MessageHeader *message,
-                                         struct GNUNET_TIME_Relative latency,
-                                         uint32_t distance);
+                                        const struct GNUNET_TRANSPORT_ATS_Information *atsi);
 /** End forward declarations **/
 
 
 /** End forward declarations **/
 
 
@@ -1966,8 +2010,8 @@ distant_neighbor_free (struct DistantNeighbor *referee)
       GNUNET_CONTAINER_DLL_remove (referrer->referee_head,
                          referrer->referee_tail, referee);
     }
       GNUNET_CONTAINER_DLL_remove (referrer->referee_head,
                          referrer->referee_tail, referee);
     }
-  GNUNET_CONTAINER_heap_remove_node (neighbor_max_heap, referee->max_loc);
-  GNUNET_CONTAINER_heap_remove_node (neighbor_min_heap, referee->min_loc);
+  GNUNET_CONTAINER_heap_remove_node (referee->max_loc);
+  GNUNET_CONTAINER_heap_remove_node (referee->min_loc);
   GNUNET_CONTAINER_multihashmap_remove_all (extended_neighbors,
                                     &referee->identity.hashPubKey);
   GNUNET_free_non_null (referee->pkey);
   GNUNET_CONTAINER_multihashmap_remove_all (extended_neighbors,
                                     &referee->identity.hashPubKey);
   GNUNET_free_non_null (referee->pkey);
@@ -1988,7 +2032,7 @@ direct_neighbor_free (struct DirectNeighbor *direct)
   send_context = direct->send_context;
 
   if (send_context->task != GNUNET_SCHEDULER_NO_TASK)
   send_context = direct->send_context;
 
   if (send_context->task != GNUNET_SCHEDULER_NO_TASK)
-    GNUNET_SCHEDULER_cancel(sched, send_context->task);
+    GNUNET_SCHEDULER_cancel(send_context->task);
 
   about_list = send_context->fast_gossip_list_head;
   while (about_list != NULL)
 
   about_list = send_context->fast_gossip_list_head;
   while (about_list != NULL)
@@ -2041,9 +2085,9 @@ static int schedule_disconnect_messages (void *cls,
                                      core_pending_tail,
                                      pending_message);
 
                                      core_pending_tail,
                                      pending_message);
 
-  GNUNET_SCHEDULER_add_now(sched, try_core_send, NULL);
+  GNUNET_SCHEDULER_add_now(try_core_send, NULL);
   /*if (core_transmit_handle == NULL)
   /*if (core_transmit_handle == NULL)
-    core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, default_dv_priority, GNUNET_TIME_relative_get_forever(), &notify->identity, sizeof(p2p_dv_MESSAGE_Disconnect), &core_transmit_notify, NULL);*/
+    core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, GNUNET_YES, default_dv_priority, GNUNET_TIME_relative_get_forever(), &notify->identity, sizeof(p2p_dv_MESSAGE_Disconnect), &core_transmit_notify, NULL);*/
 
   return GNUNET_YES;
 }
 
   return GNUNET_YES;
 }
@@ -2108,6 +2152,7 @@ shutdown_task (void *cls,
   GNUNET_CONTAINER_heap_destroy(neighbor_min_heap);
 
   GNUNET_CORE_disconnect (coreAPI);
   GNUNET_CONTAINER_heap_destroy(neighbor_min_heap);
 
   GNUNET_CORE_disconnect (coreAPI);
+  coreAPI = NULL;
   GNUNET_PEERINFO_disconnect(peerinfo_handle);
   GNUNET_SERVER_mst_destroy(coreMST);
   GNUNET_free_non_null(my_short_id);
   GNUNET_PEERINFO_disconnect(peerinfo_handle);
   GNUNET_SERVER_mst_destroy(coreMST);
   GNUNET_free_non_null(my_short_id);
@@ -2127,8 +2172,8 @@ void core_init (void *cls,
 
   if (server == NULL)
     {
 
   if (server == NULL)
     {
-      GNUNET_SCHEDULER_cancel(sched, cleanup_task);
-      GNUNET_SCHEDULER_add_now(sched, &shutdown_task, NULL);
+      GNUNET_SCHEDULER_cancel(cleanup_task);
+      GNUNET_SCHEDULER_add_now(&shutdown_task, NULL);
       return;
     }
 #if DEBUG_DV
       return;
     }
 #if DEBUG_DV
@@ -2154,10 +2199,10 @@ void core_init (void *cls,
  */
 static int add_pkey_to_extended (void *cls,
                                  const GNUNET_HashCode * key,
  */
 static int add_pkey_to_extended (void *cls,
                                  const GNUNET_HashCode * key,
-                                 void *value)
+                                 void *abs_value)
 {
   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey = cls;
 {
   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey = cls;
-  struct DistantNeighbor *distant_neighbor = value;
+  struct DistantNeighbor *distant_neighbor = abs_value;
 
   if (distant_neighbor->pkey == NULL)
   {
 
   if (distant_neighbor->pkey == NULL)
   {
@@ -2259,9 +2304,9 @@ static int add_distant_all_direct_neighbors (void *cls,
   GNUNET_free(encPeerTo);
 #endif
   /*if (send_context->task != GNUNET_SCHEDULER_NO_TASK)
   GNUNET_free(encPeerTo);
 #endif
   /*if (send_context->task != GNUNET_SCHEDULER_NO_TASK)
-    GNUNET_SCHEDULER_cancel(sched, send_context->task);*/
+    GNUNET_SCHEDULER_cancel(send_context->task);*/
 
 
-  send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, send_context);
+  send_context->task = GNUNET_SCHEDULER_add_now(&neighbor_send_task, send_context);
   return GNUNET_YES;
 }
 
   return GNUNET_YES;
 }
 
@@ -2325,7 +2370,8 @@ generate_hello_address (void *cls, size_t max, void *buf)
  *         not added)
  */
 static struct DistantNeighbor *
  *         not added)
  */
 static struct DistantNeighbor *
-addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer, struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey,
+addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer,
+                  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey,
                    unsigned int referrer_peer_id,
                    struct DirectNeighbor *referrer, unsigned int cost)
 {
                    unsigned int referrer_peer_id,
                    struct DirectNeighbor *referrer, unsigned int cost)
 {
@@ -2464,13 +2510,23 @@ addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer, struct GNUNET_CRYPTO
 #if DEBUG_DV_MESSAGES
                   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: learned about peer %llu from which we have a previous unknown message, processing!\n", my_short_id, referrer_peer_id);
 #endif
 #if DEBUG_DV_MESSAGES
                   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: learned about peer %llu from which we have a previous unknown message, processing!\n", my_short_id, referrer_peer_id);
 #endif
-                  handle_dv_data_message(NULL, &referrer->pending_messages[i].sender, referrer->pending_messages[i].message, referrer->pending_messages[i].latency, referrer->pending_messages[i].distance);
+                  struct GNUNET_TRANSPORT_ATS_Information atsi[3];
+                  atsi[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
+                  atsi[0].value = htonl (referrer->pending_messages[i].distance);
+                  atsi[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
+                  atsi[1].value = htonl ((uint32_t)referrer->pending_messages[i].latency.rel_value);
+                  atsi[2].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
+                  atsi[2].value = htonl (0);
+                  handle_dv_data_message(NULL,
+                                         &referrer->pending_messages[i].sender,
+                                        referrer->pending_messages[i].message, 
+                                        (const struct GNUNET_TRANSPORT_ATS_Information *)&atsi);
                   GNUNET_free(referrer->pending_messages[i].message);
                   referrer->pending_messages[i].sender_id = 0;
                 }
             }
         }
                   GNUNET_free(referrer->pending_messages[i].message);
                   referrer->pending_messages[i].sender_id = 0;
                 }
             }
         }
-      if (cost != DIRECT_NEIGHBOR_COST)
+      if ((cost != DIRECT_NEIGHBOR_COST) && (neighbor->pkey != NULL))
         {
           /* Added neighbor, now send HELLO to transport */
           hello_context = GNUNET_malloc(sizeof(struct HelloContext));
         {
           /* Added neighbor, now send HELLO to transport */
           hello_context = GNUNET_malloc(sizeof(struct HelloContext));
@@ -2519,14 +2575,12 @@ addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer, struct GNUNET_CRYPTO
  * @param cls closure
  * @param peer peer which sent the message (immediate sender)
  * @param message the message
  * @param cls closure
  * @param peer peer which sent the message (immediate sender)
  * @param message the message
- * @param latency the latency of the connection we received the message from
- * @param distance the distance to the immediate peer
+ * @param atsi performance data
  */
 static int handle_dv_disconnect_message (void *cls,
                                          const struct GNUNET_PeerIdentity *peer,
                                          const struct GNUNET_MessageHeader *message,
  */
 static int handle_dv_disconnect_message (void *cls,
                                          const struct GNUNET_PeerIdentity *peer,
                                          const struct GNUNET_MessageHeader *message,
-                                         struct GNUNET_TIME_Relative latency,
-                                         uint32_t distance)
+                                        const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct DirectNeighbor *referrer;
   struct DistantNeighbor *distant;
 {
   struct DirectNeighbor *referrer;
   struct DistantNeighbor *distant;
@@ -2548,8 +2602,10 @@ static int handle_dv_disconnect_message (void *cls,
       if (distant->referrer_id == ntohl(enc_message->peer_id))
         {
           distant_neighbor_free(distant);
       if (distant->referrer_id == ntohl(enc_message->peer_id))
         {
           distant_neighbor_free(distant);
+          distant = referrer->referee_head;
         }
         }
-      distant = referrer->referee_head;
+      else
+        distant = distant->next;
     }
 
   return GNUNET_OK;
     }
 
   return GNUNET_OK;
@@ -2566,14 +2622,13 @@ static int handle_dv_disconnect_message (void *cls,
  * @param cls closure
  * @param peer peer which sent the message (immediate sender)
  * @param message the message
  * @param cls closure
  * @param peer peer which sent the message (immediate sender)
  * @param message the message
- * @param latency the latency of the connection we received the message from
- * @param distance the distance to the immediate peer
+ * @param atsi performance data
  */
  */
-static int handle_dv_gossip_message (void *cls,
-                                     const struct GNUNET_PeerIdentity *peer,
-                                     const struct GNUNET_MessageHeader *message,
-                                     struct GNUNET_TIME_Relative latency,
-                                     uint32_t distance)
+static int 
+handle_dv_gossip_message (void *cls,
+                         const struct GNUNET_PeerIdentity *peer,
+                         const struct GNUNET_MessageHeader *message,
+                         const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct DirectNeighbor *referrer;
   p2p_dv_MESSAGE_NeighborInfo *enc_message = (p2p_dv_MESSAGE_NeighborInfo *)message;
 {
   struct DirectNeighbor *referrer;
   p2p_dv_MESSAGE_NeighborInfo *enc_message = (p2p_dv_MESSAGE_NeighborInfo *)message;
@@ -2619,9 +2674,10 @@ static int handle_dv_gossip_message (void *cls,
  *
  * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise
  */
  *
  * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise
  */
-static int add_all_extended_peers (void *cls,
-                                   const GNUNET_HashCode * key,
-                                   void *value)
+static int 
+add_all_extended_peers (void *cls,
+                       const GNUNET_HashCode * key,
+                       void *value)
 {
   struct NeighborSendContext *send_context = (struct NeighborSendContext *)cls;
   struct DistantNeighbor *distant = (struct DistantNeighbor *)value;
 {
   struct NeighborSendContext *send_context = (struct NeighborSendContext *)cls;
   struct DistantNeighbor *distant = (struct DistantNeighbor *)value;
@@ -2656,18 +2712,19 @@ static int add_all_extended_peers (void *cls,
  *         iterate,
  *         GNUNET_NO if not.
  */
  *         iterate,
  *         GNUNET_NO if not.
  */
-static int gossip_all_to_all_iterator (void *cls,
-                                      const GNUNET_HashCode * key,
-                                      void *value)
+static int 
+gossip_all_to_all_iterator (void *cls,
+                           const GNUNET_HashCode * key,
+                           void *abs_value)
 {
 {
-  struct DirectNeighbor *direct = value;
+  struct DirectNeighbor *direct = abs_value;
 
   GNUNET_CONTAINER_multihashmap_iterate (extended_neighbors, &add_all_extended_peers, direct->send_context);
 
   if (direct->send_context->task != GNUNET_SCHEDULER_NO_TASK)
 
   GNUNET_CONTAINER_multihashmap_iterate (extended_neighbors, &add_all_extended_peers, direct->send_context);
 
   if (direct->send_context->task != GNUNET_SCHEDULER_NO_TASK)
-    GNUNET_SCHEDULER_cancel(sched, direct->send_context->task);
+    GNUNET_SCHEDULER_cancel(direct->send_context->task);
 
 
-  direct->send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, direct->send_context);
+  direct->send_context->task = GNUNET_SCHEDULER_add_now(&neighbor_send_task, direct->send_context);
   return GNUNET_YES;
 }
 
   return GNUNET_YES;
 }
 
@@ -2683,8 +2740,7 @@ gossip_all_to_all (void *cls,
 {
   GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, &gossip_all_to_all_iterator, NULL);
 
 {
   GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, &gossip_all_to_all_iterator, NULL);
 
-  GNUNET_SCHEDULER_add_delayed (sched,
-                                GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5),
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5),
                                 &gossip_all_to_all,
                                 NULL);
 
                                 &gossip_all_to_all,
                                 NULL);
 
@@ -2701,9 +2757,10 @@ gossip_all_to_all (void *cls,
  *
  * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise
  */
  *
  * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise
  */
-static int add_all_direct_neighbors (void *cls,
-                                     const GNUNET_HashCode * key,
-                                     void *value)
+static int 
+add_all_direct_neighbors (void *cls,
+                         const GNUNET_HashCode * key,
+                         void *value)
 {
   struct DirectNeighbor *direct = (struct DirectNeighbor *)value;
   struct DirectNeighbor *to = (struct DirectNeighbor *)cls;
 {
   struct DirectNeighbor *direct = (struct DirectNeighbor *)value;
   struct DirectNeighbor *to = (struct DirectNeighbor *)cls;
@@ -2741,9 +2798,9 @@ static int add_all_direct_neighbors (void *cls,
                                     send_context->fast_gossip_list_tail,
                                     gossip_entry);
   if (send_context->task != GNUNET_SCHEDULER_NO_TASK)
                                     send_context->fast_gossip_list_tail,
                                     gossip_entry);
   if (send_context->task != GNUNET_SCHEDULER_NO_TASK)
-    GNUNET_SCHEDULER_cancel(sched, send_context->task);
+    GNUNET_SCHEDULER_cancel(send_context->task);
 
 
-  send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, send_context);
+  send_context->task = GNUNET_SCHEDULER_add_now(&neighbor_send_task, send_context);
   //tc.reason = GNUNET_SCHEDULER_REASON_TIMEOUT;
   //neighbor_send_task(send_context, &tc);
   return GNUNET_YES;
   //tc.reason = GNUNET_SCHEDULER_REASON_TIMEOUT;
   //neighbor_send_task(send_context, &tc);
   return GNUNET_YES;
@@ -2756,12 +2813,13 @@ static int add_all_direct_neighbors (void *cls,
  * @param cls closure
  * @param peer id of the peer, NULL for last call
  * @param hello hello message for the peer (can be NULL)
  * @param cls closure
  * @param peer id of the peer, NULL for last call
  * @param hello hello message for the peer (can be NULL)
- * @param trust amount of trust we have in the peer
+ * @param err_msg NULL if successful, otherwise contains error message
  */
 static void
 process_peerinfo (void *cls,
                   const struct GNUNET_PeerIdentity *peer,
  */
 static void
 process_peerinfo (void *cls,
                   const struct GNUNET_PeerIdentity *peer,
-                  const struct GNUNET_HELLO_Message *hello, uint32_t trust)
+                  const struct GNUNET_HELLO_Message *hello,
+                  const char *err_msg)
 {
   struct PeerIteratorContext *peerinfo_iterator = cls;
   struct DirectNeighbor *neighbor = peerinfo_iterator->neighbor;
 {
   struct PeerIteratorContext *peerinfo_iterator = cls;
   struct DirectNeighbor *neighbor = peerinfo_iterator->neighbor;
@@ -2770,7 +2828,12 @@ process_peerinfo (void *cls,
   char *neighbor_pid;
 #endif
   int sent;
   char *neighbor_pid;
 #endif
   int sent;
-
+  if (err_msg != NULL)
+  {
+         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                     _("Error in communication with PEERINFO service\n"));
+         /* return; */
+  }
   if (peer == NULL)
     {
       if (distant->pkey == NULL)
   if (peer == NULL)
     {
       if (distant->pkey == NULL)
@@ -2780,7 +2843,6 @@ process_peerinfo (void *cls,
 #endif
           peerinfo_iterator->ic = GNUNET_PEERINFO_iterate(peerinfo_handle,
                                                           &peerinfo_iterator->neighbor->identity,
 #endif
           peerinfo_iterator->ic = GNUNET_PEERINFO_iterate(peerinfo_handle,
                                                           &peerinfo_iterator->neighbor->identity,
-                                                          0,
                                                           GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3),
                                                           &process_peerinfo,
                                                           peerinfo_iterator);
                                                           GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3),
                                                           &process_peerinfo,
                                                           peerinfo_iterator);
@@ -2804,17 +2866,24 @@ process_peerinfo (void *cls,
         }
 
       sent = GNUNET_CONTAINER_multihashmap_iterate (extended_neighbors, &add_all_extended_peers, neighbor->send_context);
         }
 
       sent = GNUNET_CONTAINER_multihashmap_iterate (extended_neighbors, &add_all_extended_peers, neighbor->send_context);
-
+      if (stats != NULL)
+        {
+          GNUNET_STATISTICS_update (stats, "# distant peers gossiped to direct neighbors", sent, GNUNET_NO);
+        }
 #if DEBUG_DV_PEER_NUMBERS
       neighbor_pid = GNUNET_strdup(GNUNET_i2s(&neighbor->identity));
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Gossipped %d extended peers to %s\n", GNUNET_i2s(&my_identity), sent, neighbor_pid);
 #endif
       sent = GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, &add_all_direct_neighbors, neighbor);
 #if DEBUG_DV_PEER_NUMBERS
       neighbor_pid = GNUNET_strdup(GNUNET_i2s(&neighbor->identity));
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Gossipped %d extended peers to %s\n", GNUNET_i2s(&my_identity), sent, neighbor_pid);
 #endif
       sent = GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, &add_all_direct_neighbors, neighbor);
+      if (stats != NULL)
+        {
+          GNUNET_STATISTICS_update (stats, "# direct peers gossiped to direct neighbors", sent, GNUNET_NO);
+        }
 #if DEBUG_DV_PEER_NUMBERS
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Gossipped about %s to %d direct peers\n", GNUNET_i2s(&my_identity), neighbor_pid, sent);
       GNUNET_free(neighbor_pid);
 #endif
 #if DEBUG_DV_PEER_NUMBERS
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Gossipped about %s to %d direct peers\n", GNUNET_i2s(&my_identity), neighbor_pid, sent);
       GNUNET_free(neighbor_pid);
 #endif
-      neighbor->send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, neighbor->send_context);
+      neighbor->send_context->task = GNUNET_SCHEDULER_add_now(&neighbor_send_task, neighbor->send_context);
     }
 }
 
     }
 }
 
@@ -2824,13 +2893,12 @@ process_peerinfo (void *cls,
  *
  * @param cls closure
  * @param peer peer identity this notification is about
  *
  * @param cls closure
  * @param peer peer identity this notification is about
- * @param latency reported latency of the connection with peer
- * @param distance reported distance (DV) to peer
+ * @param atsi performance data
  */
  */
-void handle_core_connect (void *cls,
-                          const struct GNUNET_PeerIdentity * peer,
-                          struct GNUNET_TIME_Relative latency,
-                          uint32_t distance)
+static void 
+handle_core_connect (void *cls,
+                    const struct GNUNET_PeerIdentity * peer,
+                    const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct DirectNeighbor *neighbor;
   struct DistantNeighbor *about;
 {
   struct DirectNeighbor *neighbor;
   struct DistantNeighbor *about;
@@ -2840,8 +2908,15 @@ void handle_core_connect (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "%s: Receives core connect message for peer %s distance %d!\n", "dv", GNUNET_i2s(peer), distance);
 #endif
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "%s: Receives core connect message for peer %s distance %d!\n", "dv", GNUNET_i2s(peer), distance);
 #endif
+  uint32_t distance;
 
 
-  if ((distance == DIRECT_NEIGHBOR_COST) && (GNUNET_CONTAINER_multihashmap_get(direct_neighbors, &peer->hashPubKey) == NULL))
+  /* Check for connect to self message */
+  if (0 == memcmp(&my_identity, peer, sizeof(struct GNUNET_PeerIdentity)))
+    return;
+
+  distance = get_atsi_distance (atsi);
+  if ((distance == DIRECT_NEIGHBOR_COST) &&
+      (GNUNET_CONTAINER_multihashmap_get(direct_neighbors, &peer->hashPubKey) == NULL))
   {
     peerinfo_iterator = GNUNET_malloc(sizeof(struct PeerIteratorContext));
     neighbor = GNUNET_malloc (sizeof (struct DirectNeighbor));
   {
     peerinfo_iterator = GNUNET_malloc(sizeof(struct PeerIteratorContext));
     neighbor = GNUNET_malloc (sizeof (struct DirectNeighbor));
@@ -2857,7 +2932,6 @@ void handle_core_connect (void *cls,
     peerinfo_iterator->neighbor = neighbor;
     peerinfo_iterator->ic = GNUNET_PEERINFO_iterate (peerinfo_handle,
                                                      peer,
     peerinfo_iterator->neighbor = neighbor;
     peerinfo_iterator->ic = GNUNET_PEERINFO_iterate (peerinfo_handle,
                                                      peer,
-                                                     0,
                                                      GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3),
                                                      &process_peerinfo,
                                                      peerinfo_iterator);
                                                      GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3),
                                                      &process_peerinfo,
                                                      peerinfo_iterator);
@@ -2877,7 +2951,13 @@ void handle_core_connect (void *cls,
   {
     about = GNUNET_CONTAINER_multihashmap_get(extended_neighbors, &peer->hashPubKey);
     if ((GNUNET_CONTAINER_multihashmap_get(direct_neighbors, &peer->hashPubKey) == NULL) && (about != NULL))
   {
     about = GNUNET_CONTAINER_multihashmap_get(extended_neighbors, &peer->hashPubKey);
     if ((GNUNET_CONTAINER_multihashmap_get(direct_neighbors, &peer->hashPubKey) == NULL) && (about != NULL))
-      sent = GNUNET_CONTAINER_multihashmap_iterate(direct_neighbors, &add_distant_all_direct_neighbors, about);
+      {
+        sent = GNUNET_CONTAINER_multihashmap_iterate(direct_neighbors, &add_distant_all_direct_neighbors, about);
+        if (stats != NULL)
+          {
+            GNUNET_STATISTICS_update (stats, "# direct peers gossiped to new direct neighbors", sent, GNUNET_NO);
+          }
+      }
 #if DEBUG_DV
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "%s: Distance (%d) greater than %d or already know about peer (%s), not re-adding!\n", "dv", distance, DIRECT_NEIGHBOR_COST, GNUNET_i2s(peer));
 #if DEBUG_DV
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "%s: Distance (%d) greater than %d or already know about peer (%s), not re-adding!\n", "dv", distance, DIRECT_NEIGHBOR_COST, GNUNET_i2s(peer));
@@ -2899,18 +2979,37 @@ void handle_core_disconnect (void *cls,
   struct DistantNeighbor *referee;
   struct FindDestinationContext fdc;
   struct DisconnectContext disconnect_context;
   struct DistantNeighbor *referee;
   struct FindDestinationContext fdc;
   struct DisconnectContext disconnect_context;
+  struct PendingMessage *pending_pos;
 
 #if DEBUG_DV
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "%s: Receives core peer disconnect message!\n", "dv");
 #endif
 
 
 #if DEBUG_DV
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "%s: Receives core peer disconnect message!\n", "dv");
 #endif
 
+  /* Check for disconnect from self message */
+  if (0 == memcmp(&my_identity, peer, sizeof(struct GNUNET_PeerIdentity)))
+    return;
+
   neighbor =
     GNUNET_CONTAINER_multihashmap_get (direct_neighbors, &peer->hashPubKey);
   neighbor =
     GNUNET_CONTAINER_multihashmap_get (direct_neighbors, &peer->hashPubKey);
+
   if (neighbor == NULL)
     {
       return;
     }
   if (neighbor == NULL)
     {
       return;
     }
+
+  pending_pos = core_pending_head;
+  while (NULL != pending_pos)
+    {
+      if (0 == memcmp(&pending_pos->recipient, &neighbor->identity, sizeof(struct GNUNET_PeerIdentity)))
+        {
+          GNUNET_CONTAINER_DLL_remove(core_pending_head, core_pending_tail, pending_pos);
+          pending_pos = core_pending_head;
+        }
+      else
+        pending_pos = pending_pos->next;
+    }
+
   while (NULL != (referee = neighbor->referee_head))
     distant_neighbor_free (referee);
 
   while (NULL != (referee = neighbor->referee_head))
     distant_neighbor_free (referee);
 
@@ -2928,12 +3027,13 @@ void handle_core_disconnect (void *cls,
 
   GNUNET_assert (neighbor->referee_tail == NULL);
   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_remove (direct_neighbors,
 
   GNUNET_assert (neighbor->referee_tail == NULL);
   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_remove (direct_neighbors,
-                                        &peer->hashPubKey, neighbor))
+                                                         &peer->hashPubKey, neighbor))
     {
       GNUNET_break(0);
     }
     {
       GNUNET_break(0);
     }
-  if ((neighbor->send_context != NULL) && (neighbor->send_context->task != GNUNET_SCHEDULER_NO_TASK))
-    GNUNET_SCHEDULER_cancel(sched, neighbor->send_context->task);
+  if ((neighbor->send_context != NULL) &&
+      (neighbor->send_context->task != GNUNET_SCHEDULER_NO_TASK))
+    GNUNET_SCHEDULER_cancel(neighbor->send_context->task);
   GNUNET_free (neighbor);
 }
 
   GNUNET_free (neighbor);
 }
 
@@ -2942,18 +3042,15 @@ void handle_core_disconnect (void *cls,
  * Process dv requests.
  *
  * @param cls closure
  * Process dv requests.
  *
  * @param cls closure
- * @param scheduler scheduler to use
  * @param server the initialized server
  * @param c configuration to use
  */
 static void
 run (void *cls,
  * @param server the initialized server
  * @param c configuration to use
  */
 static void
 run (void *cls,
-     struct GNUNET_SCHEDULER_Handle *scheduler,
      struct GNUNET_SERVER_Handle *server,
      const struct GNUNET_CONFIGURATION_Handle *c)
 {
   unsigned long long max_hosts;
      struct GNUNET_SERVER_Handle *server,
      const struct GNUNET_CONFIGURATION_Handle *c)
 {
   unsigned long long max_hosts;
-  sched = scheduler;
   cfg = c;
 
   /* FIXME: Read from config, or calculate, or something other than this! */
   cfg = c;
 
   /* FIXME: Read from config, or calculate, or something other than this! */
@@ -2982,13 +3079,13 @@ run (void *cls,
 
   GNUNET_SERVER_add_handlers (server, plugin_handlers);
   coreAPI =
 
   GNUNET_SERVER_add_handlers (server, plugin_handlers);
   coreAPI =
-  GNUNET_CORE_connect (sched,
-                       cfg,
-                       GNUNET_TIME_relative_get_forever(),
+  GNUNET_CORE_connect (cfg,
+                      1,
                        NULL, /* FIXME: anything we want to pass around? */
                        &core_init,
                        &handle_core_connect,
                        &handle_core_disconnect,
                        NULL, /* FIXME: anything we want to pass around? */
                        &core_init,
                        &handle_core_connect,
                        &handle_core_disconnect,
+                      NULL,
                        NULL,
                        GNUNET_NO,
                        NULL,
                        NULL,
                        GNUNET_NO,
                        NULL,
@@ -2998,11 +3095,10 @@ run (void *cls,
   if (coreAPI == NULL)
     return;
 
   if (coreAPI == NULL)
     return;
 
-  coreMST = GNUNET_SERVER_mst_create (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1,
-                                      &tokenized_message_handler,
+  coreMST = GNUNET_SERVER_mst_create (&tokenized_message_handler,
                                       NULL);
 
                                       NULL);
 
-   peerinfo_handle = GNUNET_PEERINFO_connect(sched, cfg);
+   peerinfo_handle = GNUNET_PEERINFO_connect(cfg);
 
    if (peerinfo_handle == NULL)
      {
 
    if (peerinfo_handle == NULL)
      {
@@ -3011,10 +3107,9 @@ run (void *cls,
      }
 
   /* Scheduled the task to clean up when shutdown is called */
      }
 
   /* Scheduled the task to clean up when shutdown is called */
-  cleanup_task = GNUNET_SCHEDULER_add_delayed (sched,
-                                GNUNET_TIME_UNIT_FOREVER_REL,
-                                &shutdown_task,
-                                NULL);
+  cleanup_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+                                               &shutdown_task,
+                                               NULL);
 }
 
 
 }