i am a dumb dummy
[oweals/gnunet.git] / src / core / core_api.c
index 802ba56d4b7cea235213bf0224cf78de298bac45..21622852b441633e1d002b7ca34451d80a0e80a0 100644 (file)
@@ -23,9 +23,6 @@
  * @brief core service; this is the main API for encrypted P2P
  *        communications
  * @author Christian Grothoff
- *
- * TODO:
- * - implement atsi parsing and passing
  */
 #include "platform.h"
 #include "gnunet_constants.h"
@@ -463,23 +460,33 @@ static void
 reconnect_later (struct GNUNET_CORE_Handle *h)
 {
   struct ControlMessage *cm;
+  struct PeerRecord *pr;
 
   while (NULL != (cm = h->pending_head))
     {
       GNUNET_CONTAINER_DLL_remove (h->pending_head,
                                   h->pending_tail,
-                                  cm);      
-      cm->cont (cm->cont_cls, NULL);
+                                  cm);
+      if (cm->th != NULL)
+       cm->th->cm = NULL; 
+      if (cm->cont != NULL)
+       cm->cont (cm->cont_cls, NULL);
       GNUNET_free (cm);
     }
   if (h->client != NULL)
     {
       GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
       h->client = NULL;
+      h->cth = NULL;
       GNUNET_CONTAINER_multihashmap_iterate (h->peers,
                                             &disconnect_and_free_peer_entry,
                                             h);
     }
+  while (NULL != (pr = h->ready_peer_head))    
+    GNUNET_CONTAINER_DLL_remove (h->ready_peer_head,
+                                h->ready_peer_tail,
+                                pr);
+  
   GNUNET_assert (h->pending_head == NULL);
   h->currently_down = GNUNET_YES;
   GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK);
@@ -516,22 +523,6 @@ transmission_timeout (void *cls,
                      const struct GNUNET_SCHEDULER_TaskContext *tc);
 
 
-/**
- * Control message was sent, mark it as such.
- *
- * @param cls the 'struct GNUNET_CORE_TransmitHandle*'
- * @param tc scheduler context
- */
-static void
-mark_control_message_sent (void *cls,
-                          const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_CORE_TransmitHandle *th = cls;
-
-  th->cm = NULL;
-}
-
-
 /**
  * Send a control message to the peer asking for transmission
  * of the message in the given peer record.
@@ -563,8 +554,6 @@ request_next_transmission (struct PeerRecord *pr)
                                                   pr);
   cm = GNUNET_malloc (sizeof (struct ControlMessage) + 
                      sizeof (struct SendMessageRequest));
-  cm->cont = &mark_control_message_sent;
-  cm->cont_cls = th;
   th->cm = cm;
   cm->th = th;
   smr = (struct SendMessageRequest*) &cm[1];
@@ -601,14 +590,26 @@ transmission_timeout (void *cls,
                      const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct PeerRecord *pr = cls;
+  struct GNUNET_CORE_Handle *h = pr->ch;
   struct GNUNET_CORE_TransmitHandle *th;
-
+  
   pr->timeout_task = GNUNET_SCHEDULER_NO_TASK;
   th = pr->pending_head;
   GNUNET_CONTAINER_DLL_remove (pr->pending_head,
                                pr->pending_tail,
                                th);
   pr->queue_size--;
+  if ( (pr->prev != NULL) ||
+       (pr->next != NULL) ||
+       (pr == h->ready_peer_head) )
+    {
+      /* the request that was 'approved' by core was
+        canceled before it could be transmitted; remove
+        us from the 'ready' list */
+      GNUNET_CONTAINER_DLL_remove (h->ready_peer_head,
+                                  h->ready_peer_tail,
+                                  pr);
+    }
 #if DEBUG_CORE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Signalling timeout of request for transmission to CORE service\n");
@@ -678,6 +679,7 @@ transmit_message (void *cls,
   /* now check for 'ready' P2P messages */
   if (NULL != (pr = h->ready_peer_head))
     {
+      GNUNET_assert (pr->pending_head != NULL);
       th = pr->pending_head;
       if (size < th->msize + sizeof (struct SendMessage))
        {
@@ -777,7 +779,7 @@ trigger_next_request (struct GNUNET_CORE_Handle *h,
     }
   if (h->pending_head != NULL)
     msize = ntohs (((struct GNUNET_MessageHeader*) &h->pending_head[1])->size);    
-  else if (h->ready_peer_head != NULL)
+  else if (h->ready_peer_head != NULL) 
     msize = h->ready_peer_head->pending_head->msize + sizeof (struct SendMessage);    
   else
     {
@@ -823,6 +825,7 @@ main_notify_handler (void *cls,
   int trigger;
   uint16_t msize;
   uint16_t et;
+  uint32_t ats_count;
 
   if (msg == NULL)
     {
@@ -880,13 +883,21 @@ main_notify_handler (void *cls,
        }
       break;
     case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT:
-      if (msize != sizeof (struct ConnectNotifyMessage))
+      if (msize < sizeof (struct ConnectNotifyMessage))
         {
           GNUNET_break (0);
          reconnect_later (h);
          return;
         }
       cnm = (const struct ConnectNotifyMessage *) msg;
+      ats_count = ntohl (cnm->ats_count);
+      if ( (msize != sizeof (struct ConnectNotifyMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)) ||
+          (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR != ntohl ((&cnm->ats)[ats_count].type)) )
+        {
+          GNUNET_break (0);
+         reconnect_later (h);
+         return;
+        }
 #if DEBUG_CORE
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                  "Received notification about connection from `%s'.\n",
@@ -919,7 +930,7 @@ main_notify_handler (void *cls,
       if (NULL != h->connects)
        h->connects (h->cls,
                     &cnm->peer,
-                    NULL /* FIXME: atsi! */);
+                    &cnm->ats);
       break;
     case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT:
       if (msize != sizeof (struct DisconnectNotifyMessage))
@@ -963,7 +974,7 @@ main_notify_handler (void *cls,
           GNUNET_break (0);
           break;
         }
-      if (msize != sizeof (struct PeerStatusNotifyMessage))
+      if (msize < sizeof (struct PeerStatusNotifyMessage))
         {
           GNUNET_break (0);
          reconnect_later (h);
@@ -978,6 +989,14 @@ main_notify_handler (void *cls,
          GNUNET_break (0);
          return;
        }
+      ats_count = ntohl (psnm->ats_count);
+      if ( (msize != sizeof (struct PeerStatusNotifyMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)) ||
+          (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR != ntohl ((&psnm->ats)[ats_count].type)) )
+        {
+          GNUNET_break (0);
+         reconnect_later (h);
+         return;
+        }
 #if DEBUG_CORE
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                  "Received notification about status change by `%s'.\n",
@@ -996,12 +1015,10 @@ main_notify_handler (void *cls,
                        psnm->bandwidth_in,
                        psnm->bandwidth_out,
                        GNUNET_TIME_absolute_ntoh (psnm->timeout),
-                       NULL /* FIXME: atsi */);
+                       &psnm->ats);
       break;
     case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND:
-      if (msize <
-          sizeof (struct NotifyTrafficMessage) +
-          sizeof (struct GNUNET_MessageHeader))
+      if (msize < sizeof (struct NotifyTrafficMessage))
         {
           GNUNET_break (0);
          reconnect_later (h);
@@ -1016,7 +1033,16 @@ main_notify_handler (void *cls,
          GNUNET_break (0);
          return;
        }
-      em = (const struct GNUNET_MessageHeader *) &ntm[1];
+      ats_count = ntohl (ntm->ats_count);
+      if ( (msize < sizeof (struct NotifyTrafficMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)
+           + sizeof (struct GNUNET_MessageHeader)) ||
+          (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR != ntohl ((&ntm->ats)[ats_count].type)) )
+        {
+          GNUNET_break (0);
+         reconnect_later (h);
+         return;
+        }
+      em = (const struct GNUNET_MessageHeader *) &(&ntm->ats)[ats_count+1];
 #if DEBUG_CORE
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "Received message of type %u and size %u from peer `%4s'\n",
@@ -1033,7 +1059,8 @@ main_notify_handler (void *cls,
          return;
        }
       if ((GNUNET_NO == h->inbound_hdr_only) &&
-          (msize != ntohs (em->size) + sizeof (struct NotifyTrafficMessage)))
+          (msize != ntohs (em->size) + sizeof (struct NotifyTrafficMessage) + 
+          + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)) )
         {
           GNUNET_break (0);
          reconnect_later (h);
@@ -1053,7 +1080,7 @@ main_notify_handler (void *cls,
             }
           if (GNUNET_OK !=
               h->handlers[hpos].callback (h->cls, &ntm->peer, em,
-                                         NULL /* FIXME: atsi */))
+                                         &ntm->ats))
             {
               /* error in processing, do not process other messages! */
               break;
@@ -1061,12 +1088,10 @@ main_notify_handler (void *cls,
         }
       if (NULL != h->inbound_notify)
         h->inbound_notify (h->cls, &ntm->peer, em,
-                          NULL /* FIXME: atsi */);
+                          &ntm->ats);
       break;
     case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND:
-      if (msize <
-          sizeof (struct NotifyTrafficMessage) +
-          sizeof (struct GNUNET_MessageHeader))
+      if (msize < sizeof (struct NotifyTrafficMessage))
         {
           GNUNET_break (0);
          reconnect_later (h);
@@ -1081,7 +1106,16 @@ main_notify_handler (void *cls,
          GNUNET_break (0);
          return;
        }
-      em = (const struct GNUNET_MessageHeader *) &ntm[1];
+      ats_count = ntohl (ntm->ats_count);
+      if ( (msize < sizeof (struct NotifyTrafficMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)
+           + sizeof (struct GNUNET_MessageHeader)) ||
+          (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR != ntohl ((&ntm->ats)[ats_count].type)) )
+        {
+          GNUNET_break (0);
+         reconnect_later (h);
+         return;
+        }
+      em = (const struct GNUNET_MessageHeader *) &(&ntm->ats)[ats_count+1];
       pr = GNUNET_CONTAINER_multihashmap_get (h->peers,
                                              &ntm->peer.hashPubKey);
       if (pr == NULL)
@@ -1096,7 +1130,8 @@ main_notify_handler (void *cls,
                  GNUNET_i2s (&ntm->peer));
 #endif
       if ((GNUNET_NO == h->outbound_hdr_only) &&
-          (msize != ntohs (em->size) + sizeof (struct NotifyTrafficMessage)))
+          (msize != ntohs (em->size) + sizeof (struct NotifyTrafficMessage) + 
+          + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)) )
         {
           GNUNET_break (0);
          reconnect_later (h);
@@ -1108,7 +1143,7 @@ main_notify_handler (void *cls,
           break;
         }
       h->outbound_notify (h->cls, &ntm->peer, em,
-                         NULL /* FIXME: atsi? */);
+                         &ntm->ats);
       break;
     case GNUNET_MESSAGE_TYPE_CORE_SEND_READY:
       if (msize != sizeof (struct SendMessageReady))
@@ -1139,6 +1174,13 @@ main_notify_handler (void *cls,
                  "Received notification about transmission readiness to `%s'.\n",
                  GNUNET_i2s (&smr->peer));
 #endif
+      if (pr->pending_head == NULL)
+        {
+         /* request must have been cancelled between the original request
+            and the response from core, ignore core's readiness */
+          return;
+        }
+
       th = pr->pending_head;
       if (ntohs (smr->smr_id) != th->smr_id)
        {
@@ -1380,7 +1422,7 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
 /**
  * Disconnect from the core service.  This function can only 
  * be called *after* all pending 'GNUNET_CORE_notify_transmit_ready'
- * requests have been explicitly cancelled.
+ * requests have been explicitly canceled.
  *
  * @param handle connection to core to disconnect
  */
@@ -1415,7 +1457,8 @@ GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle)
                                   cm);
       if (cm->th != NULL)
        cm->th->cm = NULL;
-      cm->cont (cm->cont_cls, NULL);
+      if (cm->cont != NULL)
+       cm->cont (cm->cont_cls, NULL);
       GNUNET_free (cm);
     }
   GNUNET_CONTAINER_multihashmap_iterate (handle->peers,
@@ -1483,9 +1526,9 @@ GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle,
   /* bound queue size */
   if (pr->queue_size == handle->queue_size)
     {
-      /* find lowest-priority entry */
-      minp = pr->pending_head;
-      prev = minp->next;
+      /* find lowest-priority entry, but skip the head of the list */
+      minp = pr->pending_head->next;
+      prev = minp;
       while (prev != NULL)
        {
          if (prev->priority < minp->priority)
@@ -1585,7 +1628,7 @@ GNUNET_CORE_notify_transmit_ready_cancel (struct GNUNET_CORE_TransmitHandle
           (pr == h->ready_peer_head) )
        {
          /* the request that was 'approved' by core was
-            cancelled before it could be transmitted; remove
+            canceled before it could be transmitted; remove
             us from the 'ready' list */
          GNUNET_CONTAINER_DLL_remove (h->ready_peer_head,
                                       h->ready_peer_tail,