2 This file is part of GNUnet.
3 (C) 2009-2013 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_nse_service.h"
34 #include "gnunet_ats_service.h"
35 #include "gnunet_core_service.h"
36 #include "gnunet_datacache_lib.h"
37 #include "gnunet_transport_service.h"
38 #include "gnunet_hello_lib.h"
39 #include "gnunet_dht_service.h"
40 #include "gnunet_statistics_service.h"
41 #include "gnunet-service-xdht.h"
42 #include "gnunet-service-xdht_clients.h"
43 #include "gnunet-service-xdht_datacache.h"
44 #include "gnunet-service-xdht_hello.h"
45 #include "gnunet-service-xdht_neighbours.h"
46 #include "gnunet-service-xdht_nse.h"
47 #include "gnunet-service-xdht_routing.h"
52 * 1. when should we use const struct and replace wherever needed.
53 * 2. use assert for each function where you need to check the return value.
54 1. Use a global array of all known peers in find_successor, Only when
55 a new peer is added in finger or friend peer map, then re calculate
56 the array. Or else use the old one.
57 2. Should we be using const in all the handle for the message we received
58 * and then copy the fields and make changes to the fields instead of sending
60 * 3. Everywhere you are storing yourself as the first element in the trail.
61 * It is obviously taking too much space. Try to remove it and think of something
63 4. Choose the correct interval to send finger and verify message.
64 5. Do we need expiration time for trail setup and all other messages? TTL
65 6. In case of trail setup after TTL, we should again send the request but
66 * through a different route. How do we remeber each time which friend we
67 * chose last time for the trail setup. We will need a data structure where we
68 * add entry in finger table add and when setup is done remove it.
69 * 7. I have not added any authentication on messages exachanged between peers.
70 * Only when basic put/get is correct I will add it. */
73 * Maximum possible fingers of a peer.
75 #define MAX_FINGERS 64
78 * Maximum allowed number of pending messages per friend peer.
80 #define MAXIMUM_PENDING_PER_FRIEND 64
83 * How long at least to wait before sending another find finger trail request.
85 #define DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
88 * How long at most to wait before sending another find finger trail request.
90 #define DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 10)
93 * How long at most to wait for transmission of a GET request to another peer?
95 #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
98 * Maximum number of trails allowed to go through a friend.
100 #define LINK_THRESHOLD 64
103 GNUNET_NETWORK_STRUCT_BEGIN
108 struct PeerPutMessage
111 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
113 struct GNUNET_MessageHeader header;
118 uint32_t options GNUNET_PACKED;
123 uint32_t block_type GNUNET_PACKED;
128 uint32_t hop_count GNUNET_PACKED;
131 * Replication level for this message
133 uint32_t desired_replication_level GNUNET_PACKED;
136 * Length of the PUT path that follows (if tracked).
138 uint32_t put_path_length GNUNET_PACKED;
141 * Current destination to which this message is forwarded.
143 struct GNUNET_PeerIdentity current_destination;
146 * Peer whose finger is current_destination.
148 struct GNUNET_PeerIdentity current_source;
151 * current_destination type.
153 enum current_destination_type current_destination_type;
156 * When does the content expire?
158 struct GNUNET_TIME_AbsoluteNBO expiration_time;
161 * The key to store the value under.
163 struct GNUNET_HashCode key GNUNET_PACKED;
166 /* put path (if tracked) */
176 struct PeerGetResultMessage
179 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT
181 struct GNUNET_MessageHeader header;
184 * The type for the data.
186 uint32_t type GNUNET_PACKED;
189 * Peer which is sending get result message.
191 struct GNUNET_PeerIdentity source_peer;
194 * Peer which will receive the get result message.
196 struct GNUNET_PeerIdentity destination_peer;
199 * Current index in get path.
201 unsigned int current_path_index;
203 * Number of peers recorded in the outgoing path from source to the
204 * storgage location of this message.
206 uint32_t put_path_length GNUNET_PACKED;
209 * When does this entry expire?
211 struct GNUNET_TIME_AbsoluteNBO expiration;
214 * Length of the GET path that follows (if tracked).
216 uint32_t get_path_length GNUNET_PACKED;
219 * When does the content expire?
221 struct GNUNET_TIME_AbsoluteNBO expiration_time;
224 * The key of the corresponding GET request.
226 struct GNUNET_HashCode key;
228 /* put path (if tracked) */
230 /* get path (if tracked) */
240 struct PeerGetMessage
243 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET
245 struct GNUNET_MessageHeader header;
250 uint32_t options GNUNET_PACKED;
253 * Desired content type.
255 uint32_t block_type GNUNET_PACKED;
260 uint32_t hop_count GNUNET_PACKED;
263 * Desired replication level for this request.
265 uint32_t desired_replication_level GNUNET_PACKED;
268 * Total number of peers in get path.
270 unsigned int get_path_length;
273 * Peer which is an intermediate destination.
275 struct GNUNET_PeerIdentity current_destination;
278 * Source for which current_destination is the finger.
280 struct GNUNET_PeerIdentity current_source;
283 * Type of current destination
285 enum current_destination_type current_dest_type;
288 * The key we are looking for.
290 struct GNUNET_HashCode key;
298 * P2P Trail setup message
300 struct PeerTrailSetupMessage
304 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP
306 struct GNUNET_MessageHeader header;
309 * Source peer which wants to setup the trail to one of its finger.
311 struct GNUNET_PeerIdentity source_peer;
314 * Successor of this finger value will be our finger peer.
316 uint64_t destination_finger;
319 * Peer which gets this message can be either an intermediate finger or friend.
321 enum current_destination_type current_destination_type;
324 * Peer to which this packet is forwarded.
326 struct GNUNET_PeerIdentity current_destination;
329 * In case the packet is forwarded to an intermediate finger, then
330 * current_source contains the peer id whose finger is the intermediate
331 * finger. In case the packet is forwarded to a friend, then it is NULL.
333 struct GNUNET_PeerIdentity current_source;
336 * Index into finger peer map.
338 unsigned int finger_map_index;
341 * Number of entries in trail list.
343 uint32_t trail_length GNUNET_PACKED;
349 * P2P Trail Setup Result message
351 struct PeerTrailSetupResultMessage
355 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT
357 struct GNUNET_MessageHeader header;
360 * Finger to which we have found the path.
362 struct GNUNET_PeerIdentity finger_identity;
365 * Peer which was looking for the trail to finger.
367 struct GNUNET_PeerIdentity destination_peer;
370 * Trail index which points to next destination to send this message.
372 unsigned int current_index;
375 * Index into finger peer map
377 unsigned int finger_map_index;
380 * Number of entries in trail list.
382 uint32_t trail_length GNUNET_PACKED;
389 struct PeerTrailRejectionMessage
392 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION
394 struct GNUNET_MessageHeader header;
397 * Source peer which wants to set up the trail.
399 struct GNUNET_PeerIdentity source_peer;
402 * Finger identity value.
404 uint64_t finger_identity;
407 * Peer which sent trail rejection message.
409 struct GNUNET_PeerIdentity congested_peer;
412 * Index in finger peer map of source peer.
414 unsigned int finger_map_index;
417 * Total number of peers in the trail.
419 unsigned int trail_length;
426 * P2P Verify Successor message.
428 struct PeerVerifySuccessorMessage
432 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR
434 struct GNUNET_MessageHeader header;
437 * Source peer which wants to verify its successor.
439 struct GNUNET_PeerIdentity source_peer;
442 * My current successor.
444 struct GNUNET_PeerIdentity successor;
447 * Total number of peers in trail to current successor.
449 unsigned int trail_length;
452 * Trail index which points to next destination to send this message.
454 unsigned int current_trail_index;
460 * P2P Verify Successor Result message.
462 struct PeerVerifySuccessorResultMessage
466 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT
468 struct GNUNET_MessageHeader header;
471 * Destination peer which sent the request to verify its successor.
473 struct GNUNET_PeerIdentity destination_peer;
476 * Successor to which PeerVerifySuccessorMessage was sent.
478 struct GNUNET_PeerIdentity source_successor;
481 * source_successor's predecessor
483 struct GNUNET_PeerIdentity my_predecessor;
486 * Total number of peers in trail.
487 * If source_successor is not destination peer, then trail is from destination_peer
489 * If source_successor is destination peer, then trail is from destination_peer
490 * to source_successor.
492 unsigned int trail_length;
495 * Trail index which points to next destination to send this message.
497 unsigned int current_index;
502 * P2P Notify New Successor message.
504 struct PeerNotifyNewSuccessorMessage
507 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR
509 struct GNUNET_MessageHeader header;
512 * Source peer which wants to notify its new successor.
514 struct GNUNET_PeerIdentity source_peer;
517 * New successor identity.
519 struct GNUNET_PeerIdentity destination_peer;
522 * Number of peers in trail from source_peer to new successor.
524 unsigned int trail_length;
527 * Trail index which points to next destination to send this message.
529 unsigned int current_index;
534 GNUNET_NETWORK_STRUCT_END
538 * Linked list of messages to send to a particular other peer.
540 struct P2PPendingMessage
543 * Pointer to next item in the list
545 struct P2PPendingMessage *next;
548 * Pointer to previous item in the list
550 struct P2PPendingMessage *prev;
553 * When does this message time out?
555 struct GNUNET_TIME_Absolute timeout;
558 * Message importance level. FIXME: used? useful?
560 unsigned int importance;
563 * Actual message to be sent, allocated at the end of the struct:
564 * // msg = (cast) &pm[1];
565 * // memcpy (&pm[1], data, len);
567 const struct GNUNET_MessageHeader *msg;
573 * Linked List of peers which are part of trail to reach a particular Finger.
578 * Pointer to next item in the list
580 struct TrailPeerList *next;
583 * Pointer to previous item in the list
585 struct TrailPeerList *prev;
588 * An element in this trail list
590 struct GNUNET_PeerIdentity peer;
596 * Entry in friend_peermap.
603 struct GNUNET_PeerIdentity id;
606 * Number of trail of which this friend is the first hop.
608 unsigned int trail_links;
611 * Count of outstanding messages for this friend.
613 unsigned int pending_count;
616 * Head of pending messages to be sent to this friend.
618 struct P2PPendingMessage *head;
621 * Tail of pending messages to be sent to this friend.
623 struct P2PPendingMessage *tail;
626 * Core handle for sending messages to this friend.
628 struct GNUNET_CORE_TransmitHandle *th;
634 * Entry in finger_peermap.
641 struct GNUNET_PeerIdentity finger_identity;
644 * Index in finger peer map
646 unsigned int finger_map_index;
649 * Total number of entries in trail from (me,finger]
651 unsigned int trail_length;
654 * Head of trail to reach this finger.
656 struct TrailPeerList *head;
659 * Tail of trail to reach this finger.
661 struct TrailPeerList *tail;
667 * FIXME: Think of a better name.
668 * Data structure passed to sorting algorithm in find_successor.
673 * 64 bit value of peer identity
678 * Type : MY_ID, FINGER, FINGER, Value
680 enum current_destination_type type;
683 * Pointer to original data structure linked to peer id.
690 * FIXME: Think of better comments.
691 * An entry in Failed_Trail_List
696 * Source peer which was trying to setup up the trail to @a destination_finger_value
698 struct GNUNET_PeerIdentity source_peer;
701 * Value to which we were trying to find the closest successor.
703 uint64_t destination_finger_value;
706 * Peer which has crossed the threshold limit on its routing table size.
708 struct GNUNET_PeerIdentity congested_peer;
714 * Task that sends FIND FINGER TRAIL requests.
716 static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task;
720 * Task that periodically verifies my successor.
722 static GNUNET_SCHEDULER_TaskIdentifier verify_successor;
725 * Identity of this peer.
727 static struct GNUNET_PeerIdentity my_identity;
730 * Hash map of all the friends of a peer
732 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap;
735 * Hash map of all the fingers of a peer
737 static struct GNUNET_CONTAINER_MultiPeerMap *finger_peermap;
740 * Hash maps of all the trail which failed due to a congested peer.
742 static struct GNUNET_CONTAINER_MultiPeerMap *failed_trail_list;
747 static struct GNUNET_CORE_Handle *core_api;
750 * FIXME: Is it safe to assume its initialized to 0 by default.
751 * The current finger index that we have found trail to.
753 static unsigned int current_finger_index;
757 * Called when core is ready to send a message we asked for
758 * out to the destination.
760 * @param cls the 'struct FriendInfo' of the target friend
761 * @param size number of bytes available in buf
762 * @param buf where the callee should write the message
763 * @return number of bytes written to buf
766 core_transmit_notify (void *cls, size_t size, void *buf)
768 struct FriendInfo *peer = cls;
770 struct P2PPendingMessage *pending;
775 while ((NULL != (pending = peer->head)) &&
776 (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us))
778 peer->pending_count--;
779 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
780 GNUNET_free (pending);
784 /* no messages pending */
790 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
791 GNUNET_CORE_PRIO_BEST_EFFORT,
792 GNUNET_TIME_absolute_get_remaining
793 (pending->timeout), &peer->id,
794 ntohs (pending->msg->size),
795 &core_transmit_notify, peer);
796 GNUNET_break (NULL != peer->th);
800 while ((NULL != (pending = peer->head)) &&
801 (size - off >= (msize = ntohs (pending->msg->size))))
803 GNUNET_STATISTICS_update (GDS_stats,
805 ("# Bytes transmitted to other peers"), msize,
807 memcpy (&cbuf[off], pending->msg, msize);
809 peer->pending_count--;
810 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
811 GNUNET_free (pending);
813 if (peer->head != NULL)
816 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
817 GNUNET_CORE_PRIO_BEST_EFFORT,
818 GNUNET_TIME_absolute_get_remaining
819 (pending->timeout), &peer->id, msize,
820 &core_transmit_notify, peer);
821 GNUNET_break (NULL != peer->th);
828 * Transmit all messages in the friend's message queue.
830 * @param peer message queue to process
833 process_friend_queue (struct FriendInfo *peer)
835 struct P2PPendingMessage *pending;
837 if (NULL == (pending = peer->head))
839 if (NULL != peer->th)
842 GNUNET_STATISTICS_update (GDS_stats,
844 ("# Bytes of bandwidth requested from core"),
845 ntohs (pending->msg->size), GNUNET_NO);
847 /* FIXME: Are we correctly initializing importance and pending. */
849 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
851 GNUNET_TIME_absolute_get_remaining
852 (pending->timeout), &peer->id,
853 ntohs (pending->msg->size),
854 &core_transmit_notify, peer);
855 GNUNET_break (NULL != peer->th);
859 /**FIXME: add better comment for current_source which shows its relation
860 * with current_destination.
861 * Construct a trail message and forward it to a friend.
862 * @param source_peer Peer which wants to set up the trail to one of its finger.
863 * @param destination_finger Value whose successor we are searching the network.
864 * @param current_destination Peer which gets this message.
865 * @param current_source Peer for which current_destination is its finger.
866 * @param target_friend Current friend to which this message should be forwarded.
867 * @param trail_length Numbers of peers in the trail.
868 * @param trail_peer_list peers this request has traversed so far
869 * @param finger_map_index Index in finger peer map
870 * @param type Type of current destination can be either FRIEND or FINGER
873 GDS_NEIGHBOURS_send_trail_setup (struct GNUNET_PeerIdentity *source_peer,
874 uint64_t destination_finger,
875 struct GNUNET_PeerIdentity *current_destination,
876 struct GNUNET_PeerIdentity *current_source,
877 struct FriendInfo *target_friend,
878 unsigned int trail_length,
879 struct GNUNET_PeerIdentity *trail_peer_list,
880 unsigned int finger_map_index,
881 enum current_destination_type type)
883 struct P2PPendingMessage *pending;
884 struct PeerTrailSetupMessage *tsm;
885 struct GNUNET_PeerIdentity *peer_list;
888 msize = sizeof (struct PeerTrailSetupMessage) +
889 (trail_length * sizeof (struct GNUNET_PeerIdentity));
891 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
897 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
899 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
903 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
904 pending->importance = 0; /* FIXME */
905 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
906 tsm = (struct PeerTrailSetupMessage *) &pending[1];
907 pending->msg = &tsm->header;
908 tsm->header.size = htons (msize);
909 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
910 memcpy (&(tsm->destination_finger), &destination_finger, sizeof (uint64_t));
911 memcpy (&(tsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
912 memcpy (&(tsm->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity));
913 /* FIXME: Is it correct to use NULL here for comparison? */
914 if (current_source != NULL)
915 memcpy (&(tsm->current_source), current_source, sizeof (struct GNUNET_PeerIdentity));
916 tsm->current_destination_type = htonl (type);
917 tsm->trail_length = htonl (trail_length);
918 tsm->finger_map_index = htonl (finger_map_index);
920 if (trail_peer_list != NULL)
922 peer_list = (struct GNUNET_PeerIdentity *) &tsm[1];
923 memcpy (peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
926 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
927 target_friend->pending_count++;
928 process_friend_queue (target_friend);
934 * Construct a trail setup result message and forward it to a friend.
935 * @param destination_peer Peer which will get the trail to one of its finger.
936 * @param source_finger Peer to which the trail has been setup to.
937 * @param target_friend Friend to which this message should be forwarded.
938 * @param trail_length Numbers of peers in the trail.
939 * @param trail_peer_list Peers which are part of the trail from source to destination.
940 * @param current_trail_index Index at which sender of this message is located.
941 * @param finger_map_index Index in finger peer map
944 GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity *destination_peer,
945 struct GNUNET_PeerIdentity *source_finger,
946 struct FriendInfo *target_friend,
947 unsigned int trail_length,
948 struct GNUNET_PeerIdentity *trail_peer_list,
949 unsigned int current_trail_index,
950 unsigned int finger_map_index)
952 struct P2PPendingMessage *pending;
953 struct PeerTrailSetupResultMessage *tsrm;
954 struct GNUNET_PeerIdentity *peer_list;
957 msize = sizeof (struct PeerTrailSetupResultMessage) +
958 (trail_length * sizeof (struct GNUNET_PeerIdentity));
960 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
966 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
968 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
972 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
973 pending->importance = 0;
974 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
975 tsrm = (struct PeerTrailSetupResultMessage *) &pending[1];
976 pending->msg = &tsrm->header;
977 tsrm->header.size = htons (msize);
978 tsrm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT);
979 memcpy (&(tsrm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
980 memcpy (&(tsrm->finger_identity), source_finger, sizeof (struct GNUNET_PeerIdentity));
981 tsrm->trail_length = htonl (trail_length);
982 tsrm->current_index = htonl (current_trail_index);
983 tsrm->finger_map_index = htonl (finger_map_index);
984 peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1];
985 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
987 /* Send the message to chosen friend. */
988 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
989 target_friend->pending_count++;
990 process_friend_queue (target_friend);
995 * Construct a PeerVerifySuccessor message and send it to friend.
996 * @param source_peer Peer which wants to verify its successor
997 * @param successor Peer which is our current successor
998 * @param target_friend Friend to which this message should be forwarded.
999 * @param trail_peer_list Peer which are part of trail from source to destination
1000 * @param trail_length Number of peers in the trail list.
1001 * @param current_trail_index Index in the trial list at which receiving peer should
1002 * read the next element.
1004 void GDS_NEIGHBOURS_send_verify_successor(struct GNUNET_PeerIdentity *source_peer,
1005 struct GNUNET_PeerIdentity *successor,
1006 struct FriendInfo *target_friend,
1007 struct GNUNET_PeerIdentity *trail_peer_list,
1008 unsigned int trail_length,
1009 unsigned int current_trail_index)
1011 struct PeerVerifySuccessorMessage *vsm;
1012 struct P2PPendingMessage *pending;
1013 struct GNUNET_PeerIdentity *peer_list;
1016 msize = sizeof (struct PeerVerifySuccessorMessage) +
1017 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1019 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1025 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1027 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1031 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1032 pending->importance = 0; /* FIXME */
1033 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1034 vsm = (struct PeerVerifySuccessorMessage *) &pending[1];
1035 pending->msg = &vsm->header;
1036 vsm->header.size = htons (msize);
1037 vsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR);
1038 memcpy (&(vsm->successor), successor, sizeof (struct GNUNET_PeerIdentity));
1039 memcpy (&(vsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1040 vsm->trail_length = htonl (trail_length);
1041 vsm->current_trail_index = htonl (current_trail_index);
1042 peer_list = (struct GNUNET_PeerIdentity *) &vsm[1];
1043 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1045 /* Send the message to chosen friend. */
1046 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1047 target_friend->pending_count++;
1048 process_friend_queue (target_friend);
1054 * Construct a PeerVerifySuccessorResult message and send it to friend.
1055 * @param destination_peer Peer which sent verify successor message
1056 * @param source_successor Peer to which verify successor message was sent.
1057 * @param my_predecessor source_successor's predecessor.
1058 * @param target_friend Friend to which this message should be forwarded.
1059 * @param trail_peer_list Peers which are part of trail from source to destination
1060 * @param trail_length Number of peers in the trail list.
1061 * @param current_trail_index Index in the trial list at which receiving peer should
1062 * get the next element.
1064 void GDS_NEIGHBOURS_send_verify_successor_result (struct GNUNET_PeerIdentity *destination_peer,
1065 struct GNUNET_PeerIdentity *source_successor,
1066 struct GNUNET_PeerIdentity *my_predecessor,
1067 struct FriendInfo *target_friend,
1068 struct GNUNET_PeerIdentity *trail_peer_list,
1069 unsigned int trail_length,
1070 unsigned int current_trail_index)
1072 struct PeerVerifySuccessorResultMessage *vsmr;
1073 struct P2PPendingMessage *pending;
1074 struct GNUNET_PeerIdentity *peer_list;
1077 msize = sizeof (struct PeerVerifySuccessorResultMessage) +
1078 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1080 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1087 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1089 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1093 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1094 pending->importance = 0; /* FIXME */
1095 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1096 vsmr = (struct PeerVerifySuccessorResultMessage *) &pending[1];
1097 pending->msg = &vsmr->header;
1098 vsmr->header.size = htons (msize);
1099 vsmr->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT);
1100 memcpy (&(vsmr->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1101 memcpy (&(vsmr->source_successor), source_successor, sizeof (struct GNUNET_PeerIdentity));
1102 memcpy (&(vsmr->my_predecessor), my_predecessor, sizeof (struct GNUNET_PeerIdentity));
1103 vsmr->trail_length = htonl (trail_length);
1104 vsmr->current_index = htonl (current_trail_index);
1106 peer_list = (struct GNUNET_PeerIdentity *) &vsmr[1];
1107 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1109 /* Send the message to chosen friend. */
1110 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1111 target_friend->pending_count++;
1112 process_friend_queue (target_friend);
1117 * Construct a PeerNotifyNewSuccessor message and send it to friend.
1118 * @param source_peer Peer which is sending notify message to its new successor.
1119 * @param destination_peer Peer which is the new destination.
1120 * @param target_friend Next friend to pass this message to.
1121 * @param peer_list List of peers in the trail to reach to destination_peer.
1122 * @param current_trail_index Index of peer_list for next target friend position.
1123 * @param trail_length Total number of peers in peer list
1126 GDS_NEIGHBOURS_send_notify_new_successor (struct GNUNET_PeerIdentity *source_peer,
1127 struct GNUNET_PeerIdentity *destination_peer,
1128 struct FriendInfo *target_friend,
1129 struct GNUNET_PeerIdentity *trail_peer_list,
1130 unsigned int trail_length,
1131 unsigned int current_trail_index)
1133 struct PeerNotifyNewSuccessorMessage *nsm;
1134 struct P2PPendingMessage *pending;
1135 struct GNUNET_PeerIdentity *peer_list;
1138 msize = sizeof (struct PeerNotifyNewSuccessorMessage) +
1139 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1141 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1147 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1149 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1153 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1154 pending->importance = 0; /* FIXME */
1155 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1156 nsm = (struct PeerNotifyNewSuccessorMessage *) &pending[1];
1157 pending->msg = &nsm->header;
1158 nsm->header.size = htons (msize);
1159 nsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR);
1160 memcpy (&(nsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1161 memcpy (&(nsm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1162 nsm->trail_length = htonl (trail_length);
1163 nsm->current_index = htonl (current_trail_index);
1165 peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
1166 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1168 /* Send the message to chosen friend. */
1169 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1170 target_friend->pending_count++;
1171 process_friend_queue (target_friend);
1176 * FIXME: Optimizaiton Once the basic code is running. Add the optimization
1177 * where you check if the threshold on number of links that should go through
1178 * a particular friend has crossed. If yes then again choose a different
1179 * friend. Important that the new friend chosen should be different. How to
1180 * ensure this? This is an important optimization as without this one x-vine
1181 * is actually not a sybil tolerant DHT.
1182 * Randomly choose one of your friends from the friends_peer map
1185 static struct FriendInfo *
1186 select_random_friend (struct GNUNET_PeerIdentity *congested_peer)
1188 unsigned int current_size;
1189 unsigned int *index;
1191 struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
1192 struct GNUNET_PeerIdentity key_ret;
1193 struct FriendInfo *friend;
1195 current_size = GNUNET_CONTAINER_multipeermap_size (friend_peermap);
1196 index = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, current_size);
1197 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1201 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,NULL,NULL))
1209 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,&key_ret,(const void **)&friend))
1211 /* TODO: Here you have chosen a random friend. Now you should check the size
1212 of its routing table size, and if its more than threshold, then check which
1213 of the entries has trail length greater than trail length threshold. we
1214 should without checking the routing table size also we should check the
1215 trail with trail length greater than threshold. then
1216 you should try to find a new route through this new node that has joined in
1217 only for those finger entries whose trail length is greater than threshold.
1218 But I don't want the new node to wait for this process to get over. so
1219 should i declare a function which will be called after some interval.*/
1228 * Compute finger_identity to which we want to setup the trail
1229 * @return finger_identity
1232 compute_finger_identity()
1235 uint64_t *finger_identity64;
1237 finger_identity64 = GNUNET_malloc (sizeof (uint64_t));
1238 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
1239 /*FIXME: Do we need a mod finger = ((my_id + pow(2, finger_index)) mod (pow (2, MAX_FINGERS))*/
1240 *finger_identity64 = (my_id64 + (unsigned long) pow (2,current_finger_index));
1242 return finger_identity64;
1247 * Compute immediate predecessor identity in the network.
1248 * @return peer identity of immediate predecessor.
1251 compute_predecessor_identity()
1254 uint64_t *predecessor;
1256 predecessor = GNUNET_malloc (sizeof (uint64_t));
1257 memcpy (&my_id, &my_identity, sizeof (uint64_t));
1258 /* FIXME: Do we need to use mod pow(2, MAX_FINGERS) here? */
1259 *predecessor = (my_id -1);
1266 * Periodically ping your successor to ask its current predecessor
1268 * @param cls closure for this task
1269 * @param tc the context under which the task is running
1272 send_verify_successor_message (void *cls,
1273 const struct GNUNET_SCHEDULER_TaskContext *tc )
1275 struct GNUNET_TIME_Relative next_send_time;
1276 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1277 struct GNUNET_PeerIdentity key_ret;
1278 struct FriendInfo *target_friend;
1279 struct GNUNET_PeerIdentity *next_hop;
1280 struct GNUNET_PeerIdentity *peer_list;
1281 unsigned int finger_trail_current_index;
1282 struct FingerInfo *finger;
1283 unsigned int finger_index;
1287 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1288 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
1290 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, &key_ret,
1291 (const void **)&finger))
1293 if (0 == finger->finger_map_index)
1300 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
1303 goto send_new_request;
1305 peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * finger->trail_length);
1307 struct TrailPeerList *iterate;
1308 iterate = finger->head;
1310 while ( i < (finger->trail_length))
1312 memcpy (&peer_list[i], &(iterate->peer), sizeof (struct GNUNET_PeerIdentity));
1313 iterate = iterate->next;
1317 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1318 memcpy (next_hop, &peer_list[0], sizeof (struct GNUNET_PeerIdentity));
1319 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
1320 finger_trail_current_index = 0;
1323 GDS_NEIGHBOURS_send_verify_successor (&my_identity,
1324 &(finger->finger_identity),
1327 finger->trail_length,
1328 finger_trail_current_index);
1331 /* FIXME: Use a random value so that this message is send not at the same
1332 interval as send_find_finger_trail_message. */
1334 next_send_time.rel_value_us =
1335 DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
1336 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1337 DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us /
1338 (current_finger_index + 50));
1341 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_verify_successor_message,
1347 * Task to send a find finger trail message. We attempt to find trail
1348 * to our fingers, successor and predecessor in the network.
1350 * @param cls closure for this task
1351 * @param tc the context under which the task is running
1354 send_find_finger_trail_message (void *cls,
1355 const struct GNUNET_SCHEDULER_TaskContext *tc)
1357 struct FriendInfo *target_friend;
1358 struct GNUNET_TIME_Relative next_send_time;
1359 uint64_t *finger_identity;
1360 unsigned int finger_map_index;
1362 if (1 == current_finger_index)
1364 finger_identity = compute_predecessor_identity();
1369 finger_identity = compute_finger_identity();
1373 target_friend = select_random_friend (NULL);
1375 finger_map_index = current_finger_index;
1376 current_finger_index = ( current_finger_index + 1) % MAX_FINGERS;
1378 if(NULL != target_friend)
1380 /* FIXME: Here I am passing NULL for current source, is it correct?
1381 also, we set the current source only if current_destination_type
1383 GDS_NEIGHBOURS_send_trail_setup (&my_identity, *finger_identity, &(target_friend->id),
1384 NULL, target_friend, 0, NULL, finger_map_index, FRIEND);
1387 /* FIXME: How to decide the correct interval? */
1388 next_send_time.rel_value_us =
1389 DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
1390 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1391 DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us /
1392 (current_finger_index + 10));
1394 find_finger_trail_task =
1395 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_finger_trail_message,
1401 * Method called whenever a peer connects.
1403 * @param cls closure
1404 * @param peer_identity peer identity this notification is about
1407 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity)
1409 struct FriendInfo *friend;
1411 /* Check for connect to self message */
1412 if (0 == memcmp (&my_identity, peer_identity, sizeof (struct GNUNET_PeerIdentity)))
1415 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to %s\n", GNUNET_i2s (peer_identity));
1417 /* If peer already exists in our friend_peermap, then exit. */
1418 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (friend_peermap, peer_identity))
1424 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
1427 friend = GNUNET_new (struct FriendInfo);
1428 friend->id = *peer_identity;
1430 GNUNET_assert (GNUNET_OK ==
1431 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
1432 peer_identity, friend,
1433 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1435 /* got a first connection, good time to start with FIND FINGER TRAIL requests... */
1436 if (1 == GNUNET_CONTAINER_multipeermap_size (friend_peermap))
1437 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
1442 * Method called whenever a peer disconnects.
1444 * @param cls closure
1445 * @param peer peer identity this notification is about
1448 handle_core_disconnect (void *cls,
1449 const struct GNUNET_PeerIdentity *peer)
1451 struct FriendInfo *remove_friend;
1452 struct FingerInfo *remove_finger;
1453 struct GNUNET_PeerIdentity key_ret;
1454 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1455 struct TrailPeerList *iterator;
1456 struct GNUNET_PeerIdentity *finger_identity;
1459 /* Check for self message. */
1460 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
1463 /* Search for peer to remove in your friend_peermap. */
1465 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
1467 if (NULL == remove_friend)
1473 iterator = GNUNET_malloc (sizeof (struct TrailPeerList));
1474 finger_identity = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1475 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1476 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
1478 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, &key_ret,
1479 (const void **)&remove_finger))
1481 iterator = remove_finger->head->next;
1482 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(iterator->peer), &(remove_friend->id)))
1484 memcpy (finger_identity, &(remove_finger->finger_identity), sizeof (struct GNUNET_PeerIdentity));
1485 GNUNET_assert (GNUNET_YES ==
1486 GNUNET_CONTAINER_multipeermap_remove (finger_peermap,
1493 /* Remove the friend from friend_peermap. */
1494 GNUNET_assert (GNUNET_YES ==
1495 GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
1502 * To be called on core init/fail.
1504 * @param cls service closure
1505 * @param identity the public identity of this peer
1508 core_init (void *cls,
1509 const struct GNUNET_PeerIdentity *identity)
1511 my_identity = *identity;
1513 /* SUPU TEST CODE */
1514 struct GNUNET_PeerIdentity *print_peer;
1515 print_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1516 memcpy (print_peer, &my_identity, sizeof (struct GNUNET_PeerIdentity));
1517 FPRINTF (stderr,_("\nSUPU %s, %s, %d,my_identity = %s"),
1518 __FILE__, __func__,__LINE__, GNUNET_i2s (print_peer));
1519 /* SUPU TEST CODE ENDS */
1526 * @param destination_peer
1527 * @param existing_trail
1528 * @param trail_length
1531 static struct GNUNET_PeerIdentity *
1532 invert_trail_list (struct GNUNET_PeerIdentity *destination_peer,
1533 struct GNUNET_PeerIdentity *existing_trail,
1534 unsigned int trail_length)
1538 struct GNUNET_PeerIdentity *new_trail;
1541 new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * trail_length);
1543 if (trail_length > 1)
1545 i = trail_length - 2;
1548 memcpy( &new_trail[j], &existing_trail[i], sizeof (struct GNUNET_PeerIdentity));
1553 memcpy (&new_trail[j], destination_peer, sizeof(struct GNUNET_PeerIdentity));
1561 * @param existing_finger
1566 compare_finger_identity (struct GNUNET_PeerIdentity *existing_finger,
1567 struct GNUNET_PeerIdentity *new_finger)
1570 ret = (existing_finger > new_finger) ? 1 :
1571 (existing_finger == new_finger) ? 0 : -1;
1577 * FIXME: Not sure of the logic to find the correct predecessor
1578 * I think logic of this code is wrong everything else seems to be correct.
1579 * Given two finger identities, find the closest predecessor.
1580 * @param existing_predecessor
1581 * @param new_predecessor
1585 compare_predecessor(struct GNUNET_PeerIdentity *existing_predecessor,
1586 struct GNUNET_PeerIdentity *new_predecessor)
1589 ret = (existing_predecessor < new_predecessor) ? 1 :
1590 (existing_predecessor == new_predecessor) ? 0 : -1;
1597 * Add an entry in finger table.
1598 * @param finger_identity Peer identity of finger
1599 * @param finger_trail Trail to reach the finger
1600 * @param trail_length Number of peers in the trail.
1601 * @param finger_map_index Index in finger peer map.
1604 void finger_table_add (struct GNUNET_PeerIdentity *finger_identity,
1605 struct GNUNET_PeerIdentity *finger_trail,
1606 unsigned int trail_length,
1607 unsigned int finger_map_index)
1609 struct FingerInfo *new_finger_entry;
1610 struct GNUNET_PeerIdentity key_ret;
1612 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1613 struct FingerInfo *existing_finger;
1616 /* SUPU Here we trying to check if we already have an entry. If yes then we
1617 can keep two trails for redundant routing. if they are different then we
1618 need to choose the closest one. and remove the other one. */
1619 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1621 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
1623 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, &key_ret,
1624 (const void **)&existing_finger))
1626 if ((finger_map_index == existing_finger->finger_map_index))
1628 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity),finger_identity))
1630 FPRINTF (stderr,_("\nSUPU Entries are same. %s, %s, %d"), __FILE__, __func__,__LINE__);
1631 /* FIXME: Here you should check if the trail is same. If yes then don't add the entry. it
1632 seems to be very suboptimal. */
1633 if ((existing_finger->trail_length) == trail_length)
1635 struct TrailPeerList *iterate;
1636 iterate = existing_finger->head;
1639 while (k < trail_length)
1641 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(iterate->peer), &finger_trail[k]))
1644 iterate = iterate->next;
1647 if (k == trail_length)
1657 if (finger_map_index == 1)
1659 FPRINTF (stderr,_("\nSUPUP Predecessor are different %s, %s, %d"), __FILE__, __func__,__LINE__);
1660 ret = compare_predecessor (&(existing_finger->finger_identity),
1666 FPRINTF (stderr,_("\nSUPU %s, %s, %d"), __FILE__, __func__,__LINE__);
1667 ret = compare_finger_identity (&(existing_finger->finger_identity),
1672 FPRINTF (stderr,_("\nSUPU Adding the new one and removing the old one %s, %s, %d"), __FILE__, __func__,__LINE__);
1673 GNUNET_assert (GNUNET_YES ==
1674 GNUNET_CONTAINER_multipeermap_remove (finger_peermap,
1675 &(existing_finger->finger_identity),
1681 FPRINTF (stderr,_("\nSUPU Nothing to do return %s, %s, %d"), __FILE__, __func__,__LINE__);
1690 new_finger_entry = GNUNET_malloc (sizeof (struct FingerInfo));
1691 memcpy (&(new_finger_entry->finger_identity), finger_identity, sizeof (struct GNUNET_PeerIdentity));
1692 new_finger_entry->finger_map_index = finger_map_index;
1694 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, finger_identity))
1696 /* I am the finger */
1697 new_finger_entry->trail_length = 0;
1702 while (i < trail_length)
1704 struct TrailPeerList *element;
1705 element = GNUNET_malloc (sizeof (struct TrailPeerList));
1706 element->next = NULL;
1707 element->prev = NULL;
1709 memcpy (&(element->peer), &finger_trail[i], sizeof(struct GNUNET_PeerIdentity));
1710 GNUNET_CONTAINER_DLL_insert_tail(new_finger_entry->head, new_finger_entry->tail, element);
1713 new_finger_entry->trail_length = trail_length;
1716 /* FIXME: Here we are keeping multiple hashmap option so that there are
1717 multiple routes to reach to same finger, redundant routing.
1718 * Also same peers could be our fingers for different finger map index
1719 * Should we handle the case where we have same fingers at the different
1720 * finger index but with different trail to reach. */
1721 GNUNET_assert (GNUNET_OK ==
1722 GNUNET_CONTAINER_multipeermap_put (finger_peermap,
1723 &(new_finger_entry->finger_identity),
1725 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); /* Fixme: change to multiple */
1726 /* SUPU TEST CODE */
1727 /* Here I want to iterate over finger peer map, print its id and the trail
1728 to reach to the finger. */
1730 struct GNUNET_CONTAINER_MultiPeerMapIterator *test_iter;
1731 struct FingerInfo *test_finger;
1732 test_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1733 FPRINTF (stderr,_("\nSUPU #### %s, %s, %d, size = %d####"),__FILE__, __func__,__LINE__,GNUNET_CONTAINER_multipeermap_size (finger_peermap));
1734 for (test_index = 0; test_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); test_index++)
1736 FPRINTF (stderr,_("\nSUPU *********%s, %s, %d, %d entry*********"),__FILE__, __func__,__LINE__,test_index);
1737 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (test_iter, &key_ret,
1738 (const void **)&test_finger))
1740 FPRINTF (stderr,_("\nSUPU %s, %s, %d "),__FILE__, __func__,__LINE__);
1741 struct GNUNET_PeerIdentity *print_peer;
1742 struct TrailPeerList *iterator;
1744 iterator = GNUNET_malloc (sizeof (struct TrailPeerList));
1745 print_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1746 memcpy (print_peer, &(test_finger->finger_identity), sizeof (struct GNUNET_PeerIdentity));
1747 FPRINTF (stderr,_("\nSUPU %s, %s, %d, finger_index = %d"), __FILE__, __func__,__LINE__,test_finger->finger_map_index);
1748 FPRINTF (stderr,_("\nSUPU %s, %s, %d, finger_identity = %s"),
1749 __FILE__, __func__,__LINE__, GNUNET_i2s (print_peer));
1750 iterator = test_finger->head;
1752 while (z < test_finger->trail_length)
1754 memcpy (print_peer, &(iterator->peer), sizeof (struct GNUNET_PeerIdentity));
1755 FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail[%d] = %s"),__FILE__, __func__,__LINE__,z,GNUNET_i2s (print_peer));
1757 iterator = iterator->next;
1761 FPRINTF (stderr,_("\nSUPU End of loop%s, %s, %d"),__FILE__, __func__,__LINE__);
1762 /* SUPU TEST CODE ENDS */
1765 if (1 == GNUNET_CONTAINER_multipeermap_size (finger_peermap)
1766 && (new_finger_entry->finger_map_index!= 1))
1768 verify_successor = GNUNET_SCHEDULER_add_now (&send_verify_successor_message, NULL);
1774 * Compare two peer identities.
1775 * @param p1 Peer identity
1776 * @param p2 Peer identity
1777 * @return 1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2.
1780 compare_peer_id (const void *p1, const void *p2)
1782 struct Sorting_List *p11;
1783 struct Sorting_List *p22;
1785 p11 = GNUNET_malloc (sizeof (struct Sorting_List));
1786 p22 = GNUNET_malloc (sizeof (struct Sorting_List));
1787 p11 = (struct Sorting_List *)p1;
1788 p22 = (struct Sorting_List *)p2;
1789 ret = ( (p11->peer_id) > (p22->peer_id) ) ? 1 :
1790 ( (p11->peer_id) == (p22->peer_id) ) ? 0 : -1;
1796 * Return the successor of value in all_known_peers.
1797 * @param all_known_peers list of all the peers
1798 * @param value value we have to search in the all_known_peers.
1801 static struct Sorting_List *
1802 find_closest_successor(struct Sorting_List *all_known_peers, uint64_t value,
1811 middle = (first + last)/2;
1813 while(first <= last)
1815 if(all_known_peers[middle].peer_id < value)
1819 else if(all_known_peers[middle].peer_id == value)
1821 if(middle == (size -1))
1823 return &all_known_peers[0];
1827 return &all_known_peers[middle+1];
1835 middle = (first + last)/2;
1842 * Find closest successor for the value.
1843 * @param value Value for which we are looking for successor
1844 * @param current_destination NULL if my_identity is successor else finger/friend
1846 * @param type Next destination type
1847 * @return Peer identity of next destination i.e. successor of value.
1849 static struct GNUNET_PeerIdentity *
1850 find_successor (uint64_t value, struct GNUNET_PeerIdentity *current_destination,
1851 enum current_destination_type *type)
1853 struct GNUNET_CONTAINER_MultiPeerMapIterator *friend_iter;
1854 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1855 struct GNUNET_PeerIdentity key_ret;
1856 struct FriendInfo *friend;
1857 struct FingerInfo *finger;
1858 unsigned int finger_index;
1859 unsigned int friend_index;
1860 struct Sorting_List *successor;
1864 /* 2 is added in size for my_identity and value which will part of all_known_peers. */
1865 size = GNUNET_CONTAINER_multipeermap_size (friend_peermap)+
1866 GNUNET_CONTAINER_multipeermap_size (finger_peermap)+
1869 struct Sorting_List all_known_peers[size];
1872 for (k = 0; k < size; k++)
1873 all_known_peers[k].peer_id = 0;
1875 /* Copy your identity at 0th index in all_known_peers. */
1877 memcpy (&(all_known_peers[j].peer_id), &my_identity, sizeof (uint64_t));
1878 all_known_peers[j].type = MY_ID;
1879 all_known_peers[j].data = 0;
1883 all_known_peers[j].peer_id = value;
1884 all_known_peers[j].type = VALUE;
1885 all_known_peers[j].data = 0;
1888 /* Iterate over friend peer map and copy all the elements into array. */
1889 friend_iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1890 for (friend_index = 0; friend_index < GNUNET_CONTAINER_multipeermap_size (friend_peermap); friend_index++)
1892 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(friend_iter,&key_ret,(const void **)&friend))
1894 memcpy (&(all_known_peers[j].peer_id), &(friend->id), sizeof (uint64_t));
1895 all_known_peers[j].type = FRIEND;
1896 all_known_peers[j].data = friend;
1901 /* Iterate over finger map and copy all the entries into all_known_peers array. */
1902 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1903 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
1905 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(finger_iter,&key_ret,(const void **)&finger))
1907 memcpy (&(all_known_peers[j].peer_id), &(finger->finger_identity), sizeof (uint64_t));
1908 all_known_peers[j].type = FINGER;
1909 all_known_peers[j].data = finger;
1914 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
1915 GNUNET_CONTAINER_multipeermap_iterator_destroy (friend_iter);
1917 qsort (&all_known_peers, size, sizeof (struct Sorting_List), &compare_peer_id);
1919 /* search value in all_known_peers array. */
1920 successor = find_closest_successor (all_known_peers, value, size);
1922 if (successor->type == MY_ID)
1927 else if (successor->type == FRIEND)
1930 struct FriendInfo *target_friend;
1931 target_friend = (struct FriendInfo *)successor->data;
1932 memcpy (current_destination, &(target_friend->id), sizeof (struct GNUNET_PeerIdentity));
1933 return current_destination;
1935 else if (successor->type == FINGER)
1938 struct GNUNET_PeerIdentity *next_hop;
1939 struct FingerInfo *finger;
1940 struct TrailPeerList *iterator;
1941 iterator = GNUNET_malloc (sizeof (struct TrailPeerList));
1942 finger = successor->data;
1943 iterator = finger->head;
1944 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1945 memcpy (next_hop, &(iterator->peer), sizeof (struct GNUNET_PeerIdentity));
1946 memcpy (current_destination, &(finger->finger_identity), sizeof (struct GNUNET_PeerIdentity));
1958 * Send a get message to selected target friend. If target friend in NULL,
1959 * then search for a target friend.
1960 * @param block_type type of the block
1961 * @param options routing options
1962 * @param desired_replication_level desired replication count
1963 * @param hop_count how many hops did this request traverse so far?
1964 * @param get_peer_path Peer list to reach to final destination which contains the data.
1965 * @param get_path_length Total numbers of peer in get_path
1966 * @param key Key key for the content
1967 * @param target_peer Next peer to forward the message to.
1968 * @param current_destination Peer which will get this message.
1969 * @param current_dest_type Type of current destination can be either FRIEND or FINGER
1972 GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type block_type,
1973 enum GNUNET_DHT_RouteOption options,
1974 uint32_t desired_replication_level,
1976 struct GNUNET_PeerIdentity *get_peer_path,
1977 unsigned int get_path_length,
1978 struct GNUNET_HashCode *key,
1979 struct GNUNET_PeerIdentity *target_peer,
1980 struct GNUNET_PeerIdentity *current_destination,
1981 struct GNUNET_PeerIdentity *current_source,
1982 enum current_destination_type *current_dest_type)
1984 struct PeerGetMessage *get_request;
1985 struct P2PPendingMessage *pending;
1986 struct GNUNET_PeerIdentity *get_path;
1987 struct FriendInfo *target_friend;
1991 msize = sizeof (struct PeerGetMessage) +
1992 (get_path_length * sizeof (struct GNUNET_PeerIdentity));
1994 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2000 memcpy (&key_value, key, sizeof (uint64_t));
2002 /* FIXME: Is this correct comparison? */
2003 if (NULL == target_peer)
2005 /* We have received the request from the client file and we don't know
2006 to which peer should we forward the message to. */
2007 struct GNUNET_PeerIdentity *next_hop;
2008 next_hop = find_successor (key_value, current_destination, current_dest_type);
2010 if (*current_dest_type == MY_ID)
2012 get_path = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2013 memcpy (get_path, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2014 get_path_length = 1;
2015 /* FIXME: At the moment I am just passing null,0 for values which I don't
2016 have. Also, handle return type. Modify this function and pass get path
2017 and get path length and then in datacache_handle. here in this case
2018 you can diretly call gds_client_handle_reply. */
2020 GDS_DATACACHE_handle_get (&(get_request->key),(get_request->block_type),
2021 get_path, get_path_length,get_path_length - 1,NULL);
2027 if (*current_dest_type == FINGER)
2029 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2032 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2036 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer);
2038 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2039 pending->importance = 0; /* FIXME */
2040 get_request = (struct PeerGetMessage *) &pending[1];
2041 pending->msg = &get_request->header;
2042 get_request->header.size = htons (msize);
2043 get_request->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
2044 get_request->get_path_length = htonl (get_path_length);
2045 get_request->key = *key;
2046 memcpy (&(get_request->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity));
2047 /* FIXME: Is this comparison correct? */
2048 if (current_source != NULL)
2049 memcpy (&(get_request->current_source), current_source, sizeof (struct GNUNET_PeerIdentity));
2050 get_request->current_dest_type = htonl (*current_dest_type);
2051 get_path = (struct GNUNET_PeerIdentity *) &get_request[1];
2052 memcpy (get_path, get_peer_path, get_path_length * sizeof (struct GNUNET_PeerIdentity));
2053 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2054 target_friend->pending_count++;
2055 process_friend_queue (target_friend);
2061 * FIXME: Here you should update the fields of struct PeerGetResultMessage.
2062 * At the end of this message you should add the data and get path and send
2063 * to the original requesting client. and there you should call GDS_CLIENT_handle_reply
2064 * with correct parameter.
2067 * @param get_path_length
2069 * @param put_path_length
2076 GDS_NEIGHBOURS_datacache_get (struct GNUNET_TIME_Absolute expiration,
2077 const struct GNUNET_HashCode *key,
2078 unsigned int get_path_length,
2079 const struct GNUNET_PeerIdentity *get_path,
2080 unsigned int put_path_length,
2081 const struct GNUNET_PeerIdentity *put_path,
2082 enum GNUNET_BLOCK_Type type, size_t data_size,
2085 /* Here you don't have the get path and get path length. you should call
2086 some function get those values and update the message and send them. */
2091 * TODO: In case of put, you add the peer in the peer list in handle_dht_p2p_put.
2092 * Verify that the addition is correct and we are adding peers correctly and incrementing
2093 * the trail length correctly.
2094 * Handle a put request from client file. If I am the final destination,
2095 * do a put else forward the message to next peer.
2096 * @param block_type type of the block
2097 * @param options routing options
2098 * @param desired_replication_level desired replication count, 0 for current
2099 * implementation of X-Vine.
2100 * @param expiration_time when does the content expire
2101 * @param hop_count how many hops has this message traversed so far
2102 * @param key key for the content
2103 * @param put_path_length number of entries in @a put_path
2104 * @param put_path peers this request has traversed so far (if tracked)
2105 * @param data payload to store
2106 * @param data_size number of bytes in @a data
2107 * @param current_destination intermediate destination of the packet.
2108 * @param current_source source for which @a current_destination is destination.
2109 * @param dest_type type of @a current_destination.
2110 * @param target_peer_id Next peer to forward the message to.
2113 GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type block_type,
2114 enum GNUNET_DHT_RouteOption options,
2115 uint32_t desired_replication_level,
2116 struct GNUNET_TIME_Absolute expiration_time,
2118 const struct GNUNET_HashCode *key,
2119 unsigned int put_path_length,
2120 struct GNUNET_PeerIdentity *put_path,
2121 const void *data, size_t data_size,
2122 struct GNUNET_PeerIdentity *current_destination,
2123 struct GNUNET_PeerIdentity *current_source,
2124 enum current_destination_type dest_type,
2125 struct GNUNET_PeerIdentity *target_peer)
2127 struct PeerPutMessage *ppm;
2128 struct P2PPendingMessage *pending;
2129 struct FriendInfo *target_friend;
2130 struct GNUNET_PeerIdentity *pp;
2134 msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
2135 sizeof (struct PeerPutMessage);
2137 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2139 put_path_length = 0;
2140 msize = data_size + sizeof (struct PeerPutMessage);
2143 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2149 memcpy (&key_value, key, sizeof (uint64_t));
2150 struct GNUNET_PeerIdentity *current_dest;
2151 current_dest = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2152 if (target_peer == NULL)
2154 /* This is the first time the call has been made from handle_dht_local_put.
2155 So, you need to search for the next peer to send this message to. */
2156 struct GNUNET_PeerIdentity *next_hop;
2158 next_hop = find_successor (key_value, current_dest, &dest_type);
2159 if (dest_type == MY_ID)
2161 /* FIXME: Choose one place to do datacache_put. I am doing put only if its
2162 destination so I will do no put operation
2163 in the client file.*/
2164 GDS_DATACACHE_handle_put (expiration_time, key, put_path_length, put_path,
2165 block_type, data_size, data);
2170 /* Find the friend corresponding to next_hop */
2171 if (dest_type == FINGER)
2173 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2175 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2179 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer);
2181 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2182 pending->importance = 0; /* FIXME */
2183 pending->timeout = expiration_time;
2184 ppm = (struct PeerPutMessage *) &pending[1];
2185 pending->msg = &ppm->header;
2186 ppm->header.size = htons (msize);
2187 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
2188 ppm->options = htonl (options);
2189 ppm->block_type = htonl (block_type);
2190 ppm->hop_count = htonl (hop_count + 1);
2191 ppm->desired_replication_level = htonl (desired_replication_level);
2192 ppm->put_path_length = htonl (put_path_length);
2193 ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
2194 /* FIXME: Here I am checking if we have a value in current_source then only copy.
2195 I am not sure if this checking is correct or not. */
2196 if (current_source != NULL)
2197 memcpy (&(ppm->current_source), current_source, sizeof (struct GNUNET_PeerIdentity));
2199 /* FIXME: here current_destination is the parameter, current_dest is what you
2200 get when you call find_successor. names don't do justice to the function.
2202 if (current_destination != NULL)
2203 memcpy (&(ppm->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity));
2205 memcpy (&(ppm->current_destination), current_dest, sizeof (struct GNUNET_PeerIdentity));
2206 ppm->current_destination_type = htonl (dest_type);
2209 pp = (struct GNUNET_PeerIdentity *) &ppm[1];
2210 /* FIXME: Is this comparison correct? Do we need this comparison. What happens
2211 in the case put_path_length is 0 and put_path is NULL, then at run time
2212 memcpy will fail. And I am not sure if comparing NULL is correct or not. */
2213 if (put_path_length != 0)
2215 memcpy (pp, put_path,
2216 sizeof (struct GNUNET_PeerIdentity) * put_path_length);
2218 memcpy (&pp[put_path_length], data, data_size);
2219 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2220 target_friend->pending_count++;
2221 process_friend_queue (target_friend);
2226 * FIXME: I am removing source peer as the first element in the trail
2227 * is source identity.
2228 * If I am adding myself when I am source then I don't need destination
2229 * peer in get but if I am not adding then I need it. At the moment I am removing
2230 * it but will check later if its wrong.
2231 * Send get result back to requesting client.
2232 * @param expiration when will the reply expire
2233 * @param key the query this reply is for
2234 * @param get_path_length number of peers in @a get_path
2235 * @param get_path path the reply took on get
2236 * @param put_path_length number of peers in @a put_path
2237 * @param put_path path the reply took on put
2238 * @param type type of the reply
2239 * @param data_size number of bytes in @a data
2240 * @param data application payload data
2242 * @param get_path_length
2245 GDS_NEIGHBOURS_send_get_result (struct GNUNET_TIME_Absolute expiration,
2246 const struct GNUNET_HashCode *key,
2247 unsigned int put_path_length,
2248 const struct GNUNET_PeerIdentity *put_path,
2249 enum GNUNET_BLOCK_Type type, size_t data_size,
2251 struct GNUNET_PeerIdentity *get_path,
2252 unsigned int get_path_length,
2253 unsigned int current_path_index,
2254 struct GNUNET_PeerIdentity *next_hop)
2256 struct PeerGetResultMessage *get_result;
2257 struct GNUNET_PeerIdentity *get_result_path;
2258 struct P2PPendingMessage *pending;
2259 struct FriendInfo *target_friend;
2262 msize = get_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
2263 sizeof (struct PeerPutMessage);
2265 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2270 /* GET_REULT should have all the things which we want to pass in client_handle_reply
2271 put path put path length get path get length data data_size. and rest things
2272 are required to reach to the correct peer. */
2273 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2274 pending->importance = 0; /* FIXME */
2275 /* FIXME: Should we add an expiration time like in put message. */
2276 get_result = (struct PeerGetResultMessage *)&pending[1];
2277 pending->msg = &get_result->header;
2278 get_result->header.size = htons (msize);
2279 get_result->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT);
2280 get_result->current_path_index = current_path_index;
2281 get_result->key = *key;
2283 get_result_path = (struct GNUNET_PeerIdentity *)&get_result[1];
2284 memcpy (get_result_path, get_path,
2285 sizeof (struct GNUNET_PeerIdentity) * get_path_length);
2286 memcpy (&get_result_path[get_path_length], data, data_size);
2288 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2289 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2290 target_friend->pending_count++;
2291 process_friend_queue (target_friend);
2303 handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer,
2304 const struct GNUNET_MessageHeader *message)
2306 /* If you are the source, go back to the client file and there search for
2307 the requesting client and send back the result. */
2308 struct PeerGetResultMessage *get_result;
2309 struct GNUNET_PeerIdentity *get_path;
2311 //size_t payload_size;
2313 unsigned int getlen;
2314 int current_path_index;
2316 msize = ntohs (message->size);
2317 if (msize < sizeof (struct PeerGetResultMessage))
2319 GNUNET_break_op (0);
2323 get_result = (struct PeerGetResultMessage *)message;
2324 getlen = ntohl (get_result->get_path_length);
2327 sizeof (struct PeerGetResultMessage) +
2328 getlen * sizeof (struct GNUNET_PeerIdentity)) ||
2330 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2332 GNUNET_break_op (0);
2336 /* FIXME: Get the put_path */
2337 get_path = (struct GNUNET_PeerIdentity *) &get_result[1];
2338 //payload = &get_path[getlen];
2339 /* payload_size = msize - (sizeof (struct PeerGetResultMessage) +
2340 getlen * sizeof (struct GNUNET_PeerIdentity));*/
2341 current_path_index = ntohl (get_result->current_path_index);
2343 /* Here you just have to check if you are the destination or not if not
2344 then read the next peer and send the message. */
2345 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &(get_result->destination_peer))))
2347 /* I am the destination. Call the function in client file.
2348 * FIXME: Here I don't know how I communicate the result back to client
2350 //GDS_CLIENTS_process_get_result();
2355 /* Read the element from the get path at trail index. set the trail index
2356 and call gds_neighbours_send_get_result.*/
2357 struct GNUNET_PeerIdentity *next_hop;
2359 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2360 memcpy (next_hop, &get_path[current_path_index], sizeof (struct GNUNET_PeerIdentity));
2363 if (current_path_index != 0)
2364 current_path_index--;
2366 GDS_NEIGHBOURS_send_get_result ((get_result->expiration), get_result->key,
2367 get_result->put_path_length, put_path,
2368 get_result->type, payload, payload_size
2369 get_path, getlen,current_path_index,
2374 return GNUNET_SYSERR;
2379 * Core handler for p2p put requests.
2381 * @param cls closure
2382 * @param peer sender of the request
2383 * @param message message
2384 * @param peer peer identity this notification is about
2385 * @return #GNUNET_OK to keep the connection open,
2386 * #GNUNET_SYSERR to close it (signal serious error)
2389 handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer,
2390 const struct GNUNET_MessageHeader *message)
2392 struct PeerPutMessage *put;
2393 struct GNUNET_PeerIdentity *put_path;
2394 enum GNUNET_DHT_RouteOption options;
2395 enum current_destination_type current_dst_type;
2396 struct GNUNET_PeerIdentity *current_destination;
2397 struct GNUNET_PeerIdentity *next_hop;
2398 struct GNUNET_HashCode test_key;
2401 size_t payload_size;
2405 put = (struct PeerPutMessage *) message;
2406 putlen = ntohl (put->put_path_length);
2407 msize = ntohs (message->size);
2410 sizeof (struct PeerPutMessage) +
2411 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
2413 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2415 GNUNET_break_op (0);
2419 put_path = (struct GNUNET_PeerIdentity *) &put[1];
2420 payload = &put_path[putlen];
2421 options = ntohl (put->options);
2422 payload_size = msize - (sizeof (struct PeerPutMessage) +
2423 putlen * sizeof (struct GNUNET_PeerIdentity));
2425 switch (GNUNET_BLOCK_get_key (GDS_block_context, ntohl (put->block_type),
2426 payload, payload_size, &test_key))
2429 if (0 != memcmp (&test_key, &put->key, sizeof (struct GNUNET_HashCode)))
2431 char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key));
2432 GNUNET_break_op (0);
2433 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2434 "PUT with key `%s' for block with key %s\n",
2435 put_s, GNUNET_h2s_full (&test_key));
2436 GNUNET_free (put_s);
2441 GNUNET_break_op (0);
2444 /* cannot verify, good luck */
2448 if (ntohl (put->block_type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
2450 switch (GNUNET_BLOCK_evaluate (GDS_block_context,
2451 ntohl (put->block_type),
2453 NULL, 0, /* bloom filer */
2454 NULL, 0, /* xquery */
2455 payload, payload_size))
2457 case GNUNET_BLOCK_EVALUATION_OK_MORE:
2458 case GNUNET_BLOCK_EVALUATION_OK_LAST:
2461 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
2462 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
2463 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
2464 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
2465 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
2466 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
2468 GNUNET_break_op (0);
2473 struct GNUNET_PeerIdentity pp[putlen + 1];
2475 /* extend 'put path' by sender */
2476 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
2478 memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity));
2485 current_destination = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2486 memcpy (current_destination, &(put->current_destination), sizeof (struct GNUNET_PeerIdentity));
2487 current_dst_type = ntohl (put->current_destination_type);
2488 memcpy (&key_value, &(put->key), sizeof (uint64_t));
2490 if (current_dst_type == FRIEND)
2492 next_hop = find_successor (key_value, current_destination, ¤t_dst_type);
2494 else if (current_dst_type == FINGER)
2496 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, current_destination))
2498 next_hop = find_successor (key_value, current_destination, ¤t_dst_type);
2502 next_hop = GDS_ROUTING_search (&(put->current_source), current_destination, peer);
2503 current_dst_type = FRIEND;
2507 if (current_dst_type == MY_ID)
2509 GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time),
2510 &(put->key),putlen, pp, ntohl (put->block_type),
2511 payload_size, payload);
2516 struct GNUNET_PeerIdentity *current_source;
2517 if (current_dst_type == FINGER)
2519 current_source = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2520 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2523 current_source = NULL;
2525 GDS_CLIENTS_process_put (options,
2526 ntohl (put->block_type),
2527 ntohl (put->hop_count),
2528 ntohl (put->desired_replication_level),
2530 GNUNET_TIME_absolute_ntoh (put->expiration_time),
2535 GDS_NEIGHBOURS_handle_put (ntohl (put->block_type),ntohl (put->options),
2536 ntohl (put->desired_replication_level),
2537 GNUNET_TIME_absolute_ntoh (put->expiration_time),
2538 ntohl (put->hop_count),&put->key, putlen,
2539 pp, payload, payload_size,
2540 current_destination, current_source,current_dst_type, next_hop);
2543 return GNUNET_SYSERR;
2549 * 1. I don't do block evalute as it uses xquery and bf for evaluation.Is
2550 * it okay if I just pass NULL. I am anyways going to pass NULL in case of
2552 * Core handler for p2p get requests.
2554 * @param cls closure
2555 * @param peer sender of the request
2556 * @param message message
2557 * @return #GNUNET_OK to keep the connection open,
2558 * #GNUNET_SYSERR to close it (signal serious error)
2561 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
2562 const struct GNUNET_MessageHeader *message)
2564 struct PeerGetMessage *get;
2565 struct GNUNET_PeerIdentity *current_destination;
2567 enum current_destination_type current_dest_type;
2568 struct GNUNET_PeerIdentity *next_hop;
2569 struct GNUNET_PeerIdentity *get_path;
2570 enum GNUNET_BLOCK_Type block_type;
2571 enum GNUNET_DHT_RouteOption options;
2573 unsigned int get_length;
2575 msize = ntohs (message->size);
2576 if (msize < sizeof (struct PeerGetMessage))
2578 GNUNET_break_op (0);
2582 get = (struct PeerGetMessage *)message;
2583 get_length = ntohl (get->get_path_length);
2584 get_path = (struct GNUNET_PeerIdentity *)&get[1];
2587 sizeof (struct PeerGetMessage) +
2588 get_length * sizeof (struct GNUNET_PeerIdentity)) ||
2590 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2592 GNUNET_break_op (0);
2596 current_destination = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2597 memcpy (current_destination, &(get->current_destination), sizeof (struct GNUNET_PeerIdentity));
2598 memcpy (&key_value, &(get->key), sizeof (uint64_t));
2599 current_dest_type = ntohl (get->current_dest_type);
2600 block_type = ntohl (get->block_type);
2601 options = ntohl (get->options);
2603 if (current_dest_type == FRIEND)
2605 next_hop = find_successor (key_value, current_destination, ¤t_dest_type);
2607 else if (current_dest_type == FINGER)
2609 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, current_destination))
2611 next_hop = find_successor (key_value, current_destination, ¤t_dest_type);
2615 next_hop = GDS_ROUTING_search (&(get->current_source), current_destination, peer);
2616 current_dest_type = FRIEND;
2620 /* Add sender to get path */
2621 struct GNUNET_PeerIdentity gp[get_length + 1];
2622 memcpy (gp, get_path, get_length * sizeof (struct GNUNET_PeerIdentity));
2623 gp[get_length + 1] = *peer;
2624 get_length = get_length + 1;
2626 if (current_dest_type == MY_ID)
2628 struct GNUNET_PeerIdentity final_get_path[get_length+1];
2629 memcpy (final_get_path, get_path, get_length * sizeof (struct GNUNET_PeerIdentity));
2630 memcpy (final_get_path, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2631 get_length = get_length + 1;
2632 struct GNUNET_PeerIdentity *next_hop;
2633 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2634 /* FIXME: Check if we need to have a check on get length. */
2635 memcpy (next_hop, &final_get_path[get_length-2], sizeof (struct GNUNET_PeerIdentity));
2637 GDS_DATACACHE_handle_get (&(get->key),(get->block_type),
2638 final_get_path, get_length,get_length - 1,next_hop);
2644 struct GNUNET_PeerIdentity *current_source;
2645 current_source = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2646 if (current_dest_type == FINGER)
2648 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2651 /* FIXME: Is this correct? */
2653 /* how to handle the case when we don't have any value for current source.*/
2656 GDS_NEIGHBOURS_handle_get (block_type, options, get->desired_replication_level,
2658 get_length, &(get->key),next_hop,
2659 current_destination, &(get->current_source),¤t_dest_type);
2663 return GNUNET_SYSERR;
2669 * Send tral rejection message
2670 * @param source_peer Source peer which wants to set up the trail.
2671 * @param finger_identity Finger identity to which it want to setup the trail.
2672 * @param congested_peer Peer which has send trail rejection message
2673 * @param next_hop Peer to which this message should be forwarded.
2674 * @param finger_map_index
2675 * @param trail_peer_list
2676 * @param trail_length
2679 GDS_NEIGHBOURS_send_trail_rejection_message(struct GNUNET_PeerIdentity *source_peer,
2680 uint64_t finger_identity,
2681 struct GNUNET_PeerIdentity *congested_peer,
2682 const struct GNUNET_PeerIdentity *next_hop,
2683 unsigned int finger_map_index,
2684 struct GNUNET_PeerIdentity *trail_peer_list,
2685 unsigned int trail_length)
2687 struct PeerTrailRejectionMessage *trail_rejection;
2688 struct GNUNET_PeerIdentity *trail_list;
2689 struct P2PPendingMessage *pending;
2690 struct FriendInfo *target_friend;
2693 msize = sizeof (struct PeerTrailRejectionMessage);
2695 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2696 pending->importance = 0; /* FIXME */
2697 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
2698 trail_rejection = (struct PeerTrailRejectionMessage *) &pending[1];
2699 pending->msg = &trail_rejection->header;
2700 trail_rejection->header.size = htons (msize);
2701 trail_rejection->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
2702 memcpy (&(trail_rejection->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
2703 memcpy (&(trail_rejection->congested_peer), congested_peer, sizeof (struct GNUNET_PeerIdentity));
2704 memcpy (&(trail_rejection->finger_identity), &finger_identity, sizeof (uint64_t));
2705 trail_rejection->finger_map_index = htonl(finger_map_index);
2706 trail_rejection->trail_length = htonl (trail_length);
2708 trail_list = (struct GNUNET_PeerIdentity *)&trail_rejection[1];
2709 memcpy (trail_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
2711 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2712 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2713 target_friend->pending_count++;
2714 process_friend_queue (target_friend);
2719 * Handle a PeerTrailSetupMessage.
2720 * @param cls closure
2721 * @param message message
2722 * @param peer peer identity this notification is about
2723 * @return GNUNET_OK on success, GNUNET_SYSERR on error
2726 handle_dht_p2p_trail_setup(void *cls, const struct GNUNET_PeerIdentity *peer,
2727 const struct GNUNET_MessageHeader *message)
2729 struct PeerTrailSetupMessage *trail_setup;
2730 struct GNUNET_PeerIdentity *next_hop;
2731 struct FriendInfo *target_friend;
2732 struct GNUNET_PeerIdentity *current_destination;
2733 struct GNUNET_PeerIdentity *trail_peer_list;
2734 enum current_destination_type current_dest_type;
2735 struct GNUNET_PeerIdentity *next_peer;
2736 unsigned int trail_length;
2737 uint32_t current_trail_index;
2738 unsigned int finger_map_index;
2739 uint64_t destination_finger_value;
2742 msize = ntohs (message->size);
2743 if (msize < sizeof (struct PeerTrailSetupMessage))
2745 GNUNET_break_op (0);
2749 trail_setup = (struct PeerTrailSetupMessage *) message;
2750 trail_length = ntohl (trail_setup->trail_length);
2752 if ((msize < sizeof (struct PeerTrailSetupMessage) +
2753 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
2755 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2757 GNUNET_break_op (0);
2761 current_dest_type = ntohl (trail_setup->current_destination_type);
2762 finger_map_index = ntohl (trail_setup->finger_map_index);
2763 trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_setup[1];
2764 destination_finger_value = trail_setup->destination_finger;
2765 current_destination = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2766 memcpy (current_destination, &(trail_setup->current_destination), sizeof (struct GNUNET_PeerIdentity));
2769 each peer maintains a list of trail fail list. there it stores an entry with
2770 source, finger identity it was trying, hop which rejected. it again call
2771 select_random_friend but does not consider me. and starts trail setup
2773 if (GDS_ROUTING_size() > 1)
2775 /* Setup the trail rejection message and send the message to peer. */
2776 /* FIXME: you need to pass the trail, trail length and finger map index. */
2777 GDS_NEIGHBOURS_send_trail_rejection_message (&(trail_setup->source_peer),
2778 trail_setup->destination_finger,
2779 &my_identity, peer, finger_map_index,
2780 trail_peer_list, trail_length);
2782 /* Find the next hop to send the packet to. */
2783 if (current_dest_type == FRIEND)
2785 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_setup->current_destination),
2788 next_hop = find_successor (destination_finger_value, current_destination, &(current_dest_type));
2791 return GNUNET_SYSERR;
2793 else if (current_dest_type == FINGER)
2795 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&(trail_setup->current_destination),
2798 next_hop = GDS_ROUTING_search (&(trail_setup->current_source),
2799 &(trail_setup->current_destination), peer);
2800 /* As an optimization, find the successor from the find successor and
2801 compare both the ids to find the closest peer. */
2805 next_hop = find_successor (destination_finger_value, current_destination, &(current_dest_type));
2809 /* Add yourself to the trail list and increment the trail length. */
2810 struct GNUNET_PeerIdentity *peer_list;
2811 peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * (trail_length + 1));
2812 if ( trail_length > 0)
2814 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
2816 memcpy (&peer_list[trail_length], &my_identity, sizeof (struct GNUNET_PeerIdentity));
2819 if (current_dest_type == MY_ID ||
2820 (0 == GNUNET_CRYPTO_cmp_peer_identity(next_hop, &(trail_setup->source_peer))))
2822 struct GNUNET_PeerIdentity *source_peer;
2823 source_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2824 memcpy (source_peer, &(trail_setup->source_peer), sizeof (struct GNUNET_PeerIdentity));
2826 current_trail_index = trail_length - 1;
2827 next_peer= GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2828 if (current_trail_index == 0)
2830 memcpy (next_peer, &(trail_setup->source_peer), sizeof (struct GNUNET_PeerIdentity));
2834 memcpy (next_peer, &trail_peer_list[current_trail_index-1], sizeof (struct GNUNET_PeerIdentity));
2837 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_peer);
2838 GNUNET_free (next_peer);
2840 if (0 == trail_setup->finger_map_index)
2842 struct GNUNET_PeerIdentity *new_trail_list;
2843 new_trail_list = invert_trail_list (source_peer, peer_list, trail_length);
2844 finger_table_add (source_peer, new_trail_list, trail_length, 1);
2847 GDS_NEIGHBOURS_send_trail_setup_result (&(trail_setup->source_peer),
2849 target_friend, trail_length,
2850 peer_list, current_trail_index,
2857 struct GNUNET_PeerIdentity *current_source;
2858 current_source = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2859 if (current_dest_type == FINGER)
2861 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2864 current_source = NULL;
2866 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2867 /* FiXME: Is it correct to use null value for current source. */
2868 GDS_NEIGHBOURS_send_trail_setup (&(trail_setup->source_peer),
2869 trail_setup->destination_finger,
2870 current_destination,current_source,
2871 target_friend, trail_length, peer_list,
2872 finger_map_index, current_dest_type);
2877 return GNUNET_SYSERR;
2882 * Core handle for p2p trail construction result messages.
2883 * @param cls closure
2884 * @param message message
2885 * @param peer peer identity this notification is about
2886 * @return GNUNET_OK on success, GNUNET_SYSERR on error
2889 handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer,
2890 const struct GNUNET_MessageHeader *message)
2892 struct PeerTrailSetupResultMessage *trail_result;
2893 struct GNUNET_PeerIdentity *trail_peer_list;
2894 struct GNUNET_PeerIdentity *next_hop;
2895 struct FriendInfo *target_friend;
2896 unsigned int current_trail_index;
2897 unsigned int finger_map_index;
2898 unsigned int trail_length;
2901 msize = ntohs (message->size);
2902 if (msize < sizeof (struct PeerTrailSetupResultMessage))
2904 GNUNET_break_op (0);
2908 trail_result = (struct PeerTrailSetupResultMessage *) message;
2909 trail_length = ntohl (trail_result->trail_length);
2912 sizeof (struct PeerTrailSetupResultMessage) +
2913 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
2915 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2917 GNUNET_break_op (0);
2921 current_trail_index = ntohl (trail_result->current_index);
2922 finger_map_index = ntohl (trail_result->finger_map_index);
2924 trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_result[1];
2926 if ( 0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->destination_peer),
2929 finger_table_add (&(trail_result->finger_identity), trail_peer_list, trail_length,
2937 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2939 current_trail_index = current_trail_index - 1;
2940 if (current_trail_index == 0)
2942 memcpy (next_hop, &(trail_result->destination_peer),sizeof (struct GNUNET_PeerIdentity));
2946 memcpy (next_hop, &(trail_peer_list[current_trail_index-1]),sizeof (struct GNUNET_PeerIdentity));
2950 /* If trail length = 2, it means that destination and source peer are friends
2951 Then don't add an entry. */
2952 if (trail_length != 2)
2953 GDS_ROUTING_add (&(trail_result->destination_peer), &(trail_result->finger_identity),
2955 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2956 GNUNET_free (next_hop);
2958 GDS_NEIGHBOURS_send_trail_setup_result (&(trail_result->destination_peer),
2959 &(trail_result->finger_identity),
2960 target_friend, trail_length,
2961 trail_peer_list,current_trail_index,
2966 return GNUNET_SYSERR;
2971 * FIXME: Use flag in the case finger peer map does not contain predcessor
2972 * then its NULL. Ideally it should never happen.
2973 * Get my current predecessor from the finger peer map
2974 * @return Current predecessor.
2976 static struct FingerInfo *
2979 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
2980 struct GNUNET_PeerIdentity key_ret;
2981 unsigned int finger_index;
2982 struct FingerInfo *my_predecessor;
2984 /* Iterate over finger peer map and extract your predecessor. */
2985 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
2986 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
2988 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next
2989 (finger_iter,&key_ret,(const void **)&my_predecessor))
2991 if(1 == my_predecessor->finger_map_index)
2997 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
2998 return my_predecessor;
3003 * Core handle for p2p verify successor messages.
3004 * @param cls closure
3005 * @param message message
3006 * @param peer peer identity this notification is about
3007 * @return GNUNET_OK on success, GNUNET_SYSERR on error
3010 handle_dht_p2p_verify_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
3011 const struct GNUNET_MessageHeader *message)
3013 struct PeerVerifySuccessorMessage *vsm;
3014 struct GNUNET_PeerIdentity *trail_peer_list;
3015 struct FriendInfo *target_friend;
3016 struct GNUNET_PeerIdentity *next_hop;
3017 struct GNUNET_PeerIdentity *source_peer;
3018 unsigned int trail_length;
3019 unsigned int current_trail_index;
3022 msize = ntohs (message->size);
3023 if (msize < sizeof (struct PeerVerifySuccessorMessage))
3025 GNUNET_break_op (0);
3029 vsm = (struct PeerVerifySuccessorMessage *) message;
3030 trail_length = ntohl (vsm->trail_length);
3032 if ((msize < sizeof (struct PeerVerifySuccessorMessage) +
3033 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3034 (trail_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3036 GNUNET_break_op (0);
3040 current_trail_index = ntohl (vsm->current_trail_index);
3041 trail_peer_list = (struct GNUNET_PeerIdentity *) &vsm[1];
3042 source_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
3043 memcpy (source_peer, &(vsm->source_peer), sizeof (struct GNUNET_PeerIdentity));
3045 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
3047 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsm->successor),&my_identity)))
3049 struct FingerInfo *my_predecessor;
3050 current_trail_index = trail_length - 1;
3051 if (current_trail_index == 0)
3052 memcpy (next_hop, source_peer, sizeof (struct GNUNET_PeerIdentity));
3054 memcpy (next_hop, &trail_peer_list[current_trail_index-1], sizeof (struct GNUNET_PeerIdentity));
3056 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3057 GNUNET_free (next_hop);
3059 my_predecessor = get_predecessor();
3060 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (source_peer,
3061 &(my_predecessor->finger_identity))))
3063 GDS_NEIGHBOURS_send_verify_successor_result (source_peer,
3065 &(my_predecessor->finger_identity),
3069 current_trail_index);
3073 struct GNUNET_PeerIdentity *new_successor_trail;
3074 int new_trail_length;
3077 new_trail_length = trail_length + my_predecessor->trail_length;
3078 new_successor_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * new_trail_length);
3079 memcpy (new_successor_trail, trail_peer_list, (trail_length) * sizeof (struct GNUNET_PeerIdentity));
3080 struct TrailPeerList *iterator;
3081 iterator = GNUNET_malloc (sizeof (struct TrailPeerList));
3082 iterator = my_predecessor->head;
3084 while (i < new_trail_length)
3086 memcpy (&new_successor_trail[i], &(iterator->peer), sizeof (struct GNUNET_PeerIdentity));
3087 iterator = iterator->next;
3091 GDS_NEIGHBOURS_send_verify_successor_result (source_peer,
3093 &(my_predecessor->finger_identity),
3095 new_successor_trail,
3097 current_trail_index);
3103 current_trail_index = current_trail_index + 1;
3104 memcpy (next_hop, &trail_peer_list[current_trail_index], sizeof (struct GNUNET_PeerIdentity));
3105 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3106 GNUNET_free (next_hop);
3108 GDS_NEIGHBOURS_send_verify_successor (source_peer, &(vsm->successor),target_friend,
3109 trail_peer_list, trail_length, current_trail_index);
3116 * Core handle for p2p notify new successor messages.
3117 * @param cls closure
3118 * @param message message
3119 * @param peer peer identity this notification is about
3120 * @return GNUNET_OK on success, GNUNET_SYSERR on error
3123 handle_dht_p2p_notify_new_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
3124 const struct GNUNET_MessageHeader *message)
3126 struct PeerNotifyNewSuccessorMessage *nsm;
3127 struct GNUNET_PeerIdentity *trail_peer_list;
3128 unsigned int current_trail_index;
3130 unsigned int trail_length;
3132 msize = ntohs (message->size);
3133 if (msize < sizeof (struct PeerNotifyNewSuccessorMessage))
3135 GNUNET_break_op (0);
3139 nsm = (struct PeerNotifyNewSuccessorMessage *) message;
3140 trail_length = ntohl (nsm->trail_length);
3142 if ((msize < sizeof (struct PeerNotifyNewSuccessorMessage) +
3143 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3145 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3147 GNUNET_break_op (0);
3151 current_trail_index = ntohl (nsm->current_index);
3152 trail_peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
3154 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(nsm->destination_peer), &my_identity)))
3156 struct GNUNET_PeerIdentity *new_trail;
3157 new_trail = invert_trail_list (&(nsm->source_peer), trail_peer_list, trail_length);
3158 finger_table_add (&(nsm->source_peer), new_trail, trail_length, 1);
3163 struct FriendInfo *target_friend;
3164 struct GNUNET_PeerIdentity *next_hop;
3166 target_friend = GNUNET_malloc (sizeof (struct FriendInfo));
3167 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
3169 current_trail_index = current_trail_index + 1;
3170 memcpy (next_hop, &trail_peer_list[current_trail_index], sizeof (struct GNUNET_PeerIdentity));
3171 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3172 GNUNET_free (next_hop);
3174 GDS_NEIGHBOURS_send_notify_new_successor (&(nsm->source_peer),
3175 &(nsm->destination_peer),
3176 target_friend, trail_peer_list,
3177 trail_length, current_trail_index);
3184 * Core handle for p2p verify successor result messages.
3185 * @param cls closure
3186 * @param message message
3187 * @param peer peer identity this notification is about
3188 * @return GNUNET_OK on success, GNUNET_SYSERR on error
3191 handle_dht_p2p_verify_successor_result(void *cls, const struct GNUNET_PeerIdentity *peer,
3192 const struct GNUNET_MessageHeader *message)
3194 struct PeerVerifySuccessorResultMessage *vsrm;
3195 struct FriendInfo *target_friend;
3196 struct GNUNET_PeerIdentity *trail_peer_list;
3197 struct GNUNET_PeerIdentity *next_hop;
3198 unsigned int trail_length;
3199 unsigned int current_trail_index;
3202 msize = ntohs (message->size);
3203 if (msize < sizeof (struct PeerVerifySuccessorResultMessage))
3205 GNUNET_break_op (0);
3209 vsrm = (struct PeerVerifySuccessorResultMessage *) message;
3210 trail_length = ntohl (vsrm->trail_length);
3213 sizeof (struct PeerVerifySuccessorResultMessage) +
3214 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3216 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3218 GNUNET_break_op (0);
3222 current_trail_index = ntohl (vsrm->current_index);
3223 trail_peer_list = (struct GNUNET_PeerIdentity *) &vsrm[1];
3225 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->destination_peer), &(my_identity))))
3227 if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->my_predecessor), &(my_identity))))
3229 finger_table_add (&(vsrm->my_predecessor), trail_peer_list, trail_length, 0);
3230 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
3231 memcpy (next_hop, &trail_peer_list[0], sizeof (struct GNUNET_PeerIdentity));
3232 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3233 current_trail_index = 0;
3234 GNUNET_free (next_hop);
3236 GDS_NEIGHBOURS_send_notify_new_successor (&my_identity, &(vsrm->my_predecessor),
3237 target_friend, trail_peer_list,
3238 trail_length, current_trail_index);
3243 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
3244 current_trail_index = current_trail_index - 1;
3245 if (current_trail_index == 0)
3246 memcpy (next_hop, &(vsrm->destination_peer), sizeof (struct GNUNET_PeerIdentity));
3248 memcpy (next_hop, &trail_peer_list[current_trail_index-1], sizeof (struct GNUNET_PeerIdentity));
3249 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3250 GNUNET_free (next_hop);
3252 GDS_NEIGHBOURS_send_verify_successor_result (&(vsrm->destination_peer),
3253 &(vsrm->source_successor),
3254 &(vsrm->my_predecessor),
3258 current_trail_index);
3265 * FIXME: Does it matter if the packet was going to a finger or friend?
3266 * Core handle for p2p trail rejection messages.
3267 * @param cls closure
3268 * @param message message
3269 * @param peer peer identity this notification is about
3270 * @return GNUNET_OK on success, GNUNET_SYSERR on error
3273 int handle_dht_p2p_trail_rejection(void *cls, const struct GNUNET_PeerIdentity *peer,
3274 const struct GNUNET_MessageHeader *message)
3276 struct PeerTrailRejectionMessage *trail_rejection;
3277 struct FailedTrail *trail_fail;
3278 struct FriendInfo *target_friend;
3279 struct GNUNET_PeerIdentity *trail_peer_list;
3280 unsigned int finger_map_index;
3283 msize = ntohs (message->size);
3284 if (msize < sizeof (struct PeerTrailRejectionMessage))
3286 GNUNET_break_op (0);
3290 trail_rejection = (struct PeerTrailRejectionMessage *) message;
3291 trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_rejection[1];
3292 finger_map_index = ntohl (trail_rejection->finger_map_index);
3293 trail_fail = GNUNET_malloc (sizeof (struct FailedTrail));
3294 memcpy (&(trail_fail->source_peer), &(trail_rejection->source_peer), sizeof (struct GNUNET_PeerIdentity));
3295 memcpy (&(trail_fail->congested_peer), &(trail_rejection->congested_peer), sizeof (struct GNUNET_PeerIdentity));
3296 memcpy (&(trail_fail->destination_finger_value), &(trail_rejection->finger_identity), sizeof (uint64_t));
3298 GNUNET_assert (GNUNET_OK ==
3299 GNUNET_CONTAINER_multipeermap_put (failed_trail_list, &(trail_fail->source_peer),
3300 trail_fail, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
3302 /* FIXME: Is it okay if I pass the struct as parameter. */
3303 target_friend = select_random_friend (&(trail_fail->congested_peer));
3305 if(NULL != target_friend)
3307 /* FIXME: Here I am passing NULL for current source, is it correct?
3308 also, we set the current source only if current_destination_type
3310 GDS_NEIGHBOURS_send_trail_setup (&(trail_fail->source_peer),
3311 trail_fail->destination_finger_value,
3312 &(target_friend->id),
3313 NULL, target_friend, ntohl (trail_rejection->trail_length),
3315 finger_map_index, FRIEND);
3318 return GNUNET_SYSERR;
3323 * Initialize neighbours subsystem.
3324 * @return GNUNET_OK on success, GNUNET_SYSERR on error
3327 GDS_NEIGHBOURS_init()
3329 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
3330 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0},
3331 {&handle_dht_p2p_get_result, GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT, 0},
3332 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0},
3333 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP, 0},
3334 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT, 0},
3335 {&handle_dht_p2p_verify_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR, 0},
3336 {&handle_dht_p2p_verify_successor_result, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT, 0},
3337 {&handle_dht_p2p_notify_new_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR, 0},
3338 {&handle_dht_p2p_trail_rejection, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION, 0},
3343 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
3344 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
3345 GNUNET_NO, core_handlers);
3346 if (NULL == core_api)
3347 return GNUNET_SYSERR;
3349 friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
3350 finger_peermap = GNUNET_CONTAINER_multipeermap_create (MAX_FINGERS, GNUNET_NO);
3351 /* FIXME: Not sure if this value is correct for this data structure. */
3352 failed_trail_list = GNUNET_CONTAINER_multipeermap_create (LINK_THRESHOLD, GNUNET_NO);
3358 * Shutdown neighbours subsystem.
3361 GDS_NEIGHBOURS_done ()
3363 if (NULL == core_api)
3366 GNUNET_CORE_disconnect (core_api);
3369 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
3370 GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
3371 friend_peermap = NULL;
3373 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (finger_peermap));
3374 GNUNET_CONTAINER_multipeermap_destroy (finger_peermap);
3375 finger_peermap = NULL;
3377 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
3379 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
3380 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
3383 if (GNUNET_SCHEDULER_NO_TASK != verify_successor)
3385 GNUNET_SCHEDULER_cancel (verify_successor);
3386 verify_successor = GNUNET_SCHEDULER_NO_TASK;
3393 * Get the ID of the local node.
3395 * @return identity of the local node
3397 struct GNUNET_PeerIdentity *
3398 GDS_NEIGHBOURS_get_id ()
3400 return &my_identity;
3404 /* end of gnunet-service-xdht_neighbours.c */