aboutsummaryrefslogtreecommitdiff
path: root/src/service/cadet/gnunet-service-cadet_dht.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/cadet/gnunet-service-cadet_dht.c')
-rw-r--r--src/service/cadet/gnunet-service-cadet_dht.c340
1 files changed, 340 insertions, 0 deletions
diff --git a/src/service/cadet/gnunet-service-cadet_dht.c b/src/service/cadet/gnunet-service-cadet_dht.c
new file mode 100644
index 000000000..dcd1efaa2
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_dht.c
@@ -0,0 +1,340 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file cadet/gnunet-service-cadet_dht.c
22 * @brief Information we track per peer.
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_dht_service.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet-service-cadet.h"
32#include "gnunet-service-cadet_dht.h"
33#include "gnunet-service-cadet_hello.h"
34#include "gnunet-service-cadet_peer.h"
35#include "gnunet-service-cadet_paths.h"
36
37/**
38 * How long do we wait before first announcing our presence to the DHT.
39 * Used to wait for our HELLO to be available. Note that we also get
40 * notifications when our HELLO is ready, so this is just the maximum
41 * we wait for the first notification.
42 */
43#define STARTUP_DELAY GNUNET_TIME_relative_multiply ( \
44 GNUNET_TIME_UNIT_MILLISECONDS, 500)
45
46/**
47 * How long do we wait after we get an updated HELLO before publishing?
48 * Allows for the HELLO to be updated again quickly, for example in
49 * case multiple addresses changed and we got a partial update.
50 */
51#define CHANGE_DELAY GNUNET_TIME_relative_multiply ( \
52 GNUNET_TIME_UNIT_MILLISECONDS, 100)
53
54
55#define LOG(level, ...) GNUNET_log_from (level, "cadet-dht", __VA_ARGS__)
56
57
58struct GCD_search_handle
59{
60 /**
61 * DHT_GET handle.
62 */
63 struct GNUNET_DHT_GetHandle *dhtget;
64};
65
66
67/**
68 * Handle to use DHT.
69 */
70static struct GNUNET_DHT_Handle *dht_handle;
71
72/**
73 * How often to PUT own ID in the DHT.
74 */
75static struct GNUNET_TIME_Relative id_announce_time;
76
77/**
78 * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put().
79 */
80static unsigned long long dht_replication_level;
81
82/**
83 * Task to periodically announce itself in the network.
84 */
85static struct GNUNET_SCHEDULER_Task *announce_id_task;
86
87/**
88 * Delay for the next ID announce.
89 */
90static struct GNUNET_TIME_Relative announce_delay;
91
92
93/**
94 * Function to process paths received for a new peer addition. The recorded
95 * paths form the initial tunnel, which can be optimized later.
96 * Called on each result obtained for the DHT search.
97 *
98 * @param cls closure
99 * @param exp when will this value expire
100 * @param key key of the result
101 * @param trunc_peer peer preceeding with invalid signature, or NULL
102 * @param get_path path of the get request
103 * @param get_path_length length of @a get_path
104 * @param put_path path of the put request
105 * @param put_path_length length of the @a put_path
106 * @param type type of the result
107 * @param size number of bytes in data
108 * @param data pointer to the result data
109 */
110static void
111dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
112 const struct GNUNET_HashCode *key,
113 const struct GNUNET_PeerIdentity *trunc_peer,
114 const struct GNUNET_DHT_PathElement *get_path,
115 unsigned int get_path_length,
116 const struct GNUNET_DHT_PathElement *put_path,
117 unsigned int put_path_length,
118 enum GNUNET_BLOCK_Type type,
119 size_t size,
120 const void *data)
121{
122 const struct GNUNET_MessageHeader *hello = data;
123 struct GNUNET_HELLO_Builder *builder = GNUNET_HELLO_builder_from_msg (hello);
124
125 GNUNET_assert (NULL != builder);
126 (void) trunc_peer;
127 GCPP_try_path_from_dht (get_path,
128 get_path_length,
129 put_path,
130 put_path_length);
131
132 struct CadetPeer *peer;
133
134 peer = GCP_get (&put_path[0].pred,
135 GNUNET_YES);
136 LOG (GNUNET_ERROR_TYPE_DEBUG,
137 "Got HELLO for %s\n",
138 GCP_2s (peer));
139 GCP_set_hello (peer,
140 hello);
141 GNUNET_HELLO_builder_free (builder);
142}
143
144
145/**
146 * Periodically announce self id in the DHT
147 *
148 * @param cls closure
149 */
150static void
151announce_id (void *cls)
152{
153 struct GNUNET_HashCode phash;
154 const struct GNUNET_MessageHeader *hello;
155 size_t size;
156 size_t block_size;
157 void *block;
158 struct GNUNET_TIME_Absolute expiration;
159 struct GNUNET_TIME_Relative next_put;
160
161 hello = GCH_get_mine ();
162 size = (NULL != hello) ? ntohs(hello->size) : 0;
163 if (0 == size)
164 {
165 expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
166 announce_delay);
167 announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
168 }
169 else
170 {
171 expiration = GNUNET_HELLO_builder_get_expiration_time (hello);
172 announce_delay = GNUNET_TIME_UNIT_SECONDS;
173 }
174
175 /* Call again in id_announce_time, unless HELLO expires first,
176 * but wait at least 1s. */
177 next_put
178 = GNUNET_TIME_absolute_get_remaining (expiration);
179 next_put
180 = GNUNET_TIME_relative_min (next_put,
181 id_announce_time);
182 next_put
183 = GNUNET_TIME_relative_max (next_put,
184 GNUNET_TIME_UNIT_SECONDS);
185 announce_id_task
186 = GNUNET_SCHEDULER_add_delayed (next_put,
187 &announce_id,
188 cls);
189 GNUNET_STATISTICS_update (stats,
190 "# DHT announce",
191 1,
192 GNUNET_NO);
193 memset (&phash,
194 0,
195 sizeof(phash));
196 GNUNET_memcpy (&phash,
197 &my_full_id,
198 sizeof(my_full_id));
199 if (GNUNET_OK != GNUNET_HELLO_dht_msg_to_block (hello,
200 &my_full_id,
201 &block,
202 &block_size,
203 &expiration))
204 return;
205
206 LOG (GNUNET_ERROR_TYPE_DEBUG,
207 "Announcing my HELLO (%lu bytes) in the DHT\n",
208 (unsigned long) block_size);
209 GNUNET_DHT_put (dht_handle, /* DHT handle */
210 &phash, /* Key to use */
211 dht_replication_level, /* Replication level */
212 GNUNET_DHT_RO_RECORD_ROUTE
213 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
214 GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */
215 block_size, /* Size of the data */
216 (const char *) block, /* Data itself */
217 expiration, /* Data expiration */
218 NULL, /* Continuation */
219 NULL); /* Continuation closure */
220 GNUNET_free (block);
221}
222
223
224void
225GCD_hello_update ()
226{
227 if (NULL == announce_id_task)
228 return; /* too early */
229 GNUNET_SCHEDULER_cancel (announce_id_task);
230 announce_id_task
231 = GNUNET_SCHEDULER_add_delayed (CHANGE_DELAY,
232 &announce_id,
233 NULL);
234}
235
236
237void
238GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
239{
240 if (GNUNET_OK !=
241 GNUNET_CONFIGURATION_get_value_number (c,
242 "CADET",
243 "DHT_REPLICATION_LEVEL",
244 &dht_replication_level))
245 {
246 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
247 "CADET",
248 "DHT_REPLICATION_LEVEL",
249 "USING DEFAULT");
250 dht_replication_level = 3;
251 }
252
253 if (GNUNET_OK !=
254 GNUNET_CONFIGURATION_get_value_time (c,
255 "CADET",
256 "ID_ANNOUNCE_TIME",
257 &id_announce_time))
258 {
259 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
260 "CADET",
261 "ID_ANNOUNCE_TIME",
262 "MISSING");
263 GNUNET_SCHEDULER_shutdown ();
264 return;
265 }
266
267 dht_handle = GNUNET_DHT_connect (c,
268 64);
269 GNUNET_break (NULL != dht_handle);
270 announce_delay = GNUNET_TIME_UNIT_SECONDS;
271 announce_id_task = GNUNET_SCHEDULER_add_delayed (STARTUP_DELAY,
272 &announce_id,
273 NULL);
274}
275
276
277void
278GCD_shutdown (void)
279{
280 if (NULL != dht_handle)
281 {
282 GNUNET_DHT_disconnect (dht_handle);
283 dht_handle = NULL;
284 }
285 if (NULL != announce_id_task)
286 {
287 GNUNET_SCHEDULER_cancel (announce_id_task);
288 announce_id_task = NULL;
289 }
290}
291
292
293struct GCD_search_handle *
294GCD_search (const struct GNUNET_PeerIdentity *peer_id)
295{
296 struct GNUNET_HashCode phash;
297 struct GCD_search_handle *h;
298
299 GNUNET_STATISTICS_update (stats,
300 "# DHT search",
301 1,
302 GNUNET_NO);
303 memset (&phash,
304 0,
305 sizeof(phash));
306 GNUNET_memcpy (&phash,
307 peer_id,
308 sizeof(*peer_id));
309
310 h = GNUNET_new (struct GCD_search_handle);
311 h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */
312 GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */
313 &phash, /* key to search */
314 dht_replication_level, /* replication level */
315 GNUNET_DHT_RO_RECORD_ROUTE
316 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
317 NULL, /* xquery */
318 0, /* xquery bits */
319 &dht_get_id_handler,
320 h);
321 LOG (GNUNET_ERROR_TYPE_DEBUG,
322 "Starting DHT GET for peer %s (%p)\n",
323 GNUNET_i2s (peer_id),
324 h);
325 return h;
326}
327
328
329void
330GCD_search_stop (struct GCD_search_handle *h)
331{
332 LOG (GNUNET_ERROR_TYPE_DEBUG,
333 "Stopping DHT GET %p\n",
334 h);
335 GNUNET_DHT_get_stop (h->dhtget);
336 GNUNET_free (h);
337}
338
339
340/* end of gnunet-service-cadet_dht.c */