aboutsummaryrefslogtreecommitdiff
path: root/src/dht
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-01-15 19:24:33 +0100
committerChristian Grothoff <christian@grothoff.org>2022-02-19 12:39:55 +0100
commitb0abdf7127f2403ff583d224e0d9d4e68c1c5bfc (patch)
tree47df762cdbcce501ec5536c8963b5c9ee55da31d /src/dht
parent3a71153405e8fc26712807b4bdb5987fb3bf2b9e (diff)
downloadgnunet-b0abdf7127f2403ff583d224e0d9d4e68c1c5bfc.tar.gz
gnunet-b0abdf7127f2403ff583d224e0d9d4e68c1c5bfc.zip
-more work on DHTU integration
Diffstat (limited to 'src/dht')
-rw-r--r--src/dht/Makefile.am1
-rw-r--r--src/dht/dht_api.c11
-rw-r--r--src/dht/gnunet-service-dht.c149
-rw-r--r--src/dht/gnunet-service-dht.h60
-rw-r--r--src/dht/gnunet-service-dht_clients.c2
-rw-r--r--src/dht/gnunet-service-dht_datacache.c124
-rw-r--r--src/dht/gnunet-service-dht_datacache.h11
-rw-r--r--src/dht/gnunet-service-dht_hello.c154
-rw-r--r--src/dht/gnunet-service-dht_hello.h55
-rw-r--r--src/dht/gnunet-service-dht_neighbours.c1108
-rw-r--r--src/dht/gnunet-service-dht_neighbours.h17
-rw-r--r--src/dht/gnunet-service-dht_routing.c2
12 files changed, 814 insertions, 880 deletions
diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am
index 44439f66f..ab4ec1b3c 100644
--- a/src/dht/Makefile.am
+++ b/src/dht/Makefile.am
@@ -58,7 +58,6 @@ noinst_PROGRAMS = \
58gnunet_service_dht_SOURCES = \ 58gnunet_service_dht_SOURCES = \
59 gnunet-service-dht.c gnunet-service-dht.h \ 59 gnunet-service-dht.c gnunet-service-dht.h \
60 gnunet-service-dht_datacache.c gnunet-service-dht_datacache.h \ 60 gnunet-service-dht_datacache.c gnunet-service-dht_datacache.h \
61 gnunet-service-dht_hello.c gnunet-service-dht_hello.h \
62 gnunet-service-dht_neighbours.c gnunet-service-dht_neighbours.h \ 61 gnunet-service-dht_neighbours.c gnunet-service-dht_neighbours.h \
63 gnunet-service-dht_routing.c gnunet-service-dht_routing.h 62 gnunet-service-dht_routing.c gnunet-service-dht_routing.h
64gnunet_service_dht_LDADD = \ 63gnunet_service_dht_LDADD = \
diff --git a/src/dht/dht_api.c b/src/dht/dht_api.c
index 8389bbb95..a0c30d5e7 100644
--- a/src/dht/dht_api.c
+++ b/src/dht/dht_api.c
@@ -726,6 +726,7 @@ process_client_result (void *cls,
726 const struct GNUNET_DHT_ClientResultMessage *crm = cls; 726 const struct GNUNET_DHT_ClientResultMessage *crm = cls;
727 struct GNUNET_DHT_GetHandle *get_handle = value; 727 struct GNUNET_DHT_GetHandle *get_handle = value;
728 size_t msize = ntohs (crm->header.size) - sizeof(*crm); 728 size_t msize = ntohs (crm->header.size) - sizeof(*crm);
729 uint16_t type = ntohl (crm->type);
729 uint32_t put_path_length = ntohl (crm->put_path_length); 730 uint32_t put_path_length = ntohl (crm->put_path_length);
730 uint32_t get_path_length = ntohl (crm->get_path_length); 731 uint32_t get_path_length = ntohl (crm->get_path_length);
731 const struct GNUNET_DHT_PathElement *put_path; 732 const struct GNUNET_DHT_PathElement *put_path;
@@ -745,7 +746,13 @@ process_client_result (void *cls,
745 (unsigned long long) get_handle->unique_id); 746 (unsigned long long) get_handle->unique_id);
746 return GNUNET_YES; 747 return GNUNET_YES;
747 } 748 }
748 /* FIXME: might want to check that type matches */ 749 if ( (get_handle->type != GNUNET_BLOCK_TYPE_ANY) &&
750 (get_handle->type != type) )
751 {
752 /* type mismatch */
753 GNUNET_break (0);
754 return GNUNET_YES;
755 }
749 meta_length = 756 meta_length =
750 sizeof(struct GNUNET_DHT_PathElement) * (get_path_length + put_path_length); 757 sizeof(struct GNUNET_DHT_PathElement) * (get_path_length + put_path_length);
751 data_length = msize - meta_length; 758 data_length = msize - meta_length;
@@ -786,7 +793,7 @@ process_client_result (void *cls,
786 get_path_length, 793 get_path_length,
787 put_path, 794 put_path,
788 put_path_length, 795 put_path_length,
789 ntohl (crm->type), 796 type,
790 data_length, 797 data_length,
791 data); 798 data);
792 return GNUNET_YES; 799 return GNUNET_YES;
diff --git a/src/dht/gnunet-service-dht.c b/src/dht/gnunet-service-dht.c
index 6f2573d26..35e219926 100644
--- a/src/dht/gnunet-service-dht.c
+++ b/src/dht/gnunet-service-dht.c
@@ -28,14 +28,20 @@
28#include "gnunet_block_lib.h" 28#include "gnunet_block_lib.h"
29#include "gnunet_util_lib.h" 29#include "gnunet_util_lib.h"
30#include "gnunet_hello_lib.h" 30#include "gnunet_hello_lib.h"
31#include "gnunet_hello_uri_lib.h"
31#include "gnunet_dht_service.h" 32#include "gnunet_dht_service.h"
32#include "gnunet_statistics_service.h" 33#include "gnunet_statistics_service.h"
33#include "gnunet-service-dht.h" 34#include "gnunet-service-dht.h"
34#include "gnunet-service-dht_datacache.h" 35#include "gnunet-service-dht_datacache.h"
35#include "gnunet-service-dht_hello.h"
36#include "gnunet-service-dht_neighbours.h" 36#include "gnunet-service-dht_neighbours.h"
37#include "gnunet-service-dht_routing.h" 37#include "gnunet-service-dht_routing.h"
38 38
39/**
40 * How often do we broadcast our HELLO to neighbours if
41 * nothing special happens?
42 */
43#define HELLO_FREQUENCY GNUNET_TIME_UNIT_HOURS
44
39 45
40/** 46/**
41 * Information we keep per underlay. 47 * Information we keep per underlay.
@@ -110,7 +116,27 @@ struct MyAddress
110/** 116/**
111 * Our HELLO 117 * Our HELLO
112 */ 118 */
113struct GNUNET_MessageHeader *GDS_my_hello; 119struct GNUNET_HELLO_Builder *GDS_my_hello;
120
121/**
122 * Identity of this peer.
123 */
124struct GNUNET_PeerIdentity GDS_my_identity;
125
126/**
127 * Hash of the identity of this peer.
128 */
129struct GNUNET_HashCode GDS_my_identity_hash;
130
131/**
132 * Our private key.
133 */
134struct GNUNET_CRYPTO_EddsaPrivateKey GDS_my_private_key;
135
136/**
137 * Task broadcasting our HELLO.
138 */
139static struct GNUNET_SCHEDULER_Task *hello_task;
114 140
115/** 141/**
116 * Handles for the DHT underlays. 142 * Handles for the DHT underlays.
@@ -133,11 +159,6 @@ static struct MyAddress *a_head;
133static struct MyAddress *a_tail; 159static struct MyAddress *a_tail;
134 160
135/** 161/**
136 * Hello address expiration
137 */
138struct GNUNET_TIME_Relative hello_expiration;
139
140/**
141 * log of the current network size estimate, used as the point where 162 * log of the current network size estimate, used as the point where
142 * we switch between random and deterministic routing. 163 * we switch between random and deterministic routing.
143 */ 164 */
@@ -195,13 +216,29 @@ GDS_NSE_get (void)
195 216
196 217
197/** 218/**
198 * Update our HELLO with all of our our addresses. 219 * Task run periodically to broadcast our HELLO.
220 *
221 * @param cls NULL
199 */ 222 */
200static void 223static void
201update_hello (void) 224broadcast_hello (void *cls)
202{ 225{
203 GNUNET_free (GDS_my_hello); 226 struct GNUNET_MessageHeader *hello;
204 // FIXME: build new HELLO properly! 227
228 (void) cls;
229 /* TODO: randomize! */
230 hello_task = GNUNET_SCHEDULER_add_delayed (HELLO_FREQUENCY,
231 &broadcast_hello,
232 NULL);
233 hello = GNUNET_HELLO_builder_to_dht_hello_msg (GDS_my_hello,
234 &GDS_my_private_key);
235 if (NULL == hello)
236 {
237 GNUNET_break (0);
238 return;
239 }
240 GDS_NEIGHBOURS_broadcast (hello);
241 GNUNET_free (hello);
205} 242}
206 243
207 244
@@ -231,7 +268,12 @@ u_address_add (void *cls,
231 a_tail, 268 a_tail,
232 a); 269 a);
233 *ctx = a; 270 *ctx = a;
234 update_hello (); 271 GNUNET_HELLO_builder_add_address (GDS_my_hello,
272 address);
273 if (NULL != hello_task)
274 GNUNET_SCHEDULER_cancel (hello_task);
275 hello_task = GNUNET_SCHEDULER_add_now (&broadcast_hello,
276 NULL);
235} 277}
236 278
237 279
@@ -245,12 +287,47 @@ u_address_del (void *ctx)
245{ 287{
246 struct MyAddress *a = ctx; 288 struct MyAddress *a = ctx;
247 289
290 GNUNET_HELLO_builder_del_address (GDS_my_hello,
291 a->url);
248 GNUNET_CONTAINER_DLL_remove (a_head, 292 GNUNET_CONTAINER_DLL_remove (a_head,
249 a_tail, 293 a_tail,
250 a); 294 a);
251 GNUNET_free (a->url); 295 GNUNET_free (a->url);
252 GNUNET_free (a); 296 GNUNET_free (a);
253 update_hello (); 297 if (NULL != hello_task)
298 GNUNET_SCHEDULER_cancel (hello_task);
299 hello_task = GNUNET_SCHEDULER_add_now (&broadcast_hello,
300 NULL);
301}
302
303
304void
305GDS_u_try_connect (const struct GNUNET_PeerIdentity *pid,
306 const char *address)
307{
308 for (struct Underlay *u = u_head;
309 NULL != u;
310 u = u->next)
311 u->dhtu->try_connect (u->dhtu->cls,
312 pid,
313 address);
314}
315
316
317void
318GDS_u_send (struct Underlay *u,
319 struct GNUNET_DHTU_Target *target,
320 const void *msg,
321 size_t msg_size,
322 GNUNET_SCHEDULER_TaskCallback finished_cb,
323 void *finished_cb_cls)
324{
325 u->dhtu->send (u->dhtu->cls,
326 target,
327 msg,
328 msg_size,
329 finished_cb,
330 finished_cb_cls);
254} 331}
255 332
256 333
@@ -265,7 +342,6 @@ shutdown_task (void *cls)
265 GDS_NEIGHBOURS_done (); 342 GDS_NEIGHBOURS_done ();
266 GDS_DATACACHE_done (); 343 GDS_DATACACHE_done ();
267 GDS_ROUTING_done (); 344 GDS_ROUTING_done ();
268 GDS_HELLO_done ();
269 if (NULL != GDS_block_context) 345 if (NULL != GDS_block_context)
270 { 346 {
271 GNUNET_BLOCK_context_destroy (GDS_block_context); 347 GNUNET_BLOCK_context_destroy (GDS_block_context);
@@ -277,7 +353,7 @@ shutdown_task (void *cls)
277 GNUNET_YES); 353 GNUNET_YES);
278 GDS_stats = NULL; 354 GDS_stats = NULL;
279 } 355 }
280 GNUNET_free (GDS_my_hello); 356 GNUNET_HELLO_builder_free (GDS_my_hello);
281 GDS_my_hello = NULL; 357 GDS_my_hello = NULL;
282 GDS_CLIENTS_stop (); 358 GDS_CLIENTS_stop ();
283} 359}
@@ -348,14 +424,39 @@ run (void *cls,
348{ 424{
349 GDS_cfg = c; 425 GDS_cfg = c;
350 GDS_service = service; 426 GDS_service = service;
351 if (GNUNET_OK !=
352 GNUNET_CONFIGURATION_get_value_time (c,
353 "transport",
354 "HELLO_EXPIRATION",
355 &hello_expiration))
356 { 427 {
357 hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION; 428 char *keyfile;
429
430 if (GNUNET_OK !=
431 GNUNET_CONFIGURATION_get_value_filename (GDS_cfg,
432 "PEER",
433 "PRIVATE_KEY",
434 &keyfile))
435 {
436 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
437 "PEER",
438 "PRIVATE_KEY");
439 GNUNET_SCHEDULER_shutdown ();
440 return;
441 }
442 if (GNUNET_SYSERR ==
443 GNUNET_CRYPTO_eddsa_key_from_file (keyfile,
444 GNUNET_YES,
445 &GDS_my_private_key))
446 {
447 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
448 "Failed to setup peer's private key\n");
449 GNUNET_free (keyfile);
450 GNUNET_SCHEDULER_shutdown ();
451 return;
452 }
453 GNUNET_free (keyfile);
358 } 454 }
455 GNUNET_CRYPTO_eddsa_key_get_public (&GDS_my_private_key,
456 &GDS_my_identity.public_key);
457 GNUNET_CRYPTO_hash (&GDS_my_identity,
458 sizeof(struct GNUNET_PeerIdentity),
459 &GDS_my_identity_hash);
359 GDS_block_context = GNUNET_BLOCK_context_create (GDS_cfg); 460 GDS_block_context = GNUNET_BLOCK_context_create (GDS_cfg);
360 GDS_stats = GNUNET_STATISTICS_create ("dht", 461 GDS_stats = GNUNET_STATISTICS_create ("dht",
361 GDS_cfg); 462 GDS_cfg);
@@ -364,6 +465,12 @@ run (void *cls,
364 GDS_DATACACHE_init (); 465 GDS_DATACACHE_init ();
365 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, 466 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
366 NULL); 467 NULL);
468 if (GNUNET_OK !=
469 GDS_NEIGHBOURS_init ())
470 {
471 GNUNET_SCHEDULER_shutdown ();
472 return;
473 }
367 GNUNET_CONFIGURATION_iterate_sections (GDS_cfg, 474 GNUNET_CONFIGURATION_iterate_sections (GDS_cfg,
368 &load_underlay, 475 &load_underlay,
369 NULL); 476 NULL);
diff --git a/src/dht/gnunet-service-dht.h b/src/dht/gnunet-service-dht.h
index 687e2d4d3..403b3f5a1 100644
--- a/src/dht/gnunet-service-dht.h
+++ b/src/dht/gnunet-service-dht.h
@@ -27,6 +27,7 @@
27#define GNUNET_SERVICE_DHT_H 27#define GNUNET_SERVICE_DHT_H
28 28
29#include "gnunet-service-dht_datacache.h" 29#include "gnunet-service-dht_datacache.h"
30#include "gnunet-service-dht_neighbours.h"
30#include "gnunet_statistics_service.h" 31#include "gnunet_statistics_service.h"
31#include "gnunet_transport_service.h" 32#include "gnunet_transport_service.h"
32 33
@@ -34,6 +35,11 @@
34#define DEBUG_DHT GNUNET_EXTRA_LOGGING 35#define DEBUG_DHT GNUNET_EXTRA_LOGGING
35 36
36/** 37/**
38 * Information we keep per underlay.
39 */
40struct Underlay;
41
42/**
37 * Configuration we use. 43 * Configuration we use.
38 */ 44 */
39extern const struct GNUNET_CONFIGURATION_Handle *GDS_cfg; 45extern const struct GNUNET_CONFIGURATION_Handle *GDS_cfg;
@@ -54,9 +60,59 @@ extern struct GNUNET_BLOCK_Context *GDS_block_context;
54extern struct GNUNET_STATISTICS_Handle *GDS_stats; 60extern struct GNUNET_STATISTICS_Handle *GDS_stats;
55 61
56/** 62/**
57 * Our HELLO 63 * Our HELLO builder.
64 */
65extern struct GNUNET_HELLO_Builder *GDS_my_hello;
66
67/**
68 * Identity of this peer.
69 */
70extern struct GNUNET_PeerIdentity GDS_my_identity;
71
72/**
73 * Hash of the identity of this peer.
74 */
75extern struct GNUNET_HashCode GDS_my_identity_hash;
76
77/**
78 * Our private key.
58 */ 79 */
59extern struct GNUNET_MessageHeader *GDS_my_hello; 80extern struct GNUNET_CRYPTO_EddsaPrivateKey GDS_my_private_key;
81
82
83/**
84 * Ask all underlays to connect to peer @a pid at @a address.
85 *
86 * @param pid identity of the peer we would connect to
87 * @param address an address of @a pid
88 */
89void
90GDS_u_try_connect (const struct GNUNET_PeerIdentity *pid,
91 const char *address);
92
93
94/**
95 * Send message to some other participant over the network. Note that
96 * sending is not guaranteeing that the other peer actually received the
97 * message. For any given @a target, the DHT must wait for the @a
98 * finished_cb to be called before calling send() again.
99 *
100 * @param u underlay to use for transmission
101 * @param target receiver identification
102 * @param msg message
103 * @param msg_size number of bytes in @a msg
104 * @param finished_cb function called once transmission is done
105 * (not called if @a target disconnects, then only the
106 * disconnect_cb is called).
107 * @param finished_cb_cls closure for @a finished_cb
108 */
109void
110GDS_u_send (struct Underlay *u,
111 struct GNUNET_DHTU_Target *target,
112 const void *msg,
113 size_t msg_size,
114 GNUNET_SCHEDULER_TaskCallback finished_cb,
115 void *finished_cb_cls);
60 116
61 117
62/** 118/**
diff --git a/src/dht/gnunet-service-dht_clients.c b/src/dht/gnunet-service-dht_clients.c
index a1c3024de..bc39e004a 100644
--- a/src/dht/gnunet-service-dht_clients.c
+++ b/src/dht/gnunet-service-dht_clients.c
@@ -917,7 +917,7 @@ forward_reply (void *cls,
917 GNUNET_NO); 917 GNUNET_NO);
918 return GNUNET_YES; /* type mismatch */ 918 return GNUNET_YES; /* type mismatch */
919 } 919 }
920 if ( (0 == (record->msg_options & GNUNET_DHT_RO_FIND_PEER)) && 920 if ( (0 == (record->msg_options & GNUNET_DHT_RO_FIND_APPROXIMATE)) &&
921 (0 != GNUNET_memcmp (&frc->bd->key, 921 (0 != GNUNET_memcmp (&frc->bd->key,
922 query_hash)) ) 922 query_hash)) )
923 { 923 {
diff --git a/src/dht/gnunet-service-dht_datacache.c b/src/dht/gnunet-service-dht_datacache.c
index cb778717b..880c72cb2 100644
--- a/src/dht/gnunet-service-dht_datacache.c
+++ b/src/dht/gnunet-service-dht_datacache.c
@@ -68,7 +68,7 @@ GDS_DATACACHE_handle_put (const struct GDS_DATACACHE_BlockData *bd)
68 1, 68 1,
69 GNUNET_NO); 69 GNUNET_NO);
70 GNUNET_CRYPTO_hash_xor (&bd->key, 70 GNUNET_CRYPTO_hash_xor (&bd->key,
71 &my_identity_hash, 71 &GDS_my_identity_hash,
72 &xor); 72 &xor);
73 r = GNUNET_DATACACHE_put (datacache, 73 r = GNUNET_DATACACHE_put (datacache,
74 &bd->key, 74 &bd->key,
@@ -231,7 +231,15 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
231 GDS_DATACACHE_GetCallback gc, 231 GDS_DATACACHE_GetCallback gc,
232 void *gc_cls) 232 void *gc_cls)
233{ 233{
234 struct GetRequestContext ctx; 234 struct GetRequestContext ctx = {
235 .eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID,
236 .key = *key,
237 .xquery = xquery,
238 .xquery_size = xquery_size,
239 .bg = bg,
240 .gc = gc,
241 .gc_cls = gc_cls
242 };
235 unsigned int r; 243 unsigned int r;
236 244
237 if (NULL == datacache) 245 if (NULL == datacache)
@@ -240,13 +248,6 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
240 "# GET requests given to datacache", 248 "# GET requests given to datacache",
241 1, 249 1,
242 GNUNET_NO); 250 GNUNET_NO);
243 ctx.eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
244 ctx.key = *key;
245 ctx.xquery = xquery;
246 ctx.xquery_size = xquery_size;
247 ctx.bg = bg;
248 ctx.gc = gc;
249 ctx.gc_cls = gc_cls;
250 r = GNUNET_DATACACHE_get (datacache, 251 r = GNUNET_DATACACHE_get (datacache,
251 key, 252 key,
252 type, 253 type,
@@ -261,85 +262,44 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
261} 262}
262 263
263 264
264/** 265enum GNUNET_BLOCK_EvaluationResult
265 * Closure for #datacache_get_successors_iterator().
266 */
267struct SuccContext
268{
269 /**
270 * Function to call on the result
271 */
272 GDS_DATACACHE_GetCallback cb;
273
274 /**
275 * Closure for @e cb.
276 */
277 void *cb_cls;
278
279};
280
281
282/**
283 * Iterator for local get request results,
284 *
285 * @param cls closure with the `struct GNUNET_HashCode *` with the trail ID
286 * @param key the key this data is stored under
287 * @param size the size of the data identified by key
288 * @param data the actual data
289 * @param type the type of the data
290 * @param exp when does this value expire?
291 * @param put_path_length number of peers in @a put_path
292 * @param put_path path the reply took on put
293 * @return #GNUNET_OK to continue iteration, anything else
294 * to stop iteration.
295 */
296static enum GNUNET_GenericReturnValue
297datacache_get_successors_iterator (void *cls,
298 const struct GNUNET_HashCode *key,
299 size_t size,
300 const char *data,
301 enum GNUNET_BLOCK_Type type,
302 struct GNUNET_TIME_Absolute exp,
303 unsigned int put_path_length,
304 const struct
305 GNUNET_DHT_PathElement *put_path)
306{
307 const struct SuccContext *sc = cls;
308 struct GDS_DATACACHE_BlockData bd = {
309 .key = *key,
310 .expiration_time = exp,
311 .put_path = put_path,
312 .data = data,
313 .data_size = size,
314 .put_path_length = put_path_length,
315 .type = type
316 };
317
318 /* NOTE: The datacache currently does not store the RO from
319 the original 'put', so we don't know the 'correct' option
320 at this point anymore. Thus, we conservatively assume
321 that recording is desired (for now). */
322 sc->cb (sc->cb_cls,
323 &bd);
324 return GNUNET_OK;
325}
326
327
328void
329GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key, 266GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key,
267 enum GNUNET_BLOCK_Type type,
268 const void *xquery,
269 size_t xquery_size,
270 struct GNUNET_BLOCK_Group *bg,
330 GDS_DATACACHE_GetCallback cb, 271 GDS_DATACACHE_GetCallback cb,
331 void *cb_cls) 272 void *cb_cls)
332{ 273{
333 struct SuccContext sc = { 274 struct GetRequestContext ctx = {
334 .cb = cb, 275 .eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID,
335 .cb_cls = cb_cls 276 .key = *key,
277 .xquery = xquery,
278 .xquery_size = xquery_size,
279 .bg = bg,
280 .gc = cb,
281 .gc_cls = cb_cls
336 }; 282 };
283 unsigned int r;
337 284
338 (void) GNUNET_DATACACHE_get_closest (datacache, 285 if (NULL == datacache)
339 key, 286 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
340 NUM_CLOSEST, 287 GNUNET_STATISTICS_update (GDS_stats,
341 &datacache_get_successors_iterator, 288 "# GET closest requests given to datacache",
342 &sc); 289 1,
290 GNUNET_NO);
291 r = GNUNET_DATACACHE_get_closest (datacache,
292 key,
293 type,
294 NUM_CLOSEST,
295 &datacache_get_iterator,
296 &ctx);
297 LOG (GNUNET_ERROR_TYPE_DEBUG,
298 "DATACACHE approximate GET for key %s completed (%d). %u results found.\n",
299 GNUNET_h2s (key),
300 ctx.eval,
301 r);
302 return ctx.eval;
343} 303}
344 304
345 305
diff --git a/src/dht/gnunet-service-dht_datacache.h b/src/dht/gnunet-service-dht_datacache.h
index 691a51e0e..69a18c605 100644
--- a/src/dht/gnunet-service-dht_datacache.h
+++ b/src/dht/gnunet-service-dht_datacache.h
@@ -122,11 +122,20 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
122 * another peer. 122 * another peer.
123 * 123 *
124 * @param key the location at which the peer is looking for data that is close 124 * @param key the location at which the peer is looking for data that is close
125 * @param type requested data type
126 * @param xquery extended query
127 * @param xquery_size number of bytes in xquery
128 * @param bg block group to use for evaluation of replies
125 * @param cb function to call with the result 129 * @param cb function to call with the result
126 * @param cb_cls closure for @a cb 130 * @param cb_cls closure for @a cb
131 * @return evaluation result for the local replies
127 */ 132 */
128void 133enum GNUNET_BLOCK_EvaluationResult
129GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key, 134GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key,
135 enum GNUNET_BLOCK_Type type,
136 const void *xquery,
137 size_t xquery_size,
138 struct GNUNET_BLOCK_Group *bg,
130 GDS_DATACACHE_GetCallback cb, 139 GDS_DATACACHE_GetCallback cb,
131 void *cb_cls); 140 void *cb_cls);
132 141
diff --git a/src/dht/gnunet-service-dht_hello.c b/src/dht/gnunet-service-dht_hello.c
deleted file mode 100644
index 949456575..000000000
--- a/src/dht/gnunet-service-dht_hello.c
+++ /dev/null
@@ -1,154 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V.
4
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.
9
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.
14
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/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file dht/gnunet-service-dht_hello.c
23 * @brief GNUnet DHT integration with peerinfo
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - consider adding mechanism to remove expired HELLOs
28 */
29#include "platform.h"
30#include "gnunet-service-dht.h"
31#include "gnunet-service-dht_hello.h"
32#include "gnunet_peerinfo_service.h"
33
34
35/**
36 * Handle for peerinfo notifications.
37 */
38static struct GNUNET_PEERINFO_NotifyContext *pnc;
39
40/**
41 * Hash map of peers to HELLOs.
42 */
43static struct GNUNET_CONTAINER_MultiPeerMap *peer_to_hello;
44
45
46/**
47 * Obtain a peer's HELLO if available
48 *
49 * @param peer peer to look for a HELLO from
50 * @return HELLO for the given peer
51 */
52const struct GNUNET_HELLO_Message *
53GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer)
54{
55 if (NULL == peer_to_hello)
56 return NULL;
57 return GNUNET_CONTAINER_multipeermap_get (peer_to_hello,
58 peer);
59}
60
61
62/**
63 * Function called for each HELLO known to PEERINFO.
64 *
65 * @param cls closure
66 * @param peer id of the peer, NULL for last call
67 * @param hello hello message for the peer (can be NULL)
68 * @param err_msg error message (not used)
69 *
70 * FIXME this is called once per address. Merge instead of replacing?
71 */
72static void
73process_hello (void *cls,
74 const struct GNUNET_PeerIdentity *peer,
75 const struct GNUNET_HELLO_Message *hello,
76 const char *err_msg)
77{
78 struct GNUNET_TIME_Absolute ex;
79 struct GNUNET_HELLO_Message *hm;
80
81 if (NULL == hello)
82 return;
83 ex = GNUNET_HELLO_get_last_expiration (hello);
84 if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us)
85 return;
86 GNUNET_STATISTICS_update (GDS_stats,
87 "# HELLOs obtained from peerinfo",
88 1,
89 GNUNET_NO);
90 hm = GNUNET_CONTAINER_multipeermap_get (peer_to_hello,
91 peer);
92 GNUNET_free (hm);
93 hm = GNUNET_malloc (GNUNET_HELLO_size (hello));
94 GNUNET_memcpy (hm,
95 hello,
96 GNUNET_HELLO_size (hello));
97 GNUNET_assert (GNUNET_SYSERR !=
98 GNUNET_CONTAINER_multipeermap_put (peer_to_hello,
99 peer,
100 hm,
101 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
102}
103
104
105/**
106 * Initialize HELLO subsystem.
107 */
108void
109GDS_HELLO_init ()
110{
111 pnc = GNUNET_PEERINFO_notify (GDS_cfg,
112 GNUNET_NO,
113 &process_hello,
114 NULL);
115 peer_to_hello = GNUNET_CONTAINER_multipeermap_create (256,
116 GNUNET_NO);
117}
118
119
120/**
121 * Free memory occopied by the HELLO.
122 */
123static enum GNUNET_GenericReturnValue
124free_hello (void *cls,
125 const struct GNUNET_PeerIdentity *key,
126 void *hello)
127{
128 GNUNET_free (hello);
129 return GNUNET_OK;
130}
131
132
133/**
134 * Shutdown HELLO subsystem.
135 */
136void
137GDS_HELLO_done ()
138{
139 if (NULL != pnc)
140 {
141 GNUNET_PEERINFO_notify_cancel (pnc);
142 pnc = NULL;
143 }
144 if (NULL != peer_to_hello)
145 {
146 GNUNET_CONTAINER_multipeermap_iterate (peer_to_hello,
147 &free_hello,
148 NULL);
149 GNUNET_CONTAINER_multipeermap_destroy (peer_to_hello);
150 }
151}
152
153
154/* end of gnunet-service-dht_hello.c */
diff --git a/src/dht/gnunet-service-dht_hello.h b/src/dht/gnunet-service-dht_hello.h
deleted file mode 100644
index f8b90862d..000000000
--- a/src/dht/gnunet-service-dht_hello.h
+++ /dev/null
@@ -1,55 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V.
4
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.
9
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.
14
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/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file dht/gnunet-service-dht_hello.h
23 * @brief GNUnet DHT integration with peerinfo
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_DHT_HELLO_H
27#define GNUNET_SERVICE_DHT_HELLO_H
28
29#include "gnunet_util_lib.h"
30#include "gnunet_hello_lib.h"
31
32/**
33 * Obtain a peer's HELLO if available
34 *
35 * @param peer peer to look for a HELLO from
36 * @return HELLO for the given peer
37 */
38const struct GNUNET_HELLO_Message *
39GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer);
40
41
42/**
43 * Initialize HELLO subsystem.
44 */
45void
46GDS_HELLO_init (void);
47
48
49/**
50 * Shutdown HELLO subsystem.
51 */
52void
53GDS_HELLO_done (void);
54
55#endif
diff --git a/src/dht/gnunet-service-dht_neighbours.c b/src/dht/gnunet-service-dht_neighbours.c
index bc473df69..b7b5e8097 100644
--- a/src/dht/gnunet-service-dht_neighbours.c
+++ b/src/dht/gnunet-service-dht_neighbours.c
@@ -29,8 +29,8 @@
29#include "gnunet_protocols.h" 29#include "gnunet_protocols.h"
30#include "gnunet_signatures.h" 30#include "gnunet_signatures.h"
31#include "gnunet_hello_lib.h" 31#include "gnunet_hello_lib.h"
32#include "gnunet_hello_uri_lib.h"
32#include "gnunet-service-dht.h" 33#include "gnunet-service-dht.h"
33#include "gnunet-service-dht_hello.h"
34#include "gnunet-service-dht_neighbours.h" 34#include "gnunet-service-dht_neighbours.h"
35#include "gnunet-service-dht_routing.h" 35#include "gnunet-service-dht_routing.h"
36#include "dht.h" 36#include "dht.h"
@@ -88,11 +88,6 @@
88 */ 88 */
89#define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2) 89#define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
90 90
91/**
92 * Hello address expiration
93 */
94extern struct GNUNET_TIME_Relative hello_expiration;
95
96 91
97GNUNET_NETWORK_STRUCT_BEGIN 92GNUNET_NETWORK_STRUCT_BEGIN
98 93
@@ -260,81 +255,129 @@ GNUNET_NETWORK_STRUCT_END
260/** 255/**
261 * Entry for a peer in a bucket. 256 * Entry for a peer in a bucket.
262 */ 257 */
263struct PeerInfo 258struct PeerInfo;
259
260
261/**
262 * List of targets that we can use to reach this peer.
263 */
264struct Target
264{ 265{
265 /** 266 /**
266 * Next peer entry (DLL) 267 * Kept in a DLL.
267 */ 268 */
268 struct PeerInfo *next; 269 struct Target *next;
269 270
270 /** 271 /**
271 * Prev peer entry (DLL) 272 * Kept in a DLL.
272 */ 273 */
273 struct PeerInfo *prev; 274 struct Target *prev;
274 275
275 /** 276 /**
276 * Handle for sending messages to this peer. 277 * Handle for sending messages to this peer.
277 */ 278 */
278 struct GNUNET_DHTU_Target *target; 279 struct GNUNET_DHTU_Target *utarget;
279 280
280 /** 281 /**
281 * What is the identity of the peer? 282 * Underlay providing this target.
282 */ 283 */
283 struct GNUNET_PeerIdentity id; 284 struct Underlay *u;
284 285
285 /** 286 /**
286 * Hash of @e id. 287 * Peer this is a target for.
287 */ 288 */
288 struct GNUNET_HashCode phash; 289 struct PeerInfo *pi;
289 290
290 /** 291 /**
291 * Which bucket is this peer in? 292 * Set to number of messages are waiting for the transmission to finish.
292 */ 293 */
293 int peer_bucket; 294 unsigned int load;
295
296 /**
297 * Set to @a true if the target was dropped, but we could not clean
298 * up yet because @e busy was also true.
299 */
300 bool dropped;
301
294}; 302};
295 303
296 304
297/** 305/**
298 * Peers are grouped into buckets. 306 * Entry for a peer in a bucket.
299 */ 307 */
300struct PeerBucket 308struct PeerInfo
301{ 309{
302 /** 310 /**
303 * Head of DLL 311 * What is the identity of the peer?
304 */ 312 */
305 struct PeerInfo *head; 313 struct GNUNET_PeerIdentity id;
306 314
307 /** 315 /**
308 * Tail of DLL 316 * Hash of @e id.
309 */ 317 */
310 struct PeerInfo *tail; 318 struct GNUNET_HashCode phash;
311 319
312 /** 320 /**
313 * Number of peers in the bucket. 321 * When does our HELLO from this peer expire?
314 */ 322 */
315 unsigned int peers_size; 323 struct GNUNET_TIME_Absolute hello_expiration;
324
325 /**
326 * Next peer entry (DLL)
327 */
328 struct PeerInfo *next;
329
330 /**
331 * Prev peer entry (DLL)
332 */
333 struct PeerInfo *prev;
334
335 /**
336 * Head of DLL of targets for this peer.
337 */
338 struct Target *t_head;
339
340 /**
341 * Tail of DLL of targets for this peer.
342 */
343 struct Target *t_tail;
344
345 /**
346 * Block with a HELLO of this peer.
347 */
348 void *hello;
349
350 /**
351 * Number of bytes in @e hello.
352 */
353 size_t hello_size;
354
355 /**
356 * Which bucket is this peer in?
357 */
358 int peer_bucket;
316}; 359};
317 360
318 361
319/** 362/**
320 * Information about a peer that we would like to connect to. 363 * Peers are grouped into buckets.
321 */ 364 */
322struct ConnectInfo 365struct PeerBucket
323{ 366{
324 /** 367 /**
325 * Handle to active HELLO offer operation, or NULL. 368 * Head of DLL
326 */ 369 */
327 struct GNUNET_TRANSPORT_OfferHelloHandle *oh; 370 struct PeerInfo *head;
328 371
329 /** 372 /**
330 * Handle to active connectivity suggestion operation, or NULL. 373 * Tail of DLL
331 */ 374 */
332 struct GNUNET_DHTU_PreferenceHandle *ph; 375 struct PeerInfo *tail;
333 376
334 /** 377 /**
335 * How much would we like to connect to this peer? 378 * Number of peers in the bucket.
336 */ 379 */
337 uint32_t strength; 380 unsigned int peers_size;
338}; 381};
339 382
340 383
@@ -371,12 +414,6 @@ static struct PeerBucket k_buckets[MAX_BUCKETS];
371static struct GNUNET_CONTAINER_MultiPeerMap *all_connected_peers; 414static struct GNUNET_CONTAINER_MultiPeerMap *all_connected_peers;
372 415
373/** 416/**
374 * Hash map of all peers we would like to be connected to.
375 * Values are of type `struct ConnectInfo`.
376 */
377static struct GNUNET_CONTAINER_MultiPeerMap *all_desired_peers;
378
379/**
380 * Maximum size for each bucket. 417 * Maximum size for each bucket.
381 */ 418 */
382static unsigned int bucket_size = DEFAULT_BUCKET_SIZE; 419static unsigned int bucket_size = DEFAULT_BUCKET_SIZE;
@@ -386,20 +423,83 @@ static unsigned int bucket_size = DEFAULT_BUCKET_SIZE;
386 */ 423 */
387static struct GNUNET_SCHEDULER_Task *find_peer_task; 424static struct GNUNET_SCHEDULER_Task *find_peer_task;
388 425
389/**
390 * Identity of this peer.
391 */
392static struct GNUNET_PeerIdentity my_identity;
393 426
394/** 427/**
395 * Hash of the identity of this peer. 428 * Function called whenever we finished sending to a target.
429 * Marks the transmission as finished (and the target as ready
430 * for the next message).
431 *
432 * @param cls a `struct Target *`
396 */ 433 */
397struct GNUNET_HashCode my_identity_hash; 434static void
435send_done_cb (void *cls)
436{
437 struct Target *t = cls;
438 struct PeerInfo *pi = t->pi; /* NULL if t->dropped! */
439
440 GNUNET_assert (t->load > 0);
441 t->load--;
442 if (0 < t->load)
443 return;
444 if (t->dropped)
445 {
446 GNUNET_free (t);
447 return;
448 }
449 /* move target back to the front */
450 GNUNET_CONTAINER_DLL_remove (pi->t_head,
451 pi->t_tail,
452 t);
453 GNUNET_CONTAINER_DLL_insert (pi->t_head,
454 pi->t_tail,
455 t);
456}
457
398 458
399/** 459/**
400 * Our private key. 460 * Send @a msg to @a pi.
461 *
462 * @param pi where to send the message
463 * @param msg message to send
401 */ 464 */
402static struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key; 465static void
466do_send (struct PeerInfo *pi,
467 const struct GNUNET_MessageHeader *msg)
468{
469 struct Target *t;
470
471 for (t = pi->t_head;
472 NULL != t;
473 t = t->next)
474 if (t->load < MAXIMUM_PENDING_PER_PEER)
475 break;
476 if (NULL == t)
477 {
478 /* all targets busy, drop message */
479 GNUNET_STATISTICS_update (GDS_stats,
480 "# messages dropped (underlays busy)",
481 1,
482 GNUNET_NO);
483 return;
484 }
485 t->load++;
486 /* rotate busy targets to the end */
487 if (MAXIMUM_PENDING_PER_PEER == t->load)
488 {
489 GNUNET_CONTAINER_DLL_remove (pi->t_head,
490 pi->t_tail,
491 t);
492 GNUNET_CONTAINER_DLL_insert_tail (pi->t_head,
493 pi->t_tail,
494 t);
495 }
496 GDS_u_send (t->u,
497 t->utarget,
498 msg,
499 ntohs (msg->size),
500 &send_done_cb,
501 t);
502}
403 503
404 504
405/** 505/**
@@ -436,7 +536,7 @@ sign_path (const struct GNUNET_HashCode *key,
436 GNUNET_CRYPTO_hash (data, 536 GNUNET_CRYPTO_hash (data,
437 data_size, 537 data_size,
438 &hs.h_data); 538 &hs.h_data);
439 GNUNET_CRYPTO_eddsa_sign (&my_private_key, 539 GNUNET_CRYPTO_eddsa_sign (&GDS_my_private_key,
440 &hs, 540 &hs,
441 sig); 541 sig);
442} 542}
@@ -456,7 +556,7 @@ find_bucket (const struct GNUNET_HashCode *hc)
456 unsigned int bits; 556 unsigned int bits;
457 557
458 GNUNET_CRYPTO_hash_xor (hc, 558 GNUNET_CRYPTO_hash_xor (hc,
459 &my_identity_hash, 559 &GDS_my_identity_hash,
460 &xor); 560 &xor);
461 bits = GNUNET_CRYPTO_hash_count_leading_zeros (&xor); 561 bits = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
462 if (bits == MAX_BUCKETS) 562 if (bits == MAX_BUCKETS)
@@ -470,175 +570,6 @@ find_bucket (const struct GNUNET_HashCode *hc)
470 570
471 571
472/** 572/**
473 * Function called when #GNUNET_TRANSPORT_offer_hello() is done.
474 * Clean up the "oh" field in the @a cls
475 *
476 * @param cls a `struct ConnectInfo`
477 */
478static void
479offer_hello_done (void *cls)
480{
481 struct ConnectInfo *ci = cls;
482
483 ci->oh = NULL;
484}
485
486
487/**
488 * Function called for all entries in #all_desired_peers to clean up.
489 *
490 * @param cls NULL
491 * @param peer peer the entry is for
492 * @param value the value to remove
493 * @return #GNUNET_YES
494 */
495static enum GNUNET_GenericReturnValue
496free_connect_info (void *cls,
497 const struct GNUNET_PeerIdentity *peer,
498 void *value)
499{
500 struct ConnectInfo *ci = value;
501
502 (void) cls;
503 GNUNET_assert (GNUNET_YES ==
504 GNUNET_CONTAINER_multipeermap_remove (all_desired_peers,
505 peer,
506 ci));
507 if (NULL != ci->ph)
508 {
509 // ci->u->drop (ci->ph); // FIXME!
510 ci->ph = NULL;
511 }
512 if (NULL != ci->oh)
513 {
514 GNUNET_TRANSPORT_offer_hello_cancel (ci->oh);
515 ci->oh = NULL;
516 }
517 GNUNET_free (ci);
518 return GNUNET_YES;
519}
520
521
522/**
523 * Consider if we want to connect to a given peer, and if so
524 * let ATS know. If applicable, the HELLO is offered to the
525 * TRANSPORT service.
526 *
527 * @param pid peer to consider connectivity requirements for
528 * @param h a HELLO message, or NULL
529 */
530static void
531try_connect (const struct GNUNET_PeerIdentity *pid,
532 const struct GNUNET_MessageHeader *h)
533{
534 int bucket_idx;
535 struct GNUNET_HashCode pid_hash;
536 struct ConnectInfo *ci;
537 uint32_t strength;
538 struct PeerBucket *bucket;
539
540 GNUNET_CRYPTO_hash (pid,
541 sizeof(struct GNUNET_PeerIdentity),
542 &pid_hash);
543 bucket_idx = find_bucket (&pid_hash);
544 if (bucket_idx < 0)
545 {
546 GNUNET_break (0);
547 return; /* self!? */
548 }
549 bucket = &k_buckets[bucket_idx];
550 ci = GNUNET_CONTAINER_multipeermap_get (all_desired_peers,
551 pid);
552 if (bucket->peers_size < bucket_size)
553 strength = (bucket_size - bucket->peers_size) * bucket_idx;
554 else
555 strength = 0;
556 if (GNUNET_YES ==
557 GNUNET_CONTAINER_multipeermap_contains (all_connected_peers,
558 pid))
559 strength *= 2; /* double for connected peers */
560 if ( (0 == strength) &&
561 (NULL != ci) )
562 {
563 /* release request */
564 GNUNET_assert (GNUNET_YES ==
565 free_connect_info (NULL,
566 pid,
567 ci));
568 return;
569 }
570 if (NULL == ci)
571 {
572 ci = GNUNET_new (struct ConnectInfo);
573 GNUNET_assert (GNUNET_OK ==
574 GNUNET_CONTAINER_multipeermap_put (all_desired_peers,
575 pid,
576 ci,
577 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
578 }
579 if ( (NULL != ci->oh) &&
580 (NULL != h) )
581 GNUNET_TRANSPORT_offer_hello_cancel (ci->oh);
582 if (NULL != h)
583 ci->oh = GNUNET_TRANSPORT_offer_hello (GDS_cfg,
584 h,
585 &offer_hello_done,
586 ci);
587 if ( (NULL != ci->ph) &&
588 (ci->strength != strength) )
589 {
590 // ci->u_api->drop (ci->ph);
591 ci->ph = NULL;
592 }
593 if (ci->strength != strength)
594 {
595#if FIXME
596 ci->ph = ci->u_api->hold (ci->u_api->cls,
597 TARGET);
598#endif
599 ci->strength = strength;
600 }
601}
602
603
604/**
605 * Function called for each peer in #all_desired_peers during
606 * #update_connect_preferences() if we have reason to adjust
607 * the strength of our desire to keep connections to certain
608 * peers. Calls #try_connect() to update the calculations for
609 * the given @a pid.
610 *
611 * @param cls NULL
612 * @param pid peer to update
613 * @param value unused
614 * @return #GNUNET_YES (continue to iterate)
615 */
616static enum GNUNET_GenericReturnValue
617update_desire_strength (void *cls,
618 const struct GNUNET_PeerIdentity *pid,
619 void *value)
620{
621 (void) cls;
622 (void) value;
623 try_connect (pid,
624 NULL);
625 return GNUNET_YES;
626}
627
628
629/**
630 * Update our preferences for connectivity as given to ATS.
631 */
632static void
633update_connect_preferences (void)
634{
635 GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers,
636 &update_desire_strength,
637 NULL);
638}
639
640
641/**
642 * Add each of the peers we already know to the Bloom filter of 573 * Add each of the peers we already know to the Bloom filter of
643 * the request so that we don't get duplicate HELLOs. 574 * the request so that we don't get duplicate HELLOs.
644 * 575 *
@@ -728,11 +659,11 @@ send_find_peer_message (void *cls)
728 GNUNET_CONSTANTS_BLOOMFILTER_K); 659 GNUNET_CONSTANTS_BLOOMFILTER_K);
729 if (GNUNET_OK != 660 if (GNUNET_OK !=
730 GDS_NEIGHBOURS_handle_get (GNUNET_BLOCK_TYPE_DHT_URL_HELLO, 661 GDS_NEIGHBOURS_handle_get (GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
731 GNUNET_DHT_RO_FIND_PEER 662 GNUNET_DHT_RO_FIND_APPROXIMATE
732 | GNUNET_DHT_RO_RECORD_ROUTE, 663 | GNUNET_DHT_RO_RECORD_ROUTE,
733 FIND_PEER_REPLICATION_LEVEL, 664 FIND_PEER_REPLICATION_LEVEL,
734 0, /* hop count */ 665 0, /* hop count */
735 &my_identity_hash, 666 &GDS_my_identity_hash,
736 NULL, 0, /* xquery */ 667 NULL, 0, /* xquery */
737 bg, 668 bg,
738 peer_bf)) 669 peer_bf))
@@ -761,106 +692,131 @@ GDS_u_connect (void *cls,
761 const struct GNUNET_PeerIdentity *pid, 692 const struct GNUNET_PeerIdentity *pid,
762 void **ctx) 693 void **ctx)
763{ 694{
695 struct Underlay *u = cls;
764 struct PeerInfo *pi; 696 struct PeerInfo *pi;
765 struct PeerBucket *bucket; 697 struct PeerBucket *bucket;
766 698
767 (void) cls;
768 /* Check for connect to self message */ 699 /* Check for connect to self message */
769 if (0 == GNUNET_memcmp (&my_identity, 700 if (0 == GNUNET_memcmp (&GDS_my_identity,
770 pid)) 701 pid))
771 return; 702 return;
772 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 703 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
773 "Connected to peer %s\n", 704 "Connected to peer %s\n",
774 GNUNET_i2s (pid)); 705 GNUNET_i2s (pid));
775 GNUNET_assert (NULL == 706 pi = GNUNET_CONTAINER_multipeermap_get (all_connected_peers,
776 GNUNET_CONTAINER_multipeermap_get (all_connected_peers, 707 pid);
777 pid)); 708 if (NULL == pi)
778 GNUNET_STATISTICS_update (GDS_stats,
779 "# peers connected",
780 1,
781 GNUNET_NO);
782 pi = GNUNET_new (struct PeerInfo);
783 pi->id = *pid;
784 pi->target = target;
785 GNUNET_CRYPTO_hash (pid,
786 sizeof(*pid),
787 &pi->phash);
788 pi->peer_bucket = find_bucket (&pi->phash);
789 GNUNET_assert ( (pi->peer_bucket >= 0) &&
790 ((unsigned int) pi->peer_bucket < MAX_BUCKETS));
791 bucket = &k_buckets[pi->peer_bucket];
792 GNUNET_CONTAINER_DLL_insert_tail (bucket->head,
793 bucket->tail,
794 pi);
795 bucket->peers_size++;
796 closest_bucket = GNUNET_MAX (closest_bucket,
797 (unsigned int) pi->peer_bucket + 1);
798 GNUNET_assert (GNUNET_OK ==
799 GNUNET_CONTAINER_multipeermap_put (all_connected_peers,
800 &pi->id,
801 pi,
802 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
803 if (bucket->peers_size <= bucket_size)
804 { 709 {
805 update_connect_preferences (); 710 GNUNET_STATISTICS_update (GDS_stats,
806 newly_found_peers++; 711 "# peers connected",
712 1,
713 GNUNET_NO);
714 pi = GNUNET_new (struct PeerInfo);
715 pi->id = *pid;
716 GNUNET_CRYPTO_hash (pid,
717 sizeof(*pid),
718 &pi->phash);
719 pi->peer_bucket = find_bucket (&pi->phash);
720 GNUNET_assert ( (pi->peer_bucket >= 0) &&
721 ((unsigned int) pi->peer_bucket < MAX_BUCKETS));
722 bucket = &k_buckets[pi->peer_bucket];
723 GNUNET_CONTAINER_DLL_insert_tail (bucket->head,
724 bucket->tail,
725 pi);
726 bucket->peers_size++;
727 closest_bucket = GNUNET_MAX (closest_bucket,
728 (unsigned int) pi->peer_bucket + 1);
729 GNUNET_assert (GNUNET_OK ==
730 GNUNET_CONTAINER_multipeermap_put (all_connected_peers,
731 &pi->id,
732 pi,
733 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
734 if (bucket->peers_size <= bucket_size)
735 {
736 newly_found_peers++;
737 // FIXME: call 'hold'!
738 }
739 if ( (1 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
740 (GNUNET_YES != disable_try_connect) )
741 {
742 /* got a first connection, good time to start with FIND PEER requests... */
743 GNUNET_assert (NULL == find_peer_task);
744 find_peer_task = GNUNET_SCHEDULER_add_now (&send_find_peer_message,
745 NULL);
746 }
807 } 747 }
808 if ( (1 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
809 (GNUNET_YES != disable_try_connect) )
810 { 748 {
811 /* got a first connection, good time to start with FIND PEER requests... */ 749 struct Target *t;
812 GNUNET_assert (NULL == find_peer_task); 750
813 find_peer_task = GNUNET_SCHEDULER_add_now (&send_find_peer_message, 751 t = GNUNET_new (struct Target);
814 NULL); 752 t->u = u;
753 t->utarget = target;
754 t->pi = pi;
755 GNUNET_CONTAINER_DLL_insert (pi->t_head,
756 pi->t_tail,
757 t);
758 *ctx = t;
759
815 } 760 }
816 *ctx = pi;
817} 761}
818 762
819 763
820/**
821 * Method called whenever a peer disconnects.
822 *
823 * @param ctx context
824 */
825void 764void
826GDS_u_disconnect (void *ctx) 765GDS_u_disconnect (void *ctx)
827{ 766{
828 struct PeerInfo *to_remove = ctx; 767 struct Target *t = ctx;
768 struct PeerInfo *pi;
829 struct PeerBucket *bucket; 769 struct PeerBucket *bucket;
830 770
831 /* Check for disconnect from self message (on shutdown) */ 771 /* Check for disconnect from self message (on shutdown) */
832 if (NULL == to_remove) 772 if (NULL == t)
833 return; 773 return;
774 pi = t->pi;
775 GNUNET_CONTAINER_DLL_remove (pi->t_head,
776 pi->t_tail,
777 t);
778 if (t->load > 0)
779 {
780 t->dropped = true;
781 t->pi = NULL;
782 }
783 else
784 {
785 GNUNET_free (t);
786 }
787 if (NULL != pi->t_head)
788 return; /* got other connections still */
834 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 789 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
835 "Disconnected from peer %s\n", 790 "Disconnected from peer %s\n",
836 GNUNET_i2s (&to_remove->id)); 791 GNUNET_i2s (&pi->id));
837 GNUNET_STATISTICS_update (GDS_stats, 792 GNUNET_STATISTICS_update (GDS_stats,
838 "# peers connected", 793 "# peers connected",
839 -1, 794 -1,
840 GNUNET_NO); 795 GNUNET_NO);
841 GNUNET_assert (GNUNET_YES == 796 GNUNET_assert (GNUNET_YES ==
842 GNUNET_CONTAINER_multipeermap_remove (all_connected_peers, 797 GNUNET_CONTAINER_multipeermap_remove (all_connected_peers,
843 &to_remove->id, 798 &pi->id,
844 to_remove)); 799 pi));
845 if ( (0 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) && 800 if ( (0 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
846 (GNUNET_YES != disable_try_connect)) 801 (GNUNET_YES != disable_try_connect))
847 { 802 {
848 GNUNET_SCHEDULER_cancel (find_peer_task); 803 GNUNET_SCHEDULER_cancel (find_peer_task);
849 find_peer_task = NULL; 804 find_peer_task = NULL;
850 } 805 }
851 GNUNET_assert (to_remove->peer_bucket >= 0); 806 GNUNET_assert (pi->peer_bucket >= 0);
852 bucket = &k_buckets[to_remove->peer_bucket]; 807 bucket = &k_buckets[pi->peer_bucket];
853 GNUNET_CONTAINER_DLL_remove (bucket->head, 808 GNUNET_CONTAINER_DLL_remove (bucket->head,
854 bucket->tail, 809 bucket->tail,
855 to_remove); 810 pi);
856 GNUNET_assert (bucket->peers_size > 0); 811 GNUNET_assert (bucket->peers_size > 0);
857 bucket->peers_size--; 812 bucket->peers_size--;
813 // FIXME: check if this peer was in one of the first 'bucket_size'
814 // peers, and call 'hold' on the next peer if there is any!
858 while ( (closest_bucket > 0) && 815 while ( (closest_bucket > 0) &&
859 (0 == k_buckets[closest_bucket - 1].peers_size)) 816 (0 == k_buckets[closest_bucket - 1].peers_size))
860 closest_bucket--; 817 closest_bucket--;
861 if (bucket->peers_size < bucket_size) 818 GNUNET_free (pi->hello);
862 update_connect_preferences (); 819 GNUNET_free (pi);
863 GNUNET_free (to_remove);
864} 820}
865 821
866 822
@@ -935,7 +891,7 @@ enum GNUNET_GenericReturnValue
935GDS_am_closest_peer (const struct GNUNET_HashCode *key, 891GDS_am_closest_peer (const struct GNUNET_HashCode *key,
936 const struct GNUNET_CONTAINER_BloomFilter *bloom) 892 const struct GNUNET_CONTAINER_BloomFilter *bloom)
937{ 893{
938 if (0 == GNUNET_memcmp (&my_identity_hash, 894 if (0 == GNUNET_memcmp (&GDS_my_identity_hash,
939 key)) 895 key))
940 return GNUNET_YES; 896 return GNUNET_YES;
941 for (int bucket_num = find_bucket (key); 897 for (int bucket_num = find_bucket (key);
@@ -962,7 +918,7 @@ GDS_am_closest_peer (const struct GNUNET_HashCode *key,
962 because an unfiltered peer exists, we are not the 918 because an unfiltered peer exists, we are not the
963 closest. */ 919 closest. */
964 int delta = GNUNET_CRYPTO_hash_xorcmp (&pos->phash, 920 int delta = GNUNET_CRYPTO_hash_xorcmp (&pos->phash,
965 &my_identity_hash, 921 &GDS_my_identity_hash,
966 key); 922 key);
967 switch (delta) 923 switch (delta)
968 { 924 {
@@ -1026,7 +982,7 @@ select_peer (const struct GNUNET_HashCode *key,
1026 struct GNUNET_HashCode xor; 982 struct GNUNET_HashCode xor;
1027 983
1028 GNUNET_CRYPTO_hash_xor (key, 984 GNUNET_CRYPTO_hash_xor (key,
1029 &my_identity_hash, 985 &GDS_my_identity_hash,
1030 &xor); 986 &xor);
1031 best_bucket = GNUNET_CRYPTO_hash_count_leading_zeros (&xor); 987 best_bucket = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
1032 } 988 }
@@ -1046,9 +1002,10 @@ select_peer (const struct GNUNET_HashCode *key,
1046 if (count >= bucket_size) 1002 if (count >= bucket_size)
1047 break; /* we only consider first #bucket_size entries per bucket */ 1003 break; /* we only consider first #bucket_size entries per bucket */
1048 count++; 1004 count++;
1049 if (GNUNET_YES == 1005 if ( (NULL != bloom) &&
1050 GNUNET_CONTAINER_bloomfilter_test (bloom, 1006 (GNUNET_YES ==
1051 &pos->phash)) 1007 GNUNET_CONTAINER_bloomfilter_test (bloom,
1008 &pos->phash)) )
1052 { 1009 {
1053 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1010 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1054 "Excluded peer `%s' due to BF match in greedy routing for %s\n", 1011 "Excluded peer `%s' due to BF match in greedy routing for %s\n",
@@ -1134,18 +1091,20 @@ select_peer (const struct GNUNET_HashCode *key,
1134 1091
1135 for (unsigned int bc = 0; bc < closest_bucket; bc++) 1092 for (unsigned int bc = 0; bc < closest_bucket; bc++)
1136 { 1093 {
1094 struct PeerBucket *bucket = &k_buckets[bc];
1137 unsigned int count = 0; 1095 unsigned int count = 0;
1138 1096
1139 for (struct PeerInfo *pos = k_buckets[bc].head; 1097 for (struct PeerInfo *pos = bucket->head;
1140 NULL != pos; 1098 NULL != pos;
1141 pos = pos->next) 1099 pos = pos->next)
1142 { 1100 {
1143 count++; 1101 count++;
1144 if (count > bucket_size) 1102 if (count > bucket_size)
1145 break; /* limits search to #bucket_size peers per bucket */ 1103 break; /* limits search to #bucket_size peers per bucket */
1146 if (GNUNET_YES == 1104 if ( (NULL != bloom) &&
1147 GNUNET_CONTAINER_bloomfilter_test (bloom, 1105 (GNUNET_YES ==
1148 &pos->phash)) 1106 GNUNET_CONTAINER_bloomfilter_test (bloom,
1107 &pos->phash)) )
1149 { 1108 {
1150 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1109 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1151 "Excluded peer `%s' due to BF match in random routing for %s\n", 1110 "Excluded peer `%s' due to BF match in random routing for %s\n",
@@ -1180,9 +1139,10 @@ select_peer (const struct GNUNET_HashCode *key,
1180 if (count > bucket_size) 1139 if (count > bucket_size)
1181 break; /* limits search to #bucket_size peers per bucket */ 1140 break; /* limits search to #bucket_size peers per bucket */
1182 1141
1183 if (GNUNET_YES == 1142 if ( (NULL != bloom) &&
1184 GNUNET_CONTAINER_bloomfilter_test (bloom, 1143 (GNUNET_YES ==
1185 &pos->phash)) 1144 GNUNET_CONTAINER_bloomfilter_test (bloom,
1145 &pos->phash)) )
1186 continue; /* Ignore bloomfiltered peers */ 1146 continue; /* Ignore bloomfiltered peers */
1187 if (0 == selected--) 1147 if (0 == selected--)
1188 { 1148 {
@@ -1296,7 +1256,7 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1296 bd->put_path, 1256 bd->put_path,
1297 bd->put_path_length, 1257 bd->put_path_length,
1298 NULL, 0, /* get_path */ 1258 NULL, 0, /* get_path */
1299 &my_identity)) 1259 &GDS_my_identity))
1300 { 1260 {
1301 GNUNET_break_op (0); 1261 GNUNET_break_op (0);
1302 put_path_length = 0; 1262 put_path_length = 0;
@@ -1304,10 +1264,10 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1304#endif 1264#endif
1305 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1306 "Adding myself (%s) to PUT bloomfilter for %s\n", 1266 "Adding myself (%s) to PUT bloomfilter for %s\n",
1307 GNUNET_i2s (&my_identity), 1267 GNUNET_i2s (&GDS_my_identity),
1308 GNUNET_h2s (&bd->key)); 1268 GNUNET_h2s (&bd->key));
1309 GNUNET_CONTAINER_bloomfilter_add (bf, 1269 GNUNET_CONTAINER_bloomfilter_add (bf,
1310 &my_identity_hash); 1270 &GDS_my_identity_hash);
1311 GNUNET_STATISTICS_update (GDS_stats, 1271 GNUNET_STATISTICS_update (GDS_stats,
1312 "# PUT requests routed", 1272 "# PUT requests routed",
1313 1, 1273 1,
@@ -1324,7 +1284,7 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1324 "Routing PUT for %s terminates after %u hops at %s\n", 1284 "Routing PUT for %s terminates after %u hops at %s\n",
1325 GNUNET_h2s (&bd->key), 1285 GNUNET_h2s (&bd->key),
1326 (unsigned int) hop_count, 1286 (unsigned int) hop_count,
1327 GNUNET_i2s (&my_identity)); 1287 GNUNET_i2s (&GDS_my_identity));
1328 return GNUNET_NO; 1288 return GNUNET_NO;
1329 } 1289 }
1330 msize = bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement) 1290 msize = bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement)
@@ -1346,30 +1306,18 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1346 for (unsigned int i = 0; i < target_count; i++) 1306 for (unsigned int i = 0; i < target_count; i++)
1347 { 1307 {
1348 struct PeerInfo *target = targets[i]; 1308 struct PeerInfo *target = targets[i];
1349 struct GNUNET_MQ_Envelope *env;
1350 struct PeerPutMessage *ppm; 1309 struct PeerPutMessage *ppm;
1310 char buf[sizeof (*ppm) + msize] GNUNET_ALIGN;
1351 struct GNUNET_DHT_PathElement *pp; 1311 struct GNUNET_DHT_PathElement *pp;
1352 1312
1353#if FIXME_LEGACY
1354 if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER)
1355 {
1356 /* skip */
1357 GNUNET_STATISTICS_update (GDS_stats,
1358 "# P2P messages dropped due to full queue",
1359 1,
1360 GNUNET_NO);
1361 skip_count++;
1362 continue;
1363 }
1364#endif
1365 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1313 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1366 "Routing PUT for %s after %u hops to %s\n", 1314 "Routing PUT for %s after %u hops to %s\n",
1367 GNUNET_h2s (&bd->key), 1315 GNUNET_h2s (&bd->key),
1368 (unsigned int) hop_count, 1316 (unsigned int) hop_count,
1369 GNUNET_i2s (&target->id)); 1317 GNUNET_i2s (&target->id));
1370 env = GNUNET_MQ_msg_extra (ppm, 1318 ppm = (struct PeerPutMessage *) buf;
1371 msize, 1319 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
1372 GNUNET_MESSAGE_TYPE_DHT_P2P_PUT); 1320 ppm->header.size = htons (sizeof (buf));
1373 ppm->options = htonl (options); 1321 ppm->options = htonl (options);
1374 ppm->type = htonl (bd->type); 1322 ppm->type = htonl (bd->type);
1375 ppm->hop_count = htonl (hop_count + 1); 1323 ppm->hop_count = htonl (hop_count + 1);
@@ -1405,10 +1353,8 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1405 GNUNET_memcpy (&pp[put_path_length], 1353 GNUNET_memcpy (&pp[put_path_length],
1406 bd->data, 1354 bd->data,
1407 bd->data_size); 1355 bd->data_size);
1408#if FIXME 1356 do_send (target,
1409 GNUNET_MQ_send (target->mq, 1357 &ppm->header);
1410 env);
1411#endif
1412 } 1358 }
1413 GNUNET_free (targets); 1359 GNUNET_free (targets);
1414 GNUNET_STATISTICS_update (GDS_stats, 1360 GNUNET_STATISTICS_update (GDS_stats,
@@ -1450,17 +1396,17 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1450 &targets); 1396 &targets);
1451 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1397 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1452 "Adding myself (%s) to GET bloomfilter for %s\n", 1398 "Adding myself (%s) to GET bloomfilter for %s\n",
1453 GNUNET_i2s (&my_identity), 1399 GNUNET_i2s (&GDS_my_identity),
1454 GNUNET_h2s (key)); 1400 GNUNET_h2s (key));
1455 GNUNET_CONTAINER_bloomfilter_add (peer_bf, 1401 GNUNET_CONTAINER_bloomfilter_add (peer_bf,
1456 &my_identity_hash); 1402 &GDS_my_identity_hash);
1457 if (0 == target_count) 1403 if (0 == target_count)
1458 { 1404 {
1459 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1405 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1460 "Routing GET for %s terminates after %u hops at %s\n", 1406 "Routing GET for %s terminates after %u hops at %s\n",
1461 GNUNET_h2s (key), 1407 GNUNET_h2s (key),
1462 (unsigned int) hop_count, 1408 (unsigned int) hop_count,
1463 GNUNET_i2s (&my_identity)); 1409 GNUNET_i2s (&GDS_my_identity));
1464 return GNUNET_NO; 1410 return GNUNET_NO;
1465 } 1411 }
1466 if (GNUNET_OK != 1412 if (GNUNET_OK !=
@@ -1487,30 +1433,18 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1487 for (unsigned int i = 0; i < target_count; i++) 1433 for (unsigned int i = 0; i < target_count; i++)
1488 { 1434 {
1489 struct PeerInfo *target = targets[i]; 1435 struct PeerInfo *target = targets[i];
1490 struct GNUNET_MQ_Envelope *env;
1491 struct PeerGetMessage *pgm; 1436 struct PeerGetMessage *pgm;
1437 char buf[sizeof (*pgm) + msize] GNUNET_ALIGN;
1492 char *xq; 1438 char *xq;
1493 1439
1494#if FIXME
1495 if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER)
1496 {
1497 /* skip */
1498 GNUNET_STATISTICS_update (GDS_stats,
1499 "# P2P messages dropped due to full queue",
1500 1,
1501 GNUNET_NO);
1502 skip_count++;
1503 continue;
1504 }
1505#endif
1506 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1440 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1507 "Routing GET for %s after %u hops to %s\n", 1441 "Routing GET for %s after %u hops to %s\n",
1508 GNUNET_h2s (key), 1442 GNUNET_h2s (key),
1509 (unsigned int) hop_count, 1443 (unsigned int) hop_count,
1510 GNUNET_i2s (&target->id)); 1444 GNUNET_i2s (&target->id));
1511 env = GNUNET_MQ_msg_extra (pgm, 1445 pgm = (struct PeerGetMessage *) buf;
1512 msize, 1446 pgm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
1513 GNUNET_MESSAGE_TYPE_DHT_P2P_GET); 1447 pgm->header.size = htons (sizeof (buf));
1514 pgm->options = htonl (options); 1448 pgm->options = htonl (options);
1515 pgm->type = htonl (type); 1449 pgm->type = htonl (type);
1516 pgm->hop_count = htonl (hop_count + 1); 1450 pgm->hop_count = htonl (hop_count + 1);
@@ -1532,10 +1466,8 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1532 GNUNET_memcpy (&xq[xquery_size], 1466 GNUNET_memcpy (&xq[xquery_size],
1533 reply_bf, 1467 reply_bf,
1534 reply_bf_size); 1468 reply_bf_size);
1535#if FIXME 1469 do_send (target,
1536 GNUNET_MQ_send (target->mq, 1470 &pgm->header);
1537 env);
1538#endif
1539 } 1471 }
1540 GNUNET_STATISTICS_update (GDS_stats, 1472 GNUNET_STATISTICS_update (GDS_stats,
1541 "# GET messages queued for transmission", 1473 "# GET messages queued for transmission",
@@ -1562,8 +1494,6 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
1562 unsigned int get_path_length, 1494 unsigned int get_path_length,
1563 const struct GNUNET_DHT_PathElement *get_path) 1495 const struct GNUNET_DHT_PathElement *get_path)
1564{ 1496{
1565 struct GNUNET_MQ_Envelope *env;
1566 struct PeerResultMessage *prm;
1567 struct GNUNET_DHT_PathElement *paths; 1497 struct GNUNET_DHT_PathElement *paths;
1568 size_t msize; 1498 size_t msize;
1569 unsigned int ppl = bd->put_path_length; 1499 unsigned int ppl = bd->put_path_length;
@@ -1578,7 +1508,7 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
1578 bd->put_path_length, 1508 bd->put_path_length,
1579 get_path, 1509 get_path,
1580 get_path_length, 1510 get_path_length,
1581 &my_identity)) 1511 &GDS_my_identity))
1582 { 1512 {
1583 GNUNET_break_op (0); 1513 GNUNET_break_op (0);
1584 get_path_length = 0; 1514 get_path_length = 0;
@@ -1609,20 +1539,6 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
1609 GNUNET_break (0); 1539 GNUNET_break (0);
1610 return; 1540 return;
1611 } 1541 }
1612#if FIXME
1613 if (GNUNET_MQ_get_length (pi->mq) >= MAXIMUM_PENDING_PER_PEER)
1614 {
1615 /* skip */
1616 GNUNET_STATISTICS_update (GDS_stats,
1617 "# P2P messages dropped due to full queue",
1618 1,
1619 GNUNET_NO);
1620 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1621 "Peer queue full, ignoring reply for key %s\n",
1622 GNUNET_h2s (&bd->key));
1623 return;
1624 }
1625#endif
1626 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1542 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1627 "Forwarding reply for key %s to peer %s\n", 1543 "Forwarding reply for key %s to peer %s\n",
1628 GNUNET_h2s (query_hash), 1544 GNUNET_h2s (query_hash),
@@ -1631,41 +1547,44 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
1631 "# RESULT messages queued for transmission", 1547 "# RESULT messages queued for transmission",
1632 1, 1548 1,
1633 GNUNET_NO); 1549 GNUNET_NO);
1634 env = GNUNET_MQ_msg_extra (prm,
1635 msize,
1636 GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT);
1637 prm->type = htonl (bd->type);
1638 prm->put_path_length = htonl (ppl);
1639 prm->get_path_length = htonl (get_path_length);
1640 prm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1641 prm->key = *query_hash;
1642 paths = (struct GNUNET_DHT_PathElement *) &prm[1];
1643 GNUNET_memcpy (paths,
1644 bd->put_path,
1645 ppl * sizeof(struct GNUNET_DHT_PathElement));
1646 GNUNET_memcpy (&paths[ppl],
1647 get_path,
1648 get_path_length * sizeof(struct GNUNET_DHT_PathElement));
1649 /* 0 == get_path_length means path is not being tracked */
1650 if (0 != get_path_length)
1651 { 1550 {
1652 /* Note that the signature in 'get_path' was not initialized before, 1551 struct PeerResultMessage *prm;
1653 so this is crucial to avoid sending garbage. */ 1552 char buf[sizeof (*prm) + msize] GNUNET_ALIGN;
1654 sign_path (&bd->key, 1553
1655 bd->data, 1554 prm = (struct PeerResultMessage *) buf;
1656 bd->data_size, 1555 prm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT);
1657 bd->expiration_time, 1556 prm->header.size = htons (sizeof (buf));
1658 &paths[ppl + get_path_length - 1].pred, 1557 prm->type = htonl (bd->type);
1659 &pi->id, 1558 prm->put_path_length = htonl (ppl);
1660 &paths[ppl + get_path_length - 1].sig); 1559 prm->get_path_length = htonl (get_path_length);
1661 } 1560 prm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1662 GNUNET_memcpy (&paths[ppl + get_path_length], 1561 prm->key = *query_hash;
1562 paths = (struct GNUNET_DHT_PathElement *) &prm[1];
1563 GNUNET_memcpy (paths,
1564 bd->put_path,
1565 ppl * sizeof(struct GNUNET_DHT_PathElement));
1566 GNUNET_memcpy (&paths[ppl],
1567 get_path,
1568 get_path_length * sizeof(struct GNUNET_DHT_PathElement));
1569 /* 0 == get_path_length means path is not being tracked */
1570 if (0 != get_path_length)
1571 {
1572 /* Note that the signature in 'get_path' was not initialized before,
1573 so this is crucial to avoid sending garbage. */
1574 sign_path (&bd->key,
1663 bd->data, 1575 bd->data,
1664 bd->data_size); 1576 bd->data_size,
1665#if FIXME 1577 bd->expiration_time,
1666 GNUNET_MQ_send (pi->mq, 1578 &paths[ppl + get_path_length - 1].pred,
1667 env); 1579 &pi->id,
1668#endif 1580 &paths[ppl + get_path_length - 1].sig);
1581 }
1582 GNUNET_memcpy (&paths[ppl + get_path_length],
1583 bd->data,
1584 bd->data_size);
1585 do_send (pi,
1586 &prm->header);
1587 }
1669} 1588}
1670 1589
1671 1590
@@ -1819,7 +1738,7 @@ handle_dht_p2p_put (void *cls,
1819 bd.put_path, 1738 bd.put_path,
1820 putlen, 1739 putlen,
1821 NULL, 0, /* get_path */ 1740 NULL, 0, /* get_path */
1822 &my_identity)) 1741 &GDS_my_identity))
1823 { 1742 {
1824 GNUNET_break_op (0); 1743 GNUNET_break_op (0);
1825 putlen = 0; 1744 putlen = 0;
@@ -1875,45 +1794,60 @@ handle_dht_p2p_put (void *cls,
1875 1794
1876 1795
1877/** 1796/**
1878 * We have received a FIND PEER request. Send matching 1797 * We have received a request for a HELLO. Sends our
1879 * HELLOs back. 1798 * HELLO back.
1880 * 1799 *
1881 * @param pi sender of the FIND PEER request 1800 * @param pi sender of the request
1882 * @param key peers close to this key are desired 1801 * @param key peers close to this key are desired
1883 * @param bg group for filtering peers 1802 * @param bg group for filtering peers
1884 */ 1803 */
1885static void 1804static void
1886handle_find_peer (struct PeerInfo *pi, 1805handle_find_my_hello (struct PeerInfo *pi,
1887 const struct GNUNET_HashCode *query_hash, 1806 const struct GNUNET_HashCode *query_hash,
1888 struct GNUNET_BLOCK_Group *bg) 1807 struct GNUNET_BLOCK_Group *bg)
1889{ 1808{
1890 int bucket_idx; 1809 size_t block_size = 0;
1891 struct PeerBucket *bucket; 1810
1892 struct PeerInfo *peer; 1811 /* TODO: consider caching our HELLO block for a bit, to
1893 unsigned int choice; 1812 avoid signing too often here... */
1894 struct GDS_DATACACHE_BlockData bd = { 1813 GNUNET_break (GNUNET_NO ==
1895 .type = GNUNET_BLOCK_TYPE_DHT_URL_HELLO 1814 GNUNET_HELLO_builder_to_block (GDS_my_hello,
1896 }; 1815 &GDS_my_private_key,
1897 1816 NULL,
1898 /* first, check about our own HELLO */ 1817 &block_size));
1899 if (NULL != GDS_my_hello)
1900 { 1818 {
1901 bd.expiration_time = GNUNET_TIME_relative_to_absolute ( 1819 char block[block_size];
1902 hello_expiration), 1820
1903 bd.key = my_identity_hash, 1821 if (GNUNET_OK !=
1904 bd.data = GDS_my_hello; 1822 GNUNET_HELLO_builder_to_block (GDS_my_hello,
1905 bd.data_size = GNUNET_HELLO_size ( 1823 &GDS_my_private_key,
1906 (const struct GNUNET_HELLO_Message *) GDS_my_hello); 1824 block,
1907 GNUNET_break (bd.data_size >= sizeof(struct GNUNET_MessageHeader)); 1825 &block_size))
1908 if (GNUNET_BLOCK_REPLY_OK_MORE ==
1909 GNUNET_BLOCK_check_reply (GDS_block_context,
1910 GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
1911 bg,
1912 &my_identity_hash,
1913 NULL, 0,
1914 bd.data,
1915 bd.data_size))
1916 { 1826 {
1827 GNUNET_STATISTICS_update (GDS_stats,
1828 "# FIND PEER requests ignored due to lack of HELLO",
1829 1,
1830 GNUNET_NO);
1831 }
1832 else if (GNUNET_BLOCK_REPLY_OK_MORE ==
1833 GNUNET_BLOCK_check_reply (GDS_block_context,
1834 GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
1835 bg,
1836 &GDS_my_identity_hash,
1837 NULL, 0,
1838 block,
1839 block_size))
1840 {
1841 struct GDS_DATACACHE_BlockData bd = {
1842 .type = GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
1843 .expiration_time
1844 = GNUNET_TIME_relative_to_absolute (
1845 GNUNET_HELLO_ADDRESS_EXPIRATION),
1846 .key = GDS_my_identity_hash,
1847 .data = block,
1848 .data_size = block_size
1849 };
1850
1917 GDS_NEIGHBOURS_handle_reply (pi, 1851 GDS_NEIGHBOURS_handle_reply (pi,
1918 &bd, 1852 &bd,
1919 query_hash, 1853 query_hash,
@@ -1927,66 +1861,48 @@ handle_find_peer (struct PeerInfo *pi,
1927 GNUNET_NO); 1861 GNUNET_NO);
1928 } 1862 }
1929 } 1863 }
1930 else 1864}
1931 {
1932 GNUNET_STATISTICS_update (GDS_stats,
1933 "# FIND PEER requests ignored due to lack of HELLO",
1934 1,
1935 GNUNET_NO);
1936 }
1937 1865
1938 /* then, also consider sending a random HELLO from the closest bucket */
1939 /* FIXME: How can this be true? Shouldnt we just do find_bucket() ? */
1940 if (0 ==
1941 GNUNET_memcmp (&my_identity_hash,
1942 query_hash))
1943 bucket_idx = closest_bucket - 1;
1944 else
1945 bucket_idx = GNUNET_MIN ((int) closest_bucket - 1,
1946 find_bucket (query_hash));
1947 if (bucket_idx < 0)
1948 return;
1949 bucket = &k_buckets[bucket_idx];
1950 if (bucket->peers_size == 0)
1951 return;
1952 choice = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1953 bucket->peers_size);
1954 peer = bucket->head;
1955 while (choice > 0)
1956 {
1957 GNUNET_assert (NULL != peer);
1958 peer = peer->next;
1959 choice--;
1960 }
1961 choice = bucket->peers_size;
1962 1866
1867/**
1868 * We have received a request for nearby HELLOs. Sends matching
1869 * HELLOs back.
1870 *
1871 * @param pi sender of the request
1872 * @param key peers close to this key are desired
1873 * @param bg group for filtering peers
1874 */
1875static void
1876handle_find_local_hello (struct PeerInfo *pi,
1877 const struct GNUNET_HashCode *query_hash,
1878 struct GNUNET_BLOCK_Group *bg)
1879{
1880 /* Force non-random selection by hop count */
1881 struct PeerInfo *peer;
1882
1883 peer = select_peer (query_hash,
1884 NULL,
1885 GDS_NSE_get () + 1);
1886 if ( (NULL != peer->hello) &&
1887 (! GNUNET_TIME_absolute_is_past (peer->hello_expiration)) &&
1888 (GNUNET_BLOCK_REPLY_OK_MORE ==
1889 GNUNET_BLOCK_check_reply (
1890 GDS_block_context,
1891 GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
1892 bg,
1893 &peer->phash,
1894 NULL, 0, /* xquery */
1895 peer->hello,
1896 peer->hello_size)) )
1963 { 1897 {
1964 const struct GNUNET_HELLO_Message *hello; 1898 struct GDS_DATACACHE_BlockData bd = {
1965 size_t hello_size; 1899 .type = GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
1900 .expiration_time = peer->hello_expiration,
1901 .key = peer->phash,
1902 .data = peer->hello,
1903 .data_size = peer->hello_size
1904 };
1966 1905
1967 do
1968 {
1969 peer = peer->next;
1970 if (0 == choice--)
1971 return; /* no non-masked peer available */
1972 if (NULL == peer)
1973 peer = bucket->head;
1974 hello = GDS_HELLO_get (&peer->id);
1975 } while ( (NULL == hello) ||
1976 (GNUNET_BLOCK_REPLY_OK_MORE !=
1977 GNUNET_BLOCK_check_reply (
1978 GDS_block_context,
1979 GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
1980 bg,
1981 &peer->phash,
1982 NULL, 0, /* xquery */
1983 hello,
1984 (hello_size = GNUNET_HELLO_size (hello)))));
1985 bd.expiration_time = GNUNET_TIME_relative_to_absolute (
1986 GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION);
1987 bd.key = peer->phash;
1988 bd.data = hello;
1989 bd.data_size = hello_size;
1990 GDS_NEIGHBOURS_handle_reply (pi, 1906 GDS_NEIGHBOURS_handle_reply (pi,
1991 &bd, 1907 &bd,
1992 query_hash, 1908 query_hash,
@@ -2101,32 +2017,45 @@ handle_dht_p2p_get (void *cls,
2101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2017 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2102 "GET for %s at %s after %u hops\n", 2018 "GET for %s at %s after %u hops\n",
2103 GNUNET_h2s (&get->key), 2019 GNUNET_h2s (&get->key),
2104 GNUNET_i2s (&my_identity), 2020 GNUNET_i2s (&GDS_my_identity),
2105 (unsigned int) hop_count); 2021 (unsigned int) hop_count);
2106 /* local lookup (this may update the reply_bf) */ 2022 /* local lookup (this may update the bg) */
2107 if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) || 2023 if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
2108 (GDS_am_closest_peer (&get->key, 2024 (GDS_am_closest_peer (&get->key,
2109 peer_bf)) ) 2025 peer_bf)) )
2110 { 2026 {
2111 if ((0 != (options & GNUNET_DHT_RO_FIND_PEER))) 2027 if (GNUNET_BLOCK_TYPE_DHT_URL_HELLO == type)
2112 { 2028 {
2113 GNUNET_STATISTICS_update (GDS_stats, 2029 GNUNET_STATISTICS_update (GDS_stats,
2114 "# P2P FIND PEER requests processed", 2030 "# P2P HELLO lookup requests processed",
2115 1, 2031 1,
2116 GNUNET_NO); 2032 GNUNET_NO);
2117 handle_find_peer (peer, 2033 handle_find_my_hello (peer,
2118 &get->key, 2034 &get->key,
2119 bg); 2035 bg);
2036 if (0 != (options & GNUNET_DHT_RO_FIND_APPROXIMATE))
2037 handle_find_local_hello (peer,
2038 &get->key,
2039 bg);
2120 } 2040 }
2121 else 2041 else
2122 { 2042 {
2123 eval = GDS_DATACACHE_handle_get (&get->key, 2043 if (0 != (options & GNUNET_DHT_RO_FIND_APPROXIMATE))
2124 type, 2044 eval = GDS_DATACACHE_get_closest (&get->key,
2125 xquery, 2045 type,
2126 xquery_size, 2046 xquery,
2127 bg, 2047 xquery_size,
2128 &handle_local_result, 2048 bg,
2129 peer); 2049 &handle_local_result,
2050 peer);
2051 else
2052 eval = GDS_DATACACHE_handle_get (&get->key,
2053 type,
2054 xquery,
2055 xquery_size,
2056 bg,
2057 &handle_local_result,
2058 peer);
2130 } 2059 }
2131 } 2060 }
2132 else 2061 else
@@ -2137,7 +2066,9 @@ handle_dht_p2p_get (void *cls,
2137 GNUNET_NO); 2066 GNUNET_NO);
2138 } 2067 }
2139 2068
2140 /* remember request for routing replies */ 2069 /* remember request for routing replies
2070 TODO: why should we do this if GNUNET_BLOCK_REPLY_OK_LAST == eval?
2071 */
2141 GDS_ROUTING_add (&peer->id, 2072 GDS_ROUTING_add (&peer->id,
2142 type, 2073 type,
2143 bg, /* bg now owned by routing, but valid at least until end of this function! */ 2074 bg, /* bg now owned by routing, but valid at least until end of this function! */
@@ -2260,6 +2191,52 @@ check_dht_p2p_result (void *cls,
2260 2191
2261 2192
2262/** 2193/**
2194 * Callback function used to extract URIs from a builder.
2195 * Called when we should consider connecting to a peer.
2196 *
2197 * @param cls closure pointing to a `struct GNUNET_PeerIdentity *`
2198 * @param uri one of the URIs
2199 */
2200static void
2201try_connect (void *cls,
2202 const char *uri)
2203{
2204 const struct GNUNET_PeerIdentity *pid = cls;
2205 struct GNUNET_HashCode phash;
2206 int peer_bucket;
2207 struct PeerBucket *bucket;
2208
2209 if (0 == GNUNET_memcmp (&GDS_my_identity,
2210 pid))
2211 return; /* that's us! */
2212 GNUNET_CRYPTO_hash (pid,
2213 sizeof(*pid),
2214 &phash);
2215 peer_bucket = find_bucket (&phash);
2216 GNUNET_assert ( (peer_bucket >= 0) &&
2217 ((unsigned int) peer_bucket < MAX_BUCKETS));
2218 bucket = &k_buckets[peer_bucket];
2219 if (bucket->peers_size >= bucket_size)
2220 return; /* do not care */
2221 for (struct PeerInfo *pi = bucket->head;
2222 NULL != pi;
2223 pi = pi->next)
2224 if (0 ==
2225 GNUNET_memcmp (&pi->id,
2226 pid))
2227 {
2228 /* already connected */
2229 /* TODO: maybe consider 'uri' anyway as an additional
2230 alternative address??? */
2231 return;
2232 }
2233 /* new peer that we like! */
2234 GDS_u_try_connect (pid,
2235 uri);
2236}
2237
2238
2239/**
2263 * Core handler for p2p result messages. 2240 * Core handler for p2p result messages.
2264 * 2241 *
2265 * @param cls closure 2242 * @param cls closure
@@ -2333,32 +2310,17 @@ handle_dht_p2p_result (void *cls,
2333 /* if we got a HELLO, consider it for our own routing table */ 2310 /* if we got a HELLO, consider it for our own routing table */
2334 if (GNUNET_BLOCK_TYPE_DHT_URL_HELLO == bd.type) 2311 if (GNUNET_BLOCK_TYPE_DHT_URL_HELLO == bd.type)
2335 { 2312 {
2336 const struct GNUNET_MessageHeader *h = bd.data;
2337 struct GNUNET_PeerIdentity pid; 2313 struct GNUNET_PeerIdentity pid;
2338 2314 struct GNUNET_HELLO_Builder *b;
2339 /* Should be a HELLO, validate and consider using it! */ 2315
2340 if (bd.data_size < sizeof(struct GNUNET_HELLO_Message)) 2316 b = GNUNET_HELLO_builder_from_block (bd.data,
2341 { 2317 bd.data_size);
2342 GNUNET_break (0); 2318 if (GNUNET_YES != disable_try_connect)
2343 return; 2319 GNUNET_HELLO_builder_iterate (b,
2344 } 2320 &pid,
2345 if (bd.data_size != ntohs (h->size)) 2321 &try_connect,
2346 { 2322 &pid);
2347 GNUNET_break (0); 2323 GNUNET_HELLO_builder_free (b);
2348 return;
2349 }
2350 if (GNUNET_OK !=
2351 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) h,
2352 &pid))
2353 {
2354 GNUNET_break_op (0);
2355 return;
2356 }
2357 if ( (GNUNET_YES != disable_try_connect) &&
2358 (0 != GNUNET_memcmp (&my_identity,
2359 &pid)) )
2360 try_connect (&pid,
2361 h);
2362 } 2324 }
2363 2325
2364 /* First, check if 'peer' is already on the path, and if 2326 /* First, check if 'peer' is already on the path, and if
@@ -2391,6 +2353,50 @@ handle_dht_p2p_result (void *cls,
2391} 2353}
2392 2354
2393 2355
2356/**
2357 * Check validity of a p2p hello message.
2358 *
2359 * @param cls closure
2360 * @param hello message
2361 * @return #GNUNET_YES if the message is well-formed
2362 */
2363static enum GNUNET_GenericReturnValue
2364check_dht_p2p_hello (void *cls,
2365 const struct GNUNET_MessageHeader *hello)
2366{
2367 struct GNUNET_HELLO_Builder *b;
2368 enum GNUNET_GenericReturnValue ret;
2369
2370 b = GNUNET_HELLO_builder_from_msg (hello);
2371 ret = (NULL == b) ? GNUNET_SYSERR : GNUNET_OK;
2372 GNUNET_HELLO_builder_free (b);
2373 return ret;
2374}
2375
2376
2377/**
2378 * Core handler for p2p HELLO messages.
2379 *
2380 * @param cls closure
2381 * @param message message
2382 */
2383static void
2384handle_dht_p2p_hello (void *cls,
2385 const struct GNUNET_MessageHeader *hello)
2386{
2387 struct PeerInfo *peer = cls;
2388
2389 GNUNET_free (peer->hello);
2390 peer->hello_size = 0;
2391 GNUNET_break (GNUNET_OK ==
2392 GNUNET_HELLO_dht_msg_to_block (hello,
2393 &peer->id,
2394 &peer->hello,
2395 &peer->hello_size,
2396 &peer->hello_expiration));
2397}
2398
2399
2394void 2400void
2395GDS_u_receive (void *cls, 2401GDS_u_receive (void *cls,
2396 void **tctx, 2402 void **tctx,
@@ -2412,6 +2418,10 @@ GDS_u_receive (void *cls,
2412 GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT, 2418 GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT,
2413 struct PeerResultMessage, 2419 struct PeerResultMessage,
2414 pi), 2420 pi),
2421 GNUNET_MQ_hd_var_size (dht_p2p_hello,
2422 GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO,
2423 struct GNUNET_MessageHeader,
2424 pi),
2415 GNUNET_MQ_handler_end () 2425 GNUNET_MQ_handler_end ()
2416 }; 2426 };
2417 const struct GNUNET_MessageHeader *mh = message; 2427 const struct GNUNET_MessageHeader *mh = message;
@@ -2438,6 +2448,34 @@ GDS_u_receive (void *cls,
2438} 2448}
2439 2449
2440 2450
2451/**
2452 * Send @a msg to all peers in our buckets.
2453 *
2454 * @param msg message to broadcast
2455 */
2456void
2457GDS_NEIGHBOURS_broadcast (const struct GNUNET_MessageHeader *msg)
2458{
2459 for (unsigned int bc = 0; bc<closest_bucket; bc++)
2460 {
2461 struct PeerBucket *bucket = &k_buckets[bc];
2462 unsigned int count = 0;
2463
2464 for (struct PeerInfo *pos = bucket->head;
2465 NULL != pos;
2466 pos = pos->next)
2467 {
2468 if (count >= bucket_size)
2469 break; /* we only consider first #bucket_size entries per bucket */
2470 count++;
2471 GNUNET_break (0);
2472 do_send (pos,
2473 msg);
2474 }
2475 }
2476}
2477
2478
2441enum GNUNET_GenericReturnValue 2479enum GNUNET_GenericReturnValue
2442GDS_NEIGHBOURS_init () 2480GDS_NEIGHBOURS_init ()
2443{ 2481{
@@ -2458,41 +2496,8 @@ GDS_NEIGHBOURS_init ()
2458 = GNUNET_CONFIGURATION_get_value_yesno (GDS_cfg, 2496 = GNUNET_CONFIGURATION_get_value_yesno (GDS_cfg,
2459 "DHT", 2497 "DHT",
2460 "CACHE_RESULTS"); 2498 "CACHE_RESULTS");
2461 {
2462 char *keyfile;
2463
2464 if (GNUNET_OK !=
2465 GNUNET_CONFIGURATION_get_value_filename (GDS_cfg,
2466 "PEER",
2467 "PRIVATE_KEY",
2468 &keyfile))
2469 {
2470 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2471 "Core service is lacking HOSTKEY configuration setting. Exiting.\n");
2472 return GNUNET_SYSERR;
2473 }
2474 if (GNUNET_SYSERR ==
2475 GNUNET_CRYPTO_eddsa_key_from_file (keyfile,
2476 GNUNET_YES,
2477 &my_private_key))
2478 {
2479 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2480 "Failed to setup peer's private key\n");
2481 GNUNET_free (keyfile);
2482 return GNUNET_SYSERR;
2483 }
2484 GNUNET_free (keyfile);
2485 }
2486 GNUNET_CRYPTO_eddsa_key_get_public (&my_private_key,
2487 &my_identity.public_key);
2488 GNUNET_CRYPTO_hash (&my_identity,
2489 sizeof(struct GNUNET_PeerIdentity),
2490 &my_identity_hash);
2491
2492 all_connected_peers = GNUNET_CONTAINER_multipeermap_create (256, 2499 all_connected_peers = GNUNET_CONTAINER_multipeermap_create (256,
2493 GNUNET_YES); 2500 GNUNET_YES);
2494 all_desired_peers = GNUNET_CONTAINER_multipeermap_create (256,
2495 GNUNET_NO);
2496 return GNUNET_OK; 2501 return GNUNET_OK;
2497} 2502}
2498 2503
@@ -2506,11 +2511,6 @@ GDS_NEIGHBOURS_done ()
2506 GNUNET_CONTAINER_multipeermap_size (all_connected_peers)); 2511 GNUNET_CONTAINER_multipeermap_size (all_connected_peers));
2507 GNUNET_CONTAINER_multipeermap_destroy (all_connected_peers); 2512 GNUNET_CONTAINER_multipeermap_destroy (all_connected_peers);
2508 all_connected_peers = NULL; 2513 all_connected_peers = NULL;
2509 GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers,
2510 &free_connect_info,
2511 NULL);
2512 GNUNET_CONTAINER_multipeermap_destroy (all_desired_peers);
2513 all_desired_peers = NULL;
2514 GNUNET_assert (NULL == find_peer_task); 2514 GNUNET_assert (NULL == find_peer_task);
2515} 2515}
2516 2516
@@ -2518,7 +2518,7 @@ GDS_NEIGHBOURS_done ()
2518struct GNUNET_PeerIdentity * 2518struct GNUNET_PeerIdentity *
2519GDS_NEIGHBOURS_get_id () 2519GDS_NEIGHBOURS_get_id ()
2520{ 2520{
2521 return &my_identity; 2521 return &GDS_my_identity;
2522} 2522}
2523 2523
2524 2524
diff --git a/src/dht/gnunet-service-dht_neighbours.h b/src/dht/gnunet-service-dht_neighbours.h
index e1a553f06..5a4c8c620 100644
--- a/src/dht/gnunet-service-dht_neighbours.h
+++ b/src/dht/gnunet-service-dht_neighbours.h
@@ -33,11 +33,6 @@
33#include "gnunet_dhtu_plugin.h" 33#include "gnunet_dhtu_plugin.h"
34#include "gnunet-service-dht_datacache.h" 34#include "gnunet-service-dht_datacache.h"
35 35
36/**
37 * Hash of the identity of this peer.
38 */
39extern struct GNUNET_HashCode my_identity_hash;
40
41 36
42struct PeerInfo; 37struct PeerInfo;
43 38
@@ -141,7 +136,7 @@ GDS_am_closest_peer (const struct GNUNET_HashCode *key,
141 * Function to call when we connect to a peer and can henceforth transmit to 136 * Function to call when we connect to a peer and can henceforth transmit to
142 * that peer. 137 * that peer.
143 * 138 *
144 * @param cls the closure 139 * @param cls the closure, must be a `struct Underlay`
145 * @param target handle to the target, 140 * @param target handle to the target,
146 * pointer will remain valid until @e disconnect_cb is called 141 * pointer will remain valid until @e disconnect_cb is called
147 * @para pid peer identity, 142 * @para pid peer identity,
@@ -154,6 +149,7 @@ GDS_u_connect (void *cls,
154 const struct GNUNET_PeerIdentity *pid, 149 const struct GNUNET_PeerIdentity *pid,
155 void **ctx); 150 void **ctx);
156 151
152
157/** 153/**
158 * Function to call when we disconnected from a peer and can henceforth 154 * Function to call when we disconnected from a peer and can henceforth
159 * cannot transmit to that peer anymore. 155 * cannot transmit to that peer anymore.
@@ -183,6 +179,15 @@ GDS_u_receive (void *cls,
183 179
184 180
185/** 181/**
182 * Send @a msg to all peers in our buckets.
183 *
184 * @param msg message to broadcast
185 */
186void
187GDS_NEIGHBOURS_broadcast (const struct GNUNET_MessageHeader *msg);
188
189
190/**
186 * Initialize neighbours subsystem. 191 * Initialize neighbours subsystem.
187 * 192 *
188 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 193 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
diff --git a/src/dht/gnunet-service-dht_routing.c b/src/dht/gnunet-service-dht_routing.c
index e7b5c3571..ec3f5b46f 100644
--- a/src/dht/gnunet-service-dht_routing.c
+++ b/src/dht/gnunet-service-dht_routing.c
@@ -151,7 +151,7 @@ process (void *cls,
151 bdx.put_path_length = 0; 151 bdx.put_path_length = 0;
152 bdx.put_path = NULL; 152 bdx.put_path = NULL;
153 } 153 }
154 if ( (0 == (rr->options & GNUNET_DHT_RO_FIND_PEER)) && 154 if ( (0 == (rr->options & GNUNET_DHT_RO_FIND_APPROXIMATE)) &&
155 (0 != GNUNET_memcmp (query_hash, 155 (0 != GNUNET_memcmp (query_hash,
156 &bdx.key)) ) 156 &bdx.key)) )
157 { 157 {