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.c772
1 files changed, 0 insertions, 772 deletions
diff --git a/src/dhtu/plugin_dhtu_gnunet.c b/src/dhtu/plugin_dhtu_gnunet.c
deleted file mode 100644
index ee78858c8..000000000
--- a/src/dhtu/plugin_dhtu_gnunet.c
+++ /dev/null
@@ -1,772 +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 private key used by this underlay.
39 */
40struct GNUNET_DHTU_PrivateKey
41{
42 /**
43 * GNUnet uses eddsa for peers.
44 */
45 struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv;
46
47};
48
49GNUNET_NETWORK_STRUCT_BEGIN
50
51/**
52 * Handle for a public key used by this underlay.
53 */
54struct PublicKey
55{
56
57 /**
58 * Header.
59 */
60 struct GNUNET_DHTU_PublicKey header;
61
62 /**
63 * GNUnet uses eddsa for peers.
64 */
65 struct GNUNET_PeerIdentity peer_pub;
66
67};
68
69
70GNUNET_NETWORK_STRUCT_END
71
72
73/**
74 * Handle for a HELLO we're offering the transport.
75 */
76struct HelloHandle
77{
78 /**
79 * Kept in a DLL.
80 */
81 struct HelloHandle *next;
82
83 /**
84 * Kept in a DLL.
85 */
86 struct HelloHandle *prev;
87
88 /**
89 * Our plugin.
90 */
91 struct Plugin *plugin;
92
93 /**
94 * Offer handle.
95 */
96 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
97
98};
99
100
101/**
102 * Opaque handle that the underlay offers for our address to be used when
103 * sending messages to another peer.
104 */
105struct GNUNET_DHTU_Source
106{
107
108 /**
109 * Application context for this source.
110 */
111 void *app_ctx;
112
113 /**
114 * Hash position of this peer in the DHT.
115 */
116 struct GNUNET_DHTU_Hash my_id;
117
118 /**
119 * Private key of this peer.
120 */
121 struct GNUNET_DHTU_PrivateKey pk;
122
123};
124
125
126/**
127 * Opaque handle that the underlay offers for the target peer when sending
128 * messages to another peer.
129 */
130struct GNUNET_DHTU_Target
131{
132
133 /**
134 * Application context for this target.
135 */
136 void *app_ctx;
137
138 /**
139 * Our plugin with its environment.
140 */
141 struct Plugin *plugin;
142
143 /**
144 * CORE MQ to send messages to this peer.
145 */
146 struct GNUNET_MQ_Handle *mq;
147
148 /**
149 * Public key of the peer.
150 */
151 struct PublicKey pk;
152
153 /**
154 * Hash of the @a pk to identify position of the peer
155 * in the DHT.
156 */
157 struct GNUNET_DHTU_Hash peer_id;
158
159 /**
160 * Head of preferences expressed for this target.
161 */
162 struct GNUNET_DHTU_PreferenceHandle *ph_head;
163
164 /**
165 * Tail of preferences expressed for this target.
166 */
167 struct GNUNET_DHTU_PreferenceHandle *ph_tail;
168
169 /**
170 * ATS preference handle for this peer, or NULL.
171 */
172 struct GNUNET_ATS_ConnectivitySuggestHandle *csh;
173
174 /**
175 * Preference counter, length of the @a ph_head DLL.
176 */
177 unsigned int ph_count;
178
179};
180
181
182/**
183 * Opaque handle expressing a preference of the DHT to
184 * keep a particular target connected.
185 */
186struct GNUNET_DHTU_PreferenceHandle
187{
188 /**
189 * Kept in a DLL.
190 */
191 struct GNUNET_DHTU_PreferenceHandle *next;
192
193 /**
194 * Kept in a DLL.
195 */
196 struct GNUNET_DHTU_PreferenceHandle *prev;
197
198 /**
199 * Target a preference was expressed for.
200 */
201 struct GNUNET_DHTU_Target *target;
202};
203
204
205/**
206 * Closure for all plugin functions.
207 */
208struct Plugin
209{
210
211 /**
212 * Our "source" address. Traditional CORE API does not tell us which source
213 * it is, so they are all identical.
214 */
215 struct GNUNET_DHTU_Source src;
216
217 /**
218 * My identity.
219 */
220 struct GNUNET_PeerIdentity my_identity;
221
222 /**
223 * Callbacks into the DHT.
224 */
225 struct GNUNET_DHTU_PluginEnvironment *env;
226
227 /**
228 * Handle to the CORE service.
229 */
230 struct GNUNET_CORE_Handle *core;
231
232 /**
233 * Handle to ATS service.
234 */
235 struct GNUNET_ATS_ConnectivityHandle *ats;
236
237 /**
238 * Handle to the NSE service.
239 */
240 struct GNUNET_NSE_Handle *nse;
241
242 /**
243 * Watching for our address to change.
244 */
245 struct GNUNET_PEERINFO_NotifyContext *nc;
246
247 /**
248 * Hellos we are offering to transport.
249 */
250 struct HelloHandle *hh_head;
251
252 /**
253 * Hellos we are offering to transport.
254 */
255 struct HelloHandle *hh_tail;
256};
257
258
259/**
260 * Use our private key to sign a message.
261 *
262 * @param cls closure
263 * @param pk our private key to sign with
264 * @param purpose what to sign
265 * @param[out] signature, allocated on heap and returned
266 * @return -1 on error, otherwise number of bytes in @a sig
267 */
268static ssize_t
269ip_sign (void *cls,
270 const struct GNUNET_DHTU_PrivateKey *pk,
271 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
272 void **sig)
273{
274 struct GNUNET_CRYPTO_EddsaSignature *es;
275
276 es = GNUNET_new (struct GNUNET_CRYPTO_EddsaSignature);
277 GNUNET_CRYPTO_eddsa_sign_ (&pk->eddsa_priv,
278 purpose,
279 es);
280 *sig = es;
281 return sizeof (*es);
282}
283
284
285/**
286 * Verify signature in @a sig over @a purpose.
287 *
288 * @param cls closure
289 * @param pk public key to verify signature of
290 * @param purpose what was being signed
291 * @param sig signature data
292 * @param sig_size number of bytes in @a sig
293 * @return #GNUNET_OK if signature is valid
294 * #GNUNET_NO if signatures are not supported
295 * #GNUNET_SYSERR if signature is invalid
296 */
297static enum GNUNET_GenericReturnValue
298ip_verify (void *cls,
299 const struct GNUNET_DHTU_PublicKey *pk,
300 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
301 const void *sig,
302 size_t sig_size)
303{
304 const struct GNUNET_CRYPTO_EddsaSignature *es = sig;
305 const struct PublicKey *pub;
306
307 GNUNET_assert (sizeof (struct PublicKey) ==
308 ntohs (pk->size));
309 pub = (const struct PublicKey *) pk;
310 if (sizeof (*es) != sig_size)
311 {
312 GNUNET_break_op (0);
313 return GNUNET_SYSERR;
314 }
315 if (GNUNET_OK !=
316 GNUNET_CRYPTO_eddsa_verify_ (ntohl (purpose->purpose),
317 purpose,
318 es,
319 &pub->peer_pub.public_key))
320 {
321 GNUNET_break_op (0);
322 return GNUNET_SYSERR;
323 }
324 return GNUNET_OK;
325}
326
327
328/**
329 * Function called once a hello offer is completed.
330 *
331 * @param cls a `struct HelloHandle`
332 */
333static void
334hello_offered_cb (void *cls)
335{
336 struct HelloHandle *hh = cls;
337 struct Plugin *plugin = hh->plugin;
338
339 GNUNET_CONTAINER_DLL_remove (plugin->hh_head,
340 plugin->hh_tail,
341 hh);
342 GNUNET_free (hh);
343}
344
345
346#include "../peerinfo-tool/gnunet-peerinfo_plugins.c"
347
348
349/**
350 * Request creation of a session with a peer at the given @a address.
351 *
352 * @param cls closure (internal context for the plugin)
353 * @param address target address to connect to
354 */
355static void
356ip_try_connect (void *cls,
357 const char *address)
358{
359 struct Plugin *plugin = cls;
360 struct GNUNET_HELLO_Message *hello = NULL;
361 struct HelloHandle *hh;
362 struct GNUNET_CRYPTO_EddsaPublicKey pubkey;
363
364 if (GNUNET_OK !=
365 GNUNET_HELLO_parse_uri (address,
366 &pubkey,
367 &hello,
368 &GPI_plugins_find))
369 {
370 GNUNET_break (0);
371 return;
372 }
373
374 hh = GNUNET_new (struct HelloHandle);
375 hh->plugin = plugin;
376 GNUNET_CONTAINER_DLL_insert (plugin->hh_head,
377 plugin->hh_tail,
378 hh);
379 hh->ohh = GNUNET_TRANSPORT_offer_hello (plugin->env->cfg,
380 &hello->header,
381 &hello_offered_cb,
382 hh);
383 GNUNET_free (hello);
384}
385
386
387/**
388 * Request underlay to keep the connection to @a target alive if possible.
389 * Hold may be called multiple times to express a strong preference to
390 * keep a connection, say because a @a target is in multiple tables.
391 *
392 * @param cls closure
393 * @param target connection to keep alive
394 */
395static struct GNUNET_DHTU_PreferenceHandle *
396ip_hold (void *cls,
397 struct GNUNET_DHTU_Target *target)
398{
399 struct Plugin *plugin = cls;
400 struct GNUNET_DHTU_PreferenceHandle *ph;
401
402 ph = GNUNET_new (struct GNUNET_DHTU_PreferenceHandle);
403 ph->target = target;
404 GNUNET_CONTAINER_DLL_insert (target->ph_head,
405 target->ph_tail,
406 ph);
407 target->ph_count++;
408 if (NULL != target->csh)
409 GNUNET_ATS_connectivity_suggest_cancel (target->csh);
410 target->csh
411 = GNUNET_ATS_connectivity_suggest (plugin->ats,
412 &target->pk.peer_pub,
413 target->ph_count);
414 return ph;
415}
416
417
418/**
419 * Do no long request underlay to keep the connection alive.
420 *
421 * @param cls closure
422 * @param target connection to keep alive
423 */
424static void
425ip_drop (struct GNUNET_DHTU_PreferenceHandle *ph)
426{
427 struct GNUNET_DHTU_Target *target = ph->target;
428 struct Plugin *plugin = target->plugin;
429
430 GNUNET_CONTAINER_DLL_remove (target->ph_head,
431 target->ph_tail,
432 ph);
433 target->ph_count--;
434 GNUNET_free (ph);
435 if (NULL != target->csh)
436 GNUNET_ATS_connectivity_suggest_cancel (target->csh);
437 if (0 == target->ph_count)
438 target->csh = NULL;
439 else
440 target->csh
441 = GNUNET_ATS_connectivity_suggest (plugin->ats,
442 &target->pk.peer_pub,
443 target->ph_count);
444}
445
446
447/**
448 * Send message to some other participant over the network. Note that
449 * sending is not guaranteeing that the other peer actually received the
450 * message. For any given @a target, the DHT must wait for the @a
451 * finished_cb to be called before calling send() again.
452 *
453 * @param cls closure (internal context for the plugin)
454 * @param target receiver identification
455 * @param msg message
456 * @param msg_size number of bytes in @a msg
457 * @param finished_cb function called once transmission is done
458 * (not called if @a target disconnects, then only the
459 * disconnect_cb is called).
460 * @param finished_cb_cls closure for @a finished_cb
461 */
462static void
463ip_send (void *cls,
464 struct GNUNET_DHTU_Target *target,
465 const void *msg,
466 size_t msg_size,
467 GNUNET_SCHEDULER_TaskCallback finished_cb,
468 void *finished_cb_cls)
469{
470 struct GNUNET_MQ_Envelope *env;
471 struct GNUNET_MessageHeader *cmsg;
472
473 env = GNUNET_MQ_msg_extra (cmsg,
474 msg_size,
475 GNUNET_MESSAGE_TYPE_DHT_CORE);
476 GNUNET_MQ_notify_sent (env,
477 finished_cb,
478 finished_cb_cls);
479 memcpy (&cmsg[1],
480 msg,
481 msg_size);
482 GNUNET_MQ_send (target->mq,
483 env);
484}
485
486
487/**
488 * Method called whenever a given peer connects.
489 *
490 * @param cls closure
491 * @param peer peer identity this notification is about
492 * @return closure associated with @a peer. given to mq callbacks and
493 * #GNUNET_CORE_DisconnectEventHandler
494 */
495static void *
496core_connect_cb (void *cls,
497 const struct GNUNET_PeerIdentity *peer,
498 struct GNUNET_MQ_Handle *mq)
499{
500 struct Plugin *plugin = cls;
501 struct GNUNET_DHTU_Target *target;
502
503 target = GNUNET_new (struct GNUNET_DHTU_Target);
504 target->plugin = plugin;
505 target->mq = mq;
506 target->pk.header.size = htons (sizeof (struct PublicKey));
507 target->pk.peer_pub = *peer;
508 GNUNET_CRYPTO_hash (peer,
509 sizeof (struct GNUNET_PeerIdentity),
510 &target->peer_id.hc);
511 plugin->env->connect_cb (plugin->env->cls,
512 &target->pk.header,
513 &target->peer_id,
514 target,
515 &target->app_ctx);
516 return target;
517}
518
519
520/**
521 * Method called whenever a peer disconnects.
522 *
523 * @param cls closure
524 * @param peer peer identity this notification is about
525 * @param peer_cls closure associated with peer. given in
526 * #GNUNET_CORE_ConnectEventHandler
527 */
528static void
529core_disconnect_cb (void *cls,
530 const struct GNUNET_PeerIdentity *peer,
531 void *peer_cls)
532{
533 struct Plugin *plugin = cls;
534 struct GNUNET_DHTU_Target *target = peer_cls;
535
536 plugin->env->disconnect_cb (target->app_ctx);
537 if (NULL != target->csh)
538 GNUNET_ATS_connectivity_suggest_cancel (target->csh);
539 GNUNET_free (target);
540}
541
542
543/**
544 * Find the @a hello for our identity and then pass
545 * it to the DHT as a URL. Note that we only
546 * add addresses, never remove them, due to limitations
547 * of the current peerinfo/core/transport APIs.
548 * This will change with TNG.
549 *
550 * @param cls a `struct Plugin`
551 * @param peer id of the peer, NULL for last call
552 * @param hello hello message for the peer (can be NULL)
553 * @param error message
554 */
555static void
556peerinfo_cb (void *cls,
557 const struct GNUNET_PeerIdentity *peer,
558 const struct GNUNET_HELLO_Message *hello,
559 const char *err_msg)
560{
561 struct Plugin *plugin = cls;
562 char *addr;
563
564 if (NULL == hello)
565 return;
566 if (NULL == peer)
567 return;
568 if (0 !=
569 GNUNET_memcmp (peer,
570 &plugin->my_identity))
571 return;
572 addr = GNUNET_HELLO_compose_uri (hello,
573 &GPI_plugins_find);
574 if (NULL == addr)
575 return;
576 GNUNET_CRYPTO_hash (&plugin->my_identity,
577 sizeof (struct GNUNET_PeerIdentity),
578 &plugin->src.my_id.hc);
579 plugin->env->address_add_cb (plugin->env->cls,
580 &plugin->src.my_id,
581 &plugin->src.pk,
582 addr,
583 &plugin->src,
584 &plugin->src.app_ctx);
585 GNUNET_free (addr);
586}
587
588
589/**
590 * Function called after #GNUNET_CORE_connect has succeeded (or failed
591 * for good). Note that the private key of the peer is intentionally
592 * not exposed here; if you need it, your process should try to read
593 * the private key file directly (which should work if you are
594 * authorized...). Implementations of this function must not call
595 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
596 * do this later).
597 *
598 * @param cls closure
599 * @param my_identity ID of this peer, NULL if we failed
600 */
601static void
602core_init_cb (void *cls,
603 const struct GNUNET_PeerIdentity *my_identity)
604{
605 struct Plugin *plugin = cls;
606
607 plugin->my_identity = *my_identity;
608 plugin->nc = GNUNET_PEERINFO_notify (plugin->env->cfg,
609 GNUNET_NO,
610 &peerinfo_cb,
611 plugin);
612}
613
614
615/**
616 * Anything goes, always return #GNUNET_OK.
617 *
618 * @param cls unused
619 * @param msg message to check
620 * @return #GNUNET_OK if all is fine
621 */
622static int
623check_core_message (void *cls,
624 const struct GNUNET_MessageHeader *msg)
625{
626 (void) cls;
627 (void) msg;
628 return GNUNET_OK;
629}
630
631
632/**
633 * Handle message from CORE for the DHT. Passes it to the
634 * DHT logic.
635 *
636 * @param cls a `struct GNUNET_DHTU_Target` of the sender
637 * @param msg the message we received
638 */
639static void
640handle_core_message (void *cls,
641 const struct GNUNET_MessageHeader *msg)
642{
643 struct GNUNET_DHTU_Target *origin = cls;
644 struct Plugin *plugin = origin->plugin;
645
646 plugin->env->receive_cb (plugin->env->cls,
647 &origin->app_ctx,
648 &plugin->src.app_ctx,
649 &msg[1],
650 ntohs (msg->size) - sizeof (*msg));
651}
652
653
654/**
655 * Callback to call when network size estimate is updated.
656 *
657 * @param cls closure
658 * @param timestamp time when the estimate was received from the server (or created by the server)
659 * @param logestimate the log(Base 2) value of the current network size estimate
660 * @param std_dev standard deviation for the estimate
661 */
662static void
663nse_cb (void *cls,
664 struct GNUNET_TIME_Absolute timestamp,
665 double logestimate,
666 double std_dev)
667{
668 struct Plugin *plugin = cls;
669
670 plugin->env->network_size_cb (plugin->env->cls,
671 timestamp,
672 logestimate,
673 std_dev);
674}
675
676
677/**
678 * Exit point from the plugin.
679 *
680 * @param cls closure (our `struct Plugin`)
681 * @return NULL
682 */
683void *
684libgnunet_plugin_dhtu_gnunet_done (void *cls)
685{
686 struct GNUNET_DHTU_PluginFunctions *api = cls;
687 struct Plugin *plugin = api->cls;
688 struct HelloHandle *hh;
689
690 while (NULL != (hh = plugin->hh_head))
691 {
692 GNUNET_CONTAINER_DLL_remove (plugin->hh_head,
693 plugin->hh_tail,
694 hh);
695 GNUNET_TRANSPORT_offer_hello_cancel (hh->ohh);
696 GNUNET_free (hh);
697 }
698 if (NULL != plugin->nse)
699 GNUNET_NSE_disconnect (plugin->nse);
700 if (NULL != plugin->core)
701 GNUNET_CORE_disconnect (plugin->core);
702 if (NULL != plugin->ats)
703 GNUNET_ATS_connectivity_done (plugin->ats);
704 if (NULL != plugin->nc)
705 GNUNET_PEERINFO_notify_cancel (plugin->nc);
706 GPI_plugins_unload ();
707 GNUNET_free (plugin);
708 GNUNET_free (api);
709 return NULL;
710}
711
712
713/**
714 * Entry point for the plugin.
715 *
716 * @param cls closure (the `struct GNUNET_DHTU_PluginEnvironment`)
717 * @return the plugin's API
718 */
719void *
720libgnunet_plugin_dhtu_ip_init (void *cls)
721{
722 struct GNUNET_DHTU_PluginEnvironment *env = cls;
723 struct GNUNET_DHTU_PluginFunctions *api;
724 struct Plugin *plugin;
725 struct GNUNET_MQ_MessageHandler handlers[] = {
726 GNUNET_MQ_hd_var_size (core_message,
727 GNUNET_MESSAGE_TYPE_DHT_CORE,
728 struct GNUNET_MessageHeader,
729 NULL),
730 GNUNET_MQ_handler_end ()
731 };
732 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
733
734 pk = GNUNET_CRYPTO_eddsa_key_create_from_configuration (env->cfg);
735 if (NULL == pk)
736 {
737 GNUNET_break (0);
738 return NULL;
739 }
740 plugin = GNUNET_new (struct Plugin);
741 plugin->env = env;
742 plugin->src.pk.eddsa_priv = *pk;
743 GNUNET_free (pk);
744 api = GNUNET_new (struct GNUNET_DHTU_PluginFunctions);
745 api->cls = plugin;
746 api->sign = &ip_sign;
747 api->verify = &ip_verify;
748 api->try_connect = &ip_try_connect;
749 api->hold = &ip_hold;
750 api->drop = &ip_drop;
751 api->send = &ip_send;
752 plugin->ats = GNUNET_ATS_connectivity_init (env->cfg);
753 plugin->core = GNUNET_CORE_connect (env->cfg,
754 plugin,
755 &core_init_cb,
756 &core_connect_cb,
757 &core_disconnect_cb,
758 handlers);
759 plugin->nse = GNUNET_NSE_connect (env->cfg,
760 &nse_cb,
761 plugin);
762 if ( (NULL == plugin->ats) ||
763 (NULL == plugin->core) ||
764 (NULL == plugin->nse) )
765 {
766 GNUNET_break (0);
767 libgnunet_plugin_dhtu_gnunet_done (plugin);
768 return NULL;
769 }
770 GPI_plugins_load (env->cfg);
771 return api;
772}