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 1. to randomly choose one of the routes in case there are multiple
49 routes to reach to the finger.
50 2. Structure alignment.
51 3. In put, we don't have anything like put result. so we are not adding anything
53 4. Maintain a list of trails --> struct Trail *all_trails_head
54 * struct Trail *all_trails_tail. How do I keep it as an array and not as a list??
55 * First will complete the logic everywhere and then make this change.
56 5. At some places you use memcpy and at some places =, use uniformly.
57 6. I have removed compare_and_update_predecessor from handle_dht_p2p_Trail_setup
58 * (refer to google docs for reason).
59 7. when to use GNUNET_ntohll and when to use ntohl.
60 8. everywhere check if you should use GNUNET_htonll for key value which is 64 bit
61 * right now you are doing memcpy which does not seem correct.
65 * Maximum possible fingers of a peer.
67 #define MAX_FINGERS 66
70 * Maximum allowed number of pending messages per friend peer.
72 #define MAXIMUM_PENDING_PER_FRIEND 64
75 * How long to wait before sending another find finger trail request
77 #define DHT_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
80 * How long at most to wait for transmission of a request to another peer?
82 #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
85 * How long will I remain congested?
87 #define CONGESTION_TIMEOUT GNUNET_TIME_relative_get_minute_()
91 * Maximum number of trails stored per finger.
93 #define TRAILS_COUNT 2
96 * Used to distinguish put/get request use of find_successor() from others
98 #define PUT_GET_REQUEST 68
100 GNUNET_NETWORK_STRUCT_BEGIN
105 struct PeerPutMessage
108 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
110 struct GNUNET_MessageHeader header;
115 uint32_t options GNUNET_PACKED;
120 uint32_t block_type GNUNET_PACKED;
125 uint32_t hop_count GNUNET_PACKED;
128 * Replication level for this message
129 * In the current implementation, this value is not used.
131 uint32_t desired_replication_level GNUNET_PACKED;
134 * Length of the PUT path that follows (if tracked).
136 uint32_t put_path_length GNUNET_PACKED;
139 * Current destination to which this message is forwarded.
141 struct GNUNET_PeerIdentity current_destination;
144 * Peer whose finger is current_destination.
146 struct GNUNET_PeerIdentity current_source;
149 * When does the content expire?
151 struct GNUNET_TIME_AbsoluteNBO expiration_time;
154 * The key to store the value under.
156 struct GNUNET_HashCode key GNUNET_PACKED;
158 /* put path (if tracked) */
168 struct PeerGetResultMessage
171 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT
173 struct GNUNET_MessageHeader header;
176 * The type for the data.
178 uint32_t type GNUNET_PACKED;
181 * Peer which will receive the get result message.
183 struct GNUNET_PeerIdentity source_peer;
186 * Number of peers recorded in the outgoing path from source to the
187 * stored location of this message.
189 uint32_t put_path_length GNUNET_PACKED;
192 * Length of the GET path that follows (if tracked).
194 uint32_t get_path_length GNUNET_PACKED;
197 * When does the content expire?
199 struct GNUNET_TIME_Absolute expiration_time;
202 * The key of the corresponding GET request.
204 struct GNUNET_HashCode key;
206 /* put path (if tracked) */
208 /* get path (if tracked) */
218 struct PeerGetMessage
221 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET
223 struct GNUNET_MessageHeader header;
228 uint32_t options GNUNET_PACKED;
231 * Desired content type.
233 uint32_t block_type GNUNET_PACKED;
238 uint32_t hop_count GNUNET_PACKED;
241 * Desired replication level for this request.
242 * In the current implementation, this value is not used.
244 uint32_t desired_replication_level GNUNET_PACKED;
247 * Total number of peers in get path.
249 unsigned int get_path_length;
252 * Peer which is an intermediate destination.
254 struct GNUNET_PeerIdentity current_destination;
257 * Source for which current_destination is the finger.
259 struct GNUNET_PeerIdentity current_source;
262 * The key we are looking for.
264 struct GNUNET_HashCode key;
272 * P2P Trail setup message
274 struct PeerTrailSetupMessage
278 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP
280 struct GNUNET_MessageHeader header;
283 * Successor of this finger value will be our finger peer.
285 uint64_t destination_finger;
288 * Source peer which wants to setup the trail to one of its finger.
290 struct GNUNET_PeerIdentity source_peer;
293 * Peer to which this packet is forwarded.
295 struct GNUNET_PeerIdentity current_destination;
298 * In case the packet is forwarded to an intermediate finger, then
299 * current_source contains the peer id whose finger is the intermediate
300 * finger. In case the packet is forwarded to a friend, then it is NULL.
301 * FIXME: check the usage of current_source and fix this comment.
303 struct GNUNET_PeerIdentity current_source;
306 * Index into finger peer map, in Network Byte Order.
308 uint32_t finger_map_index;
311 * Number of entries in trail list, in Network Byte Order.
313 uint32_t trail_length GNUNET_PACKED;
315 /* Trail formed in the process. */
320 * P2P Trail Setup Result message
322 struct PeerTrailSetupResultMessage
326 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT
328 struct GNUNET_MessageHeader header;
331 * Finger to which we have found the path.
333 struct GNUNET_PeerIdentity finger_identity;
336 * Peer which was looking for the trail to finger.
338 struct GNUNET_PeerIdentity destination_peer;
341 * Index into finger peer map in NBO.
343 uint32_t finger_map_index;
346 * Number of entries in trail list in NBO.
348 uint32_t trail_length GNUNET_PACKED;
350 /* Trail from destination_peer to finger_identity */
356 * P2P Trail Rejection Message.
358 struct PeerTrailRejectionMessage
361 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION
363 struct GNUNET_MessageHeader header;
366 * Source peer which wants to set up the trail.
368 struct GNUNET_PeerIdentity source_peer;
371 * Peer which sent trail rejection message.
373 struct GNUNET_PeerIdentity congested_peer;
376 * Peer identity which will be successor to this value will be finger of
379 uint64_t finger_identity_value;
382 * Index in finger peer map of source peer.
384 uint32_t finger_map_index;
387 * Total number of peers in the trail.
389 uint32_t trail_length;
392 * Relative time for which congested_peer will remain congested.
394 struct GNUNET_TIME_Relative congestion_time;
396 /* Trail_list from source_peer to peer which sent the message for trail setup
397 * to congested peer.*/
402 * P2P Verify Successor message.
404 struct PeerVerifySuccessorMessage
408 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR
410 struct GNUNET_MessageHeader header;
413 * Source peer which wants to verify its successor.
415 struct GNUNET_PeerIdentity source_peer;
418 * My current successor.
420 struct GNUNET_PeerIdentity successor;
423 * Total number of peers in trail to current successor.
425 uint32_t trail_length;
427 /* Trail to reach to from source_peer to successor. */
432 * P2P Verify Successor Result message.
434 struct PeerVerifySuccessorResultMessage
438 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT
440 struct GNUNET_MessageHeader header;
443 * Destination peer which sent the request to verify its successor.
445 struct GNUNET_PeerIdentity destination_peer;
448 * Successor to which PeerVerifySuccessorMessage was sent.
450 struct GNUNET_PeerIdentity source_successor;
453 * source_successor's predecessor
455 struct GNUNET_PeerIdentity my_predecessor;
458 * Total number of peers in trail.
460 uint32_t trail_length;
462 /* Trail to reach from destination_peer to its correct successor.
463 * If source_successor is not destination peer, then trail is from destination_peer
465 * If source_successor is destination peer, then trail is from destination_peer
466 * to source_successor. */
471 * P2P Notify New Successor message.
473 struct PeerNotifyNewSuccessorMessage
476 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR
478 struct GNUNET_MessageHeader header;
481 * Source peer which wants to notify its new successor.
483 struct GNUNET_PeerIdentity source_peer;
486 * Old successor of source peer.
488 struct GNUNET_PeerIdentity old_successor;
491 * New successor identity.
493 struct GNUNET_PeerIdentity destination_peer;
496 * Number of peers in trail from source_peer to new successor.
498 uint32_t trail_length;
500 /* Trail to from source_peer to destination_peer. */
503 struct PeerTrailTearDownMessage
506 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_TEARDOWN
508 struct GNUNET_MessageHeader header;
511 * Source peer of this trail.
513 struct GNUNET_PeerIdentity source_peer;
516 * Destination peer of this trail.
518 struct GNUNET_PeerIdentity destination_peer;
521 * Trail from source_peer to destination_peer compressed such that
522 * new_first_friend is the first hop in the trail from source to
525 struct GNUNET_PeerIdentity new_first_friend;
527 * Number of peers in trail from source_peer to new first friend.
529 uint32_t trail_length;
531 /* Trail from source_peer to new first friend. */
535 struct PeerAddTrailMessage
538 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_ADD_TRAIL
540 struct GNUNET_MessageHeader header;
543 * Source peer of the routing trail.
545 struct GNUNET_PeerIdentity source_peer;
548 * Destination peer of the routing trail.
550 struct GNUNET_PeerIdentity destination_peer;
553 * Total number of peers from source peer to destination peer.
555 unsigned int trail_length;
557 /* Trail from source peer to destination peer. */
561 GNUNET_NETWORK_STRUCT_END
565 * Linked list of messages to send to a particular other peer.
567 struct P2PPendingMessage
570 * Pointer to next item in the list
572 struct P2PPendingMessage *next;
575 * Pointer to previous item in the list
577 struct P2PPendingMessage *prev;
580 * Message importance level. FIXME: used? useful?
582 unsigned int importance;
585 * When does this message time out?
587 struct GNUNET_TIME_Absolute timeout;
590 * Actual message to be sent, allocated at the end of the struct:
591 * // msg = (cast) &pm[1];
592 * // memcpy (&pm[1], data, len);
594 const struct GNUNET_MessageHeader *msg;
600 * Linked List of peers which are part of trail to reach a particular Finger.
605 * Pointer to next item in the list
607 struct TrailPeerList *next;
610 * Pointer to previous item in the list
612 struct TrailPeerList *prev;
615 * An element in this trail list
617 struct GNUNET_PeerIdentity peer;
623 * FIXME: for congested peer just define a relative time as #define.
624 * Entry in friend_peermap.
631 struct GNUNET_PeerIdentity id;
634 * Number of trails for which this friend is the first hop.
636 unsigned int trails_count;
639 * Count of outstanding messages for this friend.
641 unsigned int pending_count;
646 struct GNUNET_TIME_Absolute congestion_duration;
649 * Head of pending messages to be sent to this friend.
651 struct P2PPendingMessage *head;
654 * Tail of pending messages to be sent to this friend.
656 struct P2PPendingMessage *tail;
659 * Core handle for sending messages to this friend.
661 struct GNUNET_CORE_TransmitHandle *th;
667 * FIXME: make an array of trails. #define number of entries in the array =
668 * number of trails we want to keep. Remove head, tail of trails.
669 * Entry in finger_peermap.
676 struct GNUNET_PeerIdentity finger_identity;
679 * Index in finger peer map
681 unsigned int finger_map_index;
684 * Number of trails to reach to this finger.
686 unsigned int trail_count;
689 * Total number of entries in first trail from (me,finger)
691 unsigned int first_trail_length;
694 * Total number of entries in second trail from (me,finger)
696 unsigned int second_trail_length;
700 * Number of trail of which the first element to reach to this finger is
703 unsigned int first_friend_trails_count;
706 * Head of first trail to reach this finger.
708 struct TrailPeerList *first_trail_head;
711 * Tail of first trail to reach this finger.
713 struct TrailPeerList *first_trail_tail;
716 * Head of second trail to reach this finger.
718 struct TrailPeerList *second_trail_head;
721 * Tail of second trail to reach this finger.
723 struct TrailPeerList *second_trail_tail;
729 * FIXME: The name is not correct.
730 * Used to specify the kind of value stored in the array all_known_peers.
732 enum current_destination_type
742 * Data structure passed to sorting algorithm in find_successor().
747 * 64 bit value of peer identity
752 * FIXME: think of a better name for both the struct and destination_type
753 * Type : MY_ID, FINGER, FINGER, Value
755 enum current_destination_type type;
758 * Pointer to original data structure linked to peer id.
765 * Task that sends FIND FINGER TRAIL requests. This task is started when we have
766 * get our first friend.
768 static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task;
771 * Identity of this peer.
773 static struct GNUNET_PeerIdentity my_identity;
776 * Hash map of all the friends of a peer
778 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap;
781 * Hash map of all the fingers of a peer
783 static struct GNUNET_CONTAINER_MultiPeerMap *finger_peermap;
788 static struct GNUNET_CORE_Handle *core_api;
791 * Finger map index for predecessor entry in finger peermap.
793 #define PREDECESSOR_FINGER_ID 64
796 * Maximum number of trails allowed to go through a friend.
797 * FIXME: Better name, Random value at the moment, need to be adjusted to maintain a balance
798 * between performance and Sybil tolerance.
800 #define TRAIL_THROUGH_FRIEND_THRESHOLD 64
803 * Possible number of different trails to reach to a finger. (Redundant routing)
805 #define TRAIL_COUNT 2
808 * The current finger index that we have want to find trail to.
810 static unsigned int current_search_finger_index;
814 * Iterate over trail and search your index location in the array.
815 * @param trail Trail which contains list of peers.
816 * @param trail_length Number of peers in the trail.
817 * @return Index in the array.
818 * #GNUNET_SYSERR, in case there is no entry which should not be the case ideally.
821 search_my_index (const struct GNUNET_PeerIdentity *trail,
826 while (i < trail_length)
828 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &trail[i]))
834 return GNUNET_SYSERR;
838 * Compare two peer identities.
839 * @param p1 Peer identity
840 * @param p2 Peer identity
841 * @return 1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2.
844 compare_peer_id (const void *p1, const void *p2)
846 struct Sorting_List *p11;
847 struct Sorting_List *p22;
849 p11 = GNUNET_malloc (sizeof (struct Sorting_List));
850 p22 = GNUNET_malloc (sizeof (struct Sorting_List));
851 p11 = (struct Sorting_List *)p1;
852 p22 = (struct Sorting_List *)p2;
853 ret = ( (p11->peer_id) > (p22->peer_id) ) ? 1 :
854 ( (p11->peer_id) == (p22->peer_id) ) ? 0 : -1;
860 * Return the predecessor of value in all_known_peers.
861 * @param all_known_peers list of all the peers
862 * @param value value we have to search in the all_known_peers.
863 * @param size Total numbers of elements
864 * @return Predecessor
866 static struct Sorting_List *
867 find_closest_predecessor(struct Sorting_List *all_known_peers, uint64_t value,
876 middle = (first + last)/2;
880 if(all_known_peers[middle].peer_id < value)
884 else if(all_known_peers[middle].peer_id == value)
888 return &all_known_peers[size - 1];
892 return &all_known_peers[middle - 1];
900 middle = (first + last)/2;
907 * Return the successor of value in all_known_peers.
908 * @param all_known_peers list of all the peers
909 * @param value value we have to search in the all_known_peers.
910 * @param size Total numbers of elements
913 static struct Sorting_List *
914 find_closest_successor(struct Sorting_List *all_known_peers, uint64_t value,
923 middle = (first + last)/2;
927 if(all_known_peers[middle].peer_id < value)
931 else if(all_known_peers[middle].peer_id == value)
933 if(middle == (size -1))
935 return &all_known_peers[0];
939 return &all_known_peers[middle+1];
947 middle = (first + last)/2;
954 * Called when core is ready to send a message we asked for
955 * out to the destination.
957 * @param cls the 'struct FriendInfo' of the target friend
958 * @param size number of bytes available in buf
959 * @param buf where the callee should write the message
960 * @return number of bytes written to buf
963 core_transmit_notify (void *cls, size_t size, void *buf)
965 struct FriendInfo *peer = cls;
967 struct P2PPendingMessage *pending;
972 while ((NULL != (pending = peer->head)) &&
973 (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us))
975 peer->pending_count--;
976 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
977 GNUNET_free (pending);
981 /* no messages pending */
987 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
988 GNUNET_CORE_PRIO_BEST_EFFORT,
989 GNUNET_TIME_absolute_get_remaining
990 (pending->timeout), &peer->id,
991 ntohs (pending->msg->size),
992 &core_transmit_notify, peer);
993 GNUNET_break (NULL != peer->th);
997 while ((NULL != (pending = peer->head)) &&
998 (size - off >= (msize = ntohs (pending->msg->size))))
1000 GNUNET_STATISTICS_update (GDS_stats,
1002 ("# Bytes transmitted to other peers"), msize,
1004 memcpy (&cbuf[off], pending->msg, msize);
1006 peer->pending_count--;
1007 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
1008 GNUNET_free (pending);
1010 if (peer->head != NULL)
1013 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
1014 GNUNET_CORE_PRIO_BEST_EFFORT,
1015 GNUNET_TIME_absolute_get_remaining
1016 (pending->timeout), &peer->id, msize,
1017 &core_transmit_notify, peer);
1018 GNUNET_break (NULL != peer->th);
1026 * Transmit all messages in the friend's message queue.
1028 * @param peer message queue to process
1031 process_friend_queue (struct FriendInfo *peer)
1033 struct P2PPendingMessage *pending;
1035 if (NULL == (pending = peer->head))
1037 if (NULL != peer->th)
1040 GNUNET_STATISTICS_update (GDS_stats,
1042 ("# Bytes of bandwidth requested from core"),
1043 ntohs (pending->msg->size), GNUNET_NO);
1045 /* FIXME: Are we correctly initializing importance and pending. */
1047 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
1048 pending->importance,
1049 GNUNET_TIME_absolute_get_remaining
1050 (pending->timeout), &peer->id,
1051 ntohs (pending->msg->size),
1052 &core_transmit_notify, peer);
1053 GNUNET_break (NULL != peer->th);
1058 * Construct a trail setup message and forward it to a friend.
1059 * @param source_peer Peer which wants to set up the trail to one of its finger.
1060 * @param destination_finger Peer identity closest to this value will be
1061 * @a source_peer's finger.
1062 * @param current_destination next destination corresponding to @a current_source,
1063 * can be either a finger or a friend of @a current_source.
1064 * @param current_source Peer for which @a current_destination is its finger/friend.
1065 * @param target_friend Friend to which this message should be forwarded.
1066 * @param trail_length Numbers of peers in the trail found so far.
1067 * @param trail_peer_list Peers this request has traversed so far
1068 * @param finger_map_index Index in finger peer map
1071 GDS_NEIGHBOURS_send_trail_setup (const struct GNUNET_PeerIdentity *source_peer,
1072 uint64_t destination_finger,
1073 struct GNUNET_PeerIdentity *current_destination,
1074 struct GNUNET_PeerIdentity *current_source,
1075 struct FriendInfo *target_friend,
1076 unsigned int trail_length,
1077 const struct GNUNET_PeerIdentity *trail_peer_list,
1078 unsigned int finger_map_index)
1080 struct P2PPendingMessage *pending;
1081 struct PeerTrailSetupMessage *tsm;
1082 struct GNUNET_PeerIdentity *peer_list;
1085 msize = sizeof (struct PeerTrailSetupMessage) +
1086 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1088 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1094 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1096 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1100 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1101 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1102 tsm = (struct PeerTrailSetupMessage *) &pending[1];
1103 pending->msg = &tsm->header;
1104 tsm->header.size = htons (msize);
1105 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
1106 memcpy (&(tsm->destination_finger), &destination_finger, sizeof (uint64_t));
1107 memcpy (&(tsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1108 memcpy (&(tsm->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity));
1109 memcpy (&(tsm->current_source), current_source, sizeof (struct GNUNET_PeerIdentity));
1110 tsm->trail_length = htonl (trail_length);
1111 tsm->finger_map_index = htonl (finger_map_index);
1113 if (trail_length > 0)
1115 peer_list = (struct GNUNET_PeerIdentity *) &tsm[1];
1116 memcpy (peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
1119 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1120 target_friend->pending_count++;
1121 process_friend_queue (target_friend);
1126 * Construct a trail setup result message and forward it to a friend.
1127 * @param destination_peer Peer which will get the trail to one of its finger.
1128 * @param source_finger Peer to which the trail has been setup to.
1129 * @param target_friend Friend to which this message should be forwarded.
1130 * @param trail_length Numbers of peers in the trail.
1131 * @param trail_peer_list Peers which are part of the trail from source to destination.
1132 * @param finger_map_index Index in finger peer map
1135 GDS_NEIGHBOURS_send_trail_setup_result (const struct GNUNET_PeerIdentity *destination_peer,
1136 const struct GNUNET_PeerIdentity *source_finger,
1137 struct FriendInfo *target_friend,
1138 unsigned int trail_length,
1139 const struct GNUNET_PeerIdentity *trail_peer_list,
1140 unsigned int finger_map_index)
1142 struct P2PPendingMessage *pending;
1143 struct PeerTrailSetupResultMessage *tsrm;
1144 struct GNUNET_PeerIdentity *peer_list;
1147 msize = sizeof (struct PeerTrailSetupResultMessage) +
1148 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1150 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1156 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1158 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1162 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1163 pending->importance = 0;
1164 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1165 tsrm = (struct PeerTrailSetupResultMessage *) &pending[1];
1166 pending->msg = &tsrm->header;
1167 tsrm->header.size = htons (msize);
1168 tsrm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT);
1169 memcpy (&(tsrm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1170 memcpy (&(tsrm->finger_identity), source_finger, sizeof (struct GNUNET_PeerIdentity));
1171 tsrm->trail_length = htonl (trail_length);
1172 tsrm->finger_map_index = htonl (finger_map_index);
1174 peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1];
1175 if (trail_length > 0)
1177 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1179 /* Send the message to chosen friend. */
1180 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1181 target_friend->pending_count++;
1182 process_friend_queue (target_friend);
1187 * Construct a PeerVerifySuccessor message and send it to friend.
1188 * @param source_peer Peer which wants to verify its successor
1189 * @param successor Peer which is our current successor
1190 * @param target_friend Friend to which this message should be forwarded.
1191 * @param trail_peer_list Peer which are part of trail from source to destination
1192 * @param trail_length Number of peers in the trail list.
1194 void GDS_NEIGHBOURS_send_verify_successor(const struct GNUNET_PeerIdentity *source_peer,
1195 const struct GNUNET_PeerIdentity *successor,
1196 struct FriendInfo *target_friend,
1197 const struct GNUNET_PeerIdentity *trail_peer_list,
1198 unsigned int trail_length)
1200 struct PeerVerifySuccessorMessage *vsm;
1201 struct P2PPendingMessage *pending;
1202 struct GNUNET_PeerIdentity *peer_list;
1205 msize = sizeof (struct PeerVerifySuccessorMessage) +
1206 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1208 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1214 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1216 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1220 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1221 pending->importance = 0; /* FIXME */
1222 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1223 vsm = (struct PeerVerifySuccessorMessage *) &pending[1];
1224 pending->msg = &vsm->header;
1225 vsm->header.size = htons (msize);
1226 vsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR);
1227 memcpy (&(vsm->successor), successor, sizeof (struct GNUNET_PeerIdentity));
1228 memcpy (&(vsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1229 vsm->trail_length = htonl (trail_length);
1231 if (trail_length > 0)
1233 peer_list = (struct GNUNET_PeerIdentity *) &vsm[1];
1234 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1237 /* Send the message to chosen friend. */
1238 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1239 target_friend->pending_count++;
1240 process_friend_queue (target_friend);
1246 * Construct a PeerVerifySuccessorResult message and send it to friend.
1247 * @param destination_peer Peer which sent verify successor message
1248 * @param source_successor Peer to which verify successor message was sent.
1249 * @param my_predecessor source_successor's predecessor.
1250 * @param target_friend Friend to which this message should be forwarded.
1251 * @param trail_peer_list Peers which are part of trail from source to destination
1252 * @param trail_length Number of peers in the trail list.
1254 void GDS_NEIGHBOURS_send_verify_successor_result (const struct GNUNET_PeerIdentity *destination_peer,
1255 const struct GNUNET_PeerIdentity *source_successor,
1256 const struct GNUNET_PeerIdentity *my_predecessor,
1257 struct FriendInfo *target_friend,
1258 const struct GNUNET_PeerIdentity *trail_peer_list,
1259 unsigned int trail_length)
1261 struct PeerVerifySuccessorResultMessage *vsmr;
1262 struct P2PPendingMessage *pending;
1263 struct GNUNET_PeerIdentity *peer_list;
1266 msize = sizeof (struct PeerVerifySuccessorResultMessage) +
1267 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1269 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1276 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1278 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1282 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1283 pending->importance = 0; /* FIXME */
1284 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1285 vsmr = (struct PeerVerifySuccessorResultMessage *) &pending[1];
1286 pending->msg = &vsmr->header;
1287 vsmr->header.size = htons (msize);
1288 vsmr->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT);
1289 memcpy (&(vsmr->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1290 memcpy (&(vsmr->source_successor), source_successor, sizeof (struct GNUNET_PeerIdentity));
1291 memcpy (&(vsmr->my_predecessor), my_predecessor, sizeof (struct GNUNET_PeerIdentity));
1292 vsmr->trail_length = htonl (trail_length);
1293 if (trail_length > 0)
1295 peer_list = (struct GNUNET_PeerIdentity *) &vsmr[1];
1296 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1299 /* Send the message to chosen friend. */
1300 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1301 target_friend->pending_count++;
1302 process_friend_queue (target_friend);
1307 * Construct a PeerNotifyNewSuccessor message and send it to friend.
1308 * @param source_peer Peer which is sending notify message to its new successor.
1309 * @param destination_peer Peer which is the new destination.
1310 * @param target_friend Next friend to pass this message to.
1311 * @param peer_list List of peers in the trail to reach to destination_peer.
1312 * @param trail_length Total number of peers in peer list
1315 GDS_NEIGHBOURS_send_notify_new_successor (const struct GNUNET_PeerIdentity *source_peer,
1316 const struct GNUNET_PeerIdentity *destination_peer,
1317 const struct GNUNET_PeerIdentity *old_successor,
1318 struct FriendInfo *target_friend,
1319 const struct GNUNET_PeerIdentity *trail_peer_list,
1320 unsigned int trail_length)
1322 struct PeerNotifyNewSuccessorMessage *nsm;
1323 struct P2PPendingMessage *pending;
1324 struct GNUNET_PeerIdentity *peer_list;
1327 msize = sizeof (struct PeerNotifyNewSuccessorMessage) +
1328 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1330 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1336 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1338 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1342 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1343 pending->importance = 0; /* FIXME */
1344 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1345 nsm = (struct PeerNotifyNewSuccessorMessage *) &pending[1];
1346 pending->msg = &nsm->header;
1347 nsm->header.size = htons (msize);
1348 nsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR);
1349 memcpy (&(nsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1350 memcpy (&(nsm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1351 memcpy (&(nsm->old_successor), old_successor, sizeof (struct GNUNET_PeerIdentity));
1352 nsm->trail_length = htonl (trail_length);
1354 if (trail_length > 0)
1356 peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
1357 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1359 /* Send the message to chosen friend. */
1360 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1361 target_friend->pending_count++;
1362 process_friend_queue (target_friend);
1366 * Send a trail tear down message
1367 * @param source_peer Source of the trail.
1368 * @param destination_peer Destination of the trail.
1369 * @param discarded_trail Discarded trail from source to destination.
1370 * @param discarded_trail_length Total number of peers in trail_list.
1371 * @pararm target_peer Next peer to forward this message to.
1372 * @param new_first_friend The new first hop in the new trail from source to destination
1376 GDS_NEIGHBOURS_send_trail_teardown (const struct GNUNET_PeerIdentity *source_peer,
1377 const struct GNUNET_PeerIdentity *destination_peer,
1378 const struct GNUNET_PeerIdentity *discarded_trail,
1379 unsigned int discarded_trail_length,
1380 struct FriendInfo *target_friend,
1381 const struct GNUNET_PeerIdentity *new_first_friend)
1383 struct P2PPendingMessage *pending;
1384 struct PeerTrailTearDownMessage *ttdm;
1385 struct GNUNET_PeerIdentity *peer_list;
1388 msize = sizeof (struct PeerTrailTearDownMessage) +
1389 (discarded_trail_length * sizeof(struct GNUNET_PeerIdentity));
1391 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1397 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1399 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1403 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1404 pending->importance = 0; /* FIXME */
1405 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1406 ttdm = (struct PeerTrailTearDownMessage *) &pending[1];
1407 pending->msg = &ttdm->header;
1408 ttdm->header.size = htons (msize);
1409 ttdm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_TEARDOWN);
1410 memcpy (&(ttdm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1411 memcpy (&(ttdm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1412 memcpy (&(ttdm->new_first_friend),new_first_friend, sizeof (struct GNUNET_PeerIdentity));
1413 ttdm->trail_length = htonl (discarded_trail_length);
1415 if (discarded_trail_length > 0)
1417 peer_list = (struct GNUNET_PeerIdentity *) &ttdm[1];
1418 memcpy (peer_list, discarded_trail, discarded_trail_length * sizeof (struct GNUNET_PeerIdentity));
1420 /* Send the message to chosen friend. */
1421 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1422 target_friend->pending_count++;
1423 process_friend_queue (target_friend);
1429 * @param source_peer
1430 * @param destination_peer
1432 * @param trail_length
1433 * @param target_friend
1436 GDS_NEIGHBOURS_send_add_trail_message (struct GNUNET_PeerIdentity *source_peer,
1437 struct GNUNET_PeerIdentity *destination_peer,
1438 struct GNUNET_PeerIdentity *trail,
1439 unsigned int trail_length,
1440 struct FriendInfo *target_friend)
1442 struct P2PPendingMessage *pending;
1443 struct PeerAddTrailMessage *adm;
1444 struct GNUNET_PeerIdentity *peer_list;
1447 msize = sizeof (struct PeerAddTrailMessage) +
1448 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1450 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1456 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1458 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1462 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1463 pending->importance = 0; /* FIXME */
1464 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1465 adm = (struct PeerAddTrailMessage *) &pending[1];
1466 pending->msg = &adm->header;
1467 adm->header.size = htons (msize);
1468 adm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_ADD_TRAIL);
1469 memcpy (&(adm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1470 memcpy (&(adm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1471 adm->trail_length = htonl (trail_length);
1473 if (trail_length > 0)
1475 peer_list = (struct GNUNET_PeerIdentity *)&adm[1];
1476 memcpy (peer_list, trail, sizeof (struct GNUNET_PeerIdentity) * trail_length);
1479 /* Send the message to chosen friend. */
1480 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1481 target_friend->pending_count++;
1482 process_friend_queue (target_friend);
1487 * FIXME: CONGESTION: check the code once basic code is all correct. s
1488 * FIXME: call GNUNET_CONTAINER_multipeermap_iterator_destroy (iter);
1489 * In case the friend chosen in select_random_friend() is congested or
1490 * has crossed trail_threshold, then get next friend which is not congested or
1491 * has not crossed trail threshold from friend peermap.
1492 * @param current_index Index in finger peermap chosen randomly
1493 * @param friend_peermap_size Total number of entries in friend peermap.
1494 * @param count Total number of time this function has been called, in case
1495 * count == sizeof(friend_peermap) - 1, it means none of the friends are free.
1496 * @return Friend Friend found.
1497 * NULL in case all the friends are congested or have crossed trail threshold.
1499 static struct FriendInfo *
1500 get_next_friend (unsigned int current_index,
1501 unsigned int friend_peermap_size,
1504 struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
1505 struct GNUNET_PeerIdentity key_ret;
1506 struct FriendInfo *friend;
1509 current_index = (current_index + 1) % friend_peermap_size;
1510 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1511 while(j < (current_index))
1513 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,NULL,NULL))
1521 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,&key_ret,(const void **)&friend))
1523 if ((friend->trails_count > TRAIL_THROUGH_FRIEND_THRESHOLD) ||
1524 (0 != GNUNET_TIME_absolute_get_remaining (friend->congestion_duration).rel_value_us))
1527 if (count == (friend_peermap_size -1))
1530 return get_next_friend (j,friend_peermap_size,count);
1540 * FIXME: CONGESTION: check the code once basic code is all correct.
1541 * FIXME: call GNUNET_CONTAINER_multipeermap_iterator_destroy (iter);
1542 * Randomly choose one of your friends from the friends_peer map
1543 * @return Friend Randomly chosen friend.
1544 * NULL in case friend peermap is empty, or all the friends are either
1545 * congested or have crossed trail threshold.
1547 static struct FriendInfo *
1548 select_random_friend ()
1550 unsigned int current_size;
1551 unsigned int *index;
1553 struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
1554 struct GNUNET_PeerIdentity key_ret;
1555 struct FriendInfo *friend;
1557 current_size = GNUNET_CONTAINER_multipeermap_size (friend_peermap);
1558 if (0 == current_size)
1561 index = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, current_size);
1562 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1566 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,NULL,NULL))
1576 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,&key_ret,(const void **)&friend))
1578 if ((TRAIL_THROUGH_FRIEND_THRESHOLD == friend->trails_count) ||
1579 (0 != GNUNET_TIME_absolute_get_remaining (friend->congestion_duration).rel_value_us))
1581 return get_next_friend (*index, current_size, 1);
1591 * Compute finger_identity to which we want to setup the trail
1592 * @return finger_identity
1595 compute_finger_identity()
1599 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
1600 my_id64 = GNUNET_ntohll (my_id64);
1601 return (my_id64 + (unsigned long) pow (2, current_search_finger_index));
1606 * Compute immediate predecessor identity in the network.
1607 * @return peer identity of immediate predecessor.
1610 compute_predecessor_identity()
1614 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
1615 my_id64 = GNUNET_ntohll (my_id64);
1616 return (my_id64 -1);
1621 * Ping your successor to verify if it is still your successor or not.
1624 send_verify_successor_message()
1626 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1627 struct GNUNET_PeerIdentity key_ret;
1628 struct FriendInfo *target_friend;
1629 struct GNUNET_PeerIdentity next_hop;
1630 struct GNUNET_PeerIdentity *peer_list;
1631 struct FingerInfo *finger;
1632 unsigned int finger_index;
1635 /* Find the successor from the finger peermap.*/
1636 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1637 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
1639 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, &key_ret,
1640 (const void **)&finger))
1642 if (0 == finger->finger_map_index)
1649 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
1651 /* Either you don't have a successor or you are your own successor, then don't
1652 send a successor message. */
1654 (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, &(finger->finger_identity))))
1659 if (finger->first_trail_length > 0)
1661 struct TrailPeerList *iterate;
1663 peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * finger->first_trail_length);
1664 iterate = finger->first_trail_head;
1666 while ( i < (finger->first_trail_length))
1668 memcpy (&peer_list[i], &(iterate->peer), sizeof (struct GNUNET_PeerIdentity));
1669 iterate = iterate->next;
1672 memcpy (&next_hop, &peer_list[0], sizeof (struct GNUNET_PeerIdentity));
1673 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
1677 /* If trail length = 0, then our successor is our friend. */
1679 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1680 &(finger->finger_identity));
1683 GDS_NEIGHBOURS_send_verify_successor (&my_identity,
1684 &(finger->finger_identity),
1687 finger->first_trail_length);
1692 * Choose a random friend and start looking for the trail to reach to
1693 * finger identity through this random friend.
1695 * @param cls closure for this task
1696 * @param tc the context under which the task is running
1699 send_find_finger_trail_message (void *cls,
1700 const struct GNUNET_SCHEDULER_TaskContext *tc)
1702 struct FriendInfo *target_friend;
1703 struct GNUNET_TIME_Relative next_send_time;
1704 uint64_t finger_identity;
1705 unsigned int finger_map_index;
1707 next_send_time.rel_value_us =
1708 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
1709 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1710 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us);
1711 find_finger_trail_task =
1712 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_finger_trail_message,
1715 target_friend = select_random_friend ();
1716 if (NULL == target_friend)
1721 if (PREDECESSOR_FINGER_ID == current_search_finger_index)
1723 finger_identity = compute_predecessor_identity();
1727 finger_identity = compute_finger_identity();
1730 finger_map_index = current_search_finger_index;
1731 GDS_NEIGHBOURS_send_trail_setup (&my_identity, finger_identity, &(target_friend->id),
1732 &my_identity, target_friend, 0, NULL, finger_map_index);
1737 * Scan the trail to check if any of my own friend is part of trail. If yes
1738 * then shortcut the trail, send a trail teardown for the discarded trail,
1739 * update trail list and trail_length.
1740 * @param trail[Out] Current trail to reach to @a finger, will be updated
1741 * in case we compress the trail.
1742 * @param trail_length[Out] Number of peers in @a finger_trail, will be updated
1743 * in case we compress the trail.
1744 * @param finger Finger identity
1747 scan_and_compress_trail (struct GNUNET_PeerIdentity *trail,
1748 unsigned int *trail_length,
1749 const struct GNUNET_PeerIdentity *finger)
1752 struct FriendInfo *target_friend;
1754 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity,finger))
1756 /* Here you don't send a trail teardown as no one added this in their
1762 if (GNUNET_CONTAINER_multipeermap_get (friend_peermap, finger))
1764 int discarded_trail_length = *trail_length;
1765 target_friend = GNUNET_CONTAINER_multipeermap_get(friend_peermap, &trail[0]);
1766 GDS_NEIGHBOURS_send_trail_teardown (&my_identity, finger, trail,
1767 discarded_trail_length, target_friend, finger);
1773 i = *trail_length - 1;
1777 if (NULL == GNUNET_CONTAINER_multipeermap_get (friend_peermap, &trail[i]))
1779 /* This element of trail is not my friend. */
1784 /* A --> B(friend 1) --> C(friend 2)--> D ---> E, then we can rewrite the trail as
1786 * Now, we should remove the entry from A's routing table, B's routing table
1787 * and update the entry in C's routing table. Rest everything will be same.
1788 * C's routing table should have source peer as the prev.hop.
1790 struct GNUNET_PeerIdentity *discarded_trail;
1791 struct FriendInfo *target_friend;
1792 int discarded_trail_length;
1795 discarded_trail_length = i - 1;
1796 discarded_trail = GNUNET_malloc (discarded_trail_length * sizeof (struct GNUNET_PeerIdentity));
1797 memcpy (discarded_trail, trail, discarded_trail_length * sizeof (struct GNUNET_PeerIdentity));
1798 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &trail[0]);
1799 GDS_NEIGHBOURS_send_trail_teardown (&my_identity, finger, discarded_trail,
1800 discarded_trail_length, target_friend,
1803 /* Copy the trail from index i to index trail_length -1 and change
1804 trail length and return */
1805 while (i < *trail_length)
1807 memcpy (&trail[j], &trail[i], sizeof(struct GNUNET_PeerIdentity));
1811 *trail_length = j+1;
1820 * FIXME: Adapt the code for List of trails.
1821 * Free finger and its trail.
1822 * @param finger Finger to be freed.
1825 free_finger (struct FingerInfo *finger)
1827 struct TrailPeerList *peer;
1829 if(finger->first_trail_head != NULL)
1831 while (NULL != (peer = finger->first_trail_head))
1833 GNUNET_CONTAINER_DLL_remove (finger->first_trail_head, finger->first_trail_tail, peer);
1838 if (finger->second_trail_head != NULL)
1840 while (NULL != (peer = finger->second_trail_head))
1842 GNUNET_CONTAINER_DLL_remove (finger->second_trail_head, finger->second_trail_tail, peer);
1845 GNUNET_free (finger);
1851 * FIXME: First check if both the trails are present if yes then send it
1852 * for both of them. Currently sending it only for one trail.
1853 * Send a trail teardown message for the trail of removed finger from the finger
1855 * @param existing_finger Finger to removed from the finger peermap.
1858 void send_trail_teardown (struct FingerInfo *removed_finger)
1860 struct GNUNET_PeerIdentity *peer_list;
1861 struct FriendInfo *friend;
1862 struct TrailPeerList *finger_trail;
1863 int removed_finger_trail_length = removed_finger->first_trail_length;
1866 if (removed_finger->first_trail_length == 0)
1869 finger_trail = removed_finger->first_trail_head;
1870 friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &(finger_trail->peer));
1871 peer_list = GNUNET_malloc ( removed_finger_trail_length * sizeof (struct GNUNET_PeerIdentity));
1872 while (i < removed_finger->first_trail_length)
1874 memcpy (&peer_list[i], &(finger_trail->peer), sizeof (struct GNUNET_PeerIdentity));
1875 finger_trail = finger_trail->next;
1879 GDS_NEIGHBOURS_send_trail_teardown (&my_identity, &(removed_finger->finger_identity),
1880 peer_list, removed_finger_trail_length, friend,
1881 &(removed_finger->finger_identity));
1886 * FIXME: How do we understand which is the correct trail head?
1887 * Add a new trail to reach an existing finger in finger peermap and increment
1888 * the count of number of trails to reach to this finger.
1889 * @param existing_finger Finger
1890 * @param trail New trail to be added
1891 * @param trail_length Total number of peers in the trail.
1894 void add_new_trail (struct FingerInfo *existing_finger,
1895 struct GNUNET_PeerIdentity *trail,
1896 unsigned int trail_length)
1900 /* FIXME: Here you need to understand which trail is there and which not.
1901 In case first_trail_head != NULL, then that trail is present
1902 so you should add the second one. Need to verify this logic. */
1903 if (existing_finger->first_trail_head != NULL)
1905 while (i < trail_length)
1907 struct TrailPeerList *element;
1908 element = GNUNET_malloc (sizeof (struct TrailPeerList));
1909 element->next = NULL;
1910 element->prev = NULL;
1912 memcpy (&(element->peer), &trail[i], sizeof(struct GNUNET_PeerIdentity));
1913 GNUNET_CONTAINER_DLL_insert_tail(existing_finger->second_trail_head, existing_finger->second_trail_tail, element);
1917 else if (existing_finger->second_trail_head != NULL)
1919 while (i < trail_length)
1921 struct TrailPeerList *element;
1922 element = GNUNET_malloc (sizeof (struct TrailPeerList));
1923 element->next = NULL;
1924 element->prev = NULL;
1926 memcpy (&(element->peer), &trail[i], sizeof(struct GNUNET_PeerIdentity));
1927 GNUNET_CONTAINER_DLL_insert_tail(existing_finger->first_trail_head, existing_finger->first_trail_tail, element);
1931 existing_finger->trail_count++;
1936 * In case there are already maximum number of possible trail to reach to a finger,
1937 * then check if the new trail's length is lesser than any of the existing trails.
1938 * If yes then replace that old trail by new trail.
1939 * Note: Here we are taking length as a parameter to choose the best possible trail,
1940 * but there could be other parameters also like - 1. duration of existence of a
1941 * trail - older the better. 2. if the new trail is completely disjoint than the
1942 * other trails, then may be choosing it is better.
1943 * @param existing_finger
1945 * @param trail_length
1946 * @return #GNUNET_YES
1950 void select_and_replace_trail (struct FingerInfo *existing_finger,
1951 struct GNUNET_PeerIdentity *new_trail,
1952 unsigned int new_trail_length)
1954 if (existing_finger->first_trail_length == existing_finger->second_trail_length)
1956 if (new_trail_length < existing_finger->first_trail_length)
1958 /* Randomly choose one of the trail. FIXME:currently I am just replacing the
1960 struct TrailPeerList *peer;
1963 while (NULL != (peer = existing_finger->first_trail_head))
1965 GNUNET_CONTAINER_DLL_remove (existing_finger->first_trail_head, existing_finger->first_trail_tail, peer);
1969 while (i < new_trail_length)
1971 struct TrailPeerList *element;
1972 element = GNUNET_malloc (sizeof (struct TrailPeerList));
1973 element->next = NULL;
1974 element->prev = NULL;
1976 memcpy (&(element->peer), &new_trail[i], sizeof(struct GNUNET_PeerIdentity));
1977 GNUNET_CONTAINER_DLL_insert_tail(existing_finger->second_trail_head, existing_finger->second_trail_tail, element);
1982 else if ((new_trail_length < existing_finger->second_trail_length) &&
1983 (existing_finger->second_trail_length < existing_finger->first_trail_length))
1985 /* Replace the first trail by the new trail. */
1986 struct TrailPeerList *peer;
1989 while (NULL != (peer = existing_finger->first_trail_head))
1991 GNUNET_CONTAINER_DLL_remove (existing_finger->first_trail_head, existing_finger->first_trail_tail, peer);
1995 while (i < new_trail_length)
1997 struct TrailPeerList *element;
1998 element = GNUNET_malloc (sizeof (struct TrailPeerList));
1999 element->next = NULL;
2000 element->prev = NULL;
2002 memcpy (&(element->peer), &new_trail[i], sizeof(struct GNUNET_PeerIdentity));
2003 GNUNET_CONTAINER_DLL_insert_tail(existing_finger->second_trail_head, existing_finger->second_trail_tail, element);
2007 else if ( (new_trail_length < existing_finger->first_trail_length) &&
2008 (existing_finger->first_trail_length < existing_finger->second_trail_length))
2010 /* Replace the second trail by the new trail. */
2011 struct TrailPeerList *peer;
2014 while (NULL != (peer = existing_finger->second_trail_head))
2016 GNUNET_CONTAINER_DLL_remove (existing_finger->second_trail_head, existing_finger->second_trail_tail, peer);
2020 while (i < new_trail_length)
2022 struct TrailPeerList *element;
2023 element = GNUNET_malloc (sizeof (struct TrailPeerList));
2024 element->next = NULL;
2025 element->prev = NULL;
2027 memcpy (&(element->peer), &new_trail[i], sizeof(struct GNUNET_PeerIdentity));
2028 GNUNET_CONTAINER_DLL_insert_tail(existing_finger->second_trail_head, existing_finger->second_trail_tail, element);
2036 * FIXME: If we remove a finger which is our friend, then how should we handle it.
2037 * Ideally only in case if the trail_length > 0,we increment the trail count
2038 * of the first friend in the trail to reach to the finger. in case finger is
2039 * our friend then trail length = 0, and hence, we have never incremented the
2040 * trail count associated with that friend.
2041 * Decrement the trail count for the first friend to reach to the finger.
2045 decrement_friend_trail_count (struct FingerInfo *finger)
2047 struct FriendInfo *first_trail_friend;
2048 struct FriendInfo *second_trail_friend;
2050 if(finger->first_trail_head != NULL)
2052 first_trail_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2053 &(finger->first_trail_head->peer));
2054 first_trail_friend->trails_count--;
2057 if(finger->second_trail_head != NULL)
2059 second_trail_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2060 &(finger->second_trail_head->peer));
2061 second_trail_friend->trails_count--;
2065 /* We will not need this variable any more, all_friends_trail_threshold,
2066 FIXME: REMOVE IT. */
2067 if (GNUNET_YES == all_friends_trail_threshold)
2069 all_friends_trail_threshold = GNUNET_NO;
2070 /* FIXME; Here you should reschedule the send_find_finger_task here. or
2078 * FIXME: create a different data structure for storing the peer ids here.
2079 * Select the closest finger. Used for both predecessor and other fingers..
2080 * But internally calls different functions for predecessor and other fingers.
2081 * @param existing_finger Finger in finger peermap.
2082 * @param new_finger New finger identity
2083 * @param finger_map_index Index in finger peermap where @a existing_finger is stored.
2084 * @return #GNUNET_YES if the new finger is closest.
2085 * #GNUNET_NO if the old finger is closest.
2086 * #GNUNET_SYSERR in case our own identity is closest (should never happen).
2089 int select_finger (struct FingerInfo *existing_finger,
2090 const struct GNUNET_PeerIdentity *new_finger,
2091 unsigned int finger_map_index)
2093 struct Sorting_List peers[3]; /* 3 for existing_finger, new_finger, my_identity */
2094 struct Sorting_List *closest_finger;
2098 for (k = 0; k < 3; k++)
2101 /* Add your entry to peers. */
2102 memcpy (&peers[0], &my_identity, sizeof (uint64_t));
2103 peers[0].type = MY_ID;
2104 peers[0].data = NULL;
2106 /* Add existing_finger identity to the peers. */
2107 memcpy (&peers[1], &(existing_finger->finger_identity), sizeof (uint64_t));
2108 peers[1].type = FINGER;
2109 peers[1].data = existing_finger;
2111 /* Add new_finger identity to the peers. s*/
2112 memcpy (&peers[2], &new_finger, sizeof (uint64_t));
2113 peers[2].type = VALUE;
2114 peers[2].data = NULL;
2116 memcpy (&value, &my_identity, sizeof (uint64_t));
2117 qsort (&peers, 3, sizeof (struct Sorting_List), &compare_peer_id);
2119 if (PREDECESSOR_FINGER_ID == finger_map_index)
2120 closest_finger = find_closest_predecessor (peers, value, 3);
2122 closest_finger = find_closest_successor (peers, value, 3);
2124 if (closest_finger->type == FINGER)
2128 else if (closest_finger->type == VALUE)
2132 else if (closest_finger->type == MY_ID);
2134 return GNUNET_SYSERR;
2140 * FIXME: Better name, and make the code more cleaner.
2141 * Compare the new finger entry added and our successor.
2142 * @return #GNUNET_YES if same.
2143 * #GNUNET_NO if not.
2146 compare_new_entry_and_successor (const struct GNUNET_PeerIdentity *new_finger,
2147 int finger_map_index)
2149 int successor_flag = 0;
2150 struct FingerInfo *successor_finger;
2151 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
2154 if (PREDECESSOR_FINGER_ID == finger_map_index)
2157 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
2158 for (i= 0; i < GNUNET_CONTAINER_multipeermap_size (finger_peermap); i++)
2160 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, NULL,
2161 (const void **)&successor_finger))
2163 if (successor_finger->finger_map_index == 0)
2170 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
2172 /* Ideally we should never reach here. */
2173 if (successor_flag == 0)
2179 if (0 == GNUNET_CRYPTO_cmp_peer_identity (new_finger, &(successor_finger->finger_identity)))
2187 * Add a new entry in finger table.
2188 * @param finger_identity PeerIdentity of the new finger
2189 * @param finger_trail Trail to reach to the finger, can be NULL in case I am my own
2191 * @param finger_trail_length Number of peers in the trail, can be 0 in case finger
2192 * is a friend or I am my own finger.
2193 * @param finger_map_index Index in finger map.
2196 add_new_entry (const struct GNUNET_PeerIdentity *finger_identity,
2197 struct GNUNET_PeerIdentity *finger_trail,
2198 uint32_t finger_trail_length,
2199 uint32_t finger_map_index)
2201 struct FriendInfo *first_friend_trail;
2202 struct FingerInfo *new_finger_entry;
2205 /* Add a new entry. */
2206 new_finger_entry = GNUNET_malloc (sizeof (struct FingerInfo));
2207 memcpy (&(new_finger_entry->finger_identity), finger_identity, sizeof (struct GNUNET_PeerIdentity));
2208 new_finger_entry->finger_map_index = finger_map_index;
2209 new_finger_entry->first_trail_length = finger_trail_length;
2210 new_finger_entry->trail_count = 1;
2212 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,finger_identity)) /* finger_trail is NULL in case I am my own finger identity. */
2214 /* Incrementing the friend trails count. */
2215 if (finger_trail_length > 0)
2217 first_friend_trail = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger_trail[0]);
2218 first_friend_trail->trails_count++;
2222 /* It means the finger is my friend. */
2223 first_friend_trail = GNUNET_CONTAINER_multipeermap_get (friend_peermap, finger_identity);
2224 first_friend_trail->trails_count++;
2226 new_finger_entry->first_friend_trails_count = first_friend_trail->trails_count;
2228 /* Copy the trail. */
2230 while (i < finger_trail_length)
2232 struct TrailPeerList *element;
2233 element = GNUNET_malloc (sizeof (struct TrailPeerList));
2234 element->next = NULL;
2235 element->prev = NULL;
2237 memcpy (&(element->peer), &finger_trail[i], sizeof(struct GNUNET_PeerIdentity));
2238 GNUNET_CONTAINER_DLL_insert_tail(new_finger_entry->first_trail_head, new_finger_entry->first_trail_tail, element);
2243 return GNUNET_CONTAINER_multipeermap_put (finger_peermap,
2244 &(new_finger_entry->finger_identity),
2246 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2251 * Choose the closest finger between existing finger and new finger.
2252 * If the new finger is closest, then send a trail_teardown message along
2253 * existing_finger's trail. In case both the id's are same, and there is a place
2254 * to add more trails, then store both of them. In case there is no space to
2255 * store any more trail, then choose the best trail (best - depends on length in
2256 * current_implementation) and discard the others.
2257 * @param existing_finger
2258 * @param new_finger Existing finger in finger_peermap for @a finger_map_index
2259 * @param trail Trail to reach from me to @a new_finger
2260 * @param trail_length Total number of peers in @a trail.
2261 * @param finger_map_index Index in finger peermap.
2262 * @return #GNUNET_YES In case we want to store the new entry.
2263 * #GNUNET_NO In case we want the existing entry.
2264 * #GNUNET_SYSERR Error.
2267 int select_closest_finger (struct FingerInfo *existing_finger,
2268 const struct GNUNET_PeerIdentity *new_finger,
2269 struct GNUNET_PeerIdentity *trail,
2270 unsigned int trail_length,
2271 unsigned int finger_map_index)
2273 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity), new_finger))
2275 /* New entry and existing entry are same. */
2276 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity), &my_identity))
2278 /* If existing_finger is my_identity then trail_length = 0, trail = NULL. In
2279 this case you don't need to check the trails. Exit. */
2282 if (trail_length > 0)
2284 scan_and_compress_trail (trail, &trail_length, new_finger);
2286 if (existing_finger->trail_count < TRAIL_COUNT)
2288 add_new_trail (existing_finger, trail, trail_length);
2293 select_and_replace_trail (existing_finger, trail, trail_length);
2297 else if (GNUNET_YES == select_finger (existing_finger, new_finger, finger_map_index))
2299 /* New finger is the closest finger. */
2300 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, new_finger))
2302 /* FIXME: Here in case the new finger is my_identity and old entry is not,
2303 should we keep the old entry even if the old entry is not the closest? */
2306 send_trail_teardown (existing_finger);
2307 decrement_friend_trail_count (existing_finger);
2308 free_finger (existing_finger);
2310 if (trail_length > 0)
2312 scan_and_compress_trail (trail, &trail_length, new_finger);
2316 else if (GNUNET_NO == select_finger (existing_finger, new_finger,finger_map_index))
2318 /* existing_finger is the closest finger. */
2321 return GNUNET_SYSERR;
2326 * Check if there is already an entry for finger map index in finger table.
2327 * If yes then choose the closest finger.
2328 * @param finger_identity Peer Identity of finger.
2329 * @param finger_trail Trail to reach from me to @a finger_identity
2330 * @param finger_trail_length Total number of peers in finger_trail.
2331 * @param finger_map_index Index in finger_peermap.
2332 * @return #GNUNET_YES if the new entry is added.
2333 * #GNUNET_NO if the new entry is discarded.
2336 int finger_table_add (const struct GNUNET_PeerIdentity *finger_identity,
2337 struct GNUNET_PeerIdentity *finger_trail,
2338 uint32_t finger_trail_length,
2339 uint32_t finger_map_index)
2341 struct FingerInfo *existing_finger;
2342 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
2344 int old_entry_found = GNUNET_NO;
2345 int new_entry_added = GNUNET_NO;
2347 /* Check if there is already an entry for the finger map index in the finger peer map. */
2348 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
2349 for (i= 0; i < GNUNET_CONTAINER_multipeermap_size (finger_peermap); i++)
2351 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, NULL,
2352 (const void **)&existing_finger))
2354 if (existing_finger->finger_map_index == finger_map_index)
2356 old_entry_found = GNUNET_YES;
2357 if ( GNUNET_NO == select_closest_finger (existing_finger, finger_identity,
2358 finger_trail, finger_trail_length,
2360 goto update_current_search_finger_index;
2366 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
2368 if (GNUNET_NO == old_entry_found)
2370 if (finger_trail_length > 0)
2372 scan_and_compress_trail (finger_trail, &finger_trail_length, finger_identity);
2376 /* FIXME: handle the case when addition in peer map failed. */
2377 if(GNUNET_OK == add_new_entry (finger_identity,finger_trail,finger_trail_length, finger_map_index))
2378 new_entry_added = GNUNET_YES;
2382 update_current_search_finger_index:
2383 if (0 == finger_map_index)
2385 current_search_finger_index = PREDECESSOR_FINGER_ID;
2386 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,finger_identity))
2387 send_verify_successor_message();
2389 else if (GNUNET_YES == compare_new_entry_and_successor (finger_identity,finger_map_index))
2391 current_search_finger_index = 0;
2395 current_search_finger_index = current_search_finger_index - 1;
2398 return new_entry_added;
2403 * Check if the successor chosen is congested or has crossed trail threshold.
2404 * @param successor Successor to be checked.
2405 * @return #GNUNET_YES in case its is either congested or has crossed trail threshold.
2406 * #GNUNET_NO if its good to go.
2409 check_friend_threshold_and_congestion (struct Sorting_List *successor)
2411 struct FriendInfo *friend;
2413 if (successor->type == FRIEND)
2415 friend = successor->data;
2417 else if (successor->type == FINGER)
2419 struct FingerInfo *finger = successor->data;
2420 if (finger->first_trail_length > 0)
2422 friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2423 &(finger->first_trail_head->peer));
2427 friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &(finger->finger_identity));
2431 if ((friend->trails_count == TRAIL_THROUGH_FRIEND_THRESHOLD)||
2432 ((0 != GNUNET_TIME_absolute_get_remaining (friend->congestion_duration).rel_value_us)))
2443 * @param all_known_peers
2449 static struct Sorting_List *
2450 get_next_successor (struct Sorting_List *all_known_peers,
2451 unsigned int array_size, int start_index,
2452 int search_index, int count)
2454 struct Sorting_List *next_peer;
2456 if (search_index == start_index)
2458 next_peer = GNUNET_malloc (sizeof (struct Sorting_List));
2459 memcpy (next_peer, &all_known_peers[search_index], sizeof (struct Sorting_List));
2461 if ((next_peer->type == VALUE) ||
2462 (GNUNET_YES == check_friend_threshold_and_congestion (next_peer)))
2464 search_index = (search_index + 1) % array_size;
2466 return get_next_successor (all_known_peers, array_size, start_index, search_index, count);
2475 * @param all_known_peers
2477 * @param search_value
2481 get_friend_location (struct Sorting_List *all_known_peers, size_t array_size,
2482 uint64_t search_value)
2486 while (0 != memcmp (&all_known_peers[k], &search_value, sizeof (uint64_t)))
2490 if (k == array_size)
2491 return GNUNET_SYSERR;
2498 * Initialize all_known_peers with my_id, value, friends and fingers.
2499 * @param all_known_peers Empty all_known_peers
2500 * @param size Total number of elements in all_known_peers
2503 init_all_known_peers (struct Sorting_List *all_known_peers, int size, uint64_t value)
2505 struct GNUNET_CONTAINER_MultiPeerMapIterator *friend_iter;
2506 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
2507 struct GNUNET_PeerIdentity key_ret;
2508 struct FriendInfo *friend;
2509 struct FingerInfo *finger;
2510 unsigned int finger_index;
2511 unsigned int friend_index;
2515 for (k = 0; k < size; k++)
2516 all_known_peers[k].peer_id = 0;
2518 /* Copy your identity at 0th index in all_known_peers. */
2520 memcpy (&(all_known_peers[j].peer_id), &my_identity, sizeof (uint64_t));
2521 all_known_peers[j].type = MY_ID;
2522 all_known_peers[j].data = 0;
2526 all_known_peers[j].peer_id = value;
2527 all_known_peers[j].type = VALUE;
2528 all_known_peers[j].data = 0;
2531 /* Iterate over friend peer map and copy all the elements into array. */
2532 friend_iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
2533 for (friend_index = 0; friend_index < GNUNET_CONTAINER_multipeermap_size (friend_peermap); friend_index++)
2535 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(friend_iter,&key_ret,(const void **)&friend))
2537 memcpy (&(all_known_peers[j].peer_id), &(friend->id), sizeof (uint64_t));
2538 all_known_peers[j].type = FRIEND;
2539 all_known_peers[j].data = friend;
2545 /* Iterate over finger map and copy all the entries into all_known_peers array. */
2546 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
2547 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
2549 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(finger_iter,&key_ret,(const void **)&finger))
2551 memcpy (&(all_known_peers[j].peer_id), &(finger->finger_identity), sizeof (uint64_t));
2552 all_known_peers[j].type = FINGER;
2553 all_known_peers[j].data = finger;
2558 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
2559 GNUNET_CONTAINER_multipeermap_iterator_destroy (friend_iter);
2562 /** Find closest successor for the value.
2563 * @param value Value for which we are looking for successor
2564 * @param[out] current_destination set to my_identity in case I am the final destination,
2565 * set to friend identity in case friend is final destination,
2566 * set to first friend to reach to finger, in case finger
2567 * is final destination.
2568 * @param[out] current_source set to my_identity.
2569 * @param finger_map_index Index in finger peer map.
2570 * @return Peer identity of next hop to send trail setup message to,
2571 * NULL in case all the friends are either congested or have crossed
2572 * their trail threshold.
2574 static struct GNUNET_PeerIdentity *
2575 find_successor (uint64_t value, struct GNUNET_PeerIdentity *current_destination,
2576 struct GNUNET_PeerIdentity *current_source, unsigned int finger_map_index)
2578 struct Sorting_List *successor;
2581 size = GNUNET_CONTAINER_multipeermap_size (friend_peermap)+
2582 GNUNET_CONTAINER_multipeermap_size (finger_peermap)+
2585 struct Sorting_List all_known_peers[size];
2586 init_all_known_peers (all_known_peers, size, value);
2587 qsort (&all_known_peers, size, sizeof (struct Sorting_List), &compare_peer_id);
2589 if (PREDECESSOR_FINGER_ID == finger_map_index)
2590 successor = find_closest_predecessor (all_known_peers, value, size);
2592 successor = find_closest_successor (all_known_peers, value, size);
2594 if ((successor->type != MY_ID) && (successor->type != VALUE))
2596 if (GNUNET_YES == check_friend_threshold_and_congestion (successor))
2598 int search_index = get_friend_location (all_known_peers, size, successor->peer_id);
2599 successor = get_next_successor (all_known_peers, size, search_index, search_index + 1, 0);
2603 if (successor->type == MY_ID)
2605 memcpy (current_destination, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2606 return &my_identity;
2608 else if (successor->type == FRIEND)
2610 struct FriendInfo *target_friend = successor->data;
2611 memcpy (current_destination, &(target_friend->id), sizeof (struct GNUNET_PeerIdentity));
2612 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2613 return current_destination;
2615 else if (successor->type == FINGER)
2617 struct GNUNET_PeerIdentity *next_hop;
2618 struct FingerInfo *finger;
2619 finger = successor->data;
2620 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2622 if (finger->first_trail_length > 0)
2624 struct TrailPeerList *iterator;
2625 iterator = GNUNET_malloc (sizeof (struct TrailPeerList));
2626 iterator = finger->first_trail_head;
2627 memcpy (next_hop, &(iterator->peer), sizeof (struct GNUNET_PeerIdentity));
2629 else /* This means finger is our friend. */
2630 memcpy (next_hop, &(finger->finger_identity), sizeof(struct GNUNET_PeerIdentity));
2632 memcpy (current_destination, &(finger->finger_identity), sizeof (struct GNUNET_PeerIdentity));
2633 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2638 /* It means all the peers known to me are either congested or has crossed
2646 * FIXME: Complete the code for checking the threshold and getting the next
2647 * peer, add the case in finger.
2648 * In case a friend is either congested or has crossed its trail threshold,
2649 * then don't consider it as next successor, In case of finger if its first
2650 * friend has crossed the threshold then don't consider it. In case no finger
2651 * or friend is found, then return NULL.
2652 * Find closest successor for the value.
2653 * @param value Value for which we are looking for successor
2654 * @param[out] current_destination set to my_identity in case I am the final destination,
2655 * set to friend identity in case friend is final destination,
2656 * set to first friend to reach to finger, in case finger
2657 * is final destination.
2658 * @param[out] current_source set to my_identity.
2659 * @param finger_map_index Index in finger peer map.
2660 * @return Peer identity of next hop to send trail setup message to,
2661 * NULL in case all the friends are either congested or have crossed
2662 * their trail threshold.
2664 static struct GNUNET_PeerIdentity *
2665 find_successor (uint64_t value, struct GNUNET_PeerIdentity *current_destination,
2666 struct GNUNET_PeerIdentity *current_source, unsigned int finger_map_index)
2668 struct GNUNET_CONTAINER_MultiPeerMapIterator *friend_iter;
2669 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
2670 struct GNUNET_PeerIdentity key_ret;
2671 struct FriendInfo *friend;
2672 struct FingerInfo *finger;
2673 unsigned int finger_index;
2674 unsigned int friend_index;
2675 struct Sorting_List *successor;
2679 /* 2 is added in size for my_identity and value which will part of all_known_peers. */
2680 size = GNUNET_CONTAINER_multipeermap_size (friend_peermap)+
2681 GNUNET_CONTAINER_multipeermap_size (finger_peermap)+
2684 struct Sorting_List all_known_peers[size];
2687 for (k = 0; k < size; k++)
2688 all_known_peers[k].peer_id = 0;
2690 /* Copy your identity at 0th index in all_known_peers. */
2692 memcpy (&(all_known_peers[j].peer_id), &my_identity, sizeof (uint64_t));
2693 all_known_peers[j].type = MY_ID;
2694 all_known_peers[j].data = 0;
2698 all_known_peers[j].peer_id = value;
2699 all_known_peers[j].type = VALUE;
2700 all_known_peers[j].data = 0;
2703 /* Iterate over friend peer map and copy all the elements into array. */
2704 friend_iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
2705 for (friend_index = 0; friend_index < GNUNET_CONTAINER_multipeermap_size (friend_peermap); friend_index++)
2707 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(friend_iter,&key_ret,(const void **)&friend))
2709 memcpy (&(all_known_peers[j].peer_id), &(friend->id), sizeof (uint64_t));
2710 all_known_peers[j].type = FRIEND;
2711 all_known_peers[j].data = friend;
2717 /* Iterate over finger map and copy all the entries into all_known_peers array. */
2718 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
2719 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
2721 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(finger_iter,&key_ret,(const void **)&finger))
2723 memcpy (&(all_known_peers[j].peer_id), &(finger->finger_identity), sizeof (uint64_t));
2724 all_known_peers[j].type = FINGER;
2725 all_known_peers[j].data = finger;
2730 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
2731 GNUNET_CONTAINER_multipeermap_iterator_destroy (friend_iter);
2733 qsort (&all_known_peers, size, sizeof (struct Sorting_List), &compare_peer_id);
2735 /* search value in all_known_peers array. */
2736 if (PREDECESSOR_FINGER_ID == finger_map_index)
2737 successor = find_closest_predecessor (all_known_peers, value, size);
2739 successor = find_closest_successor (all_known_peers, value, size);
2741 if (successor->type == MY_ID)
2743 memcpy (current_destination, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2744 return &my_identity;
2746 else if (successor->type == FRIEND)
2748 struct FriendInfo *target_friend;
2749 target_friend = (struct FriendInfo *)successor->data;
2750 if( GNUNET_YES == check_friend_threshold_and_congestion (all_known_peers, size, target_friend, value))
2752 int search_index = get_friend_location (all_known_peers);
2753 get_next_successor (all_known_peers, size, search_index, search_index + 1, 0);
2755 memcpy (current_destination, &(target_friend->id), sizeof (struct GNUNET_PeerIdentity));
2756 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2757 return current_destination;
2759 else if (successor->type == FINGER)
2761 struct GNUNET_PeerIdentity *next_hop;
2762 struct FingerInfo *finger;
2763 finger = successor->data;
2764 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2766 if (finger->first_trail_length > 0)
2768 struct TrailPeerList *iterator;
2769 iterator = GNUNET_malloc (sizeof (struct TrailPeerList));
2770 iterator = finger->first_trail_head;
2771 memcpy (next_hop, &(iterator->peer), sizeof (struct GNUNET_PeerIdentity));
2773 else /* This means finger is our friend. */
2774 memcpy (next_hop, &(finger->finger_identity), sizeof(struct GNUNET_PeerIdentity));
2776 memcpy (current_destination, &(finger->finger_identity), sizeof (struct GNUNET_PeerIdentity));
2777 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2789 * Construct a Put message and send it to target_peer.
2790 * @param key Key for the content
2791 * @param data Content to store
2792 * @param data_size Size of content @a data in bytes
2793 * @param block_type Type of the block
2794 * @param options Routing options
2795 * @param desired_replication_level Desired replication count
2796 * @param expiration_time When does the content expire
2797 * @param current_destination
2798 * @param current_source
2799 * @param target_peer Peer to which this message will be forwarded.
2800 * @param hop_count Number of hops traversed so far.
2801 * @param put_path_length Total number of peers in @a put_path
2802 * @param put_path Number of peers traversed so far
2805 GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key,
2806 const void *data, size_t data_size,
2807 enum GNUNET_BLOCK_Type block_type,
2808 enum GNUNET_DHT_RouteOption options,
2809 uint32_t desired_replication_level,
2810 struct GNUNET_TIME_Absolute expiration_time,
2811 struct GNUNET_PeerIdentity current_destination,
2812 struct GNUNET_PeerIdentity current_source,
2813 struct GNUNET_PeerIdentity *target_peer,
2815 uint32_t put_path_length,
2816 struct GNUNET_PeerIdentity *put_path)
2818 struct PeerPutMessage *ppm;
2819 struct P2PPendingMessage *pending;
2820 struct FriendInfo *target_friend;
2821 struct GNUNET_PeerIdentity *pp;
2824 msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
2825 sizeof (struct PeerPutMessage);
2827 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2829 put_path_length = 0;
2830 msize = data_size + sizeof (struct PeerPutMessage);
2833 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2839 /* This is the first call made from clients file. So, we should search for the
2841 if (NULL == target_peer)
2844 struct GNUNET_PeerIdentity *next_hop;
2846 memcpy (&key_value, key, sizeof (uint64_t));
2847 next_hop = find_successor (key_value, ¤t_destination, ¤t_source,PUT_GET_REQUEST);
2848 if (0 == GNUNET_CRYPTO_cmp_peer_identity(next_hop, &my_identity)) /* I am the destination do datacache_put */
2850 GDS_DATACACHE_handle_put (expiration_time, key, put_path_length, put_path,
2851 block_type, data_size, data);
2855 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2858 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2859 pending->timeout = expiration_time;
2860 ppm = (struct PeerPutMessage *) &pending[1];
2861 pending->msg = &ppm->header;
2862 ppm->header.size = htons (msize);
2863 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
2864 ppm->options = htonl (options);
2865 ppm->block_type = htonl (block_type);
2866 ppm->hop_count = htonl (hop_count + 1);
2867 ppm->desired_replication_level = htonl (desired_replication_level);
2868 ppm->put_path_length = htonl (put_path_length);
2869 ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
2871 ppm->current_destination = current_destination;
2872 ppm->current_source = current_source;
2874 pp = (struct GNUNET_PeerIdentity *) &ppm[1];
2875 if (put_path_length != 0)
2877 memcpy (pp, put_path,
2878 sizeof (struct GNUNET_PeerIdentity) * put_path_length);
2880 memcpy (&pp[put_path_length], data, data_size);
2881 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2882 target_friend->pending_count++;
2883 process_friend_queue (target_friend);
2889 * Construct a Get message and send it to target_peer.
2890 * @param key Key for the content
2891 * @param block_type Type of the block
2892 * @param options Routing options
2893 * @param desired_replication_level Desired replication count
2894 * @param expiration_time When does the content expire
2895 * @param current_destination
2896 * @param current_source
2897 * @param target_peer Peer to which this message will be forwarded.
2898 * @param hop_count Number of hops traversed so far.
2899 * @param put_path_length Total number of peers in @a put_path
2900 * @param put_path Number of peers traversed so far
2903 GDS_NEIGHBOURS_send_get (const struct GNUNET_HashCode *key,
2904 enum GNUNET_BLOCK_Type block_type,
2905 enum GNUNET_DHT_RouteOption options,
2906 uint32_t desired_replication_level,
2907 struct GNUNET_PeerIdentity current_destination,
2908 struct GNUNET_PeerIdentity current_source,
2909 struct GNUNET_PeerIdentity *target_peer,
2911 uint32_t get_path_length,
2912 struct GNUNET_PeerIdentity *get_path)
2914 struct PeerGetMessage *pgm;
2915 struct P2PPendingMessage *pending;
2916 struct FriendInfo *target_friend;
2917 struct GNUNET_PeerIdentity *gp;
2920 msize = sizeof (struct PeerGetMessage) +
2921 (get_path_length * sizeof (struct GNUNET_PeerIdentity));
2923 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2929 if (NULL == target_peer)
2931 /* This is the first call from client file, we need to search for next_hop*/
2932 struct GNUNET_PeerIdentity *next_hop;
2935 memcpy (&key_value, key, sizeof (uint64_t));
2936 // FIXME: endianess of key_value!?
2937 next_hop = find_successor (key_value, ¤t_destination, ¤t_source,PUT_GET_REQUEST);
2938 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity,next_hop)) /* I am the destination do datacache_put */
2940 GDS_DATACACHE_handle_get (key,block_type, NULL, 0,
2941 NULL, 0, 1, &my_identity, NULL,&my_identity);
2946 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2950 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2951 pending->importance = 0; /* FIXME */
2952 pgm = (struct PeerGetMessage *) &pending[1];
2953 pending->msg = &pgm->header;
2954 pgm->header.size = htons (msize);
2955 pgm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
2956 pgm->get_path_length = htonl (get_path_length);
2958 pgm->current_destination = current_destination;
2959 pgm->current_source = current_source;
2960 pgm->hop_count = htonl (hop_count + 1);
2964 gp = (struct GNUNET_PeerIdentity *) &pgm[1];
2965 memcpy (gp, get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity));
2967 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2968 target_friend->pending_count++;
2969 process_friend_queue (target_friend);
2974 * Send the get result to requesting client.
2975 * @param expiration When will this result expire?
2976 * @param key Key of the requested data.
2977 * @param put_path_length Number of peers in @a put_path
2978 * @param put_path Path taken to put the data at its stored location.
2979 * @param type Block type
2980 * @param data_size Size of the @a data
2981 * @param data Payload to store
2982 * @param get_path Path taken to reach to the location of the key.
2983 * @param get_path_length Number of peers in @a get_path
2984 * @param next_hop Next peer to forward the message to.
2985 * @param source_peer Peer which has the data for the key.
2988 GDS_NEIGHBOURS_send_get_result (struct GNUNET_TIME_Absolute expiration,
2989 const struct GNUNET_HashCode *key,
2990 unsigned int put_path_length,
2991 const struct GNUNET_PeerIdentity *put_path,
2992 enum GNUNET_BLOCK_Type type, size_t data_size,
2994 struct GNUNET_PeerIdentity *get_path,
2995 unsigned int get_path_length,
2996 struct GNUNET_PeerIdentity *next_hop,
2997 struct GNUNET_PeerIdentity *source_peer)
2999 struct PeerGetResultMessage *get_result;
3000 struct GNUNET_PeerIdentity *get_result_path;
3001 struct GNUNET_PeerIdentity *pp;
3002 struct P2PPendingMessage *pending;
3003 struct FriendInfo *target_friend;
3004 int current_path_index;
3007 msize = get_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
3008 sizeof (struct PeerPutMessage);
3010 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
3016 if(get_path_length > 0)
3018 current_path_index = search_my_index(get_path, get_path_length);
3019 if (GNUNET_SYSERR == current_path_index)
3021 /* FIXME: This assertion always fails. FIX IT. */
3026 if (0 == current_path_index)
3028 GDS_CLIENTS_handle_reply (expiration, key, get_path_length, get_path, put_path_length,
3029 put_path, type, data_size, data);
3033 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
3034 pending->importance = 0;
3035 get_result = (struct PeerGetResultMessage *)&pending[1];
3036 pending->msg = &get_result->header;
3037 get_result->header.size = htons (msize);
3038 get_result->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT);
3039 get_result->key = *key;
3040 memcpy (&(get_result->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
3041 get_result->expiration_time = expiration;
3043 if (get_path_length != 0)
3045 get_result_path = (struct GNUNET_PeerIdentity *)&get_result[1];
3046 memcpy (get_result_path, get_path,
3047 sizeof (struct GNUNET_PeerIdentity) * get_path_length);
3049 memcpy (&get_result_path[get_path_length], data, data_size);
3051 /* FIXME: Is this correct? */
3052 if (put_path_length != 0)
3054 pp = (struct GNUNET_PeerIdentity *)&get_result_path[1];
3055 memcpy (pp, put_path,sizeof (struct GNUNET_PeerIdentity) * put_path_length);
3057 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3058 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
3059 target_friend->pending_count++;
3060 process_friend_queue (target_friend);
3065 * Send trail rejection message to the peer which sent me a trail setup message.
3066 * @param source_peer Source peer which wants to set up the trail.
3067 * @param finger_identity Value whose successor will be the finger of @a source_peer.
3068 * @param congested_peer Peer which has send trail rejection message.
3069 * @param next_hop Peer to which this message should be forwarded.
3070 * @param finger_map_index Index in @a source_peer finger peermap.
3071 * @param trail_peer_list Trail followed to reach from @a source_peer to next_hop,
3072 * NULL, in case the @a congested_peer was the first peer
3073 * to which trail setup message was forwarded.
3074 * @param trail_length Number of peers in trail_peer_list.
3077 GDS_NEIGHBOURS_send_trail_rejection (const struct GNUNET_PeerIdentity *source_peer,
3078 uint64_t finger_identity,
3079 const struct GNUNET_PeerIdentity *congested_peer,
3080 const struct GNUNET_PeerIdentity *next_hop,
3081 unsigned int finger_map_index,
3082 struct GNUNET_PeerIdentity *trail_peer_list,
3083 unsigned int trail_length,
3084 struct GNUNET_TIME_Relative congestion_timeout)
3086 struct PeerTrailRejectionMessage *trail_rejection;
3087 struct GNUNET_PeerIdentity *trail_list;
3088 struct P2PPendingMessage *pending;
3089 struct FriendInfo *target_friend;
3092 msize = trail_length * sizeof(struct GNUNET_PeerIdentity) +
3093 sizeof (struct PeerTrailRejectionMessage);
3095 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
3101 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
3102 pending->importance = 0;
3103 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
3104 trail_rejection = (struct PeerTrailRejectionMessage *) &pending[1];
3105 pending->msg = &trail_rejection->header;
3106 trail_rejection->header.size = htons (msize);
3107 trail_rejection->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
3108 memcpy (&(trail_rejection->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
3109 memcpy (&(trail_rejection->congested_peer), congested_peer, sizeof (struct GNUNET_PeerIdentity));
3110 memcpy (&(trail_rejection->finger_identity_value), &finger_identity, sizeof (uint64_t));
3111 trail_rejection->finger_map_index = htonl (finger_map_index);
3112 trail_rejection->trail_length = htonl (trail_length);
3113 trail_rejection->congestion_time = congestion_timeout;
3115 if (trail_length != 0)
3117 trail_list = (struct GNUNET_PeerIdentity *)&trail_rejection[1];
3118 memcpy (trail_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
3121 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3122 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
3123 target_friend->pending_count++;
3124 process_friend_queue (target_friend);
3129 * Core handler for P2P put messages.
3130 * @param cls closure
3131 * @param peer sender of the request
3132 * @param message message
3133 * @return #GNUNET_OK to keep the connection open,
3134 * #GNUNET_SYSERR to close it (signal serious error)
3137 handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer,
3138 const struct GNUNET_MessageHeader *message)
3140 struct PeerPutMessage *put;
3141 struct GNUNET_PeerIdentity *put_path;
3142 struct GNUNET_HashCode test_key;
3143 enum GNUNET_DHT_RouteOption options;
3144 struct GNUNET_PeerIdentity current_destination;
3145 struct GNUNET_PeerIdentity current_source;
3146 struct GNUNET_PeerIdentity *next_hop;
3150 size_t payload_size;
3153 msize = ntohs (message->size);
3154 if (msize < sizeof (struct PeerPutMessage))
3156 GNUNET_break_op (0);
3160 put = (struct PeerPutMessage *) message;
3161 putlen = ntohl (put->put_path_length);
3164 sizeof (struct PeerPutMessage) +
3165 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
3167 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3169 GNUNET_break_op (0);
3173 current_destination = put->current_destination;
3174 current_source = put->current_source;
3175 put_path = (struct GNUNET_PeerIdentity *) &put[1];
3176 payload = &put_path[putlen];
3177 options = ntohl (put->options);
3178 payload_size = msize - (sizeof (struct PeerPutMessage) +
3179 putlen * sizeof (struct GNUNET_PeerIdentity));
3181 switch (GNUNET_BLOCK_get_key (GDS_block_context, ntohl (put->block_type),
3182 payload, payload_size, &test_key))
3185 if (0 != memcmp (&test_key, &put->key, sizeof (struct GNUNET_HashCode)))
3187 char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key));
3188 GNUNET_break_op (0);
3189 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3190 "PUT with key `%s' for block with key %s\n",
3191 put_s, GNUNET_h2s_full (&test_key));
3192 GNUNET_free (put_s);
3197 GNUNET_break_op (0);
3200 /* cannot verify, good luck */
3204 if (ntohl (put->block_type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
3206 switch (GNUNET_BLOCK_evaluate (GDS_block_context,
3207 ntohl (put->block_type),
3209 NULL, 0, /* bloom filer */
3210 NULL, 0, /* xquery */
3211 payload, payload_size))
3213 case GNUNET_BLOCK_EVALUATION_OK_MORE:
3214 case GNUNET_BLOCK_EVALUATION_OK_LAST:
3217 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
3218 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
3219 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
3220 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
3221 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
3222 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
3224 GNUNET_break_op (0);
3229 struct GNUNET_PeerIdentity pp[putlen + 1];
3230 /* extend 'put path' by sender */
3231 /* FIXME: Check what are we doing here? */
3232 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
3234 memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity));
3241 memcpy (&key_value, &(put->key), sizeof (uint64_t));
3242 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_destination, &my_identity)))
3244 GDS_ROUTING_print();
3245 next_hop = GDS_ROUTING_search (¤t_source, ¤t_destination, peer);
3246 if (next_hop == NULL)
3248 /* refer to handle_dht_p2p_trail_setup. */
3253 next_hop = find_successor (key_value, ¤t_destination, ¤t_source,PUT_GET_REQUEST);
3256 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, next_hop)) /* I am the final destination */
3258 GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time),
3259 &(put->key),putlen, pp, ntohl (put->block_type),
3260 payload_size, payload);
3265 GDS_CLIENTS_process_put (options,
3266 ntohl (put->block_type),
3267 ntohl (put->hop_count),
3268 ntohl (put->desired_replication_level),
3270 GNUNET_TIME_absolute_ntoh (put->expiration_time),
3274 GDS_NEIGHBOURS_send_put (&put->key, payload, payload_size,
3275 ntohl (put->block_type),ntohl (put->options),
3276 ntohl (put->desired_replication_level),
3277 GNUNET_TIME_absolute_ntoh (put->expiration_time),
3278 current_destination, current_source, next_hop,
3279 ntohl (put->hop_count), putlen, pp);
3283 return GNUNET_SYSERR;
3288 * Core handler for p2p get requests.
3290 * @param cls closure
3291 * @param peer sender of the request
3292 * @param message message
3293 * @return #GNUNET_OK to keep the connection open,
3294 * #GNUNET_SYSERR to close it (signal serious error)
3297 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
3298 const struct GNUNET_MessageHeader *message)
3300 struct PeerGetMessage *get;
3301 struct GNUNET_PeerIdentity *get_path;
3302 struct GNUNET_PeerIdentity current_destination;
3303 struct GNUNET_PeerIdentity current_source;
3304 struct GNUNET_PeerIdentity *next_hop;
3305 uint32_t get_length;
3309 msize = ntohs (message->size);
3310 if (msize < sizeof (struct PeerGetMessage))
3312 GNUNET_break_op (0);
3316 get = (struct PeerGetMessage *)message;
3317 get_length = ntohl (get->get_path_length);
3318 get_path = (struct GNUNET_PeerIdentity *)&get[1];
3319 current_destination = get->current_destination;
3320 current_source = get->current_source;
3323 sizeof (struct PeerGetMessage) +
3324 get_length * sizeof (struct GNUNET_PeerIdentity)) ||
3326 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3328 GNUNET_break_op (0);
3332 /* Add sender to get path */
3333 struct GNUNET_PeerIdentity gp[get_length + 1];
3334 memcpy (gp, get_path, get_length * sizeof (struct GNUNET_PeerIdentity));
3335 gp[get_length + 1] = *peer;
3336 get_length = get_length + 1;
3338 memcpy (&key_value, &(get->key), sizeof (uint64_t));
3339 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_destination, &my_identity)))
3341 GDS_ROUTING_print();
3342 next_hop = GDS_ROUTING_search (¤t_source, ¤t_destination, peer);
3343 if (next_hop == NULL)
3345 /* refer to handle_dht_p2p_trail_setup. */
3350 next_hop = find_successor (key_value, ¤t_destination, ¤t_source,PUT_GET_REQUEST);
3353 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, next_hop))
3355 /* I am the destination.*/
3356 struct GNUNET_PeerIdentity final_get_path[get_length+1];
3357 struct GNUNET_PeerIdentity next_hop;
3359 memcpy (final_get_path, gp, get_length * sizeof (struct GNUNET_PeerIdentity));
3360 memcpy (&final_get_path[get_length+1], &my_identity, sizeof (struct GNUNET_PeerIdentity));
3361 get_length = get_length + 1;
3362 memcpy (&next_hop, &final_get_path[get_length-2], sizeof (struct GNUNET_PeerIdentity));
3363 GDS_DATACACHE_handle_get (&(get->key),(get->block_type), NULL, 0, NULL, 0,
3364 get_length, final_get_path,&next_hop, &my_identity);
3370 GDS_NEIGHBOURS_send_get (&(get->key), get->block_type, get->options,
3371 get->desired_replication_level,current_destination,
3372 current_source, next_hop, 0,
3375 return GNUNET_SYSERR;
3380 * FIXME: In case of trail, we don't have source and destination part of the trail,
3381 * Check if we follow the same in case of get/put/get_result. Also, in case of
3382 * put should we do a routing table add.
3383 * Core handler for get result
3384 * @param cls closure
3385 * @param peer sender of the request
3386 * @param message message
3387 * @return #GNUNET_OK to keep the connection open,
3388 * #GNUNET_SYSERR to close it (signal serious error)
3391 handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer,
3392 const struct GNUNET_MessageHeader *message)
3394 struct PeerGetResultMessage *get_result;
3395 struct GNUNET_PeerIdentity *get_path;
3396 struct GNUNET_PeerIdentity *put_path;
3398 size_t payload_size;
3400 unsigned int getlen;
3401 unsigned int putlen;
3402 int current_path_index;
3404 msize = ntohs (message->size);
3405 if (msize < sizeof (struct PeerGetResultMessage))
3407 GNUNET_break_op (0);
3411 get_result = (struct PeerGetResultMessage *)message;
3412 getlen = ntohl (get_result->get_path_length);
3413 putlen = ntohl (get_result->put_path_length);
3416 sizeof (struct PeerGetResultMessage) +
3417 getlen * sizeof (struct GNUNET_PeerIdentity) +
3418 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
3420 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity) ||
3422 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))))
3424 GNUNET_break_op (0);
3428 get_path = (struct GNUNET_PeerIdentity *) &get_result[1];
3429 payload = &get_path[getlen];
3430 payload_size = msize - (sizeof (struct PeerGetResultMessage) +
3431 getlen * sizeof (struct GNUNET_PeerIdentity));
3432 /* FIXME: Check if its correct or not. */
3435 put_path = &get_path[1];
3439 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &(get_path[0]))))
3441 GDS_CLIENTS_handle_reply (get_result->expiration_time, &(get_result->key),
3442 getlen, get_path, putlen,
3443 put_path, get_result->type, payload_size, payload);
3448 struct GNUNET_PeerIdentity *next_hop;
3449 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
3450 /* FIXME: handle the case when current_path_index = GNUNET_SYSERR;*/
3451 current_path_index = search_my_index (get_path, getlen);
3452 /* FIXME: First check if you are adding yourself to the get path or not.
3453 if yes then don't check if current_path_index == 0, if not then check
3454 and next_hop == source_peer. */
3455 memcpy (next_hop, &get_path[current_path_index - 1], sizeof (struct GNUNET_PeerIdentity));
3457 GDS_NEIGHBOURS_send_get_result (get_result->expiration_time, &(get_result->key),
3459 get_result->type, payload_size,payload,
3461 next_hop, &(get_result->source_peer));
3464 return GNUNET_SYSERR;
3469 * FIXME: URGENT: refactor it.
3470 * FIXME; now we can make a new ds to store 2 peers and one value as we are
3471 * using it at two places. Will complete the logic and then add a new ds.
3472 * In case finger map index is 64 do we need to call find_closest_predecessor?
3473 * Select the closest peer.
3475 * @param current_destination
3476 * @param current_source
3478 * @para finger_map_index
3479 * @return Peer which is closest, in case of error NULL.
3481 struct GNUNET_PeerIdentity *
3482 select_closest_peer (const struct GNUNET_PeerIdentity *prev_hop,
3483 struct GNUNET_PeerIdentity *current_destination,
3484 struct GNUNET_PeerIdentity *current_source,
3486 unsigned int finger_map_index)
3488 struct GNUNET_PeerIdentity *peer1;
3489 struct GNUNET_PeerIdentity *peer2;
3490 struct Sorting_List peers[3];
3491 struct Sorting_List *closest_finger;
3493 peer1 = GDS_ROUTING_search (current_source, current_destination, prev_hop);
3494 peer2 = find_successor (value, current_destination, current_source,finger_map_index);
3496 /* SUPU TEST CODE */
3497 struct GNUNET_PeerIdentity print_peer;
3498 memcpy (&print_peer, &peer1, sizeof (struct GNUNET_PeerIdentity));
3499 FPRINTF (stderr,_("\nSUPU %s, %s, %d,routing_peer = %s"), __FILE__, __func__,__LINE__,GNUNET_i2s(&print_peer));
3500 memcpy (&print_peer, &peer2, sizeof (struct GNUNET_PeerIdentity));
3501 FPRINTF (stderr,_("\nSUPU %s, %s, %d,find_successor_peer = %s"), __FILE__, __func__,__LINE__,GNUNET_i2s(&print_peer));
3502 /* SUPU TEST CODE ENDS*/
3503 if( (peer1 != NULL) && (peer2 != NULL))
3505 /* Add peer 1 to the list. */
3506 memcpy (&peers[0], &peer1, sizeof (uint64_t));
3507 peers[0].type = FINGER;
3508 peers[0].data = NULL;
3510 /* Add peer 2 to the list. */
3511 memcpy (&peers[1], &peer1, sizeof (uint64_t));
3512 peers[0].type = FRIEND;
3513 peers[0].data = NULL;
3515 /* Add value to the list. */
3516 memcpy (&peers[2], &peer1, sizeof (uint64_t));
3517 peers[0].type = VALUE;
3518 peers[0].data = NULL;
3520 qsort (&peers, 3, sizeof (struct Sorting_List), &compare_peer_id);
3521 if (PREDECESSOR_FINGER_ID == finger_map_index)
3522 closest_finger = find_closest_predecessor (peers, value, 3);
3524 closest_finger = find_closest_successor (peers, value, 3);
3527 if (closest_finger->type == FINGER)
3529 FPRINTF (stderr,_("\nSUPU %s, %s, %d"), __FILE__, __func__,__LINE__);
3532 else if (closest_finger->type == VALUE)
3536 else if (closest_finger->type == FRIEND);
3538 /* If we are returning peer2 then find_successor has already taken care
3539 of setting up current_destination and current_source. */
3543 else if ((peer1 == NULL) && (peer2 == NULL))
3547 else if (peer1 == NULL)
3551 else if (peer2 == NULL)
3560 * Core handle for PeerTrailSetupMessage.
3561 * @param cls closure
3562 * @param message message
3563 * @param peer peer identity this notification is about
3564 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3567 handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer,
3568 const struct GNUNET_MessageHeader *message)
3570 const struct PeerTrailSetupMessage *trail_setup;
3571 struct GNUNET_PeerIdentity current_destination;
3572 struct GNUNET_PeerIdentity current_source;
3573 struct GNUNET_PeerIdentity source;
3574 struct GNUNET_PeerIdentity *next_hop;
3575 struct GNUNET_PeerIdentity next_peer;
3576 struct GNUNET_PeerIdentity *trail_peer_list;
3577 struct FriendInfo *target_friend;
3578 uint64_t destination_finger_value;
3579 uint32_t trail_length;
3580 uint32_t finger_map_index;
3583 msize = ntohs (message->size);
3584 if (msize < sizeof (struct PeerTrailSetupMessage))
3586 GNUNET_break_op (0);
3590 trail_setup = (const struct PeerTrailSetupMessage *) message;
3591 trail_length = ntohl (trail_setup->trail_length);
3593 if ((msize < sizeof (struct PeerTrailSetupMessage) +
3594 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3596 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3598 GNUNET_break_op (0);
3602 if (trail_length > 0)
3603 trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_setup[1];
3604 memcpy (¤t_destination, &(trail_setup->current_destination), sizeof (struct GNUNET_PeerIdentity));
3605 memcpy (¤t_source,&(trail_setup->current_source), sizeof (struct GNUNET_PeerIdentity));
3606 memcpy (&source, &(trail_setup->source_peer), sizeof (struct GNUNET_PeerIdentity));
3607 finger_map_index = ntohl (trail_setup->finger_map_index);
3608 destination_finger_value = ntohl (trail_setup->destination_finger);
3610 /* Check your routing table size, and if you can handle any more trails through you. */
3611 if (GNUNET_YES == GDS_ROUTING_check_threshold())
3613 GDS_NEIGHBOURS_send_trail_rejection (&source, destination_finger_value, &my_identity,
3614 peer, finger_map_index, trail_peer_list, trail_length,
3615 CONGESTION_TIMEOUT);
3619 /* Check if you are current_destination or not. */
3620 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_destination, &my_identity)))
3622 next_hop = select_closest_peer (peer, ¤t_destination, ¤t_source,
3623 destination_finger_value, finger_map_index);
3627 next_hop = find_successor (destination_finger_value, ¤t_destination,
3628 ¤t_source,finger_map_index);
3631 if (NULL == next_hop)
3633 GNUNET_STATISTICS_update (GDS_stats,
3634 gettext_noop ("# Trail not found in routing table during"
3635 "trail setup request, packet dropped."),
3637 return GNUNET_SYSERR;
3639 else if (0 == (GNUNET_CRYPTO_cmp_peer_identity (next_hop, &my_identity)))/* This means I am the final destination */
3641 if (trail_length == 0)
3643 memcpy (&next_peer, &source, sizeof (struct GNUNET_PeerIdentity));
3647 memcpy (&next_peer, &trail_peer_list[trail_length-1], sizeof (struct GNUNET_PeerIdentity));
3650 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer);
3651 GDS_NEIGHBOURS_send_trail_setup_result (&source,
3653 target_friend, trail_length,
3660 /* Now add yourself to the trail. */
3661 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
3662 if (trail_length != 0)
3663 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
3664 peer_list[trail_length] = my_identity;
3666 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3667 GDS_NEIGHBOURS_send_trail_setup (&source,
3668 destination_finger_value,
3669 ¤t_destination, ¤t_source,
3670 target_friend, trail_length, peer_list,
3678 * Core handle for p2p trail construction result messages.
3680 * @param message message
3681 * @param peer peer identity this notification is about
3682 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3685 handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer,
3686 const struct GNUNET_MessageHeader *message)
3688 const struct PeerTrailSetupResultMessage *trail_result;
3689 struct GNUNET_PeerIdentity *trail_peer_list;
3690 struct GNUNET_PeerIdentity destination_peer;
3691 struct GNUNET_PeerIdentity finger_identity;
3692 uint32_t trail_length;
3693 uint32_t finger_map_index;
3696 msize = ntohs (message->size);
3697 if (msize < sizeof (struct PeerTrailSetupResultMessage))
3699 GNUNET_break_op (0);
3703 trail_result = (const struct PeerTrailSetupResultMessage *) message;
3704 trail_length = ntohl (trail_result->trail_length);
3707 sizeof (struct PeerTrailSetupResultMessage) +
3708 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3710 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3712 GNUNET_break_op (0);
3716 finger_map_index = htonl (trail_result->finger_map_index);
3717 memcpy (&destination_peer, &(trail_result->destination_peer), sizeof (struct GNUNET_PeerIdentity));
3718 memcpy (&finger_identity, &(trail_result->finger_identity), sizeof (struct GNUNET_PeerIdentity));
3720 if (trail_length > 0)
3721 trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_result[1];
3724 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->destination_peer),
3727 finger_table_add (&(trail_result->finger_identity), trail_peer_list, trail_length,
3733 struct GNUNET_PeerIdentity next_hop;
3734 struct FriendInfo *target_friend;
3737 my_index = search_my_index (trail_peer_list, trail_length);
3738 if (my_index == GNUNET_SYSERR)
3739 return GNUNET_SYSERR;
3743 next_hop = trail_result->destination_peer;
3746 next_hop = trail_peer_list[my_index - 1];
3748 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->destination_peer),
3749 &(trail_result->finger_identity))))
3751 struct GNUNET_PeerIdentity *routing_next_hop;
3753 routing_next_hop = GDS_ROUTING_search (&destination_peer,&finger_identity,
3755 if ((NULL == routing_next_hop) ||
3756 (0 != GNUNET_CRYPTO_cmp_peer_identity(routing_next_hop, &next_hop)))
3758 GDS_ROUTING_add (&(trail_result->destination_peer), &(trail_result->finger_identity),
3761 GDS_ROUTING_print();
3764 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3765 GDS_NEIGHBOURS_send_trail_setup_result (&(trail_result->destination_peer),
3766 &(trail_result->finger_identity),
3767 target_friend, trail_length,
3772 return GNUNET_SYSERR;
3777 * Get my current predecessor from the finger peer map
3778 * @return Current predecessor.
3780 static struct FingerInfo *
3783 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
3784 struct GNUNET_PeerIdentity key_ret;
3785 unsigned int finger_index;
3786 struct FingerInfo *my_predecessor;
3789 /* Iterate over finger peer map and extract your predecessor. */
3790 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
3791 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
3793 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next
3794 (finger_iter,&key_ret,(const void **)&my_predecessor))
3796 if(PREDECESSOR_FINGER_ID == my_predecessor->finger_map_index)
3803 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
3808 return my_predecessor;
3813 * Core handle for p2p verify successor messages.
3814 * @param cls closure
3815 * @param message message
3816 * @param peer peer identity this notification is about
3817 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3820 handle_dht_p2p_verify_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
3821 const struct GNUNET_MessageHeader *message)
3823 const struct PeerVerifySuccessorMessage *vsm;
3824 const struct GNUNET_PeerIdentity *trail_peer_list;
3825 struct GNUNET_PeerIdentity source_peer;
3826 struct GNUNET_PeerIdentity next_hop;
3827 struct FriendInfo *target_friend;
3829 uint32_t trail_length;
3831 msize = ntohs (message->size);
3832 if (msize < sizeof (struct PeerVerifySuccessorMessage))
3834 GNUNET_break_op (0);
3838 vsm = (struct PeerVerifySuccessorMessage *) message;
3839 trail_length = ntohl (vsm->trail_length);
3841 if ((msize < sizeof (struct PeerVerifySuccessorMessage) +
3842 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3843 (trail_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3845 GNUNET_break_op (0);
3848 if (trail_length > 0)
3849 trail_peer_list = (const struct GNUNET_PeerIdentity *)&vsm[1];
3850 memcpy (&source_peer, &(vsm->source_peer), sizeof(struct GNUNET_PeerIdentity));
3852 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsm->successor),&my_identity)))
3854 struct FingerInfo *my_predecessor;
3855 if (trail_length == 0)
3857 memcpy (&next_hop, &source_peer, sizeof (struct GNUNET_PeerIdentity));
3861 memcpy (&next_hop, &trail_peer_list[trail_length-1], sizeof (struct GNUNET_PeerIdentity));
3863 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3865 my_predecessor = get_predecessor();
3866 if (NULL == my_predecessor)
3868 /* FIXME: should we just return. */
3872 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&source_peer,
3873 &(my_predecessor->finger_identity))))
3875 /* Source peer and my predecessor, both are same. */
3876 GDS_NEIGHBOURS_send_verify_successor_result (&source_peer,
3878 &(my_predecessor->finger_identity),
3885 struct GNUNET_PeerIdentity *new_successor_trail;
3886 struct TrailPeerList *iterator;
3887 int new_trail_length;
3890 new_trail_length = trail_length + my_predecessor->first_trail_length + 1;
3891 new_successor_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * new_trail_length);
3892 if (trail_length > 0)
3893 memcpy (new_successor_trail, trail_peer_list, (trail_length) * sizeof (struct GNUNET_PeerIdentity));
3895 memcpy (&new_successor_trail[trail_length], &my_identity, sizeof (struct GNUNET_PeerIdentity));
3897 if (my_predecessor->first_trail_length)
3899 iterator = GNUNET_malloc (sizeof (struct TrailPeerList));
3900 iterator = my_predecessor->first_trail_head;
3901 i = trail_length + 1;
3902 while (i < new_trail_length)
3904 memcpy (&new_successor_trail[i], &(iterator->peer), sizeof (struct GNUNET_PeerIdentity));
3905 iterator = iterator->next;
3909 GDS_NEIGHBOURS_send_verify_successor_result (&source_peer,
3911 &(my_predecessor->finger_identity),
3913 new_successor_trail,
3922 if (trail_length == 0)
3925 return GNUNET_SYSERR;
3928 my_index = search_my_index (trail_peer_list, trail_length);
3929 if (my_index == GNUNET_SYSERR)
3932 return GNUNET_SYSERR;
3934 if (my_index == (trail_length - 1))
3936 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &(vsm->successor));
3940 memcpy (&next_hop, &trail_peer_list[my_index + 1], sizeof (struct GNUNET_PeerIdentity));
3941 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3944 GDS_NEIGHBOURS_send_verify_successor (&(vsm->source_peer), &(vsm->successor),target_friend,
3945 trail_peer_list, trail_length);
3947 return GNUNET_SYSERR;
3952 * Core handle for p2p verify successor result messages.
3953 * @param cls closure
3954 * @param message message
3955 * @param peer peer identity this notification is about
3956 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3959 handle_dht_p2p_verify_successor_result(void *cls, const struct GNUNET_PeerIdentity *peer,
3960 const struct GNUNET_MessageHeader *message)
3962 const struct PeerVerifySuccessorResultMessage *vsrm;
3963 struct GNUNET_PeerIdentity *trail_peer_list;
3964 struct GNUNET_PeerIdentity next_hop;
3965 struct FriendInfo *target_friend;
3967 uint32_t trail_length;
3969 msize = ntohs (message->size);
3970 if (msize < sizeof (struct PeerVerifySuccessorResultMessage))
3972 GNUNET_break_op (0);
3975 vsrm = (const struct PeerVerifySuccessorResultMessage *) message;
3976 trail_length = ntohl (vsrm->trail_length);
3979 sizeof (struct PeerVerifySuccessorResultMessage) +
3980 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3982 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3984 GNUNET_break_op (0);
3988 if (trail_length > 0)
3989 trail_peer_list = (struct GNUNET_PeerIdentity *) &vsrm[1];
3991 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->destination_peer), &(my_identity))))
3993 if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->my_predecessor), &(my_identity))))
3995 if (GNUNET_YES == finger_table_add (&(vsrm->my_predecessor), trail_peer_list, trail_length, 0))
3997 memcpy (&next_hop, &trail_peer_list[0], sizeof (struct GNUNET_PeerIdentity));
3998 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3999 /* FIXME: first call scan_and_compress_trail and then call the notify new
4000 successor with new trail. */
4001 GDS_NEIGHBOURS_send_notify_new_successor (&my_identity, &(vsrm->my_predecessor),
4002 &(vsrm->source_successor),
4003 target_friend, trail_peer_list,
4015 my_index = search_my_index (trail_peer_list, trail_length);
4016 if (GNUNET_SYSERR == my_index)
4019 return GNUNET_SYSERR;
4024 memcpy (&next_hop, &(vsrm->destination_peer), sizeof (struct GNUNET_PeerIdentity));
4028 memcpy (&next_hop, &trail_peer_list[my_index-1], sizeof (struct GNUNET_PeerIdentity));
4031 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
4032 GDS_NEIGHBOURS_send_verify_successor_result (&(vsrm->destination_peer),
4033 &(vsrm->source_successor),
4034 &(vsrm->my_predecessor),
4040 return GNUNET_SYSERR;
4045 * Core handle for p2p notify new successor messages.
4046 * @param cls closure
4047 * @param message message
4048 * @param peer peer identity this notification is about
4049 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4052 handle_dht_p2p_notify_new_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
4053 const struct GNUNET_MessageHeader *message)
4055 const struct PeerNotifyNewSuccessorMessage *nsm;
4056 struct GNUNET_PeerIdentity *trail_peer_list;
4057 struct GNUNET_PeerIdentity source_peer;
4058 struct GNUNET_PeerIdentity old_successor;
4059 struct GNUNET_PeerIdentity new_successor;
4061 uint32_t trail_length;
4063 msize = ntohs (message->size);
4064 if (msize < sizeof (struct PeerNotifyNewSuccessorMessage))
4066 GNUNET_break_op (0);
4069 nsm = (const struct PeerNotifyNewSuccessorMessage *) message;
4070 trail_length = ntohl (nsm->trail_length);
4072 if ((msize < sizeof (struct PeerNotifyNewSuccessorMessage) +
4073 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
4075 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
4077 GNUNET_break_op (0);
4081 if( trail_length > 0)
4082 trail_peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
4083 memcpy (&source_peer, &(nsm->source_peer), sizeof (struct GNUNET_PeerIdentity));
4084 memcpy (&old_successor, &(nsm->old_successor), sizeof (struct GNUNET_PeerIdentity));
4085 memcpy (&new_successor, &(nsm->destination_peer), sizeof (struct GNUNET_PeerIdentity));
4087 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&new_successor, &my_identity)))
4089 /* I am the new successor. */
4090 struct GNUNET_PeerIdentity *new_predecessor;
4091 new_predecessor = GNUNET_new (struct GNUNET_PeerIdentity);
4092 memcpy (new_predecessor, &(nsm->source_peer), sizeof (struct GNUNET_PeerIdentity));
4093 if (GNUNET_YES == finger_table_add (new_predecessor, trail_peer_list, trail_length, PREDECESSOR_FINGER_ID))
4095 /* You are adding a new predecessor in your finger table. but the intermediate
4096 peers don't have an entry in their routing table. So, you need to check the
4097 return value of finger_table_Add and if its successful then you should send
4098 routing_add_message. */
4104 struct FriendInfo *target_friend;
4105 struct GNUNET_PeerIdentity next_hop;
4108 if (trail_length == 0)
4109 return GNUNET_SYSERR;
4111 my_index = search_my_index (trail_peer_list, trail_length);
4112 if (GNUNET_SYSERR == my_index)
4114 /* FIXME: happend once */
4116 return GNUNET_SYSERR;
4119 if (my_index == (trail_length - 1))
4121 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &(nsm->destination_peer));
4125 memcpy (&next_hop, &trail_peer_list[my_index+1], sizeof (struct GNUNET_PeerIdentity));
4126 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
4129 GDS_ROUTING_remove_trail (&source_peer, &old_successor, peer);
4130 GDS_ROUTING_add (&(nsm->source_peer), &(nsm->destination_peer), &next_hop, peer);
4131 GDS_NEIGHBOURS_send_notify_new_successor (&(nsm->source_peer),
4132 &(nsm->destination_peer),
4133 &(nsm->old_successor),
4134 target_friend, trail_peer_list,
4138 return GNUNET_SYSERR;
4142 * FIXME: pass congestion time in struct PeerTrailRejectionMessage,
4143 * we are calling exact same thing here as in handle_dht_p2p_trail_seutp.set
4145 * if we make it a function then we can it here.
4146 * Core handler for P2P trail rejection message
4147 * @param cls closure
4148 * @param message message
4149 * @param peer peer identity this notification is about
4150 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4153 int handle_dht_p2p_trail_rejection(void *cls, const struct GNUNET_PeerIdentity *peer,
4154 const struct GNUNET_MessageHeader *message)
4156 const struct PeerTrailRejectionMessage *trail_rejection;
4157 struct GNUNET_PeerIdentity *trail_peer_list;
4158 struct FriendInfo *target_friend;
4159 struct GNUNET_PeerIdentity next_hop;
4160 struct GNUNET_PeerIdentity *next_peer;
4161 struct GNUNET_PeerIdentity source;
4162 struct GNUNET_PeerIdentity current_destination;
4163 struct GNUNET_PeerIdentity current_source;
4164 uint32_t trail_length;
4165 uint32_t finger_map_index;
4166 uint64_t destination_finger_value;
4167 struct GNUNET_TIME_Relative congestion_timeout;
4170 msize = ntohs (message->size);
4171 if (msize < sizeof (struct PeerTrailRejectionMessage))
4173 GNUNET_break_op (0);
4177 trail_rejection = (struct PeerTrailRejectionMessage *) message;
4178 trail_length = ntohl (trail_rejection->trail_length);
4180 if ((msize < sizeof (struct PeerTrailRejectionMessage) +
4181 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
4183 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
4185 GNUNET_break_op (0);
4189 if (trail_length > 0)
4190 trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_rejection[1];
4191 finger_map_index = ntohl (trail_rejection->finger_map_index);
4192 memcpy (&destination_finger_value, &(trail_rejection->finger_identity_value), sizeof (uint64_t));
4193 memcpy (&source, &(trail_rejection->source_peer), sizeof (struct GNUNET_PeerIdentity));
4194 congestion_timeout = trail_rejection->congestion_time;
4196 /* First set the congestion time of the friend that sent you this message. */
4197 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
4198 target_friend->congestion_duration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(),
4199 congestion_timeout);
4201 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &(trail_rejection->source_peer))))
4206 if(GNUNET_YES == GDS_ROUTING_check_threshold())
4208 struct GNUNET_PeerIdentity *new_trail;
4209 unsigned int new_trail_length;
4211 if (trail_length == 1)
4214 new_trail_length = 0;
4215 memcpy (&next_hop, &(trail_rejection->source_peer), sizeof (struct GNUNET_PeerIdentity));
4219 memcpy (&next_hop, &trail_peer_list[trail_length - 2], sizeof (struct GNUNET_PeerIdentity));
4220 /* Remove myself from the trail. */
4221 new_trail_length = trail_length -1;
4222 new_trail = GNUNET_malloc (new_trail_length * sizeof (struct GNUNET_PeerIdentity));
4223 memcpy (new_trail, trail_peer_list, new_trail_length * sizeof (struct GNUNET_PeerIdentity));
4225 GDS_NEIGHBOURS_send_trail_rejection (&(trail_rejection->source_peer),
4226 destination_finger_value,
4227 &my_identity, &next_hop,finger_map_index,
4228 new_trail,new_trail_length, CONGESTION_TIMEOUT);
4233 memcpy (¤t_destination, &my_identity, sizeof (struct GNUNET_PeerIdentity));
4234 memcpy (¤t_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
4235 next_peer = find_successor (destination_finger_value,¤t_destination,
4236 ¤t_source, finger_map_index);
4237 if (NULL == next_peer)
4239 GNUNET_STATISTICS_update (GDS_stats,
4240 gettext_noop ("# Trail not found in routing table during"
4241 "trail setup request, packet dropped."),
4243 return GNUNET_SYSERR;
4245 else if (0 == (GNUNET_CRYPTO_cmp_peer_identity (next_peer, &my_identity)))/* This means I am the final destination */
4247 if (trail_length == 0)
4249 memcpy (&next_hop, &source, sizeof (struct GNUNET_PeerIdentity));
4253 memcpy (&next_hop, &trail_peer_list[trail_length-1], sizeof (struct GNUNET_PeerIdentity));
4255 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
4256 GDS_NEIGHBOURS_send_trail_setup_result (&source,
4258 target_friend, trail_length,
4265 /* Now add yourself to the trail. */
4266 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
4267 if (trail_length != 0)
4268 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
4269 peer_list[trail_length] = my_identity;
4271 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
4272 GDS_NEIGHBOURS_send_trail_setup (&source,
4273 destination_finger_value,
4274 ¤t_destination, ¤t_source,
4275 target_friend, trail_length, peer_list,
4284 /* FIXME: there is a loop between in call from notify new successor to this function
4285 * check why and fix it.
4286 * Core handle for p2p trail tear down messages.
4287 * @param cls closure
4288 * @param message message
4289 * @param peer peer identity this notification is about
4290 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4293 int handle_dht_p2p_trail_teardown (void *cls, const struct GNUNET_PeerIdentity *peer,
4294 const struct GNUNET_MessageHeader *message)
4296 struct PeerTrailTearDownMessage *trail_teardown;
4297 struct GNUNET_PeerIdentity *discarded_trail;
4298 struct GNUNET_PeerIdentity next_hop;
4299 struct FriendInfo *target_friend;
4300 uint32_t discarded_trail_length;
4304 msize = ntohs (message->size);
4305 if (msize < sizeof (struct PeerTrailTearDownMessage))
4307 GNUNET_break_op (0);
4311 trail_teardown = (struct PeerTrailTearDownMessage *) message;
4312 discarded_trail_length = ntohl (trail_teardown->trail_length);
4314 if ((msize < sizeof (struct PeerTrailTearDownMessage) +
4315 discarded_trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
4316 (discarded_trail_length >
4317 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
4319 GNUNET_break_op (0);
4323 if (discarded_trail_length > 0)
4324 discarded_trail = (struct GNUNET_PeerIdentity *) &trail_teardown[1];
4326 /* SUPU TEST CODE */
4327 struct GNUNET_PeerIdentity print_peer;
4329 while ( k < discarded_trail_length)
4331 memcpy (&print_peer, &discarded_trail[k], sizeof (struct GNUNET_PeerIdentity));
4332 FPRINTF (stderr,_("\nSUPU %s, %s, %d,discarded_trail[%d]=%s"),
4333 __FILE__, __func__,__LINE__,k,GNUNET_i2s(&print_peer));
4336 /* SUPU TEST CODE ENDS*/
4337 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_teardown->new_first_friend),
4340 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_teardown->destination_peer),
4348 * I am the new first hop in the trail to reach from source to destination.
4349 Update the trail in routing table with prev_hop == source peer. */
4350 return GDS_ROUTING_trail_update (&(trail_teardown->source_peer),
4351 &(trail_teardown->destination_peer), peer);
4356 /* This should always be the case. */
4357 if (discarded_trail_length > 0)
4359 my_index = search_my_index (discarded_trail, discarded_trail_length);
4360 if(GNUNET_SYSERR == my_index)
4361 return GNUNET_SYSERR;
4366 return GNUNET_SYSERR;
4368 GDS_ROUTING_print();
4369 if (GNUNET_NO == GDS_ROUTING_remove_trail (&(trail_teardown->source_peer),
4370 &(trail_teardown->destination_peer),peer))
4372 /* Here we get GNUNET_NO, only if there is no matching entry found in routing
4378 /* In case we got this message when we removed an entry from finger table,
4379 then we need to send the message to destination. */
4380 if (my_index != (discarded_trail_length - 1))
4381 memcpy (&next_hop, &discarded_trail[my_index + 1], sizeof (struct GNUNET_PeerIdentity));
4383 memcpy (&next_hop, &(trail_teardown->destination_peer), sizeof (struct GNUNET_PeerIdentity));
4384 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
4386 GDS_NEIGHBOURS_send_trail_teardown (&(trail_teardown->source_peer),
4387 &(trail_teardown->destination_peer),
4388 discarded_trail, discarded_trail_length,
4389 target_friend, &(trail_teardown->new_first_friend));
4392 return GNUNET_SYSERR;
4396 * Core handle for p2p routing table add messages.
4397 * @param cls closure
4398 * @param message message
4399 * @param peer peer identity this notification is about
4400 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4403 handle_dht_p2p_add_trail (void *cls, const struct GNUNET_PeerIdentity *peer,
4404 const struct GNUNET_MessageHeader *message)
4406 /* This function is called in case when we update our predecessor as a new peer
4407 claims to be our successor. In that case as we did not do a trail setup,
4408 intermediate nodes don't know about this trail. our predecessor has added
4409 that trail but not we. So, we need to add it. Its only in case of predecessor
4410 and succcessor that we have a symmetric relation. */
4411 struct PeerAddTrailMessage *add_trail;
4412 struct GNUNET_PeerIdentity *trail;
4413 struct GNUNET_PeerIdentity next_hop;
4414 struct FriendInfo *target_friend;
4416 uint32_t trail_length;
4419 msize = ntohs (message->size);
4420 if (msize < sizeof (struct PeerAddTrailMessage))
4422 GNUNET_break_op (0);
4426 add_trail = (struct PeerAddTrailMessage *) message;
4427 trail_length = ntohl (add_trail->trail_length);
4429 if ((msize < sizeof (struct PeerAddTrailMessage) +
4430 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
4432 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
4434 GNUNET_break_op (0);
4438 if (trail_length > 0)
4439 trail = (struct GNUNET_PeerIdentity *)&add_trail[1];
4441 my_index = search_my_index (trail, trail_length);
4442 if (GNUNET_SYSERR == my_index)
4445 return GNUNET_SYSERR;
4448 memcpy(&next_hop, &(add_trail->source_peer), sizeof (struct GNUNET_PeerIdentity));
4450 memcpy (&next_hop, &trail[my_index - 1], sizeof (struct GNUNET_PeerIdentity));
4452 if (GNUNET_YES == GDS_ROUTING_add (&(add_trail->source_peer), &(add_trail->destination_peer),
4457 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
4458 GDS_NEIGHBOURS_send_add_trail_message (&(add_trail->source_peer),
4459 &(add_trail->destination_peer),
4460 trail, trail_length,target_friend);
4466 /* FIXME: there is not space in routing table to add the trail. What should
4468 return GNUNET_SYSERR;
4474 * FIXME: Adapt the code for List of trails.
4475 * Iterate over finger_peermap, and remove entries with peer as the first element
4477 * @param cls closure
4478 * @param key current public key
4479 * @param value value in the hash map
4480 * @return #GNUNET_YES if we should continue to
4482 * #GNUNET_NO if not.
4485 remove_matching_finger (void *cls,
4486 const struct GNUNET_PeerIdentity *key,
4489 struct FingerInfo *remove_finger = value;
4490 const struct GNUNET_PeerIdentity *disconnected_peer = cls;
4492 if (remove_finger->first_trail_length > 0)
4494 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&remove_finger->first_trail_head->peer, disconnected_peer))
4496 GNUNET_assert (GNUNET_YES ==
4497 GNUNET_CONTAINER_multipeermap_remove (finger_peermap,
4500 free_finger (remove_finger);
4503 else if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(remove_finger->finger_identity),
4506 GNUNET_assert (GNUNET_YES ==
4507 GNUNET_CONTAINER_multipeermap_remove (finger_peermap,
4510 free_finger (remove_finger);
4518 * Method called whenever a peer disconnects.
4520 * @param cls closure
4521 * @param peer peer identity this notification is about
4524 handle_core_disconnect (void *cls,
4525 const struct GNUNET_PeerIdentity *peer)
4527 struct FriendInfo *remove_friend;
4529 /* Check for self message. */
4530 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
4533 /* Search for peer to remove in your friend_peermap. */
4535 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
4537 if (NULL == remove_friend)
4543 /* Remove fingers for which this peer is the first element in the trail or if
4544 * the friend is a finger. */
4545 GNUNET_CONTAINER_multipeermap_iterate (finger_peermap,
4546 &remove_matching_finger, (void *)peer);
4547 GDS_ROUTING_remove_entry (peer);
4549 /* Remove the peer from friend_peermap. */
4550 GNUNET_assert (GNUNET_YES ==
4551 GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
4555 if (0 != GNUNET_CONTAINER_multipeermap_size (friend_peermap))
4558 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
4560 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
4561 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
4569 * Method called whenever a peer connects.
4571 * @param cls closure
4572 * @param peer_identity peer identity this notification is about
4575 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity)
4577 struct FriendInfo *friend;
4579 /* Check for connect to self message */
4580 if (0 == memcmp (&my_identity, peer_identity, sizeof (struct GNUNET_PeerIdentity)))
4583 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to %s\n", GNUNET_i2s (peer_identity));
4585 /* If peer already exists in our friend_peermap, then exit. */
4586 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (friend_peermap, peer_identity))
4592 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
4595 friend = GNUNET_new (struct FriendInfo);
4596 friend->id = *peer_identity;
4597 friend->trails_count = 0;
4599 GNUNET_assert (GNUNET_OK ==
4600 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
4601 peer_identity, friend,
4602 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
4604 /* got a first connection, good time to start with FIND FINGER TRAIL requests... */
4605 if (GNUNET_SCHEDULER_NO_TASK == find_finger_trail_task)
4606 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
4611 * To be called on core init/fail.
4613 * @param cls service closure
4614 * @param identity the public identity of this peer
4617 core_init (void *cls,
4618 const struct GNUNET_PeerIdentity *identity)
4620 my_identity = *identity;
4625 * Initialize neighbours subsystem.
4626 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4629 GDS_NEIGHBOURS_init (void)
4631 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
4632 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0},
4633 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0},
4634 {&handle_dht_p2p_get_result, GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT, 0},
4635 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP, 0},
4636 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT, 0},
4637 {&handle_dht_p2p_verify_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR, 0},
4638 {&handle_dht_p2p_verify_successor_result, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT, 0},
4639 {&handle_dht_p2p_notify_new_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR, 0},
4640 {&handle_dht_p2p_trail_rejection, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION, 0},
4641 {&handle_dht_p2p_trail_teardown, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_TEARDOWN, 0},
4642 {&handle_dht_p2p_add_trail, GNUNET_MESSAGE_TYPE_DHT_P2P_ADD_TRAIL, 0},
4647 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
4648 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
4649 GNUNET_NO, core_handlers);
4650 if (NULL == core_api)
4651 return GNUNET_SYSERR;
4653 friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
4654 finger_peermap = GNUNET_CONTAINER_multipeermap_create (MAX_FINGERS * 4/3, GNUNET_NO);
4661 * Shutdown neighbours subsystem.
4664 GDS_NEIGHBOURS_done (void)
4666 if (NULL == core_api)
4669 GNUNET_CORE_disconnect (core_api);
4672 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
4673 GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
4674 friend_peermap = NULL;
4676 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (finger_peermap));
4677 GNUNET_CONTAINER_multipeermap_destroy (finger_peermap);
4678 finger_peermap = NULL;
4680 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
4683 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
4684 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
4692 * @return my identity
4694 struct GNUNET_PeerIdentity
4695 GDS_NEIGHBOURS_get_my_id (void)
4701 /* end of gnunet-service-xdht_neighbours.c */