gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r26393 - gnunet/src/dv


From: gnunet
Subject: [GNUnet-SVN] r26393 - gnunet/src/dv
Date: Tue, 12 Mar 2013 20:32:02 +0100

Author: grothoff
Date: 2013-03-12 20:32:02 +0100 (Tue, 12 Mar 2013)
New Revision: 26393

Modified:
   gnunet/src/dv/dv_api.c
   gnunet/src/dv/gnunet-service-dv.c
Log:
-removing useless parts of old code, work on DHT API

Modified: gnunet/src/dv/dv_api.c
===================================================================
--- gnunet/src/dv/dv_api.c      2013-03-12 14:23:57 UTC (rev 26392)
+++ gnunet/src/dv/dv_api.c      2013-03-12 19:32:02 UTC (rev 26393)
@@ -39,18 +39,39 @@
  */
 struct GNUNET_DV_TransmitHandle
 {
+  /**
+   * Kept in a DLL.
+   */
   struct GNUNET_DV_TransmitHandle *next;
 
+  /**
+   * Kept in a DLL.
+   */
   struct GNUNET_DV_TransmitHandle *prev;
 
+  /**
+   * Handle to the service.
+   */
   struct GNUNET_DV_ServiceHandle *sh;
 
+  /**
+   * Function to call upon completion.
+   */
   GNUNET_DV_MessageSentCallback cb;
 
+  /**
+   * Closure for 'cb'.
+   */
   void *cb_cls;
   
+  /**
+   * The actual message (allocated at the end of this struct).
+   */
   const struct GNUNET_MessageHeader *msg;
 
+  /**
+   * Destination for the message.
+   */
   struct GNUNET_PeerIdentity target;
 
 };
@@ -62,413 +83,132 @@
 struct GNUNET_DV_ServiceHandle
 {
 
-  struct GNUNET_ClientHandle *client;
-
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  void *cls;
-  
-  GNUNET_DV_ConnectCallback connect_cb;
-
-  GNUNET_DV_DisconnectCallback disconnect_cb;
-
-  GNUNET_DV_MessageReceivedCallback message_cb;
-
-  struct GNUNET_DV_TransmitHandle *th_head;
-
-  struct GNUNET_DV_TransmitHandle *th_tail;
-
-};
-
-
-/**
- * Connect to the DV service.
- *
- * @param cfg configuration
- * @param cls closure for callbacks
- * @param connect_cb function to call on connects
- * @param disconnect_cb function to call on disconnects
- * @param message_cb function to call if we receive messages
- * @return handle to access the service
- */
-struct GNUNET_DV_ServiceHandle *
-GNUNET_DV_service_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                          void *cls,
-                          GNUNET_DV_ConnectCallback connect_cb,
-                          GNUNET_DV_DisconnectCallback disconnect_cb,
-                          GNUNET_DV_MessageReceivedCallback message_cb)
-{
-  GNUNET_break (0);
-  return NULL;
-}
-
-
-/**
- * Disconnect from DV service.
- *
- * @param sh service handle
- */
-void
-GNUNET_DV_service_disconnect (struct GNUNET_DV_ServiceHandle *sh)
-{
-  GNUNET_break (0);
-}
-
-
-
-/**
- * Send a message via DV service.
- *
- * @param sh service handle
- * @param target intended recpient
- * @param msg message payload
- * @param cb function to invoke when done
- * @param cb_cls closure for 'cb'
- * @return handle to cancel the operation
- */
-struct GNUNET_DV_TransmitHandle *
-GNUNET_DV_send (struct GNUNET_DV_ServiceHandle *sh,
-               const struct GNUNET_PeerIdentity *target,
-               const struct GNUNET_MessageHeader *msg,
-               GNUNET_DV_MessageSentCallback cb,
-               void *cb_cls)
-{
-  GNUNET_break (0);
-  return NULL;
-}
-
-
-/**
- * Abort send operation (naturally, the message may have
- * already been transmitted; this only stops the 'cb'
- * from being called again).
- *
- * @param th send operation to cancel
- */
-void
-GNUNET_DV_send_cancel (struct GNUNET_DV_TransmitHandle *th)
-{
-  GNUNET_break (0);
-}
-
-
-
-#if 0
-
-
-
-
-
-
-
-
-
-
-
-
-/**
- * Store ready to send messages
- */
-struct PendingMessages
-{
   /**
-   * Linked list of pending messages
+   * Connection to DV service.
    */
-  struct PendingMessages *next;
+  struct GNUNET_CLIENT_Connection *client;
 
   /**
-   * Message that is pending
+   * Active request for transmission to DV service.
    */
-  struct GNUNET_DV_SendMessage *msg;
+  struct GNUNET_CLIENT_TransmitHandle *th;
 
   /**
-   * Timeout for this message
+   * Our configuration.
    */
-  struct GNUNET_TIME_Absolute timeout;
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
 
-};
-
-/**
- * Handle for the service.
- */
-struct GNUNET_DV_Handle
-{
-
   /**
-   * Configuration to use.
+   * Closure for the callbacks.
    */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
+  void *cls;
+  
   /**
-   * Socket (if available).
+   * Function to call on connect events.
    */
-  struct GNUNET_CLIENT_Connection *client;
+  GNUNET_DV_ConnectCallback connect_cb;
 
   /**
-   * Currently pending transmission request.
+   * Function to call on disconnect events.
    */
-  struct GNUNET_CLIENT_TransmitHandle *th;
+  GNUNET_DV_DisconnectCallback disconnect_cb;
 
   /**
-   * List of the currently pending messages for the DV service.
+   * Function to call on receiving messages events.
    */
-  struct PendingMessages *pending_list;
+  GNUNET_DV_MessageReceivedCallback message_cb;
 
   /**
-   * Message we are currently sending.
+   * Head of messages to transmit.
    */
-  struct PendingMessages *current;
+  struct GNUNET_DV_TransmitHandle *th_head;
 
   /**
-   * Handler for messages we receive from the DV service
+   * Tail of messages to transmit.
    */
-  GNUNET_DV_MessageReceivedHandler receive_handler;
+  struct GNUNET_DV_TransmitHandle *th_tail;
 
   /**
-   * Closure for the receive handler
+   * Mapping of peer identities to TransmitHandles to invoke
+   * upon successful transmission.  The respective
+   * transmissions have already been done.
    */
-  void *receive_cls;
+  struct GNUNET_CONTAINER_MultiHashMap *send_callbacks;
 
   /**
    * Current unique ID
    */
   uint32_t uid_gen;
 
-  /**
-   * Hashmap containing outstanding send requests awaiting confirmation.
-   */
-  struct GNUNET_CONTAINER_MultiHashMap *send_callbacks;
-
 };
 
 
-struct StartContext
-{
-  /**
-   * Start message
-   */
-  struct GNUNET_MessageHeader *message;
-
-  /**
-   * Handle to service, in case of timeout
-   */
-  struct GNUNET_DV_Handle *handle;
-};
-
-struct SendCallbackContext
-{
-  /**
-   * The continuation to call once a message is confirmed sent (or failed)
-   */
-  GNUNET_TRANSPORT_TransmitContinuation cont;
-
-  /**
-   * Closure to call with send continuation.
-   */
-  void *cont_cls;
-
-  /**
-   * Target of the message.
-   */
-  struct GNUNET_PeerIdentity target;
-
-  /**
-   * Payload size in bytes
-   */
-  size_t payload_size;
-
-  /**
-   * DV message size
-   */
-  size_t msg_size;
-};
-
 /**
- * Convert unique ID to hash code.
+ * Disconnect and then reconnect to the DV service.
  *
- * @param uid unique ID to convert
- * @param hash set to uid (extended with zeros)
+ * @param sh service handle
  */
 static void
-hash_from_uid (uint32_t uid, struct GNUNET_HashCode * hash)
-{
-  memset (hash, 0, sizeof (struct GNUNET_HashCode));
-  *((uint32_t *) hash) = uid;
-}
+reconnect (struct GNUNET_DV_ServiceHandle *sh);
 
-/**
- * Try to (re)connect to the dv service.
- *
- * @param ret handle to the (disconnected) dv service
- *
- * @return GNUNET_YES on success, GNUNET_NO on failure.
- */
-static int
-try_connect (struct GNUNET_DV_Handle *ret)
-{
-  if (ret->client != NULL)
-    return GNUNET_OK;
-  ret->client = GNUNET_CLIENT_connect ("dv", ret->cfg);
-  if (ret->client != NULL)
-    return GNUNET_YES;
-#if DEBUG_DV_MESSAGES
-  LOG (GNUNET_ERROR_TYPE_DEBUG, _("Failed to connect to the dv service!\n"));
-#endif
-  return GNUNET_NO;
-}
 
-static void
-process_pending_message (struct GNUNET_DV_Handle *handle);
-
 /**
- * Send complete, schedule next
+ * Gives a message from our queue to the DV service.
  *
- * @param handle handle to the dv service
- * @param code return code for send (unused)
- */
-static void
-finish (struct GNUNET_DV_Handle *handle, int code)
-{
-  struct PendingMessages *pos = handle->current;
-
-  handle->current = NULL;
-  process_pending_message (handle);
-
-  GNUNET_free (pos->msg);
-  GNUNET_free (pos);
-}
-
-/**
- * Notification that we can send data
- *
- * @param cls handle to the dv service (struct GNUNET_DV_Handle)
+ * @param cls handle to the dv service (struct GNUNET_DV_ServiceHandle)
  * @param size how many bytes can we send
  * @param buf where to copy the message to send
- *
  * @return how many bytes we copied to buf
  */
 static size_t
 transmit_pending (void *cls, size_t size, void *buf)
 {
-  struct GNUNET_DV_Handle *handle = cls;
+  struct GNUNET_DV_ServiceHandle *sh = cls;
   size_t ret;
   size_t tsize;
 
-#if DEBUG_DV
-  if (handle->current != NULL)
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "DV API: Transmit pending called with message type %d\n",
-         ntohs (handle->current->msg->header.type));
-#endif
-
-  if (buf == NULL)
+  sh->th = NULL;
+  if (NULL == buf)
   {
-#if DEBUG_DV
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "DV API: Transmit pending FAILED!\n\n\n");
-#endif
-    finish (handle, GNUNET_SYSERR);
+    reconnect (sh);
     return 0;
   }
-  handle->th = NULL;
-
   ret = 0;
-
-  if (handle->current != NULL)
+  // FIXME: yuck! -- copy multiple, remove from DLL, and add to hash map!
+  if (NULL != sh->th_head)
   {
-    tsize = ntohs (handle->current->msg->header.size);
+    tsize = ntohs (sh->th_head->msg->size);
     if (size >= tsize)
     {
-      memcpy (buf, handle->current->msg, tsize);
-#if DEBUG_DV
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "DV API: Copied %d bytes into buffer!\n\n\n", tsize);
-#endif
-      finish (handle, GNUNET_OK);
+      memcpy (buf, sh->th_head->msg, tsize);
       return tsize;
     }
-
   }
-
   return ret;
 }
 
+
 /**
- * Try to send messages from list of messages to send
+ * Start sending messages from our queue to the service.
  *
- * @param handle handle to the distance vector service
+ * @param sh service handle
  */
 static void
-process_pending_message (struct GNUNET_DV_Handle *handle)
+start_transmit (struct GNUNET_DV_ServiceHandle *sh)
 {
-
-  if (handle->current != NULL)
-    return;                     /* action already pending */
-  if (GNUNET_YES != try_connect (handle))
-  {
-    finish (handle, GNUNET_SYSERR);
+  if (NULL != sh->th)
     return;
-  }
-
-  /* schedule next action */
-  handle->current = handle->pending_list;
-  if (NULL == handle->current)
-  {
-    return;
-  }
-  handle->pending_list = handle->pending_list->next;
-  handle->current->next = NULL;
-
-  if (NULL ==
-      (handle->th =
-       GNUNET_CLIENT_notify_transmit_ready (handle->client,
-                                            ntohs (handle->current->msg->
-                                                   header.size),
-                                            handle->current->msg->timeout,
-                                            GNUNET_YES, &transmit_pending,
-                                            handle)))
-  {
-#if DEBUG_DV
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Failed to transmit request to dv service.\n");
-#endif
-    finish (handle, GNUNET_SYSERR);
-  }
+  if (NULL == sh->th_head)
+    return; 
+  sh->th =
+    GNUNET_CLIENT_notify_transmit_ready (sh->client,
+                                        ntohs (sh->th_head->msg->size),
+                                        GNUNET_TIME_UNIT_FOREVER_REL,
+                                        GNUNET_NO, 
+                                        &transmit_pending, sh);
 }
 
-/**
- * Add a pending message to the linked list
- *
- * @param handle handle to the specified DV api
- * @param msg the message to add to the list
- */
-static void
-add_pending (struct GNUNET_DV_Handle *handle, struct GNUNET_DV_SendMessage 
*msg)
-{
-  struct PendingMessages *new_message;
-  struct PendingMessages *pos;
-  struct PendingMessages *last;
 
-  new_message = GNUNET_malloc (sizeof (struct PendingMessages));
-  new_message->msg = msg;
-
-  if (handle->pending_list != NULL)
-  {
-    pos = handle->pending_list;
-    while (pos != NULL)
-    {
-      last = pos;
-      pos = pos->next;
-    }
-    last->next = new_message;
-  }
-  else
-  {
-    handle->pending_list = new_message;
-  }
-
-  process_pending_message (handle);
-}
-
 /**
  * Handles a message sent from the DV service to us.
  * Parse it out and give it to the plugin.
@@ -476,295 +216,255 @@
  * @param cls the handle to the DV API
  * @param msg the message that was received
  */
-void
-handle_message_receipt (void *cls, const struct GNUNET_MessageHeader *msg)
+static void
+handle_message_receipt (void *cls, 
+                       const struct GNUNET_MessageHeader *msg)
 {
-  struct GNUNET_DV_Handle *handle = cls;
-  struct GNUNET_DV_MessageReceived *received_msg;
-  struct GNUNET_DV_SendResultMessage *send_result_msg;
-  size_t packed_msg_len;
-  size_t sender_address_len;
-  char *sender_address;
-  char *packed_msg;
-  char *packed_msg_start;
-  struct GNUNET_HashCode uidhash;
-  struct SendCallbackContext *send_ctx;
+  struct GNUNET_DV_ServiceHandle *sh = cls;
+  const struct GNUNET_DV_ConnectMessage *cm;
+  const struct GNUNET_DV_DisconnectMessage *dm;
+  const struct GNUNET_DV_ReceivedMessage *rm;
 
-  if (msg == NULL)
+  if (NULL == msg)
   {
-#if DEBUG_DV_MESSAGES
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "DV_API receive: connection closed\n");
-#endif
-    return;                     /* Connection closed? */
+    /* Connection closed */
+    reconnect (sh);
+    return;
   }
-
-  GNUNET_assert ((ntohs (msg->type) == 
GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE)
-                 || (ntohs (msg->type) ==
-                     GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND_RESULT));
-
   switch (ntohs (msg->type))
   {
-  case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE:
-    if (ntohs (msg->size) < sizeof (struct GNUNET_DV_MessageReceived))
+  case GNUNET_MESSAGE_TYPE_DV_CONNECT:
+    if (ntohs (msg->size) != sizeof (struct GNUNET_DV_ConnectMessage))
+    {
+      GNUNET_break (0);
+      reconnect (sh);
       return;
-
-    received_msg = (struct GNUNET_DV_MessageReceived *) msg;
-    packed_msg_len = ntohl (received_msg->msg_len);
-    sender_address_len =
-        ntohs (msg->size) - packed_msg_len -
-        sizeof (struct GNUNET_DV_MessageReceived);
-    GNUNET_assert (sender_address_len > 0);
-    sender_address = GNUNET_malloc (sender_address_len);
-    memcpy (sender_address, &received_msg[1], sender_address_len);
-    packed_msg_start = (char *) &received_msg[1];
-    packed_msg = GNUNET_malloc (packed_msg_len);
-    memcpy (packed_msg, &packed_msg_start[sender_address_len], packed_msg_len);
-
-#if DEBUG_DV_MESSAGES
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "DV_API receive: packed message type: %d or %d\n",
-         ntohs (((struct GNUNET_MessageHeader *) packed_msg)->type),
-         ((struct GNUNET_MessageHeader *) packed_msg)->type);
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "DV_API receive: message sender reported as %s\n",
-         GNUNET_i2s (&received_msg->sender));
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "DV_API receive: distance is %u\n",
-         ntohl (received_msg->distance));
-#endif
-
-    handle->receive_handler (handle->receive_cls, &received_msg->sender,
-                             packed_msg, packed_msg_len,
-                             ntohl (received_msg->distance), sender_address,
-                             sender_address_len);
-
-    GNUNET_free (sender_address);
+    }
+    cm = (const struct GNUNET_DV_ConnectMessage *) msg;
+    // FIXME
     break;
-  case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND_RESULT:
-    if (ntohs (msg->size) < sizeof (struct GNUNET_DV_SendResultMessage))
+  case GNUNET_MESSAGE_TYPE_DV_DISCONNECT:
+    if (ntohs (msg->size) != sizeof (struct GNUNET_DV_DisconnectMessage))
+    {
+      GNUNET_break (0);
+      reconnect (sh);
       return;
-
-    send_result_msg = (struct GNUNET_DV_SendResultMessage *) msg;
-    hash_from_uid (ntohl (send_result_msg->uid), &uidhash);
-    send_ctx =
-        GNUNET_CONTAINER_multihashmap_get (handle->send_callbacks, &uidhash);
-
-    if ((send_ctx != NULL) && (send_ctx->cont != NULL))
+    }
+    dm = (const struct GNUNET_DV_DisconnectMessage *) msg;
+    // FIXME
+    break;
+  case GNUNET_MESSAGE_TYPE_DV_RECV:
+    if (ntohs (msg->size) < sizeof (struct GNUNET_DV_ReceivedMessage))
     {
-      if (ntohl (send_result_msg->result) == 0)
-      {
-        send_ctx->cont (send_ctx->cont_cls, &send_ctx->target, GNUNET_OK,
-                        send_ctx->payload_size, send_ctx->msg_size);
-      }
-      else
-      {
-        send_ctx->cont (send_ctx->cont_cls, &send_ctx->target, GNUNET_SYSERR,
-                        send_ctx->payload_size, 0);
-      }
+      GNUNET_break (0);
+      reconnect (sh);
+      return;
     }
-    GNUNET_free_non_null (send_ctx);
+    rm = (const struct GNUNET_DV_ReceivedMessage *) msg;
+    // FIXME
     break;
   default:
+    reconnect (sh);
     break;
   }
-  GNUNET_CLIENT_receive (handle->client, &handle_message_receipt, handle,
+  GNUNET_CLIENT_receive (sh->client, 
+                        &handle_message_receipt, sh,
                          GNUNET_TIME_UNIT_FOREVER_REL);
 }
 
+
 /**
- * Send a message from the plugin to the DV service indicating that
- * a message should be sent via DV to some peer.
+ * Transmit the start message to the DV service.
  *
- * @param dv_handle the handle to the DV api
- * @param target the final target of the message
- * @param msgbuf the msg(s) to send
- * @param msgbuf_size the size of msgbuf
- * @param priority priority to pass on to core when sending the message
- * @param timeout how long can this message be delayed (pass through to core)
- * @param addr the address of this peer (internally known to DV)
- * @param addrlen the length of the peer address
- * @param cont continuation to call once the message has been sent (or failed)
- * @param cont_cls closure for continuation
- *
- */
-int
-GNUNET_DV_send (struct GNUNET_DV_Handle *dv_handle,
-                const struct GNUNET_PeerIdentity *target, const char *msgbuf,
-                size_t msgbuf_size, unsigned int priority,
-                struct GNUNET_TIME_Relative timeout, const void *addr,
-                size_t addrlen, GNUNET_TRANSPORT_TransmitContinuation cont,
-                void *cont_cls)
+ * @param cls the 'struct GNUNET_DV_ServiceHandle'
+ * @param size number of bytes available in buf
+ * @param buf where to copy the message
+ * @return number of bytes written to buf
+ */ 
+static size_t
+transmit_start (void *cls,
+               size_t size,
+               void *buf)
 {
-  struct GNUNET_DV_SendMessage *msg;
-  struct SendCallbackContext *send_ctx;
-  char *end_of_message;
-  struct GNUNET_HashCode uidhash;
-  int msize;
+  struct GNUNET_DV_ServiceHandle *sh = cls;
+  struct GNUNET_MessageHeader start_message;
 
-#if DEBUG_DV_MESSAGES
-  dv_handle->uid_gen =
-      GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, UINT32_MAX);
-#else
-  dv_handle->uid_gen++;
-#endif
+  sh->th = NULL;
+  if (NULL == buf)
+  {
+    GNUNET_break (0);
+    reconnect (sh);
+    return 0;
+  }
+  GNUNET_assert (size >= sizeof (start_message));
+  start_message.size = htons (sizeof (struct GNUNET_MessageHeader));
+  start_message.type = htons (GNUNET_MESSAGE_TYPE_DV_START);
+  memcpy (buf, &start_message, sizeof (start_message));
+  GNUNET_CLIENT_receive (sh->client,
+                        &handle_message_receipt, sh,
+                         GNUNET_TIME_UNIT_FOREVER_REL);
+  start_transmit (sh);
+  return sizeof (start_message);
+}
 
-  msize = sizeof (struct GNUNET_DV_SendMessage) + addrlen + msgbuf_size;
-  msg = GNUNET_malloc (msize);
-  msg->header.size = htons (msize);
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND);
-  memcpy (&msg->target, target, sizeof (struct GNUNET_PeerIdentity));
-  msg->priority = htonl (priority);
-  msg->timeout = timeout;
-  msg->addrlen = htonl (addrlen);
-  msg->uid = htonl (dv_handle->uid_gen);
-  memcpy (&msg[1], addr, addrlen);
-  end_of_message = (char *) &msg[1];
-  end_of_message = &end_of_message[addrlen];
-  memcpy (end_of_message, msgbuf, msgbuf_size);
-  add_pending (dv_handle, msg);
-  send_ctx = GNUNET_malloc (sizeof (struct SendCallbackContext));
-  send_ctx->payload_size = msgbuf_size;
-  send_ctx->msg_size = msize;
-  send_ctx->cont = cont;
-  send_ctx->cont_cls = cont_cls;
-  memcpy (&send_ctx->target, target, sizeof (struct GNUNET_PeerIdentity));
-  hash_from_uid (dv_handle->uid_gen, &uidhash);
-  GNUNET_CONTAINER_multihashmap_put (dv_handle->send_callbacks, &uidhash,
-                                     send_ctx,
-                                     
GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
 
-  return GNUNET_OK;
-}
-
 /**
- * Callback to transmit a start message to
- * the DV service, once we can send
+ * Disconnect and then reconnect to the DV service.
  *
- * @param cls struct StartContext
- * @param size how much can we send
- * @param buf where to copy the message
- *
- * @return number of bytes copied to buf
+ * @param sh service handle
  */
-static size_t
-transmit_start (void *cls, size_t size, void *buf)
+static void
+reconnect (struct GNUNET_DV_ServiceHandle *sh)
 {
-  struct StartContext *start_context = cls;
-  struct GNUNET_DV_Handle *handle = start_context->handle;
-  size_t tsize;
-
-#if DEBUG_DV
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "DV API: sending start request to service\n");
-#endif
-  if (buf == NULL)
+  if (NULL != sh->th)
   {
-    GNUNET_free (start_context->message);
-    GNUNET_free (start_context);
-    GNUNET_DV_disconnect (handle);
-    return 0;
+    GNUNET_CLIENT_notify_transmit_ready_cancel (sh->th);
+    sh->th = NULL;
   }
-
-  tsize = ntohs (start_context->message->size);
-  if (size >= tsize)
+  if (NULL != sh->client)
   {
-    memcpy (buf, start_context->message, tsize);
-    GNUNET_free (start_context->message);
-    GNUNET_free (start_context);
-    GNUNET_CLIENT_receive (handle->client, &handle_message_receipt, handle,
-                           GNUNET_TIME_UNIT_FOREVER_REL);
-
-
-    return tsize;
+    GNUNET_CLIENT_disconnect (sh->client);
+    sh->client = NULL;
   }
-
-  return 0;
+  sh->client = GNUNET_CLIENT_connect ("dv", sh->cfg);
+  if (NULL == sh->client)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  sh->th = GNUNET_CLIENT_notify_transmit_ready (sh->client,
+                                               sizeof (struct 
GNUNET_MessageHeader),
+                                               GNUNET_TIME_UNIT_FOREVER_REL,
+                                               GNUNET_YES,
+                                               &transmit_start,
+                                               sh);
 }
 
+
 /**
- * Connect to the DV service
+ * Connect to the DV service.
  *
- * @param cfg the configuration to use
- * @param receive_handler method call when on receipt from the service
- * @param receive_handler_cls closure for receive_handler
- *
- * @return handle to the DV service
+ * @param cfg configuration
+ * @param cls closure for callbacks
+ * @param connect_cb function to call on connects
+ * @param disconnect_cb function to call on disconnects
+ * @param message_cb function to call if we receive messages
+ * @return handle to access the service
  */
-struct GNUNET_DV_Handle *
-GNUNET_DV_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                   GNUNET_DV_MessageReceivedHandler receive_handler,
-                   void *receive_handler_cls)
+struct GNUNET_DV_ServiceHandle *
+GNUNET_DV_service_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                          void *cls,
+                          GNUNET_DV_ConnectCallback connect_cb,
+                          GNUNET_DV_DisconnectCallback disconnect_cb,
+                          GNUNET_DV_MessageReceivedCallback message_cb)
 {
-  struct GNUNET_DV_Handle *handle;
-  struct GNUNET_MessageHeader *start_message;
-  struct StartContext *start_context;
+  struct GNUNET_DV_ServiceHandle *sh;
 
-  handle = GNUNET_malloc (sizeof (struct GNUNET_DV_Handle));
+  sh = GNUNET_malloc (sizeof (struct GNUNET_DV_ServiceHandle));
+  sh->cfg = cfg;
+  sh->cls = cls;
+  sh->connect_cb = connect_cb;
+  sh->disconnect_cb = disconnect_cb;
+  sh->message_cb = message_cb;
+  sh->send_callbacks = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_YES);
+  reconnect (sh);
+  return sh;
+}
 
-  handle->cfg = cfg;
-  handle->pending_list = NULL;
-  handle->current = NULL;
-  handle->th = NULL;
-  handle->client = GNUNET_CLIENT_connect ("dv", cfg);
-  handle->receive_handler = receive_handler;
-  handle->receive_cls = receive_handler_cls;
 
-  if (handle->client == NULL)
-  {
-    GNUNET_free (handle);
-    return NULL;
-  }
-
-  start_message = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader));
-  start_message->size = htons (sizeof (struct GNUNET_MessageHeader));
-  start_message->type = htons (GNUNET_MESSAGE_TYPE_DV_START);
-
-  start_context = GNUNET_malloc (sizeof (struct StartContext));
-  start_context->handle = handle;
-  start_context->message = start_message;
-  GNUNET_CLIENT_notify_transmit_ready (handle->client,
-                                       sizeof (struct GNUNET_MessageHeader),
-                                       GNUNET_TIME_relative_multiply
-                                       (GNUNET_TIME_UNIT_SECONDS, 60),
-                                       GNUNET_YES, &transmit_start,
-                                       start_context);
-
-  handle->send_callbacks = GNUNET_CONTAINER_multihashmap_create (100, 
GNUNET_NO);
-
-  return handle;
-}
-
 /**
- * Disconnect from the DV service
+ * Disconnect from DV service.
  *
- * @param handle the current handle to the service to disconnect
+ * @param sh service handle
  */
 void
-GNUNET_DV_disconnect (struct GNUNET_DV_Handle *handle)
+GNUNET_DV_service_disconnect (struct GNUNET_DV_ServiceHandle *sh)
 {
-  struct PendingMessages *pos;
-
-  GNUNET_assert (handle != NULL);
-
-  if (handle->th != NULL)       /* We have a live transmit request in the 
Aether */
+  struct GNUNET_DV_TransmitHandle *pos;
+  
+  if (NULL == sh)
+    return;
+  if (NULL != sh->th)
   {
-    GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
-    handle->th = NULL;
+    GNUNET_CLIENT_notify_transmit_ready_cancel (sh->th);
+    sh->th = NULL;
   }
-  if (handle->current != NULL)  /* We are trying to send something now, clean 
it up */
-    GNUNET_free (handle->current);
-  while (NULL != (pos = handle->pending_list))  /* Remove all pending sends 
from the list */
+  while (NULL != (pos = sh->th_head))
   {
-    handle->pending_list = pos->next;
+    GNUNET_CONTAINER_DLL_remove (sh->th_head,
+                                sh->th_tail,
+                                pos);
     GNUNET_free (pos);
   }
-  if (handle->client != NULL)   /* Finally, disconnect from the service */
+  if (NULL != sh->client) 
   {
-    GNUNET_CLIENT_disconnect (handle->client);
-    handle->client = NULL;
+    GNUNET_CLIENT_disconnect (sh->client);
+    sh->client = NULL;
   }
+  // FIXME: handle and/or free entries in 'send_callbacks'!
+  GNUNET_CONTAINER_multihashmap_destroy (sh->send_callbacks);
+  GNUNET_free (sh);
+}
 
-  GNUNET_free (handle);
+
+/**
+ * Send a message via DV service.
+ *
+ * @param sh service handle
+ * @param target intended recpient
+ * @param msg message payload
+ * @param cb function to invoke when done
+ * @param cb_cls closure for 'cb'
+ * @return handle to cancel the operation
+ */
+struct GNUNET_DV_TransmitHandle *
+GNUNET_DV_send (struct GNUNET_DV_ServiceHandle *sh,
+               const struct GNUNET_PeerIdentity *target,
+               const struct GNUNET_MessageHeader *msg,
+               GNUNET_DV_MessageSentCallback cb,
+               void *cb_cls)
+{
+  struct GNUNET_DV_TransmitHandle *th;
+
+  th = GNUNET_malloc (sizeof (struct GNUNET_DV_TransmitHandle) +
+                     ntohs (msg->size));
+  th->sh = sh;
+  th->target = *target;
+  th->cb = cb;
+  th->cb_cls = cb_cls;
+  // FIXME: wrong, need to box 'msg' AND generate UID!
+  th->msg = (const struct GNUNET_MessageHeader *) &th[1];
+  memcpy (&th[1], msg, ntohs (msg->size));
+  GNUNET_CONTAINER_DLL_insert (sh->th_head,
+                              sh->th_tail,
+                              th);
+  start_transmit (sh);
+  return th;
 }
 
-#endif
 
+/**
+ * Abort send operation (naturally, the message may have
+ * already been transmitted; this only stops the 'cb'
+ * from being called again).
+ *
+ * @param th send operation to cancel
+ */
+void
+GNUNET_DV_send_cancel (struct GNUNET_DV_TransmitHandle *th)
+{
+  struct GNUNET_DV_ServiceHandle *sh = th->sh;
+  int ret;
+
+  ret = GNUNET_CONTAINER_multihashmap_remove (sh->send_callbacks,
+                                             &th->target.hashPubKey,
+                                             th);
+  if (GNUNET_YES != ret)
+    GNUNET_CONTAINER_DLL_remove (sh->th_head,
+                                sh->th_tail,
+                                th);
+  GNUNET_free (th);
+}
+
+
 /* end of dv_api.c */

Modified: gnunet/src/dv/gnunet-service-dv.c
===================================================================
--- gnunet/src/dv/gnunet-service-dv.c   2013-03-12 14:23:57 UTC (rev 26392)
+++ gnunet/src/dv/gnunet-service-dv.c   2013-03-12 19:32:02 UTC (rev 26393)
@@ -445,7 +445,7 @@
   pending_message = GNUNET_malloc (sizeof (struct PendingMessage) + size);
   received_msg = (struct GNUNET_DV_ReceivedMessage *) &pending_message[1];
   received_msg->header.size = htons (size);
-  received_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECV);
+  received_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DV_RECV);
   received_msg->distance = htonl (distance);
   received_msg->sender = *distant_neighbor;
   memcpy (&received_msg[1], message, ntohs (message->size));
@@ -490,7 +490,7 @@
   pending_message = GNUNET_malloc (sizeof (struct PendingMessage) + size);
   ack_msg = (struct GNUNET_DV_AckMessage *) &pending_message[1];
   ack_msg->header.size = htons (size);
-  ack_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND_ACK);
+  ack_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DV_SEND_ACK);
   ack_msg->uid = htonl (uid);
   ack_msg->target = *target;
   GNUNET_CONTAINER_DLL_insert_tail (plugin_pending_head, 
@@ -556,1283 +556,7 @@
 }
 
 
-#if 0
-// ////////////////////////////////////////////////////////////////////////
-
-
 /**
- * Send a DV data message via DV.
- *
- * @param sender the original sender of the message
- * @param recipient the next hop recipient, may be our direct peer, maybe not
- * @param send_context the send context
- */
-static int
-send_message_via (const struct GNUNET_PeerIdentity *sender,
-                  const struct GNUNET_PeerIdentity *recipient,
-                  struct DV_SendContext *send_context)
-{
-  p2p_dv_MESSAGE_Data *toSend;
-  unsigned int msg_size;
-  unsigned int recipient_id;
-  unsigned int sender_id;
-  struct DistantNeighbor *source;
-  struct PendingMessage *pending_message;
-  struct FindIDContext find_context;
-
-  msg_size = send_context->message_size + sizeof (p2p_dv_MESSAGE_Data);
-
-  find_context.dest = send_context->distant_peer;
-  find_context.via = recipient;
-  find_context.tid = 0;
-  GNUNET_CONTAINER_multihashmap_get_multiple (extended_neighbors,
-                                              &send_context->
-                                              distant_peer->hashPubKey,
-                                              &find_specific_id, 
&find_context);
-
-  if (find_context.tid == 0)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "%s: find_specific_id failed to find peer!\n", my_short_id);
-    /* target unknown to us, drop! */
-    return GNUNET_SYSERR;
-  }
-  recipient_id = find_context.tid;
-
-  if (0 == (memcmp (&my_identity, sender, sizeof (struct 
GNUNET_PeerIdentity))))
-  {
-    sender_id = 0;
-    source =
-        GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
-                                           &sender->hashPubKey);
-    if (source != NULL)
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "%s: send_message_via found %s, myself in extended peer 
list???\n",
-                  my_short_id, GNUNET_i2s (&source->identity));
-  }
-  else
-  {
-    source =
-        GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
-                                           &sender->hashPubKey);
-    if (source == NULL)
-    {
-      /* sender unknown to us, drop! */
-      return GNUNET_SYSERR;
-    }
-    sender_id = source->our_id;
-  }
-
-  pending_message = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size);
-  pending_message->msg = (struct GNUNET_MessageHeader *) &pending_message[1];
-  pending_message->send_result = send_context->send_result;
-  memcpy (&pending_message->recipient, recipient,
-          sizeof (struct GNUNET_PeerIdentity));
-  pending_message->msg_size = msg_size;
-  pending_message->importance = send_context->importance;
-  pending_message->timeout = send_context->timeout;
-  toSend = (p2p_dv_MESSAGE_Data *) pending_message->msg;
-  toSend->header.size = htons (msg_size);
-  toSend->header.type = htons (GNUNET_MESSAGE_TYPE_DV_DATA);
-  toSend->sender = htonl (sender_id);
-  toSend->recipient = htonl (recipient_id);
-#if DEBUG_DV_MESSAGES
-  toSend->uid = send_context->uid;      /* Still sent around in network byte 
order */
-#else
-  toSend->uid = htonl (0);
-#endif
-
-  memcpy (&toSend[1], send_context->message, send_context->message_size);
-
-#if DEBUG_DV
-  memcpy (&shortname, GNUNET_i2s (send_context->distant_peer), 4);
-  shortname[4] = '\0';
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "%s: Notifying core of send to destination `%s' via `%s' size 
%u\n",
-              "DV", &shortname, GNUNET_i2s (recipient), msg_size);
-#endif
-
-  GNUNET_CONTAINER_DLL_insert_after (core_pending_head, core_pending_tail,
-                                     core_pending_tail, pending_message);
-
-  GNUNET_SCHEDULER_add_now (try_core_send, NULL);
-
-  return GNUNET_YES;
-}
-
-/**
- * Given a FindLeastCostContext, and a set
- * of peers that match the target, return the cheapest.
- *
- * @param cls closure, a struct FindLeastCostContext
- * @param key the key identifying the target peer
- * @param value the target peer
- *
- * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
- */
-static int
-find_least_cost_peer (void *cls, const struct GNUNET_HashCode * key, void 
*value)
-{
-  struct FindLeastCostContext *find_context = cls;
-  struct DistantNeighbor *dn = value;
-
-  if (dn->cost < find_context->least_cost)
-  {
-    find_context->target = dn;
-  }
-  if (dn->cost == DIRECT_NEIGHBOR_COST)
-    return GNUNET_NO;
-  return GNUNET_YES;
-}
-
-/**
- * Send a DV data message via DV.
- *
- * @param recipient the ultimate recipient of this message
- * @param sender the original sender of the message
- * @param specific_neighbor the specific neighbor to send this message via
- * @param message the packed message
- * @param message_size size of the message
- * @param importance what priority to send this message with
- * @param uid the unique identifier of this message (or 0 for none)
- * @param timeout how long to possibly delay sending this message
- */
-static int
-send_message (const struct GNUNET_PeerIdentity *recipient,
-              const struct GNUNET_PeerIdentity *sender,
-              const struct DistantNeighbor *specific_neighbor,
-              const struct GNUNET_MessageHeader *message, size_t message_size,
-              unsigned int importance, unsigned int uid,
-              struct GNUNET_TIME_Relative timeout)
-{
-  p2p_dv_MESSAGE_Data *toSend;
-  unsigned int msg_size;
-  unsigned int cost;
-  unsigned int recipient_id;
-  unsigned int sender_id;
-  struct DistantNeighbor *target;
-  struct DistantNeighbor *source;
-  struct PendingMessage *pending_message;
-  struct FindLeastCostContext find_least_ctx;
-
-#if DEBUG_DV_PEER_NUMBERS
-  struct GNUNET_CRYPTO_HashAsciiEncoded encPeerFrom;
-  struct GNUNET_CRYPTO_HashAsciiEncoded encPeerTo;
-  struct GNUNET_CRYPTO_HashAsciiEncoded encPeerVia;
-#endif
-  msg_size = message_size + sizeof (p2p_dv_MESSAGE_Data);
-
-  find_least_ctx.least_cost = -1;
-  find_least_ctx.target = NULL;
-  /*
-   * Need to find the least cost peer, lest the transport selection keep
-   * picking the same DV route for the same destination which results
-   * in messages looping forever.  Relatively cheap, we don't iterate
-   * over all known peers, just those that apply.
-   */
-  GNUNET_CONTAINER_multihashmap_get_multiple (extended_neighbors,
-                                              &recipient->hashPubKey,
-                                              &find_least_cost_peer,
-                                              &find_least_ctx);
-  target = find_least_ctx.target;
-
-  if (target == NULL)
-  {
-    /* target unknown to us, drop! */
-    return GNUNET_SYSERR;
-  }
-  recipient_id = target->referrer_id;
-
-  source =
-      GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
-                                         &sender->hashPubKey);
-  if (source == NULL)
-  {
-    if (0 !=
-        (memcmp (&my_identity, sender, sizeof (struct GNUNET_PeerIdentity))))
-    {
-      /* sender unknown to us, drop! */
-      return GNUNET_SYSERR;
-    }
-    sender_id = 0;              /* 0 == us */
-  }
-  else
-  {
-    /* find out the number that we use when we gossip about
-     * the sender */
-    sender_id = source->our_id;
-  }
-
-#if DEBUG_DV_PEER_NUMBERS
-  GNUNET_CRYPTO_hash_to_enc (&source->identity.hashPubKey, &encPeerFrom);
-  GNUNET_CRYPTO_hash_to_enc (&target->referrer->identity.hashPubKey,
-                             &encPeerVia);
-  encPeerFrom.encoding[4] = '\0';
-  encPeerVia.encoding[4] = '\0';
-#endif
-  if ((sender_id != 0) &&
-      (0 ==
-       memcmp (&source->identity, &target->referrer->identity,
-               sizeof (struct GNUNET_PeerIdentity))))
-  {
-    return 0;
-  }
-
-  cost = target->cost;
-  pending_message = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size);
-  pending_message->msg = (struct GNUNET_MessageHeader *) &pending_message[1];
-  pending_message->send_result = NULL;
-  pending_message->importance = importance;
-  pending_message->timeout = timeout;
-  memcpy (&pending_message->recipient, &target->referrer->identity,
-          sizeof (struct GNUNET_PeerIdentity));
-  pending_message->msg_size = msg_size;
-  toSend = (p2p_dv_MESSAGE_Data *) pending_message->msg;
-  toSend->header.size = htons (msg_size);
-  toSend->header.type = htons (GNUNET_MESSAGE_TYPE_DV_DATA);
-  toSend->sender = htonl (sender_id);
-  toSend->recipient = htonl (recipient_id);
-#if DEBUG_DV_MESSAGES
-  toSend->uid = htonl (uid);
-#else
-  toSend->uid = htonl (0);
-#endif
-
-#if DEBUG_DV_PEER_NUMBERS
-  GNUNET_CRYPTO_hash_to_enc (&target->identity.hashPubKey, &encPeerTo);
-  encPeerTo.encoding[4] = '\0';
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "%s: Sending DATA message. Sender id %u, source %s, destination 
%s, via %s\n",
-              GNUNET_i2s (&my_identity), sender_id, &encPeerFrom, &encPeerTo,
-              &encPeerVia);
-#endif
-  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",
-                my_short_id);
-  }
-  GNUNET_CONTAINER_DLL_insert_after (core_pending_head, core_pending_tail,
-                                     core_pending_tail, pending_message);
-#if DEBUG_DV
-  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 (try_core_send, NULL);
-  return (int) cost;
-}
-
-#if USE_PEER_ID
-struct CheckPeerContext
-{
-  /**
-   * Peer we found
-   */
-  struct DistantNeighbor *peer;
-
-  /**
-   * Sender id to search for
-   */
-  unsigned int sender_id;
-};
-
-/**
- * Iterator over hash map entries.
- *
- * @param cls closure
- * @param key current key code
- * @param value value in the hash map
- * @return GNUNET_YES if we should continue to
- *         iterate,
- *         GNUNET_NO if not.
- */
-int
-checkPeerID (void *cls, const struct GNUNET_HashCode * key, void *value)
-{
-  struct CheckPeerContext *ctx = cls;
-  struct DistantNeighbor *distant = value;
-
-  if (memcmp (key, &ctx->sender_id, sizeof (unsigned int)) == 0)
-  {
-    ctx->peer = distant;
-    return GNUNET_NO;
-  }
-  return GNUNET_YES;
-
-}
-#endif
-
-
-/**
- * Handler for messages parsed out by the tokenizer from
- * DV DATA received for this peer.
- *
- * @param cls NULL
- * @param client the TokenizedMessageContext which contains message information
- * @param message the actual message
- */
-int
-tokenized_message_handler (void *cls, void *client,
-                           const struct GNUNET_MessageHeader *message)
-{
-  struct TokenizedMessageContext *ctx = client;
-
-  GNUNET_break_op (ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP);
-  GNUNET_break_op (ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_DATA);
-  if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP) &&
-      (ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_DATA))
-  {
-#if DEBUG_DV_MESSAGES
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "%s: Receives %s message for me, uid %u, size %d, type %d cost 
%u from %s!\n",
-                my_short_id, "DV DATA", ctx->uid, ntohs (message->size),
-                ntohs (message->type), ctx->distant->cost,
-                GNUNET_i2s (&ctx->distant->identity));
-#endif
-    GNUNET_assert (memcmp
-                   (ctx->peer, &ctx->distant->identity,
-                    sizeof (struct GNUNET_PeerIdentity)) != 0);
-    send_to_plugin (ctx->peer, message, ntohs (message->size),
-                    &ctx->distant->identity, ctx->distant->cost);
-  }
-  return GNUNET_OK;
-}
-
-#if DELAY_FORWARDS
-struct DelayedMessageContext
-{
-  struct GNUNET_PeerIdentity dest;
-  struct GNUNET_PeerIdentity sender;
-  struct GNUNET_MessageHeader *message;
-  size_t message_size;
-  uint32_t uid;
-};
-
-void
-send_message_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct DelayedMessageContext *msg_ctx = cls;
-
-  if (msg_ctx != NULL)
-  {
-    send_message (&msg_ctx->dest, &msg_ctx->sender, NULL, msg_ctx->message,
-                  msg_ctx->message_size, default_dv_priority, msg_ctx->uid,
-                  GNUNET_TIME_UNIT_FOREVER_REL);
-    GNUNET_free (msg_ctx->message);
-    GNUNET_free (msg_ctx);
-  }
-}
-#endif
-
-/**
- * Find latency information in 'atsi'.
- *
- * @param atsi performance data
- * @param atsi_count number of entries in atsi
- * @return connection latency
- */
-static struct GNUNET_TIME_Relative
-get_atsi_latency (const struct GNUNET_ATS_Information *atsi,
-                  unsigned int atsi_count)
-{
-  unsigned int i;
-
-  for (i = 0; i < atsi_count; i++)
-    if (ntohl (atsi[i].type) == GNUNET_ATS_QUALITY_NET_DELAY)
-      return GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
-                                            ntohl (atsi->value));
-  GNUNET_break (0);
-  /* how can we not have latency data? */
-  return GNUNET_TIME_UNIT_SECONDS;
-}
-
-
-#if DEBUG_DV
-/**
- * Iterator over hash map entries.
- *
- * @param cls closure (NULL)
- * @param key current key code
- * @param value value in the hash map (DistantNeighbor)
- * @return GNUNET_YES if we should continue to
- *         iterate,
- *         GNUNET_NO if not.
- */
-int
-print_neighbors (void *cls, const struct GNUNET_HashCode * key, void 
*abs_value)
-{
-  struct DistantNeighbor *distant_neighbor = abs_value;
-  char my_shortname[5];
-  char referrer_shortname[5];
-
-  memcpy (&my_shortname, GNUNET_i2s (&my_identity), 4);
-  my_shortname[4] = '\0';
-  memcpy (&referrer_shortname,
-          GNUNET_i2s (&distant_neighbor->referrer->identity), 4);
-  referrer_shortname[4] = '\0';
-
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "`%s' %s: Peer `%s', distance %d, referrer `%s' pkey: %s\n",
-              &my_shortname, "DV", GNUNET_i2s (&distant_neighbor->identity),
-              distant_neighbor->cost, &referrer_shortname,
-              distant_neighbor->pkey == NULL ? "no" : "yes");
-  return GNUNET_YES;
-}
-#endif
-
-/**
- *  Scheduled task which gossips about known direct peers to other connected
- *  peers.  Will run until called with reason shutdown.
- */
-static void
-neighbor_send_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct NeighborSendContext *send_context = cls;
-
-#if DEBUG_DV_GOSSIP_SEND
-  char *encPeerAbout;
-  char *encPeerTo;
-#endif
-  struct DistantNeighbor *about;
-  struct DirectNeighbor *to;
-  struct FastGossipNeighborList *about_list;
-
-  p2p_dv_MESSAGE_NeighborInfo *message;
-  struct PendingMessage *pending_message;
-
-  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
-    return;
-  }
-
-  if (send_context->fast_gossip_list_head != NULL)
-  {
-    about_list = send_context->fast_gossip_list_head;
-    about = about_list->about;
-    GNUNET_CONTAINER_DLL_remove (send_context->fast_gossip_list_head,
-                                 send_context->fast_gossip_list_tail,
-                                 about_list);
-    GNUNET_free (about_list);
-  }
-  else
-  {
-    /* FIXME: this may become a problem, because the heap walk has only one 
internal "walker".  This means
-     * that if two neighbor_send_tasks are operating in lockstep (which is 
quite possible, given default
-     * values for all connected peers) there may be a serious bias as to which 
peers get gossiped about!
-     * Probably the *best* way to fix would be to have an opaque pointer to 
the walk position passed as
-     * part of the walk_get_next call.  Then the heap would have to keep a 
list of walks, or reset the walk
-     * whenever a modification has been detected.  Yuck either way.  Perhaps 
we could iterate over the heap
-     * once to get a list of peers to gossip about and gossip them over 
time... But then if one goes away
-     * in the mean time that becomes nasty.  For now we'll just assume that 
the walking is done
-     * asynchronously enough to avoid major problems (-;
-     *
-     * NOTE: probably fixed once we decided send rate based on allowed 
bandwidth.
-     */
-    about = GNUNET_CONTAINER_heap_walk_get_next (neighbor_min_heap);
-  }
-  to = send_context->toNeighbor;
-
-  if ((about != NULL) && (to != about->referrer /* split horizon */ ) &&
-#if SUPPORT_HIDING
-      (about->hidden == GNUNET_NO) &&
-#endif
-      (to != NULL) &&
-      (0 !=
-       memcmp (&about->identity, &to->identity,
-               sizeof (struct GNUNET_PeerIdentity))) && (about->pkey != NULL))
-  {
-#if DEBUG_DV_GOSSIP_SEND
-    encPeerAbout = GNUNET_strdup (GNUNET_i2s (&about->identity));
-    encPeerTo = GNUNET_strdup (GNUNET_i2s (&to->identity));
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "%s: Sending info about peer %s id %u to directly connected 
peer %s\n",
-                GNUNET_i2s (&my_identity), encPeerAbout, about->our_id,
-                encPeerTo);
-    GNUNET_free (encPeerAbout);
-    GNUNET_free (encPeerTo);
-#endif
-    about->last_gossip = GNUNET_TIME_absolute_get ();
-    pending_message =
-        GNUNET_malloc (sizeof (struct PendingMessage) +
-                       sizeof (p2p_dv_MESSAGE_NeighborInfo));
-    pending_message->msg = (struct GNUNET_MessageHeader *) &pending_message[1];
-    pending_message->importance = default_dv_priority;
-    pending_message->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
-    memcpy (&pending_message->recipient, &to->identity,
-            sizeof (struct GNUNET_PeerIdentity));
-    pending_message->msg_size = sizeof (p2p_dv_MESSAGE_NeighborInfo);
-    message = (p2p_dv_MESSAGE_NeighborInfo *) pending_message->msg;
-    message->header.size = htons (sizeof (p2p_dv_MESSAGE_NeighborInfo));
-    message->header.type = htons (GNUNET_MESSAGE_TYPE_DV_GOSSIP);
-    message->cost = htonl (about->cost);
-    message->neighbor_id = htonl (about->our_id);
-
-    memcpy (&message->pkey, about->pkey,
-            sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded));
-    memcpy (&message->neighbor, &about->identity,
-            sizeof (struct GNUNET_PeerIdentity));
-
-    GNUNET_CONTAINER_DLL_insert_after (core_pending_head, core_pending_tail,
-                                       core_pending_tail, pending_message);
-
-    GNUNET_SCHEDULER_add_now (try_core_send, NULL);
-    /*if (core_transmit_handle == NULL)
-     * core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, 
GNUNET_YES,  default_dv_priority, GNUNET_TIME_UNIT_FOREVER_REL, &to->identity, 
sizeof(p2p_dv_MESSAGE_NeighborInfo), &core_transmit_notify, NULL); */
-
-  }
-
-  if (send_context->fast_gossip_list_head != NULL)      /* If there are other 
peers in the fast list, schedule right away */
-  {
-#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 (&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
-    send_context->task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_DV_DEFAULT_SEND_INTERVAL,
-                                      &neighbor_send_task, send_context);
-  }
-
-  return;
-}
-
-
-
-#if UNSIMPLER
-/**
- * Iterate over hash map entries for a distant neighbor,
- * if direct neighbor matches context call send message
- *
- * @param cls closure, a DV_SendContext
- * @param key current key code
- * @param value value in the hash map
- * @return GNUNET_YES if we should continue to
- *         iterate,
- *         GNUNET_NO if not.
- */
-int
-send_iterator (void *cls, const struct GNUNET_HashCode * key, void *abs_value)
-{
-  struct DV_SendContext *send_context = cls;
-  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 */
-  {
-    send_message_via (&my_identity, distant_neighbor, send_context);
-    return GNUNET_NO;
-  }
-  return GNUNET_YES;
-}
-#endif
-
-
-/** Forward declarations **/
-static int
-handle_dv_gossip_message (void *cls, const struct GNUNET_PeerIdentity *peer,
-                          const struct GNUNET_MessageHeader *message,
-                          const struct GNUNET_ATS_Information *atsi,
-                          unsigned int atsi_count);
-
-static int
-handle_dv_disconnect_message (void *cls, const struct GNUNET_PeerIdentity 
*peer,
-                              const struct GNUNET_MessageHeader *message,
-                              const struct GNUNET_ATS_Information *atsi,
-                              unsigned int atsi_count);
-/** End forward declarations **/
-
-
-/**
- * Free a DistantNeighbor node, including removing it
- * from the referer's list.
- */
-static void
-distant_neighbor_free (struct DistantNeighbor *referee)
-{
-  struct DirectNeighbor *referrer;
-
-  referrer = referee->referrer;
-  if (referrer != NULL)
-  {
-    GNUNET_CONTAINER_DLL_remove (referrer->referee_head, 
referrer->referee_tail,
-                                 referee);
-  }
-  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_free (referee);
-}
-
-/**
- * Free a DirectNeighbor node, including removing it
- * from the referer's list.
- */
-static void
-direct_neighbor_free (struct DirectNeighbor *direct)
-{
-  struct NeighborSendContext *send_context;
-  struct FastGossipNeighborList *about_list;
-  struct FastGossipNeighborList *prev_about;
-
-  send_context = direct->send_context;
-
-  if (send_context->task != GNUNET_SCHEDULER_NO_TASK)
-    GNUNET_SCHEDULER_cancel (send_context->task);
-
-  about_list = send_context->fast_gossip_list_head;
-  while (about_list != NULL)
-  {
-    GNUNET_CONTAINER_DLL_remove (send_context->fast_gossip_list_head,
-                                 send_context->fast_gossip_list_tail,
-                                 about_list);
-    prev_about = about_list;
-    about_list = about_list->next;
-    GNUNET_free (prev_about);
-  }
-  GNUNET_free (send_context);
-  GNUNET_free (direct);
-}
-
-/**
- * Multihashmap iterator for sending out disconnect messages
- * for a peer.
- *
- * @param cls the peer that was disconnected
- * @param key key value stored under
- * @param value the direct neighbor to send disconnect to
- *
- * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
- */
-static int
-schedule_disconnect_messages (void *cls, const struct GNUNET_HashCode * key,
-                              void *value)
-{
-  struct DisconnectContext *disconnect_context = cls;
-  struct DirectNeighbor *disconnected = disconnect_context->direct;
-  struct DirectNeighbor *notify = value;
-  struct PendingMessage *pending_message;
-  p2p_dv_MESSAGE_Disconnect *disconnect_message;
-
-  if (memcmp
-      (&notify->identity, &disconnected->identity,
-       sizeof (struct GNUNET_PeerIdentity)) == 0)
-    return GNUNET_YES;          /* Don't send disconnect message to peer that 
disconnected! */
-
-  pending_message =
-      GNUNET_malloc (sizeof (struct PendingMessage) +
-                     sizeof (p2p_dv_MESSAGE_Disconnect));
-  pending_message->msg = (struct GNUNET_MessageHeader *) &pending_message[1];
-  pending_message->importance = default_dv_priority;
-  pending_message->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
-  memcpy (&pending_message->recipient, &notify->identity,
-          sizeof (struct GNUNET_PeerIdentity));
-  pending_message->msg_size = sizeof (p2p_dv_MESSAGE_Disconnect);
-  disconnect_message = (p2p_dv_MESSAGE_Disconnect *) pending_message->msg;
-  disconnect_message->header.size = htons (sizeof (p2p_dv_MESSAGE_Disconnect));
-  disconnect_message->header.type = htons (GNUNET_MESSAGE_TYPE_DV_DISCONNECT);
-  disconnect_message->peer_id = htonl (disconnect_context->distant->our_id);
-
-  GNUNET_CONTAINER_DLL_insert_after (core_pending_head, core_pending_tail,
-                                     core_pending_tail, pending_message);
-
-  GNUNET_SCHEDULER_add_now (try_core_send, NULL);
-  /*if (core_transmit_handle == NULL)
-   * core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, 
GNUNET_YES, default_dv_priority, GNUNET_TIME_UNIT_FOREVER_REL, 
&notify->identity, sizeof(p2p_dv_MESSAGE_Disconnect), &core_transmit_notify, 
NULL); */
-
-  return GNUNET_YES;
-}
-
-
-#if PKEY_NO_NEIGHBOR_ON_ADD
-/**
- * Iterator over hash map entries.
- *
- * @param cls closure
- * @param key current key code
- * @param value value in the hash map
- * @return GNUNET_YES if we should continue to
- *         iterate,
- *         GNUNET_NO if not.
- */
-static int
-add_pkey_to_extended (void *cls, const struct GNUNET_HashCode * key, void 
*abs_value)
-{
-  struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pkey = cls;
-  struct DistantNeighbor *distant_neighbor = abs_value;
-
-  if (distant_neighbor->pkey == NULL)
-  {
-    distant_neighbor->pkey =
-        GNUNET_malloc (sizeof (struct 
GNUNET_CRYPTO_EccPublicKeyBinaryEncoded));
-    memcpy (distant_neighbor->pkey, pkey,
-            sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded));
-  }
-
-  return GNUNET_YES;
-}
-#endif
-
-/**
- * Iterator over hash map entries.
- *
- * @param cls closure
- * @param key current key code
- * @param value value in the hash map
- * @return GNUNET_YES if we should continue to
- *         iterate,
- *         GNUNET_NO if not.
- */
-static int
-update_matching_neighbors (void *cls, const struct GNUNET_HashCode * key, void 
*value)
-{
-  struct NeighborUpdateInfo *update_info = cls;
-  struct DistantNeighbor *distant_neighbor = value;
-
-  if (update_info->referrer == distant_neighbor->referrer)      /* Direct 
neighbor matches, update it's info and return GNUNET_NO */
-  {
-    /* same referrer, cost change! */
-    GNUNET_CONTAINER_heap_update_cost (neighbor_max_heap,
-                                       update_info->neighbor->max_loc,
-                                       update_info->cost);
-    GNUNET_CONTAINER_heap_update_cost (neighbor_min_heap,
-                                       update_info->neighbor->min_loc,
-                                       update_info->cost);
-    update_info->neighbor->last_activity = update_info->now;
-    update_info->neighbor->cost = update_info->cost;
-    update_info->neighbor->referrer_id = update_info->referrer_peer_id;
-    return GNUNET_NO;
-  }
-
-  return GNUNET_YES;
-}
-
-
-/**
- * Iterate over all current direct peers, add DISTANT newly connected
- * peer to the fast gossip list for that peer so we get DV routing
- * information out as fast as possible!
- *
- * @param cls the newly connected neighbor we will gossip about
- * @param key the hashcode of the peer
- * @param value the direct neighbor we should gossip to
- *
- * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise
- */
-static int
-add_distant_all_direct_neighbors (void *cls, const struct GNUNET_HashCode * 
key,
-                                  void *value)
-{
-  struct DirectNeighbor *direct = (struct DirectNeighbor *) value;
-  struct DistantNeighbor *distant = (struct DistantNeighbor *) cls;
-  struct NeighborSendContext *send_context = direct->send_context;
-  struct FastGossipNeighborList *gossip_entry;
-
-#if DEBUG_DV
-  char *encPeerAbout;
-  char *encPeerTo;
-#endif
-
-  if (distant == NULL)
-  {
-    return GNUNET_YES;
-  }
-
-  if (memcmp
-      (&direct->identity, &distant->identity,
-       sizeof (struct GNUNET_PeerIdentity)) == 0)
-  {
-    return GNUNET_YES;          /* Don't gossip to a peer about itself! */
-  }
-
-#if SUPPORT_HIDING
-  if (distant->hidden == GNUNET_YES)
-    return GNUNET_YES;          /* This peer should not be gossipped about 
(hidden) */
-#endif
-  gossip_entry = GNUNET_malloc (sizeof (struct FastGossipNeighborList));
-  gossip_entry->about = distant;
-
-  GNUNET_CONTAINER_DLL_insert_after (send_context->fast_gossip_list_head,
-                                     send_context->fast_gossip_list_tail,
-                                     send_context->fast_gossip_list_tail,
-                                     gossip_entry);
-#if DEBUG_DV
-  encPeerAbout = GNUNET_strdup (GNUNET_i2s (&distant->identity));
-  encPeerTo = GNUNET_strdup (GNUNET_i2s (&direct->identity));
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "%s: Fast send info about peer %s id %u for directly connected 
peer %s\n",
-              GNUNET_i2s (&my_identity), encPeerAbout, distant->our_id,
-              encPeerTo);
-  GNUNET_free (encPeerAbout);
-  GNUNET_free (encPeerTo);
-#endif
-  /*if (send_context->task != GNUNET_SCHEDULER_NO_TASK)
-   * GNUNET_SCHEDULER_cancel(send_context->task); */
-
-  send_context->task =
-      GNUNET_SCHEDULER_add_now (&neighbor_send_task, send_context);
-  return GNUNET_YES;
-}
-
-/**
- * Callback for hello address creation.
- *
- * @param cls closure, a struct HelloContext
- * @param max maximum number of bytes that can be written to buf
- * @param buf where to write the address information
- *
- * @return number of bytes written, 0 to signal the
- *         end of the iteration.
- */
-static size_t
-generate_hello_address (void *cls, size_t max, void *buf)
-{
-  struct HelloContext *hello_context = cls;
-  struct GNUNET_HELLO_Address hello_address;
-  char *addr_buffer;
-  size_t offset;
-  size_t size;
-  size_t ret;
-
-  if (hello_context->addresses_to_add == 0)
-    return 0;
-
-  /* Hello "address" will be concatenation of distant peer and direct peer 
identities */
-  size = 2 * sizeof (struct GNUNET_PeerIdentity);
-  GNUNET_assert (max >= size);
-
-  addr_buffer = GNUNET_malloc (size);
-  offset = 0;
-  /* Copy the distant peer identity to buffer */
-  memcpy (addr_buffer, &hello_context->distant_peer,
-          sizeof (struct GNUNET_PeerIdentity));
-  offset += sizeof (struct GNUNET_PeerIdentity);
-  /* Copy the direct peer identity to buffer */
-  memcpy (&addr_buffer[offset], hello_context->direct_peer,
-          sizeof (struct GNUNET_PeerIdentity));
-  memset (&hello_address.peer, 0, sizeof (struct GNUNET_PeerIdentity));
-  hello_address.address = addr_buffer;
-  hello_address.transport_name = "dv";
-  hello_address.address_length = size;
-  ret =
-      GNUNET_HELLO_add_address (&hello_address,
-                                GNUNET_TIME_relative_to_absolute
-                                (GNUNET_TIME_UNIT_HOURS), buf, max);
-
-  hello_context->addresses_to_add--;
-
-  GNUNET_free (addr_buffer);
-  return ret;
-}
-
-
-/**
- * Handles when a peer is either added due to being newly connected
- * or having been gossiped about, also called when the cost for a neighbor
- * needs to be updated.
- *
- * @param peer identity of the peer whose info is being added/updated
- * @param pkey public key of the peer whose info is being added/updated
- * @param referrer_peer_id id to use when sending to 'peer'
- * @param referrer if this is a gossiped peer, who did we hear it from?
- * @param cost the cost of communicating with this peer via 'referrer'
- *
- * @return the added neighbor, the updated neighbor or NULL (neighbor
- *         not added)
- */
-static struct DistantNeighbor *
-addUpdateNeighbor (const struct GNUNET_PeerIdentity *peer,
-                   struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pkey,
-                   unsigned int referrer_peer_id,
-                   struct DirectNeighbor *referrer, unsigned int cost)
-{
-  struct DistantNeighbor *neighbor;
-  struct DistantNeighbor *max;
-  struct GNUNET_TIME_Absolute now;
-  struct NeighborUpdateInfo *neighbor_update;
-  struct HelloContext *hello_context;
-  struct GNUNET_HELLO_Message *hello_msg;
-  unsigned int our_id;
-  char *addr1;
-  char *addr2;
-  int i;
-
-#if DEBUG_DV_PEER_NUMBERS
-  char *encAbout;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s Received sender id (%u)!\n",
-              "DV SERVICE", referrer_peer_id);
-#endif
-
-  now = GNUNET_TIME_absolute_get ();
-  neighbor =
-      GNUNET_CONTAINER_multihashmap_get (extended_neighbors, 
&peer->hashPubKey);
-  neighbor_update = GNUNET_malloc (sizeof (struct NeighborUpdateInfo));
-  neighbor_update->neighbor = neighbor;
-  neighbor_update->cost = cost;
-  neighbor_update->now = now;
-  neighbor_update->referrer = referrer;
-  neighbor_update->referrer_peer_id = referrer_peer_id;
-
-  if (neighbor != NULL)
-  {
-#if USE_PEER_ID
-    memcpy (&our_id, &neighbor->identity, sizeof (unsigned int));
-#else
-    our_id = neighbor->our_id;
-#endif
-  }
-  else
-  {
-#if USE_PEER_ID
-    memcpy (&our_id, peer, sizeof (unsigned int));
-#else
-    our_id =
-        GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG,
-                                  RAND_MAX - 1) + 1;
-#endif
-  }
-
-  /* Either we do not know this peer, or we already do but via a different 
immediate peer */
-  if ((neighbor == NULL) ||
-      (GNUNET_CONTAINER_multihashmap_get_multiple
-       (extended_neighbors, &peer->hashPubKey, &update_matching_neighbors,
-        neighbor_update) != GNUNET_SYSERR))
-  {
-#if AT_MOST_ONE
-    if ((neighbor != NULL) && (cost < neighbor->cost))  /* New cost is less 
than old, remove old */
-    {
-      distant_neighbor_free (neighbor);
-    }
-    else if (neighbor != NULL)  /* Only allow one DV connection to each peer */
-    {
-      return NULL;
-    }
-#endif
-    /* new neighbor! */
-    if (cost > fisheye_depth)
-    {
-      /* too costly */
-      GNUNET_free (neighbor_update);
-      return NULL;
-    }
-
-#if DEBUG_DV_PEER_NUMBERS
-    encAbout = GNUNET_strdup (GNUNET_i2s (peer));
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "%s: %s Chose NEW id (%u) for peer %s!\n",
-                GNUNET_i2s (&my_identity), "DV SERVICE", our_id, encAbout);
-    GNUNET_free (encAbout);
-#endif
-
-    if (max_table_size <=
-        GNUNET_CONTAINER_multihashmap_size (extended_neighbors))
-    {
-      /* remove most expensive entry */
-      max = GNUNET_CONTAINER_heap_peek (neighbor_max_heap);
-      GNUNET_assert (max != NULL);
-      if (cost > max->cost)
-      {
-        /* new entry most expensive, don't create */
-        GNUNET_free (neighbor_update);
-        return NULL;
-      }
-      if (max->cost > 1)
-      {
-        /* only free if this is not a direct connection;
-         * we could theoretically have more direct
-         * connections than DV entries allowed total! */
-        distant_neighbor_free (max);
-      }
-    }
-
-    neighbor = GNUNET_malloc (sizeof (struct DistantNeighbor));
-    GNUNET_CONTAINER_DLL_insert (referrer->referee_head, 
referrer->referee_tail,
-                                 neighbor);
-    neighbor->max_loc =
-        GNUNET_CONTAINER_heap_insert (neighbor_max_heap, neighbor, cost);
-    neighbor->min_loc =
-        GNUNET_CONTAINER_heap_insert (neighbor_min_heap, neighbor, cost);
-    neighbor->referrer = referrer;
-    memcpy (&neighbor->identity, peer, sizeof (struct GNUNET_PeerIdentity));
-    if (pkey != NULL)           /* pkey will be null on direct neighbor 
addition */
-    {
-      neighbor->pkey =
-          GNUNET_malloc (sizeof
-                         (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded));
-      memcpy (neighbor->pkey, pkey,
-              sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded));
-    }
-    else
-      neighbor->pkey = pkey;
-
-    neighbor->last_activity = now;
-    neighbor->cost = cost;
-    neighbor->referrer_id = referrer_peer_id;
-    neighbor->our_id = our_id;
-    neighbor->hidden =
-        (cost ==
-         DIRECT_NEIGHBOR_COST)
-        ? (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 4) ==
-           0) : GNUNET_NO;
-
-    GNUNET_CONTAINER_multihashmap_put (extended_neighbors, &peer->hashPubKey,
-                                       neighbor,
-                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-    if (referrer_peer_id != 0)
-    {
-      for (i = 0; i < MAX_OUTSTANDING_MESSAGES; i++)
-      {
-        if (referrer->pending_messages[i].sender_id == referrer_peer_id)       
 /* We have a queued message from just learned about peer! */
-        {
-#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
-          struct GNUNET_ATS_Information atsi[2];
-
-          atsi[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
-          atsi[0].value = htonl (referrer->pending_messages[i].distance);
-          atsi[1].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY);
-          atsi[1].value =
-              htonl ((uint32_t) referrer->pending_messages[i].
-                     latency.rel_value);
-          handle_dv_data_message (NULL, &referrer->pending_messages[i].sender,
-                                  referrer->pending_messages[i].message, atsi,
-                                  2);
-          GNUNET_free (referrer->pending_messages[i].message);
-          referrer->pending_messages[i].sender_id = 0;
-        }
-      }
-    }
-    if ((cost != DIRECT_NEIGHBOR_COST) && (neighbor->pkey != NULL))
-    {
-      /* Added neighbor, now send HELLO to transport */
-      hello_context = GNUNET_malloc (sizeof (struct HelloContext));
-      hello_context->direct_peer = &referrer->identity;
-      memcpy (&hello_context->distant_peer, peer,
-              sizeof (struct GNUNET_PeerIdentity));
-      hello_context->addresses_to_add = 1;
-      hello_msg =
-          GNUNET_HELLO_create (pkey, &generate_hello_address, hello_context);
-      GNUNET_assert (memcmp
-                     (hello_context->direct_peer, &hello_context->distant_peer,
-                      sizeof (struct GNUNET_PeerIdentity)) != 0);
-      addr1 = GNUNET_strdup (GNUNET_i2s (hello_context->direct_peer));
-      addr2 = GNUNET_strdup (GNUNET_i2s (&hello_context->distant_peer));
-#if DEBUG_DV
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "%s: GIVING HELLO size %d for %s via %s to TRANSPORT\n",
-                  my_short_id, GNUNET_HELLO_size (hello_msg), addr2, addr1);
-#endif
-      GNUNET_free (addr1);
-      GNUNET_free (addr2);
-      send_to_plugin (hello_context->direct_peer,
-                      GNUNET_HELLO_get_header (hello_msg),
-                      GNUNET_HELLO_size (hello_msg),
-                      &hello_context->distant_peer, cost);
-      GNUNET_free (hello_context);
-      GNUNET_free (hello_msg);
-    }
-
-  }
-  else
-  {
-#if DEBUG_DV_GOSSIP
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "%s: Already know peer %s distance %d, referrer id %d!\n", 
"dv",
-                GNUNET_i2s (peer), cost, referrer_peer_id);
-#endif
-  }
-#if DEBUG_DV
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s: Size of extended_neighbors is 
%d\n",
-              "dv", GNUNET_CONTAINER_multihashmap_size (extended_neighbors));
-#endif
-
-  GNUNET_free (neighbor_update);
-  return neighbor;
-}
-
-
-/**
- * Core handler for dv disconnect messages.  These will be used
- * by us to tell transport via the dv plugin that a peer can
- * no longer be contacted by us via a certain address.  We should
- * then propagate these messages on, given that the distance to
- * the peer indicates we would have gossiped about it to others.
- *
- * @param cls closure
- * @param peer peer which sent the message (immediate sender)
- * @param message the message
- * @param atsi performance data
- * @param atsi_count number of entries in atsi
- */
-static int
-handle_dv_disconnect_message (void *cls, const struct GNUNET_PeerIdentity 
*peer,
-                              const struct GNUNET_MessageHeader *message,
-                              const struct GNUNET_ATS_Information *atsi,
-                              unsigned int atsi_count)
-{
-  struct DirectNeighbor *referrer;
-  struct DistantNeighbor *distant;
-  p2p_dv_MESSAGE_Disconnect *enc_message =
-      (p2p_dv_MESSAGE_Disconnect *) message;
-
-  if (ntohs (message->size) < sizeof (p2p_dv_MESSAGE_Disconnect))
-  {
-    return GNUNET_SYSERR;       /* invalid message */
-  }
-
-  referrer =
-      GNUNET_CONTAINER_multihashmap_get (direct_neighbors, &peer->hashPubKey);
-  if (referrer == NULL)
-    return GNUNET_OK;
-
-  distant = referrer->referee_head;
-  while (distant != NULL)
-  {
-    if (distant->referrer_id == ntohl (enc_message->peer_id))
-    {
-      distant_neighbor_free (distant);
-      distant = referrer->referee_head;
-    }
-    else
-      distant = distant->next;
-  }
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Iterate over all currently known peers, add them to the
- * fast gossip list for this peer so we get DV routing information
- * out as fast as possible!
- *
- * @param cls the direct neighbor we will gossip to
- * @param key the hashcode of the peer
- * @param value the distant neighbor we should add to the list
- *
- * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise
- */
-static int
-add_all_extended_peers (void *cls, const struct GNUNET_HashCode * key, void 
*value)
-{
-  struct NeighborSendContext *send_context = (struct NeighborSendContext *) 
cls;
-  struct DistantNeighbor *distant = (struct DistantNeighbor *) value;
-  struct FastGossipNeighborList *gossip_entry;
-
-  if (memcmp
-      (&send_context->toNeighbor->identity, &distant->identity,
-       sizeof (struct GNUNET_PeerIdentity)) == 0)
-    return GNUNET_YES;          /* Don't gossip to a peer about itself! */
-
-#if SUPPORT_HIDING
-  if (distant->hidden == GNUNET_YES)
-    return GNUNET_YES;          /* This peer should not be gossipped about 
(hidden) */
-#endif
-  gossip_entry = GNUNET_malloc (sizeof (struct FastGossipNeighborList));
-  gossip_entry->about = distant;
-
-  GNUNET_CONTAINER_DLL_insert_after (send_context->fast_gossip_list_head,
-                                     send_context->fast_gossip_list_tail,
-                                     send_context->fast_gossip_list_tail,
-                                     gossip_entry);
-
-  return GNUNET_YES;
-}
-
-
-/**
- * Iterate over all current direct peers, add newly connected peer
- * to the fast gossip list for that peer so we get DV routing
- * information out as fast as possible!
- *
- * @param cls the newly connected neighbor we will gossip about
- * @param key the hashcode of the peer
- * @param value the direct neighbor we should gossip to
- *
- * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise
- */
-static int
-add_all_direct_neighbors (void *cls, const struct GNUNET_HashCode * key, void 
*value)
-{
-  struct DirectNeighbor *direct = (struct DirectNeighbor *) value;
-  struct DirectNeighbor *to = (struct DirectNeighbor *) cls;
-  struct DistantNeighbor *distant;
-  struct NeighborSendContext *send_context = direct->send_context;
-  struct FastGossipNeighborList *gossip_entry;
-  char *direct_id;
-
-
-  distant =
-      GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
-                                         &to->identity.hashPubKey);
-  if (distant == NULL)
-  {
-    return GNUNET_YES;
-  }
-
-  if (memcmp
-      (&direct->identity, &to->identity,
-       sizeof (struct GNUNET_PeerIdentity)) == 0)
-  {
-    return GNUNET_YES;          /* Don't gossip to a peer about itself! */
-  }
-
-#if SUPPORT_HIDING
-  if (distant->hidden == GNUNET_YES)
-    return GNUNET_YES;          /* This peer should not be gossipped about 
(hidden) */
-#endif
-  direct_id = GNUNET_strdup (GNUNET_i2s (&direct->identity));
-#if DEBUG_DV_GOSSIP
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "%s: adding peer %s to fast send list for %s\n", my_short_id,
-              GNUNET_i2s (&distant->identity), direct_id);
-#endif
-  GNUNET_free (direct_id);
-  gossip_entry = GNUNET_malloc (sizeof (struct FastGossipNeighborList));
-  gossip_entry->about = distant;
-
-  GNUNET_CONTAINER_DLL_insert_after (send_context->fast_gossip_list_head,
-                                     send_context->fast_gossip_list_tail,
-                                     send_context->fast_gossip_list_tail,
-                                     gossip_entry);
-  if (send_context->task != GNUNET_SCHEDULER_NO_TASK)
-    GNUNET_SCHEDULER_cancel (send_context->task);
-
-  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;
-}
-
-
-////////////////////////////////////////////////////////////////////////
-#endif
-
-
-
-/**
  * Method called whenever a peer connects.
  *
  * @param cls closure
@@ -2168,7 +892,7 @@
      GNUNET_MESSAGE_TYPE_DV_START, 
      sizeof (struct GNUNET_MessageHeader) },
     { &handle_dv_send_message, NULL, 
-      GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND, 
+      GNUNET_MESSAGE_TYPE_DV_SEND, 
       0},
     {NULL, NULL, 0, 0}
   };




reply via email to

[Prev in Thread] Current Thread [Next in Thread]