2 This file is part of GNUnet.
3 (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-xdht_clients.h"
41 #include "gnunet-service-xdht_datacache.h"
42 #include "gnunet-service-xdht_neighbours.h"
43 #include "gnunet-service-xdht_routing.h"
48 * Maximum possible fingers of a peer.
50 #define MAX_FINGERS 65
53 * Maximum allowed number of pending messages per friend peer.
55 #define MAXIMUM_PENDING_PER_FRIEND 64
58 * How long to wait before sending another find finger trail request
60 #define DHT_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
63 * How long at most to wait for transmission of a request to another peer?
65 #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
68 * How long will I remain congested?
70 #define CONGESTION_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
73 * Maximum number of trails stored per finger.
75 #define MAXIMUM_TRAILS_PER_FINGER 2
78 * Used to distinguish put/get request use of find_successor() from others
80 #define PUT_GET_REQUEST 65
83 * Maximum number of trails that can go through a friend.
85 #define TRAIL_THROUGH_FRIEND_THRESHOLD 64
88 * Finger map index for predecessor entry in finger peermap.
90 #define PREDECESSOR_FINGER_ID 64
93 * Maximum number of trails allowed to go through a friend.
95 #define TRAILS_THROUGH_FRIEND_THRESHOLD 64
97 GNUNET_NETWORK_STRUCT_BEGIN
100 * P2P Trail setup message
102 struct PeerTrailSetupMessage
105 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP
107 struct GNUNET_MessageHeader header;
110 * Peer closest to this value will be our finger.
112 uint64_t ultimate_destination_finger;
115 * Source peer which wants to setup the trail to one of its finger.
117 struct GNUNET_PeerIdentity source_peer;
120 * Peer to which this packet is forwarded.
122 struct GNUNET_PeerIdentity next_destination;
125 * Index into finger peer map, in Network Byte Order.
127 uint32_t finger_map_index;
130 * Number of entries in trail list, in Network Byte Order.
132 uint32_t trail_length GNUNET_PACKED;
135 * Trail id of any intermediate trail we may encounter while doing trail setup.
137 struct GNUNET_HashCode intermediate_trail_id;
140 * Trail id for trail which we are trying to setup.
142 struct GNUNET_HashCode new_trail_id;
144 /* Trail formed in the process. */
148 * P2P Trail Setup Result message
150 struct PeerTrailSetupResultMessage
154 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT
156 struct GNUNET_MessageHeader header;
159 * Finger to which we have found the path.
161 struct GNUNET_PeerIdentity finger_identity;
164 * Peer which was looking for the trail to finger.
166 struct GNUNET_PeerIdentity destination_peer;
169 * Index into finger peer map in NBO.
171 uint32_t finger_map_index;
174 * Number of entries in trail list in NBO.
176 uint32_t trail_length GNUNET_PACKED;
179 * Identifier of the trail.
181 struct GNUNET_HashCode trail_id;
183 /* Trail from destination_peer to finger_identity */
187 * P2P Verify Successor Message.
189 struct PeerVerifySuccessorMessage
192 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR
194 struct GNUNET_MessageHeader header;
197 * Source peer which wants to verify its successor.
199 struct GNUNET_PeerIdentity source_peer;
202 * My current successor.
204 struct GNUNET_PeerIdentity successor;
207 * Identifier of trail to reach from source_peer to successor.
209 struct GNUNET_HashCode trail_id;
212 * Total number of peers to reach from source to successor.
214 unsigned int trail_length;
220 * P2P Verify Successor Result Message
222 struct PeerVerifySuccessorResultMessage
225 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT
227 struct GNUNET_MessageHeader header;
230 * Destination peer which sent the request to verify its successor.
232 struct GNUNET_PeerIdentity destination_peer;
235 * Successor to which PeerVerifySuccessorMessage was sent.
237 struct GNUNET_PeerIdentity source_successor;
240 * source_successor's predecessor
242 struct GNUNET_PeerIdentity my_predecessor;
245 * Trail identifier of trail from my_predecessor to source_successor.
247 struct GNUNET_HashCode trail_id;
250 * Direction in which we are looking at the trail.
252 enum GDS_ROUTING_trail_direction trail_direction;
255 * Total number of peers in trail from source_successor to my_predecessor
256 * if my_predecessor is not same as destination_peer.
258 uint32_t trail_length;
260 /* Trail from source_successor to my_predecessor where
261 * my_predecessor != destination_peer*/
265 * P2P Notify New Successor Message.
267 struct PeerNotifyNewSuccessorMessage
270 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR
272 struct GNUNET_MessageHeader header;
275 * Source peer which wants to notify its new successor.
277 struct GNUNET_PeerIdentity source_peer;
280 * New successor identity.
282 struct GNUNET_PeerIdentity destination_peer;
285 * Total number of peers in trail from source_peer to destination_peer
287 unsigned int trail_length;
290 * Unique identifier of the trail.
292 struct GNUNET_HashCode trail_id;
298 * P2P Trail Compression Message.
300 struct PeerTrailCompressionMessage
303 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_COMPRESSION
305 struct GNUNET_MessageHeader header;
308 * Source peer of this trail.
310 struct GNUNET_PeerIdentity source_peer;
313 * Destination of this trail.
315 struct GNUNET_PeerIdentity destination_peer;
318 * Trail from source_peer to destination_peer compressed such that
319 * new_first_friend is the first hop in the trail from source to
322 struct GNUNET_PeerIdentity new_first_friend;
325 * Unique identifier of trail.
327 struct GNUNET_HashCode trail_id;
332 * P2P Trail Tear Down message.
334 struct PeerTrailTearDownMessage
337 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_TEARDOWN
339 struct GNUNET_MessageHeader header;
344 * P2P Trail Rejection Message.
346 struct PeerTrailRejectionMessage
349 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION
351 struct GNUNET_MessageHeader header;
354 * Source peer which wants to set up the trail.
356 struct GNUNET_PeerIdentity source_peer;
359 * Peer which sent trail rejection message.
361 struct GNUNET_PeerIdentity congested_peer;
364 * Peer identity which will be successor to this value will be finger of
367 uint64_t ultimate_destination_finger_identity_value;
370 * Index in finger peer map of source peer.
372 uint32_t finger_map_index;
375 * Total number of peers in the trail.
377 uint32_t trail_length;
380 * Identifier for the trail source peer is trying to setup.
382 struct GNUNET_HashCode trail_id;
384 * Relative time for which congested_peer will remain congested.
386 struct GNUNET_TIME_Relative congestion_time;
388 /* Trail_list from source_peer to peer which sent the message for trail setup
389 * to congested peer.*/
393 * P2P Add Trail Message.
395 struct PeerAddTrailMessage
398 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_ADD_TRAIL
400 struct GNUNET_MessageHeader header;
403 * Source peer of the routing trail.
405 struct GNUNET_PeerIdentity source_peer;
408 * Destination peer of the routing trail.
410 struct GNUNET_PeerIdentity destination_peer;
413 * Total number of peers from source peer to destination peer.
415 unsigned int trail_length;
418 * Unique identifier of the trail.
420 struct GNUNET_HashCode trail_id;
422 /* Trail from source peer to destination peer. */
425 GNUNET_NETWORK_STRUCT_END
428 * Linked list of messages to send to a particular other peer.
430 struct P2PPendingMessage
433 * Pointer to next item in the list
435 struct P2PPendingMessage *next;
438 * Pointer to previous item in the list
440 struct P2PPendingMessage *prev;
443 * Message importance level. FIXME: used? useful?
445 unsigned int importance;
448 * When does this message time out?
450 struct GNUNET_TIME_Absolute timeout;
453 * Actual message to be sent, allocated at the end of the struct:
454 * // msg = (cast) &pm[1];
455 * // memcpy (&pm[1], data, len);
457 const struct GNUNET_MessageHeader *msg;
463 * Entry in friend_peermap.
470 struct GNUNET_PeerIdentity id;
473 * Number of trails for which this friend is the first hop.
475 unsigned int trails_count;
478 * Count of outstanding messages for this friend.
480 unsigned int pending_count;
483 * In case not 0, then amount of time for which this friend is congested.
485 struct GNUNET_TIME_Absolute congestion_duration;
488 * Head of pending messages to be sent to this friend.
490 struct P2PPendingMessage *head;
493 * Tail of pending messages to be sent to this friend.
495 struct P2PPendingMessage *tail;
498 * Core handle for sending messages to this friend.
500 struct GNUNET_CORE_TransmitHandle *th;
505 * An individual trail to reach to a finger.
510 * Pointer to next item in the list
515 * Pointer to prev item in the list
520 * An element in this trail.
522 struct GNUNET_PeerIdentity peer;
526 * List of all trails to reach a particular finger.
533 struct Trail *trail_head;
538 struct Trail *trail_tail;
541 * Unique identifier of this trail.
543 struct GNUNET_HashCode trail_id;
546 * Length of trail pointed
548 unsigned int trail_length;
551 * Number of trails that the first friend of this trail is a part of.
553 unsigned int first_friend_trail_count;
557 * An entry in finger_hashmap.
564 struct GNUNET_PeerIdentity finger_identity;
567 * Index in finger peer map
569 unsigned int finger_map_index;
572 * Number of trails setup so far for this finger.
574 unsigned int trails_count;
579 struct TrailList trail_list[MAXIMUM_TRAILS_PER_FINGER];
583 * Data structure to keep track of closest peer seen so far in find_successor()
588 * 64 bit value of the peer
593 * Trail id to reach to peer.
595 struct GNUNET_HashCode trail_id;
598 * First hop, NULL in case of friend and my_identity
600 struct GNUNET_PeerIdentity next_hop;
603 * Next destination. In case of friend and my_identity , it is same as next_hop
604 * In case of finger it is finger identity.
606 struct GNUNET_PeerIdentity next_destination;
610 * Data structure to store the trail chosen to reach to finger.
615 * First friend in the trail to reach finger.
617 struct FriendInfo friend;
620 * Identifier of this trail.
622 struct GNUNET_HashCode trail_id;
625 * Total number of peers in this trail.
627 unsigned int trail_length;
631 * Task that sends FIND FINGER TRAIL requests. This task is started when we have
632 * get our first friend.
634 static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task;
637 * Identity of this peer.
639 static struct GNUNET_PeerIdentity my_identity;
642 * Peer map of all the friends of a peer
644 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap;
647 * Hash map of all the fingers of a peer
649 static struct GNUNET_CONTAINER_MultiHashMap32 *finger_hashmap;
654 static struct GNUNET_CORE_Handle *core_api;
657 * The current finger index that we have want to find trail to. We start the
658 * search with value = 0, i.e. successor peer and then go to PREDCESSOR_FINGER_ID
659 * and decrement it. For any index 63 <= index < 0, if finger is same as successor,
660 * we reset this index to 0.
662 static unsigned int current_search_finger_index;
666 * Called when core is ready to send a message we asked for
667 * out to the destination.
669 * @param cls the 'struct FriendInfo' of the target friend
670 * @param size number of bytes available in buf
671 * @param buf where the callee should write the message
672 * @return number of bytes written to buf
675 core_transmit_notify (void *cls, size_t size, void *buf)
677 struct FriendInfo *peer = cls;
679 struct P2PPendingMessage *pending;
684 while ((NULL != (pending = peer->head)) &&
685 (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us))
687 peer->pending_count--;
688 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
689 GNUNET_free (pending);
693 /* no messages pending */
699 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
700 GNUNET_CORE_PRIO_BEST_EFFORT,
701 GNUNET_TIME_absolute_get_remaining
702 (pending->timeout), &peer->id,
703 ntohs (pending->msg->size),
704 &core_transmit_notify, peer);
705 GNUNET_break (NULL != peer->th);
709 while ((NULL != (pending = peer->head)) &&
710 (size - off >= (msize = ntohs (pending->msg->size))))
712 GNUNET_STATISTICS_update (GDS_stats,
714 ("# Bytes transmitted to other peers"), msize,
716 memcpy (&cbuf[off], pending->msg, msize);
718 peer->pending_count--;
719 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
720 GNUNET_free (pending);
722 if (peer->head != NULL)
725 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
726 GNUNET_CORE_PRIO_BEST_EFFORT,
727 GNUNET_TIME_absolute_get_remaining
728 (pending->timeout), &peer->id, msize,
729 &core_transmit_notify, peer);
730 GNUNET_break (NULL != peer->th);
738 * FIXME: assertion fails at the end of this function. also in core_api.c at 1299.
739 * Transmit all messages in the friend's message queue.
741 * @param peer message queue to process
744 process_friend_queue (struct FriendInfo *peer)
746 struct P2PPendingMessage *pending;
748 if (NULL == (pending = peer->head))
750 if (NULL != peer->th)
753 GNUNET_STATISTICS_update (GDS_stats,
755 ("# Bytes of bandwidth requested from core"),
756 ntohs (pending->msg->size), GNUNET_NO);
759 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
761 GNUNET_TIME_absolute_get_remaining
762 (pending->timeout), &peer->id,
763 ntohs (pending->msg->size),
764 &core_transmit_notify, peer);
765 GNUNET_break (NULL != peer->th);
770 * Construct a trail setup message and forward it to target_friend
771 * @param source_peer Source peer which wants to setup the trail
772 * @param ultimate_destination_finger Peer identity closest to this value will
773 * be finger to @a source_peer
774 * @param next_destination Peer which should get the packet. I can be same as
775 * target_friend or different.
776 * @param target_friend Friend to which message is forwarded now.
777 * @param trail_length Total number of peers in trail setup so far.
778 * @param trail_peer_list Trail setup so far
779 * @param finger_map_index Index in finger map for which we are looking for finger.
780 * @param trail_id Unique identifier for the trail we are trying to setup.
781 * @param intermediate_trail_id Trail id of any intermediate trail we may have to
782 * traverse during trail setup. If not used then set to
786 GDS_NEIGHBOURS_send_trail_setup (const struct GNUNET_PeerIdentity source_peer,
787 uint64_t ultimate_destination_finger,
788 struct GNUNET_PeerIdentity next_destination,
789 struct FriendInfo *target_friend,
790 unsigned int trail_length,
791 const struct GNUNET_PeerIdentity *trail_peer_list,
792 unsigned int finger_map_index,
793 struct GNUNET_HashCode new_trail_id,
794 struct GNUNET_HashCode intermediate_trail_id)
796 struct P2PPendingMessage *pending;
797 struct PeerTrailSetupMessage *tsm;
798 struct GNUNET_PeerIdentity *peer_list;
801 msize = sizeof (struct PeerTrailSetupMessage) +
802 (trail_length * sizeof (struct GNUNET_PeerIdentity));
804 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
810 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
812 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
816 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
817 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
818 tsm = (struct PeerTrailSetupMessage *) &pending[1];
819 pending->msg = &tsm->header;
820 tsm->header.size = htons (msize);
821 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
822 tsm->ultimate_destination_finger = GNUNET_htonll (ultimate_destination_finger);
823 tsm->source_peer = source_peer;
824 tsm->next_destination = next_destination;
825 tsm->trail_length = htonl (trail_length);
826 tsm->finger_map_index = htonl (finger_map_index);
827 tsm->new_trail_id = new_trail_id;
828 tsm->intermediate_trail_id = intermediate_trail_id;
829 if (trail_length > 0)
831 peer_list = (struct GNUNET_PeerIdentity *) &tsm[1];
832 memcpy (peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
835 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
836 target_friend->pending_count++;
837 process_friend_queue (target_friend);
842 * Construct a trail setup result message and forward it to target friend.
843 * @param destination_peer Peer which will get the trail to one of its finger.
844 * @param source_finger Peer to which the trail has been setup to.
845 * @param target_friend Friend to which this message should be forwarded.
846 * @param trail_length Numbers of peers in the trail.
847 * @param trail_peer_list Peers which are part of the trail from source to destination.
848 * @param finger_map_index Index in finger peer map
849 * @param trail_id Unique identifier of the trail.
852 GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity destination_peer,
853 struct GNUNET_PeerIdentity source_finger,
854 struct FriendInfo *target_friend,
855 unsigned int trail_length,
856 const struct GNUNET_PeerIdentity *trail_peer_list,
857 unsigned int finger_map_index,
858 struct GNUNET_HashCode trail_id)
860 struct P2PPendingMessage *pending;
861 struct PeerTrailSetupResultMessage *tsrm;
862 struct GNUNET_PeerIdentity *peer_list;
865 msize = sizeof (struct PeerTrailSetupResultMessage) +
866 (trail_length * sizeof (struct GNUNET_PeerIdentity));
868 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
874 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
876 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
880 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
881 pending->importance = 0;
882 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
883 tsrm = (struct PeerTrailSetupResultMessage *) &pending[1];
884 pending->msg = &tsrm->header;
885 tsrm->header.size = htons (msize);
886 tsrm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT);
887 tsrm->destination_peer = destination_peer;
888 tsrm->finger_identity = source_finger;
889 tsrm->trail_length = htonl (trail_length);
890 tsrm->finger_map_index = htonl (finger_map_index);
891 tsrm->trail_id = trail_id;
893 peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1];
894 if (trail_length > 0)
896 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
898 /* Send the message to chosen friend. */
899 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
900 target_friend->pending_count++;
901 process_friend_queue (target_friend);
906 * Send trail rejection message to next_hop
907 * @param source_peer Source peer which is trying to setup the trail.
908 * @param finger_identity Peer closest to this value will be @a source_peer's finger
909 * @param congested_peer Peer which sent this message as it is congested.
910 * @param next_hop Peer to which we are forwarding this message.
911 * @param finger_map_index Index in finger peermap for which we are searching for finger.
912 * @param trail_peer_list Trails seen so far in trail setup before getting rejected
914 * @param trail_length Total number of peers in trail_peer_list
915 * @param trail_id Unique identifier of this trail.
916 * @param congestion_timeout Duration given by congested peer as an estimate of
917 * how long it may remain congested.
920 GDS_NEIGHBOURS_send_trail_rejection (struct GNUNET_PeerIdentity source_peer,
921 uint64_t finger_identity,
922 struct GNUNET_PeerIdentity congested_peer,
923 unsigned int finger_map_index,
924 struct GNUNET_PeerIdentity *trail_peer_list,
925 unsigned int trail_length,
926 struct GNUNET_HashCode trail_id,
927 struct FriendInfo *target_friend,
928 const struct GNUNET_TIME_Relative congestion_timeout)
930 struct PeerTrailRejectionMessage *trm;
931 struct P2PPendingMessage *pending;
932 struct GNUNET_PeerIdentity *peer_list;
935 msize = sizeof (struct PeerTrailRejectionMessage) +
936 (trail_length * sizeof (struct GNUNET_PeerIdentity));
938 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
944 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
946 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
950 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
951 pending->importance = 0;
952 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
953 trm = (struct PeerTrailRejectionMessage *)&pending[1];
954 pending->msg = &trm->header;
955 trm->header.size = htons (msize);
956 trm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION);
957 trm->source_peer = source_peer;
958 trm->congested_peer = congested_peer;
959 trm->congestion_time = congestion_timeout;
960 trm->finger_map_index = htonl (finger_map_index);
961 trm->trail_id = trail_id;
963 peer_list = (struct GNUNET_PeerIdentity *) &trm[1];
964 if (trail_length > 0)
966 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
968 /* Send the message to chosen friend. */
969 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
970 target_friend->pending_count++;
971 process_friend_queue (target_friend);
976 * Construct a verify successor message and forward it to target_friend.
977 * @param source_peer Peer which wants to verify its successor.
978 * @param successor Peer which is @a source_peer's current successor.
979 * @param trail_id Identifier of trail to reach successor.
980 * @param trail Trail to reach from source_peer to successor
981 * @param trail_length Total number of peers in @a trail.
982 * @param target_friend Message send to this friend.
985 GDS_NEIGHBOURS_send_verify_successor_message (struct GNUNET_PeerIdentity source_peer,
986 struct GNUNET_PeerIdentity successor,
987 const struct GNUNET_HashCode trail_id,
988 struct GNUNET_PeerIdentity *trail,
989 unsigned int trail_length,
990 struct FriendInfo *target_friend)
992 struct PeerVerifySuccessorMessage *vsm;
993 struct P2PPendingMessage *pending;
994 struct GNUNET_PeerIdentity *peer_list;
997 msize = sizeof (struct PeerVerifySuccessorMessage);
998 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1004 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1006 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1010 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1011 pending->importance = 0; /* FIXME */
1012 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1013 vsm = (struct PeerVerifySuccessorMessage *) &pending[1];
1014 pending->msg = &vsm->header;
1015 vsm->header.size = htons (msize);
1016 vsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR);
1017 vsm->source_peer = source_peer;
1018 vsm->successor = successor;
1019 vsm->trail_id = trail_id;
1020 vsm->trail_length = htonl (trail_length);
1022 if (trail_length > 0)
1024 peer_list = (struct GNUNET_PeerIdentity *) &vsm[1];
1025 memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
1028 /* Send the message to chosen friend. */
1029 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1030 target_friend->pending_count++;
1031 process_friend_queue (target_friend);
1036 * Construct a trail teardown message and send it to target_friend
1037 * @param source_peer
1038 * @param destination_peer
1040 * @param trail_direction
1041 * @param target_friend
1044 GDS_NEIGHBOURS_send_trail_teardown (struct GNUNET_PeerIdentity source_peer,
1045 struct GNUNET_PeerIdentity destination_peer,
1046 struct GNUNET_HashCode trail_id,
1047 enum GDS_ROUTING_trail_direction trail_direction,
1048 struct FriendInfo *target_friend)
1055 * Construct a verify successor message and send it to target_friend
1056 * @param destination_peer
1057 * @param source_successor
1058 * @param succ_predecessor
1061 * @param trail_length
1062 * @param target_friend
1065 GDS_NEIGHBOURS_send_verify_successor_result (struct GNUNET_PeerIdentity destination_peer,
1066 struct GNUNET_PeerIdentity source_successor,
1067 struct GNUNET_PeerIdentity succ_predecessor,
1068 struct GNUNET_HashCode trail_id,
1069 const struct GNUNET_PeerIdentity *trail,
1070 unsigned int trail_length,
1071 enum GDS_ROUTING_trail_direction trail_direction,
1072 struct FriendInfo *target_friend)
1074 struct PeerVerifySuccessorResultMessage *vsmr;
1075 struct P2PPendingMessage *pending;
1076 struct GNUNET_PeerIdentity *peer_list;
1079 msize = sizeof (struct PeerVerifySuccessorResultMessage) +
1080 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1082 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1088 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1090 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1094 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1095 pending->importance = 0; /* FIXME */
1096 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1097 vsmr = (struct PeerVerifySuccessorResultMessage *) &pending[1];
1098 pending->msg = &vsmr->header;
1099 vsmr->header.size = htons (msize);
1100 vsmr->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT);
1101 vsmr->destination_peer = destination_peer;
1102 vsmr->my_predecessor = succ_predecessor;
1103 vsmr->source_successor = source_successor;
1104 vsmr->trail_direction = htonl (trail_direction);
1106 if (trail_length > 0)
1108 peer_list = (struct GNUNET_PeerIdentity *) &vsmr[1];
1109 memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
1112 /* Send the message to chosen friend. */
1113 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1114 target_friend->pending_count++;
1115 process_friend_queue (target_friend);
1120 * Construct a notify new successor message and send it to target_friend
1121 * @param source_peer
1122 * @param new_successor
1123 * @param new_successor_trail
1124 * @param new_successor_trail_length
1125 * @param new_succesor_trail_id
1128 GDS_NEIGHBOURS_send_notify_new_successor (struct GNUNET_PeerIdentity source_peer,
1129 struct GNUNET_PeerIdentity new_successor,
1130 struct GNUNET_PeerIdentity *new_successor_trail,
1131 unsigned int new_successor_trail_length,
1132 struct GNUNET_HashCode new_succesor_trail_id,
1133 struct FriendInfo *target_friend)
1135 struct PeerNotifyNewSuccessorMessage *nsm;
1136 struct P2PPendingMessage *pending;
1137 struct GNUNET_PeerIdentity *peer_list;
1140 msize = sizeof (struct PeerNotifyNewSuccessorMessage) +
1141 (new_successor_trail_length * sizeof(struct GNUNET_PeerIdentity));
1143 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1149 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1151 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1155 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1156 pending->importance = 0; /* FIXME */
1157 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1158 nsm = (struct PeerNotifyNewSuccessorMessage *) &pending[1];
1159 pending->msg = &nsm->header;
1160 nsm->header.size = htons (msize);
1161 nsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR);
1162 nsm->source_peer = source_peer;
1163 nsm->destination_peer = new_successor;
1164 nsm->trail_length = htonl (new_successor_trail_length);
1165 nsm->trail_id = new_succesor_trail_id;
1166 if (new_successor_trail_length > 0)
1168 peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
1169 memcpy (peer_list, new_successor_trail,
1170 new_successor_trail_length * sizeof (struct GNUNET_PeerIdentity));
1173 /* Send the message to chosen friend. */
1174 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1175 target_friend->pending_count++;
1176 process_friend_queue (target_friend);
1181 * Construct an add_trail message and send it to target_friend
1182 * @param source_peer Source of the trail.
1183 * @param destination_peer Destination of the trail.
1184 * @param trail_id Unique identifer of the trail
1185 * @param trail Trail from @a source_peer to @a destination_peer
1186 * @param trail_length Total number of peers in @a trail.
1187 * @param target_friend Next peer to get this message.
1190 GDS_NEIGHBOURS_send_add_trail (struct GNUNET_PeerIdentity source_peer,
1191 struct GNUNET_PeerIdentity destination_peer,
1192 struct GNUNET_HashCode trail_id,
1193 struct GNUNET_PeerIdentity *trail,
1194 unsigned int trail_length,
1195 struct FriendInfo *target_friend)
1197 struct PeerAddTrailMessage *adm;
1198 struct GNUNET_PeerIdentity *peer_list;
1199 struct P2PPendingMessage *pending;
1202 msize = sizeof (struct PeerAddTrailMessage) +
1203 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1205 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1211 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1213 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1217 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1218 pending->importance = 0; /* FIXME */
1219 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1220 adm = (struct PeerAddTrailMessage *) &pending[1];
1221 pending->msg = &adm->header;
1222 adm->header.size = htons (msize);
1223 adm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_ADD_TRAIL);
1224 adm->source_peer = source_peer;
1225 adm->destination_peer = destination_peer;
1226 adm->trail_length = htonl (trail_length);
1227 adm->trail_id = trail_id;
1229 if (trail_length > 0)
1231 peer_list = (struct GNUNET_PeerIdentity *)&adm[1];
1232 memcpy (peer_list, trail, sizeof (struct GNUNET_PeerIdentity) * trail_length);
1235 /* Send the message to chosen friend. */
1236 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1237 target_friend->pending_count++;
1238 process_friend_queue (target_friend);
1244 * Construct a trail compression message and send it to target_friend.
1245 * @param source_peer Source of the trail.
1246 * @param destination_finger Destination of trail.
1247 * @param trail_id Unique identifier of trail.
1248 * @param first_friend First hop in compressed trail to reach from source to finger
1249 * @param target_friend Next friend to get this message.
1252 GDS_NEIGHBOURS_send_trail_compression (struct GNUNET_PeerIdentity source_peer,
1253 struct GNUNET_PeerIdentity destination_peer,
1254 struct GNUNET_HashCode trail_id,
1255 struct GNUNET_PeerIdentity first_friend,
1256 struct FriendInfo *target_friend)
1258 struct P2PPendingMessage *pending;
1259 struct PeerTrailCompressionMessage *tcm;
1262 msize = sizeof (struct PeerTrailCompressionMessage);
1264 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1270 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1272 GNUNET_STATISTICS_update (GDS_stats,
1273 gettext_noop ("# P2P messages dropped due to full queue"),
1277 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1278 pending->importance = 0; /* FIXME */
1279 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1280 tcm = (struct PeerTrailCompressionMessage *) &pending[1];
1281 pending->msg = &tcm->header;
1282 tcm->header.size = htons (msize);
1283 tcm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_COMPRESSION);
1284 tcm->source_peer = source_peer;
1285 tcm->new_first_friend = first_friend;
1286 tcm->trail_id = trail_id;
1287 tcm->destination_peer = destination_peer;
1289 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1290 target_friend->pending_count++;
1291 process_friend_queue (target_friend);
1297 * Seach my location in trail.
1298 * @param trail List of peers
1299 * @return my_index if found
1300 * #GNUNET_SYSERR if no entry found.
1303 search_my_index (const struct GNUNET_PeerIdentity *trail,
1308 for (i = 0; i < trail_length; i++)
1310 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &trail[i]))
1314 return GNUNET_SYSERR;
1319 * Iterate over the list of all the trails to reach Finger. In case the first
1320 * friend to reach the finger has crossed the trail threshold or is congested,
1321 * then don't select it. In case there multiple available good trails to reach
1322 * to Finger, choose the one with shortest trail length.
1323 * @param finger Finger
1324 * @return struct Correct_Trail which contains the first friend , trail id
1325 * and trail length. NULL in case none of the trails are free.
1327 static struct Correct_Trail *
1328 select_trail_to_finger (struct FingerInfo *finger)
1330 struct FriendInfo *friend;
1331 struct TrailList *iterator;
1332 struct Correct_Trail *finger_trail;
1335 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
1339 finger_trail = GNUNET_new (struct Correct_Trail);
1341 for (i = 0; i < finger->trails_count; i++)
1343 iterator = &finger->trail_list[i];
1344 if (iterator->trail_length > 0)
1346 friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1347 &iterator->trail_head->peer);
1351 friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1352 &finger->finger_identity);
1355 if ((friend->trails_count < TRAIL_THROUGH_FRIEND_THRESHOLD)||
1356 ((0 == GNUNET_TIME_absolute_get_remaining (friend->congestion_duration).rel_value_us)))
1358 if (iterator->trail_length == 0)
1360 finger_trail->friend = *friend;
1361 //finger_trail->trail_id = 0;
1362 finger_trail->trail_length = 0;
1363 return finger_trail;
1366 if (finger_trail->trail_length > iterator->trail_length)
1368 finger_trail->friend = *friend;
1369 finger_trail->trail_id = iterator->trail_id;
1370 finger_trail->trail_length = iterator->trail_length;
1375 return finger_trail;
1380 * Select closest finger to value.
1381 * @param peer1 First peer
1382 * @param peer2 Second peer
1383 * @param value Value to be compare
1384 * @return Closest peer
1386 static struct GNUNET_PeerIdentity *
1387 select_closest_finger (struct GNUNET_PeerIdentity *peer1,
1388 struct GNUNET_PeerIdentity *peer2,
1391 uint64_t peer1_value;
1392 uint64_t peer2_value;
1394 memcpy (&peer1_value, peer1, sizeof (uint64_t));
1395 memcpy (&peer2_value, peer2, sizeof (uint64_t));
1397 if ((peer1_value <= value) && (value <= peer2_value))
1399 else if ((peer2_value <= value) && (value <= peer1_value))
1401 else if ((peer1_value <= peer2_value) && (peer2_value <= value))
1403 else if ((peer2_value <= peer1_value) && (peer1_value <= value))
1405 else if ((value <= peer1_value) && (peer1_value <= peer2_value))
1407 else /*if ((value <= peer2_value) && (peer2_value <= peer1_value))*/
1413 * Select closest predecessor to value.
1414 * @param peer1 First peer
1415 * @param peer2 Second peer
1416 * @param value Value to be compare
1417 * @return Closest peer
1419 static struct GNUNET_PeerIdentity *
1420 select_closest_predecessor (struct GNUNET_PeerIdentity *peer1,
1421 struct GNUNET_PeerIdentity *peer2,
1424 uint64_t peer1_value;
1425 uint64_t peer2_value;
1427 memcpy (&peer1_value, peer1, sizeof (uint64_t));
1428 memcpy (&peer2_value, peer2, sizeof (uint64_t));
1430 if ((peer1_value <= value) && (value <= peer2_value))
1432 else if ((peer2_value <= value) && (value <= peer1_value))
1434 else if ((peer1_value <= peer2_value) && (peer2_value <= value))
1436 else if ((peer2_value <= peer1_value) && (peer1_value <= value))
1438 else if ((value <= peer1_value) && (peer1_value <= peer2_value))
1440 else /*if ((value <= peer2_value) && (peer2_value <= peer1_value))*/
1446 * Select the closest peer among two peers (which should not be same)
1447 * with respect to value and finger_map_index
1448 * @param peer1 First peer
1449 * @param peer2 Second peer
1450 * @param value Value relative to which we find the closest
1451 * @param finger_map_index Index in finger map. If equal to PREDECESSOR_FINGER_ID,
1452 * then we use different logic than other
1454 * @return Closest peer among two peers.
1456 static struct GNUNET_PeerIdentity *
1457 select_closest_peer (struct GNUNET_PeerIdentity *peer1,
1458 struct GNUNET_PeerIdentity *peer2,
1460 unsigned int finger_map_index)
1462 struct GNUNET_PeerIdentity *closest_peer;
1464 if (PREDECESSOR_FINGER_ID == finger_map_index)
1465 closest_peer = select_closest_predecessor (peer1, peer2, value);
1467 closest_peer = select_closest_finger (peer1, peer2, value);
1469 return closest_peer;
1474 * Find the successor for destination_finger_value among my_identity, all my
1475 * friend and all my fingers. Don't consider friends/ fingers with first friend in
1476 * the trail which are congested or have crossed the threshold.
1477 * @param destination_finger_value Peer closest to this value will be the next successor.
1478 * @param next_destination [out] Updated to friend identity in case a friend is
1479 * successor, updated to first friend to reach to finger
1480 * in case finger is the destination.
1481 * @param new_intermediate_trail_id [out] In case we finger is the @a next_destination,
1482 * then we updated the field with trail id to reach
1484 * @param finger_map_index Index in finger peermap for which we are looking for a finger.
1487 static struct GNUNET_PeerIdentity *
1488 find_successor (uint64_t destination_finger_value,
1489 struct GNUNET_PeerIdentity *next_destination,
1490 struct GNUNET_HashCode *new_intermediate_trail_id,
1491 unsigned int finger_map_index)
1493 struct Closest_Peer *successor;
1494 struct GNUNET_PeerIdentity *next_hop;
1495 struct GNUNET_CONTAINER_MultiPeerMapIterator *friend_iter;
1496 struct GNUNET_CONTAINER_MultiHashMap32Iterator *finger_iter;
1497 struct GNUNET_PeerIdentity *closest_peer;
1498 struct Correct_Trail *finger_trail;
1499 struct FriendInfo *friend;
1500 struct FingerInfo *finger;
1503 successor = GNUNET_new (struct Closest_Peer);
1504 memcpy (&successor->value, &my_identity, sizeof (uint64_t));
1505 //successor->trail_id = 0;
1506 successor->next_hop = my_identity;
1507 successor->next_destination = my_identity;
1509 friend_iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1510 for (i= 0; i < GNUNET_CONTAINER_multipeermap_size (friend_peermap); i++)
1512 GNUNET_assert (GNUNET_YES ==
1513 GNUNET_CONTAINER_multipeermap_iterator_next (friend_iter, NULL,
1514 (const void **)&friend));
1515 if ((friend->trails_count > TRAIL_THROUGH_FRIEND_THRESHOLD)||
1516 (0 != GNUNET_TIME_absolute_get_remaining (friend->congestion_duration).rel_value_us))
1519 closest_peer = select_closest_peer (&my_identity, &friend->id,
1520 destination_finger_value,
1522 if (0 == GNUNET_CRYPTO_cmp_peer_identity (closest_peer, &friend->id))
1524 memcpy (&successor->value, &friend->id, sizeof (uint64_t));
1525 //successor->trail_id = 0;
1526 successor->next_hop = friend->id;
1527 successor->next_destination = friend->id;
1531 finger_iter = GNUNET_CONTAINER_multihashmap32_iterator_create (finger_hashmap);
1532 for (i = 0; i < GNUNET_CONTAINER_multihashmap32_size (finger_hashmap); i++)
1534 GNUNET_assert (GNUNET_YES ==
1535 GNUNET_CONTAINER_multihashmap32_iterator_next (finger_iter, NULL,
1537 finger_trail = select_trail_to_finger (finger);
1538 if (NULL == finger_trail)
1541 closest_peer = select_closest_peer (&my_identity,
1542 &finger->finger_identity,
1543 destination_finger_value,
1545 if (0 == GNUNET_CRYPTO_cmp_peer_identity (closest_peer,
1546 &finger->finger_identity))
1548 memcpy (&successor->value, &finger->finger_identity, sizeof (uint64_t));
1549 successor->trail_id = finger_trail->trail_id;
1550 successor->next_hop = finger_trail->friend.id;
1551 successor->next_destination = finger->finger_identity;
1555 next_destination = &successor->next_destination;
1556 new_intermediate_trail_id = &successor->trail_id;
1557 next_hop = &successor->next_hop;
1563 * Construct a Put message and send it to target_peer.
1564 * @param key Key for the content
1565 * @param block_type Type of the block
1566 * @param options Routing options
1567 * @param desired_replication_level Desired replication count
1568 * @param current_destination Next current destination which will get this message.
1569 * @param current_source Source for @a current_destination
1570 * @param target_peer Peer to which this message will be forwarded.
1571 * @param hop_count Number of hops traversed so far.
1572 * @param put_path_length Total number of peers in @a put_path
1573 * @param put_path Number of peers traversed so far
1574 * @param expiration_time When does the content expire
1575 * @param data Content to store
1576 * @param data_size Size of content @a data in bytes
1579 GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key,
1580 enum GNUNET_BLOCK_Type block_type,
1581 enum GNUNET_DHT_RouteOption options,
1582 uint32_t desired_replication_level,
1583 struct GNUNET_PeerIdentity current_destination,
1584 struct GNUNET_PeerIdentity current_source,
1585 struct GNUNET_PeerIdentity *target_peer,
1587 uint32_t put_path_length,
1588 struct GNUNET_PeerIdentity *put_path,
1589 struct GNUNET_TIME_Absolute expiration_time,
1590 const void *data, size_t data_size)
1596 * Construct a Get message and send it to target_peer.
1597 * @param key Key for the content
1598 * @param block_type Type of the block
1599 * @param options Routing options
1600 * @param desired_replication_level Desired replication count
1601 * @param current_destination Next current destination which will get this message.
1602 * @param current_source Source for @a current_destination
1603 * @param target_peer Peer to which this message will be forwarded.
1604 * @param hop_count Number of hops traversed so far.
1605 * @param data Content to store
1606 * @param data_size Size of content @a data in bytes
1607 * @param get_path_length Total number of peers in @a get_path
1608 * @param get_path Number of peers traversed so far
1611 GDS_NEIGHBOURS_send_get (const struct GNUNET_HashCode *key,
1612 enum GNUNET_BLOCK_Type block_type,
1613 enum GNUNET_DHT_RouteOption options,
1614 uint32_t desired_replication_level,
1615 struct GNUNET_PeerIdentity current_destination,
1616 struct GNUNET_PeerIdentity current_source,
1617 struct GNUNET_PeerIdentity *target_peer,
1619 uint32_t get_path_length,
1620 struct GNUNET_PeerIdentity *get_path)
1627 * Send the get result to requesting client.
1628 * @param key Key of the requested data.
1629 * @param type Block type
1630 * @param target_peer Next peer to forward the message to.
1631 * @param source_peer Peer which has the data for the key.
1632 * @param put_path_length Number of peers in @a put_path
1633 * @param put_path Path taken to put the data at its stored location.
1634 * @param get_path_length Number of peers in @a get_path
1635 * @param get_path Path taken to reach to the location of the key.
1636 * @param expiration When will this result expire?
1637 * @param data Payload to store
1638 * @param data_size Size of the @a data
1641 GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key,
1642 enum GNUNET_BLOCK_Type type,
1643 struct GNUNET_PeerIdentity *target_peer,
1644 struct GNUNET_PeerIdentity *source_peer,
1645 unsigned int put_path_length,
1646 const struct GNUNET_PeerIdentity *put_path,
1647 unsigned int get_path_length,
1648 struct GNUNET_PeerIdentity *get_path,
1649 struct GNUNET_TIME_Absolute expiration,
1650 const void *data, size_t data_size)
1657 * Randomly choose one of your friends (which is not congested and have not crossed
1658 * trail threshold) from the friends_peer map
1659 * @return Friend Randomly chosen friend.
1660 * NULL in case friend peermap is empty, or all the friends are either
1661 * congested or have crossed trail threshold.
1663 static struct FriendInfo *
1664 select_random_friend ()
1666 unsigned int current_size;
1669 struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
1670 struct GNUNET_PeerIdentity key_ret;
1671 struct FriendInfo *friend;
1673 current_size = GNUNET_CONTAINER_multipeermap_size (friend_peermap);
1674 if (0 == current_size)
1677 index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, current_size);
1678 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1680 for (j = 0; j < index ; j++)
1681 GNUNET_assert (GNUNET_YES ==
1682 GNUNET_CONTAINER_multipeermap_iterator_next (iter, NULL, NULL));
1685 if (j == current_size)
1688 GNUNET_CONTAINER_multipeermap_iterator_destroy (iter);
1689 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1692 GNUNET_assert (GNUNET_YES ==
1693 GNUNET_CONTAINER_multipeermap_iterator_next (iter,
1695 (const void **)&friend));
1698 if ((TRAILS_THROUGH_FRIEND_THRESHOLD > friend->trails_count) &&
1699 (0 == GNUNET_TIME_absolute_get_remaining (friend->congestion_duration).rel_value_us))
1705 } while (j != index);
1707 GNUNET_CONTAINER_multipeermap_iterator_destroy (iter);
1713 * Compute finger_identity to which we want to setup the trail
1714 * @return finger_identity
1717 compute_finger_identity()
1721 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
1722 my_id64 = GNUNET_ntohll (my_id64);
1723 return (my_id64 + (unsigned long) pow (2, current_search_finger_index));
1728 * Compute immediate predecessor identity in the network.
1729 * @return peer identity of immediate predecessor.
1732 compute_predecessor_identity()
1736 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
1737 my_id64 = GNUNET_ntohll (my_id64);
1738 return (my_id64 -1);
1743 * Choose a random friend and start looking for the trail to reach to
1744 * finger identity through this random friend.
1746 * @param cls closure for this task
1747 * @param tc the context under which the task is running
1750 send_find_finger_trail_message (void *cls,
1751 const struct GNUNET_SCHEDULER_TaskContext *tc)
1753 struct FriendInfo *target_friend;
1754 struct GNUNET_TIME_Relative next_send_time;
1755 struct GNUNET_HashCode trail_id;
1756 uint64_t trail_id_value;
1757 struct GNUNET_HashCode intermediate_trail_id;
1758 unsigned int finger_map_index;
1759 uint64_t finger_identity;
1761 next_send_time.rel_value_us =
1762 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
1763 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1764 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us);
1765 find_finger_trail_task =
1766 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_finger_trail_message,
1769 target_friend = select_random_friend ();
1770 if (NULL == target_friend)
1775 if (PREDECESSOR_FINGER_ID == current_search_finger_index)
1777 finger_identity = compute_predecessor_identity();
1781 finger_identity = compute_finger_identity();
1784 finger_map_index = current_search_finger_index;
1786 trail_id_value = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
1787 memcpy (&trail_id, &trail_id_value, sizeof (struct GNUNET_HashCode));
1788 GDS_NEIGHBOURS_send_trail_setup (my_identity, finger_identity,
1789 target_friend->id, target_friend, 0, NULL,
1790 finger_map_index, trail_id, intermediate_trail_id);
1795 * In case there are already maximum number of possible trail to reach to a finger,
1796 * then check if the new trail's length is lesser than any of the existing trails.
1797 * If yes then replace that old trail by new trail.
1798 * Note: Here we are taking length as a parameter to choose the best possible trail,
1799 * but there could be other parameters also like - 1. duration of existence of a
1800 * trail - older the better. 2. if the new trail is completely disjoint than the
1801 * other trails, then may be choosing it is better.
1802 * @param existing_finger
1803 * @param new_finger_trail
1804 * @param new_finger_trail_length
1805 * @param new_finger_trail_id
1808 select_and_replace_trail (struct FingerInfo *existing_finger,
1809 struct GNUNET_PeerIdentity *new_trail,
1810 unsigned int new_trail_length,
1811 struct GNUNET_HashCode new_trail_id)
1813 struct TrailList *trail_list_iterator;
1814 unsigned int largest_trail_length;
1815 unsigned int largest_trail_index;
1816 struct Trail *trail_element;
1819 largest_trail_length = new_trail_length;
1820 largest_trail_index = MAXIMUM_TRAILS_PER_FINGER + 1;
1822 GNUNET_assert (MAXIMUM_TRAILS_PER_FINGER == existing_finger->trails_count);
1824 for (i = 0; i < existing_finger->trails_count; i++)
1826 trail_list_iterator = &existing_finger->trail_list[i];
1827 if (trail_list_iterator->trail_length > largest_trail_length)
1829 largest_trail_length = trail_list_iterator->trail_length;
1830 largest_trail_index = i;
1834 if (largest_trail_index == (MAXIMUM_TRAILS_PER_FINGER + 1))
1837 /* Send trail teardown message across the replaced trail. */
1838 struct TrailList *replace_trail = &existing_finger->trail_list[largest_trail_index];
1839 struct FriendInfo *target_friend =
1840 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1841 &replace_trail->trail_head->peer);
1843 GDS_NEIGHBOURS_send_trail_teardown (my_identity,
1844 existing_finger->finger_identity,
1845 replace_trail->trail_id,
1846 GDS_ROUTING_SRC_TO_DEST, target_friend);
1847 /* Free the trail .*/
1848 while (NULL != (trail_element = replace_trail->trail_head))
1850 GNUNET_CONTAINER_DLL_remove (replace_trail->trail_head,
1851 replace_trail->trail_tail, trail_element);
1852 GNUNET_free (trail_element);
1855 /* Add new trial at that location. */
1857 while ( i < new_trail_length)
1859 struct Trail *element = GNUNET_new (struct Trail);
1860 element->next = NULL;
1861 element->prev = NULL;
1862 element->peer = new_trail[0];
1864 GNUNET_CONTAINER_DLL_insert_tail (replace_trail->trail_head,
1865 replace_trail->trail_tail,
1872 * Check if the new trail to reach to finger is unique or do we already have
1873 * such a trail present for finger.
1874 * @param existing_finger Finger identity
1875 * @param new_trail New trail to reach @a existing_finger
1876 * @param trail_length Total number of peers in new_trail.
1877 * @return #GNUNET_YES if the new trail is unique
1878 * #GNUNET_NO if same trail is already present.
1881 is_new_trail_unique (struct FingerInfo *existing_finger,
1882 struct GNUNET_PeerIdentity *new_trail,
1883 unsigned int trail_length)
1885 struct TrailList *trail_list_iterator;
1886 struct Trail *trail_element;
1889 int trail_unique = GNUNET_NO;
1891 for (i = 0; i < existing_finger->trails_count; i++)
1893 trail_list_iterator = &existing_finger->trail_list[i];
1894 trail_element = trail_list_iterator->trail_head;
1895 for (j = 0; j < trail_list_iterator->trail_length; j++)
1897 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&new_trail[j],
1898 &trail_element->peer))
1900 trail_unique = GNUNET_YES;
1905 return trail_unique;
1910 * Add a new trail to existing finger.
1911 * @param existing_finger
1912 * @param new_finger_trail
1913 * @param new_finger_trail_length
1914 * @param new_finger_trail_id
1917 add_new_trail (struct FingerInfo *existing_finger,
1918 struct GNUNET_PeerIdentity *new_trail,
1919 unsigned int new_trail_length,
1920 struct GNUNET_HashCode new_trail_id)
1922 struct TrailList *trail_list_iterator;
1923 struct FriendInfo *first_friend;
1927 if (GNUNET_NO == is_new_trail_unique (existing_finger,
1934 trail_list_iterator = &existing_finger->trail_list[i];
1936 } while (trail_list_iterator->trail_head != NULL);
1938 if (new_trail_length > 0)
1939 first_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1942 first_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1943 &(existing_finger->finger_identity));
1944 first_friend->trails_count++;
1945 trail_list_iterator->first_friend_trail_count = first_friend->trails_count;
1946 trail_list_iterator->trail_length = new_trail_length;
1948 for (j = 0; j < new_trail_length; j++)
1950 struct Trail *element;
1951 element = GNUNET_new (struct Trail);
1953 element->next = NULL;
1954 element->prev = NULL;
1955 element->peer = new_trail[j];
1956 GNUNET_CONTAINER_DLL_insert_tail (trail_list_iterator->trail_head,
1957 trail_list_iterator->trail_tail,
1960 existing_finger->trails_count++;
1965 * Send trail teardown message on all trails associated with finger.
1966 * @param finger_to_be_removed
1969 send_trail_teardown (struct FingerInfo *finger)
1971 struct TrailList *trail_list_iterator;
1972 struct GNUNET_HashCode trail_id;
1973 struct FriendInfo *target_friend;
1976 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity, &my_identity)
1977 || (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1978 &finger->finger_identity)))
1981 for (i = 0; i < finger->trails_count; i++)
1983 trail_list_iterator = &finger->trail_list[i];
1984 if (trail_list_iterator->trail_length > 0)
1986 trail_id = trail_list_iterator->trail_id;
1988 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1989 &trail_list_iterator->trail_head->peer);
1990 GDS_NEIGHBOURS_send_trail_teardown (my_identity, finger->finger_identity,
1991 trail_id, GDS_ROUTING_SRC_TO_DEST,
1999 * Decrement the trail count of the first friend to reach the finger
2000 * In case finger is the friend, then decrement its trail count.
2004 decrement_friend_trail_count (struct FingerInfo *finger)
2006 struct TrailList *trail_list_iterator;
2007 struct FriendInfo *target_friend;
2010 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
2014 for (i = 0; i < finger->trails_count; i++)
2016 trail_list_iterator = &finger->trail_list[i];
2017 if (trail_list_iterator->trail_length > 0)
2019 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2020 &trail_list_iterator->trail_head->peer);
2023 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2024 &finger->finger_identity);
2026 target_friend->trails_count--;
2027 trail_list_iterator->first_friend_trail_count--;
2034 * Free finger and its trail.
2035 * @param finger Finger to be freed.
2038 free_finger (struct FingerInfo *finger)
2040 struct TrailList *trail_list_iterator;
2041 struct Trail *trail_element;
2044 for (i = 0; i < finger->trails_count; i++)
2046 trail_list_iterator = &finger->trail_list[i];
2047 while (NULL != (trail_element = trail_list_iterator->trail_head))
2049 GNUNET_CONTAINER_DLL_remove (trail_list_iterator->trail_head,
2050 trail_list_iterator->trail_tail, trail_element);
2051 GNUNET_free (trail_element);
2054 GNUNET_free (finger);
2059 * Check if new finger is closer than existing_finger. If both new finger and
2060 * existing finger are same then we may add a new trail (if there is space)
2061 * or choose the best trail among existing trails and new trails.
2062 * @param existing_finger Finger present in finger_peermap at @a finger_map_index
2063 * @param new_finger_identity Peer identity of new finger.
2064 * @param new_finger_trail Trail to reach from source to new_finger.
2065 * @param new_finger_trail_length Total number of peers in @a new_finger_trail.
2066 * @param trail_id Unique identifier of trail.
2067 * @param finger_map_index Index in finger map.
2068 * @return #GNUNET_YES if the new finger is closest.
2069 * #GNUNET_NO either new_finger and existing_finger are same, or
2070 * existing_finger is closest.
2073 is_new_finger_closest (struct FingerInfo *existing_finger,
2074 struct GNUNET_PeerIdentity new_finger_identity,
2075 struct GNUNET_PeerIdentity *new_finger_trail,
2076 unsigned int new_finger_trail_length,
2077 struct GNUNET_HashCode new_finger_trail_id,
2078 unsigned int finger_map_index)
2080 struct GNUNET_PeerIdentity *closest_peer;
2083 if (NULL == existing_finger)
2086 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity),
2087 &new_finger_identity))
2089 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
2090 closest_peer = select_closest_peer (&existing_finger->finger_identity,
2091 &new_finger_identity,
2092 my_id64, finger_map_index);
2094 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&new_finger_identity, closest_peer))
2096 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
2097 &new_finger_identity)) /* FIXME: not sure what to do here? */
2100 send_trail_teardown (existing_finger);
2101 decrement_friend_trail_count (existing_finger);
2102 free_finger (existing_finger);
2108 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity),
2112 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2113 &(existing_finger->finger_identity)))
2115 if (existing_finger->trails_count < MAXIMUM_TRAILS_PER_FINGER)
2116 add_new_trail (existing_finger, new_finger_trail,
2117 new_finger_trail_length, new_finger_trail_id);
2119 select_and_replace_trail (existing_finger, new_finger_trail,
2120 new_finger_trail_length, new_finger_trail_id);
2129 * Add a new entry in finger hashmap at finger_map_index
2130 * @param finger_identity Peer Identity of new finger
2131 * @param finger_trail Trail to reach from me to finger (excluding both end points).
2132 * @param finger_trail_length Total number of peers in @a finger_trail.
2133 * @param trail_id Unique identifier of the trail.
2134 * @param finger_map_index Index in finger hashmap.
2135 * @return #GNUNET_OK if new entry is added
2136 * #GNUNET_NO -- FIXME: need to check what value does hahsmap put
2137 * returns on failure.
2140 add_new_entry (struct GNUNET_PeerIdentity finger_identity,
2141 struct GNUNET_PeerIdentity *finger_trail,
2142 unsigned int finger_trail_length,
2143 struct GNUNET_HashCode trail_id,
2144 unsigned int finger_map_index)
2146 struct FingerInfo *new_entry;
2147 struct FriendInfo *first_trail_hop;
2148 struct TrailList *first_trail;
2151 new_entry = GNUNET_new (struct FingerInfo);
2152 new_entry->finger_identity = finger_identity;
2153 new_entry->finger_map_index = finger_map_index;
2154 new_entry->trails_count = 1;
2156 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity))
2158 if (finger_trail_length > 0)
2160 first_trail_hop = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2165 first_trail_hop = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2169 first_trail_hop->trails_count++;
2170 first_trail = &new_entry->trail_list[0];
2171 first_trail->first_friend_trail_count = first_trail_hop->trails_count;
2173 while (i < finger_trail_length)
2175 struct Trail *element = GNUNET_new (struct Trail);
2177 element->next = NULL;
2178 element->prev = NULL;
2179 element->peer = finger_trail[i];
2180 GNUNET_CONTAINER_DLL_insert_tail (first_trail->trail_head,
2181 first_trail->trail_tail,
2187 return GNUNET_CONTAINER_multihashmap32_put (finger_hashmap,
2188 new_entry->finger_map_index,
2190 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
2195 * Scan the trail to check if there is any other friend in the trail other than
2196 * first hop. If yes the shortcut the trail, send trail compression message to
2197 * peers which are no longer part of trail and send back the updated trail
2198 * and trail_length to calling function.
2199 * @param finger_identity Finger whose trail we will scan.
2200 * @param finger_trail [in, out] Trail to reach from source to finger,
2201 * @param finger_trail_length Total number of peers in original finger_trail.
2202 * @param finger_trail_id Unique identifier of the finger trail.
2203 * @return updated trail length in case we shortcut the trail, else original
2207 scan_and_compress_trail (struct GNUNET_PeerIdentity finger_identity,
2208 struct GNUNET_PeerIdentity *trail,
2209 unsigned int trail_length,
2210 struct GNUNET_HashCode trail_id)
2212 struct FriendInfo *target_friend;
2215 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity))
2221 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger_identity))
2223 if (trail_length > 0)
2225 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2227 GDS_NEIGHBOURS_send_trail_compression (my_identity, finger_identity,
2228 trail_id, finger_identity,
2235 for ( i = trail_length - 1; i > 0; i--)
2237 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, &trail[i]))
2239 struct FriendInfo *target_friend;
2242 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2244 GDS_NEIGHBOURS_send_trail_compression (my_identity, finger_identity,
2248 /* Copy the trail from index i to index trail_length -1 and change
2249 trail length and return */
2250 while (i < trail_length)
2252 memcpy (&trail[j], &trail[i], sizeof(struct GNUNET_PeerIdentity));
2260 return trail_length;
2265 * Send verify successor message to your successor on all trails to reach successor.
2266 * @param successor My current successor
2269 send_verify_successor_message (struct FingerInfo *successor)
2271 struct TrailList *trail_list_iterator;
2272 struct GNUNET_HashCode trail_id;
2273 struct GNUNET_PeerIdentity next_hop;
2274 struct FriendInfo *target_friend;
2275 struct GNUNET_PeerIdentity *trail;
2276 unsigned int trail_length;
2280 for (i = 0; i < successor->trails_count; i++)
2282 trail_list_iterator = &successor->trail_list[i];
2284 if (trail_list_iterator->trail_length > 0)
2286 trail_length = trail_list_iterator->trail_length;
2288 trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) *
2290 struct Trail *element;
2291 element = trail_list_iterator->trail_head;
2292 while ( j < trail_length)
2294 trail[j] = element->peer;
2295 element = element->next;
2298 next_hop = trail_list_iterator->trail_head->peer;
2304 next_hop = successor->finger_identity;
2306 trail_id = trail_list_iterator->trail_id;
2307 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
2308 GDS_NEIGHBOURS_send_verify_successor_message (my_identity,
2309 successor->finger_identity,
2310 trail_id, trail, trail_length,
2317 * Check if there is already an entry in finger peermap for given finger map index.
2318 * If yes, then select the closest finger. If new and existing finger are same,
2319 * the check if you can store more trails. If yes then add trail, else keep the best
2320 * trails to reach to the finger. If the new finger is closest, add it.
2321 * Then, update current_search_finger_index.
2322 * @param new_finger_identity Peer Identity of new finger
2323 * @param new_finger_trail Trail to reach the new finger
2324 * @param new_finger_length Total number of peers in @a new_finger_trail.
2325 * @param finger_map_index Index in finger peermap.
2326 * @param new_finger_trail_id Unique identifier of @new_finger_trail.
2327 * @return #GNUNET_YES if the new entry is added
2328 * #GNUNET_NO if new entry is not added, either it was discarded or
2329 * it was same as existing finger at finger map index.
2332 finger_table_add (struct GNUNET_PeerIdentity new_finger_identity,
2333 struct GNUNET_PeerIdentity *new_finger_trail,
2334 unsigned int new_finger_trail_length,
2335 unsigned int finger_map_index,
2336 struct GNUNET_HashCode new_finger_trail_id)
2338 struct FingerInfo *existing_finger;
2339 struct FingerInfo *successor;
2340 unsigned int new_entry_added = GNUNET_NO;
2342 int new_finger_updated_trail_length =
2343 scan_and_compress_trail (new_finger_identity, new_finger_trail,
2344 new_finger_trail_length, new_finger_trail_id);
2346 existing_finger = GNUNET_CONTAINER_multihashmap32_get (finger_hashmap,
2349 if (GNUNET_YES == is_new_finger_closest (existing_finger,
2350 new_finger_identity,
2352 new_finger_updated_trail_length,
2353 new_finger_trail_id, finger_map_index))
2355 GNUNET_assert (GNUNET_YES == add_new_entry (new_finger_identity,
2357 new_finger_updated_trail_length,
2358 new_finger_trail_id,
2360 new_entry_added = GNUNET_YES;
2363 successor = GNUNET_CONTAINER_multihashmap32_get (finger_hashmap,
2365 if (0 == finger_map_index)
2367 current_search_finger_index = PREDECESSOR_FINGER_ID;
2369 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,&new_finger_identity))
2371 send_verify_successor_message (successor);
2374 else if (0 == GNUNET_CRYPTO_cmp_peer_identity (&new_finger_identity,
2375 &(successor->finger_identity)))
2377 current_search_finger_index = 0;
2380 current_search_finger_index = current_search_finger_index - 1;
2382 return new_entry_added;
2387 * Core handler for P2P put messages.
2388 * @param cls closure
2389 * @param peer sender of the request
2390 * @param message message
2391 * @return #GNUNET_OK to keep the connection open,
2392 * #GNUNET_SYSERR to close it (signal serious error)
2395 handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer,
2396 const struct GNUNET_MessageHeader *message)
2403 * Core handler for p2p get requests.
2405 * @param cls closure
2406 * @param peer sender of the request
2407 * @param message message
2408 * @return #GNUNET_OK to keep the connection open,
2409 * #GNUNET_SYSERR to close it (signal serious error)
2412 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
2413 const struct GNUNET_MessageHeader *message)
2420 * Core handler for get result
2421 * @param cls closure
2422 * @param peer sender of the request
2423 * @param message message
2424 * @return #GNUNET_OK to keep the connection open,
2425 * #GNUNET_SYSERR to close it (signal serious error)
2428 handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer,
2429 const struct GNUNET_MessageHeader *message)
2435 /* Core handle for PeerTrailSetupMessage.
2436 * @param cls closure
2437 * @param message message
2438 * @param peer peer identity this notification is about
2439 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
2442 handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer,
2443 const struct GNUNET_MessageHeader *message)
2445 struct PeerTrailSetupMessage *trail_setup;
2446 struct GNUNET_PeerIdentity *trail_peer_list;
2447 struct GNUNET_PeerIdentity next_destination;
2448 struct GNUNET_PeerIdentity *current_destination;
2449 struct GNUNET_PeerIdentity *next_hop;
2450 struct GNUNET_PeerIdentity next_peer;
2451 struct FriendInfo *target_friend;
2452 struct GNUNET_PeerIdentity source;
2453 uint64_t ultimate_destination_finger_value;
2454 struct GNUNET_HashCode new_intermediate_trail_id;
2455 struct GNUNET_HashCode intermediate_trail_id;
2456 struct GNUNET_HashCode new_trail_id;
2457 unsigned int finger_map_index;
2458 uint32_t trail_length;
2461 msize = ntohs (message->size);
2462 if (msize != sizeof (struct PeerTrailSetupMessage))
2464 GNUNET_break_op (0);
2468 trail_setup = (struct PeerTrailSetupMessage *) message;
2469 trail_length = ntohl (trail_setup->trail_length);
2470 if ((msize != sizeof (struct PeerTrailSetupMessage) +
2471 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
2473 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2475 GNUNET_break_op (0);
2479 trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_setup[1];
2480 current_destination = &trail_setup->next_destination;
2481 intermediate_trail_id = trail_setup->intermediate_trail_id;
2482 new_trail_id = trail_setup->new_trail_id;
2483 ultimate_destination_finger_value = GNUNET_ntohll (trail_setup->ultimate_destination_finger);
2484 source = trail_setup->source_peer;
2485 finger_map_index = ntohl (trail_setup->finger_map_index);
2487 if (GNUNET_YES == GDS_ROUTING_threshold_reached())
2489 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
2490 GDS_NEIGHBOURS_send_trail_rejection (source, ultimate_destination_finger_value,
2491 my_identity, finger_map_index,
2492 trail_peer_list, trail_length,
2493 new_trail_id, target_friend,
2494 CONGESTION_TIMEOUT);
2498 next_hop = find_successor (ultimate_destination_finger_value, &next_destination,
2499 &new_intermediate_trail_id, finger_map_index);
2501 if (0 != (GNUNET_CRYPTO_cmp_peer_identity(&my_identity, current_destination)))
2503 struct GNUNET_PeerIdentity *closest_peer;
2504 struct GNUNET_PeerIdentity *peer1 =
2505 GDS_ROUTING_get_next_hop (intermediate_trail_id, GDS_ROUTING_SRC_TO_DEST);
2506 if (0 != GNUNET_CRYPTO_cmp_peer_identity (peer1, next_hop))
2508 closest_peer = select_closest_peer (peer1, next_hop,
2509 ultimate_destination_finger_value,
2512 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer1, closest_peer) ||
2513 (0 == GNUNET_CRYPTO_cmp_peer_identity (peer1, next_hop)))
2516 next_destination = *current_destination;
2517 new_intermediate_trail_id = intermediate_trail_id;
2521 GNUNET_assert (NULL != next_hop);
2522 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (next_hop, &my_identity)))/* This means I am the final destination */
2524 if (0 == trail_length)
2525 memcpy (&next_peer, &source, sizeof (struct GNUNET_PeerIdentity));
2527 memcpy (&next_peer, &trail_peer_list[trail_length-1], sizeof (struct GNUNET_PeerIdentity));
2529 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer);
2530 GDS_NEIGHBOURS_send_trail_setup_result (source,
2532 target_friend, trail_length,
2534 finger_map_index, new_trail_id);
2538 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
2540 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
2541 peer_list[trail_length] = my_identity;
2542 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2543 GDS_NEIGHBOURS_send_trail_setup (source,
2544 ultimate_destination_finger_value,
2546 target_friend, trail_length + 1, peer_list,
2547 finger_map_index, new_trail_id,
2548 new_intermediate_trail_id);
2555 * Core handle for p2p trail construction result messages.
2557 * @param message message
2558 * @param peer peer identity this notification is about
2559 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
2562 handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer,
2563 const struct GNUNET_MessageHeader *message)
2565 struct PeerTrailSetupResultMessage *trail_result;
2566 struct GNUNET_PeerIdentity *trail_peer_list;
2567 struct GNUNET_PeerIdentity destination_peer;
2568 struct GNUNET_PeerIdentity finger_identity;
2569 uint32_t trail_length;
2570 uint32_t finger_map_index;
2571 struct GNUNET_HashCode trail_id;
2574 msize = ntohs (message->size);
2575 if (msize != sizeof (struct PeerTrailSetupResultMessage))
2577 GNUNET_break_op (0);
2581 trail_result = (struct PeerTrailSetupResultMessage *) message;
2582 trail_length = ntohl (trail_result->trail_length);
2585 sizeof (struct PeerTrailSetupResultMessage) +
2586 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
2588 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2590 GNUNET_break_op (0);
2594 finger_map_index = htonl (trail_result->finger_map_index);
2595 destination_peer = trail_result->destination_peer;
2596 finger_identity = trail_result->finger_identity;
2597 trail_id = trail_result->trail_id;
2598 trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_result[1];
2600 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&destination_peer,
2603 finger_table_add (finger_identity, trail_peer_list,
2605 finger_map_index, trail_id);
2609 struct GNUNET_PeerIdentity next_hop;
2610 struct FriendInfo *target_friend;
2613 my_index = search_my_index(trail_peer_list, trail_length);
2614 if (my_index == GNUNET_SYSERR)
2617 return GNUNET_SYSERR;
2621 next_hop = trail_result->destination_peer;
2623 next_hop = trail_peer_list[my_index - 1];
2625 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->destination_peer),
2626 &(trail_result->finger_identity))))
2628 GDS_ROUTING_add (trail_id, &next_hop, peer);
2631 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
2632 GDS_NEIGHBOURS_send_trail_setup_result (destination_peer, finger_identity,
2633 target_friend, trail_length, trail_peer_list,
2634 finger_map_index, trail_id);
2641 * @param trail Trail to be inverted
2642 * @param trail_length Total number of peers in the trail.
2643 * @return Updated trail
2645 static struct GNUNET_PeerIdentity *
2646 invert_trail (struct GNUNET_PeerIdentity *trail,
2647 unsigned int trail_length)
2651 struct GNUNET_PeerIdentity *inverted_trail;
2653 inverted_trail = GNUNET_malloc (sizeof(struct GNUNET_PeerIdentity) *
2656 j = trail_length - 1;
2657 while (i < trail_length)
2659 inverted_trail[i] = trail[j];
2663 return inverted_trail;
2668 * Check if the new finger can be our predecessor. If yes then update predecessor
2671 * @param new_finger_trail
2672 * @param new_finger_trail_length
2676 is_new_entry_correct_predecessor (struct FingerInfo *my_predecessor,
2677 struct GNUNET_PeerIdentity new_finger,
2678 struct GNUNET_PeerIdentity *new_finger_trail,
2679 unsigned int new_finger_trail_length)
2681 struct GNUNET_PeerIdentity *updated_trail;
2682 struct GNUNET_HashCode new_trail_id;
2684 updated_trail = invert_trail (new_finger_trail, new_finger_trail_length);
2685 if (GNUNET_YES == is_new_finger_closest (my_predecessor, new_finger,
2687 new_finger_trail_length,
2688 new_trail_id, PREDECESSOR_FINGER_ID))
2690 add_new_entry (new_finger, updated_trail, new_finger_trail_length,
2691 new_trail_id, PREDECESSOR_FINGER_ID);
2692 /* FIXME: check where you send add trail message */
2699 * In case the source peer of verify successor message is not my successor,
2700 * then construct a trail from source peer to my current predecessor.
2701 * @param my_predecessor my current predecessor.
2702 * @param current_trail Trail from source to me.
2703 * @param current_trail_length Total number of peers in @a current_trail
2704 * @param new_trail_length [out] Total number of peers in updated trail.
2705 * @return Updated trail from source peer to my_predecessor.
2707 static struct GNUNET_PeerIdentity *
2708 trail_source_to_my_predecessor (struct FingerInfo *my_predecessor,
2709 struct GNUNET_PeerIdentity *current_trail,
2710 unsigned int current_trail_length,
2711 unsigned int *new_trail_length)
2713 struct GNUNET_PeerIdentity *new_trail;
2714 struct TrailList *trail_list_iterator;
2715 struct Trail *trail_iterator;
2718 unsigned int shortest_trail_length = 0;
2719 unsigned int trail_index = 0;
2721 for (i = 0; i < my_predecessor->trails_count; i++)
2723 trail_list_iterator = &my_predecessor->trail_list[i];
2724 if (trail_list_iterator->trail_length > shortest_trail_length)
2726 shortest_trail_length = trail_list_iterator->trail_length;
2730 *new_trail_length = current_trail_length + shortest_trail_length + 1;
2731 new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) *
2733 memcpy (new_trail, current_trail,
2734 current_trail_length * sizeof (struct GNUNET_PeerIdentity));
2735 new_trail[current_trail_length + 1] = my_identity;
2738 j = current_trail_length + 1;
2739 trail_list_iterator = &my_predecessor->trail_list[trail_index];
2740 trail_iterator = trail_list_iterator->trail_head;
2741 while ( i < shortest_trail_length)
2743 new_trail[j] = trail_iterator->peer;
2746 trail_iterator = trail_iterator->next;
2749 *new_trail_length = j;
2755 * Core handle for p2p verify successor messages.
2756 * @param cls closure
2757 * @param message message
2758 * @param peer peer identity this notification is about
2759 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
2762 handle_dht_p2p_verify_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
2763 const struct GNUNET_MessageHeader *message)
2765 struct PeerVerifySuccessorMessage *vsm;
2766 struct GNUNET_PeerIdentity successor;
2767 struct GNUNET_PeerIdentity source_peer;
2768 struct GNUNET_PeerIdentity *next_hop;
2769 struct FriendInfo *target_friend;
2770 struct GNUNET_HashCode trail_id;
2771 struct FingerInfo *my_predecessor;
2772 struct GNUNET_PeerIdentity *trail;
2773 struct GNUNET_PeerIdentity *new_trail;
2774 unsigned int trail_length;
2775 unsigned int new_trail_length;
2778 msize = ntohs (message->size);
2779 if (msize != sizeof (struct PeerVerifySuccessorMessage))
2781 GNUNET_break_op (0);
2785 vsm = (struct PeerVerifySuccessorMessage *) message;
2786 trail_length = ntohl (vsm->trail_length);
2787 if ((msize != sizeof (struct PeerVerifySuccessorMessage) +
2788 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
2789 (trail_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2791 GNUNET_break_op (0);
2794 trail = (struct GNUNET_PeerIdentity *)&vsm[1];
2795 source_peer = vsm->source_peer;
2796 successor = vsm->successor;
2797 trail_id = vsm->trail_id;
2799 if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&successor, &my_identity)))
2801 next_hop = GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST);
2802 if (NULL == next_hop)
2805 return GNUNET_SYSERR;
2807 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2808 GDS_NEIGHBOURS_send_verify_successor_message (source_peer, successor,
2809 trail_id, trail, trail_length,
2814 my_predecessor = GNUNET_CONTAINER_multihashmap32_get (finger_hashmap,
2815 PREDECESSOR_FINGER_ID);
2816 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
2817 if (GNUNET_NO == is_new_entry_correct_predecessor (my_predecessor, source_peer,
2818 trail, trail_length))
2820 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&source_peer,
2821 &my_predecessor->finger_identity))
2823 new_trail = trail_source_to_my_predecessor (my_predecessor, trail,
2824 trail_length, &new_trail_length);
2829 my_predecessor = GNUNET_CONTAINER_multihashmap32_get (finger_hashmap,
2830 PREDECESSOR_FINGER_ID);
2831 GDS_NEIGHBOURS_send_add_trail (my_predecessor->finger_identity,
2832 source_peer, trail_id,
2833 trail, trail_length,
2835 new_trail_length = trail_length;
2836 new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) *
2838 memcpy (new_trail, trail, sizeof (struct GNUNET_PeerIdentity) *
2842 GDS_NEIGHBOURS_send_verify_successor_result (source_peer, my_identity,
2843 my_predecessor->finger_identity,
2844 trail_id, new_trail,
2846 GDS_ROUTING_DEST_TO_SRC,
2853 * Core handle for p2p verify successor result messages.
2854 * @param cls closure
2855 * @param message message
2856 * @param peer peer identity this notification is about
2857 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
2860 handle_dht_p2p_verify_successor_result(void *cls, const struct GNUNET_PeerIdentity *peer,
2861 const struct GNUNET_MessageHeader *message)
2863 struct PeerVerifySuccessorResultMessage *vsrm;
2864 enum GDS_ROUTING_trail_direction trail_direction;
2865 struct GNUNET_HashCode trail_id;
2866 unsigned int new_trail_length;
2867 struct GNUNET_PeerIdentity *new_trail;
2868 struct GNUNET_PeerIdentity destination_peer;
2869 struct GNUNET_PeerIdentity my_new_successor;
2870 struct GNUNET_PeerIdentity *next_hop;
2871 struct FriendInfo *target_friend;
2874 msize = ntohs (message->size);
2875 if (msize != sizeof (struct PeerVerifySuccessorResultMessage))
2877 GNUNET_break_op (0);
2880 vsrm = (struct PeerVerifySuccessorResultMessage *) message;
2881 new_trail_length = ntohl (vsrm->trail_length);
2882 trail_direction = ntohl (vsrm->trail_direction);
2883 trail_id = vsrm->trail_id;
2886 sizeof (struct PeerVerifySuccessorResultMessage) +
2888 sizeof (struct GNUNET_PeerIdentity)) ||
2890 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2892 GNUNET_break_op (0);
2896 new_trail = (struct GNUNET_PeerIdentity *) &vsrm[1];
2897 destination_peer = vsrm->destination_peer;
2898 my_new_successor = vsrm->my_predecessor;
2900 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&destination_peer, &my_identity)))
2902 struct GNUNET_HashCode new_finger_trail_id;
2903 if (GNUNET_YES == finger_table_add (my_new_successor,
2906 PREDECESSOR_FINGER_ID, new_finger_trail_id))
2908 if (new_trail_length > 0)
2909 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2912 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2914 GDS_NEIGHBOURS_send_notify_new_successor (my_identity, my_new_successor,
2917 new_finger_trail_id, target_friend);
2922 GNUNET_assert (NULL != (next_hop =
2923 GDS_ROUTING_get_next_hop (trail_id, trail_direction)));
2924 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2925 GDS_NEIGHBOURS_send_verify_successor_result (destination_peer,
2926 vsrm->source_successor,
2927 my_new_successor, trail_id,
2930 trail_direction, target_friend);
2936 * Here we need to pass the whole trail to reach to new successor as we
2937 don't have that stored in our routing table. while passing through each
2938 peer we will have to add an entry. also when you are the destination and
2939 if you have added it back as pred, then you also need to add the trail in
2940 your own finger table and send add trail message to add this trail. you
2941 shoudl generate a new trail id. although they are same trails but you have
2942 to ahve different trail id.
2943 * Core handle for p2p notify new successor messages.
2944 * @param cls closure
2945 * @param message message
2946 * @param peer peer identity this notification is about
2947 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
2950 handle_dht_p2p_notify_new_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
2951 const struct GNUNET_MessageHeader *message)
2953 struct PeerNotifyNewSuccessorMessage *nsm;
2954 struct GNUNET_PeerIdentity *trail;
2955 struct GNUNET_PeerIdentity source;
2956 struct GNUNET_PeerIdentity destination;
2957 struct FriendInfo *target_friend;
2958 //struct GNUNET_HashCode trail_id;
2960 uint32_t trail_length;
2962 msize = ntohs (message->size);
2963 if (msize < sizeof (struct PeerNotifyNewSuccessorMessage))
2965 GNUNET_break_op (0);
2968 nsm = (struct PeerNotifyNewSuccessorMessage *) message;
2969 trail_length = ntohl (nsm->trail_length);
2971 if ((msize < sizeof (struct PeerNotifyNewSuccessorMessage) +
2972 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
2974 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2976 GNUNET_break_op (0);
2980 trail = (struct GNUNET_PeerIdentity *) &nsm[1];
2981 source = nsm->source_peer;
2982 destination = nsm->destination_peer;
2983 //trail_id = nsm->trail_id;
2985 if ( 0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &destination))
2987 struct GNUNET_HashCode new_trail_id;
2988 struct FingerInfo *my_predecessor;
2989 if (GNUNET_YES == is_new_entry_correct_predecessor (my_predecessor,
2993 GDS_NEIGHBOURS_send_add_trail (my_identity, source, new_trail_id,
2994 trail, trail_length, target_friend);
2998 //GDS_ROUTING_add (new_trail_id, peer, next_hop);
3006 * FIXME: Here you should keep the trail id with you.
3007 * Core handler for P2P trail rejection message
3008 * @param cls closure
3009 * @param message message
3010 * @param peer peer identity this notification is about
3011 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3014 handle_dht_p2p_trail_rejection(void *cls, const struct GNUNET_PeerIdentity *peer,
3015 const struct GNUNET_MessageHeader *message)
3017 struct PeerTrailRejectionMessage *trail_rejection;
3018 unsigned int trail_length;
3019 struct GNUNET_PeerIdentity *trail_peer_list;
3020 struct FriendInfo *target_friend;
3021 struct GNUNET_TIME_Relative congestion_timeout;
3022 struct GNUNET_HashCode trail_id;
3023 struct GNUNET_PeerIdentity next_destination;
3024 struct GNUNET_HashCode new_intermediate_trail_id;
3025 struct GNUNET_PeerIdentity next_peer;
3026 struct GNUNET_PeerIdentity source;
3027 struct GNUNET_PeerIdentity *next_hop;
3028 uint64_t ultimate_destination_finger_value;
3029 unsigned int finger_map_index;
3032 msize = ntohs (message->size);
3033 if (msize != sizeof (struct PeerTrailRejectionMessage))
3035 GNUNET_break_op (0);
3039 trail_rejection = (struct PeerTrailRejectionMessage *) message;
3040 trail_length = ntohl (trail_rejection->trail_length);
3042 if ((msize != sizeof (struct PeerTrailRejectionMessage) +
3043 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3045 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3047 GNUNET_break_op (0);
3051 trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_rejection[1];
3052 finger_map_index = ntohl (trail_rejection->finger_map_index);
3053 congestion_timeout = trail_rejection->congestion_time;
3054 source = trail_rejection->source_peer;
3055 trail_id = trail_rejection->trail_id;
3056 ultimate_destination_finger_value =
3057 trail_rejection->ultimate_destination_finger_identity_value;
3059 /* First set the congestion time of the friend that sent you this message. */
3060 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
3061 target_friend->congestion_duration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(),
3062 congestion_timeout);
3064 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &source)))
3069 /* If I am congested then pass this message to peer before me in trail. */
3070 if(GNUNET_YES == GDS_ROUTING_threshold_reached())
3072 struct GNUNET_PeerIdentity *new_trail;
3073 unsigned int new_trail_length;
3075 if (trail_length == 1)
3078 new_trail_length = 0;
3083 next_hop = &trail_peer_list[trail_length - 2];
3084 /* Remove myself from the trail. */
3085 new_trail_length = trail_length -1;
3086 new_trail = GNUNET_malloc (new_trail_length * sizeof (struct GNUNET_PeerIdentity));
3087 memcpy (new_trail, trail_peer_list, new_trail_length * sizeof (struct GNUNET_PeerIdentity));
3090 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3091 GDS_NEIGHBOURS_send_trail_rejection (source,
3092 ultimate_destination_finger_value,
3093 my_identity, finger_map_index,
3094 new_trail,new_trail_length,trail_id,
3095 target_friend, CONGESTION_TIMEOUT);
3099 /* Look for next_hop to pass the trail setup message */
3100 next_hop = find_successor (ultimate_destination_finger_value,
3102 &new_intermediate_trail_id,
3105 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (next_hop, &my_identity)))/* This means I am the final destination */
3107 if (0 == trail_length)
3110 next_peer = trail_peer_list[trail_length-1];
3112 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer);
3113 GDS_NEIGHBOURS_send_trail_setup_result (source,
3115 target_friend, trail_length,
3117 finger_map_index, trail_id);
3121 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
3123 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
3124 peer_list[trail_length] = my_identity;
3126 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3127 GDS_NEIGHBOURS_send_trail_setup (source,
3128 ultimate_destination_finger_value,
3130 target_friend, trail_length + 1, peer_list,
3131 finger_map_index, trail_id,
3132 new_intermediate_trail_id);
3139 * Core handle for p2p trail tear down messages.
3140 * @param cls closure
3141 * @param message message
3142 * @param peer peer identity this notification is about
3143 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3146 handle_dht_p2p_trail_compression (void *cls, const struct GNUNET_PeerIdentity *peer,
3147 const struct GNUNET_MessageHeader *message)
3149 struct PeerTrailCompressionMessage *trail_compression;
3150 struct GNUNET_PeerIdentity *next_hop;
3151 struct GNUNET_HashCode trail_id;
3152 struct FriendInfo *target_friend;
3155 msize = ntohs (message->size);
3156 if (msize != sizeof (struct PeerTrailCompressionMessage))
3158 GNUNET_break_op (0);
3162 trail_compression = (struct PeerTrailCompressionMessage *) message;
3163 trail_id = trail_compression->trail_id;
3165 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_compression->new_first_friend),
3168 if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&(trail_compression->destination_peer),
3171 GDS_ROUTING_update_trail_prev_hop (trail_id,
3172 trail_compression->source_peer);
3177 next_hop = GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST);
3178 if (NULL == next_hop)
3180 GNUNET_break (0); /*FIXME: How to handle this case. */
3183 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id));
3184 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3185 GDS_NEIGHBOURS_send_trail_compression (trail_compression->source_peer,
3186 trail_compression->destination_peer,
3188 trail_compression->new_first_friend,
3195 * Core handler for trail teardown message.
3196 * @param cls closure
3197 * @param message message
3198 * @param peer peer identity this notification is about
3199 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3202 handle_dht_p2p_trail_teardown (void *cls, const struct GNUNET_PeerIdentity *peer,
3203 const struct GNUNET_MessageHeader *message)
3210 * TRAIL ID and each peer should add an entry in the routing table.
3211 * Core handle for p2p add trail message.
3212 * @param cls closure
3213 * @param message message
3214 * @param peer peer identity this notification is about
3215 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3218 handle_dht_p2p_add_trail (void *cls, const struct GNUNET_PeerIdentity *peer,
3219 const struct GNUNET_MessageHeader *message)
3226 *FIXME; call send_trail_teardown_message on all the trails of the finger that
3227 * you remove. Also you don't need to decerement friend trail count as that
3228 * friend is removed. But you can not send trail teardown message as the friend
3229 * is disconnected. then you don't have any next_hop. and in case there are
3230 * multiple trails. and friend is the first trail then you remove only the trail.
3231 * Iterate over finger_hashmap, and remove entries if finger is the disconnected
3232 * peer or if disconnected peer is the first friend in the trail to reach the
3234 * @param cls closure
3235 * @param key current public key
3236 * @param value value in the hash map
3237 * @return #GNUNET_YES if we should continue to
3239 * #GNUNET_NO if not.
3242 remove_matching_finger (void *cls,
3246 struct FingerInfo *remove_finger = value;
3247 const struct GNUNET_PeerIdentity *disconnected_peer = cls;
3248 struct TrailList *trail_list;
3251 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&remove_finger->finger_identity,
3254 GNUNET_assert (GNUNET_YES ==
3255 GNUNET_CONTAINER_multihashmap32_remove (finger_hashmap,
3258 free_finger (remove_finger);
3262 for (i = 0; i< remove_finger->trails_count; i++)
3264 trail_list = &remove_finger->trail_list[i];
3265 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&trail_list->trail_head->peer,
3268 GNUNET_assert (GNUNET_YES ==
3269 GNUNET_CONTAINER_multihashmap32_remove (finger_hashmap,
3272 free_finger (remove_finger);
3281 * Method called whenever a peer disconnects.
3283 * @param cls closure
3284 * @param peer peer identity this notification is about
3287 handle_core_disconnect (void *cls,
3288 const struct GNUNET_PeerIdentity *peer)
3290 struct FriendInfo *remove_friend;
3292 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
3296 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
3298 if (NULL == remove_friend)
3304 GNUNET_assert (GNUNET_SYSERR !=
3305 GNUNET_CONTAINER_multihashmap32_iterate (finger_hashmap,
3306 &remove_matching_finger,
3308 GDS_ROUTING_remove_trail_by_peer (peer);
3309 GNUNET_assert (GNUNET_YES ==
3310 GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
3314 if (0 != GNUNET_CONTAINER_multipeermap_size (friend_peermap))
3317 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
3319 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
3320 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
3328 * Method called whenever a peer connects.
3330 * @param cls closure
3331 * @param peer_identity peer identity this notification is about
3334 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity)
3336 struct FriendInfo *friend;
3338 /* Check for connect to self message */
3339 if (0 == memcmp (&my_identity, peer_identity, sizeof (struct GNUNET_PeerIdentity)))
3342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to %s\n", GNUNET_i2s (peer_identity));
3344 /* If peer already exists in our friend_peermap, then exit. */
3345 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (friend_peermap, peer_identity))
3351 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
3354 friend = GNUNET_new (struct FriendInfo);
3355 friend->id = *peer_identity;
3357 GNUNET_assert (GNUNET_OK ==
3358 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
3359 peer_identity, friend,
3360 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
3362 /* got a first connection, good time to start with FIND FINGER TRAIL requests... */
3363 if (GNUNET_SCHEDULER_NO_TASK == find_finger_trail_task)
3364 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
3369 * To be called on core init/fail.
3371 * @param cls service closure
3372 * @param identity the public identity of this peer
3375 core_init (void *cls,
3376 const struct GNUNET_PeerIdentity *identity)
3378 my_identity = *identity;
3383 * Initialize neighbours subsystem.
3384 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3387 GDS_NEIGHBOURS_init (void)
3389 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
3390 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0},
3391 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0},
3392 {&handle_dht_p2p_get_result, GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT, 0},
3393 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP, 0},
3394 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT, 0},
3395 {&handle_dht_p2p_verify_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR, 0},
3396 {&handle_dht_p2p_verify_successor_result, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT, 0},
3397 {&handle_dht_p2p_notify_new_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR, 0},
3398 {&handle_dht_p2p_trail_rejection, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION, 0},
3399 {&handle_dht_p2p_trail_compression, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_COMPRESSION, 0},
3400 {&handle_dht_p2p_trail_teardown, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_TEARDOWN, 0},
3401 {&handle_dht_p2p_add_trail, GNUNET_MESSAGE_TYPE_DHT_P2P_ADD_TRAIL, 0},
3406 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
3407 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
3408 GNUNET_NO, core_handlers);
3409 if (NULL == core_api)
3410 return GNUNET_SYSERR;
3412 friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
3413 finger_hashmap = GNUNET_CONTAINER_multihashmap32_create (MAX_FINGERS * 4/3);
3419 * Shutdown neighbours subsystem.
3422 GDS_NEIGHBOURS_done (void)
3424 if (NULL == core_api)
3427 GNUNET_CORE_disconnect (core_api);
3430 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
3431 GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
3432 friend_peermap = NULL;
3434 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (finger_hashmap));
3435 GNUNET_CONTAINER_multihashmap32_destroy (finger_hashmap);
3436 finger_hashmap = NULL;
3438 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
3441 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
3442 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
3450 * @return my identity
3452 struct GNUNET_PeerIdentity
3453 GDS_NEIGHBOURS_get_my_id (void)