i am a dumb dummy
[oweals/gnunet.git] / src / core / core_api.c
index 02c9e43a291699b022c2179af4d8f2746a5dfc8f..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,6 +460,7 @@ static void
 reconnect_later (struct GNUNET_CORE_Handle *h)
 {
   struct ControlMessage *cm;
+  struct PeerRecord *pr;
 
   while (NULL != (cm = h->pending_head))
     {
@@ -479,13 +477,16 @@ reconnect_later (struct GNUNET_CORE_Handle *h)
     {
       GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
       h->client = NULL;
-      /* FIXME: is this right? GNUNET_CLIENT_disconnect frees all outstanding transmission handles, so h->cth is invalid! */
-      /* Otherwise a subsequent call to GNUNET_CORE_disconnect tries to cancel this task!!! */
       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);
@@ -589,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");
@@ -666,12 +679,7 @@ transmit_message (void *cls,
   /* now check for 'ready' P2P messages */
   if (NULL != (pr = h->ready_peer_head))
     {
-      /* FIXME: If a reconnect_later call happened, this can be NULL! */
-      if (pr->pending_head == NULL)
-        {
-          GNUNET_break(0);
-          return 0;
-        }
+      GNUNET_assert (pr->pending_head != NULL);
       th = pr->pending_head;
       if (size < th->msize + sizeof (struct SendMessage))
        {
@@ -771,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
     {
@@ -817,6 +825,7 @@ main_notify_handler (void *cls,
   int trigger;
   uint16_t msize;
   uint16_t et;
+  uint32_t ats_count;
 
   if (msg == NULL)
     {
@@ -874,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",
@@ -913,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))
@@ -957,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);
@@ -972,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",
@@ -990,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);
@@ -1010,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",
@@ -1027,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);
@@ -1047,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;
@@ -1055,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);
@@ -1075,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)
@@ -1090,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);
@@ -1102,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))
@@ -1133,11 +1174,10 @@ main_notify_handler (void *cls,
                  "Received notification about transmission readiness to `%s'.\n",
                  GNUNET_i2s (&smr->peer));
 #endif
-      /* FIXME: pr->pending_head is sometimes NULL here... Safe to just return?  Or does this indicate something is out of sync somewhere else? */
       if (pr->pending_head == NULL)
         {
-          GNUNET_break (0);
-          reconnect_later (h);
+         /* request must have been cancelled between the original request
+            and the response from core, ignore core's readiness */
           return;
         }
 
@@ -1486,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)
@@ -1588,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,