Add some comments in the handler functions.
[oweals/gnunet.git] / src / dht / gnunet-service-wdht_neighbours.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2015 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19 */
20
21 /**
22  * @file dht/gnunet-service-wdht_neighbours.c
23  * @brief GNUnet DHT service's finger and friend table management code
24  * @author Supriti Singh
25  */
26
27 #include "platform.h"
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"
43 #include <fenv.h>
44 #include "dht.h"
45
46 #define DEBUG(...)                                           \
47   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
48
49 /**
50  * FIXME
51  */
52 #define FOO_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
53
54 /**
55  * The number of layered ID to use.
56  */
57 #define NUMBER_LAYERED_ID 8
58
59 /**
60  * Contains all the layered ID.
61  */
62 struct GNUNET_PeerIdentity layered_id[NUMBER_LAYERED_ID];
63
64
65 GNUNET_NETWORK_STRUCT_BEGIN
66
67 /**
68  * Setup a finger using the underlay topology ("social network").
69  */
70 struct FingerSetupMessage
71 {
72   /**
73    * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP
74    */
75   struct GNUNET_MessageHeader header;
76
77   /**
78    * Number of hops this message has taken so far, we stop at
79    * log(NSE), in NBO.
80    */
81   uint16_t hops_taken GNUNET_PACKED;
82
83   /**
84    * Layer for the request, in NBO.
85    */
86   uint16_t layer GNUNET_PACKED;
87
88   /**
89    * Unique (random) identifier this peer will use to
90    * identify the finger (in future messages).
91    */
92   struct GNUNET_HashCode finger_id;
93
94 };
95
96
97 /**
98  * Response to a `struct FingerSetupMessage`.
99  */
100 struct FingerSetupResponseMessage
101 {
102   /**
103    * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP_RESPONSE
104    */
105   struct GNUNET_MessageHeader header;
106
107   /**
108    * Zero, for alignment.
109    */
110   uint32_t reserved GNUNET_PACKED;
111
112   /**
113    * Unique (random) identifier this peer will use to
114    * identify the finger (in future messages).
115    */
116   struct GNUNET_HashCode finger_id;
117
118   /**
119    * Random location in the respective layer where the
120    * random path of the finger setup terminated.
121    */
122   struct GNUNET_HashCode location;
123
124 };
125
126
127 /**
128  * Response to an event that causes a finger to die.
129  */
130 struct FingerDestroyMessage
131 {
132   /**
133    * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_DESTROY
134    */
135   struct GNUNET_MessageHeader header;
136
137   /**
138    * Zero, for alignment.
139    */
140   uint32_t reserved GNUNET_PACKED;
141
142   /**
143    * Unique (random) identifier this peer will use to
144    * identify the finger (in future messages).
145    */
146   struct GNUNET_HashCode finger_id;
147
148 };
149
150
151 /**
152  * Send a message along a finger.
153  */
154 struct FingerRouteMessage
155 {
156   /**
157    * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_ROUTE
158    */
159   struct GNUNET_MessageHeader header;
160
161   /**
162    * Zero, for alignment.
163    */
164   uint32_t reserved GNUNET_PACKED;
165
166   /**
167    * Unique (random) identifier this peer will use to
168    * identify the finger (in future messages).
169    */
170   struct GNUNET_HashCode finger_id;
171
172   /* followed by payload to send along the finger */
173 };
174
175
176 /**
177  * P2P PUT message
178  */
179 struct PeerPutMessage
180 {
181   /**
182    * Type: #GNUNET_MESSAGE_TYPE_WDHT_P2P_PUT
183    */
184   struct GNUNET_MessageHeader header;
185
186   /**
187    * Processing options
188    */
189   uint32_t options GNUNET_PACKED;
190
191   /**
192    * Content type.
193    */
194   uint32_t block_type GNUNET_PACKED;
195
196   /**
197    * Hop count
198    */
199   uint32_t hop_count GNUNET_PACKED;
200
201   /**
202    * Replication level for this message
203    * In the current implementation, this value is not used.
204    */
205   uint32_t desired_replication_level GNUNET_PACKED;
206
207   /**
208    * Length of the PUT path that follows (if tracked).
209    */
210   uint32_t put_path_length GNUNET_PACKED;
211
212   /**
213    * When does the content expire?
214    */
215   struct GNUNET_TIME_AbsoluteNBO expiration_time;
216
217   /**
218    * The key to store the value under.
219    */
220   struct GNUNET_HashCode key GNUNET_PACKED;
221
222   /* put path (if tracked) */
223
224   /* Payload */
225
226 };
227
228 /**
229  * P2P GET message
230  */
231 struct PeerGetMessage
232 {
233   /**
234    * Type: #GNUNET_MESSAGE_TYPE_WDHT_P2P_GET
235    */
236   struct GNUNET_MessageHeader header;
237
238   /**
239    * Processing options
240    */
241   uint32_t options GNUNET_PACKED;
242
243   /**
244    * Desired content type.
245    */
246   uint32_t block_type GNUNET_PACKED;
247
248   /**
249    * Hop count
250    */
251   uint32_t hop_count GNUNET_PACKED;
252
253   /**
254    * Desired replication level for this request.
255    * In the current implementation, this value is not used.
256    */
257   uint32_t desired_replication_level GNUNET_PACKED;
258
259   /**
260    * Total number of peers in get path.
261    */
262   unsigned int get_path_length;
263
264   /**
265    * The key we are looking for.
266    */
267   struct GNUNET_HashCode key;
268
269   /* Get path. */
270   /* struct GNUNET_PeerIdentity[]*/
271 };
272
273
274 /**
275  * P2P Result message
276  */
277 struct PeerGetResultMessage
278 {
279   /**
280    * Type: #GNUNET_MESSAGE_TYPE_WDHT_P2P_GET_RESULT
281    */
282   struct GNUNET_MessageHeader header;
283
284   /**
285    * The type for the data.
286    */
287   uint32_t type GNUNET_PACKED;
288
289   /**
290    * Number of peers recorded in the outgoing path from source to the
291    * stored location of this message.
292    */
293   uint32_t put_path_length GNUNET_PACKED;
294
295   /**
296    * Length of the GET path that follows (if tracked).
297    */
298   uint32_t get_path_length GNUNET_PACKED;
299
300   /**
301    * Peer which queried for get and should get the result.
302    */
303   struct GNUNET_PeerIdentity querying_peer;
304
305   /**
306    * When does the content expire?
307    */
308   struct GNUNET_TIME_Absolute expiration_time;
309
310   /**
311    * The key of the corresponding GET request.
312    */
313   struct GNUNET_HashCode key;
314
315   /* put path (if tracked) */
316
317   /* get path (if tracked) */
318
319   /* Payload */
320
321 };
322
323 GNUNET_NETWORK_STRUCT_END
324
325 /**
326  * Entry in friend_peermap.
327  */
328 struct FriendInfo;
329
330
331 /**
332  * Information we keep per trail.
333  */
334 struct Trail
335 {
336
337   /**
338    * MDLL entry in the list of all trails with the same predecessor.
339    */
340   struct Tail *prev_succ;
341
342   /**
343    * MDLL entry in the list of all trails with the same predecessor.
344    */
345   struct Tail *next_succ;
346
347   /**
348    * MDLL entry in the list of all trails with the same predecessor.
349    */
350   struct Tail *prev_pred;
351
352   /**
353    * MDLL entry in the list of all trails with the same predecessor.
354    */
355   struct Tail *next_pred;
356
357   /**
358    * Our predecessor in the trail, NULL if we are initiator (?).
359    */
360   struct FriendInfo *pred;
361
362   /**
363    * Our successor in the trail, NULL if we are the last peer.
364    */
365   struct FriendInfo *succ;
366
367   /**
368    * Identifier of the trail with the predecessor.
369    */
370   struct GNUNET_HashCode pred_id;
371
372   /**
373    * Identifier of the trail with the successor.
374    */
375   struct GNUNET_HashCode succ_id;
376
377   /**
378    * When does this trail expire.
379    */
380   struct GNUNET_TIME_Absolute expiration_time;
381
382   /**
383    * Location of this trail in the heap.
384    */
385   struct GNUNET_CONTAINER_HeapNode *hn;
386
387 };
388
389
390 /**
391  *  Entry in friend_peermap.
392  */
393 struct FriendInfo
394 {
395   /**
396    * Friend Identity
397    */
398   struct GNUNET_PeerIdentity id;
399
400   struct Tail *pred_head;
401
402   struct Tail *pred_tail;
403
404   struct Tail *succ_head;
405
406   struct Tail *succ_tail;
407
408   /**
409    * Core handle for sending messages to this friend.
410    * FIXME: use MQ?
411    */
412   struct GNUNET_CORE_TransmitHandle *th;
413
414 };
415
416
417
418 /**
419  * Task to timeout trails that have expired.
420  */
421 static struct GNUNET_SCHEDULER_Task *trail_timeout_task;
422
423 /**
424  * Identity of this peer.
425  */
426 static struct GNUNET_PeerIdentity my_identity;
427
428 /**
429  * Peer map of all the fingers of a peer
430  */
431 static struct GNUNET_CONTAINER_MultiPeerMap *fingers_peermap;
432
433 /**
434  * Peer map of all the successors of a peer
435  */
436 static struct GNUNET_CONTAINER_MultiPeerMap *successors_peermap;
437
438 /**
439  * Tail map, mapping tail identifiers to `struct Trail`s
440  */
441 static struct GNUNET_CONTAINER_MultiHashMap *tail_map;
442
443 /**
444  * Tail heap, organizing trails by expiration time.
445  */
446 static struct GNUNET_CONTAINER_Heap *tail_heap;
447
448 /**
449  * Handle to CORE.
450  */
451 static struct GNUNET_CORE_Handle *core_api;
452
453
454 /**
455  * Handle the put request from the client.
456  *
457  * @param key Key for the content
458  * @param block_type Type of the block
459  * @param options Routing options
460  * @param desired_replication_level Desired replication count
461  * @param expiration_time When does the content expire
462  * @param data Content to store
463  * @param data_size Size of content @a data in bytes
464  */
465 void
466 GDS_NEIGHBOURS_handle_put (const struct GNUNET_HashCode *key,
467                            enum GNUNET_BLOCK_Type block_type,
468                            enum GNUNET_DHT_RouteOption options,
469                            uint32_t desired_replication_level,
470                            struct GNUNET_TIME_Absolute expiration_time,
471                            const void *data, size_t data_size)
472 {
473 }
474
475
476 /**
477  * Handle the get request from the client file. If I am destination do
478  * datacache put and return. Else find the target friend and forward message
479  * to it.
480  *
481  * @param key Key for the content
482  * @param block_type Type of the block
483  * @param options Routing options
484  * @param desired_replication_level Desired replication count
485  */
486 void
487 GDS_NEIGHBOURS_handle_get (const struct GNUNET_HashCode *key,
488                            enum GNUNET_BLOCK_Type block_type,
489                            enum GNUNET_DHT_RouteOption options,
490                            uint32_t desired_replication_level)
491 {
492 }
493
494
495
496 /**
497  * Send the get result to requesting client.
498  *
499  * @param key Key of the requested data.
500  * @param type Block type
501  * @param target_peer Next peer to forward the message to.
502  * @param source_peer Peer which has the data for the key.
503  * @param put_path_length Number of peers in @a put_path
504  * @param put_path Path taken to put the data at its stored location.
505  * @param get_path_length Number of peers in @a get_path
506  * @param get_path Path taken to reach to the location of the key.
507  * @param expiration When will this result expire?
508  * @param data Payload to store
509  * @param data_size Size of the @a data
510  */
511 void
512 GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key,
513                                 enum GNUNET_BLOCK_Type type,
514                                 const struct GNUNET_PeerIdentity *target_peer,
515                                 const struct GNUNET_PeerIdentity *source_peer,
516                                 unsigned int put_path_length,
517                                 const struct GNUNET_PeerIdentity *put_path,
518                                 unsigned int get_path_length,
519                                 const struct GNUNET_PeerIdentity *get_path,
520                                 struct GNUNET_TIME_Absolute expiration,
521                                 const void *data, size_t data_size)
522 {
523 }
524
525
526 /**
527  * Method called whenever a peer disconnects.
528  *
529  * @param cls closure
530  * @param peer peer identity this notification is about
531  */
532 static void
533 handle_core_disconnect (void *cls,
534                         const struct GNUNET_PeerIdentity *peer)
535 {
536   struct FriendInfo *remove_friend;
537
538   /* If disconnected to own identity, then return. */
539   if (0 == memcmp (&my_identity,
540                    peer,
541                    sizeof (struct GNUNET_PeerIdentity)))
542     return;
543
544   if (NULL == (remove_friend =
545                GNUNET_CONTAINER_multipeermap_get (friend_peermap,
546                                                   peer)))
547   {
548     GNUNET_break (0);
549     return;
550   }
551
552   GNUNET_assert (GNUNET_YES ==
553                  GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
554                                                        peer,
555                                                        remove_friend));
556   /* FIXME: do stuff */
557 }
558
559
560 /**
561  * Method called whenever a peer connects.
562  *
563  * @param cls closure
564  * @param peer_identity peer identity this notification is about
565  */
566 static void
567 handle_core_connect (void *cls,
568                      const struct GNUNET_PeerIdentity *peer_identity)
569 {
570   struct FriendInfo *friend;
571
572   /* Check for connect to self message */
573   if (0 == memcmp (&my_identity,
574                    peer_identity,
575                    sizeof (struct GNUNET_PeerIdentity)))
576     return;
577
578   /* If peer already exists in our friend_peermap, then exit. */
579   if (GNUNET_YES ==
580       GNUNET_CONTAINER_multipeermap_contains (friend_peermap,
581                                               peer_identity))
582   {
583     GNUNET_break (0);
584     return;
585   }
586
587   friend = GNUNET_new (struct FriendInfo);
588   friend->id = *peer_identity;
589
590   GNUNET_assert (GNUNET_OK ==
591                  GNUNET_CONTAINER_multipeermap_put (friend_peermap,
592                                                     peer_identity,
593                                                     friend,
594                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
595   /* do work? */
596 }
597
598
599 /**
600  * To be called on core init/fail.
601  *
602  * @param cls service closure
603  * @param identity the public identity of this peer
604  */
605 static void
606 core_init (void *cls,
607            const struct GNUNET_PeerIdentity *identity)
608 {
609   my_identity = *identity;
610 }
611
612
613 /**
614  * Handle a `struct FingerSetupMessage` from a GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP
615  * message.
616  *
617  * @param cls closure (NULL)
618  * @param peer sender identity
619  * @param message the setup message
620  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
621  */
622 static int
623 handle_dht_p2p_finger_setup (void *cls,
624                              const struct GNUNET_PeerIdentity *peer,
625                              const struct GNUNET_MessageHeader *message)
626 {
627   const struct FingerSetupMessage *fsm;
628
629   fsm = (const struct FingerSetupMessage *) message;
630
631   /*
632    * Steps :
633    *  1 check if the hops_taken is < to log(honest node)
634    *  1.a.1 if true : increments the hops_taken
635    *  1.a.2 send the same structure
636    *  1.b if false : drop the message
637    */
638
639   return GNUNET_OK;
640 }
641
642 /**
643  * Handle a `struct FingerSetupResponseMessage` from a GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP_RESPONSE
644  * message.
645  *
646  * @param cls closure (NULL)
647  * @param peer sender identity
648  * @param message the setup response message
649  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
650  */
651 static int
652 handle_dht_p2p_finger_setup_response (void *cls,
653                              const struct GNUNET_PeerIdentity *peer,
654                              const struct GNUNET_MessageHeader *message)
655 {
656   const struct FingerSetupResponseMessage *fsrm;
657
658   fsm = (const struct FingerSetupResponseMessage *) message;
659
660   /*
661    * Steps :
662    *  1 check if we are the correct layer
663    *  1.a if true : add the return value in the db structure
664    *  1.b if true : do nothing
665    */
666
667   return GNUNET_OK;
668 }
669
670
671 /**
672  * Handle a `struct FingerDestroyMessage`.
673  *
674  * @param cls closure (NULL)
675  * @param peer sender identity
676  * @param message the finger destroy message
677  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
678  */
679 static int
680 handle_dht_p2p_finger_destroy (void *cls,
681                              const struct GNUNET_PeerIdentity *peer,
682                              const struct GNUNET_MessageHeader *message)
683 {
684   const struct FingerDestroyMessage *fdm;
685
686   fdm = (const struct FingerDestroyMessage *) message;
687
688   /*
689    * Steps :
690    *  1 check if message comme from a trail
691    *  1.a.1 if true: send the destroy message to the rest trail
692    *  1.a.2 clean the trail structure
693    *  1.a.3 did i have to remove the trail and ID from the db structure?
694    *  1.b if false: do nothing
695    */
696
697   return GNUNET_OK;
698 }
699
700 /**
701  * Handle a `struct FingerRouteMessage`.
702  *
703  * @param cls closure (NULL)
704  * @param peer sender identity
705  * @param message the finger route message
706  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
707  */
708 static int
709 handle_dht_p2p_finger_route (void *cls,
710                              const struct GNUNET_PeerIdentity *peer,
711                              const struct GNUNET_MessageHeader *message)
712 {
713   const struct FingerRouteMessage *frm;
714
715   frm = (const struct FingerRouteMessage *) message;
716   /* FIXME: check the size of the message */
717
718   /*
719    * steps :
720    *  1 find the good trail
721    *  2 send the finger route message
722    */
723
724   return GNUNET_OK;
725 }
726
727 /**
728  * Handle a `struct FingerSetupMessage` from a GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FIND
729  * message.
730  *
731  * @param cls closure (NULL)
732  * @param peer sender identity
733  * @param message the finger setup message
734  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
735  */
736 static int
737 handle_dht_p2p_neighbour_find (void *cls,
738                              const struct GNUNET_PeerIdentity *peer,
739                              const struct GNUNET_MessageHeader *message)
740 {
741   const struct FingerSetupMessage *fsm;
742
743   fsm = (const struct FingerSetupMessage *) message;
744
745   return GNUNET_OK;
746 }
747
748 /**
749  * Handle a `struct FingerSetupResponseMessage` from a GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FIND
750  * message.
751  *
752  * @param cls closure (NULL)
753  * @param peer sender identity
754  * @param message the finger setup response message
755  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
756  */
757 static int
758 handle_dht_p2p_neighbour_found (void *cls,
759                              const struct GNUNET_PeerIdentity *peer,
760                              const struct GNUNET_MessageHeader *message)
761 {
762   const struct FingerSetupResponseMessage *fsrm;
763
764   fsrm = (const struct FingerSetupResponseMessage *) message;
765
766   return GNUNET_OK;
767 }
768
769 /**
770  * Handle a `struct PeerGetMessage`.
771  *
772  * @param cls closure (NULL)
773  * @param peer sender identity
774  * @param message the peer get message
775  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
776  */
777 static int
778 handle_dht_p2p_peer_get (void *cls,
779                              const struct GNUNET_PeerIdentity *peer,
780                              const struct GNUNET_MessageHeader *message)
781 {
782   const struct PeerGetMessage *pgm;
783
784   pgm = (const struct PeerGetMessage *) message;
785
786      /*
787     * steps :
788     *   1 extract the result
789     *   2 save the peer
790     *   3 send it using the good trail
791     *
792     * What do i do when i don't have the key/value?
793     */
794
795   return GNUNET_OK;
796 }
797
798 /**
799  * Handle a `struct PeerGetResultMessage`.
800  *
801  * @param cls closure (NULL)
802  * @param peer sender identity
803  * @param message the peer get result message
804  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
805  */
806 static int
807 handle_dht_p2p_peer_get_result (void *cls,
808                              const struct GNUNET_PeerIdentity *peer,
809                              const struct GNUNET_MessageHeader *message)
810 {
811   const struct PeerGetResultMessage *pgrm;
812
813   pgrm = (const struct PeerGetResultMessage *) message;
814
815   /*
816    * steps :
817    *   1 extract the result
818    *   2 create a peerGetResult struct
819    *   3 send it using the good trail
820    *
821    * What do i do when i don't have the key/value?
822    */
823
824   return GNUNET_OK;
825 }
826
827 /**
828  * Handle a `struct PeerPutMessage`.
829  *
830  * @param cls closure (NULL)
831  * @param peer sender identity
832  * @param message the peer put message
833  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
834  */
835 static int
836 handle_dht_p2p_peer_put (void *cls,
837                              const struct GNUNET_PeerIdentity *peer,
838                              const struct GNUNET_MessageHeader *message)
839 {
840   const struct PeerGetResultMessage *pgrm;
841
842   pgrm = (const struct PeerGetResultMessage *) message;
843
844   /*
845    * steps :
846    * 1 check the size of the message
847    * 2 use the API to add the value in the "database". Check on the xdht file, how to do it.
848    * 3 Did i a have to return a notification or did i have to return GNUNET_[OK|SYSERR]?
849    */
850   return GNUNET_OK;
851 }
852
853 /**
854  * Initialize neighbours subsystem.
855  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
856  */
857 int
858 GDS_NEIGHBOURS_init (void)
859 {
860   static const struct GNUNET_CORE_MessageHandler core_handlers[] = {
861     { &handle_dht_p2p_finger_setup,
862       GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP,
863       sizeof (struct FingerSetupMessage) },
864     { &handle_dht_p2p_finger_setup_response,
865       GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP_RESPONSE,
866       sizeof (struct FingerSetupResponseMessage) },
867     { &handle_dht_p2p_finger_destroy,
868       GNUNET_MESSAGE_TYPE_WDHT_FINGER_DESTROY,
869       sizeof (struct FingerDestroyMessage) },
870     { &handle_dht_p2p_finger_route,
871       GNUNET_MESSAGE_TYPE_WDHT_FINGER_ROUTE,
872       0},
873     { &handle_dht_p2p_neighbour_find,
874       GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FIND,
875       sizeof (struct FingerSetupMessage) },
876     { &handle_dht_p2p_neighbour_found,
877       GNUNET_MESSAGE_TYPE_WDHT_NEIGHBOUR_FOUND,
878       sizeof (struct FingerSetupResponseMessage) },
879     { &handle_dht_p2p_peer_get,
880       GNUNET_MESSAGE_TYPE_WDHT_GET,
881       sizeof (struct PeerGetMessage) },
882     { &handle_dht_p2p_peer_get_result,
883       GNUNET_MESSAGE_TYPE_WDHT_GET_RESULT,
884       0},
885     { &handle_dht_p2p_peer_put,
886       GNUNET_MESSAGE_TYPE_WDHT_PUT,
887       0},
888     {NULL, 0, 0}
889   };
890
891   core_api =
892     GNUNET_CORE_connect (GDS_cfg, NULL,
893                          &core_init,
894                          &handle_core_connect,
895                          &handle_core_disconnect,
896                          NULL, GNUNET_NO,
897                          NULL, GNUNET_NO,
898                          core_handlers);
899
900   if (NULL == core_api)
901     return GNUNET_SYSERR;
902
903   fingers_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
904   successors_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
905
906   return GNUNET_OK;
907 }
908
909
910 /**
911  * Shutdown neighbours subsystem.
912  */
913 void
914 GDS_NEIGHBOURS_done (void)
915 {
916   if (NULL == core_api)
917     return;
918   GNUNET_CORE_disconnect (core_api);
919   core_api = NULL;
920
921   GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
922   GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
923   friend_peermap = NULL;
924 }
925
926
927 /**
928  * Get my identity
929  *
930  * @return my identity
931  */
932 struct GNUNET_PeerIdentity
933 GDS_NEIGHBOURS_get_my_id (void)
934 {
935   return my_identity;
936 }
937
938 /* end of gnunet-service-wdht_neighbours.c */