aboutsummaryrefslogtreecommitdiff
path: root/src/dhtu
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 14:04:28 +0200
committerMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 14:04:28 +0200
commit14d9446a7d2bf06dc03ba35f361bf0bbcd9e7b44 (patch)
tree1bc74819bec16a2227ca24a4c76091f5bf08776c /src/dhtu
parentcc90a65e1a562889778d748c129bff2920e3dd21 (diff)
downloadgnunet-14d9446a7d2bf06dc03ba35f361bf0bbcd9e7b44.tar.gz
gnunet-14d9446a7d2bf06dc03ba35f361bf0bbcd9e7b44.zip
BUILD: Move dhtu to plugin
Diffstat (limited to 'src/dhtu')
-rw-r--r--src/dhtu/.gitignore1
-rw-r--r--src/dhtu/Makefile.am81
-rw-r--r--src/dhtu/dhtu.conf7
-rw-r--r--src/dhtu/meson.build61
-rw-r--r--src/dhtu/plugin_dhtu_gnunet.c603
-rw-r--r--src/dhtu/plugin_dhtu_ip.c1171
-rw-r--r--src/dhtu/test_dhtu_ip.c45
-rw-r--r--src/dhtu/testing_dhtu_cmd_send.c119
8 files changed, 0 insertions, 2088 deletions
diff --git a/src/dhtu/.gitignore b/src/dhtu/.gitignore
deleted file mode 100644
index 21f1a7c9b..000000000
--- a/src/dhtu/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
1test_dhtu_ip
diff --git a/src/dhtu/Makefile.am b/src/dhtu/Makefile.am
deleted file mode 100644
index cfe2a014f..000000000
--- a/src/dhtu/Makefile.am
+++ /dev/null
@@ -1,81 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4plugindir = $(libdir)/gnunet
5
6pkgcfgdir= $(pkgdatadir)/config.d/
7
8if USE_COVERAGE
9 AM_CFLAGS = --coverage -O0
10 XLIBS = -lgcov
11endif
12
13pkgcfg_DATA = \
14 dhtu.conf
15
16plugin_LTLIBRARIES = \
17 libgnunet_plugin_dhtu_gnunet.la
18
19if !OPENBSD
20plugin_LTLIBRARIES += libgnunet_plugin_dhtu_ip.la
21
22libgnunet_plugin_dhtu_ip_la_SOURCES = \
23 plugin_dhtu_ip.c
24libgnunet_plugin_dhtu_ip_la_LIBADD = \
25 $(top_builddir)/src/lib/util/libgnunetutil.la \
26 $(XLIBS) \
27 $(LTLIBINTL)
28libgnunet_plugin_dhtu_ip_la_LDFLAGS = \
29 $(GN_PLUGIN_LDFLAGS)
30endif
31
32
33libgnunet_plugin_dhtu_gnunet_la_SOURCES = \
34 plugin_dhtu_gnunet.c
35libgnunet_plugin_dhtu_gnunet_la_LIBADD = \
36 $(top_builddir)/src/core/libgnunetcore.la \
37 $(top_builddir)/src/peerstore/libgnunetpeerstore.la \
38 $(top_builddir)/src/transport/libgnunettransportapplication.la \
39 $(top_builddir)/src/lib/hello/libgnunethello.la \
40 $(top_builddir)/src/nse/libgnunetnse.la \
41 $(top_builddir)/src/lib/util/libgnunetutil.la \
42 $(XLIBS) \
43 $(LTLIBINTL)
44libgnunet_plugin_dhtu_gnunet_la_LDFLAGS = \
45 $(GN_PLUGIN_LDFLAGS)
46
47
48lib_LTLIBRARIES = \
49 libgnunettestingdhtu.la
50
51libgnunettestingdhtu_la_SOURCES = \
52 testing_dhtu_cmd_send.c
53libgnunettestingdhtu_la_LIBADD = \
54 $(top_builddir)/src/lib/testing/libgnunettesting.la \
55 $(top_builddir)/src/arm/libgnunetarm.la \
56 $(top_builddir)/src/lib/util/libgnunetutil.la \
57 $(LTLIBINTL)
58libgnunettestingdhtu_la_LDFLAGS = \
59 $(GN_LIB_LDFLAGS) \
60 -version-info 0:0:0
61
62
63
64test_dhtu_ip_SOURCES = \
65 test_dhtu_ip.c
66test_dhtu_ip_LDADD = \
67 $(top_builddir)/src/lib/testing/libgnunettesting.la \
68 $(top_builddir)/src/arm/libgnunetarm.la \
69 $(top_builddir)/src/lib/util/libgnunetutil.la
70
71check_PROGRAMS = \
72 test_dhtu_ip
73
74EXTRA_DIST = \
75 dhtu.conf
76
77if ENABLE_TEST_RUN
78AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
79TESTS = \
80 $(check_PROGRAMS)
81endif
diff --git a/src/dhtu/dhtu.conf b/src/dhtu/dhtu.conf
deleted file mode 100644
index ea5ade752..000000000
--- a/src/dhtu/dhtu.conf
+++ /dev/null
@@ -1,7 +0,0 @@
1[dhtu-gnunet]
2ENABLED = YES
3
4[dhtu-ip]
5ENABLED = NO
6NSE = 4
7UDP_PORT = 6666
diff --git a/src/dhtu/meson.build b/src/dhtu/meson.build
deleted file mode 100644
index b2525e782..000000000
--- a/src/dhtu/meson.build
+++ /dev/null
@@ -1,61 +0,0 @@
1libgnunetplugindhtuip_src = ['plugin_dhtu_ip.c']
2libgnunetplugindhtugnunet_src = ['plugin_dhtu_gnunet.c']
3
4configure_file(input : 'dhtu.conf',
5 output : 'dhtu.conf',
6 configuration : cdata,
7 install: true,
8 install_dir: pkgcfgdir)
9
10if get_option('monolith')
11 foreach p : libgnunetplugindhtuip_src + libgnunetplugindhtugnunet_src
12 gnunet_src += 'dhtu/' + p
13 endforeach
14 subdir_done()
15endif
16
17libgnunettestingdhtu = library('gnunettestingdhtu',
18 ['testing_dhtu_cmd_send.c'],
19 soversion: '0',
20 version: '0.0.0',
21 dependencies: [
22 libgnunetutil_dep,
23 libgnunetarm_dep,
24 libgnunettesting_dep
25 ],
26 include_directories: [incdir, configuration_inc],
27 install: true,
28 install_dir: get_option('libdir'))
29libgnunettestingdhtu_dep = declare_dependency(link_with : libgnunettestingdhtu)
30
31shared_module('gnunet_plugin_dhtu_ip',
32 libgnunetplugindhtuip_src,
33 dependencies: [libgnunetutil_dep, m_dep],
34 include_directories: [incdir, configuration_inc],
35 install: true,
36 install_dir: get_option('libdir')/'gnunet')
37
38shared_module('gnunet_plugin_dhtu_gnunet',
39 libgnunetplugindhtugnunet_src,
40 dependencies: [libgnunetutil_dep,
41 m_dep,
42 libgnunetcore_dep,
43 libgnunethello_dep,
44 libgnunetpeerstore_dep,
45 libgnunetnse_dep,
46 ],
47 include_directories: [incdir, configuration_inc],
48 install: true,
49 install_dir: get_option('libdir')/'gnunet')
50
51testdhtu_ip = executable('test_dhtu_ip',
52 ['test_dhtu_ip.c'],
53 dependencies: [libgnunetutil_dep,
54 libgnunettesting_dep],
55 include_directories: [incdir, configuration_inc],
56 install: false)
57
58test('test_dhtu_ip', testdhtu_ip, suite: 'dhtu',
59 workdir: meson.current_build_dir())
60
61
diff --git a/src/dhtu/plugin_dhtu_gnunet.c b/src/dhtu/plugin_dhtu_gnunet.c
deleted file mode 100644
index 75f466916..000000000
--- a/src/dhtu/plugin_dhtu_gnunet.c
+++ /dev/null
@@ -1,603 +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_core_service.h"
30#include "gnunet_transport_application_service.h"
31#include "gnunet_hello_uri_lib.h"
32#include "gnunet_peerstore_service.h"
33#include "gnunet_nse_service.h"
34
35/**
36 * Opaque handle that the underlay offers for our address to be used when
37 * sending messages to another peer.
38 */
39struct GNUNET_DHTU_Source
40{
41
42 /**
43 * Application context for this source.
44 */
45 void *app_ctx;
46
47};
48
49
50/**
51 * Opaque handle that the underlay offers for the target peer when sending
52 * messages to another peer.
53 */
54struct GNUNET_DHTU_Target
55{
56
57 /**
58 * Application context for this target.
59 */
60 void *app_ctx;
61
62 /**
63 * Our plugin with its environment.
64 */
65 struct Plugin *plugin;
66
67 /**
68 * CORE MQ to send messages to this peer.
69 */
70 struct GNUNET_MQ_Handle *mq;
71
72 /**
73 * Head of preferences expressed for this target.
74 */
75 struct GNUNET_DHTU_PreferenceHandle *ph_head;
76
77 /**
78 * Tail of preferences expressed for this target.
79 */
80 struct GNUNET_DHTU_PreferenceHandle *ph_tail;
81
82 /**
83 * Transport suggest handle.
84 */
85 struct GNUNET_TRANSPORT_ApplicationSuggestHandle *ash;
86
87 /**
88 * Identity of this peer.
89 */
90 struct GNUNET_PeerIdentity pid;
91
92 /**
93 * Preference counter, length of the @a ph_head DLL.
94 */
95 unsigned int ph_count;
96
97};
98
99
100/**
101 * Opaque handle expressing a preference of the DHT to
102 * keep a particular target connected.
103 */
104struct GNUNET_DHTU_PreferenceHandle
105{
106 /**
107 * Kept in a DLL.
108 */
109 struct GNUNET_DHTU_PreferenceHandle *next;
110
111 /**
112 * Kept in a DLL.
113 */
114 struct GNUNET_DHTU_PreferenceHandle *prev;
115
116 /**
117 * Target a preference was expressed for.
118 */
119 struct GNUNET_DHTU_Target *target;
120};
121
122
123/**
124 * Closure for all plugin functions.
125 */
126struct Plugin
127{
128
129 /**
130 * Our "source" address. Traditional CORE API does not tell us which source
131 * it is, so they are all identical.
132 */
133 struct GNUNET_DHTU_Source src;
134
135 /**
136 * Callbacks into the DHT.
137 */
138 struct GNUNET_DHTU_PluginEnvironment *env;
139
140 /**
141 * Handle to the PEERSTORE service.
142 */
143 struct GNUNET_PEERSTORE_Handle *peerstore;
144
145 /**
146 * Handle to the CORE service.
147 */
148 struct GNUNET_CORE_Handle *core;
149
150 /**
151 * Handle to Transport service.
152 */
153 struct GNUNET_TRANSPORT_ApplicationHandle *transport;
154
155 /**
156 * Handle to the NSE service.
157 */
158 struct GNUNET_NSE_Handle *nse;
159
160 /**
161 * Our peerstore notification context. We use notification
162 * to instantly learn about new peers as they are discovered.
163 */
164 struct GNUNET_PEERSTORE_NotifyContext *peerstore_notify;
165
166 /**
167 * Identity of this peer.
168 */
169 struct GNUNET_PeerIdentity my_identity;
170
171 /**
172 * Our private key.
173 */
174 struct GNUNET_CRYPTO_EddsaPrivateKey *my_priv;
175
176};
177
178
179//#include "../peerinfo-tool/gnunet-peerinfo_plugins.c"
180
181
182/**
183 * Request creation of a session with a peer at the given @a address.
184 *
185 * @param cls closure (internal context for the plugin)
186 * @param pid target identity of the peer to connect to
187 * @param address target address to connect to
188 */
189static void
190gnunet_try_connect (void *cls,
191 const struct GNUNET_PeerIdentity *pid,
192 const char *address)
193{
194 struct Plugin *plugin = cls;
195 enum GNUNET_NetworkType nt = 0;
196 char *addr;
197 const char *eou;
198 int pfx_len;
199
200 eou = strstr (address,
201 "://");
202 if (NULL == eou)
203 {
204 GNUNET_break (0);
205 return;
206 }
207 pfx_len = eou - address;
208 eou += 3;
209 GNUNET_asprintf (&addr,
210 "%.*s-%s",
211 pfx_len,
212 address,
213 eou);
214 GNUNET_TRANSPORT_application_validate (plugin->transport,
215 pid,
216 nt,
217 addr);
218 GNUNET_free (addr);
219}
220
221
222/**
223 * Request underlay to keep the connection to @a target alive if possible.
224 * Hold may be called multiple times to express a strong preference to
225 * keep a connection, say because a @a target is in multiple tables.
226 *
227 * @param cls closure
228 * @param target connection to keep alive
229 */
230static struct GNUNET_DHTU_PreferenceHandle *
231gnunet_hold (void *cls,
232 struct GNUNET_DHTU_Target *target)
233{
234 struct Plugin *plugin = cls;
235 struct GNUNET_DHTU_PreferenceHandle *ph;
236
237 ph = GNUNET_new (struct GNUNET_DHTU_PreferenceHandle);
238 ph->target = target;
239 GNUNET_CONTAINER_DLL_insert (target->ph_head,
240 target->ph_tail,
241 ph);
242 target->ph_count++;
243 if (NULL != target->ash)
244 GNUNET_TRANSPORT_application_suggest_cancel (target->ash);
245 target->ash
246 = GNUNET_TRANSPORT_application_suggest (plugin->transport,
247 &target->pid,
248 GNUNET_MQ_PRIO_BEST_EFFORT,
249 GNUNET_BANDWIDTH_ZERO);
250 return ph;
251}
252
253
254/**
255 * Do no long request underlay to keep the connection alive.
256 *
257 * @param cls closure
258 * @param target connection to keep alive
259 */
260static void
261gnunet_drop (struct GNUNET_DHTU_PreferenceHandle *ph)
262{
263 struct GNUNET_DHTU_Target *target = ph->target;
264 struct Plugin *plugin = target->plugin;
265
266 GNUNET_CONTAINER_DLL_remove (target->ph_head,
267 target->ph_tail,
268 ph);
269 target->ph_count--;
270 GNUNET_free (ph);
271 if (NULL != target->ash)
272 GNUNET_TRANSPORT_application_suggest_cancel (target->ash);
273 if (0 == target->ph_count)
274 target->ash = NULL;
275 else
276 target->ash
277 = GNUNET_TRANSPORT_application_suggest (plugin->transport,
278 &target->pid,
279 GNUNET_MQ_PRIO_BEST_EFFORT,
280 GNUNET_BANDWIDTH_ZERO);
281}
282
283
284/**
285 * Send message to some other participant over the network. Note that
286 * sending is not guaranteeing that the other peer actually received the
287 * message. For any given @a target, the DHT must wait for the @a
288 * finished_cb to be called before calling send() again.
289 *
290 * @param cls closure (internal context for the plugin)
291 * @param target receiver identification
292 * @param msg message
293 * @param msg_size number of bytes in @a msg
294 * @param finished_cb function called once transmission is done
295 * (not called if @a target disconnects, then only the
296 * disconnect_cb is called).
297 * @param finished_cb_cls closure for @a finished_cb
298 */
299static void
300gnunet_send (void *cls,
301 struct GNUNET_DHTU_Target *target,
302 const void *msg,
303 size_t msg_size,
304 GNUNET_SCHEDULER_TaskCallback finished_cb,
305 void *finished_cb_cls)
306{
307 struct GNUNET_MQ_Envelope *env;
308 struct GNUNET_MessageHeader *cmsg;
309
310 env = GNUNET_MQ_msg_extra (cmsg,
311 msg_size,
312 GNUNET_MESSAGE_TYPE_DHT_CORE);
313 GNUNET_MQ_notify_sent (env,
314 finished_cb,
315 finished_cb_cls);
316 memcpy (&cmsg[1],
317 msg,
318 msg_size);
319 GNUNET_MQ_send (target->mq,
320 env);
321}
322
323
324/**
325 * Method called whenever a given peer connects.
326 *
327 * @param cls closure
328 * @param peer peer identity this notification is about
329 * @return closure associated with @a peer. given to mq callbacks and
330 * #GNUNET_CORE_DisconnectEventHandler
331 */
332static void *
333core_connect_cb (void *cls,
334 const struct GNUNET_PeerIdentity *peer,
335 struct GNUNET_MQ_Handle *mq)
336{
337 struct Plugin *plugin = cls;
338 struct GNUNET_DHTU_Target *target;
339
340 target = GNUNET_new (struct GNUNET_DHTU_Target);
341 target->plugin = plugin;
342 target->mq = mq;
343 target->pid = *peer;
344 plugin->env->connect_cb (plugin->env->cls,
345 target,
346 &target->pid,
347 &target->app_ctx);
348 return target;
349}
350
351
352/**
353 * Method called whenever a peer disconnects.
354 *
355 * @param cls closure
356 * @param peer peer identity this notification is about
357 * @param peer_cls closure associated with peer. given in
358 * #GNUNET_CORE_ConnectEventHandler
359 */
360static void
361core_disconnect_cb (void *cls,
362 const struct GNUNET_PeerIdentity *peer,
363 void *peer_cls)
364{
365 struct Plugin *plugin = cls;
366 struct GNUNET_DHTU_Target *target = peer_cls;
367
368 plugin->env->disconnect_cb (target->app_ctx);
369 if (NULL != target->ash)
370 GNUNET_TRANSPORT_application_suggest_cancel (target->ash);
371 GNUNET_free (target);
372}
373
374
375static void
376add_addr (void *cls,
377 const char *addr)
378{
379 struct Plugin *plugin = cls;
380
381 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG ,
382 "peerinfo_cb addr %s\n",
383 addr);
384 plugin->env->address_add_cb (plugin->env->cls,
385 addr,
386 &plugin->src,
387 &plugin->src.app_ctx);
388}
389
390
391/**
392 * Find the @a hello for our identity and then pass
393 * it to the DHT as a URL. Note that we only
394 * add addresses, never remove them, due to limitations
395 * of the current peerinfo/core/transport APIs.
396 * This will change with TNG.
397 *
398 * @param cls a `struct Plugin`
399 * @param peer id of the peer, NULL for last call
400 * @param hello hello message for the peer (can be NULL)
401 * @param err_msg message
402 */
403static void
404peerinfo_cb (void *cls,
405 const struct GNUNET_PeerIdentity *peer,
406 const struct GNUNET_MessageHeader *hello,
407 const char *emsg)
408{
409 struct Plugin *plugin = cls;
410 struct GNUNET_HELLO_Builder *builder;
411
412 if (NULL == hello)
413 return;
414 if (NULL == peer)
415 return;
416 if (0 !=
417 GNUNET_memcmp (peer,
418 &plugin->my_identity))
419 return;
420 builder = GNUNET_HELLO_builder_from_msg (hello);
421 GNUNET_HELLO_builder_iterate (builder,
422 (struct GNUNET_PeerIdentity *) peer,
423 add_addr,
424 plugin);
425 GNUNET_HELLO_builder_free (builder);
426}
427
428
429/**
430 * Function called after #GNUNET_CORE_connect has succeeded (or failed
431 * for good). Note that the private key of the peer is intentionally
432 * not exposed here; if you need it, your process should try to read
433 * the private key file directly (which should work if you are
434 * authorized...). Implementations of this function must not call
435 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
436 * do this later).
437 *
438 * @param cls closure
439 * @param my_identity ID of this peer, NULL if we failed
440 */
441static void
442 core_init_cb (void *cls,
443 const struct GNUNET_PeerIdentity *my_identity)
444{
445 struct Plugin *plugin = cls;
446
447 plugin->my_identity = *my_identity;
448 plugin->peerstore_notify =
449 GNUNET_PEERSTORE_hello_changed_notify (plugin->peerstore,
450 GNUNET_NO,
451 &peerinfo_cb,
452 plugin);
453}
454
455
456/**
457 * Anything goes, always return #GNUNET_OK.
458 *
459 * @param cls unused
460 * @param msg message to check
461 * @return #GNUNET_OK if all is fine
462 */
463static int
464check_core_message (void *cls,
465 const struct GNUNET_MessageHeader *msg)
466{
467 (void) cls;
468 (void) msg;
469 return GNUNET_OK;
470}
471
472
473/**
474 * Handle message from CORE for the DHT. Passes it to the
475 * DHT logic.
476 *
477 * @param cls a `struct GNUNET_DHTU_Target` of the sender
478 * @param msg the message we received
479 */
480static void
481handle_core_message (void *cls,
482 const struct GNUNET_MessageHeader *msg)
483{
484 struct GNUNET_DHTU_Target *origin = cls;
485 struct Plugin *plugin = origin->plugin;
486
487 plugin->env->receive_cb (plugin->env->cls,
488 &origin->app_ctx,
489 &plugin->src.app_ctx,
490 &msg[1],
491 ntohs (msg->size) - sizeof (*msg));
492}
493
494
495/**
496 * Callback to call when network size estimate is updated.
497 *
498 * @param cls closure
499 * @param timestamp time when the estimate was received from the server (or created by the server)
500 * @param logestimate the log(Base 2) value of the current network size estimate
501 * @param std_dev standard deviation for the estimate
502 */
503static void
504nse_cb (void *cls,
505 struct GNUNET_TIME_Absolute timestamp,
506 double logestimate,
507 double std_dev)
508{
509 struct Plugin *plugin = cls;
510
511 plugin->env->network_size_cb (plugin->env->cls,
512 timestamp,
513 logestimate,
514 std_dev);
515}
516
517
518/**
519 * Exit point from the plugin.
520 *
521 * @param cls closure (our `struct Plugin`)
522 * @return NULL
523 */
524void *
525libgnunet_plugin_dhtu_gnunet_done (void *cls)
526{
527 struct GNUNET_DHTU_PluginFunctions *api = cls;
528 struct Plugin *plugin = api->cls;
529
530 if (NULL != plugin->nse)
531 GNUNET_NSE_disconnect (plugin->nse);
532 plugin->env->network_size_cb (plugin->env->cls,
533 GNUNET_TIME_UNIT_FOREVER_ABS,
534 0.0,
535 0.0);
536 if (NULL != plugin->core)
537 GNUNET_CORE_disconnect (plugin->core);
538 if (NULL != plugin->transport)
539 GNUNET_TRANSPORT_application_done (plugin->transport);
540 if (NULL != plugin->peerstore_notify)
541 GNUNET_PEERSTORE_hello_changed_notify_cancel (plugin->peerstore_notify);
542 if (NULL != plugin->peerstore)
543 GNUNET_PEERSTORE_disconnect (plugin->peerstore, GNUNET_YES);
544 //GPI_plugins_unload ();
545 GNUNET_free (plugin->my_priv);
546 GNUNET_free (plugin);
547 GNUNET_free (api);
548 return NULL;
549}
550
551
552/**
553 * Entry point for the plugin.
554 *
555 * @param cls closure (the `struct GNUNET_DHTU_PluginEnvironment`)
556 * @return the plugin's API
557 */
558void *
559libgnunet_plugin_dhtu_gnunet_init (void *cls)
560{
561 struct GNUNET_DHTU_PluginEnvironment *env = cls;
562 struct GNUNET_DHTU_PluginFunctions *api;
563 struct Plugin *plugin;
564 struct GNUNET_MQ_MessageHandler handlers[] = {
565 GNUNET_MQ_hd_var_size (core_message,
566 GNUNET_MESSAGE_TYPE_DHT_CORE,
567 struct GNUNET_MessageHeader,
568 NULL),
569 GNUNET_MQ_handler_end ()
570 };
571
572 plugin = GNUNET_new (struct Plugin);
573 plugin->my_priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (env->cfg);
574 plugin->env = env;
575 api = GNUNET_new (struct GNUNET_DHTU_PluginFunctions);
576 api->cls = plugin;
577 api->try_connect = &gnunet_try_connect;
578 api->hold = &gnunet_hold;
579 api->drop = &gnunet_drop;
580 api->send = &gnunet_send;
581 plugin->peerstore = GNUNET_PEERSTORE_connect (env->cfg);
582 plugin->transport = GNUNET_TRANSPORT_application_init (env->cfg);
583 plugin->core = GNUNET_CORE_connect (env->cfg,
584 plugin,
585 &core_init_cb,
586 &core_connect_cb,
587 &core_disconnect_cb,
588 handlers);
589 plugin->nse = GNUNET_NSE_connect (env->cfg,
590 &nse_cb,
591 plugin);
592 if ( (NULL == plugin->transport) ||
593 (NULL == plugin->core) ||
594 (NULL == plugin->nse) )
595 {
596 GNUNET_break (0);
597 GNUNET_free (api);
598 libgnunet_plugin_dhtu_gnunet_done (plugin);
599 return NULL;
600 }
601 //GPI_plugins_load (env->cfg);
602 return api;
603}
diff --git a/src/dhtu/plugin_dhtu_ip.c b/src/dhtu/plugin_dhtu_ip.c
deleted file mode 100644
index 06d0f0f60..000000000
--- a/src/dhtu/plugin_dhtu_ip.c
+++ /dev/null
@@ -1,1171 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021, 2022 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_ip.c
25 * @brief plain IP based DHT network underlay
26 */
27#include "platform.h"
28#include "gnunet_dhtu_plugin.h"
29
30/**
31 * How frequently should we re-scan our local interfaces for IPs?
32 */
33#define SCAN_FREQ GNUNET_TIME_UNIT_MINUTES
34
35/**
36 * Maximum number of concurrently active destinations to support.
37 */
38#define MAX_DESTS 256
39
40
41/**
42 * Opaque handle that the underlay offers for our address to be used when
43 * sending messages to another peer.
44 */
45struct GNUNET_DHTU_Source
46{
47
48 /**
49 * Kept in a DLL.
50 */
51 struct GNUNET_DHTU_Source *next;
52
53 /**
54 * Kept in a DLL.
55 */
56 struct GNUNET_DHTU_Source *prev;
57
58 /**
59 * Application context for this source.
60 */
61 void *app_ctx;
62
63 /**
64 * Address in URL form ("ip+udp://$PID/$IP:$PORT")
65 */
66 char *address;
67
68 /**
69 * My actual address.
70 */
71 struct sockaddr_storage addr;
72
73 /**
74 * Number of bytes in @a addr.
75 */
76 socklen_t addrlen;
77
78 /**
79 * Last generation this address was observed.
80 */
81 unsigned int scan_generation;
82
83};
84
85
86/**
87 * Opaque handle that the underlay offers for the target peer when sending
88 * messages to another peer.
89 */
90struct GNUNET_DHTU_Target
91{
92
93 /**
94 * Kept in a DLL.
95 */
96 struct GNUNET_DHTU_Target *next;
97
98 /**
99 * Kept in a DLL.
100 */
101 struct GNUNET_DHTU_Target *prev;
102
103 /**
104 * Application context for this target.
105 */
106 void *app_ctx;
107
108 /**
109 * Head of preferences expressed for this target.
110 */
111 struct GNUNET_DHTU_PreferenceHandle *ph_head;
112
113 /**
114 * Tail of preferences expressed for this target.
115 */
116 struct GNUNET_DHTU_PreferenceHandle *ph_tail;
117
118 /**
119 * Peer's identity.
120 */
121 struct GNUNET_PeerIdentity pid;
122
123 /**
124 * Target IP address.
125 */
126 struct sockaddr_storage addr;
127
128 /**
129 * Number of bytes in @a addr.
130 */
131 socklen_t addrlen;
132
133 /**
134 * Preference counter, length of the @a ph_head DLL.
135 */
136 unsigned int ph_count;
137
138};
139
140/**
141 * Opaque handle expressing a preference of the DHT to
142 * keep a particular target connected.
143 */
144struct GNUNET_DHTU_PreferenceHandle
145{
146 /**
147 * Kept in a DLL.
148 */
149 struct GNUNET_DHTU_PreferenceHandle *next;
150
151 /**
152 * Kept in a DLL.
153 */
154 struct GNUNET_DHTU_PreferenceHandle *prev;
155
156 /**
157 * Target a preference was expressed for.
158 */
159 struct GNUNET_DHTU_Target *target;
160};
161
162
163/**
164 * Closure for all plugin functions.
165 */
166struct Plugin
167{
168 /**
169 * Callbacks into the DHT.
170 */
171 struct GNUNET_DHTU_PluginEnvironment *env;
172
173 /**
174 * Head of sources where we receive traffic.
175 */
176 struct GNUNET_DHTU_Source *src_head;
177
178 /**
179 * Tail of sources where we receive traffic.
180 */
181 struct GNUNET_DHTU_Source *src_tail;
182
183 /**
184 * Head of destinations that are active. Sorted by
185 * last use, with latest used at the head.
186 */
187 struct GNUNET_DHTU_Target *dst_head;
188
189 /**
190 * Tail of destinations that are active.
191 */
192 struct GNUNET_DHTU_Target *dst_tail;
193
194 /**
195 * Map from hashes of sockaddrs to targets.
196 */
197 struct GNUNET_CONTAINER_MultiHashMap *dsts;
198
199 /**
200 * Task that scans for IP address changes.
201 */
202 struct GNUNET_SCHEDULER_Task *scan_task;
203
204 /**
205 * Task that reads incoming UDP packets.
206 */
207 struct GNUNET_SCHEDULER_Task *read_task;
208
209 /**
210 * Port we bind to.
211 */
212 char *port;
213
214 /**
215 * My UDP socket.
216 */
217 struct GNUNET_NETWORK_Handle *sock;
218
219 /**
220 * My identity.
221 */
222 struct GNUNET_PeerIdentity my_id;
223
224 /**
225 * How often have we scanned for IPs?
226 */
227 unsigned int scan_generation;
228
229 /**
230 * Port as a 16-bit value.
231 */
232 uint16_t port16;
233};
234
235
236/**
237 * Create a target to which we may send traffic.
238 *
239 * @param plugin our plugin
240 * @param pid presumed identity of the target
241 * @param addr target address
242 * @param addrlen number of bytes in @a addr
243 * @return new target object
244 */
245static struct GNUNET_DHTU_Target *
246create_target (struct Plugin *plugin,
247 const struct GNUNET_PeerIdentity *pid,
248 const struct sockaddr *addr,
249 socklen_t addrlen)
250{
251 struct GNUNET_DHTU_Target *dst;
252
253 if (MAX_DESTS <=
254 GNUNET_CONTAINER_multihashmap_size (plugin->dsts))
255 {
256 struct GNUNET_HashCode key;
257
258 dst = NULL;
259 for (struct GNUNET_DHTU_Target *pos = plugin->dst_head;
260 NULL != pos;
261 pos = pos->next)
262 {
263 /* >= here assures we remove oldest entries first */
264 if ( (NULL == dst) ||
265 (dst->ph_count >= pos->ph_count) )
266 dst = pos;
267 }
268 GNUNET_assert (NULL != dst);
269 plugin->env->disconnect_cb (dst->app_ctx);
270 GNUNET_CRYPTO_hash (&dst->addr,
271 dst->addrlen,
272 &key);
273 GNUNET_assert (GNUNET_YES ==
274 GNUNET_CONTAINER_multihashmap_remove (plugin->dsts,
275 &key,
276 dst));
277 GNUNET_CONTAINER_DLL_remove (plugin->dst_head,
278 plugin->dst_tail,
279 dst);
280 GNUNET_assert (NULL == dst->ph_head);
281 GNUNET_free (dst);
282 }
283 dst = GNUNET_new (struct GNUNET_DHTU_Target);
284 dst->addrlen = addrlen;
285 dst->pid = *pid;
286 memcpy (&dst->addr,
287 addr,
288 addrlen);
289 GNUNET_CONTAINER_DLL_insert (plugin->dst_head,
290 plugin->dst_tail,
291 dst);
292 plugin->env->connect_cb (plugin->env->cls,
293 dst,
294 &dst->pid,
295 &dst->app_ctx);
296 return dst;
297}
298
299
300/**
301 * Find target matching @a addr. If none exists,
302 * create one!
303 *
304 * @param plugin the plugin handle
305 * @param pid presumed identity of the target
306 * @param addr socket address to find
307 * @param addrlen number of bytes in @a addr
308 * @return matching target object
309 */
310static struct GNUNET_DHTU_Target *
311find_target (struct Plugin *plugin,
312 const struct GNUNET_PeerIdentity *pid,
313 const void *addr,
314 size_t addrlen)
315{
316 struct GNUNET_HashCode key;
317 struct GNUNET_DHTU_Target *dst;
318
319 GNUNET_CRYPTO_hash (addr,
320 addrlen,
321 &key);
322 dst = GNUNET_CONTAINER_multihashmap_get (plugin->dsts,
323 &key);
324 if (NULL == dst)
325 {
326 dst = create_target (plugin,
327 pid,
328 (const struct sockaddr *) addr,
329 addrlen);
330 GNUNET_assert (GNUNET_YES ==
331 GNUNET_CONTAINER_multihashmap_put (
332 plugin->dsts,
333 &key,
334 dst,
335 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
336 }
337 else
338 {
339 /* move to head of DLL */
340 GNUNET_CONTAINER_DLL_remove (plugin->dst_head,
341 plugin->dst_tail,
342 dst);
343 GNUNET_CONTAINER_DLL_insert (plugin->dst_head,
344 plugin->dst_tail,
345 dst);
346
347 }
348 return dst;
349}
350
351
352/**
353 * Request creation of a session with a peer at the given @a address.
354 *
355 * @param cls closure (internal context for the plugin)
356 * @param pid identity of the target peer
357 * @param address target address to connect to
358 */
359static void
360ip_try_connect (void *cls,
361 const struct GNUNET_PeerIdentity *pid,
362 const char *address)
363{
364 struct Plugin *plugin = cls;
365 char *colon;
366 const char *port;
367 char *addr;
368 struct addrinfo hints = {
369 .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV
370 };
371 struct addrinfo *result = NULL;
372
373 if (0 !=
374 strncmp (address,
375 "ip+",
376 strlen ("ip+")))
377 return;
378 address += strlen ("ip+");
379 if (0 !=
380 strncmp (address,
381 "udp://",
382 strlen ("udp://")))
383 return;
384 address += strlen ("udp://");
385 addr = GNUNET_strdup (address);
386 colon = strchr (addr, ':');
387 if (NULL == colon)
388 {
389 port = plugin->port;
390 }
391 else
392 {
393 *colon = '\0';
394 port = colon + 1;
395 }
396 if (0 !=
397 getaddrinfo (addr,
398 port,
399 &hints,
400 &result))
401 {
402 GNUNET_break (0);
403 GNUNET_free (addr);
404 return;
405 }
406 GNUNET_free (addr);
407 (void) find_target (plugin,
408 pid,
409 result->ai_addr,
410 result->ai_addrlen);
411 freeaddrinfo (result);
412}
413
414
415/**
416 * Request underlay to keep the connection to @a target alive if possible.
417 * Hold may be called multiple times to express a strong preference to
418 * keep a connection, say because a @a target is in multiple tables.
419 *
420 * @param cls closure
421 * @param target connection to keep alive
422 */
423static struct GNUNET_DHTU_PreferenceHandle *
424ip_hold (void *cls,
425 struct GNUNET_DHTU_Target *target)
426{
427 struct GNUNET_DHTU_PreferenceHandle *ph;
428
429 ph = GNUNET_new (struct GNUNET_DHTU_PreferenceHandle);
430 ph->target = target;
431 GNUNET_CONTAINER_DLL_insert (target->ph_head,
432 target->ph_tail,
433 ph);
434 target->ph_count++;
435 return ph;
436}
437
438
439/**
440 * Do no long request underlay to keep the connection alive.
441 *
442 * @param cls closure
443 * @param target connection to keep alive
444 */
445static void
446ip_drop (struct GNUNET_DHTU_PreferenceHandle *ph)
447{
448 struct GNUNET_DHTU_Target *target = ph->target;
449
450 GNUNET_CONTAINER_DLL_remove (target->ph_head,
451 target->ph_tail,
452 ph);
453 target->ph_count--;
454 GNUNET_free (ph);
455}
456
457
458/**
459 * Send message to some other participant over the network. Note that
460 * sending is not guaranteeing that the other peer actually received the
461 * message. For any given @a target, the DHT must wait for the @a
462 * finished_cb to be called before calling send() again.
463 *
464 * @param cls closure (internal context for the plugin)
465 * @param target receiver identification
466 * @param msg message
467 * @param msg_size number of bytes in @a msg
468 * @param finished_cb function called once transmission is done
469 * (not called if @a target disconnects, then only the
470 * disconnect_cb is called).
471 * @param finished_cb_cls closure for @a finished_cb
472 */
473static void
474ip_send (void *cls,
475 struct GNUNET_DHTU_Target *target,
476 const void *msg,
477 size_t msg_size,
478 GNUNET_SCHEDULER_TaskCallback finished_cb,
479 void *finished_cb_cls)
480{
481 struct Plugin *plugin = cls;
482 char buf[sizeof (plugin->my_id) + msg_size];
483
484 memcpy (buf,
485 &plugin->my_id,
486 sizeof (plugin->my_id));
487 memcpy (&buf[sizeof (plugin->my_id)],
488 msg,
489 msg_size);
490 GNUNET_NETWORK_socket_sendto (plugin->sock,
491 buf,
492 sizeof (buf),
493 (const struct sockaddr *) &target->addr,
494 target->addrlen);
495 finished_cb (finished_cb_cls);
496}
497
498
499/**
500 * Create a new source on which we may be receiving traffic.
501 *
502 * @param plugin our plugin
503 * @param addr our address
504 * @param addrlen number of bytes in @a addr
505 * @return new source object
506 */
507static struct GNUNET_DHTU_Source *
508create_source (struct Plugin *plugin,
509 const struct sockaddr *addr,
510 socklen_t addrlen)
511{
512 struct GNUNET_DHTU_Source *src;
513
514 src = GNUNET_new (struct GNUNET_DHTU_Source);
515 src->addrlen = addrlen;
516 memcpy (&src->addr,
517 addr,
518 addrlen);
519 src->scan_generation = plugin->scan_generation;
520 switch (addr->sa_family)
521 {
522 case AF_INET:
523 {
524 const struct sockaddr_in *s4 = (const struct sockaddr_in *) addr;
525 char buf[INET_ADDRSTRLEN];
526
527 GNUNET_assert (sizeof (struct sockaddr_in) == addrlen);
528 GNUNET_asprintf (&src->address,
529 "ip+udp://%s:%u",
530 inet_ntop (AF_INET,
531 &s4->sin_addr,
532 buf,
533 sizeof (buf)),
534 ntohs (s4->sin_port));
535 }
536 break;
537 case AF_INET6:
538 {
539 const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) addr;
540 char buf[INET6_ADDRSTRLEN];
541
542 GNUNET_assert (sizeof (struct sockaddr_in6) == addrlen);
543 GNUNET_asprintf (&src->address,
544 "ip+udp://[%s]:%u",
545 inet_ntop (AF_INET6,
546 &s6->sin6_addr,
547 buf,
548 sizeof (buf)),
549 ntohs (s6->sin6_port));
550 }
551 break;
552 default:
553 GNUNET_break (0);
554 GNUNET_free (src);
555 return NULL;
556 }
557 GNUNET_CONTAINER_DLL_insert (plugin->src_head,
558 plugin->src_tail,
559 src);
560 plugin->env->address_add_cb (plugin->env->cls,
561 src->address,
562 src,
563 &src->app_ctx);
564 return src;
565}
566
567
568/**
569 * Compare two addresses excluding the ports for equality. Only compares IP
570 * address. Must only be called on AF_INET or AF_INET6 addresses.
571 *
572 * @param a1 address to compare
573 * @param a2 address to compare
574 * @param alen number of bytes in @a a1 and @a a2
575 * @return 0 if @a a1 == @a a2.
576 */
577static int
578addrcmp_np (const struct sockaddr *a1,
579 const struct sockaddr *a2,
580 size_t alen)
581{
582 GNUNET_assert (a1->sa_family == a2->sa_family);
583 switch (a1->sa_family)
584 {
585 case AF_INET:
586 GNUNET_assert (sizeof (struct sockaddr_in) == alen);
587 {
588 const struct sockaddr_in *s1 = (const struct sockaddr_in *) a1;
589 const struct sockaddr_in *s2 = (const struct sockaddr_in *) a2;
590
591 if (s1->sin_addr.s_addr != s2->sin_addr.s_addr)
592 return 1;
593 break;
594 }
595 case AF_INET6:
596 GNUNET_assert (sizeof (struct sockaddr_in6) == alen);
597 {
598 const struct sockaddr_in6 *s1 = (const struct sockaddr_in6 *) a1;
599 const struct sockaddr_in6 *s2 = (const struct sockaddr_in6 *) a2;
600
601 if (0 != GNUNET_memcmp (&s1->sin6_addr,
602 &s2->sin6_addr))
603 return 1;
604 break;
605 }
606 default:
607 GNUNET_assert (0);
608 }
609 return 0;
610}
611
612
613/**
614 * Compare two addresses for equality. Only
615 * compares IP address and port. Must only be
616 * called on AF_INET or AF_INET6 addresses.
617 *
618 * @param a1 address to compare
619 * @param a2 address to compare
620 * @param alen number of bytes in @a a1 and @a a2
621 * @return 0 if @a a1 == @a a2.
622 */
623static int
624addrcmp (const struct sockaddr *a1,
625 const struct sockaddr *a2,
626 size_t alen)
627{
628 GNUNET_assert (a1->sa_family == a2->sa_family);
629 switch (a1->sa_family)
630 {
631 case AF_INET:
632 GNUNET_assert (sizeof (struct sockaddr_in) == alen);
633 {
634 const struct sockaddr_in *s1 = (const struct sockaddr_in *) a1;
635 const struct sockaddr_in *s2 = (const struct sockaddr_in *) a2;
636
637 if (s1->sin_port != s2->sin_port)
638 return 1;
639 if (s1->sin_addr.s_addr != s2->sin_addr.s_addr)
640 return 1;
641 break;
642 }
643 case AF_INET6:
644 GNUNET_assert (sizeof (struct sockaddr_in6) == alen);
645 {
646 const struct sockaddr_in6 *s1 = (const struct sockaddr_in6 *) a1;
647 const struct sockaddr_in6 *s2 = (const struct sockaddr_in6 *) a2;
648
649 if (s1->sin6_port != s2->sin6_port)
650 return 1;
651 if (0 != GNUNET_memcmp (&s1->sin6_addr,
652 &s2->sin6_addr))
653 return 1;
654 break;
655 }
656 default:
657 GNUNET_assert (0);
658 }
659 return 0;
660}
661
662
663/**
664 * Callback function invoked for each interface found.
665 *
666 * @param cls closure
667 * @param name name of the interface (can be NULL for unknown)
668 * @param isDefault is this presumably the default interface
669 * @param addr address of this interface (can be NULL for unknown or unassigned)
670 * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
671 * @param netmask the network mask (can be NULL for unknown or unassigned)
672 * @param addrlen length of the address
673 * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort
674 */
675static enum GNUNET_GenericReturnValue
676process_ifcs (void *cls,
677 const char *name,
678 int isDefault,
679 const struct sockaddr *addr,
680 const struct sockaddr *broadcast_addr,
681 const struct sockaddr *netmask,
682 socklen_t addrlen)
683{
684 struct Plugin *plugin = cls;
685 struct GNUNET_DHTU_Source *src;
686
687 for (src = plugin->src_head;
688 NULL != src;
689 src = src->next)
690 {
691 if ( (addrlen == src->addrlen) &&
692 (0 == addrcmp_np (addr,
693 (const struct sockaddr *) &src->addr,
694 addrlen)) )
695 {
696 src->scan_generation = plugin->scan_generation;
697 return GNUNET_OK;
698 }
699 }
700 switch (addr->sa_family)
701 {
702 case AF_INET:
703 {
704 struct sockaddr_in v4;
705
706 GNUNET_assert (sizeof(v4) == addrlen);
707 memcpy (&v4,
708 addr,
709 addrlen);
710 v4.sin_port = htons (plugin->port16);
711 (void) create_source (plugin,
712 (const struct sockaddr *) &v4,
713 sizeof (v4));
714 break;
715 }
716 case AF_INET6:
717 {
718 struct sockaddr_in6 v6;
719
720 GNUNET_assert (sizeof(v6) == addrlen);
721 memcpy (&v6,
722 addr,
723 addrlen);
724 v6.sin6_port = htons (plugin->port16);
725 (void) create_source (plugin,
726 (const struct sockaddr *) &v6,
727 sizeof (v6));
728 break;
729 }
730 }
731 return GNUNET_OK;
732}
733
734
735/**
736 * Scan network interfaces for IP address changes.
737 *
738 * @param cls a `struct Plugin`
739 */
740static void
741scan (void *cls)
742{
743 struct Plugin *plugin = cls;
744 struct GNUNET_DHTU_Source *next;
745
746 plugin->scan_generation++;
747 GNUNET_OS_network_interfaces_list (&process_ifcs,
748 plugin);
749 for (struct GNUNET_DHTU_Source *src = plugin->src_head;
750 NULL != src;
751 src = next)
752 {
753 next = src->next;
754 if (src->scan_generation >= plugin->scan_generation)
755 continue;
756 GNUNET_CONTAINER_DLL_remove (plugin->src_head,
757 plugin->src_tail,
758 src);
759 plugin->env->address_del_cb (src->app_ctx);
760 GNUNET_free (src->address);
761 GNUNET_free (src);
762 }
763 plugin->scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ,
764 &scan,
765 plugin);
766}
767
768
769/**
770 * Find our source matching @a addr. If none exists,
771 * create one!
772 *
773 * @param plugin the plugin handle
774 * @param addr socket address to find
775 * @param addrlen number of bytes in @a addr
776 * @return matching source object
777 */
778static struct GNUNET_DHTU_Source *
779find_source (struct Plugin *plugin,
780 const void *addr,
781 size_t addrlen)
782{
783 for (struct GNUNET_DHTU_Source *src = plugin->src_head;
784 NULL != src;
785 src = src->next)
786 {
787 if ( (addrlen == src->addrlen) &&
788 (0 == addrcmp (addr,
789 (const struct sockaddr *) &src->addr,
790 addrlen)) )
791 return src;
792 }
793
794 return create_source (plugin,
795 (const struct sockaddr *) addr,
796 addrlen);
797}
798
799
800/**
801 * UDP socket is ready to receive. Read.
802 *
803 * @param cls our `struct Plugin *`
804 */
805static void
806read_cb (void *cls)
807{
808 struct Plugin *plugin = cls;
809 ssize_t ret;
810 const struct GNUNET_PeerIdentity *pid;
811 char buf[65536] GNUNET_ALIGN;
812 struct sockaddr_storage sa;
813 struct iovec iov = {
814 .iov_base = buf,
815 .iov_len = sizeof (buf)
816 };
817 char ctl[128];
818 struct msghdr mh = {
819 .msg_name = &sa,
820 .msg_namelen = sizeof (sa),
821 .msg_iov = &iov,
822 .msg_iovlen = 1,
823 .msg_control = ctl,
824 .msg_controllen = sizeof (ctl)
825 };
826 struct GNUNET_DHTU_Target *dst = NULL;
827 struct GNUNET_DHTU_Source *src = NULL;
828
829 ret = recvmsg (GNUNET_NETWORK_get_fd (plugin->sock),
830 &mh,
831 MSG_DONTWAIT);
832 plugin->read_task = GNUNET_SCHEDULER_add_read_net (
833 GNUNET_TIME_UNIT_FOREVER_REL,
834 plugin->sock,
835 &read_cb,
836 plugin);
837 if (ret < 0)
838 return; /* read failure, hopefully EAGAIN */
839 if (ret < sizeof (*pid))
840 {
841 GNUNET_break_op (0);
842 return;
843 }
844 /* find IP where we received message */
845 for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mh);
846 NULL != cmsg;
847 cmsg = CMSG_NXTHDR (&mh,
848 cmsg))
849 {
850 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
851 "Got CMSG level %u (%d/%d), type %u (%d/%d)\n",
852 cmsg->cmsg_level,
853 (cmsg->cmsg_level == IPPROTO_IP),
854 (cmsg->cmsg_level == IPPROTO_IPV6),
855 cmsg->cmsg_type,
856 (cmsg->cmsg_type == IP_PKTINFO),
857 (cmsg->cmsg_type == IPV6_PKTINFO));
858 if ( (cmsg->cmsg_level == IPPROTO_IP) &&
859 (cmsg->cmsg_type == IP_PKTINFO) )
860 {
861 if (CMSG_LEN (sizeof (struct in_pktinfo)) ==
862 cmsg->cmsg_len)
863 {
864 struct in_pktinfo pi;
865
866 memcpy (&pi,
867 CMSG_DATA (cmsg),
868 sizeof (pi));
869 {
870 struct sockaddr_in sa = {
871 .sin_family = AF_INET,
872 .sin_addr = pi.ipi_addr,
873 .sin_port = htons (plugin->port16)
874 };
875
876 src = find_source (plugin,
877 &sa,
878 sizeof (sa));
879 /* For sources we discovered by reading,
880 force the generation far into the future */
881 src->scan_generation = plugin->scan_generation + 60;
882 }
883 break;
884 }
885 else
886 GNUNET_break (0);
887 }
888 if ( (cmsg->cmsg_level == IPPROTO_IPV6) &&
889 (cmsg->cmsg_type == IPV6_PKTINFO) )
890 {
891 if (CMSG_LEN (sizeof (struct in6_pktinfo)) ==
892 cmsg->cmsg_len)
893 {
894 struct in6_pktinfo pi;
895
896 memcpy (&pi,
897 CMSG_DATA (cmsg),
898 sizeof (pi));
899 {
900 struct sockaddr_in6 sa = {
901 .sin6_family = AF_INET6,
902 .sin6_addr = pi.ipi6_addr,
903 .sin6_port = htons (plugin->port16),
904 .sin6_scope_id = pi.ipi6_ifindex
905 };
906
907 src = find_source (plugin,
908 &sa,
909 sizeof (sa));
910 /* For sources we discovered by reading,
911 force the generation far into the future */
912 src->scan_generation = plugin->scan_generation + 60;
913 break;
914 }
915 }
916 else
917 GNUNET_break (0);
918 }
919 }
920 if (NULL == src)
921 {
922 GNUNET_break (0);
923 return;
924 }
925 pid = (const struct GNUNET_PeerIdentity *) buf;
926 dst = find_target (plugin,
927 pid,
928 &sa,
929 mh.msg_namelen);
930 if (NULL == dst)
931 {
932 GNUNET_break (0);
933 return;
934 }
935 plugin->env->receive_cb (plugin->env->cls,
936 &dst->app_ctx,
937 &src->app_ctx,
938 &buf[sizeof(*pid)],
939 ret - sizeof (*pid));
940}
941
942
943/**
944 * Entry point for the plugin.
945 *
946 * @param cls closure (the `struct GNUNET_DHTU_PluginEnvironment`)
947 * @return the plugin's API
948 */
949void *
950libgnunet_plugin_dhtu_ip_init (void *cls)
951{
952 struct GNUNET_DHTU_PluginEnvironment *env = cls;
953 struct GNUNET_DHTU_PluginFunctions *api;
954 struct Plugin *plugin;
955 char *port;
956 unsigned int nport;
957 int sock;
958 int af;
959 unsigned long long nse;
960
961 if (GNUNET_OK !=
962 GNUNET_CONFIGURATION_get_value_number (env->cfg,
963 "DHTU-IP",
964 "NSE",
965 &nse))
966 {
967 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
968 "DHTU-IP",
969 "NSE");
970 return NULL;
971 }
972 if (GNUNET_OK !=
973 GNUNET_CONFIGURATION_get_value_string (env->cfg,
974 "DHTU-IP",
975 "UDP_PORT",
976 &port))
977 {
978 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
979 "DHTU-IP",
980 "UDP_PORT");
981 return NULL;
982 }
983 {
984 char dummy;
985
986 if ( (1 != sscanf (port,
987 "%u%c",
988 &nport,
989 &dummy)) ||
990 (nport > UINT16_MAX) )
991 {
992 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
993 "DHTU-IP",
994 "UDP_PORT",
995 "must be number below 65536");
996 GNUNET_free (port);
997 return NULL;
998 }
999 }
1000 plugin = GNUNET_new (struct Plugin);
1001 plugin->env = env;
1002 plugin->port = port;
1003 plugin->port16 = (uint16_t) nport;
1004 if (GNUNET_OK !=
1005 GNUNET_CRYPTO_get_peer_identity (env->cfg,
1006 &plugin->my_id))
1007 {
1008 GNUNET_free (plugin);
1009 return NULL;
1010 }
1011 af = AF_INET6;
1012 sock = socket (af,
1013 SOCK_DGRAM,
1014 IPPROTO_UDP);
1015 if (-1 == sock)
1016 {
1017 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1018 "socket");
1019 GNUNET_free (plugin->port);
1020 GNUNET_free (plugin);
1021 return NULL;
1022 }
1023 switch (af)
1024 {
1025 case AF_INET:
1026 {
1027 int on = 1;
1028
1029 if (0 !=
1030 setsockopt (sock,
1031 IPPROTO_IP,
1032 IP_PKTINFO,
1033 &on,
1034 sizeof (on)))
1035 {
1036 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1037 "setsockopt");
1038 }
1039 }
1040 {
1041 struct sockaddr_in sa = {
1042 .sin_family = AF_INET,
1043 .sin_port = htons ((uint16_t) nport)
1044 };
1045
1046 if (0 !=
1047 bind (sock,
1048 (const struct sockaddr *) &sa,
1049 sizeof (sa)))
1050 {
1051 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1052 "socket");
1053 GNUNET_break (0 ==
1054 close (sock));
1055 GNUNET_free (plugin->port);
1056 GNUNET_free (plugin);
1057 return NULL;
1058 }
1059 }
1060 break;
1061 case AF_INET6:
1062 {
1063 int on = 1;
1064
1065 if (0 !=
1066 setsockopt (sock,
1067 IPPROTO_IPV6,
1068 IPV6_RECVPKTINFO,
1069 &on,
1070 sizeof (on)))
1071 {
1072 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1073 "setsockopt");
1074 }
1075 }
1076 {
1077 struct sockaddr_in6 sa = {
1078 .sin6_family = AF_INET6,
1079 .sin6_port = htons ((uint16_t) nport)
1080 };
1081
1082 if (0 !=
1083 bind (sock,
1084 (const struct sockaddr *) &sa,
1085 sizeof (sa)))
1086 {
1087 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1088 "socket");
1089 GNUNET_break (0 ==
1090 close (sock));
1091 GNUNET_free (plugin->port);
1092 GNUNET_free (plugin);
1093 return NULL;
1094 }
1095 }
1096 break;
1097 }
1098 plugin->dsts = GNUNET_CONTAINER_multihashmap_create (128,
1099 GNUNET_NO);
1100 plugin->sock = GNUNET_NETWORK_socket_box_native (sock);
1101 plugin->read_task = GNUNET_SCHEDULER_add_read_net (
1102 GNUNET_TIME_UNIT_FOREVER_REL,
1103 plugin->sock,
1104 &read_cb,
1105 plugin);
1106 env->network_size_cb (env->cls,
1107 GNUNET_TIME_UNIT_ZERO_ABS,
1108 log (nse) / log (2),
1109 -1.0 /* stddev */);
1110 plugin->scan_task = GNUNET_SCHEDULER_add_now (&scan,
1111 plugin);
1112 api = GNUNET_new (struct GNUNET_DHTU_PluginFunctions);
1113 api->cls = plugin;
1114 api->try_connect = &ip_try_connect;
1115 api->hold = &ip_hold;
1116 api->drop = &ip_drop;
1117 api->send = &ip_send;
1118 return api;
1119}
1120
1121
1122/**
1123 * Exit point from the plugin.
1124 *
1125 * @param cls closure (our `struct Plugin`)
1126 * @return NULL
1127 */
1128void *
1129libgnunet_plugin_dhtu_ip_done (void *cls)
1130{
1131 struct GNUNET_DHTU_PluginFunctions *api = cls;
1132 struct Plugin *plugin = api->cls;
1133 struct GNUNET_DHTU_Source *src;
1134 struct GNUNET_DHTU_Target *dst;
1135
1136 while (NULL != (dst = plugin->dst_head))
1137 {
1138 plugin->env->disconnect_cb (dst->app_ctx);
1139 GNUNET_assert (NULL == dst->ph_head);
1140 GNUNET_CONTAINER_DLL_remove (plugin->dst_head,
1141 plugin->dst_tail,
1142 dst);
1143 GNUNET_free (dst);
1144 }
1145 while (NULL != (src = plugin->src_head))
1146 {
1147 plugin->env->address_del_cb (src->app_ctx);
1148 GNUNET_CONTAINER_DLL_remove (plugin->src_head,
1149 plugin->src_tail,
1150 src);
1151 GNUNET_free (src->address);
1152 GNUNET_free (src);
1153 }
1154 plugin->env->network_size_cb (plugin->env->cls,
1155 GNUNET_TIME_UNIT_FOREVER_ABS,
1156 0.0,
1157 0.0);
1158 GNUNET_CONTAINER_multihashmap_destroy (plugin->dsts);
1159 if (NULL != plugin->read_task)
1160 {
1161 GNUNET_SCHEDULER_cancel (plugin->read_task);
1162 plugin->read_task = NULL;
1163 }
1164 GNUNET_SCHEDULER_cancel (plugin->scan_task);
1165 GNUNET_break (GNUNET_OK ==
1166 GNUNET_NETWORK_socket_close (plugin->sock));
1167 GNUNET_free (plugin->port);
1168 GNUNET_free (plugin);
1169 GNUNET_free (api);
1170 return NULL;
1171}
diff --git a/src/dhtu/test_dhtu_ip.c b/src/dhtu/test_dhtu_ip.c
deleted file mode 100644
index 030b17b5f..000000000
--- a/src/dhtu/test_dhtu_ip.c
+++ /dev/null
@@ -1,45 +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 * @file dhtu/test_dhtu_ip.c
23 * @brief Test case for the DHTU implementation for IP
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_testing_netjail_lib.h"
28#include "gnunet_util_lib.h"
29
30#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
31
32#define CONFIG_FILE "test_dhtu_ip.conf"
33
34
35int
36main (int argc,
37 char *const *argv)
38{
39 struct GNUNET_TESTING_Command commands[] = {
40 GNUNET_TESTING_cmd_end ()
41 };
42
43 return GNUNET_TESTING_main (commands,
44 TIMEOUT);
45}
diff --git a/src/dhtu/testing_dhtu_cmd_send.c b/src/dhtu/testing_dhtu_cmd_send.c
deleted file mode 100644
index 45d166b14..000000000
--- a/src/dhtu/testing_dhtu_cmd_send.c
+++ /dev/null
@@ -1,119 +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 * @file testing/testing_dhtu_cmd_send.c
23 * @brief use DHTU to send a message
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_testing_ng_lib.h"
28#include "gnunet_testing_netjail_lib.h"
29
30
31/**
32 * State for the 'send' command.
33 */
34struct SendState
35{
36
37 /**
38 * Mandatory context for async commands.
39 */
40 struct GNUNET_TESTING_AsyncContext ac;
41
42};
43
44
45/**
46 *
47 *
48 * @param cls a `struct SendState`
49 */
50static void
51send_cleanup (void *cls)
52{
53 struct SendState *ss = cls;
54
55 GNUNET_free (ss);
56}
57
58
59/**
60 * Return trains of the ``send`` command.
61 *
62 * @param cls closure.
63 * @param[out] ret result
64 * @param trait name of the trait.
65 * @param index index number of the object to offer.
66 * @return #GNUNET_OK on success.
67 * #GNUNET_NO if no trait was found
68 */
69static enum GNUNET_GenericReturnValue
70send_traits (void *cls,
71 const void **ret,
72 const char *trait,
73 unsigned int index)
74{
75 return GNUNET_NO;
76}
77
78
79/**
80 * Run the 'send' command.
81 *
82 * @param cls closure.
83 * @param is interpreter state.
84 */
85static void
86send_run (void *cls,
87 struct GNUNET_TESTING_Interpreter *is)
88{
89 struct SendState *ss = cls;
90
91#if 0
92 other_cmd = GNUNET_TESTING_interpreter_lookup_command (ss->other_label);
93 GNUNET_TESTING_get_trait_XXX (other_cmd,
94 &data);
95#endif
96 GNUNET_TESTING_async_finish (&ss->ac);
97}
98
99
100struct GNUNET_TESTING_Command
101GNUNET_TESTING_DHTU_cmd_send (const char *label)
102{
103 struct SendState *ss;
104
105 ss = GNUNET_new (struct SendState);
106
107 {
108 struct GNUNET_TESTING_Command cmd = {
109 .cls = ss,
110 .run = &send_run,
111 .ac = &ss->ac,
112 .cleanup = &send_cleanup,
113 .traits = &send_traits
114 };
115 strncpy (cmd.label, label, GNUNET_TESTING_CMD_MAX_LABEL_LENGTH);
116
117 return cmd;
118 }
119}