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-wdht.h"
40 #include "gnunet-service-wdht_clients.h"
41 #include "gnunet-service-wdht_datacache.h"
42 #include "gnunet-service-wdht_neighbours.h"
49 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
54 #define FOO_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
57 * The number of layered ID to use.
59 #define NUMBER_LAYERED_ID 8
62 * The number of random walk to launch at the beginning of the initialization
64 /* FIXME: find a better value */
65 #define NUMBER_RANDOM_WALK 20
69 * Contains all the layered ID.
71 struct GNUNET_PeerIdentity layered_id[NUMBER_LAYERED_ID];
73 /******************* The db structure and related functions *******************/
75 * The number of cell store in the db structure.
80 * If sorted_db array are sorted 1. Otherwise 0.
82 /* FIXME: not sure about this one */
87 * The identity of the.
89 GNUNET_PeerIdentity *peer_id;
91 * The trail to use to reach the peer.
95 * 1 if a response are received. Otherwise 0.
100 struct db_cell *unsorted_db[NUMBER_RANDOM_WALK * NUMBER_LAYERED_ID];
102 struct db_cell *sorted_db[NUMBER_RANDOM_WALK * NUMBER_LAYERED_ID];
105 * Initialize the db structure with default values.
108 init_db_structure (){
110 for(i = 0; i < NUMBER_RANDOM_WALK; i++){
111 unsorted_db[i] = NULL;
112 sorted_db[i] = unsorted_db[i];
117 * Destroy the db_structure. Basically, free every db_cell.
120 destroy_db_structure (){
122 for(i = 0; i < NUMBER_RANDOM_WALK; i++){
123 GNUNET_free_non_null(unsorted_db[i]);
128 * Add a new db_cell in the db structure.
131 add_new_cell(const struct *bd_cell){
132 unsorted_db[number_cell] = bd_cell;
133 sorted_db[number_cell] = db_cell;
134 /* FIXME: add some code to sort by friend id */
138 /*********************** end of the db structure part ***********************/
141 GNUNET_NETWORK_STRUCT_BEGIN
144 * Setup a finger using the underlay topology ("social network").
146 struct FingerSetupMessage
149 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP
151 struct GNUNET_MessageHeader header;
154 * Number of hops this message has taken so far, we stop at
157 uint16_t hops_taken GNUNET_PACKED;
160 * Layer for the request, in NBO.
162 uint16_t layer GNUNET_PACKED;
165 * Unique (random) identifier this peer will use to
166 * identify the finger (in future messages).
168 struct GNUNET_HashCode finger_id;
174 * Response to a `struct FingerSetupMessage`.
176 struct FingerSetupResponseMessage
179 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP_RESPONSE
181 struct GNUNET_MessageHeader header;
184 * Zero, for alignment.
186 uint32_t reserved GNUNET_PACKED;
189 * Unique (random) identifier this peer will use to
190 * identify the finger (in future messages).
192 struct GNUNET_HashCode finger_id;
195 * Random location in the respective layer where the
196 * random path of the finger setup terminated.
198 struct GNUNET_HashCode location;
204 * Response to an event that causes a finger to die.
206 struct FingerDestroyMessage
209 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_DESTROY
211 struct GNUNET_MessageHeader header;
214 * Zero, for alignment.
216 uint32_t reserved GNUNET_PACKED;
219 * Unique (random) identifier this peer will use to
220 * identify the finger (in future messages).
222 struct GNUNET_HashCode finger_id;
228 * Send a message along a finger.
230 struct FingerRouteMessage
233 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_ROUTE
235 struct GNUNET_MessageHeader header;
238 * Zero, for alignment.
240 uint32_t reserved GNUNET_PACKED;
243 * Unique (random) identifier this peer will use to
244 * identify the finger (in future messages).
246 struct GNUNET_HashCode finger_id;
248 /* followed by payload to send along the finger */
255 struct PeerPutMessage
258 * Type: #GNUNET_MESSAGE_TYPE_WDHT_PUT
260 struct GNUNET_MessageHeader header;
265 uint32_t options GNUNET_PACKED;
270 uint32_t block_type GNUNET_PACKED;
275 uint32_t hop_count GNUNET_PACKED;
278 * Replication level for this message
279 * In the current implementation, this value is not used.
281 uint32_t desired_replication_level GNUNET_PACKED;
284 * Length of the PUT path that follows (if tracked).
286 uint32_t put_path_length GNUNET_PACKED;
289 * When does the content expire?
291 struct GNUNET_TIME_AbsoluteNBO expiration_time;
294 * The key to store the value under.
296 struct GNUNET_HashCode key GNUNET_PACKED;
298 /* put path (if tracked) */
307 struct PeerGetMessage
310 * Type: #GNUNET_MESSAGE_TYPE_WDHT_GET
312 struct GNUNET_MessageHeader header;
317 uint32_t options GNUNET_PACKED;
320 * Desired content type.
322 uint32_t block_type GNUNET_PACKED;
327 uint32_t hop_count GNUNET_PACKED;
330 * Desired replication level for this request.
331 * In the current implementation, this value is not used.
333 uint32_t desired_replication_level GNUNET_PACKED;
336 * Total number of peers in get path.
338 unsigned int get_path_length;
341 * The key we are looking for.
343 struct GNUNET_HashCode key;
346 /* struct GNUNET_PeerIdentity[]*/
353 struct PeerGetResultMessage
356 * Type: #GNUNET_MESSAGE_TYPE_WDHT_GET_RESULT
358 struct GNUNET_MessageHeader header;
361 * The type for the data.
363 uint32_t type GNUNET_PACKED;
366 * Number of peers recorded in the outgoing path from source to the
367 * stored location of this message.
369 uint32_t put_path_length GNUNET_PACKED;
372 * Length of the GET path that follows (if tracked).
374 uint32_t get_path_length GNUNET_PACKED;
377 * Peer which queried for get and should get the result.
379 struct GNUNET_PeerIdentity querying_peer;
382 * When does the content expire?
384 struct GNUNET_TIME_Absolute expiration_time;
387 * The key of the corresponding GET request.
389 struct GNUNET_HashCode key;
391 /* put path (if tracked) */
393 /* get path (if tracked) */
399 GNUNET_NETWORK_STRUCT_END
402 * Entry in friend_peermap.
408 * Information we keep per trail.
414 * MDLL entry in the list of all trails with the same predecessor.
416 struct Tail *prev_succ;
419 * MDLL entry in the list of all trails with the same predecessor.
421 struct Tail *next_succ;
424 * MDLL entry in the list of all trails with the same predecessor.
426 struct Tail *prev_pred;
429 * MDLL entry in the list of all trails with the same predecessor.
431 struct Tail *next_pred;
434 * Our predecessor in the trail, NULL if we are initiator (?).
436 struct FriendInfo *pred;
439 * Our successor in the trail, NULL if we are the last peer.
441 struct FriendInfo *succ;
444 * Identifier of the trail with the predecessor.
446 struct GNUNET_HashCode pred_id;
449 * Identifier of the trail with the successor.
451 struct GNUNET_HashCode succ_id;
454 * When does this trail expire.
456 struct GNUNET_TIME_Absolute expiration_time;
459 * Location of this trail in the heap.
461 struct GNUNET_CONTAINER_HeapNode *hn;
467 * Entry in friend_peermap.
474 struct GNUNET_PeerIdentity id;
476 struct Tail *pred_head;
478 struct Tail *pred_tail;
480 struct Tail *succ_head;
482 struct Tail *succ_tail;
485 * Core handle for sending messages to this friend.
487 struct GNUNET_MQ_Handle *mq;
494 * Task to timeout trails that have expired.
496 static struct GNUNET_SCHEDULER_Task *trail_timeout_task;
499 * Task to perform random walks.
501 static struct GNUNET_SCHEDULER_Task *random_walk_task;
504 * Identity of this peer.
506 static struct GNUNET_PeerIdentity my_identity;
509 * Peer map of all the fingers of a peer
511 static struct GNUNET_CONTAINER_MultiPeerMap *fingers_peermap;
514 * Peer map of all the successors of a peer
516 static struct GNUNET_CONTAINER_MultiPeerMap *successors_peermap;
519 * Tail map, mapping tail identifiers to `struct Trail`s
521 static struct GNUNET_CONTAINER_MultiHashMap *tail_map;
524 * Tail heap, organizing trails by expiration time.
526 static struct GNUNET_CONTAINER_Heap *tail_heap;
531 static struct GNUNET_CORE_Handle *core_api;
535 * Handle the put request from the client.
537 * @param key Key for the content
538 * @param block_type Type of the block
539 * @param options Routing options
540 * @param desired_replication_level Desired replication count
541 * @param expiration_time When does the content expire
542 * @param data Content to store
543 * @param data_size Size of content @a data in bytes
546 GDS_NEIGHBOURS_handle_put (const struct GNUNET_HashCode *key,
547 enum GNUNET_BLOCK_Type block_type,
548 enum GNUNET_DHT_RouteOption options,
549 uint32_t desired_replication_level,
550 struct GNUNET_TIME_Absolute expiration_time,
551 const void *data, size_t data_size)
557 * Handle the get request from the client file. If I am destination do
558 * datacache put and return. Else find the target friend and forward message
561 * @param key Key for the content
562 * @param block_type Type of the block
563 * @param options Routing options
564 * @param desired_replication_level Desired replication count
567 GDS_NEIGHBOURS_handle_get (const struct GNUNET_HashCode *key,
568 enum GNUNET_BLOCK_Type block_type,
569 enum GNUNET_DHT_RouteOption options,
570 uint32_t desired_replication_level)
577 * Send the get result to requesting client.
579 * @param key Key of the requested data.
580 * @param type Block type
581 * @param target_peer Next peer to forward the message to.
582 * @param source_peer Peer which has the data for the key.
583 * @param put_path_length Number of peers in @a put_path
584 * @param put_path Path taken to put the data at its stored location.
585 * @param get_path_length Number of peers in @a get_path
586 * @param get_path Path taken to reach to the location of the key.
587 * @param expiration When will this result expire?
588 * @param data Payload to store
589 * @param data_size Size of the @a data
592 GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key,
593 enum GNUNET_BLOCK_Type type,
594 const struct GNUNET_PeerIdentity *target_peer,
595 const struct GNUNET_PeerIdentity *source_peer,
596 unsigned int put_path_length,
597 const struct GNUNET_PeerIdentity *put_path,
598 unsigned int get_path_length,
599 const struct GNUNET_PeerIdentity *get_path,
600 struct GNUNET_TIME_Absolute expiration,
601 const void *data, size_t data_size)
607 * Method called whenever a peer disconnects.
610 * @param peer peer identity this notification is about
613 handle_core_disconnect (void *cls,
614 const struct GNUNET_PeerIdentity *peer)
616 struct FriendInfo *remove_friend;
618 /* If disconnected to own identity, then return. */
619 if (0 == memcmp (&my_identity,
621 sizeof (struct GNUNET_PeerIdentity)))
624 if (NULL == (remove_friend =
625 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
632 GNUNET_assert (GNUNET_YES ==
633 GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
636 /* FIXME: do stuff */
637 GNUNET_MQ_destroy (remove_friend->mq);
638 GNUNET_free (remove_friend);
640 GNUNET_CONTAINER_multipeermap_size (friend_peermap))
642 GNUNET_SCHEDULER_cancel (random_walk_task);
643 random_walk_task = NULL;
649 * Initiate a random walk.
655 do_random_walk (void *cls,
656 const struct GNUNET_SCHEDULER_TaskContext *tc)
658 struct FriendInfo *friend;
659 struct GNUNET_MQ_Envelope *env;
660 struct FingerSetupMessage *fsm;
661 struct db_cell *friend_cell;
664 friend = NULL; // FIXME: pick at random...
666 friend_cell = GNUNET_malloc(sizeof(struct db_cell));
667 friend_cell->peer_identity = friend->id;
669 trail = GNUNET_new(struct Trail);
671 /* We create the random walk so, no predecessor */
672 trail->succ = friend;
674 GNUNET_CONTAINER_MDLL_insert_tail(succ, trail->prev, trail->next,friend)
675 env = GNUNET_MQ_msg (fsm,
676 GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP);
677 fsm->hops_task = htons (0);
678 fsm->layer = htons (0); // FIXME: not always 0...
679 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE,
681 GNUNET_MQ_send (friend->mq,
687 * Method called whenever a peer connects.
690 * @param peer_identity peer identity this notification is about
693 handle_core_connect (void *cls,
694 const struct GNUNET_PeerIdentity *peer_identity)
696 struct FriendInfo *friend;
698 /* Check for connect to self message */
699 if (0 == memcmp (&my_identity,
701 sizeof (struct GNUNET_PeerIdentity)))
704 /* If peer already exists in our friend_peermap, then exit. */
706 GNUNET_CONTAINER_multipeermap_contains (friend_peermap,
713 friend = GNUNET_new (struct FriendInfo);
714 friend->id = *peer_identity;
715 friend->mq = GNUNET_CORE_mq_create (core_api,
717 GNUNET_assert (GNUNET_OK ==
718 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
721 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
724 if (NULL == random_walk_task)
726 random_walk_task = GNUNET_SCHEDULER_add_now (&do_random_walk,
733 * To be called on core init/fail.
735 * @param cls service closure
736 * @param identity the public identity of this peer
739 core_init (void *cls,
740 const struct GNUNET_PeerIdentity *identity)
742 my_identity = *identity;
747 * Handle a `struct FingerSetupMessage` from a GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP
750 * @param cls closure (NULL)
751 * @param peer sender identity
752 * @param message the setup message
753 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
756 handle_dht_p2p_finger_setup (void *cls,
757 const struct GNUNET_PeerIdentity *peer,
758 const struct GNUNET_MessageHeader *message)
760 const struct FingerSetupMessage *fsm;
762 fsm = (const struct FingerSetupMessage *) message;
766 * 1 check if the hops_taken is < to log(honest node)
767 * 1.a.1 if true : increments the hops_taken
768 * 1.a.2 send the same structure
769 * 1.b if false : drop the message
776 * Handle a `struct FingerSetupResponseMessage` from a GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP_RESPONSE
779 * @param cls closure (NULL)
780 * @param peer sender identity
781 * @param message the setup response message
782 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
785 handle_dht_p2p_finger_setup_response (void *cls,
786 const struct GNUNET_PeerIdentity *peer,
787 const struct GNUNET_MessageHeader *message)
789 const struct FingerSetupResponseMessage *fsrm;
791 fsm = (const struct FingerSetupResponseMessage *) message;
795 * 1 check if we are the correct layer
796 * 1.a if true : add the returned value (finger) in the db structure
797 * 1.b if true : do nothing
799 if(NUMBER_LAYERED_ID >= fsm->layer){
800 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
801 "The layer id is too big. %d received, an id below %d is expected",
802 fsm->layer, NUMBER_LAYERED_ID);
806 /* FIXME: add the value in db structure 1.a */
813 * Handle a `struct FingerDestroyMessage`.
815 * @param cls closure (NULL)
816 * @param peer sender identity
817 * @param message the finger destroy message
818 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
821 handle_dht_p2p_finger_destroy (void *cls,
822 const struct GNUNET_PeerIdentity *peer,
823 const struct GNUNET_MessageHeader *message)
825 const struct FingerDestroyMessage *fdm;
827 fdm = (const struct FingerDestroyMessage *) message;
831 * 1 check if message comme from a trail
832 * 1.a.1 if true: send the destroy message to the rest trail
833 * 1.a.2 clean the trail structure
834 * 1.a.3 did i have to remove the trail and ID from the db structure?
835 * 1.b if false: do nothing
842 * Handle a `struct FingerRouteMessage`.
844 * @param cls closure (NULL)
845 * @param peer sender identity
846 * @param message the finger route message
847 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
850 handle_dht_p2p_finger_route (void *cls,
851 const struct GNUNET_PeerIdentity *peer,
852 const struct GNUNET_MessageHeader *message)
854 const struct FingerRouteMessage *frm;
856 frm = (const struct FingerRouteMessage *) message;
857 /* FIXME: check the size of the message */
861 * 1 find the good trail
862 * 2 check the message inside
863 * 2.a if the message is a finger setup message : increments ce hops_takeb
864 * 3 send the finger route message
871 * Handle a `struct FingerSetupMessage` from a GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FIND
874 * @param cls closure (NULL)
875 * @param peer sender identity
876 * @param message the finger setup message
877 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
880 handle_dht_p2p_neighbour_find (void *cls,
881 const struct GNUNET_PeerIdentity *peer,
882 const struct GNUNET_MessageHeader *message)
884 const struct FingerSetupMessage *fsm;
886 fsm = (const struct FingerSetupMessage *) message;
892 * Handle a `struct FingerSetupResponseMessage` from a GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FIND
895 * @param cls closure (NULL)
896 * @param peer sender identity
897 * @param message the finger setup response message
898 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
901 handle_dht_p2p_neighbour_found (void *cls,
902 const struct GNUNET_PeerIdentity *peer,
903 const struct GNUNET_MessageHeader *message)
905 const struct FingerSetupResponseMessage *fsrm;
907 fsrm = (const struct FingerSetupResponseMessage *) message;
913 * Handle a `struct PeerGetMessage`.
915 * @param cls closure (NULL)
916 * @param peer sender identity
917 * @param message the peer get message
918 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
921 handle_dht_p2p_peer_get (void *cls,
922 const struct GNUNET_PeerIdentity *peer,
923 const struct GNUNET_MessageHeader *message)
925 const struct PeerGetMessage *pgm;
927 pgm = (const struct PeerGetMessage *) message;
931 * 1 extract the result
933 * 3 send it using the good trail
935 * What do i do when i don't have the key/value?
942 * Handle a `struct PeerGetResultMessage`.
944 * @param cls closure (NULL)
945 * @param peer sender identity
946 * @param message the peer get result message
947 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
950 handle_dht_p2p_peer_get_result (void *cls,
951 const struct GNUNET_PeerIdentity *peer,
952 const struct GNUNET_MessageHeader *message)
954 const struct PeerGetResultMessage *pgrm;
956 pgrm = (const struct PeerGetResultMessage *) message;
960 * 1 extract the result
961 * 2 create a peerGetResult struct
962 * 3 send it using the good trail
964 * What do i do when i don't have the key/value?
972 * Handle a `struct PeerPutMessage`.
974 * @param cls closure (NULL)
975 * @param peer sender identity
976 * @param message the peer put message
977 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
980 handle_dht_p2p_peer_put (void *cls,
981 const struct GNUNET_PeerIdentity *peer,
982 const struct GNUNET_MessageHeader *message)
984 const struct PeerGetResultMessage *pgrm;
986 pgrm = (const struct PeerGetResultMessage *) message;
990 * 1 check the size of the message
991 * 2 use the API to add the value in the "database". Check on the xdht file, how to do it.
992 * 3 Did i a have to return a notification or did i have to return GNUNET_[OK|SYSERR]?
999 * Initialize neighbours subsystem.
1000 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1003 GDS_NEIGHBOURS_init (void)
1005 static const struct GNUNET_CORE_MessageHandler core_handlers[] = {
1006 { &handle_dht_p2p_finger_setup,
1007 GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP,
1008 sizeof (struct FingerSetupMessage) },
1009 { &handle_dht_p2p_finger_setup_response,
1010 GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP_RESPONSE,
1011 sizeof (struct FingerSetupResponseMessage) },
1012 { &handle_dht_p2p_finger_destroy,
1013 GNUNET_MESSAGE_TYPE_WDHT_FINGER_DESTROY,
1014 sizeof (struct FingerDestroyMessage) },
1015 { &handle_dht_p2p_finger_route,
1016 GNUNET_MESSAGE_TYPE_WDHT_FINGER_ROUTE,
1018 { &handle_dht_p2p_neighbour_find,
1019 GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FIND,
1020 sizeof (struct FingerSetupMessage) },
1021 { &handle_dht_p2p_neighbour_found,
1022 GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FOUND,
1023 sizeof (struct FingerSetupResponseMessage) },
1024 { &handle_dht_p2p_peer_get,
1025 GNUNET_MESSAGE_TYPE_WDHT_GET,
1026 sizeof (struct PeerGetMessage) },
1027 { &handle_dht_p2p_peer_get_result,
1028 GNUNET_MESSAGE_TYPE_WDHT_GET_RESULT,
1030 { &handle_dht_p2p_peer_put,
1031 GNUNET_MESSAGE_TYPE_WDHT_PUT,
1037 GNUNET_CORE_connect (GDS_cfg, NULL,
1039 &handle_core_connect,
1040 &handle_core_disconnect,
1045 if (NULL == core_api)
1046 return GNUNET_SYSERR;
1048 fingers_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1049 successors_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1051 init_db_structure();
1061 * Shutdown neighbours subsystem.
1064 GDS_NEIGHBOURS_done (void)
1066 if (NULL == core_api)
1068 GNUNET_CORE_disconnect (core_api);
1071 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
1072 GNUNET_CONTAINER_multipeermap_destroy (fingers_peermap);
1073 GNUNET_CONTAINER_multipeermap_destroy (successors_peermap);
1074 destroy_db_structure();
1076 friend_peermap = NULL;
1083 * @return my identity
1085 struct GNUNET_PeerIdentity
1086 GDS_NEIGHBOURS_get_my_id (void)
1091 /* end of gnunet-service-wdht_neighbours.c */