refactor DHT for new service API
[oweals/gnunet.git] / src / core / core_api.c
index 4c55d0e5f42c8b03308466d6c385d99ce71f2f90..67f17352ddfd9170f8117b04332fabd6b0d4c28a 100644 (file)
@@ -411,7 +411,7 @@ handle_init_reply (void *cls,
  */
 static void
 handle_connect_notify (void *cls,
-                       const struct ConnectNotifyMessage * cnm)
+                       const struct ConnectNotifyMessage *cnm)
 {
   struct GNUNET_CORE_Handle *h = cls;
   struct PeerRecord *pr;
@@ -541,11 +541,12 @@ handle_notify_inbound (void *cls,
   uint16_t et;
 
   GNUNET_break (GNUNET_NO == h->currently_down);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Received inbound message from `%s'.\n",
-       GNUNET_i2s (&ntm->peer));
   em = (const struct GNUNET_MessageHeader *) &ntm[1];
   et = ntohs (em->type);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received inbound message of type %d from `%s'.\n",
+       (int) et,
+       GNUNET_i2s (&ntm->peer));
   for (unsigned int hpos = 0; NULL != h->handlers[hpos].callback; hpos++)
   {
     const struct GNUNET_CORE_MessageHandler *mh;
@@ -674,6 +675,8 @@ handle_send_ready (void *cls,
   struct GNUNET_TIME_Relative delay;
   struct GNUNET_TIME_Relative overdue;
   unsigned int ret;
+  unsigned int priority;
+  int cork;
 
   GNUNET_break (GNUNET_NO == h->currently_down);
   pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
@@ -708,37 +711,51 @@ handle_send_ready (void *cls,
   sm->priority = htonl ((uint32_t) th->priority);
   sm->deadline = GNUNET_TIME_absolute_hton (th->deadline);
   sm->peer = pr->peer;
-  sm->cork = htonl ((uint32_t) th->cork);
+  sm->cork = htonl ((uint32_t) (cork = th->cork));
   sm->reserved = htonl (0);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Calling get_message with buffer of %u bytes\n",
-              (unsigned int) th->msize);
+              "Calling get_message with buffer of %u bytes (%s)\n",
+              (unsigned int) th->msize,
+             cork ? "corked" : "uncorked");
+  /* FIXME: this is ugly and a bit brutal, but "get_message"
+     may call GNUNET_CORE_notify_transmit_ready() which
+     may call GNUNET_MQ_send() as well, and we MUST get this
+     message out before the next SEND_REQUEST.  So we queue
+     it (even though incomplete) and then---relying on MQ being
+     nice and not actually touching 'env' until much later---
+     fill it afterwards.  This is horrible style, and once
+     the core_api abandons GNUNET_CORE_notify_transmit_ready
+     in favor of an MQ-style API, this hack should no longer
+     be required */
+  GNUNET_MQ_send (h->mq,
+                  env);
+  delay = GNUNET_TIME_absolute_get_duration (th->request_time);
+  overdue = GNUNET_TIME_absolute_get_duration (th->deadline);
+  priority = th->priority;
   ret = th->get_message (th->get_message_cls,
                          th->msize,
                          &sm[1]);
+  /* after this point, 'th' should not be used anymore, it
+     may now be about another message! */
   sm->header.size = htons (ret + sizeof (struct SendMessage));
-  delay = GNUNET_TIME_absolute_get_duration (th->request_time);
-  overdue = GNUNET_TIME_absolute_get_duration (th->deadline);
   if (overdue.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
     LOG (GNUNET_ERROR_TYPE_WARNING,
          "Transmitting overdue %u bytes to `%s' at priority %u with %s delay %s\n",
          ret,
          GNUNET_i2s (&pr->peer),
-         (unsigned int) th->priority,
+         priority,
          GNUNET_STRINGS_relative_time_to_string (delay,
                                                  GNUNET_YES),
-         (th->cork) ? " (corked)" : "");
+         (cork) ? " (corked)" : " (uncorked)");
   else
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Transmitting %u bytes to `%s' at priority %u with %s delay %s\n",
          ret,
          GNUNET_i2s (&pr->peer),
-         (unsigned int) th->priority,
+         priority,
          GNUNET_STRINGS_relative_time_to_string (delay,
                                                  GNUNET_YES),
-         (th->cork) ? " (corked)" : "");
-  GNUNET_MQ_send (h->mq,
-                  env);
+         (cork) ? " (corked)" : " (uncorked)");
 }
 
 
@@ -751,31 +768,31 @@ handle_send_ready (void *cls,
 static void
 reconnect (struct GNUNET_CORE_Handle *h)
 {
-  GNUNET_MQ_hd_fixed_size (init_reply,
-                           GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY,
-                           struct InitReplyMessage);
-  GNUNET_MQ_hd_fixed_size (connect_notify,
-                           GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT,
-                           struct ConnectNotifyMessage);
-  GNUNET_MQ_hd_fixed_size (disconnect_notify,
-                           GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT,
-                           struct DisconnectNotifyMessage);
-  GNUNET_MQ_hd_var_size (notify_inbound,
-                         GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND,
-                         struct NotifyTrafficMessage);
-  GNUNET_MQ_hd_var_size (notify_outbound,
-                         GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND,
-                         struct NotifyTrafficMessage);
-  GNUNET_MQ_hd_fixed_size (send_ready,
-                           GNUNET_MESSAGE_TYPE_CORE_SEND_READY,
-                           struct SendMessageReady);
- struct GNUNET_MQ_MessageHandler handlers[] = {
-    make_init_reply_handler (h),
-    make_connect_notify_handler (h),
-    make_disconnect_notify_handler (h),
-    make_notify_inbound_handler (h),
-    make_notify_outbound_handler (h),
-    make_send_ready_handler (h),
+  struct GNUNET_MQ_MessageHandler handlers[] = {
+    GNUNET_MQ_hd_fixed_size (init_reply,
+                             GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY,
+                             struct InitReplyMessage,
+                             h),
+    GNUNET_MQ_hd_fixed_size (connect_notify,
+                             GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT,
+                             struct ConnectNotifyMessage,
+                             h),
+    GNUNET_MQ_hd_fixed_size (disconnect_notify,
+                             GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT,
+                             struct DisconnectNotifyMessage,
+                             h),
+    GNUNET_MQ_hd_var_size (notify_inbound,
+                           GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND,
+                           struct NotifyTrafficMessage,
+                           h),
+    GNUNET_MQ_hd_var_size (notify_outbound,
+                           GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND,
+                           struct NotifyTrafficMessage,
+                           h),
+    GNUNET_MQ_hd_fixed_size (send_ready,
+                             GNUNET_MESSAGE_TYPE_CORE_SEND_READY,
+                             struct SendMessageReady,
+                             h),
     GNUNET_MQ_handler_end ()
   };
   struct InitMessage *init;
@@ -838,13 +855,13 @@ reconnect (struct GNUNET_CORE_Handle *h)
  * @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;
- *                can be used to improve efficiency, ignored if @a inbound_notify is NULLL
+ *                can be used to improve efficiency, ignored if @a inbound_notify is NULL
  * @param outbound_notify function to call for all outbound messages, can be NULL
  * @param outbound_hdr_only set to #GNUNET_YES if outbound_notify will only read the
  *                GNUNET_MessageHeader and hence we do not need to give it the full message
- *                can be used to improve efficiency, ignored if @a outbound_notify is NULLL
+ *                can be used to improve efficiency, ignored if @a outbound_notify is NULL
  * @param handlers callbacks for messages we care about, NULL-terminated
- * @return handle to the core service (only useful for disconnect until 'init' is called);
+ * @return handle to the core service (only useful for disconnect until @a init is called);
  *                NULL on error (in this case, init is never called)
  */
 struct GNUNET_CORE_Handle *
@@ -881,7 +898,7 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
   h->handlers = GNUNET_new_array (hcnt + 1,
                                   struct GNUNET_CORE_MessageHandler);
   if (NULL != handlers)
-    memcpy (h->handlers,
+    GNUNET_memcpy (h->handlers,
             handlers,
             hcnt * sizeof (struct GNUNET_CORE_MessageHandler));
   h->hcnt = hcnt;
@@ -985,9 +1002,10 @@ GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle,
     return NULL;
   }
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Asking core for transmission of %u bytes to `%s'\n",
+       "Asking core for transmission of %u bytes to `%s'%s\n",
        (unsigned int) notify_size,
-       GNUNET_i2s (target));
+       GNUNET_i2s (target),
+       cork ? " (corked)" : "");
   pr = GNUNET_CONTAINER_multipeermap_get (handle->peers,
                                           target);
   if (NULL == pr)
@@ -1017,6 +1035,8 @@ GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle,
   th->priority = priority;
   th->msize = notify_size;
   th->cork = cork;
+  if (NULL == handle->mq)
+    return th; /* see #4588 (hack until we transition core fully to MQ) */
   env = GNUNET_MQ_msg (smr,
                        GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST);
   smr->priority = htonl ((uint32_t) th->priority);