diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-01-15 19:24:33 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-02-19 12:39:55 +0100 |
commit | b0abdf7127f2403ff583d224e0d9d4e68c1c5bfc (patch) | |
tree | 47df762cdbcce501ec5536c8963b5c9ee55da31d /src/dht/gnunet-service-dht_neighbours.c | |
parent | 3a71153405e8fc26712807b4bdb5987fb3bf2b9e (diff) | |
download | gnunet-b0abdf7127f2403ff583d224e0d9d4e68c1c5bfc.tar.gz gnunet-b0abdf7127f2403ff583d224e0d9d4e68c1c5bfc.zip |
-more work on DHTU integration
Diffstat (limited to 'src/dht/gnunet-service-dht_neighbours.c')
-rw-r--r-- | src/dht/gnunet-service-dht_neighbours.c | 1108 |
1 files changed, 554 insertions, 554 deletions
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 | */ | ||
94 | extern struct GNUNET_TIME_Relative hello_expiration; | ||
95 | |||
96 | 91 | ||
97 | GNUNET_NETWORK_STRUCT_BEGIN | 92 | GNUNET_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 | */ |
263 | struct PeerInfo | 258 | struct PeerInfo; |
259 | |||
260 | |||
261 | /** | ||
262 | * List of targets that we can use to reach this peer. | ||
263 | */ | ||
264 | struct 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 | */ |
300 | struct PeerBucket | 308 | struct 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 | */ |
322 | struct ConnectInfo | 365 | struct 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]; | |||
371 | static struct GNUNET_CONTAINER_MultiPeerMap *all_connected_peers; | 414 | static 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 | */ | ||
377 | static struct GNUNET_CONTAINER_MultiPeerMap *all_desired_peers; | ||
378 | |||
379 | /** | ||
380 | * Maximum size for each bucket. | 417 | * Maximum size for each bucket. |
381 | */ | 418 | */ |
382 | static unsigned int bucket_size = DEFAULT_BUCKET_SIZE; | 419 | static unsigned int bucket_size = DEFAULT_BUCKET_SIZE; |
@@ -386,20 +423,83 @@ static unsigned int bucket_size = DEFAULT_BUCKET_SIZE; | |||
386 | */ | 423 | */ |
387 | static struct GNUNET_SCHEDULER_Task *find_peer_task; | 424 | static struct GNUNET_SCHEDULER_Task *find_peer_task; |
388 | 425 | ||
389 | /** | ||
390 | * Identity of this peer. | ||
391 | */ | ||
392 | static 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 | */ |
397 | struct GNUNET_HashCode my_identity_hash; | 434 | static void |
435 | send_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 | */ |
402 | static struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key; | 465 | static void |
466 | do_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 | */ | ||
478 | static void | ||
479 | offer_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 | */ | ||
495 | static enum GNUNET_GenericReturnValue | ||
496 | free_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 | */ | ||
530 | static void | ||
531 | try_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 | */ | ||
616 | static enum GNUNET_GenericReturnValue | ||
617 | update_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 | */ | ||
632 | static void | ||
633 | update_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 | */ | ||
825 | void | 764 | void |
826 | GDS_u_disconnect (void *ctx) | 765 | GDS_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 | |||
935 | GDS_am_closest_peer (const struct GNUNET_HashCode *key, | 891 | GDS_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 | */ |
1885 | static void | 1804 | static void |
1886 | handle_find_peer (struct PeerInfo *pi, | 1805 | handle_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 | */ | ||
1875 | static void | ||
1876 | handle_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 | */ | ||
2200 | static void | ||
2201 | try_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 | */ | ||
2363 | static enum GNUNET_GenericReturnValue | ||
2364 | check_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 | */ | ||
2383 | static void | ||
2384 | handle_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 | |||
2394 | void | 2400 | void |
2395 | GDS_u_receive (void *cls, | 2401 | GDS_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 | */ | ||
2456 | void | ||
2457 | GDS_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 | |||
2441 | enum GNUNET_GenericReturnValue | 2479 | enum GNUNET_GenericReturnValue |
2442 | GDS_NEIGHBOURS_init () | 2480 | GDS_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 () | |||
2518 | struct GNUNET_PeerIdentity * | 2518 | struct GNUNET_PeerIdentity * |
2519 | GDS_NEIGHBOURS_get_id () | 2519 | GDS_NEIGHBOURS_get_id () |
2520 | { | 2520 | { |
2521 | return &my_identity; | 2521 | return &GDS_my_identity; |
2522 | } | 2522 | } |
2523 | 2523 | ||
2524 | 2524 | ||