2 This file is part of GNUnet.
3 Copyright (C) 2013, 2017 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * @file cadet/gnunet-service-cadet_dht.c
20 * @brief Information we track per peer.
21 * @author Bartlomiej Polot
22 * @author Christian Grothoff
26 #include "gnunet_util_lib.h"
27 #include "gnunet_dht_service.h"
28 #include "gnunet_statistics_service.h"
29 #include "gnunet-service-cadet.h"
30 #include "gnunet-service-cadet_dht.h"
31 #include "gnunet-service-cadet_hello.h"
32 #include "gnunet-service-cadet_peer.h"
33 #include "gnunet-service-cadet_paths.h"
36 * How long do we wait before first announcing our presence to the DHT.
37 * Used to wait for our HELLO to be available. Note that we also get
38 * notifications when our HELLO is ready, so this is just the maximum
39 * we wait for the first notification.
41 #define STARTUP_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500)
44 * How long do we wait after we get an updated HELLO before publishing?
45 * Allows for the HELLO to be updated again quickly, for example in
46 * case multiple addresses changed and we got a partial update.
48 #define CHANGE_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100)
51 #define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__)
55 * Handle for DHT searches.
57 struct GCD_search_handle
62 struct GNUNET_DHT_GetHandle *dhtget;
70 static struct GNUNET_DHT_Handle *dht_handle;
73 * How often to PUT own ID in the DHT.
75 static struct GNUNET_TIME_Relative id_announce_time;
78 * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put().
80 static unsigned long long dht_replication_level;
83 * Task to periodically announce itself in the network.
85 static struct GNUNET_SCHEDULER_Task *announce_id_task;
88 * Delay for the next ID announce.
90 static struct GNUNET_TIME_Relative announce_delay;
94 * Function to process paths received for a new peer addition. The recorded
95 * paths form the initial tunnel, which can be optimized later.
96 * Called on each result obtained for the DHT search.
99 * @param exp when will this value expire
100 * @param key key of the result
101 * @param get_path path of the get request
102 * @param get_path_length lenght of @a get_path
103 * @param put_path path of the put request
104 * @param put_path_length length of the @a put_path
105 * @param type type of the result
106 * @param size number of bytes in data
107 * @param data pointer to the result data
110 dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
111 const struct GNUNET_HashCode *key,
112 const struct GNUNET_PeerIdentity *get_path,
113 unsigned int get_path_length,
114 const struct GNUNET_PeerIdentity *put_path,
115 unsigned int put_path_length,
116 enum GNUNET_BLOCK_Type type,
120 const struct GNUNET_HELLO_Message *hello = data;
121 struct CadetPeer *peer;
123 GCPP_try_path_from_dht (get_path,
127 if ( (size >= sizeof (struct GNUNET_HELLO_Message)) &&
128 (ntohs (hello->header.size) == size) &&
129 (size == GNUNET_HELLO_size (hello)) )
131 peer = GCP_get (&put_path[0],
133 LOG (GNUNET_ERROR_TYPE_DEBUG,
134 "Got HELLO for %s\n",
143 * Periodically announce self id in the DHT
148 announce_id (void *cls)
150 struct GNUNET_HashCode phash;
151 const struct GNUNET_HELLO_Message *hello;
153 struct GNUNET_TIME_Absolute expiration;
154 struct GNUNET_TIME_Relative next_put;
156 hello = GCH_get_mine ();
157 size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0;
160 expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
162 announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
166 expiration = GNUNET_HELLO_get_last_expiration (hello);
167 announce_delay = GNUNET_TIME_UNIT_SECONDS;
170 /* Call again in id_announce_time, unless HELLO expires first,
171 * but wait at least 1s. */
173 = GNUNET_TIME_absolute_get_remaining (expiration);
175 = GNUNET_TIME_relative_min (next_put,
178 = GNUNET_TIME_relative_max (next_put,
179 GNUNET_TIME_UNIT_SECONDS);
181 = GNUNET_SCHEDULER_add_delayed (next_put,
184 GNUNET_STATISTICS_update (stats,
191 GNUNET_memcpy (&phash,
193 sizeof (my_full_id));
194 LOG (GNUNET_ERROR_TYPE_DEBUG,
195 "Announcing my HELLO (%u bytes) in the DHT\n",
197 GNUNET_DHT_put (dht_handle, /* DHT handle */
198 &phash, /* Key to use */
199 dht_replication_level, /* Replication level */
200 GNUNET_DHT_RO_RECORD_ROUTE
201 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
202 GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */
203 size, /* Size of the data */
204 (const char *) hello, /* Data itself */
205 expiration, /* Data expiration */
206 NULL, /* Continuation */
207 NULL); /* Continuation closure */
212 * Function called by the HELLO subsystem whenever OUR hello
213 * changes. Re-triggers the DHT PUT immediately.
218 if (NULL == announce_id_task)
219 return; /* too early */
220 GNUNET_SCHEDULER_cancel (announce_id_task);
222 = GNUNET_SCHEDULER_add_delayed (CHANGE_DELAY,
229 * Initialize the DHT subsystem.
231 * @param c Configuration.
234 GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
237 GNUNET_CONFIGURATION_get_value_number (c,
239 "DHT_REPLICATION_LEVEL",
240 &dht_replication_level))
242 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
244 "DHT_REPLICATION_LEVEL",
246 dht_replication_level = 3;
250 GNUNET_CONFIGURATION_get_value_time (c,
255 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
259 GNUNET_SCHEDULER_shutdown ();
263 dht_handle = GNUNET_DHT_connect (c,
265 GNUNET_break (NULL != dht_handle);
266 announce_delay = GNUNET_TIME_UNIT_SECONDS;
267 announce_id_task = GNUNET_SCHEDULER_add_delayed (STARTUP_DELAY,
274 * Shut down the DHT subsystem.
279 if (NULL != dht_handle)
281 GNUNET_DHT_disconnect (dht_handle);
284 if (NULL != announce_id_task)
286 GNUNET_SCHEDULER_cancel (announce_id_task);
287 announce_id_task = NULL;
293 * Search DHT for paths to @a peeR_id
295 * @param peer_id peer to search for
296 * @return handle to abort search
298 struct GCD_search_handle *
299 GCD_search (const struct GNUNET_PeerIdentity *peer_id)
301 struct GNUNET_HashCode phash;
302 struct GCD_search_handle *h;
304 GNUNET_STATISTICS_update (stats,
311 GNUNET_memcpy (&phash,
315 h = GNUNET_new (struct GCD_search_handle);
316 h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */
317 GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */
318 &phash, /* key to search */
319 dht_replication_level, /* replication level */
320 GNUNET_DHT_RO_RECORD_ROUTE |
321 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
326 LOG (GNUNET_ERROR_TYPE_DEBUG,
327 "Starting DHT GET for peer %s (%p)\n",
328 GNUNET_i2s (peer_id),
335 * Stop DHT search started with #GCD_search().
337 * @param h handle to search to stop
340 GCD_search_stop (struct GCD_search_handle *h)
342 LOG (GNUNET_ERROR_TYPE_DEBUG,
343 "Stopping DHT GET %p\n",
345 GNUNET_DHT_get_stop (h->dhtget);
349 /* end of gnunet-service-cadet_dht.c */