Adding a function pick_random_friend ()
[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  * @file dht/gnunet-service-wdht_neighbours.c
22  * @brief GNUnet DHT service's finger and friend table management code
23  * @author Supriti Singh
24  */
25 #include "platform.h"
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"
41 #include "gnunet-service-wdht_nse.h"
42 #include <fenv.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include "dht.h"
46
47 #define DEBUG(...)                                           \
48   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
49
50 /**
51  * Trail timeout. After what time do trails always die?
52  */
53 #define TRAIL_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 42)
54
55 /**
56  * Random walk delay. How often do we walk the overlay?
57  */
58 #define RANDOM_WALK_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 42)
59
60 /**
61  * The number of layered ID to use.
62  */
63 #define NUMBER_LAYERED_ID 8
64
65 /**
66  * The number of random walk to launch at the beginning of the initialization
67  */
68 /* FIXME: find a better value */
69 #define NUMBER_RANDOM_WALK 20
70
71
72 /******************* The db structure and related functions *******************/
73
74 /**
75  * Entry in #friends_peermap.
76  */
77 struct FriendInfo;
78
79
80 /**
81  * Information we keep per trail.
82  */
83 struct Trail
84 {
85
86   /**
87    * MDLL entry in the list of all trails with the same predecessor.
88    */
89   struct Trail *prev_succ;
90
91   /**
92    * MDLL entry in the list of all trails with the same predecessor.
93    */
94   struct Trail *next_succ;
95
96   /**
97    * MDLL entry in the list of all trails with the same predecessor.
98    */
99   struct Trail *prev_pred;
100
101   /**
102    * MDLL entry in the list of all trails with the same predecessor.
103    */
104   struct Trail *next_pred;
105
106   /**
107    * Our predecessor in the trail, NULL if we are initiator (?).
108    */
109   struct FriendInfo *pred;
110
111   /**
112    * Our successor in the trail, NULL if we are the last peer.
113    */
114   struct FriendInfo *succ;
115
116   /**
117    * Identifier of the trail with the predecessor.
118    */
119   struct GNUNET_HashCode pred_id;
120
121   /**
122    * Identifier of the trail with the successor.
123    */
124   struct GNUNET_HashCode succ_id;
125
126   /**
127    * When does this trail expire.
128    */
129   struct GNUNET_TIME_Absolute expiration_time;
130
131   /**
132    * Location of this trail in the heap.
133    */
134   struct GNUNET_CONTAINER_HeapNode *hn;
135
136   /**
137    * If this peer started the to create a Finger (and thus @e pred is
138    * NULL), this is the Finger we are trying to intialize.
139    */
140   struct Finger **finger;
141
142 };
143
144
145 /**
146  *  Entry in #friends_peermap.
147  */
148 struct FriendInfo
149 {
150   /**
151    * Friend Identity
152    */
153   struct GNUNET_PeerIdentity id;
154
155   /**
156    *
157    */
158   struct Trail *pred_head;
159
160   /**
161    *
162    */
163   struct Trail *pred_tail;
164
165   /**
166    *
167    */
168   struct Trail *succ_head;
169
170   /**
171    *
172    */
173   struct Trail *succ_tail;
174
175   /**
176    * Core handle for sending messages to this friend.
177    */
178   struct GNUNET_MQ_Handle *mq;
179
180 };
181
182
183 /**
184  *
185  */
186 struct FingerTable;
187
188
189 /**
190  *
191  */
192 struct Finger
193 {
194   /**
195    *
196    */
197   struct Trail *trail;
198
199   /**
200    *
201    */
202   struct FingerTable *ft;
203
204   /**
205    *
206    */
207   struct GNUNET_HashCode destination;
208
209   /**
210    * #GNUNET_YES if a response has been received. Otherwise #GNUNET_NO.
211    */
212   int valid;
213 };
214
215
216 struct FingerTable
217 {
218   /**
219    * Array of our fingers, unsorted.
220    */
221   struct Finger **fingers;
222
223   /**
224    * Array of sorted fingers (sorted by destination, valid fingers first).
225    */
226   struct Finger **sorted_fingers;
227
228   /**
229    * Size of the finger array.
230    */
231   unsigned int finger_array_size;
232
233   /**
234    * Number of valid entries in @e sorted_fingers (contiguous from offset 0)
235    */
236   unsigned int number_valid_fingers;
237
238   /**
239    * Which offset in @e fingers will we redo next.
240    */
241   unsigned int walk_offset;
242
243   /**
244    * Is the finger array sorted?
245    */
246   int is_sorted;
247
248 };
249
250
251 /***********************  end of the db structure part  ***********************/
252
253
254 GNUNET_NETWORK_STRUCT_BEGIN
255
256 /**
257  * Setup a finger using the underlay topology ("social network").
258  */
259 struct RandomWalkMessage
260 {
261   /**
262    * Type: #GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK
263    */
264   struct GNUNET_MessageHeader header;
265
266   /**
267    * Number of hops this message has taken so far, we stop at
268    * log(NSE), in NBO.
269    */
270   uint16_t hops_taken GNUNET_PACKED;
271
272   /**
273    * Layer for the request, in NBO.
274    */
275   uint16_t layer GNUNET_PACKED;
276
277   /**
278    * Unique (random) identifier this peer will use to
279    * identify the trail (in future messages).
280    */
281   struct GNUNET_HashCode trail_id;
282
283 };
284
285 /**
286  * Response to a `struct RandomWalkMessage`.
287  */
288 struct RandomWalkResponseMessage
289 {
290   /**
291    * Type: #GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK_RESPONSE
292    */
293   struct GNUNET_MessageHeader header;
294
295   /**
296    * Zero, for alignment.
297    */
298   uint32_t reserved GNUNET_PACKED;
299
300   /**
301    * Unique (random) identifier from the
302    * `struct RandomWalkMessage`.
303    */
304   struct GNUNET_HashCode trail_id;
305
306   /**
307    * Random location in the respective layer where the
308    * random path of the finger setup terminated.
309    */
310   struct GNUNET_HashCode location;
311
312 };
313
314 /**
315  * Response to an event that causes a trail to die.
316  */
317 struct TrailDestroyMessage
318 {
319   /**
320    * Type: #GNUNET_MESSAGE_TYPE_WDHT_TRAIL_DESTROY
321    */
322   struct GNUNET_MessageHeader header;
323
324   /**
325    * Zero, for alignment.
326    */
327   uint32_t reserved GNUNET_PACKED;
328
329   /**
330    * Unique (random) identifier this peer will use to
331    * identify the finger (in future messages).
332    */
333   struct GNUNET_HashCode trail_id;
334
335 };
336
337
338 /**
339  * Send a message along a trail.
340  */
341 struct FindSuccessorMessage
342 {
343   /**
344    * Type: #GNUNET_MESSAGE_TYPE_WDHT_FIND_SUCCESSOR
345    */
346   struct GNUNET_MessageHeader header;
347
348   /**
349    * Zero, for alignment.
350    */
351   uint32_t reserved GNUNET_PACKED;
352
353   /**
354    * Unique (random) identifier this peer will use to
355    * identify the finger (in future messages).
356    */
357   struct GNUNET_HashCode trail_id;
358
359   /**
360    * Key for which we would like close values returned.
361    * identify the finger (in future messages).
362    */
363   struct GNUNET_HashCode key;
364
365 };
366
367
368 /**
369  * Send a message along a trail.
370  */
371 struct TrailRouteMessage
372 {
373   /**
374    * Type: #GNUNET_MESSAGE_TYPE_WDHT_TRAIL_ROUTE
375    */
376   struct GNUNET_MessageHeader header;
377
378   /**
379    * #GNUNET_YES if the path should be recorded, #GNUNET_NO if not; in NBO.
380    */
381   uint16_t record_path GNUNET_PACKED;
382
383   /**
384    * Length of the recorded trail, 0 if @e record_path is #GNUNET_NO; in NBO.
385    */
386   uint16_t path_length GNUNET_PACKED;
387
388   /**
389    * Unique (random) identifier this peer will use to
390    * identify the finger (in future messages).
391    */
392   struct GNUNET_HashCode trail_id;
393
394   /**
395    * Path the message has taken so far (excluding sender).
396    */
397   /* struct GNUNET_PeerIdentity path[path_length]; */
398
399   /* followed by payload (another `struct GNUNET_MessageHeader`) to
400      send along the trail */
401 };
402
403
404 /**
405  * P2P PUT message
406  */
407 struct PeerPutMessage
408 {
409   /**
410    * Type: #GNUNET_MESSAGE_TYPE_WDHT_PUT
411    */
412   struct GNUNET_MessageHeader header;
413
414   /**
415    * Processing options
416    */
417   uint32_t options GNUNET_PACKED;
418
419   /**
420    * Content type.
421    */
422   uint32_t block_type GNUNET_PACKED;
423
424   /**
425    * Hop count
426    */
427   uint32_t hop_count GNUNET_PACKED;
428
429   /**
430    * Replication level for this message
431    * In the current implementation, this value is not used.
432    */
433   uint32_t desired_replication_level GNUNET_PACKED;
434
435   /**
436    * Length of the PUT path that follows (if tracked).
437    */
438   uint32_t put_path_length GNUNET_PACKED;
439
440   /**
441    * When does the content expire?
442    */
443   struct GNUNET_TIME_AbsoluteNBO expiration_time;
444
445   /**
446    * The key to store the value under.
447    */
448   struct GNUNET_HashCode key GNUNET_PACKED;
449
450   /* put path (if tracked) */
451
452   /* Payload */
453
454 };
455
456 /**
457  * P2P GET message
458  */
459 struct PeerGetMessage
460 {
461   /**
462    * Type: #GNUNET_MESSAGE_TYPE_WDHT_GET
463    */
464   struct GNUNET_MessageHeader header;
465
466   /**
467    * Processing options
468    */
469   uint32_t options GNUNET_PACKED;
470
471   /**
472    * Desired content type.
473    */
474   uint32_t block_type GNUNET_PACKED;
475
476   /**
477    * Hop count
478    */
479   uint32_t hop_count GNUNET_PACKED;
480
481   /**
482    * Desired replication level for this request.
483    * In the current implementation, this value is not used.
484    */
485   uint32_t desired_replication_level GNUNET_PACKED;
486
487   /**
488    * Total number of peers in get path.
489    */
490   unsigned int get_path_length;
491
492   /**
493    * The key we are looking for.
494    */
495   struct GNUNET_HashCode key;
496
497   /* Get path. */
498   /* struct GNUNET_PeerIdentity[]*/
499 };
500
501
502 /**
503  * P2P Result message
504  */
505 struct PeerGetResultMessage
506 {
507   /**
508    * Type: #GNUNET_MESSAGE_TYPE_WDHT_GET_RESULT
509    */
510   struct GNUNET_MessageHeader header;
511
512   /**
513    * The type for the data.
514    */
515   uint32_t type GNUNET_PACKED;
516
517   /**
518    * Number of peers recorded in the outgoing path from source to the
519    * stored location of this message.
520    */
521   uint32_t put_path_length GNUNET_PACKED;
522
523   /**
524    * Length of the GET path that follows (if tracked).
525    */
526   uint32_t get_path_length GNUNET_PACKED;
527
528   /**
529    * Peer which queried for get and should get the result.
530    */
531   struct GNUNET_PeerIdentity querying_peer;
532
533   /**
534    * When does the content expire?
535    */
536   struct GNUNET_TIME_Absolute expiration_time;
537
538   /**
539    * The key of the corresponding GET request.
540    */
541   struct GNUNET_HashCode key;
542
543   /* put path (if tracked) */
544
545   /* get path (if tracked) */
546
547   /* Payload */
548
549 };
550
551 GNUNET_NETWORK_STRUCT_END
552
553
554 /**
555  * Contains all the layered IDs of this peer.
556  */
557 struct GNUNET_PeerIdentity layered_id[NUMBER_LAYERED_ID];
558
559 /**
560  * Task to timeout trails that have expired.
561  */
562 static struct GNUNET_SCHEDULER_Task *trail_timeout_task;
563
564 /**
565  * Task to perform random walks.
566  */
567 static struct GNUNET_SCHEDULER_Task *random_walk_task;
568
569 /**
570  * Identity of this peer.
571  */
572 static struct GNUNET_PeerIdentity my_identity;
573
574 /**
575  * Peer map of all the friends of a peer
576  */
577 static struct GNUNET_CONTAINER_MultiPeerMap *friends_peermap;
578
579 /**
580  * Fingers per layer.
581  */
582 static struct FingerTable fingers[NUMBER_LAYERED_ID];
583
584 /**
585  * Tail map, mapping tail identifiers to `struct Trail`s
586  */
587 static struct GNUNET_CONTAINER_MultiHashMap *trail_map;
588
589 /**
590  * Tail heap, organizing trails by expiration time.
591  */
592 static struct GNUNET_CONTAINER_Heap *trail_heap;
593
594 /**
595  * Handle to CORE.
596  */
597 static struct GNUNET_CORE_Handle *core_api;
598
599
600 /**
601  * Handle the put request from the client.
602  *
603  * @param key Key for the content
604  * @param block_type Type of the block
605  * @param options Routing options
606  * @param desired_replication_level Desired replication count
607  * @param expiration_time When does the content expire
608  * @param data Content to store
609  * @param data_size Size of content @a data in bytes
610  */
611 void
612 GDS_NEIGHBOURS_handle_put (const struct GNUNET_HashCode *key,
613                            enum GNUNET_BLOCK_Type block_type,
614                            enum GNUNET_DHT_RouteOption options,
615                            uint32_t desired_replication_level,
616                            struct GNUNET_TIME_Absolute expiration_time,
617                            const void *data,
618                            size_t data_size)
619 {
620   GDS_DATACACHE_handle_put (expiration_time,
621                             key,
622                             0, NULL,
623                             0, NULL,
624                             block_type,
625                             data_size,
626                             data);
627   GDS_CLIENTS_process_put (options,
628                            block_type,
629                            0, 0,
630                            0, NULL,
631                            expiration_time,
632                            key,
633                            data,
634                            data_size);
635 }
636
637
638 /**
639  * Handle the get request from the client file. If I am destination do
640  * datacache put and return. Else find the target friend and forward message
641  * to it.
642  *
643  * @param key Key for the content
644  * @param block_type Type of the block
645  * @param options Routing options
646  * @param desired_replication_level Desired replication count
647  */
648 void
649 GDS_NEIGHBOURS_handle_get (const struct GNUNET_HashCode *key,
650                            enum GNUNET_BLOCK_Type block_type,
651                            enum GNUNET_DHT_RouteOption options,
652                            uint32_t desired_replication_level)
653 {
654   // find closest finger(s) on all layers
655   // use TrailRoute with PeerGetMessage embedded to contact peer
656 }
657
658
659 /**
660  * Delete a trail, it died (timeout, link failure, etc.).
661  *
662  * @param trail trail to delete from all data structures
663  * @param inform_pred should we notify the predecessor?
664  * @param inform_succ should we inform the successor?
665  */
666 static void
667 delete_trail (struct Trail *trail,
668               int inform_pred,
669               int inform_succ)
670 {
671   struct FriendInfo *friend;
672   struct GNUNET_MQ_Envelope *env;
673   struct TrailDestroyMessage *tdm;
674   struct Finger *finger;
675
676   friend = trail->pred;
677   if (NULL != friend)
678   {
679     if (GNUNET_YES == inform_pred)
680     {
681       env = GNUNET_MQ_msg (tdm,
682                            GNUNET_MESSAGE_TYPE_WDHT_TRAIL_DESTROY);
683       tdm->trail_id = trail->pred_id;
684       GNUNET_MQ_send (friend->mq,
685                       env);
686     }
687     GNUNET_CONTAINER_MDLL_remove (pred,
688                                   friend->pred_head,
689                                   friend->pred_tail,
690                                   trail);
691   }
692   friend = trail->succ;
693   if (NULL != friend)
694   {
695     if (GNUNET_YES == inform_succ)
696     {
697       env = GNUNET_MQ_msg (tdm,
698                            GNUNET_MESSAGE_TYPE_WDHT_TRAIL_DESTROY);
699       tdm->trail_id = trail->pred_id;
700       GNUNET_MQ_send (friend->mq,
701                       env);
702     }
703     GNUNET_CONTAINER_MDLL_remove (succ,
704                                   friend->pred_head,
705                                   friend->pred_tail,
706                                   trail);
707   }
708   GNUNET_break (trail ==
709                 GNUNET_CONTAINER_heap_remove_node (trail->hn));
710   finger = *trail->finger;
711   if (NULL != finger)
712   {
713     *trail->finger = NULL;
714     GNUNET_free (finger);
715   }
716   GNUNET_free (trail);
717 }
718
719
720 /**
721  * Blah.
722  */
723 static void
724 forward_message_on_trail (struct FriendInfo *next_target,
725                           const struct GNUNET_HashCode *trail_id,
726                           int have_path,
727                           const struct GNUNET_PeerIdentity *predecessor,
728                           const struct GNUNET_PeerIdentity *path,
729                           uint16_t path_length,
730                           const struct GNUNET_MessageHeader *payload)
731 {
732   struct GNUNET_MQ_Envelope *env;
733   struct TrailRouteMessage *trm;
734   struct GNUNET_PeerIdentity *new_path;
735   unsigned int plen;
736   uint16_t payload_len;
737
738   payload_len = ntohs (payload->size);
739   if (have_path)
740   {
741     plen = path_length + 1;
742     if (plen >= (GNUNET_SERVER_MAX_MESSAGE_SIZE
743                  - payload_len
744                  - sizeof (struct TrailRouteMessage))
745         / sizeof (struct GNUNET_PeerIdentity))
746     {
747       /* Should really not have paths this long... */
748       GNUNET_break_op (0);
749       plen = 0;
750       have_path = 0;
751     }
752   }
753   else
754   {
755     GNUNET_break_op (0 == path_length);
756     path_length = 0;
757     plen = 0;
758   }
759   env = GNUNET_MQ_msg_extra (trm,
760                              payload_len +
761                              plen * sizeof (struct GNUNET_PeerIdentity),
762                              GNUNET_MESSAGE_TYPE_WDHT_TRAIL_ROUTE);
763   trm->record_path = htons (have_path);
764   trm->path_length = htons (plen);
765   trm->trail_id = *trail_id;
766   new_path = (struct GNUNET_PeerIdentity *) &trm[1];
767   if (have_path)
768   {
769     memcpy (new_path,
770             path,
771             path_length * sizeof (struct GNUNET_PeerIdentity));
772     new_path[path_length] = *predecessor;
773   }
774   memcpy (&new_path[plen],
775           payload,
776           payload_len);
777   GNUNET_MQ_send (next_target->mq,
778                   env);
779 }
780
781
782 /**
783  * Send the get result to requesting client.
784  *
785  * @param trail_id trail identifying where to send the result to, NULL for us
786  * @param key Key of the requested data.
787  * @param type Block type
788  * @param put_path_length Number of peers in @a put_path
789  * @param put_path Path taken to put the data at its stored location.
790  * @param expiration When will this result expire?
791  * @param data Payload to store
792  * @param data_size Size of the @a data
793  *
794  * FIXME: also pass options, so we know to record paths or not...
795  */
796 void
797 GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *trail_id,
798                                 const struct GNUNET_HashCode *key,
799                                 enum GNUNET_BLOCK_Type type,
800                                 unsigned int put_path_length,
801                                 const struct GNUNET_PeerIdentity *put_path,
802                                 struct GNUNET_TIME_Absolute expiration,
803                                 const void *data,
804                                 size_t data_size)
805 {
806   struct GNUNET_MessageHeader *payload;
807
808   payload = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader) + data_size);
809   payload->size = data_size;
810   payload->type = GNUNET_MESSAGE_TYPE_WDHT_GET_RESULT;
811
812   forward_message_on_trail (NULL /* FIXME: put something right */,
813                             trail_id,
814                             0 /* FIXME: put something right */,
815                             &my_identity,
816                             put_path,
817                             put_path_length,
818                             payload);
819 }
820
821
822 /**
823  * Method called whenever a peer disconnects.
824  *
825  * @param cls closure
826  * @param peer peer identity this notification is about
827  */
828 static void
829 handle_core_disconnect (void *cls,
830                         const struct GNUNET_PeerIdentity *peer)
831 {
832   struct FriendInfo *remove_friend;
833   struct Trail *t;
834
835   /* If disconnected to own identity, then return. */
836   if (0 == memcmp (&my_identity,
837                    peer,
838                    sizeof (struct GNUNET_PeerIdentity)))
839     return;
840
841   if (NULL == (remove_friend =
842                GNUNET_CONTAINER_multipeermap_get (friends_peermap,
843                                                   peer)))
844   {
845     GNUNET_break (0);
846     return;
847   }
848
849   GNUNET_assert (GNUNET_YES ==
850                  GNUNET_CONTAINER_multipeermap_remove (friends_peermap,
851                                                        peer,
852                                                        remove_friend));
853   while (NULL != (t = remove_friend->succ_head))
854     delete_trail (t,
855                   GNUNET_YES,
856                   GNUNET_NO);
857   while (NULL != (t = remove_friend->pred_head))
858     delete_trail (t,
859                   GNUNET_NO,
860                   GNUNET_YES);
861   GNUNET_MQ_destroy (remove_friend->mq);
862   GNUNET_free (remove_friend);
863   if (0 ==
864       GNUNET_CONTAINER_multipeermap_size (friends_peermap))
865   {
866     GNUNET_SCHEDULER_cancel (random_walk_task);
867     random_walk_task = NULL;
868   }
869 }
870
871
872 /**
873  * Pick random friend from friends for random walk.
874  */
875 static struct FriendInfo *
876 pick_random_friend ()
877 {
878   GNUNET_CONTAINER_PeerMapIterator *it;
879   if (0 != GNUNET_CONTAINER_multipeermap_get_random (friends_peermap,
880                                                      *it,
881                                                      NULL) ){
882     static struct FriendInfo **friend;
883     struct GNUNET_PeerIdentity *key;
884
885     /* FIXME: i am not sure of this one */
886     key = NULL;
887
888     if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (it,
889                                                                   key,
890                                                                   (void *) friend))
891     {
892       return *friend;
893     }
894   }
895   return NULL;
896 }
897
898
899 /**
900  * One of our trails might have timed out, check and
901  * possibly initiate cleanup.
902  *
903  * @param cls NULL
904  * @param tc unused
905  */
906 static void
907 trail_timeout_callback (void *cls,
908                         const struct GNUNET_SCHEDULER_TaskContext *tc)
909 {
910   struct Trail *trail;
911   struct GNUNET_TIME_Relative left;
912
913   trail_timeout_task = NULL;
914   while (NULL != (trail = GNUNET_CONTAINER_heap_peek (trail_heap)))
915   {
916     left = GNUNET_TIME_absolute_get_remaining (trail->expiration_time);
917     if (0 != left.rel_value_us)
918       break;
919     delete_trail (trail,
920                   GNUNET_YES,
921                   GNUNET_YES);
922   }
923   if (NULL != trail)
924     trail_timeout_task = GNUNET_SCHEDULER_add_delayed (left,
925                                                        &trail_timeout_callback,
926                                                        NULL);
927 }
928
929
930 /**
931  * Initiate a random walk.
932  *
933  * @param cls NULL
934  * @param tc unused
935  */
936 static void
937 do_random_walk (void *cls,
938                 const struct GNUNET_SCHEDULER_TaskContext *tc)
939 {
940   static unsigned int walk_layer;
941   struct FriendInfo *friend;
942   struct GNUNET_MQ_Envelope *env;
943   struct RandomWalkMessage *rwm;
944   struct FingerTable *ft;
945   struct Finger *finger;
946   struct Trail *trail;
947
948   random_walk_task = NULL;
949   friend = pick_random_friend ();
950
951   trail = GNUNET_new (struct Trail);
952   /* We create the random walk so, no predecessor */
953   trail->succ = friend;
954   GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE,
955                                     &trail->succ_id);
956   if (GNUNET_OK !=
957       GNUNET_CONTAINER_multihashmap_put (trail_map,
958                                          &trail->succ_id,
959                                          trail,
960                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
961   {
962     GNUNET_break (0);
963     GNUNET_free (trail);
964     return;
965   }
966   GNUNET_CONTAINER_MDLL_insert (succ,
967                                 friend->succ_head,
968                                 friend->succ_tail,
969                                 trail);
970   trail->expiration_time = GNUNET_TIME_relative_to_absolute (TRAIL_TIMEOUT);
971   trail->hn = GNUNET_CONTAINER_heap_insert (trail_heap,
972                                             trail,
973                                             trail->expiration_time.abs_value_us);
974   if (NULL == trail_timeout_task)
975     trail_timeout_task = GNUNET_SCHEDULER_add_delayed (TRAIL_TIMEOUT,
976                                                        &trail_timeout_callback,
977                                                        NULL);
978   env = GNUNET_MQ_msg (rwm,
979                        GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK);
980   rwm->hops_taken = htonl (0);
981   rwm->trail_id = trail->succ_id;
982   GNUNET_MQ_send (friend->mq,
983                   env);
984   /* clean up 'old' entry (implicitly via trail cleanup) */
985   ft = &fingers[walk_layer];
986
987   if ( (NULL != ft->fingers) &&
988        (NULL != (finger = ft->fingers[ft->walk_offset])) )
989     delete_trail (finger->trail,
990                   GNUNET_NO,
991                   GNUNET_YES);
992   if (ft->finger_array_size < 42)
993   {
994     // FIXME: must have finger array of the right size here,
995     // FIXME: growing / shrinking are tricky -- with pointers
996     // from Trails!!!
997   }
998
999   GNUNET_assert (NULL == ft->fingers[ft->walk_offset]);
1000
1001   finger = GNUNET_new (struct Finger);
1002   finger->trail = trail;
1003   trail->finger = &ft->fingers[ft->walk_offset];
1004   finger->ft = ft;
1005   ft->fingers[ft->walk_offset] = finger;
1006   ft->is_sorted = GNUNET_NO;
1007   ft->walk_offset = (ft->walk_offset + 1) % ft->finger_array_size;
1008
1009   walk_layer = (walk_layer + 1) % NUMBER_LAYERED_ID;
1010   random_walk_task = GNUNET_SCHEDULER_add_delayed (RANDOM_WALK_DELAY,
1011                                                    &do_random_walk,
1012                                                    NULL);
1013 }
1014
1015
1016 /**
1017  * Method called whenever a peer connects.
1018  *
1019  * @param cls closure
1020  * @param peer_identity peer identity this notification is about
1021  */
1022 static void
1023 handle_core_connect (void *cls,
1024                      const struct GNUNET_PeerIdentity *peer_identity)
1025 {
1026   struct FriendInfo *friend;
1027
1028   /* Check for connect to self message */
1029   if (0 == memcmp (&my_identity,
1030                    peer_identity,
1031                    sizeof (struct GNUNET_PeerIdentity)))
1032     return;
1033
1034   /* If peer already exists in our friend_peermap, then exit. */
1035   if (GNUNET_YES ==
1036       GNUNET_CONTAINER_multipeermap_contains (friends_peermap,
1037                                               peer_identity))
1038   {
1039     GNUNET_break (0);
1040     return;
1041   }
1042
1043   friend = GNUNET_new (struct FriendInfo);
1044   friend->id = *peer_identity;
1045   friend->mq = GNUNET_CORE_mq_create (core_api,
1046                                       peer_identity);
1047   GNUNET_assert (GNUNET_OK ==
1048                  GNUNET_CONTAINER_multipeermap_put (friends_peermap,
1049                                                     peer_identity,
1050                                                     friend,
1051                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1052   if (NULL == random_walk_task)
1053   {
1054     /* random walk needs to be started -- we have a first connection */
1055     random_walk_task = GNUNET_SCHEDULER_add_now (&do_random_walk,
1056                                                  NULL);
1057   }
1058 }
1059
1060
1061 /**
1062  * To be called on core init/fail.
1063  *
1064  * @param cls service closure
1065  * @param identity the public identity of this peer
1066  */
1067 static void
1068 core_init (void *cls,
1069            const struct GNUNET_PeerIdentity *identity)
1070 {
1071   my_identity = *identity;
1072 }
1073
1074
1075 /**
1076  * Handle a `struct RandomWalkMessage` from a
1077  * #GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK message.
1078  *
1079  * @param cls closure (NULL)
1080  * @param peer sender identity
1081  * @param message the setup message
1082  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1083  */
1084 static int
1085 handle_dht_p2p_random_walk (void *cls,
1086                             const struct GNUNET_PeerIdentity *peer,
1087                             const struct GNUNET_MessageHeader *message)
1088 {
1089   const struct RandomWalkMessage *m;
1090   struct Trail *t;
1091   struct FriendInfo *pred;
1092
1093   m = (const struct RandomWalkMessage *) message;
1094   pred = GNUNET_CONTAINER_multipeermap_get (friends_peermap,
1095                                             peer);
1096   t = GNUNET_new (struct Trail);
1097   t->pred_id = m->trail_id;
1098   t->pred = pred;
1099   if (GNUNET_OK !=
1100       GNUNET_CONTAINER_multihashmap_put (trail_map,
1101                                          &t->pred_id,
1102                                          t,
1103                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1104   {
1105     GNUNET_break_op (0);
1106     GNUNET_free (t);
1107     return GNUNET_SYSERR;
1108   }
1109   GNUNET_CONTAINER_MDLL_insert (pred,
1110                                 pred->pred_head,
1111                                 pred->pred_tail,
1112                                 t);
1113   t->expiration_time = GNUNET_TIME_relative_to_absolute (TRAIL_TIMEOUT);
1114   t->hn = GNUNET_CONTAINER_heap_insert (trail_heap,
1115                                         t,
1116                                         t->expiration_time.abs_value_us);
1117   if (NULL == trail_timeout_task)
1118     trail_timeout_task = GNUNET_SCHEDULER_add_delayed (TRAIL_TIMEOUT,
1119                                                        &trail_timeout_callback,
1120                                                        NULL);
1121
1122   if (ntohl (m->hops_taken) > GDS_NSE_get ())
1123   {
1124     /* We are the last hop, generate response */
1125     struct GNUNET_MQ_Envelope *env;
1126     struct RandomWalkResponseMessage *rwrm;
1127     uint16_t layer;
1128
1129     env = GNUNET_MQ_msg (rwrm,
1130                          GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK_RESPONSE);
1131     rwrm->reserved = htonl (0);
1132     rwrm->trail_id = m->trail_id;
1133     layer = ntohs (m->layer);
1134     if (0 == layer)
1135       (void) GDS_DATACACHE_get_random_key (&rwrm->location);
1136     else
1137     {
1138       struct FingerTable *ft;
1139
1140       if (layer > NUMBER_LAYERED_ID)
1141       {
1142         GNUNET_break_op (0);
1143         // FIXME: clean up 't'...
1144         return GNUNET_SYSERR;
1145       }
1146       ft = &fingers[layer-1];
1147       if (0 == ft->number_valid_fingers)
1148       {
1149         GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE,
1150                                           &rwrm->location);
1151       }
1152       else
1153       {
1154         struct Finger *f;
1155
1156         f = ft->fingers[GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
1157                                                   ft->number_valid_fingers)];
1158         rwrm->location = f->destination;
1159       }
1160     }
1161     GNUNET_MQ_send (pred->mq,
1162                     env);
1163   }
1164   else
1165   {
1166     struct GNUNET_MQ_Envelope *env;
1167     struct RandomWalkMessage *rwm;
1168     struct FriendInfo *succ;
1169
1170     /* extend the trail by another random hop */
1171     succ = pick_random_friend ();
1172     GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE,
1173                                       &t->succ_id);
1174     t->succ = succ;
1175     if (GNUNET_OK !=
1176         GNUNET_CONTAINER_multihashmap_put (trail_map,
1177                                            &t->succ_id,
1178                                            t,
1179                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1180     {
1181       GNUNET_break (0);
1182       GNUNET_CONTAINER_MDLL_remove (pred,
1183                                     pred->pred_head,
1184                                     pred->pred_tail,
1185                                     t);
1186       GNUNET_free (t);
1187       return GNUNET_OK;
1188     }
1189     GNUNET_CONTAINER_MDLL_insert (succ,
1190                                   succ->succ_head,
1191                                   succ->succ_tail,
1192                                   t);
1193     env = GNUNET_MQ_msg (rwm,
1194                          GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK);
1195     rwm->hops_taken = htons (1 + ntohs (m->hops_taken));
1196     rwm->layer = m->layer;
1197     rwm->trail_id = t->succ_id;
1198     GNUNET_MQ_send (succ->mq,
1199                     env);
1200   }
1201   return GNUNET_OK;
1202 }
1203
1204
1205 /**
1206  * Handle a `struct RandomWalkResponseMessage` from a GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK_RESPONSE
1207  * message.
1208  *
1209  * @param cls closure (NULL)
1210  * @param peer sender identity
1211  * @param message the setup response message
1212  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1213  */
1214 static int
1215 handle_dht_p2p_random_walk_response (void *cls,
1216                                      const struct GNUNET_PeerIdentity *peer,
1217                                      const struct GNUNET_MessageHeader *message)
1218 {
1219   const struct RandomWalkResponseMessage *rwrm;
1220
1221   rwrm = (const struct RandomWalkResponseMessage *) message;
1222   // 1) lookup trail => find Finger entry => fill in 'destination' and mark valid, move to end of sorted array,
1223   //mark unsorted, update links from 'trails'
1224   /*
1225    * Steps :
1226    *  1 check if we are the correct layer
1227    *  1.a if true : add the returned value (finger) in the db structure
1228    *  1.b if true : do nothing
1229    */
1230   /* FIXME: add the value in db structure 1.a */
1231
1232   return GNUNET_OK;
1233 }
1234
1235
1236 /**
1237  * Handle a `struct TrailDestroyMessage`.
1238  *
1239  * @param cls closure (NULL)
1240  * @param peer sender identity
1241  * @param message the finger destroy message
1242  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1243  */
1244 static int
1245 handle_dht_p2p_trail_destroy (void *cls,
1246                              const struct GNUNET_PeerIdentity *peer,
1247                              const struct GNUNET_MessageHeader *message)
1248 {
1249   const struct TrailDestroyMessage *tdm;
1250   struct Trail *trail;
1251
1252   tdm = (const struct TrailDestroyMessage *) message;
1253   trail = GNUNET_CONTAINER_multihashmap_get (trail_map,
1254                                              &tdm->trail_id);
1255   delete_trail (trail,
1256                 ( (NULL != trail->succ) &&
1257                   (0 == memcmp (peer,
1258                                 &trail->succ->id,
1259                                 sizeof (struct GNUNET_PeerIdentity))) ),
1260                 ( (NULL != trail->pred) &&
1261                   (0 == memcmp (peer,
1262                                 &trail->pred->id,
1263                                 sizeof (struct GNUNET_PeerIdentity))) ));
1264   return GNUNET_OK;
1265 }
1266
1267
1268 /**
1269  * Handle a `struct FindSuccessorMessage` from a #GNUNET_MESSAGE_TYPE_WDHT_SUCCESSOR_FIND
1270  * message.
1271  *
1272  * @param cls closure (NULL)
1273  * @param trail_id path to the originator
1274  * @param message the finger setup message
1275  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1276  */
1277 static int
1278 handle_dht_p2p_successor_find (void *cls,
1279                                const struct GNUNET_HashCode *trail_id,
1280                                const struct GNUNET_MessageHeader *message)
1281 {
1282   const struct FindSuccessorMessage *fsm;
1283
1284   fsm = (const struct FindSuccessorMessage *) message;
1285   // locate trail (for sending reply), if not exists, fail nicely.
1286   // otherwise, go to datacache and return 'top k' elements closest to 'key'
1287   // as "PUT" messages via the trail (need to extend DB API!)
1288 #if 0
1289   GDS_DATACACHE_get_successors (trail_id,
1290                                 key);
1291 #endif
1292   return GNUNET_OK;
1293 }
1294
1295
1296 /**
1297  * Handle a `struct PeerGetMessage`.
1298  *
1299  * @param cls closure (NULL)
1300  * @param trail_id path to the originator
1301  * @param message the peer get message
1302  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1303  */
1304 static int
1305 handle_dht_p2p_peer_get (void *cls,
1306                          const struct GNUNET_HashCode *trail_id,
1307                          const struct GNUNET_MessageHeader *message)
1308 {
1309   const struct PeerGetMessage *pgm;
1310
1311   // FIXME: note: never called like this, message embedded with trail route!
1312   pgm = (const struct PeerGetMessage *) message;
1313   // -> lookup in datacache (figure out way to remember trail!)
1314      /*
1315     * steps :
1316     *   1 extract the result
1317     *   2 save the peer
1318     *   3 send it using the good trail
1319     *
1320     * What do i do when i don't have the key/value?
1321     */
1322
1323   return GNUNET_OK;
1324 }
1325
1326
1327 /**
1328  * Handle a `struct PeerGetResultMessage`.
1329  *
1330  * @param cls closure (NULL)
1331  * @param trail_id path to the originator
1332  * @param message the peer get result message
1333  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1334  */
1335 static int
1336 handle_dht_p2p_peer_get_result (void *cls,
1337                                 const struct GNUNET_HashCode *trail_id,
1338                                 const struct GNUNET_MessageHeader *message)
1339 {
1340   const struct PeerGetResultMessage *pgrm;
1341
1342   pgrm = (const struct PeerGetResultMessage *) message;
1343   // pretty much: parse, & pass to client (there is some call for that...)
1344
1345 #if 0
1346   GDS_CLIENTS_process_get (options,
1347                            type,
1348                            0, 0,
1349                            path_length, path,
1350                            key);
1351   (void) GDS_DATACACHE_handle_get (trail_id,
1352                                    key,
1353                                    type,
1354                                    xquery,
1355                                    xquery_size,
1356                                    &reply_bf,
1357                                    reply_bf_mutator);
1358 #endif
1359   return GNUNET_OK;
1360 }
1361
1362
1363 /**
1364  * Handle a `struct PeerPutMessage`.
1365  *
1366  * @param cls closure (NULL)
1367  * @param trail_id path to the originator
1368  * @param message the peer put message
1369  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1370  */
1371 static int
1372 handle_dht_p2p_peer_put (void *cls,
1373                          const struct GNUNET_HashCode *trail_id,
1374                          const struct GNUNET_MessageHeader *message)
1375 {
1376   const struct PeerGetResultMessage *pgrm;
1377
1378   pgrm = (const struct PeerGetResultMessage *) message;
1379   // parse & store in datacache, this is in response to us asking for successors.
1380   /*
1381    * steps :
1382    * 1 check the size of the message
1383    * 2 use the API to add the value in the "database". Check on the xdht file, how to do it.
1384    * 3 Did i a have to return a notification or did i have to return GNUNET_[OK|SYSERR]?
1385    */
1386 #if 0
1387   GDS_DATACACHE_handle_put (expiration_time,
1388                             key,
1389                             path_length, path,
1390                             block_type,
1391                             data_size,
1392                             data);
1393   GDS_CLIENTS_process_put (options,
1394                            block_type,
1395                            0, 0,
1396                            path_length, path,
1397                            expiration_time,
1398                            key,
1399                            data,
1400                            data_size);
1401 #endif
1402   return GNUNET_OK;
1403 }
1404
1405
1406
1407
1408 /**
1409  * Handler for a message we received along some trail.
1410  *
1411  * @param cls closure
1412  * @param trail_id trail identifier
1413  * @param message the message we got
1414  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1415  */
1416 typedef int
1417 (*TrailHandlerCallback)(void *cls,
1418                         const struct GNUNET_HashCode *trail_id,
1419                         const struct GNUNET_MessageHeader *message);
1420
1421
1422 /**
1423  * Definition of a handler for a message received along some trail.
1424  */
1425 struct TrailHandler
1426 {
1427   /**
1428    * NULL for end-of-list.
1429    */
1430   TrailHandlerCallback callback;
1431
1432   /**
1433    * Closure for @e callback.
1434    */
1435   void *cls;
1436
1437   /**
1438    * Message type this handler addresses.
1439    */
1440   uint16_t message_type;
1441
1442   /**
1443    * Use 0 for variable-size.
1444    */
1445   uint16_t message_size;
1446 };
1447
1448
1449 /**
1450  * Handle a `struct TrailRouteMessage`.
1451  *
1452  * @param cls closure (NULL)
1453  * @param peer sender identity
1454  * @param message the finger destroy message
1455  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1456  */
1457 static int
1458 handle_dht_p2p_trail_route (void *cls,
1459                             const struct GNUNET_PeerIdentity *peer,
1460                             const struct GNUNET_MessageHeader *message)
1461 {
1462   static const struct TrailHandler handlers[] = {
1463     { &handle_dht_p2p_successor_find, NULL,
1464       GNUNET_MESSAGE_TYPE_WDHT_SUCCESSOR_FIND,
1465       sizeof (struct FindSuccessorMessage) },
1466     { NULL, NULL, 0, 0 }
1467   };
1468   unsigned int i;
1469   const struct TrailRouteMessage *trm;
1470   const struct GNUNET_PeerIdentity *path;
1471   uint16_t path_length;
1472   const struct GNUNET_MessageHeader *payload;
1473   const struct TrailHandler *th;
1474   struct Trail *trail;
1475   size_t msize;
1476
1477   /* Parse and check message is well-formed */
1478   msize = ntohs (message->size);
1479   if (msize < sizeof (struct TrailRouteMessage))
1480   {
1481     GNUNET_break_op (0);
1482     return GNUNET_YES;
1483   }
1484   trm = (const struct TrailRouteMessage *) message;
1485   path_length = ntohs (trm->path_length);
1486   if (msize < sizeof (struct TrailRouteMessage) +
1487       path_length * sizeof (struct GNUNET_PeerIdentity) +
1488       sizeof (struct GNUNET_MessageHeader) )
1489   {
1490     GNUNET_break_op (0);
1491     return GNUNET_YES;
1492   }
1493   path = (const struct GNUNET_PeerIdentity *) &trm[1];
1494   payload = (const struct GNUNET_MessageHeader *) &path[path_length];
1495   if (msize != (ntohs (payload->size) +
1496                 sizeof (struct TrailRouteMessage) +
1497                 path_length * sizeof (struct GNUNET_PeerIdentity)))
1498   {
1499     GNUNET_break_op (0);
1500     return GNUNET_YES;
1501   }
1502
1503   /* Is this message for us? */
1504   trail = GNUNET_CONTAINER_multihashmap_get (trail_map,
1505                                              &trm->trail_id);
1506   if ( (NULL != trail->pred) &&
1507        (0 == memcmp (peer,
1508                      &trail->pred->id,
1509                      sizeof (struct GNUNET_PeerIdentity))) )
1510   {
1511     /* forward to 'successor' */
1512     if (NULL != trail->succ)
1513     {
1514       forward_message_on_trail (trail->succ,
1515                                 &trail->succ_id,
1516                                 ntohs (trm->record_path),
1517                                 peer,
1518                                 path,
1519                                 path_length,
1520                                 payload);
1521       return GNUNET_OK;
1522     }
1523   }
1524   else
1525   {
1526     /* forward to 'predecessor' */
1527     GNUNET_break_op ( (NULL != trail->succ) &&
1528                       (0 == memcmp (peer,
1529                                     &trail->succ->id,
1530                                     sizeof (struct GNUNET_PeerIdentity))) );
1531     if (NULL != trail->pred)
1532     {
1533       forward_message_on_trail (trail->pred,
1534                                 &trail->pred_id,
1535                                 ntohs (trm->record_path),
1536                                 peer,
1537                                 path,
1538                                 path_length,
1539                                 payload);
1540       return GNUNET_OK;
1541     }
1542   }
1543
1544   /* Message is for us, dispatch to handler */
1545   th = NULL;
1546   for (i=0; NULL != handlers[i].callback; i++)
1547   {
1548     th = &handlers[i];
1549     if (ntohs (payload->type) == th->message_type)
1550     {
1551       if ( (0 == th->message_size) ||
1552            (ntohs (payload->size) == th->message_size) )
1553         th->callback (th->cls,
1554                       &trm->trail_id,
1555                       payload);
1556       else
1557         GNUNET_break_op (0);
1558       break;
1559     }
1560   }
1561   GNUNET_break_op (NULL != th);
1562   return GNUNET_OK;
1563 }
1564
1565
1566 /**
1567  * Initialize neighbours subsystem.
1568  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1569  */
1570 int
1571 GDS_NEIGHBOURS_init (void)
1572 {
1573   static const struct GNUNET_CORE_MessageHandler core_handlers[] = {
1574     { &handle_dht_p2p_random_walk,
1575       GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK,
1576       sizeof (struct RandomWalkMessage) },
1577     { &handle_dht_p2p_random_walk_response,
1578       GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK_RESPONSE,
1579       sizeof (struct RandomWalkResponseMessage) },
1580     { &handle_dht_p2p_trail_destroy,
1581       GNUNET_MESSAGE_TYPE_WDHT_TRAIL_DESTROY,
1582       sizeof (struct TrailDestroyMessage) },
1583     { &handle_dht_p2p_trail_route,
1584       GNUNET_MESSAGE_TYPE_WDHT_TRAIL_ROUTE,
1585       0},
1586     {NULL, 0, 0}
1587   };
1588
1589   core_api =
1590     GNUNET_CORE_connect (GDS_cfg, NULL,
1591                          &core_init,
1592                          &handle_core_connect,
1593                          &handle_core_disconnect,
1594                          NULL, GNUNET_NO,
1595                          NULL, GNUNET_NO,
1596                          core_handlers);
1597
1598   if (NULL == core_api)
1599     return GNUNET_SYSERR;
1600   friends_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1601   trail_map = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES);
1602   trail_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1603   return GNUNET_OK;
1604 }
1605
1606
1607 /**
1608  * Shutdown neighbours subsystem.
1609  */
1610 void
1611 GDS_NEIGHBOURS_done (void)
1612 {
1613   if (NULL == core_api)
1614     return;
1615   GNUNET_CORE_disconnect (core_api);
1616   core_api = NULL;
1617   GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friends_peermap));
1618   GNUNET_CONTAINER_multipeermap_destroy (friends_peermap);
1619   friends_peermap = NULL;
1620   GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (trail_map));
1621   GNUNET_CONTAINER_multihashmap_destroy (trail_map);
1622   trail_map = NULL;
1623   GNUNET_CONTAINER_heap_destroy (trail_heap);
1624   trail_heap = NULL;
1625   if (NULL != trail_timeout_task)
1626   {
1627     GNUNET_SCHEDULER_cancel (trail_timeout_task);
1628     trail_timeout_task = NULL;
1629   }
1630 }
1631
1632
1633 /**
1634  * Get my identity
1635  *
1636  * @return my identity
1637  */
1638 struct GNUNET_PeerIdentity
1639 GDS_NEIGHBOURS_get_my_id (void)
1640 {
1641   return my_identity;
1642 }
1643
1644 /* end of gnunet-service-wdht_neighbours.c */