dbg
[oweals/gnunet.git] / src / core / core_api.c
index 931ffe97e457f5239a9144ab48b8ca2dab235c6c..f8c7c0aa6ef79a231e1d5454bb897117db764cc8 100644 (file)
@@ -43,7 +43,7 @@ struct GNUNET_CORE_Handle
   /**
    * Configuration we're using.
    */
-  struct GNUNET_CONFIGURATION_Handle *cfg;
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
 
   /**
    * Closure for the various callbacks.
@@ -58,18 +58,12 @@ struct GNUNET_CORE_Handle
   /**
    * Function to call whenever we're notified about a peer connecting.
    */
-  GNUNET_CORE_ClientEventHandler connects;
+  GNUNET_CORE_ConnectEventHandler connects;
 
   /**
    * Function to call whenever we're notified about a peer disconnecting.
    */
-  GNUNET_CORE_ClientEventHandler disconnects;
-
-  /**
-   * Function to call whenever we're asked to generate traffic
-   * (data provided to be transmitted back to the service).
-   */
-  GNUNET_CORE_BufferFillCallback bfc;
+  GNUNET_CORE_DisconnectEventHandler disconnects;
 
   /**
    * Function to call whenever we receive an inbound message.
@@ -87,14 +81,14 @@ struct GNUNET_CORE_Handle
   const struct GNUNET_CORE_MessageHandler *handlers;
 
   /**
-   * Our connection to the service.
+   * Our connection to the service for notifications.
    */
-  struct GNUNET_CLIENT_Connection *client;
+  struct GNUNET_CLIENT_Connection *client_notifications;
 
   /**
    * Handle for our current transmission request.
    */
-  struct GNUNET_NETWORK_TransmitHandle *th;
+  struct GNUNET_CLIENT_TransmitHandle *th;
 
   /**
    * Head of doubly-linked list of pending requests.
@@ -111,6 +105,17 @@ struct GNUNET_CORE_Handle
    */
   struct GNUNET_CORE_TransmitHandle *submitted;
 
+  /**
+   * Currently submitted request based on solicitation (or NULL)
+   */
+  struct GNUNET_CORE_TransmitHandle *solicit_transmit_req;
+
+  /**
+   * Buffer where we store a message for transmission in response
+   * to a traffic solicitation (or NULL).
+   */
+  char *solicit_buffer;
+
   /**
    * How long to wait until we time out the connection attempt?
    */
@@ -173,29 +178,18 @@ struct GNUNET_CORE_TransmitHandle
    * The function will be called with a NULL buffer to signal
    * timeout.
    */
-  GNUNET_NETWORK_TransmitReadyNotify get_message;
+  GNUNET_CONNECTION_TransmitReadyNotify get_message;
 
   /**
    * Closure for get_message.
    */
   void *get_message_cls;
 
-  /**
-   * If this entry is for a configuration request, pointer
-   * to the information callback; otherwise NULL.
-   */
-  GNUNET_CORE_PeerConfigurationInfoCallback info;
-
-  /**
-   * Closure for info.
-   */
-  void *info_cls;
-
   /**
    * If this entry is for a transmission request, pointer
    * to the notify callback; otherwise NULL.
    */
-  GNUNET_NETWORK_TransmitReadyNotify notify;
+  GNUNET_CONNECTION_TransmitReadyNotify notify;
 
   /**
    * Closure for notify.
@@ -231,6 +225,10 @@ struct GNUNET_CORE_TransmitHandle
 };
 
 
+static void
+reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
 /**
  * Function called when we are ready to transmit our
  * "START" message (or when this operation timed out).
@@ -246,18 +244,28 @@ static size_t transmit_start (void *cls, size_t size, void *buf);
 /**
  * Our current client connection went down.  Clean it up
  * and try to reconnect!
+ *
+ * @param h our handle to the core service
  */
 static void
 reconnect (struct GNUNET_CORE_Handle *h)
 {
-  GNUNET_CLIENT_disconnect (h->client);
+  if (h->client_notifications != NULL)
+    GNUNET_CLIENT_disconnect (h->client_notifications, GNUNET_NO);
   h->currently_down = GNUNET_YES;
-  h->client = GNUNET_CLIENT_connect (h->sched, "core", h->cfg);
-  h->th = GNUNET_CLIENT_notify_transmit_ready (h->client,
-                                               sizeof (struct InitMessage) +
-                                               sizeof (uint16_t) * h->hcnt,
-                                               GNUNET_TIME_UNIT_SECONDS,
-                                               &transmit_start, h);
+  h->client_notifications = GNUNET_CLIENT_connect (h->sched, "core", h->cfg);
+  if (h->client_notifications == NULL)
+    h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->sched,
+                                                     GNUNET_TIME_UNIT_SECONDS,
+                                                     &reconnect_task,
+                                                     h);
+  else
+    h->th = GNUNET_CLIENT_notify_transmit_ready (h->client_notifications,
+                                                sizeof (struct InitMessage) +
+                                                sizeof (uint16_t) * h->hcnt,
+                                                GNUNET_TIME_UNIT_SECONDS,
+                                                GNUNET_NO,
+                                                &transmit_start, h);
 }
 
 
@@ -272,12 +280,9 @@ static void
 timeout_request (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct GNUNET_CORE_TransmitHandle *th = cls;
-  struct GNUNET_CORE_Handle *h;
 
-  h = th->ch;
-  th->timeout_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
+  th->timeout_task = GNUNET_SCHEDULER_NO_TASK;
   GNUNET_assert (0 == th->get_message (th->get_message_cls, 0, NULL));
-  GNUNET_CORE_notify_transmit_ready_cancel (th);
 }
 
 
@@ -306,9 +311,6 @@ request_start (void *cls, size_t size, void *buf)
     }
   /* create new timeout task (in case core takes too long to respond!) */
   th->timeout_task = GNUNET_SCHEDULER_add_delayed (h->sched,
-                                                   GNUNET_NO,
-                                                   GNUNET_SCHEDULER_PRIORITY_KEEP,
-                                                   GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
                                                    GNUNET_TIME_absolute_get_remaining
                                                    (th->timeout),
                                                    &timeout_request, th);
@@ -336,91 +338,55 @@ static void
 trigger_next_request (struct GNUNET_CORE_Handle *h)
 {
   struct GNUNET_CORE_TransmitHandle *th;
+
   if (h->currently_down)
-    return;                     /* connection temporarily down */
+    {
+#if DEBUG_CORE
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "In trigger_next_request, connection currently down...\n");
+#endif
+      return;                     /* connection temporarily down */
+    }
   if (NULL == (th = h->pending_head))
     return;                     /* no requests pending */
   GNUNET_assert (NULL == h->th);
-  GNUNET_SCHEDULER_cancel (h->sched, th->timeout_task);
-  th->timeout_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
-  h->th = GNUNET_CLIENT_notify_transmit_ready (h->client,
+  if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
+    {
+      GNUNET_SCHEDULER_cancel (h->sched, th->timeout_task);
+      th->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+    }
+  h->th = GNUNET_CLIENT_notify_transmit_ready (h->client_notifications,
                                                th->msize,
                                                GNUNET_TIME_absolute_get_remaining
-                                               (th->timeout), &request_start,
+                                               (th->timeout), 
+                                              GNUNET_NO,
+                                              &request_start,
                                                h);
 }
 
 
 /**
- * cls is a pointer to a 32 bit number followed by that
- * amount of data.  If possible, copy to buf and return
- * number of bytes copied.  Always free the buffer.
- */
-static size_t
-copy_and_free (void *cls, size_t size, void *buf)
-{
-  char *cbuf = cls;
-  uint32_t have;
-
-  memcpy (&have, cbuf, sizeof (uint32_t));
-  if (have > size)
-    {
-      /* timeout / error case */
-      GNUNET_free (cbuf);
-      return 0;
-    }
-  memcpy (buf, cbuf + sizeof (uint32_t), have);
-  GNUNET_free (cbuf);
-  return have;
-}
-
-
-/**
- * Call bfc callback to solicit traffic for the given peer.
- */
-static void
-solicit_traffic (struct GNUNET_CORE_Handle *h,
-                 const struct GNUNET_PeerIdentity *peer, uint32_t amount)
-{
-  char buf[amount];
-  size_t have;
-  char *cbuf;
-
-  have = h->bfc (h->cls, peer, buf, amount);
-  if (have == 0)
-    return;
-  GNUNET_assert (have >= sizeof (struct GNUNET_MessageHeader));
-  cbuf = GNUNET_malloc (have + sizeof (uint32_t));
-  memcpy (cbuf, &have, sizeof (uint32_t));
-  memcpy (cbuf + sizeof (uint32_t), buf, have);
-  GNUNET_CORE_notify_transmit_ready (h,
-                                     0,
-                                     GNUNET_TIME_UNIT_SECONDS,
-                                     peer, have, &copy_and_free, cbuf);
-}
-
-
-/**
- * Handler for most messages received from the core.
+ * Handler for notification messages received from the core.
+ *
+ * @param cls our "struct GNUNET_CORE_Handle"
+ * @param msg the message received from the core service
  */
 static void
-main_handler (void *cls, const struct GNUNET_MessageHeader *msg)
+main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg)
 {
   struct GNUNET_CORE_Handle *h = cls;
   unsigned int hpos;
   const struct ConnectNotifyMessage *cnm;
+  const struct DisconnectNotifyMessage *dnm;
   const struct NotifyTrafficMessage *ntm;
-  const struct ConfigurationInfoMessage *cim;
-  const struct SolicitTrafficMessage *stm;
   const struct GNUNET_MessageHeader *em;
   uint16_t msize;
   uint16_t et;
-  uint32_t ss;
   const struct GNUNET_CORE_MessageHandler *mh;
 
   if (msg == NULL)
     {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                   _
                   ("Client was disconnected from core service, trying to reconnect.\n"));
       reconnect (h);
@@ -446,6 +412,10 @@ main_handler (void *cls, const struct GNUNET_MessageHeader *msg)
           break;
         }
       cnm = (const struct ConnectNotifyMessage *) msg;
+      h->connects (h->cls,
+                  &cnm->peer,
+                  GNUNET_TIME_relative_ntoh (cnm->latency),
+                  ntohl (cnm->distance));
       break;
     case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT:
       if (NULL == h->disconnects)
@@ -453,12 +423,14 @@ main_handler (void *cls, const struct GNUNET_MessageHeader *msg)
           GNUNET_break (0);
           break;
         }
-      if (msize != sizeof (struct ConnectNotifyMessage))
+      if (msize != sizeof (struct DisconnectNotifyMessage))
         {
           GNUNET_break (0);
           break;
         }
-      cnm = (const struct ConnectNotifyMessage *) msg;
+      dnm = (const struct DisconnectNotifyMessage *) msg;
+      h->disconnects (h->cls,
+                     &dnm->peer);
       break;
     case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND:
       if (msize <
@@ -494,7 +466,9 @@ main_handler (void *cls, const struct GNUNET_MessageHeader *msg)
               continue;
             }
           if (GNUNET_OK !=
-              h->handlers[hpos].callback (h->cls, &ntm->peer, em))
+              h->handlers[hpos].callback (h->cls, &ntm->peer, em,
+                                         GNUNET_TIME_relative_ntoh (ntm->latency),
+                                         ntohl (ntm->distance)))
             {
               /* error in processing, disconnect ! */
               reconnect (h);
@@ -502,7 +476,9 @@ main_handler (void *cls, const struct GNUNET_MessageHeader *msg)
             }
         }
       if (NULL != h->inbound_notify)
-        h->inbound_notify (h->cls, &ntm->peer, em);
+        h->inbound_notify (h->cls, &ntm->peer, em,
+                          GNUNET_TIME_relative_ntoh (ntm->latency),
+                          ntohl (ntm->distance));
       break;
     case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND:
       if (msize <
@@ -525,62 +501,19 @@ main_handler (void *cls, const struct GNUNET_MessageHeader *msg)
           GNUNET_break (0);
           break;
         }
-      h->outbound_notify (h->cls, &ntm->peer, em);
-      break;
-    case GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO:
-      if (msize != sizeof (struct ConfigurationInfoMessage))
-        {
-          GNUNET_break (0);
-          break;
-        }
-      if (NULL == h->submitted)
-        break;
-      cim = (const struct ConfigurationInfoMessage *) msg;
-
-      /* process configuration data */
-      if (h->submitted->info != NULL)
-        h->submitted->info (h->submitted->info_cls,
-                            &h->submitted->peer,
-                            ntohl (cim->bpm_in),
-                            ntohl (cim->bpm_out),
-                            GNUNET_TIME_relative_ntoh (cim->latency),
-                            (int) ntohl (cim->reserved_amount),
-                            cim->preference);
-      /* done, clean up! */
-      GNUNET_CORE_notify_transmit_ready_cancel (h->submitted);
-      trigger_next_request (h);
-      break;
-    case GNUNET_MESSAGE_TYPE_CORE_SOLICIT_TRAFFIC:
-      if (msize != sizeof (struct SolicitTrafficMessage))
-        {
-          GNUNET_break (0);
-          break;
-        }
-      stm = (const struct SolicitTrafficMessage *) msg;
-      if (NULL == h->bfc)
-        {
-          GNUNET_break (0);
-          break;
-        }
-      ss = ntohl (stm->solicit_size);
-      if ((ss > GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
-          (ss + sizeof (struct SendMessage) > GNUNET_SERVER_MAX_MESSAGE_SIZE))
-        {
-          GNUNET_break (0);
-          break;
-        }
-      solicit_traffic (h, &stm->peer, ss);
+      h->outbound_notify (h->cls, &ntm->peer, em,
+                         GNUNET_TIME_relative_ntoh (ntm->latency),
+                         ntohl (ntm->distance));
       break;
     default:
       GNUNET_break (0);
       break;
     }
-  GNUNET_CLIENT_receive (h->client,
-                         &main_handler, h, GNUNET_TIME_UNIT_FOREVER_REL);
+  GNUNET_CLIENT_receive (h->client_notifications,
+                         &main_notify_handler, h, GNUNET_TIME_UNIT_FOREVER_REL);
 }
 
 
-
 /**
  * Function called when we are ready to transmit our
  * "START" message (or when this operation timed out).
@@ -614,10 +547,12 @@ init_reply_handler (void *cls, const struct GNUNET_MessageHeader *msg)
       (ntohs (msg->size) != sizeof (struct InitReplyMessage)) ||
       (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY))
     {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   _
-                  ("Error connecting to core service (failed to receive `%s' message).\n"),
-                  "INIT_REPLY");
+                  ("Error connecting to core service (failed to receive `%s' message, got message of type %u and size %u).\n"),
+                  "INIT_REPLY",
+                 (msg == NULL) ? -1 : ntohs (msg->type),
+                 (msg == NULL) ? -1 : ntohs (msg->size));
       GNUNET_break (msg == NULL);
       transmit_start (h, 0, NULL);
       return;
@@ -626,21 +561,16 @@ init_reply_handler (void *cls, const struct GNUNET_MessageHeader *msg)
   /* start our message processing loop */
 #if DEBUG_CORE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              _
-              ("Successfully connected to core service, starting processing loop.\n"));
+             "Successfully connected to core service, starting processing loop.\n");
 #endif
   h->currently_down = GNUNET_NO;
   trigger_next_request (h);
-  GNUNET_CLIENT_receive (h->client,
-                         &main_handler, h, GNUNET_TIME_UNIT_FOREVER_REL);
+  GNUNET_CLIENT_receive (h->client_notifications,
+                         &main_notify_handler, h, GNUNET_TIME_UNIT_FOREVER_REL);
   if (NULL != (init = h->init))
     {
       /* mark so we don't call init on reconnect */
       h->init = NULL;
-#if DEBUG_CORE
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  _("Successfully connected to core service.\n"));
-#endif
       GNUNET_CRYPTO_hash (&m->publicKey,
                           sizeof (struct
                                   GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
@@ -654,7 +584,7 @@ static void
 reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct GNUNET_CORE_Handle *h = cls;
-  h->reconnect_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
+  h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
   reconnect (h);
 }
 
@@ -694,9 +624,7 @@ transmit_start (void *cls, size_t size, void *buf)
             h->startup_timeout =
               GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
           h->reconnect_task =
-            GNUNET_SCHEDULER_add_delayed (h->sched, GNUNET_NO,
-                                          GNUNET_SCHEDULER_PRIORITY_IDLE,
-                                          GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
+            GNUNET_SCHEDULER_add_delayed (h->sched, 
                                           delay, &reconnect_task, h);
           return 0;
         }
@@ -717,8 +645,6 @@ transmit_start (void *cls, size_t size, void *buf)
     opt |= GNUNET_CORE_OPTION_SEND_CONNECT;
   if (h->disconnects != NULL)
     opt |= GNUNET_CORE_OPTION_SEND_DISCONNECT;
-  if (h->bfc != NULL)
-    opt |= GNUNET_CORE_OPTION_SEND_BFC;
   if (h->inbound_notify != NULL)
     {
       if (h->inbound_hdr_only)
@@ -737,7 +663,7 @@ transmit_start (void *cls, size_t size, void *buf)
   ts = (uint16_t *) & init[1];
   for (hpos = 0; hpos < h->hcnt; hpos++)
     ts[hpos] = htons (h->handlers[hpos].type);
-  GNUNET_CLIENT_receive (h->client,
+  GNUNET_CLIENT_receive (h->client_notifications,
                          &init_reply_handler,
                          h,
                          GNUNET_TIME_absolute_get_remaining
@@ -755,10 +681,9 @@ transmit_start (void *cls, size_t size, void *buf)
  * @param timeout after how long should we give up trying to connect to the core service?
  * @param cls closure for the various callbacks that follow (including handlers in the handlers array)
  * @param init callback to call on timeout or once we have successfully
- *        connected to the core service
+ *        connected to the core service; note that timeout is only meaningful if init is not NULL
  * @param connects function to call on peer connect, can be NULL
  * @param disconnects function to call on peer disconnect / timeout, can be NULL
- * @param bfc function to call to fill up spare bandwidth, can be NULL
  * @param inbound_notify function to call for all inbound messages, can be NULL
  * @param inbound_hdr_only set to GNUNET_YES if inbound_notify will only read the
  *                GNUNET_MessageHeader and hence we do not need to give it the full message;
@@ -768,16 +693,17 @@ transmit_start (void *cls, size_t size, void *buf)
  *                GNUNET_MessageHeader and hence we do not need to give it the full message
  *                can be used to improve efficiency, ignored if outbound_notify is NULLL
  * @param handlers callbacks for messages we care about, NULL-terminated
+ * @return handle to the core service (only useful for disconnect until 'init' is called);
+ *                NULL on error (in this case, init is never called)
  */
-void
+struct GNUNET_CORE_Handle *
 GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
-                     struct GNUNET_CONFIGURATION_Handle *cfg,
+                     const struct GNUNET_CONFIGURATION_Handle *cfg,
                      struct GNUNET_TIME_Relative timeout,
                      void *cls,
                      GNUNET_CORE_StartupCallback init,
-                     GNUNET_CORE_ClientEventHandler connects,
-                     GNUNET_CORE_ClientEventHandler disconnects,
-                     GNUNET_CORE_BufferFillCallback bfc,
+                     GNUNET_CORE_ConnectEventHandler connects,
+                     GNUNET_CORE_DisconnectEventHandler disconnects,
                      GNUNET_CORE_MessageCallback inbound_notify,
                      int inbound_hdr_only,
                      GNUNET_CORE_MessageCallback outbound_notify,
@@ -786,7 +712,6 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
 {
   struct GNUNET_CORE_Handle *h;
 
-  GNUNET_assert (init != NULL);
   h = GNUNET_malloc (sizeof (struct GNUNET_CORE_Handle));
   h->sched = sched;
   h->cfg = cfg;
@@ -794,13 +719,17 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
   h->init = init;
   h->connects = connects;
   h->disconnects = disconnects;
-  h->bfc = bfc;
   h->inbound_notify = inbound_notify;
   h->outbound_notify = outbound_notify;
   h->inbound_hdr_only = inbound_hdr_only;
   h->outbound_hdr_only = outbound_hdr_only;
   h->handlers = handlers;
-  h->client = GNUNET_CLIENT_connect (sched, "core", cfg);
+  h->client_notifications = GNUNET_CLIENT_connect (sched, "core", cfg);
+  if (h->client_notifications == NULL)
+    {
+      GNUNET_free (h);
+      return NULL;
+    }
   h->startup_timeout = GNUNET_TIME_relative_to_absolute (timeout);
   h->hcnt = 0;
   while (handlers[h->hcnt].callback != NULL)
@@ -814,10 +743,12 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
               timeout.value);
 #endif
   h->th =
-    GNUNET_CLIENT_notify_transmit_ready (h->client,
+    GNUNET_CLIENT_notify_transmit_ready (h->client_notifications,
                                          sizeof (struct InitMessage) +
                                          sizeof (uint16_t) * h->hcnt, timeout,
+                                        GNUNET_YES,
                                          &transmit_start, h);
+  return h;
 }
 
 
@@ -830,121 +761,18 @@ void
 GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle)
 {
   if (handle->th != NULL)
-    GNUNET_NETWORK_notify_transmit_ready_cancel (handle->th);
-  if (handle->reconnect_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
+    GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
+  if (handle->solicit_transmit_req != NULL)
+    GNUNET_CORE_notify_transmit_ready_cancel (handle->solicit_transmit_req);
+  if (handle->reconnect_task != GNUNET_SCHEDULER_NO_TASK)
     GNUNET_SCHEDULER_cancel (handle->sched, handle->reconnect_task);
-  GNUNET_CLIENT_disconnect (handle->client);
+  if (handle->client_notifications != NULL)
+    GNUNET_CLIENT_disconnect (handle->client_notifications, GNUNET_NO);
+  GNUNET_free_non_null (handle->solicit_buffer);
   GNUNET_free (handle);
 }
 
 
-/**
- * Build the configure message.
- */
-static size_t
-produce_configure_message (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_CORE_TransmitHandle *th = cls;
-  struct GNUNET_CORE_Handle *ch = th->ch;
-
-  if (buf == NULL)
-    {
-      /* communicate handle timeout/error! */
-      if (th->info != NULL)
-        th->info (th->info_cls, NULL, 0, 0, GNUNET_TIME_UNIT_ZERO, 0, 0.0);
-      if (th->timeout_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
-        GNUNET_CORE_notify_transmit_ready_cancel (th);
-      if (ch->submitted == th)
-        ch->submitted = NULL;
-      trigger_next_request (ch);
-      return 0;
-    }
-  GNUNET_assert (size >= sizeof (struct RequestConfigureMessage));
-  memcpy (buf, &th[1], sizeof (struct RequestConfigureMessage));
-  if (th->prev == NULL)
-    ch->pending_head = th->next;
-  else
-    th->prev->next = th->next;
-  if (th->next == NULL)
-    ch->pending_tail = th->prev;
-  else
-    th->next->prev = th->prev;
-  GNUNET_assert (ch->submitted == NULL);
-  ch->submitted = th;
-  return sizeof (struct RequestConfigureMessage);
-}
-
-
-/**
- * Obtain statistics and/or change preferences for the given peer.
- *
- * @param handle connection to core to use
- * @param peer identifies the peer
- * @param timeout after how long should we give up (and call "info" with NULL
- *                for "peer" to signal an error)?
- * @param bpm_out set to the current bandwidth limit (sending) for this peer,
- *                caller should set "bpm_out" to "-1" to avoid changing
- *                the current value; otherwise "bpm_out" will be lowered to
- *                the specified value; passing a pointer to "0" can be used to force
- *                us to disconnect from the peer; "bpm_out" might not increase
- *                as specified since the upper bound is generally
- *                determined by the other peer!
- * @param amount reserve N bytes for receiving, negative
- *                amounts can be used to undo a (recent) reservation;
- * @param preference increase incoming traffic share preference by this amount;
- *                in the absence of "amount" reservations, we use this
- *                preference value to assign proportional bandwidth shares
- *                to all connected peers
- * @param info function to call with the resulting configuration information
- * @param info_cls closure for info
- */
-void
-GNUNET_CORE_peer_configure (struct GNUNET_CORE_Handle *handle,
-                            const struct GNUNET_PeerIdentity *peer,
-                            struct GNUNET_TIME_Relative timeout,
-                            unsigned int bpm_out,
-                            int amount,
-                            unsigned long long preference,
-                            GNUNET_CORE_PeerConfigurationInfoCallback info,
-                            void *info_cls)
-{
-  struct RequestConfigureMessage *rcm;
-  struct GNUNET_CORE_TransmitHandle *th;
-
-  th = GNUNET_malloc (sizeof (struct GNUNET_CORE_TransmitHandle) +
-                      sizeof (struct RequestConfigureMessage));
-  /* append to list */
-  th->prev = handle->pending_tail;
-  if (handle->pending_tail == NULL)
-    handle->pending_head = th;
-  else
-    handle->pending_tail->next = th;
-  th->ch = handle;
-  th->get_message = &produce_configure_message;
-  th->get_message_cls = th;
-  th->info = info;
-  th->info_cls = info_cls;
-  th->timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  th->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->sched,
-                                                   GNUNET_NO,
-                                                   GNUNET_SCHEDULER_PRIORITY_KEEP,
-                                                   GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
-                                                   timeout,
-                                                   &timeout_request, th);
-  th->msize = sizeof (struct RequestConfigureMessage);
-  rcm = (struct RequestConfigureMessage *) &th[1];
-  rcm->header.size = htons (sizeof (struct RequestConfigureMessage));
-  rcm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONFIGURE);
-  rcm->reserved = htonl (0);
-  rcm->limit_outbound_bpm = htonl (bpm_out);
-  rcm->reserve_inbound = htonl (amount);
-  rcm->preference_change = GNUNET_htonll(preference);
-  rcm->peer = *peer;
-  if (handle->pending_head == th)
-    trigger_next_request (handle);
-}
-
-
 /**
  * Build the message requesting data transmission.
  */
@@ -955,20 +783,29 @@ produce_send (void *cls, size_t size, void *buf)
   struct GNUNET_CORE_Handle *h;
   struct SendMessage *sm;
   size_t dt;
-  GNUNET_NETWORK_TransmitReadyNotify notify;
+  GNUNET_CONNECTION_TransmitReadyNotify notify;
   void *notify_cls;
 
   h = th->ch;
   if (buf == NULL)
     {
       /* timeout or error */
+#if DEBUG_CORE
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "P2P transmission request for `%4s' timed out.\n",
+                 GNUNET_i2s(&th->peer));
+#endif
       GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL));
-      if (th->timeout_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
-        GNUNET_CORE_notify_transmit_ready_cancel (th);
+      GNUNET_CORE_notify_transmit_ready_cancel (th);
       trigger_next_request (h);
       return 0;
     }
-  GNUNET_assert (th->timeout_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK);
+#if DEBUG_CORE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Preparing for P2P transmission to `%4s'.\n",
+             GNUNET_i2s(&th->peer));
+#endif
+  GNUNET_assert (th->timeout_task != GNUNET_SCHEDULER_NO_TASK);
   sm = (struct SendMessage *) buf;
   sm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND);
   sm->priority = htonl (th->priority);
@@ -980,8 +817,24 @@ produce_send (void *cls, size_t size, void *buf)
   trigger_next_request (h);
   GNUNET_assert (size >= sizeof (struct SendMessage));
   dt = notify (notify_cls, size - sizeof (struct SendMessage), &sm[1]);
+  if (0 == dt)
+    {
+#if DEBUG_CORE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Size of clients message to peer %s is 0!\n",
+              GNUNET_i2s(&th->peer));
+#endif
+      /* client decided to send nothing! */
+      return 0;
+    }
+  GNUNET_assert (dt >= sizeof (struct GNUNET_MessageHeader));
+  if (dt + sizeof (struct SendMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+    {
+      GNUNET_break (0);
+      return 0;
+    }
   sm->header.size = htons (dt + sizeof (struct SendMessage));
-  GNUNET_assert (dt + sizeof (struct SendMessage) < size);
+  GNUNET_assert (dt + sizeof (struct SendMessage) <= size);
   return dt + sizeof (struct SendMessage);
 }
 
@@ -1010,7 +863,7 @@ GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle,
                                    struct GNUNET_TIME_Relative maxdelay,
                                    const struct GNUNET_PeerIdentity *target,
                                    size_t notify_size,
-                                   GNUNET_NETWORK_TransmitReadyNotify notify,
+                                   GNUNET_CONNECTION_TransmitReadyNotify notify,
                                    void *notify_cls)
 {
   struct GNUNET_CORE_TransmitHandle *th;
@@ -1032,17 +885,15 @@ GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle,
   th->peer = *target;
   th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
   th->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->sched,
-                                                   GNUNET_NO,
-                                                   GNUNET_SCHEDULER_PRIORITY_KEEP,
-                                                   GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
                                                    maxdelay,
                                                    &timeout_request, th);
   th->priority = priority;
   th->msize = sizeof (struct SendMessage) + notify_size;
   /* was the request queue previously empty? */
-  if (handle->pending_head == th)
+  if ( (handle->pending_head == th) &&
+       (handle->th == NULL) )
     trigger_next_request (handle);
-  return NULL;
+  return th;
 }
 
 
@@ -1072,7 +923,7 @@ GNUNET_CORE_notify_transmit_ready_cancel (struct GNUNET_CORE_TransmitHandle
       else
         h->next->prev = h->prev;
     }
-  if (h->timeout_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
+  if (h->timeout_task != GNUNET_SCHEDULER_NO_TASK)
     GNUNET_SCHEDULER_cancel (handle->sched, h->timeout_task);
   GNUNET_free (h);
 }