aboutsummaryrefslogtreecommitdiff
path: root/src/cadet/gnunet-service-cadet_dht.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cadet/gnunet-service-cadet_dht.c')
-rw-r--r--src/cadet/gnunet-service-cadet_dht.c373
1 files changed, 150 insertions, 223 deletions
diff --git a/src/cadet/gnunet-service-cadet_dht.c b/src/cadet/gnunet-service-cadet_dht.c
index 22673b167..f00c0caf3 100644
--- a/src/cadet/gnunet-service-cadet_dht.c
+++ b/src/cadet/gnunet-service-cadet_dht.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2013 GNUnet e.V. 3 Copyright (C) 2013, 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -17,25 +17,41 @@
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA. 18 Boston, MA 02110-1301, USA.
19*/ 19*/
20 20/**
21 * @file cadet/gnunet-service-cadet_dht.c
22 * @brief Information we track per peer.
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 */
21 26
22#include "platform.h" 27#include "platform.h"
23#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
24
25#include "gnunet_dht_service.h" 29#include "gnunet_dht_service.h"
26#include "gnunet_statistics_service.h" 30#include "gnunet_statistics_service.h"
27 31#include "gnunet-service-cadet.h"
28#include "cadet_path.h"
29#include "gnunet-service-cadet_dht.h" 32#include "gnunet-service-cadet_dht.h"
30#include "gnunet-service-cadet_peer.h"
31#include "gnunet-service-cadet_hello.h" 33#include "gnunet-service-cadet_hello.h"
34#include "gnunet-service-cadet_peer.h"
35#include "gnunet-service-cadet_paths.h"
32 36
33#define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__) 37/**
38 * How long do we wait before first announcing our presence to the DHT.
39 * Used to wait for our HELLO to be available. Note that we also get
40 * notifications when our HELLO is ready, so this is just the maximum
41 * we wait for the first notification.
42 */
43#define STARTUP_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500)
34 44
45/**
46 * How long do we wait after we get an updated HELLO before publishing?
47 * Allows for the HELLO to be updated again quickly, for example in
48 * case multiple addresses changed and we got a partial update.
49 */
50#define CHANGE_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100)
51
52
53#define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__)
35 54
36/******************************************************************************/
37/******************************** STRUCTS **********************************/
38/******************************************************************************/
39 55
40/** 56/**
41 * Handle for DHT searches. 57 * Handle for DHT searches.
@@ -47,42 +63,9 @@ struct GCD_search_handle
47 */ 63 */
48 struct GNUNET_DHT_GetHandle *dhtget; 64 struct GNUNET_DHT_GetHandle *dhtget;
49 65
50 /**
51 * Provided callback to call when a path is found.
52 */
53 GCD_search_callback callback;
54
55 /**
56 * Provided closure.
57 */
58 void *cls;
59
60 /**
61 * Peer ID searched for
62 */
63 GNUNET_PEER_Id peer_id;
64}; 66};
65 67
66 68
67/******************************************************************************/
68/******************************* GLOBALS ***********************************/
69/******************************************************************************/
70
71/**
72 * Global handle to the statistics service.
73 */
74extern struct GNUNET_STATISTICS_Handle *stats;
75
76/**
77 * Own ID (short value).
78 */
79extern GNUNET_PEER_Id myid;
80
81/**
82 * Own ID (full value).
83 */
84extern struct GNUNET_PeerIdentity my_full_id;
85
86/** 69/**
87 * Handle to use DHT. 70 * Handle to use DHT.
88 */ 71 */
@@ -94,69 +77,20 @@ static struct GNUNET_DHT_Handle *dht_handle;
94static struct GNUNET_TIME_Relative id_announce_time; 77static struct GNUNET_TIME_Relative id_announce_time;
95 78
96/** 79/**
97 * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put. 80 * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put().
98 */ 81 */
99static unsigned long long dht_replication_level; 82static unsigned long long dht_replication_level;
100 83
101/** 84/**
102 * Task to periodically announce itself in the network. 85 * Task to periodically announce itself in the network.
103 */ 86 */
104static struct GNUNET_SCHEDULER_Task * announce_id_task; 87static struct GNUNET_SCHEDULER_Task *announce_id_task;
105 88
106/** 89/**
107 * Delay for the next ID announce. 90 * Delay for the next ID announce.
108 */ 91 */
109static struct GNUNET_TIME_Relative announce_delay; 92static struct GNUNET_TIME_Relative announce_delay;
110 93
111/**
112 * GET requests to stop on shutdown.
113 */
114static struct GNUNET_CONTAINER_MultiHashMap32 *get_requests;
115
116/******************************************************************************/
117/******************************** STATIC ***********************************/
118/******************************************************************************/
119
120
121/**
122 * Build a PeerPath from the paths returned from the DHT, reversing the paths
123 * to obtain a local peer -> destination path and interning the peer ids.
124 *
125 * @return Newly allocated and created path
126 *
127 * FIXME refactor and use build_path_from_peer_ids
128 */
129static struct CadetPeerPath *
130path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
131 unsigned int get_path_length,
132 const struct GNUNET_PeerIdentity *put_path,
133 unsigned int put_path_length)
134{
135 size_t size = get_path_length + put_path_length + 1;
136 struct GNUNET_PeerIdentity peers[size];
137 const struct GNUNET_PeerIdentity *peer;
138 struct CadetPeerPath *p;
139 unsigned int own_pos;
140 int i;
141
142 peers[0] = my_full_id;
143 LOG (GNUNET_ERROR_TYPE_DEBUG, " GET has %d hops.\n", get_path_length);
144 for (i = 0 ; i < get_path_length; i++)
145 {
146 peer = &get_path[get_path_length - i - 1];
147 LOG (GNUNET_ERROR_TYPE_DEBUG, " From GET: %s\n", GNUNET_i2s (peer));
148 peers[i + 1] = *peer;
149 }
150 for (i = 0 ; i < put_path_length; i++)
151 {
152 peer = &put_path[put_path_length - i - 1];
153 LOG (GNUNET_ERROR_TYPE_DEBUG, " From PUT: %s\n", GNUNET_i2s (peer));
154 peers[i + get_path_length + 1] = *peer;
155 }
156 p = path_build_from_peer_ids (peers, size, myid, &own_pos);
157 return p;
158}
159
160 94
161/** 95/**
162 * Function to process paths received for a new peer addition. The recorded 96 * Function to process paths received for a new peer addition. The recorded
@@ -176,42 +110,34 @@ path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
176 */ 110 */
177static void 111static void
178dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, 112dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
179 const struct GNUNET_HashCode * key, 113 const struct GNUNET_HashCode *key,
180 const struct GNUNET_PeerIdentity *get_path, 114 const struct GNUNET_PeerIdentity *get_path,
181 unsigned int get_path_length, 115 unsigned int get_path_length,
182 const struct GNUNET_PeerIdentity *put_path, 116 const struct GNUNET_PeerIdentity *put_path,
183 unsigned int put_path_length, enum GNUNET_BLOCK_Type type, 117 unsigned int put_path_length,
184 size_t size, const void *data) 118 enum GNUNET_BLOCK_Type type,
119 size_t size,
120 const void *data)
185{ 121{
186 struct GCD_search_handle *h = cls; 122 const struct GNUNET_HELLO_Message *hello = data;
187 struct GNUNET_HELLO_Message *hello;
188 struct CadetPeerPath *p;
189 struct CadetPeer *peer; 123 struct CadetPeer *peer;
190 char *s;
191 124
192 p = path_build_from_dht (get_path, get_path_length, 125 GCPP_try_path_from_dht (get_path,
193 put_path, put_path_length); 126 get_path_length,
194 if (NULL == p) 127 put_path,
128 put_path_length);
129 if ( (size >= sizeof (struct GNUNET_HELLO_Message)) &&
130 (ntohs (hello->header.size) == size) &&
131 (size == GNUNET_HELLO_size (hello)) )
195 { 132 {
196 GNUNET_break_op (0); 133 peer = GCP_get (&put_path[0],
197 return; 134 GNUNET_YES);
135 LOG (GNUNET_ERROR_TYPE_DEBUG,
136 "Got HELLO for %s\n",
137 GCP_2s (peer));
138 GCP_set_hello (peer,
139 hello);
198 } 140 }
199
200 s = path_2s (p);
201 LOG (GNUNET_ERROR_TYPE_INFO,
202 "Got path from DHT: %s\n",
203 s);
204 GNUNET_free_non_null (s);
205
206 peer = GCP_get_short (p->peers[p->length - 1], GNUNET_YES);
207 LOG (GNUNET_ERROR_TYPE_DEBUG,
208 "Got HELLO for %s\n",
209 GCP_2s (peer));
210 h->callback (h->cls, p);
211 path_destroy (p);
212 hello = (struct GNUNET_HELLO_Message *) data;
213 GCP_set_hello (peer, hello);
214 GCP_try_connect (peer);
215} 141}
216 142
217 143
@@ -229,19 +155,10 @@ announce_id (void *cls)
229 struct GNUNET_TIME_Absolute expiration; 155 struct GNUNET_TIME_Absolute expiration;
230 struct GNUNET_TIME_Relative next_put; 156 struct GNUNET_TIME_Relative next_put;
231 157
232 announce_id_task = NULL;
233 LOG (GNUNET_ERROR_TYPE_DEBUG, "Announce ID\n");
234 hello = GCH_get_mine (); 158 hello = GCH_get_mine ();
235 size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0; 159 size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0;
236 if ( (NULL == hello) || (0 == size) ) 160 if (0 == size)
237 { 161 {
238 /* Peerinfo gave us no hello yet, try again soon. */
239 LOG (GNUNET_ERROR_TYPE_INFO,
240 " no hello, waiting!\n");
241 GNUNET_STATISTICS_update (stats,
242 "# DHT announce skipped (no hello)",
243 1,
244 GNUNET_NO);
245 expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), 162 expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
246 announce_delay); 163 announce_delay);
247 announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay); 164 announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
@@ -252,71 +169,64 @@ announce_id (void *cls)
252 announce_delay = GNUNET_TIME_UNIT_SECONDS; 169 announce_delay = GNUNET_TIME_UNIT_SECONDS;
253 } 170 }
254 171
255 LOG (GNUNET_ERROR_TYPE_DEBUG,
256 "Hello %p size: %u\n",
257 hello,
258 size);
259 if (NULL != hello)
260 {
261 GNUNET_STATISTICS_update (stats,
262 "# DHT announce",
263 1, GNUNET_NO);
264 memset (&phash,
265 0,
266 sizeof (phash));
267 GNUNET_memcpy (&phash,
268 &my_full_id,
269 sizeof (my_full_id));
270 GNUNET_DHT_put (dht_handle, /* DHT handle */
271 &phash, /* Key to use */
272 dht_replication_level, /* Replication level */
273 GNUNET_DHT_RO_RECORD_ROUTE
274 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
275 GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */
276 size, /* Size of the data */
277 (const char *) hello, /* Data itself */
278 expiration, /* Data expiration */
279 NULL, /* Continuation */
280 NULL); /* Continuation closure */
281 }
282 /* Call again in id_announce_time, unless HELLO expires first, 172 /* Call again in id_announce_time, unless HELLO expires first,
283 * but wait at least 1s. */ 173 * but wait at least 1s. */
284 next_put = GNUNET_TIME_absolute_get_remaining (expiration); 174 next_put
285 next_put = GNUNET_TIME_relative_min (next_put, 175 = GNUNET_TIME_absolute_get_remaining (expiration);
286 id_announce_time); 176 next_put
287 next_put = GNUNET_TIME_relative_max (next_put, 177 = GNUNET_TIME_relative_min (next_put,
288 GNUNET_TIME_UNIT_SECONDS); 178 id_announce_time);
289 announce_id_task = GNUNET_SCHEDULER_add_delayed (next_put, 179 next_put
290 &announce_id, 180 = GNUNET_TIME_relative_max (next_put,
291 cls); 181 GNUNET_TIME_UNIT_SECONDS);
182 announce_id_task
183 = GNUNET_SCHEDULER_add_delayed (next_put,
184 &announce_id,
185 cls);
186 GNUNET_STATISTICS_update (stats,
187 "# DHT announce",
188 1,
189 GNUNET_NO);
190 memset (&phash,
191 0,
192 sizeof (phash));
193 GNUNET_memcpy (&phash,
194 &my_full_id,
195 sizeof (my_full_id));
196 LOG (GNUNET_ERROR_TYPE_DEBUG,
197 "Announcing my HELLO (%u bytes) in the DHT\n",
198 size);
199 GNUNET_DHT_put (dht_handle, /* DHT handle */
200 &phash, /* Key to use */
201 dht_replication_level, /* Replication level */
202 GNUNET_DHT_RO_RECORD_ROUTE
203 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
204 GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */
205 size, /* Size of the data */
206 (const char *) hello, /* Data itself */
207 expiration, /* Data expiration */
208 NULL, /* Continuation */
209 NULL); /* Continuation closure */
292} 210}
293 211
212
294/** 213/**
295 * Iterator over hash map entries and stop GET requests before disconnecting 214 * Function called by the HELLO subsystem whenever OUR hello
296 * from the DHT. 215 * changes. Re-triggers the DHT PUT immediately.
297 *
298 * @param cls Closure (unused)
299 * @param key Current peer ID.
300 * @param value Value in the hash map (GCD_search_handle).
301 *
302 * @return #GNUNET_YES, we should continue to iterate,
303 */ 216 */
304int 217void
305stop_get (void *cls, 218GCD_hello_update ()
306 uint32_t key,
307 void *value)
308{ 219{
309 struct GCD_search_handle *h = value; 220 if (NULL == announce_id_task)
310 221 return; /* too early */
311 GCD_search_stop (h); 222 GNUNET_SCHEDULER_cancel (announce_id_task);
312 return GNUNET_YES; 223 announce_id_task
224 = GNUNET_SCHEDULER_add_delayed (CHANGE_DELAY,
225 &announce_id,
226 NULL);
313} 227}
314 228
315 229
316/******************************************************************************/
317/******************************** API ***********************************/
318/******************************************************************************/
319
320/** 230/**
321 * Initialize the DHT subsystem. 231 * Initialize the DHT subsystem.
322 * 232 *
@@ -325,36 +235,40 @@ stop_get (void *cls,
325void 235void
326GCD_init (const struct GNUNET_CONFIGURATION_Handle *c) 236GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
327{ 237{
328 LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
329 if (GNUNET_OK != 238 if (GNUNET_OK !=
330 GNUNET_CONFIGURATION_get_value_number (c, "CADET", 239 GNUNET_CONFIGURATION_get_value_number (c,
240 "CADET",
331 "DHT_REPLICATION_LEVEL", 241 "DHT_REPLICATION_LEVEL",
332 &dht_replication_level)) 242 &dht_replication_level))
333 { 243 {
334 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, "CADET", 244 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
335 "DHT_REPLICATION_LEVEL", "USING DEFAULT"); 245 "CADET",
246 "DHT_REPLICATION_LEVEL",
247 "USING DEFAULT");
336 dht_replication_level = 3; 248 dht_replication_level = 3;
337 } 249 }
338 250
339 if (GNUNET_OK != 251 if (GNUNET_OK !=
340 GNUNET_CONFIGURATION_get_value_time (c, "CADET", "ID_ANNOUNCE_TIME", 252 GNUNET_CONFIGURATION_get_value_time (c,
253 "CADET",
254 "ID_ANNOUNCE_TIME",
341 &id_announce_time)) 255 &id_announce_time))
342 { 256 {
343 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "CADET", 257 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
344 "ID_ANNOUNCE_TIME", "MISSING"); 258 "CADET",
259 "ID_ANNOUNCE_TIME",
260 "MISSING");
345 GNUNET_SCHEDULER_shutdown (); 261 GNUNET_SCHEDULER_shutdown ();
346 return; 262 return;
347 } 263 }
348 264
349 dht_handle = GNUNET_DHT_connect (c, 64); 265 dht_handle = GNUNET_DHT_connect (c,
350 if (NULL == dht_handle) 266 64);
351 { 267 GNUNET_break (NULL != dht_handle);
352 GNUNET_break (0);
353 }
354
355 announce_delay = GNUNET_TIME_UNIT_SECONDS; 268 announce_delay = GNUNET_TIME_UNIT_SECONDS;
356 announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, NULL); 269 announce_id_task = GNUNET_SCHEDULER_add_delayed (STARTUP_DELAY,
357 get_requests = GNUNET_CONTAINER_multihashmap32_create (32); 270 &announce_id,
271 NULL);
358} 272}
359 273
360 274
@@ -364,10 +278,7 @@ GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
364void 278void
365GCD_shutdown (void) 279GCD_shutdown (void)
366{ 280{
367 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down DHT\n"); 281 if (NULL != dht_handle)
368 GNUNET_CONTAINER_multihashmap32_iterate (get_requests, &stop_get, NULL);
369 GNUNET_CONTAINER_multihashmap32_destroy (get_requests);
370 if (dht_handle != NULL)
371 { 282 {
372 GNUNET_DHT_disconnect (dht_handle); 283 GNUNET_DHT_disconnect (dht_handle);
373 dht_handle = NULL; 284 dht_handle = NULL;
@@ -379,22 +290,31 @@ GCD_shutdown (void)
379 } 290 }
380} 291}
381 292
293
294/**
295 * Search DHT for paths to @a peeR_id
296 *
297 * @param peer_id peer to search for
298 * @return handle to abort search
299 */
382struct GCD_search_handle * 300struct GCD_search_handle *
383GCD_search (const struct GNUNET_PeerIdentity *peer_id, 301GCD_search (const struct GNUNET_PeerIdentity *peer_id)
384 GCD_search_callback callback, void *cls)
385{ 302{
386 struct GNUNET_HashCode phash; 303 struct GNUNET_HashCode phash;
387 struct GCD_search_handle *h; 304 struct GCD_search_handle *h;
388 305
389 LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting DHT GET for peer %s\n", 306 GNUNET_STATISTICS_update (stats,
390 GNUNET_i2s (peer_id)); 307 "# DHT search",
391 GNUNET_STATISTICS_update (stats, "# DHT search", 1, GNUNET_NO); 308 1,
392 memset (&phash, 0, sizeof (phash)); 309 GNUNET_NO);
393 GNUNET_memcpy (&phash, peer_id, sizeof (*peer_id)); 310 memset (&phash,
311 0,
312 sizeof (phash));
313 GNUNET_memcpy (&phash,
314 peer_id,
315 sizeof (*peer_id));
316
394 h = GNUNET_new (struct GCD_search_handle); 317 h = GNUNET_new (struct GCD_search_handle);
395 h->peer_id = GNUNET_PEER_intern (peer_id);
396 h->callback = callback;
397 h->cls = cls;
398 h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */ 318 h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */
399 GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */ 319 GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */
400 &phash, /* key to search */ 320 &phash, /* key to search */
@@ -405,20 +325,27 @@ GCD_search (const struct GNUNET_PeerIdentity *peer_id,
405 0, /* xquery bits */ 325 0, /* xquery bits */
406 &dht_get_id_handler, 326 &dht_get_id_handler,
407 h); 327 h);
408 GNUNET_CONTAINER_multihashmap32_put (get_requests, 328 LOG (GNUNET_ERROR_TYPE_DEBUG,
409 h->peer_id, 329 "Starting DHT GET for peer %s (%p)\n",
410 h, 330 GNUNET_i2s (peer_id),
411 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 331 h);
412 return h; 332 return h;
413} 333}
414 334
415 335
336/**
337 * Stop DHT search started with #GCD_search().
338 *
339 * @param h handle to search to stop
340 */
416void 341void
417GCD_search_stop (struct GCD_search_handle *h) 342GCD_search_stop (struct GCD_search_handle *h)
418{ 343{
419 GNUNET_break (GNUNET_OK == 344 LOG (GNUNET_ERROR_TYPE_DEBUG,
420 GNUNET_CONTAINER_multihashmap32_remove (get_requests, 345 "Stopping DHT GET %p\n",
421 h->peer_id, h)); 346 h);
422 GNUNET_DHT_get_stop (h->dhtget); 347 GNUNET_DHT_get_stop (h->dhtget);
423 GNUNET_free (h); 348 GNUNET_free (h);
424} 349}
350
351/* end of gnunet-service-cadet_dht.c */