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 bucket and neighbour 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"
51 /* The maximum possible fingers of a peer. */
52 #define MAX_FINGERS 256
55 * Maximum allowed number of pending messages per peer.
57 #define MAXIMUM_PENDING_PER_PEER 64
60 * How long at least to wait before sending another find finger trail request.
62 #define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
65 * How long at most to wait before sending another find finger trail request.
67 #define DHT_MAXIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 10)
70 GNUNET_NETWORK_STRUCT_BEGIN
73 * 1) Bloomfilter is not required for X-Vine.
74 * Keep the field now but remove it when implementing PUT/GET.
75 * 2) also, check the field of put/get/result if all are required for
84 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
86 struct GNUNET_MessageHeader header;
91 uint32_t options GNUNET_PACKED;
96 uint32_t type GNUNET_PACKED;
101 uint32_t hop_count GNUNET_PACKED;
104 * Replication level for this message
106 uint32_t desired_replication_level GNUNET_PACKED;
109 * Length of the PUT path that follows (if tracked).
111 uint32_t put_path_length GNUNET_PACKED;
114 * When does the content expire?
116 struct GNUNET_TIME_AbsoluteNBO expiration_time;
119 * Bloomfilter (for peer identities) to stop circular routes
121 char bloomfilter[DHT_BLOOM_SIZE];
124 * The key we are storing under.
126 struct GNUNET_HashCode key;
128 /* put path (if tracked) */
138 struct PeerResultMessage
141 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT
143 struct GNUNET_MessageHeader header;
148 uint32_t type GNUNET_PACKED;
151 * Length of the PUT path that follows (if tracked).
153 uint32_t put_path_length GNUNET_PACKED;
156 * Length of the GET path that follows (if tracked).
158 uint32_t get_path_length GNUNET_PACKED;
161 * When does the content expire?
163 struct GNUNET_TIME_AbsoluteNBO expiration_time;
166 * The key of the corresponding GET request.
168 struct GNUNET_HashCode key;
170 /* put path (if tracked) */
172 /* get path (if tracked) */
182 struct PeerGetMessage
185 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET
187 struct GNUNET_MessageHeader header;
192 uint32_t options GNUNET_PACKED;
195 * Desired content type.
197 uint32_t type GNUNET_PACKED;
202 uint32_t hop_count GNUNET_PACKED;
205 * Desired replication level for this request.
207 uint32_t desired_replication_level GNUNET_PACKED;
210 * Size of the extended query.
212 uint32_t xquery_size;
215 * Bloomfilter mutator.
220 * Bloomfilter (for peer identities) to stop circular routes
222 char bloomfilter[DHT_BLOOM_SIZE];
225 * The key we are looking for.
227 struct GNUNET_HashCode key;
233 * FIXME : should change the fields
234 * P2P Trail setup message
236 struct PeerTrailSetupMessage
239 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP
241 struct GNUNET_MessageHeader header;
243 /* Source peer which wants to find trail to one of its finger. */
244 struct GNUNET_PeerIdentity *source_peer;
246 /* Finger id to which we want to set up the trail to. */
247 struct GNUNET_PeerIdentity *destination_finger;
249 /* This field contains the peer to which this packet is forwarded.
250 If temp_destination = my_identity, then check if destination_finger = temp_destination.
251 If temp_destination != my_identity, then it means you are part of trail that
252 you take to temp_destination. So, search in routing table.
254 struct GNUNET_PeerIdentity *temp_destination;
256 /*FIXME: I want to store a list of all the peer_id which are part of trail in
258 Also, when sending the reply back we are just going to read this list
259 backwards. Assuming that we add a new peer at the end of our list. */
265 * P2P Trail setup Result message
266 * TODO: Check the fields and if they are really required.
267 * FIXME: should change the fields
268 * it can contain the peertrailsetup only
269 * and we just read the list backwards and make the
270 * packet reach to destination
271 *There can be lots and lots of cases where the packet are lost but
272 * as we have non blocking function call we are ok
273 * i think i will implement and verify by printing the design.
275 struct PeerTrailSetupResultMessage
278 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_RESULT_SETUP
280 struct GNUNET_MessageHeader header;
285 uint32_t type GNUNET_PACKED;
288 * Length of the PUT path that follows (if tracked).
290 uint32_t put_path_length GNUNET_PACKED;
293 * Length of the GET path that follows (if tracked).
295 uint32_t get_path_length GNUNET_PACKED;
298 * When does the content expire?
300 struct GNUNET_TIME_AbsoluteNBO expiration_time;
303 * The key of the corresponding GET request.
305 struct GNUNET_HashCode key;
307 /* put path (if tracked) */
309 /* get path (if tracked) */
315 GNUNET_NETWORK_STRUCT_END
319 * Linked list of messages to send to a particular other peer.
321 struct P2PPendingMessage
324 * Pointer to next item in the list
326 struct P2PPendingMessage *next;
329 * Pointer to previous item in the list
331 struct P2PPendingMessage *prev;
334 * When does this message time out?
336 struct GNUNET_TIME_Absolute timeout;
339 * Message importance level. FIXME: used? useful?
341 unsigned int importance;
344 * Actual message to be sent, allocated at the end of the struct:
345 * // msg = (cast) &pm[1];
346 * // memcpy (&pm[1], data, len);
348 const struct GNUNET_MessageHeader *msg;
354 * Entry in friend_peers map.
360 * What is the identity of the peer?
362 struct GNUNET_PeerIdentity id;
365 * Count of outstanding messages for peer.
367 unsigned int pending_count;
370 * Head of pending messages to be sent to this peer.
372 struct P2PPendingMessage *head;
375 * Tail of pending messages to be sent to this peer.
377 struct P2PPendingMessage *tail;
381 * TODO - How and where to use this?
382 * Core handle for sending messages to this peer.
384 struct GNUNET_CORE_TransmitHandle *th;
389 * Linked List of peers which are part of trail to reach a particular Finger.
394 * Pointer to next item in the list
396 struct TrailList *next;
399 * Pointer to previous item in the list
401 struct TrailList *prev;
405 * Entry in finger_peers map.
410 * What is the identity of the peer?
412 struct GNUNET_PeerIdentity id;
414 /* FIXME:: Range of keys for which this finger is responsible */
415 /* Start of the interval of keys for which this finger is responsible. */
416 unsigned int interval_start;
418 /* End of the interval of keys for which this finger is responsible. */
419 unsigned int interval_end;
422 /* FIXME:: A double link list which stores the trail to reach it from given peer .*/
425 * Head of trail list.
427 struct TrailList *head;
430 * Tail of trail list.
432 struct TrailList *tail;
437 * Task that sends FIND FINGER TRAIL requests.
439 static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task;
442 * Identity of this peer.
444 static struct GNUNET_PeerIdentity my_identity;
447 * Hash of the identity of this peer.
449 static struct GNUNET_HashCode my_identity_hash;
452 * Hash map of all the friends of a peer
454 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peers;
457 * Hash map of all the fingers of a peer
459 static struct GNUNET_CONTAINER_MultiPeerMap *finger_peers;
464 static struct GNUNET_ATS_PerformanceHandle *atsAPI;
469 static struct GNUNET_CORE_Handle *core_api;
472 * The highest finger_id that we have found trail to.
474 static unsigned int finger_id;
478 * Called when core is ready to send a message we asked for
479 * out to the destination. At the moment, I have just copied it from previous
482 * @param cls the 'struct PeerInfo' of the target peer
483 * @param size number of bytes available in buf
484 * @param buf where the callee should write the message
485 * @return number of bytes written to buf
488 core_transmit_notify (void *cls, size_t size, void *buf)
490 struct FriendInfo *peer = cls;
492 struct P2PPendingMessage *pending;
497 while ((NULL != (pending = peer->head)) &&
498 (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us))
500 peer->pending_count--;
501 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
502 GNUNET_free (pending);
506 /* no messages pending */
512 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
514 GNUNET_TIME_absolute_get_remaining
515 (pending->timeout), &peer->id,
516 ntohs (pending->msg->size),
517 &core_transmit_notify, peer);
518 GNUNET_break (NULL != peer->th);
522 while ((NULL != (pending = peer->head)) &&
523 (size - off >= (msize = ntohs (pending->msg->size))))
525 GNUNET_STATISTICS_update (GDS_stats,
527 ("# Bytes transmitted to other peers"), msize,
529 memcpy (&cbuf[off], pending->msg, msize);
531 peer->pending_count--;
532 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
533 GNUNET_free (pending);
535 if (peer->head != NULL)
538 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
540 GNUNET_TIME_absolute_get_remaining
541 (pending->timeout), &peer->id, msize,
542 &core_transmit_notify, peer);
543 GNUNET_break (NULL != peer->th);
550 * Transmit all messages in the peer's message queue.
552 * @param peer message queue to process
555 process_peer_queue (struct FriendInfo *peer)
558 struct P2PPendingMessage *pending;
560 if (NULL == (pending = peer->head))
562 if (NULL != peer->th)
564 GNUNET_STATISTICS_update (GDS_stats,
566 ("# Bytes of bandwidth requested from core"),
567 ntohs (pending->msg->size), GNUNET_NO);
568 /*FIXME : here I don't know the use of importance, time out
569 Will check at run time if its all correct. */
571 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
573 GNUNET_TIME_absolute_get_remaining
574 (pending->timeout), &peer->id,
575 ntohs (pending->msg->size),
576 &core_transmit_notify, peer);
577 GNUNET_break (NULL != peer->th);
582 * This function is similar to get request but used specifically for trail
583 * construction. I don't know if using GDS_NEIGHBOURS_handle_get is sufficient
584 * or we need this new function.
585 * @param Finger id to which we want to setup the trail.
586 * @param Friend id through which we will try to setup the trail.
589 GDS_NEIGHBOURS_trail_setup(struct GNUNET_PeerIdentity *finger_id,
590 struct FriendInfo *target_friend)
593 1. first construct the trail message which should contain
594 * the source peer id, the finger peer id and randomly chosen one of our
595 * friends peer id. Should there be a new block type?
596 * Construct a message and add it to your peer queue of the friend you have
597 * chosen to send the packet to and then call process_peer_queue.
598 * Just follow GDS_NEIGHBOURS_handle_reply to complete this function.
601 * FIXME: check if pending message actually contains the correct data.
603 struct P2PPendingMessage *pending;
604 /* FIXME: why I have defined as **? verify by testing. */
605 struct PeerTrailSetupMessage *tsm;
608 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_PEER)
610 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
614 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage));
615 tsm = (struct PeerTrailSetupMessage *) &pending[1];
616 pending->msg = &tsm->header;
617 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
618 tsm->destination_finger = finger_id;
619 tsm->source_peer = &my_identity;
620 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
621 target_friend->pending_count++;
622 process_peer_queue(target_friend);
626 /**FIXME: Old implementation just to remove error
627 * Perform a GET operation. Forwards the given request to other
628 * peers. Does not lookup the key locally. May do nothing if this is
629 * the only peer in the network (or if we are the closest peer in the
632 * @param type type of the block
633 * @param options routing options
634 * @param desired_replication_level desired replication count
635 * @param hop_count how many hops did this request traverse so far?
636 * @param key key for the content
637 * @param xquery extended query
638 * @param xquery_size number of bytes in @a xquery
639 * @param reply_bf bloomfilter to filter duplicates
640 * @param reply_bf_mutator mutator for @a reply_bf
641 * @param peer_bf filter for peers not to select (again)
644 GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
645 enum GNUNET_DHT_RouteOption options,
646 uint32_t desired_replication_level,
647 uint32_t hop_count, const struct GNUNET_HashCode * key,
648 const void *xquery, size_t xquery_size,
649 const struct GNUNET_CONTAINER_BloomFilter *reply_bf,
650 uint32_t reply_bf_mutator,
651 struct GNUNET_CONTAINER_BloomFilter *peer_bf)
656 /**FIXME: Old implementation just to remove error.
657 * Perform a PUT operation. Forwards the given request to other
658 * peers. Does not store the data locally. Does not give the
659 * data to local clients. May do nothing if this is the only
660 * peer in the network (or if we are the closest peer in the
663 * @param type type of the block
664 * @param options routing options
665 * @param desired_replication_level desired replication count
666 * @param expiration_time when does the content expire
667 * @param hop_count how many hops has this message traversed so far
668 * @param bf Bloom filter of peers this PUT has already traversed
669 * @param key key for the content
670 * @param put_path_length number of entries in @a put_path
671 * @param put_path peers this request has traversed so far (if tracked)
672 * @param data payload to store
673 * @param data_size number of bytes in @a data
676 GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
677 enum GNUNET_DHT_RouteOption options,
678 uint32_t desired_replication_level,
679 struct GNUNET_TIME_Absolute expiration_time,
681 struct GNUNET_CONTAINER_BloomFilter *bf,
682 const struct GNUNET_HashCode *key,
683 unsigned int put_path_length,
684 struct GNUNET_PeerIdentity *put_path,
685 const void *data, size_t data_size)
690 * Randomly choose one of your friends from the friends_peer map
693 static struct FriendInfo *
701 * Use Chord formula finger[i]=(n+2^(i-1))mod m,
702 * where i = current finger map index.
703 * n = own peer identity
704 * m = number of bits in peer id.
705 * @return finger_peer_id for which we have to find the trail through network.
707 static struct GNUNET_PeerIdentity *
708 finger_id_to_search()
710 /* After finding the finger_id increment the value of 'i'
711 so that the next search begins from there. */
712 struct GNUNET_PeerIdentity *finger_peer_id;
716 /* FIXME: This typecasting is not correct. */
717 //finger_peer_id = ((unsigned int)(my_identity.public_key.q_y)+(2^(finger_id)))%MAX_FINGERS;
719 /* Increment the next finger_id we should be searching. */
720 finger_id = (finger_id+1)%MAX_FINGERS;
722 return finger_peer_id;
728 * Task to send a find finger trail message. We attempt to find trail
729 * to our fingers in the network.
731 * @param cls closure for this task
732 * @param tc the context under which the task is running
735 send_find_finger_trail_message (void *cls,
736 const struct GNUNET_SCHEDULER_TaskContext *tc)
738 /* finger we are searching for */
739 struct GNUNET_PeerIdentity *finger_peer_id;
740 struct FriendInfo *friend_peer_id;
741 struct GNUNET_TIME_Relative next_send_time;
743 /* FIXME: Not sure if this is required. Here I am checking if I have
744 already found trail for each of the possible finger. If yes then don't look
745 anymore in the network. */
746 if (GNUNET_CONTAINER_multipeermap_size(finger_peers) == MAX_FINGERS)
751 /* Find the finger_peer_id to which we want to setup the trial */
752 finger_peer_id = finger_id_to_search();
754 /* Choose a friend randomly from your friend_peers map. */
755 friend_peer_id = get_friend();
757 GDS_NEIGHBOURS_trail_setup(finger_peer_id, friend_peer_id);
759 /* FIXME: Is using finger_id to generate random function ok here. */
760 next_send_time.rel_value_us =
761 DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value_us +
762 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
763 DHT_MAXIMUM_FIND_PEER_INTERVAL.rel_value_us /
766 find_finger_trail_task =
767 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_finger_trail_message,
773 * Method called whenever a peer connects.
776 * @param peer peer identity this notification is about
779 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
781 /*When a peer is connected, then add it to your friend_peers map.
782 Also, start an asynchronous method to look for your fingers that you can
783 reach whenever you get the first connection to the peer. Also try to
784 reach to your predecessor. */
786 struct FriendInfo *ret;
787 struct GNUNET_HashCode phash;
789 /* Check for connect to self message */
790 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
793 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
798 GNUNET_CONTAINER_multipeermap_contains (friend_peers,
805 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
807 GNUNET_CRYPTO_hash (peer,
808 sizeof (struct GNUNET_PeerIdentity),
811 ret = GNUNET_new (struct FriendInfo);
814 GNUNET_assert (GNUNET_OK ==
815 GNUNET_CONTAINER_multipeermap_put (friend_peers,
817 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
819 /* got a first connection, good time to start with FIND TRAIL TO FINGER requests... */
820 if (1 == GNUNET_CONTAINER_multipeermap_size(friend_peers))
821 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
826 * Method called whenever a peer disconnects.
829 * @param peer peer identity this notification is about
832 handle_core_disconnect (void *cls,
833 const struct GNUNET_PeerIdentity *peer)
840 * To be called on core init/fail.
842 * @param cls service closure
843 * @param identity the public identity of this peer
846 core_init (void *cls,
847 const struct GNUNET_PeerIdentity *identity)
849 my_identity = *identity;
850 GNUNET_CRYPTO_hash (identity,
851 sizeof (struct GNUNET_PeerIdentity),
857 * Core handler for p2p put requests.
860 * @param peer sender of the request
861 * @param message message
862 * @param peer peer identity this notification is about
863 * @return #GNUNET_OK to keep the connection open,
864 * #GNUNET_SYSERR to close it (signal serious error)
867 handle_dht_p2p_put (void *cls,
868 const struct GNUNET_PeerIdentity *peer,
869 const struct GNUNET_MessageHeader *message)
872 1. Search the friend,finger and check your own id to find the closest
873 * predecessor the given key.
874 2. If self then datache_store
875 3. If friend, then add to peer queue
876 4. If finger, then add to the peer queue of the first hop.Again the
877 * same doubt,how does a peer when it is in handle_dht_p2p_put makes
878 * a distinction weather it should do a lookup in routing table or finger or
886 * Core handler for p2p get requests.
889 * @param peer sender of the request
890 * @param message message
891 * @return #GNUNET_OK to keep the connection open,
892 * #GNUNET_SYSERR to close it (signal serious error)
895 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
896 const struct GNUNET_MessageHeader *message)
903 * Core handler for p2p result messages.
906 * @param message message
907 * @param peer peer identity this notification is about
908 * @return #GNUNET_YES (do not cut p2p connection)
911 handle_dht_p2p_result (void *cls, const struct GNUNET_PeerIdentity *peer,
912 const struct GNUNET_MessageHeader *message)
919 * Read the trail setup message backwards to find which is the next hop to which
920 * it should be send to.
924 struct GNUNET_PeerIdentity *
932 * Find the predecessor for given finger_id from the
933 * friend and finger table.
934 * if friend, then just return the friend it
935 * if finger, then return the next hop to forward the packet to.
939 struct GNUNET_PeerIdentity *
947 * Core handler for P2P trail setup message.
950 handle_dht_p2p_trail_setup()
953 * When we get this message from our friend then
954 * 1. Check the destination finger id that the message is looking for.
955 * 2. If my_identity = destination, then create a trail_setup_result message
956 * read the path taken to reach to you. read that list backwards to find which
957 * friend to forward this trailsetupresult to. find_next_hop()
958 * call process_peer_queue() to add trailsetupresult message to peer
959 * 3. If you are not the destination
960 * then call find_predecessor() to find closest finger to our given finger_id
971 * Core handle for p2p trail construction result messages.
976 handle_dht_p2p_trail_setup_result()
979 Here you got a message that trail is set*/
985 * Initialize neighbours subsystem.
986 * @return GNUNET_OK on success, GNUNET_SYSERR on error
989 GDS_NEIGHBOURS_init()
991 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
992 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0},
993 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0},
994 {&handle_dht_p2p_result, GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT, 0},
995 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP, 0},
996 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT, 0},
1000 atsAPI = GNUNET_ATS_performance_init (GDS_cfg, NULL, NULL);
1002 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
1003 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
1004 GNUNET_NO, core_handlers);
1005 if (core_api == NULL)
1006 return GNUNET_SYSERR;
1008 friend_peers = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1009 finger_peers = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1018 * Shutdown neighbours subsystem.
1021 GDS_NEIGHBOURS_done ()
1023 if (NULL == core_api)
1025 GNUNET_CORE_disconnect (core_api);
1027 GNUNET_ATS_performance_done (atsAPI);
1030 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peers));
1031 GNUNET_CONTAINER_multipeermap_destroy (friend_peers);
1032 friend_peers = NULL;
1034 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (finger_peers));
1035 GNUNET_CONTAINER_multipeermap_destroy (finger_peers);
1036 finger_peers = NULL;
1038 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
1040 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
1041 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
1047 * Get the ID of the local node.
1049 * @return identity of the local node
1051 struct GNUNET_PeerIdentity *
1052 GDS_NEIGHBOURS_get_id ()
1054 return &my_identity;
1058 /* end of gnunet-service-xdht_neighbours.c */