aboutsummaryrefslogtreecommitdiff
path: root/src/dhtu/plugin_dhtu_gnunet.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dhtu/plugin_dhtu_gnunet.c')
-rw-r--r--src/dhtu/plugin_dhtu_gnunet.c635
1 files changed, 0 insertions, 635 deletions
diff --git a/src/dhtu/plugin_dhtu_gnunet.c b/src/dhtu/plugin_dhtu_gnunet.c
deleted file mode 100644
index b072be2be..000000000
--- a/src/dhtu/plugin_dhtu_gnunet.c
+++ /dev/null
@@ -1,635 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 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/**
22 * @author Christian Grothoff
23 *
24 * @file plugin_dhtu_gnunet.c
25 * @brief plain IP based DHT network underlay
26 */
27#include "platform.h"
28#include "gnunet_dhtu_plugin.h"
29#include "gnunet_ats_service.h"
30#include "gnunet_core_service.h"
31#include "gnunet_transport_service.h"
32#include "gnunet_hello_lib.h"
33#include "gnunet_peerinfo_service.h"
34#include "gnunet_nse_service.h"
35
36
37/**
38 * Handle for a HELLO we're offering the transport.
39 */
40struct HelloHandle
41{
42 /**
43 * Kept in a DLL.
44 */
45 struct HelloHandle *next;
46
47 /**
48 * Kept in a DLL.
49 */
50 struct HelloHandle *prev;
51
52 /**
53 * Our plugin.
54 */
55 struct Plugin *plugin;
56
57 /**
58 * Offer handle.
59 */
60 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
61
62};
63
64
65/**
66 * Opaque handle that the underlay offers for our address to be used when
67 * sending messages to another peer.
68 */
69struct GNUNET_DHTU_Source
70{
71
72 /**
73 * Application context for this source.
74 */
75 void *app_ctx;
76
77};
78
79
80/**
81 * Opaque handle that the underlay offers for the target peer when sending
82 * messages to another peer.
83 */
84struct GNUNET_DHTU_Target
85{
86
87 /**
88 * Application context for this target.
89 */
90 void *app_ctx;
91
92 /**
93 * Our plugin with its environment.
94 */
95 struct Plugin *plugin;
96
97 /**
98 * CORE MQ to send messages to this peer.
99 */
100 struct GNUNET_MQ_Handle *mq;
101
102 /**
103 * Head of preferences expressed for this target.
104 */
105 struct GNUNET_DHTU_PreferenceHandle *ph_head;
106
107 /**
108 * Tail of preferences expressed for this target.
109 */
110 struct GNUNET_DHTU_PreferenceHandle *ph_tail;
111
112 /**
113 * ATS preference handle for this peer, or NULL.
114 */
115 struct GNUNET_ATS_ConnectivitySuggestHandle *csh;
116
117 /**
118 * Identity of this peer.
119 */
120 struct GNUNET_PeerIdentity pid;
121
122 /**
123 * Preference counter, length of the @a ph_head DLL.
124 */
125 unsigned int ph_count;
126
127};
128
129
130/**
131 * Opaque handle expressing a preference of the DHT to
132 * keep a particular target connected.
133 */
134struct GNUNET_DHTU_PreferenceHandle
135{
136 /**
137 * Kept in a DLL.
138 */
139 struct GNUNET_DHTU_PreferenceHandle *next;
140
141 /**
142 * Kept in a DLL.
143 */
144 struct GNUNET_DHTU_PreferenceHandle *prev;
145
146 /**
147 * Target a preference was expressed for.
148 */
149 struct GNUNET_DHTU_Target *target;
150};
151
152
153/**
154 * Closure for all plugin functions.
155 */
156struct Plugin
157{
158
159 /**
160 * Our "source" address. Traditional CORE API does not tell us which source
161 * it is, so they are all identical.
162 */
163 struct GNUNET_DHTU_Source src;
164
165 /**
166 * Callbacks into the DHT.
167 */
168 struct GNUNET_DHTU_PluginEnvironment *env;
169
170 /**
171 * Handle to the CORE service.
172 */
173 struct GNUNET_CORE_Handle *core;
174
175 /**
176 * Handle to ATS service.
177 */
178 struct GNUNET_ATS_ConnectivityHandle *ats;
179
180 /**
181 * Handle to the NSE service.
182 */
183 struct GNUNET_NSE_Handle *nse;
184
185 /**
186 * Watching for our address to change.
187 */
188 struct GNUNET_PEERINFO_NotifyContext *nc;
189
190 /**
191 * Hellos we are offering to transport.
192 */
193 struct HelloHandle *hh_head;
194
195 /**
196 * Hellos we are offering to transport.
197 */
198 struct HelloHandle *hh_tail;
199
200 /**
201 * Identity of this peer.
202 */
203 struct GNUNET_PeerIdentity my_identity;
204
205};
206
207
208/**
209 * Function called once a hello offer is completed.
210 *
211 * @param cls a `struct HelloHandle`
212 */
213static void
214hello_offered_cb (void *cls)
215{
216 struct HelloHandle *hh = cls;
217 struct Plugin *plugin = hh->plugin;
218
219 GNUNET_CONTAINER_DLL_remove (plugin->hh_head,
220 plugin->hh_tail,
221 hh);
222 GNUNET_free (hh);
223}
224
225
226#include "../peerinfo-tool/gnunet-peerinfo_plugins.c"
227
228
229/**
230 * Request creation of a session with a peer at the given @a address.
231 *
232 * @param cls closure (internal context for the plugin)
233 * @param pid target identity of the peer to connect to
234 * @param address target address to connect to
235 */
236static void
237gnunet_try_connect (void *cls,
238 const struct GNUNET_PeerIdentity *pid,
239 const char *address)
240{
241 struct Plugin *plugin = cls;
242 struct GNUNET_HELLO_Message *hello = NULL;
243 struct HelloHandle *hh;
244 struct GNUNET_CRYPTO_EddsaPublicKey pubkey;
245
246 (void) pid; /* will be needed with future address URIs */
247 if (GNUNET_OK !=
248 GNUNET_HELLO_parse_uri (address,
249 &pubkey,
250 &hello,
251 &GPI_plugins_find))
252 return;
253 hh = GNUNET_new (struct HelloHandle);
254 hh->plugin = plugin;
255 GNUNET_CONTAINER_DLL_insert (plugin->hh_head,
256 plugin->hh_tail,
257 hh);
258 hh->ohh = GNUNET_TRANSPORT_offer_hello (plugin->env->cfg,
259 &hello->header,
260 &hello_offered_cb,
261 hh);
262 GNUNET_free (hello);
263}
264
265
266/**
267 * Request underlay to keep the connection to @a target alive if possible.
268 * Hold may be called multiple times to express a strong preference to
269 * keep a connection, say because a @a target is in multiple tables.
270 *
271 * @param cls closure
272 * @param target connection to keep alive
273 */
274static struct GNUNET_DHTU_PreferenceHandle *
275gnunet_hold (void *cls,
276 struct GNUNET_DHTU_Target *target)
277{
278 struct Plugin *plugin = cls;
279 struct GNUNET_DHTU_PreferenceHandle *ph;
280
281 ph = GNUNET_new (struct GNUNET_DHTU_PreferenceHandle);
282 ph->target = target;
283 GNUNET_CONTAINER_DLL_insert (target->ph_head,
284 target->ph_tail,
285 ph);
286 target->ph_count++;
287 if (NULL != target->csh)
288 GNUNET_ATS_connectivity_suggest_cancel (target->csh);
289 target->csh
290 = GNUNET_ATS_connectivity_suggest (plugin->ats,
291 &target->pid,
292 target->ph_count);
293 return ph;
294}
295
296
297/**
298 * Do no long request underlay to keep the connection alive.
299 *
300 * @param cls closure
301 * @param target connection to keep alive
302 */
303static void
304gnunet_drop (struct GNUNET_DHTU_PreferenceHandle *ph)
305{
306 struct GNUNET_DHTU_Target *target = ph->target;
307 struct Plugin *plugin = target->plugin;
308
309 GNUNET_CONTAINER_DLL_remove (target->ph_head,
310 target->ph_tail,
311 ph);
312 target->ph_count--;
313 GNUNET_free (ph);
314 if (NULL != target->csh)
315 GNUNET_ATS_connectivity_suggest_cancel (target->csh);
316 if (0 == target->ph_count)
317 target->csh = NULL;
318 else
319 target->csh
320 = GNUNET_ATS_connectivity_suggest (plugin->ats,
321 &target->pid,
322 target->ph_count);
323}
324
325
326/**
327 * Send message to some other participant over the network. Note that
328 * sending is not guaranteeing that the other peer actually received the
329 * message. For any given @a target, the DHT must wait for the @a
330 * finished_cb to be called before calling send() again.
331 *
332 * @param cls closure (internal context for the plugin)
333 * @param target receiver identification
334 * @param msg message
335 * @param msg_size number of bytes in @a msg
336 * @param finished_cb function called once transmission is done
337 * (not called if @a target disconnects, then only the
338 * disconnect_cb is called).
339 * @param finished_cb_cls closure for @a finished_cb
340 */
341static void
342gnunet_send (void *cls,
343 struct GNUNET_DHTU_Target *target,
344 const void *msg,
345 size_t msg_size,
346 GNUNET_SCHEDULER_TaskCallback finished_cb,
347 void *finished_cb_cls)
348{
349 struct GNUNET_MQ_Envelope *env;
350 struct GNUNET_MessageHeader *cmsg;
351
352 env = GNUNET_MQ_msg_extra (cmsg,
353 msg_size,
354 GNUNET_MESSAGE_TYPE_DHT_CORE);
355 GNUNET_MQ_notify_sent (env,
356 finished_cb,
357 finished_cb_cls);
358 memcpy (&cmsg[1],
359 msg,
360 msg_size);
361 GNUNET_MQ_send (target->mq,
362 env);
363}
364
365
366/**
367 * Method called whenever a given peer connects.
368 *
369 * @param cls closure
370 * @param peer peer identity this notification is about
371 * @return closure associated with @a peer. given to mq callbacks and
372 * #GNUNET_CORE_DisconnectEventHandler
373 */
374static void *
375core_connect_cb (void *cls,
376 const struct GNUNET_PeerIdentity *peer,
377 struct GNUNET_MQ_Handle *mq)
378{
379 struct Plugin *plugin = cls;
380 struct GNUNET_DHTU_Target *target;
381
382 target = GNUNET_new (struct GNUNET_DHTU_Target);
383 target->plugin = plugin;
384 target->mq = mq;
385 target->pid = *peer;
386 plugin->env->connect_cb (plugin->env->cls,
387 target,
388 &target->pid,
389 &target->app_ctx);
390 return target;
391}
392
393
394/**
395 * Method called whenever a peer disconnects.
396 *
397 * @param cls closure
398 * @param peer peer identity this notification is about
399 * @param peer_cls closure associated with peer. given in
400 * #GNUNET_CORE_ConnectEventHandler
401 */
402static void
403core_disconnect_cb (void *cls,
404 const struct GNUNET_PeerIdentity *peer,
405 void *peer_cls)
406{
407 struct Plugin *plugin = cls;
408 struct GNUNET_DHTU_Target *target = peer_cls;
409
410 plugin->env->disconnect_cb (target->app_ctx);
411 if (NULL != target->csh)
412 GNUNET_ATS_connectivity_suggest_cancel (target->csh);
413 GNUNET_free (target);
414}
415
416
417/**
418 * Find the @a hello for our identity and then pass
419 * it to the DHT as a URL. Note that we only
420 * add addresses, never remove them, due to limitations
421 * of the current peerinfo/core/transport APIs.
422 * This will change with TNG.
423 *
424 * @param cls a `struct Plugin`
425 * @param peer id of the peer, NULL for last call
426 * @param hello hello message for the peer (can be NULL)
427 * @param error message
428 */
429static void
430peerinfo_cb (void *cls,
431 const struct GNUNET_PeerIdentity *peer,
432 const struct GNUNET_HELLO_Message *hello,
433 const char *err_msg)
434{
435 struct Plugin *plugin = cls;
436 char *addr;
437
438 if (NULL == hello)
439 return;
440 if (NULL == peer)
441 return;
442 if (0 !=
443 GNUNET_memcmp (peer,
444 &plugin->my_identity))
445 return;
446 addr = GNUNET_HELLO_compose_uri (hello,
447 &GPI_plugins_find);
448 if (NULL == addr)
449 return;
450 plugin->env->address_add_cb (plugin->env->cls,
451 addr,
452 &plugin->src,
453 &plugin->src.app_ctx);
454 GNUNET_free (addr);
455}
456
457
458/**
459 * Function called after #GNUNET_CORE_connect has succeeded (or failed
460 * for good). Note that the private key of the peer is intentionally
461 * not exposed here; if you need it, your process should try to read
462 * the private key file directly (which should work if you are
463 * authorized...). Implementations of this function must not call
464 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
465 * do this later).
466 *
467 * @param cls closure
468 * @param my_identity ID of this peer, NULL if we failed
469 */
470static void
471core_init_cb (void *cls,
472 const struct GNUNET_PeerIdentity *my_identity)
473{
474 struct Plugin *plugin = cls;
475
476 plugin->my_identity = *my_identity;
477 plugin->nc = GNUNET_PEERINFO_notify (plugin->env->cfg,
478 GNUNET_NO,
479 &peerinfo_cb,
480 plugin);
481}
482
483
484/**
485 * Anything goes, always return #GNUNET_OK.
486 *
487 * @param cls unused
488 * @param msg message to check
489 * @return #GNUNET_OK if all is fine
490 */
491static int
492check_core_message (void *cls,
493 const struct GNUNET_MessageHeader *msg)
494{
495 (void) cls;
496 (void) msg;
497 return GNUNET_OK;
498}
499
500
501/**
502 * Handle message from CORE for the DHT. Passes it to the
503 * DHT logic.
504 *
505 * @param cls a `struct GNUNET_DHTU_Target` of the sender
506 * @param msg the message we received
507 */
508static void
509handle_core_message (void *cls,
510 const struct GNUNET_MessageHeader *msg)
511{
512 struct GNUNET_DHTU_Target *origin = cls;
513 struct Plugin *plugin = origin->plugin;
514
515 plugin->env->receive_cb (plugin->env->cls,
516 &origin->app_ctx,
517 &plugin->src.app_ctx,
518 &msg[1],
519 ntohs (msg->size) - sizeof (*msg));
520}
521
522
523/**
524 * Callback to call when network size estimate is updated.
525 *
526 * @param cls closure
527 * @param timestamp time when the estimate was received from the server (or created by the server)
528 * @param logestimate the log(Base 2) value of the current network size estimate
529 * @param std_dev standard deviation for the estimate
530 */
531static void
532nse_cb (void *cls,
533 struct GNUNET_TIME_Absolute timestamp,
534 double logestimate,
535 double std_dev)
536{
537 struct Plugin *plugin = cls;
538
539 plugin->env->network_size_cb (plugin->env->cls,
540 timestamp,
541 logestimate,
542 std_dev);
543}
544
545
546/**
547 * Exit point from the plugin.
548 *
549 * @param cls closure (our `struct Plugin`)
550 * @return NULL
551 */
552void *
553libgnunet_plugin_dhtu_gnunet_done (void *cls)
554{
555 struct GNUNET_DHTU_PluginFunctions *api = cls;
556 struct Plugin *plugin = api->cls;
557 struct HelloHandle *hh;
558
559 while (NULL != (hh = plugin->hh_head))
560 {
561 GNUNET_CONTAINER_DLL_remove (plugin->hh_head,
562 plugin->hh_tail,
563 hh);
564 GNUNET_TRANSPORT_offer_hello_cancel (hh->ohh);
565 GNUNET_free (hh);
566 }
567 if (NULL != plugin->nse)
568 GNUNET_NSE_disconnect (plugin->nse);
569 plugin->env->network_size_cb (plugin->env->cls,
570 GNUNET_TIME_UNIT_FOREVER_ABS,
571 0.0,
572 0.0);
573 if (NULL != plugin->core)
574 GNUNET_CORE_disconnect (plugin->core);
575 if (NULL != plugin->ats)
576 GNUNET_ATS_connectivity_done (plugin->ats);
577 if (NULL != plugin->nc)
578 GNUNET_PEERINFO_notify_cancel (plugin->nc);
579 GPI_plugins_unload ();
580 GNUNET_free (plugin);
581 GNUNET_free (api);
582 return NULL;
583}
584
585
586/**
587 * Entry point for the plugin.
588 *
589 * @param cls closure (the `struct GNUNET_DHTU_PluginEnvironment`)
590 * @return the plugin's API
591 */
592void *
593libgnunet_plugin_dhtu_gnunet_init (void *cls)
594{
595 struct GNUNET_DHTU_PluginEnvironment *env = cls;
596 struct GNUNET_DHTU_PluginFunctions *api;
597 struct Plugin *plugin;
598 struct GNUNET_MQ_MessageHandler handlers[] = {
599 GNUNET_MQ_hd_var_size (core_message,
600 GNUNET_MESSAGE_TYPE_DHT_CORE,
601 struct GNUNET_MessageHeader,
602 NULL),
603 GNUNET_MQ_handler_end ()
604 };
605
606 plugin = GNUNET_new (struct Plugin);
607 plugin->env = env;
608 api = GNUNET_new (struct GNUNET_DHTU_PluginFunctions);
609 api->cls = plugin;
610 api->try_connect = &gnunet_try_connect;
611 api->hold = &gnunet_hold;
612 api->drop = &gnunet_drop;
613 api->send = &gnunet_send;
614 plugin->ats = GNUNET_ATS_connectivity_init (env->cfg);
615 plugin->core = GNUNET_CORE_connect (env->cfg,
616 plugin,
617 &core_init_cb,
618 &core_connect_cb,
619 &core_disconnect_cb,
620 handlers);
621 plugin->nse = GNUNET_NSE_connect (env->cfg,
622 &nse_cb,
623 plugin);
624 if ( (NULL == plugin->ats) ||
625 (NULL == plugin->core) ||
626 (NULL == plugin->nse) )
627 {
628 GNUNET_break (0);
629 GNUNET_free (api);
630 libgnunet_plugin_dhtu_gnunet_done (plugin);
631 return NULL;
632 }
633 GPI_plugins_load (env->cfg);
634 return api;
635}