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 logic to get connected to your predecessor
54 because when nodes join/fail , you need to maintain correct
55 pointers to predecessor and your successor (your first finger),
57 2. Remove extra comments - FIXME,TODO,SUPU
58 3. When do we call GDS_Routing_add()? */
61 * Maximum possible fingers of a peer.
63 #define MAX_FINGERS 256
66 * Maximum allowed number of pending messages per friend peer.
68 #define MAXIMUM_PENDING_PER_FRIEND 64
71 * How long at least to wait before sending another find finger trail request.
73 #define DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
76 * How long at most to wait before sending another find finger trail request.
78 #define DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 10)
81 GNUNET_NETWORK_STRUCT_BEGIN
84 * 1) Bloomfilter is not required for X-Vine.
85 * Keep the field now but remove it when implementing PUT/GET.
86 * 2) also, check the field of put/get/result if all are required for
95 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
97 struct GNUNET_MessageHeader header;
102 uint32_t options GNUNET_PACKED;
107 uint32_t type GNUNET_PACKED;
112 uint32_t hop_count GNUNET_PACKED;
115 * Replication level for this message
117 uint32_t desired_replication_level GNUNET_PACKED;
120 * Length of the PUT path that follows (if tracked).
122 uint32_t put_path_length GNUNET_PACKED;
125 * When does the content expire?
127 struct GNUNET_TIME_AbsoluteNBO expiration_time;
130 * Bloomfilter (for peer identities) to stop circular routes
132 char bloomfilter[DHT_BLOOM_SIZE];
135 * The key we are storing under.
137 struct GNUNET_HashCode key;
139 /* put path (if tracked) */
149 struct PeerResultMessage
152 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT
154 struct GNUNET_MessageHeader header;
159 uint32_t type GNUNET_PACKED;
162 * Length of the PUT path that follows (if tracked).
164 uint32_t put_path_length GNUNET_PACKED;
167 * Length of the GET path that follows (if tracked).
169 uint32_t get_path_length GNUNET_PACKED;
172 * When does the content expire?
174 struct GNUNET_TIME_AbsoluteNBO expiration_time;
177 * The key of the corresponding GET request.
179 struct GNUNET_HashCode key;
181 /* put path (if tracked) */
183 /* get path (if tracked) */
193 struct PeerGetMessage
196 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET
198 struct GNUNET_MessageHeader header;
203 uint32_t options GNUNET_PACKED;
206 * Desired content type.
208 uint32_t type GNUNET_PACKED;
213 uint32_t hop_count GNUNET_PACKED;
216 * Desired replication level for this request.
218 uint32_t desired_replication_level GNUNET_PACKED;
221 * Size of the extended query.
223 uint32_t xquery_size;
226 * Bloomfilter mutator.
231 * Bloomfilter (for peer identities) to stop circular routes
233 char bloomfilter[DHT_BLOOM_SIZE];
236 * The key we are looking for.
238 struct GNUNET_HashCode key;
244 * FIXME: I have defined this struct between GNUNET_NETWORK_STRUCT_BEGIN. Is
245 * it correct? Also, I am using the same struct inside finger info and trailsetup
246 * trailsetupresult message. Is it correct? */
248 * Linked List of peers which are part of trail to reach a particular Finger.
253 * Pointer to next item in the list
255 struct TrailPeerList *next;
258 * Pointer to previous item in the list
260 struct TrailPeerList *prev;
263 * An element in this trail list
265 struct GNUNET_PeerIdentity *peer;
271 * FIXME : I am using the same structure trail list in both finger info
272 * and peertrailsetupmessage. Verify if its okay.
273 * P2P Trail setup message
275 struct PeerTrailSetupMessage
278 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP
280 struct GNUNET_MessageHeader header;
283 * Source peer which wants to find trail to one of its finger.
285 struct GNUNET_PeerIdentity *source_peer;
288 * Finger id to which we want to set up the trail to.
290 struct GNUNET_PeerIdentity *destination_finger;
293 * This field contains the peer to which this packet is forwarded.
295 struct GNUNET_PeerIdentity *current_destination;
298 * Head of trail list.
300 struct TrailPeerList *head;
303 * Tail of trail list.
305 struct TrailPeerList *tail;
311 * P2P Trail setup Result message
312 * FIXME: There seem to be no difference between trail_setup and trailsetupresult
313 * Can we somehow merge these two. As in result we don't have to do any
314 * search in our finger or friend table thats why I kept it separate. But is it
315 * actually required to keep these two things different.
317 struct PeerTrailSetupResultMessage
320 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_RESULT_SETUP
322 struct GNUNET_MessageHeader header;
324 /* SUPU: It should contain the list of peers which form the trail.
325 and also maintain a pointer to the current_peer to which we have to forward
326 the packet. We have to maintain the whole list in this message because
327 at the end source peer will store this list in its finger table. */
330 * Source peer which wants to find trail to one of its finger.
332 struct GNUNET_PeerIdentity *source_peer;
335 * Finger id to which we want to set up the trail to.
337 struct GNUNET_PeerIdentity *destination_finger;
340 * This field contains the peer to which this packet is forwarded.
342 struct GNUNET_PeerIdentity *current_destination;
345 * Head of trail list.
347 struct TrailPeerList *head;
350 * Tail of trail list.
352 struct TrailPeerList *tail;
356 GNUNET_NETWORK_STRUCT_END
360 * Linked list of messages to send to a particular other peer.
362 struct P2PPendingMessage
365 * Pointer to next item in the list
367 struct P2PPendingMessage *next;
370 * Pointer to previous item in the list
372 struct P2PPendingMessage *prev;
375 * When does this message time out?
377 struct GNUNET_TIME_Absolute timeout;
380 * Message importance level. FIXME: used? useful?
382 unsigned int importance;
385 * Actual message to be sent, allocated at the end of the struct:
386 * // msg = (cast) &pm[1];
387 * // memcpy (&pm[1], data, len);
389 const struct GNUNET_MessageHeader *msg;
394 * Entry in friend_peers map.
400 * What is the identity of the peer?
402 struct GNUNET_PeerIdentity id;
405 * Count of outstanding messages for peer.
407 unsigned int pending_count;
410 * Head of pending messages to be sent to this peer.
412 struct P2PPendingMessage *head;
415 * Tail of pending messages to be sent to this peer.
417 struct P2PPendingMessage *tail;
420 * TODO - How and where to use this?
421 * Core handle for sending messages to this peer.
423 struct GNUNET_CORE_TransmitHandle *th;
428 * Entry in finger_peers map.
433 * What is the identity of the peer?
435 struct GNUNET_PeerIdentity id;
439 * Start of the interval of keys for which this finger is responsible.
441 unsigned int interval_start;
444 * End of the interval of keys for which this finger is responsible.
446 unsigned int interval_end;
449 * Head of trail list.
451 struct TrailPeerList *head;
454 * Tail of trail list.
456 struct TrailPeerList *tail;
462 * Task that sends FIND FINGER TRAIL requests.
464 static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task;
467 * Identity of this peer.
469 static struct GNUNET_PeerIdentity my_identity;
472 * Hash of the identity of this peer.
474 static struct GNUNET_HashCode my_identity_hash;
477 * Hash map of all the friends of a peer
479 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peers;
482 * Hash map of all the fingers of a peer
484 static struct GNUNET_CONTAINER_MultiPeerMap *finger_peers;
489 static struct GNUNET_ATS_PerformanceHandle *atsAPI;
494 static struct GNUNET_CORE_Handle *core_api;
497 * FIXME:where are we using this field.
498 * The highest finger_id that we have found trail to.
500 static unsigned int finger_id;
504 * TODO: Check this function again.
505 * Called when core is ready to send a message we asked for
506 * out to the destination.
508 * @param cls the 'struct FriendInfo' of the target friend peer
509 * @param size number of bytes available in buf
510 * @param buf where the callee should write the message
511 * @return number of bytes written to buf
514 core_transmit_notify (void *cls, size_t size, void *buf)
516 struct FriendInfo *peer = cls;
518 struct P2PPendingMessage *pending;
523 while ((NULL != (pending = peer->head)) &&
524 (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us))
526 peer->pending_count--;
527 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
528 GNUNET_free (pending);
532 /* no messages pending */
538 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
540 GNUNET_TIME_absolute_get_remaining
541 (pending->timeout), &peer->id,
542 ntohs (pending->msg->size),
543 &core_transmit_notify, peer);
544 GNUNET_break (NULL != peer->th);
548 while ((NULL != (pending = peer->head)) &&
549 (size - off >= (msize = ntohs (pending->msg->size))))
551 GNUNET_STATISTICS_update (GDS_stats,
553 ("# Bytes transmitted to other peers"), msize,
555 memcpy (&cbuf[off], pending->msg, msize);
557 peer->pending_count--;
558 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
559 GNUNET_free (pending);
561 if (peer->head != NULL)
564 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
566 GNUNET_TIME_absolute_get_remaining
567 (pending->timeout), &peer->id, msize,
568 &core_transmit_notify, peer);
569 GNUNET_break (NULL != peer->th);
576 * Transmit all messages in the friend's message queue.
578 * @param peer message queue to process
581 process_friend_queue (struct FriendInfo *peer)
584 struct P2PPendingMessage *pending;
586 if (NULL == (pending = peer->head))
588 if (NULL != peer->th)
590 GNUNET_STATISTICS_update (GDS_stats,
592 ("# Bytes of bandwidth requested from core"),
593 ntohs (pending->msg->size), GNUNET_NO);
595 /*FIXME : here I don't know the use of importance, time out
596 Will check at run time if its all correct. */
598 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
600 GNUNET_TIME_absolute_get_remaining
601 (pending->timeout), &peer->id,
602 ntohs (pending->msg->size),
603 &core_transmit_notify, peer);
604 GNUNET_break (NULL != peer->th);
609 * FIXME: Check the parameters.
610 * Set up the trial message and forwards this message to friend.
612 * @param Finger id to which we want to setup the trail.
613 * @param Friend id through which we will try to setup the trail.
616 GDS_NEIGHBOURS_trail_setup(struct GNUNET_PeerIdentity *finger_id,
617 struct FriendInfo *target_friend)
620 * FIXME: check if pending message actually contains the correct data.
622 struct P2PPendingMessage *pending;
623 /* FIXME: why I have defined as **? verify by testing. */
624 struct PeerTrailSetupMessage *tsm;
627 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
629 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
633 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage));
634 tsm = (struct PeerTrailSetupMessage *) &pending[1];
635 pending->msg = &tsm->header;
636 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
637 tsm->destination_finger = finger_id;
638 tsm->source_peer = &my_identity;
639 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
640 target_friend->pending_count++;
641 process_friend_queue(target_friend);
645 /**FIXME: Old implementation just to remove error
646 * TODO: Modify this function to handle our get request.
647 * Perform a GET operation. Forwards the given request to other
648 * peers. Does not lookup the key locally. May do nothing if this is
649 * the only peer in the network (or if we are the closest peer in the
652 * @param type type of the block
653 * @param options routing options
654 * @param desired_replication_level desired replication count
655 * @param hop_count how many hops did this request traverse so far?
656 * @param key key for the content
657 * @param xquery extended query
658 * @param xquery_size number of bytes in @a xquery
659 * @param reply_bf bloomfilter to filter duplicates
660 * @param reply_bf_mutator mutator for @a reply_bf
661 * @param peer_bf filter for peers not to select (again)
664 GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
665 enum GNUNET_DHT_RouteOption options,
666 uint32_t desired_replication_level,
667 uint32_t hop_count, const struct GNUNET_HashCode * key,
668 const void *xquery, size_t xquery_size,
669 const struct GNUNET_CONTAINER_BloomFilter *reply_bf,
670 uint32_t reply_bf_mutator,
671 struct GNUNET_CONTAINER_BloomFilter *peer_bf)
676 /**FIXME: Old implementation just to remove error.
677 * TODO: Modify this function to handle our put request.
678 * Perform a PUT operation. Forwards the given request to other
679 * peers. Does not store the data locally. Does not give the
680 * data to local clients. May do nothing if this is the only
681 * peer in the network (or if we are the closest peer in the
684 * @param type type of the block
685 * @param options routing options
686 * @param desired_replication_level desired replication count
687 * @param expiration_time when does the content expire
688 * @param hop_count how many hops has this message traversed so far
689 * @param bf Bloom filter of peers this PUT has already traversed
690 * @param key key for the content
691 * @param put_path_length number of entries in @a put_path
692 * @param put_path peers this request has traversed so far (if tracked)
693 * @param data payload to store
694 * @param data_size number of bytes in @a data
697 GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
698 enum GNUNET_DHT_RouteOption options,
699 uint32_t desired_replication_level,
700 struct GNUNET_TIME_Absolute expiration_time,
702 struct GNUNET_CONTAINER_BloomFilter *bf,
703 const struct GNUNET_HashCode *key,
704 unsigned int put_path_length,
705 struct GNUNET_PeerIdentity *put_path,
706 const void *data, size_t data_size)
712 /**FIXME: Old implementation just to remove error.
713 * Handle a reply (route to origin). Only forwards the reply back to
714 * other peers waiting for it. Does not do local caching or
715 * forwarding to local clients.
717 * @param target neighbour that should receive the block (if still connected)
718 * @param type type of the block
719 * @param expiration_time when does the content expire
720 * @param key key for the content
721 * @param put_path_length number of entries in put_path
722 * @param put_path peers the original PUT traversed (if tracked)
723 * @param get_path_length number of entries in put_path
724 * @param get_path peers this reply has traversed so far (if tracked)
725 * @param data payload of the reply
726 * @param data_size number of bytes in data
729 GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target,
730 enum GNUNET_BLOCK_Type type,
731 struct GNUNET_TIME_Absolute expiration_time,
732 const struct GNUNET_HashCode * key,
733 unsigned int put_path_length,
734 const struct GNUNET_PeerIdentity *put_path,
735 unsigned int get_path_length,
736 const struct GNUNET_PeerIdentity *get_path,
737 const void *data, size_t data_size)
745 * I have written a code where
746 * 1. I choose a random index from 0 to current size of my map.
747 * 2. Create an iterator.
748 * 3. set the iterator value to the current index id.
749 * 4. get the element stored at that index id.
750 * 5. return the index to calling function.
751 * I have not yet tested this function and I am not sure if its correct.
752 * Randomly choose one of your friends from the friends_peer map
755 static struct FriendInfo *
758 unsigned int current_size;
761 struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
762 struct GNUNET_PeerIdentity key_ret;
763 struct FriendInfo *friend;
765 current_size = GNUNET_CONTAINER_multipeermap_size(friend_peers);
767 /* Element stored at this index in friend_peers map should be chosen friend. */
768 index = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, current_size);
770 /* Create an iterator for friend_peers map. */
771 iter = GNUNET_CONTAINER_multipeermap_iterator_create(friend_peers);
773 /* Set the position of iterator to index. */
776 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(iter,NULL,NULL))
782 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(iter,&key_ret,(const void **)&friend))
792 * TODO: Complete this function.
793 * Use Chord formula finger[i]=(n+2^(i-1))mod m,
794 * where i = current finger map index.
795 * n = own peer identity
796 * m = number of bits in peer id.
797 * @return finger_peer_id for which we have to find the trail through network.
800 struct GNUNET_PeerIdentity *
801 finger_id_to_search()
804 //struct GNUNET_PeerIdentity *finger_peer_id;
806 /*TODO: Add a wrapper in crypto_ecc.c to add an integer do mod operation on integer
807 to find peer id. Take care of parameters. You should work on the value of
808 finger_id not on its pointer.
809 Increment the value of finger_id. */
811 //return finger_peer_id;
817 * FIXME: Implement after testing friend/finger map.
818 * This function will be needed when we are handling node joins/fails
819 * to maintain correct pointer to our predecessor and successor in the network.
820 * Find immediate predecessor in the network.
821 * @param me my own identity
822 * @return peer identity of immediate predecessor.
825 struct GNUNET_PeerIdentity*
826 find_immediate_predecessor()
828 /* Using your own peer identity, calculate your predecessor
829 in the network. Try to setup path to this predecessor using
830 the same logic as used for other fingers. */
836 * Task to send a find finger trail message. We attempt to find trail
837 * to our finger in the network.
839 * @param cls closure for this task
840 * @param tc the context under which the task is running
843 send_find_finger_trail_message (void *cls,
844 const struct GNUNET_SCHEDULER_TaskContext *tc)
846 struct GNUNET_PeerIdentity *finger_peer_id;
847 struct FriendInfo *friend_peer_id;
848 struct GNUNET_TIME_Relative next_send_time;
850 /* We already have found trail to each of our possible fingers in the network. */
851 if (GNUNET_CONTAINER_multipeermap_size(finger_peers) == MAX_FINGERS)
853 /* We can find trail to our immediate predecessor in the network. */
854 finger_peer_id = find_immediate_predecessor();
858 /* Find the finger_peer_id for which we want to setup the trial */
859 finger_peer_id = finger_id_to_search();
862 /* Choose a friend randomly from your friend_peers map. */
863 friend_peer_id = get_random_friend();
865 /* Check if we found a friend or not. */
866 if(NULL != friend_peer_id)
867 GDS_NEIGHBOURS_trail_setup(finger_peer_id, friend_peer_id);
870 next_send_time.rel_value_us =
871 DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
872 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
873 DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us /
876 find_finger_trail_task =
877 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_finger_trail_message,
883 * Method called whenever a peer connects.
886 * @param peer peer identity this notification is about
889 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
891 struct FriendInfo *ret;
893 /* Check for connect to self message */
894 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
897 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
901 /* If peer already exists in our friend_peers, then exit. */
903 GNUNET_CONTAINER_multipeermap_contains (friend_peers,
910 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
913 ret = GNUNET_new (struct FriendInfo);
916 GNUNET_assert (GNUNET_OK ==
917 GNUNET_CONTAINER_multipeermap_put (friend_peers,
919 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
921 /* got a first connection, good time to start with FIND FINGER TRAIL requests... */
922 if (1 == GNUNET_CONTAINER_multipeermap_size(friend_peers))
923 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
928 * FIXME: Implement after testing finger/friend table setup.
929 * Method called whenever a peer disconnects.
932 * @param peer peer identity this notification is about
935 handle_core_disconnect (void *cls,
936 const struct GNUNET_PeerIdentity *peer)
939 * 1. remove the friend from the friend map.
940 * 2. remove the trail for the fingers for which this peer was the first hop.
941 * 3. start send_find_finger_trail for these fingers to find a new trail
943 * 4. Also when a node gets disconnected, how should we update pointers of its
944 * immediate successor and predecessor in the network ?
945 * 5. Also how do we distribute the keys in the network?
946 * 6. Here is case where we started put operation but a peer got disconnected and
947 we removed the entry from the table. How to handle such a case.
954 * To be called on core init/fail.
956 * @param cls service closure
957 * @param identity the public identity of this peer
960 core_init (void *cls,
961 const struct GNUNET_PeerIdentity *identity)
963 my_identity = *identity;
964 GNUNET_CRYPTO_hash (identity,
965 sizeof (struct GNUNET_PeerIdentity),
971 * Core handler for p2p put requests.
974 * @param peer sender of the request
975 * @param message message
976 * @param peer peer identity this notification is about
977 * @return #GNUNET_OK to keep the connection open,
978 * #GNUNET_SYSERR to close it (signal serious error)
981 handle_dht_p2p_put (void *cls,
982 const struct GNUNET_PeerIdentity *peer,
983 const struct GNUNET_MessageHeader *message)
986 1. Search the friend,finger and check your own id to find the closest
987 * predecessor the given key. --> find_predecessor()
988 2. If self then datache_store
989 3. If friend, then add to peer queue
990 4. If finger, then add to the peer queue of the first hop.
991 * in put message also maintain a field current_destination and use
992 * same logic as trail setup to understand if you are just part of trail
993 * to reach to a particular peer or you are endpoint of trail or just a friend.
1001 * Core handler for p2p get requests.
1003 * @param cls closure
1004 * @param peer sender of the request
1005 * @param message message
1006 * @return #GNUNET_OK to keep the connection open,
1007 * #GNUNET_SYSERR to close it (signal serious error)
1010 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
1011 const struct GNUNET_MessageHeader *message)
1018 * Core handler for p2p result messages.
1020 * @param cls closure
1021 * @param message message
1022 * @param peer peer identity this notification is about
1023 * @return #GNUNET_YES (do not cut p2p connection)
1026 handle_dht_p2p_result (void *cls, const struct GNUNET_PeerIdentity *peer,
1027 const struct GNUNET_MessageHeader *message)
1034 * Read the trail setup message backwards to find which is the next hop to which
1035 * it should be send to.
1039 struct GNUNET_PeerIdentity *
1048 * Are we comparing the predecessor with our own identity also.
1050 * Here also we would be comparing the numeric value of
1051 * peer identity. We read the element from our map. Extract
1052 * the peer id and compare it with destination id. But again
1053 * this comparison is on values. Same issue again.
1054 * Find the predecessor for given finger_id from the
1055 * friend and finger table.
1056 * if friend, then just return the friend
1057 * if finger, then return the next hop to forward the packet to and also
1058 * set the current_destination field to finger_id.
1059 * @param destination peer id's predecessor we are looking for.
1062 static struct GNUNET_PeerIdentity *
1063 find_successor(struct GNUNET_PeerIdentity *destination)
1065 unsigned int friend_index;
1066 unsigned int finger_index;
1067 struct GNUNET_CONTAINER_MultiPeerMapIterator *friend_iter;
1068 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1069 struct GNUNET_PeerIdentity key_ret;
1070 struct FriendInfo *friend;
1071 struct FingerInfo *finger;
1073 /* Should I keep a variable to remember if GNUNET_PeerIdentity is
1074 friend or finger. */
1075 friend_iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peers);
1077 /*iterate over friend map till you reach a peer id such that destination <= peer id */
1078 for (friend_index = 0; friend_index < GNUNET_CONTAINER_multipeermap_size (friend_peers); friend_index++)
1080 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(friend_iter,&key_ret,(const void **)&friend))
1083 * 1. Check if friend >= destination.
1084 * 2. If yes then check if friend <= current_predecessor,
1085 * if yes then curret_predecessor = friend.
1086 * 3 If not then do nothing.
1092 finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peers);
1093 /*iterate over finger map till you reach a peer id such that destination <= peer id */
1094 for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (friend_peers); finger_index++)
1096 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(finger_iter,&key_ret,(const void **)&finger))
1099 * 1. Check if finger >= destination.
1100 * 2. If yes then check if finger <= current_predecessor,
1101 * if yes then curret_predecessor = finger.
1102 * 3 If not then do nothing.
1108 /* Check between friend and finger value to decide which is the predecessor.
1109 If friend, then send the friend id.
1110 If finger, then send the next hop. */
1117 * 1. Check if we are maintaining the 64k size of struct PeerTrailSetupMessage.
1118 * when we add ourself to the trail list.
1119 * 2. Ensure every case is handled for current_destination.
1120 * Core handler for P2P trail setup message.
1121 * @param cls closure
1122 * @param message message
1123 * @param peer peer identity this notification is about
1124 * @return #GNUNET_YES
1127 handle_dht_p2p_trail_setup(void *cls, const struct GNUNET_PeerIdentity *peer,
1128 const struct GNUNET_MessageHeader *message)
1130 const struct PeerTrailSetupMessage *trail_setup;
1131 struct GNUNET_PeerIdentity *next_hop;
1132 struct FriendInfo *friend;
1133 struct TrailPeerList *peer_entry;
1134 struct P2PPendingMessage *pending;
1138 msize = ntohs (message->size);
1139 if (msize < sizeof (struct PeerTrailSetupMessage))
1141 GNUNET_break_op (0);
1145 trail_setup = (const struct PeerTrailSetupMessage *) message;
1147 GNUNET_STATISTICS_update (GDS_stats,
1148 gettext_noop ("# TRAIL SETUP requests received"), 1,
1150 GNUNET_STATISTICS_update (GDS_stats,
1151 gettext_noop ("# TRAIL SETUP bytes received"), msize,
1155 /* Check the value of current_destination and handle the respective case. */
1156 if(trail_setup->current_destination == NULL)
1158 /* Find the next peer to pass the trail setup message. */
1159 next_hop = find_successor(trail_setup->destination_finger);
1161 else if( 0 == (GNUNET_CRYPTO_cmp_peer_identity(trail_setup->current_destination,&my_identity)))
1163 /* I am current destination, find the next peer to pass the trail setup message. */
1164 next_hop = find_successor(trail_setup->destination_finger);
1168 /* I am part of the trail to reach to current_destination. */
1169 next_hop = GDS_Routing_search(trail_setup->source_peer, trail_setup->current_destination, trail_setup->tail->peer);
1173 if(0 == (GNUNET_CRYPTO_cmp_peer_identity(next_hop,&my_identity)))
1175 /* I am the closest successor of the destination finger in the network. */
1177 1. Prepare a trail setup result message.
1178 2. Add yourself to trail list.
1179 3. send packet to last element in the list.
1184 /* Insert next hop into trial list. */
1185 peer_entry = GNUNET_malloc (sizeof (struct TrailPeerList));
1186 peer_entry->peer = &my_identity;
1187 peer_entry->next = NULL;
1188 peer_entry->prev = NULL;
1190 /*SUPU what is this stupid code that I have written. */
1191 GNUNET_CONTAINER_DLL_insert_tail(trail_setup->head->next,trail_setup->tail->prev,peer_entry);
1193 /* Find the struct FriendInfo for next_hop peer id. */
1194 friend = GNUNET_CONTAINER_multipeermap_get(friend_peers,next_hop);
1196 /* Send trail setup message to next hop friend. */
1197 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage));
1198 GNUNET_CONTAINER_DLL_insert_tail (friend->head, friend->tail, pending);
1199 friend->pending_count++;
1200 process_friend_queue(friend);
1206 * Core handle for p2p trail construction result messages.
1207 * @param cls closure
1208 * @param message message
1209 * @param peer peer identity this notification is about
1210 * @return #GNUNET_YES (do not cut p2p connection)
1214 handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer,
1215 const struct GNUNET_MessageHeader *message)
1218 * Just read the linked list backwards and send the packet to next hop
1219 * till you don't reach the source
1220 * but if you are source, then add an entry in finger table for given finger id.
1224 //const struct PeerTrailSetupResultMessage *trail_result;
1225 //trail_result = (const struct PeerTrailSetupResultMessage *) message;
1227 /*FIXME: This code is wrong, I am writing just to understand the flow,
1228 if(trail_result->destination == message->destination)
1230 This condition holds true, then we should add an entry in our
1231 routing table and store this finger and its trail.
1232 struct finger_info = with interval .
1233 GNUNET_multipeer_map_insert(finger_map)
1234 * GDS_Routing_add();
1238 Read the trail list, Check the next_hop and pass the packet to it.
1239 FIXME: Should we an entry in our own routing table.
1247 * Initialize neighbours subsystem.
1248 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1251 GDS_NEIGHBOURS_init()
1253 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1254 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0},
1255 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0},
1256 {&handle_dht_p2p_result, GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT, 0},
1257 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP, 0},
1258 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT, 0},
1262 atsAPI = GNUNET_ATS_performance_init (GDS_cfg, NULL, NULL);
1264 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
1265 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
1266 GNUNET_NO, core_handlers);
1267 if (core_api == NULL)
1268 return GNUNET_SYSERR;
1270 friend_peers = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1271 finger_peers = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1280 * Shutdown neighbours subsystem.
1283 GDS_NEIGHBOURS_done ()
1285 if (NULL == core_api)
1287 GNUNET_CORE_disconnect (core_api);
1289 GNUNET_ATS_performance_done (atsAPI);
1292 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peers));
1293 GNUNET_CONTAINER_multipeermap_destroy (friend_peers);
1294 friend_peers = NULL;
1296 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (finger_peers));
1297 GNUNET_CONTAINER_multipeermap_destroy (finger_peers);
1298 finger_peers = NULL;
1300 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
1302 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
1303 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
1309 * Get the ID of the local node.
1311 * @return identity of the local node
1313 struct GNUNET_PeerIdentity *
1314 GDS_NEIGHBOURS_get_id ()
1316 return &my_identity;
1320 /* end of gnunet-service-xdht_neighbours.c */