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