pass only CadetTunnelAxolotl if it suffices, preparation for having ambiguous KX...
[oweals/gnunet.git] / src / cadet / gnunet-service-cadet_dht.c
index 81051a70002400e54cec2c45551302b66ffd5415..22673b16706f49ddec79a97f094982e92e39a864 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2013 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2013 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
  */
 struct GCD_search_handle
 {
-  /** DHT_GET handle. */
+  /**
+   * DHT_GET handle.
+   */
   struct GNUNET_DHT_GetHandle *dhtget;
 
-  /** Provided callback to call when a path is found. */
+  /**
+   * Provided callback to call when a path is found.
+   */
   GCD_search_callback callback;
 
-  /** Provided closure. */
+  /**
+   * Provided closure.
+   */
   void *cls;
 
-  /** Peer ID searched for */
+  /**
+   * Peer ID searched for
+   */
   GNUNET_PEER_Id peer_id;
 };
 
@@ -95,6 +103,11 @@ static unsigned long long dht_replication_level;
  */
 static struct GNUNET_SCHEDULER_Task * announce_id_task;
 
+/**
+ * Delay for the next ID announce.
+ */
+static struct GNUNET_TIME_Relative announce_delay;
+
 /**
  * GET requests to stop on shutdown.
  */
@@ -154,9 +167,9 @@ path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
  * @param exp when will this value expire
  * @param key key of the result
  * @param get_path path of the get request
- * @param get_path_length lenght of get_path
+ * @param get_path_length lenght of @a get_path
  * @param put_path path of the put request
- * @param put_path_length length of the put_path
+ * @param put_path_length length of the @a put_path
  * @param type type of the result
  * @param size number of bytes in data
  * @param data pointer to the result data
@@ -185,10 +198,15 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
   }
 
   s = path_2s (p);
-  LOG (GNUNET_ERROR_TYPE_INFO, "Got path from DHT: %s\n", s);
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "Got path from DHT: %s\n",
+       s);
   GNUNET_free_non_null (s);
-  peer = GCP_get_short (p->peers[p->length - 1]);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got HELLO for %s\n", GCP_2s (peer));
+
+  peer = GCP_get_short (p->peers[p->length - 1], GNUNET_YES);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Got HELLO for %s\n",
+       GCP_2s (peer));
   h->callback (h->cls, p);
   path_destroy (p);
   hello = (struct GNUNET_HELLO_Message *) data;
@@ -201,61 +219,76 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
  * Periodically announce self id in the DHT
  *
  * @param cls closure
- * @param tc task context
  */
 static void
-announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+announce_id (void *cls)
 {
   struct GNUNET_HashCode phash;
   const struct GNUNET_HELLO_Message *hello;
   size_t size;
   struct GNUNET_TIME_Absolute expiration;
-  struct GNUNET_TIME_Relative retry_time;
+  struct GNUNET_TIME_Relative next_put;
 
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-  {
-    announce_id_task = NULL;
-    return;
-  }
+  announce_id_task = NULL;
   LOG (GNUNET_ERROR_TYPE_DEBUG, "Announce ID\n");
-  /* TODO
-   * - Set data expiration in function of X
-   * - Adapt X to churn
-   */
   hello = GCH_get_mine ();
-  if (NULL == hello || (size = GNUNET_HELLO_size (hello)) == 0)
+  size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0;
+  if ( (NULL == hello) || (0 == size) )
   {
-    /* Peerinfo gave us no hello yet, try again in a second. */
-    announce_id_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                                     &announce_id, cls);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  no hello, waiting!\n");
-    GNUNET_STATISTICS_update (stats, "# DHT announce skipped (no hello)",
-                              1, GNUNET_NO);
-
-    return;
+    /* Peerinfo gave us no hello yet, try again soon. */
+    LOG (GNUNET_ERROR_TYPE_INFO,
+        "  no hello, waiting!\n");
+    GNUNET_STATISTICS_update (stats,
+                             "# DHT announce skipped (no hello)",
+                              1,
+                             GNUNET_NO);
+    expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+                                           announce_delay);
+    announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
+  }
+  else
+  {
+    expiration = GNUNET_HELLO_get_last_expiration (hello);
+    announce_delay = GNUNET_TIME_UNIT_SECONDS;
   }
-  expiration = GNUNET_HELLO_get_last_expiration (hello);
-  retry_time = GNUNET_TIME_absolute_get_remaining (expiration);
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Hello %p size: %u\n", hello, size);
-  GNUNET_STATISTICS_update (stats, "# DHT announce",
-                            1, GNUNET_NO);
-  memset (&phash, 0, sizeof (phash));
-  memcpy (&phash, &my_full_id, sizeof (my_full_id));
-  GNUNET_DHT_put (dht_handle,   /* DHT handle */
-                  &phash,       /* Key to use */
-                  dht_replication_level,     /* Replication level */
-                  GNUNET_DHT_RO_RECORD_ROUTE
-                  | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,    /* DHT options */
-                  GNUNET_BLOCK_TYPE_DHT_HELLO,       /* Block type */
-                  size,  /* Size of the data */
-                  (const char *) hello, /* Data itself */
-                  expiration,  /* Data expiration */
-                  retry_time, /* Retry time */
-                  NULL,         /* Continuation */
-                  NULL);        /* Continuation closure */
-  announce_id_task =
-      GNUNET_SCHEDULER_add_delayed (id_announce_time, &announce_id, cls);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Hello %p size: %u\n",
+       hello,
+       size);
+  if (NULL != hello)
+  {
+    GNUNET_STATISTICS_update (stats,
+                             "# DHT announce",
+                             1, GNUNET_NO);
+    memset (&phash,
+           0,
+           sizeof (phash));
+    GNUNET_memcpy (&phash,
+                  &my_full_id,
+                  sizeof (my_full_id));
+    GNUNET_DHT_put (dht_handle,   /* DHT handle */
+                   &phash,       /* Key to use */
+                   dht_replication_level,     /* Replication level */
+                   GNUNET_DHT_RO_RECORD_ROUTE
+                   | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,    /* DHT options */
+                   GNUNET_BLOCK_TYPE_DHT_HELLO,       /* Block type */
+                   size,  /* Size of the data */
+                   (const char *) hello, /* Data itself */
+                   expiration,  /* Data expiration */
+                   NULL,         /* Continuation */
+                   NULL);        /* Continuation closure */
+  }
+  /* Call again in id_announce_time, unless HELLO expires first,
+   * but wait at least 1s. */
+  next_put = GNUNET_TIME_absolute_get_remaining (expiration);
+  next_put = GNUNET_TIME_relative_min (next_put,
+                                      id_announce_time);
+  next_put = GNUNET_TIME_relative_max (next_put,
+                                      GNUNET_TIME_UNIT_SECONDS);
+  announce_id_task = GNUNET_SCHEDULER_add_delayed (next_put,
+                                                  &announce_id,
+                                                  cls);
 }
 
 /**
@@ -294,11 +327,12 @@ GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
 {
   LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "CADET", "DHT_REPLICATION_LEVEL",
+      GNUNET_CONFIGURATION_get_value_number (c, "CADET",
+                                             "DHT_REPLICATION_LEVEL",
                                              &dht_replication_level))
   {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
-                               "CADET", "DHT_REPLICATION_LEVEL", "USING DEFAULT");
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, "CADET",
+                               "DHT_REPLICATION_LEVEL", "USING DEFAULT");
     dht_replication_level = 3;
   }
 
@@ -306,8 +340,8 @@ GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
       GNUNET_CONFIGURATION_get_value_time (c, "CADET", "ID_ANNOUNCE_TIME",
                                            &id_announce_time))
   {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-                               "CADET", "ID_ANNOUNCE_TIME", "MISSING");
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "CADET",
+                               "ID_ANNOUNCE_TIME", "MISSING");
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
@@ -318,6 +352,7 @@ GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
     GNUNET_break (0);
   }
 
+  announce_delay = GNUNET_TIME_UNIT_SECONDS;
   announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, NULL);
   get_requests = GNUNET_CONTAINER_multihashmap32_create (32);
 }
@@ -329,6 +364,7 @@ GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
 void
 GCD_shutdown (void)
 {
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down DHT\n");
   GNUNET_CONTAINER_multihashmap32_iterate (get_requests, &stop_get, NULL);
   GNUNET_CONTAINER_multihashmap32_destroy (get_requests);
   if (dht_handle != NULL)
@@ -354,7 +390,7 @@ GCD_search (const struct GNUNET_PeerIdentity *peer_id,
        GNUNET_i2s (peer_id));
   GNUNET_STATISTICS_update (stats, "# DHT search", 1, GNUNET_NO);
   memset (&phash, 0, sizeof (phash));
-  memcpy (&phash, peer_id, sizeof (*peer_id));
+  GNUNET_memcpy (&phash, peer_id, sizeof (*peer_id));
   h = GNUNET_new (struct GCD_search_handle);
   h->peer_id = GNUNET_PEER_intern (peer_id);
   h->callback = callback;
@@ -367,8 +403,11 @@ GCD_search (const struct GNUNET_PeerIdentity *peer_id,
                                     GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
                                     NULL,       /* xquery */
                                     0,     /* xquery bits */
-                                    &dht_get_id_handler, h);
-  GNUNET_CONTAINER_multihashmap32_put (get_requests, h->peer_id, h,
+                                    &dht_get_id_handler,
+                                   h);
+  GNUNET_CONTAINER_multihashmap32_put (get_requests,
+                                      h->peer_id,
+                                      h,
                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
   return h;
 }