2 This file is part of GNUnet.
3 Copyright (C) 2009-2015 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-wdht_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_ats_service.h"
34 #include "gnunet_core_service.h"
35 #include "gnunet_datacache_lib.h"
36 #include "gnunet_transport_service.h"
37 #include "gnunet_dht_service.h"
38 #include "gnunet_statistics_service.h"
39 #include "gnunet-service-xdht.h"
40 #include "gnunet-service-wdht_clients.h"
41 #include "gnunet-service-wdht_datacache.h"
42 #include "gnunet-service-wdht_neighbours.h"
47 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
52 #define FOO_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
55 GNUNET_NETWORK_STRUCT_BEGIN
58 * Setup a finger using the underlay topology ("social network").
60 struct FingerSetupMessage
63 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP
65 struct GNUNET_MessageHeader header;
68 * Number of hops this message has taken so far, we stop at
71 uint16_t hops_taken GNUNET_PACKED;
74 * Layer for the request, in NBO.
76 uint16_t layer GNUNET_PACKED;
79 * Unique (random) identifier this peer will use to
80 * identify the finger (in future messages).
82 struct GNUNET_HashCode finger_id;
88 * Response to a `struct FingerSetupMessage`.
90 struct FingerSetupResponseMessage
93 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP_RESPONSE
95 struct GNUNET_MessageHeader header;
98 * Zero, for alignment.
100 uint32_t reserved GNUNET_PACKED;
103 * Unique (random) identifier this peer will use to
104 * identify the finger (in future messages).
106 struct GNUNET_HashCode finger_id;
109 * Random location in the respective layer where the
110 * random path of the finger setup terminated.
112 struct GNUNET_HashCode location;
118 * Response to an event that causes a finger to die.
120 struct FingerDestroyMessage
123 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_DESTROY
125 struct GNUNET_MessageHeader header;
128 * Zero, for alignment.
130 uint32_t reserved GNUNET_PACKED;
133 * Unique (random) identifier this peer will use to
134 * identify the finger (in future messages).
136 struct GNUNET_HashCode finger_id;
142 * Send a message along a finger.
144 struct FingerRouteMessage
147 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_ROUTE
149 struct GNUNET_MessageHeader header;
152 * Zero, for alignment.
154 uint32_t reserved GNUNET_PACKED;
157 * Unique (random) identifier this peer will use to
158 * identify the finger (in future messages).
160 struct GNUNET_HashCode finger_id;
162 /* followed by payload to send along the finger */
169 struct PeerPutMessage
172 * Type: #GNUNET_MESSAGE_TYPE_WDHT_P2P_PUT
174 struct GNUNET_MessageHeader header;
179 uint32_t options GNUNET_PACKED;
184 uint32_t block_type GNUNET_PACKED;
189 uint32_t hop_count GNUNET_PACKED;
192 * Replication level for this message
193 * In the current implementation, this value is not used.
195 uint32_t desired_replication_level GNUNET_PACKED;
198 * Length of the PUT path that follows (if tracked).
200 uint32_t put_path_length GNUNET_PACKED;
203 * When does the content expire?
205 struct GNUNET_TIME_AbsoluteNBO expiration_time;
208 * The key to store the value under.
210 struct GNUNET_HashCode key GNUNET_PACKED;
212 /* put path (if tracked) */
221 struct PeerGetMessage
224 * Type: #GNUNET_MESSAGE_TYPE_WDHT_P2P_GET
226 struct GNUNET_MessageHeader header;
231 uint32_t options GNUNET_PACKED;
234 * Desired content type.
236 uint32_t block_type GNUNET_PACKED;
241 uint32_t hop_count GNUNET_PACKED;
244 * Desired replication level for this request.
245 * In the current implementation, this value is not used.
247 uint32_t desired_replication_level GNUNET_PACKED;
250 * Total number of peers in get path.
252 unsigned int get_path_length;
255 * The key we are looking for.
257 struct GNUNET_HashCode key;
260 /* struct GNUNET_PeerIdentity[]*/
267 struct PeerGetResultMessage
270 * Type: #GNUNET_MESSAGE_TYPE_WDHT_P2P_GET_RESULT
272 struct GNUNET_MessageHeader header;
275 * The type for the data.
277 uint32_t type GNUNET_PACKED;
280 * Number of peers recorded in the outgoing path from source to the
281 * stored location of this message.
283 uint32_t put_path_length GNUNET_PACKED;
286 * Length of the GET path that follows (if tracked).
288 uint32_t get_path_length GNUNET_PACKED;
291 * Peer which queried for get and should get the result.
293 struct GNUNET_PeerIdentity querying_peer;
296 * When does the content expire?
298 struct GNUNET_TIME_Absolute expiration_time;
301 * The key of the corresponding GET request.
303 struct GNUNET_HashCode key;
305 /* put path (if tracked) */
307 /* get path (if tracked) */
313 GNUNET_NETWORK_STRUCT_END
316 * Entry in friend_peermap.
322 * Information we keep per trail.
328 * MDLL entry in the list of all trails with the same predecessor.
330 struct Tail *prev_succ;
333 * MDLL entry in the list of all trails with the same predecessor.
335 struct Tail *next_succ;
338 * MDLL entry in the list of all trails with the same predecessor.
340 struct Tail *prev_pred;
343 * MDLL entry in the list of all trails with the same predecessor.
345 struct Tail *next_pred;
348 * Our predecessor in the trail, NULL if we are initiator (?).
350 struct FriendInfo *pred;
353 * Our successor in the trail, NULL if we are the last peer.
355 struct FriendInfo *succ;
358 * Identifier of the trail with the predecessor.
360 struct GNUNET_HashCode pred_id;
363 * Identifier of the trail with the successor.
365 struct GNUNET_HashCode succ_id;
368 * When does this trail expire.
370 struct GNUNET_TIME_Absolute expiration_time;
373 * Location of this trail in the heap.
375 struct GNUNET_CONTAINER_HeapNode *hn;
381 * Entry in friend_peermap.
388 struct GNUNET_PeerIdentity id;
390 struct Tail *pred_head;
392 struct Tail *pred_tail;
394 struct Tail *succ_head;
396 struct Tail *succ_tail;
399 * Core handle for sending messages to this friend.
402 struct GNUNET_CORE_TransmitHandle *th;
409 * Task to timeout trails that have expired.
411 static struct GNUNET_SCHEDULER_Task *trail_timeout_task;
414 * Identity of this peer.
416 static struct GNUNET_PeerIdentity my_identity;
419 * Peer map of all the fingers of a peer
421 static struct GNUNET_CONTAINER_MultiPeerMap *fingers_peermap;
424 * Peer map of all the successors of a peer
426 static struct GNUNET_CONTAINER_MultiPeerMap *successors_peermap;
429 * Tail map, mapping tail identifiers to `struct Trail`s
431 static struct GNUNET_CONTAINER_MultiHashMap *tail_map;
434 * Tail heap, organizing trails by expiration time.
436 static struct GNUNET_CONTAINER_Heap *tail_heap;
441 static struct GNUNET_CORE_Handle *core_api;
445 * Handle the put request from the client.
447 * @param key Key for the content
448 * @param block_type Type of the block
449 * @param options Routing options
450 * @param desired_replication_level Desired replication count
451 * @param expiration_time When does the content expire
452 * @param data Content to store
453 * @param data_size Size of content @a data in bytes
456 GDS_NEIGHBOURS_handle_put (const struct GNUNET_HashCode *key,
457 enum GNUNET_BLOCK_Type block_type,
458 enum GNUNET_DHT_RouteOption options,
459 uint32_t desired_replication_level,
460 struct GNUNET_TIME_Absolute expiration_time,
461 const void *data, size_t data_size)
467 * Handle the get request from the client file. If I am destination do
468 * datacache put and return. Else find the target friend and forward message
471 * @param key Key for the content
472 * @param block_type Type of the block
473 * @param options Routing options
474 * @param desired_replication_level Desired replication count
477 GDS_NEIGHBOURS_handle_get (const struct GNUNET_HashCode *key,
478 enum GNUNET_BLOCK_Type block_type,
479 enum GNUNET_DHT_RouteOption options,
480 uint32_t desired_replication_level)
487 * Send the get result to requesting client.
489 * @param key Key of the requested data.
490 * @param type Block type
491 * @param target_peer Next peer to forward the message to.
492 * @param source_peer Peer which has the data for the key.
493 * @param put_path_length Number of peers in @a put_path
494 * @param put_path Path taken to put the data at its stored location.
495 * @param get_path_length Number of peers in @a get_path
496 * @param get_path Path taken to reach to the location of the key.
497 * @param expiration When will this result expire?
498 * @param data Payload to store
499 * @param data_size Size of the @a data
502 GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key,
503 enum GNUNET_BLOCK_Type type,
504 const struct GNUNET_PeerIdentity *target_peer,
505 const struct GNUNET_PeerIdentity *source_peer,
506 unsigned int put_path_length,
507 const struct GNUNET_PeerIdentity *put_path,
508 unsigned int get_path_length,
509 const struct GNUNET_PeerIdentity *get_path,
510 struct GNUNET_TIME_Absolute expiration,
511 const void *data, size_t data_size)
517 * Method called whenever a peer disconnects.
520 * @param peer peer identity this notification is about
523 handle_core_disconnect (void *cls,
524 const struct GNUNET_PeerIdentity *peer)
526 struct FriendInfo *remove_friend;
528 /* If disconnected to own identity, then return. */
529 if (0 == memcmp (&my_identity,
531 sizeof (struct GNUNET_PeerIdentity)))
534 if (NULL == (remove_friend =
535 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
542 GNUNET_assert (GNUNET_YES ==
543 GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
546 /* FIXME: do stuff */
551 * Method called whenever a peer connects.
554 * @param peer_identity peer identity this notification is about
557 handle_core_connect (void *cls,
558 const struct GNUNET_PeerIdentity *peer_identity)
560 struct FriendInfo *friend;
562 /* Check for connect to self message */
563 if (0 == memcmp (&my_identity,
565 sizeof (struct GNUNET_PeerIdentity)))
568 /* If peer already exists in our friend_peermap, then exit. */
570 GNUNET_CONTAINER_multipeermap_contains (friend_peermap,
577 friend = GNUNET_new (struct FriendInfo);
578 friend->id = *peer_identity;
580 GNUNET_assert (GNUNET_OK ==
581 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
584 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
590 * To be called on core init/fail.
592 * @param cls service closure
593 * @param identity the public identity of this peer
596 core_init (void *cls,
597 const struct GNUNET_PeerIdentity *identity)
599 my_identity = *identity;
604 * Handle a `struct FingerSetupMessage` from a GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP
607 * @param cls closure (NULL)
608 * @param peer sender identity
609 * @param message the setup message
610 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
613 handle_dht_p2p_finger_setup (void *cls,
614 const struct GNUNET_PeerIdentity *peer,
615 const struct GNUNET_MessageHeader *message)
617 const struct FingerSetupMessage *fsm;
619 fsm = (const struct FingerSetupMessage *) message;
625 * Handle a `struct FingerSetupResponseMessage` from a GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP_RESPONSE
628 * @param cls closure (NULL)
629 * @param peer sender identity
630 * @param message the setup response message
631 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
634 handle_dht_p2p_finger_setup_response (void *cls,
635 const struct GNUNET_PeerIdentity *peer,
636 const struct GNUNET_MessageHeader *message)
638 const struct FingerSetupResponseMessage *fsrm;
640 fsm = (const struct FingerSetupResponseMessage *) message;
647 * Handle a `struct FingerDestroyMessage`.
649 * @param cls closure (NULL)
650 * @param peer sender identity
651 * @param message the finger destroy message
652 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
655 handle_dht_p2p_finger_destroy (void *cls,
656 const struct GNUNET_PeerIdentity *peer,
657 const struct GNUNET_MessageHeader *message)
659 const struct FingerDestroyMessage *fdm;
661 fdm = (const struct FingerDestroyMessage *) message;
667 * Handle a `struct FingerRouteMessage`.
669 * @param cls closure (NULL)
670 * @param peer sender identity
671 * @param message the finger route message
672 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
675 handle_dht_p2p_finger_route (void *cls,
676 const struct GNUNET_PeerIdentity *peer,
677 const struct GNUNET_MessageHeader *message)
679 const struct FingerRouteMessage *frm;
681 frm = (const struct FingerRouteMessage *) message;
682 /* FIXME: check the size of the message */
688 * Handle a `struct FingerSetupMessage` from a GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FIND
691 * @param cls closure (NULL)
692 * @param peer sender identity
693 * @param message the finger setup message
694 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
697 handle_dht_p2p_neighbour_find (void *cls,
698 const struct GNUNET_PeerIdentity *peer,
699 const struct GNUNET_MessageHeader *message)
701 const struct FingerSetupMessage *fsm;
703 fsm = (const struct FingerSetupMessage *) message;
709 * Handle a `struct FingerSetupResponseMessage` from a GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FIND
712 * @param cls closure (NULL)
713 * @param peer sender identity
714 * @param message the finger setup response message
715 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
718 handle_dht_p2p_neighbour_found (void *cls,
719 const struct GNUNET_PeerIdentity *peer,
720 const struct GNUNET_MessageHeader *message)
722 const struct FingerSetupResponseMessage *fsrm;
724 fsrm = (const struct FingerSetupResponseMessage *) message;
730 * Handle a `struct PeerGetMessage`.
732 * @param cls closure (NULL)
733 * @param peer sender identity
734 * @param message the peer get message
735 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
738 handle_dht_p2p_peer_get (void *cls,
739 const struct GNUNET_PeerIdentity *peer,
740 const struct GNUNET_MessageHeader *message)
742 const struct PeerGetMessage *pgm;
744 pgm = (const struct PeerGetMessage *) message;
748 * 1 extract the result
749 * 2 create a peerGetResult struct
750 * 3 send it using the good trail
752 * What do i do when i don't have the key/value?
759 * Handle a `struct PeerGetResultMessage`.
761 * @param cls closure (NULL)
762 * @param peer sender identity
763 * @param message the peer get result message
764 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
767 handle_dht_p2p_peer_get_result (void *cls,
768 const struct GNUNET_PeerIdentity *peer,
769 const struct GNUNET_MessageHeader *message)
771 const struct PeerGetResultMessage *pgrm;
773 pgrm = (const struct PeerGetResultMessage *) message;
779 * Handle a `struct PeerPutMessage`.
781 * @param cls closure (NULL)
782 * @param peer sender identity
783 * @param message the peer put message
784 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
787 handle_dht_p2p_peer_put (void *cls,
788 const struct GNUNET_PeerIdentity *peer,
789 const struct GNUNET_MessageHeader *message)
791 const struct PeerGetResultMessage *pgrm;
793 pgrm = (const struct PeerGetResultMessage *) message;
799 * Initialize neighbours subsystem.
800 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
803 GDS_NEIGHBOURS_init (void)
805 static const struct GNUNET_CORE_MessageHandler core_handlers[] = {
806 { &handle_dht_p2p_finger_setup,
807 GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP,
808 sizeof (struct FingerSetupMessage) },
809 { &handle_dht_p2p_finger_setup_response,
810 GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP_RESPONSE,
811 sizeof (struct FingerSetupResponseMessage) },
812 { &handle_dht_p2p_finger_destroy,
813 GNUNET_MESSAGE_TYPE_WDHT_FINGER_DESTROY,
814 sizeof (struct FingerDestroyMessage) },
815 { &handle_dht_p2p_finger_route,
816 GNUNET_MESSAGE_TYPE_WDHT_FINGER_ROUTE,
818 { &handle_dht_p2p_neighbour_find,
819 GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FIND,
820 sizeof (struct FingerSetupMessage) },
821 { &handle_dht_p2p_neighbour_found,
822 GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FOUND,
823 sizeof (struct FingerSetupResponseMessage) },
824 { &handle_dht_p2p_peer_get,
825 GNUNET_MESSAGE_TYPE_WDHT_GET,
826 sizeof (struct PeerGetMessage) },
827 { &handle_dht_p2p_peer_get_result,
828 GNUNET_MESSAGE_TYPE_WDHT_GET_RESULT,
830 { &handle_dht_p2p_peer_put,
831 GNUNET_MESSAGE_TYPE_WDHT_PUT,
837 GNUNET_CORE_connect (GDS_cfg, NULL,
839 &handle_core_connect,
840 &handle_core_disconnect,
845 if (NULL == core_api)
846 return GNUNET_SYSERR;
848 fingers_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
849 successors_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
856 * Shutdown neighbours subsystem.
859 GDS_NEIGHBOURS_done (void)
861 if (NULL == core_api)
863 GNUNET_CORE_disconnect (core_api);
866 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
867 GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
868 friend_peermap = NULL;
875 * @return my identity
877 struct GNUNET_PeerIdentity
878 GDS_NEIGHBOURS_get_my_id (void)
883 /* end of gnunet-service-wdht_neighbours.c */