- Remove deprecated code, coverity 10236
[oweals/gnunet.git] / src / mesh / gnunet-service-mesh.c
index d633c477f9e332781f54edfab265f2ec9f7446e1..fa392901cb838d11d1cf48d536c21a91c5104aa1 100644 (file)
@@ -512,6 +512,22 @@ struct MeshTunnelChildInfo
      * Last ACK sent to that child (BCK ACK).
      */
   uint32_t bck_ack;
+
+    /**
+     * Circular buffer pointing to MeshPeerQueue elements.
+     * Size determined by the tunnel queue size.
+     */
+  struct MeshPeerQueue **send_buffer;
+
+    /**
+     * Index of the oldest element in the send_buffer.
+     */
+  unsigned int send_buffer_start;
+
+    /**
+     * How many elements are already in the buffer.
+     */
+  unsigned int send_buffer_n;
 };
 
 
@@ -3061,7 +3077,22 @@ tunnel_destroy_child (void *cls,
                       const struct GNUNET_HashCode * key,
                       void *value)
 {
-  GNUNET_free (value);
+  struct MeshTunnelChildInfo *cinfo = value;
+  struct MeshTunnel *t = cls;
+  unsigned int c;
+  unsigned int i;
+
+  for (c = 0; c < cinfo->send_buffer_n; c++)
+  {
+    i = (cinfo->send_buffer_start + c) % t->fwd_queue_max;
+    if (NULL != cinfo->send_buffer[i])
+      queue_destroy(cinfo->send_buffer[i], GNUNET_YES);
+    else
+      GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u %u\n", c, cinfo->send_buffer_n);
+  }
+  GNUNET_free_non_null (cinfo->send_buffer);
+  GNUNET_free (cinfo);
   return GNUNET_YES;
 }
 
@@ -3346,7 +3377,6 @@ tunnel_send_multicast (struct MeshTunnel *t,
   tree_iterate_children (t->tree, &tunnel_send_multicast_iterator, mdata);
   if (*(mdata->reference_counter) == 0)
   {
-    GNUNET_break (0);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "  no one to send data to\n");
     GNUNET_free (mdata->data);
@@ -3427,6 +3457,9 @@ tunnel_get_neighbor_fc (const struct MeshTunnel *t,
     cinfo->fwd_ack = t->fwd_pid + delta;
     cinfo->bck_ack = delta;
 
+    cinfo->send_buffer =
+        GNUNET_malloc (sizeof(struct MeshPeerQueue *) * t->fwd_queue_max);
+
     GNUNET_assert (GNUNET_OK ==
       GNUNET_CONTAINER_multihashmap_put (t->children_fc,
                                          &peer->hashPubKey,
@@ -3624,7 +3657,7 @@ tunnel_get_fwd_ack (struct MeshTunnel *t)
   if (-1 == child_ack)
   {
     // Node has no children, child_ack AND core buffer are irrelevant.
-    GNUNET_break (-1 != client_ack); // No children AND no clients? Not good! // FIXME fc
+    GNUNET_break (-1 != client_ack); // No children AND no clients? Not good!
     return (uint32_t) client_ack;
   }
 
@@ -4538,6 +4571,11 @@ queue_get_next (const struct MeshPeerInfo *peer)
         break;
       case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
         mcast = (struct GNUNET_MESH_Multicast *) info->mesh_data->data;
+        if (GNUNET_MESSAGE_TYPE_MESH_MULTICAST != ntohs(mcast->header.type)) 
+        {
+          // Not a multicast payload: multicast control traffic (destroy, etc)
+          return q;
+        }
         pid = ntohl (mcast->pid);
         GNUNET_PEER_resolve (info->peer->id, &id);
         cinfo = tunnel_get_neighbor_fc(t, &id);
@@ -4585,6 +4623,8 @@ queue_send (void *cls, size_t size, void *buf)
     struct GNUNET_MessageHeader *msg;
     struct MeshPeerQueue *queue;
     struct MeshTunnel *t;
+    struct MeshTunnelChildInfo *cinfo;
+    struct GNUNET_PeerIdentity dst_id;
     size_t data_size;
 
     peer->core_transmit = NULL;
@@ -4602,20 +4642,20 @@ queue_send (void *cls, size_t size, void *buf)
     }
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   not empty\n");
 
+    GNUNET_PEER_resolve (peer->id, &dst_id);
     /* Check if buffer size is enough for the message */
     if (queue->size > size)
     {
-        struct GNUNET_PeerIdentity id;
+
 
         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                     "*********   not enough room, reissue\n");
-        GNUNET_PEER_resolve (peer->id, &id);
         peer->core_transmit =
             GNUNET_CORE_notify_transmit_ready(core_handle,
                                               0,
                                               0,
                                               GNUNET_TIME_UNIT_FOREVER_REL,
-                                              &id,
+                                              &dst_id,
                                               queue->size,
                                               &queue_send,
                                               peer);
@@ -4686,6 +4726,30 @@ queue_send (void *cls, size_t size, void *buf)
                     queue->type);
         data_size = 0;
     }
+    switch (queue->type)
+    {
+      case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
+      case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
+      case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
+        cinfo = tunnel_get_neighbor_fc(t, &dst_id);
+        if (cinfo->send_buffer[cinfo->send_buffer_start] != queue)
+        {
+          GNUNET_break(0);
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "at pos %u (%p) != %p\n",
+                      cinfo->send_buffer_start,
+                      cinfo->send_buffer[cinfo->send_buffer_start],
+                      queue);
+        }
+        GNUNET_break(cinfo->send_buffer_n > 0);
+        cinfo->send_buffer[cinfo->send_buffer_start] = NULL;
+        cinfo->send_buffer_n--;
+        cinfo->send_buffer_start++;
+        cinfo->send_buffer_start %= t->fwd_queue_max;
+        break;
+      default:
+        break;
+    }
 
     /* Free queue, but cls was freed by send_core_* */
     queue_destroy (queue, GNUNET_NO);
@@ -4732,8 +4796,11 @@ queue_add (void *cls, uint16_t type, size_t size,
            struct MeshPeerInfo *dst, struct MeshTunnel *t)
 {
   struct MeshPeerQueue *queue;
+  struct MeshTunnelChildInfo *cinfo;
+  struct GNUNET_PeerIdentity id;
   unsigned int *max;
   unsigned int *n;
+  unsigned int i;
 
   n = NULL;
   if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type ||
@@ -4754,6 +4821,8 @@ queue_add (void *cls, uint16_t type, size_t size,
         GNUNET_break_op(0);       // TODO: kill connection?
       else
         GNUNET_break(0);
+      GNUNET_STATISTICS_update(stats, "# messages dropped (buffer full)",
+                               1, GNUNET_NO);
       return;                       // Drop message
     }
     (*n)++;
@@ -4765,11 +4834,9 @@ queue_add (void *cls, uint16_t type, size_t size,
   queue->peer = dst;
   queue->tunnel = t;
   GNUNET_CONTAINER_DLL_insert_tail (dst->queue_head, dst->queue_tail, queue);
+  GNUNET_PEER_resolve (dst->id, &id);
   if (NULL == dst->core_transmit)
   {
-      struct GNUNET_PeerIdentity id;
-
-      GNUNET_PEER_resolve (dst->id, &id);
       dst->core_transmit =
           GNUNET_CORE_notify_transmit_ready(core_handle,
                                             0,
@@ -4780,6 +4847,27 @@ queue_add (void *cls, uint16_t type, size_t size,
                                             &queue_send,
                                             dst);
   }
+  if (NULL == n) // Is this internal mesh traffic?
+    return;
+
+  // It's payload, keep track of buffer per peer.
+  cinfo = tunnel_get_neighbor_fc(t, &id);
+  i = (cinfo->send_buffer_start + cinfo->send_buffer_n) % t->fwd_queue_max;
+  if (NULL != cinfo->send_buffer[i])
+  {
+    GNUNET_break (cinfo->send_buffer_n == t->fwd_queue_max); // aka i == start
+    queue_destroy(cinfo->send_buffer[cinfo->send_buffer_start], GNUNET_YES);
+    cinfo->send_buffer_start++;
+    cinfo->send_buffer_start %= t->fwd_queue_max;
+    cinfo->send_buffer_n--;
+  }
+  cinfo->send_buffer[i] = queue;
+  cinfo->send_buffer_n++;
+  if (cinfo->send_buffer_n > t->fwd_queue_max)
+  {
+    GNUNET_break (0);
+    cinfo->send_buffer_n = t->fwd_queue_max;
+  }
 }
 
 
@@ -7319,7 +7407,7 @@ handle_local_ack (void *cls, struct GNUNET_SERVER_Client *client,
   t = tunnel_get_by_local_id (c, tid);
   if (NULL == t)
   {
-    GNUNET_break (0); // FIXME fc
+    GNUNET_break (0);
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tunnel %X unknown.\n", tid);
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "  for client %u.\n", c->id);
     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);