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
57 * Maximum possible fingers (including predecessor) of a peer
59 #define MAX_FINGERS 65
62 * Maximum allowed number of pending messages per friend peer.
64 #define MAXIMUM_PENDING_PER_FRIEND 64
67 * How long to wait before sending another find finger trail request
69 #define DHT_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
72 * How long to wait before sending another verify successor message.
74 #define DHT_SEND_VERIFY_SUCCESSOR_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 1)
77 * How long at most to wait for transmission of a request to a friend ?
79 #define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
82 * Duration for which I may remain congested.
83 * Note: Its a static value. In future, a peer may do some analysis and calculate
84 * congestion_timeout based on 'some' parameters.
86 #define CONGESTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
89 * Maximum number of trails allowed to go through a friend.
91 #define TRAILS_THROUGH_FRIEND_THRESHOLD 64
94 * Maximum number of trails stored per finger.
96 #define MAXIMUM_TRAILS_PER_FINGER 1
99 * Finger map index for predecessor entry in finger table.
101 #define PREDECESSOR_FINGER_ID 64
104 * Wrap around in peer identity circle.
106 #define PEER_IDENTITES_WRAP_AROUND pow(2, 64) - 1
109 * FIXME: Its use only at 3 places check if you can remove it.
110 * To check if a finger is predecessor or not.
112 enum GDS_NEIGHBOURS_finger_type
114 GDS_FINGER_TYPE_PREDECESSOR = 1,
115 GDS_FINGER_TYPE_NON_PREDECESSOR = 0
118 GNUNET_NETWORK_STRUCT_BEGIN
123 struct PeerPutMessage
126 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_PUT
128 struct GNUNET_MessageHeader header;
133 uint32_t options GNUNET_PACKED;
138 uint32_t block_type GNUNET_PACKED;
143 uint32_t hop_count GNUNET_PACKED;
146 * Replication level for this message
147 * In the current implementation, this value is not used.
149 uint32_t desired_replication_level GNUNET_PACKED;
152 * Length of the PUT path that follows (if tracked).
154 uint32_t put_path_length GNUNET_PACKED;
157 * Best known destination (could be my friend or finger) which should
158 * get this message next.
160 struct GNUNET_PeerIdentity best_known_destination;
163 * In case best_known_destination is a finger, then trail to reach
164 * to that finger. Else its default value is 0.
166 struct GNUNET_HashCode intermediate_trail_id;
169 * When does the content expire?
171 struct GNUNET_TIME_AbsoluteNBO expiration_time;
174 * The key to store the value under.
176 struct GNUNET_HashCode key GNUNET_PACKED;
178 /* put path (if tracked) */
187 struct PeerGetMessage
190 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_GET
192 struct GNUNET_MessageHeader header;
197 uint32_t options GNUNET_PACKED;
200 * Desired content type.
202 uint32_t block_type GNUNET_PACKED;
207 uint32_t hop_count GNUNET_PACKED;
210 * Desired replication level for this request.
211 * In the current implementation, this value is not used.
213 uint32_t desired_replication_level GNUNET_PACKED;
216 * Total number of peers in get path.
218 unsigned int get_path_length;
221 * Best known destination (could be my friend or finger) which should
222 * get this message next.
224 struct GNUNET_PeerIdentity best_known_destination;
227 * In case best_known_destination is a finger, then trail to reach
228 * to that finger. Else its default value is 0.
230 struct GNUNET_HashCode intermediate_trail_id;
233 * The key we are looking for.
235 struct GNUNET_HashCode key;
238 /* struct GNUNET_PeerIdentity[]*/
244 struct PeerGetResultMessage
247 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_GET_RESULT
249 struct GNUNET_MessageHeader header;
252 * The type for the data.
254 uint32_t type GNUNET_PACKED;
257 * Number of peers recorded in the outgoing path from source to the
258 * stored location of this message.
260 uint32_t put_path_length GNUNET_PACKED;
263 * Length of the GET path that follows (if tracked).
265 uint32_t get_path_length GNUNET_PACKED;
268 * Peer which queried for get and should get the result.
270 struct GNUNET_PeerIdentity querying_peer;
273 * When does the content expire?
275 struct GNUNET_TIME_Absolute expiration_time;
278 * The key of the corresponding GET request.
280 struct GNUNET_HashCode key;
282 /* put path (if tracked) */
284 /* get path (if tracked) */
291 * P2P Trail setup message
293 struct PeerTrailSetupMessage
296 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP
298 struct GNUNET_MessageHeader header;
301 * Is source_peer trying to setup the trail to a predecessor or any finger.
303 uint32_t is_predecessor;
306 * Peer closest to this value will be our finger.
308 uint64_t final_destination_finger_value;
311 * Source peer which wants to setup the trail to one of its finger.
313 struct GNUNET_PeerIdentity source_peer;
316 * Best known destination (could be my friend or finger) which should
317 * get this message next.
319 * FIXME: this could be removed if we include trail_source / trail_dest
320 * in the routing table. This way we save 32 bytes of bandwidth by using
321 * extra 8 bytes of memory (2 * sizeof (GNUNET_PEER_ID))
323 struct GNUNET_PeerIdentity best_known_destination;
326 * In case best_known_destination is a finger, then trail id of trail to
327 * reach to this finger.
329 struct GNUNET_HashCode intermediate_trail_id;
332 * Trail id for trail which we are trying to setup.
334 struct GNUNET_HashCode trail_id;
336 /* List of peers which are part of trail setup so far.
337 * Trail does NOT include source_peer and peer which will be closest to
338 * ultimate_destination_finger_value.
339 * struct GNUNET_PeerIdentity trail[]
344 * P2P Trail Setup Result message
346 struct PeerTrailSetupResultMessage
350 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_RESULT
352 struct GNUNET_MessageHeader header;
355 * Finger to which we have found the path.
357 struct GNUNET_PeerIdentity finger_identity;
360 * Peer which started trail_setup to find trail to finger_identity
362 struct GNUNET_PeerIdentity querying_peer;
365 * Is the trail setup to querying_peer's predecessor or finger?
367 uint32_t is_predecessor;
370 * Value to which finger_identity is the closest peer.
372 uint64_t ulitmate_destination_finger_value;
375 * Identifier of the trail from querying peer to finger_identity, NOT
376 * including both endpoints.
378 struct GNUNET_HashCode trail_id;
380 /* List of peers which are part of the trail from querying peer to
381 * finger_identity, NOT including both endpoints.
382 * struct GNUNET_PeerIdentity trail[]
387 * P2P Verify Successor Message.
389 struct PeerVerifySuccessorMessage
392 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR
394 struct GNUNET_MessageHeader header;
397 * Peer which wants to verify its successor.
399 struct GNUNET_PeerIdentity source_peer;
402 * Source Peer's current successor.
404 struct GNUNET_PeerIdentity successor;
407 * Identifier of trail to reach from source_peer to successor.
409 struct GNUNET_HashCode trail_id;
411 /* List of the peers which are part of trail to reach from source_peer
412 * to successor, NOT including them
413 * struct GNUNET_PeerIdentity trail[]
418 * P2P Verify Successor Result Message
420 struct PeerVerifySuccessorResultMessage
423 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR_RESULT
425 struct GNUNET_MessageHeader header;
428 * Peer which sent the request to verify its successor.
430 struct GNUNET_PeerIdentity querying_peer;
433 * Successor to which PeerVerifySuccessorMessage was sent.
435 struct GNUNET_PeerIdentity current_successor;
438 * Current Predecessor of source_successor. It can be same as querying peer
439 * or different. In case it is different then it can be querying_peer's
440 * probable successor.
442 struct GNUNET_PeerIdentity probable_successor;
445 * Trail identifier of trail from querying_peer to current_successor.
447 struct GNUNET_HashCode trail_id;
450 * Direction in which we are looking at the trail.
452 uint32_t trail_direction;
454 /* In case probable_successor != querying_peer, then trail to reach from
455 * querying_peer to probable_successor, NOT including end points.
456 * struct GNUNET_PeerIdentity trail[]
461 * P2P Notify New Successor Message.
463 struct PeerNotifyNewSuccessorMessage
466 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_NEW_SUCCESSOR
468 struct GNUNET_MessageHeader header;
471 * Peer which wants to notify its new successor.
473 struct GNUNET_PeerIdentity source_peer;
476 * New successor of source_peer.
478 struct GNUNET_PeerIdentity new_successor;
481 * Unique identifier of the trail from source_peer to new_successor,
482 * NOT including the endpoints.
484 struct GNUNET_HashCode trail_id;
486 /* List of peers in trail from source_peer to new_successor,
487 * NOT including the endpoints.
488 * struct GNUNET_PeerIdentity trail[]
493 * P2P Trail Compression Message.
495 struct PeerTrailCompressionMessage
498 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_COMPRESSION
500 struct GNUNET_MessageHeader header;
503 * Source peer of this trail.
505 struct GNUNET_PeerIdentity source_peer;
508 * Trail from source_peer to destination_peer compressed such that
509 * new_first_friend is the first hop in the trail from source to
512 struct GNUNET_PeerIdentity new_first_friend;
515 * Unique identifier of trail.
517 struct GNUNET_HashCode trail_id;
522 * P2P Trail Tear Down message.
524 struct PeerTrailTearDownMessage
527 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN
529 struct GNUNET_MessageHeader header;
532 * Unique identifier of the trail.
534 struct GNUNET_HashCode trail_id;
537 * Direction of trail.
539 uint32_t trail_direction;
544 * P2P Trail Rejection Message.
546 struct PeerTrailRejectionMessage
549 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_REJECTION
551 struct GNUNET_MessageHeader header;
554 * Peer which wants to set up the trail.
556 struct GNUNET_PeerIdentity source_peer;
559 * Peer which sent trail rejection message as it it congested.
561 struct GNUNET_PeerIdentity congested_peer;
564 * Peer identity closest to this value will be finger of
567 uint64_t ultimate_destination_finger_value;
570 * Is source_peer trying to setup the trail to its predecessor or finger.
572 uint32_t is_predecessor;
575 * Identifier for the trail that source peer is trying to setup.
577 struct GNUNET_HashCode trail_id;
580 * Relative time for which congested_peer will remain congested.
582 struct GNUNET_TIME_Relative congestion_time;
584 /* Trail_list from source_peer to peer which sent the message for trail setup
585 * to congested peer. This trail does NOT include source_peer.
586 struct GNUNET_PeerIdnetity trail[]*/
590 * P2P Add Trail Message.
592 struct PeerAddTrailMessage
595 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_ADD_TRAIL
597 struct GNUNET_MessageHeader header;
600 * Source of the routing trail.
602 struct GNUNET_PeerIdentity source_peer;
605 * Destination of the routing trail.
607 struct GNUNET_PeerIdentity destination_peer;
610 * Unique identifier of the trail from source_peer to destination_peer,
611 * NOT including the endpoints.
613 struct GNUNET_HashCode trail_id;
615 /* Trail from source peer to destination peer, NOT including them.
616 * struct GNUNET_PeerIdentity trail[]
620 GNUNET_NETWORK_STRUCT_END
623 * Linked list of messages to send to a particular other peer.
625 struct P2PPendingMessage
628 * Pointer to next item in the list
630 struct P2PPendingMessage *next;
633 * Pointer to previous item in the list
635 struct P2PPendingMessage *prev;
638 * Message importance level. FIXME: used? useful?
640 unsigned int importance;
643 * When does this message time out?
645 struct GNUNET_TIME_Absolute timeout;
648 * Actual message to be sent, allocated at the end of the struct:
649 * // msg = (cast) &pm[1];
650 * // memcpy (&pm[1], data, len);
652 const struct GNUNET_MessageHeader *msg;
657 * Entry in friend_peermap.
664 struct GNUNET_PeerIdentity id;
667 * Number of trails for which this friend is the first hop or if the friend
670 unsigned int trails_count;
673 * Count of outstanding messages for this friend.
675 unsigned int pending_count;
678 * In case not 0, then amount of time for which this friend is congested.
680 struct GNUNET_TIME_Absolute congestion_timestamp;
683 * Head of pending messages to be sent to this friend.
685 struct P2PPendingMessage *head;
688 * Tail of pending messages to be sent to this friend.
690 struct P2PPendingMessage *tail;
693 * Core handle for sending messages to this friend.
695 struct GNUNET_CORE_TransmitHandle *th;
700 * An individual element of the trail to reach to a finger.
705 * Pointer to next item in the list
707 struct Trail_Element *next;
710 * Pointer to prev item in the list
712 struct Trail_Element *prev;
715 * An element in this trail.
717 struct GNUNET_PeerIdentity peer;
721 * Information about an individual trail.
728 struct Trail_Element *trail_head;
733 struct Trail_Element *trail_tail;
736 * Unique identifier of this trail.
738 struct GNUNET_HashCode trail_id;
741 * Length of trail pointed
743 unsigned int trail_length;
746 * Is there a valid trail entry.
748 unsigned int is_present;
752 * An entry in finger_table
759 struct GNUNET_PeerIdentity finger_identity;
762 * Is any finger stored at this finger index.
764 unsigned int is_present;
767 * Index in finger peer map
769 uint32_t finger_table_index;
772 * Number of trails setup so far for this finger.
773 * Should not cross MAXIMUM_TRAILS_PER_FINGER.
775 uint32_t trails_count;
778 * Array of trails to reach to this finger.
780 struct Trail trail_list[MAXIMUM_TRAILS_PER_FINGER];
785 * Stores information about the peer which is closest to destination_finger_value.
786 * 'closest' can be either successor or predecessor depending on is_predecessor
792 * Destination finger value.
794 uint64_t destination_finger_value;
797 * Is finger_value a predecessor or any other finger.
799 unsigned int is_predecessor;
802 * Trail id to reach to peer.
803 * In case peer is my identity or friend, it is set to 0.
805 struct GNUNET_HashCode trail_id;
808 * Next destination. In case of friend and my_identity , it is same as next_hop
809 * In case of finger it is finger identity.
811 struct GNUNET_PeerIdentity best_known_destination;
814 * In case best_known_destination is a finger, then first friend in the trail
815 * to reach to it. In other case, same as best_known_destination.
817 struct GNUNET_PeerIdentity next_hop;
822 * Data structure to store the trail chosen to reach to finger.
824 struct Selected_Finger_Trail
827 * First friend in the trail to reach finger.
829 struct FriendInfo friend;
832 * Identifier of this trail.
834 struct GNUNET_HashCode trail_id;
837 * Total number of peers in this trail.
839 unsigned int trail_length;
843 * Task that sends FIND FINGER TRAIL requests. This task is started when we have
844 * get our first friend.
846 static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task;
849 * Task that sends verify successor message. This task is started when we get
850 * our successor for the first time.
852 static GNUNET_SCHEDULER_TaskIdentifier send_verify_successor_task;
855 * Identity of this peer.
857 static struct GNUNET_PeerIdentity my_identity;
860 * Peer map of all the friends of a peer
862 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap;
865 * Array of all the fingers.
867 static struct FingerInfo finger_table [MAX_FINGERS];
872 static struct GNUNET_CORE_Handle *core_api;
875 * Handle for the statistics service.
877 extern struct GNUNET_STATISTICS_Handle *GDS_stats;
880 * The current finger index that we have want to find trail to. We start the
881 * search with value = 0, i.e. successor and then go to PREDCESSOR_FINGER_ID
882 * and decrement it. For any index 63 <= index < 0, if finger is same as successor,
883 * we reset this index to 0.
885 static unsigned int current_search_finger_index;
888 * Should we store our topology predecessor and successor IDs into statistics?
890 unsigned int track_topology;
893 * Called when core is ready to send a message we asked for
894 * out to the destination.
896 * @param cls the 'struct FriendInfo' of the target friend
897 * @param size number of bytes available in buf
898 * @param buf where the callee should write the message
899 * @return number of bytes written to buf
902 core_transmit_notify (void *cls, size_t size, void *buf)
904 struct FriendInfo *peer = cls;
906 struct P2PPendingMessage *pending;
911 while ((NULL != (pending = peer->head)) &&
912 (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us))
914 peer->pending_count--;
915 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
916 GNUNET_free (pending);
920 /* no messages pending */
926 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
927 GNUNET_CORE_PRIO_BEST_EFFORT,
928 GNUNET_TIME_absolute_get_remaining
929 (pending->timeout), &peer->id,
930 ntohs (pending->msg->size),
931 &core_transmit_notify, peer);
932 GNUNET_break (NULL != peer->th);
936 while ((NULL != (pending = peer->head)) &&
937 (size - off >= (msize = ntohs (pending->msg->size))))
939 /*GNUNET_STATISTICS_update (GDS_stats,
941 ("# Bytes transmitted to other peers"), msize,
943 memcpy (&cbuf[off], pending->msg, msize);
945 peer->pending_count--;
946 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
947 GNUNET_free (pending);
949 if (peer->head != NULL)
952 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
953 GNUNET_CORE_PRIO_BEST_EFFORT,
954 GNUNET_TIME_absolute_get_remaining
955 (pending->timeout), &peer->id, msize,
956 &core_transmit_notify, peer);
957 GNUNET_break (NULL != peer->th);
964 * Transmit all messages in the friend's message queue.
966 * @param peer message queue to process
969 process_friend_queue (struct FriendInfo *peer)
971 struct P2PPendingMessage *pending;
973 if (NULL == (pending = peer->head))
977 if (NULL != peer->th)
981 GNUNET_STATISTICS_update (GDS_stats,
983 ("# Bytes of bandwidth requested from core"),
984 ntohs (pending->msg->size), GNUNET_NO);
987 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
989 GNUNET_TIME_absolute_get_remaining
990 (pending->timeout), &peer->id,
991 ntohs (pending->msg->size),
992 &core_transmit_notify, peer);
993 GNUNET_break (NULL != peer->th);
998 * Construct a trail setup message and forward it to target_friend
999 * @param source_peer Peer which wants to setup the trail
1000 * @param ultimate_destination_finger_value Peer identity closest to this value
1001 * will be finger to @a source_peer
1002 * @param best_known_destination Best known destination (could be finger or friend)
1003 * which should get this message. In case it is
1004 * friend, then it is same as target_friend
1005 * @param target_friend Friend to which message is forwarded now.
1006 * @param trail_length Total number of peers in trail setup so far.
1007 * @param trail_peer_list Trail setup so far
1008 * @param is_predecessor Is @a source_peer looking for trail to a predecessor or not.
1009 * @param trail_id Unique identifier for the trail we are trying to setup.
1010 * @param intermediate_trail_id Trail id of intermediate trail to reach to
1011 * best_known_destination when its a finger. If not
1012 * used then set to 0.
1015 GDS_NEIGHBOURS_send_trail_setup (struct GNUNET_PeerIdentity source_peer,
1016 uint64_t ultimate_destination_finger_value,
1017 struct GNUNET_PeerIdentity best_known_destination,
1018 struct FriendInfo *target_friend,
1019 unsigned int trail_length,
1020 const struct GNUNET_PeerIdentity *trail_peer_list,
1021 unsigned int is_predecessor,
1022 struct GNUNET_HashCode trail_id,
1023 struct GNUNET_HashCode intermediate_trail_id)
1025 struct P2PPendingMessage *pending;
1026 struct PeerTrailSetupMessage *tsm;
1027 struct GNUNET_PeerIdentity *peer_list;
1030 msize = sizeof (struct PeerTrailSetupMessage) +
1031 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1033 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1039 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1041 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1045 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1046 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1047 tsm = (struct PeerTrailSetupMessage *) &pending[1];
1048 pending->msg = &tsm->header;
1049 tsm->header.size = htons (msize);
1050 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP);
1051 tsm->final_destination_finger_value = GNUNET_htonll (ultimate_destination_finger_value);
1052 tsm->source_peer = source_peer;
1053 tsm->best_known_destination = best_known_destination;
1054 tsm->is_predecessor = htonl (is_predecessor);
1055 tsm->trail_id = trail_id;
1056 tsm->intermediate_trail_id = intermediate_trail_id;
1058 if (trail_length > 0)
1060 peer_list = (struct GNUNET_PeerIdentity *) &tsm[1];
1061 memcpy (peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
1064 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1065 target_friend->pending_count++;
1066 process_friend_queue (target_friend);
1071 * Construct a trail setup result message and forward it to target friend.
1072 * @param querying_peer Peer which sent the trail setup request and should get
1074 * @param Finger Peer to which the trail has been setup to.
1075 * @param target_friend Friend to which this message should be forwarded.
1076 * @param trail_length Numbers of peers in the trail.
1077 * @param trail_peer_list Peers which are part of the trail from
1078 * querying_peer to Finger, NOT including them.
1079 * @param is_predecessor Is @a Finger predecessor to @a querying_peer ?
1080 * @param ultimate_destination_finger_value Value to which @a finger is the closest
1082 * @param trail_id Unique identifier of the trail.
1085 GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity querying_peer,
1086 struct GNUNET_PeerIdentity finger,
1087 struct FriendInfo *target_friend,
1088 unsigned int trail_length,
1089 const struct GNUNET_PeerIdentity *trail_peer_list,
1090 unsigned int is_predecessor,
1091 uint64_t ultimate_destination_finger_value,
1092 struct GNUNET_HashCode trail_id)
1094 struct P2PPendingMessage *pending;
1095 struct PeerTrailSetupResultMessage *tsrm;
1096 struct GNUNET_PeerIdentity *peer_list;
1099 msize = sizeof (struct PeerTrailSetupResultMessage) +
1100 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1102 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1108 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1110 GNUNET_STATISTICS_update (GDS_stats,
1111 gettext_noop ("# P2P messages dropped due to full queue"),
1115 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1116 pending->importance = 0;
1117 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1118 tsrm = (struct PeerTrailSetupResultMessage *) &pending[1];
1119 pending->msg = &tsrm->header;
1120 tsrm->header.size = htons (msize);
1121 tsrm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_RESULT);
1122 tsrm->querying_peer = querying_peer;
1123 tsrm->finger_identity = finger;
1124 tsrm->is_predecessor = htonl (is_predecessor);
1125 tsrm->trail_id = trail_id;
1126 tsrm->ulitmate_destination_finger_value =
1127 GNUNET_htonll (ultimate_destination_finger_value);
1128 peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1];
1130 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1132 /* Send the message to chosen friend. */
1133 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1134 target_friend->pending_count++;
1135 process_friend_queue (target_friend);
1140 * Send trail rejection message to target friend
1141 * @param source_peer Peer which is trying to setup the trail.
1142 * @param ultimate_destination_finger_value Peer closest to this value will be
1143 * @a source_peer's finger
1144 * @param congested_peer Peer which sent this message as it is congested.
1145 * @param is_predecessor Is source_peer looking for trail to a predecessor or not.
1146 * @param trail_peer_list Trails seen so far in trail setup before getting rejected
1147 * by congested_peer. This does NOT include @a source_peer
1148 * and congested_peer.
1149 * @param trail_length Total number of peers in trail_peer_list, NOT including
1150 * @a source_peer and @a congested_peer
1151 * @param trail_id Unique identifier of this trail.
1152 * @param congestion_timeout Duration given by congested peer as an estimate of
1153 * how long it may remain congested.
1156 GDS_NEIGHBOURS_send_trail_rejection (struct GNUNET_PeerIdentity source_peer,
1157 uint64_t ultimate_destination_finger_value,
1158 struct GNUNET_PeerIdentity congested_peer,
1159 unsigned int is_predecessor,
1160 const struct GNUNET_PeerIdentity *trail_peer_list,
1161 unsigned int trail_length,
1162 struct GNUNET_HashCode trail_id,
1163 struct FriendInfo *target_friend,
1164 const struct GNUNET_TIME_Relative congestion_timeout)
1166 struct PeerTrailRejectionMessage *trm;
1167 struct P2PPendingMessage *pending;
1168 struct GNUNET_PeerIdentity *peer_list;
1171 msize = sizeof (struct PeerTrailRejectionMessage) +
1172 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1174 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1180 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1182 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1186 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1187 pending->importance = 0;
1188 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1189 trm = (struct PeerTrailRejectionMessage *)&pending[1];
1190 pending->msg = &trm->header;
1191 trm->header.size = htons (msize);
1192 trm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_REJECTION);
1193 trm->source_peer = source_peer;
1194 trm->congested_peer = congested_peer;
1195 trm->congestion_time = congestion_timeout;
1196 trm->is_predecessor = htonl (is_predecessor);
1197 trm->trail_id = trail_id;
1198 trm->ultimate_destination_finger_value =
1199 GNUNET_htonll (ultimate_destination_finger_value);
1201 peer_list = (struct GNUNET_PeerIdentity *) &trm[1];
1202 if (trail_length > 0)
1204 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1207 /* Send the message to chosen friend. */
1208 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1209 target_friend->pending_count++;
1210 process_friend_queue (target_friend);
1215 * Construct a verify successor message and forward it to target_friend.
1216 * @param source_peer Peer which wants to verify its successor.
1217 * @param successor Peer which is @a source_peer's current successor.
1218 * @param trail_id Unique Identifier of trail from @a source_peer to @a successor,
1219 * NOT including them.
1220 * @param trail List of peers which are part of trail to reach from @a source_peer
1221 * to @a successor, NOT including them.
1222 * @param trail_length Total number of peers in @a trail.
1223 * @param target_friend Next friend to get this message.
1226 GDS_NEIGHBOURS_send_verify_successor_message (struct GNUNET_PeerIdentity source_peer,
1227 struct GNUNET_PeerIdentity successor,
1228 struct GNUNET_HashCode trail_id,
1229 struct GNUNET_PeerIdentity *trail,
1230 unsigned int trail_length,
1231 struct FriendInfo *target_friend)
1233 struct PeerVerifySuccessorMessage *vsm;
1234 struct P2PPendingMessage *pending;
1235 struct GNUNET_PeerIdentity *peer_list;
1238 msize = sizeof (struct PeerVerifySuccessorMessage) +
1239 (trail_length * sizeof (struct GNUNET_PeerIdentity));;
1240 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1246 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1248 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1252 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1253 pending->importance = 0; /* FIXME */
1254 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1255 vsm = (struct PeerVerifySuccessorMessage *) &pending[1];
1256 pending->msg = &vsm->header;
1257 vsm->header.size = htons (msize);
1258 vsm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR);
1259 vsm->source_peer = source_peer;
1260 vsm->successor = successor;
1261 vsm->trail_id = trail_id;
1263 if (trail_length != 0)
1265 peer_list = (struct GNUNET_PeerIdentity *) &vsm[1];
1266 memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
1269 /* Send the message to chosen friend. */
1270 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1271 target_friend->pending_count++;
1272 process_friend_queue (target_friend);
1277 * FIXME: In every function we pass target friend except for this one.
1278 * so, either change everything or this one. also, should se just store
1279 * the pointer to friend in routing table rather than gnunet_peeridentity.
1280 * if yes then we should keep friend info in.h andmake lot of changes.
1281 * Construct a trail teardown message and forward it to target friend.
1282 * @param trail_id Unique identifier of the trail.
1283 * @param trail_direction Direction of trail.
1284 * @param target_friend Friend to get this message.
1287 GDS_NEIGHBOURS_send_trail_teardown (struct GNUNET_HashCode trail_id,
1288 unsigned int trail_direction,
1289 struct GNUNET_PeerIdentity peer)
1291 struct PeerTrailTearDownMessage *ttdm;
1292 struct P2PPendingMessage *pending;
1293 struct FriendInfo *target_friend;
1296 msize = sizeof (struct PeerTrailTearDownMessage);
1298 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1304 /*FIXME:In what case friend can be null. ?*/
1305 if (NULL == (target_friend =
1306 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &peer)));
1309 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1311 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1315 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1316 pending->importance = 0; /* FIXME */
1317 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1318 ttdm = (struct PeerTrailTearDownMessage *) &pending[1];
1319 pending->msg = &ttdm->header;
1320 ttdm->header.size = htons (msize);
1321 ttdm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN);
1322 ttdm->trail_id = trail_id;
1323 ttdm->trail_direction = htonl (trail_direction);
1325 /* Send the message to chosen friend. */
1326 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1327 target_friend->pending_count++;
1328 process_friend_queue (target_friend);
1333 * Construct a verify successor result message and send it to target_friend
1334 * @param querying_peer Peer which sent the verify successor message.
1335 * @param source_successor Current_successor of @a querying_peer.
1336 * @param current_predecessor Current predecessor of @a successor. Could be same
1337 * or different from @a querying_peer.
1338 * @param trail_id Unique identifier of the trail from @a querying_peer to
1339 * @a successor, NOT including them.
1340 * @param trail List of peers which are part of trail from @a querying_peer to
1341 * @a successor, NOT including them.
1342 * @param trail_length Total number of peers in @a trail
1343 * @param trail_direction Direction in which we are sending the message. In this
1344 * case we are sending result from @a successor to @a querying_peer.
1345 * @param target_friend Next friend to get this message.
1348 GDS_NEIGHBOURS_send_verify_successor_result (struct GNUNET_PeerIdentity querying_peer,
1349 struct GNUNET_PeerIdentity current_successor,
1350 struct GNUNET_PeerIdentity probable_successor,
1351 struct GNUNET_HashCode trail_id,
1352 const struct GNUNET_PeerIdentity *trail,
1353 unsigned int trail_length,
1354 enum GDS_ROUTING_trail_direction trail_direction,
1355 struct FriendInfo *target_friend)
1357 struct PeerVerifySuccessorResultMessage *vsmr;
1358 struct P2PPendingMessage *pending;
1359 struct GNUNET_PeerIdentity *peer_list;
1362 msize = sizeof (struct PeerVerifySuccessorResultMessage) +
1363 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1365 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1371 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1373 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1377 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1378 pending->importance = 0; /* FIXME */
1379 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1380 vsmr = (struct PeerVerifySuccessorResultMessage *) &pending[1];
1381 pending->msg = &vsmr->header;
1382 vsmr->header.size = htons (msize);
1383 vsmr->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR_RESULT);
1384 vsmr->querying_peer = querying_peer;
1385 vsmr->current_successor = current_successor;
1386 vsmr->probable_successor = probable_successor;
1387 vsmr->trail_direction = htonl (trail_direction);
1388 vsmr->trail_id = trail_id;
1390 if (trail_length > 0)
1392 peer_list = (struct GNUNET_PeerIdentity *) &vsmr[1];
1393 memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
1396 /* Send the message to chosen friend. */
1397 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1398 target_friend->pending_count++;
1399 process_friend_queue (target_friend);
1404 * Construct a notify new successor message and send it to target_friend
1405 * @param source_peer Peer which wants to notify to its new successor that it
1406 * could be its predecessor.
1407 * @param successor New successor of @a source_peer
1408 * @param successor_trail List of peers in Trail to reach from
1409 * @a source_peer to @a new_successor, NOT including
1411 * @param successor_trail_length Total number of peers in @a new_successor_trail.
1412 * @param successor_trail_id Unique identifier of @a new_successor_trail.
1413 * @param target_friend Next friend to get this message.
1416 GDS_NEIGHBOURS_send_notify_new_successor (struct GNUNET_PeerIdentity source_peer,
1417 struct GNUNET_PeerIdentity successor,
1418 const struct GNUNET_PeerIdentity *successor_trail,
1419 unsigned int successor_trail_length,
1420 struct GNUNET_HashCode succesor_trail_id,
1421 struct FriendInfo *target_friend)
1423 struct PeerNotifyNewSuccessorMessage *nsm;
1424 struct P2PPendingMessage *pending;
1425 struct GNUNET_PeerIdentity *peer_list;
1428 msize = sizeof (struct PeerNotifyNewSuccessorMessage) +
1429 (successor_trail_length * sizeof(struct GNUNET_PeerIdentity));
1431 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1437 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1439 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1443 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1444 pending->importance = 0; /* FIXME */
1445 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1446 nsm = (struct PeerNotifyNewSuccessorMessage *) &pending[1];
1447 pending->msg = &nsm->header;
1448 nsm->header.size = htons (msize);
1449 nsm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_NEW_SUCCESSOR);
1450 nsm->new_successor = successor;
1451 nsm->source_peer = source_peer;
1452 nsm->trail_id = succesor_trail_id;
1454 if (successor_trail_length > 0)
1456 peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
1457 memcpy (peer_list, successor_trail,
1458 successor_trail_length * sizeof (struct GNUNET_PeerIdentity));
1461 /* Send the message to chosen friend. */
1462 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1463 target_friend->pending_count++;
1464 process_friend_queue (target_friend);
1469 * Construct an add_trail message and send it to target_friend
1470 * @param source_peer Source of the trail.
1471 * @param destination_peer Destination of the trail.
1472 * @param trail_id Unique identifier of the trail from
1473 * @a source_peer to @a destination_peer, NOT including the endpoints.
1474 * @param trail List of peers in Trail from @a source_peer to @a destination_peer,
1475 * NOT including the endpoints.
1476 * @param trail_length Total number of peers in @a trail.
1477 * @param target_friend Next friend to get this message.
1480 GDS_NEIGHBOURS_send_add_trail (struct GNUNET_PeerIdentity source_peer,
1481 struct GNUNET_PeerIdentity destination_peer,
1482 struct GNUNET_HashCode trail_id,
1483 const struct GNUNET_PeerIdentity *trail,
1484 unsigned int trail_length,
1485 struct FriendInfo *target_friend)
1487 struct PeerAddTrailMessage *adm;
1488 struct GNUNET_PeerIdentity *peer_list;
1489 struct P2PPendingMessage *pending;
1492 msize = sizeof (struct PeerAddTrailMessage) +
1493 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1495 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1501 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1503 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1507 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1508 pending->importance = 0; /* FIXME */
1509 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1510 adm = (struct PeerAddTrailMessage *) &pending[1];
1511 pending->msg = &adm->header;
1512 adm->header.size = htons (msize);
1513 adm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_ADD_TRAIL);
1514 adm->source_peer = source_peer;
1515 adm->destination_peer = destination_peer;
1516 adm->trail_id = trail_id;
1517 peer_list = (struct GNUNET_PeerIdentity *)&adm[1];
1518 memcpy (peer_list, trail, sizeof (struct GNUNET_PeerIdentity) * trail_length);
1520 /* Send the message to chosen friend. */
1521 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1522 target_friend->pending_count++;
1523 process_friend_queue (target_friend);
1529 * Construct a trail compression message and send it to target_friend.
1530 * @param source_peer Source of the trail.
1531 * @param trail_id Unique identifier of trail.
1532 * @param first_friend First hop in compressed trail to reach from source to finger
1533 * @param target_friend Next friend to get this message.
1536 GDS_NEIGHBOURS_send_trail_compression (struct GNUNET_PeerIdentity source_peer,
1537 struct GNUNET_HashCode trail_id,
1538 struct GNUNET_PeerIdentity first_friend,
1539 struct FriendInfo *target_friend)
1541 struct P2PPendingMessage *pending;
1542 struct PeerTrailCompressionMessage *tcm;
1545 msize = sizeof (struct PeerTrailCompressionMessage);
1547 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1553 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1555 GNUNET_STATISTICS_update (GDS_stats,
1556 gettext_noop ("# P2P messages dropped due to full queue"),
1560 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1561 pending->importance = 0; /* FIXME */
1562 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1563 tcm = (struct PeerTrailCompressionMessage *) &pending[1];
1564 pending->msg = &tcm->header;
1565 tcm->header.size = htons (msize);
1566 tcm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_COMPRESSION);
1567 tcm->source_peer = source_peer;
1568 tcm->new_first_friend = first_friend;
1569 tcm->trail_id = trail_id;
1571 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1572 target_friend->pending_count++;
1573 process_friend_queue (target_friend);
1579 * Search my location in trail. In case I am present more than once in the
1580 * trail (can happen during trail setup), then return my lowest index.
1581 * @param trail List of peers
1582 * @return my_index if found
1583 * -1 if no entry found.
1586 search_my_index (const struct GNUNET_PeerIdentity *trail,
1591 for (i = 0; i < trail_length; i++)
1593 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &trail[i]))
1602 * Check if the friend is congested or have reached maximum number of trails
1603 * it can be part of of.
1604 * @param friend Friend to be checked.
1605 * @return #GNUNET_NO if friend is not congested or have not crossed threshold.
1606 * #GNUNET_YES if friend is either congested or have crossed threshold
1609 is_friend_congested (struct FriendInfo *friend)
1611 if ((TRAILS_THROUGH_FRIEND_THRESHOLD > friend->trails_count) &&
1612 ((0 == GNUNET_TIME_absolute_get_remaining
1613 (friend->congestion_timestamp).rel_value_us)))
1621 * Select closest finger to value.
1622 * @param peer1 First peer
1623 * @param peer2 Second peer
1624 * @param value Value to be compare
1625 * @return Closest peer
1627 const static struct GNUNET_PeerIdentity *
1628 select_closest_finger (const struct GNUNET_PeerIdentity *peer1,
1629 const struct GNUNET_PeerIdentity *peer2,
1632 uint64_t peer1_value;
1633 uint64_t peer2_value;
1635 memcpy (&peer1_value, peer1, sizeof (uint64_t));
1636 memcpy (&peer2_value, peer2, sizeof (uint64_t));
1637 peer1_value = GNUNET_ntohll (peer1_value);
1638 peer2_value = GNUNET_ntohll (peer2_value);
1640 if (peer1_value == value)
1645 if (peer2_value == value)
1650 if (peer2_value < peer1_value)
1652 if ((peer2_value < value) && (value < peer1_value))
1656 else if (((peer1_value < value) && (value < PEER_IDENTITES_WRAP_AROUND)) ||
1657 ((0 < value) && (value < peer2_value)))
1663 if (peer1_value < peer2_value)
1665 if ((peer1_value < value) && (value < peer2_value))
1669 else if (((peer2_value < value) && (value < PEER_IDENTITES_WRAP_AROUND)) ||
1670 ((0 < value) && (value < peer1_value)))
1680 * Select closest predecessor to value.
1681 * @param peer1 First peer
1682 * @param peer2 Second peer
1683 * @param value Value to be compare
1684 * @return Peer which precedes value in the network.
1686 const static struct GNUNET_PeerIdentity *
1687 select_closest_predecessor (const struct GNUNET_PeerIdentity *peer1,
1688 const struct GNUNET_PeerIdentity *peer2,
1691 uint64_t peer1_value;
1692 uint64_t peer2_value;
1694 memcpy (&peer1_value, peer1, sizeof (uint64_t));
1695 memcpy (&peer2_value, peer2, sizeof (uint64_t));
1696 peer1_value = GNUNET_ntohll (peer1_value);
1697 peer2_value = GNUNET_ntohll (peer2_value);
1699 if (peer1_value == value)
1702 if (peer2_value == value)
1705 if (peer1_value < peer2_value)
1707 if ((peer1_value < value) && (value < peer2_value))
1711 else if (((peer2_value < value) && (value < PEER_IDENTITES_WRAP_AROUND)) ||
1712 ((PEER_IDENTITES_WRAP_AROUND > value) && (value < peer1_value)))
1718 if (peer2_value < peer1_value)
1720 if ((peer2_value < value) && (value < peer1_value))
1724 else if (((peer1_value < value) && (value < PEER_IDENTITES_WRAP_AROUND)) ||
1725 ((PEER_IDENTITES_WRAP_AROUND > value) && (value < peer2_value)))
1735 * This is a test function to print all the entries of friend table.
1738 test_friend_peermap_print ()
1740 struct FriendInfo *friend;
1741 struct GNUNET_CONTAINER_MultiPeerMapIterator *friend_iter;
1742 struct GNUNET_PeerIdentity print_peer;
1743 struct GNUNET_PeerIdentity key_ret;
1746 print_peer = my_identity;
1747 FPRINTF (stderr,_("\nSUPU************ FRIEND_PEERMAP of %s"),GNUNET_i2s(&print_peer));
1748 friend_iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1750 for (i = 0; i < GNUNET_CONTAINER_multipeermap_size (friend_peermap); i++)
1752 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (friend_iter,
1754 (const void **)&friend))
1756 memcpy (&print_peer, &key_ret, sizeof (struct GNUNET_PeerIdentity));
1757 FPRINTF (stderr,_("\nSUPU %s, %s, %d, friend = %s, friend->trails_count = %d"),
1758 __FILE__, __func__,__LINE__, GNUNET_i2s(&print_peer), friend->trails_count);
1766 * This is a test function, to print all the entries of finger table.
1769 test_finger_table_print()
1771 struct FingerInfo *finger;
1772 struct GNUNET_PeerIdentity print_peer;
1773 //struct Trail *trail;
1777 print_peer = my_identity;
1778 FPRINTF (stderr,_("\nSUPU************ FINGER_TABLE of %s"),GNUNET_i2s(&print_peer));
1779 for (i = 0; i < MAX_FINGERS; i++)
1781 finger = &finger_table[i];
1783 if (GNUNET_NO == finger->is_present)
1786 print_peer = finger->finger_identity;
1787 FPRINTF (stderr,_("\nSUPU %s, %s, %d, finger_table[%d] = %s, trails_count = %d"),
1788 __FILE__, __func__,__LINE__,i,GNUNET_i2s (&print_peer), finger->trails_count);
1791 for (j = 0; j < finger->trails_count; j++)
1793 trail = &finger->trail_list[j];
1794 FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail_id[%d]=%s"),__FILE__, __func__,__LINE__,j, GNUNET_h2s(&trail->trail_id));
1795 struct Trail_Element *element;
1796 element = trail->trail_head;
1797 for (k = 0; k < trail->trail_length; k++)
1799 print_peer = element->peer;
1800 FPRINTF (stderr,_("\nSUPU %s, %s, %d,trail[%d] = %s "),__FILE__, __func__,__LINE__,k, GNUNET_i2s(&print_peer));
1801 element = element->next;
1810 * Select the closest peer among two peers (which should not be same)
1811 * with respect to value and finger_table_index
1812 * NOTE: peer1 != peer2
1813 * @param peer1 First peer
1814 * @param peer2 Second peer
1815 * @param value Value relative to which we find the closest
1816 * @param is_predecessor Is value a predecessor or any other finger.
1817 * @return Closest peer among two peers.
1819 const static struct GNUNET_PeerIdentity *
1820 select_closest_peer (const struct GNUNET_PeerIdentity *peer1,
1821 const struct GNUNET_PeerIdentity *peer2,
1823 unsigned int is_predecessor)
1825 if (1 == is_predecessor)
1826 return select_closest_predecessor (peer1, peer2, value);
1828 return select_closest_finger (peer1, peer2, value);
1833 * Iterate over the list of all the trails of a finger. In case the first
1834 * friend to reach the finger has reached trail threshold or is congested,
1835 * then don't select it. In case there multiple available good trails to reach
1836 * to Finger, choose the one with shortest trail length.
1837 * Note: We use length as parameter. But we can use any other suitable parameter
1839 * @param finger Finger
1840 * @return struct Selected_Finger_Trail which contains the first friend , trail id
1841 * and trail length. NULL in case none of the trails are free.
1843 static struct Selected_Finger_Trail *
1844 select_finger_trail (struct FingerInfo *finger)
1846 struct FriendInfo *friend;
1847 struct Trail *iterator;
1848 struct Selected_Finger_Trail *finger_trail;
1850 unsigned int flag = 0;
1853 finger_trail = GNUNET_new (struct Selected_Finger_Trail);
1854 GNUNET_assert (finger->trails_count > 0);
1856 for (i = 0; i < finger->trails_count; i++)
1858 iterator = &finger->trail_list[i];
1860 /* No trail stored at this index. */
1861 if (GNUNET_NO == iterator->is_present)
1864 GNUNET_assert (NULL !=
1866 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1867 &iterator->trail_head->peer)));
1869 /* First friend to reach trail is not free. */
1870 if (GNUNET_YES == is_friend_congested (friend))
1879 finger_trail->trail_length = iterator->trail_length;
1880 finger_trail->friend = *friend;
1881 finger_trail->trail_id = iterator->trail_id;
1883 else if (finger_trail->trail_length > iterator->trail_length)
1885 finger_trail->friend = *friend;
1886 finger_trail->trail_id = iterator->trail_id;
1887 finger_trail->trail_length = iterator->trail_length;
1891 /* All the first friend in all the trails to reach to finger are either
1892 congested or have crossed trail threshold. */
1893 if (j == finger->trails_count)
1896 return finger_trail;
1901 * Compare FINGER entry with current successor. If finger's first friend of all
1902 * its trail is not congested and has not crossed trail threshold, then check
1903 * if finger peer identity is closer to final_destination_finger_value than
1904 * current_successor. If yes then update current_successor.
1905 * @param current_successor[in/out]
1909 compare_finger_and_current_successor (struct Closest_Peer *current_closest_peer)
1911 struct FingerInfo *finger;
1912 const struct GNUNET_PeerIdentity *closest_peer;
1913 struct Selected_Finger_Trail *finger_trail;
1916 /* Iterate over finger table. */
1917 for (i = 0; i < MAX_FINGERS; i++)
1919 finger = &finger_table[i];
1921 if (GNUNET_NO == finger->is_present)
1924 /* FIXME write correct comment here */
1925 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
1926 ¤t_closest_peer->best_known_destination))
1929 /* If I am my own finger, then ignore this finger. */
1930 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
1933 /* FIXME: I think a peer should not select itself as its own identity ever.
1934 But it does select. Find out why??*/
1940 /* If finger is a friend, then do nothing. As we have already checked
1941 * for each friend in compare_friend_and_current_successor(). */
1942 if (NULL != (GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1943 &finger->finger_identity)))
1948 closest_peer = select_closest_peer (&finger->finger_identity,
1949 ¤t_closest_peer->best_known_destination,
1950 current_closest_peer->destination_finger_value,
1951 current_closest_peer->is_predecessor);
1953 if (&finger->finger_identity == closest_peer)
1955 /* Choose one of the trail to reach to finger. */
1956 finger_trail = select_finger_trail (finger);
1958 /* In case no trail found, ignore this finger. */
1959 if (NULL == finger_trail)
1962 current_closest_peer->best_known_destination = finger->finger_identity;
1963 current_closest_peer->next_hop = finger_trail->friend.id;
1964 current_closest_peer->trail_id = finger_trail->trail_id;
1965 //GNUNET_free(finger_trail);//FIXME: where should we free the finger trail.
1973 * Compare friend entry with current successor.
1974 * If friend identity and current_successor is same, then do nothing.
1975 * If friend is not congested and has not crossed trail threshold, then check
1976 * if friend peer identity is closer to final_destination_finger_value than
1977 * current_successor. If yes then update current_successor.
1978 * @param cls closure
1979 * @param key current public key
1980 * @param value struct Closest_Peer
1981 * @return #GNUNET_YES if we should continue to iterate,
1982 * #GNUNET_NO if not.
1985 compare_friend_and_current_closest_peer (void *cls,
1986 const struct GNUNET_PeerIdentity *key,
1989 struct FriendInfo *friend = value;
1990 struct Closest_Peer *current_closest_peer = cls;
1991 const struct GNUNET_PeerIdentity *closest_peer;
1993 /* Friend is either congested or has crossed threshold. */
1994 if (GNUNET_YES == is_friend_congested (friend))
1997 /* If current_closest_peer and friend identity are same, then do nothing.*/
1998 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&friend->id,
1999 ¤t_closest_peer->best_known_destination))
2005 closest_peer = select_closest_peer (&friend->id,
2006 ¤t_closest_peer->best_known_destination,
2007 current_closest_peer->destination_finger_value,
2008 current_closest_peer->is_predecessor);
2010 /* Is friend the closest successor? */
2011 if (&friend->id == closest_peer)
2013 current_closest_peer->best_known_destination = friend->id;
2014 current_closest_peer->next_hop = friend->id;
2022 * Initialize current_successor to my_identity.
2023 * @param my_identity My peer identity
2024 * @return Updated closest_peer
2026 static struct Closest_Peer
2027 init_current_successor (struct GNUNET_PeerIdentity my_identity,
2028 uint64_t destination_finger_value,
2029 unsigned int is_predecessor)
2031 struct Closest_Peer current_closest_peer;
2033 memset (¤t_closest_peer.trail_id, 0, sizeof(struct GNUNET_HashCode));
2034 current_closest_peer.destination_finger_value = destination_finger_value;
2035 current_closest_peer.is_predecessor = is_predecessor;
2036 current_closest_peer.next_hop = my_identity;
2037 current_closest_peer.best_known_destination = my_identity;
2039 return current_closest_peer;
2044 * FIXME: at the moment, there is not 100% get and put in case of non-malicious
2045 * peer. It could be because of the logic we wrote here. Verify if its correct.
2046 * If not then return immediate_successor.
2048 * Find the successor for destination_finger_value among my_identity, my
2049 * friends and my fingers. Don't consider friends or fingers which are either
2050 * congested or have crossed the threshold.
2051 * NOTE: In case a friend is also a finger, then it is always chosen as friend
2053 * @param destination_finger_value Peer closest to this value will be the next successor.
2054 * @param is_predecessor Are we looking for predecessor or finger?
2055 * @return Successor It is never NULL, in case none of friend or finger is closest,
2056 * then we return my_identity.
2058 static struct Closest_Peer
2059 find_successor (uint64_t destination_finger_value,
2060 unsigned int is_predecessor)
2062 struct Closest_Peer current_closest_peer;
2064 /* Initialize current_successor to my_identity. */
2065 current_closest_peer = init_current_successor (my_identity,
2066 destination_finger_value,
2069 /* Compare each friend entry with current_successor and update current_successor
2070 * with friend if its closest. */
2073 GNUNET_CONTAINER_multipeermap_iterate (friend_peermap,
2074 &compare_friend_and_current_closest_peer,
2075 ¤t_closest_peer));
2077 /* Compare each finger entry with current_successor and update current_successor
2078 * with finger if its closest. */
2079 compare_finger_and_current_successor (¤t_closest_peer);
2081 return current_closest_peer;
2086 * Construct a Put message and send it to target_peer.
2087 * @param key Key for the content
2088 * @param block_type Type of the block
2089 * @param options Routing options
2090 * @param desired_replication_level Desired replication count
2091 * @param best_known_dest Peer to which this message should reach eventually,
2092 * as it is best known destination to me.
2093 * @param intermediate_trail_id Trail id in case
2094 * @param target_peer Peer to which this message will be forwarded.
2095 * @param hop_count Number of hops traversed so far.
2096 * @param put_path_length Total number of peers in @a put_path
2097 * @param put_path Number of peers traversed so far
2098 * @param expiration_time When does the content expire
2099 * @param data Content to store
2100 * @param data_size Size of content @a data in bytes
2103 GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key,
2104 enum GNUNET_BLOCK_Type block_type,
2105 enum GNUNET_DHT_RouteOption options,
2106 uint32_t desired_replication_level,
2107 struct GNUNET_PeerIdentity best_known_dest,
2108 struct GNUNET_HashCode intermediate_trail_id,
2109 struct GNUNET_PeerIdentity *target_peer,
2111 uint32_t put_path_length,
2112 struct GNUNET_PeerIdentity *put_path,
2113 struct GNUNET_TIME_Absolute expiration_time,
2114 const void *data, size_t data_size)
2116 struct PeerPutMessage *ppm;
2117 struct P2PPendingMessage *pending;
2118 struct FriendInfo *target_friend;
2119 struct GNUNET_PeerIdentity *pp;
2120 struct GNUNET_PeerIdentity next_hop;
2124 msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
2125 sizeof (struct PeerPutMessage);
2127 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2129 put_path_length = 0;
2130 msize = data_size + sizeof (struct PeerPutMessage);
2133 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2139 /* This is the first call made from clients file. So, we should search for the
2141 if (NULL == target_peer)
2144 struct Closest_Peer successor;
2146 memcpy (&key_value, key, sizeof (uint64_t));
2147 key_value = GNUNET_ntohll (key_value);
2149 successor = find_successor (key_value, GDS_FINGER_TYPE_NON_PREDECESSOR);
2150 best_known_dest = successor.best_known_destination;
2151 next_hop = successor.next_hop;
2152 intermediate_trail_id = successor.trail_id;
2154 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&best_known_dest, &my_identity))
2156 /* I am the destination. */
2157 GDS_DATACACHE_handle_put (expiration_time, key, 0, NULL,
2158 block_type,data_size,data);
2162 GNUNET_assert (NULL !=
2164 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop)));
2168 GNUNET_assert (NULL !=
2170 GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer)));
2173 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2174 pending->timeout = expiration_time;
2175 ppm = (struct PeerPutMessage *) &pending[1];
2176 pending->msg = &ppm->header;
2177 ppm->header.size = htons (msize);
2178 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_PUT);
2179 ppm->options = htonl (options);
2180 ppm->block_type = htonl (block_type);
2181 ppm->hop_count = htonl (hop_count + 1);
2182 ppm->desired_replication_level = htonl (desired_replication_level);
2183 ppm->put_path_length = htonl (put_path_length);
2184 ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
2185 ppm->best_known_destination = best_known_dest;
2188 pp = (struct GNUNET_PeerIdentity *) &ppm[1];
2189 if (put_path_length != 0)
2191 memcpy (pp, put_path,
2192 sizeof (struct GNUNET_PeerIdentity) * put_path_length);
2194 memcpy (&pp[put_path_length], data, data_size);
2195 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2196 target_friend->pending_count++;
2197 process_friend_queue (target_friend);
2202 * Construct a Get message and send it to target_peer.
2203 * @param key Key for the content
2204 * @param block_type Type of the block
2205 * @param options Routing options
2206 * @param desired_replication_level Desired replication count
2207 * @param best_known_dest Peer which should get this message. Same as target peer
2208 * if best_known_dest is a friend else its a finger.
2209 * @param intermediate_trail_id Trail id to reach to @a best_known_dest
2210 * in case it is a finger else set to 0.
2211 * @param target_peer Peer to which this message will be forwarded.
2212 * @param hop_count Number of hops traversed so far.
2213 * @param data Content to store
2214 * @param data_size Size of content @a data in bytes
2215 * @param get_path_length Total number of peers in @a get_path
2216 * @param get_path Number of peers traversed so far
2219 GDS_NEIGHBOURS_send_get (const struct GNUNET_HashCode *key,
2220 enum GNUNET_BLOCK_Type block_type,
2221 enum GNUNET_DHT_RouteOption options,
2222 uint32_t desired_replication_level,
2223 struct GNUNET_PeerIdentity best_known_dest,
2224 struct GNUNET_HashCode intermediate_trail_id,
2225 struct GNUNET_PeerIdentity *target_peer,
2227 uint32_t get_path_length,
2228 struct GNUNET_PeerIdentity *get_path)
2230 struct PeerGetMessage *pgm;
2231 struct P2PPendingMessage *pending;
2232 struct FriendInfo *target_friend;
2233 struct GNUNET_PeerIdentity *gp;
2236 msize = sizeof (struct PeerGetMessage) +
2237 (get_path_length * sizeof (struct GNUNET_PeerIdentity));
2239 /* In this case we don't make get_path_length = 0, as we need get path to
2240 * return the message back to querying client. */
2241 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2247 /* This is the first time we got request from our own client file. */
2248 if (NULL == target_peer)
2251 struct Closest_Peer successor;
2253 memcpy (&key_value, key, sizeof (uint64_t));
2254 key_value = GNUNET_ntohll (key_value);
2255 successor = find_successor (key_value, GDS_FINGER_TYPE_NON_PREDECESSOR);
2257 best_known_dest = successor.best_known_destination;
2258 intermediate_trail_id = successor.trail_id;
2260 /* I am the destination. I have the data. */
2261 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
2264 GDS_DATACACHE_handle_get (key,block_type, NULL, 0,
2265 NULL, 0, 1, &my_identity, NULL,&my_identity);
2271 GNUNET_assert (NULL !=
2273 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2274 &successor.next_hop)));
2280 GNUNET_assert (NULL !=
2282 GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer))); //FIXME: assertion fails.
2285 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2286 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
2287 pending->importance = 0; /* FIXME */
2288 pgm = (struct PeerGetMessage *) &pending[1];
2289 pending->msg = &pgm->header;
2290 pgm->header.size = htons (msize);
2291 pgm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_GET);
2292 pgm->get_path_length = htonl (get_path_length);
2293 pgm->best_known_destination = best_known_dest;
2295 pgm->intermediate_trail_id = intermediate_trail_id;
2296 pgm->hop_count = htonl (hop_count + 1);
2297 gp = (struct GNUNET_PeerIdentity *) &pgm[1];
2299 if (get_path_length != 0)
2301 memcpy (gp, get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity));
2304 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2305 target_friend->pending_count++;
2306 process_friend_queue (target_friend);
2311 * Send the get result to requesting client.
2312 * @param key Key of the requested data.
2313 * @param type Block type
2314 * @param target_peer Next peer to forward the message to.
2315 * @param source_peer Peer which has the data for the key.
2316 * @param put_path_length Number of peers in @a put_path
2317 * @param put_path Path taken to put the data at its stored location.
2318 * @param get_path_length Number of peers in @a get_path
2319 * @param get_path Path taken to reach to the location of the key.
2320 * @param expiration When will this result expire?
2321 * @param data Payload to store
2322 * @param data_size Size of the @a data
2325 GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key,
2326 enum GNUNET_BLOCK_Type type,
2327 const struct GNUNET_PeerIdentity *target_peer,
2328 const struct GNUNET_PeerIdentity *source_peer,
2329 unsigned int put_path_length,
2330 const struct GNUNET_PeerIdentity *put_path,
2331 unsigned int get_path_length,
2332 const struct GNUNET_PeerIdentity *get_path,
2333 struct GNUNET_TIME_Absolute expiration,
2334 const void *data, size_t data_size)
2336 struct PeerGetResultMessage *get_result;
2337 struct GNUNET_PeerIdentity *paths;
2338 struct P2PPendingMessage *pending;
2339 struct FriendInfo *target_friend;
2340 int current_path_index;
2343 msize = (put_path_length + get_path_length )* sizeof (struct GNUNET_PeerIdentity) +
2345 sizeof (struct PeerGetResultMessage);
2347 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2353 current_path_index = 0;
2354 if(get_path_length > 0)
2356 current_path_index = search_my_index(get_path, get_path_length);
2357 if (-1 == current_path_index)
2363 if (0 == current_path_index)
2365 GDS_CLIENTS_handle_reply (expiration, key, get_path_length,
2366 get_path, put_path_length,
2367 put_path, type, data_size, data);
2371 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2372 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
2373 pending->importance = 0;
2374 get_result = (struct PeerGetResultMessage *)&pending[1];
2375 pending->msg = &get_result->header;
2376 get_result->header.size = htons (msize);
2377 get_result->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_GET_RESULT);
2378 get_result->key = *key;
2379 get_result->querying_peer = *source_peer;
2380 get_result->expiration_time = expiration;
2381 get_result->get_path_length = htonl (get_path_length);
2382 get_result->put_path_length = htonl (put_path_length);
2383 paths = (struct GNUNET_PeerIdentity *)&get_result[1];
2384 memcpy (paths, put_path,
2385 put_path_length * sizeof (struct GNUNET_PeerIdentity));
2386 memcpy (&paths[put_path_length], get_path,
2387 get_path_length * sizeof (struct GNUNET_PeerIdentity));
2388 memcpy (&paths[put_path_length + get_path_length], data, data_size);
2390 GNUNET_assert (NULL !=
2392 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2393 &get_path[current_path_index - 1])));
2394 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2395 target_friend->pending_count++;
2396 process_friend_queue (target_friend);
2401 * Randomly choose one of your friends (which is not congested and have not crossed
2402 * trail threshold) from the friend_peermap
2403 * @return Friend Randomly chosen friend.
2404 * NULL in case friend peermap is empty, or all the friends are either
2405 * congested or have crossed trail threshold.
2407 static struct FriendInfo *
2408 select_random_friend ()
2410 unsigned int current_size;
2413 struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
2414 struct GNUNET_PeerIdentity key_ret;
2415 struct FriendInfo *friend;
2417 current_size = GNUNET_CONTAINER_multipeermap_size (friend_peermap);
2420 if (0 == current_size)
2423 index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, current_size);
2424 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
2426 /* Iterate till you don't reach to index. */
2427 for (j = 0; j < index ; j++)
2428 GNUNET_assert (GNUNET_YES ==
2429 GNUNET_CONTAINER_multipeermap_iterator_next (iter, NULL, NULL));
2432 /* Reset the index in friend peermap to 0 as we reached to the end. */
2433 if (j == current_size)
2436 GNUNET_CONTAINER_multipeermap_iterator_destroy (iter);
2437 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
2441 /* Get the friend stored at the index, j*/
2442 GNUNET_assert (GNUNET_YES ==
2443 GNUNET_CONTAINER_multipeermap_iterator_next (iter,
2445 (const void **)&friend));
2447 /* This friend is not congested and has not crossed trail threshold. */
2448 if ((TRAILS_THROUGH_FRIEND_THRESHOLD > friend->trails_count) &&
2449 (0 == GNUNET_TIME_absolute_get_remaining (friend->congestion_timestamp).rel_value_us))
2455 } while (j != index);
2457 GNUNET_CONTAINER_multipeermap_iterator_destroy (iter);
2463 * Compute 64 bit value of finger_identity corresponding to a finger index using
2465 * For all fingers, n.finger[i] = n + pow (2,i),
2466 * For predecessor, n.finger[PREDECESSOR_FINGER_ID] = n - 1, where
2467 * n = my_identity, i = finger_index, n.finger[i] = 64 bit finger value
2468 * @param finger_index Index corresponding to which we calculate 64 bit value.
2469 * @return 64 bit value.
2472 compute_finger_identity_value (unsigned int finger_index)
2476 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
2477 my_id64 = GNUNET_ntohll (my_id64);
2479 /* Are we looking for immediate predecessor? */
2480 if (PREDECESSOR_FINGER_ID == finger_index)
2481 return (my_id64 - 1);
2484 uint64_t add = (uint64_t)1 << finger_index;
2485 return (my_id64 + add);
2489 static struct GNUNET_TIME_Relative next_send_time;
2492 * Choose a random friend. Calculate the next finger identity to search,from
2493 * current_search_finger_index. Start looking for the trail to reach to
2494 * finger identity through this random friend.
2496 * @param cls closure for this task
2497 * @param tc the context under which the task is running
2500 send_find_finger_trail_message (void *cls,
2501 const struct GNUNET_SCHEDULER_TaskContext *tc)
2503 struct FriendInfo *target_friend;
2504 //struct GNUNET_TIME_Relative next_send_time;
2505 struct GNUNET_HashCode trail_id;
2506 struct GNUNET_HashCode intermediate_trail_id;
2507 unsigned int is_predecessor;
2508 uint64_t finger_id_value;
2510 /* Schedule another send_find_finger_trail_message task. */
2511 find_finger_trail_task =
2512 GNUNET_SCHEDULER_add_delayed (next_send_time,
2513 &send_find_finger_trail_message,
2516 /* No space in my routing table. (Source and destination peers also store entries
2517 * in their routing table). */
2518 if (GNUNET_YES == GDS_ROUTING_threshold_reached())
2522 target_friend = select_random_friend ();
2523 if (NULL == target_friend)
2528 finger_id_value = compute_finger_identity_value (current_search_finger_index);
2530 if (PREDECESSOR_FINGER_ID == current_search_finger_index)
2535 /* Generate a unique trail id for trail we are trying to setup. */
2536 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
2537 &trail_id, sizeof (trail_id));
2538 memset(&intermediate_trail_id, 0, sizeof (struct GNUNET_HashCode));
2540 GDS_NEIGHBOURS_send_trail_setup (my_identity, finger_id_value,
2541 target_friend->id, target_friend, 0, NULL,
2542 is_predecessor, trail_id,
2543 intermediate_trail_id);
2548 * In case there are already maximum number of possible trails to reach to a
2549 * finger, then check if the new trail's length is lesser than any of the
2551 * If yes then replace that old trail by new trail.
2553 * Note: Here we are taking length as a parameter to choose the best possible
2554 * trail, but there could be other parameters also like:
2555 * 1. duration of existence of a trail - older the better.
2556 * 2. if the new trail is completely disjoint than the
2557 * other trails, then may be choosing it is better.
2559 * @param existing_finger
2560 * @param new_finger_trail
2561 * @param new_finger_trail_length
2562 * @param new_finger_trail_id
2565 select_and_replace_trail (struct FingerInfo *existing_finger,
2566 const struct GNUNET_PeerIdentity *new_trail,
2567 unsigned int new_trail_length,
2568 struct GNUNET_HashCode new_trail_id)
2570 struct Trail *trail_list_iterator;
2571 unsigned int largest_trail_length;
2572 unsigned int largest_trail_index;
2573 struct Trail_Element *trail_element;
2576 largest_trail_length = new_trail_length;
2577 largest_trail_index = MAXIMUM_TRAILS_PER_FINGER + 1;
2579 GNUNET_assert (MAXIMUM_TRAILS_PER_FINGER == existing_finger->trails_count);
2581 for (i = 0; i < existing_finger->trails_count; i++)
2583 trail_list_iterator = &existing_finger->trail_list[i];
2584 if (trail_list_iterator->trail_length > largest_trail_length)
2586 largest_trail_length = trail_list_iterator->trail_length;
2587 largest_trail_index = i;
2591 /* New trail is not better than existing ones. Send trail teardown. */
2592 if (largest_trail_index == (MAXIMUM_TRAILS_PER_FINGER + 1))
2594 struct GNUNET_PeerIdentity next_hop;
2596 memcpy (&next_hop, &new_trail[0], sizeof(struct GNUNET_PeerIdentity));
2597 GDS_ROUTING_remove_trail (new_trail_id);
2598 GDS_NEIGHBOURS_send_trail_teardown (new_trail_id,
2599 GDS_ROUTING_SRC_TO_DEST,
2604 /* Send trail teardown message across the replaced trail. */
2605 struct Trail *replace_trail = &existing_finger->trail_list[largest_trail_index];
2606 existing_finger->trail_list[largest_trail_index].is_present = GNUNET_NO;
2607 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (replace_trail->trail_id));
2608 GDS_NEIGHBOURS_send_trail_teardown (replace_trail->trail_id,
2609 GDS_ROUTING_SRC_TO_DEST,
2610 replace_trail->trail_head->peer);
2611 /* Free the trail. */
2612 while (NULL != (trail_element = replace_trail->trail_head))
2614 GNUNET_CONTAINER_DLL_remove (replace_trail->trail_head,
2615 replace_trail->trail_tail, trail_element);
2616 GNUNET_free_non_null (trail_element);
2619 /* Add new trial at that location. */
2620 replace_trail->is_present = GNUNET_YES;
2621 replace_trail->trail_length = new_trail_length;
2622 replace_trail->trail_id = new_trail_id;
2623 //FIXME: Do we need to add pointers for head and tail.
2625 while (i < new_trail_length)
2627 struct Trail_Element *element = GNUNET_new (struct Trail_Element);
2628 element->peer = new_trail[i];
2630 GNUNET_CONTAINER_DLL_insert_tail (replace_trail->trail_head,
2631 replace_trail->trail_tail,
2638 * Check if the new trail to reach to finger is unique or do we already have
2639 * such a trail present for finger.
2640 * @param existing_finger Finger identity
2641 * @param new_trail New trail to reach @a existing_finger
2642 * @param trail_length Total number of peers in new_trail.
2643 * @return #GNUNET_YES if the new trail is unique
2644 * #GNUNET_NO if same trail is already present.
2647 is_new_trail_unique (struct FingerInfo *existing_finger,
2648 const struct GNUNET_PeerIdentity *new_trail,
2649 unsigned int trail_length)
2651 struct Trail *trail_list_iterator;
2652 struct Trail_Element *trail_element;
2655 int trail_unique = GNUNET_NO;
2657 GNUNET_assert (existing_finger->trails_count > 0);
2659 /* Iterate over list of trails. */
2660 for (i = 0; i < existing_finger->trails_count; i++)
2662 trail_list_iterator = &existing_finger->trail_list[i];
2663 GNUNET_assert (GNUNET_YES == trail_list_iterator->is_present);
2665 /* New trail and existing trail length are not same. */
2666 if (trail_list_iterator->trail_length != trail_length)
2668 trail_unique = GNUNET_YES;
2672 trail_element = trail_list_iterator->trail_head;
2673 for (j = 0; j < trail_list_iterator->trail_length; j++)
2675 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&new_trail[j],
2676 &trail_element->peer))
2678 trail_unique = GNUNET_YES;
2681 trail_element = trail_element->next;
2684 trail_unique = GNUNET_NO;
2687 return trail_unique;
2692 * Add a new trail to existing finger. This function is called only when finger
2693 * is not my own identity or a friend.
2694 * @param existing_finger Finger
2695 * @param new_finger_trail New trail from me to finger, NOT including endpoints
2696 * @param new_finger_trail_length Total number of peers in @a new_finger_trail
2697 * @param new_finger_trail_id Unique identifier of the trail.
2700 add_new_trail (struct FingerInfo *existing_finger,
2701 const struct GNUNET_PeerIdentity *new_trail,
2702 unsigned int new_trail_length,
2703 struct GNUNET_HashCode new_trail_id)
2705 struct Trail *trail_list_iterator;
2706 struct FriendInfo *first_friend;
2709 if (GNUNET_NO == is_new_trail_unique (existing_finger, new_trail,
2715 trail_list_iterator = &existing_finger->trail_list[existing_finger->trails_count];
2716 GNUNET_assert (GNUNET_NO == trail_list_iterator->is_present);
2717 trail_list_iterator->trail_id = new_trail_id;
2718 trail_list_iterator->trail_length = new_trail_length;
2719 existing_finger->trails_count++;
2720 trail_list_iterator->is_present = GNUNET_YES;
2722 GNUNET_assert (NULL == (GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2723 &existing_finger->finger_identity)));
2724 /* If finger is a friend then we never call this function. */
2725 GNUNET_assert (new_trail_length > 0);
2727 first_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2729 first_friend->trails_count++;
2731 for (i = 0; i < new_trail_length; i++)
2733 struct Trail_Element *element;
2735 element = GNUNET_new (struct Trail_Element);
2736 element->peer = new_trail[i];
2737 GNUNET_CONTAINER_DLL_insert_tail (trail_list_iterator->trail_head,
2738 trail_list_iterator->trail_tail,
2741 /* Do we need to add trail head and trail tail in the trail list itearator.*/
2747 * FIXME Check if this function is called for opposite direction if yes then
2748 * take it as parameter.
2749 * Get the next hop to send trail teardown message from routing table and
2750 * then delete the entry from routing table. Send trail teardown message for a
2751 * specific trail of a finger.
2752 * @param finger Finger whose trail is to be removed.
2753 * @param trail List of peers in trail from me to a finger, NOT including
2757 send_trail_teardown (struct FingerInfo *finger,
2758 struct Trail *trail)
2760 struct FriendInfo *friend;
2761 struct GNUNET_PeerIdentity *next_hop;
2763 next_hop = GDS_ROUTING_get_next_hop (trail->trail_id,
2764 GDS_ROUTING_SRC_TO_DEST);
2766 if (NULL == next_hop)
2771 GNUNET_assert (0 != GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
2774 GNUNET_assert (trail->is_present == GNUNET_YES);
2776 /* Finger is not a friend. */
2777 if (trail->trail_length > 0)
2779 GNUNET_assert (NULL != (friend =
2780 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2781 &trail->trail_head->peer)));
2785 GNUNET_assert (NULL != (friend =
2786 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2787 &finger->finger_identity)));
2790 GNUNET_assert (0 == GNUNET_CRYPTO_cmp_peer_identity (next_hop, &friend->id)); //Fixme: assertion fails.
2791 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail->trail_id));
2792 friend->trails_count--;
2793 GDS_NEIGHBOURS_send_trail_teardown (trail->trail_id,
2794 GDS_ROUTING_SRC_TO_DEST,
2800 * Send trail teardown message across all the trails to reach to finger.
2801 * @param finger Finger whose all the trail should be freed.
2804 send_all_finger_trails_teardown (struct FingerInfo *finger)
2808 for (i = 0; i < finger->trails_count; i++)
2810 struct Trail *trail;
2812 trail = &finger->trail_list[i];
2813 GNUNET_assert (trail->is_present == GNUNET_YES);
2814 send_trail_teardown (finger, trail);
2815 trail->is_present = GNUNET_NO;
2821 * Free a specific trail
2822 * @param trail List of peers to be freed.
2825 free_trail (struct Trail *trail)
2827 struct Trail_Element *trail_element;
2829 while (NULL != (trail_element = trail->trail_head))
2831 GNUNET_CONTAINER_DLL_remove (trail->trail_head,
2834 GNUNET_free_non_null (trail_element);
2836 trail->trail_head = NULL;
2837 trail->trail_tail = NULL;
2842 * Free finger and its trail.
2843 * @param finger Finger to be freed.
2846 free_finger (struct FingerInfo *finger, unsigned int finger_table_index)
2848 struct Trail *trail;
2851 /* Free all the trails to reach to finger */
2852 for (i = 0; i < finger->trails_count; i++)
2854 trail = &finger->trail_list[i];
2855 //FIXME: Check if there are any missing entry in this list because of
2856 // how we insert. If not then no need of this check.
2857 if (GNUNET_NO == trail->is_present)
2860 if (trail->trail_length > 0)
2864 trail->is_present = GNUNET_NO;
2867 finger->is_present = GNUNET_NO;
2868 memset ((void *)&finger_table[finger_table_index], 0, sizeof (finger_table[finger_table_index]));
2873 * FIXME: ensure that you are not adding any trail to reach to a friend which
2874 * is a finger. Also decide on should you increment trails count of a friend
2875 * which is also a finger.
2876 * Add a new entry in finger table at finger_table_index.
2877 * In case finger identity is me or a friend, then don't add a trail. NOTE
2878 * trail length to reach to a finger can be 0 only if the finger is a friend
2880 * In case a finger is a friend, then increment the trails count of the friend.
2881 * @param finger_identity Peer Identity of new finger
2882 * @param finger_trail Trail to reach from me to finger (excluding both end points).
2883 * @param finger_trail_length Total number of peers in @a finger_trail.
2884 * @param trail_id Unique identifier of the trail.
2885 * @param finger_table_index Index in finger table.
2888 add_new_finger (struct GNUNET_PeerIdentity finger_identity,
2889 const struct GNUNET_PeerIdentity *finger_trail,
2890 unsigned int finger_trail_length,
2891 struct GNUNET_HashCode trail_id,
2892 unsigned int finger_table_index)
2894 struct FingerInfo *new_entry;
2895 struct FriendInfo *first_trail_hop;
2896 struct Trail *trail;
2899 new_entry = GNUNET_new (struct FingerInfo);
2900 new_entry->finger_identity = finger_identity;
2901 new_entry->finger_table_index = finger_table_index;
2902 new_entry->is_present = GNUNET_YES;
2904 /* If the new entry is my own identity. */
2905 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity))
2907 new_entry->trails_count = 0;
2908 finger_table[finger_table_index] = *new_entry;
2909 GNUNET_free (new_entry);
2913 /* If finger is a friend, then we don't actually have a trail.
2914 * Just a trail id */
2915 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2918 new_entry->trail_list[0].trail_id = trail_id;
2919 new_entry->trails_count = 1;
2920 new_entry->trail_list[0].is_present = GNUNET_YES;
2921 new_entry->trail_list[0].trail_length = 0;
2922 new_entry->trail_list[0].trail_head = NULL;
2923 new_entry->trail_list[0].trail_tail = NULL;
2924 finger_table[finger_table_index] = *new_entry;
2925 GNUNET_assert (NULL !=
2927 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2928 &finger_identity)));
2930 first_trail_hop->trails_count++;
2931 GNUNET_free (new_entry);
2935 /* finger trail length can be 0 only in case if finger is my identity or
2936 finger is friend. We should never reach here. */
2937 GNUNET_assert (finger_trail_length > 0);
2939 GNUNET_assert (NULL !=
2941 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2942 &finger_trail[0])));
2943 new_entry->trails_count = 1;
2944 first_trail_hop->trails_count++;
2946 /* Copy the finger trail into trail. */
2947 trail = GNUNET_new (struct Trail);
2948 while (i < finger_trail_length)
2950 struct Trail_Element *element = GNUNET_new (struct Trail_Element);
2952 element->next = NULL;
2953 element->prev = NULL;
2954 element->peer = finger_trail[i];
2955 GNUNET_CONTAINER_DLL_insert_tail (trail->trail_head,
2961 /* Add trail to trail list. */
2962 new_entry->trail_list[0].trail_head = trail->trail_head;
2963 new_entry->trail_list[0].trail_tail = trail->trail_tail;
2964 new_entry->trail_list[0].trail_length = finger_trail_length;
2965 new_entry->trail_list[0].trail_id = trail_id;
2966 new_entry->trail_list[0].is_present = GNUNET_YES;
2967 finger_table[finger_table_index] = *new_entry;
2968 //GNUNET_free (new_entry);
2969 //GNUNET_free (trail);
2975 * Scan the trail to check if there is any other friend in the trail other than
2976 * first hop. If yes then shortcut the trail, send trail compression message to
2977 * peers which are no longer part of trail and send back the updated trail
2978 * and trail_length to calling function.
2979 * @param finger_identity Finger whose trail we will scan.
2980 * @param finger_trail [in, out] Trail to reach from source to finger,
2981 * @param finger_trail_length Total number of peers in original finger_trail.
2982 * @param finger_trail_id Unique identifier of the finger trail.
2983 * @return updated trail length in case we shortcut the trail, else original
2986 static struct GNUNET_PeerIdentity *
2987 scan_and_compress_trail (struct GNUNET_PeerIdentity finger_identity,
2988 const struct GNUNET_PeerIdentity *trail,
2989 unsigned int trail_length,
2990 struct GNUNET_HashCode trail_id,
2991 int *new_trail_length)
2993 struct FriendInfo *target_friend;
2994 struct GNUNET_PeerIdentity *new_trail;
2997 /* I am my own finger. */
2998 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity))
3000 *new_trail_length = 0;
3004 if (0 == trail_length)
3006 *new_trail_length = 0;
3010 /* If finger identity is a friend. */
3011 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger_identity))
3013 *new_trail_length = 0;
3015 /* If there is trail to reach this finger/friend */
3016 if (trail_length > 0)
3018 /* Finger is your first friend. */
3019 GDS_ROUTING_update_trail_next_hop (trail_id, finger_identity);
3020 GNUNET_assert (NULL !=
3022 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3026 GDS_NEIGHBOURS_send_trail_compression (my_identity,
3027 trail_id, finger_identity,
3033 /* For other cases, when its neither a friend nor my own identity.*/
3034 for (i = trail_length - 1; i > 0; i--)
3036 /* If the element at this index in trail is a friend. */
3037 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, &trail[i]))
3039 struct FriendInfo *target_friend;
3042 GNUNET_assert (NULL !=
3044 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3046 GDS_ROUTING_update_trail_next_hop (trail_id, trail[i]);
3047 GDS_NEIGHBOURS_send_trail_compression (my_identity,
3052 /* Copy the trail from index i to index (trail_length -1) into a new trail
3053 * and update new trail length */
3054 new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * (trail_length - i));
3055 while (i < trail_length)
3057 memcpy (&new_trail[j], &trail[i], sizeof(struct GNUNET_PeerIdentity));
3061 *new_trail_length = j+1;
3066 /* If we did not compress the trail, return the original trail back.*/
3067 new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * trail_length);
3068 *new_trail_length = trail_length;
3069 memcpy (new_trail, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
3075 * Periodic task to verify current successor. There can be multiple trails to reach
3076 * to successor, choose the shortest one and send verify successor message
3077 * across that trail.
3078 * @param cls closure for this task
3079 * @param tc the context under which the task is running
3082 send_verify_successor_message (void *cls,
3083 const struct GNUNET_SCHEDULER_TaskContext *tc)
3085 struct FriendInfo *target_friend;
3086 struct GNUNET_HashCode trail_id;
3088 struct GNUNET_TIME_Relative next_send_time;
3089 struct Trail *trail;
3090 struct Trail_Element *element;
3091 unsigned int trail_length;
3093 struct FingerInfo *successor;
3095 /* Schedule another send_find_finger_trail_message task. */
3096 next_send_time.rel_value_us =
3097 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
3098 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
3099 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us);
3100 send_verify_successor_task =
3101 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_verify_successor_message,
3104 successor = &finger_table[0];
3106 trail = &successor->trail_list[i];
3108 /* Store the successor for path tracking */
3109 if (track_topology && (NULL != GDS_stats))
3115 my_id_str = GNUNET_strdup (GNUNET_i2s (&my_identity));
3116 succ_id_str = GNUNET_strdup (GNUNET_i2s
3117 (&successor->finger_identity));
3118 GNUNET_asprintf (&key, "XDHT:0:%.4s:%.4s", my_id_str, succ_id_str);
3119 GNUNET_free (my_id_str);
3120 GNUNET_free (succ_id_str);
3121 GNUNET_STATISTICS_update (GDS_stats, "key", 1, 0);
3125 GNUNET_assert(0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
3126 &successor->finger_identity));
3128 /* Trail stored at this index. */
3129 GNUNET_assert (GNUNET_YES == trail->is_present);
3131 trail_id = trail->trail_id;
3132 trail_length = trail->trail_length;
3134 if (trail_length > 0)
3136 /* Copy the trail into peer list. */
3137 struct GNUNET_PeerIdentity peer_list[trail_length];
3139 element = trail->trail_head;
3140 while (j < trail_length)
3142 peer_list[j] = element->peer;
3143 element = element->next;
3147 GNUNET_assert (NULL != (target_friend =
3148 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3150 GDS_NEIGHBOURS_send_verify_successor_message (my_identity,
3151 successor->finger_identity,
3152 trail_id, peer_list, trail_length,
3158 GNUNET_assert (NULL != (target_friend =
3159 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3160 &successor->finger_identity)));
3161 GDS_NEIGHBOURS_send_verify_successor_message (my_identity,
3162 successor->finger_identity,
3171 * Update the current search finger index.
3173 * FIXME document parameters!
3176 update_current_search_finger_index (struct GNUNET_PeerIdentity finger_identity,
3177 unsigned int finger_table_index)
3179 struct FingerInfo *successor;
3181 /* FIXME correct this: only move current index periodically */
3182 if (finger_table_index != current_search_finger_index)
3185 successor = &finger_table[0];
3186 GNUNET_assert (GNUNET_YES == successor->is_present);
3188 /* We were looking for immediate successor. */
3189 if (0 == current_search_finger_index)
3191 /* Start looking for immediate predecessor. */
3192 current_search_finger_index = PREDECESSOR_FINGER_ID;
3194 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity))
3196 if (GNUNET_SCHEDULER_NO_TASK == send_verify_successor_task)
3197 send_verify_successor_task = GNUNET_SCHEDULER_add_now (&send_verify_successor_message, NULL);
3203 current_search_finger_index = current_search_finger_index - 1;
3209 * Get the least significant bit set in val.
3212 * @return Position of first bit set, 65 in case of error.
3215 find_set_bit (uint64_t val)
3235 return 65; /* Some other bit was set to 1 as well. */
3242 * Calculate finger_table_index from initial 64 bit finger identity value that
3243 * we send in trail setup message.
3244 * @param ultimate_destination_finger_value Value that we calculated from our
3245 * identity and finger_table_index.
3246 * @param is_predecessor Is the entry for predecessor or not?
3247 * @return finger_table_index Value between 0 <= finger_table_index <= 64
3248 * finger_table_index > PREDECESSOR_FINGER_ID, if error occurs.
3251 get_finger_table_index (uint64_t ultimate_destination_finger_value,
3252 unsigned int is_predecessor)
3256 unsigned int finger_table_index;
3258 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
3259 my_id64 = GNUNET_ntohll (my_id64);
3261 /* Is this a predecessor finger? */
3262 if (1 == is_predecessor)
3264 diff = my_id64 - ultimate_destination_finger_value;
3266 finger_table_index = PREDECESSOR_FINGER_ID;
3268 finger_table_index = PREDECESSOR_FINGER_ID + 1; //error value
3273 diff = ultimate_destination_finger_value - my_id64;
3274 finger_table_index = find_set_bit (diff);
3276 return finger_table_index;
3281 * Remove finger and its associated data structures from finger table.
3282 * @param finger Finger to be removed.
3285 remove_existing_finger (struct FingerInfo *existing_finger,
3286 unsigned int finger_table_index)
3288 struct FingerInfo *finger;
3290 finger = &finger_table[finger_table_index];
3291 GNUNET_assert (GNUNET_YES == finger->is_present);
3293 /* If I am my own finger, then we have no trails. */
3294 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
3297 finger->is_present = GNUNET_NO;
3298 memset ((void *)&finger_table[finger_table_index], 0,
3299 sizeof (finger_table[finger_table_index]));
3303 /* For all other fingers, send trail teardown across all the trails to reach
3304 finger, and free the finger. */
3305 send_all_finger_trails_teardown (finger);
3306 free_finger (finger, finger_table_index);
3312 * Check if there is already an entry in finger_table at finger_table_index.
3313 * We get the finger_table_index from 64bit finger value we got from the network.
3314 * -- If yes, then select the closest finger.
3315 * -- If new and existing finger are same, then check if you can store more
3317 * -- If yes then add trail, else keep the best trails to reach to the
3319 * -- If the new finger is closest, remove the existing entry, send trail
3320 * teardown message across all the trails to reach the existing entry.
3321 * Add the new finger.
3322 * -- If new and existing finger are different, and existing finger is closest
3324 * -- Update current_search_finger_index.
3325 * @param finger_identity Peer Identity of new finger
3326 * @param finger_trail Trail to reach the new finger
3327 * @param finger_trail_length Total number of peers in @a new_finger_trail.
3328 * @param is_predecessor Is this entry for predecessor in finger_table?
3329 * @param finger_value 64 bit value of finger identity that we got from network.
3330 * @param finger_trail_id Unique identifier of @finger_trail.
3333 finger_table_add (struct GNUNET_PeerIdentity finger_identity,
3334 const struct GNUNET_PeerIdentity *finger_trail,
3335 unsigned int finger_trail_length,
3336 unsigned int is_predecessor,
3337 uint64_t finger_value,
3338 struct GNUNET_HashCode finger_trail_id)
3340 struct FingerInfo *existing_finger;
3341 const struct GNUNET_PeerIdentity *closest_peer;
3342 struct FingerInfo *successor;
3343 int updated_finger_trail_length;
3344 unsigned int finger_table_index;
3346 /* Get the finger_table_index corresponding to finger_value we got from network.*/
3347 finger_table_index = get_finger_table_index (finger_value, is_predecessor);
3349 /* Invalid finger_table_index. */
3350 if ((finger_table_index > PREDECESSOR_FINGER_ID))
3352 GNUNET_break_op (0);
3356 /* New entry same as successor. */
3357 if ((0 != finger_table_index) &&
3358 (PREDECESSOR_FINGER_ID != finger_table_index))
3360 successor = &finger_table[0];
3361 if (GNUNET_NO == successor->is_present)
3363 GNUNET_break_op (0);
3366 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity,
3367 &successor->finger_identity))
3369 current_search_finger_index = 0;
3370 /* We slow down the find_finger_trail_task as we have completed the circle. */
3371 next_send_time = GNUNET_TIME_STD_BACKOFF(next_send_time);
3376 struct FingerInfo prev_finger;
3377 prev_finger = finger_table[finger_table_index - 1];
3378 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity,
3379 &prev_finger.finger_identity))
3381 current_search_finger_index--;
3386 existing_finger = &finger_table[finger_table_index];
3388 /* No entry present in finger_table for given finger map index. */
3389 if (GNUNET_NO == existing_finger->is_present)
3391 struct GNUNET_PeerIdentity *updated_trail;
3393 /* Shorten the trail if possible. */
3394 updated_finger_trail_length = finger_trail_length;
3395 updated_trail = scan_and_compress_trail (finger_identity, finger_trail,
3396 finger_trail_length,
3398 &updated_finger_trail_length);
3400 add_new_finger (finger_identity, updated_trail,
3401 updated_finger_trail_length,
3402 finger_trail_id, finger_table_index);
3403 update_current_search_finger_index (finger_identity,
3404 finger_table_index);
3409 /* If existing entry and finger identity are not same. */
3410 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity),
3413 closest_peer = select_closest_peer (&existing_finger->finger_identity,
3418 /* If the new finger is the closest peer. */
3419 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, closest_peer))
3421 struct GNUNET_PeerIdentity *updated_trail;
3422 /* Shorten the trail if possible. */
3423 updated_finger_trail_length = finger_trail_length;
3425 scan_and_compress_trail (finger_identity, finger_trail,
3426 finger_trail_length, finger_trail_id,
3427 &updated_finger_trail_length);
3428 remove_existing_finger (existing_finger, finger_table_index);
3429 add_new_finger (finger_identity, updated_trail, updated_finger_trail_length,
3430 finger_trail_id, finger_table_index);
3435 /* Existing finger is the closest one. We need to send trail teardown
3436 across the trail setup in routing table of all the peers. */
3437 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, &my_identity))
3439 if (finger_trail_length > 0)
3440 GDS_NEIGHBOURS_send_trail_teardown (finger_trail_id,
3441 GDS_ROUTING_SRC_TO_DEST,
3444 GDS_NEIGHBOURS_send_trail_teardown (finger_trail_id,
3445 GDS_ROUTING_SRC_TO_DEST,
3452 /* If both new and existing entry are same as my_identity, then do nothing. */
3453 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity),
3458 /* If the existing finger is not a friend. */
3460 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3461 &existing_finger->finger_identity))
3463 struct GNUNET_PeerIdentity *updated_trail;
3465 /* Shorten the trail if possible. */
3466 updated_finger_trail_length = finger_trail_length;
3468 scan_and_compress_trail (finger_identity, finger_trail,
3469 finger_trail_length, finger_trail_id,
3470 &updated_finger_trail_length);
3471 /* If there is space to store more trails. */
3472 if (existing_finger->trails_count < MAXIMUM_TRAILS_PER_FINGER)
3473 add_new_trail (existing_finger, updated_trail,
3474 updated_finger_trail_length, finger_trail_id);
3476 select_and_replace_trail (existing_finger, updated_trail,
3477 updated_finger_trail_length, finger_trail_id);
3481 update_current_search_finger_index (finger_identity, finger_table_index);
3486 * Core handler for P2P put messages.
3487 * @param cls closure
3488 * @param peer sender of the request
3489 * @param message message
3490 * @return #GNUNET_OK to keep the connection open,
3491 * #GNUNET_SYSERR to close it (signal serious error)
3494 handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer,
3495 const struct GNUNET_MessageHeader *message)
3497 struct PeerPutMessage *put;
3498 struct GNUNET_PeerIdentity *put_path;
3499 struct GNUNET_PeerIdentity best_known_dest;
3500 struct GNUNET_HashCode intermediate_trail_id;
3501 struct GNUNET_PeerIdentity *next_hop;
3502 enum GNUNET_DHT_RouteOption options;
3503 struct GNUNET_HashCode test_key;
3507 size_t payload_size;
3510 msize = ntohs (message->size);
3511 if (msize < sizeof (struct PeerPutMessage))
3513 GNUNET_break_op (0);
3517 put = (struct PeerPutMessage *) message;
3518 putlen = ntohl (put->put_path_length);
3522 sizeof (struct PeerPutMessage) +
3523 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
3525 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3527 GNUNET_break_op (0);
3531 best_known_dest = put->best_known_destination;
3532 put_path = (struct GNUNET_PeerIdentity *) &put[1];
3533 payload = &put_path[putlen];
3534 options = ntohl (put->options);
3535 intermediate_trail_id = put->intermediate_trail_id;
3537 payload_size = msize - (sizeof (struct PeerPutMessage) +
3538 putlen * sizeof (struct GNUNET_PeerIdentity));
3540 switch (GNUNET_BLOCK_get_key (GDS_block_context, ntohl (put->block_type),
3541 payload, payload_size, &test_key))
3544 if (0 != memcmp (&test_key, &put->key, sizeof (struct GNUNET_HashCode)))
3546 char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key));
3547 GNUNET_break_op (0);
3548 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3549 "PUT with key `%s' for block with key %s\n",
3550 put_s, GNUNET_h2s_full (&test_key));
3551 GNUNET_free (put_s);
3556 GNUNET_break_op (0);
3559 /* cannot verify, good luck */
3563 if (ntohl (put->block_type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
3565 switch (GNUNET_BLOCK_evaluate (GDS_block_context,
3566 ntohl (put->block_type),
3568 NULL, 0, /* bloom filer */
3569 NULL, 0, /* xquery */
3570 payload, payload_size))
3572 case GNUNET_BLOCK_EVALUATION_OK_MORE:
3573 case GNUNET_BLOCK_EVALUATION_OK_LAST:
3576 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
3577 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
3578 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
3579 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
3580 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
3581 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
3583 GNUNET_break_op (0);
3588 /* extend 'put path' by sender */
3589 struct GNUNET_PeerIdentity pp[putlen + 1];
3590 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
3592 memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity));
3599 memcpy (&key_value, &(put->key), sizeof (uint64_t));
3600 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&best_known_dest, &my_identity)))
3602 next_hop = GDS_ROUTING_get_next_hop (intermediate_trail_id,
3603 GDS_ROUTING_SRC_TO_DEST);
3604 if (NULL == next_hop)
3606 GNUNET_STATISTICS_update (GDS_stats,
3607 gettext_noop ("# Next hop to forward the packet not found "
3608 "trail setup request, packet dropped."),
3610 return GNUNET_SYSERR;
3615 struct Closest_Peer successor;
3616 key_value = GNUNET_ntohll (key_value);
3617 successor = find_successor (key_value, GDS_FINGER_TYPE_NON_PREDECESSOR);
3619 next_hop = GNUNET_new (struct GNUNET_PeerIdentity);
3620 *next_hop = successor.next_hop;
3621 intermediate_trail_id = successor.trail_id;
3622 best_known_dest = successor.best_known_destination;
3625 GDS_CLIENTS_process_put (options,
3626 ntohl (put->block_type),
3627 ntohl (put->hop_count),
3628 ntohl (put->desired_replication_level),
3630 GNUNET_TIME_absolute_ntoh (put->expiration_time),
3635 /* I am the final destination */
3636 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &best_known_dest))
3638 GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time),
3639 &(put->key),putlen, pp, ntohl (put->block_type),
3640 payload_size, payload);
3644 GDS_NEIGHBOURS_send_put (&put->key,
3645 ntohl (put->block_type),ntohl (put->options),
3646 ntohl (put->desired_replication_level),
3647 best_known_dest, intermediate_trail_id, next_hop,
3648 ntohl (put->hop_count), putlen, pp,
3649 GNUNET_TIME_absolute_ntoh (put->expiration_time),
3650 payload, payload_size);
3657 * Core handler for p2p get requests.
3659 * @param cls closure
3660 * @param peer sender of the request
3661 * @param message message
3662 * @return #GNUNET_OK to keep the connection open,
3663 * #GNUNET_SYSERR to close it (signal serious error)
3666 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
3667 const struct GNUNET_MessageHeader *message)
3669 const struct PeerGetMessage *get;
3670 const struct GNUNET_PeerIdentity *get_path;
3671 struct GNUNET_PeerIdentity best_known_dest;
3672 struct GNUNET_HashCode intermediate_trail_id;
3673 struct GNUNET_PeerIdentity *next_hop;
3674 uint32_t get_length;
3678 msize = ntohs (message->size);
3679 if (msize < sizeof (struct PeerGetMessage))
3681 GNUNET_break_op (0);
3685 get = (const struct PeerGetMessage *)message;
3686 get_length = ntohl (get->get_path_length);
3687 best_known_dest = get->best_known_destination;
3688 intermediate_trail_id = get->intermediate_trail_id;
3689 get_path = (const struct GNUNET_PeerIdentity *)&get[1];
3692 sizeof (struct PeerGetMessage) +
3693 get_length * sizeof (struct GNUNET_PeerIdentity)) ||
3695 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3697 GNUNET_break_op (0);
3701 /* Add sender to get path */
3702 struct GNUNET_PeerIdentity gp[get_length + 1];
3704 memcpy (gp, get_path, get_length * sizeof (struct GNUNET_PeerIdentity));
3705 gp[get_length] = *peer;
3706 get_length = get_length + 1;
3708 memcpy (&key_value, &(get->key), sizeof (uint64_t));
3709 key_value = GNUNET_ntohll (key_value);
3711 /* I am not the final destination. I am part of trail to reach final dest. */
3712 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&best_known_dest, &my_identity)))
3714 next_hop = GDS_ROUTING_get_next_hop (intermediate_trail_id,
3715 GDS_ROUTING_SRC_TO_DEST);
3716 if (NULL == next_hop)
3718 GNUNET_STATISTICS_update (GDS_stats,
3719 gettext_noop ("# Next hop to forward the packet not found "
3720 "GET request, packet dropped."),
3722 return GNUNET_SYSERR;
3727 struct Closest_Peer successor;
3729 successor = find_successor (key_value, GDS_FINGER_TYPE_NON_PREDECESSOR);
3730 next_hop = GNUNET_new (struct GNUNET_PeerIdentity);
3731 *next_hop = successor.next_hop;
3732 best_known_dest = successor.best_known_destination;
3733 intermediate_trail_id = successor.trail_id;
3736 GDS_CLIENTS_process_get (get->options, get->block_type,get->hop_count,
3737 get->desired_replication_level, get->get_path_length,
3739 /* I am the final destination. */
3740 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, &best_known_dest))
3742 struct GNUNET_PeerIdentity final_get_path[get_length+1];
3744 memcpy (final_get_path, gp, get_length * sizeof (struct GNUNET_PeerIdentity));
3745 memcpy (&final_get_path[get_length], &my_identity, sizeof (struct GNUNET_PeerIdentity));
3746 get_length = get_length + 1;
3748 GDS_DATACACHE_handle_get (&(get->key),(get->block_type), NULL, 0, NULL, 0,
3749 get_length, final_get_path,
3750 &final_get_path[get_length-2], &my_identity);
3754 GDS_NEIGHBOURS_send_get (&(get->key), get->block_type, get->options,
3755 get->desired_replication_level, best_known_dest,
3756 intermediate_trail_id, next_hop, 0,
3764 * Core handler for get result
3765 * @param cls closure
3766 * @param peer sender of the request
3767 * @param message message
3768 * @return #GNUNET_OK to keep the connection open,
3769 * #GNUNET_SYSERR to close it (signal serious error)
3772 handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer,
3773 const struct GNUNET_MessageHeader *message)
3775 const struct PeerGetResultMessage *get_result;
3776 const struct GNUNET_PeerIdentity *get_path;
3777 const struct GNUNET_PeerIdentity *put_path;
3778 const void *payload;
3779 size_t payload_size;
3781 unsigned int getlen;
3782 unsigned int putlen;
3783 int current_path_index;
3785 msize = ntohs (message->size);
3786 if (msize < sizeof (struct PeerGetResultMessage))
3788 GNUNET_break_op (0);
3792 get_result = (const struct PeerGetResultMessage *)message;
3793 getlen = ntohl (get_result->get_path_length);
3794 putlen = ntohl (get_result->put_path_length);
3797 sizeof (struct PeerGetResultMessage) +
3798 getlen * sizeof (struct GNUNET_PeerIdentity) +
3799 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
3801 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity) ||
3803 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))))
3805 GNUNET_break_op (0);
3809 put_path = (const struct GNUNET_PeerIdentity *) &get_result[1];
3810 get_path = &put_path[putlen];
3811 payload = (const void *) &get_path[getlen];
3812 payload_size = msize - (sizeof (struct PeerGetResultMessage) +
3813 (getlen + putlen) * sizeof (struct GNUNET_PeerIdentity));
3815 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &(get_path[0]))))
3817 GDS_CLIENTS_handle_reply (get_result->expiration_time, &(get_result->key),
3818 getlen, get_path, putlen,
3819 put_path, get_result->type, payload_size, payload);
3824 current_path_index = search_my_index (get_path, getlen);
3825 if (-1 == current_path_index )
3828 return GNUNET_SYSERR;
3830 GDS_NEIGHBOURS_send_get_result (&(get_result->key), get_result->type,
3831 &get_path[current_path_index - 1],
3832 &(get_result->querying_peer), putlen, put_path,
3833 getlen, get_path, get_result->expiration_time,
3834 payload, payload_size);
3837 return GNUNET_SYSERR;
3842 * Find the next hop to pass trail setup message. First find the local best known
3843 * hop from your own identity, friends and finger. If you were part of trail,
3844 * then get the next hop from routing table. Compare next_hop from routing table
3845 * and local best known hop, and return the closest one to final_dest_finger_val
3846 * @param final_dest_finger_val 64 bit value of finger identity
3847 * @param intermediate_trail_id If you are part of trail to reach to some other
3848 * finger, then it is the trail id to reach to
3849 * that finger, else set to 0.
3850 * @param is_predecessor Are we looking for closest successor or predecessor.
3851 * @param current_dest In case you are part of trail, then finger to which
3852 * we should forward the message. Else my own identity
3853 * @return Closest Peer for @a final_dest_finger_val
3855 static struct Closest_Peer
3856 get_local_best_known_next_hop (uint64_t final_dest_finger_val,
3857 struct GNUNET_HashCode intermediate_trail_id,
3858 unsigned int is_predecessor,
3859 struct GNUNET_PeerIdentity prev_hop,
3860 struct GNUNET_PeerIdentity source,
3861 struct GNUNET_PeerIdentity *current_dest)
3863 struct Closest_Peer peer;
3865 /* Find a local best known peer. */
3866 peer = find_successor (final_dest_finger_val, is_predecessor);//FIXME: chnage to better name
3868 /* Am I just a part of a trail towards a finger (current_destination)? */
3869 /* Select best successor among one found locally and current_destination
3870 * that we got from network.*/
3871 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, current_dest) &&
3872 0 != GNUNET_CRYPTO_cmp_peer_identity (&peer.best_known_destination,
3875 const struct GNUNET_PeerIdentity *closest_peer;
3877 closest_peer = select_closest_peer (&peer.best_known_destination,
3879 final_dest_finger_val,
3882 /* Is current dest (end point of the trail of which I am a part) closest_peer? */
3883 if (0 == GNUNET_CRYPTO_cmp_peer_identity (current_dest, closest_peer))
3885 struct GNUNET_PeerIdentity *next_hop;
3887 next_hop = GDS_ROUTING_get_next_hop (intermediate_trail_id,
3888 GDS_ROUTING_SRC_TO_DEST);
3889 /* It may happen that trail teardown message got delayed and hence,
3890 the previous hop sent the message over intermediate trail id.In that
3891 case next_hop could be NULL. */
3892 if(NULL != next_hop)
3894 peer.next_hop = *next_hop;
3895 peer.best_known_destination = *current_dest;
3896 peer.trail_id = intermediate_trail_id;
3904 * Core handle for PeerTrailSetupMessage.
3905 * @param cls closure
3906 * @param message message
3907 * @param peer peer identity this notification is about
3908 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3911 handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer,
3912 const struct GNUNET_MessageHeader *message)
3914 const struct PeerTrailSetupMessage *trail_setup;
3915 const struct GNUNET_PeerIdentity *trail_peer_list;
3916 struct GNUNET_PeerIdentity current_dest;
3917 struct FriendInfo *target_friend;
3918 struct GNUNET_PeerIdentity source;
3919 uint64_t final_dest_finger_val;
3920 struct GNUNET_HashCode intermediate_trail_id;
3921 struct GNUNET_HashCode trail_id;
3922 unsigned int is_predecessor;
3923 uint32_t trail_length;
3927 msize = ntohs (message->size);
3928 if (msize < sizeof (struct PeerTrailSetupMessage))
3930 GNUNET_break_op (0);
3931 return GNUNET_SYSERR;
3934 trail_setup = (const struct PeerTrailSetupMessage *) message;
3935 trail_length = (msize - sizeof (struct PeerTrailSetupMessage))/
3936 sizeof (struct GNUNET_PeerIdentity);
3937 if ((msize - sizeof (struct PeerTrailSetupMessage)) %
3938 sizeof (struct GNUNET_PeerIdentity) != 0)
3940 GNUNET_break_op (0);
3944 trail_peer_list = (const struct GNUNET_PeerIdentity *)&trail_setup[1];
3945 current_dest = trail_setup->best_known_destination;
3946 trail_id = trail_setup->trail_id;
3947 final_dest_finger_val =
3948 GNUNET_ntohll (trail_setup->final_destination_finger_value);
3949 source = trail_setup->source_peer;
3950 is_predecessor = ntohl (trail_setup->is_predecessor);
3951 intermediate_trail_id = trail_setup->intermediate_trail_id;
3953 /* Did the friend insert its ID in the trail list? */
3954 if (trail_length > 0 &&
3955 0 != memcmp (&trail_peer_list[trail_length-1], peer, sizeof (*peer)))
3957 GNUNET_break_op (0);
3958 return GNUNET_SYSERR;
3961 /* If I was the source and got the message back, then set trail length to 0.*/
3962 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, &source))
3964 /* IF (!) the peers know the destinations of the trails in their routing
3967 * This shoud only happen after 1 hop, since the first message is sent
3968 * to random friend, and we can happen to be on the best trail to the dest.
3969 * If the first friend selects someone else, the request should never come
3974 // GNUNET_break_op (1 == trail_length);
3978 /* Check if you are present in the trail seen so far? */
3979 if(trail_length > 0)
3981 for (i = 0; i < trail_length ; i++)
3983 if(0 == GNUNET_CRYPTO_cmp_peer_identity(&trail_peer_list[i],&my_identity))
3985 //Here if you already were present in the trail. then you
3986 // shoudl trail length to i + 1
3993 /* Is my routing table full? */
3994 if (GNUNET_YES == GDS_ROUTING_threshold_reached())
3996 GNUNET_assert (NULL !=
3998 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer)));
3999 GDS_NEIGHBOURS_send_trail_rejection (source, final_dest_finger_val,
4000 my_identity, is_predecessor,
4001 trail_peer_list, trail_length,
4002 trail_id, target_friend,
4003 CONGESTION_TIMEOUT);
4007 /* Get the next hop to forward the trail setup request. */
4008 struct Closest_Peer next_peer =
4009 get_local_best_known_next_hop (final_dest_finger_val,
4010 intermediate_trail_id,
4016 /* Am I the final destination? */
4017 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&next_peer.best_known_destination,
4020 /* If I was not the source of this message for which now I am destination */
4021 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&source, &my_identity))
4023 GDS_ROUTING_add (trail_id, *peer, my_identity);
4026 if(0 == GNUNET_CRYPTO_cmp_peer_identity (&source, &my_identity))
4028 finger_table_add (my_identity, NULL, 0, is_predecessor,
4029 final_dest_finger_val, trail_id);
4033 if (trail_length > 0)
4034 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
4036 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &source);
4037 if (NULL == target_friend)
4039 GNUNET_break_op (0);
4040 return GNUNET_SYSERR;
4043 GDS_NEIGHBOURS_send_trail_setup_result (source,
4045 target_friend, trail_length,
4048 final_dest_finger_val,trail_id);
4050 else /* I'm not the final destination. */
4052 GNUNET_assert (NULL !=
4054 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4055 &next_peer.next_hop)));
4057 if (0 != GNUNET_CRYPTO_cmp_peer_identity(&my_identity, &source))
4059 /* Add yourself to list of peers. */
4060 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
4062 memcpy (peer_list, trail_peer_list,
4063 trail_length * sizeof (struct GNUNET_PeerIdentity));
4064 peer_list[trail_length] = my_identity;
4066 GDS_NEIGHBOURS_send_trail_setup (source,
4067 final_dest_finger_val,
4068 next_peer.best_known_destination,
4069 target_friend, trail_length + 1, peer_list,
4070 is_predecessor, trail_id,
4071 next_peer.trail_id);
4074 GDS_NEIGHBOURS_send_trail_setup (source,
4075 final_dest_finger_val,
4076 next_peer.best_known_destination,
4077 target_friend, 0, NULL,
4078 is_predecessor, trail_id,
4079 next_peer.trail_id);
4085 /* FIXME: here we are calculating my_index and comparing also in this function.
4086 And we are doing it again here in this function. Re factor the code. */
4088 * FIXME: Should we call this function everywhere in all the handle functions
4089 * where we have a trail to verify from or a trail id. something like
4090 * if prev hop is not same then drop the message.
4091 * Check if sender_peer and peer from which we should receive the message are
4092 * same or different.
4093 * @param trail_peer_list List of peers in trail
4094 * @param trail_length Total number of peers in @a trail_peer_list
4095 * @param sender_peer Peer from which we got the message.
4096 * @param finger_identity Finger to which trail is setup. It is not part of trail.
4097 * @return #GNUNET_YES if sender_peer and peer from which we should receive the
4098 * message are different.
4099 * #GNUNET_NO if sender_peer and peer from which we should receive the
4100 * message are different.
4103 is_sender_peer_correct (const struct GNUNET_PeerIdentity *trail_peer_list,
4104 unsigned int trail_length,
4105 const struct GNUNET_PeerIdentity *sender_peer,
4106 struct GNUNET_PeerIdentity finger_identity,
4107 struct GNUNET_PeerIdentity source_peer)
4111 /* I am the source peer. */
4112 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&source_peer,
4115 /* Is the first element of the trail is sender_peer.*/
4116 if (trail_length > 0)
4118 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&trail_peer_list[0],
4124 /* Is finger the sender peer? */
4125 if (0 != GNUNET_CRYPTO_cmp_peer_identity (sender_peer,
4132 /* Get my current location in the trail. */
4133 my_index = search_my_index (trail_peer_list, trail_length);
4137 /* I am the last element in the trail. */
4138 if ((trail_length - 1) == my_index)
4140 /* Is finger the sender_peer? */
4141 if (0 != GNUNET_CRYPTO_cmp_peer_identity (sender_peer,
4147 /* Is peer after me in trail the sender peer? */
4148 if (0 != GNUNET_CRYPTO_cmp_peer_identity (sender_peer,
4149 &trail_peer_list[my_index + 1]))
4159 * FIXME: we should also add a case where we search if we are present in the trail
4161 * Core handle for p2p trail setup result messages.
4163 * @param message message
4164 * @param peer sender of this message.
4165 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4168 handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer,
4169 const struct GNUNET_MessageHeader *message)
4171 const struct PeerTrailSetupResultMessage *trail_result;
4172 const struct GNUNET_PeerIdentity *trail_peer_list;
4173 struct GNUNET_PeerIdentity next_hop;
4174 struct FriendInfo *target_friend;
4175 struct GNUNET_PeerIdentity querying_peer;
4176 struct GNUNET_PeerIdentity finger_identity;
4177 uint32_t trail_length;
4178 uint64_t ulitmate_destination_finger_value;
4179 uint32_t is_predecessor;
4180 struct GNUNET_HashCode trail_id;
4184 msize = ntohs (message->size);
4185 if (msize < sizeof (struct PeerTrailSetupResultMessage))
4187 GNUNET_break_op (0);
4191 trail_result = (const struct PeerTrailSetupResultMessage *) message;
4192 trail_length = (msize - sizeof (struct PeerTrailSetupResultMessage))/
4193 sizeof (struct GNUNET_PeerIdentity);
4194 if ((msize - sizeof (struct PeerTrailSetupResultMessage)) %
4195 sizeof (struct GNUNET_PeerIdentity) != 0)
4197 GNUNET_break_op (0);
4201 is_predecessor = ntohl (trail_result->is_predecessor);
4202 querying_peer = trail_result->querying_peer;
4203 finger_identity = trail_result->finger_identity;
4204 trail_id = trail_result->trail_id;
4205 trail_peer_list = (const struct GNUNET_PeerIdentity *) &trail_result[1];
4206 ulitmate_destination_finger_value =
4207 GNUNET_ntohll (trail_result->ulitmate_destination_finger_value);
4209 /* FIXME: here we are calculating my_index and comparing also in this function.
4210 And we are doing it again here in this function. Re factor the code. */
4211 /* Ensure that sender peer is the peer from which we were expecting the message. */
4213 if (GNUNET_NO == is_sender_peer_correct (trail_peer_list,
4215 peer, finger_identity, querying_peer))
4217 GNUNET_break_op (0);
4218 return GNUNET_SYSERR;
4222 /*TODO:URGENT Check if I am already present in the trail. If yes then its an error,
4223 as in trail setup we ensure that it should never happen. */
4225 /* Am I the one who initiated the query? */
4226 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&querying_peer, &my_identity)))
4228 /* If I am my own finger identity, error. */
4229 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity))
4231 GNUNET_break_op (0);
4232 return GNUNET_SYSERR;
4234 GDS_ROUTING_add (trail_id, my_identity, *peer);
4235 finger_table_add (finger_identity, trail_peer_list, trail_length,
4236 is_predecessor, ulitmate_destination_finger_value, trail_id);
4240 /* Get my location in the trail. */
4241 my_index = search_my_index (trail_peer_list, trail_length);
4245 return GNUNET_SYSERR;
4249 next_hop = trail_result->querying_peer;
4251 next_hop = trail_peer_list[my_index - 1];
4253 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
4254 if (NULL == target_friend)
4256 GNUNET_break_op (0);
4257 return GNUNET_SYSERR;
4260 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->querying_peer),
4261 &(trail_result->finger_identity))))
4263 GNUNET_break_op (0);
4264 return GNUNET_SYSERR;
4267 GDS_ROUTING_add (trail_id, next_hop, *peer);
4269 GDS_NEIGHBOURS_send_trail_setup_result (querying_peer, finger_identity,
4270 target_friend, trail_length, trail_peer_list,
4272 ulitmate_destination_finger_value,
4280 * @param trail Trail to be inverted
4281 * @param trail_length Total number of peers in the trail.
4282 * @return Updated trail
4284 static struct GNUNET_PeerIdentity *
4285 invert_trail (const struct GNUNET_PeerIdentity *trail,
4286 unsigned int trail_length)
4290 struct GNUNET_PeerIdentity *inverted_trail;
4292 inverted_trail = GNUNET_malloc (sizeof(struct GNUNET_PeerIdentity) *
4295 j = trail_length - 1;
4296 while (i < trail_length)
4298 inverted_trail[i] = trail[j];
4303 GNUNET_assert(NULL != GNUNET_CONTAINER_multipeermap_get(friend_peermap,
4304 &inverted_trail[0]));
4305 return inverted_trail;
4310 * Return the shortest trail among all the trails to reach to finger from me.
4311 * @param finger Finger
4312 * @param shortest_trail_length[out] Trail length of shortest trail from me
4314 * @return Shortest trail.
4316 static struct GNUNET_PeerIdentity *
4317 get_shortest_trail (struct FingerInfo *finger,
4318 unsigned int *trail_length)
4320 struct Trail *trail;
4321 unsigned int flag = 0;
4322 unsigned int shortest_trail_index = 0;
4323 int shortest_trail_length = -1;
4324 struct Trail_Element *trail_element;
4325 struct GNUNET_PeerIdentity *trail_list;
4328 trail = GNUNET_new (struct Trail);
4330 /* Get the shortest trail to reach to current successor. */
4331 for (i = 0; i < finger->trails_count; i++)
4333 trail = &finger->trail_list[i];
4337 shortest_trail_index = i;
4338 shortest_trail_length = trail->trail_length;
4343 if (shortest_trail_length > trail->trail_length)
4345 shortest_trail_index = i;
4346 shortest_trail_length = trail->trail_length;
4351 /* Copy the shortest trail and return. */
4352 trail = &finger->trail_list[shortest_trail_index];
4353 trail_element = trail->trail_head;
4355 trail_list = GNUNET_malloc (sizeof(struct GNUNET_PeerIdentity)*
4356 shortest_trail_length);
4358 for(i = 0; i < shortest_trail_length; i++,trail_element = trail_element->next)
4360 trail_list[i] = trail_element->peer;
4363 GNUNET_assert(shortest_trail_length != -1);
4365 *trail_length = shortest_trail_length;
4370 * Check if trail_1 and trail_2 have any common element. If yes then join
4371 * them at common element. trail_1 always preceeds trail_2 in joined trail.
4373 * @param trail_1_len
4375 * @param trail_2_len
4376 * @param joined_trail_len
4379 static struct GNUNET_PeerIdentity *
4380 check_for_duplicate_entries (const struct GNUNET_PeerIdentity *trail_1,
4381 unsigned int trail_1_len,
4382 struct GNUNET_PeerIdentity *trail_2,
4383 unsigned int trail_2_len,
4384 unsigned int *joined_trail_len)
4386 struct GNUNET_PeerIdentity *joined_trail;
4391 for (i = 0; i < trail_1_len; i++)
4393 for (j = 0; j < trail_2_len; j++)
4395 if(0 != GNUNET_CRYPTO_cmp_peer_identity (&trail_1[i],&trail_2[j]))
4398 *joined_trail_len = i + (trail_2_len - j);
4399 joined_trail = GNUNET_malloc (*joined_trail_len *
4400 sizeof(struct GNUNET_PeerIdentity));
4403 /* Copy all the elements from 0 to i into joined_trail. */
4404 for(k = 0; k < trail_1_len; k++)
4406 joined_trail[k] = trail_1[k];
4409 /* Increment j as entry stored is same as entry stored at i*/
4412 /* Copy all the elements from j+1 to trail_2_len-1 to joined trail.*/
4413 while(k < *joined_trail_len)
4415 joined_trail[k] = trail_2[j];
4419 return joined_trail;
4423 /* Here you should join the trails. */
4424 *joined_trail_len = trail_1_len + trail_2_len + 1;
4425 joined_trail = GNUNET_malloc (*joined_trail_len *
4426 sizeof(struct GNUNET_PeerIdentity));
4428 while( i < trail_1_len)
4430 joined_trail[i] = trail_1[i];
4433 joined_trail[i] = my_identity;
4436 for (j = 0; i < *joined_trail_len; i++,j++)
4438 joined_trail[i] = trail_2[j];
4440 return joined_trail;
4445 * Return the trail from source to my current predecessor. Check if source
4446 * is already part of the this trail, if yes then return the shorten trail.
4447 * @param current_trail Trail from source to me, NOT including the endpoints.
4448 * @param current_trail_length Number of peers in @a current_trail.
4449 * @param trail_src_to_curr_pred_length[out] Number of peers in trail from
4450 * source to my predecessor, NOT including
4452 * @return Trail from source to my predecessor.
4454 static struct GNUNET_PeerIdentity *
4455 get_trail_src_to_curr_pred (struct GNUNET_PeerIdentity source_peer,
4456 const struct GNUNET_PeerIdentity *trail_src_to_me,
4457 unsigned int trail_src_to_me_len,
4458 unsigned int *trail_src_to_curr_pred_length)
4460 struct GNUNET_PeerIdentity *trail_me_to_curr_pred;
4461 struct GNUNET_PeerIdentity *trail_src_to_curr_pred;
4462 unsigned int trail_me_to_curr_pred_length;
4463 struct FingerInfo *current_predecessor;
4467 current_predecessor = &finger_table[PREDECESSOR_FINGER_ID];
4468 trail_me_to_curr_pred = get_shortest_trail (current_predecessor,
4469 &trail_me_to_curr_pred_length);
4471 if ((trail_me_to_curr_pred_length == 1) &&
4472 (0 == GNUNET_CRYPTO_cmp_peer_identity (&source_peer,
4473 &trail_me_to_curr_pred[0])))
4475 *trail_src_to_curr_pred_length = 0;
4479 /* Check if trail_me_to_curr_pred contains source. */
4480 if (trail_me_to_curr_pred_length > 1)
4482 for(i = trail_me_to_curr_pred_length - 1; i > 0; i--)
4484 if(0 != GNUNET_CRYPTO_cmp_peer_identity (&source_peer,
4485 &trail_me_to_curr_pred[i]))
4490 /* Source is the last element in the trail to reach to my pred.
4491 Source is direct friend of the pred. */
4492 if (trail_me_to_curr_pred_length == i)
4494 *trail_src_to_curr_pred_length = 0;
4499 *trail_src_to_curr_pred_length = trail_me_to_curr_pred_length - i;
4500 trail_src_to_curr_pred = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)*
4501 *trail_src_to_curr_pred_length);
4502 for(j = 0; j < *trail_src_to_curr_pred_length; i++,j++)
4504 trail_src_to_curr_pred[j] = trail_me_to_curr_pred[i];
4506 return trail_src_to_curr_pred;
4511 trail_src_to_curr_pred = check_for_duplicate_entries (trail_src_to_me,
4512 trail_src_to_me_len,
4513 trail_me_to_curr_pred,
4514 trail_me_to_curr_pred_length,
4516 *trail_src_to_curr_pred_length = len;
4517 return trail_src_to_curr_pred;
4522 * Add finger as your predecessor. To add, first generate a new trail id, invert
4523 * the trail to get the trail from me to finger, add an entry in your routing
4524 * table, send add trail message to peers which are part of trail from me to
4525 * finger and add finger in finger table.
4528 * @param trail_length
4531 update_predecessor (struct GNUNET_PeerIdentity finger,
4532 struct GNUNET_PeerIdentity *trail,
4533 unsigned int trail_length)
4535 struct GNUNET_HashCode trail_to_new_predecessor_id;
4536 struct GNUNET_PeerIdentity *trail_to_new_predecessor;
4537 struct FriendInfo *target_friend;
4539 /* Generate trail id for trail from me to new predecessor = finger. */
4540 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
4541 &trail_to_new_predecessor_id,
4542 sizeof (trail_to_new_predecessor_id));
4544 /* Finger is a friend. */
4545 if (trail_length == 0)
4547 trail_to_new_predecessor = NULL;
4548 GDS_ROUTING_add (trail_to_new_predecessor_id, my_identity, finger);
4549 GNUNET_assert (NULL != (target_friend =
4550 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4555 /* Invert the trail to get the trail from me to finger, NOT including the
4557 trail_to_new_predecessor = invert_trail (trail, trail_length);
4559 /* Add an entry in your routing table. */
4560 GDS_ROUTING_add (trail_to_new_predecessor_id,
4562 trail_to_new_predecessor[0]);
4564 GNUNET_assert (NULL != (target_friend =
4565 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4566 &trail_to_new_predecessor[0])));
4567 GNUNET_assert (NULL != (
4568 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4569 &trail[trail_length - 1])));
4572 /* Add entry in routing table of all peers that are part of trail from me
4573 to finger, including finger. */
4574 GDS_NEIGHBOURS_send_add_trail (my_identity,
4576 trail_to_new_predecessor_id,
4577 trail_to_new_predecessor,
4581 add_new_finger (finger, trail_to_new_predecessor, trail_length,
4582 trail_to_new_predecessor_id, PREDECESSOR_FINGER_ID);
4583 GNUNET_free_non_null (trail_to_new_predecessor);
4588 * Check if you already have a predecessor. If not then add finger as your
4589 * predecessor. If you have predecessor, then compare two peer identites.
4590 * If finger is correct predecessor, then remove the old entry, add finger in
4591 * finger table and send add_trail message to add the trail in the routing
4592 * table of all peers which are part of trail to reach from me to finger.
4593 * @param finger New peer which may be our predecessor.
4594 * @param trail List of peers to reach from @finger to me.
4595 * @param trail_length Total number of peer in @a trail.
4598 compare_and_update_predecessor (struct GNUNET_PeerIdentity finger,
4599 struct GNUNET_PeerIdentity *trail,
4600 unsigned int trail_length)
4602 struct FingerInfo *current_predecessor;
4603 const struct GNUNET_PeerIdentity *closest_peer;
4604 uint64_t predecessor_value;
4605 unsigned int is_predecessor = 1;
4607 current_predecessor = &finger_table[PREDECESSOR_FINGER_ID];
4609 GNUNET_assert (0 != GNUNET_CRYPTO_cmp_peer_identity (&finger, &my_identity));
4611 /* No predecessor. Add finger as your predecessor. */
4612 if (GNUNET_NO == current_predecessor->is_present)
4614 update_predecessor (finger, trail, trail_length);
4617 /* FIXME: Here we should first call find_successor and get a locally known
4618 predecessor. If locally known predecessor is closest then current or finger,
4619 add that as predecessor. */
4620 if (0 == GNUNET_CRYPTO_cmp_peer_identity (¤t_predecessor->finger_identity,
4626 predecessor_value = compute_finger_identity_value (PREDECESSOR_FINGER_ID);
4627 closest_peer = select_closest_peer (&finger,
4628 ¤t_predecessor->finger_identity,
4629 predecessor_value, is_predecessor);
4631 /* Finger is the closest predecessor. Remove the existing one and add the new
4633 if (closest_peer == &finger)
4635 remove_existing_finger (current_predecessor, PREDECESSOR_FINGER_ID);
4636 update_predecessor (finger, trail, trail_length);
4644 * Core handle for p2p verify successor messages.
4645 * @param cls closure
4646 * @param message message
4647 * @param peer peer identity this notification is about
4648 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4651 handle_dht_p2p_verify_successor(void *cls,
4652 const struct GNUNET_PeerIdentity *peer,
4653 const struct GNUNET_MessageHeader *message)
4655 const struct PeerVerifySuccessorMessage *vsm;
4656 struct GNUNET_HashCode trail_id;
4657 struct GNUNET_PeerIdentity successor;
4658 struct GNUNET_PeerIdentity source_peer;
4659 struct GNUNET_PeerIdentity *trail;
4660 struct GNUNET_PeerIdentity *next_hop;
4661 struct FingerInfo *current_predecessor;
4662 struct FriendInfo *target_friend;
4663 unsigned int trail_src_to_curr_pred_len = 0;
4664 struct GNUNET_PeerIdentity *trail_src_to_curr_pred;
4666 unsigned int trail_length;
4668 msize = ntohs (message->size);
4670 if (msize < sizeof (struct PeerVerifySuccessorMessage))
4672 GNUNET_break_op (0);
4676 vsm = (const struct PeerVerifySuccessorMessage *) message;
4677 trail_length = (msize - sizeof (struct PeerVerifySuccessorMessage))/
4678 sizeof (struct GNUNET_PeerIdentity);
4679 if ((msize - sizeof (struct PeerVerifySuccessorMessage)) %
4680 sizeof (struct GNUNET_PeerIdentity) != 0)
4682 GNUNET_break_op (0);
4686 trail_id = vsm->trail_id;
4687 source_peer = vsm->source_peer;
4688 successor = vsm->successor;
4689 trail = (struct GNUNET_PeerIdentity *)&vsm[1];
4692 /* I am NOT the successor of source_peer. Pass the message to next_hop on
4694 if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&successor, &my_identity)))
4696 next_hop = GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST);
4698 if (NULL == next_hop)
4700 GNUNET_break_op (0);
4701 return GNUNET_SYSERR;
4704 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
4706 if(NULL == target_friend)
4711 GDS_NEIGHBOURS_send_verify_successor_message (source_peer, successor,
4712 trail_id, trail, trail_length,
4717 /* I am the destination of this message. */
4719 /* Check if the source_peer could be our predecessor and if yes then update
4721 compare_and_update_predecessor (source_peer, trail, trail_length);
4722 current_predecessor = &finger_table[PREDECESSOR_FINGER_ID];
4724 /* Is source of this message NOT my predecessor. */
4725 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_predecessor->finger_identity,
4728 trail_src_to_curr_pred = get_trail_src_to_curr_pred (source_peer,
4731 &trail_src_to_curr_pred_len);
4735 trail_src_to_curr_pred_len = trail_length;
4738 trail_src_to_curr_pred = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity)*trail_length);
4739 for(i = 0; i < trail_src_to_curr_pred_len; i++)
4741 trail_src_to_curr_pred[i] = trail[i];
4746 GNUNET_assert (NULL !=
4748 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer)));
4749 GDS_NEIGHBOURS_send_verify_successor_result (source_peer, my_identity,
4750 current_predecessor->finger_identity,
4751 trail_id, trail_src_to_curr_pred,
4752 trail_src_to_curr_pred_len,
4753 GDS_ROUTING_DEST_TO_SRC,
4761 * If the trail from me to my probable successor contains a friend not
4762 * at index 0, then we can shorten the trail.
4763 * @param probable_successor Peer which is our probable successor
4764 * @param trail_me_to_probable_successor Peers in path from me to my probable
4765 * successor, NOT including the endpoints.
4766 * @param trail_me_to_probable_successor_len Total number of peers in
4767 * @a trail_me_to_probable_succesor.
4768 * @return Updated trail, if any friend found.
4769 * Else the trail_me_to_probable_successor.
4771 struct GNUNET_PeerIdentity *
4772 check_trail_me_to_probable_succ (struct GNUNET_PeerIdentity probable_successor,
4773 const struct GNUNET_PeerIdentity *trail_me_to_probable_successor,
4774 unsigned int trail_me_to_probable_successor_len,
4775 unsigned int *trail_to_new_successor_length)
4779 struct GNUNET_PeerIdentity *trail_to_new_successor;
4781 /* Probable successor is a friend */
4782 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4783 &probable_successor))
4785 trail_to_new_successor = NULL;
4786 *trail_to_new_successor_length = 0;
4787 return trail_to_new_successor;
4790 /* Is there any friend of yours in this trail. */
4791 if(trail_me_to_probable_successor_len > 1)
4793 for (i = trail_me_to_probable_successor_len - 1; i > 0; i--)
4795 if (NULL == GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4796 &trail_me_to_probable_successor[i]))
4800 *trail_to_new_successor_length = (trail_me_to_probable_successor_len - i);
4801 trail_to_new_successor = GNUNET_malloc (sizeof(struct GNUNET_PeerIdentity)*
4802 *trail_to_new_successor_length);
4804 for(j = 0;i < trail_me_to_probable_successor_len;i++,j++)
4806 trail_to_new_successor[j] = trail_me_to_probable_successor[i];
4808 return trail_to_new_successor;
4812 *trail_to_new_successor_length = trail_me_to_probable_successor_len;
4813 trail_to_new_successor = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)*
4814 *trail_to_new_successor_length);
4816 for(i = 0; i < *trail_to_new_successor_length; i++)
4817 trail_to_new_successor[i] = trail_me_to_probable_successor[i];
4819 return trail_to_new_successor;
4824 * Check if the peer which sent us verify successor result message is still ours
4825 * successor or not. If not, then compare existing successor and probable successor.
4826 * In case probable successor is the correct successor, remove the existing
4827 * successor. Add probable successor as new successor. Send notify new successor
4828 * message to new successor.
4830 * @param probable_successor
4832 * @param trail_length
4835 compare_and_update_successor (struct GNUNET_PeerIdentity curr_succ,
4836 struct GNUNET_PeerIdentity probable_successor,
4837 const struct GNUNET_PeerIdentity *trail,
4838 unsigned int trail_length)
4840 struct FingerInfo *current_successor;
4841 const struct GNUNET_PeerIdentity *closest_peer;
4842 struct GNUNET_HashCode trail_id;
4843 struct GNUNET_PeerIdentity *trail_me_to_probable_succ;
4844 struct FriendInfo *target_friend;
4845 unsigned int trail_me_to_probable_succ_len;
4846 unsigned int is_predecessor = GNUNET_NO;
4847 uint64_t successor_value;
4849 current_successor = &finger_table[0];
4850 successor_value = compute_finger_identity_value(0);
4852 /* Have we found some other successor, while waiting for verify successor result
4854 * FIXME closest_peer is being overwritten just after the if
4857 if(0 != GNUNET_CRYPTO_cmp_peer_identity(&curr_succ, ¤t_successor->finger_identity))
4859 /* We could have added this new successor, only if it was closer the old one. */
4860 closest_peer = select_closest_peer (&curr_succ,
4861 ¤t_successor->finger_identity,
4862 successor_value, is_predecessor);
4864 /* FIXME: it may fail in case we have done more number of iterations of
4865 find _finger_trail_task. */
4866 /*GNUNET_assert (0 ==
4867 GNUNET_CRYPTO_cmp_peer_identity (closest_peer,
4868 ¤t_successor->finger_identity));*/
4873 closest_peer = select_closest_peer (&probable_successor,
4874 ¤t_successor->finger_identity,
4875 successor_value, is_predecessor);
4877 /* If the current_successor in the finger table is closest, then do nothing. */
4878 if (closest_peer == ¤t_successor->finger_identity)
4881 /* Probable successor is the closest peer.*/
4882 if(trail_length > 0)
4884 GNUNET_assert(NULL != GNUNET_CONTAINER_multipeermap_get(friend_peermap,
4889 GNUNET_assert(NULL != GNUNET_CONTAINER_multipeermap_get(friend_peermap,
4890 &probable_successor));
4893 trail_me_to_probable_succ_len = 0;
4894 /* TODO: Check if the path to reach to probable successor contains a friend. */
4895 trail_me_to_probable_succ =
4896 check_trail_me_to_probable_succ (probable_successor,
4897 trail, trail_length,
4898 &trail_me_to_probable_succ_len);
4900 /* Remove the existing successor. */
4901 remove_existing_finger (current_successor, 0);
4903 /* TODO URGENT: Check if any peer is present more than once, if yes then shorten
4904 the trail. before sending it across the network. */
4905 /* Generate a new trail id to reach to your new successor. */
4906 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
4907 &trail_id, sizeof (trail_id));
4909 if (trail_me_to_probable_succ_len > 0)
4911 GDS_ROUTING_add (trail_id, my_identity, trail_me_to_probable_succ[0]);
4912 GNUNET_assert (NULL !=
4914 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4915 &trail_me_to_probable_succ[0])));
4919 GDS_ROUTING_add (trail_id, my_identity, probable_successor);
4920 GNUNET_assert (NULL !=
4922 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4923 &probable_successor)));
4926 add_new_finger (probable_successor, trail_me_to_probable_succ,
4927 trail_me_to_probable_succ_len, trail_id, 0);
4929 GDS_NEIGHBOURS_send_notify_new_successor (my_identity, probable_successor,
4930 trail_me_to_probable_succ,
4931 trail_me_to_probable_succ_len,
4939 * FIXME: Check for duplicate elements everywhere when you are making
4941 * Core handle for p2p verify successor result messages.
4942 * @param cls closure
4943 * @param message message
4944 * @param peer peer identity this notification is about
4945 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4948 handle_dht_p2p_verify_successor_result(void *cls,
4949 const struct GNUNET_PeerIdentity *peer,
4950 const struct GNUNET_MessageHeader *message)
4952 const struct PeerVerifySuccessorResultMessage *vsrm;
4953 enum GDS_ROUTING_trail_direction trail_direction;
4954 struct GNUNET_PeerIdentity querying_peer;
4955 struct GNUNET_HashCode trail_id;
4956 struct GNUNET_PeerIdentity *next_hop;
4957 struct FriendInfo *target_friend;
4958 struct GNUNET_PeerIdentity probable_successor;
4959 struct GNUNET_PeerIdentity current_successor;
4960 const struct GNUNET_PeerIdentity *trail;
4961 unsigned int trail_length;
4964 msize = ntohs (message->size);
4965 /* We send a trail to reach from old successor to new successor, if
4966 * old_successor != new_successor.*/
4967 if (msize < sizeof (struct PeerVerifySuccessorResultMessage))
4969 GNUNET_break_op (0);
4973 vsrm = (const struct PeerVerifySuccessorResultMessage *) message;
4974 trail_length = (msize - sizeof (struct PeerVerifySuccessorResultMessage))/
4975 sizeof (struct GNUNET_PeerIdentity);
4977 if ((msize - sizeof (struct PeerVerifySuccessorResultMessage)) %
4978 sizeof (struct GNUNET_PeerIdentity) != 0)
4980 GNUNET_break_op (0);
4984 trail = (const struct GNUNET_PeerIdentity *) &vsrm[1];
4985 querying_peer = vsrm->querying_peer;
4986 trail_direction = ntohl (vsrm->trail_direction);
4987 trail_id = vsrm->trail_id;
4988 probable_successor = vsrm->probable_successor;
4989 current_successor = vsrm->current_successor;
4991 /* I am the querying_peer. */
4992 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&querying_peer, &my_identity)))
4994 compare_and_update_successor (current_successor,
4995 probable_successor, trail, trail_length);
4999 /*If you are not the querying peer then pass on the message */
5000 GNUNET_assert (NULL != (next_hop =
5001 GDS_ROUTING_get_next_hop (trail_id, trail_direction)));
5002 GNUNET_assert (NULL !=
5004 GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop)));
5005 GDS_NEIGHBOURS_send_verify_successor_result (querying_peer,
5006 vsrm->current_successor,
5007 probable_successor, trail_id,
5010 trail_direction, target_friend);
5016 * Core handle for p2p notify new successor messages.
5017 * @param cls closure
5018 * @param message message
5019 * @param peer peer identity this notification is about
5020 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5023 handle_dht_p2p_notify_new_successor(void *cls,
5024 const struct GNUNET_PeerIdentity *peer,
5025 const struct GNUNET_MessageHeader *message)
5027 const struct PeerNotifyNewSuccessorMessage *nsm;
5028 struct GNUNET_PeerIdentity *trail;
5029 struct GNUNET_PeerIdentity source;
5030 struct GNUNET_PeerIdentity new_successor;
5031 struct GNUNET_HashCode trail_id;
5032 struct GNUNET_PeerIdentity next_hop;
5033 struct FriendInfo *target_friend;
5036 uint32_t trail_length;
5038 msize = ntohs (message->size);
5040 /* We have the trail to reach from source to new successor. */
5041 if (msize < sizeof (struct PeerNotifyNewSuccessorMessage))
5043 GNUNET_break_op (0);
5047 nsm = (const struct PeerNotifyNewSuccessorMessage *) message;
5048 trail_length = (msize - sizeof (struct PeerNotifyNewSuccessorMessage))/
5049 sizeof (struct GNUNET_PeerIdentity);
5050 if ((msize - sizeof (struct PeerNotifyNewSuccessorMessage)) %
5051 sizeof (struct GNUNET_PeerIdentity) != 0)
5053 GNUNET_break_op (0);
5057 trail = (struct GNUNET_PeerIdentity *) &nsm[1];
5058 source = nsm->source_peer;
5059 new_successor = nsm->new_successor;
5060 trail_id = nsm->trail_id;
5062 //FIXME: add a check to make sure peer is correct.
5064 /* I am the new_successor to source_peer. */
5065 if ( 0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &new_successor))
5067 GDS_ROUTING_add (trail_id, *peer, my_identity);
5068 compare_and_update_predecessor (source, trail, trail_length);
5072 GNUNET_assert(trail_length > 0);
5073 /* I am part of trail to reach to successor. */
5074 my_index = search_my_index (trail, trail_length);
5077 GNUNET_break_op (0);
5078 return GNUNET_SYSERR;
5081 if ((trail_length-1) == my_index)
5082 next_hop = new_successor;
5084 next_hop = trail[my_index + 1];
5087 /* Add an entry in routing table for trail from source to its new successor. */
5088 GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, *peer, next_hop));
5090 GNUNET_assert (NULL !=
5092 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop)));
5093 GDS_NEIGHBOURS_send_notify_new_successor (source, new_successor, trail,
5095 trail_id, target_friend);
5102 * Core handler for P2P trail rejection message
5103 * @param cls closure
5104 * @param message message
5105 * @param peer peer identity this notification is about
5106 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5109 handle_dht_p2p_trail_setup_rejection (void *cls,
5110 const struct GNUNET_PeerIdentity *peer,
5111 const struct GNUNET_MessageHeader *message)
5113 const struct PeerTrailRejectionMessage *trail_rejection;
5114 unsigned int trail_length;
5115 const struct GNUNET_PeerIdentity *trail_peer_list;
5116 struct FriendInfo *target_friend;
5117 struct GNUNET_TIME_Relative congestion_timeout;
5118 struct GNUNET_HashCode trail_id;
5119 struct GNUNET_PeerIdentity next_peer;
5120 struct GNUNET_PeerIdentity source;
5121 struct GNUNET_PeerIdentity *next_hop;
5122 uint64_t ultimate_destination_finger_value;
5123 unsigned int is_predecessor;
5126 msize = ntohs (message->size);
5127 /* We are passing the trail setup so far. */
5128 if (msize < sizeof (struct PeerTrailRejectionMessage))
5130 GNUNET_break_op (0);
5134 trail_rejection = (const struct PeerTrailRejectionMessage *) message;
5135 trail_length = (msize - sizeof (struct PeerTrailRejectionMessage))/
5136 sizeof (struct GNUNET_PeerIdentity);
5137 if ((msize - sizeof (struct PeerTrailRejectionMessage)) %
5138 sizeof (struct GNUNET_PeerIdentity) != 0)
5140 GNUNET_break_op (0);
5144 trail_peer_list = (const struct GNUNET_PeerIdentity *)&trail_rejection[1];
5145 is_predecessor = ntohl (trail_rejection->is_predecessor);
5146 congestion_timeout = trail_rejection->congestion_time;
5147 source = trail_rejection->source_peer;
5148 trail_id = trail_rejection->trail_id;
5149 ultimate_destination_finger_value =
5150 GNUNET_ntohll (trail_rejection->ultimate_destination_finger_value);
5152 /* First set the congestion time of the friend that sent you this message. */
5153 GNUNET_assert (NULL !=
5155 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer)));
5156 target_friend->congestion_timestamp =
5157 GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(),
5158 congestion_timeout);
5160 /* I am the source peer which wants to setup the trail. Do nothing.
5161 * send_find_finger_trail_task is scheduled periodically.*/
5162 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &source)))
5165 /* If I am congested then pass this message to peer before me in trail. */
5166 if(GNUNET_YES == GDS_ROUTING_threshold_reached())
5168 struct GNUNET_PeerIdentity *new_trail;
5169 unsigned int new_trail_length;
5171 /* Remove yourself from the trail setup so far. */
5172 if (trail_length == 1)
5175 new_trail_length = 0;
5180 memcpy (&next_hop , &trail_peer_list[trail_length - 2],
5181 sizeof (struct GNUNET_PeerIdentity));
5183 /* Remove myself from the trail. */
5184 new_trail_length = trail_length -1;
5185 new_trail = GNUNET_malloc (new_trail_length * sizeof (struct GNUNET_PeerIdentity));
5186 memcpy (new_trail, trail_peer_list, new_trail_length * sizeof (struct GNUNET_PeerIdentity));
5189 GNUNET_assert (NULL !=
5191 GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop)));
5192 GDS_NEIGHBOURS_send_trail_rejection (source,
5193 ultimate_destination_finger_value,
5194 my_identity, is_predecessor,
5195 new_trail,new_trail_length,trail_id,
5196 target_friend, CONGESTION_TIMEOUT);
5197 GNUNET_free (new_trail);
5201 struct Closest_Peer successor;
5202 successor = find_successor (ultimate_destination_finger_value, is_predecessor);
5204 /* Am I the final destination? */
5205 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&successor.best_known_destination,
5208 if (0 == trail_length)
5211 next_peer = trail_peer_list[trail_length-1];
5213 GNUNET_assert (NULL !=
5215 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer)));
5217 GDS_NEIGHBOURS_send_trail_setup_result (source,
5219 target_friend, trail_length,
5222 ultimate_destination_finger_value,
5227 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
5229 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
5230 peer_list[trail_length] = my_identity;
5232 GNUNET_assert (NULL !=
5234 GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop)));
5236 GDS_NEIGHBOURS_send_trail_setup (source,
5237 ultimate_destination_finger_value,
5238 successor.best_known_destination,
5239 target_friend, trail_length + 1, peer_list,
5240 is_predecessor, trail_id,
5241 successor.trail_id);
5248 * Core handle for p2p trail tear compression messages.
5249 * @param cls closure
5250 * @param message message
5251 * @param peer peer identity this notification is about
5252 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5255 handle_dht_p2p_trail_compression (void *cls, const struct GNUNET_PeerIdentity *peer,
5256 const struct GNUNET_MessageHeader *message)
5258 const struct PeerTrailCompressionMessage *trail_compression;
5259 struct GNUNET_PeerIdentity *next_hop;
5260 struct FriendInfo *target_friend;
5261 struct GNUNET_HashCode trail_id;
5264 msize = ntohs (message->size);
5266 if (msize != sizeof (struct PeerTrailCompressionMessage))
5268 GNUNET_break_op (0);
5272 trail_compression = (const struct PeerTrailCompressionMessage *) message;
5273 trail_id = trail_compression->trail_id;
5275 /* Am I the new first friend to reach to finger of this trail. */
5276 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&trail_compression->new_first_friend,
5279 GNUNET_assert (NULL !=
5280 (GNUNET_CONTAINER_multipeermap_get (friend_peermap,
5281 &trail_compression->source_peer)));
5283 /* Update your prev hop to source of this message. */
5284 GNUNET_assert (GNUNET_SYSERR !=
5285 (GDS_ROUTING_update_trail_prev_hop (trail_id,
5286 trail_compression->source_peer)));
5290 /* Pass the message to next hop to finally reach to new_first_friend. */
5291 next_hop = GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST);
5293 if (NULL == next_hop)
5299 GNUNET_assert (NULL !=
5301 GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop)));
5303 GDS_ROUTING_remove_trail (trail_id);
5305 GDS_NEIGHBOURS_send_trail_compression (trail_compression->source_peer,
5307 trail_compression->new_first_friend,
5314 * Core handler for trail teardown message.
5315 * @param cls closure
5316 * @param message message
5317 * @param peer sender of this messsage.
5318 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5321 handle_dht_p2p_trail_teardown (void *cls, const struct GNUNET_PeerIdentity *peer,
5322 const struct GNUNET_MessageHeader *message)
5324 const struct PeerTrailTearDownMessage *trail_teardown;
5325 enum GDS_ROUTING_trail_direction trail_direction;
5326 struct GNUNET_HashCode trail_id;
5327 struct GNUNET_PeerIdentity *next_hop;
5330 msize = ntohs (message->size);
5332 /* Here we pass only the trail id. */
5333 if (msize != sizeof (struct PeerTrailTearDownMessage))
5335 GNUNET_break_op (0);
5339 trail_teardown = (const struct PeerTrailTearDownMessage *) message;
5340 trail_direction = ntohl (trail_teardown->trail_direction);
5341 trail_id = trail_teardown->trail_id;
5343 /* Check if peer is the real peer from which we should get this message.*/
5344 /* Get the prev_hop for this trail by getting the next hop in opposite direction. */
5346 GNUNET_assert (NULL != (prev_hop =
5347 GDS_ROUTING_get_next_hop (trail_id, !trail_direction)));
5348 if (0 != GNUNET_CRYPTO_cmp_peer_identity (prev_hop, peer))
5351 return GNUNET_SYSERR;
5355 next_hop = GDS_ROUTING_get_next_hop (trail_id, trail_direction);
5357 if (NULL == next_hop)
5360 return GNUNET_SYSERR;
5363 /* I am the next hop, which means I am the final destination. */
5364 if (0 == GNUNET_CRYPTO_cmp_peer_identity (next_hop, &my_identity))
5366 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id));
5371 /* If not final destination, then send a trail teardown message to next hop.*/
5372 GNUNET_assert (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop));
5373 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id));
5374 GDS_NEIGHBOURS_send_trail_teardown (trail_id, trail_direction, *next_hop);
5382 * Core handle for p2p add trail message.
5383 * @param cls closure
5384 * @param message message
5385 * @param peer peer identity this notification is about
5386 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5389 handle_dht_p2p_add_trail (void *cls, const struct GNUNET_PeerIdentity *peer,
5390 const struct GNUNET_MessageHeader *message)
5392 const struct PeerAddTrailMessage *add_trail;
5393 const struct GNUNET_PeerIdentity *trail;
5394 struct GNUNET_HashCode trail_id;
5395 struct GNUNET_PeerIdentity destination_peer;
5396 struct GNUNET_PeerIdentity source_peer;
5397 struct GNUNET_PeerIdentity next_hop;
5398 unsigned int trail_length;
5399 unsigned int my_index;
5402 msize = ntohs (message->size);
5403 /* In this message we pass the whole trail from source to destination as we
5404 * are adding that trail.*/
5405 //FIXME: failed when run with 1000 pears. check why.
5406 if (msize < sizeof (struct PeerAddTrailMessage))
5408 GNUNET_break_op (0);
5412 add_trail = (const struct PeerAddTrailMessage *) message;
5413 trail_length = (msize - sizeof (struct PeerAddTrailMessage))/
5414 sizeof (struct GNUNET_PeerIdentity);
5415 if ((msize - sizeof (struct PeerAddTrailMessage)) %
5416 sizeof (struct GNUNET_PeerIdentity) != 0)
5418 GNUNET_break_op (0);
5422 trail = (const struct GNUNET_PeerIdentity *)&add_trail[1];
5423 destination_peer = add_trail->destination_peer;
5424 source_peer = add_trail->source_peer;
5425 trail_id = add_trail->trail_id;
5427 //FIXME: add a check that sender peer is not malicious. Make it a generic
5428 // function so that it can be used in all other functions where we need the
5429 // same functionality.
5431 /* I am not the destination of the trail. */
5432 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &destination_peer))
5434 struct FriendInfo *target_friend;
5436 /* Get my location in the trail. */
5437 my_index = search_my_index (trail, trail_length);
5440 GNUNET_break_op (0);
5441 return GNUNET_SYSERR;
5444 if ((trail_length - 1) == my_index)
5446 next_hop = destination_peer;
5450 next_hop = trail[my_index + 1];
5453 /* Add in your routing table. */
5454 GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, next_hop, *peer));
5455 GNUNET_assert (NULL !=
5457 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop)));
5458 GDS_NEIGHBOURS_send_add_trail (source_peer, destination_peer, trail_id,
5459 trail, trail_length, target_friend);
5462 /* I am the destination. Add an entry in routing table. */
5463 GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, *peer, my_identity));
5469 * Free the finger trail in which the first friend to reach to a finger is
5470 * disconnected_friend. Also remove entry from routing table for that particular
5472 * @param disconnected_friend PeerIdentity of friend which got disconnected
5473 * @param remove_finger Finger whose trail we need to check if it has
5474 * disconnected_friend as the first hop.
5475 * @return Total number of trails in which disconnected_friend was the first
5479 remove_matching_trails (const struct GNUNET_PeerIdentity *disconnected_friend,
5480 struct FingerInfo *remove_finger)
5482 unsigned int matching_trails_count;
5485 /* Number of trails with disconnected_friend as the first hop in the trail
5486 * to reach from me to remove_finger, NOT including endpoints. */
5487 matching_trails_count = 0;
5489 /* Iterate over all the trails of finger. */
5490 for (i = 0; i < remove_finger->trails_count; i++)
5492 struct Trail *trail;
5493 trail = &remove_finger->trail_list[i];
5495 /* This assertion is ensure that there are no gaps in the trail list.
5496 REMOVE IT AFTERWARDS. */
5497 GNUNET_assert (GNUNET_YES == trail->is_present);
5499 /* First friend to reach to finger is disconnected_peer. */
5500 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&trail->trail_head->peer,
5501 disconnected_friend))
5503 struct GNUNET_PeerIdentity *next_hop;
5504 struct FriendInfo *remove_friend;
5506 GNUNET_assert (NULL !=
5508 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
5509 disconnected_friend)));
5510 /* FIXME: removing no but check it. */
5511 //remove_friend->trails_count--;
5512 next_hop = GDS_ROUTING_get_next_hop (trail->trail_id,
5513 GDS_ROUTING_SRC_TO_DEST);
5515 /* Here it may happen that as all the peers got disconnected, the entry in
5516 routing table for that particular trail has been removed, because the
5517 previously disconnected peer was either a next hop or prev hop of that
5519 if (NULL == next_hop)
5522 GNUNET_assert (0 == (GNUNET_CRYPTO_cmp_peer_identity (disconnected_friend,
5524 matching_trails_count++;
5525 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail->trail_id));
5528 trail->is_present = GNUNET_NO;
5531 return matching_trails_count;
5536 * Iterate over finger_table entries.
5537 * 0. Ignore finger which is my_identity or if no valid entry present at
5538 * that finger index.
5539 * 1. If disconnected_friend is a finger, then remove the routing entry from
5540 your own table. Free the trail.
5541 * 2. Check if disconnected_friend is the first friend in the trail to reach to a finger.
5542 * 2.1 Remove all the trails and entry from routing table in which disconnected
5543 * friend is the first friend in the trail. If disconnected_friend is the
5544 * first friend in all the trails to reach finger, then remove the finger.
5545 * @param disconnected_friend Peer identity of friend which got disconnected.
5548 remove_matching_fingers (const struct GNUNET_PeerIdentity *disconnected_peer)
5550 struct FingerInfo *remove_finger;
5551 struct FriendInfo *remove_friend;
5552 int removed_trails_count;
5555 /* Iterate over finger table entries. */
5556 for (i = 0; i < MAX_FINGERS; i++)
5558 remove_finger = &finger_table[i];
5560 /* No finger stored at this trail index. */
5561 if (GNUNET_NO == remove_finger->is_present)
5564 /* I am my own finger, then ignore this finger. */
5565 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&remove_finger->finger_identity,
5569 /* Is disconnected_peer a finger? */
5570 if (0 == GNUNET_CRYPTO_cmp_peer_identity (disconnected_peer,
5571 &remove_finger->finger_identity))
5573 struct GNUNET_PeerIdentity *next_hop;
5574 struct GNUNET_HashCode trail_id;
5577 GNUNET_assert (GNUNET_YES == (remove_finger->trail_list[0].is_present));
5578 trail_id = remove_finger->trail_list[0].trail_id;
5582 GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST)))
5585 (GNUNET_CRYPTO_cmp_peer_identity (next_hop,
5586 &remove_finger->finger_identity)));
5587 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id));
5588 GNUNET_assert (NULL !=
5590 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
5591 disconnected_peer)));
5594 remove_finger->trail_list[0].is_present = GNUNET_NO;
5595 //GNUNET_assert (0 != remove_friend->trails_count);
5596 //remove_friend->trails_count--; //FIXME; CHECK WHY IT FAILS AND THEN UNCOMMENT.
5597 remove_finger->is_present = GNUNET_NO;
5598 memset ((void *)&finger_table[i], 0, sizeof (finger_table[i]));
5602 /* If finger is a friend but not disconnected_friend, then continue. */
5603 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap,
5604 &remove_finger->finger_identity))
5607 /* Iterate over the list of trails to reach remove_finger. Check if
5608 * disconnected_friend is the first friend in any of the trail. */
5609 removed_trails_count = remove_matching_trails (disconnected_peer,
5611 remove_finger->trails_count =
5612 remove_finger->trails_count - removed_trails_count;
5613 /* All the finger trails had disconnected_friend as the first friend,
5614 * so free the finger. */
5615 if (remove_finger->trails_count == 0)
5617 remove_finger->is_present = GNUNET_NO;
5618 memset ((void *)&finger_table[i], 0, sizeof (finger_table[i]));
5625 * Method called whenever a peer disconnects.
5627 * @param cls closure
5628 * @param peer peer identity this notification is about
5631 handle_core_disconnect (void *cls,
5632 const struct GNUNET_PeerIdentity *peer)
5634 struct FriendInfo *remove_friend;
5636 /* If disconnected to own identity, then return. */
5637 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
5640 GNUNET_assert (NULL != (remove_friend =
5641 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer)));
5643 /* Remove fingers with peer as first friend or if peer is a finger. */
5644 remove_matching_fingers (peer);
5646 /* Remove any trail from routing table of which peer is a part of. This function
5647 * internally sends a trail teardown message in the direction of which
5648 * disconnected peer is not part of. */
5649 GNUNET_assert (GNUNET_SYSERR != GDS_ROUTING_remove_trail_by_peer (peer));
5651 //GNUNET_assert (0 == remove_friend->trails_count); //FIXME; why should this fai.
5653 /* Remove peer from friend_peermap. */
5654 GNUNET_assert (GNUNET_YES ==
5655 GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
5659 if (0 != GNUNET_CONTAINER_multipeermap_size (friend_peermap))
5662 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
5664 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
5665 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
5674 * Method called whenever a peer connects.
5676 * @param cls closure
5677 * @param peer_identity peer identity this notification is about
5680 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity)
5682 struct FriendInfo *friend;
5684 /* Check for connect to self message */
5685 if (0 == memcmp (&my_identity, peer_identity, sizeof (struct GNUNET_PeerIdentity)))
5688 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to %s\n", GNUNET_i2s (peer_identity));
5690 /* If peer already exists in our friend_peermap, then exit. */
5691 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (friend_peermap,
5698 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
5701 friend = GNUNET_new (struct FriendInfo);
5702 friend->id = *peer_identity;
5704 GNUNET_assert (GNUNET_OK ==
5705 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
5706 peer_identity, friend,
5707 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
5710 /* got a first connection, good time to start with FIND FINGER TRAIL requests...*/
5711 if (GNUNET_SCHEDULER_NO_TASK == find_finger_trail_task)
5713 next_send_time.rel_value_us =
5714 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
5715 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
5716 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us);
5717 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
5723 * To be called on core init/fail.
5725 * @param cls service closure
5726 * @param identity the public identity of this peer
5729 core_init (void *cls,
5730 const struct GNUNET_PeerIdentity *identity)
5732 my_identity = *identity;
5735 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
5736 my_id64 = GNUNET_ntohll (my_id64);
5737 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5738 "my_indentity = %s, my_id64=%llu\n",GNUNET_i2s(&my_identity),(unsigned long long)my_id64);
5744 * Initialize finger table entries.
5747 finger_table_init ()
5749 memset (&finger_table, 0, sizeof (finger_table));
5754 * Initialize neighbours subsystem.
5755 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5758 GDS_NEIGHBOURS_init (void)
5760 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
5761 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_XDHT_P2P_PUT, 0},
5762 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_XDHT_P2P_GET, 0},
5763 {&handle_dht_p2p_get_result, GNUNET_MESSAGE_TYPE_XDHT_P2P_GET_RESULT, 0},
5764 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP, 0},
5765 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_RESULT, 0},
5766 {&handle_dht_p2p_verify_successor, GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR, 0},
5767 {&handle_dht_p2p_verify_successor_result, GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR_RESULT, 0},
5768 {&handle_dht_p2p_notify_new_successor, GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_NEW_SUCCESSOR, 0},
5769 {&handle_dht_p2p_trail_setup_rejection, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_REJECTION, 0},
5770 {&handle_dht_p2p_trail_compression, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_COMPRESSION,
5771 sizeof (struct PeerTrailCompressionMessage)},
5772 {&handle_dht_p2p_trail_teardown, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN,
5773 sizeof (struct PeerTrailTearDownMessage)},
5774 {&handle_dht_p2p_add_trail, GNUNET_MESSAGE_TYPE_XDHT_P2P_ADD_TRAIL, 0},
5779 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
5780 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
5781 GNUNET_NO, core_handlers);
5782 if (NULL == core_api)
5783 return GNUNET_SYSERR;
5785 friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
5786 finger_table_init ();
5793 * Shutdown neighbours subsystem.
5796 GDS_NEIGHBOURS_done (void)
5798 if (NULL == core_api)
5801 GNUNET_CORE_disconnect (core_api);
5804 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
5805 GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
5806 friend_peermap = NULL;
5808 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
5811 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
5812 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
5815 if (GNUNET_SCHEDULER_NO_TASK != send_verify_successor_task)
5817 GNUNET_SCHEDULER_cancel (send_verify_successor_task);
5818 send_verify_successor_task = GNUNET_SCHEDULER_NO_TASK;
5826 * @return my identity
5828 struct GNUNET_PeerIdentity
5829 GDS_NEIGHBOURS_get_my_id (void)
5834 /* end of gnunet-service-xdht_neighbours.c */