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"
53 *SUPU: Lets assume that while adding entries in the multipeermap
54 we are adding it in sorted way.
55 1. Add content and route replication later.
56 *2. Algorithm to shorten the trail length - one possible solution could be
57 * when we are in trail seutp result part. each peer in the trail check if any of
58 * the corresponding peers is its friend list. Then it can shortcut the path.
59 * But this will have O(n) run time at each peer, where n = trail_length.\
60 * or rather O(n)+O(n-1)+..O(1) =O(n).
61 * 3. Add a new field finger index to keep track of which finger respongs to which
63 * 4. As we start looking for finger from i = 0, using this parameter to
64 * generate random value does not look smart in send_find_finger_trail_message.
65 * 5. Need to store the interval in finger and friend table which will be used
66 * to find the correct successor.
67 * 6. Need to add a new task, fix fingers. For node join/leave, we need to
68 * upgrade our finger table periodically. So, we should call fix_fingers
69 * and change our finger table.
70 * 7. Should we look for fingers one by one in send_find_finger_trail_setup
71 * 8. Change the message is gnunet_protocols.h
76 * Maximum possible fingers of a peer.
77 * FIXME: Should it be 64 as we are doing all the operation on 64 bit numbers now?
79 #define MAX_FINGERS 64
82 * Maximum allowed number of pending messages per friend peer.
84 #define MAXIMUM_PENDING_PER_FRIEND 64
87 * How long at least to wait before sending another find finger trail request.
89 #define DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
92 * How long at most to wait before sending another find finger trail request.
94 #define DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 10)
97 * FIXME: Currently used in GDS_NEIGHBOURS_handle_trail_setup.
98 * I have just copied it from gnunet-service-dht_neighbours. Will it work here?
99 * How long at most to wait for transmission of a GET request to another peer?
101 #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
103 GNUNET_NETWORK_STRUCT_BEGIN
106 * 1) Bloomfilter is not required for X-Vine.
107 * Keep the field now but remove it when implementing PUT/GET.
108 * 2) also, check the field of put/get/result if all are required for
114 struct PeerPutMessage
117 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
119 struct GNUNET_MessageHeader header;
124 uint32_t options GNUNET_PACKED;
129 uint32_t type GNUNET_PACKED;
134 uint32_t hop_count GNUNET_PACKED;
137 * Replication level for this message
139 uint32_t desired_replication_level GNUNET_PACKED;
142 * Length of the PUT path that follows (if tracked).
144 uint32_t put_path_length GNUNET_PACKED;
147 * When does the content expire?
149 struct GNUNET_TIME_AbsoluteNBO expiration_time;
152 * Bloomfilter (for peer identities) to stop circular routes
154 char bloomfilter[DHT_BLOOM_SIZE];
157 * The key we are storing under.
159 struct GNUNET_HashCode key;
161 /* put path (if tracked) */
171 struct PeerResultMessage
174 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT
176 struct GNUNET_MessageHeader header;
181 uint32_t type GNUNET_PACKED;
184 * Length of the PUT path that follows (if tracked).
186 uint32_t put_path_length GNUNET_PACKED;
189 * Length of the GET path that follows (if tracked).
191 uint32_t get_path_length GNUNET_PACKED;
194 * When does the content expire?
196 struct GNUNET_TIME_AbsoluteNBO expiration_time;
199 * The key of the corresponding GET request.
201 struct GNUNET_HashCode key;
203 /* put path (if tracked) */
205 /* get path (if tracked) */
215 struct PeerGetMessage
218 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET
220 struct GNUNET_MessageHeader header;
225 uint32_t options GNUNET_PACKED;
228 * Desired content type.
230 uint32_t type GNUNET_PACKED;
235 uint32_t hop_count GNUNET_PACKED;
238 * Desired replication level for this request.
240 uint32_t desired_replication_level GNUNET_PACKED;
243 * Size of the extended query.
245 uint32_t xquery_size;
248 * Bloomfilter mutator.
253 * Bloomfilter (for peer identities) to stop circular routes
255 char bloomfilter[DHT_BLOOM_SIZE];
258 * The key we are looking for.
260 struct GNUNET_HashCode key;
266 * A destination can be either a friend or finger.
268 enum current_destination_type
276 /* My own identity */
281 * P2P Trail setup message
282 * TODO: Take reference from put_path and get_path to understand how to use size of trail list.
284 struct PeerTrailSetupMessage
287 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP
289 struct GNUNET_MessageHeader header;
292 * Source peer which wants to find trail to one of its finger.
294 struct GNUNET_PeerIdentity source_peer;
297 * As we are not sending any hello messages to this destination
298 * finger, we are only searching for it, we can just send 64 bit.
299 * Finger id to which we want to set up the trail to.
301 struct GNUNET_PeerIdentity destination_finger; */
304 * Finger id to which we want to set up the trail to.
306 uint64_t destination_finger;
309 * If the message is forwarded to finger or friend.
311 enum current_destination_type current_destination_type;
314 * This field contains the peer to which this packet is forwarded.
316 struct GNUNET_PeerIdentity current_destination;
319 * Number of entries in trail list.
320 * FIXME: Is this data type correct?
321 * FIMXE: Is usage of GNUNET_PACKED correct?
323 uint32_t trail_length GNUNET_PACKED;
325 /* FIXME: Add this field later.
326 * The finger index in finger map.
327 unsigned int finger_index;*/
333 * P2P Trail setup Result message
335 struct PeerTrailSetupResultMessage
338 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_RESULT_SETUP
340 struct GNUNET_MessageHeader header;
343 * Finger to which we have found the path.
345 struct GNUNET_PeerIdentity finger;
348 * Peer which was looking for the trail to finger.
350 struct GNUNET_PeerIdentity destination_peer;
353 * This field contains the peer to which this packet is forwarded.
355 struct GNUNET_PeerIdentity current_destination;
358 * FIXME: Temporary field used to remember at which index we should read
359 * to get our next peer.
361 unsigned int current_index;
364 * Number of entries in trail list.
365 * FIXME: Is this data type correct?
366 * FIXME: Is usage of GNUNET_PACKED correct?
368 uint32_t trail_length GNUNET_PACKED;
372 GNUNET_NETWORK_STRUCT_END
376 * Linked list of messages to send to a particular other peer.
378 struct P2PPendingMessage
381 * Pointer to next item in the list
383 struct P2PPendingMessage *next;
386 * Pointer to previous item in the list
388 struct P2PPendingMessage *prev;
391 * When does this message time out?
393 struct GNUNET_TIME_Absolute timeout;
396 * Message importance level. FIXME: used? useful?
398 unsigned int importance;
401 * Actual message to be sent, allocated at the end of the struct:
402 * // msg = (cast) &pm[1];
403 * // memcpy (&pm[1], data, len);
405 const struct GNUNET_MessageHeader *msg;
411 * Linked List of peers which are part of trail to reach a particular Finger.
416 * Pointer to next item in the list
418 struct TrailPeerList *next;
421 * Pointer to previous item in the list
423 struct TrailPeerList *prev;
426 * An element in this trail list
428 struct GNUNET_PeerIdentity peer;
434 * Entry in friend_peermap.
439 * What is the identity of the peer?
441 struct GNUNET_PeerIdentity id;
444 * Count of outstanding messages for peer.
446 unsigned int pending_count;
449 * Start of interval friend[i].start
451 uint64_t interval_start;
454 * Start of interval friend[i+1].start
456 uint64_t interval_end;
459 * Successor of this finger.
461 struct GNUNET_PeerIdentity successor_identity;
464 * Predecessor of this finger.
466 struct GNUNET_PeerIdentity predecessor_identity;
469 * Head of pending messages to be sent to this peer.
471 struct P2PPendingMessage *head;
474 * Tail of pending messages to be sent to this peer.
476 struct P2PPendingMessage *tail;
479 * TODO - How and where to use this?
480 * Core handle for sending messages to this peer.
482 struct GNUNET_CORE_TransmitHandle *th;
488 * FIXME: Should we use another PeerIdentity which is smaller
489 * than 256 bits while storing.
491 * finger_identity is the actual finger that we were looking for.
492 * successor is the peer id which is our finger in place of finger_identity
493 * that we were actually looking for. It may happen that finger_identity
494 * was not in the network and we found the successor closest to that
496 * Predcessor is needed in case of node join/fail.
497 * Entry in finger_peermap.
502 * Index in finger_peermap.
509 struct GNUNET_PeerIdentity finger_identity;
512 * Start of interval finger[i].start
514 uint64_t interval_start;
517 * Start of interval finger[i+1].start
519 uint64_t interval_end;
522 * Successor of this finger.
524 struct GNUNET_PeerIdentity successor_identity;
527 * Predecessor of this finger.
529 struct GNUNET_PeerIdentity predecessor_identity;
532 * List of peers in the trail.
534 const struct GNUNET_PeerIdentity *trail_peer_list;
538 * Task that sends FIND FINGER TRAIL requests.
540 static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task;
543 * FIXME: As we should check for our immediate successor
544 * in case of node join/fail, the immediate successor will change.
545 * Hence we define a process which will be scheduled in regular interval.
546 * But you should schedule this process once you have found your successor.
547 * so, in finger_table_add_entry, when finger_peermap is size 1 then start
548 * this task, and periodically call it within it self like find_finger_trail_setup
550 * Task that periodically checks for the immediate successor.
552 static GNUNET_SCHEDULER_TaskIdentifier verify_immediate_successor;
555 * Identity of this peer.
557 static struct GNUNET_PeerIdentity my_identity;
560 * FIXME: Not used anywhere in the code yet.
561 * Hash of the identity of this peer.
563 static struct GNUNET_HashCode my_identity_hash;
566 * Hash map of all the friends of a peer
568 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap;
571 * Hash map of all the fingers of a peer
573 static struct GNUNET_CONTAINER_MultiPeerMap *finger_peermap;
576 * TODO: Ask whats the use of ATS.
579 static struct GNUNET_ATS_PerformanceHandle *atsAPI;
584 static struct GNUNET_CORE_Handle *core_api;
587 * The current finger index that we have found trail to.
589 static unsigned int current_finger_index;
593 * Called when core is ready to send a message we asked for
594 * out to the destination.
596 * @param cls the 'struct PeerInfo' of the target peer
597 * @param size number of bytes available in buf
598 * @param buf where the callee should write the message
599 * @return number of bytes written to buf
602 core_transmit_notify (void *cls, size_t size, void *buf)
604 struct FriendInfo *peer = cls;
606 struct P2PPendingMessage *pending;
611 while ((NULL != (pending = peer->head)) &&
612 (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us))
614 peer->pending_count--;
615 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
616 GNUNET_free (pending);
620 /* no messages pending */
626 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
627 GNUNET_CORE_PRIO_BEST_EFFORT,
628 GNUNET_TIME_absolute_get_remaining
629 (pending->timeout), &peer->id,
630 ntohs (pending->msg->size),
631 &core_transmit_notify, peer);
632 GNUNET_break (NULL != peer->th);
636 while ((NULL != (pending = peer->head)) &&
637 (size - off >= (msize = ntohs (pending->msg->size))))
639 GNUNET_STATISTICS_update (GDS_stats,
641 ("# Bytes transmitted to other peers"), msize,
643 memcpy (&cbuf[off], pending->msg, msize);
645 peer->pending_count--;
646 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
647 GNUNET_free (pending);
649 if (peer->head != NULL)
652 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
653 GNUNET_CORE_PRIO_BEST_EFFORT,
654 GNUNET_TIME_absolute_get_remaining
655 (pending->timeout), &peer->id, msize,
656 &core_transmit_notify, peer);
657 GNUNET_break (NULL != peer->th);
664 * Transmit all messages in the friend's message queue.
666 * @param peer message queue to process
669 process_friend_queue (struct FriendInfo *peer)
671 struct P2PPendingMessage *pending;
673 if (NULL == (pending = peer->head))
675 if (NULL != peer->th)
678 GNUNET_STATISTICS_update (GDS_stats,
680 ("# Bytes of bandwidth requested from core"),
681 ntohs (pending->msg->size), GNUNET_NO);
683 /* FIXME: Are we correctly initializing importance and pending. */
685 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
687 GNUNET_TIME_absolute_get_remaining
688 (pending->timeout), &peer->id,
689 ntohs (pending->msg->size),
690 &core_transmit_notify, peer);
691 GNUNET_break (NULL != peer->th);
697 * We add the next destination i.e. friend to which we are sending the packet
698 * to our peer list in the calling function and we also increment trail_length
699 * in calling function i.e. send_find_finger_trail and handle_dht_p2p_trail_setup.
700 * Here we only copy the whole trail into our peer_list.
701 * Setup the trail message and forward it to a friend.
702 * @param source_peer Peer which wants to set up the trail to one of its finger.
703 * @param destination_finger Peer to which we want to set up the trail to.
704 * @param current_destination Current peer to which this message should be forwarded.
705 * @param trail_length Numbers of peers in the trail.
706 * @param trail_peer_list peers this request has traversed so far
709 GDS_NEIGHBOURS_handle_trail_setup(struct GNUNET_PeerIdentity *source_peer,
710 uint64_t *destination_finger,
711 struct FriendInfo *current_destination,
712 unsigned int trail_length,
713 struct GNUNET_PeerIdentity *trail_peer_list)
715 struct P2PPendingMessage *pending;
716 struct PeerTrailSetupMessage *tsm;
717 struct GNUNET_PeerIdentity *peer_list;
720 msize = sizeof(struct PeerTrailSetupMessage) +
721 (trail_length * sizeof(struct GNUNET_PeerIdentity));
723 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
729 if (current_destination->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
731 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
735 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
736 pending->importance = 0; /* FIXME */
737 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
738 tsm = (struct PeerTrailSetupMessage *) &pending[1];
739 pending->msg = &tsm->header;
740 tsm->header.size = htons (msize);
741 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
742 memcpy(&(tsm->destination_finger), destination_finger, sizeof (uint64_t)); //FIXME: Is this copy correct?
743 memcpy(&(tsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
744 memcpy(&(tsm->current_destination),&(current_destination->id), sizeof (struct GNUNET_PeerIdentity));
745 tsm->current_destination_type = htonl(FRIEND);
746 tsm->trail_length = htonl(trail_length);
747 peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * trail_length);
748 peer_list = (struct GNUNET_PeerIdentity *) &tsm[1];
749 memcpy(peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
751 GNUNET_CONTAINER_DLL_insert_tail (current_destination->head, current_destination->tail, pending);
752 current_destination->pending_count++;
753 process_friend_queue (current_destination);
758 * Handle a tail setup result message.
759 * @param destination_peer Peer which will get the trail to one of its finger.
760 * @param source_finger Peer to which the trail has been setup to.
761 * @param current_destination Current peer to which this message should be forwarded.
762 * @param trail_length Numbers of peers in the trail.
763 * @param trail_peer_list peers this request has traversed so far
764 * @param current_trail_index Index in trail_peer_list.
767 GDS_NEIGHBOURS_handle_trail_setup_result(struct GNUNET_PeerIdentity *destination_peer,
768 struct GNUNET_PeerIdentity *source_finger,
769 struct FriendInfo *current_destination,
770 unsigned int trail_length,
771 const struct GNUNET_PeerIdentity *trail_peer_list,
772 unsigned int current_trial_index)
774 struct P2PPendingMessage *pending;
775 struct PeerTrailSetupResultMessage *tsrm;
776 struct GNUNET_PeerIdentity *peer_list;
779 msize = sizeof(struct PeerTrailSetupMessage) +
780 (trail_length * sizeof(struct GNUNET_PeerIdentity));
782 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
788 if (current_destination->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
790 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
794 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
795 pending->importance = 0; /* FIXME */
796 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
797 tsrm = (struct PeerTrailSetupResultMessage *) &pending[1];
798 pending->msg = &tsrm->header;
799 tsrm->header.size = htons (msize);
800 tsrm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT);
801 memcpy(&(tsrm->current_destination), &(current_destination->id), sizeof(struct GNUNET_PeerIdentity));
802 memcpy(&(tsrm->destination_peer), destination_peer, sizeof(struct GNUNET_PeerIdentity));
803 memcpy(&(tsrm->finger), source_finger, sizeof(struct GNUNET_PeerIdentity));
804 tsrm->trail_length = htonl(trail_length);
805 tsrm->current_index = htonl(current_trial_index);
806 peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1];
807 memcpy(peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
809 /* Send the message to chosen friend. */
810 GNUNET_CONTAINER_DLL_insert_tail (current_destination->head, current_destination->tail, pending);
811 current_destination->pending_count++;
812 process_friend_queue (current_destination);
816 /**FIXME: Old implementation just to remove error
817 * TODO: Modify this function to handle our get request.
818 * Perform a GET operation. Forwards the given request to other
819 * peers. Does not lookup the key locally. May do nothing if this is
820 * the only peer in the network (or if we are the closest peer in the
823 * @param type type of the block
824 * @param options routing options
825 * @param desired_replication_level desired replication count
826 * @param hop_count how many hops did this request traverse so far?
827 * @param key key for the content
828 * @param xquery extended query
829 * @param xquery_size number of bytes in @a xquery
830 * @param reply_bf bloomfilter to filter duplicates
831 * @param reply_bf_mutator mutator for @a reply_bf
832 * @param peer_bf filter for peers not to select (again)
835 GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
836 enum GNUNET_DHT_RouteOption options,
837 uint32_t desired_replication_level,
838 uint32_t hop_count, const struct GNUNET_HashCode * key,
839 const void *xquery, size_t xquery_size,
840 const struct GNUNET_CONTAINER_BloomFilter *reply_bf,
841 uint32_t reply_bf_mutator,
842 struct GNUNET_CONTAINER_BloomFilter *peer_bf)
846 1. take the key, get the 64 bit value of the key.
847 2. call find_successor to get the successor of the key.
848 3. successor can be either a friend or finger.
849 4. update the field in get message to reflect if its a friend or finger table
850 5. add the put message to pending message and send it.
854 /**FIXME: Old implementation just to remove error.
855 * TODO: Modify this function to handle our put request.
856 * Perform a PUT operation. Forwards the given request to other
857 * peers. Does not store the data locally. Does not give the
858 * data to local clients. May do nothing if this is the only
859 * peer in the network (or if we are the closest peer in the
862 * @param type type of the block
863 * @param options routing options
864 * @param desired_replication_level desired replication count
865 * @param expiration_time when does the content expire
866 * @param hop_count how many hops has this message traversed so far
867 * @param bf Bloom filter of peers this PUT has already traversed
868 * @param key key for the content
869 * @param put_path_length number of entries in @a put_path
870 * @param put_path peers this request has traversed so far (if tracked)
871 * @param data payload to store
872 * @param data_size number of bytes in @a data
875 GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
876 enum GNUNET_DHT_RouteOption options,
877 uint32_t desired_replication_level,
878 struct GNUNET_TIME_Absolute expiration_time,
880 struct GNUNET_CONTAINER_BloomFilter *bf,
881 const struct GNUNET_HashCode *key,
882 unsigned int put_path_length,
883 struct GNUNET_PeerIdentity *put_path,
884 const void *data, size_t data_size)
888 1. take the key, get the 64 bit value of the key.
889 2. call find_successor to get the successor of the key.
890 3. successor can be either a friend or finger.
891 4. update the field in put message to reflect if its a friend or finger table
892 5. add the put message to pending message and send it.
898 * Randomly choose one of your friends from the friends_peer map
901 static struct FriendInfo *
902 select_random_friend()
904 unsigned int current_size;
907 struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
908 struct GNUNET_PeerIdentity key_ret;
909 struct FriendInfo *friend;
911 current_size = GNUNET_CONTAINER_multipeermap_size(friend_peermap);
913 /* Element stored at this index in friend_peermap should be selected friend. */
914 index = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, current_size);
916 /* Create an iterator for friend_peermap. */
917 iter = GNUNET_CONTAINER_multipeermap_iterator_create(friend_peermap);
919 /* Set the position of iterator to index. */
922 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(iter,NULL,NULL))
928 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(iter,&key_ret,(const void **)&friend))
938 * Compute finger_identity to which we want to setup the trail
939 * FIXME: If we maintain a index that is value of current_finger_index
940 * to which a particular entry in finger map corresponds then should we first
941 * check if there is already an entry for that index. If yes then don't
942 * search for trail to that finger.
943 * @return finger_identity
946 compute_finger_identity()
949 uint64_t *finger_identity64;
951 my_id64 = GNUNET_malloc (sizeof (uint64_t));
952 finger_identity64 = GNUNET_malloc (sizeof (uint64_t));
954 memcpy(my_id64, &(my_identity.public_key.q_y), sizeof (uint64_t));
955 *finger_identity64 = fmod ((*my_id64 + pow (2,current_finger_index)),( (pow (2,MAX_FINGERS))));
956 current_finger_index = current_finger_index + 1;
958 return finger_identity64;
963 * TODO: Implement after testing friend/finger map.
964 * TODO: Handle the case when we already have a trail to our predecessor in
966 * This function will be needed when we are handling node joins/fails
967 * to maintain correct pointer to our predecessor and successor in the network.
968 * Find immediate predecessor in the network.
969 * @param me my own identity
970 * @return peer identity of immediate predecessor.
973 find_immediate_predecessor()
975 /* Using your own peer identity, calculate your predecessor
976 * in the network. Try to setup path to this predecessor using
977 * the same logic as used for other fingers.
978 * If we already have a trail to our predecessor then send NULL and
979 * calling function should be able to handle that case.
981 /* FIXME: O could be a valid peer id, return something else. */
987 * Periodically verify your own immediate successor and
988 * tell your successor about yourself.
990 * @param cls closure for this task
991 * @param tc the context under which the task is running
995 const struct GNUNET_SCHEDULER_TaskContext *tc )
999 * Should we have a new message type
1000 * 1. like who is your predecessor.
1003 1. ask your immediate successor ( its stored in your finger table with
1004 field that notes that its immediate successor) who is its predecessor.
1005 2. Then after getting the reply, check if its you.
1006 3. If not then update the new successor and your successor
1007 and notify the new successor that you are its new predecessor.
1009 struct GNUNET_TIME_Relative next_send_time;
1011 next_send_time.rel_value_us =
1012 DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
1013 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1014 DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us /
1015 (current_finger_index + 1));
1017 verify_immediate_successor =
1018 GNUNET_SCHEDULER_add_delayed (next_send_time, &stabilize,
1024 * Task to send a find finger trail message. We attempt to find trail
1025 * to our finger and successor in the network.
1027 * @param cls closure for this task
1028 * @param tc the context under which the task is running
1031 send_find_finger_trail_message (void *cls,
1032 const struct GNUNET_SCHEDULER_TaskContext *tc)
1034 struct FriendInfo *friend;
1035 struct GNUNET_TIME_Relative next_send_time;
1036 uint64_t *finger_identity; /* FIXME: Better variable name */
1037 struct GNUNET_PeerIdentity *peer_list;
1039 /* We already have found trail to each of our possible fingers in the network. */
1040 if (GNUNET_CONTAINER_multipeermap_size (finger_peermap) == MAX_FINGERS)
1042 /* FIXME: I call find_immediate_predecessor when I have found trail to
1043 * all the possible fingers in the network. But we need to find immediate
1044 * predecessor when there is a node failure/join. It may happen before.
1045 * Think of a better strategy to decide when to call this function.
1046 * We can find trail to our immediate predecessor in the network.
1047 * I think its better to call this after we have trail to our successor set up.
1049 finger_identity = find_immediate_predecessor();
1051 if(NULL == finger_identity)
1053 /* We already have a trail to reach to immediate predecessor. */
1054 goto new_find_finger_trail_request;
1059 finger_identity = compute_finger_identity();
1061 if(finger_identity == NULL)
1063 goto new_find_finger_trail_request;
1067 friend = GNUNET_malloc (sizeof (struct FriendInfo));
1068 friend = select_random_friend();
1070 /* We found a friend.*/
1073 /* SUPU: Verify if its correct or not. */
1074 unsigned int trail_length = 2;
1075 peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * trail_length);
1076 memcpy(&peer_list[0], &(my_identity), sizeof (struct GNUNET_PeerIdentity));
1077 memcpy(&peer_list[1], &(friend->id), sizeof (struct GNUNET_PeerIdentity));
1078 GDS_NEIGHBOURS_handle_trail_setup(&my_identity, finger_identity,
1079 friend, trail_length, peer_list);
1082 /* FIXME: Should we be using current_finger_index to generate random interval.*/
1083 new_find_finger_trail_request:
1084 next_send_time.rel_value_us =
1085 DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
1086 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1087 DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us /
1088 (current_finger_index + 1));
1090 find_finger_trail_task =
1091 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_finger_trail_message,
1097 * Method called whenever a peer connects.
1099 * @param cls closure
1100 * @param peer peer identity this notification is about
1103 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
1105 struct FriendInfo *ret;
1107 /* Check for connect to self message */
1108 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
1111 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1112 "Connected to %s\n",
1115 /* If peer already exists in our friend_peermap, then exit. */
1117 GNUNET_CONTAINER_multipeermap_contains (friend_peermap,
1124 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
1127 /* FIXME: Whenever you add an entry into your finger peermap,
1128 first add everything in sorted way and interval field should also
1130 ret = GNUNET_new (struct FriendInfo);
1134 GNUNET_assert (GNUNET_OK ==
1135 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
1137 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1140 /* got a first connection, good time to start with FIND FINGER TRAIL requests... */
1141 if (1 == GNUNET_CONTAINER_multipeermap_size (friend_peermap))
1142 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
1147 * FIXME: Implement after testing finger/friend table setup.
1148 * Method called whenever a peer disconnects.
1150 * @param cls closure
1151 * @param peer peer identity this notification is about
1154 handle_core_disconnect (void *cls,
1155 const struct GNUNET_PeerIdentity *peer)
1158 * 1. remove the friend from the friend map.
1159 * 2. remove the trail for the fingers for which this peer was the first hop.
1160 * 3. start send_find_finger_trail for these fingers to find a new trail
1162 * 4. Also when a node gets disconnected, how should we update pointers of its
1163 * immediate successor and predecessor in the network ?
1164 * 5. Also how do we distribute the keys in the network?
1165 * 6. Here is case where we started put operation but a peer got disconnected and
1166 we removed the entry from the table. How to handle such a case.
1172 * To be called on core init/fail.
1174 * @param cls service closure
1175 * @param identity the public identity of this peer
1178 core_init (void *cls,
1179 const struct GNUNET_PeerIdentity *identity)
1181 my_identity = *identity;
1182 GNUNET_CRYPTO_hash (identity,
1183 sizeof (struct GNUNET_PeerIdentity),
1189 * Core handler for p2p put requests.
1191 * @param cls closure
1192 * @param peer sender of the request
1193 * @param message message
1194 * @param peer peer identity this notification is about
1195 * @return #GNUNET_OK to keep the connection open,
1196 * #GNUNET_SYSERR to close it (signal serious error)
1199 handle_dht_p2p_put (void *cls,
1200 const struct GNUNET_PeerIdentity *peer,
1201 const struct GNUNET_MessageHeader *message)
1204 1. Check if destination is friend or finger.
1205 2. If finger then get the next hop from routing table and
1206 * call GDS_NEGIHBOURS_handle_get.
1207 3. If friend then call find_successor to get the next hop and again
1208 * call GDS_NEIGHBOURS_handle_get to send to chosen hop.
1209 4. If you are the destination then do datacache_store.
1216 * Core handler for p2p get requests.
1218 * @param cls closure
1219 * @param peer sender of the request
1220 * @param message message
1221 * @return #GNUNET_OK to keep the connection open,
1222 * #GNUNET_SYSERR to close it (signal serious error)
1225 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
1226 const struct GNUNET_MessageHeader *message)
1229 1. Check if destination is friend or finger.
1230 2. If finger then get the next hop from routing table and
1231 * call GDS_NEGIHBOURS_handle_get.
1232 3. If friend then call find_successor to get the next hop and again
1233 * call GDS_NEIGHBOURS_handle_get to send to chosen hop.
1234 4. If you are the destination then send the data back to source peer
1235 * Assuming we have trail setup we can
1236 * either store the whole trail or again do the search process..
1243 * FIXME: Use some optimal way to do the operations.
1244 * FIXME: Check if this function can be used as such for put/get
1245 * 1.assumption that when ever we insert a value into friend or
1246 * finger map, we sort it and also update the interval correctly,
1247 * 2. all the comparison are done on 64 bit values. so in last part when
1248 * you compare finger , friend and your own identity then also you need to
1249 * have the values in 64 bit format and get the correct successor.
1250 * At this point the algorithm does not look very smart.
1251 * Finds successor of the identifier
1252 * @param id Identifier for which we are trying to find the successor
1255 static struct GNUNET_PeerIdentity *
1256 find_successor(uint64_t id,
1257 struct GNUNET_PeerIdentity *current_destination,
1258 enum current_destination_type *type)
1260 /* 1. Iterate over friend map and find the closest peer.
1261 2. Iterate over finger map and find the closest peer.
1262 3. Sort my_identity, friend successor and finger successor.
1263 4. Choose the closest peer among the three.
1265 struct GNUNET_CONTAINER_MultiPeerMapIterator *friend_iter;
1266 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1267 struct FriendInfo *friend;
1268 struct FingerInfo *finger;
1269 struct GNUNET_PeerIdentity key_ret;
1270 unsigned int finger_index;
1271 unsigned int friend_index;
1272 struct FriendInfo *successor_friend;
1273 struct FingerInfo *successor_finger;
1278 successor_friend = GNUNET_malloc (sizeof (struct FriendInfo ));
1279 successor_finger = GNUNET_malloc (sizeof (struct FingerInfo ));
1281 /* Iterate over friend map. */
1282 friend_iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1283 for (friend_index = 0; friend_index < GNUNET_CONTAINER_multipeermap_size (friend_peermap); friend_index++)
1285 /* SUPU: check if you are using iterator_next correctly */
1286 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(friend_iter,&key_ret,(const void **)&friend))
1288 if(((friend->interval_start <= id) && (id < friend->interval_end))
1289 || (((friend->interval_start) > (friend->interval_end))
1290 && ((friend->interval_start <= id) && (id < friend->interval_end))))
1292 /* SUPU: Here I am copying friend into successor_friend as when among
1293 three ids i.e. friend, finger and my_id, one is chosen then I should
1294 be able to identify which one was chosen. */
1295 memcpy(successor_friend, friend, sizeof (struct FriendInfo));
1296 break; /*FIXME: Will it come out of outer for loop */
1301 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1302 /* iterate over finger map till you reach a peer id such that destination <= peer id */
1303 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
1305 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(finger_iter,&key_ret,(const void **)&finger))
1307 if(((finger->interval_start <= id) && (id < finger->interval_end))
1308 || (((finger->interval_start) > (finger->interval_end))
1309 && ((finger->interval_start <= id) && (id < finger->interval_end))))
1311 memcpy(successor_finger, finger, sizeof (struct FingerInfo));
1312 break; /*FIXME: Will it come out of outer for loop */
1317 /* Here you have two values from friend and finger map.
1318 Now sort the my_identity, friend and finger and
1319 choose the closest peer. Also update the closest successor type
1320 correctly to finger/friend/me. and update the current_destination value. */
1321 memcpy (&my_id, &(my_identity.public_key.q_y), sizeof (uint64_t));
1322 memcpy (&friend_id, (successor_friend->id.public_key.q_y), sizeof (uint64_t));
1323 memcpy (&finger_id, (successor_finger->finger_identity.public_key.q_y), sizeof (uint64_t));
1325 /* if finger_id is selected, then set type = FINGER, current_destination = finger
1326 and next_hop = first peer in trail list.
1327 if friend id is selected, then set type = FRIEND, current_destination = friend
1328 and return friend. */
1329 /* You need some function to compare which three of them is successor to
1330 id that we are looking for.
1331 1. Sort three of them.
1332 2. Set up the new interval.
1333 3. Check in which interval id lies.
1334 * You should set the type proprly. Need to add a new type to handle
1336 This is very suboptimal.
1337 Once you found the correct successor you should just return the
1338 correct PeerIdentity.
1344 and we are looking for 1. */
1345 return &(successor_friend->id); /* FIXME: remove this, added just to remove
1351 * Handle a P2PTrailSetupMessage.
1352 * @param cls closure
1353 * @param message message
1354 * @param peer peer identity this notification is about
1355 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1358 handle_dht_p2p_trail_setup(void *cls, const struct GNUNET_PeerIdentity *peer,
1359 const struct GNUNET_MessageHeader *message)
1361 struct PeerTrailSetupMessage *trail_setup;
1362 struct GNUNET_PeerIdentity *next_hop;
1363 struct FriendInfo *target_friend;
1365 uint32_t trail_length;
1366 enum current_destination_type peer_type;
1367 struct GNUNET_PeerIdentity *trail_peer_list;
1368 uint32_t current_trail_index;
1369 struct GNUNET_PeerIdentity *next_peer;
1372 /* parse and validate message. */
1373 msize = ntohs (message->size);
1374 if (msize < sizeof (struct PeerTrailSetupMessage))
1376 GNUNET_break_op (0);
1380 trail_setup = (struct PeerTrailSetupMessage *) message;
1381 trail_length = ntohl (trail_setup->trail_length);
1382 peer_type = ntohl (trail_setup->current_destination_type);
1383 trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_setup[1];
1386 sizeof (struct PeerTrailSetupMessage) +
1387 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
1389 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
1391 GNUNET_break_op (0);
1392 return GNUNET_YES; /*TODO: Why do we send GNUNET_YES here? */
1396 GNUNET_STATISTICS_update (GDS_stats,
1397 gettext_noop ("# TRAIL SETUP requests received"), 1,
1399 GNUNET_STATISTICS_update (GDS_stats,
1400 gettext_noop ("# TRAIL SETUP bytes received"), msize,
1403 if(peer_type == FRIEND)
1405 if(0 == (GNUNET_CRYPTO_cmp_peer_identity(&(trail_setup->current_destination),&my_identity)))
1407 next_hop = find_successor((trail_setup->destination_finger),&(trail_setup->current_destination),&(peer_type));
1410 return GNUNET_SYSERR; /*TODO: Should we handle this case differently? */
1412 else if(peer_type == FINGER)
1414 if(0 != (GNUNET_CRYPTO_cmp_peer_identity(&(trail_setup->current_destination),&my_identity)))
1416 /* I am part of trail.
1417 SUPU: So, I should ask for next hop to reach the current_destination which is the finger
1418 for which this packet has been sent. */
1419 next_hop = GDS_ROUTING_search(&(trail_setup->source_peer),&(trail_setup->current_destination));
1422 call find_successor and compare the two peer ids
1423 and choose whichever is closest to the destination finger. */
1427 /* I am the current_destination finger
1428 FIXME: Why are we sending current_destination to find_successor.
1429 In this case, is it safe to assume current_Destination = my_identity.
1430 I guess we are sending current_destination so that we update it with new
1431 current_destination, if could either me, friend or finger.*/
1432 next_hop = find_successor((trail_setup->destination_finger),&(trail_setup->current_destination),&(peer_type));
1436 /* If you are the next hop */
1437 if(peer_type == MY_ID)
1439 /* FIXME: Verify if its allowed here to definer peer_list and define it
1440 again in the next block below? */
1441 struct GNUNET_PeerIdentity *peer_list;
1442 peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * (trail_length));
1443 memcpy(peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1444 current_trail_index = trail_length - 2;
1445 next_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); //FIXME: Do we need to allocate the memory?
1446 memcpy(next_peer, &peer_list[current_trail_index], sizeof (struct GNUNET_PeerIdentity));
1448 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_peer);
1450 /* FIXME: It does not find a friend. Could be possible error in find_successor
1451 function. Change the logic in find_successor and change it again. */
1453 /* FIXME: Here as destination_finger is 64 bit instead of struct
1454 GNUNET_PeerIdentity, but you need destination_peer id. If you calling the
1455 function handle_Trail_setup_result from here, it means you are the
1456 destination. So, you can send your own identity. */
1457 GDS_NEIGHBOURS_handle_trail_setup_result(&(trail_setup->source_peer),
1459 target_friend, trail_length,
1460 peer_list,current_trail_index);
1465 /* Add next_hop to list of peers that trail setup message have traversed so far
1466 and increment trail length. */
1467 struct GNUNET_PeerIdentity *peer_list;
1468 peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * (trail_length + 1));
1469 memcpy(peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1470 memcpy(&peer_list[trail_length], next_hop, sizeof (struct GNUNET_PeerIdentity));
1473 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
1475 if(peer_type == FINGER)
1477 GDS_ROUTING_add(&(trail_setup->source_peer),&(trail_setup->current_destination),next_hop);
1480 GDS_NEIGHBOURS_handle_trail_setup(&(trail_setup->source_peer),
1481 &(trail_setup->destination_finger),
1483 trail_setup->trail_length,
1490 * FIXME : Add interval field.
1491 * When adding successor or predeccsor, update a field to
1492 * specify that this entry is not a finger but immediate
1493 * successor or predeccesor.
1494 * Add an entry in finger table.
1495 * @param finger Finger to be added to finger table
1496 * @param peer_list peers this request has traversed so far
1497 * @param trail_length Numbers of peers in the trail.
1500 void finger_table_add(struct GNUNET_PeerIdentity *finger,
1501 const struct GNUNET_PeerIdentity *peer_list,
1502 unsigned int trail_length)
1504 struct FingerInfo *finger_entry;
1505 finger_entry = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity));
1506 memcpy(&(finger_entry->finger_identity), finger, sizeof(struct GNUNET_PeerIdentity));
1507 memcpy(&(finger_entry->trail_peer_list), peer_list, sizeof(struct GNUNET_PeerIdentity)
1509 /*FIXME: When you add an entry into your finger table, then
1510 you should add it in sorted way. Also, once sorted update the finger table
1511 entry. As we will be using sorting and updating the interval in finger and friend
1512 table and also in find_successor, we need this functionality see if you can
1513 define a common function which can be used in all the three functions.
1514 Also, you should then insert that entry into your finger_peermap.
1515 It seems to be too much of complexity but I need a working copy but i will
1518 if (1 == GNUNET_CONTAINER_multipeermap_size (finger_peermap))
1519 verify_immediate_successor = GNUNET_SCHEDULER_add_now (&stabilize, NULL);
1524 * Core handle for p2p trail construction result messages.
1525 * @param cls closure
1526 * @param message message
1527 * @param peer peer identity this notification is about
1528 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1531 handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer,
1532 const struct GNUNET_MessageHeader *message)
1534 struct PeerTrailSetupResultMessage *trail_result;
1536 uint32_t trail_length;
1537 const struct GNUNET_PeerIdentity *trail_peer_list;
1538 uint32_t current_trail_index;
1539 struct GNUNET_PeerIdentity *next_peer;
1540 struct FriendInfo *target_friend;
1542 msize = ntohs (message->size);
1543 if (msize < sizeof (struct PeerTrailSetupMessage))
1545 GNUNET_break_op (0);
1549 trail_result = (struct PeerTrailSetupResultMessage *) message;
1550 trail_length = ntohl (trail_result->trail_length);
1551 current_trail_index = ntohl(trail_result->current_index);
1552 trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_result[1];
1555 sizeof (struct PeerTrailSetupResultMessage) +
1556 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
1558 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
1560 GNUNET_break_op (0);
1564 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->current_destination), &my_identity)))
1566 /* Am I the destination? */
1567 if( 0 == (GNUNET_CRYPTO_cmp_peer_identity(&(trail_result->destination_peer), &my_identity)))
1569 finger_table_add(&(trail_result->finger), trail_peer_list,trail_length);
1574 next_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1575 current_trail_index = current_trail_index - 1;
1576 memcpy(next_peer, &(trail_peer_list[trail_length-1]), sizeof (struct GNUNET_PeerIdentity));
1577 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_peer);
1579 GDS_NEIGHBOURS_handle_trail_setup_result(&(trail_result->destination_peer),
1580 &(trail_result->finger),
1581 target_friend, trail_length,
1582 trail_peer_list,current_trail_index);
1587 return GNUNET_SYSERR;
1592 * Core handle for p2p verify successor messages.
1593 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1596 handle_dht_p2p_verify_successor()
1599 * In this function you have received the message verify successor,
1600 * Now, either you are the destination or just part of the trail.
1601 * As we already know the whole path find out the next destination
1602 * and pass the packet forward.
1603 * If you are the final destination, check who is your predecessor.
1604 * and send your predecessor back to calling function.
1605 * FIXME: Should we have a different handler function for it.
1611 * Core handle for p2p notify successor messages.
1612 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1615 handle_dht_p2p_notify_successor()
1618 * So, if you are the destination you should update your
1619 * predecessor field with peer id of source peer of this message.
1620 * If you are not the destination peer, then just check your routing
1621 * table and pass on the message.
1627 * Core handle for p2p verify successor result messages.
1628 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1631 handle_dht_p2p_verify_successor_result()
1634 * In this function you have received the message verify successor result,
1635 If you are not the destination, just pass this message forward
1636 * if you are destination,
1637 * then check if immediate predecessor of this peer is you or someone else.
1638 * If its you, then don't do anything.
1639 * If its some one else, then call notify method to let your new successor
1640 * know that you are its predecessor.
1647 * Initialize neighbours subsystem.
1648 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1651 GDS_NEIGHBOURS_init()
1653 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1654 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0},
1655 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0},
1656 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP, 0},
1657 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT, 0},
1658 {&handle_dht_p2p_verify_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR, 0},
1659 {&handle_dht_p2p_notify_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_SUCCESSOR, 0},
1660 {&handle_dht_p2p_verify_successor_result, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT, 0},
1664 /*TODO: What is ATS? Why do we need it? */
1665 atsAPI = GNUNET_ATS_performance_init (GDS_cfg, NULL, NULL);
1667 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
1668 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
1669 GNUNET_NO, core_handlers);
1670 if (core_api == NULL)
1671 return GNUNET_SYSERR;
1673 friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1674 finger_peermap = GNUNET_CONTAINER_multipeermap_create (MAX_FINGERS, GNUNET_NO);
1681 * Shutdown neighbours subsystem.
1684 GDS_NEIGHBOURS_done ()
1686 if (NULL == core_api)
1689 GNUNET_CORE_disconnect (core_api);
1691 GNUNET_ATS_performance_done (atsAPI);
1694 /* FIXME: Once handle_core_disconnect is implemented, both below assertion should not
1696 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
1697 GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
1698 friend_peermap = NULL;
1700 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (finger_peermap));
1701 GNUNET_CONTAINER_multipeermap_destroy (finger_peermap);
1702 finger_peermap = NULL;
1704 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
1706 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
1707 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
1710 /* FIXME: fix_fingers will also be a task like this.
1712 if (GNUNET_SCHEDULER_NO_TASK != verify_immediate_successor)
1714 GNUNET_SCHEDULER_cancel (verify_immediate_successor);
1715 verify_immediate_successor = GNUNET_SCHEDULER_NO_TASK;
1722 * Get the ID of the local node.
1724 * @return identity of the local node
1726 struct GNUNET_PeerIdentity *
1727 GDS_NEIGHBOURS_get_id ()
1729 return &my_identity;
1733 /* end of gnunet-service-xdht_neighbours.c */