REST/NAMESTORE: rework API
[oweals/gnunet.git] / src / cadet / gnunet-service-cadet_core.c
index 99957d8a11af09ee2b8697fab7243c54beff568b..879230d297b22353c6985b109567af25ecf41e65 100644 (file)
@@ -2,20 +2,20 @@
      This file is part of GNUnet.
      Copyright (C) 2017 GNUnet e.V.
 
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
+     SPDX-License-Identifier: AGPL3.0-or-later
 */
 
 /**
@@ -406,6 +406,28 @@ route_message (struct CadetPeer *prev,
        (NULL != dir->env_head) )
     discard_buffer (dir,
                     dir->env_head);
+  /* Check for duplicates */
+  for (const struct GNUNET_MQ_Envelope *env = dir->env_head;
+       NULL != env;
+       env = GNUNET_MQ_env_next (env))
+  {
+    const struct GNUNET_MessageHeader *hdr = GNUNET_MQ_env_get_msg (env);
+
+    if ( (hdr->size == msg->size) &&
+         (0 == memcmp (hdr,
+                       msg,
+                       ntohs (msg->size))) )
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "Received duplicate of message already in buffer, dropping\n");
+      GNUNET_STATISTICS_update (stats,
+                                "# messages dropped due to duplicate in buffer",
+                                1,
+                                GNUNET_NO);
+      return;
+    }
+  }
+
   rung = dir->rung;
   if (cur_buffers == max_buffers)
   {
@@ -434,7 +456,7 @@ route_message (struct CadetPeer *prev,
   GNUNET_CONTAINER_DLL_remove (rung->rd_head,
                                rung->rd_tail,
                                dir);
-  /* make 'nxt' point to the next higher rung, creat if necessary */
+  /* make 'nxt' point to the next higher rung, create if necessary */
   nxt = rung->next;
   if ( (NULL == nxt) ||
        (rung->rung_off + 1 != nxt->rung_off) )
@@ -623,7 +645,7 @@ timeout_cb (void *cls)
   {
     exp = GNUNET_TIME_absolute_add (r->last_use,
                                     linger);
-    if (0 != GNUNET_TIME_absolute_get_duration (exp).rel_value_us)
+    if (0 != GNUNET_TIME_absolute_get_remaining (exp).rel_value_us)
     {
       /* Route not yet timed out, wait until it does. */
       timeout_task = GNUNET_SCHEDULER_add_at (exp,
@@ -631,6 +653,11 @@ timeout_cb (void *cls)
                                               NULL);
       return;
     }
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+               "Sending BROKEN due to timeout (%s was last use, %s linger)\n",
+               GNUNET_STRINGS_absolute_time_to_string (r->last_use),
+               GNUNET_STRINGS_relative_time_to_string (linger,
+                                                       GNUNET_YES));
     send_broken (&r->prev,
                  &r->cid,
                  NULL,
@@ -688,6 +715,8 @@ dir_ready_cb (void *cls,
     return;
   }
   odir = (dir == &route->next) ? &route->prev : &route->next;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Sending BROKEN due to MQ going down\n");
   send_broken (&route->next,
                &route->cid,
                GCP_get_id (odir->hop),
@@ -774,40 +803,53 @@ handle_connection_create (void *cls,
   if (0 == path_length)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
-      "Dropping CADET_CONNECTION_CREATE with empty path\n");
+         "Dropping CADET_CONNECTION_CREATE with empty path\n");
     GNUNET_break_op (0);
     return;
   }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Handling CADET_CONNECTION_CREATE from %s for CID %s with %u hops\n",
+       GCP_2s (sender),
+       GNUNET_sh2s (&msg->cid.connection_of_tunnel),
+       path_length);
   /* Check for loops */
-  struct GNUNET_CONTAINER_MultiPeerMap *map;
-  map = GNUNET_CONTAINER_multipeermap_create (path_length * 2,
-                                              GNUNET_YES);
-  GNUNET_assert (NULL != map);
-  for (off = 0; off < path_length; off++) {
-    if (GNUNET_SYSERR ==
-        GNUNET_CONTAINER_multipeermap_put (map,
-                                           &pids[off],
-                                           NULL,
-                                           GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) {
-      /* bogus request */
-      GNUNET_CONTAINER_multipeermap_destroy (map);
+  {
+    struct GNUNET_CONTAINER_MultiPeerMap *map;
+
+    map = GNUNET_CONTAINER_multipeermap_create (path_length * 2,
+                                                GNUNET_YES);
+    GNUNET_assert (NULL != map);
+    for (unsigned int i=0;i<path_length;i++)
+    {
       LOG (GNUNET_ERROR_TYPE_DEBUG,
-        "Dropping CADET_CONNECTION_CREATE with cyclic path\n");
-      GNUNET_break_op (0);
-      return;
+           "CADET_CONNECTION_CREATE has peer %s at offset %u\n",
+           GNUNET_i2s (&pids[i]),
+           i);
+      if (GNUNET_SYSERR ==
+          GNUNET_CONTAINER_multipeermap_put (map,
+                                             &pids[i],
+                                             NULL,
+                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
+      {
+        /* bogus request */
+        GNUNET_CONTAINER_multipeermap_destroy (map);
+        LOG (GNUNET_ERROR_TYPE_DEBUG,
+             "Dropping CADET_CONNECTION_CREATE with cyclic path\n");
+        GNUNET_break_op (0);
+        return;
+      }
     }
+    GNUNET_CONTAINER_multipeermap_destroy (map);
   }
-  GNUNET_CONTAINER_multipeermap_destroy (map);
-  /* Initiator is at offset 0. */
+  /* Initiator is at offset 0, find us */
   for (off=1;off<path_length;off++)
-    if (0 == memcmp (&my_full_id,
-                     &pids[off],
-                     sizeof (struct GNUNET_PeerIdentity)))
+    if (0 == GNUNET_memcmp (&my_full_id,
+                     &pids[off]))
       break;
   if (off == path_length)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
-      "Dropping CADET_CONNECTION_CREATE without us in the path\n");
+         "Dropping CADET_CONNECTION_CREATE without us in the path\n");
     GNUNET_break_op (0);
     return;
   }
@@ -816,14 +858,15 @@ handle_connection_create (void *cls,
                          GNUNET_NO))
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
-      "Dropping CADET_CONNECTION_CREATE without sender in the path\n");
+         "Dropping CADET_CONNECTION_CREATE without sender at previous hop in the path\n");
     GNUNET_break_op (0);
     return;
   }
   if (NULL !=
-      get_route (&msg->cid))
+      (route = get_route (&msg->cid)))
   {
     /* Duplicate CREATE, pass it on, previous one might have been lost! */
+
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n",
          GNUNET_sh2s (&msg->cid.connection_of_tunnel));
@@ -852,7 +895,7 @@ handle_connection_create (void *cls,
     origin = GCP_get (&pids[0],
                       GNUNET_YES);
     LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Received CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
+         "I am destination for CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
          GCP_2s (origin),
          GNUNET_sh2s (&msg->cid.connection_of_tunnel));
     path = GCPP_get_path_from_route (path_length - 1,
@@ -942,6 +985,10 @@ handle_connection_create (void *cls,
                                                                                 3),
                                                  &timeout_cb,
                                                  NULL);
+  /* also pass CREATE message along to next hop */
+  route_message (sender,
+                 &msg->cid,
+                 &msg->header);
 }
 
 
@@ -963,7 +1010,9 @@ handle_connection_create_ack (void *cls,
   if (NULL != cc)
   {
     /* verify ACK came from the right direction */
-    struct CadetPeerPath *path = GCC_get_path (cc);
+    unsigned int len;
+    struct CadetPeerPath *path = GCC_get_path (cc,
+                                               &len);
 
     if (peer !=
         GCPP_get_peer_at_offset (path,
@@ -1007,7 +1056,9 @@ handle_connection_broken (void *cls,
   if (NULL != cc)
   {
     /* verify message came from the right direction */
-    struct CadetPeerPath *path = GCC_get_path (cc);
+    unsigned int len;
+    struct CadetPeerPath *path = GCC_get_path (cc,
+                                               &len);
 
     if (peer !=
         GCPP_get_peer_at_offset (path,
@@ -1056,7 +1107,9 @@ handle_connection_destroy (void *cls,
   if (NULL != cc)
   {
     /* verify message came from the right direction */
-    struct CadetPeerPath *path = GCC_get_path (cc);
+    unsigned int len;
+    struct CadetPeerPath *path = GCC_get_path (cc,
+                                               &len);
 
     if (peer !=
         GCPP_get_peer_at_offset (path,
@@ -1101,11 +1154,19 @@ handle_tunnel_kx (void *cls,
   struct CadetConnection *cc;
 
   /* First, check if message belongs to a connection that ends here. */
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Routing KX with ephemeral %s on CID %s\n",
+       GNUNET_e2s (&msg->ephemeral_key),
+       GNUNET_sh2s (&msg->cid.connection_of_tunnel));
+
+
   cc = GCC_lookup (&msg->cid);
   if (NULL != cc)
   {
     /* verify message came from the right direction */
-    struct CadetPeerPath *path = GCC_get_path (cc);
+    unsigned int len;
+    struct CadetPeerPath *path = GCC_get_path (cc,
+                                               &len);
 
     if (peer !=
         GCPP_get_peer_at_offset (path,
@@ -1145,7 +1206,9 @@ handle_tunnel_kx_auth (void *cls,
   if (NULL != cc)
   {
     /* verify message came from the right direction */
-    struct CadetPeerPath *path = GCC_get_path (cc);
+    unsigned int len;
+    struct CadetPeerPath *path = GCC_get_path (cc,
+                                               &len);
 
     if (peer !=
         GCPP_get_peer_at_offset (path,
@@ -1201,7 +1264,9 @@ handle_tunnel_encrypted (void *cls,
   if (NULL != cc)
   {
     /* verify message came from the right direction */
-    struct CadetPeerPath *path = GCC_get_path (cc);
+    unsigned int len;
+    struct CadetPeerPath *path = GCC_get_path (cc,
+                                               &len);
 
     if (peer !=
         GCPP_get_peer_at_offset (path,
@@ -1244,9 +1309,8 @@ core_init_cb (void *cls,
     return;
   }
   GNUNET_break (0 ==
-                memcmp (my_identity,
-                        &my_full_id,
-                        sizeof (struct GNUNET_PeerIdentity)));
+                GNUNET_memcmp (my_identity,
+                        &my_full_id));
 }