diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cadet/gnunet-service-cadet-new_peer.c | 373 |
1 files changed, 210 insertions, 163 deletions
diff --git a/src/cadet/gnunet-service-cadet-new_peer.c b/src/cadet/gnunet-service-cadet-new_peer.c index 11fd29657..fe344fcbf 100644 --- a/src/cadet/gnunet-service-cadet-new_peer.c +++ b/src/cadet/gnunet-service-cadet-new_peer.c | |||
@@ -225,19 +225,18 @@ struct CadetPeer | |||
225 | /** | 225 | /** |
226 | * Get the static string for a peer ID. | 226 | * Get the static string for a peer ID. |
227 | * | 227 | * |
228 | * @param peer Peer. | 228 | * @param cp Peer. |
229 | * | ||
230 | * @return Static string for it's ID. | 229 | * @return Static string for it's ID. |
231 | */ | 230 | */ |
232 | const char * | 231 | const char * |
233 | GCP_2s (const struct CadetPeer *peer) | 232 | GCP_2s (const struct CadetPeer *cp) |
234 | { | 233 | { |
235 | static char buf[64]; | 234 | static char buf[32]; |
236 | 235 | ||
237 | GNUNET_snprintf (buf, | 236 | GNUNET_snprintf (buf, |
238 | sizeof (buf), | 237 | sizeof (buf), |
239 | "P(%s)", | 238 | "P(%s)", |
240 | GNUNET_i2s (&peer->pid)); | 239 | GNUNET_i2s (&cp->pid)); |
241 | return buf; | 240 | return buf; |
242 | } | 241 | } |
243 | 242 | ||
@@ -297,6 +296,146 @@ destroy_peer (void *cls) | |||
297 | 296 | ||
298 | 297 | ||
299 | /** | 298 | /** |
299 | * This peer is now on more "active" duty, activate processes related to it. | ||
300 | * | ||
301 | * @param cp the more-active peer | ||
302 | */ | ||
303 | static void | ||
304 | consider_peer_activate (struct CadetPeer *cp) | ||
305 | { | ||
306 | uint32_t strength; | ||
307 | |||
308 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
309 | "Updating peer %s activation state (%u connections)%s%s\n", | ||
310 | GCP_2s (cp), | ||
311 | GNUNET_CONTAINER_multishortmap_size (cp->connections), | ||
312 | (NULL == cp->t) ? "" : " with tunnel", | ||
313 | (NULL == cp->core_mq) ? "" : " with CORE link"); | ||
314 | if (NULL != cp->destroy_task) | ||
315 | { | ||
316 | /* It's active, do not destory! */ | ||
317 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
318 | cp->destroy_task = NULL; | ||
319 | } | ||
320 | if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) && | ||
321 | (NULL == cp->t) ) | ||
322 | { | ||
323 | /* We're just on a path or directly connected; don't bother too much */ | ||
324 | if (NULL != cp->connectivity_suggestion) | ||
325 | { | ||
326 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); | ||
327 | cp->connectivity_suggestion = NULL; | ||
328 | } | ||
329 | if (NULL != cp->search_h) | ||
330 | { | ||
331 | GCD_search_stop (cp->search_h); | ||
332 | cp->search_h = NULL; | ||
333 | } | ||
334 | return; | ||
335 | } | ||
336 | if (NULL == cp->core_mq) | ||
337 | { | ||
338 | /* Lacks direct connection, try to create one by querying the DHT */ | ||
339 | if ( (NULL == cp->search_h) && | ||
340 | (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) ) | ||
341 | cp->search_h | ||
342 | = GCD_search (&cp->pid); | ||
343 | } | ||
344 | else | ||
345 | { | ||
346 | /* Have direct connection, stop DHT search if active */ | ||
347 | if (NULL != cp->search_h) | ||
348 | { | ||
349 | GCD_search_stop (cp->search_h); | ||
350 | cp->search_h = NULL; | ||
351 | } | ||
352 | } | ||
353 | |||
354 | /* If we have a tunnel, our urge for connections is much bigger */ | ||
355 | strength = (NULL != cp->t) ? 32 : 1; | ||
356 | if (NULL != cp->connectivity_suggestion) | ||
357 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); | ||
358 | cp->connectivity_suggestion | ||
359 | = GNUNET_ATS_connectivity_suggest (ats_ch, | ||
360 | &cp->pid, | ||
361 | strength); | ||
362 | } | ||
363 | |||
364 | |||
365 | /** | ||
366 | * This peer may no longer be needed, consider cleaning it up. | ||
367 | * | ||
368 | * @param cp peer to clean up | ||
369 | */ | ||
370 | static void | ||
371 | consider_peer_destroy (struct CadetPeer *cp); | ||
372 | |||
373 | |||
374 | /** | ||
375 | * We really no longere care about a peer, stop hogging memory with paths to it. | ||
376 | * Afterwards, see if there is more to be cleaned up about this peer. | ||
377 | * | ||
378 | * @param cls a `struct CadetPeer`. | ||
379 | */ | ||
380 | static void | ||
381 | drop_paths (void *cls) | ||
382 | { | ||
383 | struct CadetPeer *cp = cls; | ||
384 | struct CadetPeerPath *path; | ||
385 | |||
386 | cp->destroy_task = NULL; | ||
387 | while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap))) | ||
388 | GCPP_release (path); | ||
389 | consider_peer_destroy (cp); | ||
390 | } | ||
391 | |||
392 | |||
393 | /** | ||
394 | * This peer may no longer be needed, consider cleaning it up. | ||
395 | * | ||
396 | * @param cp peer to clean up | ||
397 | */ | ||
398 | static void | ||
399 | consider_peer_destroy (struct CadetPeer *cp) | ||
400 | { | ||
401 | struct GNUNET_TIME_Relative exp; | ||
402 | |||
403 | if (NULL != cp->destroy_task) | ||
404 | { | ||
405 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
406 | cp->destroy_task = NULL; | ||
407 | } | ||
408 | if (NULL != cp->t) | ||
409 | return; /* still relevant! */ | ||
410 | if (NULL != cp->core_mq) | ||
411 | return; /* still relevant! */ | ||
412 | if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections)) | ||
413 | return; /* still relevant! */ | ||
414 | if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap)) | ||
415 | { | ||
416 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT, | ||
417 | &drop_paths, | ||
418 | cp); | ||
419 | return; | ||
420 | } | ||
421 | if (0 < cp->path_dll_length) | ||
422 | return; /* still relevant! */ | ||
423 | if (NULL != cp->hello) | ||
424 | { | ||
425 | /* relevant only until HELLO expires */ | ||
426 | exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello)); | ||
427 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp, | ||
428 | &destroy_peer, | ||
429 | cp); | ||
430 | return; | ||
431 | } | ||
432 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT, | ||
433 | &destroy_peer, | ||
434 | cp); | ||
435 | } | ||
436 | |||
437 | |||
438 | /** | ||
300 | * Set the message queue to @a mq for peer @a cp and notify watchers. | 439 | * Set the message queue to @a mq for peer @a cp and notify watchers. |
301 | * | 440 | * |
302 | * @param cp peer to modify | 441 | * @param cp peer to modify |
@@ -311,7 +450,6 @@ GCP_set_mq (struct CadetPeer *cp, | |||
311 | GCP_2s (cp), | 450 | GCP_2s (cp), |
312 | mq); | 451 | mq); |
313 | cp->core_mq = mq; | 452 | cp->core_mq = mq; |
314 | |||
315 | for (struct GCP_MessageQueueManager *mqm = cp->mqm_head; | 453 | for (struct GCP_MessageQueueManager *mqm = cp->mqm_head; |
316 | NULL != mqm; | 454 | NULL != mqm; |
317 | mqm = mqm->next) | 455 | mqm = mqm->next) |
@@ -338,6 +476,24 @@ GCP_set_mq (struct CadetPeer *cp, | |||
338 | GNUNET_YES); | 476 | GNUNET_YES); |
339 | } | 477 | } |
340 | } | 478 | } |
479 | if ( (NULL != mq) || | ||
480 | (NULL != cp->t) ) | ||
481 | consider_peer_activate (cp); | ||
482 | else | ||
483 | consider_peer_destroy (cp); | ||
484 | |||
485 | if ( (NULL != mq) && | ||
486 | (NULL != cp->t) ) | ||
487 | { | ||
488 | /* have a new, direct path to the target, notify tunnel */ | ||
489 | struct CadetPeerPath *path; | ||
490 | |||
491 | path = GCPP_get_path_from_route (1, | ||
492 | &cp->pid); | ||
493 | GCT_consider_path (cp->t, | ||
494 | path, | ||
495 | 0); | ||
496 | } | ||
341 | } | 497 | } |
342 | 498 | ||
343 | 499 | ||
@@ -472,79 +628,6 @@ GCP_destroy_all_peers () | |||
472 | 628 | ||
473 | 629 | ||
474 | /** | 630 | /** |
475 | * This peer may no longer be needed, consider cleaning it up. | ||
476 | * | ||
477 | * @param cp peer to clean up | ||
478 | */ | ||
479 | static void | ||
480 | consider_peer_destroy (struct CadetPeer *cp); | ||
481 | |||
482 | |||
483 | /** | ||
484 | * We really no longere care about a peer, stop hogging memory with paths to it. | ||
485 | * Afterwards, see if there is more to be cleaned up about this peer. | ||
486 | * | ||
487 | * @param cls a `struct CadetPeer`. | ||
488 | */ | ||
489 | static void | ||
490 | drop_paths (void *cls) | ||
491 | { | ||
492 | struct CadetPeer *cp = cls; | ||
493 | struct CadetPeerPath *path; | ||
494 | |||
495 | cp->destroy_task = NULL; | ||
496 | while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap))) | ||
497 | GCPP_release (path); | ||
498 | consider_peer_destroy (cp); | ||
499 | } | ||
500 | |||
501 | |||
502 | /** | ||
503 | * This peer may no longer be needed, consider cleaning it up. | ||
504 | * | ||
505 | * @param cp peer to clean up | ||
506 | */ | ||
507 | static void | ||
508 | consider_peer_destroy (struct CadetPeer *cp) | ||
509 | { | ||
510 | struct GNUNET_TIME_Relative exp; | ||
511 | |||
512 | if (NULL != cp->destroy_task) | ||
513 | { | ||
514 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
515 | cp->destroy_task = NULL; | ||
516 | } | ||
517 | if (NULL != cp->t) | ||
518 | return; /* still relevant! */ | ||
519 | if (NULL != cp->core_mq) | ||
520 | return; /* still relevant! */ | ||
521 | if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections)) | ||
522 | return; /* still relevant! */ | ||
523 | if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap)) | ||
524 | { | ||
525 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT, | ||
526 | &drop_paths, | ||
527 | cp); | ||
528 | return; | ||
529 | } | ||
530 | if (0 < cp->path_dll_length) | ||
531 | return; /* still relevant! */ | ||
532 | if (NULL != cp->hello) | ||
533 | { | ||
534 | /* relevant only until HELLO expires */ | ||
535 | exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello)); | ||
536 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp, | ||
537 | &destroy_peer, | ||
538 | cp); | ||
539 | return; | ||
540 | } | ||
541 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT, | ||
542 | &destroy_peer, | ||
543 | cp); | ||
544 | } | ||
545 | |||
546 | |||
547 | /** | ||
548 | * Add an entry to the DLL of all of the paths that this peer is on. | 631 | * Add an entry to the DLL of all of the paths that this peer is on. |
549 | * | 632 | * |
550 | * @param cp peer to modify | 633 | * @param cp peer to modify |
@@ -583,6 +666,14 @@ GCP_path_entry_add (struct CadetPeer *cp, | |||
583 | GCT_consider_path (cp->t, | 666 | GCT_consider_path (cp->t, |
584 | entry->path, | 667 | entry->path, |
585 | off); | 668 | off); |
669 | |||
670 | if ( (NULL != cp->search_h) && | ||
671 | (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths) ) | ||
672 | { | ||
673 | /* Now I have enough paths, stop search */ | ||
674 | GCD_search_stop (cp->search_h); | ||
675 | cp->search_h = NULL; | ||
676 | } | ||
586 | } | 677 | } |
587 | 678 | ||
588 | 679 | ||
@@ -608,6 +699,12 @@ GCP_path_entry_remove (struct CadetPeer *cp, | |||
608 | entry); | 699 | entry); |
609 | GNUNET_assert (0 < cp->num_paths); | 700 | GNUNET_assert (0 < cp->num_paths); |
610 | cp->num_paths--; | 701 | cp->num_paths--; |
702 | if ( (NULL == cp->core_mq) && | ||
703 | (NULL != cp->t) && | ||
704 | (NULL == cp->search_h) && | ||
705 | (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) ) | ||
706 | cp->search_h | ||
707 | = GCD_search (&cp->pid); | ||
611 | } | 708 | } |
612 | 709 | ||
613 | 710 | ||
@@ -633,10 +730,10 @@ GCP_attach_path (struct CadetPeer *cp, | |||
633 | GNUNET_CONTAINER_HeapCostType root_desirability; | 730 | GNUNET_CONTAINER_HeapCostType root_desirability; |
634 | struct GNUNET_CONTAINER_HeapNode *hn; | 731 | struct GNUNET_CONTAINER_HeapNode *hn; |
635 | 732 | ||
733 | desirability = GCPP_get_desirability (path); | ||
636 | if (GNUNET_NO == force) | 734 | if (GNUNET_NO == force) |
637 | { | 735 | { |
638 | /* FIXME: desirability is not yet initialized; tricky! */ | 736 | /* FIXME: desirability is not yet initialized; tricky! */ |
639 | desirability = GCPP_get_desirability (path); | ||
640 | if (GNUNET_NO == | 737 | if (GNUNET_NO == |
641 | GNUNET_CONTAINER_heap_peek2 (cp->path_heap, | 738 | GNUNET_CONTAINER_heap_peek2 (cp->path_heap, |
642 | (void **) &root, | 739 | (void **) &root, |
@@ -665,7 +762,7 @@ GCP_attach_path (struct CadetPeer *cp, | |||
665 | 762 | ||
666 | /* Yes, we'd like to add this path, add to our heap */ | 763 | /* Yes, we'd like to add this path, add to our heap */ |
667 | hn = GNUNET_CONTAINER_heap_insert (cp->path_heap, | 764 | hn = GNUNET_CONTAINER_heap_insert (cp->path_heap, |
668 | (void *) cp, | 765 | path, |
669 | desirability); | 766 | desirability); |
670 | 767 | ||
671 | /* Consider maybe dropping other paths because of the new one */ | 768 | /* Consider maybe dropping other paths because of the new one */ |
@@ -761,73 +858,6 @@ GCP_remove_connection (struct CadetPeer *cp, | |||
761 | 858 | ||
762 | 859 | ||
763 | /** | 860 | /** |
764 | * This peer is now on more "active" duty, activate processes related to it. | ||
765 | * | ||
766 | * @param cp the more-active peer | ||
767 | */ | ||
768 | static void | ||
769 | consider_peer_activate (struct CadetPeer *cp) | ||
770 | { | ||
771 | uint32_t strength; | ||
772 | |||
773 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
774 | "Updating peer %s activation state (%u connections)%s%s\n", | ||
775 | GCP_2s (cp), | ||
776 | GNUNET_CONTAINER_multishortmap_size (cp->connections), | ||
777 | (NULL == cp->t) ? "" : " with tunnel", | ||
778 | (NULL == cp->core_mq) ? "" : " with CORE link"); | ||
779 | if (NULL != cp->destroy_task) | ||
780 | { | ||
781 | /* It's active, do not destory! */ | ||
782 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
783 | cp->destroy_task = NULL; | ||
784 | } | ||
785 | if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) && | ||
786 | (NULL == cp->t) ) | ||
787 | { | ||
788 | /* We're just on a path or directly connected; don't bother too much */ | ||
789 | if (NULL != cp->connectivity_suggestion) | ||
790 | { | ||
791 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); | ||
792 | cp->connectivity_suggestion = NULL; | ||
793 | } | ||
794 | if (NULL != cp->search_h) | ||
795 | { | ||
796 | GCD_search_stop (cp->search_h); | ||
797 | cp->search_h = NULL; | ||
798 | } | ||
799 | return; | ||
800 | } | ||
801 | if (NULL == cp->core_mq) | ||
802 | { | ||
803 | /* Lacks direct connection, try to create one by querying the DHT */ | ||
804 | if ( (NULL == cp->search_h) && | ||
805 | (DESIRED_CONNECTIONS_PER_TUNNEL < cp->num_paths) ) | ||
806 | cp->search_h | ||
807 | = GCD_search (&cp->pid); | ||
808 | } | ||
809 | else | ||
810 | { | ||
811 | /* Have direct connection, stop DHT search if active */ | ||
812 | if (NULL != cp->search_h) | ||
813 | { | ||
814 | GCD_search_stop (cp->search_h); | ||
815 | cp->search_h = NULL; | ||
816 | } | ||
817 | } | ||
818 | |||
819 | /* If we have a tunnel, our urge for connections is much bigger */ | ||
820 | strength = (NULL != cp->t) ? 32 : 1; | ||
821 | if (NULL != cp->connectivity_suggestion) | ||
822 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); | ||
823 | cp->connectivity_suggestion | ||
824 | = GNUNET_ATS_connectivity_suggest (ats_ch, | ||
825 | &cp->pid, | ||
826 | strength); | ||
827 | } | ||
828 | |||
829 | |||
830 | /** | ||
831 | * Retrieve the CadetPeer stucture associated with the | 861 | * Retrieve the CadetPeer stucture associated with the |
832 | * peer. Optionally create one and insert it in the appropriate | 862 | * peer. Optionally create one and insert it in the appropriate |
833 | * structures if the peer is not known yet. | 863 | * structures if the peer is not known yet. |
@@ -899,43 +929,60 @@ GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, | |||
899 | /** | 929 | /** |
900 | * Count the number of known paths toward the peer. | 930 | * Count the number of known paths toward the peer. |
901 | * | 931 | * |
902 | * @param peer Peer to get path info. | 932 | * @param cp Peer to get path info. |
903 | * @return Number of known paths. | 933 | * @return Number of known paths. |
904 | */ | 934 | */ |
905 | unsigned int | 935 | unsigned int |
906 | GCP_count_paths (const struct CadetPeer *peer) | 936 | GCP_count_paths (const struct CadetPeer *cp) |
907 | { | 937 | { |
908 | return peer->num_paths; | 938 | return cp->num_paths; |
909 | } | 939 | } |
910 | 940 | ||
911 | 941 | ||
912 | /** | 942 | /** |
913 | * Iterate over the paths to a peer. | 943 | * Iterate over the paths to a peer. |
914 | * | 944 | * |
915 | * @param peer Peer to get path info. | 945 | * @param cp Peer to get path info. |
916 | * @param callback Function to call for every path. | 946 | * @param callback Function to call for every path. |
917 | * @param callback_cls Closure for @a callback. | 947 | * @param callback_cls Closure for @a callback. |
918 | * @return Number of iterated paths. | 948 | * @return Number of iterated paths. |
919 | */ | 949 | */ |
920 | unsigned int | 950 | unsigned int |
921 | GCP_iterate_paths (struct CadetPeer *peer, | 951 | GCP_iterate_paths (struct CadetPeer *cp, |
922 | GCP_PathIterator callback, | 952 | GCP_PathIterator callback, |
923 | void *callback_cls) | 953 | void *callback_cls) |
924 | { | 954 | { |
925 | unsigned int ret = 0; | 955 | unsigned int ret = 0; |
926 | 956 | ||
927 | for (unsigned int i=0;i<peer->path_dll_length;i++) | 957 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
958 | "Iterating over paths to peer %s%s\n", | ||
959 | GCP_2s (cp), | ||
960 | (NULL == cp->core_mq) ? "" : " including direct link"); | ||
961 | if (NULL != cp->core_mq) | ||
962 | { | ||
963 | struct CadetPeerPath *path; | ||
964 | |||
965 | path = GCPP_get_path_from_route (1, | ||
966 | &cp->pid); | ||
967 | ret++; | ||
968 | if (GNUNET_NO == | ||
969 | callback (callback_cls, | ||
970 | path, | ||
971 | 1)) | ||
972 | return ret; | ||
973 | } | ||
974 | for (unsigned int i=0;i<cp->path_dll_length;i++) | ||
928 | { | 975 | { |
929 | for (struct CadetPeerPathEntry *pe = peer->path_heads[i]; | 976 | for (struct CadetPeerPathEntry *pe = cp->path_heads[i]; |
930 | NULL != pe; | 977 | NULL != pe; |
931 | pe = pe->next) | 978 | pe = pe->next) |
932 | { | 979 | { |
980 | ret++; | ||
933 | if (GNUNET_NO == | 981 | if (GNUNET_NO == |
934 | callback (callback_cls, | 982 | callback (callback_cls, |
935 | pe->path, | 983 | pe->path, |
936 | i)) | 984 | i)) |
937 | return ret; | 985 | return ret; |
938 | ret++; | ||
939 | } | 986 | } |
940 | } | 987 | } |
941 | return ret; | 988 | return ret; |
@@ -943,26 +990,26 @@ GCP_iterate_paths (struct CadetPeer *peer, | |||
943 | 990 | ||
944 | 991 | ||
945 | /** | 992 | /** |
946 | * Iterate over the paths to @a peer where | 993 | * Iterate over the paths to @a cp where |
947 | * @a peer is at distance @a dist from us. | 994 | * @a cp is at distance @a dist from us. |
948 | * | 995 | * |
949 | * @param peer Peer to get path info. | 996 | * @param cp Peer to get path info. |
950 | * @param dist desired distance of @a peer to us on the path | 997 | * @param dist desired distance of @a cp to us on the path |
951 | * @param callback Function to call for every path. | 998 | * @param callback Function to call for every path. |
952 | * @param callback_cls Closure for @a callback. | 999 | * @param callback_cls Closure for @a callback. |
953 | * @return Number of iterated paths. | 1000 | * @return Number of iterated paths. |
954 | */ | 1001 | */ |
955 | unsigned int | 1002 | unsigned int |
956 | GCP_iterate_paths_at (struct CadetPeer *peer, | 1003 | GCP_iterate_paths_at (struct CadetPeer *cp, |
957 | unsigned int dist, | 1004 | unsigned int dist, |
958 | GCP_PathIterator callback, | 1005 | GCP_PathIterator callback, |
959 | void *callback_cls) | 1006 | void *callback_cls) |
960 | { | 1007 | { |
961 | unsigned int ret = 0; | 1008 | unsigned int ret = 0; |
962 | 1009 | ||
963 | if (dist<peer->path_dll_length) | 1010 | if (dist <= cp->path_dll_length) |
964 | return 0; | 1011 | return 0; |
965 | for (struct CadetPeerPathEntry *pe = peer->path_heads[dist]; | 1012 | for (struct CadetPeerPathEntry *pe = cp->path_heads[dist]; |
966 | NULL != pe; | 1013 | NULL != pe; |
967 | pe = pe->next) | 1014 | pe = pe->next) |
968 | { | 1015 | { |