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 1. Add content and route replication later.
54 *2. Algorithm to shorten the trail length - one possible solution could be
55 * when we are in trail seutp result part. each peer in the trail check if any of
56 * the corresponding peers is its friend list. Then it can shortcut the path.
57 * But this will have O(n) run time at each peer, where n = trail_length.\
58 * or rather O(n)+O(n-1)+..O(1) =O(n).
59 * 4. As we start looking for finger from i = 0, using this parameter to
60 * generate random value does not look smart in send_find_finger_trail_message.
61 * 6. Need to add a new task, fix fingers. For node join/leave, we need to
62 * upgrade our finger table periodically. So, we should call fix_fingers
63 * and change our finger table.
64 * 7. Should we look for fingers one by one in send_find_finger_trail_setup
65 * 8. Change the message is gnunet_protocols.h
70 * Maximum possible fingers of a peer.
71 * FIXME: Should it be 64 as we are doing all the operation on 64 bit numbers now?
73 #define MAX_FINGERS 64
76 * Maximum allowed number of pending messages per friend peer.
78 #define MAXIMUM_PENDING_PER_FRIEND 64
81 * How long at least to wait before sending another find finger trail request.
83 #define DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
86 * How long at most to wait before sending another find finger trail request.
88 #define DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 10)
91 * FIXME: Currently used in GDS_NEIGHBOURS_handle_trail_setup.
92 * I have just copied it from gnunet-service-dht_neighbours. Will it work here?
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)
97 GNUNET_NETWORK_STRUCT_BEGIN
100 * 1) Bloomfilter is not required for X-Vine.
101 * Keep the field now but remove it when implementing PUT/GET.
102 * 2) also, check the field of put/get/result if all are required for
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 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 * When does the content expire?
143 struct GNUNET_TIME_AbsoluteNBO expiration_time;
146 * Bloomfilter (for peer identities) to stop circular routes
148 char bloomfilter[DHT_BLOOM_SIZE];
151 * The key we are storing under.
153 struct GNUNET_HashCode key;
155 /* put path (if tracked) */
165 struct PeerResultMessage
168 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT
170 struct GNUNET_MessageHeader header;
175 uint32_t type GNUNET_PACKED;
178 * Length of the PUT path that follows (if tracked).
180 uint32_t put_path_length GNUNET_PACKED;
183 * Length of the GET path that follows (if tracked).
185 uint32_t get_path_length GNUNET_PACKED;
188 * When does the content expire?
190 struct GNUNET_TIME_AbsoluteNBO expiration_time;
193 * The key of the corresponding GET request.
195 struct GNUNET_HashCode key;
197 /* put path (if tracked) */
199 /* get path (if tracked) */
209 struct PeerGetMessage
212 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET
214 struct GNUNET_MessageHeader header;
219 uint32_t options GNUNET_PACKED;
222 * Desired content type.
224 uint32_t type GNUNET_PACKED;
229 uint32_t hop_count GNUNET_PACKED;
232 * Desired replication level for this request.
234 uint32_t desired_replication_level GNUNET_PACKED;
237 * Size of the extended query.
239 uint32_t xquery_size;
242 * Bloomfilter mutator.
247 * Bloomfilter (for peer identities) to stop circular routes
249 char bloomfilter[DHT_BLOOM_SIZE];
252 * The key we are looking for.
254 struct GNUNET_HashCode key;
260 * A destination can be either a friend or finger.
262 enum current_destination_type
270 /* My own identity */
275 * P2P Trail setup message
276 * TODO: Take reference from put_path and get_path to understand how to use size of trail list.
278 struct PeerTrailSetupMessage
281 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP
283 struct GNUNET_MessageHeader header;
286 * Source peer which wants to find trail to one of its finger.
288 struct GNUNET_PeerIdentity source_peer;
291 * As we are not sending any hello messages to this destination
292 * finger, we are only searching for it, we can just send 64 bit.
293 * Finger id to which we want to set up the trail to.
295 struct GNUNET_PeerIdentity destination_finger; */
298 * Finger id to which we want to set up the trail to.
300 uint64_t destination_finger;
303 * If set to 1, then we are looking for trail to our immediate successor.
305 unsigned int successor_flag;
308 * If the message is forwarded to finger or friend.
310 enum current_destination_type current_destination_type;
313 * This field contains the peer to which this packet is forwarded.
315 struct GNUNET_PeerIdentity current_destination;
318 * Number of entries in trail list.
319 * FIXME: Is this data type correct?
320 * FIMXE: Is usage of GNUNET_PACKED correct?
322 uint32_t trail_length GNUNET_PACKED;
324 /* FIXME: Add this field later.
325 * The finger index in finger map.
326 unsigned int finger_index;*/
333 struct PeerVerifySuccessor
342 struct PeerVerifySuccessorResult
350 struct PeerNotifyNewSuccessor
355 * P2P Trail setup Result message
357 struct PeerTrailSetupResultMessage
360 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_RESULT_SETUP
362 struct GNUNET_MessageHeader header;
365 * Finger to which we have found the path.
367 struct GNUNET_PeerIdentity finger;
370 * Peer which was looking for the trail to finger.
372 struct GNUNET_PeerIdentity destination_peer;
375 * This field contains the peer to which this packet is forwarded.
377 struct GNUNET_PeerIdentity current_destination;
380 * FIXME: Temporary field used to remember at which index we should read
381 * to get our next peer.
383 unsigned int current_index;
386 * If set to 1, then this trail is the trail to succcessor of our finger.
388 unsigned int successor_flag;
391 * Number of entries in trail list.
392 * FIXME: Is this data type correct?
393 * FIXME: Is usage of GNUNET_PACKED correct?
395 uint32_t trail_length GNUNET_PACKED;
399 GNUNET_NETWORK_STRUCT_END
403 * Linked list of messages to send to a particular other peer.
405 struct P2PPendingMessage
408 * Pointer to next item in the list
410 struct P2PPendingMessage *next;
413 * Pointer to previous item in the list
415 struct P2PPendingMessage *prev;
418 * When does this message time out?
420 struct GNUNET_TIME_Absolute timeout;
423 * Message importance level. FIXME: used? useful?
425 unsigned int importance;
428 * Actual message to be sent, allocated at the end of the struct:
429 * // msg = (cast) &pm[1];
430 * // memcpy (&pm[1], data, len);
432 const struct GNUNET_MessageHeader *msg;
438 * Linked List of peers which are part of trail to reach a particular Finger.
443 * Pointer to next item in the list
445 struct TrailPeerList *next;
448 * Pointer to previous item in the list
450 struct TrailPeerList *prev;
453 * An element in this trail list
455 struct GNUNET_PeerIdentity peer;
461 * Entry in friend_peermap.
466 * What is the identity of the peer?
468 struct GNUNET_PeerIdentity id;
471 * Count of outstanding messages for peer.
473 unsigned int pending_count;
476 * Successor of this finger.
478 struct GNUNET_PeerIdentity successor_identity;
481 * Predecessor of this finger.
483 struct GNUNET_PeerIdentity predecessor_identity;
486 * Head of pending messages to be sent to this peer.
488 struct P2PPendingMessage *head;
491 * Tail of pending messages to be sent to this peer.
493 struct P2PPendingMessage *tail;
496 * TODO - How and where to use this?
497 * Core handle for sending messages to this peer.
499 struct GNUNET_CORE_TransmitHandle *th;
505 * FIXME: As in chord , where we store the actual finger identity we were looking
506 * for and the real id which we got as successor. If we want to store like that
507 * then we will need to add a new field and search actual peer id.
508 * FIXME: Should we use another PeerIdentity which is smaller
509 * than 256 bits while storing.
511 * finger_identity is the actual finger that we were looking for.
512 * successor is the peer id which is our finger in place of finger_identity
513 * that we were actually looking for. It may happen that finger_identity
514 * was not in the network and we found the successor closest to that
516 * Predcessor is needed in case of node join/fail.
517 * Entry in finger_peermap.
524 struct GNUNET_PeerIdentity finger_identity;
527 * If 1, then this finger entry is first finger /successor of the peer.
529 unsigned int successor;
531 * List of peers in the trail.
533 const struct GNUNET_PeerIdentity *trail_peer_list;
537 * Task that sends FIND FINGER TRAIL requests.
539 static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task;
542 * FIXME: As we should check for our immediate successor
543 * in case of node join/fail, the immediate successor will change.
544 * Hence we define a process which will be scheduled in regular interval.
545 * But you should schedule this process once you have found your successor.
546 * so, in finger_table_add_entry, when finger_peermap is size 1 then start
547 * this task, and periodically call it within it self like find_finger_trail_setup
549 * Task that periodically checks for the immediate successor.
551 static GNUNET_SCHEDULER_TaskIdentifier verify_successor;
554 * Identity of this peer.
556 static struct GNUNET_PeerIdentity my_identity;
559 * FIXME: Not used anywhere in the code yet.
560 * Hash of the identity of this peer.
562 static struct GNUNET_HashCode my_identity_hash;
565 * Hash map of all the friends of a peer
567 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap;
570 * Hash map of all the fingers of a peer
572 static struct GNUNET_CONTAINER_MultiPeerMap *finger_peermap;
575 * TODO: Ask whats the use of ATS.
578 static struct GNUNET_ATS_PerformanceHandle *atsAPI;
583 static struct GNUNET_CORE_Handle *core_api;
586 * The current finger index that we have found trail to.
588 static unsigned int current_finger_index;
592 * Called when core is ready to send a message we asked for
593 * out to the destination.
595 * @param cls the 'struct PeerInfo' of the target peer
596 * @param size number of bytes available in buf
597 * @param buf where the callee should write the message
598 * @return number of bytes written to buf
601 core_transmit_notify (void *cls, size_t size, void *buf)
603 struct FriendInfo *peer = cls;
605 struct P2PPendingMessage *pending;
610 while ((NULL != (pending = peer->head)) &&
611 (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us))
613 peer->pending_count--;
614 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
615 GNUNET_free (pending);
619 /* no messages pending */
625 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
626 GNUNET_CORE_PRIO_BEST_EFFORT,
627 GNUNET_TIME_absolute_get_remaining
628 (pending->timeout), &peer->id,
629 ntohs (pending->msg->size),
630 &core_transmit_notify, peer);
631 GNUNET_break (NULL != peer->th);
635 while ((NULL != (pending = peer->head)) &&
636 (size - off >= (msize = ntohs (pending->msg->size))))
638 GNUNET_STATISTICS_update (GDS_stats,
640 ("# Bytes transmitted to other peers"), msize,
642 memcpy (&cbuf[off], pending->msg, msize);
644 peer->pending_count--;
645 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
646 GNUNET_free (pending);
648 if (peer->head != NULL)
651 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
652 GNUNET_CORE_PRIO_BEST_EFFORT,
653 GNUNET_TIME_absolute_get_remaining
654 (pending->timeout), &peer->id, msize,
655 &core_transmit_notify, peer);
656 GNUNET_break (NULL != peer->th);
663 * Transmit all messages in the friend's message queue.
665 * @param peer message queue to process
668 process_friend_queue (struct FriendInfo *peer)
670 struct P2PPendingMessage *pending;
672 if (NULL == (pending = peer->head))
674 if (NULL != peer->th)
677 GNUNET_STATISTICS_update (GDS_stats,
679 ("# Bytes of bandwidth requested from core"),
680 ntohs (pending->msg->size), GNUNET_NO);
682 /* FIXME: Are we correctly initializing importance and pending. */
684 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
686 GNUNET_TIME_absolute_get_remaining
687 (pending->timeout), &peer->id,
688 ntohs (pending->msg->size),
689 &core_transmit_notify, peer);
690 GNUNET_break (NULL != peer->th);
696 * We add the next destination i.e. friend to which we are sending the packet
697 * to our peer list in the calling function and we also increment trail_length
698 * in calling function i.e. send_find_finger_trail and handle_dht_p2p_trail_setup.
699 * Here we only copy the whole trail into our peer_list.
700 * Setup the trail message and forward it to a friend.
701 * @param source_peer Peer which wants to set up the trail to one of its finger.
702 * @param destination_finger Peer to which we want to set up the trail to.
703 * @param current_destination Current peer to which this message should be forwarded.
704 * @param trail_length Numbers of peers in the trail.
705 * @param trail_peer_list peers this request has traversed so far
706 * @param successor_flag If 1 then we are looking for trail to our successor.
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,
714 unsigned int successor_flag)
716 struct P2PPendingMessage *pending;
717 struct PeerTrailSetupMessage *tsm;
718 struct GNUNET_PeerIdentity *peer_list;
721 msize = sizeof(struct PeerTrailSetupMessage) +
722 (trail_length * sizeof(struct GNUNET_PeerIdentity));
724 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
730 if (current_destination->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
732 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
736 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
737 pending->importance = 0; /* FIXME */
738 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
739 tsm = (struct PeerTrailSetupMessage *) &pending[1];
740 pending->msg = &tsm->header;
741 tsm->header.size = htons (msize);
742 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
743 memcpy(&(tsm->destination_finger), destination_finger, sizeof (uint64_t)); //FIXME: Is this copy correct?
744 memcpy(&(tsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity));
745 memcpy(&(tsm->current_destination),&(current_destination->id), sizeof (struct GNUNET_PeerIdentity));
746 tsm->current_destination_type = htonl(FRIEND);
747 tsm->trail_length = htonl(trail_length);
748 if(successor_flag == 1)
749 tsm->successor_flag = 1;
750 peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * trail_length);
751 peer_list = (struct GNUNET_PeerIdentity *) &tsm[1];
752 memcpy(peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
754 GNUNET_CONTAINER_DLL_insert_tail (current_destination->head, current_destination->tail, pending);
755 current_destination->pending_count++;
756 process_friend_queue (current_destination);
761 * Handle a tail setup result message.
762 * @param destination_peer Peer which will get the trail to one of its finger.
763 * @param source_finger Peer to which the trail has been setup to.
764 * @param current_destination Current peer to which this message should be forwarded.
765 * @param trail_length Numbers of peers in the trail.
766 * @param trail_peer_list peers this request has traversed so far
767 * @param current_trail_index Index in trail_peer_list.
770 GDS_NEIGHBOURS_handle_trail_setup_result(struct GNUNET_PeerIdentity *destination_peer,
771 struct GNUNET_PeerIdentity *source_finger,
772 struct FriendInfo *current_destination,
773 unsigned int trail_length,
774 const struct GNUNET_PeerIdentity *trail_peer_list,
775 unsigned int current_trial_index,
776 unsigned int successor_flag)
778 struct P2PPendingMessage *pending;
779 struct PeerTrailSetupResultMessage *tsrm;
780 struct GNUNET_PeerIdentity *peer_list;
783 msize = sizeof(struct PeerTrailSetupMessage) +
784 (trail_length * sizeof(struct GNUNET_PeerIdentity));
786 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
792 if (current_destination->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
794 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
798 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
799 pending->importance = 0; /* FIXME */
800 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
801 tsrm = (struct PeerTrailSetupResultMessage *) &pending[1];
802 pending->msg = &tsrm->header;
803 tsrm->header.size = htons (msize);
804 tsrm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT);
805 memcpy(&(tsrm->current_destination), &(current_destination->id), sizeof(struct GNUNET_PeerIdentity));
806 memcpy(&(tsrm->destination_peer), destination_peer, sizeof(struct GNUNET_PeerIdentity));
807 memcpy(&(tsrm->finger), source_finger, sizeof(struct GNUNET_PeerIdentity));
808 tsrm->trail_length = htonl(trail_length);
809 tsrm->current_index = htonl(current_trial_index);
810 tsrm->successor_flag = htonl(successor_flag);
811 peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1];
812 memcpy(peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
814 /* Send the message to chosen friend. */
815 GNUNET_CONTAINER_DLL_insert_tail (current_destination->head, current_destination->tail, pending);
816 current_destination->pending_count++;
817 process_friend_queue (current_destination);
822 * This function is called from send_verify_successor_message funciton
823 * and handle_dht_p2p_verify_successor.
824 * Construct a PeerVerifySuccessor message and send it to friend.
826 void GDS_NEIGUBOURS_handle_verify_successor()
828 /* In this funciton, you receive
830 2. trial to reach that successor
832 4. current trail index --> this gives the next_hop on whose pending queue you should
838 * this function will be called by destination successor.
839 * Construct a PeerVerifySuccessorResult message and send it to friend.
841 void GDS_NEIGHBOURS_handle_verify_successor_result()
843 /* In this funciton, you receive
845 2. trial to reach that successor
847 4. current trail index --> this gives the next_hop on whose pending queue you should
853 * Construct a PeerNotifyNewSuccessor message and send it to friend.
855 void GDS_NEIGHBOURS_handle_notify_new_successor()
861 /**FIXME: Old implementation just to remove error
862 * TODO: Modify this function to handle our get request.
863 * Perform a GET operation. Forwards the given request to other
864 * peers. Does not lookup the key locally. May do nothing if this is
865 * the only peer in the network (or if we are the closest peer in the
868 * @param type type of the block
869 * @param options routing options
870 * @param desired_replication_level desired replication count
871 * @param hop_count how many hops did this request traverse so far?
872 * @param key key for the content
873 * @param xquery extended query
874 * @param xquery_size number of bytes in @a xquery
875 * @param reply_bf bloomfilter to filter duplicates
876 * @param reply_bf_mutator mutator for @a reply_bf
877 * @param peer_bf filter for peers not to select (again)
880 GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
881 enum GNUNET_DHT_RouteOption options,
882 uint32_t desired_replication_level,
883 uint32_t hop_count, const struct GNUNET_HashCode * key,
884 const void *xquery, size_t xquery_size,
885 const struct GNUNET_CONTAINER_BloomFilter *reply_bf,
886 uint32_t reply_bf_mutator,
887 struct GNUNET_CONTAINER_BloomFilter *peer_bf)
891 1. take the key, get the 64 bit value of the key.
892 2. call find_successor to get the successor of the key.
893 3. successor can be either a friend or finger.
894 4. update the field in get message to reflect if its a friend or finger table
895 5. add the put message to pending message and send it.
899 /**FIXME: Old implementation just to remove error.
900 * TODO: Modify this function to handle our put request.
901 * Perform a PUT operation. Forwards the given request to other
902 * peers. Does not store the data locally. Does not give the
903 * data to local clients. May do nothing if this is the only
904 * peer in the network (or if we are the closest peer in the
907 * @param type type of the block
908 * @param options routing options
909 * @param desired_replication_level desired replication count
910 * @param expiration_time when does the content expire
911 * @param hop_count how many hops has this message traversed so far
912 * @param bf Bloom filter of peers this PUT has already traversed
913 * @param key key for the content
914 * @param put_path_length number of entries in @a put_path
915 * @param put_path peers this request has traversed so far (if tracked)
916 * @param data payload to store
917 * @param data_size number of bytes in @a data
920 GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
921 enum GNUNET_DHT_RouteOption options,
922 uint32_t desired_replication_level,
923 struct GNUNET_TIME_Absolute expiration_time,
925 struct GNUNET_CONTAINER_BloomFilter *bf,
926 const struct GNUNET_HashCode *key,
927 unsigned int put_path_length,
928 struct GNUNET_PeerIdentity *put_path,
929 const void *data, size_t data_size)
933 1. take the key, get the 64 bit value of the key.
934 2. call find_successor to get the successor of the key.
935 3. successor can be either a friend or finger.
936 4. update the field in put message to reflect if its a friend or finger table
937 5. add the put message to pending message and send it.
943 * FIXME: Check if this function actually iterates or not.
944 * Randomly choose one of your friends from the friends_peer map
947 static struct FriendInfo *
948 select_random_friend()
950 unsigned int current_size;
953 struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
954 struct GNUNET_PeerIdentity key_ret;
955 struct FriendInfo *friend;
957 current_size = GNUNET_CONTAINER_multipeermap_size(friend_peermap);
959 /* Element stored at this index in friend_peermap should be selected friend. */
960 index = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, current_size);
962 /* Create an iterator for friend_peermap. */
963 iter = GNUNET_CONTAINER_multipeermap_iterator_create(friend_peermap);
965 /* Set the position of iterator to index. */
968 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(iter,NULL,NULL))
970 /* FIXME: I don't think we are actually incrementing iter. iter is always
971 pointing to the same element. */
978 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(iter,&key_ret,(const void **)&friend))
988 * Compute finger_identity to which we want to setup the trail
989 * FIXME: If we maintain a index that is value of current_finger_index
990 * to which a particular entry in finger map corresponds then should we first
991 * check if there is already an entry for that index. If yes then don't
992 * search for trail to that finger.
993 * @return finger_identity
996 compute_finger_identity()
999 uint64_t *finger_identity64;
1001 my_id64 = GNUNET_malloc (sizeof (uint64_t));
1002 finger_identity64 = GNUNET_malloc (sizeof (uint64_t));
1004 memcpy(my_id64, &(my_identity.public_key.q_y), sizeof (uint64_t));
1005 *finger_identity64 = fmod ((*my_id64 + pow (2,current_finger_index)),( (pow (2,MAX_FINGERS))));
1007 return finger_identity64;
1012 * TODO: Implement after testing friend/finger map.
1013 * TODO: Handle the case when we already have a trail to our predecessor in
1015 * This function will be needed when we are handling node joins/fails
1016 * to maintain correct pointer to our predecessor and successor in the network.
1017 * Find immediate predecessor in the network.
1018 * @param me my own identity
1019 * @return peer identity of immediate predecessor.
1022 find_immediate_predecessor()
1024 /* Using your own peer identity, calculate your predecessor
1025 * in the network. Try to setup path to this predecessor using
1026 * the same logic as used for other fingers.
1027 * If we already have a trail to our predecessor then send NULL and
1028 * calling function should be able to handle that case.
1030 /* FIXME: O could be a valid peer id, return something else. */
1036 * Periodically verify your own immediate successor and
1037 * tell your successor about yourself.
1039 * @param cls closure for this task
1040 * @param tc the context under which the task is running
1043 send_verify_successor_message(void *cls,
1044 const struct GNUNET_SCHEDULER_TaskContext *tc )
1048 * Should we have a new message type
1049 * 1. like who is your predecessor.
1052 1. ask your immediate successor ( its stored in your finger table with
1053 field that notes that its immediate successor) who is its predecessor.
1054 2. Then after getting the reply, check if its you.
1055 3. If not then update the new successor and your successor
1056 and notify the new successor that you are its new predecessor.
1059 /* okay so you first need to construct a messsage that you want to send
1060 to your "successor". but here you should just call another function which
1061 will construct the message and send it to first friend in the trial to
1062 reach our successor. */
1063 struct GNUNET_TIME_Relative next_send_time;
1064 //struct GNUNET_PeerIdentity *successor;
1065 //struct FingerInfo *finger;
1067 /* Iterate over your finger peermap to find the element with successor field set.
1068 That field is your successor. */
1070 /* In this function you should send your successor id, trail to reach that successor,
1071 trail_length, current_trial_index. */
1072 GDS_NEIGUBOURS_handle_verify_successor();
1074 /* FIXME: Use a random value so that this message is send not at the same
1075 interval as send_find_finger_trail_message. */
1076 next_send_time.rel_value_us =
1077 DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
1078 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1079 DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us /
1080 (current_finger_index + 1));
1083 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_verify_successor_message,
1089 * Task to send a find finger trail message. We attempt to find trail
1090 * to our finger and successor in the network.
1092 * @param cls closure for this task
1093 * @param tc the context under which the task is running
1096 send_find_finger_trail_message (void *cls,
1097 const struct GNUNET_SCHEDULER_TaskContext *tc)
1099 struct FriendInfo *friend;
1100 struct GNUNET_TIME_Relative next_send_time;
1101 uint64_t *finger_identity; /* FIXME: Better variable name */
1102 struct GNUNET_PeerIdentity *peer_list;
1103 unsigned int successor_flag; /* set to 1 if we are looking for first finger/
1104 our succcessor, else 0. */
1106 /* We already have found trail to each of our possible fingers in the network. */
1107 if (GNUNET_CONTAINER_multipeermap_size (finger_peermap) == MAX_FINGERS)
1109 /* FIXME: I call find_immediate_predecessor when I have found trail to
1110 * all the possible fingers in the network. But we need to find immediate
1111 * predecessor when there is a node failure/join. It may happen before.
1112 * Think of a better strategy to decide when to call this function.
1113 * We can find trail to our immediate predecessor in the network.
1114 * I think its better to call this after we have trail to our successor set up.
1116 finger_identity = find_immediate_predecessor();
1118 if(NULL == finger_identity)
1120 /* We already have a trail to reach to immediate predecessor. */
1121 goto new_find_finger_trail_request;
1126 finger_identity = compute_finger_identity();
1128 if(finger_identity == NULL)
1130 goto new_find_finger_trail_request;
1134 if(0 == current_finger_index)
1136 /* We are searching for our successor in the network. */
1139 friend = GNUNET_malloc (sizeof (struct FriendInfo));
1140 friend = select_random_friend();
1142 /* We found a friend.*/
1145 unsigned int trail_length = 2;
1146 peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * trail_length);
1147 memcpy(&peer_list[0], &(my_identity), sizeof (struct GNUNET_PeerIdentity));
1148 memcpy(&peer_list[1], &(friend->id), sizeof (struct GNUNET_PeerIdentity));
1149 GDS_NEIGHBOURS_handle_trail_setup(&my_identity, finger_identity,
1150 friend, trail_length, peer_list,successor_flag);
1153 /* FIXME: Should we be using current_finger_index to generate random interval.*/
1154 new_find_finger_trail_request:
1155 next_send_time.rel_value_us =
1156 DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
1157 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1158 DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us /
1159 (current_finger_index + 1));
1161 find_finger_trail_task =
1162 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_finger_trail_message,
1168 * Method called whenever a peer connects.
1170 * @param cls closure
1171 * @param peer peer identity this notification is about
1174 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
1176 struct FriendInfo *ret;
1178 /* Check for connect to self message */
1179 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
1182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1183 "Connected to %s\n",
1186 /* If peer already exists in our friend_peermap, then exit. */
1188 GNUNET_CONTAINER_multipeermap_contains (friend_peermap,
1195 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
1199 ret = GNUNET_new (struct FriendInfo);
1202 GNUNET_assert (GNUNET_OK ==
1203 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
1205 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1208 /* got a first connection, good time to start with FIND FINGER TRAIL requests... */
1209 if (1 == GNUNET_CONTAINER_multipeermap_size (friend_peermap))
1210 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
1215 * FIXME: Implement after testing finger/friend table setup.
1216 * Method called whenever a peer disconnects.
1218 * @param cls closure
1219 * @param peer peer identity this notification is about
1222 handle_core_disconnect (void *cls,
1223 const struct GNUNET_PeerIdentity *peer)
1226 * 1. remove the friend from the friend map.
1227 * 2. remove the trail for the fingers for which this peer was the first hop.
1228 * 3. start send_find_finger_trail for these fingers to find a new trail
1230 * 4. Also when a node gets disconnected, how should we update pointers of its
1231 * immediate successor and predecessor in the network ?
1232 * 5. Also how do we distribute the keys in the network?
1233 * 6. Here is case where we started put operation but a peer got disconnected and
1234 we removed the entry from the table. How to handle such a case.
1240 * To be called on core init/fail.
1242 * @param cls service closure
1243 * @param identity the public identity of this peer
1246 core_init (void *cls,
1247 const struct GNUNET_PeerIdentity *identity)
1249 my_identity = *identity;
1250 GNUNET_CRYPTO_hash (identity,
1251 sizeof (struct GNUNET_PeerIdentity),
1258 * Core handler for p2p put requests.
1260 * @param cls closure
1261 * @param peer sender of the request
1262 * @param message message
1263 * @param peer peer identity this notification is about
1264 * @return #GNUNET_OK to keep the connection open,
1265 * #GNUNET_SYSERR to close it (signal serious error)
1268 handle_dht_p2p_put (void *cls,
1269 const struct GNUNET_PeerIdentity *peer,
1270 const struct GNUNET_MessageHeader *message)
1273 1. Check if destination is friend or finger.
1274 2. If finger then get the next hop from routing table and
1275 * call GDS_NEGIHBOURS_handle_get.
1276 3. If friend then call find_successor to get the next hop and again
1277 * call GDS_NEIGHBOURS_handle_get to send to chosen hop.
1278 4. If you are the destination then do datacache_store.
1285 * Core handler for p2p get requests.
1287 * @param cls closure
1288 * @param peer sender of the request
1289 * @param message message
1290 * @return #GNUNET_OK to keep the connection open,
1291 * #GNUNET_SYSERR to close it (signal serious error)
1294 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
1295 const struct GNUNET_MessageHeader *message)
1298 1. Check if destination is friend or finger.
1299 2. If finger then get the next hop from routing table and
1300 * call GDS_NEGIHBOURS_handle_get.
1301 3. If friend then call find_successor to get the next hop and again
1302 * call GDS_NEIGHBOURS_handle_get to send to chosen hop.
1303 4. If you are the destination then send the data back to source peer
1304 * Assuming we have trail setup we can
1305 * either store the whole trail or again do the search process..
1311 * Compare two peer identities. Used with qsort or bsearch.
1313 * @param p1 Some peer identity.
1314 * @param p2 Some peer identity.
1315 * @return 1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2.
1318 peer_id_cmp (const void *p1, const void *p2)
1320 return memcmp (p1, p2, sizeof (uint64_t));
1324 * Returns the previous element of value in all_known_peers.
1325 * @param all_known_peers list of all the peers
1326 * @param value value we have to search in the all_known_peers.
1329 static struct GNUNET_PeerIdentity *
1330 binary_search(struct GNUNET_PeerIdentity *all_known_peers, uint64_t *value,
1335 unsigned int middle;
1336 struct GNUNET_PeerIdentity *successor;
1337 successor = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1341 middle = (first + last)/2;
1343 while(first <= last)
1345 /* all_known_peers[middle] > value*/
1346 if(0 > peer_id_cmp(&all_known_peers[middle], &value))
1350 else if(0 == peer_id_cmp(&all_known_peers[middle], &value))
1354 successor = &(all_known_peers[size - 1]);
1357 successor = &(all_known_peers[middle-1]);
1364 middle = (first + last)/2;
1372 * Find closest successor for the value.
1373 * @param value Value for which we are looking for successor
1374 * @param current_destination NULL if my_identity is successor else finger/friend
1376 * @param type Next destination type
1377 * @return Peer identity of next destination i.e. successor of value.
1379 static struct GNUNET_PeerIdentity *
1380 find_successor(uint64_t *value, struct GNUNET_PeerIdentity *current_destination,
1381 enum current_destination_type *type)
1383 /* 1. Create an array and copy all the peer identites from finger_peermap,
1384 friend_peermap, your own identity and value you are searching.
1386 3. Do a binary search on array to find the location of your value.
1387 4. previous element of the value is your successor.
1388 5. search for the successor in friend/finger/my_identity .
1389 6. if my_identity, then return NULL and set type to my_identity
1390 7. if friend, then return friend->id and set type to friend.
1391 8. if finger, then set current_destination = finger and return the first
1392 element from the trail list of finger as next_hop. */
1393 struct GNUNET_CONTAINER_MultiPeerMapIterator *friend_iter;
1394 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1395 struct GNUNET_PeerIdentity key_ret;
1396 struct FriendInfo *friend;
1397 struct FingerInfo *finger;
1398 unsigned int finger_index;
1399 unsigned int friend_index;
1400 struct GNUNET_PeerIdentity *all_known_peers;
1401 struct GNUNET_PeerIdentity *successor;
1404 /* SUPU: 2 is added for my_identity and value. */
1405 size = GNUNET_CONTAINER_multipeermap_size (friend_peermap)+
1406 GNUNET_CONTAINER_multipeermap_size (finger_peermap)+
1409 all_known_peers = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * size);
1412 memcpy(&all_known_peers[j], &(my_identity), sizeof (struct GNUNET_PeerIdentity));
1414 memcpy(&all_known_peers[j], value, sizeof(struct GNUNET_PeerIdentity));
1416 /* Iterate over friend peermap and copy all the elements into array. */
1417 friend_iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1418 for (friend_index = 0; friend_index < GNUNET_CONTAINER_multipeermap_size (friend_peermap); friend_index++)
1420 /* FIXME: I don't think we are actually iterating.
1421 Read about how to iterate over the multipeermap. */
1422 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(friend_iter,&key_ret,(const void **)&friend))
1424 memcpy(&all_known_peers[j], &(friend->id), sizeof (struct GNUNET_PeerIdentity));
1429 /* Iterate over finger map and copy all the entries into all_known_peers array. */
1430 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap);
1431 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++)
1433 /* FIXME: I don't think we are actually iterating.
1434 Read about how to iterate over the multi peer map. */
1435 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(finger_iter,&key_ret,(const void **)&finger))
1437 memcpy(&all_known_peers[j], &(finger->finger_identity), sizeof (struct GNUNET_PeerIdentity));
1442 qsort(all_known_peers, size, sizeof (struct GNUNET_PeerIdentity), &peer_id_cmp);
1444 /* search value in all_known_peers array. */
1445 successor = binary_search(all_known_peers, value, size);
1447 /* compare successor with my_identity, finger and friend */
1448 if(0 == GNUNET_CRYPTO_cmp_peer_identity(&(my_identity), successor))
1453 else if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (friend_peermap,
1457 memcpy(current_destination, successor, sizeof (struct GNUNET_PeerIdentity));
1460 else if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (finger_peermap,
1464 memcpy(current_destination, successor, sizeof (struct GNUNET_PeerIdentity));
1465 /* get the corresponding finger for succcesor and read the first element from
1466 the trail list and return that element. */
1467 struct FingerInfo *successor_finger;
1468 struct GNUNET_PeerIdentity *next_hop;
1469 next_hop = GNUNET_malloc(sizeof (struct GNUNET_PeerIdentity));
1470 successor_finger = GNUNET_malloc (sizeof (struct FingerInfo));
1471 successor_finger = GNUNET_CONTAINER_multipeermap_get (finger_peermap, successor);
1472 memcpy(next_hop, &(successor_finger->trail_peer_list[0]), sizeof (struct GNUNET_PeerIdentity));
1480 * Handle a PeerTrailSetupMessage.
1481 * @param cls closure
1482 * @param message message
1483 * @param peer peer identity this notification is about
1484 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1487 handle_dht_p2p_trail_setup(void *cls, const struct GNUNET_PeerIdentity *peer,
1488 const struct GNUNET_MessageHeader *message)
1490 struct PeerTrailSetupMessage *trail_setup;
1491 struct GNUNET_PeerIdentity *next_hop;
1492 struct FriendInfo *target_friend;
1494 uint32_t trail_length;
1495 enum current_destination_type peer_type;
1496 struct GNUNET_PeerIdentity *trail_peer_list;
1497 uint32_t current_trail_index;
1498 struct GNUNET_PeerIdentity *next_peer;
1501 /* parse and validate message. */
1502 msize = ntohs (message->size);
1503 if (msize < sizeof (struct PeerTrailSetupMessage))
1505 GNUNET_break_op (0);
1509 trail_setup = (struct PeerTrailSetupMessage *) message;
1510 trail_length = ntohl (trail_setup->trail_length);
1511 peer_type = ntohl (trail_setup->current_destination_type);
1512 trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_setup[1];
1515 sizeof (struct PeerTrailSetupMessage) +
1516 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
1518 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
1520 GNUNET_break_op (0);
1521 return GNUNET_YES; /*TODO: Why do we send GNUNET_YES here? */
1525 GNUNET_STATISTICS_update (GDS_stats,
1526 gettext_noop ("# TRAIL SETUP requests received"), 1,
1528 GNUNET_STATISTICS_update (GDS_stats,
1529 gettext_noop ("# TRAIL SETUP bytes received"), msize,
1532 if(peer_type == FRIEND)
1534 if(0 == (GNUNET_CRYPTO_cmp_peer_identity(&(trail_setup->current_destination),&my_identity)))
1536 next_hop = find_successor(&(trail_setup->destination_finger),&(trail_setup->current_destination),&(peer_type));
1539 return GNUNET_SYSERR; /*TODO: Should we handle this case differently? */
1541 else if(peer_type == FINGER)
1543 if(0 != (GNUNET_CRYPTO_cmp_peer_identity(&(trail_setup->current_destination),&my_identity)))
1545 /* I am part of trail.
1546 SUPU: So, I should ask for next hop to reach the current_destination which is the finger
1547 for which this packet has been sent. */
1548 next_hop = GDS_ROUTING_search(&(trail_setup->source_peer),&(trail_setup->current_destination));
1551 call find_successor and compare the two peer ids
1552 and choose whichever is closest to the destination finger. */
1556 /* I am the current_destination finger
1557 FIXME: Why are we sending current_destination to find_successor.
1558 In this case, is it safe to assume current_Destination = my_identity.
1559 I guess we are sending current_destination so that we update it with new
1560 current_destination, if could either me, friend or finger.*/
1561 next_hop = find_successor(&(trail_setup->destination_finger),&(trail_setup->current_destination),&(peer_type));
1565 /* If you are the next hop */
1566 if(peer_type == MY_ID)
1568 /* FIXME: Verify if its allowed here to definer peer_list and define it
1569 again in the next block below? */
1570 struct GNUNET_PeerIdentity *peer_list;
1571 peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * (trail_length));
1572 memcpy(peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1573 current_trail_index = trail_length - 2;
1574 next_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); //FIXME: Do we need to allocate the memory?
1575 memcpy(next_peer, &peer_list[current_trail_index], sizeof (struct GNUNET_PeerIdentity));
1577 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_peer);
1579 /* FIXME: It does not find a friend. Could be possible error in find_successor
1580 function. Change the logic in find_successor and change it again. */
1582 /* FIXME: Here as destination_finger is 64 bit instead of struct
1583 GNUNET_PeerIdentity, but you need destination_peer id. If you calling the
1584 function handle_Trail_setup_result from here, it means you are the
1585 destination. So, you can send your own identity. */
1586 GDS_NEIGHBOURS_handle_trail_setup_result(&(trail_setup->source_peer),
1588 target_friend, trail_length,
1589 peer_list,current_trail_index,
1590 trail_setup->successor_flag);
1595 /* Add next_hop to list of peers that trail setup message have traversed so far
1596 and increment trail length. */
1597 struct GNUNET_PeerIdentity *peer_list;
1598 peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * (trail_length + 1));
1599 memcpy(peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1600 memcpy(&peer_list[trail_length], next_hop, sizeof (struct GNUNET_PeerIdentity));
1603 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
1605 if(peer_type == FINGER)
1607 GDS_ROUTING_add(&(trail_setup->source_peer),&(trail_setup->current_destination),next_hop);
1610 GDS_NEIGHBOURS_handle_trail_setup(&(trail_setup->source_peer),
1611 &(trail_setup->destination_finger),
1613 trail_setup->trail_length,
1614 peer_list,trail_setup->successor_flag);
1620 * FIXME : Add interval field.
1621 * When adding successor or predeccsor, update a field to
1622 * specify that this entry is not a finger but immediate
1623 * successor or predeccesor.
1624 * Add an entry in finger table.
1625 * @param finger Finger to be added to finger table
1626 * @param peer_list peers this request has traversed so far
1627 * @param trail_length Numbers of peers in the trail.
1630 void finger_table_add(struct GNUNET_PeerIdentity *finger,
1631 const struct GNUNET_PeerIdentity *peer_list,
1632 unsigned int trail_length,
1633 unsigned int successor_flag)
1635 /*FIXME: okay so there are two fields. one we should remember what finger
1636 identity we were looking for and what successor id we got. */
1637 struct FingerInfo *finger_entry;
1638 finger_entry = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity));
1639 memcpy(&(finger_entry->finger_identity), finger, sizeof(struct GNUNET_PeerIdentity));
1640 memcpy(&(finger_entry->trail_peer_list), peer_list, sizeof(struct GNUNET_PeerIdentity)
1642 finger_entry->successor = successor_flag;
1643 if (1 == GNUNET_CONTAINER_multipeermap_size (finger_peermap))
1644 verify_successor = GNUNET_SCHEDULER_add_now (&send_verify_successor_message, NULL);
1649 * Core handle for p2p trail construction result messages.
1650 * @param cls closure
1651 * @param message message
1652 * @param peer peer identity this notification is about
1653 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1656 handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer,
1657 const struct GNUNET_MessageHeader *message)
1659 struct PeerTrailSetupResultMessage *trail_result;
1661 uint32_t trail_length;
1662 const struct GNUNET_PeerIdentity *trail_peer_list;
1663 uint32_t current_trail_index;
1664 struct GNUNET_PeerIdentity *next_peer;
1665 struct FriendInfo *target_friend;
1667 msize = ntohs (message->size);
1668 if (msize < sizeof (struct PeerTrailSetupMessage))
1670 GNUNET_break_op (0);
1674 trail_result = (struct PeerTrailSetupResultMessage *) message;
1675 trail_length = ntohl (trail_result->trail_length);
1676 current_trail_index = ntohl(trail_result->current_index);
1677 trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_result[1];
1680 sizeof (struct PeerTrailSetupResultMessage) +
1681 trail_length * sizeof (struct GNUNET_PeerIdentity)) ||
1683 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
1685 GNUNET_break_op (0);
1689 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->current_destination), &my_identity)))
1691 /* Am I the destination? */
1692 if( 0 == (GNUNET_CRYPTO_cmp_peer_identity(&(trail_result->destination_peer), &my_identity)))
1694 finger_table_add(&(trail_result->finger), trail_peer_list,trail_length,trail_result->successor_flag);
1699 next_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1700 current_trail_index = current_trail_index - 1;
1701 memcpy(next_peer, &(trail_peer_list[trail_length-1]), sizeof (struct GNUNET_PeerIdentity));
1702 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_peer);
1704 GDS_NEIGHBOURS_handle_trail_setup_result(&(trail_result->destination_peer),
1705 &(trail_result->finger),
1706 target_friend, trail_length,
1707 trail_peer_list,current_trail_index,
1708 trail_result->successor_flag);
1713 return GNUNET_SYSERR;
1718 * Core handle for p2p verify successor messages.
1719 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1722 handle_dht_p2p_verify_successor()
1725 * In this function you have received the message verify successor,
1726 * Now, either you are the destination or just part of the trail.
1727 * As we already know the whole path find out the next destination
1728 * and pass the packet forward.
1729 * If you are the final destination, check who is your predecessor.
1730 * and send your predecessor back to calling function.
1731 * FIXME: Should we have a different handler function for it.
1737 * Core handle for p2p notify successor messages.
1738 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1741 handle_dht_p2p_notify_new_successor()
1744 * So, if you are the destination you should update your
1745 * predecessor field with peer id of source peer of this message.
1746 * If you are not the destination peer, then just check your routing
1747 * table and pass on the message.
1753 * Core handle for p2p verify successor result messages.
1754 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1757 handle_dht_p2p_verify_successor_result()
1760 * In this function you have received the message verify successor result,
1761 If you are not the destination, just pass this message forward
1762 * if you are destination,
1763 * then check if immediate predecessor of this peer is you or someone else.
1764 * If its you, then don't do anything.
1765 * If its some one else, then call notify method to let your new successor
1766 * know that you are its predecessor.
1773 * Initialize neighbours subsystem.
1774 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1777 GDS_NEIGHBOURS_init()
1779 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1780 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0},
1781 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0},
1782 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP, 0},
1783 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT, 0},
1784 {&handle_dht_p2p_verify_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR, 0},
1785 {&handle_dht_p2p_notify_new_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR, 0},
1786 {&handle_dht_p2p_verify_successor_result, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT, 0},
1790 /*TODO: What is ATS? Why do we need it? */
1791 atsAPI = GNUNET_ATS_performance_init (GDS_cfg, NULL, NULL);
1793 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
1794 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
1795 GNUNET_NO, core_handlers);
1796 if (core_api == NULL)
1797 return GNUNET_SYSERR;
1799 friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1800 finger_peermap = GNUNET_CONTAINER_multipeermap_create (MAX_FINGERS, GNUNET_NO);
1807 * Shutdown neighbours subsystem.
1810 GDS_NEIGHBOURS_done ()
1812 if (NULL == core_api)
1815 GNUNET_CORE_disconnect (core_api);
1817 GNUNET_ATS_performance_done (atsAPI);
1820 /* FIXME: Once handle_core_disconnect is implemented, both below assertion should not
1822 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
1823 GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
1824 friend_peermap = NULL;
1826 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (finger_peermap));
1827 GNUNET_CONTAINER_multipeermap_destroy (finger_peermap);
1828 finger_peermap = NULL;
1830 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
1832 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
1833 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
1836 /* FIXME: fix_fingers will also be a task like this.
1838 if (GNUNET_SCHEDULER_NO_TASK != verify_successor)
1840 GNUNET_SCHEDULER_cancel (verify_successor);
1841 verify_successor = GNUNET_SCHEDULER_NO_TASK;
1848 * Get the ID of the local node.
1850 * @return identity of the local node
1852 struct GNUNET_PeerIdentity *
1853 GDS_NEIGHBOURS_get_id ()
1855 return &my_identity;
1859 /* end of gnunet-service-xdht_neighbours.c */