2 This file is part of GNUnet.
3 (C) 2009-2014 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file dht/gnunet-service-xdht_neighbours.c
23 * @brief GNUnet DHT service's finger and friend table management code
24 * @author Supriti Singh
28 #include "gnunet_util_lib.h"
29 #include "gnunet_block_lib.h"
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_protocols.h"
33 #include "gnunet_ats_service.h"
34 #include "gnunet_core_service.h"
35 #include "gnunet_datacache_lib.h"
36 #include "gnunet_transport_service.h"
37 #include "gnunet_dht_service.h"
38 #include "gnunet_statistics_service.h"
39 #include "gnunet-service-xdht.h"
40 #include "gnunet-service-xdht_clients.h"
41 #include "gnunet-service-xdht_datacache.h"
42 #include "gnunet-service-xdht_neighbours.h"
43 #include "gnunet-service-xdht_routing.h"
48 1. Use a global array of all known peers in find_successor, Only when
49 a new peer is added in finger or friend peer map, then re calculate
50 the array. Or else use the old one. The benefit of having this list is something
51 * I am not sure. only when the code is complete and working I will do this part.
52 2. Structure alignment.
53 3. In case of trail setup, you can see the comment on top of finger map index,
54 * trial length --> in NBO. Check how do we keep it in NBO, and make sure its
55 * same everywhere. When i send any message across the network i use htonl, so that
56 * converts it into network byte order.
57 4.THAT IN ROUTING TABLE SOURCE PEER IS INDEED THE SOURCE PEER.
58 should trail contain last element as finger or just the last element.? if
59 you can get some value then you should not keep at different places.
60 remove finger as last element in the trail.
61 5. I have removed the last element in the trail which was finger identity as we
62 * are already sending finger identity in the message. handle the case in case
63 * of notify new successor and verify the successor. */
66 * Maximum possible fingers of a peer.
68 #define MAX_FINGERS 65
71 * Maximum allowed number of pending messages per friend peer.
73 #define MAXIMUM_PENDING_PER_FRIEND 64
76 * How long to wait before sending another find finger trail request
78 #define DHT_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
81 * How long at most to wait for transmission of a request to another peer?
83 #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
85 GNUNET_NETWORK_STRUCT_BEGIN
93 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
95 struct GNUNET_MessageHeader header;
100 uint32_t options GNUNET_PACKED;
105 uint32_t block_type GNUNET_PACKED;
110 uint32_t hop_count GNUNET_PACKED;
113 * Replication level for this message
114 * In the current implementation, this value is not used.
116 uint32_t desired_replication_level GNUNET_PACKED;
119 * Length of the PUT path that follows (if tracked).
121 uint32_t put_path_length GNUNET_PACKED;
124 * Current destination to which this message is forwarded.
126 struct GNUNET_PeerIdentity current_destination;
129 * Peer whose finger is current_destination.
131 struct GNUNET_PeerIdentity current_source;
134 * When does the content expire?
136 struct GNUNET_TIME_AbsoluteNBO expiration_time;
139 * The key to store the value under.
141 struct GNUNET_HashCode key GNUNET_PACKED;
143 /* put path (if tracked) */
153 struct PeerGetResultMessage
156 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT
158 struct GNUNET_MessageHeader header;
161 * The type for the data.
163 uint32_t type GNUNET_PACKED;
166 * Peer which will receive the get result message.
168 struct GNUNET_PeerIdentity source_peer;
171 * Number of peers recorded in the outgoing path from source to the
172 * stored location of this message.
174 uint32_t put_path_length GNUNET_PACKED;
177 * Length of the GET path that follows (if tracked).
179 uint32_t get_path_length GNUNET_PACKED;
182 * When does the content expire?
184 struct GNUNET_TIME_Absolute expiration_time;
187 * The key of the corresponding GET request.
189 struct GNUNET_HashCode key;
191 /* put path (if tracked) */
193 /* get path (if tracked) */
203 struct PeerGetMessage
206 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET
208 struct GNUNET_MessageHeader header;
213 uint32_t options GNUNET_PACKED;
216 * Desired content type.
218 uint32_t block_type GNUNET_PACKED;
223 uint32_t hop_count GNUNET_PACKED;
226 * Desired replication level for this request.
227 * In the current implementation, this value is not used.
229 uint32_t desired_replication_level GNUNET_PACKED;
232 * Total number of peers in get path.
234 unsigned int get_path_length;
237 * Peer which is an intermediate destination.
239 struct GNUNET_PeerIdentity current_destination;
242 * Source for which current_destination is the finger.
244 struct GNUNET_PeerIdentity current_source;
247 * The key we are looking for.
249 struct GNUNET_HashCode key;
257 * P2P Trail setup message
259 struct PeerTrailSetupMessage
263 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP
265 struct GNUNET_MessageHeader header;
268 * Successor of this finger value will be our finger peer.
270 uint64_t destination_finger;
273 * Source peer which wants to setup the trail to one of its finger.
275 struct GNUNET_PeerIdentity source_peer;
278 * Peer to which this packet is forwarded.
280 struct GNUNET_PeerIdentity current_destination;
283 * In case the packet is forwarded to an intermediate finger, then
284 * current_source contains the peer id whose finger is the intermediate
285 * finger. In case the packet is forwarded to a friend, then it is NULL.
286 * FIXME: check the usage of current_source and fix this comment.
288 struct GNUNET_PeerIdentity current_source;
291 * Index into finger peer map, in Network Byte Order.
293 uint32_t finger_map_index;
296 * Number of entries in trail list, in Network Byte Order.
298 uint32_t trail_length GNUNET_PACKED;
300 /* Trail formed in the process. */
305 * P2P Trail Setup Result message
307 struct PeerTrailSetupResultMessage
311 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT
313 struct GNUNET_MessageHeader header;
316 * Finger to which we have found the path.
318 struct GNUNET_PeerIdentity finger_identity;
321 * Peer which was looking for the trail to finger.
323 struct GNUNET_PeerIdentity destination_peer;
326 * Index into finger peer map in NBO.
328 uint32_t finger_map_index;
331 * Number of entries in trail list in NBO.
333 uint32_t trail_length GNUNET_PACKED;
335 /* Trail from destination_peer to finger_identity */
341 * P2P Trail Rejection Message.
343 struct PeerTrailRejectionMessage
346 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION
348 struct GNUNET_MessageHeader header;
351 * Source peer which wants to set up the trail.
353 struct GNUNET_PeerIdentity source_peer;
356 * Peer which sent trail rejection message.
358 struct GNUNET_PeerIdentity congested_peer;
361 * Peer identity which will be successor to this value will be finger of
364 uint64_t finger_identity_value;
367 * Index in finger peer map of source peer.
369 uint32_t finger_map_index;
372 * Total number of peers in the trail.
374 uint32_t trail_length;
376 /* Trail_list from source_peer to peer which sent the message for trail setup
377 * to congested peer.*/
382 * P2P Verify Successor message.
384 struct PeerVerifySuccessorMessage
388 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR
390 struct GNUNET_MessageHeader header;
393 * Source peer which wants to verify its successor.
395 struct GNUNET_PeerIdentity source_peer;
398 * My current successor.
400 struct GNUNET_PeerIdentity successor;
403 * Total number of peers in trail to current successor.
405 uint32_t trail_length;
407 /* Trail to reach to from source_peer to successor. */
412 * P2P Verify Successor Result message.
414 struct PeerVerifySuccessorResultMessage
418 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT
420 struct GNUNET_MessageHeader header;
423 * Destination peer which sent the request to verify its successor.
425 struct GNUNET_PeerIdentity destination_peer;
428 * Successor to which PeerVerifySuccessorMessage was sent.
430 struct GNUNET_PeerIdentity source_successor;
433 * source_successor's predecessor
435 struct GNUNET_PeerIdentity my_predecessor;
438 * Total number of peers in trail.
440 uint32_t trail_length;
442 /* Trail to reach from destination_peer to its correct successor.
443 * If source_successor is not destination peer, then trail is from destination_peer
445 * If source_successor is destination peer, then trail is from destination_peer
446 * to source_successor. */
451 * P2P Notify New Successor message.
453 struct PeerNotifyNewSuccessorMessage
456 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR
458 struct GNUNET_MessageHeader header;
461 * Source peer which wants to notify its new successor.
463 struct GNUNET_PeerIdentity source_peer;
466 * New successor identity.
468 struct GNUNET_PeerIdentity destination_peer;
471 * Number of peers in trail from source_peer to new successor.
473 uint32_t trail_length;
475 /* Trail to from source_peer to destination_peer. */
478 struct PeerTrailTearDownMessage
481 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_TEARDOWN
483 struct GNUNET_MessageHeader header;
486 * Source peer which wants to notify its new successor.
488 struct GNUNET_PeerIdentity source_peer;
491 * New successor identity.
493 struct GNUNET_PeerIdentity destination_peer;
496 * Number of peers in trail from source_peer to new successor.
498 uint32_t trail_length;
500 /* Trail to from source_peer to destination_peer. */
503 GNUNET_NETWORK_STRUCT_END
507 * Linked list of messages to send to a particular other peer.
509 struct P2PPendingMessage
512 * Pointer to next item in the list
514 struct P2PPendingMessage *next;
517 * Pointer to previous item in the list
519 struct P2PPendingMessage *prev;
522 * Message importance level. FIXME: used? useful?
524 unsigned int importance;
527 * When does this message time out?
529 struct GNUNET_TIME_Absolute timeout;
532 * Actual message to be sent, allocated at the end of the struct:
533 * // msg = (cast) &pm[1];
534 * // memcpy (&pm[1], data, len);
536 const struct GNUNET_MessageHeader *msg;
542 * Linked List of peers which are part of trail to reach a particular Finger.
547 * Pointer to next item in the list
549 struct TrailPeerList *next;
552 * Pointer to previous item in the list
554 struct TrailPeerList *prev;
557 * An element in this trail list
559 struct GNUNET_PeerIdentity peer;
565 * Entry in friend_peermap.
572 struct GNUNET_PeerIdentity id;
575 * 1. used in select_random_friend(), in case the friend has trails_count > TRAILS_THROUGH_FRIEND,
576 * then choose another friend.
577 * 2. in case of find_successor(), if the number of trails going through the friend
578 * has already crossed, then choose another friend.
579 * 3. in case of find_successor(), if we choose a finger, and if friend through
580 * which we reach this finger has crossed the limit then choose another finger/friend.
581 * 4. One way to implement in case of find_successor, is 1) you can have a global
582 * array of the entries and only when an entry is added in finger table, friend table,
583 * then you re calculate the array. In array while adding the element you check
584 * the threshold of the friend in case its friend, and in case of finger check
585 * the threshold of the first friend in the trail. If crossed then don't add the
586 * entries in the array. When the count goes down, then again set a flag and
587 * recalculte the array. Store a field in Finger table also, which will be
588 * equal to number of trails going through the first friend.
589 * Number of trail of which this friend is the first hop.
590 * 5.FIXME: understand where you need to use memcpy or direct assignment.
592 unsigned int trails_count;
595 * Count of outstanding messages for this friend.
597 unsigned int pending_count;
600 * Head of pending messages to be sent to this friend.
602 struct P2PPendingMessage *head;
605 * Tail of pending messages to be sent to this friend.
607 struct P2PPendingMessage *tail;
610 * Core handle for sending messages to this friend.
612 struct GNUNET_CORE_TransmitHandle *th;
618 * Entry in finger_peermap.
625 struct GNUNET_PeerIdentity finger_identity;
628 * Index in finger peer map
630 unsigned int finger_map_index;
633 * Number of trails to reach to this finger.
635 unsigned int trail_count;
638 * Total number of entries in first trail from (me,finger)
640 unsigned int first_trail_length;
643 * Total number of entries in second trail from (me,finger)
645 unsigned int second_trail_length;
649 * Number of trail of which the first element to reach to this finger is
652 unsigned int first_friend_trails_count;
655 * Head of first trail to reach this finger.
657 struct TrailPeerList *first_trail_head;
660 * Tail of first trail to reach this finger.
662 struct TrailPeerList *first_trail_tail;
665 * Head of second trail to reach this finger.
667 struct TrailPeerList *second_trail_head;
670 * Tail of second trail to reach this finger.
672 struct TrailPeerList *second_trail_tail;
678 * FIXME: The name is not correct.
679 * Used to specify the kind of value stored in the array all_known_peers.
681 enum current_destination_type
691 * Data structure passed to sorting algorithm in find_successor().
696 * 64 bit value of peer identity
701 * FIXME: think of a better name for both the struct and destination_type
702 * Type : MY_ID, FINGER, FINGER, Value
704 enum current_destination_type type;
707 * Pointer to original data structure linked to peer id.
714 * Task that sends FIND FINGER TRAIL requests. This task is started when we have
715 * get our first friend.
717 static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task;
720 * Task that periodically verifies my successor. This task is started when we
721 * have found our successor.
723 static GNUNET_SCHEDULER_TaskIdentifier verify_successor;
726 * Identity of this peer.
728 static struct GNUNET_PeerIdentity my_identity;
731 * Hash map of all the friends of a peer
733 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap;
736 * Hash map of all the fingers of a peer
738 static struct GNUNET_CONTAINER_MultiPeerMap *finger_peermap;
743 static struct GNUNET_CORE_Handle *core_api;
746 * Finger map index for predecessor entry in finger peermap.
748 #define PREDECESSOR_FINGER_ID 64
751 * Maximum number of trails allowed to go through a friend.
752 * FIXME: Better name, Random value at the moment, need to be adjusted to maintain a balance
753 * between performance and Sybil tolerance.
755 #define TRAIL_THROUGH_FRIEND_THRESHOLD 64
758 * Possible number of different trails to reach to a finger. (Redundant routing)
760 #define TRAIL_COUNT 2
763 * FIXME: better name.
764 * Set to GNUNET_YES, when the number of trails going through all my friends
765 * have reached the TRAIL_THROUGH_FRIEND_THRESHOLD.
767 static unsigned int all_friends_trail_threshold;
770 * The current finger index that we have want to find trail to.
772 static unsigned int current_search_finger_index;
776 * Iterate over trail and search your index location in the array.
777 * @param trail Trail which contains list of peers.
778 * @param trail_length Number of peers in the trail.
779 * @return Index in the array.
780 * #GNUNET_SYSERR, in case there is no entry which should not be the case ideally.
783 search_my_index (const struct GNUNET_PeerIdentity *trail,
788 while (i < trail_length)
790 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &trail[i]))
796 return GNUNET_SYSERR;
801 * Invert the trail list.
802 * @param existing_trail Trail
803 * @param trail_length Number of peers in the existing trail.
806 static struct GNUNET_PeerIdentity *
807 invert_trail_list (struct GNUNET_PeerIdentity *existing_trail,
808 unsigned int trail_length)
812 struct GNUNET_PeerIdentity *new_trail;
815 new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * trail_length);
817 if (trail_length > 1)
819 i = trail_length - 2;
822 memcpy( &new_trail[j], &existing_trail[i], sizeof (struct GNUNET_PeerIdentity));
832 * Called when core is ready to send a message we asked for
833 * out to the destination.
835 * @param cls the 'struct FriendInfo' of the target friend
836 * @param size number of bytes available in buf
837 * @param buf where the callee should write the message
838 * @return number of bytes written to buf
841 core_transmit_notify (void *cls, size_t size, void *buf)
843 struct FriendInfo *peer = cls;
845 struct P2PPendingMessage *pending;
850 while ((NULL != (pending = peer->head)) &&
851 (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us))
853 peer->pending_count--;
854 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
855 GNUNET_free (pending);
859 /* no messages pending */
865 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
866 GNUNET_CORE_PRIO_BEST_EFFORT,
867 GNUNET_TIME_absolute_get_remaining
868 (pending->timeout), &peer->id,
869 ntohs (pending->msg->size),
870 &core_transmit_notify, peer);
871 GNUNET_break (NULL != peer->th);
875 while ((NULL != (pending = peer->head)) &&
876 (size - off >= (msize = ntohs (pending->msg->size))))
878 GNUNET_STATISTICS_update (GDS_stats,
880 ("# Bytes transmitted to other peers"), msize,
882 memcpy (&cbuf[off], pending->msg, msize);
884 peer->pending_count--;
885 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
886 GNUNET_free (pending);
888 if (peer->head != NULL)
891 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
892 GNUNET_CORE_PRIO_BEST_EFFORT,
893 GNUNET_TIME_absolute_get_remaining
894 (pending->timeout), &peer->id, msize,
895 &core_transmit_notify, peer);
896 GNUNET_break (NULL != peer->th);
904 * Transmit all messages in the friend's message queue.
906 * @param peer message queue to process
909 process_friend_queue (struct FriendInfo *peer)
911 struct P2PPendingMessage *pending;
913 if (NULL == (pending = peer->head))
915 if (NULL != peer->th)
918 GNUNET_STATISTICS_update (GDS_stats,
920 ("# Bytes of bandwidth requested from core"),
921 ntohs (pending->msg->size), GNUNET_NO);
923 /* FIXME: Are we correctly initializing importance and pending. */
925 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
927 GNUNET_TIME_absolute_get_remaining
928 (pending->timeout), &peer->id,
929 ntohs (pending->msg->size),
930 &core_transmit_notify, peer);
931 GNUNET_break (NULL != peer->th);
936 * Construct a trail message and forward it to a friend.
937 * @param source_peer Peer which wants to set up the trail to one of its finger.
938 * @param destination_finger Peer identity closest to this value will be
939 * @a source_peer's finger.
940 * @param current_destination Finger of the @a current_source, for which among
941 * its friends, its own identity and all fingers, this
942 * finger is the closest to the @a destination_finger
943 * @param current_source Peer for which @a current_destination is its finger.
944 * @param target_friend Friend to which this message should be forwarded.
945 * @param trail_length Numbers of peers in the trail found so far.
946 * @param trail_peer_list Peers this request has traversed so far
947 * @param finger_map_index Index in finger peer map
950 GDS_NEIGHBOURS_send_trail_setup (const struct GNUNET_PeerIdentity *source_peer,
951 uint64_t destination_finger,
952 struct GNUNET_PeerIdentity *current_destination,
953 struct GNUNET_PeerIdentity *current_source,
954 struct FriendInfo *target_friend,
955 unsigned int trail_length,
956 const struct GNUNET_PeerIdentity *trail_peer_list,
957 unsigned int finger_map_index)
959 struct P2PPendingMessage *pending;
960 struct PeerTrailSetupMessage *tsm;
961 struct GNUNET_PeerIdentity *peer_list;
964 msize = sizeof (struct PeerTrailSetupMessage) +
965 (trail_length * sizeof (struct GNUNET_PeerIdentity));
967 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
973 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
975 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
979 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
980 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
981 tsm = (struct PeerTrailSetupMessage *) &pending[1];
982 pending->msg = &tsm->header;
983 tsm->header.size = htons (msize);
984 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
985 memcpy (&(tsm->destination_finger), &destination_finger, sizeof (uint64_t));
986 memcpy (&(tsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
987 memcpy (&(tsm->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity));
988 memcpy (&(tsm->current_source), current_source, sizeof (struct GNUNET_PeerIdentity));
989 tsm->trail_length = htonl (trail_length);
990 tsm->finger_map_index = htonl (finger_map_index);
992 if (trail_peer_list != NULL)
994 peer_list = (struct GNUNET_PeerIdentity *) &tsm[1];
995 memcpy (peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
998 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
999 target_friend->pending_count++;
1000 process_friend_queue (target_friend);
1006 * Construct a trail setup result message and forward it to a friend.
1007 * @param destination_peer Peer which will get the trail to one of its finger.
1008 * @param source_finger Peer to which the trail has been setup to.
1009 * @param target_friend Friend to which this message should be forwarded.
1010 * @param trail_length Numbers of peers in the trail.
1011 * @param trail_peer_list Peers which are part of the trail from source to destination.
1012 * @param finger_map_index Index in finger peer map
1015 GDS_NEIGHBOURS_send_trail_setup_result (const struct GNUNET_PeerIdentity *destination_peer,
1016 const struct GNUNET_PeerIdentity *source_finger,
1017 struct FriendInfo *target_friend,
1018 unsigned int trail_length,
1019 const struct GNUNET_PeerIdentity *trail_peer_list,
1020 unsigned int finger_map_index)
1022 struct P2PPendingMessage *pending;
1023 struct PeerTrailSetupResultMessage *tsrm;
1024 struct GNUNET_PeerIdentity *peer_list;
1027 msize = sizeof (struct PeerTrailSetupResultMessage) +
1028 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1030 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1036 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1038 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1042 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1043 pending->importance = 0;
1044 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1045 tsrm = (struct PeerTrailSetupResultMessage *) &pending[1];
1046 pending->msg = &tsrm->header;
1047 tsrm->header.size = htons (msize);
1048 tsrm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT);
1049 memcpy (&(tsrm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1050 memcpy (&(tsrm->finger_identity), source_finger, sizeof (struct GNUNET_PeerIdentity));
1051 tsrm->trail_length = htonl (trail_length);
1052 tsrm->finger_map_index = htonl (finger_map_index);
1054 peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1];
1055 if (trail_length > 0)
1056 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1058 /* Send the message to chosen friend. */
1059 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1060 target_friend->pending_count++;
1061 process_friend_queue (target_friend);
1066 * Construct a PeerVerifySuccessor message and send it to friend.
1067 * @param source_peer Peer which wants to verify its successor
1068 * @param successor Peer which is our current successor
1069 * @param target_friend Friend to which this message should be forwarded.
1070 * @param trail_peer_list Peer which are part of trail from source to destination
1071 * @param trail_length Number of peers in the trail list.
1073 void GDS_NEIGHBOURS_send_verify_successor(const struct GNUNET_PeerIdentity *source_peer,
1074 const struct GNUNET_PeerIdentity *successor,
1075 struct FriendInfo *target_friend,
1076 const struct GNUNET_PeerIdentity *trail_peer_list,
1077 unsigned int trail_length)
1079 struct PeerVerifySuccessorMessage *vsm;
1080 struct P2PPendingMessage *pending;
1081 struct GNUNET_PeerIdentity *peer_list;
1084 msize = sizeof (struct PeerVerifySuccessorMessage) +
1085 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1087 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1093 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1095 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1099 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1100 pending->importance = 0; /* FIXME */
1101 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1102 vsm = (struct PeerVerifySuccessorMessage *) &pending[1];
1103 pending->msg = &vsm->header;
1104 vsm->header.size = htons (msize);
1105 vsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR);
1106 memcpy (&(vsm->successor), successor, sizeof (struct GNUNET_PeerIdentity));
1107 memcpy (&(vsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1108 vsm->trail_length = htonl (trail_length);
1109 peer_list = (struct GNUNET_PeerIdentity *) &vsm[1];
1110 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1112 /* Send the message to chosen friend. */
1113 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1114 target_friend->pending_count++;
1115 process_friend_queue (target_friend);
1121 * Construct a PeerVerifySuccessorResult message and send it to friend.
1122 * @param destination_peer Peer which sent verify successor message
1123 * @param source_successor Peer to which verify successor message was sent.
1124 * @param my_predecessor source_successor's predecessor.
1125 * @param target_friend Friend to which this message should be forwarded.
1126 * @param trail_peer_list Peers which are part of trail from source to destination
1127 * @param trail_length Number of peers in the trail list.
1129 void GDS_NEIGHBOURS_send_verify_successor_result (const struct GNUNET_PeerIdentity *destination_peer,
1130 const struct GNUNET_PeerIdentity *source_successor,
1131 const struct GNUNET_PeerIdentity *my_predecessor,
1132 struct FriendInfo *target_friend,
1133 const struct GNUNET_PeerIdentity *trail_peer_list,
1134 unsigned int trail_length)
1136 struct PeerVerifySuccessorResultMessage *vsmr;
1137 struct P2PPendingMessage *pending;
1138 struct GNUNET_PeerIdentity *peer_list;
1141 msize = sizeof (struct PeerVerifySuccessorResultMessage) +
1142 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1144 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1151 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1153 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1157 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1158 pending->importance = 0; /* FIXME */
1159 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1160 vsmr = (struct PeerVerifySuccessorResultMessage *) &pending[1];
1161 pending->msg = &vsmr->header;
1162 vsmr->header.size = htons (msize);
1163 vsmr->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT);
1164 memcpy (&(vsmr->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1165 memcpy (&(vsmr->source_successor), source_successor, sizeof (struct GNUNET_PeerIdentity));
1166 memcpy (&(vsmr->my_predecessor), my_predecessor, sizeof (struct GNUNET_PeerIdentity));
1167 vsmr->trail_length = htonl (trail_length);
1168 peer_list = (struct GNUNET_PeerIdentity *) &vsmr[1];
1169 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1171 /* Send the message to chosen friend. */
1172 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1173 target_friend->pending_count++;
1174 process_friend_queue (target_friend);
1179 * Construct a PeerNotifyNewSuccessor message and send it to friend.
1180 * @param source_peer Peer which is sending notify message to its new successor.
1181 * @param destination_peer Peer which is the new destination.
1182 * @param target_friend Next friend to pass this message to.
1183 * @param peer_list List of peers in the trail to reach to destination_peer.
1184 * @param trail_length Total number of peers in peer list
1187 GDS_NEIGHBOURS_send_notify_new_successor (const struct GNUNET_PeerIdentity *source_peer,
1188 const struct GNUNET_PeerIdentity *destination_peer,
1189 struct FriendInfo *target_friend,
1190 const struct GNUNET_PeerIdentity *trail_peer_list,
1191 unsigned int trail_length)
1193 struct PeerNotifyNewSuccessorMessage *nsm;
1194 struct P2PPendingMessage *pending;
1195 struct GNUNET_PeerIdentity *peer_list;
1198 msize = sizeof (struct PeerNotifyNewSuccessorMessage) +
1199 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1201 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1207 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1209 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1213 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1214 pending->importance = 0; /* FIXME */
1215 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1216 nsm = (struct PeerNotifyNewSuccessorMessage *) &pending[1];
1217 pending->msg = &nsm->header;
1218 nsm->header.size = htons (msize);
1219 nsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR);
1220 memcpy (&(nsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1221 memcpy (&(nsm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1222 nsm->trail_length = htonl (trail_length);
1224 peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
1225 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1227 /* Send the message to chosen friend. */
1228 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1229 target_friend->pending_count++;
1230 process_friend_queue (target_friend);
1234 * Send a trail tear down message
1235 * @param source_peer Source of the trail.
1236 * @param destination_peer Destination of the trail.
1237 * @param trail_list Peers in the trail from @a source_peer to @a destination_peer
1238 * @param trail_length Total number of peers in trail_list.
1239 * @pararm target_peer Next peer to forward this message to.
1242 GDS_NEIGHBOURS_send_trail_teardown (struct GNUNET_PeerIdentity *source_peer,
1243 const struct GNUNET_PeerIdentity *destination_peer,
1244 struct GNUNET_PeerIdentity *trail_peer_list,
1245 unsigned int trail_length,
1246 struct FriendInfo *target_friend)
1248 struct P2PPendingMessage *pending;
1249 struct PeerTrailTearDownMessage *ttdm;
1250 struct GNUNET_PeerIdentity *peer_list;
1253 msize = sizeof (struct PeerTrailTearDownMessage) +
1254 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1256 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1262 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1264 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1268 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1269 pending->importance = 0; /* FIXME */
1270 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1271 ttdm = (struct PeerTrailTearDownMessage *) &pending[1];
1272 pending->msg = &ttdm->header;
1273 ttdm->header.size = htons (msize);
1274 ttdm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_TEARDOWN);
1275 memcpy (&(ttdm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1276 memcpy (&(ttdm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1277 ttdm->trail_length = htonl (trail_length);
1279 peer_list = (struct GNUNET_PeerIdentity *) &ttdm[1];
1280 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 * FIXME: Handle congested peer - don't choose this friend, also don't choose
1291 * the friend if the link threshold has crossed. Not implemented yet.
1292 * Randomly choose one of your friends from the friends_peer map
1295 static struct FriendInfo *
1296 select_random_friend (struct GNUNET_PeerIdentity *congested_peer)
1298 unsigned int current_size;
1299 unsigned int *index;
1301 struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
1302 struct GNUNET_PeerIdentity key_ret;
1303 struct FriendInfo *friend;
1305 current_size = GNUNET_CONTAINER_multipeermap_size (friend_peermap);
1306 index = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, current_size);
1307 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1311 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,NULL,NULL))
1319 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,&key_ret,(const void **)&friend))
1321 /* Possible number of trails that can go through this friend has been reached. */
1322 if (friend->trails_count > TRAIL_THROUGH_FRIEND_THRESHOLD)
1324 /* FIXME: What should I do now, should I call this same function again and
1325 remember the index, j so that call random function without j and find
1326 a new friend. Also, I need some way to make sure that if number of times
1327 I have called the function is equal to number of entries in friend peermap.
1328 then I should return NULL. but its much better to have a function which
1329 just eliminates looking at the entries with threshold crossed. URGENT: Whats
1330 the best way to handle this case? */
1340 * Compute finger_identity to which we want to setup the trail
1341 * @return finger_identity
1344 compute_finger_identity()
1348 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
1349 my_id64 = GNUNET_ntohll (my_id64);
1350 return (my_id64 + (unsigned long) pow (2, current_search_finger_index));
1355 * Compute immediate predecessor identity in the network.
1356 * @return peer identity of immediate predecessor.
1359 compute_predecessor_identity()
1363 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
1364 my_id64 = GNUNET_ntohll (my_id64);
1365 return (my_id64 -1);
1370 * Periodically ping your successor to ask its current predecessor
1372 * @param cls closure for this task
1373 * @param tc the context under which the task is running
1376 send_verify_successor_message (void *cls,
1377 const struct GNUNET_SCHEDULER_TaskContext *tc )
1379 struct GNUNET_TIME_Relative next_send_time;
1380 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1381 struct GNUNET_PeerIdentity key_ret;
1382 struct FriendInfo *target_friend;
1383 struct GNUNET_PeerIdentity *next_hop;
1384 struct GNUNET_PeerIdentity *peer_list;
1385 struct FingerInfo *finger;
1386 unsigned int finger_index;
1390 /* Find the successor from the finger peermap.*/
1391 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1392 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
1394 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, &key_ret,
1395 (const void **)&finger))
1397 if (0 == finger->finger_map_index)
1404 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
1407 goto send_new_request;
1409 peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * finger->first_trail_length);
1411 struct TrailPeerList *iterate;
1412 iterate = finger->first_trail_head;
1414 while ( i < (finger->first_trail_length))
1416 memcpy (&peer_list[i], &(iterate->peer), sizeof (struct GNUNET_PeerIdentity));
1417 iterate = iterate->next;
1421 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1422 memcpy (next_hop, &peer_list[0], sizeof (struct GNUNET_PeerIdentity));
1423 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
1425 GDS_NEIGHBOURS_send_verify_successor (&my_identity,
1426 &(finger->finger_identity),
1429 finger->first_trail_length);
1432 /* FIXME: Understand what this function is actually doing here. */
1434 next_send_time.rel_value_us =
1435 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
1436 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1437 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us);
1440 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_verify_successor_message,
1446 * Choose a random friend and start looking for the trail to reach to
1447 * finger identity through this random friend.
1449 * @param cls closure for this task
1450 * @param tc the context under which the task is running
1453 send_find_finger_trail_message (void *cls,
1454 const struct GNUNET_SCHEDULER_TaskContext *tc)
1456 struct FriendInfo *target_friend;
1457 struct GNUNET_TIME_Relative next_send_time;
1458 uint64_t finger_identity;
1459 unsigned int finger_map_index;
1461 next_send_time.rel_value_us =
1462 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
1463 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1464 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us);
1466 /* FIXME; if all the friend have reached their threshold, then don't schedule
1467 * the task till the all_friends_trail_threshold gets reset. It will be
1468 * scheduled from there. So, in finger table when we remove an entry and the new
1469 * entry does not have the same friend as the first hop, then decrement the
1470 * threshold limit. and schedule this task.
1471 IMPORTANT: reset the value some where. Better name */
1472 if (GNUNET_YES == all_friends_trail_threshold)
1477 find_finger_trail_task =
1478 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_finger_trail_message,
1481 /* Friend peermap is empty but this task has already been started it failed.*/
1482 if (GNUNET_CONTAINER_multipeermap_size (friend_peermap) == 0)
1488 target_friend = select_random_friend (NULL);
1490 if (NULL == target_friend)
1492 /* FIXME URGENT: Here we can get NULL all of the friends have reached their threshold.
1493 * At the moment, the code for select_random_friend, is not handling it. In such a
1494 * case I think we can set a flag, and only when any value for any friend gets
1495 * decremented,(which can happen only in finger table, when we remove an entry
1496 * from our finger table, and we are not part of the trail to reach to that
1497 * finger any more, t then reset the flag and schedule the code from there. */
1498 all_friends_trail_threshold = GNUNET_YES;
1502 if (PREDECESSOR_FINGER_ID == current_search_finger_index)
1504 finger_identity = compute_predecessor_identity();
1508 finger_identity = compute_finger_identity();
1511 finger_map_index = current_search_finger_index;
1513 /* URGENT :FIXME: In case the packet is not sent to a finger, then current_source is the
1514 * peer which sent the packet and current_destination which recevied it. Now
1515 * these fields are not always used. Think of some way to remove these variables. */
1516 GDS_NEIGHBOURS_send_trail_setup (&my_identity, finger_identity, &(target_friend->id),
1517 &my_identity, target_friend, 0, NULL, finger_map_index);
1522 * FIXME: How do I send back the updated trail.
1523 * Scan the trail to check if any on my own friend is part of trail. If yes
1524 * the shortcut the trail and update the finger_trail and trail_length.
1525 * @param finger_trail
1526 * @param trail_length
1529 static struct GNUNET_PeerIdentity *
1530 scan_and_compress_trail (struct GNUNET_PeerIdentity *finger_trail, unsigned int trail_length,
1531 const struct GNUNET_PeerIdentity *finger)
1533 /* start from the second element as first element will always be your friend.
1534 In case trail_length = 2, and the last element is also your friend then you
1535 should delete the first element. In other cases go through the list and check
1537 int i = trail_length - 1;
1541 if (NULL == GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger_trail[i]))
1543 /* This element of trail is not my friend. */
1548 /* If for any i>1 we found a friend, then we can use this friend as the
1549 first link and forget about all the peers behind it. But we need to first
1550 copy the peers behind it. send a trail tear down message along
1552 struct GNUNET_PeerIdentity *discarded_trail;
1553 struct FriendInfo *target_friend;
1554 /* FIXME: Create a new trail. to send back*/
1555 int discarded_trail_length = trail_length - i;
1557 discarded_trail = GNUNET_malloc (discarded_trail_length * sizeof (struct GNUNET_PeerIdentity));
1559 while (j < (discarded_trail_length + 1))
1561 memcpy (&discarded_trail[j], &finger_trail[j], sizeof (struct GNUNET_PeerIdentity));
1565 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger_trail[0]);
1566 /* FIXME: THAT IN ROUTING TABLE SOURCE PEER IS INDEED THE SOURCE PEER.
1567 * should trail contain last element as finger or just the last element.? if
1568 * you can get some value then you should not keep at different places.
1569 * remove finger as last element in the trail. */
1570 GDS_NEIGHBOURS_send_trail_teardown (&my_identity, finger, discarded_trail,
1571 discarded_trail_length, target_friend);
1573 /* fixme: CHANGE IT TO NEW TRAIL */
1583 * To see the logic better, I guess it better that function calling
1584 * free_finger, decrement the count of the trail going through them
1585 * reset all_friends_trail_threshold. In case you are removing an entry from
1586 * finger table, and the new entry has the first friend different from the old
1587 * entry, then reset this all_friends_trail_threshold, if it is set to GNUNET_YES.
1588 * and also schedule send_find_finger_trail_message.
1589 * Free finger and its trail.
1590 * @param remove_finger Finger to be freed.
1593 free_finger (struct FingerInfo *finger)
1595 struct TrailPeerList *peer;
1596 struct FriendInfo *first_trail_friend;
1597 struct FriendInfo *second_trail_friend;
1599 first_trail_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1600 &(finger->first_trail_head->peer));
1601 second_trail_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1602 &(finger->second_trail_head->peer));
1604 first_trail_friend->trails_count--;
1605 second_trail_friend->trails_count--;
1607 /* FIXME: Here we should reset the all_peers_trail_count to GNUNET_NO, and
1608 send_find_finger_trail_message. */
1609 while (NULL != (peer = finger->first_trail_head))
1611 GNUNET_CONTAINER_DLL_remove (finger->first_trail_head, finger->first_trail_tail, peer);
1615 while (NULL != (peer = finger->second_trail_head))
1617 GNUNET_CONTAINER_DLL_remove (finger->second_trail_head, finger->second_trail_tail, peer);
1620 GNUNET_free (finger);
1625 * FIMXE: Change the function, here you need to invert the trail.
1626 * @param existing_finger
1629 * @param trail_length
1633 int select_correct_predecessor (struct FingerInfo *existing_finger,
1634 const struct GNUNET_PeerIdentity *new_finger,
1635 struct GNUNET_PeerIdentity *trail,
1636 unsigned int trail_length)
1638 int val = GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity), new_finger);
1641 /* FIXME: if the new entry = old entry, then compare the trails, and see if the trails
1642 are disjoint, then send GNUNET_YES, but don't free old finger. But first you
1643 * should collapse the trail and then do comparison. Also, if you are collapsing
1644 * for one case then you should do it for all the cases where you are sending
1646 /* Scan the trail for a friend and shorten if possible. */
1647 scan_and_compress_trail (trail, trail_length, new_finger);
1652 /* If the new entry is closest one, then free the old entry, send a trail_teardown message.*/
1653 struct GNUNET_PeerIdentity *peer_list;
1654 struct FriendInfo *friend;
1655 struct TrailPeerList *finger_trail;
1656 int existing_finger_trail_length = existing_finger->first_trail_length;
1659 finger_trail = existing_finger->first_trail_head;
1660 friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &(finger_trail->peer));
1661 peer_list = GNUNET_malloc ( existing_finger_trail_length * sizeof (struct GNUNET_PeerIdentity));
1662 while (i < existing_finger->first_trail_length)
1664 memcpy (&peer_list[i], &(finger_trail->peer), sizeof (struct GNUNET_PeerIdentity));
1665 finger_trail = finger_trail->next;
1669 GDS_NEIGHBOURS_send_trail_teardown (&my_identity, &(existing_finger->finger_identity),
1670 peer_list, existing_finger_trail_length, friend);
1672 free_finger (existing_finger);
1673 scan_and_compress_trail (trail, trail_length, new_finger);
1678 /* If the old entry is closest then just return GNUNET_NO.*/
1681 return GNUNET_SYSERR;
1686 * Check if there is a predecessor in our finger peer map or not.
1687 * If no, then return GNUNET_YES
1688 * else compare existing predecessor and peer, and find the correct
1690 * @param existing_predecessor
1691 * @param new_predecessor
1692 * @return #GNUNET_YES if new peer is predecessor
1693 * #GNUNET_NO if new peer is not the predecessor.
1696 compare_and_update_predecessor (struct GNUNET_PeerIdentity *peer,
1697 struct GNUNET_PeerIdentity *trail,
1698 unsigned int trail_length)
1700 /* ! HAVE A PREDECESSOR || (source_peer closer than existing PREDECESOR) */
1701 struct FingerInfo *existing_finger;
1702 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1703 struct FingerInfo *new_finger_entry;
1705 int predecessor_flag = 0;
1707 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1708 for (i= 0; i < GNUNET_CONTAINER_multipeermap_size (finger_peermap); i++)
1710 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, NULL,
1711 (const void **)&existing_finger))
1713 if (existing_finger->finger_map_index == PREDECESSOR_FINGER_ID)
1715 predecessor_flag = 1;
1721 if (predecessor_flag != 0)
1723 /* There is a predecessor entry. Now we need to find out which one is
1724 * the closest one. If both are same then how to handle. */
1725 if(select_correct_predecessor (existing_finger, peer, trail, trail_length) == GNUNET_NO)
1730 scan_and_compress_trail (trail, trail_length, peer);
1731 invert_trail_list (trail, trail_length);
1733 FPRINTF (stderr,_("\nSUPU %s, %s, %d"),__FILE__, __func__,__LINE__);
1734 memcpy (&(new_finger_entry->finger_identity), peer, sizeof (struct GNUNET_PeerIdentity));
1735 new_finger_entry->finger_map_index = PREDECESSOR_FINGER_ID;
1736 new_finger_entry->first_trail_length = trail_length;
1738 while (i < trail_length)
1740 struct TrailPeerList *element;
1741 element = GNUNET_malloc (sizeof (struct TrailPeerList));
1742 element->next = NULL;
1743 element->prev = NULL;
1745 memcpy (&(element->peer), &trail[i], sizeof(struct GNUNET_PeerIdentity));
1746 GNUNET_CONTAINER_DLL_insert_tail(new_finger_entry->first_trail_head, new_finger_entry->first_trail_tail, element);
1750 GNUNET_assert (GNUNET_OK ==
1751 GNUNET_CONTAINER_multipeermap_put (finger_peermap,
1752 &(new_finger_entry->finger_identity),
1754 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1761 * FIXME: In this case first you should check which of the trail is longest and
1762 * the just discard it. Right now you are not checking it.
1763 * In case there are already maximum number of possible trail to reach to a finger,
1764 * then check if the new trail can replace an existing one. If yes then replace.
1765 * @param existing_finger
1767 * @param trail_length
1768 * @return #GNUNET_YES
1772 void select_and_replace_trail (struct FingerInfo *existing_finger,
1773 struct GNUNET_PeerIdentity *trail,
1774 unsigned int trail_length)
1776 if (trail_length < existing_finger->first_trail_length)
1778 struct TrailPeerList *peer;
1781 while (NULL != (peer = existing_finger->first_trail_head))
1783 GNUNET_CONTAINER_DLL_remove (existing_finger->first_trail_head, existing_finger->first_trail_tail, peer);
1787 while (i < trail_length)
1789 struct TrailPeerList *element;
1790 element = GNUNET_malloc (sizeof (struct TrailPeerList));
1791 element->next = NULL;
1792 element->prev = NULL;
1794 memcpy (&(element->peer), &trail[i], sizeof(struct GNUNET_PeerIdentity));
1795 GNUNET_CONTAINER_DLL_insert_tail(existing_finger->second_trail_head, existing_finger->second_trail_tail, element);
1799 else if (trail_length < existing_finger->second_trail_length)
1801 struct TrailPeerList *peer;
1804 while (NULL != (peer = existing_finger->second_trail_head))
1806 GNUNET_CONTAINER_DLL_remove (existing_finger->second_trail_head, existing_finger->second_trail_tail, peer);
1810 while (i < trail_length)
1812 struct TrailPeerList *element;
1813 element = GNUNET_malloc (sizeof (struct TrailPeerList));
1814 element->next = NULL;
1815 element->prev = NULL;
1817 memcpy (&(element->peer), &trail[i], sizeof(struct GNUNET_PeerIdentity));
1818 GNUNET_CONTAINER_DLL_insert_tail(existing_finger->second_trail_head, existing_finger->second_trail_tail, element);
1826 * Add a new trail to reach an existing finger in finger peermap.
1827 * @param existing_finger
1829 * @param trail_length
1832 void add_new_trail (struct FingerInfo *existing_finger,
1833 struct GNUNET_PeerIdentity *trail,
1834 unsigned int trail_length)
1839 if (existing_finger->second_trail_head != NULL)
1841 while (i < trail_length)
1843 struct TrailPeerList *element;
1844 element = GNUNET_malloc (sizeof (struct TrailPeerList));
1845 element->next = NULL;
1846 element->prev = NULL;
1848 memcpy (&(element->peer), &trail[i], sizeof(struct GNUNET_PeerIdentity));
1849 GNUNET_CONTAINER_DLL_insert_tail(existing_finger->second_trail_head, existing_finger->second_trail_tail, element);
1853 else if (existing_finger->second_trail_head != NULL)
1855 while (i < trail_length)
1857 struct TrailPeerList *element;
1858 element = GNUNET_malloc (sizeof (struct TrailPeerList));
1859 element->next = NULL;
1860 element->prev = NULL;
1862 memcpy (&(element->peer), &trail[i], sizeof(struct GNUNET_PeerIdentity));
1863 GNUNET_CONTAINER_DLL_insert_tail(existing_finger->second_trail_head, existing_finger->second_trail_tail, element);
1871 * * 1.* If you remove an entry from finger table, and if the finger is not your friend
1872 * and the trail length > 1 for the finger that you removed, then you should send
1873 * a trail_teardown message along the trail. so that the peers which have an
1874 * entry in their routing table for this trail can remove it from their routing
1877 * TODO: First check if both the trails are present if yes then send it
1879 * @param existing_finger
1882 void send_trail_teardown (struct FingerInfo *existing_finger)
1884 struct GNUNET_PeerIdentity *peer_list;
1885 struct FriendInfo *friend;
1886 struct TrailPeerList *finger_trail;
1887 int existing_finger_trail_length = existing_finger->first_trail_length;
1891 finger_trail = existing_finger->first_trail_head;
1892 friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &(finger_trail->peer));
1893 peer_list = GNUNET_malloc ( existing_finger_trail_length * sizeof (struct GNUNET_PeerIdentity));
1894 while (i < existing_finger->first_trail_length)
1896 memcpy (&peer_list[i], &(finger_trail->peer), sizeof (struct GNUNET_PeerIdentity));
1897 finger_trail = finger_trail->next;
1901 GDS_NEIGHBOURS_send_trail_teardown (&my_identity, &(existing_finger->finger_identity),
1902 peer_list, existing_finger_trail_length, friend);
1907 * Choose the closest successor from existing_finger and new_finger. In case new_finger
1908 * is choosen, then send a tear down message along the trail to reach existing_finger.
1909 * @param existing_finger Existing entry in finger peer map
1910 * @param new_finger New finger
1911 * @param trail Trail to reach to the new finger from me.
1912 * @param trail_length Number of peers in the @a trail
1913 * @param finger_map_index If finger_map_index == PREDECESSOR_FINGER_INDEX,
1914 * then we use a different logic to find the closest
1916 * @return #GNUNET_YES In case we want to store the new entry.
1917 * #GNUNET_NO In case we want the existing entry.
1918 * #GNUNET_SYSERR Error.
1921 int select_closest_finger (struct FingerInfo *existing_finger,
1922 const struct GNUNET_PeerIdentity *new_finger,
1923 struct GNUNET_PeerIdentity *trail,
1924 unsigned int trail_length)
1926 int val = GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity), new_finger);
1930 /*FIXME: Check if this returns the compressed trail in the trail sent as parameter.
1931 Scan the trail for a friend and shorten if possible. */
1932 scan_and_compress_trail (trail, trail_length, new_finger);
1934 if (existing_finger->trail_count < TRAIL_COUNT)
1936 add_new_trail (existing_finger, trail, trail_length);
1941 /* If not then first check if this new trail is shorter than other trails,
1942 if yes then remove the old trail, and add this new trail. and send GNUNET_YES. */
1943 select_and_replace_trail (existing_finger, trail, trail_length);
1949 /* If the new entry is closest one, then free the old entry, send a trail_teardown message.*/
1951 send_trail_teardown (existing_finger);
1952 free_finger (existing_finger);
1953 scan_and_compress_trail (trail, trail_length, new_finger);
1958 /* If the old entry is closest then just return GNUNET_NO.*/
1961 return GNUNET_SYSERR;
1966 * FIXME: Better name, and make the code more cleaner.
1967 * Compare the new finger entry added and our successor.
1968 * @return #GNUNET_YES if same.
1969 * #GNUNET_NO if not.
1972 compare_new_entry_successor (const struct GNUNET_PeerIdentity *new_finger)
1974 int successor_flag = 0;
1975 struct FingerInfo *successor_finger;
1976 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1979 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1980 for (i= 0; i < GNUNET_CONTAINER_multipeermap_size (finger_peermap); i++)
1982 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, NULL,
1983 (const void **)&successor_finger))
1985 if (successor_finger->finger_map_index == 0)
1992 /* Ideally we should never reach here. */
1993 if (successor_flag == 0)
1999 if (0 == GNUNET_CRYPTO_cmp_peer_identity (new_finger, &(successor_finger->finger_identity)))
2007 * Add an entry in the finger table. If there is already an existing entry in
2008 * the finger peermap for given finger map index, then choose the closest one.
2009 * In case both the new entry and old entry are same, store both of them. (Redundant
2011 * @param finger_identity
2012 * @param finger_trail
2013 * @param finger_trail_length
2014 * @param finger_map_index
2017 void finger_table_add (const struct GNUNET_PeerIdentity *finger_identity,
2018 struct GNUNET_PeerIdentity *finger_trail,
2019 uint32_t finger_trail_length,
2020 uint32_t finger_map_index)
2022 struct FingerInfo new_finger_entry;
2023 struct FingerInfo *existing_finger;
2024 struct FriendInfo *first_friend_trail;
2025 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
2028 /* If you are your own finger, then exit. */
2029 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, finger_identity))
2031 /* SUPU: We don't store this trail in case of trail_setup_result, if
2032 source and destination of the message are same. */
2036 /* Check if there is already an entry for the finger map index in the finger peer map. */
2037 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
2038 for (i= 0; i < GNUNET_CONTAINER_multipeermap_size (finger_peermap); i++)
2040 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, NULL,
2041 (const void **)&existing_finger))
2043 if (existing_finger->finger_map_index == finger_map_index)
2045 /* If existing finger is closest or both the new finger and existing finger
2046 are same, then just update current_search_finger_index. We are not
2047 adding a new entry just updating the existing entry or doing nothing. */
2048 if ( GNUNET_NO == select_closest_finger (existing_finger, finger_identity,
2049 finger_trail, finger_trail_length))
2050 goto update_current_search_finger_index;
2057 /* Add the new entry. */
2058 memcpy (&(new_finger_entry.finger_identity), finger_identity, sizeof (struct GNUNET_PeerIdentity));
2059 new_finger_entry.finger_map_index = finger_map_index;
2060 new_finger_entry.first_trail_length = finger_trail_length;
2062 if (finger_trail_length > 0)
2064 first_friend_trail = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger_trail[0]);
2065 first_friend_trail->trails_count++;
2069 /* It means the finger is my friend. */
2070 first_friend_trail = GNUNET_CONTAINER_multipeermap_get (friend_peermap, finger_identity);
2071 first_friend_trail->trails_count++;
2075 new_finger_entry.first_friend_trails_count = first_friend_trail->trails_count;
2077 while (i < finger_trail_length)
2079 struct TrailPeerList *element;
2080 element = GNUNET_malloc (sizeof (struct TrailPeerList));
2081 element->next = NULL;
2082 element->prev = NULL;
2084 memcpy (&(element->peer), &finger_trail[i], sizeof(struct GNUNET_PeerIdentity));
2085 GNUNET_CONTAINER_DLL_insert_tail(new_finger_entry.first_trail_head, new_finger_entry.first_trail_tail, element);
2089 GNUNET_assert (GNUNET_OK ==
2090 GNUNET_CONTAINER_multipeermap_put (finger_peermap,
2091 &(new_finger_entry.finger_identity),
2093 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2095 /* Set the value of current_search_finger_index. */
2096 update_current_search_finger_index:
2097 if (0 == finger_map_index)
2099 verify_successor = GNUNET_SCHEDULER_add_now (&send_verify_successor_message, NULL);
2100 current_search_finger_index = PREDECESSOR_FINGER_ID;
2103 else if (GNUNET_YES == compare_new_entry_successor (finger_identity))
2105 /* If the new entry is same as our successor, then reset the current_search_finger_index to 0*/
2106 current_search_finger_index = 0;
2111 current_search_finger_index = current_search_finger_index - 1;
2118 * Compare two peer identities.
2119 * @param p1 Peer identity
2120 * @param p2 Peer identity
2121 * @return 1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2.
2124 compare_peer_id (const void *p1, const void *p2)
2126 struct Sorting_List *p11;
2127 struct Sorting_List *p22;
2129 p11 = GNUNET_malloc (sizeof (struct Sorting_List));
2130 p22 = GNUNET_malloc (sizeof (struct Sorting_List));
2131 p11 = (struct Sorting_List *)p1;
2132 p22 = (struct Sorting_List *)p2;
2133 ret = ( (p11->peer_id) > (p22->peer_id) ) ? 1 :
2134 ( (p11->peer_id) == (p22->peer_id) ) ? 0 : -1;
2140 * Return the successor of value in all_known_peers.
2141 * @param all_known_peers list of all the peers
2142 * @param value value we have to search in the all_known_peers.
2145 static struct Sorting_List *
2146 find_closest_successor(struct Sorting_List *all_known_peers, uint64_t value,
2155 middle = (first + last)/2;
2157 while(first <= last)
2159 if(all_known_peers[middle].peer_id < value)
2163 else if(all_known_peers[middle].peer_id == value)
2165 if(middle == (size -1))
2167 return &all_known_peers[0];
2171 return &all_known_peers[middle+1];
2179 middle = (first + last)/2;
2186 * Find closest successor for the value.
2187 * @param value Value for which we are looking for successor
2188 * @param[out] current_destination set to the end of the finger to traverse next
2189 * @param[out] current_source set to my_identity.
2190 * @param congested_peer Peer not to be considered when looking for
2191 * successor. FIXME: IMPLEMENT IT.
2192 * @return Peer identity of next hop, NULL if we are the
2193 * ultimate destination
2195 static struct GNUNET_PeerIdentity *
2196 find_successor (uint64_t value, struct GNUNET_PeerIdentity *current_destination,
2197 struct GNUNET_PeerIdentity *current_source,
2198 struct GNUNET_PeerIdentity *congested_peer)
2200 struct GNUNET_CONTAINER_MultiPeerMapIterator *friend_iter;
2201 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
2202 struct GNUNET_PeerIdentity key_ret;
2203 struct FriendInfo *friend;
2204 struct FingerInfo *finger;
2205 unsigned int finger_index;
2206 unsigned int friend_index;
2207 struct Sorting_List *successor;
2211 /* 2 is added in size for my_identity and value which will part of all_known_peers. */
2212 size = GNUNET_CONTAINER_multipeermap_size (friend_peermap)+
2213 GNUNET_CONTAINER_multipeermap_size (finger_peermap)+
2216 struct Sorting_List all_known_peers[size];
2219 for (k = 0; k < size; k++)
2220 all_known_peers[k].peer_id = 0;
2222 /* Copy your identity at 0th index in all_known_peers. */
2224 memcpy (&(all_known_peers[j].peer_id), &my_identity, sizeof (uint64_t));
2225 all_known_peers[j].type = MY_ID;
2226 all_known_peers[j].data = 0;
2230 all_known_peers[j].peer_id = value;
2231 all_known_peers[j].type = VALUE;
2232 all_known_peers[j].data = 0;
2235 /* Iterate over friend peer map and copy all the elements into array. */
2236 friend_iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
2237 for (friend_index = 0; friend_index < GNUNET_CONTAINER_multipeermap_size (friend_peermap); friend_index++)
2239 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(friend_iter,&key_ret,(const void **)&friend))
2241 memcpy (&(all_known_peers[j].peer_id), &(friend->id), sizeof (uint64_t));
2242 all_known_peers[j].type = FRIEND;
2243 all_known_peers[j].data = friend;
2248 /* Iterate over finger map and copy all the entries into all_known_peers array. */
2249 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
2250 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
2252 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(finger_iter,&key_ret,(const void **)&finger))
2254 memcpy (&(all_known_peers[j].peer_id), &(finger->finger_identity), sizeof (uint64_t));
2255 all_known_peers[j].type = FINGER;
2256 all_known_peers[j].data = finger;
2261 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
2262 GNUNET_CONTAINER_multipeermap_iterator_destroy (friend_iter);
2264 qsort (&all_known_peers, size, sizeof (struct Sorting_List), &compare_peer_id);
2266 /* search value in all_known_peers array. */
2267 successor = find_closest_successor (all_known_peers, value, size);
2269 if (successor->type == MY_ID)
2271 /* FIXME: make sure everywhere you are using current_destination to check if
2272 I am the final destination. */
2273 memcpy (current_destination, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2276 else if (successor->type == FRIEND)
2278 struct FriendInfo *target_friend;
2279 target_friend = (struct FriendInfo *)successor->data;
2280 memcpy (current_destination, &(target_friend->id), sizeof (struct GNUNET_PeerIdentity));
2281 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2282 return current_destination;
2284 else if (successor->type == FINGER)
2286 struct GNUNET_PeerIdentity *next_hop;
2287 struct FingerInfo *finger;
2288 struct TrailPeerList *iterator;
2289 iterator = GNUNET_malloc (sizeof (struct TrailPeerList));
2290 finger = successor->data;
2291 iterator = finger->first_trail_head;
2292 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2293 memcpy (next_hop, &(iterator->peer), sizeof (struct GNUNET_PeerIdentity));
2294 memcpy (current_destination, &(finger->finger_identity), sizeof (struct GNUNET_PeerIdentity));
2295 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2300 /* FIXME: This is returned when congested peer is the only peer or the only
2301 finger that we have is reachable through this congested peer. */
2308 /** FIXME: by default I keep current_source, and destination as my own id.
2309 * in case we find a finger then we update current_source in the
2310 * find_successor message.
2311 * Construct a Put message and send it to target_peer.
2312 * @param key Key for the content
2313 * @param data Content to store
2314 * @param data_size Size of content @a data in bytes
2315 * @param block_type Type of the block
2316 * @param options Routing options
2317 * @param desired_replication_level Desired replication count
2318 * @param expiration_time When does the content expire
2319 * @param current_destination
2320 * @param current_source
2321 * @param target_peer Peer to which this message will be forwarded.
2322 * @param hop_count Number of hops traversed so far.
2323 * @param put_path_length Total number of peers in @a put_path
2324 * @param put_path Number of peers traversed so far
2327 GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key,
2328 const void *data, size_t data_size,
2329 enum GNUNET_BLOCK_Type block_type,
2330 enum GNUNET_DHT_RouteOption options,
2331 uint32_t desired_replication_level,
2332 struct GNUNET_TIME_Absolute expiration_time,
2333 struct GNUNET_PeerIdentity current_destination,
2334 struct GNUNET_PeerIdentity current_source,
2335 struct GNUNET_PeerIdentity *target_peer,
2337 uint32_t put_path_length,
2338 struct GNUNET_PeerIdentity *put_path)
2340 struct PeerPutMessage *ppm;
2341 struct P2PPendingMessage *pending;
2342 struct FriendInfo *target_friend;
2343 struct GNUNET_PeerIdentity *pp;
2346 msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
2347 sizeof (struct PeerPutMessage);
2349 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2351 put_path_length = 0;
2352 msize = data_size + sizeof (struct PeerPutMessage);
2355 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2361 /* This is the first call made from clients file. So, we should search for the
2363 if (NULL == target_peer)
2366 struct GNUNET_PeerIdentity *next_hop;
2368 memcpy (&key_value, key, sizeof (uint64_t));
2369 struct GNUNET_PeerIdentity curr_dest;
2370 struct GNUNET_PeerIdentity curr_src;
2371 memcpy (&curr_dest, ¤t_destination, sizeof (struct GNUNET_PeerIdentity));
2372 memcpy (&curr_src, ¤t_source, sizeof (struct GNUNET_PeerIdentity));
2373 next_hop = find_successor (key_value, &curr_dest, &curr_src, NULL);
2374 /* FIXME: I am copying back current_destination and current_source. but I am not
2375 sure, if its correct. I am doing so just to remove the code from client file.*/
2376 memcpy (¤t_destination, &curr_dest, sizeof (struct GNUNET_PeerIdentity));
2377 memcpy (¤t_source, &curr_src, sizeof (struct GNUNET_PeerIdentity));
2379 if (NULL == next_hop) /* I am the destination do datacache_put */
2381 GDS_DATACACHE_handle_put (expiration_time, key, put_path_length, put_path,
2382 block_type, data_size, data);
2386 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2389 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2390 pending->timeout = expiration_time;
2391 ppm = (struct PeerPutMessage *) &pending[1];
2392 pending->msg = &ppm->header;
2393 ppm->header.size = htons (msize);
2394 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
2395 ppm->options = htonl (options);
2396 ppm->block_type = htonl (block_type);
2397 ppm->hop_count = htonl (hop_count + 1);
2398 ppm->desired_replication_level = htonl (desired_replication_level);
2399 ppm->put_path_length = htonl (put_path_length);
2400 ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
2402 ppm->current_destination = current_destination;
2403 ppm->current_source = current_source;
2405 pp = (struct GNUNET_PeerIdentity *) &ppm[1];
2406 if (put_path_length != 0)
2408 memcpy (pp, put_path,
2409 sizeof (struct GNUNET_PeerIdentity) * put_path_length);
2411 memcpy (&pp[put_path_length], data, data_size);
2412 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2413 target_friend->pending_count++;
2414 process_friend_queue (target_friend);
2419 /** FIXME: by default I keep current_source, and destination as my own id.
2420 * in case we find a finger then we update current_source in the
2421 * find_successor message.
2422 * Construct a Get message and send it to target_peer.
2423 * @param key Key for the content
2424 * @param block_type Type of the block
2425 * @param options Routing options
2426 * @param desired_replication_level Desired replication count
2427 * @param expiration_time When does the content expire
2428 * @param current_destination
2429 * @param current_source
2430 * @param target_peer Peer to which this message will be forwarded.
2431 * @param hop_count Number of hops traversed so far.
2432 * @param put_path_length Total number of peers in @a put_path
2433 * @param put_path Number of peers traversed so far
2436 GDS_NEIGHBOURS_send_get (const struct GNUNET_HashCode *key,
2437 enum GNUNET_BLOCK_Type block_type,
2438 enum GNUNET_DHT_RouteOption options,
2439 uint32_t desired_replication_level,
2440 struct GNUNET_PeerIdentity current_destination,
2441 struct GNUNET_PeerIdentity current_source,
2442 struct GNUNET_PeerIdentity *target_peer,
2444 uint32_t get_path_length,
2445 struct GNUNET_PeerIdentity *get_path)
2447 struct PeerGetMessage *pgm;
2448 struct P2PPendingMessage *pending;
2449 struct FriendInfo *target_friend;
2450 struct GNUNET_PeerIdentity *gp;
2453 msize = sizeof (struct PeerGetMessage) +
2454 (get_path_length * sizeof (struct GNUNET_PeerIdentity));
2456 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2462 if (NULL == target_peer)
2464 /* This is the first call from client file, we need to search for next_hop*/
2465 struct GNUNET_PeerIdentity *next_hop;
2467 struct GNUNET_PeerIdentity curr_dest;
2468 struct GNUNET_PeerIdentity curr_src;
2469 memcpy (&curr_dest, ¤t_destination, sizeof (struct GNUNET_PeerIdentity));
2470 memcpy (&curr_src, ¤t_source, sizeof (struct GNUNET_PeerIdentity));
2471 memcpy (&key_value, key, sizeof (uint64_t));
2472 // FIXME: endianess of key_value!?
2473 next_hop = find_successor (key_value, &curr_dest, &curr_src, NULL);
2474 /* FIXME: Again I am copying back value of current_destination, current_source,
2475 Think of a better solution. */
2476 memcpy (¤t_destination, &curr_dest, sizeof (struct GNUNET_PeerIdentity));
2477 memcpy (¤t_source, &curr_src, sizeof (struct GNUNET_PeerIdentity));
2478 if (NULL == next_hop) /* I am the destination do datacache_put */
2480 GDS_DATACACHE_handle_get (key,block_type, NULL, 0,
2481 NULL, 0, 1, &my_identity, NULL,&my_identity);
2486 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2490 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2491 pending->importance = 0; /* FIXME */
2492 pgm = (struct PeerGetMessage *) &pending[1];
2493 pending->msg = &pgm->header;
2494 pgm->header.size = htons (msize);
2495 pgm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
2496 pgm->get_path_length = htonl (get_path_length);
2498 pgm->current_destination = current_destination;
2499 pgm->current_source = current_source;
2500 pgm->hop_count = htonl (hop_count + 1);
2502 gp = (struct GNUNET_PeerIdentity *) &pgm[1];
2503 memcpy (gp, get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity));
2504 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2505 target_friend->pending_count++;
2506 process_friend_queue (target_friend);
2511 * Send the get result to requesting client.
2512 * @param expiration When will this result expire?
2513 * @param key Key of the requested data.
2514 * @param put_path_length Number of peers in @a put_path
2515 * @param put_path Path taken to put the data at its stored location.
2516 * @param type Block type
2517 * @param data_size Size of the @a data
2518 * @param data Payload to store
2519 * @param get_path Path taken to reach to the location of the key.
2520 * @param get_path_length Number of peers in @a get_path
2521 * @param next_hop Next peer to forward the message to.
2522 * @param source_peer Peer which has the data for the key.
2525 GDS_NEIGHBOURS_send_get_result (struct GNUNET_TIME_Absolute expiration,
2526 const struct GNUNET_HashCode *key,
2527 unsigned int put_path_length,
2528 const struct GNUNET_PeerIdentity *put_path,
2529 enum GNUNET_BLOCK_Type type, size_t data_size,
2531 struct GNUNET_PeerIdentity *get_path,
2532 unsigned int get_path_length,
2533 struct GNUNET_PeerIdentity *next_hop,
2534 struct GNUNET_PeerIdentity *source_peer)
2536 struct PeerGetResultMessage *get_result;
2537 struct GNUNET_PeerIdentity *get_result_path;
2538 struct GNUNET_PeerIdentity *pp;
2539 struct P2PPendingMessage *pending;
2540 struct FriendInfo *target_friend;
2541 int current_path_index;
2544 msize = get_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
2545 sizeof (struct PeerPutMessage);
2547 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2553 current_path_index = search_my_index(get_path, get_path_length);
2554 /* FIXME: handle the case when current_path_index = GNUNET_SYSERR;*/
2555 if (0 == current_path_index)
2557 GDS_CLIENTS_handle_reply (expiration, key, get_path_length, get_path, put_path_length,
2558 put_path, type, data_size, data);
2561 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2562 pending->importance = 0;
2563 get_result = (struct PeerGetResultMessage *)&pending[1];
2564 pending->msg = &get_result->header;
2565 get_result->header.size = htons (msize);
2566 get_result->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT);
2567 get_result->key = *key;
2568 memcpy (&(get_result->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
2569 get_result->expiration_time = expiration;
2571 get_result_path = (struct GNUNET_PeerIdentity *)&get_result[1];
2572 memcpy (get_result_path, get_path,
2573 sizeof (struct GNUNET_PeerIdentity) * get_path_length);
2574 memcpy (&get_result_path[get_path_length], data, data_size);
2575 /* FIXME: Is this correct? */
2576 pp = (struct GNUNET_PeerIdentity *)&get_result_path[1];
2577 memcpy (pp, put_path,sizeof (struct GNUNET_PeerIdentity) * put_path_length);
2579 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2580 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2581 target_friend->pending_count++;
2582 process_friend_queue (target_friend);
2587 * Send tral rejection message to the peer which sent me a trail setup message.
2588 * @param source_peer Source peer which wants to set up the trail.
2589 * @param finger_identity Value whose successor will be the finger of @a source_peer.
2590 * @param congested_peer Peer which has send trail rejection message.
2591 * @param next_hop Peer to which this message should be forwarded.
2592 * @param finger_map_index Index in @a source_peer finger peermap.
2593 * @param trail_peer_list Trail followed to reach from @a source_peer to next_hop,
2594 * NULL, in case the @a congested_peer was the first peer
2595 * to which trail setup message was forwarded.
2596 * @param trail_length Number of peers in trail_peer_list.
2599 GDS_NEIGHBOURS_send_trail_rejection (struct GNUNET_PeerIdentity *source_peer,
2600 uint64_t finger_identity,
2601 struct GNUNET_PeerIdentity *congested_peer,
2602 const struct GNUNET_PeerIdentity *next_hop,
2603 unsigned int finger_map_index,
2604 struct GNUNET_PeerIdentity *trail_peer_list,
2605 unsigned int trail_length)
2607 struct PeerTrailRejectionMessage *trail_rejection;
2608 struct GNUNET_PeerIdentity *trail_list;
2609 struct P2PPendingMessage *pending;
2610 struct FriendInfo *target_friend;
2613 msize = trail_length * sizeof(struct GNUNET_PeerIdentity) +
2614 sizeof (struct PeerTrailRejectionMessage);
2616 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2622 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2623 pending->importance = 0;
2624 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
2625 trail_rejection = (struct PeerTrailRejectionMessage *) &pending[1];
2626 pending->msg = &trail_rejection->header;
2627 trail_rejection->header.size = htons (msize);
2628 trail_rejection->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
2629 memcpy (&(trail_rejection->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
2630 memcpy (&(trail_rejection->congested_peer), congested_peer, sizeof (struct GNUNET_PeerIdentity));
2631 memcpy (&(trail_rejection->finger_identity_value), &finger_identity, sizeof (uint64_t));
2632 trail_rejection->finger_map_index = htonl(finger_map_index);
2633 trail_rejection->trail_length = htonl (trail_length);
2635 trail_list = (struct GNUNET_PeerIdentity *)&trail_rejection[1];
2636 if (trail_length != 0)
2637 memcpy (trail_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
2639 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2640 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2641 target_friend->pending_count++;
2642 process_friend_queue (target_friend);
2647 * Core handler for P2P put messages.
2648 * @param cls closure
2649 * @param peer sender of the request
2650 * @param message message
2651 * @return #GNUNET_OK to keep the connection open,
2652 * #GNUNET_SYSERR to close it (signal serious error)
2655 handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer,
2656 const struct GNUNET_MessageHeader *message)
2658 struct PeerPutMessage *put;
2659 struct GNUNET_PeerIdentity *put_path;
2660 struct GNUNET_HashCode test_key;
2661 enum GNUNET_DHT_RouteOption options;
2662 struct GNUNET_PeerIdentity current_destination;
2663 struct GNUNET_PeerIdentity current_source;
2664 struct GNUNET_PeerIdentity *next_hop;
2668 size_t payload_size;
2671 msize = ntohs (message->size);
2672 if (msize < sizeof (struct PeerPutMessage))
2674 GNUNET_break_op (0);
2678 put = (struct PeerPutMessage *) message;
2679 putlen = ntohl (put->put_path_length);
2682 sizeof (struct PeerPutMessage) +
2683 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
2685 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2687 GNUNET_break_op (0);
2691 current_destination = put->current_destination;
2692 current_source = put->current_source;
2693 put_path = (struct GNUNET_PeerIdentity *) &put[1];
2694 payload = &put_path[putlen];
2695 options = ntohl (put->options);
2696 payload_size = msize - (sizeof (struct PeerPutMessage) +
2697 putlen * sizeof (struct GNUNET_PeerIdentity));
2699 switch (GNUNET_BLOCK_get_key (GDS_block_context, ntohl (put->block_type),
2700 payload, payload_size, &test_key))
2703 if (0 != memcmp (&test_key, &put->key, sizeof (struct GNUNET_HashCode)))
2705 char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key));
2706 GNUNET_break_op (0);
2707 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2708 "PUT with key `%s' for block with key %s\n",
2709 put_s, GNUNET_h2s_full (&test_key));
2710 GNUNET_free (put_s);
2715 GNUNET_break_op (0);
2718 /* cannot verify, good luck */
2722 if (ntohl (put->block_type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
2724 switch (GNUNET_BLOCK_evaluate (GDS_block_context,
2725 ntohl (put->block_type),
2727 NULL, 0, /* bloom filer */
2728 NULL, 0, /* xquery */
2729 payload, payload_size))
2731 case GNUNET_BLOCK_EVALUATION_OK_MORE:
2732 case GNUNET_BLOCK_EVALUATION_OK_LAST:
2735 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
2736 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
2737 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
2738 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
2739 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
2740 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
2742 GNUNET_break_op (0);
2747 struct GNUNET_PeerIdentity pp[putlen + 1];
2748 /* extend 'put path' by sender */
2749 /* FIXME: Check what are we doing here? */
2750 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
2752 memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity));
2759 memcpy (&key_value, &(put->key), sizeof (uint64_t));
2760 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_destination, &my_identity)))
2762 next_hop = GDS_ROUTING_search (¤t_source, ¤t_destination, peer);
2763 if (next_hop == NULL)
2765 /* refer to handle_dht_p2p_trail_setup. */
2770 next_hop = find_successor (key_value, ¤t_destination, ¤t_source, NULL);
2773 if (NULL == next_hop) /* I am the final destination */
2775 GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time),
2776 &(put->key),putlen, pp, ntohl (put->block_type),
2777 payload_size, payload);
2782 GDS_CLIENTS_process_put (options,
2783 ntohl (put->block_type),
2784 ntohl (put->hop_count),
2785 ntohl (put->desired_replication_level),
2787 GNUNET_TIME_absolute_ntoh (put->expiration_time),
2792 GDS_NEIGHBOURS_send_put (&put->key, payload, payload_size,
2793 ntohl (put->block_type),ntohl (put->options),
2794 ntohl (put->desired_replication_level),
2795 GNUNET_TIME_absolute_ntoh (put->expiration_time),
2796 current_destination, current_source, next_hop,
2797 ntohl (put->hop_count), putlen, pp);
2801 return GNUNET_SYSERR;
2806 * Core handler for p2p get requests.
2808 * @param cls closure
2809 * @param peer sender of the request
2810 * @param message message
2811 * @return #GNUNET_OK to keep the connection open,
2812 * #GNUNET_SYSERR to close it (signal serious error)
2815 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
2816 const struct GNUNET_MessageHeader *message)
2818 struct PeerGetMessage *get;
2819 struct GNUNET_PeerIdentity *get_path;
2820 struct GNUNET_PeerIdentity current_destination;
2821 struct GNUNET_PeerIdentity current_source;
2822 struct GNUNET_PeerIdentity *next_hop;
2823 uint32_t get_length;
2827 msize = ntohs (message->size);
2828 if (msize < sizeof (struct PeerGetMessage))
2830 GNUNET_break_op (0);
2834 get = (struct PeerGetMessage *)message;
2835 get_length = ntohl (get->get_path_length);
2836 get_path = (struct GNUNET_PeerIdentity *)&get[1];
2837 current_destination = get->current_destination;
2838 current_source = get->current_source;
2841 sizeof (struct PeerGetMessage) +
2842 get_length * sizeof (struct GNUNET_PeerIdentity)) ||
2844 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2846 GNUNET_break_op (0);
2850 /* Add sender to get path */
2851 struct GNUNET_PeerIdentity gp[get_length + 1];
2852 memcpy (gp, get_path, get_length * sizeof (struct GNUNET_PeerIdentity));
2853 gp[get_length + 1] = *peer;
2854 get_length = get_length + 1;
2856 memcpy (&key_value, &(get->key), sizeof (uint64_t));
2857 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_destination, &my_identity)))
2859 next_hop = GDS_ROUTING_search (¤t_source, ¤t_destination, peer);
2860 if (next_hop == NULL)
2862 /* refer to handle_dht_p2p_trail_setup. */
2867 next_hop = find_successor (key_value, ¤t_destination, ¤t_source, NULL);
2870 if (NULL == next_hop)
2872 /* FIXME: Try to make this code also short and remove useless variables. */
2873 struct GNUNET_PeerIdentity final_get_path[get_length+1];
2874 memcpy (final_get_path, gp, get_length * sizeof (struct GNUNET_PeerIdentity));
2875 memcpy (&final_get_path[get_length+1], &my_identity, sizeof (struct GNUNET_PeerIdentity));
2876 get_length = get_length + 1;
2877 struct GNUNET_PeerIdentity *next_hop;
2878 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2879 memcpy (next_hop, &final_get_path[get_length-2], sizeof (struct GNUNET_PeerIdentity));
2880 GDS_DATACACHE_handle_get (&(get->key),(get->block_type), NULL, 0, NULL, 0,
2881 get_length, final_get_path,next_hop, &my_identity);
2887 GDS_NEIGHBOURS_send_get (&(get->key), get->block_type, get->options,
2888 get->desired_replication_level,current_destination,
2889 current_source, next_hop, 0,
2892 return GNUNET_SYSERR;
2898 * Core handler for get result
2899 * @param cls closure
2900 * @param peer sender of the request
2901 * @param message message
2902 * @return #GNUNET_OK to keep the connection open,
2903 * #GNUNET_SYSERR to close it (signal serious error)
2906 handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer,
2907 const struct GNUNET_MessageHeader *message)
2909 /* If you are the source, go back to the client file and there search for
2910 the requesting client and send back the result. */
2911 struct PeerGetResultMessage *get_result;
2912 struct GNUNET_PeerIdentity *get_path;
2913 struct GNUNET_PeerIdentity *put_path;
2915 size_t payload_size;
2917 unsigned int getlen;
2918 unsigned int putlen;
2919 int current_path_index;
2921 msize = ntohs (message->size);
2922 if (msize < sizeof (struct PeerGetResultMessage))
2924 GNUNET_break_op (0);
2928 get_result = (struct PeerGetResultMessage *)message;
2929 getlen = ntohl (get_result->get_path_length);
2930 putlen = ntohl (get_result->put_path_length);
2933 sizeof (struct PeerGetResultMessage) +
2934 getlen * sizeof (struct GNUNET_PeerIdentity) +
2935 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
2937 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity) ||
2939 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))))
2941 GNUNET_break_op (0);
2945 get_path = (struct GNUNET_PeerIdentity *) &get_result[1];
2946 payload = &get_path[getlen];
2947 payload_size = msize - (sizeof (struct PeerGetResultMessage) +
2948 getlen * sizeof (struct GNUNET_PeerIdentity));
2949 /* FIXME: Check if its correct or not. */
2952 put_path = &get_path[1];
2956 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &(get_path[0]))))
2958 //GDS_CLIENTS_process_get_result();
2959 GDS_CLIENTS_handle_reply (get_result->expiration_time, &(get_result->key),
2960 getlen, get_path, putlen,
2961 put_path, get_result->type, payload_size, payload);
2966 struct GNUNET_PeerIdentity *next_hop;
2967 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2968 /* FIXME: handle the case when current_path_index = GNUNET_SYSERR;*/
2969 current_path_index = search_my_index (get_path, getlen);
2970 /* FIXME: First check if you are adding yourself to the get path or not.
2971 if yes then don't check if current_path_index == 0, if not then check
2972 and next_hop == source_peer. */
2973 memcpy (next_hop, &get_path[current_path_index - 1], sizeof (struct GNUNET_PeerIdentity));
2975 GDS_NEIGHBOURS_send_get_result (get_result->expiration_time, &(get_result->key),
2977 get_result->type, payload_size,payload,
2979 next_hop, &(get_result->source_peer));
2982 return GNUNET_SYSERR;
2987 * Core handle for PeerTrailSetupMessage.
2988 * @param cls closure
2989 * @param message message
2990 * @param peer peer identity this notification is about
2991 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
2994 handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer,
2995 const struct GNUNET_MessageHeader *message)
2997 const struct PeerTrailSetupMessage *trail_setup;
2998 struct GNUNET_PeerIdentity current_destination;
2999 struct GNUNET_PeerIdentity current_source;
3000 struct GNUNET_PeerIdentity source;
3001 struct GNUNET_PeerIdentity *next_hop;
3002 struct GNUNET_PeerIdentity next_peer;
3003 struct GNUNET_PeerIdentity *trail_peer_list;
3004 struct FriendInfo *target_friend;
3005 uint64_t destination_finger_value;
3006 uint32_t trail_length;
3007 uint32_t finger_map_index;
3010 msize = ntohs (message->size);
3011 if (msize < sizeof (struct PeerTrailSetupMessage))
3013 GNUNET_break_op (0);
3017 trail_setup = (const struct PeerTrailSetupMessage *) message;
3018 trail_length = ntohl (trail_setup->trail_length);
3020 if ((msize < sizeof (struct PeerTrailSetupMessage) +
3021 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3023 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3025 GNUNET_break_op (0);
3029 trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_setup[1];
3030 current_destination = trail_setup->current_destination;
3031 current_source = trail_setup->current_source;
3032 source = trail_setup->source_peer;
3033 finger_map_index = ntohl (trail_setup->finger_map_index);
3034 destination_finger_value = ntohl (trail_setup->destination_finger);
3036 /* My routing state size has crossed the threshold, I can not be part of any more
3038 if(GDS_ROUTING_check_threshold())
3040 /* No more trails possible through me. send a trail rejection message. */
3041 GDS_NEIGHBOURS_send_trail_rejection (&source, destination_finger_value, &my_identity,
3042 peer,finger_map_index, trail_peer_list,trail_length);
3046 /* Check if you are current_destination or not. */
3047 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_destination, &my_identity)))
3049 next_hop = GDS_ROUTING_search (¤t_source, ¤t_destination, peer);
3050 /* ADDNOW: OPTIMIZATION: do find_successor also and get a better path if possible. */
3052 if (next_hop == NULL)
3054 /* FIXME next_hop is NULL, in a case when next_hop was a friend which got disconnected
3055 * and we removed the trail from our routing trail. So, I can send the message
3056 * to other peer or can drop the message. VERIFY which will be the correct
3057 * thing to do. next_hop to NULL, 1. statistics update, drop the message.
3058 * 2. complain to sender with new message: trail lost */
3064 next_hop = find_successor (destination_finger_value, ¤t_destination, ¤t_source, NULL);
3067 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (¤t_destination, &my_identity))) /* This means I am the final destination */
3069 /* SUPU: trail length is 0, when I am the friend of the source peer. */
3070 if (trail_length == 0)
3072 memcpy (&next_peer, &source, sizeof (struct GNUNET_PeerIdentity));
3076 memcpy (&next_peer, &trail_peer_list[trail_length-1], sizeof (struct GNUNET_PeerIdentity));
3079 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer);
3080 /* ! HAVE A PREDECESSOR || (source_peer closer than existing PREDECESOR) */
3081 compare_and_update_predecessor (&source, trail_peer_list, trail_length );
3083 GDS_NEIGHBOURS_send_trail_setup_result (&source,
3085 target_friend, trail_length,
3092 /* Now add yourself to the trail. */
3093 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
3094 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
3095 peer_list[trail_length] = my_identity;
3098 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3099 GDS_NEIGHBOURS_send_trail_setup (&source,
3100 destination_finger_value,
3101 ¤t_destination, ¤t_source,
3102 target_friend, trail_length, peer_list,
3106 return GNUNET_SYSERR;
3111 * Core handle for p2p trail construction result messages.
3113 * @param message message
3114 * @param peer peer identity this notification is about
3115 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3118 handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer,
3119 const struct GNUNET_MessageHeader *message)
3121 const struct PeerTrailSetupResultMessage *trail_result;
3122 struct GNUNET_PeerIdentity *trail_peer_list;
3123 uint32_t trail_length;
3124 uint32_t finger_map_index;
3127 msize = ntohs (message->size);
3128 if (msize < sizeof (struct PeerTrailSetupResultMessage))
3130 GNUNET_break_op (0);
3134 trail_result = (const struct PeerTrailSetupResultMessage *) message;
3135 trail_length = ntohl (trail_result->trail_length);
3138 sizeof (struct PeerTrailSetupResultMessage) +
3139 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3141 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3143 GNUNET_break_op (0);
3147 finger_map_index = htonl (trail_result->finger_map_index);
3148 trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_result[1];
3150 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->destination_peer),
3153 finger_table_add (&(trail_result->finger_identity), trail_peer_list, trail_length,
3159 struct GNUNET_PeerIdentity next_hop;
3160 struct FriendInfo *target_friend;
3163 /* FIXME: handle the case when current_path_index = GNUNET_SYSERR;*/
3164 /* FIXME: Make sure you are passing the current length */
3165 my_index = search_my_index (trail_peer_list, trail_length);
3168 next_hop = trail_result->destination_peer;
3171 next_hop = trail_peer_list[my_index - 1];
3173 /* Finger table of destination peer will not contain any trail for the case
3174 * where destination peer is its own finger identity. */
3175 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->destination_peer),
3176 &(trail_result->finger_identity))))
3178 GDS_ROUTING_add (&(trail_result->destination_peer), &(trail_result->finger_identity),
3182 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3183 GDS_NEIGHBOURS_send_trail_setup_result (&(trail_result->destination_peer),
3184 &(trail_result->finger_identity),
3185 target_friend, trail_length,
3190 return GNUNET_SYSERR;
3195 * FIXME: Use flag in the case finger peer map does not contain predcessor
3196 * then its NULL. Ideally it should never happen. Some one sent you are verify
3197 * successor and you don't have any predecessor, then ideally you should
3198 * GNUNET_break_op(0).
3199 * Get my current predecessor from the finger peer map
3200 * @return Current predecessor.
3202 static struct FingerInfo *
3205 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
3206 struct GNUNET_PeerIdentity key_ret;
3207 unsigned int finger_index;
3208 struct FingerInfo *my_predecessor;
3210 /* Iterate over finger peer map and extract your predecessor. */
3211 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
3212 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
3214 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next
3215 (finger_iter,&key_ret,(const void **)&my_predecessor))
3217 if(1 == my_predecessor->finger_map_index)
3223 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
3224 return my_predecessor;
3229 * Core handle for p2p verify successor messages.
3230 * @param cls closure
3231 * @param message message
3232 * @param peer peer identity this notification is about
3233 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3236 handle_dht_p2p_verify_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
3237 const struct GNUNET_MessageHeader *message)
3239 const struct PeerVerifySuccessorMessage *vsm;
3240 const struct GNUNET_PeerIdentity *trail_peer_list;
3241 struct GNUNET_PeerIdentity source_peer;
3242 struct GNUNET_PeerIdentity next_hop;
3243 struct FriendInfo *target_friend;
3245 uint32_t trail_length;
3247 msize = ntohs (message->size);
3248 if (msize < sizeof (struct PeerVerifySuccessorMessage))
3250 GNUNET_break_op (0);
3254 vsm = (struct PeerVerifySuccessorMessage *) message;
3255 trail_length = ntohl (vsm->trail_length);
3257 if ((msize < sizeof (struct PeerVerifySuccessorMessage) +
3258 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3259 (trail_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3261 GNUNET_break_op (0);
3265 trail_peer_list = (const struct GNUNET_PeerIdentity *)&vsm[1];
3266 memcpy (&source_peer, &(vsm->source_peer), sizeof(struct GNUNET_PeerIdentity));
3267 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsm->successor),&my_identity)))
3269 struct FingerInfo *my_predecessor;
3271 if (trail_length == 0)
3272 memcpy (&next_hop, &source_peer, sizeof (struct GNUNET_PeerIdentity));
3275 int current_trail_index;
3276 current_trail_index = search_my_index (trail_peer_list, trail_length);
3277 memcpy (&next_hop, &trail_peer_list[current_trail_index-1], sizeof (struct GNUNET_PeerIdentity));
3279 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3281 my_predecessor = get_predecessor();
3282 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&source_peer,
3283 &(my_predecessor->finger_identity))))
3286 GDS_NEIGHBOURS_send_verify_successor_result (&source_peer,
3288 &(my_predecessor->finger_identity),
3295 struct GNUNET_PeerIdentity *new_successor_trail;
3296 struct TrailPeerList *iterator;
3297 int new_trail_length;
3300 new_trail_length = trail_length + my_predecessor->first_trail_length + 1;
3301 new_successor_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * new_trail_length);
3302 memcpy (new_successor_trail, trail_peer_list, (trail_length) * sizeof (struct GNUNET_PeerIdentity));
3303 memcpy (&new_successor_trail[trail_length], &my_identity, sizeof (struct GNUNET_PeerIdentity));
3305 iterator = GNUNET_malloc (sizeof (struct TrailPeerList));
3306 iterator = my_predecessor->first_trail_head;
3307 i = trail_length + 1;
3308 while (i < new_trail_length)
3310 memcpy (&new_successor_trail[i], &(iterator->peer), sizeof (struct GNUNET_PeerIdentity));
3311 iterator = iterator->next;
3315 GDS_NEIGHBOURS_send_verify_successor_result (&source_peer,
3317 &(my_predecessor->finger_identity),
3319 new_successor_trail,
3327 /* FIXME: handle the case when current_path_index = GNUNET_SYSERR;*/
3328 /* FIXME: make sure you are passing the correct trail length */
3329 my_index = search_my_index (trail_peer_list, trail_length);
3330 memcpy (&next_hop, &trail_peer_list[my_index + 1], sizeof (struct GNUNET_PeerIdentity));
3331 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3333 GDS_NEIGHBOURS_send_verify_successor (&(vsm->source_peer), &(vsm->successor),target_friend,
3334 trail_peer_list, trail_length);
3336 return GNUNET_SYSERR;
3341 * Core handle for p2p verify successor result messages.
3342 * @param cls closure
3343 * @param message message
3344 * @param peer peer identity this notification is about
3345 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3348 handle_dht_p2p_verify_successor_result(void *cls, const struct GNUNET_PeerIdentity *peer,
3349 const struct GNUNET_MessageHeader *message)
3351 const struct PeerVerifySuccessorResultMessage *vsrm;
3352 struct GNUNET_PeerIdentity *trail_peer_list;
3353 struct GNUNET_PeerIdentity next_hop;
3354 struct FriendInfo *target_friend;
3356 uint32_t trail_length;
3358 msize = ntohs (message->size);
3359 if (msize < sizeof (struct PeerVerifySuccessorResultMessage))
3361 GNUNET_break_op (0);
3365 vsrm = (const struct PeerVerifySuccessorResultMessage *) message;
3366 trail_length = ntohl (vsrm->trail_length);
3369 sizeof (struct PeerVerifySuccessorResultMessage) +
3370 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3372 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3374 GNUNET_break_op (0);
3378 trail_peer_list = (struct GNUNET_PeerIdentity *) &vsrm[1];
3380 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->destination_peer), &(my_identity))))
3382 if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->my_predecessor), &(my_identity))))
3384 finger_table_add (&(vsrm->my_predecessor), trail_peer_list, trail_length, 0);
3385 memcpy (&next_hop, &trail_peer_list[0], sizeof (struct GNUNET_PeerIdentity));
3386 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3387 GDS_NEIGHBOURS_send_notify_new_successor (&my_identity, &(vsrm->my_predecessor),
3388 target_friend, trail_peer_list,
3396 /* FIXME: handle the case when current_path_index = GNUNET_SYSERR;*/
3397 /* FIXME: make sure you are passing the correct trail length */
3398 my_index = search_my_index (trail_peer_list, trail_length);
3400 memcpy (&next_hop, &(vsrm->destination_peer), sizeof (struct GNUNET_PeerIdentity));
3402 memcpy (&next_hop, &trail_peer_list[my_index-1], sizeof (struct GNUNET_PeerIdentity));
3403 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3404 GDS_NEIGHBOURS_send_verify_successor_result (&(vsrm->destination_peer),
3405 &(vsrm->source_successor),
3406 &(vsrm->my_predecessor),
3412 return GNUNET_SYSERR;
3417 * Core handle for p2p notify new successor messages.
3418 * @param cls closure
3419 * @param message message
3420 * @param peer peer identity this notification is about
3421 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3424 handle_dht_p2p_notify_new_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
3425 const struct GNUNET_MessageHeader *message)
3427 const struct PeerNotifyNewSuccessorMessage *nsm;
3428 struct GNUNET_PeerIdentity *trail_peer_list;
3430 uint32_t trail_length;
3432 msize = ntohs (message->size);
3433 if (msize < sizeof (struct PeerNotifyNewSuccessorMessage))
3435 GNUNET_break_op (0);
3439 nsm = (const struct PeerNotifyNewSuccessorMessage *) message;
3440 trail_length = ntohl (nsm->trail_length);
3442 if ((msize < sizeof (struct PeerNotifyNewSuccessorMessage) +
3443 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3445 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3447 GNUNET_break_op (0);
3451 trail_peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
3453 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(nsm->destination_peer), &my_identity)))
3455 //update_predecessor (&(nsm->destination_peer), trail_peer_list);
3460 struct FriendInfo *target_friend;
3461 struct GNUNET_PeerIdentity next_hop;
3464 /* FIXME: handle the case when current_path_index = GNUNET_SYSERR;*/
3465 /* FIXME: check that trail length is correct. */
3466 my_index = search_my_index (trail_peer_list, trail_length);
3467 memcpy (&next_hop, &trail_peer_list[my_index+1], sizeof (struct GNUNET_PeerIdentity));
3468 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3469 GDS_NEIGHBOURS_send_notify_new_successor (&(nsm->source_peer),
3470 &(nsm->destination_peer),
3471 target_friend, trail_peer_list,
3475 return GNUNET_SYSERR;
3480 * Core handler for P2P trail rejection message
3481 * @param cls closure
3482 * @param message message
3483 * @param peer peer identity this notification is about
3484 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3487 int handle_dht_p2p_trail_rejection(void *cls, const struct GNUNET_PeerIdentity *peer,
3488 const struct GNUNET_MessageHeader *message)
3490 /* Here you have recevied the message it means that the peer next to you have
3491 failed to setup the trail to the finger identity value. now you should call
3492 find_successor and make sure that you don't choose the peer as next hop
3493 in order to do so, you need to pass a new parameter to find successor,
3494 congested peer - a peer which you should ignore. once you have found this
3495 peer then just send a trail setup message to that peer. In case you are
3496 also congested then remove yourself from the trail as this message
3497 reached to as you are part of the trail. and then send the message to
3498 element before you. Ideally you should be the last element in the trail as
3499 all the the elements before you have rejected you. In case you are source,
3500 then you should call select_random_Friend(congested_peer). in case you don't
3501 find any peer because congested peer then set flag that all friends are busy
3503 const struct PeerTrailRejectionMessage *trail_rejection;
3504 struct GNUNET_PeerIdentity *trail_peer_list;
3505 struct GNUNET_PeerIdentity source_peer;
3506 struct GNUNET_PeerIdentity congested_peer;
3507 struct FriendInfo *target_friend;
3508 struct GNUNET_PeerIdentity next_peer;
3509 struct GNUNET_PeerIdentity *next_hop;
3510 struct GNUNET_PeerIdentity current_source;
3511 struct GNUNET_PeerIdentity current_destination;
3513 uint32_t trail_length;
3514 uint32_t finger_map_index;
3515 uint64_t destination_finger_value;
3517 msize = ntohs (message->size);
3518 if (msize < sizeof (struct PeerTrailRejectionMessage))
3520 GNUNET_break_op (0);
3524 trail_rejection = (struct PeerTrailRejectionMessage *) message;
3525 trail_length = ntohl (trail_rejection->trail_length);
3527 if ((msize < sizeof (struct PeerTrailRejectionMessage) +
3528 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3530 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3532 GNUNET_break_op (0);
3535 trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_rejection[1];
3536 finger_map_index = ntohl (trail_rejection->finger_map_index);
3537 memcpy (&source_peer, &(trail_rejection->source_peer), sizeof(struct GNUNET_PeerIdentity));
3538 memcpy (&destination_finger_value, &(trail_rejection->finger_identity_value), sizeof (uint64_t));
3539 memcpy (&congested_peer, &(trail_rejection->congested_peer), sizeof (struct GNUNET_PeerIdentity));
3541 /* If I am the source of the original trail setup message, then again select
3542 a random friend and send a new trail setup message to this finger identity
3544 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &source_peer)))
3546 /* If friend peer map is empty, or all the friends trail threshold has been crossed,
3548 if ((GNUNET_CONTAINER_multipeermap_size (friend_peermap) == 0) ||
3549 (all_friends_trail_threshold == GNUNET_YES))
3552 return GNUNET_SYSERR;
3555 /* Select any random friend except congested peer. */
3556 target_friend = select_random_friend (&congested_peer);
3558 if (NULL == target_friend)
3560 all_friends_trail_threshold = GNUNET_YES;
3561 return GNUNET_SYSERR;
3564 GDS_NEIGHBOURS_send_trail_setup (&my_identity, destination_finger_value, &(target_friend->id),
3565 &my_identity, target_friend, 0, NULL, finger_map_index);
3569 /* My routing state size has crossed the threshold, I can not be part of any more
3571 if(GDS_ROUTING_check_threshold())
3573 struct GNUNET_PeerIdentity *new_trail;
3575 if (trail_length == 1)
3577 memcpy (&next_peer, &source_peer, sizeof (struct GNUNET_PeerIdentity));
3581 memcpy (&next_peer, &trail_peer_list[trail_length - 2], sizeof (struct GNUNET_PeerIdentity));
3584 /* Remove myself from the trail. */
3585 new_trail = GNUNET_malloc ((trail_length -1) * sizeof (struct GNUNET_PeerIdentity));
3586 memcpy (new_trail, trail_peer_list, (trail_length -1) * sizeof (struct GNUNET_PeerIdentity));
3588 /* No more trails possible through me. send a trail rejection message to next hop. */
3589 GDS_NEIGHBOURS_send_trail_rejection (&source_peer, destination_finger_value, &my_identity,
3590 &next_peer,finger_map_index, new_trail,trail_length - 1);
3594 /* FIXME: In this case I have just written my_identity as current_destination
3595 and current source need ot think more of better values anad if needed or not.
3596 Also, i am adding a new parameter to funciton find_successor so that this peer
3597 is not considered as next hop congested_peer is not being used. FIXME. */
3598 memcpy (¤t_destination, &my_identity, sizeof (struct GNUNET_PeerIdentity));
3599 memcpy (¤t_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
3600 next_hop = find_successor (destination_finger_value, ¤t_destination, ¤t_source, &congested_peer);
3602 /* FIXME: WE NEED ANOTHER CASE as it may happend that congested peer is the only
3603 friend, and find_successor finds nothig, so check something else
3604 here like if current_destination is me, it means that i am destination
3605 or if current_destination = NULL, then it means found nothing. URGENT. */
3606 if (NULL == next_hop) /* This means I am the final destination */
3608 /* SUPU: trail length is 1, when I am the friend of the srouce peer. */
3609 if (trail_length == 1)
3611 memcpy (&next_peer, &source_peer, sizeof (struct GNUNET_PeerIdentity));
3615 memcpy (&next_peer, &trail_peer_list[trail_length-1], sizeof (struct GNUNET_PeerIdentity));
3618 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer);
3619 compare_and_update_predecessor (&source_peer, trail_peer_list, trail_length);
3621 GDS_NEIGHBOURS_send_trail_setup_result (&source_peer,
3623 target_friend, trail_length,
3630 /* Now add yourself to the trail. */
3631 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
3632 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
3633 peer_list[trail_length] = my_identity;
3636 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3637 GDS_NEIGHBOURS_send_trail_setup (&source_peer,
3638 destination_finger_value,
3639 ¤t_destination, ¤t_source,
3640 target_friend, trail_length, peer_list,
3644 return GNUNET_SYSERR;
3649 * Core handle for p2p trail tear down messages.
3650 * @param cls closure
3651 * @param message message
3652 * @param peer peer identity this notification is about
3653 * @return GNUNET_OK on success, GNUNET_SYSERR on error
3656 int handle_dht_p2p_trail_treadown (void *cls, const struct GNUNET_PeerIdentity *peer,
3657 const struct GNUNET_MessageHeader *message)
3659 /* Call is made to this function when the source peer removes an existing
3660 finger entry and it need to inform the peers which are part of the trail to remove
3661 the trail from their routing table. So, this peer should first
3662 get the next hop and then delete the entry. */
3663 struct PeerTrailTearDownMessage *trail_teardown;
3664 struct GNUNET_PeerIdentity *trail_peer_list;
3665 struct GNUNET_PeerIdentity next_hop;
3666 struct FriendInfo *target_friend;
3667 uint32_t trail_length;
3671 msize = ntohs (message->size);
3672 if (msize < sizeof (struct PeerTrailTearDownMessage))
3674 GNUNET_break_op (0);
3678 trail_teardown = (struct PeerTrailTearDownMessage *) message;
3679 trail_length = ntohl (trail_teardown->trail_length);
3681 if ((msize < sizeof (struct PeerTrailTearDownMessage) +
3682 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3684 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3686 GNUNET_break_op (0);
3690 trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_teardown[1];
3692 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_teardown->destination_peer), &my_identity)))
3694 /* We have reached destination then just return. May be if the peer before this
3695 destination, does not forward the packet to destination. So, this case should never
3701 my_index = search_my_index (trail_peer_list, trail_length);
3702 if (GNUNET_NO == GDS_ROUTING_remove_trail (&(trail_teardown->source_peer),
3703 &(trail_teardown->destination_peer),peer))
3705 /* Here we get GNUNET_NO, only if there is no matching entry found in routing
3711 if (my_index == (trail_length - 2))
3712 return GNUNET_SYSERR;
3714 memcpy (&next_hop, &trail_peer_list[my_index + 1], sizeof (struct GNUNET_PeerIdentity));
3715 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3717 GDS_NEIGHBOURS_send_trail_teardown (&(trail_teardown->source_peer),
3718 &(trail_teardown->destination_peer),
3719 trail_peer_list, trail_length, target_friend);
3724 * Iterate over finger_peermap, and remove entries with peer as the first element
3726 * @param cls closure
3727 * @param key current public key
3728 * @param value value in the hash map
3729 * @return #GNUNET_YES if we should continue to
3731 * #GNUNET_NO if not.
3734 remove_matching_finger (void *cls,
3735 const struct GNUNET_PeerIdentity *key,
3738 struct FingerInfo *remove_finger = value;
3739 const struct GNUNET_PeerIdentity *disconnected_peer = cls;
3741 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&remove_finger->first_trail_head->peer, disconnected_peer))
3743 GNUNET_assert (GNUNET_YES ==
3744 GNUNET_CONTAINER_multipeermap_remove (finger_peermap,
3747 free_finger (remove_finger);
3754 * Method called whenever a peer disconnects.
3756 * @param cls closure
3757 * @param peer peer identity this notification is about
3760 handle_core_disconnect (void *cls,
3761 const struct GNUNET_PeerIdentity *peer)
3763 struct FriendInfo *remove_friend;
3765 /* Check for self message. */
3766 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
3769 /* Search for peer to remove in your friend_peermap. */
3771 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
3773 if (NULL == remove_friend)
3779 /* Remove fingers for which this peer is the first element in the trail. */
3780 GNUNET_CONTAINER_multipeermap_iterate (finger_peermap,
3781 &remove_matching_finger, (void *)peer);
3783 /* Remove routing trails of which this peer is a part. */
3784 GDS_ROUTING_remove_entry (peer);
3786 /* Remove the peer from friend_peermap. */
3787 GNUNET_assert (GNUNET_YES ==
3788 GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
3792 if (0 != GNUNET_CONTAINER_multipeermap_size (friend_peermap))
3795 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
3797 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
3798 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
3803 if (GNUNET_SCHEDULER_NO_TASK != verify_successor)
3805 GNUNET_SCHEDULER_cancel (verify_successor);
3806 verify_successor = GNUNET_SCHEDULER_NO_TASK;
3812 * Method called whenever a peer connects.
3814 * @param cls closure
3815 * @param peer_identity peer identity this notification is about
3818 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity)
3820 struct FriendInfo *friend;
3822 /* Check for connect to self message */
3823 if (0 == memcmp (&my_identity, peer_identity, sizeof (struct GNUNET_PeerIdentity)))
3826 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to %s\n", GNUNET_i2s (peer_identity));
3828 /* If peer already exists in our friend_peermap, then exit. */
3829 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (friend_peermap, peer_identity))
3835 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
3838 friend = GNUNET_new (struct FriendInfo);
3839 friend->id = *peer_identity;
3840 friend->trails_count = 0;
3842 GNUNET_assert (GNUNET_OK ==
3843 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
3844 peer_identity, friend,
3845 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
3847 /* got a first connection, good time to start with FIND FINGER TRAIL requests... */
3848 if (GNUNET_SCHEDULER_NO_TASK == find_finger_trail_task)
3849 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
3854 * To be called on core init/fail.
3856 * @param cls service closure
3857 * @param identity the public identity of this peer
3860 core_init (void *cls,
3861 const struct GNUNET_PeerIdentity *identity)
3863 my_identity = *identity;
3868 * Initialize neighbours subsystem.
3869 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3872 GDS_NEIGHBOURS_init (void)
3874 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
3875 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0},
3876 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0},
3877 {&handle_dht_p2p_get_result, GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT, 0},
3878 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP, 0},
3879 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT, 0},
3880 {&handle_dht_p2p_verify_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR, 0},
3881 {&handle_dht_p2p_verify_successor_result, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT, 0},
3882 {&handle_dht_p2p_notify_new_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR, 0},
3883 {&handle_dht_p2p_trail_rejection, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION, 0},
3884 {&handle_dht_p2p_trail_treadown, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_TEARDOWN, 0},
3889 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
3890 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
3891 GNUNET_NO, core_handlers);
3892 if (NULL == core_api)
3893 return GNUNET_SYSERR;
3895 friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
3896 finger_peermap = GNUNET_CONTAINER_multipeermap_create (MAX_FINGERS * 4/3, GNUNET_NO);
3898 all_friends_trail_threshold = GNUNET_NO;
3905 * Shutdown neighbours subsystem.
3908 GDS_NEIGHBOURS_done (void)
3910 if (NULL == core_api)
3913 GNUNET_CORE_disconnect (core_api);
3916 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
3917 GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
3918 friend_peermap = NULL;
3920 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (finger_peermap));
3921 GNUNET_CONTAINER_multipeermap_destroy (finger_peermap);
3922 finger_peermap = NULL;
3924 /* FIXME: Here I have added GNUNET_break(0) as ideally if friend_peermap
3925 is already zero, then we really don't need to cancel it again. If this
3926 condition happens it mean we might have missed some corner case. */
3927 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
3930 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
3931 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
3934 if (GNUNET_SCHEDULER_NO_TASK != verify_successor)
3937 GNUNET_SCHEDULER_cancel (verify_successor);
3938 verify_successor = GNUNET_SCHEDULER_NO_TASK;
3944 * FIXME: Here I want to send only the value not the address. Initially
3945 * I wanted to make it const struct * so that no other function can change it.
3946 * then in client file, i make a copy and send that copy. now I have made this
3950 * @return my identity
3952 struct GNUNET_PeerIdentity
3953 GDS_NEIGHBOURS_get_my_id (void)
3959 /* end of gnunet-service-xdht_neighbours.c */