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.
21 * @file dht/gnunet-service-wdht_neighbours.c
22 * @brief GNUnet DHT service's finger and friend table management code
23 * @author Supriti Singh
26 #include "gnunet_util_lib.h"
27 #include "gnunet_block_lib.h"
28 #include "gnunet_hello_lib.h"
29 #include "gnunet_constants.h"
30 #include "gnunet_protocols.h"
31 #include "gnunet_ats_service.h"
32 #include "gnunet_core_service.h"
33 #include "gnunet_datacache_lib.h"
34 #include "gnunet_transport_service.h"
35 #include "gnunet_dht_service.h"
36 #include "gnunet_statistics_service.h"
37 #include "gnunet-service-wdht.h"
38 #include "gnunet-service-wdht_clients.h"
39 #include "gnunet-service-wdht_datacache.h"
40 #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 * The number of layered ID to use.
57 #define NUMBER_LAYERED_ID 8
60 * The number of random walk to launch at the beginning of the initialization
62 /* FIXME: find a better value */
63 #define NUMBER_RANDOM_WALK 20
66 /******************* The db structure and related functions *******************/
69 * Entry in friend_peermap.
75 * Information we keep per trail.
81 * MDLL entry in the list of all trails with the same predecessor.
83 struct Trail *prev_succ;
86 * MDLL entry in the list of all trails with the same predecessor.
88 struct Trail *next_succ;
91 * MDLL entry in the list of all trails with the same predecessor.
93 struct Trail *prev_pred;
96 * MDLL entry in the list of all trails with the same predecessor.
98 struct Trail *next_pred;
101 * Our predecessor in the trail, NULL if we are initiator (?).
103 struct FriendInfo *pred;
106 * Our successor in the trail, NULL if we are the last peer.
108 struct FriendInfo *succ;
111 * Identifier of the trail with the predecessor.
113 struct GNUNET_HashCode pred_id;
116 * Identifier of the trail with the successor.
118 struct GNUNET_HashCode succ_id;
121 * When does this trail expire.
123 struct GNUNET_TIME_Absolute expiration_time;
126 * Location of this trail in the heap.
128 struct GNUNET_CONTAINER_HeapNode *hn;
134 * Entry in friend_peermap.
141 struct GNUNET_PeerIdentity id;
143 struct Trail *pred_head;
145 struct Trail *pred_tail;
147 struct Trail *succ_head;
149 struct Trail *succ_tail;
152 * Core handle for sending messages to this friend.
154 struct GNUNET_MQ_Handle *mq;
162 * The identity of the peer.
164 struct GNUNET_PeerIdentity peer_id;
167 * The trail to use to reach the peer.
172 * #GNUNET_YES if a response has been received. Otherwise #GNUNET_NO.
178 /*********************** end of the db structure part ***********************/
181 GNUNET_NETWORK_STRUCT_BEGIN
184 * Setup a finger using the underlay topology ("social network").
186 struct FingerSetupMessage
189 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP
191 struct GNUNET_MessageHeader header;
194 * Number of hops this message has taken so far, we stop at
197 uint16_t hops_taken GNUNET_PACKED;
200 * Layer for the request, in NBO.
202 uint16_t layer GNUNET_PACKED;
205 * Unique (random) identifier this peer will use to
206 * identify the finger (in future messages).
208 struct GNUNET_HashCode finger_id;
214 * Response to a `struct FingerSetupMessage`.
216 struct FingerSetupResponseMessage
219 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP_RESPONSE
221 struct GNUNET_MessageHeader header;
224 * Zero, for alignment.
226 uint32_t reserved GNUNET_PACKED;
229 * Unique (random) identifier this peer will use to
230 * identify the finger (in future messages).
232 struct GNUNET_HashCode finger_id;
235 * Random location in the respective layer where the
236 * random path of the finger setup terminated.
238 struct GNUNET_HashCode location;
244 * Response to an event that causes a finger to die.
246 struct FingerDestroyMessage
249 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_DESTROY
251 struct GNUNET_MessageHeader header;
254 * Zero, for alignment.
256 uint32_t reserved GNUNET_PACKED;
259 * Unique (random) identifier this peer will use to
260 * identify the finger (in future messages).
262 struct GNUNET_HashCode finger_id;
268 * Send a message along a finger.
270 struct FingerRouteMessage
273 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_ROUTE
275 struct GNUNET_MessageHeader header;
278 * Zero, for alignment.
280 uint32_t reserved GNUNET_PACKED;
283 * Unique (random) identifier this peer will use to
284 * identify the finger (in future messages).
286 struct GNUNET_HashCode finger_id;
288 /* followed by payload to send along the finger */
295 struct PeerPutMessage
298 * Type: #GNUNET_MESSAGE_TYPE_WDHT_PUT
300 struct GNUNET_MessageHeader header;
305 uint32_t options GNUNET_PACKED;
310 uint32_t block_type GNUNET_PACKED;
315 uint32_t hop_count GNUNET_PACKED;
318 * Replication level for this message
319 * In the current implementation, this value is not used.
321 uint32_t desired_replication_level GNUNET_PACKED;
324 * Length of the PUT path that follows (if tracked).
326 uint32_t put_path_length GNUNET_PACKED;
329 * When does the content expire?
331 struct GNUNET_TIME_AbsoluteNBO expiration_time;
334 * The key to store the value under.
336 struct GNUNET_HashCode key GNUNET_PACKED;
338 /* put path (if tracked) */
347 struct PeerGetMessage
350 * Type: #GNUNET_MESSAGE_TYPE_WDHT_GET
352 struct GNUNET_MessageHeader header;
357 uint32_t options GNUNET_PACKED;
360 * Desired content type.
362 uint32_t block_type GNUNET_PACKED;
367 uint32_t hop_count GNUNET_PACKED;
370 * Desired replication level for this request.
371 * In the current implementation, this value is not used.
373 uint32_t desired_replication_level GNUNET_PACKED;
376 * Total number of peers in get path.
378 unsigned int get_path_length;
381 * The key we are looking for.
383 struct GNUNET_HashCode key;
386 /* struct GNUNET_PeerIdentity[]*/
393 struct PeerGetResultMessage
396 * Type: #GNUNET_MESSAGE_TYPE_WDHT_GET_RESULT
398 struct GNUNET_MessageHeader header;
401 * The type for the data.
403 uint32_t type GNUNET_PACKED;
406 * Number of peers recorded in the outgoing path from source to the
407 * stored location of this message.
409 uint32_t put_path_length GNUNET_PACKED;
412 * Length of the GET path that follows (if tracked).
414 uint32_t get_path_length GNUNET_PACKED;
417 * Peer which queried for get and should get the result.
419 struct GNUNET_PeerIdentity querying_peer;
422 * When does the content expire?
424 struct GNUNET_TIME_Absolute expiration_time;
427 * The key of the corresponding GET request.
429 struct GNUNET_HashCode key;
431 /* put path (if tracked) */
433 /* get path (if tracked) */
439 GNUNET_NETWORK_STRUCT_END
442 * The number of cells stored in the db structure.
444 static unsigned int number_cell;
447 * If sorted_db array is sorted #GNUNET_YES. Otherwise #GNUNET_NO.
449 static int is_sorted;
452 * Contains all the layered IDs of this peer.
454 struct GNUNET_PeerIdentity layered_id[NUMBER_LAYERED_ID];
457 * Unsorted database, here we manage the entries.
459 static struct db_cell *unsorted_db[NUMBER_RANDOM_WALK * NUMBER_LAYERED_ID];
462 * Sorted database by peer identity, needs to be re-sorted if
463 * #is_sorted is #GNUNET_NO.
465 static struct db_cell **sorted_db[NUMBER_RANDOM_WALK * NUMBER_LAYERED_ID];
468 * Task to timeout trails that have expired.
470 static struct GNUNET_SCHEDULER_Task *trail_timeout_task;
473 * Task to perform random walks.
475 static struct GNUNET_SCHEDULER_Task *random_walk_task;
478 * Identity of this peer.
480 static struct GNUNET_PeerIdentity my_identity;
483 * Peer map of all the fingers of a peer
485 static struct GNUNET_CONTAINER_MultiPeerMap *fingers_peermap;
488 * Peer map of all the successors of a peer
490 static struct GNUNET_CONTAINER_MultiPeerMap *successors_peermap;
493 * Tail map, mapping tail identifiers to `struct Trail`s
495 static struct GNUNET_CONTAINER_MultiHashMap *trail_map;
498 * Tail heap, organizing trails by expiration time.
500 static struct GNUNET_CONTAINER_Heap *trail_heap;
505 static struct GNUNET_CORE_Handle *core_api;
509 * Initialize the db structure with default values.
516 for (i = 0; i < NUMBER_RANDOM_WALK; i++)
518 unsorted_db[i] = NULL;
519 sorted_db[i] = &unsorted_db[i];
525 * Destroy the db_structure. Basically, free every db_cell.
528 destroy_db_structure ()
532 for (i = 0; i < NUMBER_RANDOM_WALK; i++)
534 // what about 'unsorted_db[i]->trail?
535 GNUNET_free_non_null (unsorted_db[i]);
541 * Add a new db_cell in the db structure.
544 add_new_cell (struct db_cell *bd_cell)
546 unsorted_db[number_cell] = bd_cell;
547 is_sorted = GNUNET_NO;
552 * Handle the put request from the client.
554 * @param key Key for the content
555 * @param block_type Type of the block
556 * @param options Routing options
557 * @param desired_replication_level Desired replication count
558 * @param expiration_time When does the content expire
559 * @param data Content to store
560 * @param data_size Size of content @a data in bytes
563 GDS_NEIGHBOURS_handle_put (const struct GNUNET_HashCode *key,
564 enum GNUNET_BLOCK_Type block_type,
565 enum GNUNET_DHT_RouteOption options,
566 uint32_t desired_replication_level,
567 struct GNUNET_TIME_Absolute expiration_time,
568 const void *data, size_t data_size)
574 * Handle the get request from the client file. If I am destination do
575 * datacache put and return. Else find the target friend and forward message
578 * @param key Key for the content
579 * @param block_type Type of the block
580 * @param options Routing options
581 * @param desired_replication_level Desired replication count
584 GDS_NEIGHBOURS_handle_get (const struct GNUNET_HashCode *key,
585 enum GNUNET_BLOCK_Type block_type,
586 enum GNUNET_DHT_RouteOption options,
587 uint32_t desired_replication_level)
594 * Send the get result to requesting client.
596 * @param key Key of the requested data.
597 * @param type Block type
598 * @param target_peer Next peer to forward the message to.
599 * @param source_peer Peer which has the data for the key.
600 * @param put_path_length Number of peers in @a put_path
601 * @param put_path Path taken to put the data at its stored location.
602 * @param get_path_length Number of peers in @a get_path
603 * @param get_path Path taken to reach to the location of the key.
604 * @param expiration When will this result expire?
605 * @param data Payload to store
606 * @param data_size Size of the @a data
609 GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key,
610 enum GNUNET_BLOCK_Type type,
611 const struct GNUNET_PeerIdentity *target_peer,
612 const struct GNUNET_PeerIdentity *source_peer,
613 unsigned int put_path_length,
614 const struct GNUNET_PeerIdentity *put_path,
615 unsigned int get_path_length,
616 const struct GNUNET_PeerIdentity *get_path,
617 struct GNUNET_TIME_Absolute expiration,
618 const void *data, size_t data_size)
624 * Method called whenever a peer disconnects.
627 * @param peer peer identity this notification is about
630 handle_core_disconnect (void *cls,
631 const struct GNUNET_PeerIdentity *peer)
633 struct FriendInfo *remove_friend;
635 /* If disconnected to own identity, then return. */
636 if (0 == memcmp (&my_identity,
638 sizeof (struct GNUNET_PeerIdentity)))
641 if (NULL == (remove_friend =
642 GNUNET_CONTAINER_multipeermap_get (fingers_peermap,
649 GNUNET_assert (GNUNET_YES ==
650 GNUNET_CONTAINER_multipeermap_remove (fingers_peermap,
653 /* FIXME: do stuff */
654 GNUNET_MQ_destroy (remove_friend->mq);
655 GNUNET_free (remove_friend);
657 GNUNET_CONTAINER_multipeermap_size (fingers_peermap))
659 GNUNET_SCHEDULER_cancel (random_walk_task);
660 random_walk_task = NULL;
666 * Initiate a random walk.
672 do_random_walk (void *cls,
673 const struct GNUNET_SCHEDULER_TaskContext *tc)
675 struct FriendInfo *friend;
676 struct GNUNET_MQ_Envelope *env;
677 struct FingerSetupMessage *fsm;
678 struct db_cell *friend_cell;
681 friend = NULL; // FIXME: pick at random...
683 friend_cell = GNUNET_new (struct db_cell);
684 friend_cell->peer_id = friend->id;
686 trail = GNUNET_new (struct Trail);
688 /* We create the random walk so, no predecessor */
689 trail->succ = friend;
691 GNUNET_CONTAINER_MDLL_insert (succ,
695 env = GNUNET_MQ_msg (fsm,
696 GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP);
697 fsm->hops_taken = htons (0);
698 fsm->layer = htons (0); // FIXME: not always 0...
699 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE,
701 GNUNET_MQ_send (friend->mq,
707 * Method called whenever a peer connects.
710 * @param peer_identity peer identity this notification is about
713 handle_core_connect (void *cls,
714 const struct GNUNET_PeerIdentity *peer_identity)
716 struct FriendInfo *friend;
718 /* Check for connect to self message */
719 if (0 == memcmp (&my_identity,
721 sizeof (struct GNUNET_PeerIdentity)))
724 /* If peer already exists in our friend_peermap, then exit. */
726 GNUNET_CONTAINER_multipeermap_contains (fingers_peermap,
733 friend = GNUNET_new (struct FriendInfo);
734 friend->id = *peer_identity;
735 friend->mq = GNUNET_CORE_mq_create (core_api,
737 GNUNET_assert (GNUNET_OK ==
738 GNUNET_CONTAINER_multipeermap_put (fingers_peermap,
741 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
744 if (NULL == random_walk_task)
746 random_walk_task = GNUNET_SCHEDULER_add_now (&do_random_walk,
753 * To be called on core init/fail.
755 * @param cls service closure
756 * @param identity the public identity of this peer
759 core_init (void *cls,
760 const struct GNUNET_PeerIdentity *identity)
762 my_identity = *identity;
767 * Handle a `struct FingerSetupMessage` from a GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP
770 * @param cls closure (NULL)
771 * @param peer sender identity
772 * @param message the setup message
773 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
776 handle_dht_p2p_finger_setup (void *cls,
777 const struct GNUNET_PeerIdentity *peer,
778 const struct GNUNET_MessageHeader *message)
780 const struct FingerSetupMessage *fsm;
782 fsm = (const struct FingerSetupMessage *) message;
786 * 1 check if the hops_taken is < to log(honest node)
787 * 1.a.1 if true : increments the hops_taken
788 * 1.a.2 send the same structure
789 * 1.b if false : drop the message
796 * Handle a `struct FingerSetupResponseMessage` from a GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP_RESPONSE
799 * @param cls closure (NULL)
800 * @param peer sender identity
801 * @param message the setup response message
802 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
805 handle_dht_p2p_finger_setup_response (void *cls,
806 const struct GNUNET_PeerIdentity *peer,
807 const struct GNUNET_MessageHeader *message)
809 const struct FingerSetupResponseMessage *fsrm;
811 fsrm = (const struct FingerSetupResponseMessage *) message;
815 * 1 check if we are the correct layer
816 * 1.a if true : add the returned value (finger) in the db structure
817 * 1.b if true : do nothing
819 /* FIXME: add the value in db structure 1.a */
826 * Handle a `struct FingerDestroyMessage`.
828 * @param cls closure (NULL)
829 * @param peer sender identity
830 * @param message the finger destroy message
831 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
834 handle_dht_p2p_finger_destroy (void *cls,
835 const struct GNUNET_PeerIdentity *peer,
836 const struct GNUNET_MessageHeader *message)
838 const struct FingerDestroyMessage *fdm;
840 fdm = (const struct FingerDestroyMessage *) message;
844 * 1 check if message comme from a trail
845 * 1.a.1 if true: send the destroy message to the rest trail
846 * 1.a.2 clean the trail structure
847 * 1.a.3 did i have to remove the trail and ID from the db structure?
848 * 1.b if false: do nothing
855 * Handle a `struct FingerRouteMessage`.
857 * @param cls closure (NULL)
858 * @param peer sender identity
859 * @param message the finger route message
860 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
863 handle_dht_p2p_finger_route (void *cls,
864 const struct GNUNET_PeerIdentity *peer,
865 const struct GNUNET_MessageHeader *message)
867 const struct FingerRouteMessage *frm;
869 frm = (const struct FingerRouteMessage *) message;
870 /* FIXME: check the size of the message */
874 * 1 find the good trail
875 * 2 check the message inside
876 * 2.a if the message is a finger setup message : increments ce hops_takeb
877 * 3 send the finger route message
884 * Handle a `struct FingerSetupMessage` from a GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FIND
887 * @param cls closure (NULL)
888 * @param peer sender identity
889 * @param message the finger setup message
890 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
893 handle_dht_p2p_neighbour_find (void *cls,
894 const struct GNUNET_PeerIdentity *peer,
895 const struct GNUNET_MessageHeader *message)
897 const struct FingerSetupMessage *fsm;
899 fsm = (const struct FingerSetupMessage *) message;
905 * Handle a `struct FingerSetupResponseMessage` from a GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FIND
908 * @param cls closure (NULL)
909 * @param peer sender identity
910 * @param message the finger setup response message
911 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
914 handle_dht_p2p_neighbour_found (void *cls,
915 const struct GNUNET_PeerIdentity *peer,
916 const struct GNUNET_MessageHeader *message)
918 const struct FingerSetupResponseMessage *fsrm;
920 fsrm = (const struct FingerSetupResponseMessage *) message;
926 * Handle a `struct PeerGetMessage`.
928 * @param cls closure (NULL)
929 * @param peer sender identity
930 * @param message the peer get message
931 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
934 handle_dht_p2p_peer_get (void *cls,
935 const struct GNUNET_PeerIdentity *peer,
936 const struct GNUNET_MessageHeader *message)
938 const struct PeerGetMessage *pgm;
940 pgm = (const struct PeerGetMessage *) message;
944 * 1 extract the result
946 * 3 send it using the good trail
948 * What do i do when i don't have the key/value?
955 * Handle a `struct PeerGetResultMessage`.
957 * @param cls closure (NULL)
958 * @param peer sender identity
959 * @param message the peer get result message
960 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
963 handle_dht_p2p_peer_get_result (void *cls,
964 const struct GNUNET_PeerIdentity *peer,
965 const struct GNUNET_MessageHeader *message)
967 const struct PeerGetResultMessage *pgrm;
969 pgrm = (const struct PeerGetResultMessage *) message;
973 * 1 extract the result
974 * 2 create a peerGetResult struct
975 * 3 send it using the good trail
977 * What do i do when i don't have the key/value?
985 * Handle a `struct PeerPutMessage`.
987 * @param cls closure (NULL)
988 * @param peer sender identity
989 * @param message the peer put message
990 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
993 handle_dht_p2p_peer_put (void *cls,
994 const struct GNUNET_PeerIdentity *peer,
995 const struct GNUNET_MessageHeader *message)
997 const struct PeerGetResultMessage *pgrm;
999 pgrm = (const struct PeerGetResultMessage *) message;
1003 * 1 check the size of the message
1004 * 2 use the API to add the value in the "database". Check on the xdht file, how to do it.
1005 * 3 Did i a have to return a notification or did i have to return GNUNET_[OK|SYSERR]?
1012 * Initialize neighbours subsystem.
1013 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1016 GDS_NEIGHBOURS_init (void)
1018 static const struct GNUNET_CORE_MessageHandler core_handlers[] = {
1019 { &handle_dht_p2p_finger_setup,
1020 GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP,
1021 sizeof (struct FingerSetupMessage) },
1022 { &handle_dht_p2p_finger_setup_response,
1023 GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP_RESPONSE,
1024 sizeof (struct FingerSetupResponseMessage) },
1025 { &handle_dht_p2p_finger_destroy,
1026 GNUNET_MESSAGE_TYPE_WDHT_FINGER_DESTROY,
1027 sizeof (struct FingerDestroyMessage) },
1028 { &handle_dht_p2p_finger_route,
1029 GNUNET_MESSAGE_TYPE_WDHT_FINGER_ROUTE,
1031 { &handle_dht_p2p_neighbour_find,
1032 GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FIND,
1033 sizeof (struct FingerSetupMessage) },
1034 { &handle_dht_p2p_neighbour_found,
1035 GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FOUND,
1036 sizeof (struct FingerSetupResponseMessage) },
1037 { &handle_dht_p2p_peer_get,
1038 GNUNET_MESSAGE_TYPE_WDHT_GET,
1039 sizeof (struct PeerGetMessage) },
1040 { &handle_dht_p2p_peer_get_result,
1041 GNUNET_MESSAGE_TYPE_WDHT_GET_RESULT,
1043 { &handle_dht_p2p_peer_put,
1044 GNUNET_MESSAGE_TYPE_WDHT_PUT,
1050 GNUNET_CORE_connect (GDS_cfg, NULL,
1052 &handle_core_connect,
1053 &handle_core_disconnect,
1058 if (NULL == core_api)
1059 return GNUNET_SYSERR;
1061 fingers_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1062 successors_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1064 init_db_structure();
1074 * Shutdown neighbours subsystem.
1077 GDS_NEIGHBOURS_done (void)
1079 if (NULL == core_api)
1081 GNUNET_CORE_disconnect (core_api);
1084 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (fingers_peermap));
1085 GNUNET_CONTAINER_multipeermap_destroy (fingers_peermap);
1086 GNUNET_CONTAINER_multipeermap_destroy (successors_peermap);
1087 destroy_db_structure();
1089 fingers_peermap = NULL;
1096 * @return my identity
1098 struct GNUNET_PeerIdentity
1099 GDS_NEIGHBOURS_get_my_id (void)
1104 /* end of gnunet-service-wdht_neighbours.c */