2 This file is part of GNUnet.
3 (C) 2009-2014 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file dht/gnunet-service-xdht_neighbours.c
23 * @brief GNUnet DHT service's finger and friend table management code
24 * @author Supriti Singh
28 #include "gnunet_util_lib.h"
29 #include "gnunet_block_lib.h"
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_protocols.h"
33 #include "gnunet_ats_service.h"
34 #include "gnunet_core_service.h"
35 #include "gnunet_datacache_lib.h"
36 #include "gnunet_transport_service.h"
37 #include "gnunet_dht_service.h"
38 #include "gnunet_statistics_service.h"
39 #include "gnunet-service-xdht.h"
40 #include "gnunet-service-xdht_clients.h"
41 #include "gnunet-service-xdht_datacache.h"
42 #include "gnunet-service-xdht_neighbours.h"
43 #include "gnunet-service-xdht_routing.h"
49 * Maximum possible fingers of a peer.
51 #define MAX_FINGERS 65
54 * Maximum allowed number of pending messages per friend peer.
56 #define MAXIMUM_PENDING_PER_FRIEND 64
59 * How long to wait before sending another find finger trail request
61 #define DHT_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
64 * How long at most to wait for transmission of a request to another peer?
66 #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
69 * How long will I remain congested?
71 #define CONGESTION_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
74 * Maximum number of trails stored per finger.
76 #define TRAILS_COUNT 2
79 * Used to distinguish put/get request use of find_successor() from others
81 #define PUT_GET_REQUEST 65
84 GNUNET_NETWORK_STRUCT_BEGIN
92 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
94 struct GNUNET_MessageHeader header;
99 uint32_t options GNUNET_PACKED;
104 uint32_t block_type GNUNET_PACKED;
109 uint32_t hop_count GNUNET_PACKED;
112 * Replication level for this message
113 * In the current implementation, this value is not used.
115 uint32_t desired_replication_level GNUNET_PACKED;
118 * Length of the PUT path that follows (if tracked).
120 uint32_t put_path_length GNUNET_PACKED;
123 * Current destination to which this message is forwarded.
125 struct GNUNET_PeerIdentity current_destination;
128 * Peer whose finger is current_destination.
130 struct GNUNET_PeerIdentity current_source;
133 * When does the content expire?
135 struct GNUNET_TIME_AbsoluteNBO expiration_time;
138 * The key to store the value under.
140 struct GNUNET_HashCode key GNUNET_PACKED;
142 /* put path (if tracked) */
152 struct PeerGetResultMessage
155 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT
157 struct GNUNET_MessageHeader header;
160 * The type for the data.
162 uint32_t type GNUNET_PACKED;
165 * Number of peers recorded in the outgoing path from source to the
166 * stored location of this message.
168 uint32_t put_path_length GNUNET_PACKED;
171 * Length of the GET path that follows (if tracked).
173 uint32_t get_path_length GNUNET_PACKED;
176 * Peer which will receive the get result message.
178 struct GNUNET_PeerIdentity source_peer;
181 * When does the content expire?
183 struct GNUNET_TIME_Absolute expiration_time;
186 * The key of the corresponding GET request.
188 struct GNUNET_HashCode key;
190 /* put path (if tracked) */
192 /* get path (if tracked) */
202 struct PeerGetMessage
205 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET
207 struct GNUNET_MessageHeader header;
212 uint32_t options GNUNET_PACKED;
215 * Desired content type.
217 uint32_t block_type GNUNET_PACKED;
222 uint32_t hop_count GNUNET_PACKED;
225 * Desired replication level for this request.
226 * In the current implementation, this value is not used.
228 uint32_t desired_replication_level GNUNET_PACKED;
231 * Total number of peers in get path.
233 unsigned int get_path_length;
236 * Peer which is an intermediate destination.
238 struct GNUNET_PeerIdentity current_destination;
241 * Source for which current_destination is the finger.
243 struct GNUNET_PeerIdentity current_source;
246 * The key we are looking for.
248 struct GNUNET_HashCode key;
256 * P2P Trail setup message
258 struct PeerTrailSetupMessage
262 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP
264 struct GNUNET_MessageHeader header;
267 * Peer closest to this value will be our finger.
269 uint64_t destination_finger;
272 * Source peer which wants to setup the trail to one of its finger.
274 struct GNUNET_PeerIdentity source_peer;
277 * Peer to which this packet is forwarded.
279 struct GNUNET_PeerIdentity current_destination;
282 * In case the packet is forwarded to an intermediate finger, then
283 * current_source contains the peer id whose finger is the intermediate
284 * finger. In case the packet is forwarded to a friend, then it is NULL.
285 * FIXME: check the usage of current_source and fix this comment.
287 struct GNUNET_PeerIdentity current_source;
290 * Index into finger peer map, in Network Byte Order.
292 uint32_t finger_map_index;
295 * Number of entries in trail list, in Network Byte Order.
297 uint32_t trail_length GNUNET_PACKED;
299 /* Trail formed in the process. */
304 * P2P Trail Setup Result message
306 struct PeerTrailSetupResultMessage
310 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT
312 struct GNUNET_MessageHeader header;
315 * Finger to which we have found the path.
317 struct GNUNET_PeerIdentity finger_identity;
320 * Peer which was looking for the trail to finger.
322 struct GNUNET_PeerIdentity destination_peer;
325 * Index into finger peer map in NBO.
327 uint32_t finger_map_index;
330 * Number of entries in trail list in NBO.
332 uint32_t trail_length GNUNET_PACKED;
334 /* Trail from destination_peer to finger_identity */
340 * P2P Trail Rejection Message.
342 struct PeerTrailRejectionMessage
345 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION
347 struct GNUNET_MessageHeader header;
350 * Source peer which wants to set up the trail.
352 struct GNUNET_PeerIdentity source_peer;
355 * Peer which sent trail rejection message.
357 struct GNUNET_PeerIdentity congested_peer;
360 * Peer identity which will be successor to this value will be finger of
363 uint64_t finger_identity_value;
366 * Index in finger peer map of source peer.
368 uint32_t finger_map_index;
371 * Total number of peers in the trail.
373 uint32_t trail_length;
376 * Relative time for which congested_peer will remain congested.
378 struct GNUNET_TIME_Relative congestion_time;
380 /* Trail_list from source_peer to peer which sent the message for trail setup
381 * to congested peer.*/
386 * P2P Verify Successor message.
388 struct PeerVerifySuccessorMessage
392 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR
394 struct GNUNET_MessageHeader header;
397 * Source peer which wants to verify its successor.
399 struct GNUNET_PeerIdentity source_peer;
402 * My current successor.
404 struct GNUNET_PeerIdentity successor;
407 * Total number of peers in trail to current successor.
409 uint32_t trail_length;
411 /* Trail to reach to from source_peer to successor. */
416 * P2P Verify Successor Result message.
418 struct PeerVerifySuccessorResultMessage
422 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT
424 struct GNUNET_MessageHeader header;
427 * Destination peer which sent the request to verify its successor.
429 struct GNUNET_PeerIdentity destination_peer;
432 * Successor to which PeerVerifySuccessorMessage was sent.
434 struct GNUNET_PeerIdentity source_successor;
437 * source_successor's predecessor
439 struct GNUNET_PeerIdentity my_predecessor;
442 * Total number of peers in trail.
444 uint32_t trail_length;
446 /* Trail to reach from destination_peer to its correct successor.
447 * If source_successor is not destination peer, then trail is from destination_peer
449 * If source_successor is destination peer, then trail is from destination_peer
450 * to source_successor. */
455 * P2P Notify New Successor message.
457 struct PeerNotifyNewSuccessorMessage
460 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR
462 struct GNUNET_MessageHeader header;
465 * Source peer which wants to notify its new successor.
467 struct GNUNET_PeerIdentity source_peer;
470 * Old successor of source peer.
472 struct GNUNET_PeerIdentity old_successor;
475 * New successor identity.
477 struct GNUNET_PeerIdentity destination_peer;
480 * Number of peers in trail from source_peer to new successor.
482 uint32_t trail_length;
484 /* Trail to from source_peer to destination_peer. */
487 struct PeerTrailTearDownMessage
490 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_TEARDOWN
492 struct GNUNET_MessageHeader header;
495 * Source peer of this trail.
497 struct GNUNET_PeerIdentity source_peer;
500 * Destination peer of this trail.
502 struct GNUNET_PeerIdentity destination_peer;
505 * Trail from source_peer to destination_peer compressed such that
506 * new_first_friend is the first hop in the trail from source to
509 struct GNUNET_PeerIdentity new_first_friend;
511 * Number of peers in trail from source_peer to new first friend.
513 uint32_t trail_length;
515 /* Trail from source_peer to new first friend. */
519 struct PeerAddTrailMessage
522 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_ADD_TRAIL
524 struct GNUNET_MessageHeader header;
527 * Source peer of the routing trail.
529 struct GNUNET_PeerIdentity source_peer;
532 * Destination peer of the routing trail.
534 struct GNUNET_PeerIdentity destination_peer;
537 * Total number of peers from source peer to destination peer.
539 unsigned int trail_length;
541 /* Trail from source peer to destination peer. */
545 GNUNET_NETWORK_STRUCT_END
549 * Linked list of messages to send to a particular other peer.
551 struct P2PPendingMessage
554 * Pointer to next item in the list
556 struct P2PPendingMessage *next;
559 * Pointer to previous item in the list
561 struct P2PPendingMessage *prev;
564 * Message importance level. FIXME: used? useful?
566 unsigned int importance;
569 * When does this message time out?
571 struct GNUNET_TIME_Absolute timeout;
574 * Actual message to be sent, allocated at the end of the struct:
575 * // msg = (cast) &pm[1];
576 * // memcpy (&pm[1], data, len);
578 const struct GNUNET_MessageHeader *msg;
584 * Linked List of peers which are part of trail to reach a particular Finger.
589 * Pointer to next item in the list
591 struct TrailPeerList *next;
594 * Pointer to previous item in the list
596 struct TrailPeerList *prev;
599 * An element in this trail list
601 struct GNUNET_PeerIdentity peer;
607 * FIXME: for congested peer just define a relative time as #define.
608 * Entry in friend_peermap.
615 struct GNUNET_PeerIdentity id;
618 * Number of trails for which this friend is the first hop.
620 unsigned int trails_count;
623 * Count of outstanding messages for this friend.
625 unsigned int pending_count;
628 * In case not 0, then amount of time for which this friend is congested.
630 struct GNUNET_TIME_Absolute congestion_duration;
633 * Head of pending messages to be sent to this friend.
635 struct P2PPendingMessage *head;
638 * Tail of pending messages to be sent to this friend.
640 struct P2PPendingMessage *tail;
643 * Core handle for sending messages to this friend.
645 struct GNUNET_CORE_TransmitHandle *th;
651 * Entry in finger_peermap.
658 struct GNUNET_PeerIdentity finger_identity;
661 * Index in finger peer map
663 unsigned int finger_map_index;
666 * Number of trails to reach to this finger.
668 unsigned int trail_count;
671 * Total number of entries in first trail from (me,finger)
673 unsigned int first_trail_length;
676 * Total number of entries in second trail from (me,finger)
678 unsigned int second_trail_length;
682 * Number of trail of which the first element to reach to this finger is
685 unsigned int first_friend_trails_count;
688 * Head of first trail to reach this finger.
690 struct TrailPeerList *first_trail_head;
693 * Tail of first trail to reach this finger.
695 struct TrailPeerList *first_trail_tail;
698 * Head of second trail to reach this finger.
700 struct TrailPeerList *second_trail_head;
703 * Tail of second trail to reach this finger.
705 struct TrailPeerList *second_trail_tail;
711 * FIXME: The name is not correct.
712 * Used to specify the kind of value stored in the array all_known_peers.
714 enum current_destination_type
724 * Data structure passed to sorting algorithm in find_successor().
729 * 64 bit value of peer identity
734 * FIXME: think of a better name for both the struct and destination_type
735 * Type : MY_ID, FINGER, FINGER, Value
737 enum current_destination_type type;
740 * Pointer to original data structure linked to peer id.
747 * Task that sends FIND FINGER TRAIL requests. This task is started when we have
748 * get our first friend.
750 static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task;
753 * Identity of this peer.
755 static struct GNUNET_PeerIdentity my_identity;
758 * Hash map of all the friends of a peer
760 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap;
763 * Hash map of all the fingers of a peer
765 static struct GNUNET_CONTAINER_MultiPeerMap *finger_peermap;
770 static struct GNUNET_CORE_Handle *core_api;
773 * Finger map index for predecessor entry in finger peermap.
775 #define PREDECESSOR_FINGER_ID 64
778 * Maximum number of trails allowed to go through a friend.
779 * FIXME: Better name, Random value at the moment, need to be adjusted to maintain a balance
780 * between performance and Sybil tolerance.
782 #define TRAIL_THROUGH_FRIEND_THRESHOLD 64
785 * Possible number of different trails to reach to a finger. (Redundant routing)
787 #define TRAIL_COUNT 2
790 * The current finger index that we have want to find trail to.
792 static unsigned int current_search_finger_index;
796 * Iterate over trail and search your index location in the array.
797 * @param trail Trail which contains list of peers.
798 * @param trail_length Number of peers in the trail.
799 * @return Index in the array.
800 * #GNUNET_SYSERR, in case there is no entry which should not be the case ideally.
803 search_my_index (const struct GNUNET_PeerIdentity *trail,
808 while (i < trail_length)
810 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &trail[i]))
816 return GNUNET_SYSERR;
821 * Compare two peer identities.
822 * @param p1 Peer identity
823 * @param p2 Peer identity
824 * @return 1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2.
827 compare_peer_id (const void *p1, const void *p2)
829 struct Sorting_List *p11;
830 struct Sorting_List *p22;
832 p11 = GNUNET_malloc (sizeof (struct Sorting_List));
833 p22 = GNUNET_malloc (sizeof (struct Sorting_List));
834 p11 = (struct Sorting_List *)p1;
835 p22 = (struct Sorting_List *)p2;
836 ret = ( (p11->peer_id) > (p22->peer_id) ) ? 1 :
837 ( (p11->peer_id) == (p22->peer_id) ) ? 0 : -1;
843 * Return the predecessor of value in all_known_peers.
844 * @param all_known_peers list of all the peers
845 * @param value value we have to search in the all_known_peers.
846 * @param size Total numbers of elements
847 * @return Predecessor
849 static struct Sorting_List *
850 find_closest_predecessor(struct Sorting_List *all_known_peers, uint64_t value,
859 middle = (first + last)/2;
863 if(all_known_peers[middle].peer_id < value)
867 else if(all_known_peers[middle].peer_id == value)
871 return &all_known_peers[size - 1];
875 return &all_known_peers[middle - 1];
883 middle = (first + last)/2;
890 * Return the successor of value in all_known_peers.
891 * @param all_known_peers list of all the peers
892 * @param value value we have to search in the all_known_peers.
893 * @param size Total numbers of elements
896 static struct Sorting_List *
897 find_closest_successor(struct Sorting_List *all_known_peers, uint64_t value,
906 middle = (first + last)/2;
910 if(all_known_peers[middle].peer_id < value)
914 else if(all_known_peers[middle].peer_id == value)
916 if(middle == (size -1))
918 return &all_known_peers[0];
922 return &all_known_peers[middle+1];
930 middle = (first + last)/2;
937 * Called when core is ready to send a message we asked for
938 * out to the destination.
940 * @param cls the 'struct FriendInfo' of the target friend
941 * @param size number of bytes available in buf
942 * @param buf where the callee should write the message
943 * @return number of bytes written to buf
946 core_transmit_notify (void *cls, size_t size, void *buf)
948 struct FriendInfo *peer = cls;
950 struct P2PPendingMessage *pending;
955 while ((NULL != (pending = peer->head)) &&
956 (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us))
958 peer->pending_count--;
959 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
960 GNUNET_free (pending);
964 /* no messages pending */
970 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
971 GNUNET_CORE_PRIO_BEST_EFFORT,
972 GNUNET_TIME_absolute_get_remaining
973 (pending->timeout), &peer->id,
974 ntohs (pending->msg->size),
975 &core_transmit_notify, peer);
976 GNUNET_break (NULL != peer->th);
980 while ((NULL != (pending = peer->head)) &&
981 (size - off >= (msize = ntohs (pending->msg->size))))
983 GNUNET_STATISTICS_update (GDS_stats,
985 ("# Bytes transmitted to other peers"), msize,
987 memcpy (&cbuf[off], pending->msg, msize);
989 peer->pending_count--;
990 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
991 GNUNET_free (pending);
993 if (peer->head != NULL)
996 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
997 GNUNET_CORE_PRIO_BEST_EFFORT,
998 GNUNET_TIME_absolute_get_remaining
999 (pending->timeout), &peer->id, msize,
1000 &core_transmit_notify, peer);
1001 GNUNET_break (NULL != peer->th);
1009 * FIXME: assertion fails at the end of this function. also in core_api.c at 1299.
1010 * Transmit all messages in the friend's message queue.
1012 * @param peer message queue to process
1015 process_friend_queue (struct FriendInfo *peer)
1017 struct P2PPendingMessage *pending;
1019 if (NULL == (pending = peer->head))
1021 if (NULL != peer->th)
1024 GNUNET_STATISTICS_update (GDS_stats,
1026 ("# Bytes of bandwidth requested from core"),
1027 ntohs (pending->msg->size), GNUNET_NO);
1030 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
1031 pending->importance,
1032 GNUNET_TIME_absolute_get_remaining
1033 (pending->timeout), &peer->id,
1034 ntohs (pending->msg->size),
1035 &core_transmit_notify, peer);
1036 GNUNET_break (NULL != peer->th);
1041 * Construct a trail setup message and forward it to a friend.
1042 * @param source_peer Peer which wants to set up the trail to one of its finger.
1043 * @param destination_finger Peer identity closest to this value will be
1044 * @a source_peer's finger.
1045 * @param current_destination next destination corresponding to @a current_source,
1046 * can be either a finger or a friend of @a current_source.
1047 * @param current_source Peer for which @a current_destination is its finger/friend.
1048 * @param target_friend Friend to which this message should be forwarded.
1049 * @param trail_length Numbers of peers in the trail found so far.
1050 * @param trail_peer_list Peers this request has traversed so far
1051 * @param finger_map_index Index in finger peer map
1054 GDS_NEIGHBOURS_send_trail_setup (const struct GNUNET_PeerIdentity *source_peer,
1055 uint64_t destination_finger,
1056 struct GNUNET_PeerIdentity *current_destination,
1057 struct GNUNET_PeerIdentity *current_source,
1058 struct FriendInfo *target_friend,
1059 unsigned int trail_length,
1060 const struct GNUNET_PeerIdentity *trail_peer_list,
1061 unsigned int finger_map_index)
1063 struct P2PPendingMessage *pending;
1064 struct PeerTrailSetupMessage *tsm;
1065 struct GNUNET_PeerIdentity *peer_list;
1068 msize = sizeof (struct PeerTrailSetupMessage) +
1069 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1071 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1077 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1079 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1083 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1084 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1085 tsm = (struct PeerTrailSetupMessage *) &pending[1];
1086 pending->msg = &tsm->header;
1087 tsm->header.size = htons (msize);
1088 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
1089 memcpy (&(tsm->destination_finger), &destination_finger, sizeof (uint64_t));
1090 memcpy (&(tsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1091 memcpy (&(tsm->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity));
1092 memcpy (&(tsm->current_source), current_source, sizeof (struct GNUNET_PeerIdentity));
1093 tsm->trail_length = htonl (trail_length);
1094 tsm->finger_map_index = htonl (finger_map_index);
1096 if (trail_length > 0)
1098 peer_list = (struct GNUNET_PeerIdentity *) &tsm[1];
1099 memcpy (peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
1102 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1103 target_friend->pending_count++;
1104 process_friend_queue (target_friend);
1109 * Construct a trail setup result message and forward it to a friend.
1110 * @param destination_peer Peer which will get the trail to one of its finger.
1111 * @param source_finger Peer to which the trail has been setup to.
1112 * @param target_friend Friend to which this message should be forwarded.
1113 * @param trail_length Numbers of peers in the trail.
1114 * @param trail_peer_list Peers which are part of the trail from source to destination.
1115 * @param finger_map_index Index in finger peer map
1118 GDS_NEIGHBOURS_send_trail_setup_result (const struct GNUNET_PeerIdentity *destination_peer,
1119 const struct GNUNET_PeerIdentity *source_finger,
1120 struct FriendInfo *target_friend,
1121 unsigned int trail_length,
1122 const struct GNUNET_PeerIdentity *trail_peer_list,
1123 unsigned int finger_map_index)
1125 struct P2PPendingMessage *pending;
1126 struct PeerTrailSetupResultMessage *tsrm;
1127 struct GNUNET_PeerIdentity *peer_list;
1130 msize = sizeof (struct PeerTrailSetupResultMessage) +
1131 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1133 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1139 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1141 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1145 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1146 pending->importance = 0;
1147 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1148 tsrm = (struct PeerTrailSetupResultMessage *) &pending[1];
1149 pending->msg = &tsrm->header;
1150 tsrm->header.size = htons (msize);
1151 tsrm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT);
1152 memcpy (&(tsrm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1153 memcpy (&(tsrm->finger_identity), source_finger, sizeof (struct GNUNET_PeerIdentity));
1154 tsrm->trail_length = htonl (trail_length);
1155 tsrm->finger_map_index = htonl (finger_map_index);
1157 peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1];
1158 if (trail_length > 0)
1160 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1162 /* Send the message to chosen friend. */
1163 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1164 target_friend->pending_count++;
1165 process_friend_queue (target_friend);
1170 * Construct a PeerVerifySuccessor message and send it to friend.
1171 * @param source_peer Peer which wants to verify its successor
1172 * @param successor Peer which is our current successor
1173 * @param target_friend Friend to which this message should be forwarded.
1174 * @param trail_peer_list Peer which are part of trail from source to destination
1175 * @param trail_length Number of peers in the trail list.
1177 void GDS_NEIGHBOURS_send_verify_successor(const struct GNUNET_PeerIdentity *source_peer,
1178 const struct GNUNET_PeerIdentity *successor,
1179 struct FriendInfo *target_friend,
1180 const struct GNUNET_PeerIdentity *trail_peer_list,
1181 unsigned int trail_length)
1183 struct PeerVerifySuccessorMessage *vsm;
1184 struct P2PPendingMessage *pending;
1185 struct GNUNET_PeerIdentity *peer_list;
1188 msize = sizeof (struct PeerVerifySuccessorMessage) +
1189 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1191 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1197 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1199 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1203 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1204 pending->importance = 0; /* FIXME */
1205 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1206 vsm = (struct PeerVerifySuccessorMessage *) &pending[1];
1207 pending->msg = &vsm->header;
1208 vsm->header.size = htons (msize);
1209 vsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR);
1210 memcpy (&(vsm->successor), successor, sizeof (struct GNUNET_PeerIdentity));
1211 memcpy (&(vsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1212 vsm->trail_length = htonl (trail_length);
1214 if (trail_length > 0)
1216 peer_list = (struct GNUNET_PeerIdentity *) &vsm[1];
1217 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1220 /* Send the message to chosen friend. */
1221 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1222 target_friend->pending_count++;
1223 process_friend_queue (target_friend);
1229 * Construct a PeerVerifySuccessorResult message and send it to friend.
1230 * @param destination_peer Peer which sent verify successor message
1231 * @param source_successor Peer to which verify successor message was sent.
1232 * @param my_predecessor source_successor's predecessor.
1233 * @param target_friend Friend to which this message should be forwarded.
1234 * @param trail_peer_list Peers which are part of trail from source to destination
1235 * @param trail_length Number of peers in the trail list.
1237 void GDS_NEIGHBOURS_send_verify_successor_result (const struct GNUNET_PeerIdentity *destination_peer,
1238 const struct GNUNET_PeerIdentity *source_successor,
1239 const struct GNUNET_PeerIdentity *my_predecessor,
1240 struct FriendInfo *target_friend,
1241 const struct GNUNET_PeerIdentity *trail_peer_list,
1242 unsigned int trail_length)
1244 struct PeerVerifySuccessorResultMessage *vsmr;
1245 struct P2PPendingMessage *pending;
1246 struct GNUNET_PeerIdentity *peer_list;
1249 msize = sizeof (struct PeerVerifySuccessorResultMessage) +
1250 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1252 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1259 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1261 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1265 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1266 pending->importance = 0; /* FIXME */
1267 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1268 vsmr = (struct PeerVerifySuccessorResultMessage *) &pending[1];
1269 pending->msg = &vsmr->header;
1270 vsmr->header.size = htons (msize);
1271 vsmr->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT);
1272 memcpy (&(vsmr->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1273 memcpy (&(vsmr->source_successor), source_successor, sizeof (struct GNUNET_PeerIdentity));
1274 memcpy (&(vsmr->my_predecessor), my_predecessor, sizeof (struct GNUNET_PeerIdentity));
1275 vsmr->trail_length = htonl (trail_length);
1276 if (trail_length > 0)
1278 peer_list = (struct GNUNET_PeerIdentity *) &vsmr[1];
1279 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1282 /* Send the message to chosen friend. */
1283 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1284 target_friend->pending_count++;
1285 process_friend_queue (target_friend);
1290 * Construct a PeerNotifyNewSuccessor message and send it to friend.
1291 * @param source_peer Peer which is sending notify message to its new successor.
1292 * @param destination_peer Peer which is the new destination.
1293 * @param target_friend Next friend to pass this message to.
1294 * @param peer_list List of peers in the trail to reach to destination_peer.
1295 * @param trail_length Total number of peers in peer list
1298 GDS_NEIGHBOURS_send_notify_new_successor (const struct GNUNET_PeerIdentity *source_peer,
1299 const struct GNUNET_PeerIdentity *destination_peer,
1300 const struct GNUNET_PeerIdentity *old_successor,
1301 struct FriendInfo *target_friend,
1302 const struct GNUNET_PeerIdentity *trail_peer_list,
1303 unsigned int trail_length)
1305 struct PeerNotifyNewSuccessorMessage *nsm;
1306 struct P2PPendingMessage *pending;
1307 struct GNUNET_PeerIdentity *peer_list;
1310 msize = sizeof (struct PeerNotifyNewSuccessorMessage) +
1311 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1313 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1319 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1321 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1325 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1326 pending->importance = 0; /* FIXME */
1327 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1328 nsm = (struct PeerNotifyNewSuccessorMessage *) &pending[1];
1329 pending->msg = &nsm->header;
1330 nsm->header.size = htons (msize);
1331 nsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR);
1332 memcpy (&(nsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1333 memcpy (&(nsm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1334 memcpy (&(nsm->old_successor), old_successor, sizeof (struct GNUNET_PeerIdentity));
1335 nsm->trail_length = htonl (trail_length);
1337 if (trail_length > 0)
1339 peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
1340 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1342 /* Send the message to chosen friend. */
1343 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1344 target_friend->pending_count++;
1345 process_friend_queue (target_friend);
1350 * Send a trail tear down message
1351 * @param source_peer Source of the trail.
1352 * @param destination_peer Destination of the trail.
1353 * @param discarded_trail Discarded trail from source to destination.
1354 * @param discarded_trail_length Total number of peers in trail_list.
1355 * @pararm target_peer Next peer to forward this message to.
1356 * @param new_first_friend The new first hop in the new trail from source to destination
1360 GDS_NEIGHBOURS_send_trail_teardown (const struct GNUNET_PeerIdentity *source_peer,
1361 const struct GNUNET_PeerIdentity *destination_peer,
1362 const struct GNUNET_PeerIdentity *discarded_trail,
1363 unsigned int discarded_trail_length,
1364 struct FriendInfo *target_friend,
1365 const struct GNUNET_PeerIdentity *new_first_friend)
1367 struct P2PPendingMessage *pending;
1368 struct PeerTrailTearDownMessage *ttdm;
1369 struct GNUNET_PeerIdentity *peer_list;
1372 msize = sizeof (struct PeerTrailTearDownMessage) +
1373 (discarded_trail_length * sizeof(struct GNUNET_PeerIdentity));
1375 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1381 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1383 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1387 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1388 pending->importance = 0; /* FIXME */
1389 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1390 ttdm = (struct PeerTrailTearDownMessage *) &pending[1];
1391 pending->msg = &ttdm->header;
1392 ttdm->header.size = htons (msize);
1393 ttdm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_TEARDOWN);
1394 memcpy (&(ttdm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1395 memcpy (&(ttdm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1396 memcpy (&(ttdm->new_first_friend),new_first_friend, sizeof (struct GNUNET_PeerIdentity));
1397 ttdm->trail_length = htonl (discarded_trail_length);
1399 if (discarded_trail_length > 0)
1401 peer_list = (struct GNUNET_PeerIdentity *) &ttdm[1];
1402 memcpy (peer_list, discarded_trail, discarded_trail_length * sizeof (struct GNUNET_PeerIdentity));
1404 /* Send the message to chosen friend. */
1405 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1406 target_friend->pending_count++;
1407 process_friend_queue (target_friend);
1412 * Construct an add_trail_message and send it to target_friend
1413 * @param source_peer Source of the trail to be added
1414 * @param destination_peer Destination of the trail to be added
1415 * @param trail Trail from source to destination
1416 * @param trail_length Total number of peers in the trail
1417 * @param target_friend Friend to forward this message.
1420 GDS_NEIGHBOURS_send_add_trail_message (struct GNUNET_PeerIdentity *source_peer,
1421 struct GNUNET_PeerIdentity *destination_peer,
1422 struct GNUNET_PeerIdentity *trail,
1423 unsigned int trail_length,
1424 struct FriendInfo *target_friend)
1426 struct P2PPendingMessage *pending;
1427 struct PeerAddTrailMessage *adm;
1428 struct GNUNET_PeerIdentity *peer_list;
1431 msize = sizeof (struct PeerAddTrailMessage) +
1432 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1434 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1440 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1442 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1446 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1447 pending->importance = 0; /* FIXME */
1448 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1449 adm = (struct PeerAddTrailMessage *) &pending[1];
1450 pending->msg = &adm->header;
1451 adm->header.size = htons (msize);
1452 adm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_ADD_TRAIL);
1453 memcpy (&(adm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1454 memcpy (&(adm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1455 adm->trail_length = htonl (trail_length);
1457 if (trail_length > 0)
1459 peer_list = (struct GNUNET_PeerIdentity *)&adm[1];
1460 memcpy (peer_list, trail, sizeof (struct GNUNET_PeerIdentity) * trail_length);
1463 /* Send the message to chosen friend. */
1464 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1465 target_friend->pending_count++;
1466 process_friend_queue (target_friend);
1471 * FIXME: CONGESTION: check the code once basic code is all correct. s
1472 * FIXME: call GNUNET_CONTAINER_multipeermap_iterator_destroy (iter);
1473 * In case the friend chosen in select_random_friend() is congested or
1474 * has crossed trail_threshold, then get next friend which is not congested or
1475 * has not crossed trail threshold from friend peermap.
1476 * @param current_index Index in finger peermap chosen randomly
1477 * @param friend_peermap_size Total number of entries in friend peermap.
1478 * @param count Total number of time this function has been called, in case
1479 * count == sizeof(friend_peermap) - 1, it means none of the friends are free.
1480 * @return Friend Friend found.
1481 * NULL in case all the friends are congested or have crossed trail threshold.
1483 static struct FriendInfo *
1484 get_next_friend (unsigned int current_index,
1485 unsigned int friend_peermap_size,
1488 struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
1489 struct GNUNET_PeerIdentity key_ret;
1490 struct FriendInfo *friend;
1493 current_index = (current_index + 1) % friend_peermap_size;
1494 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1495 while(j < (current_index))
1497 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,NULL,NULL))
1505 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,&key_ret,(const void **)&friend))
1507 if ((friend->trails_count > TRAIL_THROUGH_FRIEND_THRESHOLD) ||
1508 (0 != GNUNET_TIME_absolute_get_remaining (friend->congestion_duration).rel_value_us))
1511 if (count == (friend_peermap_size -1))
1514 return get_next_friend (j,friend_peermap_size,count);
1524 * FIXME: CONGESTION: check the code once basic code is all correct.
1525 * FIXME: call GNUNET_CONTAINER_multipeermap_iterator_destroy (iter);
1526 * Randomly choose one of your friends from the friends_peer map
1527 * @return Friend Randomly chosen friend.
1528 * NULL in case friend peermap is empty, or all the friends are either
1529 * congested or have crossed trail threshold.
1531 static struct FriendInfo *
1532 select_random_friend ()
1534 unsigned int current_size;
1535 unsigned int *index;
1537 struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
1538 struct GNUNET_PeerIdentity key_ret;
1539 struct FriendInfo *friend;
1541 current_size = GNUNET_CONTAINER_multipeermap_size (friend_peermap);
1542 if (0 == current_size)
1545 index = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, current_size);
1546 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1550 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,NULL,NULL))
1560 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,&key_ret,(const void **)&friend))
1562 if ((TRAIL_THROUGH_FRIEND_THRESHOLD == friend->trails_count) ||
1563 (0 != GNUNET_TIME_absolute_get_remaining (friend->congestion_duration).rel_value_us))
1565 return get_next_friend (*index, current_size, 1);
1575 * Compute finger_identity to which we want to setup the trail
1576 * @return finger_identity
1579 compute_finger_identity()
1583 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
1584 my_id64 = GNUNET_ntohll (my_id64);
1585 return (my_id64 + (unsigned long) pow (2, current_search_finger_index));
1590 * Compute immediate predecessor identity in the network.
1591 * @return peer identity of immediate predecessor.
1594 compute_predecessor_identity()
1598 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
1599 my_id64 = GNUNET_ntohll (my_id64);
1600 return (my_id64 -1);
1605 * Ping your successor to verify if it is still your successor or not.
1608 send_verify_successor_message()
1610 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1611 struct GNUNET_PeerIdentity key_ret;
1612 struct FriendInfo *target_friend;
1613 struct GNUNET_PeerIdentity next_hop;
1614 struct GNUNET_PeerIdentity *peer_list;
1615 struct FingerInfo *finger;
1616 unsigned int finger_index;
1619 /* Find the successor from the finger peermap.*/
1620 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1621 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
1623 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, &key_ret,
1624 (const void **)&finger))
1626 if (0 == finger->finger_map_index)
1633 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
1635 /* Either you don't have a successor or you are your own successor, then don't
1636 send a successor message. */
1638 (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, &(finger->finger_identity))))
1643 if (finger->first_trail_length > 0)
1645 struct TrailPeerList *iterate;
1647 peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * finger->first_trail_length);
1648 iterate = finger->first_trail_head;
1650 while ( i < (finger->first_trail_length))
1652 memcpy (&peer_list[i], &(iterate->peer), sizeof (struct GNUNET_PeerIdentity));
1653 iterate = iterate->next;
1656 memcpy (&next_hop, &peer_list[0], sizeof (struct GNUNET_PeerIdentity));
1657 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
1661 /* If trail length = 0, then our successor is our friend. */
1663 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1664 &(finger->finger_identity));
1667 GDS_NEIGHBOURS_send_verify_successor (&my_identity,
1668 &(finger->finger_identity),
1671 finger->first_trail_length);
1676 * Choose a random friend and start looking for the trail to reach to
1677 * finger identity through this random friend.
1679 * @param cls closure for this task
1680 * @param tc the context under which the task is running
1683 send_find_finger_trail_message (void *cls,
1684 const struct GNUNET_SCHEDULER_TaskContext *tc)
1686 struct FriendInfo *target_friend;
1687 struct GNUNET_TIME_Relative next_send_time;
1688 uint64_t finger_identity;
1689 unsigned int finger_map_index;
1691 next_send_time.rel_value_us =
1692 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
1693 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1694 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us);
1695 find_finger_trail_task =
1696 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_finger_trail_message,
1699 target_friend = select_random_friend ();
1700 if (NULL == target_friend)
1705 if (PREDECESSOR_FINGER_ID == current_search_finger_index)
1707 finger_identity = compute_predecessor_identity();
1711 finger_identity = compute_finger_identity();
1714 finger_map_index = current_search_finger_index;
1715 GDS_NEIGHBOURS_send_trail_setup (&my_identity, finger_identity, &(target_friend->id),
1716 &my_identity, target_friend, 0, NULL, finger_map_index);
1721 * FIXME: TRAIL_LIST URGENT. Send trail teardown message along each of the trail.
1722 * Scan the trail to check if any of my own friend is part of trail. If yes
1723 * then shortcut the trail, send a trail teardown for the discarded trail,
1724 * update trail list and trail_length.
1725 * @param trail[Out] Current trail to reach to @a finger, will be updated
1726 * in case we compress the trail.
1727 * @param trail_length[Out] Number of peers in @a finger_trail, will be updated
1728 * in case we compress the trail.
1729 * @param finger Finger identity
1732 scan_and_compress_trail (struct GNUNET_PeerIdentity *trail,
1733 unsigned int *trail_length,
1734 const struct GNUNET_PeerIdentity *finger)
1737 struct FriendInfo *target_friend;
1739 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity,finger))
1741 /* Here you don't send a trail teardown as no one added this in their
1747 if (GNUNET_CONTAINER_multipeermap_get (friend_peermap, finger))
1749 int discarded_trail_length = *trail_length;
1750 target_friend = GNUNET_CONTAINER_multipeermap_get(friend_peermap, &trail[0]);
1751 GDS_NEIGHBOURS_send_trail_teardown (&my_identity, finger, trail,
1752 discarded_trail_length, target_friend, finger);
1758 i = *trail_length - 1;
1762 if (NULL == GNUNET_CONTAINER_multipeermap_get (friend_peermap, &trail[i]))
1764 /* This element of trail is not my friend. */
1769 /* A --> B(friend 1) --> C(friend 2)--> D ---> E, then we can rewrite the trail as
1771 * Now, we should remove the entry from A's routing table, B's routing table
1772 * and update the entry in C's routing table. Rest everything will be same.
1773 * C's routing table should have source peer as the prev.hop.
1775 struct GNUNET_PeerIdentity *discarded_trail;
1776 struct FriendInfo *target_friend;
1777 int discarded_trail_length;
1780 discarded_trail_length = i - 1;
1781 discarded_trail = GNUNET_malloc (discarded_trail_length * sizeof (struct GNUNET_PeerIdentity));
1782 memcpy (discarded_trail, trail, discarded_trail_length * sizeof (struct GNUNET_PeerIdentity));
1783 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &trail[0]);
1784 GDS_NEIGHBOURS_send_trail_teardown (&my_identity, finger, discarded_trail,
1785 discarded_trail_length, target_friend,
1788 /* Copy the trail from index i to index trail_length -1 and change
1789 trail length and return */
1790 while (i < *trail_length)
1792 memcpy (&trail[j], &trail[i], sizeof(struct GNUNET_PeerIdentity));
1796 *trail_length = j+1;
1805 * FIXME: URGENT:Adapt the code for List of trails.
1806 * Free finger and its trail.
1807 * @param finger Finger to be freed.
1810 free_finger (struct FingerInfo *finger)
1812 struct TrailPeerList *peer;
1814 if(finger->first_trail_head != NULL)
1816 while (NULL != (peer = finger->first_trail_head))
1818 GNUNET_CONTAINER_DLL_remove (finger->first_trail_head, finger->first_trail_tail, peer);
1823 if (finger->second_trail_head != NULL)
1825 while (NULL != (peer = finger->second_trail_head))
1827 GNUNET_CONTAINER_DLL_remove (finger->second_trail_head, finger->second_trail_tail, peer);
1830 GNUNET_free (finger);
1836 * FIXME: URGENT: TRAIL_LIST First check if both the trails are present if yes
1837 * then send it for both of them. Currently sending it only for one trail.
1838 * Send a trail teardown message for the trail of removed finger from the finger
1840 * @param existing_finger Finger to removed from the finger peermap.
1843 void send_trail_teardown (struct FingerInfo *removed_finger)
1845 struct GNUNET_PeerIdentity *peer_list;
1846 struct FriendInfo *friend;
1847 struct TrailPeerList *finger_trail;
1848 int removed_finger_trail_length = removed_finger->first_trail_length;
1851 if (removed_finger->first_trail_length == 0)
1854 finger_trail = removed_finger->first_trail_head;
1855 friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &(finger_trail->peer));
1856 peer_list = GNUNET_malloc ( removed_finger_trail_length * sizeof (struct GNUNET_PeerIdentity));
1857 while (i < removed_finger->first_trail_length)
1859 memcpy (&peer_list[i], &(finger_trail->peer), sizeof (struct GNUNET_PeerIdentity));
1860 finger_trail = finger_trail->next;
1864 GDS_NEIGHBOURS_send_trail_teardown (&my_identity, &(removed_finger->finger_identity),
1865 peer_list, removed_finger_trail_length, friend,
1866 &(removed_finger->finger_identity));
1871 * FIXME: URGENT Adapt it to trail list.
1872 * Add a new trail to reach an existing finger in finger peermap and increment
1873 * the count of number of trails to reach to this finger.
1874 * @param existing_finger Finger
1875 * @param trail New trail to be added
1876 * @param trail_length Total number of peers in the trail.
1879 void add_new_trail (struct FingerInfo *existing_finger,
1880 struct GNUNET_PeerIdentity *trail,
1881 unsigned int trail_length)
1885 /* FIXME: Here you need to understand which trail is there and which not.
1886 In case first_trail_head != NULL, then that trail is present
1887 so you should add the second one. Need to verify this logic. */
1888 if (existing_finger->first_trail_head != NULL)
1890 while (i < trail_length)
1892 struct TrailPeerList *element;
1893 element = GNUNET_malloc (sizeof (struct TrailPeerList));
1894 element->next = NULL;
1895 element->prev = NULL;
1897 memcpy (&(element->peer), &trail[i], sizeof(struct GNUNET_PeerIdentity));
1898 GNUNET_CONTAINER_DLL_insert_tail(existing_finger->second_trail_head, existing_finger->second_trail_tail, element);
1902 else if (existing_finger->second_trail_head != NULL)
1904 while (i < trail_length)
1906 struct TrailPeerList *element;
1907 element = GNUNET_malloc (sizeof (struct TrailPeerList));
1908 element->next = NULL;
1909 element->prev = NULL;
1911 memcpy (&(element->peer), &trail[i], sizeof(struct GNUNET_PeerIdentity));
1912 GNUNET_CONTAINER_DLL_insert_tail(existing_finger->first_trail_head, existing_finger->first_trail_tail, element);
1916 existing_finger->trail_count++;
1921 * FIXME: URGENT: adapt it to TRAIL LIST.
1922 * In case there are already maximum number of possible trail to reach to a finger,
1923 * then check if the new trail's length is lesser than any of the existing trails.
1924 * If yes then replace that old trail by new trail.
1925 * Note: Here we are taking length as a parameter to choose the best possible trail,
1926 * but there could be other parameters also like - 1. duration of existence of a
1927 * trail - older the better. 2. if the new trail is completely disjoint than the
1928 * other trails, then may be choosing it is better.
1929 * @param existing_finger
1931 * @param trail_length
1932 * @return #GNUNET_YES
1936 void select_and_replace_trail (struct FingerInfo *existing_finger,
1937 struct GNUNET_PeerIdentity *new_trail,
1938 unsigned int new_trail_length)
1940 if (existing_finger->first_trail_length == existing_finger->second_trail_length)
1942 if (new_trail_length < existing_finger->first_trail_length)
1944 /* Randomly choose one of the trail. FIXME:currently I am just replacing the
1946 struct TrailPeerList *peer;
1949 while (NULL != (peer = existing_finger->first_trail_head))
1951 GNUNET_CONTAINER_DLL_remove (existing_finger->first_trail_head, existing_finger->first_trail_tail, peer);
1955 while (i < new_trail_length)
1957 struct TrailPeerList *element;
1958 element = GNUNET_malloc (sizeof (struct TrailPeerList));
1959 element->next = NULL;
1960 element->prev = NULL;
1962 memcpy (&(element->peer), &new_trail[i], sizeof(struct GNUNET_PeerIdentity));
1963 GNUNET_CONTAINER_DLL_insert_tail(existing_finger->second_trail_head, existing_finger->second_trail_tail, element);
1968 else if ((new_trail_length < existing_finger->second_trail_length) &&
1969 (existing_finger->second_trail_length < existing_finger->first_trail_length))
1971 /* Replace the first trail by the new trail. */
1972 struct TrailPeerList *peer;
1975 while (NULL != (peer = existing_finger->first_trail_head))
1977 GNUNET_CONTAINER_DLL_remove (existing_finger->first_trail_head, existing_finger->first_trail_tail, peer);
1981 while (i < new_trail_length)
1983 struct TrailPeerList *element;
1984 element = GNUNET_malloc (sizeof (struct TrailPeerList));
1985 element->next = NULL;
1986 element->prev = NULL;
1988 memcpy (&(element->peer), &new_trail[i], sizeof(struct GNUNET_PeerIdentity));
1989 GNUNET_CONTAINER_DLL_insert_tail(existing_finger->second_trail_head, existing_finger->second_trail_tail, element);
1993 else if ( (new_trail_length < existing_finger->first_trail_length) &&
1994 (existing_finger->first_trail_length < existing_finger->second_trail_length))
1996 /* Replace the second trail by the new trail. */
1997 struct TrailPeerList *peer;
2000 while (NULL != (peer = existing_finger->second_trail_head))
2002 GNUNET_CONTAINER_DLL_remove (existing_finger->second_trail_head, existing_finger->second_trail_tail, peer);
2006 while (i < new_trail_length)
2008 struct TrailPeerList *element;
2009 element = GNUNET_malloc (sizeof (struct TrailPeerList));
2010 element->next = NULL;
2011 element->prev = NULL;
2013 memcpy (&(element->peer), &new_trail[i], sizeof(struct GNUNET_PeerIdentity));
2014 GNUNET_CONTAINER_DLL_insert_tail(existing_finger->second_trail_head, existing_finger->second_trail_tail, element);
2022 * FIXME: URGENT: Adapat it for trail list.
2023 * FIXME: If we remove a finger which is our friend, then how should we handle it.
2024 * Ideally only in case if the trail_length > 0,we increment the trail count
2025 * of the first friend in the trail to reach to the finger. in case finger is
2026 * our friend then trail length = 0, and hence, we have never incremented the
2027 * trail count associated with that friend.
2028 * Decrement the trail count for the first friend to reach to the finger.
2032 decrement_friend_trail_count (struct FingerInfo *finger)
2034 struct FriendInfo *first_trail_friend;
2035 struct FriendInfo *second_trail_friend;
2037 if(finger->first_trail_head != NULL)
2039 first_trail_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2040 &(finger->first_trail_head->peer));
2041 first_trail_friend->trails_count--;
2044 if(finger->second_trail_head != NULL)
2046 second_trail_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2047 &(finger->second_trail_head->peer));
2048 second_trail_friend->trails_count--;
2052 /* We will not need this variable any more, all_friends_trail_threshold,
2053 FIXME: REMOVE IT. */
2054 if (GNUNET_YES == all_friends_trail_threshold)
2056 all_friends_trail_threshold = GNUNET_NO;
2057 /* FIXME; Here you should reschedule the send_find_finger_task here. or
2065 * FIXME: create a different data structure for storing the peer ids here.
2066 * Select the closest finger. Used for both predecessor and other fingers..
2067 * But internally calls different functions for predecessor and other fingers.
2068 * @param existing_finger Finger in finger peermap.
2069 * @param new_finger New finger identity
2070 * @param finger_map_index Index in finger peermap where @a existing_finger is stored.
2071 * @return #GNUNET_YES if the new finger is closest.
2072 * #GNUNET_NO if the old finger is closest.
2073 * #GNUNET_SYSERR in case our own identity is closest (should never happen).
2076 int select_finger (struct FingerInfo *existing_finger,
2077 const struct GNUNET_PeerIdentity *new_finger,
2078 unsigned int finger_map_index)
2080 struct Sorting_List peers[3]; /* 3 for existing_finger, new_finger, my_identity */
2081 struct Sorting_List *closest_finger;
2085 for (k = 0; k < 3; k++)
2088 /* Add your entry to peers. */
2089 memcpy (&peers[0], &my_identity, sizeof (uint64_t));
2090 peers[0].type = MY_ID;
2091 peers[0].data = NULL;
2093 /* Add existing_finger identity to the peers. */
2094 memcpy (&peers[1], &(existing_finger->finger_identity), sizeof (uint64_t));
2095 peers[1].type = FINGER;
2096 peers[1].data = existing_finger;
2098 /* Add new_finger identity to the peers. s*/
2099 memcpy (&peers[2], &new_finger, sizeof (uint64_t));
2100 peers[2].type = VALUE;
2101 peers[2].data = NULL;
2103 memcpy (&value, &my_identity, sizeof (uint64_t));
2104 qsort (&peers, 3, sizeof (struct Sorting_List), &compare_peer_id);
2106 if (PREDECESSOR_FINGER_ID == finger_map_index)
2107 closest_finger = find_closest_predecessor (peers, value, 3);
2109 closest_finger = find_closest_successor (peers, value, 3);
2111 if (closest_finger->type == FINGER)
2115 else if (closest_finger->type == VALUE)
2119 else if (closest_finger->type == MY_ID);
2121 return GNUNET_SYSERR;
2127 * FIXME: Better name, and make the code more cleaner.
2128 * Compare the new finger entry added and our successor.
2129 * @return #GNUNET_YES if same.
2130 * #GNUNET_NO if not.
2133 compare_new_entry_and_successor (const struct GNUNET_PeerIdentity *new_finger,
2134 int finger_map_index)
2136 int successor_flag = 0;
2137 struct FingerInfo *successor_finger;
2138 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
2141 if (PREDECESSOR_FINGER_ID == finger_map_index)
2144 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
2145 for (i= 0; i < GNUNET_CONTAINER_multipeermap_size (finger_peermap); i++)
2147 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, NULL,
2148 (const void **)&successor_finger))
2150 if (successor_finger->finger_map_index == 0)
2157 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
2159 /* Ideally we should never reach here. */
2160 if (successor_flag == 0)
2166 if (0 == GNUNET_CRYPTO_cmp_peer_identity (new_finger, &(successor_finger->finger_identity)))
2174 * FIXME: URGENT: Adapat it for trail list.
2175 * Add a new entry in finger table.
2176 * @param finger_identity PeerIdentity of the new finger
2177 * @param finger_trail Trail to reach to the finger, can be NULL in case I am my own
2179 * @param finger_trail_length Number of peers in the trail, can be 0 in case finger
2180 * is a friend or I am my own finger.
2181 * @param finger_map_index Index in finger map.
2184 add_new_entry (const struct GNUNET_PeerIdentity *finger_identity,
2185 struct GNUNET_PeerIdentity *finger_trail,
2186 uint32_t finger_trail_length,
2187 uint32_t finger_map_index)
2189 struct FriendInfo *first_friend_trail;
2190 struct FingerInfo *new_finger_entry;
2193 /* Add a new entry. */
2194 new_finger_entry = GNUNET_malloc (sizeof (struct FingerInfo));
2195 memcpy (&(new_finger_entry->finger_identity), finger_identity, sizeof (struct GNUNET_PeerIdentity));
2196 new_finger_entry->finger_map_index = finger_map_index;
2197 new_finger_entry->first_trail_length = finger_trail_length;
2198 new_finger_entry->trail_count = 1;
2200 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,finger_identity)) /* finger_trail is NULL in case I am my own finger identity. */
2202 /* Incrementing the friend trails count. */
2203 if (finger_trail_length > 0)
2205 first_friend_trail = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger_trail[0]);
2206 first_friend_trail->trails_count++;
2210 /* It means the finger is my friend. */
2211 first_friend_trail = GNUNET_CONTAINER_multipeermap_get (friend_peermap, finger_identity);
2212 first_friend_trail->trails_count++;
2214 new_finger_entry->first_friend_trails_count = first_friend_trail->trails_count;
2216 /* Copy the trail. */
2218 while (i < finger_trail_length)
2220 struct TrailPeerList *element;
2221 element = GNUNET_malloc (sizeof (struct TrailPeerList));
2222 element->next = NULL;
2223 element->prev = NULL;
2225 memcpy (&(element->peer), &finger_trail[i], sizeof(struct GNUNET_PeerIdentity));
2226 GNUNET_CONTAINER_DLL_insert_tail(new_finger_entry->first_trail_head, new_finger_entry->first_trail_tail, element);
2231 return GNUNET_CONTAINER_multipeermap_put (finger_peermap,
2232 &(new_finger_entry->finger_identity),
2234 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2239 * Choose the closest finger between existing finger and new finger.
2240 * If the new finger is closest, then send a trail_teardown message along
2241 * existing_finger's trail. In case both the id's are same, and there is a place
2242 * to add more trails, then store both of them. In case there is no space to
2243 * store any more trail, then choose the best trail (best - depends on length in
2244 * current_implementation) and discard the others.
2245 * @param existing_finger
2246 * @param new_finger Existing finger in finger_peermap for @a finger_map_index
2247 * @param trail Trail to reach from me to @a new_finger
2248 * @param trail_length Total number of peers in @a trail.
2249 * @param finger_map_index Index in finger peermap.
2250 * @return #GNUNET_YES In case we want to store the new entry.
2251 * #GNUNET_NO In case we want the existing entry.
2252 * #GNUNET_SYSERR Error.
2255 int select_closest_finger (struct FingerInfo *existing_finger,
2256 const struct GNUNET_PeerIdentity *new_finger,
2257 struct GNUNET_PeerIdentity *trail,
2258 unsigned int trail_length,
2259 unsigned int finger_map_index)
2261 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity), new_finger))
2263 /* New entry and existing entry are same. */
2264 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity), &my_identity))
2266 /* If existing_finger is my_identity then trail_length = 0, trail = NULL. In
2267 this case you don't need to check the trails. Exit. */
2270 if (trail_length > 0)
2272 scan_and_compress_trail (trail, &trail_length, new_finger);
2274 if (existing_finger->trail_count < TRAIL_COUNT)
2276 add_new_trail (existing_finger, trail, trail_length);
2281 select_and_replace_trail (existing_finger, trail, trail_length);
2285 else if (GNUNET_YES == select_finger (existing_finger, new_finger, finger_map_index))
2287 /* New finger is the closest finger. */
2288 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, new_finger))
2290 /* FIXME: Here in case the new finger is my_identity and old entry is not,
2291 should we keep the old entry even if the old entry is not the closest? */
2294 send_trail_teardown (existing_finger);
2295 decrement_friend_trail_count (existing_finger);
2296 free_finger (existing_finger);
2298 if (trail_length > 0)
2300 scan_and_compress_trail (trail, &trail_length, new_finger);
2304 else if (GNUNET_NO == select_finger (existing_finger, new_finger,finger_map_index))
2306 /* existing_finger is the closest finger. */
2309 return GNUNET_SYSERR;
2314 * FIXME: TRAIL LIST urgent.
2315 * Check if there is already an entry for finger map index in finger table.
2316 * If yes then choose the closest finger.
2317 * @param finger_identity Peer Identity of finger.
2318 * @param finger_trail Trail to reach from me to @a finger_identity
2319 * @param finger_trail_length Total number of peers in finger_trail.
2320 * @param finger_map_index Index in finger_peermap.
2321 * @return #GNUNET_YES if the new entry is added.
2322 * #GNUNET_NO if the new entry is discarded.
2325 int finger_table_add (const struct GNUNET_PeerIdentity *finger_identity,
2326 struct GNUNET_PeerIdentity *finger_trail,
2327 uint32_t finger_trail_length,
2328 uint32_t finger_map_index)
2330 struct FingerInfo *existing_finger;
2331 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
2333 int old_entry_found = GNUNET_NO;
2334 int new_entry_added = GNUNET_NO;
2336 /* Check if there is already an entry for the finger map index in the finger peer map. */
2337 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
2338 for (i= 0; i < GNUNET_CONTAINER_multipeermap_size (finger_peermap); i++)
2340 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, NULL,
2341 (const void **)&existing_finger))
2343 if (existing_finger->finger_map_index == finger_map_index)
2345 old_entry_found = GNUNET_YES;
2346 if ( GNUNET_NO == select_closest_finger (existing_finger, finger_identity,
2347 finger_trail, finger_trail_length,
2349 goto update_current_search_finger_index;
2355 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
2357 if (GNUNET_NO == old_entry_found)
2359 if (finger_trail_length > 0)
2361 scan_and_compress_trail (finger_trail, &finger_trail_length, finger_identity);
2365 /* FIXME: handle the case when addition in peer map failed. */
2366 if(GNUNET_OK == add_new_entry (finger_identity,finger_trail,finger_trail_length, finger_map_index))
2367 new_entry_added = GNUNET_YES;
2371 update_current_search_finger_index:
2372 if (0 == finger_map_index)
2374 current_search_finger_index = PREDECESSOR_FINGER_ID;
2375 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,finger_identity))
2376 send_verify_successor_message();
2378 else if (GNUNET_YES == compare_new_entry_and_successor (finger_identity,finger_map_index))
2380 current_search_finger_index = 0;
2384 current_search_finger_index = current_search_finger_index - 1;
2387 return new_entry_added;
2392 * FIXME: URGNET: adapt it for trail list.
2393 * Check if the successor chosen is congested or has crossed trail threshold.
2394 * @param successor Successor to be checked.
2395 * @return #GNUNET_YES in case its is either congested or has crossed trail threshold.
2396 * #GNUNET_NO if its good to go.
2399 check_friend_threshold_and_congestion (struct Sorting_List *successor)
2401 struct FriendInfo *friend;
2403 if (successor->type == FRIEND)
2405 friend = successor->data;
2407 else if (successor->type == FINGER)
2409 struct FingerInfo *finger = successor->data;
2410 if (finger->first_trail_length > 0)
2412 friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2413 &(finger->first_trail_head->peer));
2417 if (0 != GNUNET_CRYPTO_cmp_peer_identity(&my_identity, &finger->finger_identity))
2418 friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &(finger->finger_identity));
2424 if ((friend->trails_count == TRAIL_THROUGH_FRIEND_THRESHOLD)||
2425 ((0 != GNUNET_TIME_absolute_get_remaining (friend->congestion_duration).rel_value_us)))
2435 * Find the next successor for key_value as the earlier selected successor is either
2436 * congested or have crossed trail threshold.
2437 * @param all_known_peers Array that contains my_identity, value, friends and fingers.
2438 * @param array_size Total number of entries in @a all_known_peers.
2439 * @param start_index Index at which original successor is located.
2440 * @param search_index Index at which our possible current successor is located.
2441 * @param count Number of times this function has been called.
2442 * @return successor, in case found.
2443 * NULL, in case of error.
2445 static struct Sorting_List *
2446 get_next_successor (struct Sorting_List *all_known_peers,
2447 unsigned int array_size, int start_index,
2448 int search_index, int count)
2450 struct Sorting_List *next_peer;
2452 if (search_index == start_index)
2454 next_peer = GNUNET_malloc (sizeof (struct Sorting_List));
2455 memcpy (next_peer, &all_known_peers[search_index], sizeof (struct Sorting_List));
2457 if (next_peer->type == MY_ID)
2460 if ((next_peer->type == VALUE) ||
2461 (GNUNET_YES == check_friend_threshold_and_congestion (next_peer)))
2463 search_index = (search_index + 1) % array_size;
2465 return get_next_successor (all_known_peers, array_size, start_index, search_index, count);
2473 * Search the current location of successor in all_known_peers array.
2474 * @param all_known_peers Array which contains my_id, key value, friends and fingers.
2475 * @param array_size Total number of entries in @a all_known_peers
2476 * @param search_value 64 bit value of successor.
2477 * @return Index of array at which value is stored,
2478 * #GNUNET_SYSERR in case of error.
2481 get_successor_location (struct Sorting_List *all_known_peers, size_t array_size,
2482 uint64_t search_value)
2486 while (0 != memcmp (&all_known_peers[k].data, &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);
2564 * FIXME: 1. In case all the peers are congested/threshold then by default my_id is
2565 * chosen. There is no limit on number of peers which can keep me as their finger.
2566 * Should there be limit? If yes then we need to keep a counter of number of peers
2567 * that keep me as fingers. This counter may/may not give the correct value as
2568 * that peer may have found a better finger. So should reset the limit at some
2570 * 2. Change the finger code, TRAIL_LIST. URGENT
2571 * Find closest successor for the value.
2572 * @param value Value for which we are looking for successor
2573 * @param[out] current_destination set to my_identity in case I am the final destination,
2574 * set to friend identity in case friend is final destination,
2575 * set to first friend to reach to finger, in case finger
2576 * is final destination.
2577 * @param[out] current_source set to my_identity.
2578 * @param finger_map_index Index in finger peer map.
2579 * @return Peer identity of next hop to send trail setup message to
2581 static struct GNUNET_PeerIdentity *
2582 find_successor (uint64_t value, struct GNUNET_PeerIdentity *current_destination,
2583 struct GNUNET_PeerIdentity *current_source, unsigned int finger_map_index)
2585 struct Sorting_List *successor;
2588 size = GNUNET_CONTAINER_multipeermap_size (friend_peermap)+
2589 GNUNET_CONTAINER_multipeermap_size (finger_peermap)+
2592 struct Sorting_List all_known_peers[size];
2593 init_all_known_peers (all_known_peers, size, value);
2594 qsort (&all_known_peers, size, sizeof (struct Sorting_List), &compare_peer_id);
2596 if (PREDECESSOR_FINGER_ID == finger_map_index)
2597 successor = find_closest_predecessor (all_known_peers, value, size);
2599 successor = find_closest_successor (all_known_peers, value, size);
2601 if ((successor->type != MY_ID) && (successor->type != VALUE))
2603 if (GNUNET_YES == check_friend_threshold_and_congestion (successor))
2605 int search_index = get_successor_location (all_known_peers, size, successor->peer_id);
2606 successor = get_next_successor (all_known_peers, size, search_index, search_index + 1, 0);
2610 if (successor->type == MY_ID)
2612 memcpy (current_destination, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2613 return &my_identity;
2615 else if (successor->type == FRIEND)
2617 struct FriendInfo *target_friend = successor->data;
2618 memcpy (current_destination, &(target_friend->id), sizeof (struct GNUNET_PeerIdentity));
2619 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2620 return current_destination;
2622 else if (successor->type == FINGER)
2624 struct GNUNET_PeerIdentity *next_hop;
2625 struct FingerInfo *finger;
2626 finger = successor->data;
2627 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2629 if (finger->first_trail_length > 0)
2631 struct TrailPeerList *iterator;
2632 iterator = GNUNET_malloc (sizeof (struct TrailPeerList));
2633 iterator = finger->first_trail_head;
2634 memcpy (next_hop, &(iterator->peer), sizeof (struct GNUNET_PeerIdentity));
2636 else /* This means finger is our friend. */
2637 memcpy (next_hop, &(finger->finger_identity), sizeof(struct GNUNET_PeerIdentity));
2639 memcpy (current_destination, &(finger->finger_identity), sizeof (struct GNUNET_PeerIdentity));
2640 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2651 * Construct a Put message and send it to target_peer.
2652 * @param key Key for the content
2653 * @param block_type Type of the block
2654 * @param options Routing options
2655 * @param desired_replication_level Desired replication count
2656 * @param current_destination Next current destination which will get this message.
2657 * @param current_source Source for @a current_destination
2658 * @param target_peer Peer to which this message will be forwarded.
2659 * @param hop_count Number of hops traversed so far.
2660 * @param put_path_length Total number of peers in @a put_path
2661 * @param put_path Number of peers traversed so far
2662 * @param expiration_time When does the content expire
2663 * @param data Content to store
2664 * @param data_size Size of content @a data in bytes
2667 GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key,
2668 enum GNUNET_BLOCK_Type block_type,
2669 enum GNUNET_DHT_RouteOption options,
2670 uint32_t desired_replication_level,
2671 struct GNUNET_PeerIdentity current_destination,
2672 struct GNUNET_PeerIdentity current_source,
2673 struct GNUNET_PeerIdentity *target_peer,
2675 uint32_t put_path_length,
2676 struct GNUNET_PeerIdentity *put_path,
2677 struct GNUNET_TIME_Absolute expiration_time,
2678 const void *data, size_t data_size)
2680 struct PeerPutMessage *ppm;
2681 struct P2PPendingMessage *pending;
2682 struct FriendInfo *target_friend;
2683 struct GNUNET_PeerIdentity *pp;
2686 msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
2687 sizeof (struct PeerPutMessage);
2689 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2691 put_path_length = 0;
2692 msize = data_size + sizeof (struct PeerPutMessage);
2695 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2701 /* This is the first call made from clients file. So, we should search for the
2703 if (NULL == target_peer)
2706 struct GNUNET_PeerIdentity *next_hop;
2708 memcpy (&key_value, key, sizeof (uint64_t));
2709 next_hop = find_successor (key_value, ¤t_destination, ¤t_source,PUT_GET_REQUEST);
2710 if (0 == GNUNET_CRYPTO_cmp_peer_identity(next_hop, &my_identity))
2712 /* I am the destination but we have already done datacache_put in client file. */
2716 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2719 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2720 pending->timeout = expiration_time;
2721 ppm = (struct PeerPutMessage *) &pending[1];
2722 pending->msg = &ppm->header;
2723 ppm->header.size = htons (msize);
2724 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
2725 ppm->options = htonl (options);
2726 ppm->block_type = htonl (block_type);
2727 ppm->hop_count = htonl (hop_count + 1);
2728 ppm->desired_replication_level = htonl (desired_replication_level);
2729 ppm->put_path_length = htonl (put_path_length);
2730 ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
2732 ppm->current_destination = current_destination;
2733 ppm->current_source = current_source;
2735 pp = (struct GNUNET_PeerIdentity *) &ppm[1];
2736 if (put_path_length != 0)
2738 memcpy (pp, put_path,
2739 sizeof (struct GNUNET_PeerIdentity) * put_path_length);
2741 memcpy (&pp[put_path_length], data, data_size);
2742 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2743 target_friend->pending_count++;
2744 process_friend_queue (target_friend);
2749 * Construct a Get message and send it to target_peer.
2750 * @param key Key for the content
2751 * @param block_type Type of the block
2752 * @param options Routing options
2753 * @param desired_replication_level Desired replication count
2754 * @param current_destination Next current destination which will get this message.
2755 * @param current_source Source for @a current_destination
2756 * @param target_peer Peer to which this message will be forwarded.
2757 * @param hop_count Number of hops traversed so far.
2758 * @param data Content to store
2759 * @param data_size Size of content @a data in bytes
2760 * @param get_path_length Total number of peers in @a get_path
2761 * @param get_path Number of peers traversed so far
2764 GDS_NEIGHBOURS_send_get (const struct GNUNET_HashCode *key,
2765 enum GNUNET_BLOCK_Type block_type,
2766 enum GNUNET_DHT_RouteOption options,
2767 uint32_t desired_replication_level,
2768 struct GNUNET_PeerIdentity current_destination,
2769 struct GNUNET_PeerIdentity current_source,
2770 struct GNUNET_PeerIdentity *target_peer,
2772 uint32_t get_path_length,
2773 struct GNUNET_PeerIdentity *get_path)
2775 struct PeerGetMessage *pgm;
2776 struct P2PPendingMessage *pending;
2777 struct FriendInfo *target_friend;
2778 struct GNUNET_PeerIdentity *gp;
2781 msize = sizeof (struct PeerGetMessage) +
2782 (get_path_length * sizeof (struct GNUNET_PeerIdentity));
2784 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2790 if (NULL == target_peer)
2792 struct GNUNET_PeerIdentity *next_hop;
2795 memcpy (&key_value, key, sizeof (uint64_t));
2796 // FIXME: endianess of key_value!?
2797 next_hop = find_successor (key_value, ¤t_destination, ¤t_source, PUT_GET_REQUEST);
2798 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity,next_hop))
2800 GDS_DATACACHE_handle_get (key,block_type, NULL, 0,
2801 NULL, 0, 1, &my_identity, NULL,&my_identity);
2806 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2810 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2811 pending->importance = 0; /* FIXME */
2812 pgm = (struct PeerGetMessage *) &pending[1];
2813 pending->msg = &pgm->header;
2814 pgm->header.size = htons (msize);
2815 pgm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
2816 pgm->get_path_length = htonl (get_path_length);
2818 pgm->current_destination = current_destination;
2819 pgm->current_source = current_source;
2820 pgm->hop_count = htonl (hop_count + 1);
2824 gp = (struct GNUNET_PeerIdentity *) &pgm[1];
2825 memcpy (gp, get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity));
2827 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2828 target_friend->pending_count++;
2829 process_friend_queue (target_friend);
2834 * Send the get result to requesting client.
2835 * @param key Key of the requested data.
2836 * @param type Block type
2837 * @param target_peer Next peer to forward the message to.
2838 * @param source_peer Peer which has the data for the key.
2839 * @param put_path_length Number of peers in @a put_path
2840 * @param put_path Path taken to put the data at its stored location.
2841 * @param get_path_length Number of peers in @a get_path
2842 * @param get_path Path taken to reach to the location of the key.
2843 * @param expiration When will this result expire?
2844 * @param data Payload to store
2845 * @param data_size Size of the @a data
2848 GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key,
2849 enum GNUNET_BLOCK_Type type,
2850 struct GNUNET_PeerIdentity *next_hop,
2851 struct GNUNET_PeerIdentity *source_peer,
2852 unsigned int put_path_length,
2853 const struct GNUNET_PeerIdentity *put_path,
2854 unsigned int get_path_length,
2855 struct GNUNET_PeerIdentity *get_path,
2856 struct GNUNET_TIME_Absolute expiration,
2857 const void *data, size_t data_size)
2859 struct PeerGetResultMessage *get_result;
2860 struct GNUNET_PeerIdentity *get_result_path;
2861 struct GNUNET_PeerIdentity *pp;
2862 struct P2PPendingMessage *pending;
2863 struct FriendInfo *target_friend;
2864 int current_path_index;
2867 msize = get_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
2868 sizeof (struct PeerPutMessage);
2870 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2876 if(get_path_length > 0)
2878 current_path_index = search_my_index(get_path, get_path_length);
2879 if (GNUNET_SYSERR == current_path_index)
2885 if (0 == current_path_index)
2887 GDS_CLIENTS_handle_reply (expiration, key, get_path_length, get_path, put_path_length,
2888 put_path, type, data_size, data);
2892 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2893 pending->importance = 0;
2894 get_result = (struct PeerGetResultMessage *)&pending[1];
2895 pending->msg = &get_result->header;
2896 get_result->header.size = htons (msize);
2897 get_result->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT);
2898 get_result->key = *key;
2899 memcpy (&(get_result->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
2900 get_result->expiration_time = expiration;
2902 if (get_path_length != 0)
2904 get_result_path = (struct GNUNET_PeerIdentity *)&get_result[1];
2905 memcpy (get_result_path, get_path,
2906 sizeof (struct GNUNET_PeerIdentity) * get_path_length);
2908 memcpy (&get_result_path[get_path_length], data, data_size);
2910 /* FIXME: Is this correct? */
2911 if (put_path_length != 0)
2913 pp = (struct GNUNET_PeerIdentity *)&get_result_path[1];
2914 memcpy (pp, put_path,sizeof (struct GNUNET_PeerIdentity) * put_path_length);
2916 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2917 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2918 target_friend->pending_count++;
2919 process_friend_queue (target_friend);
2924 * Send trail rejection message to the peer which sent me a trail setup message.
2925 * @param source_peer Source peer which wants to set up the trail.
2926 * @param finger_identity Value whose successor will be the finger of @a source_peer.
2927 * @param congested_peer Peer which has send trail rejection message.
2928 * @param next_hop Peer to which this message should be forwarded.
2929 * @param finger_map_index Index in @a source_peer finger peermap.
2930 * @param trail_peer_list Trail followed to reach from @a source_peer to next_hop,
2931 * NULL, in case the @a congested_peer was the first peer
2932 * to which trail setup message was forwarded.
2933 * @param trail_length Number of peers in trail_peer_list.
2934 * @param congestion_timeout Time duration for which @a congested peer will be
2938 GDS_NEIGHBOURS_send_trail_rejection (const struct GNUNET_PeerIdentity *source_peer,
2939 uint64_t finger_identity,
2940 const struct GNUNET_PeerIdentity *congested_peer,
2941 const struct GNUNET_PeerIdentity *next_hop,
2942 unsigned int finger_map_index,
2943 struct GNUNET_PeerIdentity *trail_peer_list,
2944 unsigned int trail_length,
2945 struct GNUNET_TIME_Relative congestion_timeout)
2947 struct PeerTrailRejectionMessage *trail_rejection;
2948 struct GNUNET_PeerIdentity *trail_list;
2949 struct P2PPendingMessage *pending;
2950 struct FriendInfo *target_friend;
2953 msize = trail_length * sizeof(struct GNUNET_PeerIdentity) +
2954 sizeof (struct PeerTrailRejectionMessage);
2956 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2962 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2963 pending->importance = 0;
2964 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
2965 trail_rejection = (struct PeerTrailRejectionMessage *) &pending[1];
2966 pending->msg = &trail_rejection->header;
2967 trail_rejection->header.size = htons (msize);
2968 trail_rejection->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
2969 memcpy (&(trail_rejection->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
2970 memcpy (&(trail_rejection->congested_peer), congested_peer, sizeof (struct GNUNET_PeerIdentity));
2971 memcpy (&(trail_rejection->finger_identity_value), &finger_identity, sizeof (uint64_t));
2972 trail_rejection->finger_map_index = htonl (finger_map_index);
2973 trail_rejection->trail_length = htonl (trail_length);
2974 trail_rejection->congestion_time = congestion_timeout;
2976 if (trail_length != 0)
2978 trail_list = (struct GNUNET_PeerIdentity *)&trail_rejection[1];
2979 memcpy (trail_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
2982 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2983 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2984 target_friend->pending_count++;
2985 process_friend_queue (target_friend);
2990 * Core handler for P2P put messages.
2991 * @param cls closure
2992 * @param peer sender of the request
2993 * @param message message
2994 * @return #GNUNET_OK to keep the connection open,
2995 * #GNUNET_SYSERR to close it (signal serious error)
2998 handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer,
2999 const struct GNUNET_MessageHeader *message)
3001 struct PeerPutMessage *put;
3002 struct GNUNET_PeerIdentity *put_path;
3003 struct GNUNET_HashCode test_key;
3004 enum GNUNET_DHT_RouteOption options;
3005 struct GNUNET_PeerIdentity current_destination;
3006 struct GNUNET_PeerIdentity current_source;
3007 struct GNUNET_PeerIdentity *next_hop;
3011 size_t payload_size;
3014 msize = ntohs (message->size);
3015 if (msize < sizeof (struct PeerPutMessage))
3017 GNUNET_break_op (0);
3021 put = (struct PeerPutMessage *) message;
3022 putlen = ntohl (put->put_path_length);
3025 sizeof (struct PeerPutMessage) +
3026 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
3028 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3030 GNUNET_break_op (0);
3034 current_destination = put->current_destination;
3035 current_source = put->current_source;
3036 put_path = (struct GNUNET_PeerIdentity *) &put[1];
3037 payload = &put_path[putlen];
3038 options = ntohl (put->options);
3039 payload_size = msize - (sizeof (struct PeerPutMessage) +
3040 putlen * sizeof (struct GNUNET_PeerIdentity));
3042 switch (GNUNET_BLOCK_get_key (GDS_block_context, ntohl (put->block_type),
3043 payload, payload_size, &test_key))
3046 if (0 != memcmp (&test_key, &put->key, sizeof (struct GNUNET_HashCode)))
3048 char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key));
3049 GNUNET_break_op (0);
3050 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3051 "PUT with key `%s' for block with key %s\n",
3052 put_s, GNUNET_h2s_full (&test_key));
3053 GNUNET_free (put_s);
3058 GNUNET_break_op (0);
3061 /* cannot verify, good luck */
3065 if (ntohl (put->block_type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
3067 switch (GNUNET_BLOCK_evaluate (GDS_block_context,
3068 ntohl (put->block_type),
3070 NULL, 0, /* bloom filer */
3071 NULL, 0, /* xquery */
3072 payload, payload_size))
3074 case GNUNET_BLOCK_EVALUATION_OK_MORE:
3075 case GNUNET_BLOCK_EVALUATION_OK_LAST:
3078 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
3079 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
3080 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
3081 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
3082 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
3083 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
3085 GNUNET_break_op (0);
3090 /* extend 'put path' by sender */
3091 struct GNUNET_PeerIdentity pp[putlen + 1];
3092 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
3094 memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity));
3101 memcpy (&key_value, &(put->key), sizeof (uint64_t));
3102 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_destination, &my_identity)))
3104 next_hop = GDS_ROUTING_search (¤t_source, ¤t_destination, peer);
3108 next_hop = find_successor (key_value, ¤t_destination, ¤t_source,PUT_GET_REQUEST);
3111 if (NULL == next_hop)
3113 GNUNET_STATISTICS_update (GDS_stats,
3114 gettext_noop ("# Next hop to forward the packet not found "
3115 "trail setup request, packet dropped."),
3117 return GNUNET_SYSERR;
3120 GDS_CLIENTS_process_put (options,
3121 ntohl (put->block_type),
3122 ntohl (put->hop_count),
3123 ntohl (put->desired_replication_level),
3125 GNUNET_TIME_absolute_ntoh (put->expiration_time),
3130 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, next_hop)) /* I am the final destination */
3132 GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time),
3133 &(put->key),putlen, pp, ntohl (put->block_type),
3134 payload_size, payload);
3139 GDS_NEIGHBOURS_send_put (&put->key,
3140 ntohl (put->block_type),ntohl (put->options),
3141 ntohl (put->desired_replication_level),
3142 current_destination, current_source, next_hop,
3143 ntohl (put->hop_count), putlen, pp,
3144 GNUNET_TIME_absolute_ntoh (put->expiration_time),
3145 payload, payload_size);
3149 return GNUNET_SYSERR;
3154 * Core handler for p2p get requests.
3156 * @param cls closure
3157 * @param peer sender of the request
3158 * @param message message
3159 * @return #GNUNET_OK to keep the connection open,
3160 * #GNUNET_SYSERR to close it (signal serious error)
3163 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
3164 const struct GNUNET_MessageHeader *message)
3166 struct PeerGetMessage *get;
3167 struct GNUNET_PeerIdentity *get_path;
3168 struct GNUNET_PeerIdentity current_destination;
3169 struct GNUNET_PeerIdentity current_source;
3170 struct GNUNET_PeerIdentity *next_hop;
3171 uint32_t get_length;
3175 msize = ntohs (message->size);
3176 if (msize < sizeof (struct PeerGetMessage))
3178 GNUNET_break_op (0);
3182 get = (struct PeerGetMessage *)message;
3183 get_length = ntohl (get->get_path_length);
3184 current_destination = get->current_destination;
3185 current_source = get->current_source;
3187 get_path = (struct GNUNET_PeerIdentity *)&get[1];
3190 sizeof (struct PeerGetMessage) +
3191 get_length * sizeof (struct GNUNET_PeerIdentity)) ||
3193 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3195 GNUNET_break_op (0);
3199 /* Add sender to get path */
3200 struct GNUNET_PeerIdentity gp[get_length + 1];
3201 memcpy (gp, get_path, get_length * sizeof (struct GNUNET_PeerIdentity));
3202 gp[get_length + 1] = *peer;
3203 get_length = get_length + 1;
3205 memcpy (&key_value, &(get->key), sizeof (uint64_t));
3206 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_destination, &my_identity)))
3208 next_hop = GDS_ROUTING_search (¤t_source, ¤t_destination, peer);
3212 next_hop = find_successor (key_value, ¤t_destination, ¤t_source,PUT_GET_REQUEST);
3215 if (NULL == next_hop)
3217 GNUNET_STATISTICS_update (GDS_stats,
3218 gettext_noop ("# Next hop to forward the packet not found "
3219 "trail setup request, packet dropped."),
3221 return GNUNET_SYSERR;
3223 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, next_hop))
3225 /* I am the destination.*/
3226 struct GNUNET_PeerIdentity final_get_path[get_length+1];
3227 struct GNUNET_PeerIdentity next_hop;
3229 memcpy (final_get_path, gp, get_length * sizeof (struct GNUNET_PeerIdentity));
3230 memcpy (&final_get_path[get_length+1], &my_identity, sizeof (struct GNUNET_PeerIdentity));
3231 get_length = get_length + 1;
3232 memcpy (&next_hop, &final_get_path[get_length-2], sizeof (struct GNUNET_PeerIdentity));
3233 GDS_DATACACHE_handle_get (&(get->key),(get->block_type), NULL, 0, NULL, 0,
3234 get_length, final_get_path,&next_hop, &my_identity);
3240 GDS_NEIGHBOURS_send_get (&(get->key), get->block_type, get->options,
3241 get->desired_replication_level,current_destination,
3242 current_source, next_hop, 0,
3245 return GNUNET_SYSERR;
3250 * Core handler for get result
3251 * @param cls closure
3252 * @param peer sender of the request
3253 * @param message message
3254 * @return #GNUNET_OK to keep the connection open,
3255 * #GNUNET_SYSERR to close it (signal serious error)
3258 handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer,
3259 const struct GNUNET_MessageHeader *message)
3261 struct PeerGetResultMessage *get_result;
3262 struct GNUNET_PeerIdentity *get_path;
3263 struct GNUNET_PeerIdentity *put_path;
3265 size_t payload_size;
3267 unsigned int getlen;
3268 unsigned int putlen;
3269 int current_path_index;
3271 msize = ntohs (message->size);
3272 if (msize < sizeof (struct PeerGetResultMessage))
3274 GNUNET_break_op (0);
3278 get_result = (struct PeerGetResultMessage *)message;
3279 getlen = ntohl (get_result->get_path_length);
3280 putlen = ntohl (get_result->put_path_length);
3283 sizeof (struct PeerGetResultMessage) +
3284 getlen * sizeof (struct GNUNET_PeerIdentity) +
3285 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
3287 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity) ||
3289 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))))
3291 GNUNET_break_op (0);
3296 get_path = (struct GNUNET_PeerIdentity *) &get_result[1];
3297 payload = &get_path[getlen];
3298 payload_size = msize - (sizeof (struct PeerGetResultMessage) +
3299 getlen * sizeof (struct GNUNET_PeerIdentity));
3302 put_path = &get_path[1];
3306 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &(get_path[0]))))
3308 GDS_CLIENTS_handle_reply (get_result->expiration_time, &(get_result->key),
3309 getlen, get_path, putlen,
3310 put_path, get_result->type, payload_size, payload);
3315 current_path_index = search_my_index (get_path, getlen);
3316 if (GNUNET_SYSERR == current_path_index )
3319 return GNUNET_SYSERR;
3321 GDS_NEIGHBOURS_send_get_result (&(get_result->key), get_result->type,
3322 &get_path[current_path_index - 1],
3323 &(get_result->source_peer), putlen, put_path,
3324 getlen, get_path, get_result->expiration_time,
3325 payload, payload_size);
3328 return GNUNET_SYSERR;
3333 * Select the closest peer between peer returned from routing table and from
3335 * @param prev_hop Peer which sent the trail setup message.
3336 * @param current_destination[out] Next peer which will receive this message.
3337 * @param current_source[out] Source of the @a current_destination.
3338 * @param value Key value to which the peer should be closest.
3339 * @para finger_map_index Index in finger map.
3340 * @return Peer which is closest, in case of error NULL.
3342 struct GNUNET_PeerIdentity *
3343 select_closest_peer (const struct GNUNET_PeerIdentity *prev_hop,
3344 struct GNUNET_PeerIdentity *current_destination,
3345 struct GNUNET_PeerIdentity *current_source,
3347 unsigned int finger_map_index)
3349 struct GNUNET_PeerIdentity *peer1;
3350 struct GNUNET_PeerIdentity *peer2;
3351 struct Sorting_List peers[3];
3352 struct Sorting_List *closest_finger;
3353 struct GNUNET_PeerIdentity current_dest;
3354 struct GNUNET_PeerIdentity current_src;
3356 peer1 = GDS_ROUTING_search (current_source, current_destination, prev_hop);
3357 peer2 = find_successor (value, ¤t_dest, ¤t_src,finger_map_index);
3359 if( (peer1 != NULL) && (peer2 != NULL))
3361 memcpy (&peers[0], &peer1, sizeof (uint64_t));
3362 peers[0].type = FRIEND;
3363 peers[0].data = NULL;
3365 memcpy (&peers[1], &value, sizeof (uint64_t));
3366 peers[1].type = VALUE;
3367 peers[1].data = NULL;
3369 memcpy (&peers[2], &peer2, sizeof (uint64_t));
3370 peers[2].type = FINGER;
3371 peers[1].data = NULL;
3373 qsort (&peers, 3, sizeof (struct Sorting_List), &compare_peer_id);
3374 if (PREDECESSOR_FINGER_ID == finger_map_index)
3375 closest_finger = find_closest_predecessor (peers, value, 3);
3377 closest_finger = find_closest_successor (peers, value, 3);
3379 if (closest_finger->type == FINGER)
3381 memcpy (current_destination, ¤t_dest, sizeof (struct GNUNET_PeerIdentity));
3382 memcpy (current_source, ¤t_src, sizeof (struct GNUNET_PeerIdentity));
3385 else if (closest_finger->type == VALUE)
3389 else if (closest_finger->type == FRIEND);
3394 else if ((peer1 == NULL) && (peer2 == NULL))
3398 else if (peer1 == NULL)
3402 else if (peer2 == NULL)
3411 * Core handle for PeerTrailSetupMessage.
3412 * @param cls closure
3413 * @param message message
3414 * @param peer peer identity this notification is about
3415 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3418 handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer,
3419 const struct GNUNET_MessageHeader *message)
3421 const struct PeerTrailSetupMessage *trail_setup;
3422 struct GNUNET_PeerIdentity current_destination;
3423 struct GNUNET_PeerIdentity current_source;
3424 struct GNUNET_PeerIdentity source;
3425 struct GNUNET_PeerIdentity *next_hop;
3426 struct GNUNET_PeerIdentity next_peer;
3427 struct GNUNET_PeerIdentity *trail_peer_list;
3428 struct FriendInfo *target_friend;
3429 uint64_t destination_finger_value;
3430 uint32_t trail_length;
3431 uint32_t finger_map_index;
3434 msize = ntohs (message->size);
3435 if (msize < sizeof (struct PeerTrailSetupMessage))
3437 GNUNET_break_op (0);
3441 trail_setup = (const struct PeerTrailSetupMessage *) message;
3442 trail_length = ntohl (trail_setup->trail_length);
3444 if ((msize < sizeof (struct PeerTrailSetupMessage) +
3445 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3447 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3449 GNUNET_break_op (0);
3453 if (trail_length > 0)
3454 trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_setup[1];
3455 memcpy (¤t_destination, &(trail_setup->current_destination), sizeof (struct GNUNET_PeerIdentity));
3456 memcpy (¤t_source,&(trail_setup->current_source), sizeof (struct GNUNET_PeerIdentity));
3457 memcpy (&source, &(trail_setup->source_peer), sizeof (struct GNUNET_PeerIdentity));
3458 finger_map_index = ntohl (trail_setup->finger_map_index);
3459 destination_finger_value = ntohl (trail_setup->destination_finger);
3461 /* Check your routing table size, and if you can handle any more trails through you. */
3462 if (GNUNET_YES == GDS_ROUTING_check_threshold())
3464 GDS_NEIGHBOURS_send_trail_rejection (&source, destination_finger_value, &my_identity,
3465 peer, finger_map_index, trail_peer_list, trail_length,
3466 CONGESTION_TIMEOUT);
3470 /* Check if you are current_destination or not. */
3471 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_destination, &my_identity)))
3473 next_hop = select_closest_peer (peer, ¤t_destination, ¤t_source,
3474 destination_finger_value, finger_map_index);
3478 next_hop = find_successor (destination_finger_value, ¤t_destination,
3479 ¤t_source,finger_map_index);
3482 if (NULL == next_hop)
3484 GNUNET_STATISTICS_update (GDS_stats,
3485 gettext_noop ("# Next hop to forward the packet not found "
3486 "trail setup request, packet dropped."),
3488 return GNUNET_SYSERR;
3490 else if (0 == (GNUNET_CRYPTO_cmp_peer_identity (next_hop, &my_identity)))/* This means I am the final destination */
3492 if (trail_length == 0)
3494 memcpy (&next_peer, &source, sizeof (struct GNUNET_PeerIdentity));
3498 memcpy (&next_peer, &trail_peer_list[trail_length-1], sizeof (struct GNUNET_PeerIdentity));
3501 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer);
3502 GDS_NEIGHBOURS_send_trail_setup_result (&source,
3504 target_friend, trail_length,
3511 /* Now add yourself to the trail. */
3512 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
3513 if (trail_length != 0)
3514 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
3515 peer_list[trail_length] = my_identity;
3517 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3518 GDS_NEIGHBOURS_send_trail_setup (&source,
3519 destination_finger_value,
3520 ¤t_destination, ¤t_source,
3521 target_friend, trail_length, peer_list,
3529 * Core handle for p2p trail construction result messages.
3531 * @param message message
3532 * @param peer peer identity this notification is about
3533 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3536 handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer,
3537 const struct GNUNET_MessageHeader *message)
3539 const struct PeerTrailSetupResultMessage *trail_result;
3540 struct GNUNET_PeerIdentity *trail_peer_list;
3541 struct GNUNET_PeerIdentity destination_peer;
3542 struct GNUNET_PeerIdentity finger_identity;
3543 uint32_t trail_length;
3544 uint32_t finger_map_index;
3547 msize = ntohs (message->size);
3548 if (msize < sizeof (struct PeerTrailSetupResultMessage))
3550 GNUNET_break_op (0);
3554 trail_result = (const struct PeerTrailSetupResultMessage *) message;
3555 trail_length = ntohl (trail_result->trail_length);
3558 sizeof (struct PeerTrailSetupResultMessage) +
3559 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3561 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3563 GNUNET_break_op (0);
3567 finger_map_index = htonl (trail_result->finger_map_index);
3568 memcpy (&destination_peer, &(trail_result->destination_peer), sizeof (struct GNUNET_PeerIdentity));
3569 memcpy (&finger_identity, &(trail_result->finger_identity), sizeof (struct GNUNET_PeerIdentity));
3571 if (trail_length > 0)
3572 trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_result[1];
3575 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->destination_peer),
3578 finger_table_add (&(trail_result->finger_identity), trail_peer_list, trail_length,
3584 struct GNUNET_PeerIdentity next_hop;
3585 struct FriendInfo *target_friend;
3588 my_index = search_my_index (trail_peer_list, trail_length);
3589 if (my_index == GNUNET_SYSERR)
3590 return GNUNET_SYSERR;
3593 next_hop = trail_result->destination_peer;
3595 next_hop = trail_peer_list[my_index - 1];
3597 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->destination_peer),
3598 &(trail_result->finger_identity))))
3600 struct GNUNET_PeerIdentity *routing_next_hop;
3602 routing_next_hop = GDS_ROUTING_search (&destination_peer,&finger_identity,
3604 if ((NULL == routing_next_hop) ||
3605 (0 != GNUNET_CRYPTO_cmp_peer_identity(routing_next_hop, &next_hop)))
3607 GDS_ROUTING_add (&(trail_result->destination_peer), &(trail_result->finger_identity),
3612 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3613 GDS_NEIGHBOURS_send_trail_setup_result (&(trail_result->destination_peer),
3614 &(trail_result->finger_identity),
3615 target_friend, trail_length,
3620 return GNUNET_SYSERR;
3625 * Get my current predecessor from the finger peer map
3626 * @return Current predecessor.
3628 static struct FingerInfo *
3631 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
3632 struct GNUNET_PeerIdentity key_ret;
3633 unsigned int finger_index;
3634 struct FingerInfo *my_predecessor;
3637 /* Iterate over finger peer map and extract your predecessor. */
3638 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
3639 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
3641 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next
3642 (finger_iter,&key_ret,(const void **)&my_predecessor))
3644 if(PREDECESSOR_FINGER_ID == my_predecessor->finger_map_index)
3651 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
3656 return my_predecessor;
3661 * Core handle for p2p verify successor messages.
3662 * @param cls closure
3663 * @param message message
3664 * @param peer peer identity this notification is about
3665 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3668 handle_dht_p2p_verify_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
3669 const struct GNUNET_MessageHeader *message)
3671 const struct PeerVerifySuccessorMessage *vsm;
3672 const struct GNUNET_PeerIdentity *trail_peer_list;
3673 struct GNUNET_PeerIdentity source_peer;
3674 struct GNUNET_PeerIdentity next_hop;
3675 struct FriendInfo *target_friend;
3677 uint32_t trail_length;
3679 msize = ntohs (message->size);
3680 if (msize < sizeof (struct PeerVerifySuccessorMessage))
3682 GNUNET_break_op (0);
3686 vsm = (struct PeerVerifySuccessorMessage *) message;
3687 trail_length = ntohl (vsm->trail_length);
3689 if ((msize < sizeof (struct PeerVerifySuccessorMessage) +
3690 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3691 (trail_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3693 GNUNET_break_op (0);
3696 if (trail_length > 0)
3697 trail_peer_list = (const struct GNUNET_PeerIdentity *)&vsm[1];
3698 memcpy (&source_peer, &(vsm->source_peer), sizeof(struct GNUNET_PeerIdentity));
3700 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsm->successor),&my_identity)))
3702 struct FingerInfo *my_predecessor;
3704 my_predecessor = get_predecessor();
3705 if (NULL == my_predecessor)
3707 /* FIXME: should we just return. */
3711 if (trail_length == 0)
3713 memcpy (&next_hop, &source_peer, sizeof (struct GNUNET_PeerIdentity));
3717 memcpy (&next_hop, &trail_peer_list[trail_length-1], sizeof (struct GNUNET_PeerIdentity));
3719 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3721 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&source_peer,
3722 &(my_predecessor->finger_identity))))
3724 /* Source peer and my predecessor, both are same. */
3726 GDS_NEIGHBOURS_send_verify_successor_result (&source_peer,
3728 &(my_predecessor->finger_identity),
3735 struct GNUNET_PeerIdentity *new_successor_trail;
3736 struct TrailPeerList *iterator;
3737 int new_trail_length;
3740 new_trail_length = trail_length + my_predecessor->first_trail_length + 1;
3741 new_successor_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * new_trail_length);
3742 if (trail_length > 0)
3743 memcpy (new_successor_trail, trail_peer_list, (trail_length) * sizeof (struct GNUNET_PeerIdentity));
3745 memcpy (&new_successor_trail[trail_length], &my_identity, sizeof (struct GNUNET_PeerIdentity));
3747 if (my_predecessor->first_trail_length)
3749 iterator = GNUNET_malloc (sizeof (struct TrailPeerList));
3750 iterator = my_predecessor->first_trail_head;
3751 i = trail_length + 1;
3752 while (i < new_trail_length)
3754 memcpy (&new_successor_trail[i], &(iterator->peer), sizeof (struct GNUNET_PeerIdentity));
3755 iterator = iterator->next;
3759 GDS_NEIGHBOURS_send_verify_successor_result (&source_peer,
3761 &(my_predecessor->finger_identity),
3763 new_successor_trail,
3772 my_index = search_my_index (trail_peer_list, trail_length);
3773 if (my_index == GNUNET_SYSERR)
3776 return GNUNET_SYSERR;
3778 if (my_index == (trail_length - 1))
3780 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &(vsm->successor));
3784 memcpy (&next_hop, &trail_peer_list[my_index + 1], sizeof (struct GNUNET_PeerIdentity));
3785 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3788 GDS_NEIGHBOURS_send_verify_successor (&(vsm->source_peer), &(vsm->successor),target_friend,
3789 trail_peer_list, trail_length);
3791 return GNUNET_SYSERR;
3796 * Core handle for p2p verify successor result messages.
3797 * @param cls closure
3798 * @param message message
3799 * @param peer peer identity this notification is about
3800 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3803 handle_dht_p2p_verify_successor_result(void *cls, const struct GNUNET_PeerIdentity *peer,
3804 const struct GNUNET_MessageHeader *message)
3806 const struct PeerVerifySuccessorResultMessage *vsrm;
3807 struct GNUNET_PeerIdentity *trail_peer_list;
3808 struct GNUNET_PeerIdentity next_hop;
3809 struct FriendInfo *target_friend;
3811 uint32_t trail_length;
3813 msize = ntohs (message->size);
3814 if (msize < sizeof (struct PeerVerifySuccessorResultMessage))
3816 GNUNET_break_op (0);
3819 vsrm = (const struct PeerVerifySuccessorResultMessage *) message;
3820 trail_length = ntohl (vsrm->trail_length);
3823 sizeof (struct PeerVerifySuccessorResultMessage) +
3824 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3826 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3828 GNUNET_break_op (0);
3832 if (trail_length > 0)
3833 trail_peer_list = (struct GNUNET_PeerIdentity *) &vsrm[1];
3835 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->destination_peer), &(my_identity))))
3837 if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->my_predecessor), &(my_identity))))
3839 if (GNUNET_YES == finger_table_add (&(vsrm->my_predecessor), trail_peer_list, trail_length, 0))
3841 memcpy (&next_hop, &trail_peer_list[0], sizeof (struct GNUNET_PeerIdentity));
3842 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3843 scan_and_compress_trail (trail_peer_list, &trail_length, &(vsrm->my_predecessor));
3844 GDS_NEIGHBOURS_send_notify_new_successor (&my_identity, &(vsrm->my_predecessor),
3845 &(vsrm->source_successor),
3846 target_friend, trail_peer_list,
3856 my_index = search_my_index (trail_peer_list, trail_length);
3857 if (GNUNET_SYSERR == my_index)
3860 return GNUNET_SYSERR;
3864 memcpy (&next_hop, &(vsrm->destination_peer), sizeof (struct GNUNET_PeerIdentity));
3868 memcpy (&next_hop, &trail_peer_list[my_index-1], sizeof (struct GNUNET_PeerIdentity));
3871 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3872 GDS_NEIGHBOURS_send_verify_successor_result (&(vsrm->destination_peer),
3873 &(vsrm->source_successor),
3874 &(vsrm->my_predecessor),
3880 return GNUNET_SYSERR;
3885 * Core handle for p2p notify new successor messages.
3886 * @param cls closure
3887 * @param message message
3888 * @param peer peer identity this notification is about
3889 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3892 handle_dht_p2p_notify_new_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
3893 const struct GNUNET_MessageHeader *message)
3895 const struct PeerNotifyNewSuccessorMessage *nsm;
3896 struct GNUNET_PeerIdentity *trail_peer_list;
3897 struct GNUNET_PeerIdentity source_peer;
3898 struct GNUNET_PeerIdentity old_successor;
3899 struct GNUNET_PeerIdentity new_successor;
3900 struct FriendInfo *target_friend;
3902 uint32_t trail_length;
3904 msize = ntohs (message->size);
3905 if (msize < sizeof (struct PeerNotifyNewSuccessorMessage))
3907 GNUNET_break_op (0);
3910 nsm = (const struct PeerNotifyNewSuccessorMessage *) message;
3911 trail_length = ntohl (nsm->trail_length);
3913 if ((msize < sizeof (struct PeerNotifyNewSuccessorMessage) +
3914 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3916 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3918 GNUNET_break_op (0);
3922 if( trail_length > 0)
3923 trail_peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
3924 memcpy (&source_peer, &(nsm->source_peer), sizeof (struct GNUNET_PeerIdentity));
3925 memcpy (&old_successor, &(nsm->old_successor), sizeof (struct GNUNET_PeerIdentity));
3926 memcpy (&new_successor, &(nsm->destination_peer), sizeof (struct GNUNET_PeerIdentity));
3928 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&new_successor, &my_identity)))
3930 /* I am the new successor. */
3931 struct GNUNET_PeerIdentity *new_predecessor;
3933 new_predecessor = GNUNET_new (struct GNUNET_PeerIdentity);
3934 memcpy (new_predecessor, &(nsm->source_peer), sizeof (struct GNUNET_PeerIdentity));
3935 if (GNUNET_YES == finger_table_add (new_predecessor, trail_peer_list, trail_length, PREDECESSOR_FINGER_ID))
3937 if (trail_length > 0)
3938 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &(trail_peer_list[trail_length - 1]));
3940 target_friend = NULL;
3941 GDS_NEIGHBOURS_send_add_trail_message (&my_identity, new_predecessor,
3942 trail_peer_list, trail_length, target_friend);
3948 struct GNUNET_PeerIdentity next_hop;
3951 my_index = search_my_index (trail_peer_list, trail_length);
3952 if (GNUNET_SYSERR == my_index)
3955 return GNUNET_SYSERR;
3958 if (my_index == (trail_length - 1))
3960 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &(nsm->destination_peer));
3964 memcpy (&next_hop, &trail_peer_list[my_index+1], sizeof (struct GNUNET_PeerIdentity));
3965 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3967 GDS_ROUTING_remove_trail (&source_peer, &old_successor, peer);
3968 GDS_ROUTING_add (&(nsm->source_peer), &(nsm->destination_peer), &next_hop, peer);
3969 GDS_NEIGHBOURS_send_notify_new_successor (&(nsm->source_peer),
3970 &(nsm->destination_peer),
3971 &(nsm->old_successor),
3972 target_friend, trail_peer_list,
3976 return GNUNET_SYSERR;
3981 * Core handler for P2P trail rejection message
3982 * @param cls closure
3983 * @param message message
3984 * @param peer peer identity this notification is about
3985 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3988 int handle_dht_p2p_trail_rejection(void *cls, const struct GNUNET_PeerIdentity *peer,
3989 const struct GNUNET_MessageHeader *message)
3991 const struct PeerTrailRejectionMessage *trail_rejection;
3992 struct GNUNET_PeerIdentity *trail_peer_list;
3993 struct FriendInfo *target_friend;
3994 struct GNUNET_PeerIdentity next_hop;
3995 struct GNUNET_PeerIdentity *next_peer;
3996 struct GNUNET_PeerIdentity source;
3997 struct GNUNET_PeerIdentity current_destination;
3998 struct GNUNET_PeerIdentity current_source;
3999 uint32_t trail_length;
4000 uint32_t finger_map_index;
4001 uint64_t destination_finger_value;
4002 struct GNUNET_TIME_Relative congestion_timeout;
4005 msize = ntohs (message->size);
4006 if (msize < sizeof (struct PeerTrailRejectionMessage))
4008 GNUNET_break_op (0);
4012 trail_rejection = (struct PeerTrailRejectionMessage *) message;
4013 trail_length = ntohl (trail_rejection->trail_length);
4015 if ((msize < sizeof (struct PeerTrailRejectionMessage) +
4016 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
4018 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
4020 GNUNET_break_op (0);
4024 if (trail_length > 0)
4025 trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_rejection[1];
4026 finger_map_index = ntohl (trail_rejection->finger_map_index);
4027 memcpy (&destination_finger_value, &(trail_rejection->finger_identity_value), sizeof (uint64_t));
4028 memcpy (&source, &(trail_rejection->source_peer), sizeof (struct GNUNET_PeerIdentity));
4029 congestion_timeout = trail_rejection->congestion_time;
4031 /* First set the congestion time of the friend that sent you this message. */
4032 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
4033 target_friend->congestion_duration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(),
4034 congestion_timeout);
4036 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &(trail_rejection->source_peer))))
4041 if(GNUNET_YES == GDS_ROUTING_check_threshold())
4043 struct GNUNET_PeerIdentity *new_trail;
4044 unsigned int new_trail_length;
4046 if (trail_length == 1)
4049 new_trail_length = 0;
4050 memcpy (&next_hop, &(trail_rejection->source_peer), sizeof (struct GNUNET_PeerIdentity));
4054 memcpy (&next_hop, &trail_peer_list[trail_length - 2], sizeof (struct GNUNET_PeerIdentity));
4055 /* Remove myself from the trail. */
4056 new_trail_length = trail_length -1;
4057 new_trail = GNUNET_malloc (new_trail_length * sizeof (struct GNUNET_PeerIdentity));
4058 memcpy (new_trail, trail_peer_list, new_trail_length * sizeof (struct GNUNET_PeerIdentity));
4060 GDS_NEIGHBOURS_send_trail_rejection (&(trail_rejection->source_peer),
4061 destination_finger_value,
4062 &my_identity, &next_hop,finger_map_index,
4063 new_trail,new_trail_length, CONGESTION_TIMEOUT);
4068 memcpy (¤t_destination, &my_identity, sizeof (struct GNUNET_PeerIdentity));
4069 memcpy (¤t_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
4070 next_peer = find_successor (destination_finger_value,¤t_destination,
4071 ¤t_source, finger_map_index);
4072 if (NULL == next_peer)
4074 GNUNET_STATISTICS_update (GDS_stats,
4075 gettext_noop ("# Next hop not found"
4076 "trail setup request, packet dropped."),
4078 return GNUNET_SYSERR;
4080 else if (0 == (GNUNET_CRYPTO_cmp_peer_identity (next_peer, &my_identity)))/* This means I am the final destination */
4082 memcpy (&next_hop, &trail_peer_list[trail_length-1], sizeof (struct GNUNET_PeerIdentity));
4083 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
4084 GDS_NEIGHBOURS_send_trail_setup_result (&source,
4086 target_friend, trail_length,
4093 /* Now add yourself to the trail. */
4094 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
4095 if (trail_length != 0)
4096 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
4097 peer_list[trail_length] = my_identity;
4099 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
4100 GDS_NEIGHBOURS_send_trail_setup (&source,
4101 destination_finger_value,
4102 ¤t_destination, ¤t_source,
4103 target_friend, trail_length, peer_list,
4113 * Core handle for p2p trail tear down messages.
4114 * @param cls closure
4115 * @param message message
4116 * @param peer peer identity this notification is about
4117 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4120 int handle_dht_p2p_trail_teardown (void *cls, const struct GNUNET_PeerIdentity *peer,
4121 const struct GNUNET_MessageHeader *message)
4123 struct PeerTrailTearDownMessage *trail_teardown;
4124 struct GNUNET_PeerIdentity *discarded_trail;
4125 struct GNUNET_PeerIdentity next_hop;
4126 struct FriendInfo *target_friend;
4127 uint32_t discarded_trail_length;
4131 msize = ntohs (message->size);
4132 if (msize < sizeof (struct PeerTrailTearDownMessage))
4134 GNUNET_break_op (0);
4138 trail_teardown = (struct PeerTrailTearDownMessage *) message;
4139 discarded_trail_length = ntohl (trail_teardown->trail_length);
4141 if ((msize < sizeof (struct PeerTrailTearDownMessage) +
4142 discarded_trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
4143 (discarded_trail_length >
4144 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
4146 GNUNET_break_op (0);
4150 if (discarded_trail_length > 0)
4151 discarded_trail = (struct GNUNET_PeerIdentity *) &trail_teardown[1];
4153 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_teardown->new_first_friend),
4156 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_teardown->destination_peer),
4163 return GDS_ROUTING_trail_update (&(trail_teardown->source_peer),
4164 &(trail_teardown->destination_peer), peer);
4169 my_index = search_my_index (discarded_trail, discarded_trail_length);
4170 if(GNUNET_SYSERR == my_index)
4171 return GNUNET_SYSERR;
4173 if (GNUNET_NO == GDS_ROUTING_remove_trail (&(trail_teardown->source_peer),
4174 &(trail_teardown->destination_peer),peer))
4176 GNUNET_break (0); /* no matching entry found. Should not happen */
4177 return GNUNET_SYSERR;
4180 if (my_index == (discarded_trail_length - 1))
4183 memcpy (&next_hop, &discarded_trail[my_index + 1], sizeof (struct GNUNET_PeerIdentity));
4184 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
4185 GDS_NEIGHBOURS_send_trail_teardown (&(trail_teardown->source_peer),
4186 &(trail_teardown->destination_peer),
4187 discarded_trail, discarded_trail_length,
4188 target_friend, &(trail_teardown->new_first_friend));
4191 return GNUNET_SYSERR;
4196 * Core handle for p2p add trail message.
4197 * @param cls closure
4198 * @param message message
4199 * @param peer peer identity this notification is about
4200 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4203 handle_dht_p2p_add_trail (void *cls, const struct GNUNET_PeerIdentity *peer,
4204 const struct GNUNET_MessageHeader *message)
4206 struct PeerAddTrailMessage *add_trail;
4207 struct GNUNET_PeerIdentity *trail;
4208 struct GNUNET_PeerIdentity next_hop;
4209 struct FriendInfo *target_friend;
4211 uint32_t trail_length;
4214 msize = ntohs (message->size);
4215 if (msize < sizeof (struct PeerAddTrailMessage))
4217 GNUNET_break_op (0);
4221 add_trail = (struct PeerAddTrailMessage *) message;
4222 trail_length = ntohl (add_trail->trail_length);
4224 if ((msize < sizeof (struct PeerAddTrailMessage) +
4225 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
4227 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
4229 GNUNET_break_op (0);
4233 if (trail_length > 0)
4234 trail = (struct GNUNET_PeerIdentity *)&add_trail[1];
4236 my_index = search_my_index (trail, trail_length);
4237 if (GNUNET_SYSERR == my_index)
4240 return GNUNET_SYSERR;
4243 if (GNUNET_YES == GDS_ROUTING_add (&(add_trail->source_peer), &(add_trail->destination_peer),
4248 memcpy (&next_hop, &trail[my_index - 1], sizeof (struct GNUNET_PeerIdentity));
4249 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
4250 GDS_NEIGHBOURS_send_add_trail_message (&(add_trail->source_peer),
4251 &(add_trail->destination_peer),
4252 trail, trail_length,target_friend);
4258 /* No space left in my routing table. How should we handle this case? */
4259 return GNUNET_SYSERR;
4265 * FIXME: Adapt the code for List of trails.
4266 * Iterate over finger_peermap, and remove entries with peer as the first element
4268 * @param cls closure
4269 * @param key current public key
4270 * @param value value in the hash map
4271 * @return #GNUNET_YES if we should continue to
4273 * #GNUNET_NO if not.
4276 remove_matching_finger (void *cls,
4277 const struct GNUNET_PeerIdentity *key,
4280 struct FingerInfo *remove_finger = value;
4281 const struct GNUNET_PeerIdentity *disconnected_peer = cls;
4283 if (remove_finger->first_trail_length > 0)
4285 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&remove_finger->first_trail_head->peer, disconnected_peer))
4287 GNUNET_assert (GNUNET_YES ==
4288 GNUNET_CONTAINER_multipeermap_remove (finger_peermap,
4291 free_finger (remove_finger);
4294 else if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(remove_finger->finger_identity),
4297 GNUNET_assert (GNUNET_YES ==
4298 GNUNET_CONTAINER_multipeermap_remove (finger_peermap,
4301 free_finger (remove_finger);
4309 * Method called whenever a peer disconnects.
4311 * @param cls closure
4312 * @param peer peer identity this notification is about
4315 handle_core_disconnect (void *cls,
4316 const struct GNUNET_PeerIdentity *peer)
4318 struct FriendInfo *remove_friend;
4320 /* Check for self message. */
4321 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
4324 /* Search for peer to remove in your friend_peermap. */
4326 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
4328 if (NULL == remove_friend)
4334 /* Remove fingers for which this peer is the first element in the trail or if
4335 * the friend is a finger. */
4336 GNUNET_CONTAINER_multipeermap_iterate (finger_peermap,
4337 &remove_matching_finger, (void *)peer);
4338 GDS_ROUTING_remove_entry (peer);
4340 /* Remove the peer from friend_peermap. */
4341 GNUNET_assert (GNUNET_YES ==
4342 GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
4346 if (0 != GNUNET_CONTAINER_multipeermap_size (friend_peermap))
4349 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
4351 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
4352 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
4360 * Method called whenever a peer connects.
4362 * @param cls closure
4363 * @param peer_identity peer identity this notification is about
4366 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity)
4368 struct FriendInfo *friend;
4370 /* Check for connect to self message */
4371 if (0 == memcmp (&my_identity, peer_identity, sizeof (struct GNUNET_PeerIdentity)))
4374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to %s\n", GNUNET_i2s (peer_identity));
4376 /* If peer already exists in our friend_peermap, then exit. */
4377 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (friend_peermap, peer_identity))
4383 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
4386 friend = GNUNET_new (struct FriendInfo);
4387 friend->id = *peer_identity;
4388 friend->trails_count = 0;
4390 GNUNET_assert (GNUNET_OK ==
4391 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
4392 peer_identity, friend,
4393 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
4395 /* got a first connection, good time to start with FIND FINGER TRAIL requests... */
4396 if (GNUNET_SCHEDULER_NO_TASK == find_finger_trail_task)
4397 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
4402 * To be called on core init/fail.
4404 * @param cls service closure
4405 * @param identity the public identity of this peer
4408 core_init (void *cls,
4409 const struct GNUNET_PeerIdentity *identity)
4411 my_identity = *identity;
4416 * Initialize neighbours subsystem.
4417 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4420 GDS_NEIGHBOURS_init (void)
4422 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
4423 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0},
4424 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0},
4425 {&handle_dht_p2p_get_result, GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT, 0},
4426 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP, 0},
4427 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT, 0},
4428 {&handle_dht_p2p_verify_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR, 0},
4429 {&handle_dht_p2p_verify_successor_result, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT, 0},
4430 {&handle_dht_p2p_notify_new_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR, 0},
4431 {&handle_dht_p2p_trail_rejection, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION, 0},
4432 {&handle_dht_p2p_trail_teardown, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_TEARDOWN, 0},
4433 {&handle_dht_p2p_add_trail, GNUNET_MESSAGE_TYPE_DHT_P2P_ADD_TRAIL, 0},
4438 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
4439 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
4440 GNUNET_NO, core_handlers);
4441 if (NULL == core_api)
4442 return GNUNET_SYSERR;
4444 friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
4445 finger_peermap = GNUNET_CONTAINER_multipeermap_create (MAX_FINGERS * 4/3, GNUNET_NO);
4452 * Shutdown neighbours subsystem.
4455 GDS_NEIGHBOURS_done (void)
4457 if (NULL == core_api)
4460 GNUNET_CORE_disconnect (core_api);
4463 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
4464 GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
4465 friend_peermap = NULL;
4467 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (finger_peermap));
4468 GNUNET_CONTAINER_multipeermap_destroy (finger_peermap);
4469 finger_peermap = NULL;
4471 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
4474 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
4475 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
4483 * @return my identity
4485 struct GNUNET_PeerIdentity
4486 GDS_NEIGHBOURS_get_my_id (void)
4492 /* end of gnunet-service-xdht_neighbours.c */