2 This file is part of GNUnet.
3 Copyright (C) 2009-2015 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
21 * @file dht/gnunet-service-wdht_neighbours.c
22 * @brief GNUnet DHT service's finger and friend table management code
23 * @author Supriti Singh
26 #include "gnunet_util_lib.h"
27 #include "gnunet_block_lib.h"
28 #include "gnunet_hello_lib.h"
29 #include "gnunet_constants.h"
30 #include "gnunet_protocols.h"
31 #include "gnunet_ats_service.h"
32 #include "gnunet_core_service.h"
33 #include "gnunet_datacache_lib.h"
34 #include "gnunet_transport_service.h"
35 #include "gnunet_dht_service.h"
36 #include "gnunet_statistics_service.h"
37 #include "gnunet-service-wdht.h"
38 #include "gnunet-service-wdht_clients.h"
39 #include "gnunet-service-wdht_datacache.h"
40 #include "gnunet-service-wdht_neighbours.h"
41 #include "gnunet-service-wdht_nse.h"
48 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
51 * Trail timeout. After what time do trails always die?
53 #define TRAIL_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 42)
56 * Random walk delay. How often do we walk the overlay?
58 #define RANDOM_WALK_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 42)
61 * The number of layered ID to use.
63 #define NUMBER_LAYERED_ID 8
66 * The number of random walk to launch at the beginning of the initialization
68 /* FIXME: find a better value */
69 #define NUMBER_RANDOM_WALK 20
72 /******************* The db structure and related functions *******************/
75 * Entry in #friends_peermap.
81 * Information we keep per trail.
87 * MDLL entry in the list of all trails with the same predecessor.
89 struct Trail *prev_succ;
92 * MDLL entry in the list of all trails with the same predecessor.
94 struct Trail *next_succ;
97 * MDLL entry in the list of all trails with the same predecessor.
99 struct Trail *prev_pred;
102 * MDLL entry in the list of all trails with the same predecessor.
104 struct Trail *next_pred;
107 * Our predecessor in the trail, NULL if we are initiator (?).
109 struct FriendInfo *pred;
112 * Our successor in the trail, NULL if we are the last peer.
114 struct FriendInfo *succ;
117 * Identifier of the trail with the predecessor.
119 struct GNUNET_HashCode pred_id;
122 * Identifier of the trail with the successor.
124 struct GNUNET_HashCode succ_id;
127 * When does this trail expire.
129 struct GNUNET_TIME_Absolute expiration_time;
132 * Location of this trail in the heap.
134 struct GNUNET_CONTAINER_HeapNode *hn;
137 * If this peer started the to create a Finger (and thus @e pred is
138 * NULL), this is the Finger we are trying to intialize.
140 struct Finger **finger;
146 * Entry in #friends_peermap.
153 struct GNUNET_PeerIdentity id;
155 struct Trail *pred_head;
157 struct Trail *pred_tail;
159 struct Trail *succ_head;
161 struct Trail *succ_tail;
164 * Core handle for sending messages to this friend.
166 struct GNUNET_MQ_Handle *mq;
178 struct FingerTable *ft;
180 struct GNUNET_HashCode destination;
183 * #GNUNET_YES if a response has been received. Otherwise #GNUNET_NO.
192 * Array of our fingers, unsorted.
194 struct Finger **fingers;
197 * Array of sorted fingers (sorted by destination, valid fingers first).
199 struct Finger **sorted_fingers;
202 * Size of the finger array.
204 unsigned int finger_array_size;
207 * Number of valid entries in @e sorted_fingers (contiguous from offset 0)
209 unsigned int number_valid_fingers;
212 * Which offset in @e fingers will we redo next.
214 unsigned int walk_offset;
217 * Is the finger array sorted?
224 /*********************** end of the db structure part ***********************/
227 GNUNET_NETWORK_STRUCT_BEGIN
230 * Setup a finger using the underlay topology ("social network").
232 struct RandomWalkMessage
235 * Type: #GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK
237 struct GNUNET_MessageHeader header;
240 * Number of hops this message has taken so far, we stop at
243 uint16_t hops_taken GNUNET_PACKED;
246 * Layer for the request, in NBO.
248 uint16_t layer GNUNET_PACKED;
251 * Unique (random) identifier this peer will use to
252 * identify the trail (in future messages).
254 struct GNUNET_HashCode trail_id;
259 * Response to a `struct RandomWalkMessage`.
261 struct RandomWalkResponseMessage
264 * Type: #GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK_RESPONSE
266 struct GNUNET_MessageHeader header;
269 * Zero, for alignment.
271 uint32_t reserved GNUNET_PACKED;
274 * Unique (random) identifier from the
275 * `struct RandomWalkMessage`.
277 struct GNUNET_HashCode trail_id;
280 * Random location in the respective layer where the
281 * random path of the finger setup terminated.
283 struct GNUNET_HashCode location;
288 * Response to an event that causes a trail to die.
290 struct TrailDestroyMessage
293 * Type: #GNUNET_MESSAGE_TYPE_WDHT_TRAIL_DESTROY
295 struct GNUNET_MessageHeader header;
298 * Zero, for alignment.
300 uint32_t reserved GNUNET_PACKED;
303 * Unique (random) identifier this peer will use to
304 * identify the finger (in future messages).
306 struct GNUNET_HashCode trail_id;
312 * Send a message along a trail.
314 struct FindSuccessorMessage
317 * Type: #GNUNET_MESSAGE_TYPE_WDHT_FIND_SUCCESSOR
319 struct GNUNET_MessageHeader header;
322 * Zero, for alignment.
324 uint32_t reserved GNUNET_PACKED;
327 * Unique (random) identifier this peer will use to
328 * identify the finger (in future messages).
330 struct GNUNET_HashCode trail_id;
333 * Key for which we would like close values returned.
334 * identify the finger (in future messages).
336 struct GNUNET_HashCode key;
342 * Send a message along a trail.
344 struct TrailRouteMessage
347 * Type: #GNUNET_MESSAGE_TYPE_WDHT_TRAIL_ROUTE
349 struct GNUNET_MessageHeader header;
352 * Zero, for alignment.
354 uint32_t reserved GNUNET_PACKED;
357 * Unique (random) identifier this peer will use to
358 * identify the finger (in future messages).
360 struct GNUNET_HashCode trail_id;
362 /* followed by payload to send along the trail */
369 struct PeerPutMessage
372 * Type: #GNUNET_MESSAGE_TYPE_WDHT_PUT
374 struct GNUNET_MessageHeader header;
379 uint32_t options GNUNET_PACKED;
384 uint32_t block_type GNUNET_PACKED;
389 uint32_t hop_count GNUNET_PACKED;
392 * Replication level for this message
393 * In the current implementation, this value is not used.
395 uint32_t desired_replication_level GNUNET_PACKED;
398 * Length of the PUT path that follows (if tracked).
400 uint32_t put_path_length GNUNET_PACKED;
403 * When does the content expire?
405 struct GNUNET_TIME_AbsoluteNBO expiration_time;
408 * The key to store the value under.
410 struct GNUNET_HashCode key GNUNET_PACKED;
412 /* put path (if tracked) */
421 struct PeerGetMessage
424 * Type: #GNUNET_MESSAGE_TYPE_WDHT_GET
426 struct GNUNET_MessageHeader header;
431 uint32_t options GNUNET_PACKED;
434 * Desired content type.
436 uint32_t block_type GNUNET_PACKED;
441 uint32_t hop_count GNUNET_PACKED;
444 * Desired replication level for this request.
445 * In the current implementation, this value is not used.
447 uint32_t desired_replication_level GNUNET_PACKED;
450 * Total number of peers in get path.
452 unsigned int get_path_length;
455 * The key we are looking for.
457 struct GNUNET_HashCode key;
460 /* struct GNUNET_PeerIdentity[]*/
467 struct PeerGetResultMessage
470 * Type: #GNUNET_MESSAGE_TYPE_WDHT_GET_RESULT
472 struct GNUNET_MessageHeader header;
475 * The type for the data.
477 uint32_t type GNUNET_PACKED;
480 * Number of peers recorded in the outgoing path from source to the
481 * stored location of this message.
483 uint32_t put_path_length GNUNET_PACKED;
486 * Length of the GET path that follows (if tracked).
488 uint32_t get_path_length GNUNET_PACKED;
491 * Peer which queried for get and should get the result.
493 struct GNUNET_PeerIdentity querying_peer;
496 * When does the content expire?
498 struct GNUNET_TIME_Absolute expiration_time;
501 * The key of the corresponding GET request.
503 struct GNUNET_HashCode key;
505 /* put path (if tracked) */
507 /* get path (if tracked) */
513 GNUNET_NETWORK_STRUCT_END
517 * Contains all the layered IDs of this peer.
519 struct GNUNET_PeerIdentity layered_id[NUMBER_LAYERED_ID];
522 * Task to timeout trails that have expired.
524 static struct GNUNET_SCHEDULER_Task *trail_timeout_task;
527 * Task to perform random walks.
529 static struct GNUNET_SCHEDULER_Task *random_walk_task;
532 * Identity of this peer.
534 static struct GNUNET_PeerIdentity my_identity;
537 * Peer map of all the friends of a peer
539 static struct GNUNET_CONTAINER_MultiPeerMap *friends_peermap;
544 static struct FingerTable fingers[NUMBER_LAYERED_ID];
547 * Tail map, mapping tail identifiers to `struct Trail`s
549 static struct GNUNET_CONTAINER_MultiHashMap *trail_map;
552 * Tail heap, organizing trails by expiration time.
554 static struct GNUNET_CONTAINER_Heap *trail_heap;
559 static struct GNUNET_CORE_Handle *core_api;
563 * Handle the put request from the client.
565 * @param key Key for the content
566 * @param block_type Type of the block
567 * @param options Routing options
568 * @param desired_replication_level Desired replication count
569 * @param expiration_time When does the content expire
570 * @param data Content to store
571 * @param data_size Size of content @a data in bytes
574 GDS_NEIGHBOURS_handle_put (const struct GNUNET_HashCode *key,
575 enum GNUNET_BLOCK_Type block_type,
576 enum GNUNET_DHT_RouteOption options,
577 uint32_t desired_replication_level,
578 struct GNUNET_TIME_Absolute expiration_time,
579 const void *data, size_t data_size)
581 GDS_DATACACHE_handle_put (expiration_time,
591 * Handle the get request from the client file. If I am destination do
592 * datacache put and return. Else find the target friend and forward message
595 * @param key Key for the content
596 * @param block_type Type of the block
597 * @param options Routing options
598 * @param desired_replication_level Desired replication count
601 GDS_NEIGHBOURS_handle_get (const struct GNUNET_HashCode *key,
602 enum GNUNET_BLOCK_Type block_type,
603 enum GNUNET_DHT_RouteOption options,
604 uint32_t desired_replication_level)
606 // find closest finger(s) on all layers
607 // use TrailRoute with PeerGetMessage embedded to contact peer
612 * Delete a trail, it died (timeout, link failure, etc.).
614 * @param trail trail to delete from all data structures
615 * @param inform_pred should we notify the predecessor?
616 * @param inform_succ should we inform the successor?
619 delete_trail (struct Trail *trail,
623 struct FriendInfo *friend;
624 struct GNUNET_MQ_Envelope *env;
625 struct TrailDestroyMessage *tdm;
626 struct Trail *current;
628 tdm = GNUNET_new(struct TrailDestroyMessage);
633 struct Trail *previous_pred;
634 struct Trail *next_pred;
635 tdm->trail_id = current->pred_id;
636 friend = current->pred;
638 while( NULL != current)
642 env = GNUNET_MQ_msg (tdm,
643 GNUNET_MESSAGE_TYPE_WDHT_TRAIL_DESTROY);
644 GNUNET_MQ_send (friend->mq,
648 next_pred = current->next_pred;
649 previous_pred = current->prev_pred;
651 /* Freeing current trail memory */
652 GNUNET_free(current);
654 /* Destroying the next successor list */
655 while(NULL != previous_pred)
660 env = GNUNET_MQ_msg (tdm,
661 GNUNET_MESSAGE_TYPE_WDHT_TRAIL_DESTROY);
662 GNUNET_MQ_send (friend->mq,
667 next_pred = next_pred->next_pred;
671 /* Destroying the next predecessor list */
672 while(NULL != next_pred)
677 env = GNUNET_MQ_msg (tdm,
678 GNUNET_MESSAGE_TYPE_WDHT_TRAIL_DESTROY);
679 GNUNET_MQ_send (friend->mq,
684 next_pred = next_pred->next_pred;
692 struct Trail *previous_succ;
693 struct Trail *next_succ;
694 tdm->trail_id = current->succ_id;
695 friend = current->succ;
697 while( NULL != current)
701 env = GNUNET_MQ_msg (tdm,
702 GNUNET_MESSAGE_TYPE_WDHT_TRAIL_DESTROY);
703 GNUNET_MQ_send (friend->mq,
707 next_succ = current->next_succ;
708 previous_succ = current->prev_succ;
710 /* Freeing current trail memory */
711 GNUNET_free(current);
713 /* Destroying the next successor list */
714 while(NULL != previous_succ)
719 env = GNUNET_MQ_msg (tdm,
720 GNUNET_MESSAGE_TYPE_WDHT_TRAIL_DESTROY);
721 GNUNET_MQ_send (friend->mq,
725 previous_succ = previous_succ->prev_succ;
729 /* Destroying the next successor list */
730 while(NULL != next_succ)
735 env = GNUNET_MQ_msg (tdm,
736 GNUNET_MESSAGE_TYPE_WDHT_TRAIL_DESTROY);
737 GNUNET_MQ_send (friend->mq,
741 next_succ = next_succ->next_pred;
750 * Send the get result to requesting client.
752 * @param key Key of the requested data.
753 * @param type Block type
754 * @param target_peer Next peer to forward the message to.
755 * @param source_peer Peer which has the data for the key.
756 * @param put_path_length Number of peers in @a put_path
757 * @param put_path Path taken to put the data at its stored location.
758 * @param get_path_length Number of peers in @a get_path
759 * @param get_path Path taken to reach to the location of the key.
760 * @param expiration When will this result expire?
761 * @param data Payload to store
762 * @param data_size Size of the @a data
765 GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key,
766 enum GNUNET_BLOCK_Type type,
767 const struct GNUNET_PeerIdentity *target_peer,
768 const struct GNUNET_PeerIdentity *source_peer,
769 unsigned int put_path_length,
770 const struct GNUNET_PeerIdentity *put_path,
771 unsigned int get_path_length,
772 const struct GNUNET_PeerIdentity *get_path,
773 struct GNUNET_TIME_Absolute expiration,
774 const void *data, size_t data_size)
776 // TRICKY: need to introduce some context to remember trail from
781 * Method called whenever a peer disconnects.
784 * @param peer peer identity this notification is about
787 handle_core_disconnect (void *cls,
788 const struct GNUNET_PeerIdentity *peer)
790 struct FriendInfo *remove_friend;
793 /* If disconnected to own identity, then return. */
794 if (0 == memcmp (&my_identity,
796 sizeof (struct GNUNET_PeerIdentity)))
799 if (NULL == (remove_friend =
800 GNUNET_CONTAINER_multipeermap_get (friends_peermap,
807 GNUNET_assert (GNUNET_YES ==
808 GNUNET_CONTAINER_multipeermap_remove (friends_peermap,
811 while (NULL != (t = remove_friend->succ_head))
815 while (NULL != (t = remove_friend->pred_head))
819 GNUNET_MQ_destroy (remove_friend->mq);
820 GNUNET_free (remove_friend);
822 GNUNET_CONTAINER_multipeermap_size (friends_peermap))
824 GNUNET_SCHEDULER_cancel (random_walk_task);
825 random_walk_task = NULL;
831 * Pick random friend from friends for random walk.
833 static struct FriendInfo *
834 pick_random_friend ()
836 // TODO: need to extend peermap API to return random entry...
837 // (Note: same extension exists for hashmap API).
838 return NULL; // FIXME...
843 * Initiate a random walk.
849 do_random_walk (void *cls,
850 const struct GNUNET_SCHEDULER_TaskContext *tc)
852 static unsigned int walk_layer;
853 struct FriendInfo *friend;
854 struct GNUNET_MQ_Envelope *env;
855 struct RandomWalkMessage *rwm;
856 struct FingerTable *ft;
857 struct Finger *finger;
860 random_walk_task = NULL;
861 friend = pick_random_friend ();
863 trail = GNUNET_new (struct Trail);
864 /* We create the random walk so, no predecessor */
865 trail->succ = friend;
866 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE,
869 GNUNET_CONTAINER_multihashmap_put (trail_map,
872 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
878 GNUNET_CONTAINER_MDLL_insert (succ,
882 env = GNUNET_MQ_msg (rwm,
883 GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK);
884 rwm->hops_taken = htonl (0);
885 rwm->trail_id = trail->succ_id;
886 GNUNET_MQ_send (friend->mq,
888 /* clean up 'old' entry (implicitly via trail cleanup) */
889 ft = &fingers[walk_layer];
891 if ( (NULL != ft->fingers) &&
892 (NULL != (finger = ft->fingers[ft->walk_offset])) )
893 delete_trail (finger->trail,
896 if (ft->finger_array_size < 42)
898 // FIXME: must have finger array of the right size here,
899 // FIXME: growing / shrinking are tricy -- with pointers
903 GNUNET_assert (NULL == ft->fingers[ft->walk_offset]);
905 finger = GNUNET_new (struct Finger);
906 finger->trail = trail;
907 trail->finger = &ft->fingers[ft->walk_offset];
909 ft->fingers[ft->walk_offset] = finger;
910 ft->is_sorted = GNUNET_NO;
911 ft->walk_offset = (ft->walk_offset + 1) % ft->finger_array_size;
913 walk_layer = (walk_layer + 1) % NUMBER_LAYERED_ID;
914 random_walk_task = GNUNET_SCHEDULER_add_delayed (RANDOM_WALK_DELAY,
921 * Method called whenever a peer connects.
924 * @param peer_identity peer identity this notification is about
927 handle_core_connect (void *cls,
928 const struct GNUNET_PeerIdentity *peer_identity)
930 struct FriendInfo *friend;
932 /* Check for connect to self message */
933 if (0 == memcmp (&my_identity,
935 sizeof (struct GNUNET_PeerIdentity)))
938 /* If peer already exists in our friend_peermap, then exit. */
940 GNUNET_CONTAINER_multipeermap_contains (friends_peermap,
947 friend = GNUNET_new (struct FriendInfo);
948 friend->id = *peer_identity;
949 friend->mq = GNUNET_CORE_mq_create (core_api,
951 GNUNET_assert (GNUNET_OK ==
952 GNUNET_CONTAINER_multipeermap_put (friends_peermap,
955 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
956 if (NULL == random_walk_task)
958 /* random walk needs to be started -- we have a first connection */
959 random_walk_task = GNUNET_SCHEDULER_add_now (&do_random_walk,
966 * To be called on core init/fail.
968 * @param cls service closure
969 * @param identity the public identity of this peer
972 core_init (void *cls,
973 const struct GNUNET_PeerIdentity *identity)
975 my_identity = *identity;
980 * Handle a `struct RandomWalkMessage` from a
981 * #GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK message.
983 * @param cls closure (NULL)
984 * @param peer sender identity
985 * @param message the setup message
986 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
989 handle_dht_p2p_random_walk (void *cls,
990 const struct GNUNET_PeerIdentity *peer,
991 const struct GNUNET_MessageHeader *message)
993 const struct RandomWalkMessage *m;
995 struct FriendInfo *pred;
997 m = (const struct RandomWalkMessage *) message;
998 pred = GNUNET_CONTAINER_multipeermap_get (friends_peermap,
1000 t = GNUNET_new (struct Trail);
1001 t->pred_id = m->trail_id;
1003 t->expiration_time = GNUNET_TIME_relative_to_absolute (TRAIL_TIMEOUT);
1005 GNUNET_CONTAINER_multihashmap_put (trail_map,
1008 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1010 GNUNET_break_op (0);
1012 return GNUNET_SYSERR;
1014 GNUNET_CONTAINER_MDLL_insert (pred,
1018 if (ntohl (m->hops_taken) > GDS_NSE_get ())
1020 /* We are the last hop, generate response */
1021 struct GNUNET_MQ_Envelope *env;
1022 struct RandomWalkResponseMessage *rwrm;
1025 env = GNUNET_MQ_msg (rwrm,
1026 GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK_RESPONSE);
1027 rwrm->reserved = htonl (0);
1028 rwrm->trail_id = m->trail_id;
1029 layer = ntohs (m->layer);
1031 (void) GDS_DATACACHE_get_random_key (&rwrm->location);
1034 struct FingerTable *ft;
1036 if (layer > NUMBER_LAYERED_ID)
1038 GNUNET_break_op (0);
1039 // FIXME: clean up 't'...
1040 return GNUNET_SYSERR;
1042 ft = &fingers[layer-1];
1043 if (0 == ft->number_valid_fingers)
1045 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE,
1052 f = ft->fingers[GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
1053 ft->number_valid_fingers)];
1054 rwrm->location = f->destination;
1057 GNUNET_MQ_send (pred->mq,
1062 struct GNUNET_MQ_Envelope *env;
1063 struct RandomWalkMessage *rwm;
1064 struct FriendInfo *succ;
1066 /* extend the trail by another random hop */
1067 succ = pick_random_friend ();
1068 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE,
1072 GNUNET_CONTAINER_multihashmap_put (trail_map,
1075 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1078 GNUNET_CONTAINER_MDLL_remove (pred,
1085 GNUNET_CONTAINER_MDLL_insert (succ,
1089 env = GNUNET_MQ_msg (rwm,
1090 GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK);
1091 rwm->hops_taken = htons (1 + ntohs (m->hops_taken));
1092 rwm->layer = m->layer;
1093 rwm->trail_id = t->succ_id;
1094 GNUNET_MQ_send (succ->mq,
1102 * Handle a `struct RandomWalkResponseMessage` from a GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK_RESPONSE
1105 * @param cls closure (NULL)
1106 * @param peer sender identity
1107 * @param message the setup response message
1108 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1111 handle_dht_p2p_random_walk_response (void *cls,
1112 const struct GNUNET_PeerIdentity *peer,
1113 const struct GNUNET_MessageHeader *message)
1115 const struct RandomWalkResponseMessage *rwrm;
1117 rwrm = (const struct RandomWalkResponseMessage *) message;
1118 // 1) lookup trail => find Finger entry => fill in 'destination' and mark valid, move to end of sorted array, mark unsorted, update links from 'trails'
1121 * 1 check if we are the correct layer
1122 * 1.a if true : add the returned value (finger) in the db structure
1123 * 1.b if true : do nothing
1125 /* FIXME: add the value in db structure 1.a */
1132 * Handle a `struct TrailDestroyMessage`.
1134 * @param cls closure (NULL)
1135 * @param peer sender identity
1136 * @param message the finger destroy message
1137 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1140 handle_dht_p2p_trail_destroy (void *cls,
1141 const struct GNUNET_PeerIdentity *peer,
1142 const struct GNUNET_MessageHeader *message)
1144 const struct TrailDestroyMessage *tdm;
1146 tdm = (const struct TrailDestroyMessage *) message;
1150 * 1 check if message comme from a trail (that we still remember...)
1151 * 1.a.1 if true: send the destroy message to the rest trail
1152 * 1.a.2 clean the trail structure
1153 * 1.a.3 did i have to remove the trail and ID from the db structure?
1154 * 1.b if false: do nothing
1162 * Handle a `struct TrailRouteMessage`.
1164 * @param cls closure (NULL)
1165 * @param peer sender identity
1166 * @param message the finger destroy message
1167 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1170 handle_dht_p2p_trail_route (void *cls,
1171 const struct GNUNET_PeerIdentity *peer,
1172 const struct GNUNET_MessageHeader *message)
1174 const struct TrailRouteMessage *trm;
1176 trm = (const struct TrailRouteMessage *) message;
1180 * 1 check if message comme from a trail
1181 * 1.a.1 if trail not finished with us, continue to forward
1182 * 1.a.2 otherwise handle body message embedded in trail
1190 * Handle a `struct FindSuccessorMessage` from a #GNUNET_MESSAGE_TYPE_WDHT_SUCCESSOR_FIND
1193 * @param cls closure (NULL)
1194 * @param peer sender identity
1195 * @param message the finger setup message
1196 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1199 handle_dht_p2p_successor_find (void *cls,
1200 const struct GNUNET_PeerIdentity *peer,
1201 const struct GNUNET_MessageHeader *message)
1203 const struct FindSuccessorMessage *fsm;
1205 fsm = (const struct FindSuccessorMessage *) message;
1206 // locate trail (for sending reply), if not exists, fail nicely.
1207 // otherwise, go to datacache and return 'top k' elements closest to 'key'
1208 // as "PUT" messages via the trail (need to extend DB API!)
1215 * Handle a `struct PeerGetMessage`.
1217 * @param cls closure (NULL)
1218 * @param peer sender identity
1219 * @param message the peer get message
1220 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1223 handle_dht_p2p_peer_get (void *cls,
1224 const struct GNUNET_PeerIdentity *peer,
1225 const struct GNUNET_MessageHeader *message)
1227 const struct PeerGetMessage *pgm;
1229 // FIXME: note: never called like this, message embedded with trail route!
1230 pgm = (const struct PeerGetMessage *) message;
1231 // -> lookup in datacache (figure out way to remember trail!)
1234 * 1 extract the result
1236 * 3 send it using the good trail
1238 * What do i do when i don't have the key/value?
1246 * Handle a `struct PeerGetResultMessage`.
1248 * @param cls closure (NULL)
1249 * @param peer sender identity
1250 * @param message the peer get result message
1251 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1254 handle_dht_p2p_peer_get_result (void *cls,
1255 const struct GNUNET_PeerIdentity *peer,
1256 const struct GNUNET_MessageHeader *message)
1258 const struct PeerGetResultMessage *pgrm;
1260 pgrm = (const struct PeerGetResultMessage *) message;
1261 // pretty much: parse, & pass to client (there is some call for that...)
1268 * Handle a `struct PeerPutMessage`.
1270 * @param cls closure (NULL)
1271 * @param peer sender identity
1272 * @param message the peer put message
1273 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1276 handle_dht_p2p_peer_put (void *cls,
1277 const struct GNUNET_PeerIdentity *peer,
1278 const struct GNUNET_MessageHeader *message)
1280 const struct PeerGetResultMessage *pgrm;
1282 pgrm = (const struct PeerGetResultMessage *) message;
1283 // parse & store in datacache, this is in response to us asking for successors.
1286 * 1 check the size of the message
1287 * 2 use the API to add the value in the "database". Check on the xdht file, how to do it.
1288 * 3 Did i a have to return a notification or did i have to return GNUNET_[OK|SYSERR]?
1295 * Initialize neighbours subsystem.
1296 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1299 GDS_NEIGHBOURS_init (void)
1301 static const struct GNUNET_CORE_MessageHandler core_handlers[] = {
1302 { &handle_dht_p2p_random_walk,
1303 GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK,
1304 sizeof (struct RandomWalkMessage) },
1305 { &handle_dht_p2p_random_walk_response,
1306 GNUNET_MESSAGE_TYPE_WDHT_RANDOM_WALK_RESPONSE,
1307 sizeof (struct RandomWalkResponseMessage) },
1308 { &handle_dht_p2p_trail_destroy,
1309 GNUNET_MESSAGE_TYPE_WDHT_TRAIL_DESTROY,
1310 sizeof (struct TrailDestroyMessage) },
1311 { &handle_dht_p2p_trail_route,
1312 GNUNET_MESSAGE_TYPE_WDHT_TRAIL_ROUTE,
1314 { &handle_dht_p2p_successor_find,
1315 GNUNET_MESSAGE_TYPE_WDHT_SUCCESSOR_FIND,
1316 sizeof (struct FindSuccessorMessage) },
1317 { &handle_dht_p2p_peer_get,
1318 GNUNET_MESSAGE_TYPE_WDHT_GET,
1319 sizeof (struct PeerGetMessage) },
1320 { &handle_dht_p2p_peer_get_result,
1321 GNUNET_MESSAGE_TYPE_WDHT_GET_RESULT,
1323 { &handle_dht_p2p_peer_put,
1324 GNUNET_MESSAGE_TYPE_WDHT_PUT,
1330 GNUNET_CORE_connect (GDS_cfg, NULL,
1332 &handle_core_connect,
1333 &handle_core_disconnect,
1338 if (NULL == core_api)
1339 return GNUNET_SYSERR;
1340 friends_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1341 trail_map = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES);
1342 trail_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1348 * Shutdown neighbours subsystem.
1351 GDS_NEIGHBOURS_done (void)
1353 if (NULL == core_api)
1355 GNUNET_CORE_disconnect (core_api);
1357 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friends_peermap));
1358 GNUNET_CONTAINER_multipeermap_destroy (friends_peermap);
1359 friends_peermap = NULL;
1360 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (trail_map));
1361 GNUNET_CONTAINER_multihashmap_destroy (trail_map);
1363 GNUNET_CONTAINER_heap_destroy (trail_heap);
1371 * @return my identity
1373 struct GNUNET_PeerIdentity
1374 GDS_NEIGHBOURS_get_my_id (void)
1379 /* end of gnunet-service-wdht_neighbours.c */