- doc
[oweals/gnunet.git] / src / mesh / gnunet-service-mesh.c
index c8c66e089769bc59ca368a4a616ab54841248bca..7ebe7d199d188696f36268b002a872fa3a1b1ae1 100644 (file)
@@ -3599,6 +3599,7 @@ tunnel_get_children_fwd_ack (struct MeshTunnel *t)
   ctx.t = t;
   ctx.max_child_ack = 0;
   ctx.nchildren = 0;
+  ctx.init = GNUNET_NO;
   tree_iterate_children (t->tree, tunnel_get_child_fwd_ack, &ctx);
 
   if (0 == ctx.nchildren)
@@ -4167,14 +4168,17 @@ tunnel_destroy (struct MeshTunnel *t)
     r = GNUNET_SYSERR;
   }
 
-  GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
-  if (NULL != c &&
-      GNUNET_YES !=
-      GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels, &hash, t))
+  if (NULL != c)
   {
-    GNUNET_break (0);
-    r = GNUNET_SYSERR;
+    GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
+    if (GNUNET_YES !=
+        GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels, &hash, t))
+    {
+      GNUNET_break (0);
+      r = GNUNET_SYSERR;
+    }
   }
+
   GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
   for (i = 0; i < t->nclients; i++)
   {
@@ -4196,6 +4200,7 @@ tunnel_destroy (struct MeshTunnel *t)
       r = GNUNET_SYSERR;
     }
   }
+
   if (t->nclients > 0)
   {
     if (GNUNET_YES !=
@@ -4206,6 +4211,7 @@ tunnel_destroy (struct MeshTunnel *t)
     }
     GNUNET_free (t->clients);
   }
+
   if (NULL != t->peers)
   {
     GNUNET_CONTAINER_multihashmap_iterate (t->peers, &peer_info_delete_tunnel,
@@ -4335,8 +4341,10 @@ tunnel_delete_peer (struct MeshTunnel *t, GNUNET_PEER_Id peer)
  * @param cls closure (client that is disconnecting)
  * @param key the hash of the local tunnel id (used to access the hashmap)
  * @param value the value stored at the key (tunnel to destroy)
+ *
+ * @return GNUNET_OK, keep iterating.
  */
-static void
+static int
 tunnel_destroy_iterator (void *cls, const struct GNUNET_HashCode * key, void *value)
 {
   struct MeshTunnel *t = value;
@@ -4354,6 +4362,8 @@ tunnel_destroy_iterator (void *cls, const struct GNUNET_HashCode * key, void *va
   tunnel_send_destroy(t);
   t->owner = NULL;
   t->destroy = GNUNET_YES;
+
+  return GNUNET_OK;
 }
 
 
@@ -4442,6 +4452,7 @@ send_core_path_create (void *cls, size_t size, void *buf)
   if (GNUNET_YES == t->nobuffer)
     opt |= MESH_TUNNEL_OPT_NOBUFFER;
   msg->opt = htonl(opt);
+  msg->reserved = 0;
 
   peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
   for (i = 0; i < p->length; i++)
@@ -4563,24 +4574,32 @@ queue_destroy (struct MeshPeerQueue *queue, int clear_cls)
 {
   struct MeshTransmissionDescriptor *dd;
   struct MeshPathInfo *path_info;
+  struct MeshTunnelChildInfo *cinfo;
+  struct GNUNET_PeerIdentity id;
+  unsigned int i;
+  unsigned int max;
 
   if (GNUNET_YES == clear_cls)
   {
     switch (queue->type)
     {
-    case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-    case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
-    case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   type payload\n");
+      case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "   cancelling TUNNEL_DESTROY\n");
+        /* fall through */
+      case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
+      case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
+      case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "   type prebuilt (payload, tunnel destroy)\n");
         dd = queue->cls;
         data_descriptor_decrement_rc (dd->mesh_data);
         break;
-    case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
+      case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   type create path\n");
         path_info = queue->cls;
         path_destroy (path_info->path);
         break;
-    default:
+      default:
         GNUNET_break (0);
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                     "   type %s unknown!\n",
@@ -4591,6 +4610,36 @@ queue_destroy (struct MeshPeerQueue *queue, int clear_cls)
   GNUNET_CONTAINER_DLL_remove (queue->peer->queue_head,
                                queue->peer->queue_tail,
                                queue);
+
+  /* Delete from child_fc in the appropiate tunnel */
+  max = queue->tunnel->fwd_queue_max;
+  GNUNET_PEER_resolve (queue->peer->id, &id);
+  cinfo = tunnel_get_neighbor_fc (queue->tunnel, &id);
+  for (i = 0; i < cinfo->send_buffer_n; i++)
+  {
+    unsigned int i2;
+    i2 = (cinfo->send_buffer_start + i) % max;
+    if (cinfo->send_buffer[i2] == queue)
+    {
+      /* Found corresponding entry in the send_buffer. Move all others back. */
+      unsigned int j;
+      unsigned int j2;
+      unsigned int j3;
+
+      for (j = i, j2 = 0, j3 = 0; j < cinfo->send_buffer_n - 1; j++)
+      {
+        j2 = (cinfo->send_buffer_start + j) % max;
+        j3 = (cinfo->send_buffer_start + j + 1) % max;
+        cinfo->send_buffer[j2] = cinfo->send_buffer[j3];
+      }
+
+      cinfo->send_buffer[j3] = NULL;
+
+      cinfo->send_buffer_n--;
+    }
+  }
+  //queue->
+
   GNUNET_free (queue);
 }
 
@@ -7723,13 +7772,15 @@ core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
   while (NULL != q)
   {
       n = q->next;
-      if (q->peer == pi)
-      {
-        /* try to reroute this traffic instead */
-        queue_destroy(q, GNUNET_YES);
-      }
+      /* TODO try to reroute this traffic instead */
+      queue_destroy(q, GNUNET_YES);
       q = n;
   }
+  if (NULL != pi->core_transmit)
+  {
+    GNUNET_CORE_notify_transmit_ready_cancel(pi->core_transmit);
+    pi->core_transmit = NULL;
+  }
   peer_info_remove_path (pi, pi->id, myid);
   if (myid == pi->id)
   {