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"
49 * 1. In X-Vine paper, there is no policy defined for replicating the data to
50 * recover in case of peer failure. We can do it in Chord way. In R5N, the key
51 * is hashed and then data is stored according to the key value generated after
53 * 2. We will keep an entry in routing table even if its a friend for the moment.
54 * Because I am not sure if there is a case where it will not work.
55 * Trail id we can keep but actually there is no trail.
60 * Maximum possible fingers (including predecessor) of a peer
62 #define MAX_FINGERS 65
65 * Maximum allowed number of pending messages per friend peer.
67 #define MAXIMUM_PENDING_PER_FRIEND 64
70 * How long to wait before sending another find finger trail request
72 #define DHT_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
75 * How long at most to wait for transmission of a request to a friend ?
77 #define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
80 * Duration for which I may remain congested.
81 * Note: Its a static value. In future, a peer may do some analysis and calculate
82 * congestion_timeout based on 'some' parameters.
84 #define CONGESTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
87 * Maximum number of trails allowed to go through a friend.
89 #define TRAILS_THROUGH_FRIEND_THRESHOLD 64
92 * Maximum number of trails stored per finger.
94 #define MAXIMUM_TRAILS_PER_FINGER 1
97 * Finger map index for predecessor entry in finger table.
99 #define PREDECESSOR_FINGER_ID 64
102 * Wrap around in peer identity circle.
104 #define PEER_IDENTITES_WRAP_AROUND pow(2, 64) - 1
107 * FIXME: Its use only at 3 places check if you can remove it.
108 * To check if a finger is predecessor or not.
110 enum GDS_NEIGHBOURS_finger_type
112 GDS_FINGER_TYPE_PREDECESSOR = 0,
113 GDS_FINGER_TYPE_NON_PREDECESSOR = 1
116 GNUNET_NETWORK_STRUCT_BEGIN
121 struct PeerPutMessage
124 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_PUT
126 struct GNUNET_MessageHeader header;
131 uint32_t options GNUNET_PACKED;
136 uint32_t block_type GNUNET_PACKED;
141 uint32_t hop_count GNUNET_PACKED;
144 * Replication level for this message
145 * In the current implementation, this value is not used.
147 uint32_t desired_replication_level GNUNET_PACKED;
150 * Length of the PUT path that follows (if tracked).
152 uint32_t put_path_length GNUNET_PACKED;
155 * Best known destination (could be my friend or finger) which should
156 * get this message next.
158 struct GNUNET_PeerIdentity best_known_destination;
161 * In case best_known_destination is a finger, then trail to reach
162 * to that finger. Else its default value is 0.
164 struct GNUNET_HashCode intermediate_trail_id;
167 * When does the content expire?
169 struct GNUNET_TIME_AbsoluteNBO expiration_time;
172 * The key to store the value under.
174 struct GNUNET_HashCode key GNUNET_PACKED;
176 /* put path (if tracked) */
185 struct PeerGetMessage
188 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_GET
190 struct GNUNET_MessageHeader header;
195 uint32_t options GNUNET_PACKED;
198 * Desired content type.
200 uint32_t block_type GNUNET_PACKED;
205 uint32_t hop_count GNUNET_PACKED;
208 * Desired replication level for this request.
209 * In the current implementation, this value is not used.
211 uint32_t desired_replication_level GNUNET_PACKED;
214 * Total number of peers in get path.
216 unsigned int get_path_length;
219 * Best known destination (could be my friend or finger) which should
220 * get this message next.
222 struct GNUNET_PeerIdentity best_known_destination;
225 * In case best_known_destination is a finger, then trail to reach
226 * to that finger. Else its default value is 0.
228 struct GNUNET_HashCode intermediate_trail_id;
231 * The key we are looking for.
233 struct GNUNET_HashCode key;
236 /* struct GNUNET_PeerIdentity[]*/
242 struct PeerGetResultMessage
245 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_GET_RESULT
247 struct GNUNET_MessageHeader header;
250 * The type for the data.
252 uint32_t type GNUNET_PACKED;
255 * Number of peers recorded in the outgoing path from source to the
256 * stored location of this message.
258 uint32_t put_path_length GNUNET_PACKED;
261 * Length of the GET path that follows (if tracked).
263 uint32_t get_path_length GNUNET_PACKED;
266 * Peer which queried for get and should get the result.
268 struct GNUNET_PeerIdentity querying_peer;
271 * When does the content expire?
273 struct GNUNET_TIME_Absolute expiration_time;
276 * The key of the corresponding GET request.
278 struct GNUNET_HashCode key;
280 /* put path (if tracked) */
282 /* get path (if tracked) */
289 * P2P Trail setup message
291 struct PeerTrailSetupMessage
294 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP
296 struct GNUNET_MessageHeader header;
299 * Is source_peer trying to setup the trail to a predecessor or any finger.
301 uint32_t is_predecessor;
304 * Peer closest to this value will be our finger.
306 uint64_t final_destination_finger_value;
309 * Source peer which wants to setup the trail to one of its finger.
311 struct GNUNET_PeerIdentity source_peer;
314 * Best known destination (could be my friend or finger) which should
315 * get this message next.
317 struct GNUNET_PeerIdentity best_known_destination;
320 * In case best_known_destination is a finger, then trail id of trail to
321 * reach to this finger.
323 struct GNUNET_HashCode intermediate_trail_id;
326 * Trail id for trail which we are trying to setup.
328 struct GNUNET_HashCode trail_id;
330 /* List of peers which are part of trail setup so far.
331 * Trail does NOT include source_peer and peer which will be closest to
332 * ultimate_destination_finger_value.
333 * struct GNUNET_PeerIdentity trail[]
338 * P2P Trail Setup Result message
340 struct PeerTrailSetupResultMessage
344 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_RESULT
346 struct GNUNET_MessageHeader header;
349 * Finger to which we have found the path.
351 struct GNUNET_PeerIdentity finger_identity;
354 * Peer which started trail_setup to find trail to finger_identity
356 struct GNUNET_PeerIdentity querying_peer;
359 * Is the trail setup to querying_peer's predecessor or finger?
361 uint32_t is_predecessor;
364 * Value to which finger_identity is the closest peer.
366 uint64_t ulitmate_destination_finger_value;
369 * Identifier of the trail from querying peer to finger_identity, NOT
370 * including both endpoints.
372 struct GNUNET_HashCode trail_id;
374 /* List of peers which are part of the trail from querying peer to
375 * finger_identity, NOT including both endpoints.
376 * struct GNUNET_PeerIdentity trail[]
381 * P2P Verify Successor Message.
383 struct PeerVerifySuccessorMessage
386 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR
388 struct GNUNET_MessageHeader header;
391 * Peer which wants to verify its successor.
393 struct GNUNET_PeerIdentity source_peer;
396 * Source Peer's current successor.
398 struct GNUNET_PeerIdentity successor;
401 * Identifier of trail to reach from source_peer to successor.
403 struct GNUNET_HashCode trail_id;
405 /* List of the peers which are part of trail to reach from source_peer
406 * to successor, NOT including them
407 * struct GNUNET_PeerIdentity trail[]
412 * P2P Verify Successor Result Message
414 struct PeerVerifySuccessorResultMessage
417 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR_RESULT
419 struct GNUNET_MessageHeader header;
422 * Peer which sent the request to verify its successor.
424 struct GNUNET_PeerIdentity querying_peer;
427 * Successor to which PeerVerifySuccessorMessage was sent.
429 struct GNUNET_PeerIdentity current_successor;
432 * Current Predecessor of source_successor. It can be same as querying peer
433 * or different. In case it is different then it can be querying_peer's
434 * probable successor.
436 struct GNUNET_PeerIdentity probable_successor;
439 * Trail identifier of trail from querying_peer to current_successor.
441 struct GNUNET_HashCode trail_id;
444 * Direction in which we are looking at the trail.
446 uint32_t trail_direction;
448 /* In case probable_successor != querying_peer, then trail to reach from
449 * querying_peer to probable_successor, NOT including end points.
450 * struct GNUNET_PeerIdentity trail[]
455 * P2P Notify New Successor Message.
457 struct PeerNotifyNewSuccessorMessage
460 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_NEW_SUCCESSOR
462 struct GNUNET_MessageHeader header;
465 * Peer which wants to notify its new successor.
467 struct GNUNET_PeerIdentity source_peer;
470 * New successor of source_peer.
472 struct GNUNET_PeerIdentity new_successor;
475 * Unique identifier of the trail from source_peer to new_successor,
476 * NOT including the endpoints.
478 struct GNUNET_HashCode trail_id;
480 /* List of peers in trail from source_peer to new_successor,
481 * NOT including the endpoints.
482 * struct GNUNET_PeerIdentity trail[]
487 * P2P Trail Compression Message.
489 struct PeerTrailCompressionMessage
492 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_COMPRESSION
494 struct GNUNET_MessageHeader header;
497 * Source peer of this trail.
499 struct GNUNET_PeerIdentity source_peer;
502 * Trail from source_peer to destination_peer compressed such that
503 * new_first_friend is the first hop in the trail from source to
506 struct GNUNET_PeerIdentity new_first_friend;
509 * Unique identifier of trail.
511 struct GNUNET_HashCode trail_id;
516 * P2P Trail Tear Down message.
518 struct PeerTrailTearDownMessage
521 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN
523 struct GNUNET_MessageHeader header;
526 * Unique identifier of the trail.
528 struct GNUNET_HashCode trail_id;
531 * Direction of trail.
533 uint32_t trail_direction;
538 * P2P Trail Rejection Message.
540 struct PeerTrailRejectionMessage
543 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_REJECTION
545 struct GNUNET_MessageHeader header;
548 * Peer which wants to set up the trail.
550 struct GNUNET_PeerIdentity source_peer;
553 * Peer which sent trail rejection message as it it congested.
555 struct GNUNET_PeerIdentity congested_peer;
558 * Peer identity closest to this value will be finger of
561 uint64_t ultimate_destination_finger_value;
564 * Is source_peer trying to setup the trail to its predecessor or finger.
566 uint32_t is_predecessor;
569 * Identifier for the trail that source peer is trying to setup.
571 struct GNUNET_HashCode trail_id;
574 * Relative time for which congested_peer will remain congested.
576 struct GNUNET_TIME_Relative congestion_time;
578 /* Trail_list from source_peer to peer which sent the message for trail setup
579 * to congested peer. This trail does NOT include source_peer.
580 struct GNUNET_PeerIdnetity trail[]*/
584 * P2P Add Trail Message.
586 struct PeerAddTrailMessage
589 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_ADD_TRAIL
591 struct GNUNET_MessageHeader header;
594 * Source of the routing trail.
596 struct GNUNET_PeerIdentity source_peer;
599 * Destination of the routing trail.
601 struct GNUNET_PeerIdentity destination_peer;
604 * Unique identifier of the trail from source_peer to destination_peer,
605 * NOT including the endpoints.
607 struct GNUNET_HashCode trail_id;
609 /* Trail from source peer to destination peer, NOT including them.
610 * struct GNUNET_PeerIdentity trail[]
614 GNUNET_NETWORK_STRUCT_END
617 * Linked list of messages to send to a particular other peer.
619 struct P2PPendingMessage
622 * Pointer to next item in the list
624 struct P2PPendingMessage *next;
627 * Pointer to previous item in the list
629 struct P2PPendingMessage *prev;
632 * Message importance level. FIXME: used? useful?
634 unsigned int importance;
637 * When does this message time out?
639 struct GNUNET_TIME_Absolute timeout;
642 * Actual message to be sent, allocated at the end of the struct:
643 * // msg = (cast) &pm[1];
644 * // memcpy (&pm[1], data, len);
646 const struct GNUNET_MessageHeader *msg;
651 * Entry in friend_peermap.
658 struct GNUNET_PeerIdentity id;
661 * Number of trails for which this friend is the first hop or if the friend
664 unsigned int trails_count;
667 * Count of outstanding messages for this friend.
669 unsigned int pending_count;
672 * In case not 0, then amount of time for which this friend is congested.
674 struct GNUNET_TIME_Absolute congestion_timestamp;
677 * Head of pending messages to be sent to this friend.
679 struct P2PPendingMessage *head;
682 * Tail of pending messages to be sent to this friend.
684 struct P2PPendingMessage *tail;
687 * Core handle for sending messages to this friend.
689 struct GNUNET_CORE_TransmitHandle *th;
694 * An individual element of the trail to reach to a finger.
699 * Pointer to next item in the list
701 struct Trail_Element *next;
704 * Pointer to prev item in the list
706 struct Trail_Element *prev;
709 * An element in this trail.
711 struct GNUNET_PeerIdentity peer;
715 * FIXME: removed first_friend_trails_count, need to write a function
716 * to calculate each time we need it. Else, keep a pointer to first
717 * friend of in the trail.
718 * Information about an individual trail.
725 struct Trail_Element *trail_head;
730 struct Trail_Element *trail_tail;
733 * Unique identifier of this trail.
735 struct GNUNET_HashCode trail_id;
738 * Length of trail pointed
740 unsigned int trail_length;
743 * Is there a valid trail entry.
745 unsigned int is_present;
749 * An entry in finger_table
756 struct GNUNET_PeerIdentity finger_identity;
759 * Is any finger stored at this finger index.
761 unsigned int is_present;
764 * Index in finger peer map
766 uint32_t finger_table_index;
769 * Number of trails setup so far for this finger.
770 * Should not cross MAXIMUM_TRAILS_PER_FINGER.
772 uint32_t trails_count;
775 * Array of trails to reach to this finger.
777 struct Trail trail_list[MAXIMUM_TRAILS_PER_FINGER];
782 * Data structure to keep track of closest peer seen so far in find_successor()
787 * Destination finger value.
789 uint64_t destination_finger_value;
792 * Is finger_value a predecessor or any other finger.
794 unsigned int is_predecessor;
797 * Trail id to reach to peer.
798 * In case peer is my identity or friend, it is set to NULL.
800 struct GNUNET_HashCode *trail_id;
803 * Next destination. In case of friend and my_identity , it is same as next_hop
804 * In case of finger it is finger identity.
806 struct GNUNET_PeerIdentity best_known_destination;
809 * In case best_known_destination is a finger, then first friend in the trail
810 * to reach to it. In other case, same as best_known_destination.
812 struct GNUNET_PeerIdentity next_hop;
817 * Data structure to store the trail chosen to reach to finger.
819 struct Selected_Finger_Trail
822 * First friend in the trail to reach finger.
824 struct FriendInfo friend;
827 * Identifier of this trail.
829 struct GNUNET_HashCode *trail_id;
832 * Total number of peers in this trail.
834 unsigned int trail_length;
838 * Task that sends FIND FINGER TRAIL requests. This task is started when we have
839 * get our first friend.
841 static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task;
844 * Identity of this peer.
846 static struct GNUNET_PeerIdentity my_identity;
849 * Peer map of all the friends of a peer
851 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap;
854 * Array of all the fingers.
856 static struct FingerInfo finger_table [MAX_FINGERS];
861 static struct GNUNET_CORE_Handle *core_api;
864 * The current finger index that we have want to find trail to. We start the
865 * search with value = 0, i.e. successor and then go to PREDCESSOR_FINGER_ID
866 * and decrement it. For any index 63 <= index < 0, if finger is same as successor,
867 * we reset this index to 0.
869 static unsigned int current_search_finger_index;
873 * Called when core is ready to send a message we asked for
874 * out to the destination.
876 * @param cls the 'struct FriendInfo' of the target friend
877 * @param size number of bytes available in buf
878 * @param buf where the callee should write the message
879 * @return number of bytes written to buf
882 core_transmit_notify (void *cls, size_t size, void *buf)
884 struct FriendInfo *peer = cls;
886 struct P2PPendingMessage *pending;
891 while ((NULL != (pending = peer->head)) &&
892 (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us))
894 peer->pending_count--;
895 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
896 GNUNET_free (pending);
900 /* no messages pending */
906 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
907 GNUNET_CORE_PRIO_BEST_EFFORT,
908 GNUNET_TIME_absolute_get_remaining
909 (pending->timeout), &peer->id,
910 ntohs (pending->msg->size),
911 &core_transmit_notify, peer);
912 GNUNET_break (NULL != peer->th);
916 while ((NULL != (pending = peer->head)) &&
917 (size - off >= (msize = ntohs (pending->msg->size))))
919 GNUNET_STATISTICS_update (GDS_stats,
921 ("# Bytes transmitted to other peers"), msize,
923 memcpy (&cbuf[off], pending->msg, msize);
925 peer->pending_count--;
926 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
927 GNUNET_free (pending);
929 if (peer->head != NULL)
932 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
933 GNUNET_CORE_PRIO_BEST_EFFORT,
934 GNUNET_TIME_absolute_get_remaining
935 (pending->timeout), &peer->id, msize,
936 &core_transmit_notify, peer);
937 GNUNET_break (NULL != peer->th);
944 * Transmit all messages in the friend's message queue.
946 * @param peer message queue to process
949 process_friend_queue (struct FriendInfo *peer)
951 struct P2PPendingMessage *pending;
953 if (NULL == (pending = peer->head))
955 if (NULL != peer->th)
958 GNUNET_STATISTICS_update (GDS_stats,
960 ("# Bytes of bandwidth requested from core"),
961 ntohs (pending->msg->size), GNUNET_NO);
964 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
966 GNUNET_TIME_absolute_get_remaining
967 (pending->timeout), &peer->id,
968 ntohs (pending->msg->size),
969 &core_transmit_notify, peer);
970 GNUNET_break (NULL != peer->th);
975 * Return friend corresponding to peer.
980 GDS_NEIGHBOURS_get_friend (struct GNUNET_PeerIdentity peer)
982 struct FriendInfo *friend;
983 GNUNET_assert (NULL != (friend =
984 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &peer)));
990 * Construct a trail setup message and forward it to target_friend
991 * @param source_peer Peer which wants to setup the trail
992 * @param ultimate_destination_finger_value Peer identity closest to this value
993 * will be finger to @a source_peer
994 * @param best_known_destination Best known destination (could be finger or friend)
995 * which should get this message. In case it is
996 * friend, then it is same as target_friend
997 * @param target_friend Friend to which message is forwarded now.
998 * @param trail_length Total number of peers in trail setup so far.
999 * @param trail_peer_list Trail setup so far
1000 * @param is_predecessor Is @a source_peer looking for trail to a predecessor or not.
1001 * @param trail_id Unique identifier for the trail we are trying to setup.
1002 * @param intermediate_trail_id Trail id of intermediate trail to reach to
1003 * best_known_destination when its a finger. If not
1004 * used then set to 0.
1007 GDS_NEIGHBOURS_send_trail_setup (struct GNUNET_PeerIdentity source_peer,
1008 uint64_t ultimate_destination_finger_value,
1009 struct GNUNET_PeerIdentity best_known_destination,
1010 struct FriendInfo *target_friend,
1011 unsigned int trail_length,
1012 const struct GNUNET_PeerIdentity *trail_peer_list,
1013 unsigned int is_predecessor,
1014 struct GNUNET_HashCode trail_id,
1015 struct GNUNET_HashCode *intermediate_trail_id)
1017 struct P2PPendingMessage *pending;
1018 struct PeerTrailSetupMessage *tsm;
1019 struct GNUNET_PeerIdentity *peer_list;
1022 msize = sizeof (struct PeerTrailSetupMessage) +
1023 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1025 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1031 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1033 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1037 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1038 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1039 tsm = (struct PeerTrailSetupMessage *) &pending[1];
1040 pending->msg = &tsm->header;
1041 tsm->header.size = htons (msize);
1042 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP);
1043 tsm->final_destination_finger_value = GNUNET_htonll (ultimate_destination_finger_value);
1044 tsm->source_peer = source_peer;
1045 tsm->best_known_destination = best_known_destination;
1046 tsm->is_predecessor = htonl (is_predecessor);
1047 tsm->trail_id = trail_id;
1049 if (NULL == intermediate_trail_id)
1050 memset (&tsm->intermediate_trail_id, 0, sizeof (tsm->intermediate_trail_id));
1052 tsm->intermediate_trail_id = *intermediate_trail_id;
1054 if (trail_length > 0)
1056 peer_list = (struct GNUNET_PeerIdentity *) &tsm[1];
1057 memcpy (peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
1060 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1061 target_friend->pending_count++;
1062 process_friend_queue (target_friend);
1067 * Construct a trail setup result message and forward it to target friend.
1068 * @param querying_peer Peer which sent the trail setup request and should get
1070 * @param Finger Peer to which the trail has been setup to.
1071 * @param target_friend Friend to which this message should be forwarded.
1072 * @param trail_length Numbers of peers in the trail.
1073 * @param trail_peer_list Peers which are part of the trail from
1074 * querying_peer to Finger, NOT including them.
1075 * @param is_predecessor Is @a Finger predecessor to @a querying_peer ?
1076 * @param ultimate_destination_finger_value Value to which @a finger is the closest
1078 * @param trail_id Unique identifier of the trail.
1081 GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity querying_peer,
1082 struct GNUNET_PeerIdentity finger,
1083 struct FriendInfo *target_friend,
1084 unsigned int trail_length,
1085 const struct GNUNET_PeerIdentity *trail_peer_list,
1086 unsigned int is_predecessor,
1087 uint64_t ultimate_destination_finger_value,
1088 struct GNUNET_HashCode trail_id)
1090 struct P2PPendingMessage *pending;
1091 struct PeerTrailSetupResultMessage *tsrm;
1092 struct GNUNET_PeerIdentity *peer_list;
1095 msize = sizeof (struct PeerTrailSetupResultMessage) +
1096 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1098 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1104 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1106 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1110 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1111 pending->importance = 0;
1112 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1113 tsrm = (struct PeerTrailSetupResultMessage *) &pending[1];
1114 pending->msg = &tsrm->header;
1115 tsrm->header.size = htons (msize);
1116 tsrm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_RESULT);
1117 tsrm->querying_peer = querying_peer;
1118 tsrm->finger_identity = finger;
1119 tsrm->is_predecessor = htonl (is_predecessor);
1120 tsrm->trail_id = trail_id;
1121 tsrm->ulitmate_destination_finger_value =
1122 GNUNET_htonll (ultimate_destination_finger_value);
1123 peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1];
1124 if (trail_length > 0)
1126 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1128 /* Send the message to chosen friend. */
1129 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1130 target_friend->pending_count++;
1131 process_friend_queue (target_friend);
1136 * Send trail rejection message to target friend
1137 * @param source_peer Peer which is trying to setup the trail.
1138 * @param ultimate_destination_finger_value Peer closest to this value will be
1139 * @a source_peer's finger
1140 * @param congested_peer Peer which sent this message as it is congested.
1141 * @param is_predecessor Is source_peer looking for trail to a predecessor or not.
1142 * @param trail_peer_list Trails seen so far in trail setup before getting rejected
1143 * by congested_peer. This does NOT include @a source_peer
1144 * and congested_peer.
1145 * @param trail_length Total number of peers in trail_peer_list, NOT including
1146 * @a source_peer and @a congested_peer
1147 * @param trail_id Unique identifier of this trail.
1148 * @param congestion_timeout Duration given by congested peer as an estimate of
1149 * how long it may remain congested.
1152 GDS_NEIGHBOURS_send_trail_rejection (struct GNUNET_PeerIdentity source_peer,
1153 uint64_t ultimate_destination_finger_value,
1154 struct GNUNET_PeerIdentity congested_peer,
1155 unsigned int is_predecessor,
1156 const struct GNUNET_PeerIdentity *trail_peer_list,
1157 unsigned int trail_length,
1158 struct GNUNET_HashCode trail_id,
1159 struct FriendInfo *target_friend,
1160 const struct GNUNET_TIME_Relative congestion_timeout)
1162 struct PeerTrailRejectionMessage *trm;
1163 struct P2PPendingMessage *pending;
1164 struct GNUNET_PeerIdentity *peer_list;
1167 msize = sizeof (struct PeerTrailRejectionMessage) +
1168 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1170 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1176 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1178 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1182 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1183 pending->importance = 0;
1184 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1185 trm = (struct PeerTrailRejectionMessage *)&pending[1];
1186 pending->msg = &trm->header;
1187 trm->header.size = htons (msize);
1188 trm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_REJECTION);
1189 trm->source_peer = source_peer;
1190 trm->congested_peer = congested_peer;
1191 trm->congestion_time = congestion_timeout;
1192 trm->is_predecessor = htonl (is_predecessor);
1193 trm->trail_id = trail_id;
1194 trm->ultimate_destination_finger_value =
1195 GNUNET_htonll (ultimate_destination_finger_value);
1197 peer_list = (struct GNUNET_PeerIdentity *) &trm[1];
1198 if (trail_length > 0)
1200 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1203 /* Send the message to chosen friend. */
1204 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1205 target_friend->pending_count++;
1206 process_friend_queue (target_friend);
1211 * Construct a verify successor message and forward it to target_friend.
1212 * @param source_peer Peer which wants to verify its successor.
1213 * @param successor Peer which is @a source_peer's current successor.
1214 * @param trail_id Unique Identifier of trail from @a source_peer to @a successor,
1215 * NOT including them.
1216 * @param trail List of peers which are part of trail to reach from @a source_peer
1217 * to @a successor, NOT including them.
1218 * @param trail_length Total number of peers in @a trail.
1219 * @param target_friend Next friend to get this message.
1222 GDS_NEIGHBOURS_send_verify_successor_message (struct GNUNET_PeerIdentity source_peer,
1223 struct GNUNET_PeerIdentity successor,
1224 struct GNUNET_HashCode trail_id,
1225 struct GNUNET_PeerIdentity *trail,
1226 unsigned int trail_length,
1227 struct FriendInfo *target_friend)
1229 struct PeerVerifySuccessorMessage *vsm;
1230 struct P2PPendingMessage *pending;
1231 struct GNUNET_PeerIdentity *peer_list;
1234 msize = sizeof (struct PeerVerifySuccessorMessage);
1235 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1241 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1243 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1247 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1248 pending->importance = 0; /* FIXME */
1249 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1250 vsm = (struct PeerVerifySuccessorMessage *) &pending[1];
1251 pending->msg = &vsm->header;
1252 vsm->header.size = htons (msize);
1253 vsm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR);
1254 vsm->source_peer = source_peer;
1255 vsm->successor = successor;
1256 vsm->trail_id = trail_id;
1258 if (trail_length > 0)
1260 peer_list = (struct GNUNET_PeerIdentity *) &vsm[1];
1261 memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
1264 /* Send the message to chosen friend. */
1265 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1266 target_friend->pending_count++;
1267 process_friend_queue (target_friend);
1272 * FIXME: In every function we pass target friend except for this one.
1273 * so, either change everything or this one. also, should se just store
1274 * the pointer to friend in routing table rather than gnunet_peeridentity.
1275 * if yes then we should keep friend info in.h andmake lot of changes.
1276 * Construct a trail teardown message and forward it to target friend.
1277 * @param trail_id Unique identifier of the trail.
1278 * @param trail_direction Direction of trail.
1279 * @param target_friend Friend to get this message.
1282 GDS_NEIGHBOURS_send_trail_teardown (struct GNUNET_HashCode trail_id,
1283 unsigned int trail_direction,
1284 struct GNUNET_PeerIdentity peer)
1286 struct PeerTrailTearDownMessage *ttdm;
1287 struct P2PPendingMessage *pending;
1288 struct FriendInfo *target_friend;
1291 msize = sizeof (struct PeerTrailTearDownMessage);
1293 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1299 GNUNET_assert (NULL != (target_friend =
1300 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &peer)));
1302 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1304 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1308 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1309 pending->importance = 0; /* FIXME */
1310 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1311 ttdm = (struct PeerTrailTearDownMessage *) &pending[1];
1312 pending->msg = &ttdm->header;
1313 ttdm->header.size = htons (msize);
1314 ttdm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN);
1315 ttdm->trail_id = trail_id;
1316 ttdm->trail_direction = htonl (trail_direction);
1318 /* Send the message to chosen friend. */
1319 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1320 target_friend->pending_count++;
1321 process_friend_queue (target_friend);
1326 * Construct a verify successor result message and send it to target_friend
1327 * @param querying_peer Peer which sent the verify successor message.
1328 * @param source_successor Current_successor of @a querying_peer.
1329 * @param current_predecessor Current predecessor of @a successor. Could be same
1330 * or different from @a querying_peer.
1331 * @param trail_id Unique identifier of the trail from @a querying_peer to
1332 * @a successor, NOT including them.
1333 * @param trail List of peers which are part of trail from @a querying_peer to
1334 * @a successor, NOT including them.
1335 * @param trail_length Total number of peers in @a trail
1336 * @param trail_direction Direction in which we are sending the message. In this
1337 * case we are sending result from @a successor to @a querying_peer.
1338 * @param target_friend Next friend to get this message.
1341 GDS_NEIGHBOURS_send_verify_successor_result (struct GNUNET_PeerIdentity querying_peer,
1342 struct GNUNET_PeerIdentity current_successor,
1343 struct GNUNET_PeerIdentity probable_successor,
1344 struct GNUNET_HashCode trail_id,
1345 const struct GNUNET_PeerIdentity *trail,
1346 unsigned int trail_length,
1347 enum GDS_ROUTING_trail_direction trail_direction,
1348 struct FriendInfo *target_friend)
1350 struct PeerVerifySuccessorResultMessage *vsmr;
1351 struct P2PPendingMessage *pending;
1352 struct GNUNET_PeerIdentity *peer_list;
1355 msize = sizeof (struct PeerVerifySuccessorResultMessage) +
1356 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1358 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1364 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1366 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1370 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1371 pending->importance = 0; /* FIXME */
1372 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1373 vsmr = (struct PeerVerifySuccessorResultMessage *) &pending[1];
1374 pending->msg = &vsmr->header;
1375 vsmr->header.size = htons (msize);
1376 vsmr->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR_RESULT);
1377 vsmr->querying_peer = querying_peer;
1378 vsmr->current_successor = current_successor;
1379 vsmr->probable_successor = probable_successor;
1380 vsmr->trail_direction = htonl (trail_direction);
1381 vsmr->trail_id = trail_id;
1383 if (trail_length > 0)
1385 peer_list = (struct GNUNET_PeerIdentity *) &vsmr[1];
1386 memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
1389 /* Send the message to chosen friend. */
1390 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1391 target_friend->pending_count++;
1392 process_friend_queue (target_friend);
1397 * Construct a notify new successor message and send it to target_friend
1398 * @param source_peer Peer which wants to notify to its new successor that it
1399 * could be its predecessor.
1400 * @param successor New successor of @a source_peer
1401 * @param successor_trail List of peers in Trail to reach from
1402 * @a source_peer to @a new_successor, NOT including
1404 * @param successor_trail_length Total number of peers in @a new_successor_trail.
1405 * @param successor_trail_id Unique identifier of @a new_successor_trail.
1406 * @param target_friend Next friend to get this message.
1409 GDS_NEIGHBOURS_send_notify_new_successor (struct GNUNET_PeerIdentity source_peer,
1410 struct GNUNET_PeerIdentity successor,
1411 const struct GNUNET_PeerIdentity *successor_trail,
1412 unsigned int successor_trail_length,
1413 struct GNUNET_HashCode succesor_trail_id,
1414 struct FriendInfo *target_friend)
1416 struct PeerNotifyNewSuccessorMessage *nsm;
1417 struct P2PPendingMessage *pending;
1418 struct GNUNET_PeerIdentity *peer_list;
1421 msize = sizeof (struct PeerNotifyNewSuccessorMessage) +
1422 (successor_trail_length * sizeof(struct GNUNET_PeerIdentity));
1424 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1430 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1432 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1436 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1437 pending->importance = 0; /* FIXME */
1438 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1439 nsm = (struct PeerNotifyNewSuccessorMessage *) &pending[1];
1440 pending->msg = &nsm->header;
1441 nsm->header.size = htons (msize);
1442 nsm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_NEW_SUCCESSOR);
1443 nsm->new_successor = successor;
1444 nsm->source_peer = source_peer;
1445 nsm->trail_id = succesor_trail_id;
1447 if (successor_trail_length > 0)
1449 peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
1450 memcpy (peer_list, successor_trail,
1451 successor_trail_length * sizeof (struct GNUNET_PeerIdentity));
1454 /* Send the message to chosen friend. */
1455 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1456 target_friend->pending_count++;
1457 process_friend_queue (target_friend);
1462 * Construct an add_trail message and send it to target_friend
1463 * @param source_peer Source of the trail.
1464 * @param destination_peer Destination of the trail.
1465 * @param trail_id Unique identifier of the trail from
1466 * @a source_peer to @a destination_peer, NOT including the endpoints.
1467 * @param trail List of peers in Trail from @a source_peer to @a destination_peer,
1468 * NOT including the endpoints.
1469 * @param trail_length Total number of peers in @a trail.
1470 * @param target_friend Next friend to get this message.
1473 GDS_NEIGHBOURS_send_add_trail (struct GNUNET_PeerIdentity source_peer,
1474 struct GNUNET_PeerIdentity destination_peer,
1475 struct GNUNET_HashCode trail_id,
1476 const struct GNUNET_PeerIdentity *trail,
1477 unsigned int trail_length,
1478 struct FriendInfo *target_friend)
1480 struct PeerAddTrailMessage *adm;
1481 struct GNUNET_PeerIdentity *peer_list;
1482 struct P2PPendingMessage *pending;
1485 msize = sizeof (struct PeerAddTrailMessage) +
1486 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1488 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1494 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1496 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1500 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1501 pending->importance = 0; /* FIXME */
1502 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1503 adm = (struct PeerAddTrailMessage *) &pending[1];
1504 pending->msg = &adm->header;
1505 adm->header.size = htons (msize);
1506 adm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_ADD_TRAIL);
1507 adm->source_peer = source_peer;
1508 adm->destination_peer = destination_peer;
1509 adm->trail_id = trail_id;
1511 if (trail_length > 0)
1513 peer_list = (struct GNUNET_PeerIdentity *)&adm[1];
1514 memcpy (peer_list, trail, sizeof (struct GNUNET_PeerIdentity) * trail_length);
1516 /* Send the message to chosen friend. */
1517 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1518 target_friend->pending_count++;
1519 process_friend_queue (target_friend);
1525 * Construct a trail compression message and send it to target_friend.
1526 * @param source_peer Source of the trail.
1527 * @param trail_id Unique identifier of trail.
1528 * @param first_friend First hop in compressed trail to reach from source to finger
1529 * @param target_friend Next friend to get this message.
1532 GDS_NEIGHBOURS_send_trail_compression (struct GNUNET_PeerIdentity source_peer,
1533 struct GNUNET_HashCode trail_id,
1534 struct GNUNET_PeerIdentity first_friend,
1535 struct FriendInfo *target_friend)
1537 struct P2PPendingMessage *pending;
1538 struct PeerTrailCompressionMessage *tcm;
1541 msize = sizeof (struct PeerTrailCompressionMessage);
1543 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1549 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1551 GNUNET_STATISTICS_update (GDS_stats,
1552 gettext_noop ("# P2P messages dropped due to full queue"),
1556 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1557 pending->importance = 0; /* FIXME */
1558 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1559 tcm = (struct PeerTrailCompressionMessage *) &pending[1];
1560 pending->msg = &tcm->header;
1561 tcm->header.size = htons (msize);
1562 tcm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_COMPRESSION);
1563 tcm->source_peer = source_peer;
1564 tcm->new_first_friend = first_friend;
1565 tcm->trail_id = trail_id;
1567 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1568 target_friend->pending_count++;
1569 process_friend_queue (target_friend);
1575 * Search my location in trail.
1576 * @param trail List of peers
1577 * @return my_index if found
1578 * -1 if no entry found.
1581 search_my_index (const struct GNUNET_PeerIdentity *trail,
1586 for (i = 0; i < trail_length; i++)
1588 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &trail[i]))
1597 * Check if the friend is congested or have reached maximum number of trails
1598 * it can be part of of.
1599 * @param friend Friend to be checked.
1600 * @return #GNUNET_YES if friend is not congested or have not crossed threshold.
1601 * #GNUNET_NO if friend is either congested or have crossed threshold
1604 is_friend_congested (struct FriendInfo *friend)
1606 if ((friend->trails_count < TRAILS_THROUGH_FRIEND_THRESHOLD) &&
1607 ((0 == GNUNET_TIME_absolute_get_remaining
1608 (friend->congestion_timestamp).rel_value_us)))
1616 * FIXME; not handling the wrap around logic correctly.
1617 * Select closest finger to value.
1618 * @param peer1 First peer
1619 * @param peer2 Second peer
1620 * @param value Value to be compare
1621 * @return Closest peer
1623 static struct GNUNET_PeerIdentity *
1624 select_closest_finger (struct GNUNET_PeerIdentity *peer1,
1625 struct GNUNET_PeerIdentity *peer2,
1628 uint64_t peer1_value;
1629 uint64_t peer2_value;
1631 memcpy (&peer1_value, peer1, sizeof (uint64_t));
1632 memcpy (&peer2_value, peer2, sizeof (uint64_t));
1633 peer1_value = GNUNET_ntohll (peer1_value);
1634 peer2_value = GNUNET_ntohll (peer2_value);
1635 //value = GNUNET_ntohll (value); //FIXME: Is it correct to do it here?
1637 if (peer1_value == value)
1642 if (peer2_value == value)
1647 if (peer2_value < peer1_value)
1649 if ((peer2_value < value) && (value < peer1_value))
1653 else if (((peer1_value < value) && (value < PEER_IDENTITES_WRAP_AROUND)) ||
1654 ((0 < value) && (value < peer2_value)))
1660 if (peer1_value < peer2_value)
1662 if ((peer1_value < value) && (value < peer2_value))
1666 else if (((peer2_value < value) && (value < PEER_IDENTITES_WRAP_AROUND)) ||
1667 ((0 < value) && (value < peer1_value)))
1677 * Select closest predecessor to value.
1678 * @param peer1 First peer
1679 * @param peer2 Second peer
1680 * @param value Value to be compare
1681 * @return Peer which precedes value in the network.
1683 static struct GNUNET_PeerIdentity *
1684 select_closest_predecessor (struct GNUNET_PeerIdentity *peer1,
1685 struct GNUNET_PeerIdentity *peer2,
1688 uint64_t peer1_value;
1689 uint64_t peer2_value;
1691 memcpy (&peer1_value, peer1, sizeof (uint64_t));
1692 memcpy (&peer2_value, peer2, sizeof (uint64_t));
1693 peer1_value = GNUNET_ntohll (peer1_value);
1694 peer2_value = GNUNET_ntohll (peer2_value);
1696 if (peer1_value == value)
1699 if (peer2_value == value)
1702 if (peer1_value < peer2_value)
1704 if ((peer1_value < value) && (value < peer2_value))
1706 else if (((peer2_value < value) && (value < PEER_IDENTITES_WRAP_AROUND)) ||
1707 ((PEER_IDENTITES_WRAP_AROUND > value) && (value < peer1_value)))
1711 if (peer2_value < peer1_value)
1713 if ((peer2_value < value) && (value < peer1_value))
1715 else if (((peer1_value < value) && (value < PEER_IDENTITES_WRAP_AROUND)) ||
1716 ((PEER_IDENTITES_WRAP_AROUND > value) && (value < peer2_value)))
1724 * Select the closest peer among two peers (which should not be same)
1725 * with respect to value and finger_table_index
1726 * NOTE: peer1 != peer2
1727 * @param peer1 First peer
1728 * @param peer2 Second peer
1729 * @param value Value relative to which we find the closest
1730 * @param is_predecessor Is value a predecessor or any other finger.
1731 * @return Closest peer among two peers.
1733 static struct GNUNET_PeerIdentity *
1734 select_closest_peer (struct GNUNET_PeerIdentity *peer1,
1735 struct GNUNET_PeerIdentity *peer2,
1737 unsigned int is_predecessor)
1739 struct GNUNET_PeerIdentity *closest_peer;
1741 if (1 == is_predecessor)
1742 closest_peer = select_closest_predecessor (peer1, peer2, value);
1744 closest_peer = select_closest_finger (peer1, peer2, value);
1746 return closest_peer;
1751 * Iterate over the list of all the trails of a finger. In case the first
1752 * friend to reach the finger has reached trail threshold or is congested,
1753 * then don't select it. In case there multiple available good trails to reach
1754 * to Finger, choose the one with shortest trail length.
1755 * Note: We use length as parameter. But we can use any other suitable parameter
1757 * @param finger Finger
1758 * @return struct Selected_Finger_Trail which contains the first friend , trail id
1759 * and trail length. NULL in case none of the trails are free.
1761 static struct Selected_Finger_Trail *
1762 select_finger_trail (struct FingerInfo *finger)
1764 struct FriendInfo *friend;
1765 struct Trail *iterator;
1766 struct Selected_Finger_Trail *finger_trail;
1768 unsigned int flag = 0;
1771 finger_trail = GNUNET_new (struct Selected_Finger_Trail);
1773 /* It can never happen that we have a finger (which is not a friend or my identity),
1774 and we don't have a trail to reach to it. */
1775 GNUNET_assert (finger->trails_count > 0);
1777 for (i = 0; i < finger->trails_count; i++)
1779 iterator = &finger->trail_list[i];
1781 /* No trail stored at this index. */
1782 if (GNUNET_NO == iterator->is_present)
1787 GNUNET_assert (NULL !=
1789 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1790 &iterator->trail_head->peer)));
1792 /* First friend to reach trail is not free. */
1793 if (GNUNET_YES == is_friend_congested (friend))
1798 /* This is the first time we enter the loop. Set finger trail length to
1799 * trail length of this trail. */
1803 finger_trail->trail_length = iterator->trail_length;
1804 finger_trail->friend = *friend;
1805 finger_trail->trail_id = &iterator->trail_id;
1806 //memcmp (finger_trail->trail_id, &iterator->trail_id, sizeof (struct GNUNET_HashCode));
1808 else if (finger_trail->trail_length > iterator->trail_length)
1810 /* Check if the trail length of this trail is least seen so far. If yes then
1811 set finger_trail to this trail.*/
1812 finger_trail->friend = *friend;
1813 finger_trail->trail_id = &iterator->trail_id;
1814 //memcmp (finger_trail->trail_id, &iterator->trail_id, sizeof (struct GNUNET_HashCode));
1815 finger_trail->trail_length = iterator->trail_length;
1819 /* All the first friend in all the trails to reach to finger are either
1820 congested or have crossed trail threshold. */
1821 if (j == finger->trails_count)
1824 return finger_trail;
1829 * This is a test function, to print all the entries of finger table.
1832 test_finger_table_print()
1834 struct FingerInfo *finger;
1835 struct GNUNET_PeerIdentity print_peer;
1836 struct Trail *trail;
1841 FPRINTF (stderr,_("\nSUPU************ FINGER_TABLE"));
1842 for (i = 0; i < MAX_FINGERS; i++)
1844 finger = &finger_table[i];
1846 if (GNUNET_NO == finger->is_present)
1849 print_peer = finger->finger_identity;
1850 FPRINTF (stderr,_("\nSUPU %s, %s, %d, finger_table[%d] = %s, trails_count = %d"),
1851 __FILE__, __func__,__LINE__,i,GNUNET_i2s (&print_peer), finger->trails_count);
1854 for (j = 0; j < finger->trails_count; j++)
1856 trail = &finger->trail_list[j];
1857 FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail_id[%d]=%s"),__FILE__, __func__,__LINE__,j, GNUNET_h2s(&trail->trail_id));
1858 struct Trail_Element *element;
1859 element = trail->trail_head;
1860 for (k = 0; k < trail->trail_length; k++)
1862 print_peer = element->peer;
1863 FPRINTF (stderr,_("\nSUPU %s, %s, %d,trail[%d] = %s "),__FILE__, __func__,__LINE__,k, GNUNET_i2s(&print_peer));
1864 element = element->next;
1872 * Compare FINGER entry with current successor. If finger's first friend of all
1873 * its trail is not congested and has not crossed trail threshold, then check
1874 * if finger peer identity is closer to final_destination_finger_value than
1875 * current_successor. If yes then update current_successor.
1876 * @param current_successor[in/out]
1880 compare_finger_and_current_successor (struct Closest_Peer *current_closest_peer)
1882 struct FingerInfo *finger;
1883 struct GNUNET_PeerIdentity *closest_peer;
1884 struct Selected_Finger_Trail *finger_trail;
1887 /* Iterate over finger table. */
1888 for (i = 0; i < MAX_FINGERS; i++)
1890 finger = &finger_table[i];
1892 /* No valid entry at this index, go to next element.*/
1893 if (GNUNET_NO == finger->is_present)
1896 /* If my identity is same as current closest peer then don't consider me*/
1898 GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
1899 ¤t_closest_peer->best_known_destination))
1902 /* If I am my own finger, then ignore this finger. */
1903 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
1907 /* If finger is a friend, then do nothing. As we have already checked
1908 * for each friend in compare_friend_and_current_successor(). */
1909 if (NULL != (GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1910 &finger->finger_identity)))
1914 /* We have a finger which not a friend, not my identity */
1915 /* Choose one of the trail to reach to finger. */
1916 finger_trail = select_finger_trail (finger);
1918 /* In case no trail found, ignore this finger. */
1919 if (NULL == finger_trail)
1922 closest_peer = select_closest_peer (&finger->finger_identity,
1923 ¤t_closest_peer->best_known_destination,
1924 current_closest_peer->destination_finger_value,
1925 current_closest_peer->is_predecessor);
1927 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
1930 current_closest_peer->best_known_destination = finger->finger_identity;
1931 current_closest_peer->next_hop = finger_trail->friend.id;
1932 current_closest_peer->trail_id = finger_trail->trail_id;
1940 * Compare friend entry with current successor.
1941 * If friend identity and current_successor is same, then do nothing.
1942 * If friend is not congested and has not crossed trail threshold, then check
1943 * if friend peer identity is closer to final_destination_finger_value than
1944 * current_successor. If yes then update current_successor.
1945 * @param cls closure
1946 * @param key current public key
1947 * @param value struct Closest_Peer
1948 * @return #GNUNET_YES if we should continue to iterate,
1949 * #GNUNET_NO if not.
1952 compare_friend_and_current_closest_peer (void *cls,
1953 const struct GNUNET_PeerIdentity *key,
1956 struct FriendInfo *friend = value;
1957 struct Closest_Peer *current_closest_peer = cls;
1958 struct GNUNET_PeerIdentity *closest_peer;
1960 /* If friend is either congested or has crossed threshold, then don't consider
1962 if (GNUNET_YES == is_friend_congested (friend))
1965 /* If current_closest_peer and friend identity are same, then do nothing.*/
1967 GNUNET_CRYPTO_cmp_peer_identity (&friend->id,
1968 ¤t_closest_peer->best_known_destination))
1971 closest_peer = select_closest_peer (&friend->id,
1972 ¤t_closest_peer->best_known_destination,
1973 current_closest_peer->destination_finger_value,
1974 current_closest_peer->is_predecessor);
1976 /* Is friend the closest successor? */
1977 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&friend->id, closest_peer))
1979 current_closest_peer->best_known_destination = friend->id;
1980 current_closest_peer->next_hop = friend->id;
1988 * Initialize current_successor to my_identity.
1989 * @param my_identity My peer identity
1990 * @return current_successor
1992 static struct Closest_Peer *
1993 init_current_successor (struct GNUNET_PeerIdentity my_identity,
1994 uint64_t destination_finger_value,
1995 unsigned int is_predecessor)
1997 struct Closest_Peer *current_closest_peer;
1999 current_closest_peer = GNUNET_new (struct Closest_Peer);
2000 //memset (¤t_closest_peer->trail_id, 0, sizeof (current_closest_peer->trail_id));
2001 current_closest_peer->trail_id = NULL;
2002 current_closest_peer->destination_finger_value = destination_finger_value;
2003 current_closest_peer->is_predecessor = is_predecessor;
2004 current_closest_peer->next_hop = my_identity;
2005 current_closest_peer->best_known_destination = my_identity;
2007 return current_closest_peer;
2012 * Find the successor for destination_finger_value among my_identity, all my
2013 * friend and all my fingers. Don't consider friends or fingers which are either
2014 * congested or have crossed the threshold.
2015 * NOTE: In case a friend is also a finger, then it is always chosen as friend
2017 * @param destination_finger_value Peer closest to this value will be the next successor.
2018 * @param local_best_known_destination[out] Updated to my_identity if I am the
2019 * final destination. Updated to friend
2020 * identity in case a friend is successor,
2021 * updated to finger in case finger is the
2023 * @param new_intermediate_trail_id[out] In case a finger is the
2024 * @a local_best_known_destination,
2025 * then it is the trail to reach it. Else
2027 * @param is_predecessor Are we looking for predecessor or finger?
2028 * @return Next hop to reach to local_best_known_destination. In case my_identity
2029 * or a friend is a local_best_known_destination, then
2030 * next_hop = local_best_known_destination. Else
2031 * next_hop is the first friend to reach to finger (local_best_known_destination)
2033 static struct GNUNET_PeerIdentity *
2034 find_successor (uint64_t destination_finger_value,
2035 struct GNUNET_PeerIdentity *local_best_known_destination,
2036 struct GNUNET_HashCode *new_intermediate_trail_id,
2037 unsigned int is_predecessor)
2039 struct Closest_Peer *current_closest_peer;
2040 struct GNUNET_PeerIdentity *next_hop;
2042 /* Initialize current_successor to my_identity. */
2043 current_closest_peer = init_current_successor (my_identity,
2044 destination_finger_value,
2046 /* Compare each friend entry with current_successor and update current_successor
2047 * with friend if its closest. */
2050 GNUNET_CONTAINER_multipeermap_iterate (friend_peermap,
2051 &compare_friend_and_current_closest_peer,
2052 current_closest_peer));
2054 /* Compare each finger entry with current_successor and update current_successor
2055 * with finger if its closest. */
2056 compare_finger_and_current_successor (current_closest_peer);
2057 *local_best_known_destination = current_closest_peer->best_known_destination;
2058 if (current_closest_peer->trail_id != NULL)
2059 *new_intermediate_trail_id = *current_closest_peer->trail_id;
2060 next_hop = GNUNET_new (struct GNUNET_PeerIdentity);
2061 *next_hop = current_closest_peer->next_hop;
2067 * Construct a Put message and send it to target_peer.
2068 * @param key Key for the content
2069 * @param block_type Type of the block
2070 * @param options Routing options
2071 * @param desired_replication_level Desired replication count
2072 * @param best_known_dest Peer to which this message should reach eventually,
2073 * as it is best known destination to me.
2074 * @param intermediate_trail_id Trail id in case
2075 * @param target_peer Peer to which this message will be forwarded.
2076 * @param hop_count Number of hops traversed so far.
2077 * @param put_path_length Total number of peers in @a put_path
2078 * @param put_path Number of peers traversed so far
2079 * @param expiration_time When does the content expire
2080 * @param data Content to store
2081 * @param data_size Size of content @a data in bytes
2084 GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key,
2085 enum GNUNET_BLOCK_Type block_type,
2086 enum GNUNET_DHT_RouteOption options,
2087 uint32_t desired_replication_level,
2088 struct GNUNET_PeerIdentity *best_known_dest,
2089 struct GNUNET_HashCode *intermediate_trail_id,
2090 struct GNUNET_PeerIdentity *target_peer,
2092 uint32_t put_path_length,
2093 struct GNUNET_PeerIdentity *put_path,
2094 struct GNUNET_TIME_Absolute expiration_time,
2095 const void *data, size_t data_size)
2097 struct PeerPutMessage *ppm;
2098 struct P2PPendingMessage *pending;
2099 struct FriendInfo *target_friend;
2100 struct GNUNET_PeerIdentity *pp;
2101 struct GNUNET_PeerIdentity local_best_known_dest;
2104 msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
2105 sizeof (struct PeerPutMessage);
2107 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2109 put_path_length = 0;
2110 msize = data_size + sizeof (struct PeerPutMessage);
2113 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2119 /* This is the first call made from clients file. So, we should search for the
2121 if (NULL == target_peer)
2124 struct GNUNET_PeerIdentity *next_hop;
2126 memcpy (&key_value, key, sizeof (uint64_t));
2127 key_value = GNUNET_ntohll (key_value);
2129 next_hop = find_successor (key_value, &local_best_known_dest,
2130 intermediate_trail_id, GDS_FINGER_TYPE_NON_PREDECESSOR);
2131 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&local_best_known_dest, &my_identity))
2133 /* I am the destination but we have already done datacache_put in client file. */
2137 GNUNET_assert (NULL !=
2138 (target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop)));
2139 GNUNET_free (next_hop);
2143 GNUNET_assert (NULL !=
2145 GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer)));
2147 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2148 pending->timeout = expiration_time;
2149 ppm = (struct PeerPutMessage *) &pending[1];
2150 pending->msg = &ppm->header;
2151 ppm->header.size = htons (msize);
2152 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_PUT);
2153 ppm->options = htonl (options);
2154 ppm->block_type = htonl (block_type);
2155 ppm->hop_count = htonl (hop_count + 1);
2156 ppm->desired_replication_level = htonl (desired_replication_level);
2157 ppm->put_path_length = htonl (put_path_length);
2158 ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
2159 if (NULL == best_known_dest)
2160 ppm->best_known_destination = local_best_known_dest;
2162 ppm->best_known_destination = *best_known_dest;
2164 if (NULL == intermediate_trail_id)
2165 memset (&ppm->intermediate_trail_id, 0, sizeof (ppm->intermediate_trail_id));
2167 ppm->intermediate_trail_id = *intermediate_trail_id;
2168 pp = (struct GNUNET_PeerIdentity *) &ppm[1];
2169 if (put_path_length != 0)
2171 memcpy (pp, put_path,
2172 sizeof (struct GNUNET_PeerIdentity) * put_path_length);
2174 memcpy (&pp[put_path_length], data, data_size);
2176 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2177 target_friend->pending_count++;
2178 process_friend_queue (target_friend);
2183 * Construct a Get message and send it to target_peer.
2184 * @param key Key for the content
2185 * @param block_type Type of the block
2186 * @param options Routing options
2187 * @param desired_replication_level Desired replication count
2188 * @param best_known_dest Peer which should get this message. Same as target peer
2189 * if best_known_dest is a friend else its a finger.
2190 * @param intermediate_trail_id Trail id to reach to @a best_known_dest
2191 * in case it is a finger else set to 0.
2192 * @param target_peer Peer to which this message will be forwarded.
2193 * @param hop_count Number of hops traversed so far.
2194 * @param data Content to store
2195 * @param data_size Size of content @a data in bytes
2196 * @param get_path_length Total number of peers in @a get_path
2197 * @param get_path Number of peers traversed so far
2200 GDS_NEIGHBOURS_send_get (const struct GNUNET_HashCode *key,
2201 enum GNUNET_BLOCK_Type block_type,
2202 enum GNUNET_DHT_RouteOption options,
2203 uint32_t desired_replication_level,
2204 const struct GNUNET_PeerIdentity *best_known_dest,
2205 struct GNUNET_HashCode *intermediate_trail_id,
2206 struct GNUNET_PeerIdentity *target_peer,
2208 uint32_t get_path_length,
2209 struct GNUNET_PeerIdentity *get_path)
2211 struct PeerGetMessage *pgm;
2212 struct P2PPendingMessage *pending;
2213 struct FriendInfo *target_friend;
2214 struct GNUNET_PeerIdentity local_best_known_dest;
2215 struct GNUNET_PeerIdentity *gp;
2218 msize = sizeof (struct PeerGetMessage) +
2219 (get_path_length * sizeof (struct GNUNET_PeerIdentity));
2221 /* In this case we don't make get_path_length = 0, as we need get path to
2222 * return the message back to querying client. */
2223 if (msize > GNUNET_SERVER_MAX_MESSAGE_SIZE)
2228 /* This is the first time we got request from our own client file. */
2229 if (NULL == target_peer)
2231 struct GNUNET_PeerIdentity *next_hop;
2234 memcpy (&key_value, key, sizeof (uint64_t));
2235 key_value = GNUNET_ntohll (key_value);
2237 /* Find the next destination to forward the packet. */
2238 next_hop = find_successor (key_value, &local_best_known_dest,
2239 intermediate_trail_id, GDS_FINGER_TYPE_NON_PREDECESSOR);
2241 /* I am the destination. I have the data. */
2242 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
2243 &local_best_known_dest))
2245 GDS_DATACACHE_handle_get (key,block_type, NULL, 0,
2246 NULL, 0, 1, &my_identity, NULL,&my_identity);
2252 GNUNET_assert (NULL !=
2254 GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop)));
2256 GNUNET_free (next_hop);
2260 local_best_known_dest = *best_known_dest;
2261 GNUNET_assert (NULL !=
2263 GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer)));
2266 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2267 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
2268 pending->importance = 0; /* FIXME */
2269 pgm = (struct PeerGetMessage *) &pending[1];
2270 pending->msg = &pgm->header;
2271 pgm->header.size = htons (msize);
2272 pgm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_GET);
2273 pgm->get_path_length = htonl (get_path_length);
2274 pgm->best_known_destination = local_best_known_dest;
2277 if (NULL == intermediate_trail_id)
2278 memset ((void *)&pgm->intermediate_trail_id, 0, sizeof (pgm->intermediate_trail_id));
2280 pgm->intermediate_trail_id = *intermediate_trail_id;
2281 pgm->hop_count = htonl (hop_count + 1);
2282 gp = (struct GNUNET_PeerIdentity *) &pgm[1];
2284 if (get_path_length != 0)
2286 memcpy (gp, get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity));
2289 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2290 target_friend->pending_count++;
2291 process_friend_queue (target_friend);
2296 * Send the get result to requesting client.
2297 * @param key Key of the requested data.
2298 * @param type Block type
2299 * @param target_peer Next peer to forward the message to.
2300 * @param source_peer Peer which has the data for the key.
2301 * @param put_path_length Number of peers in @a put_path
2302 * @param put_path Path taken to put the data at its stored location.
2303 * @param get_path_length Number of peers in @a get_path
2304 * @param get_path Path taken to reach to the location of the key.
2305 * @param expiration When will this result expire?
2306 * @param data Payload to store
2307 * @param data_size Size of the @a data
2310 GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key,
2311 enum GNUNET_BLOCK_Type type,
2312 const struct GNUNET_PeerIdentity *target_peer,
2313 const struct GNUNET_PeerIdentity *source_peer,
2314 unsigned int put_path_length,
2315 const struct GNUNET_PeerIdentity *put_path,
2316 unsigned int get_path_length,
2317 const struct GNUNET_PeerIdentity *get_path,
2318 struct GNUNET_TIME_Absolute expiration,
2319 const void *data, size_t data_size)
2321 struct PeerGetResultMessage *get_result;
2322 struct GNUNET_PeerIdentity *paths;
2323 struct P2PPendingMessage *pending;
2324 struct FriendInfo *target_friend;
2325 int current_path_index;
2328 msize = (put_path_length + get_path_length )* sizeof (struct GNUNET_PeerIdentity) +
2330 sizeof (struct PeerGetResultMessage);
2332 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2338 current_path_index = 0;
2339 if(get_path_length > 0)
2341 current_path_index = search_my_index(get_path, get_path_length);
2342 if (-1 == current_path_index)
2348 if (0 == current_path_index)
2350 GDS_CLIENTS_handle_reply (expiration, key, get_path_length,
2351 get_path, put_path_length,
2352 put_path, type, data_size, data);
2356 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2357 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
2358 pending->importance = 0;
2359 get_result = (struct PeerGetResultMessage *)&pending[1];
2360 pending->msg = &get_result->header;
2361 get_result->header.size = htons (msize);
2362 get_result->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_GET_RESULT);
2363 get_result->key = *key;
2364 get_result->querying_peer = *source_peer;
2365 get_result->expiration_time = expiration;
2366 get_result->get_path_length = htonl (get_path_length);
2367 get_result->put_path_length = htonl (put_path_length);
2368 paths = (struct GNUNET_PeerIdentity *)&get_result[1];
2369 memcpy (paths, put_path,
2370 put_path_length * sizeof (struct GNUNET_PeerIdentity));
2371 memcpy (&paths[put_path_length], get_path,
2372 get_path_length * sizeof (struct GNUNET_PeerIdentity));
2373 memcpy (&paths[put_path_length + get_path_length], data, data_size);
2375 GNUNET_assert (NULL !=
2377 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2378 &get_path[current_path_index - 1])));
2379 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2380 target_friend->pending_count++;
2381 process_friend_queue (target_friend);
2386 * Randomly choose one of your friends (which is not congested and have not crossed
2387 * trail threshold) from the friends_peer map
2388 * @return Friend Randomly chosen friend.
2389 * NULL in case friend peermap is empty, or all the friends are either
2390 * congested or have crossed trail threshold.
2392 static struct FriendInfo *
2393 select_random_friend ()
2395 unsigned int current_size;
2398 struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
2399 struct GNUNET_PeerIdentity key_ret;
2400 struct FriendInfo *friend;
2402 current_size = GNUNET_CONTAINER_multipeermap_size (friend_peermap);
2405 if (0 == current_size)
2408 index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, current_size);
2409 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
2411 /* Iterate till you don't reach to index. */
2412 for (j = 0; j < index ; j++)
2413 GNUNET_assert (GNUNET_YES ==
2414 GNUNET_CONTAINER_multipeermap_iterator_next (iter, NULL, NULL));
2417 /* Reset the index in friend peermap to 0 as we reached to the end. */
2418 if (j == current_size)
2421 GNUNET_CONTAINER_multipeermap_iterator_destroy (iter);
2422 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
2426 /* Get the friend stored at the index, j*/
2427 GNUNET_assert (GNUNET_YES ==
2428 GNUNET_CONTAINER_multipeermap_iterator_next (iter,
2430 (const void **)&friend));
2432 /* This friend is not congested and has not crossed trail threshold. */
2433 if ((TRAILS_THROUGH_FRIEND_THRESHOLD > friend->trails_count) &&
2434 (0 == GNUNET_TIME_absolute_get_remaining (friend->congestion_timestamp).rel_value_us))
2440 } while (j != index);
2442 GNUNET_CONTAINER_multipeermap_iterator_destroy (iter);
2448 * Compute 64 bit value of finger_identity corresponding to a finger index using
2451 * n.finger[i] = n + pow (2,i),
2453 * n.finger[i] = n - 1, where
2456 * n.finger[i] = 64 bit finger value
2457 * @param finger_index Index corresponding to which we calculate 64 bit value.
2458 * @return 64 bit value.
2461 compute_finger_identity_value (unsigned int finger_index)
2465 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
2466 my_id64 = GNUNET_ntohll (my_id64);
2468 /* Are we looking for immediate predecessor? */
2469 if (PREDECESSOR_FINGER_ID == finger_index)
2470 return (my_id64 -1);
2472 return (my_id64 + (unsigned long) pow (2, finger_index));
2477 * Choose a random friend. Start looking for the trail to reach to
2478 * finger identity corresponding to current_search_finger_index through
2479 * this random friend.
2481 * @param cls closure for this task
2482 * @param tc the context under which the task is running
2485 send_find_finger_trail_message (void *cls,
2486 const struct GNUNET_SCHEDULER_TaskContext *tc)
2488 struct FriendInfo *target_friend;
2489 struct GNUNET_TIME_Relative next_send_time;
2490 struct GNUNET_HashCode trail_id;
2491 unsigned int is_predecessor;
2492 uint64_t finger_id_value;
2494 /* Schedule another send_find_finger_trail_message task. */
2495 next_send_time.rel_value_us =
2496 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
2497 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
2498 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us);
2499 find_finger_trail_task =
2500 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_finger_trail_message,
2503 /* No space in my routing table. (Source and destination peers also store entries
2504 * in their routing table). */
2505 if (GNUNET_YES == GDS_ROUTING_threshold_reached())
2508 target_friend = select_random_friend ();
2509 if (NULL == target_friend)
2514 finger_id_value = compute_finger_identity_value (current_search_finger_index);
2515 if (PREDECESSOR_FINGER_ID == current_search_finger_index)
2520 /* Generate a unique trail id for trail we are trying to setup. */
2521 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
2522 &trail_id, sizeof (trail_id));
2523 GDS_NEIGHBOURS_send_trail_setup (my_identity, finger_id_value,
2524 target_friend->id, target_friend, 0, NULL,
2525 is_predecessor, trail_id, NULL);
2530 * In case there are already maximum number of possible trails to reach to a
2531 * finger, then check if the new trail's length is lesser than any of the
2533 * If yes then replace that old trail by new trail.
2535 * Note: Here we are taking length as a parameter to choose the best possible
2536 * trail, but there could be other parameters also like:
2537 * 1. duration of existence of a trail - older the better.
2538 * 2. if the new trail is completely disjoint than the
2539 * other trails, then may be choosing it is better.
2541 * @param existing_finger
2542 * @param new_finger_trail
2543 * @param new_finger_trail_length
2544 * @param new_finger_trail_id
2547 select_and_replace_trail (struct FingerInfo *existing_finger,
2548 const struct GNUNET_PeerIdentity *new_trail,
2549 unsigned int new_trail_length,
2550 struct GNUNET_HashCode new_trail_id)
2552 struct Trail *trail_list_iterator;
2553 unsigned int largest_trail_length;
2554 unsigned int largest_trail_index;
2555 struct Trail_Element *trail_element;
2558 largest_trail_length = new_trail_length;
2559 largest_trail_index = MAXIMUM_TRAILS_PER_FINGER + 1;
2561 GNUNET_assert (MAXIMUM_TRAILS_PER_FINGER == existing_finger->trails_count);
2563 for (i = 0; i < existing_finger->trails_count; i++)
2565 trail_list_iterator = &existing_finger->trail_list[i];
2566 if (trail_list_iterator->trail_length > largest_trail_length)
2568 largest_trail_length = trail_list_iterator->trail_length;
2569 largest_trail_index = i;
2573 /* New trail is not better than existing ones. Send trail teardown. */
2574 if (largest_trail_index == (MAXIMUM_TRAILS_PER_FINGER + 1))
2576 struct GNUNET_PeerIdentity next_hop;
2578 memcpy (&next_hop, &new_trail[0], sizeof(struct GNUNET_PeerIdentity));
2579 GDS_ROUTING_remove_trail (new_trail_id);
2580 GDS_NEIGHBOURS_send_trail_teardown (new_trail_id,
2581 GDS_ROUTING_SRC_TO_DEST,
2586 /* Send trail teardown message across the replaced trail. */
2587 struct Trail *replace_trail = &existing_finger->trail_list[largest_trail_index];
2588 existing_finger->trail_list[largest_trail_index].is_present = GNUNET_NO;
2589 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (replace_trail->trail_id));
2590 GDS_NEIGHBOURS_send_trail_teardown (replace_trail->trail_id,
2591 GDS_ROUTING_SRC_TO_DEST,
2592 replace_trail->trail_head->peer);
2593 /* Free the trail. */
2594 while (NULL != (trail_element = replace_trail->trail_head))
2596 GNUNET_CONTAINER_DLL_remove (replace_trail->trail_head,
2597 replace_trail->trail_tail, trail_element);
2598 GNUNET_free_non_null (trail_element);
2601 /* Add new trial at that location. */
2602 replace_trail->is_present = GNUNET_YES;
2603 replace_trail->trail_length = new_trail_length;
2604 replace_trail->trail_id = new_trail_id;
2605 //FIXME: Do we need to add pointers for head and tail.
2607 while (i < new_trail_length)
2609 struct Trail_Element *element = GNUNET_new (struct Trail_Element);
2610 element->peer = new_trail[i];
2612 GNUNET_CONTAINER_DLL_insert_tail (replace_trail->trail_head,
2613 replace_trail->trail_tail,
2620 * Check if the new trail to reach to finger is unique or do we already have
2621 * such a trail present for finger.
2622 * @param existing_finger Finger identity
2623 * @param new_trail New trail to reach @a existing_finger
2624 * @param trail_length Total number of peers in new_trail.
2625 * @return #GNUNET_YES if the new trail is unique
2626 * #GNUNET_NO if same trail is already present.
2629 is_new_trail_unique (struct FingerInfo *existing_finger,
2630 const struct GNUNET_PeerIdentity *new_trail,
2631 unsigned int trail_length)
2633 struct Trail *trail_list_iterator;
2634 struct Trail_Element *trail_element;
2637 int trail_unique = GNUNET_NO;
2639 GNUNET_assert (existing_finger->trails_count > 0);
2641 /* Iterate over list of trails. */
2642 for (i = 0; i < existing_finger->trails_count; i++)
2644 trail_list_iterator = &existing_finger->trail_list[i];
2645 GNUNET_assert (GNUNET_YES == trail_list_iterator->is_present);
2647 /* New trail and existing trail length are not same. */
2648 if (trail_list_iterator->trail_length != trail_length)
2650 trail_unique = GNUNET_YES;
2654 trail_element = trail_list_iterator->trail_head;
2655 for (j = 0; j < trail_list_iterator->trail_length; j++)
2657 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&new_trail[j],
2658 &trail_element->peer))
2660 trail_unique = GNUNET_YES;
2663 trail_element = trail_element->next;
2666 trail_unique = GNUNET_NO;
2669 return trail_unique;
2674 * Add a new trail to existing finger. This function is called only when finger
2675 * is not my own identity or a friend.
2676 * @param existing_finger Finger
2677 * @param new_finger_trail New trail from me to finger, NOT including endpoints
2678 * @param new_finger_trail_length Total number of peers in @a new_finger_trail
2679 * @param new_finger_trail_id Unique identifier of the trail.
2682 add_new_trail (struct FingerInfo *existing_finger,
2683 const struct GNUNET_PeerIdentity *new_trail,
2684 unsigned int new_trail_length,
2685 struct GNUNET_HashCode new_trail_id)
2687 struct Trail *trail_list_iterator;
2688 struct FriendInfo *first_friend;
2691 if (GNUNET_NO == is_new_trail_unique (existing_finger, new_trail,
2697 trail_list_iterator = &existing_finger->trail_list[existing_finger->trails_count];
2698 GNUNET_assert (GNUNET_NO == trail_list_iterator->is_present);
2699 trail_list_iterator->trail_id = new_trail_id;
2700 trail_list_iterator->trail_length = new_trail_length;
2701 existing_finger->trails_count++;
2702 trail_list_iterator->is_present = GNUNET_YES;
2704 /* If finger is a friend then we never call this function. */
2705 GNUNET_assert (new_trail_length > 0);
2707 first_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2709 first_friend->trails_count++;
2711 for (i = 0; i < new_trail_length; i++)
2713 struct Trail_Element *element;
2714 element = GNUNET_new (struct Trail_Element);
2716 element->peer = new_trail[i];
2717 GNUNET_CONTAINER_DLL_insert_tail (trail_list_iterator->trail_head,
2718 trail_list_iterator->trail_tail,
2721 /* Do we need to add trail head and trail tail in the trail list itearator.*/
2727 * FIXME Check if this function is called for opposite direction if yes then
2728 * take it as parameter.
2729 * Get the next hop to send trail teardown message from routing table and
2730 * then delete the entry from routing table. Send trail teardown message for a
2731 * specific trail of a finger.
2732 * @param finger Finger whose trail is to be removed.
2733 * @param trail List of peers in trail from me to a finger, NOT including
2737 send_trail_teardown (struct FingerInfo *finger,
2738 struct Trail *trail)
2740 struct FriendInfo *friend;
2741 struct GNUNET_PeerIdentity *next_hop;
2743 GNUNET_assert (NULL !=
2744 (next_hop = GDS_ROUTING_get_next_hop (trail->trail_id,
2745 GDS_ROUTING_SRC_TO_DEST)));
2747 GNUNET_assert (0 != GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
2749 if (trail->trail_length > 0)
2750 GNUNET_assert (NULL != (friend =
2751 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2752 &trail->trail_head->peer)));
2755 GNUNET_assert (NULL != (friend =
2756 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2757 &finger->finger_identity)));
2759 GNUNET_assert (0 == GNUNET_CRYPTO_cmp_peer_identity (next_hop, &friend->id));
2760 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail->trail_id));
2761 friend->trails_count--;
2762 GDS_NEIGHBOURS_send_trail_teardown (trail->trail_id,
2763 GDS_ROUTING_SRC_TO_DEST,
2769 * Send trail teardown message across all the trails to reach to finger.
2770 * @param finger Finger whose all the trail should be freed.
2773 send_all_finger_trails_teardown (struct FingerInfo *finger)
2777 for (i = 0; i < finger->trails_count; i++)
2779 struct Trail *trail;
2781 trail = &finger->trail_list[i];
2782 GNUNET_assert (trail->is_present == GNUNET_YES);
2783 send_trail_teardown (finger, trail);
2784 trail->is_present = GNUNET_NO;
2790 * Free a specific trail
2791 * @param trail List of peers to be freed.
2794 free_trail (struct Trail *trail)
2796 struct Trail_Element *trail_element;
2798 while (NULL != (trail_element = trail->trail_head))
2800 GNUNET_CONTAINER_DLL_remove (trail->trail_head,
2803 GNUNET_free_non_null (trail_element);
2805 trail->trail_head = NULL;
2806 trail->trail_tail = NULL;
2811 * Free finger and its trail.
2812 * @param finger Finger to be freed.
2815 free_finger (struct FingerInfo *finger, unsigned int finger_table_index)
2817 struct Trail *trail;
2820 /* Free all the trails to reach to finger */
2821 for (i = 0; i < finger->trails_count; i++)
2823 trail = &finger->trail_list[i];
2824 //FIXME: Check if there are any missing entry in this list because of
2825 // how we insert. If not then no need of this check.
2826 if (GNUNET_NO == trail->is_present)
2829 if (trail->trail_length > 0)
2833 trail->is_present = GNUNET_NO;
2836 finger->is_present = GNUNET_NO;
2837 memset ((void *)&finger_table[finger_table_index], 0, sizeof (finger_table[finger_table_index]));
2842 * FIXME: ensure that you are not adding any trail to reach to a friend which
2843 * is a finger. Also decide on should you increment trails count of a friend
2844 * which is also a finger.
2845 * Add a new entry in finger table at finger_table_index.
2846 * In case finger identity is me or a friend, then don't add a trail. NOTE
2847 * trail length to reach to a finger can be 0 only if the finger is a friend
2849 * In case a finger is a friend, then increment the trails count of the friend.
2850 * @param finger_identity Peer Identity of new finger
2851 * @param finger_trail Trail to reach from me to finger (excluding both end points).
2852 * @param finger_trail_length Total number of peers in @a finger_trail.
2853 * @param trail_id Unique identifier of the trail.
2854 * @param finger_table_index Index in finger table.
2857 add_new_finger (struct GNUNET_PeerIdentity finger_identity,
2858 const struct GNUNET_PeerIdentity *finger_trail,
2859 unsigned int finger_trail_length,
2860 struct GNUNET_HashCode trail_id,
2861 unsigned int finger_table_index)
2863 struct FingerInfo *new_entry;
2864 struct FriendInfo *first_trail_hop;
2865 struct Trail *trail;
2868 new_entry = GNUNET_new (struct FingerInfo);
2869 new_entry->finger_identity = finger_identity;
2870 new_entry->finger_table_index = finger_table_index;
2871 new_entry->is_present = GNUNET_YES;
2873 /* If the new entry is my own identity. */
2874 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity))
2876 new_entry->trails_count = 0;
2877 finger_table[finger_table_index] = *new_entry;
2881 /* If finger is a friend, then we don't actually have a trail.
2882 * Just a trail id */
2883 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2886 new_entry->trail_list[0].trail_id = trail_id;
2887 new_entry->trails_count = 1;
2888 new_entry->trail_list[0].is_present = GNUNET_YES;
2889 new_entry->trail_list[0].trail_length = 0;
2890 new_entry->trail_list[0].trail_head = NULL;
2891 new_entry->trail_list[0].trail_tail = NULL;
2892 finger_table[finger_table_index] = *new_entry;
2893 GNUNET_assert (NULL !=
2895 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2896 &finger_identity)));
2897 first_trail_hop->trails_count++;
2901 /* finger trail length can be 0 only in case if finger is my identity or
2902 finger is friend. We should never reach here. */
2903 GNUNET_assert (finger_trail_length > 0);
2905 GNUNET_assert (NULL !=
2907 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2908 &finger_trail[0])));
2909 new_entry->trails_count = 1;
2910 first_trail_hop->trails_count++;
2912 /* Copy the finger trail into trail. */
2913 trail = GNUNET_new (struct Trail);
2914 while (i < finger_trail_length)
2916 struct Trail_Element *element = GNUNET_new (struct Trail_Element);
2918 element->next = NULL;
2919 element->prev = NULL;
2920 element->peer = finger_trail[i];
2921 GNUNET_CONTAINER_DLL_insert_tail (trail->trail_head,
2927 /* Add trail to trail list. */
2928 new_entry->trail_list[0].trail_head = trail->trail_head;
2929 new_entry->trail_list[0].trail_tail = trail->trail_tail;
2930 new_entry->trail_list[0].trail_length = finger_trail_length;
2931 new_entry->trail_list[0].trail_id = trail_id;
2932 new_entry->trail_list[0].is_present = GNUNET_YES;
2933 finger_table[finger_table_index] = *new_entry;
2934 GNUNET_free (new_entry);
2935 GNUNET_free (trail);
2941 * Scan the trail to check if there is any other friend in the trail other than
2942 * first hop. If yes then shortcut the trail, send trail compression message to
2943 * peers which are no longer part of trail and send back the updated trail
2944 * and trail_length to calling function.
2945 * @param finger_identity Finger whose trail we will scan.
2946 * @param finger_trail [in, out] Trail to reach from source to finger,
2947 * @param finger_trail_length Total number of peers in original finger_trail.
2948 * @param finger_trail_id Unique identifier of the finger trail.
2949 * @return updated trail length in case we shortcut the trail, else original
2952 static struct GNUNET_PeerIdentity *
2953 scan_and_compress_trail (struct GNUNET_PeerIdentity finger_identity,
2954 const struct GNUNET_PeerIdentity *trail,
2955 unsigned int trail_length,
2956 struct GNUNET_HashCode trail_id,
2957 int *new_trail_length)
2959 struct FriendInfo *target_friend;
2960 struct GNUNET_PeerIdentity *new_trail;
2963 /* If I am my own finger identity, then we set trail_length = 0.
2964 Note: Here we don't send trail compression message, as no peer in its
2965 trail added an entry in its routing table.*/
2966 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity))
2968 *new_trail_length = 0;
2972 /* If finger identity is a friend. */
2973 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger_identity))
2975 *new_trail_length = 0;
2977 /* If there is trail to reach this finger/friend */
2978 if (trail_length > 0)
2980 GNUNET_assert (NULL !=
2982 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2985 /* Before you send a trail compression, get the routing entry
2986 from you routing table. update the fields in routing table
2987 to update your next hop to finger identity. */
2988 GDS_NEIGHBOURS_send_trail_compression (my_identity,
2989 trail_id, finger_identity,
2995 /* For other cases, when its neither a friend nor my own identity.*/
2996 for (i = trail_length - 1; i > 0; i--)
2998 /* If the element at this index in trail is a friend. */
2999 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, &trail[i]))
3001 struct FriendInfo *target_friend;
3004 GNUNET_assert (NULL !=
3006 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3008 GNUNET_assert (NULL !=
3009 (GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3011 GDS_ROUTING_update_trail_next_hop (trail_id, trail[i]);
3012 GDS_NEIGHBOURS_send_trail_compression (my_identity,
3017 /* Copy the trail from index i to index (trail_length -1) into a new trail
3018 * and update new trail length */
3019 new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * i);
3020 while (i < trail_length)
3022 memcpy (&new_trail[j], &trail[i], sizeof(struct GNUNET_PeerIdentity));
3026 *new_trail_length = j+1;
3031 /* If we did not compress the trail, return the original trail back.*/
3032 new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * trail_length);
3033 *new_trail_length = trail_length;
3034 memcpy (new_trail, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
3040 * Send verify successor message to your current successor over the shortest
3042 * @param successor Current successor.
3045 send_verify_successor_message (struct FingerInfo *successor)
3048 * FIXME: should we send a verify successor message across all the trails
3049 * in case we send through all friends. It complicates the logic, don't
3050 * do it at the moment. Write it as optimization and do it later.
3051 * 1. Here we can have 3 types of fingers
3052 * --> my own identity
3053 * Assumption that the calling function will not send request for
3054 * such successor. Move the logic here.
3055 * --> friend is a finger
3056 * Need to verify if we keep the trails count for a friend. In case of
3057 * friend there is no trail to reach to that friend, so
3058 * 1. no entry in routing table
3060 * 3. no trails count
3061 * 4. but do we increment the count of trails through the friend?
3062 * Trails count is used only to keep a limit on number of trails
3063 * that a friend should be part of. No need to increment the trails
3064 * count for a friend which is a finegr also. so, if finger = friend
3065 * then don't increment the trails count. But if the same friend
3066 * is the first friend to reach to some other finger then increment
3067 * the trails count. Not sure if this design is correct need to verify
3071 struct FriendInfo *target_friend;
3072 struct GNUNET_HashCode trail_id;
3075 for (i = 0; i < successor->trails_count; i++)
3077 struct Trail *trail;
3078 struct Trail_Element *element;
3079 unsigned int trail_length;
3082 trail = &successor->trail_list[i];
3084 /* No trail stored at this index. */
3085 if (GNUNET_YES == trail->is_present)
3088 trail_id = trail->trail_id;
3089 trail_length = trail->trail_length;
3091 /* Copy the trail into peer list. */
3092 element = trail->trail_head;
3093 struct GNUNET_PeerIdentity peer_list[trail_length];
3094 while (j < trail_length)
3096 peer_list[j] = element->peer;
3097 element = element->next;
3101 if (trail_length > 0)
3102 GNUNET_assert (NULL != (target_friend =
3103 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3106 GNUNET_assert (NULL != (target_friend =
3107 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3108 &successor->finger_identity)));
3109 GDS_NEIGHBOURS_send_verify_successor_message (my_identity,
3110 successor->finger_identity,
3111 trail_id, peer_list, trail_length,
3119 * Update the current search finger index.
3122 update_current_search_finger_index (struct GNUNET_PeerIdentity finger_identity,
3123 unsigned int finger_table_index)
3125 struct FingerInfo *successor;
3127 if (finger_table_index != current_search_finger_index)
3130 successor = &finger_table[0];
3131 if (GNUNET_NO == successor->is_present)
3134 /* We were looking for immediate successor. */
3135 if (0 == current_search_finger_index)
3137 /* Start looking for immediate predecessor. */
3138 current_search_finger_index = PREDECESSOR_FINGER_ID;
3140 /* If I am not my own successor, then send a verify successor message. */
3141 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity))
3143 send_verify_successor_message (successor);
3148 current_search_finger_index = current_search_finger_index - 1;
3154 * Calculate finger_table_index from initial 64 bit finger identity value that
3155 * we send in trail setup message.
3156 * @param ultimate_destination_finger_value Value that we calculated from our
3157 * identity and finger_table_index.
3158 * @param is_predecessor Is the entry for predecessor or not?
3159 * @return finger_table_index Value between 0 <= finger_table_index <= 64
3160 * finger_table_index > PREDECESSOR_FINGER_ID ,
3161 * if no valid finger_table_index is found.
3164 get_finger_table_index (uint64_t ultimate_destination_finger_value,
3165 unsigned int is_predecessor)
3169 unsigned int finger_table_index;
3171 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
3172 my_id64 = GNUNET_ntohll (my_id64);
3174 /* Is this a predecessor finger? */
3175 if (1 == is_predecessor)
3177 diff = my_id64 - ultimate_destination_finger_value;
3179 finger_table_index = PREDECESSOR_FINGER_ID;
3181 finger_table_index = PREDECESSOR_FINGER_ID + 1; //error value
3186 diff = ultimate_destination_finger_value - my_id64;
3187 finger_table_index = (log10 (diff))/(log10 (2));
3190 return finger_table_index;
3195 * Remove finger and its associated data structures from finger table.
3196 * @param finger Finger to be removed.
3199 remove_existing_finger (struct FingerInfo *existing_finger, unsigned int finger_table_index)
3201 struct FingerInfo *finger;
3203 finger = &finger_table[finger_table_index];
3204 GNUNET_assert (GNUNET_YES == finger->is_present);
3206 /* If I am my own finger, then we have no trails. */
3207 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
3210 finger->is_present = GNUNET_NO;
3211 memset ((void *)&finger_table[finger_table_index], 0, sizeof (finger_table[finger_table_index]));
3215 /* For all other fingers, send trail teardown across all the trails to reach
3216 finger, and free the finger. */
3217 send_all_finger_trails_teardown (finger);
3218 free_finger (finger, finger_table_index);
3224 * This is a test function to print all the entries of friend table.
3227 test_friend_peermap_print ()
3229 struct FriendInfo *friend;
3230 struct GNUNET_CONTAINER_MultiPeerMapIterator *friend_iter;
3231 struct GNUNET_PeerIdentity print_peer;
3232 struct GNUNET_PeerIdentity key_ret;
3235 friend_iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
3237 for (i = 0; i < GNUNET_CONTAINER_multipeermap_size (friend_peermap); i++)
3239 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (friend_iter,
3241 (const void **)&friend))
3243 memcpy (&print_peer, &key_ret, sizeof (struct GNUNET_PeerIdentity));
3244 FPRINTF (stderr,_("\nSUPU %s, %s, %d, friend = %s, friend->trails_count = %d"),
3245 __FILE__, __func__,__LINE__, GNUNET_i2s(&print_peer), friend->trails_count);
3252 * Check if there is already an entry in finger_table at finger_table_index.
3253 * We get the finger_table_index from 64bit finger value we got from the network.
3254 * -- If yes, then select the closest finger.
3255 * -- If new and existing finger are same, then check if you can store more
3257 * -- If yes then add trail, else keep the best trails to reach to the
3259 * -- If the new finger is closest, remove the existing entry, send trail
3260 * teardown message across all the trails to reach the existing entry.
3261 * Add the new finger.
3262 * -- If new and existing finger are different, and existing finger is closest
3264 * -- Update current_search_finger_index.
3265 * @param finger_identity Peer Identity of new finger
3266 * @param finger_trail Trail to reach the new finger
3267 * @param finger_trail_length Total number of peers in @a new_finger_trail.
3268 * @param is_predecessor Is this entry for predecessor in finger_table?
3269 * @param finger_value 64 bit value of finger identity that we got from network.
3270 * @param finger_trail_id Unique identifier of @finger_trail.
3273 finger_table_add (struct GNUNET_PeerIdentity finger_identity,
3274 const struct GNUNET_PeerIdentity *finger_trail,
3275 unsigned int finger_trail_length,
3276 unsigned int is_predecessor,
3277 uint64_t finger_value,
3278 struct GNUNET_HashCode finger_trail_id)
3280 struct FingerInfo *existing_finger;
3281 struct GNUNET_PeerIdentity *closest_peer;
3282 struct GNUNET_PeerIdentity *updated_trail;
3283 struct FingerInfo *successor;
3284 int updated_finger_trail_length;
3285 unsigned int finger_table_index;
3287 /* Get the finger_table_index corresponding to finger_value we got from network.*/
3288 finger_table_index = get_finger_table_index (finger_value, is_predecessor);
3290 /* Invalid finger_table_index. */
3291 if ((finger_table_index > PREDECESSOR_FINGER_ID))
3293 GNUNET_break_op (0);
3297 /* If the new entry for any finger table index other than successor or predecessor
3298 * is same as successor then don't add it in finger table,
3299 * reset the current search finger index and exit. */
3300 if ((0 != finger_table_index) &&
3301 (PREDECESSOR_FINGER_ID != finger_table_index) &&
3302 (finger_table_index == current_search_finger_index)) //FIXME; why do I check this cond?
3304 successor = &finger_table[0];
3305 GNUNET_assert (GNUNET_YES == successor->is_present);
3306 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity,
3307 &successor->finger_identity))
3309 current_search_finger_index = 0;
3314 existing_finger = &finger_table[finger_table_index];
3316 /* Shorten the trail if possible. */
3317 updated_finger_trail_length = finger_trail_length;
3319 scan_and_compress_trail (finger_identity, finger_trail,
3320 finger_trail_length, finger_trail_id,
3321 &updated_finger_trail_length);
3323 /* No entry present in finger_table for given finger map index. */
3324 if (GNUNET_NO == existing_finger->is_present)
3326 add_new_finger (finger_identity, updated_trail,
3327 updated_finger_trail_length,
3328 finger_trail_id, finger_table_index);
3329 update_current_search_finger_index (finger_identity, finger_table_index);
3330 GNUNET_free_non_null (updated_trail);
3335 /* If existing entry and finger identity are not same. */
3336 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity),
3339 closest_peer = select_closest_peer (&existing_finger->finger_identity,
3344 /* If the new finger is the closest peer. */
3345 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, closest_peer))
3347 remove_existing_finger (existing_finger, finger_table_index);
3348 add_new_finger (finger_identity, updated_trail, updated_finger_trail_length,
3349 finger_trail_id, finger_table_index);
3353 /* Existing finger is the closest one. We need to send trail teardown
3354 across the trail setup in routing table of all the peers. */
3355 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, &my_identity))
3357 if (updated_finger_trail_length > 0)
3358 GDS_NEIGHBOURS_send_trail_teardown (finger_trail_id,
3359 GDS_ROUTING_SRC_TO_DEST,
3362 GDS_NEIGHBOURS_send_trail_teardown (finger_trail_id,
3363 GDS_ROUTING_SRC_TO_DEST,
3370 /* If both new and existing entry are same as my_identity, then do nothing. */
3371 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity),
3374 GNUNET_free_non_null (updated_trail);
3377 /* If the existing finger is not a friend. */
3379 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3380 &existing_finger->finger_identity))
3382 /* If there is space to store more trails. */
3383 if (existing_finger->trails_count < MAXIMUM_TRAILS_PER_FINGER)
3384 add_new_trail (existing_finger, updated_trail,
3385 finger_trail_length, finger_trail_id);
3387 select_and_replace_trail (existing_finger, updated_trail,
3388 finger_trail_length, finger_trail_id);
3391 update_current_search_finger_index (finger_identity, finger_table_index);
3392 GNUNET_free_non_null (updated_trail);
3398 * Core handler for P2P put messages.
3399 * @param cls closure
3400 * @param peer sender of the request
3401 * @param message message
3402 * @return #GNUNET_OK to keep the connection open,
3403 * #GNUNET_SYSERR to close it (signal serious error)
3406 handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer,
3407 const struct GNUNET_MessageHeader *message)
3409 struct PeerPutMessage *put;
3410 struct GNUNET_PeerIdentity *put_path;
3411 struct GNUNET_HashCode test_key;
3412 enum GNUNET_DHT_RouteOption options;
3413 struct GNUNET_PeerIdentity best_known_dest;
3414 struct GNUNET_HashCode intermediate_trail_id;
3415 struct GNUNET_PeerIdentity *next_hop;
3419 size_t payload_size;
3422 msize = ntohs (message->size);
3423 if (msize < sizeof (struct PeerPutMessage))
3425 GNUNET_break_op (0);
3429 put = (struct PeerPutMessage *) message;
3430 putlen = ntohl (put->put_path_length);
3433 sizeof (struct PeerPutMessage) +
3434 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
3436 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3438 GNUNET_break_op (0);
3442 best_known_dest = put->best_known_destination;
3443 put_path = (struct GNUNET_PeerIdentity *) &put[1];
3444 payload = &put_path[putlen];
3445 options = ntohl (put->options);
3446 intermediate_trail_id = put->intermediate_trail_id;
3448 payload_size = msize - (sizeof (struct PeerPutMessage) +
3449 putlen * sizeof (struct GNUNET_PeerIdentity));
3451 switch (GNUNET_BLOCK_get_key (GDS_block_context, ntohl (put->block_type),
3452 payload, payload_size, &test_key))
3455 if (0 != memcmp (&test_key, &put->key, sizeof (struct GNUNET_HashCode)))
3457 char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key));
3458 GNUNET_break_op (0);
3459 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3460 "PUT with key `%s' for block with key %s\n",
3461 put_s, GNUNET_h2s_full (&test_key));
3462 GNUNET_free (put_s);
3467 GNUNET_break_op (0);
3470 /* cannot verify, good luck */
3474 if (ntohl (put->block_type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
3476 switch (GNUNET_BLOCK_evaluate (GDS_block_context,
3477 ntohl (put->block_type),
3479 NULL, 0, /* bloom filer */
3480 NULL, 0, /* xquery */
3481 payload, payload_size))
3483 case GNUNET_BLOCK_EVALUATION_OK_MORE:
3484 case GNUNET_BLOCK_EVALUATION_OK_LAST:
3487 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
3488 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
3489 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
3490 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
3491 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
3492 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
3494 GNUNET_break_op (0);
3499 /* extend 'put path' by sender */
3500 struct GNUNET_PeerIdentity pp[putlen + 1];
3501 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
3503 memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity));
3510 memcpy (&key_value, &(put->key), sizeof (uint64_t));
3511 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&best_known_dest, &my_identity)))
3513 next_hop = GDS_ROUTING_get_next_hop (intermediate_trail_id,
3514 GDS_ROUTING_SRC_TO_DEST);
3518 key_value = GNUNET_ntohll (key_value);
3519 next_hop = find_successor (key_value, &best_known_dest,
3520 &intermediate_trail_id, GDS_FINGER_TYPE_NON_PREDECESSOR);
3523 if (NULL == next_hop)
3525 GNUNET_STATISTICS_update (GDS_stats,
3526 gettext_noop ("# Next hop to forward the packet not found "
3527 "trail setup request, packet dropped."),
3529 return GNUNET_SYSERR;
3532 GDS_CLIENTS_process_put (options,
3533 ntohl (put->block_type),
3534 ntohl (put->hop_count),
3535 ntohl (put->desired_replication_level),
3537 GNUNET_TIME_absolute_ntoh (put->expiration_time),
3542 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &best_known_dest)) /* I am the final destination */
3544 GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time),
3545 &(put->key),putlen, pp, ntohl (put->block_type),
3546 payload_size, payload);
3547 GNUNET_free_non_null (next_hop);
3552 GDS_NEIGHBOURS_send_put (&put->key,
3553 ntohl (put->block_type),ntohl (put->options),
3554 ntohl (put->desired_replication_level),
3555 &best_known_dest, &intermediate_trail_id, next_hop,
3556 ntohl (put->hop_count), putlen, pp,
3557 GNUNET_TIME_absolute_ntoh (put->expiration_time),
3558 payload, payload_size);
3562 return GNUNET_SYSERR;
3567 * Core handler for p2p get requests.
3569 * @param cls closure
3570 * @param peer sender of the request
3571 * @param message message
3572 * @return #GNUNET_OK to keep the connection open,
3573 * #GNUNET_SYSERR to close it (signal serious error)
3576 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
3577 const struct GNUNET_MessageHeader *message)
3579 const struct PeerGetMessage *get;
3580 const struct GNUNET_PeerIdentity *get_path;
3581 struct GNUNET_PeerIdentity best_known_dest;
3582 struct GNUNET_HashCode intermediate_trail_id;
3583 struct GNUNET_PeerIdentity *next_hop;
3584 uint32_t get_length;
3588 msize = ntohs (message->size);
3589 if (msize < sizeof (struct PeerGetMessage))
3591 GNUNET_break_op (0);
3595 get = (const struct PeerGetMessage *)message;
3596 get_length = ntohl (get->get_path_length);
3597 best_known_dest = get->best_known_destination;
3598 intermediate_trail_id = get->intermediate_trail_id;
3599 get_path = (const struct GNUNET_PeerIdentity *)&get[1];
3602 sizeof (struct PeerGetMessage) +
3603 get_length * sizeof (struct GNUNET_PeerIdentity)) ||
3605 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3607 GNUNET_break_op (0);
3611 /* Add sender to get path */
3612 struct GNUNET_PeerIdentity gp[get_length + 1];
3614 memcpy (gp, get_path, get_length * sizeof (struct GNUNET_PeerIdentity));
3615 gp[get_length] = *peer;
3616 get_length = get_length + 1;
3618 memcpy (&key_value, &(get->key), sizeof (uint64_t));
3619 key_value = GNUNET_ntohll (key_value);
3621 /* I am not the final destination. I am part of trail to reach final dest. */
3622 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&best_known_dest, &my_identity)))
3624 next_hop = GDS_ROUTING_get_next_hop (intermediate_trail_id,
3625 GDS_ROUTING_SRC_TO_DEST);
3629 /* Get the next hop to pass the message to. */
3630 next_hop = find_successor (key_value, &best_known_dest,
3631 &intermediate_trail_id, GDS_FINGER_TYPE_NON_PREDECESSOR);
3634 if (NULL == next_hop)
3636 GNUNET_STATISTICS_update (GDS_stats,
3637 gettext_noop ("# Next hop to forward the packet not found "
3638 "trail setup request, packet dropped."),
3640 return GNUNET_SYSERR;
3642 GDS_CLIENTS_process_get (get->options, get->block_type,get->hop_count,
3643 get->desired_replication_level, get->get_path_length,
3645 /* I am the final destination. */
3646 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, &best_known_dest))
3648 struct GNUNET_PeerIdentity final_get_path[get_length+1];
3650 memcpy (final_get_path, gp, get_length * sizeof (struct GNUNET_PeerIdentity));
3651 memcpy (&final_get_path[get_length], &my_identity, sizeof (struct GNUNET_PeerIdentity));
3652 get_length = get_length + 1;
3654 GDS_DATACACHE_handle_get (&(get->key),(get->block_type), NULL, 0, NULL, 0,
3655 get_length, final_get_path,
3656 &final_get_path[get_length-2], &my_identity);
3662 GDS_NEIGHBOURS_send_get (&(get->key), get->block_type, get->options,
3663 get->desired_replication_level, &best_known_dest,
3664 &intermediate_trail_id, next_hop, 0,
3666 GNUNET_free (next_hop);
3668 return GNUNET_SYSERR;
3673 * Core handler for get result
3674 * @param cls closure
3675 * @param peer sender of the request
3676 * @param message message
3677 * @return #GNUNET_OK to keep the connection open,
3678 * #GNUNET_SYSERR to close it (signal serious error)
3681 handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer,
3682 const struct GNUNET_MessageHeader *message)
3684 const struct PeerGetResultMessage *get_result;
3685 const struct GNUNET_PeerIdentity *get_path;
3686 const struct GNUNET_PeerIdentity *put_path;
3687 const void *payload;
3688 size_t payload_size;
3690 unsigned int getlen;
3691 unsigned int putlen;
3692 int current_path_index;
3694 msize = ntohs (message->size);
3695 if (msize < sizeof (struct PeerGetResultMessage))
3697 GNUNET_break_op (0);
3701 get_result = (const struct PeerGetResultMessage *)message;
3702 getlen = ntohl (get_result->get_path_length);
3703 putlen = ntohl (get_result->put_path_length);
3706 sizeof (struct PeerGetResultMessage) +
3707 getlen * sizeof (struct GNUNET_PeerIdentity) +
3708 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
3710 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity) ||
3712 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))))
3714 GNUNET_break_op (0);
3718 put_path = (const struct GNUNET_PeerIdentity *) &get_result[1];
3719 get_path = &put_path[putlen];
3720 payload = (const void *) &get_path[getlen];
3721 payload_size = msize - (sizeof (struct PeerGetResultMessage) +
3722 (getlen + putlen) * sizeof (struct GNUNET_PeerIdentity));
3724 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &(get_path[0]))))
3726 GDS_CLIENTS_handle_reply (get_result->expiration_time, &(get_result->key),
3727 getlen, get_path, putlen,
3728 put_path, get_result->type, payload_size, payload);
3733 current_path_index = search_my_index (get_path, getlen);
3734 if (-1 == current_path_index )
3737 return GNUNET_SYSERR;
3739 GDS_NEIGHBOURS_send_get_result (&(get_result->key), get_result->type,
3740 &get_path[current_path_index - 1],
3741 &(get_result->querying_peer), putlen, put_path,
3742 getlen, get_path, get_result->expiration_time,
3743 payload, payload_size);
3746 return GNUNET_SYSERR;
3751 * Get the best known next destination (local_dest) among your fingers, friends
3752 * and my identity. In case I was part of trail to reach to some other destination
3753 * (current_dest), then compare current_dest and local_dest, and choose the
3755 * @param final_dest_finger_value Peer closest to this value will be
3756 * @a local_best_known_dest
3757 * @param local_best_known_dest[out] Updated to peer identity which is closest to
3758 * @a final_dest_finger_value.
3759 * @param new_intermediate_trail_id In case @a local_best_known_dest is a finger,
3760 * then the trail id to reach to the finger
3761 * @param is_predecessor Is source peer trying to setup trail to its predecessor
3763 * @param current_dest Peer which should get this message ultimately according
3764 * to the peer which sent me this message. It could be me
3765 * or some other peer. In case it is not me, then I am a part
3766 * of trail to reach to that peer.
3769 static struct GNUNET_PeerIdentity *
3770 get_local_best_known_next_hop (uint64_t final_dest_finger_value,
3771 struct GNUNET_PeerIdentity *local_best_known_dest,
3772 struct GNUNET_HashCode *new_intermediate_trail_id,
3773 struct GNUNET_HashCode intermediate_trail_id,
3774 unsigned int is_predecessor,
3775 struct GNUNET_PeerIdentity *current_dest)
3777 struct GNUNET_PeerIdentity *next_hop_to_local_best_known_dest;
3779 /* Choose a local best known hop among your fingers, friends and you. */
3780 next_hop_to_local_best_known_dest = find_successor (final_dest_finger_value,
3781 local_best_known_dest,
3782 new_intermediate_trail_id,
3785 /* Are we just a part of a trail towards a finger (current_destination)? */
3786 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, current_dest)))
3788 struct GNUNET_PeerIdentity *closest_peer;
3790 /* Select best successor among one found locally and current_destination
3791 * that we got from network.*/
3792 if (0 != GNUNET_CRYPTO_cmp_peer_identity (local_best_known_dest, current_dest))
3794 closest_peer = select_closest_peer (local_best_known_dest,
3796 final_dest_finger_value,
3799 /* Is current dest (end point of the trail of which I am a part) closest_peer? */
3800 if (0 == GNUNET_CRYPTO_cmp_peer_identity (current_dest, closest_peer))
3802 struct GNUNET_PeerIdentity *next_hop;
3803 next_hop = GDS_ROUTING_get_next_hop (intermediate_trail_id,
3804 GDS_ROUTING_SRC_TO_DEST);
3805 /* FIXME: Here we found next_hop NULL from routing table, but we still
3806 * have a next_hop from find_successor should we not break and choose that
3808 if (NULL == next_hop)
3810 GNUNET_break_op (0);
3813 next_hop_to_local_best_known_dest = next_hop;
3814 local_best_known_dest = current_dest;
3815 *new_intermediate_trail_id = intermediate_trail_id;
3820 GNUNET_assert (NULL != next_hop_to_local_best_known_dest);
3821 return next_hop_to_local_best_known_dest;
3826 * Core handle for PeerTrailSetupMessage.
3827 * @param cls closure
3828 * @param message message
3829 * @param peer peer identity this notification is about
3830 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3833 handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer,
3834 const struct GNUNET_MessageHeader *message)
3836 const struct PeerTrailSetupMessage *trail_setup;
3837 const struct GNUNET_PeerIdentity *trail_peer_list;
3838 struct GNUNET_PeerIdentity *local_best_known_dest;
3839 struct GNUNET_PeerIdentity current_dest;
3840 struct GNUNET_PeerIdentity *next_hop_towards_local_best_known_dest;
3841 struct FriendInfo *target_friend;
3842 struct GNUNET_PeerIdentity source;
3843 uint64_t final_dest_finger_val;
3844 struct GNUNET_HashCode *new_intermediate_trail_id;
3845 struct GNUNET_HashCode intermediate_trail_id;
3846 struct GNUNET_HashCode trail_id;
3847 unsigned int is_predecessor;
3848 uint32_t trail_length;
3851 msize = ntohs (message->size);
3852 if (msize < sizeof (struct PeerTrailSetupMessage))
3854 GNUNET_break_op (0);
3858 trail_setup = (const struct PeerTrailSetupMessage *) message;
3859 trail_length = (msize - sizeof (struct PeerTrailSetupMessage))/
3860 sizeof (struct GNUNET_PeerIdentity);
3861 if ((msize - sizeof (struct PeerTrailSetupMessage)) %
3862 sizeof (struct GNUNET_PeerIdentity) != 0)
3864 GNUNET_break_op (0);
3868 trail_peer_list = (const struct GNUNET_PeerIdentity *)&trail_setup[1];
3869 current_dest = trail_setup->best_known_destination;
3870 trail_id = trail_setup->trail_id;
3871 final_dest_finger_val =
3872 GNUNET_ntohll (trail_setup->final_destination_finger_value);
3873 source = trail_setup->source_peer;
3874 is_predecessor = ntohl (trail_setup->is_predecessor);
3875 intermediate_trail_id = trail_setup->intermediate_trail_id;
3877 /* Is my routing table full? */
3878 if (GNUNET_YES == GDS_ROUTING_threshold_reached())
3880 /* As my routing table is full, I can no longer handle any more trail
3883 GNUNET_assert (NULL !=
3885 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer)));
3886 GDS_NEIGHBOURS_send_trail_rejection (source, final_dest_finger_val,
3887 my_identity, is_predecessor,
3888 trail_peer_list, trail_length,
3889 trail_id, target_friend,
3890 CONGESTION_TIMEOUT);
3894 new_intermediate_trail_id = GNUNET_new (struct GNUNET_HashCode);
3896 local_best_known_dest = GNUNET_new (struct GNUNET_PeerIdentity);
3898 /* Get the next hop to forward the trail setup request. */
3899 next_hop_towards_local_best_known_dest =
3900 get_local_best_known_next_hop (final_dest_finger_val,
3901 local_best_known_dest,
3902 new_intermediate_trail_id,
3903 intermediate_trail_id,
3907 GNUNET_assert (NULL != local_best_known_dest);
3908 GNUNET_assert (NULL != next_hop_towards_local_best_known_dest);
3910 /* Am I the final destination? */
3911 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (local_best_known_dest,
3914 /* If I was not the source of this message for which now I am destination */
3915 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&source, &my_identity))
3917 GDS_ROUTING_add (trail_id, *peer, my_identity);
3920 GNUNET_assert (NULL !=
3922 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer)));
3923 GDS_NEIGHBOURS_send_trail_setup_result (source,
3925 target_friend, trail_length,
3927 final_dest_finger_val,
3928 is_predecessor, trail_id);
3932 /* Add yourself to list of peers. */
3933 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
3935 memcpy (peer_list, trail_peer_list,
3936 trail_length * sizeof (struct GNUNET_PeerIdentity));
3937 peer_list[trail_length] = my_identity;
3938 GNUNET_assert (NULL !=
3940 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3941 next_hop_towards_local_best_known_dest)));
3942 /* FIXME; CHECK IF INTERMEDIATE TRAIL ID is 0 thne pas null. */
3944 GDS_NEIGHBOURS_send_trail_setup (source,
3945 final_dest_finger_val,
3946 *local_best_known_dest,
3947 target_friend, trail_length + 1, peer_list,
3948 is_predecessor, trail_id,
3949 new_intermediate_trail_id);
3951 GNUNET_free (local_best_known_dest);
3952 GNUNET_free (next_hop_towards_local_best_known_dest);
3957 /* FIXME: here we are calculating my_index and comparing also in this function.
3958 And we are doing it again here in this function. Re factor the code. */
3960 * FIXME: Should we call this function everywhere in all the handle functions
3961 * where we have a trail to verify from or a trail id. something like
3962 * if prev hop is not same then drop the message.
3963 * Check if sender_peer and peer from which we should receive the message are
3964 * same or different.
3965 * @param trail_peer_list List of peers in trail
3966 * @param trail_length Total number of peers in @a trail_peer_list
3967 * @param sender_peer Peer from which we got the message.
3968 * @param finger_identity Finger to which trail is setup. It is not part of trail.
3969 * @return #GNUNET_YES if sender_peer and peer from which we should receive the
3970 * message are different.
3971 * #GNUNET_NO if sender_peer and peer from which we should receive the
3972 * message are different.
3975 is_sender_peer_correct (const struct GNUNET_PeerIdentity *trail_peer_list,
3976 unsigned int trail_length,
3977 const struct GNUNET_PeerIdentity *sender_peer,
3978 struct GNUNET_PeerIdentity finger_identity,
3979 struct GNUNET_PeerIdentity source_peer)
3983 /* I am the source peer. */
3984 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&source_peer,
3987 /* Is the first element of the trail is sender_peer.*/
3988 if (trail_length > 0)
3990 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&trail_peer_list[0],
3996 /* Is finger the sender peer? */
3997 if (0 != GNUNET_CRYPTO_cmp_peer_identity (sender_peer,
4004 /* Get my current location in the trail. */
4005 my_index = search_my_index (trail_peer_list, trail_length);
4009 /* I am the last element in the trail. */
4010 if ((trail_length - 1) == my_index)
4012 /* Is finger the sender_peer? */
4013 if (0 != GNUNET_CRYPTO_cmp_peer_identity (sender_peer,
4019 /* Is peer after me in trail the sender peer? */
4020 if (0 != GNUNET_CRYPTO_cmp_peer_identity (sender_peer,
4021 &trail_peer_list[my_index + 1]))
4030 * FIXME: we should also add a case where we search if we are present in the trail
4032 * Core handle for p2p trail setup result messages.
4034 * @param message message
4035 * @param peer sender of this message.
4036 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4039 handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer,
4040 const struct GNUNET_MessageHeader *message)
4042 const struct PeerTrailSetupResultMessage *trail_result;
4043 const struct GNUNET_PeerIdentity *trail_peer_list;
4044 struct GNUNET_PeerIdentity next_hop;
4045 struct FriendInfo *target_friend;
4046 struct GNUNET_PeerIdentity querying_peer;
4047 struct GNUNET_PeerIdentity finger_identity;
4048 uint32_t trail_length;
4049 uint64_t ulitmate_destination_finger_value;
4050 uint32_t is_predecessor;
4051 struct GNUNET_HashCode trail_id;
4055 msize = ntohs (message->size);
4056 if (msize < sizeof (struct PeerTrailSetupResultMessage))
4058 GNUNET_break_op (0);
4062 trail_result = (const struct PeerTrailSetupResultMessage *) message;
4063 trail_length = (msize - sizeof (struct PeerTrailSetupResultMessage))/
4064 sizeof (struct GNUNET_PeerIdentity);
4065 if ((msize - sizeof (struct PeerTrailSetupResultMessage)) %
4066 sizeof (struct GNUNET_PeerIdentity) != 0)
4068 GNUNET_break_op (0);
4072 is_predecessor = htonl (trail_result->is_predecessor);
4073 querying_peer = trail_result->querying_peer;
4074 finger_identity = trail_result->finger_identity;
4075 trail_id = trail_result->trail_id;
4076 trail_peer_list = (const struct GNUNET_PeerIdentity *) &trail_result[1];
4077 ulitmate_destination_finger_value =
4078 GNUNET_ntohll (trail_result->ulitmate_destination_finger_value);
4080 /* FIXME: here we are calculating my_index and comparing also in this function.
4081 And we are doing it again here in this function. Re factor the code. */
4082 /* Ensure that sender peer is the peer from which we were expecting the message. */
4084 if (GNUNET_NO == is_sender_peer_correct (trail_peer_list,
4086 peer, finger_identity, querying_peer))
4088 GNUNET_break_op (0);
4089 return GNUNET_SYSERR;
4093 /* Am I the one who initiated the query? */
4094 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&querying_peer,
4097 /* If I am not my own finger identity, then add routing table entry. */
4098 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity))
4100 GDS_ROUTING_add (trail_id, my_identity, *peer);
4103 finger_table_add (finger_identity, trail_peer_list,
4104 trail_length, ulitmate_destination_finger_value,
4105 is_predecessor, trail_id);
4109 /* Get my location in the trail. */
4110 my_index = search_my_index(trail_peer_list, trail_length);
4114 return GNUNET_SYSERR;
4117 /* FIXME: CHECK IF YOU ARE PRESENT MORE THAN ONCE IN THE TRAIL, IF YES
4118 THEN REMOVE ALL THE ENTRIES AND CHOOSE THE PEER THERE.*/
4120 next_hop = trail_result->querying_peer;
4122 next_hop = trail_peer_list[my_index - 1];
4124 /* If the querying_peer is its own finger, then don't add an entry in routing
4125 * table as querying peer will discard the trail. */
4126 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->querying_peer),
4127 &(trail_result->finger_identity))))
4129 GDS_ROUTING_add (trail_id, next_hop, *peer);
4132 GNUNET_assert (NULL !=
4134 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop)));
4135 GDS_NEIGHBOURS_send_trail_setup_result (querying_peer, finger_identity,
4136 target_friend, trail_length, trail_peer_list,
4138 ulitmate_destination_finger_value,
4146 * @param trail Trail to be inverted
4147 * @param trail_length Total number of peers in the trail.
4148 * @return Updated trail
4150 static struct GNUNET_PeerIdentity *
4151 invert_trail (const struct GNUNET_PeerIdentity *trail,
4152 unsigned int trail_length)
4156 struct GNUNET_PeerIdentity *inverted_trail;
4158 inverted_trail = GNUNET_malloc (sizeof(struct GNUNET_PeerIdentity) *
4161 j = trail_length - 1;
4162 while (i < trail_length)
4164 inverted_trail[i] = trail[j];
4168 return inverted_trail;
4173 * Return the shortest trail to reach from me to my_predecessor.
4174 * @param my_predecessor my current predecessor.
4175 * @param current_trail Trail from source to me.
4176 * @param current_trail_length Total number of peers in @a current_trail
4177 * @param trail_length [out] Total number of peers in selected trail.
4178 * @return Updated trail from source peer to my_predecessor.
4180 static struct GNUNET_PeerIdentity *
4181 trail_source_to_my_predecessor (const struct GNUNET_PeerIdentity *current_trail,
4182 unsigned int current_trail_length,
4183 unsigned int *trail_length)
4185 struct GNUNET_PeerIdentity *trail_me_to_predecessor;
4186 struct Trail *trail;
4187 struct Trail_Element *trail_element;
4188 struct FingerInfo *my_predecessor;
4190 unsigned int shortest_trail_length = 0;
4191 unsigned int trail_index = 0;
4193 my_predecessor = &finger_table[PREDECESSOR_FINGER_ID];
4195 GNUNET_assert (GNUNET_YES == my_predecessor->is_present);
4197 //if my_predecessor is a friend then don't send back any trail. as
4198 // there is no trail.
4201 /* Choose the shortest path from me to my predecessor. */
4202 for (i = 0; i < my_predecessor->trails_count; i++)
4204 trail = &my_predecessor->trail_list[i];
4205 if (trail->trail_length > shortest_trail_length)
4207 shortest_trail_length = trail->trail_length;
4211 *trail_length = shortest_trail_length;
4212 trail_me_to_predecessor = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)
4215 /* Copy the selected trail and send this trail to calling function. */
4217 trail = &my_predecessor->trail_list[trail_index];
4218 trail_element = trail->trail_head;
4219 while ( i < shortest_trail_length)
4221 trail_me_to_predecessor[i] = trail_element->peer;
4223 trail_element = trail_element->next;
4226 return trail_me_to_predecessor;
4231 * FIXME In case predecessor is a friend then do we add it in routing table.
4232 * if not then check the logic of trail teardown in case we compress the trail
4233 * such that friend is finger. then do we remove the entry from end points or
4234 * not. Ideally we should remove the entries from end point.
4235 * Add finger as your predecessor. To add, first generate a new trail id, invert
4236 * the trail to get the trail from me to finger, add an entry in your routing
4237 * table, send add trail message to peers which are part of trail from me to
4238 * finger and add finger in finger table.
4241 * @param trail_length
4244 update_predecessor (struct GNUNET_PeerIdentity finger,
4245 struct GNUNET_PeerIdentity *trail,
4246 unsigned int trail_length)
4248 struct GNUNET_HashCode trail_to_new_predecessor_id;
4249 struct GNUNET_PeerIdentity *trail_to_new_predecessor;
4250 struct FriendInfo *target_friend;
4252 /* Generate trail id for trail from me to new predecessor = finger. */
4253 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
4254 &trail_to_new_predecessor_id,
4255 sizeof (trail_to_new_predecessor_id));
4257 /* Finger is a friend. */
4258 if (trail_length == 0)
4260 trail_to_new_predecessor = NULL;
4261 /* FIXME: check that you always add trail entry even if your finger is
4263 GDS_ROUTING_add (trail_to_new_predecessor_id, finger, my_identity);
4264 GNUNET_assert (NULL != (target_friend =
4265 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4270 /* Invert the trail to get the trail from me to finger, NOT including the
4272 trail_to_new_predecessor = invert_trail (trail, trail_length);
4273 /* FIXME: check that you always add trail entry even if your finger is
4276 /* Add an entry in your routing table. */
4277 GDS_ROUTING_add (trail_to_new_predecessor_id,
4278 trail_to_new_predecessor[trail_length - 1],
4281 GNUNET_assert (NULL != (target_friend =
4282 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4283 &trail_to_new_predecessor[trail_length - 1])));
4286 /* Add entry in routing table of all peers that are part of trail from me
4287 to finger, including finger. */
4288 GDS_NEIGHBOURS_send_add_trail (my_identity,
4290 trail_to_new_predecessor_id,
4291 trail_to_new_predecessor,
4295 add_new_finger (finger, trail_to_new_predecessor, trail_length,
4296 trail_to_new_predecessor_id, PREDECESSOR_FINGER_ID);
4297 GNUNET_free_non_null (trail_to_new_predecessor);
4301 /* 3. In case you are successor, then
4302 * 3.1 check if you have a predecessor
4303 * 3.2 if no predecessor, then add the source of this message as your
4304 * predecessor. To add, first you should generate a new trail id,
4305 * invert the trail, send add trail message across new trail, add
4306 * an entry in finger table. Now, destination also have routing
4307 * table entry so add in your routing table also.
4308 * 3.3 If its closer than existing one, then do everything in step 1 and
4309 * free existing finger.
4310 * 3.3 If its same as the old one, then do nothing.
4311 * 3.4 if its not same as old one, and between source and old one, old one
4312 * is the correct predecessor, then construct a trail from source
4313 * to your old successor. scan the trail to remove duplicate entries.
4314 * 4. send verify successor result, with trail id of trail from source to
4315 * me. And also send the new trail from source to reach to its probable
4318 * 1. this function is called from both verify and notify.
4319 * 2. so write in a way that it is used in both.
4322 * Check if you have a predecessor.
4323 * 1. if no predecessor, then add finger as your predecessor. To add, first
4324 * generate a new trail id, invert the trail to get the trail from me to finger,
4325 * add an entry in your routing table, send add trail message to peers which
4326 * are part of trail from me to finger and add finger in finger table.
4327 * 2. If there is a predecessor, then compare existing one and finger.
4328 * 2.1 If finger is correct predecessor, then remove current_predecessor. And
4329 * do everything in step 1 to add finger into finger table.
4330 * 2.2 If current_predecessor is correct predecessor, the construct a trail from
4331 * finger to current_predecessor.
4334 * @param trail_length
4338 compare_and_update_predecessor (struct GNUNET_PeerIdentity finger,
4339 struct GNUNET_PeerIdentity *trail,
4340 unsigned int trail_length)
4342 struct FingerInfo *current_predecessor;
4343 struct GNUNET_PeerIdentity *closest_peer;
4344 uint64_t predecessor_value;
4345 unsigned int is_predecessor = 1;
4347 current_predecessor = &finger_table[PREDECESSOR_FINGER_ID];
4349 GNUNET_assert (0 != GNUNET_CRYPTO_cmp_peer_identity (&finger, &my_identity));
4351 /* No predecessor. Add finger as your predecessor. */
4352 if (GNUNET_NO == current_predecessor->is_present)
4354 update_predecessor (finger, trail, trail_length);
4358 predecessor_value = compute_finger_identity_value (PREDECESSOR_FINGER_ID);
4359 closest_peer = select_closest_peer (&finger,
4360 ¤t_predecessor->finger_identity,
4361 predecessor_value, is_predecessor);
4363 /* Finger is the closest predecessor. Remove the existing one and add the new
4365 if (0 == GNUNET_CRYPTO_cmp_peer_identity (closest_peer, &finger))
4367 remove_existing_finger (current_predecessor, PREDECESSOR_FINGER_ID);
4368 update_predecessor (finger, trail, trail_length);
4377 * FIXME: if i have no predecessor and I get a new predecessor but the first
4378 * friend to reach to that hop is congested then?
4379 * 1. check if you are the successor or not.
4380 * 2. if not then get the next hop from routing table, and pass the message,
4381 * 3. In case you are successor, then
4382 * 3.1 check if you have a predecessor
4383 * 3.2 if no predecessor, then add the source of this message as your
4384 * predecessor. To add, first you should generate a new trail id,
4385 * invert the trail, send add trail message across new trail, add
4386 * an entry in finger table. Now, destination also have routing
4387 * table entry so add in your routing table also.
4388 * 3.3 If its closer than existing one, then do everything in step 1 and
4389 * free existing finger.
4390 * 3.3 If its same as the old one, then do nothing.
4391 * 3.4 if its not same as old one, and between source and old one, old one
4392 * is the correct predecessor, then choose the shortest path to reach
4393 * from you to your predecessor. Pass this trail to source of this message.
4394 * It is the responsibility of source peer to scan the trail to reach to
4395 * its new probable successor.
4396 * 4. send verify successor result, with trail id of trail from source to
4397 * me. And also send the trail from me to reach to my predecessor, if
4398 * my_predecessor != source.
4400 * Core handle for p2p verify successor messages.
4401 * @param cls closure
4402 * @param message message
4403 * @param peer peer identity this notification is about
4404 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4407 handle_dht_p2p_verify_successor(void *cls,
4408 const struct GNUNET_PeerIdentity *peer,
4409 const struct GNUNET_MessageHeader *message)
4411 const struct PeerVerifySuccessorMessage *vsm;
4412 struct GNUNET_HashCode trail_id;
4413 struct GNUNET_PeerIdentity successor;
4414 struct GNUNET_PeerIdentity source_peer;
4415 struct GNUNET_PeerIdentity *trail;
4416 struct GNUNET_PeerIdentity *next_hop;
4417 struct GNUNET_PeerIdentity *trail_to_predecessor;
4418 struct FingerInfo *current_predecessor;
4419 struct FriendInfo *target_friend;
4420 unsigned int trail_to_predecessor_length;
4422 unsigned int trail_length;
4424 msize = ntohs (message->size);
4426 /* Here we pass trail to reach from source to successor, and in case successor
4427 * does not have any predecessor, then we will add source as my predecessor.
4428 * So we pass the trail along with trail id. */
4429 if (msize < sizeof (struct PeerVerifySuccessorMessage))
4431 GNUNET_break_op (0);
4435 vsm = (const struct PeerVerifySuccessorMessage *) message;
4436 trail_length = (msize - sizeof (struct PeerVerifySuccessorMessage))/
4437 sizeof (struct GNUNET_PeerIdentity);
4438 if ((msize - sizeof (struct PeerVerifySuccessorMessage)) %
4439 sizeof (struct GNUNET_PeerIdentity) != 0)
4441 GNUNET_break_op (0);
4445 trail_id = vsm->trail_id;
4446 source_peer = vsm->source_peer;
4447 successor = vsm->successor;
4448 trail = (struct GNUNET_PeerIdentity *)&vsm[1];
4450 //FIXME: we can have a check if peer is correct peer which should have
4451 // sent this message. use same function is_sender_peer_correct
4452 // but specify direction so that the function can be used in other functions
4455 /* I am not the successor of source_peer. Pass the message to next_hop on
4457 if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&successor, &my_identity)))
4459 next_hop = GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST);
4460 if (NULL == next_hop)
4463 return GNUNET_SYSERR;
4465 GNUNET_assert (NULL !=
4467 GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop)));
4469 GDS_NEIGHBOURS_send_verify_successor_message (source_peer, successor,
4470 trail_id, trail, trail_length,
4475 /* I am the destination of this message. */
4477 /* Check if the source_peer could be our predecessor and if yes then update
4479 compare_and_update_predecessor (source_peer, trail, trail_length);
4481 current_predecessor = &finger_table[PREDECESSOR_FINGER_ID];
4483 /* Is source of this message NOT my predecessor. */
4484 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_predecessor->finger_identity,
4487 /* if current predecessor is not a friend, we have a trail to reach to it*/
4488 if (NULL == (GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4489 ¤t_predecessor->finger_identity)))
4491 trail_to_predecessor =
4492 trail_source_to_my_predecessor (trail,
4494 &trail_to_predecessor_length);
4499 trail_to_predecessor = NULL;
4500 trail_to_predecessor_length = 0;
4502 GNUNET_assert (NULL !=
4504 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer)));
4505 GDS_NEIGHBOURS_send_verify_successor_result (source_peer, my_identity,
4506 current_predecessor->finger_identity,
4507 trail_id, trail_to_predecessor,
4508 trail_to_predecessor_length,
4509 GDS_ROUTING_DEST_TO_SRC,
4511 GNUNET_free_non_null (trail_to_predecessor);
4517 * Construct the trail from me to probable successor that goes through current
4518 * successor. Scan this trail to check if you can shortcut the trail somehow.
4519 * In case we can shortcut the trail, don't send trail compression as we don't
4520 * have any entry in routing table.
4521 * @param current_successor
4522 * @param probable_successor
4523 * @param trail_from_curr_to_probable_successor
4524 * @param trail_from_curr_to_probable_successor_length
4525 * @param trail_to_new_successor_length
4528 static struct GNUNET_PeerIdentity *
4529 get_trail_to_new_successor (struct FingerInfo *current_successor,
4530 struct GNUNET_PeerIdentity probable_successor,
4531 const struct GNUNET_PeerIdentity *trail,
4532 unsigned int trail_length,
4533 unsigned int *trail_to_new_successor_length)
4535 struct GNUNET_PeerIdentity *trail_to_new_successor;
4537 /* If the probable successor is a friend, then we don't need to have a trail
4539 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4540 &probable_successor))
4542 trail_to_new_successor = NULL;
4543 *trail_to_new_successor_length = 0;
4544 return trail_to_new_successor;
4548 * FIXME: can we some how use the select_finger_trail here??
4549 * complete this logic.
4550 * 1. Choose the shortest trail to reach to current successor.
4551 * 2. append the trail with the current trail
4552 * 3. scan the trail for duplicate elements
4553 * 4. scan the trail for friend
4554 * 5. get the shortest trail.
4555 * 6. send back the trail.
4562 * Compare probable successor and current successor.
4563 * If the probable successor is the correct successor, then construct the trail
4564 * from me to probable successor that goes through current successor. Scan this
4565 * trail to check if you can shortcut the trail somehow. In case we can short
4566 * cut the trail, don't send trail compression as we don't have any entry in
4568 * Once you have scanned trail, then add an entry in finger table.
4569 * Add an entry in routing table (Only if new successor is NOT a friend).
4570 * @param probable_successor Peer which could be our successor
4571 * @param trail_from_curr_to_probable_successor Trail from current successor
4572 * to probable successor, NOT
4574 * @param trail_from_curr_to_probable_successor_length Total number of peers
4575 * in @a trail_from_curr_to_probable_successor
4578 compare_and_update_successor (struct GNUNET_PeerIdentity probable_successor,
4579 const struct GNUNET_PeerIdentity *trail_from_curr_to_probable_successor,
4580 unsigned int trail_from_curr_to_probable_successor_length)
4582 struct GNUNET_PeerIdentity *closest_peer;
4583 struct GNUNET_PeerIdentity *trail_to_new_successor;
4584 struct GNUNET_HashCode trail_id;
4585 unsigned int trail_to_new_successor_length;
4586 uint64_t successor_value;
4587 struct FingerInfo *current_successor;
4588 struct FriendInfo *target_friend;
4589 unsigned int is_predecessor = 0;
4591 current_successor = &finger_table[0];
4592 GNUNET_assert (GNUNET_YES == current_successor->is_present);
4594 /* Compute the 64 bit value of successor identity. We need this as we need to
4595 * find the closest peer w.r.t this value.*/
4596 successor_value = compute_finger_identity_value (0);
4597 closest_peer = select_closest_peer (¤t_successor->finger_identity,
4598 &probable_successor,
4599 successor_value, is_predecessor);
4601 /* If the current_successor is the closest one, then exit. */
4602 if (0 == GNUNET_CRYPTO_cmp_peer_identity (closest_peer,
4603 ¤t_successor->finger_identity))
4606 /* probable successor is the closest_peer. */
4608 /* Get the trail to reach to your new successor. */
4609 trail_to_new_successor = get_trail_to_new_successor (current_successor,
4611 trail_from_curr_to_probable_successor,
4612 trail_from_curr_to_probable_successor_length,
4613 &trail_to_new_successor_length);
4614 /* Remove the existing successor. */
4615 remove_existing_finger (current_successor, 0);
4617 /* Generate a new trail id to reach to your new successor. */
4618 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
4619 &trail_id, sizeof (trail_id));
4620 add_new_finger (probable_successor, trail_to_new_successor,
4621 trail_to_new_successor_length, trail_id, 0);
4623 /* If probable successor is not a friend, then add an entry in your own
4625 if (trail_to_new_successor_length > 0)
4627 /* FIXME: check that you always add trail entry even if your finger is
4629 GDS_ROUTING_add (trail_id, my_identity, trail_to_new_successor[0]);
4630 GNUNET_assert (NULL !=
4631 (target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4632 &trail_to_new_successor[0])));
4636 /* FIXME: check that you always add trail entry even if your finger is
4638 GDS_ROUTING_add (trail_id, my_identity, probable_successor);
4639 GNUNET_assert (NULL !=
4641 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4642 &probable_successor)));
4645 GDS_NEIGHBOURS_send_notify_new_successor (my_identity, probable_successor,
4646 trail_from_curr_to_probable_successor,
4647 trail_from_curr_to_probable_successor_length,
4655 * 1. If you are not the querying peer then pass on the message,
4656 * 2. If you are querying peer, then
4657 * 2.1 is new successor same as old one
4658 * 2.1.1 if yes then do noting
4659 * 2.1.2 if no then you need to notify the new one about your existence,
4660 * 2.1.2,1 also you need to remove the older successor, remove entry
4661 * from finger table, send trail teardown message across all the trail
4662 * of older successor. Call notify new successor with new trail id
4663 * and new trail to reach it.
4664 * Core handle for p2p verify successor result messages.
4665 * @param cls closure
4666 * @param message message
4667 * @param peer peer identity this notification is about
4668 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4671 handle_dht_p2p_verify_successor_result(void *cls,
4672 const struct GNUNET_PeerIdentity *peer,
4673 const struct GNUNET_MessageHeader *message)
4675 const struct PeerVerifySuccessorResultMessage *vsrm;
4676 enum GDS_ROUTING_trail_direction trail_direction;
4677 struct GNUNET_PeerIdentity querying_peer;
4678 struct GNUNET_HashCode trail_id;
4679 struct GNUNET_PeerIdentity *next_hop;
4680 struct FriendInfo *target_friend;
4681 struct GNUNET_PeerIdentity probable_successor;
4682 const struct GNUNET_PeerIdentity *trail;
4683 unsigned int trail_length;
4686 msize = ntohs (message->size);
4687 /* We send a trail to reach from old successor to new successor, if
4688 * old_successor != new_successor.*/
4689 if (msize < sizeof (struct PeerVerifySuccessorResultMessage))
4691 GNUNET_break_op (0);
4695 vsrm = (const struct PeerVerifySuccessorResultMessage *) message;
4696 trail_length = (msize - sizeof (struct PeerVerifySuccessorResultMessage))/
4697 sizeof (struct GNUNET_PeerIdentity);
4699 if ((msize - sizeof (struct PeerVerifySuccessorResultMessage)) %
4700 sizeof (struct GNUNET_PeerIdentity) != 0)
4702 GNUNET_break_op (0);
4706 trail = (const struct GNUNET_PeerIdentity *) &vsrm[1];
4707 querying_peer = vsrm->querying_peer;
4708 trail_direction = ntohl (vsrm->trail_direction);
4709 trail_id = vsrm->trail_id;
4710 probable_successor = vsrm->probable_successor;
4712 //FIXME: add a check to ensure that peer from which you got the message is
4714 /* I am the querying_peer. */
4715 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&querying_peer, &my_identity)))
4717 compare_and_update_successor (probable_successor, trail, trail_length);
4721 /*If you are not the querying peer then pass on the message */
4722 GNUNET_assert (NULL != (next_hop =
4723 GDS_ROUTING_get_next_hop (trail_id, trail_direction)));
4724 GNUNET_assert (NULL !=
4726 GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop)));
4727 GDS_NEIGHBOURS_send_verify_successor_result (querying_peer,
4728 vsrm->current_successor,
4729 probable_successor, trail_id,
4732 trail_direction, target_friend);
4738 * Add entry in your routing table if source of the message is not a friend.
4739 * Irrespective if destination peer accepts source peer as predecessor or not,
4740 * we need to add an entry. So, that in next round to verify successor, source
4741 * is able to reach to its successor.
4742 * Check if you are the new successor of this message
4743 * 1. If yes the call function compare_and_update_successor(). This function
4744 * checks if source is real predecessor or not and take action accordingly.
4745 * 2. If not then find the next hop to find the message from the trail that
4746 * you got from the message and pass on the message.
4747 * Core handle for p2p notify new successor messages.
4748 * @param cls closure
4749 * @param message message
4750 * @param peer peer identity this notification is about
4751 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4754 handle_dht_p2p_notify_new_successor(void *cls,
4755 const struct GNUNET_PeerIdentity *peer,
4756 const struct GNUNET_MessageHeader *message)
4758 const struct PeerNotifyNewSuccessorMessage *nsm;
4759 struct GNUNET_PeerIdentity *trail;
4760 struct GNUNET_PeerIdentity source;
4761 struct GNUNET_PeerIdentity new_successor;
4762 struct GNUNET_HashCode trail_id;
4763 struct GNUNET_PeerIdentity next_hop;
4764 struct FriendInfo *target_friend;
4767 uint32_t trail_length;
4769 msize = ntohs (message->size);
4770 /* We have the trail to reach from source to new successor. */
4771 if (msize < sizeof (struct PeerNotifyNewSuccessorMessage))
4773 GNUNET_break_op (0);
4777 nsm = (const struct PeerNotifyNewSuccessorMessage *) message;
4778 trail_length = (msize - sizeof (struct PeerNotifyNewSuccessorMessage))/
4779 sizeof (struct GNUNET_PeerIdentity);
4780 if ((msize - sizeof (struct PeerTrailRejectionMessage)) %
4781 sizeof (struct GNUNET_PeerIdentity) != 0)
4783 GNUNET_break_op (0);
4787 trail = (struct GNUNET_PeerIdentity *) &nsm[1];
4788 source = nsm->source_peer;
4789 new_successor = nsm->new_successor;
4790 trail_id = nsm->trail_id;
4792 //FIXME: add a check to make sure peer is correct.
4794 /* I am the new_successor to source_peer. */
4795 if ( 0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &new_successor))
4797 GDS_ROUTING_add (trail_id, *peer, my_identity);
4798 compare_and_update_predecessor (source, trail, trail_length);
4802 /* I am part of trail to reach to successor. */
4803 my_index = search_my_index (trail, trail_length);
4806 GNUNET_break_op (0);
4807 return GNUNET_SYSERR;
4809 if (trail_length == my_index)
4810 next_hop = new_successor;
4812 next_hop = trail[my_index + 1];
4814 /* Add an entry in routing table for trail from source to its new successor. */
4815 GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, *peer, next_hop));
4816 GNUNET_assert (NULL !=
4818 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop)));
4819 GDS_NEIGHBOURS_send_notify_new_successor (source, new_successor, trail,
4821 trail_id, target_friend);
4828 * 1. Set the congestion timeout for the friend which is congested and sent
4830 * 2. Check if you were the source of this message
4831 * 2.1 If yes then exit. find_finger_trail_task is scheduled periodically.
4832 * So, we will eventually send a new request to setup trail to finger.
4833 * 2. Check if you can handle more trails through you. (Routing table space)
4834 * 2.1 If not then you are congested. Set your congestion time and pass this
4835 * message to peer before you in the trail setup so far.
4836 * 2.2 If yes, the call find_successor(). It will give you the next hop to
4837 * pass this message.
4838 * 2.2.1 If you are the final destination, then send back the trail setup
4840 * 2.2.2 If you are not the final dest, then send trail setup message to
4842 * Core handler for P2P trail rejection message
4843 * @param cls closure
4844 * @param message message
4845 * @param peer peer identity this notification is about
4846 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4849 handle_dht_p2p_trail_setup_rejection (void *cls,
4850 const struct GNUNET_PeerIdentity *peer,
4851 const struct GNUNET_MessageHeader *message)
4853 const struct PeerTrailRejectionMessage *trail_rejection;
4854 unsigned int trail_length;
4855 const struct GNUNET_PeerIdentity *trail_peer_list;
4856 struct FriendInfo *target_friend;
4857 struct GNUNET_TIME_Relative congestion_timeout;
4858 struct GNUNET_HashCode trail_id;
4859 struct GNUNET_PeerIdentity next_destination;
4860 struct GNUNET_HashCode new_intermediate_trail_id;
4861 struct GNUNET_PeerIdentity next_peer;
4862 struct GNUNET_PeerIdentity source;
4863 struct GNUNET_PeerIdentity *next_hop;
4864 uint64_t ultimate_destination_finger_value;
4865 unsigned int is_predecessor;
4868 msize = ntohs (message->size);
4869 /* We are passing the trail setup so far. */
4870 if (msize < sizeof (struct PeerTrailRejectionMessage))
4872 GNUNET_break_op (0);
4876 trail_rejection = (const struct PeerTrailRejectionMessage *) message;
4877 trail_length = (msize - sizeof (struct PeerTrailRejectionMessage))/
4878 sizeof (struct GNUNET_PeerIdentity);
4879 if ((msize - sizeof (struct PeerTrailRejectionMessage)) %
4880 sizeof (struct GNUNET_PeerIdentity) != 0)
4882 GNUNET_break_op (0);
4886 trail_peer_list = (const struct GNUNET_PeerIdentity *)&trail_rejection[1];
4887 is_predecessor = ntohl (trail_rejection->is_predecessor);
4888 congestion_timeout = trail_rejection->congestion_time;
4889 source = trail_rejection->source_peer;
4890 trail_id = trail_rejection->trail_id;
4891 ultimate_destination_finger_value =
4892 GNUNET_ntohll (trail_rejection->ultimate_destination_finger_value);
4894 /* First set the congestion time of the friend that sent you this message. */
4895 GNUNET_assert (NULL !=
4897 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer)));
4898 target_friend->congestion_timestamp =
4899 GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(),
4900 congestion_timeout);
4902 /* I am the source peer which wants to setup the trail. Do nothing.
4903 * send_find_finger_trail_task is scheduled periodically.*/
4904 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &source)))
4907 /* If I am congested then pass this message to peer before me in trail. */
4908 if(GNUNET_YES == GDS_ROUTING_threshold_reached())
4910 struct GNUNET_PeerIdentity *new_trail;
4911 unsigned int new_trail_length;
4913 /* Remove yourself from the trail setup so far. */
4914 if (trail_length == 1)
4917 new_trail_length = 0;
4922 memcpy (&next_hop , &trail_peer_list[trail_length - 2],
4923 sizeof (struct GNUNET_PeerIdentity));
4925 /* Remove myself from the trail. */
4926 new_trail_length = trail_length -1;
4927 new_trail = GNUNET_malloc (new_trail_length * sizeof (struct GNUNET_PeerIdentity));
4928 memcpy (new_trail, trail_peer_list, new_trail_length * sizeof (struct GNUNET_PeerIdentity));
4931 GNUNET_assert (NULL !=
4933 GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop)));
4934 GDS_NEIGHBOURS_send_trail_rejection (source,
4935 ultimate_destination_finger_value,
4936 my_identity, is_predecessor,
4937 new_trail,new_trail_length,trail_id,
4938 target_friend, CONGESTION_TIMEOUT);
4939 GNUNET_free (new_trail);
4943 /* Look for next_hop to pass the trail setup message */
4944 next_hop = find_successor (ultimate_destination_finger_value,
4946 &new_intermediate_trail_id,
4949 /* Am I the final destination? */
4950 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (next_hop, &my_identity)))
4952 /* Add an entry in routing table only
4953 * 1. If I am not the original source which sent the request for trail setup
4954 FIXME: check that you always add trail entry even if your finger is
4956 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&source, &my_identity))
4957 GNUNET_assert (GNUNET_YES == GDS_ROUTING_add (trail_id, *peer, my_identity));
4959 if (0 == trail_length)
4962 next_peer = trail_peer_list[trail_length-1];
4964 GNUNET_assert (NULL !=
4966 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer)));
4967 GDS_NEIGHBOURS_send_trail_setup_result (source,
4969 target_friend, trail_length,
4972 ultimate_destination_finger_value,
4977 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
4979 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
4980 peer_list[trail_length] = my_identity;
4982 GNUNET_assert (NULL !=
4984 GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop)));
4985 GDS_NEIGHBOURS_send_trail_setup (source,
4986 ultimate_destination_finger_value,
4988 target_friend, trail_length + 1, peer_list,
4989 is_predecessor, trail_id,
4990 &new_intermediate_trail_id);
4992 GNUNET_free (next_hop);
4998 * If you are the new first friend, then update prev hop to source of this message
4999 * else get the next hop and pass this message forward to ultimately reach
5001 * Core handle for p2p trail tear compression messages.
5002 * @param cls closure
5003 * @param message message
5004 * @param peer peer identity this notification is about
5005 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5008 handle_dht_p2p_trail_compression (void *cls, const struct GNUNET_PeerIdentity *peer,
5009 const struct GNUNET_MessageHeader *message)
5011 const struct PeerTrailCompressionMessage *trail_compression;
5012 struct GNUNET_PeerIdentity *next_hop;
5013 struct FriendInfo *target_friend;
5014 struct GNUNET_HashCode trail_id;
5017 msize = ntohs (message->size);
5018 /* Here we pass only the trail id. */
5019 if (msize != sizeof (struct PeerTrailCompressionMessage))
5021 GNUNET_break_op (0);
5025 trail_compression = (const struct PeerTrailCompressionMessage *) message;
5026 trail_id = trail_compression->trail_id;
5027 //FIXME: again check if peer is the correct peer. same logic as
5028 //trail teardown make a generic function.
5030 /* Am I the new first friend to reach to finger of this trail. */
5031 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&trail_compression->new_first_friend,
5034 GNUNET_assert (NULL !=
5035 (GNUNET_CONTAINER_multipeermap_get (friend_peermap,
5036 &trail_compression->source_peer)));
5037 /* Update your prev hop to source of this message. */
5038 GNUNET_assert (GNUNET_SYSERR !=
5039 (GDS_ROUTING_update_trail_prev_hop (trail_id,
5040 trail_compression->source_peer)));
5044 /* Pass the message to next hop to finally reach to new_first_friend. */
5045 /* FIXME THIS FAILS.*/
5046 next_hop = GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST);
5047 if (NULL == next_hop)
5053 GNUNET_assert (NULL !=
5055 GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop)));
5057 GDS_ROUTING_remove_trail (trail_id);
5059 GDS_NEIGHBOURS_send_trail_compression (trail_compression->source_peer,
5061 trail_compression->new_first_friend,
5068 * Remove entry from your own routing table and pass the message to next
5069 * peer in the trail.
5070 * Core handler for trail teardown message.
5071 * @param cls closure
5072 * @param message message
5073 * @param peer sender of this messsage.
5074 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5077 handle_dht_p2p_trail_teardown (void *cls, const struct GNUNET_PeerIdentity *peer,
5078 const struct GNUNET_MessageHeader *message)
5080 const struct PeerTrailTearDownMessage *trail_teardown;
5081 enum GDS_ROUTING_trail_direction trail_direction;
5082 struct GNUNET_HashCode trail_id;
5083 struct GNUNET_PeerIdentity *next_hop;
5086 msize = ntohs (message->size);
5088 /* Here we pass only the trail id. */
5089 if (msize != sizeof (struct PeerTrailTearDownMessage))
5091 GNUNET_break_op (0);
5095 trail_teardown = (const struct PeerTrailTearDownMessage *) message;
5096 trail_direction = ntohl (trail_teardown->trail_direction);
5097 trail_id = trail_teardown->trail_id;
5099 /* Check if peer is the real peer from which we should get this message.*/
5100 /* Get the prev_hop for this trail by getting the next hop in opposite direction. */
5101 /* FIXME: is using negation of trail direction correct. */
5103 GNUNET_assert (NULL != (prev_hop =
5104 GDS_ROUTING_get_next_hop (trail_id, !trail_direction)));
5105 if (0 != GNUNET_CRYPTO_cmp_peer_identity (prev_hop, peer))
5108 return GNUNET_SYSERR;
5112 next_hop = GDS_ROUTING_get_next_hop (trail_id, trail_direction);
5114 if (NULL == next_hop)
5117 return GNUNET_SYSERR;
5120 /* I am the next hop, which means I am the final destination. */
5121 if (0 == GNUNET_CRYPTO_cmp_peer_identity (next_hop, &my_identity))
5123 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id));
5128 /* If not final destination, then send a trail teardown message to next hop.*/
5129 GNUNET_assert (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop));
5130 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id));
5131 GDS_NEIGHBOURS_send_trail_teardown (trail_id, trail_direction, *next_hop);
5139 * Add an entry in your routing table. If you are destination of this message
5140 * then next_hop in routing table should be your own identity. If you are NOT
5141 * destination, then get the next hop and forward message to it.
5142 * Core handle for p2p add trail message.
5143 * @param cls closure
5144 * @param message message
5145 * @param peer peer identity this notification is about
5146 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5149 handle_dht_p2p_add_trail (void *cls, const struct GNUNET_PeerIdentity *peer,
5150 const struct GNUNET_MessageHeader *message)
5152 const struct PeerAddTrailMessage *add_trail;
5153 const struct GNUNET_PeerIdentity *trail;
5154 struct GNUNET_HashCode trail_id;
5155 struct GNUNET_PeerIdentity destination_peer;
5156 struct GNUNET_PeerIdentity source_peer;
5157 struct GNUNET_PeerIdentity next_hop;
5158 unsigned int trail_length;
5159 unsigned int my_index;
5162 msize = ntohs (message->size);
5163 /* In this message we pass the whole trail from source to destination as we
5164 * are adding that trail.*/
5165 if (msize < sizeof (struct PeerAddTrailMessage))
5167 GNUNET_break_op (0);
5171 add_trail = (const struct PeerAddTrailMessage *) message;
5172 trail_length = (msize - sizeof (struct PeerAddTrailMessage))/
5173 sizeof (struct GNUNET_PeerIdentity);
5174 if ((msize - sizeof (struct PeerAddTrailMessage)) %
5175 sizeof (struct GNUNET_PeerIdentity) != 0)
5177 GNUNET_break_op (0);
5181 trail = (const struct GNUNET_PeerIdentity *)&add_trail[1];
5182 destination_peer = add_trail->destination_peer;
5183 source_peer = add_trail->source_peer;
5184 trail_id = add_trail->trail_id;
5186 //FIXME: add a check that sender peer is not malicious. Make it a generic
5187 // function so that it can be used in all other functions where we need the
5188 // same functionality.
5190 /* I am not the destination of the trail. */
5191 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &destination_peer))
5193 struct FriendInfo *target_friend;
5195 /* Get my location in the trail. */
5196 my_index = search_my_index (trail, trail_length);
5199 GNUNET_break_op (0);
5200 return GNUNET_SYSERR;
5204 next_hop = source_peer;
5206 next_hop = trail[trail_length - 1];
5207 /* FIXME: check that you always add trail entry even if your finger is
5209 /* Add in your routing table. */
5210 GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, next_hop, *peer));
5211 GNUNET_assert (NULL !=
5213 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop)));
5214 GDS_NEIGHBOURS_send_add_trail (source_peer, destination_peer, trail_id,
5215 trail, trail_length, target_friend);
5218 /* FIXME: check that you always add trail entry even if your finger is
5220 /* I am the destination. Add an entry in routing table. */
5221 GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, *peer, my_identity));
5227 * Free the finger trail in which the first friend to reach to a finger is
5228 * disconnected_friend. Also remove entry from routing table for that particular
5230 * @param disconnected_friend PeerIdentity of friend which got disconnected
5231 * @param remove_finger Finger whose trail we need to check if it has
5232 * disconnected_friend as the first hop.
5233 * @return Total number of trails in which disconnected_friend was the first
5237 remove_matching_trails (const struct GNUNET_PeerIdentity *disconnected_friend,
5238 struct FingerInfo *remove_finger)
5240 unsigned int matching_trails_count;
5243 /* Number of trails with disconnected_friend as the first hop in the trail
5244 * to reach from me to remove_finger, NOT including endpoints. */
5245 matching_trails_count = 0;
5247 /* Iterate over all the trails of finger. */
5248 for (i = 0; i < remove_finger->trails_count; i++)
5250 struct Trail *trail;
5251 trail = &remove_finger->trail_list[i];
5253 if (GNUNET_NO == trail->is_present)
5256 /*FIXME: This is here to ensure that no finger which is a friend should ever call this
5257 function. remove afterwards.*/
5258 GNUNET_assert (trail->trail_length > 0);
5260 /* First friend to reach to finger is disconnected_peer. */
5261 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&trail->trail_head->peer,
5262 disconnected_friend))
5264 struct GNUNET_PeerIdentity *next_hop;
5265 struct FriendInfo *remove_friend;
5267 GNUNET_assert (NULL !=
5269 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
5270 disconnected_friend)));
5271 remove_friend->trails_count--;
5272 next_hop = GDS_ROUTING_get_next_hop (trail->trail_id, GDS_ROUTING_SRC_TO_DEST);
5274 /* Here it may happen that as all the peers got disconnected, the entry in
5275 routing table for that particular trail has been removed, because the
5276 previously disconnected peer was either a next hop or prev hop of that
5278 if (NULL == next_hop)
5281 GNUNET_assert (0 == (GNUNET_CRYPTO_cmp_peer_identity (disconnected_friend,
5283 matching_trails_count++;
5284 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail->trail_id));
5287 trail->is_present = GNUNET_NO;
5290 return matching_trails_count;
5295 * Iterate over finger_table entries.
5296 * 0. Ignore finger which is my_identity or if no valid entry present at
5297 * that finger index.
5298 * 1. If disconnected_friend is a finger, then remove the routing entry from
5299 your own table. Free the trail.
5300 * 2. Check if disconnected_friend is the first friend in the trail to reach to a finger.
5301 * 2.1 Remove all the trails and entry from routing table in which disconnected
5302 * friend is the first friend in the trail. If disconnected_friend is the
5303 * first friend in all the trails to reach finger, then remove the finger.
5304 * @param disconnected_friend Peer identity of friend which got disconnected.
5307 remove_matching_fingers (const struct GNUNET_PeerIdentity *disconnected_peer)
5309 struct FingerInfo *remove_finger;
5310 struct FriendInfo *remove_friend;
5311 int removed_trails_count;
5314 //test_finger_table_print();
5316 /* Iterate over finger table entries. */
5317 for (i = 0; i < MAX_FINGERS; i++)
5319 remove_finger = &finger_table[i];
5321 /* No finger stored at this trail index. */
5322 if (GNUNET_NO == remove_finger->is_present)
5325 /* I am my own finger, then ignore this finger. */
5326 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&remove_finger->finger_identity,
5330 /* Is disconnected_peer a finger? */
5331 if (0 == GNUNET_CRYPTO_cmp_peer_identity (disconnected_peer,
5332 &remove_finger->finger_identity))
5334 struct GNUNET_PeerIdentity *next_hop;
5335 struct GNUNET_HashCode trail_id;
5338 GNUNET_assert (GNUNET_YES == (remove_finger->trail_list[0].is_present));
5339 /* FIXME: I am adding this check just to ensure that for a finger which
5340 is also a friend, we are storing only one trail and not more. REMOVE
5342 GNUNET_assert (1 == remove_finger->trails_count);
5343 trail_id = remove_finger->trail_list[0].trail_id;
5345 /* FIXME: This assertion fails. Check why. */
5349 GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST)))
5351 /* As finger is a friend, you have no trail as such but you have entry in routing
5352 * table of source and dest, so next_hop will be same as finger identity. */
5354 (GNUNET_CRYPTO_cmp_peer_identity (next_hop,
5355 &remove_finger->finger_identity)));
5356 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id));
5357 GNUNET_assert (NULL !=
5359 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
5360 disconnected_peer)));
5363 remove_finger->trail_list[0].is_present = GNUNET_NO;
5364 remove_friend->trails_count--;
5365 remove_finger->is_present = GNUNET_NO;
5366 memset ((void *)&finger_table[i], 0, sizeof (finger_table[i]));
5370 /* If finger is a friend but not disconnected_friend, then continue. */
5371 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap,
5372 &remove_finger->finger_identity))
5375 /* Iterate over the list of trails to reach remove_finger. Check if
5376 * disconnected_friend makis the first friend in any of the trail. */
5377 removed_trails_count = remove_matching_trails (disconnected_peer,
5380 /* All the finger trails had disconnected_friend as the first friend,
5381 * so free the finger. */
5382 if (removed_trails_count == remove_finger->trails_count)
5384 remove_finger->is_present = GNUNET_NO;
5385 memset ((void *)&finger_table[i], 0, sizeof (finger_table[i]));
5392 * Method called whenever a peer disconnects.
5394 * @param cls closure
5395 * @param peer peer identity this notification is about
5398 handle_core_disconnect (void *cls,
5399 const struct GNUNET_PeerIdentity *peer)
5401 struct FriendInfo *remove_friend;
5403 /* If disconnected to own identity, then return. */
5404 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
5407 GNUNET_assert (NULL != (remove_friend =
5408 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer)));
5410 /* Remove fingers with peer as first friend or if peer is a finger. */
5411 remove_matching_fingers (peer);
5413 /* Remove any trail from routing table of which peer is a part of. This function
5414 * internally sends a trail teardown message in the direction of which
5415 * disconnected peer is not part of. */
5416 GNUNET_assert (GNUNET_SYSERR != GDS_ROUTING_remove_trail_by_peer (peer));
5418 //GNUNET_assert (0 == remove_friend->trails_count);
5420 /* Remove peer from friend_peermap. */
5421 GNUNET_assert (GNUNET_YES ==
5422 GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
5426 if (0 != GNUNET_CONTAINER_multipeermap_size (friend_peermap))
5429 /* If there are no more friends in friend_peermap, then don't schedule
5430 * find_finger_trail_task. */
5431 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
5433 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
5434 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
5443 * Method called whenever a peer connects.
5445 * @param cls closure
5446 * @param peer_identity peer identity this notification is about
5449 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity)
5451 struct FriendInfo *friend;
5453 /* Check for connect to self message */
5454 if (0 == memcmp (&my_identity, peer_identity, sizeof (struct GNUNET_PeerIdentity)))
5457 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to %s\n", GNUNET_i2s (peer_identity));
5459 /* If peer already exists in our friend_peermap, then exit. */
5460 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (friend_peermap,
5467 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
5470 friend = GNUNET_new (struct FriendInfo);
5471 friend->id = *peer_identity;
5473 GNUNET_assert (GNUNET_OK ==
5474 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
5475 peer_identity, friend,
5476 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
5479 /* got a first connection, good time to start with FIND FINGER TRAIL requests...*/
5480 if (GNUNET_SCHEDULER_NO_TASK == find_finger_trail_task)
5481 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
5486 * To be called on core init/fail.
5488 * @param cls service closure
5489 * @param identity the public identity of this peer
5492 core_init (void *cls,
5493 const struct GNUNET_PeerIdentity *identity)
5495 my_identity = *identity;
5496 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5497 "my_indentity = %s\n",GNUNET_i2s(&my_identity));
5502 * Initialize finger table entries.
5505 finger_table_init ()
5510 for(i = 0; i < MAX_FINGERS; i++)
5512 finger_table[i].is_present = GNUNET_NO;
5513 for (j = 0; j < MAXIMUM_TRAILS_PER_FINGER; j++)
5514 finger_table[i].trail_list[j].is_present = GNUNET_NO;
5515 memset ((void *)&finger_table[i], 0, sizeof (finger_table[i]));
5521 * Initialize neighbours subsystem.
5522 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5525 GDS_NEIGHBOURS_init (void)
5527 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
5528 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_XDHT_P2P_PUT, 0},
5529 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_XDHT_P2P_GET, 0},
5530 {&handle_dht_p2p_get_result, GNUNET_MESSAGE_TYPE_XDHT_P2P_GET_RESULT, 0},
5531 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP, 0},
5532 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_RESULT, 0},
5533 {&handle_dht_p2p_verify_successor, GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR, 0},
5534 {&handle_dht_p2p_verify_successor_result, GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR_RESULT, 0},
5535 {&handle_dht_p2p_notify_new_successor, GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_NEW_SUCCESSOR, 0},
5536 {&handle_dht_p2p_trail_setup_rejection, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_REJECTION, 0},
5537 {&handle_dht_p2p_trail_compression, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_COMPRESSION,
5538 sizeof (struct PeerTrailCompressionMessage)},
5539 {&handle_dht_p2p_trail_teardown, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN,
5540 sizeof (struct PeerTrailTearDownMessage)},
5541 {&handle_dht_p2p_add_trail, GNUNET_MESSAGE_TYPE_XDHT_P2P_ADD_TRAIL, 0},
5546 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
5547 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
5548 GNUNET_NO, core_handlers);
5549 if (NULL == core_api)
5550 return GNUNET_SYSERR;
5552 friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
5553 finger_table_init ();
5560 * Shutdown neighbours subsystem.
5563 GDS_NEIGHBOURS_done (void)
5565 if (NULL == core_api)
5568 GNUNET_CORE_disconnect (core_api);
5571 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
5572 GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
5573 friend_peermap = NULL;
5575 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
5578 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
5579 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
5587 * @return my identity
5589 struct GNUNET_PeerIdentity
5590 GDS_NEIGHBOURS_get_my_id (void)
5595 /* end of gnunet-service-xdht_neighbours.c */