- add framework for mesh2 mutipeer tests
[oweals/gnunet.git] / src / mesh / gnunet-service-mesh-new.c
index e1bc42a6718863c19715f349e3f77e5504dac86e..3e64003f9a2453510550480423ea0bbb707a9e05 100644 (file)
@@ -937,6 +937,7 @@ send_client_tunnel_create (struct MeshTunnel *t)
   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
   msg.tunnel_id = htonl (t->local_tid_dest);
   msg.port = htonl (t->port);
+  GNUNET_PEER_resolve (t->id.oid, &msg.peer);
   GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
                                               &msg.header, GNUNET_NO);
 }
@@ -1500,6 +1501,30 @@ peer_info_add_path_to_origin (struct MeshPeerInfo *peer_info,
 }
 
 
+
+/**
+ * Remove a tunnel from the list of tunnels a peer participates in.
+ * 
+ * @param p Peer to clean.
+ * @param t Tunnel to remove.
+ */
+static void
+peer_info_remove_tunnel (struct MeshPeerInfo *p, struct MeshTunnel *t)
+{
+  unsigned int i;
+
+  for (i = 0; i < p->ntunnels; i++)
+  {
+    if (p->tunnels[i] == t)
+    {
+      p->tunnels[i] = p->tunnels[p->ntunnels - 1];
+      GNUNET_array_grow (p->tunnels, p->ntunnels, p->ntunnels - 1);
+      return;
+    }
+  }
+}
+
+
 /**
  * Function called if the connection to the peer has been stalled for a while,
  * possibly due to a missed ACK. Poll the peer about its ACK status.
@@ -1765,11 +1790,6 @@ tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c)
     GNUNET_break(0);
     return;
   }
-  if (0 != t->next_hop)
-  {
-    GNUNET_break(0);
-    return;
-  }
   GMC_hash32 (t->local_tid_dest, &hash);
   if (GNUNET_OK !=
       GNUNET_CONTAINER_multihashmap_put (c->incoming_tunnels, &hash, t,
@@ -1945,6 +1965,7 @@ tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type)
     case GNUNET_MESSAGE_TYPE_MESH_ACK:
     case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
       break;
+    case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
     case GNUNET_MESSAGE_TYPE_MESH_POLL:
       t->force_ack = GNUNET_YES;
       break;
@@ -2052,6 +2073,72 @@ tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type)
 }
 
 
+/**
+ * Modify the unicast message TID from global to local and send to client.
+ * 
+ * @param t Tunnel on which to send the message.
+ * @param msg Message to modify and send.
+ */
+static void
+tunnel_send_client_ucast (struct MeshTunnel *t,
+                          const struct GNUNET_MESH_Unicast *msg)
+{
+  struct GNUNET_MESH_Unicast *copy;
+  uint16_t size = ntohs (msg->header.size);
+  char cbuf[size];
+
+  if (size < sizeof (struct GNUNET_MESH_Unicast) +
+             sizeof (struct GNUNET_MessageHeader))
+  {
+    GNUNET_break_op (0);
+    return;
+  }
+  if (NULL == t->client)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  copy = (struct GNUNET_MESH_Unicast *) cbuf;
+  memcpy (copy, msg, size);
+  copy->tid = htonl (t->local_tid_dest);
+  GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
+                                              &copy->header, GNUNET_NO);
+}
+
+
+/**
+ * Modify the to_origin  message TID from global to local and send to client.
+ * 
+ * @param t Tunnel on which to send the message.
+ * @param msg Message to modify and send.
+ */
+static void
+tunnel_send_client_to_orig (struct MeshTunnel *t,
+                            const struct GNUNET_MESH_ToOrigin *msg)
+{
+  struct GNUNET_MESH_ToOrigin *copy;
+  uint16_t size = ntohs (msg->header.size);
+  char cbuf[size];
+
+  if (size < sizeof (struct GNUNET_MESH_ToOrigin) +
+             sizeof (struct GNUNET_MessageHeader))
+  {
+    GNUNET_break_op (0);
+    return;
+  }
+  if (NULL == t->owner)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  copy = (struct GNUNET_MESH_ToOrigin *) cbuf;
+  memcpy (cbuf, msg, size);
+  copy->tid = htonl (t->local_tid);
+  GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
+                                              &copy->header, GNUNET_NO);
+}
+
+
 /**
  * @brief Re-initiate traffic to this peer if necessary.
  *
@@ -2118,7 +2205,7 @@ tunnel_send_destroy (struct MeshTunnel *t)
               "  sending tunnel destroy for tunnel: %s [%X]\n",
               GNUNET_i2s (&msg.oid), t->id.tid);
 
-  if (NULL == t->client)
+  if (NULL == t->client && 0 != t->next_hop)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  child: %u\n", t->next_hop);
     GNUNET_PEER_resolve (t->next_hop, &id);
@@ -2127,7 +2214,7 @@ tunnel_send_destroy (struct MeshTunnel *t)
                 GNUNET_i2s (&id));
     send_prebuilt_message (&msg.header, t->next_hop, t);
   }
-  if (NULL == t->owner)
+  if (NULL == t->owner && 0 != t->prev_hop)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  parent: %u\n", t->prev_hop);
     GNUNET_PEER_resolve (t->prev_hop, &id);
@@ -2152,6 +2239,8 @@ peer_cancel_queues (GNUNET_PEER_Id neighbor, struct MeshTunnel *t)
   struct MeshPeerQueue *pq;
   struct MeshPeerQueue *next;
 
+  if (0 == neighbor)
+    return; /* Was local peer, 0'ed in tunnel_destroy_iterator */
   peer_info = peer_get_short (neighbor);
   for (pq = peer_info->queue_head; NULL != pq; pq = next)
   {
@@ -2252,6 +2341,7 @@ tunnel_destroy (struct MeshTunnel *t)
 
   n_tunnels--;
   GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO);
+  path_destroy (t->path);
   GNUNET_free (t);
   return r;
 }
@@ -2397,11 +2487,16 @@ tunnel_destroy_iterator (void *cls,
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Client %u is destination.\n", c->id);
     t->client = NULL;
+    t->next_hop = 0;
   }
   else if (c == t->owner)
   {
+    struct MeshPeerInfo *p;
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Client %u is owner.\n", c->id);
     t->owner = NULL;
+    t->prev_hop = 0;
+    p = peer_get_short(t->dest);
+    peer_info_remove_tunnel (p, t);
   }
   else
   {
@@ -3150,6 +3245,7 @@ handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
       peer_info->dhtget = NULL;
     }
     tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
+    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
     return GNUNET_OK;
   }
 
@@ -3319,16 +3415,11 @@ handle_mesh_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
   tunnel_reset_timeout (t);
   if (t->dest == myid)
   {
-    if (NULL == t->client)
-    {
-      GNUNET_break (0);
-      return GNUNET_OK;
-    }
+    /* TODO signature verification */
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "  it's for us! sending to clients...\n");
     GNUNET_STATISTICS_update (stats, "# unicast received", 1, GNUNET_NO);
-    GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
-                                                message, GNUNET_NO);
+    tunnel_send_client_ucast (t, msg);
     tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST);
     return GNUNET_OK;
   }
@@ -3423,20 +3514,13 @@ handle_mesh_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               " pid %u not seen yet, forwarding\n", pid);
 
-  if (NULL != t->owner)
+  if (myid == t->id.oid)
   {
-    char cbuf[size];
-    struct GNUNET_MESH_ToOrigin *copy;
-
+    /* TODO signature verification */
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "  it's for us! sending to clients...\n");
-    /* TODO signature verification */
-    memcpy (cbuf, message, size);
-    copy = (struct GNUNET_MESH_ToOrigin *) cbuf;
-    copy->tid = htonl (t->local_tid);
     GNUNET_STATISTICS_update (stats, "# to origin received", 1, GNUNET_NO);
-    GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
-                                                &copy->header, GNUNET_NO);
+    tunnel_send_client_to_orig (t, msg);
     tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
     return GNUNET_OK;
   }