aboutsummaryrefslogtreecommitdiff
path: root/src/cadet/gnunet-service-cadet_dht.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cadet/gnunet-service-cadet_dht.c')
-rw-r--r--src/cadet/gnunet-service-cadet_dht.c351
1 files changed, 351 insertions, 0 deletions
diff --git a/src/cadet/gnunet-service-cadet_dht.c b/src/cadet/gnunet-service-cadet_dht.c
new file mode 100644
index 000000000..f00c0caf3
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet_dht.c
@@ -0,0 +1,351 @@
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
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 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 (GNUNET_TIME_UNIT_MILLISECONDS, 500)
44
45/**
46 * How long do we wait after we get an updated HELLO before publishing?
47 * Allows for the HELLO to be updated again quickly, for example in
48 * case multiple addresses changed and we got a partial update.
49 */
50#define CHANGE_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100)
51
52
53#define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__)
54
55
56/**
57 * Handle for DHT searches.
58 */
59struct GCD_search_handle
60{
61 /**
62 * DHT_GET handle.
63 */
64 struct GNUNET_DHT_GetHandle *dhtget;
65
66};
67
68
69/**
70 * Handle to use DHT.
71 */
72static struct GNUNET_DHT_Handle *dht_handle;
73
74/**
75 * How often to PUT own ID in the DHT.
76 */
77static struct GNUNET_TIME_Relative id_announce_time;
78
79/**
80 * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put().
81 */
82static unsigned long long dht_replication_level;
83
84/**
85 * Task to periodically announce itself in the network.
86 */
87static struct GNUNET_SCHEDULER_Task *announce_id_task;
88
89/**
90 * Delay for the next ID announce.
91 */
92static struct GNUNET_TIME_Relative announce_delay;
93
94
95/**
96 * Function to process paths received for a new peer addition. The recorded
97 * paths form the initial tunnel, which can be optimized later.
98 * Called on each result obtained for the DHT search.
99 *
100 * @param cls closure
101 * @param exp when will this value expire
102 * @param key key of the result
103 * @param get_path path of the get request
104 * @param get_path_length lenght of @a get_path
105 * @param put_path path of the put request
106 * @param put_path_length length of the @a put_path
107 * @param type type of the result
108 * @param size number of bytes in data
109 * @param data pointer to the result data
110 */
111static void
112dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
113 const struct GNUNET_HashCode *key,
114 const struct GNUNET_PeerIdentity *get_path,
115 unsigned int get_path_length,
116 const struct GNUNET_PeerIdentity *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_HELLO_Message *hello = data;
123 struct CadetPeer *peer;
124
125 GCPP_try_path_from_dht (get_path,
126 get_path_length,
127 put_path,
128 put_path_length);
129 if ( (size >= sizeof (struct GNUNET_HELLO_Message)) &&
130 (ntohs (hello->header.size) == size) &&
131 (size == GNUNET_HELLO_size (hello)) )
132 {
133 peer = GCP_get (&put_path[0],
134 GNUNET_YES);
135 LOG (GNUNET_ERROR_TYPE_DEBUG,
136 "Got HELLO for %s\n",
137 GCP_2s (peer));
138 GCP_set_hello (peer,
139 hello);
140 }
141}
142
143
144/**
145 * Periodically announce self id in the DHT
146 *
147 * @param cls closure
148 */
149static void
150announce_id (void *cls)
151{
152 struct GNUNET_HashCode phash;
153 const struct GNUNET_HELLO_Message *hello;
154 size_t size;
155 struct GNUNET_TIME_Absolute expiration;
156 struct GNUNET_TIME_Relative next_put;
157
158 hello = GCH_get_mine ();
159 size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0;
160 if (0 == size)
161 {
162 expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
163 announce_delay);
164 announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
165 }
166 else
167 {
168 expiration = GNUNET_HELLO_get_last_expiration (hello);
169 announce_delay = GNUNET_TIME_UNIT_SECONDS;
170 }
171
172 /* Call again in id_announce_time, unless HELLO expires first,
173 * but wait at least 1s. */
174 next_put
175 = GNUNET_TIME_absolute_get_remaining (expiration);
176 next_put
177 = GNUNET_TIME_relative_min (next_put,
178 id_announce_time);
179 next_put
180 = GNUNET_TIME_relative_max (next_put,
181 GNUNET_TIME_UNIT_SECONDS);
182 announce_id_task
183 = GNUNET_SCHEDULER_add_delayed (next_put,
184 &announce_id,
185 cls);
186 GNUNET_STATISTICS_update (stats,
187 "# DHT announce",
188 1,
189 GNUNET_NO);
190 memset (&phash,
191 0,
192 sizeof (phash));
193 GNUNET_memcpy (&phash,
194 &my_full_id,
195 sizeof (my_full_id));
196 LOG (GNUNET_ERROR_TYPE_DEBUG,
197 "Announcing my HELLO (%u bytes) in the DHT\n",
198 size);
199 GNUNET_DHT_put (dht_handle, /* DHT handle */
200 &phash, /* Key to use */
201 dht_replication_level, /* Replication level */
202 GNUNET_DHT_RO_RECORD_ROUTE
203 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
204 GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */
205 size, /* Size of the data */
206 (const char *) hello, /* Data itself */
207 expiration, /* Data expiration */
208 NULL, /* Continuation */
209 NULL); /* Continuation closure */
210}
211
212
213/**
214 * Function called by the HELLO subsystem whenever OUR hello
215 * changes. Re-triggers the DHT PUT immediately.
216 */
217void
218GCD_hello_update ()
219{
220 if (NULL == announce_id_task)
221 return; /* too early */
222 GNUNET_SCHEDULER_cancel (announce_id_task);
223 announce_id_task
224 = GNUNET_SCHEDULER_add_delayed (CHANGE_DELAY,
225 &announce_id,
226 NULL);
227}
228
229
230/**
231 * Initialize the DHT subsystem.
232 *
233 * @param c Configuration.
234 */
235void
236GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
237{
238 if (GNUNET_OK !=
239 GNUNET_CONFIGURATION_get_value_number (c,
240 "CADET",
241 "DHT_REPLICATION_LEVEL",
242 &dht_replication_level))
243 {
244 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
245 "CADET",
246 "DHT_REPLICATION_LEVEL",
247 "USING DEFAULT");
248 dht_replication_level = 3;
249 }
250
251 if (GNUNET_OK !=
252 GNUNET_CONFIGURATION_get_value_time (c,
253 "CADET",
254 "ID_ANNOUNCE_TIME",
255 &id_announce_time))
256 {
257 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
258 "CADET",
259 "ID_ANNOUNCE_TIME",
260 "MISSING");
261 GNUNET_SCHEDULER_shutdown ();
262 return;
263 }
264
265 dht_handle = GNUNET_DHT_connect (c,
266 64);
267 GNUNET_break (NULL != dht_handle);
268 announce_delay = GNUNET_TIME_UNIT_SECONDS;
269 announce_id_task = GNUNET_SCHEDULER_add_delayed (STARTUP_DELAY,
270 &announce_id,
271 NULL);
272}
273
274
275/**
276 * Shut down the DHT subsystem.
277 */
278void
279GCD_shutdown (void)
280{
281 if (NULL != dht_handle)
282 {
283 GNUNET_DHT_disconnect (dht_handle);
284 dht_handle = NULL;
285 }
286 if (NULL != announce_id_task)
287 {
288 GNUNET_SCHEDULER_cancel (announce_id_task);
289 announce_id_task = NULL;
290 }
291}
292
293
294/**
295 * Search DHT for paths to @a peeR_id
296 *
297 * @param peer_id peer to search for
298 * @return handle to abort search
299 */
300struct GCD_search_handle *
301GCD_search (const struct GNUNET_PeerIdentity *peer_id)
302{
303 struct GNUNET_HashCode phash;
304 struct GCD_search_handle *h;
305
306 GNUNET_STATISTICS_update (stats,
307 "# DHT search",
308 1,
309 GNUNET_NO);
310 memset (&phash,
311 0,
312 sizeof (phash));
313 GNUNET_memcpy (&phash,
314 peer_id,
315 sizeof (*peer_id));
316
317 h = GNUNET_new (struct GCD_search_handle);
318 h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */
319 GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */
320 &phash, /* key to search */
321 dht_replication_level, /* replication level */
322 GNUNET_DHT_RO_RECORD_ROUTE |
323 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
324 NULL, /* xquery */
325 0, /* xquery bits */
326 &dht_get_id_handler,
327 h);
328 LOG (GNUNET_ERROR_TYPE_DEBUG,
329 "Starting DHT GET for peer %s (%p)\n",
330 GNUNET_i2s (peer_id),
331 h);
332 return h;
333}
334
335
336/**
337 * Stop DHT search started with #GCD_search().
338 *
339 * @param h handle to search to stop
340 */
341void
342GCD_search_stop (struct GCD_search_handle *h)
343{
344 LOG (GNUNET_ERROR_TYPE_DEBUG,
345 "Stopping DHT GET %p\n",
346 h);
347 GNUNET_DHT_get_stop (h->dhtget);
348 GNUNET_free (h);
349}
350
351/* end of gnunet-service-cadet_dht.c */