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 will receive the get result message.
191 struct GNUNET_PeerIdentity source_peer;
194 * Current index in get path.
196 unsigned int current_path_index;
199 * Number of peers recorded in the outgoing path from source to the
200 * stored location of this message.
202 uint32_t put_path_length GNUNET_PACKED;
205 * Length of the GET path that follows (if tracked).
207 uint32_t get_path_length GNUNET_PACKED;
210 * When does the content expire?
212 struct GNUNET_TIME_Absolute expiration_time;
215 * The key of the corresponding GET request.
217 struct GNUNET_HashCode key;
219 /* put path (if tracked) */
221 /* get path (if tracked) */
231 struct PeerGetMessage
234 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET
236 struct GNUNET_MessageHeader header;
241 uint32_t options GNUNET_PACKED;
244 * Desired content type.
246 uint32_t block_type GNUNET_PACKED;
251 uint32_t hop_count GNUNET_PACKED;
254 * Desired replication level for this request.
256 uint32_t desired_replication_level GNUNET_PACKED;
259 * Total number of peers in get path.
261 unsigned int get_path_length;
264 * Peer which is an intermediate destination.
266 struct GNUNET_PeerIdentity current_destination;
269 * Source for which current_destination is the finger.
271 struct GNUNET_PeerIdentity current_source;
274 * Type of current destination
276 enum current_destination_type current_dest_type;
279 * The key we are looking for.
281 struct GNUNET_HashCode key;
289 * P2P Trail setup message
291 struct PeerTrailSetupMessage
295 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP
297 struct GNUNET_MessageHeader header;
300 * Source peer which wants to setup the trail to one of its finger.
302 struct GNUNET_PeerIdentity source_peer;
305 * Successor of this finger value will be our finger peer.
307 uint64_t destination_finger;
310 * Peer which gets this message can be either an intermediate finger or friend.
312 enum current_destination_type current_destination_type;
315 * Peer to which this packet is forwarded.
317 struct GNUNET_PeerIdentity current_destination;
320 * In case the packet is forwarded to an intermediate finger, then
321 * current_source contains the peer id whose finger is the intermediate
322 * finger. In case the packet is forwarded to a friend, then it is NULL.
324 struct GNUNET_PeerIdentity current_source;
327 * Index into finger peer map.
329 unsigned int finger_map_index;
332 * Number of entries in trail list.
334 uint32_t trail_length GNUNET_PACKED;
340 * P2P Trail Setup Result message
342 struct PeerTrailSetupResultMessage
346 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT
348 struct GNUNET_MessageHeader header;
351 * Finger to which we have found the path.
353 struct GNUNET_PeerIdentity finger_identity;
356 * Peer which was looking for the trail to finger.
358 struct GNUNET_PeerIdentity destination_peer;
361 * Trail index which points to next destination to send this message.
363 unsigned int current_index;
366 * Index into finger peer map
368 unsigned int finger_map_index;
371 * Number of entries in trail list.
373 uint32_t trail_length GNUNET_PACKED;
380 struct PeerTrailRejectionMessage
383 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION
385 struct GNUNET_MessageHeader header;
388 * Source peer which wants to set up the trail.
390 struct GNUNET_PeerIdentity source_peer;
393 * Finger identity value.
395 uint64_t finger_identity;
398 * Peer which sent trail rejection message.
400 struct GNUNET_PeerIdentity congested_peer;
403 * Index in finger peer map of source peer.
405 unsigned int finger_map_index;
408 * Total number of peers in the trail.
410 unsigned int trail_length;
417 * P2P Verify Successor message.
419 struct PeerVerifySuccessorMessage
423 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR
425 struct GNUNET_MessageHeader header;
428 * Source peer which wants to verify its successor.
430 struct GNUNET_PeerIdentity source_peer;
433 * My current successor.
435 struct GNUNET_PeerIdentity successor;
438 * Total number of peers in trail to current successor.
440 unsigned int trail_length;
443 * Trail index which points to next destination to send this message.
445 unsigned int current_trail_index;
451 * P2P Verify Successor Result message.
453 struct PeerVerifySuccessorResultMessage
457 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT
459 struct GNUNET_MessageHeader header;
462 * Destination peer which sent the request to verify its successor.
464 struct GNUNET_PeerIdentity destination_peer;
467 * Successor to which PeerVerifySuccessorMessage was sent.
469 struct GNUNET_PeerIdentity source_successor;
472 * source_successor's predecessor
474 struct GNUNET_PeerIdentity my_predecessor;
477 * Total number of peers in trail.
478 * If source_successor is not destination peer, then trail is from destination_peer
480 * If source_successor is destination peer, then trail is from destination_peer
481 * to source_successor.
483 unsigned int trail_length;
486 * Trail index which points to next destination to send this message.
488 unsigned int current_index;
493 * P2P Notify New Successor message.
495 struct PeerNotifyNewSuccessorMessage
498 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR
500 struct GNUNET_MessageHeader header;
503 * Source peer which wants to notify its new successor.
505 struct GNUNET_PeerIdentity source_peer;
508 * New successor identity.
510 struct GNUNET_PeerIdentity destination_peer;
513 * Number of peers in trail from source_peer to new successor.
515 unsigned int trail_length;
518 * Trail index which points to next destination to send this message.
520 unsigned int current_index;
525 GNUNET_NETWORK_STRUCT_END
529 * Linked list of messages to send to a particular other peer.
531 struct P2PPendingMessage
534 * Pointer to next item in the list
536 struct P2PPendingMessage *next;
539 * Pointer to previous item in the list
541 struct P2PPendingMessage *prev;
544 * When does this message time out?
546 struct GNUNET_TIME_Absolute timeout;
549 * Message importance level. FIXME: used? useful?
551 unsigned int importance;
554 * Actual message to be sent, allocated at the end of the struct:
555 * // msg = (cast) &pm[1];
556 * // memcpy (&pm[1], data, len);
558 const struct GNUNET_MessageHeader *msg;
564 * Linked List of peers which are part of trail to reach a particular Finger.
569 * Pointer to next item in the list
571 struct TrailPeerList *next;
574 * Pointer to previous item in the list
576 struct TrailPeerList *prev;
579 * An element in this trail list
581 struct GNUNET_PeerIdentity peer;
587 * Entry in friend_peermap.
594 struct GNUNET_PeerIdentity id;
597 * Number of trail of which this friend is the first hop.
599 unsigned int trail_links;
602 * Count of outstanding messages for this friend.
604 unsigned int pending_count;
607 * Head of pending messages to be sent to this friend.
609 struct P2PPendingMessage *head;
612 * Tail of pending messages to be sent to this friend.
614 struct P2PPendingMessage *tail;
617 * Core handle for sending messages to this friend.
619 struct GNUNET_CORE_TransmitHandle *th;
625 * Entry in finger_peermap.
632 struct GNUNET_PeerIdentity finger_identity;
635 * Index in finger peer map
637 unsigned int finger_map_index;
640 * Total number of entries in trail from (me,finger]
642 unsigned int trail_length;
645 * Head of trail to reach this finger.
647 struct TrailPeerList *head;
650 * Tail of trail to reach this finger.
652 struct TrailPeerList *tail;
658 * FIXME: Think of a better name.
659 * Data structure passed to sorting algorithm in find_successor.
664 * 64 bit value of peer identity
669 * Type : MY_ID, FINGER, FINGER, Value
671 enum current_destination_type type;
674 * Pointer to original data structure linked to peer id.
681 * FIXME: Think of better comments.
682 * An entry in Failed_Trail_List
687 * Source peer which was trying to setup up the trail to @a destination_finger_value
689 struct GNUNET_PeerIdentity source_peer;
692 * Value to which we were trying to find the closest successor.
694 uint64_t destination_finger_value;
697 * Peer which has crossed the threshold limit on its routing table size.
699 struct GNUNET_PeerIdentity congested_peer;
705 * Task that sends FIND FINGER TRAIL requests.
707 static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task;
711 * Task that periodically verifies my successor.
713 static GNUNET_SCHEDULER_TaskIdentifier verify_successor;
716 * Identity of this peer.
718 static struct GNUNET_PeerIdentity my_identity;
721 * Hash map of all the friends of a peer
723 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap;
726 * Hash map of all the fingers of a peer
728 static struct GNUNET_CONTAINER_MultiPeerMap *finger_peermap;
731 * Hash maps of all the trail which failed due to a congested peer.
733 static struct GNUNET_CONTAINER_MultiPeerMap *failed_trail_list;
738 static struct GNUNET_CORE_Handle *core_api;
741 * FIXME: Is it safe to assume its initialized to 0 by default.
742 * The current finger index that we have found trail to.
744 static unsigned int current_finger_index;
748 * Called when core is ready to send a message we asked for
749 * out to the destination.
751 * @param cls the 'struct FriendInfo' of the target friend
752 * @param size number of bytes available in buf
753 * @param buf where the callee should write the message
754 * @return number of bytes written to buf
757 core_transmit_notify (void *cls, size_t size, void *buf)
759 struct FriendInfo *peer = cls;
761 struct P2PPendingMessage *pending;
766 while ((NULL != (pending = peer->head)) &&
767 (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us))
769 peer->pending_count--;
770 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
771 GNUNET_free (pending);
775 /* no messages pending */
781 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
782 GNUNET_CORE_PRIO_BEST_EFFORT,
783 GNUNET_TIME_absolute_get_remaining
784 (pending->timeout), &peer->id,
785 ntohs (pending->msg->size),
786 &core_transmit_notify, peer);
787 GNUNET_break (NULL != peer->th);
791 while ((NULL != (pending = peer->head)) &&
792 (size - off >= (msize = ntohs (pending->msg->size))))
794 GNUNET_STATISTICS_update (GDS_stats,
796 ("# Bytes transmitted to other peers"), msize,
798 memcpy (&cbuf[off], pending->msg, msize);
800 peer->pending_count--;
801 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
802 GNUNET_free (pending);
804 if (peer->head != NULL)
807 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
808 GNUNET_CORE_PRIO_BEST_EFFORT,
809 GNUNET_TIME_absolute_get_remaining
810 (pending->timeout), &peer->id, msize,
811 &core_transmit_notify, peer);
812 GNUNET_break (NULL != peer->th);
819 * Transmit all messages in the friend's message queue.
821 * @param peer message queue to process
824 process_friend_queue (struct FriendInfo *peer)
826 struct P2PPendingMessage *pending;
828 if (NULL == (pending = peer->head))
830 if (NULL != peer->th)
833 GNUNET_STATISTICS_update (GDS_stats,
835 ("# Bytes of bandwidth requested from core"),
836 ntohs (pending->msg->size), GNUNET_NO);
838 /* FIXME: Are we correctly initializing importance and pending. */
840 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
842 GNUNET_TIME_absolute_get_remaining
843 (pending->timeout), &peer->id,
844 ntohs (pending->msg->size),
845 &core_transmit_notify, peer);
846 GNUNET_break (NULL != peer->th);
850 /**FIXME: add better comment for current_source which shows its relation
851 * with current_destination.
852 * Construct a trail message and forward it to a friend.
853 * @param source_peer Peer which wants to set up the trail to one of its finger.
854 * @param destination_finger Value whose successor we are searching the network.
855 * @param current_destination Peer which gets this message.
856 * @param current_source Peer for which current_destination is its finger.
857 * @param target_friend Current friend to which this message should be forwarded.
858 * @param trail_length Numbers of peers in the trail.
859 * @param trail_peer_list peers this request has traversed so far
860 * @param finger_map_index Index in finger peer map
861 * @param type Type of current destination can be either FRIEND or FINGER
864 GDS_NEIGHBOURS_send_trail_setup (struct GNUNET_PeerIdentity *source_peer,
865 uint64_t destination_finger,
866 struct GNUNET_PeerIdentity *current_destination,
867 struct GNUNET_PeerIdentity *current_source,
868 struct FriendInfo *target_friend,
869 unsigned int trail_length,
870 struct GNUNET_PeerIdentity *trail_peer_list,
871 unsigned int finger_map_index,
872 enum current_destination_type type)
874 struct P2PPendingMessage *pending;
875 struct PeerTrailSetupMessage *tsm;
876 struct GNUNET_PeerIdentity *peer_list;
879 msize = sizeof (struct PeerTrailSetupMessage) +
880 (trail_length * sizeof (struct GNUNET_PeerIdentity));
882 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
888 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
890 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
894 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
895 pending->importance = 0; /* FIXME */
896 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
897 tsm = (struct PeerTrailSetupMessage *) &pending[1];
898 pending->msg = &tsm->header;
899 tsm->header.size = htons (msize);
900 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
901 memcpy (&(tsm->destination_finger), &destination_finger, sizeof (uint64_t));
902 memcpy (&(tsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
903 memcpy (&(tsm->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity));
904 /* FIXME: Is it correct to use NULL here for comparison? */
905 if (current_source != NULL)
906 memcpy (&(tsm->current_source), current_source, sizeof (struct GNUNET_PeerIdentity));
907 tsm->current_destination_type = htonl (type);
908 tsm->trail_length = htonl (trail_length);
909 tsm->finger_map_index = htonl (finger_map_index);
911 if (trail_peer_list != NULL)
913 peer_list = (struct GNUNET_PeerIdentity *) &tsm[1];
914 memcpy (peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
917 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
918 target_friend->pending_count++;
919 process_friend_queue (target_friend);
925 * Construct a trail setup result message and forward it to a friend.
926 * @param destination_peer Peer which will get the trail to one of its finger.
927 * @param source_finger Peer to which the trail has been setup to.
928 * @param target_friend Friend to which this message should be forwarded.
929 * @param trail_length Numbers of peers in the trail.
930 * @param trail_peer_list Peers which are part of the trail from source to destination.
931 * @param current_trail_index Index at which sender of this message is located.
932 * @param finger_map_index Index in finger peer map
935 GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity *destination_peer,
936 struct GNUNET_PeerIdentity *source_finger,
937 struct FriendInfo *target_friend,
938 unsigned int trail_length,
939 struct GNUNET_PeerIdentity *trail_peer_list,
940 unsigned int current_trail_index,
941 unsigned int finger_map_index)
943 struct P2PPendingMessage *pending;
944 struct PeerTrailSetupResultMessage *tsrm;
945 struct GNUNET_PeerIdentity *peer_list;
948 msize = sizeof (struct PeerTrailSetupResultMessage) +
949 (trail_length * sizeof (struct GNUNET_PeerIdentity));
951 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
957 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
959 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
963 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
964 pending->importance = 0;
965 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
966 tsrm = (struct PeerTrailSetupResultMessage *) &pending[1];
967 pending->msg = &tsrm->header;
968 tsrm->header.size = htons (msize);
969 tsrm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT);
970 memcpy (&(tsrm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
971 memcpy (&(tsrm->finger_identity), source_finger, sizeof (struct GNUNET_PeerIdentity));
972 tsrm->trail_length = htonl (trail_length);
973 tsrm->current_index = htonl (current_trail_index);
974 tsrm->finger_map_index = htonl (finger_map_index);
975 peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1];
976 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
978 /* Send the message to chosen friend. */
979 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
980 target_friend->pending_count++;
981 process_friend_queue (target_friend);
986 * Construct a PeerVerifySuccessor message and send it to friend.
987 * @param source_peer Peer which wants to verify its successor
988 * @param successor Peer which is our current successor
989 * @param target_friend Friend to which this message should be forwarded.
990 * @param trail_peer_list Peer which are part of trail from source to destination
991 * @param trail_length Number of peers in the trail list.
992 * @param current_trail_index Index in the trial list at which receiving peer should
993 * read the next element.
995 void GDS_NEIGHBOURS_send_verify_successor(struct GNUNET_PeerIdentity *source_peer,
996 struct GNUNET_PeerIdentity *successor,
997 struct FriendInfo *target_friend,
998 struct GNUNET_PeerIdentity *trail_peer_list,
999 unsigned int trail_length,
1000 unsigned int current_trail_index)
1002 struct PeerVerifySuccessorMessage *vsm;
1003 struct P2PPendingMessage *pending;
1004 struct GNUNET_PeerIdentity *peer_list;
1007 msize = sizeof (struct PeerVerifySuccessorMessage) +
1008 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1010 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1016 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1018 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1022 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1023 pending->importance = 0; /* FIXME */
1024 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1025 vsm = (struct PeerVerifySuccessorMessage *) &pending[1];
1026 pending->msg = &vsm->header;
1027 vsm->header.size = htons (msize);
1028 vsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR);
1029 memcpy (&(vsm->successor), successor, sizeof (struct GNUNET_PeerIdentity));
1030 memcpy (&(vsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1031 vsm->trail_length = htonl (trail_length);
1032 vsm->current_trail_index = htonl (current_trail_index);
1033 peer_list = (struct GNUNET_PeerIdentity *) &vsm[1];
1034 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1036 /* Send the message to chosen friend. */
1037 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1038 target_friend->pending_count++;
1039 process_friend_queue (target_friend);
1045 * Construct a PeerVerifySuccessorResult message and send it to friend.
1046 * @param destination_peer Peer which sent verify successor message
1047 * @param source_successor Peer to which verify successor message was sent.
1048 * @param my_predecessor source_successor's predecessor.
1049 * @param target_friend Friend to which this message should be forwarded.
1050 * @param trail_peer_list Peers which are part of trail from source to destination
1051 * @param trail_length Number of peers in the trail list.
1052 * @param current_trail_index Index in the trial list at which receiving peer should
1053 * get the next element.
1055 void GDS_NEIGHBOURS_send_verify_successor_result (struct GNUNET_PeerIdentity *destination_peer,
1056 struct GNUNET_PeerIdentity *source_successor,
1057 struct GNUNET_PeerIdentity *my_predecessor,
1058 struct FriendInfo *target_friend,
1059 struct GNUNET_PeerIdentity *trail_peer_list,
1060 unsigned int trail_length,
1061 unsigned int current_trail_index)
1063 struct PeerVerifySuccessorResultMessage *vsmr;
1064 struct P2PPendingMessage *pending;
1065 struct GNUNET_PeerIdentity *peer_list;
1068 msize = sizeof (struct PeerVerifySuccessorResultMessage) +
1069 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1071 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1078 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1080 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1084 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1085 pending->importance = 0; /* FIXME */
1086 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1087 vsmr = (struct PeerVerifySuccessorResultMessage *) &pending[1];
1088 pending->msg = &vsmr->header;
1089 vsmr->header.size = htons (msize);
1090 vsmr->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT);
1091 memcpy (&(vsmr->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1092 memcpy (&(vsmr->source_successor), source_successor, sizeof (struct GNUNET_PeerIdentity));
1093 memcpy (&(vsmr->my_predecessor), my_predecessor, sizeof (struct GNUNET_PeerIdentity));
1094 vsmr->trail_length = htonl (trail_length);
1095 vsmr->current_index = htonl (current_trail_index);
1097 peer_list = (struct GNUNET_PeerIdentity *) &vsmr[1];
1098 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1100 /* Send the message to chosen friend. */
1101 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1102 target_friend->pending_count++;
1103 process_friend_queue (target_friend);
1108 * Construct a PeerNotifyNewSuccessor message and send it to friend.
1109 * @param source_peer Peer which is sending notify message to its new successor.
1110 * @param destination_peer Peer which is the new destination.
1111 * @param target_friend Next friend to pass this message to.
1112 * @param peer_list List of peers in the trail to reach to destination_peer.
1113 * @param current_trail_index Index of peer_list for next target friend position.
1114 * @param trail_length Total number of peers in peer list
1117 GDS_NEIGHBOURS_send_notify_new_successor (struct GNUNET_PeerIdentity *source_peer,
1118 struct GNUNET_PeerIdentity *destination_peer,
1119 struct FriendInfo *target_friend,
1120 struct GNUNET_PeerIdentity *trail_peer_list,
1121 unsigned int trail_length,
1122 unsigned int current_trail_index)
1124 struct PeerNotifyNewSuccessorMessage *nsm;
1125 struct P2PPendingMessage *pending;
1126 struct GNUNET_PeerIdentity *peer_list;
1129 msize = sizeof (struct PeerNotifyNewSuccessorMessage) +
1130 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1132 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1138 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1140 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1144 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1145 pending->importance = 0; /* FIXME */
1146 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1147 nsm = (struct PeerNotifyNewSuccessorMessage *) &pending[1];
1148 pending->msg = &nsm->header;
1149 nsm->header.size = htons (msize);
1150 nsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR);
1151 memcpy (&(nsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
1152 memcpy (&(nsm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity));
1153 nsm->trail_length = htonl (trail_length);
1154 nsm->current_index = htonl (current_trail_index);
1156 peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
1157 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1159 /* Send the message to chosen friend. */
1160 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1161 target_friend->pending_count++;
1162 process_friend_queue (target_friend);
1167 * FIXME: Optimizaiton Once the basic code is running. Add the optimization
1168 * where you check if the threshold on number of links that should go through
1169 * a particular friend has crossed. If yes then again choose a different
1170 * friend. Important that the new friend chosen should be different. How to
1171 * ensure this? This is an important optimization as without this one x-vine
1172 * is actually not a sybil tolerant DHT.
1173 * Randomly choose one of your friends from the friends_peer map
1176 static struct FriendInfo *
1177 select_random_friend (struct GNUNET_PeerIdentity *congested_peer)
1179 unsigned int current_size;
1180 unsigned int *index;
1182 struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
1183 struct GNUNET_PeerIdentity key_ret;
1184 struct FriendInfo *friend;
1186 current_size = GNUNET_CONTAINER_multipeermap_size (friend_peermap);
1187 index = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, current_size);
1188 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1192 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,NULL,NULL))
1200 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,&key_ret,(const void **)&friend))
1202 /* TODO: Here you have chosen a random friend. Now you should check the size
1203 of its routing table size, and if its more than threshold, then check which
1204 of the entries has trail length greater than trail length threshold. we
1205 should without checking the routing table size also we should check the
1206 trail with trail length greater than threshold. then
1207 you should try to find a new route through this new node that has joined in
1208 only for those finger entries whose trail length is greater than threshold.
1209 But I don't want the new node to wait for this process to get over. so
1210 should i declare a function which will be called after some interval.*/
1219 * Compute finger_identity to which we want to setup the trail
1220 * @return finger_identity
1223 compute_finger_identity()
1226 uint64_t *finger_identity64;
1228 finger_identity64 = GNUNET_malloc (sizeof (uint64_t));
1229 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
1230 /*FIXME: Do we need a mod finger = ((my_id + pow(2, finger_index)) mod (pow (2, MAX_FINGERS))*/
1231 *finger_identity64 = (my_id64 + (unsigned long) pow (2,current_finger_index));
1233 return finger_identity64;
1238 * Compute immediate predecessor identity in the network.
1239 * @return peer identity of immediate predecessor.
1242 compute_predecessor_identity()
1245 uint64_t *predecessor;
1247 predecessor = GNUNET_malloc (sizeof (uint64_t));
1248 memcpy (&my_id, &my_identity, sizeof (uint64_t));
1249 /* FIXME: Do we need to use mod pow(2, MAX_FINGERS) here? */
1250 *predecessor = (my_id -1);
1257 * Periodically ping your successor to ask its current predecessor
1259 * @param cls closure for this task
1260 * @param tc the context under which the task is running
1263 send_verify_successor_message (void *cls,
1264 const struct GNUNET_SCHEDULER_TaskContext *tc )
1266 struct GNUNET_TIME_Relative next_send_time;
1267 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1268 struct GNUNET_PeerIdentity key_ret;
1269 struct FriendInfo *target_friend;
1270 struct GNUNET_PeerIdentity *next_hop;
1271 struct GNUNET_PeerIdentity *peer_list;
1272 unsigned int finger_trail_current_index;
1273 struct FingerInfo *finger;
1274 unsigned int finger_index;
1278 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1279 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
1281 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, &key_ret,
1282 (const void **)&finger))
1284 if (0 == finger->finger_map_index)
1291 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
1294 goto send_new_request;
1296 peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * finger->trail_length);
1298 struct TrailPeerList *iterate;
1299 iterate = finger->head;
1301 while ( i < (finger->trail_length))
1303 memcpy (&peer_list[i], &(iterate->peer), sizeof (struct GNUNET_PeerIdentity));
1304 iterate = iterate->next;
1308 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1309 memcpy (next_hop, &peer_list[0], sizeof (struct GNUNET_PeerIdentity));
1310 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
1311 finger_trail_current_index = 0;
1314 GDS_NEIGHBOURS_send_verify_successor (&my_identity,
1315 &(finger->finger_identity),
1318 finger->trail_length,
1319 finger_trail_current_index);
1322 /* FIXME: Use a random value so that this message is send not at the same
1323 interval as send_find_finger_trail_message. */
1325 next_send_time.rel_value_us =
1326 DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
1327 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1328 DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us /
1329 (current_finger_index + 50));
1332 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_verify_successor_message,
1338 * Task to send a find finger trail message. We attempt to find trail
1339 * to our fingers, successor and predecessor in the network.
1341 * @param cls closure for this task
1342 * @param tc the context under which the task is running
1345 send_find_finger_trail_message (void *cls,
1346 const struct GNUNET_SCHEDULER_TaskContext *tc)
1348 struct FriendInfo *target_friend;
1349 struct GNUNET_TIME_Relative next_send_time;
1350 uint64_t *finger_identity;
1351 unsigned int finger_map_index;
1353 if (1 == current_finger_index)
1355 finger_identity = compute_predecessor_identity();
1360 finger_identity = compute_finger_identity();
1364 target_friend = select_random_friend (NULL);
1366 finger_map_index = current_finger_index;
1367 current_finger_index = ( current_finger_index + 1) % MAX_FINGERS;
1369 if(NULL != target_friend)
1371 /* FIXME: Here I am passing NULL for current source, is it correct?
1372 also, we set the current source only if current_destination_type
1374 GDS_NEIGHBOURS_send_trail_setup (&my_identity, *finger_identity, &(target_friend->id),
1375 NULL, target_friend, 0, NULL, finger_map_index, FRIEND);
1378 /* FIXME: How to decide the correct interval? */
1379 next_send_time.rel_value_us =
1380 DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
1381 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1382 DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us /
1383 (current_finger_index + 10));
1385 find_finger_trail_task =
1386 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_finger_trail_message,
1392 * Method called whenever a peer connects.
1394 * @param cls closure
1395 * @param peer_identity peer identity this notification is about
1398 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity)
1400 struct FriendInfo *friend;
1402 /* Check for connect to self message */
1403 if (0 == memcmp (&my_identity, peer_identity, sizeof (struct GNUNET_PeerIdentity)))
1406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to %s\n", GNUNET_i2s (peer_identity));
1408 /* If peer already exists in our friend_peermap, then exit. */
1409 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (friend_peermap, peer_identity))
1415 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
1418 friend = GNUNET_new (struct FriendInfo);
1419 friend->id = *peer_identity;
1421 GNUNET_assert (GNUNET_OK ==
1422 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
1423 peer_identity, friend,
1424 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1426 /* got a first connection, good time to start with FIND FINGER TRAIL requests... */
1427 if (1 == GNUNET_CONTAINER_multipeermap_size (friend_peermap))
1428 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
1433 * Method called whenever a peer disconnects.
1435 * @param cls closure
1436 * @param peer peer identity this notification is about
1439 handle_core_disconnect (void *cls,
1440 const struct GNUNET_PeerIdentity *peer)
1442 struct FriendInfo *remove_friend;
1443 struct FingerInfo *remove_finger;
1444 struct GNUNET_PeerIdentity key_ret;
1445 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1446 struct TrailPeerList *iterator;
1447 struct GNUNET_PeerIdentity *finger_identity;
1450 /* Check for self message. */
1451 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
1454 /* Search for peer to remove in your friend_peermap. */
1456 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
1458 if (NULL == remove_friend)
1464 iterator = GNUNET_malloc (sizeof (struct TrailPeerList));
1465 finger_identity = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1466 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1467 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
1469 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, &key_ret,
1470 (const void **)&remove_finger))
1472 iterator = remove_finger->head->next;
1473 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(iterator->peer), &(remove_friend->id)))
1475 memcpy (finger_identity, &(remove_finger->finger_identity), sizeof (struct GNUNET_PeerIdentity));
1476 GNUNET_assert (GNUNET_YES ==
1477 GNUNET_CONTAINER_multipeermap_remove (finger_peermap,
1484 /* Remove the friend from friend_peermap. */
1485 GNUNET_assert (GNUNET_YES ==
1486 GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
1493 * To be called on core init/fail.
1495 * @param cls service closure
1496 * @param identity the public identity of this peer
1499 core_init (void *cls,
1500 const struct GNUNET_PeerIdentity *identity)
1502 my_identity = *identity;
1504 /* SUPU TEST CODE */
1505 struct GNUNET_PeerIdentity *print_peer;
1506 print_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1507 memcpy (print_peer, &my_identity, sizeof (struct GNUNET_PeerIdentity));
1508 FPRINTF (stderr,_("\nSUPU %s, %s, %d,my_identity = %s"),
1509 __FILE__, __func__,__LINE__, GNUNET_i2s (print_peer));
1510 /* SUPU TEST CODE ENDS */
1517 * @param destination_peer
1518 * @param existing_trail
1519 * @param trail_length
1522 static struct GNUNET_PeerIdentity *
1523 invert_trail_list (struct GNUNET_PeerIdentity *destination_peer,
1524 struct GNUNET_PeerIdentity *existing_trail,
1525 unsigned int trail_length)
1529 struct GNUNET_PeerIdentity *new_trail;
1532 new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * trail_length);
1534 if (trail_length > 1)
1536 i = trail_length - 2;
1539 memcpy( &new_trail[j], &existing_trail[i], sizeof (struct GNUNET_PeerIdentity));
1544 memcpy (&new_trail[j], destination_peer, sizeof(struct GNUNET_PeerIdentity));
1552 * @param existing_finger
1557 compare_finger_identity (struct GNUNET_PeerIdentity *existing_finger,
1558 struct GNUNET_PeerIdentity *new_finger)
1561 ret = (existing_finger > new_finger) ? 1 :
1562 (existing_finger == new_finger) ? 0 : -1;
1568 * FIXME: Not sure of the logic to find the correct predecessor
1569 * I think logic of this code is wrong everything else seems to be correct.
1570 * Given two finger identities, find the closest predecessor.
1571 * @param existing_predecessor
1572 * @param new_predecessor
1576 compare_predecessor(struct GNUNET_PeerIdentity *existing_predecessor,
1577 struct GNUNET_PeerIdentity *new_predecessor)
1580 ret = (existing_predecessor < new_predecessor) ? 1 :
1581 (existing_predecessor == new_predecessor) ? 0 : -1;
1588 * Add an entry in finger table.
1589 * @param finger_identity Peer identity of finger
1590 * @param finger_trail Trail to reach the finger
1591 * @param trail_length Number of peers in the trail.
1592 * @param finger_map_index Index in finger peer map.
1595 void finger_table_add (struct GNUNET_PeerIdentity *finger_identity,
1596 struct GNUNET_PeerIdentity *finger_trail,
1597 unsigned int trail_length,
1598 unsigned int finger_map_index)
1600 struct FingerInfo *new_finger_entry;
1601 struct GNUNET_PeerIdentity key_ret;
1603 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1604 struct FingerInfo *existing_finger;
1607 /* SUPU Here we trying to check if we already have an entry. If yes then we
1608 can keep two trails for redundant routing. if they are different then we
1609 need to choose the closest one. and remove the other one. */
1610 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1612 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
1614 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, &key_ret,
1615 (const void **)&existing_finger))
1617 if ((finger_map_index == existing_finger->finger_map_index))
1619 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity),finger_identity))
1621 /* FIXME: Here you should check if the trail is same. If yes then don't add the entry. it
1622 seems to be very suboptimal. */
1623 if ((existing_finger->trail_length) == trail_length)
1625 struct TrailPeerList *iterate;
1626 iterate = existing_finger->head;
1629 while (k < trail_length)
1631 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(iterate->peer), &finger_trail[k]))
1634 iterate = iterate->next;
1637 if (k == trail_length)
1647 if (finger_map_index == 1)
1649 ret = compare_predecessor (&(existing_finger->finger_identity),
1655 ret = compare_finger_identity (&(existing_finger->finger_identity),
1660 GNUNET_assert (GNUNET_YES ==
1661 GNUNET_CONTAINER_multipeermap_remove (finger_peermap,
1662 &(existing_finger->finger_identity),
1676 new_finger_entry = GNUNET_malloc (sizeof (struct FingerInfo));
1677 memcpy (&(new_finger_entry->finger_identity), finger_identity, sizeof (struct GNUNET_PeerIdentity));
1678 new_finger_entry->finger_map_index = finger_map_index;
1680 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, finger_identity))
1682 /* I am the finger */
1683 new_finger_entry->trail_length = 0;
1688 while (i < trail_length)
1690 struct TrailPeerList *element;
1691 element = GNUNET_malloc (sizeof (struct TrailPeerList));
1692 element->next = NULL;
1693 element->prev = NULL;
1695 memcpy (&(element->peer), &finger_trail[i], sizeof(struct GNUNET_PeerIdentity));
1696 GNUNET_CONTAINER_DLL_insert_tail(new_finger_entry->head, new_finger_entry->tail, element);
1699 new_finger_entry->trail_length = trail_length;
1702 /* FIXME: Here we are keeping multiple hashmap option so that there are
1703 multiple routes to reach to same finger, redundant routing.
1704 * Also same peers could be our fingers for different finger map index
1705 * Should we handle the case where we have same fingers at the different
1706 * finger index but with different trail to reach. */
1707 GNUNET_assert (GNUNET_OK ==
1708 GNUNET_CONTAINER_multipeermap_put (finger_peermap,
1709 &(new_finger_entry->finger_identity),
1711 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1713 if (1 == GNUNET_CONTAINER_multipeermap_size (finger_peermap)
1714 && (new_finger_entry->finger_map_index!= 1))
1716 verify_successor = GNUNET_SCHEDULER_add_now (&send_verify_successor_message, NULL);
1722 * Compare two peer identities.
1723 * @param p1 Peer identity
1724 * @param p2 Peer identity
1725 * @return 1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2.
1728 compare_peer_id (const void *p1, const void *p2)
1730 struct Sorting_List *p11;
1731 struct Sorting_List *p22;
1733 p11 = GNUNET_malloc (sizeof (struct Sorting_List));
1734 p22 = GNUNET_malloc (sizeof (struct Sorting_List));
1735 p11 = (struct Sorting_List *)p1;
1736 p22 = (struct Sorting_List *)p2;
1737 ret = ( (p11->peer_id) > (p22->peer_id) ) ? 1 :
1738 ( (p11->peer_id) == (p22->peer_id) ) ? 0 : -1;
1744 * Return the successor of value in all_known_peers.
1745 * @param all_known_peers list of all the peers
1746 * @param value value we have to search in the all_known_peers.
1749 static struct Sorting_List *
1750 find_closest_successor(struct Sorting_List *all_known_peers, uint64_t value,
1759 middle = (first + last)/2;
1761 while(first <= last)
1763 if(all_known_peers[middle].peer_id < value)
1767 else if(all_known_peers[middle].peer_id == value)
1769 if(middle == (size -1))
1771 return &all_known_peers[0];
1775 return &all_known_peers[middle+1];
1783 middle = (first + last)/2;
1790 * Find closest successor for the value.
1791 * @param value Value for which we are looking for successor
1792 * @param current_destination NULL if my_identity is successor else finger/friend
1794 * @param type Next destination type
1795 * @return Peer identity of next destination i.e. successor of value.
1797 static struct GNUNET_PeerIdentity *
1798 find_successor (uint64_t value, struct GNUNET_PeerIdentity *current_destination,
1799 enum current_destination_type *type)
1801 struct GNUNET_CONTAINER_MultiPeerMapIterator *friend_iter;
1802 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1803 struct GNUNET_PeerIdentity key_ret;
1804 struct FriendInfo *friend;
1805 struct FingerInfo *finger;
1806 unsigned int finger_index;
1807 unsigned int friend_index;
1808 struct Sorting_List *successor;
1812 /* 2 is added in size for my_identity and value which will part of all_known_peers. */
1813 size = GNUNET_CONTAINER_multipeermap_size (friend_peermap)+
1814 GNUNET_CONTAINER_multipeermap_size (finger_peermap)+
1817 struct Sorting_List all_known_peers[size];
1820 for (k = 0; k < size; k++)
1821 all_known_peers[k].peer_id = 0;
1823 /* Copy your identity at 0th index in all_known_peers. */
1825 memcpy (&(all_known_peers[j].peer_id), &my_identity, sizeof (uint64_t));
1826 all_known_peers[j].type = MY_ID;
1827 all_known_peers[j].data = 0;
1831 all_known_peers[j].peer_id = value;
1832 all_known_peers[j].type = VALUE;
1833 all_known_peers[j].data = 0;
1836 /* Iterate over friend peer map and copy all the elements into array. */
1837 friend_iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1838 for (friend_index = 0; friend_index < GNUNET_CONTAINER_multipeermap_size (friend_peermap); friend_index++)
1840 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(friend_iter,&key_ret,(const void **)&friend))
1842 memcpy (&(all_known_peers[j].peer_id), &(friend->id), sizeof (uint64_t));
1843 all_known_peers[j].type = FRIEND;
1844 all_known_peers[j].data = friend;
1849 /* Iterate over finger map and copy all the entries into all_known_peers array. */
1850 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1851 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
1853 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(finger_iter,&key_ret,(const void **)&finger))
1855 memcpy (&(all_known_peers[j].peer_id), &(finger->finger_identity), sizeof (uint64_t));
1856 all_known_peers[j].type = FINGER;
1857 all_known_peers[j].data = finger;
1862 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
1863 GNUNET_CONTAINER_multipeermap_iterator_destroy (friend_iter);
1865 qsort (&all_known_peers, size, sizeof (struct Sorting_List), &compare_peer_id);
1867 /* search value in all_known_peers array. */
1868 successor = find_closest_successor (all_known_peers, value, size);
1870 if (successor->type == MY_ID)
1875 else if (successor->type == FRIEND)
1878 struct FriendInfo *target_friend;
1879 target_friend = (struct FriendInfo *)successor->data;
1880 memcpy (current_destination, &(target_friend->id), sizeof (struct GNUNET_PeerIdentity));
1881 return current_destination;
1883 else if (successor->type == FINGER)
1886 struct GNUNET_PeerIdentity *next_hop;
1887 struct FingerInfo *finger;
1888 struct TrailPeerList *iterator;
1889 iterator = GNUNET_malloc (sizeof (struct TrailPeerList));
1890 finger = successor->data;
1891 iterator = finger->head;
1892 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1893 memcpy (next_hop, &(iterator->peer), sizeof (struct GNUNET_PeerIdentity));
1894 memcpy (current_destination, &(finger->finger_identity), sizeof (struct GNUNET_PeerIdentity));
1906 * Send a get message to selected target friend. If target friend in NULL,
1907 * then search for a target friend.
1908 * @param block_type type of the block
1909 * @param options routing options
1910 * @param desired_replication_level desired replication count
1911 * @param hop_count how many hops did this request traverse so far?
1912 * @param get_peer_path Peer list to reach to final destination which contains the data.
1913 * @param get_path_length Total numbers of peer in @a get_path
1914 * @param key Key key for the content
1915 * @param target_peer Next peer to forward the message to.
1916 * @param current_destination Peer which will get this message.
1917 * @param current_source Peer for @a current_destination is the finger.
1918 * @param current_dest_type Type of current destination can be either FRIEND or FINGER
1921 GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type block_type,
1922 enum GNUNET_DHT_RouteOption options,
1923 uint32_t desired_replication_level,
1925 struct GNUNET_PeerIdentity *get_peer_path,
1926 unsigned int get_path_length,
1927 struct GNUNET_HashCode *key,
1928 struct GNUNET_PeerIdentity *target_peer,
1929 struct GNUNET_PeerIdentity *current_destination,
1930 struct GNUNET_PeerIdentity *current_source,
1931 enum current_destination_type current_dest_type)
1933 struct PeerGetMessage *get_request;
1934 struct P2PPendingMessage *pending;
1935 struct GNUNET_PeerIdentity *get_path;
1936 struct FriendInfo *target_friend;
1937 struct GNUNET_PeerIdentity *next_hop;
1938 struct GNUNET_PeerIdentity *current_dest;
1939 enum current_destination_type dest_type;
1943 FPRINTF (stderr,_("\nSUPU %s, %s, %d"),__FILE__, __func__,__LINE__);
1944 msize = sizeof (struct PeerGetMessage) +
1945 (get_path_length * sizeof (struct GNUNET_PeerIdentity));
1947 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1953 memcpy (&key_value, key, sizeof (uint64_t));
1955 if (NULL == target_peer)
1957 FPRINTF (stderr,_("\nSUPU %s, %s, %d"),__FILE__, __func__,__LINE__);
1958 current_dest = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1960 next_hop = find_successor (key_value, current_dest, &dest_type);
1962 if (dest_type == MY_ID)
1964 FPRINTF (stderr,_("\nSUPU %s, %s, %d"),__FILE__, __func__,__LINE__);
1965 get_path = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1966 memcpy (get_path, &my_identity, sizeof (struct GNUNET_PeerIdentity));
1967 get_path_length = 1;
1968 GDS_DATACACHE_handle_get (key,block_type, NULL, 0,
1969 NULL, 0, get_path_length, get_path, 0, NULL,&my_identity);
1974 if (dest_type == FINGER)
1976 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
1978 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
1980 current_dest_type = dest_type;
1984 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer);
1986 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1987 pending->importance = 0; /* FIXME */
1988 get_request = (struct PeerGetMessage *) &pending[1];
1989 pending->msg = &get_request->header;
1990 get_request->header.size = htons (msize);
1991 get_request->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
1992 get_request->get_path_length = htonl (get_path_length);
1993 get_request->key = *key;
1994 if (current_destination != NULL)
1995 memcpy (&(get_request->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity));
1997 memcpy (&(get_request->current_destination), current_dest, sizeof (struct GNUNET_PeerIdentity));
1998 /* FIXME: Is this comparison correct? */
1999 if (current_source != NULL)
2000 memcpy (&(get_request->current_source), current_source, sizeof (struct GNUNET_PeerIdentity));
2001 get_request->current_dest_type = htonl (current_dest_type);
2002 get_path = (struct GNUNET_PeerIdentity *) &get_request[1];
2003 if (get_path_length > 0)
2004 memcpy (get_path, get_peer_path, get_path_length * sizeof (struct GNUNET_PeerIdentity));
2005 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2006 target_friend->pending_count++;
2007 process_friend_queue (target_friend);
2013 * FIXME: Here you should update the fields of struct PeerGetResultMessage.
2014 * At the end of this message you should add the data and get path and send
2015 * to the original requesting client. and there you should call GDS_CLIENT_handle_reply
2016 * with correct parameter.
2019 * @param get_path_length
2021 * @param put_path_length
2028 GDS_NEIGHBOURS_datacache_get (struct GNUNET_TIME_Absolute expiration,
2029 const struct GNUNET_HashCode *key,
2030 unsigned int get_path_length,
2031 const struct GNUNET_PeerIdentity *get_path,
2032 unsigned int put_path_length,
2033 const struct GNUNET_PeerIdentity *put_path,
2034 enum GNUNET_BLOCK_Type type, size_t data_size,
2037 /* Here you don't have the get path and get path length. you should call
2038 some function get those values and update the message and send them. */
2043 * TODO: In case of put, you add the peer in the peer list in handle_dht_p2p_put.
2044 * Verify that the addition is correct and we are adding peers correctly and incrementing
2045 * the trail length correctly.
2046 * Handle a put request from client file. If I am the final destination,
2047 * do a put else forward the message to next peer.
2048 * @param block_type type of the block
2049 * @param options routing options
2050 * @param desired_replication_level desired replication count, 0 for current
2051 * implementation of X-Vine.
2052 * @param expiration_time when does the content expire
2053 * @param hop_count how many hops has this message traversed so far
2054 * @param key key for the content
2055 * @param put_path_length number of entries in @a put_path
2056 * @param put_path peers this request has traversed so far (if tracked)
2057 * @param data payload to store
2058 * @param data_size number of bytes in @a data
2059 * @param current_destination intermediate destination of the packet.
2060 * @param current_source source for which @a current_destination is destination.
2061 * @param dest_type type of @a current_destination.
2062 * @param target_peer_id Next peer to forward the message to.
2065 GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type block_type,
2066 enum GNUNET_DHT_RouteOption options,
2067 uint32_t desired_replication_level,
2068 struct GNUNET_TIME_Absolute expiration_time,
2070 const struct GNUNET_HashCode *key,
2071 unsigned int put_path_length,
2072 struct GNUNET_PeerIdentity *put_path,
2073 const void *data, size_t data_size,
2074 struct GNUNET_PeerIdentity *current_destination,
2075 struct GNUNET_PeerIdentity *current_source,
2076 enum current_destination_type dest_type,
2077 struct GNUNET_PeerIdentity *target_peer)
2079 struct PeerPutMessage *ppm;
2080 struct P2PPendingMessage *pending;
2081 struct FriendInfo *target_friend;
2082 struct GNUNET_PeerIdentity *pp;
2083 struct GNUNET_PeerIdentity *next_hop;
2084 struct GNUNET_PeerIdentity *current_dest;
2085 enum current_destination_type curr_dest_type;
2089 msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
2090 sizeof (struct PeerPutMessage);
2092 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2094 put_path_length = 0;
2095 msize = data_size + sizeof (struct PeerPutMessage);
2098 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2104 memcpy (&key_value, key, sizeof (uint64_t));
2106 if (target_peer == NULL)
2108 FPRINTF (stderr,_("\nSUPU %s, %s, %d"),__FILE__, __func__,__LINE__);
2109 curr_dest_type = MY_ID;
2110 current_dest = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2111 next_hop = find_successor (key_value, current_dest, &curr_dest_type);
2112 if (curr_dest_type == MY_ID)
2114 /* FIXME: Choose one place to do datacache_put. I am doing put only if its
2115 destination so I will do no put operation
2116 in the client file.*/
2117 FPRINTF (stderr,_("\nSUPU %s, %s, %d"),__FILE__, __func__,__LINE__);
2118 GDS_DATACACHE_handle_put (expiration_time, key, put_path_length, put_path,
2119 block_type, data_size, data);
2124 /* Find the friend corresponding to next_hop */
2125 if (curr_dest_type == FINGER)
2127 FPRINTF (stderr,_("\nSUPU %s, %s, %d"),__FILE__, __func__,__LINE__);
2128 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2130 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2132 dest_type = curr_dest_type;
2135 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer);
2137 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2138 pending->importance = 0; /* FIXME */
2139 pending->timeout = expiration_time;
2140 ppm = (struct PeerPutMessage *) &pending[1];
2141 pending->msg = &ppm->header;
2142 ppm->header.size = htons (msize);
2143 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
2144 ppm->options = htonl (options);
2145 ppm->block_type = htonl (block_type);
2146 ppm->hop_count = htonl (hop_count + 1);
2147 ppm->desired_replication_level = htonl (desired_replication_level);
2148 ppm->put_path_length = htonl (put_path_length);
2149 ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
2150 ppm->current_destination_type = dest_type;
2151 /* FIXME: Here I am checking if we have a value in current_source then only copy.
2152 I am not sure if this checking is correct or not. */
2153 if (current_source != NULL)
2155 FPRINTF (stderr,_("\nSUPU %s, %s, %d"),__FILE__, __func__,__LINE__);
2156 memcpy (&(ppm->current_source), current_source, sizeof (struct GNUNET_PeerIdentity));
2159 FPRINTF (stderr,_("\nSUPU %s, %s, %d"),__FILE__, __func__,__LINE__);
2160 if (current_destination != NULL)
2161 memcpy (&(ppm->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity));
2163 memcpy (&(ppm->current_destination), current_dest, sizeof (struct GNUNET_PeerIdentity));
2164 ppm->current_destination_type = htonl (dest_type);
2167 pp = (struct GNUNET_PeerIdentity *) &ppm[1];
2168 /* FIXME: Is this comparison correct? Do we need this comparison. What happens
2169 in the case put_path_length is 0 and put_path is NULL, then at run time
2170 memcpy will fail. And I am not sure if comparing NULL is correct or not. */
2171 if (put_path_length != 0)
2173 memcpy (pp, put_path,
2174 sizeof (struct GNUNET_PeerIdentity) * put_path_length);
2176 memcpy (&pp[put_path_length], data, data_size);
2177 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2178 target_friend->pending_count++;
2179 process_friend_queue (target_friend);
2184 * Send get result back to requesting client.
2185 * @param expiration when will the reply expire
2186 * @param key the query this reply is for
2187 * @param get_path_length number of peers in @a get_path
2188 * @param get_path path the reply took on get
2189 * @param put_path_length number of peers in @a put_path
2190 * @param put_path path the reply took on put
2191 * @param type type of the reply
2192 * @param data_size number of bytes in @a data
2193 * @param data application payload data
2195 * @param get_path_length
2198 GDS_NEIGHBOURS_send_get_result (struct GNUNET_TIME_Absolute expiration,
2199 const struct GNUNET_HashCode *key,
2200 unsigned int put_path_length,
2201 const struct GNUNET_PeerIdentity *put_path,
2202 enum GNUNET_BLOCK_Type type, size_t data_size,
2204 struct GNUNET_PeerIdentity *get_path,
2205 unsigned int get_path_length,
2206 unsigned int current_path_index,
2207 struct GNUNET_PeerIdentity *next_hop,
2208 struct GNUNET_PeerIdentity *source_peer)
2210 struct PeerGetResultMessage *get_result;
2211 struct GNUNET_PeerIdentity *get_result_path;
2212 struct GNUNET_PeerIdentity *pp;
2213 struct P2PPendingMessage *pending;
2214 struct FriendInfo *target_friend;
2217 msize = get_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
2218 sizeof (struct PeerPutMessage);
2220 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2226 if (current_path_index == 0)
2228 FPRINTF (stderr,_("\nSUPU %s, %s, %d"),__FILE__, __func__,__LINE__);
2229 GDS_CLIENTS_handle_reply (expiration, key, get_path_length, get_path, put_path_length,
2230 put_path, type, data_size, data);
2233 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2234 pending->importance = 0;
2235 get_result = (struct PeerGetResultMessage *)&pending[1];
2236 pending->msg = &get_result->header;
2237 get_result->header.size = htons (msize);
2238 get_result->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT);
2239 get_result->current_path_index = current_path_index;
2240 get_result->key = *key;
2241 memcpy (&(get_result->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
2242 get_result->expiration_time = expiration;
2244 get_result_path = (struct GNUNET_PeerIdentity *)&get_result[1];
2245 memcpy (get_result_path, get_path,
2246 sizeof (struct GNUNET_PeerIdentity) * get_path_length);
2247 memcpy (&get_result_path[get_path_length], data, data_size);
2248 /* FIXME: Is this correct? */
2249 pp = (struct GNUNET_PeerIdentity *)&get_result_path[1];
2250 memcpy (pp, put_path,sizeof (struct GNUNET_PeerIdentity) * put_path_length);
2252 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2253 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2254 target_friend->pending_count++;
2255 process_friend_queue (target_friend);
2267 handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer,
2268 const struct GNUNET_MessageHeader *message)
2270 /* If you are the source, go back to the client file and there search for
2271 the requesting client and send back the result. */
2272 struct PeerGetResultMessage *get_result;
2273 struct GNUNET_PeerIdentity *get_path;
2274 struct GNUNET_PeerIdentity *put_path;
2276 size_t payload_size;
2278 unsigned int getlen;
2279 unsigned int putlen;
2280 int current_path_index;
2282 msize = ntohs (message->size);
2283 if (msize < sizeof (struct PeerGetResultMessage))
2285 GNUNET_break_op (0);
2289 get_result = (struct PeerGetResultMessage *)message;
2290 getlen = ntohl (get_result->get_path_length);
2291 putlen = ntohl (get_result->put_path_length);
2294 sizeof (struct PeerGetResultMessage) +
2295 getlen * sizeof (struct GNUNET_PeerIdentity) +
2296 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
2298 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity) ||
2300 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))))
2302 GNUNET_break_op (0);
2306 get_path = (struct GNUNET_PeerIdentity *) &get_result[1];
2307 payload = &get_path[getlen];
2308 payload_size = msize - (sizeof (struct PeerGetResultMessage) +
2309 getlen * sizeof (struct GNUNET_PeerIdentity));
2310 /* FIXME: Check if its correct or not. */
2312 put_path = &get_path[1];
2314 current_path_index = ntohl (get_result->current_path_index);
2315 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &(get_path[0]))))
2317 //GDS_CLIENTS_process_get_result();
2318 GDS_CLIENTS_handle_reply (get_result->expiration_time, &(get_result->key),
2319 getlen, get_path, putlen,
2320 put_path, get_result->type, payload_size, payload);
2325 struct GNUNET_PeerIdentity *next_hop;
2326 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2327 if (current_path_index != 0)
2328 current_path_index--;
2329 memcpy (next_hop, &get_path[current_path_index], sizeof (struct GNUNET_PeerIdentity));
2331 GDS_NEIGHBOURS_send_get_result (get_result->expiration_time, &(get_result->key),
2333 get_result->type, payload_size,payload,
2334 get_path, getlen,current_path_index,
2335 next_hop, &(get_result->source_peer));
2338 return GNUNET_SYSERR;
2343 * FIXME: Can refactor the code where we are setting the current source and
2345 * Core handler for p2p put requests.
2347 * @param cls closure
2348 * @param peer sender of the request
2349 * @param message message
2350 * @param peer peer identity this notification is about
2351 * @return #GNUNET_OK to keep the connection open,
2352 * #GNUNET_SYSERR to close it (signal serious error)
2355 handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer,
2356 const struct GNUNET_MessageHeader *message)
2358 struct PeerPutMessage *put;
2359 struct GNUNET_PeerIdentity *put_path;
2360 enum GNUNET_DHT_RouteOption options;
2361 enum current_destination_type current_dst_type;
2362 struct GNUNET_PeerIdentity *current_destination;
2363 struct GNUNET_PeerIdentity *current_source;
2364 struct GNUNET_PeerIdentity *next_hop;
2365 struct GNUNET_HashCode test_key;
2368 size_t payload_size;
2372 msize = ntohs (message->size);
2373 if (msize < sizeof (struct PeerPutMessage))
2375 GNUNET_break_op (0);
2379 put = (struct PeerPutMessage *) message;
2380 putlen = ntohl (put->put_path_length);
2383 sizeof (struct PeerPutMessage) +
2384 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
2386 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2388 GNUNET_break_op (0);
2392 put_path = (struct GNUNET_PeerIdentity *) &put[1];
2393 payload = &put_path[putlen];
2394 options = ntohl (put->options);
2395 payload_size = msize - (sizeof (struct PeerPutMessage) +
2396 putlen * sizeof (struct GNUNET_PeerIdentity));
2398 switch (GNUNET_BLOCK_get_key (GDS_block_context, ntohl (put->block_type),
2399 payload, payload_size, &test_key))
2402 if (0 != memcmp (&test_key, &put->key, sizeof (struct GNUNET_HashCode)))
2404 char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key));
2405 GNUNET_break_op (0);
2406 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2407 "PUT with key `%s' for block with key %s\n",
2408 put_s, GNUNET_h2s_full (&test_key));
2409 GNUNET_free (put_s);
2414 GNUNET_break_op (0);
2417 /* cannot verify, good luck */
2421 if (ntohl (put->block_type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
2423 switch (GNUNET_BLOCK_evaluate (GDS_block_context,
2424 ntohl (put->block_type),
2426 NULL, 0, /* bloom filer */
2427 NULL, 0, /* xquery */
2428 payload, payload_size))
2430 case GNUNET_BLOCK_EVALUATION_OK_MORE:
2431 case GNUNET_BLOCK_EVALUATION_OK_LAST:
2434 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
2435 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
2436 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
2437 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
2438 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
2439 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
2441 GNUNET_break_op (0);
2446 struct GNUNET_PeerIdentity pp[putlen + 1];
2448 /* extend 'put path' by sender */
2449 /* FIXME: Check what are we doing here? */
2450 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
2452 memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity));
2459 current_destination = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2460 memcpy (current_destination, &(put->current_destination), sizeof (struct GNUNET_PeerIdentity));
2461 current_dst_type = ntohl (put->current_destination_type);
2462 memcpy (&key_value, &(put->key), sizeof (uint64_t));
2463 current_source = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2464 if (current_dst_type == FRIEND)
2466 next_hop = find_successor (key_value, current_destination, ¤t_dst_type);
2467 if (current_dst_type == FINGER)
2469 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2472 current_source = NULL;
2474 else if (current_dst_type == FINGER)
2476 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, current_destination))
2478 next_hop = find_successor (key_value, current_destination, ¤t_dst_type);
2479 if (current_dst_type == FINGER)
2481 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2484 current_source = NULL;
2488 next_hop = GDS_ROUTING_search (&(put->current_source), current_destination, peer);
2489 memcpy (current_source, &(put->current_source), sizeof (struct GNUNET_PeerIdentity));
2490 current_dst_type = FINGER;
2494 if (current_dst_type == MY_ID)
2496 GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time),
2497 &(put->key),putlen, pp, ntohl (put->block_type),
2498 payload_size, payload);
2503 GDS_CLIENTS_process_put (options,
2504 ntohl (put->block_type),
2505 ntohl (put->hop_count),
2506 ntohl (put->desired_replication_level),
2508 GNUNET_TIME_absolute_ntoh (put->expiration_time),
2513 GDS_NEIGHBOURS_handle_put (ntohl (put->block_type),ntohl (put->options),
2514 ntohl (put->desired_replication_level),
2515 GNUNET_TIME_absolute_ntoh (put->expiration_time),
2516 ntohl (put->hop_count),&put->key, putlen,
2517 pp, payload, payload_size,
2518 current_destination, current_source,current_dst_type, next_hop);
2521 return GNUNET_SYSERR;
2526 * Core handler for p2p get requests.
2528 * @param cls closure
2529 * @param peer sender of the request
2530 * @param message message
2531 * @return #GNUNET_OK to keep the connection open,
2532 * #GNUNET_SYSERR to close it (signal serious error)
2535 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
2536 const struct GNUNET_MessageHeader *message)
2538 struct PeerGetMessage *get;
2539 struct GNUNET_PeerIdentity *current_destination;
2541 enum current_destination_type current_dest_type;
2542 struct GNUNET_PeerIdentity *next_hop;
2543 struct GNUNET_PeerIdentity *get_path;
2544 enum GNUNET_BLOCK_Type block_type;
2545 enum GNUNET_DHT_RouteOption options;
2547 unsigned int get_length;
2549 msize = ntohs (message->size);
2550 if (msize < sizeof (struct PeerGetMessage))
2552 GNUNET_break_op (0);
2556 get = (struct PeerGetMessage *)message;
2557 get_length = ntohl (get->get_path_length);
2558 get_path = (struct GNUNET_PeerIdentity *)&get[1];
2561 sizeof (struct PeerGetMessage) +
2562 get_length * sizeof (struct GNUNET_PeerIdentity)) ||
2564 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2566 GNUNET_break_op (0);
2570 current_destination = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2571 memcpy (current_destination, &(get->current_destination), sizeof (struct GNUNET_PeerIdentity));
2572 memcpy (&key_value, &(get->key), sizeof (uint64_t));
2573 current_dest_type = ntohl (get->current_dest_type);
2574 block_type = ntohl (get->block_type);
2575 options = ntohl (get->options);
2576 struct GNUNET_PeerIdentity *current_source;
2577 current_source = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2579 if (current_dest_type == FRIEND)
2581 next_hop = find_successor (key_value, current_destination, ¤t_dest_type);
2582 if (current_dest_type == FINGER)
2584 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2587 current_source = NULL;
2589 else if (current_dest_type == FINGER)
2591 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, current_destination))
2593 next_hop = find_successor (key_value, current_destination, ¤t_dest_type);
2594 if (current_dest_type == FINGER)
2596 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2599 current_source = NULL;
2603 next_hop = GDS_ROUTING_search (&(get->current_source), current_destination, peer);
2604 current_dest_type = FINGER;
2608 /* Add sender to get path */
2609 struct GNUNET_PeerIdentity gp[get_length + 1];
2610 memcpy (gp, get_path, get_length * sizeof (struct GNUNET_PeerIdentity));
2611 gp[get_length + 1] = *peer;
2612 get_length = get_length + 1;
2614 if (current_dest_type == MY_ID)
2616 struct GNUNET_PeerIdentity final_get_path[get_length+1];
2617 memcpy (final_get_path, gp, get_length * sizeof (struct GNUNET_PeerIdentity));
2618 memcpy (&final_get_path[get_length+1], &my_identity, sizeof (struct GNUNET_PeerIdentity));
2619 get_length = get_length + 1;
2620 struct GNUNET_PeerIdentity *next_hop;
2621 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2622 memcpy (next_hop, &final_get_path[get_length-2], sizeof (struct GNUNET_PeerIdentity));
2623 GDS_DATACACHE_handle_get (&(get->key),(get->block_type), NULL, 0, NULL, 0,
2624 get_length, final_get_path,get_length - 1,next_hop, &my_identity);
2630 GDS_NEIGHBOURS_handle_get (block_type, options, get->desired_replication_level,
2632 get_length, &(get->key),next_hop,
2633 current_destination, &(get->current_source),current_dest_type);
2637 return GNUNET_SYSERR;
2643 * Send tral rejection message
2644 * @param source_peer Source peer which wants to set up the trail.
2645 * @param finger_identity Finger identity to which it want to setup the trail.
2646 * @param congested_peer Peer which has send trail rejection message
2647 * @param next_hop Peer to which this message should be forwarded.
2648 * @param finger_map_index
2649 * @param trail_peer_list
2650 * @param trail_length
2653 GDS_NEIGHBOURS_send_trail_rejection_message(struct GNUNET_PeerIdentity *source_peer,
2654 uint64_t finger_identity,
2655 struct GNUNET_PeerIdentity *congested_peer,
2656 const struct GNUNET_PeerIdentity *next_hop,
2657 unsigned int finger_map_index,
2658 struct GNUNET_PeerIdentity *trail_peer_list,
2659 unsigned int trail_length)
2661 struct PeerTrailRejectionMessage *trail_rejection;
2662 struct GNUNET_PeerIdentity *trail_list;
2663 struct P2PPendingMessage *pending;
2664 struct FriendInfo *target_friend;
2667 msize = sizeof (struct PeerTrailRejectionMessage);
2669 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2670 pending->importance = 0; /* FIXME */
2671 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
2672 trail_rejection = (struct PeerTrailRejectionMessage *) &pending[1];
2673 pending->msg = &trail_rejection->header;
2674 trail_rejection->header.size = htons (msize);
2675 trail_rejection->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
2676 memcpy (&(trail_rejection->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
2677 memcpy (&(trail_rejection->congested_peer), congested_peer, sizeof (struct GNUNET_PeerIdentity));
2678 memcpy (&(trail_rejection->finger_identity), &finger_identity, sizeof (uint64_t));
2679 trail_rejection->finger_map_index = htonl(finger_map_index);
2680 trail_rejection->trail_length = htonl (trail_length);
2682 trail_list = (struct GNUNET_PeerIdentity *)&trail_rejection[1];
2683 memcpy (trail_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
2685 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2686 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2687 target_friend->pending_count++;
2688 process_friend_queue (target_friend);
2693 * Handle a PeerTrailSetupMessage.
2694 * @param cls closure
2695 * @param message message
2696 * @param peer peer identity this notification is about
2697 * @return GNUNET_OK on success, GNUNET_SYSERR on error
2700 handle_dht_p2p_trail_setup(void *cls, const struct GNUNET_PeerIdentity *peer,
2701 const struct GNUNET_MessageHeader *message)
2703 struct PeerTrailSetupMessage *trail_setup;
2704 struct GNUNET_PeerIdentity *next_hop;
2705 struct FriendInfo *target_friend;
2706 struct GNUNET_PeerIdentity *current_destination;
2707 struct GNUNET_PeerIdentity *trail_peer_list;
2708 enum current_destination_type current_dest_type;
2709 struct GNUNET_PeerIdentity *next_peer;
2710 unsigned int trail_length;
2711 uint32_t current_trail_index;
2712 unsigned int finger_map_index;
2713 uint64_t destination_finger_value;
2716 msize = ntohs (message->size);
2717 if (msize < sizeof (struct PeerTrailSetupMessage))
2719 GNUNET_break_op (0);
2723 trail_setup = (struct PeerTrailSetupMessage *) message;
2724 trail_length = ntohl (trail_setup->trail_length);
2726 if ((msize < sizeof (struct PeerTrailSetupMessage) +
2727 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
2729 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2731 GNUNET_break_op (0);
2735 current_dest_type = ntohl (trail_setup->current_destination_type);
2736 finger_map_index = ntohl (trail_setup->finger_map_index);
2737 trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_setup[1];
2738 destination_finger_value = trail_setup->destination_finger;
2739 current_destination = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2740 memcpy (current_destination, &(trail_setup->current_destination), sizeof (struct GNUNET_PeerIdentity));
2743 each peer maintains a list of trail fail list. there it stores an entry with
2744 source, finger identity it was trying, hop which rejected. it again call
2745 select_random_friend but does not consider me. and starts trail setup
2747 if (GDS_ROUTING_size() > 1)
2749 /* Setup the trail rejection message and send the message to peer. */
2750 /* FIXME: you need to pass the trail, trail length and finger map index. */
2751 GDS_NEIGHBOURS_send_trail_rejection_message (&(trail_setup->source_peer),
2752 trail_setup->destination_finger,
2753 &my_identity, peer, finger_map_index,
2754 trail_peer_list, trail_length);
2756 /* Find the next hop to send the packet to. */
2757 if (current_dest_type == FRIEND)
2759 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_setup->current_destination),
2762 next_hop = find_successor (destination_finger_value, current_destination, &(current_dest_type));
2765 return GNUNET_SYSERR;
2767 else if (current_dest_type == FINGER)
2769 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&(trail_setup->current_destination),
2772 next_hop = GDS_ROUTING_search (&(trail_setup->current_source),
2773 &(trail_setup->current_destination), peer);
2774 /* As an optimization, find the successor from the find successor and
2775 compare both the ids to find the closest peer. */
2779 next_hop = find_successor (destination_finger_value, current_destination, &(current_dest_type));
2783 /* Add yourself to the trail list and increment the trail length. */
2784 struct GNUNET_PeerIdentity *peer_list;
2785 peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * (trail_length + 1));
2786 if ( trail_length > 0)
2788 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
2790 memcpy (&peer_list[trail_length], &my_identity, sizeof (struct GNUNET_PeerIdentity));
2793 if (current_dest_type == MY_ID ||
2794 (0 == GNUNET_CRYPTO_cmp_peer_identity(next_hop, &(trail_setup->source_peer))))
2796 struct GNUNET_PeerIdentity *source_peer;
2797 source_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2798 memcpy (source_peer, &(trail_setup->source_peer), sizeof (struct GNUNET_PeerIdentity));
2800 current_trail_index = trail_length - 1;
2801 next_peer= GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2802 if (current_trail_index == 0)
2804 memcpy (next_peer, &(trail_setup->source_peer), sizeof (struct GNUNET_PeerIdentity));
2808 memcpy (next_peer, &trail_peer_list[current_trail_index-1], sizeof (struct GNUNET_PeerIdentity));
2811 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_peer);
2812 GNUNET_free (next_peer);
2814 if (0 == trail_setup->finger_map_index)
2816 struct GNUNET_PeerIdentity *new_trail_list;
2817 new_trail_list = invert_trail_list (source_peer, peer_list, trail_length);
2818 finger_table_add (source_peer, new_trail_list, trail_length, 1);
2821 GDS_NEIGHBOURS_send_trail_setup_result (&(trail_setup->source_peer),
2823 target_friend, trail_length,
2824 peer_list, current_trail_index,
2831 struct GNUNET_PeerIdentity *current_source;
2832 current_source = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2833 if (current_dest_type == FINGER)
2835 memcpy (current_source, &my_identity, sizeof (struct GNUNET_PeerIdentity));
2838 current_source = NULL;
2840 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2841 /* FiXME: Is it correct to use null value for current source. */
2842 GDS_NEIGHBOURS_send_trail_setup (&(trail_setup->source_peer),
2843 trail_setup->destination_finger,
2844 current_destination,current_source,
2845 target_friend, trail_length, peer_list,
2846 finger_map_index, current_dest_type);
2851 return GNUNET_SYSERR;
2856 * Core handle for p2p trail construction result messages.
2857 * @param cls closure
2858 * @param message message
2859 * @param peer peer identity this notification is about
2860 * @return GNUNET_OK on success, GNUNET_SYSERR on error
2863 handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer,
2864 const struct GNUNET_MessageHeader *message)
2866 struct PeerTrailSetupResultMessage *trail_result;
2867 struct GNUNET_PeerIdentity *trail_peer_list;
2868 struct GNUNET_PeerIdentity *next_hop;
2869 struct FriendInfo *target_friend;
2870 unsigned int current_trail_index;
2871 unsigned int finger_map_index;
2872 unsigned int trail_length;
2875 msize = ntohs (message->size);
2876 if (msize < sizeof (struct PeerTrailSetupResultMessage))
2878 GNUNET_break_op (0);
2882 trail_result = (struct PeerTrailSetupResultMessage *) message;
2883 trail_length = ntohl (trail_result->trail_length);
2886 sizeof (struct PeerTrailSetupResultMessage) +
2887 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
2889 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2891 GNUNET_break_op (0);
2895 current_trail_index = ntohl (trail_result->current_index);
2896 finger_map_index = ntohl (trail_result->finger_map_index);
2898 trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_result[1];
2900 if ( 0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->destination_peer),
2903 finger_table_add (&(trail_result->finger_identity), trail_peer_list, trail_length,
2911 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
2913 current_trail_index = current_trail_index - 1;
2914 if (current_trail_index == 0)
2916 memcpy (next_hop, &(trail_result->destination_peer),sizeof (struct GNUNET_PeerIdentity));
2920 memcpy (next_hop, &(trail_peer_list[current_trail_index-1]),sizeof (struct GNUNET_PeerIdentity));
2924 /* If trail length = 2, it means that destination and source peer are friends
2925 Then don't add an entry. */
2926 if (trail_length != 2)
2927 GDS_ROUTING_add (&(trail_result->destination_peer), &(trail_result->finger_identity),
2929 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
2930 GNUNET_free (next_hop);
2932 GDS_NEIGHBOURS_send_trail_setup_result (&(trail_result->destination_peer),
2933 &(trail_result->finger_identity),
2934 target_friend, trail_length,
2935 trail_peer_list,current_trail_index,
2940 return GNUNET_SYSERR;
2945 * FIXME: Use flag in the case finger peer map does not contain predcessor
2946 * then its NULL. Ideally it should never happen.
2947 * Get my current predecessor from the finger peer map
2948 * @return Current predecessor.
2950 static struct FingerInfo *
2953 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
2954 struct GNUNET_PeerIdentity key_ret;
2955 unsigned int finger_index;
2956 struct FingerInfo *my_predecessor;
2958 /* Iterate over finger peer map and extract your predecessor. */
2959 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
2960 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
2962 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next
2963 (finger_iter,&key_ret,(const void **)&my_predecessor))
2965 if(1 == my_predecessor->finger_map_index)
2971 GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter);
2972 return my_predecessor;
2977 * Core handle for p2p verify successor messages.
2978 * @param cls closure
2979 * @param message message
2980 * @param peer peer identity this notification is about
2981 * @return GNUNET_OK on success, GNUNET_SYSERR on error
2984 handle_dht_p2p_verify_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
2985 const struct GNUNET_MessageHeader *message)
2987 struct PeerVerifySuccessorMessage *vsm;
2988 struct GNUNET_PeerIdentity *trail_peer_list;
2989 struct FriendInfo *target_friend;
2990 struct GNUNET_PeerIdentity *next_hop;
2991 struct GNUNET_PeerIdentity *source_peer;
2992 unsigned int trail_length;
2993 unsigned int current_trail_index;
2996 msize = ntohs (message->size);
2997 if (msize < sizeof (struct PeerVerifySuccessorMessage))
2999 GNUNET_break_op (0);
3003 vsm = (struct PeerVerifySuccessorMessage *) message;
3004 trail_length = ntohl (vsm->trail_length);
3006 if ((msize < sizeof (struct PeerVerifySuccessorMessage) +
3007 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3008 (trail_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3010 GNUNET_break_op (0);
3014 current_trail_index = ntohl (vsm->current_trail_index);
3015 trail_peer_list = (struct GNUNET_PeerIdentity *) &vsm[1];
3016 source_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
3017 memcpy (source_peer, &(vsm->source_peer), sizeof (struct GNUNET_PeerIdentity));
3019 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
3021 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsm->successor),&my_identity)))
3023 struct FingerInfo *my_predecessor;
3024 current_trail_index = trail_length - 1;
3025 if (current_trail_index == 0)
3026 memcpy (next_hop, source_peer, sizeof (struct GNUNET_PeerIdentity));
3028 memcpy (next_hop, &trail_peer_list[current_trail_index-1], sizeof (struct GNUNET_PeerIdentity));
3030 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3031 GNUNET_free (next_hop);
3033 my_predecessor = get_predecessor();
3034 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (source_peer,
3035 &(my_predecessor->finger_identity))))
3037 GDS_NEIGHBOURS_send_verify_successor_result (source_peer,
3039 &(my_predecessor->finger_identity),
3043 current_trail_index);
3047 struct GNUNET_PeerIdentity *new_successor_trail;
3048 int new_trail_length;
3051 new_trail_length = trail_length + my_predecessor->trail_length;
3052 new_successor_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * new_trail_length);
3053 memcpy (new_successor_trail, trail_peer_list, (trail_length) * sizeof (struct GNUNET_PeerIdentity));
3054 struct TrailPeerList *iterator;
3055 iterator = GNUNET_malloc (sizeof (struct TrailPeerList));
3056 iterator = my_predecessor->head;
3058 while (i < new_trail_length)
3060 memcpy (&new_successor_trail[i], &(iterator->peer), sizeof (struct GNUNET_PeerIdentity));
3061 iterator = iterator->next;
3065 GDS_NEIGHBOURS_send_verify_successor_result (source_peer,
3067 &(my_predecessor->finger_identity),
3069 new_successor_trail,
3071 current_trail_index);
3077 current_trail_index = current_trail_index + 1;
3078 memcpy (next_hop, &trail_peer_list[current_trail_index], sizeof (struct GNUNET_PeerIdentity));
3079 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3080 GNUNET_free (next_hop);
3082 GDS_NEIGHBOURS_send_verify_successor (source_peer, &(vsm->successor),target_friend,
3083 trail_peer_list, trail_length, current_trail_index);
3090 * Core handle for p2p notify new successor messages.
3091 * @param cls closure
3092 * @param message message
3093 * @param peer peer identity this notification is about
3094 * @return GNUNET_OK on success, GNUNET_SYSERR on error
3097 handle_dht_p2p_notify_new_successor(void *cls, const struct GNUNET_PeerIdentity *peer,
3098 const struct GNUNET_MessageHeader *message)
3100 struct PeerNotifyNewSuccessorMessage *nsm;
3101 struct GNUNET_PeerIdentity *trail_peer_list;
3102 unsigned int current_trail_index;
3104 unsigned int trail_length;
3106 msize = ntohs (message->size);
3107 if (msize < sizeof (struct PeerNotifyNewSuccessorMessage))
3109 GNUNET_break_op (0);
3113 nsm = (struct PeerNotifyNewSuccessorMessage *) message;
3114 trail_length = ntohl (nsm->trail_length);
3116 if ((msize < sizeof (struct PeerNotifyNewSuccessorMessage) +
3117 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3119 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3121 GNUNET_break_op (0);
3125 current_trail_index = ntohl (nsm->current_index);
3126 trail_peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
3128 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(nsm->destination_peer), &my_identity)))
3130 struct GNUNET_PeerIdentity *new_trail;
3131 new_trail = invert_trail_list (&(nsm->source_peer), trail_peer_list, trail_length);
3132 finger_table_add (&(nsm->source_peer), new_trail, trail_length, 1);
3137 struct FriendInfo *target_friend;
3138 struct GNUNET_PeerIdentity *next_hop;
3140 target_friend = GNUNET_malloc (sizeof (struct FriendInfo));
3141 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
3143 current_trail_index = current_trail_index + 1;
3144 memcpy (next_hop, &trail_peer_list[current_trail_index], sizeof (struct GNUNET_PeerIdentity));
3145 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3146 GNUNET_free (next_hop);
3148 GDS_NEIGHBOURS_send_notify_new_successor (&(nsm->source_peer),
3149 &(nsm->destination_peer),
3150 target_friend, trail_peer_list,
3151 trail_length, current_trail_index);
3158 * Core handle for p2p verify successor result messages.
3159 * @param cls closure
3160 * @param message message
3161 * @param peer peer identity this notification is about
3162 * @return GNUNET_OK on success, GNUNET_SYSERR on error
3165 handle_dht_p2p_verify_successor_result(void *cls, const struct GNUNET_PeerIdentity *peer,
3166 const struct GNUNET_MessageHeader *message)
3168 struct PeerVerifySuccessorResultMessage *vsrm;
3169 struct FriendInfo *target_friend;
3170 struct GNUNET_PeerIdentity *trail_peer_list;
3171 struct GNUNET_PeerIdentity *next_hop;
3172 unsigned int trail_length;
3173 unsigned int current_trail_index;
3176 msize = ntohs (message->size);
3177 if (msize < sizeof (struct PeerVerifySuccessorResultMessage))
3179 GNUNET_break_op (0);
3183 vsrm = (struct PeerVerifySuccessorResultMessage *) message;
3184 trail_length = ntohl (vsrm->trail_length);
3187 sizeof (struct PeerVerifySuccessorResultMessage) +
3188 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
3190 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3192 GNUNET_break_op (0);
3196 current_trail_index = ntohl (vsrm->current_index);
3197 trail_peer_list = (struct GNUNET_PeerIdentity *) &vsrm[1];
3199 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->destination_peer), &(my_identity))))
3201 if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->my_predecessor), &(my_identity))))
3203 finger_table_add (&(vsrm->my_predecessor), trail_peer_list, trail_length, 0);
3204 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
3205 memcpy (next_hop, &trail_peer_list[0], sizeof (struct GNUNET_PeerIdentity));
3206 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3207 current_trail_index = 0;
3208 GNUNET_free (next_hop);
3210 GDS_NEIGHBOURS_send_notify_new_successor (&my_identity, &(vsrm->my_predecessor),
3211 target_friend, trail_peer_list,
3212 trail_length, current_trail_index);
3217 next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
3218 current_trail_index = current_trail_index - 1;
3219 if (current_trail_index == 0)
3220 memcpy (next_hop, &(vsrm->destination_peer), sizeof (struct GNUNET_PeerIdentity));
3222 memcpy (next_hop, &trail_peer_list[current_trail_index-1], sizeof (struct GNUNET_PeerIdentity));
3223 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
3224 GNUNET_free (next_hop);
3226 GDS_NEIGHBOURS_send_verify_successor_result (&(vsrm->destination_peer),
3227 &(vsrm->source_successor),
3228 &(vsrm->my_predecessor),
3232 current_trail_index);
3239 * FIXME: Does it matter if the packet was going to a finger or friend?
3240 * Core handle for p2p trail rejection messages.
3241 * @param cls closure
3242 * @param message message
3243 * @param peer peer identity this notification is about
3244 * @return GNUNET_OK on success, GNUNET_SYSERR on error
3247 int handle_dht_p2p_trail_rejection(void *cls, const struct GNUNET_PeerIdentity *peer,
3248 const struct GNUNET_MessageHeader *message)
3250 struct PeerTrailRejectionMessage *trail_rejection;
3251 struct FailedTrail *trail_fail;
3252 struct FriendInfo *target_friend;
3253 struct GNUNET_PeerIdentity *trail_peer_list;
3254 unsigned int finger_map_index;
3257 msize = ntohs (message->size);
3258 if (msize < sizeof (struct PeerTrailRejectionMessage))
3260 GNUNET_break_op (0);
3264 trail_rejection = (struct PeerTrailRejectionMessage *) message;
3265 trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_rejection[1];
3266 finger_map_index = ntohl (trail_rejection->finger_map_index);
3267 trail_fail = GNUNET_malloc (sizeof (struct FailedTrail));
3268 memcpy (&(trail_fail->source_peer), &(trail_rejection->source_peer), sizeof (struct GNUNET_PeerIdentity));
3269 memcpy (&(trail_fail->congested_peer), &(trail_rejection->congested_peer), sizeof (struct GNUNET_PeerIdentity));
3270 memcpy (&(trail_fail->destination_finger_value), &(trail_rejection->finger_identity), sizeof (uint64_t));
3272 GNUNET_assert (GNUNET_OK ==
3273 GNUNET_CONTAINER_multipeermap_put (failed_trail_list, &(trail_fail->source_peer),
3274 trail_fail, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
3276 /* FIXME: Is it okay if I pass the struct as parameter. */
3277 target_friend = select_random_friend (&(trail_fail->congested_peer));
3279 if(NULL != target_friend)
3281 /* FIXME: Here I am passing NULL for current source, is it correct?
3282 also, we set the current source only if current_destination_type
3284 GDS_NEIGHBOURS_send_trail_setup (&(trail_fail->source_peer),
3285 trail_fail->destination_finger_value,
3286 &(target_friend->id),
3287 NULL, target_friend, ntohl (trail_rejection->trail_length),
3289 finger_map_index, FRIEND);
3292 return GNUNET_SYSERR;
3297 * Initialize neighbours subsystem.
3298 * @return GNUNET_OK on success, GNUNET_SYSERR on error
3301 GDS_NEIGHBOURS_init()
3303 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
3304 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0},
3305 {&handle_dht_p2p_get_result, GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT, 0},
3306 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0},
3307 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP, 0},
3308 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT, 0},
3309 {&handle_dht_p2p_verify_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR, 0},
3310 {&handle_dht_p2p_verify_successor_result, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT, 0},
3311 {&handle_dht_p2p_notify_new_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR, 0},
3312 {&handle_dht_p2p_trail_rejection, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION, 0},
3317 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
3318 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
3319 GNUNET_NO, core_handlers);
3320 if (NULL == core_api)
3321 return GNUNET_SYSERR;
3323 friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
3324 finger_peermap = GNUNET_CONTAINER_multipeermap_create (MAX_FINGERS, GNUNET_NO);
3325 /* FIXME: Not sure if this value is correct for this data structure. */
3326 failed_trail_list = GNUNET_CONTAINER_multipeermap_create (LINK_THRESHOLD, GNUNET_NO);
3332 * Shutdown neighbours subsystem.
3335 GDS_NEIGHBOURS_done ()
3337 if (NULL == core_api)
3340 GNUNET_CORE_disconnect (core_api);
3343 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
3344 GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
3345 friend_peermap = NULL;
3347 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (finger_peermap));
3348 GNUNET_CONTAINER_multipeermap_destroy (finger_peermap);
3349 finger_peermap = NULL;
3351 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
3353 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
3354 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
3357 if (GNUNET_SCHEDULER_NO_TASK != verify_successor)
3359 GNUNET_SCHEDULER_cancel (verify_successor);
3360 verify_successor = GNUNET_SCHEDULER_NO_TASK;
3367 * Get the ID of the local node.
3369 * @return identity of the local node
3371 struct GNUNET_PeerIdentity *
3372 GDS_NEIGHBOURS_get_id ()
3374 return &my_identity;
3378 /* end of gnunet-service-xdht_neighbours.c */