i am a dumb dummy
[oweals/gnunet.git] / src / core / gnunet-service-core.c
index e6f0a1eed59bb6bd8ae99f92186fa13b3517c5cf..76e26cc8f962ef02022ae18c26cb473c865e7a37 100644 (file)
@@ -1001,7 +1001,10 @@ send_to_all_clients (const struct GNUNET_MessageHeader *msg,
 static void
 handle_peer_status_change (struct Neighbour *n)
 {
-  struct PeerStatusNotifyMessage psnm;
+  struct PeerStatusNotifyMessage *psnm;
+  char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
+  struct GNUNET_TRANSPORT_ATS_Information *ats;
+  size_t size;
 
   if ( (! n->is_connected) ||
        (n->status != PEER_STATE_KEY_CONFIRMED) )
@@ -1011,16 +1014,33 @@ handle_peer_status_change (struct Neighbour *n)
               "Peer `%4s' changed status\n",
              GNUNET_i2s (&n->peer));
 #endif
-  psnm.header.size = htons (sizeof (struct PeerStatusNotifyMessage));
-  psnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE);
-  psnm.ats_count = htonl (0);
-  psnm.ats.type = htonl (0);
-  psnm.ats.value = htonl (0);
-  psnm.timeout = GNUNET_TIME_absolute_hton (get_neighbour_timeout (n));
-  psnm.bandwidth_in = n->bw_in;
-  psnm.bandwidth_out = n->bw_out;
-  psnm.peer = n->peer;
-  send_to_all_clients (&psnm.header, 
+  size = sizeof (struct PeerStatusNotifyMessage) +
+    n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+  if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+    {
+      GNUNET_break (0);
+      /* recovery strategy: throw away performance data */
+      GNUNET_array_grow (n->ats,
+                        n->ats_count,
+                        0);
+      size = sizeof (struct PeerStatusNotifyMessage) +
+       n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+    }
+  psnm = (struct PeerStatusNotifyMessage*) buf;
+  psnm->header.size = htons (size);
+  psnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE);
+  psnm->timeout = GNUNET_TIME_absolute_hton (get_neighbour_timeout (n));
+  psnm->bandwidth_in = n->bw_in;
+  psnm->bandwidth_out = n->bw_out;
+  psnm->peer = n->peer;
+  psnm->ats_count = htonl (n->ats_count);
+  ats = &psnm->ats;
+  memcpy (ats,
+         n->ats,
+         n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
+  ats[n->ats_count].type = htonl (0);
+  ats[n->ats_count].value = htonl (0);
+  send_to_all_clients (&psnm->header, 
                       GNUNET_YES, 
                       GNUNET_CORE_OPTION_SEND_STATUS_CHANGE);
   GNUNET_STATISTICS_update (stats, 
@@ -1188,7 +1208,10 @@ handle_client_init (void *cls,
   const uint16_t *types;
   uint16_t *wtypes;
   struct Neighbour *n;
-  struct ConnectNotifyMessage cnm;
+  struct ConnectNotifyMessage *cnm;
+  char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
+  struct GNUNET_TRANSPORT_ATS_Information *ats;
+  size_t size;
   unsigned int i;
 
 #if DEBUG_CORE_CLIENT
@@ -1250,22 +1273,39 @@ handle_client_init (void *cls,
   if (0 != (c->options & GNUNET_CORE_OPTION_SEND_CONNECT))
     {
       /* notify new client about existing neighbours */
-      cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
-      cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
-      cnm.ats_count = htonl (0);
-      cnm.ats.type = htonl (0);
-      cnm.ats.value = htonl (0);
       n = neighbours;
       while (n != NULL)
        {
+         size = sizeof (struct ConnectNotifyMessage) +
+           (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+         if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+           {
+             GNUNET_break (0);
+             /* recovery strategy: throw away performance data */
+             GNUNET_array_grow (n->ats,
+                                n->ats_count,
+                                0);
+             size = sizeof (struct ConnectNotifyMessage) +
+               (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+           }
+         cnm = (struct ConnectNotifyMessage*) buf;       
+         cnm->header.size = htons (size);
+         cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
+         cnm->ats_count = htonl (n->ats_count);
+         ats = &cnm->ats;
+         memcpy (ats,
+                 n->ats,
+                 sizeof (struct GNUNET_TRANSPORT_ATS_Information) * n->ats_count);
+         ats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
+         ats[n->ats_count].value = htonl (0);
          if (n->status == PEER_STATE_KEY_CONFIRMED)
            {
 #if DEBUG_CORE_CLIENT
              GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                          "Sending `%s' message to client.\n", "NOTIFY_CONNECT");
 #endif
-             cnm.peer = n->peer;
-             send_to_client (c, &cnm.header, GNUNET_NO);
+             cnm->peer = n->peer;
+             send_to_client (c, &cnm->header, GNUNET_NO);
            }
          n = n->next;
        }
@@ -1351,6 +1391,10 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
 
 /**
  * Handle CORE_ITERATE_PEERS request.
+ *
+ * @param cls unused
+ * @param client client sending the iteration request
+ * @param message iteration request message
  */
 static void
 handle_client_iterate_peers (void *cls,
@@ -1359,33 +1403,56 @@ handle_client_iterate_peers (void *cls,
 
 {
   struct Neighbour *n;
-  struct ConnectNotifyMessage cnm;
+  struct ConnectNotifyMessage *cnm;
   struct GNUNET_MessageHeader done_msg;
   struct GNUNET_SERVER_TransmitContext *tc;
+  char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
+  struct GNUNET_TRANSPORT_ATS_Information *ats;
+  size_t size;
 
   /* notify new client about existing neighbours */
-  cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
-  cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
-  done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
-  done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
   tc = GNUNET_SERVER_transmit_context_create (client);
+  cnm = (struct ConnectNotifyMessage*) buf;
   n = neighbours;
-  cnm.ats_count = htonl (0);
-  cnm.ats.type = htonl (0);
-  cnm.ats.value = htonl (0);
   while (n != NULL)
     {
       if (n->status == PEER_STATE_KEY_CONFIRMED)
         {
+         size = sizeof (struct ConnectNotifyMessage) +
+           (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+         if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+           {
+             GNUNET_break (0);
+             /* recovery strategy: throw away performance data */
+             GNUNET_array_grow (n->ats,
+                                n->ats_count,
+                                0);
+             size = sizeof (struct PeerStatusNotifyMessage) +
+               n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+           }
+         cnm = (struct ConnectNotifyMessage*) buf;
+         cnm->header.size = htons (size);
+         cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
+         cnm->ats_count = htonl (n->ats_count);
+         ats = &cnm->ats;
+         memcpy (ats,
+                 n->ats,
+                 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
+         ats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
+         ats[n->ats_count].value = htonl (0);    
 #if DEBUG_CORE_CLIENT
           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                      "Sending `%s' message to client.\n", "NOTIFY_CONNECT");
+                      "Sending `%s' message to client.\n",
+                     "NOTIFY_CONNECT");
 #endif
-          cnm.peer = n->peer;
-          GNUNET_SERVER_transmit_context_append_message (tc, &cnm.header);
+          cnm->peer = n->peer;
+          GNUNET_SERVER_transmit_context_append_message (tc, 
+                                                        &cnm->header);
         }
       n = n->next;
     }
+  done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
+  done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END);
   GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
   GNUNET_SERVER_transmit_context_run (tc,
                                       GNUNET_TIME_UNIT_FOREVER_REL);
@@ -3229,9 +3296,9 @@ update_neighbour_performance (struct Neighbour *n,
 
   if (ats_count == 0)
     return;
-  for (i=0;i<ats_count;i++)
+  for (i = 0; i < ats_count; i++)
     {
-      for (j=0;j<n->ats_count;j++)
+      for (j=0;j < n->ats_count; j++)
        {
          if (n->ats[j].type == ats[i].type)
            {
@@ -3239,10 +3306,12 @@ update_neighbour_performance (struct Neighbour *n,
              break;
            }
        }
-      if (j == n->ats_count)   
-       GNUNET_array_append (n->ats,
-                            n->ats_count,
-                            *ats);     
+      if (j == n->ats_count)
+        {
+          GNUNET_array_append (n->ats,
+                               n->ats_count,
+                               ats[i]);
+        }
     }
 }
 
@@ -3359,8 +3428,11 @@ handle_pong (struct Neighbour *n,
             uint32_t ats_count)
 {
   struct PongMessage t;
-  struct ConnectNotifyMessage cnm;
+  struct ConnectNotifyMessage *cnm;
   struct GNUNET_CRYPTO_AesInitializationVector iv;
+  char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
+  struct GNUNET_TRANSPORT_ATS_Information *mats;
+  size_t size;
 
 #if DEBUG_CORE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -3454,13 +3526,33 @@ handle_pong (struct Neighbour *n,
           GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
           n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
         }      
-      cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
-      cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
-      cnm.ats_count = htonl (0);
-      cnm.peer = n->peer;
-      cnm.ats.type = htonl (0);
-      cnm.ats.value = htonl (0);
-      send_to_all_clients (&cnm.header, GNUNET_NO, GNUNET_CORE_OPTION_SEND_CONNECT);
+      update_neighbour_performance (n, ats, ats_count);      
+      size = sizeof (struct ConnectNotifyMessage) +
+       (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+      if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+       {
+         GNUNET_break (0);
+         /* recovery strategy: throw away performance data */
+         GNUNET_array_grow (n->ats,
+                            n->ats_count,
+                            0);
+         size = sizeof (struct PeerStatusNotifyMessage) +
+           n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+       }
+      cnm = (struct ConnectNotifyMessage*) buf;
+      cnm->header.size = htons (size);
+      cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
+      cnm->ats_count = htonl (n->ats_count);
+      cnm->peer = n->peer;
+      mats = &cnm->ats;
+      memcpy (mats,
+             n->ats,
+             n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
+      mats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
+      mats[n->ats_count].value = htonl (0);      
+      send_to_all_clients (&cnm->header, 
+                          GNUNET_NO, 
+                          GNUNET_CORE_OPTION_SEND_CONNECT);
       process_encrypted_neighbour_queue (n);
       /* fall-through! */
     case PEER_STATE_KEY_CONFIRMED:
@@ -3471,7 +3563,6 @@ handle_pong (struct Neighbour *n,
        = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
                                        &send_keep_alive,
                                        n);
-      update_neighbour_performance (n, ats, ats_count);
       handle_peer_status_change (n);
       break;
     default:
@@ -3673,9 +3764,22 @@ send_p2p_message_to_client (struct Neighbour *sender,
                             struct Client *client,
                             const void *m, size_t msize)
 {
-  char buf[msize + sizeof (struct NotifyTrafficMessage)];
+  size_t size = msize + sizeof (struct NotifyTrafficMessage) +
+    (sender->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+  char buf[size];
   struct NotifyTrafficMessage *ntm;
+  struct GNUNET_TRANSPORT_ATS_Information *ats;
 
+  if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+    {
+      GNUNET_break (0);
+      /* recovery strategy: throw performance data away... */
+      GNUNET_array_grow (sender->ats,
+                        sender->ats_count,
+                        0);
+      size = msize + sizeof (struct NotifyTrafficMessage) +
+       (sender->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+    }
 #if DEBUG_CORE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Core service passes message from `%4s' of type %u to client.\n",
@@ -3683,13 +3787,19 @@ send_p2p_message_to_client (struct Neighbour *sender,
               (unsigned int) ntohs (((const struct GNUNET_MessageHeader *) m)->type));
 #endif
   ntm = (struct NotifyTrafficMessage *) buf;
-  ntm->header.size = htons (msize + sizeof (struct NotifyTrafficMessage));
+  ntm->header.size = htons (size);
   ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND);
-  ntm->ats_count = htonl (0);
-  ntm->ats.type = htonl (0);
-  ntm->ats.value = htonl (0);
+  ntm->ats_count = htonl (sender->ats_count);
   ntm->peer = sender->peer;
-  memcpy (&ntm[1], m, msize);
+  ats = &ntm->ats;
+  memcpy (ats,
+         sender->ats,
+         sizeof (struct GNUNET_TRANSPORT_ATS_Information) * sender->ats_count);
+  ats[sender->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
+  ats[sender->ats_count].value = htonl (0);  
+  memcpy (&ats[sender->ats_count+1],
+         m, 
+         msize);
   send_to_client (client, &ntm->header, GNUNET_YES);
 }
 
@@ -4300,11 +4410,14 @@ handle_transport_notify_disconnect (void *cls,
       cnm.peer = *peer;
       send_to_all_clients (&cnm.header, GNUNET_NO, GNUNET_CORE_OPTION_SEND_DISCONNECT);
     }
-  if (NULL != n->th)
+
+  /* On transport disconnect transport doesn't cancel requests, so must do so here. */
+  if (n->th != NULL)
     {
-      GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
-      n->th = NULL;
+      GNUNET_TRANSPORT_notify_transmit_ready_cancel(n->th);
     }
+  n->th = NULL;
+
   n->is_connected = GNUNET_NO;
   n->status = PEER_STATE_DOWN;
   while (NULL != (car = n->active_client_request_head))