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 next_hop = find_successor (key_value, &curr_dest, &curr_src, NULL);
2473 /* FIXME: Again I am copying back value of current_destination, current_source,
2474 Think of a better solution. */
2475 memcpy (¤t_destination, &curr_dest, sizeof (struct GNUNET_PeerIdentity));
2476 memcpy (¤t_source, &curr_src, sizeof (struct GNUNET_PeerIdentity));
2477 if (NULL == next_hop) /* I am the destination do datacache_put */
2479 GDS_DATACACHE_handle_get (key,block_type, NULL, 0,
2480 NULL, 0, 1, &my_identity, NULL,&my_identity);
2485 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2489 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2490 pending->importance = 0; /* FIXME */
2491 pgm = (struct PeerGetMessage *) &pending[1];
2492 pending->msg = &pgm->header;
2493 pgm->header.size = htons (msize);
2494 pgm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
2495 pgm->get_path_length = htonl (get_path_length);
2497 pgm->current_destination = current_destination;
2498 pgm->current_source = current_source;
2499 pgm->hop_count = htonl (hop_count + 1);
2501 gp = (struct GNUNET_PeerIdentity *) &pgm[1];
2502 memcpy (gp, get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity));
2503 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2504 target_friend->pending_count++;
2505 process_friend_queue (target_friend);
2510 * Send the get result to requesting client.
2511 * @param expiration When will this result expire?
2512 * @param key Key of the requested data.
2513 * @param put_path_length Number of peers in @a put_path
2514 * @param put_path Path taken to put the data at its stored location.
2515 * @param type Block type
2516 * @param data_size Size of the @a data
2517 * @param data Payload to store
2518 * @param get_path Path taken to reach to the location of the key.
2519 * @param get_path_length Number of peers in @a get_path
2520 * @param next_hop Next peer to forward the message to.
2521 * @param source_peer Peer which has the data for the key.
2524 GDS_NEIGHBOURS_send_get_result (struct GNUNET_TIME_Absolute expiration,
2525 const struct GNUNET_HashCode *key,
2526 unsigned int put_path_length,
2527 const struct GNUNET_PeerIdentity *put_path,
2528 enum GNUNET_BLOCK_Type type, size_t data_size,
2530 struct GNUNET_PeerIdentity *get_path,
2531 unsigned int get_path_length,
2532 struct GNUNET_PeerIdentity *next_hop,
2533 struct GNUNET_PeerIdentity *source_peer)
2535 struct PeerGetResultMessage *get_result;
2536 struct GNUNET_PeerIdentity *get_result_path;
2537 struct GNUNET_PeerIdentity *pp;
2538 struct P2PPendingMessage *pending;
2539 struct FriendInfo *target_friend;
2540 int current_path_index;
2543 msize = get_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
2544 sizeof (struct PeerPutMessage);
2546 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2552 current_path_index = search_my_index(get_path, get_path_length);
2553 /* FIXME: handle the case when current_path_index = GNUNET_SYSERR;*/
2554 if (0 == current_path_index)
2556 GDS_CLIENTS_handle_reply (expiration, key, get_path_length, get_path, put_path_length,
2557 put_path, type, data_size, data);
2560 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2561 pending->importance = 0;
2562 get_result = (struct PeerGetResultMessage *)&pending[1];
2563 pending->msg = &get_result->header;
2564 get_result->header.size = htons (msize);
2565 get_result->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT);
2566 get_result->key = *key;
2567 memcpy (&(get_result->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
2568 get_result->expiration_time = expiration;
2570 get_result_path = (struct GNUNET_PeerIdentity *)&get_result[1];
2571 memcpy (get_result_path, get_path,
2572 sizeof (struct GNUNET_PeerIdentity) * get_path_length);
2573 memcpy (&get_result_path[get_path_length], data, data_size);
2574 /* FIXME: Is this correct? */
2575 pp = (struct GNUNET_PeerIdentity *)&get_result_path[1];
2576 memcpy (pp, put_path,sizeof (struct GNUNET_PeerIdentity) * put_path_length);
2578 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2579 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2580 target_friend->pending_count++;
2581 process_friend_queue (target_friend);
2586 * Send tral rejection message to the peer which sent me a trail setup message.
2587 * @param source_peer Source peer which wants to set up the trail.
2588 * @param finger_identity Value whose successor will be the finger of @a source_peer.
2589 * @param congested_peer Peer which has send trail rejection message.
2590 * @param next_hop Peer to which this message should be forwarded.
2591 * @param finger_map_index Index in @a source_peer finger peermap.
2592 * @param trail_peer_list Trail followed to reach from @a source_peer to next_hop,
2593 * NULL, in case the @a congested_peer was the first peer
2594 * to which trail setup message was forwarded.
2595 * @param trail_length Number of peers in trail_peer_list.
2598 GDS_NEIGHBOURS_send_trail_rejection (struct GNUNET_PeerIdentity *source_peer,
2599 uint64_t finger_identity,
2600 struct GNUNET_PeerIdentity *congested_peer,
2601 const struct GNUNET_PeerIdentity *next_hop,
2602 unsigned int finger_map_index,
2603 struct GNUNET_PeerIdentity *trail_peer_list,
2604 unsigned int trail_length)
2606 struct PeerTrailRejectionMessage *trail_rejection;
2607 struct GNUNET_PeerIdentity *trail_list;
2608 struct P2PPendingMessage *pending;
2609 struct FriendInfo *target_friend;
2612 msize = trail_length * sizeof(struct GNUNET_PeerIdentity) +
2613 sizeof (struct PeerTrailRejectionMessage);
2615 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2621 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2622 pending->importance = 0;
2623 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
2624 trail_rejection = (struct PeerTrailRejectionMessage *) &pending[1];
2625 pending->msg = &trail_rejection->header;
2626 trail_rejection->header.size = htons (msize);
2627 trail_rejection->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
2628 memcpy (&(trail_rejection->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
2629 memcpy (&(trail_rejection->congested_peer), congested_peer, sizeof (struct GNUNET_PeerIdentity));
2630 memcpy (&(trail_rejection->finger_identity_value), &finger_identity, sizeof (uint64_t));
2631 trail_rejection->finger_map_index = htonl(finger_map_index);
2632 trail_rejection->trail_length = htonl (trail_length);
2634 trail_list = (struct GNUNET_PeerIdentity *)&trail_rejection[1];
2635 if (trail_length != 0)
2636 memcpy (trail_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
2638 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2639 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2640 target_friend->pending_count++;
2641 process_friend_queue (target_friend);
2646 * Core handler for P2P put messages.
2647 * @param cls closure
2648 * @param peer sender of the request
2649 * @param message message
2650 * @return #GNUNET_OK to keep the connection open,
2651 * #GNUNET_SYSERR to close it (signal serious error)
2654 handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer,
2655 const struct GNUNET_MessageHeader *message)
2657 struct PeerPutMessage *put;
2658 struct GNUNET_PeerIdentity *put_path;
2659 struct GNUNET_HashCode test_key;
2660 enum GNUNET_DHT_RouteOption options;
2661 struct GNUNET_PeerIdentity current_destination;
2662 struct GNUNET_PeerIdentity current_source;
2663 struct GNUNET_PeerIdentity *next_hop;
2667 size_t payload_size;
2670 msize = ntohs (message->size);
2671 if (msize < sizeof (struct PeerPutMessage))
2673 GNUNET_break_op (0);
2677 put = (struct PeerPutMessage *) message;
2678 putlen = ntohl (put->put_path_length);
2681 sizeof (struct PeerPutMessage) +
2682 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
2684 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2686 GNUNET_break_op (0);
2690 current_destination = put->current_destination;
2691 current_source = put->current_source;
2692 put_path = (struct GNUNET_PeerIdentity *) &put[1];
2693 payload = &put_path[putlen];
2694 options = ntohl (put->options);
2695 payload_size = msize - (sizeof (struct PeerPutMessage) +
2696 putlen * sizeof (struct GNUNET_PeerIdentity));
2698 switch (GNUNET_BLOCK_get_key (GDS_block_context, ntohl (put->block_type),
2699 payload, payload_size, &test_key))
2702 if (0 != memcmp (&test_key, &put->key, sizeof (struct GNUNET_HashCode)))
2704 char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key));
2705 GNUNET_break_op (0);
2706 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2707 "PUT with key `%s' for block with key %s\n",
2708 put_s, GNUNET_h2s_full (&test_key));
2709 GNUNET_free (put_s);
2714 GNUNET_break_op (0);
2717 /* cannot verify, good luck */
2721 if (ntohl (put->block_type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
2723 switch (GNUNET_BLOCK_evaluate (GDS_block_context,
2724 ntohl (put->block_type),
2726 NULL, 0, /* bloom filer */
2727 NULL, 0, /* xquery */
2728 payload, payload_size))
2730 case GNUNET_BLOCK_EVALUATION_OK_MORE:
2731 case GNUNET_BLOCK_EVALUATION_OK_LAST:
2734 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
2735 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
2736 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
2737 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
2738 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
2739 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
2741 GNUNET_break_op (0);
2746 struct GNUNET_PeerIdentity pp[putlen + 1];
2747 /* extend 'put path' by sender */
2748 /* FIXME: Check what are we doing here? */
2749 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
2751 memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity));
2758 memcpy (&key_value, &(put->key), sizeof (uint64_t));
2759 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_destination, &my_identity)))
2761 next_hop = GDS_ROUTING_search (¤t_source, ¤t_destination, peer);
2762 if (next_hop == NULL)
2764 /* refer to handle_dht_p2p_trail_setup. */
2769 next_hop = find_successor (key_value, ¤t_destination, ¤t_source, NULL);
2772 if (NULL == next_hop) /* I am the final destination */
2774 GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time),
2775 &(put->key),putlen, pp, ntohl (put->block_type),
2776 payload_size, payload);
2781 GDS_CLIENTS_process_put (options,
2782 ntohl (put->block_type),
2783 ntohl (put->hop_count),
2784 ntohl (put->desired_replication_level),
2786 GNUNET_TIME_absolute_ntoh (put->expiration_time),
2791 GDS_NEIGHBOURS_send_put (&put->key, payload, payload_size,
2792 ntohl (put->block_type),ntohl (put->options),
2793 ntohl (put->desired_replication_level),
2794 GNUNET_TIME_absolute_ntoh (put->expiration_time),
2795 current_destination, current_source, next_hop,
2796 ntohl (put->hop_count), putlen, pp);
2800 return GNUNET_SYSERR;
2805 * Core handler for p2p get requests.
2807 * @param cls closure
2808 * @param peer sender of the request
2809 * @param message message
2810 * @return #GNUNET_OK to keep the connection open,
2811 * #GNUNET_SYSERR to close it (signal serious error)
2814 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
2815 const struct GNUNET_MessageHeader *message)
2817 struct PeerGetMessage *get;
2818 struct GNUNET_PeerIdentity *get_path;
2819 struct GNUNET_PeerIdentity current_destination;
2820 struct GNUNET_PeerIdentity current_source;
2821 struct GNUNET_PeerIdentity *next_hop;
2822 uint32_t get_length;
2826 msize = ntohs (message->size);
2827 if (msize < sizeof (struct PeerGetMessage))
2829 GNUNET_break_op (0);
2833 get = (struct PeerGetMessage *)message;
2834 get_length = ntohl (get->get_path_length);
2835 get_path = (struct GNUNET_PeerIdentity *)&get[1];
2836 current_destination = get->current_destination;
2837 current_source = get->current_source;
2840 sizeof (struct PeerGetMessage) +
2841 get_length * sizeof (struct GNUNET_PeerIdentity)) ||
2843 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2845 GNUNET_break_op (0);
2849 /* Add sender to get path */
2850 struct GNUNET_PeerIdentity gp[get_length + 1];
2851 memcpy (gp, get_path, get_length * sizeof (struct GNUNET_PeerIdentity));
2852 gp[get_length + 1] = *peer;
2853 get_length = get_length + 1;
2855 memcpy (&key_value, &(get->key), sizeof (uint64_t));
2856 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_destination, &my_identity)))
2858 next_hop = GDS_ROUTING_search (¤t_source, ¤t_destination, peer);
2859 if (next_hop == NULL)
2861 /* refer to handle_dht_p2p_trail_setup. */
2866 next_hop = find_successor (key_value, ¤t_destination, ¤t_source, NULL);
2869 if (NULL == next_hop)
2871 /* FIXME: Try to make this code also short and remove useless variables. */
2872 struct GNUNET_PeerIdentity final_get_path[get_length+1];
2873 memcpy (final_get_path, gp, get_length * sizeof (struct GNUNET_PeerIdentity));
2874 memcpy (&final_get_path[get_length+1], &my_identity, sizeof (struct GNUNET_PeerIdentity));
2875 get_length = get_length + 1;
2876 struct GNUNET_PeerIdentity *next_hop;
2877 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2878 memcpy (next_hop, &final_get_path[get_length-2], sizeof (struct GNUNET_PeerIdentity));
2879 GDS_DATACACHE_handle_get (&(get->key),(get->block_type), NULL, 0, NULL, 0,
2880 get_length, final_get_path,next_hop, &my_identity);
2886 GDS_NEIGHBOURS_send_get (&(get->key), get->block_type, get->options,
2887 get->desired_replication_level,current_destination,
2888 current_source, next_hop, 0,
2891 return GNUNET_SYSERR;
2897 * Core handler for get result
2898 * @param cls closure
2899 * @param peer sender of the request
2900 * @param message message
2901 * @return #GNUNET_OK to keep the connection open,
2902 * #GNUNET_SYSERR to close it (signal serious error)
2905 handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer,
2906 const struct GNUNET_MessageHeader *message)
2908 /* If you are the source, go back to the client file and there search for
2909 the requesting client and send back the result. */
2910 struct PeerGetResultMessage *get_result;
2911 struct GNUNET_PeerIdentity *get_path;
2912 struct GNUNET_PeerIdentity *put_path;
2914 size_t payload_size;
2916 unsigned int getlen;
2917 unsigned int putlen;
2918 int current_path_index;
2920 msize = ntohs (message->size);
2921 if (msize < sizeof (struct PeerGetResultMessage))
2923 GNUNET_break_op (0);
2927 get_result = (struct PeerGetResultMessage *)message;
2928 getlen = ntohl (get_result->get_path_length);
2929 putlen = ntohl (get_result->put_path_length);
2932 sizeof (struct PeerGetResultMessage) +
2933 getlen * sizeof (struct GNUNET_PeerIdentity) +
2934 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
2936 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity) ||
2938 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))))
2940 GNUNET_break_op (0);
2944 get_path = (struct GNUNET_PeerIdentity *) &get_result[1];
2945 payload = &get_path[getlen];
2946 payload_size = msize - (sizeof (struct PeerGetResultMessage) +
2947 getlen * sizeof (struct GNUNET_PeerIdentity));
2948 /* FIXME: Check if its correct or not. */
2951 put_path = &get_path[1];
2955 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &(get_path[0]))))
2957 //GDS_CLIENTS_process_get_result();
2958 GDS_CLIENTS_handle_reply (get_result->expiration_time, &(get_result->key),
2959 getlen, get_path, putlen,
2960 put_path, get_result->type, payload_size, payload);
2965 struct GNUNET_PeerIdentity *next_hop;
2966 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2967 /* FIXME: handle the case when current_path_index = GNUNET_SYSERR;*/
2968 current_path_index = search_my_index (get_path, getlen);
2969 /* FIXME: First check if you are adding yourself to the get path or not.
2970 if yes then don't check if current_path_index == 0, if not then check
2971 and next_hop == source_peer. */
2972 memcpy (next_hop, &get_path[current_path_index - 1], sizeof (struct GNUNET_PeerIdentity));
2974 GDS_NEIGHBOURS_send_get_result (get_result->expiration_time, &(get_result->key),
2976 get_result->type, payload_size,payload,
2978 next_hop, &(get_result->source_peer));
2981 return GNUNET_SYSERR;
2986 * Core handle for PeerTrailSetupMessage.
2987 * @param cls closure
2988 * @param message message
2989 * @param peer peer identity this notification is about
2990 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
2993 handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer,
2994 const struct GNUNET_MessageHeader *message)
2996 const struct PeerTrailSetupMessage *trail_setup;
2997 struct GNUNET_PeerIdentity current_destination;
2998 struct GNUNET_PeerIdentity current_source;
2999 struct GNUNET_PeerIdentity source;
3000 struct GNUNET_PeerIdentity *next_hop;
3001 struct GNUNET_PeerIdentity next_peer;
3002 struct GNUNET_PeerIdentity *trail_peer_list;
3003 struct FriendInfo *target_friend;
3004 uint64_t destination_finger_value;
3005 uint32_t trail_length;
3006 uint32_t finger_map_index;
3009 msize = ntohs (message->size);
3010 if (msize < sizeof (struct PeerTrailSetupMessage))
3012 GNUNET_break_op (0);
3016 trail_setup = (const struct PeerTrailSetupMessage *) message;
3017 trail_length = ntohl (trail_setup->trail_length);
3019 if ((msize < sizeof (struct PeerTrailSetupMessage) +
3020 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3022 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3024 GNUNET_break_op (0);
3028 trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_setup[1];
3029 current_destination = trail_setup->current_destination;
3030 current_source = trail_setup->current_source;
3031 source = trail_setup->source_peer;
3032 finger_map_index = ntohl (trail_setup->finger_map_index);
3033 destination_finger_value = ntohl (trail_setup->destination_finger);
3035 /* My routing state size has crossed the threshold, I can not be part of any more
3037 if(GDS_ROUTING_check_threshold())
3039 /* No more trails possible through me. send a trail rejection message. */
3040 GDS_NEIGHBOURS_send_trail_rejection (&source, destination_finger_value, &my_identity,
3041 peer,finger_map_index, trail_peer_list,trail_length);
3045 /* Check if you are current_destination or not. */
3046 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_destination, &my_identity)))
3048 next_hop = GDS_ROUTING_search (¤t_source, ¤t_destination, peer);
3049 /* ADDNOW: OPTIMIZATION: do find_successor also and get a better path if possible. */
3051 if (next_hop == NULL)
3053 /* FIXME next_hop is NULL, in a case when next_hop was a friend which got disconnected
3054 * and we removed the trail from our routing trail. So, I can send the message
3055 * to other peer or can drop the message. VERIFY which will be the correct
3056 * thing to do. next_hop to NULL, 1. statistics update, drop the message.
3057 * 2. complain to sender with new message: trail lost */
3063 next_hop = find_successor (destination_finger_value, ¤t_destination, ¤t_source, NULL);
3066 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (¤t_destination, &my_identity))) /* This means I am the final destination */
3068 /* SUPU: trail length is 0, when I am the friend of the source peer. */
3069 if (trail_length == 0)
3071 memcpy (&next_peer, &source, sizeof (struct GNUNET_PeerIdentity));
3075 memcpy (&next_peer, &trail_peer_list[trail_length-1], sizeof (struct GNUNET_PeerIdentity));
3078 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer);
3079 /* ! HAVE A PREDECESSOR || (source_peer closer than existing PREDECESOR) */
3080 compare_and_update_predecessor (&source, trail_peer_list, trail_length );
3082 GDS_NEIGHBOURS_send_trail_setup_result (&source,
3084 target_friend, trail_length,
3091 /* Now add yourself to the trail. */
3092 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
3093 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
3094 peer_list[trail_length] = my_identity;
3097 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3098 GDS_NEIGHBOURS_send_trail_setup (&source,
3099 destination_finger_value,
3100 ¤t_destination, ¤t_source,
3101 target_friend, trail_length, peer_list,
3105 return GNUNET_SYSERR;
3110 * Core handle for p2p trail construction result messages.
3112 * @param message message
3113 * @param peer peer identity this notification is about
3114 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3117 handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer,
3118 const struct GNUNET_MessageHeader *message)
3120 const struct PeerTrailSetupResultMessage *trail_result;
3121 struct GNUNET_PeerIdentity *trail_peer_list;
3122 uint32_t trail_length;
3123 uint32_t finger_map_index;
3126 msize = ntohs (message->size);
3127 if (msize < sizeof (struct PeerTrailSetupResultMessage))
3129 GNUNET_break_op (0);
3133 trail_result = (const struct PeerTrailSetupResultMessage *) message;
3134 trail_length = ntohl (trail_result->trail_length);
3137 sizeof (struct PeerTrailSetupResultMessage) +
3138 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3140 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3142 GNUNET_break_op (0);
3146 finger_map_index = htonl (trail_result->finger_map_index);
3147 trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_result[1];
3149 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->destination_peer),
3152 finger_table_add (&(trail_result->finger_identity), trail_peer_list, trail_length,
3158 struct GNUNET_PeerIdentity next_hop;
3159 struct FriendInfo *target_friend;
3162 /* FIXME: handle the case when current_path_index = GNUNET_SYSERR;*/
3163 /* FIXME: Make sure you are passing the current length */
3164 my_index = search_my_index (trail_peer_list, trail_length);
3167 next_hop = trail_result->destination_peer;
3170 next_hop = trail_peer_list[my_index - 1];
3172 /* Finger table of destination peer will not contain any trail for the case
3173 * where destination peer is its own finger identity. */
3174 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->destination_peer),
3175 &(trail_result->finger_identity))))
3177 GDS_ROUTING_add (&(trail_result->destination_peer), &(trail_result->finger_identity),
3181 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3182 GDS_NEIGHBOURS_send_trail_setup_result (&(trail_result->destination_peer),
3183 &(trail_result->finger_identity),
3184 target_friend, trail_length,
3189 return GNUNET_SYSERR;
3194 * FIXME: Use flag in the case finger peer map does not contain predcessor
3195 * then its NULL. Ideally it should never happen. Some one sent you are verify
3196 * successor and you don't have any predecessor, then ideally you should
3197 * GNUNET_break_op(0).
3198 * Get my current predecessor from the finger peer map
3199 * @return Current predecessor.
3201 static struct FingerInfo *
3204 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
3205 struct GNUNET_PeerIdentity key_ret;
3206 unsigned int finger_index;
3207 struct FingerInfo *my_predecessor;
3209 /* Iterate over finger peer map and extract your predecessor. */
3210 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
3211 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
3213 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next
3214 (finger_iter,&key_ret,(const void **)&my_predecessor))
3216 if(1 == my_predecessor->finger_map_index)
3222 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
3223 return my_predecessor;
3228 * Core handle for p2p verify successor messages.
3229 * @param cls closure
3230 * @param message message
3231 * @param peer peer identity this notification is about
3232 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3235 handle_dht_p2p_verify_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
3236 const struct GNUNET_MessageHeader *message)
3238 const struct PeerVerifySuccessorMessage *vsm;
3239 const struct GNUNET_PeerIdentity *trail_peer_list;
3240 struct GNUNET_PeerIdentity source_peer;
3241 struct GNUNET_PeerIdentity next_hop;
3242 struct FriendInfo *target_friend;
3244 uint32_t trail_length;
3246 msize = ntohs (message->size);
3247 if (msize < sizeof (struct PeerVerifySuccessorMessage))
3249 GNUNET_break_op (0);
3253 vsm = (struct PeerVerifySuccessorMessage *) message;
3254 trail_length = ntohl (vsm->trail_length);
3256 if ((msize < sizeof (struct PeerVerifySuccessorMessage) +
3257 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3258 (trail_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3260 GNUNET_break_op (0);
3264 trail_peer_list = (const struct GNUNET_PeerIdentity *)&vsm[1];
3265 memcpy (&source_peer, &(vsm->source_peer), sizeof(struct GNUNET_PeerIdentity));
3266 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsm->successor),&my_identity)))
3268 struct FingerInfo *my_predecessor;
3270 if (trail_length == 0)
3271 memcpy (&next_hop, &source_peer, sizeof (struct GNUNET_PeerIdentity));
3274 int current_trail_index;
3275 current_trail_index = search_my_index (trail_peer_list, trail_length);
3276 memcpy (&next_hop, &trail_peer_list[current_trail_index-1], sizeof (struct GNUNET_PeerIdentity));
3278 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3280 my_predecessor = get_predecessor();
3281 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&source_peer,
3282 &(my_predecessor->finger_identity))))
3285 GDS_NEIGHBOURS_send_verify_successor_result (&source_peer,
3287 &(my_predecessor->finger_identity),
3294 struct GNUNET_PeerIdentity *new_successor_trail;
3295 struct TrailPeerList *iterator;
3296 int new_trail_length;
3299 new_trail_length = trail_length + my_predecessor->first_trail_length + 1;
3300 new_successor_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * new_trail_length);
3301 memcpy (new_successor_trail, trail_peer_list, (trail_length) * sizeof (struct GNUNET_PeerIdentity));
3302 memcpy (&new_successor_trail[trail_length], &my_identity, sizeof (struct GNUNET_PeerIdentity));
3304 iterator = GNUNET_malloc (sizeof (struct TrailPeerList));
3305 iterator = my_predecessor->first_trail_head;
3306 i = trail_length + 1;
3307 while (i < new_trail_length)
3309 memcpy (&new_successor_trail[i], &(iterator->peer), sizeof (struct GNUNET_PeerIdentity));
3310 iterator = iterator->next;
3314 GDS_NEIGHBOURS_send_verify_successor_result (&source_peer,
3316 &(my_predecessor->finger_identity),
3318 new_successor_trail,
3326 /* FIXME: handle the case when current_path_index = GNUNET_SYSERR;*/
3327 /* FIXME: make sure you are passing the correct trail length */
3328 my_index = search_my_index (trail_peer_list, trail_length);
3329 memcpy (&next_hop, &trail_peer_list[my_index + 1], sizeof (struct GNUNET_PeerIdentity));
3330 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3332 GDS_NEIGHBOURS_send_verify_successor (&(vsm->source_peer), &(vsm->successor),target_friend,
3333 trail_peer_list, trail_length);
3335 return GNUNET_SYSERR;
3340 * Core handle for p2p verify successor result messages.
3341 * @param cls closure
3342 * @param message message
3343 * @param peer peer identity this notification is about
3344 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3347 handle_dht_p2p_verify_successor_result(void *cls, const struct GNUNET_PeerIdentity *peer,
3348 const struct GNUNET_MessageHeader *message)
3350 const struct PeerVerifySuccessorResultMessage *vsrm;
3351 struct GNUNET_PeerIdentity *trail_peer_list;
3352 struct GNUNET_PeerIdentity next_hop;
3353 struct FriendInfo *target_friend;
3355 uint32_t trail_length;
3357 msize = ntohs (message->size);
3358 if (msize < sizeof (struct PeerVerifySuccessorResultMessage))
3360 GNUNET_break_op (0);
3364 vsrm = (const struct PeerVerifySuccessorResultMessage *) message;
3365 trail_length = ntohl (vsrm->trail_length);
3368 sizeof (struct PeerVerifySuccessorResultMessage) +
3369 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3371 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3373 GNUNET_break_op (0);
3377 trail_peer_list = (struct GNUNET_PeerIdentity *) &vsrm[1];
3379 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->destination_peer), &(my_identity))))
3381 if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->my_predecessor), &(my_identity))))
3383 finger_table_add (&(vsrm->my_predecessor), trail_peer_list, trail_length, 0);
3384 memcpy (&next_hop, &trail_peer_list[0], sizeof (struct GNUNET_PeerIdentity));
3385 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3386 GDS_NEIGHBOURS_send_notify_new_successor (&my_identity, &(vsrm->my_predecessor),
3387 target_friend, trail_peer_list,
3395 /* FIXME: handle the case when current_path_index = GNUNET_SYSERR;*/
3396 /* FIXME: make sure you are passing the correct trail length */
3397 my_index = search_my_index (trail_peer_list, trail_length);
3399 memcpy (&next_hop, &(vsrm->destination_peer), sizeof (struct GNUNET_PeerIdentity));
3401 memcpy (&next_hop, &trail_peer_list[my_index-1], sizeof (struct GNUNET_PeerIdentity));
3402 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3403 GDS_NEIGHBOURS_send_verify_successor_result (&(vsrm->destination_peer),
3404 &(vsrm->source_successor),
3405 &(vsrm->my_predecessor),
3411 return GNUNET_SYSERR;
3416 * Core handle for p2p notify new successor messages.
3417 * @param cls closure
3418 * @param message message
3419 * @param peer peer identity this notification is about
3420 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3423 handle_dht_p2p_notify_new_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
3424 const struct GNUNET_MessageHeader *message)
3426 const struct PeerNotifyNewSuccessorMessage *nsm;
3427 struct GNUNET_PeerIdentity *trail_peer_list;
3429 uint32_t trail_length;
3431 msize = ntohs (message->size);
3432 if (msize < sizeof (struct PeerNotifyNewSuccessorMessage))
3434 GNUNET_break_op (0);
3438 nsm = (const struct PeerNotifyNewSuccessorMessage *) message;
3439 trail_length = ntohl (nsm->trail_length);
3441 if ((msize < sizeof (struct PeerNotifyNewSuccessorMessage) +
3442 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3444 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3446 GNUNET_break_op (0);
3450 trail_peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
3452 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(nsm->destination_peer), &my_identity)))
3454 //update_predecessor (&(nsm->destination_peer), trail_peer_list);
3459 struct FriendInfo *target_friend;
3460 struct GNUNET_PeerIdentity next_hop;
3463 /* FIXME: handle the case when current_path_index = GNUNET_SYSERR;*/
3464 /* FIXME: check that trail length is correct. */
3465 my_index = search_my_index (trail_peer_list, trail_length);
3466 memcpy (&next_hop, &trail_peer_list[my_index+1], sizeof (struct GNUNET_PeerIdentity));
3467 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3468 GDS_NEIGHBOURS_send_notify_new_successor (&(nsm->source_peer),
3469 &(nsm->destination_peer),
3470 target_friend, trail_peer_list,
3474 return GNUNET_SYSERR;
3479 * Core handler for P2P trail rejection message
3480 * @param cls closure
3481 * @param message message
3482 * @param peer peer identity this notification is about
3483 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3486 int handle_dht_p2p_trail_rejection(void *cls, const struct GNUNET_PeerIdentity *peer,
3487 const struct GNUNET_MessageHeader *message)
3489 /* Here you have recevied the message it means that the peer next to you have
3490 failed to setup the trail to the finger identity value. now you should call
3491 find_successor and make sure that you don't choose the peer as next hop
3492 in order to do so, you need to pass a new parameter to find successor,
3493 congested peer - a peer which you should ignore. once you have found this
3494 peer then just send a trail setup message to that peer. In case you are
3495 also congested then remove yourself from the trail as this message
3496 reached to as you are part of the trail. and then send the message to
3497 element before you. Ideally you should be the last element in the trail as
3498 all the the elements before you have rejected you. In case you are source,
3499 then you should call select_random_Friend(congested_peer). in case you don't
3500 find any peer because congested peer then set flag that all friends are busy
3502 const struct PeerTrailRejectionMessage *trail_rejection;
3503 struct GNUNET_PeerIdentity *trail_peer_list;
3504 struct GNUNET_PeerIdentity source_peer;
3505 struct GNUNET_PeerIdentity congested_peer;
3506 struct FriendInfo *target_friend;
3507 struct GNUNET_PeerIdentity next_peer;
3508 struct GNUNET_PeerIdentity *next_hop;
3509 struct GNUNET_PeerIdentity current_source;
3510 struct GNUNET_PeerIdentity current_destination;
3512 uint32_t trail_length;
3513 uint32_t finger_map_index;
3514 uint64_t destination_finger_value;
3516 msize = ntohs (message->size);
3517 if (msize < sizeof (struct PeerTrailRejectionMessage))
3519 GNUNET_break_op (0);
3523 trail_rejection = (struct PeerTrailRejectionMessage *) message;
3524 trail_length = ntohl (trail_rejection->trail_length);
3526 if ((msize < sizeof (struct PeerTrailRejectionMessage) +
3527 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3529 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3531 GNUNET_break_op (0);
3534 trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_rejection[1];
3535 finger_map_index = ntohl (trail_rejection->finger_map_index);
3536 memcpy (&source_peer, &(trail_rejection->source_peer), sizeof(struct GNUNET_PeerIdentity));
3537 memcpy (&destination_finger_value, &(trail_rejection->finger_identity_value), sizeof (uint64_t));
3538 memcpy (&congested_peer, &(trail_rejection->congested_peer), sizeof (struct GNUNET_PeerIdentity));
3540 /* If I am the source of the original trail setup message, then again select
3541 a random friend and send a new trail setup message to this finger identity
3543 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &source_peer)))
3545 /* If friend peer map is empty, or all the friends trail threshold has been crossed,
3547 if ((GNUNET_CONTAINER_multipeermap_size (friend_peermap) == 0) ||
3548 (all_friends_trail_threshold == GNUNET_YES))
3551 return GNUNET_SYSERR;
3554 /* Select any random friend except congested peer. */
3555 target_friend = select_random_friend (&congested_peer);
3557 if (NULL == target_friend)
3559 all_friends_trail_threshold = GNUNET_YES;
3560 return GNUNET_SYSERR;
3563 GDS_NEIGHBOURS_send_trail_setup (&my_identity, destination_finger_value, &(target_friend->id),
3564 &my_identity, target_friend, 0, NULL, finger_map_index);
3568 /* My routing state size has crossed the threshold, I can not be part of any more
3570 if(GDS_ROUTING_check_threshold())
3572 struct GNUNET_PeerIdentity *new_trail;
3574 if (trail_length == 1)
3576 memcpy (&next_peer, &source_peer, sizeof (struct GNUNET_PeerIdentity));
3580 memcpy (&next_peer, &trail_peer_list[trail_length - 2], sizeof (struct GNUNET_PeerIdentity));
3583 /* Remove myself from the trail. */
3584 new_trail = GNUNET_malloc ((trail_length -1) * sizeof (struct GNUNET_PeerIdentity));
3585 memcpy (new_trail, trail_peer_list, (trail_length -1) * sizeof (struct GNUNET_PeerIdentity));
3587 /* No more trails possible through me. send a trail rejection message to next hop. */
3588 GDS_NEIGHBOURS_send_trail_rejection (&source_peer, destination_finger_value, &my_identity,
3589 &next_peer,finger_map_index, new_trail,trail_length - 1);
3593 /* FIXME: In this case I have just written my_identity as current_destination
3594 and current source need ot think more of better values anad if needed or not.
3595 Also, i am adding a new parameter to funciton find_successor so that this peer
3596 is not considered as next hop congested_peer is not being used. FIXME. */
3597 memcpy (¤t_destination, &my_identity, sizeof (struct GNUNET_PeerIdentity));
3598 memcpy (¤t_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
3599 next_hop = find_successor (destination_finger_value, ¤t_destination, ¤t_source, &congested_peer);
3601 /* FIXME: WE NEED ANOTHER CASE as it may happend that congested peer is the only
3602 friend, and find_successor finds nothig, so check something else
3603 here like if current_destination is me, it means that i am destination
3604 or if current_destination = NULL, then it means found nothing. URGENT. */
3605 if (NULL == next_hop) /* This means I am the final destination */
3607 /* SUPU: trail length is 1, when I am the friend of the srouce peer. */
3608 if (trail_length == 1)
3610 memcpy (&next_peer, &source_peer, sizeof (struct GNUNET_PeerIdentity));
3614 memcpy (&next_peer, &trail_peer_list[trail_length-1], sizeof (struct GNUNET_PeerIdentity));
3617 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer);
3618 compare_and_update_predecessor (&source_peer, trail_peer_list, trail_length);
3620 GDS_NEIGHBOURS_send_trail_setup_result (&source_peer,
3622 target_friend, trail_length,
3629 /* Now add yourself to the trail. */
3630 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
3631 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
3632 peer_list[trail_length] = my_identity;
3635 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3636 GDS_NEIGHBOURS_send_trail_setup (&source_peer,
3637 destination_finger_value,
3638 ¤t_destination, ¤t_source,
3639 target_friend, trail_length, peer_list,
3643 return GNUNET_SYSERR;
3648 * Core handle for p2p trail tear down messages.
3649 * @param cls closure
3650 * @param message message
3651 * @param peer peer identity this notification is about
3652 * @return GNUNET_OK on success, GNUNET_SYSERR on error
3655 int handle_dht_p2p_trail_treadown (void *cls, const struct GNUNET_PeerIdentity *peer,
3656 const struct GNUNET_MessageHeader *message)
3658 /* Call is made to this function when the source peer removes an existing
3659 finger entry and it need to inform the peers which are part of the trail to remove
3660 the trail from their routing table. So, this peer should first
3661 get the next hop and then delete the entry. */
3662 struct PeerTrailTearDownMessage *trail_teardown;
3663 struct GNUNET_PeerIdentity *trail_peer_list;
3664 struct GNUNET_PeerIdentity next_hop;
3665 struct FriendInfo *target_friend;
3666 uint32_t trail_length;
3670 msize = ntohs (message->size);
3671 if (msize < sizeof (struct PeerTrailTearDownMessage))
3673 GNUNET_break_op (0);
3677 trail_teardown = (struct PeerTrailTearDownMessage *) message;
3678 trail_length = ntohl (trail_teardown->trail_length);
3680 if ((msize < sizeof (struct PeerTrailTearDownMessage) +
3681 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3683 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3685 GNUNET_break_op (0);
3689 trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_teardown[1];
3691 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_teardown->destination_peer), &my_identity)))
3693 /* We have reached destination then just return. May be if the peer before this
3694 destination, does not forward the packet to destination. So, this case should never
3700 my_index = search_my_index (trail_peer_list, trail_length);
3701 if (GNUNET_NO == GDS_ROUTING_remove_trail (&(trail_teardown->source_peer),
3702 &(trail_teardown->destination_peer),peer))
3704 /* Here we get GNUNET_NO, only if there is no matching entry found in routing
3710 if (my_index == (trail_length - 2))
3711 return GNUNET_SYSERR;
3713 memcpy (&next_hop, &trail_peer_list[my_index + 1], sizeof (struct GNUNET_PeerIdentity));
3714 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
3716 GDS_NEIGHBOURS_send_trail_teardown (&(trail_teardown->source_peer),
3717 &(trail_teardown->destination_peer),
3718 trail_peer_list, trail_length, target_friend);
3723 * Iterate over finger_peermap, and remove entries with peer as the first element
3725 * @param cls closure
3726 * @param key current public key
3727 * @param value value in the hash map
3728 * @return #GNUNET_YES if we should continue to
3730 * #GNUNET_NO if not.
3733 remove_matching_finger (void *cls,
3734 const struct GNUNET_PeerIdentity *key,
3737 struct FingerInfo *remove_finger = value;
3738 const struct GNUNET_PeerIdentity *disconnected_peer = cls;
3740 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&remove_finger->first_trail_head->peer, disconnected_peer))
3742 GNUNET_assert (GNUNET_YES ==
3743 GNUNET_CONTAINER_multipeermap_remove (finger_peermap,
3746 free_finger (remove_finger);
3753 * Method called whenever a peer disconnects.
3755 * @param cls closure
3756 * @param peer peer identity this notification is about
3759 handle_core_disconnect (void *cls,
3760 const struct GNUNET_PeerIdentity *peer)
3762 struct FriendInfo *remove_friend;
3764 /* Check for self message. */
3765 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
3768 /* Search for peer to remove in your friend_peermap. */
3770 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
3772 if (NULL == remove_friend)
3778 /* Remove fingers for which this peer is the first element in the trail. */
3779 GNUNET_CONTAINER_multipeermap_iterate (finger_peermap,
3780 &remove_matching_finger, (void *)peer);
3782 /* Remove routing trails of which this peer is a part. */
3783 GDS_ROUTING_remove_entry (peer);
3785 /* Remove the peer from friend_peermap. */
3786 GNUNET_assert (GNUNET_YES ==
3787 GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
3791 if (0 != GNUNET_CONTAINER_multipeermap_size (friend_peermap))
3794 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
3796 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
3797 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
3802 if (GNUNET_SCHEDULER_NO_TASK != verify_successor)
3804 GNUNET_SCHEDULER_cancel (verify_successor);
3805 verify_successor = GNUNET_SCHEDULER_NO_TASK;
3811 * Method called whenever a peer connects.
3813 * @param cls closure
3814 * @param peer_identity peer identity this notification is about
3817 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity)
3819 struct FriendInfo *friend;
3821 /* Check for connect to self message */
3822 if (0 == memcmp (&my_identity, peer_identity, sizeof (struct GNUNET_PeerIdentity)))
3825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to %s\n", GNUNET_i2s (peer_identity));
3827 /* If peer already exists in our friend_peermap, then exit. */
3828 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (friend_peermap, peer_identity))
3834 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
3837 friend = GNUNET_new (struct FriendInfo);
3838 friend->id = *peer_identity;
3839 friend->trails_count = 0;
3841 GNUNET_assert (GNUNET_OK ==
3842 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
3843 peer_identity, friend,
3844 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
3846 /* got a first connection, good time to start with FIND FINGER TRAIL requests... */
3847 if (GNUNET_SCHEDULER_NO_TASK == find_finger_trail_task)
3848 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
3853 * To be called on core init/fail.
3855 * @param cls service closure
3856 * @param identity the public identity of this peer
3859 core_init (void *cls,
3860 const struct GNUNET_PeerIdentity *identity)
3862 my_identity = *identity;
3867 * Initialize neighbours subsystem.
3868 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
3871 GDS_NEIGHBOURS_init (void)
3873 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
3874 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0},
3875 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0},
3876 {&handle_dht_p2p_get_result, GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT, 0},
3877 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP, 0},
3878 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT, 0},
3879 {&handle_dht_p2p_verify_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR, 0},
3880 {&handle_dht_p2p_verify_successor_result, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT, 0},
3881 {&handle_dht_p2p_notify_new_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR, 0},
3882 {&handle_dht_p2p_trail_rejection, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION, 0},
3883 {&handle_dht_p2p_trail_treadown, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_TEARDOWN, 0},
3888 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
3889 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
3890 GNUNET_NO, core_handlers);
3891 if (NULL == core_api)
3892 return GNUNET_SYSERR;
3894 friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
3895 finger_peermap = GNUNET_CONTAINER_multipeermap_create (MAX_FINGERS * 4/3, GNUNET_NO);
3897 all_friends_trail_threshold = GNUNET_NO;
3904 * Shutdown neighbours subsystem.
3907 GDS_NEIGHBOURS_done (void)
3909 if (NULL == core_api)
3912 GNUNET_CORE_disconnect (core_api);
3915 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
3916 GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
3917 friend_peermap = NULL;
3919 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (finger_peermap));
3920 GNUNET_CONTAINER_multipeermap_destroy (finger_peermap);
3921 finger_peermap = NULL;
3923 /* FIXME: Here I have added GNUNET_break(0) as ideally if friend_peermap
3924 is already zero, then we really don't need to cancel it again. If this
3925 condition happens it mean we might have missed some corner case. */
3926 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
3929 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
3930 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
3933 if (GNUNET_SCHEDULER_NO_TASK != verify_successor)
3936 GNUNET_SCHEDULER_cancel (verify_successor);
3937 verify_successor = GNUNET_SCHEDULER_NO_TASK;
3943 * FIXME: Here I want to send only the value not the address. Initially
3944 * I wanted to make it const struct * so that no other function can change it.
3945 * then in client file, i make a copy and send that copy. now I have made this
3949 * @return my identity
3951 struct GNUNET_PeerIdentity
3952 GDS_NEIGHBOURS_get_my_id (void)
3958 /* end of gnunet-service-xdht_neighbours.c */