-only trigger check config if we actually need it
[oweals/gnunet.git] / src / dht / gnunet-service-wdht_neighbours.c
index df02d8adf1366c779444c1f307c66bb567a89ad0..54c52507e1714a5553734ad97f324a2167ae4ddc 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2009-2015 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2009-2015 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
 
      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., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 /**
  * @file dht/gnunet-service-wdht_neighbours.c
  * @brief GNUnet DHT service's finger and friend table management code
  * @author Supriti Singh
+ * @author Christian Grothoff
+ * @author Arthur Dewarumez
+ *
+ * TODO:
+ * - initiate finding of successors
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
@@ -39,9 +44,6 @@
 #include "gnunet-service-wdht_datacache.h"
 #include "gnunet-service-wdht_neighbours.h"
 #include "gnunet-service-wdht_nse.h"
-#include <fenv.h>
-#include <stdlib.h>
-#include <string.h>
 #include "dht.h"
 
 #define DEBUG(...)                                           \
@@ -351,12 +353,6 @@ struct FindSuccessorMessage
    */
   uint32_t reserved GNUNET_PACKED;
 
-  /**
-   * Unique (random) identifier this peer will use to
-   * identify the finger (in future messages).
-   */
-  struct GNUNET_HashCode trail_id;
-
   /**
    * Key for which we would like close values returned.
    * identify the finger (in future messages).
@@ -831,7 +827,7 @@ GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *trail_id,
 
   forward_message_on_trail (trail->pred,
                             trail_id,
-                            0 /* FIXME: put something right */,
+                            0 != (options & GNUNET_DHT_RO_RECORD_ROUTE),
                             &my_identity,
                             NULL, 0,
                             payload);
@@ -935,11 +931,9 @@ pick_random_friend ()
  * possibly initiate cleanup.
  *
  * @param cls NULL
- * @param tc unused
  */
 static void
-trail_timeout_callback (void *cls,
-                        const struct GNUNET_SCHEDULER_TaskContext *tc)
+trail_timeout_callback (void *cls)
 {
   struct Trail *trail;
   struct GNUNET_TIME_Relative left;
@@ -978,11 +972,9 @@ get_desired_finger_array_size ()
  * Initiate a random walk.
  *
  * @param cls NULL
- * @param tc unused
  */
 static void
-do_random_walk (void *cls,
-                const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_random_walk (void *cls)
 {
   static unsigned int walk_layer;
   struct FriendInfo *friend;
@@ -1252,8 +1244,7 @@ handle_dht_p2p_random_walk (void *cls,
 
 
 /**
- * Handle a `struct RandomWalkResponseMessage` from a GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK_RESPONSE
- * message.
+ * Handle a `struct RandomWalkResponseMessage`.
  *
  * @param cls closure (NULL)
  * @param peer sender identity
@@ -1266,8 +1257,55 @@ handle_dht_p2p_random_walk_response (void *cls,
                                      const struct GNUNET_MessageHeader *message)
 {
   const struct RandomWalkResponseMessage *rwrm;
+  struct Trail *trail;
+  struct FriendInfo *pred;
+  struct FingerTable *ft;
+  struct Finger *finger;
 
   rwrm = (const struct RandomWalkResponseMessage *) message;
+  trail = GNUNET_CONTAINER_multihashmap_get (trail_map,
+                                             &rwrm->trail_id);
+  if (NULL == trail)
+  {
+    /* TODO: log/statistics: we didn't find the trail (can happen) */
+    return GNUNET_OK;
+  }
+  if (NULL != (pred = trail->pred))
+  {
+    /* We are not the first hop, keep forwarding */
+    struct GNUNET_MQ_Envelope *env;
+    struct RandomWalkResponseMessage *rwrm2;
+
+    env = GNUNET_MQ_msg (rwrm2,
+                         GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK_RESPONSE);
+    rwrm2->reserved = htonl (0);
+    rwrm2->location = rwrm->location;
+    rwrm2->trail_id = trail->pred_id;
+    GNUNET_MQ_send (pred->mq,
+                    env);
+    return GNUNET_OK;
+  }
+  /* We are the first hop, complete finger */
+  if (NULL == (ft = trail->ft))
+  {
+    /* Eh, why did we create the trail if we have no FT? */
+    GNUNET_break (0);
+    delete_trail (trail,
+                  GNUNET_NO,
+                  GNUNET_YES);
+    return GNUNET_OK;
+  }
+  if (NULL == (finger = ft->fingers[trail->finger_off]))
+  {
+    /* Eh, finger got deleted, but why not the trail as well? */
+    GNUNET_break (0);
+    delete_trail (trail,
+                  GNUNET_NO,
+                  GNUNET_YES);
+    return GNUNET_OK;
+  }
+
+
   // 1) lookup trail => find Finger entry => fill in 'destination' and mark valid, move to end of sorted array,
   //mark unsorted, update links from 'trails'
   /*
@@ -1320,24 +1358,26 @@ handle_dht_p2p_trail_destroy (void *cls,
  *
  * @param cls closure (NULL)
  * @param trail_id path to the originator
+ * @param trail_path path the message took on the trail, if available
+ * @param trail_path_length number of entries on the @a trail_path
  * @param message the finger setup message
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 static int
 handle_dht_p2p_successor_find (void *cls,
                                const struct GNUNET_HashCode *trail_id,
+                               const struct GNUNET_PeerIdentity *trail_path,
+                               unsigned int trail_path_length,
                                const struct GNUNET_MessageHeader *message)
 {
   const struct FindSuccessorMessage *fsm;
 
+  /* We do not expect to track trails for the forward-direction
+     of successor finding... */
+  GNUNET_break_op (0 == trail_path_length);
   fsm = (const struct FindSuccessorMessage *) message;
-  // locate trail (for sending reply), if not exists, fail nicely.
-  // otherwise, go to datacache and return 'top k' elements closest to 'key'
-  // as "PUT" messages via the trail (need to extend DB API!)
-#if 0
   GDS_DATACACHE_get_successors (trail_id,
-                                key);
-#endif
+                                &fsm->key);
   return GNUNET_OK;
 }
 
@@ -1347,12 +1387,16 @@ handle_dht_p2p_successor_find (void *cls,
  *
  * @param cls closure (NULL)
  * @param trail_id path to the originator
+ * @param trail_path path the message took on the trail, if available
+ * @param trail_path_length number of entries on the @a trail_path
  * @param message the peer get message
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 static int
 handle_dht_p2p_peer_get (void *cls,
                          const struct GNUNET_HashCode *trail_id,
+                         const struct GNUNET_PeerIdentity *trail_path,
+                         unsigned int trail_path_length,
                          const struct GNUNET_MessageHeader *message)
 {
   const struct PeerGetMessage *pgm;
@@ -1378,12 +1422,16 @@ handle_dht_p2p_peer_get (void *cls,
  *
  * @param cls closure (NULL)
  * @param trail_id path to the originator
+ * @param trail_path path the message took on the trail, if available
+ * @param trail_path_length number of entries on the @a trail_path
  * @param message the peer get result message
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 static int
 handle_dht_p2p_peer_get_result (void *cls,
                                 const struct GNUNET_HashCode *trail_id,
+                                const struct GNUNET_PeerIdentity *trail_path,
+                                unsigned int trail_path_length,
                                 const struct GNUNET_MessageHeader *message)
 {
   const struct PeerGetResultMessage *pgrm;
@@ -1414,12 +1462,16 @@ handle_dht_p2p_peer_get_result (void *cls,
  *
  * @param cls closure (NULL)
  * @param trail_id path to the originator
+ * @param trail_path path the message took on the trail, if available
+ * @param trail_path_length number of entries on the @a trail_path
  * @param message the peer put message
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 static int
 handle_dht_p2p_peer_put (void *cls,
                          const struct GNUNET_HashCode *trail_id,
+                         const struct GNUNET_PeerIdentity *trail_path,
+                         unsigned int trail_path_length,
                          const struct GNUNET_MessageHeader *message)
 {
   const struct PeerGetResultMessage *pgrm;
@@ -1435,14 +1487,14 @@ handle_dht_p2p_peer_put (void *cls,
 #if 0
   GDS_DATACACHE_handle_put (expiration_time,
                             key,
-                            path_length, path,
+                            combined_path_length, combined_path,
                             block_type,
                             data_size,
                             data);
   GDS_CLIENTS_process_put (options,
                            block_type,
                            0, 0,
-                           path_length, path,
+                           combined_path_length, combined_path,
                            expiration_time,
                            key,
                            data,
@@ -1452,19 +1504,21 @@ handle_dht_p2p_peer_put (void *cls,
 }
 
 
-
-
 /**
  * Handler for a message we received along some trail.
  *
  * @param cls closure
  * @param trail_id trail identifier
+ * @param trail_path path the message took on the trail, if available
+ * @param trail_path_length number of entries on the @a trail_path
  * @param message the message we got
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 typedef int
 (*TrailHandlerCallback)(void *cls,
                         const struct GNUNET_HashCode *trail_id,
+                        const struct GNUNET_PeerIdentity *trail_path,
+                        unsigned int trail_path_length,
                         const struct GNUNET_MessageHeader *message);
 
 
@@ -1514,7 +1568,7 @@ handle_dht_p2p_trail_route (void *cls,
       sizeof (struct FindSuccessorMessage) },
     { &handle_dht_p2p_peer_get, NULL,
       GNUNET_MESSAGE_TYPE_WDHT_GET,
-      sizeof (struct FindSuccessorMessage) },
+      0 },
     { &handle_dht_p2p_peer_get_result, NULL,
       GNUNET_MESSAGE_TYPE_WDHT_GET_RESULT,
       0 },
@@ -1610,6 +1664,8 @@ handle_dht_p2p_trail_route (void *cls,
            (ntohs (payload->size) == th->message_size) )
         th->callback (th->cls,
                       &trm->trail_id,
+                      path,
+                      path_length,
                       payload);
       else
         GNUNET_break_op (0);
@@ -1623,6 +1679,7 @@ handle_dht_p2p_trail_route (void *cls,
 
 /**
  * Initialize neighbours subsystem.
+ *
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int