- begin work on enhanced multipart receiving
[oweals/gnunet.git] / src / mesh / gnunet-service-mesh_connection.c
index 9806bf674b55f8539d7d9b8b78452bbf00087086..04f1e07c4c0849254d1f725ceb80f09be36733b1 100644 (file)
@@ -179,7 +179,8 @@ struct MeshConnection
   enum MeshConnectionState state;
 
   /**
-   * Path being used for the tunnel.
+   * Path being used for the tunnel. At the origin of the connection
+   * it's a pointer to the destination's path pool, otherwise just a copy.
    */
   struct MeshPeerPath *path;
 
@@ -638,7 +639,6 @@ get_prev_hop (const struct MeshConnection *c)
 {
   GNUNET_PEER_Id id;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Get prev hop, own pos %u\n", c->own_pos);
   if (0 == c->own_pos || c->path->length < 2)
     id = c->path->peers[0];
   else
@@ -1149,13 +1149,13 @@ register_neighbors (struct MeshConnection *c)
       || GNUNET_NO == GMP_is_neighbor (prev_peer))
   {
     if (GMC_is_origin (c, GNUNET_YES))
-      GNUNET_break (0);
-    else
-      GNUNET_break_op (0);
+    GNUNET_STATISTICS_update (stats, "# local bad paths", 1, GNUNET_NO);
+    GNUNET_STATISTICS_update (stats, "# bad paths", 1, GNUNET_NO);
+
     LOG (GNUNET_ERROR_TYPE_DEBUG, "  register neighbors failed\n");
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  prev: %s, %d\n",
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  prev: %s, neighbor: %d\n",
          GMP_2s (prev_peer), GMP_is_neighbor (prev_peer));
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  next: %s, %d\n",
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  next: %s, neighbor: %d\n",
          GMP_2s (next_peer), GMP_is_neighbor (next_peer));
     return GNUNET_SYSERR;
   }
@@ -1178,11 +1178,18 @@ unregister_neighbors (struct MeshConnection *c)
   struct MeshPeer *peer;
 
   peer = get_next_hop (c);
-  GMP_remove_connection (peer, c);
+  if (GNUNET_OK != GMP_remove_connection (peer, c))
+  {
+    GNUNET_break (MESH_CONNECTION_NEW == c->state);
+    LOG (GNUNET_ERROR_TYPE_ERROR, "  cstate: %u\n", c->state);
+  }
 
   peer = get_prev_hop (c);
-  GMP_remove_connection (peer, c);
-
+  if (GNUNET_OK != GMP_remove_connection (peer, c))
+  {
+    GNUNET_break (MESH_CONNECTION_NEW == c->state);
+    LOG (GNUNET_ERROR_TYPE_ERROR, "  cstate: %u\n", c->state);
+  }
 }
 
 
@@ -1291,7 +1298,7 @@ GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
     }
     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Own position: %u\n", own_pos);
     GMP_add_path_to_all (path, GNUNET_NO);
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "  Creating connection\n");
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  Creating connection\n");
     c = GMC_new (cid, NULL, path_duplicate (path), own_pos);
     if (NULL == c)
     {
@@ -1570,7 +1577,7 @@ GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG, "!  directly destroying connection!\n");
     GMC_destroy (c);
-    return;
+    return GNUNET_OK;
   }
   c->destroy = GNUNET_YES;
   c->state = MESH_CONNECTION_DESTROYED;
@@ -1740,7 +1747,7 @@ handle_mesh_kx (const struct GNUNET_PeerIdentity *peer,
   type = ntohs (msg->header.type);
   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
   LOG (GNUNET_ERROR_TYPE_DEBUG, "got a %s message from %s\n",
-              GM_m2s (type), GNUNET_i2s (peer));
+       GM_m2s (type), GNUNET_i2s (peer));
 
   /* Check connection */
   c = connection_get (&msg->cid);
@@ -1750,6 +1757,7 @@ handle_mesh_kx (const struct GNUNET_PeerIdentity *peer,
     LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING connection unknown\n");
     return GNUNET_OK;
   }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " on connection %s\n", GMC_2s (c));
 
   /* Check if origin is as expected */
   neighbor = get_prev_hop (c);
@@ -2203,22 +2211,31 @@ GMC_new (const struct GNUNET_HashCode *cid,
 
   c = GNUNET_new (struct MeshConnection);
   c->id = *cid;
-  GNUNET_CONTAINER_multihashmap_put (connections, &c->id, c,
-                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONTAINER_multihashmap_put (connections,
+                                                    &c->id, c,
+                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
   fc_init (&c->fwd_fc);
   fc_init (&c->bck_fc);
   c->fwd_fc.c = c;
   c->bck_fc.c = c;
 
   c->t = t;
-  if (own_pos > p->length - 1)
+  GNUNET_assert (own_pos <= p->length - 1);
+  c->own_pos = own_pos;
+  c->path = p;
+
+  if (GNUNET_OK != register_neighbors (c))
   {
-    GNUNET_break (0);
+    if (0 == own_pos)
+    {
+      GMT_remove_path (c->t, p);
+      c->t = NULL;
+      c->path = NULL;
+    }
     GMC_destroy (c);
     return NULL;
   }
-  c->own_pos = own_pos;
-  c->path = p;
 
   if (0 == own_pos)
   {
@@ -2226,11 +2243,6 @@ GMC_new (const struct GNUNET_HashCode *cid,
       GNUNET_SCHEDULER_add_delayed (create_connection_time,
                                     &connection_fwd_keepalive, c);
   }
-  if (GNUNET_OK != register_neighbors (c))
-  {
-    GMC_destroy (c);
-    return NULL;
-  }
 
   return c;
 }
@@ -2240,7 +2252,10 @@ void
 GMC_destroy (struct MeshConnection *c)
 {
   if (NULL == c)
+  {
+    GNUNET_break (0);
     return;
+  }
 
   if (2 == c->destroy) /* cancel queues -> GMP_queue_cancel -> q_destroy -> */
     return;            /* -> message_sent -> GMC_destroy. Don't loop. */
@@ -2253,8 +2268,12 @@ GMC_destroy (struct MeshConnection *c)
        c->fwd_fc.poll_task, c->bck_fc.poll_task);
 
   /* Cancel all traffic */
-  connection_cancel_queues (c, GNUNET_YES);
-  connection_cancel_queues (c, GNUNET_NO);
+  if (NULL != c->path)
+  {
+    connection_cancel_queues (c, GNUNET_YES);
+    connection_cancel_queues (c, GNUNET_NO);
+    unregister_neighbors (c);
+  }
 
   LOG (GNUNET_ERROR_TYPE_DEBUG, " fc tasks f: %u, b: %u\n",
        c->fwd_fc.poll_task, c->bck_fc.poll_task);
@@ -2271,15 +2290,11 @@ GMC_destroy (struct MeshConnection *c)
     LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL msg BCK canceled\n");
   }
 
-  /* Unregister from neighbors */
-  unregister_neighbors (c);
-
-  /* Delete */
-  GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO);
+  /* Delete from tunnel */
   if (NULL != c->t)
     GMT_remove_connection (c->t, c);
 
-  if (GNUNET_NO == GMC_is_origin (c, GNUNET_YES))
+  if (GNUNET_NO == GMC_is_origin (c, GNUNET_YES) && NULL != c->path)
     path_destroy (c->path);
   if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task)
     GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
@@ -2299,6 +2314,7 @@ GMC_destroy (struct MeshConnection *c)
   GNUNET_break (GNUNET_YES ==
                 GNUNET_CONTAINER_multihashmap_remove (connections, &c->id, c));
 
+  GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO);
   GNUNET_free (c);
 }
 
@@ -2564,7 +2580,7 @@ GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
   memcpy (data, message, size);
   type = ntohs (message->type);
   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send %s (%u bytes) on connection %s\n",
-              GM_m2s (type), size, GMC_2s (c));
+       GM_m2s (type), size, GMC_2s (c));
 
   fc = fwd ? &c->fwd_fc : &c->bck_fc;
   droppable = GNUNET_NO == force;