2 This file is part of GNUnet.
3 (C) 2009-2014 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file dht/gnunet-service-xdht_neighbours.c
23 * @brief GNUnet DHT service's finger and friend table management code
24 * @author Supriti Singh
28 #include "gnunet_util_lib.h"
29 #include "gnunet_block_lib.h"
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_protocols.h"
33 #include "gnunet_ats_service.h"
34 #include "gnunet_core_service.h"
35 #include "gnunet_datacache_lib.h"
36 #include "gnunet_transport_service.h"
37 #include "gnunet_dht_service.h"
38 #include "gnunet_statistics_service.h"
39 #include "gnunet-service-xdht.h"
40 #include "gnunet-service-xdht_clients.h"
41 #include "gnunet-service-xdht_datacache.h"
42 #include "gnunet-service-xdht_neighbours.h"
43 #include "gnunet-service-xdht_routing.h"
48 * Maximum possible fingers (including predecessor) of a peer
50 #define MAX_FINGERS 65
53 * Maximum allowed number of pending messages per friend peer.
55 #define MAXIMUM_PENDING_PER_FRIEND 64
58 * How long to wait before sending another find finger trail request
60 #define DHT_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
63 * How long at most to wait for transmission of a request to another peer?
65 #define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
68 * Duration for which I may remain congested.
69 * Note: Its a static value. In future, a peer may do some analysis and calculate
70 * congestion_timeout based on 'some' parameters.
72 #define CONGESTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
75 * Maximum number of trails allowed to go through a friend.
77 #define TRAILS_THROUGH_FRIEND_THRESHOLD 64
80 * Maximum number of trails stored per finger.
82 #define MAXIMUM_TRAILS_PER_FINGER 2
85 * Finger map index for predecessor entry in finger peermap.
87 #define PREDECESSOR_FINGER_ID 64
90 * Wrap around in peer identity circle.
91 * FIXME: not used anywhere, should be used in
92 * find_successor() while comparing two peers.
94 #define PEER_IDENTITES_WRAP_AROUND pow(2, 64) - 1
97 * To check if a finger is predecessor or not.
99 enum GDS_NEIGHBOURS_finger_type
101 GDS_FINGER_TYPE_PREDECESSOR = 0,
102 GDS_FINGER_TYPE_NON_PREDECESSOR = 1
105 GNUNET_NETWORK_STRUCT_BEGIN
110 struct PeerPutMessage
113 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
115 struct GNUNET_MessageHeader header;
120 uint32_t options GNUNET_PACKED;
125 uint32_t block_type GNUNET_PACKED;
130 uint32_t hop_count GNUNET_PACKED;
133 * Replication level for this message
134 * In the current implementation, this value is not used.
136 uint32_t desired_replication_level GNUNET_PACKED;
139 * Length of the PUT path that follows (if tracked).
141 uint32_t put_path_length GNUNET_PACKED;
144 * Best known destination (could be my friend or finger) which should
145 * get this message next.
147 struct GNUNET_PeerIdentity best_known_destination;
150 * In case best_known_destination is a finger, then trail to reach
151 * to that finger. Else its default value is 0.
153 struct GNUNET_HashCode intermediate_trail_id;
156 * When does the content expire?
158 struct GNUNET_TIME_AbsoluteNBO expiration_time;
161 * The key to store the value under.
163 struct GNUNET_HashCode key GNUNET_PACKED;
165 /* put path (if tracked) */
174 struct PeerGetMessage
177 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET
179 struct GNUNET_MessageHeader header;
184 uint32_t options GNUNET_PACKED;
187 * Desired content type.
189 uint32_t block_type GNUNET_PACKED;
194 uint32_t hop_count GNUNET_PACKED;
197 * Desired replication level for this request.
198 * In the current implementation, this value is not used.
200 uint32_t desired_replication_level GNUNET_PACKED;
203 * Total number of peers in get path.
205 unsigned int get_path_length;
208 * Best known destination (could be my friend or finger) which should
209 * get this message next.
211 struct GNUNET_PeerIdentity best_known_destination;
214 * In case best_known_destination is a finger, then trail to reach
215 * to that finger. Else its default value is 0.
217 struct GNUNET_HashCode intermediate_trail_id;
220 * The key we are looking for.
222 struct GNUNET_HashCode key;
231 struct PeerGetResultMessage
234 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT
236 struct GNUNET_MessageHeader header;
239 * The type for the data.
241 uint32_t type GNUNET_PACKED;
244 * Number of peers recorded in the outgoing path from source to the
245 * stored location of this message.
247 uint32_t put_path_length GNUNET_PACKED;
250 * Length of the GET path that follows (if tracked).
252 uint32_t get_path_length GNUNET_PACKED;
255 * Peer which queried for get and should get the result.
257 struct GNUNET_PeerIdentity querying_peer;
260 * When does the content expire?
262 struct GNUNET_TIME_Absolute expiration_time;
265 * The key of the corresponding GET request.
267 struct GNUNET_HashCode key;
269 /* put path (if tracked) */
271 /* get path (if tracked) */
278 * P2P Trail setup message
280 struct PeerTrailSetupMessage
283 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP
285 struct GNUNET_MessageHeader header;
288 * Is source_peer trying to setup the trail to any finger or predecessor.
290 uint32_t is_predecessor;
293 * Peer closest to this value will be our finger.
295 uint64_t ultimate_destination_finger_value;
298 * Source peer which wants to setup the trail to one of its finger.
300 struct GNUNET_PeerIdentity source_peer;
303 * Best known destination (could be my friend or finger) which should
304 * get this message next.
306 struct GNUNET_PeerIdentity best_known_destination;
309 * Trail id of any intermediate trail we may encounter while doing trail setup.
311 struct GNUNET_HashCode intermediate_trail_id;
314 * Trail id for trail which we are trying to setup.
316 struct GNUNET_HashCode trail_id;
318 /* List of peers which are part of trail setup so far.
319 * Trail does NOT include source_peer and peer which will be closest to
320 * ultimate_destination_finger_value.
321 * struct GNUNET_PeerIdentity trail_list[]
326 * P2P Trail Setup Result message
328 struct PeerTrailSetupResultMessage
332 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT
334 struct GNUNET_MessageHeader header;
337 * Finger to which we have found the path.
339 struct GNUNET_PeerIdentity finger_identity;
342 * Peer which started trail_setup to find trail to finger_identity
344 struct GNUNET_PeerIdentity querying_peer;
347 * Is the trail setup to querying_peer's predecessor or finger?
349 uint32_t is_predecessor;
352 * Value to which finger_identity is the closest peer.
354 uint64_t ulitmate_destination_finger_value;
357 * Identifier of the trail from querying peer to finger_identity, NOT
358 * including both endpoints.
360 struct GNUNET_HashCode trail_id;
362 /* List of peers which are part of the trail from querying peer to
363 * finger_identity, NOT including both endpoints.
364 * struct GNUNET_PeerIdentity trail[]
369 * P2P Verify Successor Message.
371 struct PeerVerifySuccessorMessage
374 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR
376 struct GNUNET_MessageHeader header;
379 * Peer which wants to verify its successor.
381 struct GNUNET_PeerIdentity source_peer;
384 * Source Peer's current successor.
386 struct GNUNET_PeerIdentity successor;
389 * Identifier of trail to reach from source_peer to successor.
391 struct GNUNET_HashCode trail_id;
393 /* List of the peers which are part of trail to reach from source_peer
394 * to successor, NOT including them
395 * struct GNUNET_PeerIdentity trail[]
400 * FIXME: In case you append the trail it may contain the same peer twice.
401 * So, when you call search_my_index it can return error. Solution is while
402 * appending the entry first check for duplicate entries or may be don't
403 * send the current_predecessor at all.
404 * P2P Verify Successor Result Message
406 struct PeerVerifySuccessorResultMessage
409 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT
411 struct GNUNET_MessageHeader header;
414 * Peer which sent the request to verify its successor.
416 struct GNUNET_PeerIdentity querying_peer;
419 * Successor to which PeerVerifySuccessorMessage was sent.
421 struct GNUNET_PeerIdentity source_successor;
424 * Current Predecessor of source_successor. It can be same as querying peer
427 struct GNUNET_PeerIdentity current_predecessor;
430 * Trail identifier of trail from querying_peer to source_successor.
432 struct GNUNET_HashCode trail_id;
435 * Direction in which we are looking at the trail.
437 uint32_t trail_direction;
439 /* In case current_predecessor != querying_peer, then trail to reach from
440 * querying_peer to current_predecessor, NOT including end points.
441 * struct GNUNET_PeerIdentity trail[]
446 * P2P Notify New Successor Message.
448 struct PeerNotifyNewSuccessorMessage
451 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR
453 struct GNUNET_MessageHeader header;
456 * Peer which wants to notify its new successor.
458 struct GNUNET_PeerIdentity source_peer;
461 * New successor of source_peer.
463 struct GNUNET_PeerIdentity new_successor;
466 * Unique identifier of the trail from source_peer to new_successor,
467 * NOT including the endpoints.
469 struct GNUNET_HashCode trail_id;
471 /* List of peers in trail from source_peer to new_successor,
472 * NOT including the endpoints.
473 * struct GNUNET_PeerIdentity trail[]
478 * FIXME: Check if you can merge trail compression and trail teardown
479 * by modifying routing table structure a little bit. PRIORITY: at the end
481 * P2P Trail Compression Message.
483 struct PeerTrailCompressionMessage
486 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_COMPRESSION
488 struct GNUNET_MessageHeader header;
491 * Source peer of this trail.
493 struct GNUNET_PeerIdentity source_peer;
496 * Destination of this trail.
498 struct GNUNET_PeerIdentity destination_peer;
501 * Trail from source_peer to destination_peer compressed such that
502 * new_first_friend is the first hop in the trail from source to
505 struct GNUNET_PeerIdentity new_first_friend;
508 * Unique identifier of trail.
510 struct GNUNET_HashCode trail_id;
515 * P2P Trail Tear Down message.
517 struct PeerTrailTearDownMessage
520 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_TEARDOWN
522 struct GNUNET_MessageHeader header;
525 * Source peer of the trail.
527 struct GNUNET_PeerIdentity source_peer;
530 * Destination peer of the trail.
532 struct GNUNET_PeerIdentity destination_peer;
535 * Unique identifier of the trail.
537 struct GNUNET_HashCode TRAIL_ID;
540 * Direction of trail.
542 uint32_t trail_direction;
547 * P2P Trail Rejection Message.
549 struct PeerTrailRejectionMessage
552 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION
554 struct GNUNET_MessageHeader header;
557 * Peer which wants to set up the trail.
559 struct GNUNET_PeerIdentity source_peer;
562 * Peer which sent trail rejection message as it it congested.
564 struct GNUNET_PeerIdentity congested_peer;
567 * Peer identity closest to this value will be finger of
570 uint64_t ultimate_destination_finger_value;
573 * Is source_peer trying to setup the trail to its predecessor or finger.
575 uint32_t is_predecessor;
578 * Identifier for the trail that source peer is trying to setup.
580 struct GNUNET_HashCode trail_id;
583 * Relative time for which congested_peer will remain congested.
585 struct GNUNET_TIME_Relative congestion_time;
587 /* Trail_list from source_peer to peer which sent the message for trail setup
588 * to congested peer. This trail does NOT include source_peer.
589 struct GNUNET_PeerIdnetity trail[]*/
593 * P2P Add Trail Message.
595 struct PeerAddTrailMessage
598 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_ADD_TRAIL
600 struct GNUNET_MessageHeader header;
603 * Source of the routing trail.
605 struct GNUNET_PeerIdentity source_peer;
608 * Destination of the routing trail.
610 struct GNUNET_PeerIdentity destination_peer;
613 * Unique identifier of the trail from source_peer to destination_peer,
614 * NOT including the endpoints.
616 struct GNUNET_HashCode trail_id;
618 /* Trail from source peer to destination peer, NOT including them.
619 * struct GNUNET_PeerIdentity trail[]
623 GNUNET_NETWORK_STRUCT_END
626 * Linked list of messages to send to a particular other peer.
628 struct P2PPendingMessage
631 * Pointer to next item in the list
633 struct P2PPendingMessage *next;
636 * Pointer to previous item in the list
638 struct P2PPendingMessage *prev;
641 * Message importance level. FIXME: used? useful?
643 unsigned int importance;
646 * When does this message time out?
648 struct GNUNET_TIME_Absolute timeout;
651 * Actual message to be sent, allocated at the end of the struct:
652 * // msg = (cast) &pm[1];
653 * // memcpy (&pm[1], data, len);
655 const struct GNUNET_MessageHeader *msg;
661 * Entry in friend_peermap.
668 struct GNUNET_PeerIdentity id;
671 * Number of trails for which this friend is the first hop or if the friend
674 unsigned int trails_count;
677 * Count of outstanding messages for this friend.
679 unsigned int pending_count;
682 * In case not 0, then amount of time for which this friend is congested.
684 struct GNUNET_TIME_Absolute congestion_timestamp;
687 * Head of pending messages to be sent to this friend.
689 struct P2PPendingMessage *head;
692 * Tail of pending messages to be sent to this friend.
694 struct P2PPendingMessage *tail;
697 * Core handle for sending messages to this friend.
699 struct GNUNET_CORE_TransmitHandle *th;
704 * An individual element of the trail to reach to a finger.
709 * Pointer to next item in the list
711 struct Trail_Element *next;
714 * Pointer to prev item in the list
716 struct Trail_Element *prev;
719 * An element in this trail.
721 struct GNUNET_PeerIdentity peer;
725 * FIXME: removed first_friend_trails_count, need to write a function
726 * to calculate each time we need it. Else, keep a pointer to first
727 * friend of in the trail.
728 * Information about an individual trail.
735 struct Trail_Element *trail_head;
740 struct Trail_Element *trail_tail;
743 * Unique identifier of this trail.
745 struct GNUNET_HashCode trail_id;
748 * Length of trail pointed
750 unsigned int trail_length;
754 * An entry in finger_hashmap.
761 struct GNUNET_PeerIdentity finger_identity;
764 * Index in finger peer map
766 uint32_t finger_map_index;
769 * Number of trails setup so far for this finger.
770 * Should not cross MAXIMUM_TRAILS_PER_FINGER.
772 uint32_t trails_count;
775 * Array of trails to reach to this finger.
777 struct Trail trail_list[MAXIMUM_TRAILS_PER_FINGER];
781 * FIXME: Need to check if we need all the fields or not.
782 * Data structure to keep track of closest peer seen so far in find_successor()
787 * 64 bit value of the peer
792 * Trail id to reach to peer.
794 struct GNUNET_HashCode trail_id;
797 * FIXME: see the usage of this field and write comment.
799 struct GNUNET_PeerIdentity next_hop;
802 * Next destination. In case of friend and my_identity , it is same as next_hop
803 * In case of finger it is finger identity.
805 struct GNUNET_PeerIdentity best_known_destination;
809 * FIXME: now I have removed the first_friend_trail_count,
810 * Need to update the code to find the count.
811 * Data structure to store the trail chosen to reach to finger.
813 struct Selected_Finger_Trail
816 * First friend in the trail to reach finger.
818 struct FriendInfo friend;
821 * Identifier of this trail.
823 struct GNUNET_HashCode trail_id;
826 * Total number of peers in this trail.
828 unsigned int trail_length;
832 * Task that sends FIND FINGER TRAIL requests. This task is started when we have
833 * get our first friend.
835 static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task;
838 * Identity of this peer.
840 static struct GNUNET_PeerIdentity my_identity;
843 * Peer map of all the friends of a peer
845 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap;
848 * Hash map of all the fingers of a peer
850 static struct GNUNET_CONTAINER_MultiHashMap32 *finger_hashmap;
853 * FIXME: Check if you can replace finger_hashmap by an array of fingers.
854 * Array of all the fingers.
856 static struct FingerInfo finger_table [MAX_FINGERS];*/
861 static struct GNUNET_CORE_Handle *core_api;
864 * The current finger index that we have want to find trail to. We start the
865 * search with value = 0, i.e. successor and then go to PREDCESSOR_FINGER_ID
866 * and decrement it. For any index 63 <= index < 0, if finger is same as successor,
867 * we reset this index to 0.
869 static unsigned int current_search_finger_index;
873 * Called when core is ready to send a message we asked for
874 * out to the destination.
876 * @param cls the 'struct FriendInfo' of the target friend
877 * @param size number of bytes available in buf
878 * @param buf where the callee should write the message
879 * @return number of bytes written to buf
882 core_transmit_notify (void *cls, size_t size, void *buf)
884 struct FriendInfo *peer = cls;
886 struct P2PPendingMessage *pending;
891 while ((NULL != (pending = peer->head)) &&
892 (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us))
894 peer->pending_count--;
895 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
896 GNUNET_free (pending);
900 /* no messages pending */
906 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
907 GNUNET_CORE_PRIO_BEST_EFFORT,
908 GNUNET_TIME_absolute_get_remaining
909 (pending->timeout), &peer->id,
910 ntohs (pending->msg->size),
911 &core_transmit_notify, peer);
912 GNUNET_break (NULL != peer->th);
916 while ((NULL != (pending = peer->head)) &&
917 (size - off >= (msize = ntohs (pending->msg->size))))
919 GNUNET_STATISTICS_update (GDS_stats,
921 ("# Bytes transmitted to other peers"), msize,
923 memcpy (&cbuf[off], pending->msg, msize);
925 peer->pending_count--;
926 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
927 GNUNET_free (pending);
929 if (peer->head != NULL)
932 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
933 GNUNET_CORE_PRIO_BEST_EFFORT,
934 GNUNET_TIME_absolute_get_remaining
935 (pending->timeout), &peer->id, msize,
936 &core_transmit_notify, peer);
937 GNUNET_break (NULL != peer->th);
945 * Transmit all messages in the friend's message queue.
947 * @param peer message queue to process
950 process_friend_queue (struct FriendInfo *peer)
952 struct P2PPendingMessage *pending;
954 if (NULL == (pending = peer->head))
956 if (NULL != peer->th)
959 GNUNET_STATISTICS_update (GDS_stats,
961 ("# Bytes of bandwidth requested from core"),
962 ntohs (pending->msg->size), GNUNET_NO);
965 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
967 GNUNET_TIME_absolute_get_remaining
968 (pending->timeout), &peer->id,
969 ntohs (pending->msg->size),
970 &core_transmit_notify, peer);
971 GNUNET_break (NULL != peer->th);
976 * Construct a trail setup message and forward it to target_friend
977 * @param source_peer Peer which wants to setup the trail
978 * @param ultimate_destination_finger_value Peer identity closest to this value
979 * will be finger to @a source_peer
980 * @param best_known_destination Best known destination (could be finger or friend)
981 * which should get this message.
982 * @param target_friend Friend to which message is forwarded now.
983 * @param trail_length Total number of peers in trail setup so far.
984 * @param trail_peer_list Trail setup so far
985 * @param is_predecessor Is source_peer looking for trail to a predecessor or not.
986 * @param trail_id Unique identifier for the trail we are trying to setup.
987 * @param intermediate_trail_id Trail id of intermediate trail to reach to
988 * best_known_destination when its a finger. If not
989 * used then set to 0.
992 GDS_NEIGHBOURS_send_trail_setup (struct GNUNET_PeerIdentity source_peer,
993 uint64_t ultimate_destination_finger_value,
994 struct GNUNET_PeerIdentity best_known_destination,
995 struct FriendInfo *target_friend,
996 unsigned int trail_length,
997 const struct GNUNET_PeerIdentity *trail_peer_list,
998 unsigned int is_predecessor,
999 struct GNUNET_HashCode trail_id,
1000 struct GNUNET_HashCode *intermediate_trail_id)
1002 struct P2PPendingMessage *pending;
1003 struct PeerTrailSetupMessage *tsm;
1004 struct GNUNET_PeerIdentity *peer_list;
1007 msize = sizeof (struct PeerTrailSetupMessage) +
1008 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1010 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1016 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1018 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1022 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1023 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1024 tsm = (struct PeerTrailSetupMessage *) &pending[1];
1025 pending->msg = &tsm->header;
1026 tsm->header.size = htons (msize);
1027 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
1028 tsm->ultimate_destination_finger_value = GNUNET_htonll (ultimate_destination_finger_value);
1029 tsm->source_peer = source_peer;
1030 tsm->best_known_destination = best_known_destination;
1031 tsm->is_predecessor = htonl (is_predecessor);
1032 tsm->trail_id = trail_id;
1034 if (NULL == intermediate_trail_id)
1035 memset (&tsm->intermediate_trail_id, 0, sizeof (tsm->intermediate_trail_id));
1037 tsm->intermediate_trail_id = *intermediate_trail_id;
1039 if (trail_length > 0)
1041 peer_list = (struct GNUNET_PeerIdentity *) &tsm[1];
1042 memcpy (peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
1045 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1046 target_friend->pending_count++;
1047 process_friend_queue (target_friend);
1052 * Construct a trail setup result message and forward it to target friend.
1053 * @param querying_peer Peer which sent the trail setup request and should get
1055 * @param Finger Peer to which the trail has been setup to.
1056 * @param target_friend Friend to which this message should be forwarded.
1057 * @param trail_length Numbers of peers in the trail.
1058 * @param trail_peer_list Peers which are part of the trail from q
1059 * querying_peer to Finger, NOT including them.
1060 * @param is_predecessor Is @a Finger predecessor to @a querying_peer
1061 * @param ultimate_destination_finger_value Value to which @a finger is the closest
1063 * @param trail_id Unique identifier of the trail.
1066 GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity querying_peer,
1067 struct GNUNET_PeerIdentity finger,
1068 struct FriendInfo *target_friend,
1069 unsigned int trail_length,
1070 const struct GNUNET_PeerIdentity *trail_peer_list,
1071 unsigned int is_predecessor,
1072 uint64_t ultimate_destination_finger_value,
1073 struct GNUNET_HashCode trail_id)
1075 struct P2PPendingMessage *pending;
1076 struct PeerTrailSetupResultMessage *tsrm;
1077 struct GNUNET_PeerIdentity *peer_list;
1080 msize = sizeof (struct PeerTrailSetupResultMessage) +
1081 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1083 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1089 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1091 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1095 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1096 pending->importance = 0;
1097 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1098 tsrm = (struct PeerTrailSetupResultMessage *) &pending[1];
1099 pending->msg = &tsrm->header;
1100 tsrm->header.size = htons (msize);
1101 tsrm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT);
1102 tsrm->querying_peer = querying_peer;
1103 tsrm->finger_identity = finger;
1104 tsrm->is_predecessor = htonl (is_predecessor);
1105 tsrm->trail_id = trail_id;
1106 tsrm->ulitmate_destination_finger_value =
1107 GNUNET_htonll (ultimate_destination_finger_value);
1108 peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1];
1109 if (trail_length > 0)
1111 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1113 /* Send the message to chosen friend. */
1114 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1115 target_friend->pending_count++;
1116 process_friend_queue (target_friend);
1121 * Send trail rejection message to next_hop
1122 * @param source_peer Peer which is trying to setup the trail.
1123 * @param ultimate_destination_finger_value Peer closest to this value will be
1124 * @a source_peer's finger
1125 * @param congested_peer Peer which sent this message as it is congested.
1126 * @param is_predecessor Is source_peer looking for trail to a predecessor or not.
1127 * @param trail_peer_list Trails seen so far in trail setup before getting rejected
1128 * by congested_peer. This does not include @a source_peer
1129 * @param trail_length Total number of peers in trail_peer_list, not including
1131 * @param trail_id Unique identifier of this trail.
1132 * @param congestion_timeout Duration given by congested peer as an estimate of
1133 * how long it may remain congested.
1136 GDS_NEIGHBOURS_send_trail_rejection (struct GNUNET_PeerIdentity source_peer,
1137 uint64_t ultimate_destination_finger_value,
1138 struct GNUNET_PeerIdentity congested_peer,
1139 unsigned int is_predecessor,
1140 const struct GNUNET_PeerIdentity *trail_peer_list,
1141 unsigned int trail_length,
1142 struct GNUNET_HashCode trail_id,
1143 struct FriendInfo *target_friend,
1144 const struct GNUNET_TIME_Relative congestion_timeout)
1146 struct PeerTrailRejectionMessage *trm;
1147 struct P2PPendingMessage *pending;
1148 struct GNUNET_PeerIdentity *peer_list;
1151 msize = sizeof (struct PeerTrailRejectionMessage) +
1152 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1154 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1160 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1162 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1166 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1167 pending->importance = 0;
1168 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1169 trm = (struct PeerTrailRejectionMessage *)&pending[1];
1170 pending->msg = &trm->header;
1171 trm->header.size = htons (msize);
1172 trm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION);
1173 trm->source_peer = source_peer;
1174 trm->congested_peer = congested_peer;
1175 trm->congestion_time = congestion_timeout;
1176 trm->is_predecessor = htonl (is_predecessor);
1177 trm->trail_id = trail_id;
1178 trm->ultimate_destination_finger_value = GNUNET_htonll (ultimate_destination_finger_value);
1180 peer_list = (struct GNUNET_PeerIdentity *) &trm[1];
1181 if (trail_length > 0)
1183 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1186 /* Send the message to chosen friend. */
1187 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1188 target_friend->pending_count++;
1189 process_friend_queue (target_friend);
1194 * Construct a verify successor message and forward it to target_friend.
1195 * @param source_peer Peer which wants to verify its successor.
1196 * @param successor Peer which is @a source_peer's current successor.
1197 * @param trail_id Unique Identifier of trail from @a source_peer to @a successor,
1198 * NOT including them.
1199 * @param trail List of peers which are part of trail to reach from @a source_peer
1200 * to @a successor, NOT including them.
1201 * @param trail_length Total number of peers in @a trail.
1202 * @param target_friend Next friend to get this message.
1205 GDS_NEIGHBOURS_send_verify_successor_message (struct GNUNET_PeerIdentity source_peer,
1206 struct GNUNET_PeerIdentity successor,
1207 const struct GNUNET_HashCode trail_id,
1208 struct GNUNET_PeerIdentity *trail,
1209 unsigned int trail_length,
1210 struct FriendInfo *target_friend)
1212 struct PeerVerifySuccessorMessage *vsm;
1213 struct P2PPendingMessage *pending;
1214 struct GNUNET_PeerIdentity *peer_list;
1217 msize = sizeof (struct PeerVerifySuccessorMessage);
1218 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1224 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1226 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1230 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1231 pending->importance = 0; /* FIXME */
1232 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1233 vsm = (struct PeerVerifySuccessorMessage *) &pending[1];
1234 pending->msg = &vsm->header;
1235 vsm->header.size = htons (msize);
1236 vsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR);
1237 vsm->source_peer = source_peer;
1238 vsm->successor = successor;
1239 vsm->trail_id = trail_id;
1241 if (trail_length > 0)
1243 peer_list = (struct GNUNET_PeerIdentity *) &vsm[1];
1244 memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
1247 /* Send the message to chosen friend. */
1248 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1249 target_friend->pending_count++;
1250 process_friend_queue (target_friend);
1255 * FIXME: check if we can merge send_trail_teardown and trail_compression
1256 * Construct a trail teardown message and send it to target_friend
1257 * @param source_peer Source of the trail.
1258 * @param destination_peer Destination of the trail.
1259 * @param trail_id Unique identifier of the trail.
1260 * @param trail_direction Direction of trail.
1261 * @param target_friend Friend to get this message.
1264 GDS_NEIGHBOURS_send_trail_teardown (struct GNUNET_PeerIdentity source_peer,
1265 struct GNUNET_PeerIdentity destination_peer,
1266 struct GNUNET_HashCode trail_id,
1267 enum GDS_ROUTING_trail_direction trail_direction,
1268 struct FriendInfo *target_friend)
1270 struct PeerTrailTearDownMessage *ttdm;
1271 struct P2PPendingMessage *pending;
1274 msize = sizeof (struct PeerTrailTearDownMessage);
1276 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1282 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1284 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1288 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1289 pending->importance = 0; /* FIXME */
1290 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1291 ttdm = (struct PeerTrailTearDownMessage *) &pending[1];
1292 pending->msg = &ttdm->header;
1293 ttdm->header.size = htons (msize);
1294 ttdm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_TEARDOWN);
1295 ttdm->source_peer = source_peer;
1296 ttdm->destination_peer = destination_peer;
1297 ttdm->TRAIL_ID = trail_id;
1298 ttdm->trail_direction = htonl (trail_direction);
1300 /* Send the message to chosen friend. */
1301 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1302 target_friend->pending_count++;
1303 process_friend_queue (target_friend);
1308 * Construct a verify successor result message and send it to target_friend
1309 * @param querying_peer Peer which sent the verify successor message.
1310 * @param source_successor Current_successor of @a querying_peer.
1311 * @param current_predecessor Current predecessor of @a successor. Could be same
1312 * or different from @a querying_peer.
1313 * @param trail_id Unique identifier of the trail from @a querying_peer to
1314 * @a successor, NOT including them.
1315 * @param trail List of peers which are part of trail from @a querying_peer to
1316 * @a successor, NOT including them.
1317 * @param trail_length Total number of peers in @a trail
1318 * @param trail_direction Direction in which we are sending the message. In this
1319 * case we are sending result from @a successor to @a querying_peer.
1320 * @param target_friend Next friend to get this message.
1323 GDS_NEIGHBOURS_send_verify_successor_result (struct GNUNET_PeerIdentity querying_peer,
1324 struct GNUNET_PeerIdentity source_successor,
1325 struct GNUNET_PeerIdentity current_predecessor,
1326 struct GNUNET_HashCode trail_id,
1327 const struct GNUNET_PeerIdentity *trail,
1328 unsigned int trail_length,
1329 enum GDS_ROUTING_trail_direction trail_direction,
1330 struct FriendInfo *target_friend)
1332 struct PeerVerifySuccessorResultMessage *vsmr;
1333 struct P2PPendingMessage *pending;
1334 struct GNUNET_PeerIdentity *peer_list;
1337 msize = sizeof (struct PeerVerifySuccessorResultMessage) +
1338 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1340 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1346 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1348 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1352 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1353 pending->importance = 0; /* FIXME */
1354 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1355 vsmr = (struct PeerVerifySuccessorResultMessage *) &pending[1];
1356 pending->msg = &vsmr->header;
1357 vsmr->header.size = htons (msize);
1358 vsmr->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT);
1359 vsmr->querying_peer = querying_peer;
1360 vsmr->source_successor = source_successor;
1361 vsmr->current_predecessor = current_predecessor;
1362 vsmr->trail_direction = htonl (trail_direction);
1363 vsmr->trail_id = trail_id;
1365 if (trail_length > 0)
1367 peer_list = (struct GNUNET_PeerIdentity *) &vsmr[1];
1368 memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
1371 /* Send the message to chosen friend. */
1372 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1373 target_friend->pending_count++;
1374 process_friend_queue (target_friend);
1379 * Construct a notify new successor message and send it to target_friend
1380 * @param source_peer Peer which wants to notify to its new successor that it
1381 * could be its predecessor.
1382 * @param successor New successor of @a source_peer
1383 * @param successor_trail List of peers in Trail to reach from
1384 * @a source_peer to @a new_successor, NOT including
1386 * @param successor_trail_length Total number of peers in @a new_successor_trail.
1387 * @param successor_trail_id Unique identifier of @a new_successor_trail.
1388 * @param target_friend Next friend to get this message.
1391 GDS_NEIGHBOURS_send_notify_new_successor (struct GNUNET_PeerIdentity source_peer,
1392 struct GNUNET_PeerIdentity successor,
1393 struct GNUNET_PeerIdentity *successor_trail,
1394 unsigned int successor_trail_length,
1395 struct GNUNET_HashCode succesor_trail_id,
1396 struct FriendInfo *target_friend)
1398 struct PeerNotifyNewSuccessorMessage *nsm;
1399 struct P2PPendingMessage *pending;
1400 struct GNUNET_PeerIdentity *peer_list;
1403 msize = sizeof (struct PeerNotifyNewSuccessorMessage) +
1404 (successor_trail_length * sizeof(struct GNUNET_PeerIdentity));
1406 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1412 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1414 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1418 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1419 pending->importance = 0; /* FIXME */
1420 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1421 nsm = (struct PeerNotifyNewSuccessorMessage *) &pending[1];
1422 pending->msg = &nsm->header;
1423 nsm->header.size = htons (msize);
1424 nsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR);
1425 nsm->new_successor = successor;
1426 nsm->source_peer = source_peer;
1427 nsm->trail_id = succesor_trail_id;
1429 if (successor_trail_length > 0)
1431 peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
1432 memcpy (peer_list, successor_trail,
1433 successor_trail_length * sizeof (struct GNUNET_PeerIdentity));
1436 /* Send the message to chosen friend. */
1437 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1438 target_friend->pending_count++;
1439 process_friend_queue (target_friend);
1444 * Construct an add_trail message and send it to target_friend
1445 * @param source_peer Source of the trail.
1446 * @param destination_peer Destination of the trail.
1447 * @param trail_id Unique identifier of the trail from
1448 * @a source_peer to @a destination_peer, NOT including the endpoints.
1449 * @param trail List of peers in Trail from @a source_peer to @a destination_peer,
1450 * NOT including the endpoints.
1451 * @param trail_length Total number of peers in @a trail.
1452 * @param target_friend Next friend to get this message.
1455 GDS_NEIGHBOURS_send_add_trail (struct GNUNET_PeerIdentity source_peer,
1456 struct GNUNET_PeerIdentity destination_peer,
1457 struct GNUNET_HashCode trail_id,
1458 struct GNUNET_PeerIdentity *trail,
1459 unsigned int trail_length,
1460 struct FriendInfo *target_friend)
1462 struct PeerAddTrailMessage *adm;
1463 struct GNUNET_PeerIdentity *peer_list;
1464 struct P2PPendingMessage *pending;
1467 msize = sizeof (struct PeerAddTrailMessage) +
1468 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1470 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1476 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1478 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1482 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1483 pending->importance = 0; /* FIXME */
1484 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1485 adm = (struct PeerAddTrailMessage *) &pending[1];
1486 pending->msg = &adm->header;
1487 adm->header.size = htons (msize);
1488 adm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_ADD_TRAIL);
1489 adm->source_peer = source_peer;
1490 adm->destination_peer = destination_peer;
1491 adm->trail_id = trail_id;
1493 if (trail_length > 0)
1495 peer_list = (struct GNUNET_PeerIdentity *)&adm[1];
1496 memcpy (peer_list, trail, sizeof (struct GNUNET_PeerIdentity) * trail_length);
1499 /* Send the message to chosen friend. */
1500 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1501 target_friend->pending_count++;
1502 process_friend_queue (target_friend);
1508 * FIXME: Merge into "teardown", add source and "last/new_first" in message struct.
1509 * Construct a trail compression message and send it to target_friend.
1510 * @param source_peer Source of the trail.
1511 * @param destination_finger Destination of trail.
1512 * @param trail_id Unique identifier of trail.
1513 * @param first_friend First hop in compressed trail to reach from source to finger
1514 * @param target_friend Next friend to get this message.
1517 GDS_NEIGHBOURS_send_trail_compression (struct GNUNET_PeerIdentity source_peer,
1518 struct GNUNET_PeerIdentity destination_peer,
1519 struct GNUNET_HashCode trail_id,
1520 struct GNUNET_PeerIdentity first_friend,
1521 struct FriendInfo *target_friend)
1523 struct P2PPendingMessage *pending;
1524 struct PeerTrailCompressionMessage *tcm;
1527 msize = sizeof (struct PeerTrailCompressionMessage);
1529 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1535 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1537 GNUNET_STATISTICS_update (GDS_stats,
1538 gettext_noop ("# P2P messages dropped due to full queue"),
1542 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1543 pending->importance = 0; /* FIXME */
1544 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1545 tcm = (struct PeerTrailCompressionMessage *) &pending[1];
1546 pending->msg = &tcm->header;
1547 tcm->header.size = htons (msize);
1548 tcm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_COMPRESSION);
1549 tcm->source_peer = source_peer;
1550 tcm->new_first_friend = first_friend;
1551 tcm->trail_id = trail_id;
1552 tcm->destination_peer = destination_peer;
1554 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1555 target_friend->pending_count++;
1556 process_friend_queue (target_friend);
1562 * Search my location in trail.
1563 * @param trail List of peers
1564 * @return my_index if found
1565 * -1 if no entry found.
1568 search_my_index (const struct GNUNET_PeerIdentity *trail,
1573 for (i = 0; i < trail_length; i++)
1575 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &trail[i]))
1583 * Check if the friend is congested or have reached maximum number of trails
1584 * it can be part of of.
1585 * @param friend Friend to be chechked.
1586 * @return #GNUNET_YES if friend is not congested or have not crossed threshold.
1587 * #GNUNET_NO if friend is either congested or have crossed threshold
1590 is_friend_congested (struct FriendInfo *friend)
1592 if ((friend->trails_count == TRAILS_THROUGH_FRIEND_THRESHOLD)||
1593 ((0 != GNUNET_TIME_absolute_get_remaining
1594 (friend->congestion_timestamp).rel_value_us)))
1602 * FIXME: here we should also check if iterator is null or not. It can be NULL
1603 * only if we insert randomly at locations. But as we are using trails_count
1604 * as the parameter, it should not happen.
1605 * Iterate over the list of all the trails of a finger. In case the first
1606 * friend to reach the finger has reached trail threshold or is congested,
1607 * then don't select it. In case there multiple available good trails to reach
1608 * to Finger, choose the one with shortest trail length.
1609 * Note: We use length as parameter. But we can use any other suitable parameter
1611 * @param finger Finger
1612 * @return struct Selected_Finger_Trail which contains the first friend , trail id
1613 * and trail length. NULL in case none of the trails are free.
1615 static struct Selected_Finger_Trail *
1616 select_finger_trail (struct FingerInfo *finger)
1618 struct FriendInfo *friend;
1619 struct Trail *iterator;
1620 struct Selected_Finger_Trail *finger_trail;
1623 finger_trail = GNUNET_new (struct Selected_Finger_Trail);
1625 for (i = 0; i < finger->trails_count; i++)
1627 iterator = &finger->trail_list[i];
1628 friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1629 &iterator->trail_head->peer);
1630 if (GNUNET_YES == is_friend_congested (friend))
1633 /* Check if the trail length of this trail is least seen so far. If yes then
1634 set finger_trail to this trail.*/
1635 if (finger_trail->trail_length > iterator->trail_length)
1637 finger_trail->friend = *friend;
1638 finger_trail->trail_id = iterator->trail_id;
1639 finger_trail->trail_length = iterator->trail_length;
1643 /* No trail found. */
1644 if (i == finger->trails_count)
1645 finger_trail = NULL;
1647 return finger_trail;
1652 * Select closest finger to value.
1653 * @param peer1 First peer
1654 * @param peer2 Second peer
1655 * @param value Value to be compare
1656 * @return Closest peer
1658 static struct GNUNET_PeerIdentity *
1659 select_closest_finger (struct GNUNET_PeerIdentity *peer1,
1660 struct GNUNET_PeerIdentity *peer2,
1664 uint64_t peer1_value;
1665 uint64_t peer2_value;
1667 memcpy (&peer1_value, peer1, sizeof (uint64_t));
1668 memcpy (&peer2_value, peer2, sizeof (uint64_t));
1670 if ((peer1_value <= value) && (value <= peer2_value))
1672 else if ((peer2_value <= value) && (value <= peer1_value))
1674 else if ((peer1_value <= peer2_value) && (peer2_value <= value))
1676 else if ((peer2_value <= peer1_value) && (peer1_value <= value))
1678 else if ((value <= peer1_value) && (peer1_value <= peer2_value))
1680 else /*if ((value <= peer2_value) && (peer2_value <= peer1_value))*/
1688 * Select closest predecessor to value.
1689 * @param peer1 First peer
1690 * @param peer2 Second peer
1691 * @param value Value to be compare
1692 * @return Closest peer
1694 static struct GNUNET_PeerIdentity *
1695 select_closest_predecessor (struct GNUNET_PeerIdentity *peer1,
1696 struct GNUNET_PeerIdentity *peer2,
1700 uint64_t peer1_value;
1701 uint64_t peer2_value;
1703 memcpy (&peer1_value, peer1, sizeof (uint64_t));
1704 memcpy (&peer2_value, peer2, sizeof (uint64_t));
1712 * Select the closest peer among two peers (which should not be same)
1713 * with respect to value and finger_map_index
1714 * @param peer1 First peer
1715 * @param peer2 Second peer
1716 * @param value Value relative to which we find the closest
1717 * @param finger_map_index Index in finger map. If equal to PREDECESSOR_FINGER_ID,
1718 * then we use different logic than other
1720 * @return Closest peer among two peers.
1722 static struct GNUNET_PeerIdentity *
1723 select_closest_peer (struct GNUNET_PeerIdentity *peer1,
1724 struct GNUNET_PeerIdentity *peer2,
1726 unsigned int finger_map_index)
1728 struct GNUNET_PeerIdentity *closest_peer;
1730 if (PREDECESSOR_FINGER_ID == finger_map_index)
1731 closest_peer = select_closest_predecessor (peer1, peer2, value);
1733 closest_peer = select_closest_finger (peer1, peer2, value);
1735 return closest_peer;
1740 * Find the successor for destination_finger_value among my_identity, all my
1741 * friend and all my fingers. Don't consider friends or fingers
1742 * which are congested or have crossed the threshold.
1743 * @param destination_finger_value Peer closest to this value will be the next successor.
1744 * @param next_destination [out] Updated to friend identity in case a friend is
1745 * successor, updated to first friend to reach to finger
1746 * in case finger is the destination.
1747 * @param new_intermediate_trail_id [out] In case we finger is the @a next_destination,
1748 * then we updated the field with trail id to reach
1750 * @param finger_map_index Index in finger peermap for which we are
1751 * looking for a finger, to discern between
1752 * IS_PREDECESSOR or not.
1753 * @return Closest successor for value.
1755 static struct GNUNET_PeerIdentity *
1756 find_successor (uint64_t destination_finger_value,
1757 struct GNUNET_PeerIdentity *best_known_destination,
1758 struct GNUNET_HashCode *new_intermediate_trail_id,
1759 unsigned int finger_map_index)
1761 struct Closest_Peer *current_successor;
1762 struct GNUNET_PeerIdentity *next_hop;
1763 struct GNUNET_CONTAINER_MultiPeerMapIterator *friend_iter;
1764 struct GNUNET_CONTAINER_MultiHashMap32Iterator *finger_iter;
1765 struct Selected_Finger_Trail *finger_trail;
1766 struct FriendInfo *friend;
1767 struct FingerInfo *finger;
1770 /* Initialize current_successor to my_identity. */
1771 current_successor = GNUNET_new (struct Closest_Peer);
1772 memcpy (¤t_successor->value, &my_identity, sizeof (uint64_t));
1773 memset (¤t_successor->trail_id, 0, sizeof (current_successor->trail_id));
1774 current_successor->next_hop = my_identity;
1775 current_successor->best_known_destination = my_identity;
1777 /* Iterate over friend_peermap and compare each friend with current_successor.*/
1778 friend_iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1779 for (i= 0; i < GNUNET_CONTAINER_multipeermap_size (friend_peermap); i++)
1781 GNUNET_assert (GNUNET_YES ==
1782 GNUNET_CONTAINER_multipeermap_iterator_next (friend_iter, NULL,
1783 (const void **)&friend));
1785 if (GNUNET_YES == is_friend_congested (friend))
1788 /* FIXME: select closest peer w.r.t. value. [friend_id, current_successor->id)
1789 and [current_successor->id, friend_id). Check in which range value lies.
1790 Also, check for wrap around. Set the value of current_successor accordingly.*/
1793 /* Iterate over finger_hashmap and compare each finger with current_successor.*/
1794 finger_iter = GNUNET_CONTAINER_multihashmap32_iterator_create (finger_hashmap);
1795 for (i = 0; i < GNUNET_CONTAINER_multihashmap32_size (finger_hashmap); i++)
1797 GNUNET_assert (GNUNET_YES ==
1798 GNUNET_CONTAINER_multihashmap32_iterator_next (finger_iter, NULL,
1801 /* If I am my own finger, then ignore this finger. */
1802 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
1806 /* If finger is friend. */
1807 if(GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger->finger_identity))
1809 /* If not congested then compare it with current_successor. */
1810 if (GNUNET_NO == is_friend_congested (friend))
1812 //compare it with current successor.
1815 /* Choose one of the trail to reach to finger. */
1816 finger_trail = select_finger_trail (finger);
1818 /* In case no trail found, ignore this finger. */
1819 if (NULL == finger_trail)
1822 /* FIXME: select closest peer w.r.t. value. [finger->friend_id, current_successor->id)
1823 and [current_successor->id, finger->friend_id). Check in which range value lies.
1824 Also, check for wrap around. But this will give you the immediate predecessor
1825 For example. if we have 0,1,6 and I am 0 and one of my finger is 6. Then
1826 for 1, we will have ranges like [0,6) and [6,0) 1 lies in range from [0,6)
1827 but successor is 6 not 0 as 6 is > than 1. If you are the closest one,
1829 in current_successor. Want to write a generic code so that it is used in
1830 * finger_table_add also while choosing the closest one among new and existing
1834 best_known_destination = ¤t_successor->best_known_destination;
1835 new_intermediate_trail_id = ¤t_successor->trail_id;
1836 next_hop = ¤t_successor->next_hop;
1843 * Construct a Put message and send it to target_peer.
1844 * @param key Key for the content
1845 * @param block_type Type of the block
1846 * @param options Routing options
1847 * @param desired_replication_level Desired replication count
1848 * @param best_known_dest Peer to which this message should reach eventually,
1849 * as it is best known destination to me.
1850 * @param intermediate_trail_id Trail id in case
1851 * @param target_peer Peer to which this message will be forwarded.
1852 * @param hop_count Number of hops traversed so far.
1853 * @param put_path_length Total number of peers in @a put_path
1854 * @param put_path Number of peers traversed so far
1855 * @param expiration_time When does the content expire
1856 * @param data Content to store
1857 * @param data_size Size of content @a data in bytes
1860 GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key,
1861 enum GNUNET_BLOCK_Type block_type,
1862 enum GNUNET_DHT_RouteOption options,
1863 uint32_t desired_replication_level,
1864 struct GNUNET_PeerIdentity *best_known_dest,
1865 struct GNUNET_HashCode *intermediate_trail_id,
1866 struct GNUNET_PeerIdentity *target_peer,
1868 uint32_t put_path_length,
1869 struct GNUNET_PeerIdentity *put_path,
1870 struct GNUNET_TIME_Absolute expiration_time,
1871 const void *data, size_t data_size)
1873 struct PeerPutMessage *ppm;
1874 struct P2PPendingMessage *pending;
1875 struct FriendInfo *target_friend;
1876 struct GNUNET_PeerIdentity *pp;
1879 msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
1880 sizeof (struct PeerPutMessage);
1882 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1884 put_path_length = 0;
1885 msize = data_size + sizeof (struct PeerPutMessage);
1888 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1894 /* This is the first call made from clients file. So, we should search for the
1896 if (NULL == target_peer)
1899 struct GNUNET_PeerIdentity *next_hop;
1901 memcpy (&key_value, key, sizeof (uint64_t));
1902 next_hop = find_successor (key_value, best_known_dest,
1903 intermediate_trail_id, GDS_FINGER_TYPE_NON_PREDECESSOR);
1904 if (0 == GNUNET_CRYPTO_cmp_peer_identity(next_hop, &my_identity))
1906 /* I am the destination but we have already done datacache_put in client file. */
1910 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
1913 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1914 pending->timeout = expiration_time;
1915 ppm = (struct PeerPutMessage *) &pending[1];
1916 pending->msg = &ppm->header;
1917 ppm->header.size = htons (msize);
1918 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
1919 ppm->options = htonl (options);
1920 ppm->block_type = htonl (block_type);
1921 ppm->hop_count = htonl (hop_count + 1);
1922 ppm->desired_replication_level = htonl (desired_replication_level);
1923 ppm->put_path_length = htonl (put_path_length);
1924 ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
1925 ppm->best_known_destination = *best_known_dest;
1927 if (NULL == intermediate_trail_id)
1928 memset (&ppm->intermediate_trail_id, 0, sizeof (ppm->intermediate_trail_id));
1930 ppm->intermediate_trail_id = *intermediate_trail_id;
1931 pp = (struct GNUNET_PeerIdentity *) &ppm[1];
1932 if (put_path_length != 0)
1934 memcpy (pp, put_path,
1935 sizeof (struct GNUNET_PeerIdentity) * put_path_length);
1937 memcpy (&pp[put_path_length], data, data_size);
1938 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1939 target_friend->pending_count++;
1940 process_friend_queue (target_friend);
1946 * Construct a Get message and send it to target_peer.
1947 * @param key Key for the content
1948 * @param block_type Type of the block
1949 * @param options Routing options
1950 * @param desired_replication_level Desired replication count
1951 * @param best_known_dest
1952 * @param intermediate_trail_id
1953 * @param target_peer Peer to which this message will be forwarded.
1954 * @param hop_count Number of hops traversed so far.
1955 * @param data Content to store
1956 * @param data_size Size of content @a data in bytes
1957 * @param get_path_length Total number of peers in @a get_path
1958 * @param get_path Number of peers traversed so far
1961 GDS_NEIGHBOURS_send_get (const struct GNUNET_HashCode *key,
1962 enum GNUNET_BLOCK_Type block_type,
1963 enum GNUNET_DHT_RouteOption options,
1964 uint32_t desired_replication_level,
1965 struct GNUNET_PeerIdentity *best_known_dest,
1966 struct GNUNET_HashCode *intermediate_trail_id,
1967 struct GNUNET_PeerIdentity *target_peer,
1969 uint32_t get_path_length,
1970 struct GNUNET_PeerIdentity *get_path)
1972 struct PeerGetMessage *pgm;
1973 struct P2PPendingMessage *pending;
1974 struct FriendInfo *target_friend;
1975 struct GNUNET_PeerIdentity *gp;
1978 msize = sizeof (struct PeerGetMessage) +
1979 (get_path_length * sizeof (struct GNUNET_PeerIdentity));
1981 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1987 if (NULL == target_peer)
1989 struct GNUNET_PeerIdentity *next_hop;
1992 memcpy (&key_value, key, sizeof (uint64_t));
1993 // FIXME: endianess of key_value!?
1994 /* FIXME: Here you should use enum GDS_NEIGHBOURS_FINGER_TYPE in place of 0. */
1995 next_hop = find_successor (key_value, best_known_dest,
1996 intermediate_trail_id, GDS_FINGER_TYPE_NON_PREDECESSOR);
1998 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity,next_hop))
2000 GDS_DATACACHE_handle_get (key,block_type, NULL, 0,
2001 NULL, 0, 1, &my_identity, NULL,&my_identity);
2006 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2010 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2011 pending->importance = 0; /* FIXME */
2012 pgm = (struct PeerGetMessage *) &pending[1];
2013 pending->msg = &pgm->header;
2014 pgm->header.size = htons (msize);
2015 pgm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
2016 pgm->get_path_length = htonl (get_path_length);
2018 pgm->best_known_destination = *best_known_dest;
2019 pgm->intermediate_trail_id = *intermediate_trail_id;
2020 pgm->hop_count = htonl (hop_count + 1);
2024 gp = (struct GNUNET_PeerIdentity *) &pgm[1];
2025 memcpy (gp, get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity));
2027 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2028 target_friend->pending_count++;
2029 process_friend_queue (target_friend);
2034 * Send the get result to requesting client.
2035 * @param key Key of the requested data.
2036 * @param type Block type
2037 * @param target_peer Next peer to forward the message to.
2038 * @param source_peer Peer which has the data for the key.
2039 * @param put_path_length Number of peers in @a put_path
2040 * @param put_path Path taken to put the data at its stored location.
2041 * @param get_path_length Number of peers in @a get_path
2042 * @param get_path Path taken to reach to the location of the key.
2043 * @param expiration When will this result expire?
2044 * @param data Payload to store
2045 * @param data_size Size of the @a data
2048 GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key,
2049 enum GNUNET_BLOCK_Type type,
2050 struct GNUNET_PeerIdentity *target_peer,
2051 struct GNUNET_PeerIdentity *source_peer,
2052 unsigned int put_path_length,
2053 const struct GNUNET_PeerIdentity *put_path,
2054 unsigned int get_path_length,
2055 struct GNUNET_PeerIdentity *get_path,
2056 struct GNUNET_TIME_Absolute expiration,
2057 const void *data, size_t data_size)
2059 struct PeerGetResultMessage *get_result;
2060 struct GNUNET_PeerIdentity *get_result_path;
2061 struct GNUNET_PeerIdentity *pp;
2062 struct P2PPendingMessage *pending;
2063 struct FriendInfo *target_friend;
2064 int current_path_index;
2067 msize = get_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
2068 sizeof (struct PeerPutMessage);
2070 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2076 if(get_path_length > 0)
2078 current_path_index = search_my_index(get_path, get_path_length);
2079 if (GNUNET_SYSERR == current_path_index)
2085 if (0 == current_path_index)
2087 GDS_CLIENTS_handle_reply (expiration, key, get_path_length,
2088 get_path, put_path_length,
2089 put_path, type, data_size, data);
2093 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2094 pending->importance = 0;
2095 get_result = (struct PeerGetResultMessage *)&pending[1];
2096 pending->msg = &get_result->header;
2097 get_result->header.size = htons (msize);
2098 get_result->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT);
2099 get_result->key = *key;
2100 /* FIXME: check if you are passing the correct querying_peer as described in
2101 the get_result documentation. */
2102 memcpy (&(get_result->querying_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
2103 get_result->expiration_time = expiration;
2105 if (get_path_length != 0)
2107 get_result_path = (struct GNUNET_PeerIdentity *)&get_result[1];
2108 memcpy (get_result_path, get_path,
2109 sizeof (struct GNUNET_PeerIdentity) * get_path_length);
2111 memcpy (&get_result_path[get_path_length], data, data_size);
2113 /* FIXME: Is this correct? */
2114 if (put_path_length != 0)
2116 pp = (struct GNUNET_PeerIdentity *)&get_result_path[1];
2117 memcpy (pp, put_path,sizeof (struct GNUNET_PeerIdentity) * put_path_length);
2120 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2121 &get_result_path[current_path_index - 1]);
2122 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2123 target_friend->pending_count++;
2124 process_friend_queue (target_friend);
2129 * Randomly choose one of your friends (which is not congested and have not crossed
2130 * trail threshold) from the friends_peer map
2131 * @return Friend Randomly chosen friend.
2132 * NULL in case friend peermap is empty, or all the friends are either
2133 * congested or have crossed trail threshold.
2135 static struct FriendInfo *
2136 select_random_friend ()
2138 unsigned int current_size;
2141 struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
2142 struct GNUNET_PeerIdentity key_ret;
2143 struct FriendInfo *friend;
2145 current_size = GNUNET_CONTAINER_multipeermap_size (friend_peermap);
2146 if (0 == current_size)
2149 index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, current_size);
2150 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
2152 for (j = 0; j < index ; j++)
2153 GNUNET_assert (GNUNET_YES ==
2154 GNUNET_CONTAINER_multipeermap_iterator_next (iter, NULL, NULL));
2157 if (j == current_size)
2160 GNUNET_CONTAINER_multipeermap_iterator_destroy (iter);
2161 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
2164 GNUNET_assert (GNUNET_YES ==
2165 GNUNET_CONTAINER_multipeermap_iterator_next (iter,
2167 (const void **)&friend));
2170 if ((TRAILS_THROUGH_FRIEND_THRESHOLD == friend->trails_count) &&
2171 (0 == GNUNET_TIME_absolute_get_remaining (friend->congestion_timestamp).rel_value_us))
2177 } while (j != index);
2179 GNUNET_CONTAINER_multipeermap_iterator_destroy (iter);
2185 * FIXME: pass current_search_finger_index as parameter
2186 * Compute finger_identity to which we want to setup the trail
2187 * @return finger_identity
2190 compute_finger_identity_value ()
2194 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
2195 my_id64 = GNUNET_ntohll (my_id64);
2196 return (my_id64 + (unsigned long) pow (2, current_search_finger_index));
2201 * Compute immediate predecessor identity in the network.
2202 * @return peer identity of immediate predecessor.
2205 compute_predecessor_identity_value ()
2209 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
2210 my_id64 = GNUNET_ntohll (my_id64);
2211 return (my_id64 -1);
2216 * Choose a random friend and start looking for the trail to reach to
2217 * finger identity through this random friend.
2219 * @param cls closure for this task
2220 * @param tc the context under which the task is running
2223 send_find_finger_trail_message (void *cls,
2224 const struct GNUNET_SCHEDULER_TaskContext *tc)
2226 struct FriendInfo *target_friend;
2227 struct GNUNET_TIME_Relative next_send_time;
2228 struct GNUNET_HashCode trail_id;
2229 unsigned int is_predecessor;
2230 uint64_t finger_id_value;
2232 next_send_time.rel_value_us =
2233 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
2234 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
2235 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us);
2236 find_finger_trail_task =
2237 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_finger_trail_message,
2240 target_friend = select_random_friend ();
2241 if (NULL == target_friend)
2246 if (PREDECESSOR_FINGER_ID == current_search_finger_index)
2248 finger_id_value = compute_predecessor_identity_value();
2253 finger_id_value = compute_finger_identity_value();
2257 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
2258 &trail_id, sizeof (trail_id));
2259 GDS_NEIGHBOURS_send_trail_setup (my_identity, finger_id_value,
2260 target_friend->id, target_friend, 0, NULL,
2261 is_predecessor, trail_id, NULL);
2266 * In case there are already maximum number of possible trails to reach to a
2267 * finger, then check if the new trail's length is lesser than any of the
2269 * If yes then replace that old trail by new trail.
2271 * Note: Here we are taking length as a parameter to choose the best possible
2272 * trail, but there could be other parameters also like:
2273 * 1. duration of existence of a trail - older the better.
2274 * 2. if the new trail is completely disjoint than the
2275 * other trails, then may be choosing it is better.
2277 * @param existing_finger
2278 * @param new_finger_trail
2279 * @param new_finger_trail_length
2280 * @param new_finger_trail_id
2283 select_and_replace_trail (struct FingerInfo *existing_finger,
2284 const struct GNUNET_PeerIdentity *new_trail,
2285 unsigned int new_trail_length,
2286 struct GNUNET_HashCode new_trail_id)
2288 struct Trail *trail_list_iterator;
2289 unsigned int largest_trail_length;
2290 unsigned int largest_trail_index;
2291 struct Trail_Element *trail_element;
2294 largest_trail_length = new_trail_length;
2295 largest_trail_index = MAXIMUM_TRAILS_PER_FINGER + 1;
2297 GNUNET_assert (MAXIMUM_TRAILS_PER_FINGER == existing_finger->trails_count);
2299 for (i = 0; i < existing_finger->trails_count; i++)
2301 trail_list_iterator = &existing_finger->trail_list[i];
2302 if (trail_list_iterator->trail_length > largest_trail_length)
2304 largest_trail_length = trail_list_iterator->trail_length;
2305 largest_trail_index = i;
2309 if (largest_trail_index == (MAXIMUM_TRAILS_PER_FINGER + 1))
2311 // tear down new trail: it's not better than the existing ones
2315 /* Send trail teardown message across the replaced trail. */
2316 struct Trail *replace_trail = &existing_finger->trail_list[largest_trail_index];
2317 struct FriendInfo *target_friend =
2318 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2319 &replace_trail->trail_head->peer);
2321 GDS_NEIGHBOURS_send_trail_teardown (my_identity,
2322 existing_finger->finger_identity,
2323 replace_trail->trail_id,
2324 GDS_ROUTING_SRC_TO_DEST, target_friend);
2325 /* Free the trail. */
2326 while (NULL != (trail_element = replace_trail->trail_head))
2328 GNUNET_CONTAINER_DLL_remove (replace_trail->trail_head,
2329 replace_trail->trail_tail, trail_element);
2330 GNUNET_free (trail_element);
2333 /* Add new trial at that location. */
2335 while (i < new_trail_length)
2337 struct Trail_Element *element = GNUNET_new (struct Trail_Element);
2338 element->peer = new_trail[i];
2340 GNUNET_CONTAINER_DLL_insert_tail (replace_trail->trail_head,
2341 replace_trail->trail_tail,
2348 * Check if the new trail to reach to finger is unique or do we already have
2349 * such a trail present for finger.
2350 * @param existing_finger Finger identity
2351 * @param new_trail New trail to reach @a existing_finger
2352 * @param trail_length Total number of peers in new_trail.
2353 * @return #GNUNET_YES if the new trail is unique
2354 * #GNUNET_NO if same trail is already present.
2357 is_new_trail_unique (struct FingerInfo *existing_finger,
2358 const struct GNUNET_PeerIdentity *new_trail,
2359 unsigned int trail_length)
2361 struct Trail *trail_list_iterator;
2362 struct Trail_Element *trail_element;
2365 int trail_unique = GNUNET_NO;
2367 for (i = 0; i < existing_finger->trails_count; i++)
2369 trail_list_iterator = &existing_finger->trail_list[i];
2370 if (trail_list_iterator->trail_length != trail_length)
2372 trail_element = trail_list_iterator->trail_head;
2373 for (j = 0; j < trail_list_iterator->trail_length; j++)
2375 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&new_trail[j],
2376 &trail_element->peer))
2378 trail_unique = GNUNET_YES;
2383 return trail_unique;
2388 * Add a new trail to existing finger.
2389 * @param existing_finger
2390 * @param new_finger_trail
2391 * @param new_finger_trail_length
2392 * @param new_finger_trail_id
2395 add_new_trail (struct FingerInfo *existing_finger,
2396 const struct GNUNET_PeerIdentity *new_trail,
2397 unsigned int new_trail_length,
2398 struct GNUNET_HashCode new_trail_id)
2400 struct Trail *trail_list_iterator;
2401 struct FriendInfo *first_friend;
2404 if (GNUNET_NO == is_new_trail_unique (existing_finger, new_trail,
2410 // FIXME checking trail_head is NOT a valid way to verify an open slot
2411 for (i = 0; existing_finger->trail_list[i].trail_head != NULL; i++)
2412 GNUNET_assert (i < MAXIMUM_TRAILS_PER_FINGER);
2414 trail_list_iterator = &existing_finger->trail_list[i];
2416 if (new_trail_length > 0)
2417 first_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2420 first_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2421 &(existing_finger->finger_identity));
2422 first_friend->trails_count++;
2423 /* FIXME; we removed this field but read fixme. */
2424 //trail_list_iterator->first_friend_trail_count = first_friend->trails_count;
2425 trail_list_iterator->trail_length = new_trail_length;
2427 for (i = 0; i < new_trail_length; i++)
2429 struct Trail_Element *element;
2430 element = GNUNET_new (struct Trail_Element);
2432 element->peer = new_trail[i];
2433 GNUNET_CONTAINER_DLL_insert_tail (trail_list_iterator->trail_head,
2434 trail_list_iterator->trail_tail,
2437 existing_finger->trails_count++;
2442 * Send trail teardown message on all trails associated with finger.
2443 * @param finger_to_be_removed
2446 send_trail_teardown (struct FingerInfo *finger)
2448 struct Trail *trail_list_iterator;
2449 struct FriendInfo *target_friend;
2452 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity, &my_identity)
2453 || (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2454 &finger->finger_identity)))
2457 for (i = 0; i < finger->trails_count; i++)
2459 trail_list_iterator = &finger->trail_list[i];
2460 if (trail_list_iterator->trail_length > 0)
2463 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2464 &trail_list_iterator->trail_head->peer);
2465 // check target_friend
2466 GDS_NEIGHBOURS_send_trail_teardown (my_identity, finger->finger_identity,
2467 trail_list_iterator->trail_id,
2468 GDS_ROUTING_SRC_TO_DEST,
2476 * Decrement the trail count of the first friend to reach the finger
2477 * In case finger is the friend, then decrement its trail count.
2481 decrement_friend_trail_count (struct FingerInfo *finger)
2483 struct Trail *trail_list_iterator;
2484 struct FriendInfo *target_friend;
2487 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
2491 for (i = 0; i < finger->trails_count; i++)
2493 trail_list_iterator = &finger->trail_list[i];
2494 if (trail_list_iterator->trail_length > 0)
2496 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2497 &trail_list_iterator->trail_head->peer);
2500 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2501 &finger->finger_identity);
2503 // check target_friend for NULL
2504 /* FIXME: we have removed first_friend_trail_count field. */
2505 target_friend->trails_count--;
2506 //trail_list_iterator->first_friend_trail_count--;
2513 * Free finger and its trail.
2514 * @param finger Finger to be freed.
2517 free_finger (struct FingerInfo *finger)
2519 struct Trail *trail_list_iterator;
2520 struct Trail_Element *trail_element;
2523 for (i = 0; i < finger->trails_count; i++)
2525 trail_list_iterator = &finger->trail_list[i];
2526 while (NULL != (trail_element = trail_list_iterator->trail_head))
2528 GNUNET_CONTAINER_DLL_remove (trail_list_iterator->trail_head,
2529 trail_list_iterator->trail_tail,
2531 GNUNET_free (trail_element);
2534 GNUNET_free (finger);
2539 * Add a new entry in finger hashmap at finger_map_index
2540 * @param finger_identity Peer Identity of new finger
2541 * @param finger_trail Trail to reach from me to finger (excluding both end points).
2542 * @param finger_trail_length Total number of peers in @a finger_trail.
2543 * @param trail_id Unique identifier of the trail.
2544 * @param finger_map_index Index in finger hashmap.
2545 * @return #GNUNET_OK if new entry is added
2546 * #GNUNET_NO -- FIXME: need to check what value does hahsmap put
2547 * returns on failure.
2550 add_new_entry (struct GNUNET_PeerIdentity finger_identity,
2551 const struct GNUNET_PeerIdentity *finger_trail,
2552 unsigned int finger_trail_length,
2553 struct GNUNET_HashCode trail_id,
2554 unsigned int finger_map_index)
2556 struct FingerInfo *new_entry;
2557 struct FriendInfo *first_trail_hop;
2558 struct Trail *first_trail;
2561 new_entry = GNUNET_new (struct FingerInfo);
2562 new_entry->finger_identity = finger_identity;
2563 new_entry->finger_map_index = finger_map_index;
2564 new_entry->trails_count = 1;
2566 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity))
2568 if (finger_trail_length > 0)
2570 first_trail_hop = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2575 first_trail_hop = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2579 first_trail_hop->trails_count++;
2580 first_trail = &new_entry->trail_list[0];
2581 /* FIXME: We have removed this field. */
2582 //first_trail->first_friend_trail_count = first_trail_hop->trails_count;
2584 while (i < finger_trail_length)
2586 struct Trail_Element *element = GNUNET_new (struct Trail_Element);
2588 element->next = NULL;
2589 element->prev = NULL;
2590 element->peer = finger_trail[i];
2591 GNUNET_CONTAINER_DLL_insert_tail (first_trail->trail_head,
2592 first_trail->trail_tail,
2598 return GNUNET_CONTAINER_multihashmap32_put (finger_hashmap,
2599 new_entry->finger_map_index,
2601 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
2606 * Scan the trail to check if there is any other friend in the trail other than
2607 * first hop. If yes then shortcut the trail, send trail compression message to
2608 * peers which are no longer part of trail and send back the updated trail
2609 * and trail_length to calling function.
2610 * @param finger_identity Finger whose trail we will scan.
2611 * @param finger_trail [in, out] Trail to reach from source to finger,
2612 * @param finger_trail_length Total number of peers in original finger_trail.
2613 * @param finger_trail_id Unique identifier of the finger trail.
2614 * @return updated trail length in case we shortcut the trail, else original
2617 static struct GNUNET_PeerIdentity *
2618 scan_and_compress_trail (struct GNUNET_PeerIdentity finger_identity,
2619 const struct GNUNET_PeerIdentity *trail,
2620 unsigned int trail_length,
2621 struct GNUNET_HashCode trail_id,
2622 int *new_trail_length)
2624 struct FriendInfo *target_friend;
2625 struct GNUNET_PeerIdentity *new_trail;
2628 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity))
2630 *new_trail_length = 0;
2634 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger_identity))
2636 if (trail_length > 0)
2638 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2640 GDS_NEIGHBOURS_send_trail_compression (my_identity, finger_identity,
2641 trail_id, finger_identity,
2643 *new_trail_length = 0;
2648 for (i = trail_length - 1; i > 0; i--)
2650 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, &trail[i]))
2652 struct FriendInfo *target_friend;
2655 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2657 GDS_NEIGHBOURS_send_trail_compression (my_identity, finger_identity,
2662 /* Copy the trail from index i to index trail_length -1 and change
2663 trail length and return */
2664 new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * i);
2665 while (i < trail_length)
2667 memcpy (&new_trail[j], &trail[i], sizeof(struct GNUNET_PeerIdentity));
2671 *new_trail_length = j+1;
2676 *new_trail_length = trail_length;
2677 memcpy (new_trail, new_trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
2683 * FIXME: Ensure that we add trail in succession in the trail list.
2684 * There are no free spots within the trail list.
2685 * Send verify successor message to your successor on all trails to reach
2687 * @param successor My current successor
2690 send_verify_successor_message (struct FingerInfo *successor)
2692 struct Trail *trail_list_iterator;
2693 struct GNUNET_HashCode trail_id;
2694 struct GNUNET_PeerIdentity next_hop;
2695 struct FriendInfo *target_friend;
2696 struct GNUNET_PeerIdentity *trail;
2697 unsigned int trail_length;
2701 for (i = 0; i < successor->trails_count; i++)
2703 trail_list_iterator = &successor->trail_list[i];
2704 GNUNET_assert (NULL != trail_list_iterator->trail_head);
2706 if (trail_list_iterator->trail_length > 0)
2708 struct Trail_Element *element;
2710 trail_length = trail_list_iterator->trail_length;
2711 trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)
2713 element = trail_list_iterator->trail_head;
2714 for (j = 0; j < trail_length; j++, element = element->next)
2715 trail[j] = element->peer;
2716 next_hop = trail_list_iterator->trail_head->peer;
2722 next_hop = successor->finger_identity;
2724 trail_id = trail_list_iterator->trail_id;
2725 GNUNET_assert (NULL != (target_friend =
2726 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop)));
2728 GDS_NEIGHBOURS_send_verify_successor_message (my_identity,
2729 successor->finger_identity,
2730 trail_id, trail, trail_length,
2732 GNUNET_free_non_null (trail);
2738 * FIXME: Is it safe to assume that current_search_finger_index == finger_map_index?
2739 * Update the current search finger index.
2742 update_current_search_finger_index (struct GNUNET_PeerIdentity new_finger_identity)
2744 struct FingerInfo *successor;
2746 successor = GNUNET_CONTAINER_multihashmap32_get (finger_hashmap, 0);
2748 if (0 == current_search_finger_index)
2750 current_search_finger_index = PREDECESSOR_FINGER_ID;
2752 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &new_finger_identity))
2754 send_verify_successor_message (successor);
2757 else if (0 == GNUNET_CRYPTO_cmp_peer_identity (&new_finger_identity,
2758 &(successor->finger_identity)))
2760 current_search_finger_index = 0;
2763 current_search_finger_index = current_search_finger_index - 1;
2767 * FIXME: Is it sage to assume that finger_map_index == current_search_finger_index
2768 * Calculate finger_map_index from initial value that we send in trail setup
2770 * @param ultimate_destination_finger_value Value that we calculated from our
2771 * identity and finger_map_index.
2772 * @param is_predecessor Is the entry for predecessor or not.
2773 * @return finger_map_index which is a value between 0 <= finger_map_index <= 64
2774 * -1, if no valid finger_map_index is found.
2777 get_finger_map_index (uint64_t ultimate_destination_finger_value,
2778 unsigned int is_predecessor)
2781 unsigned int finger_map_index;
2783 finger_map_index = -1;
2784 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
2788 if(1 == (my_id64 - ultimate_destination_finger_value))
2789 finger_map_index = PREDECESSOR_FINGER_ID;
2793 finger_map_index = log (ultimate_destination_finger_value - my_id64);
2796 if ((finger_map_index > PREDECESSOR_FINGER_ID) ||
2797 (finger_map_index == current_search_finger_index))
2798 finger_map_index = -1;
2800 return finger_map_index;
2805 * Check if there is already an entry in finger peermap for given finger map index.
2806 * If yes, then select the closest finger. If new and existing finger are same,
2807 * the check if you can store more trails. If yes then add trail, else keep the best
2808 * trails to reach to the finger. If the new finger is closest, add it.
2809 * Then, update current_search_finger_index.
2810 * @param new_finger_identity Peer Identity of new finger
2811 * @param new_finger_trail Trail to reach the new finger
2812 * @param new_finger_length Total number of peers in @a new_finger_trail.
2813 * @param is_predecessor Is this entry for predecessor in finger_peermap.
2814 * @param new_finger_trail_id Unique identifier of @new_finger_trail.
2815 * @return #GNUNET_YES if the new entry is added
2816 * #GNUNET_NO if new entry is not added, either it was discarded or
2817 * it was same as existing finger at finger map index.
2820 finger_table_add (struct GNUNET_PeerIdentity finger_identity,
2821 const struct GNUNET_PeerIdentity *finger_trail,
2822 unsigned int finger_trail_length,
2823 unsigned int is_predecessor,
2824 uint64_t finger_value,
2825 struct GNUNET_HashCode finger_trail_id)
2827 struct FingerInfo *existing_finger;
2828 struct GNUNET_PeerIdentity *closest_peer;
2829 int updated_finger_trail_length;
2830 struct GNUNET_PeerIdentity *updated_trail;
2831 unsigned int finger_map_index;
2832 unsigned int new_entry_added;
2834 new_entry_added = GNUNET_NO;
2836 finger_map_index = get_finger_map_index (finger_value,
2839 if (-1 == finger_map_index)
2841 GNUNET_break_op (0);
2842 return GNUNET_SYSERR;
2846 scan_and_compress_trail (finger_identity, finger_trail,
2847 finger_trail_length, finger_trail_id,
2848 &updated_finger_trail_length);
2850 existing_finger = GNUNET_CONTAINER_multihashmap32_get (finger_hashmap,
2853 /* No entry present in finger hashmap for given finger map index. */
2854 if (NULL == existing_finger)
2856 add_new_entry (finger_identity, updated_trail, updated_finger_trail_length,
2857 finger_trail_id, finger_map_index);
2858 update_current_search_finger_index (finger_identity);
2862 /* If existing entry and finger identity are not same. */
2863 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity),
2866 closest_peer = select_closest_peer (&existing_finger->finger_identity,
2868 finger_value, finger_map_index);
2870 /* If the new finger is the closest peer. */
2871 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, closest_peer))
2873 GNUNET_assert (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
2876 send_trail_teardown (existing_finger);
2877 decrement_friend_trail_count (existing_finger);
2878 free_finger (existing_finger);
2879 add_new_entry (finger_identity, updated_trail, updated_finger_trail_length,
2880 finger_trail_id, finger_map_index);
2881 new_entry_added = GNUNET_YES;
2886 /* If both new and existing entry are same as my_identity, then do nothing. */
2887 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity),
2893 /* If the existing finger is not a friend. */
2895 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2896 &(existing_finger->finger_identity)))
2898 if (existing_finger->trails_count < MAXIMUM_TRAILS_PER_FINGER)
2899 add_new_trail (existing_finger, updated_trail,
2900 finger_trail_length, finger_trail_id);
2902 select_and_replace_trail (existing_finger, updated_trail,
2903 finger_trail_length, finger_trail_id);
2905 new_entry_added = GNUNET_NO;
2908 update_current_search_finger_index (finger_identity);
2909 return new_entry_added;
2914 * Core handler for P2P put messages.
2915 * @param cls closure
2916 * @param peer sender of the request
2917 * @param message message
2918 * @return #GNUNET_OK to keep the connection open,
2919 * #GNUNET_SYSERR to close it (signal serious error)
2922 handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer,
2923 const struct GNUNET_MessageHeader *message)
2925 struct PeerPutMessage *put;
2926 struct GNUNET_PeerIdentity *put_path;
2927 struct GNUNET_HashCode test_key;
2928 enum GNUNET_DHT_RouteOption options;
2929 struct GNUNET_PeerIdentity best_known_dest;
2930 struct GNUNET_HashCode intermediate_trail_id;
2931 struct GNUNET_PeerIdentity *next_hop;
2935 size_t payload_size;
2938 msize = ntohs (message->size);
2939 if (msize < sizeof (struct PeerPutMessage))
2941 GNUNET_break_op (0);
2945 put = (struct PeerPutMessage *) message;
2946 putlen = ntohl (put->put_path_length);
2949 sizeof (struct PeerPutMessage) +
2950 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
2952 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2954 GNUNET_break_op (0);
2958 best_known_dest = put->best_known_destination;
2959 put_path = (struct GNUNET_PeerIdentity *) &put[1];
2960 payload = &put_path[putlen];
2961 options = ntohl (put->options);
2962 intermediate_trail_id = put->intermediate_trail_id;
2964 payload_size = msize - (sizeof (struct PeerPutMessage) +
2965 putlen * sizeof (struct GNUNET_PeerIdentity));
2967 switch (GNUNET_BLOCK_get_key (GDS_block_context, ntohl (put->block_type),
2968 payload, payload_size, &test_key))
2971 if (0 != memcmp (&test_key, &put->key, sizeof (struct GNUNET_HashCode)))
2973 char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key));
2974 GNUNET_break_op (0);
2975 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2976 "PUT with key `%s' for block with key %s\n",
2977 put_s, GNUNET_h2s_full (&test_key));
2978 GNUNET_free (put_s);
2983 GNUNET_break_op (0);
2986 /* cannot verify, good luck */
2990 if (ntohl (put->block_type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
2992 switch (GNUNET_BLOCK_evaluate (GDS_block_context,
2993 ntohl (put->block_type),
2995 NULL, 0, /* bloom filer */
2996 NULL, 0, /* xquery */
2997 payload, payload_size))
2999 case GNUNET_BLOCK_EVALUATION_OK_MORE:
3000 case GNUNET_BLOCK_EVALUATION_OK_LAST:
3003 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
3004 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
3005 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
3006 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
3007 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
3008 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
3010 GNUNET_break_op (0);
3015 /* extend 'put path' by sender */
3016 struct GNUNET_PeerIdentity pp[putlen + 1];
3017 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
3019 memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity));
3026 memcpy (&key_value, &(put->key), sizeof (uint64_t));
3027 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&best_known_dest, &my_identity)))
3029 next_hop = GDS_ROUTING_get_next_hop (intermediate_trail_id,
3030 GDS_ROUTING_SRC_TO_DEST);
3034 /*FIXME: Here you should use enum GDS_NEIGHBOURS_FINGER_TYPE in place of 0. */
3035 next_hop = find_successor (key_value, &best_known_dest,
3036 &intermediate_trail_id, GDS_FINGER_TYPE_NON_PREDECESSOR);
3039 if (NULL == next_hop)
3041 GNUNET_STATISTICS_update (GDS_stats,
3042 gettext_noop ("# Next hop to forward the packet not found "
3043 "trail setup request, packet dropped."),
3045 return GNUNET_SYSERR;
3048 GDS_CLIENTS_process_put (options,
3049 ntohl (put->block_type),
3050 ntohl (put->hop_count),
3051 ntohl (put->desired_replication_level),
3053 GNUNET_TIME_absolute_ntoh (put->expiration_time),
3058 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, next_hop)) /* I am the final destination */
3060 GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time),
3061 &(put->key),putlen, pp, ntohl (put->block_type),
3062 payload_size, payload);
3067 GDS_NEIGHBOURS_send_put (&put->key,
3068 ntohl (put->block_type),ntohl (put->options),
3069 ntohl (put->desired_replication_level),
3070 &best_known_dest, &intermediate_trail_id, next_hop,
3071 ntohl (put->hop_count), putlen, pp,
3072 GNUNET_TIME_absolute_ntoh (put->expiration_time),
3073 payload, payload_size);
3077 return GNUNET_SYSERR;
3082 * Core handler for p2p get requests.
3084 * @param cls closure
3085 * @param peer sender of the request
3086 * @param message message
3087 * @return #GNUNET_OK to keep the connection open,
3088 * #GNUNET_SYSERR to close it (signal serious error)
3091 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
3092 const struct GNUNET_MessageHeader *message)
3094 struct PeerGetMessage *get;
3095 struct GNUNET_PeerIdentity *get_path;
3096 struct GNUNET_PeerIdentity best_known_dest;
3097 struct GNUNET_HashCode intermediate_trail_id;
3098 struct GNUNET_PeerIdentity *next_hop;
3099 uint32_t get_length;
3103 msize = ntohs (message->size);
3104 if (msize < sizeof (struct PeerGetMessage))
3106 GNUNET_break_op (0);
3110 get = (struct PeerGetMessage *)message;
3111 get_length = ntohl (get->get_path_length);
3112 best_known_dest = get->best_known_destination;
3113 intermediate_trail_id = get->intermediate_trail_id;
3115 get_path = (struct GNUNET_PeerIdentity *)&get[1];
3118 sizeof (struct PeerGetMessage) +
3119 get_length * sizeof (struct GNUNET_PeerIdentity)) ||
3121 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3123 GNUNET_break_op (0);
3127 /* Add sender to get path */
3128 struct GNUNET_PeerIdentity gp[get_length + 1];
3129 memcpy (gp, get_path, get_length * sizeof (struct GNUNET_PeerIdentity));
3130 gp[get_length + 1] = *peer;
3131 get_length = get_length + 1;
3133 memcpy (&key_value, &(get->key), sizeof (uint64_t));
3134 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&best_known_dest, &my_identity)))
3136 next_hop = GDS_ROUTING_get_next_hop (intermediate_trail_id,
3137 GDS_ROUTING_SRC_TO_DEST);
3141 /*FIXME: Here you should use enum GDS_NEIGHBOURS_FINGER_TYPE in place of 0. */
3142 next_hop = find_successor (key_value, &best_known_dest,
3143 &intermediate_trail_id, GDS_FINGER_TYPE_NON_PREDECESSOR);
3146 if (NULL == next_hop)
3148 GNUNET_STATISTICS_update (GDS_stats,
3149 gettext_noop ("# Next hop to forward the packet not found "
3150 "trail setup request, packet dropped."),
3152 return GNUNET_SYSERR;
3154 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, next_hop))
3156 /* I am the destination.*/
3157 struct GNUNET_PeerIdentity final_get_path[get_length+1];
3158 struct GNUNET_PeerIdentity next_hop;
3160 memcpy (final_get_path, gp, get_length * sizeof (struct GNUNET_PeerIdentity));
3161 memcpy (&final_get_path[get_length+1], &my_identity, sizeof (struct GNUNET_PeerIdentity));
3162 get_length = get_length + 1;
3163 memcpy (&next_hop, &final_get_path[get_length-2], sizeof (struct GNUNET_PeerIdentity));
3164 GDS_DATACACHE_handle_get (&(get->key),(get->block_type), NULL, 0, NULL, 0,
3165 get_length, final_get_path,&next_hop, &my_identity);
3171 GDS_NEIGHBOURS_send_get (&(get->key), get->block_type, get->options,
3172 get->desired_replication_level, &best_known_dest,
3173 &intermediate_trail_id, next_hop, 0,
3176 return GNUNET_SYSERR;
3181 * Core handler for get result
3182 * @param cls closure
3183 * @param peer sender of the request
3184 * @param message message
3185 * @return #GNUNET_OK to keep the connection open,
3186 * #GNUNET_SYSERR to close it (signal serious error)
3189 handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer,
3190 const struct GNUNET_MessageHeader *message)
3192 struct PeerGetResultMessage *get_result;
3193 struct GNUNET_PeerIdentity *get_path;
3194 struct GNUNET_PeerIdentity *put_path;
3196 size_t payload_size;
3198 unsigned int getlen;
3199 unsigned int putlen;
3200 int current_path_index;
3202 msize = ntohs (message->size);
3203 if (msize < sizeof (struct PeerGetResultMessage))
3205 GNUNET_break_op (0);
3209 get_result = (struct PeerGetResultMessage *)message;
3210 getlen = ntohl (get_result->get_path_length);
3211 putlen = ntohl (get_result->put_path_length);
3214 sizeof (struct PeerGetResultMessage) +
3215 getlen * sizeof (struct GNUNET_PeerIdentity) +
3216 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
3218 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity) ||
3220 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))))
3222 GNUNET_break_op (0);
3227 get_path = (struct GNUNET_PeerIdentity *) &get_result[1];
3228 payload = &get_path[getlen];
3229 payload_size = msize - (sizeof (struct PeerGetResultMessage) +
3230 getlen * sizeof (struct GNUNET_PeerIdentity));
3233 put_path = &get_path[1];
3237 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &(get_path[0]))))
3239 GDS_CLIENTS_handle_reply (get_result->expiration_time, &(get_result->key),
3240 getlen, get_path, putlen,
3241 put_path, get_result->type, payload_size, payload);
3246 current_path_index = search_my_index (get_path, getlen);
3247 if (GNUNET_SYSERR == current_path_index )
3250 return GNUNET_SYSERR;
3252 GDS_NEIGHBOURS_send_get_result (&(get_result->key), get_result->type,
3253 &get_path[current_path_index - 1],
3254 &(get_result->querying_peer), putlen, put_path,
3255 getlen, get_path, get_result->expiration_time,
3256 payload, payload_size);
3259 return GNUNET_SYSERR;
3263 /* Core handle for PeerTrailSetupMessage.
3264 * @param cls closure
3265 * @param message message
3266 * @param peer peer identity this notification is about
3267 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3270 handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer,
3271 const struct GNUNET_MessageHeader *message)
3273 const struct PeerTrailSetupMessage *trail_setup;
3274 const struct GNUNET_PeerIdentity *trail_peer_list;
3275 struct GNUNET_PeerIdentity local_best_known_destination;
3276 struct GNUNET_PeerIdentity current_destination;
3277 struct GNUNET_PeerIdentity *next_hop;
3278 struct GNUNET_PeerIdentity next_peer;
3279 struct FriendInfo *target_friend;
3280 struct GNUNET_PeerIdentity source;
3281 uint64_t ultimate_destination_finger_value;
3282 struct GNUNET_HashCode new_intermediate_trail_id;
3283 struct GNUNET_HashCode intermediate_trail_id;
3284 struct GNUNET_HashCode trail_id;
3285 unsigned int is_predecessor;
3286 uint32_t trail_length;
3289 msize = ntohs (message->size);
3290 /* There are PeerId's appended to the end of the message! */
3291 if (msize < sizeof (struct PeerTrailSetupMessage))
3293 GNUNET_break_op (0);
3297 trail_setup = (const struct PeerTrailSetupMessage *) message;
3298 trail_length = (msize - sizeof (struct PeerTrailSetupMessage))/
3299 sizeof (struct GNUNET_PeerIdentity);
3300 if ((msize - sizeof (struct PeerTrailSetupMessage)) %
3301 sizeof (struct GNUNET_PeerIdentity) != 0)
3303 GNUNET_break_op (0);
3307 trail_peer_list = (const struct GNUNET_PeerIdentity *)&trail_setup[1];
3308 current_destination = trail_setup->best_known_destination;
3309 trail_id = trail_setup->trail_id;
3310 ultimate_destination_finger_value =
3311 GNUNET_ntohll (trail_setup->ultimate_destination_finger_value);
3312 source = trail_setup->source_peer;
3313 is_predecessor = ntohl (trail_setup->is_predecessor);
3314 intermediate_trail_id = trail_setup->intermediate_trail_id;
3316 if (GNUNET_YES == GDS_ROUTING_threshold_reached())
3318 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
3319 GDS_NEIGHBOURS_send_trail_rejection (source, ultimate_destination_finger_value,
3320 my_identity, is_predecessor,
3321 trail_peer_list, trail_length,
3322 trail_id, target_friend,
3323 CONGESTION_TIMEOUT);
3328 next_hop = find_successor (ultimate_destination_finger_value,
3329 &local_best_known_destination,
3330 &new_intermediate_trail_id, is_predecessor);
3332 /* Are we just a part of a trail towards a finger (current_destination)? */
3333 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, ¤t_destination)))
3335 struct GNUNET_PeerIdentity *closest_peer;
3337 /* Select best successor among one found locally and current_destination.*/
3338 closest_peer = select_closest_peer (&local_best_known_destination,
3339 ¤t_destination,
3340 ultimate_destination_finger_value,
3342 if (0 == GNUNET_CRYPTO_cmp_peer_identity (¤t_destination,
3345 next_hop = GDS_ROUTING_get_next_hop (intermediate_trail_id,
3346 GDS_ROUTING_SRC_TO_DEST);
3347 if (NULL == next_hop) /* FIXME: Here we found next_hop NULL from routing table,
3348 * but we still have a next_hop from find_successor.
3349 * Should we not break and choose that next_hop. */
3351 GNUNET_break_op (0);
3352 return GNUNET_SYSERR;
3355 local_best_known_destination = current_destination;
3356 new_intermediate_trail_id = intermediate_trail_id;
3360 GNUNET_assert (NULL != next_hop);
3362 /* Am I the final destination? */
3363 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (next_hop, &my_identity)))
3365 if (0 == trail_length)
3366 memcpy (&next_peer, &source, sizeof (struct GNUNET_PeerIdentity));
3368 memcpy (&next_peer, &trail_peer_list[trail_length-1], sizeof (struct GNUNET_PeerIdentity));
3370 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer);
3371 GDS_NEIGHBOURS_send_trail_setup_result (source,
3373 target_friend, trail_length,
3375 ultimate_destination_finger_value,
3376 is_predecessor, trail_id);
3380 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
3382 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
3383 peer_list[trail_length] = my_identity;
3384 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3385 GDS_NEIGHBOURS_send_trail_setup (source,
3386 ultimate_destination_finger_value,
3387 local_best_known_destination,
3388 target_friend, trail_length + 1, peer_list,
3389 is_predecessor, trail_id,
3390 &new_intermediate_trail_id);
3396 /* FIXME: here we are calculating my_index and comparing also in this function.
3397 And we are doing it again here in this function. Re factor the code. */
3399 * Check if sender_peer and peer from which we should receive the message are
3400 * same or different.
3401 * @param trail_peer_list List of peers in trail
3402 * @param trail_length Total number of peers in @a trail_peer_list
3403 * @param sender_peer Peer from which we got the message.
3404 * @param finger_identity Finger to which trail is setup. It is not part of trail.
3405 * @return #GNUNET_YES if sender_peer and peer from which we should receive the
3406 * message are different.
3407 * #GNUNET_NO if sender_peer and peer from which we should receive the
3408 * message are different.
3411 is_sender_peer_correct (const struct GNUNET_PeerIdentity *trail_peer_list,
3412 unsigned int trail_length,
3413 const struct GNUNET_PeerIdentity *sender_peer,
3414 struct GNUNET_PeerIdentity finger_identity,
3415 struct GNUNET_PeerIdentity source_peer)
3419 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&source_peer,
3422 if (trail_length > 0)
3424 // source, then trail_length > 0, trail_peer_list[0] != peer
3425 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&trail_peer_list[0],
3431 // source, trail_length == 0, finger != peer
3432 if (0 != GNUNET_CRYPTO_cmp_peer_identity (sender_peer,
3439 my_index = search_my_index (trail_peer_list, trail_length);
3443 // my_index == trail_length -1, finger != peer
3444 if ((trail_length - 1) == my_index)
3446 if (0 != GNUNET_CRYPTO_cmp_peer_identity (sender_peer,
3452 // FIXME: if trail_peer_list[my_index + 1] != peer
3453 if (0 != GNUNET_CRYPTO_cmp_peer_identity (sender_peer,
3454 &trail_peer_list[my_index + 1]))
3463 * Core handle for p2p trail setup result messages.
3465 * @param message message
3466 * @param peer sender of this message.
3467 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3470 handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer,
3471 const struct GNUNET_MessageHeader *message)
3473 const struct PeerTrailSetupResultMessage *trail_result;
3474 const struct GNUNET_PeerIdentity *trail_peer_list;
3475 struct GNUNET_PeerIdentity next_hop;
3476 struct FriendInfo *target_friend;
3477 struct GNUNET_PeerIdentity querying_peer;
3478 struct GNUNET_PeerIdentity finger_identity;
3479 uint32_t trail_length;
3480 uint64_t ulitmate_destination_finger_value;
3481 uint32_t is_predecessor;
3482 struct GNUNET_HashCode trail_id;
3486 msize = ntohs (message->size);
3487 if (msize < sizeof (struct PeerTrailSetupResultMessage))
3489 GNUNET_break_op (0);
3493 trail_result = (const struct PeerTrailSetupResultMessage *) message;
3494 trail_length = (msize - sizeof (struct PeerTrailSetupResultMessage))/
3495 sizeof (struct GNUNET_PeerIdentity);
3496 if ((msize - sizeof (struct PeerTrailSetupResultMessage)) %
3497 sizeof (struct GNUNET_PeerIdentity) != 0)
3499 GNUNET_break_op (0);
3503 is_predecessor = htonl (trail_result->is_predecessor);
3504 querying_peer = trail_result->querying_peer;
3505 finger_identity = trail_result->finger_identity;
3506 trail_id = trail_result->trail_id;
3507 trail_peer_list = (const struct GNUNET_PeerIdentity *) &trail_result[1];
3508 ulitmate_destination_finger_value =
3509 GNUNET_ntohll (trail_result->ulitmate_destination_finger_value);
3510 /* FIXME: here we are calculating my_index and comparing also in this function.
3511 And we are doing it again here in this function. Re factor the code. */
3512 /* Ensure that sender peer is the peer from which we were expecting the message. */
3513 if (GNUNET_NO == is_sender_peer_correct (trail_peer_list,
3515 peer, finger_identity, querying_peer))
3517 GNUNET_break_op (0);
3518 return GNUNET_SYSERR;
3521 /* Am I the one who initiated the query? */
3522 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&querying_peer,
3525 finger_table_add (finger_identity, trail_peer_list,
3526 trail_length, ulitmate_destination_finger_value,
3527 is_predecessor, trail_id);
3531 my_index = search_my_index(trail_peer_list, trail_length);
3535 return GNUNET_SYSERR;
3539 next_hop = trail_result->querying_peer;
3541 next_hop = trail_peer_list[my_index - 1];
3543 /* If the querying_peer is its own finger, then don't add an entry in routing
3544 * table as querying peer will discard the trail.
3546 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->querying_peer),
3547 &(trail_result->finger_identity))))
3549 GDS_ROUTING_add (trail_id, next_hop, *peer);
3552 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3553 GDS_NEIGHBOURS_send_trail_setup_result (querying_peer, finger_identity,
3554 target_friend, trail_length, trail_peer_list,
3556 ulitmate_destination_finger_value,
3564 * @param trail Trail to be inverted
3565 * @param trail_length Total number of peers in the trail.
3566 * @return Updated trail
3568 static struct GNUNET_PeerIdentity *
3569 invert_trail (const struct GNUNET_PeerIdentity *trail,
3570 unsigned int trail_length)
3574 struct GNUNET_PeerIdentity *inverted_trail;
3576 inverted_trail = GNUNET_malloc (sizeof(struct GNUNET_PeerIdentity) *
3579 j = trail_length - 1;
3580 while (i < trail_length)
3582 inverted_trail[i] = trail[j];
3586 return inverted_trail;
3592 * my_current_predecessor != source_peer. get the trail to reach to
3593 * my_current_predecessor and append it to the trail from source to me.
3594 * It can contain duplicate elements. Need to get the correct one.
3595 * In case the source peer of verify successor message is not my successor,
3596 * then construct a trail from source peer to my current predecessor.
3597 * @param my_predecessor my current predecessor.
3598 * @param current_trail Trail from source to me.
3599 * @param current_trail_length Total number of peers in @a current_trail
3600 * @param new_trail_length [out] Total number of peers in updated trail.
3601 * @return Updated trail from source peer to my_predecessor.
3603 static struct GNUNET_PeerIdentity *
3604 trail_source_to_my_predecessor (const struct GNUNET_PeerIdentity *current_trail,
3605 unsigned int current_trail_length,
3606 unsigned int *new_trail_length)
3608 struct GNUNET_PeerIdentity *new_trail;
3609 struct Trail *trail_list_iterator;
3610 struct Trail_Element *trail_iterator;
3611 struct FingerInfo *my_predecessor;
3614 unsigned int shortest_trail_length = 0;
3615 unsigned int trail_index = 0;
3617 my_predecessor = GNUNET_CONTAINER_multihashmap32_get (finger_hashmap,
3618 PREDECESSOR_FINGER_ID);
3620 for (i = 0; i < my_predecessor->trails_count; i++)
3622 trail_list_iterator = &my_predecessor->trail_list[i];
3623 if (trail_list_iterator->trail_length > shortest_trail_length)
3625 shortest_trail_length = trail_list_iterator->trail_length;
3629 *new_trail_length = current_trail_length + shortest_trail_length + 1;
3630 new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) *
3632 memcpy (new_trail, current_trail,
3633 current_trail_length * sizeof (struct GNUNET_PeerIdentity));
3634 new_trail[current_trail_length + 1] = my_identity;
3637 j = current_trail_length + 1;
3638 trail_list_iterator = &my_predecessor->trail_list[trail_index];
3639 trail_iterator = trail_list_iterator->trail_head;
3640 while ( i < shortest_trail_length)
3642 new_trail[j] = trail_iterator->peer;
3645 trail_iterator = trail_iterator->next;
3648 *new_trail_length = j;
3654 * FIMXE: IF you update your predecessor with new finger identity or added
3655 * a new trail, then you should send add_trail message or else the peers
3656 * which are part of the trail to reach to your new predecessor will not
3657 * know its existence.
3658 * Check if we already have an entry for predecessor in our finger hashmap.
3659 * If no, then add new predecessor.
3660 * If yes, then compare new and existing entry. If both are same, and there is
3661 * place to store more trail, then add entry. If both are different then choose
3663 * @param finger Peer which claims to be our predecessor.
3664 * @param trail Trail to reach from @a predecessor to me, NOT including both endpoints
3665 * @param trail_length Total number of peers in @a trail.
3666 * @return #GNUNET_YES if we added the new entry.
3667 * #GNUNET_NO, if new entry is not the closest predecessor or both new
3668 * and existing entry are same.
3670 static struct GNUNET_PeerIdentity
3671 compare_and_update_predecessor (struct GNUNET_PeerIdentity finger_identity,
3672 const struct GNUNET_PeerIdentity *trail,
3673 unsigned int trail_length)
3675 struct FingerInfo *current_predecessor;
3676 struct GNUNET_PeerIdentity *closest_peer;
3677 struct GNUNET_PeerIdentity *inverted_trail;
3678 struct GNUNET_HashCode trail_id;
3679 uint64_t finger_value;
3681 current_predecessor = GNUNET_CONTAINER_multihashmap32_get (finger_hashmap,
3682 PREDECESSOR_FINGER_ID);
3683 inverted_trail = invert_trail (trail, trail_length);
3685 /* No predecessor in finger table. Add the new predecessor. */
3686 if (NULL == current_predecessor)
3688 add_new_entry (finger_identity, inverted_trail, trail_length,
3689 trail_id, PREDECESSOR_FINGER_ID);
3690 return finger_identity;
3693 /* If the new predecessor and current predecessor are not same, then choose
3695 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&finger_identity,
3696 ¤t_predecessor->finger_identity))
3698 finger_value = compute_predecessor_identity_value();
3699 closest_peer = select_closest_peer (¤t_predecessor->finger_identity,
3701 finger_value, PREDECESSOR_FINGER_ID);
3703 /* If the finger is the closest predecessor, then add it in finger table
3704 * and free resources of current_predecessor. */
3705 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, closest_peer))
3707 GNUNET_assert (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
3710 send_trail_teardown (current_predecessor);
3711 decrement_friend_trail_count (current_predecessor);
3712 free_finger (current_predecessor);
3713 add_new_entry (finger_identity, inverted_trail, trail_length,
3714 trail_id, PREDECESSOR_FINGER_ID);
3715 return finger_identity;
3719 /* If both finger and current_predecessor are same as my_identity, then do nothing. */
3720 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, &my_identity))
3721 return current_predecessor->finger_identity;
3723 /* If the current_predecessor is not a friend. */
3725 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3726 ¤t_predecessor->finger_identity))
3728 if (current_predecessor->trails_count < MAXIMUM_TRAILS_PER_FINGER)
3729 add_new_trail (current_predecessor, inverted_trail,
3730 trail_length, trail_id);
3731 //FIXME: here you should send add a new trail as you don't have this trail
3732 // in the routing table.
3734 select_and_replace_trail (current_predecessor, inverted_trail,
3735 trail_length, trail_id);
3736 //FIXME: here you should send add a new trail as you don't have this trail
3737 // in the routing table.
3739 return current_predecessor->finger_identity;
3744 * Core handle for p2p verify successor messages.
3745 * @param cls closure
3746 * @param message message
3747 * @param peer peer identity this notification is about
3748 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3751 handle_dht_p2p_verify_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
3752 const struct GNUNET_MessageHeader *message)
3754 struct PeerVerifySuccessorMessage *vsm;
3755 struct GNUNET_PeerIdentity successor;
3756 struct GNUNET_PeerIdentity source_peer;
3757 struct GNUNET_PeerIdentity *next_hop;
3758 struct FriendInfo *target_friend;
3759 struct GNUNET_HashCode trail_id;
3760 struct GNUNET_PeerIdentity current_predecessor;
3761 struct GNUNET_PeerIdentity *trail;
3762 struct GNUNET_PeerIdentity *new_trail;
3763 unsigned int trail_length;
3764 unsigned int new_trail_length;
3767 msize = ntohs (message->size);
3768 if (msize != sizeof (struct PeerVerifySuccessorMessage))
3770 GNUNET_break_op (0);
3774 vsm = (struct PeerVerifySuccessorMessage *) message;
3775 trail_length = (msize - sizeof (struct PeerVerifySuccessorMessage))/
3776 sizeof (struct GNUNET_PeerIdentity);
3777 if ((msize - sizeof (struct PeerVerifySuccessorMessage)) %
3778 sizeof (struct GNUNET_PeerIdentity) != 0)
3780 GNUNET_break_op (0);
3784 trail = (struct GNUNET_PeerIdentity *)&vsm[1];
3785 source_peer = vsm->source_peer;
3786 successor = vsm->successor;
3787 trail_id = vsm->trail_id;
3789 /* I am not the successor of source_peer. Pass the message to next_hop on
3791 if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&successor, &my_identity)))
3793 next_hop = GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST);
3794 if (NULL == next_hop)
3797 return GNUNET_SYSERR;
3799 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3800 GDS_NEIGHBOURS_send_verify_successor_message (source_peer, successor,
3801 trail_id, trail, trail_length,
3806 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
3807 current_predecessor = compare_and_update_predecessor (source_peer,
3808 trail, trail_length);
3809 /* source_peer is my current_predecessor. */
3810 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (¤t_predecessor, &source_peer)))
3812 /* Here we don't need to pass the trail as it is of new use. We can pass
3813 NULL and trail length = 0. */
3815 new_trail_length = 0;
3819 new_trail = trail_source_to_my_predecessor (trail, trail_length,
3822 GDS_NEIGHBOURS_send_verify_successor_result (source_peer, my_identity,
3823 current_predecessor, trail_id,
3824 new_trail, new_trail_length,
3825 GDS_ROUTING_DEST_TO_SRC,
3832 * Here you may or may not be the predecessor. If you are then also while adding
3833 * you have to check and if not then notify new successor. But again the trail
3834 * may be a problem here.
3835 * FIXME: I will keep the logic to remove the old trail to reach from me to
3836 * my old successor here and move adding a new trail from me to new successor to notify
3837 * new successor. And in case if the new successor also take it as predecessor
3838 * then call add_trail.
3839 * Core handle for p2p verify successor result messages.
3840 * @param cls closure
3841 * @param message message
3842 * @param peer peer identity this notification is about
3843 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3846 handle_dht_p2p_verify_successor_result(void *cls, const struct GNUNET_PeerIdentity *peer,
3847 const struct GNUNET_MessageHeader *message)
3849 struct PeerVerifySuccessorResultMessage *vsrm;
3850 enum GDS_ROUTING_trail_direction trail_direction;
3851 struct GNUNET_HashCode trail_id;
3852 unsigned int new_trail_length;
3853 struct GNUNET_PeerIdentity *new_trail;
3854 struct GNUNET_PeerIdentity querying_peer;
3855 struct GNUNET_PeerIdentity current_predecessor;
3856 //struct GNUNET_PeerIdentity old_successor;
3857 struct GNUNET_PeerIdentity *next_hop;
3858 struct FriendInfo *target_friend;
3861 msize = ntohs (message->size);
3862 if (msize != sizeof (struct PeerVerifySuccessorResultMessage))
3864 GNUNET_break_op (0);
3867 vsrm = (struct PeerVerifySuccessorResultMessage *) message;
3868 new_trail_length = (msize - sizeof (struct PeerTrailSetupMessage))/
3869 sizeof (struct GNUNET_PeerIdentity);
3870 if ((msize - sizeof (struct PeerTrailSetupMessage)) %
3871 sizeof (struct GNUNET_PeerIdentity) != 0)
3873 GNUNET_break_op (0);
3876 trail_direction = ntohl (vsrm->trail_direction);
3877 trail_id = vsrm->trail_id;
3879 new_trail = (struct GNUNET_PeerIdentity *) &vsrm[1];
3880 querying_peer = vsrm->querying_peer;
3881 current_predecessor = vsrm->current_predecessor;
3882 //old_successor = vsrm->source_successor;
3884 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&querying_peer, &my_identity)))
3887 //Here I am the final quering peer and its verify successor result.
3888 // now I know it is for successor and now I don't have any finger_map_index
3889 // as parameter in finger_table_add.
3890 // BIG FIX HOW TO ADAPT IT FOR change in finger_table_add
3891 struct GNUNET_HashCode new_finger_trail_id;
3892 /* FIXME: generate a new trail id. */
3893 if (GNUNET_YES == finger_table_add (my_new_successor,
3896 PREDECESSOR_FINGER_ID, new_finger_trail_id))
3898 if (new_trail_length > 0)
3899 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3902 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3904 GDS_NEIGHBOURS_send_trail_teardown (my_identity, old_successor, trail_id,
3905 GDS_ROUTING_SRC_TO_DEST, target_friend);
3906 GDS_NEIGHBOURS_send_notify_new_successor (my_identity, my_new_successor,
3909 new_finger_trail_id, target_friend);
3915 GNUNET_assert (NULL != (next_hop =
3916 GDS_ROUTING_get_next_hop (trail_id, trail_direction)));
3917 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3918 GDS_NEIGHBOURS_send_verify_successor_result (querying_peer,
3919 vsrm->source_successor,
3920 current_predecessor, trail_id,
3923 trail_direction, target_friend);
3929 * FIXME: here before adding the peer you again have to call to check
3930 * if its correct predecessor or not.
3931 * Core handle for p2p notify new successor messages.
3932 * @param cls closure
3933 * @param message message
3934 * @param peer peer identity this notification is about
3935 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3938 handle_dht_p2p_notify_new_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
3939 const struct GNUNET_MessageHeader *message)
3941 struct PeerNotifyNewSuccessorMessage *nsm;
3942 struct GNUNET_PeerIdentity *trail;
3943 struct GNUNET_PeerIdentity source;
3944 struct GNUNET_PeerIdentity new_successor;
3945 struct FriendInfo *target_friend;
3946 struct GNUNET_PeerIdentity closest_successor;
3947 struct GNUNET_HashCode trail_id;
3948 unsigned int my_index;
3949 struct GNUNET_PeerIdentity next_hop;
3951 uint32_t trail_length;
3953 msize = ntohs (message->size);
3954 if (msize != sizeof (struct PeerNotifyNewSuccessorMessage))
3956 GNUNET_break_op (0);
3960 nsm = (struct PeerNotifyNewSuccessorMessage *) message;
3961 trail_length = (msize - sizeof (struct PeerNotifyNewSuccessorMessage))/
3962 sizeof (struct GNUNET_PeerIdentity);
3963 if ((msize - sizeof (struct PeerTrailRejectionMessage)) %
3964 sizeof (struct GNUNET_PeerIdentity) != 0)
3966 GNUNET_break_op (0);
3970 if ((msize < sizeof (struct PeerNotifyNewSuccessorMessage) +
3971 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3973 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3975 GNUNET_break_op (0);
3979 trail = (struct GNUNET_PeerIdentity *) &nsm[1];
3980 source = nsm->source_peer;
3981 new_successor = nsm->new_successor;
3982 trail_id = nsm->trail_id;
3984 /* I am the new_successor to source_peer. */
3985 if ( 0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &new_successor))
3987 closest_successor = compare_and_update_predecessor (source, trail, trail_length);
3988 /* If the source peer is my new predecessor, then add trail in the
3989 routing table of all the peers which are part of the trail to reach from
3990 me to source, NOT including endpoints.
3991 FIXME: In case we have same predecessor but we added just a new trail, then
3992 we are not sending add a new trail message. Need to update this. */
3993 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&closest_successor, &source))
3995 struct GNUNET_HashCode new_trail_id;
3996 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3998 GDS_NEIGHBOURS_send_add_trail (my_identity, source, new_trail_id,
3999 trail, trail_length, target_friend);
4004 my_index = search_my_index (trail, trail_length);
4007 GNUNET_break_op (0);
4008 return GNUNET_SYSERR;
4010 if (trail_length == my_index)
4011 next_hop = new_successor;
4013 next_hop = trail[my_index + 1];
4014 GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, *peer, next_hop));
4015 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
4016 GDS_NEIGHBOURS_send_notify_new_successor (source, new_successor, trail,
4018 trail_id, target_friend);
4024 * FIXME: Here you should keep the trail id with you.
4025 * Core handler for P2P trail rejection message
4026 * @param cls closure
4027 * @param message message
4028 * @param peer peer identity this notification is about
4029 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4032 handle_dht_p2p_trail_rejection(void *cls, const struct GNUNET_PeerIdentity *peer,
4033 const struct GNUNET_MessageHeader *message)
4035 struct PeerTrailRejectionMessage *trail_rejection;
4036 unsigned int trail_length;
4037 struct GNUNET_PeerIdentity *trail_peer_list;
4038 struct FriendInfo *target_friend;
4039 struct GNUNET_TIME_Relative congestion_timeout;
4040 struct GNUNET_HashCode trail_id;
4041 struct GNUNET_PeerIdentity next_destination;
4042 struct GNUNET_HashCode new_intermediate_trail_id;
4043 struct GNUNET_PeerIdentity next_peer;
4044 struct GNUNET_PeerIdentity source;
4045 struct GNUNET_PeerIdentity *next_hop;
4046 uint64_t ultimate_destination_finger_value;
4047 unsigned int is_predecessor;
4050 msize = ntohs (message->size);
4051 if (msize != sizeof (struct PeerTrailRejectionMessage))
4053 GNUNET_break_op (0);
4057 trail_rejection = (struct PeerTrailRejectionMessage *) message;
4058 trail_length = (msize - sizeof (struct PeerTrailRejectionMessage))/
4059 sizeof (struct GNUNET_PeerIdentity);
4060 if ((msize - sizeof (struct PeerTrailRejectionMessage)) %
4061 sizeof (struct GNUNET_PeerIdentity) != 0)
4063 GNUNET_break_op (0);
4067 trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_rejection[1];
4068 is_predecessor = ntohl (trail_rejection->is_predecessor);
4069 congestion_timeout = trail_rejection->congestion_time;
4070 source = trail_rejection->source_peer;
4071 trail_id = trail_rejection->trail_id;
4072 ultimate_destination_finger_value =
4073 trail_rejection->ultimate_destination_finger_value;
4075 /* First set the congestion time of the friend that sent you this message. */
4076 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
4077 target_friend->congestion_timestamp = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(),
4078 congestion_timeout);
4080 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &source)))
4085 /* If I am congested then pass this message to peer before me in trail. */
4086 if(GNUNET_YES == GDS_ROUTING_threshold_reached())
4088 struct GNUNET_PeerIdentity *new_trail;
4089 unsigned int new_trail_length;
4091 if (trail_length == 1)
4094 new_trail_length = 0;
4099 next_hop = &trail_peer_list[trail_length - 2];
4100 /* Remove myself from the trail. */
4101 new_trail_length = trail_length -1;
4102 new_trail = GNUNET_malloc (new_trail_length * sizeof (struct GNUNET_PeerIdentity));
4103 memcpy (new_trail, trail_peer_list, new_trail_length * sizeof (struct GNUNET_PeerIdentity));
4106 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
4107 GDS_NEIGHBOURS_send_trail_rejection (source,
4108 ultimate_destination_finger_value,
4109 my_identity, is_predecessor,
4110 new_trail,new_trail_length,trail_id,
4111 target_friend, CONGESTION_TIMEOUT);
4115 /* Look for next_hop to pass the trail setup message */
4116 next_hop = find_successor (ultimate_destination_finger_value,
4118 &new_intermediate_trail_id,
4121 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (next_hop, &my_identity)))/* This means I am the final destination */
4123 if (0 == trail_length)
4126 next_peer = trail_peer_list[trail_length-1];
4128 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer);
4129 GDS_NEIGHBOURS_send_trail_setup_result (source,
4131 target_friend, trail_length,
4134 ultimate_destination_finger_value,
4139 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
4141 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
4142 peer_list[trail_length] = my_identity;
4144 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
4145 GDS_NEIGHBOURS_send_trail_setup (source,
4146 ultimate_destination_finger_value,
4148 target_friend, trail_length + 1, peer_list,
4149 is_predecessor, trail_id,
4150 &new_intermediate_trail_id);
4157 * Core handle for p2p trail tear down messages.
4158 * @param cls closure
4159 * @param message message
4160 * @param peer peer identity this notification is about
4161 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4164 handle_dht_p2p_trail_compression (void *cls, const struct GNUNET_PeerIdentity *peer,
4165 const struct GNUNET_MessageHeader *message)
4167 struct PeerTrailCompressionMessage *trail_compression;
4168 struct GNUNET_PeerIdentity *next_hop;
4169 struct GNUNET_HashCode trail_id;
4170 struct FriendInfo *target_friend;
4173 msize = ntohs (message->size);
4174 if (msize != sizeof (struct PeerTrailCompressionMessage))
4176 GNUNET_break_op (0);
4180 trail_compression = (struct PeerTrailCompressionMessage *) message;
4181 trail_id = trail_compression->trail_id;
4183 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_compression->new_first_friend),
4186 if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&(trail_compression->destination_peer),
4189 GDS_ROUTING_update_trail_prev_hop (trail_id,
4190 trail_compression->source_peer);
4195 next_hop = GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST);
4196 if (NULL == next_hop)
4198 GNUNET_break (0); /*FIXME: How to handle this case. */
4201 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id));
4202 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
4203 GDS_NEIGHBOURS_send_trail_compression (trail_compression->source_peer,
4204 trail_compression->destination_peer,
4206 trail_compression->new_first_friend,
4213 * Core handler for trail teardown message.
4214 * @param cls closure
4215 * @param message message
4216 * @param peer peer identity this notification is about
4217 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4220 handle_dht_p2p_trail_teardown (void *cls, const struct GNUNET_PeerIdentity *peer,
4221 const struct GNUNET_MessageHeader *message)
4223 struct PeerTrailTearDownMessage *trail_teardown;
4224 struct GNUNET_HashCode trail_id;
4225 enum GDS_ROUTING_trail_direction trail_direction;
4228 msize = ntohs (message->size);
4229 if (msize != sizeof (struct PeerTrailTearDownMessage))
4231 GNUNET_break_op (0);
4235 trail_teardown = (struct PeerTrailTearDownMessage *) message;
4236 trail_direction = ntohl (trail_teardown->trail_direction);
4237 trail_id = trail_teardown->TRAIL_ID;
4239 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
4240 &trail_teardown->destination_peer))
4242 struct GNUNET_PeerIdentity *next_hop;
4243 struct FriendInfo *target_friend;
4245 next_hop = GDS_ROUTING_get_next_hop (trail_id, trail_direction);
4246 if (NULL == next_hop)
4249 return GNUNET_SYSERR;
4252 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4254 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id));
4255 GDS_NEIGHBOURS_send_trail_teardown (trail_teardown->source_peer,
4256 trail_teardown->destination_peer,
4257 trail_id, trail_direction,
4265 * Fixme: this function is called only in case in notify new successor, the new
4266 * successor wants to add the source of the peer as its predecessor. Identify
4267 * if there is any other use case where it is required and if yes then adapt the
4269 * Core handle for p2p add trail message.
4270 * @param cls closure
4271 * @param message message
4272 * @param peer peer identity this notification is about
4273 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4276 handle_dht_p2p_add_trail (void *cls, const struct GNUNET_PeerIdentity *peer,
4277 const struct GNUNET_MessageHeader *message)
4279 struct PeerAddTrailMessage *add_trail;
4280 struct GNUNET_PeerIdentity *trail;
4281 struct GNUNET_HashCode trail_id;
4282 struct GNUNET_PeerIdentity destination_peer;
4283 struct GNUNET_PeerIdentity source_peer;
4284 struct GNUNET_PeerIdentity next_hop;
4285 unsigned int trail_length;
4286 unsigned int my_index;
4289 msize = ntohs (message->size);
4290 if (msize != sizeof (struct PeerAddTrailMessage))
4292 GNUNET_break_op (0);
4296 add_trail = (struct PeerAddTrailMessage *) message;
4297 trail_length = (msize - sizeof (struct PeerAddTrailMessage))/
4298 sizeof (struct GNUNET_PeerIdentity);
4299 if ((msize - sizeof (struct PeerAddTrailMessage)) %
4300 sizeof (struct GNUNET_PeerIdentity) != 0)
4302 GNUNET_break_op (0);
4306 if ((msize < sizeof (struct PeerAddTrailMessage) +
4307 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
4309 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
4311 GNUNET_break_op (0);
4315 trail = (struct GNUNET_PeerIdentity *)&add_trail[1];
4316 destination_peer = add_trail->destination_peer;
4317 source_peer = add_trail->source_peer;
4318 trail_id = add_trail->trail_id;
4320 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
4323 struct FriendInfo *target_friend;
4325 my_index = search_my_index (trail, trail_length);
4326 if (GNUNET_SYSERR == my_index)
4328 GNUNET_break_op (0);
4329 return GNUNET_SYSERR;
4333 next_hop = source_peer;
4335 next_hop = trail[trail_length - 1];
4337 GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, next_hop, *peer));
4338 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
4339 GDS_NEIGHBOURS_send_add_trail (source_peer, destination_peer, trail_id,
4340 trail, trail_length, target_friend);
4347 *FIXME; call send_trail_teardown_message on all the trails of the finger that
4348 * you remove. Also you don't need to decerement friend trail count as that
4349 * friend is removed. But you can not send trail teardown message as the friend
4350 * is disconnected. then you don't have any next_hop. and in case there are
4351 * multiple trails. and friend is the first trail then you remove only the trail.
4352 * Iterate over finger_hashmap, and remove entries if finger is the disconnected
4353 * peer or if disconnected peer is the first friend in the trail to reach the
4355 * @param cls closure
4356 * @param key current public key
4357 * @param value value in the hash map
4358 * @return #GNUNET_YES if we should continue to
4360 * #GNUNET_NO if not.
4363 remove_matching_finger (void *cls,
4367 struct FingerInfo *remove_finger = value;
4368 const struct GNUNET_PeerIdentity *disconnected_peer = cls;
4369 struct Trail *trail_list;
4372 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&remove_finger->finger_identity,
4375 GNUNET_assert (GNUNET_YES ==
4376 GNUNET_CONTAINER_multihashmap32_remove (finger_hashmap,
4379 free_finger (remove_finger);
4383 for (i = 0; i< remove_finger->trails_count; i++)
4385 trail_list = &remove_finger->trail_list[i];
4386 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&trail_list->trail_head->peer,
4389 GNUNET_assert (GNUNET_YES ==
4390 GNUNET_CONTAINER_multihashmap32_remove (finger_hashmap,
4393 free_finger (remove_finger);
4402 * Method called whenever a peer disconnects.
4404 * @param cls closure
4405 * @param peer peer identity this notification is about
4408 handle_core_disconnect (void *cls,
4409 const struct GNUNET_PeerIdentity *peer)
4411 struct FriendInfo *remove_friend;
4413 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
4417 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
4419 if (NULL == remove_friend)
4425 GNUNET_assert (GNUNET_SYSERR !=
4426 GNUNET_CONTAINER_multihashmap32_iterate (finger_hashmap,
4427 &remove_matching_finger,
4429 GDS_ROUTING_remove_trail_by_peer (peer);
4430 GNUNET_assert (GNUNET_YES ==
4431 GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
4435 if (0 != GNUNET_CONTAINER_multipeermap_size (friend_peermap))
4438 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
4440 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
4441 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
4449 * Method called whenever a peer connects.
4451 * @param cls closure
4452 * @param peer_identity peer identity this notification is about
4455 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity)
4457 struct FriendInfo *friend;
4459 /* Check for connect to self message */
4460 if (0 == memcmp (&my_identity, peer_identity, sizeof (struct GNUNET_PeerIdentity)))
4463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to %s\n", GNUNET_i2s (peer_identity));
4465 /* If peer already exists in our friend_peermap, then exit. */
4466 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (friend_peermap, peer_identity))
4472 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
4475 friend = GNUNET_new (struct FriendInfo);
4476 friend->id = *peer_identity;
4478 GNUNET_assert (GNUNET_OK ==
4479 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
4480 peer_identity, friend,
4481 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
4483 /* got a first connection, good time to start with FIND FINGER TRAIL requests... */
4484 if (GNUNET_SCHEDULER_NO_TASK == find_finger_trail_task)
4485 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
4490 * To be called on core init/fail.
4492 * @param cls service closure
4493 * @param identity the public identity of this peer
4496 core_init (void *cls,
4497 const struct GNUNET_PeerIdentity *identity)
4499 my_identity = *identity;
4504 * Initialize neighbours subsystem.
4505 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4508 GDS_NEIGHBOURS_init (void)
4510 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
4511 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0},
4512 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0},
4513 {&handle_dht_p2p_get_result, GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT, 0},
4514 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP, 0},
4515 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT, 0},
4516 {&handle_dht_p2p_verify_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR, 0},
4517 {&handle_dht_p2p_verify_successor_result, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT, 0},
4518 {&handle_dht_p2p_notify_new_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR, 0},
4519 {&handle_dht_p2p_trail_rejection, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION, 0},
4520 {&handle_dht_p2p_trail_compression, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_COMPRESSION, 0},
4521 {&handle_dht_p2p_trail_teardown, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_TEARDOWN, 0},
4522 {&handle_dht_p2p_add_trail, GNUNET_MESSAGE_TYPE_DHT_P2P_ADD_TRAIL, 0},
4527 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
4528 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
4529 GNUNET_NO, core_handlers);
4530 if (NULL == core_api)
4531 return GNUNET_SYSERR;
4533 friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
4534 finger_hashmap = GNUNET_CONTAINER_multihashmap32_create (MAX_FINGERS * 4/3);
4540 * Shutdown neighbours subsystem.
4543 GDS_NEIGHBOURS_done (void)
4545 if (NULL == core_api)
4548 GNUNET_CORE_disconnect (core_api);
4551 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
4552 GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
4553 friend_peermap = NULL;
4555 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (finger_hashmap));
4556 GNUNET_CONTAINER_multihashmap32_destroy (finger_hashmap);
4557 finger_hashmap = NULL;
4559 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
4562 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
4563 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
4571 * @return my identity
4573 struct GNUNET_PeerIdentity
4574 GDS_NEIGHBOURS_get_my_id (void)