aboutsummaryrefslogtreecommitdiff
path: root/src/transport
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 19:35:11 +0200
committerMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 19:35:11 +0200
commitddfee3f564bff9c5d5719af3132d7869b8783ec4 (patch)
treee6fd7801fe6808797f3418bf081ab68d5a5ec27b /src/transport
parent852718c2473e41bc01ada0d53ad93c7da78e6ec8 (diff)
downloadgnunet-ddfee3f564bff9c5d5719af3132d7869b8783ec4.tar.gz
gnunet-ddfee3f564bff9c5d5719af3132d7869b8783ec4.zip
BUILD: more more components into new structure; ftbfs fix
Diffstat (limited to 'src/transport')
-rw-r--r--src/transport/.gitignore94
-rw-r--r--src/transport/Makefile.am460
-rw-r--r--src/transport/NOTES46
-rwxr-xr-xsrc/transport/benchmark.sh13
-rw-r--r--src/transport/communicator.h138
-rw-r--r--src/transport/gnunet-communicator-quic.c1795
-rw-r--r--src/transport/gnunet-communicator-tcp.c4082
-rw-r--r--src/transport/gnunet-communicator-udp.c3444
-rw-r--r--src/transport/gnunet-communicator-unix.c1166
-rw-r--r--src/transport/gnunet-service-transport.c11750
-rw-r--r--src/transport/gnunet-service-transport.h234
-rw-r--r--src/transport/gnunet-transport-certificate-creation.in158
-rw-r--r--src/transport/gnunet-transport.c1437
-rw-r--r--src/transport/ieee80211_radiotap.h276
-rw-r--r--src/transport/meson.build261
-rw-r--r--src/transport/template_cfg_peer1.conf50
-rw-r--r--src/transport/template_cfg_peer2.conf58
-rw-r--r--src/transport/template_tng_cfg_peer1.conf34
-rw-r--r--src/transport/test_communicator_basic.c1224
-rw-r--r--src/transport/test_communicator_quic_basic_peer1.conf45
-rw-r--r--src/transport/test_communicator_quic_basic_peer2.conf45
-rw-r--r--src/transport/test_communicator_tcp_basic_peer1.conf48
-rw-r--r--src/transport/test_communicator_tcp_basic_peer2.conf44
-rw-r--r--src/transport/test_communicator_tcp_bidirect_peer1.conf48
-rw-r--r--src/transport/test_communicator_tcp_bidirect_peer2.conf44
-rw-r--r--src/transport/test_communicator_tcp_rekey_peer1.conf45
-rw-r--r--src/transport/test_communicator_tcp_rekey_peer2.conf45
-rw-r--r--src/transport/test_communicator_udp_backchannel_peer1.conf48
-rw-r--r--src/transport/test_communicator_udp_backchannel_peer2.conf48
-rw-r--r--src/transport/test_communicator_udp_basic_peer1.conf39
-rw-r--r--src/transport/test_communicator_udp_basic_peer2.conf39
-rw-r--r--src/transport/test_communicator_udp_rekey_peer1.conf52
-rw-r--r--src/transport/test_communicator_udp_rekey_peer2.conf52
-rw-r--r--src/transport/test_communicator_unix_basic_peer1.conf43
-rw-r--r--src/transport/test_communicator_unix_basic_peer2.conf43
-rwxr-xr-xsrc/transport/test_delay19
-rw-r--r--src/transport/test_plugin_hostkeybin915 -> 0 bytes
-rw-r--r--src/transport/test_plugin_hostkey.ecc1
-rw-r--r--src/transport/test_tng_defaults.conf14
-rw-r--r--src/transport/test_transport_address_switch.c433
-rw-r--r--src/transport/test_transport_address_switch_tcp_peer1.conf48
-rw-r--r--src/transport/test_transport_address_switch_tcp_peer2.conf48
-rw-r--r--src/transport/test_transport_address_switch_udp_peer1.conf48
-rw-r--r--src/transport/test_transport_address_switch_udp_peer2.conf48
-rw-r--r--src/transport/test_transport_api.c126
-rw-r--r--src/transport/test_transport_api2.c126
-rw-r--r--src/transport/test_transport_api2_tcp_node1.conf35
-rw-r--r--src/transport/test_transport_api2_tcp_node2.conf22
-rw-r--r--src/transport/test_transport_api2_tcp_peer1.conf23
-rw-r--r--src/transport/test_transport_api2_tcp_peer2.conf22
-rw-r--r--src/transport/test_transport_api2_tng_node.conf40
-rw-r--r--src/transport/test_transport_api_data.conf9
-rw-r--r--src/transport/test_transport_api_monitor_peers.c226
-rw-r--r--src/transport/test_transport_api_monitor_peers_peer1.conf4
-rw-r--r--src/transport/test_transport_api_monitor_peers_peer2.conf5
-rw-r--r--src/transport/test_transport_api_monitor_validation_peer1.conf6
-rw-r--r--src/transport/test_transport_api_monitor_validation_peer2.conf7
-rw-r--r--src/transport/test_transport_api_multi_peer1.conf7
-rw-r--r--src/transport/test_transport_api_multi_peer2.conf9
-rw-r--r--src/transport/test_transport_api_tcp_nat_peer1.conf34
-rw-r--r--src/transport/test_transport_api_tcp_nat_peer2.conf32
-rw-r--r--src/transport/test_transport_api_tcp_peer1.conf9
-rw-r--r--src/transport/test_transport_api_tcp_peer2.conf9
-rw-r--r--src/transport/test_transport_api_udp_nat_peer1.conf34
-rw-r--r--src/transport/test_transport_api_udp_nat_peer2.conf32
-rw-r--r--src/transport/test_transport_api_udp_peer1.conf17
-rw-r--r--src/transport/test_transport_api_udp_peer2.conf15
-rw-r--r--src/transport/test_transport_api_unix_peer1.conf10
-rw-r--r--src/transport/test_transport_api_unix_peer2.conf7
-rw-r--r--src/transport/test_transport_defaults.conf20
-rw-r--r--src/transport/test_transport_distance_vector_circle_topo.conf11
-rw-r--r--src/transport/test_transport_distance_vector_inverse_topo.conf13
-rw-r--r--src/transport/test_transport_distance_vector_topo.conf8
-rw-r--r--src/transport/test_transport_just_run_topo.conf6
-rwxr-xr-xsrc/transport/test_transport_nat_icmp_tcp.sh12
-rw-r--r--src/transport/test_transport_nat_icmp_tcp_topo.conf7
-rwxr-xr-xsrc/transport/test_transport_nat_upnp.sh12
-rw-r--r--src/transport/test_transport_nat_upnp_topo.conf7
-rw-r--r--src/transport/test_transport_plugin_cmd_just_run.c494
-rw-r--r--src/transport/test_transport_plugin_cmd_nat_upnp.c368
-rw-r--r--src/transport/test_transport_plugin_cmd_simple_send.c377
-rw-r--r--src/transport/test_transport_plugin_cmd_simple_send_broadcast.c402
-rw-r--r--src/transport/test_transport_plugin_cmd_simple_send_dv.c434
-rw-r--r--src/transport/test_transport_plugin_cmd_simple_send_performance.c480
-rw-r--r--src/transport/test_transport_plugin_cmd_udp_backchannel.c371
-rwxr-xr-xsrc/transport/test_transport_simple_send.sh11
-rwxr-xr-xsrc/transport/test_transport_simple_send_broadcast.sh11
-rw-r--r--src/transport/test_transport_simple_send_broadcast_topo.conf4
-rwxr-xr-xsrc/transport/test_transport_simple_send_dv_circle.sh11
-rwxr-xr-xsrc/transport/test_transport_simple_send_dv_inverse.sh12
-rwxr-xr-xsrc/transport/test_transport_simple_send_performance.sh11
-rw-r--r--src/transport/test_transport_simple_send_performance_topo.conf6
-rwxr-xr-xsrc/transport/test_transport_simple_send_string.sh21
-rw-r--r--src/transport/test_transport_simple_send_topo.conf6
-rwxr-xr-xsrc/transport/test_transport_start_testcase.sh12
-rw-r--r--src/transport/test_transport_start_with_config.c121
-rw-r--r--src/transport/test_transport_test_transport_address_switch_tcp_peer1.conf29
-rw-r--r--src/transport/test_transport_test_transport_address_switch_tcp_peer2.conf29
-rw-r--r--src/transport/test_transport_testing_startstop.c138
-rwxr-xr-xsrc/transport/test_transport_udp_backchannel.sh14
-rw-r--r--src/transport/test_transport_udp_backchannel_topo.conf7
-rw-r--r--src/transport/transport-testing-cmds.h245
-rw-r--r--src/transport/transport-testing-communicator.c1238
-rw-r--r--src/transport/transport-testing-communicator.h370
-rw-r--r--src/transport/transport-testing-filenames2.c203
-rw-r--r--src/transport/transport-testing-loggers2.c81
-rw-r--r--src/transport/transport-testing-main2.c614
-rw-r--r--src/transport/transport-testing-send2.c241
-rw-r--r--src/transport/transport-testing2.c924
-rw-r--r--src/transport/transport-testing2.h941
-rw-r--r--src/transport/transport.conf.in248
-rw-r--r--src/transport/transport.h828
-rw-r--r--src/transport/transport_api2_application.c397
-rw-r--r--src/transport/transport_api2_communication.c1114
-rw-r--r--src/transport/transport_api2_core.c826
-rw-r--r--src/transport/transport_api2_monitor.c292
-rw-r--r--src/transport/transport_api_cmd_backchannel_check.c554
-rw-r--r--src/transport/transport_api_cmd_connecting_peers.c311
-rw-r--r--src/transport/transport_api_cmd_send_simple.c162
-rw-r--r--src/transport/transport_api_cmd_send_simple_performance.c220
-rw-r--r--src/transport/transport_api_cmd_start_peer.c483
-rw-r--r--src/transport/transport_api_cmd_stop_peer.c154
-rw-r--r--src/transport/transport_api_traits.c32
-rwxr-xr-xsrc/transport/upnp.sh22
124 files changed, 0 insertions, 42938 deletions
diff --git a/src/transport/.gitignore b/src/transport/.gitignore
deleted file mode 100644
index 163ffbd5d..000000000
--- a/src/transport/.gitignore
+++ /dev/null
@@ -1,94 +0,0 @@
1gnunet-transport-wlan-sender
2gnunet-helper-transport-bluetooth
3gnunet-helper-transport-wlan
4gnunet-helper-transport-wlan-dummy
5gnunet-service-transport
6gnunet-transport
7gnunet-transport-certificate-creation
8gnunet-transport-profiler
9gnunet-transport-wlan-receiver
10https_cert_qutoa_p2.crt
11https_key_quota_p2.key
12test_http_common
13test_plugin_bluetooth
14test_plugin_http_client
15test_plugin_http_server
16test_plugin_https_client
17test_plugin_https_server
18test_plugin_tcp
19test_plugin_udp
20test_plugin_unix
21test_plugin_wlan
22test_quota_compliance_bluetooth
23test_quota_compliance_bluetooth_asymmetric
24test_quota_compliance_http
25test_quota_compliance_http_asymmetric
26test_quota_compliance_https
27test_quota_compliance_https_asymmetric
28test_quota_compliance_tcp
29test_quota_compliance_tcp_asymmetric
30test_quota_compliance_udp
31test_quota_compliance_unix
32test_quota_compliance_unix_asymmetric
33test_quota_compliance_wlan
34test_quota_compliance_wlan_asymmetric
35test_transport_address_switch_http
36test_transport_address_switch_https
37test_transport_address_switch_tcp
38test_transport_address_switch_udp
39test_transport_api_blacklisting_tcp
40test_transport_api_bluetooth
41test_transport_api_disconnect_tcp
42test_transport_api_http
43test_transport_api_http_reverse
44test_transport_api_https
45test_transport_api_limited_sockets_tcp
46test_transport_api_manipulation_cfg
47test_transport_api_manipulation_recv_tcp
48test_transport_api_manipulation_send_tcp
49test_transport_api_monitor_peers
50test_transport_api_multi
51test_transport_api_reliability_bluetooth
52test_transport_api_reliability_http
53test_transport_api_reliability_http_xhr
54test_transport_api_reliability_https
55test_transport_api_reliability_https_xhr
56test_transport_api_reliability_tcp
57test_transport_api_reliability_tcp_nat
58test_transport_api_reliability_udp
59test_transport_api_reliability_unix
60test_transport_api_reliability_wlan
61test_transport_api_restart_1peer
62test_transport_api_restart_2peers
63test_transport_api_slow_ats
64test_transport_api_tcp
65test_transport_api_tcp_nat
66test_transport_api_timeout_bluetooth
67test_transport_api_timeout_http
68test_transport_api_timeout_https
69test_transport_api_timeout_tcp
70test_transport_api_timeout_udp
71test_transport_api_timeout_unix
72test_transport_api_timeout_wlan
73test_transport_api_udp
74test_transport_api_udp_nat
75test_transport_api_unix
76test_transport_api_unix_abstract
77test_transport_api_wlan
78test_transport_blacklisting_inbound_bl_full
79test_transport_blacklisting_inbound_bl_plugin
80test_transport_blacklisting_multiple_plugins
81test_transport_blacklisting_no_bl
82test_transport_blacklisting_outbound_bl_full
83test_transport_blacklisting_outbound_bl_plugin
84test_transport_testing_restart
85test_transport_testing_startstop
86gnunet-communicator-unix
87gnunet-service-tng
88gnunet-communicator-tcp
89gnunet-communicator-udp
90test_communicator_basic-*
91test_communicator_rekey-*
92test_transport_start_with_config
93test_transport_api2_tcp
94gnunet-communicator-quic
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
deleted file mode 100644
index 7f71b0967..000000000
--- a/src/transport/Makefile.am
+++ /dev/null
@@ -1,460 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include
3
4plugindir = $(libdir)/gnunet
5
6pkgcfgdir= $(pkgdatadir)/config.d/
7
8libexecdir= $(pkglibdir)/libexec/
9
10pkgcfg_DATA = \
11 transport.conf
12
13if USE_COVERAGE
14 AM_CFLAGS = --coverage -O0
15endif
16
17noinst_PROGRAMS = \
18 test_transport_start_with_config \
19 gnunet-communicator-udp
20
21TESTING_LIBS = \
22 libgnunettransporttesting2.la
23
24lib_LTLIBRARIES = \
25 libgnunettransportapplication.la \
26 libgnunettransportcore.la \
27 libgnunettransportcommunicator.la \
28 libgnunettransportmonitor.la \
29 $(TESTING_LIBS)
30
31libgnunettransporttesting2_la_SOURCES = \
32 transport_api_traits.c \
33 transport_api_cmd_connecting_peers.c \
34 transport_api_cmd_backchannel_check.c \
35 transport_api_cmd_start_peer.c \
36 transport_api_cmd_stop_peer.c \
37 transport_api_cmd_send_simple.c \
38 transport_api_cmd_send_simple_performance.c \
39 transport-testing2.c transport-testing2.h \
40 transport-testing-cmds.h \
41 transport-testing-filenames2.c \
42 transport-testing-loggers2.c \
43 transport-testing-main2.c \
44 transport-testing-send2.c \
45 transport-testing-communicator.c transport-testing-communicator.h
46libgnunettransporttesting2_la_LIBADD = \
47 libgnunettransportapplication.la \
48 libgnunettransportcore.la \
49 $(top_builddir)/src/service/arm/libgnunetarm.la \
50 $(top_builddir)/src/lib/testing/libgnunettesting.la \
51 $(top_builddir)/src/lib/hello/libgnunethello.la \
52 $(top_builddir)/src/peerstore/libgnunetpeerstore.la \
53 $(top_builddir)/src/lib/util/libgnunetutil.la
54libgnunettransporttesting2_la_LDFLAGS = \
55 $(GN_LIBINTL) \
56 $(GN_LIB_LDFLAGS) \
57 -version-info 0:0:0
58
59libgnunettransportapplication_la_SOURCES = \
60 transport_api2_application.c
61libgnunettransportapplication_la_LIBADD = \
62 $(top_builddir)/src/lib/util/libgnunetutil.la \
63 $(LTLIBINTL)
64libgnunettransportapplication_la_LDFLAGS = \
65 $(GN_LIB_LDFLAGS) \
66 -version-info 0:0:0
67
68
69libgnunettransportcore_la_SOURCES = \
70 transport_api2_core.c
71libgnunettransportcore_la_LIBADD = \
72 $(top_builddir)/src/lib/util/libgnunetutil.la \
73 $(GN_LIBINTL)
74libgnunettransportcore_la_LDFLAGS = \
75 $(GN_LIB_LDFLAGS) \
76 -version-info 0:0:0
77
78libgnunettransportcommunicator_la_SOURCES = \
79 transport_api2_communication.c
80libgnunettransportcommunicator_la_LIBADD = \
81 $(top_builddir)/src/lib/util/libgnunetutil.la \
82 $(GN_LIBINTL)
83libgnunettransportcommunicator_la_LDFLAGS = \
84 $(GN_LIB_LDFLAGS) \
85 -version-info 0:0:0
86
87
88libgnunettransportmonitor_la_SOURCES = \
89 transport_api2_monitor.c
90libgnunettransportmonitor_la_LIBADD = \
91 $(top_builddir)/src/lib/util/libgnunetutil.la \
92 $(GN_LIBINTL)
93libgnunettransportmonitor_la_LDFLAGS = \
94 $(GN_LIB_LDFLAGS) \
95 -version-info 0:0:0
96
97
98libexec_PROGRAMS = \
99 gnunet-service-transport \
100 gnunet-communicator-unix \
101 gnunet-communicator-udp \
102 gnunet-communicator-tcp
103if HAVE_EXPERIMENTAL
104if HAVE_QUICHE
105libexec_PROGRAMS += \
106 gnunet-communicator-quic
107endif
108endif
109
110
111#bin_PROGRAMS = \
112# gnunet-transport
113
114bin_SCRIPTS = \
115 gnunet-transport-certificate-creation
116
117# See: https://www.gnu.org/software/automake/manual/html_node/Scripts.html#Scripts
118do_subst = sed -e 's,[@]pkgdatadir[@],$(pkgdatadir),g'
119
120
121gnunet-transport-certificate-creation: gnunet-transport-certificate-creation.in Makefile
122 $(AWK) -v bdir="$(bindir)" -v py="$(PYTHON)" -v awkay="$(AWK_BINARY)" -v pfx="$(prefix)" -v prl="$(PERL)" -v sysconfdirectory="$(sysconfdir)" -v pkgdatadirectory="$(pkgdatadir)" -f $(top_srcdir)/bin/dosubst.awk < $(srcdir)/gnunet-transport-certificate-creation.in > gnunet-transport-certificate-creation
123 @chmod +x gnunet-transport-certificate-creation
124
125
126
127
128gnunet_communicator_unix_SOURCES = \
129 gnunet-communicator-unix.c
130gnunet_communicator_unix_LDADD = \
131 libgnunettransportcommunicator.la \
132 $(top_builddir)/src/statistics/libgnunetstatistics.la \
133 $(top_builddir)/src/lib/util/libgnunetutil.la
134
135gnunet_communicator_tcp_SOURCES = \
136 gnunet-communicator-tcp.c
137gnunet_communicator_tcp_LDADD = \
138 libgnunettransportcommunicator.la \
139 $(top_builddir)/src/peerstore/libgnunetpeerstore.la \
140 $(top_builddir)/src/nat/libgnunetnatnew.la \
141 $(top_builddir)/src/statistics/libgnunetstatistics.la \
142 $(top_builddir)/src/lib/util/libgnunetutil.la \
143 $(LIBGCRYPT_LIBS)
144
145gnunet_communicator_udp_SOURCES = \
146 gnunet-communicator-udp.c
147gnunet_communicator_udp_LDADD = \
148 libgnunettransportapplication.la \
149 libgnunettransportcommunicator.la \
150 $(top_builddir)/src/nat/libgnunetnatnew.la \
151 $(top_builddir)/src/statistics/libgnunetstatistics.la \
152 $(top_builddir)/src/lib/util/libgnunetutil.la \
153 $(LIBGCRYPT_LIBS)
154
155if HAVE_EXPERIMENTAL
156if HAVE_QUICHE
157gnunet_communicator_quic_SOURCES = \
158 gnunet-communicator-quic.c
159gnunet_communicator_quic_LDADD = \
160 libgnunettransportapplication.la \
161 libgnunettransportcommunicator.la \
162 $(top_builddir)/src/peerstore/libgnunetpeerstore.la \
163 $(top_builddir)/src/nat/libgnunetnatnew.la \
164 $(top_builddir)/src/statistics/libgnunetstatistics.la \
165 $(top_builddir)/src/lib/util/libgnunetutil.la \
166 -lquiche \
167 $(LIBGCRYPT_LIBS)
168endif
169endif
170
171#gnunet_transport_SOURCES = \
172# gnunet-transport.c
173#gnunet_transport_LDADD = \
174# libgnunettransport.la \
175# $(top_builddir)/src/lib/hello/libgnunethello.la \
176# $(top_builddir)/src/lib/util/libgnunetutil.la \
177# $(GN_LIBINTL)
178
179gnunet_service_transport_SOURCES = \
180 gnunet-service-transport.c transport.h
181gnunet_service_transport_LDADD = \
182 $(top_builddir)/src/peerstore/libgnunetpeerstore.la \
183 $(top_builddir)/src/lib/hello/libgnunethello.la \
184 $(top_builddir)/src/statistics/libgnunetstatistics.la \
185 $(top_builddir)/src/lib/util/libgnunetutil.la \
186 $(LIBGCRYPT_LIBS) \
187 $(GN_LIBINTL)
188
189plugin_LTLIBRARIES = \
190 libgnunet_test_transport_plugin_cmd_simple_send_performance.la \
191 libgnunet_test_transport_plugin_cmd_nat_upnp.la \
192 libgnunet_test_transport_plugin_cmd_simple_send.la \
193 libgnunet_test_transport_plugin_cmd_simple_send_broadcast.la \
194 libgnunet_test_transport_plugin_cmd_simple_send_dv.la \
195 libgnunet_test_transport_plugin_cmd_udp_backchannel.la
196
197libgnunet_test_transport_plugin_cmd_nat_upnp_la_SOURCES = \
198 test_transport_plugin_cmd_nat_upnp.c
199libgnunet_test_transport_plugin_cmd_nat_upnp_la_LIBADD = \
200 libgnunettransporttesting2.la \
201 libgnunettransportapplication.la \
202 libgnunettransportcore.la \
203 $(top_builddir)/src/lib/testing/libgnunettesting.la \
204 $(top_builddir)/src/peerstore/libgnunetpeerstore.la \
205 $(top_builddir)/src/statistics/libgnunetstatistics.la \
206 $(top_builddir)/src/lib/hello/libgnunethello.la \
207 $(top_builddir)/src/service/arm/libgnunetarm.la \
208 $(top_builddir)/src/lib/util/libgnunetutil.la \
209 $(LTLIBINTL)
210libgnunet_test_transport_plugin_cmd_nat_upnp_la_LDFLAGS = \
211 $(GN_PLUGIN_LDFLAGS)
212
213libgnunet_test_transport_plugin_cmd_udp_backchannel_la_SOURCES = \
214 test_transport_plugin_cmd_udp_backchannel.c
215libgnunet_test_transport_plugin_cmd_udp_backchannel_la_LIBADD = \
216 libgnunettransporttesting2.la \
217 libgnunettransportapplication.la \
218 libgnunettransportcore.la \
219 $(top_builddir)/src/lib/testing/libgnunettesting.la \
220 $(top_builddir)/src/peerstore/libgnunetpeerstore.la \
221 $(top_builddir)/src/statistics/libgnunetstatistics.la \
222 $(top_builddir)/src/lib/hello/libgnunethello.la \
223 $(top_builddir)/src/service/arm/libgnunetarm.la \
224 $(top_builddir)/src/lib/util/libgnunetutil.la \
225 $(LTLIBINTL)
226libgnunet_test_transport_plugin_cmd_udp_backchannel_la_LDFLAGS = \
227 $(GN_PLUGIN_LDFLAGS)
228
229libgnunet_test_transport_plugin_cmd_simple_send_la_SOURCES = \
230 test_transport_plugin_cmd_simple_send.c
231libgnunet_test_transport_plugin_cmd_simple_send_la_LIBADD = \
232 libgnunettransporttesting2.la \
233 libgnunettransportapplication.la \
234 libgnunettransportcore.la \
235 $(top_builddir)/src/lib/testing/libgnunettesting.la \
236 $(top_builddir)/src/peerstore/libgnunetpeerstore.la \
237 $(top_builddir)/src/statistics/libgnunetstatistics.la \
238 $(top_builddir)/src/lib/hello/libgnunethello.la \
239 $(top_builddir)/src/service/arm/libgnunetarm.la \
240 $(top_builddir)/src/lib/util/libgnunetutil.la \
241 $(LTLIBINTL)
242libgnunet_test_transport_plugin_cmd_simple_send_la_LDFLAGS = \
243 $(GN_PLUGIN_LDFLAGS)
244
245libgnunet_test_transport_plugin_cmd_simple_send_performance_la_SOURCES = \
246 test_transport_plugin_cmd_simple_send_performance.c
247libgnunet_test_transport_plugin_cmd_simple_send_performance_la_LIBADD = \
248 libgnunettransporttesting2.la \
249 libgnunettransportapplication.la \
250 libgnunettransportcore.la \
251 $(top_builddir)/src/lib/testing/libgnunettesting.la \
252 $(top_builddir)/src/peerstore/libgnunetpeerstore.la \
253 $(top_builddir)/src/statistics/libgnunetstatistics.la \
254 $(top_builddir)/src/lib/hello/libgnunethello.la \
255 $(top_builddir)/src/service/arm/libgnunetarm.la \
256 $(top_builddir)/src/lib/util/libgnunetutil.la \
257 $(LTLIBINTL)
258libgnunet_test_transport_plugin_cmd_simple_send_performance_la_LDFLAGS = \
259 $(GN_PLUGIN_LDFLAGS)
260
261libgnunet_test_transport_plugin_cmd_simple_send_broadcast_la_SOURCES = \
262 test_transport_plugin_cmd_simple_send_broadcast.c
263libgnunet_test_transport_plugin_cmd_simple_send_broadcast_la_LIBADD = \
264 libgnunettransporttesting2.la \
265 libgnunettransportapplication.la \
266 libgnunettransportcore.la \
267 $(top_builddir)/src/lib/testing/libgnunettesting.la \
268 $(top_builddir)/src/peerstore/libgnunetpeerstore.la \
269 $(top_builddir)/src/statistics/libgnunetstatistics.la \
270 $(top_builddir)/src/lib/hello/libgnunethello.la \
271 $(top_builddir)/src/service/arm/libgnunetarm.la \
272 $(top_builddir)/src/lib/util/libgnunetutil.la \
273 $(LTLIBINTL)
274libgnunet_test_transport_plugin_cmd_simple_send_broadcast_la_LDFLAGS = \
275 $(GN_PLUGIN_LDFLAGS)
276
277libgnunet_test_transport_plugin_cmd_simple_send_dv_la_SOURCES = \
278 test_transport_plugin_cmd_simple_send_dv.c
279libgnunet_test_transport_plugin_cmd_simple_send_dv_la_LIBADD = \
280 libgnunettransporttesting2.la \
281 libgnunettransportapplication.la \
282 libgnunettransportcore.la \
283 $(top_builddir)/src/lib/testing/libgnunettesting.la \
284 $(top_builddir)/src/peerstore/libgnunetpeerstore.la \
285 $(top_builddir)/src/statistics/libgnunetstatistics.la \
286 $(top_builddir)/src/lib/hello/libgnunethello.la \
287 $(top_builddir)/src/service/arm/libgnunetarm.la \
288 $(top_builddir)/src/lib/util/libgnunetutil.la \
289 $(LTLIBINTL)
290libgnunet_test_transport_plugin_cmd_simple_send_dv_la_LDFLAGS = \
291 $(GN_PLUGIN_LDFLAGS)
292
293check_PROGRAMS = \
294 test_communicator_basic-unix \
295 test_communicator_basic-tcp \
296 test_communicator_basic-udp \
297 test_communicator_basic-quic \
298 test_communicator_rekey-tcp \
299 test_communicator_rekey-udp \
300 test_communicator_backchannel-udp \
301 test_communicator_bidirect-tcp
302
303check_SCRIPTS= \
304 test_transport_start_testcase.sh \
305 test_transport_simple_send_performance.sh \
306 test_transport_nat_icmp_tcp.sh \
307 test_transport_nat_upnp.sh \
308 test_transport_simple_send_string.sh \
309 test_transport_simple_send.sh \
310 test_transport_simple_send_broadcast.sh \
311 test_transport_udp_backchannel.sh \
312 test_transport_simple_send_dv_circle.sh \
313 test_transport_simple_send_dv_inverse.sh
314
315if ENABLE_TEST_RUN
316AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
317TESTS = \
318 $(check_SCRIPTS) \
319 test_communicator_basic-unix \
320 test_communicator_basic-tcp \
321 test_communicator_basic-quic \
322 test_communicator_basic-udp \
323 test_communicator_rekey-tcp \
324 test_communicator_rekey-udp \
325 test_communicator_backchannel-udp \
326 test_communicator_bidirect-tcp
327endif
328
329
330test_transport_start_with_config_SOURCES = \
331 test_transport_start_with_config.c
332test_transport_start_with_config_LDADD = \
333 $(top_builddir)/src/lib/testing/libgnunettesting.la \
334 $(top_builddir)/src/lib/util/libgnunetutil.la \
335 $(top_builddir)/src/lib/hello/libgnunethello.la \
336 libgnunettransportcore.la \
337 libgnunettransporttesting2.la
338
339test_communicator_basic_unix_SOURCES = \
340 test_communicator_basic.c
341test_communicator_basic_unix_LDADD = \
342 libgnunettransporttesting2.la \
343 $(top_builddir)/src/lib/testing/libgnunettesting.la \
344 $(top_builddir)/src/lib/util/libgnunetutil.la \
345 $(top_builddir)/src/statistics/libgnunetstatistics.la
346
347test_communicator_basic_tcp_SOURCES = \
348 test_communicator_basic.c
349test_communicator_basic_tcp_LDADD = \
350 libgnunettransporttesting2.la \
351 $(top_builddir)/src/lib/testing/libgnunettesting.la \
352 $(top_builddir)/src/lib/util/libgnunetutil.la \
353 $(top_builddir)/src/statistics/libgnunetstatistics.la
354
355test_communicator_basic_udp_SOURCES = \
356 test_communicator_basic.c
357test_communicator_basic_udp_LDADD = \
358 libgnunettransporttesting2.la \
359 $(top_builddir)/src/lib/testing/libgnunettesting.la \
360 $(top_builddir)/src/lib/util/libgnunetutil.la \
361 $(top_builddir)/src/statistics/libgnunetstatistics.la
362
363test_communicator_basic_quic_SOURCES = \
364 test_communicator_basic.c
365test_communicator_basic_quic_LDADD = \
366 libgnunettransporttesting2.la \
367 $(top_builddir)/src/lib/testing/libgnunettesting.la \
368 $(top_builddir)/src/lib/util/libgnunetutil.la \
369 $(top_builddir)/src/statistics/libgnunetstatistics.la
370
371test_communicator_rekey_tcp_SOURCES = \
372 test_communicator_basic.c
373test_communicator_rekey_tcp_LDADD = \
374 libgnunettransporttesting2.la \
375 $(top_builddir)/src/lib/testing/libgnunettesting.la \
376 $(top_builddir)/src/lib/util/libgnunetutil.la \
377 $(top_builddir)/src/statistics/libgnunetstatistics.la
378
379test_communicator_rekey_udp_SOURCES = \
380 test_communicator_basic.c
381test_communicator_rekey_udp_LDADD = \
382 libgnunettransporttesting2.la \
383 $(top_builddir)/src/lib/testing/libgnunettesting.la \
384 $(top_builddir)/src/lib/util/libgnunetutil.la \
385 $(top_builddir)/src/statistics/libgnunetstatistics.la
386
387test_communicator_backchannel_udp_SOURCES = \
388 test_communicator_basic.c
389test_communicator_backchannel_udp_LDADD = \
390 libgnunettransporttesting2.la \
391 $(top_builddir)/src/lib/testing/libgnunettesting.la \
392 $(top_builddir)/src/lib/util/libgnunetutil.la \
393 $(top_builddir)/src/statistics/libgnunetstatistics.la
394
395test_communicator_bidirect_tcp_SOURCES = \
396 test_communicator_basic.c
397test_communicator_bidirect_tcp_LDADD = \
398 libgnunettransporttesting2.la \
399 $(top_builddir)/src/lib/testing/libgnunettesting.la \
400 $(top_builddir)/src/lib/util/libgnunetutil.la \
401 $(top_builddir)/src/statistics/libgnunetstatistics.la
402
403test_transport_api2_tcp_SOURCES = \
404 test_transport_api2.c
405test_transport_api2_tcp_LDADD = \
406 $(top_builddir)/src/lib/hello/libgnunethello.la \
407 $(top_builddir)/src/lib/util/libgnunetutil.la \
408 libgnunettransporttesting2.la
409
410EXTRA_DIST = \
411test_transport_start_testcase.sh \
412test_transport_simple_send_performance.sh \
413test_transport_nat_icmp_tcp.sh \
414test_transport_nat_upnp.sh \
415test_transport_simple_send_string.sh \
416test_transport_simple_send.sh \
417test_transport_simple_send_broadcast.sh \
418test_transport_udp_backchannel.sh \
419test_transport_simple_send_dv_circle.sh \
420test_transport_simple_send_dv_inverse.sh \
421gnunet-transport-certificate-creation.in \
422test_plugin_hostkey \
423test_plugin_hostkey.ecc \
424test_delay \
425template_cfg_peer1.conf\
426template_cfg_peer2.conf\
427test_transport_api_data.conf\
428test_transport_api_multi_peer1.conf\
429test_transport_api_multi_peer2.conf\
430test_transport_api_tcp_nat_peer1.conf\
431test_transport_api_tcp_nat_peer2.conf\
432test_transport_api_tcp_peer1.conf\
433test_transport_api_tcp_peer2.conf\
434test_transport_api2_tcp_peer1.conf\
435test_transport_api2_tcp_peer2.conf\
436test_transport_api_udp_nat_peer1.conf\
437test_transport_api_udp_nat_peer2.conf\
438test_transport_api_udp_peer1.conf\
439test_transport_api_udp_peer2.conf\
440test_transport_api_unix_peer1.conf\
441test_transport_api_unix_peer2.conf\
442test_transport_api_monitor_peers_peer1.conf\
443test_transport_api_monitor_peers_peer2.conf\
444test_transport_api_monitor_validation_peer1.conf\
445test_transport_api_monitor_validation_peer2.conf\
446test_transport_defaults.conf\
447test_communicator_unix_basic_peer1.conf \
448test_communicator_unix_basic_peer2.conf \
449test_communicator_tcp_basic_peer1.conf \
450test_communicator_tcp_basic_peer2.conf \
451test_communicator_udp_basic_peer1.conf \
452test_communicator_udp_basic_peer2.conf \
453test_communicator_tcp_rekey_peer1.conf \
454test_communicator_tcp_rekey_peer2.conf \
455test_communicator_udp_rekey_peer1.conf \
456test_communicator_udp_rekey_peer2.conf \
457test_communicator_udp_backchannel_peer1.conf \
458test_communicator_udp_backchannel_peer2.conf \
459test_communicator_tcp_bidirect_peer1.conf \
460test_communicator_tcp_bidirect_peer2.conf
diff --git a/src/transport/NOTES b/src/transport/NOTES
deleted file mode 100644
index 41404e1f9..000000000
--- a/src/transport/NOTES
+++ /dev/null
@@ -1,46 +0,0 @@
1KEY DESIGN CHOICES:
2 - who decides which connections to keep/create?
3 => higher level session/key management!
4 - who enforces things like F2F topology, etc?
5 => higher level session/key management!
6 - who tracks all known HELLOs & validates?
7 => We validate, PEERINFO tracks!
8 - who advertises our HELLO?
9 => us! (need background job; previously: advertising)
10 - who advertises other peers HELLOs?
11 => higher level (core?)
12 - who does bootstrapping?
13 => bootstrap service (external!)
14 - who enforces inbound bandwidth limits?
15 => transport-service and plugins! (previously: core);
16 either by limiting reads (TCP) or discarding packets
17 (transport-service)
18 - who enforces outbound bandwidth limits?
19 => transport_api!
20 - who decides outbound bandwidth limits?
21 => other peer, via core (need authenticated limits!)
22 - who decides inbound bandwidth limits?
23 => core / apps above core (need trust info)
24 - cost function for transports is latency estimate in ms
25 => plugin provides latency data, transport-service
26 selects plugin(s) for transmission
27 - who is responsible for fragmentation?
28 => plugins! (may use common shared library)
29 - should we require UDP to be reliable?
30 => NO. There are other places that may (rarely)
31 use messages that we can not fix
32 - how do we access the 50% of service that we need for TCP/UDP
33 from service.c without code replication or getting 50%
34 that we do not want (i.e. shutdown, pid-file-writing, etc.)
35 => use GNUNET_SERVICE_start/stop functions!
36 - At what level do we manage timeouts?
37 => At the plugin (TCP connections),
38 transport-service (neighbours) and
39 core (sessions) level!
40 => All plugins have to disconnect before service-level
41 disconnect occurs
42 => We can have a plugin-connection die, but the session
43 survives!
44 => We can have a session die (no further authenticated
45 communication) even if the plugin thinks it is still
46 up!
diff --git a/src/transport/benchmark.sh b/src/transport/benchmark.sh
deleted file mode 100755
index a29e6ec2d..000000000
--- a/src/transport/benchmark.sh
+++ /dev/null
@@ -1,13 +0,0 @@
1#!/bin/sh
2
3for i in $(seq 1 0)
4do
5 echo RUN $i
6 ./test_transport_api_reliability_http
7done
8
9for i in $(seq 1 100)
10do
11 echo RUN $i
12 ./test_transport_api_reliability_https
13done
diff --git a/src/transport/communicator.h b/src/transport/communicator.h
deleted file mode 100644
index 5ef43597d..000000000
--- a/src/transport/communicator.h
+++ /dev/null
@@ -1,138 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2014 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 transport/communicator.h
23 * @brief common internal definitions for communicator services
24 * @author Christian Grothoff
25 */
26#ifndef COMMUNICATOR_H
27#define COMMUNICAOTR_H
28
29#include "gnunet_util_lib.h"
30#include "gnunet_protocols.h"
31
32GNUNET_NETWORK_STRUCT_BEGIN
33
34/**
35 * Message used to tell a communicator about a successful
36 * key exchange.
37 *
38 * Note that this style of KX acknowledgement typically only applies
39 * for communicators where the underlying network protocol is
40 * unidirectional and/or lacks cryptography. Furthermore, this is
41 * just the recommended "generic" style, communicators are always free
42 * to implement original designs that better fit their requirements.
43 */
44struct GNUNET_TRANSPORT_CommunicatorGenericKXConfirmation
45{
46 /**
47 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_KX_CONFIRMATION
48 */
49 struct GNUNET_MessageHeader header;
50
51 /**
52 * Timestamp from the original sender which identifies the original KX.
53 */
54 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
55
56 /**
57 * How long does the receiver of the KX believe that the address
58 * on which the KX was received will continue to be valid.
59 */
60 struct GNUNET_TIME_RelativeNBO validity;
61
62 /**
63 * Hash of the shared secret. Specific hash function may depend on
64 * the communicator's protocol details.
65 */
66 struct GNUNET_HashCode token;
67};
68
69
70/**
71 * Message used to tell a communicator about the receiver's
72 * flow control limits and to acknowledge receipt of certain
73 * messages.
74 *
75 * Note that a sender MAY choose to violate the flow-control
76 * limits provided in this message by a receiver, which may
77 * result in messages being lost (after all, transport is an
78 * unreliable channel). So if the sender violates these
79 * constraints, it should expect that the receive will simply
80 * discard the (partially) received "old" messages.
81 *
82 * This way, if a sender or receiver crashes, there is no protocol
83 * violation.
84 *
85 * Note that this style of flow control typically only applies
86 * for communicators where the underlying network protocol does
87 * not already implement flow control. Furthermore, this is
88 * just the recommended "generic" style, communicators are always
89 * free to implement original designs that better fit their
90 * requirements.
91 */
92struct GNUNET_TRANSPORT_CommunicatorGenericFCLimits
93{
94 /**
95 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_FC_LIMITS
96 */
97 struct GNUNET_MessageHeader header;
98
99 /**
100 * Maximum number of messages beyond the acknowledged message
101 * number that can still be transmitted concurrently without
102 * further acknowledgements.
103 */
104 uint32_t msg_window_size;
105
106 /**
107 * Up to which message number were all messages received.
108 */
109 uint64_t msg_cummulative_ack;
110
111 /**
112 * Maximum number of payload bytes beyond the acknowledged
113 * number of bytes can still be transmitted without further
114 * acknowledgements.
115 */
116 uint64_t bytes_window_size;
117
118 /**
119 * Cumulative acknowledgement for number of bytes received.
120 */
121 uint64_t bytes_cummulative_ack;
122
123 /**
124 * Followed by a variable-size bitfield for messages received
125 * beyond @e msg_cummulative_ack. Index at offset 0 must thus
126 * be zero, otherwise @e msg_cummulative_ack should be
127 * increased. Note that this field can be overall of 0 bytes.
128 * The variable-size bitfield must be a multiple of 64 bits
129 * long.
130 */
131 /* uint64_t msg_selective_ack_field[]; */
132};
133
134
135GNUNET_NETWORK_STRUCT_END
136
137/* end of communicator.h */
138#endif
diff --git a/src/transport/gnunet-communicator-quic.c b/src/transport/gnunet-communicator-quic.c
deleted file mode 100644
index 0a7e511eb..000000000
--- a/src/transport/gnunet-communicator-quic.c
+++ /dev/null
@@ -1,1795 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2014, 2018, 2019 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 transport/gnunet-communicator-quic.c
23 * @brief Transport plugin using QUIC.
24 * @author Marshall Stone
25 * @author Martin Schanzenbach
26 *
27 * TODO:
28 * - Automatically generate self-signed x509 certificates and load from config
29 * - Figure out MTU and how we have to handle fragmentation in Quiche.
30 * - Mandate timeouts
31 * - Setup stats handler properly
32 * - Doxygen documentation of methods
33 * - Refactor code shared with UDP and TCP communicator
34 * - Performance testing
35 * - Check for memory leaks with coverity/valgrind
36 */
37#include "gnunet_common.h"
38#include "gnunet_util_lib.h"
39#include "gnunet_core_service.h"
40#include "quiche.h"
41#include "platform.h"
42#include "gnunet_protocols.h"
43#include "gnunet_signatures.h"
44#include "gnunet_constants.h"
45#include "gnunet_statistics_service.h"
46#include "gnunet_transport_application_service.h"
47#include "gnunet_transport_communication_service.h"
48#include "gnunet_nat_service.h"
49#include "stdint.h"
50#include "inttypes.h"
51
52#define COMMUNICATOR_CONFIG_SECTION "communicator-quic"
53#define COMMUNICATOR_ADDRESS_PREFIX "quic"
54#define MAX_DATAGRAM_SIZE 1350
55
56
57/* FIXME: Review all static lengths/contents below. Maybe this can be done smarter */
58/* Currently equivalent to QUICHE_MAX_CONN_ID_LEN */
59#define LOCAL_CONN_ID_LEN 20
60#define MAX_TOKEN_LEN \
61 sizeof("quiche") - 1 \
62 + sizeof(struct sockaddr_storage) \
63 + QUICHE_MAX_CONN_ID_LEN
64#define CID_LEN sizeof(uint8_t) * QUICHE_MAX_CONN_ID_LEN
65#define TOKEN_LEN sizeof (uint8_t) * MAX_TOKEN_LEN
66
67
68/* FIXME: Why 4?
69 Generic, bidirectional, client-initiated quic stream id */
70#define STREAMID_BI 4
71
72/**
73 * How long do we believe our addresses to remain up (before
74 * the other peer should revalidate).
75 */
76#define ADDRESS_VALIDITY_PERIOD GNUNET_TIME_UNIT_HOURS
77
78/**
79 * Map of DCID (uint8_t) -> quic_conn for quickly retrieving connections to other peers.
80 */
81struct GNUNET_CONTAINER_MultiHashMap *conn_map;
82
83/**
84 * Map of sockaddr -> struct PeerAddress
85 */
86struct GNUNET_CONTAINER_MultiHashMap *addr_map;
87
88/**
89 * Handle to the config
90 */
91static const struct GNUNET_CONFIGURATION_Handle *cfg;
92
93/**
94 * FIXME undocumented
95 */
96static struct GNUNET_TIME_Relative rekey_interval;
97
98/**
99 * FIXME undocumented
100 */
101static struct GNUNET_NETWORK_Handle *udp_sock;
102
103/**
104 * FIXME undocumented
105 */
106static struct GNUNET_SCHEDULER_Task *read_task;
107
108/**
109 * FIXME undocumented
110 */
111static struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
112
113/**
114 * FIXME undocumented
115 */
116static struct GNUNET_TRANSPORT_ApplicationHandle *ah;
117
118/**
119 * FIXME undocumented
120 */
121static int have_v6_socket;
122
123/**
124 * FIXME undocumented
125 */
126static uint16_t my_port;
127
128/**
129 * FIXME undocumented
130 */
131static unsigned long long rekey_max_bytes;
132
133/**
134 * FIXME undocumented
135 */
136static quiche_config *config = NULL;
137
138/**
139 * Our peer identity
140*/
141struct GNUNET_PeerIdentity my_identity;
142
143/**
144 * Our private key.
145 */
146static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
147
148/**
149 * Connection to NAT service.
150 */
151static struct GNUNET_NAT_Handle *nat;
152
153/**
154 * Information we track per peer we have recently been in contact with.
155 *
156 * (Since quiche handles crypto, handshakes, etc. we don't differentiate
157 * between SenderAddress and ReceiverAddress)
158 * FIXME: But we do a handshake as well. The flag in this struct seems to
159 * indicate this. Update comment!
160 */
161struct PeerAddress
162{
163 /**
164 * To whom are we talking to.
165 */
166 struct GNUNET_PeerIdentity target;
167
168 /**
169 * Flag to indicate whether we know the PeerIdentity (target) yet
170 */
171 int id_rcvd;
172
173 /**
174 * Flag to indicate whether we have sent OUR PeerIdentity to this peer
175 */
176 int id_sent;
177
178 /**
179 * Flag to indicate if we are the initiator of the connection
180 */
181 int is_receiver;
182
183 /**
184 * Address of the receiver in the human-readable format
185 * with the #COMMUNICATOR_ADDRESS_PREFIX.
186 */
187 char *foreign_addr;
188
189 /**
190 * Address of the other peer.
191 */
192 struct sockaddr *address;
193
194 /**
195 * Length of the address.
196 */
197 socklen_t address_len;
198
199 /**
200 * The QUIC connection associated with this peer
201 */
202 struct quic_conn *conn;
203
204 /**
205 * Default message queue we are providing for the #ch.
206 */
207 struct GNUNET_MQ_Handle *d_mq;
208
209 /**
210 * handle for default queue with the #ch.
211 */
212 struct GNUNET_TRANSPORT_QueueHandle *d_qh;
213
214 /**
215 * Timeout for this peer address.
216 */
217 struct GNUNET_TIME_Absolute timeout;
218
219 /**
220 * MTU we allowed transport for this peer's default queue.
221 * FIXME: MTU from quiche
222 */
223 size_t d_mtu;
224
225 /**
226 * Which network type does this queue use?
227 */
228 enum GNUNET_NetworkType nt;
229
230 /**
231 * receiver_destroy already called on receiver.
232 */
233 int peer_destroy_called;
234
235 /**
236 * FIXME implementation missing
237 * Entry in sender expiration heap.
238 */
239 // struct GNUNET_CONTAINER_HeapNode *hn;
240};
241
242// /**
243// * FIXME: Implementation missing
244// * Expiration heap for peers (contains `struct PeerAddress`)
245// */
246// static struct GNUNET_CONTAINER_Heap *peers_heap;
247
248/**
249 * ID of timeout task
250 */
251static struct GNUNET_SCHEDULER_Task *timeout_task;
252
253/**
254 * Network scanner to determine network types.
255 */
256static struct GNUNET_NT_InterfaceScanner *is;
257
258/**
259 * For logging statistics.
260 */
261static struct GNUNET_STATISTICS_Handle *stats;
262
263/**
264 * QUIC connection object. A connection has a unique SCID/DCID pair. Here we store our SCID
265 * (incoming packet DCID field == outgoing packet SCID field) for a given connection. This
266 * is hashed for each unique quic_conn.
267*/
268struct quic_conn
269{
270 uint8_t cid[LOCAL_CONN_ID_LEN];
271
272 quiche_conn *conn;
273};
274
275/**
276 * QUIC_header is used to store information received from an incoming QUIC packet
277*/
278struct QUIC_header
279{
280 uint8_t type;
281 uint32_t version;
282
283 uint8_t scid[QUICHE_MAX_CONN_ID_LEN];
284 size_t scid_len;
285
286 uint8_t dcid[QUICHE_MAX_CONN_ID_LEN];
287 size_t dcid_len;
288
289 uint8_t odcid[QUICHE_MAX_CONN_ID_LEN];
290 size_t odcid_len;
291
292 uint8_t token[MAX_TOKEN_LEN];
293 size_t token_len;
294};
295
296
297/**
298 * Given a PeerAddress, receive data from streams after doing connection logic.
299 * ASSUMES: connection is established to peer
300*/
301static void
302recv_from_streams (struct PeerAddress *peer)
303{
304 char stream_buf[UINT16_MAX];
305 size_t buf_size = UINT16_MAX;
306 char *buf_ptr = stream_buf;
307 struct GNUNET_MessageHeader *hdr;
308
309 uint64_t s = 0;
310 quiche_stream_iter *readable;
311 bool fin;
312 ssize_t recv_len;
313
314 readable = quiche_conn_readable (peer->conn->conn);
315 while (quiche_stream_iter_next (readable, &s))
316 {
317 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "stream %" PRIu64 " is readable\n",
318 s);
319 fin = false;
320 recv_len = quiche_conn_stream_recv (peer->conn->conn, s,
321 (uint8_t *) stream_buf, buf_size,
322 &fin);
323 if (recv_len < 0)
324 {
325 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
326 "error while receiving data from stream %" PRIu64 "\n", s);
327 break;
328 }
329 /**
330 * FIXME: Do not use implicit booleans. Use GNUNET_YES, GNUNET_NO, GNUNET_SYSERR
331 * and check for that.
332 *
333 * Initial packet should contain peerid if they are the initiator
334 */
335 if (! peer->is_receiver && GNUNET_NO == peer->id_rcvd)
336 {
337 if (recv_len < sizeof(struct GNUNET_PeerIdentity))
338 {
339 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
340 "message recv len of %zd less than length of peer identity\n",
341 recv_len);
342 return;
343 }
344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
345 "received peer identity\n");
346 struct GNUNET_PeerIdentity *pid = (struct
347 GNUNET_PeerIdentity *) stream_buf;
348 peer->target = *pid;
349 peer->id_rcvd = GNUNET_YES;
350 buf_ptr += sizeof(struct GNUNET_PeerIdentity);
351 recv_len -= sizeof(struct GNUNET_PeerIdentity);
352 }
353 /**
354 * Parse messages to pass to communicator
355 */
356 while (recv_len >= sizeof(struct GNUNET_MessageHeader))
357 {
358 hdr = (struct GNUNET_MessageHeader *) buf_ptr;
359 if (ntohs (hdr->size) > recv_len)
360 {
361 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
362 "message size stated (%d) is greater than length of rcvd data (%zd)!\n",
363 ntohs (hdr->size), recv_len);
364 return;
365 }
366 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "passing %zd bytes to core\n",
367 recv_len);
368 GNUNET_TRANSPORT_communicator_receive (ch, &peer->target, hdr,
369 ADDRESS_VALIDITY_PERIOD, NULL,
370 NULL);
371 recv_len -= ntohs (hdr->size);
372 buf_ptr += ntohs (hdr->size);
373 }
374 /**
375 * Check for leftover bytes
376 */
377 if (0 != recv_len)
378 {
379 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
380 "message recv len of %zd less than length of message header\n",
381 recv_len);
382 }
383 /**
384 * FIXME: comment useless
385 * fin
386 */
387 if (fin)
388 {
389 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
390 "fin received, closing connection\n");
391 if (0 > quiche_conn_close (peer->conn->conn, true, 0, NULL, 0))
392 {
393 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
394 "quiche failed to close connection to peer\n");
395 }
396 }
397 }
398 quiche_stream_iter_free (readable);
399}
400
401
402/**
403 * FIXME: review token generation, assure tokens are generated properly. doxygen
404 */
405static void
406mint_token (const uint8_t *dcid, size_t dcid_len,
407 struct sockaddr_storage *addr, socklen_t addr_len,
408 uint8_t *token, size_t *token_len)
409{
410 GNUNET_memcpy (token, "quiche", sizeof("quiche") - 1);
411 GNUNET_memcpy (token + sizeof("quiche") - 1, addr, addr_len);
412 GNUNET_memcpy (token + sizeof("quiche") - 1 + addr_len, dcid, dcid_len);
413
414 *token_len = sizeof("quiche") - 1 + addr_len + dcid_len;
415}
416
417
418static enum GNUNET_GenericReturnValue
419validate_token (const uint8_t *token, size_t token_len,
420 struct sockaddr_storage *addr, socklen_t addr_len,
421 uint8_t *odcid, size_t *odcid_len)
422{
423 if ((token_len < sizeof("quiche") - 1) ||
424 memcmp (token, "quiche", sizeof("quiche") - 1))
425 {
426 return GNUNET_NO;
427 }
428
429 token += sizeof("quiche") - 1;
430 token_len -= sizeof("quiche") - 1;
431
432 if ((token_len < addr_len) || memcmp (token, addr, addr_len))
433 {
434 return GNUNET_NO;
435 }
436
437 token += addr_len;
438 token_len -= addr_len;
439
440 if (*odcid_len < token_len)
441 {
442 return GNUNET_NO;
443 }
444
445 memcpy (odcid, token, token_len);
446 *odcid_len = token_len;
447
448 return GNUNET_OK;
449}
450
451
452static struct quic_conn*
453create_conn (uint8_t *scid, size_t scid_len,
454 uint8_t *odcid, size_t odcid_len,
455 struct sockaddr *local_addr,
456 socklen_t local_addr_len,
457 struct sockaddr_storage *peer_addr,
458 socklen_t peer_addr_len)
459{
460 struct quic_conn *conn;
461 quiche_conn *q_conn;
462 conn = GNUNET_new (struct quic_conn);
463 if (scid_len != LOCAL_CONN_ID_LEN)
464 {
465 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
466 "error while creating connection, scid length too short: %zu\n",
467 scid_len);
468 return NULL;
469 }
470
471 GNUNET_memcpy (conn->cid, scid, LOCAL_CONN_ID_LEN);
472 q_conn = quiche_accept (conn->cid, LOCAL_CONN_ID_LEN,
473 odcid, odcid_len,
474 local_addr,
475 local_addr_len,
476 (struct sockaddr *) peer_addr,
477 peer_addr_len,
478 config);
479 if (NULL == q_conn)
480 {
481 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
482 "quiche failed to create connection after call to quiche_accept\n");
483 return NULL;
484 }
485 conn->conn = q_conn;
486 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new quic connection created\n");
487 return conn;
488}
489
490
491static void
492flush_egress (struct quic_conn *conn)
493{
494 static uint8_t out[MAX_DATAGRAM_SIZE];
495 quiche_send_info send_info;
496
497 ssize_t written;
498 ssize_t sent;
499
500 while (1)
501 {
502 written = quiche_conn_send (conn->conn, out, sizeof(out), &send_info);
503 if (QUICHE_ERR_DONE == written)
504 {
505 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done writing quic packets\n");
506 break;
507 }
508 if (0 > written)
509 {
510 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
511 "quiche failed to create packet. quiche error: %zd\n",
512 written);
513 return;
514 }
515 sent = GNUNET_NETWORK_socket_sendto (udp_sock, out, written,
516 (struct sockaddr *) &send_info.to,
517 send_info.to_len);
518 if (sent != written)
519 {
520 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
521 "quiche failed to send data to peer\n");
522 return;
523 }
524 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent %zd bytes\n", sent);
525 }
526}
527
528
529/**
530 * Increment receiver timeout due to activity.
531 *
532 * @param receiver address for which the timeout should be rescheduled
533 */
534static void
535reschedule_peer_timeout (struct PeerAddress *peer)
536{
537 peer->timeout =
538 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
539 // GNUNET_CONTAINER_heap_update_cost (peer->hn,
540 // peer->timeout.abs_value_us);
541}
542
543
544/**
545 * Destroys a receiving state due to timeout or shutdown.
546 *
547 * @param receiver entity to close down
548 */
549static void
550peer_destroy (struct PeerAddress *peer)
551{
552 struct GNUNET_HashCode addr_key;
553
554 peer->peer_destroy_called = GNUNET_YES;
555 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
556 "Disconnecting peer for peer `%s'\n",
557 GNUNET_i2s (&peer->target));
558 if (NULL != peer->d_qh)
559 {
560 GNUNET_TRANSPORT_communicator_mq_del (peer->d_qh);
561 peer->d_qh = NULL;
562 }
563 // GNUNET_assert (peer == GNUNET_CONTAINER_heap_remove_node (peer->hn));
564 /**
565 * Remove peer from hashmap
566 */
567 GNUNET_CRYPTO_hash (peer->address, peer->address_len, &addr_key);
568 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_remove (addr_map, &addr_key,
569 peer))
570 {
571 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
572 "tried to remove non-existent peer from addr map\n");
573 return;
574 }
575 GNUNET_STATISTICS_set (stats,
576 "# peers active",
577 GNUNET_CONTAINER_multihashmap_size (addr_map),
578 GNUNET_NO);
579 quiche_conn_free (peer->conn->conn);
580 GNUNET_free (peer->address);
581 GNUNET_free (peer->foreign_addr);
582 GNUNET_free (peer->conn);
583 GNUNET_free (peer);
584}
585
586
587/**
588 * Iterator over all peers to clean up.
589 *
590 * @param cls NULL
591 * @param key peer->address
592 * @param value the peer to destroy
593 * @return #GNUNET_OK to continue to iterate
594 */
595static int
596get_peer_delete_it (void *cls,
597 const struct GNUNET_HashCode *key,
598 void *value)
599{
600 struct PeerAddress *peer = value;
601 (void) cls;
602 (void) key;
603 peer_destroy (peer);
604 return GNUNET_OK;
605}
606
607
608/**
609 * Signature of functions implementing the sending functionality of a
610 * message queue.
611 *
612 * @param mq the message queue
613 * @param msg the message to send
614 * @param impl_state our `struct PeerAddress`
615 */
616static void
617mq_send_d (struct GNUNET_MQ_Handle *mq,
618 const struct GNUNET_MessageHeader *msg,
619 void *impl_state)
620{
621 struct PeerAddress *peer = impl_state;
622 uint16_t msize = ntohs (msg->size);
623 ssize_t send_len;
624
625 if (NULL == peer->conn->conn)
626 {
627 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
628 "peer never established quic connection\n");
629 return;
630 }
631
632 GNUNET_assert (mq == peer->d_mq);
633 if (msize > peer->d_mtu)
634 {
635 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
636 "msize: %u, mtu: %lu\n",
637 msize,
638 peer->d_mtu);
639 GNUNET_break (0);
640 if (GNUNET_YES != peer->peer_destroy_called)
641 {
642 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
643 "peer destroy called, destroying peer\n");
644 peer_destroy (peer);
645 }
646 return;
647 }
648 reschedule_peer_timeout (peer);
649
650 send_len = quiche_conn_stream_send (peer->conn->conn, 4, (uint8_t *) msg,
651 msize, false);
652 if (send_len != msize)
653 {
654 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
655 "tried to send message and quiche returned %zd", send_len);
656 return;
657 }
658 flush_egress (peer->conn);
659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
660 "sent a message of %zd bytes\n", send_len);
661 GNUNET_MQ_impl_send_continue (mq);
662}
663
664
665/**
666 * Signature of functions implementing the destruction of a message
667 * queue. Implementations must not free @a mq, but should take care
668 * of @a impl_state.
669 *
670 * @param mq the message queue to destroy
671 * @param impl_state our `struct PeerAddress`
672 */
673static void
674mq_destroy_d (struct GNUNET_MQ_Handle *mq, void *impl_state)
675{
676 struct PeerAddress *peer = impl_state;
677 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
678 "Default MQ destroyed\n");
679 if (mq == peer->d_mq)
680 {
681 peer->d_mq = NULL;
682 if (GNUNET_YES != peer->peer_destroy_called)
683 peer_destroy (peer);
684 }
685}
686
687
688/**
689 * Implementation function that cancels the currently sent message.
690 *
691 * @param mq message queue
692 * @param impl_state our `struct PeerAddress`
693 */
694static void
695mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
696{
697 /* Cancellation is impossible with QUIC; bail */
698 GNUNET_assert (0);
699}
700
701
702/**
703 * Generic error handler, called with the appropriate
704 * error code and the same closure specified at the creation of
705 * the message queue.
706 * Not every message queue implementation supports an error handler.
707 *
708 * @param cls our `struct ReceiverAddress`
709 * @param error error code
710 */
711static void
712mq_error (void *cls, enum GNUNET_MQ_Error error)
713{
714 struct PeerAddress *peer = cls;
715
716 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
717 "MQ error in queue to %s: %d\n",
718 GNUNET_i2s (&peer->target),
719 (int) error);
720 peer_destroy (peer);
721}
722
723
724/**
725 * Convert UDP bind specification to a `struct sockaddr *`
726 *
727 * @param bindto bind specification to convert
728 * @param[out] sock_len set to the length of the address
729 * @return converted bindto specification
730 */
731static struct sockaddr *
732udp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
733{
734 struct sockaddr *in;
735 unsigned int port;
736 char dummy[2];
737 char *colon;
738 char *cp;
739
740 if (1 == sscanf (bindto, "%u%1s", &port, dummy))
741 {
742 /* interpreting value as just a PORT number */
743 if (port > UINT16_MAX)
744 {
745 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
746 "BINDTO specification `%s' invalid: value too large for port\n",
747 bindto);
748 return NULL;
749 }
750 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
751 (GNUNET_YES ==
752 GNUNET_CONFIGURATION_get_value_yesno (cfg,
753 COMMUNICATOR_CONFIG_SECTION,
754 "DISABLE_V6")))
755 {
756 struct sockaddr_in *i4;
757
758 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
759 i4->sin_family = AF_INET;
760 i4->sin_port = htons ((uint16_t) port);
761 *sock_len = sizeof(struct sockaddr_in);
762 in = (struct sockaddr *) i4;
763 }
764 else
765 {
766 struct sockaddr_in6 *i6;
767
768 i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
769 i6->sin6_family = AF_INET6;
770 i6->sin6_port = htons ((uint16_t) port);
771 *sock_len = sizeof(struct sockaddr_in6);
772 in = (struct sockaddr *) i6;
773 }
774 return in;
775 }
776 cp = GNUNET_strdup (bindto);
777 colon = strrchr (cp, ':');
778 if (NULL != colon)
779 {
780 /* interpret value after colon as port */
781 *colon = '\0';
782 colon++;
783 if (1 == sscanf (colon, "%u%1s", &port, dummy))
784 {
785 /* interpreting value as just a PORT number */
786 if (port > UINT16_MAX)
787 {
788 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
789 "BINDTO specification `%s' invalid: value too large for port\n",
790 bindto);
791 GNUNET_free (cp);
792 return NULL;
793 }
794 }
795 else
796 {
797 GNUNET_log (
798 GNUNET_ERROR_TYPE_ERROR,
799 "BINDTO specification `%s' invalid: last ':' not followed by number\n",
800 bindto);
801 GNUNET_free (cp);
802 return NULL;
803 }
804 }
805 else
806 {
807 /* interpret missing port as 0, aka pick any free one */
808 port = 0;
809 }
810 {
811 /* try IPv4 */
812 struct sockaddr_in v4;
813
814 memset (&v4, 0, sizeof(v4));
815 if (1 == inet_pton (AF_INET, cp, &v4.sin_addr))
816 {
817 v4.sin_family = AF_INET;
818 v4.sin_port = htons ((uint16_t) port);
819#if HAVE_SOCKADDR_IN_SIN_LEN
820 v4.sin_len = sizeof(struct sockaddr_in);
821#endif
822 in = GNUNET_memdup (&v4, sizeof(struct sockaddr_in));
823 *sock_len = sizeof(struct sockaddr_in);
824 GNUNET_free (cp);
825 return in;
826 }
827 }
828 {
829 /* try IPv6 */
830 struct sockaddr_in6 v6;
831 const char *start;
832
833 memset (&v6, 0, sizeof(v6));
834 start = cp;
835 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
836 {
837 start++; /* skip over '[' */
838 cp[strlen (cp) - 1] = '\0'; /* eat ']' */
839 }
840 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
841 {
842 v6.sin6_family = AF_INET6;
843 v6.sin6_port = htons ((uint16_t) port);
844#if HAVE_SOCKADDR_IN_SIN_LEN
845 v6.sin6_len = sizeof(sizeof(struct sockaddr_in6));
846#endif
847 in = GNUNET_memdup (&v6, sizeof(v6));
848 *sock_len = sizeof(v6);
849 GNUNET_free (cp);
850 return in;
851 }
852 }
853 /* #5528 FIXME (feature!): maybe also try getnameinfo()? */
854 GNUNET_free (cp);
855 return NULL;
856}
857
858
859/**
860 * Setup the MQ for the @a peer. If a queue exists,
861 * the existing one is destroyed. Then the MTU is
862 * recalculated and a fresh queue is initialized.
863 *
864 * @param peer peer to setup MQ for
865 */
866static void
867setup_peer_mq (struct PeerAddress *peer)
868{
869 size_t base_mtu;
870
871 switch (peer->address->sa_family)
872 {
873 case AF_INET:
874 base_mtu = 1480 /* Ethernet MTU, 1500 - Ethernet header - VLAN tag */
875 - sizeof(struct GNUNET_TUN_IPv4Header) /* 20 */
876 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
877 break;
878
879 case AF_INET6:
880 base_mtu = 1280 /* Minimum MTU required by IPv6 */
881 - sizeof(struct GNUNET_TUN_IPv6Header) /* 40 */
882 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
883 break;
884
885 default:
886 GNUNET_assert (0);
887 break;
888 }
889 /* MTU == base_mtu */
890 peer->d_mtu = base_mtu;
891
892 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
893 "Setting up MQs and QHs\n");
894 /* => Effective MTU for CORE will range from 1080 (IPv6 + KX) to
895 1404 (IPv4 + Box) bytes, depending on circumstances... */
896
897 if (NULL == peer->d_mq)
898 peer->d_mq = GNUNET_MQ_queue_for_callbacks (&mq_send_d,
899 &mq_destroy_d,
900 &mq_cancel,
901 peer,
902 NULL,
903 &mq_error,
904 peer);
905 peer->d_qh =
906 GNUNET_TRANSPORT_communicator_mq_add (ch,
907 &peer->target,
908 peer->foreign_addr,
909 1000,
910 GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED,
911 0, /* Priority */
912 peer->nt,
913 GNUNET_TRANSPORT_CS_OUTBOUND,
914 peer->d_mq);
915}
916
917
918/**
919 * Taken from: UDP communicator
920 * Converts @a address to the address string format used by this
921 * communicator in HELLOs.
922 *
923 * @param address the address to convert, must be AF_INET or AF_INET6.
924 * @param address_len number of bytes in @a address
925 * @return string representation of @a address
926 */
927static char *
928sockaddr_to_udpaddr_string (const struct sockaddr *address,
929 socklen_t address_len)
930{
931 char *ret;
932
933 switch (address->sa_family)
934 {
935 case AF_INET:
936 GNUNET_asprintf (&ret,
937 "%s-%s",
938 COMMUNICATOR_ADDRESS_PREFIX,
939 GNUNET_a2s (address, address_len));
940 break;
941
942 case AF_INET6:
943 GNUNET_asprintf (&ret,
944 "%s-%s",
945 COMMUNICATOR_ADDRESS_PREFIX,
946 GNUNET_a2s (address, address_len));
947 break;
948
949 default:
950 GNUNET_assert (0);
951 }
952 return ret;
953}
954
955
956/**
957 * Function called when the transport service has received a
958 * backchannel message for this communicator (!) via a different return
959 * path. Should be an acknowledgement.
960 *
961 * @param cls closure, NULL
962 * @param sender which peer sent the notification
963 * @param msg payload
964 */
965static void
966notify_cb (void *cls,
967 const struct GNUNET_PeerIdentity *sender,
968 const struct GNUNET_MessageHeader *msg)
969{
970 // const struct UDPAck *ack;
971
972 // (void) cls;
973 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
974 // "Storing UDPAck received from backchannel from %s\n",
975 // GNUNET_i2s_full (sender));
976 // if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK) ||
977 // (ntohs (msg->size) != sizeof(struct UDPAck)))
978 // {
979 // GNUNET_break_op (0);
980 // return;
981 // }
982 // ack = (const struct UDPAck *) msg;
983 // GNUNET_CONTAINER_multipeermap_get_multiple (receivers,
984 // sender,
985 // &handle_ack,
986 // (void *) ack);
987}
988
989
990/**
991 * Task run to check #receiver_heap and #sender_heap for timeouts.
992 *
993 * @param cls unused, NULL
994 */
995static void
996check_timeouts (void *cls)
997{
998 // struct GNUNET_TIME_Relative st;
999 // struct GNUNET_TIME_Relative rt;
1000 // struct GNUNET_TIME_Relative delay;
1001 // struct ReceiverAddress *receiver;
1002 // struct SenderAddress *sender;
1003
1004 // (void) cls;
1005 // timeout_task = NULL;
1006 // rt = GNUNET_TIME_UNIT_FOREVER_REL;
1007 // while (NULL != (receiver = GNUNET_CONTAINER_heap_peek (receivers_heap)))
1008 // {
1009 // /* if (GNUNET_YES != receiver->receiver_destroy_called) */
1010 // /* { */
1011 // rt = GNUNET_TIME_absolute_get_remaining (receiver->timeout);
1012 // if (0 != rt.rel_value_us)
1013 // break;
1014 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1015 // "Receiver timed out\n");
1016 // receiver_destroy (receiver);
1017 // // }
1018 // }
1019 // st = GNUNET_TIME_UNIT_FOREVER_REL;
1020 // while (NULL != (sender = GNUNET_CONTAINER_heap_peek (senders_heap)))
1021 // {
1022 // if (GNUNET_YES != sender->sender_destroy_called)
1023 // {
1024 // st = GNUNET_TIME_absolute_get_remaining (sender->timeout);
1025 // if (0 != st.rel_value_us)
1026 // break;
1027 // sender_destroy (sender);
1028 // }
1029 // }
1030 // delay = GNUNET_TIME_relative_min (rt, st);
1031 // if (delay.rel_value_us < GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1032 // timeout_task = GNUNET_SCHEDULER_add_delayed (delay, &check_timeouts, NULL);
1033}
1034
1035
1036/**
1037 * Function called by the transport service to initialize a
1038 * message queue given address information about another peer.
1039 * If and when the communication channel is established, the
1040 * communicator must call #GNUNET_TRANSPORT_communicator_mq_add()
1041 * to notify the service that the channel is now up. It is
1042 * the responsibility of the communicator to manage sane
1043 * retries and timeouts for any @a peer/@a address combination
1044 * provided by the transport service. Timeouts and retries
1045 * do not need to be signalled to the transport service.
1046 *
1047 * @param cls closure
1048 * @param peer identity of the other peer
1049 * @param address where to send the message, human-readable
1050 * communicator-specific format, 0-terminated, UTF-8
1051 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the provided address is
1052 * invalid
1053 */
1054static int
1055mq_init (void *cls, const struct GNUNET_PeerIdentity *peer_id, const
1056 char *address)
1057{
1058 struct PeerAddress *peer;
1059 const char *path;
1060 struct sockaddr *in;
1061 socklen_t in_len;
1062 struct GNUNET_HashCode addr_key;
1063 uint8_t scid[LOCAL_CONN_ID_LEN];
1064
1065 struct quic_conn *q_conn;
1066 char *bindto;
1067 socklen_t local_in_len;
1068 struct sockaddr *local_addr;
1069
1070 if (GNUNET_OK !=
1071 GNUNET_CONFIGURATION_get_value_string (cfg,
1072 COMMUNICATOR_CONFIG_SECTION,
1073 "BINDTO",
1074 &bindto))
1075 {
1076 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1077 COMMUNICATOR_CONFIG_SECTION,
1078 "BINDTO");
1079 return GNUNET_SYSERR;
1080 }
1081 local_addr = udp_address_to_sockaddr (bindto, &local_in_len);
1082
1083 if (0 != strncmp (address,
1084 COMMUNICATOR_ADDRESS_PREFIX "-",
1085 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
1086 {
1087 GNUNET_break_op (0);
1088 return GNUNET_SYSERR;
1089 }
1090 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
1091 in = udp_address_to_sockaddr (path, &in_len);
1092 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mq_init in_len length before: %d\n",
1093 in_len);
1094 /**
1095 * If we already have a queue with this peer, ignore
1096 */
1097 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address string in mq_init: %s\n",
1098 address);
1099 GNUNET_CRYPTO_hash (address, strlen (address), &addr_key);
1100 peer = GNUNET_CONTAINER_multihashmap_get (addr_map, &addr_key);
1101 if (NULL != peer)
1102 {
1103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1104 "ignoring transport service mq request, we already have an mq with this peer (address)\n");
1105 return GNUNET_SYSERR;
1106 }
1107 peer = GNUNET_new (struct PeerAddress);
1108 peer->address = in;
1109 peer->address_len = in_len;
1110 peer->target = *peer_id;
1111 peer->id_rcvd = GNUNET_YES;
1112 peer->is_receiver = GNUNET_YES;
1113 peer->nt = GNUNET_NT_scanner_get_type (is, in, in_len);
1114 peer->timeout =
1115 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1116 GNUNET_STATISTICS_set (stats,
1117 "# peers active",
1118 GNUNET_CONTAINER_multihashmap_size (addr_map),
1119 GNUNET_NO);
1120 peer->foreign_addr =
1121 sockaddr_to_udpaddr_string (peer->address, peer->address_len);
1122 /**
1123 * Insert peer into hashmap
1124 */
1125 GNUNET_CONTAINER_multihashmap_put (addr_map, &addr_key,
1126 peer,
1127 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1128 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1129 "mq_init added new peer to the addr map\n");
1130 /**
1131 * Before setting up peer mq, initiate a quic connection to the target (perform handshake w/ quiche)
1132 */
1133 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, scid,
1134 LOCAL_CONN_ID_LEN);
1135 q_conn = GNUNET_new (struct quic_conn);
1136 GNUNET_memcpy (q_conn->cid, scid, LOCAL_CONN_ID_LEN);
1137 peer->conn = q_conn;
1138 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1139 "attempting to perform QUIC handshake with peer\n");
1140 q_conn->conn = quiche_connect (peer->foreign_addr, scid, LOCAL_CONN_ID_LEN,
1141 local_addr,
1142 local_in_len, peer->address, peer->address_len,
1143 config);
1144 flush_egress (peer->conn);
1145 GNUNET_free (local_addr);
1146 return GNUNET_OK;
1147 /**
1148 * TODO: handle this
1149 */
1150 // if (NULL == timeout_task)
1151 // timeout_task = GNUNET_SCHEDULER_add_now (&check_timeouts, NULL);
1152}
1153
1154
1155static void
1156try_connection_reversal (void *cls,
1157 const struct sockaddr *addr,
1158 socklen_t addrlen)
1159{
1160 /* FIXME: support reversal: #5529 */
1161 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1162 "No connection reversal implemented!");
1163}
1164
1165
1166/**
1167 * Signature of the callback passed to #GNUNET_NAT_register() for
1168 * a function to call whenever our set of 'valid' addresses changes.
1169 *
1170 * @param cls closure
1171 * @param app_ctx[in,out] location where the app can store stuff
1172 * on add and retrieve it on remove
1173 * @param add_remove #GNUNET_YES to add a new public IP address,
1174 * #GNUNET_NO to remove a previous (now invalid) one
1175 * @param ac address class the address belongs to
1176 * @param addr either the previous or the new public IP address
1177 * @param addrlen actual length of the @a addr
1178 */
1179static void
1180nat_address_cb (void *cls,
1181 void **app_ctx,
1182 int add_remove,
1183 enum GNUNET_NAT_AddressClass ac,
1184 const struct sockaddr *addr,
1185 socklen_t addrlen)
1186{
1187 char *my_addr;
1188 struct GNUNET_TRANSPORT_AddressIdentifier *ai;
1189
1190 if (GNUNET_YES == add_remove)
1191 {
1192 enum GNUNET_NetworkType nt;
1193
1194 GNUNET_asprintf (&my_addr,
1195 "%s-%s",
1196 COMMUNICATOR_ADDRESS_PREFIX,
1197 GNUNET_a2s (addr, addrlen));
1198 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
1199 ai =
1200 GNUNET_TRANSPORT_communicator_address_add (ch,
1201 my_addr,
1202 nt,
1203 GNUNET_TIME_UNIT_FOREVER_REL);
1204 GNUNET_free (my_addr);
1205 *app_ctx = ai;
1206 }
1207 else
1208 {
1209 ai = *app_ctx;
1210 GNUNET_TRANSPORT_communicator_address_remove (ai);
1211 *app_ctx = NULL;
1212 }
1213}
1214
1215
1216/**
1217 * Shutdown the QUIC communicator.
1218 *
1219 * @param cls NULL (always)
1220 */
1221static void
1222do_shutdown (void *cls)
1223{
1224 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1225 "do_shutdown\n");
1226 GNUNET_CONTAINER_multihashmap_iterate (addr_map, &get_peer_delete_it, NULL);
1227 GNUNET_CONTAINER_multihashmap_destroy (addr_map);
1228 quiche_config_free (config);
1229
1230 if (NULL != timeout_task)
1231 {
1232 GNUNET_SCHEDULER_cancel (timeout_task);
1233 timeout_task = NULL;
1234 }
1235 if (NULL != read_task)
1236 {
1237 GNUNET_SCHEDULER_cancel (read_task);
1238 read_task = NULL;
1239 }
1240 if (NULL != udp_sock)
1241 {
1242 GNUNET_break (GNUNET_OK ==
1243 GNUNET_NETWORK_socket_close (udp_sock));
1244 udp_sock = NULL;
1245 }
1246 if (NULL != ch)
1247 {
1248 GNUNET_TRANSPORT_communicator_disconnect (ch);
1249 ch = NULL;
1250 }
1251 if (NULL != ah)
1252 {
1253 GNUNET_TRANSPORT_application_done (ah);
1254 ah = NULL;
1255 }
1256 if (NULL != my_private_key)
1257 {
1258 GNUNET_free (my_private_key);
1259 my_private_key = NULL;
1260 }
1261 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1262 "do_shutdown finished\n");
1263}
1264
1265
1266static void
1267sock_read (void *cls)
1268{
1269 struct sockaddr_storage sa;
1270 struct sockaddr_in *addr_verify;
1271 socklen_t salen = sizeof(sa);
1272 uint8_t buf[UINT16_MAX];
1273 uint8_t out[MAX_DATAGRAM_SIZE];
1274 ssize_t rcvd;
1275
1276 ssize_t process_pkt;
1277 struct QUIC_header quic_header;
1278 uint8_t new_cid[LOCAL_CONN_ID_LEN];
1279
1280 struct PeerAddress *peer;
1281 struct GNUNET_HashCode addr_key;
1282
1283 (void) cls;
1284 quic_header.scid_len = sizeof(quic_header.scid);
1285 quic_header.dcid_len = sizeof(quic_header.dcid);
1286 quic_header.odcid_len = sizeof(quic_header.odcid);
1287 quic_header.token_len = sizeof(quic_header.token);
1288 /**
1289 * Get local_addr, in_len for quiche
1290 */
1291 char *bindto;
1292 socklen_t in_len;
1293 if (GNUNET_OK !=
1294 GNUNET_CONFIGURATION_get_value_string (cfg,
1295 COMMUNICATOR_CONFIG_SECTION,
1296 "BINDTO",
1297 &bindto))
1298 {
1299 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1300 COMMUNICATOR_CONFIG_SECTION,
1301 "BINDTO");
1302 return;
1303 }
1304 struct sockaddr *local_addr = udp_address_to_sockaddr (bindto, &in_len);
1305
1306 read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1307 udp_sock,
1308 &sock_read,
1309 NULL);
1310 while (1)
1311 {
1312 rcvd = GNUNET_NETWORK_socket_recvfrom (udp_sock,
1313 buf,
1314 sizeof(buf),
1315 (struct sockaddr *) &sa,
1316 &salen);
1317 if (-1 == rcvd)
1318 {
1319 if (EAGAIN == errno)
1320 break; // We are done reading data
1321 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "recv");
1322 return;
1323 }
1324
1325 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1326 "Read %lu bytes\n", rcvd);
1327
1328 if (-1 == rcvd)
1329 {
1330 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "recv");
1331 return;
1332 }
1333 /**
1334 * FIXME: hashing address string vs ip/port. It is not ideal that
1335 * we hash the string, instead of the binary representation, but
1336 * for now it is certainly less code.
1337 * Note that simply hashing the sockaddr does NOT work because the
1338 * the struct is not portable.
1339 */
1340 const char *addr_string = sockaddr_to_udpaddr_string ((const struct
1341 sockaddr *) &sa,
1342 salen);
1343 GNUNET_CRYPTO_hash (addr_string, strlen (addr_string),
1344 &addr_key);
1345 GNUNET_free (addr_string);
1346 peer = GNUNET_CONTAINER_multihashmap_get (addr_map, &addr_key);
1347
1348 if (NULL == peer)
1349 {
1350 /**
1351 * Create new PeerAddress (receiver) with id_rcvd = false
1352 */
1353 peer = GNUNET_new (struct PeerAddress);
1354 peer->address = GNUNET_memdup (&sa, salen);
1355 peer->address_len = salen;
1356 peer->id_rcvd = GNUNET_NO;
1357 peer->id_sent = GNUNET_NO;
1358 peer->is_receiver = GNUNET_NO;
1359 peer->conn = NULL;
1360 peer->foreign_addr = sockaddr_to_udpaddr_string (peer->address,
1361 peer->address_len);
1362 /**
1363 * TODO: after connection established
1364 */
1365 // setup_peer_mq (peer);
1366 if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put (addr_map,
1367 &addr_key,
1368 peer,
1369 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1370 {
1371 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1372 "tried to add duplicate address into address map\n");
1373 return;
1374 }
1375 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1376 "sock_read added new peer to address map\n");
1377 }
1378
1379 /**
1380 * Parse QUIC info
1381 */
1382 int rc = quiche_header_info (buf, rcvd, LOCAL_CONN_ID_LEN,
1383 &quic_header.version,
1384 &quic_header.type, quic_header.scid,
1385 &quic_header.scid_len, quic_header.dcid,
1386 &quic_header.dcid_len,
1387 quic_header.token, &quic_header.token_len);
1388 if (0 > rc)
1389 {
1390 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1391 "failed to parse quic header: %d\n",
1392 rc);
1393 return;
1394 }
1395
1396 /**
1397 * New QUIC connection with peer
1398 */
1399 if (NULL == peer->conn)
1400 {
1401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1402 "attempting to create new connection\n");
1403 if (0 == quiche_version_is_supported (quic_header.version))
1404 {
1405 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1406 "quic version negotiation initiated\n");
1407 /**
1408 * FIXME variables are redeclared often. Refactor either
1409 * to declare variables once in the beginning or refactor into
1410 * method.
1411 *
1412 * Write a version negotiation packet to "out"
1413 */
1414 ssize_t written = quiche_negotiate_version (quic_header.scid,
1415 quic_header.scid_len,
1416 quic_header.dcid,
1417 quic_header.dcid_len,
1418 out, sizeof(out));
1419 if (0 > written)
1420 {
1421 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1422 "quiche failed to generate version negotiation packet\n");
1423 return;
1424 }
1425 ssize_t sent = GNUNET_NETWORK_socket_sendto (udp_sock,
1426 out,
1427 written,
1428 (struct sockaddr*) &sa,
1429 salen);
1430 if (sent != written)
1431 {
1432 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1433 "failed to send version negotiation packet to peer\n");
1434 return;
1435 }
1436 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1437 "sent %zd bytes to peer during version negotiation\n",
1438 sent);
1439 return;
1440 }
1441
1442 if (0 == quic_header.token_len)
1443 {
1444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "quic stateless retry\n");
1445 mint_token (quic_header.dcid, quic_header.dcid_len, &sa, salen,
1446 quic_header.token, &quic_header.token_len);
1447
1448 uint8_t new_cid[LOCAL_CONN_ID_LEN];
1449 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, new_cid,
1450 LOCAL_CONN_ID_LEN);
1451
1452 ssize_t written = quiche_retry (quic_header.scid, quic_header.scid_len,
1453 quic_header.dcid, quic_header.dcid_len,
1454 new_cid, LOCAL_CONN_ID_LEN,
1455 quic_header.token,
1456 quic_header.token_len,
1457 quic_header.version, out, sizeof(out));
1458 if (0 > written)
1459 {
1460 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1461 "quiche failed to write retry packet\n");
1462 return;
1463 }
1464 ssize_t sent = GNUNET_NETWORK_socket_sendto (udp_sock,
1465 out,
1466 written,
1467 (struct sockaddr*) &sa,
1468 salen);
1469 if (written != sent)
1470 {
1471 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "failed to send retry packet\n");
1472 return;
1473 }
1474
1475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent %zd bytes\n", sent);
1476 continue;
1477 }
1478
1479 if (GNUNET_OK != validate_token (quic_header.token, quic_header.token_len,
1480 &sa, salen,
1481 quic_header.odcid,
1482 &quic_header.odcid_len))
1483 {
1484 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1485 "invalid address validation token created\n");
1486 return;
1487 }
1488 peer->conn = create_conn (quic_header.dcid, quic_header.dcid_len,
1489 quic_header.odcid, quic_header.odcid_len,
1490 local_addr, in_len,
1491 &sa, salen);
1492 if (NULL == peer->conn)
1493 {
1494 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1495 "failed to create quic connection with peer\n");
1496 return;
1497 }
1498 } // null connection
1499
1500 quiche_recv_info recv_info = {
1501 (struct sockaddr *) &sa,
1502 salen,
1503
1504 local_addr,
1505 in_len,
1506 };
1507 /**
1508 * Send our PeerIdentity if the connection is established now
1509 */
1510 if (quiche_conn_is_established (peer->conn->conn) && ! peer->id_sent &&
1511 peer->is_receiver)
1512 {
1513 ssize_t send_len;
1514
1515 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1516 "handshake established with peer, sending our peer id\n");
1517 send_len = quiche_conn_stream_send (peer->conn->conn, STREAMID_BI,
1518 (const uint8_t *) &my_identity,
1519 sizeof(my_identity),
1520 false);
1521 if (0 > send_len)
1522 {
1523 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1524 "failed to write peer identity packet. quiche error: %zd\n",
1525 send_len);
1526 return;
1527 }
1528 flush_egress (peer->conn);
1529 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer identity sent to peer\n");
1530 peer->id_sent = GNUNET_YES;
1531 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "setting up peer mq\n");
1532 setup_peer_mq (peer);
1533 /**
1534 * After this, we should be all good to send/recv data
1535 */
1536 }
1537 process_pkt = quiche_conn_recv (peer->conn->conn, buf, rcvd, &recv_info);
1538 if (0 > process_pkt)
1539 {
1540 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1541 "quiche failed to process received packet: %zd\n",
1542 process_pkt);
1543 return;
1544 }
1545 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1546 "quiche processed %zd bytes\n", process_pkt);
1547 // Check for data on all available streams if the connection is established
1548 if (GNUNET_YES == quiche_conn_is_established (peer->conn->conn))
1549 {
1550 recv_from_streams (peer);
1551 }
1552 /**
1553 * TODO: Should we use a list instead of hashmap?
1554 * Overhead for hashing function, O(1) retrieval vs O(n) iteration with n=30?
1555 *
1556 * TODO: Is iteration necessary as in the quiche server example?
1557 */
1558 quiche_stats stats;
1559 quiche_path_stats path_stats;
1560
1561 flush_egress (peer->conn);
1562
1563 if (quiche_conn_is_closed (peer->conn->conn))
1564 {
1565 quiche_conn_stats (peer->conn->conn, &stats);
1566 quiche_conn_path_stats (peer->conn->conn, 0, &path_stats);
1567
1568 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1569 "connection closed. quiche stats: sent=%zu, recv=%zu\n",
1570 stats.sent, stats.recv);
1571 peer_destroy (peer);
1572 }
1573 }
1574 GNUNET_free (local_addr);
1575}
1576
1577
1578/**
1579 * Setup communicator and launch network interactions.
1580 *
1581 * @param cls NULL (always)
1582 * @param args remaining command-line arguments
1583 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1584 * @param c configuration
1585 */
1586static void
1587run (void *cls,
1588 char *const *args,
1589 const char *cfgfile,
1590 const struct GNUNET_CONFIGURATION_Handle *c)
1591{
1592 char *bindto;
1593 struct sockaddr *in;
1594 socklen_t in_len;
1595 struct sockaddr_storage in_sto;
1596 socklen_t sto_len;
1597
1598 (void) cls;
1599 cfg = c;
1600
1601 if (GNUNET_OK !=
1602 GNUNET_CONFIGURATION_get_value_string (cfg,
1603 COMMUNICATOR_CONFIG_SECTION,
1604 "BINDTO",
1605 &bindto))
1606 {
1607 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1608 COMMUNICATOR_CONFIG_SECTION,
1609 "BINDTO");
1610 return;
1611 }
1612
1613 in = udp_address_to_sockaddr (bindto, &in_len);
1614
1615 if (NULL == in)
1616 {
1617 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1618 "Failed to setup UDP socket address with path `%s'\n",
1619 bindto);
1620 GNUNET_free (bindto);
1621 return;
1622 }
1623 udp_sock =
1624 GNUNET_NETWORK_socket_create (in->sa_family,
1625 SOCK_DGRAM,
1626 IPPROTO_UDP);
1627 if (NULL == udp_sock)
1628 {
1629 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
1630 GNUNET_free (in);
1631 GNUNET_free (bindto);
1632 return;
1633 }
1634 if (AF_INET6 == in->sa_family)
1635 have_v6_socket = GNUNET_YES;
1636 if (GNUNET_OK !=
1637 GNUNET_NETWORK_socket_bind (udp_sock,
1638 in,
1639 in_len))
1640 {
1641 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
1642 "bind",
1643 bindto);
1644 GNUNET_NETWORK_socket_close (udp_sock);
1645 udp_sock = NULL;
1646 GNUNET_free (in);
1647 GNUNET_free (bindto);
1648 return;
1649 }
1650 sto_len = sizeof(in_sto);
1651 if (0 != getsockname (GNUNET_NETWORK_get_fd (udp_sock),
1652 (struct sockaddr *) &in_sto,
1653 &sto_len))
1654 {
1655 memcpy (&in_sto, in, in_len);
1656 sto_len = in_len;
1657 }
1658 GNUNET_free (in);
1659 GNUNET_free (bindto);
1660 in = (struct sockaddr *) &in_sto;
1661 in_len = sto_len;
1662 GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG,
1663 "transport",
1664 "Bound to `%s'\n",
1665 GNUNET_a2s ((const struct sockaddr *) &in_sto,
1666 sto_len));
1667 switch (in->sa_family)
1668 {
1669 case AF_INET:
1670 my_port = ntohs (((struct sockaddr_in *) in)->sin_port);
1671 break;
1672
1673 case AF_INET6:
1674 my_port = ntohs (((struct sockaddr_in6 *) in)->sin6_port);
1675 break;
1676
1677 default:
1678 GNUNET_break (0);
1679 my_port = 0;
1680 }
1681 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1682 /**
1683 * Setup QUICHE configuration
1684 */
1685 config = quiche_config_new (QUICHE_PROTOCOL_VERSION);
1686 quiche_config_verify_peer (config, false);
1687 /**
1688 * TODO: configure TLS cert
1689 */
1690 quiche_config_load_cert_chain_from_pem_file (config, "./cert.crt");
1691 quiche_config_load_priv_key_from_pem_file (config, "./cert.key");
1692 quiche_config_set_application_protos (config,
1693 (uint8_t *)
1694 "\x0ahq-interop\x05hq-29\x05hq-28\x05hq-27\x08http/0.9",
1695 38);
1696 quiche_config_set_max_idle_timeout (config, 5000);
1697 quiche_config_set_max_recv_udp_payload_size (config, 1200);
1698 quiche_config_set_max_send_udp_payload_size (config, 1200);
1699 quiche_config_set_initial_max_data (config, 10000000);
1700 quiche_config_set_initial_max_stream_data_bidi_local (config, 1000000);
1701 quiche_config_set_initial_max_stream_data_bidi_remote (config, 1000000);
1702 quiche_config_set_initial_max_stream_data_uni (config, 1000000);
1703 quiche_config_set_initial_max_streams_bidi (config, 100);
1704 quiche_config_set_initial_max_streams_uni (config, 100);
1705 quiche_config_set_cc_algorithm (config, QUICHE_CC_RENO);
1706 quiche_config_set_disable_active_migration (config, true);
1707 addr_map = GNUNET_CONTAINER_multihashmap_create (2, GNUNET_NO);
1708 /**
1709 * Get our public key for initial packet
1710 */
1711 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
1712 if (NULL == my_private_key)
1713 {
1714 GNUNET_log (
1715 GNUNET_ERROR_TYPE_ERROR,
1716 _ (
1717 "Transport service is lacking key configuration settings. Exiting.\n"));
1718 GNUNET_SCHEDULER_shutdown ();
1719 return;
1720 }
1721 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_identity.public_key);
1722 /* start reading */
1723 read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1724 udp_sock,
1725 &sock_read,
1726 NULL);
1727 ch = GNUNET_TRANSPORT_communicator_connect (cfg,
1728 COMMUNICATOR_CONFIG_SECTION,
1729 COMMUNICATOR_ADDRESS_PREFIX,
1730 GNUNET_TRANSPORT_CC_RELIABLE,
1731 &mq_init,
1732 NULL,
1733 &notify_cb,
1734 NULL);
1735 is = GNUNET_NT_scanner_init ();
1736 nat = GNUNET_NAT_register (cfg,
1737 COMMUNICATOR_CONFIG_SECTION,
1738 IPPROTO_UDP,
1739 1 /* one address */,
1740 (const struct sockaddr **) &in,
1741 &in_len,
1742 &nat_address_cb,
1743 try_connection_reversal,
1744 NULL /* closure */);
1745 if (NULL == ch)
1746 {
1747 GNUNET_break (0);
1748 GNUNET_SCHEDULER_shutdown ();
1749 return;
1750 }
1751 ah = GNUNET_TRANSPORT_application_init (cfg);
1752 if (NULL == ah)
1753 {
1754 GNUNET_break (0);
1755 GNUNET_SCHEDULER_shutdown ();
1756 return;
1757 }
1758
1759 /* start broadcasting */
1760 // if (GNUNET_YES !=
1761 // GNUNET_CONFIGURATION_get_value_yesno (cfg,
1762 // COMMUNICATOR_CONFIG_SECTION,
1763 // "DISABLE_BROADCAST"))
1764 // {
1765 // broadcast_task = GNUNET_SCHEDULER_add_now (&do_broadcast, NULL);
1766 // }
1767}
1768
1769
1770int
1771main (int argc, char *const *argv)
1772{
1773 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1774 GNUNET_GETOPT_OPTION_END
1775 };
1776 int ret;
1777
1778 GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG,
1779 "transport",
1780 "Starting quic communicator\n");
1781 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1782 return 2;
1783
1784 ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc,
1785 argv,
1786 "gnunet-communicator-quic",
1787 _ ("GNUnet QUIC communicator"),
1788 options,
1789 &run,
1790 NULL))
1791 ? 0
1792 : 1;
1793 GNUNET_free_nz ((void *) argv);
1794 return ret;
1795}
diff --git a/src/transport/gnunet-communicator-tcp.c b/src/transport/gnunet-communicator-tcp.c
deleted file mode 100644
index e7d989021..000000000
--- a/src/transport/gnunet-communicator-tcp.c
+++ /dev/null
@@ -1,4082 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2014, 2018, 2019 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 transport/gnunet-communicator-tcp.c
23 * @brief Transport plugin using TCP.
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - support NAT connection reversal method (#5529)
28 * - support other TCP-specific NAT traversal methods (#5531)
29 */
30#include "platform.h"
31#include "gnunet_util_lib.h"
32#include "gnunet_core_service.h"
33#include "gnunet_peerstore_service.h"
34#include "gnunet_protocols.h"
35#include "gnunet_signatures.h"
36#include "gnunet_constants.h"
37#include "gnunet_nat_service.h"
38#include "gnunet_statistics_service.h"
39#include "gnunet_transport_communication_service.h"
40#include "gnunet_resolver_service.h"
41
42
43/**
44 * How long until we give up on establishing an NAT connection?
45 * Must be > 4 RTT
46 */
47#define NAT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
48
49/**
50 * How long do we believe our addresses to remain up (before
51 * the other peer should revalidate).
52 */
53#define ADDRESS_VALIDITY_PERIOD \
54 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
55
56/**
57 * How many messages do we keep at most in the queue to the
58 * transport service before we start to drop (default,
59 * can be changed via the configuration file).
60 * Should be _below_ the level of the communicator API, as
61 * otherwise we may read messages just to have them dropped
62 * by the communicator API.
63 */
64#define DEFAULT_MAX_QUEUE_LENGTH 8
65
66/**
67 * Size of our IO buffers for ciphertext data. Must be at
68 * least UINT_MAX + sizeof (struct TCPBox).
69 */
70#define BUF_SIZE (2 * 64 * 1024 + sizeof(struct TCPBox))
71
72/**
73 * How often do we rekey based on time (at least)
74 */
75#define DEFAULT_REKEY_INTERVAL GNUNET_TIME_UNIT_DAYS
76
77/**
78 * How long do we wait until we must have received the initial KX?
79 */
80#define PROTO_QUEUE_TIMEOUT GNUNET_TIME_UNIT_MINUTES
81
82/**
83 * How often do we rekey based on number of bytes transmitted?
84 * (additionally randomized). Currently 400 MB
85 */
86#define REKEY_MAX_BYTES (1024LLU * 1024 * 400)
87
88/**
89 * Size of the initial key exchange message sent first in both
90 * directions.
91 */
92#define INITIAL_KX_SIZE \
93 (sizeof(struct GNUNET_CRYPTO_EcdhePublicKey) \
94 + sizeof(struct TCPConfirmation))
95
96/**
97 * Size of the initial core key exchange messages.
98 */
99#define INITIAL_CORE_KX_SIZE \
100 (sizeof(struct EphemeralKeyMessage) \
101 + sizeof(struct PingMessage) \
102 + sizeof(struct PongMessage))
103
104/**
105 * Address prefix used by the communicator.
106 */
107#define COMMUNICATOR_ADDRESS_PREFIX "tcp"
108
109/**
110 * Configuration section used by the communicator.
111 */
112#define COMMUNICATOR_CONFIG_SECTION "communicator-tcp"
113
114GNUNET_NETWORK_STRUCT_BEGIN
115
116
117/**
118 * Signature we use to verify that the ephemeral key was really chosen by
119 * the specified sender.
120 */
121struct TcpHandshakeSignature
122{
123 /**
124 * Purpose must be #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE
125 */
126 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
127
128 /**
129 * Identity of the inititor of the TCP connection (TCP client).
130 */
131 struct GNUNET_PeerIdentity sender;
132
133 /**
134 * Presumed identity of the target of the TCP connection (TCP server)
135 */
136 struct GNUNET_PeerIdentity receiver;
137
138 /**
139 * Ephemeral key used by the @e sender.
140 */
141 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
142
143 /**
144 * Monotonic time of @e sender, to possibly help detect replay attacks
145 * (if receiver persists times by sender).
146 */
147 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
148
149 /**
150 * Challenge value used to protect against replay attack, if there is no stored monotonic time value.
151 */
152 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
153};
154
155/**
156 * Signature we use to verify that the ack from the receiver of the ephemeral key was really send by
157 * the specified sender.
158 */
159struct TcpHandshakeAckSignature
160{
161 /**
162 * Purpose must be #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK
163 */
164 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
165
166 /**
167 * Identity of the inititor of the TCP connection (TCP client).
168 */
169 struct GNUNET_PeerIdentity sender;
170
171 /**
172 * Presumed identity of the target of the TCP connection (TCP server)
173 */
174 struct GNUNET_PeerIdentity receiver;
175
176 /**
177 * Monotonic time of @e sender, to possibly help detect replay attacks
178 * (if receiver persists times by sender).
179 */
180 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
181
182 /**
183 * Challenge value used to protect against replay attack, if there is no stored monotonic time value.
184 */
185 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
186};
187
188/**
189 * Encrypted continuation of TCP initial handshake.
190 */
191struct TCPConfirmation
192{
193 /**
194 * Sender's identity
195 */
196 struct GNUNET_PeerIdentity sender;
197
198 /**
199 * Sender's signature of type #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE
200 */
201 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
202
203 /**
204 * Monotonic time of @e sender, to possibly help detect replay attacks
205 * (if receiver persists times by sender).
206 */
207 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
208
209 /**
210 * Challenge value used to protect against replay attack, if there is no stored monotonic time value.
211 */
212 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
213
214};
215
216/**
217 * Ack for the encrypted continuation of TCP initial handshake.
218 */
219struct TCPConfirmationAck
220{
221
222
223 /**
224 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK.
225 */
226 struct GNUNET_MessageHeader header;
227
228 /**
229 * Sender's identity
230 */
231 struct GNUNET_PeerIdentity sender;
232
233 /**
234 * Sender's signature of type #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK
235 */
236 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
237
238 /**
239 * Monotonic time of @e sender, to possibly help detect replay attacks
240 * (if receiver persists times by sender).
241 */
242 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
243
244 /**
245 * Challenge value used to protect against replay attack, if there is no stored monotonic time value.
246 */
247 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
248
249};
250
251/**
252 * TCP message box. Always sent encrypted!
253 */
254struct TCPBox
255{
256 /**
257 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX. Warning: the
258 * header size EXCLUDES the size of the `struct TCPBox`. We usually
259 * never do this, but here the payload may truly be 64k *after* the
260 * TCPBox (as we have no MTU)!!
261 */
262 struct GNUNET_MessageHeader header;
263
264 /**
265 * HMAC for the following encrypted message. Yes, we MUST use
266 * mac-then-encrypt here, as we want to hide the message sizes on
267 * the wire (zero plaintext design!). Using CTR mode, padding oracle
268 * attacks do not apply. Besides, due to the use of ephemeral keys
269 * (hopefully with effective replay protection from monotonic time!)
270 * the attacker is limited in using the oracle.
271 */
272 struct GNUNET_ShortHashCode hmac;
273
274 /* followed by as may bytes of payload as indicated in @e header,
275 excluding the TCPBox itself! */
276};
277
278
279/**
280 * TCP rekey message box. Always sent encrypted! Data after
281 * this message will use the new key.
282 */
283struct TCPRekey
284{
285 /**
286 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY.
287 */
288 struct GNUNET_MessageHeader header;
289
290 /**
291 * HMAC for the following encrypted message. Yes, we MUST use
292 * mac-then-encrypt here, as we want to hide the message sizes on
293 * the wire (zero plaintext design!). Using CTR mode padding oracle
294 * attacks do not apply. Besides, due to the use of ephemeral keys
295 * (hopefully with effective replay protection from monotonic time!)
296 * the attacker is limited in using the oracle.
297 */
298 struct GNUNET_ShortHashCode hmac;
299
300 /**
301 * New ephemeral key.
302 */
303 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
304
305 /**
306 * Sender's signature of type #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY
307 */
308 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
309
310 /**
311 * Monotonic time of @e sender, to possibly help detect replay attacks
312 * (if receiver persists times by sender).
313 */
314 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
315};
316
317/**
318 * Signature we use to verify that the ephemeral key was really chosen by
319 * the specified sender.
320 */
321struct TcpRekeySignature
322{
323 /**
324 * Purpose must be #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY
325 */
326 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
327
328 /**
329 * Identity of the inititor of the TCP connection (TCP client).
330 */
331 struct GNUNET_PeerIdentity sender;
332
333 /**
334 * Presumed identity of the target of the TCP connection (TCP server)
335 */
336 struct GNUNET_PeerIdentity receiver;
337
338 /**
339 * Ephemeral key used by the @e sender.
340 */
341 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
342
343 /**
344 * Monotonic time of @e sender, to possibly help detect replay attacks
345 * (if receiver persists times by sender).
346 */
347 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
348};
349
350/**
351 * TCP finish. Sender asks for the connection to be closed.
352 * Needed/useful in case we drop RST/FIN packets on the GNUnet
353 * port due to the possibility of malicious RST/FIN injection.
354 */
355struct TCPFinish
356{
357 /**
358 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH.
359 */
360 struct GNUNET_MessageHeader header;
361
362 /**
363 * HMAC for the following encrypted message. Yes, we MUST use
364 * mac-then-encrypt here, as we want to hide the message sizes on
365 * the wire (zero plaintext design!). Using CTR mode padding oracle
366 * attacks do not apply. Besides, due to the use of ephemeral keys
367 * (hopefully with effective replay protection from monotonic time!)
368 * the attacker is limited in using the oracle.
369 */
370 struct GNUNET_ShortHashCode hmac;
371};
372
373/**
374 * Basically a WELCOME message, but with the purpose
375 * of giving the waiting peer a client handle to use
376 */
377struct TCPNATProbeMessage
378{
379 /**
380 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE.
381 */
382 struct GNUNET_MessageHeader header;
383
384 /**
385 * Identity of the sender of the message.
386 */
387 struct GNUNET_PeerIdentity clientIdentity;
388};
389
390GNUNET_NETWORK_STRUCT_END
391
392/**
393 * Struct for pending nat reversals.
394 */
395struct PendingReversal
396{
397 /*
398 * Timeout task.
399 */
400 struct GNUNET_SCHEDULER_Task *timeout_task;
401
402 /**
403 * To whom are we like to talk to.
404 */
405 struct GNUNET_PeerIdentity target;
406
407 /**
408 * Address the reversal was send to.
409 */
410 struct sockaddr *in;
411};
412
413/**
414 * Struct to use as closure.
415 */
416struct ListenTask
417{
418 /**
419 * ID of listen task
420 */
421 struct GNUNET_SCHEDULER_Task *listen_task;
422
423 /**
424 * Listen socket.
425 */
426 struct GNUNET_NETWORK_Handle *listen_sock;
427};
428
429/**
430 * Handle for a queue.
431 */
432struct Queue
433{
434 /**
435 * To whom are we talking to.
436 */
437 struct GNUNET_PeerIdentity target;
438
439 /**
440 * Listen socket.
441 */
442 struct GNUNET_NETWORK_Handle *listen_sock;
443
444 /**
445 * socket that we transmit all data with on this queue
446 */
447 struct GNUNET_NETWORK_Handle *sock;
448
449 /**
450 * cipher for decryption of incoming data.
451 */
452 gcry_cipher_hd_t in_cipher;
453
454 /**
455 * cipher for encryption of outgoing data.
456 */
457 gcry_cipher_hd_t out_cipher;
458
459 /**
460 * Shared secret for HMAC verification on incoming data.
461 */
462 struct GNUNET_HashCode in_hmac;
463
464 /**
465 * Shared secret for HMAC generation on outgoing data, ratcheted after
466 * each operation.
467 */
468 struct GNUNET_HashCode out_hmac;
469
470 /**
471 * ID of read task for this connection.
472 */
473 struct GNUNET_SCHEDULER_Task *read_task;
474
475 /**
476 * ID of write task for this connection.
477 */
478 struct GNUNET_SCHEDULER_Task *write_task;
479
480 /**
481 * Address of the other peer.
482 */
483 struct sockaddr *address;
484
485 /**
486 * How many more bytes may we sent with the current @e out_cipher
487 * before we should rekey?
488 */
489 uint64_t rekey_left_bytes;
490
491 /**
492 * Until what time may we sent with the current @e out_cipher
493 * before we should rekey?
494 */
495 struct GNUNET_TIME_Absolute rekey_time;
496
497 /**
498 * Length of the address.
499 */
500 socklen_t address_len;
501
502 /**
503 * Message queue we are providing for the #ch.
504 */
505 struct GNUNET_MQ_Handle *mq;
506
507 /**
508 * handle for this queue with the #ch.
509 */
510 struct GNUNET_TRANSPORT_QueueHandle *qh;
511
512 /**
513 * Number of bytes we currently have in our write queue.
514 */
515 unsigned long long bytes_in_queue;
516
517 /**
518 * Buffer for reading ciphertext from network into.
519 */
520 char cread_buf[BUF_SIZE];
521
522 /**
523 * buffer for writing ciphertext to network.
524 */
525 char cwrite_buf[BUF_SIZE];
526
527 /**
528 * Plaintext buffer for decrypted plaintext.
529 */
530 char pread_buf[UINT16_MAX + 1 + sizeof(struct TCPBox)];
531
532 /**
533 * Plaintext buffer for messages to be encrypted.
534 */
535 char pwrite_buf[UINT16_MAX + 1 + sizeof(struct TCPBox)];
536
537 /**
538 * At which offset in the ciphertext read buffer should we
539 * append more ciphertext for transmission next?
540 */
541 size_t cread_off;
542
543 /**
544 * At which offset in the ciphertext write buffer should we
545 * append more ciphertext from reading next?
546 */
547 size_t cwrite_off;
548
549 /**
550 * At which offset in the plaintext input buffer should we
551 * append more plaintext from decryption next?
552 */
553 size_t pread_off;
554
555 /**
556 * At which offset in the plaintext output buffer should we
557 * append more plaintext for encryption next?
558 */
559 size_t pwrite_off;
560
561 /**
562 * Timeout for this queue.
563 */
564 struct GNUNET_TIME_Absolute timeout;
565
566 /**
567 * How may messages did we pass from this queue to CORE for which we
568 * have yet to receive an acknoweldgement that CORE is done with
569 * them? If "large" (or even just non-zero), we should throttle
570 * reading to provide flow control. See also #DEFAULT_MAX_QUEUE_LENGTH
571 * and #max_queue_length.
572 */
573 unsigned int backpressure;
574
575 /**
576 * Which network type does this queue use?
577 */
578 enum GNUNET_NetworkType nt;
579
580 /**
581 * The connection status of this queue.
582 */
583 enum GNUNET_TRANSPORT_ConnectionStatus cs;
584
585 /**
586 * Is MQ awaiting a #GNUNET_MQ_impl_send_continue() call?
587 */
588 int mq_awaits_continue;
589
590 /**
591 * Did we enqueue a finish message and are closing down the queue?
592 */
593 int finishing;
594
595 /**
596 * Did we technically destroy this queue, but kept the allocation
597 * around because of @e backpressure not being zero yet? Used
598 * simply to delay the final #GNUNET_free() operation until
599 * #core_read_finished_cb() has been called.
600 */
601 int destroyed;
602
603 /**
604 * #GNUNET_YES if we just rekeyed and must thus possibly
605 * re-decrypt ciphertext.
606 */
607 int rekeyed;
608
609 /**
610 * Monotonic time value for rekey message.
611 */
612 struct GNUNET_TIME_AbsoluteNBO rekey_monotonic_time;
613
614 /**
615 * Monotonic time value for handshake message.
616 */
617 struct GNUNET_TIME_AbsoluteNBO handshake_monotonic_time;
618
619 /**
620 * Monotonic time value for handshake ack message.
621 */
622 struct GNUNET_TIME_AbsoluteNBO handshake_ack_monotonic_time;
623
624 /**
625 * Challenge value used to protect against replay attack, if there is no stored monotonic time value.
626 */
627 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
628
629 /**
630 * Challenge value received. In case of inbound connection we have to remember the value, because we send the challenge back later after we received the GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK.
631 */
632 struct GNUNET_CRYPTO_ChallengeNonceP challenge_received;
633
634 /**
635 * Iteration Context for retrieving the monotonic time send with key for rekeying.
636 */
637 struct GNUNET_PEERSTORE_IterateContext *rekey_monotime_get;
638
639 /**
640 * Iteration Context for retrieving the monotonic time send with the handshake.
641 */
642 struct GNUNET_PEERSTORE_IterateContext *handshake_monotime_get;
643
644 /**
645 * Iteration Context for retrieving the monotonic time send with the handshake ack.
646 */
647 struct GNUNET_PEERSTORE_IterateContext *handshake_ack_monotime_get;
648
649 /**
650 * Store Context for retrieving the monotonic time send with key for rekeying.
651 */
652 struct GNUNET_PEERSTORE_StoreContext *rekey_monotime_sc;
653
654 /**
655 * Store Context for retrieving the monotonic time send with the handshake.
656 */
657 struct GNUNET_PEERSTORE_StoreContext *handshake_monotime_sc;
658
659 /**
660 * Store Context for retrieving the monotonic time send with the handshake ack.
661 */
662 struct GNUNET_PEERSTORE_StoreContext *handshake_ack_monotime_sc;
663
664 /**
665 * Size of data received without KX challenge played back.
666 */
667 // TODO remove?
668 size_t unverified_size;
669
670 /**
671 * Has the initial (core) handshake already happened?
672 */
673 int initial_core_kx_done;
674};
675
676
677/**
678 * Handle for an incoming connection where we do not yet have enough
679 * information to setup a full queue.
680 */
681struct ProtoQueue
682{
683 /**
684 * Kept in a DLL.
685 */
686 struct ProtoQueue *next;
687
688 /**
689 * Kept in a DLL.
690 */
691 struct ProtoQueue *prev;
692
693 /**
694 * Listen socket.
695 */
696 struct GNUNET_NETWORK_Handle *listen_sock;
697
698 /**
699 * socket that we transmit all data with on this queue
700 */
701 struct GNUNET_NETWORK_Handle *sock;
702
703 /**
704 * ID of write task for this connection.
705 */
706 struct GNUNET_SCHEDULER_Task *write_task;
707
708 /**
709 * buffer for writing struct TCPNATProbeMessage to network.
710 */
711 char write_buf[sizeof (struct TCPNATProbeMessage)];
712
713 /**
714 * Offset of the buffer?
715 */
716 size_t write_off;
717
718 /**
719 * ID of read task for this connection.
720 */
721 struct GNUNET_SCHEDULER_Task *read_task;
722
723 /**
724 * Address of the other peer.
725 */
726 struct sockaddr *address;
727
728 /**
729 * Length of the address.
730 */
731 socklen_t address_len;
732
733 /**
734 * Timeout for this protoqueue.
735 */
736 struct GNUNET_TIME_Absolute timeout;
737
738 /**
739 * Buffer for reading all the information we need to upgrade from
740 * protoqueue to queue.
741 */
742 char ibuf[INITIAL_KX_SIZE];
743
744 /**
745 * Current offset for reading into @e ibuf.
746 */
747 size_t ibuf_off;
748};
749
750/**
751 * In case of port only configuration we like to bind to ipv4 and ipv6 addresses.
752 */
753struct PortOnlyIpv4Ipv6
754{
755 /**
756 * Ipv4 address we like to bind to.
757 */
758 struct sockaddr *addr_ipv4;
759
760 /**
761 * Length of ipv4 address.
762 */
763 socklen_t addr_len_ipv4;
764
765 /**
766 * Ipv6 address we like to bind to.
767 */
768 struct sockaddr *addr_ipv6;
769
770 /**
771 * Length of ipv6 address.
772 */
773 socklen_t addr_len_ipv6;
774
775};
776
777/**
778 * DLL to store the addresses we like to register at NAT service.
779 */
780struct Addresses
781{
782 /**
783 * Kept in a DLL.
784 */
785 struct Addresses *next;
786
787 /**
788 * Kept in a DLL.
789 */
790 struct Addresses *prev;
791
792 /**
793 * Address we like to register at NAT service.
794 */
795 struct sockaddr *addr;
796
797 /**
798 * Length of address we like to register at NAT service.
799 */
800 socklen_t addr_len;
801
802};
803
804
805/**
806 * Maximum queue length before we stop reading towards the transport service.
807 */
808static unsigned long long max_queue_length;
809
810/**
811 * For logging statistics.
812 */
813static struct GNUNET_STATISTICS_Handle *stats;
814
815/**
816 * Our environment.
817 */
818static struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
819
820/**
821 * Queues (map from peer identity to `struct Queue`)
822 */
823static struct GNUNET_CONTAINER_MultiPeerMap *queue_map;
824
825/**
826 * ListenTasks (map from socket to `struct ListenTask`)
827 */
828static struct GNUNET_CONTAINER_MultiHashMap *lt_map;
829
830/**
831 * Our public key.
832 */
833static struct GNUNET_PeerIdentity my_identity;
834
835/**
836 * The rekey interval
837 */
838static struct GNUNET_TIME_Relative rekey_interval;
839
840/**
841 * Our private key.
842 */
843static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
844
845/**
846 * Our configuration.
847 */
848static const struct GNUNET_CONFIGURATION_Handle *cfg;
849
850/**
851 * Network scanner to determine network types.
852 */
853static struct GNUNET_NT_InterfaceScanner *is;
854
855/**
856 * Connection to NAT service.
857 */
858static struct GNUNET_NAT_Handle *nat;
859
860/**
861 * Protoqueues DLL head.
862 */
863static struct ProtoQueue *proto_head;
864
865/**
866 * Protoqueues DLL tail.
867 */
868static struct ProtoQueue *proto_tail;
869
870/**
871 * Handle for DNS lookup of bindto address
872 */
873struct GNUNET_RESOLVER_RequestHandle *resolve_request_handle;
874
875/**
876 * Head of DLL with addresses we like to register at NAT servcie.
877 */
878struct Addresses *addrs_head;
879
880/**
881 * Head of DLL with addresses we like to register at NAT servcie.
882 */
883struct Addresses *addrs_tail;
884
885/**
886 * Head of DLL with ListenTasks.
887 */
888struct ListenTask *lts_head;
889
890/**
891 * Head of DLL with ListenTask.
892 */
893struct ListenTask *lts_tail;
894
895/**
896 * Number of addresses in the DLL for register at NAT service.
897 */
898int addrs_lens;
899
900
901/**
902 * Database for peer's HELLOs.
903 */
904static struct GNUNET_PEERSTORE_Handle *peerstore;
905
906/**
907 * A flag indicating we are already doing a shutdown.
908 */
909int shutdown_running = GNUNET_NO;
910
911/**
912 * The port the communicator should be assigned to.
913 */
914unsigned int bind_port;
915
916/**
917 * Map of pending reversals.
918 */
919struct GNUNET_CONTAINER_MultiHashMap *pending_reversals;
920
921/**
922 * We have been notified that our listen socket has something to
923 * read. Do the read and reschedule this function to be called again
924 * once more is available.
925 *
926 * @param cls NULL
927 */
928static void
929listen_cb (void *cls);
930
931/**
932 * Functions with this signature are called whenever we need
933 * to close a queue due to a disconnect or failure to
934 * establish a connection.
935 *
936 * @param queue queue to close down
937 */
938static void
939queue_destroy (struct Queue *queue)
940{
941 struct ListenTask *lt = NULL;
942 struct GNUNET_HashCode h_sock;
943 int sockfd;
944
945 if (NULL != queue->listen_sock)
946 {
947 sockfd = GNUNET_NETWORK_get_fd (queue->listen_sock);
948 GNUNET_CRYPTO_hash (&sockfd,
949 sizeof(int),
950 &h_sock);
951
952 lt = GNUNET_CONTAINER_multihashmap_get (lt_map, &h_sock);
953 }
954
955 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
956 "Disconnecting queue for peer `%s'\n",
957 GNUNET_i2s (&queue->target));
958 if (NULL != queue->rekey_monotime_sc)
959 {
960 GNUNET_PEERSTORE_store_cancel (queue->rekey_monotime_sc);
961 queue->rekey_monotime_sc = NULL;
962 }
963 if (NULL != queue->handshake_monotime_sc)
964 {
965 GNUNET_PEERSTORE_store_cancel (queue->handshake_monotime_sc);
966 queue->handshake_monotime_sc = NULL;
967 }
968 if (NULL != queue->handshake_ack_monotime_sc)
969 {
970 GNUNET_PEERSTORE_store_cancel (queue->handshake_ack_monotime_sc);
971 queue->handshake_ack_monotime_sc = NULL;
972 }
973 if (NULL != queue->rekey_monotime_get)
974 {
975 GNUNET_PEERSTORE_iterate_cancel (queue->rekey_monotime_get);
976 queue->rekey_monotime_get = NULL;
977 }
978 if (NULL != queue->handshake_monotime_get)
979 {
980 GNUNET_PEERSTORE_iterate_cancel (queue->handshake_monotime_get);
981 queue->handshake_monotime_get = NULL;
982 }
983 if (NULL != queue->handshake_ack_monotime_get)
984 {
985 GNUNET_PEERSTORE_iterate_cancel (queue->handshake_ack_monotime_get);
986 queue->handshake_ack_monotime_get = NULL;
987 }
988 if (NULL != queue->qh)
989 {
990 GNUNET_TRANSPORT_communicator_mq_del (queue->qh);
991 queue->qh = NULL;
992 }
993 GNUNET_assert (
994 GNUNET_YES ==
995 GNUNET_CONTAINER_multipeermap_remove (queue_map, &queue->target, queue));
996 GNUNET_STATISTICS_set (stats,
997 "# queues active",
998 GNUNET_CONTAINER_multipeermap_size (queue_map),
999 GNUNET_NO);
1000 if (NULL != queue->read_task)
1001 {
1002 GNUNET_SCHEDULER_cancel (queue->read_task);
1003 queue->read_task = NULL;
1004 }
1005 if (NULL != queue->write_task)
1006 {
1007 GNUNET_SCHEDULER_cancel (queue->write_task);
1008 queue->write_task = NULL;
1009 }
1010 if (GNUNET_SYSERR == GNUNET_NETWORK_socket_close (queue->sock))
1011 {
1012 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1013 "closing socket failed\n");
1014 }
1015 gcry_cipher_close (queue->in_cipher);
1016 gcry_cipher_close (queue->out_cipher);
1017 GNUNET_free (queue->address);
1018 if (0 != queue->backpressure)
1019 queue->destroyed = GNUNET_YES;
1020 else
1021 GNUNET_free (queue);
1022
1023 if (NULL == lt)
1024 return;
1025
1026 if ((! shutdown_running) && (NULL == lt->listen_task))
1027 {
1028 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1029 "add read net listen\n");
1030 lt->listen_task = GNUNET_SCHEDULER_add_read_net (
1031 GNUNET_TIME_UNIT_FOREVER_REL,
1032 lt->listen_sock,
1033 &listen_cb,
1034 lt);
1035 }
1036 else
1037 GNUNET_free (lt);
1038}
1039
1040
1041/**
1042 * Compute @a mac over @a buf, and ratched the @a hmac_secret.
1043 *
1044 * @param[in,out] hmac_secret secret for HMAC calculation
1045 * @param buf buffer to MAC
1046 * @param buf_size number of bytes in @a buf
1047 * @param[out] smac where to write the HMAC
1048 */
1049static void
1050calculate_hmac (struct GNUNET_HashCode *hmac_secret,
1051 const void *buf,
1052 size_t buf_size,
1053 struct GNUNET_ShortHashCode *smac)
1054{
1055 struct GNUNET_HashCode mac;
1056
1057 GNUNET_CRYPTO_hmac_raw (hmac_secret,
1058 sizeof(struct GNUNET_HashCode),
1059 buf,
1060 buf_size,
1061 &mac);
1062 /* truncate to `struct GNUNET_ShortHashCode` */
1063 memcpy (smac, &mac, sizeof(struct GNUNET_ShortHashCode));
1064 /* ratchet hmac key */
1065 GNUNET_CRYPTO_hash (hmac_secret,
1066 sizeof(struct GNUNET_HashCode),
1067 hmac_secret);
1068}
1069
1070
1071/**
1072 * Append a 'finish' message to the outgoing transmission. Once the
1073 * finish has been transmitted, destroy the queue.
1074 *
1075 * @param queue queue to shut down nicely
1076 */
1077static void
1078queue_finish (struct Queue *queue)
1079{
1080 struct TCPFinish fin;
1081
1082 memset (&fin, 0, sizeof(fin));
1083 fin.header.size = htons (sizeof(fin));
1084 fin.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH);
1085 calculate_hmac (&queue->out_hmac, &fin, sizeof(fin), &fin.hmac);
1086 /* if there is any message left in pwrite_buf, we
1087 overwrite it (possibly dropping the last message
1088 from CORE hard here) */
1089 memcpy (queue->pwrite_buf, &fin, sizeof(fin));
1090 queue->pwrite_off = sizeof(fin);
1091 /* This flag will ensure that #queue_write() no longer
1092 notifies CORE about the possibility of sending
1093 more data, and that #queue_write() will call
1094 #queue_destroy() once the @c fin was fully written. */
1095 queue->finishing = GNUNET_YES;
1096}
1097
1098
1099/**
1100 * Increment queue timeout due to activity. We do not immediately
1101 * notify the monitor here as that might generate excessive
1102 * signalling.
1103 *
1104 * @param queue queue for which the timeout should be rescheduled
1105 */
1106static void
1107reschedule_queue_timeout (struct Queue *queue)
1108{
1109 queue->timeout =
1110 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1111}
1112
1113
1114/**
1115 * Queue read task. If we hit the timeout, disconnect it
1116 *
1117 * @param cls the `struct Queue *` to disconnect
1118 */
1119static void
1120queue_read (void *cls);
1121
1122
1123/**
1124 * Core tells us it is done processing a message that transport
1125 * received on a queue with status @a success.
1126 *
1127 * @param cls a `struct Queue *` where the message originally came from
1128 * @param success #GNUNET_OK on success
1129 */
1130static void
1131core_read_finished_cb (void *cls, int success)
1132{
1133 struct Queue *queue = cls;
1134 if (GNUNET_OK != success)
1135 GNUNET_STATISTICS_update (stats,
1136 "# messages lost in communicator API towards CORE",
1137 1,
1138 GNUNET_NO);
1139 if (NULL == queue)
1140 return;
1141
1142 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1143 "backpressure %u\n",
1144 queue->backpressure);
1145
1146 queue->backpressure--;
1147 /* handle deferred queue destruction */
1148 if ((queue->destroyed) && (0 == queue->backpressure))
1149 {
1150 GNUNET_free (queue);
1151 return;
1152 }
1153 else if (GNUNET_YES != queue->destroyed)
1154 {
1155 reschedule_queue_timeout (queue);
1156 /* possibly unchoke reading, now that CORE made progress */
1157 if (NULL == queue->read_task)
1158 queue->read_task =
1159 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining (
1160 queue->timeout),
1161 queue->sock,
1162 &queue_read,
1163 queue);
1164 }
1165}
1166
1167
1168/**
1169 * We received @a plaintext_len bytes of @a plaintext on @a queue.
1170 * Pass it on to CORE. If transmission is actually happening,
1171 * increase backpressure counter.
1172 *
1173 * @param queue the queue that received the plaintext
1174 * @param plaintext the plaintext that was received
1175 * @param plaintext_len number of bytes of plaintext received
1176 */
1177static void
1178pass_plaintext_to_core (struct Queue *queue,
1179 const void *plaintext,
1180 size_t plaintext_len)
1181{
1182 const struct GNUNET_MessageHeader *hdr = plaintext;
1183 int ret;
1184
1185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1186 "pass message from %s to core\n",
1187 GNUNET_i2s (&queue->target));
1188
1189 if (ntohs (hdr->size) != plaintext_len)
1190 {
1191 /* NOTE: If we ever allow multiple CORE messages in one
1192 BOX, this will have to change! */
1193 GNUNET_break (0);
1194 return;
1195 }
1196 ret = GNUNET_TRANSPORT_communicator_receive (ch,
1197 &queue->target,
1198 hdr,
1199 ADDRESS_VALIDITY_PERIOD,
1200 &core_read_finished_cb,
1201 queue);
1202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1203 "passed to core\n");
1204 if (GNUNET_OK == ret)
1205 queue->backpressure++;
1206 GNUNET_break (GNUNET_NO != ret); /* backpressure not working!? */
1207 if (GNUNET_SYSERR == ret)
1208 GNUNET_STATISTICS_update (stats,
1209 "# bytes lost due to CORE not running",
1210 plaintext_len,
1211 GNUNET_NO);
1212}
1213
1214
1215/**
1216 * Setup @a cipher based on shared secret @a dh and decrypting
1217 * peer @a pid.
1218 *
1219 * @param dh shared secret
1220 * @param pid decrypting peer's identity
1221 * @param[out] cipher cipher to initialize
1222 * @param[out] hmac_key HMAC key to initialize
1223 */
1224static void
1225setup_cipher (const struct GNUNET_HashCode *dh,
1226 const struct GNUNET_PeerIdentity *pid,
1227 gcry_cipher_hd_t *cipher,
1228 struct GNUNET_HashCode *hmac_key)
1229{
1230 char key[256 / 8];
1231 char ctr[128 / 8];
1232
1233 GNUNET_assert (0 == gcry_cipher_open (cipher,
1234 GCRY_CIPHER_AES256 /* low level: go for speed */,
1235 GCRY_CIPHER_MODE_CTR,
1236 0 /* flags */));
1237 GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_kdf (key,
1238 sizeof(key),
1239 "TCP-key",
1240 strlen ("TCP-key"),
1241 dh,
1242 sizeof(*dh),
1243 pid,
1244 sizeof(*pid),
1245 NULL,
1246 0));
1247 GNUNET_assert (0 == gcry_cipher_setkey (*cipher, key, sizeof(key)));
1248 GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_kdf (ctr,
1249 sizeof(ctr),
1250 "TCP-ctr",
1251 strlen ("TCP-ctr"),
1252 dh,
1253 sizeof(*dh),
1254 pid,
1255 sizeof(*pid),
1256 NULL,
1257 0));
1258 gcry_cipher_setctr (*cipher, ctr, sizeof(ctr));
1259 GNUNET_assert (GNUNET_YES ==
1260 GNUNET_CRYPTO_kdf (hmac_key,
1261 sizeof(struct GNUNET_HashCode),
1262 "TCP-hmac",
1263 strlen ("TCP-hmac"),
1264 dh,
1265 sizeof(*dh),
1266 pid,
1267 sizeof(*pid),
1268 NULL,
1269 0));
1270}
1271
1272
1273/**
1274 * Callback called when peerstore store operation for rekey monotime value is finished.
1275 * @param cls Queue context the store operation was executed.
1276 * @param success Store operation was successful (GNUNET_OK) or not.
1277 */
1278static void
1279rekey_monotime_store_cb (void *cls, int success)
1280{
1281 struct Queue *queue = cls;
1282 if (GNUNET_OK != success)
1283 {
1284 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1285 "Failed to store rekey monotonic time in PEERSTORE!\n");
1286 }
1287 queue->rekey_monotime_sc = NULL;
1288}
1289
1290
1291/**
1292 * Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY
1293 * where found.
1294 * @param cls Queue context the store operation was executed.
1295 * @param record The record found or NULL if there is no record left.
1296 * @param emsg Message from peerstore.
1297 */
1298static void
1299rekey_monotime_cb (void *cls,
1300 const struct GNUNET_PEERSTORE_Record *record,
1301 const char *emsg)
1302{
1303 struct Queue *queue = cls;
1304 struct GNUNET_TIME_AbsoluteNBO *mtbe;
1305 struct GNUNET_TIME_Absolute mt;
1306 const struct GNUNET_PeerIdentity *pid;
1307 struct GNUNET_TIME_AbsoluteNBO *rekey_monotonic_time;
1308
1309 (void) emsg;
1310
1311 rekey_monotonic_time = &queue->rekey_monotonic_time;
1312 pid = &queue->target;
1313 if (NULL == record)
1314 {
1315 queue->rekey_monotime_get = NULL;
1316 return;
1317 }
1318 if (sizeof(*mtbe) != record->value_size)
1319 {
1320 GNUNET_break (0);
1321 return;
1322 }
1323 mtbe = record->value;
1324 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
1325 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
1326 queue->rekey_monotonic_time).abs_value_us)
1327 {
1328 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1329 "Queue from %s dropped, rekey monotime in the past\n",
1330 GNUNET_i2s (&queue->target));
1331 GNUNET_break (0);
1332 queue_finish (queue);
1333 return;
1334 }
1335 queue->rekey_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
1336 "transport_tcp_communicator",
1337 pid,
1338 GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY,
1339 rekey_monotonic_time,
1340 sizeof(*
1341 rekey_monotonic_time),
1342 GNUNET_TIME_UNIT_FOREVER_ABS,
1343 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
1344 &rekey_monotime_store_cb,
1345 queue);
1346}
1347
1348
1349/**
1350 * Setup cipher of @a queue for decryption.
1351 *
1352 * @param ephemeral ephemeral key we received from the other peer
1353 * @param[in,out] queue queue to initialize decryption cipher for
1354 */
1355static void
1356setup_in_cipher (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral,
1357 struct Queue *queue)
1358{
1359 struct GNUNET_HashCode k;
1360
1361 GNUNET_CRYPTO_eddsa_kem_decaps (my_private_key, ephemeral, &k);
1362 setup_cipher (&k, &my_identity, &queue->in_cipher, &queue->in_hmac);
1363}
1364
1365
1366/**
1367 * Handle @a rekey message on @a queue. The message was already
1368 * HMAC'ed, but we should additionally still check the signature.
1369 * Then we need to stop the old cipher and start afresh.
1370 *
1371 * @param queue the queue @a rekey was received on
1372 * @param rekey the rekey message
1373 */
1374static void
1375do_rekey (struct Queue *queue, const struct TCPRekey *rekey)
1376{
1377 struct TcpRekeySignature thp;
1378
1379 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY);
1380 thp.purpose.size = htonl (sizeof(thp));
1381 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1382 "do_rekey size %u\n",
1383 thp.purpose.size);
1384 thp.sender = queue->target;
1385 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1386 "sender %s\n",
1387 GNUNET_p2s (&thp.sender.public_key));
1388 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1389 "sender %s\n",
1390 GNUNET_p2s (&queue->target.public_key));
1391 thp.receiver = my_identity;
1392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1393 "receiver %s\n",
1394 GNUNET_p2s (&thp.receiver.public_key));
1395 thp.ephemeral = rekey->ephemeral;
1396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1397 "ephemeral %s\n",
1398 GNUNET_e2s (&thp.ephemeral));
1399 thp.monotonic_time = rekey->monotonic_time;
1400 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1401 "time %s\n",
1402 GNUNET_STRINGS_absolute_time_to_string (
1403 GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
1404 GNUNET_assert (ntohl ((&thp)->purpose.size) == sizeof (*(&thp)));
1405 if (GNUNET_OK !=
1406 GNUNET_CRYPTO_eddsa_verify (
1407 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY,
1408 &thp,
1409 &rekey->sender_sig,
1410 &queue->target.public_key))
1411 {
1412 GNUNET_break (0);
1413 queue_finish (queue);
1414 return;
1415 }
1416 queue->rekey_monotonic_time = rekey->monotonic_time;
1417 queue->rekey_monotime_get = GNUNET_PEERSTORE_iterate (peerstore,
1418 "transport_tcp_communicator",
1419 &queue->target,
1420 GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY,
1421 &rekey_monotime_cb,
1422 queue);
1423 gcry_cipher_close (queue->in_cipher);
1424 queue->rekeyed = GNUNET_YES;
1425 setup_in_cipher (&rekey->ephemeral, queue);
1426}
1427
1428
1429/**
1430 * Callback called when peerstore store operation for handshake ack monotime value is finished.
1431 * @param cls Queue context the store operation was executed.
1432 * @param success Store operation was successful (GNUNET_OK) or not.
1433 */
1434static void
1435handshake_ack_monotime_store_cb (void *cls, int success)
1436{
1437 struct Queue *queue = cls;
1438
1439 if (GNUNET_OK != success)
1440 {
1441 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1442 "Failed to store handshake ack monotonic time in PEERSTORE!\n");
1443 }
1444 queue->handshake_ack_monotime_sc = NULL;
1445}
1446
1447
1448/**
1449 * Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK
1450 * where found.
1451 * @param cls Queue context the store operation was executed.
1452 * @param record The record found or NULL if there is no record left.
1453 * @param emsg Message from peerstore.
1454 */
1455static void
1456handshake_ack_monotime_cb (void *cls,
1457 const struct GNUNET_PEERSTORE_Record *record,
1458 const char *emsg)
1459{
1460 struct Queue *queue = cls;
1461 struct GNUNET_TIME_AbsoluteNBO *mtbe;
1462 struct GNUNET_TIME_Absolute mt;
1463 const struct GNUNET_PeerIdentity *pid;
1464 struct GNUNET_TIME_AbsoluteNBO *handshake_ack_monotonic_time;
1465
1466 (void) emsg;
1467
1468 handshake_ack_monotonic_time = &queue->handshake_ack_monotonic_time;
1469 pid = &queue->target;
1470 if (NULL == record)
1471 {
1472 queue->handshake_ack_monotime_get = NULL;
1473 return;
1474 }
1475 if (sizeof(*mtbe) != record->value_size)
1476 {
1477 GNUNET_break (0);
1478 return;
1479 }
1480 mtbe = record->value;
1481 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
1482 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
1483 queue->handshake_ack_monotonic_time).abs_value_us)
1484 {
1485 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1486 "Queue from %s dropped, handshake ack monotime in the past\n",
1487 GNUNET_i2s (&queue->target));
1488 GNUNET_break (0);
1489 queue_finish (queue);
1490 return;
1491 }
1492 queue->handshake_ack_monotime_sc =
1493 GNUNET_PEERSTORE_store (peerstore,
1494 "transport_tcp_communicator",
1495 pid,
1496 GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK,
1497 handshake_ack_monotonic_time,
1498 sizeof(*handshake_ack_monotonic_time),
1499 GNUNET_TIME_UNIT_FOREVER_ABS,
1500 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
1501 &
1502 handshake_ack_monotime_store_cb,
1503 queue);
1504}
1505
1506
1507/**
1508 * Sending challenge with TcpConfirmationAck back to sender of ephemeral key.
1509 *
1510 * @param tc The TCPConfirmation originally send.
1511 * @param queue The queue context.
1512 */
1513static void
1514send_challenge (struct GNUNET_CRYPTO_ChallengeNonceP challenge,
1515 struct Queue *queue)
1516{
1517 struct TCPConfirmationAck tca;
1518 struct TcpHandshakeAckSignature thas;
1519
1520 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1521 "sending challenge\n");
1522
1523 tca.header.type = ntohs (
1524 GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK);
1525 tca.header.size = ntohs (sizeof(tca));
1526 tca.challenge = challenge;
1527 tca.sender = my_identity;
1528 tca.monotonic_time =
1529 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
1530 thas.purpose.purpose = htonl (
1531 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK);
1532 thas.purpose.size = htonl (sizeof(thas));
1533 thas.sender = my_identity;
1534 thas.receiver = queue->target;
1535 thas.monotonic_time = tca.monotonic_time;
1536 thas.challenge = tca.challenge;
1537 GNUNET_CRYPTO_eddsa_sign (my_private_key,
1538 &thas,
1539 &tca.sender_sig);
1540 GNUNET_assert (0 ==
1541 gcry_cipher_encrypt (queue->out_cipher,
1542 &queue->cwrite_buf[queue->cwrite_off],
1543 sizeof(tca),
1544 &tca,
1545 sizeof(tca)));
1546 queue->cwrite_off += sizeof(tca);
1547 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1548 "sending challenge done\n");
1549}
1550
1551
1552/**
1553 * Setup cipher for outgoing data stream based on target and
1554 * our ephemeral private key.
1555 *
1556 * @param queue queue to setup outgoing (encryption) cipher for
1557 */
1558static void
1559setup_out_cipher (struct Queue *queue, struct GNUNET_HashCode *dh)
1560{
1561 setup_cipher (dh, &queue->target, &queue->out_cipher, &queue->out_hmac);
1562 queue->rekey_time = GNUNET_TIME_relative_to_absolute (rekey_interval);
1563 queue->rekey_left_bytes =
1564 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, REKEY_MAX_BYTES);
1565}
1566
1567
1568/**
1569 * Inject a `struct TCPRekey` message into the queue's plaintext
1570 * buffer.
1571 *
1572 * @param queue queue to perform rekeying on
1573 */
1574static void
1575inject_rekey (struct Queue *queue)
1576{
1577 struct TCPRekey rekey;
1578 struct TcpRekeySignature thp;
1579 struct GNUNET_HashCode k;
1580
1581 GNUNET_assert (0 == queue->pwrite_off);
1582 memset (&rekey, 0, sizeof(rekey));
1583 GNUNET_CRYPTO_eddsa_kem_encaps (&queue->target.public_key, &rekey.ephemeral,
1584 &k);
1585 rekey.header.type = ntohs (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY);
1586 rekey.header.size = ntohs (sizeof(rekey));
1587 rekey.monotonic_time =
1588 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
1589 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY);
1590 thp.purpose.size = htonl (sizeof(thp));
1591 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1592 "inject_rekey size %u\n",
1593 thp.purpose.size);
1594 thp.sender = my_identity;
1595 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1596 "sender %s\n",
1597 GNUNET_p2s (&thp.sender.public_key));
1598 thp.receiver = queue->target;
1599 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1600 "receiver %s\n",
1601 GNUNET_p2s (&thp.receiver.public_key));
1602 thp.ephemeral = rekey.ephemeral;
1603 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1604 "ephemeral %s\n",
1605 GNUNET_e2s (&thp.ephemeral));
1606 thp.monotonic_time = rekey.monotonic_time;
1607 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1608 "time %s\n",
1609 GNUNET_STRINGS_absolute_time_to_string (
1610 GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
1611 GNUNET_CRYPTO_eddsa_sign (my_private_key,
1612 &thp,
1613 &rekey.sender_sig);
1614 calculate_hmac (&queue->out_hmac, &rekey, sizeof(rekey), &rekey.hmac);
1615 /* Encrypt rekey message with 'old' cipher */
1616 GNUNET_assert (0 ==
1617 gcry_cipher_encrypt (queue->out_cipher,
1618 &queue->cwrite_buf[queue->cwrite_off],
1619 sizeof(rekey),
1620 &rekey,
1621 sizeof(rekey)));
1622 queue->cwrite_off += sizeof(rekey);
1623 /* Setup new cipher for successive messages */
1624 gcry_cipher_close (queue->out_cipher);
1625 setup_out_cipher (queue, &k);
1626}
1627
1628
1629static int
1630pending_reversals_delete_it (void *cls,
1631 const struct GNUNET_HashCode *key,
1632 void *value)
1633{
1634 (void) cls;
1635 struct PendingReversal *pending_reversal = value;
1636
1637 if (NULL != pending_reversal->timeout_task)
1638 {
1639 GNUNET_SCHEDULER_cancel (pending_reversal->timeout_task);
1640 pending_reversal->timeout_task = NULL;
1641 }
1642 GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (
1643 pending_reversals,
1644 key,
1645 pending_reversal));
1646 GNUNET_free (pending_reversal->in);
1647 GNUNET_free (pending_reversal);
1648 return GNUNET_OK;
1649}
1650
1651
1652static void
1653check_and_remove_pending_reversal (struct sockaddr *in, sa_family_t sa_family,
1654 struct GNUNET_PeerIdentity *sender)
1655{
1656 if (AF_INET == sa_family)
1657 {
1658 struct PendingReversal *pending_reversal;
1659 struct GNUNET_HashCode key;
1660 struct sockaddr_in *natted_address;
1661
1662 natted_address = GNUNET_memdup (in, sizeof (struct sockaddr));
1663 natted_address->sin_port = 0;
1664 GNUNET_CRYPTO_hash (natted_address,
1665 sizeof(struct sockaddr),
1666 &key);
1667
1668 pending_reversal = GNUNET_CONTAINER_multihashmap_get (pending_reversals,
1669 &key);
1670 if (NULL != pending_reversal && (NULL == sender ||
1671 0 != memcmp (sender,
1672 &pending_reversal->target,
1673 sizeof(struct
1674 GNUNET_PeerIdentity))))
1675 {
1676 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1677 "Removing invalid pending reversal for `%s'at `%s'\n",
1678 GNUNET_i2s (&pending_reversal->target),
1679 GNUNET_a2s (in, sizeof (struct sockaddr)));
1680 pending_reversals_delete_it (NULL, &key, pending_reversal);
1681 }
1682 GNUNET_free (natted_address);
1683 }
1684}
1685
1686
1687/**
1688 * Closes socket and frees memory associated with @a pq.
1689 *
1690 * @param pq proto queue to free
1691 */
1692static void
1693free_proto_queue (struct ProtoQueue *pq)
1694{
1695 if (NULL != pq->listen_sock)
1696 {
1697 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pq->listen_sock));
1698 pq->listen_sock = NULL;
1699 }
1700 if (NULL != pq->read_task)
1701 {
1702 GNUNET_SCHEDULER_cancel (pq->read_task);
1703 pq->read_task = NULL;
1704 }
1705 if (NULL != pq->write_task)
1706 {
1707 GNUNET_SCHEDULER_cancel (pq->write_task);
1708 pq->write_task = NULL;
1709 }
1710 check_and_remove_pending_reversal (pq->address, pq->address->sa_family, NULL);
1711 GNUNET_NETWORK_socket_close (pq->sock);
1712 GNUNET_free (pq->address);
1713 GNUNET_CONTAINER_DLL_remove (proto_head, proto_tail, pq);
1714 GNUNET_free (pq);
1715}
1716
1717
1718/**
1719 * We have been notified that our socket is ready to write.
1720 * Then reschedule this function to be called again once more is available.
1721 *
1722 * @param cls a `struct ProtoQueue`
1723 */
1724static void
1725proto_queue_write (void *cls)
1726{
1727 struct ProtoQueue *pq = cls;
1728 ssize_t sent;
1729 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In proto queue write\n");
1730 pq->write_task = NULL;
1731 if (0 != pq->write_off)
1732 {
1733 sent = GNUNET_NETWORK_socket_send (pq->sock,
1734 pq->write_buf,
1735 pq->write_off);
1736 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1737 "Sent %lu bytes to TCP queue\n", sent);
1738 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1739 {
1740 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send");
1741 free_proto_queue (pq);
1742 return;
1743 }
1744 if (sent > 0)
1745 {
1746 size_t usent = (size_t) sent;
1747 pq->write_off -= usent;
1748 memmove (pq->write_buf,
1749 &pq->write_buf[usent],
1750 pq->write_off);
1751 }
1752 }
1753 /* do we care to write more? */
1754 if ((0 < pq->write_off))
1755 pq->write_task =
1756 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
1757 pq->sock,
1758 &proto_queue_write,
1759 pq);
1760}
1761
1762
1763/**
1764 * We have been notified that our socket is ready to write.
1765 * Then reschedule this function to be called again once more is available.
1766 *
1767 * @param cls a `struct Queue`
1768 */
1769static void
1770queue_write (void *cls)
1771{
1772 struct Queue *queue = cls;
1773 ssize_t sent;
1774 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In queue write\n");
1775 queue->write_task = NULL;
1776 if (0 != queue->cwrite_off)
1777 {
1778 sent = GNUNET_NETWORK_socket_send (queue->sock,
1779 queue->cwrite_buf,
1780 queue->cwrite_off);
1781 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1782 "Sent %lu bytes to TCP queue\n", sent);
1783 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1784 {
1785 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send");
1786 queue_destroy (queue);
1787 return;
1788 }
1789 if (sent > 0)
1790 {
1791 size_t usent = (size_t) sent;
1792 queue->cwrite_off -= usent;
1793 memmove (queue->cwrite_buf,
1794 &queue->cwrite_buf[usent],
1795 queue->cwrite_off);
1796 reschedule_queue_timeout (queue);
1797 }
1798 }
1799 /* can we encrypt more? (always encrypt full messages, needed
1800 such that #mq_cancel() can work!) */
1801 unsigned int we_do_not_need_to_rekey = (0 < queue->rekey_left_bytes
1802 - (queue->cwrite_off
1803 + queue->pwrite_off
1804 + sizeof (struct TCPRekey)));
1805 if (we_do_not_need_to_rekey &&
1806 (queue->pwrite_off > 0) &&
1807 (queue->cwrite_off + queue->pwrite_off <= BUF_SIZE))
1808 {
1809 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1810 "Encrypting %lu bytes\n", queue->pwrite_off);
1811 GNUNET_assert (0 ==
1812 gcry_cipher_encrypt (queue->out_cipher,
1813 &queue->cwrite_buf[queue->cwrite_off],
1814 queue->pwrite_off,
1815 queue->pwrite_buf,
1816 queue->pwrite_off));
1817 if (queue->rekey_left_bytes > queue->pwrite_off)
1818 queue->rekey_left_bytes -= queue->pwrite_off;
1819 else
1820 queue->rekey_left_bytes = 0;
1821 queue->cwrite_off += queue->pwrite_off;
1822 queue->pwrite_off = 0;
1823 }
1824 // if ((-1 != unverified_size)&& ((0 == queue->pwrite_off) &&
1825 if (((0 == queue->rekey_left_bytes) ||
1826 (0 == GNUNET_TIME_absolute_get_remaining (
1827 queue->rekey_time).rel_value_us)) &&
1828 (((0 == queue->pwrite_off) || ! we_do_not_need_to_rekey) &&
1829 (queue->cwrite_off + sizeof (struct TCPRekey) <= BUF_SIZE)))
1830 {
1831 inject_rekey (queue);
1832 }
1833 if ((0 == queue->pwrite_off) && (! queue->finishing) &&
1834 (GNUNET_YES == queue->mq_awaits_continue))
1835 {
1836 queue->mq_awaits_continue = GNUNET_NO;
1837 GNUNET_MQ_impl_send_continue (queue->mq);
1838 }
1839 /* did we just finish writing 'finish'? */
1840 if ((0 == queue->cwrite_off) && (GNUNET_YES == queue->finishing))
1841 {
1842 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1843 "Finishing queue\n");
1844 queue_destroy (queue);
1845 return;
1846 }
1847 /* do we care to write more? */
1848 if ((0 < queue->cwrite_off) || (0 < queue->pwrite_off))
1849 queue->write_task =
1850 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
1851 queue->sock,
1852 &queue_write,
1853 queue);
1854}
1855
1856
1857/**
1858 * Test if we have received a full message in plaintext.
1859 * If so, handle it.
1860 *
1861 * @param queue queue to process inbound plaintext for
1862 * @return number of bytes of plaintext handled, 0 for none
1863 */
1864static size_t
1865try_handle_plaintext (struct Queue *queue)
1866{
1867 const struct GNUNET_MessageHeader *hdr;
1868 const struct TCPConfirmationAck *tca;
1869 const struct TCPBox *box;
1870 const struct TCPRekey *rekey;
1871 const struct TCPFinish *fin;
1872 struct TCPRekey rekeyz;
1873 struct TCPFinish finz;
1874 struct GNUNET_ShortHashCode tmac;
1875 uint16_t type;
1876 size_t size = 0;
1877 struct TcpHandshakeAckSignature thas;
1878 const struct GNUNET_CRYPTO_ChallengeNonceP challenge = queue->challenge;
1879
1880 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1881 "try handle plaintext!\n");
1882
1883 hdr = (const struct GNUNET_MessageHeader *) queue->pread_buf;
1884 if ((sizeof(*hdr) > queue->pread_off))
1885 {
1886 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1887 "Handling plaintext, not even a header!\n");
1888 return 0; /* not even a header */
1889 }
1890
1891 if ((GNUNET_YES != queue->initial_core_kx_done) && (queue->unverified_size >
1892 INITIAL_CORE_KX_SIZE))
1893 {
1894 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1895 "Already received data of size %lu bigger than KX size %lu!\n",
1896 queue->unverified_size,
1897 INITIAL_CORE_KX_SIZE);
1898 GNUNET_break_op (0);
1899 queue_finish (queue);
1900 return 0;
1901 }
1902
1903 type = ntohs (hdr->type);
1904 switch (type)
1905 {
1906 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK:
1907 tca = (const struct TCPConfirmationAck *) queue->pread_buf;
1908 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1909 "start processing ack\n");
1910 if (sizeof(*tca) > queue->pread_off)
1911 {
1912 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1913 "Handling plaintext size of tca greater than pread offset.\n");
1914 return 0;
1915 }
1916 if (ntohs (hdr->size) != sizeof(*tca))
1917 {
1918 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1919 "Handling plaintext size does not match message type.\n");
1920 GNUNET_break_op (0);
1921 queue_finish (queue);
1922 return 0;
1923 }
1924
1925 thas.purpose.purpose = htonl (
1926 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK);
1927 thas.purpose.size = htonl (sizeof(thas));
1928 thas.sender = tca->sender;
1929 thas.receiver = my_identity;
1930 thas.monotonic_time = tca->monotonic_time;
1931 thas.challenge = tca->challenge;
1932
1933 if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_verify (
1934 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK,
1935 &thas,
1936 &tca->sender_sig,
1937 &tca->sender.public_key))
1938 {
1939 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1940 "Verification of signature failed!\n");
1941 GNUNET_break (0);
1942 queue_finish (queue);
1943 return 0;
1944 }
1945 if (0 != GNUNET_memcmp (&tca->challenge, &challenge))
1946 {
1947 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1948 "Challenge in TCPConfirmationAck not correct!\n");
1949 GNUNET_break (0);
1950 queue_finish (queue);
1951 return 0;
1952 }
1953
1954 queue->handshake_ack_monotime_get = GNUNET_PEERSTORE_iterate (peerstore,
1955 "transport_tcp_communicator",
1956 &queue->target,
1957 GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK,
1958 &
1959 handshake_ack_monotime_cb,
1960 queue);
1961
1962 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1963 "Handling plaintext, ack processed!\n");
1964
1965 if (GNUNET_TRANSPORT_CS_INBOUND == queue->cs)
1966 {
1967 send_challenge (queue->challenge_received, queue);
1968 queue->write_task =
1969 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
1970 queue->sock,
1971 &queue_write,
1972 queue);
1973 }
1974 else if (GNUNET_TRANSPORT_CS_OUTBOUND == queue->cs)
1975 {
1976 check_and_remove_pending_reversal (queue->address,
1977 queue->address->sa_family, NULL);
1978 }
1979
1980 /**
1981 * Once we received this ack, we consider this a verified connection.
1982 * FIXME: I am not sure this logic is sane here.
1983 */
1984 queue->initial_core_kx_done = GNUNET_YES;
1985
1986 char *foreign_addr;
1987
1988 switch (queue->address->sa_family)
1989 {
1990 case AF_INET:
1991 GNUNET_asprintf (&foreign_addr,
1992 "%s-%s",
1993 COMMUNICATOR_ADDRESS_PREFIX,
1994 GNUNET_a2s (queue->address, queue->address_len));
1995 break;
1996
1997 case AF_INET6:
1998 GNUNET_asprintf (&foreign_addr,
1999 "%s-%s",
2000 COMMUNICATOR_ADDRESS_PREFIX,
2001 GNUNET_a2s (queue->address, queue->address_len));
2002 break;
2003
2004 default:
2005 GNUNET_assert (0);
2006 }
2007
2008 queue->qh = GNUNET_TRANSPORT_communicator_mq_add (ch,
2009 &queue->target,
2010 foreign_addr,
2011 UINT16_MAX, /* no MTU */
2012 GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED,
2013 0, /* Priority */
2014 queue->nt,
2015 queue->cs,
2016 queue->mq);
2017
2018 GNUNET_free (foreign_addr);
2019
2020 size = ntohs (hdr->size);
2021 break;
2022 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX:
2023 /* Special case: header size excludes box itself! */
2024 box = (const struct TCPBox *) queue->pread_buf;
2025 if (ntohs (hdr->size) + sizeof(struct TCPBox) > queue->pread_off)
2026 return 0;
2027 calculate_hmac (&queue->in_hmac, &box[1], ntohs (hdr->size), &tmac);
2028 if (0 != memcmp (&tmac, &box->hmac, sizeof(tmac)))
2029 {
2030 GNUNET_break_op (0);
2031 queue_finish (queue);
2032 return 0;
2033 }
2034 pass_plaintext_to_core (queue, (const void *) &box[1], ntohs (hdr->size));
2035 size = ntohs (hdr->size) + sizeof(*box);
2036 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2037 "Handling plaintext, box processed!\n");
2038 break;
2039
2040 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY:
2041 rekey = (const struct TCPRekey *) queue->pread_buf;
2042 if (sizeof(*rekey) > queue->pread_off)
2043 return 0;
2044 if (ntohs (hdr->size) != sizeof(*rekey))
2045 {
2046 GNUNET_break_op (0);
2047 queue_finish (queue);
2048 return 0;
2049 }
2050 rekeyz = *rekey;
2051 memset (&rekeyz.hmac, 0, sizeof(rekeyz.hmac));
2052 calculate_hmac (&queue->in_hmac, &rekeyz, sizeof(rekeyz), &tmac);
2053 if (0 != memcmp (&tmac, &rekey->hmac, sizeof(tmac)))
2054 {
2055 GNUNET_break_op (0);
2056 queue_finish (queue);
2057 return 0;
2058 }
2059 do_rekey (queue, rekey);
2060 size = ntohs (hdr->size);
2061 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2062 "Handling plaintext, rekey processed!\n");
2063 break;
2064
2065 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH:
2066 fin = (const struct TCPFinish *) queue->pread_buf;
2067 if (sizeof(*fin) > queue->pread_off)
2068 return 0;
2069 if (ntohs (hdr->size) != sizeof(*fin))
2070 {
2071 GNUNET_break_op (0);
2072 queue_finish (queue);
2073 return 0;
2074 }
2075 finz = *fin;
2076 memset (&finz.hmac, 0, sizeof(finz.hmac));
2077 calculate_hmac (&queue->in_hmac, &rekeyz, sizeof(rekeyz), &tmac);
2078 if (0 != memcmp (&tmac, &fin->hmac, sizeof(tmac)))
2079 {
2080 GNUNET_break_op (0);
2081 queue_finish (queue);
2082 return 0;
2083 }
2084 /* handle FINISH by destroying queue */
2085 queue_destroy (queue);
2086 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2087 "Handling plaintext, finish processed!\n");
2088 break;
2089
2090 default:
2091 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2092 "Handling plaintext, nothing processed!\n");
2093 GNUNET_break_op (0);
2094 queue_finish (queue);
2095 return 0;
2096 }
2097 GNUNET_assert (0 != size);
2098 if (-1 != queue->unverified_size)
2099 queue->unverified_size += size;
2100 return size;
2101}
2102
2103
2104/**
2105 * Queue read task. If we hit the timeout, disconnect it
2106 *
2107 * @param cls the `struct Queue *` to disconnect
2108 */
2109static void
2110queue_read (void *cls)
2111{
2112 struct Queue *queue = cls;
2113 struct GNUNET_TIME_Relative left;
2114 ssize_t rcvd;
2115
2116 queue->read_task = NULL;
2117 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
2118 &queue->cread_buf[queue->cread_off],
2119 BUF_SIZE - queue->cread_off);
2120 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2121 "Received %zd bytes from TCP queue\n", rcvd);
2122 if (-1 == rcvd)
2123 {
2124 if ((EAGAIN != errno) && (EINTR != errno))
2125 {
2126 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "recv");
2127 queue_finish (queue);
2128 return;
2129 }
2130 /* try again */
2131 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2132 queue->read_task =
2133 GNUNET_SCHEDULER_add_read_net (left, queue->sock, &queue_read, queue);
2134 return;
2135 }
2136 if (0 != rcvd)
2137 reschedule_queue_timeout (queue);
2138 queue->cread_off += rcvd;
2139 while ((queue->pread_off < sizeof(queue->pread_buf)) &&
2140 (queue->cread_off > 0))
2141 {
2142 size_t max = GNUNET_MIN (sizeof(queue->pread_buf) - queue->pread_off,
2143 queue->cread_off);
2144 size_t done;
2145 size_t total;
2146 size_t old_pread_off = queue->pread_off;
2147
2148 GNUNET_assert (0 ==
2149 gcry_cipher_decrypt (queue->in_cipher,
2150 &queue->pread_buf[queue->pread_off],
2151 max,
2152 queue->cread_buf,
2153 max));
2154 queue->pread_off += max;
2155 total = 0;
2156 while (0 != (done = try_handle_plaintext (queue)))
2157 {
2158 /* 'done' bytes of plaintext were used, shift buffer */
2159 GNUNET_assert (done <= queue->pread_off);
2160 /* NOTE: this memmove() could possibly sometimes be
2161 avoided if we pass 'total' into try_handle_plaintext()
2162 and use it at an offset into the buffer there! */
2163 memmove (queue->pread_buf,
2164 &queue->pread_buf[done],
2165 queue->pread_off - done);
2166 queue->pread_off -= done;
2167 total += done;
2168 /* The last plaintext was a rekey, abort for now */
2169 if (GNUNET_YES == queue->rekeyed)
2170 break;
2171 }
2172 /* when we encounter a rekey message, the decryption above uses the
2173 wrong key for everything after the rekey; in that case, we have
2174 to re-do the decryption at 'total' instead of at 'max'.
2175 However, we have to take into account that the plaintext buffer may have
2176 already contained data and not jumped too far ahead in the ciphertext.
2177 If there is no rekey and the last message is incomplete (max > total),
2178 it is safe to keep the decryption so we shift by 'max' */
2179 if (GNUNET_YES == queue->rekeyed)
2180 {
2181 max = total - old_pread_off;
2182 queue->rekeyed = GNUNET_NO;
2183 queue->pread_off = 0;
2184 }
2185 memmove (queue->cread_buf, &queue->cread_buf[max], queue->cread_off - max);
2186 queue->cread_off -= max;
2187 }
2188 if (BUF_SIZE == queue->cread_off)
2189 return; /* buffer full, suspend reading */
2190 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2191 if (0 != left.rel_value_us)
2192 {
2193 if (max_queue_length > queue->backpressure)
2194 {
2195 /* continue reading */
2196 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2197 queue->read_task =
2198 GNUNET_SCHEDULER_add_read_net (left, queue->sock, &queue_read, queue);
2199 }
2200 return;
2201 }
2202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2203 "Queue %p was idle for %s, disconnecting\n",
2204 queue,
2205 GNUNET_STRINGS_relative_time_to_string (
2206 GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
2207 GNUNET_YES));
2208 queue_finish (queue);
2209}
2210
2211
2212/**
2213 * Convert a `struct sockaddr_in6 to a `struct sockaddr *`
2214 *
2215 * @param[out] sock_len set to the length of the address.
2216 * @param v6 The sockaddr_in6 to be converted.
2217 * @return The struct sockaddr *.
2218 */
2219static struct sockaddr *
2220tcp_address_to_sockaddr_numeric_v6 (socklen_t *sock_len,
2221 struct sockaddr_in6 v6,
2222 unsigned int port)
2223{
2224 struct sockaddr *in;
2225
2226 v6.sin6_family = AF_INET6;
2227 v6.sin6_port = htons ((uint16_t) port);
2228#if HAVE_SOCKADDR_IN_SIN_LEN
2229 v6.sin6_len = sizeof(sizeof(struct sockaddr_in6));
2230#endif
2231 v6.sin6_flowinfo = 0;
2232 v6.sin6_scope_id = 0;
2233 in = GNUNET_memdup (&v6, sizeof(v6));
2234 *sock_len = sizeof(struct sockaddr_in6);
2235
2236 return in;
2237}
2238
2239
2240/**
2241 * Convert a `struct sockaddr_in4 to a `struct sockaddr *`
2242 *
2243 * @param[out] sock_len set to the length of the address.
2244 * @param v4 The sockaddr_in4 to be converted.
2245 * @return The struct sockaddr *.
2246 */
2247static struct sockaddr *
2248tcp_address_to_sockaddr_numeric_v4 (socklen_t *sock_len,
2249 struct sockaddr_in v4,
2250 unsigned int port)
2251{
2252 struct sockaddr *in;
2253
2254 v4.sin_family = AF_INET;
2255 v4.sin_port = htons ((uint16_t) port);
2256#if HAVE_SOCKADDR_IN_SIN_LEN
2257 v4.sin_len = sizeof(struct sockaddr_in);
2258#endif
2259 in = GNUNET_memdup (&v4, sizeof(v4));
2260 *sock_len = sizeof(struct sockaddr_in);
2261 return in;
2262}
2263
2264
2265/**
2266 * Convert TCP bind specification to a `struct PortOnlyIpv4Ipv6 *`
2267 *
2268 * @param bindto bind specification to convert.
2269 * @return The converted bindto specification.
2270 */
2271static struct PortOnlyIpv4Ipv6 *
2272tcp_address_to_sockaddr_port_only (const char *bindto, unsigned int *port)
2273{
2274 struct PortOnlyIpv4Ipv6 *po;
2275 struct sockaddr_in *i4;
2276 struct sockaddr_in6 *i6;
2277 socklen_t sock_len_ipv4;
2278 socklen_t sock_len_ipv6;
2279
2280 /* interpreting value as just a PORT number */
2281 if (*port > UINT16_MAX)
2282 {
2283 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2284 "BINDTO specification `%s' invalid: value too large for port\n",
2285 bindto);
2286 return NULL;
2287 }
2288
2289 po = GNUNET_new (struct PortOnlyIpv4Ipv6);
2290
2291 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
2292 (GNUNET_YES ==
2293 GNUNET_CONFIGURATION_get_value_yesno (cfg,
2294 COMMUNICATOR_CONFIG_SECTION,
2295 "DISABLE_V6")))
2296 {
2297 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
2298 po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
2299 *port);
2300 po->addr_len_ipv4 = sock_len_ipv4;
2301 }
2302 else
2303 {
2304
2305 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
2306 po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
2307 *port);
2308 po->addr_len_ipv4 = sock_len_ipv4;
2309
2310 i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
2311 po->addr_ipv6 = tcp_address_to_sockaddr_numeric_v6 (&sock_len_ipv6, *i6,
2312 *port);
2313
2314 po->addr_len_ipv6 = sock_len_ipv6;
2315
2316 GNUNET_free (i6);
2317 }
2318
2319 GNUNET_free (i4);
2320
2321 return po;
2322}
2323
2324
2325/**
2326 * This Method extracts the address part of the BINDTO string.
2327 *
2328 * @param bindto String we extract the address part from.
2329 * @return The extracted address string.
2330 */
2331static char *
2332extract_address (const char *bindto)
2333{
2334 char *addr;
2335 char *start;
2336 char *token;
2337 char *cp;
2338 char *rest = NULL;
2339 char *res;
2340
2341 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2342 "extract address with bindto %s\n",
2343 bindto);
2344
2345 if (NULL == bindto)
2346 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2347 "bindto is NULL\n");
2348
2349 cp = GNUNET_strdup (bindto);
2350
2351 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2352 "extract address 2\n");
2353
2354 start = cp;
2355 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
2356 {
2357 start++; /* skip over '['*/
2358 cp[strlen (cp) - 1] = '\0'; /* eat ']'*/
2359 addr = GNUNET_strdup (start);
2360 }
2361 else
2362 {
2363 token = strtok_r (cp, "]", &rest);
2364 if (strlen (bindto) == strlen (token))
2365 {
2366 token = strtok_r (cp, ":", &rest);
2367 addr = GNUNET_strdup (token);
2368 }
2369 else
2370 {
2371 token++;
2372 res = GNUNET_strdup (token);
2373 addr = GNUNET_strdup (res);
2374 }
2375 }
2376
2377 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2378 "tcp address: %s\n",
2379 addr);
2380 GNUNET_free (cp);
2381 return addr;
2382}
2383
2384
2385/**
2386 * This Method extracts the port part of the BINDTO string.
2387 *
2388 * @param addr_and_port String we extract the port from.
2389 * @return The extracted port as unsigned int.
2390 */
2391static unsigned int
2392extract_port (const char *addr_and_port)
2393{
2394 unsigned int port;
2395 char dummy[2];
2396 char *token;
2397 char *addr;
2398 char *colon;
2399 char *cp;
2400 char *rest = NULL;
2401
2402 if (NULL != addr_and_port)
2403 {
2404 cp = GNUNET_strdup (addr_and_port);
2405 token = strtok_r (cp, "]", &rest);
2406 if (strlen (addr_and_port) == strlen (token))
2407 {
2408 colon = strrchr (cp, ':');
2409 if (NULL == colon)
2410 {
2411 GNUNET_free (cp);
2412 return 0;
2413 }
2414 addr = colon;
2415 addr++;
2416 }
2417 else
2418 {
2419 token = strtok_r (NULL, "]", &rest);
2420 if (NULL == token)
2421 {
2422 GNUNET_free (cp);
2423 return 0;
2424 }
2425 else
2426 {
2427 addr = token;
2428 addr++;
2429 }
2430 }
2431
2432
2433 if (1 == sscanf (addr, "%u%1s", &port, dummy))
2434 {
2435 /* interpreting value as just a PORT number */
2436 if (port > UINT16_MAX)
2437 {
2438 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2439 "Port `%u' invalid: value too large for port\n",
2440 port);
2441 GNUNET_free (cp);
2442 return 0;
2443 }
2444 }
2445 else
2446 {
2447 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2448 "BINDTO specification invalid: last ':' not followed by number\n");
2449 GNUNET_free (cp);
2450 return 0;
2451 }
2452 GNUNET_free (cp);
2453 }
2454 else
2455 {
2456 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2457 "return 0\n");
2458 /* interpret missing port as 0, aka pick any free one */
2459 port = 0;
2460 }
2461
2462 return port;
2463}
2464
2465
2466/**
2467 * Convert TCP bind specification to a `struct sockaddr *`
2468 *
2469 * @param bindto bind specification to convert
2470 * @param[out] sock_len set to the length of the address
2471 * @return converted bindto specification
2472 */
2473static struct sockaddr *
2474tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
2475{
2476 struct sockaddr *in;
2477 unsigned int port;
2478 struct sockaddr_in v4;
2479 struct sockaddr_in6 v6;
2480 char *start;
2481
2482 memset (&v4, 0, sizeof(v4));
2483 start = extract_address (bindto);
2484 GNUNET_assert (NULL != start);
2485 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2486 "start %s\n",
2487 start);
2488
2489 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2490 "!bindto %s\n",
2491 bindto);
2492
2493
2494 if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
2495 {
2496 // colon = strrchr (cp, ':');
2497 port = extract_port (bindto);
2498
2499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2500 "port %u\n",
2501 port);
2502
2503 in = tcp_address_to_sockaddr_numeric_v4 (sock_len, v4, port);
2504 }
2505 else if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
2506 {
2507 // colon = strrchr (cp, ':');
2508 port = extract_port (bindto);
2509 in = tcp_address_to_sockaddr_numeric_v6 (sock_len, v6, port);
2510 }
2511 else
2512 {
2513 GNUNET_assert (0);
2514 }
2515
2516 GNUNET_free (start);
2517 return in;
2518}
2519
2520
2521/**
2522 * Signature of functions implementing the sending functionality of a
2523 * message queue.
2524 *
2525 * @param mq the message queue
2526 * @param msg the message to send
2527 * @param impl_state our `struct Queue`
2528 */
2529static void
2530mq_send (struct GNUNET_MQ_Handle *mq,
2531 const struct GNUNET_MessageHeader *msg,
2532 void *impl_state)
2533{
2534 struct Queue *queue = impl_state;
2535 uint16_t msize = ntohs (msg->size);
2536 struct TCPBox box;
2537 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2538 "In MQ send. Queue finishing: %s; write task running: %s\n",
2539 (GNUNET_YES == queue->finishing) ? "yes" : "no",
2540 (NULL == queue->write_task) ? "yes" : "no");
2541 GNUNET_assert (mq == queue->mq);
2542 queue->mq_awaits_continue = GNUNET_YES;
2543 if (GNUNET_YES == queue->finishing)
2544 return; /* this queue is dying, drop msg */
2545 GNUNET_assert (0 == queue->pwrite_off);
2546 box.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX);
2547 box.header.size = htons (msize);
2548 calculate_hmac (&queue->out_hmac, msg, msize, &box.hmac);
2549 memcpy (&queue->pwrite_buf[queue->pwrite_off], &box, sizeof(box));
2550 queue->pwrite_off += sizeof(box);
2551 memcpy (&queue->pwrite_buf[queue->pwrite_off], msg, msize);
2552 queue->pwrite_off += msize;
2553 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2554 "%lu bytes of plaintext to send\n", queue->pwrite_off);
2555 GNUNET_assert (NULL != queue->sock);
2556 if (NULL == queue->write_task)
2557 queue->write_task =
2558 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
2559 queue->sock,
2560 &queue_write,
2561 queue);
2562}
2563
2564
2565/**
2566 * Signature of functions implementing the destruction of a message
2567 * queue. Implementations must not free @a mq, but should take care
2568 * of @a impl_state.
2569 *
2570 * @param mq the message queue to destroy
2571 * @param impl_state our `struct Queue`
2572 */
2573static void
2574mq_destroy (struct GNUNET_MQ_Handle *mq, void *impl_state)
2575{
2576 struct Queue *queue = impl_state;
2577
2578 if (mq == queue->mq)
2579 {
2580 queue->mq = NULL;
2581 queue_finish (queue);
2582 }
2583}
2584
2585
2586/**
2587 * Implementation function that cancels the currently sent message.
2588 *
2589 * @param mq message queue
2590 * @param impl_state our `struct Queue`
2591 */
2592static void
2593mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
2594{
2595 struct Queue *queue = impl_state;
2596
2597 GNUNET_assert (0 != queue->pwrite_off);
2598 queue->pwrite_off = 0;
2599}
2600
2601
2602/**
2603 * Generic error handler, called with the appropriate
2604 * error code and the same closure specified at the creation of
2605 * the message queue.
2606 * Not every message queue implementation supports an error handler.
2607 *
2608 * @param cls our `struct Queue`
2609 * @param error error code
2610 */
2611static void
2612mq_error (void *cls, enum GNUNET_MQ_Error error)
2613{
2614 struct Queue *queue = cls;
2615
2616 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2617 "MQ error in queue to %s: %d\n",
2618 GNUNET_i2s (&queue->target),
2619 (int) error);
2620 queue_finish (queue);
2621}
2622
2623
2624/**
2625 * Add the given @a queue to our internal data structure. Setup the
2626 * MQ processing and inform transport that the queue is ready. Must
2627 * be called after the KX for outgoing messages has been bootstrapped.
2628 *
2629 * @param queue queue to boot
2630 */
2631static void
2632boot_queue (struct Queue *queue)
2633{
2634 queue->nt =
2635 GNUNET_NT_scanner_get_type (is, queue->address, queue->address_len);
2636 (void) GNUNET_CONTAINER_multipeermap_put (
2637 queue_map,
2638 &queue->target,
2639 queue,
2640 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2641 GNUNET_STATISTICS_set (stats,
2642 "# queues active",
2643 GNUNET_CONTAINER_multipeermap_size (queue_map),
2644 GNUNET_NO);
2645 queue->timeout =
2646 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2647 queue->mq = GNUNET_MQ_queue_for_callbacks (&mq_send,
2648 &mq_destroy,
2649 &mq_cancel,
2650 queue,
2651 NULL,
2652 &mq_error,
2653 queue);
2654}
2655
2656
2657/**
2658 * Generate and transmit our ephemeral key and the signature for
2659 * the initial KX with the other peer. Must be called first, before
2660 * any other bytes are ever written to the output buffer. Note that
2661 * our cipher must already be initialized when calling this function.
2662 * Helper function for #start_initial_kx_out().
2663 *
2664 * @param queue queue to do KX for
2665 * @param epub our public key for the KX
2666 */
2667static void
2668transmit_kx (struct Queue *queue,
2669 const struct GNUNET_CRYPTO_EcdhePublicKey *epub)
2670{
2671 struct TcpHandshakeSignature ths;
2672 struct TCPConfirmation tc;
2673
2674 memcpy (queue->cwrite_buf, epub, sizeof(*epub));
2675 queue->cwrite_off = sizeof(*epub);
2676 /* compute 'tc' and append in encrypted format to cwrite_buf */
2677 tc.sender = my_identity;
2678 tc.monotonic_time =
2679 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
2680 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
2681 &tc.challenge,
2682 sizeof(tc.challenge));
2683 ths.purpose.purpose = htonl (
2684 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE);
2685 ths.purpose.size = htonl (sizeof(ths));
2686 ths.sender = my_identity;
2687 ths.receiver = queue->target;
2688 ths.ephemeral = *epub;
2689 ths.monotonic_time = tc.monotonic_time;
2690 ths.challenge = tc.challenge;
2691 GNUNET_CRYPTO_eddsa_sign (my_private_key,
2692 &ths,
2693 &tc.sender_sig);
2694 GNUNET_assert (0 ==
2695 gcry_cipher_encrypt (queue->out_cipher,
2696 &queue->cwrite_buf[queue->cwrite_off],
2697 sizeof(tc),
2698 &tc,
2699 sizeof(tc)));
2700 queue->challenge = tc.challenge;
2701 queue->cwrite_off += sizeof(tc);
2702
2703 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2704 "handshake written\n");
2705}
2706
2707
2708/**
2709 * Initialize our key material for outgoing transmissions and
2710 * inform the other peer about it. Must be called first before
2711 * any data is sent.
2712 *
2713 * @param queue the queue to setup
2714 */
2715static void
2716start_initial_kx_out (struct Queue *queue)
2717{
2718 struct GNUNET_CRYPTO_EcdhePublicKey epub;
2719 struct GNUNET_HashCode k;
2720
2721 GNUNET_CRYPTO_eddsa_kem_encaps (&queue->target.public_key, &epub, &k);
2722 setup_out_cipher (queue, &k);
2723 transmit_kx (queue, &epub);
2724}
2725
2726
2727/**
2728 * Callback called when peerstore store operation for handshake monotime is finished.
2729 * @param cls Queue context the store operation was executed.
2730 * @param success Store operation was successful (GNUNET_OK) or not.
2731 */
2732static void
2733handshake_monotime_store_cb (void *cls, int success)
2734{
2735 struct Queue *queue = cls;
2736 if (GNUNET_OK != success)
2737 {
2738 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2739 "Failed to store handshake monotonic time in PEERSTORE!\n");
2740 }
2741 queue->handshake_monotime_sc = NULL;
2742}
2743
2744
2745/**
2746 * Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE
2747 * where found.
2748 * @param cls Queue context the store operation was executed.
2749 * @param record The record found or NULL if there is no record left.
2750 * @param emsg Message from peerstore.
2751 */
2752static void
2753handshake_monotime_cb (void *cls,
2754 const struct GNUNET_PEERSTORE_Record *record,
2755 const char *emsg)
2756{
2757 struct Queue *queue = cls;
2758 struct GNUNET_TIME_AbsoluteNBO *mtbe;
2759 struct GNUNET_TIME_Absolute mt;
2760 const struct GNUNET_PeerIdentity *pid;
2761 struct GNUNET_TIME_AbsoluteNBO *handshake_monotonic_time;
2762
2763 (void) emsg;
2764
2765 handshake_monotonic_time = &queue->handshake_monotonic_time;
2766 pid = &queue->target;
2767 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2768 "tcp handshake with us %s\n",
2769 GNUNET_i2s (&my_identity));
2770 if (NULL == record)
2771 {
2772 queue->handshake_monotime_get = NULL;
2773 return;
2774 }
2775 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2776 "tcp handshake from peer %s\n",
2777 GNUNET_i2s (pid));
2778 if (sizeof(*mtbe) != record->value_size)
2779 {
2780 GNUNET_break (0);
2781 return;
2782 }
2783 mtbe = record->value;
2784 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
2785 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
2786 queue->handshake_monotonic_time).abs_value_us)
2787 {
2788 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2789 "Queue from %s dropped, handshake monotime in the past\n",
2790 GNUNET_i2s (&queue->target));
2791 GNUNET_break (0);
2792 queue_finish (queue);
2793 return;
2794 }
2795 queue->handshake_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
2796 "transport_tcp_communicator",
2797 pid,
2798 GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE,
2799 handshake_monotonic_time,
2800 sizeof(*
2801 handshake_monotonic_time),
2802 GNUNET_TIME_UNIT_FOREVER_ABS,
2803 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
2804 &
2805 handshake_monotime_store_cb,
2806 queue);
2807}
2808
2809
2810/**
2811 * We have received the first bytes from the other side on a @a queue.
2812 * Decrypt the @a tc contained in @a ibuf and check the signature.
2813 * Note that #setup_in_cipher() must have already been called.
2814 *
2815 * @param queue queue to decrypt initial bytes from other peer for
2816 * @param[out] tc where to store the result
2817 * @param ibuf incoming data, of size
2818 * `INITIAL_KX_SIZE`
2819 * @return #GNUNET_OK if the signature was OK, #GNUNET_SYSERR if not
2820 */
2821static int
2822decrypt_and_check_tc (struct Queue *queue,
2823 struct TCPConfirmation *tc,
2824 char *ibuf)
2825{
2826 struct TcpHandshakeSignature ths;
2827 enum GNUNET_GenericReturnValue ret;
2828
2829 GNUNET_assert (
2830 0 ==
2831 gcry_cipher_decrypt (queue->in_cipher,
2832 tc,
2833 sizeof(*tc),
2834 &ibuf[sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)],
2835 sizeof(*tc)));
2836 ths.purpose.purpose = htonl (
2837 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE);
2838 ths.purpose.size = htonl (sizeof(ths));
2839 ths.sender = tc->sender;
2840 ths.receiver = my_identity;
2841 memcpy (&ths.ephemeral, ibuf, sizeof(struct GNUNET_CRYPTO_EcdhePublicKey));
2842 ths.monotonic_time = tc->monotonic_time;
2843 ths.challenge = tc->challenge;
2844 ret = GNUNET_CRYPTO_eddsa_verify (
2845 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE,
2846 &ths,
2847 &tc->sender_sig,
2848 &tc->sender.public_key);
2849 if (GNUNET_YES == ret)
2850 queue->handshake_monotime_get =
2851 GNUNET_PEERSTORE_iterate (peerstore,
2852 "transport_tcp_communicator",
2853 &queue->target,
2854 GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE,
2855 &handshake_monotime_cb,
2856 queue);
2857 return ret;
2858}
2859
2860
2861/**
2862 * Read from the socket of the queue until we have enough data
2863 * to initialize the decryption logic and can switch to regular
2864 * reading.
2865 *
2866 * @param cls a `struct Queue`
2867 */
2868static void
2869queue_read_kx (void *cls)
2870{
2871 struct Queue *queue = cls;
2872 ssize_t rcvd;
2873 struct GNUNET_TIME_Relative left;
2874 struct TCPConfirmation tc;
2875
2876 queue->read_task = NULL;
2877 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2878 if (0 == left.rel_value_us)
2879 {
2880 queue_destroy (queue);
2881 return;
2882 }
2883 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
2884 &queue->cread_buf[queue->cread_off],
2885 BUF_SIZE - queue->cread_off);
2886 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2887 "Received %lu bytes for KX\n",
2888 rcvd);
2889 if (-1 == rcvd)
2890 {
2891 if ((EAGAIN != errno) && (EINTR != errno))
2892 {
2893 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "recv");
2894 queue_destroy (queue);
2895 return;
2896 }
2897 queue->read_task =
2898 GNUNET_SCHEDULER_add_read_net (left, queue->sock, &queue_read_kx, queue);
2899 return;
2900 }
2901 queue->cread_off += rcvd;
2902 if (queue->cread_off < INITIAL_KX_SIZE)
2903 {
2904 /* read more */
2905 queue->read_task =
2906 GNUNET_SCHEDULER_add_read_net (left, queue->sock, &queue_read_kx, queue);
2907 return;
2908 }
2909 /* we got all the data, let's find out who we are talking to! */
2910 setup_in_cipher ((const struct GNUNET_CRYPTO_EcdhePublicKey *)
2911 queue->cread_buf,
2912 queue);
2913 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, queue->cread_buf))
2914 {
2915 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2916 "Invalid TCP KX received from %s\n",
2917 GNUNET_a2s (queue->address, queue->address_len));
2918 queue_destroy (queue);
2919 return;
2920 }
2921 if (0 !=
2922 memcmp (&tc.sender, &queue->target, sizeof(struct GNUNET_PeerIdentity)))
2923 {
2924 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2925 "Invalid sender in TCP KX received from %s\n",
2926 GNUNET_a2s (queue->address, queue->address_len));
2927 queue_destroy (queue);
2928 return;
2929 }
2930 send_challenge (tc.challenge, queue);
2931 queue->write_task =
2932 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
2933 queue->sock,
2934 &queue_write,
2935 queue);
2936
2937 /* update queue timeout */
2938 reschedule_queue_timeout (queue);
2939 /* prepare to continue with regular read task immediately */
2940 memmove (queue->cread_buf,
2941 &queue->cread_buf[INITIAL_KX_SIZE],
2942 queue->cread_off - (INITIAL_KX_SIZE));
2943 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2944 "cread_off is %lu bytes before adjusting\n",
2945 queue->cread_off);
2946 queue->cread_off -= INITIAL_KX_SIZE;
2947 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2948 "cread_off set to %lu bytes\n",
2949 queue->cread_off);
2950 queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue);
2951}
2952
2953
2954/**
2955 * Read from the socket of the proto queue until we have enough data
2956 * to upgrade to full queue.
2957 *
2958 * @param cls a `struct ProtoQueue`
2959 */
2960static void
2961proto_read_kx (void *cls)
2962{
2963 struct ProtoQueue *pq = cls;
2964 ssize_t rcvd;
2965 struct GNUNET_TIME_Relative left;
2966 struct Queue *queue;
2967 struct TCPConfirmation tc;
2968 GNUNET_SCHEDULER_TaskCallback read_task;
2969
2970 pq->read_task = NULL;
2971 left = GNUNET_TIME_absolute_get_remaining (pq->timeout);
2972 if (0 == left.rel_value_us)
2973 {
2974 free_proto_queue (pq);
2975 return;
2976 }
2977 rcvd = GNUNET_NETWORK_socket_recv (pq->sock,
2978 &pq->ibuf[pq->ibuf_off],
2979 sizeof(pq->ibuf) - pq->ibuf_off);
2980 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2981 "Proto received %lu bytes for KX\n", rcvd);
2982 if (-1 == rcvd)
2983 {
2984 if ((EAGAIN != errno) && (EINTR != errno))
2985 {
2986 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "recv");
2987 free_proto_queue (pq);
2988 return;
2989 }
2990 /* try again */
2991 pq->read_task =
2992 GNUNET_SCHEDULER_add_read_net (left, pq->sock, &proto_read_kx, pq);
2993 return;
2994 }
2995 pq->ibuf_off += rcvd;
2996 if (sizeof (struct TCPNATProbeMessage) == pq->ibuf_off)
2997 {
2998 struct TCPNATProbeMessage *pm = (struct TCPNATProbeMessage *) pq->ibuf;
2999
3000 check_and_remove_pending_reversal (pq->address, pq->address->sa_family,
3001 &pm->clientIdentity);
3002
3003 queue = GNUNET_new (struct Queue);
3004 queue->target = pm->clientIdentity;
3005 queue->cs = GNUNET_TRANSPORT_CS_OUTBOUND;
3006 read_task = &queue_read_kx;
3007 }
3008 else if (pq->ibuf_off > sizeof(pq->ibuf))
3009 {
3010 /* read more */
3011 pq->read_task =
3012 GNUNET_SCHEDULER_add_read_net (left, pq->sock, &proto_read_kx, pq);
3013 return;
3014 }
3015 else
3016 {
3017 /* we got all the data, let's find out who we are talking to! */
3018 queue = GNUNET_new (struct Queue);
3019 setup_in_cipher ((const struct GNUNET_CRYPTO_EcdhePublicKey *) pq->ibuf,
3020 queue);
3021 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, pq->ibuf))
3022 {
3023 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3024 "Invalid TCP KX received from %s\n",
3025 GNUNET_a2s (pq->address, pq->address_len));
3026 gcry_cipher_close (queue->in_cipher);
3027 GNUNET_free (queue);
3028 free_proto_queue (pq);
3029 return;
3030 }
3031 queue->target = tc.sender;
3032 queue->cs = GNUNET_TRANSPORT_CS_INBOUND;
3033 read_task = &queue_read;
3034 }
3035 queue->address = pq->address; /* steals reference */
3036 queue->address_len = pq->address_len;
3037 queue->listen_sock = pq->listen_sock;
3038 queue->sock = pq->sock;
3039
3040 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3041 "created queue with target %s\n",
3042 GNUNET_i2s (&queue->target));
3043
3044 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3045 "start kx proto\n");
3046
3047 start_initial_kx_out (queue);
3048 boot_queue (queue);
3049 queue->read_task =
3050 GNUNET_SCHEDULER_add_read_net (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
3051 queue->sock,
3052 read_task,
3053 queue);
3054 queue->write_task =
3055 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
3056 queue->sock,
3057 &queue_write,
3058 queue);
3059 // TODO To early! Move it somewhere else.
3060 // send_challenge (tc.challenge, queue);
3061 queue->challenge_received = tc.challenge;
3062
3063 GNUNET_CONTAINER_DLL_remove (proto_head, proto_tail, pq);
3064 GNUNET_free (pq);
3065}
3066
3067
3068static struct ProtoQueue *
3069create_proto_queue (struct GNUNET_NETWORK_Handle *sock,
3070 struct sockaddr *in,
3071 socklen_t addrlen)
3072{
3073 struct ProtoQueue *pq = GNUNET_new (struct ProtoQueue);
3074
3075 if (NULL == sock)
3076 {
3077 // sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET, addr, addrlen);
3078 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, 0);
3079 if (NULL == sock)
3080 {
3081 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3082 "socket(%d) failed: %s",
3083 in->sa_family,
3084 strerror (errno));
3085 GNUNET_free (in);
3086 GNUNET_free (pq);
3087 return NULL;
3088 }
3089 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, addrlen)) &&
3090 (errno != EINPROGRESS))
3091 {
3092 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3093 "connect to `%s' failed: %s",
3094 GNUNET_a2s (in, addrlen),
3095 strerror (errno));
3096 GNUNET_NETWORK_socket_close (sock);
3097 GNUNET_free (in);
3098 return NULL;
3099 }
3100 }
3101 pq->address_len = addrlen;
3102 pq->address = in;
3103 pq->timeout = GNUNET_TIME_relative_to_absolute (PROTO_QUEUE_TIMEOUT);
3104 pq->sock = sock;
3105 pq->read_task = GNUNET_SCHEDULER_add_read_net (PROTO_QUEUE_TIMEOUT,
3106 pq->sock,
3107 &proto_read_kx,
3108 pq);
3109 GNUNET_CONTAINER_DLL_insert (proto_head, proto_tail, pq);
3110
3111 return pq;
3112}
3113
3114
3115/**
3116 * We have been notified that our listen socket has something to
3117 * read. Do the read and reschedule this function to be called again
3118 * once more is available.
3119 *
3120 * @param cls ListenTask with listening socket and task
3121 */
3122static void
3123listen_cb (void *cls)
3124{
3125 struct sockaddr_storage in;
3126 socklen_t addrlen;
3127 struct GNUNET_NETWORK_Handle *sock;
3128 struct ListenTask *lt;
3129 struct sockaddr *in_addr;
3130
3131 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3132 "listen_cb\n");
3133
3134 lt = cls;
3135
3136 lt->listen_task = NULL;
3137 GNUNET_assert (NULL != lt->listen_sock);
3138 addrlen = sizeof(in);
3139 memset (&in, 0, sizeof(in));
3140 sock = GNUNET_NETWORK_socket_accept (lt->listen_sock,
3141 (struct sockaddr*) &in,
3142 &addrlen);
3143 if ((NULL == sock) && ((EMFILE == errno) || (ENFILE == errno)))
3144 return; /* system limit reached, wait until connection goes down */
3145 lt->listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
3146 lt->listen_sock,
3147 &listen_cb,
3148 lt);
3149 if ((NULL == sock) && ((EAGAIN == errno) || (ENOBUFS == errno)))
3150 return;
3151 if (NULL == sock)
3152 {
3153 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "accept");
3154 return;
3155 }
3156 in_addr = GNUNET_memdup (&in, addrlen);
3157 create_proto_queue (sock, in_addr, addrlen);
3158}
3159
3160
3161static void
3162try_connection_reversal (void *cls,
3163 const struct sockaddr *addr,
3164 socklen_t addrlen)
3165{
3166 (void) cls;
3167 struct TCPNATProbeMessage pm;
3168 struct ProtoQueue *pq;
3169 struct sockaddr *in_addr;
3170
3171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3172 "addr->sa_family %d\n",
3173 addr->sa_family);
3174 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3175 "Try to connect back\n");
3176 in_addr = GNUNET_memdup (addr, addrlen);
3177 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3178 "in_addr->sa_family %d\n",
3179 in_addr->sa_family);
3180 pq = create_proto_queue (NULL, in_addr, addrlen);
3181 if (NULL != pq)
3182 {
3183 pm.header.size = htons (sizeof(struct TCPNATProbeMessage));
3184 pm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE);
3185 pm.clientIdentity = my_identity;
3186 memcpy (pq->write_buf, &pm, sizeof(struct TCPNATProbeMessage));
3187 pq->write_off = sizeof(struct TCPNATProbeMessage);
3188 pq->write_task = GNUNET_SCHEDULER_add_write_net (PROTO_QUEUE_TIMEOUT,
3189 pq->sock,
3190 &proto_queue_write,
3191 pq);
3192 }
3193 else
3194 {
3195 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3196 "Couldn't create ProtoQueue for sending TCPNATProbeMessage\n");
3197 }
3198}
3199
3200
3201static void
3202pending_reversal_timeout (void *cls)
3203{
3204 struct sockaddr *in = cls;
3205 struct PendingReversal *pending_reversal;
3206 struct GNUNET_HashCode key;
3207
3208 GNUNET_CRYPTO_hash (in,
3209 sizeof(struct sockaddr),
3210 &key);
3211 pending_reversal = GNUNET_CONTAINER_multihashmap_get (pending_reversals,
3212 &key);
3213
3214 GNUNET_assert (NULL != pending_reversal);
3215
3216 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_remove (pending_reversals,
3217 &key,
3218 pending_reversal))
3219 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3220 "No pending reversal found for address %s\n",
3221 GNUNET_a2s (in, sizeof (struct sockaddr)));
3222 GNUNET_free (pending_reversal->in);
3223 GNUNET_free (pending_reversal);
3224}
3225
3226
3227/**
3228 * Function called by the transport service to initialize a
3229 * message queue given address information about another peer.
3230 * If and when the communication channel is established, the
3231 * communicator must call #GNUNET_TRANSPORT_communicator_mq_add()
3232 * to notify the service that the channel is now up. It is
3233 * the responsibility of the communicator to manage sane
3234 * retries and timeouts for any @a peer/@a address combination
3235 * provided by the transport service. Timeouts and retries
3236 * do not need to be signalled to the transport service.
3237 *
3238 * @param cls closure
3239 * @param peer identity of the other peer
3240 * @param address where to send the message, human-readable
3241 * communicator-specific format, 0-terminated, UTF-8
3242 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the provided address is
3243 * invalid
3244 */
3245static int
3246mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
3247{
3248 struct sockaddr *in;
3249 socklen_t in_len = 0;
3250 const char *path;
3251 struct sockaddr_in *v4;
3252 struct sockaddr_in6 *v6;
3253 unsigned int is_natd = GNUNET_NO;
3254 struct GNUNET_HashCode key;
3255
3256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3257 "Connecting to %s at %s\n",
3258 GNUNET_i2s (peer),
3259 address);
3260 if (0 != strncmp (address,
3261 COMMUNICATOR_ADDRESS_PREFIX "-",
3262 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
3263 {
3264 GNUNET_break_op (0);
3265 return GNUNET_SYSERR;
3266 }
3267 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
3268 in = tcp_address_to_sockaddr (path, &in_len);
3269
3270 if (NULL == in)
3271 {
3272 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3273 "Failed to setup TCP socket address\n");
3274 return GNUNET_SYSERR;
3275 }
3276
3277 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3278 "in %s\n",
3279 GNUNET_a2s (in, in_len));
3280
3281 switch (in->sa_family)
3282 {
3283 case AF_INET:
3284 v4 = (struct sockaddr_in *) in;
3285 if (0 == v4->sin_port)
3286 {
3287 is_natd = GNUNET_YES;
3288 GNUNET_CRYPTO_hash (in,
3289 sizeof(struct sockaddr),
3290 &key);
3291 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (
3292 pending_reversals,
3293 &key))
3294 {
3295 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3296 "There is already a request reversal for `%s'at `%s'\n",
3297 GNUNET_i2s (peer),
3298 address);
3299 GNUNET_free (in);
3300 return GNUNET_SYSERR;
3301 }
3302 }
3303 break;
3304
3305 case AF_INET6:
3306 v6 = (struct sockaddr_in6 *) in;
3307 if (0 == v6->sin6_port)
3308 {
3309 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3310 "Request reversal for `%s' at `%s' not possible for an IPv6 address\n",
3311 GNUNET_i2s (peer),
3312 address);
3313 GNUNET_free (in);
3314 return GNUNET_SYSERR;
3315 }
3316 break;
3317
3318 default:
3319 GNUNET_assert (0);
3320 }
3321
3322 if (GNUNET_YES == is_natd)
3323 {
3324 struct sockaddr_in local_sa;
3325 struct PendingReversal *pending_reversal;
3326
3327 memset (&local_sa, 0, sizeof(local_sa));
3328 local_sa.sin_family = AF_INET;
3329 local_sa.sin_port = htons (bind_port);
3330 /* We leave sin_address at 0, let the kernel figure it out,
3331 even if our bind() is more specific. (May want to reconsider
3332 later.) */
3333 if (GNUNET_OK != GNUNET_NAT_request_reversal (nat, &local_sa, v4))
3334 {
3335 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3336 "request reversal for `%s' at `%s' failed\n",
3337 GNUNET_i2s (peer),
3338 address);
3339 GNUNET_free (in);
3340 return GNUNET_SYSERR;
3341 }
3342 pending_reversal = GNUNET_new (struct PendingReversal);
3343 pending_reversal->in = in;
3344 GNUNET_assert (GNUNET_OK ==
3345 GNUNET_CONTAINER_multihashmap_put (pending_reversals,
3346 &key,
3347 pending_reversal,
3348 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
3349 pending_reversal->target = *peer;
3350 pending_reversal->timeout_task = GNUNET_SCHEDULER_add_delayed (NAT_TIMEOUT,
3351 &
3352 pending_reversal_timeout,
3353 in);
3354 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3355 "Created NAT WAIT connection to `%s' at `%s'\n",
3356 GNUNET_i2s (peer),
3357 GNUNET_a2s (in, sizeof (struct sockaddr)));
3358 }
3359 else
3360 {
3361 struct GNUNET_NETWORK_Handle *sock;
3362 struct Queue *queue;
3363
3364 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM,
3365 IPPROTO_TCP);
3366 if (NULL == sock)
3367 {
3368 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3369 "socket(%d) failed: %s",
3370 in->sa_family,
3371 strerror (errno));
3372 GNUNET_free (in);
3373 return GNUNET_SYSERR;
3374 }
3375 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, in_len)) &&
3376 (errno != EINPROGRESS))
3377 {
3378 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3379 "connect to `%s' failed: %s",
3380 address,
3381 strerror (errno));
3382 GNUNET_NETWORK_socket_close (sock);
3383 GNUNET_free (in);
3384 return GNUNET_SYSERR;
3385 }
3386
3387 queue = GNUNET_new (struct Queue);
3388 queue->target = *peer;
3389 queue->address = in;
3390 queue->address_len = in_len;
3391 queue->sock = sock;
3392 queue->cs = GNUNET_TRANSPORT_CS_OUTBOUND;
3393 boot_queue (queue);
3394 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3395 "booted queue with target %s\n",
3396 GNUNET_i2s (&queue->target));
3397 // queue->mq_awaits_continue = GNUNET_YES;
3398 queue->read_task =
3399 GNUNET_SCHEDULER_add_read_net (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
3400 queue->sock,
3401 &queue_read_kx,
3402 queue);
3403
3404
3405 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3406 "start kx mq_init\n");
3407
3408 start_initial_kx_out (queue);
3409 queue->write_task =
3410 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
3411 queue->sock,
3412 &queue_write,
3413 queue);
3414 }
3415
3416 return GNUNET_OK;
3417}
3418
3419
3420/**
3421 * Iterator over all ListenTasks to clean up.
3422 *
3423 * @param cls NULL
3424 * @param key unused
3425 * @param value the ListenTask to cancel.
3426 * @return #GNUNET_OK to continue to iterate
3427 */
3428static int
3429get_lt_delete_it (void *cls,
3430 const struct GNUNET_HashCode *key,
3431 void *value)
3432{
3433 struct ListenTask *lt = value;
3434
3435 (void) cls;
3436 (void) key;
3437 if (NULL != lt->listen_task)
3438 {
3439 GNUNET_SCHEDULER_cancel (lt->listen_task);
3440 lt->listen_task = NULL;
3441 }
3442 if (NULL != lt->listen_sock)
3443 {
3444 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (lt->listen_sock));
3445 lt->listen_sock = NULL;
3446 }
3447 GNUNET_free (lt);
3448 return GNUNET_OK;
3449}
3450
3451
3452/**
3453 * Iterator over all message queues to clean up.
3454 *
3455 * @param cls NULL
3456 * @param target unused
3457 * @param value the queue to destroy
3458 * @return #GNUNET_OK to continue to iterate
3459 */
3460static int
3461get_queue_delete_it (void *cls,
3462 const struct GNUNET_PeerIdentity *target,
3463 void *value)
3464{
3465 struct Queue *queue = value;
3466
3467 (void) cls;
3468 (void) target;
3469 queue_destroy (queue);
3470 return GNUNET_OK;
3471}
3472
3473
3474/**
3475 * Shutdown the UNIX communicator.
3476 *
3477 * @param cls NULL (always)
3478 */
3479static void
3480do_shutdown (void *cls)
3481{
3482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3483 "Shutdown %s!\n",
3484 shutdown_running ? "running" : "not running");
3485
3486 if (GNUNET_YES == shutdown_running)
3487 return;
3488 else
3489 shutdown_running = GNUNET_YES;
3490
3491 while (NULL != proto_head)
3492 free_proto_queue (proto_head);
3493 if (NULL != nat)
3494 {
3495 GNUNET_NAT_unregister (nat);
3496 nat = NULL;
3497 }
3498 GNUNET_CONTAINER_multihashmap_iterate (pending_reversals,
3499 &pending_reversals_delete_it, NULL);
3500 GNUNET_CONTAINER_multihashmap_destroy (pending_reversals);
3501 GNUNET_CONTAINER_multihashmap_iterate (lt_map, &get_lt_delete_it, NULL);
3502 GNUNET_CONTAINER_multihashmap_destroy (lt_map);
3503 GNUNET_CONTAINER_multipeermap_iterate (queue_map, &get_queue_delete_it, NULL);
3504 GNUNET_CONTAINER_multipeermap_destroy (queue_map);
3505 if (NULL != ch)
3506 {
3507 GNUNET_TRANSPORT_communicator_address_remove_all (ch);
3508 GNUNET_TRANSPORT_communicator_disconnect (ch);
3509 ch = NULL;
3510 }
3511 if (NULL != stats)
3512 {
3513 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
3514 stats = NULL;
3515 }
3516 if (NULL != my_private_key)
3517 {
3518 GNUNET_free (my_private_key);
3519 my_private_key = NULL;
3520 }
3521 if (NULL != is)
3522 {
3523 GNUNET_NT_scanner_done (is);
3524 is = NULL;
3525 }
3526 if (NULL != peerstore)
3527 {
3528 GNUNET_PEERSTORE_disconnect (peerstore, GNUNET_NO);
3529 peerstore = NULL;
3530 }
3531 if (NULL != resolve_request_handle)
3532 {
3533 GNUNET_RESOLVER_request_cancel (resolve_request_handle);
3534 resolve_request_handle = NULL;
3535 }
3536 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3537 "Shutdown done!\n");
3538}
3539
3540
3541/**
3542 * Function called when the transport service has received an
3543 * acknowledgement for this communicator (!) via a different return
3544 * path.
3545 *
3546 * Not applicable for TCP.
3547 *
3548 * @param cls closure
3549 * @param sender which peer sent the notification
3550 * @param msg payload
3551 */
3552static void
3553enc_notify_cb (void *cls,
3554 const struct GNUNET_PeerIdentity *sender,
3555 const struct GNUNET_MessageHeader *msg)
3556{
3557 (void) cls;
3558 (void) sender;
3559 (void) msg;
3560 GNUNET_break_op (0);
3561}
3562
3563
3564/**
3565 * Signature of the callback passed to #GNUNET_NAT_register() for
3566 * a function to call whenever our set of 'valid' addresses changes.
3567 *
3568 * @param cls closure
3569 * @param[in,out] app_ctx location where the app can store stuff
3570 * on add and retrieve it on remove
3571 * @param add_remove #GNUNET_YES to add a new public IP address,
3572 * #GNUNET_NO to remove a previous (now invalid) one
3573 * @param ac address class the address belongs to
3574 * @param addr either the previous or the new public IP address
3575 * @param addrlen actual length of the @a addr
3576 */
3577static void
3578nat_address_cb (void *cls,
3579 void **app_ctx,
3580 int add_remove,
3581 enum GNUNET_NAT_AddressClass ac,
3582 const struct sockaddr *addr,
3583 socklen_t addrlen)
3584{
3585 char *my_addr;
3586 struct GNUNET_TRANSPORT_AddressIdentifier *ai;
3587
3588 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3589 "nat address cb %s %s\n",
3590 add_remove ? "add" : "remove",
3591 GNUNET_a2s (addr, addrlen));
3592
3593 if (GNUNET_YES == add_remove)
3594 {
3595 enum GNUNET_NetworkType nt;
3596
3597 GNUNET_asprintf (&my_addr,
3598 "%s-%s",
3599 COMMUNICATOR_ADDRESS_PREFIX,
3600 GNUNET_a2s (addr, addrlen));
3601 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
3602 ai =
3603 GNUNET_TRANSPORT_communicator_address_add (ch,
3604 my_addr,
3605 nt,
3606 GNUNET_TIME_UNIT_FOREVER_REL);
3607 GNUNET_free (my_addr);
3608 *app_ctx = ai;
3609 }
3610 else
3611 {
3612 ai = *app_ctx;
3613 GNUNET_TRANSPORT_communicator_address_remove (ai);
3614 *app_ctx = NULL;
3615 }
3616}
3617
3618
3619/**
3620 * This method adds addresses to the DLL, that are later register at the NAT service.
3621 */
3622static void
3623add_addr (struct sockaddr *in, socklen_t in_len)
3624{
3625
3626 struct Addresses *saddrs;
3627
3628 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3629 "add address %s\n",
3630 GNUNET_a2s (in, in_len));
3631
3632 saddrs = GNUNET_new (struct Addresses);
3633 saddrs->addr = in;
3634 saddrs->addr_len = in_len;
3635 GNUNET_CONTAINER_DLL_insert (addrs_head, addrs_tail, saddrs);
3636
3637 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3638 "after add address %s\n",
3639 GNUNET_a2s (in, in_len));
3640
3641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3642 "add address %s\n",
3643 GNUNET_a2s (saddrs->addr, saddrs->addr_len));
3644
3645 addrs_lens++;
3646}
3647
3648
3649/**
3650 * This method launch network interactions for each address we like to bind to.
3651 *
3652 * @param addr The address we will listen to.
3653 * @param in_len The length of the address we will listen to.
3654 * @return GNUNET_SYSERR in case of error. GNUNET_OK in case we are successfully listen to the address.
3655 */
3656static int
3657init_socket (struct sockaddr *addr,
3658 socklen_t in_len)
3659{
3660 struct sockaddr_storage in_sto;
3661 socklen_t sto_len;
3662 struct GNUNET_NETWORK_Handle *listen_sock;
3663 struct ListenTask *lt;
3664 int sockfd;
3665 struct GNUNET_HashCode h_sock;
3666
3667 if (NULL == addr)
3668 {
3669 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3670 "Address is NULL.\n");
3671 return GNUNET_SYSERR;
3672 }
3673
3674 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3675 "address %s\n",
3676 GNUNET_a2s (addr, in_len));
3677
3678 listen_sock =
3679 GNUNET_NETWORK_socket_create (addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
3680 if (NULL == listen_sock)
3681 {
3682 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
3683 return GNUNET_SYSERR;
3684 }
3685
3686 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (listen_sock, addr, in_len))
3687 {
3688 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
3689 GNUNET_NETWORK_socket_close (listen_sock);
3690 listen_sock = NULL;
3691 return GNUNET_SYSERR;
3692 }
3693
3694 if (GNUNET_OK !=
3695 GNUNET_NETWORK_socket_listen (listen_sock,
3696 5))
3697 {
3698 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
3699 "listen");
3700 GNUNET_NETWORK_socket_close (listen_sock);
3701 listen_sock = NULL;
3702 return GNUNET_SYSERR;
3703 }
3704
3705 /* We might have bound to port 0, allowing the OS to figure it out;
3706 thus, get the real IN-address from the socket */
3707 sto_len = sizeof(in_sto);
3708
3709 if (0 != getsockname (GNUNET_NETWORK_get_fd (listen_sock),
3710 (struct sockaddr *) &in_sto,
3711 &sto_len))
3712 {
3713 memcpy (&in_sto, addr, in_len);
3714 sto_len = in_len;
3715 }
3716
3717 // addr = (struct sockaddr *) &in_sto;
3718 in_len = sto_len;
3719 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3720 "Bound to `%s'\n",
3721 GNUNET_a2s ((const struct sockaddr *) &in_sto, sto_len));
3722 stats = GNUNET_STATISTICS_create ("C-TCP", cfg);
3723
3724 if (NULL == is)
3725 is = GNUNET_NT_scanner_init ();
3726
3727 if (NULL == my_private_key)
3728 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
3729 if (NULL == my_private_key)
3730 {
3731 GNUNET_log (
3732 GNUNET_ERROR_TYPE_ERROR,
3733 _ (
3734 "Transport service is lacking key configuration settings. Exiting.\n"));
3735 if (NULL != resolve_request_handle)
3736 GNUNET_RESOLVER_request_cancel (resolve_request_handle);
3737 GNUNET_SCHEDULER_shutdown ();
3738 return GNUNET_SYSERR;
3739 }
3740 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_identity.public_key);
3741 /* start listening */
3742
3743 lt = GNUNET_new (struct ListenTask);
3744 lt->listen_sock = listen_sock;
3745
3746 lt->listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
3747 listen_sock,
3748 &listen_cb,
3749 lt);
3750
3751 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3752 "creating hash\n");
3753 sockfd = GNUNET_NETWORK_get_fd (lt->listen_sock);
3754 GNUNET_CRYPTO_hash (&sockfd,
3755 sizeof(int),
3756 &h_sock);
3757
3758 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3759 "creating map\n");
3760 if (NULL == lt_map)
3761 lt_map = GNUNET_CONTAINER_multihashmap_create (2, GNUNET_NO);
3762
3763 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3764 "creating map entry\n");
3765 GNUNET_assert (GNUNET_OK ==
3766 GNUNET_CONTAINER_multihashmap_put (lt_map,
3767 &h_sock,
3768 lt,
3769 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
3770
3771 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3772 "map entry created\n");
3773
3774 if (NULL == queue_map)
3775 queue_map = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
3776
3777 if (NULL == ch)
3778 ch = GNUNET_TRANSPORT_communicator_connect (cfg,
3779 COMMUNICATOR_CONFIG_SECTION,
3780 COMMUNICATOR_ADDRESS_PREFIX,
3781 GNUNET_TRANSPORT_CC_RELIABLE,
3782 &mq_init,
3783 NULL,
3784 &enc_notify_cb,
3785 NULL);
3786
3787 if (NULL == ch)
3788 {
3789 GNUNET_break (0);
3790 if (NULL != resolve_request_handle)
3791 GNUNET_RESOLVER_request_cancel (resolve_request_handle);
3792 GNUNET_SCHEDULER_shutdown ();
3793 return GNUNET_SYSERR;
3794 }
3795
3796 add_addr (addr, in_len);
3797 return GNUNET_OK;
3798
3799}
3800
3801
3802/**
3803 * This method reads from the DLL addrs_head to register them at the NAT service.
3804 */
3805static void
3806nat_register ()
3807{
3808 struct sockaddr **saddrs;
3809 socklen_t *saddr_lens;
3810 int i;
3811 size_t len;
3812
3813 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3814 "starting nat register!\n");
3815 len = 0;
3816 i = 0;
3817 saddrs = GNUNET_malloc ((addrs_lens) * sizeof(struct sockaddr *));
3818 saddr_lens = GNUNET_malloc ((addrs_lens) * sizeof(socklen_t));
3819 for (struct Addresses *pos = addrs_head; NULL != pos; pos = pos->next)
3820 {
3821 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3822 "registering address %s\n",
3823 GNUNET_a2s (addrs_head->addr, addrs_head->addr_len));
3824
3825 saddr_lens[i] = addrs_head->addr_len;
3826 len += saddr_lens[i];
3827 saddrs[i] = GNUNET_memdup (addrs_head->addr, saddr_lens[i]);
3828 i++;
3829 }
3830
3831 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3832 "registering addresses %lu %lu %lu %lu\n",
3833 (addrs_lens) * sizeof(struct sockaddr *),
3834 (addrs_lens) * sizeof(socklen_t),
3835 len,
3836 sizeof(COMMUNICATOR_CONFIG_SECTION));
3837 nat = GNUNET_NAT_register (cfg,
3838 COMMUNICATOR_CONFIG_SECTION,
3839 IPPROTO_TCP,
3840 addrs_lens,
3841 (const struct sockaddr **) saddrs,
3842 saddr_lens,
3843 &nat_address_cb,
3844 try_connection_reversal,
3845 NULL /* closure */);
3846 for (i = addrs_lens - 1; i >= 0; i--)
3847 GNUNET_free (saddrs[i]);
3848 GNUNET_free (saddrs);
3849 GNUNET_free (saddr_lens);
3850
3851 if (NULL == nat)
3852 {
3853 GNUNET_break (0);
3854 if (NULL != resolve_request_handle)
3855 GNUNET_RESOLVER_request_cancel (resolve_request_handle);
3856 GNUNET_SCHEDULER_shutdown ();
3857 }
3858}
3859
3860
3861/**
3862 * This method is the callback called by the resolver API, and wraps method init_socket.
3863 *
3864 * @param cls The port we will bind to.
3865 * @param addr The address we will bind to.
3866 * @param in_len The length of the address we will bind to.
3867 */
3868static void
3869init_socket_resolv (void *cls,
3870 const struct sockaddr *addr,
3871 socklen_t in_len)
3872{
3873 struct sockaddr_in *v4;
3874 struct sockaddr_in6 *v6;
3875 struct sockaddr *in;
3876
3877 (void) cls;
3878 if (NULL != addr)
3879 {
3880 if (AF_INET == addr->sa_family)
3881 {
3882 v4 = (struct sockaddr_in *) addr;
3883 in = tcp_address_to_sockaddr_numeric_v4 (&in_len, *v4, bind_port);// _global);
3884 }
3885 else if (AF_INET6 == addr->sa_family)
3886 {
3887 v6 = (struct sockaddr_in6 *) addr;
3888 in = tcp_address_to_sockaddr_numeric_v6 (&in_len, *v6, bind_port);// _global);
3889 }
3890 else
3891 {
3892 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3893 "Address family %u not suitable (not AF_INET %u nor AF_INET6 %u \n",
3894 addr->sa_family,
3895 AF_INET,
3896 AF_INET6);
3897 return;
3898 }
3899 init_socket (in, in_len);
3900 }
3901 else
3902 {
3903 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3904 "Address is NULL. This might be an error or the resolver finished resolving.\n");
3905 if (NULL == addrs_head)
3906 {
3907 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3908 "Resolver finished resolving, but we do not listen to an address!.\n");
3909 return;
3910 }
3911 nat_register ();
3912 }
3913}
3914
3915
3916/**
3917 * Setup communicator and launch network interactions.
3918 *
3919 * @param cls NULL (always)
3920 * @param args remaining command-line arguments
3921 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
3922 * @param c configuration
3923 */
3924static void
3925run (void *cls,
3926 char *const *args,
3927 const char *cfgfile,
3928 const struct GNUNET_CONFIGURATION_Handle *c)
3929{
3930 char *bindto;
3931 struct sockaddr *in;
3932 socklen_t in_len;
3933 struct sockaddr_in v4;
3934 struct sockaddr_in6 v6;
3935 char *start;
3936 unsigned int port;
3937 char dummy[2];
3938 char *rest = NULL;
3939 struct PortOnlyIpv4Ipv6 *po;
3940 socklen_t addr_len_ipv4;
3941 socklen_t addr_len_ipv6;
3942
3943 (void) cls;
3944
3945 pending_reversals = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO);
3946 memset (&v4,0,sizeof(struct sockaddr_in));
3947 memset (&v6,0,sizeof(struct sockaddr_in6));
3948 cfg = c;
3949 if (GNUNET_OK !=
3950 GNUNET_CONFIGURATION_get_value_string (cfg,
3951 COMMUNICATOR_CONFIG_SECTION,
3952 "BINDTO",
3953 &bindto))
3954 {
3955 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3956 COMMUNICATOR_CONFIG_SECTION,
3957 "BINDTO");
3958 return;
3959 }
3960 if (GNUNET_OK !=
3961 GNUNET_CONFIGURATION_get_value_number (cfg,
3962 COMMUNICATOR_CONFIG_SECTION,
3963 "MAX_QUEUE_LENGTH",
3964 &max_queue_length))
3965 max_queue_length = DEFAULT_MAX_QUEUE_LENGTH;
3966 if (GNUNET_OK !=
3967 GNUNET_CONFIGURATION_get_value_time (cfg,
3968 COMMUNICATOR_CONFIG_SECTION,
3969 "REKEY_INTERVAL",
3970 &rekey_interval))
3971 rekey_interval = DEFAULT_REKEY_INTERVAL;
3972
3973 peerstore = GNUNET_PEERSTORE_connect (cfg);
3974 if (NULL == peerstore)
3975 {
3976 GNUNET_free (bindto);
3977 GNUNET_break (0);
3978 GNUNET_SCHEDULER_shutdown ();
3979 return;
3980 }
3981
3982 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
3983
3984 if (1 == sscanf (bindto, "%u%1s", &bind_port, dummy))
3985 {
3986 po = tcp_address_to_sockaddr_port_only (bindto, &bind_port);
3987 addr_len_ipv4 = po->addr_len_ipv4;
3988 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3989 "address po %s\n",
3990 GNUNET_a2s (po->addr_ipv4, addr_len_ipv4));
3991 if (NULL != po->addr_ipv4)
3992 {
3993 init_socket (po->addr_ipv4, addr_len_ipv4);
3994 }
3995 if (NULL != po->addr_ipv6)
3996 {
3997 addr_len_ipv6 = po->addr_len_ipv6;
3998 init_socket (po->addr_ipv6, addr_len_ipv6);
3999 }
4000 GNUNET_free (po);
4001 nat_register ();
4002 GNUNET_free (bindto);
4003 return;
4004 }
4005
4006 start = extract_address (bindto);
4007 // FIXME: check for NULL == start...
4008 if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
4009 {
4010 bind_port = extract_port (bindto);
4011
4012 in = tcp_address_to_sockaddr_numeric_v4 (&in_len, v4, bind_port);
4013 init_socket (in, in_len);
4014 nat_register ();
4015 GNUNET_free (start);
4016 GNUNET_free (bindto);
4017 return;
4018 }
4019
4020 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
4021 {
4022 bind_port = extract_port (bindto);
4023 in = tcp_address_to_sockaddr_numeric_v6 (&in_len, v6, bind_port);
4024 init_socket (in, in_len);
4025 nat_register ();
4026 GNUNET_free (start);
4027 GNUNET_free (bindto);
4028 return;
4029 }
4030
4031 bind_port = extract_port (bindto);
4032 resolve_request_handle = GNUNET_RESOLVER_ip_get (strtok_r (bindto,
4033 ":",
4034 &rest),
4035 AF_UNSPEC,
4036 GNUNET_TIME_UNIT_MINUTES,
4037 &init_socket_resolv,
4038 &port);
4039
4040 GNUNET_free (bindto);
4041 GNUNET_free (start);
4042}
4043
4044
4045/**
4046 * The main function for the UNIX communicator.
4047 *
4048 * @param argc number of arguments from the command line
4049 * @param argv command line arguments
4050 * @return 0 ok, 1 on error
4051 */
4052int
4053main (int argc, char *const *argv)
4054{
4055 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
4056 GNUNET_GETOPT_OPTION_END
4057 };
4058 int ret;
4059
4060 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4061 "Starting tcp communicator\n");
4062 if (GNUNET_OK !=
4063 GNUNET_STRINGS_get_utf8_args (argc, argv,
4064 &argc, &argv))
4065 return 2;
4066
4067 ret = (GNUNET_OK ==
4068 GNUNET_PROGRAM_run (argc,
4069 argv,
4070 "gnunet-communicator-tcp",
4071 _ ("GNUnet TCP communicator"),
4072 options,
4073 &run,
4074 NULL))
4075 ? 0
4076 : 1;
4077 GNUNET_free_nz ((void *) argv);
4078 return ret;
4079}
4080
4081
4082/* end of gnunet-communicator-tcp.c */
diff --git a/src/transport/gnunet-communicator-udp.c b/src/transport/gnunet-communicator-udp.c
deleted file mode 100644
index f9bbe91f6..000000000
--- a/src/transport/gnunet-communicator-udp.c
+++ /dev/null
@@ -1,3444 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2014, 2018, 2019 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 transport/gnunet-communicator-udp.c
23 * @brief Transport plugin using UDP.
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - consider imposing transmission limits in the absence
28 * of ACKs; or: maybe this should be done at TNG service level?
29 * (at least the receiver might want to enforce limits on
30 * KX/DH operations per sender in here) (#5552)
31 * - overall, we should look more into flow control support
32 * (either in backchannel, or general solution in TNG service)
33 * - handle addresses discovered from broadcasts (#5551)
34 * (think: what was the story again on address validation?
35 * where is the API for that!?!)
36 * - support DNS names in BINDTO option (#5528)
37 * - support NAT connection reversal method (#5529)
38 * - support other UDP-specific NAT traversal methods (#)
39 */
40#include "platform.h"
41#include "gnunet_common.h"
42#include "gnunet_util_lib.h"
43#include "gnunet_protocols.h"
44#include "gnunet_signatures.h"
45#include "gnunet_constants.h"
46#include "gnunet_nat_service.h"
47#include "gnunet_statistics_service.h"
48#include "gnunet_transport_application_service.h"
49#include "gnunet_transport_communication_service.h"
50
51/**
52 * How often do we rekey based on time (at least)
53 */
54#define DEFAULT_REKEY_TIME_INTERVAL GNUNET_TIME_UNIT_DAYS
55
56/**
57 * How long do we wait until we must have received the initial KX?
58 */
59#define PROTO_QUEUE_TIMEOUT GNUNET_TIME_UNIT_MINUTES
60
61/**
62 * How often do we broadcast our presence on the LAN?
63 */
64#define BROADCAST_FREQUENCY GNUNET_TIME_UNIT_MINUTES
65
66/**
67 * How often do we scan for changes to our network interfaces?
68 */
69#define INTERFACE_SCAN_FREQUENCY \
70 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
71
72/**
73 * How long do we believe our addresses to remain up (before
74 * the other peer should revalidate).
75 */
76#define ADDRESS_VALIDITY_PERIOD GNUNET_TIME_UNIT_HOURS
77
78#define WORKING_QUEUE_INTERVALL \
79 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS,1)
80
81/**
82 * AES key size.
83 */
84#define AES_KEY_SIZE (256 / 8)
85
86/**
87 * AES (GCM) IV size.
88 */
89#define AES_IV_SIZE (96 / 8)
90
91/**
92 * Size of the GCM tag.
93 */
94#define GCM_TAG_SIZE (128 / 8)
95
96#define GENERATE_AT_ONCE 16
97
98/**
99 * If we fall below this number of available KCNs,
100 * we generate additional ACKs until we reach
101 * #KCN_TARGET.
102 * Should be large enough that we don't generate ACKs all
103 * the time and still have enough time for the ACK to
104 * arrive before the sender runs out. So really this
105 * should ideally be based on the RTT.
106 */
107#define KCN_THRESHOLD 96
108
109/**
110 * How many KCNs do we keep around *after* we hit
111 * the #KCN_THRESHOLD? Should be larger than
112 * #KCN_THRESHOLD so we do not generate just one
113 * ACK at the time.
114 */
115#define KCN_TARGET 128
116
117/**
118 * What is the maximum delta between KCN sequence numbers
119 * that we allow. Used to expire 'ancient' KCNs that likely
120 * were dropped by the network. Must be larger than
121 * KCN_TARGET (otherwise we generate new KCNs all the time),
122 * but not too large (otherwise packet loss may cause
123 * sender to fall back to KX needlessly when sender runs
124 * out of ACK'ed KCNs due to losses).
125 */
126#define MAX_SQN_DELTA 160
127
128/**
129 * How many shared master secrets do we keep around
130 * at most per sender? Should be large enough so
131 * that we generally have a chance of sending an ACK
132 * before the sender already rotated out the master
133 * secret. Generally values around #KCN_TARGET make
134 * sense. Might make sense to adapt to RTT if we had
135 * a good measurement...
136 */
137#define MAX_SECRETS 256
138
139/**
140 * Default value for how often we do rekey based on number of bytes transmitted?
141 * (additionally randomized).
142 */
143#define DEFAULT_REKEY_MAX_BYTES (1024LLU * 1024 * 1024 * 4LLU)
144
145/**
146 * Address prefix used by the communicator.
147 */
148
149#define COMMUNICATOR_ADDRESS_PREFIX "udp"
150
151/**
152 * Configuration section used by the communicator.
153 */
154#define COMMUNICATOR_CONFIG_SECTION "communicator-udp"
155
156GNUNET_NETWORK_STRUCT_BEGIN
157
158
159/**
160 * Signature we use to verify that the ephemeral key was really chosen by
161 * the specified sender. If possible, the receiver should respond with
162 * a `struct UDPAck` (possibly via backchannel).
163 */
164struct UdpHandshakeSignature
165{
166 /**
167 * Purpose must be #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_HANDSHAKE
168 */
169 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
170
171 /**
172 * Identity of the inititor of the UDP connection (UDP client).
173 */
174 struct GNUNET_PeerIdentity sender;
175
176 /**
177 * Presumed identity of the target of the UDP connection (UDP server)
178 */
179 struct GNUNET_PeerIdentity receiver;
180
181 /**
182 * Ephemeral key used by the @e sender.
183 */
184 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
185
186 /**
187 * Monotonic time of @e sender, to possibly help detect replay attacks
188 * (if receiver persists times by sender).
189 */
190 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
191};
192
193
194/**
195 * "Plaintext" header at beginning of KX message. Followed
196 * by encrypted `struct UDPConfirmation`.
197 */
198struct InitialKX
199{
200 /**
201 * Ephemeral key for KX.
202 */
203 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
204
205 /**
206 * HMAC for the following encrypted message, using GCM. HMAC uses
207 * key derived from the handshake with sequence number zero.
208 */
209 uint8_t gcm_tag[GCM_TAG_SIZE];
210
211};
212
213
214/**
215 * Encrypted continuation of UDP initial handshake, followed
216 * by message header with payload.
217 */
218struct UDPConfirmation
219{
220 /**
221 * Sender's identity
222 */
223 struct GNUNET_PeerIdentity sender;
224
225 /**
226 * Sender's signature of type #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_HANDSHAKE
227 */
228 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
229
230 /**
231 * Monotonic time of @e sender, to possibly help detect replay attacks
232 * (if receiver persists times by sender).
233 */
234 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
235
236 /* followed by messages */
237
238 /* padding may follow actual messages */
239};
240
241
242/**
243 * UDP key acknowledgement. May be sent via backchannel. Allows the
244 * sender to use `struct UDPBox` with the acknowledge key henceforth.
245 */
246struct UDPAck
247{
248 /**
249 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK.
250 */
251 struct GNUNET_MessageHeader header;
252
253 /**
254 * Sequence acknowledgement limit. Specifies current maximum sequence
255 * number supported by receiver.
256 */
257 uint32_t sequence_ack GNUNET_PACKED;
258
259 /**
260 * CMAC of the base key being acknowledged.
261 */
262 struct GNUNET_HashCode cmac;
263};
264
265
266/**
267 * Signature we use to verify that the broadcast was really made by
268 * the peer that claims to have made it. Basically, affirms that the
269 * peer is really using this IP address (albeit possibly not in _our_
270 * LAN). Makes it difficult for peers in the LAN to claim to
271 * be just any global peer -- an attacker must have at least
272 * shared a LAN with the peer they're pretending to be here.
273 */
274struct UdpBroadcastSignature
275{
276 /**
277 * Purpose must be #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_BROADCAST
278 */
279 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
280
281 /**
282 * Identity of the inititor of the UDP broadcast.
283 */
284 struct GNUNET_PeerIdentity sender;
285
286 /**
287 * Hash of the sender's UDP address.
288 */
289 struct GNUNET_HashCode h_address;
290};
291
292
293/**
294 * Broadcast by peer in LAN announcing its presence. Unusual in that
295 * we don't pad these to full MTU, as we cannot prevent being
296 * recognized in LAN as GNUnet peers if this feature is enabled
297 * anyway. Also, the entire message is in cleartext.
298 */
299struct UDPBroadcast
300{
301 /**
302 * Sender's peer identity.
303 */
304 struct GNUNET_PeerIdentity sender;
305
306 /**
307 * Sender's signature of type
308 * #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_BROADCAST
309 */
310 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
311};
312
313
314/**
315 * UDP message box. Always sent encrypted, only allowed after
316 * the receiver sent a `struct UDPAck` for the base key!
317 */
318struct UDPBox
319{
320 /**
321 * Key and IV identification code. KDF applied to an acknowledged
322 * base key and a sequence number. Sequence numbers must be used
323 * monotonically increasing up to the maximum specified in
324 * `struct UDPAck`. Without further `struct UDPAck`s, the sender
325 * must fall back to sending handshakes!
326 */
327 struct GNUNET_ShortHashCode kid;
328
329 /**
330 * 128-bit authentication tag for the following encrypted message,
331 * from GCM. MAC starts at the @e body_start that follows and
332 * extends until the end of the UDP payload. If the @e hmac is
333 * wrong, the receiver should check if the message might be a
334 * `struct UdpHandshakeSignature`.
335 */
336 uint8_t gcm_tag[GCM_TAG_SIZE];
337
338};
339
340/**
341 * Plaintext of a rekey payload in a UDPBox.
342 */
343struct UDPRekey
344{
345 /**
346 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_REKEY.
347 */
348 struct GNUNET_MessageHeader header;
349
350 /**
351 * Ephemeral key to rekey with.
352 */
353 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
354};
355
356GNUNET_NETWORK_STRUCT_END
357
358/**
359 * Shared secret we generated for a particular sender or receiver.
360 */
361struct SharedSecret;
362
363
364/**
365 * Pre-generated "kid" code (key and IV identification code) to
366 * quickly derive master key for a `struct UDPBox`.
367 */
368struct KeyCacheEntry
369{
370 /**
371 * Kept in a DLL.
372 */
373 struct KeyCacheEntry *next;
374
375 /**
376 * Kept in a DLL.
377 */
378 struct KeyCacheEntry *prev;
379
380 /**
381 * Key and IV identification code. KDF applied to an acknowledged
382 * base key and a sequence number. Sequence numbers must be used
383 * monotonically increasing up to the maximum specified in
384 * `struct UDPAck`. Without further `struct UDPAck`s, the sender
385 * must fall back to sending handshakes!
386 */
387 struct GNUNET_ShortHashCode kid;
388
389 /**
390 * Corresponding shared secret.
391 */
392 struct SharedSecret *ss;
393
394 /**
395 * Sequence number used to derive this entry from master key.
396 */
397 uint32_t sequence_number;
398};
399
400
401/**
402 * Information we track per sender address we have recently been
403 * in contact with (decryption from sender).
404 */
405struct SenderAddress;
406
407/**
408 * Information we track per receiving address we have recently been
409 * in contact with (encryption to receiver).
410 */
411struct ReceiverAddress;
412
413/**
414 * Shared secret we generated for a particular sender or receiver.
415 */
416struct SharedSecret
417{
418 /**
419 * Kept in a DLL.
420 */
421 struct SharedSecret *next;
422
423 /**
424 * Kept in a DLL.
425 */
426 struct SharedSecret *prev;
427
428 /**
429 * Kept in a DLL, sorted by sequence number. Only if we are decrypting.
430 */
431 struct KeyCacheEntry *kce_head;
432
433 /**
434 * Kept in a DLL, sorted by sequence number. Only if we are decrypting.
435 */
436 struct KeyCacheEntry *kce_tail;
437
438 /**
439 * Sender we use this shared secret with, or NULL.
440 */
441 struct SenderAddress *sender;
442
443 /**
444 * Receiver we use this shared secret with, or NULL.
445 */
446 struct ReceiverAddress *receiver;
447
448 /**
449 * Master shared secret.
450 */
451 struct GNUNET_HashCode master;
452
453 /**
454 * CMAC is used to identify @e master in ACKs.
455 */
456 struct GNUNET_HashCode cmac;
457
458 /**
459 * Up to which sequence number did we use this @e master already?
460 * (for encrypting only)
461 */
462 uint32_t sequence_used;
463
464 /**
465 * Up to which sequence number did the other peer allow us to use
466 * this key, or up to which number did we allow the other peer to
467 * use this key?
468 */
469 uint32_t sequence_allowed;
470
471 /**
472 * Number of active KCN entries.
473 */
474 unsigned int active_kce_count;
475
476 /**
477 * Bytes sent with this shared secret
478 */
479 size_t bytes_sent;
480
481 /**
482 * rekey initiated for this secret?
483 */
484 int rekey_initiated;
485
486 /**
487 * Also precompute keys despite sufficient acks (for rekey)
488 */
489 int override_available_acks;
490};
491
492
493/**
494 * Information we track per sender address we have recently been
495 * in contact with (we decrypt messages from the sender).
496 */
497struct SenderAddress
498{
499 /**
500 * To whom are we talking to.
501 */
502 struct GNUNET_PeerIdentity target;
503
504 /**
505 * Entry in sender expiration heap.
506 */
507 struct GNUNET_CONTAINER_HeapNode *hn;
508
509 /**
510 * Shared secrets we used with @e target, first used is head.
511 */
512 struct SharedSecret *ss_head;
513
514 /**
515 * Shared secrets we used with @e target, last used is tail.
516 */
517 struct SharedSecret *ss_tail;
518
519 /**
520 * Address of the other peer.
521 */
522 struct sockaddr *address;
523
524 /**
525 * Length of the address.
526 */
527 socklen_t address_len;
528
529 /**
530 * Timeout for this sender.
531 */
532 struct GNUNET_TIME_Absolute timeout;
533
534 /**
535 * Length of the DLL at @a ss_head.
536 */
537 unsigned int num_secrets;
538
539 /**
540 * Number of BOX keys from ACKs we have currently
541 * available for this sender.
542 */
543 unsigned int acks_available;
544
545 /**
546 * Which network type does this queue use?
547 */
548 enum GNUNET_NetworkType nt;
549
550 /**
551 * sender_destroy already called on sender.
552 */
553 int sender_destroy_called;
554
555 /**
556 * ID of kce working queue task
557 */
558 struct GNUNET_SCHEDULER_Task *kce_task;
559
560 /**
561 * Is the kce_task finished?
562 */
563 int kce_task_finished;
564
565 /**
566 * When KCE finishes, send ACK if GNUNET_YES
567 */
568 int kce_send_ack_on_finish;
569};
570
571
572/**
573 * Information we track per receiving address we have recently been
574 * in contact with (encryption to receiver).
575 */
576struct ReceiverAddress
577{
578 /**
579 * Timeout for this receiver address.
580 */
581 struct GNUNET_TIME_Absolute rekey_timeout;
582
583 /**
584 * To whom are we talking to.
585 */
586 struct GNUNET_PeerIdentity target;
587
588 /**
589 * Shared secrets we received from @e target, first used is head.
590 */
591 struct SharedSecret *ss_head;
592
593 /**
594 * Shared secrets we received with @e target, last used is tail.
595 */
596 struct SharedSecret *ss_tail;
597
598 /**
599 * Address of the receiver in the human-readable format
600 * with the #COMMUNICATOR_ADDRESS_PREFIX.
601 */
602 char *foreign_addr;
603
604 /**
605 * Address of the other peer.
606 */
607 struct sockaddr *address;
608
609 /**
610 * Length of the address.
611 */
612 socklen_t address_len;
613
614 /**
615 * Entry in sender expiration heap.
616 */
617 struct GNUNET_CONTAINER_HeapNode *hn;
618
619 /**
620 * KX message queue we are providing for the #ch.
621 */
622 struct GNUNET_MQ_Handle *kx_mq;
623
624 /**
625 * Default message queue we are providing for the #ch.
626 */
627 struct GNUNET_MQ_Handle *d_mq;
628
629 /**
630 * handle for KX queue with the #ch.
631 */
632 struct GNUNET_TRANSPORT_QueueHandle *kx_qh;
633
634 /**
635 * handle for default queue with the #ch.
636 */
637 struct GNUNET_TRANSPORT_QueueHandle *d_qh;
638
639 /**
640 * Timeout for this receiver address.
641 */
642 struct GNUNET_TIME_Absolute timeout;
643
644 /**
645 * MTU we allowed transport for this receiver's KX queue.
646 */
647 size_t kx_mtu;
648
649 /**
650 * MTU we allowed transport for this receiver's default queue.
651 */
652 size_t d_mtu;
653
654 /**
655 * Length of the DLL at @a ss_head.
656 */
657 unsigned int num_secrets;
658
659 /**
660 * Number of BOX keys from ACKs we have currently
661 * available for this receiver.
662 */
663 unsigned int acks_available;
664
665 /**
666 * Which network type does this queue use?
667 */
668 enum GNUNET_NetworkType nt;
669
670 /**
671 * receiver_destroy already called on receiver.
672 */
673 int receiver_destroy_called;
674};
675
676/**
677 * Interface we broadcast our presence on.
678 */
679struct BroadcastInterface
680{
681 /**
682 * Kept in a DLL.
683 */
684 struct BroadcastInterface *next;
685
686 /**
687 * Kept in a DLL.
688 */
689 struct BroadcastInterface *prev;
690
691 /**
692 * Task for this broadcast interface.
693 */
694 struct GNUNET_SCHEDULER_Task *broadcast_task;
695
696 /**
697 * Sender's address of the interface.
698 */
699 struct sockaddr *sa;
700
701 /**
702 * Broadcast address to use on the interface.
703 */
704 struct sockaddr *ba;
705
706 /**
707 * Message we broadcast on this interface.
708 */
709 struct UDPBroadcast bcm;
710
711 /**
712 * If this is an IPv6 interface, this is the request
713 * we use to join/leave the group.
714 */
715 struct ipv6_mreq mcreq;
716
717 /**
718 * Number of bytes in @e sa.
719 */
720 socklen_t salen;
721
722 /**
723 * Was this interface found in the last #iface_proc() scan?
724 */
725 int found;
726};
727
728/**
729 * The rekey interval
730 */
731static struct GNUNET_TIME_Relative rekey_interval;
732
733/**
734 * How often we do rekey based on number of bytes transmitted
735 */
736static unsigned long long rekey_max_bytes;
737
738/**
739 * Cache of pre-generated key IDs.
740 */
741static struct GNUNET_CONTAINER_MultiShortmap *key_cache;
742
743/**
744 * ID of read task
745 */
746static struct GNUNET_SCHEDULER_Task *read_task;
747
748/**
749 * ID of timeout task
750 */
751static struct GNUNET_SCHEDULER_Task *timeout_task;
752
753/**
754 * ID of master broadcast task
755 */
756static struct GNUNET_SCHEDULER_Task *broadcast_task;
757
758/**
759 * For logging statistics.
760 */
761static struct GNUNET_STATISTICS_Handle *stats;
762
763/**
764 * Our environment.
765 */
766static struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
767
768/**
769 * Receivers (map from peer identity to `struct ReceiverAddress`)
770 */
771static struct GNUNET_CONTAINER_MultiPeerMap *receivers;
772
773/**
774 * Senders (map from peer identity to `struct SenderAddress`)
775 */
776static struct GNUNET_CONTAINER_MultiPeerMap *senders;
777
778/**
779 * Expiration heap for senders (contains `struct SenderAddress`)
780 */
781static struct GNUNET_CONTAINER_Heap *senders_heap;
782
783/**
784 * Expiration heap for receivers (contains `struct ReceiverAddress`)
785 */
786static struct GNUNET_CONTAINER_Heap *receivers_heap;
787
788/**
789 * Broadcast interface tasks. Kept in a DLL.
790 */
791static struct BroadcastInterface *bi_head;
792
793/**
794 * Broadcast interface tasks. Kept in a DLL.
795 */
796static struct BroadcastInterface *bi_tail;
797
798/**
799 * Our socket.
800 */
801static struct GNUNET_NETWORK_Handle *udp_sock;
802
803/**
804 * #GNUNET_YES if #udp_sock supports IPv6.
805 */
806static int have_v6_socket;
807
808/**
809 * Our public key.
810 */
811static struct GNUNET_PeerIdentity my_identity;
812
813/**
814 * Our private key.
815 */
816static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
817
818/**
819 * Our configuration.
820 */
821static const struct GNUNET_CONFIGURATION_Handle *cfg;
822
823/**
824 * Our handle to report addresses for validation to TRANSPORT.
825 */
826static struct GNUNET_TRANSPORT_ApplicationHandle *ah;
827
828/**
829 * Network scanner to determine network types.
830 */
831static struct GNUNET_NT_InterfaceScanner *is;
832
833/**
834 * Connection to NAT service.
835 */
836static struct GNUNET_NAT_Handle *nat;
837
838/**
839 * Port number to which we are actually bound.
840 */
841static uint16_t my_port;
842
843
844/**
845 * An interface went away, stop broadcasting on it.
846 *
847 * @param bi entity to close down
848 */
849static void
850bi_destroy (struct BroadcastInterface *bi)
851{
852 if (AF_INET6 == bi->sa->sa_family)
853 {
854 /* Leave the multicast group */
855 if (GNUNET_OK != GNUNET_NETWORK_socket_setsockopt (udp_sock,
856 IPPROTO_IPV6,
857 IPV6_LEAVE_GROUP,
858 &bi->mcreq,
859 sizeof(bi->mcreq)))
860 {
861 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
862 }
863 }
864 GNUNET_CONTAINER_DLL_remove (bi_head, bi_tail, bi);
865 GNUNET_SCHEDULER_cancel (bi->broadcast_task);
866 GNUNET_free (bi->sa);
867 GNUNET_free (bi->ba);
868 GNUNET_free (bi);
869}
870
871
872/**
873 * Destroys a receiving state due to timeout or shutdown.
874 *
875 * @param receiver entity to close down
876 */
877static void
878receiver_destroy (struct ReceiverAddress *receiver)
879{
880
881 receiver->receiver_destroy_called = GNUNET_YES;
882
883 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
884 "Disconnecting receiver for peer `%s'\n",
885 GNUNET_i2s (&receiver->target));
886 if (NULL != receiver->kx_qh)
887 {
888 GNUNET_TRANSPORT_communicator_mq_del (receiver->kx_qh);
889 receiver->kx_qh = NULL;
890 receiver->kx_mq = NULL;
891 }
892 if (NULL != receiver->d_qh)
893 {
894 GNUNET_TRANSPORT_communicator_mq_del (receiver->d_qh);
895 receiver->d_qh = NULL;
896 }
897 GNUNET_assert (GNUNET_YES ==
898 GNUNET_CONTAINER_multipeermap_remove (receivers,
899 &receiver->target,
900 receiver));
901 GNUNET_assert (receiver == GNUNET_CONTAINER_heap_remove_node (receiver->hn));
902 GNUNET_STATISTICS_set (stats,
903 "# receivers active",
904 GNUNET_CONTAINER_multipeermap_size (receivers),
905 GNUNET_NO);
906 GNUNET_free (receiver->address);
907 GNUNET_free (receiver->foreign_addr);
908 GNUNET_free (receiver);
909}
910
911
912/**
913 * Free memory used by key cache entry.
914 *
915 * @param kce the key cache entry
916 */
917static void
918kce_destroy (struct KeyCacheEntry *kce)
919{
920 struct SharedSecret *ss = kce->ss;
921
922 ss->active_kce_count--;
923 ss->sender->acks_available--;
924 GNUNET_CONTAINER_DLL_remove (ss->kce_head, ss->kce_tail, kce);
925 GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multishortmap_remove (key_cache,
926 &kce->kid,
927 kce));
928 GNUNET_free (kce);
929}
930
931
932/**
933 * Compute @a kid.
934 *
935 * @param msec master secret for HMAC calculation
936 * @param serial number for the @a smac calculation
937 * @param[out] kid where to write the key ID
938 */
939static void
940get_kid (const struct GNUNET_HashCode *msec,
941 uint32_t serial,
942 struct GNUNET_ShortHashCode *kid)
943{
944 uint32_t sid = htonl (serial);
945
946 GNUNET_CRYPTO_hkdf (kid,
947 sizeof(*kid),
948 GCRY_MD_SHA512,
949 GCRY_MD_SHA256,
950 &sid,
951 sizeof(sid),
952 msec,
953 sizeof(*msec),
954 "UDP-KID",
955 strlen ("UDP-KID"),
956 NULL,
957 0);
958}
959
960
961/**
962 * Setup key cache entry for sequence number @a seq and shared secret @a ss.
963 *
964 * @param ss shared secret
965 * @param seq sequence number for the key cache entry
966 */
967static void
968kce_generate (struct SharedSecret *ss, uint32_t seq)
969{
970 struct KeyCacheEntry *kce;
971
972 GNUNET_assert (0 < seq);
973 kce = GNUNET_new (struct KeyCacheEntry);
974 kce->ss = ss;
975 kce->sequence_number = seq;
976 get_kid (&ss->master, seq, &kce->kid);
977 GNUNET_CONTAINER_DLL_insert (ss->kce_head, ss->kce_tail, kce);
978 ss->active_kce_count++;
979 ss->sender->acks_available++;
980 (void) GNUNET_CONTAINER_multishortmap_put (
981 key_cache,
982 &kce->kid,
983 kce,
984 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
985 GNUNET_STATISTICS_set (stats,
986 "# KIDs active",
987 GNUNET_CONTAINER_multishortmap_size (key_cache),
988 GNUNET_NO);
989}
990
991
992/**
993 * Destroy @a ss and associated key cache entries.
994 *
995 * @param ss shared secret to destroy
996 * @param withoutKce If GNUNET_YES shared secrets with kce will not be destroyed.
997 */
998static int
999secret_destroy (struct SharedSecret *ss)
1000{
1001 struct SenderAddress *sender;
1002 struct ReceiverAddress *receiver;
1003 struct KeyCacheEntry *kce;
1004
1005 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1006 "secret %s destroy %u\n",
1007 GNUNET_h2s (&ss->master),
1008 ss->sequence_allowed);
1009 if (NULL != (sender = ss->sender))
1010 {
1011 GNUNET_CONTAINER_DLL_remove (sender->ss_head, sender->ss_tail, ss);
1012 sender->num_secrets--;
1013 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1014 "%u sender->num_secrets\n",
1015 receiver->num_secrets);
1016 if (NULL != ss->sender->kce_task)
1017 {
1018 GNUNET_SCHEDULER_cancel (ss->sender->kce_task);
1019 ss->sender->kce_task = NULL;
1020 }
1021 }
1022 if (NULL != (receiver = ss->receiver))
1023 {
1024 GNUNET_CONTAINER_DLL_remove (receiver->ss_head, receiver->ss_tail, ss);
1025 receiver->num_secrets--;
1026 receiver->acks_available -= (ss->sequence_allowed - ss->sequence_used);
1027 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1028 "%u receiver->num_secrets\n",
1029 receiver->num_secrets);
1030 }
1031 while (NULL != (kce = ss->kce_head))
1032 kce_destroy (kce);
1033 GNUNET_STATISTICS_update (stats, "# Secrets active", -1, GNUNET_NO);
1034 GNUNET_STATISTICS_set (stats,
1035 "# KIDs active",
1036 GNUNET_CONTAINER_multishortmap_size (key_cache),
1037 GNUNET_NO);
1038 GNUNET_free (ss);
1039 return GNUNET_YES;
1040}
1041
1042
1043/**
1044 * Functions with this signature are called whenever we need
1045 * to close a sender's state due to timeout.
1046 *
1047 * @param sender entity to close down
1048 */
1049static void
1050sender_destroy (struct SenderAddress *sender)
1051{
1052 sender->sender_destroy_called = GNUNET_YES;
1053 GNUNET_assert (
1054 GNUNET_YES ==
1055 GNUNET_CONTAINER_multipeermap_remove (senders, &sender->target, sender));
1056 GNUNET_assert (sender == GNUNET_CONTAINER_heap_remove_node (sender->hn));
1057 GNUNET_STATISTICS_set (stats,
1058 "# senders active",
1059 GNUNET_CONTAINER_multipeermap_size (senders),
1060 GNUNET_NO);
1061 GNUNET_free (sender->address);
1062 GNUNET_free (sender);
1063}
1064
1065
1066/**
1067 * Compute @a key and @a iv.
1068 *
1069 * @param msec master secret for calculation
1070 * @param serial number for the @a smac calculation
1071 * @param[out] key where to write the decryption key
1072 * @param[out] iv where to write the IV
1073 */
1074static void
1075get_iv_key (const struct GNUNET_HashCode *msec,
1076 uint32_t serial,
1077 char key[AES_KEY_SIZE],
1078 char iv[AES_IV_SIZE])
1079{
1080 uint32_t sid = htonl (serial);
1081 char res[AES_KEY_SIZE + AES_IV_SIZE];
1082
1083 GNUNET_CRYPTO_hkdf (res,
1084 sizeof(res),
1085 GCRY_MD_SHA512,
1086 GCRY_MD_SHA256,
1087 &sid,
1088 sizeof(sid),
1089 msec,
1090 sizeof(*msec),
1091 "UDP-IV-KEY",
1092 strlen ("UDP-IV-KEY"),
1093 NULL,
1094 0);
1095 memcpy (key, res, AES_KEY_SIZE);
1096 memcpy (iv, &res[AES_KEY_SIZE], AES_IV_SIZE);
1097}
1098
1099
1100/**
1101 * Increment sender timeout due to activity.
1102 *
1103 * @param sender address for which the timeout should be rescheduled
1104 */
1105static void
1106reschedule_sender_timeout (struct SenderAddress *sender)
1107{
1108 sender->timeout =
1109 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1110 GNUNET_CONTAINER_heap_update_cost (sender->hn, sender->timeout.abs_value_us);
1111}
1112
1113
1114/**
1115 * Increment receiver timeout due to activity.
1116 *
1117 * @param receiver address for which the timeout should be rescheduled
1118 */
1119static void
1120reschedule_receiver_timeout (struct ReceiverAddress *receiver)
1121{
1122 receiver->timeout =
1123 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1124 GNUNET_CONTAINER_heap_update_cost (receiver->hn,
1125 receiver->timeout.abs_value_us);
1126}
1127
1128
1129/**
1130 * Task run to check #receiver_heap and #sender_heap for timeouts.
1131 *
1132 * @param cls unused, NULL
1133 */
1134static void
1135check_timeouts (void *cls)
1136{
1137 struct GNUNET_TIME_Relative st;
1138 struct GNUNET_TIME_Relative rt;
1139 struct GNUNET_TIME_Relative delay;
1140 struct ReceiverAddress *receiver;
1141 struct SenderAddress *sender;
1142
1143 (void) cls;
1144 timeout_task = NULL;
1145 rt = GNUNET_TIME_UNIT_FOREVER_REL;
1146 while (NULL != (receiver = GNUNET_CONTAINER_heap_peek (receivers_heap)))
1147 {
1148 rt = GNUNET_TIME_absolute_get_remaining (receiver->timeout);
1149 if (0 != rt.rel_value_us)
1150 break;
1151 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1152 "Receiver timed out\n");
1153 receiver_destroy (receiver);
1154 }
1155 st = GNUNET_TIME_UNIT_FOREVER_REL;
1156 while (NULL != (sender = GNUNET_CONTAINER_heap_peek (senders_heap)))
1157 {
1158 if (GNUNET_YES != sender->sender_destroy_called)
1159 {
1160 st = GNUNET_TIME_absolute_get_remaining (sender->timeout);
1161 if (0 != st.rel_value_us)
1162 break;
1163 sender_destroy (sender);
1164 }
1165 }
1166 delay = GNUNET_TIME_relative_min (rt, st);
1167 if (delay.rel_value_us < GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1168 timeout_task = GNUNET_SCHEDULER_add_delayed (delay, &check_timeouts, NULL);
1169}
1170
1171
1172/**
1173 * Calculate cmac from master in @a ss.
1174 *
1175 * @param[in,out] ss data structure to complete
1176 */
1177static void
1178calculate_cmac (struct SharedSecret *ss)
1179{
1180 GNUNET_CRYPTO_hkdf (&ss->cmac,
1181 sizeof(ss->cmac),
1182 GCRY_MD_SHA512,
1183 GCRY_MD_SHA256,
1184 "CMAC",
1185 strlen ("CMAC"),
1186 &ss->master,
1187 sizeof(ss->master),
1188 "UDP-CMAC",
1189 strlen ("UDP-CMAC"),
1190 NULL,
1191 0);
1192}
1193
1194
1195/**
1196 * We received @a plaintext_len bytes of @a plaintext from a @a sender.
1197 * Pass it on to CORE.
1198 *
1199 * @param queue the queue that received the plaintext
1200 * @param plaintext the plaintext that was received
1201 * @param plaintext_len number of bytes of plaintext received
1202 */
1203static void
1204pass_plaintext_to_core (struct SenderAddress *sender,
1205 const void *plaintext,
1206 size_t plaintext_len)
1207{
1208 const struct GNUNET_MessageHeader *hdr = plaintext;
1209 const char *pos = plaintext;
1210
1211 while (ntohs (hdr->size) <= plaintext_len)
1212 {
1213 GNUNET_STATISTICS_update (stats,
1214 "# bytes given to core",
1215 ntohs (hdr->size),
1216 GNUNET_NO);
1217 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1218 "Giving %u bytes to TNG\n", ntohs (hdr->size));
1219 GNUNET_assert (GNUNET_SYSERR !=
1220 GNUNET_TRANSPORT_communicator_receive (ch,
1221 &sender->target,
1222 hdr,
1223 ADDRESS_VALIDITY_PERIOD,
1224 NULL /* no flow control possible */
1225 ,
1226 NULL));
1227 /* move on to next message, if any */
1228 plaintext_len -= ntohs (hdr->size);
1229 if (plaintext_len < sizeof(*hdr))
1230 break;
1231 pos += ntohs (hdr->size);
1232 hdr = (const struct GNUNET_MessageHeader *) pos;
1233 // TODO for now..., we do not actually sen >1msg or have a way of telling
1234 // if we are done
1235 break;
1236 }
1237 GNUNET_STATISTICS_update (stats,
1238 "# bytes padding discarded",
1239 plaintext_len,
1240 GNUNET_NO);
1241}
1242
1243
1244/**
1245 * Setup @a cipher based on shared secret @a msec and
1246 * serial number @a serial.
1247 *
1248 * @param msec master shared secret
1249 * @param serial serial number of cipher to set up
1250 * @param cipher[out] cipher to initialize
1251 */
1252static void
1253setup_cipher (const struct GNUNET_HashCode *msec,
1254 uint32_t serial,
1255 gcry_cipher_hd_t *cipher)
1256{
1257 char key[AES_KEY_SIZE];
1258 char iv[AES_IV_SIZE];
1259 int rc;
1260
1261 GNUNET_assert (0 ==
1262 gcry_cipher_open (cipher,
1263 GCRY_CIPHER_AES256 /* low level: go for speed */,
1264 GCRY_CIPHER_MODE_GCM,
1265 0 /* flags */));
1266 get_iv_key (msec, serial, key, iv);
1267 rc = gcry_cipher_setkey (*cipher, key, sizeof(key));
1268 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
1269 rc = gcry_cipher_setiv (*cipher, iv, sizeof(iv));
1270 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
1271}
1272
1273
1274/**
1275 * Try to decrypt @a buf using shared secret @a ss and key/iv
1276 * derived using @a serial.
1277 *
1278 * @param ss shared secret
1279 * @param tag GCM authentication tag
1280 * @param serial serial number to use
1281 * @param in_buf input buffer to decrypt
1282 * @param in_buf_size number of bytes in @a in_buf and available in @a out_buf
1283 * @param out_buf where to write the result
1284 * @return #GNUNET_OK on success
1285 */
1286static int
1287try_decrypt (const struct SharedSecret *ss,
1288 const uint8_t *tag,
1289 uint32_t serial,
1290 const char *in_buf,
1291 size_t in_buf_size,
1292 char *out_buf)
1293{
1294 gcry_cipher_hd_t cipher;
1295
1296 setup_cipher (&ss->master, serial, &cipher);
1297 GNUNET_assert (
1298 0 ==
1299 gcry_cipher_decrypt (cipher, out_buf, in_buf_size, in_buf, in_buf_size));
1300 if (0 != gcry_cipher_checktag (cipher, tag, GCM_TAG_SIZE))
1301 {
1302 gcry_cipher_close (cipher);
1303 GNUNET_STATISTICS_update (stats,
1304 "# AEAD authentication failures",
1305 1,
1306 GNUNET_NO);
1307 return GNUNET_SYSERR;
1308 }
1309 gcry_cipher_close (cipher);
1310 return GNUNET_OK;
1311}
1312
1313
1314/**
1315 * Setup shared secret for decryption.
1316 *
1317 * @param ephemeral ephemeral key we received from the other peer
1318 * @return new shared secret
1319 */
1320static struct SharedSecret *
1321setup_shared_secret_dec (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral)
1322{
1323 struct SharedSecret *ss;
1324
1325 ss = GNUNET_new (struct SharedSecret);
1326 GNUNET_CRYPTO_eddsa_kem_decaps (my_private_key, ephemeral, &ss->master);
1327 calculate_cmac (ss);
1328 return ss;
1329}
1330
1331
1332/**
1333 * Setup new shared secret for encryption using KEM.
1334 *
1335 * @param[out] ephemeral ephemeral key to be sent to other peer (encapsulated key from KEM)
1336 * @param[in,out] receiver queue to initialize encryption key for
1337 * @return new shared secret
1338 */
1339static struct SharedSecret *
1340setup_shared_secret_ephemeral (struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral,
1341 struct ReceiverAddress *receiver)
1342{
1343 struct SharedSecret *ss;
1344 struct GNUNET_HashCode k;
1345
1346 GNUNET_CRYPTO_eddsa_kem_encaps (&receiver->target.public_key, ephemeral, &k);
1347 ss = GNUNET_new (struct SharedSecret);
1348 memcpy (&ss->master, &k, sizeof (k));
1349 calculate_cmac (ss);
1350 ss->receiver = receiver;
1351 GNUNET_CONTAINER_DLL_insert (receiver->ss_head, receiver->ss_tail, ss);
1352 receiver->num_secrets++;
1353 GNUNET_STATISTICS_update (stats, "# Secrets active", 1, GNUNET_NO);
1354 return ss;
1355}
1356
1357
1358/**
1359 * Setup the MQ for the @a receiver. If a queue exists,
1360 * the existing one is destroyed. Then the MTU is
1361 * recalculated and a fresh queue is initialized.
1362 *
1363 * @param receiver receiver to setup MQ for
1364 */
1365static void
1366setup_receiver_mq (struct ReceiverAddress *receiver);
1367
1368
1369/**
1370 * Best effort try to purge some secrets.
1371 * Ideally those, not ACKed.
1372 *
1373 * @param ss_list_tail the oldest secret in the list of interest.
1374 * @return number of deleted secrets.
1375 */
1376unsigned int
1377purge_secrets (struct SharedSecret *ss_list_tail)
1378{
1379 struct SharedSecret *pos;
1380 struct SharedSecret *ss_to_purge;
1381 unsigned int deleted = 0;
1382
1383 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1384 "Purging secrets.\n");
1385 pos = ss_list_tail;
1386 while (NULL != pos)
1387 {
1388 ss_to_purge = pos;
1389 pos = pos->prev;
1390
1391 // FIXME we may also want to purge old unacked.
1392 if (rekey_max_bytes <= ss_to_purge->bytes_sent)
1393 {
1394 secret_destroy (ss_to_purge);
1395 deleted++;
1396 }
1397 }
1398 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1399 "Finished purging all, deleted %u.\n", deleted);
1400 return deleted;
1401}
1402
1403
1404static void
1405add_acks (struct SharedSecret *ss, int acks_to_add)
1406{
1407
1408 struct ReceiverAddress *receiver = ss->receiver;
1409
1410 GNUNET_assert (NULL != ss);
1411 GNUNET_assert (NULL != receiver);
1412
1413 if (NULL == receiver->d_qh)
1414 {
1415 receiver->d_qh =
1416 GNUNET_TRANSPORT_communicator_mq_add (ch,
1417 &receiver->target,
1418 receiver->foreign_addr,
1419 receiver->d_mtu,
1420 acks_to_add,
1421 1, /* Priority */
1422 receiver->nt,
1423 GNUNET_TRANSPORT_CS_OUTBOUND,
1424 receiver->d_mq);
1425 }
1426 else
1427 {
1428 GNUNET_TRANSPORT_communicator_mq_update (ch,
1429 receiver->d_qh,
1430 acks_to_add,
1431 1);
1432 }
1433
1434 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1435 "Tell transport we have %u more acks!\n",
1436 acks_to_add);
1437
1438 // Until here for alternativ 1
1439
1440 /* move ss to head to avoid discarding it anytime soon! */
1441
1442 GNUNET_CONTAINER_DLL_remove (receiver->ss_head, receiver->ss_tail, ss);
1443 GNUNET_CONTAINER_DLL_insert (receiver->ss_head, receiver->ss_tail, ss);
1444}
1445
1446
1447/**
1448 * We received an ACK for @a pid. Check if it is for
1449 * the receiver in @a value and if so, handle it and
1450 * return #GNUNET_NO. Otherwise, return #GNUNET_YES.
1451 *
1452 * @param cls a `const struct UDPAck`
1453 * @param pid peer the ACK is from
1454 * @param value a `struct ReceiverAddress`
1455 * @return #GNUNET_YES to continue to iterate
1456 */
1457static int
1458handle_ack (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
1459{
1460 const struct UDPAck *ack = cls;
1461 struct ReceiverAddress *receiver = value;
1462 uint32_t acks_to_add;
1463 uint32_t allowed;
1464
1465 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1466 "in handle ack with cmac %s\n",
1467 GNUNET_h2s (&ack->cmac));
1468
1469 (void) pid;
1470 for (struct SharedSecret *ss = receiver->ss_head; NULL != ss; ss = ss->next)
1471 {
1472 if (0 == memcmp (&ack->cmac, &ss->cmac, sizeof(struct GNUNET_HashCode)))
1473 {
1474
1475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1476 "Found matching cmac\n");
1477
1478 allowed = ntohl (ack->sequence_ack);
1479
1480 if (allowed <= ss->sequence_allowed)
1481 {
1482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1483 "Ignoring ack, not giving us increased window\n.");
1484 return GNUNET_NO;
1485 }
1486 acks_to_add = (allowed - ss->sequence_allowed);
1487 GNUNET_assert (0 != acks_to_add);
1488 receiver->acks_available += (allowed - ss->sequence_allowed);
1489 ss->sequence_allowed = allowed;
1490 add_acks (ss, acks_to_add);
1491 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1492 "New sequence allows until %u (+%u). Acks available to us: %u. For secret %s\n",
1493 allowed,
1494 acks_to_add,
1495 receiver->acks_available,
1496 GNUNET_h2s (&ss->master));
1497 return GNUNET_NO;
1498 }
1499 }
1500 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1501 "Matching cmac not found for ack!\n");
1502 return GNUNET_YES;
1503}
1504
1505
1506/**
1507 * We established a shared secret with a sender. We should try to send
1508 * the sender an `struct UDPAck` at the next opportunity to allow the
1509 * sender to use @a ss longer (assuming we did not yet already
1510 * recently).
1511 *
1512 * @param ss shared secret to generate ACKs for
1513 */
1514static void
1515consider_ss_ack (struct SharedSecret *ss)
1516{
1517 struct UDPAck ack;
1518 GNUNET_assert (NULL != ss->sender);
1519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1520 "Considering SS UDPAck %s\n",
1521 GNUNET_i2s_full (&ss->sender->target));
1522
1523 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1524 "Sender has %u acks available.\n",
1525 ss->sender->acks_available);
1526 /* drop ancient KeyCacheEntries */
1527 while ((NULL != ss->kce_head) &&
1528 (MAX_SQN_DELTA <
1529 ss->kce_head->sequence_number - ss->kce_tail->sequence_number))
1530 kce_destroy (ss->kce_tail);
1531
1532
1533 ack.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK);
1534 ack.header.size = htons (sizeof(ack));
1535 ack.sequence_ack = htonl (ss->sequence_allowed);
1536 ack.cmac = ss->cmac;
1537 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1538 "Notifying transport with UDPAck %s, sequence %u and master %s\n",
1539 GNUNET_i2s_full (&ss->sender->target),
1540 ss->sequence_allowed,
1541 GNUNET_h2s (&(ss->master)));
1542 GNUNET_TRANSPORT_communicator_notify (ch,
1543 &ss->sender->target,
1544 COMMUNICATOR_ADDRESS_PREFIX,
1545 &ack.header);
1546}
1547
1548
1549static void
1550kce_generate_cb (void *cls)
1551{
1552 struct SharedSecret *ss = cls;
1553 ss->sender->kce_task = NULL;
1554
1555 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1556 "Precomputing %u keys for master %s\n",
1557 GENERATE_AT_ONCE,
1558 GNUNET_h2s (&(ss->master)));
1559 if ((ss->override_available_acks != GNUNET_YES) &&
1560 (KCN_TARGET < ss->sender->acks_available))
1561 return;
1562 for (int i = 0; i < GENERATE_AT_ONCE; i++)
1563 kce_generate (ss, ++ss->sequence_allowed);
1564
1565 /**
1566 * As long as we loose over 30% of max acks in reschedule,
1567 * We keep generating acks for this ss.
1568 */
1569 if (KCN_TARGET > ss->sender->acks_available)
1570 {
1571 ss->sender->kce_task = GNUNET_SCHEDULER_add_delayed (
1572 WORKING_QUEUE_INTERVALL,
1573 kce_generate_cb,
1574 ss);
1575 return;
1576 }
1577 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1578 "We have enough keys (ACKs: %u).\n", ss->sender->acks_available);
1579 ss->sender->kce_task_finished = GNUNET_YES;
1580 ss->override_available_acks = GNUNET_NO;
1581 if (ss->sender->kce_send_ack_on_finish == GNUNET_YES)
1582 consider_ss_ack (ss);
1583}
1584
1585
1586/**
1587 * Test if we have received a valid message in plaintext.
1588 * If so, handle it.
1589 *
1590 * @param sender peer to process inbound plaintext for
1591 * @param buf buffer we received
1592 * @param buf_size number of bytes in @a buf
1593 */
1594static void
1595try_handle_plaintext (struct SenderAddress *sender,
1596 const void *buf,
1597 size_t buf_size)
1598{
1599 const struct GNUNET_MessageHeader *hdr;
1600 const struct UDPAck *ack;
1601 const struct UDPRekey *rekey;
1602 struct SharedSecret *ss_rekey;
1603 const char *buf_pos = buf;
1604 size_t bytes_remaining = buf_size;
1605 uint16_t type;
1606
1607 hdr = (struct GNUNET_MessageHeader*) buf_pos;
1608 if (sizeof(*hdr) > bytes_remaining)
1609 {
1610 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Plaintext too short, dropping...\n");
1611 return; /* no data left */
1612 }
1613 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1614 "try_handle_plaintext of size %lu (%u %lu) and type %u\n",
1615 bytes_remaining,
1616 ntohs (hdr->size),
1617 sizeof(*hdr),
1618 ntohs (hdr->type));
1619 if (ntohs (hdr->size) > bytes_remaining)
1620 return; /* buffer too short for indicated message length */
1621 type = ntohs (hdr->type);
1622 switch (type)
1623 {
1624 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_REKEY:
1625 rekey = (struct UDPRekey*) buf_pos;
1626 ss_rekey = setup_shared_secret_dec (&rekey->ephemeral);
1627 ss_rekey->sender = sender;
1628 GNUNET_CONTAINER_DLL_insert (sender->ss_head, sender->ss_tail, ss_rekey);
1629 sender->num_secrets++;
1630 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1631 "Received rekey secret with cmac %s\n",
1632 GNUNET_h2s (&(ss_rekey->cmac)));
1633 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1634 "Received secret with master %s.\n",
1635 GNUNET_h2s (&(ss_rekey->master)));
1636 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1637 "We have %u sequence_allowed.\n",
1638 ss_rekey->sequence_allowed);
1639 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1640 "We have a sender %p\n",
1641 ss_rekey->sender);
1642 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1643 "We have %u acks available.\n",
1644 ss_rekey->sender->acks_available);
1645 ss_rekey->sender->kce_send_ack_on_finish = GNUNET_YES;
1646 ss_rekey->override_available_acks = GNUNET_YES;
1647 // FIXME
1648 ss_rekey->sender->kce_task = GNUNET_SCHEDULER_add_delayed (
1649 WORKING_QUEUE_INTERVALL,
1650 kce_generate_cb,
1651 ss_rekey);
1652 // FIXME: Theoretically, this could be an Ack
1653 buf_pos += ntohs (hdr->size);
1654 bytes_remaining -= ntohs (hdr->size);
1655 pass_plaintext_to_core (sender, buf_pos, bytes_remaining);
1656 if (sender->num_secrets > MAX_SECRETS)
1657 {
1658 if (0 == purge_secrets (sender->ss_tail))
1659 {
1660 // No secret purged. Delete oldest.
1661 secret_destroy (sender->ss_tail);
1662 }
1663 }
1664 break;
1665 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK:
1666 /* lookup master secret by 'cmac', then update sequence_max */
1667 ack = (struct UDPAck*) buf_pos;
1668 GNUNET_CONTAINER_multipeermap_get_multiple (receivers,
1669 &sender->target,
1670 &handle_ack,
1671 (void *) ack);
1672 /* There could be more messages after the ACK, handle those as well */
1673 buf_pos += ntohs (hdr->size);
1674 bytes_remaining -= ntohs (hdr->size);
1675 pass_plaintext_to_core (sender, buf_pos, bytes_remaining);
1676 break;
1677
1678 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_PAD:
1679 /* skip padding */
1680 break;
1681
1682 default:
1683 pass_plaintext_to_core (sender, buf_pos, bytes_remaining);
1684 }
1685 return;
1686}
1687
1688
1689/**
1690 * We received a @a box with matching @a kce. Decrypt and process it.
1691 *
1692 * @param box the data we received
1693 * @param box_len number of bytes in @a box
1694 * @param kce key index to decrypt @a box
1695 */
1696static void
1697decrypt_box (const struct UDPBox *box,
1698 size_t box_len,
1699 struct KeyCacheEntry *kce)
1700{
1701 struct SharedSecret *ss = kce->ss;
1702 char out_buf[box_len - sizeof(*box)];
1703
1704 GNUNET_assert (NULL != ss->sender);
1705 if (GNUNET_OK != try_decrypt (ss,
1706 box->gcm_tag,
1707 kce->sequence_number,
1708 (const char *) &box[1],
1709 sizeof(out_buf),
1710 out_buf))
1711 {
1712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed decryption.\n");
1713 GNUNET_STATISTICS_update (stats,
1714 "# Decryption failures with valid KCE",
1715 1,
1716 GNUNET_NO);
1717 kce_destroy (kce);
1718 return;
1719 }
1720 kce_destroy (kce);
1721 kce = NULL;
1722 GNUNET_STATISTICS_update (stats,
1723 "# bytes decrypted with BOX",
1724 sizeof(out_buf),
1725 GNUNET_NO);
1726 GNUNET_STATISTICS_update (stats,
1727 "# messages decrypted with BOX",
1728 1,
1729 GNUNET_NO);
1730 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1731 "decrypted UDPBox with kid %s\n",
1732 GNUNET_sh2s (&box->kid));
1733 try_handle_plaintext (ss->sender, out_buf, sizeof(out_buf));
1734 if ((KCN_THRESHOLD > ss->sender->acks_available) &&
1735 (NULL == ss->sender->kce_task) &&
1736 (GNUNET_YES == ss->sender->kce_task_finished))
1737 {
1738 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1739 "Sender has %u ack left which is under threshold.\n",
1740 ss->sender->acks_available);
1741 ss->sender->kce_send_ack_on_finish = GNUNET_YES;
1742 ss->sender->kce_task = GNUNET_SCHEDULER_add_now (
1743 kce_generate_cb,
1744 ss);
1745 }
1746}
1747
1748
1749/**
1750 * Closure for #find_sender_by_address()
1751 */
1752struct SearchContext
1753{
1754 /**
1755 * Address we are looking for.
1756 */
1757 const struct sockaddr *address;
1758
1759 /**
1760 * Number of bytes in @e address.
1761 */
1762 socklen_t address_len;
1763
1764 /**
1765 * Return value to set if we found a match.
1766 */
1767 struct SenderAddress *sender;
1768};
1769
1770
1771/**
1772 * Find existing `struct SenderAddress` by matching addresses.
1773 *
1774 * @param cls a `struct SearchContext`
1775 * @param key ignored, must match already
1776 * @param value a `struct SenderAddress`
1777 * @return #GNUNET_YES if not found (continue to search), #GNUNET_NO if found
1778 */
1779static int
1780find_sender_by_address (void *cls,
1781 const struct GNUNET_PeerIdentity *key,
1782 void *value)
1783{
1784 struct SearchContext *sc = cls;
1785 struct SenderAddress *sender = value;
1786
1787 if ((sender->address_len == sc->address_len) &&
1788 (0 == memcmp (sender->address, sc->address, sender->address_len)))
1789 {
1790 sc->sender = sender;
1791 return GNUNET_NO; /* stop iterating! */
1792 }
1793 return GNUNET_YES;
1794}
1795
1796
1797/**
1798 * Create sender address for @a target. Note that we
1799 * might already have one, so a fresh one is only allocated
1800 * if one does not yet exist for @a address.
1801 *
1802 * @param target peer to generate address for
1803 * @param address target address
1804 * @param address_len number of bytes in @a address
1805 * @return data structure to keep track of key material for
1806 * decrypting data from @a target
1807 */
1808static struct SenderAddress *
1809setup_sender (const struct GNUNET_PeerIdentity *target,
1810 const struct sockaddr *address,
1811 socklen_t address_len)
1812{
1813 struct SenderAddress *sender;
1814 struct SearchContext sc = { .address = address,
1815 .address_len = address_len,
1816 .sender = NULL };
1817
1818 GNUNET_CONTAINER_multipeermap_get_multiple (senders,
1819 target,
1820 &find_sender_by_address,
1821 &sc);
1822 if (NULL != sc.sender)
1823 {
1824 reschedule_sender_timeout (sc.sender);
1825 return sc.sender;
1826 }
1827 sender = GNUNET_new (struct SenderAddress);
1828 sender->target = *target;
1829 sender->address = GNUNET_memdup (address, address_len);
1830 sender->address_len = address_len;
1831 (void) GNUNET_CONTAINER_multipeermap_put (
1832 senders,
1833 &sender->target,
1834 sender,
1835 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1836 GNUNET_STATISTICS_set (stats,
1837 "# senders active",
1838 GNUNET_CONTAINER_multipeermap_size (receivers),
1839 GNUNET_NO);
1840 sender->timeout =
1841 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1842 sender->hn = GNUNET_CONTAINER_heap_insert (senders_heap,
1843 sender,
1844 sender->timeout.abs_value_us);
1845 sender->nt = GNUNET_NT_scanner_get_type (is, address, address_len);
1846 if (NULL == timeout_task)
1847 timeout_task = GNUNET_SCHEDULER_add_now (&check_timeouts, NULL);
1848 return sender;
1849}
1850
1851
1852/**
1853 * Check signature from @a uc against @a ephemeral.
1854 *
1855 * @param ephemeral key that is signed
1856 * @param uc signature of claimant
1857 * @return #GNUNET_OK if signature is valid
1858 */
1859static int
1860verify_confirmation (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral,
1861 const struct UDPConfirmation *uc)
1862{
1863 struct UdpHandshakeSignature uhs;
1864
1865 uhs.purpose.purpose = htonl (
1866 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_HANDSHAKE);
1867 uhs.purpose.size = htonl (sizeof(uhs));
1868 uhs.sender = uc->sender;
1869 uhs.receiver = my_identity;
1870 uhs.ephemeral = *ephemeral;
1871 uhs.monotonic_time = uc->monotonic_time;
1872 return GNUNET_CRYPTO_eddsa_verify (
1873 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_HANDSHAKE,
1874 &uhs,
1875 &uc->sender_sig,
1876 &uc->sender.public_key);
1877}
1878
1879
1880/**
1881 * Converts @a address to the address string format used by this
1882 * communicator in HELLOs.
1883 *
1884 * @param address the address to convert, must be AF_INET or AF_INET6.
1885 * @param address_len number of bytes in @a address
1886 * @return string representation of @a address
1887 */
1888static char *
1889sockaddr_to_udpaddr_string (const struct sockaddr *address,
1890 socklen_t address_len)
1891{
1892 char *ret;
1893
1894 switch (address->sa_family)
1895 {
1896 case AF_INET:
1897 GNUNET_asprintf (&ret,
1898 "%s-%s",
1899 COMMUNICATOR_ADDRESS_PREFIX,
1900 GNUNET_a2s (address, address_len));
1901 break;
1902
1903 case AF_INET6:
1904 GNUNET_asprintf (&ret,
1905 "%s-%s",
1906 COMMUNICATOR_ADDRESS_PREFIX,
1907 GNUNET_a2s (address, address_len));
1908 break;
1909
1910 default:
1911 GNUNET_assert (0);
1912 }
1913 return ret;
1914}
1915
1916
1917/**
1918 * Socket read task.
1919 *
1920 * @param cls NULL
1921 */
1922static void
1923sock_read (void *cls)
1924{
1925 struct sockaddr_storage sa;
1926 struct sockaddr_in *addr_verify;
1927 socklen_t salen = sizeof(sa);
1928 char buf[UINT16_MAX];
1929 ssize_t rcvd;
1930
1931 (void) cls;
1932 read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1933 udp_sock,
1934 &sock_read,
1935 NULL);
1936 while (1)
1937 {
1938 rcvd = GNUNET_NETWORK_socket_recvfrom (udp_sock,
1939 buf,
1940 sizeof(buf),
1941 (struct sockaddr *) &sa,
1942 &salen);
1943 if (-1 == rcvd)
1944 {
1945 if (EAGAIN == errno)
1946 break; // We are done reading data
1947 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "recv");
1948 return;
1949 }
1950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1951 "Read %lu bytes\n", rcvd);
1952
1953 /* first, see if it is a UDPBox */
1954 if (rcvd > sizeof(struct UDPBox))
1955 {
1956 const struct UDPBox *box;
1957 struct KeyCacheEntry *kce;
1958
1959 box = (const struct UDPBox *) buf;
1960 kce = GNUNET_CONTAINER_multishortmap_get (key_cache, &box->kid);
1961 if (NULL != kce)
1962 {
1963 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1964 "Found KCE with kid %s\n",
1965 GNUNET_sh2s (&box->kid));
1966 decrypt_box (box, (size_t) rcvd, kce);
1967 continue;
1968 }
1969 }
1970
1971 /* next, check if it is a broadcast */
1972 if (sizeof(struct UDPBroadcast) == rcvd)
1973 {
1974 const struct UDPBroadcast *ub;
1975 struct UdpBroadcastSignature uhs;
1976 struct GNUNET_PeerIdentity sender;
1977
1978 addr_verify = GNUNET_memdup (&sa, salen);
1979 addr_verify->sin_port = 0;
1980 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1981 "received UDPBroadcast from %s\n",
1982 GNUNET_a2s ((const struct sockaddr *) addr_verify, salen));
1983 ub = (const struct UDPBroadcast *) buf;
1984 uhs.purpose.purpose = htonl (
1985 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_BROADCAST);
1986 uhs.purpose.size = htonl (sizeof(uhs));
1987 uhs.sender = ub->sender;
1988 sender = ub->sender;
1989 if (0 == memcmp (&sender, &my_identity, sizeof (struct
1990 GNUNET_PeerIdentity)))
1991 {
1992 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1993 "Received our own broadcast\n");
1994 GNUNET_free (addr_verify);
1995 continue;
1996 }
1997 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1998 "checking UDPBroadcastSignature for %s\n",
1999 GNUNET_i2s (&sender));
2000 GNUNET_CRYPTO_hash ((struct sockaddr *) addr_verify, salen,
2001 &uhs.h_address);
2002 if (GNUNET_OK ==
2003 GNUNET_CRYPTO_eddsa_verify (
2004 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_BROADCAST,
2005 &uhs,
2006 &ub->sender_sig,
2007 &ub->sender.public_key))
2008 {
2009 char *addr_s;
2010 enum GNUNET_NetworkType nt;
2011
2012 addr_s =
2013 sockaddr_to_udpaddr_string ((const struct sockaddr *) &sa, salen);
2014 GNUNET_STATISTICS_update (stats, "# broadcasts received", 1, GNUNET_NO);
2015 /* use our own mechanism to determine network type */
2016 nt =
2017 GNUNET_NT_scanner_get_type (is, (const struct sockaddr *) &sa, salen);
2018 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2019 "validating address %s received from UDPBroadcast\n",
2020 GNUNET_i2s (&sender));
2021 GNUNET_TRANSPORT_application_validate (ah, &sender, nt, addr_s);
2022 GNUNET_free (addr_s);
2023 GNUNET_free (addr_verify);
2024 continue;
2025 }
2026 else
2027 {
2028 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2029 "VerifyingPeer %s is verifying UDPBroadcast\n",
2030 GNUNET_i2s (&my_identity));
2031 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2032 "Verifying UDPBroadcast from %s failed\n",
2033 GNUNET_i2s (&ub->sender));
2034 }
2035 GNUNET_free (addr_verify);
2036 /* continue with KX, mostly for statistics... */
2037 }
2038
2039
2040 /* finally, test if it is a KX */
2041 if (rcvd < sizeof(struct UDPConfirmation) + sizeof(struct InitialKX))
2042 {
2043 GNUNET_STATISTICS_update (stats,
2044 "# messages dropped (no kid, too small for KX)",
2045 1,
2046 GNUNET_NO);
2047 continue;
2048 }
2049 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2050 "Got KX\n");
2051 {
2052 const struct InitialKX *kx;
2053 struct SharedSecret *ss;
2054 char pbuf[rcvd - sizeof(struct InitialKX)];
2055 const struct UDPConfirmation *uc;
2056 struct SenderAddress *sender;
2057
2058 kx = (const struct InitialKX *) buf;
2059 ss = setup_shared_secret_dec (&kx->ephemeral);
2060 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2061 "Before DEC\n");
2062
2063 if (GNUNET_OK != try_decrypt (ss,
2064 kx->gcm_tag,
2065 0,
2066 &buf[sizeof(*kx)],
2067 sizeof(pbuf),
2068 pbuf))
2069 {
2070 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2071 "Unable to decrypt tag, dropping...\n");
2072 GNUNET_free (ss);
2073 GNUNET_STATISTICS_update (
2074 stats,
2075 "# messages dropped (no kid, AEAD decryption failed)",
2076 1,
2077 GNUNET_NO);
2078 continue;
2079 }
2080 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2081 "Before VERIFY\n");
2082
2083 uc = (const struct UDPConfirmation *) pbuf;
2084 if (GNUNET_OK != verify_confirmation (&kx->ephemeral, uc))
2085 {
2086 GNUNET_break_op (0);
2087 GNUNET_free (ss);
2088 GNUNET_STATISTICS_update (stats,
2089 "# messages dropped (sender signature invalid)",
2090 1,
2091 GNUNET_NO);
2092 continue;
2093 }
2094 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2095 "Before SETUP_SENDER\n");
2096
2097 calculate_cmac (ss);
2098 sender = setup_sender (&uc->sender, (const struct sockaddr *) &sa, salen);
2099 ss->sender = sender;
2100 GNUNET_CONTAINER_DLL_insert (sender->ss_head, sender->ss_tail, ss);
2101 if ((KCN_THRESHOLD > ss->sender->acks_available) &&
2102 (NULL == ss->sender->kce_task) &&
2103 (GNUNET_NO == ss->sender->kce_task_finished))
2104 {
2105 // TODO This task must be per sender! FIXME: This is a nice todo, but I do not know what must be done here to fix.
2106 ss->sender->kce_send_ack_on_finish = GNUNET_YES;
2107 ss->sender->kce_task = GNUNET_SCHEDULER_add_now (
2108 kce_generate_cb,
2109 ss);
2110 }
2111 sender->num_secrets++;
2112 GNUNET_STATISTICS_update (stats, "# Secrets active", 1, GNUNET_NO);
2113 GNUNET_STATISTICS_update (stats,
2114 "# messages decrypted without BOX",
2115 1,
2116 GNUNET_NO);
2117 try_handle_plaintext (sender, &uc[1], sizeof(pbuf) - sizeof(*uc));
2118 if (sender->num_secrets > MAX_SECRETS)
2119 {
2120 if (0 == purge_secrets (sender->ss_tail))
2121 {
2122 // No secret purged. Delete oldest.
2123 secret_destroy (sender->ss_tail);
2124 }
2125 }
2126 }
2127 }
2128}
2129
2130
2131/**
2132 * Convert UDP bind specification to a `struct sockaddr *`
2133 *
2134 * @param bindto bind specification to convert
2135 * @param[out] sock_len set to the length of the address
2136 * @return converted bindto specification
2137 */
2138static struct sockaddr *
2139udp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
2140{
2141 struct sockaddr *in;
2142 unsigned int port;
2143 char dummy[2];
2144 char *colon;
2145 char *cp;
2146
2147 if (1 == sscanf (bindto, "%u%1s", &port, dummy))
2148 {
2149 /* interpreting value as just a PORT number */
2150 if (port > UINT16_MAX)
2151 {
2152 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2153 "BINDTO specification `%s' invalid: value too large for port\n",
2154 bindto);
2155 return NULL;
2156 }
2157 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
2158 (GNUNET_YES ==
2159 GNUNET_CONFIGURATION_get_value_yesno (cfg,
2160 COMMUNICATOR_CONFIG_SECTION,
2161 "DISABLE_V6")))
2162 {
2163 struct sockaddr_in *i4;
2164
2165 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
2166 i4->sin_family = AF_INET;
2167 i4->sin_port = htons ((uint16_t) port);
2168 *sock_len = sizeof(struct sockaddr_in);
2169 in = (struct sockaddr *) i4;
2170 }
2171 else
2172 {
2173 struct sockaddr_in6 *i6;
2174
2175 i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
2176 i6->sin6_family = AF_INET6;
2177 i6->sin6_port = htons ((uint16_t) port);
2178 *sock_len = sizeof(struct sockaddr_in6);
2179 in = (struct sockaddr *) i6;
2180 }
2181 return in;
2182 }
2183 cp = GNUNET_strdup (bindto);
2184 colon = strrchr (cp, ':');
2185 if (NULL != colon)
2186 {
2187 /* interpret value after colon as port */
2188 *colon = '\0';
2189 colon++;
2190 if (1 == sscanf (colon, "%u%1s", &port, dummy))
2191 {
2192 /* interpreting value as just a PORT number */
2193 if (port > UINT16_MAX)
2194 {
2195 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2196 "BINDTO specification `%s' invalid: value too large for port\n",
2197 bindto);
2198 GNUNET_free (cp);
2199 return NULL;
2200 }
2201 }
2202 else
2203 {
2204 GNUNET_log (
2205 GNUNET_ERROR_TYPE_ERROR,
2206 "BINDTO specification `%s' invalid: last ':' not followed by number\n",
2207 bindto);
2208 GNUNET_free (cp);
2209 return NULL;
2210 }
2211 }
2212 else
2213 {
2214 /* interpret missing port as 0, aka pick any free one */
2215 port = 0;
2216 }
2217 {
2218 /* try IPv4 */
2219 struct sockaddr_in v4;
2220
2221 memset (&v4, 0, sizeof(v4));
2222 if (1 == inet_pton (AF_INET, cp, &v4.sin_addr))
2223 {
2224 v4.sin_family = AF_INET;
2225 v4.sin_port = htons ((uint16_t) port);
2226#if HAVE_SOCKADDR_IN_SIN_LEN
2227 v4.sin_len = sizeof(struct sockaddr_in);
2228#endif
2229 in = GNUNET_memdup (&v4, sizeof(struct sockaddr_in));
2230 *sock_len = sizeof(struct sockaddr_in);
2231 GNUNET_free (cp);
2232 return in;
2233 }
2234 }
2235 {
2236 /* try IPv6 */
2237 struct sockaddr_in6 v6;
2238 const char *start;
2239
2240 memset (&v6, 0, sizeof(v6));
2241 start = cp;
2242 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
2243 {
2244 start++; /* skip over '[' */
2245 cp[strlen (cp) - 1] = '\0'; /* eat ']' */
2246 }
2247 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
2248 {
2249 v6.sin6_family = AF_INET6;
2250 v6.sin6_port = htons ((uint16_t) port);
2251#if HAVE_SOCKADDR_IN_SIN_LEN
2252 v6.sin6_len = sizeof(sizeof(struct sockaddr_in6));
2253#endif
2254 in = GNUNET_memdup (&v6, sizeof(v6));
2255 *sock_len = sizeof(v6);
2256 GNUNET_free (cp);
2257 return in;
2258 }
2259 }
2260 /* #5528 FIXME (feature!): maybe also try getnameinfo()? */
2261 GNUNET_free (cp);
2262 return NULL;
2263}
2264
2265
2266/**
2267 * Pad @a dgram by @a pad_size using @a out_cipher.
2268 *
2269 * @param out_cipher cipher to use
2270 * @param dgram datagram to pad
2271 * @param pad_size number of bytes of padding to append
2272 */
2273static void
2274do_pad (gcry_cipher_hd_t out_cipher, char *dgram, size_t pad_size)
2275{
2276 char pad[pad_size];
2277
2278 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, pad, sizeof(pad));
2279 if (sizeof(pad) > sizeof(struct GNUNET_MessageHeader))
2280 {
2281 struct GNUNET_MessageHeader hdr =
2282 { .size = htons (sizeof(pad)),
2283 .type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_PAD) };
2284
2285 memcpy (pad, &hdr, sizeof(hdr));
2286 }
2287 GNUNET_assert (
2288 0 ==
2289 gcry_cipher_encrypt (out_cipher, dgram, sizeof(pad), pad, sizeof(pad)));
2290}
2291
2292
2293static void
2294send_msg_with_kx (const struct GNUNET_MessageHeader *msg, struct
2295 ReceiverAddress *receiver)
2296{
2297 uint16_t msize = ntohs (msg->size);
2298 struct UdpHandshakeSignature uhs;
2299 struct UDPConfirmation uc;
2300 struct InitialKX kx;
2301 char dgram[receiver->kx_mtu + sizeof(uc) + sizeof(kx)];
2302 size_t dpos;
2303 gcry_cipher_hd_t out_cipher;
2304 struct SharedSecret *ss;
2305
2306 if (msize > receiver->kx_mtu)
2307 {
2308 GNUNET_break (0);
2309 if (GNUNET_YES != receiver->receiver_destroy_called)
2310 receiver_destroy (receiver);
2311 return;
2312 }
2313 reschedule_receiver_timeout (receiver);
2314
2315 /* setup key material */
2316
2317 ss = setup_shared_secret_ephemeral (&uhs.ephemeral, receiver);
2318
2319 if (receiver->num_secrets > MAX_SECRETS)
2320 {
2321 if (0 == purge_secrets (receiver->ss_tail))
2322 {
2323 // No secret purged. Delete oldest.
2324 secret_destroy (receiver->ss_tail);
2325 }
2326 }
2327
2328 setup_cipher (&ss->master, 0, &out_cipher);
2329 /* compute 'uc' */
2330 uc.sender = my_identity;
2331 uc.monotonic_time =
2332 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
2333 uhs.purpose.purpose = htonl (
2334 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_HANDSHAKE);
2335 uhs.purpose.size = htonl (sizeof(uhs));
2336 uhs.sender = my_identity;
2337 uhs.receiver = receiver->target;
2338 uhs.monotonic_time = uc.monotonic_time;
2339 GNUNET_CRYPTO_eddsa_sign (my_private_key,
2340 &uhs,
2341 &uc.sender_sig);
2342 /* Leave space for kx */
2343 dpos = sizeof(kx);
2344 /* Append encrypted uc to dgram */
2345 GNUNET_assert (0 == gcry_cipher_encrypt (out_cipher,
2346 &dgram[dpos],
2347 sizeof(uc),
2348 &uc,
2349 sizeof(uc)));
2350 dpos += sizeof(uc);
2351 /* Append encrypted payload to dgram */
2352 GNUNET_assert (
2353 0 == gcry_cipher_encrypt (out_cipher, &dgram[dpos], msize, msg, msize));
2354 dpos += msize;
2355 do_pad (out_cipher, &dgram[dpos], sizeof(dgram) - dpos);
2356 /* Datagram starts with kx */
2357 kx.ephemeral = uhs.ephemeral;
2358 GNUNET_assert (
2359 0 == gcry_cipher_gettag (out_cipher, kx.gcm_tag, sizeof(kx.gcm_tag)));
2360 gcry_cipher_close (out_cipher);
2361 memcpy (dgram, &kx, sizeof(kx));
2362 if (-1 == GNUNET_NETWORK_socket_sendto (udp_sock,
2363 dgram,
2364 sizeof(dgram),
2365 receiver->address,
2366 receiver->address_len))
2367 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send");
2368 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2369 "Sending KX with payload size %u to %s\n",
2370 msize,
2371 GNUNET_a2s (receiver->address,
2372 receiver->address_len));
2373}
2374
2375
2376/**
2377 * Signature of functions implementing the sending functionality of a
2378 * message queue.
2379 *
2380 * @param mq the message queue
2381 * @param msg the message to send
2382 * @param impl_state our `struct ReceiverAddress`
2383 */
2384static void
2385mq_send_kx (struct GNUNET_MQ_Handle *mq,
2386 const struct GNUNET_MessageHeader *msg,
2387 void *impl_state)
2388{
2389 struct ReceiverAddress *receiver = impl_state;
2390
2391 GNUNET_assert (mq == receiver->kx_mq);
2392 send_msg_with_kx (msg, receiver);
2393 GNUNET_MQ_impl_send_continue (mq);
2394}
2395
2396
2397static void
2398create_rekey (struct ReceiverAddress *receiver, struct SharedSecret *ss, struct
2399 UDPRekey *rekey)
2400{
2401 struct SharedSecret *ss_rekey;
2402
2403 ss->rekey_initiated = GNUNET_YES;
2404 /* setup key material */
2405 ss_rekey = setup_shared_secret_ephemeral (&rekey->ephemeral,
2406 receiver);
2407 ss_rekey->sequence_allowed = 0;
2408 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2409 "Setup secret with k = %s\n",
2410 GNUNET_h2s (&(ss_rekey->master)));
2411 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2412 "Setup secret with H(k) = %s\n",
2413 GNUNET_h2s (&(ss_rekey->cmac)));
2414
2415 /* Append encrypted payload to dgram */
2416 rekey->header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_REKEY);
2417 rekey->header.size = htons (sizeof (struct UDPRekey));
2418}
2419
2420
2421/**
2422 * Signature of functions implementing the sending functionality of a
2423 * message queue.
2424 *
2425 * @param mq the message queue
2426 * @param msg the message to send
2427 * @param impl_state our `struct ReceiverAddress`
2428 */
2429static void
2430mq_send_d (struct GNUNET_MQ_Handle *mq,
2431 const struct GNUNET_MessageHeader *msg,
2432 void *impl_state)
2433{
2434 struct ReceiverAddress *receiver = impl_state;
2435 struct UDPRekey rekey;
2436 struct SharedSecret *ss;
2437 int inject_rekey = GNUNET_NO;
2438 uint16_t msize = ntohs (msg->size);
2439
2440 GNUNET_assert (mq == receiver->d_mq);
2441 if ((msize > receiver->d_mtu) ||
2442 (0 == receiver->acks_available))
2443 {
2444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2445 "msize: %u, mtu: %lu, acks: %u\n",
2446 msize,
2447 receiver->d_mtu,
2448 receiver->acks_available);
2449
2450 GNUNET_break (0);
2451 if (GNUNET_YES != receiver->receiver_destroy_called)
2452 receiver_destroy (receiver);
2453 return;
2454 }
2455 reschedule_receiver_timeout (receiver);
2456
2457 if (receiver->num_secrets > MAX_SECRETS)
2458 {
2459 if (0 == purge_secrets (receiver->ss_tail))
2460 {
2461 // No secret purged. Delete oldest.
2462 secret_destroy (receiver->ss_tail);
2463 }
2464 }
2465 /* begin "BOX" encryption method, scan for ACKs from tail! */
2466 for (ss = receiver->ss_tail; NULL != ss; ss = ss->prev)
2467 {
2468 size_t payload_len = sizeof(struct UDPBox) + receiver->d_mtu;
2469 if (ss->sequence_used >= ss->sequence_allowed)
2470 {
2471 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2472 "Skipping ss because no acks to use.\n");
2473 continue;
2474 }
2475 if (ss->bytes_sent >= rekey_max_bytes)
2476 {
2477 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2478 "Skipping ss because rekey bytes reached.\n");
2479 // FIXME cleanup ss with too many bytes sent!
2480 continue;
2481 }
2482 if (ss->bytes_sent > rekey_max_bytes * 0.7)
2483 {
2484 if (ss->rekey_initiated == GNUNET_NO)
2485 {
2486 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2487 "Injecting rekey for ss with byte sent %lu\n",
2488 (unsigned long) ss->bytes_sent);
2489 create_rekey (receiver, ss, &rekey);
2490 inject_rekey = GNUNET_YES;
2491 payload_len += sizeof (rekey);
2492 ss->rekey_initiated = GNUNET_YES;
2493 }
2494 }
2495 if (0 < ss->sequence_used)
2496 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2497 "Trying to send UDPBox with shared secrect %s sequence_used %u and ss->sequence_allowed %u\n",
2498 GNUNET_h2s (&ss->master),
2499 ss->sequence_used,
2500 ss->sequence_allowed);
2501
2502 char dgram[payload_len];
2503 struct UDPBox *box;
2504 gcry_cipher_hd_t out_cipher;
2505 size_t dpos;
2506
2507 box = (struct UDPBox *) dgram;
2508 ss->sequence_used++;
2509 get_kid (&ss->master, ss->sequence_used, &box->kid);
2510 setup_cipher (&ss->master, ss->sequence_used, &out_cipher);
2511 /* Append encrypted payload to dgram */
2512 dpos = sizeof(struct UDPBox);
2513 if (GNUNET_YES == inject_rekey)
2514 {
2515 GNUNET_assert (
2516 0 == gcry_cipher_encrypt (out_cipher, &dgram[dpos], sizeof (rekey),
2517 &rekey, sizeof (rekey)));
2518 dpos += sizeof (rekey);
2519 }
2520 GNUNET_assert (
2521 0 == gcry_cipher_encrypt (out_cipher, &dgram[dpos], msize, msg, msize));
2522 dpos += msize;
2523 do_pad (out_cipher, &dgram[dpos], sizeof(dgram) - dpos);
2524 GNUNET_assert (0 == gcry_cipher_gettag (out_cipher,
2525 box->gcm_tag,
2526 sizeof(box->gcm_tag)));
2527 gcry_cipher_close (out_cipher);
2528
2529 if (-1 == GNUNET_NETWORK_socket_sendto (udp_sock,
2530 dgram,
2531 payload_len, // FIXME why always send sizeof dgram?
2532 receiver->address,
2533 receiver->address_len))
2534 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send");
2535 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2536 "Sending UDPBox with payload size %u, %u acks left, %lu bytes sent\n",
2537 msize,
2538 receiver->acks_available,
2539 (unsigned long) ss->bytes_sent);
2540 ss->bytes_sent += sizeof (dgram);
2541 receiver->acks_available--;
2542 GNUNET_MQ_impl_send_continue (mq);
2543 return;
2544 }
2545 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2546 "No suitable ss found, sending as KX...\n");
2547 send_msg_with_kx (msg, receiver);
2548 GNUNET_MQ_impl_send_continue (mq);
2549}
2550
2551
2552/**
2553 * Signature of functions implementing the destruction of a message
2554 * queue. Implementations must not free @a mq, but should take care
2555 * of @a impl_state.
2556 *
2557 * @param mq the message queue to destroy
2558 * @param impl_state our `struct ReceiverAddress`
2559 */
2560static void
2561mq_destroy_d (struct GNUNET_MQ_Handle *mq, void *impl_state)
2562{
2563 struct ReceiverAddress *receiver = impl_state;
2564 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2565 "Default MQ destroyed\n");
2566 if (mq == receiver->d_mq)
2567 {
2568 receiver->d_mq = NULL;
2569 if (GNUNET_YES != receiver->receiver_destroy_called)
2570 receiver_destroy (receiver);
2571 }
2572}
2573
2574
2575/**
2576 * Signature of functions implementing the destruction of a message
2577 * queue. Implementations must not free @a mq, but should take care
2578 * of @a impl_state.
2579 *
2580 * @param mq the message queue to destroy
2581 * @param impl_state our `struct ReceiverAddress`
2582 */
2583static void
2584mq_destroy_kx (struct GNUNET_MQ_Handle *mq, void *impl_state)
2585{
2586 struct ReceiverAddress *receiver = impl_state;
2587 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2588 "KX MQ destroyed\n");
2589 if (mq == receiver->kx_mq)
2590 {
2591 receiver->kx_mq = NULL;
2592 if (GNUNET_YES != receiver->receiver_destroy_called)
2593 receiver_destroy (receiver);
2594 }
2595}
2596
2597
2598/**
2599 * Implementation function that cancels the currently sent message.
2600 *
2601 * @param mq message queue
2602 * @param impl_state our `struct RecvierAddress`
2603 */
2604static void
2605mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
2606{
2607 /* Cancellation is impossible with UDP; bail */
2608 GNUNET_assert (0);
2609}
2610
2611
2612/**
2613 * Generic error handler, called with the appropriate
2614 * error code and the same closure specified at the creation of
2615 * the message queue.
2616 * Not every message queue implementation supports an error handler.
2617 *
2618 * @param cls our `struct ReceiverAddress`
2619 * @param error error code
2620 */
2621static void
2622mq_error (void *cls, enum GNUNET_MQ_Error error)
2623{
2624 struct ReceiverAddress *receiver = cls;
2625
2626 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2627 "MQ error in queue to %s: %d\n",
2628 GNUNET_i2s (&receiver->target),
2629 (int) error);
2630 receiver_destroy (receiver);
2631}
2632
2633
2634/**
2635 * Setup the MQ for the @a receiver. If a queue exists,
2636 * the existing one is destroyed. Then the MTU is
2637 * recalculated and a fresh queue is initialized.
2638 *
2639 * @param receiver receiver to setup MQ for
2640 */
2641static void
2642setup_receiver_mq (struct ReceiverAddress *receiver)
2643{
2644 size_t base_mtu;
2645
2646 switch (receiver->address->sa_family)
2647 {
2648 case AF_INET:
2649 base_mtu = 1480 /* Ethernet MTU, 1500 - Ethernet header - VLAN tag */
2650 - sizeof(struct GNUNET_TUN_IPv4Header) /* 20 */
2651 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
2652 break;
2653
2654 case AF_INET6:
2655 base_mtu = 1280 /* Minimum MTU required by IPv6 */
2656 - sizeof(struct GNUNET_TUN_IPv6Header) /* 40 */
2657 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
2658 break;
2659
2660 default:
2661 GNUNET_assert (0);
2662 break;
2663 }
2664 /* MTU based on full KX messages */
2665 receiver->kx_mtu = base_mtu - sizeof(struct InitialKX) /* 48 */
2666 - sizeof(struct UDPConfirmation); /* 104 */
2667 /* MTU based on BOXed messages */
2668 receiver->d_mtu = base_mtu - sizeof(struct UDPBox);
2669
2670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2671 "Setting up MQs and QHs\n");
2672 /* => Effective MTU for CORE will range from 1080 (IPv6 + KX) to
2673 1404 (IPv4 + Box) bytes, depending on circumstances... */
2674 if (NULL == receiver->kx_mq)
2675 receiver->kx_mq = GNUNET_MQ_queue_for_callbacks (&mq_send_kx,
2676 &mq_destroy_kx,
2677 &mq_cancel,
2678 receiver,
2679 NULL,
2680 &mq_error,
2681 receiver);
2682 if (NULL == receiver->d_mq)
2683 receiver->d_mq = GNUNET_MQ_queue_for_callbacks (&mq_send_d,
2684 &mq_destroy_d,
2685 &mq_cancel,
2686 receiver,
2687 NULL,
2688 &mq_error,
2689 receiver);
2690
2691 receiver->kx_qh =
2692 GNUNET_TRANSPORT_communicator_mq_add (ch,
2693 &receiver->target,
2694 receiver->foreign_addr,
2695 receiver->kx_mtu,
2696 GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED,
2697 0, /* Priority */
2698 receiver->nt,
2699 GNUNET_TRANSPORT_CS_OUTBOUND,
2700 receiver->kx_mq);
2701}
2702
2703
2704/**
2705 * Function called by the transport service to initialize a
2706 * message queue given address information about another peer.
2707 * If and when the communication channel is established, the
2708 * communicator must call #GNUNET_TRANSPORT_communicator_mq_add()
2709 * to notify the service that the channel is now up. It is
2710 * the responsibility of the communicator to manage sane
2711 * retries and timeouts for any @a peer/@a address combination
2712 * provided by the transport service. Timeouts and retries
2713 * do not need to be signalled to the transport service.
2714 *
2715 * @param cls closure
2716 * @param peer identity of the other peer
2717 * @param address where to send the message, human-readable
2718 * communicator-specific format, 0-terminated, UTF-8
2719 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the provided address is
2720 * invalid
2721 */
2722static int
2723mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
2724{
2725 struct ReceiverAddress *receiver;
2726 const char *path;
2727 struct sockaddr *in;
2728 socklen_t in_len;
2729
2730 if (0 != strncmp (address,
2731 COMMUNICATOR_ADDRESS_PREFIX "-",
2732 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
2733 {
2734 GNUNET_break_op (0);
2735 return GNUNET_SYSERR;
2736 }
2737 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
2738 in = udp_address_to_sockaddr (path, &in_len);
2739
2740 receiver = GNUNET_new (struct ReceiverAddress);
2741 receiver->address = in;
2742 receiver->address_len = in_len;
2743 receiver->target = *peer;
2744 receiver->nt = GNUNET_NT_scanner_get_type (is, in, in_len);
2745 (void) GNUNET_CONTAINER_multipeermap_put (
2746 receivers,
2747 &receiver->target,
2748 receiver,
2749 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2750 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2751 "Added %s to receivers\n",
2752 GNUNET_i2s_full (&receiver->target));
2753 receiver->timeout =
2754 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2755 receiver->hn = GNUNET_CONTAINER_heap_insert (receivers_heap,
2756 receiver,
2757 receiver->timeout.abs_value_us);
2758 GNUNET_STATISTICS_set (stats,
2759 "# receivers active",
2760 GNUNET_CONTAINER_multipeermap_size (receivers),
2761 GNUNET_NO);
2762 receiver->foreign_addr =
2763 sockaddr_to_udpaddr_string (receiver->address, receiver->address_len);
2764 setup_receiver_mq (receiver);
2765 if (NULL == timeout_task)
2766 timeout_task = GNUNET_SCHEDULER_add_now (&check_timeouts, NULL);
2767 return GNUNET_OK;
2768}
2769
2770
2771/**
2772 * Iterator over all receivers to clean up.
2773 *
2774 * @param cls NULL
2775 * @param target unused
2776 * @param value the queue to destroy
2777 * @return #GNUNET_OK to continue to iterate
2778 */
2779static int
2780get_receiver_delete_it (void *cls,
2781 const struct GNUNET_PeerIdentity *target,
2782 void *value)
2783{
2784 struct ReceiverAddress *receiver = value;
2785
2786 (void) cls;
2787 (void) target;
2788 receiver_destroy (receiver);
2789 return GNUNET_OK;
2790}
2791
2792
2793/**
2794 * Iterator over all senders to clean up.
2795 *
2796 * @param cls NULL
2797 * @param target unused
2798 * @param value the queue to destroy
2799 * @return #GNUNET_OK to continue to iterate
2800 */
2801static int
2802get_sender_delete_it (void *cls,
2803 const struct GNUNET_PeerIdentity *target,
2804 void *value)
2805{
2806 struct SenderAddress *sender = value;
2807
2808 (void) cls;
2809 (void) target;
2810
2811
2812 sender_destroy (sender);
2813 return GNUNET_OK;
2814}
2815
2816
2817/**
2818 * Shutdown the UNIX communicator.
2819 *
2820 * @param cls NULL (always)
2821 */
2822static void
2823do_shutdown (void *cls)
2824{
2825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2826 "do_shutdown\n");
2827 if (NULL != nat)
2828 {
2829 GNUNET_NAT_unregister (nat);
2830 nat = NULL;
2831 }
2832 while (NULL != bi_head)
2833 bi_destroy (bi_head);
2834 if (NULL != broadcast_task)
2835 {
2836 GNUNET_SCHEDULER_cancel (broadcast_task);
2837 broadcast_task = NULL;
2838 }
2839 if (NULL != timeout_task)
2840 {
2841 GNUNET_SCHEDULER_cancel (timeout_task);
2842 timeout_task = NULL;
2843 }
2844 if (NULL != read_task)
2845 {
2846 GNUNET_SCHEDULER_cancel (read_task);
2847 read_task = NULL;
2848 }
2849 if (NULL != udp_sock)
2850 {
2851 GNUNET_break (GNUNET_OK ==
2852 GNUNET_NETWORK_socket_close (udp_sock));
2853 udp_sock = NULL;
2854 }
2855 GNUNET_CONTAINER_multipeermap_iterate (receivers,
2856 &get_receiver_delete_it,
2857 NULL);
2858 GNUNET_CONTAINER_multipeermap_destroy (receivers);
2859 GNUNET_CONTAINER_multipeermap_iterate (senders,
2860 &get_sender_delete_it,
2861 NULL);
2862 GNUNET_CONTAINER_multipeermap_destroy (senders);
2863 GNUNET_CONTAINER_multishortmap_destroy (key_cache);
2864 GNUNET_CONTAINER_heap_destroy (senders_heap);
2865 GNUNET_CONTAINER_heap_destroy (receivers_heap);
2866 if (NULL != timeout_task)
2867 {
2868 GNUNET_SCHEDULER_cancel (timeout_task);
2869 timeout_task = NULL;
2870 }
2871 if (NULL != ch)
2872 {
2873 GNUNET_TRANSPORT_communicator_disconnect (ch);
2874 ch = NULL;
2875 }
2876 if (NULL != ah)
2877 {
2878 GNUNET_TRANSPORT_application_done (ah);
2879 ah = NULL;
2880 }
2881 if (NULL != stats)
2882 {
2883 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2884 stats = NULL;
2885 }
2886 if (NULL != my_private_key)
2887 {
2888 GNUNET_free (my_private_key);
2889 my_private_key = NULL;
2890 }
2891 if (NULL != is)
2892 {
2893 GNUNET_NT_scanner_done (is);
2894 is = NULL;
2895 }
2896 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2897 "do_shutdown finished\n");
2898}
2899
2900
2901/**
2902 * Function called when the transport service has received a
2903 * backchannel message for this communicator (!) via a different return
2904 * path. Should be an acknowledgement.
2905 *
2906 * @param cls closure, NULL
2907 * @param sender which peer sent the notification
2908 * @param msg payload
2909 */
2910static void
2911enc_notify_cb (void *cls,
2912 const struct GNUNET_PeerIdentity *sender,
2913 const struct GNUNET_MessageHeader *msg)
2914{
2915 const struct UDPAck *ack;
2916
2917 (void) cls;
2918 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2919 "Storing UDPAck received from backchannel from %s\n",
2920 GNUNET_i2s_full (sender));
2921 if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK) ||
2922 (ntohs (msg->size) != sizeof(struct UDPAck)))
2923 {
2924 GNUNET_break_op (0);
2925 return;
2926 }
2927 ack = (const struct UDPAck *) msg;
2928 GNUNET_CONTAINER_multipeermap_get_multiple (receivers,
2929 sender,
2930 &handle_ack,
2931 (void *) ack);
2932}
2933
2934
2935/**
2936 * Signature of the callback passed to #GNUNET_NAT_register() for
2937 * a function to call whenever our set of 'valid' addresses changes.
2938 *
2939 * @param cls closure
2940 * @param app_ctx[in,out] location where the app can store stuff
2941 * on add and retrieve it on remove
2942 * @param add_remove #GNUNET_YES to add a new public IP address,
2943 * #GNUNET_NO to remove a previous (now invalid) one
2944 * @param ac address class the address belongs to
2945 * @param addr either the previous or the new public IP address
2946 * @param addrlen actual length of the @a addr
2947 */
2948static void
2949nat_address_cb (void *cls,
2950 void **app_ctx,
2951 int add_remove,
2952 enum GNUNET_NAT_AddressClass ac,
2953 const struct sockaddr *addr,
2954 socklen_t addrlen)
2955{
2956 char *my_addr;
2957 struct GNUNET_TRANSPORT_AddressIdentifier *ai;
2958
2959 if (GNUNET_YES == add_remove)
2960 {
2961 enum GNUNET_NetworkType nt;
2962
2963 GNUNET_asprintf (&my_addr,
2964 "%s-%s",
2965 COMMUNICATOR_ADDRESS_PREFIX,
2966 GNUNET_a2s (addr, addrlen));
2967 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
2968 ai =
2969 GNUNET_TRANSPORT_communicator_address_add (ch,
2970 my_addr,
2971 nt,
2972 GNUNET_TIME_UNIT_FOREVER_REL);
2973 GNUNET_free (my_addr);
2974 *app_ctx = ai;
2975 }
2976 else
2977 {
2978 ai = *app_ctx;
2979 GNUNET_TRANSPORT_communicator_address_remove (ai);
2980 *app_ctx = NULL;
2981 }
2982}
2983
2984
2985/**
2986 * Broadcast our presence on one of our interfaces.
2987 *
2988 * @param cls a `struct BroadcastInterface`
2989 */
2990static void
2991ifc_broadcast (void *cls)
2992{
2993 struct BroadcastInterface *bi = cls;
2994 struct GNUNET_TIME_Relative delay;
2995
2996 delay = BROADCAST_FREQUENCY;
2997 delay.rel_value_us =
2998 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, delay.rel_value_us);
2999 bi->broadcast_task =
3000 GNUNET_SCHEDULER_add_delayed (delay, &ifc_broadcast, bi);
3001
3002 switch (bi->sa->sa_family)
3003 {
3004 case AF_INET: {
3005 static int yes = 1;
3006 static int no = 0;
3007 ssize_t sent;
3008
3009 if (GNUNET_OK !=
3010 GNUNET_NETWORK_socket_setsockopt (udp_sock,
3011 SOL_SOCKET,
3012 SO_BROADCAST,
3013 &yes,
3014 sizeof(int)))
3015 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
3016 "setsockopt");
3017 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3018 "creating UDPBroadcast from %s\n",
3019 GNUNET_i2s (&(bi->bcm.sender)));
3020 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3021 "sending UDPBroadcast to add %s\n",
3022 GNUNET_a2s (bi->ba, bi->salen));
3023 sent = GNUNET_NETWORK_socket_sendto (udp_sock,
3024 &bi->bcm,
3025 sizeof(bi->bcm),
3026 bi->ba,
3027 bi->salen);
3028 if (-1 == sent)
3029 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
3030 "sendto");
3031 if (GNUNET_OK != GNUNET_NETWORK_socket_setsockopt (udp_sock,
3032 SOL_SOCKET,
3033 SO_BROADCAST,
3034 &no,
3035 sizeof(int)))
3036 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
3037 "setsockopt");
3038 break;
3039 }
3040
3041 case AF_INET6: {
3042 ssize_t sent;
3043 struct sockaddr_in6 dst;
3044
3045 dst.sin6_family = AF_INET6;
3046 dst.sin6_port = htons (my_port);
3047 dst.sin6_addr = bi->mcreq.ipv6mr_multiaddr;
3048 dst.sin6_scope_id = ((struct sockaddr_in6 *) bi->ba)->sin6_scope_id;
3049
3050 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3051 "sending UDPBroadcast\n");
3052 sent = GNUNET_NETWORK_socket_sendto (udp_sock,
3053 &bi->bcm,
3054 sizeof(bi->bcm),
3055 (const struct sockaddr *) &dst,
3056 sizeof(dst));
3057 if (-1 == sent)
3058 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "sendto");
3059 break;
3060 }
3061
3062 default:
3063 GNUNET_break (0);
3064 break;
3065 }
3066}
3067
3068
3069/**
3070 * Callback function invoked for each interface found.
3071 * Activates/deactivates broadcast interfaces.
3072 *
3073 * @param cls NULL
3074 * @param name name of the interface (can be NULL for unknown)
3075 * @param isDefault is this presumably the default interface
3076 * @param addr address of this interface (can be NULL for unknown or unassigned)
3077 * @param broadcast_addr the broadcast address (can be NULL for unknown or
3078 * unassigned)
3079 * @param netmask the network mask (can be NULL for unknown or unassigned)
3080 * @param addrlen length of the address
3081 * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort
3082 */
3083static int
3084iface_proc (void *cls,
3085 const char *name,
3086 int isDefault,
3087 const struct sockaddr *addr,
3088 const struct sockaddr *broadcast_addr,
3089 const struct sockaddr *netmask,
3090 socklen_t addrlen)
3091{
3092 struct BroadcastInterface *bi;
3093 enum GNUNET_NetworkType network;
3094 struct UdpBroadcastSignature ubs;
3095
3096 (void) cls;
3097 (void) netmask;
3098 if (NULL == addr)
3099 return GNUNET_YES; /* need to know our address! */
3100 network = GNUNET_NT_scanner_get_type (is, addr, addrlen);
3101 if (GNUNET_NT_LOOPBACK == network)
3102 {
3103 /* Broadcasting on loopback does not make sense */
3104 return GNUNET_YES;
3105 }
3106 for (bi = bi_head; NULL != bi; bi = bi->next)
3107 {
3108 if ((bi->salen == addrlen) && (0 == memcmp (addr, bi->sa, addrlen)))
3109 {
3110 bi->found = GNUNET_YES;
3111 return GNUNET_OK;
3112 }
3113 }
3114
3115 if ((AF_INET6 == addr->sa_family) && (NULL == broadcast_addr))
3116 return GNUNET_OK; /* broadcast_addr is required for IPv6! */
3117 if ((AF_INET6 == addr->sa_family) && (GNUNET_YES != have_v6_socket))
3118 return GNUNET_OK; /* not using IPv6 */
3119
3120 bi = GNUNET_new (struct BroadcastInterface);
3121 bi->sa = GNUNET_memdup (addr,
3122 addrlen);
3123 if ( (NULL != broadcast_addr) &&
3124 (addrlen == sizeof (struct sockaddr_in)) )
3125 {
3126 struct sockaddr_in *ba;
3127
3128 ba = GNUNET_memdup (broadcast_addr,
3129 addrlen);
3130 ba->sin_port = htons (2086); /* always GNUnet port, ignore configuration! */
3131 bi->ba = (struct sockaddr *) ba;
3132 }
3133 bi->salen = addrlen;
3134 bi->found = GNUNET_YES;
3135 bi->bcm.sender = my_identity;
3136 ubs.purpose.purpose = htonl (
3137 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_BROADCAST);
3138 ubs.purpose.size = htonl (sizeof(ubs));
3139 ubs.sender = my_identity;
3140 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3141 "creating UDPBroadcastSignature for %s\n",
3142 GNUNET_a2s (addr, addrlen));
3143 GNUNET_CRYPTO_hash (addr, addrlen, &ubs.h_address);
3144 GNUNET_CRYPTO_eddsa_sign (my_private_key,
3145 &ubs,
3146 &bi->bcm.sender_sig);
3147 if (NULL != bi->ba)
3148 {
3149 bi->broadcast_task = GNUNET_SCHEDULER_add_now (&ifc_broadcast, bi);
3150 GNUNET_CONTAINER_DLL_insert (bi_head, bi_tail, bi);
3151 }
3152 if ((AF_INET6 == addr->sa_family) && (NULL != broadcast_addr))
3153 {
3154 /* Create IPv6 multicast request */
3155 const struct sockaddr_in6 *s6 =
3156 (const struct sockaddr_in6 *) broadcast_addr;
3157
3158 GNUNET_assert (
3159 1 == inet_pton (AF_INET6, "FF05::13B", &bi->mcreq.ipv6mr_multiaddr));
3160
3161 /* http://tools.ietf.org/html/rfc2553#section-5.2:
3162 *
3163 * IPV6_JOIN_GROUP
3164 *
3165 * Join a multicast group on a specified local interface. If the
3166 * interface index is specified as 0, the kernel chooses the local
3167 * interface. For example, some kernels look up the multicast
3168 * group in the normal IPv6 routing table and using the resulting
3169 * interface; we do this for each interface, so no need to use
3170 * zero (anymore...).
3171 */
3172 bi->mcreq.ipv6mr_interface = s6->sin6_scope_id;
3173
3174 /* Join the multicast group */
3175 if (GNUNET_OK != GNUNET_NETWORK_socket_setsockopt (udp_sock,
3176 IPPROTO_IPV6,
3177 IPV6_JOIN_GROUP,
3178 &bi->mcreq,
3179 sizeof(bi->mcreq)))
3180 {
3181 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
3182 }
3183 }
3184 return GNUNET_OK;
3185}
3186
3187
3188/**
3189 * Scan interfaces to broadcast our presence on the LAN.
3190 *
3191 * @param cls NULL, unused
3192 */
3193static void
3194do_broadcast (void *cls)
3195{
3196 struct BroadcastInterface *bin;
3197
3198 (void) cls;
3199 for (struct BroadcastInterface *bi = bi_head; NULL != bi; bi = bi->next)
3200 bi->found = GNUNET_NO;
3201 GNUNET_OS_network_interfaces_list (&iface_proc, NULL);
3202 for (struct BroadcastInterface *bi = bi_head; NULL != bi; bi = bin)
3203 {
3204 bin = bi->next;
3205 if (GNUNET_NO == bi->found)
3206 bi_destroy (bi);
3207 }
3208 broadcast_task = GNUNET_SCHEDULER_add_delayed (INTERFACE_SCAN_FREQUENCY,
3209 &do_broadcast,
3210 NULL);
3211}
3212
3213
3214static void
3215try_connection_reversal (void *cls,
3216 const struct sockaddr *addr,
3217 socklen_t addrlen)
3218{
3219 /* FIXME: support reversal: #5529 */
3220 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3221 "No connection reversal implemented!");
3222}
3223
3224
3225/**
3226 * Setup communicator and launch network interactions.
3227 *
3228 * @param cls NULL (always)
3229 * @param args remaining command-line arguments
3230 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
3231 * @param c configuration
3232 */
3233static void
3234run (void *cls,
3235 char *const *args,
3236 const char *cfgfile,
3237 const struct GNUNET_CONFIGURATION_Handle *c)
3238{
3239 char *bindto;
3240 struct sockaddr *in;
3241 socklen_t in_len;
3242 struct sockaddr_storage in_sto;
3243 socklen_t sto_len;
3244
3245 (void) cls;
3246 cfg = c;
3247 if (GNUNET_OK !=
3248 GNUNET_CONFIGURATION_get_value_string (cfg,
3249 COMMUNICATOR_CONFIG_SECTION,
3250 "BINDTO",
3251 &bindto))
3252 {
3253 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3254 COMMUNICATOR_CONFIG_SECTION,
3255 "BINDTO");
3256 return;
3257 }
3258
3259 if (GNUNET_OK !=
3260 GNUNET_CONFIGURATION_get_value_time (cfg,
3261 COMMUNICATOR_CONFIG_SECTION,
3262 "REKEY_INTERVAL",
3263 &rekey_interval))
3264 rekey_interval = DEFAULT_REKEY_TIME_INTERVAL;
3265
3266 if (GNUNET_OK !=
3267 GNUNET_CONFIGURATION_get_value_size (cfg,
3268 COMMUNICATOR_CONFIG_SECTION,
3269 "REKEY_MAX_BYTES",
3270 &rekey_max_bytes))
3271 rekey_max_bytes = DEFAULT_REKEY_MAX_BYTES;
3272
3273 in = udp_address_to_sockaddr (bindto, &in_len);
3274 if (NULL == in)
3275 {
3276 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3277 "Failed to setup UDP socket address with path `%s'\n",
3278 bindto);
3279 GNUNET_free (bindto);
3280 return;
3281 }
3282 udp_sock =
3283 GNUNET_NETWORK_socket_create (in->sa_family,
3284 SOCK_DGRAM,
3285 IPPROTO_UDP);
3286 if (NULL == udp_sock)
3287 {
3288 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
3289 GNUNET_free (in);
3290 GNUNET_free (bindto);
3291 return;
3292 }
3293 if (AF_INET6 == in->sa_family)
3294 have_v6_socket = GNUNET_YES;
3295 if (GNUNET_OK !=
3296 GNUNET_NETWORK_socket_bind (udp_sock,
3297 in,
3298 in_len))
3299 {
3300 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
3301 "bind",
3302 bindto);
3303 GNUNET_NETWORK_socket_close (udp_sock);
3304 udp_sock = NULL;
3305 GNUNET_free (in);
3306 GNUNET_free (bindto);
3307 return;
3308 }
3309
3310 /* We might have bound to port 0, allowing the OS to figure it out;
3311 thus, get the real IN-address from the socket */
3312 sto_len = sizeof(in_sto);
3313 if (0 != getsockname (GNUNET_NETWORK_get_fd (udp_sock),
3314 (struct sockaddr *) &in_sto,
3315 &sto_len))
3316 {
3317 memcpy (&in_sto, in, in_len);
3318 sto_len = in_len;
3319 }
3320 GNUNET_free (in);
3321 GNUNET_free (bindto);
3322 in = (struct sockaddr *) &in_sto;
3323 in_len = sto_len;
3324 GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG,
3325 "transport",
3326 "Bound to `%s'\n",
3327 GNUNET_a2s ((const struct sockaddr *) &in_sto,
3328 sto_len));
3329 switch (in->sa_family)
3330 {
3331 case AF_INET:
3332 my_port = ntohs (((struct sockaddr_in *) in)->sin_port);
3333 break;
3334
3335 case AF_INET6:
3336 my_port = ntohs (((struct sockaddr_in6 *) in)->sin6_port);
3337 break;
3338
3339 default:
3340 GNUNET_break (0);
3341 my_port = 0;
3342 }
3343 stats = GNUNET_STATISTICS_create ("C-UDP", cfg);
3344 senders = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_YES);
3345 receivers = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_YES);
3346 senders_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3347 receivers_heap =
3348 GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3349 key_cache = GNUNET_CONTAINER_multishortmap_create (1024, GNUNET_YES);
3350 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
3351 is = GNUNET_NT_scanner_init ();
3352 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
3353 if (NULL == my_private_key)
3354 {
3355 GNUNET_log (
3356 GNUNET_ERROR_TYPE_ERROR,
3357 _ (
3358 "Transport service is lacking key configuration settings. Exiting.\n"));
3359 GNUNET_SCHEDULER_shutdown ();
3360 return;
3361 }
3362 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_identity.public_key);
3363 /* start reading */
3364 read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
3365 udp_sock,
3366 &sock_read,
3367 NULL);
3368 ch = GNUNET_TRANSPORT_communicator_connect (cfg,
3369 COMMUNICATOR_CONFIG_SECTION,
3370 COMMUNICATOR_ADDRESS_PREFIX,
3371 GNUNET_TRANSPORT_CC_UNRELIABLE,
3372 &mq_init,
3373 NULL,
3374 &enc_notify_cb,
3375 NULL);
3376 if (NULL == ch)
3377 {
3378 GNUNET_break (0);
3379 GNUNET_SCHEDULER_shutdown ();
3380 return;
3381 }
3382 ah = GNUNET_TRANSPORT_application_init (cfg);
3383 if (NULL == ah)
3384 {
3385 GNUNET_break (0);
3386 GNUNET_SCHEDULER_shutdown ();
3387 return;
3388 }
3389 /* start broadcasting */
3390 if (GNUNET_YES !=
3391 GNUNET_CONFIGURATION_get_value_yesno (cfg,
3392 COMMUNICATOR_CONFIG_SECTION,
3393 "DISABLE_BROADCAST"))
3394 {
3395 broadcast_task = GNUNET_SCHEDULER_add_now (&do_broadcast, NULL);
3396 }
3397 nat = GNUNET_NAT_register (cfg,
3398 COMMUNICATOR_CONFIG_SECTION,
3399 IPPROTO_UDP,
3400 1 /* one address */,
3401 (const struct sockaddr **) &in,
3402 &in_len,
3403 &nat_address_cb,
3404 try_connection_reversal,
3405 NULL /* closure */);
3406}
3407
3408
3409/**
3410 * The main function for the UNIX communicator.
3411 *
3412 * @param argc number of arguments from the command line
3413 * @param argv command line arguments
3414 * @return 0 ok, 1 on error
3415 */
3416int
3417main (int argc, char *const *argv)
3418{
3419 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
3420 GNUNET_GETOPT_OPTION_END
3421 };
3422 int ret;
3423
3424 GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG,
3425 "transport",
3426 "Starting udp communicator\n");
3427 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
3428 return 2;
3429
3430 ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc,
3431 argv,
3432 "gnunet-communicator-udp",
3433 _ ("GNUnet UDP communicator"),
3434 options,
3435 &run,
3436 NULL))
3437 ? 0
3438 : 1;
3439 GNUNET_free_nz ((void *) argv);
3440 return ret;
3441}
3442
3443
3444/* end of gnunet-communicator-udp.c */
diff --git a/src/transport/gnunet-communicator-unix.c b/src/transport/gnunet-communicator-unix.c
deleted file mode 100644
index 0ff16ab08..000000000
--- a/src/transport/gnunet-communicator-unix.c
+++ /dev/null
@@ -1,1166 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2014, 2018 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 transport/gnunet-communicator-unix.c
23 * @brief Transport plugin using unix domain sockets (!)
24 * Clearly, can only be used locally on Unix/Linux hosts...
25 * ONLY INTENDED FOR TESTING!!!
26 * @author Christian Grothoff
27 * @author Nathan Evans
28 */
29#include "platform.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_protocols.h"
32#include "gnunet_constants.h"
33#include "gnunet_statistics_service.h"
34#include "gnunet_transport_communication_service.h"
35
36/**
37 * How many messages do we keep at most in the queue to the
38 * transport service before we start to drop (default,
39 * can be changed via the configuration file).
40 * Should be _below_ the level of the communicator API, as
41 * otherwise we may read messages just to have them dropped
42 * by the communicator API.
43 */
44#define DEFAULT_MAX_QUEUE_LENGTH 8000
45
46/**
47 * Address prefix used by the communicator.
48 */
49#define COMMUNICATOR_ADDRESS_PREFIX "unix"
50
51/**
52 * Configuration section used by the communicator.
53 */
54#define COMMUNICATOR_CONFIG_SECTION "communicator-unix"
55
56/**
57 * Our MTU.
58 */
59#ifndef DARWIN
60#define UNIX_MTU UINT16_MAX
61#else
62#define UNIX_MTU 2048
63#endif
64
65GNUNET_NETWORK_STRUCT_BEGIN
66
67/**
68 * UNIX Message-Packet header.
69 */
70struct UNIXMessage
71{
72 /**
73 * Message header.
74 */
75 struct GNUNET_MessageHeader header;
76
77 /**
78 * What is the identity of the sender (GNUNET_hash of public key)
79 */
80 struct GNUNET_PeerIdentity sender;
81};
82
83GNUNET_NETWORK_STRUCT_END
84
85
86/**
87 * Handle for a queue.
88 */
89struct Queue
90{
91 /**
92 * Queues with pending messages (!) are kept in a DLL.
93 */
94 struct Queue *next;
95
96 /**
97 * Queues with pending messages (!) are kept in a DLL.
98 */
99 struct Queue *prev;
100
101 /**
102 * To whom are we talking to.
103 */
104 struct GNUNET_PeerIdentity target;
105
106 /**
107 * Address of the other peer.
108 */
109 struct sockaddr_un *address;
110
111 /**
112 * Length of the address.
113 */
114 socklen_t address_len;
115
116 /**
117 * Message currently scheduled for transmission, non-NULL if and only
118 * if this queue is in the #queue_head DLL.
119 */
120 struct UNIXMessage *msg;
121
122 /**
123 * Message queue we are providing for the #ch.
124 */
125 struct GNUNET_MQ_Handle *mq;
126
127 /**
128 * handle for this queue with the #ch.
129 */
130 struct GNUNET_TRANSPORT_QueueHandle *qh;
131
132 /**
133 * Number of bytes we currently have in our write queue.
134 */
135 unsigned long long bytes_in_queue;
136
137 /**
138 * Timeout for this queue.
139 */
140 struct GNUNET_TIME_Absolute timeout;
141
142 /**
143 * Queue timeout task.
144 */
145 struct GNUNET_SCHEDULER_Task *timeout_task;
146};
147
148/**
149 * My Peer Identity
150 */
151static struct GNUNET_PeerIdentity my_identity;
152
153/**
154 * ID of read task
155 */
156static struct GNUNET_SCHEDULER_Task *read_task;
157
158/**
159 * ID of write task
160 */
161static struct GNUNET_SCHEDULER_Task *write_task;
162
163/**
164 * Number of messages we currently have in our queues towards the transport service.
165 */
166static unsigned long long delivering_messages;
167
168/**
169 * Maximum queue length before we stop reading towards the transport service.
170 */
171static unsigned long long max_queue_length;
172
173/**
174 * For logging statistics.
175 */
176static struct GNUNET_STATISTICS_Handle *stats;
177
178/**
179 * Our environment.
180 */
181static struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
182
183/**
184 * Queues (map from peer identity to `struct Queue`)
185 */
186static struct GNUNET_CONTAINER_MultiPeerMap *queue_map;
187
188/**
189 * Head of queue of messages to transmit.
190 */
191static struct Queue *queue_head;
192
193/**
194 * Tail of queue of messages to transmit.
195 */
196static struct Queue *queue_tail;
197
198/**
199 * socket that we transmit all data with
200 */
201static struct GNUNET_NETWORK_Handle *unix_sock;
202
203/**
204 * Handle to the operation that publishes our address.
205 */
206static struct GNUNET_TRANSPORT_AddressIdentifier *ai;
207
208
209/**
210 * Functions with this signature are called whenever we need
211 * to close a queue due to a disconnect or failure to
212 * establish a connection.
213 *
214 * @param queue queue to close down
215 */
216static void
217queue_destroy (struct Queue *queue)
218{
219 struct GNUNET_MQ_Handle *mq;
220
221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
222 "Disconnecting queue for peer `%s'\n",
223 GNUNET_i2s (&queue->target));
224 if (0 != queue->bytes_in_queue)
225 {
226 GNUNET_CONTAINER_DLL_remove (queue_head, queue_tail, queue);
227 queue->bytes_in_queue = 0;
228 }
229 if (NULL != (mq = queue->mq))
230 {
231 queue->mq = NULL;
232 GNUNET_MQ_destroy (mq);
233 }
234 GNUNET_assert (
235 GNUNET_YES ==
236 GNUNET_CONTAINER_multipeermap_remove (queue_map, &queue->target, queue));
237 GNUNET_STATISTICS_set (stats,
238 "# queues active",
239 GNUNET_CONTAINER_multipeermap_size (queue_map),
240 GNUNET_NO);
241 if (NULL != queue->timeout_task)
242 {
243 GNUNET_SCHEDULER_cancel (queue->timeout_task);
244 queue->timeout_task = NULL;
245 }
246 GNUNET_free (queue->address);
247 GNUNET_free (queue);
248}
249
250
251/**
252 * Queue was idle for too long, so disconnect it
253 *
254 * @param cls the `struct Queue *` to disconnect
255 */
256static void
257queue_timeout (void *cls)
258{
259 struct Queue *queue = cls;
260 struct GNUNET_TIME_Relative left;
261
262 queue->timeout_task = NULL;
263 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
264 if (0 != left.rel_value_us)
265 {
266 /* not actually our turn yet, but let's at least update
267 the monitor, it may think we're about to die ... */
268 queue->timeout_task =
269 GNUNET_SCHEDULER_add_delayed (left, &queue_timeout, queue);
270 return;
271 }
272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
273 "Queue %p was idle for %s, disconnecting\n",
274 queue,
275 GNUNET_STRINGS_relative_time_to_string (
276 GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
277 GNUNET_YES));
278 queue_destroy (queue);
279}
280
281
282/**
283 * Increment queue timeout due to activity. We do not immediately
284 * notify the monitor here as that might generate excessive
285 * signalling.
286 *
287 * @param queue queue for which the timeout should be rescheduled
288 */
289static void
290reschedule_queue_timeout (struct Queue *queue)
291{
292 GNUNET_assert (NULL != queue->timeout_task);
293 queue->timeout =
294 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
295}
296
297
298/**
299 * Convert unix path to a `struct sockaddr_un *`
300 *
301 * @param unixpath path to convert
302 * @param[out] sock_len set to the length of the address
303 * @param is_abstract is this an abstract @a unixpath
304 * @return converted unix path
305 */
306static struct sockaddr_un *
307unix_address_to_sockaddr (const char *unixpath, socklen_t *sock_len)
308{
309 struct sockaddr_un *un;
310 size_t slen;
311
312 GNUNET_assert (0 < strlen (unixpath)); /* sanity check */
313 un = GNUNET_new (struct sockaddr_un);
314 un->sun_family = AF_UNIX;
315 slen = strlen (unixpath);
316 if (slen >= sizeof(un->sun_path))
317 slen = sizeof(un->sun_path) - 1;
318 GNUNET_memcpy (un->sun_path, unixpath, slen);
319 un->sun_path[slen] = '\0';
320 slen = sizeof(struct sockaddr_un);
321#if HAVE_SOCKADDR_UN_SUN_LEN
322 un->sun_len = (u_char) slen;
323#endif
324 (*sock_len) = slen;
325 if ('@' == un->sun_path[0])
326 un->sun_path[0] = '\0';
327 return un;
328}
329
330
331/**
332 * Closure to #lookup_queue_it().
333 */
334struct LookupCtx
335{
336 /**
337 * Location to store the queue, if found.
338 */
339 struct Queue *res;
340
341 /**
342 * Address we are looking for.
343 */
344 const struct sockaddr_un *un;
345
346 /**
347 * Number of bytes in @a un
348 */
349 socklen_t un_len;
350};
351
352
353/**
354 * Function called to find a queue by address.
355 *
356 * @param cls the `struct LookupCtx *`
357 * @param key peer we are looking for (unused)
358 * @param value a queue
359 * @return #GNUNET_YES if not found (continue looking), #GNUNET_NO on success
360 */
361static int
362lookup_queue_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
363{
364 struct LookupCtx *lctx = cls;
365 struct Queue *queue = value;
366
367 if ((queue->address_len == lctx->un_len) &&
368 (0 == memcmp (lctx->un, queue->address, queue->address_len)))
369 {
370 lctx->res = queue;
371 return GNUNET_NO;
372 }
373 return GNUNET_YES;
374}
375
376
377/**
378 * Find an existing queue by address.
379 *
380 * @param plugin the plugin
381 * @param address the address to find
382 * @return NULL if queue was not found
383 */
384static struct Queue *
385lookup_queue (const struct GNUNET_PeerIdentity *peer,
386 const struct sockaddr_un *un,
387 socklen_t un_len)
388{
389 struct LookupCtx lctx;
390
391 lctx.un = un;
392 lctx.un_len = un_len;
393 lctx.res = NULL;
394 GNUNET_CONTAINER_multipeermap_get_multiple (queue_map,
395 peer,
396 &lookup_queue_it,
397 &lctx);
398 return lctx.res;
399}
400
401
402/**
403 * We have been notified that our socket is ready to write.
404 * Then reschedule this function to be called again once more is available.
405 *
406 * @param cls NULL
407 */
408static void
409select_write_cb (void *cls)
410{
411 struct Queue *queue = queue_tail;
412 const struct GNUNET_MessageHeader *msg = &queue->msg->header;
413 size_t msg_size = ntohs (msg->size);
414 ssize_t sent;
415
416 /* take queue of the ready list */
417 write_task = NULL;
418resend:
419 /* Send the data */
420 sent = GNUNET_NETWORK_socket_sendto (unix_sock,
421 msg,
422 msg_size,
423 (const struct sockaddr *) queue->address,
424 queue->address_len);
425 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
426 "UNIX transmitted message to %s (%d/%u: %s)\n",
427 GNUNET_i2s (&queue->target),
428 (int) sent,
429 (unsigned int) msg_size,
430 (sent < 0) ? strerror (errno) : "ok");
431 if (-1 != sent)
432 {
433 GNUNET_CONTAINER_DLL_remove (queue_head, queue_tail, queue);
434 if (NULL != queue_head)
435 write_task = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
436 unix_sock,
437 &select_write_cb,
438 NULL);
439
440 /* send 'msg' */
441 GNUNET_free (queue->msg);
442 queue->msg = NULL;
443 GNUNET_MQ_impl_send_continue (queue->mq);
444 GNUNET_STATISTICS_update (stats,
445 "# bytes sent",
446 (long long) sent,
447 GNUNET_NO);
448 reschedule_queue_timeout (queue);
449 return; /* all good */
450 }
451 GNUNET_STATISTICS_update (stats,
452 "# network transmission failures",
453 1,
454 GNUNET_NO);
455 write_task = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
456 unix_sock,
457 &select_write_cb,
458 NULL);
459 switch (errno)
460 {
461 case EAGAIN:
462 case ENOBUFS:
463 /* We should retry later... */
464 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send");
465 return;
466
467 case EMSGSIZE: {
468 socklen_t size = 0;
469 socklen_t len = sizeof(size);
470
471 GNUNET_NETWORK_socket_getsockopt (unix_sock,
472 SOL_SOCKET,
473 SO_SNDBUF,
474 &size,
475 &len);
476 if (size > ntohs (msg->size))
477 {
478 /* Buffer is bigger than message: error, no retry
479 * This should never happen!*/
480 GNUNET_break (0);
481 return;
482 }
483 GNUNET_log (
484 GNUNET_ERROR_TYPE_WARNING,
485 "Trying to increase socket buffer size from %u to %u for message size %u\n",
486 (unsigned int) size,
487 (unsigned int) ((msg_size / 1000) + 2) * 1000,
488 (unsigned int) msg_size);
489 size = ((msg_size / 1000) + 2) * 1000;
490 if (GNUNET_OK == GNUNET_NETWORK_socket_setsockopt (unix_sock,
491 SOL_SOCKET,
492 SO_SNDBUF,
493 &size,
494 sizeof(size)))
495 goto resend; /* Increased buffer size, retry sending */
496 /* Ok, then just try very modest increase */
497 size = msg_size;
498 if (GNUNET_OK == GNUNET_NETWORK_socket_setsockopt (unix_sock,
499 SOL_SOCKET,
500 SO_SNDBUF,
501 &size,
502 sizeof(size)))
503 goto resend; /* Increased buffer size, retry sending */
504 /* Could not increase buffer size: error, no retry */
505 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "setsockopt");
506 return;
507 }
508
509 default:
510 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "send");
511 return;
512 }
513}
514
515
516/**
517 * Signature of functions implementing the sending functionality of a
518 * message queue.
519 *
520 * @param mq the message queue
521 * @param msg the message to send
522 * @param impl_state our `struct Queue`
523 */
524static void
525mq_send (struct GNUNET_MQ_Handle *mq,
526 const struct GNUNET_MessageHeader *msg,
527 void *impl_state)
528{
529 struct Queue *queue = impl_state;
530 size_t msize = ntohs (msg->size);
531
532 GNUNET_assert (mq == queue->mq);
533 GNUNET_assert (NULL == queue->msg);
534 // Convert to UNIXMessage
535 queue->msg = GNUNET_malloc (msize + sizeof (struct UNIXMessage));
536 queue->msg->header.size = htons (msize + sizeof (struct UNIXMessage));
537 queue->msg->sender = my_identity;
538 memcpy (&queue->msg[1], msg, msize);
539 GNUNET_CONTAINER_DLL_insert (queue_head, queue_tail, queue);
540 GNUNET_assert (NULL != unix_sock);
541 if (NULL == write_task)
542 write_task = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
543 unix_sock,
544 &select_write_cb,
545 NULL);
546}
547
548
549/**
550 * Signature of functions implementing the destruction of a message
551 * queue. Implementations must not free @a mq, but should take care
552 * of @a impl_state.
553 *
554 * @param mq the message queue to destroy
555 * @param impl_state our `struct Queue`
556 */
557static void
558mq_destroy (struct GNUNET_MQ_Handle *mq, void *impl_state)
559{
560 struct Queue *queue = impl_state;
561
562 if (mq == queue->mq)
563 {
564 queue->mq = NULL;
565 queue_destroy (queue);
566 }
567}
568
569
570/**
571 * Implementation function that cancels the currently sent message.
572 *
573 * @param mq message queue
574 * @param impl_state our `struct Queue`
575 */
576static void
577mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
578{
579 struct Queue *queue = impl_state;
580
581 GNUNET_assert (NULL != queue->msg);
582 queue->msg = NULL;
583 GNUNET_CONTAINER_DLL_remove (queue_head, queue_tail, queue);
584 GNUNET_assert (NULL != write_task);
585 if (NULL == queue_head)
586 {
587 GNUNET_SCHEDULER_cancel (write_task);
588 write_task = NULL;
589 }
590}
591
592
593/**
594 * Generic error handler, called with the appropriate
595 * error code and the same closure specified at the creation of
596 * the message queue.
597 * Not every message queue implementation supports an error handler.
598 *
599 * @param cls our `struct Queue`
600 * @param error error code
601 */
602static void
603mq_error (void *cls, enum GNUNET_MQ_Error error)
604{
605 struct Queue *queue = cls;
606
607 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
608 "UNIX MQ error in queue to %s: %d\n",
609 GNUNET_i2s (&queue->target),
610 (int) error);
611 queue_destroy (queue);
612}
613
614
615/**
616 * Creates a new outbound queue the transport service will use to send
617 * data to another peer.
618 *
619 * @param peer the target peer
620 * @param cs inbound or outbound queue
621 * @param un the address
622 * @param un_len number of bytes in @a un
623 * @return the queue or NULL of max connections exceeded
624 */
625static struct Queue *
626setup_queue (const struct GNUNET_PeerIdentity *target,
627 enum GNUNET_TRANSPORT_ConnectionStatus cs,
628 const struct sockaddr_un *un,
629 socklen_t un_len)
630{
631 struct Queue *queue;
632
633 queue = GNUNET_new (struct Queue);
634 queue->target = *target;
635 queue->address = GNUNET_memdup (un, un_len);
636 queue->address_len = un_len;
637 (void) GNUNET_CONTAINER_multipeermap_put (
638 queue_map,
639 &queue->target,
640 queue,
641 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
642 GNUNET_STATISTICS_set (stats,
643 "# queues active",
644 GNUNET_CONTAINER_multipeermap_size (queue_map),
645 GNUNET_NO);
646 queue->timeout =
647 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
648 queue->timeout_task =
649 GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
650 &queue_timeout,
651 queue);
652 queue->mq = GNUNET_MQ_queue_for_callbacks (&mq_send,
653 &mq_destroy,
654 &mq_cancel,
655 queue,
656 NULL,
657 &mq_error,
658 queue);
659 {
660 char *foreign_addr;
661
662 if ('\0' == un->sun_path[0])
663 GNUNET_asprintf (&foreign_addr,
664 "%s-@%s",
665 COMMUNICATOR_ADDRESS_PREFIX,
666 &un->sun_path[1]);
667 else
668 GNUNET_asprintf (&foreign_addr,
669 "%s-%s",
670 COMMUNICATOR_ADDRESS_PREFIX,
671 un->sun_path);
672 queue->qh = GNUNET_TRANSPORT_communicator_mq_add (ch,
673 &queue->target,
674 foreign_addr,
675 UNIX_MTU - sizeof (struct
676 UNIXMessage),
677 GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED,
678 0,
679 GNUNET_NT_LOOPBACK,
680 cs,
681 queue->mq);
682 GNUNET_free (foreign_addr);
683 }
684 return queue;
685}
686
687
688/**
689 * We have been notified that our socket has something to read. Do the
690 * read and reschedule this function to be called again once more is
691 * available.
692 *
693 * @param cls NULL
694 */
695static void
696select_read_cb (void *cls);
697
698
699/**
700 * Function called when message was successfully passed to
701 * transport service. Continue read activity.
702 *
703 * @param cls NULL
704 * @param success #GNUNET_OK on success
705 */
706static void
707receive_complete_cb (void *cls, int success)
708{
709 (void) cls;
710 delivering_messages--;
711 if (GNUNET_OK != success)
712 GNUNET_STATISTICS_update (stats,
713 "# transport transmission failures",
714 1,
715 GNUNET_NO);
716 if ((NULL == read_task) && (delivering_messages < max_queue_length) &&
717 (NULL != unix_sock))
718 read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
719 unix_sock,
720 &select_read_cb,
721 NULL);
722}
723
724
725/**
726 * We have been notified that our socket has something to read. Do the
727 * read and reschedule this function to be called again once more is
728 * available.
729 *
730 * @param cls NULL
731 */
732static void
733select_read_cb (void *cls)
734{
735 char buf[65536] GNUNET_ALIGN;
736 struct Queue *queue;
737 const struct UNIXMessage *msg;
738 struct sockaddr_un un;
739 socklen_t addrlen;
740 ssize_t ret;
741 uint16_t msize;
742
743 GNUNET_assert (NULL != unix_sock);
744 read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
745 unix_sock,
746 &select_read_cb,
747 NULL);
748 addrlen = sizeof(un);
749 memset (&un, 0, sizeof(un));
750 ret = GNUNET_NETWORK_socket_recvfrom (unix_sock,
751 buf,
752 sizeof(buf),
753 (struct sockaddr *) &un,
754 &addrlen);
755 if ((-1 == ret) && ((EAGAIN == errno) || (ENOBUFS == errno)))
756 return;
757 if (-1 == ret)
758 {
759 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "recvfrom");
760 return;
761 }
762 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
763 "Read %d bytes from socket %s\n",
764 (int) ret,
765 un.sun_path);
766 GNUNET_assert (AF_UNIX == (un.sun_family));
767 msg = (struct UNIXMessage *) buf;
768 msize = ntohs (msg->header.size);
769 if ((msize < sizeof(struct UNIXMessage)) || (msize > ret))
770 {
771 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
772 "Wrong message size: %d bytes\n",
773 msize);
774 GNUNET_break_op (0);
775 return;
776 }
777 queue = lookup_queue (&msg->sender, &un, addrlen);
778 if (NULL == queue)
779 queue =
780 setup_queue (&msg->sender, GNUNET_TRANSPORT_CS_INBOUND, &un, addrlen);
781 else
782 reschedule_queue_timeout (queue);
783 if (NULL == queue)
784 {
785 GNUNET_log (
786 GNUNET_ERROR_TYPE_ERROR,
787 _ (
788 "Maximum number of UNIX connections exceeded, dropping incoming message\n"));
789 return;
790 }
791
792 {
793 uint16_t tsize = msize - sizeof(struct UNIXMessage);
794
795 const struct GNUNET_MessageHeader *currhdr;
796 struct GNUNET_MessageHeader al_hdr;
797
798 currhdr = (const struct GNUNET_MessageHeader *) &msg[1];
799 /* ensure aligned access */
800 memcpy (&al_hdr, currhdr, sizeof(al_hdr));
801 if ((tsize < sizeof(struct GNUNET_MessageHeader)) ||
802 (tsize != ntohs (al_hdr.size)))
803 {
804 GNUNET_break_op (0);
805 return;
806 }
807 ret = GNUNET_TRANSPORT_communicator_receive (ch,
808 &msg->sender,
809 currhdr,
810 GNUNET_TIME_UNIT_FOREVER_REL,
811 &receive_complete_cb,
812 NULL);
813 if (GNUNET_SYSERR == ret)
814 {
815 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
816 "Transport not up!\n");
817 return; /* transport not up */
818 }
819 if (GNUNET_NO == ret)
820 {
821 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
822 "Error sending message to transport\n");
823 return;
824 }
825 delivering_messages++;
826 }
827 if (delivering_messages >= max_queue_length)
828 {
829 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
830 "Back pressure %llu\n", delivering_messages);
831
832 /* we should try to apply 'back pressure' */
833 GNUNET_SCHEDULER_cancel (read_task);
834 read_task = NULL;
835 }
836}
837
838
839/**
840 * Function called by the transport service to initialize a
841 * message queue given address information about another peer.
842 * If and when the communication channel is established, the
843 * communicator must call #GNUNET_TRANSPORT_communicator_mq_add()
844 * to notify the service that the channel is now up. It is
845 * the responsibility of the communicator to manage sane
846 * retries and timeouts for any @a peer/@a address combination
847 * provided by the transport service. Timeouts and retries
848 * do not need to be signalled to the transport service.
849 *
850 * @param cls closure
851 * @param peer identity of the other peer
852 * @param address where to send the message, human-readable
853 * communicator-specific format, 0-terminated, UTF-8
854 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the provided address is invalid
855 */
856static int
857mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
858{
859 struct Queue *queue;
860 const char *path;
861 struct sockaddr_un *un;
862 socklen_t un_len;
863
864 (void) cls;
865 if (0 != strncmp (address,
866 COMMUNICATOR_ADDRESS_PREFIX "-",
867 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
868 {
869 GNUNET_break_op (0);
870 return GNUNET_SYSERR;
871 }
872 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
873 un = unix_address_to_sockaddr (path, &un_len);
874 queue = lookup_queue (peer, un, un_len);
875 if (NULL != queue)
876 {
877 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
878 "Address `%s' for %s ignored, queue exists\n",
879 path,
880 GNUNET_i2s (peer));
881 GNUNET_free (un);
882 return GNUNET_OK;
883 }
884 queue = setup_queue (peer, GNUNET_TRANSPORT_CS_OUTBOUND, un, un_len);
885 GNUNET_free (un);
886 if (NULL == queue)
887 {
888 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
889 "Failed to setup queue to %s at `%s'\n",
890 GNUNET_i2s (peer),
891 path);
892 return GNUNET_NO;
893 }
894 return GNUNET_OK;
895}
896
897
898/**
899 * Iterator over all message queues to clean up.
900 *
901 * @param cls NULL
902 * @param target unused
903 * @param value the queue to destroy
904 * @return #GNUNET_OK to continue to iterate
905 */
906static int
907get_queue_delete_it (void *cls,
908 const struct GNUNET_PeerIdentity *target,
909 void *value)
910{
911 struct Queue *queue = value;
912
913 (void) cls;
914 (void) target;
915 queue_destroy (queue);
916 return GNUNET_OK;
917}
918
919
920/**
921 * Shutdown the UNIX communicator.
922 *
923 * @param cls NULL (always)
924 */
925static void
926do_shutdown (void *cls)
927{
928 if (NULL != read_task)
929 {
930 GNUNET_SCHEDULER_cancel (read_task);
931 read_task = NULL;
932 }
933 if (NULL != write_task)
934 {
935 GNUNET_SCHEDULER_cancel (write_task);
936 write_task = NULL;
937 }
938 if (NULL != unix_sock)
939 {
940 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (unix_sock));
941 unix_sock = NULL;
942 }
943 GNUNET_CONTAINER_multipeermap_iterate (queue_map, &get_queue_delete_it, NULL);
944 GNUNET_CONTAINER_multipeermap_destroy (queue_map);
945 if (NULL != ai)
946 {
947 GNUNET_TRANSPORT_communicator_address_remove (ai);
948 ai = NULL;
949 }
950 if (NULL != ch)
951 {
952 GNUNET_TRANSPORT_communicator_disconnect (ch);
953 ch = NULL;
954 }
955 if (NULL != stats)
956 {
957 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
958 stats = NULL;
959 }
960}
961
962
963/**
964 * Function called when the transport service has received an
965 * acknowledgement for this communicator (!) via a different return
966 * path.
967 *
968 * Not applicable for UNIX.
969 *
970 * @param cls closure
971 * @param sender which peer sent the notification
972 * @param msg payload
973 */
974static void
975enc_notify_cb (void *cls,
976 const struct GNUNET_PeerIdentity *sender,
977 const struct GNUNET_MessageHeader *msg)
978{
979 (void) cls;
980 (void) sender;
981 (void) msg;
982 GNUNET_break_op (0);
983}
984
985
986/**
987 * Setup communicator and launch network interactions.
988 *
989 * @param cls NULL (always)
990 * @param args remaining command-line arguments
991 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
992 * @param cfg configuration
993 */
994static void
995run (void *cls,
996 char *const *args,
997 const char *cfgfile,
998 const struct GNUNET_CONFIGURATION_Handle *cfg)
999{
1000 char *unix_socket_path;
1001 struct sockaddr_un *un;
1002 socklen_t un_len;
1003 char *my_addr;
1004 struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
1005
1006 (void) cls;
1007 delivering_messages = 0;
1008
1009 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
1010 if (NULL == my_private_key)
1011 {
1012 GNUNET_log (
1013 GNUNET_ERROR_TYPE_ERROR,
1014 _ (
1015 "UNIX communicator is lacking key configuration settings. Exiting.\n"));
1016 GNUNET_SCHEDULER_shutdown ();
1017 return;
1018 }
1019 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_identity.public_key);
1020
1021 if (GNUNET_OK !=
1022 GNUNET_CONFIGURATION_get_value_filename (cfg,
1023 COMMUNICATOR_CONFIG_SECTION,
1024 "UNIXPATH",
1025 &unix_socket_path))
1026 {
1027 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1028 COMMUNICATOR_CONFIG_SECTION,
1029 "UNIXPATH");
1030 return;
1031 }
1032 if (GNUNET_OK !=
1033 GNUNET_CONFIGURATION_get_value_number (cfg,
1034 COMMUNICATOR_CONFIG_SECTION,
1035 "MAX_QUEUE_LENGTH",
1036 &max_queue_length))
1037 max_queue_length = DEFAULT_MAX_QUEUE_LENGTH;
1038
1039 un = unix_address_to_sockaddr (unix_socket_path, &un_len);
1040 if (NULL == un)
1041 {
1042 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1043 "Failed to setup UNIX domain socket address with path `%s'\n",
1044 unix_socket_path);
1045 GNUNET_free (unix_socket_path);
1046 return;
1047 }
1048 unix_sock = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_DGRAM, 0);
1049 if (NULL == unix_sock)
1050 {
1051 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
1052 GNUNET_free (un);
1053 GNUNET_free (unix_socket_path);
1054 return;
1055 }
1056 if (('\0' != un->sun_path[0]) &&
1057 (GNUNET_OK != GNUNET_DISK_directory_create_for_file (un->sun_path)))
1058 {
1059 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1060 _ ("Cannot create path to `%s'\n"),
1061 un->sun_path);
1062 GNUNET_NETWORK_socket_close (unix_sock);
1063 unix_sock = NULL;
1064 GNUNET_free (un);
1065 GNUNET_free (unix_socket_path);
1066 return;
1067 }
1068 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (unix_sock,
1069 (const struct sockaddr *) un,
1070 un_len))
1071 {
1072 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "bind", un->sun_path);
1073 GNUNET_NETWORK_socket_close (unix_sock);
1074 unix_sock = NULL;
1075 GNUNET_free (un);
1076 GNUNET_free (unix_socket_path);
1077 return;
1078 }
1079 GNUNET_free (un);
1080 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Bound to `%s'\n", unix_socket_path);
1081 stats = GNUNET_STATISTICS_create ("C-UNIX", cfg);
1082 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1083 read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1084 unix_sock,
1085 &select_read_cb,
1086 NULL);
1087 queue_map = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
1088 ch = GNUNET_TRANSPORT_communicator_connect (cfg,
1089 COMMUNICATOR_CONFIG_SECTION,
1090 COMMUNICATOR_ADDRESS_PREFIX,
1091 GNUNET_TRANSPORT_CC_RELIABLE,
1092 &mq_init,
1093 NULL,
1094 &enc_notify_cb,
1095 NULL);
1096 if (NULL == ch)
1097 {
1098 GNUNET_break (0);
1099 GNUNET_SCHEDULER_shutdown ();
1100 GNUNET_free (unix_socket_path);
1101 return;
1102 }
1103 GNUNET_asprintf (&my_addr,
1104 "%s-%s",
1105 COMMUNICATOR_ADDRESS_PREFIX,
1106 unix_socket_path);
1107 GNUNET_free (unix_socket_path);
1108 ai = GNUNET_TRANSPORT_communicator_address_add (ch,
1109 my_addr,
1110 GNUNET_NT_LOOPBACK,
1111 GNUNET_TIME_UNIT_FOREVER_REL);
1112 GNUNET_free (my_addr);
1113}
1114
1115
1116/**
1117 * The main function for the UNIX communicator.
1118 *
1119 * @param argc number of arguments from the command line
1120 * @param argv command line arguments
1121 * @return 0 ok, 1 on error
1122 */
1123int
1124main (int argc, char *const *argv)
1125{
1126 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1127 GNUNET_GETOPT_OPTION_END
1128 };
1129 int ret;
1130
1131 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1132 return 2;
1133
1134 ret = (GNUNET_OK ==
1135 GNUNET_PROGRAM_run (argc,
1136 argv,
1137 "gnunet-communicator-unix",
1138 _ ("GNUnet UNIX domain socket communicator"),
1139 options,
1140 &run,
1141 NULL))
1142 ? 0
1143 : 1;
1144 GNUNET_free_nz ((void *) argv);
1145 return ret;
1146}
1147
1148
1149#if defined(__linux__) && defined(__GLIBC__)
1150#include <malloc.h>
1151
1152/**
1153 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
1154 */
1155void __attribute__ ((constructor))
1156GNUNET_ARM_memory_init ()
1157{
1158 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1159 mallopt (M_TOP_PAD, 1 * 1024);
1160 malloc_trim (0);
1161}
1162
1163
1164#endif
1165
1166/* end of gnunet-communicator-unix.c */
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
deleted file mode 100644
index ec3019161..000000000
--- a/src/transport/gnunet-service-transport.c
+++ /dev/null
@@ -1,11750 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2016, 2018, 2019 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file transport/gnunet-service-transport.c
22 * @brief main for gnunet-service-transport
23 * @author Christian Grothoff
24 *
25 * TODO:
26 * Implement next:
27 * - review retransmission logic, right now there is no smartness there!
28 * => congestion control, etc [PERFORMANCE-BASICS]
29 *
30 * Optimizations-Statistics:
31 * - Track ACK losses based on ACK-counter [ROUTING]
32 * - Need to track total bandwidth per VirtualLink and adjust how frequently
33 * we send FC messages based on bandwidth-delay-product (and relation
34 * to the window size!). See OPTIMIZE-FC-BDP.
35 * - Consider more statistics in #check_connection_quality() [FIXME-CONQ-STATISTICS]
36 * - Adapt available_fc_window_size, using larger values for high-bandwidth
37 * and high-latency links *if* we have the RAM [GOODPUT / utilization / stalls]
38 * - Set last_window_consum_limit promise properly based on
39 * latency and bandwidth of the respective connection [GOODPUT / utilization / stalls]
40 *
41 * Optimizations-DV:
42 * - When forwarding DV learn messages, if a peer is reached that
43 * has a *bidirectional* link to the origin beyond 1st hop,
44 * do NOT forward it to peers _other_ than the origin, as
45 * there is clearly a better path directly from the origin to
46 * whatever else we could reach.
47 * - When we passively learned DV (with unconfirmed freshness), we
48 * right now add the path to our list but with a zero path_valid_until
49 * time and only use it for unconfirmed routes. However, we could consider
50 * triggering an explicit validation mechanism ourselves, specifically routing
51 * a challenge-response message over the path [ROUTING]
52 * = if available, try to confirm unconfirmed DV paths when trying to establish
53 * virtual link for a `struct IncomingRequest`. (i.e. if DVH is
54 * unconfirmed, incoming requests cause us to try to validate a passively
55 * learned path (requires new message type!))
56 *
57 * Optimizations-Fragmentation:
58 * - Fragments send over a reliable channel could do without the
59 * AcknowledgementUUIDP altogether, as they won't be acked! [BANDWIDTH]
60 * (-> have 2nd type of acknowledgment message; low priority, as we
61 * do not have an MTU-limited *reliable* communicator) [FIXME-FRAG-REL-UUID]
62 * - if messages are below MTU, consider adding ACKs and other stuff
63 * to the same transmission to avoid tiny messages (requires planning at
64 * receiver, and additional MST-style demultiplex at receiver!) [PACKET COUNT]
65 *
66 * Optimizations-internals:
67 * - queue_send_msg by API design has to make a copy
68 * of the payload, and route_message on top of that requires a malloc/free.
69 * Change design to approximate "zero" copy better... [CPU]
70 * - could avoid copying body of message into each fragment and keep
71 * fragments as just pointers into the original message and only
72 * fully build fragments just before transmission (optimization, should
73 * reduce CPU and memory use) [CPU, MEMORY]
74 */
75#include "platform.h"
76#include "gnunet_util_lib.h"
77#include "gnunet_statistics_service.h"
78#include "gnunet_transport_monitor_service.h"
79#include "gnunet_peerstore_service.h"
80#include "gnunet_hello_lib.h"
81#include "gnunet_hello_uri_lib.h"
82#include "gnunet_signatures.h"
83#include "transport.h"
84
85/**
86 * Size of ring buffer to cache CORE and forwarded DVBox messages.
87 */
88#define RING_BUFFER_SIZE 16
89
90/**
91 * Maximum number of FC retransmissions for a running retransmission task.
92 */
93#define MAX_FC_RETRANSMIT_COUNT 1000
94
95/**
96 * Maximum number of messages we acknowledge together in one
97 * cumulative ACK. Larger values may save a bit of bandwidth.
98 */
99#define MAX_CUMMULATIVE_ACKS 64
100
101/**
102 * What is the 1:n chance that we send a Flow control response when
103 * receiving a flow control message that did not change anything for
104 * us? Basically, this is used in the case where both peers are stuck
105 * on flow control (no window changes), but one might continue sending
106 * flow control messages to the other peer as the first FC message
107 * when things stalled got lost, and then subsequently the other peer
108 * does *usually* not respond as nothing changed. So to ensure that
109 * eventually the FC messages stop, we do send with 1/8th probability
110 * an FC message even if nothing changed. That prevents one peer
111 * being stuck in sending (useless) FC messages "forever".
112 */
113#define FC_NO_CHANGE_REPLY_PROBABILITY 8
114
115/**
116 * What is the size we assume for a read operation in the
117 * absence of an MTU for the purpose of flow control?
118 */
119#define IN_PACKET_SIZE_WITHOUT_MTU 128
120
121/**
122 * Number of slots we keep of historic data for computation of
123 * goodput / message loss ratio.
124 */
125#define GOODPUT_AGING_SLOTS 4
126
127/**
128 * How big is the flow control window size by default;
129 * limits per-neighbour RAM utilization.
130 */
131#define DEFAULT_WINDOW_SIZE (128 * 1024)
132
133/**
134 * For how many incoming connections do we try to create a
135 * virtual link for (at the same time!). This does NOT
136 * limit the number of incoming connections, just the number
137 * for which we are actively trying to find working addresses
138 * in the absence (!) of our own applications wanting the
139 * link to go up.
140 */
141#define MAX_INCOMING_REQUEST 16
142
143/**
144 * Maximum number of peers we select for forwarding DVInit
145 * messages at the same time (excluding initiator).
146 */
147#define MAX_DV_DISCOVERY_SELECTION 16
148
149/**
150 * Window size. How many messages to the same target do we pass
151 * to CORE without a RECV_OK in between? Small values limit
152 * thoughput, large values will increase latency.
153 *
154 * FIXME-OPTIMIZE: find out what good values are experimentally,
155 * maybe set adaptively (i.e. to observed available bandwidth).
156 */
157#define RECV_WINDOW_SIZE 4
158
159/**
160 * Minimum number of hops we should forward DV learn messages
161 * even if they are NOT useful for us in hope of looping
162 * back to the initiator?
163 *
164 * FIXME: allow initiator some control here instead?
165 */
166#define MIN_DV_PATH_LENGTH_FOR_INITIATOR 3
167
168/**
169 * Maximum DV distance allowed ever.
170 */
171#define MAX_DV_HOPS_ALLOWED 16
172
173/**
174 * Maximum number of DV learning activities we may
175 * have pending at the same time.
176 */
177#define MAX_DV_LEARN_PENDING 64
178
179/**
180 * Maximum number of DV paths we keep simultaneously to the same target.
181 */
182#define MAX_DV_PATHS_TO_TARGET 3
183
184/**
185 * If a queue delays the next message by more than this number
186 * of seconds we log a warning. Note: this is for testing,
187 * the value chosen here might be too aggressively low!
188 */
189#define DELAY_WARN_THRESHOLD \
190 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
191
192/**
193 * If a DVBox could not be forwarded after this number of
194 * seconds we drop it.
195 */
196#define DV_FORWARD_TIMEOUT \
197 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
198
199/**
200 * Default value for how long we wait for reliability ack.
201 */
202#define DEFAULT_ACK_WAIT_DURATION \
203 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
204
205/**
206 * We only consider queues as "quality" connections when
207 * suppressing the generation of DV initiation messages if
208 * the latency of the queue is below this threshold.
209 */
210#define DV_QUALITY_RTT_THRESHOLD \
211 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
212
213/**
214 * How long do we consider a DV path valid if we see no
215 * further updates on it? Note: the value chosen here might be too low!
216 */
217#define DV_PATH_VALIDITY_TIMEOUT \
218 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
219
220/**
221 * How long do we cache backchannel (struct Backtalker) information
222 * after a backchannel goes inactive?
223 */
224#define BACKCHANNEL_INACTIVITY_TIMEOUT \
225 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
226
227/**
228 * How long before paths expire would we like to (re)discover DV paths? Should
229 * be below #DV_PATH_VALIDITY_TIMEOUT.
230 */
231#define DV_PATH_DISCOVERY_FREQUENCY \
232 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
233
234/**
235 * How long are ephemeral keys valid?
236 */
237#define EPHEMERAL_VALIDITY \
238 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
239
240/**
241 * How long do we keep partially reassembled messages around before giving up?
242 */
243#define REASSEMBLY_EXPIRATION \
244 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
245
246/**
247 * What is the fastest rate at which we send challenges *if* we keep learning
248 * an address (gossip, DHT, etc.)?
249 */
250#define FAST_VALIDATION_CHALLENGE_FREQ \
251 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
252
253/**
254 * What is the slowest rate at which we send challenges?
255 */
256#define MAX_VALIDATION_CHALLENGE_FREQ \
257 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, 1)
258
259/**
260 * How long until we forget about historic accumulators and thus
261 * reset the ACK counter? Should exceed the maximum time an
262 * active connection experiences without an ACK.
263 */
264#define ACK_CUMMULATOR_TIMEOUT \
265 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
266
267/**
268 * What is the non-randomized base frequency at which we
269 * would initiate DV learn messages?
270 */
271#define DV_LEARN_BASE_FREQUENCY GNUNET_TIME_UNIT_MINUTES
272
273/**
274 * How many good connections (confirmed, bi-directional, not DV)
275 * do we need to have to suppress initiating DV learn messages?
276 */
277#define DV_LEARN_QUALITY_THRESHOLD 100
278
279/**
280 * When do we forget an invalid address for sure?
281 */
282#define MAX_ADDRESS_VALID_UNTIL \
283 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1)
284
285/**
286 * How long do we consider an address valid if we just checked?
287 */
288#define ADDRESS_VALIDATION_LIFETIME \
289 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
290
291/**
292 * What is the maximum frequency at which we do address validation?
293 * A random value between 0 and this value is added when scheduling
294 * the #validation_task (both to ensure we do not validate too often,
295 * and to randomize a bit).
296 */
297#define MIN_DELAY_ADDRESS_VALIDATION GNUNET_TIME_UNIT_MILLISECONDS
298
299/**
300 * How many network RTTs before an address validation expires should we begin
301 * trying to revalidate? (Note that the RTT used here is the one that we
302 * experienced during the last validation, not necessarily the latest RTT
303 * observed).
304 */
305#define VALIDATION_RTT_BUFFER_FACTOR 3
306
307/**
308 * How many messages can we have pending for a given communicator
309 * process before we start to throttle that communicator?
310 *
311 * Used if a communicator might be CPU-bound and cannot handle the traffic.
312 */
313#define COMMUNICATOR_TOTAL_QUEUE_LIMIT 512
314
315/**
316 * How many messages can we have pending for a given queue (queue to
317 * a particular peer via a communicator) process before we start to
318 * throttle that queue?
319 */
320#define QUEUE_LENGTH_LIMIT 32
321
322
323GNUNET_NETWORK_STRUCT_BEGIN
324
325/**
326 * Unique identifier we attach to a message.
327 */
328struct MessageUUIDP
329{
330 /**
331 * Unique value, generated by incrementing the
332 * `message_uuid_ctr` of `struct Neighbour`.
333 */
334 uint64_t uuid GNUNET_PACKED;
335};
336
337
338/**
339 * Unique identifier to map an acknowledgement to a transmission.
340 */
341struct AcknowledgementUUIDP
342{
343 /**
344 * The UUID value.
345 */
346 struct GNUNET_Uuid value;
347};
348
349/**
350 * Outer layer of an encapsulated backchannel message.
351 */
352struct TransportBackchannelEncapsulationMessage
353{
354 /**
355 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION.
356 */
357 struct GNUNET_MessageHeader header;
358
359 /* Followed by *another* message header which is the message to
360 the communicator */
361
362 /* Followed by a 0-terminated name of the communicator */
363};
364
365
366/**
367 * Body by which a peer confirms that it is using an ephemeral key.
368 */
369struct EphemeralConfirmationPS
370{
371 /**
372 * Purpose is #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
373 */
374 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
375
376 /**
377 * How long is this signature over the ephemeral key valid?
378 *
379 * Note that the receiver MUST IGNORE the absolute time, and only interpret
380 * the value as a mononic time and reject "older" values than the last one
381 * observed. This is necessary as we do not want to require synchronized
382 * clocks and may not have a bidirectional communication channel.
383 *
384 * Even with this, there is no real guarantee against replay achieved here,
385 * unless the latest timestamp is persisted. While persistence should be
386 * provided via PEERSTORE, we do not consider the mechanism reliable! Thus,
387 * communicators must protect against replay attacks when using backchannel
388 * communication!
389 */
390 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time;
391
392 /**
393 * Target's peer identity.
394 */
395 struct GNUNET_PeerIdentity target;
396
397 /**
398 * Ephemeral key setup by the sender for @e target, used
399 * to encrypt the payload.
400 */
401 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
402};
403
404
405/**
406 * Plaintext of the variable-size payload that is encrypted
407 * within a `struct TransportBackchannelEncapsulationMessage`
408 */
409struct TransportDVBoxPayloadP
410{
411 /**
412 * Sender's peer identity.
413 */
414 struct GNUNET_PeerIdentity sender;
415
416 /**
417 * Signature of the sender over an
418 * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
419 */
420 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
421
422 /**
423 * Current monotonic time of the sending transport service. Used to
424 * detect replayed messages. Note that the receiver should remember
425 * a list of the recently seen timestamps and only reject messages
426 * if the timestamp is in the list, or the list is "full" and the
427 * timestamp is smaller than the lowest in the list.
428 *
429 * Like the @e ephemeral_validity, the list of timestamps per peer should be
430 * persisted to guard against replays after restarts.
431 */
432 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
433
434 /* Followed by a `struct GNUNET_MessageHeader` with a message
435 for the target peer */
436};
437
438
439/**
440 * Outer layer of an encapsulated unfragmented application message sent
441 * over an unreliable channel.
442 */
443struct TransportReliabilityBoxMessage
444{
445 /**
446 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX
447 */
448 struct GNUNET_MessageHeader header;
449
450 /**
451 * Number of messages still to be sent before a commulative
452 * ACK is requested. Zero if an ACK is requested immediately.
453 * In NBO. Note that the receiver may send the ACK faster
454 * if it believes that is reasonable.
455 */
456 uint32_t ack_countdown GNUNET_PACKED;
457
458 /**
459 * Unique ID of the message used for signalling receipt of
460 * messages sent over possibly unreliable channels. Should
461 * be a random.
462 */
463 struct AcknowledgementUUIDP ack_uuid;
464};
465
466
467/**
468 * Acknowledgement payload.
469 */
470struct TransportCummulativeAckPayloadP
471{
472 /**
473 * How long was the ACK delayed for generating cumulative ACKs?
474 * Used to calculate the correct network RTT by taking the receipt
475 * time of the ack minus the transmission time of the sender minus
476 * this value.
477 */
478 struct GNUNET_TIME_RelativeNBO ack_delay;
479
480 /**
481 * UUID of a message being acknowledged.
482 */
483 struct AcknowledgementUUIDP ack_uuid;
484};
485
486
487/**
488 * Confirmation that the receiver got a
489 * #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX. Note that the
490 * confirmation may be transmitted over a completely different queue,
491 * so ACKs are identified by a combination of PID of sender and
492 * message UUID, without the queue playing any role!
493 */
494struct TransportReliabilityAckMessage
495{
496 /**
497 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK
498 */
499 struct GNUNET_MessageHeader header;
500
501 /**
502 * Counter of ACKs transmitted by the sender to us. Incremented
503 * by one for each ACK, used to detect how many ACKs were lost.
504 */
505 uint32_t ack_counter GNUNET_PACKED;
506
507 /* followed by any number of `struct TransportCummulativeAckPayloadP`
508 messages providing ACKs */
509};
510
511
512/**
513 * Outer layer of an encapsulated fragmented application message.
514 */
515struct TransportFragmentBoxMessage
516{
517 /**
518 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT
519 */
520 struct GNUNET_MessageHeader header;
521
522 /**
523 * Offset of this fragment in the overall message.
524 */
525 uint16_t frag_off GNUNET_PACKED;
526
527 /**
528 * Total size of the message that is being fragmented.
529 */
530 uint16_t msg_size GNUNET_PACKED;
531
532 /**
533 * Unique ID of this fragment (and fragment transmission!). Will
534 * change even if a fragment is retransmitted to make each
535 * transmission attempt unique! If a client receives a duplicate
536 * fragment (same @e frag_off for same @a msg_uuid, it must send
537 * #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK immediately.
538 */
539 struct AcknowledgementUUIDP ack_uuid;
540
541 /**
542 * Original message ID for of the message that all the fragments
543 * belong to. Must be the same for all fragments.
544 */
545 struct MessageUUIDP msg_uuid;
546};
547
548
549/**
550 * Content signed by the initator during DV learning.
551 *
552 * The signature is required to prevent DDoS attacks. A peer sending out this
553 * message is potentially generating a lot of traffic that will go back to the
554 * initator, as peers receiving this message will try to let the initiator
555 * know that they got the message.
556 *
557 * Without this signature, an attacker could abuse this mechanism for traffic
558 * amplification, sending a lot of traffic to a peer by putting out this type
559 * of message with the victim's peer identity.
560 *
561 * Even with just a signature, traffic amplification would be possible via
562 * replay attacks. The @e monotonic_time limits such replay attacks, as every
563 * potential amplificator will check the @e monotonic_time and only respond
564 * (at most) once per message.
565 */
566struct DvInitPS
567{
568 /**
569 * Purpose is #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR
570 */
571 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
572
573 /**
574 * Time at the initiator when generating the signature.
575 *
576 * Note that the receiver MUST IGNORE the absolute time, and only interpret
577 * the value as a mononic time and reject "older" values than the last one
578 * observed. This is necessary as we do not want to require synchronized
579 * clocks and may not have a bidirectional communication channel.
580 *
581 * Even with this, there is no real guarantee against replay achieved here,
582 * unless the latest timestamp is persisted. Persistence should be
583 * provided via PEERSTORE if possible.
584 */
585 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
586
587 /**
588 * Challenge value used by the initiator to re-identify the path.
589 */
590 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
591};
592
593
594/**
595 * Content signed by each peer during DV learning.
596 *
597 * This assues the initiator of the DV learning operation that the hop from @e
598 * pred via the signing peer to @e succ actually exists. This makes it
599 * impossible for an adversary to supply the network with bogus routes.
600 *
601 * The @e challenge is included to provide replay protection for the
602 * initiator. This way, the initiator knows that the hop existed after the
603 * original @e challenge was first transmitted, providing a freshness metric.
604 *
605 * Peers other than the initiator that passively learn paths by observing
606 * these messages do NOT benefit from this. Here, an adversary may indeed
607 * replay old messages. Thus, passively learned paths should always be
608 * immediately marked as "potentially stale".
609 */
610struct DvHopPS
611{
612 /**
613 * Purpose is #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP
614 */
615 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
616
617 /**
618 * Identity of the previous peer on the path.
619 */
620 struct GNUNET_PeerIdentity pred;
621
622 /**
623 * Identity of the next peer on the path.
624 */
625 struct GNUNET_PeerIdentity succ;
626
627 /**
628 * Challenge value used by the initiator to re-identify the path.
629 */
630 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
631};
632
633
634/**
635 * An entry describing a peer on a path in a
636 * `struct TransportDVLearnMessage` message.
637 */
638struct DVPathEntryP
639{
640 /**
641 * Identity of a peer on the path.
642 */
643 struct GNUNET_PeerIdentity hop;
644
645 /**
646 * Signature of this hop over the path, of purpose
647 * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP
648 */
649 struct GNUNET_CRYPTO_EddsaSignature hop_sig;
650};
651
652
653/**
654 * Internal message used by transport for distance vector learning.
655 * If @e num_hops does not exceed the threshold, peers should append
656 * themselves to the peer list and flood the message (possibly only
657 * to a subset of their neighbours to limit discoverability of the
658 * network topology). To the extend that the @e bidirectional bits
659 * are set, peers may learn the inverse paths even if they did not
660 * initiate.
661 *
662 * Unless received on a bidirectional queue and @e num_hops just
663 * zero, peers that can forward to the initator should always try to
664 * forward to the initiator.
665 */
666struct TransportDVLearnMessage
667{
668 /**
669 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN
670 */
671 struct GNUNET_MessageHeader header;
672
673 /**
674 * Number of hops this messages has travelled, in NBO. Zero if
675 * sent by initiator.
676 */
677 uint16_t num_hops GNUNET_PACKED;
678
679 /**
680 * Bitmask of the last 16 hops indicating whether they are confirmed
681 * available (without DV) in both directions or not, in NBO. Used
682 * to possibly instantly learn a path in both directions. Each peer
683 * should shift this value by one to the left, and then set the
684 * lowest bit IF the current sender can be reached from it (without
685 * DV routing).
686 */
687 uint16_t bidirectional GNUNET_PACKED;
688
689 /**
690 * Peers receiving this message and delaying forwarding to other
691 * peers for any reason should increment this value by the non-network
692 * delay created by the peer.
693 */
694 struct GNUNET_TIME_RelativeNBO non_network_delay;
695
696 /**
697 * Time at the initiator when generating the signature.
698 *
699 * Note that the receiver MUST IGNORE the absolute time, and only interpret
700 * the value as a mononic time and reject "older" values than the last one
701 * observed. This is necessary as we do not want to require synchronized
702 * clocks and may not have a bidirectional communication channel.
703 *
704 * Even with this, there is no real guarantee against replay achieved here,
705 * unless the latest timestamp is persisted. Persistence should be
706 * provided via PEERSTORE if possible.
707 */
708 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
709
710 /**
711 * Signature of this hop over the path, of purpose
712 * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR
713 */
714 struct GNUNET_CRYPTO_EddsaSignature init_sig;
715
716 /**
717 * Identity of the peer that started this learning activity.
718 */
719 struct GNUNET_PeerIdentity initiator;
720
721 /**
722 * Challenge value used by the initiator to re-identify the path.
723 */
724 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
725
726 /* Followed by @e num_hops `struct DVPathEntryP` values,
727 excluding the initiator of the DV trace; the last entry is the
728 current sender; the current peer must not be included. */
729};
730
731
732/**
733 * Outer layer of an encapsulated message send over multiple hops.
734 * The path given only includes the identities of the subsequent
735 * peers, i.e. it will be empty if we are the receiver. Each
736 * forwarding peer should scan the list from the end, and if it can,
737 * forward to the respective peer. The list should then be shortened
738 * by all the entries up to and including that peer. Each hop should
739 * also increment @e total_hops to allow the receiver to get a precise
740 * estimate on the number of hops the message travelled. Senders must
741 * provide a learned path that thus should work, but intermediaries
742 * know of a shortcut, they are allowed to send the message via that
743 * shortcut.
744 *
745 * If a peer finds itself still on the list, it must drop the message.
746 *
747 * The payload of the box can only be decrypted and verified by the
748 * ultimate receiver. Intermediaries do not learn the sender's
749 * identity and the path the message has taken. However, the first
750 * hop does learn the sender as @e total_hops would be zero and thus
751 * the predecessor must be the origin (so this is not really useful
752 * for anonymization).
753 */
754struct TransportDVBoxMessage
755{
756 /**
757 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX
758 */
759 struct GNUNET_MessageHeader header;
760
761 /**
762 * Flag if the payload is a control message. In NBO.
763 */
764 unsigned int without_fc;
765
766 /**
767 * Number of total hops this messages travelled. In NBO.
768 * @e origin sets this to zero, to be incremented at
769 * each hop. Peers should limit the @e total_hops value
770 * they accept from other peers.
771 */
772 uint16_t total_hops GNUNET_PACKED;
773
774 /**
775 * Number of hops this messages includes. In NBO. Reduced by one
776 * or more at each hop. Peers should limit the @e num_hops value
777 * they accept from other peers.
778 */
779 uint16_t num_hops GNUNET_PACKED;
780
781 /**
782 * Ephemeral key setup by the sender for target, used to encrypt the
783 * payload. Intermediaries must not change this value.
784 */
785 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
786
787 /**
788 * We use an IV here as the @e ephemeral_key is re-used for
789 * #EPHEMERAL_VALIDITY time to avoid re-signing it all the time.
790 * Intermediaries must not change this value.
791 */
792 struct GNUNET_ShortHashCode iv;
793
794 /**
795 * HMAC over the ciphertext of the encrypted, variable-size body
796 * that follows. Verified via DH of target and @e ephemeral_key.
797 * Intermediaries must not change this value.
798 */
799 struct GNUNET_HashCode hmac;
800
801 /**
802 * Size this msg had initially. This is needed to calculate the hmac at the target.
803 * The header size can not be used for that, because the box size is getting smaller at each hop.
804 *
805 */
806 uint16_t orig_size GNUNET_PACKED;
807
808 /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
809 excluding the @e origin and the current peer, the last must be
810 the ultimate target; if @e num_hops is zero, the receiver of this
811 message is the ultimate target. */
812
813 /* Followed by encrypted, variable-size payload, which
814 must begin with a `struct TransportDVBoxPayloadP` */
815
816 /* Followed by the actual message, which itself must not be a
817 a DV_LEARN or DV_BOX message! */
818};
819
820
821/**
822 * Message send to another peer to validate that it can indeed
823 * receive messages at a particular address.
824 */
825struct TransportValidationChallengeMessage
826{
827 /**
828 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE
829 */
830 struct GNUNET_MessageHeader header;
831
832 /**
833 * Always zero.
834 */
835 uint32_t reserved GNUNET_PACKED;
836
837 /**
838 * Challenge to be signed by the receiving peer.
839 */
840 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
841
842 /**
843 * Timestamp of the sender, to be copied into the reply to allow
844 * sender to calculate RTT. Must be monotonically increasing!
845 */
846 struct GNUNET_TIME_AbsoluteNBO sender_time;
847};
848
849
850/**
851 * Message signed by a peer to confirm that it can indeed
852 * receive messages at a particular address.
853 */
854struct TransportValidationPS
855{
856 /**
857 * Purpose is #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE
858 */
859 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
860
861 /**
862 * How long does the sender believe the address on
863 * which the challenge was received to remain valid?
864 */
865 struct GNUNET_TIME_RelativeNBO validity_duration;
866
867 /**
868 * Challenge signed by the receiving peer.
869 */
870 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
871};
872
873
874/**
875 * Message send to a peer to respond to a
876 * #GNUNET_MESSAGE_TYPE_ADDRESS_VALIDATION_CHALLENGE
877 */
878struct TransportValidationResponseMessage
879{
880 /**
881 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE
882 */
883 struct GNUNET_MessageHeader header;
884
885 /**
886 * Always zero.
887 */
888 uint32_t reserved GNUNET_PACKED;
889
890 /**
891 * The peer's signature matching the
892 * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE purpose.
893 */
894 struct GNUNET_CRYPTO_EddsaSignature signature;
895
896 /**
897 * The challenge that was signed by the receiving peer.
898 */
899 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
900
901 /**
902 * Original timestamp of the sender (was @code{sender_time}),
903 * copied into the reply to allow sender to calculate RTT.
904 */
905 struct GNUNET_TIME_AbsoluteNBO origin_time;
906
907 /**
908 * How long does the sender believe this address to remain
909 * valid?
910 */
911 struct GNUNET_TIME_RelativeNBO validity_duration;
912};
913
914
915/**
916 * Message for Transport-to-Transport Flow control. Specifies the size
917 * of the flow control window, including how much we believe to have
918 * consumed (at transmission time), how much we believe to be allowed
919 * (at transmission time), and how much the other peer is allowed to
920 * send to us, and how much data we already received from the other
921 * peer.
922 */
923struct TransportFlowControlMessage
924{
925 /**
926 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL
927 */
928 struct GNUNET_MessageHeader header;
929
930 /**
931 * Sequence number of the flow control message. Incremented by one
932 * for each message. Starts at zero when a virtual link goes up.
933 * Used to detect one-sided connection drops. On wrap-around, the
934 * flow control counters will be reset as if the connection had
935 * dropped.
936 */
937 uint32_t seq GNUNET_PACKED;
938
939 /**
940 * Flow control window size in bytes, in NBO.
941 * The receiver can send this many bytes at most.
942 */
943 uint64_t inbound_window_size GNUNET_PACKED;
944
945 /**
946 * How many bytes has the sender sent that count for flow control at
947 * this time. Used to allow the receiver to estimate the packet
948 * loss rate.
949 */
950 uint64_t outbound_sent GNUNET_PACKED;
951
952 /**
953 * Latest flow control window size we learned from the other peer,
954 * in bytes, in NBO. We are limited to sending at most this many
955 * bytes to the other peer. May help the other peer detect when
956 * flow control messages were lost and should thus be retransmitted.
957 * In particular, if the delta to @e outbound_sent is too small,
958 * this signals that we are stalled.
959 */
960 uint64_t outbound_window_size GNUNET_PACKED;
961
962 /**
963 * Timestamp of the sender. Must be monotonically increasing!
964 * Used to enable receiver to ignore out-of-order packets in
965 * combination with the @e seq. Note that @e seq will go down
966 * (back to zero) whenever either side believes the connection
967 * was dropped, allowing the peers to detect that they need to
968 * reset the counters for the number of bytes sent!
969 */
970 struct GNUNET_TIME_AbsoluteNBO sender_time;
971};
972
973
974GNUNET_NETWORK_STRUCT_END
975
976
977/**
978 * What type of client is the `struct TransportClient` about?
979 */
980enum ClientType
981{
982 /**
983 * We do not know yet (client is fresh).
984 */
985 CT_NONE = 0,
986
987 /**
988 * Is the CORE service, we need to forward traffic to it.
989 */
990 CT_CORE = 1,
991
992 /**
993 * It is a monitor, forward monitor data.
994 */
995 CT_MONITOR = 2,
996
997 /**
998 * It is a communicator, use for communication.
999 */
1000 CT_COMMUNICATOR = 3,
1001
1002 /**
1003 * "Application" telling us where to connect (i.e. TOPOLOGY, DHT or CADET).
1004 */
1005 CT_APPLICATION = 4
1006};
1007
1008
1009/**
1010 * Which transmission options are allowable for transmission?
1011 * Interpreted bit-wise!
1012 */
1013enum RouteMessageOptions
1014{
1015 /**
1016 * Only confirmed, non-DV direct neighbours.
1017 */
1018 RMO_NONE = 0,
1019
1020 /**
1021 * We are allowed to use DV routing for this @a hdr
1022 */
1023 RMO_DV_ALLOWED = 1,
1024
1025 /**
1026 * We are allowed to use unconfirmed queues or DV routes for this message
1027 */
1028 RMO_UNCONFIRMED_ALLOWED = 2,
1029
1030 /**
1031 * Reliable and unreliable, DV and non-DV are all acceptable.
1032 */
1033 RMO_ANYTHING_GOES = (RMO_DV_ALLOWED | RMO_UNCONFIRMED_ALLOWED),
1034
1035 /**
1036 * If we have multiple choices, it is OK to send this message
1037 * over multiple channels at the same time to improve loss tolerance.
1038 * (We do at most 2 transmissions.)
1039 */
1040 RMO_REDUNDANT = 4
1041};
1042
1043
1044/**
1045 * When did we launch this DV learning activity?
1046 */
1047struct LearnLaunchEntry
1048{
1049 /**
1050 * Kept (also) in a DLL sorted by launch time.
1051 */
1052 struct LearnLaunchEntry *prev;
1053
1054 /**
1055 * Kept (also) in a DLL sorted by launch time.
1056 */
1057 struct LearnLaunchEntry *next;
1058
1059 /**
1060 * Challenge that uniquely identifies this activity.
1061 */
1062 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
1063
1064 /**
1065 * When did we transmit the DV learn message (used to calculate RTT) and
1066 * determine freshness of paths learned via this operation.
1067 */
1068 struct GNUNET_TIME_Absolute launch_time;
1069};
1070
1071
1072/**
1073 * Information we keep per #GOODPUT_AGING_SLOTS about historic
1074 * (or current) transmission performance.
1075 */
1076struct TransmissionHistoryEntry
1077{
1078 /**
1079 * Number of bytes actually sent in the interval.
1080 */
1081 uint64_t bytes_sent;
1082
1083 /**
1084 * Number of bytes received and acknowledged by the other peer in
1085 * the interval.
1086 */
1087 uint64_t bytes_received;
1088};
1089
1090
1091/**
1092 * Performance data for a transmission possibility.
1093 */
1094struct PerformanceData
1095{
1096 /**
1097 * Weighted average for the RTT.
1098 */
1099 struct GNUNET_TIME_Relative aged_rtt;
1100
1101 /**
1102 * Historic performance data, using a ring buffer of#GOODPUT_AGING_SLOTS
1103 * entries.
1104 */
1105 struct TransmissionHistoryEntry the[GOODPUT_AGING_SLOTS];
1106
1107 /**
1108 * What was the last age when we wrote to @e the? Used to clear
1109 * old entries when the age advances.
1110 */
1111 unsigned int last_age;
1112};
1113
1114
1115/**
1116 * Client connected to the transport service.
1117 */
1118struct TransportClient;
1119
1120/**
1121 * A neighbour that at least one communicator is connected to.
1122 */
1123struct Neighbour;
1124
1125/**
1126 * Entry in our #dv_routes table, representing a (set of) distance
1127 * vector routes to a particular peer.
1128 */
1129struct DistanceVector;
1130
1131/**
1132 * A queue is a message queue provided by a communicator
1133 * via which we can reach a particular neighbour.
1134 */
1135struct Queue;
1136
1137/**
1138 * Message awaiting transmission. See detailed comments below.
1139 */
1140struct PendingMessage;
1141
1142/**
1143 * One possible hop towards a DV target.
1144 */
1145struct DistanceVectorHop;
1146
1147/**
1148 * A virtual link is another reachable peer that is known to CORE. It
1149 * can be either a `struct Neighbour` with at least one confirmed
1150 * `struct Queue`, or a `struct DistanceVector` with at least one
1151 * confirmed `struct DistanceVectorHop`. With a virtual link we track
1152 * data that is per neighbour that is not specific to how the
1153 * connectivity is established.
1154 */
1155struct VirtualLink;
1156
1157
1158/**
1159 * Context from #handle_incoming_msg(). Closure for many
1160 * message handlers below.
1161 */
1162struct CommunicatorMessageContext
1163{
1164 /**
1165 * Kept in a DLL of `struct VirtualLink` if waiting for CORE
1166 * flow control to unchoke.
1167 */
1168 struct CommunicatorMessageContext *next;
1169
1170 /**
1171 * Kept in a DLL of `struct VirtualLink` if waiting for CORE
1172 * flow control to unchoke.
1173 */
1174 struct CommunicatorMessageContext *prev;
1175
1176 /**
1177 * Which communicator provided us with the message.
1178 */
1179 struct TransportClient *tc;
1180
1181 /**
1182 * Additional information for flow control and about the sender.
1183 */
1184 struct GNUNET_TRANSPORT_IncomingMessage im;
1185
1186 /**
1187 * The message to demultiplex.
1188 */
1189 const struct GNUNET_MessageHeader *mh;
1190
1191 /**
1192 * Number of hops the message has travelled (if DV-routed).
1193 * FIXME: make use of this in ACK handling!
1194 */
1195 uint16_t total_hops;
1196};
1197
1198
1199/**
1200 * Entry for the ring buffer caching messages send to core, when virtual link is avaliable.
1201 **/
1202struct RingBufferEntry
1203{
1204 /**
1205 * Communicator context for this ring buffer entry.
1206 **/
1207 struct CommunicatorMessageContext *cmc;
1208
1209 /**
1210 * The message in this entry.
1211 **/
1212 struct GNUNET_MessageHeader *mh;
1213};
1214
1215
1216/**
1217 * Closure for #core_env_sent_cb.
1218 */
1219struct CoreSentContext
1220{
1221 /**
1222 * Kept in a DLL to clear @e vl in case @e vl is lost.
1223 */
1224 struct CoreSentContext *next;
1225
1226 /**
1227 * Kept in a DLL to clear @e vl in case @e vl is lost.
1228 */
1229 struct CoreSentContext *prev;
1230
1231 /**
1232 * Virtual link this is about.
1233 */
1234 struct VirtualLink *vl;
1235
1236 /**
1237 * How big was the message.
1238 */
1239 uint16_t size;
1240
1241 /**
1242 * By how much should we increment @e vl's
1243 * incoming_fc_window_size_used once we are done sending to CORE?
1244 * Use to ensure we do not increment twice if there is more than one
1245 * CORE client.
1246 */
1247 uint16_t isize;
1248};
1249
1250
1251/**
1252 * Information we keep for a message that we are reassembling.
1253 */
1254struct ReassemblyContext
1255{
1256 /**
1257 * Original message ID for of the message that all the fragments
1258 * belong to.
1259 */
1260 struct MessageUUIDP msg_uuid;
1261
1262 /**
1263 * Which neighbour is this context for?
1264 */
1265 struct VirtualLink *virtual_link;
1266
1267 /**
1268 * Entry in the reassembly heap (sorted by expiration).
1269 */
1270 struct GNUNET_CONTAINER_HeapNode *hn;
1271
1272 /**
1273 * Bitfield with @e msg_size bits representing the positions
1274 * where we have received fragments. When we receive a fragment,
1275 * we check the bits in @e bitfield before incrementing @e msg_missing.
1276 *
1277 * Allocated after the reassembled message.
1278 */
1279 uint8_t *bitfield;
1280
1281 /**
1282 * At what time will we give up reassembly of this message?
1283 */
1284 struct GNUNET_TIME_Absolute reassembly_timeout;
1285
1286 /**
1287 * Time we received the last fragment. @e avg_ack_delay must be
1288 * incremented by now - @e last_frag multiplied by @e num_acks.
1289 */
1290 struct GNUNET_TIME_Absolute last_frag;
1291
1292 /**
1293 * How big is the message we are reassembling in total?
1294 */
1295 uint16_t msg_size;
1296
1297 /**
1298 * How many bytes of the message are still missing? Defragmentation
1299 * is complete when @e msg_missing == 0.
1300 */
1301 uint16_t msg_missing;
1302
1303 /* Followed by @e msg_size bytes of the (partially) defragmented original
1304 * message */
1305
1306 /* Followed by @e bitfield data */
1307};
1308
1309
1310/**
1311 * A virtual link is another reachable peer that is known to CORE. It
1312 * can be either a `struct Neighbour` with at least one confirmed
1313 * `struct Queue`, or a `struct DistanceVector` with at least one
1314 * confirmed `struct DistanceVectorHop`. With a virtual link we track
1315 * data that is per neighbour that is not specific to how the
1316 * connectivity is established.
1317 */
1318struct VirtualLink
1319{
1320 /**
1321 * Identity of the peer at the other end of the link.
1322 */
1323 struct GNUNET_PeerIdentity target;
1324
1325 /**
1326 * Map with `struct ReassemblyContext` structs for fragments under
1327 * reassembly. May be NULL if we currently have no fragments from
1328 * this @e pid (lazy initialization).
1329 */
1330 struct GNUNET_CONTAINER_MultiHashMap32 *reassembly_map;
1331
1332 /**
1333 * Heap with `struct ReassemblyContext` structs for fragments under
1334 * reassembly. May be NULL if we currently have no fragments from
1335 * this @e pid (lazy initialization).
1336 */
1337 struct GNUNET_CONTAINER_Heap *reassembly_heap;
1338
1339 /**
1340 * Task to free old entries from the @e reassembly_heap and @e reassembly_map.
1341 */
1342 struct GNUNET_SCHEDULER_Task *reassembly_timeout_task;
1343
1344 /**
1345 * Communicators blocked for receiving on @e target as we are waiting
1346 * on the @e core_recv_window to increase.
1347 */
1348 struct CommunicatorMessageContext *cmc_head;
1349
1350 /**
1351 * Communicators blocked for receiving on @e target as we are waiting
1352 * on the @e core_recv_window to increase.
1353 */
1354 struct CommunicatorMessageContext *cmc_tail;
1355
1356 /**
1357 * Head of list of messages pending for this VL.
1358 */
1359 struct PendingMessage *pending_msg_head;
1360
1361 /**
1362 * Tail of list of messages pending for this VL.
1363 */
1364 struct PendingMessage *pending_msg_tail;
1365
1366 /**
1367 * Kept in a DLL to clear @e vl in case @e vl is lost.
1368 */
1369 struct CoreSentContext *csc_tail;
1370
1371 /**
1372 * Kept in a DLL to clear @e vl in case @e vl is lost.
1373 */
1374 struct CoreSentContext *csc_head;
1375
1376 /**
1377 * Task scheduled to possibly notfiy core that this peer is no
1378 * longer counting as confirmed. Runs the #core_visibility_check(),
1379 * which checks that some DV-path or a queue exists that is still
1380 * considered confirmed.
1381 */
1382 struct GNUNET_SCHEDULER_Task *visibility_task;
1383
1384 /**
1385 * Task scheduled to periodically retransmit FC messages (in
1386 * case one got lost).
1387 */
1388 struct GNUNET_SCHEDULER_Task *fc_retransmit_task;
1389
1390 /**
1391 * Number of FC retransmissions for this running task.
1392 */
1393 unsigned int fc_retransmit_count;
1394
1395 /**
1396 * Is this VirtualLink confirmed.
1397 * A unconfirmed VirtualLink might exist, if we got a FC from that target.
1398 */
1399 unsigned int confirmed;
1400
1401 /**
1402 * Neighbour used by this virtual link, NULL if @e dv is used.
1403 */
1404 struct Neighbour *n;
1405
1406 /**
1407 * Distance vector used by this virtual link, NULL if @e n is used.
1408 */
1409 struct DistanceVector *dv;
1410
1411 /**
1412 * Sender timestamp of @e n_challenge, used to generate out-of-order
1413 * challenges (as sender's timestamps must be monotonically
1414 * increasing). FIXME: where do we need this?
1415 */
1416 struct GNUNET_TIME_Absolute n_challenge_time;
1417
1418 /**
1419 * When did we last send a
1420 * #GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL message?
1421 * Used to determine whether it is time to re-transmit the message.
1422 */
1423 struct GNUNET_TIME_Absolute last_fc_transmission;
1424
1425 /**
1426 * Sender timestamp of the last
1427 * #GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL message we have
1428 * received. Note that we do not persist this monotonic time as we
1429 * do not really have to worry about ancient flow control window
1430 * sizes after restarts.
1431 */
1432 struct GNUNET_TIME_Absolute last_fc_timestamp;
1433
1434 /**
1435 * Expected RTT from the last FC transmission. (Zero if the last
1436 * attempt failed, but could theoretically be zero even on success.)
1437 */
1438 struct GNUNET_TIME_Relative last_fc_rtt;
1439
1440 /**
1441 * Used to generate unique UUIDs for messages that are being
1442 * fragmented.
1443 */
1444 uint64_t message_uuid_ctr;
1445
1446 /**
1447 * Memory allocated for this virtual link. Expresses how much RAM
1448 * we are willing to allocate to this virtual link. OPTIMIZE-ME:
1449 * Can be adapted to dedicate more RAM to links that need it, while
1450 * sticking to some overall RAM limit. For now, set to
1451 * #DEFAULT_WINDOW_SIZE.
1452 */
1453 uint64_t available_fc_window_size;
1454
1455 /**
1456 * Memory actually used to buffer packets on this virtual link.
1457 * Expresses how much RAM we are currently using for virtual link.
1458 * Note that once CORE is done with a packet, we decrement the value
1459 * here.
1460 */
1461 uint64_t incoming_fc_window_size_ram;
1462
1463 /**
1464 * Last flow control window size we provided to the other peer, in
1465 * bytes. We are allowing the other peer to send this
1466 * many bytes.
1467 */
1468 uint64_t incoming_fc_window_size;
1469
1470 /**
1471 * How much of the window did the other peer successfully use (and
1472 * we already passed it on to CORE)? Must be below @e
1473 * incoming_fc_window_size. We should effectively signal the
1474 * other peer that the window is this much bigger at the next
1475 * opportunity / challenge.
1476 */
1477 uint64_t incoming_fc_window_size_used;
1478
1479 /**
1480 * What is our current estimate on the message loss rate for the sender?
1481 * Based on the difference between how much the sender sent according
1482 * to the last #GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL message
1483 * (@e outbound_sent field) and how much we actually received at that
1484 * time (@e incoming_fc_window_size_used). This delta is then
1485 * added onto the @e incoming_fc_window_size when determining the
1486 * @e outbound_window_size we send to the other peer. Initially zero.
1487 * May be negative if we (due to out-of-order delivery) actually received
1488 * more than the sender claims to have sent in its last FC message.
1489 */
1490 int64_t incoming_fc_window_size_loss;
1491
1492 /**
1493 * Our current flow control window size in bytes. We
1494 * are allowed to transmit this many bytes to @a n.
1495 */
1496 uint64_t outbound_fc_window_size;
1497
1498 /**
1499 * How much of our current flow control window size have we
1500 * used (in bytes). Must be below
1501 * @e outbound_fc_window_size.
1502 */
1503 uint64_t outbound_fc_window_size_used;
1504
1505 /**
1506 * What is the most recent FC window the other peer sent us
1507 * in `outbound_window_size`? This is basically the window
1508 * size value the other peer has definitively received from
1509 * us. If it matches @e incoming_fc_window_size, we should
1510 * not send a FC message to increase the FC window. However,
1511 * we may still send an FC message to notify the other peer
1512 * that we received the other peer's FC message.
1513 */
1514 uint64_t last_outbound_window_size_received;
1515
1516 /**
1517 * Generator for the sequence numbers of
1518 * #GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL messages we send.
1519 */
1520 uint32_t fc_seq_gen;
1521
1522 /**
1523 * Last sequence number of a
1524 * #GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL message we have
1525 * received.
1526 */
1527 uint32_t last_fc_seq;
1528
1529 /**
1530 * How many more messages can we send to CORE before we exhaust
1531 * the receive window of CORE for this peer? If this hits zero,
1532 * we must tell communicators to stop providing us more messages
1533 * for this peer. In fact, the window can go negative as we
1534 * have multiple communicators, so per communicator we can go
1535 * down by one into the negative range. Furthermore, we count
1536 * delivery per CORE client, so if we had multiple cores, that
1537 * might also cause a negative window size here (as one message
1538 * would decrement the window by one per CORE client).
1539 */
1540 int core_recv_window;
1541};
1542
1543
1544/**
1545 * Data structure kept when we are waiting for an acknowledgement.
1546 */
1547struct PendingAcknowledgement
1548{
1549 /**
1550 * If @e pm is non-NULL, this is the DLL in which this acknowledgement
1551 * is kept in relation to its pending message.
1552 */
1553 struct PendingAcknowledgement *next_pm;
1554
1555 /**
1556 * If @e pm is non-NULL, this is the DLL in which this acknowledgement
1557 * is kept in relation to its pending message.
1558 */
1559 struct PendingAcknowledgement *prev_pm;
1560
1561 /**
1562 * If @e queue is non-NULL, this is the DLL in which this acknowledgement
1563 * is kept in relation to the queue that was used to transmit the
1564 * @a pm.
1565 */
1566 struct PendingAcknowledgement *next_queue;
1567
1568 /**
1569 * If @e queue is non-NULL, this is the DLL in which this acknowledgement
1570 * is kept in relation to the queue that was used to transmit the
1571 * @a pm.
1572 */
1573 struct PendingAcknowledgement *prev_queue;
1574
1575 /**
1576 * If @e dvh is non-NULL, this is the DLL in which this acknowledgement
1577 * is kept in relation to the DVH that was used to transmit the
1578 * @a pm.
1579 */
1580 struct PendingAcknowledgement *next_dvh;
1581
1582 /**
1583 * If @e dvh is non-NULL, this is the DLL in which this acknowledgement
1584 * is kept in relation to the DVH that was used to transmit the
1585 * @a pm.
1586 */
1587 struct PendingAcknowledgement *prev_dvh;
1588
1589 /**
1590 * Pointers for the DLL of all pending acknowledgements.
1591 * This list is sorted by @e transmission time. If the list gets too
1592 * long, the oldest entries are discarded.
1593 */
1594 struct PendingAcknowledgement *next_pa;
1595
1596 /**
1597 * Pointers for the DLL of all pending acknowledgements.
1598 * This list is sorted by @e transmission time. If the list gets too
1599 * long, the oldest entries are discarded.
1600 */
1601 struct PendingAcknowledgement *prev_pa;
1602
1603 /**
1604 * Unique identifier for this transmission operation.
1605 */
1606 struct AcknowledgementUUIDP ack_uuid;
1607
1608 /**
1609 * Message that was transmitted, may be NULL if the message was ACKed
1610 * via another channel.
1611 */
1612 struct PendingMessage *pm;
1613
1614 /**
1615 * Distance vector path chosen for this transmission, NULL if transmission
1616 * was to a direct neighbour OR if the path was forgotten in the meantime.
1617 */
1618 struct DistanceVectorHop *dvh;
1619
1620 /**
1621 * Queue used for transmission, NULL if the queue has been destroyed
1622 * (which may happen before we get an acknowledgement).
1623 */
1624 struct Queue *queue;
1625
1626 /**
1627 * Time of the transmission, for RTT calculation.
1628 */
1629 struct GNUNET_TIME_Absolute transmission_time;
1630
1631 /**
1632 * Number of bytes of the original message (to calculate bandwidth).
1633 */
1634 uint16_t message_size;
1635
1636 /**
1637 * How often the PendingMessage was send via the Queue of this PendingAcknowledgement.
1638 */
1639 unsigned int num_send;
1640};
1641
1642
1643/**
1644 * One possible hop towards a DV target.
1645 */
1646struct DistanceVectorHop
1647{
1648 /**
1649 * Kept in a MDLL, sorted by @e timeout.
1650 */
1651 struct DistanceVectorHop *next_dv;
1652
1653 /**
1654 * Kept in a MDLL, sorted by @e timeout.
1655 */
1656 struct DistanceVectorHop *prev_dv;
1657
1658 /**
1659 * Kept in a MDLL.
1660 */
1661 struct DistanceVectorHop *next_neighbour;
1662
1663 /**
1664 * Kept in a MDLL.
1665 */
1666 struct DistanceVectorHop *prev_neighbour;
1667
1668 /**
1669 * Head of DLL of PAs that used our @a path.
1670 */
1671 struct PendingAcknowledgement *pa_head;
1672
1673 /**
1674 * Tail of DLL of PAs that used our @a path.
1675 */
1676 struct PendingAcknowledgement *pa_tail;
1677
1678 /**
1679 * What would be the next hop to @e target?
1680 */
1681 struct Neighbour *next_hop;
1682
1683 /**
1684 * Distance vector entry this hop belongs with.
1685 */
1686 struct DistanceVector *dv;
1687
1688 /**
1689 * Array of @e distance hops to the target, excluding @e next_hop.
1690 * NULL if the entire path is us to @e next_hop to `target`. Allocated
1691 * at the end of this struct. Excludes the target itself!
1692 */
1693 const struct GNUNET_PeerIdentity *path;
1694
1695 /**
1696 * At what time do we forget about this path unless we see it again
1697 * while learning?
1698 */
1699 struct GNUNET_TIME_Absolute timeout;
1700
1701 /**
1702 * For how long is the validation of this path considered
1703 * valid?
1704 * Set to ZERO if the path is learned by snooping on DV learn messages
1705 * initiated by other peers, and to the time at which we generated the
1706 * challenge for DV learn operations this peer initiated.
1707 */
1708 struct GNUNET_TIME_Absolute path_valid_until;
1709
1710 /**
1711 * Performance data for this transmission possibility.
1712 */
1713 struct PerformanceData pd;
1714
1715 /**
1716 * Number of hops in total to the `target` (excluding @e next_hop and `target`
1717 * itself). Thus 0 still means a distance of 2 hops (to @e next_hop and then
1718 * to `target`).
1719 */
1720 unsigned int distance;
1721};
1722
1723
1724/**
1725 * Entry in our #dv_routes table, representing a (set of) distance
1726 * vector routes to a particular peer.
1727 */
1728struct DistanceVector
1729{
1730 /**
1731 * To which peer is this a route?
1732 */
1733 struct GNUNET_PeerIdentity target;
1734
1735 /**
1736 * Known paths to @e target.
1737 */
1738 struct DistanceVectorHop *dv_head;
1739
1740 /**
1741 * Known paths to @e target.
1742 */
1743 struct DistanceVectorHop *dv_tail;
1744
1745 /**
1746 * Task scheduled to purge expired paths from @e dv_head MDLL.
1747 */
1748 struct GNUNET_SCHEDULER_Task *timeout_task;
1749
1750 /**
1751 * Do we have a confirmed working queue and are thus visible to
1752 * CORE? If so, this is the virtual link, otherwise NULL.
1753 */
1754 struct VirtualLink *vl;
1755
1756 /**
1757 * Signature affirming @e ephemeral_key of type
1758 * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
1759 */
1760 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
1761
1762 /**
1763 * How long is @e sender_sig valid
1764 */
1765 struct GNUNET_TIME_Absolute ephemeral_validity;
1766
1767 /**
1768 * What time was @e sender_sig created
1769 */
1770 struct GNUNET_TIME_Absolute monotime;
1771
1772 /**
1773 * Our ephemeral key.
1774 */
1775 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
1776
1777};
1778
1779
1780/**
1781 * Entry identifying transmission in one of our `struct
1782 * Queue` which still awaits an ACK. This is used to
1783 * ensure we do not overwhelm a communicator and limit the number of
1784 * messages outstanding per communicator (say in case communicator is
1785 * CPU bound) and per queue (in case bandwidth allocation exceeds
1786 * what the communicator can actually provide towards a particular
1787 * peer/target).
1788 */
1789struct QueueEntry
1790{
1791 /**
1792 * Kept as a DLL.
1793 */
1794 struct QueueEntry *next;
1795
1796 /**
1797 * Kept as a DLL.
1798 */
1799 struct QueueEntry *prev;
1800
1801 /**
1802 * Queue this entry is queued with.
1803 */
1804 struct Queue *queue;
1805
1806 /**
1807 * Pending message this entry is for, or NULL for none.
1808 */
1809 struct PendingMessage *pm;
1810
1811 /**
1812 * Message ID used for this message with the queue used for transmission.
1813 */
1814 uint64_t mid;
1815};
1816
1817
1818/**
1819 * A queue is a message queue provided by a communicator
1820 * via which we can reach a particular neighbour.
1821 */
1822struct Queue
1823{
1824 /**
1825 * Kept in a MDLL.
1826 */
1827 struct Queue *next_neighbour;
1828
1829 /**
1830 * Kept in a MDLL.
1831 */
1832 struct Queue *prev_neighbour;
1833
1834 /**
1835 * Kept in a MDLL.
1836 */
1837 struct Queue *prev_client;
1838
1839 /**
1840 * Kept in a MDLL.
1841 */
1842 struct Queue *next_client;
1843
1844 /**
1845 * Head of DLL of PAs that used this queue.
1846 */
1847 struct PendingAcknowledgement *pa_head;
1848
1849 /**
1850 * Tail of DLL of PAs that used this queue.
1851 */
1852 struct PendingAcknowledgement *pa_tail;
1853
1854 /**
1855 * Head of DLL of unacked transmission requests.
1856 */
1857 struct QueueEntry *queue_head;
1858
1859 /**
1860 * End of DLL of unacked transmission requests.
1861 */
1862 struct QueueEntry *queue_tail;
1863
1864 /**
1865 * Which neighbour is this queue for?
1866 */
1867 struct Neighbour *neighbour;
1868
1869 /**
1870 * Which communicator offers this queue?
1871 */
1872 struct TransportClient *tc;
1873
1874 /**
1875 * Address served by the queue.
1876 */
1877 const char *address;
1878
1879 /**
1880 * Is this queue of unlimited length.
1881 */
1882 unsigned int unlimited_length;
1883
1884 /**
1885 * Task scheduled for the time when this queue can (likely) transmit the
1886 * next message.
1887 */
1888 struct GNUNET_SCHEDULER_Task *transmit_task;
1889
1890 /**
1891 * How long do *we* consider this @e address to be valid? In the past or
1892 * zero if we have not yet validated it. Can be updated based on
1893 * challenge-response validations (via address validation logic), or when we
1894 * receive ACKs that we can definitively map to transmissions via this
1895 * queue.
1896 */
1897 struct GNUNET_TIME_Absolute validated_until;
1898
1899 /**
1900 * Performance data for this queue.
1901 */
1902 struct PerformanceData pd;
1903
1904 /**
1905 * Message ID generator for transmissions on this queue to the
1906 * communicator.
1907 */
1908 uint64_t mid_gen;
1909
1910 /**
1911 * Unique identifier of this queue with the communicator.
1912 */
1913 uint32_t qid;
1914
1915 /**
1916 * Maximum transmission unit supported by this queue.
1917 */
1918 uint32_t mtu;
1919
1920 /**
1921 * Messages pending.
1922 */
1923 uint32_t num_msg_pending;
1924
1925 /**
1926 * Bytes pending.
1927 */
1928 uint32_t num_bytes_pending;
1929
1930 /**
1931 * Length of the DLL starting at @e queue_head.
1932 */
1933 unsigned int queue_length;
1934
1935 /**
1936 * Capacity of the queue.
1937 */
1938 uint64_t q_capacity;
1939
1940 /**
1941 * Queue priority
1942 */
1943 uint32_t priority;
1944
1945 /**
1946 * Network type offered by this queue.
1947 */
1948 enum GNUNET_NetworkType nt;
1949
1950 /**
1951 * Connection status for this queue.
1952 */
1953 enum GNUNET_TRANSPORT_ConnectionStatus cs;
1954
1955 /**
1956 * Set to #GNUNET_YES if this queue is idle waiting for some
1957 * virtual link to give it a pending message.
1958 */
1959 int idle;
1960};
1961
1962
1963/**
1964 * A neighbour that at least one communicator is connected to.
1965 */
1966struct Neighbour
1967{
1968 /**
1969 * Which peer is this about?
1970 */
1971 struct GNUNET_PeerIdentity pid;
1972
1973 /**
1974 * Head of MDLL of DV hops that have this neighbour as next hop. Must be
1975 * purged if this neighbour goes down.
1976 */
1977 struct DistanceVectorHop *dv_head;
1978
1979 /**
1980 * Tail of MDLL of DV hops that have this neighbour as next hop. Must be
1981 * purged if this neighbour goes down.
1982 */
1983 struct DistanceVectorHop *dv_tail;
1984
1985 /**
1986 * Head of DLL of queues to this peer.
1987 */
1988 struct Queue *queue_head;
1989
1990 /**
1991 * Tail of DLL of queues to this peer.
1992 */
1993 struct Queue *queue_tail;
1994
1995 /**
1996 * Handle for an operation to fetch @e last_dv_learn_monotime information from
1997 * the PEERSTORE, or NULL.
1998 */
1999 struct GNUNET_PEERSTORE_IterateContext *get;
2000
2001 /**
2002 * Handle to a PEERSTORE store operation to store this @e pid's @e
2003 * @e last_dv_learn_monotime. NULL if no PEERSTORE operation is pending.
2004 */
2005 struct GNUNET_PEERSTORE_StoreContext *sc;
2006
2007 /**
2008 * Do we have a confirmed working queue and are thus visible to
2009 * CORE? If so, this is the virtual link, otherwise NULL.
2010 */
2011 struct VirtualLink *vl;
2012
2013 /**
2014 * Latest DVLearn monotonic time seen from this peer. Initialized only
2015 * if @e dl_monotime_available is #GNUNET_YES.
2016 */
2017 struct GNUNET_TIME_Absolute last_dv_learn_monotime;
2018
2019 /**
2020 * Do we have the latest value for @e last_dv_learn_monotime from
2021 * PEERSTORE yet, or are we still waiting for a reply of PEERSTORE?
2022 */
2023 int dv_monotime_available;
2024};
2025
2026
2027/**
2028 * Another peer attempted to talk to us, we should try to establish
2029 * a connection in the other direction.
2030 */
2031struct IncomingRequest
2032{
2033 /**
2034 * Kept in a DLL.
2035 */
2036 struct IncomingRequest *next;
2037
2038 /**
2039 * Kept in a DLL.
2040 */
2041 struct IncomingRequest *prev;
2042
2043 /**
2044 * Notify context for new HELLOs.
2045 */
2046 struct GNUNET_PEERSTORE_NotifyContext *nc;
2047
2048 /**
2049 * Which peer is this about?
2050 */
2051 struct GNUNET_PeerIdentity pid;
2052};
2053
2054
2055/**
2056 * A peer that an application (client) would like us to talk to directly.
2057 */
2058struct PeerRequest
2059{
2060 /**
2061 * Which peer is this about?
2062 */
2063 struct GNUNET_PeerIdentity pid;
2064
2065 /**
2066 * Client responsible for the request.
2067 */
2068 struct TransportClient *tc;
2069
2070 /**
2071 * Notify context for new HELLOs.
2072 */
2073 struct GNUNET_PEERSTORE_NotifyContext *nc;
2074
2075 /**
2076 * What kind of performance preference does this @e tc have?
2077 *
2078 * TODO: use this!
2079 */
2080 enum GNUNET_MQ_PriorityPreferences pk;
2081
2082 /**
2083 * How much bandwidth would this @e tc like to see?
2084 */
2085 struct GNUNET_BANDWIDTH_Value32NBO bw;
2086};
2087
2088
2089/**
2090 * Types of different pending messages.
2091 */
2092enum PendingMessageType
2093{
2094 /**
2095 * Ordinary message received from the CORE service.
2096 */
2097 PMT_CORE = 0,
2098
2099 /**
2100 * Fragment box.
2101 */
2102 PMT_FRAGMENT_BOX = 1,
2103
2104 /**
2105 * Reliability box.
2106 */
2107 PMT_RELIABILITY_BOX = 2,
2108
2109 /**
2110 * Pending message created during #forward_dv_box().
2111 */
2112 PMT_DV_BOX = 3
2113};
2114
2115
2116/**
2117 * Transmission request that is awaiting delivery. The original
2118 * transmission requests from CORE may be too big for some queues.
2119 * In this case, a *tree* of fragments is created. At each
2120 * level of the tree, fragments are kept in a DLL ordered by which
2121 * fragment should be sent next (at the head). The tree is searched
2122 * top-down, with the original message at the root.
2123 *
2124 * To select a node for transmission, first it is checked if the
2125 * current node's message fits with the MTU. If it does not, we
2126 * either calculate the next fragment (based on @e frag_off) from the
2127 * current node, or, if all fragments have already been created,
2128 * descend to the @e head_frag. Even though the node was already
2129 * fragmented, the fragment may be too big if the fragment was
2130 * generated for a queue with a larger MTU. In this case, the node
2131 * may be fragmented again, thus creating a tree.
2132 *
2133 * When acknowledgements for fragments are received, the tree
2134 * must be pruned, removing those parts that were already
2135 * acknowledged. When fragments are sent over a reliable
2136 * channel, they can be immediately removed.
2137 *
2138 * If a message is ever fragmented, then the original "full" message
2139 * is never again transmitted (even if it fits below the MTU), and
2140 * only (remaining) fragments are sent.
2141 */
2142struct PendingMessage
2143{
2144 /**
2145 * Kept in a MDLL of messages for this @a vl.
2146 */
2147 struct PendingMessage *next_vl;
2148
2149 /**
2150 * Kept in a MDLL of messages for this @a vl.
2151 */
2152 struct PendingMessage *prev_vl;
2153
2154 /**
2155 * Kept in a MDLL of messages from this @a client (if @e pmt is #PMT_CORE)
2156 */
2157 struct PendingMessage *next_client;
2158
2159 /**
2160 * Kept in a MDLL of messages from this @a client (if @e pmt is #PMT_CORE)
2161 */
2162 struct PendingMessage *prev_client;
2163
2164 /**
2165 * Kept in a MDLL of messages from this @a cpm (if @e pmt is
2166 * #PMT_FRAGMENT_BOx)
2167 */
2168 struct PendingMessage *next_frag;
2169
2170 /**
2171 * Kept in a MDLL of messages from this @a cpm (if @e pmt is
2172 * #PMT_FRAGMENT_BOX)
2173 */
2174 struct PendingMessage *prev_frag;
2175
2176 /**
2177 * Head of DLL of PAs for this pending message.
2178 */
2179 struct PendingAcknowledgement *pa_head;
2180
2181 /**
2182 * Tail of DLL of PAs for this pending message.
2183 */
2184 struct PendingAcknowledgement *pa_tail;
2185
2186 /**
2187 * This message, reliability *or* DV-boxed. Only possibly available
2188 * if @e pmt is #PMT_CORE.
2189 */
2190 struct PendingMessage *bpm;
2191
2192 /**
2193 * Target of the request (always the ultimate destination!).
2194 * Might be NULL in case of a forwarded DVBox we have no validated neighbour.
2195 */
2196 struct VirtualLink *vl;
2197
2198 /**
2199 * In case of a not validated neighbour, we store the target peer.
2200 **/
2201 struct GNUNET_PeerIdentity target;
2202
2203 /**
2204 * Set to non-NULL value if this message is currently being given to a
2205 * communicator and we are awaiting that communicator's acknowledgement.
2206 * Note that we must not retransmit a pending message while we're still
2207 * in the process of giving it to a communicator. If a pending message
2208 * is free'd while this entry is non-NULL, the @e qe reference to us
2209 * should simply be set to NULL.
2210 */
2211 struct QueueEntry *qe;
2212
2213 /**
2214 * Client that issued the transmission request, if @e pmt is #PMT_CORE.
2215 */
2216 struct TransportClient *client;
2217
2218 /**
2219 * Head of a MDLL of fragments created for this core message.
2220 */
2221 struct PendingMessage *head_frag;
2222
2223 /**
2224 * Tail of a MDLL of fragments created for this core message.
2225 */
2226 struct PendingMessage *tail_frag;
2227
2228 /**
2229 * Our parent in the fragmentation tree.
2230 */
2231 struct PendingMessage *frag_parent;
2232
2233 /**
2234 * At what time should we give up on the transmission (and no longer retry)?
2235 */
2236 struct GNUNET_TIME_Absolute timeout;
2237
2238 /**
2239 * What is the earliest time for us to retry transmission of this message?
2240 */
2241 struct GNUNET_TIME_Absolute next_attempt;
2242
2243 /**
2244 * UUID to use for this message (used for reassembly of fragments, only
2245 * initialized if @e msg_uuid_set is #GNUNET_YES).
2246 */
2247 struct MessageUUIDP msg_uuid;
2248
2249 /**
2250 * UUID we use to identify this message in our logs.
2251 * Generated by incrementing the "logging_uuid_gen".
2252 */
2253 unsigned long long logging_uuid;
2254
2255 /**
2256 * Type of the pending message.
2257 */
2258 enum PendingMessageType pmt;
2259
2260 /**
2261 * Preferences for this message.
2262 * TODO: actually use this!
2263 */
2264 enum GNUNET_MQ_PriorityPreferences prefs;
2265
2266 /**
2267 * If pmt is of type PMT_DV_BOX we store the used path here.
2268 */
2269 struct DistanceVectorHop *used_dvh;
2270
2271 /**
2272 * Size of the original message.
2273 */
2274 uint16_t bytes_msg;
2275
2276 /**
2277 * Offset at which we should generate the next fragment.
2278 */
2279 uint16_t frag_off;
2280
2281 /**
2282 * Are we sending fragments at the moment?
2283 */
2284 unsigned int frags_in_flight;
2285
2286 /**
2287 * How many fragments do we have?
2288 **/
2289 uint16_t frag_count;
2290
2291 /**
2292 * #GNUNET_YES once @e msg_uuid was initialized
2293 */
2294 int16_t msg_uuid_set;
2295
2296 /* Followed by @e bytes_msg to transmit */
2297};
2298
2299
2300/**
2301 * Acknowledgement payload.
2302 */
2303struct TransportCummulativeAckPayload
2304{
2305 /**
2306 * When did we receive the message we are ACKing? Used to calculate
2307 * the delay we introduced by cummulating ACKs.
2308 */
2309 struct GNUNET_TIME_Absolute receive_time;
2310
2311 /**
2312 * UUID of a message being acknowledged.
2313 */
2314 struct AcknowledgementUUIDP ack_uuid;
2315};
2316
2317
2318/**
2319 * Data structure in which we track acknowledgements still to
2320 * be sent to the
2321 */
2322struct AcknowledgementCummulator
2323{
2324 /**
2325 * Target peer for which we are accumulating ACKs here.
2326 */
2327 struct GNUNET_PeerIdentity target;
2328
2329 /**
2330 * ACK data being accumulated. Only @e num_acks slots are valid.
2331 */
2332 struct TransportCummulativeAckPayload ack_uuids[MAX_CUMMULATIVE_ACKS];
2333
2334 /**
2335 * Task scheduled either to transmit the cumulative ACK message,
2336 * or to clean up this data structure after extended periods of
2337 * inactivity (if @e num_acks is zero).
2338 */
2339 struct GNUNET_SCHEDULER_Task *task;
2340
2341 /**
2342 * When is @e task run (only used if @e num_acks is non-zero)?
2343 */
2344 struct GNUNET_TIME_Absolute min_transmission_time;
2345
2346 /**
2347 * Counter to produce the `ack_counter` in the `struct
2348 * TransportReliabilityAckMessage`. Allows the receiver to detect
2349 * lost ACK messages. Incremented by @e num_acks upon transmission.
2350 */
2351 uint32_t ack_counter;
2352
2353 /**
2354 * Number of entries used in @e ack_uuids. Reset to 0 upon transmission.
2355 */
2356 unsigned int num_acks;
2357};
2358
2359
2360/**
2361 * One of the addresses of this peer.
2362 */
2363struct AddressListEntry
2364{
2365 /**
2366 * Kept in a DLL.
2367 */
2368 struct AddressListEntry *next;
2369
2370 /**
2371 * Kept in a DLL.
2372 */
2373 struct AddressListEntry *prev;
2374
2375 /**
2376 * Which communicator provides this address?
2377 */
2378 struct TransportClient *tc;
2379
2380 /**
2381 * The actual address.
2382 */
2383 const char *address;
2384
2385 /**
2386 * Current context for storing this address in the peerstore.
2387 */
2388 struct GNUNET_PEERSTORE_StoreContext *sc;
2389
2390 /**
2391 * Task to periodically do @e st operation.
2392 */
2393 struct GNUNET_SCHEDULER_Task *st;
2394
2395 /**
2396 * What is a typical lifetime the communicator expects this
2397 * address to have? (Always from now.)
2398 */
2399 struct GNUNET_TIME_Relative expiration;
2400
2401 /**
2402 * Address identifier used by the communicator.
2403 */
2404 uint32_t aid;
2405
2406 /**
2407 * Network type offered by this address.
2408 */
2409 enum GNUNET_NetworkType nt;
2410};
2411
2412
2413/**
2414 * Client connected to the transport service.
2415 */
2416struct TransportClient
2417{
2418 /**
2419 * Kept in a DLL.
2420 */
2421 struct TransportClient *next;
2422
2423 /**
2424 * Kept in a DLL.
2425 */
2426 struct TransportClient *prev;
2427
2428 /**
2429 * Handle to the client.
2430 */
2431 struct GNUNET_SERVICE_Client *client;
2432
2433 /**
2434 * Message queue to the client.
2435 */
2436 struct GNUNET_MQ_Handle *mq;
2437
2438 /**
2439 * What type of client is this?
2440 */
2441 enum ClientType type;
2442
2443 union
2444 {
2445 /**
2446 * Information for @e type #CT_CORE.
2447 */
2448 struct
2449 {
2450 /**
2451 * Head of list of messages pending for this client, sorted by
2452 * transmission time ("next_attempt" + possibly internal prioritization).
2453 */
2454 struct PendingMessage *pending_msg_head;
2455
2456 /**
2457 * Tail of list of messages pending for this client.
2458 */
2459 struct PendingMessage *pending_msg_tail;
2460 } core;
2461
2462 /**
2463 * Information for @e type #CT_MONITOR.
2464 */
2465 struct
2466 {
2467 /**
2468 * Peer identity to monitor the addresses of.
2469 * Zero to monitor all neighbours. Valid if
2470 * @e type is #CT_MONITOR.
2471 */
2472 struct GNUNET_PeerIdentity peer;
2473
2474 /**
2475 * Is this a one-shot monitor?
2476 */
2477 int one_shot;
2478 } monitor;
2479
2480
2481 /**
2482 * Information for @e type #CT_COMMUNICATOR.
2483 */
2484 struct
2485 {
2486 /**
2487 * If @e type is #CT_COMMUNICATOR, this communicator
2488 * supports communicating using these addresses.
2489 */
2490 char *address_prefix;
2491
2492 /**
2493 * Head of DLL of queues offered by this communicator.
2494 */
2495 struct Queue *queue_head;
2496
2497 /**
2498 * Tail of DLL of queues offered by this communicator.
2499 */
2500 struct Queue *queue_tail;
2501
2502 /**
2503 * Head of list of the addresses of this peer offered by this
2504 * communicator.
2505 */
2506 struct AddressListEntry *addr_head;
2507
2508 /**
2509 * Tail of list of the addresses of this peer offered by this
2510 * communicator.
2511 */
2512 struct AddressListEntry *addr_tail;
2513
2514 /**
2515 * Number of queue entries in all queues to this communicator. Used
2516 * throttle sending to a communicator if we see that the communicator
2517 * is globally unable to keep up.
2518 */
2519 unsigned int total_queue_length;
2520
2521 /**
2522 * Characteristics of this communicator.
2523 */
2524 enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc;
2525 } communicator;
2526
2527 /**
2528 * Information for @e type #CT_APPLICATION
2529 */
2530 struct
2531 {
2532 /**
2533 * Map of requests for peers the given client application would like to
2534 * see connections for. Maps from PIDs to `struct PeerRequest`.
2535 */
2536 struct GNUNET_CONTAINER_MultiPeerMap *requests;
2537 } application;
2538 } details;
2539};
2540
2541
2542/**
2543 * State we keep for validation activities. Each of these
2544 * is both in the #validation_heap and the #validation_map.
2545 */
2546struct ValidationState
2547{
2548 /**
2549 * For which peer is @a address to be validated (or possibly valid)?
2550 * Serves as key in the #validation_map.
2551 */
2552 struct GNUNET_PeerIdentity pid;
2553
2554 /**
2555 * How long did the peer claim this @e address to be valid? Capped at
2556 * minimum of #MAX_ADDRESS_VALID_UNTIL relative to the time where we last
2557 * were told about the address and the value claimed by the other peer at
2558 * that time. May be updated similarly when validation succeeds.
2559 */
2560 struct GNUNET_TIME_Absolute valid_until;
2561
2562 /**
2563 * How long do *we* consider this @e address to be valid?
2564 * In the past or zero if we have not yet validated it.
2565 */
2566 struct GNUNET_TIME_Absolute validated_until;
2567
2568 /**
2569 * When did we FIRST use the current @e challenge in a message?
2570 * Used to sanity-check @code{origin_time} in the response when
2571 * calculating the RTT. If the @code{origin_time} is not in
2572 * the expected range, the response is discarded as malicious.
2573 */
2574 struct GNUNET_TIME_Absolute first_challenge_use;
2575
2576 /**
2577 * When did we LAST use the current @e challenge in a message?
2578 * Used to sanity-check @code{origin_time} in the response when
2579 * calculating the RTT. If the @code{origin_time} is not in
2580 * the expected range, the response is discarded as malicious.
2581 */
2582 struct GNUNET_TIME_Absolute last_challenge_use;
2583
2584 /**
2585 * Next time we will send the @e challenge to the peer, if this time is past
2586 * @e valid_until, this validation state is released at this time. If the
2587 * address is valid, @e next_challenge is set to @e validated_until MINUS @e
2588 * validation_delay * #VALIDATION_RTT_BUFFER_FACTOR, such that we will try
2589 * to re-validate before the validity actually expires.
2590 */
2591 struct GNUNET_TIME_Absolute next_challenge;
2592
2593 /**
2594 * Current backoff factor we're applying for sending the @a challenge.
2595 * Reset to 0 if the @a challenge is confirmed upon validation.
2596 * Reduced to minimum of #FAST_VALIDATION_CHALLENGE_FREQ and half of the
2597 * existing value if we receive an unvalidated address again over
2598 * another channel (and thus should consider the information "fresh").
2599 * Maximum is #MAX_VALIDATION_CHALLENGE_FREQ.
2600 */
2601 struct GNUNET_TIME_Relative challenge_backoff;
2602
2603 /**
2604 * Initially set to "forever". Once @e validated_until is set, this value is
2605 * set to the RTT that tells us how long it took to receive the validation.
2606 */
2607 struct GNUNET_TIME_Relative validation_rtt;
2608
2609 /**
2610 * The challenge we sent to the peer to get it to validate the address. Note
2611 * that we rotate the challenge whenever we update @e validated_until to
2612 * avoid attacks where a peer simply replays an old challenge in the future.
2613 * (We must not rotate more often as otherwise we may discard valid answers
2614 * due to packet losses, latency and reorderings on the network).
2615 */
2616 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
2617
2618 /**
2619 * Claimed address of the peer.
2620 */
2621 char *address;
2622
2623 /**
2624 * Entry in the #validation_heap, which is sorted by @e next_challenge. The
2625 * heap is used to figure out when the next validation activity should be
2626 * run.
2627 */
2628 struct GNUNET_CONTAINER_HeapNode *hn;
2629
2630 /**
2631 * Handle to a PEERSTORE store operation for this @e address. NULL if
2632 * no PEERSTORE operation is pending.
2633 */
2634 struct GNUNET_PEERSTORE_StoreContext *sc;
2635
2636 /**
2637 * Self-imposed limit on the previous flow control window. (May be zero,
2638 * if we never used data from the previous window or are establishing the
2639 * connection for the first time).
2640 */
2641 uint32_t last_window_consum_limit;
2642
2643 /**
2644 * We are technically ready to send the challenge, but we are waiting for
2645 * the respective queue to become available for transmission.
2646 */
2647 int awaiting_queue;
2648};
2649
2650
2651/**
2652 * A Backtalker is a peer sending us backchannel messages. We use this
2653 * struct to detect monotonic time violations, cache ephemeral key
2654 * material (to avoid repeatedly checking signatures), and to synchronize
2655 * monotonic time with the PEERSTORE.
2656 */
2657struct Backtalker
2658{
2659 /**
2660 * Peer this is about.
2661 */
2662 struct GNUNET_PeerIdentity pid;
2663
2664 /**
2665 * Last (valid) monotonic time received from this sender.
2666 */
2667 struct GNUNET_TIME_Absolute monotonic_time;
2668
2669 /**
2670 * When will this entry time out?
2671 */
2672 struct GNUNET_TIME_Absolute timeout;
2673
2674 /**
2675 * Last (valid) ephemeral key received from this sender.
2676 */
2677 struct GNUNET_CRYPTO_EcdhePublicKey last_ephemeral;
2678
2679 /**
2680 * Task associated with this backtalker. Can be for timeout,
2681 * or other asynchronous operations.
2682 */
2683 struct GNUNET_SCHEDULER_Task *task;
2684
2685 /**
2686 * Communicator context waiting on this backchannel's @e get, or NULL.
2687 */
2688 struct CommunicatorMessageContext *cmc;
2689
2690 /**
2691 * Handle for an operation to fetch @e monotonic_time information from the
2692 * PEERSTORE, or NULL.
2693 */
2694 struct GNUNET_PEERSTORE_IterateContext *get;
2695
2696 /**
2697 * Handle to a PEERSTORE store operation for this @e pid's @e
2698 * monotonic_time. NULL if no PEERSTORE operation is pending.
2699 */
2700 struct GNUNET_PEERSTORE_StoreContext *sc;
2701
2702 /**
2703 * Number of bytes of the original message body that follows after this
2704 * struct.
2705 */
2706 size_t body_size;
2707};
2708
2709
2710/**
2711 * Ring buffer for a CORE message we did not deliver to CORE, because of missing virtual link to sender.
2712 */
2713static struct RingBufferEntry *ring_buffer[RING_BUFFER_SIZE];
2714
2715/**
2716 * Head of the ring buffer.
2717 */
2718static unsigned int ring_buffer_head;
2719
2720/**
2721 * Is the ring buffer filled up to RING_BUFFER_SIZE.
2722 */
2723static unsigned int is_ring_buffer_full;
2724
2725/**
2726 * Ring buffer for a forwarded DVBox message we did not deliver to the next hop, because of missing virtual link that hop.
2727 */
2728static struct PendingMessage *ring_buffer_dv[RING_BUFFER_SIZE];
2729
2730/**
2731 * Head of the ring buffer.
2732 */
2733static unsigned int ring_buffer_dv_head;
2734
2735/**
2736 * Is the ring buffer filled up to RING_BUFFER_SIZE.
2737 */
2738static unsigned int is_ring_buffer_dv_full;
2739
2740/**
2741 * Head of linked list of all clients to this service.
2742 */
2743static struct TransportClient *clients_head;
2744
2745/**
2746 * Tail of linked list of all clients to this service.
2747 */
2748static struct TransportClient *clients_tail;
2749
2750/**
2751 * Statistics handle.
2752 */
2753static struct GNUNET_STATISTICS_Handle *GST_stats;
2754
2755/**
2756 * Configuration handle.
2757 */
2758static const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
2759
2760/**
2761 * Our public key.
2762 */
2763static struct GNUNET_PeerIdentity GST_my_identity;
2764
2765/**
2766 * Our HELLO
2767 */
2768struct GNUNET_HELLO_Builder *GST_my_hello;
2769
2770/**
2771 * Our private key.
2772 */
2773static struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
2774
2775/**
2776 * Map from PIDs to `struct Neighbour` entries. A peer is
2777 * a neighbour if we have an MQ to it from some communicator.
2778 */
2779static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
2780
2781/**
2782 * Map from PIDs to `struct Backtalker` entries. A peer is
2783 * a backtalker if it recently send us backchannel messages.
2784 */
2785static struct GNUNET_CONTAINER_MultiPeerMap *backtalkers;
2786
2787/**
2788 * Map from PIDs to `struct AcknowledgementCummulator`s.
2789 * Here we track the cumulative ACKs for transmission.
2790 */
2791static struct GNUNET_CONTAINER_MultiPeerMap *ack_cummulators;
2792
2793/**
2794 * Map of pending acknowledgements, mapping `struct AcknowledgementUUID` to
2795 * a `struct PendingAcknowledgement`.
2796 */
2797static struct GNUNET_CONTAINER_MultiUuidmap *pending_acks;
2798
2799/**
2800 * Map from PIDs to `struct DistanceVector` entries describing
2801 * known paths to the peer.
2802 */
2803static struct GNUNET_CONTAINER_MultiPeerMap *dv_routes;
2804
2805/**
2806 * Map from PIDs to `struct ValidationState` entries describing
2807 * addresses we are aware of and their validity state.
2808 */
2809static struct GNUNET_CONTAINER_MultiPeerMap *validation_map;
2810
2811/**
2812 * Map from PIDs to `struct VirtualLink` entries describing
2813 * links CORE knows to exist.
2814 */
2815static struct GNUNET_CONTAINER_MultiPeerMap *links;
2816
2817/**
2818 * Map from challenges to `struct LearnLaunchEntry` values.
2819 */
2820static struct GNUNET_CONTAINER_MultiShortmap *dvlearn_map;
2821
2822/**
2823 * Head of a DLL sorted by launch time.
2824 */
2825static struct LearnLaunchEntry *lle_head = NULL;
2826
2827/**
2828 * Tail of a DLL sorted by launch time.
2829 */
2830static struct LearnLaunchEntry *lle_tail = NULL;
2831
2832/**
2833 * MIN Heap sorted by "next_challenge" to `struct ValidationState` entries
2834 * sorting addresses we are aware of by when we should next try to (re)validate
2835 * (or expire) them.
2836 */
2837static struct GNUNET_CONTAINER_Heap *validation_heap;
2838
2839/**
2840 * Database for peer's HELLOs.
2841 */
2842static struct GNUNET_PEERSTORE_Handle *peerstore;
2843
2844/**
2845 * Task run to initiate DV learning.
2846 */
2847static struct GNUNET_SCHEDULER_Task *dvlearn_task;
2848
2849/**
2850 * Task to run address validation.
2851 */
2852static struct GNUNET_SCHEDULER_Task *validation_task;
2853
2854/**
2855 * List of incoming connections where we are trying
2856 * to get a connection back established. Length
2857 * kept in #ir_total.
2858 */
2859static struct IncomingRequest *ir_head;
2860
2861/**
2862 * Tail of DLL starting at #ir_head.
2863 */
2864static struct IncomingRequest *ir_tail;
2865
2866/**
2867 * Length of the DLL starting at #ir_head.
2868 */
2869static unsigned int ir_total;
2870
2871/**
2872 * Generator of `logging_uuid` in `struct PendingMessage`.
2873 */
2874static unsigned long long logging_uuid_gen;
2875
2876/**
2877 * Monotonic time we use for HELLOs generated at this time. TODO: we
2878 * should increase this value from time to time (i.e. whenever a
2879 * `struct AddressListEntry` actually expires), but IF we do this, we
2880 * must also update *all* (remaining) addresses in the PEERSTORE at
2881 * that time! (So for now only increased when the peer is restarted,
2882 * which hopefully roughly matches whenever our addresses change.)
2883 */
2884static struct GNUNET_TIME_Absolute hello_mono_time;
2885
2886/**
2887 * Indication if we have received a shutdown signal
2888 * and are in the process of cleaning up.
2889 */
2890static int in_shutdown;
2891
2892/**
2893 * Get an offset into the transmission history buffer for `struct
2894 * PerformanceData`. Note that the caller must perform the required
2895 * modulo #GOODPUT_AGING_SLOTS operation before indexing into the
2896 * array!
2897 *
2898 * An 'age' lasts 15 minute slots.
2899 *
2900 * @return current age of the world
2901 */
2902static unsigned int
2903get_age ()
2904{
2905 struct GNUNET_TIME_Absolute now;
2906
2907 now = GNUNET_TIME_absolute_get ();
2908 return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
2909}
2910
2911
2912/**
2913 * Release @a ir data structure.
2914 *
2915 * @param ir data structure to release
2916 */
2917static void
2918free_incoming_request (struct IncomingRequest *ir)
2919{
2920 GNUNET_CONTAINER_DLL_remove (ir_head, ir_tail, ir);
2921 GNUNET_assert (ir_total > 0);
2922 ir_total--;
2923 GNUNET_PEERSTORE_hello_changed_notify_cancel (ir->nc);
2924 ir->nc = NULL;
2925 GNUNET_free (ir);
2926}
2927
2928
2929/**
2930 * Release @a pa data structure.
2931 *
2932 * @param pa data structure to release
2933 */
2934static void
2935free_pending_acknowledgement (struct PendingAcknowledgement *pa)
2936{
2937 struct Queue *q = pa->queue;
2938 struct PendingMessage *pm = pa->pm;
2939 struct DistanceVectorHop *dvh = pa->dvh;
2940
2941 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2942 "free_pending_acknowledgement\n");
2943 if (NULL != q)
2944 {
2945 GNUNET_CONTAINER_MDLL_remove (queue, q->pa_head, q->pa_tail, pa);
2946 pa->queue = NULL;
2947 }
2948 if (NULL != pm)
2949 {
2950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2951 "remove pa from message\n");
2952 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2953 "remove pa from message %llu\n",
2954 pm->logging_uuid);
2955 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2956 "remove pa from message %u\n",
2957 pm->pmt);
2958 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2959 "remove pa from message %s\n",
2960 GNUNET_uuid2s (&pa->ack_uuid.value));
2961 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
2962 pa->pm = NULL;
2963 }
2964 if (NULL != dvh)
2965 {
2966 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
2967 pa->queue = NULL;
2968 }
2969 GNUNET_assert (GNUNET_YES ==
2970 GNUNET_CONTAINER_multiuuidmap_remove (pending_acks,
2971 &pa->ack_uuid.value,
2972 pa));
2973 GNUNET_free (pa);
2974}
2975
2976
2977/**
2978 * Free fragment tree below @e root, excluding @e root itself.
2979 * FIXME: this does NOT seem to have the intended semantics
2980 * based on how this is called. Seems we generally DO expect
2981 * @a root to be free'ed itself as well!
2982 *
2983 * @param root root of the tree to free
2984 */
2985static void
2986free_fragment_tree (struct PendingMessage *root)
2987{
2988 struct PendingMessage *frag;
2989
2990 while (NULL != (frag = root->head_frag))
2991 {
2992 struct PendingAcknowledgement *pa;
2993
2994 free_fragment_tree (frag);
2995 while (NULL != (pa = frag->pa_head))
2996 {
2997 GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa);
2998 pa->pm = NULL;
2999 }
3000 GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
3001 if (NULL != frag->qe)
3002 {
3003 GNUNET_assert (frag == frag->qe->pm);
3004 frag->qe->pm = NULL;
3005 }
3006 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3007 "Free frag %p\n",
3008 frag);
3009 GNUNET_free (frag);
3010 }
3011}
3012
3013
3014/**
3015 * Release memory associated with @a pm and remove @a pm from associated
3016 * data structures. @a pm must be a top-level pending message and not
3017 * a fragment in the tree. The entire tree is freed (if applicable).
3018 *
3019 * @param pm the pending message to free
3020 */
3021static void
3022free_pending_message (struct PendingMessage *pm)
3023{
3024 struct TransportClient *tc = pm->client;
3025 struct VirtualLink *vl = pm->vl;
3026 struct PendingAcknowledgement *pa;
3027
3028 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3029 "Freeing pm %p\n",
3030 pm);
3031 if (NULL != tc)
3032 {
3033 GNUNET_CONTAINER_MDLL_remove (client,
3034 tc->details.core.pending_msg_head,
3035 tc->details.core.pending_msg_tail,
3036 pm);
3037 }
3038 if ((NULL != vl) && (NULL == pm->frag_parent))
3039 {
3040 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3041 "Removing pm %llu\n",
3042 pm->logging_uuid);
3043 GNUNET_CONTAINER_MDLL_remove (vl,
3044 vl->pending_msg_head,
3045 vl->pending_msg_tail,
3046 pm);
3047 }
3048 while (NULL != (pa = pm->pa_head))
3049 {
3050 if (NULL == pa)
3051 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3052 "free pending pa null\n");
3053 if (NULL == pm->pa_tail)
3054 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3055 "free pending pa_tail null\n");
3056 if (NULL == pa->prev_pa)
3057 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3058 "free pending pa prev null\n");
3059 if (NULL == pa->next_pa)
3060 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3061 "free pending pa next null\n");
3062 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3063 pa->pm = NULL;
3064 }
3065
3066 free_fragment_tree (pm);
3067 if (NULL != pm->qe)
3068 {
3069 GNUNET_assert (pm == pm->qe->pm);
3070 pm->qe->pm = NULL;
3071 }
3072 if (NULL != pm->bpm)
3073 {
3074 free_fragment_tree (pm->bpm);
3075 if (NULL != pm->bpm->qe)
3076 {
3077 struct QueueEntry *qe = pm->bpm->qe;
3078 qe->pm = NULL;
3079 }
3080 GNUNET_free (pm->bpm);
3081 }
3082
3083 GNUNET_free (pm);
3084 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3085 "Freeing pm done\n");
3086}
3087
3088
3089/**
3090 * Free @a rc
3091 *
3092 * @param rc data structure to free
3093 */
3094static void
3095free_reassembly_context (struct ReassemblyContext *rc)
3096{
3097 struct VirtualLink *vl = rc->virtual_link;
3098
3099 GNUNET_assert (rc == GNUNET_CONTAINER_heap_remove_node (rc->hn));
3100 GNUNET_assert (GNUNET_OK ==
3101 GNUNET_CONTAINER_multihashmap32_remove (vl->reassembly_map,
3102 rc->msg_uuid.uuid,
3103 rc));
3104 GNUNET_free (rc);
3105}
3106
3107
3108/**
3109 * Task run to clean up reassembly context of a neighbour that have expired.
3110 *
3111 * @param cls a `struct Neighbour`
3112 */
3113static void
3114reassembly_cleanup_task (void *cls)
3115{
3116 struct VirtualLink *vl = cls;
3117 struct ReassemblyContext *rc;
3118
3119 vl->reassembly_timeout_task = NULL;
3120 while (NULL != (rc = GNUNET_CONTAINER_heap_peek (vl->reassembly_heap)))
3121 {
3122 if (0 == GNUNET_TIME_absolute_get_remaining (rc->reassembly_timeout)
3123 .rel_value_us)
3124 {
3125 free_reassembly_context (rc);
3126 continue;
3127 }
3128 GNUNET_assert (NULL == vl->reassembly_timeout_task);
3129 vl->reassembly_timeout_task =
3130 GNUNET_SCHEDULER_add_at (rc->reassembly_timeout,
3131 &reassembly_cleanup_task,
3132 vl);
3133 return;
3134 }
3135}
3136
3137
3138/**
3139 * function called to #free_reassembly_context().
3140 *
3141 * @param cls NULL
3142 * @param key unused
3143 * @param value a `struct ReassemblyContext` to free
3144 * @return #GNUNET_OK (continue iteration)
3145 */
3146static int
3147free_reassembly_cb (void *cls, uint32_t key, void *value)
3148{
3149 struct ReassemblyContext *rc = value;
3150
3151 (void) cls;
3152 (void) key;
3153 free_reassembly_context (rc);
3154 return GNUNET_OK;
3155}
3156
3157
3158/**
3159 * Free virtual link.
3160 *
3161 * @param vl link data to free
3162 */
3163static void
3164free_virtual_link (struct VirtualLink *vl)
3165{
3166 struct PendingMessage *pm;
3167 struct CoreSentContext *csc;
3168
3169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3170 "free virtual link %p\n",
3171 vl);
3172
3173 if (NULL != vl->reassembly_map)
3174 {
3175 GNUNET_CONTAINER_multihashmap32_iterate (vl->reassembly_map,
3176 &free_reassembly_cb,
3177 NULL);
3178 GNUNET_CONTAINER_multihashmap32_destroy (vl->reassembly_map);
3179 vl->reassembly_map = NULL;
3180 GNUNET_CONTAINER_heap_destroy (vl->reassembly_heap);
3181 vl->reassembly_heap = NULL;
3182 }
3183 if (NULL != vl->reassembly_timeout_task)
3184 {
3185 GNUNET_SCHEDULER_cancel (vl->reassembly_timeout_task);
3186 vl->reassembly_timeout_task = NULL;
3187 }
3188 while (NULL != (pm = vl->pending_msg_head))
3189 free_pending_message (pm);
3190 GNUNET_assert (GNUNET_YES ==
3191 GNUNET_CONTAINER_multipeermap_remove (links, &vl->target, vl));
3192 if (NULL != vl->visibility_task)
3193 {
3194 GNUNET_SCHEDULER_cancel (vl->visibility_task);
3195 vl->visibility_task = NULL;
3196 }
3197 if (NULL != vl->fc_retransmit_task)
3198 {
3199 GNUNET_SCHEDULER_cancel (vl->fc_retransmit_task);
3200 vl->fc_retransmit_task = NULL;
3201 }
3202 while (NULL != (csc = vl->csc_head))
3203 {
3204 GNUNET_CONTAINER_DLL_remove (vl->csc_head, vl->csc_tail, csc);
3205 GNUNET_assert (vl == csc->vl);
3206 csc->vl = NULL;
3207 }
3208 GNUNET_break (NULL == vl->n);
3209 GNUNET_break (NULL == vl->dv);
3210 GNUNET_free (vl);
3211}
3212
3213
3214/**
3215 * Free validation state.
3216 *
3217 * @param vs validation state to free
3218 */
3219static void
3220free_validation_state (struct ValidationState *vs)
3221{
3222 GNUNET_assert (
3223 GNUNET_YES ==
3224 GNUNET_CONTAINER_multipeermap_remove (validation_map, &vs->pid, vs));
3225 GNUNET_CONTAINER_heap_remove_node (vs->hn);
3226 vs->hn = NULL;
3227 if (NULL != vs->sc)
3228 {
3229 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3230 "store cancel\n");
3231 GNUNET_PEERSTORE_store_cancel (vs->sc);
3232 vs->sc = NULL;
3233 }
3234 GNUNET_free (vs->address);
3235 GNUNET_free (vs);
3236}
3237
3238
3239/**
3240 * Lookup neighbour for peer @a pid.
3241 *
3242 * @param pid neighbour to look for
3243 * @return NULL if we do not have this peer as a neighbour
3244 */
3245static struct Neighbour *
3246lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
3247{
3248 return GNUNET_CONTAINER_multipeermap_get (neighbours, pid);
3249}
3250
3251
3252/**
3253 * Lookup virtual link for peer @a pid.
3254 *
3255 * @param pid virtual link to look for
3256 * @return NULL if we do not have this peer as a virtual link
3257 */
3258static struct VirtualLink *
3259lookup_virtual_link (const struct GNUNET_PeerIdentity *pid)
3260{
3261 return GNUNET_CONTAINER_multipeermap_get (links, pid);
3262}
3263
3264
3265/**
3266 * Details about what to notify monitors about.
3267 */
3268struct MonitorEvent
3269{
3270 /**
3271 * @deprecated To be discussed if we keep these...
3272 */
3273 struct GNUNET_TIME_Absolute last_validation;
3274 struct GNUNET_TIME_Absolute valid_until;
3275 struct GNUNET_TIME_Absolute next_validation;
3276
3277 /**
3278 * Current round-trip time estimate.
3279 */
3280 struct GNUNET_TIME_Relative rtt;
3281
3282 /**
3283 * Connection status.
3284 */
3285 enum GNUNET_TRANSPORT_ConnectionStatus cs;
3286
3287 /**
3288 * Messages pending.
3289 */
3290 uint32_t num_msg_pending;
3291
3292 /**
3293 * Bytes pending.
3294 */
3295 uint32_t num_bytes_pending;
3296};
3297
3298
3299/**
3300 * Free a @a dvh. Callers MAY want to check if this was the last path to the
3301 * `target`, and if so call #free_dv_route to also free the associated DV
3302 * entry in #dv_routes (if not, the associated scheduler job should eventually
3303 * take care of it).
3304 *
3305 * @param dvh hop to free
3306 */
3307static void
3308free_distance_vector_hop (struct DistanceVectorHop *dvh)
3309{
3310 struct Neighbour *n = dvh->next_hop;
3311 struct DistanceVector *dv = dvh->dv;
3312 struct PendingAcknowledgement *pa;
3313
3314 while (NULL != (pa = dvh->pa_head))
3315 {
3316 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
3317 pa->dvh = NULL;
3318 }
3319 GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh);
3320 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, dvh);
3321 GNUNET_free (dvh);
3322}
3323
3324
3325/**
3326 * Task run to check whether the hops of the @a cls still
3327 * are validated, or if we need to core about disconnection.
3328 *
3329 * @param cls a `struct VirtualLink`
3330 */
3331static void
3332check_link_down (void *cls);
3333
3334
3335/**
3336 * Send message to CORE clients that we lost a connection.
3337 *
3338 * @param pid peer the connection was for
3339 */
3340static void
3341cores_send_disconnect_info (const struct GNUNET_PeerIdentity *pid)
3342{
3343 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3344 "Informing CORE clients about disconnect from %s\n",
3345 GNUNET_i2s (pid));
3346 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3347 {
3348 struct GNUNET_MQ_Envelope *env;
3349 struct DisconnectInfoMessage *dim;
3350
3351 if (CT_CORE != tc->type)
3352 continue;
3353 env = GNUNET_MQ_msg (dim, GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
3354 dim->peer = *pid;
3355 GNUNET_MQ_send (tc->mq, env);
3356 }
3357}
3358
3359
3360/**
3361 * Free entry in #dv_routes. First frees all hops to the target, and
3362 * if there are no entries left, frees @a dv as well.
3363 *
3364 * @param dv route to free
3365 */
3366static void
3367free_dv_route (struct DistanceVector *dv)
3368{
3369 struct DistanceVectorHop *dvh;
3370
3371 while (NULL != (dvh = dv->dv_head))
3372 free_distance_vector_hop (dvh);
3373 if (NULL == dv->dv_head)
3374 {
3375 struct VirtualLink *vl;
3376
3377 GNUNET_assert (
3378 GNUNET_YES ==
3379 GNUNET_CONTAINER_multipeermap_remove (dv_routes, &dv->target, dv));
3380 if (NULL != (vl = dv->vl))
3381 {
3382 GNUNET_assert (dv == vl->dv);
3383 vl->dv = NULL;
3384 if (NULL == vl->n)
3385 {
3386 cores_send_disconnect_info (&dv->target);
3387 free_virtual_link (vl);
3388 }
3389 else
3390 {
3391 GNUNET_SCHEDULER_cancel (vl->visibility_task);
3392 vl->visibility_task = GNUNET_SCHEDULER_add_now (&check_link_down, vl);
3393 }
3394 dv->vl = NULL;
3395 }
3396
3397 if (NULL != dv->timeout_task)
3398 {
3399 GNUNET_SCHEDULER_cancel (dv->timeout_task);
3400 dv->timeout_task = NULL;
3401 }
3402 GNUNET_free (dv);
3403 }
3404}
3405
3406
3407/**
3408 * Notify monitor @a tc about an event. That @a tc
3409 * cares about the event has already been checked.
3410 *
3411 * Send @a tc information in @a me about a @a peer's status with
3412 * respect to some @a address to all monitors that care.
3413 *
3414 * @param tc monitor to inform
3415 * @param peer peer the information is about
3416 * @param address address the information is about
3417 * @param nt network type associated with @a address
3418 * @param me detailed information to transmit
3419 */
3420static void
3421notify_monitor (struct TransportClient *tc,
3422 const struct GNUNET_PeerIdentity *peer,
3423 const char *address,
3424 enum GNUNET_NetworkType nt,
3425 const struct MonitorEvent *me)
3426{
3427 struct GNUNET_MQ_Envelope *env;
3428 struct GNUNET_TRANSPORT_MonitorData *md;
3429 size_t addr_len = strlen (address) + 1;
3430
3431 env = GNUNET_MQ_msg_extra (md,
3432 addr_len,
3433 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA);
3434 md->nt = htonl ((uint32_t) nt);
3435 md->peer = *peer;
3436 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
3437 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
3438 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
3439 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
3440 md->cs = htonl ((uint32_t) me->cs);
3441 md->num_msg_pending = htonl (me->num_msg_pending);
3442 md->num_bytes_pending = htonl (me->num_bytes_pending);
3443 memcpy (&md[1], address, addr_len);
3444 GNUNET_MQ_send (tc->mq, env);
3445}
3446
3447
3448/**
3449 * Send information in @a me about a @a peer's status with respect
3450 * to some @a address to all monitors that care.
3451 *
3452 * @param peer peer the information is about
3453 * @param address address the information is about
3454 * @param nt network type associated with @a address
3455 * @param me detailed information to transmit
3456 */
3457static void
3458notify_monitors (const struct GNUNET_PeerIdentity *peer,
3459 const char *address,
3460 enum GNUNET_NetworkType nt,
3461 const struct MonitorEvent *me)
3462{
3463 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3464 {
3465 if (CT_MONITOR != tc->type)
3466 continue;
3467 if (tc->details.monitor.one_shot)
3468 continue;
3469 if ((GNUNET_NO == GNUNET_is_zero (&tc->details.monitor.peer)) &&
3470 (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
3471 continue;
3472 notify_monitor (tc, peer, address, nt, me);
3473 }
3474}
3475
3476
3477/**
3478 * Called whenever a client connects. Allocates our
3479 * data structures associated with that client.
3480 *
3481 * @param cls closure, NULL
3482 * @param client identification of the client
3483 * @param mq message queue for the client
3484 * @return our `struct TransportClient`
3485 */
3486static void *
3487client_connect_cb (void *cls,
3488 struct GNUNET_SERVICE_Client *client,
3489 struct GNUNET_MQ_Handle *mq)
3490{
3491 struct TransportClient *tc;
3492
3493 (void) cls;
3494 tc = GNUNET_new (struct TransportClient);
3495 tc->client = client;
3496 tc->mq = mq;
3497 GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, tc);
3498 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3499 "Client %p of type %u connected\n",
3500 tc,
3501 tc->type);
3502 return tc;
3503}
3504
3505
3506/**
3507 * Release memory used by @a neighbour.
3508 *
3509 * @param neighbour neighbour entry to free
3510 */
3511static void
3512free_neighbour (struct Neighbour *neighbour)
3513{
3514 struct DistanceVectorHop *dvh;
3515 struct VirtualLink *vl;
3516
3517 GNUNET_assert (NULL == neighbour->queue_head);
3518 GNUNET_assert (GNUNET_YES ==
3519 GNUNET_CONTAINER_multipeermap_remove (neighbours,
3520 &neighbour->pid,
3521 neighbour));
3522 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3523 "Freeing neighbour\n");
3524 while (NULL != (dvh = neighbour->dv_head))
3525 {
3526 struct DistanceVector *dv = dvh->dv;
3527
3528 free_distance_vector_hop (dvh);
3529 if (NULL == dv->dv_head)
3530 free_dv_route (dv);
3531 }
3532 if (NULL != neighbour->get)
3533 {
3534 GNUNET_PEERSTORE_iterate_cancel (neighbour->get);
3535 neighbour->get = NULL;
3536 }
3537 if (NULL != neighbour->sc)
3538 {
3539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3540 "store cancel\n");
3541 GNUNET_PEERSTORE_store_cancel (neighbour->sc);
3542 neighbour->sc = NULL;
3543 }
3544 if (NULL != (vl = neighbour->vl))
3545 {
3546 GNUNET_assert (neighbour == vl->n);
3547 vl->n = NULL;
3548 if (NULL == vl->dv)
3549 {
3550 cores_send_disconnect_info (&vl->target);
3551 free_virtual_link (vl);
3552 }
3553 else
3554 {
3555 GNUNET_SCHEDULER_cancel (vl->visibility_task);
3556 vl->visibility_task = GNUNET_SCHEDULER_add_now (&check_link_down, vl);
3557 }
3558 neighbour->vl = NULL;
3559 }
3560 GNUNET_free (neighbour);
3561}
3562
3563
3564/**
3565 * Send message to CORE clients that we lost a connection.
3566 *
3567 * @param tc client to inform (must be CORE client)
3568 * @param pid peer the connection is for
3569 */
3570static void
3571core_send_connect_info (struct TransportClient *tc,
3572 const struct GNUNET_PeerIdentity *pid)
3573{
3574 struct GNUNET_MQ_Envelope *env;
3575 struct ConnectInfoMessage *cim;
3576
3577 GNUNET_assert (CT_CORE == tc->type);
3578 env = GNUNET_MQ_msg (cim, GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
3579 cim->id = *pid;
3580 GNUNET_MQ_send (tc->mq, env);
3581}
3582
3583
3584/**
3585 * Send message to CORE clients that we gained a connection
3586 *
3587 * @param pid peer the queue was for
3588 */
3589static void
3590cores_send_connect_info (const struct GNUNET_PeerIdentity *pid)
3591{
3592 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3593 "Informing CORE clients about connection to %s\n",
3594 GNUNET_i2s (pid));
3595 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3596 {
3597 if (CT_CORE != tc->type)
3598 continue;
3599 core_send_connect_info (tc, pid);
3600 }
3601}
3602
3603
3604/**
3605 * We believe we are ready to transmit a message on a queue. Gives the
3606 * message to the communicator for transmission (updating the tracker,
3607 * and re-scheduling itself if applicable).
3608 *
3609 * @param cls the `struct Queue` to process transmissions for
3610 */
3611static void
3612transmit_on_queue (void *cls);
3613
3614
3615/**
3616 * Check if the communicator has another queue with higher prio ready for sending.
3617 */
3618static unsigned int
3619check_for_queue_with_higher_prio (struct Queue *queue, struct Queue *queue_head)
3620{
3621 for (struct Queue *s = queue_head; NULL != s;
3622 s = s->next_client)
3623 {
3624 if (s->tc->details.communicator.address_prefix !=
3625 queue->tc->details.communicator.address_prefix)
3626 {
3627 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3628 "queue address %s qid %u compare with queue: address %s qid %u\n",
3629 queue->address,
3630 queue->qid,
3631 s->address,
3632 s->qid);
3633 if ((s->priority > queue->priority) && (0 < s->q_capacity) &&
3634 (QUEUE_LENGTH_LIMIT > s->queue_length) )
3635 return GNUNET_YES;
3636 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3637 "Lower prio\n");
3638 }
3639 }
3640 return GNUNET_NO;
3641}
3642
3643
3644/**
3645 * Called whenever something changed that might effect when we
3646 * try to do the next transmission on @a queue using #transmit_on_queue().
3647 *
3648 * @param queue the queue to do scheduling for
3649 * @param p task priority to use, if @a queue is scheduled
3650 */
3651static void
3652schedule_transmit_on_queue (struct GNUNET_TIME_Relative delay,
3653 struct Queue *queue,
3654 enum GNUNET_SCHEDULER_Priority p)
3655{
3656 if (check_for_queue_with_higher_prio (queue,
3657 queue->tc->details.communicator.
3658 queue_head))
3659 return;
3660
3661 if (queue->tc->details.communicator.total_queue_length >=
3662 COMMUNICATOR_TOTAL_QUEUE_LIMIT)
3663 {
3664 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3665 "Transmission throttled due to communicator queue limit\n");
3666 GNUNET_STATISTICS_update (
3667 GST_stats,
3668 "# Transmission throttled due to communicator queue limit",
3669 1,
3670 GNUNET_NO);
3671 queue->idle = GNUNET_NO;
3672 return;
3673 }
3674 if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
3675 {
3676 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3677 "Transmission throttled due to communicator queue length limit\n");
3678 GNUNET_STATISTICS_update (GST_stats,
3679 "# Transmission throttled due to queue queue limit",
3680 1,
3681 GNUNET_NO);
3682 queue->idle = GNUNET_NO;
3683 return;
3684 }
3685 if (0 == queue->q_capacity)
3686 {
3687 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3688 "Transmission throttled due to communicator message queue qid %u has capacity %"
3689 PRIu64 ".\n",
3690 queue->qid,
3691 queue->q_capacity);
3692 GNUNET_STATISTICS_update (GST_stats,
3693 "# Transmission throttled due to message queue capacity",
3694 1,
3695 GNUNET_NO);
3696 queue->idle = GNUNET_NO;
3697 return;
3698 }
3699 /* queue might indeed be ready, schedule it */
3700 if (NULL != queue->transmit_task)
3701 GNUNET_SCHEDULER_cancel (queue->transmit_task);
3702 queue->transmit_task =
3703 GNUNET_SCHEDULER_add_delayed_with_priority (delay, p, &transmit_on_queue,
3704 queue);
3705 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3706 "Considering transmission on queue `%s' QID %llu to %s\n",
3707 queue->address,
3708 (unsigned long long) queue->qid,
3709 GNUNET_i2s (&queue->neighbour->pid));
3710}
3711
3712
3713/**
3714 * Task run to check whether the hops of the @a cls still
3715 * are validated, or if we need to core about disconnection.
3716 *
3717 * @param cls a `struct VirtualLink`
3718 */
3719static void
3720check_link_down (void *cls)
3721{
3722 struct VirtualLink *vl = cls;
3723 struct DistanceVector *dv = vl->dv;
3724 struct Neighbour *n = vl->n;
3725 struct GNUNET_TIME_Absolute dvh_timeout;
3726 struct GNUNET_TIME_Absolute q_timeout;
3727
3728 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3729 "Checking if link is down\n");
3730 vl->visibility_task = NULL;
3731 dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3732 if (NULL != dv)
3733 {
3734 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3735 pos = pos->next_dv)
3736 dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout,
3737 pos->path_valid_until);
3738 if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
3739 {
3740 vl->dv->vl = NULL;
3741 vl->dv = NULL;
3742 }
3743 }
3744 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3745 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
3746 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
3747 if (0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
3748 {
3749 vl->n->vl = NULL;
3750 vl->n = NULL;
3751 }
3752 if ((NULL == vl->n) && (NULL == vl->dv))
3753 {
3754 cores_send_disconnect_info (&vl->target);
3755 free_virtual_link (vl);
3756 return;
3757 }
3758 vl->visibility_task =
3759 GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
3760 &check_link_down,
3761 vl);
3762}
3763
3764
3765/**
3766 * Free @a queue.
3767 *
3768 * @param queue the queue to free
3769 */
3770static void
3771free_queue (struct Queue *queue)
3772{
3773 struct Neighbour *neighbour = queue->neighbour;
3774 struct TransportClient *tc = queue->tc;
3775 struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
3776 .rtt = GNUNET_TIME_UNIT_FOREVER_REL };
3777 struct QueueEntry *qe;
3778 int maxxed;
3779 struct PendingAcknowledgement *pa;
3780 struct VirtualLink *vl;
3781
3782 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3783 "Cleaning up queue %u\n", queue->qid);
3784 if (NULL != queue->transmit_task)
3785 {
3786 GNUNET_SCHEDULER_cancel (queue->transmit_task);
3787 queue->transmit_task = NULL;
3788 }
3789 while (NULL != (pa = queue->pa_head))
3790 {
3791 GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
3792 pa->queue = NULL;
3793 }
3794
3795 GNUNET_CONTAINER_MDLL_remove (neighbour,
3796 neighbour->queue_head,
3797 neighbour->queue_tail,
3798 queue);
3799 GNUNET_CONTAINER_MDLL_remove (client,
3800 tc->details.communicator.queue_head,
3801 tc->details.communicator.queue_tail,
3802 queue);
3803 maxxed = (COMMUNICATOR_TOTAL_QUEUE_LIMIT <=
3804 tc->details.communicator.
3805 total_queue_length);
3806 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3807 "Cleaning up queue with length %u\n",
3808 queue->queue_length);
3809 while (NULL != (qe = queue->queue_head))
3810 {
3811 GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
3812 queue->queue_length--;
3813 tc->details.communicator.total_queue_length--;
3814 if (NULL != qe->pm)
3815 {
3816 GNUNET_assert (qe == qe->pm->qe);
3817 qe->pm->qe = NULL;
3818 }
3819 GNUNET_free (qe);
3820 }
3821 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3822 "Cleaning up queue with length %u\n",
3823 queue->queue_length);
3824 GNUNET_assert (0 == queue->queue_length);
3825 if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT >
3826 tc->details.communicator.total_queue_length))
3827 {
3828 /* Communicator dropped below threshold, resume all _other_ queues */
3829 GNUNET_STATISTICS_update (
3830 GST_stats,
3831 "# Transmission throttled due to communicator queue limit",
3832 -1,
3833 GNUNET_NO);
3834 for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
3835 s = s->next_client)
3836 schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
3837 s,
3838 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
3839 }
3840 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
3841 GNUNET_free (queue);
3842
3843 vl = lookup_virtual_link (&neighbour->pid);
3844 if ((NULL != vl) && (neighbour == vl->n))
3845 {
3846 GNUNET_SCHEDULER_cancel (vl->visibility_task);
3847 check_link_down (vl);
3848 }
3849 if (NULL == neighbour->queue_head)
3850 {
3851 free_neighbour (neighbour);
3852 }
3853}
3854
3855
3856/**
3857 * Free @a ale
3858 *
3859 * @param ale address list entry to free
3860 */
3861static void
3862free_address_list_entry (struct AddressListEntry *ale)
3863{
3864 struct TransportClient *tc = ale->tc;
3865
3866 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
3867 tc->details.communicator.addr_tail,
3868 ale);
3869 if (NULL != ale->sc)
3870 {
3871 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3872 "store cancel\n");
3873 GNUNET_PEERSTORE_store_cancel (ale->sc);
3874 ale->sc = NULL;
3875 }
3876 if (NULL != ale->st)
3877 {
3878 GNUNET_SCHEDULER_cancel (ale->st);
3879 ale->st = NULL;
3880 }
3881 GNUNET_free (ale);
3882}
3883
3884
3885/**
3886 * Stop the peer request in @a value.
3887 *
3888 * @param cls a `struct TransportClient` that no longer makes the request
3889 * @param pid the peer's identity
3890 * @param value a `struct PeerRequest`
3891 * @return #GNUNET_YES (always)
3892 */
3893static int
3894stop_peer_request (void *cls,
3895 const struct GNUNET_PeerIdentity *pid,
3896 void *value)
3897{
3898 struct TransportClient *tc = cls;
3899 struct PeerRequest *pr = value;
3900
3901 GNUNET_PEERSTORE_hello_changed_notify_cancel (pr->nc);
3902 pr->nc = NULL;
3903 GNUNET_assert (
3904 GNUNET_YES ==
3905 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
3906 pid,
3907 pr));
3908 GNUNET_free (pr);
3909
3910 return GNUNET_OK;
3911}
3912
3913
3914static void
3915do_shutdown (void *cls);
3916
3917/**
3918 * Called whenever a client is disconnected. Frees our
3919 * resources associated with that client.
3920 *
3921 * @param cls closure, NULL
3922 * @param client identification of the client
3923 * @param app_ctx our `struct TransportClient`
3924 */
3925static void
3926client_disconnect_cb (void *cls,
3927 struct GNUNET_SERVICE_Client *client,
3928 void *app_ctx)
3929{
3930 struct TransportClient *tc = app_ctx;
3931
3932 (void) cls;
3933 (void) client;
3934 GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, tc);
3935 switch (tc->type)
3936 {
3937 case CT_NONE:
3938 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3939 "Unknown Client %p disconnected, cleaning up.\n",
3940 tc);
3941 break;
3942
3943 case CT_CORE: {
3944 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3945 "CORE Client %p disconnected, cleaning up.\n",
3946 tc);
3947
3948 struct PendingMessage *pm;
3949
3950 while (NULL != (pm = tc->details.core.pending_msg_head))
3951 {
3952 GNUNET_CONTAINER_MDLL_remove (client,
3953 tc->details.core.pending_msg_head,
3954 tc->details.core.pending_msg_tail,
3955 pm);
3956 pm->client = NULL;
3957 }
3958 }
3959 break;
3960
3961 case CT_MONITOR:
3962 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3963 "MONITOR Client %p disconnected, cleaning up.\n",
3964 tc);
3965
3966 break;
3967
3968 case CT_COMMUNICATOR: {
3969 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3970 "COMMUNICATOR Client %p disconnected, cleaning up.\n",
3971 tc);
3972
3973 struct Queue *q;
3974 struct AddressListEntry *ale;
3975
3976 while (NULL != (q = tc->details.communicator.queue_head))
3977 free_queue (q);
3978 while (NULL != (ale = tc->details.communicator.addr_head))
3979 free_address_list_entry (ale);
3980 GNUNET_free (tc->details.communicator.address_prefix);
3981 }
3982 break;
3983
3984 case CT_APPLICATION:
3985 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3986 "APPLICATION Client %p disconnected, cleaning up.\n",
3987 tc);
3988
3989 GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests,
3990 &stop_peer_request,
3991 tc);
3992 GNUNET_CONTAINER_multipeermap_destroy (tc->details.application.requests);
3993 break;
3994 }
3995 GNUNET_free (tc);
3996 if ((GNUNET_YES == in_shutdown) && (NULL == clients_head))
3997 {
3998 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3999 "Our last client disconnected\n");
4000 do_shutdown (cls);
4001 }
4002}
4003
4004
4005/**
4006 * Iterator telling new CORE client about all existing
4007 * connections to peers.
4008 *
4009 * @param cls the new `struct TransportClient`
4010 * @param pid a connected peer
4011 * @param value the `struct Neighbour` with more information
4012 * @return #GNUNET_OK (continue to iterate)
4013 */
4014static int
4015notify_client_connect_info (void *cls,
4016 const struct GNUNET_PeerIdentity *pid,
4017 void *value)
4018{
4019 struct TransportClient *tc = cls;
4020 struct Neighbour *n = value;
4021 struct VirtualLink *vl = n->vl;
4022
4023 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4024 return GNUNET_OK;
4025
4026 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4027 "Telling new CORE client about existing connection to %s\n",
4028 GNUNET_i2s (pid));
4029 core_send_connect_info (tc, pid);
4030 return GNUNET_OK;
4031}
4032
4033
4034/**
4035 * Initialize a "CORE" client. We got a start message from this
4036 * client, so add it to the list of clients for broadcasting of
4037 * inbound messages.
4038 *
4039 * @param cls the client
4040 * @param start the start message that was sent
4041 */
4042static void
4043handle_client_start (void *cls, const struct StartMessage *start)
4044{
4045 struct TransportClient *tc = cls;
4046 uint32_t options;
4047
4048 options = ntohl (start->options);
4049 if ((0 != (1 & options)) &&
4050 (0 != GNUNET_memcmp (&start->self, &GST_my_identity)))
4051 {
4052 /* client thinks this is a different peer, reject */
4053 GNUNET_break (0);
4054 GNUNET_SERVICE_client_drop (tc->client);
4055 return;
4056 }
4057 if (CT_NONE != tc->type)
4058 {
4059 GNUNET_break (0);
4060 GNUNET_SERVICE_client_drop (tc->client);
4061 return;
4062 }
4063 tc->type = CT_CORE;
4064 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4065 "New CORE client with PID %s registered\n",
4066 GNUNET_i2s (&start->self));
4067 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
4068 &notify_client_connect_info,
4069 tc);
4070 GNUNET_SERVICE_client_continue (tc->client);
4071}
4072
4073
4074/**
4075 * Client asked for transmission to a peer. Process the request.
4076 *
4077 * @param cls the client
4078 * @param obm the send message that was sent
4079 */
4080static int
4081check_client_send (void *cls, const struct OutboundMessage *obm)
4082{
4083 struct TransportClient *tc = cls;
4084 uint16_t size;
4085 const struct GNUNET_MessageHeader *obmm;
4086
4087 if (CT_CORE != tc->type)
4088 {
4089 GNUNET_break (0);
4090 return GNUNET_SYSERR;
4091 }
4092 size = ntohs (obm->header.size) - sizeof(struct OutboundMessage);
4093 if (size < sizeof(struct GNUNET_MessageHeader))
4094 {
4095 GNUNET_break (0);
4096 return GNUNET_SYSERR;
4097 }
4098 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
4099 if (size != ntohs (obmm->size))
4100 {
4101 GNUNET_break (0);
4102 return GNUNET_SYSERR;
4103 }
4104 return GNUNET_OK;
4105}
4106
4107
4108/**
4109 * Send a response to the @a pm that we have processed a "send"
4110 * request. Sends a confirmation to the "core" client responsible for
4111 * the original request and free's @a pm.
4112 *
4113 * @param pm handle to the original pending message
4114 */
4115static void
4116client_send_response (struct PendingMessage *pm)
4117{
4118 struct TransportClient *tc = pm->client;
4119 struct VirtualLink *vl = pm->vl;
4120
4121 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4122 "client send response\n");
4123 if (NULL != tc)
4124 {
4125 struct GNUNET_MQ_Envelope *env;
4126 struct SendOkMessage *so_msg;
4127
4128 env = GNUNET_MQ_msg (so_msg, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
4129 so_msg->peer = vl->target;
4130 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4131 "Confirming transmission of <%llu> to %s\n",
4132 pm->logging_uuid,
4133 GNUNET_i2s (&vl->target));
4134 GNUNET_MQ_send (tc->mq, env);
4135 }
4136 free_pending_message (pm);
4137}
4138
4139
4140/**
4141 * Pick @a hops_array_length random DV paths satisfying @a options
4142 *
4143 * @param dv data structure to pick paths from
4144 * @param options constraints to satisfy
4145 * @param[out] hops_array set to the result
4146 * @param hops_array_length length of the @a hops_array
4147 * @return number of entries set in @a hops_array
4148 */
4149static unsigned int
4150pick_random_dv_hops (const struct DistanceVector *dv,
4151 enum RouteMessageOptions options,
4152 struct DistanceVectorHop **hops_array,
4153 unsigned int hops_array_length)
4154{
4155 uint64_t choices[hops_array_length];
4156 uint64_t num_dv;
4157 unsigned int dv_count;
4158
4159 /* Pick random vectors, but weighted by distance, giving more weight
4160 to shorter vectors */
4161 num_dv = 0;
4162 dv_count = 0;
4163 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4164 pos = pos->next_dv)
4165 {
4166 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4167 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4168 .rel_value_us == 0))
4169 continue; /* pos unconfirmed and confirmed required */
4170 num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
4171 dv_count++;
4172 }
4173 if (0 == dv_count)
4174 return 0;
4175 if (dv_count <= hops_array_length)
4176 {
4177 dv_count = 0;
4178 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4179 pos = pos->next_dv)
4180 hops_array[dv_count++] = pos;
4181 return dv_count;
4182 }
4183 for (unsigned int i = 0; i < hops_array_length; i++)
4184 {
4185 int ok = GNUNET_NO;
4186 while (GNUNET_NO == ok)
4187 {
4188 choices[i] =
4189 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, num_dv);
4190 ok = GNUNET_YES;
4191 for (unsigned int j = 0; j < i; j++)
4192 if (choices[i] == choices[j])
4193 {
4194 ok = GNUNET_NO;
4195 break;
4196 }
4197 }
4198 }
4199 dv_count = 0;
4200 num_dv = 0;
4201 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4202 pos = pos->next_dv)
4203 {
4204 uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
4205
4206 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4207 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4208 .rel_value_us == 0))
4209 continue; /* pos unconfirmed and confirmed required */
4210 for (unsigned int i = 0; i < hops_array_length; i++)
4211 if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
4212 hops_array[dv_count++] = pos;
4213 num_dv += delta;
4214 }
4215 return dv_count;
4216}
4217
4218
4219/**
4220 * Communicator started. Test message is well-formed.
4221 *
4222 * @param cls the client
4223 * @param cam the send message that was sent
4224 */
4225static int
4226check_communicator_available (
4227 void *cls,
4228 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
4229{
4230 struct TransportClient *tc = cls;
4231 uint16_t size;
4232
4233 if (CT_NONE != tc->type)
4234 {
4235 GNUNET_break (0);
4236 return GNUNET_SYSERR;
4237 }
4238 tc->type = CT_COMMUNICATOR;
4239 size = ntohs (cam->header.size) - sizeof(*cam);
4240 if (0 == size)
4241 return GNUNET_OK; /* receive-only communicator */
4242 GNUNET_MQ_check_zero_termination (cam);
4243 return GNUNET_OK;
4244}
4245
4246
4247/**
4248 * Send ACK to communicator (if requested) and free @a cmc.
4249 *
4250 * @param cmc context for which we are done handling the message
4251 */
4252static void
4253finish_cmc_handling_with_continue (struct CommunicatorMessageContext *cmc,
4254 unsigned
4255 int continue_client)
4256{
4257 if (0 != ntohl (cmc->im.fc_on))
4258 {
4259 /* send ACK when done to communicator for flow control! */
4260 struct GNUNET_MQ_Envelope *env;
4261 struct GNUNET_TRANSPORT_IncomingMessageAck *ack;
4262
4263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4264 "Acknowledge message with flow control id %" PRIu64 "\n",
4265 cmc->im.fc_id);
4266 env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK);
4267 ack->reserved = htonl (0);
4268 ack->fc_id = cmc->im.fc_id;
4269 ack->sender = cmc->im.neighbour_sender;
4270 GNUNET_MQ_send (cmc->tc->mq, env);
4271 }
4272
4273 if (GNUNET_YES == continue_client)
4274 {
4275 GNUNET_SERVICE_client_continue (cmc->tc->client);
4276 }
4277 GNUNET_free (cmc);
4278}
4279
4280
4281static void
4282finish_cmc_handling (struct CommunicatorMessageContext *cmc)
4283{
4284 finish_cmc_handling_with_continue (cmc, GNUNET_YES);
4285}
4286
4287
4288/**
4289 * Client confirms that it is done handling message(s) to a particular
4290 * peer. We may now provide more messages to CORE for this peer.
4291 *
4292 * Notifies the respective queues that more messages can now be received.
4293 *
4294 * @param cls the client
4295 * @param rom the message that was sent
4296 */
4297static void
4298handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
4299{
4300 struct TransportClient *tc = cls;
4301 struct VirtualLink *vl;
4302 uint32_t delta;
4303 struct CommunicatorMessageContext *cmc;
4304
4305 if (CT_CORE != tc->type)
4306 {
4307 GNUNET_break (0);
4308 GNUNET_SERVICE_client_drop (tc->client);
4309 return;
4310 }
4311 vl = lookup_virtual_link (&rom->peer);
4312 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4313 {
4314 GNUNET_STATISTICS_update (GST_stats,
4315 "# RECV_OK dropped: virtual link unknown",
4316 1,
4317 GNUNET_NO);
4318 GNUNET_SERVICE_client_continue (tc->client);
4319 return;
4320 }
4321 delta = ntohl (rom->increase_window_delta);
4322 vl->core_recv_window += delta;
4323 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4324 "CORE ack receiving message, increased CORE recv window to %d\n",
4325 vl->core_recv_window);
4326 GNUNET_SERVICE_client_continue (tc->client);
4327 if (vl->core_recv_window <= 0)
4328 return;
4329 /* resume communicators */
4330 while (NULL != (cmc = vl->cmc_tail))
4331 {
4332 GNUNET_CONTAINER_DLL_remove (vl->cmc_head, vl->cmc_tail, cmc);
4333 finish_cmc_handling (cmc);
4334 }
4335}
4336
4337
4338/**
4339 * Communicator started. Process the request.
4340 *
4341 * @param cls the client
4342 * @param cam the send message that was sent
4343 */
4344static void
4345handle_communicator_available (
4346 void *cls,
4347 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
4348{
4349 struct TransportClient *tc = cls;
4350 uint16_t size;
4351
4352 size = ntohs (cam->header.size) - sizeof(*cam);
4353 if (0 == size)
4354 {
4355 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4356 "Receive-only communicator connected\n");
4357 return; /* receive-only communicator */
4358 }
4359 tc->details.communicator.address_prefix =
4360 GNUNET_strdup ((const char *) &cam[1]);
4361 tc->details.communicator.cc =
4362 (enum GNUNET_TRANSPORT_CommunicatorCharacteristics) ntohl (cam->cc);
4363 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4364 "Communicator with prefix `%s' connected\n",
4365 tc->details.communicator.address_prefix);
4366 GNUNET_SERVICE_client_continue (tc->client);
4367}
4368
4369
4370/**
4371 * Communicator requests backchannel transmission. Check the request.
4372 *
4373 * @param cls the client
4374 * @param cb the send message that was sent
4375 * @return #GNUNET_OK if message is well-formed
4376 */
4377static int
4378check_communicator_backchannel (
4379 void *cls,
4380 const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
4381{
4382 const struct GNUNET_MessageHeader *inbox;
4383 const char *is;
4384 uint16_t msize;
4385 uint16_t isize;
4386
4387 (void) cls;
4388 msize = ntohs (cb->header.size) - sizeof(*cb);
4389 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
4390 isize = ntohs (inbox->size);
4391 if (isize >= msize)
4392 {
4393 GNUNET_break (0);
4394 return GNUNET_SYSERR;
4395 }
4396 is = (const char *) inbox;
4397 is += isize;
4398 msize -= isize;
4399 GNUNET_assert (0 < msize);
4400 if ('\0' != is[msize - 1])
4401 {
4402 GNUNET_break (0);
4403 return GNUNET_SYSERR;
4404 }
4405 return GNUNET_OK;
4406}
4407
4408
4409/**
4410 * Sign ephemeral keys in our @a dv are current.
4411 *
4412 * @param[in,out] dv virtual link to update ephemeral for
4413 */
4414static void
4415sign_ephemeral (struct DistanceVector *dv)
4416{
4417 struct EphemeralConfirmationPS ec;
4418
4419 dv->monotime = GNUNET_TIME_absolute_get_monotonic (GST_cfg);
4420 dv->ephemeral_validity =
4421 GNUNET_TIME_absolute_add (dv->monotime, EPHEMERAL_VALIDITY);
4422 ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
4423 ec.target = dv->target;
4424 ec.ephemeral_key = dv->ephemeral_key;
4425 ec.sender_monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
4426 ec.purpose.size = htonl (sizeof(ec));
4427 GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
4428 &ec,
4429 &dv->sender_sig);
4430}
4431
4432
4433/**
4434 * Send the message @a payload on @a queue.
4435 *
4436 * @param queue the queue to use for transmission
4437 * @param pm pending message to update once transmission is done, may be NULL!
4438 * @param payload the payload to send (encapsulated in a
4439 * #GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG).
4440 * @param payload_size number of bytes in @a payload
4441 */
4442static void
4443queue_send_msg (struct Queue *queue,
4444 struct PendingMessage *pm,
4445 const void *payload,
4446 size_t payload_size)
4447{
4448 struct Neighbour *n = queue->neighbour;
4449 struct GNUNET_TRANSPORT_SendMessageTo *smt;
4450 struct GNUNET_MQ_Envelope *env;
4451 struct PendingAcknowledgement *pa;
4452
4453 GNUNET_log (
4454 GNUNET_ERROR_TYPE_DEBUG,
4455 "Queueing %u bytes of payload for transmission <%llu> on queue %llu to %s\n",
4456 (unsigned int) payload_size,
4457 (NULL == pm) ? 0 : pm->logging_uuid,
4458 (unsigned long long) queue->qid,
4459 GNUNET_i2s (&queue->neighbour->pid));
4460 env = GNUNET_MQ_msg_extra (smt,
4461 payload_size,
4462 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG);
4463 smt->qid = htonl (queue->qid);
4464 smt->mid = GNUNET_htonll (queue->mid_gen);
4465 smt->receiver = n->pid;
4466 memcpy (&smt[1], payload, payload_size);
4467 {
4468 /* Pass the env to the communicator of queue for transmission. */
4469 struct QueueEntry *qe;
4470
4471 qe = GNUNET_new (struct QueueEntry);
4472 qe->mid = queue->mid_gen;
4473 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4474 "Create QueueEntry with MID %" PRIu64
4475 " and QID %u and prefix %s\n",
4476 qe->mid,
4477 queue->qid,
4478 queue->tc->details.communicator.address_prefix);
4479 queue->mid_gen++;
4480 qe->queue = queue;
4481 if (NULL != pm)
4482 {
4483 qe->pm = pm;
4484 // TODO Why do we have a retransmission. When we know, make decision if we still want this.
4485 // GNUNET_assert (NULL == pm->qe);
4486 if (NULL != pm->qe)
4487 {
4488 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4489 "Retransmitting message <%llu> remove pm from qe with MID: %llu \n",
4490 pm->logging_uuid,
4491 (unsigned long long) pm->qe->mid);
4492 pm->qe->pm = NULL;
4493 }
4494 pm->qe = qe;
4495 }
4496 GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
4497 GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
4498 if (0 == queue->q_capacity)
4499 {
4500 // Messages without FC or fragments can get here.
4501 if (NULL != pm)
4502 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4503 "Message %llu (pm type %u) was not send because queue has no capacity.\n",
4504 pm->logging_uuid,
4505 pm->pmt);
4506 GNUNET_free (env);
4507 return;
4508 }
4509 queue->queue_length++;
4510 queue->tc->details.communicator.total_queue_length++;
4511 if (GNUNET_NO == queue->unlimited_length)
4512 queue->q_capacity--;
4513 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4514 "Queue %s with qid %u has capacity %" PRIu64 "\n",
4515 queue->address,
4516 queue->qid,
4517 queue->q_capacity);
4518 if (COMMUNICATOR_TOTAL_QUEUE_LIMIT ==
4519 queue->tc->details.communicator.total_queue_length)
4520 queue->idle = GNUNET_NO;
4521 if (QUEUE_LENGTH_LIMIT == queue->queue_length)
4522 queue->idle = GNUNET_NO;
4523 if (0 == queue->q_capacity)
4524 queue->idle = GNUNET_NO;
4525
4526 if (NULL != pm && NULL != (pa = pm->pa_head))
4527 {
4528 while (pm != pa->pm)
4529 pa = pa->next_pa;
4530 pa->num_send++;
4531 }
4532 // GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
4533 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4534 "Sending message MID %" PRIu64
4535 " of type %u (%u) and size %lu with MQ %p QID %u\n",
4536 GNUNET_ntohll (smt->mid),
4537 ntohs (((const struct GNUNET_MessageHeader *) payload)->type),
4538 ntohs (smt->header.size),
4539 (unsigned long) payload_size,
4540 queue->tc->mq,
4541 queue->qid);
4542 GNUNET_MQ_send (queue->tc->mq, env);
4543 }
4544}
4545
4546
4547/**
4548 * Pick a queue of @a n under constraints @a options and schedule
4549 * transmission of @a hdr.
4550 *
4551 * @param n neighbour to send to
4552 * @param hdr message to send as payload
4553 * @param options whether queues must be confirmed or not,
4554 * and whether we may pick multiple (2) queues
4555 * @return expected RTT for transmission, #GNUNET_TIME_UNIT_FOREVER_REL if sending failed
4556 */
4557static struct GNUNET_TIME_Relative
4558route_via_neighbour (const struct Neighbour *n,
4559 const struct GNUNET_MessageHeader *hdr,
4560 enum RouteMessageOptions options)
4561{
4562 struct GNUNET_TIME_Absolute now;
4563 unsigned int candidates;
4564 unsigned int sel1;
4565 unsigned int sel2;
4566 struct GNUNET_TIME_Relative rtt;
4567
4568 /* Pick one or two 'random' queues from n (under constraints of options) */
4569 now = GNUNET_TIME_absolute_get ();
4570 /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
4571 weight in the future; weight could be assigned by observed
4572 bandwidth (note: not sure if we should do this for this type
4573 of control traffic though). */
4574 candidates = 0;
4575 for (struct Queue *pos = n->queue_head; NULL != pos;
4576 pos = pos->next_neighbour)
4577 {
4578 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
4579 (pos->validated_until.abs_value_us > now.abs_value_us))
4580 candidates++;
4581 }
4582 if (0 == candidates)
4583 {
4584 /* This can happen rarely if the last confirmed queue timed
4585 out just as we were beginning to process this message. */
4586 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4587 "Could not route message of type %u to %s: no valid queue\n",
4588 ntohs (hdr->type),
4589 GNUNET_i2s (&n->pid));
4590 GNUNET_STATISTICS_update (GST_stats,
4591 "# route selection failed (all no valid queue)",
4592 1,
4593 GNUNET_NO);
4594 return GNUNET_TIME_UNIT_FOREVER_REL;
4595 }
4596
4597 rtt = GNUNET_TIME_UNIT_FOREVER_REL;
4598 sel1 = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, candidates);
4599 if (0 == (options & RMO_REDUNDANT))
4600 sel2 = candidates; /* picks none! */
4601 else
4602 sel2 = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, candidates);
4603 candidates = 0;
4604 for (struct Queue *pos = n->queue_head; NULL != pos;
4605 pos = pos->next_neighbour)
4606 {
4607 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
4608 (pos->validated_until.abs_value_us > now.abs_value_us))
4609 {
4610 if ((sel1 == candidates) || (sel2 == candidates))
4611 {
4612 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4613 "Routing message of type %u to %s using %s (#%u)\n",
4614 ntohs (hdr->type),
4615 GNUNET_i2s (&n->pid),
4616 pos->address,
4617 (sel1 == candidates) ? 1 : 2);
4618 rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
4619 queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
4620 }
4621 candidates++;
4622 }
4623 }
4624 return rtt;
4625}
4626
4627
4628/**
4629 * Structure of the key material used to encrypt backchannel messages.
4630 */
4631struct DVKeyState
4632{
4633 /**
4634 * State of our block cipher.
4635 */
4636 gcry_cipher_hd_t cipher;
4637
4638 /**
4639 * Actual key material.
4640 */
4641 struct
4642 {
4643 /**
4644 * Key used for HMAC calculations (via #GNUNET_CRYPTO_hmac()).
4645 */
4646 struct GNUNET_CRYPTO_AuthKey hmac_key;
4647
4648 /**
4649 * Symmetric key to use for encryption.
4650 */
4651 char aes_key[256 / 8];
4652
4653 /**
4654 * Counter value to use during setup.
4655 */
4656 char aes_ctr[128 / 8];
4657 } material;
4658};
4659
4660
4661/**
4662 * Given the key material in @a km and the initialization vector
4663 * @a iv, setup the key material for the backchannel in @a key.
4664 *
4665 * @param km raw master secret
4666 * @param iv initialization vector
4667 * @param[out] key symmetric cipher and HMAC state to generate
4668 */
4669static void
4670dv_setup_key_state_from_km (const struct GNUNET_HashCode *km,
4671 const struct GNUNET_ShortHashCode *iv,
4672 struct DVKeyState *key)
4673{
4674 /* must match what we defive from decapsulated key */
4675 GNUNET_assert (GNUNET_YES ==
4676 GNUNET_CRYPTO_kdf (&key->material,
4677 sizeof(key->material),
4678 "transport-backchannel-key",
4679 strlen ("transport-backchannel-key"),
4680 km,
4681 sizeof(*km),
4682 iv,
4683 sizeof(*iv),
4684 NULL));
4685 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4686 "Deriving backchannel key based on KM %s and IV %s\n",
4687 GNUNET_h2s (km),
4688 GNUNET_sh2s (iv));
4689 GNUNET_assert (0 == gcry_cipher_open (&key->cipher,
4690 GCRY_CIPHER_AES256 /* low level: go for speed */,
4691 GCRY_CIPHER_MODE_CTR,
4692 0 /* flags */));
4693 GNUNET_assert (0 == gcry_cipher_setkey (key->cipher,
4694 &key->material.aes_key,
4695 sizeof(key->material.aes_key)));
4696 gcry_cipher_setctr (key->cipher,
4697 &key->material.aes_ctr,
4698 sizeof(key->material.aes_ctr));
4699}
4700
4701
4702/**
4703 * Do HMAC calculation for backchannel messages over @a data using key
4704 * material from @a key.
4705 *
4706 * @param key key material (from DH)
4707 * @param[out] hmac set to the HMAC
4708 * @param data data to perform HMAC calculation over
4709 * @param data_size number of bytes in @a data
4710 */
4711static void
4712dv_hmac (const struct DVKeyState *key,
4713 struct GNUNET_HashCode *hmac,
4714 const void *data,
4715 size_t data_size)
4716{
4717 GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
4718}
4719
4720
4721/**
4722 * Perform backchannel encryption using symmetric secret in @a key
4723 * to encrypt data from @a in to @a dst.
4724 *
4725 * @param[in,out] key key material to use
4726 * @param dst where to write the result
4727 * @param in input data to encrypt (plaintext)
4728 * @param in_size number of bytes of input in @a in and available at @a dst
4729 */
4730static void
4731dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
4732{
4733 GNUNET_assert (0 ==
4734 gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
4735}
4736
4737
4738/**
4739 * Perform backchannel encryption using symmetric secret in @a key
4740 * to encrypt data from @a in to @a dst.
4741 *
4742 * @param[in,out] key key material to use
4743 * @param ciph cipher text to decrypt
4744 * @param[out] out output data to generate (plaintext)
4745 * @param out_size number of bytes of input in @a ciph and available in @a out
4746 * @return GNUNET_OK on success
4747 */
4748static enum GNUNET_GenericReturnValue
4749dv_decrypt (struct DVKeyState *key,
4750 void *out,
4751 const void *ciph,
4752 size_t out_size)
4753{
4754 return (0 ==
4755 gcry_cipher_decrypt (key->cipher,
4756 out, out_size,
4757 ciph, out_size)) ? GNUNET_OK : GNUNET_SYSERR;
4758}
4759
4760
4761/**
4762 * Clean up key material in @a key.
4763 *
4764 * @param key key material to clean up (memory must not be free'd!)
4765 */
4766static void
4767dv_key_clean (struct DVKeyState *key)
4768{
4769 gcry_cipher_close (key->cipher);
4770 GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
4771}
4772
4773
4774/**
4775 * Function to call to further operate on the now DV encapsulated
4776 * message @a hdr, forwarding it via @a next_hop under respect of
4777 * @a options.
4778 *
4779 * @param cls closure
4780 * @param next_hop next hop of the DV path
4781 * @param hdr encapsulated message, technically a `struct TransportDFBoxMessage`
4782 * @param options options of the original message
4783 */
4784typedef void (*DVMessageHandler) (void *cls,
4785 struct Neighbour *next_hop,
4786 const struct GNUNET_MessageHeader *hdr,
4787 enum RouteMessageOptions options);
4788
4789/**
4790 * Pick a path of @a dv under constraints @a options and schedule
4791 * transmission of @a hdr.
4792 *
4793 * @param target neighbour to ultimately send to
4794 * @param num_dvhs length of the @a dvhs array
4795 * @param dvhs array of hops to send the message to
4796 * @param hdr message to send as payload
4797 * @param use function to call with the encapsulated message
4798 * @param use_cls closure for @a use
4799 * @param options whether path must be confirmed or not, to be passed to @a use
4800 * @param without_fc shall this TransportDVBoxMessage be forwarded without flow control.
4801 * @return expected RTT for transmission, #GNUNET_TIME_UNIT_FOREVER_REL if sending failed
4802 */
4803static struct GNUNET_TIME_Relative
4804encapsulate_for_dv (struct DistanceVector *dv,
4805 unsigned int num_dvhs,
4806 struct DistanceVectorHop **dvhs,
4807 const struct GNUNET_MessageHeader *hdr,
4808 DVMessageHandler use,
4809 void *use_cls,
4810 enum RouteMessageOptions options,
4811 enum GNUNET_GenericReturnValue without_fc)
4812{
4813 struct TransportDVBoxMessage box_hdr;
4814 struct TransportDVBoxPayloadP payload_hdr;
4815 uint16_t enc_body_size = ntohs (hdr->size);
4816 char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
4817 struct DVKeyState *key;
4818 struct GNUNET_TIME_Relative rtt;
4819 struct GNUNET_HashCode k;
4820
4821 key = GNUNET_new (struct DVKeyState);
4822 /* Encrypt payload */
4823 box_hdr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX);
4824 box_hdr.total_hops = htons (0);
4825 box_hdr.without_fc = htons (without_fc);
4826 // update_ephemeral (dv);
4827 if (0 ==
4828 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
4829 {
4830 GNUNET_CRYPTO_eddsa_kem_encaps (&dv->target.public_key,
4831 &dv->ephemeral_key,
4832 &k);
4833 sign_ephemeral (dv);
4834 }
4835 box_hdr.ephemeral_key = dv->ephemeral_key;
4836 payload_hdr.sender_sig = dv->sender_sig;
4837
4838 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
4839 &box_hdr.iv,
4840 sizeof(box_hdr.iv));
4841 // We are creating this key, so this must work.
4842 // FIXME: Possibly also add return values here. We are processing
4843 // Input from other peers...
4844 dv_setup_key_state_from_km (&k, &box_hdr.iv, key);
4845 payload_hdr.sender = GST_my_identity;
4846 payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
4847 dv_encrypt (key, &payload_hdr, enc, sizeof(payload_hdr));
4848 dv_encrypt (key,
4849 hdr,
4850 &enc[sizeof(struct TransportDVBoxPayloadP)],
4851 enc_body_size);
4852 dv_hmac (key, &box_hdr.hmac, enc, sizeof(enc));
4853 dv_key_clean (key);
4854 rtt = GNUNET_TIME_UNIT_FOREVER_REL;
4855 /* For each selected path, take the pre-computed header and body
4856 and add the path in the middle of the message; then send it. */
4857 for (unsigned int i = 0; i < num_dvhs; i++)
4858 {
4859 struct DistanceVectorHop *dvh = dvhs[i];
4860 unsigned int num_hops = dvh->distance + 1;
4861 char buf[sizeof(struct TransportDVBoxMessage)
4862 + sizeof(struct GNUNET_PeerIdentity) * num_hops
4863 + sizeof(struct TransportDVBoxPayloadP)
4864 + enc_body_size] GNUNET_ALIGN;
4865 struct GNUNET_PeerIdentity *dhops;
4866
4867 box_hdr.header.size = htons (sizeof(buf));
4868 box_hdr.orig_size = htons (sizeof(buf));
4869 box_hdr.num_hops = htons (num_hops);
4870 memcpy (buf, &box_hdr, sizeof(box_hdr));
4871 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
4872 memcpy (dhops,
4873 dvh->path,
4874 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
4875 dhops[dvh->distance] = dv->target;
4876 if (GNUNET_EXTRA_LOGGING > 0)
4877 {
4878 char *path;
4879
4880 path = GNUNET_strdup (GNUNET_i2s (&GST_my_identity));
4881 for (unsigned int j = 0; j < num_hops; j++)
4882 {
4883 char *tmp;
4884
4885 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
4886 GNUNET_free (path);
4887 path = tmp;
4888 }
4889 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4890 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
4891 ntohs (hdr->type),
4892 GNUNET_i2s (&dv->target),
4893 i + 1,
4894 num_dvhs,
4895 path);
4896 GNUNET_free (path);
4897 }
4898 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
4899 memcpy (&dhops[num_hops], enc, sizeof(enc));
4900 use (use_cls,
4901 dvh->next_hop,
4902 (const struct GNUNET_MessageHeader *) buf,
4903 options);
4904 GNUNET_free (key);
4905 }
4906 return rtt;
4907}
4908
4909
4910/**
4911 * Wrapper around #route_via_neighbour() that matches the
4912 * #DVMessageHandler structure.
4913 *
4914 * @param cls unused
4915 * @param next_hop where to send next
4916 * @param hdr header of the message to send
4917 * @param options message options for queue selection
4918 */
4919static void
4920send_dv_to_neighbour (void *cls,
4921 struct Neighbour *next_hop,
4922 const struct GNUNET_MessageHeader *hdr,
4923 enum RouteMessageOptions options)
4924{
4925 (void) cls;
4926 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
4927}
4928
4929
4930/**
4931 * We need to transmit @a hdr to @a target. If necessary, this may
4932 * involve DV routing. This function routes without applying flow
4933 * control or congestion control and should only be used for control
4934 * traffic.
4935 *
4936 * @param target peer to receive @a hdr
4937 * @param hdr header of the message to route and #GNUNET_free()
4938 * @param options which transmission channels are allowed
4939 * @return expected RTT for transmission, #GNUNET_TIME_UNIT_FOREVER_REL if sending failed
4940 */
4941static struct GNUNET_TIME_Relative
4942route_control_message_without_fc (struct VirtualLink *vl,
4943// route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
4944 const struct GNUNET_MessageHeader *hdr,
4945 enum RouteMessageOptions options)
4946{
4947 // struct VirtualLink *vl;
4948 struct Neighbour *n;
4949 struct DistanceVector *dv;
4950 struct GNUNET_TIME_Relative rtt1;
4951 struct GNUNET_TIME_Relative rtt2;
4952 const struct GNUNET_PeerIdentity *target = &vl->target;
4953
4954 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4955 "Trying to route message of type %u to %s without fc\n",
4956 ntohs (hdr->type),
4957 GNUNET_i2s (target));
4958
4959 // TODO Do this elsewhere. vl should be given as parameter to method.
4960 // vl = lookup_virtual_link (target);
4961 GNUNET_assert (NULL != vl && GNUNET_YES == vl->confirmed);
4962 if (NULL == vl)
4963 return GNUNET_TIME_UNIT_FOREVER_REL;
4964 n = vl->n;
4965 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
4966 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
4967 {
4968 /* if confirmed is required, and we do not have anything
4969 confirmed, drop respective options */
4970 if (NULL == n)
4971 n = lookup_neighbour (target);
4972 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
4973 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, target);
4974 }
4975 if ((NULL == n) && (NULL == dv))
4976 {
4977 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4978 "Cannot route message of type %u to %s: no route\n",
4979 ntohs (hdr->type),
4980 GNUNET_i2s (target));
4981 GNUNET_STATISTICS_update (GST_stats,
4982 "# Messages dropped in routing: no acceptable method",
4983 1,
4984 GNUNET_NO);
4985 return GNUNET_TIME_UNIT_FOREVER_REL;
4986 }
4987 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4988 "Routing message of type %u to %s with options %X\n",
4989 ntohs (hdr->type),
4990 GNUNET_i2s (target),
4991 (unsigned int) options);
4992 /* If both dv and n are possible and we must choose:
4993 flip a coin for the choice between the two; for now 50/50 */
4994 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
4995 {
4996 if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2))
4997 n = NULL;
4998 else
4999 dv = NULL;
5000 }
5001 if ((NULL != n) && (NULL != dv))
5002 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5003 enough for redundancy, so clear the flag. */
5004 rtt1 = GNUNET_TIME_UNIT_FOREVER_REL;
5005 rtt2 = GNUNET_TIME_UNIT_FOREVER_REL;
5006 if (NULL != n)
5007 {
5008 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5009 "Try to route message of type %u to %s without fc via neighbour\n",
5010 ntohs (hdr->type),
5011 GNUNET_i2s (target));
5012 rtt1 = route_via_neighbour (n, hdr, options);
5013 }
5014 if (NULL != dv)
5015 {
5016 struct DistanceVectorHop *hops[2];
5017 unsigned int res;
5018
5019 res = pick_random_dv_hops (dv,
5020 options,
5021 hops,
5022 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5023 if (0 == res)
5024 {
5025 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
5026 "Failed to route message, could not determine DV path\n");
5027 return rtt1;
5028 }
5029 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5030 "encapsulate_for_dv 1\n");
5031 rtt2 = encapsulate_for_dv (dv,
5032 res,
5033 hops,
5034 hdr,
5035 &send_dv_to_neighbour,
5036 NULL,
5037 options & (~RMO_REDUNDANT),
5038 GNUNET_YES);
5039 }
5040 return GNUNET_TIME_relative_min (rtt1, rtt2);
5041}
5042
5043
5044static void
5045consider_sending_fc (void *cls);
5046
5047/**
5048 * Something changed on the virtual link with respect to flow
5049 * control. Consider retransmitting the FC window size.
5050 *
5051 * @param cls a `struct VirtualLink` to work with
5052 */
5053static void
5054task_consider_sending_fc (void *cls)
5055{
5056 struct VirtualLink *vl = cls;
5057 vl->fc_retransmit_task = NULL;
5058 consider_sending_fc (cls);
5059}
5060
5061
5062/**
5063 * Something changed on the virtual link with respect to flow
5064 * control. Consider retransmitting the FC window size.
5065 *
5066 * @param cls a `struct VirtualLink` to work with
5067 */
5068static void
5069consider_sending_fc (void *cls)
5070{
5071 struct VirtualLink *vl = cls;
5072 struct GNUNET_TIME_Absolute monotime;
5073 struct TransportFlowControlMessage fc;
5074 struct GNUNET_TIME_Relative duration;
5075 struct GNUNET_TIME_Relative rtt;
5076
5077 duration = GNUNET_TIME_absolute_get_duration (vl->last_fc_transmission);
5078 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
5079 it always! */
5080 /* For example, we should probably ONLY do this if a bit more than
5081 an RTT has passed, or if the window changed "significantly" since
5082 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
5083 need an estimate for the bandwidth-delay-product for the entire
5084 VL, as that determines "significantly". We have the delay, but
5085 the bandwidth statistics need to be added for the VL!*/(void) duration;
5086
5087 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5088 "Sending FC seq %u to %s with new window %llu\n",
5089 (unsigned int) vl->fc_seq_gen,
5090 GNUNET_i2s (&vl->target),
5091 (unsigned long long) vl->incoming_fc_window_size);
5092 monotime = GNUNET_TIME_absolute_get_monotonic (GST_cfg);
5093 vl->last_fc_transmission = monotime;
5094 fc.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL);
5095 fc.header.size = htons (sizeof(fc));
5096 fc.seq = htonl (vl->fc_seq_gen++);
5097 fc.inbound_window_size = GNUNET_htonll (vl->incoming_fc_window_size
5098 + vl->incoming_fc_window_size_used
5099 + vl->incoming_fc_window_size_loss);
5100 fc.outbound_sent = GNUNET_htonll (vl->outbound_fc_window_size_used);
5101 fc.outbound_window_size = GNUNET_htonll (vl->outbound_fc_window_size);
5102 fc.sender_time = GNUNET_TIME_absolute_hton (monotime);
5103 rtt = route_control_message_without_fc (vl, &fc.header, RMO_DV_ALLOWED);
5104 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
5105 {
5106 rtt = GNUNET_TIME_UNIT_SECONDS;
5107 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5108 "FC retransmission to %s failed, will retry in %s\n",
5109 GNUNET_i2s (&vl->target),
5110 GNUNET_STRINGS_relative_time_to_string (rtt, GNUNET_YES));
5111 vl->last_fc_rtt = GNUNET_TIME_UNIT_ZERO;
5112 }
5113 else
5114 {
5115 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
5116 vl->last_fc_rtt = rtt;
5117 }
5118 if (NULL != vl->fc_retransmit_task)
5119 GNUNET_SCHEDULER_cancel (vl->fc_retransmit_task);
5120 if (MAX_FC_RETRANSMIT_COUNT == vl->fc_retransmit_count)
5121 {
5122 rtt = GNUNET_TIME_UNIT_MINUTES;
5123 vl->fc_retransmit_count = 0;
5124 }
5125 vl->fc_retransmit_task =
5126 GNUNET_SCHEDULER_add_delayed (rtt, &task_consider_sending_fc, vl);
5127 vl->fc_retransmit_count++;
5128}
5129
5130
5131/**
5132 * There is a message at the head of the pending messages for @a vl
5133 * which may be ready for transmission. Check if a queue is ready to
5134 * take it.
5135 *
5136 * This function must (1) check for flow control to ensure that we can
5137 * right now send to @a vl, (2) check that the pending message in the
5138 * queue is actually eligible, (3) determine if any applicable queue
5139 * (direct neighbour or DVH path) is ready to accept messages, and
5140 * (4) prioritize based on the preferences associated with the
5141 * pending message.
5142 *
5143 * So yeah, easy.
5144 *
5145 * @param vl virtual link where we should check for transmission
5146 */
5147static void
5148check_vl_transmission (struct VirtualLink *vl)
5149{
5150 struct Neighbour *n = vl->n;
5151 struct DistanceVector *dv = vl->dv;
5152 struct GNUNET_TIME_Absolute now;
5153 struct VirtualLink *vl_next_hop;
5154 int elig;
5155
5156 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5157 "check_vl_transmission to target %s\n",
5158 GNUNET_i2s (&vl->target));
5159 /* Check that we have an eligible pending message!
5160 (cheaper than having #transmit_on_queue() find out!) */
5161 elig = GNUNET_NO;
5162 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
5163 pm = pm->next_vl)
5164 {
5165 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5166 "check_vl_transmission loop\n");
5167 if (NULL != pm->qe)
5168 continue; /* not eligible, is in a queue! */
5169 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
5170 vl->outbound_fc_window_size)
5171 {
5172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5173 "Stalled message %llu transmission on VL %s due to flow control: %llu < %llu\n",
5174 pm->logging_uuid,
5175 GNUNET_i2s (&vl->target),
5176 (unsigned long long) vl->outbound_fc_window_size,
5177 (unsigned long long) (pm->bytes_msg
5178 + vl->outbound_fc_window_size_used));
5179 consider_sending_fc (vl);
5180 return; /* We have a message, but flow control says "nope" */
5181 }
5182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5183 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
5184 GNUNET_i2s (&vl->target));
5185 /* Notify queues at direct neighbours that we are interested */
5186 now = GNUNET_TIME_absolute_get ();
5187 if (NULL != n)
5188 {
5189 for (struct Queue *queue = n->queue_head; NULL != queue;
5190 queue = queue->next_neighbour)
5191 {
5192 if ((GNUNET_YES == queue->idle) &&
5193 (queue->validated_until.abs_value_us > now.abs_value_us))
5194 {
5195 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5196 "Direct neighbour %s not stalled\n",
5197 GNUNET_i2s (&n->pid));
5198 schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
5199 queue,
5200 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
5201 elig = GNUNET_YES;
5202 }
5203 else
5204 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5205 "Neighbour Queue QID: %u (%u) busy or invalid\n",
5206 queue->qid,
5207 queue->idle);
5208 }
5209 }
5210 /* Notify queues via DV that we are interested */
5211 if (NULL != dv)
5212 {
5213 /* Do DV with lower scheduler priority, which effectively means that
5214 IF a neighbour exists and is available, we prefer it. */
5215 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5216 pos = pos->next_dv)
5217 {
5218 struct Neighbour *nh = pos->next_hop;
5219
5220
5221 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
5222 continue; /* skip this one: path not validated */
5223 else
5224 {
5225 vl_next_hop = lookup_virtual_link (&nh->pid);
5226 GNUNET_assert (NULL != vl_next_hop);
5227 if (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
5228 vl_next_hop->outbound_fc_window_size)
5229 {
5230 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5231 "Stalled message %llu transmission on next hop %s due to flow control: %llu < %llu\n",
5232 pm->logging_uuid,
5233 GNUNET_i2s (&vl_next_hop->target),
5234 (unsigned long
5235 long) vl_next_hop->outbound_fc_window_size,
5236 (unsigned long long) (pm->bytes_msg
5237 + vl_next_hop->
5238 outbound_fc_window_size_used));
5239 consider_sending_fc (vl_next_hop);
5240 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
5241 }
5242 for (struct Queue *queue = nh->queue_head; NULL != queue;
5243 queue = queue->next_neighbour)
5244 if ((GNUNET_YES == queue->idle) &&
5245 (queue->validated_until.abs_value_us > now.abs_value_us))
5246 {
5247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5248 "Next hop neighbour %s not stalled\n",
5249 GNUNET_i2s (&nh->pid));
5250 schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
5251 queue,
5252 GNUNET_SCHEDULER_PRIORITY_BACKGROUND);
5253 elig = GNUNET_YES;
5254 }
5255 else
5256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5257 "DV Queue QID: %u (%u) busy or invalid\n",
5258 queue->qid,
5259 queue->idle);
5260 }
5261 }
5262 }
5263 if (GNUNET_YES == elig)
5264 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5265 "Eligible message %llu of size %u to %s: %llu/%llu\n",
5266 pm->logging_uuid,
5267 pm->bytes_msg,
5268 GNUNET_i2s (&vl->target),
5269 (unsigned long long) vl->outbound_fc_window_size,
5270 (unsigned long long) (pm->bytes_msg
5271 + vl->outbound_fc_window_size_used));
5272 break;
5273 }
5274}
5275
5276
5277/**
5278 * Client asked for transmission to a peer. Process the request.
5279 *
5280 * @param cls the client
5281 * @param obm the send message that was sent
5282 */
5283static void
5284handle_client_send (void *cls, const struct OutboundMessage *obm)
5285{
5286 struct TransportClient *tc = cls;
5287 struct PendingMessage *pm;
5288 const struct GNUNET_MessageHeader *obmm;
5289 uint32_t bytes_msg;
5290 struct VirtualLink *vl;
5291 enum GNUNET_MQ_PriorityPreferences pp;
5292
5293 GNUNET_assert (CT_CORE == tc->type);
5294 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5295 bytes_msg = ntohs (obmm->size);
5296 pp = (enum GNUNET_MQ_PriorityPreferences) ntohl (obm->priority);
5297 vl = lookup_virtual_link (&obm->peer);
5298 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5299 {
5300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5301 "Don't have %s as a neighbour (anymore).\n",
5302 GNUNET_i2s (&obm->peer));
5303 /* Failure: don't have this peer as a neighbour (anymore).
5304 Might have gone down asynchronously, so this is NOT
5305 a protocol violation by CORE. Still count the event,
5306 as this should be rare. */
5307 GNUNET_SERVICE_client_continue (tc->client);
5308 GNUNET_STATISTICS_update (GST_stats,
5309 "# messages dropped (neighbour unknown)",
5310 1,
5311 GNUNET_NO);
5312 return;
5313 }
5314
5315 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
5316 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5317 "1 created pm %p storing vl %p\n",
5318 pm,
5319 vl);
5320 pm->logging_uuid = logging_uuid_gen++;
5321 pm->prefs = pp;
5322 pm->client = tc;
5323 pm->vl = vl;
5324 pm->bytes_msg = bytes_msg;
5325 memcpy (&pm[1], obmm, bytes_msg);
5326 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5327 "Sending message of type %u with %u bytes as <%llu> to %s\n",
5328 ntohs (obmm->type),
5329 bytes_msg,
5330 pm->logging_uuid,
5331 GNUNET_i2s (&obm->peer));
5332 GNUNET_CONTAINER_MDLL_insert (client,
5333 tc->details.core.pending_msg_head,
5334 tc->details.core.pending_msg_tail,
5335 pm);
5336 GNUNET_CONTAINER_MDLL_insert (vl,
5337 vl->pending_msg_head,
5338 vl->pending_msg_tail,
5339 pm);
5340 check_vl_transmission (vl);
5341 GNUNET_SERVICE_client_continue (tc->client);
5342}
5343
5344
5345/**
5346 * Communicator requests backchannel transmission. Process the request.
5347 * Just repacks it into our `struct TransportBackchannelEncapsulationMessage *`
5348 * (which for now has exactly the same format, only a different message type)
5349 * and passes it on for routing.
5350 *
5351 * @param cls the client
5352 * @param cb the send message that was sent
5353 */
5354static void
5355handle_communicator_backchannel (
5356 void *cls,
5357 const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
5358{
5359 struct Neighbour *n;
5360 struct VirtualLink *vl;
5361 struct TransportClient *tc = cls;
5362 const struct GNUNET_MessageHeader *inbox =
5363 (const struct GNUNET_MessageHeader *) &cb[1];
5364 uint16_t isize = ntohs (inbox->size);
5365 const char *is = ((const char *) &cb[1]) + isize;
5366 size_t slen = strlen (is) + 1;
5367 char
5368 mbuf[slen + isize
5369 + sizeof(struct
5370 TransportBackchannelEncapsulationMessage)] GNUNET_ALIGN;
5371 struct TransportBackchannelEncapsulationMessage *be =
5372 (struct TransportBackchannelEncapsulationMessage *) mbuf;
5373
5374 /* 0-termination of 'is' was checked already in
5375 #check_communicator_backchannel() */
5376 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5377 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
5378 GNUNET_i2s (&cb->pid),
5379 is,
5380 ntohs (inbox->type),
5381 ntohs (inbox->size));
5382 /* encapsulate and encrypt message */
5383 be->header.type =
5384 htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION);
5385 be->header.size = htons (sizeof(mbuf));
5386 memcpy (&be[1], inbox, isize);
5387 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5388 + isize],
5389 is,
5390 strlen (is) + 1);
5391 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
5392 vl = lookup_virtual_link (&cb->pid);
5393 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5394 {
5395 route_control_message_without_fc (vl, &be->header, RMO_DV_ALLOWED);
5396 }
5397 else
5398 {
5399 /* Use route via neighbour */
5400 n = lookup_neighbour (&cb->pid);
5401 if (NULL != n)
5402 route_via_neighbour (
5403 n,
5404 &be->header,
5405 RMO_NONE);
5406 }
5407 GNUNET_SERVICE_client_continue (tc->client);
5408}
5409
5410
5411/**
5412 * Address of our peer added. Test message is well-formed.
5413 *
5414 * @param cls the client
5415 * @param aam the send message that was sent
5416 * @return #GNUNET_OK if message is well-formed
5417 */
5418static int
5419check_add_address (void *cls,
5420 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5421{
5422 struct TransportClient *tc = cls;
5423
5424 if (CT_COMMUNICATOR != tc->type)
5425 {
5426 GNUNET_break (0);
5427 return GNUNET_SYSERR;
5428 }
5429 GNUNET_MQ_check_zero_termination (aam);
5430 return GNUNET_OK;
5431}
5432
5433
5434/**
5435 * Ask peerstore to store our address.
5436 *
5437 * @param cls an `struct AddressListEntry *`
5438 */
5439static void
5440store_pi (void *cls);
5441
5442
5443/**
5444 * Function called when peerstore is done storing our address.
5445 *
5446 * @param cls a `struct AddressListEntry`
5447 * @param success #GNUNET_YES if peerstore was successful
5448 */
5449static void
5450peerstore_store_own_cb (void *cls, int success)
5451{
5452 struct AddressListEntry *ale = cls;
5453
5454 ale->sc = NULL;
5455 if (GNUNET_YES != success)
5456 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5457 "Failed to store our own address `%s' in peerstore!\n",
5458 ale->address);
5459 else
5460 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5461 "Successfully stored our own address `%s' in peerstore!\n",
5462 ale->address);
5463 /* refresh period is 1/4 of expiration time, that should be plenty
5464 without being excessive. */
5465 ale->st =
5466 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (ale->expiration,
5467 4ULL),
5468 &store_pi,
5469 ale);
5470}
5471
5472
5473static void
5474shc_cont (void *cls, int success)
5475{
5476 GNUNET_free (cls);
5477}
5478
5479
5480/**
5481 * Ask peerstore to store our address.
5482 *
5483 * @param cls an `struct AddressListEntry *`
5484 */
5485static void
5486store_pi (void *cls)
5487{
5488 struct AddressListEntry *ale = cls;
5489 struct GNUNET_PEERSTORE_StoreHelloContext *shc;
5490 void *addr;
5491 size_t addr_len;
5492 struct GNUNET_TIME_Absolute expiration;
5493 enum GNUNET_GenericReturnValue add_result;
5494 struct GNUNET_MQ_Envelope *env;
5495 const struct GNUNET_MessageHeader *msg;
5496 const char *dash;
5497 char *prefix = GNUNET_HELLO_address_to_prefix (ale->address);
5498 char *address_uri;
5499
5500 dash = strchr (ale->address, '-');
5501 dash++;
5502 GNUNET_asprintf (&address_uri,
5503 "%s://%s",
5504 prefix,
5505 dash);
5506 ale->st = NULL;
5507 expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
5508 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5509 "Storing our address `%s' in peerstore until %s!\n",
5510 ale->address,
5511 GNUNET_STRINGS_absolute_time_to_string (expiration));
5512 add_result = GNUNET_HELLO_builder_add_address (GST_my_hello,
5513 address_uri);
5514 env = GNUNET_HELLO_builder_to_env (GST_my_hello,
5515 GST_my_private_key,
5516 GNUNET_TIME_UNIT_ZERO);
5517 msg = GNUNET_MQ_env_get_msg (env);
5518 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5519 "store_pi 1\n");
5520 if (GNUNET_YES == add_result)
5521 shc = GNUNET_PEERSTORE_hello_add (peerstore,
5522 msg,
5523 shc_cont,
5524 shc);
5525 else if (GNUNET_SYSERR == add_result)
5526 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5527 "Error adding address to peerstore hello!\n");
5528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5529 "store_pi 2\n");
5530 GNUNET_HELLO_sign_address (ale->address,
5531 ale->nt,
5532 hello_mono_time,
5533 GST_my_private_key,
5534 &addr,
5535 &addr_len);
5536 ale->sc = GNUNET_PEERSTORE_store (peerstore,
5537 "transport",
5538 &GST_my_identity,
5539 GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY,
5540 addr,
5541 addr_len,
5542 expiration,
5543 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
5544 &peerstore_store_own_cb,
5545 ale);
5546 GNUNET_free (addr);
5547 GNUNET_free (env);
5548 GNUNET_free (prefix);
5549 GNUNET_free (address_uri);
5550 if (NULL == ale->sc)
5551 {
5552 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
5553 "Failed to store our address `%s' with peerstore\n",
5554 ale->address);
5555 ale->st =
5556 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &store_pi, ale);
5557 }
5558}
5559
5560
5561/**
5562 * Address of our peer added. Process the request.
5563 *
5564 * @param cls the client
5565 * @param aam the send message that was sent
5566 */
5567static void
5568handle_add_address (void *cls,
5569 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5570{
5571 struct TransportClient *tc = cls;
5572 struct AddressListEntry *ale;
5573 size_t slen;
5574
5575 /* 0-termination of &aam[1] was checked in #check_add_address */
5576 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5577 "Communicator added address `%s'!\n",
5578 (const char *) &aam[1]);
5579 slen = ntohs (aam->header.size) - sizeof(*aam);
5580 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
5581 ale->tc = tc;
5582 ale->address = (const char *) &ale[1];
5583 ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
5584 ale->aid = aam->aid;
5585 ale->nt = (enum GNUNET_NetworkType) ntohl (aam->nt);
5586 memcpy (&ale[1], &aam[1], slen);
5587 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
5588 tc->details.communicator.addr_tail,
5589 ale);
5590 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
5591 GNUNET_SERVICE_client_continue (tc->client);
5592}
5593
5594
5595/**
5596 * Address of our peer deleted. Process the request.
5597 *
5598 * @param cls the client
5599 * @param dam the send message that was sent
5600 */
5601static void
5602handle_del_address (void *cls,
5603 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
5604{
5605 struct TransportClient *tc = cls;
5606 struct AddressListEntry *alen;
5607
5608 if (CT_COMMUNICATOR != tc->type)
5609 {
5610 GNUNET_break (0);
5611 GNUNET_SERVICE_client_drop (tc->client);
5612 return;
5613 }
5614 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
5615 NULL != ale;
5616 ale = alen)
5617 {
5618 alen = ale->next;
5619 if (dam->aid != ale->aid)
5620 continue;
5621 GNUNET_assert (ale->tc == tc);
5622 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5623 "Communicator deleted address `%s'!\n",
5624 ale->address);
5625 free_address_list_entry (ale);
5626 GNUNET_SERVICE_client_continue (tc->client);
5627 return;
5628 }
5629 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
5630 "Communicator removed address we did not even have.\n");
5631 GNUNET_SERVICE_client_continue (tc->client);
5632 // GNUNET_SERVICE_client_drop (tc->client);
5633}
5634
5635
5636/**
5637 * Given an inbound message @a msg from a communicator @a cmc,
5638 * demultiplex it based on the type calling the right handler.
5639 *
5640 * @param cmc context for demultiplexing
5641 * @param msg message to demultiplex
5642 */
5643static void
5644demultiplex_with_cmc (struct CommunicatorMessageContext *cmc);
5645
5646
5647/**
5648 * Function called when we are done giving a message of a certain
5649 * size to CORE and should thus decrement the number of bytes of
5650 * RAM reserved for that peer's MQ.
5651 *
5652 * @param cls a `struct CoreSentContext`
5653 */
5654static void
5655core_env_sent_cb (void *cls)
5656{
5657 struct CoreSentContext *ctx = cls;
5658 struct VirtualLink *vl = ctx->vl;
5659
5660 if (NULL == vl)
5661 {
5662 /* lost the link in the meantime, ignore */
5663 GNUNET_free (ctx);
5664 return;
5665 }
5666 GNUNET_CONTAINER_DLL_remove (vl->csc_head, vl->csc_tail, ctx);
5667 GNUNET_assert (vl->incoming_fc_window_size_ram >= ctx->size);
5668 vl->incoming_fc_window_size_ram -= ctx->size;
5669 vl->incoming_fc_window_size_used += ctx->isize;
5670 consider_sending_fc (vl);
5671 GNUNET_free (ctx);
5672}
5673
5674
5675static void
5676finish_handling_raw_message (struct VirtualLink *vl,
5677 const struct GNUNET_MessageHeader *mh,
5678 struct CommunicatorMessageContext *cmc,
5679 unsigned int continue_client)
5680{
5681 uint16_t size = ntohs (mh->size);
5682 int have_core;
5683
5684 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
5685 {
5686 GNUNET_STATISTICS_update (GST_stats,
5687 "# CORE messages dropped (FC arithmetic overflow)",
5688 1,
5689 GNUNET_NO);
5690 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5691 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
5692 (unsigned int) ntohs (mh->type),
5693 (unsigned int) ntohs (mh->size));
5694 finish_cmc_handling_with_continue (cmc, continue_client);
5695 return;
5696 }
5697 if (vl->incoming_fc_window_size_ram + size > vl->available_fc_window_size)
5698 {
5699 GNUNET_STATISTICS_update (GST_stats,
5700 "# CORE messages dropped (FC window overflow)",
5701 1,
5702 GNUNET_NO);
5703 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5704 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
5705 (unsigned int) ntohs (mh->type),
5706 (unsigned int) ntohs (mh->size));
5707 finish_cmc_handling_with_continue (cmc, continue_client);
5708 return;
5709 }
5710
5711 /* Forward to all CORE clients */
5712 have_core = GNUNET_NO;
5713 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
5714 {
5715 struct GNUNET_MQ_Envelope *env;
5716 struct InboundMessage *im;
5717 struct CoreSentContext *ctx;
5718
5719 if (CT_CORE != tc->type)
5720 continue;
5721 vl->incoming_fc_window_size_ram += size;
5722 env = GNUNET_MQ_msg_extra (im, size, GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
5723 ctx = GNUNET_new (struct CoreSentContext);
5724 ctx->vl = vl;
5725 ctx->size = size;
5726 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
5727 have_core = GNUNET_YES;
5728 GNUNET_CONTAINER_DLL_insert (vl->csc_head, vl->csc_tail, ctx);
5729 GNUNET_MQ_notify_sent (env, &core_env_sent_cb, ctx);
5730 im->peer = cmc->im.sender;
5731 memcpy (&im[1], mh, size);
5732 GNUNET_MQ_send (tc->mq, env);
5733 vl->core_recv_window--;
5734 }
5735 if (GNUNET_NO == have_core)
5736 {
5737 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
5738 "Dropped message to CORE: no CORE client connected!\n");
5739 /* Nevertheless, count window as used, as it is from the
5740 perspective of the other peer! */
5741 vl->incoming_fc_window_size_used += size;
5742 /* TODO-M1 */
5743 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5744 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
5745 (unsigned int) ntohs (mh->type),
5746 (unsigned int) ntohs (mh->size));
5747 finish_cmc_handling_with_continue (cmc, continue_client);
5748 return;
5749 }
5750 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5751 "Delivered message from %s of type %u to CORE recv window %d\n",
5752 GNUNET_i2s (&cmc->im.sender),
5753 ntohs (mh->type),
5754 vl->core_recv_window);
5755 if (vl->core_recv_window > 0)
5756 {
5757 finish_cmc_handling_with_continue (cmc, continue_client);
5758 return;
5759 }
5760 /* Wait with calling #finish_cmc_handling(cmc) until the message
5761 was processed by CORE MQs (for CORE flow control)! */
5762 GNUNET_CONTAINER_DLL_insert (vl->cmc_head, vl->cmc_tail, cmc);
5763}
5764
5765
5766/**
5767 * Communicator gave us an unencapsulated message to pass as-is to
5768 * CORE. Process the request.
5769 *
5770 * @param cls a `struct CommunicatorMessageContext` (must call
5771 * #finish_cmc_handling() when done)
5772 * @param mh the message that was received
5773 */
5774static void
5775handle_raw_message (void *cls, const struct GNUNET_MessageHeader *mh)
5776{
5777 struct CommunicatorMessageContext *cmc = cls;
5778 // struct CommunicatorMessageContext *cmc_copy =
5779 // GNUNET_new (struct CommunicatorMessageContext);
5780 struct GNUNET_MessageHeader *mh_copy;
5781 struct RingBufferEntry *rbe;
5782 struct VirtualLink *vl;
5783 uint16_t size = ntohs (mh->size);
5784
5785 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5786 "Handling raw message of type %u with %u bytes\n",
5787 (unsigned int) ntohs (mh->type),
5788 (unsigned int) ntohs (mh->size));
5789
5790 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
5791 (size < sizeof(struct GNUNET_MessageHeader)))
5792 {
5793 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
5794
5795 GNUNET_break (0);
5796 finish_cmc_handling (cmc);
5797 GNUNET_SERVICE_client_drop (client);
5798 return;
5799 }
5800 vl = lookup_virtual_link (&cmc->im.sender);
5801 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5802 {
5803 /* FIXME: sender is giving us messages for CORE but we don't have
5804 the link up yet! I *suspect* this can happen right now (i.e.
5805 sender has verified us, but we didn't verify sender), but if
5806 we pass this on, CORE would be confused (link down, messages
5807 arrive). We should investigate more if this happens often,
5808 or in a persistent manner, and possibly do "something" about
5809 it. Thus logging as error for now. */
5810
5811 mh_copy = GNUNET_malloc (size);
5812 rbe = GNUNET_new (struct RingBufferEntry);
5813 rbe->cmc = cmc;
5814 /*cmc_copy->tc = cmc->tc;
5815 cmc_copy->im = cmc->im;*/
5816 GNUNET_memcpy (mh_copy, mh, size);
5817
5818 rbe->mh = mh_copy;
5819
5820 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
5821 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
5822 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
5823 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5824 "Storing message for %s and type %u (%u) in ring buffer\n",
5825 GNUNET_i2s (&cmc->im.sender),
5826 (unsigned int) ntohs (mh->type),
5827 (unsigned int) ntohs (mh_copy->type));
5828 if (RING_BUFFER_SIZE - 1 == ring_buffer_head)
5829 {
5830 ring_buffer_head = 0;
5831 is_ring_buffer_full = GNUNET_YES;
5832 }
5833 else
5834 ring_buffer_head++;
5835
5836 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5837 "%u items stored in ring buffer\n",
5838 ring_buffer_head);
5839
5840 /*GNUNET_break_op (0);
5841 GNUNET_STATISTICS_update (GST_stats,
5842 "# CORE messages dropped (virtual link still down)",
5843 1,
5844 GNUNET_NO);
5845
5846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5847 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
5848 (unsigned int) ntohs (mh->type),
5849 (unsigned int) ntohs (mh->size));
5850 finish_cmc_handling (cmc);*/
5851 GNUNET_SERVICE_client_continue (cmc->tc->client);
5852 // GNUNET_free (cmc);
5853 return;
5854 }
5855 finish_handling_raw_message (vl, mh, cmc, GNUNET_YES);
5856}
5857
5858
5859/**
5860 * Communicator gave us a fragment box. Check the message.
5861 *
5862 * @param cls a `struct CommunicatorMessageContext`
5863 * @param fb the send message that was sent
5864 * @return #GNUNET_YES if message is well-formed
5865 */
5866static int
5867check_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
5868{
5869 uint16_t size = ntohs (fb->header.size);
5870 uint16_t bsize = size - sizeof(*fb);
5871
5872 (void) cls;
5873 if (0 == bsize)
5874 {
5875 GNUNET_break_op (0);
5876 return GNUNET_SYSERR;
5877 }
5878 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
5879 {
5880 GNUNET_break_op (0);
5881 return GNUNET_SYSERR;
5882 }
5883 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
5884 {
5885 GNUNET_break_op (0);
5886 return GNUNET_SYSERR;
5887 }
5888 return GNUNET_YES;
5889}
5890
5891
5892/**
5893 * Clean up an idle cumulative acknowledgement data structure.
5894 *
5895 * @param cls a `struct AcknowledgementCummulator *`
5896 */
5897static void
5898destroy_ack_cummulator (void *cls)
5899{
5900 struct AcknowledgementCummulator *ac = cls;
5901
5902 ac->task = NULL;
5903 GNUNET_assert (0 == ac->num_acks);
5904 GNUNET_assert (
5905 GNUNET_YES ==
5906 GNUNET_CONTAINER_multipeermap_remove (ack_cummulators, &ac->target, ac));
5907 GNUNET_free (ac);
5908}
5909
5910
5911/**
5912 * Do the transmission of a cumulative acknowledgement now.
5913 *
5914 * @param cls a `struct AcknowledgementCummulator *`
5915 */
5916static void
5917transmit_cummulative_ack_cb (void *cls)
5918{
5919 struct Neighbour *n;
5920 struct VirtualLink *vl;
5921 struct AcknowledgementCummulator *ac = cls;
5922 char buf[sizeof(struct TransportReliabilityAckMessage)
5923 + ac->num_acks
5924 * sizeof(struct TransportCummulativeAckPayloadP)] GNUNET_ALIGN;
5925 struct TransportReliabilityAckMessage *ack =
5926 (struct TransportReliabilityAckMessage *) buf;
5927 struct TransportCummulativeAckPayloadP *ap;
5928
5929 ac->task = NULL;
5930 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5931 "Sending ACK with %u components to %s\n",
5932 ac->num_acks,
5933 GNUNET_i2s (&ac->target));
5934 GNUNET_assert (0 < ac->num_acks);
5935 ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK);
5936 ack->header.size =
5937 htons (sizeof(*ack)
5938 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
5939 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
5940 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
5941 for (unsigned int i = 0; i < ac->num_acks; i++)
5942 {
5943 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
5944 ap[i].ack_delay = GNUNET_TIME_relative_hton (
5945 GNUNET_TIME_absolute_get_duration (ac->ack_uuids[i].receive_time));
5946 }
5947 /*route_control_message_without_fc (
5948 &ac->target,
5949 &ack->header,
5950 RMO_DV_ALLOWED);*/
5951 vl = lookup_virtual_link (&ac->target);
5952 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5953 {
5954 route_control_message_without_fc (
5955 vl,
5956 &ack->header,
5957 RMO_DV_ALLOWED);
5958 }
5959 else
5960 {
5961 /* Use route via neighbour */
5962 n = lookup_neighbour (&ac->target);
5963 if (NULL != n)
5964 route_via_neighbour (
5965 n,
5966 &ack->header,
5967 RMO_NONE);
5968 }
5969 ac->num_acks = 0;
5970 ac->task = GNUNET_SCHEDULER_add_delayed (ACK_CUMMULATOR_TIMEOUT,
5971 &destroy_ack_cummulator,
5972 ac);
5973}
5974
5975
5976/**
5977 * Transmit an acknowledgement for @a ack_uuid to @a pid delaying
5978 * transmission by at most @a ack_delay.
5979 *
5980 * @param pid target peer
5981 * @param ack_uuid UUID to ack
5982 * @param max_delay how long can the ACK wait
5983 */
5984static void
5985cummulative_ack (const struct GNUNET_PeerIdentity *pid,
5986 const struct AcknowledgementUUIDP *ack_uuid,
5987 struct GNUNET_TIME_Absolute max_delay)
5988{
5989 struct AcknowledgementCummulator *ac;
5990
5991 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5992 "Scheduling ACK %s for transmission to %s\n",
5993 GNUNET_uuid2s (&ack_uuid->value),
5994 GNUNET_i2s (pid));
5995 ac = GNUNET_CONTAINER_multipeermap_get (ack_cummulators, pid);
5996 if (NULL == ac)
5997 {
5998 ac = GNUNET_new (struct AcknowledgementCummulator);
5999 ac->target = *pid;
6000 ac->min_transmission_time = max_delay;
6001 GNUNET_assert (GNUNET_YES ==
6002 GNUNET_CONTAINER_multipeermap_put (
6003 ack_cummulators,
6004 &ac->target,
6005 ac,
6006 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
6007 }
6008 else
6009 {
6010 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
6011 {
6012 /* must run immediately, ack buffer full! */
6013 transmit_cummulative_ack_cb (ac);
6014 }
6015 GNUNET_SCHEDULER_cancel (ac->task);
6016 ac->min_transmission_time =
6017 GNUNET_TIME_absolute_min (ac->min_transmission_time, max_delay);
6018 }
6019 GNUNET_assert (ac->num_acks < MAX_CUMMULATIVE_ACKS);
6020 ac->ack_uuids[ac->num_acks].receive_time = GNUNET_TIME_absolute_get ();
6021 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
6022 ac->num_acks++;
6023 ac->task = GNUNET_SCHEDULER_add_at (ac->min_transmission_time,
6024 &transmit_cummulative_ack_cb,
6025 ac);
6026}
6027
6028
6029/**
6030 * Closure for #find_by_message_uuid.
6031 */
6032struct FindByMessageUuidContext
6033{
6034 /**
6035 * UUID to look for.
6036 */
6037 struct MessageUUIDP message_uuid;
6038
6039 /**
6040 * Set to the reassembly context if found.
6041 */
6042 struct ReassemblyContext *rc;
6043};
6044
6045
6046/**
6047 * Iterator called to find a reassembly context by the message UUID in the
6048 * multihashmap32.
6049 *
6050 * @param cls a `struct FindByMessageUuidContext`
6051 * @param key a key (unused)
6052 * @param value a `struct ReassemblyContext`
6053 * @return #GNUNET_YES if not found, #GNUNET_NO if found
6054 */
6055static int
6056find_by_message_uuid (void *cls, uint32_t key, void *value)
6057{
6058 struct FindByMessageUuidContext *fc = cls;
6059 struct ReassemblyContext *rc = value;
6060
6061 (void) key;
6062 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
6063 {
6064 fc->rc = rc;
6065 return GNUNET_NO;
6066 }
6067 return GNUNET_YES;
6068}
6069
6070
6071/**
6072 * Communicator gave us a fragment. Process the request.
6073 *
6074 * @param cls a `struct CommunicatorMessageContext` (must call
6075 * #finish_cmc_handling() when done)
6076 * @param fb the message that was received
6077 */
6078static void
6079handle_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
6080{
6081 struct CommunicatorMessageContext *cmc = cls;
6082 struct VirtualLink *vl;
6083 struct ReassemblyContext *rc;
6084 const struct GNUNET_MessageHeader *msg;
6085 uint16_t msize;
6086 uint16_t fsize;
6087 uint16_t frag_off;
6088 char *target;
6089 struct GNUNET_TIME_Relative cdelay;
6090 struct FindByMessageUuidContext fc;
6091
6092 vl = lookup_virtual_link (&cmc->im.sender);
6093 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6094 {
6095 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6096
6097 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6098 "No virtual link for %s to handle fragment\n",
6099 GNUNET_i2s (&cmc->im.sender));
6100 GNUNET_break (0);
6101 finish_cmc_handling (cmc);
6102 GNUNET_SERVICE_client_drop (client);
6103 return;
6104 }
6105 if (NULL == vl->reassembly_map)
6106 {
6107 vl->reassembly_map = GNUNET_CONTAINER_multihashmap32_create (8);
6108 vl->reassembly_heap =
6109 GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
6110 vl->reassembly_timeout_task =
6111 GNUNET_SCHEDULER_add_delayed (REASSEMBLY_EXPIRATION,
6112 &reassembly_cleanup_task,
6113 vl);
6114 }
6115 msize = ntohs (fb->msg_size);
6116 fc.message_uuid = fb->msg_uuid;
6117 fc.rc = NULL;
6118 (void) GNUNET_CONTAINER_multihashmap32_get_multiple (vl->reassembly_map,
6119 fb->msg_uuid.uuid,
6120 &find_by_message_uuid,
6121 &fc);
6122 fsize = ntohs (fb->header.size) - sizeof(*fb);
6123 if (NULL == (rc = fc.rc))
6124 {
6125 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
6126 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
6127 rc->msg_uuid = fb->msg_uuid;
6128 rc->virtual_link = vl;
6129 rc->msg_size = msize;
6130 rc->reassembly_timeout =
6131 GNUNET_TIME_relative_to_absolute (REASSEMBLY_EXPIRATION);
6132 rc->last_frag = GNUNET_TIME_absolute_get ();
6133 rc->hn = GNUNET_CONTAINER_heap_insert (vl->reassembly_heap,
6134 rc,
6135 rc->reassembly_timeout.abs_value_us);
6136 GNUNET_assert (GNUNET_OK ==
6137 GNUNET_CONTAINER_multihashmap32_put (
6138 vl->reassembly_map,
6139 rc->msg_uuid.uuid,
6140 rc,
6141 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
6142 target = (char *) &rc[1];
6143 rc->bitfield = (uint8_t *) (target + rc->msg_size);
6144 if (fsize != rc->msg_size)
6145 rc->msg_missing = rc->msg_size;
6146 else
6147 rc->msg_missing = 0;
6148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6149 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %u\n",
6150 fsize,
6151 ntohs (fb->frag_off),
6152 msize,
6153 rc->msg_missing,
6154 GNUNET_i2s (&cmc->im.sender),
6155 (unsigned int) fb->msg_uuid.uuid);
6156 }
6157 else
6158 {
6159 target = (char *) &rc[1];
6160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6161 "Received fragment at offset %u/%u from %s for message %u\n",
6162 ntohs (fb->frag_off),
6163 msize,
6164 GNUNET_i2s (&cmc->im.sender),
6165 (unsigned int) fb->msg_uuid.uuid);
6166 }
6167 if (msize != rc->msg_size)
6168 {
6169 GNUNET_break (0);
6170 finish_cmc_handling (cmc);
6171 return;
6172 }
6173
6174 /* reassemble */
6175 if (0 == fsize)
6176 {
6177 GNUNET_break (0);
6178 finish_cmc_handling (cmc);
6179 return;
6180 }
6181 frag_off = ntohs (fb->frag_off);
6182 if (frag_off + fsize > msize)
6183 {
6184 /* Fragment (plus fragment size) exceeds message size! */
6185 GNUNET_break_op (0);
6186 finish_cmc_handling (cmc);
6187 return;
6188 }
6189 memcpy (&target[frag_off], &fb[1], fsize);
6190 /* update bitfield and msg_missing */
6191 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
6192 {
6193 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
6194 {
6195 rc->bitfield[i / 8] |= (1 << (i % 8));
6196 rc->msg_missing--;
6197 }
6198 }
6199
6200 /* Compute cumulative ACK */
6201 cdelay = GNUNET_TIME_absolute_get_duration (rc->last_frag);
6202 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
6203 if (0 == rc->msg_missing)
6204 cdelay = GNUNET_TIME_UNIT_ZERO;
6205 cummulative_ack (&cmc->im.sender,
6206 &fb->ack_uuid,
6207 GNUNET_TIME_relative_to_absolute (cdelay));
6208 rc->last_frag = GNUNET_TIME_absolute_get ();
6209 /* is reassembly complete? */
6210 if (0 != rc->msg_missing)
6211 {
6212 finish_cmc_handling (cmc);
6213 return;
6214 }
6215 /* reassembly is complete, verify result */
6216 msg = (const struct GNUNET_MessageHeader *) &rc[1];
6217 if (ntohs (msg->size) != rc->msg_size)
6218 {
6219 GNUNET_break (0);
6220 free_reassembly_context (rc);
6221 finish_cmc_handling (cmc);
6222 return;
6223 }
6224 /* successful reassembly */
6225 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6226 "Fragment reassembly complete for message %u\n",
6227 (unsigned int) fb->msg_uuid.uuid);
6228 /* FIXME: check that the resulting msg is NOT a
6229 DV Box or Reliability Box, as that is NOT allowed! */
6230 cmc->mh = msg;
6231 demultiplex_with_cmc (cmc);
6232 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
6233 en-route and we forget that we finished this reassembly immediately!
6234 -> keep around until timeout?
6235 -> shorten timeout based on ACK? */
6236 free_reassembly_context (rc);
6237}
6238
6239
6240/**
6241 * Communicator gave us a reliability box. Check the message.
6242 *
6243 * @param cls a `struct CommunicatorMessageContext`
6244 * @param rb the send message that was sent
6245 * @return #GNUNET_YES if message is well-formed
6246 */
6247static int
6248check_reliability_box (void *cls,
6249 const struct TransportReliabilityBoxMessage *rb)
6250{
6251 (void) cls;
6252 const struct GNUNET_MessageHeader *inbox = (const struct
6253 GNUNET_MessageHeader *) &rb[1];
6254
6255 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6256 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
6257 ntohs (rb->header.size),
6258 ntohs (inbox->type),
6259 ntohs (inbox->size),
6260 sizeof (struct TransportReliabilityBoxMessage),
6261 sizeof (struct GNUNET_MessageHeader));
6262 GNUNET_MQ_check_boxed_message (rb);
6263 return GNUNET_YES;
6264}
6265
6266
6267/**
6268 * Communicator gave us a reliability box. Process the request.
6269 *
6270 * @param cls a `struct CommunicatorMessageContext` (must call
6271 * #finish_cmc_handling() when done)
6272 * @param rb the message that was received
6273 */
6274static void
6275handle_reliability_box (void *cls,
6276 const struct TransportReliabilityBoxMessage *rb)
6277{
6278 struct CommunicatorMessageContext *cmc = cls;
6279 const struct GNUNET_MessageHeader *inbox =
6280 (const struct GNUNET_MessageHeader *) &rb[1];
6281 struct GNUNET_TIME_Relative rtt;
6282
6283 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6284 "Received reliability box from %s with UUID %s of type %u\n",
6285 GNUNET_i2s (&cmc->im.sender),
6286 GNUNET_uuid2s (&rb->ack_uuid.value),
6287 (unsigned int) ntohs (inbox->type));
6288 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
6289 do not really have an RTT for the
6290 * incoming* queue (should we have
6291 the sender add it to the rb message?) */
6292 cummulative_ack (
6293 &cmc->im.sender,
6294 &rb->ack_uuid,
6295 (0 == ntohl (rb->ack_countdown))
6296 ? GNUNET_TIME_UNIT_ZERO_ABS
6297 : GNUNET_TIME_relative_to_absolute (
6298 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
6299 /* continue with inner message */
6300 /* FIXME: check that inbox is NOT a DV Box, fragment or another
6301 reliability box (not allowed!) */
6302 cmc->mh = inbox;
6303 demultiplex_with_cmc (cmc);
6304}
6305
6306
6307/**
6308 * Check if we have advanced to another age since the last time. If
6309 * so, purge ancient statistics (more than GOODPUT_AGING_SLOTS before
6310 * the current age)
6311 *
6312 * @param[in,out] pd data to update
6313 * @param age current age
6314 */
6315static void
6316update_pd_age (struct PerformanceData *pd, unsigned int age)
6317{
6318 unsigned int sage;
6319
6320 if (age == pd->last_age)
6321 return; /* nothing to do */
6322 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
6323 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
6324 {
6325 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
6326
6327 the->bytes_sent = 0;
6328 the->bytes_received = 0;
6329 }
6330 pd->last_age = age;
6331}
6332
6333
6334/**
6335 * Update @a pd based on the latest @a rtt and the number of bytes
6336 * that were confirmed to be successfully transmitted.
6337 *
6338 * @param[in,out] pd data to update
6339 * @param rtt latest round-trip time
6340 * @param bytes_transmitted_ok number of bytes receiver confirmed as received
6341 */
6342static void
6343update_performance_data (struct PerformanceData *pd,
6344 struct GNUNET_TIME_Relative rtt,
6345 uint16_t bytes_transmitted_ok)
6346{
6347 uint64_t nval = rtt.rel_value_us;
6348 uint64_t oval = pd->aged_rtt.rel_value_us;
6349 unsigned int age = get_age ();
6350 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
6351
6352 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
6353 pd->aged_rtt = rtt;
6354 else
6355 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
6356 update_pd_age (pd, age);
6357 the->bytes_received += bytes_transmitted_ok;
6358}
6359
6360
6361/**
6362 * We have successfully transmitted data via @a q, update metrics.
6363 *
6364 * @param q queue to update
6365 * @param rtt round trip time observed
6366 * @param bytes_transmitted_ok number of bytes successfully transmitted
6367 */
6368static void
6369update_queue_performance (struct Queue *q,
6370 struct GNUNET_TIME_Relative rtt,
6371 uint16_t bytes_transmitted_ok)
6372{
6373 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
6374}
6375
6376
6377/**
6378 * We have successfully transmitted data via @a dvh, update metrics.
6379 *
6380 * @param dvh distance vector path data to update
6381 * @param rtt round trip time observed
6382 * @param bytes_transmitted_ok number of bytes successfully transmitted
6383 */
6384static void
6385update_dvh_performance (struct DistanceVectorHop *dvh,
6386 struct GNUNET_TIME_Relative rtt,
6387 uint16_t bytes_transmitted_ok)
6388{
6389 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
6390}
6391
6392
6393/**
6394 * We have completed transmission of @a pm, remove it from
6395 * the transmission queues (and if it is a fragment, continue
6396 * up the tree as necessary).
6397 *
6398 * @param pm pending message that was transmitted
6399 */
6400static void
6401completed_pending_message (struct PendingMessage *pm)
6402{
6403 struct PendingMessage *pos;
6404
6405 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6406 "Complete transmission of message %llu %u\n",
6407 pm->logging_uuid,
6408 pm->pmt);
6409 switch (pm->pmt)
6410 {
6411 case PMT_CORE:
6412 case PMT_RELIABILITY_BOX:
6413 /* Full message sent, we are done */
6414 client_send_response (pm);
6415 return;
6416
6417 case PMT_FRAGMENT_BOX:
6418 /* Fragment sent over reliable channel */
6419 pos = pm->frag_parent;
6420 GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
6421 free_pending_message (pm);
6422 /* check if subtree is done */
6423 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
6424 - sizeof(struct
6425 TransportFragmentBoxMessage)))
6426 &&
6427 (NULL != pos->frag_parent))
6428 {
6429 pm = pos;
6430 pos = pm->frag_parent;
6431 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
6432 {
6433 client_send_response (pm);
6434 return;
6435 }
6436 else if (PMT_DV_BOX == pm->pmt)
6437 {
6438 client_send_response (pos);
6439 return;
6440 }
6441 GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
6442 free_pending_message (pm);
6443 }
6444
6445 /* Was this the last applicable fragment? */
6446 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent) &&
6447 (pos->frag_off == pos->bytes_msg))
6448 client_send_response (pos);
6449 return;
6450
6451 case PMT_DV_BOX:
6452 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6453 "Completed transmission of message %llu (DV Box)\n",
6454 pm->logging_uuid);
6455 if (NULL != pm->frag_parent)
6456 {
6457 if (NULL != pm->bpm)
6458 {
6459 GNUNET_free (pm->bpm);
6460 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6461 "Freed bpm\n");
6462 }
6463 pos = pm->frag_parent;
6464 free_pending_message (pm);
6465 pos->bpm = NULL;
6466 client_send_response (pos);
6467 }
6468 else
6469 client_send_response (pm);
6470 return;
6471 }
6472}
6473
6474
6475/**
6476 * The @a pa was acknowledged, process the acknowledgement.
6477 *
6478 * @param pa the pending acknowledgement that was satisfied
6479 * @param ack_delay artificial delay from cumulative acks created by the
6480 * other peer
6481 */
6482static void
6483handle_acknowledged (struct PendingAcknowledgement *pa,
6484 struct GNUNET_TIME_Relative ack_delay)
6485{
6486 struct GNUNET_TIME_Relative delay;
6487
6488 delay = GNUNET_TIME_absolute_get_duration (pa->transmission_time);
6489 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
6490 if (NULL != pa->queue && 1 == pa->num_send)
6491 update_queue_performance (pa->queue, delay, pa->message_size);
6492 if (NULL != pa->dvh && 1 == pa->num_send)
6493 update_dvh_performance (pa->dvh, delay, pa->message_size);
6494 if (NULL != pa->pm)
6495 completed_pending_message (pa->pm);
6496 free_pending_acknowledgement (pa);
6497}
6498
6499
6500/**
6501 * Communicator gave us a reliability ack. Check it is well-formed.
6502 *
6503 * @param cls a `struct CommunicatorMessageContext` (unused)
6504 * @param ra the message that was received
6505 * @return #GNUNET_Ok if @a ra is well-formed
6506 */
6507static int
6508check_reliability_ack (void *cls,
6509 const struct TransportReliabilityAckMessage *ra)
6510{
6511 unsigned int n_acks;
6512
6513 (void) cls;
6514 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
6515 / sizeof(struct TransportCummulativeAckPayloadP);
6516 if (0 == n_acks)
6517 {
6518 GNUNET_break_op (0);
6519 return GNUNET_SYSERR;
6520 }
6521 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
6522 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
6523 {
6524 GNUNET_break_op (0);
6525 return GNUNET_SYSERR;
6526 }
6527 return GNUNET_OK;
6528}
6529
6530
6531/**
6532 * Communicator gave us a reliability ack. Process the request.
6533 *
6534 * @param cls a `struct CommunicatorMessageContext` (must call
6535 * #finish_cmc_handling() when done)
6536 * @param ra the message that was received
6537 */
6538static void
6539handle_reliability_ack (void *cls,
6540 const struct TransportReliabilityAckMessage *ra)
6541{
6542 struct CommunicatorMessageContext *cmc = cls;
6543 const struct TransportCummulativeAckPayloadP *ack;
6544 unsigned int n_acks;
6545 uint32_t ack_counter;
6546
6547 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
6548 / sizeof(struct TransportCummulativeAckPayloadP);
6549 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
6550 for (unsigned int i = 0; i < n_acks; i++)
6551 {
6552 struct PendingAcknowledgement *pa =
6553 GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
6554 if (NULL == pa)
6555 {
6556 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
6557 "Received ACK from %s with UUID %s which is unknown to us!\n",
6558 GNUNET_i2s (&cmc->im.sender),
6559 GNUNET_uuid2s (&ack[i].ack_uuid.value));
6560 GNUNET_STATISTICS_update (
6561 GST_stats,
6562 "# FRAGMENT_ACKS dropped, no matching pending message",
6563 1,
6564 GNUNET_NO);
6565 continue;
6566 }
6567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6568 "Received ACK from %s with UUID %s\n",
6569 GNUNET_i2s (&cmc->im.sender),
6570 GNUNET_uuid2s (&ack[i].ack_uuid.value));
6571 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
6572 }
6573
6574 ack_counter = htonl (ra->ack_counter);
6575 (void) ack_counter; /* silence compiler warning for now */
6576 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
6577 // (DV and/or Neighbour?)
6578 finish_cmc_handling (cmc);
6579}
6580
6581
6582/**
6583 * Communicator gave us a backchannel encapsulation. Check the message.
6584 *
6585 * @param cls a `struct CommunicatorMessageContext`
6586 * @param be the send message that was sent
6587 * @return #GNUNET_YES if message is well-formed
6588 */
6589static int
6590check_backchannel_encapsulation (
6591 void *cls,
6592 const struct TransportBackchannelEncapsulationMessage *be)
6593{
6594 uint16_t size = ntohs (be->header.size) - sizeof(*be);
6595 const struct GNUNET_MessageHeader *inbox =
6596 (const struct GNUNET_MessageHeader *) &be[1];
6597 const char *is;
6598 uint16_t isize;
6599
6600 (void) cls;
6601 if (ntohs (inbox->size) >= size)
6602 {
6603 GNUNET_break_op (0);
6604 return GNUNET_SYSERR;
6605 }
6606 isize = ntohs (inbox->size);
6607 is = ((const char *) inbox) + isize;
6608 size -= isize;
6609 if ('\0' != is[size - 1])
6610 {
6611 GNUNET_break_op (0);
6612 return GNUNET_SYSERR;
6613 }
6614 return GNUNET_YES;
6615}
6616
6617
6618/**
6619 * Communicator gave us a backchannel encapsulation. Process the request.
6620 * (We are the destination of the backchannel here.)
6621 *
6622 * @param cls a `struct CommunicatorMessageContext` (must call
6623 * #finish_cmc_handling() when done)
6624 * @param be the message that was received
6625 */
6626static void
6627handle_backchannel_encapsulation (
6628 void *cls,
6629 const struct TransportBackchannelEncapsulationMessage *be)
6630{
6631 struct CommunicatorMessageContext *cmc = cls;
6632 struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *cbi;
6633 struct GNUNET_MQ_Envelope *env;
6634 struct TransportClient *tc;
6635 const struct GNUNET_MessageHeader *inbox =
6636 (const struct GNUNET_MessageHeader *) &be[1];
6637 uint16_t isize = ntohs (inbox->size);
6638 const char *target_communicator = ((const char *) inbox) + isize;
6639 char *sender;
6640 char *self;
6641
6642 GNUNET_asprintf (&sender,
6643 "%s",
6644 GNUNET_i2s (&cmc->im.sender));
6645 GNUNET_asprintf (&self,
6646 "%s",
6647 GNUNET_i2s (&GST_my_identity));
6648
6649 /* Find client providing this communicator */
6650 for (tc = clients_head; NULL != tc; tc = tc->next)
6651 if ((CT_COMMUNICATOR == tc->type) &&
6652 (0 ==
6653 strcmp (tc->details.communicator.address_prefix, target_communicator)))
6654 break;
6655 if (NULL == tc)
6656 {
6657 char *stastr;
6658
6659 GNUNET_asprintf (
6660 &stastr,
6661 "# Backchannel message dropped: target communicator `%s' unknown",
6662 target_communicator);
6663 GNUNET_STATISTICS_update (GST_stats, stastr, 1, GNUNET_NO);
6664 GNUNET_free (stastr);
6665 finish_cmc_handling (cmc);
6666 return;
6667 }
6668 /* Finally, deliver backchannel message to communicator */
6669 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6670 "Delivering backchannel message from %s to %s of type %u to %s\n",
6671 sender,
6672 self,
6673 ntohs (inbox->type),
6674 target_communicator);
6675 env = GNUNET_MQ_msg_extra (
6676 cbi,
6677 isize,
6678 GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING);
6679 cbi->pid = cmc->im.sender;
6680 memcpy (&cbi[1], inbox, isize);
6681 GNUNET_MQ_send (tc->mq, env);
6682 finish_cmc_handling (cmc);
6683}
6684
6685
6686/**
6687 * Task called when we should check if any of the DV paths
6688 * we have learned to a target are due for garbage collection.
6689 *
6690 * Collects stale paths, and possibly frees the entire DV
6691 * entry if no paths are left. Otherwise re-schedules itself.
6692 *
6693 * @param cls a `struct DistanceVector`
6694 */
6695static void
6696path_cleanup_cb (void *cls)
6697{
6698 struct DistanceVector *dv = cls;
6699 struct DistanceVectorHop *pos;
6700
6701 dv->timeout_task = NULL;
6702 while (NULL != (pos = dv->dv_head))
6703 {
6704 GNUNET_assert (dv == pos->dv);
6705 if (GNUNET_TIME_absolute_get_remaining (pos->timeout).rel_value_us > 0)
6706 break;
6707 free_distance_vector_hop (pos);
6708 }
6709 if (NULL == pos)
6710 {
6711 free_dv_route (dv);
6712 return;
6713 }
6714 dv->timeout_task =
6715 GNUNET_SCHEDULER_add_at (pos->timeout, &path_cleanup_cb, dv);
6716}
6717
6718
6719static void
6720send_msg_from_cache (struct VirtualLink *vl)
6721{
6722
6723 const struct GNUNET_PeerIdentity target = vl->target;
6724
6725
6726 if ((GNUNET_YES == is_ring_buffer_full) || (0 < ring_buffer_head))
6727 {
6728 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
6729 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
6730 0;
6731 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
6732 ring_buffer_head;
6733 struct GNUNET_TRANSPORT_IncomingMessage im;
6734 struct CommunicatorMessageContext *cmc;
6735 struct RingBufferEntry *rbe;
6736 struct GNUNET_MessageHeader *mh;
6737
6738 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6739 "Sending from ring buffer, which has %u items\n",
6740 ring_buffer_head);
6741
6742 ring_buffer_head = 0;
6743 for (unsigned int i = 0; i < head; i++)
6744 {
6745 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
6746 cmc = rbe->cmc;
6747 mh = rbe->mh;
6748
6749 im = cmc->im;
6750 // mh = cmc->mh;
6751 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6752 "Sending to ring buffer target %s using vl target %s\n",
6753 GNUNET_i2s (&im.sender),
6754 GNUNET_i2s2 (&target));
6755 if (0 == GNUNET_memcmp (&target, &im.sender))
6756 {
6757 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6758 "Finish handling message of type %u and size %u\n",
6759 (unsigned int) ntohs (mh->type),
6760 (unsigned int) ntohs (mh->size));
6761 finish_handling_raw_message (vl, mh, cmc, GNUNET_NO);
6762 GNUNET_free (mh);
6763 }
6764 else
6765 {
6766 ring_buffer_copy[i] = rbe;
6767 ring_buffer_head++;
6768 }
6769 }
6770
6771 if ((GNUNET_YES == is_ring_buffer_full) && (RING_BUFFER_SIZE - 1 >
6772 ring_buffer_head))
6773 {
6774 is_ring_buffer_full = GNUNET_NO;
6775 }
6776
6777 for (unsigned int i = 0; i < ring_buffer_head; i++)
6778 {
6779 ring_buffer[i] = ring_buffer_copy[i];
6780 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6781 "ring_buffer_copy[i]->mh->type for i %u %u\n",
6782 i,
6783 ring_buffer_copy[i]->mh->type);
6784 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6785 "ring_buffer[i]->mh->type for i %u %u\n",
6786 i,
6787 ring_buffer[i]->mh->type);
6788 }
6789
6790 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6791 "%u items still in ring buffer\n",
6792 ring_buffer_head);
6793 }
6794
6795 if ((GNUNET_YES == is_ring_buffer_full) || (0 < ring_buffer_dv_head))
6796 {
6797 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
6798 struct PendingMessage *pm;
6799 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
6800 ring_buffer_dv_head :
6801 0;
6802 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
6803 RING_BUFFER_SIZE :
6804 ring_buffer_dv_head;
6805
6806 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6807 "Sending from ring buffer dv, which has %u items\n",
6808 ring_buffer_dv_head);
6809
6810 ring_buffer_dv_head = 0;
6811 for (unsigned int i = 0; i < head; i++)
6812 {
6813 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
6814
6815 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6816 "Sending to ring buffer target %s using vl target %s\n",
6817 GNUNET_i2s (&pm->target),
6818 GNUNET_i2s2 (&target));
6819 if (0 == GNUNET_memcmp (&target, &pm->target))
6820 {
6821 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6822 "Adding PendingMessage to vl, checking transmission.\n");
6823 pm->vl = vl;
6824 GNUNET_CONTAINER_MDLL_insert (vl,
6825 vl->pending_msg_head,
6826 vl->pending_msg_tail,
6827 pm);
6828
6829 check_vl_transmission (vl);
6830 }
6831 else
6832 {
6833 ring_buffer_dv_copy[i] = pm;
6834 ring_buffer_dv_head++;
6835 }
6836 }
6837
6838 if (is_ring_buffer_dv_full && (RING_BUFFER_SIZE - 1 > ring_buffer_dv_head))
6839 {
6840 is_ring_buffer_dv_full = GNUNET_NO;
6841 }
6842
6843 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
6844 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
6845
6846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6847 "%u items still in ring buffer dv.\n",
6848 ring_buffer_dv_head);
6849
6850 }
6851}
6852
6853
6854/**
6855 * The @a hop is a validated path to the respective target
6856 * peer and we should tell core about it -- and schedule
6857 * a job to revoke the state.
6858 *
6859 * @param hop a path to some peer that is the reason for activation
6860 */
6861static void
6862activate_core_visible_dv_path (struct DistanceVectorHop *hop)
6863{
6864 struct DistanceVector *dv = hop->dv;
6865 struct VirtualLink *vl;
6866
6867 vl = lookup_virtual_link (&dv->target);
6868 if (NULL == vl)
6869 {
6870
6871 vl = GNUNET_new (struct VirtualLink);
6872 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6873 "Creating new virtual link %p to %s using DV!\n",
6874 vl,
6875 GNUNET_i2s (&dv->target));
6876 vl->confirmed = GNUNET_YES;
6877 vl->message_uuid_ctr =
6878 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
6879 vl->target = dv->target;
6880 vl->core_recv_window = RECV_WINDOW_SIZE;
6881 vl->available_fc_window_size = DEFAULT_WINDOW_SIZE;
6882 vl->incoming_fc_window_size = DEFAULT_WINDOW_SIZE;
6883 GNUNET_break (GNUNET_YES ==
6884 GNUNET_CONTAINER_multipeermap_put (
6885 links,
6886 &vl->target,
6887 vl,
6888 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
6889 vl->dv = dv;
6890 dv->vl = vl;
6891 vl->visibility_task =
6892 GNUNET_SCHEDULER_add_at (hop->path_valid_until, &check_link_down, vl);
6893 consider_sending_fc (vl);
6894 /* We lacked a confirmed connection to the target
6895 before, so tell CORE about it (finally!) */
6896 cores_send_connect_info (&dv->target);
6897 send_msg_from_cache (vl);
6898 }
6899 else
6900 {
6901 /* Link was already up, remember dv is also now available and we are done */
6902 vl->dv = dv;
6903 dv->vl = vl;
6904 if (GNUNET_NO == vl->confirmed)
6905 {
6906 vl->confirmed = GNUNET_YES;
6907 vl->visibility_task =
6908 GNUNET_SCHEDULER_add_at (hop->path_valid_until, &check_link_down, vl);
6909 consider_sending_fc (vl);
6910 /* We lacked a confirmed connection to the target
6911 before, so tell CORE about it (finally!) */
6912 cores_send_connect_info (&dv->target);
6913 send_msg_from_cache (vl);
6914 }
6915 else
6916 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6917 "Virtual link to %s could now also use DV!\n",
6918 GNUNET_i2s (&dv->target));
6919 }
6920}
6921
6922
6923/**
6924 * We have learned a @a path through the network to some other peer, add it to
6925 * our DV data structure (returning #GNUNET_YES on success).
6926 *
6927 * We do not add paths if we have a sufficient number of shorter
6928 * paths to this target already (returning #GNUNET_NO).
6929 *
6930 * We also do not add problematic paths, like those where we lack the first
6931 * hop in our neighbour list (i.e. due to a topology change) or where some
6932 * non-first hop is in our neighbour list (returning #GNUNET_SYSERR).
6933 *
6934 * @param path the path we learned, path[0] should be us,
6935 * and then path contains a valid path from us to
6936 * `path[path_len-1]` path[1] should be a direct neighbour (we should check!)
6937 * @param path_len number of entries on the @a path, at least three!
6938 * @param network_latency how long does the message take from us to
6939 * `path[path_len-1]`? set to "forever" if unknown
6940 * @param path_valid_until how long is this path considered validated? Maybe
6941 * be zero.
6942 * @return #GNUNET_YES on success,
6943 * #GNUNET_NO if we have better path(s) to the target
6944 * #GNUNET_SYSERR if the path is useless and/or invalid
6945 * (i.e. path[1] not a direct neighbour
6946 * or path[i+1] is a direct neighbour for i>0)
6947 */
6948static int
6949learn_dv_path (const struct GNUNET_PeerIdentity *path,
6950 unsigned int path_len,
6951 struct GNUNET_TIME_Relative network_latency,
6952 struct GNUNET_TIME_Absolute path_valid_until)
6953{
6954 struct DistanceVectorHop *hop;
6955 struct DistanceVector *dv;
6956 struct Neighbour *next_hop;
6957 unsigned int shorter_distance;
6958
6959 if (path_len < 3)
6960 {
6961 /* what a boring path! not allowed! */
6962 GNUNET_break (0);
6963 return GNUNET_SYSERR;
6964 }
6965 GNUNET_assert (0 == GNUNET_memcmp (&GST_my_identity, &path[0]));
6966 next_hop = lookup_neighbour (&path[1]);
6967 if (NULL == next_hop)
6968 {
6969 /* next hop must be a neighbour, otherwise this whole thing is useless! */
6970 GNUNET_break (0);
6971 return GNUNET_SYSERR;
6972 }
6973 for (unsigned int i = 2; i < path_len; i++)
6974 if (NULL != lookup_neighbour (&path[i]))
6975 {
6976 /* Useless path: we have a direct connection to some hop
6977 in the middle of the path, so this one is not even
6978 terribly useful for redundancy */
6979 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
6980 "Path of %u hops useless: directly link to hop %u (%s)\n",
6981 path_len,
6982 i,
6983 GNUNET_i2s (&path[i]));
6984 GNUNET_STATISTICS_update (GST_stats,
6985 "# Useless DV path ignored: hop is neighbour",
6986 1,
6987 GNUNET_NO);
6988 return GNUNET_SYSERR;
6989 }
6990 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
6991 if (NULL == dv)
6992 {
6993 dv = GNUNET_new (struct DistanceVector);
6994 dv->target = path[path_len - 1];
6995 dv->timeout_task = GNUNET_SCHEDULER_add_delayed (DV_PATH_VALIDITY_TIMEOUT,
6996 &path_cleanup_cb,
6997 dv);
6998 GNUNET_assert (GNUNET_OK ==
6999 GNUNET_CONTAINER_multipeermap_put (
7000 dv_routes,
7001 &dv->target,
7002 dv,
7003 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
7004 }
7005 /* Check if we have this path already! */
7006 shorter_distance = 0;
7007 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
7008 pos = pos->next_dv)
7009 {
7010 if (pos->distance < path_len - 3)
7011 shorter_distance++;
7012 /* Note that the distances in 'pos' excludes us (path[0]),
7013 the next_hop (path[1]) and the target so we need to subtract three
7014 and check next_hop explicitly */
7015 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
7016 {
7017 int match = GNUNET_YES;
7018
7019 for (unsigned int i = 0; i < pos->distance; i++)
7020 {
7021 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
7022 {
7023 match = GNUNET_NO;
7024 break;
7025 }
7026 }
7027 if (GNUNET_YES == match)
7028 {
7029 struct GNUNET_TIME_Relative last_timeout;
7030
7031 /* Re-discovered known path, update timeout */
7032 GNUNET_STATISTICS_update (GST_stats,
7033 "# Known DV path refreshed",
7034 1,
7035 GNUNET_NO);
7036 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
7037 pos->timeout =
7038 GNUNET_TIME_relative_to_absolute (DV_PATH_VALIDITY_TIMEOUT);
7039 pos->path_valid_until =
7040 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
7041 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
7042 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
7043 if (0 <
7044 GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7045 activate_core_visible_dv_path (pos);
7046 if (last_timeout.rel_value_us <
7047 GNUNET_TIME_relative_subtract (DV_PATH_VALIDITY_TIMEOUT,
7048 DV_PATH_DISCOVERY_FREQUENCY)
7049 .rel_value_us)
7050 {
7051 /* Some peer send DV learn messages too often, we are learning
7052 the same path faster than it would be useful; do not forward! */
7053 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
7054 "Rediscovered path too quickly, not forwarding further\n");
7055 return GNUNET_NO;
7056 }
7057 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7058 "Refreshed known path to %s valid until %s, forwarding further\n",
7059 GNUNET_i2s (&dv->target),
7060 GNUNET_STRINGS_absolute_time_to_string (
7061 pos->path_valid_until));
7062 return GNUNET_YES;
7063 }
7064 }
7065 }
7066 /* Count how many shorter paths we have (incl. direct
7067 neighbours) before simply giving up on this one! */
7068 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
7069 {
7070 /* We have a shorter path already! */
7071 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7072 "Have many shorter DV paths %s, not forwarding further\n",
7073 GNUNET_i2s (&dv->target));
7074 return GNUNET_NO;
7075 }
7076 /* create new DV path entry */
7077 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7078 "Discovered new DV path to %s valid until %s\n",
7079 GNUNET_i2s (&dv->target),
7080 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
7081 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
7082 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7083 hop->next_hop = next_hop;
7084 hop->dv = dv;
7085 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
7086 memcpy (&hop[1],
7087 &path[2],
7088 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7089 hop->timeout = GNUNET_TIME_relative_to_absolute (DV_PATH_VALIDITY_TIMEOUT);
7090 hop->path_valid_until = path_valid_until;
7091 hop->distance = path_len - 3;
7092 hop->pd.aged_rtt = network_latency;
7093 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
7094 GNUNET_CONTAINER_MDLL_insert (neighbour,
7095 next_hop->dv_head,
7096 next_hop->dv_tail,
7097 hop);
7098 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7099 activate_core_visible_dv_path (hop);
7100 return GNUNET_YES;
7101}
7102
7103
7104/**
7105 * Communicator gave us a DV learn message. Check the message.
7106 *
7107 * @param cls a `struct CommunicatorMessageContext`
7108 * @param dvl the send message that was sent
7109 * @return #GNUNET_YES if message is well-formed
7110 */
7111static int
7112check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
7113{
7114 uint16_t size = ntohs (dvl->header.size);
7115 uint16_t num_hops = ntohs (dvl->num_hops);
7116 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
7117
7118 (void) cls;
7119 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
7120 {
7121 GNUNET_break_op (0);
7122 return GNUNET_SYSERR;
7123 }
7124 if (num_hops > MAX_DV_HOPS_ALLOWED)
7125 {
7126 GNUNET_break_op (0);
7127 return GNUNET_SYSERR;
7128 }
7129 for (unsigned int i = 0; i < num_hops; i++)
7130 {
7131 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
7132 {
7133 GNUNET_break_op (0);
7134 return GNUNET_SYSERR;
7135 }
7136 if (0 == GNUNET_memcmp (&GST_my_identity, &hops[i].hop))
7137 {
7138 GNUNET_break_op (0);
7139 return GNUNET_SYSERR;
7140 }
7141 }
7142 return GNUNET_YES;
7143}
7144
7145
7146/**
7147 * Build and forward a DV learn message to @a next_hop.
7148 *
7149 * @param next_hop peer to send the message to
7150 * @param msg message received
7151 * @param bi_history bitmask specifying hops on path that were bidirectional
7152 * @param nhops length of the @a hops array
7153 * @param hops path the message traversed so far
7154 * @param in_time when did we receive the message, used to calculate network
7155 * delay
7156 */
7157static void
7158forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop,
7159 const struct TransportDVLearnMessage *msg,
7160 uint16_t bi_history,
7161 uint16_t nhops,
7162 const struct DVPathEntryP *hops,
7163 struct GNUNET_TIME_Absolute in_time)
7164{
7165 struct Neighbour *n;
7166 struct VirtualLink *vl;
7167 struct DVPathEntryP *dhops;
7168 char buf[sizeof(struct TransportDVLearnMessage)
7169 + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
7170 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
7171 struct GNUNET_TIME_Relative nnd;
7172
7173 /* compute message for forwarding */
7174 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7175 "Forwarding DV learn message originating from %s to %s\n",
7176 GNUNET_i2s (&msg->initiator),
7177 GNUNET_i2s2 (next_hop));
7178 GNUNET_assert (nhops < MAX_DV_HOPS_ALLOWED);
7179 fwd->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN);
7180 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
7181 + (nhops + 1) * sizeof(struct DVPathEntryP));
7182 fwd->num_hops = htons (nhops + 1);
7183 fwd->bidirectional = htons (bi_history);
7184 nnd = GNUNET_TIME_relative_add (GNUNET_TIME_absolute_get_duration (in_time),
7185 GNUNET_TIME_relative_ntoh (
7186 msg->non_network_delay));
7187 fwd->non_network_delay = GNUNET_TIME_relative_hton (nnd);
7188 fwd->init_sig = msg->init_sig;
7189 fwd->initiator = msg->initiator;
7190 fwd->challenge = msg->challenge;
7191 fwd->monotonic_time = msg->monotonic_time;
7192 dhops = (struct DVPathEntryP *) &fwd[1];
7193 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
7194 dhops[nhops].hop = GST_my_identity;
7195 {
7196 struct DvHopPS dhp = {
7197 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP),
7198 .purpose.size = htonl (sizeof(dhp)),
7199 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
7200 .succ = *next_hop,
7201 .challenge = msg->challenge
7202 };
7203 GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
7204 &dhp,
7205 &dhops[nhops].hop_sig);
7206 }
7207 /*route_control_message_without_fc (next_hop,
7208 &fwd->header,
7209 RMO_UNCONFIRMED_ALLOWED);*/
7210 vl = lookup_virtual_link (next_hop);
7211 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7212 {
7213 route_control_message_without_fc (vl,
7214 &fwd->header,
7215 RMO_UNCONFIRMED_ALLOWED);
7216 }
7217 else
7218 {
7219 /* Use route via neighbour */
7220 n = lookup_neighbour (next_hop);
7221 if (NULL != n)
7222 route_via_neighbour (
7223 n,
7224 &fwd->header,
7225 RMO_UNCONFIRMED_ALLOWED);
7226 }
7227}
7228
7229
7230/**
7231 * Check signature of type #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR
7232 *
7233 * @param sender_monotonic_time monotonic time of the initiator
7234 * @param init the signer
7235 * @param challenge the challenge that was signed
7236 * @param init_sig signature presumably by @a init
7237 * @return #GNUNET_OK if the signature is valid
7238 */
7239static int
7240validate_dv_initiator_signature (
7241 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
7242 const struct GNUNET_PeerIdentity *init,
7243 const struct GNUNET_CRYPTO_ChallengeNonceP *challenge,
7244 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
7245{
7246 struct DvInitPS ip = { .purpose.purpose = htonl (
7247 GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR),
7248 .purpose.size = htonl (sizeof(ip)),
7249 .monotonic_time = sender_monotonic_time,
7250 .challenge = *challenge };
7251
7252 if (
7253 GNUNET_OK !=
7254 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR,
7255 &ip,
7256 init_sig,
7257 &init->public_key))
7258 {
7259 GNUNET_break_op (0);
7260 return GNUNET_SYSERR;
7261 }
7262 return GNUNET_OK;
7263}
7264
7265
7266/**
7267 * Closure for #dv_neighbour_selection and #dv_neighbour_transmission.
7268 */
7269struct NeighbourSelectionContext
7270{
7271 /**
7272 * Original message we received.
7273 */
7274 const struct TransportDVLearnMessage *dvl;
7275
7276 /**
7277 * The hops taken.
7278 */
7279 const struct DVPathEntryP *hops;
7280
7281 /**
7282 * Time we received the message.
7283 */
7284 struct GNUNET_TIME_Absolute in_time;
7285
7286 /**
7287 * Offsets of the selected peers.
7288 */
7289 uint32_t selections[MAX_DV_DISCOVERY_SELECTION];
7290
7291 /**
7292 * Number of peers eligible for selection.
7293 */
7294 unsigned int num_eligible;
7295
7296 /**
7297 * Number of peers that were selected for forwarding.
7298 */
7299 unsigned int num_selections;
7300
7301 /**
7302 * Number of hops in @e hops
7303 */
7304 uint16_t nhops;
7305
7306 /**
7307 * Bitmap of bidirectional connections encountered.
7308 */
7309 uint16_t bi_history;
7310};
7311
7312
7313/**
7314 * Function called for each neighbour during #handle_dv_learn.
7315 *
7316 * @param cls a `struct NeighbourSelectionContext *`
7317 * @param pid identity of the peer
7318 * @param value a `struct Neighbour`
7319 * @return #GNUNET_YES (always)
7320 */
7321static int
7322dv_neighbour_selection (void *cls,
7323 const struct GNUNET_PeerIdentity *pid,
7324 void *value)
7325{
7326 struct NeighbourSelectionContext *nsc = cls;
7327
7328 (void) value;
7329 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
7330 return GNUNET_YES; /* skip initiator */
7331 for (unsigned int i = 0; i < nsc->nhops; i++)
7332 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
7333 return GNUNET_YES;
7334 /* skip peers on path */
7335 nsc->num_eligible++;
7336 return GNUNET_YES;
7337}
7338
7339
7340/**
7341 * Function called for each neighbour during #handle_dv_learn.
7342 * We call #forward_dv_learn() on the neighbour(s) selected
7343 * during #dv_neighbour_selection().
7344 *
7345 * @param cls a `struct NeighbourSelectionContext *`
7346 * @param pid identity of the peer
7347 * @param value a `struct Neighbour`
7348 * @return #GNUNET_YES (always)
7349 */
7350static int
7351dv_neighbour_transmission (void *cls,
7352 const struct GNUNET_PeerIdentity *pid,
7353 void *value)
7354{
7355 struct NeighbourSelectionContext *nsc = cls;
7356
7357 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7358 "transmission %s\n",
7359 GNUNET_i2s (pid));
7360 (void) value;
7361 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
7362 return GNUNET_YES; /* skip initiator */
7363 for (unsigned int i = 0; i < nsc->nhops; i++)
7364 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
7365 return GNUNET_YES;
7366 /* skip peers on path */
7367 for (unsigned int i = 0; i < nsc->num_selections; i++)
7368 {
7369 if (nsc->selections[i] == nsc->num_eligible)
7370 {
7371 forward_dv_learn (pid,
7372 nsc->dvl,
7373 nsc->bi_history,
7374 nsc->nhops,
7375 nsc->hops,
7376 nsc->in_time);
7377 break;
7378 }
7379 }
7380 nsc->num_eligible++;
7381 return GNUNET_YES;
7382}
7383
7384
7385/**
7386 * Computes the number of neighbours we should forward a DVInit
7387 * message to given that it has so far taken @a hops_taken hops
7388 * though the network and that the number of neighbours we have
7389 * in total is @a neighbour_count, out of which @a eligible_count
7390 * are not yet on the path.
7391 *
7392 * NOTE: technically we might want to include NSE in the formula to
7393 * get a better grip on the overall network size. However, for now
7394 * using NSE here would create a dependency issue in the build system.
7395 * => Left for later, hardcoded to 50 for now.
7396 *
7397 * The goal of the fomula is that we want to reach a total of LOG(NSE)
7398 * peers via DV (`target_total`). We want the reach to be spread out
7399 * over various distances to the origin, with a bias towards shorter
7400 * distances.
7401 *
7402 * We make the strong assumption that the network topology looks
7403 * "similar" at other hops, in particular the @a neighbour_count
7404 * should be comparable at other hops.
7405 *
7406 * If the local neighbourhood is densely connected, we expect that @a
7407 * eligible_count is close to @a neighbour_count minus @a hops_taken
7408 * as a lot of the path is already known. In that case, we should
7409 * forward to few(er) peers to try to find a path out of the
7410 * neighbourhood. OTOH, if @a eligible_count is close to @a
7411 * neighbour_count, we should forward to many peers as we are either
7412 * still close to the origin (i.e. @a hops_taken is small) or because
7413 * we managed to get beyond a local cluster. We express this as
7414 * the `boost_factor` using the square of the fraction of eligible
7415 * neighbours (so if only 50% are eligible, we boost by 1/4, but if
7416 * 99% are eligible, the 'boost' will be almost 1).
7417 *
7418 * Second, the more hops we have taken, the larger the problem of an
7419 * exponential traffic explosion gets. So we take the `target_total`,
7420 * and compute our degree such that at each distance d 2^{-d} peers
7421 * are selected (corrected by the `boost_factor`).
7422 *
7423 * @param hops_taken number of hops DVInit has travelled so far
7424 * @param neighbour_count number of neighbours we have in total
7425 * @param eligible_count number of neighbours we could in
7426 * theory forward to
7427 */
7428static unsigned int
7429calculate_fork_degree (unsigned int hops_taken,
7430 unsigned int neighbour_count,
7431 unsigned int eligible_count)
7432{
7433 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
7434 double eligible_ratio =
7435 ((double) eligible_count) / ((double) neighbour_count);
7436 double boost_factor = eligible_ratio * eligible_ratio;
7437 unsigned int rnd;
7438 double left;
7439
7440 if (hops_taken >= 64)
7441 {
7442 GNUNET_break (0);
7443 return 0; /* precaution given bitshift below */
7444 }
7445 for (unsigned int i = 1; i < hops_taken; i++)
7446 {
7447 /* For each hop, subtract the expected number of targets
7448 reached at distance d (so what remains divided by 2^d) */
7449 target_total -= (target_total * boost_factor / (1LLU << i));
7450 }
7451 rnd =
7452 (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
7453 /* round up or down probabilistically depending on how close we were
7454 when floor()ing to rnd */
7455 left = target_total - (double) rnd;
7456 if (UINT32_MAX * left >
7457 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX))
7458 rnd++; /* round up */
7459 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7460 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
7461 hops_taken,
7462 rnd,
7463 eligible_count,
7464 neighbour_count);
7465 return rnd;
7466}
7467
7468
7469/**
7470 * Function called when peerstore is done storing a DV monotonic time.
7471 *
7472 * @param cls a `struct Neighbour`
7473 * @param success #GNUNET_YES if peerstore was successful
7474 */
7475static void
7476neighbour_store_dvmono_cb (void *cls, int success)
7477{
7478 struct Neighbour *n = cls;
7479
7480 n->sc = NULL;
7481 if (GNUNET_YES != success)
7482 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
7483 "Failed to store other peer's monotonic time in peerstore!\n");
7484}
7485
7486
7487/**
7488 * Communicator gave us a DV learn message. Process the request.
7489 *
7490 * @param cls a `struct CommunicatorMessageContext` (must call
7491 * #finish_cmc_handling() when done)
7492 * @param dvl the message that was received
7493 */
7494static void
7495handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
7496{
7497 struct CommunicatorMessageContext *cmc = cls;
7498 enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc;
7499 int bi_hop;
7500 uint16_t nhops;
7501 uint16_t bi_history;
7502 const struct DVPathEntryP *hops;
7503 int do_fwd;
7504 int did_initiator;
7505 struct GNUNET_TIME_Absolute in_time;
7506 struct Neighbour *n;
7507
7508 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
7509 bi_history = ntohs (dvl->bidirectional);
7510 hops = (const struct DVPathEntryP *) &dvl[1];
7511 if (0 == nhops)
7512 {
7513 /* sanity check */
7514 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
7515 {
7516 GNUNET_break (0);
7517 finish_cmc_handling (cmc);
7518 return;
7519 }
7520 }
7521 else
7522 {
7523 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7524 "handle dv learn message last hop %s\n",
7525 GNUNET_i2s (&hops[nhops - 1].hop));
7526 /* sanity check */
7527 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
7528 {
7529 GNUNET_break (0);
7530 finish_cmc_handling (cmc);
7531 return;
7532 }
7533 }
7534
7535 GNUNET_assert (CT_COMMUNICATOR == cmc->tc->type);
7536 cc = cmc->tc->details.communicator.cc;
7537 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
7538 cc); // FIXME: add bi-directional flag to cc?
7539 in_time = GNUNET_TIME_absolute_get ();
7540
7541 /* continue communicator here, everything else can happen asynchronous! */
7542 finish_cmc_handling (cmc);
7543
7544 n = lookup_neighbour (&dvl->initiator);
7545 if (NULL != n)
7546 {
7547 if ((n->dv_monotime_available == GNUNET_YES) &&
7548 (GNUNET_TIME_absolute_ntoh (dvl->monotonic_time).abs_value_us <
7549 n->last_dv_learn_monotime.abs_value_us))
7550 {
7551 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7552 "DV learn from %s discarded due to time travel",
7553 GNUNET_i2s (&dvl->initiator));
7554 GNUNET_STATISTICS_update (GST_stats,
7555 "# DV learn discarded due to time travel",
7556 1,
7557 GNUNET_NO);
7558 return;
7559 }
7560 if (GNUNET_OK != validate_dv_initiator_signature (dvl->monotonic_time,
7561 &dvl->initiator,
7562 &dvl->challenge,
7563 &dvl->init_sig))
7564 {
7565 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7566 "DV learn signature from %s invalid\n",
7567 GNUNET_i2s (&dvl->initiator));
7568 GNUNET_break_op (0);
7569 return;
7570 }
7571 n->last_dv_learn_monotime = GNUNET_TIME_absolute_ntoh (dvl->monotonic_time);
7572 if (GNUNET_YES == n->dv_monotime_available)
7573 {
7574 if (NULL != n->sc)
7575 {
7576 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7577 "store cancel\n");
7578 GNUNET_PEERSTORE_store_cancel (n->sc);
7579 }
7580 n->sc =
7581 GNUNET_PEERSTORE_store (peerstore,
7582 "transport",
7583 &dvl->initiator,
7584 GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME,
7585 &dvl->monotonic_time,
7586 sizeof(dvl->monotonic_time),
7587 GNUNET_TIME_UNIT_FOREVER_ABS,
7588 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
7589 &neighbour_store_dvmono_cb,
7590 n);
7591 }
7592 }
7593 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
7594 If signature verification load too high, implement random drop strategy */
7595 for (unsigned int i = 0; i < nhops; i++)
7596 {
7597 struct DvHopPS dhp = { .purpose.purpose =
7598 htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP),
7599 .purpose.size = htonl (sizeof(dhp)),
7600 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
7601 .succ = (nhops == i + 1) ? GST_my_identity
7602 : hops[i + 1].hop,
7603 .challenge = dvl->challenge };
7604
7605 if (GNUNET_OK !=
7606 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP,
7607 &dhp,
7608 &hops[i].hop_sig,
7609 &hops[i].hop.public_key))
7610 {
7611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7612 "DV learn from %s signature of hop %u invalid\n",
7613 GNUNET_i2s (&dvl->initiator),
7614 i);
7615 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7616 "signature of hop %s invalid\n",
7617 GNUNET_i2s (&hops[i].hop));
7618 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7619 "pred %s\n",
7620 GNUNET_i2s (&dhp.pred));
7621 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7622 "succ %s\n",
7623 GNUNET_i2s (&dhp.succ));
7624 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7625 "hash %s\n",
7626 GNUNET_sh2s (&dhp.challenge.value));
7627 GNUNET_break_op (0);
7628 return;
7629 }
7630 }
7631 if (GNUNET_EXTRA_LOGGING > 0)
7632 {
7633 char *path;
7634
7635 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
7636 for (unsigned int i = 0; i < nhops; i++)
7637 {
7638 char *tmp;
7639
7640 GNUNET_asprintf (&tmp,
7641 "%s%s%s",
7642 path,
7643 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
7644 GNUNET_i2s (&hops[i].hop));
7645 GNUNET_free (path);
7646 path = tmp;
7647 }
7648 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7649 "Received DVInit via %s%s%s\n",
7650 path,
7651 bi_hop ? "<->" : "-->",
7652 GNUNET_i2s (&GST_my_identity));
7653 GNUNET_free (path);
7654 }
7655 do_fwd = GNUNET_YES;
7656 if (0 == GNUNET_memcmp (&GST_my_identity, &dvl->initiator))
7657 {
7658 struct GNUNET_PeerIdentity path[nhops + 1];
7659 struct GNUNET_TIME_Relative host_latency_sum;
7660 struct GNUNET_TIME_Relative latency;
7661 struct GNUNET_TIME_Relative network_latency;
7662
7663 /* We initiated this, learn the forward path! */
7664 path[0] = GST_my_identity;
7665 path[1] = hops[0].hop;
7666 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
7667
7668 // Need also something to lookup initiation time
7669 // to compute RTT! -> add RTT argument here?
7670 latency = GNUNET_TIME_absolute_get_duration (GNUNET_TIME_absolute_ntoh (
7671 dvl->monotonic_time));
7672 GNUNET_assert (latency.rel_value_us >= host_latency_sum.rel_value_us);
7673 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
7674 // (based on dvl->challenge, we can identify time of origin!)
7675
7676 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
7677 /* assumption: latency on all links is the same */
7678 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
7679
7680 for (unsigned int i = 2; i <= nhops; i++)
7681 {
7682 struct GNUNET_TIME_Relative ilat;
7683
7684 /* assumption: linear latency increase per hop */
7685 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
7686 path[i] = hops[i - 1].hop;
7687 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7688 "Learned path with %u hops to %s with latency %s\n",
7689 i,
7690 GNUNET_i2s (&path[i]),
7691 GNUNET_STRINGS_relative_time_to_string (ilat, GNUNET_YES));
7692 learn_dv_path (path,
7693 i + 1,
7694 ilat,
7695 GNUNET_TIME_relative_to_absolute (
7696 ADDRESS_VALIDATION_LIFETIME));
7697 }
7698 /* as we initiated, do not forward again (would be circular!) */
7699 do_fwd = GNUNET_NO;
7700 return;
7701 }
7702 if (bi_hop)
7703 {
7704 /* last hop was bi-directional, we could learn something here! */
7705 struct GNUNET_PeerIdentity path[nhops + 2];
7706
7707 path[0] = GST_my_identity;
7708 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
7709 for (unsigned int i = 0; i < nhops; i++)
7710 {
7711 int iret;
7712
7713 if (0 == (bi_history & (1 << i)))
7714 break; /* i-th hop not bi-directional, stop learning! */
7715 if (i == nhops - 1)
7716 {
7717 path[i + 2] = dvl->initiator;
7718 }
7719 else
7720 {
7721 path[i + 2] = hops[nhops - i - 2].hop;
7722 }
7723
7724 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7725 "Learned inverse path with %u hops to %s\n",
7726 i + 2,
7727 GNUNET_i2s (&path[i + 2]));
7728 iret = learn_dv_path (path,
7729 i + 3,
7730 GNUNET_TIME_UNIT_FOREVER_REL,
7731 GNUNET_TIME_relative_to_absolute (
7732 ADDRESS_VALIDATION_LIFETIME));
7733 if (GNUNET_SYSERR == iret)
7734 {
7735 /* path invalid or too long to be interesting for US, thus should also
7736 not be interesting to our neighbours, cut path when forwarding to
7737 'i' hops, except of course for the one that goes back to the
7738 initiator */
7739 GNUNET_STATISTICS_update (GST_stats,
7740 "# DV learn not forwarded due invalidity of path",
7741 1,
7742 GNUNET_NO);
7743 do_fwd = GNUNET_NO;
7744 break;
7745 }
7746 if ((GNUNET_NO == iret) && (nhops == i + 1))
7747 {
7748 /* we have better paths, and this is the longest target,
7749 so there cannot be anything interesting later */
7750 GNUNET_STATISTICS_update (GST_stats,
7751 "# DV learn not forwarded, got better paths",
7752 1,
7753 GNUNET_NO);
7754 do_fwd = GNUNET_NO;
7755 break;
7756 }
7757 }
7758 }
7759 if (MAX_DV_HOPS_ALLOWED == nhops)
7760 {
7761 /* At limit, we're out of here! */
7762 return;
7763 }
7764
7765 /* Forward to initiator, if path non-trivial and possible */
7766 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
7767 did_initiator = GNUNET_NO;
7768 if ((1 <= nhops) &&
7769 (GNUNET_YES ==
7770 GNUNET_CONTAINER_multipeermap_contains (neighbours, &dvl->initiator)))
7771 {
7772 /* send back to origin! */
7773 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7774 "Sending DVL back to initiator %s\n",
7775 GNUNET_i2s (&dvl->initiator));
7776 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
7777 did_initiator = GNUNET_YES;
7778 }
7779 /* We forward under two conditions: either we still learned something
7780 ourselves (do_fwd), or the path was darn short and thus the initiator is
7781 likely to still be very interested in this (and we did NOT already
7782 send it back to the initiator) */
7783 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
7784 (GNUNET_NO == did_initiator)))
7785 {
7786 /* Pick random neighbours that are not yet on the path */
7787 struct NeighbourSelectionContext nsc;
7788 unsigned int n_cnt;
7789
7790 n_cnt = GNUNET_CONTAINER_multipeermap_size (neighbours);
7791 nsc.nhops = nhops;
7792 nsc.dvl = dvl;
7793 nsc.bi_history = bi_history;
7794 nsc.hops = hops;
7795 nsc.in_time = in_time;
7796 nsc.num_eligible = 0;
7797 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
7798 &dv_neighbour_selection,
7799 &nsc);
7800 if (0 == nsc.num_eligible)
7801 return; /* done here, cannot forward to anyone else */
7802 nsc.num_selections = calculate_fork_degree (nhops, n_cnt, nsc.num_eligible);
7803 nsc.num_selections =
7804 GNUNET_MIN (MAX_DV_DISCOVERY_SELECTION, nsc.num_selections);
7805 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7806 "Forwarding DVL to %u other peers\n",
7807 nsc.num_selections);
7808 for (unsigned int i = 0; i < nsc.num_selections; i++)
7809 nsc.selections[i] =
7810 (nsc.num_selections == n_cnt)
7811 ? i /* all were selected, avoid collisions by chance */
7812 : GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, n_cnt);
7813 nsc.num_eligible = 0;
7814 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
7815 &dv_neighbour_transmission,
7816 &nsc);
7817 }
7818}
7819
7820
7821/**
7822 * Communicator gave us a DV box. Check the message.
7823 *
7824 * @param cls a `struct CommunicatorMessageContext`
7825 * @param dvb the send message that was sent
7826 * @return #GNUNET_YES if message is well-formed
7827 */
7828static int
7829check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
7830{
7831 uint16_t size = ntohs (dvb->header.size);
7832 uint16_t num_hops = ntohs (dvb->num_hops);
7833 const struct GNUNET_PeerIdentity *hops =
7834 (const struct GNUNET_PeerIdentity *) &dvb[1];
7835
7836 (void) cls;
7837 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
7838 + sizeof(struct GNUNET_MessageHeader))
7839 {
7840 GNUNET_break_op (0);
7841 return GNUNET_SYSERR;
7842 }
7843 /* This peer must not be on the path */
7844 for (unsigned int i = 0; i < num_hops; i++)
7845 if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
7846 {
7847 GNUNET_break_op (0);
7848 return GNUNET_SYSERR;
7849 }
7850 return GNUNET_YES;
7851}
7852
7853
7854/**
7855 * Create a DV Box message and queue it for transmission to
7856 * @a next_hop.
7857 *
7858 * @param next_hop peer to receive the message next
7859 * @param total_hops how many hops did the message take so far
7860 * @param num_hops length of the @a hops array
7861 * @param origin origin of the message
7862 * @param hops next peer(s) to the destination, including destination
7863 * @param payload payload of the box
7864 * @param payload_size number of bytes in @a payload
7865 */
7866static void
7867forward_dv_box (struct Neighbour *next_hop,
7868 struct TransportDVBoxMessage *hdr,
7869 uint16_t total_hops,
7870 uint16_t num_hops,
7871 const struct GNUNET_PeerIdentity *hops,
7872 const void *enc_payload,
7873 uint16_t enc_payload_size)
7874{
7875 struct VirtualLink *vl = next_hop->vl;
7876 struct PendingMessage *pm;
7877 size_t msg_size = sizeof(struct TransportDVBoxMessage)
7878 + num_hops * sizeof(struct GNUNET_PeerIdentity)
7879 + enc_payload_size;
7880 char *buf;
7881 char msg_buf[msg_size] GNUNET_ALIGN;
7882 struct GNUNET_PeerIdentity *dhops;
7883
7884 hdr->num_hops = htons (num_hops);
7885 hdr->total_hops = htons (total_hops);
7886 hdr->header.size = htons (msg_size);
7887 memcpy (msg_buf, hdr, sizeof(*hdr));
7888 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
7889 TransportDVBoxMessage)];
7890 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
7891 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
7892
7893 if (GNUNET_YES == ntohs (hdr->without_fc))
7894 {
7895 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7896 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
7897 enc_payload_size,
7898 GNUNET_i2s (&next_hop->pid),
7899 (unsigned int) num_hops,
7900 (unsigned int) total_hops);
7901 route_via_neighbour (next_hop, (const struct
7902 GNUNET_MessageHeader *) msg_buf,
7903 RMO_ANYTHING_GOES);
7904 }
7905 else
7906 {
7907 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
7908 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7909 "2 created pm %p storing vl %p \n",
7910 pm,
7911 vl);
7912 pm->pmt = PMT_DV_BOX;
7913 pm->vl = vl;
7914 pm->target = next_hop->pid;
7915 pm->timeout = GNUNET_TIME_relative_to_absolute (DV_FORWARD_TIMEOUT);
7916 pm->logging_uuid = logging_uuid_gen++;
7917 pm->prefs = GNUNET_MQ_PRIO_BACKGROUND;
7918 pm->bytes_msg = msg_size;
7919 buf = (char *) &pm[1];
7920 memcpy (buf, msg_buf, msg_size);
7921
7922 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7923 "Created pending message %llu for DV Box with next hop %s (%u/%u)\n",
7924 pm->logging_uuid,
7925 GNUNET_i2s (&next_hop->pid),
7926 (unsigned int) num_hops,
7927 (unsigned int) total_hops);
7928
7929 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7930 {
7931 GNUNET_CONTAINER_MDLL_insert (vl,
7932 vl->pending_msg_head,
7933 vl->pending_msg_tail,
7934 pm);
7935
7936 check_vl_transmission (vl);
7937 }
7938 else
7939 {
7940 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7941 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
7942
7943 ring_buffer_dv[ring_buffer_dv_head] = pm;
7944 if (RING_BUFFER_SIZE - 1 == ring_buffer_dv_head)
7945 {
7946 ring_buffer_dv_head = 0;
7947 is_ring_buffer_dv_full = GNUNET_YES;
7948 }
7949 else
7950 ring_buffer_dv_head++;
7951
7952 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7953 "%u items stored in DV ring buffer\n",
7954 ring_buffer_dv_head);
7955 }
7956 }
7957}
7958
7959
7960/**
7961 * Free data structures associated with @a b.
7962 *
7963 * @param b data structure to release
7964 */
7965static void
7966free_backtalker (struct Backtalker *b)
7967{
7968 if (NULL != b->get)
7969 {
7970 GNUNET_PEERSTORE_iterate_cancel (b->get);
7971 b->get = NULL;
7972 GNUNET_assert (NULL != b->cmc);
7973 finish_cmc_handling (b->cmc);
7974 b->cmc = NULL;
7975 }
7976 if (NULL != b->task)
7977 {
7978 GNUNET_SCHEDULER_cancel (b->task);
7979 b->task = NULL;
7980 }
7981 if (NULL != b->sc)
7982 {
7983 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7984 "store cancel\n");
7985 GNUNET_PEERSTORE_store_cancel (b->sc);
7986 b->sc = NULL;
7987 }
7988 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7989 "Removing backtalker for %s\n",
7990 GNUNET_i2s (&b->pid));
7991 GNUNET_assert (
7992 GNUNET_YES ==
7993 GNUNET_CONTAINER_multipeermap_remove (backtalkers, &b->pid, b));
7994 GNUNET_free (b);
7995}
7996
7997
7998/**
7999 * Callback to free backtalker records.
8000 *
8001 * @param cls NULL
8002 * @param pid unused
8003 * @param value a `struct Backtalker`
8004 * @return #GNUNET_OK (always)
8005 */
8006static int
8007free_backtalker_cb (void *cls,
8008 const struct GNUNET_PeerIdentity *pid,
8009 void *value)
8010{
8011 struct Backtalker *b = value;
8012
8013 (void) cls;
8014 (void) pid;
8015 free_backtalker (b);
8016 return GNUNET_OK;
8017}
8018
8019
8020/**
8021 * Function called when it is time to clean up a backtalker.
8022 *
8023 * @param cls a `struct Backtalker`
8024 */
8025static void
8026backtalker_timeout_cb (void *cls)
8027{
8028 struct Backtalker *b = cls;
8029
8030 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8031 "backtalker timeout.\n");
8032 b->task = NULL;
8033 if (0 != GNUNET_TIME_absolute_get_remaining (b->timeout).rel_value_us)
8034 {
8035 b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b);
8036 return;
8037 }
8038 GNUNET_assert (NULL == b->sc);
8039 free_backtalker (b);
8040}
8041
8042
8043/**
8044 * Function called with the monotonic time of a backtalker
8045 * by PEERSTORE. Updates the time and continues processing.
8046 *
8047 * @param cls a `struct Backtalker`
8048 * @param record the information found, NULL for the last call
8049 * @param emsg error message
8050 */
8051static void
8052backtalker_monotime_cb (void *cls,
8053 const struct GNUNET_PEERSTORE_Record *record,
8054 const char *emsg)
8055{
8056 struct Backtalker *b = cls;
8057 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8058 struct GNUNET_TIME_Absolute mt;
8059
8060 (void) emsg;
8061 if (NULL == record)
8062 {
8063 /* we're done with #backtalker_monotime_cb() invocations,
8064 continue normal processing */
8065 b->get = NULL;
8066 GNUNET_assert (NULL != b->cmc);
8067 b->cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
8068 if (0 != b->body_size)
8069 demultiplex_with_cmc (b->cmc);
8070 else
8071 finish_cmc_handling (b->cmc);
8072 b->cmc = NULL;
8073 return;
8074 }
8075 if (sizeof(*mtbe) != record->value_size)
8076 {
8077 GNUNET_break (0);
8078 return;
8079 }
8080 mtbe = record->value;
8081 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
8082 if (mt.abs_value_us > b->monotonic_time.abs_value_us)
8083 {
8084 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8085 "Backtalker message from %s dropped, monotime in the past\n",
8086 GNUNET_i2s (&b->pid));
8087 GNUNET_STATISTICS_update (
8088 GST_stats,
8089 "# Backchannel messages dropped: monotonic time not increasing",
8090 1,
8091 GNUNET_NO);
8092 b->monotonic_time = mt;
8093 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
8094 */
8095 b->body_size = 0;
8096 return;
8097 }
8098}
8099
8100
8101/**
8102 * Function called by PEERSTORE when the store operation of
8103 * a backtalker's monotonic time is complete.
8104 *
8105 * @param cls the `struct Backtalker`
8106 * @param success #GNUNET_OK on success
8107 */
8108static void
8109backtalker_monotime_store_cb (void *cls, int success)
8110{
8111 struct Backtalker *b = cls;
8112
8113 if (GNUNET_OK != success)
8114 {
8115 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
8116 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
8117 }
8118 b->sc = NULL;
8119 if (NULL != b->task)
8120 {
8121 GNUNET_SCHEDULER_cancel (b->task);
8122 b->task = NULL;
8123 }
8124 b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b);
8125}
8126
8127
8128/**
8129 * The backtalker @a b monotonic time changed. Update PEERSTORE.
8130 *
8131 * @param b a backtalker with updated monotonic time
8132 */
8133static void
8134update_backtalker_monotime (struct Backtalker *b)
8135{
8136 struct GNUNET_TIME_AbsoluteNBO mtbe;
8137
8138 if (NULL != b->sc)
8139 {
8140 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8141 "store cancel before store with sc %p\n",
8142 b->sc);
8143 /*GNUNET_PEERSTORE_store_cancel (b->sc);
8144 b->sc = NULL;*/
8145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8146 "store cancel before store with sc %p is null\n",
8147 b->sc);
8148 }
8149 else
8150 {
8151 GNUNET_SCHEDULER_cancel (b->task);
8152 b->task = NULL;
8153 }
8154 mtbe = GNUNET_TIME_absolute_hton (b->monotonic_time);
8155 b->sc =
8156 GNUNET_PEERSTORE_store (peerstore,
8157 "transport",
8158 &b->pid,
8159 GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME,
8160 &mtbe,
8161 sizeof(mtbe),
8162 GNUNET_TIME_UNIT_FOREVER_ABS,
8163 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
8164 &backtalker_monotime_store_cb,
8165 b);
8166}
8167
8168
8169/**
8170 * Communicator gave us a DV box. Process the request.
8171 *
8172 * @param cls a `struct CommunicatorMessageContext` (must call
8173 * #finish_cmc_handling() when done)
8174 * @param dvb the message that was received
8175 */
8176static void
8177handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8178{
8179 struct CommunicatorMessageContext *cmc = cls;
8180 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
8181 uint16_t num_hops = ntohs (dvb->num_hops);
8182 const struct GNUNET_PeerIdentity *hops =
8183 (const struct GNUNET_PeerIdentity *) &dvb[1];
8184 const char *enc_payload = (const char *) &hops[num_hops];
8185 uint16_t enc_payload_size =
8186 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
8187 struct DVKeyState key;
8188 struct GNUNET_HashCode hmac;
8189 const char *hdr;
8190 size_t hdr_len;
8191
8192 if (GNUNET_EXTRA_LOGGING > 0)
8193 {
8194 char *path;
8195
8196 path = GNUNET_strdup (GNUNET_i2s (&GST_my_identity));
8197 for (unsigned int i = 0; i < num_hops; i++)
8198 {
8199 char *tmp;
8200
8201 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
8202 GNUNET_free (path);
8203 path = tmp;
8204 }
8205 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8206 "Received DVBox with remaining path %s\n",
8207 path);
8208 GNUNET_free (path);
8209 }
8210
8211 if (num_hops > 0)
8212 {
8213 /* We're trying from the end of the hops array, as we may be
8214 able to find a shortcut unknown to the origin that way */
8215 for (int i = num_hops - 1; i >= 0; i--)
8216 {
8217 struct Neighbour *n;
8218
8219 if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
8220 {
8221 GNUNET_break_op (0);
8222 finish_cmc_handling (cmc);
8223 return;
8224 }
8225 n = lookup_neighbour (&hops[i]);
8226 if (NULL == n)
8227 continue;
8228 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8229 "Skipping %u/%u hops ahead while routing DV Box\n",
8230 i,
8231 num_hops);
8232
8233 forward_dv_box (n,
8234 (struct TransportDVBoxMessage *) dvb,
8235 ntohs (dvb->total_hops) + 1,
8236 num_hops - i - 1, /* number of hops left */
8237 &hops[i + 1], /* remaining hops */
8238 enc_payload,
8239 enc_payload_size);
8240 GNUNET_STATISTICS_update (GST_stats,
8241 "# DV hops skipped routing boxes",
8242 i,
8243 GNUNET_NO);
8244 GNUNET_STATISTICS_update (GST_stats,
8245 "# DV boxes routed (total)",
8246 1,
8247 GNUNET_NO);
8248 finish_cmc_handling (cmc);
8249 return;
8250 }
8251 /* Woopsie, next hop not in neighbours, drop! */
8252 GNUNET_STATISTICS_update (GST_stats,
8253 "# DV Boxes dropped: next hop unknown",
8254 1,
8255 GNUNET_NO);
8256 finish_cmc_handling (cmc);
8257 return;
8258 }
8259 /* We are the target. Unbox and handle message. */
8260 GNUNET_STATISTICS_update (GST_stats,
8261 "# DV boxes opened (ultimate target)",
8262 1,
8263 GNUNET_NO);
8264 cmc->total_hops = ntohs (dvb->total_hops);
8265
8266 // DH key derivation with received DV, could be garbage.
8267 struct GNUNET_HashCode km;
8268
8269 if (GNUNET_YES != GNUNET_CRYPTO_eddsa_kem_decaps (GST_my_private_key,
8270 &dvb->ephemeral_key,
8271 &km))
8272 {
8273 GNUNET_break_op (0);
8274 finish_cmc_handling (cmc);
8275 return;
8276 }
8277 dv_setup_key_state_from_km (&km, &dvb->iv, &key);
8278 hdr = (const char *) &dvb[1];
8279 hdr_len = ntohs (dvb->orig_size) - sizeof(*dvb) - sizeof(struct
8280 GNUNET_PeerIdentity)
8281 * ntohs (dvb->total_hops);
8282
8283 dv_hmac (&key, &hmac, hdr, hdr_len);
8284 if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
8285 {
8286 /* HMAC mismatch, discard! */
8287 GNUNET_break_op (0);
8288 finish_cmc_handling (cmc);
8289 return;
8290 }
8291 /* begin actual decryption */
8292 {
8293 struct Backtalker *b;
8294 struct GNUNET_TIME_Absolute monotime;
8295 struct TransportDVBoxPayloadP ppay;
8296 char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
8297 const struct GNUNET_MessageHeader *mh;
8298
8299 GNUNET_assert (hdr_len >=
8300 sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
8301 if (GNUNET_OK != dv_decrypt (&key, &ppay, hdr, sizeof(ppay)))
8302 {
8303 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
8304 "Error decrypting DV payload header\n");
8305 GNUNET_break_op (0);
8306 finish_cmc_handling (cmc);
8307 return;
8308 }
8309 if (GNUNET_OK != dv_decrypt (&key, body,
8310 &hdr[sizeof(ppay)], hdr_len - sizeof(ppay)))
8311 {
8312 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
8313 "Error decrypting DV payload\n");
8314 GNUNET_break_op (0);
8315 finish_cmc_handling (cmc);
8316 return;
8317 }
8318 mh = (const struct GNUNET_MessageHeader *) body;
8319 dv_key_clean (&key);
8320 if (ntohs (mh->size) != sizeof(body))
8321 {
8322 GNUNET_break_op (0);
8323 finish_cmc_handling (cmc);
8324 return;
8325 }
8326 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
8327 switch (ntohs (mh->type))
8328 {
8329 case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX:
8330 GNUNET_break_op (0);
8331 finish_cmc_handling (cmc);
8332 return;
8333
8334 case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN:
8335 GNUNET_break_op (0);
8336 finish_cmc_handling (cmc);
8337 return;
8338
8339 default:
8340 /* permitted, continue */
8341 break;
8342 }
8343 monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
8344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8345 "Decrypted backtalk from %s\n",
8346 GNUNET_i2s (&ppay.sender));
8347 b = GNUNET_CONTAINER_multipeermap_get (backtalkers, &ppay.sender);
8348 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
8349 {
8350 GNUNET_STATISTICS_update (
8351 GST_stats,
8352 "# Backchannel messages dropped: monotonic time not increasing",
8353 1,
8354 GNUNET_NO);
8355 finish_cmc_handling (cmc);
8356 return;
8357 }
8358 if ((NULL == b) ||
8359 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
8360 {
8361 /* Check signature */
8362 struct EphemeralConfirmationPS ec;
8363
8364 ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
8365 ec.target = GST_my_identity;
8366 ec.ephemeral_key = dvb->ephemeral_key;
8367 ec.purpose.size = htonl (sizeof(ec));
8368 ec.sender_monotonic_time = ppay.monotonic_time;
8369 if (
8370 GNUNET_OK !=
8371 GNUNET_CRYPTO_eddsa_verify (
8372 GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL,
8373 &ec,
8374 &ppay.sender_sig,
8375 &ppay.sender.public_key))
8376 {
8377 /* Signature invalid, discard! */
8378 GNUNET_break_op (0);
8379 finish_cmc_handling (cmc);
8380 return;
8381 }
8382 }
8383 /* Update sender, we now know the real origin! */
8384 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8385 "DVBox received for me from %s via %s\n",
8386 GNUNET_i2s2 (&ppay.sender),
8387 GNUNET_i2s (&cmc->im.sender));
8388 cmc->im.sender = ppay.sender;
8389
8390 if (NULL != b)
8391 {
8392 /* update key cache and mono time */
8393 b->last_ephemeral = dvb->ephemeral_key;
8394 b->monotonic_time = monotime;
8395 update_backtalker_monotime (b);
8396 b->timeout =
8397 GNUNET_TIME_relative_to_absolute (BACKCHANNEL_INACTIVITY_TIMEOUT);
8398 cmc->mh = mh;
8399 demultiplex_with_cmc (cmc);
8400 return;
8401 }
8402 /* setup data structure to cache signature AND check
8403 monotonic time with PEERSTORE before forwarding backchannel payload */
8404 b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
8405 b->pid = ppay.sender;
8406 b->body_size = sizeof(body);
8407 memcpy (&b[1], body, sizeof(body));
8408 GNUNET_assert (GNUNET_YES ==
8409 GNUNET_CONTAINER_multipeermap_put (
8410 backtalkers,
8411 &b->pid,
8412 b,
8413 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
8414 b->monotonic_time = monotime; /* NOTE: to be checked still! */
8415 b->cmc = cmc;
8416 b->timeout =
8417 GNUNET_TIME_relative_to_absolute (BACKCHANNEL_INACTIVITY_TIMEOUT);
8418 b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b);
8419 b->get =
8420 GNUNET_PEERSTORE_iterate (peerstore,
8421 "transport",
8422 &b->pid,
8423 GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME,
8424 &backtalker_monotime_cb,
8425 b);
8426 } /* end actual decryption */
8427}
8428
8429
8430/**
8431 * Client notified us about transmission from a peer. Process the request.
8432 *
8433 * @param cls a `struct TransportClient` which sent us the message
8434 * @param im the send message that was sent
8435 * @return #GNUNET_YES if message is well-formed
8436 */
8437static int
8438check_incoming_msg (void *cls,
8439 const struct GNUNET_TRANSPORT_IncomingMessage *im)
8440{
8441 struct TransportClient *tc = cls;
8442
8443 if (CT_COMMUNICATOR != tc->type)
8444 {
8445 GNUNET_break (0);
8446 return GNUNET_SYSERR;
8447 }
8448 GNUNET_MQ_check_boxed_message (im);
8449 return GNUNET_OK;
8450}
8451
8452
8453/**
8454 * Closure for #check_known_address.
8455 */
8456struct CheckKnownAddressContext
8457{
8458 /**
8459 * Set to the address we are looking for.
8460 */
8461 const char *address;
8462
8463 /**
8464 * Set to a matching validation state, if one was found.
8465 */
8466 struct ValidationState *vs;
8467};
8468
8469
8470/**
8471 * Test if the validation state in @a value matches the
8472 * address from @a cls.
8473 *
8474 * @param cls a `struct CheckKnownAddressContext`
8475 * @param pid unused (must match though)
8476 * @param value a `struct ValidationState`
8477 * @return #GNUNET_OK if not matching, #GNUNET_NO if match found
8478 */
8479static int
8480check_known_address (void *cls,
8481 const struct GNUNET_PeerIdentity *pid,
8482 void *value)
8483{
8484 struct CheckKnownAddressContext *ckac = cls;
8485 struct ValidationState *vs = value;
8486
8487 (void) pid;
8488 if (0 != strcmp (vs->address, ckac->address))
8489 return GNUNET_OK;
8490 ckac->vs = vs;
8491 return GNUNET_NO;
8492}
8493
8494
8495/**
8496 * Task run periodically to validate some address based on #validation_heap.
8497 *
8498 * @param cls NULL
8499 */
8500static void
8501validation_start_cb (void *cls);
8502
8503
8504/**
8505 * Set the time for next_challenge of @a vs to @a new_time.
8506 * Updates the heap and if necessary reschedules the job.
8507 *
8508 * @param vs validation state to update
8509 * @param new_time new time for revalidation
8510 */
8511static void
8512update_next_challenge_time (struct ValidationState *vs,
8513 struct GNUNET_TIME_Absolute new_time)
8514{
8515 struct GNUNET_TIME_Relative delta;
8516
8517 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
8518 return; /* be lazy */
8519 vs->next_challenge = new_time;
8520 if (NULL == vs->hn)
8521 vs->hn =
8522 GNUNET_CONTAINER_heap_insert (validation_heap, vs, new_time.abs_value_us);
8523 else
8524 GNUNET_CONTAINER_heap_update_cost (vs->hn, new_time.abs_value_us);
8525 if ((vs != GNUNET_CONTAINER_heap_peek (validation_heap)) &&
8526 (NULL != validation_task))
8527 return;
8528 if (NULL != validation_task)
8529 GNUNET_SCHEDULER_cancel (validation_task);
8530 /* randomize a bit */
8531 delta.rel_value_us =
8532 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
8533 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
8534 new_time = GNUNET_TIME_absolute_add (new_time, delta);
8535 validation_task =
8536 GNUNET_SCHEDULER_add_at (new_time, &validation_start_cb, NULL);
8537}
8538
8539
8540/**
8541 * Start address validation.
8542 *
8543 * @param pid peer the @a address is for
8544 * @param address an address to reach @a pid (presumably)
8545 */
8546static void
8547start_address_validation (const struct GNUNET_PeerIdentity *pid,
8548 const char *address)
8549{
8550 struct GNUNET_TIME_Absolute now;
8551 struct ValidationState *vs;
8552 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
8553
8554 (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
8555 pid,
8556 &check_known_address,
8557 &ckac);
8558 if (NULL != (vs = ckac.vs))
8559 {
8560 /* if 'vs' is not currently valid, we need to speed up retrying the
8561 * validation */
8562 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
8563 {
8564 /* reduce backoff as we got a fresh advertisement */
8565 vs->challenge_backoff =
8566 GNUNET_TIME_relative_min (FAST_VALIDATION_CHALLENGE_FREQ,
8567 GNUNET_TIME_relative_divide (
8568 vs->challenge_backoff,
8569 2));
8570 update_next_challenge_time (vs,
8571 GNUNET_TIME_relative_to_absolute (
8572 vs->challenge_backoff));
8573 }
8574 return;
8575 }
8576 now = GNUNET_TIME_absolute_get_monotonic (GST_cfg);
8577 vs = GNUNET_new (struct ValidationState);
8578 vs->pid = *pid;
8579 vs->valid_until =
8580 GNUNET_TIME_relative_to_absolute (ADDRESS_VALIDATION_LIFETIME);
8581 vs->first_challenge_use = now;
8582 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
8583 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
8584 &vs->challenge,
8585 sizeof(vs->challenge));
8586 vs->address = GNUNET_strdup (address);
8587 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8588 "Starting address validation `%s' of peer %s using challenge %s\n",
8589 address,
8590 GNUNET_i2s (pid),
8591 GNUNET_sh2s (&vs->challenge.value));
8592 GNUNET_assert (GNUNET_YES ==
8593 GNUNET_CONTAINER_multipeermap_put (
8594 validation_map,
8595 &vs->pid,
8596 vs,
8597 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
8598 update_next_challenge_time (vs, now);
8599}
8600
8601
8602static void
8603hello_for_incoming_cb (void *cls,
8604 const char *uri)
8605{
8606 const struct GNUNET_PeerIdentity *peer = cls;
8607 int pfx_len;
8608 const char *eou;
8609 char *address;
8610
8611 eou = strstr (uri,
8612 "://");
8613 pfx_len = eou - uri;
8614 eou += 3;
8615 GNUNET_asprintf (&address,
8616 "%.*s-%s",
8617 pfx_len,
8618 uri,
8619 eou);
8620
8621 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8622 "helo for client %s\n",
8623 address);
8624
8625 start_address_validation (peer, address);
8626 GNUNET_free (address);
8627}
8628
8629
8630/**
8631 * Function called by PEERSTORE for each matching record.
8632 *
8633 * @param cls closure, a `struct IncomingRequest`
8634 * @param record peerstore record information
8635 * @param emsg error message, or NULL if no errors
8636 */
8637static void
8638handle_hello_for_incoming (void *cls,
8639 const struct GNUNET_PeerIdentity *peer,
8640 const struct GNUNET_MessageHeader *hello,
8641 const char *emsg)
8642{
8643 struct IncomingRequest *ir = cls;
8644 struct GNUNET_HELLO_Builder *builder;
8645
8646 if (NULL != emsg)
8647 {
8648 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
8649 "Got failure from PEERSTORE: %s\n",
8650 emsg);
8651 return;
8652 }
8653 if (0 == GNUNET_memcmp (peer, &GST_my_identity))
8654 return;
8655 builder = GNUNET_HELLO_builder_new (peer);
8656 GNUNET_HELLO_builder_iterate (builder,
8657 (struct GNUNET_PeerIdentity *) peer,
8658 hello_for_incoming_cb,
8659 (struct GNUNET_PeerIdentity *) peer);
8660}
8661
8662
8663/**
8664 * Communicator gave us a transport address validation challenge. Process the
8665 * request.
8666 *
8667 * @param cls a `struct CommunicatorMessageContext` (must call
8668 * #finish_cmc_handling() when done)
8669 * @param tvc the message that was received
8670 */
8671static void
8672handle_validation_challenge (
8673 void *cls,
8674 const struct TransportValidationChallengeMessage *tvc)
8675{
8676 struct CommunicatorMessageContext *cmc = cls;
8677 struct TransportValidationResponseMessage tvr;
8678 struct VirtualLink *vl;
8679 struct GNUNET_TIME_RelativeNBO validity_duration;
8680 struct IncomingRequest *ir;
8681 struct Neighbour *n;
8682 struct GNUNET_PeerIdentity sender;
8683
8684 /* DV-routed messages are not allowed for validation challenges */
8685 if (cmc->total_hops > 0)
8686 {
8687 GNUNET_break_op (0);
8688 finish_cmc_handling (cmc);
8689 return;
8690 }
8691 validity_duration = cmc->im.expected_address_validity;
8692 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8693 "Received address validation challenge %s\n",
8694 GNUNET_sh2s (&tvc->challenge.value));
8695 /* If we have a virtual link, we use this mechanism to signal the
8696 size of the flow control window, and to allow the sender
8697 to ask for increases. If for us the virtual link is still down,
8698 we will always give a window size of zero. */
8699 tvr.header.type =
8700 htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE);
8701 tvr.header.size = htons (sizeof(tvr));
8702 tvr.reserved = htonl (0);
8703 tvr.challenge = tvc->challenge;
8704 tvr.origin_time = tvc->sender_time;
8705 tvr.validity_duration = validity_duration;
8706 {
8707 /* create signature */
8708 struct TransportValidationPS tvp = {
8709 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE),
8710 .purpose.size = htonl (sizeof(tvp)),
8711 .validity_duration = validity_duration,
8712 .challenge = tvc->challenge
8713 };
8714
8715 GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
8716 &tvp,
8717 &tvr.signature);
8718 }
8719 sender = cmc->im.sender;
8720 vl = lookup_virtual_link (&sender);
8721 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8722 {
8723 // route_control_message_without_fc (&cmc->im.sender,
8724 route_control_message_without_fc (vl,
8725 &tvr.header,
8726 RMO_ANYTHING_GOES | RMO_REDUNDANT);
8727 }
8728 else
8729 {
8730 /* Use route via neighbour */
8731 n = lookup_neighbour (&sender);
8732 if (NULL != n)
8733 route_via_neighbour (n, &tvr.header,
8734 RMO_ANYTHING_GOES | RMO_REDUNDANT
8735 | RMO_UNCONFIRMED_ALLOWED);
8736 }
8737
8738 finish_cmc_handling (cmc);
8739 if (NULL != vl)
8740 return;
8741
8742 /* For us, the link is still down, but we need bi-directional
8743 connections (for flow-control and for this to be useful for
8744 CORE), so we must try to bring the link up! */
8745
8746 /* (1) Check existing queues, if any, we may be lucky! */
8747 n = lookup_neighbour (&sender);
8748 if (NULL != n)
8749 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
8750 start_address_validation (&sender, q->address);
8751 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
8752 we could use */
8753 for (ir = ir_head; NULL != ir; ir = ir->next)
8754 if (0 == GNUNET_memcmp (&ir->pid, &sender))
8755 return;
8756 /* we are already trying */
8757 ir = GNUNET_new (struct IncomingRequest);
8758 ir->pid = sender;
8759 GNUNET_CONTAINER_DLL_insert (ir_head, ir_tail, ir);
8760
8761 ir->nc = GNUNET_PEERSTORE_hello_changed_notify (peerstore,
8762 GNUNET_NO,
8763 &handle_hello_for_incoming,
8764 NULL);
8765 ir_total++;
8766 /* Bound attempts we do in parallel here, might otherwise get excessive */
8767 while (ir_total > MAX_INCOMING_REQUEST)
8768 free_incoming_request (ir_head);
8769}
8770
8771
8772/**
8773 * Closure for #check_known_challenge.
8774 */
8775struct CheckKnownChallengeContext
8776{
8777 /**
8778 * Set to the challenge we are looking for.
8779 */
8780 const struct GNUNET_CRYPTO_ChallengeNonceP *challenge;
8781
8782 /**
8783 * Set to a matching validation state, if one was found.
8784 */
8785 struct ValidationState *vs;
8786};
8787
8788
8789/**
8790 * Test if the validation state in @a value matches the
8791 * challenge from @a cls.
8792 *
8793 * @param cls a `struct CheckKnownChallengeContext`
8794 * @param pid unused (must match though)
8795 * @param value a `struct ValidationState`
8796 * @return #GNUNET_OK if not matching, #GNUNET_NO if match found
8797 */
8798static int
8799check_known_challenge (void *cls,
8800 const struct GNUNET_PeerIdentity *pid,
8801 void *value)
8802{
8803 struct CheckKnownChallengeContext *ckac = cls;
8804 struct ValidationState *vs = value;
8805
8806 (void) pid;
8807 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
8808 return GNUNET_OK;
8809 ckac->vs = vs;
8810 return GNUNET_NO;
8811}
8812
8813
8814/**
8815 * Function called when peerstore is done storing a
8816 * validated address.
8817 *
8818 * @param cls a `struct ValidationState`
8819 * @param success #GNUNET_YES on success
8820 */
8821static void
8822peerstore_store_validation_cb (void *cls, int success)
8823{
8824 struct ValidationState *vs = cls;
8825
8826 vs->sc = NULL;
8827 if (GNUNET_YES == success)
8828 return;
8829 GNUNET_STATISTICS_update (GST_stats,
8830 "# Peerstore failed to store foreign address",
8831 1,
8832 GNUNET_NO);
8833}
8834
8835
8836/**
8837 * Find the queue matching @a pid and @a address.
8838 *
8839 * @param pid peer the queue must go to
8840 * @param address address the queue must use
8841 * @return NULL if no such queue exists
8842 */
8843static struct Queue *
8844find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
8845{
8846 struct Neighbour *n;
8847
8848 n = lookup_neighbour (pid);
8849 if (NULL == n)
8850 return NULL;
8851 for (struct Queue *pos = n->queue_head; NULL != pos;
8852 pos = pos->next_neighbour)
8853 {
8854 if (0 == strcmp (pos->address, address))
8855 return pos;
8856 }
8857 return NULL;
8858}
8859
8860
8861/**
8862 * Communicator gave us a transport address validation response. Process the
8863 * request.
8864 *
8865 * @param cls a `struct CommunicatorMessageContext` (must call
8866 * #finish_cmc_handling() when done)
8867 * @param tvr the message that was received
8868 */
8869static void
8870handle_validation_response (
8871 void *cls,
8872 const struct TransportValidationResponseMessage *tvr)
8873{
8874 struct CommunicatorMessageContext *cmc = cls;
8875 struct ValidationState *vs;
8876 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
8877 .vs = NULL};
8878 struct GNUNET_TIME_Absolute origin_time;
8879 struct Queue *q;
8880 struct Neighbour *n;
8881 struct VirtualLink *vl;
8882 const struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get_monotonic (GST_cfg);
8883
8884 /* check this is one of our challenges */
8885 (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
8886 &cmc->im.sender,
8887 &check_known_challenge,
8888 &ckac);
8889 if (NULL == (vs = ckac.vs))
8890 {
8891 /* This can happen simply if we 'forgot' the challenge by now,
8892 i.e. because we received the validation response twice */
8893 GNUNET_STATISTICS_update (GST_stats,
8894 "# Validations dropped, challenge unknown",
8895 1,
8896 GNUNET_NO);
8897 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8898 "Validation response %s dropped, challenge unknown\n",
8899 GNUNET_sh2s (&tvr->challenge.value));
8900 finish_cmc_handling (cmc);
8901 return;
8902 }
8903
8904 /* sanity check on origin time */
8905 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
8906 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
8907 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
8908 {
8909 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8910 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
8911 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
8912 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
8913 GNUNET_break_op (0);
8914 finish_cmc_handling (cmc);
8915 return;
8916 }
8917
8918 {
8919 /* check signature */
8920 struct TransportValidationPS tvp = {
8921 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE),
8922 .purpose.size = htonl (sizeof(tvp)),
8923 .validity_duration = tvr->validity_duration,
8924 .challenge = tvr->challenge
8925 };
8926
8927 if (
8928 GNUNET_OK !=
8929 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE,
8930 &tvp,
8931 &tvr->signature,
8932 &cmc->im.sender.public_key))
8933 {
8934 GNUNET_break_op (0);
8935 finish_cmc_handling (cmc);
8936 return;
8937 }
8938 }
8939
8940 /* validity is capped by our willingness to keep track of the
8941 validation entry and the maximum the other peer allows */
8942 vs->valid_until = GNUNET_TIME_relative_to_absolute (
8943 GNUNET_TIME_relative_min (GNUNET_TIME_relative_ntoh (
8944 tvr->validity_duration),
8945 MAX_ADDRESS_VALID_UNTIL));
8946 vs->validated_until =
8947 GNUNET_TIME_absolute_min (vs->valid_until,
8948 GNUNET_TIME_relative_to_absolute (
8949 ADDRESS_VALIDATION_LIFETIME));
8950 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
8951 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
8952 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
8953 &vs->challenge,
8954 sizeof(vs->challenge));
8955 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
8956 vs->validated_until,
8957 GNUNET_TIME_relative_multiply (vs->validation_rtt,
8958 VALIDATION_RTT_BUFFER_FACTOR));
8959 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
8960 {
8961 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8962 "First challenge use is now %" PRIu64 " %s \n",
8963 vs->first_challenge_use.abs_value_us,
8964 GNUNET_sh2s (&vs->challenge.value));
8965 vs->first_challenge_use = now;
8966 }
8967 else
8968 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8969 "First challenge use is later %" PRIu64 " %s \n",
8970 vs->first_challenge_use.abs_value_us,
8971 GNUNET_sh2s (&vs->challenge.value));
8972 vs->last_challenge_use =
8973 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
8974 update_next_challenge_time (vs, vs->first_challenge_use);
8975 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8976 "Validation response %s from %s accepted, address valid until %s\n",
8977 GNUNET_sh2s (&tvr->challenge.value),
8978 GNUNET_i2s (&cmc->im.sender),
8979 GNUNET_STRINGS_absolute_time_to_string (vs->valid_until));
8980 vs->sc = GNUNET_PEERSTORE_store (peerstore,
8981 "transport",
8982 &cmc->im.sender,
8983 GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY,
8984 vs->address,
8985 strlen (vs->address) + 1,
8986 vs->valid_until,
8987 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
8988 &peerstore_store_validation_cb,
8989 vs);
8990 finish_cmc_handling (cmc);
8991
8992 /* Finally, we now possibly have a confirmed (!) working queue,
8993 update queue status (if queue still is around) */
8994 q = find_queue (&vs->pid, vs->address);
8995 if (NULL == q)
8996 {
8997 GNUNET_STATISTICS_update (GST_stats,
8998 "# Queues lost at time of successful validation",
8999 1,
9000 GNUNET_NO);
9001 return;
9002 }
9003 q->validated_until = vs->validated_until;
9004 q->pd.aged_rtt = vs->validation_rtt;
9005 n = q->neighbour;
9006 vl = lookup_virtual_link (&vs->pid);
9007 if (NULL == vl)
9008 {
9009 vl = GNUNET_new (struct VirtualLink);
9010 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9011 "Creating new virtual link %p to %s using direct neighbour!\n",
9012 vl,
9013 GNUNET_i2s (&vs->pid));
9014 vl->confirmed = GNUNET_YES;
9015 vl->message_uuid_ctr =
9016 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
9017 vl->target = n->pid;
9018 vl->core_recv_window = RECV_WINDOW_SIZE;
9019 vl->available_fc_window_size = DEFAULT_WINDOW_SIZE;
9020 vl->incoming_fc_window_size = DEFAULT_WINDOW_SIZE;
9021 GNUNET_break (GNUNET_YES ==
9022 GNUNET_CONTAINER_multipeermap_put (
9023 links,
9024 &vl->target,
9025 vl,
9026 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
9027 vl->n = n;
9028 n->vl = vl;
9029 q->idle = GNUNET_YES;
9030 vl->visibility_task =
9031 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
9032 consider_sending_fc (vl);
9033 /* We lacked a confirmed connection to the target
9034 before, so tell CORE about it (finally!) */
9035 cores_send_connect_info (&n->pid);
9036 send_msg_from_cache (vl);
9037 }
9038 else
9039 {
9040 /* Link was already up, remember n is also now available and we are done */
9041 if (NULL == vl->n)
9042 {
9043 vl->n = n;
9044 n->vl = vl;
9045 if (GNUNET_YES == vl->confirmed)
9046 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9047 "Virtual link to %s could now also use direct neighbour!\n",
9048 GNUNET_i2s (&vs->pid));
9049 }
9050 else
9051 {
9052 GNUNET_assert (n == vl->n);
9053 }
9054 if (GNUNET_NO == vl->confirmed)
9055 {
9056 vl->confirmed = GNUNET_YES;
9057 q->idle = GNUNET_YES;
9058 vl->visibility_task =
9059 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
9060 consider_sending_fc (vl);
9061 /* We lacked a confirmed connection to the target
9062 before, so tell CORE about it (finally!) */
9063 cores_send_connect_info (&n->pid);
9064 send_msg_from_cache (vl);
9065 }
9066 }
9067}
9068
9069
9070/**
9071 * Incoming meessage. Process the request.
9072 *
9073 * @param im the send message that was received
9074 */
9075static void
9076handle_incoming_msg (void *cls,
9077 const struct GNUNET_TRANSPORT_IncomingMessage *im)
9078{
9079 struct TransportClient *tc = cls;
9080 struct CommunicatorMessageContext *cmc =
9081 GNUNET_new (struct CommunicatorMessageContext);
9082
9083 cmc->tc = tc;
9084 cmc->im = *im;
9085 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9086 "Received message with size %u and flow control id %" PRIu64
9087 " via communicator from peer %s\n",
9088 ntohs (im->header.size),
9089 im->fc_id,
9090 GNUNET_i2s (&im->sender));
9091 cmc->im.neighbour_sender = cmc->im.sender;
9092 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
9093 demultiplex_with_cmc (cmc);
9094}
9095
9096
9097/**
9098 * Communicator gave us a transport address validation response. Process the
9099 * request.
9100 *
9101 * @param cls a `struct CommunicatorMessageContext` (must call
9102 * #finish_cmc_handling() when done)
9103 * @param fc the message that was received
9104 */
9105static void
9106handle_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
9107{
9108 struct CommunicatorMessageContext *cmc = cls;
9109 struct VirtualLink *vl;
9110 uint32_t seq;
9111 struct GNUNET_TIME_Absolute st;
9112 uint64_t os;
9113 uint64_t wnd;
9114 uint32_t random;
9115
9116 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9117 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
9118 vl = lookup_virtual_link (&cmc->im.sender);
9119 if (NULL == vl)
9120 {
9121 vl = GNUNET_new (struct VirtualLink);
9122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9123 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
9124 vl,
9125 GNUNET_i2s (&cmc->im.sender));
9126 vl->confirmed = GNUNET_NO;
9127 vl->message_uuid_ctr =
9128 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
9129 vl->target = cmc->im.sender;
9130 vl->core_recv_window = RECV_WINDOW_SIZE;
9131 vl->available_fc_window_size = DEFAULT_WINDOW_SIZE;
9132 vl->incoming_fc_window_size = DEFAULT_WINDOW_SIZE;
9133 GNUNET_break (GNUNET_YES ==
9134 GNUNET_CONTAINER_multipeermap_put (
9135 links,
9136 &vl->target,
9137 vl,
9138 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
9139 }
9140 st = GNUNET_TIME_absolute_ntoh (fc->sender_time);
9141 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
9142 {
9143 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9144 "FC dropped: Message out of order\n");
9145 /* out of order, drop */
9146 GNUNET_STATISTICS_update (GST_stats,
9147 "# FC dropped: message out of order",
9148 1,
9149 GNUNET_NO);
9150 finish_cmc_handling (cmc);
9151 return;
9152 }
9153 seq = ntohl (fc->seq);
9154 if (seq < vl->last_fc_seq)
9155 {
9156 /* Wrap-around/reset of other peer; start all counters from zero */
9157 vl->outbound_fc_window_size_used = 0;
9158 }
9159 vl->last_fc_seq = seq;
9160 vl->last_fc_timestamp = st;
9161 vl->outbound_fc_window_size = GNUNET_ntohll (fc->inbound_window_size);
9162 os = GNUNET_ntohll (fc->outbound_sent);
9163 vl->incoming_fc_window_size_loss =
9164 (int64_t) (os - vl->incoming_fc_window_size_used);
9165 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9166 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
9167 GNUNET_i2s (&vl->target),
9168 (unsigned int) seq,
9169 (unsigned long long) vl->outbound_fc_window_size,
9170 (long long) vl->incoming_fc_window_size_loss);
9171 wnd = GNUNET_ntohll (fc->outbound_window_size);
9172 random = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
9173 UINT32_MAX);
9174 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
9175 + vl->incoming_fc_window_size_used
9176 + vl->incoming_fc_window_size_loss) ||
9177 (vl->last_outbound_window_size_received
9178 != wnd) ||
9179 (0 == random
9180 % FC_NO_CHANGE_REPLY_PROBABILITY)))
9181 {
9182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9183 "Consider re-sending our FC message, as clearly the other peer's idea of the window is not up-to-date (%llu vs %llu) or %llu last received differs, or random reply %u\n",
9184 (unsigned long long) wnd,
9185 (unsigned long long) vl->incoming_fc_window_size,
9186 (unsigned long long) vl->last_outbound_window_size_received,
9187 random % FC_NO_CHANGE_REPLY_PROBABILITY);
9188 consider_sending_fc (vl);
9189 }
9190 if ((wnd == vl->incoming_fc_window_size) &&
9191 (vl->last_outbound_window_size_received == wnd) &&
9192 (NULL != vl->fc_retransmit_task))
9193 {
9194 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9195 "Stopping FC retransmission to %s: peer is current at window %llu\n",
9196 GNUNET_i2s (&vl->target),
9197 (unsigned long long) wnd);
9198 GNUNET_SCHEDULER_cancel (vl->fc_retransmit_task);
9199 vl->fc_retransmit_task = NULL;
9200 vl->fc_retransmit_count = 0;
9201 }
9202 vl->last_outbound_window_size_received = wnd;
9203 /* FC window likely increased, check transmission possibilities! */
9204 check_vl_transmission (vl);
9205 finish_cmc_handling (cmc);
9206}
9207
9208
9209/**
9210 * Given an inbound message @a msg from a communicator @a cmc,
9211 * demultiplex it based on the type calling the right handler.
9212 *
9213 * @param cmc context for demultiplexing
9214 * @param msg message to demultiplex
9215 */
9216static void
9217demultiplex_with_cmc (struct CommunicatorMessageContext *cmc)
9218{
9219 struct GNUNET_MQ_MessageHandler handlers[] =
9220 { GNUNET_MQ_hd_var_size (fragment_box,
9221 GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT,
9222 struct TransportFragmentBoxMessage,
9223 cmc),
9224 GNUNET_MQ_hd_var_size (reliability_box,
9225 GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX,
9226 struct TransportReliabilityBoxMessage,
9227 cmc),
9228 GNUNET_MQ_hd_var_size (reliability_ack,
9229 GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK,
9230 struct TransportReliabilityAckMessage,
9231 cmc),
9232 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
9233 GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION,
9234 struct TransportBackchannelEncapsulationMessage,
9235 cmc),
9236 GNUNET_MQ_hd_var_size (dv_learn,
9237 GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN,
9238 struct TransportDVLearnMessage,
9239 cmc),
9240 GNUNET_MQ_hd_var_size (dv_box,
9241 GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX,
9242 struct TransportDVBoxMessage,
9243 cmc),
9244 GNUNET_MQ_hd_fixed_size (
9245 validation_challenge,
9246 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE,
9247 struct TransportValidationChallengeMessage,
9248 cmc),
9249 GNUNET_MQ_hd_fixed_size (flow_control,
9250 GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL,
9251 struct TransportFlowControlMessage,
9252 cmc),
9253 GNUNET_MQ_hd_fixed_size (
9254 validation_response,
9255 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE,
9256 struct TransportValidationResponseMessage,
9257 cmc),
9258 GNUNET_MQ_handler_end () };
9259 int ret;
9260 const struct GNUNET_MessageHeader *msg = cmc->mh;
9261
9262 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9263 "Handling message of type %u with %u bytes\n",
9264 (unsigned int) ntohs (msg->type),
9265 (unsigned int) ntohs (msg->size));
9266 ret = GNUNET_MQ_handle_message (handlers, msg);
9267 if (GNUNET_SYSERR == ret)
9268 {
9269 GNUNET_break (0);
9270 GNUNET_SERVICE_client_drop (cmc->tc->client);
9271 GNUNET_free (cmc);
9272 return;
9273 }
9274 if (GNUNET_NO == ret)
9275 {
9276 /* unencapsulated 'raw' message */
9277 handle_raw_message (cmc, msg);
9278 }
9279}
9280
9281
9282/**
9283 * New queue became available. Check message.
9284 *
9285 * @param cls the client
9286 * @param aqm the send message that was sent
9287 */
9288static int
9289check_add_queue_message (void *cls,
9290 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
9291{
9292 struct TransportClient *tc = cls;
9293
9294 if (CT_COMMUNICATOR != tc->type)
9295 {
9296 GNUNET_break (0);
9297 return GNUNET_SYSERR;
9298 }
9299 GNUNET_MQ_check_zero_termination (aqm);
9300 return GNUNET_OK;
9301}
9302
9303
9304/**
9305 * If necessary, generates the UUID for a @a pm
9306 *
9307 * @param pm pending message to generate UUID for.
9308 */
9309static void
9310set_pending_message_uuid (struct PendingMessage *pm)
9311{
9312 if (pm->msg_uuid_set)
9313 return;
9314 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
9315 pm->msg_uuid_set = GNUNET_YES;
9316}
9317
9318
9319/**
9320 * Setup data structure waiting for acknowledgements.
9321 *
9322 * @param queue queue the @a pm will be sent over
9323 * @param dvh path the message will take, may be NULL
9324 * @param pm the pending message for transmission
9325 * @return corresponding fresh pending acknowledgement
9326 */
9327static struct PendingAcknowledgement *
9328prepare_pending_acknowledgement (struct Queue *queue,
9329 struct DistanceVectorHop *dvh,
9330 struct PendingMessage *pm)
9331{
9332 struct PendingAcknowledgement *pa;
9333
9334 pa = GNUNET_new (struct PendingAcknowledgement);
9335 pa->queue = queue;
9336 pa->dvh = dvh;
9337 pa->pm = pm;
9338 do
9339 {
9340 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
9341 &pa->ack_uuid,
9342 sizeof(pa->ack_uuid));
9343 }
9344 while (GNUNET_YES != GNUNET_CONTAINER_multiuuidmap_put (
9345 pending_acks,
9346 &pa->ack_uuid.value,
9347 pa,
9348 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
9349 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
9350 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
9351 if (NULL != dvh)
9352 GNUNET_CONTAINER_MDLL_insert (dvh, dvh->pa_head, dvh->pa_tail, pa);
9353 pa->transmission_time = GNUNET_TIME_absolute_get ();
9354 pa->message_size = pm->bytes_msg;
9355 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9356 "Waiting for ACKnowledgment `%s' for <%llu>\n",
9357 GNUNET_uuid2s (&pa->ack_uuid.value),
9358 pm->logging_uuid);
9359 return pa;
9360}
9361
9362
9363/**
9364 * Fragment the given @a pm to the given @a mtu. Adds
9365 * additional fragments to the neighbour as well. If the
9366 * @a mtu is too small, generates and error for the @a pm
9367 * and returns NULL.
9368 *
9369 * @param queue which queue to fragment for
9370 * @param dvh path the message will take, or NULL
9371 * @param pm pending message to fragment for transmission
9372 * @return new message to transmit
9373 */
9374static struct PendingMessage *
9375fragment_message (struct Queue *queue,
9376 struct DistanceVectorHop *dvh,
9377 struct PendingMessage *pm)
9378{
9379 struct PendingAcknowledgement *pa;
9380 struct PendingMessage *ff;
9381 uint16_t mtu;
9382 uint16_t msize;
9383
9384 mtu = (UINT16_MAX == queue->mtu)
9385 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
9386 : queue->mtu;
9387 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9388 "Fragmenting message <%llu> with size %u to %s for MTU %u\n",
9389 pm->logging_uuid,
9390 pm->bytes_msg,
9391 GNUNET_i2s (&pm->vl->target),
9392 (unsigned int) mtu);
9393 set_pending_message_uuid (pm);
9394 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9395 "Fragmenting message %llu <%llu> with size %u to %s for MTU %u\n",
9396 (unsigned long long) pm->msg_uuid.uuid,
9397 pm->logging_uuid,
9398 pm->bytes_msg,
9399 GNUNET_i2s (&pm->vl->target),
9400 (unsigned int) mtu);
9401
9402 /* This invariant is established in #handle_add_queue_message() */
9403 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
9404
9405 /* select fragment for transmission, descending the tree if it has
9406 been expanded until we are at a leaf or at a fragment that is small
9407 enough
9408 */
9409 ff = pm;
9410 msize = ff->bytes_msg;
9411
9412 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
9413 (ff->frag_off == msize) && (NULL != ff->head_frag))
9414 {
9415 ff = ff->head_frag; /* descent into fragmented fragments */
9416 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
9417 }
9418
9419 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
9420 {
9421 /* Did not yet calculate all fragments, calculate next fragment */
9422 struct PendingMessage *frag;
9423 struct TransportFragmentBoxMessage tfb;
9424 const char *orig;
9425 char *msg;
9426 uint16_t fragmax;
9427 uint16_t fragsize;
9428 uint16_t msize;
9429 uint16_t xoff = 0;
9430
9431 orig = (const char *) &ff[1];
9432 msize = ff->bytes_msg;
9433 if (pm != ff)
9434 {
9435 const struct TransportFragmentBoxMessage *tfbo;
9436
9437 tfbo = (const struct TransportFragmentBoxMessage *) orig;
9438 orig += sizeof(struct TransportFragmentBoxMessage);
9439 msize -= sizeof(struct TransportFragmentBoxMessage);
9440 xoff = ntohs (tfbo->frag_off);
9441 }
9442 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
9443 fragsize = GNUNET_MIN (msize - ff->frag_off, fragmax);
9444 frag =
9445 GNUNET_malloc (sizeof(struct PendingMessage)
9446 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
9447 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9448 "3 created pm %p from pm %p storing vl %p from pm %p\n",
9449 frag,
9450 ff,
9451 pm->vl,
9452 pm);
9453 frag->logging_uuid = logging_uuid_gen++;
9454 frag->vl = pm->vl;
9455 frag->frag_parent = ff;
9456 frag->timeout = pm->timeout;
9457 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
9458 frag->pmt = PMT_FRAGMENT_BOX;
9459 msg = (char *) &frag[1];
9460 tfb.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT);
9461 tfb.header.size =
9462 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
9463 pa = prepare_pending_acknowledgement (queue, dvh, frag);
9464 tfb.ack_uuid = pa->ack_uuid;
9465 tfb.msg_uuid = pm->msg_uuid;
9466 tfb.frag_off = htons (ff->frag_off + xoff);
9467 tfb.msg_size = htons (pm->bytes_msg);
9468 memcpy (msg, &tfb, sizeof(tfb));
9469 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
9470 GNUNET_CONTAINER_MDLL_insert (frag, ff->head_frag,
9471 ff->tail_frag, frag);
9472 ff->frag_off += fragsize;
9473 ff = frag;
9474 }
9475
9476 /* Move head to the tail and return it */
9477 GNUNET_CONTAINER_MDLL_remove (frag,
9478 ff->frag_parent->head_frag,
9479 ff->frag_parent->tail_frag,
9480 ff);
9481 GNUNET_CONTAINER_MDLL_insert_tail (frag,
9482 ff->frag_parent->head_frag,
9483 ff->frag_parent->tail_frag,
9484 ff);
9485
9486 return ff;
9487}
9488
9489
9490/**
9491 * Reliability-box the given @a pm. On error (can there be any), NULL
9492 * may be returned, otherwise the "replacement" for @a pm (which
9493 * should then be added to the respective neighbour's queue instead of
9494 * @a pm). If the @a pm is already fragmented or reliability boxed,
9495 * or itself an ACK, this function simply returns @a pm.
9496 *
9497 * @param queue which queue to prepare transmission for
9498 * @param dvh path the message will take, or NULL
9499 * @param pm pending message to box for transmission over unreliabile queue
9500 * @return new message to transmit
9501 */
9502static struct PendingMessage *
9503reliability_box_message (struct Queue *queue,
9504 struct DistanceVectorHop *dvh,
9505 struct PendingMessage *pm)
9506{
9507 struct TransportReliabilityBoxMessage rbox;
9508 struct PendingAcknowledgement *pa;
9509 struct PendingMessage *bpm;
9510 char *msg;
9511
9512 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
9513 return pm; /* already fragmented or reliability boxed, or control message:
9514 do nothing */
9515 if (NULL != pm->bpm)
9516 return pm->bpm; /* already computed earlier: do nothing */
9517 // TODO I guess we do not need this assertion. We might have a DLL with
9518 // fragments, because the MTU changed, and we do not need to fragment anymore.
9519 // But we should keep the fragments until message was completed, because
9520 // the MTU might change again.
9521 // GNUNET_assert (NULL == pm->head_frag);
9522 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
9523 {
9524 /* failed hard */
9525 GNUNET_break (0);
9526 client_send_response (pm);
9527 return NULL;
9528 }
9529
9530 pa = prepare_pending_acknowledgement (queue, dvh, pm);
9531
9532 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
9533 + pm->bytes_msg);
9534 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9535 "4 created pm %p storing vl %p from pm %p\n",
9536 bpm,
9537 pm->vl,
9538 pm);
9539 bpm->logging_uuid = logging_uuid_gen++;
9540 bpm->vl = pm->vl;
9541 bpm->frag_parent = pm;
9542 // Why was this needed?
9543 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
9544 bpm->timeout = pm->timeout;
9545 bpm->pmt = PMT_RELIABILITY_BOX;
9546 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
9547 set_pending_message_uuid (bpm);
9548 rbox.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX);
9549 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
9550 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
9551
9552 rbox.ack_uuid = pa->ack_uuid;
9553 msg = (char *) &bpm[1];
9554 memcpy (msg, &rbox, sizeof(rbox));
9555 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
9556 pm->bpm = bpm;
9557 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9558 "Preparing reliability box for message <%llu> of size %d (%d) to %s on queue %s\n",
9559 pm->logging_uuid,
9560 pm->bytes_msg,
9561 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
9562 GNUNET_i2s (&pm->vl->target),
9563 queue->address);
9564 return bpm;
9565}
9566
9567
9568static void
9569reorder_root_pm (struct PendingMessage *pm,
9570 struct GNUNET_TIME_Absolute next_attempt)
9571{
9572 struct VirtualLink *vl = pm->vl;
9573 struct PendingMessage *pos;
9574
9575 /* re-insert sort in neighbour list */
9576 GNUNET_CONTAINER_MDLL_remove (vl,
9577 vl->pending_msg_head,
9578 vl->pending_msg_tail,
9579 pm);
9580 pos = vl->pending_msg_tail;
9581 while ((NULL != pos) &&
9582 (next_attempt.abs_value_us > pos->next_attempt.abs_value_us))
9583 pos = pos->prev_vl;
9584 GNUNET_CONTAINER_MDLL_insert_after (vl,
9585 vl->pending_msg_head,
9586 vl->pending_msg_tail,
9587 pos,
9588 pm);
9589}
9590
9591
9592static unsigned int
9593check_next_attempt_tree (struct PendingMessage *pm,
9594 struct GNUNET_TIME_Absolute next_attempt)
9595{
9596 struct PendingMessage *pos;
9597
9598 pos = pm->head_frag;
9599 while (NULL != pos)
9600 {
9601 if (pos->next_attempt.abs_value_us != next_attempt.abs_value_us ||
9602 GNUNET_YES == check_next_attempt_tree (pos, next_attempt))
9603 return GNUNET_YES;
9604 pos = pos->next_frag;
9605 }
9606
9607 return GNUNET_NO;
9608}
9609
9610
9611/**
9612 * Change the value of the `next_attempt` field of @a pm
9613 * to @a next_attempt and re-order @a pm in the transmission
9614 * list as required by the new timestamp.
9615 *
9616 * @param pm a pending message to update
9617 * @param next_attempt timestamp to use
9618 */
9619static void
9620update_pm_next_attempt (struct PendingMessage *pm,
9621 struct GNUNET_TIME_Absolute next_attempt)
9622{
9623 if (NULL == pm->frag_parent)
9624 {
9625 pm->next_attempt = next_attempt;
9626 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9627 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
9628 pm->logging_uuid,
9629 next_attempt.abs_value_us);
9630 reorder_root_pm (pm, next_attempt);
9631 }
9632 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
9633 {
9634 struct PendingMessage *root = pm->frag_parent;
9635
9636 while (NULL != root->frag_parent)
9637 root = root->frag_parent;
9638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9639 "Next attempt for root message <%" PRIu64 "> set to %s\n",
9640 root->logging_uuid,
9641 GNUNET_STRINGS_absolute_time_to_string (next_attempt));
9642 root->next_attempt = next_attempt;
9643 reorder_root_pm (root, next_attempt);
9644 }
9645 else
9646 {
9647 struct PendingMessage *root = pm->frag_parent;
9648
9649 while (NULL != root->frag_parent)
9650 root = root->frag_parent;
9651
9652 if (GNUNET_NO == root->frags_in_flight)
9653 {
9654 root->next_attempt = next_attempt;
9655 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9656 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
9657 ">)set to %" PRIu64 "\n",
9658 pm->logging_uuid,
9659 root->logging_uuid,
9660 next_attempt.abs_value_us);
9661 }
9662
9663 pm->next_attempt = root->next_attempt;
9664
9665 if (root->bytes_msg == root->frag_off)
9666 root->frags_in_flight = check_next_attempt_tree (root,
9667 root->next_attempt);
9668 else
9669 root->frags_in_flight = GNUNET_YES;
9670
9671 if (GNUNET_NO == root->frags_in_flight)
9672 {
9673 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9674 "We have no fragments in flight for message %" PRIu64
9675 ", reorder root! Next attempt is %" PRIu64 "\n",
9676 root->logging_uuid,
9677 root->next_attempt.abs_value_us);
9678 reorder_root_pm (root, root->next_attempt);
9679 root->frag_count = 0;
9680 root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
9681 }
9682 else
9683 {
9684 double factor = (root->frag_count - 1) / root->frag_count;
9685 struct GNUNET_TIME_Relative s1;
9686 struct GNUNET_TIME_Relative s2;
9687 struct GNUNET_TIME_Relative plus_mean =
9688 GNUNET_TIME_absolute_get_duration (root->next_attempt);
9689 struct GNUNET_TIME_Relative plus = GNUNET_TIME_absolute_get_duration (
9690 next_attempt);
9691
9692 s1 = GNUNET_TIME_relative_multiply (plus_mean,
9693 factor);
9694 s2 = GNUNET_TIME_relative_divide (plus,
9695 root->frag_count);
9696 plus_mean = GNUNET_TIME_relative_add (s1, s2);
9697 root->next_attempt = GNUNET_TIME_relative_to_absolute (plus_mean);
9698 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9699 "We have fragments in flight for message %" PRIu64
9700 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
9701 root->logging_uuid,
9702 root->next_attempt.abs_value_us);
9703 }
9704 }
9705}
9706
9707
9708/**
9709 * Context for #select_best_pending_from_link().
9710 */
9711struct PendingMessageScoreContext
9712{
9713 /**
9714 * Set to the best message that was found, NULL for none.
9715 */
9716 struct PendingMessage *best;
9717
9718 /**
9719 * DVH that @e best should take, or NULL for direct transmission.
9720 */
9721 struct DistanceVectorHop *dvh;
9722
9723 /**
9724 * What is the estimated total overhead for this message?
9725 */
9726 size_t real_overhead;
9727
9728 /**
9729 * Number of pending messages we seriously considered this time.
9730 */
9731 unsigned int consideration_counter;
9732
9733 /**
9734 * Did we have to fragment?
9735 */
9736 int frag;
9737
9738 /**
9739 * Did we have to reliability box?
9740 */
9741 int relb;
9742
9743 /**
9744 * There are pending messages, but it was to early to send one of them.
9745 */
9746 int to_early;
9747
9748 /**
9749 * There is a pending messages we are sending fragments at the moment.
9750 */
9751 unsigned int frags_in_flight;
9752
9753 /**
9754 * When will we try to transmit the message again for which it was to early to retry.
9755 */
9756 struct GNUNET_TIME_Relative to_early_retry_delay;
9757};
9758
9759
9760/**
9761 * Select the best pending message from @a vl for transmission
9762 * via @a queue.
9763 *
9764 * @param[in,out] sc best message so far (NULL for none), plus scoring data
9765 * @param queue the queue that will be used for transmission
9766 * @param vl the virtual link providing the messages
9767 * @param dvh path we are currently considering, or NULL for none
9768 * @param overhead number of bytes of overhead to be expected
9769 * from DV encapsulation (0 for without DV)
9770 */
9771static void
9772select_best_pending_from_link (struct PendingMessageScoreContext *sc,
9773 struct Queue *queue,
9774 struct VirtualLink *vl,
9775 struct DistanceVectorHop *dvh,
9776 size_t overhead)
9777{
9778 struct GNUNET_TIME_Absolute now;
9779
9780 now = GNUNET_TIME_absolute_get ();
9781 sc->to_early = GNUNET_NO;
9782 sc->frags_in_flight = GNUNET_NO;
9783 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
9784 pos = pos->next_vl)
9785 {
9786 size_t real_overhead = overhead;
9787 int frag;
9788 int relb;
9789
9790 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
9791 {
9792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9793 "DV messages must not be DV-routed to next hop!\n");
9794 continue; /* DV messages must not be DV-routed to next hop! */
9795 }
9796 if (pos->next_attempt.abs_value_us > now.abs_value_us)
9797 {
9798 if (GNUNET_YES == pos->frags_in_flight)
9799 {
9800 sc->frags_in_flight = GNUNET_YES;
9801 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9802 "Fragments in flight for message %llu\n",
9803 pos->logging_uuid);
9804 }
9805 else
9806 {
9807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9808 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %llu\n",
9809 pos->logging_uuid);
9810 sc->to_early = GNUNET_YES;
9811 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
9812 pos->next_attempt);
9813 continue;
9814 }
9815 // break; /* too early for all messages, they are sorted by next_attempt */
9816 }
9817 if (NULL != pos->qe)
9818 {
9819 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9820 "not eligible\n");
9821 continue; /* not eligible */
9822 }
9823 sc->consideration_counter++;
9824 /* determine if we have to fragment, if so add fragmentation
9825 overhead! */
9826 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9827 "check %llu for sc->best\n",
9828 pos->logging_uuid);
9829 frag = GNUNET_NO;
9830 if (((0 != queue->mtu) &&
9831 (pos->bytes_msg + real_overhead > queue->mtu)) ||
9832 (pos->bytes_msg > UINT16_MAX - sizeof(struct
9833 GNUNET_TRANSPORT_SendMessageTo))
9834 ||
9835 (NULL != pos->head_frag /* fragments already exist, should
9836 respect that even if MTU is UINT16_MAX for
9837 this queue */))
9838 {
9839 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9840 "fragment msg with size %u, realoverhead is %lu\n",
9841 pos->bytes_msg,
9842 real_overhead);
9843 frag = GNUNET_YES;
9844 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
9845 {
9846 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
9847 header without the ACK UUID when using a *reliable* channel! */
9848 }
9849 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
9850 }
9851 /* determine if we have to reliability-box, if so add reliability box
9852 overhead */
9853 relb = GNUNET_NO;
9854 if ((GNUNET_NO == frag) &&
9855 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
9856 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
9857 {
9858 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
9859
9860 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
9861 {
9862 frag = GNUNET_YES;
9863 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
9864 }
9865 else
9866 {
9867 relb = GNUNET_YES;
9868 }
9869 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9870 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
9871 pos->bytes_msg,
9872 real_overhead,
9873 queue->mtu,
9874 frag,
9875 relb);
9876 }
9877
9878 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
9879 message would beat it! */
9880 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
9881 {
9882 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
9883 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
9884 experimentally validated. There may be some huge potential for
9885 improvement here. Also, we right now only compare how well the
9886 given message fits _this_ queue, and do not consider how well other
9887 queues might suit the message. Taking other queues into consideration
9888 may further improve the result, but could also be expensive
9889 in terms of CPU time. */
9890 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
9891 long long pm_score = frag * 40 + relb * 20 + real_overhead;
9892 long long time_delta =
9893 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
9894 / 1000LL;
9895
9896 /* "time_delta" considers which message has been 'ready' for transmission
9897 for longer, if a message has a preference for low latency, increase
9898 the weight of the time_delta by 10x if it is favorable for that message */
9899 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
9900 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
9901 time_delta *= 10; /* increase weight (always, both are low latency) */
9902 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
9903 (time_delta > 0))
9904 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
9905 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
9906 (time_delta < 0))
9907 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
9908 if (0 != queue->mtu)
9909 {
9910 /* Grant bonus if we are below MTU, larger bonus the closer we will
9911 be to the MTU */
9912 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
9913 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
9914 if (queue->mtu > real_overhead + pos->bytes_msg)
9915 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
9916 }
9917 if (sc_score + time_delta > pm_score)
9918 {
9919 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9920 "sc_score of %llu larger, keep sc->best %llu\n",
9921 pos->logging_uuid,
9922 sc->best->logging_uuid);
9923 continue; /* sc_score larger, keep sc->best */
9924 }
9925 }
9926 sc->best = pos;
9927 sc->dvh = dvh;
9928 sc->frag = frag;
9929 sc->relb = relb;
9930 sc->real_overhead = real_overhead;
9931 }
9932}
9933
9934
9935/**
9936 * Function to call to further operate on the now DV encapsulated
9937 * message @a hdr, forwarding it via @a next_hop under respect of
9938 * @a options.
9939 *
9940 * @param cls a `struct PendingMessageScoreContext`
9941 * @param next_hop next hop of the DV path
9942 * @param hdr encapsulated message, technically a `struct TransportDVBoxMessage`
9943 * @param options options of the original message
9944 */
9945static void
9946extract_box_cb (void *cls,
9947 struct Neighbour *next_hop,
9948 const struct GNUNET_MessageHeader *hdr,
9949 enum RouteMessageOptions options)
9950{
9951 struct PendingMessageScoreContext *sc = cls;
9952 struct PendingMessage *pm = sc->best;
9953 struct PendingMessage *bpm;
9954 uint16_t bsize = ntohs (hdr->size);
9955
9956 GNUNET_assert (NULL == pm->bpm);
9957 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
9958 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9959 "5 created pm %p storing vl %p from pm %p\n",
9960 bpm,
9961 pm->vl,
9962 pm);
9963 bpm->logging_uuid = logging_uuid_gen++;
9964 bpm->pmt = PMT_DV_BOX;
9965 bpm->vl = pm->vl;
9966 bpm->timeout = pm->timeout;
9967 bpm->bytes_msg = bsize;
9968 bpm->frag_parent = pm;
9969 set_pending_message_uuid (bpm);
9970 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9971 "Creating DV Box %llu for original message %llu (next hop is %s)\n",
9972 bpm->logging_uuid,
9973 pm->logging_uuid,
9974 GNUNET_i2s (&next_hop->pid));
9975 memcpy (&bpm[1], hdr, bsize);
9976 pm->bpm = bpm;
9977}
9978
9979
9980/**
9981 * We believe we are ready to transmit a `struct PendingMessage` on a
9982 * queue, the big question is which one! We need to see if there is
9983 * one pending that is allowed by flow control and congestion control
9984 * and (ideally) matches our queue's performance profile.
9985 *
9986 * If such a message is found, we give the message to the communicator
9987 * for transmission (updating the tracker, and re-scheduling ourselves
9988 * if applicable).
9989 *
9990 * If no such message is found, the queue's `idle` field must be set
9991 * to #GNUNET_YES.
9992 *
9993 * @param cls the `struct Queue` to process transmissions for
9994 */
9995static void
9996transmit_on_queue (void *cls)
9997{
9998 struct Queue *queue = cls;
9999 struct Neighbour *n = queue->neighbour;
10000 struct PendingMessageScoreContext sc;
10001 struct PendingMessage *pm;
10002
10003 queue->transmit_task = NULL;
10004 if (NULL == n->vl)
10005 {
10006 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10007 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
10008 GNUNET_i2s (&n->pid),
10009 queue->address);
10010 queue->idle = GNUNET_YES;
10011 return;
10012 }
10013 memset (&sc, 0, sizeof(sc));
10014 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
10015 if (NULL == sc.best)
10016 {
10017 /* Also look at DVH that have the n as first hop! */
10018 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
10019 dvh = dvh->next_neighbour)
10020 {
10021 select_best_pending_from_link (&sc,
10022 queue,
10023 dvh->dv->vl,
10024 dvh,
10025 sizeof(struct GNUNET_PeerIdentity)
10026 * (1 + dvh->distance)
10027 + sizeof(struct TransportDVBoxMessage)
10028 + sizeof(struct TransportDVBoxPayloadP));
10029 }
10030 }
10031 if (NULL == sc.best)
10032 {
10033 /* no message pending, nothing to do here! */
10034 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10035 "No pending messages, queue `%s' to %s now idle\n",
10036 queue->address,
10037 GNUNET_i2s (&n->pid));
10038 if (GNUNET_YES == sc.to_early)
10039 schedule_transmit_on_queue (sc.to_early_retry_delay,
10040 queue,
10041 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
10042 queue->idle = GNUNET_YES;
10043 return;
10044 }
10045 /* There is a message pending, we are certainly not idle */
10046 queue->idle = GNUNET_NO;
10047
10048 /* Given selection in `sc`, do transmission */
10049 pm = sc.best;
10050 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10051 "Selected message <%llu>\n",
10052 pm->logging_uuid);
10053 if (NULL != sc.dvh)
10054 {
10055 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10056 "Is this %u a DV box?\n",
10057 pm->pmt);
10058 GNUNET_assert (PMT_DV_BOX != pm->pmt);
10059 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
10060 {
10061 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10062 "Discard old box, because we have a new DV path.\n");
10063 free_pending_message (sc.best->bpm);
10064 sc.best->bpm = NULL;
10065 }
10066
10067 if (NULL == sc.best->bpm)
10068 {
10069 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10070 "encapsulate_for_dv 2\n");
10071 encapsulate_for_dv (sc.dvh->dv,
10072 1,
10073 &sc.dvh,
10074 (const struct GNUNET_MessageHeader *) &sc.best[1],
10075 &extract_box_cb,
10076 &sc,
10077 RMO_NONE,
10078 GNUNET_NO);
10079 GNUNET_assert (NULL != sc.best->bpm);
10080 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10081 "%lu %lu %lu %lu %u\n",
10082 sizeof(struct GNUNET_PeerIdentity),
10083 sizeof(struct TransportDVBoxMessage),
10084 sizeof(struct TransportDVBoxPayloadP),
10085 sizeof(struct TransportFragmentBoxMessage),
10086 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
10087 sc.best->bpm->used_dvh = sc.dvh;
10088 }
10089 pm = sc.best->bpm;
10090 }
10091 if (GNUNET_YES == sc.frag)
10092 {
10093 pm = fragment_message (queue, sc.dvh, pm);
10094 if (NULL == pm)
10095 {
10096 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10097 "Fragmentation failed queue %s to %s for <%llu>, trying again\n",
10098 queue->address,
10099 GNUNET_i2s (&n->pid),
10100 sc.best->logging_uuid);
10101 schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
10102 queue,
10103 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
10104 return;
10105 }
10106 }
10107 else if (GNUNET_YES == sc.relb)
10108 {
10109 pm = reliability_box_message (queue, sc.dvh, pm);
10110 if (NULL == pm)
10111 {
10112 /* Reliability boxing failed, try next message... */
10113 GNUNET_log (
10114 GNUNET_ERROR_TYPE_DEBUG,
10115 "Reliability boxing failed queue %s to %s for <%llu>, trying again\n",
10116 queue->address,
10117 GNUNET_i2s (&n->pid),
10118 sc.best->logging_uuid);
10119 schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
10120 queue,
10121 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
10122 return;
10123 }
10124 }
10125
10126 /* Pass 'pm' for transission to the communicator */
10127 GNUNET_log (
10128 GNUNET_ERROR_TYPE_DEBUG,
10129 "Passing message <%llu> to queue %s for peer %s (considered %u others)\n",
10130 pm->logging_uuid,
10131 queue->address,
10132 GNUNET_i2s (&n->pid),
10133 sc.consideration_counter);
10134
10135 /* Flow control: increment amount of traffic sent; if we are routing
10136 via DV (and thus the ultimate target of the pending message is for
10137 a different virtual link than the one of the queue), then we need
10138 to use up not only the window of the direct link but also the
10139 flow control window for the DV link! */
10140 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
10141
10142 if (pm->vl != queue->neighbour->vl)
10143 {
10144 /* If the virtual link of the queue differs, this better be distance
10145 vector routing! */
10146 GNUNET_assert (NULL != sc.dvh);
10147 /* If we do distance vector routing, we better not do this for a
10148 message that was itself DV-routed */
10149 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
10150 /* We use the size of the unboxed message here, to avoid counting
10151 the DV-Box header which is eaten up on the way by intermediaries */
10152 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
10153 }
10154 else
10155 {
10156 GNUNET_assert (NULL == sc.dvh);
10157 }
10158
10159 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
10160
10161 /* Check if this transmission somehow conclusively finished handing 'pm'
10162 even without any explicit ACKs */
10163 if ((PMT_CORE == pm->pmt) ||
10164 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
10165 {
10166 completed_pending_message (pm);
10167 }
10168 else
10169 {
10170 struct GNUNET_TIME_Relative wait_duration;
10171 unsigned int wait_multiplier;
10172
10173 if (PMT_FRAGMENT_BOX == pm->pmt)
10174 {
10175 struct PendingMessage *root;
10176
10177 root = pm->frag_parent;
10178 while (NULL != root->frag_parent)
10179 root = root->frag_parent;
10180
10181 root->frag_count++;
10182 wait_multiplier = (unsigned int) ceil (root->bytes_msg
10183 / (root->frag_off
10184 / root->frag_count)) * 4;
10185 }
10186 else
10187 {
10188 // No fragments, we use 4 RTT before retransmitting.
10189 wait_multiplier = 4;
10190 }
10191
10192 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
10193 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
10194
10195 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10196 "Wait multiplier %u\n",
10197 wait_multiplier);
10198
10199 /* Message not finished, waiting for acknowledgement.
10200 Update time by which we might retransmit 's' based on queue
10201 characteristics (i.e. RTT); it takes one RTT for the message to
10202 arrive and the ACK to come back in the best case; but the other
10203 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
10204 retransmitting.
10205
10206 OPTIMIZE: Note that in the future this heuristic should likely
10207 be improved further (measure RTT stability, consider message
10208 urgency and size when delaying ACKs, etc.) */
10209
10210 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
10211 queue->pd.aged_rtt.rel_value_us)
10212 wait_duration = queue->pd.aged_rtt;
10213 else
10214 {
10215 wait_duration = DEFAULT_ACK_WAIT_DURATION;
10216 wait_multiplier = 4;
10217 }
10218 struct GNUNET_TIME_Absolute next = GNUNET_TIME_relative_to_absolute (
10219 GNUNET_TIME_relative_multiply (
10220 wait_duration, wait_multiplier));
10221 struct GNUNET_TIME_Relative plus = GNUNET_TIME_relative_multiply (
10222 wait_duration, wait_multiplier);
10223 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10224 "Waiting %s (%s) for ACK until %s\n",
10225 GNUNET_STRINGS_relative_time_to_string (
10226 GNUNET_TIME_relative_multiply (
10227 queue->pd.aged_rtt, wait_multiplier), GNUNET_NO),
10228 GNUNET_STRINGS_relative_time_to_string (plus, GNUNET_YES),
10229 GNUNET_STRINGS_absolute_time_to_string (next));
10230 update_pm_next_attempt (pm,
10231 GNUNET_TIME_relative_to_absolute (
10232 GNUNET_TIME_relative_multiply (wait_duration,
10233 wait_multiplier)));
10234 }
10235 /* finally, re-schedule queue transmission task itself */
10236 schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
10237 queue,
10238 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
10239}
10240
10241
10242/**
10243 * Queue to a peer went down. Process the request.
10244 *
10245 * @param cls the client
10246 * @param dqm the send message that was sent
10247 */
10248static void
10249handle_del_queue_message (void *cls,
10250 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
10251{
10252 struct TransportClient *tc = cls;
10253
10254 if (CT_COMMUNICATOR != tc->type)
10255 {
10256 GNUNET_break (0);
10257 GNUNET_SERVICE_client_drop (tc->client);
10258 return;
10259 }
10260 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
10261 queue = queue->next_client)
10262 {
10263 struct Neighbour *neighbour = queue->neighbour;
10264
10265 if ((ntohl (dqm->qid) != queue->qid) ||
10266 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
10267 continue;
10268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10269 "Dropped queue %s to peer %s\n",
10270 queue->address,
10271 GNUNET_i2s (&neighbour->pid));
10272 free_queue (queue);
10273 GNUNET_SERVICE_client_continue (tc->client);
10274 return;
10275 }
10276 GNUNET_break (0);
10277 GNUNET_SERVICE_client_drop (tc->client);
10278}
10279
10280
10281/**
10282 * Message was transmitted. Process the request.
10283 *
10284 * @param cls the client
10285 * @param sma the send message that was sent
10286 */
10287static void
10288handle_send_message_ack (void *cls,
10289 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
10290{
10291 struct TransportClient *tc = cls;
10292 struct QueueEntry *qe;
10293 struct PendingMessage *pm;
10294
10295 if (CT_COMMUNICATOR != tc->type)
10296 {
10297 GNUNET_break (0);
10298 GNUNET_SERVICE_client_drop (tc->client);
10299 return;
10300 }
10301
10302 /* find our queue entry matching the ACK */
10303 qe = NULL;
10304 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10305 "Looking for queue for PID %s\n",
10306 GNUNET_i2s (&sma->receiver));
10307 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
10308 queue = queue->next_client)
10309 {
10310 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
10311 continue;
10312 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10313 "Found PID %s\n",
10314 GNUNET_i2s (&queue->neighbour->pid));
10315
10316
10317 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
10318 qep = qep->next)
10319 {
10320 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
10321 sma->qid))
10322 continue;
10323 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10324 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
10325 PRIu64 " Ack QID %u\n",
10326 qep->mid,
10327 queue->qid,
10328 GNUNET_ntohll (sma->mid),
10329 ntohl (sma->qid));
10330 qe = qep;
10331 if ((NULL != qe->pm) && (qe->pm->qe != qe))
10332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10333 "For pending message %" PRIu64 " we had retransmissions.\n",
10334 qe->pm->logging_uuid);
10335 break;
10336 }
10337 }
10338 if (NULL == qe)
10339 {
10340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10341 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
10342 GNUNET_ntohll (sma->mid),
10343 ntohl (sma->qid));
10344 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
10345 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
10346 /* this should never happen */
10347 GNUNET_break (0);
10348 //GNUNET_SERVICE_client_drop (tc->client);
10349 GNUNET_SERVICE_client_continue (tc->client);
10350 return;
10351 }
10352 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
10353 qe->queue->queue_tail,
10354 qe);
10355 qe->queue->queue_length--;
10356 tc->details.communicator.total_queue_length--;
10357 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10358 "Received ACK on queue %s to peer %s (new length: %u/%u)\n",
10359 qe->queue->address,
10360 GNUNET_i2s (&qe->queue->neighbour->pid),
10361 qe->queue->queue_length,
10362 tc->details.communicator.total_queue_length);
10363 GNUNET_SERVICE_client_continue (tc->client);
10364
10365 /* if applicable, resume transmissions that waited on ACK */
10366 if (COMMUNICATOR_TOTAL_QUEUE_LIMIT - 1 ==
10367 tc->details.communicator.total_queue_length)
10368 {
10369 /* Communicator dropped below threshold, resume all queues
10370 incident with this client! */
10371 GNUNET_STATISTICS_update (
10372 GST_stats,
10373 "# Transmission throttled due to communicator queue limit",
10374 -1,
10375 GNUNET_NO);
10376 for (struct Queue *queue = tc->details.communicator.queue_head;
10377 NULL != queue;
10378 queue = queue->next_client)
10379 {
10380 schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
10381 queue,
10382 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
10383 }
10384 }
10385 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
10386 {
10387 /* queue dropped below threshold; only resume this one queue */
10388 GNUNET_STATISTICS_update (GST_stats,
10389 "# Transmission throttled due to queue queue limit",
10390 -1,
10391 GNUNET_NO);
10392 schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
10393 qe->queue,
10394 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
10395 }
10396 else if (1 == qe->queue->q_capacity)
10397 {
10398 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
10399 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10400 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
10401 PRIu64 ".\n",
10402 qe->queue->qid,
10403 qe->queue->q_capacity);
10404 /* message queue has capacity; only resume this one queue */
10405 /* queue dropped below threshold; only resume this one queue */
10406 GNUNET_STATISTICS_update (GST_stats,
10407 "# Transmission throttled due to message queue capacity",
10408 -1,
10409 GNUNET_NO);
10410 schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
10411 qe->queue,
10412 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
10413 }
10414
10415 if (NULL != (pm = qe->pm))
10416 {
10417 struct VirtualLink *vl;
10418
10419 // GNUNET_assert (qe == pm->qe);
10420 pm->qe = NULL;
10421 /* If waiting for this communicator may have blocked transmission
10422 of pm on other queues for this neighbour, force schedule
10423 transmit on queue for queues of the neighbour */
10424 if (NULL == pm->frag_parent)
10425 {
10426 vl = pm->vl;
10427 if ((NULL != vl) &&
10428 (NULL != vl->pending_msg_head) &&
10429 (vl->pending_msg_head == pm))
10430 check_vl_transmission (vl);
10431 }
10432 }
10433 GNUNET_free (qe);
10434}
10435
10436
10437/**
10438 * Iterator telling new MONITOR client about all existing
10439 * queues to peers.
10440 *
10441 * @param cls the new `struct TransportClient`
10442 * @param pid a connected peer
10443 * @param value the `struct Neighbour` with more information
10444 * @return #GNUNET_OK (continue to iterate)
10445 */
10446static int
10447notify_client_queues (void *cls,
10448 const struct GNUNET_PeerIdentity *pid,
10449 void *value)
10450{
10451 struct TransportClient *tc = cls;
10452 struct Neighbour *neighbour = value;
10453
10454 GNUNET_assert (CT_MONITOR == tc->type);
10455 for (struct Queue *q = neighbour->queue_head; NULL != q;
10456 q = q->next_neighbour)
10457 {
10458 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
10459 .cs = q->cs,
10460 .num_msg_pending = q->num_msg_pending,
10461 .num_bytes_pending = q->num_bytes_pending };
10462
10463 notify_monitor (tc, pid, q->address, q->nt, &me);
10464 }
10465 return GNUNET_OK;
10466}
10467
10468
10469/**
10470 * Initialize a monitor client.
10471 *
10472 * @param cls the client
10473 * @param start the start message that was sent
10474 */
10475static void
10476handle_monitor_start (void *cls,
10477 const struct GNUNET_TRANSPORT_MonitorStart *start)
10478{
10479 struct TransportClient *tc = cls;
10480
10481 if (CT_NONE != tc->type)
10482 {
10483 GNUNET_break (0);
10484 GNUNET_SERVICE_client_drop (tc->client);
10485 return;
10486 }
10487 tc->type = CT_MONITOR;
10488 tc->details.monitor.peer = start->peer;
10489 tc->details.monitor.one_shot = ntohl (start->one_shot);
10490 GNUNET_CONTAINER_multipeermap_iterate (neighbours, &notify_client_queues, tc);
10491 GNUNET_SERVICE_client_mark_monitor (tc->client);
10492 GNUNET_SERVICE_client_continue (tc->client);
10493}
10494
10495
10496/**
10497 * Find transport client providing communication service
10498 * for the protocol @a prefix.
10499 *
10500 * @param prefix communicator name
10501 * @return NULL if no such transport client is available
10502 */
10503static struct TransportClient *
10504lookup_communicator (const char *prefix)
10505{
10506 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
10507 {
10508 if (CT_COMMUNICATOR != tc->type)
10509 continue;
10510 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
10511 return tc;
10512 }
10513 GNUNET_log (
10514 GNUNET_ERROR_TYPE_WARNING,
10515 "Somone suggested use of communicator for `%s', but we do not have such a communicator!\n",
10516 prefix);
10517 return NULL;
10518}
10519
10520
10521/**
10522 * Signature of a function called with a communicator @a address of a peer
10523 * @a pid that an application wants us to connect to.
10524 *
10525 * @param pid target peer
10526 * @param address the address to try
10527 */
10528static void
10529suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address)
10530{
10531 static uint32_t idgen;
10532 struct TransportClient *tc;
10533 char *prefix;
10534 struct GNUNET_TRANSPORT_CreateQueue *cqm;
10535 struct GNUNET_MQ_Envelope *env;
10536 size_t alen;
10537
10538 prefix = GNUNET_HELLO_address_to_prefix (address);
10539 if (NULL == prefix)
10540 {
10541 GNUNET_break (0); /* We got an invalid address!? */
10542 return;
10543 }
10544 tc = lookup_communicator (prefix);
10545 if (NULL == tc)
10546 {
10547 GNUNET_STATISTICS_update (GST_stats,
10548 "# Suggestions ignored due to missing communicator",
10549 1,
10550 GNUNET_NO);
10551 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
10552 "Cannot connect to %s at `%s', no matching communicator present\n",
10553 GNUNET_i2s (pid),
10554 address);
10555 GNUNET_free (prefix);
10556 return;
10557 }
10558 /* forward suggestion for queue creation to communicator */
10559 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10560 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
10561 (unsigned int) idgen,
10562 prefix,
10563 GNUNET_i2s (pid),
10564 address);
10565 GNUNET_free (prefix);
10566 alen = strlen (address) + 1;
10567 env =
10568 GNUNET_MQ_msg_extra (cqm, alen, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE);
10569 cqm->request_id = htonl (idgen++);
10570 cqm->receiver = *pid;
10571 memcpy (&cqm[1], address, alen);
10572 GNUNET_MQ_send (tc->mq, env);
10573}
10574
10575
10576/**
10577 * The queue @a q (which matches the peer and address in @a vs) is
10578 * ready for queueing. We should now queue the validation request.
10579 *
10580 * @param q queue to send on
10581 * @param vs state to derive validation challenge from
10582 */
10583static void
10584validation_transmit_on_queue (struct Queue *q, struct ValidationState *vs)
10585{
10586 struct TransportValidationChallengeMessage tvc;
10587
10588 vs->last_challenge_use = GNUNET_TIME_absolute_get_monotonic (GST_cfg);
10589 tvc.header.type =
10590 htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE);
10591 tvc.header.size = htons (sizeof(tvc));
10592 tvc.reserved = htonl (0);
10593 tvc.challenge = vs->challenge;
10594 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
10595 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
10596 "Sending address validation challenge %s to %s\n",
10597 GNUNET_sh2s (&tvc.challenge.value),
10598 GNUNET_i2s (&q->neighbour->pid));
10599 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
10600}
10601
10602
10603/**
10604 * Task run periodically to validate some address based on #validation_heap.
10605 *
10606 * @param cls NULL
10607 */
10608static void
10609validation_start_cb (void *cls)
10610{
10611 struct ValidationState *vs;
10612 struct Queue *q;
10613 const struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get_monotonic (
10614 GST_cfg);
10615
10616 (void) cls;
10617 validation_task = NULL;
10618 vs = GNUNET_CONTAINER_heap_peek (validation_heap);
10619 /* drop validations past their expiration */
10620 while (
10621 (NULL != vs) &&
10622 (0 == GNUNET_TIME_absolute_get_remaining (vs->valid_until).rel_value_us))
10623 {
10624 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10625 "Validation response %s cleaned up\n",
10626 GNUNET_sh2s (&vs->challenge.value));
10627 free_validation_state (vs);
10628 vs = GNUNET_CONTAINER_heap_peek (validation_heap);
10629 }
10630 if (NULL == vs)
10631 {
10632 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
10633 "Address validation task not scheduled anymore, nothing to do\n");
10634 return; /* woopsie, no more addresses known, should only
10635 happen if we're really a lonely peer */
10636 }
10637 q = find_queue (&vs->pid, vs->address);
10638 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
10639 {
10640 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10641 "To early to start next address validation for challenge %s\n",
10642 GNUNET_sh2s (&vs->challenge.value));
10643 return;
10644 }
10645 if (NULL == q)
10646 {
10647 vs->awaiting_queue = GNUNET_YES;
10648 suggest_to_connect (&vs->pid, vs->address);
10649 }
10650 else
10651 validation_transmit_on_queue (q, vs);
10652 /* Finally, reschedule next attempt */
10653 vs->challenge_backoff =
10654 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
10655 MAX_VALIDATION_CHALLENGE_FREQ);
10656 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10657 "Address validation task will run again in %s\n",
10658 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
10659 GNUNET_YES));
10660 update_next_challenge_time (vs,
10661 GNUNET_TIME_relative_to_absolute (
10662 vs->challenge_backoff));
10663}
10664
10665
10666/**
10667 * Closure for #check_connection_quality.
10668 */
10669struct QueueQualityContext
10670{
10671 /**
10672 * Set to the @e k'th queue encountered.
10673 */
10674 struct Queue *q;
10675
10676 /**
10677 * Set to the number of quality queues encountered.
10678 */
10679 unsigned int quality_count;
10680
10681 /**
10682 * Set to the total number of queues encountered.
10683 */
10684 unsigned int num_queues;
10685
10686 /**
10687 * Decremented for each queue, for selection of the
10688 * k-th queue in @e q.
10689 */
10690 unsigned int k;
10691};
10692
10693
10694/**
10695 * Check whether any queue to the given neighbour is
10696 * of a good "quality" and if so, increment the counter.
10697 * Also counts the total number of queues, and returns
10698 * the k-th queue found.
10699 *
10700 * @param cls a `struct QueueQualityContext *` with counters
10701 * @param pid peer this is about
10702 * @param value a `struct Neighbour`
10703 * @return #GNUNET_OK (continue to iterate)
10704 */
10705static int
10706check_connection_quality (void *cls,
10707 const struct GNUNET_PeerIdentity *pid,
10708 void *value)
10709{
10710 struct QueueQualityContext *ctx = cls;
10711 struct Neighbour *n = value;
10712 int do_inc;
10713
10714 (void) pid;
10715 do_inc = GNUNET_NO;
10716 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
10717 {
10718 ctx->num_queues++;
10719 if (0 == ctx->k--)
10720 ctx->q = q;
10721 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
10722 statistics and consider those as well here? */
10723 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
10724 do_inc = GNUNET_YES;
10725 }
10726 if (GNUNET_YES == do_inc)
10727 ctx->quality_count++;
10728 return GNUNET_OK;
10729}
10730
10731
10732/**
10733 * Task run when we CONSIDER initiating a DV learn
10734 * process. We first check that sending out a message is
10735 * even possible (queues exist), then that it is desirable
10736 * (if not, reschedule the task for later), and finally
10737 * we may then begin the job. If there are too many
10738 * entries in the #dvlearn_map, we purge the oldest entry
10739 * using #lle_tail.
10740 *
10741 * @param cls NULL
10742 */
10743static void
10744start_dv_learn (void *cls)
10745{
10746 struct LearnLaunchEntry *lle;
10747 struct QueueQualityContext qqc;
10748 struct TransportDVLearnMessage dvl;
10749
10750 (void) cls;
10751 dvlearn_task = NULL;
10752 if (0 == GNUNET_CONTAINER_multipeermap_size (neighbours))
10753 return; /* lost all connectivity, cannot do learning */
10754 qqc.quality_count = 0;
10755 qqc.num_queues = 0;
10756 qqc.k = GNUNET_CONTAINER_multipeermap_size (neighbours);
10757 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
10758 &check_connection_quality,
10759 &qqc);
10760 if (qqc.quality_count > DV_LEARN_QUALITY_THRESHOLD)
10761 {
10762 struct GNUNET_TIME_Relative delay;
10763 unsigned int factor;
10764
10765 /* scale our retries by how far we are above the threshold */
10766 factor = qqc.quality_count / DV_LEARN_QUALITY_THRESHOLD;
10767 delay = GNUNET_TIME_relative_multiply (DV_LEARN_BASE_FREQUENCY, factor);
10768 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10769 "At connection quality %u, will launch DV learn in %s\n",
10770 qqc.quality_count,
10771 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
10772 dvlearn_task = GNUNET_SCHEDULER_add_delayed (delay, &start_dv_learn, NULL);
10773 return;
10774 }
10775 /* remove old entries in #dvlearn_map if it has grown too big */
10776 while (MAX_DV_LEARN_PENDING <=
10777 GNUNET_CONTAINER_multishortmap_size (dvlearn_map))
10778 {
10779 lle = lle_tail;
10780 GNUNET_assert (GNUNET_YES ==
10781 GNUNET_CONTAINER_multishortmap_remove (dvlearn_map,
10782 &lle->challenge.value,
10783 lle));
10784 GNUNET_CONTAINER_DLL_remove (lle_head, lle_tail, lle);
10785 GNUNET_free (lle);
10786 }
10787 /* setup data structure for learning */
10788 lle = GNUNET_new (struct LearnLaunchEntry);
10789 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
10790 &lle->challenge,
10791 sizeof(lle->challenge));
10792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10793 "Starting launch DV learn with challenge %s\n",
10794 GNUNET_sh2s (&lle->challenge.value));
10795 GNUNET_CONTAINER_DLL_insert (lle_head, lle_tail, lle);
10796 GNUNET_break (GNUNET_YES ==
10797 GNUNET_CONTAINER_multishortmap_put (
10798 dvlearn_map,
10799 &lle->challenge.value,
10800 lle,
10801 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
10802 dvl.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN);
10803 dvl.header.size = htons (sizeof(dvl));
10804 dvl.num_hops = htons (0);
10805 dvl.bidirectional = htons (0);
10806 dvl.non_network_delay = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);
10807 dvl.monotonic_time =
10808 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (GST_cfg));
10809 {
10810 struct DvInitPS dvip = {
10811 .purpose.purpose = htonl (
10812 GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR),
10813 .purpose.size = htonl (sizeof(dvip)),
10814 .monotonic_time = dvl.monotonic_time,
10815 .challenge = lle->challenge
10816 };
10817
10818 GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
10819 &dvip,
10820 &dvl.init_sig);
10821 }
10822 dvl.initiator = GST_my_identity;
10823 dvl.challenge = lle->challenge;
10824
10825 qqc.quality_count = 0;
10826 qqc.k = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, qqc.num_queues);
10827 qqc.num_queues = 0;
10828 qqc.q = NULL;
10829 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
10830 &check_connection_quality,
10831 &qqc);
10832 GNUNET_assert (NULL != qqc.q);
10833
10834 /* Do this as close to transmission time as possible! */
10835 lle->launch_time = GNUNET_TIME_absolute_get ();
10836
10837 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
10838 /* reschedule this job, randomizing the time it runs (but no
10839 actual backoff!) */
10840 dvlearn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_randomize (
10841 DV_LEARN_BASE_FREQUENCY),
10842 &start_dv_learn,
10843 NULL);
10844}
10845
10846
10847/**
10848 * Get the IP address without the port number.
10849 *
10850 * @param address The string contains a communicator prefix, IP address and port
10851 * like this 'tcp-92.68.150.1:55452'.
10852 * @return String with IP address only.
10853 */
10854static char *
10855get_address_without_port (const char *address)
10856{
10857 const char *colon;
10858 char *colon_rest;
10859 size_t colon_rest_length;
10860 char *address_without_port;
10861
10862 colon = strchr (address,':');
10863 colon_rest = GNUNET_strndup (address, colon - address);
10864 colon_rest_length = strlen (colon_rest);
10865 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
10866 GNUNET_free (colon_rest);
10867
10868 return address_without_port;
10869}
10870
10871
10872/**
10873 * A new queue has been created, check if any address validation
10874 * requests have been waiting for it.
10875 *
10876 * @param cls a `struct Queue`
10877 * @param pid peer concerned (unused)
10878 * @param value a `struct ValidationState`
10879 * @return #GNUNET_NO if a match was found and we can stop looking
10880 */
10881static int
10882check_validation_request_pending (void *cls,
10883 const struct GNUNET_PeerIdentity *pid,
10884 void *value)
10885{
10886 struct Queue *q = cls;
10887 struct ValidationState *vs = value;
10888 char *address_without_port_vs;
10889 char *address_without_port_q;
10890 int success = GNUNET_YES;
10891
10892 address_without_port_vs = get_address_without_port (vs->address);
10893 address_without_port_q = get_address_without_port (q->address);
10894
10895 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10896 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
10897 GNUNET_i2s (pid),
10898 address_without_port_vs,
10899 address_without_port_q);
10900 (void) pid;
10901 if ((GNUNET_YES == vs->awaiting_queue) &&
10902 (0 == strcmp (address_without_port_vs, address_without_port_q)))
10903 {
10904
10905 vs->awaiting_queue = GNUNET_NO;
10906 validation_transmit_on_queue (q, vs);
10907 success = GNUNET_NO;
10908 }
10909
10910 GNUNET_free (address_without_port_vs);
10911 GNUNET_free (address_without_port_q);
10912 return success;
10913}
10914
10915
10916/**
10917 * Function called with the monotonic time of a DV initiator
10918 * by PEERSTORE. Updates the time.
10919 *
10920 * @param cls a `struct Neighbour`
10921 * @param record the information found, NULL for the last call
10922 * @param emsg error message
10923 */
10924static void
10925neighbour_dv_monotime_cb (void *cls,
10926 const struct GNUNET_PEERSTORE_Record *record,
10927 const char *emsg)
10928{
10929 struct Neighbour *n = cls;
10930 struct GNUNET_TIME_AbsoluteNBO *mtbe;
10931
10932 (void) emsg;
10933 if (NULL == record)
10934 {
10935 /* we're done with #neighbour_dv_monotime_cb() invocations,
10936 continue normal processing */
10937 n->get = NULL;
10938 n->dv_monotime_available = GNUNET_YES;
10939 return;
10940 }
10941 if (sizeof(*mtbe) != record->value_size)
10942 {
10943 GNUNET_break (0);
10944 return;
10945 }
10946 mtbe = record->value;
10947 n->last_dv_learn_monotime =
10948 GNUNET_TIME_absolute_max (n->last_dv_learn_monotime,
10949 GNUNET_TIME_absolute_ntoh (*mtbe));
10950}
10951
10952
10953/**
10954 * New queue became available. Process the request.
10955 *
10956 * @param cls the client
10957 * @param aqm the send message that was sent
10958 */
10959static void
10960handle_add_queue_message (void *cls,
10961 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
10962{
10963 struct TransportClient *tc = cls;
10964 struct Queue *queue;
10965 struct Neighbour *neighbour;
10966 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
10967 const char *addr;
10968 uint16_t addr_len;
10969
10970 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
10971 {
10972 /* MTU so small as to be useless for transmissions,
10973 required for #fragment_message()! */
10974 GNUNET_break_op (0);
10975 GNUNET_SERVICE_client_drop (tc->client);
10976 return;
10977 }
10978 /* This may simply be a queue update */
10979 for (queue = tc->details.communicator.queue_head;
10980 NULL != queue;
10981 queue = queue->next_client)
10982 {
10983 validated_until = queue->validated_until;
10984 if (queue->qid != ntohl (aqm->qid))
10985 continue;
10986 break;
10987 }
10988
10989 if (NULL != queue)
10990 {
10991 neighbour = queue->neighbour;
10992 }
10993 else
10994 {
10995 neighbour = lookup_neighbour (&aqm->receiver);
10996 if (NULL == neighbour)
10997 {
10998 neighbour = GNUNET_new (struct Neighbour);
10999 neighbour->pid = aqm->receiver;
11000 GNUNET_assert (GNUNET_OK ==
11001 GNUNET_CONTAINER_multipeermap_put (
11002 neighbours,
11003 &neighbour->pid,
11004 neighbour,
11005 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
11006 neighbour->get =
11007 GNUNET_PEERSTORE_iterate (peerstore,
11008 "transport",
11009 &neighbour->pid,
11010 GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME,
11011 &neighbour_dv_monotime_cb,
11012 neighbour);
11013 }
11014 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
11015 addr = (const char *) &aqm[1];
11016 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
11017 "New queue %s to %s available with QID %u and q_len %" PRIu64
11018 " and mtu %u\n",
11019 addr,
11020 GNUNET_i2s (&aqm->receiver),
11021 ntohl (aqm->qid),
11022 GNUNET_ntohll (aqm->q_len),
11023 ntohl (aqm->mtu));
11024 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
11025 queue->tc = tc;
11026 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us != validated_until.abs_value_us)
11027 {
11028 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
11029 "New queue with QID %u inherit validated until\n",
11030 ntohl (aqm->qid));
11031 queue->validated_until = validated_until;
11032 }
11033 queue->address = (const char *) &queue[1];
11034 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
11035 queue->qid = ntohl (aqm->qid);
11036 queue->neighbour = neighbour;
11037 if (GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED == GNUNET_ntohll (aqm->q_len))
11038 queue->unlimited_length = GNUNET_YES;
11039 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
11040 memcpy (&queue[1], addr, addr_len);
11041 /* notify monitors about new queue */
11042 {
11043 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
11044
11045 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
11046 }
11047 GNUNET_CONTAINER_MDLL_insert (neighbour,
11048 neighbour->queue_head,
11049 neighbour->queue_tail,
11050 queue);
11051 GNUNET_CONTAINER_MDLL_insert (client,
11052 tc->details.communicator.queue_head,
11053 tc->details.communicator.queue_tail,
11054 queue);
11055
11056 }
11057 queue->mtu = ntohl (aqm->mtu);
11058 queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
11059 queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
11060 queue->idle = GNUNET_YES;
11061 /* check if valdiations are waiting for the queue */
11062 (void)
11063 GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
11064 &aqm->receiver,
11065 &check_validation_request_pending,
11066 queue);
11067 /* look for traffic for this queue */
11068 schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
11069 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
11070 /* might be our first queue, try launching DV learning */
11071 if (NULL == dvlearn_task)
11072 dvlearn_task = GNUNET_SCHEDULER_add_now (&start_dv_learn, NULL);
11073 GNUNET_SERVICE_client_continue (tc->client);
11074}
11075
11076
11077/**
11078 * @brief Handle updates to queues.
11079 *
11080 * @param cls the transport client.
11081 * @param msg Message struct.
11082 */
11083static void
11084handle_update_queue_message (void *cls,
11085 const struct
11086 GNUNET_TRANSPORT_UpdateQueueMessage *msg)
11087{
11088 struct TransportClient *tc = cls;
11089 struct Queue *target_queue = NULL;
11090
11091 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
11092 "Received queue update message for %u with q_len %llu and mtu %u\n",
11093 ntohl (msg->qid),
11094 (unsigned long long) GNUNET_ntohll (msg->q_len),
11095 ntohl (msg->mtu));
11096 for (target_queue = tc->details.communicator.queue_head;
11097 NULL != target_queue;
11098 target_queue = target_queue->next_client)
11099 {
11100 if (ntohl (msg->qid) == target_queue->qid)
11101 break;
11102 }
11103 if (NULL == target_queue)
11104 {
11105 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
11106 "Queue to update no longer exists! Discarding update.\n");
11107 return;
11108 }
11109
11110 target_queue->nt = msg->nt;
11111 target_queue->mtu = ntohl (msg->mtu);
11112 target_queue->cs = msg->cs;
11113 target_queue->priority = ntohl (msg->priority);
11114 /* The update message indicates how many messages
11115 * the queue should be able to handle.
11116 */
11117 if (GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED == GNUNET_ntohll (msg->q_len))
11118 target_queue->unlimited_length = GNUNET_YES;
11119 else
11120 target_queue->unlimited_length = GNUNET_NO;
11121 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
11122 if (0 < target_queue->q_capacity)
11123 schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
11124 target_queue,
11125 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
11126 GNUNET_SERVICE_client_continue (tc->client);
11127}
11128
11129
11130/**
11131 * Communicator tells us that our request to create a queue "worked", that
11132 * is setting up the queue is now in process.
11133 *
11134 * @param cls the `struct TransportClient`
11135 * @param cqr confirmation message
11136 */
11137static void
11138handle_queue_create_ok (void *cls,
11139 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
11140{
11141 struct TransportClient *tc = cls;
11142
11143 if (CT_COMMUNICATOR != tc->type)
11144 {
11145 GNUNET_break (0);
11146 GNUNET_SERVICE_client_drop (tc->client);
11147 return;
11148 }
11149 GNUNET_STATISTICS_update (GST_stats,
11150 "# Suggestions succeeded at communicator",
11151 1,
11152 GNUNET_NO);
11153 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
11154 "Request #%u for communicator to create queue succeeded\n",
11155 (unsigned int) ntohs (cqr->request_id));
11156 GNUNET_SERVICE_client_continue (tc->client);
11157}
11158
11159
11160/**
11161 * Communicator tells us that our request to create a queue failed. This
11162 * usually indicates that the provided address is simply invalid or that the
11163 * communicator's resources are exhausted.
11164 *
11165 * @param cls the `struct TransportClient`
11166 * @param cqr failure message
11167 */
11168static void
11169handle_queue_create_fail (
11170 void *cls,
11171 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
11172{
11173 struct TransportClient *tc = cls;
11174
11175 if (CT_COMMUNICATOR != tc->type)
11176 {
11177 GNUNET_break (0);
11178 GNUNET_SERVICE_client_drop (tc->client);
11179 return;
11180 }
11181 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
11182 "Request #%u for communicator to create queue failed\n",
11183 (unsigned int) ntohs (cqr->request_id));
11184 GNUNET_STATISTICS_update (GST_stats,
11185 "# Suggestions failed in queue creation at communicator",
11186 1,
11187 GNUNET_NO);
11188 GNUNET_SERVICE_client_continue (tc->client);
11189}
11190
11191
11192/**
11193 * We have received a `struct ExpressPreferenceMessage` from an application
11194 * client.
11195 *
11196 * @param cls handle to the client
11197 * @param msg the start message
11198 */
11199static void
11200handle_suggest_cancel (void *cls, const struct ExpressPreferenceMessage *msg)
11201{
11202 struct TransportClient *tc = cls;
11203 struct PeerRequest *pr;
11204
11205 if (CT_APPLICATION != tc->type)
11206 {
11207 GNUNET_break (0);
11208 GNUNET_SERVICE_client_drop (tc->client);
11209 return;
11210 }
11211 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
11212 &msg->peer);
11213 if (NULL == pr)
11214 {
11215 GNUNET_break (0);
11216 GNUNET_SERVICE_client_drop (tc->client);
11217 return;
11218 }
11219 (void) stop_peer_request (tc, &pr->pid, pr);
11220 GNUNET_SERVICE_client_continue (tc->client);
11221}
11222
11223
11224static void
11225hello_for_client_cb (void *cls,
11226 const char *uri)
11227{
11228 const struct GNUNET_PeerIdentity *peer = cls;
11229 int pfx_len;
11230 const char *eou;
11231 char *address;
11232
11233 eou = strstr (uri,
11234 "://");
11235 pfx_len = eou - uri;
11236 eou += 3;
11237 GNUNET_asprintf (&address,
11238 "%.*s-%s",
11239 pfx_len,
11240 uri,
11241 eou);
11242
11243 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
11244 "hello for client %s\n",
11245 address);
11246
11247 start_address_validation (peer, address);
11248 GNUNET_free (address);
11249}
11250
11251
11252/**
11253 * Function called by PEERSTORE for each matching record.
11254 *
11255 * @param cls closure, a `struct PeerRequest`
11256 * @param record peerstore record information
11257 * @param emsg error message, or NULL if no errors
11258 */
11259static void
11260handle_hello_for_client (void *cls,
11261 const struct GNUNET_PeerIdentity *peer,
11262 const struct GNUNET_MessageHeader *hello,
11263 const char *emsg)
11264{
11265 (void) cls;
11266 const char *val;
11267 struct GNUNET_HELLO_Builder *builder;
11268
11269 if (NULL != emsg)
11270 {
11271 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
11272 "Got failure from PEERSTORE: %s\n",
11273 emsg);
11274 return;
11275 }
11276 if (0 == GNUNET_memcmp (peer, &GST_my_identity))
11277 return;
11278 builder = GNUNET_HELLO_builder_new (peer);
11279 GNUNET_HELLO_builder_iterate (builder,
11280 (struct GNUNET_PeerIdentity *) peer,
11281 hello_for_client_cb,
11282 NULL);
11283}
11284
11285
11286/**
11287 * We have received a `struct ExpressPreferenceMessage` from an application
11288 * client.
11289 *
11290 * @param cls handle to the client
11291 * @param msg the start message
11292 */
11293static void
11294handle_suggest (void *cls, const struct ExpressPreferenceMessage *msg)
11295{
11296 struct TransportClient *tc = cls;
11297 struct PeerRequest *pr;
11298
11299 if (CT_NONE == tc->type)
11300 {
11301 tc->type = CT_APPLICATION;
11302 tc->details.application.requests =
11303 GNUNET_CONTAINER_multipeermap_create (16, GNUNET_YES);
11304 }
11305 if (CT_APPLICATION != tc->type)
11306 {
11307 GNUNET_break (0);
11308 GNUNET_SERVICE_client_drop (tc->client);
11309 return;
11310 }
11311 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
11312 "Client suggested we talk to %s with preference %d at rate %u\n",
11313 GNUNET_i2s (&msg->peer),
11314 (int) ntohl (msg->pk),
11315 (int) ntohl (msg->bw.value__));
11316 pr = GNUNET_new (struct PeerRequest);
11317 pr->tc = tc;
11318 pr->pid = msg->peer;
11319 pr->bw = msg->bw;
11320 pr->pk = (enum GNUNET_MQ_PriorityPreferences) ntohl (msg->pk);
11321 if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_put (
11322 tc->details.application.requests,
11323 &pr->pid,
11324 pr,
11325 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
11326 {
11327 GNUNET_break (0);
11328 GNUNET_free (pr);
11329 GNUNET_SERVICE_client_drop (tc->client);
11330 return;
11331 }
11332 pr->nc = GNUNET_PEERSTORE_hello_changed_notify (peerstore,
11333 GNUNET_NO,
11334 &handle_hello_for_client,
11335 NULL);
11336 GNUNET_SERVICE_client_continue (tc->client);
11337}
11338
11339
11340/**
11341 * Check #GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION
11342 * messages.
11343 *
11344 * @param cls a `struct TransportClient *`
11345 * @param m message to verify
11346 * @return #GNUNET_OK on success
11347 */
11348static int
11349check_request_hello_validation (void *cls,
11350 const struct RequestHelloValidationMessage *m)
11351{
11352 (void) cls;
11353 GNUNET_MQ_check_zero_termination (m);
11354 return GNUNET_OK;
11355}
11356
11357
11358/**
11359 * A client encountered an address of another peer. Consider validating it,
11360 * and if validation succeeds, persist it to PEERSTORE.
11361 *
11362 * @param cls a `struct TransportClient *`
11363 * @param m message to verify
11364 */
11365static void
11366handle_request_hello_validation (void *cls,
11367 const struct RequestHelloValidationMessage *m)
11368{
11369 struct TransportClient *tc = cls;
11370
11371 start_address_validation (&m->peer, (const char *) &m[1]);
11372 GNUNET_SERVICE_client_continue (tc->client);
11373}
11374
11375
11376/**
11377 * Free neighbour entry.
11378 *
11379 * @param cls NULL
11380 * @param pid unused
11381 * @param value a `struct Neighbour`
11382 * @return #GNUNET_OK (always)
11383 */
11384static int
11385free_neighbour_cb (void *cls,
11386 const struct GNUNET_PeerIdentity *pid,
11387 void *value)
11388{
11389 struct Neighbour *neighbour = value;
11390
11391 (void) cls;
11392 (void) pid;
11393 GNUNET_break (0); // should this ever happen?
11394 free_neighbour (neighbour);
11395
11396 return GNUNET_OK;
11397}
11398
11399
11400/**
11401 * Free DV route entry.
11402 *
11403 * @param cls NULL
11404 * @param pid unused
11405 * @param value a `struct DistanceVector`
11406 * @return #GNUNET_OK (always)
11407 */
11408static int
11409free_dv_routes_cb (void *cls,
11410 const struct GNUNET_PeerIdentity *pid,
11411 void *value)
11412{
11413 struct DistanceVector *dv = value;
11414
11415 (void) cls;
11416 (void) pid;
11417 free_dv_route (dv);
11418
11419 return GNUNET_OK;
11420}
11421
11422
11423/**
11424 * Free validation state.
11425 *
11426 * @param cls NULL
11427 * @param pid unused
11428 * @param value a `struct ValidationState`
11429 * @return #GNUNET_OK (always)
11430 */
11431static int
11432free_validation_state_cb (void *cls,
11433 const struct GNUNET_PeerIdentity *pid,
11434 void *value)
11435{
11436 struct ValidationState *vs = value;
11437
11438 (void) cls;
11439 (void) pid;
11440 free_validation_state (vs);
11441 return GNUNET_OK;
11442}
11443
11444
11445/**
11446 * Free pending acknowledgement.
11447 *
11448 * @param cls NULL
11449 * @param key unused
11450 * @param value a `struct PendingAcknowledgement`
11451 * @return #GNUNET_OK (always)
11452 */
11453static int
11454free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
11455{
11456 struct PendingAcknowledgement *pa = value;
11457
11458 (void) cls;
11459 (void) key;
11460 free_pending_acknowledgement (pa);
11461 return GNUNET_OK;
11462}
11463
11464
11465/**
11466 * Free acknowledgement cummulator.
11467 *
11468 * @param cls NULL
11469 * @param pid unused
11470 * @param value a `struct AcknowledgementCummulator`
11471 * @return #GNUNET_OK (always)
11472 */
11473static int
11474free_ack_cummulator_cb (void *cls,
11475 const struct GNUNET_PeerIdentity *pid,
11476 void *value)
11477{
11478 struct AcknowledgementCummulator *ac = value;
11479
11480 (void) cls;
11481 (void) pid;
11482 GNUNET_SCHEDULER_cancel (ac->task);
11483 GNUNET_free (ac);
11484 return GNUNET_OK;
11485}
11486
11487
11488/**
11489 * Function called when the service shuts down. Unloads our plugins
11490 * and cancels pending validations.
11491 *
11492 * @param cls closure, unused
11493 */
11494static void
11495do_shutdown (void *cls)
11496{
11497 struct LearnLaunchEntry *lle;
11498
11499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
11500 "shutdown logic\n");
11501 (void) cls;
11502 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
11503 &free_neighbour_cb, NULL);
11504 if (NULL != validation_task)
11505 {
11506 GNUNET_SCHEDULER_cancel (validation_task);
11507 validation_task = NULL;
11508 }
11509 if (NULL != dvlearn_task)
11510 {
11511 GNUNET_SCHEDULER_cancel (dvlearn_task);
11512 dvlearn_task = NULL;
11513 }
11514 if (NULL != GST_stats)
11515 {
11516 GNUNET_STATISTICS_destroy (GST_stats, GNUNET_NO);
11517 GST_stats = NULL;
11518 }
11519 if (NULL != GST_my_hello)
11520 {
11521 GNUNET_HELLO_builder_free (GST_my_hello);
11522 GST_my_hello = NULL;
11523 }
11524 if (NULL != GST_my_private_key)
11525 {
11526 GNUNET_free (GST_my_private_key);
11527 GST_my_private_key = NULL;
11528 }
11529 GNUNET_CONTAINER_multipeermap_iterate (ack_cummulators,
11530 &free_ack_cummulator_cb,
11531 NULL);
11532 GNUNET_CONTAINER_multipeermap_destroy (ack_cummulators);
11533 ack_cummulators = NULL;
11534 GNUNET_CONTAINER_multiuuidmap_iterate (pending_acks,
11535 &free_pending_ack_cb,
11536 NULL);
11537 GNUNET_CONTAINER_multiuuidmap_destroy (pending_acks);
11538 pending_acks = NULL;
11539 GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_size (neighbours));
11540 GNUNET_CONTAINER_multipeermap_destroy (neighbours);
11541 neighbours = NULL;
11542 GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_size (links));
11543 GNUNET_CONTAINER_multipeermap_destroy (links);
11544 links = NULL;
11545 GNUNET_CONTAINER_multipeermap_iterate (backtalkers,
11546 &free_backtalker_cb,
11547 NULL);
11548 GNUNET_CONTAINER_multipeermap_destroy (backtalkers);
11549 backtalkers = NULL;
11550 GNUNET_CONTAINER_multipeermap_iterate (validation_map,
11551 &free_validation_state_cb,
11552 NULL);
11553 GNUNET_CONTAINER_multipeermap_destroy (validation_map);
11554 validation_map = NULL;
11555 while (NULL != ir_head)
11556 free_incoming_request (ir_head);
11557 GNUNET_assert (0 == ir_total);
11558 while (NULL != (lle = lle_head))
11559 {
11560 GNUNET_CONTAINER_DLL_remove (lle_head, lle_tail, lle);
11561 GNUNET_free (lle);
11562 }
11563 if (NULL != peerstore)
11564 {
11565 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
11566 "Disconnecting from PEERSTORE service\n");
11567 GNUNET_PEERSTORE_disconnect (peerstore, GNUNET_NO);
11568 peerstore = NULL;
11569 }
11570 GNUNET_CONTAINER_multishortmap_destroy (dvlearn_map);
11571 dvlearn_map = NULL;
11572 GNUNET_CONTAINER_heap_destroy (validation_heap);
11573 validation_heap = NULL;
11574 GNUNET_CONTAINER_multipeermap_iterate (dv_routes, &free_dv_routes_cb, NULL);
11575 GNUNET_CONTAINER_multipeermap_destroy (dv_routes);
11576 dv_routes = NULL;
11577 GNUNET_SCHEDULER_shutdown ();
11578}
11579
11580
11581static void
11582shutdown_task (void *cls)
11583{
11584 in_shutdown = GNUNET_YES;
11585
11586 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
11587 "Shutdown task executed\n");
11588 if (NULL != clients_head)
11589 {
11590 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11591 {
11592 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
11593 "client still connected: %u\n",
11594 tc->type);
11595 }
11596 }
11597 else
11598 do_shutdown (cls);
11599
11600}
11601
11602
11603/**
11604 * Initiate transport service.
11605 *
11606 * @param cls closure
11607 * @param c configuration to use
11608 * @param service the initialized service
11609 */
11610static void
11611run (void *cls,
11612 const struct GNUNET_CONFIGURATION_Handle *c,
11613 struct GNUNET_SERVICE_Handle *service)
11614{
11615 (void) cls;
11616 (void) service;
11617 /* setup globals */
11618 hello_mono_time = GNUNET_TIME_absolute_get_monotonic (c);
11619 in_shutdown = GNUNET_NO;
11620 GST_cfg = c;
11621 backtalkers = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_YES);
11622 pending_acks = GNUNET_CONTAINER_multiuuidmap_create (32768, GNUNET_YES);
11623 ack_cummulators = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_YES);
11624 neighbours = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES);
11625 links = GNUNET_CONTAINER_multipeermap_create (512, GNUNET_YES);
11626 dv_routes = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES);
11627 dvlearn_map = GNUNET_CONTAINER_multishortmap_create (2 * MAX_DV_LEARN_PENDING,
11628 GNUNET_YES);
11629 validation_map = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES);
11630 validation_heap =
11631 GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
11632 GST_my_private_key =
11633 GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
11634 if (NULL == GST_my_private_key)
11635 {
11636 GNUNET_log (
11637 GNUNET_ERROR_TYPE_ERROR,
11638 _ (
11639 "Transport service is lacking key configuration settings. Exiting.\n"));
11640 GNUNET_SCHEDULER_shutdown ();
11641 return;
11642 }
11643 GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
11644 &GST_my_identity.public_key);
11645 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
11646 "My identity is `%s'\n",
11647 GNUNET_i2s_full (&GST_my_identity));
11648 GST_my_hello = GNUNET_HELLO_builder_new (&GST_my_identity);
11649 GST_stats = GNUNET_STATISTICS_create ("transport", GST_cfg);
11650 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
11651 peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
11652 if (NULL == peerstore)
11653 {
11654 GNUNET_break (0);
11655 GNUNET_SCHEDULER_shutdown ();
11656 return;
11657 }
11658}
11659
11660
11661/**
11662 * Define "main" method using service macro.
11663 */
11664GNUNET_SERVICE_MAIN (
11665 "transport",
11666 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
11667 &run,
11668 &client_connect_cb,
11669 &client_disconnect_cb,
11670 NULL,
11671 /* communication with applications */
11672 GNUNET_MQ_hd_fixed_size (suggest,
11673 GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST,
11674 struct ExpressPreferenceMessage,
11675 NULL),
11676 GNUNET_MQ_hd_fixed_size (suggest_cancel,
11677 GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL,
11678 struct ExpressPreferenceMessage,
11679 NULL),
11680 GNUNET_MQ_hd_var_size (request_hello_validation,
11681 GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION,
11682 struct RequestHelloValidationMessage,
11683 NULL),
11684 /* communication with core */
11685 GNUNET_MQ_hd_fixed_size (client_start,
11686 GNUNET_MESSAGE_TYPE_TRANSPORT_START,
11687 struct StartMessage,
11688 NULL),
11689 GNUNET_MQ_hd_var_size (client_send,
11690 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
11691 struct OutboundMessage,
11692 NULL),
11693 GNUNET_MQ_hd_fixed_size (client_recv_ok,
11694 GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK,
11695 struct RecvOkMessage,
11696 NULL),
11697 /* communication with communicators */
11698 GNUNET_MQ_hd_var_size (communicator_available,
11699 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
11700 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
11701 NULL),
11702 GNUNET_MQ_hd_var_size (communicator_backchannel,
11703 GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL,
11704 struct GNUNET_TRANSPORT_CommunicatorBackchannel,
11705 NULL),
11706 GNUNET_MQ_hd_var_size (add_address,
11707 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
11708 struct GNUNET_TRANSPORT_AddAddressMessage,
11709 NULL),
11710 GNUNET_MQ_hd_fixed_size (del_address,
11711 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
11712 struct GNUNET_TRANSPORT_DelAddressMessage,
11713 NULL),
11714 GNUNET_MQ_hd_var_size (incoming_msg,
11715 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
11716 struct GNUNET_TRANSPORT_IncomingMessage,
11717 NULL),
11718 GNUNET_MQ_hd_fixed_size (queue_create_ok,
11719 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK,
11720 struct GNUNET_TRANSPORT_CreateQueueResponse,
11721 NULL),
11722 GNUNET_MQ_hd_fixed_size (queue_create_fail,
11723 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL,
11724 struct GNUNET_TRANSPORT_CreateQueueResponse,
11725 NULL),
11726 GNUNET_MQ_hd_var_size (add_queue_message,
11727 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
11728 struct GNUNET_TRANSPORT_AddQueueMessage,
11729 NULL),
11730 GNUNET_MQ_hd_fixed_size (update_queue_message,
11731 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE,
11732 struct GNUNET_TRANSPORT_UpdateQueueMessage,
11733 NULL),
11734 GNUNET_MQ_hd_fixed_size (del_queue_message,
11735 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
11736 struct GNUNET_TRANSPORT_DelQueueMessage,
11737 NULL),
11738 GNUNET_MQ_hd_fixed_size (send_message_ack,
11739 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
11740 struct GNUNET_TRANSPORT_SendMessageToAck,
11741 NULL),
11742 /* communication with monitors */
11743 GNUNET_MQ_hd_fixed_size (monitor_start,
11744 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
11745 struct GNUNET_TRANSPORT_MonitorStart,
11746 NULL),
11747 GNUNET_MQ_handler_end ());
11748
11749
11750/* end of file gnunet-service-transport.c */
diff --git a/src/transport/gnunet-service-transport.h b/src/transport/gnunet-service-transport.h
deleted file mode 100644
index ea9e71e4b..000000000
--- a/src/transport/gnunet-service-transport.h
+++ /dev/null
@@ -1,234 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010,2011 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 transport/gnunet-service-transport.h
23 * @brief globals
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_TRANSPORT_H
27#define GNUNET_SERVICE_TRANSPORT_H
28
29#include "gnunet_util_lib.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet_ats_service.h"
32#include "gnunet_transport_service.h"
33
34#define VERBOSE_VALIDATION GNUNET_YES
35
36/**
37 * Statistics handle.
38 */
39extern struct GNUNET_STATISTICS_Handle *GST_stats;
40
41/**
42 * Configuration handle.
43 */
44extern const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
45
46/**
47 * Configuration handle.
48 */
49extern struct GNUNET_PeerIdentity GST_my_identity;
50
51/**
52 * Handle to peerinfo service.
53 */
54extern struct GNUNET_PEERINFO_Handle *GST_peerinfo;
55
56/**
57 * Our private key.
58 */
59extern struct GNUNET_CRYPTO_EddsaPrivateKey GST_my_private_key;
60
61/**
62 * ATS handle.
63 */
64extern struct GNUNET_ATS_SchedulingHandle *GST_ats;
65
66/**
67 * ATS connectivity handle.
68 */
69extern struct GNUNET_ATS_ConnectivityHandle *GST_ats_connect;
70
71/**
72 * Interface scanner determines our LAN address range(s).
73 */
74extern struct GNUNET_NT_InterfaceScanner *GST_is;
75
76
77/**
78 * Function to call when a peer's address has changed
79 *
80 * @param cls closure
81 * @param peer peer this update is about,
82 * @param address address, NULL for disconnect notification
83 */
84typedef void
85(*GNUNET_TRANSPORT_NeighbourChangeCallback) (void *cls,
86 const struct
87 GNUNET_PeerIdentity *peer,
88 const struct
89 GNUNET_HELLO_Address *address,
90 enum GNUNET_TRANSPORT_PeerState
91 state,
92 struct GNUNET_TIME_Absolute
93 state_timeout,
94 struct GNUNET_BANDWIDTH_Value32NBO
95 bandwidth_in,
96 struct GNUNET_BANDWIDTH_Value32NBO
97 bandwidth_out);
98
99
100/**
101 * Continuation called from a blacklist test.
102 *
103 * @param cls closure
104 * @param peer identity of peer that was tested
105 * @param address address associated with the request
106 * @param session session associated with the request
107 * @param result #GNUNET_OK if the connection is allowed,
108 * #GNUNET_NO if not,
109 * #GNUNET_SYSERR if operation was aborted
110 */
111typedef void
112(*GST_BlacklistTestContinuation) (void *cls,
113 const struct GNUNET_PeerIdentity *peer,
114 const struct GNUNET_HELLO_Address *address,
115 struct GNUNET_ATS_Session *session,
116 int result);
117
118
119/**
120 * Add the given peer to the blacklist (for the given transport).
121 *
122 * @param peer peer to blacklist
123 * @param transport_name transport to blacklist for this peer, NULL for all
124 */
125void
126GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer,
127 const char *transport_name);
128
129
130/**
131 * Handle to an active blacklist check.
132 */
133struct GST_BlacklistCheck;
134
135
136/**
137 * Test if a peer/transport combination is blacklisted.
138 *
139 * @param peer the identity of the peer to test
140 * @param transport_name name of the transport to test, never NULL
141 * @param cont function to call with result
142 * @param cont_cls closure for @a cont
143 * @param address address to pass back to @a cont, can be NULL
144 * @param session session to pass back to @a cont, can be NULL
145 * @return handle to the blacklist check, NULL if the decision
146 * was made instantly and @a cont was already called
147 */
148struct GST_BlacklistCheck *
149GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer,
150 const char *transport_name,
151 GST_BlacklistTestContinuation cont,
152 void *cont_cls,
153 const struct GNUNET_HELLO_Address *address,
154 struct GNUNET_ATS_Session *session);
155
156
157/**
158 * Abort blacklist if @a address and @a session match.
159 *
160 * @param address address used to abort matching checks
161 * @param session session used to abort matching checks
162 */
163void
164GST_blacklist_abort_matching (const struct GNUNET_HELLO_Address *address,
165 struct GNUNET_ATS_Session *session);
166
167/**
168 * Cancel a blacklist check.
169 *
170 * @param bc check to cancel
171 */
172void
173GST_blacklist_test_cancel (struct GST_BlacklistCheck *bc);
174
175
176/**
177 * Function called by the transport for each received message.
178 *
179 * @param cls closure, const char* with the name of the plugin we received the message from
180 * @param address address and (claimed) identity of the other peer
181 * @param session identifier used for this session (NULL for plugins
182 * that do not offer bi-directional communication to the sender
183 * using the same "connection")
184 * @param message the message, NULL if we only care about
185 * learning about the delay until we should receive again
186 * @return how long the plugin should wait until receiving more data
187 * (plugins that do not support this, can ignore the return value)
188 */
189struct GNUNET_TIME_Relative
190GST_receive_callback (void *cls,
191 const struct GNUNET_HELLO_Address *address,
192 struct GNUNET_ATS_Session *session,
193 const struct GNUNET_MessageHeader *message);
194
195/**
196 * Broadcast the given message to all of our clients.
197 *
198 * @param msg message to broadcast
199 * @param may_drop #GNUNET_YES if the message can be dropped / is payload
200 */
201void
202GST_clients_broadcast (const struct GNUNET_MessageHeader *msg,
203 int may_drop);
204
205
206/**
207 * Broadcast the new active address to all clients monitoring the peer.
208 *
209 * @param peer peer this update is about (never NULL)
210 * @param address address, NULL on disconnect
211 * @param state the current state of the peer
212 * @param state_timeout the time out for the state
213 */
214void
215GST_clients_broadcast_peer_notification (const struct GNUNET_PeerIdentity *peer,
216 const struct
217 GNUNET_HELLO_Address *address,
218 enum GNUNET_TRANSPORT_PeerState state,
219 struct GNUNET_TIME_Absolute
220 state_timeout);
221
222
223/**
224 * Notify all clients about a disconnect, and cancel
225 * pending SEND_OK messages for this peer.
226 *
227 * @param peer peer that disconnected
228 */
229void
230GST_clients_broadcast_disconnect (const struct GNUNET_PeerIdentity *peer);
231
232
233#endif
234/* end of file gnunet-service-transport_plugins.h */
diff --git a/src/transport/gnunet-transport-certificate-creation.in b/src/transport/gnunet-transport-certificate-creation.in
deleted file mode 100644
index 771422a7a..000000000
--- a/src/transport/gnunet-transport-certificate-creation.in
+++ /dev/null
@@ -1,158 +0,0 @@
1#!/bin/sh
2#
3# This shell script will generate an X509 certificate for
4# your gnunet-transport HTTPS
5#
6# The current version partially reuses and recycles
7# code from build.sh by NetBSD (although not entirely
8# used because it needs debugging):
9#
10# Copyright (c) 2001-2011 The NetBSD Foundation, Inc.
11# All rights reserved.
12#
13# This code is derived from software contributed to
14# The NetBSD Foundation by Todd Vierling and Luke Mewburn.
15
16# Redistribution and use in source and binary forms, with or
17# without modification, are permitted provided that the following
18# conditions are met:
19# 1. Redistributions of source code must retain the above
20# copyright notice, this list of conditions and the following
21# disclaimer.
22# 2. Redistributions in binary form must reproduce the above
23# copyright notice, this list of conditions and the following
24# disclaimer in the documentation and/or other materials
25# provided with the distribution.
26
27# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
28# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
29# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31# DISCLAIMED.
32# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR
33# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
35# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38# LIABILITY, OR TORT
39# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
40# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
41# OF SUCH DAMAGE.
42
43progname=${0##*/}
44
45existence() {
46 command -v "$1" >/dev/null 2>&1
47}
48
49setdefaults()
50{
51 verbosity=0
52 runcmd=
53}
54
55statusmsg()
56{
57 ${runcmd} echo " $@"
58}
59
60infomsg()
61{
62 if [ x$verbosity = x1 ]; then
63 statusmsg "INFO: $@"
64 fi
65}
66
67warningmsg()
68{
69 statusmsg "WARNING: $@"
70}
71
72errormsg()
73{
74 statusmsg "ERROR: $@"
75}
76
77linemsg()
78{
79 statusmsg "========================================="
80}
81
82
83usage()
84{
85 if [ -n "$*" ]; then
86 echo ""
87 echo "${progname}: $*"
88 fi
89 cat <<_usage_
90
91Usage: ${progname} [-hv] [-c FILE] [...]
92
93Options:
94 -c FILE Use the configuration file FILE.
95 -h Print this help message.
96 -v Print the version and exit.
97 -V be verbose
98
99_usage_
100 exit 1
101}
102
103
104generate_cert_key()
105{
106 echo ""
107 infomsg "Generating Cert and Key"
108
109 CERTTOOL=""
110 GNUTLS_CA_TEMPLATE=@PKGDATADIRECTORY@/gnunet-gns-proxy-ca.template
111 OPENSSL=0
112 if test -x $(existence gnutls-certtool)
113 #if test -z "`gnutls-certtool --version`" > /dev/null
114 then
115 if test -z "`certtool --version | grep gnutls`" > /dev/null
116 then
117 warningmsg "'gnutls-certtool' or 'certtool' command not found. Trying openssl."
118 # if test -z "`openssl version`" > /dev/null
119 if test -x $(existence openssl)
120 then
121 OPENSSL=1
122 else
123 warningmsg "Install either gnutls certtool or openssl for certificate generation!"
124 statusmsg "Cleaning up."
125 exit 1
126 fi
127 fi
128 CERTTOOL="certtool"
129 else
130 CERTTOOL="gnutls-certtool"
131 fi
132 mkdir -p `dirname $KEYFILE`
133
134 if test 1 -eq $OPENSSL
135 then
136 openssl genrsa -out $KEYFILE 1024
137 openssl req -batch -days 365 -out $CERTFILE -new -x509 -key $KEYFILE
138 else
139 $CERTTOOL --generate-privkey --outfile $KEYFILE 2>/dev/null
140 $CERTTOOL --template $GNUTLS_CA_TEMPLATE --generate-self-signed --load-privkey $KEYFILE --outfile $CERTFILE 2>/dev/null
141 fi
142 }
143
144print_version()
145{
146 GNUNET_ARM_VERSION=`gnunet-arm -v`
147 echo $GNUNET_ARM_VERSION
148}
149
150main()
151{
152 KEYFILE=$1
153 CERTFILE=$2
154 setdefaults
155 generate_cert_key
156}
157
158main "$@"
diff --git a/src/transport/gnunet-transport.c b/src/transport/gnunet-transport.c
deleted file mode 100644
index b5ad43770..000000000
--- a/src/transport/gnunet-transport.c
+++ /dev/null
@@ -1,1437 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2014, 2016, 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file src/transport/gnunet-transport.c
23 * @brief Tool to help configure, measure and control the transport subsystem.
24 * @author Christian Grothoff
25 * @author Nathan Evans
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_resolver_service.h"
30#include "gnunet_protocols.h"
31#include "gnunet_transport_service.h"
32
33/**
34 * Timeout for a name resolution
35 */
36#define RESOLUTION_TIMEOUT \
37 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
38
39/**
40 * Timeout for an operation
41 */
42#define OP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
43
44
45/**
46 * Context to store name resolutions for valiation
47 */
48struct ValidationResolutionContext
49{
50 /**
51 * Next in DLL
52 */
53 struct ValidationResolutionContext *next;
54
55 /**
56 * Previous in DLL
57 */
58 struct ValidationResolutionContext *prev;
59
60 /**
61 * Address to resolve
62 */
63 struct GNUNET_HELLO_Address *addrcp;
64
65 /**
66 * Time of last validation
67 */
68 struct GNUNET_TIME_Absolute last_validation;
69
70 /**
71 * Address is valid until
72 */
73 struct GNUNET_TIME_Absolute valid_until;
74
75 /**
76 * Time of next validation
77 */
78 struct GNUNET_TIME_Absolute next_validation;
79
80 /**
81 * Transport conversion handle
82 */
83 struct GNUNET_TRANSPORT_AddressToStringContext *asc;
84
85 /**
86 * plugin name
87 */
88 char *transport;
89
90 /**
91 * was the entry printed
92 */
93 int printed;
94};
95
96/**
97 * Struct to store information about peers in monitor mode
98 */
99struct MonitoredPeer
100{
101 /**
102 * State of the peer
103 */
104 enum GNUNET_TRANSPORT_PeerState state;
105
106 /**
107 * Timeout
108 */
109 struct GNUNET_TIME_Absolute state_timeout;
110
111 /**
112 * The address to convert
113 */
114 struct GNUNET_HELLO_Address *address;
115};
116
117/**
118 * Context to store name resolutions for valiation
119 */
120struct PeerResolutionContext
121{
122 /**
123 * Next in DLL
124 */
125 struct PeerResolutionContext *next;
126
127 /**
128 * Prev in DLL
129 */
130 struct PeerResolutionContext *prev;
131
132 /**
133 * address to resolve
134 */
135 struct GNUNET_HELLO_Address *addrcp;
136
137 /**
138 * transport conversiion context
139 */
140 struct GNUNET_TRANSPORT_AddressToStringContext *asc;
141
142 /**
143 * peer state
144 */
145 enum GNUNET_TRANSPORT_PeerState state;
146
147 /**
148 * state timeout
149 */
150 struct GNUNET_TIME_Absolute state_timeout;
151
152 /**
153 * transport plugin
154 */
155 char *transport;
156
157 /**
158 * was the entry printed
159 */
160 int printed;
161};
162
163
164/**
165 * Benchmarking block size in KB
166 */
167#define BLOCKSIZE 4
168
169/**
170 * Handle to transport service.
171 */
172static struct GNUNET_TRANSPORT_CoreHandle *handle;
173
174/**
175 * Configuration handle
176 */
177static struct GNUNET_CONFIGURATION_Handle *cfg;
178
179/**
180 * Blacklisting handle
181 */
182struct GNUNET_TRANSPORT_Blacklist *blacklist;
183
184/**
185 * Option -s.
186 */
187static int benchmark_send;
188
189/**
190 * Option -b.
191 */
192static int benchmark_receive;
193
194/**
195 * Option -l.
196 */
197static int benchmark_receive;
198
199/**
200 * Option -i.
201 */
202static int iterate_connections;
203
204/**
205 * Option -a.
206 */
207static int iterate_all;
208
209/**
210 * Option -c.
211 */
212static int monitor_connects;
213
214/**
215 * Option -m.
216 */
217static int monitor_connections;
218
219/**
220 * Option -P.
221 */
222static int monitor_plugins;
223
224/**
225 * Option -D.
226 */
227static int do_disconnect;
228
229/**
230 * Option -n.
231 */
232static int numeric;
233
234/**
235 * Global return value (0 success).
236 */
237static int ret;
238
239/**
240 * Current number of connections in monitor mode
241 */
242static int monitor_connect_counter;
243
244/**
245 * Number of bytes of traffic we received so far.
246 */
247static unsigned long long traffic_received;
248
249/**
250 * Number of bytes of traffic we sent so far.
251 */
252static unsigned long long traffic_sent;
253
254/**
255 * Starting time of transmitting/receiving data.
256 */
257static struct GNUNET_TIME_Absolute start_time;
258
259/**
260 * Map storing information about monitored peers
261 */
262static struct GNUNET_CONTAINER_MultiPeerMap *monitored_peers;
263
264/**
265 * Map storing information about monitored plugins's sessions.
266 */
267static struct GNUNET_CONTAINER_MultiPeerMap *monitored_plugins;
268
269/**
270 * Handle if we are monitoring peers at the transport level.
271 */
272static struct GNUNET_TRANSPORT_PeerMonitoringContext *pic;
273
274/**
275 * Handle if we are monitoring plugin session activity.
276 */
277static struct GNUNET_TRANSPORT_PluginMonitor *pm;
278
279/**
280 * Identity of the peer we transmit to / connect to.
281 * ('-p' command-line option).
282 */
283static struct GNUNET_PeerIdentity pid;
284
285/**
286 * Task for operation timeout
287 */
288static struct GNUNET_SCHEDULER_Task *op_timeout;
289
290/**
291 * Selected level of verbosity.
292 */
293static unsigned int verbosity;
294
295/**
296 * Resolver process handle.
297 */
298struct GNUNET_OS_Process *resolver;
299
300/**
301 * Number of address resolutions pending
302 */
303static unsigned int address_resolutions;
304
305/**
306 * DLL: head of validation resolution entries
307 */
308static struct ValidationResolutionContext *vc_head;
309
310/**
311 * DLL: tail of validation resolution entries
312 */
313static struct ValidationResolutionContext *vc_tail;
314
315/**
316 * DLL: head of resolution entries
317 */
318static struct PeerResolutionContext *rc_head;
319
320/**
321 * DLL: head of resolution entries
322 */
323static struct PeerResolutionContext *rc_tail;
324
325
326/**
327 * Function called to release data stored in the #monitored_peers map.
328 *
329 * @param cls unused
330 * @param key the peer identity
331 * @param value a `struct MonitoredPeer` to release
332 * @return #GNUNET_OK (continue to iterate)
333 */
334static int
335destroy_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
336{
337 struct MonitoredPeer *m = value;
338
339 GNUNET_assert (
340 GNUNET_OK ==
341 GNUNET_CONTAINER_multipeermap_remove (monitored_peers, key, value));
342 GNUNET_free (m->address);
343 GNUNET_free (value);
344 return GNUNET_OK;
345}
346
347
348/**
349 * Task run in monitor mode when the user presses CTRL-C to abort.
350 * Stops monitoring activity.
351 *
352 * @param cls NULL
353 */
354static void
355shutdown_task (void *cls)
356{
357 struct GNUNET_TIME_Relative duration;
358 struct ValidationResolutionContext *cur;
359 struct ValidationResolutionContext *next;
360 struct PeerResolutionContext *rc;
361
362 if (NULL != op_timeout)
363 {
364 GNUNET_SCHEDULER_cancel (op_timeout);
365 op_timeout = NULL;
366 }
367 if (NULL != pic)
368 {
369 GNUNET_TRANSPORT_monitor_peers_cancel (pic);
370 pic = NULL;
371 }
372 if (NULL != pm)
373 {
374 GNUNET_TRANSPORT_monitor_plugins_cancel (pm);
375 pm = NULL;
376 }
377
378 next = vc_head;
379 for (cur = next; NULL != cur; cur = next)
380 {
381 next = cur->next;
382
383 GNUNET_TRANSPORT_address_to_string_cancel (cur->asc);
384 GNUNET_CONTAINER_DLL_remove (vc_head, vc_tail, cur);
385 GNUNET_free (cur->transport);
386 GNUNET_HELLO_address_free (cur->addrcp);
387 GNUNET_free (cur);
388 }
389 while (NULL != (rc = rc_head))
390 {
391 GNUNET_CONTAINER_DLL_remove (rc_head, rc_tail, rc);
392 GNUNET_TRANSPORT_address_to_string_cancel (rc->asc);
393 GNUNET_free (rc->transport);
394 GNUNET_free (rc->addrcp);
395 GNUNET_free (rc);
396 }
397 if (NULL != handle)
398 {
399 GNUNET_TRANSPORT_core_disconnect (handle);
400 handle = NULL;
401 }
402 if (benchmark_send)
403 {
404 duration = GNUNET_TIME_absolute_get_duration (start_time);
405 fprintf (stdout,
406 _ ("Transmitted %llu bytes/s (%llu bytes in %s)\n"),
407 1000LL * 1000LL * traffic_sent / (1 + duration.rel_value_us),
408 traffic_sent,
409 GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES));
410 }
411 if (benchmark_receive)
412 {
413 duration = GNUNET_TIME_absolute_get_duration (start_time);
414 fprintf (stdout,
415 _ ("Received %llu bytes/s (%llu bytes in %s)\n"),
416 1000LL * 1000LL * traffic_received / (1 + duration.rel_value_us),
417 traffic_received,
418 GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES));
419 }
420
421 if (NULL != monitored_peers)
422 {
423 GNUNET_CONTAINER_multipeermap_iterate (monitored_peers, &destroy_it, NULL);
424 GNUNET_CONTAINER_multipeermap_destroy (monitored_peers);
425 monitored_peers = NULL;
426 }
427 if (NULL != monitored_plugins)
428 {
429 GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_size (monitored_plugins));
430 GNUNET_CONTAINER_multipeermap_destroy (monitored_plugins);
431 monitored_plugins = NULL;
432 }
433 if (NULL != blacklist)
434 {
435 GNUNET_TRANSPORT_blacklist_cancel (blacklist);
436 blacklist = NULL;
437 ret = 0;
438 }
439}
440
441
442/**
443 * We are done, shut down.
444 */
445static void
446operation_timeout (void *cls)
447{
448 struct PeerResolutionContext *cur;
449 struct PeerResolutionContext *next;
450
451 op_timeout = NULL;
452 if ((benchmark_send) || (benchmark_receive))
453 {
454 fprintf (stdout, _ ("Failed to connect to `%s'\n"), GNUNET_i2s_full (&pid));
455 GNUNET_SCHEDULER_shutdown ();
456 ret = 1;
457 return;
458 }
459 if (iterate_connections)
460 {
461 next = rc_head;
462 while (NULL != (cur = next))
463 {
464 next = cur->next;
465 fprintf (stdout,
466 _ ("Failed to resolve address for peer `%s'\n"),
467 GNUNET_i2s (&cur->addrcp->peer));
468
469 GNUNET_CONTAINER_DLL_remove (rc_head, rc_tail, cur);
470 GNUNET_TRANSPORT_address_to_string_cancel (cur->asc);
471 GNUNET_free (cur->transport);
472 GNUNET_free (cur->addrcp);
473 GNUNET_free (cur);
474 }
475 fprintf (stdout,
476 "%s",
477 _ ("Failed to list connections, timeout occurred\n"));
478 GNUNET_SCHEDULER_shutdown ();
479 ret = 1;
480 return;
481 }
482}
483
484
485/**
486 * Function called to notify a client about the socket
487 * begin ready to queue more data. Sends another message.
488 *
489 * @param cls closure with the message queue
490 */
491static void
492do_send (void *cls)
493{
494 struct GNUNET_MQ_Handle *mq = cls;
495 struct GNUNET_MessageHeader *m;
496 struct GNUNET_MQ_Envelope *env;
497
498 env = GNUNET_MQ_msg_extra (m, BLOCKSIZE * 1024, GNUNET_MESSAGE_TYPE_DUMMY);
499 memset (&m[1], 52, BLOCKSIZE * 1024 - sizeof(struct GNUNET_MessageHeader));
500 traffic_sent += BLOCKSIZE * 1024;
501 GNUNET_MQ_notify_sent (env, &do_send, mq);
502 if (verbosity > 0)
503 fprintf (stdout,
504 _ ("Transmitting %u bytes\n"),
505 (unsigned int) BLOCKSIZE * 1024);
506 GNUNET_MQ_send (mq, env);
507}
508
509
510/**
511 * Function called to notify transport users that another
512 * peer connected to us.
513 *
514 * @param cls closure
515 * @param peer the peer that connected
516 * @param mq message queue for sending to @a peer
517 */
518static void *
519notify_connect (void *cls,
520 const struct GNUNET_PeerIdentity *peer,
521 struct GNUNET_MQ_Handle *mq)
522{
523 if (0 != memcmp (&pid, peer, sizeof(struct GNUNET_PeerIdentity)))
524 return NULL;
525 ret = 0;
526 if (! benchmark_send)
527 return NULL;
528 if (NULL != op_timeout)
529 {
530 GNUNET_SCHEDULER_cancel (op_timeout);
531 op_timeout = NULL;
532 }
533 if (verbosity > 0)
534 fprintf (
535 stdout,
536 _ (
537 "Successfully connected to `%s', starting to send benchmark data in %u Kb blocks\n"),
538 GNUNET_i2s (peer),
539 BLOCKSIZE);
540 start_time = GNUNET_TIME_absolute_get ();
541 do_send (mq);
542 return mq;
543}
544
545
546/**
547 * Function called to notify transport users that another
548 * peer disconnected from us.
549 *
550 * @param cls closure
551 * @param peer the peer that disconnected
552 * @param internal_cls what we returned from #notify_connect()
553 */
554static void
555notify_disconnect (void *cls,
556 const struct GNUNET_PeerIdentity *peer,
557 void *internal_cls)
558{
559 if (0 != memcmp (&pid, peer, sizeof(struct GNUNET_PeerIdentity)))
560 return;
561 if (NULL == internal_cls)
562 return; /* not about target peer */
563 if (! benchmark_send)
564 return; /* not transmitting */
565 fprintf (stdout,
566 _ ("Disconnected from peer `%s' while benchmarking\n"),
567 GNUNET_i2s (&pid));
568}
569
570
571/**
572 * Function called to notify transport users that another
573 * peer connected to us.
574 *
575 * @param cls closure
576 * @param peer the peer that connected
577 * @param mq for sending messages to @a peer
578 * @return NULL
579 */
580static void *
581monitor_notify_connect (void *cls,
582 const struct GNUNET_PeerIdentity *peer,
583 struct GNUNET_MQ_Handle *mq)
584{
585 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
586 const char *now_str = GNUNET_STRINGS_absolute_time_to_string (now);
587
588 monitor_connect_counter++;
589 fprintf (stdout,
590 _ ("%24s: %-17s %4s (%u connections in total)\n"),
591 now_str,
592 _ ("Connected to"),
593 GNUNET_i2s (peer),
594 monitor_connect_counter);
595 return NULL;
596}
597
598
599/**
600 * Function called to notify transport users that another
601 * peer disconnected from us.
602 *
603 * @param cls closure
604 * @param peer the peer that disconnected
605 * @param internal_cls what we returned from #monitor_notify_connect()
606 */
607static void
608monitor_notify_disconnect (void *cls,
609 const struct GNUNET_PeerIdentity *peer,
610 void *internal_cls)
611{
612 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
613 const char *now_str = GNUNET_STRINGS_absolute_time_to_string (now);
614
615 GNUNET_assert (monitor_connect_counter > 0);
616 monitor_connect_counter--;
617
618 fprintf (stdout,
619 _ ("%24s: %-17s %4s (%u connections in total)\n"),
620 now_str,
621 _ ("Disconnected from"),
622 GNUNET_i2s (peer),
623 monitor_connect_counter);
624}
625
626
627/**
628 * Function called by the transport for each received message.
629 *
630 * @param cls closure
631 * @param message the message
632 * @return #GNUNET_OK
633 */
634static int
635check_dummy (void *cls, const struct GNUNET_MessageHeader *message)
636{
637 return GNUNET_OK; /* all messages are fine */
638}
639
640
641/**
642 * Function called by the transport for each received message.
643 *
644 * @param cls closure
645 * @param message the message
646 */
647static void
648handle_dummy (void *cls, const struct GNUNET_MessageHeader *message)
649{
650 if (! benchmark_receive)
651 return;
652 if (verbosity > 0)
653 fprintf (stdout,
654 _ ("Received %u bytes\n"),
655 (unsigned int) ntohs (message->size));
656 if (0 == traffic_received)
657 start_time = GNUNET_TIME_absolute_get ();
658 traffic_received += ntohs (message->size);
659}
660
661
662/**
663 * Convert address to a printable format.
664 *
665 * @param address the address
666 * @param numeric #GNUNET_YES to convert to numeric format, #GNUNET_NO
667 * to try to use reverse DNS
668 * @param state state the peer is in
669 * @param state_timeout when will the peer's state expire
670 */
671static void
672resolve_peer_address (const struct GNUNET_HELLO_Address *address,
673 int numeric,
674 enum GNUNET_TRANSPORT_PeerState state,
675 struct GNUNET_TIME_Absolute state_timeout);
676
677
678static void
679print_info (const struct GNUNET_PeerIdentity *id,
680 const char *transport,
681 const char *addr,
682 enum GNUNET_TRANSPORT_PeerState state,
683 struct GNUNET_TIME_Absolute state_timeout)
684{
685 if (((GNUNET_YES == iterate_connections) && (GNUNET_YES == iterate_all)) ||
686 (GNUNET_YES == monitor_connections))
687 {
688 fprintf (stdout,
689 _ ("Peer `%s': %s %s in state `%s' until %s\n"),
690 GNUNET_i2s (id),
691 (NULL == transport) ? "<none>" : transport,
692 (NULL == transport) ? "<none>" : addr,
693 GNUNET_TRANSPORT_ps2s (state),
694 GNUNET_STRINGS_absolute_time_to_string (state_timeout));
695 }
696 else if ((GNUNET_YES == iterate_connections) &&
697 (GNUNET_TRANSPORT_is_connected (state)))
698 {
699 /* Only connected peers, skip state */
700 fprintf (stdout,
701 _ ("Peer `%s': %s %s\n"),
702 GNUNET_i2s (id),
703 transport,
704 addr);
705 }
706}
707
708
709/**
710 * Function called with a textual representation of an address. This
711 * function will be called several times with different possible
712 * textual representations, and a last time with @a address being NULL
713 * to signal the end of the iteration. Note that @a address NULL
714 * always is the last call, regardless of the value in @a res.
715 *
716 * @param cls closure
717 * @param address NULL on end of iteration,
718 * otherwise 0-terminated printable UTF-8 string,
719 * in particular an empty string if @a res is #GNUNET_NO
720 * @param res result of the address to string conversion:
721 * if #GNUNET_OK: conversion successful
722 * if #GNUNET_NO: address was invalid (or not supported)
723 * if #GNUNET_SYSERR: communication error (IPC error)
724 */
725static void
726process_peer_string (void *cls, const char *address, int res)
727{
728 struct PeerResolutionContext *rc = cls;
729
730 if (NULL != address)
731 {
732 if (GNUNET_SYSERR == res)
733 {
734 fprintf (
735 stderr,
736 "Failed to convert address for peer `%s' plugin `%s' length %u to string \n",
737 GNUNET_i2s (&rc->addrcp->peer),
738 rc->addrcp->transport_name,
739 (unsigned int) rc->addrcp->address_length);
740 print_info (&rc->addrcp->peer,
741 rc->transport,
742 NULL,
743 rc->state,
744 rc->state_timeout);
745 rc->printed = GNUNET_YES;
746 return;
747 }
748 if (GNUNET_OK == res)
749 {
750 print_info (&rc->addrcp->peer,
751 rc->transport,
752 address,
753 rc->state,
754 rc->state_timeout);
755 rc->printed = GNUNET_YES;
756 return; /* Wait for done call */
757 }
758 /* GNUNET_NO == res: ignore, was simply not supported */
759 return;
760 }
761 /* NULL == address, last call, we are done */
762
763 rc->asc = NULL;
764 GNUNET_assert (address_resolutions > 0);
765 address_resolutions--;
766 if (GNUNET_NO == rc->printed)
767 {
768 if (numeric == GNUNET_NO)
769 {
770 /* Failed to resolve address, try numeric lookup
771 (note: this should not be needed, as transport
772 should fallback to numeric conversion if DNS takes
773 too long) */
774 resolve_peer_address (rc->addrcp,
775 GNUNET_YES,
776 rc->state,
777 rc->state_timeout);
778 }
779 else
780 {
781 print_info (&rc->addrcp->peer,
782 rc->transport,
783 NULL,
784 rc->state,
785 rc->state_timeout);
786 }
787 }
788 GNUNET_free (rc->transport);
789 GNUNET_free (rc->addrcp);
790 GNUNET_CONTAINER_DLL_remove (rc_head, rc_tail, rc);
791 GNUNET_free (rc);
792 if ((0 == address_resolutions) && (iterate_connections))
793 {
794 if (NULL != op_timeout)
795 {
796 GNUNET_SCHEDULER_cancel (op_timeout);
797 op_timeout = NULL;
798 }
799 ret = 0;
800 GNUNET_SCHEDULER_shutdown ();
801 }
802}
803
804
805/**
806 * Convert address to a printable format and print it
807 * together with the given state data.
808 *
809 * @param address the address
810 * @param numeric #GNUNET_YES to convert to numeric format, #GNUNET_NO
811 * to try to use reverse DNS
812 * @param state state the peer is in
813 * @param state_timeout when will the peer's state expire
814 */
815static void
816resolve_peer_address (const struct GNUNET_HELLO_Address *address,
817 int numeric,
818 enum GNUNET_TRANSPORT_PeerState state,
819 struct GNUNET_TIME_Absolute state_timeout)
820{
821 struct PeerResolutionContext *rc;
822
823 rc = GNUNET_new (struct PeerResolutionContext);
824 GNUNET_CONTAINER_DLL_insert (rc_head, rc_tail, rc);
825 address_resolutions++;
826 rc->transport = GNUNET_strdup (address->transport_name);
827 rc->addrcp = GNUNET_HELLO_address_copy (address);
828 rc->printed = GNUNET_NO;
829 rc->state = state;
830 rc->state_timeout = state_timeout;
831 /* Resolve address to string */
832 rc->asc = GNUNET_TRANSPORT_address_to_string (cfg,
833 address,
834 numeric,
835 RESOLUTION_TIMEOUT,
836 &process_peer_string,
837 rc);
838}
839
840
841/**
842 * Function called with information about a peers during a one shot iteration
843 *
844 * @param cls closure
845 * @param peer identity of the peer, NULL for final callback when operation done
846 * @param address binary address used to communicate with this peer,
847 * NULL on disconnect or when done
848 * @param state current state this peer is in
849 * @param state_timeout time out for the current state
850 */
851static void
852process_peer_iteration_cb (void *cls,
853 const struct GNUNET_PeerIdentity *peer,
854 const struct GNUNET_HELLO_Address *address,
855 enum GNUNET_TRANSPORT_PeerState state,
856 struct GNUNET_TIME_Absolute state_timeout)
857{
858 if (NULL == peer)
859 {
860 /* done */
861 pic = NULL;
862 return;
863 }
864
865 if ((GNUNET_NO == iterate_all) &&
866 (GNUNET_NO == GNUNET_TRANSPORT_is_connected (state)))
867 return; /* Display only connected peers */
868
869 if (NULL != op_timeout)
870 GNUNET_SCHEDULER_cancel (op_timeout);
871 op_timeout =
872 GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, NULL);
873
874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
875 "Received address for peer `%s': %s\n",
876 GNUNET_i2s (peer),
877 address ? address->transport_name : "");
878
879 if (NULL != address)
880 resolve_peer_address (address, numeric, state, state_timeout);
881 else
882 print_info (peer, NULL, NULL, state, state_timeout);
883}
884
885
886/**
887 * Context for address resolution by #plugin_monitoring_cb().
888 */
889struct PluginMonitorAddress
890{
891 /**
892 * Ongoing resolution request.
893 */
894 struct GNUNET_TRANSPORT_AddressToStringContext *asc;
895
896 /**
897 * Resolved address as string.
898 */
899 char *str;
900
901 /**
902 * Last event we got and did not yet print because
903 * @e str was NULL (address not yet resolved).
904 */
905 struct GNUNET_TRANSPORT_SessionInfo si;
906};
907
908
909/**
910 * Print information about a plugin monitoring event.
911 *
912 * @param addr out internal context
913 * @param info the monitoring information
914 */
915static void
916print_plugin_event_info (struct PluginMonitorAddress *addr,
917 const struct GNUNET_TRANSPORT_SessionInfo *info)
918{
919 const char *state;
920
921 switch (info->state)
922 {
923 case GNUNET_TRANSPORT_SS_INIT:
924 state = "INIT";
925 break;
926
927 case GNUNET_TRANSPORT_SS_HANDSHAKE:
928 state = "HANDSHAKE";
929 break;
930
931 case GNUNET_TRANSPORT_SS_UP:
932 state = "UP";
933 break;
934
935 case GNUNET_TRANSPORT_SS_UPDATE:
936 state = "UPDATE";
937 break;
938
939 case GNUNET_TRANSPORT_SS_DONE:
940 state = "DONE";
941 break;
942
943 default:
944 state = "UNKNOWN";
945 break;
946 }
947 fprintf (stdout,
948 "%s: state %s timeout in %s @ %s%s\n",
949 GNUNET_i2s (&info->address->peer),
950 state,
951 GNUNET_STRINGS_relative_time_to_string (
952 GNUNET_TIME_absolute_get_remaining (info->session_timeout),
953 GNUNET_YES),
954 addr->str,
955 (info->is_inbound == GNUNET_YES) ? " (INBOUND)" : "");
956 fprintf (stdout,
957 "%s: queue has %3u messages and %6u bytes\n",
958 GNUNET_i2s (&info->address->peer),
959 info->num_msg_pending,
960 info->num_bytes_pending);
961 if (0 !=
962 GNUNET_TIME_absolute_get_remaining (info->receive_delay).rel_value_us)
963 fprintf (stdout,
964 "%s: receiving blocked until %s\n",
965 GNUNET_i2s (&info->address->peer),
966 GNUNET_STRINGS_absolute_time_to_string (info->receive_delay));
967}
968
969
970/**
971 * Function called with a textual representation of an address. This
972 * function will be called several times with different possible
973 * textual representations, and a last time with @a address being NULL
974 * to signal the end of the iteration. Note that @a address NULL
975 * always is the last call, regardless of the value in @a res.
976 *
977 * @param cls closure
978 * @param address NULL on end of iteration,
979 * otherwise 0-terminated printable UTF-8 string,
980 * in particular an empty string if @a res is #GNUNET_NO
981 * @param res result of the address to string conversion:
982 * if #GNUNET_OK: conversion successful
983 * if #GNUNET_NO: address was invalid (or not supported)
984 * if #GNUNET_SYSERR: communication error (IPC error)
985 */
986static void
987address_cb (void *cls, const char *address, int res)
988{
989 struct PluginMonitorAddress *addr = cls;
990
991 if (NULL == address)
992 {
993 addr->asc = NULL;
994 return;
995 }
996 if (NULL != addr->str)
997 return;
998 addr->str = GNUNET_strdup (address);
999 print_plugin_event_info (addr, &addr->si);
1000}
1001
1002
1003/**
1004 * Function called by the plugin with information about the
1005 * current sessions managed by the plugin (for monitoring).
1006 *
1007 * @param cls closure (NULL)
1008 * @param session session handle this information is about,
1009 * NULL to indicate that we are "in sync" (initial
1010 * iteration complete)
1011 * @param session_ctx storage location where the application
1012 * can store data; will point to NULL on #GNUNET_TRANSPORT_SS_INIT,
1013 * and must be reset to NULL on #GNUNET_TRANSPORT_SS_DONE
1014 * @param info information about the state of the session,
1015 * NULL if @a session is also NULL and we are
1016 * merely signalling that the initial iteration is over;
1017 * NULL with @a session being non-NULL if the monitor
1018 * was being cancelled while sessions were active
1019 */
1020static void
1021plugin_monitoring_cb (void *cls,
1022 struct GNUNET_TRANSPORT_PluginSession *session,
1023 void **session_ctx,
1024 const struct GNUNET_TRANSPORT_SessionInfo *info)
1025{
1026 struct PluginMonitorAddress *addr;
1027
1028 if ((NULL == info) && (NULL == session))
1029 return; /* in sync with transport service */
1030 addr = *session_ctx;
1031 if (NULL == info)
1032 {
1033 if (NULL != addr)
1034 {
1035 if (NULL != addr->asc)
1036 {
1037 GNUNET_TRANSPORT_address_to_string_cancel (addr->asc);
1038 addr->asc = NULL;
1039 }
1040 GNUNET_free (addr->str);
1041 GNUNET_free (addr);
1042 *session_ctx = NULL;
1043 }
1044 return; /* shutdown */
1045 }
1046 if (0 !=
1047 memcmp (&info->address->peer, &pid, sizeof(struct GNUNET_PeerIdentity)))
1048 return; /* filtered */
1049 if (NULL == addr)
1050 {
1051 addr = GNUNET_new (struct PluginMonitorAddress);
1052 addr->asc =
1053 GNUNET_TRANSPORT_address_to_string (cfg,
1054 info->address,
1055 numeric,
1056 GNUNET_TIME_UNIT_FOREVER_REL,
1057 &address_cb,
1058 addr);
1059 *session_ctx = addr;
1060 }
1061 if (NULL == addr->str)
1062 addr->si = *info;
1063 else
1064 print_plugin_event_info (addr, info);
1065 if (GNUNET_TRANSPORT_SS_DONE == info->state)
1066 {
1067 if (NULL != addr->asc)
1068 {
1069 GNUNET_TRANSPORT_address_to_string_cancel (addr->asc);
1070 addr->asc = NULL;
1071 }
1072 GNUNET_free (addr->str);
1073 GNUNET_free (addr);
1074 *session_ctx = NULL;
1075 }
1076}
1077
1078
1079/**
1080 * Function called with information about a peers
1081 *
1082 * @param cls closure, NULL
1083 * @param peer identity of the peer, NULL for final callback when operation done
1084 * @param address binary address used to communicate with this peer,
1085 * NULL on disconnect or when done
1086 * @param state current state this peer is in
1087 * @param state_timeout time out for the current state
1088 */
1089static void
1090process_peer_monitoring_cb (void *cls,
1091 const struct GNUNET_PeerIdentity *peer,
1092 const struct GNUNET_HELLO_Address *address,
1093 enum GNUNET_TRANSPORT_PeerState state,
1094 struct GNUNET_TIME_Absolute state_timeout)
1095{
1096 struct MonitoredPeer *m;
1097
1098 if (NULL == peer)
1099 {
1100 fprintf (stdout,
1101 "%s",
1102 _ (
1103 "Monitor disconnected from transport service. Reconnecting.\n"));
1104 return;
1105 }
1106
1107 if (NULL != op_timeout)
1108 GNUNET_SCHEDULER_cancel (op_timeout);
1109 op_timeout =
1110 GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, NULL);
1111
1112 if (NULL == (m = GNUNET_CONTAINER_multipeermap_get (monitored_peers, peer)))
1113 {
1114 m = GNUNET_new (struct MonitoredPeer);
1115 GNUNET_CONTAINER_multipeermap_put (
1116 monitored_peers,
1117 peer,
1118 m,
1119 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1120 }
1121 else
1122 {
1123 if ((m->state == state) &&
1124 (m->state_timeout.abs_value_us == state_timeout.abs_value_us) &&
1125 (NULL == address) && (NULL == m->address))
1126 {
1127 return; /* No real change */
1128 }
1129 if ((m->state == state) && (NULL != address) && (NULL != m->address) &&
1130 (0 == GNUNET_HELLO_address_cmp (m->address, address)))
1131 return; /* No real change */
1132 }
1133
1134 if (NULL != m->address)
1135 {
1136 GNUNET_free (m->address);
1137 m->address = NULL;
1138 }
1139 if (NULL != address)
1140 m->address = GNUNET_HELLO_address_copy (address);
1141 m->state = state;
1142 m->state_timeout = state_timeout;
1143
1144 if (NULL != address)
1145 resolve_peer_address (m->address, numeric, m->state, m->state_timeout);
1146 else
1147 print_info (peer, NULL, NULL, m->state, m->state_timeout);
1148}
1149
1150
1151/**
1152 * Function called with the transport service checking if we
1153 * want to blacklist a peer. Return #GNUNET_SYSERR for the
1154 * peer that we should disconnect from.
1155 *
1156 * @param cls NULL
1157 * @param cpid peer to check blacklisting for
1158 * @return #GNUNET_OK if the connection is allowed, #GNUNET_SYSERR if not
1159 */
1160static int
1161blacklist_cb (void *cls, const struct GNUNET_PeerIdentity *cpid)
1162{
1163 if (0 == memcmp (cpid, &pid, sizeof(struct GNUNET_PeerIdentity)))
1164 return GNUNET_SYSERR;
1165 return GNUNET_OK;
1166}
1167
1168
1169/**
1170 * Main function that will be run by the scheduler.
1171 *
1172 * @param cls closure
1173 * @param args remaining command-line arguments
1174 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1175 * @param mycfg configuration
1176 */
1177static void
1178run (void *cls,
1179 char *const *args,
1180 const char *cfgfile,
1181 const struct GNUNET_CONFIGURATION_Handle *mycfg)
1182{
1183 static struct GNUNET_PeerIdentity zero_pid;
1184 int counter = 0;
1185
1186 ret = 1;
1187
1188 cfg = (struct GNUNET_CONFIGURATION_Handle *) mycfg;
1189
1190 counter = benchmark_send + benchmark_receive + iterate_connections
1191 + monitor_connections + monitor_connects + do_disconnect
1192 + monitor_plugins;
1193
1194 if (1 < counter)
1195 {
1196 fprintf (
1197 stderr,
1198 _ (
1199 "Multiple operations given. Please choose only one operation: %s, %s, %s, %s, %s, %s %s\n"),
1200 "disconnect",
1201 "benchmark send",
1202 "benchmark receive",
1203 "information",
1204 "monitor",
1205 "events",
1206 "plugins");
1207 return;
1208 }
1209 if (0 == counter)
1210 {
1211 fprintf (
1212 stderr,
1213 _ (
1214 "No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s, %s\n"),
1215 "disconnect",
1216 "benchmark send",
1217 "benchmark receive",
1218 "information",
1219 "monitor",
1220 "events",
1221 "plugins");
1222 return;
1223 }
1224
1225 if (do_disconnect) /* -D: Disconnect from peer */
1226 {
1227 if (0 == memcmp (&zero_pid, &pid, sizeof(pid)))
1228 {
1229 fprintf (stderr,
1230 _ ("Option `%s' makes no sense without option `%s'.\n"),
1231 "-D",
1232 "-p");
1233 ret = 1;
1234 return;
1235 }
1236 blacklist = GNUNET_TRANSPORT_blacklist (cfg, &blacklist_cb, NULL);
1237 if (NULL == blacklist)
1238 {
1239 fprintf (stderr,
1240 "%s",
1241 _ (
1242 "Failed to connect to transport service for disconnection\n"));
1243 ret = 1;
1244 return;
1245 }
1246 fprintf (stdout,
1247 "%s",
1248 _ ("Blacklisting request in place, stop with CTRL-C\n"));
1249 }
1250 else if (benchmark_send) /* -s: Benchmark sending */
1251 {
1252 if (0 == memcmp (&zero_pid, &pid, sizeof(pid)))
1253 {
1254 fprintf (stderr,
1255 _ ("Option `%s' makes no sense without option `%s'.\n"),
1256 "-s",
1257 "-p");
1258 ret = 1;
1259 return;
1260 }
1261 handle = GNUNET_TRANSPORT_core_connect (cfg,
1262 NULL,
1263 NULL,
1264 NULL,
1265 &notify_connect,
1266 &notify_disconnect,
1267 NULL);
1268 if (NULL == handle)
1269 {
1270 fprintf (stderr, "%s", _ ("Failed to connect to transport service\n"));
1271 ret = 1;
1272 return;
1273 }
1274 start_time = GNUNET_TIME_absolute_get ();
1275 op_timeout =
1276 GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, NULL);
1277 }
1278 else if (benchmark_receive) /* -b: Benchmark receiving */
1279 {
1280 struct GNUNET_MQ_MessageHandler handlers[] =
1281 { GNUNET_MQ_hd_var_size (dummy,
1282 GNUNET_MESSAGE_TYPE_DUMMY,
1283 struct GNUNET_MessageHeader,
1284 NULL),
1285 GNUNET_MQ_handler_end () };
1286
1287 handle = GNUNET_TRANSPORT_core_connect (cfg,
1288 NULL,
1289 handlers,
1290 NULL,
1291 NULL,
1292 NULL,
1293 NULL);
1294 if (NULL == handle)
1295 {
1296 fprintf (stderr, "%s", _ ("Failed to connect to transport service\n"));
1297 ret = 1;
1298 return;
1299 }
1300 if (verbosity > 0)
1301 fprintf (stdout, "%s", _ ("Starting to receive benchmark data\n"));
1302 start_time = GNUNET_TIME_absolute_get ();
1303 }
1304 else if (iterate_connections) /* -i: List information about peers once */
1305 {
1306 pic = GNUNET_TRANSPORT_monitor_peers (cfg,
1307 &pid,
1308 GNUNET_YES,
1309 &process_peer_iteration_cb,
1310 (void *) cfg);
1311 op_timeout =
1312 GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, NULL);
1313 }
1314 else if (monitor_connections) /* -m: List information about peers continuously
1315 */
1316 {
1317 monitored_peers = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
1318 pic = GNUNET_TRANSPORT_monitor_peers (cfg,
1319 &pid,
1320 GNUNET_NO,
1321 &process_peer_monitoring_cb,
1322 NULL);
1323 }
1324 else if (monitor_plugins) /* -P: List information about plugins continuously
1325 */
1326 {
1327 monitored_plugins = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
1328 pm = GNUNET_TRANSPORT_monitor_plugins (cfg, &plugin_monitoring_cb, NULL);
1329 }
1330 else if (monitor_connects) /* -e : Monitor (dis)connect events continuously */
1331 {
1332 monitor_connect_counter = 0;
1333 handle = GNUNET_TRANSPORT_core_connect (cfg,
1334 NULL,
1335 NULL,
1336 NULL,
1337 &monitor_notify_connect,
1338 &monitor_notify_disconnect,
1339 NULL);
1340 if (NULL == handle)
1341 {
1342 fprintf (stderr, "%s", _ ("Failed to connect to transport service\n"));
1343 ret = 1;
1344 return;
1345 }
1346 ret = 0;
1347 }
1348 else
1349 {
1350 GNUNET_break (0);
1351 return;
1352 }
1353
1354 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1355}
1356
1357
1358int
1359main (int argc, char *const *argv)
1360{
1361 int res;
1362 struct GNUNET_GETOPT_CommandLineOption options[] =
1363 { GNUNET_GETOPT_option_flag (
1364 'a',
1365 "all",
1366 gettext_noop (
1367 "print information for all peers (instead of only connected peers)"),
1368 &iterate_all),
1369 GNUNET_GETOPT_option_flag (
1370 'b',
1371 "benchmark",
1372 gettext_noop (
1373 "measure how fast we are receiving data from all peers (until CTRL-C)"),
1374 &benchmark_receive),
1375 GNUNET_GETOPT_option_flag ('D',
1376 "disconnect",
1377 gettext_noop ("disconnect from a peer"),
1378 &do_disconnect),
1379 GNUNET_GETOPT_option_flag (
1380 'i',
1381 "information",
1382 gettext_noop (
1383 "provide information about all current connections (once)"),
1384 &iterate_connections),
1385 GNUNET_GETOPT_option_flag (
1386 'm',
1387 "monitor",
1388 gettext_noop (
1389 "provide information about all current connections (continuously)"),
1390 &monitor_connections),
1391 GNUNET_GETOPT_option_flag (
1392 'e',
1393 "events",
1394 gettext_noop (
1395 "provide information about all connects and disconnect events (continuously)"),
1396 &monitor_connects),
1397 GNUNET_GETOPT_option_flag ('n',
1398 "numeric",
1399 gettext_noop ("do not resolve hostnames"),
1400 &numeric),
1401 GNUNET_GETOPT_option_base32_auto ('p',
1402 "peer",
1403 "PEER",
1404 gettext_noop ("peer identity"),
1405 &pid),
1406 GNUNET_GETOPT_option_flag ('P',
1407 "plugins",
1408 gettext_noop ("monitor plugin sessions"),
1409 &monitor_plugins),
1410 GNUNET_GETOPT_option_flag (
1411 's',
1412 "send",
1413 gettext_noop (
1414 "send data for benchmarking to the other peer (until CTRL-C)"),
1415 &benchmark_send),
1416 GNUNET_GETOPT_option_verbose (&verbosity),
1417 GNUNET_GETOPT_OPTION_END };
1418
1419 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1420 return 2;
1421
1422 res =
1423 GNUNET_PROGRAM_run (argc,
1424 argv,
1425 "gnunet-transport",
1426 gettext_noop ("Direct access to transport service."),
1427 options,
1428 &run,
1429 NULL);
1430 GNUNET_free_nz ((void *) argv);
1431 if (GNUNET_OK == res)
1432 return ret;
1433 return 1;
1434}
1435
1436
1437/* end of gnunet-transport.c */
diff --git a/src/transport/ieee80211_radiotap.h b/src/transport/ieee80211_radiotap.h
deleted file mode 100644
index 9351da9a5..000000000
--- a/src/transport/ieee80211_radiotap.h
+++ /dev/null
@@ -1,276 +0,0 @@
1/*
2 * Copyright (c) 2003, 2004 David Young. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of David Young may not be used to endorse or promote
13 * products derived from this software without specific prior
14 * written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
20 * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
27 * OF SUCH DAMAGE.
28 */
29
30/*
31 * Modifications to fit into the linux IEEE 802.11 stack,
32 * Mike Kershaw (dragorn@kismetwireless.net)
33 */
34
35#ifndef IEEE80211RADIOTAP_H
36#define IEEE80211RADIOTAP_H
37
38#include <linux/if_ether.h>
39#include <linux/kernel.h>
40// #include <asm/unaligned.h>
41
42/* Base version of the radiotap packet header data */
43#define PKTHDR_RADIOTAP_VERSION 0
44
45/* A generic radio capture format is desirable. There is one for
46 * Linux, but it is neither rigidly defined (there were not even
47 * units given for some fields) nor easily extensible.
48 *
49 * I suggest the following extensible radio capture format. It is
50 * based on a bitmap indicating which fields are present.
51 *
52 * I am trying to describe precisely what the application programmer
53 * should expect in the following, and for that reason I tell the
54 * units and origin of each measurement (where it applies), or else I
55 * use sufficiently weaselly language ("is a monotonically nondecreasing
56 * function of...") that I cannot set false expectations for lawyerly
57 * readers.
58 */
59
60/*
61 * The radio capture header precedes the 802.11 header.
62 * All data in the header is little endian on all platforms.
63 */
64struct ieee80211_radiotap_header
65{
66 u8 it_version; /* Version 0. Only increases
67 * for drastic changes,
68 * introduction of compatible
69 * new fields does not count.
70 */
71 u8 it_pad;
72 __le16 it_len; /* length of the whole
73 * header in bytes, including
74 * it_version, it_pad,
75 * it_len, and data fields.
76 */
77 __le32 it_present; /* A bitmap telling which
78 * fields are present. Set bit 31
79 * (0x80000000) to extend the
80 * bitmap by another 32 bits.
81 * Additional extensions are made
82 * by setting bit 31.
83 */
84} __packed;
85
86/* Name Data type Units
87 * ---- --------- -----
88 *
89 * IEEE80211_RADIOTAP_TSFT __le64 microseconds
90 *
91 * Value in microseconds of the MAC's 64-bit 802.11 Time
92 * Synchronization Function timer when the first bit of the
93 * MPDU arrived at the MAC. For received frames, only.
94 *
95 * IEEE80211_RADIOTAP_CHANNEL 2 x __le16 MHz, bitmap
96 *
97 * Tx/Rx frequency in MHz, followed by flags (see below).
98 *
99 * IEEE80211_RADIOTAP_FHSS __le16 see below
100 *
101 * For frequency-hopping radios, the hop set (first byte)
102 * and pattern (second byte).
103 *
104 * IEEE80211_RADIOTAP_RATE u8 500kb/s
105 *
106 * Tx/Rx data rate
107 *
108 * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from
109 * one milliwatt (dBm)
110 *
111 * RF signal power at the antenna, decibel difference from
112 * one milliwatt.
113 *
114 * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from
115 * one milliwatt (dBm)
116 *
117 * RF noise power at the antenna, decibel difference from one
118 * milliwatt.
119 *
120 * IEEE80211_RADIOTAP_DB_ANTSIGNAL u8 decibel (dB)
121 *
122 * RF signal power at the antenna, decibel difference from an
123 * arbitrary, fixed reference.
124 *
125 * IEEE80211_RADIOTAP_DB_ANTNOISE u8 decibel (dB)
126 *
127 * RF noise power at the antenna, decibel difference from an
128 * arbitrary, fixed reference point.
129 *
130 * IEEE80211_RADIOTAP_LOCK_QUALITY __le16 unitless
131 *
132 * Quality of Barker code lock. Unitless. Monotonically
133 * nondecreasing with "better" lock strength. Called "Signal
134 * Quality" in datasheets. (Is there a standard way to measure
135 * this?)
136 *
137 * IEEE80211_RADIOTAP_TX_ATTENUATION __le16 unitless
138 *
139 * Transmit power expressed as unitless distance from max
140 * power set at factory calibration. 0 is max power.
141 * Monotonically nondecreasing with lower power levels.
142 *
143 * IEEE80211_RADIOTAP_DB_TX_ATTENUATION __le16 decibels (dB)
144 *
145 * Transmit power expressed as decibel distance from max power
146 * set at factory calibration. 0 is max power. Monotonically
147 * nondecreasing with lower power levels.
148 *
149 * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from
150 * one milliwatt (dBm)
151 *
152 * Transmit power expressed as dBm (decibels from a 1 milliwatt
153 * reference). This is the absolute power level measured at
154 * the antenna port.
155 *
156 * IEEE80211_RADIOTAP_FLAGS u8 bitmap
157 *
158 * Properties of transmitted and received frames. See flags
159 * defined below.
160 *
161 * IEEE80211_RADIOTAP_ANTENNA u8 antenna index
162 *
163 * Unitless indication of the Rx/Tx antenna for this packet.
164 * The first antenna is antenna 0.
165 *
166 * IEEE80211_RADIOTAP_RX_FLAGS __le16 bitmap
167 *
168 * Properties of received frames. See flags defined below.
169 *
170 * IEEE80211_RADIOTAP_TX_FLAGS __le16 bitmap
171 *
172 * Properties of transmitted frames. See flags defined below.
173 *
174 * IEEE80211_RADIOTAP_RTS_RETRIES u8 data
175 *
176 * Number of rts retries a transmitted frame used.
177 *
178 * IEEE80211_RADIOTAP_DATA_RETRIES u8 data
179 *
180 * Number of unicast retries a transmitted frame used.
181 *
182 */
183enum ieee80211_radiotap_type
184{
185 IEEE80211_RADIOTAP_TSFT = 0,
186 IEEE80211_RADIOTAP_FLAGS = 1,
187 IEEE80211_RADIOTAP_RATE = 2,
188 IEEE80211_RADIOTAP_CHANNEL = 3,
189 IEEE80211_RADIOTAP_FHSS = 4,
190 IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
191 IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
192 IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
193 IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
194 IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
195 IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
196 IEEE80211_RADIOTAP_ANTENNA = 11,
197 IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
198 IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
199 IEEE80211_RADIOTAP_RX_FLAGS = 14,
200 IEEE80211_RADIOTAP_TX_FLAGS = 15,
201 IEEE80211_RADIOTAP_RTS_RETRIES = 16,
202 IEEE80211_RADIOTAP_DATA_RETRIES = 17,
203
204 /* valid in every it_present bitmap, even vendor namespaces */
205 IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
206 IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
207 IEEE80211_RADIOTAP_EXT = 31
208};
209
210/* Channel flags. */
211#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */
212#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */
213#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */
214#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */
215#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */
216#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */
217#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */
218#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */
219
220/* For IEEE80211_RADIOTAP_FLAGS */
221#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
222 * during CFP
223 */
224#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
225 * with short
226 * preamble
227 */
228#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
229 * with WEP encryption
230 */
231#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
232 * with fragmentation
233 */
234#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
235#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
236 * 802.11 header and payload
237 * (to 32-bit boundary)
238 */
239#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* bad FCS */
240
241/* For IEEE80211_RADIOTAP_RX_FLAGS */
242#define IEEE80211_RADIOTAP_F_RX_BADPLCP 0x0002 /* frame has bad PLCP */
243
244/* For IEEE80211_RADIOTAP_TX_FLAGS */
245#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive
246 * retries */
247#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */
248#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
249
250/* Ugly macro to convert literal channel numbers into their mhz equivalents
251 * There are certainly some conditions that will break this (like feeding it '30')
252 * but they shouldn't arise since nothing talks on channel 30. */
253#define ieee80211chan2mhz(x) \
254 (((x) <= 14) ? \
255 (((x) == 14) ? 2484 : ((x) * 5) + 2407) : \
256 ((x) + 1000) * 5)
257
258/* helpers */
259static inline u16
260get_unaligned_le16 (const u8 *p)
261{
262 return p[0] | p[1] << 8;
263}
264
265
266static inline int
267ieee80211_get_radiotap_len (unsigned char *data)
268{
269 struct ieee80211_radiotap_header *hdr =
270 (struct ieee80211_radiotap_header *) data;
271
272 return get_unaligned_le16 ((const u8 *) &hdr->it_len);
273}
274
275
276#endif /* IEEE80211_RADIOTAP_H */
diff --git a/src/transport/meson.build b/src/transport/meson.build
deleted file mode 100644
index 65a2beeb3..000000000
--- a/src/transport/meson.build
+++ /dev/null
@@ -1,261 +0,0 @@
1libgnunettransportapplication_src = ['transport_api2_application.c']
2libgnunettransportcore_src = ['transport_api2_core.c']
3libgnunettransportcommunicator_src = ['transport_api2_communication.c']
4libgnunettransportmonitor_src = ['transport_api2_monitor.c']
5
6gnunetservicetransport_src = ['gnunet-service-transport.c']
7gnunetcommunicatortcp_src = ['gnunet-communicator-tcp.c']
8gnunetcommunicatorudp_src = ['gnunet-communicator-udp.c']
9gnunetcommunicatorunix_src = ['gnunet-communicator-unix.c']
10
11configure_file(input : 'transport.conf.in',
12 output : 'transport.conf',
13 configuration : cdata,
14 install: true,
15 install_dir: pkgcfgdir)
16
17configure_file(input : 'gnunet-transport-certificate-creation.in',
18 output : 'gnunet-transport-certificate-creation',
19 configuration : cdata,
20 install: true,
21 install_dir: get_option('bindir'))
22
23if get_option('monolith')
24 foreach p : libgnunettransportapplication_src + libgnunettransportcore_src + libgnunettransportcommunicator_src + libgnunettransportmonitor_src + gnunetservicetransport_src
25 gnunet_src += 'transport/' + p
26 endforeach
27 subdir_done()
28endif
29
30libgnunettransportapplication = library('gnunettransportapplication',
31 libgnunettransportapplication_src,
32 soversion: '0',
33 version: '0.0.0',
34 dependencies: libgnunetutil_dep,
35 include_directories: [incdir, configuration_inc],
36 install: true,
37 install_dir: get_option('libdir'))
38pkg.generate(libgnunettransportapplication, url: 'https://www.gnunet.org',
39 description : 'Provides application APIs for accessing the transport service')
40libgnunettransportapplication_dep = declare_dependency(link_with : libgnunettransportapplication)
41
42libgnunettransportcore = library('gnunettransportcore',
43 libgnunettransportcore_src,
44 soversion: '0',
45 version: '0.0.0',
46 dependencies: libgnunetutil_dep,
47 include_directories: [incdir, configuration_inc],
48 install: true,
49 install_dir: get_option('libdir'))
50pkg.generate(libgnunettransportcore, url: 'https://www.gnunet.org',
51 description : 'Provides core API for accessing the transport service')
52libgnunettransportcore_dep = declare_dependency(link_with : libgnunettransportcore)
53
54libgnunettransportcommunicator = library('gnunettransportcommunicator',
55 libgnunettransportcommunicator_src,
56 soversion: '0',
57 version: '0.0.0',
58 dependencies: libgnunetutil_dep,
59 include_directories: [incdir, configuration_inc],
60 install: true,
61 install_dir: get_option('libdir'))
62pkg.generate(libgnunettransportcommunicator, url: 'https://www.gnunet.org',
63 description : 'Provides communicator API for accessing the transport service')
64libgnunettransportcommunicator_dep = declare_dependency(link_with : libgnunettransportcommunicator)
65
66libgnunettransportmonitor = library('gnunettransportmonitor',
67 libgnunettransportmonitor_src,
68 soversion: '0',
69 version: '0.0.0',
70 dependencies: libgnunetutil_dep,
71 include_directories: [incdir, configuration_inc],
72 install: true,
73 install_dir: get_option('libdir'))
74pkg.generate(libgnunettransportmonitor, url: 'https://www.gnunet.org',
75 description : 'Provides monitor API for accessing the transport service')
76libgnunettransportmonitor_dep = declare_dependency(link_with : libgnunettransportmonitor)
77
78libgnunettransporttesting2 = library('gnunettransporttesting2',
79 [
80 'transport_api_traits.c',
81 'transport_api_cmd_connecting_peers.c',
82 'transport_api_cmd_backchannel_check.c',
83 'transport_api_cmd_start_peer.c',
84 'transport_api_cmd_stop_peer.c',
85 'transport_api_cmd_send_simple.c',
86 'transport_api_cmd_send_simple_performance.c',
87 'transport-testing2.c',
88 'transport-testing-filenames2.c',
89 'transport-testing-loggers2.c',
90 'transport-testing-main2.c',
91 'transport-testing-send2.c',
92 'transport-testing-communicator.c',
93 ],
94 soversion: '0',
95 version: '0.0.0',
96 dependencies: [libgnunetutil_dep,
97 libgnunettransportcore_dep,
98 libgnunettransportapplication_dep,
99 libgnunetpeerstore_dep,
100 libgnunettesting_dep,
101 libgnunethello_dep],
102 include_directories: [incdir, configuration_inc],
103 install: true,
104 install_dir: get_option('libdir'))
105libgnunettransporttesting2_dep = declare_dependency(link_with : libgnunettransporttesting2)
106
107executable ('gnunet-service-transport',
108 gnunetservicetransport_src,
109 dependencies: [libgnunettransportcommunicator_dep,
110 libgnunetpeerstore_dep,
111 libgnunetstatistics_dep,
112 libgnunethello_dep,
113 libgnunetnat_dep,
114 gcrypt_dep,
115 libgnunetutil_dep],
116 include_directories: [incdir, configuration_inc],
117 install: true,
118 install_dir: get_option('libdir') / 'gnunet' / 'libexec')
119
120executable ('gnunet-communicator-unix',
121 gnunetcommunicatorunix_src,
122 dependencies: [libgnunettransportcommunicator_dep,
123 libgnunetpeerstore_dep,
124 libgnunetstatistics_dep,
125 libgnunetnat_dep,
126 gcrypt_dep,
127 libgnunetutil_dep],
128 include_directories: [incdir, configuration_inc],
129 install: true,
130 install_dir: get_option('libdir') / 'gnunet' / 'libexec')
131executable ('gnunet-communicator-udp',
132 gnunetcommunicatorudp_src,
133 dependencies: [libgnunettransportcommunicator_dep,
134 libgnunettransportapplication_dep,
135 libgnunetpeerstore_dep,
136 libgnunetstatistics_dep,
137 libgnunetnat_dep,
138 gcrypt_dep,
139 libgnunetutil_dep],
140 include_directories: [incdir, configuration_inc],
141 install: true,
142 install_dir: get_option('libdir') / 'gnunet' / 'libexec')
143executable ('gnunet-communicator-tcp',
144 gnunetcommunicatortcp_src,
145 dependencies: [libgnunettransportcommunicator_dep,
146 libgnunetpeerstore_dep,
147 libgnunetstatistics_dep,
148 libgnunetnat_dep,
149 gcrypt_dep,
150 libgnunetutil_dep],
151 include_directories: [incdir, configuration_inc],
152 install: true,
153 install_dir: get_option('libdir') / 'gnunet' / 'libexec')
154
155libgnunettesttransport_cmd_simplesend = library('gnunet_test_transport_plugin_cmd_simple_send',
156 ['test_transport_plugin_cmd_simple_send.c'],
157 dependencies: [
158 libgnunetutil_dep,
159 libgnunettransportapplication_dep,
160 libgnunettransporttesting2_dep,
161 libgnunettransportcore_dep,
162 libgnunettesting_dep,
163 libgnunetpeerstore_dep,
164 libgnunetstatistics_dep,
165 libgnunethello_dep,
166 libgnunetarm_dep,
167 libgnunetutil_dep
168 ],
169 include_directories: [incdir, configuration_inc],
170 install: true,
171 install_dir: get_option('libdir')/'gnunet')
172
173libgnunettesttransport_cmd_simplesendbc = library('gnunet_test_transport_plugin_cmd_simple_send_broadcast',
174 ['test_transport_plugin_cmd_simple_send_broadcast.c'],
175 dependencies: [
176 libgnunetutil_dep,
177 libgnunettransportapplication_dep,
178 libgnunettransporttesting2_dep,
179 libgnunettransportcore_dep,
180 libgnunettesting_dep,
181 libgnunetpeerstore_dep,
182 libgnunetstatistics_dep,
183 libgnunethello_dep,
184 libgnunetarm_dep,
185 libgnunetutil_dep
186 ],
187 include_directories: [incdir, configuration_inc],
188 install: true,
189 install_dir: get_option('libdir')/'gnunet')
190
191libgnunettesttransport_cmd_simplesenddv = library('gnunet_test_transport_plugin_cmd_simple_send_dv',
192 ['test_transport_plugin_cmd_simple_send_dv.c'],
193 dependencies: [
194 libgnunetutil_dep,
195 libgnunettransportapplication_dep,
196 libgnunettransporttesting2_dep,
197 libgnunettransportcore_dep,
198 libgnunettesting_dep,
199 libgnunetpeerstore_dep,
200 libgnunetstatistics_dep,
201 libgnunethello_dep,
202 libgnunetarm_dep,
203 libgnunetutil_dep
204 ],
205 include_directories: [incdir, configuration_inc],
206 install: true,
207 install_dir: get_option('libdir')/'gnunet')
208
209libgnunettesttransport_cmd_simplesendperf = library('gnunet_test_transport_plugin_cmd_simple_send_performance',
210 ['test_transport_plugin_cmd_simple_send_performance.c'],
211 dependencies: [
212 libgnunetutil_dep,
213 libgnunettransportapplication_dep,
214 libgnunettransporttesting2_dep,
215 libgnunettransportcore_dep,
216 libgnunettesting_dep,
217 libgnunetpeerstore_dep,
218 libgnunetstatistics_dep,
219 libgnunethello_dep,
220 libgnunetarm_dep,
221 libgnunetutil_dep
222 ],
223 include_directories: [incdir, configuration_inc],
224 install: true,
225 install_dir: get_option('libdir')/'gnunet')
226
227libgnunettesttransport_cmd_udpback = library('gnunet_test_transport_plugin_cmd_udp_backchannel',
228 ['test_transport_plugin_cmd_udp_backchannel.c'],
229 dependencies: [
230 libgnunetutil_dep,
231 libgnunettransporttesting2_dep,
232 libgnunettransportapplication_dep,
233 libgnunettransportcore_dep,
234 libgnunettesting_dep,
235 libgnunetpeerstore_dep,
236 libgnunetstatistics_dep,
237 libgnunethello_dep,
238 libgnunetarm_dep,
239 libgnunetutil_dep
240 ],
241 include_directories: [incdir, configuration_inc],
242 install: true,
243 install_dir: get_option('libdir')/'gnunet')
244
245libgnunettesttransport_cmd_natupnp = library('gnunet_test_transport_plugin_cmd_nat_upnp',
246 ['test_transport_plugin_cmd_nat_upnp.c'],
247 dependencies: [
248 libgnunetutil_dep,
249 libgnunettransportapplication_dep,
250 libgnunettransporttesting2_dep,
251 libgnunettransportcore_dep,
252 libgnunettesting_dep,
253 libgnunetpeerstore_dep,
254 libgnunetstatistics_dep,
255 libgnunethello_dep,
256 libgnunetarm_dep,
257 libgnunetutil_dep
258 ],
259 include_directories: [incdir, configuration_inc],
260 install: true,
261 install_dir: get_option('libdir')/'gnunet')
diff --git a/src/transport/template_cfg_peer1.conf b/src/transport/template_cfg_peer1.conf
deleted file mode 100644
index 5ba198450..000000000
--- a/src/transport/template_cfg_peer1.conf
+++ /dev/null
@@ -1,50 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
4GNUNET_RUNTIME_DIR = $GNUNET_TEST_HOME/runtime/
5GNUNET_USER_RUNTIME_DIR = $GNUNET_TEST_HOME/runtime/
6
7[nat]
8RETURN_LOCAL_ADDRESSES = YES
9DISABLEV6 = NO
10
11[transport-tcp]
12PORT = 12000
13TIMEOUT = 5 s
14
15[transport-udp]
16BROADCAST = NO
17
18[transport-unix]
19PORT = 12007
20
21[arm]
22PORT = 12005
23UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
24
25[statistics]
26PORT = 12004
27UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock
28
29[resolver]
30PORT = 12003
31UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock
32
33[peerinfo]
34PORT = 12002
35UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock
36USE_INCLUDED_HELLOS = NO
37
38[transport]
39#PREFIX = valgrind --leak-check=full
40PORT = 12001
41UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock
42
43[ats]
44WAN_QUOTA_IN = unlimited
45WAN_QUOTA_OUT = unlimited
46PORT = 12006
47UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-ats.sock
48
49[hostlist]
50SERVERS = dummy
diff --git a/src/transport/template_cfg_peer2.conf b/src/transport/template_cfg_peer2.conf
deleted file mode 100644
index 6ac610fec..000000000
--- a/src/transport/template_cfg_peer2.conf
+++ /dev/null
@@ -1,58 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
4GNUNET_RUNTIME_DIR = $GNUNET_TEST_HOME/runtime/
5GNUNET_USER_RUNTIME_DIR = $GNUNET_TEST_HOME/runtime/
6
7[nat]
8RETURN_LOCAL_ADDRESSES = YES
9DISABLEV6 = NO
10
11[transport-tcp]
12PORT = 12100
13TIMEOUT = 5 s
14
15[transport-udp]
16BROADCAST = NO
17
18[transport-unix]
19PORT = 12017
20
21[transport-http_server]
22PORT = 12018
23USE_IPv6 = YES
24
25[transport-https_server]
26PORT = 12019
27KEY_FILE = $GNUNET_TEST_HOME/https_key_p1.key
28CERT_FILE = $GNUNET_TEST_HOME/https_cert_p1.crt
29USE_IPv6 = YES
30
31[arm]
32PORT = 12014
33UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock
34
35[statistics]
36PORT = 12013
37UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock
38
39[resolver]
40PORT = 12012
41UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock
42
43[peerinfo]
44PORT = 12011
45UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock
46USE_INCLUDED_HELLOS = NO
47
48[transport]
49#PREFIX = valgrind --leak-check=full
50PORT = 12010
51UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock
52
53[ats]
54PORT = 12016
55UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-ats.sock
56
57[hostlist]
58SERVERS = dummy
diff --git a/src/transport/template_tng_cfg_peer1.conf b/src/transport/template_tng_cfg_peer1.conf
deleted file mode 100644
index b6198d72c..000000000
--- a/src/transport/template_tng_cfg_peer1.conf
+++ /dev/null
@@ -1,34 +0,0 @@
1@INLINE@ test_tng_defaults.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
4GNUNET_RUNTIME_DIR = $GNUNET_TEST_HOME/runtime/
5GNUNET_USER_RUNTIME_DIR = $GNUNET_TEST_HOME/runtime/
6
7[nat]
8RETURN_LOCAL_ADDRESSES = YES
9DISABLEV6 = NO
10
11[arm]
12PORT = 12005
13UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
14
15[statistics]
16PORT = 12004
17UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock
18
19[resolver]
20PORT = 12003
21UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock
22
23[peerinfo]
24PORT = 12002
25UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock
26USE_INCLUDED_HELLOS = NO
27
28[transport]
29#PREFIX = valgrind --leak-check=full
30PORT = 12001
31UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock
32
33[hostlist]
34SERVERS = dummy
diff --git a/src/transport/test_communicator_basic.c b/src/transport/test_communicator_basic.c
deleted file mode 100644
index fdbad0957..000000000
--- a/src/transport/test_communicator_basic.c
+++ /dev/null
@@ -1,1224 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2019 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 transport/test_communicator_basic.c
23* @brief test the communicators
24* @author Julius Bünger
25* @author Martin Schanzenbach
26*/
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "transport-testing-communicator.h"
30#include "gnunet_ats_transport_service.h"
31#include "gnunet_signatures.h"
32#include "gnunet_testing_lib.h"
33#include "transport.h"
34#include "gnunet_statistics_service.h"
35
36#include <inttypes.h>
37
38
39#define LOG(kind, ...) GNUNET_log_from (kind, \
40 "test_transport_communicator", \
41 __VA_ARGS__)
42
43#define NUM_PEERS 2
44
45static struct GNUNET_SCHEDULER_Task *to_task[NUM_PEERS];
46
47static int queue_est = GNUNET_NO;
48
49static struct GNUNET_PeerIdentity peer_id[NUM_PEERS];
50
51static char *communicator_binary;
52
53static struct
54GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_hs[NUM_PEERS];
55
56static struct GNUNET_CONFIGURATION_Handle *cfg_peers[NUM_PEERS];
57
58static struct GNUNET_STATISTICS_Handle *stats[NUM_PEERS];
59
60static char *cfg_peers_name[NUM_PEERS];
61
62static int finished[NUM_PEERS];
63
64static int ret;
65
66static int bidirect = GNUNET_NO;
67
68static size_t long_message_size;
69
70static struct GNUNET_TIME_Absolute start_short[NUM_PEERS];
71
72static struct GNUNET_TIME_Absolute start_long[NUM_PEERS];
73
74static struct GNUNET_TIME_Absolute timeout[NUM_PEERS];
75
76// static struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *my_tc;
77
78static char *communicator_name;
79
80static char *test_name;
81
82static struct GNUNET_STATISTICS_GetHandle *box_stats[NUM_PEERS];
83
84static struct GNUNET_STATISTICS_GetHandle *rekey_stats[NUM_PEERS];
85
86#define TEST_SECTION "test-setup"
87
88#define SHORT_MESSAGE_SIZE 128
89
90#define LONG_MESSAGE_SIZE 32000 /* FIXME */
91
92#define ALLOWED_PACKET_LOSS 91
93
94#define BURST_PACKETS 5000
95
96#define TOTAL_ITERATIONS 1
97
98#define PEER_A 0
99
100#define PEER_B 1
101
102static unsigned int iterations_left[NUM_PEERS];
103
104#define TIMEOUT_MULTIPLIER 1
105
106#define DELAY \
107 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS,200)
108
109#define SHORT_BURST_WINDOW \
110 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,2)
111
112#define LONG_BURST_WINDOW \
113 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,2)
114
115enum TestPhase
116{
117 TP_INIT,
118 TP_BURST_SHORT,
119 TP_BURST_LONG,
120 TP_SIZE_CHECK
121};
122
123static unsigned int phase_short[NUM_PEERS];
124
125static unsigned int phase_long[NUM_PEERS];
126
127static unsigned int phase_size[NUM_PEERS];
128
129static long long unsigned int allowed_packet_loss_short;
130
131static long long unsigned int allowed_packet_loss_long;
132
133static long long unsigned int burst_packets_short;
134
135static long long unsigned int burst_packets_long;
136
137static long long unsigned int delay_long_value;
138
139static long long unsigned int delay_short_value;
140
141static struct GNUNET_TIME_Relative delay_short;
142
143static struct GNUNET_TIME_Relative delay_long;
144
145static size_t num_sent_short[NUM_PEERS];
146
147static size_t num_sent_long[NUM_PEERS];
148
149static size_t num_sent_size[NUM_PEERS];
150
151static uint32_t ack[NUM_PEERS];
152
153static enum TestPhase phase[NUM_PEERS];
154
155static size_t num_received_short[NUM_PEERS];
156
157static size_t num_received_long[NUM_PEERS];
158
159static size_t num_received_size[NUM_PEERS];
160
161static uint64_t avg_latency[NUM_PEERS];
162
163static void
164communicator_available_cb (
165 void *cls,
166 struct
167 GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h,
168 enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc,
169 char *address_prefix)
170{
171 LOG (GNUNET_ERROR_TYPE_INFO,
172 "Communicator available. (cc: %u, prefix: %s)\n",
173 cc,
174 address_prefix);
175}
176
177
178static void
179open_queue (void *cls)
180{
181 const char *address = cls;
182
183 if (NULL != tc_hs[PEER_A]->c_mq)
184 {
185 queue_est = GNUNET_YES;
186 GNUNET_TRANSPORT_TESTING_transport_communicator_open_queue (tc_hs[PEER_A],
187 &peer_id[PEER_B],
188 address);
189 }
190 else
191 {
192 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
193 &open_queue,
194 (void *) address);
195 }
196}
197
198
199static void
200add_address_cb (
201 void *cls,
202 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h,
203 const char *address,
204 struct GNUNET_TIME_Relative expiration,
205 uint32_t aid,
206 enum GNUNET_NetworkType nt)
207{
208 LOG (GNUNET_ERROR_TYPE_DEBUG,
209 "New address. (addr: %s, expir: %s, ID: %" PRIu32 ", nt: %u\n",
210 address,
211 GNUNET_STRINGS_relative_time_to_string (expiration,
212 GNUNET_NO),
213 aid,
214 (int) nt);
215 // addresses[1] = GNUNET_strdup (address);
216 if ((0 == strcmp ((char*) cls, cfg_peers_name[PEER_B])) &&
217 (GNUNET_NO == queue_est))
218 {
219 open_queue ((void *) address);
220 }
221}
222
223
224/**
225 * @brief Callback that informs whether the requested queue will be
226 * established
227 *
228 * Implements #GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback.
229 *
230 * @param cls Closure - unused
231 * @param tc_h Communicator handle - unused
232 * @param will_try #GNUNET_YES if queue will be established
233 * #GNUNET_NO if queue will not be established (bogous address)
234 */
235static void
236queue_create_reply_cb (
237 void *cls,
238 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h,
239 int will_try)
240{
241 (void) cls;
242 (void) tc_h;
243 if (GNUNET_YES == will_try)
244 LOG (GNUNET_ERROR_TYPE_DEBUG,
245 "Queue will be established!\n");
246 else
247 LOG (GNUNET_ERROR_TYPE_WARNING,
248 "Queue won't be established (bougus address?)!\n");
249}
250
251
252static struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *
253handle_backchannel_cb (void *cls,
254 struct GNUNET_MessageHeader *msg,
255 struct GNUNET_PeerIdentity *pid)
256{
257 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
258
259 (void) tc_h;
260 (void) msg;
261 LOG (GNUNET_ERROR_TYPE_DEBUG, "Handling BC message...\n");
262 if (0 == memcmp (&peer_id[PEER_A], pid, sizeof (*pid)))
263 return tc_hs[PEER_A];
264 else
265 return tc_hs[PEER_B];
266}
267
268
269static char*
270make_payload (size_t payload_size)
271{
272 struct GNUNET_TIME_Absolute ts;
273 struct GNUNET_TIME_AbsoluteNBO ts_n;
274 char *payload = GNUNET_malloc (payload_size);
275
276 LOG (GNUNET_ERROR_TYPE_DEBUG,
277 "Making payload of size %lu\n", payload_size);
278 GNUNET_assert (payload_size >= 8); // So that out timestamp fits
279 ts = GNUNET_TIME_absolute_get ();
280 ts_n = GNUNET_TIME_absolute_hton (ts);
281 memset (payload, 'a', payload_size);
282 memcpy (payload, &ts_n, sizeof (struct GNUNET_TIME_AbsoluteNBO));
283 return payload;
284}
285
286
287static struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *
288get_tc_h (unsigned int peer_nr)
289{
290 LOG (GNUNET_ERROR_TYPE_DEBUG,
291 "Got peer %u\n",
292 peer_nr);
293
294 LOG (GNUNET_ERROR_TYPE_DEBUG,
295 "Handle %p peer 0\n",
296 tc_hs[0]);
297
298 LOG (GNUNET_ERROR_TYPE_DEBUG,
299 "Handle %p peer 1\n",
300 tc_hs[1]);
301
302 LOG (GNUNET_ERROR_TYPE_DEBUG,
303 "Handle %p get\n",
304 tc_hs[peer_nr]);
305
306 return tc_hs[peer_nr];
307}
308
309
310static unsigned int
311get_peer_nr_from_tc (struct
312 GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
313{
314 if (tc_h == get_tc_h (0))
315 return PEER_A;
316 else
317 return PEER_B;
318}
319
320
321static unsigned int
322get_peer_nr (void *cls, unsigned int get_the_other_one)
323{
324 if (0 == strcmp ((char*) cls, cfg_peers_name[0]))
325 return get_the_other_one ? PEER_B : PEER_A;
326 else
327 return get_the_other_one ? PEER_A : PEER_B;
328}
329
330
331static void
332process_statistics_box_done (void *cls, int success)
333{
334 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
335 unsigned int peer_nr;
336
337 peer_nr = get_peer_nr_from_tc (tc_h);
338
339 if (NULL != box_stats[peer_nr])
340 box_stats[peer_nr] = NULL;
341 if (NULL == rekey_stats[peer_nr])
342 {
343 LOG (GNUNET_ERROR_TYPE_DEBUG,
344 "Finished\n");
345 GNUNET_SCHEDULER_shutdown ();
346 }
347}
348
349
350static void
351process_statistics_rekey_done (void *cls, int success)
352{
353 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
354 unsigned int peer_nr;
355
356 peer_nr = get_peer_nr_from_tc (tc_h);
357
358 if (NULL != rekey_stats[peer_nr])
359 rekey_stats[peer_nr] = NULL;
360 if (NULL == box_stats[peer_nr])
361 {
362 LOG (GNUNET_ERROR_TYPE_DEBUG,
363 "Finished\n");
364 GNUNET_SCHEDULER_shutdown ();
365 }
366}
367
368
369static int
370process_statistics (void *cls,
371 const char *subsystem,
372 const char *name,
373 uint64_t value,
374 int is_persistent)
375{
376 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
377 "Statistic: Name %s and value %lu\n",
378 name,
379 value);
380 if ((0 == strcmp ("rekey", test_name)) && (0 == strcmp (
381 "# rekeying successful",
382 name)) && (0 == value))
383 {
384 ret = 2;
385 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
386 "No successful rekeying!\n");
387 GNUNET_SCHEDULER_shutdown ();
388 }
389 if ((0 == strcmp ("backchannel", test_name)) &&
390 (0 == strcmp (
391 "# messages decrypted with BOX",
392 name))
393 && (9000 > value))
394 {
395 ret = 2;
396 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
397 "Not enough BOX messages! (want: %u, have %llu)\n",
398 9000, value);
399 GNUNET_SCHEDULER_shutdown ();
400 }
401 if ((0 == strcmp ("rekey", test_name)) &&
402 (0 == strcmp (
403 "# messages decrypted with BOX",
404 name))
405 && (6000 > value))
406 {
407 ret = 2;
408 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
409 "Not enough BOX messages! (want: %u, have %llu)\n",
410 6000, value);
411 GNUNET_SCHEDULER_shutdown ();
412 }
413 return GNUNET_OK;
414}
415
416
417static void
418short_test (void *cls);
419
420static void
421short_test_cb (void *cls)
422{
423 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
424 unsigned int peer_nr;
425 char *payload;
426
427 peer_nr = get_peer_nr_from_tc (tc_h);
428
429 LOG (GNUNET_ERROR_TYPE_DEBUG,
430 "short_test_cb %u/%u for peer %u and handle %p\n",
431 (unsigned int) num_sent_short[peer_nr],
432 (unsigned int) num_received_short[peer_nr],
433 peer_nr,
434 tc_h);
435 payload = make_payload (SHORT_MESSAGE_SIZE);
436 num_sent_short[peer_nr]++;
437 if (burst_packets_short == num_sent_short[peer_nr])
438 tc_h->cont = NULL;
439 else
440 tc_h->cont = short_test;
441 tc_h->cont_cls = cls;
442 GNUNET_TRANSPORT_TESTING_transport_communicator_send (tc_h,
443 NULL,
444 cls,
445 payload,
446 SHORT_MESSAGE_SIZE);
447 GNUNET_free (payload);
448 timeout[peer_nr] = GNUNET_TIME_relative_to_absolute (
449 GNUNET_TIME_relative_multiply (
450 GNUNET_TIME_UNIT_SECONDS,
451 TIMEOUT_MULTIPLIER));
452}
453
454
455static void
456short_test (void *cls)
457{
458 GNUNET_SCHEDULER_add_delayed (delay_short,
459 &short_test_cb,
460 cls);
461}
462
463
464static void
465size_test (void *cls)
466{
467 unsigned int peer_nr;
468 char *payload;
469 size_t max_size = 64000;
470 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
471
472 peer_nr = get_peer_nr_from_tc (tc_h);
473 LOG (GNUNET_ERROR_TYPE_DEBUG,
474 "size_test_cb %u\n",
475 (unsigned int) num_sent_size[peer_nr]);
476 GNUNET_assert (TP_SIZE_CHECK == phase[peer_nr]);
477 if (LONG_MESSAGE_SIZE != long_message_size)
478 max_size = long_message_size;
479 if (ack[peer_nr] + 10 > max_size)
480 return; /* Leave some room for our protocol, so not 2^16 exactly */
481 ack[peer_nr] += 10;
482 payload = make_payload (ack[peer_nr]);
483 num_sent_size[peer_nr]++;
484 if (ack[peer_nr] >= max_size)
485 tc_h->cont = NULL;
486 else
487 tc_h->cont = size_test;
488 tc_h->cont_cls = cls;
489 GNUNET_TRANSPORT_TESTING_transport_communicator_send (tc_h,
490 NULL,
491 cls,
492 payload,
493 ack[peer_nr]);
494 GNUNET_free (payload);
495 timeout[peer_nr] = GNUNET_TIME_relative_to_absolute (
496 GNUNET_TIME_relative_multiply (
497 GNUNET_TIME_UNIT_SECONDS,
498 TIMEOUT_MULTIPLIER));
499}
500
501
502static void
503long_test (void *cls);
504
505static void
506long_test_cb (void *cls)
507{
508 unsigned int peer_nr;
509 char *payload;
510 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
511
512 peer_nr = get_peer_nr_from_tc (tc_h);
513
514 LOG (GNUNET_ERROR_TYPE_DEBUG,
515 "long_test_cb %u/%u\n",
516 (unsigned int) num_sent_long[peer_nr],
517 (unsigned int) num_received_long[peer_nr]);
518 payload = make_payload (long_message_size);
519 num_sent_long[peer_nr]++;
520 if (burst_packets_long == num_sent_long[peer_nr])
521 tc_h->cont = NULL;
522 else
523 tc_h->cont = long_test;
524 tc_h->cont_cls = cls;
525 GNUNET_TRANSPORT_TESTING_transport_communicator_send (tc_h,
526 NULL,
527 cls,
528 payload,
529 long_message_size);
530 GNUNET_free (payload);
531 timeout[peer_nr] = GNUNET_TIME_relative_to_absolute (
532 GNUNET_TIME_relative_multiply (
533 GNUNET_TIME_UNIT_SECONDS,
534 TIMEOUT_MULTIPLIER));
535}
536
537
538static void
539long_test (void *cls)
540{
541 GNUNET_SCHEDULER_add_delayed (delay_long,
542 &long_test_cb,
543 cls);
544}
545
546
547static void
548choose_phase (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
549{
550 unsigned int peer_nr;
551
552 peer_nr = get_peer_nr_from_tc (tc_h);
553
554 if (GNUNET_YES == phase_short[peer_nr])
555 {
556 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
557 "Choose phase short with peer %u and Handle %p\n",
558 peer_nr,
559 tc_h);
560 phase[peer_nr] = TP_BURST_SHORT;
561 start_short[peer_nr] = GNUNET_TIME_absolute_get ();
562 short_test (tc_h);
563 }
564 else if (GNUNET_YES == phase_long[peer_nr])
565 {
566 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
567 "Choose phase long with peer %u\n",
568 peer_nr);
569 phase[peer_nr] = TP_BURST_LONG;
570 start_long[peer_nr] = GNUNET_TIME_absolute_get ();
571 long_test (tc_h);
572 }
573 else if (GNUNET_YES == phase_size[peer_nr])
574 {
575 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
576 "Choose phase size\n");
577 phase[peer_nr] = TP_SIZE_CHECK;
578 size_test (tc_h);
579 }
580 else
581 {
582 if ((0 == strcmp ("udp", communicator_name)) && ((0 == strcmp ("rekey",
583 test_name))
584 || (0 == strcmp (
585 "backchannel",
586 test_name))) )
587 {
588 if (NULL != box_stats[peer_nr])
589 GNUNET_STATISTICS_get_cancel (box_stats[peer_nr]);
590 box_stats[peer_nr] = GNUNET_STATISTICS_get (stats[1],
591 "C-UDP",
592 "# messages decrypted with BOX",
593 process_statistics_box_done,
594 &process_statistics,
595 tc_h);
596 if (NULL != rekey_stats[peer_nr])
597 GNUNET_STATISTICS_get_cancel (rekey_stats[peer_nr]);
598 rekey_stats[peer_nr] = GNUNET_STATISTICS_get (stats[0],
599 "C-UDP",
600 "# rekeying successful",
601 process_statistics_rekey_done,
602 &process_statistics,
603 tc_h);
604 }
605 else
606 {
607 if ((GNUNET_NO == bidirect) || (((PEER_A == peer_nr) &&
608 finished[PEER_B]) || ((PEER_B ==
609 peer_nr) &&
610 finished
611 [PEER_A])))
612 {
613 LOG (GNUNET_ERROR_TYPE_DEBUG,
614 "Finished\n");
615 GNUNET_SCHEDULER_shutdown ();
616 }
617 finished[peer_nr] = GNUNET_YES;
618 }
619 }
620}
621
622
623static void
624finish_phase_long (unsigned int peer_nr)
625{
626 static struct GNUNET_TIME_Relative duration;
627
628 duration = GNUNET_TIME_absolute_get_duration (start_long[peer_nr]);
629 LOG (GNUNET_ERROR_TYPE_MESSAGE,
630 "Long size packet test for peer %u done.\n",
631 peer_nr);
632 char *goodput = GNUNET_STRINGS_byte_size_fancy (
633 (long_message_size * num_received_long[peer_nr] * 1000 * 1000)
634 / duration.
635 rel_value_us);
636
637 LOG (GNUNET_ERROR_TYPE_MESSAGE,
638 "%lu/%lu packets in %llu us (%s/s) -- avg latency: %llu us\n",
639 (unsigned long) num_received_long[peer_nr],
640 (unsigned long) num_sent_long[peer_nr],
641 (unsigned long long) duration.rel_value_us,
642 goodput,
643 (unsigned long long) avg_latency[peer_nr]);
644 GNUNET_free (goodput);
645 ack[peer_nr] = 0;
646 // phase = TP_SIZE_CHECK;
647 // num_received = 0;
648 // num_sent_long = 0;
649 avg_latency[peer_nr] = 0;
650 // size_test (NULL);
651 phase_long[peer_nr] = GNUNET_NO;
652 choose_phase (get_tc_h (peer_nr));
653}
654
655
656static void
657finish_phase_short (unsigned int peer_nr)
658{
659 static struct GNUNET_TIME_Relative duration;
660
661 duration = GNUNET_TIME_absolute_get_duration (start_short[peer_nr]);
662 LOG (GNUNET_ERROR_TYPE_MESSAGE,
663 "Short size packet test for peer %u done.\n",
664 peer_nr);
665 char *goodput = GNUNET_STRINGS_byte_size_fancy (
666 (SHORT_MESSAGE_SIZE * num_received_short[peer_nr] * 1000 * 1000)
667 / duration.rel_value_us);
668 LOG (GNUNET_ERROR_TYPE_MESSAGE,
669 "%lu/%lu packets in %llu us (%s/s) -- avg latency: %llu us\n",
670 (unsigned long) num_received_short[peer_nr],
671 (unsigned long) num_sent_short[peer_nr],
672 (unsigned long long) duration.rel_value_us,
673 goodput,
674 (unsigned long long) avg_latency[peer_nr]);
675 GNUNET_free (goodput);
676 // start_long = GNUNET_TIME_absolute_get ();
677 // phase = TP_BURST_LONG;
678 // num_sent_short = 0;
679 avg_latency[peer_nr] = 0;
680 // num_received = 0;
681 phase_short[peer_nr] = GNUNET_NO;
682 choose_phase (get_tc_h (peer_nr));
683 // long_test (NULL);
684}
685
686
687static void
688latency_timeout (void *cls)
689{
690
691 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
692 unsigned int peer_nr;
693 size_t num_sent = 0;
694 size_t num_received = 0;
695
696 peer_nr = get_peer_nr_from_tc (tc_h);
697 to_task[peer_nr] = NULL;
698
699 switch (phase[peer_nr])
700 {
701 case TP_INIT:
702 GNUNET_assert (0);
703 break;
704 case TP_BURST_SHORT:
705 num_sent = num_sent_short[peer_nr];
706 num_received = num_received_short[peer_nr];
707 if ((num_sent_short[peer_nr] == burst_packets_short) &&
708 (num_received_short[peer_nr] >
709 burst_packets_short
710 / 100
711 *
712 allowed_packet_loss_short) )
713 {
714 finish_phase_short (peer_nr);
715 to_task[peer_nr] = GNUNET_SCHEDULER_add_at (timeout[peer_nr],
716 &latency_timeout,
717 cls);
718 return;
719 }
720 break;
721 case TP_BURST_LONG:
722 num_sent = num_sent_long[peer_nr];
723 num_received = num_received_long[peer_nr];
724 if ((num_sent_long[peer_nr] == burst_packets_long) &&
725 (num_received_long[peer_nr] >
726 burst_packets_long
727 / 100
728 *
729 allowed_packet_loss_long) )
730 {
731 finish_phase_long (peer_nr);
732 to_task[peer_nr] = GNUNET_SCHEDULER_add_at (timeout[peer_nr],
733 &latency_timeout,
734 cls);
735 return;
736 }
737 break;
738 case TP_SIZE_CHECK:
739 num_sent = num_sent_size[peer_nr];
740 num_received = num_received_size[peer_nr];
741 break;
742 }
743 if (GNUNET_TIME_absolute_get_remaining (timeout[peer_nr]).rel_value_us > 0)
744 {
745 to_task[peer_nr] = GNUNET_SCHEDULER_add_at (timeout[peer_nr],
746 &latency_timeout,
747 cls);
748 return;
749 }
750 LOG (GNUNET_ERROR_TYPE_ERROR,
751 "Latency too high. Test failed. (Phase: %d. Sent: %lu, Received: %lu)\n",
752 phase[peer_nr], num_sent, num_received);
753 ret = 2;
754 GNUNET_SCHEDULER_shutdown ();
755}
756
757
758/**
759 * @brief Handle opening of queue
760 *
761 * Issues sending of test data
762 *
763 * Implements #GNUNET_TRANSPORT_TESTING_AddQueueCallback
764 *
765 * @param cls Closure
766 * @param tc_h Communicator handle
767 * @param tc_queue Handle to newly opened queue
768 */
769static void
770add_queue_cb (void *cls,
771 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h,
772 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *
773 tc_queue,
774 size_t mtu)
775{
776
777 unsigned int peer_nr;
778
779 peer_nr = get_peer_nr (cls, GNUNET_NO);
780 LOG (GNUNET_ERROR_TYPE_DEBUG,
781 "Handle %p add %u %u\n",
782 tc_h,
783 peer_nr,
784 get_peer_nr_from_tc (tc_h));
785 if ((GNUNET_NO == bidirect) && (0 != strcmp ((char*) cls, cfg_peers_name[0])))
786 {
787 LOG (GNUNET_ERROR_TYPE_DEBUG,
788 "Queue available at receiving peer\n");
789 return; // TODO?
790 }
791 else if (TP_INIT != phase[peer_nr])
792 return;
793 LOG (GNUNET_ERROR_TYPE_DEBUG,
794 "Queue established, starting test...\n");
795 if (UINT16_MAX != mtu) /* Message header overhead */
796 long_message_size = mtu - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
797 - sizeof(struct GNUNET_MessageHeader);
798 else
799 long_message_size = LONG_MESSAGE_SIZE;
800 timeout[peer_nr] = GNUNET_TIME_relative_to_absolute (
801 GNUNET_TIME_relative_multiply (
802 GNUNET_TIME_UNIT_SECONDS,
803 TIMEOUT_MULTIPLIER));
804 GNUNET_assert (NULL == to_task[peer_nr]);
805 to_task[peer_nr] = GNUNET_SCHEDULER_add_delayed (
806 GNUNET_TIME_relative_multiply (
807 GNUNET_TIME_UNIT_SECONDS,
808 TIMEOUT_MULTIPLIER),
809 &latency_timeout,
810 tc_h);
811 choose_phase (tc_h);
812}
813
814
815static void
816update_avg_latency (const char *payload, unsigned int peer_nr)
817{
818 struct GNUNET_TIME_AbsoluteNBO *ts_n;
819 struct GNUNET_TIME_Absolute ts;
820 struct GNUNET_TIME_Relative latency;
821 size_t num_received = 0;
822
823 ts_n = (struct GNUNET_TIME_AbsoluteNBO *) payload;
824 ts = GNUNET_TIME_absolute_ntoh (*ts_n);
825 latency = GNUNET_TIME_absolute_get_duration (ts);
826
827 switch (phase[peer_nr])
828 {
829 case TP_INIT:
830 GNUNET_assert (0);
831 break;
832 case TP_BURST_SHORT:
833 num_received = num_received_short[peer_nr];
834 break;
835 case TP_BURST_LONG:
836 num_received = num_received_long[peer_nr];
837 break;
838 case TP_SIZE_CHECK:
839 num_received = num_received_size[peer_nr];
840 break;
841 }
842 if (1 >= num_received)
843 avg_latency[peer_nr] = latency.rel_value_us;
844 else
845 avg_latency[peer_nr] = ((avg_latency[peer_nr] * (num_received - 1))
846 + latency.rel_value_us)
847 / num_received;
848 LOG (GNUNET_ERROR_TYPE_DEBUG,
849 "Latency of received packet by peer %u: %s with avg latency %lu\n",
850 peer_nr,
851 GNUNET_STRINGS_relative_time_to_string (latency,
852 GNUNET_YES),
853 avg_latency[peer_nr]);
854}
855
856
857static void
858load_phase_config ()
859{
860
861 phase_short[0] = GNUNET_CONFIGURATION_get_value_yesno (cfg_peers[0],
862 TEST_SECTION,
863 "PHASE_SHORT");
864 if (GNUNET_SYSERR == phase_short[0])
865 phase_short[0] = GNUNET_YES;
866
867 phase_short[1] = phase_short[0];
868
869 phase_long[0] = GNUNET_CONFIGURATION_get_value_yesno (cfg_peers[0],
870 TEST_SECTION,
871 "PHASE_LONG");
872
873 if (GNUNET_SYSERR == phase_long[0])
874 phase_long[0] = GNUNET_YES;
875
876 phase_long[1] = phase_long[0];
877
878 phase_size[0] = GNUNET_CONFIGURATION_get_value_yesno (cfg_peers[0],
879 TEST_SECTION,
880 "PHASE_SIZE");
881
882 if (GNUNET_SYSERR == phase_size[0])
883 phase_size[0] = GNUNET_YES;
884
885 phase_size[1] = phase_size[0];
886}
887
888
889/**
890 * @brief Handle an incoming message
891 *
892 * Implements #GNUNET_TRANSPORT_TESTING_IncomingMessageCallback
893
894 * @param cls Closure
895 * @param tc_h Handle to the receiving communicator
896 * @param msg Received message
897 */
898static void
899incoming_message_cb (
900 void *cls,
901 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h,
902 const char *payload,
903 size_t payload_len)
904{
905 unsigned int peer_nr;
906
907
908 peer_nr = get_peer_nr (cls, GNUNET_YES);
909
910 if ((GNUNET_NO == bidirect) && (0 != strcmp ((char*) cls,
911 cfg_peers_name[NUM_PEERS - 1])))
912 {
913 LOG (GNUNET_ERROR_TYPE_WARNING,
914 "unexpected receiver...\n");
915 return;
916 }
917 /* Reset timeout */
918 timeout[peer_nr] = GNUNET_TIME_relative_to_absolute (
919 GNUNET_TIME_relative_multiply (
920 GNUNET_TIME_UNIT_SECONDS,
921 TIMEOUT_MULTIPLIER));
922 switch (phase[peer_nr])
923 {
924 case TP_INIT:
925 GNUNET_break (0);
926 break;
927 case TP_BURST_SHORT:
928 {
929 GNUNET_assert (SHORT_MESSAGE_SIZE == payload_len);
930 num_received_short[peer_nr]++;
931
932 update_avg_latency (payload, peer_nr);
933 if ((num_sent_short[peer_nr] == burst_packets_short) &&
934 (num_received_short[peer_nr] ==
935 burst_packets_short))
936 {
937 finish_phase_short (peer_nr);
938 }
939 break;
940 }
941 case TP_BURST_LONG:
942 {
943 if (long_message_size != payload_len)
944 {
945 LOG (GNUNET_ERROR_TYPE_WARNING,
946 "Ignoring packet with wrong length (have: %lu, want: %lu)\n",
947 payload_len, long_message_size);
948 return; // Ignore
949 }
950 num_received_long[peer_nr]++;
951
952 update_avg_latency (payload, peer_nr);
953 if ((num_sent_long[peer_nr] == burst_packets_long) &&
954 (num_received_long[peer_nr] >
955 burst_packets_long))
956 {
957 finish_phase_long (peer_nr);
958 }
959 break;
960 }
961 case TP_SIZE_CHECK:
962 {
963 size_t max_size = 64000;
964
965 GNUNET_assert (TP_SIZE_CHECK == phase[peer_nr]);
966 if (LONG_MESSAGE_SIZE != long_message_size)
967 max_size = long_message_size;
968 num_received_size[peer_nr]++;
969 update_avg_latency (payload, peer_nr);
970 if ((GNUNET_YES == phase_size[peer_nr]) && (num_received_size[peer_nr] >=
971 (max_size) / 10) )
972 {
973 LOG (GNUNET_ERROR_TYPE_MESSAGE,
974 "Size packet test for peer %u done.\n",
975 peer_nr);
976 LOG (GNUNET_ERROR_TYPE_MESSAGE,
977 "%lu/%lu packets -- avg latency: %llu us\n",
978 (unsigned long) num_received_size[peer_nr],
979 (unsigned long) num_sent_size[peer_nr],
980 (unsigned long long) avg_latency[peer_nr]);
981 iterations_left[peer_nr]--;
982 phase_size[peer_nr] = GNUNET_NO;
983 if (0 != iterations_left[peer_nr])
984 {
985 // start_short = GNUNET_TIME_absolute_get ();
986 // phase = TP_BURST_SHORT;
987 num_received_size[peer_nr] = 0;
988 num_sent_size[peer_nr] = 0;
989 avg_latency[peer_nr] = 0;
990 num_sent_short[peer_nr] = 0;
991 num_sent_long[peer_nr] = 0;
992 num_received_short[peer_nr] = 0;
993 num_received_long[peer_nr] = 0;
994 // short_test (NULL);
995 if (((PEER_A == peer_nr) && finished[PEER_B]) || ((PEER_B ==
996 peer_nr) &&
997 finished[PEER_A]))
998 {
999 load_phase_config ();
1000 }
1001 }
1002 choose_phase (get_tc_h (peer_nr));
1003 }
1004 break;
1005 }
1006 }
1007}
1008
1009
1010static void
1011do_shutdown (void *cls)
1012{
1013 LOG (GNUNET_ERROR_TYPE_DEBUG,
1014 "shutting down test.\n");
1015
1016 for (unsigned int i = 0; i < NUM_PEERS; i++)
1017 {
1018 if (NULL != box_stats[i])
1019 {
1020 GNUNET_STATISTICS_get_cancel (box_stats[i]);
1021 box_stats[i] = NULL;
1022 }
1023 if (NULL != rekey_stats[i])
1024 {
1025 GNUNET_STATISTICS_get_cancel (rekey_stats[i]);
1026 rekey_stats[i] = NULL;
1027 }
1028 if (NULL != to_task[i])
1029 {
1030 GNUNET_SCHEDULER_cancel (to_task[i]);
1031 to_task[i] = NULL;
1032 }
1033 GNUNET_TRANSPORT_TESTING_transport_communicator_service_stop (tc_hs[i]);
1034 GNUNET_STATISTICS_destroy (stats[i], GNUNET_NO);
1035 }
1036}
1037
1038
1039/**
1040 * @brief Main function called by the scheduler
1041 *
1042 * @param cls Closure - Handle to confiation
1043 */
1044static void
1045run (void *cls)
1046{
1047 ret = 0;
1048 // num_received = 0;
1049 // num_sent = 0;
1050 for (unsigned int i = 0; i < NUM_PEERS; i++)
1051 {
1052 tc_hs[i] = GNUNET_TRANSPORT_TESTING_transport_communicator_service_start (
1053 "transport",
1054 communicator_binary,
1055 cfg_peers_name[i],
1056 &peer_id[i],
1057 &communicator_available_cb,
1058 &add_address_cb,
1059 &queue_create_reply_cb,
1060 &add_queue_cb,
1061 &incoming_message_cb,
1062 &handle_backchannel_cb,
1063 cfg_peers_name[i]); /* cls */
1064
1065 if ((0 == strcmp ("udp", communicator_name)) && ((0 == strcmp ("rekey",
1066 test_name))
1067 ||
1068 (0 == strcmp (
1069 "backchannel",
1070 test_name))) )
1071 {
1072 stats[i] = GNUNET_STATISTICS_create ("C-UDP",
1073 cfg_peers[i]);
1074 }
1075 else if ((0 == strcmp ("bidirect", test_name)))
1076 {
1077 bidirect = GNUNET_YES;
1078 }
1079 }
1080 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1081 NULL);
1082}
1083
1084
1085int
1086main (int argc,
1087 char *const *argv)
1088{
1089 struct GNUNET_CRYPTO_EddsaPrivateKey *private_key;
1090 char *test_mode;
1091 char *cfg_peer;
1092
1093 iterations_left[0] = TOTAL_ITERATIONS;
1094 iterations_left[1] = TOTAL_ITERATIONS;
1095 phase[0] = TP_INIT;
1096 phase[1] = TP_INIT;
1097 ret = 1;
1098 test_name = GNUNET_STRINGS_get_suffix_from_binary_name (argv[0]);
1099 communicator_name = strchr (test_name, '-');
1100 communicator_name[0] = '\0';
1101 communicator_name++;
1102 test_mode = test_name;
1103
1104 GNUNET_asprintf (&communicator_binary,
1105 "gnunet-communicator-%s",
1106 communicator_name);
1107
1108 if (GNUNET_OK !=
1109 GNUNET_log_setup ("test_communicator_basic",
1110 "DEBUG",
1111 NULL))
1112 {
1113 fprintf (stderr, "Unable to setup log\n");
1114 GNUNET_break (0);
1115 return 2;
1116 }
1117 for (unsigned int i = 0; i < NUM_PEERS; i++)
1118 {
1119 GNUNET_asprintf ((&cfg_peer),
1120 "test_communicator_%s_%s_peer%u.conf",
1121 communicator_name, test_mode, i + 1);
1122 cfg_peers_name[i] = cfg_peer;
1123 cfg_peers[i] = GNUNET_CONFIGURATION_create ();
1124 if (GNUNET_YES ==
1125 GNUNET_DISK_file_test (cfg_peers_name[i]))
1126 {
1127 if (GNUNET_SYSERR ==
1128 GNUNET_CONFIGURATION_load (cfg_peers[i],
1129 cfg_peers_name[i]))
1130 {
1131 fprintf (stderr,
1132 "Malformed configuration file `%s', exiting ...\n",
1133 cfg_peers_name[i]);
1134 return 1;
1135 }
1136 }
1137 else
1138 {
1139 if (GNUNET_SYSERR ==
1140 GNUNET_CONFIGURATION_load (cfg_peers[i],
1141 NULL))
1142 {
1143 fprintf (stderr,
1144 "Configuration file %s does not exist, exiting ...\n",
1145 cfg_peers_name[i]);
1146 return 1;
1147 }
1148 }
1149 private_key =
1150 GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg_peers[i]);
1151 if (NULL == private_key)
1152 {
1153 LOG (GNUNET_ERROR_TYPE_ERROR,
1154 "Unable to get peer ID\n");
1155 return 1;
1156 }
1157 GNUNET_CRYPTO_eddsa_key_get_public (private_key,
1158 &peer_id[i].public_key);
1159 GNUNET_free (private_key);
1160 LOG (GNUNET_ERROR_TYPE_INFO,
1161 "Identity of peer %u is %s\n",
1162 i,
1163 GNUNET_i2s_full (&peer_id[i]));
1164 }
1165 if (GNUNET_OK !=
1166 GNUNET_CONFIGURATION_get_value_number (cfg_peers[0],
1167 TEST_SECTION,
1168 "ALLOWED_PACKET_LOSS_SHORT",
1169 &allowed_packet_loss_short))
1170 allowed_packet_loss_short = ALLOWED_PACKET_LOSS;
1171 if (GNUNET_OK !=
1172 GNUNET_CONFIGURATION_get_value_number (cfg_peers[0],
1173 TEST_SECTION,
1174 "ALLOWED_PACKET_LOSS_LONG",
1175 &allowed_packet_loss_long))
1176 allowed_packet_loss_long = ALLOWED_PACKET_LOSS;
1177 if (GNUNET_OK !=
1178 GNUNET_CONFIGURATION_get_value_number (cfg_peers[0],
1179 TEST_SECTION,
1180 "BURST_PACKETS_SHORT",
1181 &burst_packets_short))
1182 burst_packets_short = BURST_PACKETS;
1183 if (GNUNET_OK !=
1184 GNUNET_CONFIGURATION_get_value_number (cfg_peers[0],
1185 TEST_SECTION,
1186 "BURST_PACKETS_LONG",
1187 &burst_packets_long))
1188 burst_packets_long = BURST_PACKETS;
1189 if (GNUNET_OK !=
1190 GNUNET_CONFIGURATION_get_value_number (cfg_peers[0],
1191 TEST_SECTION,
1192 "DELAY_SHORT",
1193 &delay_short_value))
1194 delay_short = DELAY;
1195 else
1196 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS,
1197 delay_short_value);
1198 if (GNUNET_OK !=
1199 GNUNET_CONFIGURATION_get_value_number (cfg_peers[0],
1200 TEST_SECTION,
1201 "DELAY_SHORT",
1202 &delay_long_value))
1203 delay_long = DELAY;
1204 else
1205 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS,
1206 delay_long_value);
1207 load_phase_config ();
1208 LOG (GNUNET_ERROR_TYPE_MESSAGE, "Starting test...\n");
1209 LOG (GNUNET_ERROR_TYPE_DEBUG,
1210 "argv[0]: %s\n",
1211 argv[0]);
1212 LOG (GNUNET_ERROR_TYPE_DEBUG,
1213 "test_name: %s\n",
1214 test_name);
1215 LOG (GNUNET_ERROR_TYPE_DEBUG,
1216 "communicator_name: %s\n",
1217 communicator_name);
1218 LOG (GNUNET_ERROR_TYPE_DEBUG,
1219 "communicator_binary: %s\n",
1220 communicator_binary);
1221 GNUNET_SCHEDULER_run (&run,
1222 NULL);
1223 return ret;
1224}
diff --git a/src/transport/test_communicator_quic_basic_peer1.conf b/src/transport/test_communicator_quic_basic_peer1.conf
deleted file mode 100644
index d43752ecc..000000000
--- a/src/transport/test_communicator_quic_basic_peer1.conf
+++ /dev/null
@@ -1,45 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-communicator-unix-1/
5
6[PEER]
7PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-1/private.key
8
9[transport-tcp]
10PORT = 52400
11
12[transport-udp]
13PORT = 52401
14
15[transport-quic]
16PORT = 52402
17
18[transport]
19#PORT = 60000
20UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_1.sock
21
22[nat]
23UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/nat.sock
24ENABLE_IPSCAN = YES
25
26[peerstore]
27UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/peerstore.sock
28
29[statistics]
30PORT = 22461
31UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_1.sock
32
33[resolver]
34PORT = 62089
35UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_1.sock
36
37[communicator-udp]
38# PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/vg_com1
39BINDTO = 60002
40DISABLE_V6 = YES
41MAX_QUEUE_LENGTH=5000
42
43[communicator-quic]
44BINDTO = 60002
45DISABLE_V6 = YES
diff --git a/src/transport/test_communicator_quic_basic_peer2.conf b/src/transport/test_communicator_quic_basic_peer2.conf
deleted file mode 100644
index 4fabc8a86..000000000
--- a/src/transport/test_communicator_quic_basic_peer2.conf
+++ /dev/null
@@ -1,45 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunetd-plugin-transport/
5
6[PEER]
7PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-2/private.key
8
9[transport-tcp]
10PORT = 52400
11
12[transport-udp]
13PORT = 52402
14
15[transport-quic]
16PORT = 52403
17
18[transport]
19#PORT = 60001
20UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_2.sock
21
22[nat]
23UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/nat.sock
24
25
26[peerstore]
27UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/peerstore.sock
28
29[statistics]
30PORT = 22462
31UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_2.sock
32
33[resolver]
34PORT = 62090
35UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_2.sock
36
37[communicator-udp]
38# PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/vg_com2
39BINDTO = 60003
40DISABLE_V6 = YES
41MAX_QUEUE_LENGTH=5000
42
43[communicator-quic]
44BINDTO = 60003
45DISABLE_V6 = YES \ No newline at end of file
diff --git a/src/transport/test_communicator_tcp_basic_peer1.conf b/src/transport/test_communicator_tcp_basic_peer1.conf
deleted file mode 100644
index dbc227ac6..000000000
--- a/src/transport/test_communicator_tcp_basic_peer1.conf
+++ /dev/null
@@ -1,48 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[test-setup]
4#PHASE_LONG=NO
5#PHASE_SIZE=NO
6#BURST_PACKETS_SHORT=1
7
8[PATHS]
9GNUNET_TEST_HOME = $GNUNET_TMP/test-communicator-unix-1/
10
11[PEER]
12PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-1/private.key
13
14[transport-tcp]
15PORT = 52400
16
17[transport-udp]
18PORT = 52401
19
20[transport]
21PORT = 60000
22UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_1.sock
23
24[nat]
25UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/nat.sock
26
27[peerstore]
28UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/peerstore.sock
29
30[statistics]
31PORT = 22461
32UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_1.sock
33
34[communicator-unix]
35UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_1.sock
36
37[communicator-tcp]
38#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
39#PREFIX = valgrind --leak-check=full --track-origins=yes
40BINDTO = 60002
41DISABLE_V6 = YES
42
43[communicator-udp]
44BINDTO = 60002
45
46[resolver]
47PORT = 62089
48UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_1.sock
diff --git a/src/transport/test_communicator_tcp_basic_peer2.conf b/src/transport/test_communicator_tcp_basic_peer2.conf
deleted file mode 100644
index b73157f0d..000000000
--- a/src/transport/test_communicator_tcp_basic_peer2.conf
+++ /dev/null
@@ -1,44 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunetd-plugin-transport/
5
6[PEER]
7PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-2/private.key
8
9
10[transport-tcp]
11PORT = 52400
12
13[transport-udp]
14PORT = 52401
15
16[transport]
17PORT = 60001
18UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_2.sock
19
20[nat]
21UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/nat.sock
22
23[peerstore]
24UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/peerstore.sock
25
26[statistics]
27PORT = 22462
28UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_2.sock
29
30[communicator-unix]
31UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_2.sock
32
33[communicator-tcp]
34#PREFIX = xterm -geometry 100x85 -T peer2 -e gdb --args
35#PREFIX = valgrind --leak-check=full --track-origins=yes
36BINDTO = 60003
37DISABLE_V6 = YES
38
39[communicator-udp]
40BINDTO = 60003
41
42[resolver]
43PORT = 62090
44UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_2.sock
diff --git a/src/transport/test_communicator_tcp_bidirect_peer1.conf b/src/transport/test_communicator_tcp_bidirect_peer1.conf
deleted file mode 100644
index dbc227ac6..000000000
--- a/src/transport/test_communicator_tcp_bidirect_peer1.conf
+++ /dev/null
@@ -1,48 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[test-setup]
4#PHASE_LONG=NO
5#PHASE_SIZE=NO
6#BURST_PACKETS_SHORT=1
7
8[PATHS]
9GNUNET_TEST_HOME = $GNUNET_TMP/test-communicator-unix-1/
10
11[PEER]
12PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-1/private.key
13
14[transport-tcp]
15PORT = 52400
16
17[transport-udp]
18PORT = 52401
19
20[transport]
21PORT = 60000
22UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_1.sock
23
24[nat]
25UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/nat.sock
26
27[peerstore]
28UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/peerstore.sock
29
30[statistics]
31PORT = 22461
32UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_1.sock
33
34[communicator-unix]
35UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_1.sock
36
37[communicator-tcp]
38#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
39#PREFIX = valgrind --leak-check=full --track-origins=yes
40BINDTO = 60002
41DISABLE_V6 = YES
42
43[communicator-udp]
44BINDTO = 60002
45
46[resolver]
47PORT = 62089
48UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_1.sock
diff --git a/src/transport/test_communicator_tcp_bidirect_peer2.conf b/src/transport/test_communicator_tcp_bidirect_peer2.conf
deleted file mode 100644
index b73157f0d..000000000
--- a/src/transport/test_communicator_tcp_bidirect_peer2.conf
+++ /dev/null
@@ -1,44 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunetd-plugin-transport/
5
6[PEER]
7PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-2/private.key
8
9
10[transport-tcp]
11PORT = 52400
12
13[transport-udp]
14PORT = 52401
15
16[transport]
17PORT = 60001
18UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_2.sock
19
20[nat]
21UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/nat.sock
22
23[peerstore]
24UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/peerstore.sock
25
26[statistics]
27PORT = 22462
28UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_2.sock
29
30[communicator-unix]
31UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_2.sock
32
33[communicator-tcp]
34#PREFIX = xterm -geometry 100x85 -T peer2 -e gdb --args
35#PREFIX = valgrind --leak-check=full --track-origins=yes
36BINDTO = 60003
37DISABLE_V6 = YES
38
39[communicator-udp]
40BINDTO = 60003
41
42[resolver]
43PORT = 62090
44UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_2.sock
diff --git a/src/transport/test_communicator_tcp_rekey_peer1.conf b/src/transport/test_communicator_tcp_rekey_peer1.conf
deleted file mode 100644
index 82fbf353a..000000000
--- a/src/transport/test_communicator_tcp_rekey_peer1.conf
+++ /dev/null
@@ -1,45 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-communicator-unix-1/
5
6[PEER]
7PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-1/private.key
8
9[transport-tcp]
10PORT = 52400
11
12[transport-udp]
13PORT = 52401
14
15[transport]
16PORT = 60000
17UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_1.sock
18
19[nat]
20UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/nat.sock
21ENABLE_IPSCAN = YES
22
23[peerstore]
24UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/peerstore.sock
25
26[statistics]
27PORT = 22461
28UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_1.sock
29
30[resolver]
31PORT = 62089
32UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_1.sock
33
34[communicator-unix]
35UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_1.sock
36
37[communicator-tcp]
38#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
39#PREFIX = valgrind --leak-check=full --track-origins=yes
40BINDTO = 60002
41DISABLE_V6 = YES
42REKEY_INTERVAL = 100ms
43
44[communicator-udp]
45BINDTO = 60002
diff --git a/src/transport/test_communicator_tcp_rekey_peer2.conf b/src/transport/test_communicator_tcp_rekey_peer2.conf
deleted file mode 100644
index 086a996ae..000000000
--- a/src/transport/test_communicator_tcp_rekey_peer2.conf
+++ /dev/null
@@ -1,45 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunetd-plugin-transport/
5
6[PEER]
7PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-2/private.key
8
9
10[transport-tcp]
11PORT = 52400
12
13[transport-udp]
14PORT = 52401
15
16[transport]
17PORT = 60001
18UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_2.sock
19
20[nat]
21UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/nat.sock
22
23[peerstore]
24UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/peerstore.sock
25
26[statistics]
27PORT = 22462
28UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_2.sock
29
30[resolver]
31PORT = 62090
32UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_2.sock
33
34[communicator-unix]
35UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_2.sock
36
37[communicator-tcp]
38#PREFIX = xterm -geometry 100x85 -T peer2 -e gdb --args
39#PREFIX = valgrind --leak-check=full --track-origins=yes
40BINDTO = 60003
41DISABLE_V6 = YES
42REKEY_INTERVAL = 100ms
43
44[communicator-udp]
45BINDTO = 60003
diff --git a/src/transport/test_communicator_udp_backchannel_peer1.conf b/src/transport/test_communicator_udp_backchannel_peer1.conf
deleted file mode 100644
index 65f33bd6b..000000000
--- a/src/transport/test_communicator_udp_backchannel_peer1.conf
+++ /dev/null
@@ -1,48 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-communicator-unix-1/
5
6[PEER]
7PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-1/private.key
8
9[transport-tcp]
10PORT = 52400
11
12[transport-udp]
13PORT = 52401
14
15[transport]
16PORT = 60000
17UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_1.sock
18
19[nat]
20UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/nat.sock
21ENABLE_IPSCAN = YES
22
23[peerstore]
24UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/peerstore.sock
25
26[statistics]
27PORT = 22461
28UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_1.sock
29
30[resolver]
31PORT = 62089
32UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_1.sock
33
34[communicator-unix]
35UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_1.sock
36
37[communicator-tcp]
38BINDTO = 60002
39DISABLE_V6 = YES
40
41[communicator-udp]
42# PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/vg_comm1
43BINDTO = 60002
44DISABLE_V6 = YES
45MAX_QUEUE_LENGTH=5000
46
47[communicator-test]
48BACKCHANNEL_ENABLED = YES
diff --git a/src/transport/test_communicator_udp_backchannel_peer2.conf b/src/transport/test_communicator_udp_backchannel_peer2.conf
deleted file mode 100644
index 9875af724..000000000
--- a/src/transport/test_communicator_udp_backchannel_peer2.conf
+++ /dev/null
@@ -1,48 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunetd-plugin-transport/
5
6[PEER]
7PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-2/private.key
8
9
10[transport-tcp]
11PORT = 52400
12
13[transport-udp]
14PORT = 52401
15
16[transport]
17PORT = 60001
18UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_2.sock
19
20[nat]
21UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/nat.sock
22
23[peerstore]
24UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/peerstore.sock
25
26[statistics]
27PORT = 22462
28UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_2.sock
29
30[resolver]
31PORT = 62090
32UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_2.sock
33
34[communicator-unix]
35UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_2.sock
36
37[communicator-tcp]
38BINDTO = 60003
39DISABLE_V6 = YES
40
41[communicator-udp]
42# PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/vg_comm2
43BINDTO = 60003
44DISABLE_V6 = YES
45MAX_QUEUE_LENGTH=5000
46
47[communicator-test]
48BACKCHANNEL_ENABLED = YES
diff --git a/src/transport/test_communicator_udp_basic_peer1.conf b/src/transport/test_communicator_udp_basic_peer1.conf
deleted file mode 100644
index 6968b3aef..000000000
--- a/src/transport/test_communicator_udp_basic_peer1.conf
+++ /dev/null
@@ -1,39 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-communicator-unix-1/
5
6[PEER]
7PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-1/private.key
8
9[transport-tcp]
10PORT = 52400
11
12[transport-udp]
13PORT = 52401
14
15[transport]
16#PORT = 60000
17UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_1.sock
18
19[nat]
20UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/nat.sock
21ENABLE_IPSCAN = YES
22
23[peerstore]
24UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/peerstore.sock
25
26[statistics]
27PORT = 22461
28UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_1.sock
29
30[resolver]
31PORT = 62089
32UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_1.sock
33
34[communicator-udp]
35# PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/vg_com1
36BINDTO = 60002
37DISABLE_V6 = YES
38MAX_QUEUE_LENGTH=5000
39
diff --git a/src/transport/test_communicator_udp_basic_peer2.conf b/src/transport/test_communicator_udp_basic_peer2.conf
deleted file mode 100644
index 781bfa7da..000000000
--- a/src/transport/test_communicator_udp_basic_peer2.conf
+++ /dev/null
@@ -1,39 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunetd-plugin-transport/
5
6[PEER]
7PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-2/private.key
8
9
10[transport-tcp]
11PORT = 52400
12
13[transport-udp]
14PORT = 52402
15
16[transport]
17#PORT = 60001
18UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_2.sock
19
20[nat]
21UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/nat.sock
22
23
24[peerstore]
25UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/peerstore.sock
26
27[statistics]
28PORT = 22462
29UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_2.sock
30
31[resolver]
32PORT = 62090
33UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_2.sock
34
35[communicator-udp]
36# PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/vg_com2
37BINDTO = 60003
38DISABLE_V6 = YES
39MAX_QUEUE_LENGTH=5000
diff --git a/src/transport/test_communicator_udp_rekey_peer1.conf b/src/transport/test_communicator_udp_rekey_peer1.conf
deleted file mode 100644
index 9b0fa7497..000000000
--- a/src/transport/test_communicator_udp_rekey_peer1.conf
+++ /dev/null
@@ -1,52 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-communicator-unix-1/
5
6[PEER]
7PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-1/private.key
8
9[transport-tcp]
10PORT = 52400
11
12[transport-udp]
13PORT = 52401
14
15[transport]
16PORT = 60000
17UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_1.sock
18
19[nat]
20UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/nat.sock
21ENABLE_IPSCAN = YES
22
23[peerstore]
24UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/peerstore.sock
25
26[statistics]
27PORT = 22461
28UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_1.sock
29
30[resolver]
31PORT = 62089
32UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_1.sock
33
34[communicator-unix]
35UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_1.sock
36
37[communicator-tcp]
38BINDTO = 60002
39DISABLE_V6 = YES
40REKEY_INTERVAL = 100ms
41
42[communicator-udp]
43#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
44#PREFIX = valgrind --leak-check=full --track-origins=yes
45BINDTO = 60002
46DISABLE_V6 = YES
47MAX_QUEUE_LENGTH=5000
48REKEY_INTERVAL = 100ms
49REKEY_MAX_BYTES=9KiB
50
51[communicator-test]
52BACKCHANNEL_ENABLED = YES
diff --git a/src/transport/test_communicator_udp_rekey_peer2.conf b/src/transport/test_communicator_udp_rekey_peer2.conf
deleted file mode 100644
index 383ab19d2..000000000
--- a/src/transport/test_communicator_udp_rekey_peer2.conf
+++ /dev/null
@@ -1,52 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunetd-plugin-transport/
5
6[PEER]
7PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-2/private.key
8
9
10[transport-tcp]
11PORT = 52400
12
13[transport-udp]
14PORT = 52401
15
16[transport]
17PORT = 60001
18UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_2.sock
19
20[nat]
21UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/nat.sock
22
23[peerstore]
24UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/peerstore.sock
25
26[statistics]
27PORT = 22462
28UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_2.sock
29
30[resolver]
31PORT = 62090
32UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_2.sock
33
34[communicator-unix]
35UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_2.sock
36
37[communicator-tcp]
38BINDTO = 60003
39DISABLE_V6 = YES
40REKEY_INTERVAL = 100ms
41
42[communicator-udp]
43#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
44#PREFIX = valgrind --leak-check=full --track-origins=yes
45BINDTO = 60003
46DISABLE_V6 = YES
47MAX_QUEUE_LENGTH=5000
48REKEY_INTERVAL = 100ms
49REKEY_MAX_BYTES=9KiB
50
51[communicator-test]
52BACKCHANNEL_ENABLED = YES
diff --git a/src/transport/test_communicator_unix_basic_peer1.conf b/src/transport/test_communicator_unix_basic_peer1.conf
deleted file mode 100644
index 13ba2d16b..000000000
--- a/src/transport/test_communicator_unix_basic_peer1.conf
+++ /dev/null
@@ -1,43 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-communicator-unix-1/
5
6[PEER]
7PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-1/private.key
8
9[transport-tcp]
10PORT = 52400
11
12[transport-udp]
13PORT = 52401
14
15[transport]
16PORT = 60000
17UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_1.sock
18
19[nat]
20UNIXPATH = $GNUNET_TMP/communicator-unix-1/nat.sock
21ENABLE_IPSCAN = YES
22
23[peerstore]
24UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/peerstore.sock
25
26[statistics]
27PORT = 22461
28UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_1.sock
29
30[resolver]
31PORT = 62089
32UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_1.sock
33
34[communicator-unix]
35#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
36#PREFIX = valgrind --leak-check=full --track-origins=yes
37UNIXPATH = $GNUNET_RUNTIME_DIR/communicator-unix-1.sock
38
39[communicator-tcp]
40BINDTO = 60002
41
42[communicator-udp]
43BINDTO = 60002
diff --git a/src/transport/test_communicator_unix_basic_peer2.conf b/src/transport/test_communicator_unix_basic_peer2.conf
deleted file mode 100644
index 727e844a7..000000000
--- a/src/transport/test_communicator_unix_basic_peer2.conf
+++ /dev/null
@@ -1,43 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunetd-plugin-transport/
5
6[PEER]
7PRIVATE_KEY = $GNUNET_TMP/test-communicator-unix-2/private.key
8
9
10[transport-tcp]
11PORT = 52400
12
13[transport-udp]
14PORT = 52401
15
16[transport]
17PORT = 60001
18UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_2.sock
19
20[nat]
21UNIXPATH = $GNUNET_TMP/communicator-unix-2/nat.sock
22
23[peerstore]
24UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/peerstore.sock
25
26[statistics]
27PORT = 22462
28UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics_test_2.sock
29
30[resolver]
31PORT = 62090
32UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_2.sock
33
34[communicator-unix]
35#PREFIX = xterm -geometry 100x85 -T peer2 -e gdb --args
36#PREFIX = valgrind --leak-check=full --track-origins=yes
37UNIXPATH = $GNUNET_RUNTIME_DIR/communicator-unix-2.sock
38
39[communicator-tcp]
40BINDTO = 60003
41
42[communicator-udp]
43BINDTO = 60003
diff --git a/src/transport/test_delay b/src/transport/test_delay
deleted file mode 100755
index 5f82b65fb..000000000
--- a/src/transport/test_delay
+++ /dev/null
@@ -1,19 +0,0 @@
1#!/bin/sh
2
3TEMP=$(getopt t: "$*")
4
5if [ $? != 0 ] ; then
6 exit 1
7fi
8
9eval set -- "$TEMP"
10
11while true ; do
12 case "$1" in
13 (-t) sleep "$2" ; shift 2 ;;
14 (--) shift ; break ;;
15 (*) echo "Error parsing getopt output" ; exit 1 ;;
16 esac
17done
18echo "exec $@"
19exec "$@"
diff --git a/src/transport/test_plugin_hostkey b/src/transport/test_plugin_hostkey
deleted file mode 100644
index e7b1ad012..000000000
--- a/src/transport/test_plugin_hostkey
+++ /dev/null
Binary files differ
diff --git a/src/transport/test_plugin_hostkey.ecc b/src/transport/test_plugin_hostkey.ecc
deleted file mode 100644
index 18641b798..000000000
--- a/src/transport/test_plugin_hostkey.ecc
+++ /dev/null
@@ -1 +0,0 @@
1‚”ˆÖ’ÛËy¢/HÒc ȃ§¿±;¼»f?¶@…~áJ \ No newline at end of file
diff --git a/src/transport/test_tng_defaults.conf b/src/transport/test_tng_defaults.conf
deleted file mode 100644
index e37dab25e..000000000
--- a/src/transport/test_tng_defaults.conf
+++ /dev/null
@@ -1,14 +0,0 @@
1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-tng/
5
6[transport]
7# PREFIX = valgrind
8
9[nat]
10DISABLEV6 = NO
11RETURN_LOCAL_ADDRESSES = YES
12BINDTO = 127.0.0.1
13INTERNAL_ADDRESS = 127.0.0.1
14EXTERNAL_ADDRESS = 127.0.0.1
diff --git a/src/transport/test_transport_address_switch.c b/src/transport/test_transport_address_switch.c
deleted file mode 100644
index ce5117bd1..000000000
--- a/src/transport/test_transport_address_switch.c
+++ /dev/null
@@ -1,433 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file transport/test_transport_address_switch.c
22 * @brief base test case for transport implementations
23 *
24 * This test case tests if peers can successfully switch addresses when
25 * connected for plugins supporting multiple addresses by monitoring transport's
26 * statistic values.
27 *
28 * This test starts 2 peers and connects them. When connected test messages
29 * are transmitted from peer 2 to peer 1. The test monitors transport's
30 * statistics values for information about address switch attempts.
31 *
32 * The test passes with success if one of the peers could successfully switch
33 * addresses in connected state and a test message was successfully transmitted
34 * after this switch.
35 *
36 * Since it is not possible to trigger an address switch from outside,
37 * the test returns "77" (skipped) when no address switching attempt
38 * takes place. It fails if an address switch attempt fails.
39 *
40 * NOTE: The test seems largely useless right now, as we simply NEVER
41 * switch addresses under the test conditions. However, it may be a
42 * good starting point for a future test. For now, it always times
43 * out and returns "77" (skipped), so we set the timeout suitably low.
44 */
45#include "platform.h"
46#include "gnunet_transport_service.h"
47#include "gnunet_ats_service.h"
48#include "transport-testing.h"
49
50
51/**
52 * Testcase timeout (set aggressively as we know this test doesn't work right now)
53 */
54#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
55
56
57static struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
58
59static struct GNUNET_SCHEDULER_Task *measure_task;
60
61
62/**
63 * Statistics we track per peer.
64 */
65struct PeerStats
66{
67 struct GNUNET_STATISTICS_Handle *stat;
68
69 unsigned int addresses_avail;
70
71 unsigned int switch_attempts;
72
73 unsigned int switch_success;
74
75 unsigned int switch_fail;
76};
77
78static struct PeerStats stats[2];
79
80/* Amount of data transferred since last switch attempt */
81static unsigned long long bytes_sent_after_switch;
82
83static unsigned long long bytes_recv_after_switch;
84
85
86static int
87stat_start_attempt_cb (void *cls,
88 const char *subsystem,
89 const char *name,
90 uint64_t value,
91 int is_persistent)
92{
93 struct PeerStats *stat = cls;
94
95 stat->switch_attempts++;
96 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Switch attempted (%p)", stat);
97 bytes_recv_after_switch = 0;
98 bytes_sent_after_switch = 0;
99
100 return GNUNET_OK;
101}
102
103
104static int
105stat_success_attempt_cb (void *cls,
106 const char *subsystem,
107 const char *name,
108 uint64_t value,
109 int is_persistent)
110{
111 struct PeerStats *stat = cls;
112
113 stat->switch_success++;
114 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Switch succeeded (%p)", stat);
115 return GNUNET_OK;
116}
117
118
119static int
120stat_fail_attempt_cb (void *cls,
121 const char *subsystem,
122 const char *name,
123 uint64_t value,
124 int is_persistent)
125{
126 struct PeerStats *stat = cls;
127
128 if (value == 0)
129 return GNUNET_OK;
130
131 stat->switch_fail++;
132 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Switch failed (%p)", stat);
133 return GNUNET_OK;
134}
135
136
137static int
138stat_addresses_available (void *cls,
139 const char *subsystem,
140 const char *name,
141 uint64_t value,
142 int is_persistent)
143{
144 struct PeerStats *stat = cls;
145
146 stat->addresses_avail++;
147 return GNUNET_OK;
148}
149
150
151/**
152 * List of statistics entries we care about.
153 */
154static struct WatchEntry
155{
156 /**
157 * Name of the statistic we watch.
158 */
159 const char *stat_name;
160
161 /**
162 * Handler to register;
163 */
164 GNUNET_STATISTICS_Iterator stat_handler;
165} watches[] =
166{ { "# Attempts to switch addresses", &stat_start_attempt_cb },
167 { "# Successful attempts to switch addresses", &stat_success_attempt_cb },
168 { "# Failed attempts to switch addresses (failed to send CONNECT CONT)",
169 &stat_fail_attempt_cb },
170 { "# Failed attempts to switch addresses (failed to send CONNECT)",
171 &stat_fail_attempt_cb },
172 { "# Failed attempts to switch addresses (no response)",
173 &stat_fail_attempt_cb },
174 { "# transport addresses", &stat_addresses_available },
175 { NULL, NULL } };
176
177
178static void
179custom_shutdown (void *cls)
180{
181 int result;
182
183 if (NULL != measure_task)
184 {
185 GNUNET_SCHEDULER_cancel (measure_task);
186 measure_task = NULL;
187 }
188 if (0 == stats[0].switch_attempts + stats[1].switch_attempts)
189 {
190 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
191 "Test did not work, as peers didn't switch (flawed testcase)!\n");
192 ccc->global_ret = 77;
193 }
194 else
195 {
196 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
197 "Fail (timeout)! No transmission after switch! Stopping peers\n");
198 ccc->global_ret = 77; /* GNUNET_SYSERR; */
199 }
200
201 /* stop statistics */
202 for (unsigned int i = 0; i < 2; i++)
203 {
204 if (NULL != stats[i].stat)
205 {
206 for (unsigned int j = 0; NULL != watches[j].stat_name; j++)
207 GNUNET_assert (GNUNET_OK ==
208 GNUNET_STATISTICS_watch_cancel (stats[i].stat,
209 "transport",
210 watches[j].stat_name,
211 watches[j].stat_handler,
212 &stats[i]));
213 GNUNET_STATISTICS_destroy (stats[i].stat, GNUNET_NO);
214 stats[i].stat = NULL;
215 }
216 }
217
218 result = 0;
219 fprintf (stderr, "\n");
220 if (stats[0].switch_attempts > 0)
221 {
222 fprintf (
223 stderr,
224 "Peer 1 tried %u times to switch and succeeded %u times, failed %u times\n",
225 stats[0].switch_attempts,
226 stats[0].switch_success,
227 stats[0].switch_fail);
228 if (stats[0].switch_success != stats[0].switch_attempts)
229 {
230 GNUNET_break (0);
231 result++;
232 }
233 }
234 else if (stats[0].addresses_avail > 1)
235 {
236 fprintf (stderr,
237 "Peer 1 had %u addresses available, but did not try to switch\n",
238 stats[0].addresses_avail);
239 }
240 if (stats[1].switch_attempts > 0)
241 {
242 fprintf (
243 stderr,
244 "Peer 2 tried %u times to switch and succeeded %u times, failed %u times\n",
245 stats[1].switch_attempts,
246 stats[1].switch_success,
247 stats[1].switch_fail);
248 if (stats[1].switch_success != stats[1].switch_attempts)
249 {
250 GNUNET_break (0);
251 result++;
252 }
253 }
254 else if (stats[1].addresses_avail > 1)
255 {
256 fprintf (stderr,
257 "Peer 2 had %u addresses available, but did not try to switch\n",
258 stats[1].addresses_avail);
259 }
260
261 if (((stats[0].switch_attempts > 0) || (stats[1].switch_attempts > 0)) &&
262 (bytes_sent_after_switch == 0))
263 {
264 fprintf (stderr, "No data sent after switching!\n");
265 GNUNET_break (0);
266 result++;
267 }
268 if (((stats[0].switch_attempts > 0) || (stats[1].switch_attempts > 0)) &&
269 (bytes_recv_after_switch == 0))
270 {
271 fprintf (stderr, "No data received after switching!\n");
272 GNUNET_break (0);
273 result++;
274 }
275#if 0
276 /* This test is not really expected to pass right now... */
277 if (0 != result)
278 ccc->global_ret = GNUNET_SYSERR;
279#endif
280}
281
282
283static void
284notify_receive (void *cls,
285 struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
286 const struct GNUNET_PeerIdentity *sender,
287 const struct GNUNET_TRANSPORT_TESTING_TestMessage *hdr)
288{
289 if (GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE != ntohs (hdr->header.type))
290 return;
291
292 {
293 char *ps = GNUNET_strdup (GNUNET_i2s (&receiver->id));
294
295 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
296 "Peer %u (`%s') got message %u of size %u from peer (`%s')\n",
297 receiver->no,
298 ps,
299 (uint32_t) ntohl (hdr->num),
300 ntohs (hdr->header.size),
301 GNUNET_i2s (sender));
302 GNUNET_free (ps);
303 }
304 if (((stats[0].switch_attempts >= 1) || (stats[1].switch_attempts >= 1)) &&
305 (stats[0].switch_attempts ==
306 stats[0].switch_fail + stats[0].switch_success) &&
307 (stats[1].switch_attempts ==
308 stats[1].switch_fail + stats[1].switch_success))
309 {
310 bytes_recv_after_switch += ntohs (hdr->header.size);
311 if ((bytes_sent_after_switch > 0) && (bytes_recv_after_switch > 0))
312 {
313 /* A peer switched addresses and sent and received data after the
314 * switch operations */
315 GNUNET_SCHEDULER_shutdown ();
316 }
317 }
318}
319
320
321static void
322notify_send (void *cls)
323{
324 static uint32_t cnt;
325
326 GNUNET_assert (
327 GNUNET_OK ==
328 GNUNET_TRANSPORT_TESTING_send (ccc->p[1],
329 ccc->p[0],
330 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
331 GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE,
332 ++cnt,
333 &notify_send,
334 NULL));
335 if (((stats[0].switch_attempts >= 1) || (stats[1].switch_attempts >= 1)) &&
336 (stats[0].switch_attempts ==
337 stats[0].switch_fail + stats[0].switch_success) &&
338 (stats[1].switch_attempts ==
339 stats[1].switch_fail + stats[1].switch_success))
340 {
341 bytes_sent_after_switch += GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE;
342 }
343}
344
345
346static void
347progress_indicator (void *cls)
348{
349 static int counter;
350
351 measure_task = NULL;
352 counter++;
353 if ((TIMEOUT.rel_value_us / 1000 / 1000LL) < counter)
354 {
355 fprintf (stderr, "%s", ".\n");
356 }
357 else
358 {
359 fprintf (stderr, "%s", ".");
360 measure_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
361 &progress_indicator,
362 NULL);
363 }
364}
365
366
367static void
368connected_cb (void *cls)
369{
370 for (unsigned int i = 0; i < 2; i++)
371 {
372 stats[i].stat = GNUNET_STATISTICS_create ("transport", ccc->p[i]->cfg);
373 if (NULL == stats[i].stat)
374 {
375 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
376 "Fail! Could not create statistics for peers!\n");
377 ccc->global_ret = GNUNET_SYSERR;
378 GNUNET_SCHEDULER_shutdown ();
379 return;
380 }
381 for (unsigned int j = 0; NULL != watches[j].stat_name; j++)
382 {
383 GNUNET_STATISTICS_watch (stats[i].stat,
384 "transport",
385 watches[j].stat_name,
386 watches[j].stat_handler,
387 &stats[i]);
388 }
389 }
390 /* Show progress */
391 ccc->global_ret = GNUNET_OK;
392 measure_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
393 &progress_indicator,
394 NULL);
395 /* Peers are connected, start transmit test messages */
396 GNUNET_assert (
397 GNUNET_OK ==
398 GNUNET_TRANSPORT_TESTING_send (ccc->p[1],
399 ccc->p[0],
400 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
401 GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE,
402 0,
403 &notify_send,
404 NULL));
405}
406
407
408int
409main (int argc, char *argv[])
410{
411 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext my_ccc =
412 { .connect_continuation = &connected_cb,
413 .config_file = "test_transport_api_data.conf",
414 .rec = &notify_receive,
415 .nc = &GNUNET_TRANSPORT_TESTING_log_connect,
416 .shutdown_task = &custom_shutdown,
417 .timeout = TIMEOUT };
418
419 ccc = &my_ccc;
420 int ret;
421
422 ret = GNUNET_TRANSPORT_TESTING_main (2,
423 &GNUNET_TRANSPORT_TESTING_connect_check,
424 ccc);
425 if (77 == ret)
426 return 77;
427 if (GNUNET_OK != ret)
428 return 1;
429 return 0;
430}
431
432
433/* end of test_transport_address_switch.c */
diff --git a/src/transport/test_transport_address_switch_tcp_peer1.conf b/src/transport/test_transport_address_switch_tcp_peer1.conf
deleted file mode 100644
index cfcbfe41c..000000000
--- a/src/transport/test_transport_address_switch_tcp_peer1.conf
+++ /dev/null
@@ -1,48 +0,0 @@
1@INLINE@ template_cfg_peer1.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
4
5[ats]
6UNSPECIFIED_QUOTA_IN = 8 KiB
7UNSPECIFIED_QUOTA_OUT = 8 KiB
8# LOOPBACK
9LOOPBACK_QUOTA_IN = 8 KiB
10LOOPBACK_QUOTA_OUT = 8 KiB
11# LAN
12LAN_QUOTA_IN = 8 KiB
13LAN_QUOTA_OUT = 8 KiB
14# WAN
15WAN_QUOTA_IN = 8 KiB
16WAN_QUOTA_OUT = 8 KiB
17# WLAN
18WLAN_QUOTA_IN = 8 KiB
19WLAN_QUOTA_OUT = 8 KiB
20# BLUETOOTH
21BLUETOOTH_QUOTA_IN = 8 KiB
22BLUETOOTH_QUOTA_OUT = 8 KiB
23
24[transport-tcp]
25PORT = 12000
26TIMEOUT = 5 s
27
28[arm]
29PORT = 12005
30UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
31
32[statistics]
33PORT = 12004
34UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock
35
36[resolver]
37PORT = 12003
38UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock
39
40[peerinfo]
41PORT = 12002
42UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock
43
44[transport]
45PORT = 12001
46UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock
47PLUGINS = tcp
48
diff --git a/src/transport/test_transport_address_switch_tcp_peer2.conf b/src/transport/test_transport_address_switch_tcp_peer2.conf
deleted file mode 100644
index bda2354b6..000000000
--- a/src/transport/test_transport_address_switch_tcp_peer2.conf
+++ /dev/null
@@ -1,48 +0,0 @@
1@INLINE@ template_cfg_peer2.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
4
5[ats]
6UNSPECIFIED_QUOTA_IN = 8 KiB
7UNSPECIFIED_QUOTA_OUT = 8 KiB
8# LOOPBACK
9LOOPBACK_QUOTA_IN = 8 KiB
10LOOPBACK_QUOTA_OUT = 8 KiB
11# LAN
12LAN_QUOTA_IN = 8 KiB
13LAN_QUOTA_OUT = 8 KiB
14# WAN
15WAN_QUOTA_IN = 8 KiB
16WAN_QUOTA_OUT = 8 KiB
17# WLAN
18WLAN_QUOTA_IN = 8 KiB
19WLAN_QUOTA_OUT = 8 KiB
20# BLUETOOTH
21BLUETOOTH_QUOTA_IN = 8 KiB
22BLUETOOTH_QUOTA_OUT = 8 KiB
23
24[transport-tcp]
25PORT = 12015
26TIMEOUT = 5 s
27
28[arm]
29PORT = 12014
30UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock
31
32[statistics]
33PORT = 12013
34UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock
35
36[resolver]
37PORT = 12012
38UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock
39
40[peerinfo]
41PORT = 12011
42UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock
43
44[transport]
45PORT = 12010
46PLUGINS = tcp
47UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock
48
diff --git a/src/transport/test_transport_address_switch_udp_peer1.conf b/src/transport/test_transport_address_switch_udp_peer1.conf
deleted file mode 100644
index bdc3a2253..000000000
--- a/src/transport/test_transport_address_switch_udp_peer1.conf
+++ /dev/null
@@ -1,48 +0,0 @@
1@INLINE@ template_cfg_peer1.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
4
5[ats]
6UNSPECIFIED_QUOTA_IN = 8 KiB
7UNSPECIFIED_QUOTA_OUT = 8 KiB
8# LOOPBACK
9LOOPBACK_QUOTA_IN = 8 KiB
10LOOPBACK_QUOTA_OUT = 8 KiB
11# LAN
12LAN_QUOTA_IN = 8 KiB
13LAN_QUOTA_OUT = 8 KiB
14# WAN
15WAN_QUOTA_IN = 8 KiB
16WAN_QUOTA_OUT = 8 KiB
17# WLAN
18WLAN_QUOTA_IN = 8 KiB
19WLAN_QUOTA_OUT = 8 KiB
20# BLUETOOTH
21BLUETOOTH_QUOTA_IN = 8 KiB
22BLUETOOTH_QUOTA_OUT = 8 KiB
23
24[transport-tcp]
25PORT = 12000
26TIMEOUT = 5 s
27
28[arm]
29PORT = 12005
30UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
31
32[statistics]
33PORT = 12004
34UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock
35
36[resolver]
37PORT = 12003
38UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock
39
40[peerinfo]
41PORT = 12002
42UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock
43
44[transport]
45PORT = 12001
46UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock
47PLUGINS = udp
48
diff --git a/src/transport/test_transport_address_switch_udp_peer2.conf b/src/transport/test_transport_address_switch_udp_peer2.conf
deleted file mode 100644
index ae6397db4..000000000
--- a/src/transport/test_transport_address_switch_udp_peer2.conf
+++ /dev/null
@@ -1,48 +0,0 @@
1@INLINE@ template_cfg_peer2.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
4
5[ats]
6UNSPECIFIED_QUOTA_IN = 8 KiB
7UNSPECIFIED_QUOTA_OUT = 8 KiB
8# LOOPBACK
9LOOPBACK_QUOTA_IN = 8 KiB
10LOOPBACK_QUOTA_OUT = 8 KiB
11# LAN
12LAN_QUOTA_IN = 8 KiB
13LAN_QUOTA_OUT = 8 KiB
14# WAN
15WAN_QUOTA_IN = 8 KiB
16WAN_QUOTA_OUT = 8 KiB
17# WLAN
18WLAN_QUOTA_IN = 8 KiB
19WLAN_QUOTA_OUT = 8 KiB
20# BLUETOOTH
21BLUETOOTH_QUOTA_IN = 8 KiB
22BLUETOOTH_QUOTA_OUT = 8 KiB
23
24[transport-tcp]
25PORT = 12015
26TIMEOUT = 5 s
27
28[arm]
29PORT = 12014
30UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock
31
32[statistics]
33PORT = 12013
34UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock
35
36[resolver]
37PORT = 12012
38UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock
39
40[peerinfo]
41PORT = 12011
42UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock
43
44[transport]
45PORT = 12010
46PLUGINS = udp
47UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock
48
diff --git a/src/transport/test_transport_api.c b/src/transport/test_transport_api.c
deleted file mode 100644
index 5f5e03a9e..000000000
--- a/src/transport/test_transport_api.c
+++ /dev/null
@@ -1,126 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file transport/test_transport_api.c
22 * @brief base test case for transport implementations
23 * @author Christian Grothoff
24 *
25 * This test case serves as a base for tcp, udp, and udp-nat
26 * transport test cases. Based on the executable being run
27 * the correct test case will be performed. Conservation of
28 * C code apparently.
29 */
30#include "platform.h"
31#include "gnunet_transport_service.h"
32#include "transport-testing.h"
33
34/**
35 * How long until we give up on transmitting the message?
36 */
37#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
38
39static struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
40
41
42static void
43notify_receive (void *cls,
44 struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
45 const struct GNUNET_PeerIdentity *sender,
46 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
47{
48 {
49 char *ps = GNUNET_strdup (GNUNET_i2s (&receiver->id));
50
51 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
52 "Peer %u (`%s') received message of type %d and size %u size from peer %s!\n",
53 receiver->no,
54 ps,
55 ntohs (message->header.type),
56 ntohs (message->header.size),
57 GNUNET_i2s (sender));
58 GNUNET_free (ps);
59 }
60
61 if ((GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE == ntohs (message->header.type)) &&
62 (GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE == ntohs (
63 message->header.size)))
64 {
65 ccc->global_ret = GNUNET_OK;
66 GNUNET_SCHEDULER_shutdown ();
67 }
68 else
69 {
70 GNUNET_break (0);
71 ccc->global_ret = GNUNET_SYSERR;
72 GNUNET_SCHEDULER_shutdown ();
73 }
74}
75
76
77/**
78 * Runs the test.
79 *
80 * @param argv the argv argument from main()
81 * @param bi_directional should we try to establish connections
82 * in both directions simultaneously?
83 */
84static int
85test (char *argv[],
86 int bi_directional)
87{
88 struct GNUNET_TRANSPORT_TESTING_SendClosure sc = {
89 .num_messages = 1
90 };
91 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext my_ccc = {
92 .connect_continuation = &GNUNET_TRANSPORT_TESTING_large_send,
93 .connect_continuation_cls = &sc,
94 .config_file = "test_transport_api_data.conf",
95 .rec = &notify_receive,
96 .nc = &GNUNET_TRANSPORT_TESTING_log_connect,
97 .nd = &GNUNET_TRANSPORT_TESTING_log_disconnect,
98 .timeout = TIMEOUT,
99 .bi_directional = bi_directional
100 };
101
102 ccc = &my_ccc;
103 sc.ccc = ccc;
104 if (GNUNET_OK !=
105 GNUNET_TRANSPORT_TESTING_main (2,
106 &GNUNET_TRANSPORT_TESTING_connect_check,
107 ccc))
108 return 1;
109 return 0;
110}
111
112
113int
114main (int argc,
115 char *argv[])
116{
117 if ((0 != test (argv,
118 GNUNET_NO)) ||
119 (0 != test (argv,
120 GNUNET_YES)))
121 return 1;
122 return 0;
123}
124
125
126/* end of test_transport_api.c */
diff --git a/src/transport/test_transport_api2.c b/src/transport/test_transport_api2.c
deleted file mode 100644
index 4d423f7c2..000000000
--- a/src/transport/test_transport_api2.c
+++ /dev/null
@@ -1,126 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file transport/test_transport_api.c
22 * @brief base test case for transport implementations
23 * @author Christian Grothoff
24 *
25 * This test case serves as a base for tcp, udp, and udp-nat
26 * transport test cases. Based on the executable being run
27 * the correct test case will be performed. Conservation of
28 * C code apparently.
29 */
30#include "platform.h"
31// #include "gnunet_transport_service.h"
32#include "transport-testing2.h"
33
34/**
35 * How long until we give up on transmitting the message?
36 */
37#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
38
39static struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
40
41
42static void
43notify_receive (void *cls,
44 struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
45 const struct GNUNET_PeerIdentity *sender,
46 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
47{
48 {
49 char *ps = GNUNET_strdup (GNUNET_i2s (&receiver->id));
50
51 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
52 "Peer %u (`%s') received message of type %d and size %u size from peer %s!\n",
53 receiver->no,
54 ps,
55 ntohs (message->header.type),
56 ntohs (message->header.size),
57 GNUNET_i2s (sender));
58 GNUNET_free (ps);
59 }
60
61 if ((GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE == ntohs (message->header.type)) &&
62 (GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE == ntohs (
63 message->header.size)))
64 {
65 ccc->global_ret = GNUNET_OK;
66 GNUNET_SCHEDULER_shutdown ();
67 }
68 else
69 {
70 GNUNET_break (0);
71 ccc->global_ret = GNUNET_SYSERR;
72 GNUNET_SCHEDULER_shutdown ();
73 }
74}
75
76
77/**
78 * Runs the test.
79 *
80 * @param argv the argv argument from main()
81 * @param bi_directional should we try to establish connections
82 * in both directions simultaneously?
83 */
84static int
85test (char *argv[],
86 int bi_directional)
87{
88 struct GNUNET_TRANSPORT_TESTING_SendClosure sc = {
89 .num_messages = 1
90 };
91 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext my_ccc = {
92 .connect_continuation = &GNUNET_TRANSPORT_TESTING_large_send,
93 .connect_continuation_cls = &sc,
94 .config_file = "test_transport_api_data.conf",
95 .rec = &notify_receive,
96 .nc = &GNUNET_TRANSPORT_TESTING_log_connect,
97 .nd = &GNUNET_TRANSPORT_TESTING_log_disconnect,
98 .timeout = TIMEOUT,
99 .bi_directional = bi_directional
100 };
101
102 ccc = &my_ccc;
103 sc.ccc = ccc;
104 if (GNUNET_OK !=
105 GNUNET_TRANSPORT_TESTING_main (2,
106 &GNUNET_TRANSPORT_TESTING_connect_check,
107 ccc))
108 return 1;
109 return 0;
110}
111
112
113int
114main (int argc,
115 char *argv[])
116{
117 if ((0 != test (argv,
118 GNUNET_NO)) ||
119 (0 != test (argv,
120 GNUNET_YES)))
121 return 1;
122 return 0;
123}
124
125
126/* end of test_transport_api.c */
diff --git a/src/transport/test_transport_api2_tcp_node1.conf b/src/transport/test_transport_api2_tcp_node1.conf
deleted file mode 100644
index 463ec61d8..000000000
--- a/src/transport/test_transport_api2_tcp_node1.conf
+++ /dev/null
@@ -1,35 +0,0 @@
1@INLINE@ template_cfg_peer1.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
4
5[transport]
6BINARY = gnunet-service-transport
7PLUGINS = tcp
8#PREFIX = valgrind --leak-check=full --track-origins=yes --trace-children=yes --log-file=$GNUNET_TEST_HOME/vg_peer1-%p
9UNIXPATH = $GNUNET_RUNTIME_DIR/tng-p1.sock
10
11[PEER]
12PRIVATE_KEY = $GNUNET_RUNTIME_DIR/private.key
13
14[communicator-tcp]
15BINARY = gnunet-communicator-tcp
16BINDTO = 192.168.15.1:60002
17DISABLE_V6 = YES
18IMMEDIATE_START = YES
19UNIXPATH = $GNUNET_RUNTIME_DIR/tcp-comm-p1.sock
20#PREFIX = valgrind --leak-check=full --track-origins=yes --trace-children=yes --log-file=$GNUNET_TEST_HOME/vg_ctpeer1-%p
21#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
22
23[communicator-udp]
24#PREFIX = valgrind --leak-check=full --track-origins=yes --trace-children=yes --log-file=$GNUNET_TEST_HOME/vg_cupeer1-%p
25BINARY = gnunet-communicator-udp
26BINDTO = 192.168.15.1:60002
27DISABLE_V6 = YES
28IMMEDIATE_START = YES
29UNIXPATH = $GNUNET_RUNTIME_DIR/udp-comm-p1.sock
30
31[peerstore]
32IMMEDIATE_START = YES
33
34#[transport]
35#PREFIX = valgrind
diff --git a/src/transport/test_transport_api2_tcp_node2.conf b/src/transport/test_transport_api2_tcp_node2.conf
deleted file mode 100644
index b7f92869e..000000000
--- a/src/transport/test_transport_api2_tcp_node2.conf
+++ /dev/null
@@ -1,22 +0,0 @@
1@INLINE@ template_cfg_peer2.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
4
5[transport]
6BINARY = gnunet-service-transport
7#PREFIX = valgrind --log-file=$GNUNET_TEST_HOME/vg_peer2-%p
8UNIXPATH = $GNUNET_RUNTIME_DIR/tng-p2.sock
9
10[communicator-tcp]
11BINARY = gnunet-communicator-tcp
12BINDTO = 192.168.15.2:60003
13DISABLE_V6 = YES
14IMMEDIATE_START = YES
15#PREFIX = valgrind --log-file=$GNUNET_TEST_HOME/vg_comm2-%p
16UNIXPATH = $GNUNET_RUNTIME_DIR/tcp-comm-p2.sock
17
18[peerstore]
19IMMEDIATE_START = YES
20
21#[transport]
22#PREFIX = valgrind
diff --git a/src/transport/test_transport_api2_tcp_peer1.conf b/src/transport/test_transport_api2_tcp_peer1.conf
deleted file mode 100644
index 54ec9fd9f..000000000
--- a/src/transport/test_transport_api2_tcp_peer1.conf
+++ /dev/null
@@ -1,23 +0,0 @@
1@INLINE@ template_cfg_peer1.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
4
5[transport]
6BINARY = gnunet-service-transport
7PLUGINS = tcp
8#PREFIX = valgrind --log-file=$GNUNET_TEST_HOME/vg_peer1-%p
9UNIXPATH = $GNUNET_RUNTIME_DIR/tng-p1.sock
10
11[communicator-tcp]
12BINARY = gnunet-communicator-tcp
13BINDTO = 60002
14DISABLE_V6 = YES
15IMMEDIATE_START = YES
16UNIXPATH = $GNUNET_RUNTIME_DIR/tcp-comm-p1.sock
17#PREFIX = valgrind --log-file=$GNUNET_TEST_HOME/vg_cpeer1-%p
18
19[peerstore]
20IMMEDIATE_START = YES
21
22#[transport]
23#PREFIX = valgrind
diff --git a/src/transport/test_transport_api2_tcp_peer2.conf b/src/transport/test_transport_api2_tcp_peer2.conf
deleted file mode 100644
index 7ae5ac697..000000000
--- a/src/transport/test_transport_api2_tcp_peer2.conf
+++ /dev/null
@@ -1,22 +0,0 @@
1@INLINE@ template_cfg_peer2.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
4
5[transport]
6BINARY = gnunet-service-transport
7#PREFIX = valgrind --log-file=$GNUNET_TEST_HOME/vg_peer2-%p
8UNIXPATH = $GNUNET_RUNTIME_DIR/tng-p2.sock
9
10[communicator-tcp]
11BINARY = gnunet-communicator-tcp
12BINDTO = 60003
13DISABLE_V6 = YES
14IMMEDIATE_START = YES
15#PREFIX = valgrind --log-file=$GNUNET_TEST_HOME/vg_comm2-%p
16UNIXPATH = $GNUNET_RUNTIME_DIR/tcp-comm-p2.sock
17
18[peerstore]
19IMMEDIATE_START = YES
20
21#[transport]
22#PREFIX = valgrind
diff --git a/src/transport/test_transport_api2_tng_node.conf b/src/transport/test_transport_api2_tng_node.conf
deleted file mode 100644
index c50ccf662..000000000
--- a/src/transport/test_transport_api2_tng_node.conf
+++ /dev/null
@@ -1,40 +0,0 @@
1@INLINE@ template_tng_cfg_peer1.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
4
5[transport]
6BINARY = gnunet-service-transport
7#PREFIX = valgrind --leak-check=full --track-origins=yes --trace-children=yes --log-file=$GNUNET_TEST_HOME/vg_peer1-%p
8UNIXPATH = $GNUNET_RUNTIME_DIR/tng-p1.sock
9
10[PEER]
11PRIVATE_KEY = $GNUNET_RUNTIME_DIR/private.key
12
13[communicator-tcp]
14BINARY = gnunet-communicator-tcp
15BINDTO = 192.168.15.1:60002
16DISABLE_V6 = YES
17IMMEDIATE_START = YES
18UNIXPATH = $GNUNET_RUNTIME_DIR/tcp-comm-p1.sock
19#PREFIX = valgrind --leak-check=full --track-origins=yes --trace-children=yes --log-file=$GNUNET_TEST_HOME/vg_ctpeer1-%p
20#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
21
22[communicator-udp]
23#PREFIX = valgrind --leak-check=full --track-origins=yes --trace-children=yes --log-file=$GNUNET_TEST_HOME/vg_cupeer1-%p
24BINARY = gnunet-communicator-udp
25BINDTO = 192.168.15.1:60002
26DISABLE_V6 = YES
27IMMEDIATE_START = YES
28UNIXPATH = $GNUNET_RUNTIME_DIR/udp-comm-p1.sock
29
30[peerstore]
31IMMEDIATE_START = YES
32
33[topology]
34IMMEDIATE_START = YES
35
36[dht]
37IMMEDIATE_START = YES
38
39[fs]
40IMMEDIATE_START = YES
diff --git a/src/transport/test_transport_api_data.conf b/src/transport/test_transport_api_data.conf
deleted file mode 100644
index c06235a0a..000000000
--- a/src/transport/test_transport_api_data.conf
+++ /dev/null
@@ -1,9 +0,0 @@
1@INLINE@ test_transport_defaults.conf
2[PATHS]
3
4[transport-tcp]
5PORT = 52094
6
7[transport-udp]
8PORT = 52094
9
diff --git a/src/transport/test_transport_api_monitor_peers.c b/src/transport/test_transport_api_monitor_peers.c
deleted file mode 100644
index c09e3782d..000000000
--- a/src/transport/test_transport_api_monitor_peers.c
+++ /dev/null
@@ -1,226 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file transport/test_transport_api_monitor_peers.c
22 * @brief base test case for transport peer monitor API
23 */
24#include "platform.h"
25#include "gnunet_transport_service.h"
26#include "transport-testing.h"
27
28/**
29 * How long until we give up on transmitting the message?
30 */
31#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
32
33/**
34 * How long until we give up on transmitting the message?
35 */
36#define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply ( \
37 GNUNET_TIME_UNIT_SECONDS, 30)
38
39#define TEST_MESSAGE_SIZE 2600
40
41#define TEST_MESSAGE_TYPE 12345
42
43static struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
44
45static struct GNUNET_TRANSPORT_PeerMonitoringContext *pmc_p1;
46
47static struct GNUNET_TRANSPORT_PeerMonitoringContext *pmc_p2;
48
49static int p1_c;
50
51static int p2_c;
52
53static int p1_c_notify;
54
55static int p2_c_notify;
56
57
58static void
59custom_shutdown (void *cls)
60{
61 if (NULL != pmc_p1)
62 {
63 GNUNET_TRANSPORT_monitor_peers_cancel (pmc_p1);
64 pmc_p1 = NULL;
65 }
66 if (NULL != pmc_p2)
67 {
68 GNUNET_TRANSPORT_monitor_peers_cancel (pmc_p2);
69 pmc_p2 = NULL;
70 }
71}
72
73
74static void
75notify_receive (void *cls,
76 struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
77 const struct GNUNET_PeerIdentity *sender,
78 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
79{
80 char *ps = GNUNET_strdup (GNUNET_i2s (&receiver->id));
81
82 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
83 "Peer %u (`%s') received message of type %d and size %u size from peer %s!\n",
84 receiver->no,
85 ps,
86 ntohs (message->header.type),
87 ntohs (message->header.size),
88 GNUNET_i2s (sender));
89 GNUNET_free (ps);
90}
91
92
93static void
94sendtask (void *cls)
95{
96 /* intentionally empty */
97}
98
99
100static void
101check_done ()
102{
103 if ((GNUNET_YES == p1_c) &&
104 (GNUNET_YES == p2_c) &&
105 p1_c_notify &&
106 p2_c_notify)
107 {
108 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
109 "Both peers state to be connected\n");
110 ccc->global_ret = GNUNET_OK;
111 GNUNET_SCHEDULER_shutdown ();
112 }
113}
114
115
116static void
117notify_connect (void *cls,
118 struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
119 const struct GNUNET_PeerIdentity *other)
120{
121 GNUNET_TRANSPORT_TESTING_log_connect (cls,
122 me,
123 other);
124 if (0 == memcmp (other, &ccc->p[0]->id, sizeof(struct GNUNET_PeerIdentity)))
125 {
126 p1_c_notify = GNUNET_YES;
127 }
128 if (0 == memcmp (other, &ccc->p[1]->id, sizeof(struct GNUNET_PeerIdentity)))
129 {
130 p2_c_notify = GNUNET_YES;
131 }
132 check_done ();
133}
134
135
136static void
137monitor1_cb (void *cls,
138 const struct GNUNET_PeerIdentity *peer,
139 const struct GNUNET_HELLO_Address *address,
140 enum GNUNET_TRANSPORT_PeerState state,
141 struct GNUNET_TIME_Absolute state_timeout)
142{
143 if ((NULL == address) || (NULL == ccc->p[0]))
144 return;
145
146 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
147 "Monitor 1: %s %s %s\n",
148 GNUNET_i2s (&address->peer),
149 GNUNET_TRANSPORT_ps2s (state),
150 GNUNET_STRINGS_absolute_time_to_string (state_timeout));
151 if ((0 == memcmp (&address->peer, &ccc->p[1]->id, sizeof(ccc->p[1]->id))) &&
152 (GNUNET_YES == GNUNET_TRANSPORT_is_connected (state)) &&
153 (GNUNET_NO == p1_c))
154 {
155 p1_c = GNUNET_YES;
156 check_done ();
157 }
158}
159
160
161static void
162monitor2_cb (void *cls,
163 const struct GNUNET_PeerIdentity *peer,
164 const struct GNUNET_HELLO_Address *address,
165 enum GNUNET_TRANSPORT_PeerState state,
166 struct GNUNET_TIME_Absolute state_timeout)
167{
168 if ((NULL == address) || (NULL == ccc->p[1]))
169 return;
170
171 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
172 "Monitor 2: %s %s %s\n",
173 GNUNET_i2s (&address->peer),
174 GNUNET_TRANSPORT_ps2s (state),
175 GNUNET_STRINGS_absolute_time_to_string (state_timeout));
176 if ((0 == memcmp (&address->peer, &ccc->p[0]->id, sizeof(ccc->p[0]->id))) &&
177 (GNUNET_YES == GNUNET_TRANSPORT_is_connected (state)) &&
178 (GNUNET_NO == p2_c))
179 {
180 p2_c = GNUNET_YES;
181 check_done ();
182 }
183}
184
185
186static void
187start_monitors (void *cls)
188{
189 pmc_p1 = GNUNET_TRANSPORT_monitor_peers (ccc->p[0]->cfg,
190 NULL,
191 GNUNET_NO,
192 &monitor1_cb,
193 NULL);
194 pmc_p2 = GNUNET_TRANSPORT_monitor_peers (ccc->p[1]->cfg,
195 NULL,
196 GNUNET_NO,
197 &monitor2_cb,
198 NULL);
199}
200
201
202int
203main (int argc, char *argv[])
204{
205 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext my_ccc = {
206 .pre_connect_task = &start_monitors,
207 .connect_continuation = &sendtask,
208 .config_file = "test_transport_api_data.conf",
209 .rec = &notify_receive,
210 .nc = &notify_connect,
211 .nd = &GNUNET_TRANSPORT_TESTING_log_disconnect,
212 .shutdown_task = &custom_shutdown,
213 .timeout = TIMEOUT
214 };
215
216 ccc = &my_ccc;
217 if (GNUNET_OK !=
218 GNUNET_TRANSPORT_TESTING_main (2,
219 &GNUNET_TRANSPORT_TESTING_connect_check,
220 ccc))
221 return 1;
222 return 0;
223}
224
225
226/* end of test_transport_api_monitor_peers.c */
diff --git a/src/transport/test_transport_api_monitor_peers_peer1.conf b/src/transport/test_transport_api_monitor_peers_peer1.conf
deleted file mode 100644
index bc9eee19b..000000000
--- a/src/transport/test_transport_api_monitor_peers_peer1.conf
+++ /dev/null
@@ -1,4 +0,0 @@
1@INLINE@ template_cfg_peer1.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-monitoring-p1/
4
diff --git a/src/transport/test_transport_api_monitor_peers_peer2.conf b/src/transport/test_transport_api_monitor_peers_peer2.conf
deleted file mode 100644
index 5225a5a87..000000000
--- a/src/transport/test_transport_api_monitor_peers_peer2.conf
+++ /dev/null
@@ -1,5 +0,0 @@
1@INLINE@ template_cfg_peer2.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-monitoring-p2/
4
5
diff --git a/src/transport/test_transport_api_monitor_validation_peer1.conf b/src/transport/test_transport_api_monitor_validation_peer1.conf
deleted file mode 100644
index 02f7bc2f0..000000000
--- a/src/transport/test_transport_api_monitor_validation_peer1.conf
+++ /dev/null
@@ -1,6 +0,0 @@
1@INLINE@ template_cfg_peer1.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-monitoring-val-p1/
4
5[transport]
6PLUGINS=tcp
diff --git a/src/transport/test_transport_api_monitor_validation_peer2.conf b/src/transport/test_transport_api_monitor_validation_peer2.conf
deleted file mode 100644
index d4e0874f0..000000000
--- a/src/transport/test_transport_api_monitor_validation_peer2.conf
+++ /dev/null
@@ -1,7 +0,0 @@
1@INLINE@ template_cfg_peer2.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-monitoring-val-p2/
4
5[TRANSPORT]
6PLUGINS=tcp
7
diff --git a/src/transport/test_transport_api_multi_peer1.conf b/src/transport/test_transport_api_multi_peer1.conf
deleted file mode 100644
index b7cb98777..000000000
--- a/src/transport/test_transport_api_multi_peer1.conf
+++ /dev/null
@@ -1,7 +0,0 @@
1@INLINE@ template_cfg_peer1.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-multi-p1/
4
5[transport]
6PLUGINS = tcp udp
7
diff --git a/src/transport/test_transport_api_multi_peer2.conf b/src/transport/test_transport_api_multi_peer2.conf
deleted file mode 100644
index f69e0abd9..000000000
--- a/src/transport/test_transport_api_multi_peer2.conf
+++ /dev/null
@@ -1,9 +0,0 @@
1@INLINE@ template_cfg_peer2.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-multi-p2/
4
5[nat]
6ALLOW_NAT = NO
7
8[transport]
9PLUGINS = tcp udp
diff --git a/src/transport/test_transport_api_tcp_nat_peer1.conf b/src/transport/test_transport_api_tcp_nat_peer1.conf
deleted file mode 100644
index fb2fcecc6..000000000
--- a/src/transport/test_transport_api_tcp_nat_peer1.conf
+++ /dev/null
@@ -1,34 +0,0 @@
1@INLINE@ template_cfg_peer1.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-nat-p1/
4
5[nat]
6BEHIND_NAT = YES
7ENABLE_NAT_SERVER = YES
8DISABLEV6 = YES
9
10[transport-tcp]
11PORT = 0
12TIMEOUT = 5 s
13
14[arm]
15PORT = 51204
16UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
17
18[statistics]
19PORT = 12023
20UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock
21
22[resolver]
23PORT = 12022
24UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock
25
26[peerinfo]
27PORT = 12021
28UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock
29
30[transport]
31PORT = 29542
32PLUGINS = tcp
33UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock
34
diff --git a/src/transport/test_transport_api_tcp_nat_peer2.conf b/src/transport/test_transport_api_tcp_nat_peer2.conf
deleted file mode 100644
index 1faefc195..000000000
--- a/src/transport/test_transport_api_tcp_nat_peer2.conf
+++ /dev/null
@@ -1,32 +0,0 @@
1@INLINE@ template_cfg_peer2.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-nat-p2/
4
5[nat]
6DISABLEV6 = YES
7ENABLE_NAT_CLIENT = YES
8
9[transport-tcp]
10PORT = 12030
11TIMEOUT = 5 s
12
13[arm]
14PORT = 12034
15UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock
16
17[statistics]
18PORT = 12033
19UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock
20
21[resolver]
22PORT = 12032
23UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock
24
25[peerinfo]
26PORT = 12031
27UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock
28
29[transport]
30PORT = 45923
31PLUGINS = tcp
32UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock
diff --git a/src/transport/test_transport_api_tcp_peer1.conf b/src/transport/test_transport_api_tcp_peer1.conf
deleted file mode 100644
index eabd6b701..000000000
--- a/src/transport/test_transport_api_tcp_peer1.conf
+++ /dev/null
@@ -1,9 +0,0 @@
1@INLINE@ template_cfg_peer1.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
4
5[transport]
6PLUGINS = tcp
7
8#[transport]
9#PREFIX = valgrind
diff --git a/src/transport/test_transport_api_tcp_peer2.conf b/src/transport/test_transport_api_tcp_peer2.conf
deleted file mode 100644
index 58ce0777f..000000000
--- a/src/transport/test_transport_api_tcp_peer2.conf
+++ /dev/null
@@ -1,9 +0,0 @@
1@INLINE@ template_cfg_peer2.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
4
5[transport]
6PLUGINS = tcp
7
8#[transport]
9#PREFIX = valgrind
diff --git a/src/transport/test_transport_api_udp_nat_peer1.conf b/src/transport/test_transport_api_udp_nat_peer1.conf
deleted file mode 100644
index 7bbcaa628..000000000
--- a/src/transport/test_transport_api_udp_nat_peer1.conf
+++ /dev/null
@@ -1,34 +0,0 @@
1@INLINE@ template_cfg_peer1.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-udp-nat-p1/
4
5[nat]
6BEHIND_NAT = YES
7ALLOW_NAT = NO
8ONLY_NAT_ADDRESSES = YES
9
10[transport-udp]
11PORT = 0
12
13[arm]
14PORT = 12065
15UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
16
17[statistics]
18PORT = 12064
19UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock
20
21[resolver]
22PORT = 12063
23UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock
24
25[peerinfo]
26PORT = 12062
27UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock
28
29[transport]
30PORT = 12061
31PLUGINS = udp
32UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock
33
34
diff --git a/src/transport/test_transport_api_udp_nat_peer2.conf b/src/transport/test_transport_api_udp_nat_peer2.conf
deleted file mode 100644
index 8bdb8c293..000000000
--- a/src/transport/test_transport_api_udp_nat_peer2.conf
+++ /dev/null
@@ -1,32 +0,0 @@
1@INLINE@ template_cfg_peer2.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-udp-nat-p2/
4
5[nat]
6ALLOW_NAT = YES
7
8[transport-udp]
9PORT = 12070
10
11[arm]
12PORT = 12075
13UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock
14
15[statistics]
16PORT = 12074
17UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock
18
19[resolver]
20PORT = 12073
21UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock
22
23[peerinfo]
24PORT = 12072
25UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock
26
27[transport]
28PORT = 12071
29PLUGINS = udp
30UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock
31
32
diff --git a/src/transport/test_transport_api_udp_peer1.conf b/src/transport/test_transport_api_udp_peer1.conf
deleted file mode 100644
index 4684b77f2..000000000
--- a/src/transport/test_transport_api_udp_peer1.conf
+++ /dev/null
@@ -1,17 +0,0 @@
1@INLINE@ template_cfg_peer1.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-udp-p1/
4
5[transport-udp]
6PORT = 0
7BROADCAST = NO
8MAX_BPS = 50000000
9BINDTO = 127.0.0.1
10BINDTO6 = ::1
11
12[transport]
13PORT = 12041
14PLUGINS = udp
15
16
17
diff --git a/src/transport/test_transport_api_udp_peer2.conf b/src/transport/test_transport_api_udp_peer2.conf
deleted file mode 100644
index 96706ce49..000000000
--- a/src/transport/test_transport_api_udp_peer2.conf
+++ /dev/null
@@ -1,15 +0,0 @@
1@INLINE@ template_cfg_peer2.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-udp-p2/
4
5[transport-udp]
6PORT = 12050
7BROADCAST = NO
8MAX_BPS = 50000000
9BINDTO = 127.0.0.1
10BINDTO6 = ::1
11
12[transport]
13PLUGINS = udp
14
15
diff --git a/src/transport/test_transport_api_unix_peer1.conf b/src/transport/test_transport_api_unix_peer1.conf
deleted file mode 100644
index 005558bcc..000000000
--- a/src/transport/test_transport_api_unix_peer1.conf
+++ /dev/null
@@ -1,10 +0,0 @@
1@INLINE@ template_cfg_peer1.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-unix-p1/
4
5[transport]
6PLUGINS = unix
7
8[transport-unix]
9PORT = 12120
10
diff --git a/src/transport/test_transport_api_unix_peer2.conf b/src/transport/test_transport_api_unix_peer2.conf
deleted file mode 100644
index 840ed81c7..000000000
--- a/src/transport/test_transport_api_unix_peer2.conf
+++ /dev/null
@@ -1,7 +0,0 @@
1@INLINE@ template_cfg_peer2.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-unix-p2/
4
5[transport]
6PLUGINS = unix
7
diff --git a/src/transport/test_transport_defaults.conf b/src/transport/test_transport_defaults.conf
deleted file mode 100644
index 3aed73f0c..000000000
--- a/src/transport/test_transport_defaults.conf
+++ /dev/null
@@ -1,20 +0,0 @@
1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-tng/
5
6[transport-tcp]
7TIMEOUT = 300 s
8
9[transport]
10# PREFIX = valgrind
11
12[nat]
13DISABLEV6 = NO
14RETURN_LOCAL_ADDRESSES = YES
15BINDTO = 127.0.0.1
16INTERNAL_ADDRESS = 127.0.0.1
17EXTERNAL_ADDRESS = 127.0.0.1
18
19[transport-udp]
20BROADCAST_RECEIVE = no
diff --git a/src/transport/test_transport_distance_vector_circle_topo.conf b/src/transport/test_transport_distance_vector_circle_topo.conf
deleted file mode 100644
index e8d694c3a..000000000
--- a/src/transport/test_transport_distance_vector_circle_topo.conf
+++ /dev/null
@@ -1,11 +0,0 @@
1M:1
2N:3
3X:0
4B:0
5T:libgnunet_test_transport_plugin_cmd_simple_send_dv
6R:1|{tcp_port:0}|{udp_port:1}
7R:2|{tcp_port:0}|{udp_port:1}
8R:3|{tcp_port:0}|{udp_port:1}
9P:1:1|{connect:{P:2:1:udp}}
10P:2:1|{connect:{P:3:1:udp}}
11P:3:1|{connect:{P:1:1:udp}}
diff --git a/src/transport/test_transport_distance_vector_inverse_topo.conf b/src/transport/test_transport_distance_vector_inverse_topo.conf
deleted file mode 100644
index e062b3e2e..000000000
--- a/src/transport/test_transport_distance_vector_inverse_topo.conf
+++ /dev/null
@@ -1,13 +0,0 @@
1M:1
2N:4
3X:0
4AC:1
5T:libgnunet_test_transport_plugin_cmd_simple_send_dv
6R:1|{tcp_port:1}|{udp_port:0}
7R:2|{tcp_port:1}|{udp_port:0}
8R:3|{tcp_port:1}|{udp_port:0}
9R:4|{tcp_port:1}|{udp_port:0}
10P:1:1|{connect:{P:2:1:tcp}}|{AC:2}
11P:2:1|{connect:{P:3:1:tcp}}|{AC:2}
12P:3:1|{connect:{P:4:1:tcp}}|{AC:2}
13P:4:1|{AC:3} \ No newline at end of file
diff --git a/src/transport/test_transport_distance_vector_topo.conf b/src/transport/test_transport_distance_vector_topo.conf
deleted file mode 100644
index ead3e0a0a..000000000
--- a/src/transport/test_transport_distance_vector_topo.conf
+++ /dev/null
@@ -1,8 +0,0 @@
1M:2
2N:2
3X:0
4T:libgnunet_test_transport_plugin_cmd_simple_send_dv
5R:1|{tcp_port:1}|{udp_port:0}
6R:2|{tcp_port:1}|{udp_port:0}
7P:1:1|{connect:{P:2:1:tcp}}
8P:2:1|{connect:{P:1:1:tcp}}
diff --git a/src/transport/test_transport_just_run_topo.conf b/src/transport/test_transport_just_run_topo.conf
deleted file mode 100644
index d27a2fc77..000000000
--- a/src/transport/test_transport_just_run_topo.conf
+++ /dev/null
@@ -1,6 +0,0 @@
1M:2
2N:1
3X:0
4T:libgnunet_test_transport_plugin_cmd_just_run
5P:1:1|{connect:{P:1:2:tcp}|{P:1:2:udp}}
6P:1:2|{connect:{P:1:1:tcp}|{P:1:1:udp}} \ No newline at end of file
diff --git a/src/transport/test_transport_nat_icmp_tcp.sh b/src/transport/test_transport_nat_icmp_tcp.sh
deleted file mode 100755
index 41cdde487..000000000
--- a/src/transport/test_transport_nat_icmp_tcp.sh
+++ /dev/null
@@ -1,12 +0,0 @@
1#!/bin/bash
2if ! [ -d "/run/netns" ]; then
3 echo You have to create the directory /run/netns.
4fi
5if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
6 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
7 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
8 exit 78
9 fi
10fi
11exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_nat_icmp_tcp_topo.conf"
12#sudo valgrind --vgdb=yes --leak-check=full --track-origins=yes --trace-children=yes --trace-children-skip=/usr/bin/awk,/usr/bin/cut,/usr/bin/seq,/sbin/ip/sed/bash ./test_transport_start_with_config test_transport_nat_upnp_topo.conf
diff --git a/src/transport/test_transport_nat_icmp_tcp_topo.conf b/src/transport/test_transport_nat_icmp_tcp_topo.conf
deleted file mode 100644
index 37738c80f..000000000
--- a/src/transport/test_transport_nat_icmp_tcp_topo.conf
+++ /dev/null
@@ -1,7 +0,0 @@
1M:1
2N:1
3X:1
4T:libgnunet_test_transport_plugin_cmd_nat_upnp
5K:1|{connect:{P:1:1:tcp_natted}}
6R:1|{tcp_port:0}|{udp_port:0}
7P:1:1 \ No newline at end of file
diff --git a/src/transport/test_transport_nat_upnp.sh b/src/transport/test_transport_nat_upnp.sh
deleted file mode 100755
index df43ef320..000000000
--- a/src/transport/test_transport_nat_upnp.sh
+++ /dev/null
@@ -1,12 +0,0 @@
1#!/bin/bash
2if ! [ -d "/run/netns" ]; then
3 echo You have to create the directory /run/netns.
4fi
5if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
6 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
7 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
8 exit 78
9 fi
10fi
11exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_nat_upnp_topo.conf"
12#sudo valgrind --vgdb=yes --leak-check=full --track-origins=yes --trace-children=yes --trace-children-skip=/usr/bin/awk,/usr/bin/cut,/usr/bin/seq,/sbin/ip/sed/bash ./test_transport_start_with_config test_transport_nat_upnp_topo.conf
diff --git a/src/transport/test_transport_nat_upnp_topo.conf b/src/transport/test_transport_nat_upnp_topo.conf
deleted file mode 100644
index e02633d4b..000000000
--- a/src/transport/test_transport_nat_upnp_topo.conf
+++ /dev/null
@@ -1,7 +0,0 @@
1M:1
2N:1
3X:1
4T:libgnunet_test_transport_plugin_cmd_nat_upnp
5K:1|{connect:{P:1:1:tcp}}
6R:1|{tcp_port:0}|{udp_port:0}|{script:upnp.sh}
7P:1:1|{connect:{K:1:udp}} \ No newline at end of file
diff --git a/src/transport/test_transport_plugin_cmd_just_run.c b/src/transport/test_transport_plugin_cmd_just_run.c
deleted file mode 100644
index df7484884..000000000
--- a/src/transport/test_transport_plugin_cmd_just_run.c
+++ /dev/null
@@ -1,494 +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 testbed/plugin_cmd_simple_send.c
23 * @brief a plugin to provide the API for running test cases.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_barrier.h"
28#include "gnunet_testing_netjail_lib.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_transport_application_service.h"
31#include "transport-testing2.h"
32#include "transport-testing-cmds.h"
33#include "gnunet_testing_barrier.h"
34#include "gnunet_core_service.h"
35
36/**
37 * Generic logging shortcut
38 */
39#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
40
41#define BASE_DIR "testdir"
42
43#define TOPOLOGY_CONFIG "test_transport_simple_send_topo.conf"
44
45#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
46
47#define MAX_RECEIVED 1000
48
49#define MESSAGE_SIZE 65000
50
51static struct GNUNET_TESTING_Command block_script;
52
53static struct GNUNET_TESTING_Command connect_peers;
54
55static struct GNUNET_TESTING_Command local_prepared;
56
57static struct GNUNET_TESTING_Command start_peer;
58
59static struct GNUNET_TESTING_Interpreter *is;
60
61static struct GNUNET_CONTAINER_MultiPeerMap *senders;
62
63struct Sender
64{
65 /**
66 * Number of received messages from sender.
67 */
68 unsigned long long num_received;
69
70 /**
71 * Sample mean time the message traveled.
72 */
73 struct GNUNET_TIME_Relative mean_time;
74
75 /**
76 * Time the first message was send.
77 */
78 struct GNUNET_TIME_Absolute time_first;
79};
80
81/**
82 * Function called to check a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE being
83 * received.
84 *
85 */
86static int
87check_test (void *cls,
88 const struct
89 GNUNET_TRANSPORT_TESTING_PerformanceTestMessage *message)
90{
91 return GNUNET_OK;
92}
93
94
95struct GNUNET_TESTING_BarrierList*
96get_waiting_for_barriers ()
97{
98 struct GNUNET_TESTING_BarrierList*barriers;
99 struct GNUNET_TESTING_BarrierListEntry *ble;
100
101 barriers = GNUNET_new (struct GNUNET_TESTING_BarrierList);
102 ble = GNUNET_new (struct GNUNET_TESTING_BarrierListEntry);
103 ble->barrier_name = "ready-to-connect";
104 ble->expected_reaches = 1;
105 GNUNET_CONTAINER_DLL_insert (barriers->head,
106 barriers->tail,
107 ble);
108
109 ble = GNUNET_new (struct GNUNET_TESTING_BarrierListEntry);
110 ble->barrier_name = "test-case-finished";
111 ble->expected_reaches = 1;
112 GNUNET_CONTAINER_DLL_insert (barriers->head,
113 barriers->tail,
114 ble);
115 return barriers;
116}
117
118
119/**
120 * Callback to set the flag indicating all peers started. Will be called via the plugin api.
121 *
122 */
123static void
124all_peers_started ()
125{
126}
127
128
129/**
130 * Function called with the final result of the test.
131 *
132 * @param cls the `struct MainParams`
133 * @param rv #GNUNET_OK if the test passed
134 */
135static void
136handle_result (void *cls,
137 enum GNUNET_GenericReturnValue rv)
138{
139 struct TestState *ts = cls;
140
141 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
142 "Local test exits with status %d\n",
143 rv);
144
145 ts->finished_cb (rv);
146 GNUNET_free (ts->testdir);
147 GNUNET_free (ts->cfgname);
148 GNUNET_TESTING_free_topology (ts->topology);
149 GNUNET_free (ts);
150}
151
152
153/**
154 * Callback from start peer cmd for signaling a peer got connected.
155 *
156 *
157static void *
158notify_connect (struct GNUNET_TESTING_Interpreter *is,
159 const struct GNUNET_PeerIdentity *peer)
160{
161 const struct ConnectPeersState *cps;
162 const struct GNUNET_TESTING_Command *cmd;
163
164 cmd = GNUNET_TESTING_interpreter_lookup_command (is,
165 "connect-peers");
166 GNUNET_TRANSPORT_get_trait_connect_peer_state (cmd,
167 &cps);
168 void *ret = NULL;
169
170 cps->notify_connect (is,
171 peer);
172 return ret;
173 }*/
174
175
176/**
177 * Callback to set the flag indicating all peers are prepared to finish. Will be called via the plugin api.
178 */
179static void
180all_local_tests_prepared ()
181{
182 const struct GNUNET_TESTING_LocalPreparedState *lfs;
183
184 GNUNET_TESTING_get_trait_local_prepared_state (&local_prepared,
185 &lfs);
186 GNUNET_assert (NULL != &lfs->ac);
187 if (NULL == lfs->ac.cont)
188 GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) &lfs->ac);
189 else
190 GNUNET_TESTING_async_finish ((struct
191 GNUNET_TESTING_AsyncContext *) &lfs->ac);
192}
193
194
195static void
196child_completed_callback (void *cls,
197 enum GNUNET_OS_ProcessStatusType type,
198 long unsigned int exit_code)
199{
200
201}
202
203
204/**
205 * Function called to check a message being
206 * received.
207 *
208 */
209static int
210check_encrypted (void *cls, struct GNUNET_MessageHeader *header)
211{
212 return GNUNET_OK;
213}
214
215
216static void
217core_receive_continue (struct GNUNET_PeerIdentity *peer)
218{
219 const struct GNUNET_TESTING_StartPeerState *sps;
220
221 GNUNET_TRANSPORT_get_trait_state (&start_peer,
222 &sps);
223
224 LOG (GNUNET_ERROR_TYPE_DEBUG,
225 "Executing core receive continue\n");
226
227 GNUNET_TRANSPORT_core_receive_continue (sps->th, peer);
228}
229
230
231/*static void
232handle_core (void *cls, struct GNUNET_MessageHeader *header)
233{
234 struct GNUNET_PeerIdentity *peer = cls;
235
236 core_receive_continue (peer);
237 }*/
238
239
240/**
241 * Function called to handle a message being received.
242 *
243 */
244static void
245handle_encrypted (void *cls, struct GNUNET_MessageHeader *header)
246{
247 struct GNUNET_PeerIdentity *peer = cls;
248
249 core_receive_continue (peer);
250}
251
252
253static void
254handle_ephemeral_key (void *cls, struct GNUNET_MessageHeader *header)
255{
256 struct GNUNET_PeerIdentity *peer = cls;
257
258 core_receive_continue (peer);
259}
260
261
262static void
263handle_ping (void *cls, struct GNUNET_MessageHeader *header)
264{
265 struct GNUNET_PeerIdentity *peer = cls;
266
267 core_receive_continue (peer);
268}
269
270
271static void
272handle_pong (void *cls, struct GNUNET_MessageHeader *header)
273{
274 struct GNUNET_PeerIdentity *peer = cls;
275
276 core_receive_continue (peer);
277}
278
279/**
280 * Function to start a local test case.
281 *
282 * @param write_message Callback to send a message to the master loop.
283 * @param router_ip Global address of the network namespace.
284 * @param node_ip The IP address of the node.
285 * @param m The number of the node in a network namespace.
286 * @param n The number of the network namespace.
287 * @param local_m The number of nodes in a network namespace.
288 * @param topology_data A file name for the file containing the topology configuration, or a string containing
289 * the topology configuration.
290 * @param read_file If read_file is GNUNET_YES this string is the filename for the topology configuration,
291 * if read_file is GNUNET_NO the string contains the topology configuration.
292 * @param finish_cb Callback function which writes a message from the helper process running on a netjail
293 * node to the master process * signaling that the test case running on the netjail node finished.
294 * @return Returns the struct GNUNET_TESTING_Interpreter of the command loop running on this netjail node.
295 */
296static struct GNUNET_TESTING_Interpreter *
297start_testcase (GNUNET_TESTING_cmd_helper_write_cb write_message,
298 const char *router_ip,
299 const char *node_ip,
300 const char *m,
301 const char *n,
302 const char *local_m,
303 const char *topology_data,
304 unsigned int *read_file,
305 GNUNET_TESTING_cmd_helper_finish_cb finished_cb)
306{
307
308 unsigned int n_int;
309 unsigned int m_int;
310 unsigned int local_m_int;
311 unsigned int num;
312 struct TestState *ts = GNUNET_new (struct TestState);
313 struct GNUNET_TESTING_NetjailTopology *topology;
314 unsigned int sscanf_ret = 0;
315 char **argv = NULL;
316 int argc = 0;
317
318 ts->finished_cb = finished_cb;
319 LOG (GNUNET_ERROR_TYPE_ERROR,
320 "n %s m %s\n",
321 n,
322 m);
323
324 if (GNUNET_YES == *read_file)
325 {
326 LOG (GNUNET_ERROR_TYPE_DEBUG,
327 "read from file\n");
328 topology = GNUNET_TESTING_get_topo_from_file (topology_data);
329 }
330 else
331 topology = GNUNET_TESTING_get_topo_from_string (topology_data);
332
333 ts->topology = topology;
334
335 errno = 0;
336 sscanf_ret = sscanf (m, "%u", &m_int);
337 if (errno != 0)
338 {
339 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
340 }
341 GNUNET_assert (0 < sscanf_ret);
342 errno = 0;
343 sscanf_ret = sscanf (n, "%u", &n_int);
344 if (errno != 0)
345 {
346 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
347 }
348 GNUNET_assert (0 < sscanf_ret);
349 errno = 0;
350 sscanf_ret = sscanf (local_m, "%u", &local_m_int);
351 if (errno != 0)
352 {
353 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
354 }
355 GNUNET_assert (0 < sscanf_ret);
356
357 if (0 == n_int)
358 num = m_int;
359 else
360 num = (n_int - 1) * local_m_int + m_int + topology->nodes_x;
361
362 block_script = GNUNET_TESTING_cmd_block_until_external_trigger (
363 "block-script");
364 connect_peers = GNUNET_TRANSPORT_cmd_connect_peers ("connect-peers",
365 "start-peer",
366 "system-create",
367 num,
368 topology,
369 0,
370 GNUNET_NO);
371 local_prepared = GNUNET_TESTING_cmd_local_test_prepared (
372 "local-test-prepared",
373 write_message);
374
375
376 GNUNET_asprintf (&ts->cfgname,
377 "test_transport_api2_tcp_node1.conf");
378
379 LOG (GNUNET_ERROR_TYPE_DEBUG,
380 "plugin cfgname: %s\n",
381 ts->cfgname);
382
383 LOG (GNUNET_ERROR_TYPE_DEBUG,
384 "node ip: %s\n",
385 node_ip);
386
387 GNUNET_asprintf (&ts->testdir,
388 "%s%s%s",
389 BASE_DIR,
390 m,
391 n);
392
393 /*struct GNUNET_MQ_MessageHandler handlers[] = {
394 GNUNET_MQ_hd_fixed_size (ephemeral_key,
395 GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY,
396 struct EphemeralKeyMessage,
397 NULL),
398 GNUNET_MQ_hd_fixed_size (ping,
399 GNUNET_MESSAGE_TYPE_CORE_PING,
400 struct PingMessage,
401 NULL),
402 GNUNET_MQ_hd_fixed_size (pong,
403 GNUNET_MESSAGE_TYPE_CORE_PONG,
404 struct PongMessage,
405 NULL),
406 GNUNET_MQ_handler_end ()
407 };*/
408
409 start_peer = GNUNET_TESTING_cmd_start_peer ("start-peer",
410 "system-create",
411 num,
412 node_ip,
413 ts->cfgname,
414 GNUNET_NO);
415
416 struct GNUNET_TESTING_Command commands[] = {
417 GNUNET_TESTING_cmd_system_create ("system-create",
418 ts->testdir),
419 start_peer,
420 GNUNET_TESTING_cmd_barrier_reached ("ready-to-connect-reached",
421 "ready-to-connect",
422 GNUNET_NO,
423 num,
424 GNUNET_NO,
425 write_message),
426 connect_peers,
427 GNUNET_TESTING_cmd_exec_bash_script ("script",
428 "block.sh",
429 argv,
430 argc,
431 &child_completed_callback),
432 block_script,
433 GNUNET_TESTING_cmd_barrier_reached ("test-case-finished-reached",
434 "test-case-finished",
435 GNUNET_NO,
436 num,
437 GNUNET_NO,
438 write_message),
439 GNUNET_TRANSPORT_cmd_stop_peer ("stop-peer",
440 "start-peer"),
441 GNUNET_TESTING_cmd_system_destroy ("system-destroy",
442 "system-create"),
443 GNUNET_TESTING_cmd_end ()
444 };
445
446 ts->write_message = write_message;
447
448 is = GNUNET_TESTING_run (commands,
449 TIMEOUT,
450 &handle_result,
451 ts);
452 return is;
453}
454
455
456/**
457 * Entry point for the plugin.
458 *
459 * @param cls NULL
460 * @return the exported block API
461 */
462void *
463libgnunet_test_transport_plugin_cmd_just_run_init (void *cls)
464{
465 struct GNUNET_TESTING_PluginFunctions *api;
466
467 GNUNET_log_setup ("simple-send",
468 "DEBUG",
469 NULL);
470
471 api = GNUNET_new (struct GNUNET_TESTING_PluginFunctions);
472 api->start_testcase = &start_testcase;
473 api->get_waiting_for_barriers = get_waiting_for_barriers;
474 return api;
475}
476
477
478/**
479 * Exit point from the plugin.
480 *
481 * @param cls the return value from #libgnunet_test_transport_plugin_just_run_init
482 * @return NULL
483 */
484void *
485libgnunet_test_transport_plugin_cmd_just_run_done (void *cls)
486{
487 struct GNUNET_TESTING_PluginFunctions *api = cls;
488
489 GNUNET_free (api);
490 return NULL;
491}
492
493
494/* end of plugin_cmd_simple_send.c */
diff --git a/src/transport/test_transport_plugin_cmd_nat_upnp.c b/src/transport/test_transport_plugin_cmd_nat_upnp.c
deleted file mode 100644
index 9d7c5d856..000000000
--- a/src/transport/test_transport_plugin_cmd_nat_upnp.c
+++ /dev/null
@@ -1,368 +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 testbed/plugin_cmd_simple_send.c
23 * @brief a plugin to provide the API for running test cases.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_barrier.h"
28#include "gnunet_testing_netjail_lib.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_transport_application_service.h"
31#include "transport-testing2.h"
32#include "transport-testing-cmds.h"
33#include "gnunet_testing_barrier.h"
34
35/**
36 * Generic logging shortcut
37 */
38#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
39
40#define BASE_DIR "testdir"
41
42#define TOPOLOGY_CONFIG "test_transport_simple_send_topo.conf"
43
44#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
45
46static struct GNUNET_TESTING_Command block_send;
47
48static struct GNUNET_TESTING_Command block_receive;
49
50static struct GNUNET_TESTING_Command connect_peers;
51
52static struct GNUNET_TESTING_Command local_prepared;
53
54static struct GNUNET_TESTING_Interpreter *is;
55
56/**
57 * Function called to check a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE being
58 * received.
59 *
60 */
61static int
62check_test (void *cls,
63 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
64{
65 return GNUNET_OK;
66}
67
68
69/**
70 * Function called to handle a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE
71 * being received.
72 *
73 */
74static void
75handle_test (void *cls,
76 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
77{
78 struct GNUNET_TESTING_AsyncContext *ac;
79
80 GNUNET_TESTING_get_trait_async_context (&block_receive,
81 &ac);
82 GNUNET_assert (NULL != ac);
83 if (NULL == ac->cont)
84 GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) ac);
85 else
86 GNUNET_TESTING_async_finish ((struct GNUNET_TESTING_AsyncContext *) ac);
87}
88
89
90struct GNUNET_TESTING_BarrierList*
91get_waiting_for_barriers ()
92{
93 struct GNUNET_TESTING_BarrierList*barriers;
94 struct GNUNET_TESTING_BarrierListEntry *ble;
95
96 barriers = GNUNET_new (struct GNUNET_TESTING_BarrierList);
97 ble = GNUNET_new (struct GNUNET_TESTING_BarrierListEntry);
98 ble->barrier_name = "ready-to-connect";
99 ble->expected_reaches = 1;
100 GNUNET_CONTAINER_DLL_insert (barriers->head,
101 barriers->tail,
102 ble);
103
104 ble = GNUNET_new (struct GNUNET_TESTING_BarrierListEntry);
105 ble->barrier_name = "test-case-finished";
106 ble->expected_reaches = 1;
107 GNUNET_CONTAINER_DLL_insert (barriers->head,
108 barriers->tail,
109 ble);
110 return barriers;
111}
112
113
114/**
115 * Function called with the final result of the test.
116 *
117 * @param cls the `struct MainParams`
118 * @param rv #GNUNET_OK if the test passed
119 */
120static void
121handle_result (void *cls,
122 enum GNUNET_GenericReturnValue rv)
123{
124 struct TestState *ts = cls;
125
126 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
127 "Local test exits with status %d\n",
128 rv);
129
130 ts->finished_cb (rv);
131 GNUNET_free (ts->testdir);
132 GNUNET_free (ts->cfgname);
133 GNUNET_TESTING_free_topology (ts->topology);
134 GNUNET_free (ts);
135}
136
137
138/**
139 * Callback from start peer cmd for signaling a peer got connected.
140 *
141 */
142static void *
143notify_connect (struct GNUNET_TESTING_Interpreter *is,
144 const struct GNUNET_PeerIdentity *peer)
145{
146 const struct ConnectPeersState *cps;
147 const struct GNUNET_TESTING_Command *cmd;
148
149 cmd = GNUNET_TESTING_interpreter_lookup_command (is,
150 "connect-peers");
151 GNUNET_TRANSPORT_get_trait_connect_peer_state (cmd,
152 &cps);
153 void *ret = NULL;
154
155 cps->notify_connect (is,
156 peer);
157 return ret;
158}
159
160
161/**
162 * Function to start a local test case.
163 *
164 * @param write_message Callback to send a message to the master loop.
165 * @param router_ip Global address of the network namespace.
166 * @param node_ip The IP address of the node.
167 * @param m The number of the node in a network namespace.
168 * @param n The number of the network namespace.
169 * @param local_m The number of nodes in a network namespace.
170 * @param topology_data A file name for the file containing the topology configuration, or a string containing
171 * the topology configuration.
172 * @param read_file If read_file is GNUNET_YES this string is the filename for the topology configuration,
173 * if read_file is GNUNET_NO the string contains the topology configuration.
174 * @param finish_cb Callback function which writes a message from the helper process running on a netjail
175 * node to the master process * signaling that the test case running on the netjail node finished.
176 * @return Returns the struct GNUNET_TESTING_Interpreter of the command loop running on this netjail node.
177 */
178static struct GNUNET_TESTING_Interpreter *
179start_testcase (GNUNET_TESTING_cmd_helper_write_cb write_message,
180 const char *router_ip,
181 const char *node_ip,
182 const char *m,
183 const char *n,
184 const char *local_m,
185 const char *topology_data,
186 unsigned int *read_file,
187 GNUNET_TESTING_cmd_helper_finish_cb finished_cb)
188{
189
190 unsigned int n_int;
191 unsigned int m_int;
192 unsigned int local_m_int;
193 unsigned int num;
194 struct TestState *ts = GNUNET_new (struct TestState);
195 struct GNUNET_TESTING_NetjailTopology *topology;
196 unsigned int sscanf_ret = 0;
197
198 ts->finished_cb = finished_cb;
199 LOG (GNUNET_ERROR_TYPE_ERROR,
200 "n %s m %s\n",
201 n,
202 m);
203
204 if (GNUNET_YES == *read_file)
205 {
206 LOG (GNUNET_ERROR_TYPE_DEBUG,
207 "read from file\n");
208 topology = GNUNET_TESTING_get_topo_from_file (topology_data);
209 }
210 else
211 topology = GNUNET_TESTING_get_topo_from_string (topology_data);
212
213 ts->topology = topology;
214
215 errno = 0;
216 sscanf_ret = sscanf (m, "%u", &m_int);
217 if (errno != 0)
218 {
219 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
220 }
221 GNUNET_assert (0 < sscanf_ret);
222 errno = 0;
223 sscanf_ret = sscanf (n, "%u", &n_int);
224 if (errno != 0)
225 {
226 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
227 }
228 GNUNET_assert (0 < sscanf_ret);
229 errno = 0;
230 sscanf_ret = sscanf (local_m, "%u", &local_m_int);
231 if (errno != 0)
232 {
233 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
234 }
235 GNUNET_assert (0 < sscanf_ret);
236
237 if (0 == n_int)
238 num = m_int;
239 else
240 num = (n_int - 1) * local_m_int + m_int + topology->nodes_x;
241
242 block_send = GNUNET_TESTING_cmd_block_until_external_trigger (
243 "block");
244 block_receive = GNUNET_TESTING_cmd_block_until_external_trigger (
245 "block-receive");
246 connect_peers = GNUNET_TRANSPORT_cmd_connect_peers ("connect-peers",
247 "start-peer",
248 "system-create",
249 num,
250 topology,
251 0,
252 GNUNET_YES);
253 local_prepared = GNUNET_TESTING_cmd_local_test_prepared (
254 "local-test-prepared",
255 write_message);
256
257
258 GNUNET_asprintf (&ts->cfgname,
259 "test_transport_api2_tcp_node1.conf");
260
261 LOG (GNUNET_ERROR_TYPE_DEBUG,
262 "plugin cfgname: %s\n",
263 ts->cfgname);
264
265 LOG (GNUNET_ERROR_TYPE_DEBUG,
266 "node ip: %s\n",
267 node_ip);
268
269 GNUNET_asprintf (&ts->testdir,
270 "%s%s%s",
271 BASE_DIR,
272 m,
273 n);
274
275 struct GNUNET_MQ_MessageHandler handlers[] = {
276 GNUNET_MQ_hd_var_size (test,
277 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
278 struct GNUNET_TRANSPORT_TESTING_TestMessage,
279 ts),
280 GNUNET_MQ_handler_end ()
281 };
282
283 struct GNUNET_TESTING_Command commands[] = {
284 GNUNET_TESTING_cmd_system_create ("system-create",
285 ts->testdir),
286 GNUNET_TRANSPORT_cmd_start_peer ("start-peer",
287 "system-create",
288 num,
289 node_ip,
290 handlers,
291 ts->cfgname,
292 notify_connect,
293 GNUNET_NO),
294 GNUNET_TESTING_cmd_barrier_reached ("ready-to-connect-reached",
295 "ready-to-connect",
296 GNUNET_NO,
297 num,
298 GNUNET_NO,
299 write_message),
300 connect_peers,
301 GNUNET_TRANSPORT_cmd_send_simple ("send-simple",
302 "start-peer",
303 "system-create",
304 num,
305 topology),
306 block_receive,
307 GNUNET_TESTING_cmd_barrier_reached ("test-case-finished-reached",
308 "test-case-finished",
309 GNUNET_NO,
310 num,
311 GNUNET_NO,
312 write_message),
313 GNUNET_TRANSPORT_cmd_stop_peer ("stop-peer",
314 "start-peer"),
315 GNUNET_TESTING_cmd_system_destroy ("system-destroy",
316 "system-create"),
317 GNUNET_TESTING_cmd_end ()
318 };
319
320 ts->write_message = write_message;
321
322 is = GNUNET_TESTING_run (commands,
323 TIMEOUT,
324 &handle_result,
325 ts);
326 return is;
327}
328
329
330/**
331 * Entry point for the plugin.
332 *
333 * @param cls NULL
334 * @return the exported block API
335 */
336void *
337libgnunet_test_transport_plugin_cmd_nat_upnp_init (void *cls)
338{
339 struct GNUNET_TESTING_PluginFunctions *api;
340
341 GNUNET_log_setup ("simple-send",
342 "DEBUG",
343 NULL);
344
345 api = GNUNET_new (struct GNUNET_TESTING_PluginFunctions);
346 api->start_testcase = &start_testcase;
347 api->get_waiting_for_barriers = get_waiting_for_barriers;
348 return api;
349}
350
351
352/**
353 * Exit point from the plugin.
354 *
355 * @param cls the return value from #libgnunet_test_transport_plugin_nat_upnp_init
356 * @return NULL
357 */
358void *
359libgnunet_test_transport_plugin_cmd_nat_upnp_done (void *cls)
360{
361 struct GNUNET_TESTING_PluginFunctions *api = cls;
362
363 GNUNET_free (api);
364 return NULL;
365}
366
367
368/* end of plugin_cmd_simple_send.c */
diff --git a/src/transport/test_transport_plugin_cmd_simple_send.c b/src/transport/test_transport_plugin_cmd_simple_send.c
deleted file mode 100644
index c6d75cce4..000000000
--- a/src/transport/test_transport_plugin_cmd_simple_send.c
+++ /dev/null
@@ -1,377 +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 testbed/plugin_cmd_simple_send.c
23 * @brief a plugin to provide the API for running test cases.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_barrier.h"
28#include "gnunet_testing_netjail_lib.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_transport_application_service.h"
31#include "transport-testing2.h"
32#include "transport-testing-cmds.h"
33#include "gnunet_testing_barrier.h"
34
35/**
36 * Generic logging shortcut
37 */
38#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
39
40#define BASE_DIR "testdir"
41
42#define TOPOLOGY_CONFIG "test_transport_simple_send_topo.conf"
43
44#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
45
46static struct GNUNET_TESTING_Command block_send;
47
48static struct GNUNET_TESTING_Command block_receive;
49
50static struct GNUNET_TESTING_Command connect_peers;
51
52static struct GNUNET_TESTING_Command local_prepared;
53
54static struct GNUNET_TESTING_Interpreter *is;
55
56/**
57 * Function called to check a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE being
58 * received.
59 *
60 */
61static int
62check_test (void *cls,
63 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
64{
65 return GNUNET_OK;
66}
67
68
69/**
70 * Function called to handle a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE
71 * being received.
72 *
73 */
74static void
75handle_test (void *cls,
76 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
77{
78 struct GNUNET_TESTING_AsyncContext *ac;
79
80 GNUNET_TESTING_get_trait_async_context (&block_receive,
81 &ac);
82 GNUNET_assert (NULL != ac);
83 if (NULL == ac->cont)
84 GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) ac);
85 else
86 GNUNET_TESTING_async_finish ((struct GNUNET_TESTING_AsyncContext *) ac);
87}
88
89
90struct GNUNET_TESTING_BarrierList *
91get_waiting_for_barriers ()
92{
93 // No Barrier
94 return GNUNET_new (struct GNUNET_TESTING_BarrierList);
95}
96
97
98/**
99 * Callback to set the flag indicating all peers started. Will be called via the plugin api.
100 *
101 */
102static void
103all_peers_started ()
104{
105 struct GNUNET_TESTING_AsyncContext *ac;
106
107 GNUNET_TESTING_get_trait_async_context (&block_send,
108 &ac);
109 GNUNET_assert (NULL != ac);
110 if (NULL == ac->cont)
111 GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) ac);
112 else
113 GNUNET_TESTING_async_finish ((struct GNUNET_TESTING_AsyncContext *) ac);
114}
115
116
117/**
118 * Function called with the final result of the test.
119 *
120 * @param cls the `struct MainParams`
121 * @param rv #GNUNET_OK if the test passed
122 */
123static void
124handle_result (void *cls,
125 enum GNUNET_GenericReturnValue rv)
126{
127 struct TestState *ts = cls;
128
129 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
130 "Local test exits with status %d\n",
131 rv);
132
133 ts->finished_cb (rv);
134 GNUNET_free (ts->testdir);
135 GNUNET_free (ts->cfgname);
136 GNUNET_TESTING_free_topology (ts->topology);
137 GNUNET_free (ts);
138}
139
140
141/**
142 * Callback from start peer cmd for signaling a peer got connected.
143 *
144 */
145static void *
146notify_connect (struct GNUNET_TESTING_Interpreter *is,
147 const struct GNUNET_PeerIdentity *peer)
148{
149 const struct ConnectPeersState *cps;
150 const struct GNUNET_TESTING_Command *cmd;
151
152 cmd = GNUNET_TESTING_interpreter_lookup_command (is,
153 "connect-peers");
154 GNUNET_TRANSPORT_get_trait_connect_peer_state (cmd,
155 &cps);
156 void *ret = NULL;
157
158 cps->notify_connect (is,
159 peer);
160 return ret;
161}
162
163
164/**
165 * Callback to set the flag indicating all peers are prepared to finish. Will be called via the plugin api.
166 */
167static void
168all_local_tests_prepared ()
169{
170 const struct GNUNET_TESTING_LocalPreparedState *lfs;
171
172 GNUNET_TESTING_get_trait_local_prepared_state (&local_prepared,
173 &lfs);
174 GNUNET_assert (NULL != &lfs->ac);
175 if (NULL == lfs->ac.cont)
176 GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) &lfs->ac);
177 else
178 GNUNET_TESTING_async_finish ((struct
179 GNUNET_TESTING_AsyncContext *) &lfs->ac);
180}
181
182
183/**
184 * Function to start a local test case.
185 *
186 * @param write_message Callback to send a message to the master loop.
187 * @param router_ip Global address of the network namespace.
188 * @param node_ip The IP address of the node.
189 * @param m The number of the node in a network namespace.
190 * @param n The number of the network namespace.
191 * @param local_m The number of nodes in a network namespace.
192 */
193static struct GNUNET_TESTING_Interpreter *
194start_testcase (GNUNET_TESTING_cmd_helper_write_cb write_message,
195 const char *router_ip,
196 const char *node_ip,
197 const char *m,
198 const char *n,
199 const char *local_m,
200 const char *topology_data,
201 unsigned int *read_file,
202 GNUNET_TESTING_cmd_helper_finish_cb finished_cb)
203{
204
205 unsigned int n_int;
206 unsigned int m_int;
207 unsigned int local_m_int;
208 unsigned int num;
209 struct TestState *ts = GNUNET_new (struct TestState);
210 struct GNUNET_TESTING_NetjailTopology *topology;
211 unsigned int sscanf_ret = 0;
212
213 ts->finished_cb = finished_cb;
214 LOG (GNUNET_ERROR_TYPE_ERROR,
215 "n %s m %s\n",
216 n,
217 m);
218
219 if (GNUNET_YES == *read_file)
220 {
221 LOG (GNUNET_ERROR_TYPE_DEBUG,
222 "read from file\n");
223 topology = GNUNET_TESTING_get_topo_from_file (topology_data);
224 }
225 else
226 topology = GNUNET_TESTING_get_topo_from_string (topology_data);
227
228 ts->topology = topology;
229
230 errno = 0;
231 sscanf_ret = sscanf (m, "%u", &m_int);
232 if (errno != 0)
233 {
234 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
235 }
236 GNUNET_assert (0 < sscanf_ret);
237 errno = 0;
238 sscanf_ret = sscanf (n, "%u", &n_int);
239 if (errno != 0)
240 {
241 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
242 }
243 GNUNET_assert (0 < sscanf_ret);
244 errno = 0;
245 sscanf_ret = sscanf (local_m, "%u", &local_m_int);
246 if (errno != 0)
247 {
248 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
249 }
250 GNUNET_assert (0 < sscanf_ret);
251
252 if (0 == n_int)
253 num = m_int;
254 else
255 num = (n_int - 1) * local_m_int + m_int + topology->nodes_x;
256
257 block_send = GNUNET_TESTING_cmd_block_until_external_trigger (
258 "block");
259 block_receive = GNUNET_TESTING_cmd_block_until_external_trigger (
260 "block-receive");
261 connect_peers = GNUNET_TRANSPORT_cmd_connect_peers ("connect-peers",
262 "start-peer",
263 "system-create",
264 num,
265 topology,
266 0,
267 GNUNET_YES);
268 local_prepared = GNUNET_TESTING_cmd_local_test_prepared (
269 "local-test-prepared",
270 write_message);
271
272
273 GNUNET_asprintf (&ts->cfgname,
274 "test_transport_api2_tcp_node1.conf");
275
276 LOG (GNUNET_ERROR_TYPE_DEBUG,
277 "plugin cfgname: %s\n",
278 ts->cfgname);
279
280 LOG (GNUNET_ERROR_TYPE_DEBUG,
281 "node ip: %s\n",
282 node_ip);
283
284 GNUNET_asprintf (&ts->testdir,
285 "%s%s%s",
286 BASE_DIR,
287 m,
288 n);
289
290 struct GNUNET_MQ_MessageHandler handlers[] = {
291 GNUNET_MQ_hd_var_size (test,
292 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
293 struct GNUNET_TRANSPORT_TESTING_TestMessage,
294 ts),
295 GNUNET_MQ_handler_end ()
296 };
297
298 struct GNUNET_TESTING_Command commands[] = {
299 GNUNET_TESTING_cmd_system_create ("system-create",
300 ts->testdir),
301 GNUNET_TRANSPORT_cmd_start_peer ("start-peer",
302 "system-create",
303 num,
304 node_ip,
305 handlers,
306 ts->cfgname,
307 notify_connect,
308 GNUNET_NO),
309 GNUNET_TESTING_cmd_send_peer_ready ("send-peer-ready",
310 write_message),
311 block_send,
312 connect_peers,
313 GNUNET_TRANSPORT_cmd_send_simple ("send-simple",
314 "start-peer",
315 "system-create",
316 num,
317 topology),
318 block_receive,
319 local_prepared,
320 GNUNET_TRANSPORT_cmd_stop_peer ("stop-peer",
321 "start-peer"),
322 GNUNET_TESTING_cmd_system_destroy ("system-destroy",
323 "system-create"),
324 GNUNET_TESTING_cmd_end ()
325 };
326
327 ts->write_message = write_message;
328
329 is = GNUNET_TESTING_run (commands,
330 TIMEOUT,
331 &handle_result,
332 ts);
333 return is;
334}
335
336
337/**
338 * Entry point for the plugin.
339 *
340 * @param cls NULL
341 * @return the exported block API
342 */
343void *
344libgnunet_test_transport_plugin_cmd_simple_send_init (void *cls)
345{
346 struct GNUNET_TESTING_PluginFunctions *api;
347
348 GNUNET_log_setup ("simple-send",
349 "DEBUG",
350 NULL);
351
352 api = GNUNET_new (struct GNUNET_TESTING_PluginFunctions);
353 api->start_testcase = &start_testcase;
354 api->all_peers_started = &all_peers_started;
355 api->all_local_tests_prepared = all_local_tests_prepared;
356 api->get_waiting_for_barriers = get_waiting_for_barriers;
357 return api;
358}
359
360
361/**
362 * Exit point from the plugin.
363 *
364 * @param cls the return value from #libgnunet_test_transport_plugin_block_test_init
365 * @return NULL
366 */
367void *
368libgnunet_test_transport_plugin_cmd_simple_send_done (void *cls)
369{
370 struct GNUNET_TESTING_PluginFunctions *api = cls;
371
372 GNUNET_free (api);
373 return NULL;
374}
375
376
377/* end of plugin_cmd_simple_send.c */
diff --git a/src/transport/test_transport_plugin_cmd_simple_send_broadcast.c b/src/transport/test_transport_plugin_cmd_simple_send_broadcast.c
deleted file mode 100644
index d2870ab34..000000000
--- a/src/transport/test_transport_plugin_cmd_simple_send_broadcast.c
+++ /dev/null
@@ -1,402 +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 testbed/plugin_cmd_simple_send_broadcast.c
23 * @brief a plugin to provide the API for running test cases.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_barrier.h"
28#include "gnunet_testing_netjail_lib.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_transport_application_service.h"
31#include "transport-testing2.h"
32#include "transport-testing-cmds.h"
33#include "gnunet_testing_barrier.h"
34
35/**
36 * Generic logging shortcut
37 */
38#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
39
40#define BASE_DIR "testdir"
41
42#define TOPOLOGY_CONFIG "test_transport_simple_send_topo.conf"
43
44#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
45
46static struct GNUNET_TESTING_Command block_send;
47
48static struct GNUNET_TESTING_Command block_receive;
49
50static struct GNUNET_TESTING_Command connect_peers;
51
52static struct GNUNET_TESTING_Command local_prepared;
53
54static struct GNUNET_TESTING_Interpreter *is;
55
56/**
57 * Function called to check a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE being
58 * received.
59 *
60 */
61static int
62check_test (void *cls,
63 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
64{
65 return GNUNET_OK;
66}
67
68
69/**
70 * Function called to handle a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE
71 * being received.
72 *
73 */
74static void
75handle_test (void *cls,
76 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
77{
78 struct GNUNET_TESTING_AsyncContext *ac;
79
80 GNUNET_TESTING_get_trait_async_context (&block_receive,
81 &ac);
82 GNUNET_assert (NULL != ac);
83 if ((GNUNET_NO == ac->finished) && (NULL == ac->cont))
84 GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) ac);
85 else if (GNUNET_NO == ac->finished)
86 GNUNET_TESTING_async_finish ((struct GNUNET_TESTING_AsyncContext *) ac);
87}
88
89
90struct GNUNET_TESTING_BarrierList *
91get_waiting_for_barriers ()
92{
93 // No Barrier
94 return GNUNET_new (struct GNUNET_TESTING_BarrierList);
95}
96
97
98/**
99 * Callback to set the flag indicating all peers started. Will be called via the plugin api.
100 *
101 */
102static void
103all_peers_started ()
104{
105 struct GNUNET_TESTING_AsyncContext *ac;
106
107 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
108 "Received message\n");
109 GNUNET_TESTING_get_trait_async_context (&block_send,
110 &ac);
111 GNUNET_assert (NULL != ac);
112 if (NULL == ac->cont)
113 GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) ac);
114 else
115 GNUNET_TESTING_async_finish ((struct GNUNET_TESTING_AsyncContext *) ac);
116}
117
118
119/**
120 * Function called with the final result of the test.
121 *
122 * @param cls the `struct MainParams`
123 * @param rv #GNUNET_OK if the test passed
124 */
125static void
126handle_result (void *cls,
127 enum GNUNET_GenericReturnValue rv)
128{
129 struct TestState *ts = cls;
130
131 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
132 "Local test exits with status %d\n",
133 rv);
134 ts->finished_cb (rv);
135 GNUNET_free (ts->testdir);
136 GNUNET_free (ts->cfgname);
137 GNUNET_TESTING_free_topology (ts->topology);
138 GNUNET_free (ts);
139}
140
141
142/**
143 * Callback from start peer cmd for signaling a peer got connected.
144 *
145 */
146static void *
147notify_connect (struct GNUNET_TESTING_Interpreter *is,
148 const struct GNUNET_PeerIdentity *peer)
149{
150 struct GNUNET_TESTING_AsyncContext *ac;
151 void *ret = NULL;
152 const struct GNUNET_TESTING_Command *cmd;
153 struct GNUNET_TESTING_BlockState *bs;
154
155 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
156 "notify_connect\n");
157
158 GNUNET_TESTING_get_trait_async_context (&connect_peers,
159 &ac);
160
161 if (NULL != ac->is)
162 {
163 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
164 "notify_connect running\n");
165 GNUNET_assert (NULL != ac);
166 if (NULL == ac->cont)
167 GNUNET_TESTING_async_fail (ac);
168 else
169 GNUNET_TESTING_async_finish (ac);
170 }
171 else
172 {
173 cmd = GNUNET_TESTING_interpreter_lookup_future_command (is,
174 "connect-peers");
175
176 LOG (GNUNET_ERROR_TYPE_DEBUG,
177 "block state %s\n",
178 cmd->label);
179 GNUNET_TESTING_get_trait_block_state (
180 cmd,
181 &bs);
182
183 LOG (GNUNET_ERROR_TYPE_DEBUG,
184 "block state %u\n",
185 bs->asynchronous_finish);
186 bs->asynchronous_finish = GNUNET_YES;
187 LOG (GNUNET_ERROR_TYPE_DEBUG,
188 "block state %u\n",
189 bs->asynchronous_finish);
190 }
191
192 return ret;
193}
194
195
196/**
197 * Callback to set the flag indicating all peers are prepared to finish. Will be called via the plugin api.
198 */
199static void
200all_local_tests_prepared ()
201{
202 const struct GNUNET_TESTING_LocalPreparedState *lfs;
203
204 GNUNET_TESTING_get_trait_local_prepared_state (&local_prepared,
205 &lfs);
206 GNUNET_assert (NULL != &lfs->ac);
207 if (NULL == lfs->ac.cont)
208 GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) &lfs->ac);
209 else
210 GNUNET_TESTING_async_finish ((struct
211 GNUNET_TESTING_AsyncContext *) &lfs->ac);
212}
213
214
215/**
216 * Function to start a local test case.
217 *
218 * @param write_message Callback to send a message to the master loop.
219 * @param router_ip Global address of the network namespace.
220 * @param node_ip The IP address of the node.
221 * @param m The number of the node in a network namespace.
222 * @param n The number of the network namespace.
223 * @param local_m The number of nodes in a network namespace.
224 */
225static struct GNUNET_TESTING_Interpreter *
226start_testcase (GNUNET_TESTING_cmd_helper_write_cb write_message,
227 const char *router_ip,
228 const char *node_ip,
229 const char *m,
230 const char *n,
231 const char *local_m,
232 const char *topology_data,
233 unsigned int *read_file,
234 GNUNET_TESTING_cmd_helper_finish_cb finished_cb)
235{
236 unsigned int n_int;
237 unsigned int m_int;
238 unsigned int local_m_int;
239 unsigned int num;
240 struct TestState *ts = GNUNET_new (struct TestState);
241 struct GNUNET_TESTING_NetjailTopology *topology;
242 unsigned int sscanf_ret = 0;
243
244 ts->finished_cb = finished_cb;
245 LOG (GNUNET_ERROR_TYPE_ERROR,
246 "n %s m %s\n",
247 n,
248 m);
249
250 if (GNUNET_YES == *read_file)
251 {
252 LOG (GNUNET_ERROR_TYPE_DEBUG,
253 "read from file\n");
254 topology = GNUNET_TESTING_get_topo_from_file (topology_data);
255 }
256 else
257 topology = GNUNET_TESTING_get_topo_from_string (topology_data);
258
259 ts->topology = topology;
260
261 errno = 0;
262 sscanf_ret = sscanf (m, "%u", &m_int);
263 if (errno != 0)
264 {
265 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
266 }
267 GNUNET_assert (0 < sscanf_ret);
268 errno = 0;
269 sscanf_ret = sscanf (n, "%u", &n_int);
270 if (errno != 0)
271 {
272 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
273 }
274 GNUNET_assert (0 < sscanf_ret);
275 errno = 0;
276 sscanf_ret = sscanf (local_m, "%u", &local_m_int);
277 if (errno != 0)
278 {
279 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
280 }
281 GNUNET_assert (0 < sscanf_ret);
282
283 if (0 == n_int)
284 num = m_int;
285 else
286 num = (n_int - 1) * local_m_int + m_int + topology->nodes_x;
287
288 block_send = GNUNET_TESTING_cmd_block_until_external_trigger ("block");
289 block_receive = GNUNET_TESTING_cmd_block_until_external_trigger (
290 "block-receive");
291 connect_peers = GNUNET_TESTING_cmd_block_until_external_trigger (
292 "connect-peers");
293 local_prepared = GNUNET_TESTING_cmd_local_test_prepared (
294 "local-test-prepared",
295 write_message);
296
297
298 GNUNET_asprintf (&ts->cfgname,
299 "test_transport_api2_tcp_node1.conf");
300
301 LOG (GNUNET_ERROR_TYPE_DEBUG,
302 "plugin cfgname: %s\n",
303 ts->cfgname);
304
305 LOG (GNUNET_ERROR_TYPE_DEBUG,
306 "node ip: %s\n",
307 node_ip);
308
309 GNUNET_asprintf (&ts->testdir,
310 "%s%s%s",
311 BASE_DIR,
312 m,
313 n);
314
315 struct GNUNET_MQ_MessageHandler handlers[] = {
316 GNUNET_MQ_hd_var_size (test,
317 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
318 struct GNUNET_TRANSPORT_TESTING_TestMessage,
319 ts),
320 GNUNET_MQ_handler_end ()
321 };
322
323 struct GNUNET_TESTING_Command commands[] = {
324 GNUNET_TESTING_cmd_system_create ("system-create",
325 ts->testdir),
326 GNUNET_TRANSPORT_cmd_start_peer ("start-peer",
327 "system-create",
328 num,
329 node_ip,
330 handlers,
331 ts->cfgname,
332 notify_connect,
333 GNUNET_YES),
334 GNUNET_TESTING_cmd_send_peer_ready ("send-peer-ready",
335 write_message),
336 block_send,
337 connect_peers,
338 GNUNET_TRANSPORT_cmd_send_simple ("send-simple",
339 "start-peer",
340 "system-create",
341 num,
342 topology),
343 block_receive,
344 local_prepared,
345 GNUNET_TRANSPORT_cmd_stop_peer ("stop-peer",
346 "start-peer"),
347 GNUNET_TESTING_cmd_system_destroy ("system-destroy",
348 "system-create"),
349 GNUNET_TESTING_cmd_end ()
350 };
351
352 ts->write_message = write_message;
353
354 is = GNUNET_TESTING_run (commands,
355 TIMEOUT,
356 &handle_result,
357 ts);
358 return is;
359}
360
361
362/**
363 * Entry point for the plugin.
364 *
365 * @param cls NULL
366 * @return the exported block API
367 */
368void *
369libgnunet_test_transport_plugin_cmd_simple_send_broadcast_init (void *cls)
370{
371 struct GNUNET_TESTING_PluginFunctions *api;
372
373 GNUNET_log_setup ("simple-send",
374 "DEBUG",
375 NULL);
376
377 api = GNUNET_new (struct GNUNET_TESTING_PluginFunctions);
378 api->start_testcase = &start_testcase;
379 api->all_peers_started = &all_peers_started;
380 api->all_local_tests_prepared = all_local_tests_prepared;
381 api->get_waiting_for_barriers = get_waiting_for_barriers;
382 return api;
383}
384
385
386/**
387 * Exit point from the plugin.
388 *
389 * @param cls the return value from #libgnunet_test_transport_plugin_block_test_init
390 * @return NULL
391 */
392void *
393libgnunet_test_transport_plugin_cmd_simple_send_broadcast_done (void *cls)
394{
395 struct GNUNET_TESTING_PluginFunctions *api = cls;
396
397 GNUNET_free (api);
398 return NULL;
399}
400
401
402/* end of plugin_cmd_simple_send_broadcast.c */
diff --git a/src/transport/test_transport_plugin_cmd_simple_send_dv.c b/src/transport/test_transport_plugin_cmd_simple_send_dv.c
deleted file mode 100644
index d35672cd9..000000000
--- a/src/transport/test_transport_plugin_cmd_simple_send_dv.c
+++ /dev/null
@@ -1,434 +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 testbed/plugin_cmd_simple_send_broadcast.c
23 * @brief a plugin to provide the API for running test cases.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_barrier.h"
28#include "gnunet_testing_netjail_lib.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_transport_application_service.h"
31#include "transport-testing2.h"
32#include "transport-testing-cmds.h"
33#include "gnunet_testing_barrier.h"
34
35/**
36 * Generic logging shortcut
37 */
38#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
39
40#define BASE_DIR "testdir"
41
42#define TOPOLOGY_CONFIG "test_transport_simple_send_topo.conf"
43
44#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
45
46/**
47 * The number of messages received.
48 */
49static unsigned int number_received;
50
51static struct GNUNET_TESTING_Command block_send;
52
53static struct GNUNET_TESTING_Command block_receive;
54
55static struct GNUNET_TESTING_Command connect_peers;
56
57static struct GNUNET_TESTING_Command local_prepared;
58
59static struct GNUNET_TESTING_Command start_peer;
60
61static struct GNUNET_TESTING_Interpreter *is;
62
63/**
64 * Function called to check a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE being
65 * received.
66 *
67 */
68static int
69check_test (void *cls,
70 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
71{
72 GNUNET_assert (NULL != cls);
73 return GNUNET_OK;
74}
75
76
77/**
78 * Function called to handle a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE
79 * being received.
80 *
81 */
82static void
83handle_test (void *cls,
84 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
85{
86 struct GNUNET_PeerIdentity *peer = cls;
87 struct GNUNET_TESTING_AsyncContext *ac_block;
88 const struct GNUNET_CONTAINER_MultiShortmap *connected_peers_map;
89 unsigned int connected;
90 struct GNUNET_TESTING_BlockState *bs;
91 struct GNUNET_TRANSPORT_CoreHandle *ch;
92 const struct GNUNET_TESTING_StartPeerState *sps;
93
94
95 GNUNET_TRANSPORT_get_trait_state (&start_peer,
96 &sps);
97 ch = sps->th;
98 GNUNET_TRANSPORT_get_trait_connected_peers_map (&start_peer,
99 &connected_peers_map);
100
101 if (NULL != connected_peers_map)
102 {
103 connected = GNUNET_CONTAINER_multishortmap_size (
104 connected_peers_map);
105
106 number_received++;
107 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
108 "Received %u test message(s) from %s, %u connected peer(s)\n",
109 number_received,
110 GNUNET_i2s (peer),
111 connected);
112
113 GNUNET_TESTING_get_trait_async_context (&block_receive,
114 &ac_block);
115
116 if (connected == number_received)
117 {
118 if (NULL != ac_block->is)
119 {
120 GNUNET_assert (NULL != ac_block);
121 if (NULL == ac_block->cont)
122 GNUNET_TESTING_async_fail ((struct
123 GNUNET_TESTING_AsyncContext *) ac_block);
124 else
125 GNUNET_TESTING_async_finish ((struct
126 GNUNET_TESTING_AsyncContext *) ac_block);
127 }
128 else
129 {
130 GNUNET_TESTING_get_trait_block_state (
131 &block_receive,
132 &bs);
133 bs->asynchronous_finish = GNUNET_YES;
134 }
135
136 }
137 }
138 GNUNET_TRANSPORT_core_receive_continue (ch, peer);
139}
140
141
142struct GNUNET_TESTING_BarrierList *
143get_waiting_for_barriers ()
144{
145 // No Barrier
146 return GNUNET_new (struct GNUNET_TESTING_BarrierList);
147}
148
149
150/**
151 * Callback to set the flag indicating all peers started. Will be called via the plugin api.
152 *
153 */
154static void
155all_peers_started ()
156{
157 struct GNUNET_TESTING_AsyncContext *ac;
158
159 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
160 "Received message\n");
161 GNUNET_TESTING_get_trait_async_context (&block_send,
162 &ac);
163 GNUNET_assert (NULL != ac);
164 if (NULL == ac->cont)
165 GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) ac);
166 else
167 GNUNET_TESTING_async_finish ((struct GNUNET_TESTING_AsyncContext *) ac);
168}
169
170
171/**
172 * Function called with the final result of the test.
173 *
174 * @param cls the `struct MainParams`
175 * @param rv #GNUNET_OK if the test passed
176 */
177static void
178handle_result (void *cls,
179 enum GNUNET_GenericReturnValue rv)
180{
181 struct TestState *ts = cls;
182
183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
184 "Local test exits with status %d\n",
185 rv);
186 ts->finished_cb (rv);
187 GNUNET_free (ts->testdir);
188 GNUNET_free (ts->cfgname);
189 GNUNET_TESTING_free_topology (ts->topology);
190 GNUNET_free (ts);
191}
192
193
194/**
195 * Callback from start peer cmd for signaling a peer got connected.
196 *
197 */
198static void *
199notify_connect (struct GNUNET_TESTING_Interpreter *is,
200 const struct GNUNET_PeerIdentity *peer)
201{
202 const struct ConnectPeersState *cps;
203 const struct GNUNET_TESTING_Command *cmd;
204
205 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
206 "notify_connect peer %s\n",
207 GNUNET_i2s (peer));
208 // FIXME: modifying future is a bit unclean, not easy to follow logic;
209 // might be better to when reaching the future command to look into
210 // the past...
211 cmd = GNUNET_TESTING_interpreter_lookup_command_all (is,
212 "connect-peers");
213 // FIXME: check return value!
214 GNUNET_TRANSPORT_get_trait_connect_peer_state (cmd,
215 &cps);
216 cps->notify_connect (is,
217 peer);
218 return NULL;
219}
220
221
222/**
223 * Callback to set the flag indicating all peers are prepared to finish. Will be called via the plugin api.
224 */
225static void
226all_local_tests_prepared ()
227{
228 const struct GNUNET_TESTING_LocalPreparedState *lfs;
229
230 GNUNET_TESTING_get_trait_local_prepared_state (&local_prepared,
231 &lfs);
232 GNUNET_assert (NULL != &lfs->ac);
233 if (NULL == lfs->ac.cont)
234 GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) &lfs->ac);
235 else
236 GNUNET_TESTING_async_finish ((struct
237 GNUNET_TESTING_AsyncContext *) &lfs->ac);
238}
239
240
241/**
242 * Function to start a local test case.
243 *
244 * @param write_message Callback to send a message to the master loop.
245 * @param router_ip Global address of the network namespace.
246 * @param node_ip The IP address of the node.
247 * @param m The number of the node in a network namespace.
248 * @param n The number of the network namespace.
249 * @param local_m The number of nodes in a network namespace.
250 */
251static struct GNUNET_TESTING_Interpreter *
252start_testcase (GNUNET_TESTING_cmd_helper_write_cb write_message,
253 const char *router_ip,
254 const char *node_ip,
255 const char *m,
256 const char *n,
257 const char *local_m,
258 const char *topology_data,
259 unsigned int *read_file,
260 GNUNET_TESTING_cmd_helper_finish_cb finished_cb)
261{
262 unsigned int n_int;
263 unsigned int m_int;
264 unsigned int local_m_int;
265 unsigned int num;
266 struct TestState *ts = GNUNET_new (struct TestState);
267 struct GNUNET_TESTING_NetjailTopology *topology;
268 struct GNUNET_MQ_MessageHandler handlers[] = {
269 GNUNET_MQ_hd_var_size (test,
270 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
271 struct GNUNET_TRANSPORT_TESTING_TestMessage,
272 ts),
273 GNUNET_MQ_handler_end ()
274 };
275 unsigned int sscanf_ret = 0;
276
277 ts->finished_cb = finished_cb;
278 LOG (GNUNET_ERROR_TYPE_ERROR,
279 "n %s m %s\n",
280 n,
281 m);
282
283 if (GNUNET_YES == *read_file)
284 {
285 LOG (GNUNET_ERROR_TYPE_DEBUG,
286 "read from file\n");
287 topology = GNUNET_TESTING_get_topo_from_file (topology_data);
288 }
289 else
290 topology = GNUNET_TESTING_get_topo_from_string (topology_data);
291
292 ts->topology = topology;
293
294 errno = 0;
295 sscanf_ret = sscanf (m, "%u", &m_int);
296 if (errno != 0)
297 {
298 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
299 }
300 GNUNET_assert (0 < sscanf_ret);
301 errno = 0;
302 sscanf_ret = sscanf (n, "%u", &n_int);
303 if (errno != 0)
304 {
305 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
306 }
307 GNUNET_assert (0 < sscanf_ret);
308 errno = 0;
309 sscanf_ret = sscanf (local_m, "%u", &local_m_int);
310 if (errno != 0)
311 {
312 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
313 }
314 GNUNET_assert (0 < sscanf_ret);
315
316 if (0 == n_int)
317 num = m_int;
318 else
319 num = (n_int - 1) * local_m_int + m_int + topology->nodes_x;
320
321 block_send = GNUNET_TESTING_cmd_block_until_external_trigger ("block");
322 block_receive = GNUNET_TESTING_cmd_block_until_external_trigger (
323 "block-receive");
324 connect_peers = GNUNET_TRANSPORT_cmd_connect_peers (
325 "connect-peers",
326 "start-peer",
327 "system-create",
328 num,
329 topology,
330 topology->additional_connects,
331 GNUNET_YES);
332 local_prepared = GNUNET_TESTING_cmd_local_test_prepared (
333 "local-test-prepared",
334 write_message);
335
336
337 GNUNET_asprintf (&ts->cfgname,
338 "test_transport_api2_tcp_node1.conf");
339
340 LOG (GNUNET_ERROR_TYPE_DEBUG,
341 "plugin cfgname: %s\n",
342 ts->cfgname);
343
344 LOG (GNUNET_ERROR_TYPE_DEBUG,
345 "node ip: %s\n",
346 node_ip);
347
348 GNUNET_asprintf (&ts->testdir,
349 "%s%s%s",
350 BASE_DIR,
351 m,
352 n);
353
354 start_peer = GNUNET_TRANSPORT_cmd_start_peer ("start-peer",
355 "system-create",
356 num,
357 node_ip,
358 handlers,
359 ts->cfgname,
360 notify_connect,
361 GNUNET_NO);
362 struct GNUNET_TESTING_Command commands[] = {
363 GNUNET_TESTING_cmd_system_create ("system-create",
364 ts->testdir),
365 start_peer,
366 GNUNET_TESTING_cmd_send_peer_ready ("send-peer-ready",
367 write_message),
368 block_send,
369 connect_peers,
370 GNUNET_TRANSPORT_cmd_send_simple ("send-simple",
371 "start-peer",
372 "system-create",
373 num,
374 topology),
375 block_receive,
376 local_prepared,
377 GNUNET_TRANSPORT_cmd_stop_peer ("stop-peer",
378 "start-peer"),
379 GNUNET_TESTING_cmd_system_destroy ("system-destroy",
380 "system-create"),
381 GNUNET_TESTING_cmd_end ()
382 };
383
384 ts->write_message = write_message;
385
386 is = GNUNET_TESTING_run (commands,
387 TIMEOUT,
388 &handle_result,
389 ts);
390 return is;
391}
392
393
394/**
395 * Entry point for the plugin.
396 *
397 * @param cls NULL
398 * @return the exported block API
399 */
400void *
401libgnunet_test_transport_plugin_cmd_simple_send_dv_init (void *cls)
402{
403 struct GNUNET_TESTING_PluginFunctions *api;
404
405 GNUNET_log_setup ("simple-send",
406 "DEBUG",
407 NULL);
408
409 api = GNUNET_new (struct GNUNET_TESTING_PluginFunctions);
410 api->start_testcase = &start_testcase;
411 api->all_peers_started = &all_peers_started;
412 api->all_local_tests_prepared = all_local_tests_prepared;
413 api->get_waiting_for_barriers = get_waiting_for_barriers;
414 return api;
415}
416
417
418/**
419 * Exit point from the plugin.
420 *
421 * @param cls the return value from #libgnunet_test_transport_plugin_block_test_init
422 * @return NULL
423 */
424void *
425libgnunet_test_transport_plugin_cmd_simple_send_dv_done (void *cls)
426{
427 struct GNUNET_TESTING_PluginFunctions *api = cls;
428
429 GNUNET_free (api);
430 return NULL;
431}
432
433
434/* end of plugin_cmd_simple_send_broadcast.c */
diff --git a/src/transport/test_transport_plugin_cmd_simple_send_performance.c b/src/transport/test_transport_plugin_cmd_simple_send_performance.c
deleted file mode 100644
index 2baa7b5b4..000000000
--- a/src/transport/test_transport_plugin_cmd_simple_send_performance.c
+++ /dev/null
@@ -1,480 +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 testbed/plugin_cmd_simple_send.c
23 * @brief a plugin to provide the API for running test cases.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_barrier.h"
28#include "gnunet_testing_netjail_lib.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_transport_application_service.h"
31#include "transport-testing2.h"
32#include "transport-testing-cmds.h"
33#include "gnunet_testing_barrier.h"
34
35/**
36 * Generic logging shortcut
37 */
38#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
39
40#define BASE_DIR "testdir"
41
42#define TOPOLOGY_CONFIG "test_transport_simple_send_topo.conf"
43
44#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
45
46#define MAX_RECEIVED 1000
47
48#define MESSAGE_SIZE 65000
49
50static struct GNUNET_TESTING_Command block_send;
51
52static struct GNUNET_TESTING_Command block_receive;
53
54static struct GNUNET_TESTING_Command connect_peers;
55
56static struct GNUNET_TESTING_Command local_prepared;
57
58static struct GNUNET_TESTING_Command start_peer;
59
60static struct GNUNET_TESTING_Interpreter *is;
61
62static struct GNUNET_CONTAINER_MultiPeerMap *senders;
63
64struct Sender
65{
66 /**
67 * Number of received messages from sender.
68 */
69 unsigned long long num_received;
70
71 /**
72 * Sample mean time the message traveled.
73 */
74 struct GNUNET_TIME_Relative mean_time;
75
76 /**
77 * Time the first message was send.
78 */
79 struct GNUNET_TIME_Absolute time_first;
80};
81
82/**
83 * Function called to check a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE being
84 * received.
85 *
86 */
87static int
88check_test (void *cls,
89 const struct
90 GNUNET_TRANSPORT_TESTING_PerformanceTestMessage *message)
91{
92 return GNUNET_OK;
93}
94
95
96/**
97 * Function called to handle a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE
98 * being received.
99 *
100 */
101static void
102handle_test (void *cls,
103 const struct
104 GNUNET_TRANSPORT_TESTING_PerformanceTestMessage *message)
105{
106 struct GNUNET_PeerIdentity *peer = cls;
107 struct GNUNET_TESTING_AsyncContext *ac;
108 struct Sender *sender;
109 struct GNUNET_TIME_Absolute time_send;
110 struct GNUNET_TIME_Absolute now;
111 struct GNUNET_TIME_Relative time_traveled;
112 uint32_t num;
113 struct GNUNET_TRANSPORT_CoreHandle *ch;
114 const struct GNUNET_TESTING_StartPeerState *sps;
115
116
117 GNUNET_TRANSPORT_get_trait_state (&start_peer,
118 &sps);
119 ch = sps->th;
120 num = ntohl (message->num);
121 GNUNET_TESTING_get_trait_async_context (&block_receive,
122 &ac);
123 GNUNET_assert (NULL != ac);
124
125 sender = GNUNET_CONTAINER_multipeermap_get (senders, peer);
126
127 now = GNUNET_TIME_absolute_get ();
128 time_send = GNUNET_TIME_absolute_ntoh (message->time_send);
129
130 time_traveled = GNUNET_TIME_absolute_get_difference (time_send, now);
131
132 if (NULL == sender)
133 {
134 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
135 "time traveled init %s\n",
136 GNUNET_i2s (peer));
137 sender = GNUNET_new (struct Sender);
138 sender->time_first = time_send;
139 sender->mean_time = GNUNET_TIME_UNIT_ZERO;
140 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (senders,
141 peer, sender,
142 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
143 }
144
145 if (GNUNET_TIME_UNIT_ZERO.rel_value_us == sender->mean_time.rel_value_us)
146 {
147 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
148 "time traveld mean zero\n");
149 sender->mean_time = time_traveled;
150 }
151 else
152 {
153 double factor = (double) sender->num_received
154 / ((double) sender->num_received + 1.0);
155 struct GNUNET_TIME_Relative s1;
156 struct GNUNET_TIME_Relative s2;
157
158 s1 = GNUNET_TIME_relative_multiply (sender->mean_time,
159 factor);
160 s2 = GNUNET_TIME_relative_divide (time_traveled,
161 sender->num_received + 1);
162 sender->mean_time = GNUNET_TIME_relative_add (s1, s2);
163 }
164
165 sender->num_received++;
166
167 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
168 "time traveled: %llu\n",
169 time_traveled.rel_value_us);
170 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
171 "mean time traveled: %s %llu messages received with message number %u\n",
172 GNUNET_STRINGS_relative_time_to_string (sender->mean_time,
173 GNUNET_NO),
174 sender->num_received,
175 num);
176 if (floor (MAX_RECEIVED * (1 - 1.0 / 200)) < sender->num_received && NULL ==
177 ac->cont)
178 {
179 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
180 "time traveled failed\n");
181 // GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) ac);
182 }
183 else if (floor (MAX_RECEIVED * (1 - 1.0 / 200)) < sender->num_received &&
184 GNUNET_NO == ac->finished)
185 {
186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
187 "time traveled finish\n");
188 GNUNET_TESTING_async_finish ((struct GNUNET_TESTING_AsyncContext *) ac);
189 }
190 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
191 "time traveled end\n");
192 GNUNET_TRANSPORT_core_receive_continue (ch, peer);
193}
194
195
196struct GNUNET_TESTING_BarrierList*
197get_waiting_for_barriers ()
198{
199 struct GNUNET_TESTING_BarrierList*barriers;
200 struct GNUNET_TESTING_BarrierListEntry *ble;
201
202 barriers = GNUNET_new (struct GNUNET_TESTING_BarrierList);
203 ble = GNUNET_new (struct GNUNET_TESTING_BarrierListEntry);
204 ble->barrier_name = "ready-to-connect";
205 ble->expected_reaches = 1;
206 GNUNET_CONTAINER_DLL_insert (barriers->head,
207 barriers->tail,
208 ble);
209
210 ble = GNUNET_new (struct GNUNET_TESTING_BarrierListEntry);
211 ble->barrier_name = "test-case-finished";
212 ble->expected_reaches = 1;
213 GNUNET_CONTAINER_DLL_insert (barriers->head,
214 barriers->tail,
215 ble);
216 return barriers;
217}
218
219
220/**
221 * Function called with the final result of the test.
222 *
223 * @param cls the `struct MainParams`
224 * @param rv #GNUNET_OK if the test passed
225 */
226static void
227handle_result (void *cls,
228 enum GNUNET_GenericReturnValue rv)
229{
230 struct TestState *ts = cls;
231
232 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
233 "Local test exits with status %d\n",
234 rv);
235
236 ts->finished_cb (rv);
237 GNUNET_free (ts->testdir);
238 GNUNET_free (ts->cfgname);
239 GNUNET_TESTING_free_topology (ts->topology);
240 GNUNET_free (ts);
241}
242
243
244/**
245 * Callback from start peer cmd for signaling a peer got connected.
246 *
247 */
248static void *
249notify_connect (struct GNUNET_TESTING_Interpreter *is,
250 const struct GNUNET_PeerIdentity *peer)
251{
252 const struct ConnectPeersState *cps;
253 const struct GNUNET_TESTING_Command *cmd;
254
255 cmd = GNUNET_TESTING_interpreter_lookup_command (is,
256 "connect-peers");
257 GNUNET_TRANSPORT_get_trait_connect_peer_state (cmd,
258 &cps);
259 void *ret = NULL;
260
261 cps->notify_connect (is,
262 peer);
263 return ret;
264}
265
266
267/**
268 * Function to start a local test case.
269 *
270 * @param write_message Callback to send a message to the master loop.
271 * @param router_ip Global address of the network namespace.
272 * @param node_ip The IP address of the node.
273 * @param m The number of the node in a network namespace.
274 * @param n The number of the network namespace.
275 * @param local_m The number of nodes in a network namespace.
276 * @param topology_data A file name for the file containing the topology configuration, or a string containing
277 * the topology configuration.
278 * @param read_file If read_file is GNUNET_YES this string is the filename for the topology configuration,
279 * if read_file is GNUNET_NO the string contains the topology configuration.
280 * @param finish_cb Callback function which writes a message from the helper process running on a netjail
281 * node to the master process * signaling that the test case running on the netjail node finished.
282 * @return Returns the struct GNUNET_TESTING_Interpreter of the command loop running on this netjail node.
283 */
284static struct GNUNET_TESTING_Interpreter *
285start_testcase (GNUNET_TESTING_cmd_helper_write_cb write_message,
286 const char *router_ip,
287 const char *node_ip,
288 const char *m,
289 const char *n,
290 const char *local_m,
291 const char *topology_data,
292 unsigned int *read_file,
293 GNUNET_TESTING_cmd_helper_finish_cb finished_cb)
294{
295
296 unsigned int n_int;
297 unsigned int m_int;
298 unsigned int local_m_int;
299 unsigned int num;
300 struct TestState *ts = GNUNET_new (struct TestState);
301 struct GNUNET_TESTING_NetjailTopology *topology;
302 unsigned int sscanf_ret = 0;
303
304 senders = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO);
305 ts->finished_cb = finished_cb;
306 LOG (GNUNET_ERROR_TYPE_ERROR,
307 "n %s m %s\n",
308 n,
309 m);
310
311 if (GNUNET_YES == *read_file)
312 {
313 LOG (GNUNET_ERROR_TYPE_DEBUG,
314 "read from file\n");
315 topology = GNUNET_TESTING_get_topo_from_file (topology_data);
316 }
317 else
318 topology = GNUNET_TESTING_get_topo_from_string (topology_data);
319
320 ts->topology = topology;
321
322 errno = 0;
323 sscanf_ret = sscanf (m, "%u", &m_int);
324 if (errno != 0)
325 {
326 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
327 }
328 GNUNET_assert (0 < sscanf_ret);
329 errno = 0;
330 sscanf_ret = sscanf (n, "%u", &n_int);
331 if (errno != 0)
332 {
333 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
334 }
335 GNUNET_assert (0 < sscanf_ret);
336 errno = 0;
337 sscanf_ret = sscanf (local_m, "%u", &local_m_int);
338 if (errno != 0)
339 {
340 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
341 }
342 GNUNET_assert (0 < sscanf_ret);
343
344 if (0 == n_int)
345 num = m_int;
346 else
347 num = (n_int - 1) * local_m_int + m_int + topology->nodes_x;
348
349 block_send = GNUNET_TESTING_cmd_block_until_external_trigger (
350 "block");
351 block_receive = GNUNET_TESTING_cmd_block_until_external_trigger (
352 "block-receive");
353 connect_peers = GNUNET_TRANSPORT_cmd_connect_peers ("connect-peers",
354 "start-peer",
355 "system-create",
356 num,
357 topology,
358 0,
359 GNUNET_YES);
360 local_prepared = GNUNET_TESTING_cmd_local_test_prepared (
361 "local-test-prepared",
362 write_message);
363
364
365 GNUNET_asprintf (&ts->cfgname,
366 "test_transport_api2_tcp_node1.conf");
367
368 LOG (GNUNET_ERROR_TYPE_DEBUG,
369 "plugin cfgname: %s\n",
370 ts->cfgname);
371
372 LOG (GNUNET_ERROR_TYPE_DEBUG,
373 "node ip: %s\n",
374 node_ip);
375
376 GNUNET_asprintf (&ts->testdir,
377 "%s%s%s",
378 BASE_DIR,
379 m,
380 n);
381
382 struct GNUNET_MQ_MessageHandler handlers[] = {
383 GNUNET_MQ_hd_var_size (test,
384 GNUNET_TRANSPORT_TESTING_SIMPLE_PERFORMANCE_MTYPE,
385 struct
386 GNUNET_TRANSPORT_TESTING_PerformanceTestMessage,
387 ts),
388 GNUNET_MQ_handler_end ()
389 };
390
391 start_peer = GNUNET_TRANSPORT_cmd_start_peer ("start-peer",
392 "system-create",
393 num,
394 node_ip,
395 handlers,
396 ts->cfgname,
397 notify_connect,
398 GNUNET_NO);
399
400 struct GNUNET_TESTING_Command commands[] = {
401 GNUNET_TESTING_cmd_system_create ("system-create",
402 ts->testdir),
403 start_peer,
404 GNUNET_TESTING_cmd_barrier_reached ("ready-to-connect-reached",
405 "ready-to-connect",
406 GNUNET_NO,
407 num,
408 GNUNET_NO,
409 write_message),
410 connect_peers,
411 GNUNET_TRANSPORT_cmd_send_simple_performance ("send-simple",
412 "start-peer",
413 "system-create",
414 num,
415 MESSAGE_SIZE,
416 MAX_RECEIVED,
417 topology),
418 block_receive,
419 GNUNET_TESTING_cmd_barrier_reached ("test-case-finished-reached",
420 "test-case-finished",
421 GNUNET_NO,
422 num,
423 GNUNET_NO,
424 write_message),
425 GNUNET_TRANSPORT_cmd_stop_peer ("stop-peer",
426 "start-peer"),
427 GNUNET_TESTING_cmd_system_destroy ("system-destroy",
428 "system-create"),
429 GNUNET_TESTING_cmd_end ()
430 };
431
432 ts->write_message = write_message;
433
434 is = GNUNET_TESTING_run (commands,
435 TIMEOUT,
436 &handle_result,
437 ts);
438 return is;
439}
440
441
442/**
443 * Entry point for the plugin.
444 *
445 * @param cls NULL
446 * @return the exported block API
447 */
448void *
449libgnunet_test_transport_plugin_cmd_simple_send_performance_init (void *cls)
450{
451 struct GNUNET_TESTING_PluginFunctions *api;
452
453 GNUNET_log_setup ("simple-send",
454 "DEBUG",
455 NULL);
456
457 api = GNUNET_new (struct GNUNET_TESTING_PluginFunctions);
458 api->start_testcase = &start_testcase;
459 api->get_waiting_for_barriers = get_waiting_for_barriers;
460 return api;
461}
462
463
464/**
465 * Exit point from the plugin.
466 *
467 * @param cls the return value from #libgnunet_test_transport_plugin_simple_send_performance_init
468 * @return NULL
469 */
470void *
471libgnunet_test_transport_plugin_cmd_simple_send_performance_done (void *cls)
472{
473 struct GNUNET_TESTING_PluginFunctions *api = cls;
474
475 GNUNET_free (api);
476 return NULL;
477}
478
479
480/* end of plugin_cmd_simple_send.c */
diff --git a/src/transport/test_transport_plugin_cmd_udp_backchannel.c b/src/transport/test_transport_plugin_cmd_udp_backchannel.c
deleted file mode 100644
index 378caf7df..000000000
--- a/src/transport/test_transport_plugin_cmd_udp_backchannel.c
+++ /dev/null
@@ -1,371 +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 testbed/plugin_cmd_simple_send.c
23 * @brief a plugin to provide the API for running test cases.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_barrier.h"
28#include "gnunet_testing_netjail_lib.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_transport_application_service.h"
31#include "transport-testing2.h"
32#include "transport-testing-cmds.h"
33#include "gnunet_testing_barrier.h"
34
35/**
36 * Generic logging shortcut
37 */
38#define LOG(kind, ...) GNUNET_log_from (kind, "udp-backchannel", __VA_ARGS__)
39
40#define BASE_DIR "testdir"
41
42#define TOPOLOGY_CONFIG "test_transport_udp_backchannel_topo.conf"
43
44#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
45
46static struct GNUNET_TESTING_Command block_send;
47
48static struct GNUNET_TESTING_Command connect_peers;
49
50static struct GNUNET_TESTING_Command local_prepared;
51
52static struct GNUNET_TESTING_Interpreter *is;
53
54
55/**
56 * Function called to check a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE being
57 * received.
58 *
59 */
60static int
61check_test (void *cls,
62 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
63{
64 return GNUNET_OK;
65}
66
67
68/**
69 * Function called to handle a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE
70 * being received.
71 *
72 */
73static void
74handle_test (void *cls,
75 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
76{
77 // struct GNUNET_TESTING_AsyncContext *ac;
78
79 /*GNUNET_TESTING_get_trait_async_context (&block_receive,
80 &ac);
81 if ((NULL == ac) || (NULL == ac->cont))
82 GNUNET_TESTING_async_fail (ac);
83 else
84 GNUNET_TESTING_async_finish (ac);*/
85}
86
87
88struct GNUNET_TESTING_BarrierList *
89get_waiting_for_barriers ()
90{
91 // No Barrier
92 return GNUNET_new (struct GNUNET_TESTING_BarrierList);
93}
94
95
96/**
97 * Callback to set the flag indicating all peers started. Will be called via the plugin api.
98 *
99 */
100static void
101all_peers_started ()
102{
103 struct GNUNET_TESTING_AsyncContext *ac;
104
105 GNUNET_TESTING_get_trait_async_context (&block_send,
106 &ac);
107 GNUNET_assert (NULL != ac);
108 if ((NULL == ac->cont))
109 GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) ac);
110 else
111 GNUNET_TESTING_async_finish ((struct GNUNET_TESTING_AsyncContext *) ac);
112}
113
114
115/**
116* Function called with the final result of the test.
117*
118* @param cls the `struct MainParams`
119* @param rv #GNUNET_OK if the test passed
120*/
121static void
122handle_result (void *cls,
123 enum GNUNET_GenericReturnValue rv)
124{
125 struct TestState *ts = cls;
126
127 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
128 "Local test exits with status %d\n",
129 rv);
130
131 ts->finished_cb (rv);
132 GNUNET_free (ts->testdir);
133 GNUNET_free (ts->cfgname);
134 GNUNET_TESTING_free_topology (ts->topology);
135 GNUNET_free (ts);
136}
137
138
139/**
140 * Callback from start peer cmd for signaling a peer got connected.
141 *
142 */
143static void *
144notify_connect (struct GNUNET_TESTING_Interpreter *is,
145 const struct GNUNET_PeerIdentity *peer)
146{
147 const struct ConnectPeersState *cps;
148
149 GNUNET_TRANSPORT_get_trait_connect_peer_state (&connect_peers,
150 &cps);
151 void *ret = NULL;
152
153 cps->notify_connect (is,
154 peer);
155 return ret;
156}
157
158
159/**
160 * Callback to set the flag indicating all peers are prepared to finish. Will be called via the plugin api.
161 */
162static void
163all_local_tests_prepared ()
164{
165 const struct GNUNET_TESTING_LocalPreparedState *lfs;
166
167 GNUNET_TESTING_get_trait_local_prepared_state (&local_prepared,
168 &lfs);
169 GNUNET_assert (NULL != &lfs->ac);
170 if (NULL == lfs->ac.cont)
171 GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) &lfs->ac);
172 else
173 GNUNET_TESTING_async_finish ((struct
174 GNUNET_TESTING_AsyncContext *) &lfs->ac);
175}
176
177
178/**
179 * Function to start a local test case.
180 *
181 * @param write_message Callback to send a message to the master loop.
182 * @param router_ip Global address of the network namespace.
183 * @param node_ip The IP address of the node.
184 * @param m The number of the node in a network namespace.
185 * @param n The number of the network namespace.
186 * @param local_m The number of nodes in a network namespace.
187 */
188static struct GNUNET_TESTING_Interpreter *
189start_testcase (GNUNET_TESTING_cmd_helper_write_cb write_message,
190 const char *router_ip,
191 const char *node_ip,
192 const char *m,
193 const char *n,
194 const char *local_m,
195 const char *topology_data,
196 unsigned int *read_file,
197 GNUNET_TESTING_cmd_helper_finish_cb finished_cb)
198{
199
200 unsigned int n_int;
201 unsigned int m_int;
202 unsigned int local_m_int;
203 unsigned int num;
204 struct TestState *ts = GNUNET_new (struct TestState);
205 struct GNUNET_TESTING_NetjailTopology *topology;
206 unsigned int sscanf_ret = 0;
207
208 ts->finished_cb = finished_cb;
209 LOG (GNUNET_ERROR_TYPE_ERROR,
210 "n %s m %s\n",
211 n,
212 m);
213
214 if (GNUNET_YES == *read_file)
215 {
216 LOG (GNUNET_ERROR_TYPE_DEBUG,
217 "read from file\n");
218 topology = GNUNET_TESTING_get_topo_from_file (topology_data);
219 }
220 else
221 topology = GNUNET_TESTING_get_topo_from_string (topology_data);
222
223 ts->topology = topology;
224
225 errno = 0;
226 sscanf_ret = sscanf (m, "%u", &m_int);
227 if (errno != 0)
228 {
229 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
230 }
231 GNUNET_assert (0 < sscanf_ret);
232 errno = 0;
233 sscanf_ret = sscanf (n, "%u", &n_int);
234 if (errno != 0)
235 {
236 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
237 }
238 GNUNET_assert (0 < sscanf_ret);
239 errno = 0;
240 sscanf_ret = sscanf (local_m, "%u", &local_m_int);
241 if (errno != 0)
242 {
243 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
244 }
245 GNUNET_assert (0 < sscanf_ret);
246
247
248 if (0 == n_int)
249 num = m_int;
250 else
251 num = (n_int - 1) * local_m_int + m_int + topology->nodes_x;
252
253 block_send = GNUNET_TESTING_cmd_block_until_external_trigger (
254 "block");
255 connect_peers = GNUNET_TRANSPORT_cmd_connect_peers ("connect-peers",
256 "start-peer",
257 "system-create",
258 num,
259 topology,
260 0,
261 GNUNET_YES);
262 local_prepared = GNUNET_TESTING_cmd_local_test_prepared (
263 "local-test-prepared",
264 write_message);
265
266 GNUNET_asprintf (&ts->cfgname,
267 "test_transport_api2_tcp_node1.conf");
268
269 LOG (GNUNET_ERROR_TYPE_DEBUG,
270 "plugin cfgname: %s\n",
271 ts->cfgname);
272
273 LOG (GNUNET_ERROR_TYPE_DEBUG,
274 "node ip: %s\n",
275 node_ip);
276
277 GNUNET_asprintf (&ts->testdir,
278 "%s%s%s",
279 BASE_DIR,
280 m,
281 n);
282
283 struct GNUNET_MQ_MessageHandler handlers[] = {
284 GNUNET_MQ_hd_var_size (test,
285 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
286 struct GNUNET_TRANSPORT_TESTING_TestMessage,
287 NULL),
288 GNUNET_MQ_handler_end ()
289 };
290
291 struct GNUNET_TESTING_Command commands[] = {
292 GNUNET_TESTING_cmd_system_create ("system-create",
293 ts->testdir),
294 GNUNET_TRANSPORT_cmd_start_peer ("start-peer",
295 "system-create",
296 num,
297 node_ip,
298 handlers,
299 ts->cfgname,
300 notify_connect,
301 GNUNET_NO),
302 GNUNET_TESTING_cmd_send_peer_ready ("send-peer-ready",
303 write_message),
304 block_send,
305 connect_peers,
306 GNUNET_TRANSPORT_cmd_backchannel_check ("backchannel-check",
307 "start-peer",
308 "system-create",
309 num,
310 m_int,
311 n_int,
312 topology),
313 local_prepared,
314 GNUNET_TRANSPORT_cmd_stop_peer ("stop-peer",
315 "start-peer"),
316 GNUNET_TESTING_cmd_system_destroy ("system-destroy",
317 "system-create"),
318 GNUNET_TESTING_cmd_end ()
319 };
320
321 ts->write_message = write_message;
322
323 is = GNUNET_TESTING_run (commands,
324 TIMEOUT,
325 &handle_result,
326 ts);
327 return is;
328}
329
330
331/**
332 * Entry point for the plugin.
333 *
334 * @param cls NULL
335 * @return the exported block API
336 */
337void *
338libgnunet_test_transport_plugin_cmd_udp_backchannel_init (void *cls)
339{
340 struct GNUNET_TESTING_PluginFunctions *api;
341
342 GNUNET_log_setup ("udp-backchannel",
343 "DEBUG",
344 "plugin.out");
345
346 api = GNUNET_new (struct GNUNET_TESTING_PluginFunctions);
347 api->start_testcase = &start_testcase;
348 api->all_peers_started = &all_peers_started;
349 api->all_local_tests_prepared = all_local_tests_prepared;
350 api->get_waiting_for_barriers = get_waiting_for_barriers;
351 return api;
352}
353
354
355/**
356 * Exit point from the plugin.
357 *
358 * @param cls the return value from #libgnunet_test_transport_plugin_block_test_init
359 * @return NULL
360 */
361void *
362libgnunet_test_transport_plugin_cmd_udp_backchannel_done (void *cls)
363{
364 struct GNUNET_TESTING_PluginFunctions *api = cls;
365
366 GNUNET_free (api);
367 return NULL;
368}
369
370
371/* end of plugin_cmd_simple_send.c */
diff --git a/src/transport/test_transport_simple_send.sh b/src/transport/test_transport_simple_send.sh
deleted file mode 100755
index 0250070be..000000000
--- a/src/transport/test_transport_simple_send.sh
+++ /dev/null
@@ -1,11 +0,0 @@
1#!/bin/bash
2if ! [ -d "/run/netns" ]; then
3 echo You have to create the directory /run/netns.
4fi
5if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
6 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
7 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
8 exit 78
9 fi
10fi
11exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_simple_send_topo.conf"
diff --git a/src/transport/test_transport_simple_send_broadcast.sh b/src/transport/test_transport_simple_send_broadcast.sh
deleted file mode 100755
index a4801bf70..000000000
--- a/src/transport/test_transport_simple_send_broadcast.sh
+++ /dev/null
@@ -1,11 +0,0 @@
1#!/bin/bash
2if ! [ -d "/run/netns" ]; then
3 echo You have to create the directory /run/netns.
4fi
5if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
6 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
7 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
8 exit 78
9 fi
10fi
11exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_simple_send_broadcast_topo.conf"
diff --git a/src/transport/test_transport_simple_send_broadcast_topo.conf b/src/transport/test_transport_simple_send_broadcast_topo.conf
deleted file mode 100644
index aa4964f81..000000000
--- a/src/transport/test_transport_simple_send_broadcast_topo.conf
+++ /dev/null
@@ -1,4 +0,0 @@
1M:2
2N:1
3X:0
4T:libgnunet_test_transport_plugin_cmd_simple_send_broadcast \ No newline at end of file
diff --git a/src/transport/test_transport_simple_send_dv_circle.sh b/src/transport/test_transport_simple_send_dv_circle.sh
deleted file mode 100755
index bd5f00abe..000000000
--- a/src/transport/test_transport_simple_send_dv_circle.sh
+++ /dev/null
@@ -1,11 +0,0 @@
1#!/bin/bash
2if ! [ -d "/run/netns" ]; then
3 echo You have to create the directory /run/netns.
4fi
5if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
6 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
7 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
8 exit 78
9 fi
10fi
11exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_distance_vector_circle_topo.conf"
diff --git a/src/transport/test_transport_simple_send_dv_inverse.sh b/src/transport/test_transport_simple_send_dv_inverse.sh
deleted file mode 100755
index cf7b863a0..000000000
--- a/src/transport/test_transport_simple_send_dv_inverse.sh
+++ /dev/null
@@ -1,12 +0,0 @@
1#!/bin/bash
2if ! [ -d "/run/netns" ]; then
3 echo You have to create the directory /run/netns.
4fi
5if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
6 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
7 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
8 exit 78
9 fi
10fi
11# exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; valgrind --leak-check=full --track-origins=yes --trace-children=yes --trace-children-skip=/usr/bin/awk,/usr/bin/cut,/usr/bin/seq,/sbin/ip/sed/bash ./test_transport_start_with_config test_transport_distance_vector_inverse_topo.conf"
12exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_distance_vector_inverse_topo.conf"
diff --git a/src/transport/test_transport_simple_send_performance.sh b/src/transport/test_transport_simple_send_performance.sh
deleted file mode 100755
index 12798c2f0..000000000
--- a/src/transport/test_transport_simple_send_performance.sh
+++ /dev/null
@@ -1,11 +0,0 @@
1#!/bin/bash
2if ! [ -d "/run/netns" ]; then
3 echo You have to create the directory /run/netns.
4fi
5if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
6 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
7 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
8 exit 78
9 fi
10fi
11exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_simple_send_performance_topo.conf"
diff --git a/src/transport/test_transport_simple_send_performance_topo.conf b/src/transport/test_transport_simple_send_performance_topo.conf
deleted file mode 100644
index 9f39cd9bc..000000000
--- a/src/transport/test_transport_simple_send_performance_topo.conf
+++ /dev/null
@@ -1,6 +0,0 @@
1M:2
2N:1
3X:0
4T:libgnunet_test_transport_plugin_cmd_simple_send_performance
5P:1:1|{connect:{P:1:2:tcp}|{P:1:2:udp}}
6P:1:2|{connect:{P:1:1:tcp}|{P:1:1:udp}} \ No newline at end of file
diff --git a/src/transport/test_transport_simple_send_string.sh b/src/transport/test_transport_simple_send_string.sh
deleted file mode 100755
index 211abb494..000000000
--- a/src/transport/test_transport_simple_send_string.sh
+++ /dev/null
@@ -1,21 +0,0 @@
1#!/bin/bash
2string=$(cat << EOF
3M:2
4N:1
5X:0
6T:libgnunet_test_transport_plugin_cmd_simple_send
7P:1:1|{connect:{P:1:2:tcp}}
8P:1:2|{connect:{P:1:1:tcp}}
9EOF
10 )
11if ! [ -d "/run/netns" ]; then
12 echo You have to create the directory /run/netns.
13fi
14if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
15 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
16 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
17 exit 78
18 fi
19fi
20
21exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config -s '$string'"
diff --git a/src/transport/test_transport_simple_send_topo.conf b/src/transport/test_transport_simple_send_topo.conf
deleted file mode 100644
index 2c16201f5..000000000
--- a/src/transport/test_transport_simple_send_topo.conf
+++ /dev/null
@@ -1,6 +0,0 @@
1M:2
2N:1
3X:0
4T:libgnunet_test_transport_plugin_cmd_simple_send
5P:1:1|{connect:{P:1:2:tcp}}
6P:1:2|{connect:{P:1:1:tcp}} \ No newline at end of file
diff --git a/src/transport/test_transport_start_testcase.sh b/src/transport/test_transport_start_testcase.sh
deleted file mode 100755
index 028c8f248..000000000
--- a/src/transport/test_transport_start_testcase.sh
+++ /dev/null
@@ -1,12 +0,0 @@
1#!/bin/bash
2read -p "Test case configuration to use:" conf
3if ! [ -d "/run/netns" ]; then
4 echo You have to create the directory /run/netns.
5fi
6if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
7 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
8 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
9 exit 78
10 fi
11fi
12exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config $conf"
diff --git a/src/transport/test_transport_start_with_config.c b/src/transport/test_transport_start_with_config.c
deleted file mode 100644
index 349cd65a5..000000000
--- a/src/transport/test_transport_start_with_config.c
+++ /dev/null
@@ -1,121 +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 transport/test_transport_start_with_config.c
23 * @brief Generic program to start testcases in an configurable topology.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_ng_lib.h"
28#include "gnunet_testing_netjail_lib.h"
29#include "gnunet_util_lib.h"
30
31#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
32
33
34int
35main (int argc,
36 char *const *argv)
37{
38 char *topology_data;
39 char *topology_data_script;
40 struct GNUNET_TESTING_NetjailTopology *topology;
41 unsigned int read_file = GNUNET_YES;
42 int ret;
43 char *rest = NULL;
44 char *token;
45 size_t single_line_len;
46 size_t data_len;
47
48 GNUNET_log_setup ("test-netjail",
49 "INFO",
50 NULL);
51
52 if (0 == strcmp ("-s", argv[1]))
53 {
54 data_len = strlen (argv[2]);
55 topology_data = GNUNET_malloc (data_len);
56 topology_data_script = GNUNET_malloc (data_len);
57 token = strtok_r (argv[2], "\n", &rest);
58 while (NULL != token)
59 {
60 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
61 "token1 %s\n",
62 token);
63 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
64 "token2 %s\n",
65 token);
66 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
67 "topology_data %s\n",
68 topology_data);
69 strcat (topology_data_script, token);
70 strcat (topology_data_script, " ");
71 strcat (topology_data, token);
72 strcat (topology_data, "\n");
73 token = strtok_r (NULL, "\n", &rest);
74 }
75 single_line_len = strlen (topology_data);
76 topology_data_script [single_line_len - 1] = '\0';
77 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
78 "read from string\n");
79 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
80 "topology_data %s\n",
81 topology_data);
82 read_file = GNUNET_NO;
83 topology = GNUNET_TESTING_get_topo_from_string (topology_data);
84 }
85 else
86 {
87 topology_data = argv[1];
88 topology_data_script = argv[1];
89 topology = GNUNET_TESTING_get_topo_from_file (topology_data);
90 }
91
92 struct GNUNET_TESTING_Command commands[] = {
93 GNUNET_TESTING_cmd_netjail_start ("netjail-start",
94 topology_data_script,
95 &read_file),
96 GNUNET_TESTING_cmd_netjail_start_cmds_helper ("netjail-start-testbed",
97 topology,
98 &read_file,
99 topology_data_script,
100 TIMEOUT),
101 GNUNET_TESTING_cmd_stop_cmds_helper ("stop-testbed",
102 "netjail-start-testbed",
103 topology),
104 GNUNET_TESTING_cmd_netjail_stop ("netjail-stop",
105 topology_data_script,
106 &read_file),
107 GNUNET_TESTING_cmd_end ()
108 };
109
110 ret = GNUNET_TESTING_main (commands,
111 TIMEOUT);
112
113 if (0 == strcmp ("-s", argv[1]))
114 {
115 GNUNET_free (topology_data_script);
116 GNUNET_free (topology_data);
117 }
118 GNUNET_TESTING_free_topology (topology);
119
120 return ret;
121}
diff --git a/src/transport/test_transport_test_transport_address_switch_tcp_peer1.conf b/src/transport/test_transport_test_transport_address_switch_tcp_peer1.conf
deleted file mode 100644
index 920e8d199..000000000
--- a/src/transport/test_transport_test_transport_address_switch_tcp_peer1.conf
+++ /dev/null
@@ -1,29 +0,0 @@
1@INLINE@ template_cfg_peer1.conf
2
3[ats]
4UNSPECIFIED_QUOTA_IN = 8 KiB
5UNSPECIFIED_QUOTA_OUT = 8 KiB
6# LOOPBACK
7LOOPBACK_QUOTA_IN = 8 KiB
8LOOPBACK_QUOTA_OUT = 8 KiB
9# LAN
10LAN_QUOTA_IN = 8 KiB
11LAN_QUOTA_OUT = 8 KiB
12# WAN
13WAN_QUOTA_IN = 8 KiB
14WAN_QUOTA_OUT = 8 KiB
15# WLAN
16WLAN_QUOTA_IN = 8 KiB
17WLAN_QUOTA_OUT = 8 KiB
18# BLUETOOTH
19BLUETOOTH_QUOTA_IN = 8 KiB
20BLUETOOTH_QUOTA_OUT = 8 KiB
21
22[PATHS]
23GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/quota-tcp-p1/
24
25[transport]
26PLUGINS = tcp
27
28
29
diff --git a/src/transport/test_transport_test_transport_address_switch_tcp_peer2.conf b/src/transport/test_transport_test_transport_address_switch_tcp_peer2.conf
deleted file mode 100644
index 6855cd00d..000000000
--- a/src/transport/test_transport_test_transport_address_switch_tcp_peer2.conf
+++ /dev/null
@@ -1,29 +0,0 @@
1@INLINE@ template_cfg_peer2.conf
2
3[ats]
4UNSPECIFIED_QUOTA_IN = 8 KiB
5UNSPECIFIED_QUOTA_OUT = 8 KiB
6# LOOPBACK
7LOOPBACK_QUOTA_IN = 8 KiB
8LOOPBACK_QUOTA_OUT = 8 KiB
9# LAN
10LAN_QUOTA_IN = 8 KiB
11LAN_QUOTA_OUT = 8 KiB
12# WAN
13WAN_QUOTA_IN = 8 KiB
14WAN_QUOTA_OUT = 8 KiB
15# WLAN
16WLAN_QUOTA_IN = 8 KiB
17WLAN_QUOTA_OUT = 8 KiB
18# BLUETOOTH
19BLUETOOTH_QUOTA_IN = 8 KiB
20BLUETOOTH_QUOTA_OUT = 8 KiB
21
22
23[PATHS]
24GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
25
26[transport]
27PLUGINS = tcp
28
29
diff --git a/src/transport/test_transport_testing_startstop.c b/src/transport/test_transport_testing_startstop.c
deleted file mode 100644
index 4783c1813..000000000
--- a/src/transport/test_transport_testing_startstop.c
+++ /dev/null
@@ -1,138 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file transport/test_transport_testing_startstop.c
22 * @brief test case for transport testing library:
23 * start the peer, get the HELLO message and stop the peer
24 */
25#include "platform.h"
26#include "gnunet_transport_service.h"
27#include "transport-testing.h"
28
29#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
30
31
32static struct GNUNET_SCHEDULER_Task *timeout_task;
33
34static struct GNUNET_TRANSPORT_TESTING_PeerContext *p;
35
36static struct GNUNET_TRANSPORT_TESTING_Handle *tth;
37
38static int ret;
39
40
41static void
42end ()
43{
44 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
45 "Stopping peers\n");
46 if (NULL != timeout_task)
47 GNUNET_SCHEDULER_cancel (timeout_task);
48 if (NULL != p)
49 GNUNET_TRANSPORT_TESTING_stop_peer (p);
50 if (NULL != tth)
51 GNUNET_TRANSPORT_TESTING_done (tth);
52}
53
54
55static void
56end_badly ()
57{
58 timeout_task = NULL;
59 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
60 "Timeout!\n");
61 end ();
62 ret = GNUNET_SYSERR;
63}
64
65
66static void
67start_cb (void *cls)
68{
69 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
70 "Peer %u (`%s') successfully started\n",
71 p->no,
72 GNUNET_i2s (&p->id));
73 ret = 0;
74 GNUNET_SCHEDULER_add_now (&end,
75 NULL);
76}
77
78
79static void
80run (void *cls,
81 char *const *args,
82 const char *cfgfile,
83 const struct GNUNET_CONFIGURATION_Handle *cfg)
84{
85 ret = 1;
86 tth = GNUNET_TRANSPORT_TESTING_init ();
87 GNUNET_assert (NULL != tth);
88
89 timeout_task =
90 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
91 &end_badly,
92 NULL);
93
94 p = GNUNET_TRANSPORT_TESTING_start_peer (tth,
95 cfgfile,
96 1,
97 NULL, /* receive cb */
98 NULL, /* connect cb */
99 NULL, /* disconnect cb */
100 NULL, /* nc/nd closure */
101 &start_cb, /* startup cb */
102 NULL); /* closure */
103 if (NULL == p)
104 {
105 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to start peer\n");
106 if (timeout_task != NULL)
107 GNUNET_SCHEDULER_cancel (timeout_task);
108 timeout_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
109 }
110}
111
112
113int
114main (int argc, char *argv[])
115{
116 char *const argv_1[] = { "test_transport_testing",
117 "-c",
118 "test_transport_api_data.conf",
119 NULL };
120 struct GNUNET_GETOPT_CommandLineOption options[] = {
121 GNUNET_GETOPT_OPTION_END
122 };
123
124 GNUNET_log_setup ("test_transport_testing_startstop",
125 "WARNING",
126 NULL);
127 GNUNET_PROGRAM_run ((sizeof(argv_1) / sizeof(char *)) - 1,
128 argv_1,
129 "test_transport_testing_startstop", "nohelp",
130 options,
131 &run,
132 &ret);
133
134 return ret;
135}
136
137
138/* end of test_transport_testing_startstop.c */
diff --git a/src/transport/test_transport_udp_backchannel.sh b/src/transport/test_transport_udp_backchannel.sh
deleted file mode 100755
index 1a7c83385..000000000
--- a/src/transport/test_transport_udp_backchannel.sh
+++ /dev/null
@@ -1,14 +0,0 @@
1#!/bin/bash
2if [ -f "test.out" ]; then
3 rm test.out
4fi
5if ! [ -d "/run/netns" ]; then
6 echo You have to create the directory /run/netns.
7fi
8if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
9 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
10 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
11 exit 78
12 fi
13fi
14exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; GNUNET_FORCE_LOG=';;;;DEBUG' GNUNET_FORCE_LOGFILE='test.out' ./test_transport_start_with_config test_transport_udp_backchannel_topo.conf"
diff --git a/src/transport/test_transport_udp_backchannel_topo.conf b/src/transport/test_transport_udp_backchannel_topo.conf
deleted file mode 100644
index ad35bde0a..000000000
--- a/src/transport/test_transport_udp_backchannel_topo.conf
+++ /dev/null
@@ -1,7 +0,0 @@
1M:1
2N:1
3X:1
4T:libgnunet_test_transport_plugin_cmd_udp_backchannel
5K:1|{connect:{P:1:1:tcp}}
6R:1|{tcp_port:1}|{udp_port:0}
7P:1:1|{connect:{K:1:udp}}
diff --git a/src/transport/transport-testing-cmds.h b/src/transport/transport-testing-cmds.h
deleted file mode 100644
index 6b6fcf4f1..000000000
--- a/src/transport/transport-testing-cmds.h
+++ /dev/null
@@ -1,245 +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 transport-testing.h
23 * @brief testing lib for transport service
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#ifndef TRANSPORT_TESTING_CMDS_H
28#define TRANSPORT_TESTING_CMDS_H
29#include "gnunet_testing_ng_lib.h"
30#include "gnunet_testing_plugin.h"
31
32typedef void *
33(*GNUNET_TRANSPORT_notify_connect_cb) (struct GNUNET_TESTING_Interpreter *is,
34 const struct GNUNET_PeerIdentity *peer);
35
36
37
38struct TestState
39{
40 /**
41 * Callback to write messages to the master loop.
42 *
43 */
44 GNUNET_TESTING_cmd_helper_write_cb write_message;
45
46 /**
47 * Callback to notify the helper test case has finished.
48 */
49 GNUNET_TESTING_cmd_helper_finish_cb finished_cb;
50
51 /**
52 * The name for a specific test environment directory.
53 *
54 */
55 char *testdir;
56
57 /**
58 * The name for the configuration file of the specific node.
59 *
60 */
61 char *cfgname;
62
63 /**
64 * The complete topology information.
65 */
66 struct GNUNET_TESTING_NetjailTopology *topology;
67};
68
69
70/**
71 * Create command.
72 *
73 * @param label name for command.
74 * @param system_label Label of the cmd to setup a test environment.
75 * @param no Decimal number representing the last byte of the IP address of this peer.
76 * @param node_ip The IP address of this node.
77 * @param handlers Handler for messages received by this peer.
78 * @param cfgname Configuration file name for this peer.
79 * @param notify_connect Method which will be called, when a peer connects.
80 * @param broadcast Flag indicating, if broadcast should be switched on.
81 * @return command.
82 */
83struct GNUNET_TESTING_Command
84GNUNET_TRANSPORT_cmd_start_peer (const char *label,
85 const char *system_label,
86 uint32_t no,
87 const char *node_ip,
88 struct GNUNET_MQ_MessageHandler *handlers,
89 const char *cfgname,
90 GNUNET_TRANSPORT_notify_connect_cb
91 notify_connect,
92 unsigned int broadcast);
93
94
95struct GNUNET_TESTING_Command
96GNUNET_TRANSPORT_cmd_stop_peer (const char *label,
97 const char *start_label);
98
99
100/**
101 * Create command
102 *
103 * @param label name for command
104 * @param start_peer_label Label of the cmd to start a peer.
105 * @param create_label Label of the cmd which started the test system.
106 * @param num Number globally identifying the node.
107 * @param topology The topology for the test setup.
108 * @param additional_connects Number of additional connects this cmd will wait for not triggered by this cmd.
109 * @return command.
110 */
111struct GNUNET_TESTING_Command
112GNUNET_TRANSPORT_cmd_connect_peers (
113 const char *label,
114 const char *start_peer_label,
115 const char *create_label,
116 uint32_t num,
117 struct GNUNET_TESTING_NetjailTopology *topology,
118 unsigned int additional_connects,
119 unsigned int wait_for_connect);
120
121
122/**
123 * Create command.
124 *
125 * @param label name for command.
126 * @param start_peer_label Label of the cmd to start a peer.
127 * @param create_label Label of the cmd which started the test system.
128 * @param num Number globally identifying the node.
129 * @param topology The topology for the test setup.
130 * @return command.
131 */
132struct GNUNET_TESTING_Command
133GNUNET_TRANSPORT_cmd_send_simple (const char *label,
134 const char *start_peer_label,
135 const char *create_label,
136 uint32_t num,
137 struct GNUNET_TESTING_NetjailTopology *
138 topology);
139
140/**
141 *
142 *
143 * @param label name for command.
144 * @param start_peer_label Label of the cmd to start a peer.
145 * @param create_label Label of the cmd which started the test system.
146 * @param num Number globally identifying the node.
147 * @param size The size of the test message to send.
148 * @param max_send The number of messages to send.
149 * @param topology The topology for the test setup.
150 * @return command.
151 */
152struct GNUNET_TESTING_Command
153GNUNET_TRANSPORT_cmd_send_simple_performance (const char *label,
154 const char *start_peer_label,
155 const char *create_label,
156 uint32_t num,
157 int size,
158 int max_send,
159 struct GNUNET_TESTING_NetjailTopology *
160 topology);
161
162
163/**
164 * Create command.
165 *
166 * @param label name for command.
167 * @param start_peer_label Label of the cmd to start a peer.
168 * @param create_label Label of the cmd to create the testing system.
169 * @param num Number globally identifying the node.
170 * @param node_n The number of the node in a network namespace.
171 * @param namespace_n The number of the network namespace.
172 * @param topology The topology for the test setup.
173 * @return command.
174 */
175struct GNUNET_TESTING_Command
176GNUNET_TRANSPORT_cmd_backchannel_check (const char *label,
177 const char *start_peer_label,
178 const char *create_label,
179 uint32_t num,
180 unsigned int node_n,
181 unsigned int namespace_n,
182 struct GNUNET_TESTING_NetjailTopology *
183 topology);
184
185
186/**
187 * Create headers for a trait with name @a name for
188 * statically allocated data of type @a type.
189 */
190#define GNUNET_TRANSPORT_MAKE_DECL_SIMPLE_TRAIT(name,type) \
191 enum GNUNET_GenericReturnValue \
192 GNUNET_TRANSPORT_get_trait_ ## name ( \
193 const struct GNUNET_TESTING_Command *cmd, \
194 type **ret); \
195 struct GNUNET_TESTING_Trait \
196 GNUNET_TRANSPORT_make_trait_ ## name ( \
197 type * value);
198
199
200/**
201 * Create C implementation for a trait with name @a name for statically
202 * allocated data of type @a type.
203 */
204#define GNUNET_TRANSPORT_MAKE_IMPL_SIMPLE_TRAIT(name,type) \
205 enum GNUNET_GenericReturnValue \
206 GNUNET_TRANSPORT_get_trait_ ## name ( \
207 const struct GNUNET_TESTING_Command *cmd, \
208 type **ret) \
209 { \
210 if (NULL == cmd->traits) return GNUNET_SYSERR; \
211 return cmd->traits (cmd->cls, \
212 (const void **) ret, \
213 GNUNET_S (name), \
214 0); \
215 } \
216 struct GNUNET_TESTING_Trait \
217 GNUNET_TRANSPORT_make_trait_ ## name ( \
218 type * value) \
219 { \
220 struct GNUNET_TESTING_Trait ret = { \
221 .trait_name = GNUNET_S (name), \
222 .ptr = (const void *) value \
223 }; \
224 return ret; \
225 }
226
227
228/**
229 * Call #op on all simple traits.
230 */
231#define GNUNET_TRANSPORT_SIMPLE_TRAITS(op) \
232 op (peer_id, const struct GNUNET_PeerIdentity) \
233 op (connected_peers_map, const struct GNUNET_CONTAINER_MultiShortmap) \
234 op (hello_size, const size_t) \
235 op (hello, const char) \
236 op (application_handle, const struct GNUNET_TRANSPORT_ApplicationHandle) \
237 op (connect_peer_state, const struct ConnectPeersState) \
238 op (state, const struct GNUNET_TESTING_StartPeerState) \
239 op (broadcast, const enum GNUNET_GenericReturnValue)
240
241GNUNET_TRANSPORT_SIMPLE_TRAITS (GNUNET_TRANSPORT_MAKE_DECL_SIMPLE_TRAIT)
242
243
244#endif
245/* end of transport_testing.h */
diff --git a/src/transport/transport-testing-communicator.c b/src/transport/transport-testing-communicator.c
deleted file mode 100644
index 553426b66..000000000
--- a/src/transport/transport-testing-communicator.c
+++ /dev/null
@@ -1,1238 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2019 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 transport/transport-testing-communicator.c
23 * @brief functions related to testing-tng
24 * @author Christian Grothoff
25 * @author Julius Bünger
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_protocols.h"
30#include "gnunet_constants.h"
31#include "transport-testing-communicator.h"
32#include "gnunet_hello_lib.h"
33#include "gnunet_signatures.h"
34#include "transport.h"
35#include <inttypes.h>
36
37#define LOG(kind, ...) GNUNET_log_from (kind, "transport-testing2", __VA_ARGS__)
38
39struct MyClient
40{
41 struct MyClient *prev;
42 struct MyClient *next;
43 /**
44 * @brief Handle to the client
45 */
46 struct GNUNET_SERVICE_Client *client;
47
48 /**
49 * @brief Handle to the client
50 */
51 struct GNUNET_MQ_Handle *c_mq;
52
53 /**
54 * The TCH
55 */
56 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc;
57
58};
59
60/**
61 * @brief Queue of a communicator and some context
62 */
63struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue
64{
65 /**
66 * @brief Handle to the TransportCommunicator
67 */
68 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h;
69
70 /**
71 * @brief Envelope to a message that requests the opening of the queue.
72 *
73 * If the client already requests queue(s), but the communicator is not yet
74 * connected, we cannot send the request to open the queue. Save it until the
75 * communicator becomes available and send it then.
76 */
77 struct GNUNET_MQ_Envelope *open_queue_env;
78
79 /**
80 * @brief Peer ID of the peer on the other side of the queue
81 */
82 struct GNUNET_PeerIdentity peer_id;
83
84 /**
85 * @brief Queue ID
86 */
87 uint32_t qid;
88
89 /**
90 * @brief Current message id
91 */
92 uint64_t mid;
93
94 /**
95 * An `enum GNUNET_NetworkType` in NBO.
96 */
97 uint32_t nt;
98
99 /**
100 * Maximum transmission unit. UINT32_MAX for unlimited.
101 */
102 uint32_t mtu;
103
104 /**
105 * Queue length. UINT64_MAX for unlimited.
106 */
107 uint64_t q_len;
108
109 /**
110 * Queue prio
111 */
112 uint32_t priority;
113
114 /**
115 * An `enum GNUNET_TRANSPORT_ConnectionStatus` in NBO.
116 */
117 uint32_t cs;
118
119 /**
120 * @brief Next element inside a DLL
121 */
122 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *next;
123
124 /**
125 * @brief Previous element inside a DLL
126 */
127 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *prev;
128};
129
130
131/**
132 * @brief Handle/Context to a single transmission
133 */
134struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorTransmission
135{
136};
137
138
139/**
140 * @brief Check whether incoming msg indicating available communicator is
141 * correct
142 *
143 * @param cls Closure
144 * @param msg Message struct
145 *
146 * @return GNUNET_YES in case message is correct
147 */
148static int
149check_communicator_available (
150 void *cls,
151 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *msg)
152{
153 uint16_t size;
154
155 size = ntohs (msg->header.size) - sizeof(*msg);
156 if (0 == size)
157 return GNUNET_OK; /* receive-only communicator */
158 GNUNET_MQ_check_zero_termination (msg);
159 return GNUNET_OK;
160}
161
162
163/**
164 * @brief Handle new communicator
165 *
166 * Store characteristics of communicator, call respective client callback.
167 *
168 * @param cls Closure - communicator handle
169 * @param msg Message struct
170 */
171static void
172handle_communicator_available (
173 void *cls,
174 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *msg)
175{
176 struct MyClient *client = cls;
177 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
178 client->tc;
179 uint16_t size;
180 tc_h->c_mq = client->c_mq;
181
182 size = ntohs (msg->header.size) - sizeof(*msg);
183 if (0 == size)
184 {
185 GNUNET_SERVICE_client_continue (client->client);
186 return; /* receive-only communicator */
187 }
188 tc_h->c_characteristics = ntohl (msg->cc);
189 tc_h->c_addr_prefix = GNUNET_strdup ((const char *) &msg[1]);
190 if (NULL != tc_h->communicator_available_cb)
191 {
192 LOG (GNUNET_ERROR_TYPE_DEBUG, "calling communicator_available_cb()\n");
193 tc_h->communicator_available_cb (tc_h->cb_cls,
194 tc_h,
195 tc_h->c_characteristics,
196 tc_h->c_addr_prefix);
197 }
198 GNUNET_SERVICE_client_continue (client->client);
199 LOG (GNUNET_ERROR_TYPE_DEBUG, "finished communicator_available_cb()\n");
200
201}
202
203
204/**
205 * Incoming message. Test message is well-formed.
206 *
207 * @param cls the client
208 * @param msg the send message that was sent
209 * @return #GNUNET_OK if message is well-formed
210 */
211static int
212check_communicator_backchannel (void *cls,
213 const struct
214 GNUNET_TRANSPORT_CommunicatorBackchannel *msg)
215{
216 // struct TransportClient *tc = cls;
217
218 // if (CT_COMMUNICATOR != tc->type)
219 // {
220 // GNUNET_break (0);
221 // return GNUNET_SYSERR;
222 // }
223 // GNUNET_MQ_check_boxed_message (msg);
224 return GNUNET_OK;
225}
226
227
228/**
229 * @brief Receive an incoming message.
230 *
231 * Pass the message to the client.
232 *
233 * @param cls Closure - communicator handle
234 * @param bc_msg Message
235 */
236static void
237handle_communicator_backchannel (void *cls,
238 const struct
239 GNUNET_TRANSPORT_CommunicatorBackchannel *
240 bc_msg)
241{
242 struct MyClient *client = cls;
243 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
244 client->tc;
245 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *other_tc_h;
246 struct GNUNET_MessageHeader *msg;
247 msg = (struct GNUNET_MessageHeader *) &bc_msg[1];
248 uint16_t isize = ntohs (msg->size);
249 const char *target_communicator = ((const char *) msg) + isize;
250 struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *cbi;
251 struct GNUNET_MQ_Envelope *env;
252
253 LOG (GNUNET_ERROR_TYPE_DEBUG,
254 "Received backchannel message\n");
255 if (tc_h->bc_enabled != GNUNET_YES)
256 {
257 GNUNET_SERVICE_client_continue (client->client);
258 return;
259 }
260 /* Find client providing this communicator */
261 /* Finally, deliver backchannel message to communicator */
262 LOG (GNUNET_ERROR_TYPE_DEBUG,
263 "Delivering backchannel message of type %u to %s\n",
264 ntohs (msg->type),
265 target_communicator);
266 other_tc_h = tc_h->bc_cb (tc_h, msg, (struct
267 GNUNET_PeerIdentity*) &bc_msg->pid);
268 env = GNUNET_MQ_msg_extra (
269 cbi,
270 isize,
271 GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING);
272 cbi->pid = tc_h->peer_id;
273 memcpy (&cbi[1], msg, isize);
274
275
276 GNUNET_MQ_send (other_tc_h->c_mq, env);
277 GNUNET_SERVICE_client_continue (client->client);
278}
279
280
281/**
282 * Address of our peer added. Test message is well-formed.
283 *
284 * @param cls the client
285 * @param msg the send message that was sent
286 * @return #GNUNET_OK if message is well-formed
287 */
288static int
289check_add_address (void *cls,
290 const struct GNUNET_TRANSPORT_AddAddressMessage *msg)
291{
292 // if (CT_COMMUNICATOR != tc->type)
293 // {
294 // GNUNET_break (0);
295 // return GNUNET_SYSERR;
296 // }
297 GNUNET_MQ_check_zero_termination (msg);
298 return GNUNET_OK;
299}
300
301
302/**
303 * @brief The communicator informs about an address.
304 *
305 * Store address and call client callback.
306 *
307 * @param cls Closure - communicator handle
308 * @param msg Message
309 */
310static void
311handle_add_address (void *cls,
312 const struct GNUNET_TRANSPORT_AddAddressMessage *msg)
313{
314 struct MyClient *client = cls;
315 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
316 client->tc;
317 uint16_t size;
318 size = ntohs (msg->header.size) - sizeof(*msg);
319 LOG (GNUNET_ERROR_TYPE_DEBUG, "received add address cb %u\n", size);
320 if (0 == size)
321 return; /* receive-only communicator */
322 LOG (GNUNET_ERROR_TYPE_DEBUG, "received add address cb %u\n", size);
323 tc_h->c_address = GNUNET_strdup ((const char *) &msg[1]);
324 if (NULL != tc_h->add_address_cb)
325 {
326 LOG (GNUNET_ERROR_TYPE_DEBUG, "calling add_address_cb()\n");
327 tc_h->add_address_cb (tc_h->cb_cls,
328 tc_h,
329 tc_h->c_address,
330 GNUNET_TIME_relative_ntoh (msg->expiration),
331 msg->aid,
332 ntohl (msg->nt));
333 }
334 GNUNET_SERVICE_client_continue (client->client);
335}
336
337
338/**
339 * Incoming message. Test message is well-formed.
340 *
341 * @param cls the client
342 * @param msg the send message that was sent
343 * @return #GNUNET_OK if message is well-formed
344 */
345static int
346check_incoming_msg (void *cls,
347 const struct GNUNET_TRANSPORT_IncomingMessage *msg)
348{
349 // struct TransportClient *tc = cls;
350
351 // if (CT_COMMUNICATOR != tc->type)
352 // {
353 // GNUNET_break (0);
354 // return GNUNET_SYSERR;
355 // }
356 GNUNET_MQ_check_boxed_message (msg);
357 return GNUNET_OK;
358}
359
360
361/**
362 * @brief Receive an incoming message.
363 *
364 * Pass the message to the client.
365 *
366 * @param cls Closure - communicator handle
367 * @param inc_msg Message
368 */
369static void
370handle_incoming_msg (void *cls,
371 const struct GNUNET_TRANSPORT_IncomingMessage *inc_msg)
372{
373 struct MyClient *client = cls;
374 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
375 client->tc;
376 struct GNUNET_MessageHeader *msg;
377 msg = (struct GNUNET_MessageHeader *) &inc_msg[1];
378 size_t payload_len = ntohs (msg->size) - sizeof (struct
379 GNUNET_MessageHeader);
380 if (NULL != tc_h->incoming_msg_cb)
381 {
382 tc_h->incoming_msg_cb (tc_h->cb_cls,
383 tc_h,
384 (char*) &msg[1],
385 payload_len);
386 }
387 else
388 {
389 LOG (GNUNET_ERROR_TYPE_WARNING,
390 "Incoming message from communicator but no handler!\n");
391 }
392 if (GNUNET_YES == ntohl (inc_msg->fc_on))
393 {
394 /* send ACK when done to communicator for flow control! */
395 struct GNUNET_MQ_Envelope *env;
396 struct GNUNET_TRANSPORT_IncomingMessageAck *ack;
397
398 env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK);
399 GNUNET_assert (NULL != env);
400 ack->reserved = htonl (0);
401 ack->fc_id = inc_msg->fc_id;
402 ack->sender = inc_msg->sender;
403 GNUNET_MQ_send (tc_h->c_mq, env);
404 }
405
406 GNUNET_SERVICE_client_continue (client->client);
407}
408
409
410/**
411 * @brief Communicator informs that it tries to establish requested queue
412 *
413 * @param cls Closure - communicator handle
414 * @param msg Message
415 */
416static void
417handle_queue_create_ok (void *cls,
418 const struct GNUNET_TRANSPORT_CreateQueueResponse *msg)
419{
420 struct MyClient *client = cls;
421 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
422 client->tc;
423
424 if (NULL != tc_h->queue_create_reply_cb)
425 {
426 tc_h->queue_create_reply_cb (tc_h->cb_cls, tc_h, GNUNET_YES);
427 }
428 GNUNET_SERVICE_client_continue (client->client);
429}
430
431
432/**
433 * @brief Communicator informs that it won't try establishing requested queue.
434 *
435 * It will not do so probably because the address is bougus (see comment to
436 * #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL)
437 *
438 * @param cls Closure - communicator handle
439 * @param msg Message
440 */
441static void
442handle_queue_create_fail (
443 void *cls,
444 const struct GNUNET_TRANSPORT_CreateQueueResponse *msg)
445{
446 struct MyClient *client = cls;
447 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
448 client->tc;
449
450 if (NULL != tc_h->queue_create_reply_cb)
451 {
452 tc_h->queue_create_reply_cb (tc_h->cb_cls, tc_h, GNUNET_NO);
453 }
454 GNUNET_SERVICE_client_continue (client->client);
455}
456
457
458/**
459 * New queue became available. Check message.
460 *
461 * @param cls the client
462 * @param aqm the send message that was sent
463 */
464static int
465check_add_queue_message (void *cls,
466 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
467{
468 GNUNET_MQ_check_zero_termination (aqm);
469 return GNUNET_OK;
470}
471
472
473/**
474 * @brief Handle new queue
475 *
476 * Store context and call client callback.
477 *
478 * @param cls Closure - communicator handle
479 * @param msg Message struct
480 */
481static void
482handle_add_queue_message (void *cls,
483 const struct GNUNET_TRANSPORT_AddQueueMessage *msg)
484{
485 struct MyClient *client = cls;
486 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
487 client->tc;
488 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue;
489
490 LOG (GNUNET_ERROR_TYPE_DEBUG,
491 "Got queue with ID %u\n", msg->qid);
492 for (tc_queue = tc_h->queue_head; NULL != tc_queue; tc_queue = tc_queue->next)
493 {
494 if (tc_queue->qid == msg->qid)
495 break;
496 }
497 if (NULL == tc_queue)
498 {
499 tc_queue =
500 GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue);
501 tc_queue->tc_h = tc_h;
502 tc_queue->qid = msg->qid;
503 tc_queue->peer_id = msg->receiver;
504 GNUNET_CONTAINER_DLL_insert (tc_h->queue_head, tc_h->queue_tail, tc_queue);
505 }
506 GNUNET_assert (tc_queue->qid == msg->qid);
507 GNUNET_assert (0 == GNUNET_memcmp (&tc_queue->peer_id, &msg->receiver));
508 tc_queue->nt = msg->nt;
509 tc_queue->mtu = ntohl (msg->mtu);
510 tc_queue->cs = msg->cs;
511 tc_queue->priority = ntohl (msg->priority);
512 tc_queue->q_len = GNUNET_ntohll (msg->q_len);
513 if (NULL != tc_h->add_queue_cb)
514 {
515 tc_h->add_queue_cb (tc_h->cb_cls, tc_h, tc_queue, tc_queue->mtu);
516 }
517 GNUNET_SERVICE_client_continue (client->client);
518}
519
520
521/**
522 * @brief Handle new queue
523 *
524 * Store context and call client callback.
525 *
526 * @param cls Closure - communicator handle
527 * @param msg Message struct
528 */
529static void
530handle_update_queue_message (void *cls,
531 const struct
532 GNUNET_TRANSPORT_UpdateQueueMessage *msg)
533{
534 struct MyClient *client = cls;
535 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
536 client->tc;
537 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue;
538
539 LOG (GNUNET_ERROR_TYPE_DEBUG,
540 "Received queue update message for %u with q_len %" PRIu64 "\n",
541 msg->qid, GNUNET_ntohll (msg->q_len));
542 tc_queue = tc_h->queue_head;
543 if (NULL != tc_queue)
544 {
545 while (tc_queue->qid != msg->qid)
546 {
547 tc_queue = tc_queue->next;
548 }
549 }
550 if (NULL == tc_queue)
551 {
552 GNUNET_SERVICE_client_continue (client->client);
553 return;
554 }
555 GNUNET_assert (tc_queue->qid == msg->qid);
556 GNUNET_assert (0 == GNUNET_memcmp (&tc_queue->peer_id, &msg->receiver));
557 tc_queue->nt = msg->nt;
558 tc_queue->mtu = ntohl (msg->mtu);
559 tc_queue->cs = msg->cs;
560 tc_queue->priority = ntohl (msg->priority);
561 // Uncomment this for alternativ 1 of backchannel functionality
562 tc_queue->q_len += GNUNET_ntohll (msg->q_len);
563 // Until here for alternativ 1
564 // Uncomment this for alternativ 2 of backchannel functionality
565 // tc_queue->q_len = GNUNET_ntohll (msg->q_len);
566 // Until here for alternativ 2
567 GNUNET_SERVICE_client_continue (client->client);
568}
569
570
571/**
572 * @brief Shut down the service
573 *
574 * @param cls Closure - Handle to the service
575 */
576static void
577shutdown_service (void *cls)
578{
579 struct GNUNET_SERVICE_Handle *h = cls;
580
581 LOG (GNUNET_ERROR_TYPE_DEBUG,
582 "Shutting down service!\n");
583
584 GNUNET_SERVICE_stop (h);
585}
586
587
588/**
589 * @brief Callback called when new Client (Communicator) connects
590 *
591 * @param cls Closure - TransporCommmunicator Handle
592 * @param client Client
593 * @param mq Messagequeue
594 *
595 * @return TransportCommunicator Handle
596 */
597static void *
598connect_cb (void *cls,
599 struct GNUNET_SERVICE_Client *client,
600 struct GNUNET_MQ_Handle *mq)
601{
602 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
603 struct MyClient *new_c;
604
605 LOG (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected to %p.\n",
606 client, tc_h);
607 new_c = GNUNET_new (struct MyClient);
608 new_c->client = client;
609 new_c->c_mq = mq;
610 new_c->tc = tc_h;
611 GNUNET_CONTAINER_DLL_insert (tc_h->client_head,
612 tc_h->client_tail,
613 new_c);
614
615 if (NULL == tc_h->queue_head)
616 return new_c;
617 /* Iterate over queues. They are yet to be opened. Request opening. */
618 for (struct
619 GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue_iter =
620 tc_h->queue_head;
621 NULL != tc_queue_iter;
622 tc_queue_iter = tc_queue_iter->next)
623 {
624 if (NULL == tc_queue_iter->open_queue_env)
625 continue;
626 /* Send the previously created mq envelope to request the creation of the
627 * queue. */
628 GNUNET_MQ_send (tc_h->c_mq,
629 tc_queue_iter->open_queue_env);
630 tc_queue_iter->open_queue_env = NULL;
631 }
632 return new_c;
633}
634
635
636/**
637 * @brief Callback called when Client disconnects
638 *
639 * @param cls Closure - TransportCommunicator Handle
640 * @param client Client
641 * @param internal_cls TransporCommmunicator Handle
642 */
643static void
644disconnect_cb (void *cls,
645 struct GNUNET_SERVICE_Client *client,
646 void *internal_cls)
647{
648 struct MyClient *cl = cls;
649 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
650
651 for (cl = tc_h->client_head; NULL != cl; cl = cl->next)
652 {
653 if (cl->client != client)
654 continue;
655 GNUNET_CONTAINER_DLL_remove (tc_h->client_head,
656 tc_h->client_tail,
657 cl);
658 if (cl->c_mq == tc_h->c_mq)
659 tc_h->c_mq = NULL;
660 GNUNET_free (cl);
661 break;
662 }
663 LOG (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected.\n");
664}
665
666
667/**
668 * Message was transmitted. Process the request.
669 *
670 * @param cls the client
671 * @param sma the send message that was sent
672 */
673static void
674handle_send_message_ack (void *cls,
675 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
676{
677 struct MyClient *client = cls;
678 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
679 client->tc;
680 static int mtr = 0;
681 mtr++;
682 if (tc_h->cont != NULL)
683 tc_h->cont (tc_h->cont_cls);
684 GNUNET_SERVICE_client_continue (client->client);
685}
686
687
688/**
689 * @brief Start the communicator part of the transport service
690 *
691 * @param communicator_available Callback to be called when a new communicator
692 * becomes available
693 * @param cfg Configuration
694 */
695static void
696transport_communicator_start (
697 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
698{
699 struct GNUNET_MQ_MessageHandler mh[] = {
700 GNUNET_MQ_hd_var_size (communicator_available,
701 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
702 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
703 tc_h),
704 GNUNET_MQ_hd_var_size (communicator_backchannel,
705 GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL,
706 struct GNUNET_TRANSPORT_CommunicatorBackchannel,
707 tc_h),
708 GNUNET_MQ_hd_var_size (add_address,
709 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
710 struct GNUNET_TRANSPORT_AddAddressMessage,
711 tc_h),
712 // GNUNET_MQ_hd_fixed_size (del_address,
713 // GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
714 // struct GNUNET_TRANSPORT_DelAddressMessage,
715 // NULL),
716 GNUNET_MQ_hd_var_size (incoming_msg,
717 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
718 struct GNUNET_TRANSPORT_IncomingMessage,
719 tc_h),
720 GNUNET_MQ_hd_fixed_size (queue_create_ok,
721 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK,
722 struct GNUNET_TRANSPORT_CreateQueueResponse,
723 tc_h),
724 GNUNET_MQ_hd_fixed_size (queue_create_fail,
725 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL,
726 struct GNUNET_TRANSPORT_CreateQueueResponse,
727 tc_h),
728 GNUNET_MQ_hd_var_size (add_queue_message,
729 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
730 struct GNUNET_TRANSPORT_AddQueueMessage,
731 tc_h),
732 GNUNET_MQ_hd_fixed_size (update_queue_message,
733 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE,
734 struct GNUNET_TRANSPORT_UpdateQueueMessage,
735 tc_h),
736 // GNUNET_MQ_hd_fixed_size (del_queue_message,
737 // GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
738 // struct GNUNET_TRANSPORT_DelQueueMessage,
739 // NULL),
740 GNUNET_MQ_hd_fixed_size (send_message_ack,
741 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
742 struct GNUNET_TRANSPORT_SendMessageToAck,
743 tc_h),
744 GNUNET_MQ_handler_end ()
745 };
746
747
748 tc_h->sh = GNUNET_SERVICE_start ("transport",
749 tc_h->cfg,
750 &connect_cb,
751 &disconnect_cb,
752 tc_h,
753 mh);
754 GNUNET_assert (NULL != tc_h->sh);
755}
756
757
758/**
759 * @brief Task run at shutdown to kill communicator and clean up
760 *
761 * @param cls Closure - Process of communicator
762 */
763static void
764shutdown_process (struct GNUNET_OS_Process *proc)
765{
766 if (0 != GNUNET_OS_process_kill (proc, SIGTERM))
767 {
768 LOG (GNUNET_ERROR_TYPE_WARNING,
769 "Error shutting down process with SIGERM, trying SIGKILL\n");
770 if (0 != GNUNET_OS_process_kill (proc, SIGKILL))
771 {
772 LOG (GNUNET_ERROR_TYPE_ERROR,
773 "Error shutting down process with SIGERM and SIGKILL\n");
774 }
775 }
776 GNUNET_OS_process_destroy (proc);
777}
778
779
780/**
781 * @brief Task run at shutdown to kill the statistics process
782 *
783 * @param cls Closure - Process of communicator
784 */
785static void
786shutdown_statistics (void *cls)
787{
788 struct GNUNET_OS_Process *proc = cls;
789 shutdown_process (proc);
790}
791
792
793/**
794 * @brief Task run at shutdown to kill the peerstore process
795 *
796 * @param cls Closure - Process of communicator
797 */
798static void
799shutdown_peerstore (void *cls)
800{
801 struct GNUNET_OS_Process *proc = cls;
802 shutdown_process (proc);
803}
804
805
806/**
807 * @brief Task run at shutdown to kill a communicator process
808 *
809 * @param cls Closure - Process of communicator
810 */
811static void
812shutdown_communicator (void *cls)
813{
814 struct GNUNET_OS_Process *proc = cls;
815 shutdown_process (proc);
816}
817
818
819/**
820 * @brief Start the communicator
821 *
822 * @param cfgname Name of the communicator
823 */
824static void
825communicator_start (
826 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h,
827 const char *binary_name)
828{
829 char *binary;
830 char *loprefix;
831 char *section_name;
832
833 LOG (GNUNET_ERROR_TYPE_DEBUG, "communicator_start\n");
834
835 section_name = strchr (binary_name, '-');
836 section_name++;
837
838 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (tc_h->cfg,
839 section_name,
840 "PREFIX",
841 &loprefix))
842 loprefix = GNUNET_strdup ("");
843
844
845 binary = GNUNET_OS_get_libexec_binary_path (binary_name);
846 tc_h->c_proc = GNUNET_OS_start_process_s (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
847 NULL,
848 loprefix,
849 binary,
850 binary_name,
851 "-c",
852 tc_h->cfg_filename,
853 NULL);
854 if (NULL == tc_h->c_proc)
855 {
856 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start communicator!");
857 return;
858 }
859 LOG (GNUNET_ERROR_TYPE_INFO, "started communicator\n");
860 GNUNET_free (binary);
861}
862
863
864/**
865 * @brief Task run at shutdown to kill communicator and clean up
866 *
867 * @param cls Closure - Process of communicator
868 */
869static void
870shutdown_nat (void *cls)
871{
872 struct GNUNET_OS_Process *proc = cls;
873 shutdown_process (proc);
874}
875
876
877/**
878 * @brief Task run at shutdown to kill the resolver process
879 *
880 * @param cls Closure - Process of communicator
881 */
882static void
883shutdown_resolver (void *cls)
884{
885 struct GNUNET_OS_Process *proc = cls;
886 shutdown_process (proc);
887}
888
889
890/**
891 * @brief Start Resolver
892 *
893 */
894static void
895resolver_start (struct
896 GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
897{
898 char *binary;
899
900 LOG (GNUNET_ERROR_TYPE_DEBUG, "resolver_start\n");
901 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
902 tc_h->resolver_proc = GNUNET_OS_start_process (
903 GNUNET_OS_INHERIT_STD_OUT_AND_ERR
904 | GNUNET_OS_USE_PIPE_CONTROL,
905 NULL,
906 NULL,
907 NULL,
908 binary,
909 "gnunet-service-resolver",
910 "-c",
911 tc_h->cfg_filename,
912 NULL);
913 if (NULL == tc_h->resolver_proc)
914 {
915 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start resolver service!");
916 return;
917 }
918 LOG (GNUNET_ERROR_TYPE_INFO, "started resolver service\n");
919 GNUNET_free (binary);
920
921}
922
923
924/**
925 * @brief Start Statistics
926 *
927 */
928static void
929statistics_start (
930 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
931{
932 char *binary;
933
934 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-statistics");
935 tc_h->stat_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
936 NULL,
937 NULL,
938 NULL,
939 binary,
940 "gnunet-service-statistics",
941 "-c",
942 tc_h->cfg_filename,
943 NULL);
944 if (NULL == tc_h->stat_proc)
945 {
946 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start Statistics!");
947 return;
948 }
949 LOG (GNUNET_ERROR_TYPE_INFO, "started Statistics\n");
950 GNUNET_free (binary);
951}
952
953
954/**
955 * @brief Start Peerstore
956 *
957 */
958static void
959peerstore_start (
960 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
961{
962 char *binary;
963
964 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-peerstore");
965 tc_h->ps_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
966 NULL,
967 NULL,
968 NULL,
969 binary,
970 "gnunet-service-peerstore",
971 "-c",
972 tc_h->cfg_filename,
973 NULL);
974 if (NULL == tc_h->ps_proc)
975 {
976 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start Peerstore!");
977 return;
978 }
979 LOG (GNUNET_ERROR_TYPE_INFO, "started Peerstore\n");
980 GNUNET_free (binary);
981}
982
983
984/**
985 * @brief Start NAT
986 *
987 */
988static void
989nat_start (
990 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
991{
992 char *binary;
993
994 LOG (GNUNET_ERROR_TYPE_DEBUG, "nat_start\n");
995 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-nat");
996 tc_h->nat_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
997 | GNUNET_OS_USE_PIPE_CONTROL,
998 NULL,
999 NULL,
1000 NULL,
1001 binary,
1002 "gnunet-service-nat",
1003 "-c",
1004 tc_h->cfg_filename,
1005 NULL);
1006 if (NULL == tc_h->nat_proc)
1007 {
1008 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start NAT!");
1009 return;
1010 }
1011 LOG (GNUNET_ERROR_TYPE_INFO, "started NAT\n");
1012 GNUNET_free (binary);
1013}
1014
1015
1016/**
1017 * @brief Start communicator part of transport service and communicator
1018 *
1019 * @param service_name Name of the service
1020 * @param cfg Configuration handle
1021 * @param communicator_available_cb Callback that is called when a new
1022 * @param add_address_cb Callback that is called when a new
1023 * communicator becomes available
1024 * @param cb_cls Closure to @a communicator_available_cb and @a
1025 *
1026 * @return Handle to the communicator duo
1027 */
1028struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *
1029GNUNET_TRANSPORT_TESTING_transport_communicator_service_start (
1030 const char *service_name,
1031 const char *binary_name,
1032 const char *cfg_filename,
1033 const struct GNUNET_PeerIdentity *peer_id,
1034 GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback
1035 communicator_available_cb,
1036 GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb,
1037 GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb,
1038 GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb,
1039 GNUNET_TRANSPORT_TESTING_IncomingMessageCallback incoming_message_cb,
1040 GNUNET_TRANSPORT_TESTING_BackchannelCallback bc_cb,
1041 void *cb_cls)
1042{
1043 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h;
1044
1045 LOG (GNUNET_ERROR_TYPE_DEBUG,
1046 "Starting new transport/communicator combo with config %s\n",
1047 cfg_filename);
1048 tc_h =
1049 GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle);
1050 tc_h->cfg_filename = GNUNET_strdup (cfg_filename);
1051 tc_h->cfg = GNUNET_CONFIGURATION_create ();
1052 if ((GNUNET_SYSERR == GNUNET_CONFIGURATION_load (tc_h->cfg, cfg_filename)))
1053 {
1054 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1055 _ ("Malformed configuration file `%s', exit ...\n"),
1056 cfg_filename);
1057 GNUNET_free (tc_h->cfg_filename);
1058 GNUNET_CONFIGURATION_destroy (tc_h->cfg);
1059 GNUNET_free (tc_h);
1060 return NULL;
1061 }
1062 tc_h->bc_enabled = GNUNET_CONFIGURATION_get_value_yesno (tc_h->cfg,
1063 "communicator-test",
1064 "BACKCHANNEL_ENABLED");
1065 tc_h->communicator_available_cb = communicator_available_cb;
1066 tc_h->add_address_cb = add_address_cb;
1067 tc_h->queue_create_reply_cb = queue_create_reply_cb;
1068 tc_h->add_queue_cb = add_queue_cb;
1069 tc_h->incoming_msg_cb = incoming_message_cb;
1070 tc_h->bc_cb = bc_cb;
1071 tc_h->peer_id = *peer_id;
1072 tc_h->cb_cls = cb_cls;
1073
1074 /* Start communicator part of service */
1075 transport_communicator_start (tc_h);
1076 /* Start NAT */
1077 nat_start (tc_h);
1078 /* Start resolver service */
1079 resolver_start (tc_h);
1080 /* Start peerstore service */
1081 peerstore_start (tc_h);
1082 /* Start statistic service */
1083 statistics_start (tc_h);
1084 /* Schedule start communicator */
1085 communicator_start (tc_h,
1086 binary_name);
1087 return tc_h;
1088}
1089
1090
1091void
1092GNUNET_TRANSPORT_TESTING_transport_communicator_service_stop (
1093 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
1094{
1095 shutdown_communicator (tc_h->c_proc);
1096 shutdown_service (tc_h->sh);
1097 shutdown_nat (tc_h->nat_proc);
1098 shutdown_resolver (tc_h->resolver_proc);
1099 shutdown_peerstore (tc_h->ps_proc);
1100 shutdown_statistics (tc_h->stat_proc);
1101 GNUNET_CONFIGURATION_destroy (tc_h->cfg);
1102 GNUNET_free (tc_h);
1103}
1104
1105
1106/**
1107 * @brief Instruct communicator to open a queue
1108 *
1109 * @param tc_h Handle to communicator which shall open queue
1110 * @param peer_id Towards which peer
1111 * @param address For which address
1112 */
1113void
1114GNUNET_TRANSPORT_TESTING_transport_communicator_open_queue (
1115 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h,
1116 const struct GNUNET_PeerIdentity *peer_id,
1117 const char *address)
1118{
1119 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue;
1120 static uint32_t idgen;
1121 char *prefix;
1122 struct GNUNET_TRANSPORT_CreateQueue *msg;
1123 struct GNUNET_MQ_Envelope *env;
1124 size_t alen;
1125
1126 tc_queue =
1127 GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue);
1128 tc_queue->tc_h = tc_h;
1129 prefix = GNUNET_HELLO_address_to_prefix (address);
1130 if (NULL == prefix)
1131 {
1132 GNUNET_break (0); /* We got an invalid address!? */
1133 GNUNET_free (tc_queue);
1134 return;
1135 }
1136 GNUNET_free (prefix);
1137 alen = strlen (address) + 1;
1138 env =
1139 GNUNET_MQ_msg_extra (msg, alen, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE);
1140 msg->request_id = htonl (idgen++);
1141 tc_queue->qid = msg->request_id;
1142 msg->receiver = *peer_id;
1143 tc_queue->peer_id = *peer_id;
1144 memcpy (&msg[1], address, alen);
1145 if (NULL != tc_h->c_mq)
1146 {
1147 LOG (GNUNET_ERROR_TYPE_DEBUG,
1148 "Sending queue create immediately\n");
1149 GNUNET_MQ_send (tc_h->c_mq, env);
1150 }
1151 else
1152 {
1153 tc_queue->open_queue_env = env;
1154 }
1155 GNUNET_CONTAINER_DLL_insert (tc_h->queue_head, tc_h->queue_tail, tc_queue);
1156}
1157
1158
1159void
1160GNUNET_TRANSPORT_TESTING_transport_communicator_send
1161 (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h,
1162 GNUNET_SCHEDULER_TaskCallback cont,
1163 void *cont_cls,
1164 const void *payload,
1165 size_t payload_size)
1166{
1167 struct GNUNET_MessageHeader *mh;
1168 struct GNUNET_TRANSPORT_SendMessageTo *msg;
1169 struct GNUNET_MQ_Envelope *env;
1170 size_t inbox_size;
1171 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue;
1172 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue_tmp;
1173 static struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *last_queue;
1174 tc_queue = NULL;
1175
1176 for (tc_queue_tmp = tc_h->queue_head;
1177 NULL != tc_queue_tmp;
1178 tc_queue_tmp = tc_queue_tmp->next)
1179 {
1180 if (tc_queue_tmp->q_len <= 0)
1181 continue;
1182 if (NULL == tc_queue)
1183 {
1184 LOG (GNUNET_ERROR_TYPE_DEBUG,
1185 "Selecting queue with prio %u, len %" PRIu64 " and MTU %u\n",
1186 tc_queue_tmp->priority,
1187 tc_queue_tmp->q_len,
1188 tc_queue_tmp->mtu);
1189 tc_queue = tc_queue_tmp;
1190 continue;
1191 }
1192 if (tc_queue->priority < tc_queue_tmp->priority)
1193 {
1194 LOG (GNUNET_ERROR_TYPE_DEBUG,
1195 "Selecting queue with prio %u, len %" PRIu64 " and MTU %u\n",
1196 tc_queue_tmp->priority,
1197 tc_queue_tmp->q_len,
1198 tc_queue_tmp->mtu);
1199 tc_queue = tc_queue_tmp;
1200 }
1201 }
1202 if (last_queue != tc_queue)
1203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1204 "Selected sending queue changed to %u with length %lu and MTU %u\n",
1205 ntohl (tc_queue->qid), (unsigned long) tc_queue->q_len, tc_queue->mtu);
1206 GNUNET_assert (NULL != tc_queue);
1207 last_queue = tc_queue;
1208 // Uncomment this for alternativ 1 of backchannel functionality
1209 if (tc_queue->q_len != GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED)
1210 tc_queue->q_len--;
1211 // Until here for alternativ 1
1212 static int msg_count = 0;
1213 msg_count++;
1214 if (msg_count % 100 == 0)
1215 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1216 "Sending %u-th (%lu-th for queue) message on queue %u\n",
1217 msg_count, (unsigned long) tc_queue->mid, ntohl (tc_queue->qid));
1218 inbox_size = sizeof (struct GNUNET_MessageHeader) + payload_size;
1219 env = GNUNET_MQ_msg_extra (msg,
1220 inbox_size,
1221 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG);
1222 GNUNET_assert (NULL != env);
1223 msg->qid = tc_queue->qid;
1224 msg->mid = tc_queue->mid++;
1225 msg->receiver = tc_queue->peer_id;
1226 mh = (struct GNUNET_MessageHeader *) &msg[1];
1227 mh->size = htons (inbox_size);
1228 mh->type = GNUNET_MESSAGE_TYPE_DUMMY;
1229 memcpy (&mh[1],
1230 payload,
1231 payload_size);
1232 if (NULL != cont)
1233 GNUNET_MQ_notify_sent (env,
1234 cont,
1235 cont_cls);
1236 GNUNET_MQ_send (tc_queue->tc_h->c_mq,
1237 env);
1238}
diff --git a/src/transport/transport-testing-communicator.h b/src/transport/transport-testing-communicator.h
deleted file mode 100644
index 7460aab8e..000000000
--- a/src/transport/transport-testing-communicator.h
+++ /dev/null
@@ -1,370 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2019 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 transport/transport-testing-communicator.h
23 * @brief functions and structures related to testing-tng
24 * @author Christian Grothoff
25 * @author Julius Bünger
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_transport_communication_service.h"
30#include "transport.h"
31
32/**
33 * @brief Queue of a communicator and some context
34 */
35struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue;
36
37
38/**
39 * @brief Handle/Context to a single transmission
40 */
41struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorTransmission;
42
43/**
44 * @brief Function signature for callbacks that are called when new
45 * backchannel message arrived
46 *
47 * @param cls Closure
48 * @param msg Backchannel message
49 * @param pid Target peer
50 */
51typedef struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *
52(*GNUNET_TRANSPORT_TESTING_BackchannelCallback)(void *cls,
53 struct GNUNET_MessageHeader *msg,
54 struct GNUNET_PeerIdentity *pid);
55
56
57/**
58 * @brief Function signature for callbacks that are called when new
59 * communicators become available
60 *
61 * @param cls Closure
62 * @param tc_h Communicator handle
63 * @param cc Characteristics of communicator
64 * @param address_prefix Prefix of the address
65 */
66typedef void
67(*GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback)(void *cls,
68 struct
69 GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle
70 *tc_h,
71 enum
72 GNUNET_TRANSPORT_CommunicatorCharacteristics
73 cc,
74 char *address_prefix);
75
76
77/**
78 * @brief Receive information about the address of a communicator.
79 *
80 * @param cls Closure
81 * @param tc_h Communicator handle
82 * @param address Address represented as string
83 * @param expiration Expiration
84 * @param aid Aid
85 * @param nt Network Type
86 */
87typedef void
88(*GNUNET_TRANSPORT_TESTING_AddAddressCallback)(void *cls,
89 struct
90 GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle
91 *tc_h,
92 const char *address,
93 struct GNUNET_TIME_Relative
94 expiration,
95 uint32_t aid,
96 enum GNUNET_NetworkType nt);
97
98
99/**
100 * @brief Get informed about the success of a queue request.
101 *
102 * @param cls Closure
103 * @param tc_h Communicator handle
104 * @param will_try #GNUNET_YES if communicator will try to create queue
105 */
106typedef void
107(*GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback)(void *cls,
108 struct
109 GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle
110 *tc_h,
111 int will_try);
112
113
114/**
115 * @brief Handle opening of queue
116 *
117 * @param cls Closure
118 * @param tc_h Communicator handle
119 * @param tc_queue Handle to newly opened queue
120 */
121typedef void
122(*GNUNET_TRANSPORT_TESTING_AddQueueCallback)(void *cls,
123 struct
124 GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle
125 *tc_h,
126 struct
127 GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue
128 *tc_queue,
129 size_t mtu);
130
131
132/**
133 * @brief Handle an incoming message
134 *
135 * @param cls Closure
136 * @param tc_h Handle to the receiving communicator
137 * @param msg Received message
138 */
139typedef void
140(*GNUNET_TRANSPORT_TESTING_IncomingMessageCallback)(void *cls,
141 struct
142 GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle
143 *tc_h,
144 const char*payload,
145 size_t payload_len);
146
147/**
148 * @brief Handle to a transport communicator
149 */
150struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle
151{
152 /**
153 * Clients
154 */
155 struct MyClient *client_head;
156 struct MyClient *client_tail;
157
158 /**
159 * @brief Handle to the client
160 */
161 struct GNUNET_MQ_Handle *c_mq;
162
163 /**
164 * @brief Handle to the configuration
165 */
166 struct GNUNET_CONFIGURATION_Handle *cfg;
167
168 /**
169 * @brief File name of configuration file
170 */
171 char *cfg_filename;
172
173 struct GNUNET_PeerIdentity peer_id;
174
175 /**
176 * @brief Handle to the transport service
177 */
178 struct GNUNET_SERVICE_Handle *tsh;
179
180 /**
181 * @brief Task that will be run on shutdown to stop and clean transport
182 * service
183 */
184 struct GNUNET_SCHEDULER_Task *ts_shutdown_task;
185
186
187 /**
188 * @brief Process of the communicator
189 */
190 struct GNUNET_OS_Process *c_proc;
191
192 /**
193 * NAT process
194 */
195 struct GNUNET_OS_Process *nat_proc;
196
197 /**
198 * resolver service process
199 */
200 struct GNUNET_OS_Process *resolver_proc;
201
202 /**
203 * statistics service process
204 */
205 struct GNUNET_OS_Process *stat_proc;
206
207 /**
208 * peerstore service process
209 */
210 struct GNUNET_OS_Process *ps_proc;
211
212 /**
213 * @brief Task that will be run on shutdown to stop and clean communicator
214 */
215 struct GNUNET_SCHEDULER_Task *c_shutdown_task;
216
217 /**
218 * @brief Characteristics of the communicator
219 */
220 enum GNUNET_TRANSPORT_CommunicatorCharacteristics c_characteristics;
221
222 /**
223 * @brief Specifies supported addresses
224 */
225 char *c_addr_prefix;
226
227 /**
228 * @brief Specifies supported addresses
229 */
230 char *c_address;
231
232 /**
233 * @brief Head of the DLL of queues associated with this communicator
234 */
235 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_head;
236
237 /**
238 * @brief Tail of the DLL of queues associated with this communicator
239 */
240 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_tail;
241
242 /* Callbacks + Closures */
243 /**
244 * @brief Callback called when a new communicator connects
245 */
246 GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback
247 communicator_available_cb;
248
249 /**
250 * @brief Callback called when a new communicator connects
251 */
252 GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb;
253
254 /**
255 * @brief Callback called when a new communicator connects
256 */
257 GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb;
258
259 /**
260 * @brief Callback called when a new communicator connects
261 */
262 GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb;
263
264 /**
265 * @brief Callback called when a new communicator connects
266 */
267 GNUNET_TRANSPORT_TESTING_IncomingMessageCallback incoming_msg_cb;
268
269 /**
270 * @brief Backchannel callback
271 */
272 GNUNET_TRANSPORT_TESTING_BackchannelCallback bc_cb;
273
274 /**
275 * Our service handle
276 */
277 struct GNUNET_SERVICE_Handle *sh;
278
279 /**
280 * @brief Closure to the callback
281 */
282 void *cb_cls;
283
284 /**
285 * Callback to call when message ack received.
286 */
287 GNUNET_SCHEDULER_TaskCallback cont;
288
289 /**
290 * Closure for cont
291 */
292 void *cont_cls;
293
294 /**
295 * Backchannel supported
296 */
297 int bc_enabled;
298};
299
300/**
301 * @brief Start communicator part of transport service and communicator
302 *
303 * @param service_name Name of the service
304 * @param cfg Configuration handle
305 * @param communicator_available Callback that is called when a new
306 * communicator becomes available
307 * @param add_address_cb Callback handling new addresses
308 * @param queue_create_reply_cb Callback handling success of queue requests
309 * @param add_queue_cb Callback handling freshly created queues
310 * @param incoming_message_cb Callback handling incoming messages
311 * @param cb_cls Closure to @p communicator_available
312 *
313 * @return Handle to the communicator duo
314 */
315struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *
316GNUNET_TRANSPORT_TESTING_transport_communicator_service_start (
317 const char *service_name,
318 const char *binary_name,
319 const char *cfg_filename,
320 const struct GNUNET_PeerIdentity *peer_id,
321 GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback
322 communicator_available_cb,
323 GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb,
324 GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb,
325 GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb,
326 GNUNET_TRANSPORT_TESTING_IncomingMessageCallback incoming_message_cb,
327 GNUNET_TRANSPORT_TESTING_BackchannelCallback bc_cb,
328 void *cb_cls);
329
330
331void
332GNUNET_TRANSPORT_TESTING_transport_communicator_service_stop (
333 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h);
334
335
336/**
337 * @brief Instruct communicator to open a queue
338 *
339 * @param tc_h Handle to communicator which shall open queue
340 * @param peer_id Towards which peer
341 * @param address For which address
342 */
343void
344GNUNET_TRANSPORT_TESTING_transport_communicator_open_queue (struct
345 GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle
346 *tc_h,
347 const struct
348 GNUNET_PeerIdentity
349 *peer_id,
350 const char *address);
351
352
353/**
354 * @brief Instruct communicator to send data
355 *
356 * @param tc_queue The queue to use for sending
357 * @param cont function to call when done sending
358 * @param cont_cls closure for @a cont
359 * @param payload Data to send
360 * @param payload_size Size of the @a payload
361 */
362void
363GNUNET_TRANSPORT_TESTING_transport_communicator_send (struct
364 GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle
365 *tc_h,
366 GNUNET_SCHEDULER_TaskCallback
367 cont,
368 void *cont_cls,
369 const void *payload,
370 size_t payload_size);
diff --git a/src/transport/transport-testing-filenames2.c b/src/transport/transport-testing-filenames2.c
deleted file mode 100644
index 59fa1ebd5..000000000
--- a/src/transport/transport-testing-filenames2.c
+++ /dev/null
@@ -1,203 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2006, 2009, 2015, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file transport-testing-filenames.c
22 * @brief convenience string manipulation functions for tests
23 * @author Matthias Wachs
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "transport-testing2.h"
28
29
30/**
31 * Removes all directory separators from absolute filename
32 *
33 * @param file the absolute file name, e.g. as found in argv[0]
34 * @return extracted file name, has to be freed by caller
35 */
36static char *
37extract_filename (const char *file)
38{
39 char *pch = GNUNET_strdup (file);
40 char *backup = pch;
41 char *filename = NULL;
42 char *res;
43
44 if (NULL != strstr (pch, "/"))
45 {
46 pch = strtok (pch, "/");
47 while (pch != NULL)
48 {
49 pch = strtok (NULL, "/");
50 if (pch != NULL)
51 {
52 filename = pch;
53 }
54 }
55 }
56 else
57 filename = pch;
58
59 res = GNUNET_strdup (filename);
60 GNUNET_free (backup);
61 return res;
62}
63
64
65/**
66 * Extracts the test filename from an absolute file name and removes
67 * the extension
68 *
69 * @param file absolute file name
70 * @return the result
71 */
72char *
73GNUNET_TRANSPORT_TESTING_get_test_name (const char *file)
74{
75 char *backup = extract_filename (file);
76 char *filename = backup;
77 char *dotexe;
78 char *ret;
79
80 if (NULL == filename)
81 return NULL;
82
83 /* remove "lt-" */
84 filename = strstr (filename, "test");
85 if (NULL == filename)
86 {
87 GNUNET_free (backup);
88 return NULL;
89 }
90
91 /* remove ".exe" */
92 if (NULL != (dotexe = strstr (filename, ".exe")))
93 dotexe[0] = '\0';
94 ret = GNUNET_strdup (filename);
95 GNUNET_free (backup);
96 return ret;
97}
98
99
100/**
101 * Extracts the filename from an absolute file name and removes the extension
102 *
103 * @param file absolute file name
104 * @return the result
105 */
106char *
107GNUNET_TRANSPORT_TESTING_get_test_source_name (const char *file)
108{
109 char *src = extract_filename (file);
110 char *split;
111
112 split = strstr (src, ".");
113 if (NULL != split)
114 split[0] = '\0';
115 return src;
116}
117
118
119/**
120 * Extracts the plugin name from an absolute file name and the test name
121 *
122 * @param file absolute file name
123 * @param test test name
124 * @return the result
125 */
126char *
127GNUNET_TRANSPORT_TESTING_get_test_plugin_name (const char *file,
128 const char *test)
129{
130 char *filename;
131 char *dotexe;
132 char *e = extract_filename (file);
133 char *t = extract_filename (test);
134 char *ret;
135
136 if (NULL == e)
137 goto fail;
138 /* remove "lt-" */
139 filename = strstr (e, "tes");
140 if (NULL == filename)
141 goto fail;
142 /* remove ".exe" */
143 if (NULL != (dotexe = strstr (filename, ".exe")))
144 dotexe[0] = '\0';
145
146 /* find last _ */
147 filename = strstr (filename, t);
148 if (NULL == filename)
149 goto fail;
150 /* copy plugin */
151 filename += strlen (t);
152 if ('\0' != *filename)
153 filename++;
154 ret = GNUNET_strdup (filename);
155 goto suc;
156fail:
157 ret = NULL;
158suc:
159 GNUNET_free (t);
160 GNUNET_free (e);
161 return ret;
162}
163
164
165/**
166 * This function takes the filename (e.g. argv[0), removes a "lt-"-prefix and
167 * if existing ".exe"-prefix and adds the peer-number
168 *
169 * @param file filename of the test, e.g. argv[0]
170 * @param count peer number
171 * @return the result
172 */
173char *
174GNUNET_TRANSPORT_TESTING_get_config_name (const char *file,
175 int count)
176{
177 char *filename = extract_filename (file);
178 char *backup = filename;
179 char *dotexe;
180 char *ret;
181
182 if (NULL == filename)
183 return NULL;
184 /* remove "lt-" */
185 filename = strstr (filename, "test");
186 if (NULL == filename)
187 goto fail;
188 /* remove ".exe" */
189 if (NULL != (dotexe = strstr (filename, ".exe")))
190 dotexe[0] = '\0';
191 GNUNET_asprintf (&ret,
192 "%s_peer%u.conf",
193 filename,
194 count);
195 GNUNET_free (backup);
196 return ret;
197fail:
198 GNUNET_free (backup);
199 return NULL;
200}
201
202
203/* end of transport-testing-filenames.c */
diff --git a/src/transport/transport-testing-loggers2.c b/src/transport/transport-testing-loggers2.c
deleted file mode 100644
index e6c79b78a..000000000
--- a/src/transport/transport-testing-loggers2.c
+++ /dev/null
@@ -1,81 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file transport-testing-loggers.c
22 * @brief convenience functions for logging common events in tests
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "transport-testing2.h"
27
28
29/**
30 * Log a connect event.
31 *
32 * @param cls NULL
33 * @param me peer that had the event
34 * @param other peer that connected.
35 */
36void
37GNUNET_TRANSPORT_TESTING_log_connect (void *cls,
38 struct
39 GNUNET_TRANSPORT_TESTING_PeerContext *me,
40 const struct GNUNET_PeerIdentity *other)
41{
42 char *ps;
43
44 ps = GNUNET_strdup (GNUNET_i2s (&me->id));
45 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
46 "Peer %s connected to %u (%s)!\n",
47 GNUNET_i2s (other),
48 me->no,
49 ps);
50 GNUNET_free (ps);
51}
52
53
54/**
55 * Log a disconnect event.
56 *
57 * @param cls NULL
58 * @param me peer that had the event
59 * @param other peer that disconnected.
60 */
61void
62GNUNET_TRANSPORT_TESTING_log_disconnect (void *cls,
63 struct
64 GNUNET_TRANSPORT_TESTING_PeerContext *
65 me,
66 const struct
67 GNUNET_PeerIdentity *other)
68{
69 char *ps;
70
71 ps = GNUNET_strdup (GNUNET_i2s (&me->id));
72 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
73 "Peer `%s' disconnected from %u (%s)!\n",
74 GNUNET_i2s (other),
75 me->no,
76 ps);
77 GNUNET_free (ps);
78}
79
80
81/* end of transport-testing-loggers.c */
diff --git a/src/transport/transport-testing-main2.c b/src/transport/transport-testing-main2.c
deleted file mode 100644
index 0a1710922..000000000
--- a/src/transport/transport-testing-main2.c
+++ /dev/null
@@ -1,614 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file transport-testing-main.c
22 * @brief convenience main function for tests
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "transport-testing2.h"
27
28
29/**
30 * Closure for #connect_cb.
31 */
32struct GNUNET_TRANSPORT_TESTING_ConnectRequestList
33{
34 /**
35 * Stored in a DLL.
36 */
37 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *next;
38
39 /**
40 * Stored in a DLL.
41 */
42 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *prev;
43
44 /**
45 * Overall context we are in.
46 */
47 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
48
49 /**
50 * Connect request this is about.
51 */
52 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cr;
53
54 /**
55 * Peer being connected.
56 */
57 struct GNUNET_TRANSPORT_TESTING_PeerContext *p1;
58
59 /**
60 * Peer being connected.
61 */
62 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2;
63};
64
65
66/**
67 * Shutdown function for the test. Stops all peers.
68 *
69 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *`
70 */
71static void
72do_shutdown (void *cls)
73{
74 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
75 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl;
76
77 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
78 "Testcase shutting down\n");
79 if (NULL != ccc->shutdown_task)
80 ccc->shutdown_task (ccc->shutdown_task_cls);
81 if (NULL != ccc->timeout_task)
82 {
83 GNUNET_SCHEDULER_cancel (ccc->timeout_task);
84 ccc->timeout_task = NULL;
85 }
86 if (NULL != ccc->connect_task)
87 {
88 GNUNET_SCHEDULER_cancel (ccc->connect_task);
89 ccc->connect_task = NULL;
90 }
91 while (NULL != (crl = ccc->crl_head))
92 {
93 GNUNET_CONTAINER_DLL_remove (ccc->crl_head,
94 ccc->crl_tail,
95 crl);
96 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (crl->cr);
97 GNUNET_free (crl);
98 }
99 for (unsigned int i = 0; i < ccc->num_peers; i++)
100 {
101 if (NULL != ccc->p[i])
102 {
103 GNUNET_TRANSPORT_TESTING_stop_peer (ccc->p[i]);
104 ccc->p[i] = NULL;
105 }
106 }
107}
108
109
110/**
111 * Testcase hit timeout, shut it down with error.
112 *
113 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *`
114 */
115static void
116do_timeout (void *cls)
117{
118 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
119
120 ccc->timeout_task = NULL;
121 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
122 "Testcase timed out\n");
123 ccc->global_ret = GNUNET_SYSERR;
124 GNUNET_SCHEDULER_shutdown ();
125}
126
127
128/**
129 * Internal data structure. Closure for
130 * #connect_cb, #disconnect_cb, #my_nc and #start_cb.
131 * Allows us to identify which peer this is about.
132 */
133struct GNUNET_TRANSPORT_TESTING_InternalPeerContext
134{
135 /**
136 * Overall context of the callback.
137 */
138 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
139
140 /**
141 * Offset of the peer this is about.
142 */
143 unsigned int off;
144};
145
146
147/**
148 * Information tracked per connected peer.
149 */
150struct ConnectPairInfo
151{
152 /**
153 * Peer this is about.
154 */
155 const struct GNUNET_PeerIdentity *sender;
156
157 /**
158 * Information about the receiving peer.
159 */
160 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi;
161};
162
163
164/**
165 * Function called when we connected two peers. Once we have gotten
166 * to the clique, launch test-specific logic.
167 *
168 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *`
169 */
170static void
171connect_cb (void *cls)
172{
173 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl = cls;
174 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = crl->ccc;
175
176 GNUNET_CONTAINER_DLL_remove (ccc->crl_head,
177 ccc->crl_tail,
178 crl);
179 {
180 char *p1_c = GNUNET_strdup (GNUNET_i2s (&crl->p1->id));
181
182 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
183 "Peers connected: %u (%s) <-> %u (%s)\n",
184 crl->p1->no,
185 p1_c,
186 crl->p2->no,
187 GNUNET_i2s (&crl->p2->id));
188 GNUNET_free (p1_c);
189 GNUNET_free (crl);
190 }
191 if (NULL == ccc->crl_head)
192 {
193 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
194 "All connections UP, launching custom test logic.\n");
195 GNUNET_SCHEDULER_add_now (ccc->connect_continuation,
196 ccc->connect_continuation_cls);
197 }
198}
199
200
201/**
202 * Find peer by peer ID.
203 *
204 * @param ccc context to search
205 * @param peer peer to look for
206 * @return NULL if @a peer was not found
207 */
208struct GNUNET_TRANSPORT_TESTING_PeerContext *
209GNUNET_TRANSPORT_TESTING_find_peer (struct
210 GNUNET_TRANSPORT_TESTING_ConnectCheckContext
211 *ccc,
212 const struct GNUNET_PeerIdentity *peer)
213{
214 for (unsigned int i = 0; i < ccc->num_peers; i++)
215 if ((NULL != ccc->p[i]) &&
216 (0 == memcmp (peer,
217 &ccc->p[i]->id,
218 sizeof(*peer))))
219 return ccc->p[i];
220 return NULL;
221}
222
223
224/**
225 * Wrapper around peers connecting. Calls client's nc function.
226 *
227 * @param cls our `struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *`
228 * @param peer peer we got connected to
229 * @param mq message queue for transmissions to @a peer
230 * @return closure for message handlers
231 */
232static void *
233my_nc (void *cls,
234 const struct GNUNET_PeerIdentity *peer,
235 struct GNUNET_MQ_Handle *mq)
236{
237 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cls;
238 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
239 struct ConnectPairInfo *cpi;
240
241 if (NULL != ccc->nc)
242 ccc->nc (ccc->cls,
243 ccc->p[ipi->off],
244 peer);
245 cpi = GNUNET_new (struct ConnectPairInfo);
246 cpi->ipi = ipi;
247 cpi->sender = peer; /* valid until disconnect */
248 return cpi;
249}
250
251
252/**
253 * Wrapper around peers disconnecting. Calls client's nd function.
254 *
255 * @param cls our `struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *`
256 * @param peer peer we got disconnected from
257 * @param custom_cls return value from @a my_nc
258 */
259static void
260my_nd (void *cls,
261 const struct GNUNET_PeerIdentity *peer,
262 void *custom_cls)
263{
264 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cls;
265 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
266 struct ConnectPairInfo *cpi = custom_cls;
267
268 if (NULL != ccc->nd)
269 ccc->nd (ccc->cls,
270 ccc->p[ipi->off],
271 peer);
272 GNUNET_free (cpi);
273}
274
275
276/**
277 * Wrapper around receiving data. Calls client's rec function.
278 *
279 * @param cls our `struct ConnectPairInfo *`
280 * @param message message we received
281 * @return #GNUNET_OK (all messages are fine)
282 */
283static int
284check_test (void *cls,
285 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
286{
287 return GNUNET_OK;
288}
289
290
291/**
292 * Wrapper around receiving data. Calls client's rec function.
293 *
294 * @param cls our `struct ConnectPairInfo *`
295 * @param message message we received
296 */
297static void
298handle_test (void *cls,
299 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
300{
301 struct ConnectPairInfo *cpi = cls;
302 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cpi->ipi;
303 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
304
305 if (NULL != ccc->rec)
306 ccc->rec (ccc->cls,
307 ccc->p[ipi->off],
308 cpi->sender,
309 message);
310}
311
312
313/**
314 * Wrapper around receiving data. Calls client's rec function.
315 *
316 * @param cls our `struct ConnectPairInfo *`
317 * @param message message we received
318 * @return #GNUNET_OK (all messages are fine)
319 */
320static int
321check_test2 (void *cls,
322 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
323{
324 return GNUNET_OK;
325}
326
327
328/**
329 * Wrapper around receiving data. Calls client's rec function.
330 *
331 * @param cls our `struct ConnectPairInfo *`
332 * @param message message we received
333 */
334static void
335handle_test2 (void *cls,
336 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
337{
338 struct ConnectPairInfo *cpi = cls;
339 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cpi->ipi;
340 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
341
342 if (NULL != ccc->rec)
343 ccc->rec (ccc->cls,
344 ccc->p[ipi->off],
345 cpi->sender,
346 message);
347}
348
349
350/**
351 * Connect the peers as a clique.
352 *
353 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
354 */
355static void
356do_connect (void *cls)
357{
358 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
359
360 ccc->connect_task = NULL;
361 for (unsigned int i = 0; i < ccc->num_peers; i++)
362 for (unsigned int j = (ccc->bi_directional ? 0 : i + 1); j < ccc->num_peers;
363 j++)
364 {
365 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl;
366
367 if (i == j)
368 continue;
369 crl = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequestList);
370 GNUNET_CONTAINER_DLL_insert (ccc->crl_head,
371 ccc->crl_tail,
372 crl);
373 crl->ccc = ccc;
374 crl->p1 = ccc->p[i];
375 crl->p2 = ccc->p[j];
376 {
377 char *sender_c = GNUNET_strdup (GNUNET_i2s (&ccc->p[0]->id));
378
379 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
380 "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n",
381 ccc->p[0]->no,
382 sender_c,
383 ccc->p[1]->no,
384 GNUNET_i2s (&ccc->p[1]->id));
385 GNUNET_free (sender_c);
386 }
387 crl->cr = GNUNET_TRANSPORT_TESTING_connect_peers (ccc->p[i],
388 ccc->p[j],
389 &connect_cb,
390 crl);
391 }
392}
393
394
395/**
396 * Function called once we have successfully launched a peer.
397 * Once all peers have been launched, we connect all of them
398 * in a clique.
399 *
400 * @param cls our `struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *`
401 */
402static void
403start_cb (void *cls)
404{
405 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cls;
406 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
407 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = ccc->p[ipi->off];
408
409 ccc->started++;
410 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
411 "Peer %u (`%s') started\n",
412 p->no,
413 GNUNET_i2s (&p->id));
414 if (ccc->started != ccc->num_peers)
415 return;
416 if (NULL != ccc->pre_connect_task)
417 {
418 /* Run the custom per-connect job, then give it a second to
419 go into effect before we continue connecting peers. */
420 ccc->pre_connect_task (ccc->pre_connect_task_cls);
421 ccc->connect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
422 &do_connect,
423 ccc);
424 }
425 else
426 {
427 do_connect (ccc);
428 }
429}
430
431
432/**
433 * Function run from #GNUNET_TRANSPORT_TESTING_connect_check
434 * once the scheduler is up. Should launch the peers and
435 * then in the continuations try to connect them.
436 *
437 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *`
438 * @param args ignored
439 * @param cfgfile ignored
440 * @param cfg configuration
441 */
442static void
443connect_check_run (void *cls,
444 char *const *args,
445 const char *cfgfile,
446 const struct GNUNET_CONFIGURATION_Handle *cfg)
447{
448 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
449 int ok;
450
451 ccc->cfg = cfg;
452 ccc->timeout_task = GNUNET_SCHEDULER_add_delayed (ccc->timeout,
453 &do_timeout,
454 ccc);
455 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
456 ccc);
457 ok = GNUNET_OK;
458 for (unsigned int i = 0; i < ccc->num_peers; i++)
459 {
460 struct GNUNET_MQ_MessageHandler handlers[] = {
461 GNUNET_MQ_hd_var_size (test,
462 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
463 struct GNUNET_TRANSPORT_TESTING_TestMessage,
464 NULL),
465 GNUNET_MQ_hd_var_size (test2,
466 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE2,
467 struct GNUNET_TRANSPORT_TESTING_TestMessage,
468 NULL),
469 GNUNET_MQ_handler_end ()
470 };
471 ccc->p[i] = GNUNET_TRANSPORT_TESTING_start_peer (ccc->tth,
472 ccc->cfg_files[i],
473 i + 1,
474 handlers,
475 &my_nc,
476 &my_nd,
477 &ccc->ip[i],
478 &start_cb,
479 &ccc->ip[i]);
480 if (NULL == ccc->p[i])
481 ok = GNUNET_SYSERR;
482 }
483 if (GNUNET_OK != ok)
484 {
485 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
486 "Fail! Could not start peers!\n");
487 GNUNET_SCHEDULER_shutdown ();
488 }
489}
490
491
492/**
493 * Common implementation of the #GNUNET_TRANSPORT_TESTING_CheckCallback.
494 * Starts and connects the two peers, then invokes the
495 * `connect_continuation` from @a cls. Sets up a timeout to
496 * abort the test, and a shutdown handler to clean up properly
497 * on exit.
498 *
499 * @param cls closure of type `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
500 * @param tth_ initialized testing handle
501 * @param test_plugin_ name of the plugin
502 * @param test_name_ name of the test
503 * @param num_peers number of entries in the @a cfg_file array
504 * @param cfg_files array of names of configuration files for the peers
505 * @return #GNUNET_SYSERR on error
506 */
507int
508GNUNET_TRANSPORT_TESTING_connect_check (void *cls,
509 struct GNUNET_TRANSPORT_TESTING_Handle *
510 tth_,
511 const char *test_plugin_,
512 const char *test_name_,
513 unsigned int num_peers,
514 char *cfg_files[])
515{
516 static struct GNUNET_GETOPT_CommandLineOption options[] = {
517 GNUNET_GETOPT_OPTION_END
518 };
519 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
520 struct GNUNET_TRANSPORT_TESTING_PeerContext *p[num_peers];
521 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext ip[num_peers];
522 char *argv[] = {
523 (char *) test_name_,
524 "-c",
525 (char *) ccc->config_file,
526 NULL
527 };
528
529 ccc->num_peers = num_peers;
530 ccc->cfg_files = cfg_files;
531 ccc->test_plugin = test_plugin_;
532 ccc->test_name = test_name_;
533 ccc->tth = tth_;
534 ccc->global_ret = GNUNET_OK;
535 ccc->p = p;
536 ccc->ip = ip;
537 for (unsigned int i = 0; i < num_peers; i++)
538 {
539 ip[i].off = i;
540 ip[i].ccc = ccc;
541 }
542 if (GNUNET_OK !=
543 GNUNET_PROGRAM_run ((sizeof(argv) / sizeof(char *)) - 1,
544 argv,
545 test_name_,
546 "nohelp",
547 options,
548 &connect_check_run,
549 ccc))
550 return GNUNET_SYSERR;
551 return ccc->global_ret;
552}
553
554
555/**
556 * Setup testcase. Calls @a check with the data the test needs.
557 *
558 * @param argv0 binary name (argv[0])
559 * @param filename source file name (__FILE__)
560 * @param num_peers number of peers to start
561 * @param check main function to run
562 * @param check_cls closure for @a check
563 * @return #GNUNET_OK on success
564 */
565int
566GNUNET_TRANSPORT_TESTING_main_ (const char *argv0,
567 const char *filename,
568 unsigned int num_peers,
569 GNUNET_TRANSPORT_TESTING_CheckCallback check,
570 void *check_cls)
571{
572 struct GNUNET_TRANSPORT_TESTING_Handle *tth;
573 char *test_name;
574 char *test_source;
575 char *test_plugin;
576 char *cfg_names[num_peers];
577 int ret;
578
579 ret = GNUNET_OK;
580 test_name = GNUNET_TRANSPORT_TESTING_get_test_name (argv0);
581 GNUNET_log_setup (test_name,
582 "WARNING",
583 NULL);
584 test_source = GNUNET_TRANSPORT_TESTING_get_test_source_name (filename);
585 test_plugin = GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv0,
586 test_source);
587 for (unsigned int i = 0; i < num_peers; i++)
588 cfg_names[i] = GNUNET_TRANSPORT_TESTING_get_config_name (argv0,
589 i + 1);
590 tth = GNUNET_TRANSPORT_TESTING_init ();
591 if (NULL == tth)
592 {
593 ret = GNUNET_SYSERR;
594 }
595 else
596 {
597 ret = check (check_cls,
598 tth,
599 test_plugin,
600 test_name,
601 num_peers,
602 cfg_names);
603 GNUNET_TRANSPORT_TESTING_done (tth);
604 }
605 for (unsigned int i = 0; i < num_peers; i++)
606 GNUNET_free (cfg_names[i]);
607 GNUNET_free (test_source);
608 GNUNET_free (test_plugin);
609 GNUNET_free (test_name);
610 return ret;
611}
612
613
614/* end of transport-testing-main.c */
diff --git a/src/transport/transport-testing-send2.c b/src/transport/transport-testing-send2.c
deleted file mode 100644
index c48dc3a4a..000000000
--- a/src/transport/transport-testing-send2.c
+++ /dev/null
@@ -1,241 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file transport-testing-send.c
22 * @brief convenience transmission function for tests
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "transport-testing2.h"
27
28/**
29 * Acceptable transmission delay.
30 */
31#define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply ( \
32 GNUNET_TIME_UNIT_SECONDS, 30)
33
34
35/**
36 * Return @a cx in @a cls.
37 */
38static void
39find_cr (void *cls,
40 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
41{
42 struct GNUNET_TRANSPORT_TESTING_ConnectRequest **cr = cls;
43
44 if (GNUNET_NO == cx->connected)
45 return;
46 *cr = cx;
47}
48
49
50/**
51 * Send a test message of type @a mtype and size @a msize from
52 * peer @a sender to peer @a receiver. The peers should be
53 * connected when this function is called.
54 *
55 * @param sender the sending peer
56 * @param receiver the receiving peer
57 * @param mtype message type to use
58 * @param msize size of the message, at least `sizeof (struct GNUNET_TRANSPORT_TESTING_TestMessage)`
59 * @param num unique message number
60 * @param cont continuation to call after transmission
61 * @param cont_cls closure for @a cont
62 * @return #GNUNET_OK if message was queued,
63 * #GNUNET_NO if peers are not connected
64 * #GNUNET_SYSERR if @a msize is illegal
65 */
66int
67GNUNET_TRANSPORT_TESTING_send (struct
68 GNUNET_TRANSPORT_TESTING_PeerContext *sender,
69 struct GNUNET_TRANSPORT_TESTING_PeerContext *
70 receiver,
71 uint16_t mtype,
72 uint16_t msize,
73 uint32_t num,
74 GNUNET_SCHEDULER_TaskCallback cont,
75 void *cont_cls)
76{
77 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cr;
78 struct GNUNET_MQ_Envelope *env;
79 struct GNUNET_TRANSPORT_TESTING_TestMessage *test;
80
81 if (msize < sizeof(struct GNUNET_TRANSPORT_TESTING_TestMessage))
82 {
83 GNUNET_break (0);
84 return GNUNET_SYSERR;
85 }
86 cr = NULL;
87 GNUNET_TRANSPORT_TESTING_find_connecting_context (sender,
88 receiver,
89 &find_cr,
90 &cr);
91 if (NULL == cr)
92 GNUNET_TRANSPORT_TESTING_find_connecting_context (receiver,
93 sender,
94 &find_cr,
95 &cr);
96 if (NULL == cr)
97 {
98 GNUNET_break (0);
99 return GNUNET_NO;
100 }
101 if (NULL == cr->mq)
102 {
103 GNUNET_break (0);
104 return GNUNET_NO;
105 }
106 {
107 char *receiver_s = GNUNET_strdup (GNUNET_i2s (&receiver->id));
108
109 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
110 "Sending message from peer %u (`%s') -> peer %u (`%s') !\n",
111 sender->no,
112 GNUNET_i2s (&sender->id),
113 receiver->no,
114 receiver_s);
115 GNUNET_free (receiver_s);
116 }
117 env = GNUNET_MQ_msg_extra (test,
118 msize - sizeof(*test),
119 mtype);
120 test->num = htonl (num);
121 memset (&test[1],
122 num,
123 msize - sizeof(*test));
124 GNUNET_MQ_notify_sent (env,
125 cont,
126 cont_cls);
127 GNUNET_MQ_send (cr->mq,
128 env);
129 return GNUNET_OK;
130}
131
132
133/**
134 * Task that sends a test message from the
135 * first peer to the second peer.
136 *
137 * @param ccc context which should contain at least two peers, the
138 * first two of which should be currently connected
139 * @param size desired message size
140 * @param cont continuation to call after transmission
141 * @param cont_cls closure for @a cont
142 */
143static void
144do_send (struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc,
145 uint16_t size,
146 GNUNET_SCHEDULER_TaskCallback cont,
147 void *cont_cls)
148{
149 int ret;
150
151 ccc->global_ret = GNUNET_SYSERR;
152 ret = GNUNET_TRANSPORT_TESTING_send (ccc->p[0],
153 ccc->p[1],
154 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
155 size,
156 ccc->send_num_gen++,
157 cont,
158 cont_cls);
159 GNUNET_assert (GNUNET_SYSERR != ret);
160 if (GNUNET_NO == ret)
161 {
162 GNUNET_break (0);
163 ccc->global_ret = GNUNET_SYSERR;
164 GNUNET_SCHEDULER_shutdown ();
165 }
166}
167
168
169/**
170 * Task that sends a minimalistic test message from the
171 * first peer to the second peer.
172 *
173 * @param cls the `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
174 * which should contain at least two peers, the first two
175 * of which should be currently connected
176 */
177void
178GNUNET_TRANSPORT_TESTING_simple_send (void *cls)
179{
180 struct GNUNET_TRANSPORT_TESTING_SendClosure *sc = cls;
181 int done;
182 size_t msize;
183
184 if (0 < sc->num_messages)
185 {
186 sc->num_messages--;
187 done = (0 == sc->num_messages);
188 }
189 else
190 {
191 done = 0; /* infinite loop */
192 }
193 msize = sizeof(struct GNUNET_TRANSPORT_TESTING_TestMessage);
194 if (NULL != sc->get_size_cb)
195 msize = sc->get_size_cb (sc->num_messages);
196 /* if this was the last message, call the continuation,
197 otherwise call this function again */
198 do_send (sc->ccc,
199 msize,
200 done ? sc->cont : &GNUNET_TRANSPORT_TESTING_simple_send,
201 done ? sc->cont_cls : sc);
202}
203
204
205/**
206 * Task that sends a large test message from the
207 * first peer to the second peer.
208 *
209 * @param cls the `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
210 * which should contain at least two peers, the first two
211 * of which should be currently connected
212 */
213void
214GNUNET_TRANSPORT_TESTING_large_send (void *cls)
215{
216 struct GNUNET_TRANSPORT_TESTING_SendClosure *sc = cls;
217 int done;
218 size_t msize;
219
220 if (0 < sc->num_messages)
221 {
222 sc->num_messages--;
223 done = (0 == sc->num_messages);
224 }
225 else
226 {
227 done = 0; /* infinite loop */
228 }
229 msize = 2600;
230 if (NULL != sc->get_size_cb)
231 msize = sc->get_size_cb (sc->num_messages);
232 /* if this was the last message, call the continuation,
233 otherwise call this function again */
234 do_send (sc->ccc,
235 msize,
236 done ? sc->cont : &GNUNET_TRANSPORT_TESTING_large_send,
237 done ? sc->cont_cls : sc);
238}
239
240
241/* end of transport-testing-send.c */
diff --git a/src/transport/transport-testing2.c b/src/transport/transport-testing2.c
deleted file mode 100644
index afa0b0ad4..000000000
--- a/src/transport/transport-testing2.c
+++ /dev/null
@@ -1,924 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2006, 2009, 2015, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file transport-testing.c
22 * @brief testing lib for transport service
23 * @author Matthias Wachs
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "transport-testing2.h"
28
29
30#define LOG(kind, ...) GNUNET_log_from (kind, "transport-testing", __VA_ARGS__)
31
32
33static struct GNUNET_TRANSPORT_TESTING_PeerContext *
34find_peer_context (struct GNUNET_TRANSPORT_TESTING_Handle *tth,
35 const struct GNUNET_PeerIdentity *peer)
36{
37 struct GNUNET_TRANSPORT_TESTING_PeerContext *t;
38
39 for (t = tth->p_head; NULL != t; t = t->next)
40 if (0 == memcmp (&t->id,
41 peer,
42 sizeof(struct GNUNET_PeerIdentity)))
43 return t;
44 return NULL;
45}
46
47
48/**
49 * Find any connecting context matching the given pair of peers.
50 *
51 * @param p1 first peer
52 * @param p2 second peer
53 * @param cb function to call
54 * @param cb_cls closure for @a cb
55 */
56void
57GNUNET_TRANSPORT_TESTING_find_connecting_context (struct
58 GNUNET_TRANSPORT_TESTING_PeerContext
59 *p1,
60 struct
61 GNUNET_TRANSPORT_TESTING_PeerContext
62 *p2,
63 GNUNET_TRANSPORT_TESTING_ConnectContextCallback
64 cb,
65 void *cb_cls)
66{
67 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p1->tth;
68 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
69 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
70
71 for (cc = tth->cc_head; NULL != cc; cc = ccn)
72 {
73 ccn = cc->next;
74 if ((cc->p1 == p1) &&
75 (cc->p2 == p2))
76 cb (cb_cls,
77 cc);
78 }
79}
80
81
82static void
83set_p1c (void *cls,
84 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
85{
86 int *found = cls;
87
88 if (NULL != found)
89 *found = GNUNET_YES;
90 cx->p1_c = GNUNET_YES;
91}
92
93
94static void
95set_mq (void *cls,
96 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
97{
98 struct GNUNET_MQ_Handle *mq = cls;
99
100 cx->mq = mq;
101}
102
103
104static void
105set_p2c (void *cls,
106 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
107{
108 int *found = cls;
109
110 if (NULL != found)
111 *found = GNUNET_YES;
112 cx->p2_c = GNUNET_YES;
113}
114
115
116static void
117clear_p1c (void *cls,
118 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
119{
120 int *found = cls;
121
122 if (NULL != found)
123 *found = GNUNET_YES;
124 cx->p1_c = GNUNET_NO;
125}
126
127
128static void
129clear_p2c (void *cls,
130 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
131{
132 int *found = cls;
133
134 if (NULL != found)
135 *found = GNUNET_YES;
136 cx->p2_c = GNUNET_NO;
137}
138
139
140static void *
141notify_connect (void *cls,
142 const struct GNUNET_PeerIdentity *peer,
143 struct GNUNET_MQ_Handle *mq)
144{
145 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
146 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
147 char *p2_s;
148 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2;
149 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
150 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
151 int found;
152 void *ret;
153
154 p2 = find_peer_context (p->tth,
155 peer);
156 if (NULL != p->nc)
157 ret = p->nc (p->cb_cls,
158 peer,
159 mq);
160 else
161 ret = NULL;
162
163 if (NULL != p2)
164 GNUNET_asprintf (&p2_s,
165 "%u (`%s')",
166 p2->no,
167 GNUNET_i2s (&p2->id));
168 else
169 GNUNET_asprintf (&p2_s,
170 "`%s'",
171 GNUNET_i2s (peer));
172 LOG (GNUNET_ERROR_TYPE_DEBUG,
173 "Peers %s connected to peer %u (`%s')\n",
174 p2_s,
175 p->no,
176 GNUNET_i2s (&p->id));
177 GNUNET_free (p2_s);
178 /* update flags in connecting contexts */
179 found = GNUNET_NO;
180 GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
181 p2,
182 &set_p1c,
183 &found);
184 if (GNUNET_NO == found)
185 {
186 cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest);
187 cc->p1 = p;
188 cc->p2 = p2;
189 cc->p1_c = GNUNET_YES;
190 GNUNET_CONTAINER_DLL_insert (tth->cc_head,
191 tth->cc_tail,
192 cc);
193 }
194 found = GNUNET_NO;
195 GNUNET_TRANSPORT_TESTING_find_connecting_context (p2,
196 p,
197 &set_p2c,
198 &found);
199 if (GNUNET_NO == found)
200 {
201 cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest);
202 cc->p1 = p2;
203 cc->p2 = p;
204 cc->p1_c = GNUNET_YES;
205 GNUNET_CONTAINER_DLL_insert (tth->cc_head,
206 tth->cc_tail,
207 cc);
208 }
209 GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
210 p2,
211 &set_mq,
212 mq);
213 /* update set connected flag for all requests */
214 for (cc = tth->cc_head; NULL != cc; cc = cc->next)
215 {
216 if (GNUNET_YES == cc->connected)
217 continue;
218 if ((GNUNET_YES == cc->p1_c) &&
219 (GNUNET_YES == cc->p2_c))
220 {
221 cc->connected = GNUNET_YES;
222 /* stop trying to connect */
223 if (NULL != cc->tct)
224 {
225 GNUNET_SCHEDULER_cancel (cc->tct);
226 cc->tct = NULL;
227 }
228 if (NULL != cc->ah_sh)
229 {
230 GNUNET_TRANSPORT_application_suggest_cancel (cc->ah_sh);
231 cc->ah_sh = NULL;
232 }
233 }
234 }
235 /* then notify application */
236 for (cc = tth->cc_head; NULL != cc; cc = ccn)
237 {
238 ccn = cc->next;
239 if ((GNUNET_YES == cc->connected) &&
240 (NULL != cc->cb))
241 {
242 cc->cb (cc->cb_cls);
243 cc->cb = NULL; /* only notify once! */
244 }
245 }
246 return ret;
247}
248
249
250/**
251 * Offer the current HELLO of P2 to P1.
252 *
253 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequest`
254 */
255static void
256offer_hello (void *cls);
257
258
259static void
260notify_disconnect (void *cls,
261 const struct GNUNET_PeerIdentity *peer,
262 void *handler_cls)
263{
264 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
265 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
266 char *p2_s;
267 /* Find PeerContext */
268 int no = 0;
269 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2 = NULL;
270 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
271
272 p2 = find_peer_context (p->tth,
273 peer);
274 no = p->no;
275 if (NULL != p2)
276 GNUNET_asprintf (&p2_s,
277 "%u (`%s')",
278 p2->no,
279 GNUNET_i2s (&p2->id));
280 else
281 GNUNET_asprintf (&p2_s,
282 "`%s'",
283 GNUNET_i2s (peer));
284 LOG (GNUNET_ERROR_TYPE_DEBUG,
285 "Peers %s disconnected from peer %u (`%s')\n",
286 p2_s,
287 no,
288 GNUNET_i2s (&p->id));
289 GNUNET_free (p2_s);
290 /* notify about disconnect */
291 if (NULL != p->nd)
292 p->nd (p->cb_cls,
293 peer,
294 handler_cls);
295 if (NULL == p2)
296 return;
297 /* clear MQ, it is now invalid */
298 GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
299 p2,
300 &set_mq,
301 NULL);
302 /* update set connected flags for all requests */
303 GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
304 p2,
305 &clear_p1c,
306 NULL);
307 GNUNET_TRANSPORT_TESTING_find_connecting_context (p2,
308 p,
309 &clear_p2c,
310 NULL);
311 /* resume connectivity requests as necessary */
312 for (cc = tth->cc_head; NULL != cc; cc = cc->next)
313 {
314 if (GNUNET_NO == cc->connected)
315 continue;
316 if ((GNUNET_YES != cc->p1_c) ||
317 (GNUNET_YES != cc->p2_c))
318 {
319 cc->connected = GNUNET_NO;
320 /* start trying to connect */
321 if (NULL == cc->tct)
322 cc->tct = GNUNET_SCHEDULER_add_now (&offer_hello,
323 cc);
324 if (NULL == cc->ah_sh)
325 cc->ah_sh = GNUNET_TRANSPORT_application_suggest (cc->p1->ah,
326 &p2->id,
327 GNUNET_MQ_PRIO_BEST_EFFORT,
328 GNUNET_BANDWIDTH_ZERO);
329 }
330 }
331}
332
333
334static void
335retrieve_hello (void *cls);
336
337static void
338hello_iter_cb (void *cb_cls,
339 const struct GNUNET_PEERSTORE_Record *record,
340 const char *emsg)
341{
342 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cb_cls;
343 if (NULL == record)
344 {
345 p->pic = NULL;
346 if (NULL != p->start_cb)
347 p->rh_task = GNUNET_SCHEDULER_add_now (retrieve_hello, p);
348 return;
349 }
350 // Check record type et al?
351 p->hello_size = record->value_size;
352 p->hello = GNUNET_malloc (p->hello_size);
353 memcpy (p->hello, record->value, p->hello_size);
354 p->hello[p->hello_size - 1] = '\0';
355
356 GNUNET_PEERSTORE_iterate_cancel (p->pic);
357 p->pic = NULL;
358 if (NULL != p->start_cb)
359 {
360 LOG (GNUNET_ERROR_TYPE_DEBUG,
361 "Peer %u (`%s') successfully started\n",
362 p->no,
363 GNUNET_i2s (&p->id));
364 p->start_cb (p->start_cb_cls);
365 p->start_cb = NULL;
366 }
367}
368
369
370static void
371retrieve_hello (void *cls)
372{
373 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
374 p->rh_task = NULL;
375 p->pic = GNUNET_PEERSTORE_iterate (p->ph,
376 "transport",
377 &p->id,
378 GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY,
379 hello_iter_cb,
380 p);
381
382}
383
384
385struct GNUNET_TRANSPORT_TESTING_PeerContext *
386GNUNET_TRANSPORT_TESTING_start_peer (struct
387 GNUNET_TRANSPORT_TESTING_Handle *tth,
388 const char *cfgname,
389 int peer_id,
390 const struct
391 GNUNET_MQ_MessageHandler *handlers,
392 GNUNET_TRANSPORT_NotifyConnect nc,
393 GNUNET_TRANSPORT_NotifyDisconnect nd,
394 void *cb_cls,
395 GNUNET_SCHEDULER_TaskCallback start_cb,
396 void *start_cb_cls)
397{
398 char *emsg = NULL;
399 struct GNUNET_TRANSPORT_TESTING_PeerContext *p;
400 struct GNUNET_PeerIdentity dummy;
401 unsigned int i;
402
403 if (GNUNET_NO == GNUNET_DISK_file_test (cfgname))
404 {
405 LOG (GNUNET_ERROR_TYPE_ERROR,
406 "File not found: `%s'\n",
407 cfgname);
408 return NULL;
409 }
410
411 p = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_PeerContext);
412 p->tth = tth;
413 p->nc = nc;
414 p->nd = nd;
415 if (NULL != handlers)
416 {
417 for (i = 0; NULL != handlers[i].cb; i++)
418 ;
419 p->handlers = GNUNET_new_array (i + 1,
420 struct GNUNET_MQ_MessageHandler);
421 GNUNET_memcpy (p->handlers,
422 handlers,
423 i * sizeof(struct GNUNET_MQ_MessageHandler));
424 }
425 if (NULL != cb_cls)
426 p->cb_cls = cb_cls;
427 else
428 p->cb_cls = p;
429 p->start_cb = start_cb;
430 if (NULL != start_cb_cls)
431 p->start_cb_cls = start_cb_cls;
432 else
433 p->start_cb_cls = p;
434 GNUNET_CONTAINER_DLL_insert (tth->p_head,
435 tth->p_tail,
436 p);
437
438 /* Create configuration and call testing lib to modify it */
439 p->cfg = GNUNET_CONFIGURATION_create ();
440 GNUNET_assert (GNUNET_OK ==
441 GNUNET_CONFIGURATION_load (p->cfg, cfgname));
442 if (GNUNET_SYSERR ==
443 GNUNET_TESTING_configuration_create (tth->tl_system,
444 p->cfg))
445 {
446 LOG (GNUNET_ERROR_TYPE_ERROR,
447 "Testing library failed to create unique configuration based on `%s'\n",
448 cfgname);
449 GNUNET_CONFIGURATION_destroy (p->cfg);
450 GNUNET_free (p);
451 return NULL;
452 }
453
454 p->no = peer_id;
455 /* Configure peer with configuration */
456 p->peer = GNUNET_TESTING_peer_configure (tth->tl_system,
457 p->cfg,
458 p->no,
459 NULL,
460 &emsg);
461 if (NULL == p->peer)
462 {
463 LOG (GNUNET_ERROR_TYPE_ERROR,
464 "Testing library failed to create unique configuration based on `%s': `%s'\n",
465 cfgname,
466 emsg);
467 GNUNET_TRANSPORT_TESTING_stop_peer (p);
468 GNUNET_free (emsg);
469 return NULL;
470 }
471
472 if (GNUNET_OK != GNUNET_TESTING_peer_start (p->peer))
473 {
474 LOG (GNUNET_ERROR_TYPE_ERROR,
475 "Testing library failed to create unique configuration based on `%s'\n",
476 cfgname);
477 GNUNET_TRANSPORT_TESTING_stop_peer (p);
478 return NULL;
479 }
480
481 memset (&dummy,
482 '\0',
483 sizeof(dummy));
484 GNUNET_TESTING_peer_get_identity (p->peer,
485 &p->id);
486 if (0 == memcmp (&dummy,
487 &p->id,
488 sizeof(struct GNUNET_PeerIdentity)))
489 {
490 LOG (GNUNET_ERROR_TYPE_ERROR,
491 "Testing library failed to obtain peer identity for peer %u\n",
492 p->no);
493 GNUNET_TRANSPORT_TESTING_stop_peer (p);
494 return NULL;
495 }
496 LOG (GNUNET_ERROR_TYPE_DEBUG,
497 "Peer %u configured with identity `%s'\n",
498 p->no,
499 GNUNET_i2s_full (&p->id));
500 p->th = GNUNET_TRANSPORT_core_connect (p->cfg,
501 NULL,
502 handlers,
503 p,
504 &notify_connect,
505 &notify_disconnect);
506 if (NULL == p->th)
507 {
508 LOG (GNUNET_ERROR_TYPE_ERROR,
509 "Failed to connect to transport service for peer `%s': `%s'\n",
510 cfgname,
511 emsg);
512 GNUNET_TRANSPORT_TESTING_stop_peer (p);
513 GNUNET_free (emsg);
514 return NULL;
515 }
516 p->ah = GNUNET_TRANSPORT_application_init (p->cfg);
517 if (NULL == p->ah)
518 {
519 LOG (GNUNET_ERROR_TYPE_ERROR,
520 "Failed to connect to TNG service for peer `%s': `%s'\n",
521 cfgname,
522 emsg);
523 GNUNET_TRANSPORT_TESTING_stop_peer (p);
524 GNUNET_free (emsg);
525 return NULL;
526 }
527 p->ph = GNUNET_PEERSTORE_connect (p->cfg);
528 // FIXME Error handling
529 p->rh_task = GNUNET_SCHEDULER_add_now (retrieve_hello, p);
530
531 return p;
532}
533
534
535int
536GNUNET_TRANSPORT_TESTING_restart_peer (struct
537 GNUNET_TRANSPORT_TESTING_PeerContext *p,
538 GNUNET_SCHEDULER_TaskCallback restart_cb,
539 void *restart_cb_cls)
540{
541 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
542 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
543
544 /* shutdown */
545 LOG (GNUNET_ERROR_TYPE_DEBUG,
546 "Stopping peer %u (`%s')\n",
547 p->no,
548 GNUNET_i2s (&p->id));
549 if (NULL != p->pic)
550 {
551 GNUNET_PEERSTORE_iterate_cancel (p->pic);
552 p->pic = NULL;
553 }
554 if (NULL != p->th)
555 {
556 GNUNET_TRANSPORT_core_disconnect (p->th);
557 p->th = NULL;
558 }
559 for (cc = p->tth->cc_head; NULL != cc; cc = ccn)
560 {
561 ccn = cc->next;
562 if ((cc->p1 == p) ||
563 (cc->p2 == p))
564 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
565 }
566 if (NULL != p->ah)
567 {
568 GNUNET_TRANSPORT_application_done (p->ah);
569 p->ah = NULL;
570 }
571 if (GNUNET_SYSERR ==
572 GNUNET_TESTING_peer_stop (p->peer))
573 {
574 LOG (GNUNET_ERROR_TYPE_ERROR,
575 "Failed to stop peer %u (`%s')\n",
576 p->no,
577 GNUNET_i2s (&p->id));
578 return GNUNET_SYSERR;
579 }
580
581 sleep (5); // YUCK!
582
583 LOG (GNUNET_ERROR_TYPE_DEBUG,
584 "Restarting peer %u (`%s')\n",
585 p->no,
586 GNUNET_i2s (&p->id));
587 /* restart */
588 if (GNUNET_SYSERR == GNUNET_TESTING_peer_start (p->peer))
589 {
590 LOG (GNUNET_ERROR_TYPE_ERROR,
591 "Failed to restart peer %u (`%s')\n",
592 p->no,
593 GNUNET_i2s (&p->id));
594 return GNUNET_SYSERR;
595 }
596
597 GNUNET_assert (NULL == p->start_cb);
598 p->start_cb = restart_cb;
599 p->start_cb_cls = restart_cb_cls;
600
601 p->th = GNUNET_TRANSPORT_core_connect (p->cfg,
602 NULL,
603 p->handlers,
604 p,
605 &notify_connect,
606 &notify_disconnect);
607 GNUNET_assert (NULL != p->th);
608 p->ah = GNUNET_TRANSPORT_application_init (p->cfg);
609 p->pic = GNUNET_PEERSTORE_iterate (p->ph,
610 "transport",
611 &p->id,
612 GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY,
613 hello_iter_cb,
614 p);
615 GNUNET_assert (NULL != p->pic);
616 return GNUNET_OK;
617}
618
619
620/**
621 * Shutdown the given peer
622 *
623 * @param p the peer
624 */
625void
626GNUNET_TRANSPORT_TESTING_stop_peer (struct
627 GNUNET_TRANSPORT_TESTING_PeerContext *p)
628{
629 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
630 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
631 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
632 /* shutdown */
633 LOG (GNUNET_ERROR_TYPE_DEBUG,
634 "Stopping peer %u (`%s')\n",
635 p->no,
636 GNUNET_i2s (&p->id));
637
638 for (cc = tth->cc_head; NULL != cc; cc = ccn)
639 {
640 ccn = cc->next;
641 if ((cc->p1 == p) ||
642 (cc->p2 == p))
643 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
644 }
645 if (NULL != p->pic)
646 {
647 GNUNET_PEERSTORE_iterate_cancel (p->pic);
648 p->pic = NULL;
649 }
650 if (NULL != p->th)
651 {
652 GNUNET_TRANSPORT_core_disconnect (p->th);
653 p->th = NULL;
654 }
655 if (NULL != p->ah)
656 {
657 GNUNET_TRANSPORT_application_done (p->ah);
658 p->ah = NULL;
659 }
660 if (NULL != p->ph)
661 {
662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
663 "Disconnecting from PEERSTORE service\n");
664 GNUNET_PEERSTORE_disconnect (p->ph, GNUNET_NO);
665 p->ph = NULL;
666 }
667
668 if (NULL != p->peer)
669 {
670 if (GNUNET_OK !=
671 GNUNET_TESTING_peer_stop (p->peer))
672 {
673 LOG (GNUNET_ERROR_TYPE_DEBUG,
674 "Testing lib failed to stop peer %u (`%s')\n",
675 p->no,
676 GNUNET_i2s (&p->id));
677 }
678 GNUNET_TESTING_peer_destroy (p->peer);
679 p->peer = NULL;
680 }
681 if (NULL != p->hello)
682 {
683 GNUNET_free (p->hello);
684 p->hello = NULL;
685 }
686 if (NULL != p->cfg)
687 {
688 GNUNET_CONFIGURATION_destroy (p->cfg);
689 p->cfg = NULL;
690 }
691 if (NULL != p->handlers)
692 {
693 GNUNET_free (p->handlers);
694 p->handlers = NULL;
695 }
696 GNUNET_CONTAINER_DLL_remove (tth->p_head,
697 tth->p_tail,
698 p);
699 LOG (GNUNET_ERROR_TYPE_DEBUG,
700 "Peer %u (`%s') stopped\n",
701 p->no,
702 GNUNET_i2s (&p->id));
703 if (NULL != p->rh_task)
704 GNUNET_SCHEDULER_cancel (p->rh_task);
705 p->rh_task = NULL;
706 GNUNET_free (p);
707}
708
709
710/**
711 * Function called after the HELLO was passed to the
712 * transport service.
713 * FIXME maybe schedule the application_validate somehow
714 */
715/*
716 static void
717 hello_offered (void *cls)
718 {
719 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = cls;
720
721 cc->oh = NULL;
722 cc->tct = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
723 &offer_hello,
724 cc);
725 }*/
726
727
728static void
729offer_hello (void *cls)
730{
731 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = cls;
732 struct GNUNET_TRANSPORT_TESTING_PeerContext *p1 = cc->p1;
733 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2 = cc->p2;
734 struct GNUNET_TIME_Absolute t;
735 enum GNUNET_NetworkType nt = 0;
736 char *addr;
737
738 cc->tct = NULL;
739 {
740 char *p2_s = GNUNET_strdup (GNUNET_i2s (&p2->id));
741
742 LOG (GNUNET_ERROR_TYPE_DEBUG,
743 "Asking peer %u (`%s') to connect peer %u (`%s'), providing HELLO with %s\n",
744 p1->no,
745 GNUNET_i2s (&p1->id),
746 p2->no,
747 p2_s,
748 p2->hello);
749 GNUNET_free (p2_s);
750 }
751
752 addr = GNUNET_HELLO_extract_address (p2->hello,
753 p2->hello_size,
754 &p2->id,
755 &nt,
756 &t);
757 GNUNET_assert (NULL != addr);
758 GNUNET_assert (NULL != p1->hello);
759 GNUNET_TRANSPORT_application_validate (p1->ah,
760 &p2->id,
761 nt,
762 addr);
763 GNUNET_free (addr);
764}
765
766
767/**
768 * Initiate a connection from p1 to p2 by offering p1 p2's HELLO message
769 *
770 * Remarks: start_peer's notify_connect callback can be called before.
771 *
772 * @param tth transport testing handle
773 * @param p1 peer 1
774 * @param p2 peer 2
775 * @param cb the callback to call when both peers notified that they are connected
776 * @param cls callback cls
777 * @return a connect request handle
778 */
779struct GNUNET_TRANSPORT_TESTING_ConnectRequest *
780GNUNET_TRANSPORT_TESTING_connect_peers (struct
781 GNUNET_TRANSPORT_TESTING_PeerContext *p1,
782 struct
783 GNUNET_TRANSPORT_TESTING_PeerContext *p2,
784 GNUNET_SCHEDULER_TaskCallback cb,
785 void *cls)
786{
787 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p1->tth;
788 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
789 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
790
791 ccn = NULL;
792 for (cc = tth->cc_head; NULL != cc; cc = cc->next)
793 {
794 if ((cc->p1 == p1) &&
795 (cc->p2 == p2))
796 {
797 ccn = cc;
798 break;
799 }
800 }
801
802 cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest);
803 cc->p1 = p1;
804 cc->p2 = p2;
805 cc->cb = cb;
806 if (NULL != cls)
807 cc->cb_cls = cls;
808 else
809 cc->cb_cls = cc;
810 if (NULL != ccn)
811 {
812 cc->p1_c = ccn->p1_c;
813 cc->p2_c = ccn->p2_c;
814 cc->connected = ccn->connected;
815 }
816 GNUNET_CONTAINER_DLL_insert (tth->cc_head,
817 tth->cc_tail,
818 cc);
819 cc->tct = GNUNET_SCHEDULER_add_now (&offer_hello,
820 cc);
821 cc->ah_sh = GNUNET_TRANSPORT_application_suggest (cc->p1->ah,
822 &p2->id,
823 GNUNET_MQ_PRIO_BEST_EFFORT,
824 GNUNET_BANDWIDTH_ZERO);
825 LOG (GNUNET_ERROR_TYPE_DEBUG,
826 "New connect request %p\n",
827 cc);
828 return cc;
829}
830
831
832void
833GNUNET_TRANSPORT_TESTING_connect_peers_cancel (struct
834 GNUNET_TRANSPORT_TESTING_ConnectRequest
835 *cc)
836{
837 struct GNUNET_TRANSPORT_TESTING_Handle *tth = cc->p1->tth;
838
839 LOG (GNUNET_ERROR_TYPE_DEBUG,
840 "Canceling connect request!\n");
841 if (NULL != cc->tct)
842 {
843 GNUNET_SCHEDULER_cancel (cc->tct);
844 cc->tct = NULL;
845 }
846 if (NULL != cc->ah_sh)
847 {
848 GNUNET_TRANSPORT_application_suggest_cancel (cc->ah_sh);
849 cc->ah_sh = NULL;
850 }
851 GNUNET_CONTAINER_DLL_remove (tth->cc_head,
852 tth->cc_tail,
853 cc);
854 GNUNET_free (cc);
855}
856
857
858/**
859 * Clean up the transport testing
860 *
861 * @param tth transport testing handle
862 */
863void
864GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_Handle *tth)
865{
866 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
867 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ct;
868 struct GNUNET_TRANSPORT_TESTING_PeerContext *p;
869 struct GNUNET_TRANSPORT_TESTING_PeerContext *t;
870
871 if (NULL == tth)
872 return;
873 cc = tth->cc_head;
874 while (NULL != cc)
875 {
876 ct = cc->next;
877 LOG (GNUNET_ERROR_TYPE_ERROR,
878 "Developer forgot to cancel connect request!\n");
879 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
880 cc = ct;
881 }
882 p = tth->p_head;
883 while (NULL != p)
884 {
885 t = p->next;
886 LOG (GNUNET_ERROR_TYPE_ERROR,
887 "Developer forgot to stop peer!\n");
888 GNUNET_TRANSPORT_TESTING_stop_peer (p);
889 p = t;
890 }
891 GNUNET_TESTING_system_destroy (tth->tl_system,
892 GNUNET_YES);
893
894 GNUNET_free (tth);
895}
896
897
898/**
899 * Initialize the transport testing
900 *
901 * @return transport testing handle
902 */
903struct GNUNET_TRANSPORT_TESTING_Handle *
904GNUNET_TRANSPORT_TESTING_init ()
905{
906 struct GNUNET_TRANSPORT_TESTING_Handle *tth;
907
908 tth = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_Handle);
909 tth->tl_system = GNUNET_TESTING_system_create ("transport-testing",
910 NULL,
911 NULL,
912 NULL);
913 if (NULL == tth->tl_system)
914 {
915 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
916 "Failed to initialize testing library!\n");
917 GNUNET_free (tth);
918 return NULL;
919 }
920 return tth;
921}
922
923
924/* end of transport-testing.c */
diff --git a/src/transport/transport-testing2.h b/src/transport/transport-testing2.h
deleted file mode 100644
index 8f1071e8f..000000000
--- a/src/transport/transport-testing2.h
+++ /dev/null
@@ -1,941 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2006, 2009, 2015, 2016 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 transport-testing.h
23 * @brief testing lib for transport service
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#ifndef TRANSPORT_TESTING_H
28#define TRANSPORT_TESTING_H
29#include "platform.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_hello_lib.h"
32#include "gnunet_peerstore_service.h"
33#include "gnunet_transport_core_service.h"
34#include "gnunet_transport_application_service.h"
35#include "gnunet_testing_lib.h"
36
37
38/* ************* Basic functions for starting/stopping/connecting *********** */
39
40/**
41 * Context for a single peer
42 */
43struct GNUNET_TRANSPORT_TESTING_PeerContext;
44
45/**
46 * Definition for a transport testing handle
47 */
48struct GNUNET_TRANSPORT_TESTING_Handle;
49
50
51/**
52 * Context for a single peer
53 */
54struct GNUNET_TRANSPORT_TESTING_PeerContext
55{
56 /**
57 * Next element in the DLL
58 */
59 struct GNUNET_TRANSPORT_TESTING_PeerContext *next;
60
61 /**
62 * Previous element in the DLL
63 */
64 struct GNUNET_TRANSPORT_TESTING_PeerContext *prev;
65
66 /**
67 * Transport testing handle this peer belongs to
68 */
69 struct GNUNET_TRANSPORT_TESTING_Handle *tth;
70
71 /**
72 * Application handle
73 */
74 struct GNUNET_TRANSPORT_ApplicationHandle *ah;
75
76 /**
77 * Peer's configuration
78 */
79 struct GNUNET_CONFIGURATION_Handle *cfg;
80
81 /**
82 * Peer's transport service handle
83 */
84 struct GNUNET_TRANSPORT_CoreHandle *th;
85
86 /**
87 * Peer's PEERSTORE Handle
88 */
89 struct GNUNET_PEERSTORE_Handle *ph;
90
91 /**
92 * Peer's transport get hello handle to retrieve peer's HELLO message
93 */
94 struct GNUNET_PEERSTORE_IterateContext *pic;
95
96 /**
97 * Hello
98 */
99 char *hello;
100
101 /**
102 * Hello size
103 */
104 size_t hello_size;
105
106 /**
107 * Peer's testing handle
108 */
109 struct GNUNET_TESTING_Peer *peer;
110
111 /**
112 * Peer identity
113 */
114 struct GNUNET_PeerIdentity id;
115
116 /**
117 * Handle for the peer's ARM process
118 */
119 struct GNUNET_OS_Process *arm_proc;
120
121 /**
122 * Receive callback
123 */
124 struct GNUNET_MQ_MessageHandler *handlers;
125
126 /**
127 * Notify connect callback
128 */
129 GNUNET_TRANSPORT_NotifyConnect nc;
130
131 /**
132 * Notify disconnect callback
133 */
134 GNUNET_TRANSPORT_NotifyDisconnect nd;
135
136 /**
137 * Startup completed callback
138 */
139 GNUNET_SCHEDULER_TaskCallback start_cb;
140
141 /**
142 * Hello get task
143 */
144 struct GNUNET_SCHEDULER_Task *rh_task;
145
146 /**
147 * Closure for the @a nc and @a nd callbacks
148 */
149 void *cb_cls;
150
151 /**
152 * Closure for @e start_cb.
153 */
154 void *start_cb_cls;
155
156 /**
157 * An unique number to identify the peer
158 */
159 unsigned int no;
160};
161
162
163/**
164 * Handle for a request to connect two peers.
165 */
166struct GNUNET_TRANSPORT_TESTING_ConnectRequest
167{
168 /**
169 * Kept in a DLL.
170 */
171 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *next;
172
173 /**
174 * Kept in a DLL.
175 */
176 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *prev;
177
178 /**
179 * Peer we want to connect.
180 */
181 struct GNUNET_TRANSPORT_TESTING_PeerContext *p1;
182
183 /**
184 * Peer we want to connect.
185 */
186 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2;
187
188 /**
189 * Task by which we accomplish the connection.
190 */
191 struct GNUNET_SCHEDULER_Task *tct;
192
193 /**
194 * Handle by which we ask TNG to facilitate the connection.
195 */
196 struct GNUNET_TRANSPORT_ApplicationSuggestHandle *ah_sh;
197
198 /**
199 * Function to call upon completion.
200 */
201 GNUNET_SCHEDULER_TaskCallback cb;
202
203 /**
204 * Closure for @e cb.
205 */
206 void *cb_cls;
207
208 /**
209 * Message queue for sending from @a p1 to @a p2.
210 */
211 struct GNUNET_MQ_Handle *mq;
212
213 /**
214 * Set if peer1 says the connection is up to peer2.
215 */
216 int p1_c;
217
218 /**
219 * Set if peer2 says the connection is up to peer1.
220 */
221 int p2_c;
222
223 /**
224 * #GNUNET_YES if both @e p1_c and @e p2_c are #GNUNET_YES.
225 */
226 int connected;
227};
228
229
230/**
231 * Handle for a test run.
232 */
233struct GNUNET_TRANSPORT_TESTING_Handle
234{
235 /**
236 * Testing library system handle
237 */
238 struct GNUNET_TESTING_System *tl_system;
239
240 /**
241 * head DLL of connect contexts
242 */
243 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc_head;
244
245 /**
246 * head DLL of connect contexts
247 */
248 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc_tail;
249
250 /**
251 * head DLL of peers
252 */
253 struct GNUNET_TRANSPORT_TESTING_PeerContext *p_head;
254
255 /**
256 * tail DLL of peers
257 */
258 struct GNUNET_TRANSPORT_TESTING_PeerContext *p_tail;
259};
260
261
262/**
263 * Initialize the transport testing
264 *
265 * @return transport testing handle
266 */
267struct GNUNET_TRANSPORT_TESTING_Handle *
268GNUNET_TRANSPORT_TESTING_init (void);
269
270
271/**
272 * Clean up the transport testing
273 *
274 * @param tth transport testing handle
275 */
276void
277GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_Handle *tth);
278
279
280/**
281 * Start a peer with the given configuration
282 *
283 * @param tth the testing handle
284 * @param cfgname configuration file
285 * @param peer_id an identification number for the peer
286 * @param handlers functions for receiving messages
287 * @param nc connect callback
288 * @param nd disconnect callback
289 * @param cb_cls closure for @a nc and @a nd callback
290 * @param start_cb start callback
291 * @param start_cb_cls closure for @a start_cb
292 * @return the peer context
293 */
294struct GNUNET_TRANSPORT_TESTING_PeerContext *
295GNUNET_TRANSPORT_TESTING_start_peer (
296 struct GNUNET_TRANSPORT_TESTING_Handle *tth,
297 const char *cfgname,
298 int peer_id,
299 const struct GNUNET_MQ_MessageHandler *handlers,
300 GNUNET_TRANSPORT_NotifyConnect nc,
301 GNUNET_TRANSPORT_NotifyDisconnect nd,
302 void *cb_cls,
303 GNUNET_SCHEDULER_TaskCallback start_cb,
304 void *start_cb_cls);
305
306
307/**
308 * Shutdown the given peer
309 *
310 * @param p the peer
311 */
312void
313GNUNET_TRANSPORT_TESTING_stop_peer (
314 struct GNUNET_TRANSPORT_TESTING_PeerContext *pc);
315
316
317/**
318 * Stops and restarts the given peer, sleeping (!) for 5s in between.
319 *
320 * @param p the peer
321 * @param restart_cb restart callback
322 * @param restart_cb_cls callback closure
323 * @return #GNUNET_OK in success otherwise #GNUNET_SYSERR
324 */
325int
326GNUNET_TRANSPORT_TESTING_restart_peer (
327 struct GNUNET_TRANSPORT_TESTING_PeerContext *p,
328 GNUNET_SCHEDULER_TaskCallback restart_cb,
329 void *restart_cb_cls);
330
331
332/**
333 * Connect the given peers and call the callback when both peers
334 * report the inbound connection. Remarks: start_peer's notify_connect
335 * callback can be called before.
336 *
337 * @param p1 peer 1
338 * @param p2 peer 2
339 * @param cb the callback to call when both peers notified that they are
340 * connected
341 * @param cls callback cls
342 * @return a connect request handle
343 */
344struct GNUNET_TRANSPORT_TESTING_ConnectRequest *
345GNUNET_TRANSPORT_TESTING_connect_peers (
346 struct GNUNET_TRANSPORT_TESTING_PeerContext *p1,
347 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2,
348 GNUNET_SCHEDULER_TaskCallback cb,
349 void *cls);
350
351
352/**
353 * Cancel the request to connect two peers. You MUST cancel the
354 * request if you stop the peers before the peers connected
355 * successfully.
356 *
357 * @param cc a connect request handle
358 */
359void
360GNUNET_TRANSPORT_TESTING_connect_peers_cancel (
361 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc);
362
363
364/**
365 * Function called on matching connect requests.
366 *
367 * @param cls closure
368 * @param cc request matching the query
369 */
370typedef void (*GNUNET_TRANSPORT_TESTING_ConnectContextCallback) (
371 void *cls,
372 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc);
373
374
375/**
376 * Find any connecting context matching the given pair of peers.
377 *
378 * @param p1 first peer
379 * @param p2 second peer
380 * @param cb function to call
381 * @param cb_cls closure for @a cb
382 */
383void
384GNUNET_TRANSPORT_TESTING_find_connecting_context (
385 struct GNUNET_TRANSPORT_TESTING_PeerContext *p1,
386 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2,
387 GNUNET_TRANSPORT_TESTING_ConnectContextCallback cb,
388 void *cb_cls);
389
390
391/* ********************** high-level process functions *************** */
392
393
394/**
395 * Function called once the peers have been launched and
396 * connected by #GNUNET_TRANSPORT_TESTING_connect_check().
397 *
398 * @param cls closure
399 * @param num_peers size of the @a p array
400 * @param p the peers that were launched
401 */
402typedef void (*GNUNET_TRANSPORT_TESTING_ConnectContinuation) (
403 void *cls,
404 unsigned int num_peers,
405 struct GNUNET_TRANSPORT_TESTING_PeerContext *p[]);
406
407
408/**
409 * Internal data structure.
410 */
411struct GNUNET_TRANSPORT_TESTING_ConnectRequestList;
412
413/**
414 * Internal data structure.
415 */
416struct GNUNET_TRANSPORT_TESTING_InternalPeerContext;
417
418
419GNUNET_NETWORK_STRUCT_BEGIN
420struct GNUNET_TRANSPORT_TESTING_TestMessage
421{
422 /**
423 * Type is (usually) #GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE.
424 */
425 struct GNUNET_MessageHeader header;
426
427 /**
428 * Monotonically increasing counter throughout the test.
429 */
430 uint32_t num GNUNET_PACKED;
431};
432
433struct GNUNET_TRANSPORT_TESTING_PerformanceTestMessage
434{
435 /**
436 * Type is (usually) #GNUNET_TRANSPORT_TESTING_SIMPLE_PERFORMANCE_MTYPE.
437 */
438 struct GNUNET_MessageHeader header;
439
440 /**
441 * Time this message was send via transport api.
442 */
443 struct GNUNET_TIME_AbsoluteNBO time_send;
444
445 /**
446 * Monotonically increasing counter throughout the test.
447 */
448 uint32_t num GNUNET_PACKED;
449};
450
451GNUNET_NETWORK_STRUCT_END
452
453
454/**
455 * Function called by the transport for each received message.
456 *
457 * @param cls closure
458 * @param receiver receiver of the message
459 * @param sender sender of the message
460 * @param message the message
461 */
462typedef void (*GNUNET_TRANSPORT_TESTING_ReceiveCallback) (
463 void *cls,
464 struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
465 const struct GNUNET_PeerIdentity *sender,
466 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message);
467
468
469/**
470 * Function called to notify transport users that another
471 * peer connected to us.
472 *
473 * @param cls closure
474 * @param me peer experiencing the event
475 * @param other peer that connected to @a me
476 */
477typedef void (*GNUNET_TRANSPORT_TESTING_NotifyConnect) (
478 void *cls,
479 struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
480 const struct GNUNET_PeerIdentity *other);
481
482
483/**
484 * Function called to notify transport users that another
485 * peer disconnected from us.
486 *
487 * @param cls closure
488 * @param me peer experiencing the event
489 * @param other peer that disconnected from @a me
490 */
491typedef void (*GNUNET_TRANSPORT_TESTING_NotifyDisconnect) (
492 void *cls,
493 struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
494 const struct GNUNET_PeerIdentity *other);
495
496
497/**
498 * Closure that must be passed to
499 * #GNUNET_TRANSPORT_TESTING_connect_check.
500 */
501struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext
502{
503 /**
504 * How should we continue after the connect?
505 */
506 GNUNET_SCHEDULER_TaskCallback connect_continuation;
507
508 /**
509 * Closure for @e connect_continuation.
510 */
511 void *connect_continuation_cls;
512
513 /**
514 * Which configuration file should we pass to the
515 * #GNUNET_PROGRAM_run() of the testcase?
516 */
517 const char *config_file;
518
519 /**
520 * Receiver argument to give for peers we start.
521 */
522 GNUNET_TRANSPORT_TESTING_ReceiveCallback rec;
523
524 /**
525 * Notify connect argument to give for peers we start.
526 */
527 GNUNET_TRANSPORT_TESTING_NotifyConnect nc;
528
529 /**
530 * Notify disconnect argument to give for peers we start.
531 */
532 GNUNET_TRANSPORT_TESTING_NotifyDisconnect nd;
533
534 /**
535 * Closure for @e rec, @e nc and @e nd.
536 */
537 void *cls;
538
539 /**
540 * Custom task to run on shutdown.
541 */
542 GNUNET_SCHEDULER_TaskCallback shutdown_task;
543
544 /**
545 * Closure for @e shutdown_task.
546 */
547 void *shutdown_task_cls;
548
549 /**
550 * Custom task to run after peers were started but before we try to
551 * connect them. If this function is set, we wait ONE second after
552 * running this function until we continue with connecting the
553 * peers.
554 */
555 GNUNET_SCHEDULER_TaskCallback pre_connect_task;
556
557 /**
558 * Closure for @e shutdown_task.
559 */
560 void *pre_connect_task_cls;
561
562 /**
563 * When should the testcase time out?
564 */
565 struct GNUNET_TIME_Relative timeout;
566
567 /**
568 * Should we try to create connections in both directions?
569 */
570 int bi_directional;
571
572 /* ******* fields set by #GNUNET_TRANSPORT_TESTING_connect_check **** */
573
574 /**
575 * Number of peers involved in the test.
576 */
577 unsigned int num_peers;
578
579 /**
580 * Configuration files we have, array with @e num_peers entries.
581 */
582 char **cfg_files;
583
584 /**
585 * Array with @e num_peers entries.
586 */
587 struct GNUNET_TRANSPORT_TESTING_PeerContext **p;
588
589 /**
590 * Name of the plugin.
591 */
592 const char *test_plugin;
593
594 /**
595 * Name of the testcase.
596 */
597 const char *test_name;
598
599 /**
600 * Configuration object for the testcase.
601 */
602 const struct GNUNET_CONFIGURATION_Handle *cfg;
603
604 /**
605 * Main testing handle.
606 */
607 struct GNUNET_TRANSPORT_TESTING_Handle *tth;
608
609 /**
610 * Result from the main function, set to #GNUNET_OK on success.
611 * Clients should set to #GNUNET_SYSERR to indicate test failure.
612 */
613 int global_ret;
614
615 /**
616 * Generator for the `num` field in test messages. Incremented each
617 * time #GNUNET_TRANSPORT_TESTING_simple_send or
618 * #GNUNET_TRANSPORT_TESTING_large_send are used to transmit a
619 * message.
620 */
621 uint32_t send_num_gen;
622
623 /* ******* internal state, clients should not mess with this **** */
624
625 /**
626 * Task run on timeout.
627 */
628 struct GNUNET_SCHEDULER_Task *timeout_task;
629
630 /**
631 * Task run to connect peers.
632 */
633 struct GNUNET_SCHEDULER_Task *connect_task;
634
635 /**
636 * Number of peers that have been started.
637 */
638 unsigned int started;
639
640 /**
641 * DLL of active connect requests.
642 */
643 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl_head;
644
645 /**
646 * DLL of active connect requests.
647 */
648 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl_tail;
649
650 /**
651 * Array with @e num_peers entries.
652 */
653 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ip;
654};
655
656
657/**
658 * Find peer by peer ID.
659 *
660 * @param ccc context to search
661 * @param peer peer to look for
662 * @return NULL if @a peer was not found
663 */
664struct GNUNET_TRANSPORT_TESTING_PeerContext *
665GNUNET_TRANSPORT_TESTING_find_peer (
666 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc,
667 const struct GNUNET_PeerIdentity *peer);
668
669
670/**
671 * Common implementation of the #GNUNET_TRANSPORT_TESTING_CheckCallback.
672 * Starts and connects the two peers, then invokes the
673 * `connect_continuation` from @a cls. Sets up a timeout to
674 * abort the test, and a shutdown handler to clean up properly
675 * on exit.
676 *
677 * @param cls closure of type `struct
678 * GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
679 * @param tth_ initialized testing handle
680 * @param test_plugin_ name of the plugin
681 * @param test_name_ name of the test
682 * @param num_peers number of entries in the @a cfg_file array
683 * @param cfg_files array of names of configuration files for the peers
684 * @return #GNUNET_SYSERR on error
685 */
686int
687GNUNET_TRANSPORT_TESTING_connect_check (
688 void *cls,
689 struct GNUNET_TRANSPORT_TESTING_Handle *tth_,
690 const char *test_plugin_,
691 const char *test_name_,
692 unsigned int num_peers,
693 char *cfg_files[]);
694
695
696/**
697 * Main function of a testcase. Called with the initial setup data
698 * for the test as derived from the source name and the binary name.
699 *
700 * @param cls closure
701 * @param tth_ initialized testing handle
702 * @param test_plugin_ name of the plugin
703 * @param test_name_ name of the test
704 * @param num_peers number of entries in the @a cfg_file array
705 * @param cfg_files array of names of configuration files for the peers
706 * @return #GNUNET_SYSERR on error
707 */
708typedef int (*GNUNET_TRANSPORT_TESTING_CheckCallback) (
709 void *cls,
710 struct GNUNET_TRANSPORT_TESTING_Handle *tth_,
711 const char *test_plugin_,
712 const char *test_name_,
713 unsigned int num_peers,
714 char *cfg_files[]);
715
716
717/**
718 * Setup testcase. Calls @a check with the data the test needs.
719 *
720 * @param argv0 binary name (argv[0])
721 * @param filename source file name (__FILE__)
722 * @param num_peers number of peers to start
723 * @param check main function to run
724 * @param check_cls closure for @a check
725 * @return #GNUNET_OK on success
726 */
727int
728GNUNET_TRANSPORT_TESTING_main_ (const char *argv0,
729 const char *filename,
730 unsigned int num_peers,
731 GNUNET_TRANSPORT_TESTING_CheckCallback check,
732 void *check_cls);
733
734
735/**
736 * Setup testcase. Calls @a check with the data the test needs.
737 *
738 * @param num_peers number of peers to start
739 * @param check main function to run
740 * @param check_cls closure for @a check
741 * @return #GNUNET_OK on success
742 */
743#define GNUNET_TRANSPORT_TESTING_main(num_peers, check, check_cls) \
744 GNUNET_TRANSPORT_TESTING_main_ (argv[0], \
745 __FILE__, \
746 num_peers, \
747 check, \
748 check_cls)
749
750/* ***************** Convenience functions for sending ********* */
751
752/**
753 * Send a test message of type @a mtype and size @a msize from
754 * peer @a sender to peer @a receiver. The peers should be
755 * connected when this function is called.
756 *
757 * @param sender the sending peer
758 * @param receiver the receiving peer
759 * @param mtype message type to use
760 * @param msize size of the message, at least `sizeof (struct
761 * GNUNET_TRANSPORT_TESTING_TestMessage)`
762 * @param num unique message number
763 * @param cont continuation to call after transmission
764 * @param cont_cls closure for @a cont
765 * @return #GNUNET_OK if message was queued,
766 * #GNUNET_NO if peers are not connected
767 * #GNUNET_SYSERR if @a msize is illegal
768 */
769int
770GNUNET_TRANSPORT_TESTING_send (
771 struct GNUNET_TRANSPORT_TESTING_PeerContext *sender,
772 struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
773 uint16_t mtype,
774 uint16_t msize,
775 uint32_t num,
776 GNUNET_SCHEDULER_TaskCallback cont,
777 void *cont_cls);
778
779
780/**
781 * Message type used by #GNUNET_TRANSPORT_TESTING_simple_send().
782 */
783#define GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE 12345
784
785/**
786 * Alternative message type for tests.
787 */
788#define GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE2 12346
789
790/**
791 * Message type used by #().
792 */
793#define GNUNET_TRANSPORT_TESTING_SIMPLE_PERFORMANCE_MTYPE 12347
794
795/**
796 * Type of the closure argument to pass to
797 * #GNUNET_TRANSPORT_TESTING_simple_send() and
798 * #GNUNET_TRANSPORT_TESTING_large_send().
799 */
800struct GNUNET_TRANSPORT_TESTING_SendClosure
801{
802 /**
803 * Context for the transmission.
804 */
805 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
806
807 /**
808 * Function that returns the desired message size. Overrides
809 * the message size, can be NULL in which case the message
810 * size is the default.
811 */
812 size_t (*get_size_cb) (unsigned int n);
813
814 /**
815 * Number of messages to be transmitted in a loop.
816 * Use zero for "forever" (until external shutdown).
817 */
818 unsigned int num_messages;
819
820 /**
821 * Function to call after all transmissions, can be NULL.
822 */
823 GNUNET_SCHEDULER_TaskCallback cont;
824
825 /**
826 * Closure for @e cont.
827 */
828 void *cont_cls;
829};
830
831
832/**
833 * Task that sends a minimalistic test message from the
834 * first peer to the second peer.
835 *
836 * @param cls the `struct GNUNET_TRANSPORT_TESTING_SendClosure`
837 * which should contain at least two peers, the first two
838 * of which should be currently connected
839 */
840void
841GNUNET_TRANSPORT_TESTING_simple_send (void *cls);
842
843/**
844 * Size of a message sent with
845 * #GNUNET_TRANSPORT_TESTING_large_send(). Big enough
846 * to usually force defragmentation.
847 */
848#define GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE 2600
849
850/**
851 * Task that sends a large test message from the
852 * first peer to the second peer.
853 *
854 * @param cls the `struct GNUNET_TRANSPORT_TESTING_SendClosure`
855 * which should contain at least two peers, the first two
856 * of which should be currently connected
857 */
858void
859GNUNET_TRANSPORT_TESTING_large_send (void *cls);
860
861
862/* ********************** log-only convenience functions ************* */
863
864
865/**
866 * Log a connect event.
867 *
868 * @param cls NULL
869 * @param me peer that had the event
870 * @param other peer that connected.
871 */
872void
873GNUNET_TRANSPORT_TESTING_log_connect (
874 void *cls,
875 struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
876 const struct GNUNET_PeerIdentity *other);
877
878
879/**
880 * Log a disconnect event.
881 *
882 * @param cls NULL
883 * @param me peer that had the event
884 * @param other peer that disconnected.
885 */
886void
887GNUNET_TRANSPORT_TESTING_log_disconnect (
888 void *cls,
889 struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
890 const struct GNUNET_PeerIdentity *other);
891
892
893/* ********************** low-level filename functions *************** */
894
895
896/**
897 * Extracts the test filename from an absolute file name and removes
898 * the extension.
899 *
900 * @param file absolute file name
901 * @return resulting test name
902 */
903char *
904GNUNET_TRANSPORT_TESTING_get_test_name (const char *file);
905
906
907/**
908 * This function takes the filename (e.g. argv[0), removes a "lt-"-prefix and
909 * if existing ".exe"-prefix and adds the peer-number
910 *
911 * @param file filename of the test, e.g. argv[0]
912 * @param count peer number
913 * @return configuration name to use
914 */
915char *
916GNUNET_TRANSPORT_TESTING_get_config_name (const char *file, int count);
917
918
919/**
920 * Extracts the plugin anme from an absolute file name and the test name
921 * @param file absolute file name
922 * @param test test name
923 * @return the plugin name
924 */
925char *
926GNUNET_TRANSPORT_TESTING_get_test_plugin_name (const char *executable,
927 const char *testname);
928
929
930/**
931 * Extracts the filename from an absolute file name and removes the
932 * extension
933 *
934 * @param file absolute file name
935 * @return the source name
936 */
937char *
938GNUNET_TRANSPORT_TESTING_get_test_source_name (const char *file);
939
940#endif
941/* end of transport_testing.h */
diff --git a/src/transport/transport.conf.in b/src/transport/transport.conf.in
deleted file mode 100644
index de4855c6a..000000000
--- a/src/transport/transport.conf.in
+++ /dev/null
@@ -1,248 +0,0 @@
1[transport]
2START_ON_DEMAND = @START_ON_DEMAND@
3@JAVAPORT@PORT = 2091
4HOSTNAME = localhost
5BINARY = gnunet-service-transport
6# PREFIX = valgrind
7
8# Maximum number of neighbours PER PLUGIN (not in total).
9NEIGHBOUR_LIMIT = 50
10ACCEPT_FROM = 127.0.0.1;
11ACCEPT_FROM6 = ::1;
12# TCP is the only transport plugin known to work "reliably"
13PLUGINS = tcp
14UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport.sock
15BLACKLIST_FILE = $GNUNET_CONFIG_HOME/transport/blacklist
16UNIX_MATCH_UID = NO
17UNIX_MATCH_GID = YES
18# DISABLE_SOCKET_FORWARDING = NO
19# USERNAME =
20# MAXBUF =
21# TIMEOUT =
22# DISABLEV6 =
23# BINDTO =
24# REJECT_FROM =
25# REJECT_FROM6 =
26# PREFIX = valgrind --leak-check=full
27
28# Configuration settings related to traffic manipulation for testing purposes
29# Distance
30# MANIPULATE_DISTANCE_IN = 1
31# MANIPULATE_DISTANCE_OUT = 1
32# Delay; WARNING: to large values may lead to peers not connecting!
33# MANIPULATE_DELAY_IN = 1 ms
34# MANIPULATE_DELAY_OUT = 1 ms
35
36
37[transport-unix]
38UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-transport-plugin-unix.sock
39TESTING_IGNORE_KEYS = ACCEPT_FROM;
40
41[transport-tcp]
42# Use 0 to ONLY advertise as a peer behind NAT (no port binding)
43PORT = 2086
44
45# Obsolete option, to be replaced by HOLE_EXTERNAL (soon)
46ADVERTISED_PORT = 2086
47
48# If we have a manually punched NAT, what is the external IP and port?
49# Can use DNS names for DynDNS-based detection of external IP.
50# Can use IPv6 addresses ([fefc::]:PORT).
51# Use "AUTO" for the hostname to automatically detect external IP.
52# Do not set if NAT is not manually punched.
53# HOLE_EXTERNAL = AUTO:2086
54
55TESTING_IGNORE_KEYS = ACCEPT_FROM;
56
57# Maximum number of open TCP connections allowed
58MAX_CONNECTIONS = 128
59
60TIMEOUT = 5 s
61# ACCEPT_FROM =
62# ACCEPT_FROM6 =
63# REJECT_FROM =
64# REJECT_FROM6 =
65# BINDTO =
66MAX_CONNECTIONS = 128
67
68# Enable TCP stealth?
69TCP_STEALTH = NO
70
71
72
73[transport-xt]
74# Use 0 to ONLY advertise as a peer behind NAT (no port binding)
75PORT = 2087
76
77# Obsolete option, to be replaced by HOLE_EXTERNAL (soon)
78ADVERTISED_PORT = 2087
79
80# If we have a manually punched NAT, what is the external IP and port?
81# Can use DNS names for DynDNS-based detection of external IP.
82# Can use IPv6 addresses ([fefc::]:PORT).
83# Use "AUTO" for the hostname to automatically detect external IP.
84# Do not set if NAT is not manually punched.
85# HOLE_EXTERNAL = AUTO:2087
86
87TESTING_IGNORE_KEYS = ACCEPT_FROM;
88
89# Maximum number of open TCP connections allowed
90MAX_CONNECTIONS = 128
91
92TIMEOUT = 5 s
93# ACCEPT_FROM =
94# ACCEPT_FROM6 =
95# REJECT_FROM =
96# REJECT_FROM6 =
97# BINDTO =
98MAX_CONNECTIONS = 128
99
100# Enable TCP stealth?
101TCP_STEALTH = NO
102
103
104[transport-udp]
105# Use PORT = 0 to autodetect a port available
106PORT = 2086
107BROADCAST = YES
108BROADCAST_RECEIVE = YES
109BROADCAST_INTERVAL = 30 s
110
111# This limits UDP to 1MB/s for SENDING. Higher values are advised
112# for benchmarking or well-connected systems. Note that this quota
113# applies IN ADDITION to the system-wide transport-wide WAN/LAN
114# quotas.
115MAX_BPS = 1000000
116TESTING_IGNORE_KEYS = ACCEPT_FROM;
117
118# If we have a manually punched NAT, what is the external IP and port?
119# Can use DNS names for DynDNS-based detection of external IP.
120# Can use IPv6 addresses ([fefc::]:PORT).
121# Use "AUTO" for the hostname to automatically detect external IP.
122# Do not set if NAT is not manually punched.
123# HOLE_EXTERNAL = AUTO:2086
124
125
126[transport-xu]
127# Use PORT = 0 to autodetect a port available
128PORT = 2087
129
130
131[transport-http_client]
132MAX_CONNECTIONS = 128
133TESTING_IGNORE_KEYS = ACCEPT_FROM;
134# Hostname or IP of proxy server
135# PROXY =
136
137# User name for proxy server
138# PROXY_USERNAME =
139# User password for proxy server
140# PROXY_PASSWORD =
141
142# Type of proxy server,
143# Valid values: HTTP, SOCKS4, SOCKS5, SOCKS4A, SOCKS5_HOSTNAME
144# Default: HTTP
145# PROXY_TYPE = HTTP
146
147# Enable tunneling proxy request instead of having proxy server evaluate it
148# Experimental, default: NO
149# PROXY_HTTP_TUNNELING = NO
150
151
152[transport-http_server]
153#EXTERNAL_HOSTNAME = <your hostname/path>
154PORT = 1080
155
156# Obsolete option, to be replaced by HOLE_EXTERNAL (soon)
157ADVERTISED_PORT = 1080
158
159# If we have a manually punched NAT, what is the external IP and port?
160# Can use DNS names for DynDNS-based detection of external IP.
161# Can use IPv6 addresses ([fefc::]:PORT).
162# Use "AUTO" for the hostname to automatically detect external IP.
163# Do not set if NAT is not manually punched.
164# HOLE_EXTERNAL = AUTO:1080
165
166MAX_CONNECTIONS = 128
167TESTING_IGNORE_KEYS = ACCEPT_FROM;
168
169# Enable TCP stealth?
170TCP_STEALTH = NO
171
172
173[transport-https_client]
174MAX_CONNECTIONS = 128
175TESTING_IGNORE_KEYS = ACCEPT_FROM;
176# Hostname or IP of proxy server
177# PROXY =
178
179# User name for proxy server
180# PROXY_USERNAME =
181# User password for proxy server
182# PROXY_PASSWORD =
183
184# Type of proxy server,
185# Valid values: HTTP, SOCKS4, SOCKS5, SOCKS4A, SOCKS5_HOSTNAME
186# Default: HTTP
187# PROXY_TYPE = HTTP
188
189# Enable tunneling proxy request instead of having proxy server evaluate it
190# Experimental, default: NO
191# PROXY_HTTP_TUNNELING = NO
192
193
194[transport-https_server]
195# EXTERNAL_HOSTNAME = <your hostname/path>
196# EXTERNAL_HOSTNAME_ONLY = YES
197# If you have a valid SSL certificate for your external hostname tell,
198# clients to verify it
199# VERIFY_EXTERNAL_HOSTNAME = YES
200# Does the external hostname use the same port?
201# EXTERNAL_HOSTNAME_USE_PORT = YES
202PORT = 4433
203
204# Obsolete option, to be replaced by HOLE_EXTERNAL (soon)
205ADVERTISED_PORT = 4433
206
207# If we have a manually punched NAT, what is the external IP and port?
208# Can use DNS names for DynDNS-based detection of external IP.
209# Can use IPv6 addresses ([fefc::]:PORT).
210# Use "AUTO" for the hostname to automatically detect external IP.
211# Do not set if NAT is not manually punched.
212# HOLE_EXTERNAL = AUTO:4433
213
214CRYPTO_INIT = NORMAL
215KEY_FILE = $GNUNET_DATA_HOME/transport/https.key
216CERT_FILE = $GNUNET_DATA_HOME/transport/https.cert
217MAX_CONNECTIONS = 128
218TESTING_IGNORE_KEYS = ACCEPT_FROM;
219
220# Enable TCP stealth?
221TCP_STEALTH = NO
222
223
224[transport-wlan]
225# Name of the interface in monitor mode (typically monX)
226INTERFACE = mon0
227# Real hardware, no testing
228TESTMODE = 0
229TESTING_IGNORE_KEYS = ACCEPT_FROM;
230
231
232[transport-bluetooth]
233# Name of the interface (typically hciX)
234INTERFACE = hci0
235# Real hardware, no testing
236TESTMODE = 0
237TESTING_IGNORE_KEYS = ACCEPT_FROM;
238
239[communicator-tcp]
240#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
241#PREFIX = valgrind --leak-check=full --track-origins=yes
242BINDTO = 2086
243DISABLE_V6 = NO
244BINARY = gnunet-communicator-tcp
245IMMEDIATE_START = YES
246
247[communicator-quic]
248BINDTO = 127.0.0.1
diff --git a/src/transport/transport.h b/src/transport/transport.h
deleted file mode 100644
index 66f17ee5b..000000000
--- a/src/transport/transport.h
+++ /dev/null
@@ -1,828 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2014 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 transport/transport.h
23 * @brief common internal definitions for transport service
24 * @author Christian Grothoff
25 */
26#ifndef TRANSPORT_H
27#define TRANSPORT_H
28
29#include "gnunet_util_lib.h"
30#include "gnunet_time_lib.h"
31#include "gnunet_constants.h"
32
33#define DEBUG_TRANSPORT GNUNET_EXTRA_LOGGING
34
35
36/**
37 * Similar to GNUNET_TRANSPORT_NotifyDisconnect but in and out quotas are
38 * included here. These values are not required outside transport_api
39 *
40 * @param cls closure
41 * @param peer the peer that connected
42 * @param bandwidth_in inbound bandwidth in NBO
43 * @param bandwidth_out outbound bandwidth in NBO
44 *
45 */
46typedef void (*NotifyConnect) (
47 void *cls,
48 const struct GNUNET_PeerIdentity *peer,
49 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
50 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out);
51
52
53GNUNET_NETWORK_STRUCT_BEGIN
54
55
56/**
57 * Message from the transport service to the library
58 * asking to check if both processes agree about this
59 * peers identity.
60 */
61struct StartMessage
62{
63 /**
64 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_START
65 */
66 struct GNUNET_MessageHeader header;
67
68 /**
69 * 0: no options
70 * 1: The @e self field should be checked
71 * 2: this client is interested in payload traffic
72 */
73 uint32_t options;
74
75 /**
76 * Identity we think we have. If it does not match, the
77 * receiver should print out an error message and disconnect.
78 */
79 struct GNUNET_PeerIdentity self;
80};
81
82
83/**
84 * Message from the transport service to the library
85 * informing about neighbors.
86 */
87struct ConnectInfoMessage
88{
89 /**
90 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT
91 */
92 struct GNUNET_MessageHeader header;
93
94#if (defined(GNUNET_TRANSPORT_COMMUNICATION_VERSION) || \
95 defined(GNUNET_TRANSPORT_CORE_VERSION))
96
97 /**
98 * Always zero, for alignment.
99 */
100 uint32_t reserved GNUNET_PACKED;
101#else
102 /**
103 * Current outbound quota for this peer
104 */
105 struct GNUNET_BANDWIDTH_Value32NBO quota_out;
106#endif
107
108 /**
109 * Identity of the new neighbour.
110 */
111 struct GNUNET_PeerIdentity id;
112};
113
114
115/**
116 * Message from the transport service to the library
117 * informing about disconnects.
118 */
119struct DisconnectInfoMessage
120{
121 /**
122 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT
123 */
124 struct GNUNET_MessageHeader header;
125
126 /**
127 * Reserved, always zero.
128 */
129 uint32_t reserved GNUNET_PACKED;
130
131 /**
132 * Who got disconnected?
133 */
134 struct GNUNET_PeerIdentity peer;
135};
136
137
138/**
139 * Message used to notify the transport API about a message
140 * received from the network. The actual message follows.
141 */
142struct InboundMessage
143{
144 /**
145 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_RECV
146 */
147 struct GNUNET_MessageHeader header;
148
149 /**
150 * Which peer sent the message?
151 */
152 struct GNUNET_PeerIdentity peer;
153};
154
155
156/**
157 * Message used to notify the transport API that it can
158 * send another message to the transport service.
159 */
160struct SendOkMessage
161{
162 /**
163 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK
164 */
165 struct GNUNET_MessageHeader header;
166
167#if (defined(GNUNET_TRANSPORT_COMMUNICATION_VERSION) || \
168 defined(GNUNET_TRANSPORT_CORE_VERSION))
169
170 uint32_t reserved GNUNET_PACKED;
171#else
172 /**
173 * #GNUNET_OK if the transmission succeeded,
174 * #GNUNET_SYSERR if it failed (i.e. network disconnect);
175 * in either case, it is now OK for this client to
176 * send us another message for the given peer.
177 */
178 uint16_t success GNUNET_PACKED;
179
180 /**
181 * Size of message sent
182 */
183 uint16_t bytes_msg GNUNET_PACKED;
184
185 /**
186 * Size of message sent over wire.
187 * Includes plugin and protocol specific overheads.
188 */
189 uint32_t bytes_physical GNUNET_PACKED;
190#endif
191
192 /**
193 * Which peer can send more now?
194 */
195 struct GNUNET_PeerIdentity peer;
196};
197
198
199/**
200 * Message used to notify the transport API that it can
201 * send another message to the transport service.
202 * (Used to implement flow control.)
203 */
204struct RecvOkMessage
205{
206 /**
207 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK
208 */
209 struct GNUNET_MessageHeader header;
210
211 /**
212 * Number of messages by which to increase the window, greater or
213 * equal to one.
214 */
215 uint32_t increase_window_delta GNUNET_PACKED;
216
217 /**
218 * Which peer can CORE handle more from now?
219 */
220 struct GNUNET_PeerIdentity peer;
221};
222
223
224/**
225 * Message used to notify the transport service about a message
226 * to be transmitted to another peer. The actual message follows.
227 */
228struct OutboundMessage
229{
230 /**
231 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_SEND
232 */
233 struct GNUNET_MessageHeader header;
234
235 /**
236 * An `enum GNUNET_MQ_PriorityPreferences` in NBO.
237 */
238 uint32_t priority GNUNET_PACKED;
239
240#if ! (defined(GNUNET_TRANSPORT_COMMUNICATION_VERSION) || \
241 defined(GNUNET_TRANSPORT_CORE_VERSION))
242
243 /**
244 * Allowed delay.
245 */
246 struct GNUNET_TIME_RelativeNBO timeout;
247#endif
248
249 /**
250 * Which peer should receive the message?
251 */
252 struct GNUNET_PeerIdentity peer;
253};
254
255
256/* *********************** TNG messages ***************** */
257
258/**
259 * Communicator goes online. Note which addresses it can
260 * work with.
261 */
262struct GNUNET_TRANSPORT_CommunicatorAvailableMessage
263{
264 /**
265 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR.
266 */
267 struct GNUNET_MessageHeader header;
268
269 /**
270 * NBO encoding of `enum GNUNET_TRANSPORT_CommunicatorCharacteristics`
271 */
272 uint32_t cc;
273
274 /* Followed by the address prefix of the communicator */
275};
276
277
278/**
279 * Add address to the list.
280 */
281struct GNUNET_TRANSPORT_AddAddressMessage
282{
283 /**
284 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS.
285 */
286 struct GNUNET_MessageHeader header;
287
288 /**
289 * Address identifier (used during deletion).
290 */
291 uint32_t aid GNUNET_PACKED;
292
293 /**
294 * When does the address expire?
295 */
296 struct GNUNET_TIME_RelativeNBO expiration;
297
298 /**
299 * An `enum GNUNET_NetworkType` in NBO.
300 */
301 uint32_t nt;
302
303 /* followed by UTF-8 encoded, 0-terminated human-readable address */
304};
305
306
307/**
308 * Remove address from the list.
309 */
310struct GNUNET_TRANSPORT_DelAddressMessage
311{
312 /**
313 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS.
314 */
315 struct GNUNET_MessageHeader header;
316
317 /**
318 * Address identifier.
319 */
320 uint32_t aid GNUNET_PACKED;
321};
322
323
324/**
325 * Inform transport about an incoming message.
326 */
327struct GNUNET_TRANSPORT_IncomingMessage
328{
329 /**
330 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG.
331 */
332 struct GNUNET_MessageHeader header;
333
334 /**
335 * Do we use flow control or not?
336 */
337 uint32_t fc_on GNUNET_PACKED;
338
339 /**
340 * 64-bit number to identify the matching ACK.
341 */
342 uint64_t fc_id GNUNET_PACKED;
343
344 /**
345 * How long does the communicator believe the address on which
346 * the message was received to remain valid?
347 */
348 struct GNUNET_TIME_RelativeNBO expected_address_validity;
349
350 /**
351 * Sender identifier.
352 */
353 struct GNUNET_PeerIdentity sender;
354
355 /**
356 * Direct neighbour sender identifier.
357 */
358 struct GNUNET_PeerIdentity neighbour_sender;
359
360 /* followed by the message */
361};
362
363
364/**
365 * Transport informs us about being done with an incoming message.
366 * (only sent if fc_on was set).
367 */
368struct GNUNET_TRANSPORT_IncomingMessageAck
369{
370 /**
371 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK.
372 */
373 struct GNUNET_MessageHeader header;
374
375 /**
376 * Reserved (0)
377 */
378 uint32_t reserved GNUNET_PACKED;
379
380 /**
381 * Which message is being ACKed?
382 */
383 uint64_t fc_id GNUNET_PACKED;
384
385 /**
386 * Sender identifier of the original message.
387 */
388 struct GNUNET_PeerIdentity sender;
389};
390
391
392/**
393 * Add queue to the transport
394 */
395struct GNUNET_TRANSPORT_AddQueueMessage
396{
397 /**
398 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP.
399 */
400 struct GNUNET_MessageHeader header;
401
402 /**
403 * Queue identifier (used to identify the queue).
404 */
405 uint32_t qid GNUNET_PACKED;
406
407 /**
408 * Receiver that can be addressed via the queue.
409 */
410 struct GNUNET_PeerIdentity receiver;
411
412 /**
413 * An `enum GNUNET_NetworkType` in NBO.
414 */
415 uint32_t nt;
416
417 /**
418 * Maximum transmission unit, in NBO. UINT32_MAX for unlimited.
419 */
420 uint32_t mtu;
421
422 /**
423 * Queue length, in NBO. Defines how many messages may be
424 * send through this queue. UINT64_MAX for unlimited.
425 */
426 uint64_t q_len;
427
428 /**
429 * Priority of the queue in relation to other queues.
430 */
431 uint32_t priority;
432
433 /**
434 * An `enum GNUNET_TRANSPORT_ConnectionStatus` in NBO.
435 */
436 uint32_t cs;
437
438 /* followed by UTF-8 encoded, 0-terminated human-readable address */
439};
440
441
442/**
443 * Update queue
444 */
445struct GNUNET_TRANSPORT_UpdateQueueMessage
446{
447 /**
448 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP.
449 */
450 struct GNUNET_MessageHeader header;
451
452 /**
453 * Queue identifier (used to identify the queue).
454 */
455 uint32_t qid GNUNET_PACKED;
456
457 /**
458 * Receiver that can be addressed via the queue.
459 */
460 struct GNUNET_PeerIdentity receiver;
461
462 /**
463 * An `enum GNUNET_NetworkType` in NBO.
464 */
465 uint32_t nt;
466
467 /**
468 * Maximum transmission unit, in NBO. UINT32_MAX for unlimited.
469 */
470 uint32_t mtu;
471
472 /**
473 * Queue length, in NBO. Defines how many messages may be
474 * send through this queue. UINT64_MAX for unlimited.
475 */
476 uint64_t q_len;
477
478 /**
479 * Priority of the queue in relation to other queues.
480 */
481 uint32_t priority;
482
483 /**
484 * An `enum GNUNET_TRANSPORT_ConnectionStatus` in NBO.
485 */
486 uint32_t cs;
487};
488
489
490/**
491 * Remove queue, it is no longer available.
492 */
493struct GNUNET_TRANSPORT_DelQueueMessage
494{
495 /**
496 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN.
497 */
498 struct GNUNET_MessageHeader header;
499
500 /**
501 * Address identifier.
502 */
503 uint32_t qid GNUNET_PACKED;
504
505 /**
506 * Receiver that can be addressed via the queue.
507 */
508 struct GNUNET_PeerIdentity receiver;
509};
510
511
512/**
513 * Transport tells communicator that it wants a new queue.
514 */
515struct GNUNET_TRANSPORT_CreateQueue
516{
517 /**
518 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE.
519 */
520 struct GNUNET_MessageHeader header;
521
522 /**
523 * Unique ID for the request.
524 */
525 uint32_t request_id GNUNET_PACKED;
526
527 /**
528 * Receiver that can be addressed via the queue.
529 */
530 struct GNUNET_PeerIdentity receiver;
531
532 /* followed by UTF-8 encoded, 0-terminated human-readable address */
533};
534
535
536/**
537 * Communicator tells transport how queue creation went down.
538 */
539struct GNUNET_TRANSPORT_CreateQueueResponse
540{
541 /**
542 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK or
543 * #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL.
544 */
545 struct GNUNET_MessageHeader header;
546
547 /**
548 * Unique ID for the request.
549 */
550 uint32_t request_id GNUNET_PACKED;
551};
552
553
554/**
555 * Inform communicator about transport's desire to send a message.
556 */
557struct GNUNET_TRANSPORT_SendMessageTo
558{
559 /**
560 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG.
561 */
562 struct GNUNET_MessageHeader header;
563
564 /**
565 * Which queue should we use?
566 */
567 uint32_t qid GNUNET_PACKED;
568
569 /**
570 * Message ID, used for flow control.
571 */
572 uint64_t mid GNUNET_PACKED;
573
574 /**
575 * Receiver identifier.
576 */
577 struct GNUNET_PeerIdentity receiver;
578
579 /* followed by the message */
580};
581
582
583/**
584 * Inform transport that message was sent.
585 */
586struct GNUNET_TRANSPORT_SendMessageToAck
587{
588 /**
589 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK.
590 */
591 struct GNUNET_MessageHeader header;
592
593 /**
594 * Success (#GNUNET_OK), failure (#GNUNET_SYSERR).
595 */
596 uint32_t status GNUNET_PACKED;
597
598 /**
599 * Message ID of the original message.
600 */
601 uint64_t mid GNUNET_PACKED;
602
603 /**
604 * Queue ID for the queue which was used to send the message.
605 */
606 uint32_t qid GNUNET_PACKED;
607
608 /**
609 * Receiver identifier.
610 */
611 struct GNUNET_PeerIdentity receiver;
612};
613
614
615/**
616 * Message from communicator to transport service asking for
617 * transmission of a backchannel message with the given peer @e pid
618 * and communicator.
619 */
620struct GNUNET_TRANSPORT_CommunicatorBackchannel
621{
622 /**
623 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL
624 */
625 struct GNUNET_MessageHeader header;
626
627 /**
628 * Always zero, for alignment.
629 */
630 uint32_t reserved;
631
632 /**
633 * Target peer.
634 */
635 struct GNUNET_PeerIdentity pid;
636
637 /* Followed by a `struct GNUNET_MessageHeader` with the encapsulated
638 message to the communicator */
639
640 /* Followed by the 0-terminated string specifying the desired
641 communicator at the target (@e pid) peer */
642};
643
644
645/**
646 * Message from transport to communicator passing along a backchannel
647 * message from the given peer @e pid.
648 */
649struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming
650{
651 /**
652 * Type will be
653 * #GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING
654 */
655 struct GNUNET_MessageHeader header;
656
657 /**
658 * Always zero, for alignment.
659 */
660 uint32_t reserved;
661
662 /**
663 * Origin peer.
664 */
665 struct GNUNET_PeerIdentity pid;
666
667 /* Followed by a `struct GNUNET_MessageHeader` with the encapsulated
668 message to the communicator */
669};
670
671
672/**
673 * Request to start monitoring.
674 */
675struct GNUNET_TRANSPORT_MonitorStart
676{
677 /**
678 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START.
679 */
680 struct GNUNET_MessageHeader header;
681
682 /**
683 * #GNUNET_YES for one-shot montoring, #GNUNET_NO for continuous monitoring.
684 */
685 uint32_t one_shot;
686
687 /**
688 * Target identifier to monitor, all zeros for "all peers".
689 */
690 struct GNUNET_PeerIdentity peer;
691};
692
693
694/**
695 * Monitoring data.
696 */
697struct GNUNET_TRANSPORT_MonitorData
698{
699 /**
700 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA.
701 */
702 struct GNUNET_MessageHeader header;
703
704 /**
705 * Network type (an `enum GNUNET_NetworkType` in NBO).
706 */
707 uint32_t nt GNUNET_PACKED;
708
709 /**
710 * Target identifier.
711 */
712 struct GNUNET_PeerIdentity peer;
713
714 /**
715 * @deprecated To be discussed if we keep these...
716 */
717 struct GNUNET_TIME_AbsoluteNBO last_validation;
718 struct GNUNET_TIME_AbsoluteNBO valid_until;
719 struct GNUNET_TIME_AbsoluteNBO next_validation;
720
721 /**
722 * Current round-trip time estimate.
723 */
724 struct GNUNET_TIME_RelativeNBO rtt;
725
726 /**
727 * Connection status (in NBO).
728 */
729 uint32_t cs GNUNET_PACKED;
730
731 /**
732 * Messages pending (in NBO).
733 */
734 uint32_t num_msg_pending GNUNET_PACKED;
735
736 /**
737 * Bytes pending (in NBO).
738 */
739 uint32_t num_bytes_pending GNUNET_PACKED;
740
741 /* Followed by 0-terminated address of the peer */
742};
743
744
745/**
746 * Request to verify address.
747 */
748struct GNUNET_TRANSPORT_AddressToVerify
749{
750 /**
751 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_CONSIDER_VERIFY.
752 */
753 struct GNUNET_MessageHeader header;
754
755 /**
756 * Reserved. 0.
757 */
758 uint32_t reserved;
759
760 /**
761 * Peer the address is from.
762 */
763 struct GNUNET_PeerIdentity peer;
764
765 /* followed by variable-size raw address */
766};
767
768
769/**
770 * Application client to TRANSPORT service: we would like to have
771 * address suggestions for this peer.
772 */
773struct ExpressPreferenceMessage
774{
775 /**
776 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST or
777 * #GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL to stop
778 * suggestions.
779 */
780 struct GNUNET_MessageHeader header;
781
782 /**
783 * What type of performance preference does the client have?
784 * A `enum GNUNET_MQ_PreferenceKind` in NBO.
785 */
786 uint32_t pk GNUNET_PACKED;
787
788 /**
789 * Peer to get address suggestions for.
790 */
791 struct GNUNET_PeerIdentity peer;
792
793 /**
794 * How much bandwidth in bytes/second does the application expect?
795 */
796 struct GNUNET_BANDWIDTH_Value32NBO bw;
797};
798
799
800/**
801 * We got an address of another peer, TRANSPORT service
802 * should validate it. There is no response.
803 */
804struct RequestHelloValidationMessage
805{
806 /**
807 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION.
808 */
809 struct GNUNET_MessageHeader header;
810
811 /**
812 * What type of network does the other peer claim this is?
813 * A `enum GNUNET_NetworkType` in NBO.
814 */
815 uint32_t nt GNUNET_PACKED;
816
817 /**
818 * Peer to the address is presumably for.
819 */
820 struct GNUNET_PeerIdentity peer;
821
822 /* followed by 0-terminated address to validate */
823};
824
825GNUNET_NETWORK_STRUCT_END
826
827/* end of transport.h */
828#endif
diff --git a/src/transport/transport_api2_application.c b/src/transport/transport_api2_application.c
deleted file mode 100644
index 00f5f62eb..000000000
--- a/src/transport/transport_api2_application.c
+++ /dev/null
@@ -1,397 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010--2019 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file transport/transport_api2_application.c
22 * @brief enable clients to ask TRANSPORT about establishing connections to peers
23 * @author Christian Grothoff
24 * @author Matthias Wachs
25 */
26#include "platform.h"
27#include "gnunet_transport_application_service.h"
28#include "gnunet_transport_core_service.h"
29#include "transport.h"
30
31
32#define LOG(kind, ...) \
33 GNUNET_log_from (kind, "transport-application-api", __VA_ARGS__)
34
35
36/**
37 * Handle for TRANSPORT address suggestion requests.
38 */
39struct GNUNET_TRANSPORT_ApplicationSuggestHandle
40{
41 /**
42 * ID of the peer for which address suggestion was requested.
43 */
44 struct GNUNET_PeerIdentity id;
45
46 /**
47 * Connecitivity handle this suggestion handle belongs to.
48 */
49 struct GNUNET_TRANSPORT_ApplicationHandle *ch;
50
51 /**
52 * What preference is being expressed?
53 */
54 enum GNUNET_MQ_PriorityPreferences pk;
55
56 /**
57 * How much bandwidth does the client expect?
58 */
59 struct GNUNET_BANDWIDTH_Value32NBO bw;
60};
61
62
63/**
64 * Handle to the TRANSPORT subsystem for application management.
65 */
66struct GNUNET_TRANSPORT_ApplicationHandle
67{
68 /**
69 * Our configuration.
70 */
71 const struct GNUNET_CONFIGURATION_Handle *cfg;
72
73 /**
74 * Map with the identities of all the peers for which we would
75 * like to have address suggestions. The key is the PID, the
76 * value is currently the `struct GNUNET_TRANSPORT_ApplicationSuggestHandle`
77 */
78 struct GNUNET_CONTAINER_MultiPeerMap *sug_requests;
79
80 /**
81 * Message queue for sending requests to the TRANSPORT service.
82 */
83 struct GNUNET_MQ_Handle *mq;
84
85 /**
86 * Task to trigger reconnect.
87 */
88 struct GNUNET_SCHEDULER_Task *task;
89
90 /**
91 * Reconnect backoff delay.
92 */
93 struct GNUNET_TIME_Relative backoff;
94};
95
96
97/**
98 * Re-establish the connection to the TRANSPORT service.
99 *
100 * @param ch handle to use to re-connect.
101 */
102static void
103reconnect (struct GNUNET_TRANSPORT_ApplicationHandle *ch);
104
105
106/**
107 * Re-establish the connection to the TRANSPORT service.
108 *
109 * @param cls handle to use to re-connect.
110 */
111static void
112reconnect_task (void *cls)
113{
114 struct GNUNET_TRANSPORT_ApplicationHandle *ch = cls;
115
116 ch->task = NULL;
117 reconnect (ch);
118}
119
120
121/**
122 * Disconnect from TRANSPORT and then reconnect.
123 *
124 * @param ch our handle
125 */
126static void
127force_reconnect (struct GNUNET_TRANSPORT_ApplicationHandle *ch)
128{
129 if (NULL != ch->mq)
130 {
131 GNUNET_MQ_destroy (ch->mq);
132 ch->mq = NULL;
133 }
134 ch->backoff = GNUNET_TIME_STD_BACKOFF (ch->backoff);
135 ch->task = GNUNET_SCHEDULER_add_delayed (ch->backoff, &reconnect_task, ch);
136}
137
138
139/**
140 * We encountered an error handling the MQ to the
141 * TRANSPORT service. Reconnect.
142 *
143 * @param cls the `struct GNUNET_TRANSPORT_ApplicationHandle`
144 * @param error details about the error
145 */
146static void
147error_handler (void *cls, enum GNUNET_MQ_Error error)
148{
149 struct GNUNET_TRANSPORT_ApplicationHandle *ch = cls;
150
151 LOG (GNUNET_ERROR_TYPE_DEBUG,
152 "TRANSPORT connection died (code %d), reconnecting\n",
153 (int) error);
154 force_reconnect (ch);
155}
156
157
158/**
159 * Transmit request for an address suggestion.
160 *
161 * @param cls the `struct GNUNET_TRANSPORT_ApplicationHandle`
162 * @param peer peer to ask for an address suggestion for
163 * @param value the `struct GNUNET_TRANSPORT_SuggestHandle`
164 * @return #GNUNET_OK (continue to iterate), #GNUNET_SYSERR on
165 * failure (message queue no longer exists)
166 */
167static int
168transmit_suggestion (void *cls,
169 const struct GNUNET_PeerIdentity *peer,
170 void *value)
171{
172 struct GNUNET_TRANSPORT_ApplicationHandle *ch = cls;
173 struct GNUNET_TRANSPORT_ApplicationSuggestHandle *sh = value;
174 struct GNUNET_MQ_Envelope *ev;
175 struct ExpressPreferenceMessage *m;
176
177 if (NULL == ch->mq)
178 return GNUNET_SYSERR;
179 ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST);
180 m->pk = htonl ((uint32_t) sh->pk);
181 m->bw = sh->bw;
182 m->peer = *peer;
183 GNUNET_MQ_send (ch->mq, ev);
184 return GNUNET_OK;
185}
186
187
188/**
189 * Re-establish the connection to the TRANSPORT service.
190 *
191 * @param ch handle to use to re-connect.
192 */
193static void
194reconnect (struct GNUNET_TRANSPORT_ApplicationHandle *ch)
195{
196 static const struct GNUNET_MQ_MessageHandler handlers[] = { { NULL, 0, 0 } };
197
198 GNUNET_assert (NULL == ch->mq);
199 ch->mq =
200 GNUNET_CLIENT_connect (ch->cfg, "transport", handlers, &error_handler, ch);
201 if (NULL == ch->mq)
202 {
203 force_reconnect (ch);
204 return;
205 }
206 GNUNET_CONTAINER_multipeermap_iterate (ch->sug_requests,
207 &transmit_suggestion,
208 ch);
209}
210
211
212/**
213 * Initialize the TRANSPORT application suggestion client handle.
214 *
215 * @param cfg configuration to use
216 * @return transport application handle, NULL on error
217 */
218struct GNUNET_TRANSPORT_ApplicationHandle *
219GNUNET_TRANSPORT_application_init (
220 const struct GNUNET_CONFIGURATION_Handle *cfg)
221{
222 struct GNUNET_TRANSPORT_ApplicationHandle *ch;
223
224 ch = GNUNET_new (struct GNUNET_TRANSPORT_ApplicationHandle);
225 ch->cfg = cfg;
226 ch->sug_requests = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_YES);
227 reconnect (ch);
228 return ch;
229}
230
231
232/**
233 * Function called to free all `struct GNUNET_TRANSPORT_ApplicationSuggestHandle`s
234 * in the map.
235 *
236 * @param cls NULL
237 * @param key the key
238 * @param value the value to free
239 * @return #GNUNET_OK (continue to iterate)
240 */
241static int
242free_sug_handle (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
243{
244 struct GNUNET_TRANSPORT_ApplicationSuggestHandle *cur = value;
245
246 GNUNET_free (cur);
247 return GNUNET_OK;
248}
249
250
251/**
252 * Client is done with TRANSPORT application management, release resources.
253 *
254 * @param ch handle to release
255 */
256void
257GNUNET_TRANSPORT_application_done (
258 struct GNUNET_TRANSPORT_ApplicationHandle *ch)
259{
260 if (NULL != ch->mq)
261 {
262 GNUNET_MQ_destroy (ch->mq);
263 ch->mq = NULL;
264 }
265 if (NULL != ch->task)
266 {
267 GNUNET_SCHEDULER_cancel (ch->task);
268 ch->task = NULL;
269 }
270 GNUNET_CONTAINER_multipeermap_iterate (ch->sug_requests,
271 &free_sug_handle,
272 NULL);
273 GNUNET_CONTAINER_multipeermap_destroy (ch->sug_requests);
274 GNUNET_free (ch);
275}
276
277
278/**
279 * An application would like TRANSPORT to connect to a peer.
280 *
281 * @param ch handle
282 * @param peer identity of the peer we need an address for
283 * @param pk what kind of application will the application require (can be
284 * #GNUNET_MQ_PRIO_BACKGROUND, we will still try to connect)
285 * @param bw desired bandwidth, can be zero (we will still try to connect)
286 * @return suggest handle, NULL if a request is already pending
287 */
288struct GNUNET_TRANSPORT_ApplicationSuggestHandle *
289GNUNET_TRANSPORT_application_suggest (
290 struct GNUNET_TRANSPORT_ApplicationHandle *ch,
291 const struct GNUNET_PeerIdentity *peer,
292 enum GNUNET_MQ_PriorityPreferences pk,
293 struct GNUNET_BANDWIDTH_Value32NBO bw)
294{
295 struct GNUNET_TRANSPORT_ApplicationSuggestHandle *s;
296
297 s = GNUNET_new (struct GNUNET_TRANSPORT_ApplicationSuggestHandle);
298 s->ch = ch;
299 s->id = *peer;
300 s->pk = pk;
301 s->bw = bw;
302 (void) GNUNET_CONTAINER_multipeermap_put (
303 ch->sug_requests,
304 &s->id,
305 s,
306 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
307 LOG (GNUNET_ERROR_TYPE_DEBUG,
308 "Requesting TRANSPORT to suggest address for `%s'\n",
309 GNUNET_i2s (peer));
310 if (NULL == ch->mq)
311 return s;
312 GNUNET_assert (GNUNET_OK == transmit_suggestion (ch, &s->id, s));
313 return s;
314}
315
316
317/**
318 * We no longer care about being connected to a peer.
319 *
320 * @param sh handle to stop
321 */
322void
323GNUNET_TRANSPORT_application_suggest_cancel (
324 struct GNUNET_TRANSPORT_ApplicationSuggestHandle *sh)
325{
326 struct GNUNET_TRANSPORT_ApplicationHandle *ch = sh->ch;
327 struct GNUNET_MQ_Envelope *ev;
328 struct ExpressPreferenceMessage *m;
329
330 LOG (GNUNET_ERROR_TYPE_DEBUG,
331 "Telling TRANSPORT we no longer care for an address for `%s'\n",
332 GNUNET_i2s (&sh->id));
333 GNUNET_assert (
334 GNUNET_OK ==
335 GNUNET_CONTAINER_multipeermap_remove (ch->sug_requests, &sh->id, sh));
336 if (NULL == ch->mq)
337 {
338 GNUNET_free (sh);
339 return;
340 }
341 ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL);
342 m->pk = htonl ((uint32_t) sh->pk);
343 m->bw = sh->bw;
344 m->peer = sh->id;
345 GNUNET_MQ_send (ch->mq, ev);
346 GNUNET_free (sh);
347}
348
349
350/**
351 * An application (or a communicator) has received a HELLO (or other address
352 * data of another peer) and wants TRANSPORT to validate that the address is
353 * correct. The result is NOT returned, in fact TRANSPORT may do nothing
354 * (i.e. if it has too many active validations or recently tried this one
355 * already). If the @a addr validates, TRANSPORT will persist the address
356 * with PEERSTORE.
357 *
358 * @param ch handle
359 * @param peer identity of the peer we have an address for
360 * @param nt network type of @a addr (as claimed by the other peer);
361 * used by TRANSPORT to avoid trying @a addr's that really cannot work
362 * due to network type mismatches
363 * @param addr address to validate
364 */
365void
366GNUNET_TRANSPORT_application_validate (
367 struct GNUNET_TRANSPORT_ApplicationHandle *ch,
368 const struct GNUNET_PeerIdentity *peer,
369 enum GNUNET_NetworkType nt,
370 const char *addr)
371{
372 struct GNUNET_MQ_Envelope *ev;
373 struct RequestHelloValidationMessage *m;
374 size_t alen;
375
376 if (NULL == ch->mq)
377 {
378 GNUNET_log (
379 GNUNET_ERROR_TYPE_WARNING,
380 "Address validation for %s:%s skipped as transport is not connected\n",
381 GNUNET_i2s (peer),
382 addr);
383 return;
384 }
385 alen = strlen (addr) + 1;
386 ev =
387 GNUNET_MQ_msg_extra (m,
388 alen,
389 GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION);
390 m->peer = *peer;
391 m->nt = htonl ((uint32_t) nt);
392 memcpy (&m[1], addr, alen);
393 GNUNET_MQ_send (ch->mq, ev);
394}
395
396
397/* end of transport_api2_application.c */
diff --git a/src/transport/transport_api2_communication.c b/src/transport/transport_api2_communication.c
deleted file mode 100644
index 0a7636843..000000000
--- a/src/transport/transport_api2_communication.c
+++ /dev/null
@@ -1,1114 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2018 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 transport/transport_api2_communication.c
23 * @brief implementation of the gnunet_transport_communication_service.h API
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_protocols.h"
29#include "gnunet_transport_communication_service.h"
30#include "transport.h"
31
32
33/**
34 * How many messages do we keep at most in the queue to the
35 * transport service before we start to drop (default,
36 * can be changed via the configuration file).
37 */
38#define DEFAULT_MAX_QUEUE_LENGTH 16
39
40
41/**
42 * Information we track per packet to enable flow control.
43 */
44struct FlowControl
45{
46 /**
47 * Kept in a DLL.
48 */
49 struct FlowControl *next;
50
51 /**
52 * Kept in a DLL.
53 */
54 struct FlowControl *prev;
55
56 /**
57 * Function to call once the message was processed.
58 */
59 GNUNET_TRANSPORT_MessageCompletedCallback cb;
60
61 /**
62 * Closure for @e cb
63 */
64 void *cb_cls;
65
66 /**
67 * Which peer is this about?
68 */
69 struct GNUNET_PeerIdentity sender;
70
71 /**
72 * More-or-less unique ID for the message.
73 */
74 uint64_t id;
75};
76
77
78/**
79 * Information we track per message to tell the transport about
80 * success or failures.
81 */
82struct AckPending
83{
84 /**
85 * Kept in a DLL.
86 */
87 struct AckPending *next;
88
89 /**
90 * Kept in a DLL.
91 */
92 struct AckPending *prev;
93
94 /**
95 * Communicator this entry belongs to.
96 */
97 struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
98
99 /**
100 * Which peer is this about?
101 */
102 struct GNUNET_PeerIdentity receiver;
103
104 /**
105 * More-or-less unique ID for the message.
106 */
107 uint64_t mid;
108
109 /**
110 * Queue ID of the queue which will be used for the message.
111 */
112 uint32_t qid;
113};
114
115
116/**
117 * Opaque handle to the transport service for communicators.
118 */
119struct GNUNET_TRANSPORT_CommunicatorHandle
120{
121 /**
122 * Head of DLL of addresses this communicator offers to the transport service.
123 */
124 struct GNUNET_TRANSPORT_AddressIdentifier *ai_head;
125
126 /**
127 * Tail of DLL of addresses this communicator offers to the transport service.
128 */
129 struct GNUNET_TRANSPORT_AddressIdentifier *ai_tail;
130
131 /**
132 * DLL of messages awaiting flow control confirmation (ack).
133 */
134 struct FlowControl *fc_head;
135
136 /**
137 * DLL of messages awaiting flow control confirmation (ack).
138 */
139 struct FlowControl *fc_tail;
140
141 /**
142 * DLL of messages awaiting transmission confirmation (ack).
143 */
144 struct AckPending *ap_head;
145
146 /**
147 * DLL of messages awaiting transmission confirmation (ack).
148 */
149 struct AckPending *ap_tail;
150
151 /**
152 * DLL of queues we offer.
153 */
154 struct GNUNET_TRANSPORT_QueueHandle *queue_head;
155
156 /**
157 * DLL of queues we offer.
158 */
159 struct GNUNET_TRANSPORT_QueueHandle *queue_tail;
160
161 /**
162 * Our configuration.
163 */
164 const struct GNUNET_CONFIGURATION_Handle *cfg;
165
166 /**
167 * Config section to use.
168 */
169 const char *config_section;
170
171 /**
172 * Address prefix to use.
173 */
174 const char *addr_prefix;
175
176 /**
177 * Function to call when the transport service wants us to initiate
178 * a communication channel with another peer.
179 */
180 GNUNET_TRANSPORT_CommunicatorMqInit mq_init;
181
182 /**
183 * Closure for @e mq_init.
184 */
185 void *mq_init_cls;
186
187 /**
188 * Function to call when the transport service receives messages
189 * for a communicator (i.e. for NAT traversal or for non-bidirectional
190 * communicators).
191 */
192 GNUNET_TRANSPORT_CommunicatorNotify notify_cb;
193
194 /**
195 * Closure for @e notify_Cb.
196 */
197 void *notify_cb_cls;
198
199 /**
200 * Queue to talk to the transport service.
201 */
202 struct GNUNET_MQ_Handle *mq;
203
204 /**
205 * Maximum permissible queue length.
206 */
207 unsigned long long max_queue_length;
208
209 /**
210 * Flow-control identifier generator.
211 */
212 uint64_t fc_gen;
213
214 /**
215 * Internal UUID for the address used in communication with the
216 * transport service.
217 */
218 uint32_t aid_gen;
219
220 /**
221 * Queue identifier generator.
222 */
223 uint32_t queue_gen;
224
225 /**
226 * Characteristics of the communicator.
227 */
228 enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc;
229};
230
231
232/**
233 * Handle returned to identify the internal data structure the transport
234 * API has created to manage a message queue to a particular peer.
235 */
236struct GNUNET_TRANSPORT_QueueHandle
237{
238 /**
239 * Kept in a DLL.
240 */
241 struct GNUNET_TRANSPORT_QueueHandle *next;
242
243 /**
244 * Kept in a DLL.
245 */
246 struct GNUNET_TRANSPORT_QueueHandle *prev;
247
248 /**
249 * Handle this queue belongs to.
250 */
251 struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
252
253 /**
254 * Address used by the communication queue.
255 */
256 char *address;
257
258 /**
259 * The queue itself.
260 */
261 struct GNUNET_MQ_Handle *mq;
262
263 /**
264 * Which peer we can communciate with.
265 */
266 struct GNUNET_PeerIdentity peer;
267
268 /**
269 * Network type of the communication queue.
270 */
271 enum GNUNET_NetworkType nt;
272
273 /**
274 * Communication status of the queue.
275 */
276 enum GNUNET_TRANSPORT_ConnectionStatus cs;
277
278 /**
279 * ID for this queue when talking to the transport service.
280 */
281 uint32_t queue_id;
282
283 /**
284 * Maximum transmission unit for the queue.
285 */
286 uint32_t mtu;
287
288 /**
289 * Queue length.
290 */
291 uint64_t q_len;
292 /**
293 * Queue priority.
294 */
295 uint32_t priority;
296};
297
298
299/**
300 * Internal representation of an address a communicator is
301 * currently providing for the transport service.
302 */
303struct GNUNET_TRANSPORT_AddressIdentifier
304{
305 /**
306 * Kept in a DLL.
307 */
308 struct GNUNET_TRANSPORT_AddressIdentifier *next;
309
310 /**
311 * Kept in a DLL.
312 */
313 struct GNUNET_TRANSPORT_AddressIdentifier *prev;
314
315 /**
316 * Transport handle where the address was added.
317 */
318 struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
319
320 /**
321 * The actual address.
322 */
323 char *address;
324
325 /**
326 * When does the address expire? (Expected lifetime of the
327 * address.)
328 */
329 struct GNUNET_TIME_Relative expiration;
330
331 /**
332 * Internal UUID for the address used in communication with the
333 * transport service.
334 */
335 uint32_t aid;
336
337 /**
338 * Network type for the address.
339 */
340 enum GNUNET_NetworkType nt;
341};
342
343
344/**
345 * (re)connect our communicator to the transport service
346 *
347 * @param ch handle to reconnect
348 */
349static void
350reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch);
351
352
353/**
354 * Send message to the transport service about address @a ai
355 * being now available.
356 *
357 * @param ai address to add
358 */
359static void
360send_add_address (struct GNUNET_TRANSPORT_AddressIdentifier *ai)
361{
362 struct GNUNET_MQ_Envelope *env;
363 struct GNUNET_TRANSPORT_AddAddressMessage *aam;
364
365 if (NULL == ai->ch->mq)
366 return;
367 env = GNUNET_MQ_msg_extra (aam,
368 strlen (ai->address) + 1,
369 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS);
370 aam->expiration = GNUNET_TIME_relative_hton (ai->expiration);
371 aam->nt = htonl ((uint32_t) ai->nt);
372 memcpy (&aam[1], ai->address, strlen (ai->address) + 1);
373 GNUNET_MQ_send (ai->ch->mq, env);
374}
375
376
377/**
378 * Send message to the transport service about address @a ai
379 * being no longer available.
380 *
381 * @param ai address to delete
382 */
383static void
384send_del_address (struct GNUNET_TRANSPORT_AddressIdentifier *ai)
385{
386 struct GNUNET_MQ_Envelope *env;
387 struct GNUNET_TRANSPORT_DelAddressMessage *dam;
388
389 if (NULL == ai->ch->mq)
390 return;
391 env = GNUNET_MQ_msg (dam, GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS);
392 dam->aid = htonl (ai->aid);
393 GNUNET_MQ_send (ai->ch->mq, env);
394}
395
396
397/**
398 * Send message to the transport service about queue @a qh
399 * being now available.
400 *
401 * @param qh queue to add
402 */
403static void
404send_add_queue (struct GNUNET_TRANSPORT_QueueHandle *qh)
405{
406 struct GNUNET_MQ_Envelope *env;
407 struct GNUNET_TRANSPORT_AddQueueMessage *aqm;
408
409 if (NULL == qh->ch->mq)
410 return;
411 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
412 "Sending `GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP` message\n");
413 env = GNUNET_MQ_msg_extra (aqm,
414 strlen (qh->address) + 1,
415 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP);
416 aqm->qid = htonl (qh->queue_id);
417 aqm->receiver = qh->peer;
418 aqm->nt = htonl ((uint32_t) qh->nt);
419 aqm->mtu = htonl (qh->mtu);
420 aqm->q_len = GNUNET_htonll (qh->q_len);
421 aqm->priority = htonl (qh->priority);
422 aqm->cs = htonl ((uint32_t) qh->cs);
423 memcpy (&aqm[1], qh->address, strlen (qh->address) + 1);
424 GNUNET_MQ_send (qh->ch->mq, env);
425}
426
427
428/**
429 * Send message to the transport service about queue @a qh
430 * updated.
431 *
432 * @param qh queue to add
433 */
434static void
435send_update_queue (struct GNUNET_TRANSPORT_QueueHandle *qh)
436{
437 struct GNUNET_MQ_Envelope *env;
438 struct GNUNET_TRANSPORT_UpdateQueueMessage *uqm;
439
440 if (NULL == qh->ch->mq)
441 return;
442 env = GNUNET_MQ_msg (uqm, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE);
443 uqm->qid = htonl (qh->queue_id);
444 uqm->receiver = qh->peer;
445 uqm->nt = htonl ((uint32_t) qh->nt);
446 uqm->mtu = htonl (qh->mtu);
447 uqm->q_len = GNUNET_htonll (qh->q_len);
448 uqm->priority = htonl (qh->priority);
449 uqm->cs = htonl ((uint32_t) qh->cs);
450 GNUNET_MQ_send (qh->ch->mq, env);
451}
452
453
454/**
455 * Send message to the transport service about queue @a qh
456 * being no longer available.
457 *
458 * @param qh queue to delete
459 */
460static void
461send_del_queue (struct GNUNET_TRANSPORT_QueueHandle *qh)
462{
463 struct GNUNET_MQ_Envelope *env;
464 struct GNUNET_TRANSPORT_DelQueueMessage *dqm;
465
466 if (NULL == qh->ch->mq)
467 return;
468 env = GNUNET_MQ_msg (dqm, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN);
469 dqm->qid = htonl (qh->queue_id);
470 dqm->receiver = qh->peer;
471 GNUNET_MQ_send (qh->ch->mq, env);
472}
473
474
475/**
476 * Disconnect from the transport service. Purges
477 * all flow control entries as we will no longer receive
478 * the ACKs. Purges the ack pending entries as the
479 * transport will no longer expect the confirmations.
480 *
481 * @param ch service to disconnect from
482 */
483static void
484disconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
485{
486 struct FlowControl *fcn;
487 struct AckPending *apn;
488
489 for (struct FlowControl *fc = ch->fc_head; NULL != fc; fc = fcn)
490 {
491 fcn = fc->next;
492 GNUNET_CONTAINER_DLL_remove (ch->fc_head, ch->fc_tail, fc);
493 fc->cb (fc->cb_cls, GNUNET_SYSERR);
494 GNUNET_free (fc);
495 }
496 for (struct AckPending *ap = ch->ap_head; NULL != ap; ap = apn)
497 {
498 apn = ap->next;
499 GNUNET_CONTAINER_DLL_remove (ch->ap_head, ch->ap_tail, ap);
500 GNUNET_free (ap);
501 }
502 if (NULL == ch->mq)
503 return;
504 GNUNET_MQ_destroy (ch->mq);
505 ch->mq = NULL;
506}
507
508
509/**
510 * Function called on MQ errors.
511 */
512static void
513error_handler (void *cls, enum GNUNET_MQ_Error error)
514{
515 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls;
516
517 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
518 "MQ failure %d, reconnecting to transport service.\n",
519 error);
520 disconnect (ch);
521 /* TODO: maybe do this with exponential backoff/delay */
522 reconnect (ch);
523}
524
525
526/**
527 * Transport service acknowledged a message we gave it
528 * (with flow control enabled). Tell the communicator.
529 *
530 * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *`
531 * @param incoming_ack the ack
532 */
533static void
534handle_incoming_ack (
535 void *cls,
536 const struct GNUNET_TRANSPORT_IncomingMessageAck *incoming_ack)
537{
538 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls;
539
540 for (struct FlowControl *fc = ch->fc_head; NULL != fc; fc = fc->next)
541 {
542 if ((fc->id == incoming_ack->fc_id) &&
543 (0 == memcmp (&fc->sender,
544 &incoming_ack->sender,
545 sizeof(struct GNUNET_PeerIdentity))))
546 {
547 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
548 "Done with message with flow control id %" PRIu64
549 " for sender %s from sender %s\n",
550 incoming_ack->fc_id,
551 GNUNET_i2s (&fc->sender),
552 GNUNET_i2s (&incoming_ack->sender));
553 GNUNET_CONTAINER_DLL_remove (ch->fc_head, ch->fc_tail, fc);
554 fc->cb (fc->cb_cls, GNUNET_OK);
555 GNUNET_free (fc);
556 return;
557 }
558 }
559 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
560 "Message with flow control id %" PRIu64
561 " from sender %s not found\n",
562 incoming_ack->fc_id,
563 GNUNET_i2s (&incoming_ack->sender));
564 GNUNET_break (0);
565 disconnect (ch);
566 /* TODO: maybe do this with exponential backoff/delay */
567 reconnect (ch);
568}
569
570
571/**
572 * Transport service wants us to create a queue. Check if @a cq
573 * is well-formed.
574 *
575 * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *`
576 * @param cq the queue creation request
577 * @return #GNUNET_OK if @a smt is well-formed
578 */
579static int
580check_create_queue (void *cls, const struct GNUNET_TRANSPORT_CreateQueue *cq)
581{
582 (void) cls;
583 GNUNET_MQ_check_zero_termination (cq);
584 return GNUNET_OK;
585}
586
587
588/**
589 * Transport service wants us to create a queue. Tell the communicator.
590 *
591 * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *`
592 * @param cq the queue creation request
593 */
594static void
595handle_create_queue (void *cls, const struct GNUNET_TRANSPORT_CreateQueue *cq)
596{
597 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls;
598 const char *addr = (const char *) &cq[1];
599 struct GNUNET_TRANSPORT_CreateQueueResponse *cqr;
600 struct GNUNET_MQ_Envelope *env;
601
602 if (GNUNET_OK != ch->mq_init (ch->mq_init_cls, &cq->receiver, addr))
603 {
604 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
605 "Address `%s' invalid for this communicator\n",
606 addr);
607 env = GNUNET_MQ_msg (cqr, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL);
608 }
609 else
610 {
611 env = GNUNET_MQ_msg (cqr, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK);
612 }
613 cqr->request_id = cq->request_id;
614 GNUNET_MQ_send (ch->mq, env);
615}
616
617
618/**
619 * Transport service wants us to send a message. Check if @a smt
620 * is well-formed.
621 *
622 * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *`
623 * @param smt the transmission request
624 * @return #GNUNET_OK if @a smt is well-formed
625 */
626static int
627check_send_msg (void *cls, const struct GNUNET_TRANSPORT_SendMessageTo *smt)
628{
629 (void) cls;
630 GNUNET_MQ_check_boxed_message (smt);
631 return GNUNET_OK;
632}
633
634
635/**
636 * Notify transport service about @a status of a message with
637 * @a mid sent to @a receiver.
638 *
639 * @param ch handle
640 * @param status #GNUNET_OK on success, #GNUNET_SYSERR on failure
641 * @param receiver which peer was the receiver
642 * @param mid message that the ack is about
643 */
644static void
645send_ack (struct GNUNET_TRANSPORT_CommunicatorHandle *ch,
646 int status,
647 const struct GNUNET_PeerIdentity *receiver,
648 uint64_t mid,
649 uint32_t qid)
650{
651 struct GNUNET_MQ_Envelope *env;
652 struct GNUNET_TRANSPORT_SendMessageToAck *ack;
653
654 env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK);
655 ack->status = htonl (status);
656 ack->mid = mid;
657 ack->qid = qid;
658 ack->receiver = *receiver;
659 GNUNET_MQ_send (ch->mq, env);
660}
661
662
663/**
664 * Message queue transmission by communicator was successful,
665 * notify transport service.
666 *
667 * @param cls an `struct AckPending *`
668 */
669static void
670send_ack_cb (void *cls)
671{
672 struct AckPending *ap = cls;
673 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = ap->ch;
674
675 GNUNET_CONTAINER_DLL_remove (ch->ap_head, ch->ap_tail, ap);
676 send_ack (ch, GNUNET_OK, &ap->receiver, ap->mid, ap->qid);
677 GNUNET_free (ap);
678}
679
680
681/**
682 * Transport service wants us to send a message. Tell the communicator.
683 *
684 * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *`
685 * @param smt the transmission request
686 */
687static void
688handle_send_msg (void *cls, const struct GNUNET_TRANSPORT_SendMessageTo *smt)
689{
690 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls;
691 const struct GNUNET_MessageHeader *mh;
692 struct GNUNET_MQ_Envelope *env;
693 struct AckPending *ap;
694 struct GNUNET_TRANSPORT_QueueHandle *qh;
695
696 for (qh = ch->queue_head; NULL != qh; qh = qh->next)
697 if ((qh->queue_id == ntohl (smt->qid)) &&
698 (0 == memcmp (&qh->peer,
699 &smt->receiver,
700 sizeof(struct GNUNET_PeerIdentity))))
701 break;
702 if (NULL == qh)
703 {
704 /* queue is already gone, tell transport this one failed */
705 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
706 "Transmission failed, queue no longer exists.\n");
707 send_ack (ch, GNUNET_NO, &smt->receiver, smt->mid, smt->qid);
708 return;
709 }
710 ap = GNUNET_new (struct AckPending);
711 ap->ch = ch;
712 ap->receiver = smt->receiver;
713 ap->mid = smt->mid;
714 ap->qid = smt->qid;
715 GNUNET_CONTAINER_DLL_insert (ch->ap_head, ch->ap_tail, ap);
716 mh = (const struct GNUNET_MessageHeader *) &smt[1];
717 env = GNUNET_MQ_msg_copy (mh);
718 GNUNET_MQ_notify_sent (env, &send_ack_cb, ap);
719 GNUNET_MQ_send (qh->mq, env);
720}
721
722
723/**
724 * Transport service gives us backchannel message. Check if @a bi
725 * is well-formed.
726 *
727 * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *`
728 * @param bi the backchannel message
729 * @return #GNUNET_OK if @a smt is well-formed
730 */
731static int
732check_backchannel_incoming (
733 void *cls,
734 const struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *bi)
735{
736 (void) cls;
737 GNUNET_MQ_check_boxed_message (bi);
738 return GNUNET_OK;
739}
740
741
742/**
743 * Transport service gives us backchannel message. Handle it.
744 *
745 * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *`
746 * @param bi the backchannel message
747 */
748static void
749handle_backchannel_incoming (
750 void *cls,
751 const struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *bi)
752{
753 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls;
754 if (NULL != ch->notify_cb)
755 ch->notify_cb (ch->notify_cb_cls,
756 &bi->pid,
757 (const struct GNUNET_MessageHeader *) &bi[1]);
758 else
759 GNUNET_log (
760 GNUNET_ERROR_TYPE_INFO,
761 _ ("Dropped backchanel message: handler not provided by communicator\n"));
762}
763
764
765/**
766 * (re)connect our communicator to the transport service
767 *
768 * @param ch handle to reconnect
769 */
770static void
771reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
772{
773 struct GNUNET_MQ_MessageHandler handlers[] =
774 { GNUNET_MQ_hd_fixed_size (incoming_ack,
775 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK,
776 struct GNUNET_TRANSPORT_IncomingMessageAck,
777 ch),
778 GNUNET_MQ_hd_var_size (create_queue,
779 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE,
780 struct GNUNET_TRANSPORT_CreateQueue,
781 ch),
782 GNUNET_MQ_hd_var_size (send_msg,
783 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG,
784 struct GNUNET_TRANSPORT_SendMessageTo,
785 ch),
786 GNUNET_MQ_hd_var_size (
787 backchannel_incoming,
788 GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING,
789 struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming,
790 ch),
791 GNUNET_MQ_handler_end () };
792 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam;
793 struct GNUNET_MQ_Envelope *env;
794
795 ch->mq =
796 GNUNET_CLIENT_connect (ch->cfg, "transport", handlers, &error_handler, ch);
797 if (NULL == ch->mq)
798 return;
799 env = GNUNET_MQ_msg_extra (cam,
800 strlen (ch->addr_prefix) + 1,
801 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR);
802 cam->cc = htonl ((uint32_t) ch->cc);
803 memcpy (&cam[1], ch->addr_prefix, strlen (ch->addr_prefix) + 1);
804 GNUNET_MQ_send (ch->mq, env);
805 for (struct GNUNET_TRANSPORT_AddressIdentifier *ai = ch->ai_head; NULL != ai;
806 ai = ai->next)
807 send_add_address (ai);
808 for (struct GNUNET_TRANSPORT_QueueHandle *qh = ch->queue_head; NULL != qh;
809 qh = qh->next)
810 send_add_queue (qh);
811}
812
813
814struct GNUNET_TRANSPORT_CommunicatorHandle *
815GNUNET_TRANSPORT_communicator_connect (
816 const struct GNUNET_CONFIGURATION_Handle *cfg,
817 const char *config_section,
818 const char *addr_prefix,
819 enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc,
820 GNUNET_TRANSPORT_CommunicatorMqInit mq_init,
821 void *mq_init_cls,
822 GNUNET_TRANSPORT_CommunicatorNotify notify_cb,
823 void *notify_cb_cls)
824{
825 struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
826
827 ch = GNUNET_new (struct GNUNET_TRANSPORT_CommunicatorHandle);
828 ch->cfg = cfg;
829 ch->config_section = config_section;
830 ch->addr_prefix = addr_prefix;
831 ch->mq_init = mq_init;
832 ch->mq_init_cls = mq_init_cls;
833 ch->notify_cb = notify_cb;
834 ch->notify_cb_cls = notify_cb_cls;
835 ch->cc = cc;
836 reconnect (ch);
837 if (GNUNET_OK !=
838 GNUNET_CONFIGURATION_get_value_number (cfg,
839 config_section,
840 "MAX_QUEUE_LENGTH",
841 &ch->max_queue_length))
842 ch->max_queue_length = DEFAULT_MAX_QUEUE_LENGTH;
843 if (NULL == ch->mq)
844 {
845 GNUNET_free (ch);
846 return NULL;
847 }
848 return ch;
849}
850
851
852/**
853 * Disconnect from the transport service.
854 *
855 * @param ch handle returned from connect
856 */
857void
858GNUNET_TRANSPORT_communicator_disconnect (
859 struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
860{
861 disconnect (ch);
862 while (NULL != ch->ai_head)
863 {
864 GNUNET_break (0); /* communicator forgot to remove address, warn! */
865 GNUNET_TRANSPORT_communicator_address_remove (ch->ai_head);
866 }
867 GNUNET_free (ch);
868}
869
870
871/* ************************* Receiving *************************** */
872
873
874int
875GNUNET_TRANSPORT_communicator_receive (
876 struct GNUNET_TRANSPORT_CommunicatorHandle *ch,
877 const struct GNUNET_PeerIdentity *sender,
878 const struct GNUNET_MessageHeader *msg,
879 struct GNUNET_TIME_Relative expected_addr_validity,
880 GNUNET_TRANSPORT_MessageCompletedCallback cb,
881 void *cb_cls)
882{
883 struct GNUNET_MQ_Envelope *env;
884 struct GNUNET_TRANSPORT_IncomingMessage *im;
885 uint16_t msize;
886
887
888 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
889 "communicator receive\n");
890
891 if (NULL == ch->mq)
892 return GNUNET_SYSERR;
893 if ((NULL == cb) && (GNUNET_MQ_get_length (ch->mq) >= ch->max_queue_length))
894 {
895 GNUNET_log (
896 GNUNET_ERROR_TYPE_WARNING,
897 "Dropping message: transport is too slow, queue length %llu exceeded\n",
898 ch->max_queue_length);
899 return GNUNET_NO;
900 }
901
902 msize = ntohs (msg->size);
903 env =
904 GNUNET_MQ_msg_extra (im, msize, GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG);
905 if (NULL == env)
906 {
907 GNUNET_break (0);
908 return GNUNET_SYSERR;
909 }
910 im->expected_address_validity =
911 GNUNET_TIME_relative_hton (expected_addr_validity);
912 im->sender = *sender;
913 // FIXME: this is expensive, would be better if we would
914 // re-design the API to allow us to create the envelope first,
915 // and then have the application fill in the body so we do
916 // not have to memcpy()
917 memcpy (&im[1], msg, msize);
918 im->fc_on = htonl (GNUNET_NO);
919 if (NULL != cb)
920 {
921 struct FlowControl *fc;
922
923 im->fc_on = htonl (GNUNET_YES);
924 im->fc_id = ch->fc_gen++;
925 fc = GNUNET_new (struct FlowControl);
926 fc->sender = *sender;
927 fc->id = im->fc_id;
928 fc->cb = cb;
929 fc->cb_cls = cb_cls;
930 GNUNET_CONTAINER_DLL_insert (ch->fc_head, ch->fc_tail, fc);
931 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
932 "Created flow control id %" PRIu64 " for sender %s\n",
933 fc->id,
934 GNUNET_i2s (&fc->sender));
935 }
936 GNUNET_MQ_send (ch->mq, env);
937 return GNUNET_OK;
938}
939
940
941/* ************************* Discovery *************************** */
942
943
944struct GNUNET_TRANSPORT_QueueHandle *
945GNUNET_TRANSPORT_communicator_mq_add (
946 struct GNUNET_TRANSPORT_CommunicatorHandle *ch,
947 const struct GNUNET_PeerIdentity *peer,
948 const char *address,
949 uint32_t mtu,
950 uint64_t q_len,
951 uint32_t priority,
952 enum GNUNET_NetworkType nt,
953 enum GNUNET_TRANSPORT_ConnectionStatus cs,
954 struct GNUNET_MQ_Handle *mq)
955{
956 struct GNUNET_TRANSPORT_QueueHandle *qh;
957
958 // Do not notify the service if there is no intial capacity.
959 GNUNET_assert (0 < q_len);
960
961 qh = GNUNET_new (struct GNUNET_TRANSPORT_QueueHandle);
962 qh->ch = ch;
963 qh->peer = *peer;
964 qh->address = GNUNET_strdup (address);
965 qh->nt = nt;
966 qh->mtu = mtu;
967 qh->q_len = q_len;
968 qh->priority = priority;
969 qh->cs = cs;
970 qh->mq = mq;
971 qh->queue_id = ch->queue_gen++;
972 GNUNET_CONTAINER_DLL_insert (ch->queue_head, ch->queue_tail, qh);
973 send_add_queue (qh);
974 return qh;
975}
976
977
978void
979GNUNET_TRANSPORT_communicator_mq_update (
980 struct GNUNET_TRANSPORT_CommunicatorHandle *ch,
981 const struct GNUNET_TRANSPORT_QueueHandle *u_qh,
982 uint64_t q_len,
983 uint32_t priority)
984{
985 struct GNUNET_TRANSPORT_QueueHandle *qh;
986
987 for (qh = ch->queue_head; NULL != qh; qh = qh->next)
988 {
989 if (u_qh == qh)
990 break;
991 }
992 GNUNET_assert (NULL != qh);
993 qh->q_len = q_len;
994 qh->priority = priority;
995 send_update_queue (qh);
996}
997
998
999/**
1000 * Notify transport service that an MQ became unavailable due to a
1001 * disconnect or timeout.
1002 *
1003 * @param qh handle for the queue that must be invalidated
1004 */
1005void
1006GNUNET_TRANSPORT_communicator_mq_del (struct GNUNET_TRANSPORT_QueueHandle *qh)
1007{
1008 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = qh->ch;
1009
1010 send_del_queue (qh);
1011 GNUNET_CONTAINER_DLL_remove (ch->queue_head, ch->queue_tail, qh);
1012 GNUNET_MQ_destroy (qh->mq);
1013 GNUNET_free (qh->address);
1014 GNUNET_free (qh);
1015}
1016
1017
1018/**
1019 * Notify transport service about an address that this communicator
1020 * provides for this peer.
1021 *
1022 * @param ch connection to transport service
1023 * @param address our address in human-readable format, 0-terminated, UTF-8
1024 * @param nt which network type does the address belong to?
1025 * @param expiration when does the communicator forsee this address expiring?
1026 */
1027struct GNUNET_TRANSPORT_AddressIdentifier *
1028GNUNET_TRANSPORT_communicator_address_add (
1029 struct GNUNET_TRANSPORT_CommunicatorHandle *ch,
1030 const char *address,
1031 enum GNUNET_NetworkType nt,
1032 struct GNUNET_TIME_Relative expiration)
1033{
1034 struct GNUNET_TRANSPORT_AddressIdentifier *ai;
1035
1036 ai = GNUNET_new (struct GNUNET_TRANSPORT_AddressIdentifier);
1037 ai->ch = ch;
1038 ai->address = GNUNET_strdup (address);
1039 ai->nt = nt;
1040 ai->expiration = expiration;
1041 ai->aid = ch->aid_gen++;
1042 GNUNET_CONTAINER_DLL_insert (ch->ai_head, ch->ai_tail, ai);
1043 send_add_address (ai);
1044 return ai;
1045}
1046
1047
1048/**
1049 * Notify transport service about an address that this communicator no
1050 * longer provides for this peer.
1051 *
1052 * @param ai address that is no longer provided
1053 */
1054void
1055GNUNET_TRANSPORT_communicator_address_remove (
1056 struct GNUNET_TRANSPORT_AddressIdentifier *ai)
1057{
1058 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = ai->ch;
1059
1060 send_del_address (ai);
1061 GNUNET_CONTAINER_DLL_remove (ch->ai_head, ch->ai_tail, ai);
1062 GNUNET_free (ai->address);
1063 GNUNET_free (ai);
1064 ai = NULL;
1065}
1066
1067
1068/**
1069 * Notify transport service that this communicator no longer provides all its addresses for this peer.
1070 *
1071 * @param ch The communicator handle.
1072 */
1073void
1074GNUNET_TRANSPORT_communicator_address_remove_all (
1075 struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
1076{
1077 struct GNUNET_TRANSPORT_AddressIdentifier *ai = ch->ai_head;
1078 while (NULL != ai)
1079 {
1080 struct GNUNET_TRANSPORT_AddressIdentifier *ai_next = ai->next;
1081 GNUNET_TRANSPORT_communicator_address_remove (ai);
1082 ai = ai_next;
1083 }
1084}
1085
1086
1087/* ************************* Backchannel *************************** */
1088
1089
1090void
1091GNUNET_TRANSPORT_communicator_notify (
1092 struct GNUNET_TRANSPORT_CommunicatorHandle *ch,
1093 const struct GNUNET_PeerIdentity *pid,
1094 const char *comm,
1095 const struct GNUNET_MessageHeader *header)
1096{
1097 struct GNUNET_MQ_Envelope *env;
1098 struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb;
1099 size_t slen = strlen (comm) + 1;
1100 uint16_t mlen = ntohs (header->size);
1101
1102 GNUNET_assert (mlen + slen + sizeof(*cb) < UINT16_MAX);
1103 env =
1104 GNUNET_MQ_msg_extra (cb,
1105 slen + mlen,
1106 GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL);
1107 cb->pid = *pid;
1108 memcpy (&cb[1], header, mlen);
1109 memcpy (((char *) &cb[1]) + mlen, comm, slen);
1110 GNUNET_MQ_send (ch->mq, env);
1111}
1112
1113
1114/* end of transport_api2_communication.c */
diff --git a/src/transport/transport_api2_core.c b/src/transport/transport_api2_core.c
deleted file mode 100644
index 0d2a0ac7f..000000000
--- a/src/transport/transport_api2_core.c
+++ /dev/null
@@ -1,826 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016, 2018 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 transport/transport_api_core.c
23 * @brief library to access the transport service for message exchange
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_constants.h"
29#include "gnunet_arm_service.h"
30#include "gnunet_hello_lib.h"
31#include "gnunet_protocols.h"
32#include "gnunet_transport_core_service.h"
33#include "transport.h"
34
35#define LOG(kind, ...) GNUNET_log_from (kind, "transport-api-core", __VA_ARGS__)
36
37/**
38 * How large to start with for the hashmap of neighbours.
39 */
40#define STARTING_NEIGHBOURS_SIZE 16
41
42/**
43 * Window size. How many messages to the same target do we pass
44 * to TRANSPORT without a SEND_OK in between? Small values limit
45 * thoughput, large values will increase latency.
46 *
47 * FIXME-OPTIMIZE: find out what good values are experimentally,
48 * maybe set adaptively (i.e. to observed available bandwidth).
49 */
50#define SEND_WINDOW_SIZE 4
51
52
53/**
54 * Entry in hash table of all of our current (connected) neighbours.
55 */
56struct Neighbour
57{
58 /**
59 * Identity of this neighbour.
60 */
61 struct GNUNET_PeerIdentity id;
62
63 /**
64 * Overall transport handle.
65 */
66 struct GNUNET_TRANSPORT_CoreHandle *h;
67
68 /**
69 * Active message queue for the peer.
70 */
71 struct GNUNET_MQ_Handle *mq;
72
73 /**
74 * Envelope with the message we are currently transmitting (or NULL).
75 */
76 struct GNUNET_MQ_Envelope *env;
77
78 /**
79 * Closure for @e mq handlers.
80 */
81 void *handlers_cls;
82
83 /**
84 * How many messages can we still send to this peer before we should
85 * throttle?
86 */
87 unsigned int ready_window;
88
89 /**
90 * Used to indicate our status if @e env is non-NULL. Set to
91 * #GNUNET_YES if we did pass a message to the MQ and are waiting
92 * for the call to #notify_send_done(). Set to #GNUNET_NO if the @e
93 * ready_window is 0 and @e env is waiting for a
94 * #GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK?
95 */
96 int16_t awaiting_done;
97
98 /**
99 * Size of the message in @e env.
100 */
101 uint16_t env_size;
102};
103
104
105/**
106 * Handle for the transport service (includes all of the
107 * state for the transport service).
108 */
109struct GNUNET_TRANSPORT_CoreHandle
110{
111 /**
112 * Closure for the callbacks.
113 */
114 void *cls;
115
116 /**
117 * Functions to call for received data (template for
118 * new message queues).
119 */
120 struct GNUNET_MQ_MessageHandler *handlers;
121
122 /**
123 * function to call on connect events
124 */
125 GNUNET_TRANSPORT_NotifyConnect nc_cb;
126
127 /**
128 * function to call on disconnect events
129 */
130 GNUNET_TRANSPORT_NotifyDisconnect nd_cb;
131
132 /**
133 * My client connection to the transport service.
134 */
135 struct GNUNET_MQ_Handle *mq;
136
137 /**
138 * My configuration.
139 */
140 const struct GNUNET_CONFIGURATION_Handle *cfg;
141
142 /**
143 * Hash map of the current connected neighbours of this peer.
144 * Maps peer identities to `struct Neighbour` entries.
145 */
146 struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
147
148 /**
149 * Peer identity as assumed by this process, or all zeros.
150 */
151 struct GNUNET_PeerIdentity self;
152
153 /**
154 * ID of the task trying to reconnect to the service.
155 */
156 struct GNUNET_SCHEDULER_Task *reconnect_task;
157
158 /**
159 * Delay until we try to reconnect.
160 */
161 struct GNUNET_TIME_Relative reconnect_delay;
162
163 /**
164 * Should we check that @e self matches what the service thinks?
165 * (if #GNUNET_NO, then @e self is all zeros!).
166 */
167 int check_self;
168};
169
170
171/**
172 * Function that will schedule the job that will try
173 * to connect us again to the client.
174 *
175 * @param h transport service to reconnect
176 */
177static void
178disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_CoreHandle *h);
179
180
181/**
182 * Get the neighbour list entry for the given peer
183 *
184 * @param h our context
185 * @param peer peer to look up
186 * @return NULL if no such peer entry exists
187 */
188static struct Neighbour *
189neighbour_find (struct GNUNET_TRANSPORT_CoreHandle *h,
190 const struct GNUNET_PeerIdentity *peer)
191{
192 return GNUNET_CONTAINER_multipeermap_get (h->neighbours, peer);
193}
194
195
196/**
197 * Iterator over hash map entries, for deleting state of a neighbour.
198 *
199 * @param cls the `struct GNUNET_TRANSPORT_CoreHandle *`
200 * @param key peer identity
201 * @param value value in the hash map, the neighbour entry to delete
202 * @return #GNUNET_YES if we should continue to
203 * iterate,
204 * #GNUNET_NO if not.
205 */
206static int
207neighbour_delete (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
208{
209 struct GNUNET_TRANSPORT_CoreHandle *handle = cls;
210 struct Neighbour *n = value;
211
212 LOG (GNUNET_ERROR_TYPE_DEBUG,
213 "Dropping entry for neighbour `%s'.\n",
214 GNUNET_i2s (key));
215 if (NULL != handle->nd_cb)
216 handle->nd_cb (handle->cls, &n->id, n->handlers_cls);
217 if (NULL != n->env)
218 {
219 GNUNET_MQ_send_cancel (n->env);
220 n->env = NULL;
221 }
222 GNUNET_MQ_destroy (n->mq);
223 GNUNET_assert (NULL == n->mq);
224 GNUNET_assert (
225 GNUNET_YES ==
226 GNUNET_CONTAINER_multipeermap_remove (handle->neighbours, key, n));
227 GNUNET_free (n);
228 return GNUNET_YES;
229}
230
231
232/**
233 * Generic error handler, called with the appropriate
234 * error code and the same closure specified at the creation of
235 * the message queue.
236 * Not every message queue implementation supports an error handler.
237 *
238 * @param cls closure with the `struct GNUNET_TRANSPORT_CoreHandle *`
239 * @param error error code
240 */
241static void
242mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
243{
244 struct GNUNET_TRANSPORT_CoreHandle *h = cls;
245
246 LOG (GNUNET_ERROR_TYPE_DEBUG,
247 "Error %u received from transport service, disconnecting temporarily.\n",
248 error);
249 disconnect_and_schedule_reconnect (h);
250}
251
252
253/**
254 * A message from the handler's message queue to a neighbour was
255 * transmitted. Now trigger (possibly delayed) notification of the
256 * neighbour's message queue that we are done and thus ready for
257 * the next message. Note that the MQ being ready is independent
258 * of the send window, as we may queue many messages and simply
259 * not pass them to TRANSPORT if the send window is insufficient.
260 *
261 * @param cls the `struct Neighbour` where the message was sent
262 */
263static void
264notify_send_done (void *cls)
265{
266 struct Neighbour *n = cls;
267
268 n->awaiting_done = GNUNET_NO;
269 n->env = NULL;
270 if (0 < n->ready_window)
271 GNUNET_MQ_impl_send_continue (n->mq);
272}
273
274
275/**
276 * We have an envelope waiting for transmission at @a n, and
277 * our transmission window is positive. Perform the transmission.
278 *
279 * @param n neighbour to perform transmission for
280 */
281static void
282do_send (struct Neighbour *n)
283{
284 GNUNET_assert (0 < n->ready_window);
285 GNUNET_assert (NULL != n->env);
286 n->ready_window--;
287 n->awaiting_done = GNUNET_YES;
288 GNUNET_MQ_notify_sent (n->env, &notify_send_done, n);
289 GNUNET_MQ_send (n->h->mq, n->env);
290 LOG (GNUNET_ERROR_TYPE_DEBUG,
291 "Passed message of type %u for neighbour `%s' to TRANSPORT. ready_window %u\n",
292 ntohs (GNUNET_MQ_env_get_msg (n->env)->type),
293 GNUNET_i2s (&n->id),
294 n->ready_window);
295}
296
297
298/**
299 * Implement sending functionality of a message queue.
300 * Called one message at a time. Should send the @a msg
301 * to the transport service and then notify the queue
302 * once we are ready for the next one.
303 *
304 * @param mq the message queue
305 * @param msg the message to send
306 * @param impl_state state of the implementation
307 */
308static void
309mq_send_impl (struct GNUNET_MQ_Handle *mq,
310 const struct GNUNET_MessageHeader *msg,
311 void *impl_state)
312{
313 struct Neighbour *n = impl_state;
314 struct OutboundMessage *obm;
315 uint16_t msize;
316
317 msize = ntohs (msg->size);
318 if (msize >= GNUNET_MAX_MESSAGE_SIZE - sizeof(*obm))
319 {
320 GNUNET_break (0);
321 GNUNET_MQ_impl_send_continue (mq);
322 return;
323 }
324 LOG (GNUNET_ERROR_TYPE_DEBUG,
325 "CORE requested transmission of message of type %u to neighbour `%s'.\n",
326 ntohs (msg->type),
327 GNUNET_i2s (&n->id));
328
329 GNUNET_assert (NULL == n->env);
330 n->env =
331 GNUNET_MQ_msg_nested_mh (obm, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, msg);
332 n->env_size = ntohs (msg->size);
333 {
334 struct GNUNET_MQ_Envelope *env;
335
336 env = GNUNET_MQ_get_current_envelope (mq);
337 obm->priority = htonl ((uint32_t) GNUNET_MQ_env_get_options (env));
338 }
339 obm->peer = n->id;
340 if (0 == n->ready_window)
341 {
342 LOG (GNUNET_ERROR_TYPE_DEBUG,
343 "Flow control delays transmission to CORE until we see SEND_OK.\n");
344 return; /* can't send yet, need to wait for SEND_OK */
345 }
346 do_send (n);
347}
348
349
350/**
351 * Handle destruction of a message queue. Implementations must not
352 * free @a mq, but should take care of @a impl_state.
353 *
354 * @param mq the message queue to destroy
355 * @param impl_state state of the implementation
356 */
357static void
358mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
359{
360 struct Neighbour *n = impl_state;
361
362 GNUNET_assert (mq == n->mq);
363 n->mq = NULL;
364}
365
366
367/**
368 * Implementation function that cancels the currently sent message.
369 * Should basically undo whatever #mq_send_impl() did.
370 *
371 * @param mq message queue
372 * @param impl_state state specific to the implementation
373 */
374static void
375mq_cancel_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
376{
377 struct Neighbour *n = impl_state;
378
379 n->ready_window++;
380 if (GNUNET_YES == n->awaiting_done)
381 {
382 GNUNET_MQ_send_cancel (n->env);
383 n->env = NULL;
384 n->awaiting_done = GNUNET_NO;
385 }
386 else
387 {
388 GNUNET_assert (0 == n->ready_window);
389 n->env = NULL;
390 }
391}
392
393
394/**
395 * We had an error processing a message we forwarded from a peer to
396 * the CORE service. We should just complain about it but otherwise
397 * continue processing.
398 *
399 * @param cls closure
400 * @param error error code
401 */
402static void
403peer_mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
404{
405 struct Neighbour *n = cls;
406
407 if (GNUNET_MQ_ERROR_MALFORMED == error)
408 GNUNET_break_op (0);
409 //TODO Look into bug #7887
410
411 GNUNET_TRANSPORT_core_receive_continue (n->h, &n->id);
412}
413
414
415/**
416 * Function we use for handling incoming connect messages.
417 *
418 * @param cls closure, a `struct GNUNET_TRANSPORT_Handle *`
419 * @param cim message received
420 */
421static void
422handle_connect (void *cls, const struct ConnectInfoMessage *cim)
423{
424 struct GNUNET_TRANSPORT_CoreHandle *h = cls;
425 struct Neighbour *n;
426
427 LOG (GNUNET_ERROR_TYPE_DEBUG,
428 "Receiving CONNECT message for `%s'\n",
429 GNUNET_i2s (&cim->id));
430 n = neighbour_find (h, &cim->id);
431 if (NULL != n)
432 {
433 GNUNET_break (0);
434 disconnect_and_schedule_reconnect (h);
435 return;
436 }
437 n = GNUNET_new (struct Neighbour);
438 n->id = cim->id;
439 n->h = h;
440 n->ready_window = SEND_WINDOW_SIZE;
441 GNUNET_assert (GNUNET_OK ==
442 GNUNET_CONTAINER_multipeermap_put (
443 h->neighbours,
444 &n->id,
445 n,
446 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
447
448 n->mq = GNUNET_MQ_queue_for_callbacks (&mq_send_impl,
449 &mq_destroy_impl,
450 &mq_cancel_impl,
451 n,
452 h->handlers,
453 &peer_mq_error_handler,
454 n);
455 if (NULL != h->nc_cb)
456 {
457 n->handlers_cls = h->nc_cb (h->cls, &n->id, n->mq);
458 GNUNET_MQ_set_handlers_closure (n->mq, n->handlers_cls);
459 }
460}
461
462
463/**
464 * Function we use for handling incoming disconnect messages.
465 *
466 * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *`
467 * @param dim message received
468 */
469static void
470handle_disconnect (void *cls, const struct DisconnectInfoMessage *dim)
471{
472 struct GNUNET_TRANSPORT_CoreHandle *h = cls;
473 struct Neighbour *n;
474
475 GNUNET_break (ntohl (dim->reserved) == 0);
476 LOG (GNUNET_ERROR_TYPE_DEBUG,
477 "Receiving DISCONNECT message for `%s'.\n",
478 GNUNET_i2s (&dim->peer));
479 n = neighbour_find (h, &dim->peer);
480 if (NULL == n)
481 {
482 GNUNET_break (0);
483 disconnect_and_schedule_reconnect (h);
484 return;
485 }
486 GNUNET_assert (GNUNET_YES == neighbour_delete (h, &dim->peer, n));
487}
488
489
490/**
491 * Function we use for handling incoming send-ok messages.
492 *
493 * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *`
494 * @param okm message received
495 */
496static void
497handle_send_ok (void *cls, const struct SendOkMessage *okm)
498{
499 struct GNUNET_TRANSPORT_CoreHandle *h = cls;
500 struct Neighbour *n;
501
502 LOG (GNUNET_ERROR_TYPE_DEBUG,
503 "Receiving SEND_OK message for transmission to %s\n",
504 GNUNET_i2s (&okm->peer));
505
506 n = neighbour_find (h, &okm->peer);
507
508 if (NULL == n)
509 {
510 /* We should never get a 'SEND_OK' for a peer that we are not
511 connected to */
512 GNUNET_break (0);
513 disconnect_and_schedule_reconnect (h);
514 return;
515 }
516
517 if ((GNUNET_NO == n->awaiting_done) &&
518 (NULL != n->env) &&
519 (0 == n->ready_window))
520 {
521 n->ready_window++;
522 do_send (n);
523 return;
524 }
525 else if ((GNUNET_NO == n->awaiting_done) &&
526 (0 == n->ready_window))
527 {
528 n->ready_window++;
529 GNUNET_MQ_impl_send_continue (n->mq);
530 return;
531 }
532 n->ready_window++;
533}
534
535
536/**
537 * Function we use for checking incoming "inbound" messages.
538 *
539 * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *`
540 * @param im message received
541 */
542static int
543check_recv (void *cls, const struct InboundMessage *im)
544{
545 const struct GNUNET_MessageHeader *imm;
546 uint16_t size;
547
548 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
549 "check_recv\n");
550 size = ntohs (im->header.size) - sizeof(*im);
551 if (size < sizeof(struct GNUNET_MessageHeader))
552 {
553 GNUNET_break (0);
554 return GNUNET_SYSERR;
555 }
556 imm = (const struct GNUNET_MessageHeader *) &im[1];
557 if (ntohs (imm->size) != size)
558 {
559 GNUNET_break (0);
560 return GNUNET_SYSERR;
561 }
562 return GNUNET_OK;
563}
564
565
566/**
567 * Function we use for handling incoming messages.
568 *
569 * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *`
570 * @param im message received
571 */
572static void
573handle_recv (void *cls, const struct InboundMessage *im)
574{
575 struct GNUNET_TRANSPORT_CoreHandle *h = cls;
576 const struct GNUNET_MessageHeader *imm =
577 (const struct GNUNET_MessageHeader *) &im[1];
578 struct Neighbour *n;
579
580 LOG (GNUNET_ERROR_TYPE_DEBUG,
581 "Received message of type %u with %u bytes from `%s'.\n",
582 (unsigned int) ntohs (imm->type),
583 (unsigned int) ntohs (imm->size),
584 GNUNET_i2s (&im->peer));
585 n = neighbour_find (h, &im->peer);
586 if (NULL == n)
587 {
588 GNUNET_break (0);
589 disconnect_and_schedule_reconnect (h);
590 return;
591 }
592 GNUNET_MQ_inject_message (n->mq, imm);
593}
594
595
596/**
597 * Try again to connect to transport service.
598 *
599 * @param cls the handle to the transport service
600 */
601static void
602reconnect (void *cls)
603{
604 struct GNUNET_TRANSPORT_CoreHandle *h = cls;
605 struct GNUNET_MQ_MessageHandler handlers[] =
606 { GNUNET_MQ_hd_fixed_size (connect,
607 GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT,
608 struct ConnectInfoMessage,
609 h),
610 GNUNET_MQ_hd_fixed_size (disconnect,
611 GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT,
612 struct DisconnectInfoMessage,
613 h),
614 GNUNET_MQ_hd_fixed_size (send_ok,
615 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK,
616 struct SendOkMessage,
617 h),
618 GNUNET_MQ_hd_var_size (recv,
619 GNUNET_MESSAGE_TYPE_TRANSPORT_RECV,
620 struct InboundMessage,
621 h),
622 GNUNET_MQ_handler_end () };
623 struct GNUNET_MQ_Envelope *env;
624 struct StartMessage *s;
625 uint32_t options;
626
627 h->reconnect_task = NULL;
628 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to transport service.\n");
629 GNUNET_assert (NULL == h->mq);
630 h->mq =
631 GNUNET_CLIENT_connect (h->cfg, "transport", handlers, &mq_error_handler, h);
632 if (NULL == h->mq)
633 return;
634 env = GNUNET_MQ_msg (s, GNUNET_MESSAGE_TYPE_TRANSPORT_START);
635 options = 0;
636 if (h->check_self)
637 options |= 1;
638 if (NULL != h->handlers)
639 options |= 2;
640 s->options = htonl (options);
641 s->self = h->self;
642 GNUNET_MQ_send (h->mq, env);
643}
644
645
646/**
647 * Disconnect from the transport service.
648 *
649 * @param h transport service to reconnect
650 */
651static void
652disconnect (struct GNUNET_TRANSPORT_CoreHandle *h)
653{
654 GNUNET_CONTAINER_multipeermap_iterate (h->neighbours, &neighbour_delete, h);
655 if (NULL != h->mq)
656 {
657 GNUNET_MQ_destroy (h->mq);
658 h->mq = NULL;
659 }
660}
661
662
663/**
664 * Function that will schedule the job that will try
665 * to connect us again to the client.
666 *
667 * @param h transport service to reconnect
668 */
669static void
670disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_CoreHandle *h)
671{
672 GNUNET_assert (NULL == h->reconnect_task);
673 disconnect (h);
674 LOG (GNUNET_ERROR_TYPE_DEBUG,
675 "Scheduling task to reconnect to transport service in %s.\n",
676 GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay, GNUNET_YES));
677 h->reconnect_task =
678 GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h);
679 h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
680}
681
682
683/**
684 * Checks if a given peer is connected to us and get the message queue.
685 *
686 * @param handle connection to transport service
687 * @param peer the peer to check
688 * @return NULL if disconnected, otherwise message queue for @a peer
689 */
690struct GNUNET_MQ_Handle *
691GNUNET_TRANSPORT_core_get_mq (struct GNUNET_TRANSPORT_CoreHandle *handle,
692 const struct GNUNET_PeerIdentity *peer)
693{
694 struct Neighbour *n;
695
696 n = neighbour_find (handle, peer);
697 if (NULL == n)
698 return NULL;
699 return n->mq;
700}
701
702
703/**
704 * Notification from the CORE service to the TRANSPORT service
705 * that the CORE service has finished processing a message from
706 * TRANSPORT (via the @code{handlers} of #GNUNET_TRANSPORT_core_connect())
707 * and that it is thus now OK for TRANSPORT to send more messages
708 * for @a pid.
709 *
710 * Used to provide flow control, this is our equivalent to
711 * #GNUNET_SERVICE_client_continue() of an ordinary service.
712 *
713 * Note that due to the use of a window, TRANSPORT may send multiple
714 * messages destined for the same peer even without an intermediate
715 * call to this function. However, CORE must still call this function
716 * once per message received, as otherwise eventually the window will
717 * be full and TRANSPORT will stop providing messages to CORE for @a
718 * pid.
719 *
720 * @param ch core handle
721 * @param pid which peer was the message from that was fully processed by CORE
722 */
723void
724GNUNET_TRANSPORT_core_receive_continue (struct GNUNET_TRANSPORT_CoreHandle *ch,
725 const struct GNUNET_PeerIdentity *pid)
726{
727 struct GNUNET_MQ_Envelope *env;
728 struct RecvOkMessage *rok;
729
730 LOG (GNUNET_ERROR_TYPE_DEBUG,
731 "Message for %s finished CORE processing, sending RECV_OK.\n",
732 GNUNET_i2s (pid));
733 if (NULL == ch->mq)
734 return;
735 env = GNUNET_MQ_msg (rok, GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK);
736 rok->increase_window_delta = htonl (1);
737 rok->peer = *pid;
738 GNUNET_MQ_send (ch->mq, env);
739}
740
741
742/**
743 * Connect to the transport service. Note that the connection may
744 * complete (or fail) asynchronously.
745 *
746 * @param cfg configuration to use
747 * @param self our own identity (API should check that it matches
748 * the identity found by transport), or NULL (no check)
749 * @param cls closure for the callbacks
750 * @param rec receive function to call
751 * @param nc function to call on connect events
752 * @param nd function to call on disconnect events
753 * @return NULL on error
754 */
755struct GNUNET_TRANSPORT_CoreHandle *
756GNUNET_TRANSPORT_core_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
757 const struct GNUNET_PeerIdentity *self,
758 const struct GNUNET_MQ_MessageHandler *handlers,
759 void *cls,
760 GNUNET_TRANSPORT_NotifyConnect nc,
761 GNUNET_TRANSPORT_NotifyDisconnect nd)
762{
763 struct GNUNET_TRANSPORT_CoreHandle *h;
764 unsigned int i;
765
766 h = GNUNET_new (struct GNUNET_TRANSPORT_CoreHandle);
767 if (NULL != self)
768 {
769 h->self = *self;
770 h->check_self = GNUNET_YES;
771 }
772 h->cfg = cfg;
773 h->cls = cls;
774 h->nc_cb = nc;
775 h->nd_cb = nd;
776 h->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
777 if (NULL != handlers)
778 {
779 for (i = 0; NULL != handlers[i].cb; i++)
780 ;
781 h->handlers = GNUNET_new_array (i + 1, struct GNUNET_MQ_MessageHandler);
782 GNUNET_memcpy (h->handlers,
783 handlers,
784 i * sizeof(struct GNUNET_MQ_MessageHandler));
785 }
786 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to transport service\n");
787 reconnect (h);
788 if (NULL == h->mq)
789 {
790 GNUNET_free (h->handlers);
791 GNUNET_free (h);
792 return NULL;
793 }
794 h->neighbours =
795 GNUNET_CONTAINER_multipeermap_create (STARTING_NEIGHBOURS_SIZE, GNUNET_YES);
796 return h;
797}
798
799
800/**
801 * Disconnect from the transport service.
802 *
803 * @param handle handle to the service as returned from
804 * #GNUNET_TRANSPORT_core_connect()
805 */
806void
807GNUNET_TRANSPORT_core_disconnect (struct GNUNET_TRANSPORT_CoreHandle *handle)
808{
809 LOG (GNUNET_ERROR_TYPE_DEBUG, "Transport disconnect called!\n");
810 /* this disconnects all neighbours... */
811 disconnect (handle);
812 /* and now we stop trying to connect again... */
813 if (NULL != handle->reconnect_task)
814 {
815 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
816 handle->reconnect_task = NULL;
817 }
818 GNUNET_CONTAINER_multipeermap_destroy (handle->neighbours);
819 handle->neighbours = NULL;
820 GNUNET_free (handle->handlers);
821 handle->handlers = NULL;
822 GNUNET_free (handle);
823}
824
825
826/* end of transport_api_core.c */
diff --git a/src/transport/transport_api2_monitor.c b/src/transport/transport_api2_monitor.c
deleted file mode 100644
index 67aa1985e..000000000
--- a/src/transport/transport_api2_monitor.c
+++ /dev/null
@@ -1,292 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2018 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 transport/transport_api2_monitor.c
23 * @brief implementation of the gnunet_transport_monitor_service.h API
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_protocols.h"
29#include "gnunet_transport_monitor_service.h"
30#include "transport.h"
31
32
33/**
34 * Opaque handle to the transport service for monitors.
35 */
36struct GNUNET_TRANSPORT_MonitorContext
37{
38 /**
39 * Our configuration.
40 */
41 const struct GNUNET_CONFIGURATION_Handle *cfg;
42
43 /**
44 * Queue to talk to the transport service.
45 */
46 struct GNUNET_MQ_Handle *mq;
47
48 /**
49 * Peer we monitor, all zeros for "all"
50 */
51 struct GNUNET_PeerIdentity peer;
52
53 /**
54 * #GNUNET_YES to return the current state and then end.
55 */
56 int one_shot;
57
58 /**
59 * Function to call with monitor data.
60 */
61 GNUNET_TRANSPORT_MonitorCallback cb;
62
63 /**
64 * Closure for @e cb.
65 */
66 void *cb_cls;
67};
68
69
70/**
71 * (re)connect our monitor to the transport service
72 *
73 * @param mc handle to reconnect
74 */
75static void
76reconnect (struct GNUNET_TRANSPORT_MonitorContext *mc);
77
78
79/**
80 * Send message to the transport service about our montoring
81 * desire.
82 *
83 * @param ai address to delete
84 */
85static void
86send_start_monitor (struct GNUNET_TRANSPORT_MonitorContext *mc)
87{
88 struct GNUNET_MQ_Envelope *env;
89 struct GNUNET_TRANSPORT_MonitorStart *smm;
90
91 if (NULL == mc->mq)
92 return;
93 env = GNUNET_MQ_msg (smm, GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START);
94 smm->one_shot = htonl ((uint32_t) mc->one_shot);
95 smm->peer = mc->peer;
96 GNUNET_MQ_send (mc->mq, env);
97}
98
99
100/**
101 * Disconnect from the transport service.
102 *
103 * @param mc service to disconnect from
104 */
105static void
106disconnect (struct GNUNET_TRANSPORT_MonitorContext *mc)
107{
108 if (NULL == mc->mq)
109 return;
110 GNUNET_MQ_destroy (mc->mq);
111 mc->mq = NULL;
112}
113
114
115/**
116 * Function called on MQ errors. Reconnects to the service.
117 *
118 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
119 * @param error what error happened?
120 */
121static void
122error_handler (void *cls, enum GNUNET_MQ_Error error)
123{
124 struct GNUNET_TRANSPORT_MonitorContext *mc = cls;
125
126 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
127 "MQ failure %d, reconnecting to transport service.\n",
128 error);
129 disconnect (mc);
130 /* TODO: maybe do this with exponential backoff/delay */
131 reconnect (mc);
132}
133
134
135/**
136 * Transport service sends us information about what is going on.
137 * Check if @a md is well-formed.
138 *
139 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
140 * @param md the monitor data we got
141 * @return #GNUNET_OK if @a smt is well-formed
142 */
143static int
144check_monitor_data (void *cls, const struct GNUNET_TRANSPORT_MonitorData *md)
145{
146 (void) cls;
147 GNUNET_MQ_check_zero_termination (md);
148 return GNUNET_OK;
149}
150
151
152/**
153 * Transport service sends us information about what is going on.
154 *
155 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
156 * @param md monitor data
157 */
158static void
159handle_monitor_data (void *cls, const struct GNUNET_TRANSPORT_MonitorData *md)
160{
161 struct GNUNET_TRANSPORT_MonitorContext *mc = cls;
162 struct GNUNET_TRANSPORT_MonitorInformation mi;
163
164 mi.address = (const char *) &md[1];
165 mi.nt = (enum GNUNET_NetworkType) ntohl (md->nt);
166 mi.cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (md->cs);
167 mi.num_msg_pending = ntohl (md->num_msg_pending);
168 mi.num_bytes_pending = ntohl (md->num_bytes_pending);
169 mi.last_validation = GNUNET_TIME_absolute_ntoh (md->last_validation);
170 mi.valid_until = GNUNET_TIME_absolute_ntoh (md->valid_until);
171 mi.next_validation = GNUNET_TIME_absolute_ntoh (md->next_validation);
172 mi.rtt = GNUNET_TIME_relative_ntoh (md->rtt);
173 mc->cb (mc->cb_cls, &md->peer, &mi);
174}
175
176
177/**
178 * One shot was requested, and transport service is done.
179 *
180 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
181 * @param me end message
182 */
183static void
184handle_monitor_end (void *cls, const struct GNUNET_MessageHeader *me)
185{
186 struct GNUNET_TRANSPORT_MonitorContext *mc = cls;
187
188 if (GNUNET_YES != mc->one_shot)
189 {
190 GNUNET_break (0);
191 disconnect (mc);
192 reconnect (mc);
193 return;
194 }
195 mc->cb (mc->cb_cls, NULL, NULL);
196 GNUNET_TRANSPORT_monitor_cancel (mc);
197}
198
199
200/**
201 * (re)connect our monitor to the transport service
202 *
203 * @param mc handle to reconnect
204 */
205static void
206reconnect (struct GNUNET_TRANSPORT_MonitorContext *mc)
207{
208 struct GNUNET_MQ_MessageHandler handlers[] =
209 { GNUNET_MQ_hd_var_size (monitor_data,
210 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA,
211 struct GNUNET_TRANSPORT_MonitorData,
212 mc),
213 GNUNET_MQ_hd_fixed_size (monitor_end,
214 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_END,
215 struct GNUNET_MessageHeader,
216 mc),
217 GNUNET_MQ_handler_end () };
218
219 mc->mq =
220 GNUNET_CLIENT_connect (mc->cfg, "transport", handlers, &error_handler, mc);
221 if (NULL == mc->mq)
222 return;
223 send_start_monitor (mc);
224}
225
226
227/**
228 * Return information about a specific peer or all peers currently known to
229 * transport service once or in monitoring mode. To obtain information about
230 * a specific peer, a peer identity can be passed. To obtain information about
231 * all peers currently known to transport service, NULL can be passed as peer
232 * identity.
233 *
234 * For each peer, the callback is called with information about the address used
235 * to communicate with this peer, the state this peer is currently in and the
236 * the current timeout for this state.
237 *
238 * Upon completion, the #GNUNET_TRANSPORT_PeerIterateCallback is called one
239 * more time with `NULL`. After this, the operation must no longer be
240 * explicitly canceled.
241 *
242 * The #GNUNET_TRANSPORT_monitor_peers_cancel call MUST not be called in the
243 * the peer_callback!
244 *
245 * @param cfg configuration to use
246 * @param peer a specific peer identity to obtain information for,
247 * NULL for all peers
248 * @param one_shot #GNUNET_YES to return the current state and then end (with NULL+NULL),
249 * #GNUNET_NO to monitor peers continuously
250 * @param cb function to call with the results
251 * @param cb_cls closure for @a mc
252 */
253struct GNUNET_TRANSPORT_MonitorContext *
254GNUNET_TRANSPORT_monitor (const struct GNUNET_CONFIGURATION_Handle *cfg,
255 const struct GNUNET_PeerIdentity *peer,
256 int one_shot,
257 GNUNET_TRANSPORT_MonitorCallback cb,
258 void *cb_cls)
259{
260 struct GNUNET_TRANSPORT_MonitorContext *mc;
261
262 mc = GNUNET_new (struct GNUNET_TRANSPORT_MonitorContext);
263 mc->cfg = cfg;
264 if (NULL != peer)
265 mc->peer = *peer;
266 mc->one_shot = one_shot;
267 mc->cb = cb;
268 mc->cb_cls = cb_cls;
269 reconnect (mc);
270 if (NULL == mc->mq)
271 {
272 GNUNET_free (mc);
273 return NULL;
274 }
275 return mc;
276}
277
278
279/**
280 * Cancel request to monitor peers
281 *
282 * @param pmc handle for the request to cancel
283 */
284void
285GNUNET_TRANSPORT_monitor_cancel (struct GNUNET_TRANSPORT_MonitorContext *mc)
286{
287 disconnect (mc);
288 GNUNET_free (mc);
289}
290
291
292/* end of transport_api2_monitor.c */
diff --git a/src/transport/transport_api_cmd_backchannel_check.c b/src/transport/transport_api_cmd_backchannel_check.c
deleted file mode 100644
index 68bdae69c..000000000
--- a/src/transport/transport_api_cmd_backchannel_check.c
+++ /dev/null
@@ -1,554 +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_api_cmd_backchannel_check.c
23 * @brief cmd to start a peer.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_common.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_testing_ng_lib.h"
30#include "gnunet_testing_netjail_lib.h"
31#include "gnunet_transport_application_service.h"
32#include "gnunet_hello_lib.h"
33#include "transport-testing-cmds.h"
34
35/**
36 * Generic logging shortcut
37 */
38#define LOG(kind, ...) GNUNET_log_from (kind, "udp-backchannel",__VA_ARGS__)
39
40#define UDP "udp"
41
42/**
43 * Maximum length allowed for line input.
44 */
45#define MAX_LINE_LENGTH 1024
46
47/**
48 * Struct to store information needed in callbacks.
49 *
50 */
51struct CheckState
52{
53 /**
54 * Context for our asynchronous completion.
55 */
56 struct GNUNET_TESTING_AsyncContext ac;
57
58 /**
59 * The number of the node in a network namespace.
60 */
61 unsigned int node_n;
62
63 /**
64 * The number of the network namespace.
65 */
66 unsigned int namespace_n;
67
68 /**
69 * The testing system of this node.
70 */
71 const struct GNUNET_TESTING_System *tl_system;
72
73 // Label of the cmd which started the test system.
74 const char *create_label;
75
76 /**
77 * Number globally identifying the node.
78 *
79 */
80 uint32_t num;
81
82 /**
83 * Label of the cmd to start a peer.
84 *
85 */
86 const char *start_peer_label;
87
88 /**
89 * The topology of the test setup.
90 */
91 struct GNUNET_TESTING_NetjailTopology *topology;
92
93 /**
94 * Connections to other peers.
95 */
96 struct GNUNET_TESTING_NodeConnection *node_connections_head;
97
98 /**
99 * Number of connections.
100 */
101 unsigned int con_num;
102
103 /**
104 * Number of received backchannel messages.
105 */
106 unsigned int received_backchannel_msgs;
107
108 /**
109 * Array with search strings.
110 */
111 char **search_string;
112
113 /**
114 * File handle for log file.
115 */
116 struct GNUNET_DISK_FileHandle *fh;
117
118 /**
119 * Task which handles the reading
120 */
121 struct GNUNET_SCHEDULER_Task *task;
122
123 /**
124 * Stream to read log file lines.
125 */
126 FILE *stream;
127};
128
129/**
130 *
131 * @param cls The cmd state CheckState.
132 */
133static void
134read_from_log (void *cls)
135{
136 struct CheckState *cs = cls;
137 char line[MAX_LINE_LENGTH + 1];
138 char *search_string;
139
140
141 LOG (GNUNET_ERROR_TYPE_DEBUG,
142 "read_from_log\n");
143
144 cs->fh = GNUNET_DISK_file_open ("test.out",
145 GNUNET_DISK_OPEN_READ,
146 GNUNET_DISK_PERM_USER_READ);
147
148 cs->task = NULL;
149
150 /* read message from line and handle it */
151 cs->stream = fdopen (cs->fh->fd, "r");
152 memset (line, 0, MAX_LINE_LENGTH + 1);
153
154 // fgets (line, MAX_LINE_LENGTH, cs->stream);
155 // while (NULL != line && 0 != strcmp (line, ""))// '\0' != line[0])
156 while (NULL != fgets (line, MAX_LINE_LENGTH, cs->stream))
157 {
158 /*LOG (GNUNET_ERROR_TYPE_DEBUG,
159 "cs->received_backchannel_msgs: %u\n",
160 cs->received_backchannel_msgs);*/
161 /*if (NULL == strstr (line, "line"))
162 LOG (GNUNET_ERROR_TYPE_DEBUG,
163 "line: %s",
164 line);*/
165
166
167 for (int i = 0; i < cs->con_num; i++)
168 {
169 search_string = cs->search_string[i];
170 /*LOG (GNUNET_ERROR_TYPE_DEBUG,
171 "search %u %u: %s %p\n",
172 i,
173 cs->con_num,
174 cs->search_string[i],
175 cs->search_string);
176 fprintf (stderr,
177 line);*/
178 if (NULL != strstr (line,
179 search_string))
180 // "Delivering backchannel message from 4TTC to F7B5 of type 1460 to udp"))
181 // cs->search_string[i]))
182 {
183 cs->received_backchannel_msgs++;
184 LOG (GNUNET_ERROR_TYPE_DEBUG,
185 "received_backchannel_msgs %u con_num %u\n",
186 cs->received_backchannel_msgs,
187 cs->con_num);
188 if (cs->received_backchannel_msgs == cs->con_num)
189 {
190 LOG (GNUNET_ERROR_TYPE_DEBUG,
191 "search finished %lu %lu %u\n",
192 strlen (cs->search_string[i]),
193 strlen (
194 "Delivering backchannel message from 4TTC to F7B5 of type 1460 to udp"),
195 strcmp (
196 "Delivering backchannel message from 4TTC to F7B5 of type 1460 to udp",
197 cs->search_string[i]));
198 GNUNET_TESTING_async_finish (&cs->ac);
199 fclose (cs->stream);
200 return;
201 }
202 }
203 }
204 }
205 LOG (GNUNET_ERROR_TYPE_DEBUG,
206 "read_from_log end\n");
207 fclose (cs->stream);
208 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
209 &read_from_log,
210 cs);
211 /*if (NULL == fgets (line, MAX_LINE_LENGTH, cs->stream))
212 {
213 LOG (GNUNET_ERROR_TYPE_DEBUG,
214 "read null\n");
215 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
216 &read_from_log,
217 cs);
218 return;
219 }*/
220 /*else {
221 cs->task =
222 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
223 cs->fh,
224 &read_from_log,
225 cs);
226
227
228 }*/
229}
230
231
232static enum GNUNET_GenericReturnValue
233will_the_other_node_connect_via_udp (
234 struct CheckState *cs,
235 const struct GNUNET_TESTING_NetjailNode *node)
236// struct GNUNET_TESTING_NodeConnection *connection)
237{
238 // struct GNUNET_TESTING_NetjailTopology *topology = cs->topology;
239 // unsigned int node_n = connection->node_n;
240 // unsigned int namespace_n = connection->namespace_n;
241 // struct GNUNET_HashCode hc;
242 // struct GNUNET_ShortHashCode *key = GNUNET_new (struct GNUNET_ShortHashCode);
243 // struct GNUNET_HashCode hc_namespace;
244 /*struct GNUNET_ShortHashCode *key_namespace = GNUNET_new (struct
245 GNUNET_ShortHashCode);*/
246 // struct GNUNET_TESTING_NetjailNode *node;
247 struct GNUNET_TESTING_NodeConnection *pos_connection;
248 struct GNUNET_TESTING_AddressPrefix *pos_prefix;
249 // struct GNUNET_TESTING_NetjailNamespace *namespace;
250 // struct GNUNET_CONTAINER_MultiShortmap *map;
251
252 /* if (0 == connection->namespace_n) */
253 /* { */
254 /* map = topology->map_globals; */
255 /* } */
256 /* else */
257 /* { */
258 /* GNUNET_CRYPTO_hash (&namespace_n, sizeof(namespace_n), &hc_namespace); */
259 /* memcpy (key_namespace, */
260 /* &hc_namespace, */
261 /* sizeof (*key_namespace)); */
262 /* if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains ( */
263 /* topology->map_namespaces, */
264 /* key_namespace)) */
265 /* { */
266 /* namespace = GNUNET_CONTAINER_multishortmap_get (topology->map_namespaces, */
267 /* key_namespace); */
268 /* map = namespace->nodes; */
269 /* } */
270 /* else */
271 /* GNUNET_assert (0); */
272 /* } */
273
274 /* GNUNET_CRYPTO_hash (&node_n, sizeof(node_n), &hc); */
275 /* memcpy (key, */
276 /* &hc, */
277 /* sizeof (*key)); */
278 /* if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains ( */
279 /* map, */
280 /* key)) */
281 /* { */
282 /* node = GNUNET_CONTAINER_multishortmap_get (cs->topology->map_globals, */
283 /* key); */
284 /* for (pos_connection = node->node_connections_head; NULL != pos_connection; */
285 /* pos_connection = pos_connection->next) */
286 /* { */
287 /* if ((node->namespace_n == pos_connection->namespace_n) && */
288 /* (node->node_n == pos_connection->node_n) ) */
289 /* { */
290 /* for (pos_prefix = pos_connection->address_prefixes_head; NULL != */
291 /* pos_prefix; */
292 /* pos_prefix = */
293 /* pos_prefix->next) */
294 /* { */
295 /* if (0 == strcmp (UDP, pos_prefix->address_prefix)) */
296 /* { */
297 /* return GNUNET_YES; */
298 /* } */
299 /* } */
300 /* } */
301 /* } */
302 /* } */
303
304 for (pos_connection = node->node_connections_head; NULL != pos_connection;
305 pos_connection = pos_connection->next)
306 {
307 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
308 "connect via udp %u %u %u %u\n",
309 node->namespace_n,
310 cs->namespace_n,
311 node->node_n,
312 cs->node_n);
313 if ((pos_connection->namespace_n == cs->namespace_n) &&
314 (pos_connection->node_n == cs->node_n) )
315 {
316 for (pos_prefix = pos_connection->address_prefixes_head; NULL !=
317 pos_prefix;
318 pos_prefix =
319 pos_prefix->next)
320 {
321 if (0 == strcmp (UDP, pos_prefix->address_prefix))
322 {
323 return GNUNET_YES;
324 }
325 }
326 }
327 }
328
329 return GNUNET_NO;
330}
331
332
333static void
334add_search_string (struct CheckState *cs, const struct
335 GNUNET_TESTING_NetjailNode *node)
336{
337 unsigned int num;
338 struct GNUNET_PeerIdentity *peer;
339 struct GNUNET_PeerIdentity *us;
340 char *buf;
341 char *part_one = "Delivering backchannel message from ";
342 char *part_two = " to ";
343 char *part_three = " of type 1460 to udp";
344 char *peer_id;
345 char *us_id;
346
347 if (0 == node->namespace_n)
348 num = node->node_n;
349 else
350 num = (node->namespace_n - 1) * cs->topology->nodes_m + node->node_n
351 + cs->topology->nodes_x;
352
353 // num = GNUNET_TESTING_calculate_num (pos_connection, cs->topology);
354 peer = GNUNET_TESTING_get_peer (num, cs->tl_system);
355 LOG (GNUNET_ERROR_TYPE_DEBUG,
356 "peer: %s num %u\n",
357 GNUNET_i2s (peer),
358 num);
359 us = GNUNET_TESTING_get_peer (cs->num, cs->tl_system);
360 LOG (GNUNET_ERROR_TYPE_DEBUG,
361 "us: %s cs->num %d\n",
362 GNUNET_i2s (us),
363 cs->num);
364
365 GNUNET_asprintf (&peer_id,
366 "%s",
367 GNUNET_i2s (peer));
368 GNUNET_asprintf (&us_id,
369 "%s",
370 GNUNET_i2s (us));
371
372 if (0 < GNUNET_asprintf (&buf,
373 "%s%s%s%s%s",
374 part_one,
375 us_id,
376 part_two,
377 peer_id,
378 part_three))
379 {
380 GNUNET_array_append (cs->search_string,
381 cs->con_num,
382 buf);
383 /*LOG (GNUNET_ERROR_TYPE_DEBUG,
384 "con_num: %u search: %s %p\n",
385 cs->con_num,
386 cs->search_string[cs->con_num - 1],
387 cs->search_string);*/
388 }
389 else
390 GNUNET_assert (0);
391 GNUNET_free (peer);
392 GNUNET_free (us);
393}
394
395
396/**
397 * The run method of this cmd will connect to peers.
398 *
399 */
400static void
401backchannel_check_run (void *cls,
402 struct GNUNET_TESTING_Interpreter *is)
403{
404 struct CheckState *cs = cls;
405 const struct GNUNET_TESTING_Command *system_cmd;
406 const struct GNUNET_TESTING_System *tl_system;
407 const struct GNUNET_TESTING_Command *peer1_cmd;
408 const struct GNUNET_TRANSPORT_ApplicationHandle *ah;
409 struct GNUNET_CONTAINER_MultiShortmapIterator *node_it;
410 struct GNUNET_CONTAINER_MultiShortmapIterator *namespace_it;
411 struct GNUNET_ShortHashCode node_key;
412 struct GNUNET_ShortHashCode namespace_key;
413 const struct GNUNET_TESTING_NetjailNode *node;
414 const struct GNUNET_TESTING_NetjailNamespace *namespace;
415
416 LOG (GNUNET_ERROR_TYPE_DEBUG,
417 "check run 1\n");
418
419 peer1_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
420 cs->start_peer_label);
421 GNUNET_TRANSPORT_get_trait_application_handle (peer1_cmd,
422 &ah);
423
424 system_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
425 cs->create_label);
426 GNUNET_TESTING_get_trait_test_system (system_cmd,
427 &tl_system);
428
429 cs->tl_system = tl_system;
430
431 cs->node_connections_head = GNUNET_TESTING_get_connections (cs->num,
432 cs->topology);
433
434 LOG (GNUNET_ERROR_TYPE_DEBUG,
435 "check run 2\n");
436
437
438 node_it = GNUNET_CONTAINER_multishortmap_iterator_create (
439 cs->topology->map_globals);
440
441 while (GNUNET_YES == GNUNET_CONTAINER_multishortmap_iterator_next (node_it,
442 &node_key,
443 (const
444 void**) &
445 node))
446 {
447 LOG (GNUNET_ERROR_TYPE_DEBUG,
448 "namespace_n %u node_n %u\n",
449 node->namespace_n,
450 node->node_n);
451 if (GNUNET_YES == will_the_other_node_connect_via_udp (cs, node))
452 {
453 add_search_string (cs, node);
454 }
455 }
456 GNUNET_free (node_it);
457 namespace_it = GNUNET_CONTAINER_multishortmap_iterator_create (
458 cs->topology->map_namespaces);
459 while (GNUNET_YES == GNUNET_CONTAINER_multishortmap_iterator_next (
460 namespace_it,
461 &namespace_key,
462 (const
463 void**) &namespace))
464 {
465 LOG (GNUNET_ERROR_TYPE_DEBUG,
466 "namespace_n %u\n",
467 node->namespace_n);
468 node_it = GNUNET_CONTAINER_multishortmap_iterator_create (
469 namespace->nodes);
470 while (GNUNET_YES == GNUNET_CONTAINER_multishortmap_iterator_next (node_it,
471 &node_key,
472 (const
473 void**)
474 &node))
475 {
476 LOG (GNUNET_ERROR_TYPE_DEBUG,
477 "namespace_n %u node_n %u\n",
478 node->namespace_n,
479 node->node_n);
480 if (GNUNET_YES == will_the_other_node_connect_via_udp (cs, node))
481 {
482 add_search_string (cs, node);
483 }
484 }
485 GNUNET_free (node_it);
486 }
487
488 if (0 != cs->con_num)
489 {
490 cs->task =
491 GNUNET_SCHEDULER_add_now (&read_from_log,
492 cs);
493 }
494 else
495 GNUNET_TESTING_async_finish (&cs->ac);
496
497 GNUNET_free (namespace_it);
498}
499
500
501/**
502 * Trait function of this cmd does nothing.
503 *
504 */
505static int
506backchannel_check_traits (void *cls,
507 const void **ret,
508 const char *trait,
509 unsigned int index)
510{
511 return GNUNET_OK;
512}
513
514
515/**
516 * The cleanup function of this cmd frees resources the cmd allocated.
517 *
518 */
519static void
520backchannel_check_cleanup (void *cls)
521{
522 struct ConnectPeersState *cs = cls;
523
524 GNUNET_free (cs);
525}
526
527
528struct GNUNET_TESTING_Command
529GNUNET_TRANSPORT_cmd_backchannel_check (const char *label,
530 const char *start_peer_label,
531 const char *create_label,
532 uint32_t num,
533 unsigned int node_n,
534 unsigned int namespace_n,
535 struct GNUNET_TESTING_NetjailTopology *
536 topology)
537{
538 struct CheckState *cs;
539
540 cs = GNUNET_new (struct CheckState);
541 cs->start_peer_label = start_peer_label;
542 cs->num = num;
543 cs->create_label = create_label;
544 cs->topology = topology;
545 cs->node_n = node_n;
546 cs->namespace_n = namespace_n;
547
548 return GNUNET_TESTING_command_new (cs,
549 label,
550 &backchannel_check_run,
551 &backchannel_check_cleanup,
552 &backchannel_check_traits,
553 &cs->ac);
554}
diff --git a/src/transport/transport_api_cmd_connecting_peers.c b/src/transport/transport_api_cmd_connecting_peers.c
deleted file mode 100644
index c59c4b006..000000000
--- a/src/transport/transport_api_cmd_connecting_peers.c
+++ /dev/null
@@ -1,311 +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_api_cmd_start_peer.c
23 * @brief cmd to start a peer.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet_testing_netjail_lib.h"
30#include "gnunet_transport_application_service.h"
31#include "gnunet_hello_lib.h"
32#include "transport-testing-cmds.h"
33
34/**
35 * Generic logging shortcut
36 */
37#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
38
39/**
40 * The run method of this cmd will connect to peers.
41 *
42 */
43static void
44connect_peers_run (void *cls,
45 struct GNUNET_TESTING_Interpreter *is)
46{
47 struct ConnectPeersState *cps = cls;
48 const struct GNUNET_TESTING_Command *system_cmd;
49 const struct GNUNET_TESTING_System *tl_system;
50
51
52 const struct GNUNET_TESTING_Command *peer1_cmd;
53 const struct GNUNET_TRANSPORT_ApplicationHandle *ah;
54 struct GNUNET_PeerIdentity *peer;
55 char *addr;
56 char *addr_and_port;
57 enum GNUNET_NetworkType nt = 0;
58 uint32_t num;
59 struct GNUNET_TESTING_NodeConnection *pos_connection;
60 struct GNUNET_TESTING_AddressPrefix *pos_prefix;
61 unsigned int con_num = 0;
62 const enum GNUNET_GenericReturnValue *broadcast;
63
64 cps->is = is;
65 peer1_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
66 cps->start_peer_label);
67 if (GNUNET_YES == cps->wait_for_connect)
68 {
69 LOG (GNUNET_ERROR_TYPE_DEBUG,
70 "Wait for connect.\n");
71 GNUNET_TRANSPORT_get_trait_application_handle (peer1_cmd,
72 &ah);
73 }
74 else
75 {
76 LOG (GNUNET_ERROR_TYPE_DEBUG,
77 "Not waiting for connect.\n");
78 GNUNET_TESTING_get_trait_application_handle (peer1_cmd,
79 &ah);
80 }
81
82 GNUNET_TRANSPORT_get_trait_broadcast (peer1_cmd,
83 &broadcast);
84
85 system_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
86 cps->create_label);
87 GNUNET_TESTING_get_trait_test_system (system_cmd,
88 &tl_system);
89
90 cps->tl_system = tl_system;
91
92 LOG (GNUNET_ERROR_TYPE_DEBUG,
93 "cps->num: %u \n",
94 cps->num);
95
96 cps->node_connections_head = GNUNET_TESTING_get_connections (cps->num,
97 cps->topology);
98
99 for (pos_connection = cps->node_connections_head; NULL != pos_connection;
100 pos_connection = pos_connection->next)
101 {
102 con_num++;
103 num = GNUNET_TESTING_calculate_num (pos_connection, cps->topology);
104 for (pos_prefix = pos_connection->address_prefixes_head; NULL != pos_prefix;
105 pos_prefix =
106 pos_prefix->next)
107 {
108 addr = GNUNET_TESTING_get_address (pos_connection,
109 pos_prefix->address_prefix);
110 if (NULL != addr)
111 {
112 char *natted_p = strstr (pos_prefix->address_prefix, "_");
113
114 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
115 "0 validating peer number %s %s %s\n",
116 natted_p,
117 pos_prefix->address_prefix,
118 addr);
119 if (0 == GNUNET_memcmp (pos_prefix->address_prefix, "udp"))
120 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
121 "validating memcmp\n");
122 if (GNUNET_YES == *broadcast)
123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
124 "validating broadcast\n");
125 if ((0 == GNUNET_memcmp (pos_prefix->address_prefix, "udp")) &&
126 (GNUNET_YES == *broadcast) )
127 GNUNET_asprintf (&addr_and_port,
128 "%s:2086",
129 addr);
130 else if (NULL == natted_p)
131 GNUNET_asprintf (&addr_and_port,
132 "%s:60002",
133 addr);
134 else if (NULL != natted_p)
135 {
136 char *prefix;
137 char *rest;
138 char *rest2;
139 char *address;
140
141 prefix = strtok (addr, "_");
142 rest = strtok (NULL, "_");
143 rest2 = strtok (rest, "-");
144 address = strtok (NULL, "-");
145
146 GNUNET_asprintf (&addr_and_port,
147 "%s-%s:0",
148 prefix,
149 address);
150
151 }
152 peer = GNUNET_TESTING_get_peer (num, tl_system);
153 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
154 "validating peer number %u with identity %s and address %s %u %s and handle %p\n",
155 num,
156 GNUNET_i2s (peer),
157 addr_and_port,
158 *broadcast,
159 pos_prefix->address_prefix,
160 ah);
161 GNUNET_TRANSPORT_application_validate ((struct
162 GNUNET_TRANSPORT_ApplicationHandle
163 *) ah,
164 peer,
165 nt,
166 addr_and_port);
167 GNUNET_free (peer);
168 GNUNET_free (addr);
169 GNUNET_free (addr_and_port);
170 }
171 }
172 }
173 cps->con_num = con_num;
174}
175
176
177/**
178 * Callback from start peer cmd for signaling a peer got connected.
179 *
180 */
181static void *
182notify_connect (struct GNUNET_TESTING_Interpreter *is,
183 const struct GNUNET_PeerIdentity *peer)
184{
185 const struct GNUNET_TESTING_Command *cmd;
186 struct ConnectPeersState *cps;
187 struct GNUNET_PeerIdentity *peer_connection;
188 unsigned int num;
189 unsigned int con_num;
190 void *ret = NULL;
191
192 cmd = GNUNET_TESTING_interpreter_lookup_command_all (is,
193 "connect-peers");
194 cps = cmd->cls; // WTF? Never go directly into cls of another command! FIXME!
195 con_num = cps->con_num_notified;
196 for (struct GNUNET_TESTING_NodeConnection *pos_connection =
197 cps->node_connections_head;
198 NULL != pos_connection;
199 pos_connection = pos_connection->next)
200 {
201 num = GNUNET_TESTING_calculate_num (pos_connection,
202 cps->topology);
203 peer_connection = GNUNET_TESTING_get_peer (num,
204 cps->tl_system);
205 if (0 == GNUNET_memcmp (peer,
206 peer_connection))
207 cps->con_num_notified++;
208 GNUNET_free (peer_connection);
209 }
210 if (cps->con_num_notified == con_num)
211 cps->additional_connects_notified++;
212
213 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
214 "con_num: %u add: %u num_notified: %u add_notified: %u peer: %s\n",
215 cps->con_num,
216 cps->additional_connects,
217 cps->con_num_notified,
218 cps->additional_connects_notified,
219 GNUNET_i2s (peer));
220 if ((cps->con_num == cps->con_num_notified) &&
221 (cps->additional_connects <= cps->additional_connects_notified))
222 {
223 GNUNET_TESTING_async_finish (&cps->ac);
224 }
225 return ret;
226}
227
228
229/**
230 * The cleanup function of this cmd frees resources the cmd allocated.
231 *
232 */
233static void
234connect_peers_cleanup (void *cls)
235{
236 struct ConnectPeersState *cps = cls;
237
238 GNUNET_free (cps);
239}
240
241
242/**
243 * This function prepares an array with traits.
244 *
245 */
246enum GNUNET_GenericReturnValue
247connect_peers_traits (void *cls,
248 const void **ret,
249 const char *trait,
250 unsigned int index)
251{
252 struct ConnectPeersState *cps = cls;
253 struct GNUNET_TESTING_Trait traits[] = {
254 GNUNET_TRANSPORT_make_trait_connect_peer_state ((const void *) cps),
255 GNUNET_TESTING_trait_end ()
256 };
257 return GNUNET_TESTING_get_trait (traits,
258 ret,
259 trait,
260 index);
261}
262
263
264struct GNUNET_TESTING_Command
265GNUNET_TRANSPORT_cmd_connect_peers (const char *label,
266 const char *start_peer_label,
267 const char *create_label,
268 uint32_t num,
269 struct GNUNET_TESTING_NetjailTopology *
270 topology,
271 unsigned int additional_connects,
272 unsigned int wait_for_connect)
273{
274 struct ConnectPeersState *cps;
275 unsigned int node_additional_connects;
276
277 node_additional_connects = GNUNET_TESTING_get_additional_connects (num,
278 topology);
279
280 LOG (GNUNET_ERROR_TYPE_DEBUG,
281 "global: %u and local: %u additional_connects\n",
282 additional_connects,
283 node_additional_connects);
284
285 if (0 != node_additional_connects)
286 additional_connects = node_additional_connects;
287
288 cps = GNUNET_new (struct ConnectPeersState);
289 cps->start_peer_label = start_peer_label;
290 cps->num = num;
291 cps->create_label = create_label;
292 cps->topology = topology;
293 cps->notify_connect = notify_connect;
294 cps->additional_connects = additional_connects;
295 cps->wait_for_connect = wait_for_connect;
296
297 if (GNUNET_YES == wait_for_connect)
298 return GNUNET_TESTING_command_new (cps,
299 label,
300 &connect_peers_run,
301 &connect_peers_cleanup,
302 &connect_peers_traits,
303 &cps->ac);
304 else
305 return GNUNET_TESTING_command_new (cps,
306 label,
307 &connect_peers_run,
308 &connect_peers_cleanup,
309 &connect_peers_traits,
310 NULL);
311}
diff --git a/src/transport/transport_api_cmd_send_simple.c b/src/transport/transport_api_cmd_send_simple.c
deleted file mode 100644
index 2671727c0..000000000
--- a/src/transport/transport_api_cmd_send_simple.c
+++ /dev/null
@@ -1,162 +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_api_cmd_start_peer.c
23 * @brief cmd to start a peer.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet_testing_netjail_lib.h"
30#include "transport-testing2.h"
31#include "transport-testing-cmds.h"
32
33/**
34 * Generic logging shortcut
35 */
36#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
37
38/**
39 * Struct to hold information for callbacks.
40 *
41 */
42struct SendSimpleState
43{
44 /**
45 * Number globally identifying the node.
46 *
47 */
48 uint32_t num;
49
50 /**
51 * Label of the cmd to start a peer.
52 *
53 */
54 const char *start_peer_label;
55
56 /**
57 * Label of the cmd which started the test system.
58 *
59 */
60 const char *create_label;
61
62 /**
63 * The topology we get the connected nodes from.
64 */
65 struct GNUNET_TESTING_NetjailTopology *topology;
66};
67
68
69/**
70 * The cleanup function of this cmd frees resources the cmd allocated.
71 *
72 */
73static void
74send_simple_cleanup (void *cls)
75{
76 struct SendSimpleState *sss = cls;
77
78 GNUNET_free (sss);
79}
80
81
82static int
83send_simple_cb (void *cls,
84 const struct GNUNET_ShortHashCode *key,
85 void *value)
86{
87 struct SendSimpleState *sss = cls;
88 struct GNUNET_MQ_Handle *mq = value;
89 struct GNUNET_MQ_Envelope *env;
90 struct GNUNET_TRANSPORT_TESTING_TestMessage *test;
91
92 LOG (GNUNET_ERROR_TYPE_DEBUG,
93 "Sending simple test message with mq %p\n",
94 mq);
95
96 env = GNUNET_MQ_msg_extra (test,
97 1000 - sizeof(*test),
98 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE);
99 test->num = htonl (sss->num);
100 memset (&test[1],
101 sss->num,
102 1000 - sizeof(*test));
103 GNUNET_MQ_send (mq,
104 env);
105 return GNUNET_OK;
106}
107
108
109/**
110 * The run method of this cmd will send a simple message to the connected peers.
111 *
112 */
113static void
114send_simple_run (void *cls,
115 struct GNUNET_TESTING_Interpreter *is)
116{
117 struct SendSimpleState *sss = cls;
118 const struct GNUNET_CONTAINER_MultiShortmap *connected_peers_map;
119 const struct GNUNET_TESTING_Command *peer1_cmd;
120 const struct GNUNET_TESTING_Command *system_cmd;
121 const struct GNUNET_TESTING_System *tl_system;
122
123 peer1_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
124 sss->start_peer_label);
125 GNUNET_TRANSPORT_get_trait_connected_peers_map (peer1_cmd,
126 &connected_peers_map);
127
128 system_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
129 sss->create_label);
130 GNUNET_TESTING_get_trait_test_system (system_cmd,
131 &tl_system);
132
133 GNUNET_CONTAINER_multishortmap_iterate (
134 (struct GNUNET_CONTAINER_MultiShortmap *)
135 connected_peers_map, send_simple_cb,
136 sss);
137}
138
139
140struct GNUNET_TESTING_Command
141GNUNET_TRANSPORT_cmd_send_simple (const char *label,
142 const char *start_peer_label,
143 const char *create_label,
144 uint32_t num,
145 struct GNUNET_TESTING_NetjailTopology *
146 topology)
147{
148 struct SendSimpleState *sss;
149
150 sss = GNUNET_new (struct SendSimpleState);
151 sss->num = num;
152 sss->start_peer_label = start_peer_label;
153 sss->create_label = create_label;
154 sss->topology = topology;
155
156 return GNUNET_TESTING_command_new (sss,
157 label,
158 &send_simple_run,
159 &send_simple_cleanup,
160 NULL,
161 NULL);
162}
diff --git a/src/transport/transport_api_cmd_send_simple_performance.c b/src/transport/transport_api_cmd_send_simple_performance.c
deleted file mode 100644
index 7ce3b8bf7..000000000
--- a/src/transport/transport_api_cmd_send_simple_performance.c
+++ /dev/null
@@ -1,220 +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_api_cmd_start_peer.c
23 * @brief cmd to start a peer.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet_testing_netjail_lib.h"
30#include "transport-testing2.h"
31#include "transport-testing-cmds.h"
32
33/**
34 * Generic logging shortcut
35 */
36#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
37
38/**
39 * Struct to hold information for callbacks.
40 *
41 */
42struct SendSimplePerfState
43{
44 /**
45 * Context for our asynchronous completion.
46 */
47 struct GNUNET_TESTING_AsyncContext ac;
48
49 /**
50 * Label of the cmd to start a peer.
51 *
52 */
53 const char *start_peer_label;
54
55 /**
56 * Label of the cmd which started the test system.
57 *
58 */
59 const char *create_label;
60
61 /**
62 * The topology we get the connected nodes from.
63 */
64 struct GNUNET_TESTING_NetjailTopology *topology;
65
66 /**
67 * Size of the message in bytes.
68 */
69 unsigned int size;
70
71 /**
72 * Maximum number of messages per peer.
73 */
74 unsigned int max_send;
75};
76
77struct MQWrapper
78{
79 /**
80 * State of the command.
81 */
82 struct SendSimplePerfState *sss;
83
84 /**
85 * Message queue for a peer.
86 */
87 struct GNUNET_MQ_Handle *mq;
88
89 /**
90 * Number of messages allready send.
91 */
92 uint32_t num_send;
93};
94
95/**
96 * The cleanup function of this cmd frees resources the cmd allocated.
97 *
98 */
99static void
100send_simple_cleanup (void *cls)
101{
102 struct SendSimpleState *sss = cls;
103
104 GNUNET_free (sss);
105}
106
107
108static void
109send_simple_single (void *cls)
110{
111 struct MQWrapper *mq_wrapper = cls;
112 struct GNUNET_MQ_Envelope *env;
113 struct GNUNET_TRANSPORT_TESTING_PerformanceTestMessage *test;
114 struct GNUNET_TIME_Absolute now;
115
116 now = GNUNET_TIME_absolute_get ();
117 mq_wrapper->num_send++;
118 LOG (GNUNET_ERROR_TYPE_DEBUG,
119 "Sending simple test message with size %u number %u with mq %p max %u\n",
120 mq_wrapper->sss->size,
121 mq_wrapper->num_send,
122 mq_wrapper->mq,
123 mq_wrapper->sss->max_send);
124
125 env = GNUNET_MQ_msg_extra (test,
126 mq_wrapper->sss->size - sizeof(*test),
127 GNUNET_TRANSPORT_TESTING_SIMPLE_PERFORMANCE_MTYPE);
128 test->num = htonl (mq_wrapper->num_send);
129 test->time_send = GNUNET_TIME_absolute_hton (now);
130 memset (&test[1],
131 '1',
132 mq_wrapper->sss->size - sizeof(*test));
133 GNUNET_MQ_send (mq_wrapper->mq,
134 env);
135 if (mq_wrapper->sss->max_send > mq_wrapper->num_send)
136 GNUNET_SCHEDULER_add_now (&send_simple_single, mq_wrapper);
137 else
138 GNUNET_TESTING_async_finish (&mq_wrapper->sss->ac);
139}
140
141
142static int
143send_simple_cb (void *cls,
144 const struct GNUNET_ShortHashCode *key,
145 void *value)
146{
147 struct SendSimplePerfState *sss = cls;
148 struct GNUNET_MQ_Handle *mq = value;
149 struct MQWrapper *mq_wrapper = GNUNET_new (struct MQWrapper);
150
151 mq_wrapper->sss = sss;
152 mq_wrapper->mq = mq;
153 send_simple_single (mq_wrapper);
154
155 return GNUNET_OK;
156}
157
158
159/**
160 * The run method of this cmd will send a simple message to the connected peers.
161 *
162 */
163static void
164send_simple_run (void *cls,
165 struct GNUNET_TESTING_Interpreter *is)
166{
167 struct SendSimplePerfState *sss = cls;
168 const struct GNUNET_CONTAINER_MultiShortmap *connected_peers_map;
169 const struct GNUNET_TESTING_Command *peer1_cmd;
170 const struct GNUNET_TESTING_Command *system_cmd;
171 const struct GNUNET_TESTING_System *tl_system;
172
173
174 peer1_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
175 sss->start_peer_label);
176 GNUNET_TRANSPORT_get_trait_connected_peers_map (peer1_cmd,
177 &connected_peers_map);
178
179 system_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
180 sss->create_label);
181 GNUNET_TESTING_get_trait_test_system (system_cmd,
182 &tl_system);
183
184 GNUNET_CONTAINER_multishortmap_iterate (
185 (struct GNUNET_CONTAINER_MultiShortmap *)
186 connected_peers_map, send_simple_cb,
187 sss);
188}
189
190
191struct GNUNET_TESTING_Command
192GNUNET_TRANSPORT_cmd_send_simple_performance (const char *label,
193 const char *start_peer_label,
194 const char *create_label,
195 uint32_t num,
196 int size,
197 int max_send,
198 struct
199 GNUNET_TESTING_NetjailTopology *
200 topology)
201{
202 struct SendSimplePerfState *sss;
203 struct GNUNET_TESTING_Command cmd;
204
205 sss = GNUNET_new (struct SendSimplePerfState);
206 sss->start_peer_label = start_peer_label;
207 sss->create_label = create_label;
208 sss->topology = topology;
209 sss->size = size;
210 sss->max_send = max_send;
211
212 cmd = GNUNET_TESTING_command_new (sss,
213 label,
214 &send_simple_run,
215 &send_simple_cleanup,
216 NULL,
217 &sss->ac);
218 cmd.asynchronous_finish = GNUNET_YES;
219 return cmd;
220}
diff --git a/src/transport/transport_api_cmd_start_peer.c b/src/transport/transport_api_cmd_start_peer.c
deleted file mode 100644
index 54e204a21..000000000
--- a/src/transport/transport_api_cmd_start_peer.c
+++ /dev/null
@@ -1,483 +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_api_cmd_start_peer.c
23 * @brief cmd to start a peer.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet_testing_netjail_lib.h"
30#include "gnunet_peerstore_service.h"
31#include "gnunet_transport_core_service.h"
32#include "gnunet_transport_application_service.h"
33#include "transport-testing-cmds.h"
34
35/**
36 * Generic logging shortcut
37 */
38#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
39
40
41static void
42retrieve_hello (void *cls);
43
44
45/**
46 * Callback delivering the hello of this peer from peerstore.
47 *
48 */
49static void
50hello_iter_cb (void *cb_cls,
51 const struct GNUNET_PEERSTORE_Record *record,
52 const char *emsg)
53{
54 struct GNUNET_TESTING_StartPeerState *sps = cb_cls;
55 if (NULL == record)
56 {
57 sps->pic = NULL;
58 sps->rh_task = GNUNET_SCHEDULER_add_now (retrieve_hello, sps);
59 return;
60 }
61 // Check record type et al?
62 sps->hello_size = record->value_size;
63 sps->hello = GNUNET_malloc (sps->hello_size);
64 memcpy (sps->hello, record->value, sps->hello_size);
65 sps->hello[sps->hello_size - 1] = '\0';
66
67 LOG (GNUNET_ERROR_TYPE_DEBUG,
68 "Our hello %s\n",
69 sps->hello);
70 GNUNET_PEERSTORE_iterate_cancel (sps->pic);
71 sps->pic = NULL;
72 GNUNET_TESTING_async_finish (&sps->ac);
73}
74
75
76/**
77 * Function to start the retrieval task to retrieve the hello of this peer
78 * from the peerstore.
79 *
80 */
81static void
82retrieve_hello (void *cls)
83{
84 struct GNUNET_TESTING_StartPeerState *sps = cls;
85 sps->rh_task = NULL;
86 sps->pic = GNUNET_PEERSTORE_iterate (sps->ph,
87 "transport",
88 &sps->id,
89 GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY,
90 hello_iter_cb,
91 sps);
92
93}
94
95
96/**
97 * Disconnect callback for the connection to the core service.
98 *
99 */
100static void
101notify_disconnect (void *cls,
102 const struct GNUNET_PeerIdentity *peer,
103 void *handler_cls)
104{
105 struct GNUNET_TESTING_StartPeerState *sps = cls;
106
107 LOG (GNUNET_ERROR_TYPE_DEBUG,
108 "Peer %s disconnected from peer %u (`%s')\n",
109 GNUNET_i2s (peer),
110 sps->no,
111 GNUNET_i2s (&sps->id));
112
113}
114
115
116/**
117 * Connect callback for the connection to the core service.
118 *
119 */
120static void *
121notify_connect (void *cls,
122 const struct GNUNET_PeerIdentity *peer,
123 struct GNUNET_MQ_Handle *mq)
124{
125 struct GNUNET_TESTING_StartPeerState *sps = cls;
126 struct GNUNET_ShortHashCode *key = GNUNET_new (struct GNUNET_ShortHashCode);
127 struct GNUNET_HashCode hc;
128 struct GNUNET_CRYPTO_EddsaPublicKey public_key = peer->public_key;
129
130 void *ret = (struct GNUNET_PeerIdentity *) peer;
131
132 LOG (GNUNET_ERROR_TYPE_DEBUG,
133 "This Peer %s \n",
134 GNUNET_i2s (&sps->id));
135
136
137 GNUNET_CRYPTO_hash (&public_key, sizeof(public_key), &hc);
138
139 LOG (GNUNET_ERROR_TYPE_DEBUG,
140 "Peer %s connected to peer number %u with mq %p\n",
141 GNUNET_i2s (peer),
142 sps->no,
143 mq);
144
145
146 memcpy (key,
147 &hc,
148 sizeof (*key));
149 GNUNET_CONTAINER_multishortmap_put (sps->connected_peers_map,
150 key,
151 mq,
152 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
153
154 GNUNET_free (key);
155
156 sps->notify_connect (sps->ac.is,
157 peer);
158
159 return ret;
160}
161
162
163/**
164 * The run method of this cmd will start all services of a peer to test the transport service.
165 *
166 */
167static void
168start_peer_run (void *cls,
169 struct GNUNET_TESTING_Interpreter *is)
170{
171 struct GNUNET_TESTING_StartPeerState *sps = cls;
172 char *emsg = NULL;
173 struct GNUNET_PeerIdentity dummy;
174 const struct GNUNET_TESTING_Command *system_cmd;
175 const struct GNUNET_TESTING_System *tl_system;
176 char *home;
177 char *transport_unix_path;
178 char *tcp_communicator_unix_path;
179 char *udp_communicator_unix_path;
180 char *bindto;
181 char *bindto_udp;
182
183 if (GNUNET_NO == GNUNET_DISK_file_test (sps->cfgname))
184 {
185 LOG (GNUNET_ERROR_TYPE_ERROR,
186 "File not found: `%s'\n",
187 sps->cfgname);
188 GNUNET_TESTING_interpreter_fail (is);
189 return;
190 }
191
192
193 sps->cfg = GNUNET_CONFIGURATION_create ();
194 GNUNET_assert (GNUNET_OK ==
195 GNUNET_CONFIGURATION_load (sps->cfg, sps->cfgname));
196
197 GNUNET_asprintf (&home,
198 "$GNUNET_TMP/test-transport/api-tcp-p%u",
199 sps->no);
200
201 GNUNET_asprintf (&transport_unix_path,
202 "$GNUNET_RUNTIME_DIR/tng-p%u.sock",
203 sps->no);
204
205 GNUNET_asprintf (&tcp_communicator_unix_path,
206 "$GNUNET_RUNTIME_DIR/tcp-comm-p%u.sock",
207 sps->no);
208
209 GNUNET_asprintf (&udp_communicator_unix_path,
210 "$GNUNET_RUNTIME_DIR/tcp-comm-p%u.sock",
211 sps->no);
212
213 GNUNET_asprintf (&bindto,
214 "%s:60002",
215 sps->node_ip);
216
217 GNUNET_asprintf (&bindto_udp,
218 "2086");
219
220 LOG (GNUNET_ERROR_TYPE_DEBUG,
221 "node_ip %s\n",
222 bindto);
223
224 LOG (GNUNET_ERROR_TYPE_DEBUG,
225 "bind_udp %s\n",
226 GNUNET_YES == sps->broadcast ?
227 bindto_udp : bindto);
228
229 GNUNET_CONFIGURATION_set_value_string (sps->cfg, "PATHS", "GNUNET_TEST_HOME",
230 home);
231 GNUNET_CONFIGURATION_set_value_string (sps->cfg, "transport", "UNIXPATH",
232 transport_unix_path);
233 GNUNET_CONFIGURATION_set_value_string (sps->cfg, "communicator-tcp",
234 "BINDTO",
235 bindto);
236 GNUNET_CONFIGURATION_set_value_string (sps->cfg, "communicator-udp",
237 "BINDTO",
238 GNUNET_YES == sps->broadcast ?
239 bindto_udp : bindto);
240 GNUNET_CONFIGURATION_set_value_string (sps->cfg, "communicator-tcp",
241 "UNIXPATH",
242 tcp_communicator_unix_path);
243 GNUNET_CONFIGURATION_set_value_string (sps->cfg, "communicator-udp",
244 "UNIXPATH",
245 udp_communicator_unix_path);
246
247
248 system_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
249 sps->system_label);
250 GNUNET_TESTING_get_trait_test_system (system_cmd,
251 &tl_system);
252
253 sps->tl_system = tl_system;
254
255 LOG (GNUNET_ERROR_TYPE_DEBUG,
256 "Creating testing library with key number %u\n",
257 sps->no);
258
259 if (GNUNET_SYSERR ==
260 GNUNET_TESTING_configuration_create ((struct
261 GNUNET_TESTING_System *) tl_system,
262 sps->cfg))
263 {
264 LOG (GNUNET_ERROR_TYPE_DEBUG,
265 "Testing library failed to create unique configuration based on `%s'\n",
266 sps->cfgname);
267 GNUNET_CONFIGURATION_destroy (sps->cfg);
268 GNUNET_TESTING_interpreter_fail (is);
269 return;
270 }
271
272 sps->peer = GNUNET_TESTING_peer_configure ((struct
273 GNUNET_TESTING_System *) sps->
274 tl_system,
275 sps->cfg,
276 sps->no,
277 NULL,
278 &emsg);
279 if (NULL == sps->peer)
280 {
281 LOG (GNUNET_ERROR_TYPE_ERROR,
282 "Testing library failed to create unique configuration based on `%s': `%s' with key number %u\n",
283 sps->cfgname,
284 emsg,
285 sps->no);
286 GNUNET_free (emsg);
287 GNUNET_TESTING_interpreter_fail (is);
288 return;
289 }
290
291 if (GNUNET_OK != GNUNET_TESTING_peer_start (sps->peer))
292 {
293 LOG (GNUNET_ERROR_TYPE_ERROR,
294 "Testing library failed to create unique configuration based on `%s'\n",
295 sps->cfgname);
296 GNUNET_free (emsg);
297 GNUNET_TESTING_interpreter_fail (is);
298 return;
299 }
300
301 memset (&dummy,
302 '\0',
303 sizeof(dummy));
304
305 GNUNET_TESTING_peer_get_identity (sps->peer,
306 &sps->id);
307
308 if (0 == memcmp (&dummy,
309 &sps->id,
310 sizeof(struct GNUNET_PeerIdentity)))
311 {
312 LOG (GNUNET_ERROR_TYPE_ERROR,
313 "Testing library failed to obtain peer identity for peer %u\n",
314 sps->no);
315 GNUNET_free (emsg);
316 GNUNET_TESTING_interpreter_fail (is);
317 return;
318 }
319 LOG (GNUNET_ERROR_TYPE_DEBUG,
320 "Peer %u configured with identity `%s'\n",
321 sps->no,
322 GNUNET_i2s_full (&sps->id));
323
324 sps->th = GNUNET_TRANSPORT_core_connect (sps->cfg,
325 NULL,
326 sps->handlers,
327 sps,
328 &notify_connect,
329 &notify_disconnect);
330 if (NULL == sps->th)
331 {
332 LOG (GNUNET_ERROR_TYPE_ERROR,
333 "Failed to connect to transport service for peer `%s': `%s'\n",
334 sps->cfgname,
335 emsg);
336 GNUNET_free (emsg);
337 GNUNET_TESTING_interpreter_fail (is);
338 return;
339 }
340
341 sps->ph = GNUNET_PEERSTORE_connect (sps->cfg);
342 if (NULL == sps->ph)
343 {
344 LOG (GNUNET_ERROR_TYPE_ERROR,
345 "Failed to connect to peerstore service for peer `%s': `%s'\n",
346 sps->cfgname,
347 emsg);
348 GNUNET_free (emsg);
349 GNUNET_TESTING_interpreter_fail (is);
350 return;
351 }
352
353 sps->ah = GNUNET_TRANSPORT_application_init (sps->cfg);
354 if (NULL == sps->ah)
355 {
356 LOG (GNUNET_ERROR_TYPE_ERROR,
357 "Failed to initialize the TRANSPORT application suggestion client handle for peer `%s': `%s'\n",
358 sps->cfgname,
359 emsg);
360 GNUNET_free (emsg);
361 GNUNET_TESTING_interpreter_fail (is);
362 return;
363 }
364 sps->rh_task = GNUNET_SCHEDULER_add_now (retrieve_hello, sps);
365 GNUNET_free (home);
366 GNUNET_free (transport_unix_path);
367 GNUNET_free (tcp_communicator_unix_path);
368 GNUNET_free (udp_communicator_unix_path);
369 GNUNET_free (bindto);
370 GNUNET_free (bindto_udp);
371}
372
373
374/**
375 * The cleanup function of this cmd frees resources the cmd allocated.
376 *
377 */
378static void
379start_peer_cleanup (void *cls)
380{
381 struct GNUNET_TESTING_StartPeerState *sps = cls;
382
383 if (NULL != sps->handlers)
384 {
385 GNUNET_free (sps->handlers);
386 sps->handlers = NULL;
387 }
388 // TODO Investigate why this caused problems during shutdown.
389 /*if (NULL != sps->cfg)
390 {
391 GNUNET_CONFIGURATION_destroy (sps->cfg);
392 sps->cfg = NULL;
393 }*/
394 GNUNET_free (sps->cfgname);
395 GNUNET_free (sps->node_ip);
396 GNUNET_free (sps->system_label);
397 GNUNET_free (sps->hello);
398 GNUNET_free (sps->connected_peers_map);
399 GNUNET_free (sps);
400}
401
402
403/**
404 * This function prepares an array with traits.
405 *
406 */
407static int
408start_peer_traits (void *cls,
409 const void **ret,
410 const char *trait,
411 unsigned int index)
412{
413 struct GNUNET_TESTING_StartPeerState *sps = cls;
414 struct GNUNET_TRANSPORT_ApplicationHandle *ah = sps->ah;
415 struct GNUNET_PeerIdentity *id = &sps->id;
416 struct GNUNET_CONTAINER_MultiShortmap *connected_peers_map =
417 sps->connected_peers_map;
418 char *hello = sps->hello;
419 size_t hello_size = sps->hello_size;
420
421
422 struct GNUNET_TESTING_Trait traits[] = {
423 GNUNET_TRANSPORT_make_trait_application_handle ((const void *) ah),
424 GNUNET_TRANSPORT_make_trait_peer_id ((const void *) id),
425 GNUNET_TRANSPORT_make_trait_connected_peers_map ((const
426 void *)
427 connected_peers_map),
428 GNUNET_TRANSPORT_make_trait_hello ((const void *) hello),
429 GNUNET_TRANSPORT_make_trait_hello_size ((const void *) hello_size),
430 GNUNET_TRANSPORT_make_trait_state ((const void *) sps),
431 GNUNET_TRANSPORT_make_trait_broadcast ((const void *) &sps->broadcast),
432 GNUNET_TESTING_trait_end ()
433 };
434
435 return GNUNET_TESTING_get_trait (traits,
436 ret,
437 trait,
438 index);
439}
440
441
442struct GNUNET_TESTING_Command
443GNUNET_TRANSPORT_cmd_start_peer (const char *label,
444 const char *system_label,
445 uint32_t no,
446 const char *node_ip,
447 struct GNUNET_MQ_MessageHandler *handlers,
448 const char *cfgname,
449 GNUNET_TRANSPORT_notify_connect_cb
450 notify_connect,
451 unsigned int broadcast)
452{
453 struct GNUNET_TESTING_StartPeerState *sps;
454 struct GNUNET_CONTAINER_MultiShortmap *connected_peers_map =
455 GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
456 unsigned int i;
457
458 sps = GNUNET_new (struct GNUNET_TESTING_StartPeerState);
459 sps->no = no;
460 sps->system_label = GNUNET_strdup (system_label);
461 sps->connected_peers_map = connected_peers_map;
462 sps->cfgname = GNUNET_strdup (cfgname);
463 sps->node_ip = GNUNET_strdup (node_ip);
464 sps->notify_connect = notify_connect;
465 sps->broadcast = broadcast;
466
467 if (NULL != handlers)
468 {
469 for (i = 0; NULL != handlers[i].cb; i++)
470 ;
471 sps->handlers = GNUNET_new_array (i + 1,
472 struct GNUNET_MQ_MessageHandler);
473 GNUNET_memcpy (sps->handlers,
474 handlers,
475 i * sizeof(struct GNUNET_MQ_MessageHandler));
476 }
477 return GNUNET_TESTING_command_new (sps,
478 label,
479 &start_peer_run,
480 &start_peer_cleanup,
481 &start_peer_traits,
482 &sps->ac);
483}
diff --git a/src/transport/transport_api_cmd_stop_peer.c b/src/transport/transport_api_cmd_stop_peer.c
deleted file mode 100644
index 60d48c56b..000000000
--- a/src/transport/transport_api_cmd_stop_peer.c
+++ /dev/null
@@ -1,154 +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_api_cmd_stop_peer.c
23 * @brief cmd to stop a peer.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet_testing_netjail_lib.h"
30#include "gnunet_peerstore_service.h"
31#include "gnunet_transport_core_service.h"
32#include "gnunet_transport_application_service.h"
33#include "transport-testing-cmds.h"
34
35/**
36 * Generic logging shortcut
37 */
38#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
39
40
41/**
42 * Struct to hold information for callbacks.
43 *
44 */
45struct StopPeerState
46{
47 // Label of the cmd to start the peer.
48 const char *start_label;
49};
50
51
52/**
53 * The run method of this cmd will stop all services of a peer which were used to test the transport service.
54 *
55 */
56static void
57stop_peer_run (void *cls,
58 struct GNUNET_TESTING_Interpreter *is)
59{
60 struct StopPeerState *stop_ps = cls;
61 const struct GNUNET_TESTING_StartPeerState *sps;
62 const struct GNUNET_TESTING_Command *start_cmd;
63
64 start_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
65 stop_ps->start_label);
66 GNUNET_TRANSPORT_get_trait_state (start_cmd,
67 &sps);
68
69 if (NULL != sps->pic)
70 {
71 GNUNET_PEERSTORE_iterate_cancel (sps->pic);
72 }
73 if (NULL != sps->th)
74 {
75 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
76 "Disconnecting from TRANSPORT service\n");
77 GNUNET_TRANSPORT_core_disconnect (sps->th);
78 }
79 if (NULL != sps->ah)
80 {
81 GNUNET_TRANSPORT_application_done (sps->ah);
82 }
83 if (NULL != sps->ph)
84 {
85 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
86 "Disconnecting from PEERSTORE service\n");
87 GNUNET_PEERSTORE_disconnect (sps->ph, GNUNET_NO);
88 }
89 if (NULL != sps->peer)
90 {
91 if (GNUNET_OK !=
92 GNUNET_TESTING_peer_stop (sps->peer))
93 {
94 LOG (GNUNET_ERROR_TYPE_ERROR,
95 "Testing lib failed to stop peer %u (`%s')\n",
96 sps->no,
97 GNUNET_i2s (&sps->id));
98 }
99 GNUNET_TESTING_peer_destroy (sps->peer);
100 }
101 if (NULL != sps->rh_task)
102 GNUNET_SCHEDULER_cancel (sps->rh_task);
103}
104
105
106/**
107 * The cleanup function of this cmd frees resources the cmd allocated.
108 *
109 */
110static void
111stop_peer_cleanup (void *cls)
112{
113 struct StopPeerState *sps = cls;
114
115 GNUNET_free (sps);
116}
117
118
119/**
120 * Trait function of this cmd does nothing.
121 *
122 */
123static int
124stop_peer_traits (void *cls,
125 const void **ret,
126 const char *trait,
127 unsigned int index)
128{
129 return GNUNET_OK;
130}
131
132
133/**
134 * Create command.
135 *
136 * @param label name for command.
137 * @param start_label Label of the cmd to start the peer.
138 * @return command.
139 */
140struct GNUNET_TESTING_Command
141GNUNET_TRANSPORT_cmd_stop_peer (const char *label,
142 const char *start_label)
143{
144 struct StopPeerState *sps;
145
146 sps = GNUNET_new (struct StopPeerState);
147 sps->start_label = start_label;
148 return GNUNET_TESTING_command_new (sps,
149 label,
150 &stop_peer_run,
151 &stop_peer_cleanup,
152 &stop_peer_traits,
153 NULL);
154}
diff --git a/src/transport/transport_api_traits.c b/src/transport/transport_api_traits.c
deleted file mode 100644
index 7e66cc3d1..000000000
--- a/src/transport/transport_api_traits.c
+++ /dev/null
@@ -1,32 +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 transport/test_transport_start_with_config.c
23 * @brief Generic program to start testcases in an configurable topology.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_ng_lib.h"
28#include "gnunet_testing_netjail_lib.h"
29#include "transport-testing-cmds.h"
30#include "gnunet_util_lib.h"
31
32GNUNET_TRANSPORT_SIMPLE_TRAITS (GNUNET_TRANSPORT_MAKE_IMPL_SIMPLE_TRAIT)
diff --git a/src/transport/upnp.sh b/src/transport/upnp.sh
deleted file mode 100755
index d01a1a1a1..000000000
--- a/src/transport/upnp.sh
+++ /dev/null
@@ -1,22 +0,0 @@
1#!/bin/bash
2
3if [ $2 -eq 1 ]
4then
5 if [ ! -d /tmp/netjail_scripts ]
6 then
7 mkdir /tmp/netjail_scripts
8 fi
9
10 ext_ifname=$(ip addr |grep UP|grep "@"|awk -F: '{printf $2"\n"}'|tr -d " "|awk -F@ '{printf $1" "}'|awk '{printf $1}')
11 listening_ip=$(ip addr |grep UP|grep "@"|awk -F: '{printf $2"\n"}'|tr -d " "|awk -F@ '{printf $1" "}'|awk '{printf $2}')
12 uuid=$(uuidgen)
13 cat miniupnpd.conf |sed 's/#ext_ifname=eth1/ext_ifname='$ext_ifname'/g'|sed 's/#listening_ip=eth0/listening_ip='$listening_ip'/g'|sed 's/uuid=73a9cb68-a00b-4d2c-8412-75fc989f0c6/uuid='$uuid'/g'|grep -v "^#"|grep -v '^$' > /tmp/netjail_scripts/gargoyle.txt
14 miniupnpd -d -f /tmp/netjail_scripts/gargoyle.txt -P /tmp/netjail_scripts/miniupnpd_$1.pid &
15else
16 kill $(cat /tmp/netjail_scripts/miniupnpd_$1.pid)
17fi
18
19
20
21
22