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