2 This file is part of GNUnet.
3 Copyright (C) 2009-2014 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file dht/gnunet-service-xdht_neighbours.c
23 * @brief GNUnet DHT service's finger and friend table management code
24 * @author Supriti Singh
28 #include "gnunet_util_lib.h"
29 #include "gnunet_block_lib.h"
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_protocols.h"
33 #include "gnunet_ats_service.h"
34 #include "gnunet_core_service.h"
35 #include "gnunet_datacache_lib.h"
36 #include "gnunet_transport_service.h"
37 #include "gnunet_dht_service.h"
38 #include "gnunet_statistics_service.h"
39 #include "gnunet-service-xdht.h"
40 #include "gnunet-service-wdht_clients.h"
41 #include "gnunet-service-wdht_datacache.h"
42 #include "gnunet-service-wdht_neighbours.h"
43 #include "gnunet-service-wdht_routing.h"
48 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
53 #define FOO_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
56 GNUNET_NETWORK_STRUCT_BEGIN
59 * Setup a finger using the underlay topology ("social network").
61 struct FingerSetupMessage
64 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP
66 struct GNUNET_MessageHeader header;
69 * Number of hops this message has taken so far, we stop at
72 uint16_t hops_taken GNUNET_PACKED;
75 * Layer for the request, in NBO.
77 uint16_t layer GNUNET_PACKED;
80 * Unique (random) identifier this peer will use to
81 * identify the finger (in future messages).
83 struct GNUNET_HashCode finger_id;
89 * Response to a `struct FingerSetupMessage`.
91 struct FingerSetupResponseMessage
94 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP_RESPONSE
96 struct GNUNET_MessageHeader header;
99 * Zero, for alignment.
101 uint32_t reserved GNUNET_PACKED;
104 * Unique (random) identifier this peer will use to
105 * identify the finger (in future messages).
107 struct GNUNET_HashCode finger_id;
110 * Random location in the respective layer where the
111 * random path of the finger setup terminated.
113 struct GNUNET_HashCode location;
119 * Response to an event that causes a finger to die.
121 struct FingerDestroyMessage
124 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_DESTROY
126 struct GNUNET_MessageHeader header;
129 * Zero, for alignment.
131 uint32_t reserved GNUNET_PACKED;
134 * Unique (random) identifier this peer will use to
135 * identify the finger (in future messages).
137 struct GNUNET_HashCode finger_id;
143 * Send a message along a finger.
145 struct FingerRouteMessage
148 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_ROUTE
150 struct GNUNET_MessageHeader header;
153 * Zero, for alignment.
155 uint32_t reserved GNUNET_PACKED;
158 * Unique (random) identifier this peer will use to
159 * identify the finger (in future messages).
161 struct GNUNET_HashCode finger_id;
163 /* followed by payload to send along the finger */
170 struct PeerPutMessage
173 * Type: #GNUNET_MESSAGE_TYPE_WDHT_P2P_PUT
175 struct GNUNET_MessageHeader header;
180 uint32_t options GNUNET_PACKED;
185 uint32_t block_type GNUNET_PACKED;
190 uint32_t hop_count GNUNET_PACKED;
193 * Replication level for this message
194 * In the current implementation, this value is not used.
196 uint32_t desired_replication_level GNUNET_PACKED;
199 * Length of the PUT path that follows (if tracked).
201 uint32_t put_path_length GNUNET_PACKED;
204 * When does the content expire?
206 struct GNUNET_TIME_AbsoluteNBO expiration_time;
209 * The key to store the value under.
211 struct GNUNET_HashCode key GNUNET_PACKED;
213 /* put path (if tracked) */
222 struct PeerGetMessage
225 * Type: #GNUNET_MESSAGE_TYPE_WDHT_P2P_GET
227 struct GNUNET_MessageHeader header;
232 uint32_t options GNUNET_PACKED;
235 * Desired content type.
237 uint32_t block_type GNUNET_PACKED;
242 uint32_t hop_count GNUNET_PACKED;
245 * Desired replication level for this request.
246 * In the current implementation, this value is not used.
248 uint32_t desired_replication_level GNUNET_PACKED;
251 * Total number of peers in get path.
253 unsigned int get_path_length;
256 * The key we are looking for.
258 struct GNUNET_HashCode key;
261 /* struct GNUNET_PeerIdentity[]*/
268 struct PeerGetResultMessage
271 * Type: #GNUNET_MESSAGE_TYPE_WDHT_P2P_GET_RESULT
273 struct GNUNET_MessageHeader header;
276 * The type for the data.
278 uint32_t type GNUNET_PACKED;
281 * Number of peers recorded in the outgoing path from source to the
282 * stored location of this message.
284 uint32_t put_path_length GNUNET_PACKED;
287 * Length of the GET path that follows (if tracked).
289 uint32_t get_path_length GNUNET_PACKED;
292 * Peer which queried for get and should get the result.
294 struct GNUNET_PeerIdentity querying_peer;
297 * When does the content expire?
299 struct GNUNET_TIME_Absolute expiration_time;
302 * The key of the corresponding GET request.
304 struct GNUNET_HashCode key;
306 /* put path (if tracked) */
308 /* get path (if tracked) */
314 GNUNET_NETWORK_STRUCT_END
317 * Entry in friend_peermap.
323 * Information we keep per trail.
329 * MDLL entry in the list of all trails with the same predecessor.
331 struct Tail *prev_succ;
334 * MDLL entry in the list of all trails with the same predecessor.
336 struct Tail *next_succ;
339 * MDLL entry in the list of all trails with the same predecessor.
341 struct Tail *prev_pred;
344 * MDLL entry in the list of all trails with the same predecessor.
346 struct Tail *next_pred;
349 * Our predecessor in the trail, NULL if we are initiator (?).
351 struct FriendInfo *pred;
354 * Our successor in the trail, NULL if we are the last peer.
356 struct FriendInfo *succ;
359 * Identifier of the trail with the predecessor.
361 struct GNUNET_HashCode pred_id;
364 * Identifier of the trail with the successor.
366 struct GNUNET_HashCode succ_id;
369 * When does this trail expire.
371 struct GNUNET_TIME_Absolute expiration_time;
377 * Entry in friend_peermap.
384 struct GNUNET_PeerIdentity id;
386 struct Tail *pred_head;
388 struct Tail *pred_tail;
390 struct Tail *succ_head;
392 struct Tail *succ_tail;
395 * Core handle for sending messages to this friend.
398 struct GNUNET_CORE_TransmitHandle *th;
405 * Task to timeout trails that have expired.
407 static struct GNUNET_SCHEDULER_Task *trail_timeout_task;
410 * Identity of this peer.
412 static struct GNUNET_PeerIdentity my_identity;
415 * Peer map of all the friends of a peer
417 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap;
420 * Tail map, mapping tail identifiers to `struct Trail`s
422 static struct GNUNET_CONTAINER_MultiHashMap *tail_map;
425 * Tail heap, organizing trails by expiration time.
427 static struct GNUNET_CONTAINER_Heap *tail_heap;
432 static struct GNUNET_CORE_Handle *core_api;
441 * Construct a trail setup message and forward it to target_friend
442 * @param source_peer Peer which wants to setup the trail
443 * @param ultimate_destination_finger_value Peer identity closest to this value
444 * will be finger to @a source_peer
445 * @param best_known_destination Best known destination (could be finger or friend)
446 * which should get this message. In case it is
447 * friend, then it is same as target_friend
448 * @param target_friend Friend to which message is forwarded now.
449 * @param trail_length Total number of peers in trail setup so far.
450 * @param trail_peer_list Trail setup so far
451 * @param is_predecessor Is @a source_peer looking for trail to a predecessor or not.
452 * @param trail_id Unique identifier for the trail we are trying to setup.
453 * @param intermediate_trail_id Trail id of intermediate trail to reach to
454 * best_known_destination when its a finger. If not
455 * used then set to 0.
458 GDS_NEIGHBOURS_send_trail_setup (struct GNUNET_PeerIdentity source_peer,
459 uint64_t ultimate_destination_finger_value,
460 struct GNUNET_PeerIdentity best_known_destination,
461 struct FriendInfo *target_friend,
462 unsigned int trail_length,
463 const struct GNUNET_PeerIdentity *trail_peer_list,
464 unsigned int is_predecessor,
465 struct GNUNET_HashCode trail_id,
466 struct GNUNET_HashCode intermediate_trail_id)
468 struct P2PPendingMessage *pending;
469 struct PeerTrailSetupMessage *tsm;
470 struct GNUNET_PeerIdentity *peer_list;
473 msize = sizeof (struct PeerTrailSetupMessage) +
474 (trail_length * sizeof (struct GNUNET_PeerIdentity));
476 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
482 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
484 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
487 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
488 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
489 tsm = (struct PeerTrailSetupMessage *) &pending[1];
490 pending->msg = &(tsm->header);
491 tsm->header.size = htons (msize);
492 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP);
493 tsm->final_destination_finger_value = GNUNET_htonll (ultimate_destination_finger_value);
494 tsm->source_peer = source_peer;
495 tsm->best_known_destination = best_known_destination;
496 tsm->is_predecessor = htonl (is_predecessor);
497 tsm->trail_id = trail_id;
498 tsm->intermediate_trail_id = intermediate_trail_id;
500 if (trail_length > 0)
502 peer_list = (struct GNUNET_PeerIdentity *) &tsm[1];
503 memcpy (peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
506 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
507 target_friend->pending_count++;
508 process_friend_queue (target_friend);
513 * Construct a trail setup result message and forward it to target friend.
514 * @param querying_peer Peer which sent the trail setup request and should get
516 * @param Finger Peer to which the trail has been setup to.
517 * @param target_friend Friend to which this message should be forwarded.
518 * @param trail_length Numbers of peers in the trail.
519 * @param trail_peer_list Peers which are part of the trail from
520 * querying_peer to Finger, NOT including them.
521 * @param is_predecessor Is @a Finger predecessor to @a querying_peer ?
522 * @param ultimate_destination_finger_value Value to which @a finger is the closest
524 * @param trail_id Unique identifier of the trail.
527 GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity querying_peer,
528 struct GNUNET_PeerIdentity finger,
529 struct FriendInfo *target_friend,
530 unsigned int trail_length,
531 const struct GNUNET_PeerIdentity *trail_peer_list,
532 unsigned int is_predecessor,
533 uint64_t ultimate_destination_finger_value,
534 struct GNUNET_HashCode trail_id)
536 struct P2PPendingMessage *pending;
537 struct PeerTrailSetupResultMessage *tsrm;
538 struct GNUNET_PeerIdentity *peer_list;
541 msize = sizeof (struct PeerTrailSetupResultMessage) +
542 (trail_length * sizeof (struct GNUNET_PeerIdentity));
544 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
550 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
552 GNUNET_STATISTICS_update (GDS_stats,
553 gettext_noop ("# P2P messages dropped due to full queue"),
557 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
558 pending->importance = 0;
559 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
560 tsrm = (struct PeerTrailSetupResultMessage *) &pending[1];
561 pending->msg = &tsrm->header;
562 tsrm->header.size = htons (msize);
563 tsrm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_RESULT);
564 tsrm->querying_peer = querying_peer;
565 tsrm->finger_identity = finger;
566 tsrm->is_predecessor = htonl (is_predecessor);
567 tsrm->trail_id = trail_id;
568 tsrm->ulitmate_destination_finger_value =
569 GNUNET_htonll (ultimate_destination_finger_value);
570 peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1];
571 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
573 /* Send the message to chosen friend. */
574 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
575 target_friend->pending_count++;
576 process_friend_queue (target_friend);
580 * Send notify successor confirmation message.
581 * @param trail_id Unique Identifier of the trail.
582 * @param trail_direction Destination to Source.
583 * @param target_friend Friend to get this message next.
586 GDS_NEIGHBOURS_send_notify_succcessor_confirmation (struct GNUNET_HashCode trail_id,
587 unsigned int trail_direction,
588 struct FriendInfo *target_friend)
590 struct PeerNotifyConfirmationMessage *ncm;
591 struct P2PPendingMessage *pending;
594 msize = sizeof (struct PeerNotifyConfirmationMessage);
595 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
601 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
603 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
607 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
608 pending->importance = 0; /* FIXME */
609 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
610 ncm = (struct PeerNotifyConfirmationMessage *) &pending[1];
611 pending->msg = &ncm->header;
612 ncm->header.size = htons (msize);
613 ncm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_SUCCESSOR_CONFIRMATION);
614 ncm->trail_id = trail_id;
615 ncm->trail_direction = htonl (trail_direction);
617 /* Send the message to chosen friend. */
618 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
619 target_friend->pending_count++;
620 process_friend_queue (target_friend);
625 * Send trail rejection message to target friend
626 * @param source_peer Peer which is trying to setup the trail.
627 * @param ultimate_destination_finger_value Peer closest to this value will be
628 * @a source_peer's finger
629 * @param congested_peer Peer which sent this message as it is congested.
630 * @param is_predecessor Is source_peer looking for trail to a predecessor or not.
631 * @param trail_peer_list Trails seen so far in trail setup before getting rejected
632 * by congested_peer. This does NOT include @a source_peer
633 * and congested_peer.
634 * @param trail_length Total number of peers in trail_peer_list, NOT including
635 * @a source_peer and @a congested_peer
636 * @param trail_id Unique identifier of this trail.
637 * @param congestion_timeout Duration given by congested peer as an estimate of
638 * how long it may remain congested.
641 GDS_NEIGHBOURS_send_trail_rejection (struct GNUNET_PeerIdentity source_peer,
642 uint64_t ultimate_destination_finger_value,
643 struct GNUNET_PeerIdentity congested_peer,
644 unsigned int is_predecessor,
645 const struct GNUNET_PeerIdentity *trail_peer_list,
646 unsigned int trail_length,
647 struct GNUNET_HashCode trail_id,
648 struct FriendInfo *target_friend,
649 const struct GNUNET_TIME_Relative congestion_timeout)
651 struct PeerTrailRejectionMessage *trm;
652 struct P2PPendingMessage *pending;
653 struct GNUNET_PeerIdentity *peer_list;
656 msize = sizeof (struct PeerTrailRejectionMessage) +
657 (trail_length * sizeof (struct GNUNET_PeerIdentity));
659 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
665 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
667 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
671 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
672 pending->importance = 0;
673 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
674 trm = (struct PeerTrailRejectionMessage *)&pending[1];
675 pending->msg = &trm->header;
676 trm->header.size = htons (msize);
677 trm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_REJECTION);
678 trm->source_peer = source_peer;
679 trm->congested_peer = congested_peer;
680 trm->congestion_time = congestion_timeout;
681 trm->is_predecessor = htonl (is_predecessor);
682 trm->trail_id = trail_id;
683 trm->ultimate_destination_finger_value =
684 GNUNET_htonll (ultimate_destination_finger_value);
686 peer_list = (struct GNUNET_PeerIdentity *) &trm[1];
687 if (trail_length > 0)
689 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
692 /* Send the message to chosen friend. */
693 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
694 target_friend->pending_count++;
695 process_friend_queue (target_friend);
700 * Construct a verify successor message and forward it to target_friend.
701 * @param source_peer Peer which wants to verify its successor.
702 * @param successor Peer which is @a source_peer's current successor.
703 * @param trail_id Unique Identifier of trail from @a source_peer to @a successor,
704 * NOT including them.
705 * @param trail List of peers which are part of trail to reach from @a source_peer
706 * to @a successor, NOT including them.
707 * @param trail_length Total number of peers in @a trail.
708 * @param target_friend Next friend to get this message.
711 GDS_NEIGHBOURS_send_verify_successor_message (struct GNUNET_PeerIdentity source_peer,
712 struct GNUNET_PeerIdentity successor,
713 struct GNUNET_HashCode trail_id,
714 struct GNUNET_PeerIdentity *trail,
715 unsigned int trail_length,
716 struct FriendInfo *target_friend)
718 struct PeerVerifySuccessorMessage *vsm;
719 struct P2PPendingMessage *pending;
720 struct GNUNET_PeerIdentity *peer_list;
723 msize = sizeof (struct PeerVerifySuccessorMessage) +
724 (trail_length * sizeof (struct GNUNET_PeerIdentity));
726 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
732 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
734 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
738 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
739 pending->importance = 0; /* FIXME */
740 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
741 vsm = (struct PeerVerifySuccessorMessage *) &pending[1];
742 pending->msg = &vsm->header;
743 vsm->header.size = htons (msize);
744 vsm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR);
745 vsm->source_peer = source_peer;
746 vsm->successor = successor;
747 vsm->trail_id = trail_id;
748 peer_list = (struct GNUNET_PeerIdentity *) &vsm[1];
749 memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
751 /* Send the message to chosen friend. */
752 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
753 target_friend->pending_count++;
754 process_friend_queue (target_friend);
759 * FIXME: In every function we pass target friend except for this one.
760 * so, either change everything or this one. also, should se just store
761 * the pointer to friend in routing table rather than gnunet_peeridentity.
762 * if yes then we should keep friend info in.h andmake lot of changes.
763 * Construct a trail teardown message and forward it to target friend.
765 * @param trail_id Unique identifier of the trail.
766 * @param trail_direction Direction of trail.
767 * @param target_friend Friend to get this message.
770 GDS_NEIGHBOURS_send_trail_teardown (const struct GNUNET_HashCode *trail_id,
771 unsigned int trail_direction,
772 const struct GNUNET_PeerIdentity *peer)
774 struct PeerTrailTearDownMessage *ttdm;
775 struct P2PPendingMessage *pending;
776 struct FriendInfo *target_friend;
779 msize = sizeof (struct PeerTrailTearDownMessage);
780 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
786 if (NULL == (target_friend =
787 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer)))
789 /* FIXME: In what case friend can be null. ?*/
794 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
796 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
800 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
801 pending->importance = 0; /* FIXME */
802 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
803 ttdm = (struct PeerTrailTearDownMessage *) &pending[1];
804 pending->msg = &ttdm->header;
805 ttdm->header.size = htons (msize);
806 ttdm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN);
807 ttdm->trail_id = *trail_id;
808 ttdm->trail_direction = htonl (trail_direction);
810 /* Send the message to chosen friend. */
811 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
812 target_friend->pending_count++;
813 process_friend_queue (target_friend);
818 * Construct a verify successor result message and send it to target_friend
819 * @param querying_peer Peer which sent the verify successor message.
820 * @param source_successor Current_successor of @a querying_peer.
821 * @param current_predecessor Current predecessor of @a successor. Could be same
822 * or different from @a querying_peer.
823 * @param trail_id Unique identifier of the trail from @a querying_peer to
824 * @a successor, NOT including them.
825 * @param trail List of peers which are part of trail from @a querying_peer to
826 * @a successor, NOT including them.
827 * @param trail_length Total number of peers in @a trail
828 * @param trail_direction Direction in which we are sending the message. In this
829 * case we are sending result from @a successor to @a querying_peer.
830 * @param target_friend Next friend to get this message.
833 GDS_NEIGHBOURS_send_verify_successor_result (struct GNUNET_PeerIdentity querying_peer,
834 struct GNUNET_PeerIdentity current_successor,
835 struct GNUNET_PeerIdentity probable_successor,
836 struct GNUNET_HashCode trail_id,
837 const struct GNUNET_PeerIdentity *trail,
838 unsigned int trail_length,
839 enum GDS_ROUTING_trail_direction trail_direction,
840 struct FriendInfo *target_friend)
842 struct PeerVerifySuccessorResultMessage *vsmr;
843 struct P2PPendingMessage *pending;
844 struct GNUNET_PeerIdentity *peer_list;
847 msize = sizeof (struct PeerVerifySuccessorResultMessage) +
848 (trail_length * sizeof(struct GNUNET_PeerIdentity));
850 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
856 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
858 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
862 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
863 pending->importance = 0; /* FIXME */
864 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
865 vsmr = (struct PeerVerifySuccessorResultMessage *) &pending[1];
866 pending->msg = &vsmr->header;
867 vsmr->header.size = htons (msize);
868 vsmr->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR_RESULT);
869 vsmr->querying_peer = querying_peer;
870 vsmr->current_successor = current_successor;
871 vsmr->probable_successor = probable_successor;
872 vsmr->trail_direction = htonl (trail_direction);
873 vsmr->trail_id = trail_id;
874 peer_list = (struct GNUNET_PeerIdentity *) &vsmr[1];
875 memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
877 /* Send the message to chosen friend. */
878 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
879 target_friend->pending_count++;
880 process_friend_queue (target_friend);
884 * Construct a Put message and send it to target_peer.
885 * @param key Key for the content
886 * @param block_type Type of the block
887 * @param options Routing options
888 * @param desired_replication_level Desired replication count
889 * @param best_known_dest Peer to which this message should reach eventually,
890 * as it is best known destination to me.
891 * @param intermediate_trail_id Trail id in case
892 * @param target_peer Peer to which this message will be forwarded.
893 * @param hop_count Number of hops traversed so far.
894 * @param put_path_length Total number of peers in @a put_path
895 * @param put_path Number of peers traversed so far
896 * @param expiration_time When does the content expire
897 * @param data Content to store
898 * @param data_size Size of content @a data in bytes
901 GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key,
902 enum GNUNET_BLOCK_Type block_type,
903 enum GNUNET_DHT_RouteOption options,
904 uint32_t desired_replication_level,
905 struct GNUNET_PeerIdentity best_known_dest,
906 struct GNUNET_HashCode intermediate_trail_id,
907 struct GNUNET_PeerIdentity *target_peer,
909 uint32_t put_path_length,
910 struct GNUNET_PeerIdentity *put_path,
911 struct GNUNET_TIME_Absolute expiration_time,
912 const void *data, size_t data_size)
914 struct PeerPutMessage *ppm;
915 struct P2PPendingMessage *pending;
916 struct FriendInfo *target_friend;
917 struct GNUNET_PeerIdentity *pp;
920 msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
921 sizeof (struct PeerPutMessage);
922 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
925 msize = data_size + sizeof (struct PeerPutMessage);
928 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
930 DEBUG("msize = %lu\n",msize);
935 GNUNET_assert (NULL !=
937 GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer)));
938 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
939 pending->timeout = expiration_time;
940 ppm = (struct PeerPutMessage *) &pending[1];
941 pending->msg = &ppm->header;
942 ppm->header.size = htons (msize);
943 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_PUT);
944 ppm->options = htonl (options);
945 ppm->block_type = htonl (block_type);
946 ppm->hop_count = htonl (hop_count + 1);
947 ppm->desired_replication_level = htonl (desired_replication_level);
948 ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
949 ppm->best_known_destination = best_known_dest;
950 ppm->intermediate_trail_id = intermediate_trail_id;
952 pp = (struct GNUNET_PeerIdentity *) &ppm[1];
953 ppm->put_path_length = htonl (put_path_length);
954 if(put_path_length > 0)
956 memcpy (pp, put_path,
957 sizeof (struct GNUNET_PeerIdentity) * put_path_length);
959 memcpy (&pp[put_path_length], data, data_size);
960 GNUNET_assert (NULL != target_friend);
961 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
962 target_friend->pending_count++;
963 process_friend_queue (target_friend);
968 * Handle the put request from the client.
969 * @param key Key for the content
970 * @param block_type Type of the block
971 * @param options Routing options
972 * @param desired_replication_level Desired replication count
973 * @param expiration_time When does the content expire
974 * @param data Content to store
975 * @param data_size Size of content @a data in bytes
978 GDS_NEIGHBOURS_handle_put (const struct GNUNET_HashCode *key,
979 enum GNUNET_BLOCK_Type block_type,
980 enum GNUNET_DHT_RouteOption options,
981 uint32_t desired_replication_level,
982 struct GNUNET_TIME_Absolute expiration_time,
983 const void *data, size_t data_size)
985 struct GNUNET_PeerIdentity best_known_dest;
986 struct GNUNET_HashCode intermediate_trail_id;
987 struct GNUNET_PeerIdentity next_hop;
989 struct Closest_Peer successor;
991 memcpy (&key_value, key, sizeof (uint64_t));
992 key_value = GNUNET_ntohll (key_value);
993 successor = find_local_best_known_next_hop (key_value,
994 GDS_FINGER_TYPE_NON_PREDECESSOR);
995 best_known_dest = successor.best_known_destination;
996 next_hop = successor.next_hop;
997 intermediate_trail_id = successor.trail_id;
999 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&best_known_dest, &my_identity))
1001 DEBUG("\n PUT_REQUEST_SUCCESSFUL for key = %s",GNUNET_h2s(key));
1002 /* I am the destination. */
1003 GDS_DATACACHE_handle_put (expiration_time, key, 0, NULL,
1004 block_type,data_size,data);
1005 GDS_CLIENTS_process_put (options, block_type, 0,
1006 ntohl (desired_replication_level),
1007 1, &my_identity, expiration_time, //FIXME: GNUNETnthoh something on expiration time.
1008 key, data, data_size);
1011 /* In case we are sending the request to a finger, then send across all of its
1013 #if ENABLE_MALICIOUS
1014 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&successor.best_known_destination,
1015 &successor.next_hop))
1017 struct FingerInfo *next_hop_finger;
1020 next_hop_finger = &finger_table[successor.finger_table_index];
1021 for (i = 0; i < next_hop_finger->trails_count; i++)
1023 if (GNUNET_YES == next_hop_finger->trail_list[i].is_present)
1025 if(0 == next_hop_finger->trail_list[i].trail_length)
1027 GDS_NEIGHBOURS_send_put (key, block_type, options, desired_replication_level,
1028 best_known_dest, intermediate_trail_id, &next_hop,
1029 0, 1, &my_identity, expiration_time,
1033 next_hop = next_hop_finger->trail_list[i].trail_head->peer;
1034 GDS_NEIGHBOURS_send_put (key, block_type, options, desired_replication_level,
1036 next_hop_finger->trail_list[i].trail_id,
1037 &next_hop, 0, 1, &my_identity,
1045 GDS_NEIGHBOURS_send_put (key, block_type, options, desired_replication_level,
1046 best_known_dest, intermediate_trail_id, &next_hop,
1047 0, 1, &my_identity, expiration_time,
1052 * Construct a Get message and send it to target_peer.
1053 * @param key Key for the content
1054 * @param block_type Type of the block
1055 * @param options Routing options
1056 * @param desired_replication_level Desired replication count
1057 * @param best_known_dest Peer which should get this message. Same as target peer
1058 * if best_known_dest is a friend else its a finger.
1059 * @param intermediate_trail_id Trail id to reach to @a best_known_dest
1060 * in case it is a finger else set to 0.
1061 * @param target_peer Peer to which this message will be forwarded.
1062 * @param hop_count Number of hops traversed so far.
1063 * @param data Content to store
1064 * @param data_size Size of content @a data in bytes
1065 * @param get_path_length Total number of peers in @a get_path
1066 * @param get_path Number of peers traversed so far
1069 GDS_NEIGHBOURS_send_get (const struct GNUNET_HashCode *key,
1070 enum GNUNET_BLOCK_Type block_type,
1071 enum GNUNET_DHT_RouteOption options,
1072 uint32_t desired_replication_level,
1073 struct GNUNET_PeerIdentity best_known_dest,
1074 struct GNUNET_HashCode intermediate_trail_id,
1075 struct GNUNET_PeerIdentity *target_peer,
1077 uint32_t get_path_length,
1078 struct GNUNET_PeerIdentity *get_path)
1080 struct PeerGetMessage *pgm;
1081 struct P2PPendingMessage *pending;
1082 struct FriendInfo *target_friend;
1083 struct GNUNET_PeerIdentity *gp;
1086 msize = sizeof (struct PeerGetMessage) +
1087 (get_path_length * sizeof (struct GNUNET_PeerIdentity));
1089 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1094 GNUNET_assert (NULL !=
1096 GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer)));
1098 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1099 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
1100 pending->importance = 0; /* FIXME */
1101 pgm = (struct PeerGetMessage *) &pending[1];
1102 pending->msg = &pgm->header;
1103 pgm->header.size = htons (msize);
1104 pgm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_GET);
1105 pgm->get_path_length = htonl (get_path_length);
1106 pgm->best_known_destination = best_known_dest;
1108 pgm->intermediate_trail_id = intermediate_trail_id;
1109 pgm->hop_count = htonl (hop_count + 1);
1110 pgm->get_path_length = htonl (get_path_length);
1111 gp = (struct GNUNET_PeerIdentity *) &pgm[1];
1112 memcpy (gp, get_path,
1113 sizeof (struct GNUNET_PeerIdentity) * get_path_length);
1114 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1115 target_friend->pending_count++;
1116 process_friend_queue (target_friend);
1121 * Handle the get request from the client file. If I am destination do
1122 * datacache put and return. Else find the target friend and forward message
1124 * @param key Key for the content
1125 * @param block_type Type of the block
1126 * @param options Routing options
1127 * @param desired_replication_level Desired replication count
1130 GDS_NEIGHBOURS_handle_get(const struct GNUNET_HashCode *key,
1131 enum GNUNET_BLOCK_Type block_type,
1132 enum GNUNET_DHT_RouteOption options,
1133 uint32_t desired_replication_level)
1135 struct Closest_Peer successor;
1136 struct GNUNET_PeerIdentity best_known_dest;
1137 struct GNUNET_HashCode intermediate_trail_id;
1140 memcpy (&key_value, key, sizeof (uint64_t));
1141 key_value = GNUNET_ntohll (key_value);
1143 successor = find_local_best_known_next_hop (key_value,
1144 GDS_FINGER_TYPE_NON_PREDECESSOR);
1146 best_known_dest = successor.best_known_destination;
1147 intermediate_trail_id = successor.trail_id;
1149 /* I am the destination. I have the data. */
1150 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
1153 GDS_DATACACHE_handle_get (key,block_type, NULL, 0,
1154 NULL, 0, 1, &my_identity, NULL,&my_identity);
1158 #if ENABLE_MALICIOUS
1159 struct GNUNET_PeerIdentity next_hop;
1160 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&successor.best_known_destination,
1161 &successor.next_hop))
1163 struct FingerInfo *next_hop_finger;
1166 next_hop_finger = &finger_table[successor.finger_table_index];
1167 for (i = 0; i < next_hop_finger->trails_count; i++)
1169 if (GNUNET_YES == next_hop_finger->trail_list[i].is_present)
1171 if(0 == next_hop_finger->trail_list[i].trail_length)
1173 GDS_NEIGHBOURS_send_get (key, block_type, options,
1174 desired_replication_level,
1175 best_known_dest,intermediate_trail_id,
1176 &successor.next_hop,
1177 0, 1, &my_identity);
1180 next_hop = next_hop_finger->trail_list[i].trail_head->peer;
1181 GDS_NEIGHBOURS_send_get (key, block_type, options, desired_replication_level,
1183 next_hop_finger->trail_list[i].trail_id,
1184 &next_hop, 0, 1, &my_identity);
1190 GDS_NEIGHBOURS_send_get (key, block_type, options, desired_replication_level,
1191 best_known_dest,intermediate_trail_id, &successor.next_hop,
1192 0, 1, &my_identity);
1197 * Send the get result to requesting client.
1199 * @param key Key of the requested data.
1200 * @param type Block type
1201 * @param target_peer Next peer to forward the message to.
1202 * @param source_peer Peer which has the data for the key.
1203 * @param put_path_length Number of peers in @a put_path
1204 * @param put_path Path taken to put the data at its stored location.
1205 * @param get_path_length Number of peers in @a get_path
1206 * @param get_path Path taken to reach to the location of the key.
1207 * @param expiration When will this result expire?
1208 * @param data Payload to store
1209 * @param data_size Size of the @a data
1212 GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key,
1213 enum GNUNET_BLOCK_Type type,
1214 const struct GNUNET_PeerIdentity *target_peer,
1215 const struct GNUNET_PeerIdentity *source_peer,
1216 unsigned int put_path_length,
1217 const struct GNUNET_PeerIdentity *put_path,
1218 unsigned int get_path_length,
1219 const struct GNUNET_PeerIdentity *get_path,
1220 struct GNUNET_TIME_Absolute expiration,
1221 const void *data, size_t data_size)
1223 struct PeerGetResultMessage *get_result;
1224 struct GNUNET_PeerIdentity *paths;
1225 struct P2PPendingMessage *pending;
1226 struct FriendInfo *target_friend;
1227 int current_path_index;
1230 msize = (put_path_length + get_path_length )* sizeof (struct GNUNET_PeerIdentity) +
1232 sizeof (struct PeerGetResultMessage);
1234 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1236 put_path_length = 0;
1237 msize = msize - put_path_length * sizeof (struct GNUNET_PeerIdentity);
1240 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1245 current_path_index = 0;
1246 if(get_path_length > 0)
1248 current_path_index = search_my_index(get_path, get_path_length);
1249 if (-1 == current_path_index)
1254 if ((get_path_length + 1) == current_path_index)
1256 DEBUG ("Peer found twice in get path. Not allowed \n");
1261 if (0 == current_path_index)
1263 DEBUG ("GET_RESULT TO CLIENT KEY = %s, Peer = %s",GNUNET_h2s(key),GNUNET_i2s(&my_identity));
1264 GDS_CLIENTS_handle_reply (expiration, key, get_path_length,
1265 get_path, put_path_length,
1266 put_path, type, data_size, data);
1270 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1271 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
1272 pending->importance = 0;
1273 get_result = (struct PeerGetResultMessage *)&pending[1];
1274 pending->msg = &get_result->header;
1275 get_result->header.size = htons (msize);
1276 get_result->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_GET_RESULT);
1277 get_result->key = *key;
1278 get_result->querying_peer = *source_peer;
1279 get_result->expiration_time = expiration;
1280 get_result->get_path_length = htonl (get_path_length);
1281 get_result->put_path_length = htonl (put_path_length);
1282 paths = (struct GNUNET_PeerIdentity *)&get_result[1];
1283 memcpy (paths, put_path,
1284 put_path_length * sizeof (struct GNUNET_PeerIdentity));
1285 memcpy (&paths[put_path_length], get_path,
1286 get_path_length * sizeof (struct GNUNET_PeerIdentity));
1287 memcpy (&paths[put_path_length + get_path_length], data, data_size);
1289 GNUNET_assert (NULL !=
1291 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1292 &get_path[current_path_index - 1])));
1293 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1294 target_friend->pending_count++;
1295 process_friend_queue (target_friend);
1300 * Method called whenever a peer disconnects.
1302 * @param cls closure
1303 * @param peer peer identity this notification is about
1306 handle_core_disconnect (void *cls,
1307 const struct GNUNET_PeerIdentity *peer)
1309 struct FriendInfo *remove_friend;
1311 /* If disconnected to own identity, then return. */
1312 if (0 == memcmp (&my_identity,
1314 sizeof (struct GNUNET_PeerIdentity)))
1317 if (NULL == (remove_friend =
1318 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1325 GNUNET_assert (GNUNET_YES ==
1326 GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
1329 /* FIXME: do stuff */
1334 * Method called whenever a peer connects.
1336 * @param cls closure
1337 * @param peer_identity peer identity this notification is about
1340 handle_core_connect (void *cls,
1341 const struct GNUNET_PeerIdentity *peer_identity)
1343 struct FriendInfo *friend;
1345 /* Check for connect to self message */
1346 if (0 == memcmp (&my_identity,
1348 sizeof (struct GNUNET_PeerIdentity)))
1351 /* If peer already exists in our friend_peermap, then exit. */
1353 GNUNET_CONTAINER_multipeermap_contains (friend_peermap,
1360 friend = GNUNET_new (struct FriendInfo);
1361 friend->id = *peer_identity;
1363 GNUNET_assert (GNUNET_OK ==
1364 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
1367 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1373 * To be called on core init/fail.
1375 * @param cls service closure
1376 * @param identity the public identity of this peer
1379 core_init (void *cls,
1380 const struct GNUNET_PeerIdentity *identity)
1382 my_identity = *identity;
1387 * Handle a `struct FingerSetupMessage`.
1389 * @param cls closure (NULL)
1390 * @param peer sender identity
1391 * @param message the setup message
1392 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1395 handle_dht_p2p_finger_setup (void *cls,
1396 const struct GNUNET_PeerIdentity *peer,
1397 const struct GNUNET_MessageHeader *message)
1399 const struct FingerSetupMessage *fsm;
1401 fsm = (const struct FingerSetupMessage *) message;
1409 * Initialize neighbours subsystem.
1410 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1413 GDS_NEIGHBOURS_init (void)
1415 static const struct GNUNET_CORE_MessageHandler core_handlers[] = {
1416 { &handle_dht_p2p_finger_setup,
1417 GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP,
1418 sizeof (struct FingerSetupMessage) },
1422 #if ENABLE_MALICIOUS
1427 GNUNET_CORE_connect (GDS_cfg, NULL,
1429 &handle_core_connect,
1430 &handle_core_disconnect,
1435 if (NULL == core_api)
1436 return GNUNET_SYSERR;
1438 //TODO: check size of this peer map?
1439 friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1445 * Shutdown neighbours subsystem.
1448 GDS_NEIGHBOURS_done (void)
1450 if (NULL == core_api)
1452 GNUNET_CORE_disconnect (core_api);
1455 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
1456 GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
1457 friend_peermap = NULL;
1464 * @return my identity
1466 struct GNUNET_PeerIdentity
1467 GDS_NEIGHBOURS_get_my_id (void)
1472 /* end of gnunet-service-wdht_neighbours.c */