aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxrs <xrs@mail36.net>2017-03-12 15:34:30 +0100
committerxrs <xrs@mail36.net>2017-03-12 15:34:30 +0100
commit02babcf349e9b80f4ff12893b4f8a78601c0e91c (patch)
treeb8ed076a358afe2affb09971a066749e14d52064
parent7cd462b984eddaf5872de7d1f75389fb6c5a5146 (diff)
parent7d473d08bcc4929c58b85ace2b16f781d721ad13 (diff)
downloadgnunet-02babcf349e9b80f4ff12893b4f8a78601c0e91c.tar.gz
gnunet-02babcf349e9b80f4ff12893b4f8a78601c0e91c.zip
Merge branch 'master' of ssh://gnunet.org/gnunet
-rw-r--r--src/arm/gnunet-service-arm.c1
-rw-r--r--src/cadet/Makefile.am208
-rw-r--r--src/cadet/cadet.conf.in2
-rw-r--r--src/cadet/cadet.h2
-rw-r--r--src/cadet/cadet_path.c363
-rw-r--r--src/cadet/cadet_path.h226
-rw-r--r--src/cadet/cadet_protocol.h150
-rw-r--r--src/cadet/cadet_test_lib.c135
-rw-r--r--src/cadet/cadet_test_lib.h40
-rw-r--r--src/cadet/cadet_test_lib_new.c362
-rw-r--r--src/cadet/cadet_test_lib_new.h106
-rw-r--r--src/cadet/gnunet-service-cadet-new.c1496
-rw-r--r--src/cadet/gnunet-service-cadet-new_channel.c2040
-rw-r--r--src/cadet/gnunet-service-cadet-new_channel.h262
-rw-r--r--src/cadet/gnunet-service-cadet-new_connection.c1093
-rw-r--r--src/cadet/gnunet-service-cadet-new_connection.h339
-rw-r--r--src/cadet/gnunet-service-cadet-new_dht.c351
-rw-r--r--src/cadet/gnunet-service-cadet-new_dht.h100
-rw-r--r--src/cadet/gnunet-service-cadet-new_hello.c152
-rw-r--r--src/cadet/gnunet-service-cadet-new_hello.h80
-rw-r--r--src/cadet/gnunet-service-cadet-new_peer.c1478
-rw-r--r--src/cadet/gnunet-service-cadet-new_peer.h394
-rw-r--r--src/cadet/gnunet-service-cadet.c1470
-rw-r--r--src/cadet/gnunet-service-cadet.h (renamed from src/cadet/gnunet-service-cadet-new.h)2
-rw-r--r--src/cadet/gnunet-service-cadet_channel.c3461
-rw-r--r--src/cadet/gnunet-service-cadet_channel.h387
-rw-r--r--src/cadet/gnunet-service-cadet_connection.c4010
-rw-r--r--src/cadet/gnunet-service-cadet_connection.h605
-rw-r--r--src/cadet/gnunet-service-cadet_core.c (renamed from src/cadet/gnunet-service-cadet-new_core.c)10
-rw-r--r--src/cadet/gnunet-service-cadet_core.h (renamed from src/cadet/gnunet-service-cadet-new_core.h)0
-rw-r--r--src/cadet/gnunet-service-cadet_dht.c373
-rw-r--r--src/cadet/gnunet-service-cadet_dht.h49
-rw-r--r--src/cadet/gnunet-service-cadet_hello.c140
-rw-r--r--src/cadet/gnunet-service-cadet_hello.h5
-rw-r--r--src/cadet/gnunet-service-cadet_local.c1553
-rw-r--r--src/cadet/gnunet-service-cadet_local.h234
-rw-r--r--src/cadet/gnunet-service-cadet_paths.c (renamed from src/cadet/gnunet-service-cadet-new_paths.c)10
-rw-r--r--src/cadet/gnunet-service-cadet_paths.h (renamed from src/cadet/gnunet-service-cadet-new_paths.h)2
-rw-r--r--src/cadet/gnunet-service-cadet_peer.c2928
-rw-r--r--src/cadet/gnunet-service-cadet_peer.h519
-rw-r--r--src/cadet/gnunet-service-cadet_tunnel.c3501
-rw-r--r--src/cadet/gnunet-service-cadet_tunnel.h616
-rw-r--r--src/cadet/gnunet-service-cadet_tunnels.c (renamed from src/cadet/gnunet-service-cadet-new_tunnels.c)13
-rw-r--r--src/cadet/gnunet-service-cadet_tunnels.h (renamed from src/cadet/gnunet-service-cadet-new_tunnels.h)4
-rw-r--r--src/cadet/test_cadet.c795
-rw-r--r--src/cadet/test_cadet_local.c351
-rw-r--r--src/cadet/test_cadet_new.c1105
-rw-r--r--src/cadet/test_cadet_single.c354
-rw-r--r--src/datacache/Makefile.am1
-rw-r--r--src/datacache/plugin_datacache_sqlite.c549
-rw-r--r--src/datastore/plugin_datastore_sqlite.c714
-rw-r--r--src/include/gnunet_sq_lib.h11
-rw-r--r--src/revocation/test_revocation.c20
-rw-r--r--src/set/Makefile.am2
-rw-r--r--src/set/gnunet-service-set.c284
-rw-r--r--src/set/gnunet-service-set.h50
-rw-r--r--src/set/gnunet-service-set_intersection.c139
-rw-r--r--src/set/gnunet-service-set_union.c682
-rw-r--r--src/set/set_api.c12
-rw-r--r--src/set/test_set_union_copy.c1
-rw-r--r--src/sq/sq.c25
-rw-r--r--src/sq/sq_query_helper.c44
-rw-r--r--src/sq/sq_result_helper.c67
63 files changed, 7516 insertions, 26962 deletions
diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c
index 4f3e964e3..cc23ef1f6 100644
--- a/src/arm/gnunet-service-arm.c
+++ b/src/arm/gnunet-service-arm.c
@@ -812,6 +812,7 @@ start_process (struct ServiceList *sl,
812 "%s %s", 812 "%s %s",
813 fin_options, 813 fin_options,
814 optpos); 814 optpos);
815 GNUNET_free (fin_options);
815 GNUNET_free (optpos); 816 GNUNET_free (optpos);
816 } 817 }
817 else 818 else
diff --git a/src/cadet/Makefile.am b/src/cadet/Makefile.am
index b52079b2e..1fe912305 100644
--- a/src/cadet/Makefile.am
+++ b/src/cadet/Makefile.am
@@ -23,7 +23,6 @@ AM_CLFAGS = -g
23 23
24libexec_PROGRAMS = \ 24libexec_PROGRAMS = \
25 gnunet-service-cadet \ 25 gnunet-service-cadet \
26 gnunet-service-cadet-new \
27 $(EXP_LIBEXEC) 26 $(EXP_LIBEXEC)
28 27
29bin_PROGRAMS = \ 28bin_PROGRAMS = \
@@ -61,88 +60,40 @@ gnunet_cadet_LDADD = \
61 libgnunetcadetnew.la \ 60 libgnunetcadetnew.la \
62 $(top_builddir)/src/util/libgnunetutil.la 61 $(top_builddir)/src/util/libgnunetutil.la
63 62
64gnunet_service_cadet_new_SOURCES = \
65 gnunet-service-cadet-new.c gnunet-service-cadet-new.h \
66 gnunet-service-cadet-new_channel.c gnunet-service-cadet-new_channel.h \
67 gnunet-service-cadet-new_connection.c gnunet-service-cadet-new_connection.h \
68 gnunet-service-cadet-new_core.c gnunet-service-cadet-new_core.h \
69 gnunet-service-cadet-new_dht.c gnunet-service-cadet-new_dht.h \
70 gnunet-service-cadet-new_hello.c gnunet-service-cadet-new_hello.h \
71 gnunet-service-cadet-new_tunnels.c gnunet-service-cadet-new_tunnels.h \
72 gnunet-service-cadet-new_paths.c gnunet-service-cadet-new_paths.h \
73 gnunet-service-cadet-new_peer.c gnunet-service-cadet-new_peer.h
74gnunet_service_cadet_new_LDADD = \
75 $(top_builddir)/src/util/libgnunetutil.la \
76 $(top_builddir)/src/ats/libgnunetats.la \
77 $(top_builddir)/src/core/libgnunetcore.la \
78 $(top_builddir)/src/dht/libgnunetdht.la \
79 $(top_builddir)/src/statistics/libgnunetstatistics.la \
80 $(top_builddir)/src/transport/libgnunettransport.la \
81 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
82 $(top_builddir)/src/hello/libgnunethello.la \
83 $(top_builddir)/src/block/libgnunetblock.la
84
85gnunet_service_cadet_SOURCES = \ 63gnunet_service_cadet_SOURCES = \
86 gnunet-service-cadet_tunnel.c gnunet-service-cadet_tunnel.h \ 64 gnunet-service-cadet.c gnunet-service-cadet.h \
87 gnunet-service-cadet_connection.c gnunet-service-cadet_connection.h \
88 gnunet-service-cadet_channel.c gnunet-service-cadet_channel.h \ 65 gnunet-service-cadet_channel.c gnunet-service-cadet_channel.h \
89 gnunet-service-cadet_local.c gnunet-service-cadet_local.h \ 66 gnunet-service-cadet_connection.c gnunet-service-cadet_connection.h \
90 gnunet-service-cadet_peer.c gnunet-service-cadet_peer.h \ 67 gnunet-service-cadet_core.c gnunet-service-cadet_core.h \
91 gnunet-service-cadet_dht.c gnunet-service-cadet_dht.h \ 68 gnunet-service-cadet_dht.c gnunet-service-cadet_dht.h \
92 gnunet-service-cadet_hello.c gnunet-service-cadet_hello.h \ 69 gnunet-service-cadet_hello.c gnunet-service-cadet_hello.h \
93 cadet_path.c cadet_path.h \ 70 gnunet-service-cadet_tunnels.c gnunet-service-cadet_tunnels.h \
94 cadet_common.c \ 71 gnunet-service-cadet_paths.c gnunet-service-cadet_paths.h \
95 gnunet-service-cadet.c 72 gnunet-service-cadet_peer.c gnunet-service-cadet_peer.h
96gnunet_service_cadet_CFLAGS = $(AM_CFLAGS)
97gnunet_service_cadet_LDADD = \ 73gnunet_service_cadet_LDADD = \
98 $(top_builddir)/src/util/libgnunetutil.la \ 74 $(top_builddir)/src/util/libgnunetutil.la \
99 $(top_builddir)/src/transport/libgnunettransport.la \
100 $(top_builddir)/src/core/libgnunetcore.la \
101 $(top_builddir)/src/ats/libgnunetats.la \ 75 $(top_builddir)/src/ats/libgnunetats.la \
76 $(top_builddir)/src/core/libgnunetcore.la \
102 $(top_builddir)/src/dht/libgnunetdht.la \ 77 $(top_builddir)/src/dht/libgnunetdht.la \
103 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 78 $(top_builddir)/src/statistics/libgnunetstatistics.la \
79 $(top_builddir)/src/transport/libgnunettransport.la \
104 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 80 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
105 $(top_builddir)/src/hello/libgnunethello.la \ 81 $(top_builddir)/src/hello/libgnunethello.la \
106 $(top_builddir)/src/block/libgnunetblock.la 82 $(top_builddir)/src/block/libgnunetblock.la
107if LINUX 83if LINUX
108 gnunet_service_cadet_LDFLAGS = -lrt 84 gnunet_service_cadet_new_LDFLAGS = -lrt
109endif 85endif
110 86
111 87
112if HAVE_TESTING 88if HAVE_TESTING
113 noinst_LTLIBRARIES = libgnunetcadettest.la libgnunetcadettestnew.la $(noinst_LIB_EXP) 89 noinst_LTLIBRARIES = libgnunetcadettest.la $(noinst_LIB_EXP)
114 noinst_PROGRAMS = gnunet-cadet-profiler 90# noinst_PROGRAMS = gnunet-cadet-profiler
115endif 91endif
116 92
117libgnunetcadettest_la_SOURCES = \
118 cadet_test_lib.c cadet_test_lib.h
119libgnunetcadettest_la_LIBADD = \
120 $(top_builddir)/src/util/libgnunetutil.la \
121 $(top_builddir)/src/testbed/libgnunettestbed.la \
122 libgnunetcadet.la
123
124if HAVE_TESTING 93if HAVE_TESTING
125check_PROGRAMS = \ 94check_PROGRAMS = \
126 test_cadet_local_mq \ 95 test_cadet_local_mq \
127 test_cadet_2_forward_new \ 96 test_cadet_2_forward \
128 test_cadet_2_forward_new \
129 test_cadet_2_signal_new \
130 test_cadet_2_keepalive_new \
131 test_cadet_2_speed_new \
132 test_cadet_2_speed_ack_new \
133 test_cadet_2_speed_backwards_new \
134 test_cadet_2_speed_reliable_new \
135 test_cadet_2_speed_reliable_backwards_new \
136 test_cadet_5_forward_new \
137 test_cadet_5_signal_new \
138 test_cadet_5_keepalive_new \
139 test_cadet_5_speed_new \
140 test_cadet_5_speed_ack_new \
141 test_cadet_5_speed_reliable_new \
142 test_cadet_5_speed_reliable_backwards_new \
143 test_cadet_5_speed_backwards_new \
144 test_cadet_single \
145 test_cadet_local \
146 test_cadet_2_forward \ 97 test_cadet_2_forward \
147 test_cadet_2_signal \ 98 test_cadet_2_signal \
148 test_cadet_2_keepalive \ 99 test_cadet_2_keepalive \
@@ -161,32 +112,10 @@ check_PROGRAMS = \
161 test_cadet_5_speed_backwards 112 test_cadet_5_speed_backwards
162endif 113endif
163 114
164ld_cadet_test_lib = \
165 $(top_builddir)/src/util/libgnunetutil.la \
166 $(top_builddir)/src/testing/libgnunettesting.la \
167 libgnunetcadettest.la \
168 libgnunetcadet.la \
169 $(top_builddir)/src/testbed/libgnunettestbed.la \
170 $(top_builddir)/src/statistics/libgnunetstatistics.la
171
172dep_cadet_test_lib = \
173 libgnunetcadet.la \
174 libgnunetcadettest.la \
175 $(top_builddir)/src/statistics/libgnunetstatistics.la
176
177
178gnunet_cadet_profiler_SOURCES = \
179 gnunet-cadet-profiler.c
180gnunet_cadet_profiler_LDADD = $(ld_cadet_test_lib)
181 115
182 116#gnunet_cadet_profiler_SOURCES = \
183test_cadet_single_SOURCES = \ 117# gnunet-cadet-profiler.c
184 test_cadet_single.c 118#gnunet_cadet_profiler_LDADD = $(ld_cadet_test_lib)
185test_cadet_single_LDADD = $(ld_cadet_test_lib)
186
187test_cadet_local_SOURCES = \
188 test_cadet_local.c
189test_cadet_local_LDADD = $(ld_cadet_test_lib)
190 119
191 120
192test_cadet_local_mq_SOURCES = \ 121test_cadet_local_mq_SOURCES = \
@@ -196,6 +125,26 @@ test_cadet_local_mq_LDADD = \
196 $(top_builddir)/src/testing/libgnunettesting.la \ 125 $(top_builddir)/src/testing/libgnunettesting.la \
197 $(top_builddir)/src/util/libgnunetutil.la 126 $(top_builddir)/src/util/libgnunetutil.la
198 127
128
129libgnunetcadettest_la_SOURCES = \
130 cadet_test_lib.c cadet_test_lib.h
131libgnunetcadettest_la_LIBADD = \
132 $(top_builddir)/src/util/libgnunetutil.la \
133 $(top_builddir)/src/testbed/libgnunettestbed.la \
134 libgnunetcadetnew.la
135
136ld_cadet_test_lib = \
137 $(top_builddir)/src/util/libgnunetutil.la \
138 $(top_builddir)/src/testing/libgnunettesting.la \
139 libgnunetcadetnew.la \
140 libgnunetcadettest.la \
141 $(top_builddir)/src/testbed/libgnunettestbed.la \
142 $(top_builddir)/src/statistics/libgnunetstatistics.la
143dep_cadet_test_lib = \
144 libgnunetcadetnew.la \
145 libgnunetcadettest.la \
146 $(top_builddir)/src/statistics/libgnunetstatistics.la
147
199test_cadet_2_forward_SOURCES = \ 148test_cadet_2_forward_SOURCES = \
200 test_cadet.c 149 test_cadet.c
201test_cadet_2_forward_LDADD = $(ld_cadet_test_lib) 150test_cadet_2_forward_LDADD = $(ld_cadet_test_lib)
@@ -228,7 +177,6 @@ test_cadet_2_speed_reliable_backwards_SOURCES = \
228 test_cadet.c 177 test_cadet.c
229test_cadet_2_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib) 178test_cadet_2_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib)
230 179
231
232test_cadet_5_forward_SOURCES = \ 180test_cadet_5_forward_SOURCES = \
233 test_cadet.c 181 test_cadet.c
234test_cadet_5_forward_LDADD = $(ld_cadet_test_lib) 182test_cadet_5_forward_LDADD = $(ld_cadet_test_lib)
@@ -262,92 +210,6 @@ test_cadet_5_speed_reliable_backwards_SOURCES = \
262test_cadet_5_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib) 210test_cadet_5_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib)
263 211
264 212
265# NEW TESTS
266libgnunetcadettestnew_la_SOURCES = \
267 cadet_test_lib_new.c cadet_test_lib_new.h
268libgnunetcadettestnew_la_LIBADD = \
269 $(top_builddir)/src/util/libgnunetutil.la \
270 $(top_builddir)/src/testbed/libgnunettestbed.la \
271 libgnunetcadetnew.la
272
273ld_cadet_test_lib_new = \
274 $(top_builddir)/src/util/libgnunetutil.la \
275 $(top_builddir)/src/testing/libgnunettesting.la \
276 libgnunetcadetnew.la \
277 libgnunetcadettestnew.la \
278 $(top_builddir)/src/testbed/libgnunettestbed.la \
279 $(top_builddir)/src/statistics/libgnunetstatistics.la
280dep_cadet_test_lib_new = \
281 libgnunetcadetnew.la \
282 libgnunetcadettestnew.la \
283 $(top_builddir)/src/statistics/libgnunetstatistics.la
284
285test_cadet_2_forward_new_SOURCES = \
286 test_cadet_new.c
287test_cadet_2_forward_new_LDADD = $(ld_cadet_test_lib_new)
288
289test_cadet_2_signal_new_SOURCES = \
290 test_cadet_new.c
291test_cadet_2_signal_new_LDADD = $(ld_cadet_test_lib_new)
292
293test_cadet_2_keepalive_new_SOURCES = \
294 test_cadet_new.c
295test_cadet_2_keepalive_new_LDADD = $(ld_cadet_test_lib_new)
296
297test_cadet_2_speed_new_SOURCES = \
298 test_cadet_new.c
299test_cadet_2_speed_new_LDADD = $(ld_cadet_test_lib_new)
300
301test_cadet_2_speed_ack_new_SOURCES = \
302 test_cadet_new.c
303test_cadet_2_speed_ack_new_LDADD = $(ld_cadet_test_lib_new)
304
305test_cadet_2_speed_backwards_new_SOURCES = \
306 test_cadet_new.c
307test_cadet_2_speed_backwards_new_LDADD = $(ld_cadet_test_lib_new)
308
309test_cadet_2_speed_reliable_new_SOURCES = \
310 test_cadet_new.c
311test_cadet_2_speed_reliable_new_LDADD = $(ld_cadet_test_lib_new)
312
313test_cadet_2_speed_reliable_backwards_new_SOURCES = \
314 test_cadet_new.c
315test_cadet_2_speed_reliable_backwards_new_LDADD = $(ld_cadet_test_lib_new)
316
317
318test_cadet_5_forward_new_SOURCES = \
319 test_cadet_new.c
320test_cadet_5_forward_new_LDADD = $(ld_cadet_test_lib_new)
321
322test_cadet_5_signal_new_SOURCES = \
323 test_cadet_new.c
324test_cadet_5_signal_new_LDADD = $(ld_cadet_test_lib_new)
325
326test_cadet_5_keepalive_new_SOURCES = \
327 test_cadet_new.c
328test_cadet_5_keepalive_new_LDADD = $(ld_cadet_test_lib_new)
329
330test_cadet_5_speed_new_SOURCES = \
331 test_cadet_new.c
332test_cadet_5_speed_new_LDADD = $(ld_cadet_test_lib_new)
333
334test_cadet_5_speed_ack_new_SOURCES = \
335 test_cadet_new.c
336test_cadet_5_speed_ack_new_LDADD = $(ld_cadet_test_lib_new)
337
338test_cadet_5_speed_backwards_new_SOURCES = \
339 test_cadet_new.c
340test_cadet_5_speed_backwards_new_LDADD = $(ld_cadet_test_lib_new)
341
342test_cadet_5_speed_reliable_new_SOURCES = \
343 test_cadet_new.c
344test_cadet_5_speed_reliable_new_LDADD = $(ld_cadet_test_lib_new)
345
346test_cadet_5_speed_reliable_backwards_new_SOURCES = \
347 test_cadet_new.c
348test_cadet_5_speed_reliable_backwards_new_LDADD = $(ld_cadet_test_lib_new)
349
350
351if ENABLE_TEST_RUN 213if ENABLE_TEST_RUN
352AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; 214AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
353TESTS = \ 215TESTS = \
diff --git a/src/cadet/cadet.conf.in b/src/cadet/cadet.conf.in
index 86ba2e535..d50e168f0 100644
--- a/src/cadet/cadet.conf.in
+++ b/src/cadet/cadet.conf.in
@@ -3,7 +3,7 @@ FORCESTART = YES
3AUTOSTART = @AUTOSTART@ 3AUTOSTART = @AUTOSTART@
4@JAVAPORT@PORT = 2096 4@JAVAPORT@PORT = 2096
5HOSTNAME = localhost 5HOSTNAME = localhost
6BINARY = gnunet-service-cadet-new 6BINARY = gnunet-service-cadet
7# PREFIX = valgrind --leak-check=yes 7# PREFIX = valgrind --leak-check=yes
8ACCEPT_FROM = 127.0.0.1; 8ACCEPT_FROM = 127.0.0.1;
9ACCEPT_FROM6 = ::1; 9ACCEPT_FROM6 = ::1;
diff --git a/src/cadet/cadet.h b/src/cadet/cadet.h
index 451d1f354..99f9f2653 100644
--- a/src/cadet/cadet.h
+++ b/src/cadet/cadet.h
@@ -59,7 +59,7 @@ extern "C"
59#include "gnunet_core_service.h" 59#include "gnunet_core_service.h"
60#include "gnunet_cadet_service.h" 60#include "gnunet_cadet_service.h"
61#include "gnunet_protocols.h" 61#include "gnunet_protocols.h"
62#include <gnunet_cadet_service.h> 62#include "gnunet_cadet_service.h"
63 63
64/******************************************************************************/ 64/******************************************************************************/
65/************************** CONSTANTS ******************************/ 65/************************** CONSTANTS ******************************/
diff --git a/src/cadet/cadet_path.c b/src/cadet/cadet_path.c
deleted file mode 100644
index 79a498805..000000000
--- a/src/cadet/cadet_path.c
+++ /dev/null
@@ -1,363 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001 - 2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/cadet_path.c
23 * @brief Path handling functions
24 * @author Bartlomiej Polot
25 */
26
27#include "cadet.h"
28#include "cadet_path.h"
29#include "gnunet-service-cadet_peer.h"
30
31#define LOG(level, ...) GNUNET_log_from (level,"cadet-pth",__VA_ARGS__)
32
33
34/**
35 * @brief Destroy a path after some time has past.
36 * Removes the path from the peer (must not be used for direct paths).
37 *
38 * @param cls Closure (path to destroy).
39 */
40static void
41path_destroy_delayed (void *cls)
42{
43 struct CadetPeerPath *path = cls;
44 struct CadetPeer *peer;
45
46 path->path_delete = NULL;
47 LOG (GNUNET_ERROR_TYPE_DEBUG,
48 "Destroy delayed %p (%u)\n",
49 path,
50 path->length);
51 GNUNET_assert (2 < path->length);
52 peer = GCP_get_short (path->peers[path->length - 1],
53 GNUNET_NO);
54 GNUNET_assert (NULL != peer);
55 GCP_remove_path (peer, path);
56}
57
58
59/**
60 * Create a new path
61 *
62 * @param length How many hops will the path have.
63 * @return A newly allocated path with a peer array of the specified length.
64 */
65struct CadetPeerPath *
66path_new (unsigned int length)
67{
68 struct CadetPeerPath *p;
69
70 p = GNUNET_new (struct CadetPeerPath);
71 if (length > 0)
72 {
73 p->length = length;
74 p->peers = GNUNET_malloc (length * sizeof (GNUNET_PEER_Id));
75 }
76 LOG (GNUNET_ERROR_TYPE_DEBUG, "New path %p (%u)\n", p, p->length);
77 return p;
78}
79
80
81/**
82 * Invert the path
83 *
84 * @param path the path to invert
85 */
86void
87path_invert (struct CadetPeerPath *path)
88{
89 GNUNET_PEER_Id aux;
90 unsigned int i;
91
92 for (i = 0; i < path->length / 2; i++)
93 {
94 aux = path->peers[i];
95 path->peers[i] = path->peers[path->length - i - 1];
96 path->peers[path->length - i - 1] = aux;
97 }
98}
99
100
101/**
102 * Duplicate a path, incrementing short peer's rc.
103 *
104 * @param path The path to duplicate.
105 */
106struct CadetPeerPath *
107path_duplicate (const struct CadetPeerPath *path)
108{
109 struct CadetPeerPath *aux;
110 unsigned int i;
111
112 aux = path_new (path->length);
113 GNUNET_memcpy (aux->peers,
114 path->peers,
115 path->length * sizeof (GNUNET_PEER_Id));
116 for (i = 0; i < aux->length; i++)
117 GNUNET_PEER_change_rc (aux->peers[i], 1);
118 return aux;
119}
120
121
122/**
123 * Get the length of a path.
124 *
125 * @param path The path to measure, with the local peer at any point of it.
126 *
127 * @return Number of hops to reach destination.
128 * UINT_MAX in case the peer is not in the path.
129 */
130unsigned int
131path_get_length (struct CadetPeerPath *path)
132{
133 if (NULL == path)
134 return UINT_MAX;
135 return path->length;
136}
137
138
139
140/**
141 * Mark path as invalid: keep it aroud for a while to avoid trying it in a loop.
142 *
143 * Never invalidates a two-hop (direct) path, only a core handler can do that.
144 *
145 * Rationale: DHT_get sometimes returns bad cached results, for instance,
146 * on a locally cached result where the PUT followed a path that is no longer
147 * current. The path must remain "known and marked as invalid" for a while.
148 *
149 * @param p Path to invalidate.
150 */
151void
152path_invalidate (struct CadetPeerPath *p)
153{
154 if (NULL != p->path_delete)
155 return;
156
157 LOG (GNUNET_ERROR_TYPE_DEBUG,
158 "Invalidating path %p (%u)\n",
159 p,
160 p->length);
161 p->path_delete
162 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
163 &path_destroy_delayed, p);
164}
165
166
167/**
168 * Builds a path from a PeerIdentity array.
169 *
170 * @param peers PeerIdentity array.
171 * @param size Size of the @c peers array.
172 * @param myid ID of local peer, to find @c own_pos.
173 * @param own_pos Output parameter: own position in the path.
174 *
175 * @return Fixed and shortened path.
176 */
177struct CadetPeerPath *
178path_build_from_peer_ids (struct GNUNET_PeerIdentity *peers,
179 unsigned int size,
180 GNUNET_PEER_Id myid,
181 unsigned int *own_pos)
182{
183 struct CadetPeerPath *path;
184 GNUNET_PEER_Id shortid;
185 unsigned int i;
186 unsigned int j;
187 unsigned int offset;
188
189 /* Create path */
190 LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n");
191 path = path_new (size);
192 *own_pos = 0;
193 offset = 0;
194 for (i = 0; i < size; i++)
195 {
196 LOG (GNUNET_ERROR_TYPE_DEBUG, " - %u: taking %s\n",
197 i, GNUNET_i2s (&peers[i]));
198 shortid = GNUNET_PEER_intern (&peers[i]);
199
200 /* Check for loops / duplicates */
201 for (j = 0; j < i - offset; j++)
202 {
203 if (path->peers[j] == shortid)
204 {
205 LOG (GNUNET_ERROR_TYPE_DEBUG, " already exists at pos %u\n", j);
206 offset = i - j;
207 LOG (GNUNET_ERROR_TYPE_DEBUG, " offset now %u\n", offset);
208 GNUNET_PEER_change_rc (shortid, -1);
209 }
210 }
211 LOG (GNUNET_ERROR_TYPE_DEBUG, " storing at %u\n", i - offset);
212 path->peers[i - offset] = shortid;
213 if (path->peers[i - offset] == myid)
214 *own_pos = i - offset;
215 }
216 path->length -= offset;
217
218 if (path->peers[*own_pos] != myid)
219 {
220 /* create path: self not found in path through self */
221 GNUNET_break_op (0);
222 path_destroy (path);
223 return NULL;
224 }
225
226 return path;
227}
228
229
230/**
231 * Test if two paths are equivalent (equal or revese of each other).
232 *
233 * @param p1 First path
234 * @param p2 Second path
235 *
236 * @return #GNUNET_YES if both paths are equivalent
237 * #GNUNET_NO otherwise
238 */
239int
240path_equivalent (const struct CadetPeerPath *p1,
241 const struct CadetPeerPath *p2)
242{
243 unsigned int i;
244 unsigned int l;
245 unsigned int half;
246
247 if (NULL == p1 || NULL == p2)
248 return GNUNET_NO;
249
250 if (p1->length != p2->length)
251 return GNUNET_NO;
252
253 l = p1->length;
254 if (0 == memcmp (p1->peers, p2->peers, sizeof (p1->peers[0]) * l))
255 return GNUNET_YES;
256
257 half = l / 2;
258 l = l - 1;
259 for (i = 0; i <= half; i++)
260 if (p1->peers[i] != p2->peers[l - i])
261 return GNUNET_NO;
262
263 return GNUNET_YES;
264}
265
266
267/**
268 * Test if a path is valid (or at least not known to be invalid).
269 *
270 * @param path Path to test.
271 *
272 * @return #GNUNET_YES If the path is valid or unknown,
273 * #GNUNET_NO If the path is known to be invalid.
274 */
275int
276path_is_valid (const struct CadetPeerPath *path)
277{
278 return (NULL == path->path_delete);
279}
280
281
282/**
283 * Destroy the path and free any allocated resources linked to it
284 *
285 * @param p the path to destroy
286 *
287 * @return #GNUNET_OK on success
288 */
289int
290path_destroy (struct CadetPeerPath *p)
291{
292 if (NULL == p)
293 return GNUNET_OK;
294
295 LOG (GNUNET_ERROR_TYPE_DEBUG,
296 "destroying path %p (%u)\n",
297 p,
298 p->length);
299 GNUNET_PEER_decrement_rcs (p->peers, p->length);
300 GNUNET_free_non_null (p->peers);
301 if (NULL != p->path_delete)
302 GNUNET_SCHEDULER_cancel (p->path_delete);
303 GNUNET_free (p);
304 return GNUNET_OK;
305}
306
307
308/**
309 * Compare two paths.
310 *
311 * @param p1 First path.
312 * @param p2 Second path.
313 *
314 * @return > 0 if p1 is longer, or the first differing PEER_Id is higher on p1.
315 * < 0 if p2 is longer, or the first differing PEER_Id is higher on p2.
316 * 0 if they are identical.
317 */
318int
319path_cmp (const struct CadetPeerPath *p1,
320 const struct CadetPeerPath *p2)
321{
322 if (p1->length > p2->length)
323 return 1;
324
325 if (p1->length < p2->length)
326 return -1;
327
328 return memcmp (p1->peers,
329 p2->peers,
330 sizeof (GNUNET_PEER_Id) * p1->length);
331}
332
333
334char *
335path_2s (struct CadetPeerPath *p)
336{
337 char *s;
338 char *old;
339 unsigned int i;
340
341 old = GNUNET_strdup ("");
342 for (i = 0; i < p->length; i++)
343 {
344 GNUNET_asprintf (&s, "%s %s",
345 old, GNUNET_i2s (GNUNET_PEER_resolve2 (p->peers[i])));
346 GNUNET_free_non_null (old);
347 old = s;
348 }
349 return old;
350}
351
352
353void
354path_debug (struct CadetPeerPath *p)
355{
356 unsigned int i;
357
358 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH:\n");
359 for (i = 0; i < p->length; i++)
360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n",
361 GNUNET_i2s (GNUNET_PEER_resolve2 (p->peers[i])));
362 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "END\n");
363}
diff --git a/src/cadet/cadet_path.h b/src/cadet/cadet_path.h
deleted file mode 100644
index bb68eec42..000000000
--- a/src/cadet/cadet_path.h
+++ /dev/null
@@ -1,226 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001 - 2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/cadet_path.h
23 * @brief Path handling functions
24 * @author Bartlomiej Polot
25 */
26
27#ifndef CADET_PATH_H_
28#define CADET_PATH_H_
29
30#ifdef __cplusplus
31extern "C"
32{
33 #if 0 /* keep Emacsens' auto-indent happy */
34}
35#endif
36#endif
37
38
39/******************************************************************************/
40/************************ DATA STRUCTURES ****************************/
41/******************************************************************************/
42
43/**
44 * Information regarding a possible path to reach a single peer
45 */
46struct CadetPeerPath
47{
48
49 /**
50 * Linked list
51 */
52 struct CadetPeerPath *next;
53 struct CadetPeerPath *prev;
54
55 /**
56 * List of all the peers that form the path from origin to target.
57 */
58 GNUNET_PEER_Id *peers;
59
60 /**
61 * Number of peers (hops) in the path
62 */
63 unsigned int length;
64
65 /**
66 * User defined data store.
67 */
68 struct CadetConnection *c;
69
70 /**
71 * Path's score, how reliable is the path.
72 */
73// int score;
74
75 /**
76 * Task to delete the path.
77 * We tried it, it didn't work, don't try again in a while.
78 */
79 struct GNUNET_SCHEDULER_Task * path_delete;
80
81};
82
83/******************************************************************************/
84/************************* FUNCTIONS *****************************/
85/******************************************************************************/
86
87/**
88 * Create a new path.
89 *
90 * @param length How many hops will the path have.
91 *
92 * @return A newly allocated path with a peer array of the specified length.
93 */
94struct CadetPeerPath *
95path_new (unsigned int length);
96
97
98/**
99 * Invert the path.
100 *
101 * @param path The path to invert.
102 */
103void
104path_invert (struct CadetPeerPath *path);
105
106
107/**
108 * Duplicate a path, incrementing short peer's rc.
109 *
110 * @param path The path to duplicate.
111 */
112struct CadetPeerPath *
113path_duplicate (const struct CadetPeerPath *path);
114
115
116/**
117 * Get the length of a path.
118 *
119 * @param path The path to measure, with the local peer at any point of it.
120 *
121 * @return Number of hops to reach destination.
122 * UINT_MAX in case the peer is not in the path.
123 */
124unsigned int
125path_get_length (struct CadetPeerPath *path);
126
127/**
128 * Mark path as invalid: keep it aroud for a while to avoid trying it in a loop.
129 *
130 * DHT_get sometimes returns bad cached results, for instance, on a locally
131 * cached result where the PUT followed a path that is no longer current.
132 *
133 * @param p Path to invalidate.
134 */
135void
136path_invalidate (struct CadetPeerPath *p);
137
138/**
139 * Test if two paths are equivalent (equal or revese of each other).
140 *
141 * @param p1 First path
142 * @param p2 Second path
143 *
144 * @return GNUNET_YES if both paths are equivalent
145 * GNUNET_NO otherwise
146 */
147int
148path_equivalent (const struct CadetPeerPath *p1,
149 const struct CadetPeerPath *p2);
150
151/**
152 * Test if a path is valid (or at least not known to be invalid).
153 *
154 * @param path Path to test.
155 *
156 * @return #GNUNET_YES If the path is valid or unknown,
157 * #GNUNET_NO If the path is known to be invalid.
158 */
159int
160path_is_valid (const struct CadetPeerPath *path);
161
162/**
163 * Destroy the path and free any allocated resources linked to it
164 *
165 * @param p the path to destroy
166 *
167 * @return GNUNET_OK on success
168 */
169int
170path_destroy (struct CadetPeerPath *p);
171
172/**
173 * Compare two paths.
174 *
175 * @param p1 First path.
176 * @param p2 Second path.
177 *
178 * @return > 0 if p1 is longer, or the first differing PEER_Id is higher on p1.
179 * < 0 if p2 is longer, or the first differing PEER_Id is higher on p2.
180 * 0 if they are identical.
181 */
182int
183path_cmp (const struct CadetPeerPath *p1, const struct CadetPeerPath *p2);
184
185/**
186 * Builds a path from a PeerIdentity array.
187 *
188 * @param peers PeerIdentity array.
189 * @param size Size of the @c peers array.
190 * @param myid ID of local peer, to find @c own_pos.
191 * @param own_pos Output parameter: own position in the path.
192 *
193 * @return Fixed and shortened path.
194 */
195struct CadetPeerPath *
196path_build_from_peer_ids (struct GNUNET_PeerIdentity *peers,
197 unsigned int size,
198 GNUNET_PEER_Id myid,
199 unsigned int *own_pos);
200
201/**
202 * Path -> allocated one line string. Caller must free.
203 *
204 * @param p Path.
205 */
206char *
207path_2s (struct CadetPeerPath *p);
208
209/**
210 * Print info about the path for debug.
211 *
212 * @param p Path to debug.
213 */
214void
215path_debug (struct CadetPeerPath *p);
216
217#if 0 /* keep Emacsens' auto-indent happy */
218{
219 #endif
220 #ifdef __cplusplus
221}
222#endif
223
224
225/* ifndef CADET_PATH_H */
226#endif
diff --git a/src/cadet/cadet_protocol.h b/src/cadet/cadet_protocol.h
index d2426addb..560c186cd 100644
--- a/src/cadet/cadet_protocol.h
+++ b/src/cadet/cadet_protocol.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2001 - 2011 GNUnet e.V. 3 Copyright (C) 2007 - 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -19,8 +19,10 @@
19*/ 19*/
20 20
21/** 21/**
22 * @author Bartlomiej Polot
23 * @file cadet/cadet_protocol.h 22 * @file cadet/cadet_protocol.h
23 * @brief P2P messages used by CADET
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
24 */ 26 */
25 27
26#ifndef CADET_PROTOCOL_H_ 28#ifndef CADET_PROTOCOL_H_
@@ -298,17 +300,10 @@ struct GNUNET_CADET_TunnelEncryptedMessage
298 */ 300 */
299 struct GNUNET_MessageHeader header; 301 struct GNUNET_MessageHeader header;
300 302
301#if NEW_CADET
302 /** 303 /**
303 * Reserved, for alignment. 304 * Reserved, for alignment.
304 */ 305 */
305 uint32_t reserved GNUNET_PACKED; 306 uint32_t reserved GNUNET_PACKED;
306#else
307 /**
308 * Maximum packet ID authorized.
309 */
310 struct CadetEncryptedMessageIdentifier cemi;
311#endif
312 307
313 /** 308 /**
314 * ID of the connection. 309 * ID of the connection.
@@ -322,89 +317,18 @@ struct GNUNET_CADET_TunnelEncryptedMessage
322 */ 317 */
323 struct GNUNET_ShortHashCode hmac; 318 struct GNUNET_ShortHashCode hmac;
324 319
325 #if NEW_CADET
326 /** 320 /**
327 * Axolotl-header that specifies which keys to use in which ratchet 321 * Axolotl-header that specifies which keys to use in which ratchet
328 * to decrypt the body that follows. 322 * to decrypt the body that follows.
329 */ 323 */
330 struct GNUNET_CADET_AxHeader ax_header; 324 struct GNUNET_CADET_AxHeader ax_header;
331#else
332 /**
333 * Number of messages sent with the current ratchet key.
334 */
335 uint32_t Ns GNUNET_PACKED;
336
337 /**
338 * Number of messages sent with the previous ratchet key.
339 */
340 uint32_t PNs GNUNET_PACKED;
341 325
342 /** 326 /**
343 * Current ratchet key.
344 */
345 struct GNUNET_CRYPTO_EcdhePublicKey DHRs;
346#endif
347 /**
348 * Encrypted content follows. 327 * Encrypted content follows.
349 */ 328 */
350}; 329};
351 330
352 331
353#ifndef NEW_CADET
354
355/**
356 * Message to query a peer about its Flow Control status regarding a tunnel.
357 *
358 * It is NOT yet clear if we need this.
359 */
360struct GNUNET_CADET_ConnectionHopByHopPollMessage
361{
362 /**
363 * Type: #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL
364 */
365 struct GNUNET_MessageHeader header;
366
367 /**
368 * Last packet sent.
369 */
370 struct CadetEncryptedMessageIdentifier cemi;
371
372 /**
373 * ID of the connection.
374 */
375 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
376
377};
378
379
380/**
381 * Message to acknowledge cadet encrypted traffic, used for
382 * flow-control on a hop-by-hop basis on the connection-level. Note
383 * that we do use the @e cemi from the tunnel layer as the connection
384 * layer's header is included/shared with the tunnel layer messages,
385 * and we only do flow control for the payload.
386 */
387struct GNUNET_CADET_ConnectionEncryptedAckMessage
388{
389 /**
390 * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK
391 */
392 struct GNUNET_MessageHeader header;
393
394 /**
395 * Maximum packet ID authorized.
396 */
397 struct CadetEncryptedMessageIdentifier cemi_max;
398
399 /**
400 * ID of the connection.
401 */
402 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
403};
404
405#endif
406
407
408/******************************************************************************/ 332/******************************************************************************/
409/******************************* CHANNEL ***********************************/ 333/******************************* CHANNEL ***********************************/
410/******************************************************************************/ 334/******************************************************************************/
@@ -450,83 +374,19 @@ struct GNUNET_CADET_ChannelManageMessage
450 */ 374 */
451 struct GNUNET_MessageHeader header; 375 struct GNUNET_MessageHeader header;
452 376
453#ifdef NEW_CADET
454 /** 377 /**
455 * For alignment. 378 * For alignment.
456 */ 379 */
457 uint32_t reserved GNUNET_PACKED; 380 uint32_t reserved GNUNET_PACKED;
458#endif
459
460 /**
461 * ID of the channel
462 */
463 struct GNUNET_CADET_ChannelTunnelNumber ctn;
464};
465
466
467#ifndef NEW_CADET
468
469/**
470 * Message for cadet data traffic.
471 */
472struct GNUNET_CADET_ChannelAppDataMessage
473{
474 /**
475 * Type: #GNUNET_MESSAGE_TYPE_CADET_UNICAST,
476 * #GNUNET_MESSAGE_TYPE_CADET_TO_ORIGIN
477 */
478 struct GNUNET_MessageHeader header;
479
480 /**
481 * Unique ID of the payload message
482 */
483 /* NEW: struct ChannelMessageIdentifier */
484 uint32_t mid GNUNET_PACKED;
485 381
486 /** 382 /**
487 * ID of the channel 383 * ID of the channel
488 */ 384 */
489 struct GNUNET_CADET_ChannelTunnelNumber ctn; 385 struct GNUNET_CADET_ChannelTunnelNumber ctn;
490
491 /**
492 * Payload follows
493 */
494}; 386};
495 387
496 388
497/** 389/**
498 * Message to acknowledge end-to-end data.
499 */
500struct GNUNET_CADET_ChannelDataAckMessage
501{
502 /**
503 * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK
504 */
505 struct GNUNET_MessageHeader header;
506
507 /**
508 * ID of the channel
509 */
510 struct GNUNET_CADET_ChannelTunnelNumber ctn;
511
512 /**
513 * Bitfield of already-received messages past @e mid.
514 * pid + 1 @ LSB
515 * pid + 64 @ MSB
516 */
517 uint64_t futures GNUNET_PACKED;
518
519 /**
520 * Last message ID received.
521 */
522 /* NEW: struct ChannelMessageIdentifier */
523 uint32_t mid GNUNET_PACKED;
524};
525
526#else
527
528
529/**
530 * Number used to uniquely identify messages in a CADET Channel. 390 * Number used to uniquely identify messages in a CADET Channel.
531 */ 391 */
532struct ChannelMessageIdentifier 392struct ChannelMessageIdentifier
@@ -595,8 +455,6 @@ struct GNUNET_CADET_ChannelDataAckMessage
595}; 455};
596 456
597 457
598#endif
599
600GNUNET_NETWORK_STRUCT_END 458GNUNET_NETWORK_STRUCT_END
601 459
602#if 0 /* keep Emacsens' auto-indent happy */ 460#if 0 /* keep Emacsens' auto-indent happy */
diff --git a/src/cadet/cadet_test_lib.c b/src/cadet/cadet_test_lib.c
index 9a70dad49..c3a1540f4 100644
--- a/src/cadet/cadet_test_lib.c
+++ b/src/cadet/cadet_test_lib.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2012 GNUnet e.V. 3 Copyright (C) 2012, 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -24,9 +24,10 @@
24 */ 24 */
25#include "platform.h" 25#include "platform.h"
26#include "gnunet_util_lib.h" 26#include "gnunet_util_lib.h"
27#include "cadet_test_lib.h" 27#include "cadet_test_lib_new.h"
28#include "gnunet_cadet_service.h" 28#include "gnunet_cadet_service.h"
29 29
30
30/** 31/**
31 * Test context for a CADET Test. 32 * Test context for a CADET Test.
32 */ 33 */
@@ -40,7 +41,7 @@ struct GNUNET_CADET_TEST_Context
40 /** 41 /**
41 * Array of handles to the CADET for each peer. 42 * Array of handles to the CADET for each peer.
42 */ 43 */
43 struct GNUNET_CADET_Handle **cadetes; 44 struct GNUNET_CADET_Handle **cadets;
44 45
45 /** 46 /**
46 * Operation associated with the connection to the CADET. 47 * Operation associated with the connection to the CADET.
@@ -48,6 +49,11 @@ struct GNUNET_CADET_TEST_Context
48 struct GNUNET_TESTBED_Operation **ops; 49 struct GNUNET_TESTBED_Operation **ops;
49 50
50 /** 51 /**
52 * Number of peers running, size of the arrays above.
53 */
54 unsigned int num_peers;
55
56 /**
51 * Main function of the test to run once all CADETs are available. 57 * Main function of the test to run once all CADETs are available.
52 */ 58 */
53 GNUNET_CADET_TEST_AppMain app_main; 59 GNUNET_CADET_TEST_AppMain app_main;
@@ -58,30 +64,35 @@ struct GNUNET_CADET_TEST_Context
58 void *app_main_cls; 64 void *app_main_cls;
59 65
60 /** 66 /**
61 * Number of peers running, size of the arrays above. 67 * Handler for incoming tunnels.
62 */ 68 */
63 unsigned int num_peers; 69 GNUNET_CADET_ConnectEventHandler connects;
64 70
65 /** 71 /**
66 * Handler for incoming tunnels. 72 * Function called when the transmit window size changes.
67 */ 73 */
68 GNUNET_CADET_InboundChannelNotificationHandler *new_channel; 74 GNUNET_CADET_WindowSizeEventHandler window_changes;
69 75
70 /** 76 /**
71 * Cleaner for destroyed incoming tunnels. 77 * Cleaner for destroyed incoming tunnels.
72 */ 78 */
73 GNUNET_CADET_ChannelEndHandler *cleaner; 79 GNUNET_CADET_DisconnectEventHandler disconnects;
74 80
75 /** 81 /**
76 * Message handlers. 82 * Message handlers.
77 */ 83 */
78 struct GNUNET_CADET_MessageHandler* handlers; 84 struct GNUNET_MQ_MessageHandler *handlers;
79 85
80 /** 86 /**
81 * Application ports. 87 * Application ports.
82 */ 88 */
83 const struct GNUNET_HashCode **ports; 89 const struct GNUNET_HashCode **ports;
84 90
91 /**
92 * Number of ports in #ports.
93 */
94 unsigned int port_count;
95
85}; 96};
86 97
87 98
@@ -94,6 +105,11 @@ struct GNUNET_CADET_TEST_AdapterContext
94 * Peer number for the particular peer. 105 * Peer number for the particular peer.
95 */ 106 */
96 unsigned int peer; 107 unsigned int peer;
108
109 /**
110 * Port handlers for open ports.
111 */
112 struct GNUNET_CADET_Port **ports;
97 113
98 /** 114 /**
99 * General context. 115 * General context.
@@ -114,26 +130,28 @@ struct GNUNET_CADET_TEST_AdapterContext
114 */ 130 */
115static void * 131static void *
116cadet_connect_adapter (void *cls, 132cadet_connect_adapter (void *cls,
117 const struct GNUNET_CONFIGURATION_Handle *cfg) 133 const struct GNUNET_CONFIGURATION_Handle *cfg)
118{ 134{
119 struct GNUNET_CADET_TEST_AdapterContext *actx = cls; 135 struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
120 struct GNUNET_CADET_TEST_Context *ctx = actx->ctx; 136 struct GNUNET_CADET_TEST_Context *ctx = actx->ctx;
121 struct GNUNET_CADET_Handle *h; 137 struct GNUNET_CADET_Handle *h;
138 unsigned int i;
122 139
123 h = GNUNET_CADET_connect (cfg, 140 h = GNUNET_CADET_connecT (cfg);
124 (void *) (long) actx->peer,
125 ctx->cleaner,
126 ctx->handlers);
127 if (NULL == ctx->ports) 141 if (NULL == ctx->ports)
128 return h; 142 return h;
129 143
130 for (int i = 0; NULL != ctx->ports[i]; i++) 144 actx->ports = GNUNET_new_array (ctx->port_count, struct GNUNET_CADET_Port *);
145 for (i = 0; i < ctx->port_count; i++)
131 { 146 {
132 (void ) GNUNET_CADET_open_port (h, ctx->ports[i], 147 actx->ports[i] = GNUNET_CADET_open_porT (h,
133 ctx->new_channel, 148 ctx->ports[i],
134 (void *) (long) actx->peer); 149 ctx->connects,
150 (void *) (long) actx->peer,
151 ctx->window_changes,
152 ctx->disconnects,
153 ctx->handlers);
135 } 154 }
136
137 return h; 155 return h;
138} 156}
139 157
@@ -152,6 +170,15 @@ cadet_disconnect_adapter (void *cls,
152 struct GNUNET_CADET_Handle *cadet = op_result; 170 struct GNUNET_CADET_Handle *cadet = op_result;
153 struct GNUNET_CADET_TEST_AdapterContext *actx = cls; 171 struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
154 172
173 if (NULL != actx->ports)
174 {
175 for (int i = 0; i < actx->ctx->port_count; i++)
176 {
177 GNUNET_CADET_close_port (actx->ports[i]);
178 actx->ports[i] = NULL;
179 }
180 GNUNET_free (actx->ports);
181 }
155 GNUNET_free (actx); 182 GNUNET_free (actx);
156 GNUNET_CADET_disconnect (cadet); 183 GNUNET_CADET_disconnect (cadet);
157} 184}
@@ -186,18 +213,18 @@ cadet_connect_cb (void *cls,
186 for (i = 0; i < ctx->num_peers; i++) 213 for (i = 0; i < ctx->num_peers; i++)
187 if (op == ctx->ops[i]) 214 if (op == ctx->ops[i])
188 { 215 {
189 ctx->cadetes[i] = ca_result; 216 ctx->cadets[i] = ca_result;
190 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "...cadet %u connected\n", i); 217 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "...cadet %u connected\n", i);
191 } 218 }
192 for (i = 0; i < ctx->num_peers; i++) 219 for (i = 0; i < ctx->num_peers; i++)
193 if (NULL == ctx->cadetes[i]) 220 if (NULL == ctx->cadets[i])
194 return; /* still some CADET connections missing */ 221 return; /* still some CADET connections missing */
195 /* all CADET connections ready! */ 222 /* all CADET connections ready! */
196 ctx->app_main (ctx->app_main_cls, 223 ctx->app_main (ctx->app_main_cls,
197 ctx, 224 ctx,
198 ctx->num_peers, 225 ctx->num_peers,
199 ctx->peers, 226 ctx->peers,
200 ctx->cadetes); 227 ctx->cadets);
201} 228}
202 229
203 230
@@ -213,7 +240,7 @@ GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx)
213 ctx->ops[i] = NULL; 240 ctx->ops[i] = NULL;
214 } 241 }
215 GNUNET_free (ctx->ops); 242 GNUNET_free (ctx->ops);
216 GNUNET_free (ctx->cadetes); 243 GNUNET_free (ctx->cadets);
217 GNUNET_free (ctx); 244 GNUNET_free (ctx);
218 GNUNET_SCHEDULER_shutdown (); 245 GNUNET_SCHEDULER_shutdown ();
219} 246}
@@ -243,12 +270,23 @@ cadet_test_run (void *cls,
243 struct GNUNET_CADET_TEST_Context *ctx = cls; 270 struct GNUNET_CADET_TEST_Context *ctx = cls;
244 unsigned int i; 271 unsigned int i;
245 272
273 if (0 != links_failed)
274 {
275 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Some links failed (%u), ending\n",
276 links_failed);
277 exit (2);
278 }
279
246 if (num_peers != ctx->num_peers) 280 if (num_peers != ctx->num_peers)
247 { 281 {
248 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers started %u/%u, ending\n", 282 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers started %u/%u, ending\n",
249 num_peers, ctx->num_peers); 283 num_peers, ctx->num_peers);
250 exit (1); 284 exit (1);
251 } 285 }
286
287 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
288 "Testbed up, %u peers and %u links\n",
289 num_peers, links_succeeded);
252 ctx->peers = peers; 290 ctx->peers = peers;
253 for (i = 0; i < num_peers; i++) 291 for (i = 0; i < num_peers; i++)
254 { 292 {
@@ -270,31 +308,52 @@ cadet_test_run (void *cls,
270} 308}
271 309
272 310
311/**
312 * Run a test using the given name, configuration file and number of peers.
313 * All cadet callbacks will receive the peer number (long) as the closure.
314 *
315 * @param testname Name of the test (for logging).
316 * @param cfgfile Name of the configuration file.
317 * @param num_peers Number of peers to start.
318 * @param tmain Main function to run once the testbed is ready.
319 * @param tmain_cls Closure for @a tmain.
320 * @param connects Handler for incoming channels.
321 * @param window_changes Handler for the window size change notification.
322 * @param disconnects Cleaner for destroyed incoming channels.
323 * @param handlers Message handlers.
324 * @param ports Ports the peers offer, NULL-terminated.
325 */
273void 326void
274GNUNET_CADET_TEST_run (const char *testname, 327GNUNET_CADET_TEST_ruN (const char *testname,
275 const char *cfgname, 328 const char *cfgfile,
276 unsigned int num_peers, 329 unsigned int num_peers,
277 GNUNET_CADET_TEST_AppMain tmain, 330 GNUNET_CADET_TEST_AppMain tmain,
278 void *tmain_cls, 331 void *tmain_cls,
279 GNUNET_CADET_InboundChannelNotificationHandler new_channel, 332 GNUNET_CADET_ConnectEventHandler connects,
280 GNUNET_CADET_ChannelEndHandler cleaner, 333 GNUNET_CADET_WindowSizeEventHandler window_changes,
281 struct GNUNET_CADET_MessageHandler* handlers, 334 GNUNET_CADET_DisconnectEventHandler disconnects,
282 const struct GNUNET_HashCode **ports) 335 struct GNUNET_MQ_MessageHandler *handlers,
336 const struct GNUNET_HashCode **ports)
283{ 337{
284 struct GNUNET_CADET_TEST_Context *ctx; 338 struct GNUNET_CADET_TEST_Context *ctx;
285 339
286 ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context); 340 ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context);
287 ctx->num_peers = num_peers; 341 ctx->num_peers = num_peers;
288 ctx->ops = GNUNET_malloc (num_peers * sizeof (struct GNUNET_TESTBED_Operation *)); 342 ctx->ops = GNUNET_new_array (num_peers, struct GNUNET_TESTBED_Operation *);
289 ctx->cadetes = GNUNET_malloc (num_peers * sizeof (struct GNUNET_CADET_Handle *)); 343 ctx->cadets = GNUNET_new_array (num_peers, struct GNUNET_CADET_Handle *);
290 ctx->app_main = tmain; 344 ctx->app_main = tmain;
291 ctx->app_main_cls = tmain_cls; 345 ctx->app_main_cls = tmain_cls;
292 ctx->new_channel = new_channel; 346 ctx->connects = connects;
293 ctx->cleaner = cleaner; 347 ctx->window_changes = window_changes;
294 ctx->handlers = handlers; 348 ctx->disconnects = disconnects;
349 ctx->handlers = GNUNET_MQ_copy_handlers (handlers);
295 ctx->ports = ports; 350 ctx->ports = ports;
351 ctx->port_count = 0;
352 while (NULL != ctx->ports[ctx->port_count])
353 ctx->port_count++;
354
296 GNUNET_TESTBED_test_run (testname, 355 GNUNET_TESTBED_test_run (testname,
297 cfgname, 356 cfgfile,
298 num_peers, 357 num_peers,
299 0LL, NULL, NULL, 358 0LL, NULL, NULL,
300 &cadet_test_run, ctx); 359 &cadet_test_run, ctx);
diff --git a/src/cadet/cadet_test_lib.h b/src/cadet/cadet_test_lib.h
index 464977d42..4b3a6b18d 100644
--- a/src/cadet/cadet_test_lib.h
+++ b/src/cadet/cadet_test_lib.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2012 GNUnet e.V. 3 Copyright (C) 2012,2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -49,41 +49,41 @@ struct GNUNET_CADET_TEST_Context;
49 * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end. 49 * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end.
50 * @param num_peers Number of peers that are running. 50 * @param num_peers Number of peers that are running.
51 * @param peers Array of peers. 51 * @param peers Array of peers.
52 * @param cadetes Handle to each of the CADETs of the peers. 52 * @param cadets Handle to each of the CADETs of the peers.
53 */ 53 */
54typedef void (*GNUNET_CADET_TEST_AppMain) (void *cls, 54typedef void (*GNUNET_CADET_TEST_AppMain) (void *cls,
55 struct GNUNET_CADET_TEST_Context *ctx, 55 struct GNUNET_CADET_TEST_Context *ctx,
56 unsigned int num_peers, 56 unsigned int num_peers,
57 struct GNUNET_TESTBED_Peer **peers, 57 struct GNUNET_TESTBED_Peer **peers,
58 struct GNUNET_CADET_Handle **cadetes); 58 struct GNUNET_CADET_Handle **cadets);
59 59
60 60
61/** 61/**
62 * Run a test using the given name, configuration file and number of 62 * Run a test using the given name, configuration file and number of peers.
63 * peers. 63 * All cadet callbacks will receive the peer number (long) as the closure.
64 * All cadet callbacks will receive the peer number as the closure.
65 * 64 *
66 * @param testname Name of the test (for logging). 65 * @param testname Name of the test (for logging).
67 * @param cfgname Name of the configuration file. 66 * @param cfgfile Name of the configuration file.
68 * @param num_peers Number of peers to start. 67 * @param num_peers Number of peers to start.
69 * @param tmain Main function to run once the testbed is ready. 68 * @param tmain Main function to run once the testbed is ready.
70 * @param tmain_cls Closure for 'tmain'. 69 * @param tmain_cls Closure for @a tmain.
71 * @param new_channel Handler for incoming tunnels. 70 * @param connects Handler for incoming channels.
72 * @param cleaner Cleaner for destroyed incoming tunnels. 71 * @param window_changes Handler for the window size change notification.
72 * @param disconnects Cleaner for destroyed incoming channels.
73 * @param handlers Message handlers. 73 * @param handlers Message handlers.
74 * @param ports Ports the peers offer, NULL-terminated. 74 * @param ports Ports the peers offer, NULL-terminated.
75 */ 75 */
76void 76void
77GNUNET_CADET_TEST_run (const char *testname, 77GNUNET_CADET_TEST_ruN (const char *testname,
78 const char *cfgname, 78 const char *cfgfile,
79 unsigned int num_peers, 79 unsigned int num_peers,
80 GNUNET_CADET_TEST_AppMain tmain, 80 GNUNET_CADET_TEST_AppMain tmain,
81 void *tmain_cls, 81 void *tmain_cls,
82 GNUNET_CADET_InboundChannelNotificationHandler new_channel, 82 GNUNET_CADET_ConnectEventHandler connects,
83 GNUNET_CADET_ChannelEndHandler cleaner, 83 GNUNET_CADET_WindowSizeEventHandler window_changes,
84 struct GNUNET_CADET_MessageHandler* handlers, 84 GNUNET_CADET_DisconnectEventHandler disconnects,
85 const struct GNUNET_HashCode **ports); 85 struct GNUNET_MQ_MessageHandler *handlers,
86 86 const struct GNUNET_HashCode **ports);
87 87
88/** 88/**
89 * Clean up the testbed. 89 * Clean up the testbed.
diff --git a/src/cadet/cadet_test_lib_new.c b/src/cadet/cadet_test_lib_new.c
deleted file mode 100644
index c3a1540f4..000000000
--- a/src/cadet/cadet_test_lib_new.c
+++ /dev/null
@@ -1,362 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file cadet/cadet_test_lib.c
22 * @author Bartlomiej Polot
23 * @brief library for writing CADET tests
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "cadet_test_lib_new.h"
28#include "gnunet_cadet_service.h"
29
30
31/**
32 * Test context for a CADET Test.
33 */
34struct GNUNET_CADET_TEST_Context
35{
36 /**
37 * Array of running peers.
38 */
39 struct GNUNET_TESTBED_Peer **peers;
40
41 /**
42 * Array of handles to the CADET for each peer.
43 */
44 struct GNUNET_CADET_Handle **cadets;
45
46 /**
47 * Operation associated with the connection to the CADET.
48 */
49 struct GNUNET_TESTBED_Operation **ops;
50
51 /**
52 * Number of peers running, size of the arrays above.
53 */
54 unsigned int num_peers;
55
56 /**
57 * Main function of the test to run once all CADETs are available.
58 */
59 GNUNET_CADET_TEST_AppMain app_main;
60
61 /**
62 * Closure for 'app_main'.
63 */
64 void *app_main_cls;
65
66 /**
67 * Handler for incoming tunnels.
68 */
69 GNUNET_CADET_ConnectEventHandler connects;
70
71 /**
72 * Function called when the transmit window size changes.
73 */
74 GNUNET_CADET_WindowSizeEventHandler window_changes;
75
76 /**
77 * Cleaner for destroyed incoming tunnels.
78 */
79 GNUNET_CADET_DisconnectEventHandler disconnects;
80
81 /**
82 * Message handlers.
83 */
84 struct GNUNET_MQ_MessageHandler *handlers;
85
86 /**
87 * Application ports.
88 */
89 const struct GNUNET_HashCode **ports;
90
91 /**
92 * Number of ports in #ports.
93 */
94 unsigned int port_count;
95
96};
97
98
99/**
100 * Context for a cadet adapter callback.
101 */
102struct GNUNET_CADET_TEST_AdapterContext
103{
104 /**
105 * Peer number for the particular peer.
106 */
107 unsigned int peer;
108
109 /**
110 * Port handlers for open ports.
111 */
112 struct GNUNET_CADET_Port **ports;
113
114 /**
115 * General context.
116 */
117 struct GNUNET_CADET_TEST_Context *ctx;
118};
119
120
121/**
122 * Adapter function called to establish a connection to
123 * the CADET service.
124 *
125 * @param cls closure
126 * @param cfg configuration of the peer to connect to; will be available until
127 * GNUNET_TESTBED_operation_done() is called on the operation returned
128 * from GNUNET_TESTBED_service_connect()
129 * @return service handle to return in 'op_result', NULL on error
130 */
131static void *
132cadet_connect_adapter (void *cls,
133 const struct GNUNET_CONFIGURATION_Handle *cfg)
134{
135 struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
136 struct GNUNET_CADET_TEST_Context *ctx = actx->ctx;
137 struct GNUNET_CADET_Handle *h;
138 unsigned int i;
139
140 h = GNUNET_CADET_connecT (cfg);
141 if (NULL == ctx->ports)
142 return h;
143
144 actx->ports = GNUNET_new_array (ctx->port_count, struct GNUNET_CADET_Port *);
145 for (i = 0; i < ctx->port_count; i++)
146 {
147 actx->ports[i] = GNUNET_CADET_open_porT (h,
148 ctx->ports[i],
149 ctx->connects,
150 (void *) (long) actx->peer,
151 ctx->window_changes,
152 ctx->disconnects,
153 ctx->handlers);
154 }
155 return h;
156}
157
158
159/**
160 * Adapter function called to destroy a connection to
161 * the CADET service.
162 *
163 * @param cls closure
164 * @param op_result service handle returned from the connect adapter
165 */
166static void
167cadet_disconnect_adapter (void *cls,
168 void *op_result)
169{
170 struct GNUNET_CADET_Handle *cadet = op_result;
171 struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
172
173 if (NULL != actx->ports)
174 {
175 for (int i = 0; i < actx->ctx->port_count; i++)
176 {
177 GNUNET_CADET_close_port (actx->ports[i]);
178 actx->ports[i] = NULL;
179 }
180 GNUNET_free (actx->ports);
181 }
182 GNUNET_free (actx);
183 GNUNET_CADET_disconnect (cadet);
184}
185
186
187/**
188 * Callback to be called when a service connect operation is completed.
189 *
190 * @param cls The callback closure from functions generating an operation.
191 * @param op The operation that has been finished.
192 * @param ca_result The service handle returned from
193 * GNUNET_TESTBED_ConnectAdapter() (cadet handle).
194 * @param emsg Error message in case the operation has failed.
195 * NULL if operation has executed successfully.
196 */
197static void
198cadet_connect_cb (void *cls,
199 struct GNUNET_TESTBED_Operation *op,
200 void *ca_result,
201 const char *emsg)
202{
203 struct GNUNET_CADET_TEST_Context *ctx = cls;
204 unsigned int i;
205
206 if (NULL != emsg)
207 {
208 fprintf (stderr, "Failed to connect to CADET service: %s\n",
209 emsg);
210 GNUNET_SCHEDULER_shutdown ();
211 return;
212 }
213 for (i = 0; i < ctx->num_peers; i++)
214 if (op == ctx->ops[i])
215 {
216 ctx->cadets[i] = ca_result;
217 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "...cadet %u connected\n", i);
218 }
219 for (i = 0; i < ctx->num_peers; i++)
220 if (NULL == ctx->cadets[i])
221 return; /* still some CADET connections missing */
222 /* all CADET connections ready! */
223 ctx->app_main (ctx->app_main_cls,
224 ctx,
225 ctx->num_peers,
226 ctx->peers,
227 ctx->cadets);
228}
229
230
231void
232GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx)
233{
234 unsigned int i;
235
236 for (i = 0; i < ctx->num_peers; i++)
237 {
238 GNUNET_assert (NULL != ctx->ops[i]);
239 GNUNET_TESTBED_operation_done (ctx->ops[i]);
240 ctx->ops[i] = NULL;
241 }
242 GNUNET_free (ctx->ops);
243 GNUNET_free (ctx->cadets);
244 GNUNET_free (ctx);
245 GNUNET_SCHEDULER_shutdown ();
246}
247
248
249/**
250 * Callback run when the testbed is ready (peers running and connected to
251 * each other)
252 *
253 * @param cls Closure (context).
254 * @param h the run handle
255 * @param num_peers Number of peers that are running.
256 * @param peers Handles to each one of the @c num_peers peers.
257 * @param links_succeeded the number of overlay link connection attempts that
258 * succeeded
259 * @param links_failed the number of overlay link connection attempts that
260 * failed
261 */
262static void
263cadet_test_run (void *cls,
264 struct GNUNET_TESTBED_RunHandle *h,
265 unsigned int num_peers,
266 struct GNUNET_TESTBED_Peer **peers,
267 unsigned int links_succeeded,
268 unsigned int links_failed)
269{
270 struct GNUNET_CADET_TEST_Context *ctx = cls;
271 unsigned int i;
272
273 if (0 != links_failed)
274 {
275 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Some links failed (%u), ending\n",
276 links_failed);
277 exit (2);
278 }
279
280 if (num_peers != ctx->num_peers)
281 {
282 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers started %u/%u, ending\n",
283 num_peers, ctx->num_peers);
284 exit (1);
285 }
286
287 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
288 "Testbed up, %u peers and %u links\n",
289 num_peers, links_succeeded);
290 ctx->peers = peers;
291 for (i = 0; i < num_peers; i++)
292 {
293 struct GNUNET_CADET_TEST_AdapterContext *newctx;
294 newctx = GNUNET_new (struct GNUNET_CADET_TEST_AdapterContext);
295 newctx->peer = i;
296 newctx->ctx = ctx;
297 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to cadet %u\n", i);
298 ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
299 peers[i],
300 "cadet",
301 &cadet_connect_cb,
302 ctx,
303 &cadet_connect_adapter,
304 &cadet_disconnect_adapter,
305 newctx);
306 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "op handle %p\n", ctx->ops[i]);
307 }
308}
309
310
311/**
312 * Run a test using the given name, configuration file and number of peers.
313 * All cadet callbacks will receive the peer number (long) as the closure.
314 *
315 * @param testname Name of the test (for logging).
316 * @param cfgfile Name of the configuration file.
317 * @param num_peers Number of peers to start.
318 * @param tmain Main function to run once the testbed is ready.
319 * @param tmain_cls Closure for @a tmain.
320 * @param connects Handler for incoming channels.
321 * @param window_changes Handler for the window size change notification.
322 * @param disconnects Cleaner for destroyed incoming channels.
323 * @param handlers Message handlers.
324 * @param ports Ports the peers offer, NULL-terminated.
325 */
326void
327GNUNET_CADET_TEST_ruN (const char *testname,
328 const char *cfgfile,
329 unsigned int num_peers,
330 GNUNET_CADET_TEST_AppMain tmain,
331 void *tmain_cls,
332 GNUNET_CADET_ConnectEventHandler connects,
333 GNUNET_CADET_WindowSizeEventHandler window_changes,
334 GNUNET_CADET_DisconnectEventHandler disconnects,
335 struct GNUNET_MQ_MessageHandler *handlers,
336 const struct GNUNET_HashCode **ports)
337{
338 struct GNUNET_CADET_TEST_Context *ctx;
339
340 ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context);
341 ctx->num_peers = num_peers;
342 ctx->ops = GNUNET_new_array (num_peers, struct GNUNET_TESTBED_Operation *);
343 ctx->cadets = GNUNET_new_array (num_peers, struct GNUNET_CADET_Handle *);
344 ctx->app_main = tmain;
345 ctx->app_main_cls = tmain_cls;
346 ctx->connects = connects;
347 ctx->window_changes = window_changes;
348 ctx->disconnects = disconnects;
349 ctx->handlers = GNUNET_MQ_copy_handlers (handlers);
350 ctx->ports = ports;
351 ctx->port_count = 0;
352 while (NULL != ctx->ports[ctx->port_count])
353 ctx->port_count++;
354
355 GNUNET_TESTBED_test_run (testname,
356 cfgfile,
357 num_peers,
358 0LL, NULL, NULL,
359 &cadet_test_run, ctx);
360}
361
362/* end of cadet_test_lib.c */
diff --git a/src/cadet/cadet_test_lib_new.h b/src/cadet/cadet_test_lib_new.h
deleted file mode 100644
index 4b3a6b18d..000000000
--- a/src/cadet/cadet_test_lib_new.h
+++ /dev/null
@@ -1,106 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012,2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file cadet/cadet_test_lib.h
22 * @author Bartlomiej Polot
23 * @brief library for writing CADET tests
24 */
25#ifndef CADET_TEST_LIB_H
26#define CADET_TEST_LIB_H
27
28#ifdef __cplusplus
29extern "C"
30{
31#if 0 /* keep Emacsens' auto-indent happy */
32}
33#endif
34#endif
35
36#include "gnunet_testbed_service.h"
37#include "gnunet_cadet_service.h"
38
39/**
40 * Test context for a CADET Test.
41 */
42struct GNUNET_CADET_TEST_Context;
43
44
45/**
46 * Main function of a CADET test.
47 *
48 * @param cls Closure.
49 * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end.
50 * @param num_peers Number of peers that are running.
51 * @param peers Array of peers.
52 * @param cadets Handle to each of the CADETs of the peers.
53 */
54typedef void (*GNUNET_CADET_TEST_AppMain) (void *cls,
55 struct GNUNET_CADET_TEST_Context *ctx,
56 unsigned int num_peers,
57 struct GNUNET_TESTBED_Peer **peers,
58 struct GNUNET_CADET_Handle **cadets);
59
60
61/**
62 * Run a test using the given name, configuration file and number of peers.
63 * All cadet callbacks will receive the peer number (long) as the closure.
64 *
65 * @param testname Name of the test (for logging).
66 * @param cfgfile Name of the configuration file.
67 * @param num_peers Number of peers to start.
68 * @param tmain Main function to run once the testbed is ready.
69 * @param tmain_cls Closure for @a tmain.
70 * @param connects Handler for incoming channels.
71 * @param window_changes Handler for the window size change notification.
72 * @param disconnects Cleaner for destroyed incoming channels.
73 * @param handlers Message handlers.
74 * @param ports Ports the peers offer, NULL-terminated.
75 */
76void
77GNUNET_CADET_TEST_ruN (const char *testname,
78 const char *cfgfile,
79 unsigned int num_peers,
80 GNUNET_CADET_TEST_AppMain tmain,
81 void *tmain_cls,
82 GNUNET_CADET_ConnectEventHandler connects,
83 GNUNET_CADET_WindowSizeEventHandler window_changes,
84 GNUNET_CADET_DisconnectEventHandler disconnects,
85 struct GNUNET_MQ_MessageHandler *handlers,
86 const struct GNUNET_HashCode **ports);
87
88/**
89 * Clean up the testbed.
90 *
91 * @param ctx handle for the testbed
92 */
93void
94GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx);
95
96
97#if 0 /* keep Emacsens' auto-indent happy */
98{
99#endif
100#ifdef __cplusplus
101}
102#endif
103
104
105/* ifndef CADET_TEST_LIB_H */
106#endif
diff --git a/src/cadet/gnunet-service-cadet-new.c b/src/cadet/gnunet-service-cadet-new.c
deleted file mode 100644
index 93f53de4c..000000000
--- a/src/cadet/gnunet-service-cadet-new.c
+++ /dev/null
@@ -1,1496 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2013, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/gnunet-service-cadet-new.c
23 * @brief GNUnet CADET service with encryption
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * Dictionary:
28 * - peer: other cadet instance. If there is direct connection it's a neighbor.
29 * - path: series of directly connected peer from one peer to another.
30 * - connection: path which is being used in a tunnel.
31 * - tunnel: encrypted connection to a peer, neighbor or not.
32 * - channel: logical link between two clients, on the same or different peers.
33 * have properties like reliability.
34 */
35
36#include "platform.h"
37#include "gnunet_util_lib.h"
38#include "cadet.h"
39#include "gnunet_statistics_service.h"
40#include "gnunet-service-cadet-new.h"
41#include "gnunet-service-cadet-new_channel.h"
42#include "gnunet-service-cadet-new_connection.h"
43#include "gnunet-service-cadet-new_core.h"
44#include "gnunet-service-cadet-new_dht.h"
45#include "gnunet-service-cadet-new_hello.h"
46#include "gnunet-service-cadet-new_tunnels.h"
47#include "gnunet-service-cadet-new_peer.h"
48#include "gnunet-service-cadet-new_paths.h"
49
50#define LOG(level, ...) GNUNET_log (level,__VA_ARGS__)
51
52
53/**
54 * Struct containing information about a client of the service
55 */
56struct CadetClient
57{
58 /**
59 * Linked list next
60 */
61 struct CadetClient *next;
62
63 /**
64 * Linked list prev
65 */
66 struct CadetClient *prev;
67
68 /**
69 * Tunnels that belong to this client, indexed by local id,
70 * value is a `struct CadetChannel`.
71 */
72 struct GNUNET_CONTAINER_MultiHashMap32 *channels;
73
74 /**
75 * Handle to communicate with the client
76 */
77 struct GNUNET_MQ_Handle *mq;
78
79 /**
80 * Client handle.
81 */
82 struct GNUNET_SERVICE_Client *client;
83
84 /**
85 * Ports that this client has declared interest in.
86 * Indexed by port, contains *Client.
87 */
88 struct GNUNET_CONTAINER_MultiHashMap *ports;
89
90 /**
91 * Channel ID to use for the next incoming channel for this client.
92 * Wraps around (in theory).
93 */
94 struct GNUNET_CADET_ClientChannelNumber next_ccn;
95
96 /**
97 * ID of the client, mainly for debug messages. Purely internal to this file.
98 */
99 unsigned int id;
100};
101
102/******************************************************************************/
103/*********************** GLOBAL VARIABLES ****************************/
104/******************************************************************************/
105
106/****************************** Global variables ******************************/
107
108/**
109 * Handle to our configuration.
110 */
111const struct GNUNET_CONFIGURATION_Handle *cfg;
112
113/**
114 * Handle to the statistics service.
115 */
116struct GNUNET_STATISTICS_Handle *stats;
117
118/**
119 * Handle to communicate with ATS.
120 */
121struct GNUNET_ATS_ConnectivityHandle *ats_ch;
122
123/**
124 * Local peer own ID.
125 */
126struct GNUNET_PeerIdentity my_full_id;
127
128/**
129 * Own private key.
130 */
131struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
132
133/**
134 * Signal that shutdown is happening: prevent recovery measures.
135 */
136int shutting_down;
137
138/**
139 * DLL with all the clients, head.
140 */
141static struct CadetClient *clients_head;
142
143/**
144 * DLL with all the clients, tail.
145 */
146static struct CadetClient *clients_tail;
147
148/**
149 * Next ID to assign to a client.
150 */
151static unsigned int next_client_id;
152
153/**
154 * All ports clients of this peer have opened.
155 */
156struct GNUNET_CONTAINER_MultiHashMap *open_ports;
157
158/**
159 * Map from ports to channels where the ports were closed at the
160 * time we got the inbound connection.
161 * Indexed by port, contains `struct CadetChannel`.
162 */
163struct GNUNET_CONTAINER_MultiHashMap *loose_channels;
164
165/**
166 * Map from PIDs to `struct CadetPeer` entries.
167 */
168struct GNUNET_CONTAINER_MultiPeerMap *peers;
169
170/**
171 * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier`
172 * hash codes to `struct CadetConnection` objects.
173 */
174struct GNUNET_CONTAINER_MultiShortmap *connections;
175
176/**
177 * How many messages are needed to trigger an AXOLOTL ratchet advance.
178 */
179unsigned long long ratchet_messages;
180
181/**
182 * How long until we trigger a ratched advance due to time.
183 */
184struct GNUNET_TIME_Relative ratchet_time;
185
186/**
187 * How frequently do we send KEEPALIVE messages on idle connections?
188 */
189struct GNUNET_TIME_Relative keepalive_period;
190
191/**
192 * Set to non-zero values to create random drops to test retransmissions.
193 */
194unsigned long long drop_percent;
195
196
197/**
198 * Send a message to a client.
199 *
200 * @param c client to get the message
201 * @param env envelope with the message
202 */
203void
204GSC_send_to_client (struct CadetClient *c,
205 struct GNUNET_MQ_Envelope *env)
206{
207 GNUNET_MQ_send (c->mq,
208 env);
209}
210
211
212/**
213 * Return identifier for a client as a string.
214 *
215 * @param c client to identify
216 * @return string for debugging
217 */
218const char *
219GSC_2s (struct CadetClient *c)
220{
221 static char buf[32];
222
223 GNUNET_snprintf (buf,
224 sizeof (buf),
225 "Client(%u)",
226 c->id);
227 return buf;
228}
229
230
231/**
232 * Lookup channel of client @a c by @a ccn.
233 *
234 * @param c client to look in
235 * @param ccn channel ID to look up
236 * @return NULL if no such channel exists
237 */
238static struct CadetChannel *
239lookup_channel (struct CadetClient *c,
240 struct GNUNET_CADET_ClientChannelNumber ccn)
241{
242 return GNUNET_CONTAINER_multihashmap32_get (c->channels,
243 ntohl (ccn.channel_of_client));
244}
245
246
247/**
248 * Obtain the next LID to use for incoming connections to
249 * the given client.
250 *
251 * @param c client handle
252 */
253static struct GNUNET_CADET_ClientChannelNumber
254client_get_next_ccn (struct CadetClient *c)
255{
256 struct GNUNET_CADET_ClientChannelNumber ccn = c->next_ccn;
257
258 /* increment until we have a free one... */
259 while (NULL !=
260 lookup_channel (c,
261 ccn))
262 {
263 ccn.channel_of_client
264 = htonl (1 + (ntohl (ccn.channel_of_client)));
265 if (ntohl (ccn.channel_of_client) >=
266 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
267 ccn.channel_of_client = htonl (0);
268 }
269 c->next_ccn.channel_of_client
270 = htonl (1 + (ntohl (ccn.channel_of_client)));
271 return ccn;
272}
273
274
275/**
276 * Bind incoming channel to this client, and notify client about
277 * incoming connection. Caller is responsible for notifying the other
278 * peer about our acceptance of the channel.
279 *
280 * @param c client to bind to
281 * @param ch channel to be bound
282 * @param dest peer that establishes the connection
283 * @param port port number
284 * @param options options
285 * @return local channel number assigned to the new client
286 */
287struct GNUNET_CADET_ClientChannelNumber
288GSC_bind (struct CadetClient *c,
289 struct CadetChannel *ch,
290 struct CadetPeer *dest,
291 const struct GNUNET_HashCode *port,
292 uint32_t options)
293{
294 struct GNUNET_MQ_Envelope *env;
295 struct GNUNET_CADET_LocalChannelCreateMessage *cm;
296 struct GNUNET_CADET_ClientChannelNumber ccn;
297
298 ccn = client_get_next_ccn (c);
299 GNUNET_assert (GNUNET_YES ==
300 GNUNET_CONTAINER_multihashmap32_put (c->channels,
301 ntohl (ccn.channel_of_client),
302 ch,
303 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
304 LOG (GNUNET_ERROR_TYPE_DEBUG,
305 "Accepting incoming %s from %s on open port %s (%u), assigning ccn %X\n",
306 GCCH_2s (ch),
307 GCP_2s (dest),
308 GNUNET_h2s (port),
309 (uint32_t) ntohl (options),
310 (uint32_t) ntohl (ccn.channel_of_client));
311 /* notify local client about incoming connection! */
312 env = GNUNET_MQ_msg (cm,
313 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
314 cm->ccn = ccn;
315 cm->port = *port;
316 cm->opt = htonl (options);
317 cm->peer = *GCP_get_id (dest);
318 GSC_send_to_client (c,
319 env);
320 return ccn;
321}
322
323
324/**
325 * Callback invoked on all peers to destroy all tunnels
326 * that may still exist.
327 *
328 * @param cls NULL
329 * @param pid identify of a peer
330 * @param value a `struct CadetPeer` that may still have a tunnel
331 * @return #GNUNET_OK (iterate over all entries)
332 */
333static int
334destroy_tunnels_now (void *cls,
335 const struct GNUNET_PeerIdentity *pid,
336 void *value)
337{
338 struct CadetPeer *cp = value;
339 struct CadetTunnel *t = GCP_get_tunnel (cp,
340 GNUNET_NO);
341
342 if (NULL != t)
343 GCT_destroy_tunnel_now (t);
344 return GNUNET_OK;
345}
346
347
348/**
349 * Callback invoked on all peers to destroy all tunnels
350 * that may still exist.
351 *
352 * @param cls NULL
353 * @param pid identify of a peer
354 * @param value a `struct CadetPeer` that may still have a tunnel
355 * @return #GNUNET_OK (iterate over all entries)
356 */
357static int
358destroy_paths_now (void *cls,
359 const struct GNUNET_PeerIdentity *pid,
360 void *value)
361{
362 struct CadetPeer *cp = value;
363
364 GCP_drop_owned_paths (cp);
365 return GNUNET_OK;
366}
367
368
369/**
370 * Shutdown everything once the clients have disconnected.
371 */
372static void
373shutdown_rest ()
374{
375 if (NULL != stats)
376 {
377 GNUNET_STATISTICS_destroy (stats,
378 GNUNET_NO);
379 stats = NULL;
380 }
381 if (NULL != open_ports)
382 {
383 GNUNET_CONTAINER_multihashmap_destroy (open_ports);
384 open_ports = NULL;
385 }
386 if (NULL != loose_channels)
387 {
388 GNUNET_CONTAINER_multihashmap_destroy (loose_channels);
389 loose_channels = NULL;
390 }
391 /* Destroy tunnels. Note that all channels must be destroyed first! */
392 GCP_iterate_all (&destroy_tunnels_now,
393 NULL);
394 /* All tunnels, channels, connections and CORE must be down before this point. */
395 GCP_iterate_all (&destroy_paths_now,
396 NULL);
397 /* All paths, tunnels, channels, connections and CORE must be down before this point. */
398 GCP_destroy_all_peers ();
399 if (NULL != peers)
400 {
401 GNUNET_CONTAINER_multipeermap_destroy (peers);
402 peers = NULL;
403 }
404 if (NULL != connections)
405 {
406 GNUNET_CONTAINER_multishortmap_destroy (connections);
407 connections = NULL;
408 }
409 if (NULL != ats_ch)
410 {
411 GNUNET_ATS_connectivity_done (ats_ch);
412 ats_ch = NULL;
413 }
414 GCD_shutdown ();
415 GCH_shutdown ();
416 GNUNET_free_non_null (my_private_key);
417 my_private_key = NULL;
418}
419
420
421/**
422 * Task run during shutdown.
423 *
424 * @param cls unused
425 */
426static void
427shutdown_task (void *cls)
428{
429 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
430 "Shutting down\n");
431 shutting_down = GNUNET_YES;
432 GCO_shutdown ();
433 if (NULL == clients_head)
434 shutdown_rest ();
435}
436
437
438/**
439 * We had a remote connection @a value to port @a port before
440 * client @a cls opened port @a port. Bind them now.
441 *
442 * @param cls the `struct CadetClient`
443 * @param port the port
444 * @param value the `struct CadetChannel`
445 * @return #GNUNET_YES (iterate over all such channels)
446 */
447static int
448bind_loose_channel (void *cls,
449 const struct GNUNET_HashCode *port,
450 void *value)
451{
452 struct CadetClient *c = cls;
453 struct CadetChannel *ch = value;
454
455 GCCH_bind (ch,
456 c);
457 GNUNET_assert (GNUNET_YES ==
458 GNUNET_CONTAINER_multihashmap_remove (loose_channels,
459 port,
460 value));
461 return GNUNET_YES;
462}
463
464
465/**
466 * Handle port open request. Creates a mapping from the
467 * port to the respective client and checks whether we have
468 * loose channels trying to bind to the port. If so, those
469 * are bound.
470 *
471 * @param cls Identification of the client.
472 * @param pmsg The actual message.
473 */
474static void
475handle_port_open (void *cls,
476 const struct GNUNET_CADET_PortMessage *pmsg)
477{
478 struct CadetClient *c = cls;
479
480 LOG (GNUNET_ERROR_TYPE_DEBUG,
481 "Open port %s requested by %s\n",
482 GNUNET_h2s (&pmsg->port),
483 GSC_2s (c));
484 if (NULL == c->ports)
485 c->ports = GNUNET_CONTAINER_multihashmap_create (4,
486 GNUNET_NO);
487 if (GNUNET_OK !=
488 GNUNET_CONTAINER_multihashmap_put (c->ports,
489 &pmsg->port,
490 c,
491 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
492 {
493 GNUNET_break (0);
494 GNUNET_SERVICE_client_drop (c->client);
495 return;
496 }
497 (void) GNUNET_CONTAINER_multihashmap_put (open_ports,
498 &pmsg->port,
499 c,
500 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
501 GNUNET_CONTAINER_multihashmap_get_multiple (loose_channels,
502 &pmsg->port,
503 &bind_loose_channel,
504 c);
505 GNUNET_SERVICE_client_continue (c->client);
506}
507
508
509/**
510 * Handler for port close requests. Marks this port as closed
511 * (unless of course we have another client with the same port
512 * open). Note that existing channels accepted on the port are
513 * not affected.
514 *
515 * @param cls Identification of the client.
516 * @param pmsg The actual message.
517 */
518static void
519handle_port_close (void *cls,
520 const struct GNUNET_CADET_PortMessage *pmsg)
521{
522 struct CadetClient *c = cls;
523
524 LOG (GNUNET_ERROR_TYPE_DEBUG,
525 "Closing port %s as requested by %s\n",
526 GNUNET_h2s (&pmsg->port),
527 GSC_2s (c));
528 if (GNUNET_YES !=
529 GNUNET_CONTAINER_multihashmap_remove (c->ports,
530 &pmsg->port,
531 c))
532 {
533 GNUNET_break (0);
534 GNUNET_SERVICE_client_drop (c->client);
535 return;
536 }
537 GNUNET_assert (GNUNET_YES ==
538 GNUNET_CONTAINER_multihashmap_remove (open_ports,
539 &pmsg->port,
540 c));
541 GNUNET_SERVICE_client_continue (c->client);
542}
543
544
545/**
546 * Handler for requests for us creating a new channel to another peer and port.
547 *
548 * @param cls Identification of the client.
549 * @param tcm The actual message.
550 */
551static void
552handle_channel_create (void *cls,
553 const struct GNUNET_CADET_LocalChannelCreateMessage *tcm)
554{
555 struct CadetClient *c = cls;
556 struct CadetChannel *ch;
557
558 if (ntohl (tcm->ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
559 {
560 /* Channel ID not in allowed range. */
561 GNUNET_break (0);
562 GNUNET_SERVICE_client_drop (c->client);
563 return;
564 }
565 ch = lookup_channel (c,
566 tcm->ccn);
567 if (NULL != ch)
568 {
569 /* Channel ID already in use. Not allowed. */
570 GNUNET_break (0);
571 GNUNET_SERVICE_client_drop (c->client);
572 return;
573 }
574 LOG (GNUNET_ERROR_TYPE_DEBUG,
575 "New channel to %s at port %s requested by %s\n",
576 GNUNET_i2s (&tcm->peer),
577 GNUNET_h2s (&tcm->port),
578 GSC_2s (c));
579
580 /* Create channel */
581 ch = GCCH_channel_local_new (c,
582 tcm->ccn,
583 GCP_get (&tcm->peer,
584 GNUNET_YES),
585 &tcm->port,
586 ntohl (tcm->opt));
587 if (NULL == ch)
588 {
589 GNUNET_break (0);
590 GNUNET_SERVICE_client_drop (c->client);
591 return;
592 }
593 GNUNET_assert (GNUNET_YES ==
594 GNUNET_CONTAINER_multihashmap32_put (c->channels,
595 ntohl (tcm->ccn.channel_of_client),
596 ch,
597 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
598
599 GNUNET_SERVICE_client_continue (c->client);
600}
601
602
603/**
604 * Handler for requests of destroying an existing channel.
605 *
606 * @param cls client identification of the client
607 * @param msg the actual message
608 */
609static void
610handle_channel_destroy (void *cls,
611 const struct GNUNET_CADET_LocalChannelDestroyMessage *msg)
612{
613 struct CadetClient *c = cls;
614 struct CadetChannel *ch;
615
616 ch = lookup_channel (c,
617 msg->ccn);
618 if (NULL == ch)
619 {
620 /* Client attempted to destroy unknown channel.
621 Can happen if the other side went down at the same time.*/
622 LOG (GNUNET_ERROR_TYPE_DEBUG,
623 "%s tried to destroy unknown channel %X\n",
624 GSC_2s(c),
625 (uint32_t) ntohl (msg->ccn.channel_of_client));
626 return;
627 }
628 LOG (GNUNET_ERROR_TYPE_DEBUG,
629 "%s is destroying %s\n",
630 GSC_2s(c),
631 GCCH_2s (ch));
632 GNUNET_assert (GNUNET_YES ==
633 GNUNET_CONTAINER_multihashmap32_remove (c->channels,
634 ntohl (msg->ccn.channel_of_client),
635 ch));
636 GCCH_channel_local_destroy (ch,
637 c,
638 msg->ccn);
639 GNUNET_SERVICE_client_continue (c->client);
640}
641
642
643/**
644 * Check for client traffic data message is well-formed.
645 *
646 * @param cls identification of the client
647 * @param msg the actual message
648 * @return #GNUNET_OK if @a msg is OK, #GNUNET_SYSERR if not
649 */
650static int
651check_local_data (void *cls,
652 const struct GNUNET_CADET_LocalData *msg)
653{
654 size_t payload_size;
655 size_t payload_claimed_size;
656 const char *buf;
657 struct GNUNET_MessageHeader pa;
658
659 /* FIXME: what is the format we shall allow for @a msg?
660 ONE payload item or multiple? Seems current cadet_api
661 at least in theory allows more than one. Next-gen
662 cadet_api will likely no more, so we could then
663 simplify this mess again. */
664 /* Sanity check for message size */
665 payload_size = ntohs (msg->header.size) - sizeof (*msg);
666 buf = (const char *) &msg[1];
667 while (payload_size >= sizeof (struct GNUNET_MessageHeader))
668 {
669 /* need to memcpy() for alignment */
670 GNUNET_memcpy (&pa,
671 buf,
672 sizeof (pa));
673 payload_claimed_size = ntohs (pa.size);
674 if ( (payload_size < payload_claimed_size) ||
675 (payload_claimed_size < sizeof (struct GNUNET_MessageHeader)) ||
676 (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < payload_claimed_size) )
677 {
678 GNUNET_break (0);
679 LOG (GNUNET_ERROR_TYPE_DEBUG,
680 "Local data of %u total size had sub-message %u at %u with %u bytes\n",
681 ntohs (msg->header.size),
682 ntohs (pa.type),
683 (unsigned int) (buf - (const char *) &msg[1]),
684 (unsigned int) payload_claimed_size);
685 return GNUNET_SYSERR;
686 }
687 payload_size -= payload_claimed_size;
688 buf += payload_claimed_size;
689 }
690 if (0 != payload_size)
691 {
692 GNUNET_break_op (0);
693 return GNUNET_SYSERR;
694 }
695 return GNUNET_OK;
696}
697
698
699/**
700 * Handler for client payload traffic to be send on a channel to
701 * another peer.
702 *
703 * @param cls identification of the client
704 * @param msg the actual message
705 */
706static void
707handle_local_data (void *cls,
708 const struct GNUNET_CADET_LocalData *msg)
709{
710 struct CadetClient *c = cls;
711 struct CadetChannel *ch;
712 size_t payload_size;
713 const char *buf;
714
715 ch = lookup_channel (c,
716 msg->ccn);
717 if (NULL == ch)
718 {
719 /* Channel does not exist (anymore) */
720 LOG (GNUNET_ERROR_TYPE_WARNING,
721 "Dropping payload for channel %u from client (channel unknown, other endpoint may have disconnected)\n",
722 (unsigned int) ntohl (msg->ccn.channel_of_client));
723 GNUNET_SERVICE_client_continue (c->client);
724 return;
725 }
726 payload_size = ntohs (msg->header.size) - sizeof (*msg);
727 GNUNET_STATISTICS_update (stats,
728 "# payload received from clients",
729 payload_size,
730 GNUNET_NO);
731 buf = (const char *) &msg[1];
732 LOG (GNUNET_ERROR_TYPE_DEBUG,
733 "Received %u bytes payload from %s for %s\n",
734 (unsigned int) payload_size,
735 GSC_2s (c),
736 GCCH_2s (ch));
737 if (GNUNET_OK !=
738 GCCH_handle_local_data (ch,
739 msg->ccn,
740 buf,
741 payload_size))
742 {
743 GNUNET_SERVICE_client_drop (c->client);
744 return;
745 }
746 GNUNET_SERVICE_client_continue (c->client);
747}
748
749
750/**
751 * Handler for client's ACKs for payload traffic.
752 *
753 * @param cls identification of the client.
754 * @param msg The actual message.
755 */
756static void
757handle_local_ack (void *cls,
758 const struct GNUNET_CADET_LocalAck *msg)
759{
760 struct CadetClient *c = cls;
761 struct CadetChannel *ch;
762
763 ch = lookup_channel (c,
764 msg->ccn);
765 if (NULL == ch)
766 {
767 /* Channel does not exist (anymore) */
768 LOG (GNUNET_ERROR_TYPE_WARNING,
769 "Ignoring local ACK for channel %u from client (channel unknown, other endpoint may have disconnected)\n",
770 (unsigned int) ntohl (msg->ccn.channel_of_client));
771 GNUNET_SERVICE_client_continue (c->client);
772 return;
773 }
774 LOG (GNUNET_ERROR_TYPE_DEBUG,
775 "Got a local ACK from %s for %s\n",
776 GSC_2s(c),
777 GCCH_2s (ch));
778 GCCH_handle_local_ack (ch,
779 msg->ccn);
780 GNUNET_SERVICE_client_continue (c->client);
781}
782
783
784/**
785 * Iterator over all peers to send a monitoring client info about each peer.
786 *
787 * @param cls Closure ().
788 * @param peer Peer ID (tunnel remote peer).
789 * @param value Peer info.
790 * @return #GNUNET_YES, to keep iterating.
791 */
792static int
793get_all_peers_iterator (void *cls,
794 const struct GNUNET_PeerIdentity *peer,
795 void *value)
796{
797 struct CadetClient *c = cls;
798 struct CadetPeer *p = value;
799 struct GNUNET_MQ_Envelope *env;
800 struct GNUNET_CADET_LocalInfoPeer *msg;
801
802 env = GNUNET_MQ_msg (msg,
803 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
804 msg->destination = *peer;
805 msg->paths = htons (GCP_count_paths (p));
806 msg->tunnel = htons (NULL != GCP_get_tunnel (p,
807 GNUNET_NO));
808 GNUNET_MQ_send (c->mq,
809 env);
810 return GNUNET_YES;
811}
812
813
814/**
815 * Handler for client's INFO PEERS request.
816 *
817 * @param cls Identification of the client.
818 * @param message The actual message.
819 */
820static void
821handle_get_peers (void *cls,
822 const struct GNUNET_MessageHeader *message)
823{
824 struct CadetClient *c = cls;
825 struct GNUNET_MQ_Envelope *env;
826 struct GNUNET_MessageHeader *reply;
827
828 GCP_iterate_all (&get_all_peers_iterator,
829 c);
830 env = GNUNET_MQ_msg (reply,
831 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
832 GNUNET_MQ_send (c->mq,
833 env);
834 GNUNET_SERVICE_client_continue (c->client);
835}
836
837
838/**
839 * Iterator over all paths of a peer to build an InfoPeer message.
840 * Message contains blocks of peers, first not included.
841 *
842 * @param cls message queue for transmission
843 * @param path Path itself
844 * @param off offset of the peer on @a path
845 * @return #GNUNET_YES if should keep iterating.
846 * #GNUNET_NO otherwise.
847 */
848static int
849path_info_iterator (void *cls,
850 struct CadetPeerPath *path,
851 unsigned int off)
852{
853 struct GNUNET_MQ_Handle *mq = cls;
854 struct GNUNET_MQ_Envelope *env;
855 struct GNUNET_MessageHeader *resp;
856 struct GNUNET_PeerIdentity *id;
857 uint16_t path_size;
858 unsigned int i;
859 unsigned int path_length;
860
861 path_length = GCPP_get_length (path);
862 path_size = sizeof (struct GNUNET_PeerIdentity) * (path_length - 1);
863 if (sizeof (*resp) + path_size > UINT16_MAX)
864 {
865 LOG (GNUNET_ERROR_TYPE_WARNING,
866 "Path of %u entries is too long for info message\n",
867 path_length);
868 return GNUNET_YES;
869 }
870 env = GNUNET_MQ_msg_extra (resp,
871 path_size,
872 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER);
873 id = (struct GNUNET_PeerIdentity *) &resp[1];
874
875 /* Don't copy first peer. First peer is always the local one. Last
876 * peer is always the destination (leave as 0, EOL).
877 */
878 for (i = 0; i < off; i++)
879 id[i] = *GCP_get_id (GCPP_get_peer_at_offset (path,
880 i + 1));
881 GNUNET_MQ_send (mq,
882 env);
883 return GNUNET_YES;
884}
885
886
887/**
888 * Handler for client's SHOW_PEER request.
889 *
890 * @param cls Identification of the client.
891 * @param msg The actual message.
892 */
893static void
894handle_show_peer (void *cls,
895 const struct GNUNET_CADET_LocalInfo *msg)
896{
897 struct CadetClient *c = cls;
898 struct CadetPeer *p;
899 struct GNUNET_MQ_Envelope *env;
900 struct GNUNET_MessageHeader *resp;
901
902 p = GCP_get (&msg->peer,
903 GNUNET_NO);
904 if (NULL != p)
905 GCP_iterate_paths (p,
906 &path_info_iterator,
907 c->mq);
908 /* Send message with 0/0 to indicate the end */
909 env = GNUNET_MQ_msg (resp,
910 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER_END);
911 GNUNET_MQ_send (c->mq,
912 env);
913 GNUNET_SERVICE_client_continue (c->client);
914}
915
916
917/**
918 * Iterator over all tunnels to send a monitoring client info about each tunnel.
919 *
920 * @param cls Closure ().
921 * @param peer Peer ID (tunnel remote peer).
922 * @param value a `struct CadetPeer`
923 * @return #GNUNET_YES, to keep iterating.
924 */
925static int
926get_all_tunnels_iterator (void *cls,
927 const struct GNUNET_PeerIdentity *peer,
928 void *value)
929{
930 struct CadetClient *c = cls;
931 struct CadetPeer *p = value;
932 struct GNUNET_MQ_Envelope *env;
933 struct GNUNET_CADET_LocalInfoTunnel *msg;
934 struct CadetTunnel *t;
935
936 t = GCP_get_tunnel (p,
937 GNUNET_NO);
938 if (NULL == t)
939 return GNUNET_YES;
940 env = GNUNET_MQ_msg (msg,
941 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
942 msg->destination = *peer;
943 msg->channels = htonl (GCT_count_channels (t));
944 msg->connections = htonl (GCT_count_any_connections (t));
945 msg->cstate = htons (0);
946 msg->estate = htons ((uint16_t) GCT_get_estate (t));
947 GNUNET_MQ_send (c->mq,
948 env);
949 return GNUNET_YES;
950}
951
952
953/**
954 * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS request.
955 *
956 * @param cls client Identification of the client.
957 * @param message The actual message.
958 */
959static void
960handle_info_tunnels (void *cls,
961 const struct GNUNET_MessageHeader *message)
962{
963 struct CadetClient *c = cls;
964 struct GNUNET_MQ_Envelope *env;
965 struct GNUNET_MessageHeader *reply;
966
967 GCP_iterate_all (&get_all_tunnels_iterator,
968 c);
969 env = GNUNET_MQ_msg (reply,
970 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
971 GNUNET_MQ_send (c->mq,
972 env);
973 GNUNET_SERVICE_client_continue (c->client);
974}
975
976
977/**
978 * Update the message with information about the connection.
979 *
980 * @param cls a `struct GNUNET_CADET_LocalInfoTunnel` message to update
981 * @param ct a connection about which we should store information in @a cls
982 */
983static void
984iter_connection (void *cls,
985 struct CadetTConnection *ct)
986{
987 struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
988 struct CadetConnection *cc = ct->cc;
989 struct GNUNET_CADET_ConnectionTunnelIdentifier *h;
990
991 h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
992 h[msg->connections++] = *(GCC_get_id (cc));
993}
994
995
996/**
997 * Update the message with information about the channel.
998 *
999 * @param cls a `struct GNUNET_CADET_LocalInfoTunnel` message to update
1000 * @param ch a channel about which we should store information in @a cls
1001 */
1002static void
1003iter_channel (void *cls,
1004 struct CadetChannel *ch)
1005{
1006 struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
1007 struct GNUNET_CADET_ConnectionTunnelIdentifier *h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
1008 struct GNUNET_CADET_ChannelTunnelNumber *chn
1009 = (struct GNUNET_CADET_ChannelTunnelNumber *) &h[msg->connections];
1010
1011 chn[msg->channels++] = GCCH_get_id (ch);
1012}
1013
1014
1015/**
1016 * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL request.
1017 *
1018 * @param cls Identification of the client.
1019 * @param msg The actual message.
1020 */
1021static void
1022handle_info_tunnel (void *cls,
1023 const struct GNUNET_CADET_LocalInfo *msg)
1024{
1025 struct CadetClient *c = cls;
1026 struct GNUNET_MQ_Envelope *env;
1027 struct GNUNET_CADET_LocalInfoTunnel *resp;
1028 struct CadetTunnel *t;
1029 struct CadetPeer *p;
1030 unsigned int ch_n;
1031 unsigned int c_n;
1032
1033 p = GCP_get (&msg->peer,
1034 GNUNET_NO);
1035 t = GCP_get_tunnel (p,
1036 GNUNET_NO);
1037 if (NULL == t)
1038 {
1039 /* We don't know the tunnel */
1040 struct GNUNET_MQ_Envelope *env;
1041 struct GNUNET_CADET_LocalInfoTunnel *warn;
1042
1043 LOG (GNUNET_ERROR_TYPE_INFO,
1044 "Tunnel to %s unknown\n",
1045 GNUNET_i2s_full (&msg->peer));
1046 env = GNUNET_MQ_msg (warn,
1047 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
1048 warn->destination = msg->peer;
1049 GNUNET_MQ_send (c->mq,
1050 env);
1051 GNUNET_SERVICE_client_continue (c->client);
1052 return;
1053 }
1054
1055 /* Initialize context */
1056 ch_n = GCT_count_channels (t);
1057 c_n = GCT_count_any_connections (t);
1058 env = GNUNET_MQ_msg_extra (resp,
1059 c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier) +
1060 ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber),
1061 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
1062 resp->destination = msg->peer;
1063 /* Do not reorder! #iter_channel needs counters in HBO! */
1064 GCT_iterate_connections (t,
1065 &iter_connection,
1066 resp);
1067 GCT_iterate_channels (t,
1068 &iter_channel,
1069 resp);
1070 resp->connections = htonl (resp->connections);
1071 resp->channels = htonl (resp->channels);
1072 resp->cstate = htons (0);
1073 resp->estate = htons (GCT_get_estate (t));
1074 GNUNET_MQ_send (c->mq,
1075 env);
1076 GNUNET_SERVICE_client_continue (c->client);
1077}
1078
1079
1080/**
1081 * Iterator over all peers to dump info for each peer.
1082 *
1083 * @param cls Closure (unused).
1084 * @param peer Peer ID (tunnel remote peer).
1085 * @param value Peer info.
1086 *
1087 * @return #GNUNET_YES, to keep iterating.
1088 */
1089static int
1090show_peer_iterator (void *cls,
1091 const struct GNUNET_PeerIdentity *peer,
1092 void *value)
1093{
1094 struct CadetPeer *p = value;
1095 struct CadetTunnel *t;
1096
1097 t = GCP_get_tunnel (p,
1098 GNUNET_NO);
1099 if (NULL != t)
1100 GCT_debug (t,
1101 GNUNET_ERROR_TYPE_ERROR);
1102 LOG (GNUNET_ERROR_TYPE_ERROR, "\n");
1103 return GNUNET_YES;
1104}
1105
1106
1107/**
1108 * Handler for client's INFO_DUMP request.
1109 *
1110 * @param cls Identification of the client.
1111 * @param message The actual message.
1112 */
1113static void
1114handle_info_dump (void *cls,
1115 const struct GNUNET_MessageHeader *message)
1116{
1117 struct CadetClient *c = cls;
1118
1119 LOG (GNUNET_ERROR_TYPE_INFO,
1120 "Received dump info request from client %u\n",
1121 c->id);
1122
1123 LOG (GNUNET_ERROR_TYPE_ERROR,
1124 "*************************** DUMP START ***************************\n");
1125 for (struct CadetClient *ci = clients_head;
1126 NULL != ci;
1127 ci = ci->next)
1128 {
1129 LOG (GNUNET_ERROR_TYPE_ERROR,
1130 "Client %u (%p), handle: %p, ports: %u, channels: %u\n",
1131 ci->id,
1132 ci,
1133 ci->client,
1134 (NULL != c->ports)
1135 ? GNUNET_CONTAINER_multihashmap_size (ci->ports)
1136 : 0,
1137 GNUNET_CONTAINER_multihashmap32_size (ci->channels));
1138 }
1139 LOG (GNUNET_ERROR_TYPE_ERROR, "***************************\n");
1140 GCP_iterate_all (&show_peer_iterator,
1141 NULL);
1142
1143 LOG (GNUNET_ERROR_TYPE_ERROR,
1144 "**************************** DUMP END ****************************\n");
1145
1146 GNUNET_SERVICE_client_continue (c->client);
1147}
1148
1149
1150
1151/**
1152 * Callback called when a client connects to the service.
1153 *
1154 * @param cls closure for the service
1155 * @param client the new client that connected to the service
1156 * @param mq the message queue used to send messages to the client
1157 * @return @a c
1158 */
1159static void *
1160client_connect_cb (void *cls,
1161 struct GNUNET_SERVICE_Client *client,
1162 struct GNUNET_MQ_Handle *mq)
1163{
1164 struct CadetClient *c;
1165
1166 c = GNUNET_new (struct CadetClient);
1167 c->client = client;
1168 c->mq = mq;
1169 c->id = next_client_id++; /* overflow not important: just for debug */
1170 c->channels
1171 = GNUNET_CONTAINER_multihashmap32_create (32);
1172 GNUNET_CONTAINER_DLL_insert (clients_head,
1173 clients_tail,
1174 c);
1175 GNUNET_STATISTICS_update (stats,
1176 "# clients",
1177 +1,
1178 GNUNET_NO);
1179 LOG (GNUNET_ERROR_TYPE_DEBUG,
1180 "%s connected\n",
1181 GSC_2s (c));
1182 return c;
1183}
1184
1185
1186/**
1187 * A channel was destroyed by the other peer. Tell our client.
1188 *
1189 * @param c client that lost a channel
1190 * @param ccn channel identification number for the client
1191 * @param ch the channel object
1192 */
1193void
1194GSC_handle_remote_channel_destroy (struct CadetClient *c,
1195 struct GNUNET_CADET_ClientChannelNumber ccn,
1196 struct CadetChannel *ch)
1197{
1198 struct GNUNET_MQ_Envelope *env;
1199 struct GNUNET_CADET_LocalChannelDestroyMessage *tdm;
1200
1201 env = GNUNET_MQ_msg (tdm,
1202 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
1203 tdm->ccn = ccn;
1204 GSC_send_to_client (c,
1205 env);
1206 GNUNET_assert (GNUNET_YES ==
1207 GNUNET_CONTAINER_multihashmap32_remove (c->channels,
1208 ntohl (ccn.channel_of_client),
1209 ch));
1210}
1211
1212
1213/**
1214 * A client that created a loose channel that was not bound to a port
1215 * disconnected, drop it from the #loose_channels list.
1216 *
1217 * @param port the port the channel was trying to bind to
1218 * @param ch the channel that was lost
1219 */
1220void
1221GSC_drop_loose_channel (const struct GNUNET_HashCode *port,
1222 struct CadetChannel *ch)
1223{
1224 GNUNET_assert (GNUNET_YES ==
1225 GNUNET_CONTAINER_multihashmap_remove (loose_channels,
1226 port,
1227 ch));
1228}
1229
1230
1231/**
1232 * Iterator for deleting each channel whose client endpoint disconnected.
1233 *
1234 * @param cls Closure (client that has disconnected).
1235 * @param key The local channel id in host byte order
1236 * @param value The value stored at the key (channel to destroy).
1237 * @return #GNUNET_OK, keep iterating.
1238 */
1239static int
1240channel_destroy_iterator (void *cls,
1241 uint32_t key,
1242 void *value)
1243{
1244 struct CadetClient *c = cls;
1245 struct GNUNET_CADET_ClientChannelNumber ccn;
1246 struct CadetChannel *ch = value;
1247
1248 LOG (GNUNET_ERROR_TYPE_DEBUG,
1249 "Destroying %s, due to %s disconnecting.\n",
1250 GCCH_2s (ch),
1251 GSC_2s (c));
1252 ccn.channel_of_client = htonl (key);
1253 GCCH_channel_local_destroy (ch,
1254 c,
1255 ccn);
1256 GNUNET_assert (GNUNET_YES ==
1257 GNUNET_CONTAINER_multihashmap32_remove (c->channels,
1258 key,
1259 ch));
1260 return GNUNET_OK;
1261}
1262
1263
1264/**
1265 * Remove client's ports from the global hashmap on disconnect.
1266 *
1267 * @param cls Closure (unused).
1268 * @param key the port.
1269 * @param value the `struct CadetClient` to remove
1270 * @return #GNUNET_OK, keep iterating.
1271 */
1272static int
1273client_release_ports (void *cls,
1274 const struct GNUNET_HashCode *key,
1275 void *value)
1276{
1277 struct CadetClient *c = value;
1278
1279 LOG (GNUNET_ERROR_TYPE_DEBUG,
1280 "Closing port %s due to %s disconnect.\n",
1281 GNUNET_h2s (key),
1282 GSC_2s (c));
1283 GNUNET_assert (GNUNET_YES ==
1284 GNUNET_CONTAINER_multihashmap_remove (open_ports,
1285 key,
1286 value));
1287 GNUNET_assert (GNUNET_YES ==
1288 GNUNET_CONTAINER_multihashmap_remove (c->ports,
1289 key,
1290 value));
1291 return GNUNET_OK;
1292}
1293
1294
1295/**
1296 * Callback called when a client disconnected from the service
1297 *
1298 * @param cls closure for the service
1299 * @param client the client that disconnected
1300 * @param internal_cls should be equal to @a c
1301 */
1302static void
1303client_disconnect_cb (void *cls,
1304 struct GNUNET_SERVICE_Client *client,
1305 void *internal_cls)
1306{
1307 struct CadetClient *c = internal_cls;
1308
1309 GNUNET_assert (c->client == client);
1310 LOG (GNUNET_ERROR_TYPE_DEBUG,
1311 "%s is disconnecting.\n",
1312 GSC_2s (c));
1313 if (NULL != c->channels)
1314 {
1315 GNUNET_CONTAINER_multihashmap32_iterate (c->channels,
1316 &channel_destroy_iterator,
1317 c);
1318 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->channels));
1319 GNUNET_CONTAINER_multihashmap32_destroy (c->channels);
1320 }
1321 if (NULL != c->ports)
1322 {
1323 GNUNET_CONTAINER_multihashmap_iterate (c->ports,
1324 &client_release_ports,
1325 c);
1326 GNUNET_CONTAINER_multihashmap_destroy (c->ports);
1327 }
1328 GNUNET_CONTAINER_DLL_remove (clients_head,
1329 clients_tail,
1330 c);
1331 GNUNET_STATISTICS_update (stats,
1332 "# clients",
1333 -1,
1334 GNUNET_NO);
1335 GNUNET_free (c);
1336 if ( (NULL == clients_head) &&
1337 (GNUNET_YES == shutting_down) )
1338 shutdown_rest ();
1339}
1340
1341
1342/**
1343 * Setup CADET internals.
1344 *
1345 * @param cls closure
1346 * @param server the initialized server
1347 * @param c configuration to use
1348 */
1349static void
1350run (void *cls,
1351 const struct GNUNET_CONFIGURATION_Handle *c,
1352 struct GNUNET_SERVICE_Handle *service)
1353{
1354 cfg = c;
1355 if (GNUNET_OK !=
1356 GNUNET_CONFIGURATION_get_value_number (c,
1357 "CADET",
1358 "RATCHET_MESSAGES",
1359 &ratchet_messages))
1360 {
1361 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1362 "CADET",
1363 "RATCHET_MESSAGES",
1364 "needs to be a number");
1365 ratchet_messages = 64;
1366 }
1367 if (GNUNET_OK !=
1368 GNUNET_CONFIGURATION_get_value_time (c,
1369 "CADET",
1370 "RATCHET_TIME",
1371 &ratchet_time))
1372 {
1373 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1374 "CADET",
1375 "RATCHET_TIME",
1376 "need delay value");
1377 ratchet_time = GNUNET_TIME_UNIT_HOURS;
1378 }
1379 if (GNUNET_OK !=
1380 GNUNET_CONFIGURATION_get_value_time (c,
1381 "CADET",
1382 "REFRESH_CONNECTION_TIME",
1383 &keepalive_period))
1384 {
1385 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1386 "CADET",
1387 "REFRESH_CONNECTION_TIME",
1388 "need delay value");
1389 keepalive_period = GNUNET_TIME_UNIT_MINUTES;
1390 }
1391 if (GNUNET_OK !=
1392 GNUNET_CONFIGURATION_get_value_number (c,
1393 "CADET",
1394 "DROP_PERCENT",
1395 &drop_percent))
1396 {
1397 drop_percent = 0;
1398 }
1399 else
1400 {
1401 LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
1402 LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n");
1403 LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n");
1404 LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n");
1405 LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
1406 }
1407 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
1408 if (NULL == my_private_key)
1409 {
1410 GNUNET_break (0);
1411 GNUNET_SCHEDULER_shutdown ();
1412 return;
1413 }
1414 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
1415 &my_full_id.public_key);
1416 stats = GNUNET_STATISTICS_create ("cadet",
1417 c);
1418 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1419 NULL);
1420 ats_ch = GNUNET_ATS_connectivity_init (c);
1421 /* FIXME: optimize code to allow GNUNET_YES here! */
1422 open_ports = GNUNET_CONTAINER_multihashmap_create (16,
1423 GNUNET_NO);
1424 loose_channels = GNUNET_CONTAINER_multihashmap_create (16,
1425 GNUNET_NO);
1426 peers = GNUNET_CONTAINER_multipeermap_create (16,
1427 GNUNET_YES);
1428 connections = GNUNET_CONTAINER_multishortmap_create (256,
1429 GNUNET_YES);
1430 GCH_init (c);
1431 GCD_init (c);
1432 GCO_init (c);
1433 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1434 "CADET started for peer %s\n",
1435 GNUNET_i2s (&my_full_id));
1436
1437}
1438
1439
1440/**
1441 * Define "main" method using service macro.
1442 */
1443GNUNET_SERVICE_MAIN
1444("cadet",
1445 GNUNET_SERVICE_OPTION_NONE,
1446 &run,
1447 &client_connect_cb,
1448 &client_disconnect_cb,
1449 NULL,
1450 GNUNET_MQ_hd_fixed_size (port_open,
1451 GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN,
1452 struct GNUNET_CADET_PortMessage,
1453 NULL),
1454 GNUNET_MQ_hd_fixed_size (port_close,
1455 GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
1456 struct GNUNET_CADET_PortMessage,
1457 NULL),
1458 GNUNET_MQ_hd_fixed_size (channel_create,
1459 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
1460 struct GNUNET_CADET_LocalChannelCreateMessage,
1461 NULL),
1462 GNUNET_MQ_hd_fixed_size (channel_destroy,
1463 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
1464 struct GNUNET_CADET_LocalChannelDestroyMessage,
1465 NULL),
1466 GNUNET_MQ_hd_var_size (local_data,
1467 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
1468 struct GNUNET_CADET_LocalData,
1469 NULL),
1470 GNUNET_MQ_hd_fixed_size (local_ack,
1471 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
1472 struct GNUNET_CADET_LocalAck,
1473 NULL),
1474 GNUNET_MQ_hd_fixed_size (get_peers,
1475 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
1476 struct GNUNET_MessageHeader,
1477 NULL),
1478 GNUNET_MQ_hd_fixed_size (show_peer,
1479 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER,
1480 struct GNUNET_CADET_LocalInfo,
1481 NULL),
1482 GNUNET_MQ_hd_fixed_size (info_tunnels,
1483 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
1484 struct GNUNET_MessageHeader,
1485 NULL),
1486 GNUNET_MQ_hd_fixed_size (info_tunnel,
1487 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL,
1488 struct GNUNET_CADET_LocalInfo,
1489 NULL),
1490 GNUNET_MQ_hd_fixed_size (info_dump,
1491 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP,
1492 struct GNUNET_MessageHeader,
1493 NULL),
1494 GNUNET_MQ_handler_end ());
1495
1496/* end of gnunet-service-cadet-new.c */
diff --git a/src/cadet/gnunet-service-cadet-new_channel.c b/src/cadet/gnunet-service-cadet-new_channel.c
deleted file mode 100644
index 43c905816..000000000
--- a/src/cadet/gnunet-service-cadet-new_channel.c
+++ /dev/null
@@ -1,2040 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file cadet/gnunet-service-cadet-new_channel.c
22 * @brief logical links between CADET clients
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - Congestion/flow control:
28 * + estimate max bandwidth using bursts and use to for CONGESTION CONTROL!
29 * (and figure out how/where to use this!)
30 * + figure out flow control without ACKs (unreliable traffic!)
31 * - revisit handling of 'unbuffered' traffic!
32 * (need to push down through tunnel into connection selection)
33 * - revisit handling of 'buffered' traffic: 4 is a rather small buffer; maybe
34 * reserve more bits in 'options' to allow for buffer size control?
35 */
36#include "platform.h"
37#include "gnunet_util_lib.h"
38#include "cadet.h"
39#include "gnunet_statistics_service.h"
40#include "gnunet-service-cadet-new.h"
41#include "gnunet-service-cadet-new_channel.h"
42#include "gnunet-service-cadet-new_connection.h"
43#include "gnunet-service-cadet-new_tunnels.h"
44#include "gnunet-service-cadet-new_peer.h"
45#include "gnunet-service-cadet-new_paths.h"
46
47#define LOG(level,...) GNUNET_log_from (level,"cadet-chn",__VA_ARGS__)
48
49/**
50 * How long do we initially wait before retransmitting?
51 */
52#define CADET_INITIAL_RETRANSMIT_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250)
53
54/**
55 * How long do we wait before dropping state about incoming
56 * connection to closed port?
57 */
58#define TIMEOUT_CLOSED_PORT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
59
60/**
61 * How long do we wait at least before retransmitting ever?
62 */
63#define MIN_RTT_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 75)
64
65/**
66 * Maximum message ID into the future we accept for out-of-order messages.
67 * If the message is more than this into the future, we drop it. This is
68 * important both to detect values that are actually in the past, as well
69 * as to limit adversarially triggerable memory consumption.
70 *
71 * Note that right now we have "max_pending_messages = 4" hard-coded in
72 * the logic below, so a value of 4 would suffice here. But we plan to
73 * allow larger windows in the future...
74 */
75#define MAX_OUT_OF_ORDER_DISTANCE 1024
76
77
78/**
79 * All the states a channel can be in.
80 */
81enum CadetChannelState
82{
83 /**
84 * Uninitialized status, should never appear in operation.
85 */
86 CADET_CHANNEL_NEW,
87
88 /**
89 * Channel is to a port that is not open, we're waiting for the
90 * port to be opened.
91 */
92 CADET_CHANNEL_LOOSE,
93
94 /**
95 * CHANNEL_OPEN message sent, waiting for CHANNEL_OPEN_ACK.
96 */
97 CADET_CHANNEL_OPEN_SENT,
98
99 /**
100 * Connection confirmed, ready to carry traffic.
101 */
102 CADET_CHANNEL_READY
103};
104
105
106/**
107 * Info needed to retry a message in case it gets lost.
108 * Note that we DO use this structure also for unreliable
109 * messages.
110 */
111struct CadetReliableMessage
112{
113 /**
114 * Double linked list, FIFO style
115 */
116 struct CadetReliableMessage *next;
117
118 /**
119 * Double linked list, FIFO style
120 */
121 struct CadetReliableMessage *prev;
122
123 /**
124 * Which channel is this message in?
125 */
126 struct CadetChannel *ch;
127
128 /**
129 * Entry in the tunnels queue for this message, NULL if it has left
130 * the tunnel. Used to cancel transmission in case we receive an
131 * ACK in time.
132 */
133 struct CadetTunnelQueueEntry *qe;
134
135 /**
136 * Data message we are trying to send.
137 */
138 struct GNUNET_CADET_ChannelAppDataMessage *data_message;
139
140 /**
141 * How soon should we retry if we fail to get an ACK?
142 * Messages in the queue are sorted by this value.
143 */
144 struct GNUNET_TIME_Absolute next_retry;
145
146 /**
147 * How long do we wait for an ACK after transmission?
148 * Use for the back-off calculation.
149 */
150 struct GNUNET_TIME_Relative retry_delay;
151
152 /**
153 * Time when we first successfully transmitted the message
154 * (that is, set @e num_transmissions to 1).
155 */
156 struct GNUNET_TIME_Absolute first_transmission_time;
157
158 /**
159 * Identifier of the connection that this message took when it
160 * was first transmitted. Only useful if @e num_transmissions is 1.
161 */
162 struct GNUNET_CADET_ConnectionTunnelIdentifier connection_taken;
163
164 /**
165 * How often was this message transmitted? #GNUNET_SYSERR if there
166 * was an error transmitting the message, #GNUNET_NO if it was not
167 * yet transmitted ever, otherwise the number of (re) transmissions.
168 */
169 int num_transmissions;
170
171};
172
173
174/**
175 * List of received out-of-order data messages.
176 */
177struct CadetOutOfOrderMessage
178{
179 /**
180 * Double linked list, FIFO style
181 */
182 struct CadetOutOfOrderMessage *next;
183
184 /**
185 * Double linked list, FIFO style
186 */
187 struct CadetOutOfOrderMessage *prev;
188
189 /**
190 * ID of the message (messages up to this point needed
191 * before we give this one to the client).
192 */
193 struct ChannelMessageIdentifier mid;
194
195 /**
196 * The envelope with the payload of the out-of-order message
197 */
198 struct GNUNET_MQ_Envelope *env;
199
200};
201
202
203/**
204 * Client endpoint of a `struct CadetChannel`. A channel may be a
205 * loopback channel, in which case it has two of these endpoints.
206 * Note that flow control also is required in both directions.
207 */
208struct CadetChannelClient
209{
210 /**
211 * Client handle. Not by itself sufficient to designate
212 * the client endpoint, as the same client handle may
213 * be used for both the owner and the destination, and
214 * we thus also need the channel ID to identify the client.
215 */
216 struct CadetClient *c;
217
218 /**
219 * Head of DLL of messages received out of order or while client was unready.
220 */
221 struct CadetOutOfOrderMessage *head_recv;
222
223 /**
224 * Tail DLL of messages received out of order or while client was unready.
225 */
226 struct CadetOutOfOrderMessage *tail_recv;
227
228 /**
229 * Local tunnel number for this client.
230 * (if owner >= #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI,
231 * otherwise < #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
232 */
233 struct GNUNET_CADET_ClientChannelNumber ccn;
234
235 /**
236 * Number of entries currently in @a head_recv DLL.
237 */
238 unsigned int num_recv;
239
240 /**
241 * Can we send data to the client?
242 */
243 int client_ready;
244
245};
246
247
248/**
249 * Struct containing all information regarding a channel to a remote client.
250 */
251struct CadetChannel
252{
253 /**
254 * Tunnel this channel is in.
255 */
256 struct CadetTunnel *t;
257
258 /**
259 * Client owner of the tunnel, if any.
260 * (Used if this channel represends the initiating end of the tunnel.)
261 */
262 struct CadetChannelClient *owner;
263
264 /**
265 * Client destination of the tunnel, if any.
266 * (Used if this channel represents the listening end of the tunnel.)
267 */
268 struct CadetChannelClient *dest;
269
270 /**
271 * Last entry in the tunnel's queue relating to control messages
272 * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN or
273 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK). Used to cancel
274 * transmission in case we receive updated information.
275 */
276 struct CadetTunnelQueueEntry *last_control_qe;
277
278 /**
279 * Head of DLL of messages sent and not yet ACK'd.
280 */
281 struct CadetReliableMessage *head_sent;
282
283 /**
284 * Tail of DLL of messages sent and not yet ACK'd.
285 */
286 struct CadetReliableMessage *tail_sent;
287
288 /**
289 * Task to resend/poll in case no ACK is received.
290 */
291 struct GNUNET_SCHEDULER_Task *retry_control_task;
292
293 /**
294 * Task to resend/poll in case no ACK is received.
295 */
296 struct GNUNET_SCHEDULER_Task *retry_data_task;
297
298 /**
299 * Last time the channel was used
300 */
301 struct GNUNET_TIME_Absolute timestamp;
302
303 /**
304 * Destination port of the channel.
305 */
306 struct GNUNET_HashCode port;
307
308 /**
309 * Counter for exponential backoff.
310 */
311 struct GNUNET_TIME_Relative retry_time;
312
313 /**
314 * Bitfield of already-received messages past @e mid_recv.
315 */
316 uint64_t mid_futures;
317
318 /**
319 * Next MID expected for incoming traffic.
320 */
321 struct ChannelMessageIdentifier mid_recv;
322
323 /**
324 * Next MID to use for outgoing traffic.
325 */
326 struct ChannelMessageIdentifier mid_send;
327
328 /**
329 * Total (reliable) messages pending ACK for this channel.
330 */
331 unsigned int pending_messages;
332
333 /**
334 * Maximum (reliable) messages pending ACK for this channel
335 * before we throttle the client.
336 */
337 unsigned int max_pending_messages;
338
339 /**
340 * Number identifying this channel in its tunnel.
341 */
342 struct GNUNET_CADET_ChannelTunnelNumber ctn;
343
344 /**
345 * Channel state.
346 */
347 enum CadetChannelState state;
348
349 /**
350 * Count how many ACKs we skipped, used to prevent long
351 * sequences of ACK skipping.
352 */
353 unsigned int skip_ack_series;
354
355 /**
356 * Is the tunnel bufferless (minimum latency)?
357 */
358 int nobuffer;
359
360 /**
361 * Is the tunnel reliable?
362 */
363 int reliable;
364
365 /**
366 * Is the tunnel out-of-order?
367 */
368 int out_of_order;
369
370 /**
371 * Is this channel a loopback channel, where the destination is us again?
372 */
373 int is_loopback;
374
375 /**
376 * Flag to signal the destruction of the channel. If this is set to
377 * #GNUNET_YES the channel will be destroyed once the queue is
378 * empty.
379 */
380 int destroy;
381
382};
383
384
385/**
386 * Get the static string for identification of the channel.
387 *
388 * @param ch Channel.
389 *
390 * @return Static string with the channel IDs.
391 */
392const char *
393GCCH_2s (const struct CadetChannel *ch)
394{
395 static char buf[128];
396
397 GNUNET_snprintf (buf,
398 sizeof (buf),
399 "Channel %s:%s ctn:%X(%X/%X)",
400 (GNUNET_YES == ch->is_loopback)
401 ? "loopback"
402 : GNUNET_i2s (GCP_get_id (GCT_get_destination (ch->t))),
403 GNUNET_h2s (&ch->port),
404 ch->ctn,
405 (NULL == ch->owner) ? 0 : ntohl (ch->owner->ccn.channel_of_client),
406 (NULL == ch->dest) ? 0 : ntohl (ch->dest->ccn.channel_of_client));
407 return buf;
408}
409
410
411/**
412 * Get the channel's public ID.
413 *
414 * @param ch Channel.
415 *
416 * @return ID used to identify the channel with the remote peer.
417 */
418struct GNUNET_CADET_ChannelTunnelNumber
419GCCH_get_id (const struct CadetChannel *ch)
420{
421 return ch->ctn;
422}
423
424
425/**
426 * Release memory associated with @a ccc
427 *
428 * @param ccc data structure to clean up
429 */
430static void
431free_channel_client (struct CadetChannelClient *ccc)
432{
433 struct CadetOutOfOrderMessage *com;
434
435 while (NULL != (com = ccc->head_recv))
436 {
437 GNUNET_CONTAINER_DLL_remove (ccc->head_recv,
438 ccc->tail_recv,
439 com);
440 ccc->num_recv--;
441 GNUNET_MQ_discard (com->env);
442 GNUNET_free (com);
443 }
444 GNUNET_free (ccc);
445}
446
447
448/**
449 * Destroy the given channel.
450 *
451 * @param ch channel to destroy
452 */
453static void
454channel_destroy (struct CadetChannel *ch)
455{
456 struct CadetReliableMessage *crm;
457
458 while (NULL != (crm = ch->head_sent))
459 {
460 GNUNET_assert (ch == crm->ch);
461 if (NULL != crm->qe)
462 {
463 GCT_send_cancel (crm->qe);
464 crm->qe = NULL;
465 }
466 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
467 ch->tail_sent,
468 crm);
469 GNUNET_free (crm->data_message);
470 GNUNET_free (crm);
471 }
472 if (NULL != ch->owner)
473 {
474 free_channel_client (ch->owner);
475 ch->owner = NULL;
476 }
477 if (NULL != ch->dest)
478 {
479 free_channel_client (ch->dest);
480 ch->dest = NULL;
481 }
482 if (NULL != ch->last_control_qe)
483 {
484 GCT_send_cancel (ch->last_control_qe);
485 ch->last_control_qe = NULL;
486 }
487 if (NULL != ch->retry_data_task)
488 {
489 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
490 ch->retry_data_task = NULL;
491 }
492 if (NULL != ch->retry_control_task)
493 {
494 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
495 ch->retry_control_task = NULL;
496 }
497 if (GNUNET_NO == ch->is_loopback)
498 {
499 GCT_remove_channel (ch->t,
500 ch,
501 ch->ctn);
502 ch->t = NULL;
503 }
504 GNUNET_free (ch);
505}
506
507
508/**
509 * Send a channel create message.
510 *
511 * @param cls Channel for which to send.
512 */
513static void
514send_channel_open (void *cls);
515
516
517/**
518 * Function called once the tunnel confirms that we sent the
519 * create message. Delays for a bit until we retry.
520 *
521 * @param cls our `struct CadetChannel`.
522 * @param cid identifier of the connection within the tunnel, NULL
523 * if transmission failed
524 */
525static void
526channel_open_sent_cb (void *cls,
527 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
528{
529 struct CadetChannel *ch = cls;
530
531 GNUNET_assert (NULL != ch->last_control_qe);
532 ch->last_control_qe = NULL;
533 ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time);
534 LOG (GNUNET_ERROR_TYPE_DEBUG,
535 "Sent CADET_CHANNEL_OPEN on %s, retrying in %s\n",
536 GCCH_2s (ch),
537 GNUNET_STRINGS_relative_time_to_string (ch->retry_time,
538 GNUNET_YES));
539 ch->retry_control_task
540 = GNUNET_SCHEDULER_add_delayed (ch->retry_time,
541 &send_channel_open,
542 ch);
543}
544
545
546/**
547 * Send a channel open message.
548 *
549 * @param cls Channel for which to send.
550 */
551static void
552send_channel_open (void *cls)
553{
554 struct CadetChannel *ch = cls;
555 struct GNUNET_CADET_ChannelOpenMessage msgcc;
556 uint32_t options;
557
558 ch->retry_control_task = NULL;
559 LOG (GNUNET_ERROR_TYPE_DEBUG,
560 "Sending CHANNEL_OPEN message for %s\n",
561 GCCH_2s (ch));
562 options = 0;
563 if (ch->nobuffer)
564 options |= GNUNET_CADET_OPTION_NOBUFFER;
565 if (ch->reliable)
566 options |= GNUNET_CADET_OPTION_RELIABLE;
567 if (ch->out_of_order)
568 options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
569 msgcc.header.size = htons (sizeof (msgcc));
570 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
571 msgcc.opt = htonl (options);
572 msgcc.port = ch->port;
573 msgcc.ctn = ch->ctn;
574 ch->state = CADET_CHANNEL_OPEN_SENT;
575 if (NULL != ch->last_control_qe)
576 GCT_send_cancel (ch->last_control_qe);
577 ch->last_control_qe = GCT_send (ch->t,
578 &msgcc.header,
579 &channel_open_sent_cb,
580 ch);
581 GNUNET_assert (NULL == ch->retry_control_task);
582}
583
584
585/**
586 * Function called once and only once after a channel was bound
587 * to its tunnel via #GCT_add_channel() is ready for transmission.
588 * Note that this is only the case for channels that this peer
589 * initiates, as for incoming channels we assume that they are
590 * ready for transmission immediately upon receiving the open
591 * message. Used to bootstrap the #GCT_send() process.
592 *
593 * @param ch the channel for which the tunnel is now ready
594 */
595void
596GCCH_tunnel_up (struct CadetChannel *ch)
597{
598 GNUNET_assert (NULL == ch->retry_control_task);
599 LOG (GNUNET_ERROR_TYPE_DEBUG,
600 "Tunnel up, sending CHANNEL_OPEN on %s now\n",
601 GCCH_2s (ch));
602 ch->retry_control_task
603 = GNUNET_SCHEDULER_add_now (&send_channel_open,
604 ch);
605}
606
607
608/**
609 * Create a new channel.
610 *
611 * @param owner local client owning the channel
612 * @param ccn local number of this channel at the @a owner
613 * @param destination peer to which we should build the channel
614 * @param port desired port at @a destination
615 * @param options options for the channel
616 * @return handle to the new channel
617 */
618struct CadetChannel *
619GCCH_channel_local_new (struct CadetClient *owner,
620 struct GNUNET_CADET_ClientChannelNumber ccn,
621 struct CadetPeer *destination,
622 const struct GNUNET_HashCode *port,
623 uint32_t options)
624{
625 struct CadetChannel *ch;
626 struct CadetChannelClient *ccco;
627
628 ccco = GNUNET_new (struct CadetChannelClient);
629 ccco->c = owner;
630 ccco->ccn = ccn;
631 ccco->client_ready = GNUNET_YES;
632
633 ch = GNUNET_new (struct CadetChannel);
634 ch->mid_recv.mid = htonl (1); /* The OPEN_ACK counts as message 0! */
635 ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER));
636 ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE));
637 ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER));
638 ch->max_pending_messages = (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
639 ch->owner = ccco;
640 ch->port = *port;
641 if (0 == memcmp (&my_full_id,
642 GCP_get_id (destination),
643 sizeof (struct GNUNET_PeerIdentity)))
644 {
645 struct CadetClient *c;
646
647 ch->is_loopback = GNUNET_YES;
648 c = GNUNET_CONTAINER_multihashmap_get (open_ports,
649 port);
650 if (NULL == c)
651 {
652 /* port closed, wait for it to possibly open */
653 ch->state = CADET_CHANNEL_LOOSE;
654 (void) GNUNET_CONTAINER_multihashmap_put (loose_channels,
655 port,
656 ch,
657 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
658 LOG (GNUNET_ERROR_TYPE_DEBUG,
659 "Created loose incoming loopback channel to port %s\n",
660 GNUNET_h2s (&ch->port));
661 }
662 else
663 {
664 GCCH_bind (ch,
665 c);
666 }
667 }
668 else
669 {
670 ch->t = GCP_get_tunnel (destination,
671 GNUNET_YES);
672 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
673 ch->ctn = GCT_add_channel (ch->t,
674 ch);
675 }
676 GNUNET_STATISTICS_update (stats,
677 "# channels",
678 1,
679 GNUNET_NO);
680 LOG (GNUNET_ERROR_TYPE_DEBUG,
681 "Created channel to port %s at peer %s for %s using %s\n",
682 GNUNET_h2s (port),
683 GCP_2s (destination),
684 GSC_2s (owner),
685 (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t));
686 return ch;
687}
688
689
690/**
691 * We had an incoming channel to a port that is closed.
692 * It has not been opened for a while, drop it.
693 *
694 * @param cls the channel to drop
695 */
696static void
697timeout_closed_cb (void *cls)
698{
699 struct CadetChannel *ch = cls;
700
701 ch->retry_control_task = NULL;
702 LOG (GNUNET_ERROR_TYPE_DEBUG,
703 "Closing incoming channel to port %s from peer %s due to timeout\n",
704 GNUNET_h2s (&ch->port),
705 GCP_2s (GCT_get_destination (ch->t)));
706 channel_destroy (ch);
707}
708
709
710/**
711 * Create a new channel based on a request coming in over the network.
712 *
713 * @param t tunnel to the remote peer
714 * @param ctn identifier of this channel in the tunnel
715 * @param port desired local port
716 * @param options options for the channel
717 * @return handle to the new channel
718 */
719struct CadetChannel *
720GCCH_channel_incoming_new (struct CadetTunnel *t,
721 struct GNUNET_CADET_ChannelTunnelNumber ctn,
722 const struct GNUNET_HashCode *port,
723 uint32_t options)
724{
725 struct CadetChannel *ch;
726 struct CadetClient *c;
727
728 ch = GNUNET_new (struct CadetChannel);
729 ch->port = *port;
730 ch->t = t;
731 ch->ctn = ctn;
732 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
733 ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER));
734 ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE));
735 ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER));
736 ch->max_pending_messages = (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
737 GNUNET_STATISTICS_update (stats,
738 "# channels",
739 1,
740 GNUNET_NO);
741
742 c = GNUNET_CONTAINER_multihashmap_get (open_ports,
743 port);
744 if (NULL == c)
745 {
746 /* port closed, wait for it to possibly open */
747 ch->state = CADET_CHANNEL_LOOSE;
748 (void) GNUNET_CONTAINER_multihashmap_put (loose_channels,
749 port,
750 ch,
751 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
752 GNUNET_assert (NULL == ch->retry_control_task);
753 ch->retry_control_task
754 = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT,
755 &timeout_closed_cb,
756 ch);
757 LOG (GNUNET_ERROR_TYPE_DEBUG,
758 "Created loose incoming channel to port %s from peer %s\n",
759 GNUNET_h2s (&ch->port),
760 GCP_2s (GCT_get_destination (ch->t)));
761 }
762 else
763 {
764 GCCH_bind (ch,
765 c);
766 }
767 GNUNET_STATISTICS_update (stats,
768 "# channels",
769 1,
770 GNUNET_NO);
771 return ch;
772}
773
774
775/**
776 * Function called once the tunnel confirms that we sent the
777 * ACK message. Just remembers it was sent, we do not expect
778 * ACKs for ACKs ;-).
779 *
780 * @param cls our `struct CadetChannel`.
781 * @param cid identifier of the connection within the tunnel, NULL
782 * if transmission failed
783 */
784static void
785send_ack_cb (void *cls,
786 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
787{
788 struct CadetChannel *ch = cls;
789
790 GNUNET_assert (NULL != ch->last_control_qe);
791 ch->last_control_qe = NULL;
792}
793
794
795/**
796 * Compute and send the current #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK to the other peer.
797 *
798 * @param ch channel to send the #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK for
799 */
800static void
801send_channel_data_ack (struct CadetChannel *ch)
802{
803 struct GNUNET_CADET_ChannelDataAckMessage msg;
804
805 if (GNUNET_NO == ch->reliable)
806 return; /* no ACKs */
807 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK);
808 msg.header.size = htons (sizeof (msg));
809 msg.ctn = ch->ctn;
810 msg.mid.mid = htonl (ntohl (ch->mid_recv.mid));
811 msg.futures = GNUNET_htonll (ch->mid_futures);
812 LOG (GNUNET_ERROR_TYPE_DEBUG,
813 "Sending DATA_ACK %u:%llX via %s\n",
814 (unsigned int) ntohl (msg.mid.mid),
815 (unsigned long long) ch->mid_futures,
816 GCCH_2s (ch));
817 if (NULL != ch->last_control_qe)
818 GCT_send_cancel (ch->last_control_qe);
819 ch->last_control_qe = GCT_send (ch->t,
820 &msg.header,
821 &send_ack_cb,
822 ch);
823}
824
825
826/**
827 * Send our initial #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the
828 * connection is up.
829 *
830 * @param cls the `struct CadetChannel`
831 */
832static void
833send_open_ack (void *cls)
834{
835 struct CadetChannel *ch = cls;
836 struct GNUNET_CADET_ChannelManageMessage msg;
837
838 ch->retry_control_task = NULL;
839 LOG (GNUNET_ERROR_TYPE_DEBUG,
840 "Sending CHANNEL_OPEN_ACK on %s\n",
841 GCCH_2s (ch));
842 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK);
843 msg.header.size = htons (sizeof (msg));
844 msg.reserved = htonl (0);
845 msg.ctn = ch->ctn;
846 if (NULL != ch->last_control_qe)
847 GCT_send_cancel (ch->last_control_qe);
848 ch->last_control_qe = GCT_send (ch->t,
849 &msg.header,
850 &send_ack_cb,
851 ch);
852}
853
854
855/**
856 * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for
857 * this channel. If the binding was successful, (re)transmit the
858 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.
859 *
860 * @param ch channel that got the duplicate open
861 * @param cti identifier of the connection that delivered the message
862 */
863void
864GCCH_handle_duplicate_open (struct CadetChannel *ch,
865 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
866{
867 if (NULL == ch->dest)
868 {
869 LOG (GNUNET_ERROR_TYPE_DEBUG,
870 "Ignoring duplicate CHANNEL_OPEN on %s: port is closed\n",
871 GCCH_2s (ch));
872 return;
873 }
874 if (NULL != ch->retry_control_task)
875 {
876 LOG (GNUNET_ERROR_TYPE_DEBUG,
877 "Ignoring duplicate CHANNEL_OPEN on %s: control message is pending\n",
878 GCCH_2s (ch));
879 return;
880 }
881 LOG (GNUNET_ERROR_TYPE_DEBUG,
882 "Retransmitting CHANNEL_OPEN_ACK on %s\n",
883 GCCH_2s (ch));
884 ch->retry_control_task
885 = GNUNET_SCHEDULER_add_now (&send_open_ack,
886 ch);
887}
888
889
890/**
891 * Send a #GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK to the client to solicit more messages.
892 *
893 * @param ch channel the ack is for
894 * @param to_owner #GNUNET_YES to send to owner,
895 * #GNUNET_NO to send to dest
896 */
897static void
898send_ack_to_client (struct CadetChannel *ch,
899 int to_owner)
900{
901 struct GNUNET_MQ_Envelope *env;
902 struct GNUNET_CADET_LocalAck *ack;
903 struct CadetChannelClient *ccc;
904
905 ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest;
906 if (NULL == ccc)
907 {
908 /* This can happen if we are just getting ACKs after
909 our local client already disconnected. */
910 GNUNET_assert (GNUNET_YES == ch->destroy);
911 return;
912 }
913 env = GNUNET_MQ_msg (ack,
914 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
915 ack->ccn = ccc->ccn;
916 LOG (GNUNET_ERROR_TYPE_DEBUG,
917 "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n",
918 GSC_2s (ccc->c),
919 (GNUNET_YES == to_owner) ? "owner" : "dest",
920 ntohl (ack->ccn.channel_of_client),
921 ch->pending_messages,
922 ch->max_pending_messages);
923 GSC_send_to_client (ccc->c,
924 env);
925}
926
927
928/**
929 * A client is bound to the port that we have a channel
930 * open to. Send the acknowledgement for the connection
931 * request and establish the link with the client.
932 *
933 * @param ch open incoming channel
934 * @param c client listening on the respective port
935 */
936void
937GCCH_bind (struct CadetChannel *ch,
938 struct CadetClient *c)
939{
940 uint32_t options;
941 struct CadetChannelClient *cccd;
942
943 LOG (GNUNET_ERROR_TYPE_DEBUG,
944 "Binding %s from %s to port %s of %s\n",
945 GCCH_2s (ch),
946 GCT_2s (ch->t),
947 GNUNET_h2s (&ch->port),
948 GSC_2s (c));
949 if (NULL != ch->retry_control_task)
950 {
951 /* there might be a timeout task here */
952 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
953 ch->retry_control_task = NULL;
954 }
955 options = 0;
956 if (ch->nobuffer)
957 options |= GNUNET_CADET_OPTION_NOBUFFER;
958 if (ch->reliable)
959 options |= GNUNET_CADET_OPTION_RELIABLE;
960 if (ch->out_of_order)
961 options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
962 cccd = GNUNET_new (struct CadetChannelClient);
963 GNUNET_assert (NULL == ch->dest);
964 ch->dest = cccd;
965 cccd->c = c;
966 cccd->client_ready = GNUNET_YES;
967 cccd->ccn = GSC_bind (c,
968 ch,
969 (GNUNET_YES == ch->is_loopback)
970 ? GCP_get (&my_full_id,
971 GNUNET_YES)
972 : GCT_get_destination (ch->t),
973 &ch->port,
974 options);
975 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
976 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
977 ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */
978 if (GNUNET_YES == ch->is_loopback)
979 {
980 ch->state = CADET_CHANNEL_OPEN_SENT;
981 GCCH_handle_channel_open_ack (ch,
982 NULL);
983 }
984 else
985 {
986 /* notify other peer that we accepted the connection */
987 ch->state = CADET_CHANNEL_READY;
988 ch->retry_control_task
989 = GNUNET_SCHEDULER_add_now (&send_open_ack,
990 ch);
991 }
992 /* give client it's initial supply of ACKs */
993 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
994 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
995 for (unsigned int i=0;i<ch->max_pending_messages;i++)
996 send_ack_to_client (ch,
997 GNUNET_NO);
998}
999
1000
1001/**
1002 * One of our clients has disconnected, tell the other one that we
1003 * are finished. Done asynchronously to avoid concurrent modification
1004 * issues if this is the same client.
1005 *
1006 * @param cls the `struct CadetChannel` where one of the ends is now dead
1007 */
1008static void
1009signal_remote_destroy_cb (void *cls)
1010{
1011 struct CadetChannel *ch = cls;
1012 struct CadetChannelClient *ccc;
1013
1014 /* Find which end is left... */
1015 ch->retry_control_task = NULL;
1016 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1017 GSC_handle_remote_channel_destroy (ccc->c,
1018 ccc->ccn,
1019 ch);
1020 channel_destroy (ch);
1021}
1022
1023
1024/**
1025 * Destroy locally created channel. Called by the local client, so no
1026 * need to tell the client.
1027 *
1028 * @param ch channel to destroy
1029 * @param c client that caused the destruction
1030 * @param ccn client number of the client @a c
1031 */
1032void
1033GCCH_channel_local_destroy (struct CadetChannel *ch,
1034 struct CadetClient *c,
1035 struct GNUNET_CADET_ClientChannelNumber ccn)
1036{
1037 LOG (GNUNET_ERROR_TYPE_DEBUG,
1038 "%s asks for destruction of %s\n",
1039 GSC_2s (c),
1040 GCCH_2s (ch));
1041 GNUNET_assert (NULL != c);
1042 if ( (NULL != ch->owner) &&
1043 (c == ch->owner->c) &&
1044 (ccn.channel_of_client == ch->owner->ccn.channel_of_client) )
1045 {
1046 free_channel_client (ch->owner);
1047 ch->owner = NULL;
1048 }
1049 else if ( (NULL != ch->dest) &&
1050 (c == ch->dest->c) &&
1051 (ccn.channel_of_client == ch->dest->ccn.channel_of_client) )
1052 {
1053 free_channel_client (ch->dest);
1054 ch->dest = NULL;
1055 }
1056 else
1057 {
1058 GNUNET_assert (0);
1059 }
1060
1061 if (GNUNET_YES == ch->destroy)
1062 {
1063 /* other end already destroyed, with the local client gone, no need
1064 to finish transmissions, just destroy immediately. */
1065 channel_destroy (ch);
1066 return;
1067 }
1068 if ( (NULL != ch->head_sent) &&
1069 ( (NULL != ch->owner) ||
1070 (NULL != ch->dest) ) )
1071 {
1072 /* Wait for other end to destroy us as well,
1073 and otherwise allow send queue to be transmitted first */
1074 ch->destroy = GNUNET_YES;
1075 return;
1076 }
1077 if ( (GNUNET_YES == ch->is_loopback) &&
1078 ( (NULL != ch->owner) ||
1079 (NULL != ch->dest) ) )
1080 {
1081 if (NULL != ch->retry_control_task)
1082 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1083 ch->retry_control_task
1084 = GNUNET_SCHEDULER_add_now (&signal_remote_destroy_cb,
1085 ch);
1086 return;
1087 }
1088 if (GNUNET_NO == ch->is_loopback)
1089 {
1090 /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */
1091 switch (ch->state)
1092 {
1093 case CADET_CHANNEL_NEW:
1094 /* We gave up on a channel that we created as a client to a remote
1095 target, but that never went anywhere. Nothing to do here. */
1096 break;
1097 case CADET_CHANNEL_LOOSE:
1098 GSC_drop_loose_channel (&ch->port,
1099 ch);
1100 break;
1101 default:
1102 GCT_send_channel_destroy (ch->t,
1103 ch->ctn);
1104 }
1105 }
1106 /* Nothing left to do, just finish destruction */
1107 channel_destroy (ch);
1108}
1109
1110
1111/**
1112 * We got an acknowledgement for the creation of the channel
1113 * (the port is open on the other side). Begin transmissions.
1114 *
1115 * @param ch channel to destroy
1116 * @param cti identifier of the connection that delivered the message
1117 */
1118void
1119GCCH_handle_channel_open_ack (struct CadetChannel *ch,
1120 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
1121{
1122 switch (ch->state)
1123 {
1124 case CADET_CHANNEL_NEW:
1125 /* this should be impossible */
1126 GNUNET_break (0);
1127 break;
1128 case CADET_CHANNEL_LOOSE:
1129 /* This makes no sense. */
1130 GNUNET_break_op (0);
1131 break;
1132 case CADET_CHANNEL_OPEN_SENT:
1133 if (NULL == ch->owner)
1134 {
1135 /* We're not the owner, wrong direction! */
1136 GNUNET_break_op (0);
1137 return;
1138 }
1139 LOG (GNUNET_ERROR_TYPE_DEBUG,
1140 "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n",
1141 GCCH_2s (ch));
1142 if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */
1143 {
1144 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1145 ch->retry_control_task = NULL;
1146 }
1147 ch->state = CADET_CHANNEL_READY;
1148 /* On first connect, send client as many ACKs as we allow messages
1149 to be buffered! */
1150 for (unsigned int i=0;i<ch->max_pending_messages;i++)
1151 send_ack_to_client (ch,
1152 GNUNET_YES);
1153 break;
1154 case CADET_CHANNEL_READY:
1155 /* duplicate ACK, maybe we retried the CREATE. Ignore. */
1156 LOG (GNUNET_ERROR_TYPE_DEBUG,
1157 "Received duplicate channel OPEN_ACK for %s\n",
1158 GCCH_2s (ch));
1159 GNUNET_STATISTICS_update (stats,
1160 "# duplicate CREATE_ACKs",
1161 1,
1162 GNUNET_NO);
1163 break;
1164 }
1165}
1166
1167
1168/**
1169 * Test if element @a e1 comes before element @a e2.
1170 *
1171 * @param cls closure, to a flag where we indicate duplicate packets
1172 * @param m1 a message of to sort
1173 * @param m2 another message to sort
1174 * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO
1175 */
1176static int
1177is_before (void *cls,
1178 struct CadetOutOfOrderMessage *m1,
1179 struct CadetOutOfOrderMessage *m2)
1180{
1181 int *duplicate = cls;
1182 uint32_t v1 = ntohl (m1->mid.mid);
1183 uint32_t v2 = ntohl (m2->mid.mid);
1184 uint32_t delta;
1185
1186 delta = v2 - v1;
1187 if (0 == delta)
1188 *duplicate = GNUNET_YES;
1189 if (delta > (uint32_t) INT_MAX)
1190 {
1191 /* in overflow range, we can safely assume we wrapped around */
1192 return GNUNET_NO;
1193 }
1194 else
1195 {
1196 /* result is small, thus v2 > v1, thus m1 < m2 */
1197 return GNUNET_YES;
1198 }
1199}
1200
1201
1202/**
1203 * We got payload data for a channel. Pass it on to the client
1204 * and send an ACK to the other end (once flow control allows it!)
1205 *
1206 * @param ch channel that got data
1207 * @param cti identifier of the connection that delivered the message
1208 * @param msg message that was received
1209 */
1210void
1211GCCH_handle_channel_plaintext_data (struct CadetChannel *ch,
1212 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1213 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
1214{
1215 struct GNUNET_MQ_Envelope *env;
1216 struct GNUNET_CADET_LocalData *ld;
1217 struct CadetChannelClient *ccc;
1218 size_t payload_size;
1219 struct CadetOutOfOrderMessage *com;
1220 int duplicate;
1221 uint32_t mid_min;
1222 uint32_t mid_max;
1223 uint32_t mid_msg;
1224 uint32_t delta;
1225
1226 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1227 if ( (GNUNET_YES == ch->destroy) &&
1228 (NULL == ch->owner) &&
1229 (NULL == ch->dest) )
1230 {
1231 /* This client is gone, but we still have messages to send to
1232 the other end (which is why @a ch is not yet dead). However,
1233 we cannot pass messages to our client anymore. */
1234 LOG (GNUNET_ERROR_TYPE_DEBUG,
1235 "Dropping incoming payload on %s as this end is already closed\n",
1236 GCCH_2s (ch));
1237 /* send back DESTROY notification to stop further retransmissions! */
1238 GCT_send_channel_destroy (ch->t,
1239 ch->ctn);
1240 return;
1241 }
1242 payload_size = ntohs (msg->header.size) - sizeof (*msg);
1243 env = GNUNET_MQ_msg_extra (ld,
1244 payload_size,
1245 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1246 ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn;
1247 GNUNET_memcpy (&ld[1],
1248 &msg[1],
1249 payload_size);
1250 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1251 if ( (GNUNET_YES == ccc->client_ready) &&
1252 ( (GNUNET_YES == ch->out_of_order) ||
1253 (msg->mid.mid == ch->mid_recv.mid) ) )
1254 {
1255 LOG (GNUNET_ERROR_TYPE_DEBUG,
1256 "Giving %u bytes of payload with MID %u from %s to client %s\n",
1257 (unsigned int) payload_size,
1258 ntohl (msg->mid.mid),
1259 GCCH_2s (ch),
1260 GSC_2s (ccc->c));
1261 ccc->client_ready = GNUNET_NO;
1262 GSC_send_to_client (ccc->c,
1263 env);
1264 ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid));
1265 ch->mid_futures >>= 1;
1266 send_channel_data_ack (ch);
1267 return;
1268 }
1269
1270 if (GNUNET_YES == ch->reliable)
1271 {
1272 /* check if message ought to be dropped because it is ancient/too distant/duplicate */
1273 mid_min = ntohl (ch->mid_recv.mid);
1274 mid_max = mid_min + ch->max_pending_messages;
1275 mid_msg = ntohl (msg->mid.mid);
1276 if ( ( (uint32_t) (mid_msg - mid_min) > ch->max_pending_messages) ||
1277 ( (uint32_t) (mid_max - mid_msg) > ch->max_pending_messages) )
1278 {
1279 LOG (GNUNET_ERROR_TYPE_DEBUG,
1280 "%s at %u drops ancient or far-future message %u\n",
1281 GCCH_2s (ch),
1282 (unsigned int) mid_min,
1283 ntohl (msg->mid.mid));
1284
1285 GNUNET_STATISTICS_update (stats,
1286 "# duplicate DATA (ancient or future)",
1287 1,
1288 GNUNET_NO);
1289 GNUNET_MQ_discard (env);
1290 send_channel_data_ack (ch);
1291 return;
1292 }
1293 /* mark bit for future ACKs */
1294 delta = mid_msg - mid_min - 1; /* overflow/underflow are OK here */
1295 if (delta < 64)
1296 {
1297 if (0 != (ch->mid_futures & (1LLU << delta)))
1298 {
1299 /* Duplicate within the queue, drop also */
1300 LOG (GNUNET_ERROR_TYPE_DEBUG,
1301 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1302 (unsigned int) payload_size,
1303 GCCH_2s (ch),
1304 ntohl (msg->mid.mid));
1305 GNUNET_STATISTICS_update (stats,
1306 "# duplicate DATA",
1307 1,
1308 GNUNET_NO);
1309 GNUNET_MQ_discard (env);
1310 send_channel_data_ack (ch);
1311 return;
1312 }
1313 ch->mid_futures |= (1LLU << delta);
1314 LOG (GNUNET_ERROR_TYPE_DEBUG,
1315 "Marked bit %llX for mid %u (base: %u); now: %llX\n",
1316 (1LLU << delta),
1317 mid_msg,
1318 mid_min,
1319 ch->mid_futures);
1320 }
1321 }
1322 else /* ! ch->reliable */
1323 {
1324 /* Channel is unreliable, so we do not ACK. But we also cannot
1325 allow buffering everything, so check if we have space... */
1326 if (ccc->num_recv >= ch->max_pending_messages)
1327 {
1328 struct CadetOutOfOrderMessage *drop;
1329
1330 /* Yep, need to drop. Drop the oldest message in
1331 the buffer. */
1332 LOG (GNUNET_ERROR_TYPE_DEBUG,
1333 "Queue full due slow client on %s, dropping oldest message\n",
1334 GCCH_2s (ch));
1335 GNUNET_STATISTICS_update (stats,
1336 "# messages dropped due to slow client",
1337 1,
1338 GNUNET_NO);
1339 drop = ccc->head_recv;
1340 GNUNET_CONTAINER_DLL_remove (ccc->head_recv,
1341 ccc->tail_recv,
1342 drop);
1343 ccc->num_recv--;
1344 GNUNET_MQ_discard (drop->env);
1345 GNUNET_free (drop);
1346 }
1347 }
1348
1349 /* Insert message into sorted out-of-order queue */
1350 com = GNUNET_new (struct CadetOutOfOrderMessage);
1351 com->mid = msg->mid;
1352 com->env = env;
1353 duplicate = GNUNET_NO;
1354 GNUNET_CONTAINER_DLL_insert_sorted (struct CadetOutOfOrderMessage,
1355 is_before,
1356 &duplicate,
1357 ccc->head_recv,
1358 ccc->tail_recv,
1359 com);
1360 ccc->num_recv++;
1361 if (GNUNET_YES == duplicate)
1362 {
1363 /* Duplicate within the queue, drop also (this is not covered by
1364 the case above if "delta" >= 64, which could be the case if
1365 max_pending_messages is also >= 64 or if our client is unready
1366 and we are seeing retransmissions of the message our client is
1367 blocked on. */
1368 LOG (GNUNET_ERROR_TYPE_DEBUG,
1369 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1370 (unsigned int) payload_size,
1371 GCCH_2s (ch),
1372 ntohl (msg->mid.mid));
1373 GNUNET_STATISTICS_update (stats,
1374 "# duplicate DATA",
1375 1,
1376 GNUNET_NO);
1377 GNUNET_CONTAINER_DLL_remove (ccc->head_recv,
1378 ccc->tail_recv,
1379 com);
1380 ccc->num_recv--;
1381 GNUNET_MQ_discard (com->env);
1382 GNUNET_free (com);
1383 send_channel_data_ack (ch);
1384 return;
1385 }
1386 LOG (GNUNET_ERROR_TYPE_DEBUG,
1387 "Queued %s payload of %u bytes on %s-%X(%p) (mid %u, need %u first)\n",
1388 (GNUNET_YES == ccc->client_ready)
1389 ? "out-of-order"
1390 : "client-not-ready",
1391 (unsigned int) payload_size,
1392 GCCH_2s (ch),
1393 ntohl (ccc->ccn.channel_of_client),
1394 ccc,
1395 ntohl (msg->mid.mid),
1396 ntohl (ch->mid_recv.mid));
1397 /* NOTE: this ACK we _could_ skip, as the packet is out-of-order and
1398 the sender may already be transmitting the previous one. Needs
1399 experimental evaluation to see if/when this ACK helps or
1400 hurts. (We might even want another option.) */
1401 send_channel_data_ack (ch);
1402}
1403
1404
1405/**
1406 * Function called once the tunnel has sent one of our messages.
1407 * If the message is unreliable, simply frees the `crm`. If the
1408 * message was reliable, calculate retransmission time and
1409 * wait for ACK (or retransmit).
1410 *
1411 * @param cls the `struct CadetReliableMessage` that was sent
1412 * @param cid identifier of the connection within the tunnel, NULL
1413 * if transmission failed
1414 */
1415static void
1416data_sent_cb (void *cls,
1417 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
1418
1419
1420/**
1421 * We need to retry a transmission, the last one took too long to
1422 * be acknowledged.
1423 *
1424 * @param cls the `struct CadetChannel` where we need to retransmit
1425 */
1426static void
1427retry_transmission (void *cls)
1428{
1429 struct CadetChannel *ch = cls;
1430 struct CadetReliableMessage *crm = ch->head_sent;
1431
1432 ch->retry_data_task = NULL;
1433 GNUNET_assert (NULL == crm->qe);
1434 LOG (GNUNET_ERROR_TYPE_DEBUG,
1435 "Retrying transmission on %s of message %u\n",
1436 GCCH_2s (ch),
1437 (unsigned int) ntohl (crm->data_message->mid.mid));
1438 crm->qe = GCT_send (ch->t,
1439 &crm->data_message->header,
1440 &data_sent_cb,
1441 crm);
1442 GNUNET_assert (NULL == ch->retry_data_task);
1443}
1444
1445
1446/**
1447 * We got an PLAINTEXT_DATA_ACK for a message in our queue, remove it from
1448 * the queue and tell our client that it can send more.
1449 *
1450 * @param ch the channel that got the PLAINTEXT_DATA_ACK
1451 * @param cti identifier of the connection that delivered the message
1452 * @param crm the message that got acknowledged
1453 */
1454static void
1455handle_matching_ack (struct CadetChannel *ch,
1456 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1457 struct CadetReliableMessage *crm)
1458{
1459 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
1460 ch->tail_sent,
1461 crm);
1462 ch->pending_messages--;
1463 GNUNET_assert (ch->pending_messages < ch->max_pending_messages);
1464 LOG (GNUNET_ERROR_TYPE_DEBUG,
1465 "Received DATA_ACK on %s for message %u (%u ACKs pending)\n",
1466 GCCH_2s (ch),
1467 (unsigned int) ntohl (crm->data_message->mid.mid),
1468 ch->pending_messages);
1469 if (NULL != crm->qe)
1470 {
1471 GCT_send_cancel (crm->qe);
1472 crm->qe = NULL;
1473 }
1474 if ( (1 == crm->num_transmissions) &&
1475 (NULL != cti) )
1476 {
1477 GCC_ack_observed (cti);
1478 if (0 == memcmp (cti,
1479 &crm->connection_taken,
1480 sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier)))
1481 {
1482 GCC_latency_observed (cti,
1483 GNUNET_TIME_absolute_get_duration (crm->first_transmission_time));
1484 }
1485 }
1486 GNUNET_free (crm->data_message);
1487 GNUNET_free (crm);
1488 send_ack_to_client (ch,
1489 (NULL == ch->owner)
1490 ? GNUNET_NO
1491 : GNUNET_YES);
1492}
1493
1494
1495/**
1496 * We got an acknowledgement for payload data for a channel.
1497 * Possibly resume transmissions.
1498 *
1499 * @param ch channel that got the ack
1500 * @param cti identifier of the connection that delivered the message
1501 * @param ack details about what was received
1502 */
1503void
1504GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch,
1505 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1506 const struct GNUNET_CADET_ChannelDataAckMessage *ack)
1507{
1508 struct CadetReliableMessage *crm;
1509 struct CadetReliableMessage *crmn;
1510 int found;
1511 uint32_t mid_base;
1512 uint64_t mid_mask;
1513 unsigned int delta;
1514
1515 GNUNET_break (GNUNET_NO == ch->is_loopback);
1516 if (GNUNET_NO == ch->reliable)
1517 {
1518 /* not expecting ACKs on unreliable channel, odd */
1519 GNUNET_break_op (0);
1520 return;
1521 }
1522 /* mid_base is the MID of the next message that the
1523 other peer expects (i.e. that is missing!), everything
1524 LOWER (but excluding mid_base itself) was received. */
1525 mid_base = ntohl (ack->mid.mid);
1526 mid_mask = GNUNET_htonll (ack->futures);
1527 found = GNUNET_NO;
1528 for (crm = ch->head_sent;
1529 NULL != crm;
1530 crm = crmn)
1531 {
1532 crmn = crm->next;
1533 delta = (unsigned int) (ntohl (crm->data_message->mid.mid) - mid_base);
1534 if (delta >= UINT_MAX - ch->max_pending_messages)
1535 {
1536 /* overflow, means crm was a bit in the past, so this ACK counts for it. */
1537 LOG (GNUNET_ERROR_TYPE_DEBUG,
1538 "Got DATA_ACK with base %u satisfying past message %u on %s\n",
1539 (unsigned int) mid_base,
1540 ntohl (crm->data_message->mid.mid),
1541 GCCH_2s (ch));
1542 handle_matching_ack (ch,
1543 cti,
1544 crm);
1545 found = GNUNET_YES;
1546 continue;
1547 }
1548 delta--;
1549 if (delta >= 64)
1550 continue;
1551 LOG (GNUNET_ERROR_TYPE_DEBUG,
1552 "Testing bit %llX for mid %u (base: %u)\n",
1553 (1LLU << delta),
1554 ntohl (crm->data_message->mid.mid),
1555 mid_base);
1556 if (0 != (mid_mask & (1LLU << delta)))
1557 {
1558 LOG (GNUNET_ERROR_TYPE_DEBUG,
1559 "Got DATA_ACK with mask for %u on %s\n",
1560 ntohl (crm->data_message->mid.mid),
1561 GCCH_2s (ch));
1562 handle_matching_ack (ch,
1563 cti,
1564 crm);
1565 found = GNUNET_YES;
1566 }
1567 }
1568 if (GNUNET_NO == found)
1569 {
1570 /* ACK for message we already dropped, might have been a
1571 duplicate ACK? Ignore. */
1572 LOG (GNUNET_ERROR_TYPE_DEBUG,
1573 "Duplicate DATA_ACK on %s, ignoring\n",
1574 GCCH_2s (ch));
1575 GNUNET_STATISTICS_update (stats,
1576 "# duplicate DATA_ACKs",
1577 1,
1578 GNUNET_NO);
1579 return;
1580 }
1581 if (NULL != ch->retry_data_task)
1582 {
1583 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1584 ch->retry_data_task = NULL;
1585 }
1586 if ( (NULL != ch->head_sent) &&
1587 (NULL == ch->head_sent->qe) )
1588 ch->retry_data_task
1589 = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1590 &retry_transmission,
1591 ch);
1592}
1593
1594
1595/**
1596 * Destroy channel, based on the other peer closing the
1597 * connection. Also needs to remove this channel from
1598 * the tunnel.
1599 *
1600 * @param ch channel to destroy
1601 * @param cti identifier of the connection that delivered the message,
1602 * NULL if we are simulating receiving a destroy due to shutdown
1603 */
1604void
1605GCCH_handle_remote_destroy (struct CadetChannel *ch,
1606 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
1607{
1608 struct CadetChannelClient *ccc;
1609
1610 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1611 LOG (GNUNET_ERROR_TYPE_DEBUG,
1612 "Received remote channel DESTROY for %s\n",
1613 GCCH_2s (ch));
1614 if (GNUNET_YES == ch->destroy)
1615 {
1616 /* Local client already gone, this is instant-death. */
1617 channel_destroy (ch);
1618 return;
1619 }
1620 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1621 if ( (NULL != ccc) &&
1622 (NULL != ccc->head_recv) )
1623 {
1624 LOG (GNUNET_ERROR_TYPE_WARNING,
1625 "Lost end of transmission due to remote shutdown on %s\n",
1626 GCCH_2s (ch));
1627 /* FIXME: change API to notify client about truncated transmission! */
1628 }
1629 ch->destroy = GNUNET_YES;
1630 if (NULL != ccc)
1631 GSC_handle_remote_channel_destroy (ccc->c,
1632 ccc->ccn,
1633 ch);
1634 channel_destroy (ch);
1635}
1636
1637
1638/**
1639 * Test if element @a e1 comes before element @a e2.
1640 *
1641 * @param cls closure, to a flag where we indicate duplicate packets
1642 * @param crm1 an element of to sort
1643 * @param crm2 another element to sort
1644 * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO
1645 */
1646static int
1647cmp_crm_by_next_retry (void *cls,
1648 struct CadetReliableMessage *crm1,
1649 struct CadetReliableMessage *crm2)
1650{
1651 if (crm1->next_retry.abs_value_us <
1652 crm2->next_retry.abs_value_us)
1653 return GNUNET_YES;
1654 return GNUNET_NO;
1655}
1656
1657
1658/**
1659 * Function called once the tunnel has sent one of our messages.
1660 * If the message is unreliable, simply frees the `crm`. If the
1661 * message was reliable, calculate retransmission time and
1662 * wait for ACK (or retransmit).
1663 *
1664 * @param cls the `struct CadetReliableMessage` that was sent
1665 * @param cid identifier of the connection within the tunnel, NULL
1666 * if transmission failed
1667 */
1668static void
1669data_sent_cb (void *cls,
1670 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
1671{
1672 struct CadetReliableMessage *crm = cls;
1673 struct CadetChannel *ch = crm->ch;
1674
1675 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1676 GNUNET_assert (NULL != crm->qe);
1677 crm->qe = NULL;
1678 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
1679 ch->tail_sent,
1680 crm);
1681 if (GNUNET_NO == ch->reliable)
1682 {
1683 GNUNET_free (crm->data_message);
1684 GNUNET_free (crm);
1685 ch->pending_messages--;
1686 send_ack_to_client (ch,
1687 (NULL == ch->owner)
1688 ? GNUNET_NO
1689 : GNUNET_YES);
1690 return;
1691 }
1692 if (NULL == cid)
1693 {
1694 /* There was an error sending. */
1695 crm->num_transmissions = GNUNET_SYSERR;
1696 }
1697 else if (GNUNET_SYSERR != crm->num_transmissions)
1698 {
1699 /* Increment transmission counter, and possibly store @a cid
1700 if this was the first transmission. */
1701 crm->num_transmissions++;
1702 if (1 == crm->num_transmissions)
1703 {
1704 crm->first_transmission_time = GNUNET_TIME_absolute_get ();
1705 crm->connection_taken = *cid;
1706 GCC_ack_expected (cid);
1707 }
1708 }
1709 if ( (0 == crm->retry_delay.rel_value_us) &&
1710 (NULL != cid) )
1711 {
1712 struct CadetConnection *cc = GCC_lookup (cid);
1713
1714 if (NULL != cc)
1715 crm->retry_delay = GCC_get_metrics (cc)->aged_latency;
1716 else
1717 crm->retry_delay = ch->retry_time;
1718 }
1719 crm->retry_delay = GNUNET_TIME_STD_BACKOFF (crm->retry_delay);
1720 crm->retry_delay = GNUNET_TIME_relative_max (crm->retry_delay,
1721 MIN_RTT_DELAY);
1722 crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay);
1723
1724 GNUNET_CONTAINER_DLL_insert_sorted (struct CadetReliableMessage,
1725 cmp_crm_by_next_retry,
1726 NULL,
1727 ch->head_sent,
1728 ch->tail_sent,
1729 crm);
1730 LOG (GNUNET_ERROR_TYPE_DEBUG,
1731 "Message %u sent, next transmission on %s in %s\n",
1732 (unsigned int) ntohl (crm->data_message->mid.mid),
1733 GCCH_2s (ch),
1734 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (ch->head_sent->next_retry),
1735 GNUNET_YES));
1736 if (NULL == ch->head_sent->qe)
1737 {
1738 if (NULL != ch->retry_data_task)
1739 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1740 ch->retry_data_task
1741 = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1742 &retry_transmission,
1743 ch);
1744 }
1745}
1746
1747
1748/**
1749 * Handle data given by a client.
1750 *
1751 * Check whether the client is allowed to send in this tunnel, save if
1752 * channel is reliable and send an ACK to the client if there is still
1753 * buffer space in the tunnel.
1754 *
1755 * @param ch Channel.
1756 * @param sender_ccn ccn of the sender
1757 * @param buf payload to transmit.
1758 * @param buf_len number of bytes in @a buf
1759 * @return #GNUNET_OK if everything goes well,
1760 * #GNUNET_SYSERR in case of an error.
1761 */
1762int
1763GCCH_handle_local_data (struct CadetChannel *ch,
1764 struct GNUNET_CADET_ClientChannelNumber sender_ccn,
1765 const char *buf,
1766 size_t buf_len)
1767{
1768 struct CadetReliableMessage *crm;
1769
1770 if (ch->pending_messages > ch->max_pending_messages)
1771 {
1772 GNUNET_break (0);
1773 return GNUNET_SYSERR;
1774 }
1775 if (GNUNET_YES == ch->destroy)
1776 {
1777 /* we are going down, drop messages */
1778 return GNUNET_OK;
1779 }
1780 ch->pending_messages++;
1781
1782 if (GNUNET_YES == ch->is_loopback)
1783 {
1784 struct CadetChannelClient *receiver;
1785 struct GNUNET_MQ_Envelope *env;
1786 struct GNUNET_CADET_LocalData *ld;
1787 int ack_to_owner;
1788
1789 env = GNUNET_MQ_msg_extra (ld,
1790 buf_len,
1791 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1792 if ( (NULL != ch->owner) &&
1793 (sender_ccn.channel_of_client ==
1794 ch->owner->ccn.channel_of_client) )
1795 {
1796 receiver = ch->dest;
1797 ack_to_owner = GNUNET_YES;
1798 }
1799 else if ( (NULL != ch->dest) &&
1800 (sender_ccn.channel_of_client ==
1801 ch->dest->ccn.channel_of_client) )
1802 {
1803 receiver = ch->owner;
1804 ack_to_owner = GNUNET_NO;
1805 }
1806 else
1807 {
1808 GNUNET_break (0);
1809 return GNUNET_SYSERR;
1810 }
1811 GNUNET_assert (NULL != receiver);
1812 ld->ccn = receiver->ccn;
1813 GNUNET_memcpy (&ld[1],
1814 buf,
1815 buf_len);
1816 if (GNUNET_YES == receiver->client_ready)
1817 {
1818 ch->pending_messages--;
1819 GSC_send_to_client (receiver->c,
1820 env);
1821 send_ack_to_client (ch,
1822 ack_to_owner);
1823 }
1824 else
1825 {
1826 struct CadetOutOfOrderMessage *oom;
1827
1828 oom = GNUNET_new (struct CadetOutOfOrderMessage);
1829 oom->env = env;
1830 GNUNET_CONTAINER_DLL_insert_tail (receiver->head_recv,
1831 receiver->tail_recv,
1832 oom);
1833 receiver->num_recv++;
1834 }
1835 return GNUNET_OK;
1836 }
1837
1838 /* Everything is correct, send the message. */
1839 crm = GNUNET_malloc (sizeof (*crm));
1840 crm->ch = ch;
1841 crm->data_message = GNUNET_malloc (sizeof (struct GNUNET_CADET_ChannelAppDataMessage)
1842 + buf_len);
1843 crm->data_message->header.size = htons (sizeof (struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1844 crm->data_message->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
1845 ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
1846 crm->data_message->mid = ch->mid_send;
1847 crm->data_message->ctn = ch->ctn;
1848 GNUNET_memcpy (&crm->data_message[1],
1849 buf,
1850 buf_len);
1851 GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent,
1852 ch->tail_sent,
1853 crm);
1854 LOG (GNUNET_ERROR_TYPE_DEBUG,
1855 "Sending message %u from local client to %s with %u bytes\n",
1856 ntohl (crm->data_message->mid.mid),
1857 GCCH_2s (ch),
1858 buf_len);
1859 if (NULL != ch->retry_data_task)
1860 {
1861 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1862 ch->retry_data_task = NULL;
1863 }
1864 crm->qe = GCT_send (ch->t,
1865 &crm->data_message->header,
1866 &data_sent_cb,
1867 crm);
1868 GNUNET_assert (NULL == ch->retry_data_task);
1869 return GNUNET_OK;
1870}
1871
1872
1873/**
1874 * Handle ACK from client on local channel. Means the client is ready
1875 * for more data, see if we have any for it.
1876 *
1877 * @param ch channel to destroy
1878 * @param client_ccn ccn of the client sending the ack
1879 */
1880void
1881GCCH_handle_local_ack (struct CadetChannel *ch,
1882 struct GNUNET_CADET_ClientChannelNumber client_ccn)
1883{
1884 struct CadetChannelClient *ccc;
1885 struct CadetOutOfOrderMessage *com;
1886
1887 if ( (NULL != ch->owner) &&
1888 (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client) )
1889 ccc = ch->owner;
1890 else if ( (NULL != ch->dest) &&
1891 (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client) )
1892 ccc = ch->dest;
1893 else
1894 GNUNET_assert (0);
1895 ccc->client_ready = GNUNET_YES;
1896 com = ccc->head_recv;
1897 if (NULL == com)
1898 {
1899 LOG (GNUNET_ERROR_TYPE_DEBUG,
1900 "Got LOCAL_ACK, %s-%X ready to receive more data, but none pending on %s-%X(%p)!\n",
1901 GSC_2s (ccc->c),
1902 ntohl (client_ccn.channel_of_client),
1903 GCCH_2s (ch),
1904 ntohl (ccc->ccn.channel_of_client),
1905 ccc);
1906 return; /* none pending */
1907 }
1908 if (GNUNET_YES == ch->is_loopback)
1909 {
1910 int to_owner;
1911
1912 /* Messages are always in-order, just send */
1913 GNUNET_CONTAINER_DLL_remove (ccc->head_recv,
1914 ccc->tail_recv,
1915 com);
1916 ccc->num_recv--;
1917 GSC_send_to_client (ccc->c,
1918 com->env);
1919 /* Notify sender that we can receive more */
1920 if ( (NULL != ch->owner) &&
1921 (ccc->ccn.channel_of_client ==
1922 ch->owner->ccn.channel_of_client) )
1923 {
1924 to_owner = GNUNET_NO;
1925 }
1926 else
1927 {
1928 GNUNET_assert ( (NULL != ch->dest) &&
1929 (ccc->ccn.channel_of_client ==
1930 ch->dest->ccn.channel_of_client) );
1931 to_owner = GNUNET_YES;
1932 }
1933 send_ack_to_client (ch,
1934 to_owner);
1935 GNUNET_free (com);
1936 return;
1937 }
1938
1939 if ( (com->mid.mid != ch->mid_recv.mid) &&
1940 (GNUNET_NO == ch->out_of_order) &&
1941 (GNUNET_YES == ch->reliable) )
1942 {
1943 LOG (GNUNET_ERROR_TYPE_DEBUG,
1944 "Got LOCAL_ACK, %s-%X ready to receive more data (but next one is out-of-order %u vs. %u)!\n",
1945 GSC_2s (ccc->c),
1946 ntohl (ccc->ccn.channel_of_client),
1947 ntohl (com->mid.mid),
1948 ntohl (ch->mid_recv.mid));
1949 return; /* missing next one in-order */
1950 }
1951
1952 LOG (GNUNET_ERROR_TYPE_DEBUG,
1953 "Got LOCAL_ACK, giving payload message %u to %s-%X on %s\n",
1954 ntohl (com->mid.mid),
1955 GSC_2s (ccc->c),
1956 ntohl (ccc->ccn.channel_of_client),
1957 GCCH_2s (ch));
1958
1959 /* all good, pass next message to client */
1960 GNUNET_CONTAINER_DLL_remove (ccc->head_recv,
1961 ccc->tail_recv,
1962 com);
1963 ccc->num_recv--;
1964 /* FIXME: if unreliable, this is not aggressive
1965 enough, as it would be OK to have lost some! */
1966
1967 ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid));
1968 ch->mid_futures >>= 1; /* equivalent to division by 2 */
1969 ccc->client_ready = GNUNET_NO;
1970 GSC_send_to_client (ccc->c,
1971 com->env);
1972 GNUNET_free (com);
1973 send_channel_data_ack (ch);
1974 if (NULL != ccc->head_recv)
1975 return;
1976 if (GNUNET_NO == ch->destroy)
1977 return;
1978 GCT_send_channel_destroy (ch->t,
1979 ch->ctn);
1980 channel_destroy (ch);
1981}
1982
1983
1984#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-chn",__VA_ARGS__)
1985
1986
1987/**
1988 * Log channel info.
1989 *
1990 * @param ch Channel.
1991 * @param level Debug level to use.
1992 */
1993void
1994GCCH_debug (struct CadetChannel *ch,
1995 enum GNUNET_ErrorType level)
1996{
1997 int do_log;
1998
1999 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
2000 "cadet-chn",
2001 __FILE__, __FUNCTION__, __LINE__);
2002 if (0 == do_log)
2003 return;
2004
2005 if (NULL == ch)
2006 {
2007 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
2008 return;
2009 }
2010 LOG2 (level,
2011 "CHN %s:%X (%p)\n",
2012 GCT_2s (ch->t),
2013 ch->ctn,
2014 ch);
2015 if (NULL != ch->owner)
2016 {
2017 LOG2 (level,
2018 "CHN origin %s ready %s local-id: %u\n",
2019 GSC_2s (ch->owner->c),
2020 ch->owner->client_ready ? "YES" : "NO",
2021 ntohl (ch->owner->ccn.channel_of_client));
2022 }
2023 if (NULL != ch->dest)
2024 {
2025 LOG2 (level,
2026 "CHN destination %s ready %s local-id: %u\n",
2027 GSC_2s (ch->dest->c),
2028 ch->dest->client_ready ? "YES" : "NO",
2029 ntohl (ch->dest->ccn.channel_of_client));
2030 }
2031 LOG2 (level,
2032 "CHN Message IDs recv: %d (%LLX), send: %d\n",
2033 ntohl (ch->mid_recv.mid),
2034 (unsigned long long) ch->mid_futures,
2035 ntohl (ch->mid_send.mid));
2036}
2037
2038
2039
2040/* end of gnunet-service-cadet-new_channel.c */
diff --git a/src/cadet/gnunet-service-cadet-new_channel.h b/src/cadet/gnunet-service-cadet-new_channel.h
deleted file mode 100644
index 5167305a6..000000000
--- a/src/cadet/gnunet-service-cadet-new_channel.h
+++ /dev/null
@@ -1,262 +0,0 @@
1
2/*
3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @file cadet/gnunet-service-cadet-new_channel.h
24 * @brief GNUnet CADET service with encryption
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
27 */
28#ifndef GNUNET_SERVICE_CADET_CHANNEL_H
29#define GNUNET_SERVICE_CADET_CHANNEL_H
30
31#include "gnunet-service-cadet-new.h"
32#include "gnunet-service-cadet-new_peer.h"
33#include "cadet_protocol.h"
34
35
36/**
37 * A channel is a bidirectional connection between two CADET
38 * clients. Communiation can be reliable, unreliable, in-order
39 * or out-of-order. One client is the "local" client, this
40 * one initiated the connection. The other client is the
41 * "incoming" client, this one listened on a port to accept
42 * the connection from the "local" client.
43 */
44struct CadetChannel;
45
46
47/**
48 * Get the static string for identification of the channel.
49 *
50 * @param ch Channel.
51 *
52 * @return Static string with the channel IDs.
53 */
54const char *
55GCCH_2s (const struct CadetChannel *ch);
56
57
58/**
59 * Log channel info.
60 *
61 * @param ch Channel.
62 * @param level Debug level to use.
63 */
64void
65GCCH_debug (struct CadetChannel *ch,
66 enum GNUNET_ErrorType level);
67
68
69/**
70 * Get the channel's public ID.
71 *
72 * @param ch Channel.
73 *
74 * @return ID used to identify the channel with the remote peer.
75 */
76struct GNUNET_CADET_ChannelTunnelNumber
77GCCH_get_id (const struct CadetChannel *ch);
78
79
80/**
81 * Create a new channel.
82 *
83 * @param owner local client owning the channel
84 * @param owner_id local chid of this channel at the @a owner
85 * @param destination peer to which we should build the channel
86 * @param port desired port at @a destination
87 * @param options options for the channel
88 * @return handle to the new channel
89 */
90struct CadetChannel *
91GCCH_channel_local_new (struct CadetClient *owner,
92 struct GNUNET_CADET_ClientChannelNumber owner_id,
93 struct CadetPeer *destination,
94 const struct GNUNET_HashCode *port,
95 uint32_t options);
96
97
98/**
99 * A client is bound to the port that we have a channel
100 * open to. Send the acknowledgement for the connection
101 * request and establish the link with the client.
102 *
103 * @param ch open incoming channel
104 * @param c client listening on the respective port
105 */
106void
107GCCH_bind (struct CadetChannel *ch,
108 struct CadetClient *c);
109
110
111/**
112 * Destroy locally created channel. Called by the
113 * local client, so no need to tell the client.
114 *
115 * @param ch channel to destroy
116 * @param c client that caused the destruction
117 * @param ccn client number of the client @a c
118 */
119void
120GCCH_channel_local_destroy (struct CadetChannel *ch,
121 struct CadetClient *c,
122 struct GNUNET_CADET_ClientChannelNumber ccn);
123
124
125/**
126 * Function called once and only once after a channel was bound
127 * to its tunnel via #GCT_add_channel() is ready for transmission.
128 * Note that this is only the case for channels that this peer
129 * initiates, as for incoming channels we assume that they are
130 * ready for transmission immediately upon receiving the open
131 * message. Used to bootstrap the #GCT_send() process.
132 *
133 * @param ch the channel for which the tunnel is now ready
134 */
135void
136GCCH_tunnel_up (struct CadetChannel *ch);
137
138
139/**
140 * Create a new channel based on a request coming in over the network.
141 *
142 * @param t tunnel to the remote peer
143 * @param chid identifier of this channel in the tunnel
144 * @param origin peer to who initiated the channel
145 * @param port desired local port
146 * @param options options for the channel
147 * @return handle to the new channel
148 */
149struct CadetChannel *
150GCCH_channel_incoming_new (struct CadetTunnel *t,
151 struct GNUNET_CADET_ChannelTunnelNumber chid,
152 const struct GNUNET_HashCode *port,
153 uint32_t options);
154
155
156/**
157 * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for
158 * this channel. If the binding was successful, (re)transmit the
159 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.
160 *
161 * @param ch channel that got the duplicate open
162 * @param cti identifier of the connection that delivered the message
163 */
164void
165GCCH_handle_duplicate_open (struct CadetChannel *ch,
166 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti);
167
168
169
170/**
171 * We got payload data for a channel. Pass it on to the client.
172 *
173 * @param ch channel that got data
174 * @param cti identifier of the connection that delivered the message
175 * @param msg message that was received
176 */
177void
178GCCH_handle_channel_plaintext_data (struct CadetChannel *ch,
179 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
180 const struct GNUNET_CADET_ChannelAppDataMessage *msg);
181
182
183/**
184 * We got an acknowledgement for payload data for a channel.
185 * Possibly resume transmissions.
186 *
187 * @param ch channel that got the ack
188 * @param cti identifier of the connection that delivered the message
189 * @param ack details about what was received
190 */
191void
192GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch,
193 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
194 const struct GNUNET_CADET_ChannelDataAckMessage *ack);
195
196
197/**
198 * We got an acknowledgement for the creation of the channel
199 * (the port is open on the other side). Begin transmissions.
200 *
201 * @param ch channel to destroy
202 * @param cti identifier of the connection that delivered the message,
203 * NULL if the ACK was inferred because we got payload or are on loopback
204 */
205void
206GCCH_handle_channel_open_ack (struct CadetChannel *ch,
207 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti);
208
209
210/**
211 * Destroy channel, based on the other peer closing the
212 * connection. Also needs to remove this channel from
213 * the tunnel.
214 *
215 * FIXME: need to make it possible to defer destruction until we have
216 * received all messages up to the destroy, and right now the destroy
217 * message (and this API) fails to give is the information we need!
218 *
219 * FIXME: also need to know if the other peer got a destroy from
220 * us before!
221 *
222 * @param ch channel to destroy
223 * @param cti identifier of the connection that delivered the message,
224 * NULL during shutdown
225 */
226void
227GCCH_handle_remote_destroy (struct CadetChannel *ch,
228 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti);
229
230
231/**
232 * Handle data given by a client.
233 *
234 * Check whether the client is allowed to send in this tunnel, save if
235 * channel is reliable and send an ACK to the client if there is still
236 * buffer space in the tunnel.
237 *
238 * @param ch Channel.
239 * @param sender_ccn ccn of the sender
240 * @param buf payload to transmit.
241 * @param buf_len number of bytes in @a buf
242 * @return #GNUNET_OK if everything goes well,
243 * #GNUNET_SYSERR in case of an error.
244 */
245int
246GCCH_handle_local_data (struct CadetChannel *ch,
247 struct GNUNET_CADET_ClientChannelNumber sender_ccn,
248 const char *buf,
249 size_t buf_len);
250
251
252/**
253 * Handle ACK from client on local channel.
254 *
255 * @param ch channel to destroy
256 * @param client_ccn ccn of the client sending the ack
257 */
258void
259GCCH_handle_local_ack (struct CadetChannel *ch,
260 struct GNUNET_CADET_ClientChannelNumber client_ccn);
261
262#endif
diff --git a/src/cadet/gnunet-service-cadet-new_connection.c b/src/cadet/gnunet-service-cadet-new_connection.c
deleted file mode 100644
index 6976e66e4..000000000
--- a/src/cadet/gnunet-service-cadet-new_connection.c
+++ /dev/null
@@ -1,1093 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/gnunet-service-cadet-new_connection.c
23 * @brief management of CORE-level end-to-end connections; establishes
24 * end-to-end routes and transmits messages along the route
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
27 */
28#include "platform.h"
29#include "gnunet-service-cadet-new.h"
30#include "gnunet-service-cadet-new_channel.h"
31#include "gnunet-service-cadet-new_connection.h"
32#include "gnunet-service-cadet-new_paths.h"
33#include "gnunet-service-cadet-new_peer.h"
34#include "gnunet-service-cadet-new_tunnels.h"
35#include "gnunet_cadet_service.h"
36#include "gnunet_statistics_service.h"
37#include "cadet_protocol.h"
38
39
40#define LOG(level, ...) GNUNET_log_from(level,"cadet-con",__VA_ARGS__)
41
42
43/**
44 * All the states a connection can be in.
45 */
46enum CadetConnectionState
47{
48 /**
49 * Uninitialized status, we have not yet even gotten the message queue.
50 */
51 CADET_CONNECTION_NEW,
52
53 /**
54 * Connection create message in queue, awaiting transmission by CORE.
55 */
56 CADET_CONNECTION_SENDING_CREATE,
57
58 /**
59 * Connection create message sent, waiting for ACK.
60 */
61 CADET_CONNECTION_SENT,
62
63 /**
64 * We are an inbound connection, and received a CREATE. Need to
65 * send an CREATE_ACK back.
66 */
67 CADET_CONNECTION_CREATE_RECEIVED,
68
69 /**
70 * Connection confirmed, ready to carry traffic.
71 */
72 CADET_CONNECTION_READY
73
74};
75
76
77/**
78 * Low-level connection to a destination.
79 */
80struct CadetConnection
81{
82
83 /**
84 * ID of the connection.
85 */
86 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
87
88 /**
89 * To which peer does this connection go?
90 */
91 struct CadetPeer *destination;
92
93 /**
94 * Which tunnel is using this connection?
95 */
96 struct CadetTConnection *ct;
97
98 /**
99 * Path we are using to our destination.
100 */
101 struct CadetPeerPath *path;
102
103 /**
104 * Pending message, NULL if we are ready to transmit.
105 */
106 struct GNUNET_MQ_Envelope *env;
107
108 /**
109 * Handle for calling #GCP_request_mq_cancel() once we are finished.
110 */
111 struct GCP_MessageQueueManager *mq_man;
112
113 /**
114 * Task for connection maintenance.
115 */
116 struct GNUNET_SCHEDULER_Task *task;
117
118 /**
119 * Queue entry for keepalive messages.
120 */
121 struct CadetTunnelQueueEntry *keepalive_qe;
122
123 /**
124 * Function to call once we are ready to transmit.
125 */
126 GCC_ReadyCallback ready_cb;
127
128 /**
129 * Closure for @e ready_cb.
130 */
131 void *ready_cb_cls;
132
133 /**
134 * How long do we wait before we try again with a CREATE message?
135 */
136 struct GNUNET_TIME_Relative retry_delay;
137
138 /**
139 * Performance metrics for this connection.
140 */
141 struct CadetConnectionMetrics metrics;
142
143 /**
144 * State of the connection.
145 */
146 enum CadetConnectionState state;
147
148 /**
149 * Options for the route, control buffering.
150 */
151 enum GNUNET_CADET_ChannelOption options;
152
153 /**
154 * How many latency observations did we make for this connection?
155 */
156 unsigned int latency_datapoints;
157
158 /**
159 * Offset of our @e destination in @e path.
160 */
161 unsigned int off;
162
163 /**
164 * Are we ready to transmit via @e mq_man right now?
165 */
166 int mqm_ready;
167
168};
169
170
171/**
172 * Lookup a connection by its identifier.
173 *
174 * @param cid identifier to resolve
175 * @return NULL if connection was not found
176 */
177struct CadetConnection *
178GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
179{
180 return GNUNET_CONTAINER_multishortmap_get (connections,
181 &cid->connection_of_tunnel);
182}
183
184
185/**
186 * Update the connection state. Also triggers the necessary
187 * MQM notifications.
188 *
189 * @param cc connection to update the state for
190 * @param new_state new state for @a cc
191 * @param new_mqm_ready new `mqm_ready` state for @a cc
192 */
193static void
194update_state (struct CadetConnection *cc,
195 enum CadetConnectionState new_state,
196 int new_mqm_ready)
197{
198 int old_ready;
199 int new_ready;
200
201 if ( (new_state == cc->state) &&
202 (new_mqm_ready == cc->mqm_ready) )
203 return; /* no change, nothing to do */
204 old_ready = ( (CADET_CONNECTION_READY == cc->state) &&
205 (GNUNET_YES == cc->mqm_ready) );
206 new_ready = ( (CADET_CONNECTION_READY == new_state) &&
207 (GNUNET_YES == new_mqm_ready) );
208 cc->state = new_state;
209 cc->mqm_ready = new_mqm_ready;
210 if (old_ready != new_ready)
211 cc->ready_cb (cc->ready_cb_cls,
212 new_ready);
213}
214
215
216/**
217 * Destroy a connection, part of the internal implementation. Called
218 * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel().
219 *
220 * @param cc connection to destroy
221 */
222static void
223GCC_destroy (struct CadetConnection *cc)
224{
225 LOG (GNUNET_ERROR_TYPE_DEBUG,
226 "Destroying %s\n",
227 GCC_2s (cc));
228 if (NULL != cc->mq_man)
229 {
230 GCP_request_mq_cancel (cc->mq_man,
231 NULL);
232 cc->mq_man = NULL;
233 }
234 if (NULL != cc->task)
235 {
236 GNUNET_SCHEDULER_cancel (cc->task);
237 cc->task = NULL;
238 }
239 if (NULL != cc->keepalive_qe)
240 {
241 GCT_send_cancel (cc->keepalive_qe);
242 cc->keepalive_qe = NULL;
243 }
244 GCPP_del_connection (cc->path,
245 cc->off,
246 cc);
247 for (unsigned int i=0;i<cc->off;i++)
248 GCP_remove_connection (GCPP_get_peer_at_offset (cc->path,
249 i),
250 cc);
251 GNUNET_assert (GNUNET_YES ==
252 GNUNET_CONTAINER_multishortmap_remove (connections,
253 &GCC_get_id (cc)->connection_of_tunnel,
254 cc));
255 GNUNET_free (cc);
256}
257
258
259
260/**
261 * Destroy a connection, called when the CORE layer is already done
262 * (i.e. has received a BROKEN message), but if we still have to
263 * communicate the destruction of the connection to the tunnel (if one
264 * exists).
265 *
266 * @param cc connection to destroy
267 */
268void
269GCC_destroy_without_core (struct CadetConnection *cc)
270{
271 if (NULL != cc->ct)
272 {
273 GCT_connection_lost (cc->ct);
274 cc->ct = NULL;
275 }
276 GCC_destroy (cc);
277}
278
279
280/**
281 * Destroy a connection, called if the tunnel association with the
282 * connection was already broken, but we still need to notify the CORE
283 * layer about the breakage.
284 *
285 * @param cc connection to destroy
286 */
287void
288GCC_destroy_without_tunnel (struct CadetConnection *cc)
289{
290 cc->ct = NULL;
291 if ( (CADET_CONNECTION_SENDING_CREATE != cc->state) &&
292 (NULL != cc->mq_man) )
293 {
294 struct GNUNET_MQ_Envelope *env;
295 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
296
297 /* Need to notify next hop that we are down. */
298 env = GNUNET_MQ_msg (destroy_msg,
299 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
300 destroy_msg->cid = cc->cid;
301 GCP_request_mq_cancel (cc->mq_man,
302 env);
303 cc->mq_man = NULL;
304 }
305 GCC_destroy (cc);
306}
307
308
309/**
310 * Return the tunnel associated with this connection.
311 *
312 * @param cc connection to query
313 * @return corresponding entry in the tunnel's connection list
314 */
315struct CadetTConnection *
316GCC_get_ct (struct CadetConnection *cc)
317{
318 return cc->ct;
319}
320
321
322/**
323 * Obtain performance @a metrics from @a cc.
324 *
325 * @param cc connection to query
326 * @return the metrics
327 */
328const struct CadetConnectionMetrics *
329GCC_get_metrics (struct CadetConnection *cc)
330{
331 return &cc->metrics;
332}
333
334
335/**
336 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
337 * tunnel to prevent it from timing out.
338 *
339 * @param cls the `struct CadetConnection` to keep alive.
340 */
341static void
342send_keepalive (void *cls);
343
344
345/**
346 * Keepalive was transmitted. Remember this, and possibly
347 * schedule the next one.
348 *
349 * @param cls the `struct CadetConnection` to keep alive.
350 * @param cid identifier of the connection within the tunnel, NULL
351 * if transmission failed
352 */
353static void
354keepalive_done (void *cls,
355 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
356{
357 struct CadetConnection *cc = cls;
358
359 cc->keepalive_qe = NULL;
360 if ( (GNUNET_YES == cc->mqm_ready) &&
361 (NULL == cc->task) )
362 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
363 &send_keepalive,
364 cc);
365}
366
367
368/**
369 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
370 * tunnel to prevent it from timing out.
371 *
372 * @param cls the `struct CadetConnection` to keep alive.
373 */
374static void
375send_keepalive (void *cls)
376{
377 struct CadetConnection *cc = cls;
378 struct GNUNET_MessageHeader msg;
379
380 cc->task = NULL;
381 if (CADET_TUNNEL_KEY_OK != GCT_get_estate (cc->ct->t))
382 {
383 /* Tunnel not yet ready, wait with keepalives... */
384 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
385 &send_keepalive,
386 cc);
387 return;
388 }
389 GNUNET_assert (NULL != cc->ct);
390 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
391 GNUNET_assert (NULL == cc->keepalive_qe);
392 LOG (GNUNET_ERROR_TYPE_INFO,
393 "Sending KEEPALIVE on behalf of %s via %s\n",
394 GCC_2s (cc),
395 GCT_2s (cc->ct->t));
396 GNUNET_STATISTICS_update (stats,
397 "# keepalives sent",
398 1,
399 GNUNET_NO);
400 msg.size = htons (sizeof (msg));
401 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
402
403 cc->keepalive_qe
404 = GCT_send (cc->ct->t,
405 &msg,
406 &keepalive_done,
407 cc);
408}
409
410
411/**
412 * We sent a message for which we expect to receive an ACK via
413 * the connection identified by @a cti.
414 *
415 * @param cid connection identifier where we expect an ACK
416 */
417void
418GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
419{
420 struct CadetConnection *cc;
421
422 cc = GCC_lookup (cid);
423 if (NULL == cc)
424 return; /* whopise, connection alredy down? */
425 cc->metrics.num_acked_transmissions++;
426}
427
428
429/**
430 * We observed an ACK for a message that was originally sent via
431 * the connection identified by @a cti.
432 *
433 * @param cti connection identifier where we got an ACK for a message
434 * that was originally sent via this connection (the ACK
435 * may have gotten back to us via a different connection).
436 */
437void
438GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
439{
440 struct CadetConnection *cc;
441
442 cc = GCC_lookup (cid);
443 if (NULL == cc)
444 return; /* whopise, connection alredy down? */
445 cc->metrics.num_successes++;
446}
447
448
449/**
450 * We observed some the given @a latency on the connection
451 * identified by @a cti. (The same connection was taken
452 * in both directions.)
453 *
454 * @param cid connection identifier where we measured latency
455 * @param latency the observed latency
456 */
457void
458GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
459 struct GNUNET_TIME_Relative latency)
460{
461 struct CadetConnection *cc;
462 double weight;
463 double result;
464
465 cc = GCC_lookup (cid);
466 if (NULL == cc)
467 return; /* whopise, connection alredy down? */
468 GNUNET_STATISTICS_update (stats,
469 "# latencies observed",
470 1,
471 GNUNET_NO);
472 cc->latency_datapoints++;
473 if (cc->latency_datapoints >= 7)
474 weight = 7.0;
475 else
476 weight = cc->latency_datapoints;
477 /* Compute weighted average, giving at MOST weight 7 to the
478 existing values, or less if that value is based on fewer than 7
479 measurements. */
480 result = (weight * cc->metrics.aged_latency.rel_value_us) + 1.0 * latency.rel_value_us;
481 result /= (weight + 1.0);
482 cc->metrics.aged_latency.rel_value_us = (uint64_t) result;
483}
484
485
486/**
487 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for this connection, implying
488 * that the end-to-end connection is up. Process it.
489 *
490 * @param cc the connection that got the ACK.
491 */
492void
493GCC_handle_connection_create_ack (struct CadetConnection *cc)
494{
495 LOG (GNUNET_ERROR_TYPE_DEBUG,
496 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
497 GCC_2s (cc),
498 cc->state,
499 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
500 if (CADET_CONNECTION_READY == cc->state)
501 return; /* Duplicate ACK, ignore */
502 if (NULL != cc->task)
503 {
504 GNUNET_SCHEDULER_cancel (cc->task);
505 cc->task = NULL;
506 }
507 cc->metrics.age = GNUNET_TIME_absolute_get ();
508 update_state (cc,
509 CADET_CONNECTION_READY,
510 cc->mqm_ready);
511 if ( (NULL == cc->keepalive_qe) &&
512 (GNUNET_YES == cc->mqm_ready) &&
513 (NULL == cc->task) )
514 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
515 &send_keepalive,
516 cc);
517}
518
519
520/**
521 * Handle KX message.
522 *
523 * @param cc connection that received encrypted message
524 * @param msg the key exchange message
525 */
526void
527GCC_handle_kx (struct CadetConnection *cc,
528 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
529{
530 if (CADET_CONNECTION_SENT == cc->state)
531 {
532 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
533 clearly something is working, so pretend we got an ACK. */
534 LOG (GNUNET_ERROR_TYPE_DEBUG,
535 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
536 GCC_2s (cc));
537 GCC_handle_connection_create_ack (cc);
538 }
539 GCT_handle_kx (cc->ct,
540 msg);
541}
542
543
544/**
545 * Handle KX_AUTH message.
546 *
547 * @param cc connection that received encrypted message
548 * @param msg the key exchange message
549 */
550void
551GCC_handle_kx_auth (struct CadetConnection *cc,
552 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
553{
554 if (CADET_CONNECTION_SENT == cc->state)
555 {
556 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
557 clearly something is working, so pretend we got an ACK. */
558 LOG (GNUNET_ERROR_TYPE_DEBUG,
559 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
560 GCC_2s (cc));
561 GCC_handle_connection_create_ack (cc);
562 }
563 GCT_handle_kx_auth (cc->ct,
564 msg);
565}
566
567
568/**
569 * Handle encrypted message.
570 *
571 * @param cc connection that received encrypted message
572 * @param msg the encrypted message to decrypt
573 */
574void
575GCC_handle_encrypted (struct CadetConnection *cc,
576 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
577{
578 if (CADET_CONNECTION_SENT == cc->state)
579 {
580 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
581 clearly something is working, so pretend we got an ACK. */
582 LOG (GNUNET_ERROR_TYPE_DEBUG,
583 "Faking connection ACK for %s due to ENCRYPTED payload\n",
584 GCC_2s (cc));
585 GCC_handle_connection_create_ack (cc);
586 }
587 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
588 GCT_handle_encrypted (cc->ct,
589 msg);
590}
591
592
593/**
594 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
595 * first hop.
596 *
597 * @param cls the `struct CadetConnection` to initiate
598 */
599static void
600send_create (void *cls)
601{
602 struct CadetConnection *cc = cls;
603 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
604 struct GNUNET_PeerIdentity *pids;
605 struct GNUNET_MQ_Envelope *env;
606 unsigned int path_length;
607
608 cc->task = NULL;
609 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
610 path_length = GCPP_get_length (cc->path);
611 env = GNUNET_MQ_msg_extra (create_msg,
612 (1 + path_length) * sizeof (struct GNUNET_PeerIdentity),
613 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
614 create_msg->options = htonl ((uint32_t) cc->options);
615 create_msg->cid = cc->cid;
616 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
617 pids[0] = my_full_id;
618 for (unsigned int i=0;i<path_length;i++)
619 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
620 i));
621 LOG (GNUNET_ERROR_TYPE_DEBUG,
622 "Sending CADET_CONNECTION_CREATE message for %s\n",
623 GCC_2s (cc));
624 cc->env = env;
625 update_state (cc,
626 CADET_CONNECTION_SENT,
627 GNUNET_NO);
628 GCP_send (cc->mq_man,
629 env);
630}
631
632
633/**
634 * Send a CREATE_ACK message towards the origin.
635 *
636 * @param cls the `struct CadetConnection` to initiate
637 */
638static void
639send_create_ack (void *cls)
640{
641 struct CadetConnection *cc = cls;
642 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
643 struct GNUNET_MQ_Envelope *env;
644
645 cc->task = NULL;
646 GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state);
647 LOG (GNUNET_ERROR_TYPE_DEBUG,
648 "Sending CONNECTION_CREATE_ACK message for %s\n",
649 GCC_2s (cc));
650 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
651 env = GNUNET_MQ_msg (ack_msg,
652 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
653 ack_msg->cid = cc->cid;
654 cc->env = env;
655 update_state (cc,
656 CADET_CONNECTION_READY,
657 GNUNET_NO);
658 GCP_send (cc->mq_man,
659 env);
660}
661
662
663/**
664 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
665 * connection that we already have. Either our ACK got lost
666 * or something is fishy. Consider retransmitting the ACK.
667 *
668 * @param cc connection that got the duplicate CREATE
669 */
670void
671GCC_handle_duplicate_create (struct CadetConnection *cc)
672{
673 if (GNUNET_YES == cc->mqm_ready)
674 {
675 LOG (GNUNET_ERROR_TYPE_DEBUG,
676 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
677 GCC_2s (cc),
678 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
679 /* Revert back to the state of having only received the 'CREATE',
680 and immediately proceed to send the CREATE_ACK. */
681 update_state (cc,
682 CADET_CONNECTION_CREATE_RECEIVED,
683 cc->mqm_ready);
684 if (NULL != cc->task)
685 GNUNET_SCHEDULER_cancel (cc->task);
686 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
687 cc);
688 }
689 else
690 {
691 /* We are currently sending something else back, which
692 can only be an ACK or payload, either of which would
693 do. So actually no need to do anything. */
694 LOG (GNUNET_ERROR_TYPE_DEBUG,
695 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
696 GCC_2s (cc));
697 }
698}
699
700
701/**
702 * There has been a change in the message queue existence for our
703 * peer at the first hop. Adjust accordingly.
704 *
705 * @param cls the `struct CadetConnection`
706 * @param available #GNUNET_YES if sending is now possible,
707 * #GNUNET_NO if sending is no longer possible
708 * #GNUNET_SYSERR if sending is no longer possible
709 * and the last envelope was discarded
710 */
711static void
712manage_first_hop_mq (void *cls,
713 int available)
714{
715 struct CadetConnection *cc = cls;
716
717 if (GNUNET_YES != available)
718 {
719 /* Connection is down, for now... */
720 LOG (GNUNET_ERROR_TYPE_DEBUG,
721 "Core MQ for %s went down\n",
722 GCC_2s (cc));
723 update_state (cc,
724 CADET_CONNECTION_NEW,
725 GNUNET_NO);
726 cc->retry_delay = GNUNET_TIME_UNIT_ZERO;
727 if (NULL != cc->task)
728 {
729 GNUNET_SCHEDULER_cancel (cc->task);
730 cc->task = NULL;
731 }
732 return;
733 }
734
735 update_state (cc,
736 cc->state,
737 GNUNET_YES);
738 LOG (GNUNET_ERROR_TYPE_DEBUG,
739 "Core MQ for %s became available in state %d\n",
740 GCC_2s (cc),
741 cc->state);
742 switch (cc->state)
743 {
744 case CADET_CONNECTION_NEW:
745 /* Transmit immediately */
746 cc->task = GNUNET_SCHEDULER_add_now (&send_create,
747 cc);
748 break;
749 case CADET_CONNECTION_SENDING_CREATE:
750 /* Should not be possible to be called in this state. */
751 GNUNET_assert (0);
752 break;
753 case CADET_CONNECTION_SENT:
754 /* Retry a bit later... */
755 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
756 cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay,
757 &send_create,
758 cc);
759 break;
760 case CADET_CONNECTION_CREATE_RECEIVED:
761 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
762 cc->metrics.age = GNUNET_TIME_absolute_get ();
763 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
764 cc);
765 break;
766 case CADET_CONNECTION_READY:
767 if ( (NULL == cc->keepalive_qe) &&
768 (GNUNET_YES == cc->mqm_ready) &&
769 (NULL == cc->task) )
770 {
771 LOG (GNUNET_ERROR_TYPE_DEBUG,
772 "Scheduling keepalive for %s in %s\n",
773 GCC_2s (cc),
774 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
775 GNUNET_YES));
776 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
777 &send_keepalive,
778 cc);
779 }
780 break;
781 }
782}
783
784
785/**
786 * Create a connection to @a destination via @a path and notify @a cb
787 * whenever we are ready for more data. Shared logic independent of
788 * who is initiating the connection.
789 *
790 * @param destination where to go
791 * @param path which path to take (may not be the full path)
792 * @param off offset of @a destination on @a path
793 * @param options options for the connection
794 * @param ct which tunnel uses this connection
795 * @param init_state initial state for the connection
796 * @param ready_cb function to call when ready to transmit
797 * @param ready_cb_cls closure for @a cb
798 * @return handle to the connection
799 */
800static struct CadetConnection *
801connection_create (struct CadetPeer *destination,
802 struct CadetPeerPath *path,
803 unsigned int off,
804 enum GNUNET_CADET_ChannelOption options,
805 struct CadetTConnection *ct,
806 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
807 enum CadetConnectionState init_state,
808 GCC_ReadyCallback ready_cb,
809 void *ready_cb_cls)
810{
811 struct CadetConnection *cc;
812 struct CadetPeer *first_hop;
813
814 cc = GNUNET_new (struct CadetConnection);
815 cc->options = options;
816 cc->state = init_state;
817 cc->ct = ct;
818 cc->cid = *cid;
819 GNUNET_assert (GNUNET_OK ==
820 GNUNET_CONTAINER_multishortmap_put (connections,
821 &GCC_get_id (cc)->connection_of_tunnel,
822 cc,
823 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
824 cc->ready_cb = ready_cb;
825 cc->ready_cb_cls = ready_cb_cls;
826 cc->path = path;
827 cc->off = off;
828 LOG (GNUNET_ERROR_TYPE_DEBUG,
829 "Creating %s using path %s\n",
830 GCC_2s (cc),
831 GCPP_2s (path));
832 GCPP_add_connection (path,
833 off,
834 cc);
835 for (unsigned int i=0;i<off;i++)
836 GCP_add_connection (GCPP_get_peer_at_offset (path,
837 i),
838 cc);
839
840 first_hop = GCPP_get_peer_at_offset (path,
841 0);
842 cc->mq_man = GCP_request_mq (first_hop,
843 &manage_first_hop_mq,
844 cc);
845 return cc;
846}
847
848
849/**
850 * Create a connection to @a destination via @a path and
851 * notify @a cb whenever we are ready for more data. This
852 * is an inbound tunnel, so we must use the existing @a cid
853 *
854 * @param destination where to go
855 * @param path which path to take (may not be the full path)
856 * @param options options for the connection
857 * @param ct which tunnel uses this connection
858 * @param ready_cb function to call when ready to transmit
859 * @param ready_cb_cls closure for @a cb
860 * @return handle to the connection, NULL if we already have
861 * a connection that takes precedence on @a path
862 */
863struct CadetConnection *
864GCC_create_inbound (struct CadetPeer *destination,
865 struct CadetPeerPath *path,
866 enum GNUNET_CADET_ChannelOption options,
867 struct CadetTConnection *ct,
868 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
869 GCC_ReadyCallback ready_cb,
870 void *ready_cb_cls)
871{
872 struct CadetConnection *cc;
873 unsigned int off;
874
875 off = GCPP_find_peer (path,
876 destination);
877 GNUNET_assert (UINT_MAX != off);
878 cc = GCPP_get_connection (path,
879 destination,
880 off);
881 if (NULL != cc)
882 {
883 int cmp;
884
885 cmp = memcmp (cid,
886 &cc->cid,
887 sizeof (*cid));
888 if (0 == cmp)
889 {
890 /* Two peers picked the SAME random connection identifier at the
891 same time for the same path? Must be malicious. Drop
892 connection (existing and inbound), even if it is the only
893 one. */
894 GNUNET_break_op (0);
895 GCT_connection_lost (cc->ct);
896 GCC_destroy_without_tunnel (cc);
897 return NULL;
898 }
899 if (0 < cmp)
900 {
901 /* drop existing */
902 LOG (GNUNET_ERROR_TYPE_DEBUG,
903 "Got two connections on %s, dropping my existing %s\n",
904 GCPP_2s (path),
905 GCC_2s (cc));
906 GCT_connection_lost (cc->ct);
907 GCC_destroy_without_tunnel (cc);
908 }
909 else
910 {
911 /* keep existing */
912 LOG (GNUNET_ERROR_TYPE_DEBUG,
913 "Got two connections on %s, keeping my existing %s\n",
914 GCPP_2s (path),
915 GCC_2s (cc));
916 return NULL;
917 }
918 }
919
920 return connection_create (destination,
921 path,
922 off,
923 options,
924 ct,
925 cid,
926 CADET_CONNECTION_CREATE_RECEIVED,
927 ready_cb,
928 ready_cb_cls);
929}
930
931
932/**
933 * Create a connection to @a destination via @a path and
934 * notify @a cb whenever we are ready for more data.
935 *
936 * @param destination where to go
937 * @param path which path to take (may not be the full path)
938 * @param off offset of @a destination on @a path
939 * @param options options for the connection
940 * @param ct tunnel that uses the connection
941 * @param ready_cb function to call when ready to transmit
942 * @param ready_cb_cls closure for @a cb
943 * @return handle to the connection
944 */
945struct CadetConnection *
946GCC_create (struct CadetPeer *destination,
947 struct CadetPeerPath *path,
948 unsigned int off,
949 enum GNUNET_CADET_ChannelOption options,
950 struct CadetTConnection *ct,
951 GCC_ReadyCallback ready_cb,
952 void *ready_cb_cls)
953{
954 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
955
956 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
957 &cid,
958 sizeof (cid));
959 return connection_create (destination,
960 path,
961 off,
962 options,
963 ct,
964 &cid,
965 CADET_CONNECTION_NEW,
966 ready_cb,
967 ready_cb_cls);
968}
969
970
971/**
972 * Transmit message @a msg via connection @a cc. Must only be called
973 * (once) after the connection has signalled that it is ready via the
974 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
975 * connection is right now ready for transmission.
976 *
977 * @param cc connection identification
978 * @param env envelope with message to transmit; must NOT
979 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
980 */
981void
982GCC_transmit (struct CadetConnection *cc,
983 struct GNUNET_MQ_Envelope *env)
984{
985 LOG (GNUNET_ERROR_TYPE_DEBUG,
986 "Scheduling message for transmission on %s\n",
987 GCC_2s (cc));
988 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
989 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
990 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
991 cc->mqm_ready = GNUNET_NO;
992 if (NULL != cc->task)
993 {
994 GNUNET_SCHEDULER_cancel (cc->task);
995 cc->task = NULL;
996 }
997 GCP_send (cc->mq_man,
998 env);
999}
1000
1001
1002/**
1003 * Obtain the path used by this connection.
1004 *
1005 * @param cc connection
1006 * @return path to @a cc
1007 */
1008struct CadetPeerPath *
1009GCC_get_path (struct CadetConnection *cc)
1010{
1011 return cc->path;
1012}
1013
1014
1015/**
1016 * Obtain unique ID for the connection.
1017 *
1018 * @param cc connection.
1019 * @return unique number of the connection
1020 */
1021const struct GNUNET_CADET_ConnectionTunnelIdentifier *
1022GCC_get_id (struct CadetConnection *cc)
1023{
1024 return &cc->cid;
1025}
1026
1027
1028/**
1029 * Get a (static) string for a connection.
1030 *
1031 * @param cc Connection.
1032 */
1033const char *
1034GCC_2s (const struct CadetConnection *cc)
1035{
1036 static char buf[128];
1037
1038 if (NULL == cc)
1039 return "Connection(NULL)";
1040
1041 if (NULL != cc->ct)
1042 {
1043 GNUNET_snprintf (buf,
1044 sizeof (buf),
1045 "Connection %s (%s)",
1046 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
1047 GCT_2s (cc->ct->t));
1048 return buf;
1049 }
1050 GNUNET_snprintf (buf,
1051 sizeof (buf),
1052 "Connection %s",
1053 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
1054 return buf;
1055}
1056
1057
1058#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
1059
1060
1061/**
1062 * Log connection info.
1063 *
1064 * @param cc connection
1065 * @param level Debug level to use.
1066 */
1067void
1068GCC_debug (struct CadetConnection *cc,
1069 enum GNUNET_ErrorType level)
1070{
1071 int do_log;
1072
1073 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1074 "cadet-con",
1075 __FILE__, __FUNCTION__, __LINE__);
1076 if (0 == do_log)
1077 return;
1078 if (NULL == cc)
1079 {
1080 LOG2 (level,
1081 "Connection (NULL)\n");
1082 return;
1083 }
1084 LOG2 (level,
1085 "%s to %s via path %s in state %d is %s\n",
1086 GCC_2s (cc),
1087 GCP_2s (cc->destination),
1088 GCPP_2s (cc->path),
1089 cc->state,
1090 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
1091}
1092
1093/* end of gnunet-service-cadet-new_connection.c */
diff --git a/src/cadet/gnunet-service-cadet-new_connection.h b/src/cadet/gnunet-service-cadet-new_connection.h
deleted file mode 100644
index e48b208fd..000000000
--- a/src/cadet/gnunet-service-cadet-new_connection.h
+++ /dev/null
@@ -1,339 +0,0 @@
1
2/*
3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @file cadet/gnunet-service-cadet-new_connection.h
24 * @brief A connection is a live end-to-end messaging mechanism
25 * where the peers are identified by a path and know how
26 * to forward along the route using a connection identifier
27 * for routing the data.
28 * @author Bartlomiej Polot
29 * @author Christian Grothoff
30 */
31#ifndef GNUNET_SERVICE_CADET_CONNECTION_H
32#define GNUNET_SERVICE_CADET_CONNECTION_H
33
34#include "gnunet_util_lib.h"
35#include "gnunet-service-cadet-new.h"
36#include "gnunet-service-cadet-new_peer.h"
37#include "cadet_protocol.h"
38
39
40/**
41 * Function called to notify tunnel about change in our readyness.
42 *
43 * @param cls closure
44 * @param is_ready #GNUNET_YES if the connection is now ready for transmission,
45 * #GNUNET_NO if the connection is no longer ready for transmission
46 */
47typedef void
48(*GCC_ReadyCallback)(void *cls,
49 int is_ready);
50
51
52/**
53 * Destroy a connection, called when the CORE layer is already done
54 * (i.e. has received a BROKEN message), but if we still have to
55 * communicate the destruction of the connection to the tunnel (if one
56 * exists).
57 *
58 * @param cc connection to destroy
59 */
60void
61GCC_destroy_without_core (struct CadetConnection *cc);
62
63
64/**
65 * Destroy a connection, called if the tunnel association with the
66 * connection was already broken, but we still need to notify the CORE
67 * layer about the breakage.
68 *
69 * @param cc connection to destroy
70 */
71void
72GCC_destroy_without_tunnel (struct CadetConnection *cc);
73
74
75/**
76 * Lookup a connection by its identifier.
77 *
78 * @param cid identifier to resolve
79 * @return NULL if connection was not found
80 */
81struct CadetConnection *
82GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
83
84
85/**
86 * Create a connection to @a destination via @a path and
87 * notify @a cb whenever we are ready for more data.
88 *
89 * @param destination where to go
90 * @param path which path to take (may not be the full path)
91 * @param off offset of @a destination on @a path
92 * @param options options for the connection
93 * @param ct which tunnel uses this connection
94 * @param ready_cb function to call when ready to transmit
95 * @param ready_cb_cls closure for @a cb
96 * @return handle to the connection
97 */
98struct CadetConnection *
99GCC_create (struct CadetPeer *destination,
100 struct CadetPeerPath *path,
101 unsigned int off,
102 enum GNUNET_CADET_ChannelOption options,
103 struct CadetTConnection *ct,
104 GCC_ReadyCallback ready_cb,
105 void *ready_cb_cls);
106
107
108/**
109 * Create a connection to @a destination via @a path and
110 * notify @a cb whenever we are ready for more data. This
111 * is an inbound tunnel, so we must use the existing @a cid
112 *
113 * @param destination where to go
114 * @param path which path to take (may not be the full path)
115 * @param options options for the connection
116 * @param ct which tunnel uses this connection
117 * @param ready_cb function to call when ready to transmit
118 * @param ready_cb_cls closure for @a cb
119 * @return handle to the connection, NULL if we already have
120 * a connection that takes precedence on @a path
121 */
122struct CadetConnection *
123GCC_create_inbound (struct CadetPeer *destination,
124 struct CadetPeerPath *path,
125 enum GNUNET_CADET_ChannelOption options,
126 struct CadetTConnection *ct,
127 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
128 GCC_ReadyCallback ready_cb,
129 void *ready_cb_cls);
130
131
132/**
133 * Transmit message @a msg via connection @a cc. Must only be called
134 * (once) after the connection has signalled that it is ready via the
135 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
136 * connection is right now ready for transmission.
137 *
138 * @param cc connection identification
139 * @param env envelope with message to transmit;
140 * the #GNUNET_MQ_notify_send() must not have yet been used
141 * for the envelope. Also, the message better match the
142 * connection identifier of this connection...
143 */
144void
145GCC_transmit (struct CadetConnection *cc,
146 struct GNUNET_MQ_Envelope *env);
147
148
149/**
150 * A CREATE_ACK was received for this connection, process it.
151 *
152 * @param cc the connection that got the ACK.
153 */
154void
155GCC_handle_connection_create_ack (struct CadetConnection *cc);
156
157
158/**
159 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
160 * connection that we already have. Either our ACK got lost
161 * or something is fishy. Consider retransmitting the ACK.
162 *
163 * @param cc connection that got the duplicate CREATE
164 */
165void
166GCC_handle_duplicate_create (struct CadetConnection *cc);
167
168
169/**
170 * Handle KX message.
171 *
172 * @param cc connection that received encrypted message
173 * @param msg the key exchange message
174 */
175void
176GCC_handle_kx (struct CadetConnection *cc,
177 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
178
179
180/**
181 * Handle KX_AUTH message.
182 *
183 * @param cc connection that received encrypted message
184 * @param msg the key exchange message
185 */
186void
187GCC_handle_kx_auth (struct CadetConnection *cc,
188 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg);
189
190
191/**
192 * Performance metrics for a connection.
193 */
194struct CadetConnectionMetrics
195{
196
197 /**
198 * Our current best estimate of the latency, based on a weighted
199 * average of at least @a latency_datapoints values.
200 */
201 struct GNUNET_TIME_Relative aged_latency;
202
203 /**
204 * When was this connection first established? (by us sending or
205 * receiving the CREATE_ACK for the first time)
206 */
207 struct GNUNET_TIME_Absolute age;
208
209 /**
210 * When was this connection last used? (by us sending or
211 * receiving a PAYLOAD message on it)
212 */
213 struct GNUNET_TIME_Absolute last_use;
214
215 /**
216 * How many packets that ought to generate an ACK did we send via
217 * this connection?
218 */
219 unsigned long long num_acked_transmissions;
220
221 /**
222 * Number of packets that were sent via this connection did actually
223 * receive an ACK? (Note: ACKs may be transmitted and lost via
224 * other connections, so this value should only be interpreted
225 * relative to @e num_acked_transmissions and in relation to other
226 * connections.)
227 */
228 unsigned long long num_successes;
229
230};
231
232
233/**
234 * Obtain performance @a metrics from @a cc.
235 *
236 * @param cc connection to query
237 * @return the metrics
238 */
239const struct CadetConnectionMetrics *
240GCC_get_metrics (struct CadetConnection *cc);
241
242
243/**
244 * Handle encrypted message.
245 *
246 * @param cc connection that received encrypted message
247 * @param msg the encrypted message to decrypt
248 */
249void
250GCC_handle_encrypted (struct CadetConnection *cc,
251 const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
252
253
254/**
255 * We sent a message for which we expect to receive an ACK via
256 * the connection identified by @a cti.
257 *
258 * @param cid connection identifier where we expect an ACK
259 */
260void
261GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
262
263
264/**
265 * We observed an ACK for a message that was originally sent via
266 * the connection identified by @a cti.
267 *
268 * @param cid connection identifier where we got an ACK for a message
269 * that was originally sent via this connection (the ACK
270 * may have gotten back to us via a different connection).
271 */
272void
273GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
274
275
276/**
277 * We observed some the given @a latency on the connection
278 * identified by @a cti. (The same connection was taken
279 * in both directions.)
280 *
281 * @param cti connection identifier where we measured latency
282 * @param latency the observed latency
283 */
284void
285GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
286 struct GNUNET_TIME_Relative latency);
287
288
289/**
290 * Return the tunnel associated with this connection.
291 *
292 * @param cc connection to query
293 * @return corresponding entry in the tunnel's connection list
294 */
295struct CadetTConnection *
296GCC_get_ct (struct CadetConnection *cc);
297
298
299/**
300 * Obtain the path used by this connection.
301 *
302 * @param cc connection
303 * @return path to @a cc
304 */
305struct CadetPeerPath *
306GCC_get_path (struct CadetConnection *cc);
307
308
309/**
310 * Obtain unique ID for the connection.
311 *
312 * @param cc connection.
313 * @return unique number of the connection
314 */
315const struct GNUNET_CADET_ConnectionTunnelIdentifier *
316GCC_get_id (struct CadetConnection *cc);
317
318
319/**
320 * Get a (static) string for a connection.
321 *
322 * @param cc Connection.
323 */
324const char *
325GCC_2s (const struct CadetConnection *cc);
326
327
328/**
329 * Log connection info.
330 *
331 * @param cc connection
332 * @param level Debug level to use.
333 */
334void
335GCC_debug (struct CadetConnection *cc,
336 enum GNUNET_ErrorType level);
337
338
339#endif
diff --git a/src/cadet/gnunet-service-cadet-new_dht.c b/src/cadet/gnunet-service-cadet-new_dht.c
deleted file mode 100644
index 849562f23..000000000
--- a/src/cadet/gnunet-service-cadet-new_dht.c
+++ /dev/null
@@ -1,351 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file cadet/gnunet-service-cadet-new_dht.c
22 * @brief Information we track per peer.
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_dht_service.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet-service-cadet-new.h"
32#include "gnunet-service-cadet-new_dht.h"
33#include "gnunet-service-cadet-new_hello.h"
34#include "gnunet-service-cadet-new_peer.h"
35#include "gnunet-service-cadet-new_paths.h"
36
37/**
38 * How long do we wait before first announcing our presence to the DHT.
39 * Used to wait for our HELLO to be available. Note that we also get
40 * notifications when our HELLO is ready, so this is just the maximum
41 * we wait for the first notification.
42 */
43#define STARTUP_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500)
44
45/**
46 * How long do we wait after we get an updated HELLO before publishing?
47 * Allows for the HELLO to be updated again quickly, for example in
48 * case multiple addresses changed and we got a partial update.
49 */
50#define CHANGE_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100)
51
52
53#define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__)
54
55
56/**
57 * Handle for DHT searches.
58 */
59struct GCD_search_handle
60{
61 /**
62 * DHT_GET handle.
63 */
64 struct GNUNET_DHT_GetHandle *dhtget;
65
66};
67
68
69/**
70 * Handle to use DHT.
71 */
72static struct GNUNET_DHT_Handle *dht_handle;
73
74/**
75 * How often to PUT own ID in the DHT.
76 */
77static struct GNUNET_TIME_Relative id_announce_time;
78
79/**
80 * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put().
81 */
82static unsigned long long dht_replication_level;
83
84/**
85 * Task to periodically announce itself in the network.
86 */
87static struct GNUNET_SCHEDULER_Task *announce_id_task;
88
89/**
90 * Delay for the next ID announce.
91 */
92static struct GNUNET_TIME_Relative announce_delay;
93
94
95/**
96 * Function to process paths received for a new peer addition. The recorded
97 * paths form the initial tunnel, which can be optimized later.
98 * Called on each result obtained for the DHT search.
99 *
100 * @param cls closure
101 * @param exp when will this value expire
102 * @param key key of the result
103 * @param get_path path of the get request
104 * @param get_path_length lenght of @a get_path
105 * @param put_path path of the put request
106 * @param put_path_length length of the @a put_path
107 * @param type type of the result
108 * @param size number of bytes in data
109 * @param data pointer to the result data
110 */
111static void
112dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
113 const struct GNUNET_HashCode *key,
114 const struct GNUNET_PeerIdentity *get_path,
115 unsigned int get_path_length,
116 const struct GNUNET_PeerIdentity *put_path,
117 unsigned int put_path_length,
118 enum GNUNET_BLOCK_Type type,
119 size_t size,
120 const void *data)
121{
122 const struct GNUNET_HELLO_Message *hello = data;
123 struct CadetPeer *peer;
124
125 GCPP_try_path_from_dht (get_path,
126 get_path_length,
127 put_path,
128 put_path_length);
129 if ( (size >= sizeof (struct GNUNET_HELLO_Message)) &&
130 (ntohs (hello->header.size) == size) &&
131 (size == GNUNET_HELLO_size (hello)) )
132 {
133 peer = GCP_get (&put_path[0],
134 GNUNET_YES);
135 LOG (GNUNET_ERROR_TYPE_DEBUG,
136 "Got HELLO for %s\n",
137 GCP_2s (peer));
138 GCP_set_hello (peer,
139 hello);
140 }
141}
142
143
144/**
145 * Periodically announce self id in the DHT
146 *
147 * @param cls closure
148 */
149static void
150announce_id (void *cls)
151{
152 struct GNUNET_HashCode phash;
153 const struct GNUNET_HELLO_Message *hello;
154 size_t size;
155 struct GNUNET_TIME_Absolute expiration;
156 struct GNUNET_TIME_Relative next_put;
157
158 hello = GCH_get_mine ();
159 size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0;
160 if (0 == size)
161 {
162 expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
163 announce_delay);
164 announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
165 }
166 else
167 {
168 expiration = GNUNET_HELLO_get_last_expiration (hello);
169 announce_delay = GNUNET_TIME_UNIT_SECONDS;
170 }
171
172 /* Call again in id_announce_time, unless HELLO expires first,
173 * but wait at least 1s. */
174 next_put
175 = GNUNET_TIME_absolute_get_remaining (expiration);
176 next_put
177 = GNUNET_TIME_relative_min (next_put,
178 id_announce_time);
179 next_put
180 = GNUNET_TIME_relative_max (next_put,
181 GNUNET_TIME_UNIT_SECONDS);
182 announce_id_task
183 = GNUNET_SCHEDULER_add_delayed (next_put,
184 &announce_id,
185 cls);
186 GNUNET_STATISTICS_update (stats,
187 "# DHT announce",
188 1,
189 GNUNET_NO);
190 memset (&phash,
191 0,
192 sizeof (phash));
193 GNUNET_memcpy (&phash,
194 &my_full_id,
195 sizeof (my_full_id));
196 LOG (GNUNET_ERROR_TYPE_DEBUG,
197 "Announcing my HELLO (%u bytes) in the DHT\n",
198 size);
199 GNUNET_DHT_put (dht_handle, /* DHT handle */
200 &phash, /* Key to use */
201 dht_replication_level, /* Replication level */
202 GNUNET_DHT_RO_RECORD_ROUTE
203 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
204 GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */
205 size, /* Size of the data */
206 (const char *) hello, /* Data itself */
207 expiration, /* Data expiration */
208 NULL, /* Continuation */
209 NULL); /* Continuation closure */
210}
211
212
213/**
214 * Function called by the HELLO subsystem whenever OUR hello
215 * changes. Re-triggers the DHT PUT immediately.
216 */
217void
218GCD_hello_update ()
219{
220 if (NULL == announce_id_task)
221 return; /* too early */
222 GNUNET_SCHEDULER_cancel (announce_id_task);
223 announce_id_task
224 = GNUNET_SCHEDULER_add_delayed (CHANGE_DELAY,
225 &announce_id,
226 NULL);
227}
228
229
230/**
231 * Initialize the DHT subsystem.
232 *
233 * @param c Configuration.
234 */
235void
236GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
237{
238 if (GNUNET_OK !=
239 GNUNET_CONFIGURATION_get_value_number (c,
240 "CADET",
241 "DHT_REPLICATION_LEVEL",
242 &dht_replication_level))
243 {
244 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
245 "CADET",
246 "DHT_REPLICATION_LEVEL",
247 "USING DEFAULT");
248 dht_replication_level = 3;
249 }
250
251 if (GNUNET_OK !=
252 GNUNET_CONFIGURATION_get_value_time (c,
253 "CADET",
254 "ID_ANNOUNCE_TIME",
255 &id_announce_time))
256 {
257 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
258 "CADET",
259 "ID_ANNOUNCE_TIME",
260 "MISSING");
261 GNUNET_SCHEDULER_shutdown ();
262 return;
263 }
264
265 dht_handle = GNUNET_DHT_connect (c,
266 64);
267 GNUNET_break (NULL != dht_handle);
268 announce_delay = GNUNET_TIME_UNIT_SECONDS;
269 announce_id_task = GNUNET_SCHEDULER_add_delayed (STARTUP_DELAY,
270 &announce_id,
271 NULL);
272}
273
274
275/**
276 * Shut down the DHT subsystem.
277 */
278void
279GCD_shutdown (void)
280{
281 if (NULL != dht_handle)
282 {
283 GNUNET_DHT_disconnect (dht_handle);
284 dht_handle = NULL;
285 }
286 if (NULL != announce_id_task)
287 {
288 GNUNET_SCHEDULER_cancel (announce_id_task);
289 announce_id_task = NULL;
290 }
291}
292
293
294/**
295 * Search DHT for paths to @a peeR_id
296 *
297 * @param peer_id peer to search for
298 * @return handle to abort search
299 */
300struct GCD_search_handle *
301GCD_search (const struct GNUNET_PeerIdentity *peer_id)
302{
303 struct GNUNET_HashCode phash;
304 struct GCD_search_handle *h;
305
306 GNUNET_STATISTICS_update (stats,
307 "# DHT search",
308 1,
309 GNUNET_NO);
310 memset (&phash,
311 0,
312 sizeof (phash));
313 GNUNET_memcpy (&phash,
314 peer_id,
315 sizeof (*peer_id));
316
317 h = GNUNET_new (struct GCD_search_handle);
318 h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */
319 GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */
320 &phash, /* key to search */
321 dht_replication_level, /* replication level */
322 GNUNET_DHT_RO_RECORD_ROUTE |
323 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
324 NULL, /* xquery */
325 0, /* xquery bits */
326 &dht_get_id_handler,
327 h);
328 LOG (GNUNET_ERROR_TYPE_DEBUG,
329 "Starting DHT GET for peer %s (%p)\n",
330 GNUNET_i2s (peer_id),
331 h);
332 return h;
333}
334
335
336/**
337 * Stop DHT search started with #GCD_search().
338 *
339 * @param h handle to search to stop
340 */
341void
342GCD_search_stop (struct GCD_search_handle *h)
343{
344 LOG (GNUNET_ERROR_TYPE_DEBUG,
345 "Stopping DHT GET %p\n",
346 h);
347 GNUNET_DHT_get_stop (h->dhtget);
348 GNUNET_free (h);
349}
350
351/* end of gnunet-service-cadet_dht.c */
diff --git a/src/cadet/gnunet-service-cadet-new_dht.h b/src/cadet/gnunet-service-cadet-new_dht.h
deleted file mode 100644
index 5d7ab29a0..000000000
--- a/src/cadet/gnunet-service-cadet-new_dht.h
+++ /dev/null
@@ -1,100 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/gnunet-service-cadet_dht.h
23 * @brief cadet service; dealing with DHT requests and results
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * All functions in this file should use the prefix GCD (Gnunet Cadet Dht)
28 */
29#ifndef GNUNET_SERVICE_CADET_DHT_H
30#define GNUNET_SERVICE_CADET_DHT_H
31
32#ifdef __cplusplus
33extern "C"
34{
35#if 0 /* keep Emacsens' auto-indent happy */
36}
37#endif
38#endif
39
40#include "platform.h"
41#include "gnunet_util_lib.h"
42
43/**
44 * Handle for DHT search operation.
45 */
46struct GCD_search_handle;
47
48
49/**
50 * Initialize the DHT subsystem.
51 *
52 * @param c Configuration.
53 */
54void
55GCD_init (const struct GNUNET_CONFIGURATION_Handle *c);
56
57
58/**
59 * Shut down the DHT subsystem.
60 */
61void
62GCD_shutdown (void);
63
64
65/**
66 * Function called by the HELLO subsystem whenever OUR hello
67 * changes. Re-triggers the DHT PUT immediately.
68 */
69void
70GCD_hello_update (void);
71
72/**
73 * Search DHT for paths to @a peeR_id
74 *
75 * @param peer_id peer to search for
76 * @return handle to abort search
77 */
78struct GCD_search_handle *
79GCD_search (const struct GNUNET_PeerIdentity *peer_id);
80
81
82/**
83 * Stop DHT search started with #GCD_search().
84 *
85 * @param h handle to search to stop
86 */
87void
88GCD_search_stop (struct GCD_search_handle *h);
89
90
91#if 0 /* keep Emacsens' auto-indent happy */
92{
93#endif
94#ifdef __cplusplus
95}
96#endif
97
98/* ifndef GNUNET_CADET_SERVICE_DHT_H */
99#endif
100/* end of gnunet-service-cadet_dht.h */
diff --git a/src/cadet/gnunet-service-cadet-new_hello.c b/src/cadet/gnunet-service-cadet-new_hello.c
deleted file mode 100644
index a24325ada..000000000
--- a/src/cadet/gnunet-service-cadet-new_hello.c
+++ /dev/null
@@ -1,152 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2014, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file cadet/gnunet-service-cadet-new_hello.c
22 * @brief spread knowledge about how to contact other peers from PEERINFO
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - is most of this necessary/helpful?
28 * - should we not simply restrict this to OUR hello?
29 */
30#include "platform.h"
31#include "gnunet_util_lib.h"
32
33#include "gnunet_statistics_service.h"
34#include "gnunet_peerinfo_service.h"
35#include "cadet_protocol.h"
36#include "gnunet-service-cadet-new.h"
37#include "gnunet-service-cadet-new_dht.h"
38#include "gnunet-service-cadet-new_hello.h"
39#include "gnunet-service-cadet-new_peer.h"
40
41#define LOG(level, ...) GNUNET_log_from(level,"cadet-hll",__VA_ARGS__)
42
43/**
44 * Hello message of local peer.
45 */
46static struct GNUNET_HELLO_Message *mine;
47
48/**
49 * Handle to peerinfo service.
50 */
51static struct GNUNET_PEERINFO_Handle *peerinfo;
52
53/**
54 * Iterator context.
55 */
56static struct GNUNET_PEERINFO_NotifyContext *nc;
57
58
59/**
60 * Process each hello message received from peerinfo.
61 *
62 * @param cls Closure (unused).
63 * @param peer Identity of the peer.
64 * @param hello Hello of the peer.
65 * @param err_msg Error message.
66 */
67static void
68got_hello (void *cls,
69 const struct GNUNET_PeerIdentity *id,
70 const struct GNUNET_HELLO_Message *hello,
71 const char *err_msg)
72{
73 struct CadetPeer *peer;
74
75 if ( (NULL == id) ||
76 (NULL == hello) )
77 return;
78 if (0 == memcmp (id,
79 &my_full_id,
80 sizeof (struct GNUNET_PeerIdentity)))
81 {
82 GNUNET_free_non_null (mine);
83 mine = (struct GNUNET_HELLO_Message *) GNUNET_copy_message (&hello->header);
84 GCD_hello_update ();
85 return;
86 }
87
88 LOG (GNUNET_ERROR_TYPE_DEBUG,
89 "Hello for %s (%d bytes), expires on %s\n",
90 GNUNET_i2s (id),
91 GNUNET_HELLO_size (hello),
92 GNUNET_STRINGS_absolute_time_to_string (GNUNET_HELLO_get_last_expiration (hello)));
93 peer = GCP_get (id,
94 GNUNET_YES);
95 GCP_set_hello (peer,
96 hello);
97}
98
99
100/**
101 * Initialize the hello subsystem.
102 *
103 * @param c Configuration.
104 */
105void
106GCH_init (const struct GNUNET_CONFIGURATION_Handle *c)
107{
108 GNUNET_assert (NULL == nc);
109 peerinfo = GNUNET_PEERINFO_connect (c);
110 nc = GNUNET_PEERINFO_notify (c,
111 GNUNET_NO,
112 &got_hello,
113 NULL);
114}
115
116
117/**
118 * Shut down the hello subsystem.
119 */
120void
121GCH_shutdown ()
122{
123 if (NULL != nc)
124 {
125 GNUNET_PEERINFO_notify_cancel (nc);
126 nc = NULL;
127 }
128 if (NULL != peerinfo)
129 {
130 GNUNET_PEERINFO_disconnect (peerinfo);
131 peerinfo = NULL;
132 }
133 if (NULL != mine)
134 {
135 GNUNET_free (mine);
136 mine = NULL;
137 }
138}
139
140
141/**
142 * Get own hello message.
143 *
144 * @return Own hello message.
145 */
146const struct GNUNET_HELLO_Message *
147GCH_get_mine (void)
148{
149 return mine;
150}
151
152/* end of gnunet-service-cadet-new_hello.c */
diff --git a/src/cadet/gnunet-service-cadet-new_hello.h b/src/cadet/gnunet-service-cadet-new_hello.h
deleted file mode 100644
index 4291ae985..000000000
--- a/src/cadet/gnunet-service-cadet-new_hello.h
+++ /dev/null
@@ -1,80 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2014, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/gnunet-service-cadet_hello.h
23 * @brief cadet service; dealing with hello messages
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * All functions in this file should use the prefix GCH (Gnunet Cadet Hello)
28 */
29
30#ifndef GNUNET_SERVICE_CADET_HELLO_H
31#define GNUNET_SERVICE_CADET_HELLO_H
32
33#ifdef __cplusplus
34extern "C"
35{
36#if 0 /* keep Emacsens' auto-indent happy */
37}
38#endif
39#endif
40
41#include "platform.h"
42#include "gnunet_util_lib.h"
43#include "gnunet_hello_lib.h"
44
45
46/**
47 * Initialize the hello subsystem.
48 *
49 * @param c Configuration.
50 */
51void
52GCH_init (const struct GNUNET_CONFIGURATION_Handle *c);
53
54
55/**
56 * Shut down the hello subsystem.
57 */
58void
59GCH_shutdown (void);
60
61
62/**
63 * Get own hello message.
64 *
65 * @return Own hello message.
66 */
67const struct GNUNET_HELLO_Message *
68GCH_get_mine (void);
69
70
71#if 0 /* keep Emacsens' auto-indent happy */
72{
73#endif
74#ifdef __cplusplus
75}
76#endif
77
78/* ifndef GNUNET_CADET_SERVICE_HELLO_H */
79#endif
80/* end of gnunet-cadet-service_hello.h */
diff --git a/src/cadet/gnunet-service-cadet-new_peer.c b/src/cadet/gnunet-service-cadet-new_peer.c
deleted file mode 100644
index 29aef6895..000000000
--- a/src/cadet/gnunet-service-cadet-new_peer.c
+++ /dev/null
@@ -1,1478 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/gnunet-service-cadet-new_peer.c
23 * @brief Information we track per peer.
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * TODO:
28 * - optimize stopping/restarting DHT search to situations
29 * where we actually need it (i.e. not if we have a direct connection,
30 * or if we already have plenty of good short ones, or maybe even
31 * to take a break if we have some connections and have searched a lot (?))
32 */
33#include "platform.h"
34#include "gnunet_util_lib.h"
35#include "gnunet_hello_lib.h"
36#include "gnunet_signatures.h"
37#include "gnunet_transport_service.h"
38#include "gnunet_ats_service.h"
39#include "gnunet_core_service.h"
40#include "gnunet_statistics_service.h"
41#include "cadet_protocol.h"
42#include "gnunet-service-cadet-new.h"
43#include "gnunet-service-cadet-new_connection.h"
44#include "gnunet-service-cadet-new_dht.h"
45#include "gnunet-service-cadet-new_peer.h"
46#include "gnunet-service-cadet-new_paths.h"
47#include "gnunet-service-cadet-new_tunnels.h"
48
49
50#define LOG(level, ...) GNUNET_log_from(level,"cadet-per",__VA_ARGS__)
51
52
53/**
54 * How long do we wait until tearing down an idle peer?
55 */
56#define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
57
58/**
59 * How long do we keep paths around if we no longer care about the peer?
60 */
61#define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
62
63
64
65
66/**
67 * Data structure used to track whom we have to notify about changes
68 * to our message queue.
69 */
70struct GCP_MessageQueueManager
71{
72
73 /**
74 * Kept in a DLL.
75 */
76 struct GCP_MessageQueueManager *next;
77
78 /**
79 * Kept in a DLL.
80 */
81 struct GCP_MessageQueueManager *prev;
82
83 /**
84 * Function to call with updated message queue object.
85 */
86 GCP_MessageQueueNotificationCallback cb;
87
88 /**
89 * Closure for @e cb.
90 */
91 void *cb_cls;
92
93 /**
94 * The peer this is for.
95 */
96 struct CadetPeer *cp;
97
98 /**
99 * Envelope this manager would like to transmit once it is its turn.
100 */
101 struct GNUNET_MQ_Envelope *env;
102
103};
104
105
106/**
107 * Struct containing all information regarding a given peer
108 */
109struct CadetPeer
110{
111 /**
112 * ID of the peer
113 */
114 struct GNUNET_PeerIdentity pid;
115
116 /**
117 * Last time we heard from this peer (currently not used!)
118 */
119 struct GNUNET_TIME_Absolute last_contactXXX;
120
121 /**
122 * Array of DLLs of paths traversing the peer, organized by the
123 * offset of the peer on the larger path.
124 */
125 struct CadetPeerPathEntry **path_heads;
126
127 /**
128 * Array of DLL of paths traversing the peer, organized by the
129 * offset of the peer on the larger path.
130 */
131 struct CadetPeerPathEntry **path_tails;
132
133 /**
134 * Notifications to call when @e core_mq changes.
135 */
136 struct GCP_MessageQueueManager *mqm_head;
137
138 /**
139 * Notifications to call when @e core_mq changes.
140 */
141 struct GCP_MessageQueueManager *mqm_tail;
142
143 /**
144 * Pointer to first "ready" entry in @e mqm_head.
145 */
146 struct GCP_MessageQueueManager *mqm_ready_ptr;
147
148 /**
149 * MIN-heap of paths owned by this peer (they also end at this
150 * peer). Ordered by desirability.
151 */
152 struct GNUNET_CONTAINER_Heap *path_heap;
153
154 /**
155 * Handle to stop the DHT search for paths to this peer
156 */
157 struct GCD_search_handle *search_h;
158
159 /**
160 * Task to clean up @e path_heap asynchronously.
161 */
162 struct GNUNET_SCHEDULER_Task *heap_cleanup_task;
163
164 /**
165 * Task to destroy this entry.
166 */
167 struct GNUNET_SCHEDULER_Task *destroy_task;
168
169 /**
170 * Tunnel to this peer, if any.
171 */
172 struct CadetTunnel *t;
173
174 /**
175 * Connections that go through this peer; indexed by tid.
176 */
177 struct GNUNET_CONTAINER_MultiShortmap *connections;
178
179 /**
180 * Handle for core transmissions.
181 */
182 struct GNUNET_MQ_Handle *core_mq;
183
184 /**
185 * Hello message of the peer.
186 */
187 struct GNUNET_HELLO_Message *hello;
188
189 /**
190 * Handle to us offering the HELLO to the transport.
191 */
192 struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
193
194 /**
195 * Handle to our ATS request asking ATS to suggest an address
196 * to TRANSPORT for this peer (to establish a direct link).
197 */
198 struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
199
200 /**
201 * How many messages are in the queue to this peer.
202 */
203 unsigned int queue_n;
204
205 /**
206 * How many paths do we have to this peer (in all @e path_heads DLLs combined).
207 */
208 unsigned int num_paths;
209
210 /**
211 * Sum over all of the offsets of all of the paths in the @a path_heads DLLs.
212 * Used to speed-up @GCP_get_desirability_of_path() calculation.
213 */
214 unsigned int off_sum;
215
216 /**
217 * Number of message queue managers of this peer that have a message in waiting.
218 *
219 * Used to quickly see if we need to bother scanning the @e msm_head DLL.
220 * TODO: could be replaced by another DLL that would then allow us to avoid
221 * the O(n)-scan of the DLL for ready entries!
222 */
223 unsigned int mqm_ready_counter;
224
225 /**
226 * Current length of the @e path_heads and @path_tails arrays.
227 * The arrays should be grown as needed.
228 */
229 unsigned int path_dll_length;
230
231};
232
233
234/**
235 * Get the static string for a peer ID.
236 *
237 * @param cp Peer.
238 * @return Static string for it's ID.
239 */
240const char *
241GCP_2s (const struct CadetPeer *cp)
242{
243 static char buf[32];
244
245 GNUNET_snprintf (buf,
246 sizeof (buf),
247 "P(%s)",
248 GNUNET_i2s (&cp->pid));
249 return buf;
250}
251
252
253/**
254 * Calculate how desirable a path is for @a cp if @a cp
255 * is at offset @a off.
256 *
257 * The 'desirability_table.c' program can be used to compute a list of
258 * sample outputs for different scenarios. Basically, we score paths
259 * lower if there are many alternatives, and higher if they are
260 * shorter than average, and very high if they are much shorter than
261 * average and without many alternatives.
262 *
263 * @param cp a peer reachable via a path
264 * @param off offset of @a cp in the path
265 * @return score how useful a path is to reach @a cp,
266 * positive scores mean path is more desirable
267 */
268double
269GCP_get_desirability_of_path (struct CadetPeer *cp,
270 unsigned int off)
271{
272 unsigned int num_alts = cp->num_paths;
273 unsigned int off_sum;
274 double avg_sum;
275 double path_delta;
276 double weight_alts;
277
278 GNUNET_assert (num_alts >= 1); /* 'path' should be in there! */
279 GNUNET_assert (0 != cp->path_dll_length);
280
281 /* We maintain 'off_sum' in 'peer' and thereby
282 avoid the SLOW recalculation each time. Kept here
283 just to document what is going on. */
284#if SLOW
285 off_sum = 0;
286 for (unsigned int j=0;j<cp->path_dll_length;j++)
287 for (struct CadetPeerPathEntry *pe = cp->path_heads[j];
288 NULL != pe;
289 pe = pe->next)
290 off_sum += j;
291 GNUNET_assert (off_sum == cp->off_sum);
292#else
293 off_sum = cp->off_sum;
294#endif
295 avg_sum = off_sum * 1.0 / cp->path_dll_length;
296 path_delta = off - avg_sum;
297 /* path_delta positiv: path off of peer above average (bad path for peer),
298 path_delta negativ: path off of peer below average (good path for peer) */
299 if (path_delta <= - 1.0)
300 weight_alts = - num_alts / path_delta; /* discount alternative paths */
301 else if (path_delta >= 1.0)
302 weight_alts = num_alts * path_delta; /* overcount alternative paths */
303 else
304 weight_alts = num_alts; /* count alternative paths normally */
305
306
307 /* off+1: long paths are generally harder to find and thus count
308 a bit more as they get longer. However, above-average paths
309 still need to count less, hence the squaring of that factor. */
310 return (off + 1.0) / (weight_alts * weight_alts);
311}
312
313
314/**
315 * This peer is no longer be needed, clean it up now.
316 *
317 * @param cls peer to clean up
318 */
319static void
320destroy_peer (void *cls)
321{
322 struct CadetPeer *cp = cls;
323
324 LOG (GNUNET_ERROR_TYPE_DEBUG,
325 "Destroying state about peer %s\n",
326 GCP_2s (cp));
327 cp->destroy_task = NULL;
328 GNUNET_assert (NULL == cp->t);
329 GNUNET_assert (NULL == cp->core_mq);
330 GNUNET_assert (0 == cp->num_paths);
331 for (unsigned int i=0;i<cp->path_dll_length;i++)
332 GNUNET_assert (NULL == cp->path_heads[i]);
333 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections));
334 GNUNET_assert (GNUNET_YES ==
335 GNUNET_CONTAINER_multipeermap_remove (peers,
336 &cp->pid,
337 cp));
338 GNUNET_free_non_null (cp->path_heads);
339 GNUNET_free_non_null (cp->path_tails);
340 cp->path_dll_length = 0;
341 if (NULL != cp->search_h)
342 {
343 GCD_search_stop (cp->search_h);
344 cp->search_h = NULL;
345 }
346 /* FIXME: clean up search_delayedXXX! */
347
348 if (NULL != cp->hello_offer)
349 {
350 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
351 cp->hello_offer = NULL;
352 }
353 if (NULL != cp->connectivity_suggestion)
354 {
355 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
356 cp->connectivity_suggestion = NULL;
357 }
358 GNUNET_CONTAINER_multishortmap_destroy (cp->connections);
359 if (NULL != cp->path_heap)
360 {
361 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
362 cp->path_heap = NULL;
363 }
364 if (NULL != cp->heap_cleanup_task)
365 {
366 GNUNET_SCHEDULER_cancel (cp->heap_cleanup_task);
367 cp->heap_cleanup_task = NULL;
368 }
369 GNUNET_free_non_null (cp->hello);
370 /* Peer should not be freed if paths exist; if there are no paths,
371 there ought to be no connections, and without connections, no
372 notifications. Thus we can assert that mqm_head is empty at this
373 point. */
374 GNUNET_assert (NULL == cp->mqm_head);
375 GNUNET_assert (NULL == cp->mqm_ready_ptr);
376 GNUNET_free (cp);
377}
378
379
380/**
381 * This peer is now on more "active" duty, activate processes related to it.
382 *
383 * @param cp the more-active peer
384 */
385static void
386consider_peer_activate (struct CadetPeer *cp)
387{
388 uint32_t strength;
389
390 LOG (GNUNET_ERROR_TYPE_DEBUG,
391 "Updating peer %s activation state (%u connections)%s%s\n",
392 GCP_2s (cp),
393 GNUNET_CONTAINER_multishortmap_size (cp->connections),
394 (NULL == cp->t) ? "" : " with tunnel",
395 (NULL == cp->core_mq) ? "" : " with CORE link");
396 if (NULL != cp->destroy_task)
397 {
398 /* It's active, do not destory! */
399 GNUNET_SCHEDULER_cancel (cp->destroy_task);
400 cp->destroy_task = NULL;
401 }
402 if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
403 (NULL == cp->t) )
404 {
405 /* We're just on a path or directly connected; don't bother too much */
406 if (NULL != cp->connectivity_suggestion)
407 {
408 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
409 cp->connectivity_suggestion = NULL;
410 }
411 if (NULL != cp->search_h)
412 {
413 GCD_search_stop (cp->search_h);
414 cp->search_h = NULL;
415 }
416 return;
417 }
418 if (NULL == cp->core_mq)
419 {
420 /* Lacks direct connection, try to create one by querying the DHT */
421 if ( (NULL == cp->search_h) &&
422 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
423 cp->search_h
424 = GCD_search (&cp->pid);
425 }
426 else
427 {
428 /* Have direct connection, stop DHT search if active */
429 if (NULL != cp->search_h)
430 {
431 GCD_search_stop (cp->search_h);
432 cp->search_h = NULL;
433 }
434 }
435
436 /* If we have a tunnel, our urge for connections is much bigger */
437 strength = (NULL != cp->t) ? 32 : 1;
438 if (NULL != cp->connectivity_suggestion)
439 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
440 cp->connectivity_suggestion
441 = GNUNET_ATS_connectivity_suggest (ats_ch,
442 &cp->pid,
443 strength);
444}
445
446
447/**
448 * This peer may no longer be needed, consider cleaning it up.
449 *
450 * @param cp peer to clean up
451 */
452static void
453consider_peer_destroy (struct CadetPeer *cp);
454
455
456/**
457 * We really no longere care about a peer, stop hogging memory with paths to it.
458 * Afterwards, see if there is more to be cleaned up about this peer.
459 *
460 * @param cls a `struct CadetPeer`.
461 */
462static void
463drop_paths (void *cls)
464{
465 struct CadetPeer *cp = cls;
466 struct CadetPeerPath *path;
467
468 cp->destroy_task = NULL;
469 while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
470 GCPP_release (path);
471 consider_peer_destroy (cp);
472}
473
474
475/**
476 * This peer may no longer be needed, consider cleaning it up.
477 *
478 * @param cp peer to clean up
479 */
480static void
481consider_peer_destroy (struct CadetPeer *cp)
482{
483 struct GNUNET_TIME_Relative exp;
484
485 if (NULL != cp->destroy_task)
486 {
487 GNUNET_SCHEDULER_cancel (cp->destroy_task);
488 cp->destroy_task = NULL;
489 }
490 if (NULL != cp->t)
491 return; /* still relevant! */
492 if (NULL != cp->core_mq)
493 return; /* still relevant! */
494 if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
495 return; /* still relevant! */
496 if ( (NULL != cp->path_heap) &&
497 (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap)) )
498 {
499 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
500 &drop_paths,
501 cp);
502 return;
503 }
504 if (0 != cp->num_paths)
505 return; /* still relevant! */
506 if (NULL != cp->hello)
507 {
508 /* relevant only until HELLO expires */
509 exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
510 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
511 &destroy_peer,
512 cp);
513 return;
514 }
515 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
516 &destroy_peer,
517 cp);
518}
519
520
521/**
522 * Set the message queue to @a mq for peer @a cp and notify watchers.
523 *
524 * @param cp peer to modify
525 * @param mq message queue to set (can be NULL)
526 */
527void
528GCP_set_mq (struct CadetPeer *cp,
529 struct GNUNET_MQ_Handle *mq)
530{
531 LOG (GNUNET_ERROR_TYPE_DEBUG,
532 "Message queue for peer %s is now %p\n",
533 GCP_2s (cp),
534 mq);
535 cp->core_mq = mq;
536 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head, *next;
537 NULL != mqm;
538 mqm = next)
539 {
540 /* Save next pointer in case mqm gets freed by the callback */
541 next = mqm->next;
542 if (NULL == mq)
543 {
544 if (NULL != mqm->env)
545 {
546 GNUNET_MQ_discard (mqm->env);
547 mqm->env = NULL;
548 mqm->cb (mqm->cb_cls,
549 GNUNET_SYSERR);
550 }
551 else
552 {
553 mqm->cb (mqm->cb_cls,
554 GNUNET_NO);
555 }
556 }
557 else
558 {
559 GNUNET_assert (NULL == mqm->env);
560 mqm->cb (mqm->cb_cls,
561 GNUNET_YES);
562 }
563 }
564 if ( (NULL != mq) ||
565 (NULL != cp->t) )
566 consider_peer_activate (cp);
567 else
568 consider_peer_destroy (cp);
569
570 if ( (NULL != mq) &&
571 (NULL != cp->t) )
572 {
573 /* have a new, direct path to the target, notify tunnel */
574 struct CadetPeerPath *path;
575
576 path = GCPP_get_path_from_route (1,
577 &cp->pid);
578 GCT_consider_path (cp->t,
579 path,
580 0);
581 }
582}
583
584
585/**
586 * Debug function should NEVER return true in production code, useful to
587 * simulate losses for testcases.
588 *
589 * @return #GNUNET_YES or #GNUNET_NO with the decision to drop.
590 */
591static int
592should_I_drop (void)
593{
594 if (0 == drop_percent)
595 return GNUNET_NO;
596 if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
597 101) < drop_percent)
598 return GNUNET_YES;
599 return GNUNET_NO;
600}
601
602
603/**
604 * Function called when CORE took one of the messages from
605 * a message queue manager and transmitted it.
606 *
607 * @param cls the `struct CadetPeeer` where we made progress
608 */
609static void
610mqm_send_done (void *cls);
611
612
613/**
614 * Transmit current envelope from this @a mqm.
615 *
616 * @param mqm mqm to transmit message for now
617 */
618static void
619mqm_execute (struct GCP_MessageQueueManager *mqm)
620{
621 struct CadetPeer *cp = mqm->cp;
622
623 /* Move ready pointer to the next entry that might be ready. */
624 if ( (mqm == cp->mqm_ready_ptr) &&
625 (NULL != mqm->next) )
626 cp->mqm_ready_ptr = mqm->next;
627 /* Move entry to the end of the DLL, to be fair. */
628 if (mqm != cp->mqm_tail)
629 {
630 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
631 cp->mqm_tail,
632 mqm);
633 GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
634 cp->mqm_tail,
635 mqm);
636 }
637 cp->mqm_ready_counter--;
638 if (GNUNET_YES == should_I_drop ())
639 {
640 LOG (GNUNET_ERROR_TYPE_DEBUG,
641 "DROPPING message to peer %s from MQM %p\n",
642 GCP_2s (cp),
643 mqm);
644 GNUNET_MQ_discard (mqm->env);
645 mqm->env = NULL;
646 mqm_send_done (cp);
647 }
648 else
649 {
650 LOG (GNUNET_ERROR_TYPE_DEBUG,
651 "Sending to peer %s from MQM %p\n",
652 GCP_2s (cp),
653 mqm);
654 GNUNET_MQ_send (cp->core_mq,
655 mqm->env);
656 mqm->env = NULL;
657 }
658 mqm->cb (mqm->cb_cls,
659 GNUNET_YES);
660}
661
662
663/**
664 * Find the next ready message in the queue (starting
665 * the search from the `cp->mqm_ready_ptr`) and if possible
666 * execute the transmission.
667 *
668 * @param cp peer to try to send the next ready message to
669 */
670static void
671send_next_ready (struct CadetPeer *cp)
672{
673 struct GCP_MessageQueueManager *mqm;
674
675 if (0 == cp->mqm_ready_counter)
676 return;
677 while ( (NULL != (mqm = cp->mqm_ready_ptr)) &&
678 (NULL == mqm->env) )
679 cp->mqm_ready_ptr = mqm->next;
680 if (NULL == mqm)
681 return; /* nothing to do */
682 mqm_execute (mqm);
683}
684
685
686/**
687 * Function called when CORE took one of the messages from
688 * a message queue manager and transmitted it.
689 *
690 * @param cls the `struct CadetPeeer` where we made progress
691 */
692static void
693mqm_send_done (void *cls)
694{
695 struct CadetPeer *cp = cls;
696
697 LOG (GNUNET_ERROR_TYPE_DEBUG,
698 "Sending to peer %s completed\n",
699 GCP_2s (cp));
700 send_next_ready (cp);
701}
702
703
704/**
705 * Send the message in @a env to @a cp.
706 *
707 * @param mqm the message queue manager to use for transmission
708 * @param env envelope with the message to send; must NOT
709 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
710 */
711void
712GCP_send (struct GCP_MessageQueueManager *mqm,
713 struct GNUNET_MQ_Envelope *env)
714{
715 struct CadetPeer *cp = mqm->cp;
716
717 GNUNET_assert (NULL != env);
718 LOG (GNUNET_ERROR_TYPE_DEBUG,
719 "Queueing message to peer %s in MQM %p\n",
720 GCP_2s (cp),
721 mqm);
722 GNUNET_assert (NULL != cp->core_mq);
723 GNUNET_assert (NULL == mqm->env);
724 GNUNET_MQ_notify_sent (env,
725 &mqm_send_done,
726 cp);
727 mqm->env = env;
728 cp->mqm_ready_counter++;
729 if (mqm != cp->mqm_ready_ptr)
730 cp->mqm_ready_ptr = cp->mqm_head;
731 if (1 == cp->mqm_ready_counter)
732 cp->mqm_ready_ptr = mqm;
733 if (0 != GNUNET_MQ_get_length (cp->core_mq))
734 return;
735 send_next_ready (cp);
736}
737
738
739/**
740 * Function called to destroy a peer now.
741 *
742 * @param cls NULL
743 * @param pid identity of the peer (unused)
744 * @param value the `struct CadetPeer` to clean up
745 * @return #GNUNET_OK (continue to iterate)
746 */
747static int
748destroy_iterator_cb (void *cls,
749 const struct GNUNET_PeerIdentity *pid,
750 void *value)
751{
752 struct CadetPeer *cp = value;
753
754 if (NULL != cp->destroy_task)
755 {
756 GNUNET_SCHEDULER_cancel (cp->destroy_task);
757 cp->destroy_task = NULL;
758 }
759 destroy_peer (cp);
760 return GNUNET_OK;
761}
762
763
764/**
765 * Clean up all entries about all peers.
766 * Must only be called after all tunnels, CORE-connections and
767 * connections are down.
768 */
769void
770GCP_destroy_all_peers ()
771{
772 LOG (GNUNET_ERROR_TYPE_DEBUG,
773 "Destroying all peers now\n");
774 GNUNET_CONTAINER_multipeermap_iterate (peers,
775 &destroy_iterator_cb,
776 NULL);
777}
778
779
780/**
781 * Drop all paths owned by this peer, and do not
782 * allow new ones to be added: We are shutting down.
783 *
784 * @param cp peer to drop paths to
785 */
786void
787GCP_drop_owned_paths (struct CadetPeer *cp)
788{
789 struct CadetPeerPath *path;
790
791 LOG (GNUNET_ERROR_TYPE_DEBUG,
792 "Destroying all paths to %s\n",
793 GCP_2s (cp));
794 while (NULL != (path =
795 GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
796 GCPP_release (path);
797 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
798 cp->path_heap = NULL;
799}
800
801
802/**
803 * Add an entry to the DLL of all of the paths that this peer is on.
804 *
805 * @param cp peer to modify
806 * @param entry an entry on a path
807 * @param off offset of this peer on the path
808 */
809void
810GCP_path_entry_add (struct CadetPeer *cp,
811 struct CadetPeerPathEntry *entry,
812 unsigned int off)
813{
814 GNUNET_assert (cp == GCPP_get_peer_at_offset (entry->path,
815 off));
816 LOG (GNUNET_ERROR_TYPE_DEBUG,
817 "Discovered that peer %s is on path %s at offset %u\n",
818 GCP_2s (cp),
819 GCPP_2s (entry->path),
820 off);
821 if (off >= cp->path_dll_length)
822 {
823 unsigned int len = cp->path_dll_length;
824
825 GNUNET_array_grow (cp->path_heads,
826 len,
827 off + 4);
828 GNUNET_array_grow (cp->path_tails,
829 cp->path_dll_length,
830 off + 4);
831 }
832 GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
833 cp->path_tails[off],
834 entry);
835 cp->off_sum += off;
836 cp->num_paths++;
837
838 /* If we have a tunnel to this peer, tell the tunnel that there is a
839 new path available. */
840 if (NULL != cp->t)
841 GCT_consider_path (cp->t,
842 entry->path,
843 off);
844
845 if ( (NULL != cp->search_h) &&
846 (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths) )
847 {
848 /* Now I have enough paths, stop search */
849 GCD_search_stop (cp->search_h);
850 cp->search_h = NULL;
851 }
852 if (NULL != cp->destroy_task)
853 {
854 /* paths changed, this resets the destroy timeout counter
855 and aborts a destroy task that may no longer be valid
856 to have (as we now have more paths via this peer). */
857 consider_peer_destroy (cp);
858 }
859}
860
861
862/**
863 * Remove an entry from the DLL of all of the paths that this peer is on.
864 *
865 * @param cp peer to modify
866 * @param entry an entry on a path
867 * @param off offset of this peer on the path
868 */
869void
870GCP_path_entry_remove (struct CadetPeer *cp,
871 struct CadetPeerPathEntry *entry,
872 unsigned int off)
873{
874 LOG (GNUNET_ERROR_TYPE_DEBUG,
875 "Removing knowledge about peer %s beging on path %s at offset %u\n",
876 GCP_2s (cp),
877 GCPP_2s (entry->path),
878 off);
879 GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
880 cp->path_tails[off],
881 entry);
882 GNUNET_assert (0 < cp->num_paths);
883 cp->off_sum -= off;
884 cp->num_paths--;
885 if ( (NULL == cp->core_mq) &&
886 (NULL != cp->t) &&
887 (NULL == cp->search_h) &&
888 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
889 cp->search_h
890 = GCD_search (&cp->pid);
891 if (NULL == cp->destroy_task)
892 {
893 /* paths changed, we might now be ready for destruction, check again */
894 consider_peer_destroy (cp);
895 }
896}
897
898
899/**
900 * Prune down the number of paths to this peer, we seem to
901 * have way too many.
902 *
903 * @param cls the `struct CadetPeer` to maintain the path heap for
904 */
905static void
906path_heap_cleanup (void *cls)
907{
908 struct CadetPeer *cp = cls;
909 struct CadetPeerPath *root;
910
911 cp->heap_cleanup_task = NULL;
912 while (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
913 2 * DESIRED_CONNECTIONS_PER_TUNNEL)
914 {
915 /* Now we have way too many, drop least desirable UNLESS it is in use!
916 (Note that this intentionally keeps highly desireable, but currently
917 unused paths around in the hope that we might be able to switch, even
918 if the number of paths exceeds the threshold.) */
919 root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
920 GNUNET_assert (NULL != root);
921 if (NULL !=
922 GCPP_get_connection (root,
923 cp,
924 GCPP_get_length (root) - 1))
925 break; /* can't fix */
926 /* Got plenty of paths to this destination, and this is a low-quality
927 one that we don't care about. Allow it to die. */
928 GNUNET_assert (root ==
929 GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
930 GCPP_release (root);
931 }
932}
933
934
935/**
936 * Try adding a @a path to this @a peer. If the peer already
937 * has plenty of paths, return NULL.
938 *
939 * @param cp peer to which the @a path leads to
940 * @param path a path looking for an owner; may not be fully initialized yet!
941 * @param off offset of @a cp in @a path
942 * @param force force attaching the path
943 * @return NULL if this peer does not care to become a new owner,
944 * otherwise the node in the peer's path heap for the @a path.
945 */
946struct GNUNET_CONTAINER_HeapNode *
947GCP_attach_path (struct CadetPeer *cp,
948 struct CadetPeerPath *path,
949 unsigned int off,
950 int force)
951{
952 GNUNET_CONTAINER_HeapCostType desirability;
953 struct CadetPeerPath *root;
954 GNUNET_CONTAINER_HeapCostType root_desirability;
955 struct GNUNET_CONTAINER_HeapNode *hn;
956
957 GNUNET_assert (off == GCPP_get_length (path) - 1);
958 GNUNET_assert (cp == GCPP_get_peer_at_offset (path,
959 off));
960 if (NULL == cp->path_heap)
961 {
962 /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */
963 GNUNET_assert (GNUNET_NO == force);
964 return NULL;
965 }
966 desirability = GCPP_get_desirability (path);
967 if (GNUNET_NO == force)
968 {
969 /* FIXME: desirability is not yet initialized; tricky! */
970 if (GNUNET_NO ==
971 GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
972 (void **) &root,
973 &root_desirability))
974 {
975 root = NULL;
976 root_desirability = 0;
977 }
978
979 if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
980 (desirability < root_desirability) )
981 {
982 LOG (GNUNET_ERROR_TYPE_DEBUG,
983 "Decided to not attach path %p to peer %s due to undesirability\n",
984 GCPP_2s (path),
985 GCP_2s (cp));
986 return NULL;
987 }
988 }
989
990 LOG (GNUNET_ERROR_TYPE_DEBUG,
991 "Attaching path %s to peer %s (%s)\n",
992 GCPP_2s (path),
993 GCP_2s (cp),
994 (GNUNET_NO == force) ? "desirable" : "forced");
995
996 /* Yes, we'd like to add this path, add to our heap */
997 hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
998 path,
999 desirability);
1000
1001 /* Consider maybe dropping other paths because of the new one */
1002 if ( (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
1003 2 * DESIRED_CONNECTIONS_PER_TUNNEL) &&
1004 (NULL != cp->heap_cleanup_task) )
1005 cp->heap_cleanup_task = GNUNET_SCHEDULER_add_now (&path_heap_cleanup,
1006 cp);
1007 return hn;
1008}
1009
1010
1011/**
1012 * This peer can no longer own @a path as the path
1013 * has been extended and a peer further down the line
1014 * is now the new owner.
1015 *
1016 * @param cp old owner of the @a path
1017 * @param path path where the ownership is lost
1018 * @param hn note in @a cp's path heap that must be deleted
1019 */
1020void
1021GCP_detach_path (struct CadetPeer *cp,
1022 struct CadetPeerPath *path,
1023 struct GNUNET_CONTAINER_HeapNode *hn)
1024{
1025 LOG (GNUNET_ERROR_TYPE_DEBUG,
1026 "Detatching path %s from peer %s\n",
1027 GCPP_2s (path),
1028 GCP_2s (cp));
1029 GNUNET_assert (path ==
1030 GNUNET_CONTAINER_heap_remove_node (hn));
1031}
1032
1033
1034/**
1035 * Add a @a connection to this @a cp.
1036 *
1037 * @param cp peer via which the @a connection goes
1038 * @param cc the connection to add
1039 */
1040void
1041GCP_add_connection (struct CadetPeer *cp,
1042 struct CadetConnection *cc)
1043{
1044 LOG (GNUNET_ERROR_TYPE_DEBUG,
1045 "Adding connection %s to peer %s\n",
1046 GCC_2s (cc),
1047 GCP_2s (cp));
1048 GNUNET_assert (GNUNET_OK ==
1049 GNUNET_CONTAINER_multishortmap_put (cp->connections,
1050 &GCC_get_id (cc)->connection_of_tunnel,
1051 cc,
1052 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1053 if (NULL != cp->destroy_task)
1054 {
1055 GNUNET_SCHEDULER_cancel (cp->destroy_task);
1056 cp->destroy_task = NULL;
1057 }
1058}
1059
1060
1061/**
1062 * Remove a @a connection that went via this @a cp.
1063 *
1064 * @param cp peer via which the @a connection went
1065 * @param cc the connection to remove
1066 */
1067void
1068GCP_remove_connection (struct CadetPeer *cp,
1069 struct CadetConnection *cc)
1070{
1071 LOG (GNUNET_ERROR_TYPE_DEBUG,
1072 "Removing connection %s from peer %s\n",
1073 GCC_2s (cc),
1074 GCP_2s (cp));
1075 GNUNET_assert (GNUNET_YES ==
1076 GNUNET_CONTAINER_multishortmap_remove (cp->connections,
1077 &GCC_get_id (cc)->connection_of_tunnel,
1078 cc));
1079 consider_peer_destroy (cp);
1080}
1081
1082
1083/**
1084 * Retrieve the CadetPeer stucture associated with the
1085 * peer. Optionally create one and insert it in the appropriate
1086 * structures if the peer is not known yet.
1087 *
1088 * @param peer_id Full identity of the peer.
1089 * @param create #GNUNET_YES if a new peer should be created if unknown.
1090 * #GNUNET_NO to return NULL if peer is unknown.
1091 * @return Existing or newly created peer structure.
1092 * NULL if unknown and not requested @a create
1093 */
1094struct CadetPeer *
1095GCP_get (const struct GNUNET_PeerIdentity *peer_id,
1096 int create)
1097{
1098 struct CadetPeer *cp;
1099
1100 cp = GNUNET_CONTAINER_multipeermap_get (peers,
1101 peer_id);
1102 if (NULL != cp)
1103 return cp;
1104 if (GNUNET_NO == create)
1105 return NULL;
1106 cp = GNUNET_new (struct CadetPeer);
1107 cp->pid = *peer_id;
1108 cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
1109 GNUNET_YES);
1110 cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1111 GNUNET_assert (GNUNET_YES ==
1112 GNUNET_CONTAINER_multipeermap_put (peers,
1113 &cp->pid,
1114 cp,
1115 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1116 LOG (GNUNET_ERROR_TYPE_DEBUG,
1117 "Creating peer %s\n",
1118 GCP_2s (cp));
1119 return cp;
1120}
1121
1122
1123/**
1124 * Obtain the peer identity for a `struct CadetPeer`.
1125 *
1126 * @param cp our peer handle
1127 * @return the peer identity
1128 */
1129const struct GNUNET_PeerIdentity *
1130GCP_get_id (struct CadetPeer *cp)
1131{
1132 return &cp->pid;
1133}
1134
1135
1136/**
1137 * Iterate over all known peers.
1138 *
1139 * @param iter Iterator.
1140 * @param cls Closure for @c iter.
1141 */
1142void
1143GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
1144 void *cls)
1145{
1146 GNUNET_CONTAINER_multipeermap_iterate (peers,
1147 iter,
1148 cls);
1149}
1150
1151
1152/**
1153 * Count the number of known paths toward the peer.
1154 *
1155 * @param cp Peer to get path info.
1156 * @return Number of known paths.
1157 */
1158unsigned int
1159GCP_count_paths (const struct CadetPeer *cp)
1160{
1161 return cp->num_paths;
1162}
1163
1164
1165/**
1166 * Iterate over the paths to a peer.
1167 *
1168 * @param cp Peer to get path info.
1169 * @param callback Function to call for every path.
1170 * @param callback_cls Closure for @a callback.
1171 * @return Number of iterated paths.
1172 */
1173unsigned int
1174GCP_iterate_paths (struct CadetPeer *cp,
1175 GCP_PathIterator callback,
1176 void *callback_cls)
1177{
1178 unsigned int ret = 0;
1179
1180 LOG (GNUNET_ERROR_TYPE_DEBUG,
1181 "Iterating over paths to peer %s%s\n",
1182 GCP_2s (cp),
1183 (NULL == cp->core_mq) ? "" : " including direct link");
1184 if (NULL != cp->core_mq)
1185 {
1186 struct CadetPeerPath *path;
1187
1188 path = GCPP_get_path_from_route (1,
1189 &cp->pid);
1190 ret++;
1191 if (GNUNET_NO ==
1192 callback (callback_cls,
1193 path,
1194 0))
1195 return ret;
1196 }
1197 for (unsigned int i=0;i<cp->path_dll_length;i++)
1198 {
1199 for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1200 NULL != pe;
1201 pe = pe->next)
1202 {
1203 ret++;
1204 if (GNUNET_NO ==
1205 callback (callback_cls,
1206 pe->path,
1207 i))
1208 return ret;
1209 }
1210 }
1211 return ret;
1212}
1213
1214
1215/**
1216 * Iterate over the paths to @a cp where
1217 * @a cp is at distance @a dist from us.
1218 *
1219 * @param cp Peer to get path info.
1220 * @param dist desired distance of @a cp to us on the path
1221 * @param callback Function to call for every path.
1222 * @param callback_cls Closure for @a callback.
1223 * @return Number of iterated paths.
1224 */
1225unsigned int
1226GCP_iterate_paths_at (struct CadetPeer *cp,
1227 unsigned int dist,
1228 GCP_PathIterator callback,
1229 void *callback_cls)
1230{
1231 unsigned int ret = 0;
1232
1233 if (dist >= cp->path_dll_length)
1234 {
1235 LOG (GNUNET_ERROR_TYPE_DEBUG,
1236 "Asked to look for paths at distance %u, but maximum for me is < %u\n",
1237 dist,
1238 cp->path_dll_length);
1239 return 0;
1240 }
1241 for (struct CadetPeerPathEntry *pe = cp->path_heads[dist];
1242 NULL != pe;
1243 pe = pe->next)
1244 {
1245 if (GNUNET_NO ==
1246 callback (callback_cls,
1247 pe->path,
1248 dist))
1249 return ret;
1250 ret++;
1251 }
1252 return ret;
1253}
1254
1255
1256/**
1257 * Get the tunnel towards a peer.
1258 *
1259 * @param cp Peer to get from.
1260 * @param create #GNUNET_YES to create a tunnel if we do not have one
1261 * @return Tunnel towards peer.
1262 */
1263struct CadetTunnel *
1264GCP_get_tunnel (struct CadetPeer *cp,
1265 int create)
1266{
1267 if (NULL == cp)
1268 return NULL;
1269 if ( (NULL != cp->t) ||
1270 (GNUNET_NO == create) )
1271 return cp->t;
1272 cp->t = GCT_create_tunnel (cp);
1273 consider_peer_activate (cp);
1274 return cp->t;
1275}
1276
1277
1278/**
1279 * Hello offer was passed to the transport service. Mark it
1280 * as done.
1281 *
1282 * @param cls the `struct CadetPeer` where the offer completed
1283 */
1284static void
1285hello_offer_done (void *cls)
1286{
1287 struct CadetPeer *cp = cls;
1288
1289 cp->hello_offer = NULL;
1290}
1291
1292
1293/**
1294 * We got a HELLO for a @a peer, remember it, and possibly
1295 * trigger adequate actions (like trying to connect).
1296 *
1297 * @param cp the peer we got a HELLO for
1298 * @param hello the HELLO to remember
1299 */
1300void
1301GCP_set_hello (struct CadetPeer *cp,
1302 const struct GNUNET_HELLO_Message *hello)
1303{
1304 struct GNUNET_HELLO_Message *mrg;
1305
1306 LOG (GNUNET_ERROR_TYPE_DEBUG,
1307 "Got %u byte HELLO for peer %s\n",
1308 (unsigned int) GNUNET_HELLO_size (hello),
1309 GCP_2s (cp));
1310 if (NULL != cp->hello_offer)
1311 {
1312 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
1313 cp->hello_offer = NULL;
1314 }
1315 if (NULL != cp->hello)
1316 {
1317 mrg = GNUNET_HELLO_merge (hello,
1318 cp->hello);
1319 GNUNET_free (cp->hello);
1320 cp->hello = mrg;
1321 }
1322 else
1323 {
1324 cp->hello = GNUNET_memdup (hello,
1325 GNUNET_HELLO_size (hello));
1326 }
1327 cp->hello_offer
1328 = GNUNET_TRANSPORT_offer_hello (cfg,
1329 GNUNET_HELLO_get_header (cp->hello) ,
1330 &hello_offer_done,
1331 cp);
1332 /* New HELLO means cp's destruction time may change... */
1333 consider_peer_destroy (cp);
1334}
1335
1336
1337/**
1338 * The tunnel to the given peer no longer exists, remove it from our
1339 * data structures, and possibly clean up the peer itself.
1340 *
1341 * @param cp the peer affected
1342 * @param t the dead tunnel
1343 */
1344void
1345GCP_drop_tunnel (struct CadetPeer *cp,
1346 struct CadetTunnel *t)
1347{
1348 LOG (GNUNET_ERROR_TYPE_DEBUG,
1349 "Dropping tunnel %s to peer %s\n",
1350 GCT_2s (t),
1351 GCP_2s (cp));
1352 GNUNET_assert (cp->t == t);
1353 cp->t = NULL;
1354 consider_peer_destroy (cp);
1355}
1356
1357
1358/**
1359 * Test if @a cp has a core-level connection
1360 *
1361 * @param cp peer to test
1362 * @return #GNUNET_YES if @a cp has a core-level connection
1363 */
1364int
1365GCP_has_core_connection (struct CadetPeer *cp)
1366{
1367 return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1368}
1369
1370
1371/**
1372 * Start message queue change notifications.
1373 *
1374 * @param cp peer to notify for
1375 * @param cb function to call if mq becomes available or unavailable
1376 * @param cb_cls closure for @a cb
1377 * @return handle to cancel request
1378 */
1379struct GCP_MessageQueueManager *
1380GCP_request_mq (struct CadetPeer *cp,
1381 GCP_MessageQueueNotificationCallback cb,
1382 void *cb_cls)
1383{
1384 struct GCP_MessageQueueManager *mqm;
1385
1386 mqm = GNUNET_new (struct GCP_MessageQueueManager);
1387 mqm->cb = cb;
1388 mqm->cb_cls = cb_cls;
1389 mqm->cp = cp;
1390 GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
1391 cp->mqm_tail,
1392 mqm);
1393 LOG (GNUNET_ERROR_TYPE_DEBUG,
1394 "Creating MQM %p for peer %s\n",
1395 mqm,
1396 GCP_2s (cp));
1397 if (NULL != cp->core_mq)
1398 cb (cb_cls,
1399 GNUNET_YES);
1400 return mqm;
1401}
1402
1403
1404/**
1405 * Stops message queue change notifications.
1406 *
1407 * @param mqm handle matching request to cancel
1408 * @param last_env final message to transmit, or NULL
1409 */
1410void
1411GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
1412 struct GNUNET_MQ_Envelope *last_env)
1413{
1414 struct CadetPeer *cp = mqm->cp;
1415
1416 LOG (GNUNET_ERROR_TYPE_DEBUG,
1417 "Destroying MQM %p for peer %s%s\n",
1418 mqm,
1419 GCP_2s (cp),
1420 (NULL == last_env) ? "" : " with last ditch transmission");
1421 if (NULL != mqm->env)
1422 GNUNET_MQ_discard (mqm->env);
1423 if (NULL != last_env)
1424 {
1425 if (NULL != cp->core_mq)
1426 {
1427 GNUNET_MQ_notify_sent (last_env,
1428 &mqm_send_done,
1429 cp);
1430 GNUNET_MQ_send (cp->core_mq,
1431 last_env);
1432 }
1433 else
1434 {
1435 GNUNET_MQ_discard (last_env);
1436 }
1437 }
1438 if (cp->mqm_ready_ptr == mqm)
1439 cp->mqm_ready_ptr = mqm->next;
1440 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1441 cp->mqm_tail,
1442 mqm);
1443 GNUNET_free (mqm);
1444}
1445
1446
1447/**
1448 * Send the message in @a env to @a cp, overriding queueing logic.
1449 * This function should only be used to send error messages outside
1450 * of flow and congestion control, similar to ICMP. Note that
1451 * the envelope may be silently discarded as well.
1452 *
1453 * @param cp peer to send the message to
1454 * @param env envelope with the message to send
1455 */
1456void
1457GCP_send_ooo (struct CadetPeer *cp,
1458 struct GNUNET_MQ_Envelope *env)
1459{
1460 LOG (GNUNET_ERROR_TYPE_DEBUG,
1461 "Sending message to %s out of management\n",
1462 GCP_2s (cp));
1463 if (NULL == cp->core_mq)
1464 {
1465 GNUNET_MQ_discard (env);
1466 return;
1467 }
1468 GNUNET_MQ_notify_sent (env,
1469 &mqm_send_done,
1470 cp);
1471 GNUNET_MQ_send (cp->core_mq,
1472 env);
1473}
1474
1475
1476
1477
1478/* end of gnunet-service-cadet-new_peer.c */
diff --git a/src/cadet/gnunet-service-cadet-new_peer.h b/src/cadet/gnunet-service-cadet-new_peer.h
deleted file mode 100644
index e1d6fc33a..000000000
--- a/src/cadet/gnunet-service-cadet-new_peer.h
+++ /dev/null
@@ -1,394 +0,0 @@
1
2/*
3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @file cadet/gnunet-service-cadet-new_peer.h
24 * @brief Information we track per peer.
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
27 */
28#ifndef GNUNET_SERVICE_CADET_PEER_H
29#define GNUNET_SERVICE_CADET_PEER_H
30
31#include "gnunet-service-cadet-new.h"
32#include "gnunet_hello_lib.h"
33
34
35/**
36 * Get the static string for a peer ID.
37 *
38 * @param peer Peer.
39 *
40 * @return Static string for it's ID.
41 */
42const char *
43GCP_2s (const struct CadetPeer *peer);
44
45
46/**
47 * Retrieve the CadetPeer stucture associated with the
48 * peer. Optionally create one and insert it in the appropriate
49 * structures if the peer is not known yet.
50 *
51 * @param peer_id Full identity of the peer.
52 * @param create #GNUNET_YES if a new peer should be created if unknown.
53 * #GNUNET_NO to return NULL if peer is unknown.
54 * @return Existing or newly created peer structure.
55 * NULL if unknown and not requested @a create
56 */
57struct CadetPeer *
58GCP_get (const struct GNUNET_PeerIdentity *peer_id,
59 int create);
60
61
62/**
63 * Calculate how desirable a path is for @a cp if
64 * @a cp is at offset @a off in the path.
65 *
66 * @param cp a peer reachable via a path
67 * @param off offset of @a cp in a path
68 * @return score how useful a path is to reach @a cp,
69 * positive scores mean path is more desirable
70 */
71double
72GCP_get_desirability_of_path (struct CadetPeer *cp,
73 unsigned int off);
74
75
76/**
77 * Obtain the peer identity for a `struct CadetPeer`.
78 *
79 * @param cp our peer handle
80 * @return the peer identity
81 */
82const struct GNUNET_PeerIdentity *
83GCP_get_id (struct CadetPeer *cp);
84
85
86/**
87 * Iterate over all known peers.
88 *
89 * @param iter Iterator.
90 * @param cls Closure for @c iter.
91 */
92void
93GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
94 void *cls);
95
96
97/**
98 * Count the number of known paths toward the peer.
99 *
100 * @param cp Peer to get path info.
101 * @return Number of known paths.
102 */
103unsigned int
104GCP_count_paths (const struct CadetPeer *cp);
105
106
107/**
108 * Drop all paths owned by this peer, and do not
109 * allow new ones to be added: We are shutting down.
110 *
111 * @param cp peer to drop paths to
112 */
113void
114GCP_drop_owned_paths (struct CadetPeer *cp);
115
116
117/**
118 * Peer path iterator.
119 *
120 * @param cls Closure.
121 * @param path Path itself
122 * @param off offset of the target peer in @a path
123 * @return #GNUNET_YES if should keep iterating.
124 * #GNUNET_NO otherwise.
125 */
126typedef int
127(*GCP_PathIterator) (void *cls,
128 struct CadetPeerPath *path,
129 unsigned int off);
130
131
132/**
133 * Iterate over the paths to a peer.
134 *
135 * @param cp Peer to get path info.
136 * @param callback Function to call for every path.
137 * @param callback_cls Closure for @a callback.
138 * @return Number of iterated paths.
139 */
140unsigned int
141GCP_iterate_paths (struct CadetPeer *cp,
142 GCP_PathIterator callback,
143 void *callback_cls);
144
145
146/**
147 * Iterate over the paths to @a peer where
148 * @a peer is at distance @a dist from us.
149 *
150 * @param cp Peer to get path info.
151 * @param dist desired distance of @a peer to us on the path
152 * @param callback Function to call for every path.
153 * @param callback_cls Closure for @a callback.
154 * @return Number of iterated paths.
155 */
156unsigned int
157GCP_iterate_paths_at (struct CadetPeer *cp,
158 unsigned int dist,
159 GCP_PathIterator callback,
160 void *callback_cls);
161
162
163/**
164 * Remove an entry from the DLL of all of the paths that this peer is on.
165 *
166 * @param cp peer to modify
167 * @param entry an entry on a path
168 * @param off offset of this peer on the path
169 */
170void
171GCP_path_entry_remove (struct CadetPeer *cp,
172 struct CadetPeerPathEntry *entry,
173 unsigned int off);
174
175
176/**
177 * Add an entry to the DLL of all of the paths that this peer is on.
178 *
179 * @param cp peer to modify
180 * @param entry an entry on a path
181 * @param off offset of this peer on the path
182 */
183void
184GCP_path_entry_add (struct CadetPeer *cp,
185 struct CadetPeerPathEntry *entry,
186 unsigned int off);
187
188
189/**
190 * Get the tunnel towards a peer.
191 *
192 * @param cp Peer to get from.
193 * @param create #GNUNET_YES to create a tunnel if we do not have one
194 * @return Tunnel towards peer.
195 */
196struct CadetTunnel *
197GCP_get_tunnel (struct CadetPeer *cp,
198 int create);
199
200
201/**
202 * The tunnel to the given peer no longer exists, remove it from our
203 * data structures, and possibly clean up the peer itself.
204 *
205 * @param cp the peer affected
206 * @param t the dead tunnel
207 */
208void
209GCP_drop_tunnel (struct CadetPeer *cp,
210 struct CadetTunnel *t);
211
212
213/**
214 * Try adding a @a path to this @a cp. If the peer already
215 * has plenty of paths, return NULL.
216 *
217 * @param cp peer to which the @a path leads to
218 * @param path a path looking for an owner; may not be fully initialized yet!
219 * @param off offset of @a cp in @a path
220 * @param force for attaching the path
221 * @return NULL if this peer does not care to become a new owner,
222 * otherwise the node in the peer's path heap for the @a path.
223 */
224struct GNUNET_CONTAINER_HeapNode *
225GCP_attach_path (struct CadetPeer *cp,
226 struct CadetPeerPath *path,
227 unsigned int off,
228 int force);
229
230
231/**
232 * This peer can no longer own @a path as the path
233 * has been extended and a peer further down the line
234 * is now the new owner.
235 *
236 * @param cp old owner of the @a path
237 * @param path path where the ownership is lost
238 * @param hn note in @a cp's path heap that must be deleted
239 */
240void
241GCP_detach_path (struct CadetPeer *cp,
242 struct CadetPeerPath *path,
243 struct GNUNET_CONTAINER_HeapNode *hn);
244
245
246/**
247 * Add a @a connection to this @a cp.
248 *
249 * @param cp peer via which the @a connection goes
250 * @param cc the connection to add
251 */
252void
253GCP_add_connection (struct CadetPeer *cp,
254 struct CadetConnection *cc);
255
256
257/**
258 * Remove a @a connection that went via this @a cp.
259 *
260 * @param cp peer via which the @a connection went
261 * @param cc the connection to remove
262 */
263void
264GCP_remove_connection (struct CadetPeer *cp,
265 struct CadetConnection *cc);
266
267
268/**
269 * We got a HELLO for a @a cp, remember it, and possibly
270 * trigger adequate actions (like trying to connect).
271 *
272 * @param cp the peer we got a HELLO for
273 * @param hello the HELLO to remember
274 */
275void
276GCP_set_hello (struct CadetPeer *cp,
277 const struct GNUNET_HELLO_Message *hello);
278
279
280/**
281 * Clean up all entries about all peers.
282 * Must only be called after all tunnels, CORE-connections and
283 * connections are down.
284 */
285void
286GCP_destroy_all_peers (void);
287
288
289/**
290 * Data structure used to track whom we have to notify about changes
291 * in our ability to transmit to a given peer.
292 *
293 * All queue managers will be given equal chance for sending messages
294 * to @a cp. This construct this guarantees fairness for access to @a
295 * cp among the different message queues. Each connection or route
296 * will have its respective message queue managers for each direction.
297 */
298struct GCP_MessageQueueManager;
299
300
301/**
302 * Function to call with updated message queue object.
303 *
304 * @param cls closure
305 * @param available #GNUNET_YES if sending is now possible,
306 * #GNUNET_NO if sending is no longer possible
307 * #GNUNET_SYSERR if sending is no longer possible
308 * and the last envelope was discarded
309 */
310typedef void
311(*GCP_MessageQueueNotificationCallback)(void *cls,
312 int available);
313
314
315/**
316 * Start message queue change notifications. Will create a new slot
317 * to manage the message queue to the given @a cp.
318 *
319 * @param cp peer to notify for
320 * @param cb function to call if mq becomes available or unavailable
321 * @param cb_cls closure for @a cb
322 * @return handle to cancel request
323 */
324struct GCP_MessageQueueManager *
325GCP_request_mq (struct CadetPeer *cp,
326 GCP_MessageQueueNotificationCallback cb,
327 void *cb_cls);
328
329
330/**
331 * Test if @a cp has a core-level connection
332 *
333 * @param cp peer to test
334 * @return #GNUNET_YES if @a cp has a core-level connection
335 */
336int
337GCP_has_core_connection (struct CadetPeer *cp);
338
339
340/**
341 * Send the message in @a env via a @a mqm. Must only be called at
342 * most once after the respective
343 * #GCP_MessageQueueNotificationCallback was called with `available`
344 * set to #GNUNET_YES, and not after the callback was called with
345 * `available` set to #GNUNET_NO or #GNUNET_SYSERR.
346 *
347 * @param mqm message queue manager for the transmission
348 * @param env envelope with the message to send; must NOT
349 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
350 */
351void
352GCP_send (struct GCP_MessageQueueManager *mqm,
353 struct GNUNET_MQ_Envelope *env);
354
355
356/**
357 * Send the message in @a env to @a cp, overriding queueing logic.
358 * This function should only be used to send error messages outside
359 * of flow and congestion control, similar to ICMP. Note that
360 * the envelope may be silently discarded as well.
361 *
362 * @param cp peer to send the message to
363 * @param env envelope with the message to send
364 */
365void
366GCP_send_ooo (struct CadetPeer *cp,
367 struct GNUNET_MQ_Envelope *env);
368
369
370/**
371 * Stops message queue change notifications and sends a last message.
372 * In practice, this is implemented by sending that @a last_env
373 * message immediately (if any), ignoring queue order.
374 *
375 * @param mqm handle matching request to cancel
376 * @param last_env final message to transmit, or NULL
377 */
378void
379GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
380 struct GNUNET_MQ_Envelope *last_env);
381
382
383/**
384 * Set the message queue to @a mq for peer @a cp and notify watchers.
385 *
386 * @param cp peer to modify
387 * @param mq message queue to set (can be NULL)
388 */
389void
390GCP_set_mq (struct CadetPeer *cp,
391 struct GNUNET_MQ_Handle *mq);
392
393
394#endif
diff --git a/src/cadet/gnunet-service-cadet.c b/src/cadet/gnunet-service-cadet.c
index 3a07f0ee5..a7e1fca47 100644
--- a/src/cadet/gnunet-service-cadet.c
+++ b/src/cadet/gnunet-service-cadet.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2001-2013 GNUnet e.V. 3 Copyright (C) 2001-2013, 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -22,38 +22,82 @@
22 * @file cadet/gnunet-service-cadet.c 22 * @file cadet/gnunet-service-cadet.c
23 * @brief GNUnet CADET service with encryption 23 * @brief GNUnet CADET service with encryption
24 * @author Bartlomiej Polot 24 * @author Bartlomiej Polot
25 * 25 * @author Christian Grothoff
26 * FIXME in progress:
27 * - rekey - reliability interaction
28 * - channel retransmit timing
29 *
30 * TODO:
31 * - relay corking down to core
32 * - set ttl relative to path length
33 * TODO END
34 * 26 *
35 * Dictionary: 27 * Dictionary:
36 * - peer: other cadet instance. If there is direct connection it's a neighbor. 28 * - peer: other cadet instance. If there is direct connection it's a neighbor.
37 * - tunnel: encrypted connection to a peer, neighbor or not.
38 * - channel: connection between two clients, on the same or different peers.
39 * have properties like reliability.
40 * - path: series of directly connected peer from one peer to another. 29 * - path: series of directly connected peer from one peer to another.
41 * - connection: path which is being used in a tunnel. 30 * - connection: path which is being used in a tunnel.
31 * - tunnel: encrypted connection to a peer, neighbor or not.
32 * - channel: logical link between two clients, on the same or different peers.
33 * have properties like reliability.
42 */ 34 */
43 35
44#include "platform.h" 36#include "platform.h"
45#include "gnunet_util_lib.h" 37#include "gnunet_util_lib.h"
46#include "cadet.h" 38#include "cadet.h"
47#include "gnunet_statistics_service.h" 39#include "gnunet_statistics_service.h"
48 40#include "gnunet-service-cadet.h"
49#include "gnunet-service-cadet_local.h"
50#include "gnunet-service-cadet_channel.h" 41#include "gnunet-service-cadet_channel.h"
51#include "gnunet-service-cadet_connection.h" 42#include "gnunet-service-cadet_connection.h"
52#include "gnunet-service-cadet_tunnel.h" 43#include "gnunet-service-cadet_core.h"
53#include "gnunet-service-cadet_dht.h" 44#include "gnunet-service-cadet_dht.h"
54#include "gnunet-service-cadet_peer.h"
55#include "gnunet-service-cadet_hello.h" 45#include "gnunet-service-cadet_hello.h"
46#include "gnunet-service-cadet_tunnels.h"
47#include "gnunet-service-cadet_peer.h"
48#include "gnunet-service-cadet_paths.h"
49
50#define LOG(level, ...) GNUNET_log (level,__VA_ARGS__)
51
52
53/**
54 * Struct containing information about a client of the service
55 */
56struct CadetClient
57{
58 /**
59 * Linked list next
60 */
61 struct CadetClient *next;
62
63 /**
64 * Linked list prev
65 */
66 struct CadetClient *prev;
67
68 /**
69 * Tunnels that belong to this client, indexed by local id,
70 * value is a `struct CadetChannel`.
71 */
72 struct GNUNET_CONTAINER_MultiHashMap32 *channels;
73
74 /**
75 * Handle to communicate with the client
76 */
77 struct GNUNET_MQ_Handle *mq;
78
79 /**
80 * Client handle.
81 */
82 struct GNUNET_SERVICE_Client *client;
83
84 /**
85 * Ports that this client has declared interest in.
86 * Indexed by port, contains *Client.
87 */
88 struct GNUNET_CONTAINER_MultiHashMap *ports;
56 89
90 /**
91 * Channel ID to use for the next incoming channel for this client.
92 * Wraps around (in theory).
93 */
94 struct GNUNET_CADET_ClientChannelNumber next_ccn;
95
96 /**
97 * ID of the client, mainly for debug messages. Purely internal to this file.
98 */
99 unsigned int id;
100};
57 101
58/******************************************************************************/ 102/******************************************************************************/
59/*********************** GLOBAL VARIABLES ****************************/ 103/*********************** GLOBAL VARIABLES ****************************/
@@ -62,37 +106,317 @@
62/****************************** Global variables ******************************/ 106/****************************** Global variables ******************************/
63 107
64/** 108/**
109 * Handle to our configuration.
110 */
111const struct GNUNET_CONFIGURATION_Handle *cfg;
112
113/**
65 * Handle to the statistics service. 114 * Handle to the statistics service.
66 */ 115 */
67struct GNUNET_STATISTICS_Handle *stats; 116struct GNUNET_STATISTICS_Handle *stats;
68 117
69/** 118/**
70 * Local peer own ID (memory efficient handle). 119 * Handle to communicate with ATS.
71 */ 120 */
72GNUNET_PEER_Id myid; 121struct GNUNET_ATS_ConnectivityHandle *ats_ch;
73 122
74/** 123/**
75 * Local peer own ID (full value). 124 * Local peer own ID.
76 */ 125 */
77struct GNUNET_PeerIdentity my_full_id; 126struct GNUNET_PeerIdentity my_full_id;
78 127
128/**
129 * Own private key.
130 */
131struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
79 132
80/** 133/**
81 * Signal that shutdown is happening: prevent recover measures. 134 * Signal that shutdown is happening: prevent recovery measures.
82 */ 135 */
83int shutting_down; 136int shutting_down;
84 137
85/*************************** Static global variables **************************/ 138/**
139 * DLL with all the clients, head.
140 */
141static struct CadetClient *clients_head;
86 142
87/** 143/**
88 * Own private key. 144 * DLL with all the clients, tail.
89 */ 145 */
90static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; 146static struct CadetClient *clients_tail;
91 147
148/**
149 * Next ID to assign to a client.
150 */
151static unsigned int next_client_id;
152
153/**
154 * All ports clients of this peer have opened.
155 */
156struct GNUNET_CONTAINER_MultiHashMap *open_ports;
157
158/**
159 * Map from ports to channels where the ports were closed at the
160 * time we got the inbound connection.
161 * Indexed by port, contains `struct CadetChannel`.
162 */
163struct GNUNET_CONTAINER_MultiHashMap *loose_channels;
164
165/**
166 * Map from PIDs to `struct CadetPeer` entries.
167 */
168struct GNUNET_CONTAINER_MultiPeerMap *peers;
169
170/**
171 * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier`
172 * hash codes to `struct CadetConnection` objects.
173 */
174struct GNUNET_CONTAINER_MultiShortmap *connections;
175
176/**
177 * How many messages are needed to trigger an AXOLOTL ratchet advance.
178 */
179unsigned long long ratchet_messages;
180
181/**
182 * How long until we trigger a ratched advance due to time.
183 */
184struct GNUNET_TIME_Relative ratchet_time;
185
186/**
187 * How frequently do we send KEEPALIVE messages on idle connections?
188 */
189struct GNUNET_TIME_Relative keepalive_period;
190
191/**
192 * Set to non-zero values to create random drops to test retransmissions.
193 */
194unsigned long long drop_percent;
195
196
197/**
198 * Send a message to a client.
199 *
200 * @param c client to get the message
201 * @param env envelope with the message
202 */
203void
204GSC_send_to_client (struct CadetClient *c,
205 struct GNUNET_MQ_Envelope *env)
206{
207 GNUNET_MQ_send (c->mq,
208 env);
209}
210
211
212/**
213 * Return identifier for a client as a string.
214 *
215 * @param c client to identify
216 * @return string for debugging
217 */
218const char *
219GSC_2s (struct CadetClient *c)
220{
221 static char buf[32];
222
223 GNUNET_snprintf (buf,
224 sizeof (buf),
225 "Client(%u)",
226 c->id);
227 return buf;
228}
229
230
231/**
232 * Lookup channel of client @a c by @a ccn.
233 *
234 * @param c client to look in
235 * @param ccn channel ID to look up
236 * @return NULL if no such channel exists
237 */
238static struct CadetChannel *
239lookup_channel (struct CadetClient *c,
240 struct GNUNET_CADET_ClientChannelNumber ccn)
241{
242 return GNUNET_CONTAINER_multihashmap32_get (c->channels,
243 ntohl (ccn.channel_of_client));
244}
245
246
247/**
248 * Obtain the next LID to use for incoming connections to
249 * the given client.
250 *
251 * @param c client handle
252 */
253static struct GNUNET_CADET_ClientChannelNumber
254client_get_next_ccn (struct CadetClient *c)
255{
256 struct GNUNET_CADET_ClientChannelNumber ccn = c->next_ccn;
257
258 /* increment until we have a free one... */
259 while (NULL !=
260 lookup_channel (c,
261 ccn))
262 {
263 ccn.channel_of_client
264 = htonl (1 + (ntohl (ccn.channel_of_client)));
265 if (ntohl (ccn.channel_of_client) >=
266 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
267 ccn.channel_of_client = htonl (0);
268 }
269 c->next_ccn.channel_of_client
270 = htonl (1 + (ntohl (ccn.channel_of_client)));
271 return ccn;
272}
273
274
275/**
276 * Bind incoming channel to this client, and notify client about
277 * incoming connection. Caller is responsible for notifying the other
278 * peer about our acceptance of the channel.
279 *
280 * @param c client to bind to
281 * @param ch channel to be bound
282 * @param dest peer that establishes the connection
283 * @param port port number
284 * @param options options
285 * @return local channel number assigned to the new client
286 */
287struct GNUNET_CADET_ClientChannelNumber
288GSC_bind (struct CadetClient *c,
289 struct CadetChannel *ch,
290 struct CadetPeer *dest,
291 const struct GNUNET_HashCode *port,
292 uint32_t options)
293{
294 struct GNUNET_MQ_Envelope *env;
295 struct GNUNET_CADET_LocalChannelCreateMessage *cm;
296 struct GNUNET_CADET_ClientChannelNumber ccn;
297
298 ccn = client_get_next_ccn (c);
299 GNUNET_assert (GNUNET_YES ==
300 GNUNET_CONTAINER_multihashmap32_put (c->channels,
301 ntohl (ccn.channel_of_client),
302 ch,
303 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
304 LOG (GNUNET_ERROR_TYPE_DEBUG,
305 "Accepting incoming %s from %s on open port %s (%u), assigning ccn %X\n",
306 GCCH_2s (ch),
307 GCP_2s (dest),
308 GNUNET_h2s (port),
309 (uint32_t) ntohl (options),
310 (uint32_t) ntohl (ccn.channel_of_client));
311 /* notify local client about incoming connection! */
312 env = GNUNET_MQ_msg (cm,
313 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
314 cm->ccn = ccn;
315 cm->port = *port;
316 cm->opt = htonl (options);
317 cm->peer = *GCP_get_id (dest);
318 GSC_send_to_client (c,
319 env);
320 return ccn;
321}
322
323
324/**
325 * Callback invoked on all peers to destroy all tunnels
326 * that may still exist.
327 *
328 * @param cls NULL
329 * @param pid identify of a peer
330 * @param value a `struct CadetPeer` that may still have a tunnel
331 * @return #GNUNET_OK (iterate over all entries)
332 */
333static int
334destroy_tunnels_now (void *cls,
335 const struct GNUNET_PeerIdentity *pid,
336 void *value)
337{
338 struct CadetPeer *cp = value;
339 struct CadetTunnel *t = GCP_get_tunnel (cp,
340 GNUNET_NO);
341
342 if (NULL != t)
343 GCT_destroy_tunnel_now (t);
344 return GNUNET_OK;
345}
346
347
348/**
349 * Callback invoked on all peers to destroy all tunnels
350 * that may still exist.
351 *
352 * @param cls NULL
353 * @param pid identify of a peer
354 * @param value a `struct CadetPeer` that may still have a tunnel
355 * @return #GNUNET_OK (iterate over all entries)
356 */
357static int
358destroy_paths_now (void *cls,
359 const struct GNUNET_PeerIdentity *pid,
360 void *value)
361{
362 struct CadetPeer *cp = value;
363
364 GCP_drop_owned_paths (cp);
365 return GNUNET_OK;
366}
367
368
369/**
370 * Shutdown everything once the clients have disconnected.
371 */
372static void
373shutdown_rest ()
374{
375 if (NULL != stats)
376 {
377 GNUNET_STATISTICS_destroy (stats,
378 GNUNET_NO);
379 stats = NULL;
380 }
381 if (NULL != open_ports)
382 {
383 GNUNET_CONTAINER_multihashmap_destroy (open_ports);
384 open_ports = NULL;
385 }
386 if (NULL != loose_channels)
387 {
388 GNUNET_CONTAINER_multihashmap_destroy (loose_channels);
389 loose_channels = NULL;
390 }
391 /* Destroy tunnels. Note that all channels must be destroyed first! */
392 GCP_iterate_all (&destroy_tunnels_now,
393 NULL);
394 /* All tunnels, channels, connections and CORE must be down before this point. */
395 GCP_iterate_all (&destroy_paths_now,
396 NULL);
397 /* All paths, tunnels, channels, connections and CORE must be down before this point. */
398 GCP_destroy_all_peers ();
399 if (NULL != peers)
400 {
401 GNUNET_CONTAINER_multipeermap_destroy (peers);
402 peers = NULL;
403 }
404 if (NULL != connections)
405 {
406 GNUNET_CONTAINER_multishortmap_destroy (connections);
407 connections = NULL;
408 }
409 if (NULL != ats_ch)
410 {
411 GNUNET_ATS_connectivity_done (ats_ch);
412 ats_ch = NULL;
413 }
414 GCD_shutdown ();
415 GCH_shutdown ();
416 GNUNET_free_non_null (my_private_key);
417 my_private_key = NULL;
418}
92 419
93/******************************************************************************/
94/************************ MAIN FUNCTIONS ****************************/
95/******************************************************************************/
96 420
97/** 421/**
98 * Task run during shutdown. 422 * Task run during shutdown.
@@ -102,83 +426,1071 @@ static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
102static void 426static void
103shutdown_task (void *cls) 427shutdown_task (void *cls)
104{ 428{
105 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n"); 429 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
106 430 "Shutting down\n");
107 shutting_down = GNUNET_YES; 431 shutting_down = GNUNET_YES;
432 GCO_shutdown ();
433 if (NULL == clients_head)
434 shutdown_rest ();
435}
108 436
109 GML_shutdown ();
110 GCH_shutdown ();
111 GCC_shutdown ();
112 GCT_shutdown ();
113 GCD_shutdown ();
114 GCP_shutdown ();
115 437
116 GNUNET_STATISTICS_destroy (stats, GNUNET_NO); 438/**
117 stats = NULL; 439 * We had a remote connection @a value to port @a port before
118 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n"); 440 * client @a cls opened port @a port. Bind them now.
441 *
442 * @param cls the `struct CadetClient`
443 * @param port the port
444 * @param value the `struct CadetChannel`
445 * @return #GNUNET_YES (iterate over all such channels)
446 */
447static int
448bind_loose_channel (void *cls,
449 const struct GNUNET_HashCode *port,
450 void *value)
451{
452 struct CadetClient *c = cls;
453 struct CadetChannel *ch = value;
454
455 GCCH_bind (ch,
456 c);
457 GNUNET_assert (GNUNET_YES ==
458 GNUNET_CONTAINER_multihashmap_remove (loose_channels,
459 port,
460 value));
461 return GNUNET_YES;
119} 462}
120 463
121 464
122/** 465/**
123 * Process cadet requests. 466 * Handle port open request. Creates a mapping from the
467 * port to the respective client and checks whether we have
468 * loose channels trying to bind to the port. If so, those
469 * are bound.
124 * 470 *
125 * @param cls closure 471 * @param cls Identification of the client.
126 * @param server the initialized server 472 * @param pmsg The actual message.
127 * @param c configuration to use
128 */ 473 */
129static void 474static void
130run (void *cls, struct GNUNET_SERVER_Handle *server, 475handle_port_open (void *cls,
131 const struct GNUNET_CONFIGURATION_Handle *c) 476 const struct GNUNET_CADET_PortMessage *pmsg)
132{ 477{
133 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n"); 478 struct CadetClient *c = cls;
134 479
135 stats = GNUNET_STATISTICS_create ("cadet", c); 480 LOG (GNUNET_ERROR_TYPE_DEBUG,
481 "Open port %s requested by %s\n",
482 GNUNET_h2s (&pmsg->port),
483 GSC_2s (c));
484 if (NULL == c->ports)
485 c->ports = GNUNET_CONTAINER_multihashmap_create (4,
486 GNUNET_NO);
487 if (GNUNET_OK !=
488 GNUNET_CONTAINER_multihashmap_put (c->ports,
489 &pmsg->port,
490 c,
491 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
492 {
493 GNUNET_break (0);
494 GNUNET_SERVICE_client_drop (c->client);
495 return;
496 }
497 (void) GNUNET_CONTAINER_multihashmap_put (open_ports,
498 &pmsg->port,
499 c,
500 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
501 GNUNET_CONTAINER_multihashmap_get_multiple (loose_channels,
502 &pmsg->port,
503 &bind_loose_channel,
504 c);
505 GNUNET_SERVICE_client_continue (c->client);
506}
136 507
137 /* Scheduled the task to clean up when shutdown is called */
138 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
139 NULL);
140 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "reading key\n");
141 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
142 GNUNET_assert (NULL != my_private_key);
143 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_full_id.public_key);
144 myid = GNUNET_PEER_intern (&my_full_id);
145 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
146 "STARTING SERVICE (cadet) for peer [%s]\n",
147 GNUNET_i2s (&my_full_id));
148 508
149 GML_init (server); /* Local clients */ 509/**
150 GCH_init (c); /* Hellos */ 510 * Handler for port close requests. Marks this port as closed
151 GCC_init (c); /* Connections */ 511 * (unless of course we have another client with the same port
152 GCP_init (c); /* Peers */ 512 * open). Note that existing channels accepted on the port are
153 GCD_init (c); /* DHT */ 513 * not affected.
154 GCT_init (c, my_private_key); /* Tunnels */ 514 *
515 * @param cls Identification of the client.
516 * @param pmsg The actual message.
517 */
518static void
519handle_port_close (void *cls,
520 const struct GNUNET_CADET_PortMessage *pmsg)
521{
522 struct CadetClient *c = cls;
155 523
156 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cadet service running\n"); 524 LOG (GNUNET_ERROR_TYPE_DEBUG,
525 "Closing port %s as requested by %s\n",
526 GNUNET_h2s (&pmsg->port),
527 GSC_2s (c));
528 if (GNUNET_YES !=
529 GNUNET_CONTAINER_multihashmap_remove (c->ports,
530 &pmsg->port,
531 c))
532 {
533 GNUNET_break (0);
534 GNUNET_SERVICE_client_drop (c->client);
535 return;
536 }
537 GNUNET_assert (GNUNET_YES ==
538 GNUNET_CONTAINER_multihashmap_remove (open_ports,
539 &pmsg->port,
540 c));
541 GNUNET_SERVICE_client_continue (c->client);
157} 542}
158 543
159 544
160/** 545/**
161 * The main function for the cadet service. 546 * Handler for requests for us creating a new channel to another peer and port.
162 * 547 *
163 * @param argc number of arguments from the command line 548 * @param cls Identification of the client.
164 * @param argv command line arguments 549 * @param tcm The actual message.
165 * @return 0 ok, 1 on error
166 */ 550 */
167int 551static void
168main (int argc, char *const *argv) 552handle_channel_create (void *cls,
553 const struct GNUNET_CADET_LocalChannelCreateMessage *tcm)
169{ 554{
170 int r; 555 struct CadetClient *c = cls;
556 struct CadetChannel *ch;
171 557
172 shutting_down = GNUNET_NO; 558 if (ntohl (tcm->ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
173 r = GNUNET_SERVICE_run (argc, argv, "cadet", GNUNET_SERVICE_OPTION_NONE, &run, 559 {
174 NULL); 560 /* Channel ID not in allowed range. */
175 GNUNET_free (my_private_key); 561 GNUNET_break (0);
562 GNUNET_SERVICE_client_drop (c->client);
563 return;
564 }
565 ch = lookup_channel (c,
566 tcm->ccn);
567 if (NULL != ch)
568 {
569 /* Channel ID already in use. Not allowed. */
570 GNUNET_break (0);
571 GNUNET_SERVICE_client_drop (c->client);
572 return;
573 }
574 LOG (GNUNET_ERROR_TYPE_DEBUG,
575 "New channel to %s at port %s requested by %s\n",
576 GNUNET_i2s (&tcm->peer),
577 GNUNET_h2s (&tcm->port),
578 GSC_2s (c));
176 579
177 if (GNUNET_OK != r) 580 /* Create channel */
581 ch = GCCH_channel_local_new (c,
582 tcm->ccn,
583 GCP_get (&tcm->peer,
584 GNUNET_YES),
585 &tcm->port,
586 ntohl (tcm->opt));
587 if (NULL == ch)
178 { 588 {
179 FPRINTF (stderr, "GNUNET_SERVICE_run for CADET has failed!\n"); 589 GNUNET_break (0);
180 return 1; 590 GNUNET_SERVICE_client_drop (c->client);
591 return;
181 } 592 }
593 GNUNET_assert (GNUNET_YES ==
594 GNUNET_CONTAINER_multihashmap32_put (c->channels,
595 ntohl (tcm->ccn.channel_of_client),
596 ch,
597 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
182 598
183 return 0; 599 GNUNET_SERVICE_client_continue (c->client);
184} 600}
601
602
603/**
604 * Handler for requests of destroying an existing channel.
605 *
606 * @param cls client identification of the client
607 * @param msg the actual message
608 */
609static void
610handle_channel_destroy (void *cls,
611 const struct GNUNET_CADET_LocalChannelDestroyMessage *msg)
612{
613 struct CadetClient *c = cls;
614 struct CadetChannel *ch;
615
616 ch = lookup_channel (c,
617 msg->ccn);
618 if (NULL == ch)
619 {
620 /* Client attempted to destroy unknown channel.
621 Can happen if the other side went down at the same time.*/
622 LOG (GNUNET_ERROR_TYPE_DEBUG,
623 "%s tried to destroy unknown channel %X\n",
624 GSC_2s(c),
625 (uint32_t) ntohl (msg->ccn.channel_of_client));
626 return;
627 }
628 LOG (GNUNET_ERROR_TYPE_DEBUG,
629 "%s is destroying %s\n",
630 GSC_2s(c),
631 GCCH_2s (ch));
632 GNUNET_assert (GNUNET_YES ==
633 GNUNET_CONTAINER_multihashmap32_remove (c->channels,
634 ntohl (msg->ccn.channel_of_client),
635 ch));
636 GCCH_channel_local_destroy (ch,
637 c,
638 msg->ccn);
639 GNUNET_SERVICE_client_continue (c->client);
640}
641
642
643/**
644 * Check for client traffic data message is well-formed.
645 *
646 * @param cls identification of the client
647 * @param msg the actual message
648 * @return #GNUNET_OK if @a msg is OK, #GNUNET_SYSERR if not
649 */
650static int
651check_local_data (void *cls,
652 const struct GNUNET_CADET_LocalData *msg)
653{
654 size_t payload_size;
655 size_t payload_claimed_size;
656 const char *buf;
657 struct GNUNET_MessageHeader pa;
658
659 /* FIXME: what is the format we shall allow for @a msg?
660 ONE payload item or multiple? Seems current cadet_api
661 at least in theory allows more than one. Next-gen
662 cadet_api will likely no more, so we could then
663 simplify this mess again. */
664 /* Sanity check for message size */
665 payload_size = ntohs (msg->header.size) - sizeof (*msg);
666 buf = (const char *) &msg[1];
667 while (payload_size >= sizeof (struct GNUNET_MessageHeader))
668 {
669 /* need to memcpy() for alignment */
670 GNUNET_memcpy (&pa,
671 buf,
672 sizeof (pa));
673 payload_claimed_size = ntohs (pa.size);
674 if ( (payload_size < payload_claimed_size) ||
675 (payload_claimed_size < sizeof (struct GNUNET_MessageHeader)) ||
676 (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < payload_claimed_size) )
677 {
678 GNUNET_break (0);
679 LOG (GNUNET_ERROR_TYPE_DEBUG,
680 "Local data of %u total size had sub-message %u at %u with %u bytes\n",
681 ntohs (msg->header.size),
682 ntohs (pa.type),
683 (unsigned int) (buf - (const char *) &msg[1]),
684 (unsigned int) payload_claimed_size);
685 return GNUNET_SYSERR;
686 }
687 payload_size -= payload_claimed_size;
688 buf += payload_claimed_size;
689 }
690 if (0 != payload_size)
691 {
692 GNUNET_break_op (0);
693 return GNUNET_SYSERR;
694 }
695 return GNUNET_OK;
696}
697
698
699/**
700 * Handler for client payload traffic to be send on a channel to
701 * another peer.
702 *
703 * @param cls identification of the client
704 * @param msg the actual message
705 */
706static void
707handle_local_data (void *cls,
708 const struct GNUNET_CADET_LocalData *msg)
709{
710 struct CadetClient *c = cls;
711 struct CadetChannel *ch;
712 size_t payload_size;
713 const char *buf;
714
715 ch = lookup_channel (c,
716 msg->ccn);
717 if (NULL == ch)
718 {
719 /* Channel does not exist (anymore) */
720 LOG (GNUNET_ERROR_TYPE_WARNING,
721 "Dropping payload for channel %u from client (channel unknown, other endpoint may have disconnected)\n",
722 (unsigned int) ntohl (msg->ccn.channel_of_client));
723 GNUNET_SERVICE_client_continue (c->client);
724 return;
725 }
726 payload_size = ntohs (msg->header.size) - sizeof (*msg);
727 GNUNET_STATISTICS_update (stats,
728 "# payload received from clients",
729 payload_size,
730 GNUNET_NO);
731 buf = (const char *) &msg[1];
732 LOG (GNUNET_ERROR_TYPE_DEBUG,
733 "Received %u bytes payload from %s for %s\n",
734 (unsigned int) payload_size,
735 GSC_2s (c),
736 GCCH_2s (ch));
737 if (GNUNET_OK !=
738 GCCH_handle_local_data (ch,
739 msg->ccn,
740 buf,
741 payload_size))
742 {
743 GNUNET_SERVICE_client_drop (c->client);
744 return;
745 }
746 GNUNET_SERVICE_client_continue (c->client);
747}
748
749
750/**
751 * Handler for client's ACKs for payload traffic.
752 *
753 * @param cls identification of the client.
754 * @param msg The actual message.
755 */
756static void
757handle_local_ack (void *cls,
758 const struct GNUNET_CADET_LocalAck *msg)
759{
760 struct CadetClient *c = cls;
761 struct CadetChannel *ch;
762
763 ch = lookup_channel (c,
764 msg->ccn);
765 if (NULL == ch)
766 {
767 /* Channel does not exist (anymore) */
768 LOG (GNUNET_ERROR_TYPE_WARNING,
769 "Ignoring local ACK for channel %u from client (channel unknown, other endpoint may have disconnected)\n",
770 (unsigned int) ntohl (msg->ccn.channel_of_client));
771 GNUNET_SERVICE_client_continue (c->client);
772 return;
773 }
774 LOG (GNUNET_ERROR_TYPE_DEBUG,
775 "Got a local ACK from %s for %s\n",
776 GSC_2s(c),
777 GCCH_2s (ch));
778 GCCH_handle_local_ack (ch,
779 msg->ccn);
780 GNUNET_SERVICE_client_continue (c->client);
781}
782
783
784/**
785 * Iterator over all peers to send a monitoring client info about each peer.
786 *
787 * @param cls Closure ().
788 * @param peer Peer ID (tunnel remote peer).
789 * @param value Peer info.
790 * @return #GNUNET_YES, to keep iterating.
791 */
792static int
793get_all_peers_iterator (void *cls,
794 const struct GNUNET_PeerIdentity *peer,
795 void *value)
796{
797 struct CadetClient *c = cls;
798 struct CadetPeer *p = value;
799 struct GNUNET_MQ_Envelope *env;
800 struct GNUNET_CADET_LocalInfoPeer *msg;
801
802 env = GNUNET_MQ_msg (msg,
803 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
804 msg->destination = *peer;
805 msg->paths = htons (GCP_count_paths (p));
806 msg->tunnel = htons (NULL != GCP_get_tunnel (p,
807 GNUNET_NO));
808 GNUNET_MQ_send (c->mq,
809 env);
810 return GNUNET_YES;
811}
812
813
814/**
815 * Handler for client's INFO PEERS request.
816 *
817 * @param cls Identification of the client.
818 * @param message The actual message.
819 */
820static void
821handle_get_peers (void *cls,
822 const struct GNUNET_MessageHeader *message)
823{
824 struct CadetClient *c = cls;
825 struct GNUNET_MQ_Envelope *env;
826 struct GNUNET_MessageHeader *reply;
827
828 GCP_iterate_all (&get_all_peers_iterator,
829 c);
830 env = GNUNET_MQ_msg (reply,
831 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
832 GNUNET_MQ_send (c->mq,
833 env);
834 GNUNET_SERVICE_client_continue (c->client);
835}
836
837
838/**
839 * Iterator over all paths of a peer to build an InfoPeer message.
840 * Message contains blocks of peers, first not included.
841 *
842 * @param cls message queue for transmission
843 * @param path Path itself
844 * @param off offset of the peer on @a path
845 * @return #GNUNET_YES if should keep iterating.
846 * #GNUNET_NO otherwise.
847 */
848static int
849path_info_iterator (void *cls,
850 struct CadetPeerPath *path,
851 unsigned int off)
852{
853 struct GNUNET_MQ_Handle *mq = cls;
854 struct GNUNET_MQ_Envelope *env;
855 struct GNUNET_MessageHeader *resp;
856 struct GNUNET_PeerIdentity *id;
857 uint16_t path_size;
858 unsigned int i;
859 unsigned int path_length;
860
861 path_length = GCPP_get_length (path);
862 path_size = sizeof (struct GNUNET_PeerIdentity) * (path_length - 1);
863 if (sizeof (*resp) + path_size > UINT16_MAX)
864 {
865 LOG (GNUNET_ERROR_TYPE_WARNING,
866 "Path of %u entries is too long for info message\n",
867 path_length);
868 return GNUNET_YES;
869 }
870 env = GNUNET_MQ_msg_extra (resp,
871 path_size,
872 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER);
873 id = (struct GNUNET_PeerIdentity *) &resp[1];
874
875 /* Don't copy first peer. First peer is always the local one. Last
876 * peer is always the destination (leave as 0, EOL).
877 */
878 for (i = 0; i < off; i++)
879 id[i] = *GCP_get_id (GCPP_get_peer_at_offset (path,
880 i + 1));
881 GNUNET_MQ_send (mq,
882 env);
883 return GNUNET_YES;
884}
885
886
887/**
888 * Handler for client's SHOW_PEER request.
889 *
890 * @param cls Identification of the client.
891 * @param msg The actual message.
892 */
893static void
894handle_show_peer (void *cls,
895 const struct GNUNET_CADET_LocalInfo *msg)
896{
897 struct CadetClient *c = cls;
898 struct CadetPeer *p;
899 struct GNUNET_MQ_Envelope *env;
900 struct GNUNET_MessageHeader *resp;
901
902 p = GCP_get (&msg->peer,
903 GNUNET_NO);
904 if (NULL != p)
905 GCP_iterate_paths (p,
906 &path_info_iterator,
907 c->mq);
908 /* Send message with 0/0 to indicate the end */
909 env = GNUNET_MQ_msg (resp,
910 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER_END);
911 GNUNET_MQ_send (c->mq,
912 env);
913 GNUNET_SERVICE_client_continue (c->client);
914}
915
916
917/**
918 * Iterator over all tunnels to send a monitoring client info about each tunnel.
919 *
920 * @param cls Closure ().
921 * @param peer Peer ID (tunnel remote peer).
922 * @param value a `struct CadetPeer`
923 * @return #GNUNET_YES, to keep iterating.
924 */
925static int
926get_all_tunnels_iterator (void *cls,
927 const struct GNUNET_PeerIdentity *peer,
928 void *value)
929{
930 struct CadetClient *c = cls;
931 struct CadetPeer *p = value;
932 struct GNUNET_MQ_Envelope *env;
933 struct GNUNET_CADET_LocalInfoTunnel *msg;
934 struct CadetTunnel *t;
935
936 t = GCP_get_tunnel (p,
937 GNUNET_NO);
938 if (NULL == t)
939 return GNUNET_YES;
940 env = GNUNET_MQ_msg (msg,
941 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
942 msg->destination = *peer;
943 msg->channels = htonl (GCT_count_channels (t));
944 msg->connections = htonl (GCT_count_any_connections (t));
945 msg->cstate = htons (0);
946 msg->estate = htons ((uint16_t) GCT_get_estate (t));
947 GNUNET_MQ_send (c->mq,
948 env);
949 return GNUNET_YES;
950}
951
952
953/**
954 * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS request.
955 *
956 * @param cls client Identification of the client.
957 * @param message The actual message.
958 */
959static void
960handle_info_tunnels (void *cls,
961 const struct GNUNET_MessageHeader *message)
962{
963 struct CadetClient *c = cls;
964 struct GNUNET_MQ_Envelope *env;
965 struct GNUNET_MessageHeader *reply;
966
967 GCP_iterate_all (&get_all_tunnels_iterator,
968 c);
969 env = GNUNET_MQ_msg (reply,
970 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
971 GNUNET_MQ_send (c->mq,
972 env);
973 GNUNET_SERVICE_client_continue (c->client);
974}
975
976
977/**
978 * Update the message with information about the connection.
979 *
980 * @param cls a `struct GNUNET_CADET_LocalInfoTunnel` message to update
981 * @param ct a connection about which we should store information in @a cls
982 */
983static void
984iter_connection (void *cls,
985 struct CadetTConnection *ct)
986{
987 struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
988 struct CadetConnection *cc = ct->cc;
989 struct GNUNET_CADET_ConnectionTunnelIdentifier *h;
990
991 h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
992 h[msg->connections++] = *(GCC_get_id (cc));
993}
994
995
996/**
997 * Update the message with information about the channel.
998 *
999 * @param cls a `struct GNUNET_CADET_LocalInfoTunnel` message to update
1000 * @param ch a channel about which we should store information in @a cls
1001 */
1002static void
1003iter_channel (void *cls,
1004 struct CadetChannel *ch)
1005{
1006 struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
1007 struct GNUNET_CADET_ConnectionTunnelIdentifier *h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
1008 struct GNUNET_CADET_ChannelTunnelNumber *chn
1009 = (struct GNUNET_CADET_ChannelTunnelNumber *) &h[msg->connections];
1010
1011 chn[msg->channels++] = GCCH_get_id (ch);
1012}
1013
1014
1015/**
1016 * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL request.
1017 *
1018 * @param cls Identification of the client.
1019 * @param msg The actual message.
1020 */
1021static void
1022handle_info_tunnel (void *cls,
1023 const struct GNUNET_CADET_LocalInfo *msg)
1024{
1025 struct CadetClient *c = cls;
1026 struct GNUNET_MQ_Envelope *env;
1027 struct GNUNET_CADET_LocalInfoTunnel *resp;
1028 struct CadetTunnel *t;
1029 struct CadetPeer *p;
1030 unsigned int ch_n;
1031 unsigned int c_n;
1032
1033 p = GCP_get (&msg->peer,
1034 GNUNET_NO);
1035 t = GCP_get_tunnel (p,
1036 GNUNET_NO);
1037 if (NULL == t)
1038 {
1039 /* We don't know the tunnel */
1040 struct GNUNET_MQ_Envelope *env;
1041 struct GNUNET_CADET_LocalInfoTunnel *warn;
1042
1043 LOG (GNUNET_ERROR_TYPE_INFO,
1044 "Tunnel to %s unknown\n",
1045 GNUNET_i2s_full (&msg->peer));
1046 env = GNUNET_MQ_msg (warn,
1047 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
1048 warn->destination = msg->peer;
1049 GNUNET_MQ_send (c->mq,
1050 env);
1051 GNUNET_SERVICE_client_continue (c->client);
1052 return;
1053 }
1054
1055 /* Initialize context */
1056 ch_n = GCT_count_channels (t);
1057 c_n = GCT_count_any_connections (t);
1058 env = GNUNET_MQ_msg_extra (resp,
1059 c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier) +
1060 ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber),
1061 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
1062 resp->destination = msg->peer;
1063 /* Do not reorder! #iter_channel needs counters in HBO! */
1064 GCT_iterate_connections (t,
1065 &iter_connection,
1066 resp);
1067 GCT_iterate_channels (t,
1068 &iter_channel,
1069 resp);
1070 resp->connections = htonl (resp->connections);
1071 resp->channels = htonl (resp->channels);
1072 resp->cstate = htons (0);
1073 resp->estate = htons (GCT_get_estate (t));
1074 GNUNET_MQ_send (c->mq,
1075 env);
1076 GNUNET_SERVICE_client_continue (c->client);
1077}
1078
1079
1080/**
1081 * Iterator over all peers to dump info for each peer.
1082 *
1083 * @param cls Closure (unused).
1084 * @param peer Peer ID (tunnel remote peer).
1085 * @param value Peer info.
1086 *
1087 * @return #GNUNET_YES, to keep iterating.
1088 */
1089static int
1090show_peer_iterator (void *cls,
1091 const struct GNUNET_PeerIdentity *peer,
1092 void *value)
1093{
1094 struct CadetPeer *p = value;
1095 struct CadetTunnel *t;
1096
1097 t = GCP_get_tunnel (p,
1098 GNUNET_NO);
1099 if (NULL != t)
1100 GCT_debug (t,
1101 GNUNET_ERROR_TYPE_ERROR);
1102 LOG (GNUNET_ERROR_TYPE_ERROR, "\n");
1103 return GNUNET_YES;
1104}
1105
1106
1107/**
1108 * Handler for client's INFO_DUMP request.
1109 *
1110 * @param cls Identification of the client.
1111 * @param message The actual message.
1112 */
1113static void
1114handle_info_dump (void *cls,
1115 const struct GNUNET_MessageHeader *message)
1116{
1117 struct CadetClient *c = cls;
1118
1119 LOG (GNUNET_ERROR_TYPE_INFO,
1120 "Received dump info request from client %u\n",
1121 c->id);
1122
1123 LOG (GNUNET_ERROR_TYPE_ERROR,
1124 "*************************** DUMP START ***************************\n");
1125 for (struct CadetClient *ci = clients_head;
1126 NULL != ci;
1127 ci = ci->next)
1128 {
1129 LOG (GNUNET_ERROR_TYPE_ERROR,
1130 "Client %u (%p), handle: %p, ports: %u, channels: %u\n",
1131 ci->id,
1132 ci,
1133 ci->client,
1134 (NULL != c->ports)
1135 ? GNUNET_CONTAINER_multihashmap_size (ci->ports)
1136 : 0,
1137 GNUNET_CONTAINER_multihashmap32_size (ci->channels));
1138 }
1139 LOG (GNUNET_ERROR_TYPE_ERROR, "***************************\n");
1140 GCP_iterate_all (&show_peer_iterator,
1141 NULL);
1142
1143 LOG (GNUNET_ERROR_TYPE_ERROR,
1144 "**************************** DUMP END ****************************\n");
1145
1146 GNUNET_SERVICE_client_continue (c->client);
1147}
1148
1149
1150
1151/**
1152 * Callback called when a client connects to the service.
1153 *
1154 * @param cls closure for the service
1155 * @param client the new client that connected to the service
1156 * @param mq the message queue used to send messages to the client
1157 * @return @a c
1158 */
1159static void *
1160client_connect_cb (void *cls,
1161 struct GNUNET_SERVICE_Client *client,
1162 struct GNUNET_MQ_Handle *mq)
1163{
1164 struct CadetClient *c;
1165
1166 c = GNUNET_new (struct CadetClient);
1167 c->client = client;
1168 c->mq = mq;
1169 c->id = next_client_id++; /* overflow not important: just for debug */
1170 c->channels
1171 = GNUNET_CONTAINER_multihashmap32_create (32);
1172 GNUNET_CONTAINER_DLL_insert (clients_head,
1173 clients_tail,
1174 c);
1175 GNUNET_STATISTICS_update (stats,
1176 "# clients",
1177 +1,
1178 GNUNET_NO);
1179 LOG (GNUNET_ERROR_TYPE_DEBUG,
1180 "%s connected\n",
1181 GSC_2s (c));
1182 return c;
1183}
1184
1185
1186/**
1187 * A channel was destroyed by the other peer. Tell our client.
1188 *
1189 * @param c client that lost a channel
1190 * @param ccn channel identification number for the client
1191 * @param ch the channel object
1192 */
1193void
1194GSC_handle_remote_channel_destroy (struct CadetClient *c,
1195 struct GNUNET_CADET_ClientChannelNumber ccn,
1196 struct CadetChannel *ch)
1197{
1198 struct GNUNET_MQ_Envelope *env;
1199 struct GNUNET_CADET_LocalChannelDestroyMessage *tdm;
1200
1201 env = GNUNET_MQ_msg (tdm,
1202 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
1203 tdm->ccn = ccn;
1204 GSC_send_to_client (c,
1205 env);
1206 GNUNET_assert (GNUNET_YES ==
1207 GNUNET_CONTAINER_multihashmap32_remove (c->channels,
1208 ntohl (ccn.channel_of_client),
1209 ch));
1210}
1211
1212
1213/**
1214 * A client that created a loose channel that was not bound to a port
1215 * disconnected, drop it from the #loose_channels list.
1216 *
1217 * @param port the port the channel was trying to bind to
1218 * @param ch the channel that was lost
1219 */
1220void
1221GSC_drop_loose_channel (const struct GNUNET_HashCode *port,
1222 struct CadetChannel *ch)
1223{
1224 GNUNET_assert (GNUNET_YES ==
1225 GNUNET_CONTAINER_multihashmap_remove (loose_channels,
1226 port,
1227 ch));
1228}
1229
1230
1231/**
1232 * Iterator for deleting each channel whose client endpoint disconnected.
1233 *
1234 * @param cls Closure (client that has disconnected).
1235 * @param key The local channel id in host byte order
1236 * @param value The value stored at the key (channel to destroy).
1237 * @return #GNUNET_OK, keep iterating.
1238 */
1239static int
1240channel_destroy_iterator (void *cls,
1241 uint32_t key,
1242 void *value)
1243{
1244 struct CadetClient *c = cls;
1245 struct GNUNET_CADET_ClientChannelNumber ccn;
1246 struct CadetChannel *ch = value;
1247
1248 LOG (GNUNET_ERROR_TYPE_DEBUG,
1249 "Destroying %s, due to %s disconnecting.\n",
1250 GCCH_2s (ch),
1251 GSC_2s (c));
1252 ccn.channel_of_client = htonl (key);
1253 GCCH_channel_local_destroy (ch,
1254 c,
1255 ccn);
1256 GNUNET_assert (GNUNET_YES ==
1257 GNUNET_CONTAINER_multihashmap32_remove (c->channels,
1258 key,
1259 ch));
1260 return GNUNET_OK;
1261}
1262
1263
1264/**
1265 * Remove client's ports from the global hashmap on disconnect.
1266 *
1267 * @param cls Closure (unused).
1268 * @param key the port.
1269 * @param value the `struct CadetClient` to remove
1270 * @return #GNUNET_OK, keep iterating.
1271 */
1272static int
1273client_release_ports (void *cls,
1274 const struct GNUNET_HashCode *key,
1275 void *value)
1276{
1277 struct CadetClient *c = value;
1278
1279 LOG (GNUNET_ERROR_TYPE_DEBUG,
1280 "Closing port %s due to %s disconnect.\n",
1281 GNUNET_h2s (key),
1282 GSC_2s (c));
1283 GNUNET_assert (GNUNET_YES ==
1284 GNUNET_CONTAINER_multihashmap_remove (open_ports,
1285 key,
1286 value));
1287 GNUNET_assert (GNUNET_YES ==
1288 GNUNET_CONTAINER_multihashmap_remove (c->ports,
1289 key,
1290 value));
1291 return GNUNET_OK;
1292}
1293
1294
1295/**
1296 * Callback called when a client disconnected from the service
1297 *
1298 * @param cls closure for the service
1299 * @param client the client that disconnected
1300 * @param internal_cls should be equal to @a c
1301 */
1302static void
1303client_disconnect_cb (void *cls,
1304 struct GNUNET_SERVICE_Client *client,
1305 void *internal_cls)
1306{
1307 struct CadetClient *c = internal_cls;
1308
1309 GNUNET_assert (c->client == client);
1310 LOG (GNUNET_ERROR_TYPE_DEBUG,
1311 "%s is disconnecting.\n",
1312 GSC_2s (c));
1313 if (NULL != c->channels)
1314 {
1315 GNUNET_CONTAINER_multihashmap32_iterate (c->channels,
1316 &channel_destroy_iterator,
1317 c);
1318 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->channels));
1319 GNUNET_CONTAINER_multihashmap32_destroy (c->channels);
1320 }
1321 if (NULL != c->ports)
1322 {
1323 GNUNET_CONTAINER_multihashmap_iterate (c->ports,
1324 &client_release_ports,
1325 c);
1326 GNUNET_CONTAINER_multihashmap_destroy (c->ports);
1327 }
1328 GNUNET_CONTAINER_DLL_remove (clients_head,
1329 clients_tail,
1330 c);
1331 GNUNET_STATISTICS_update (stats,
1332 "# clients",
1333 -1,
1334 GNUNET_NO);
1335 GNUNET_free (c);
1336 if ( (NULL == clients_head) &&
1337 (GNUNET_YES == shutting_down) )
1338 shutdown_rest ();
1339}
1340
1341
1342/**
1343 * Setup CADET internals.
1344 *
1345 * @param cls closure
1346 * @param server the initialized server
1347 * @param c configuration to use
1348 */
1349static void
1350run (void *cls,
1351 const struct GNUNET_CONFIGURATION_Handle *c,
1352 struct GNUNET_SERVICE_Handle *service)
1353{
1354 cfg = c;
1355 if (GNUNET_OK !=
1356 GNUNET_CONFIGURATION_get_value_number (c,
1357 "CADET",
1358 "RATCHET_MESSAGES",
1359 &ratchet_messages))
1360 {
1361 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1362 "CADET",
1363 "RATCHET_MESSAGES",
1364 "needs to be a number");
1365 ratchet_messages = 64;
1366 }
1367 if (GNUNET_OK !=
1368 GNUNET_CONFIGURATION_get_value_time (c,
1369 "CADET",
1370 "RATCHET_TIME",
1371 &ratchet_time))
1372 {
1373 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1374 "CADET",
1375 "RATCHET_TIME",
1376 "need delay value");
1377 ratchet_time = GNUNET_TIME_UNIT_HOURS;
1378 }
1379 if (GNUNET_OK !=
1380 GNUNET_CONFIGURATION_get_value_time (c,
1381 "CADET",
1382 "REFRESH_CONNECTION_TIME",
1383 &keepalive_period))
1384 {
1385 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1386 "CADET",
1387 "REFRESH_CONNECTION_TIME",
1388 "need delay value");
1389 keepalive_period = GNUNET_TIME_UNIT_MINUTES;
1390 }
1391 if (GNUNET_OK !=
1392 GNUNET_CONFIGURATION_get_value_number (c,
1393 "CADET",
1394 "DROP_PERCENT",
1395 &drop_percent))
1396 {
1397 drop_percent = 0;
1398 }
1399 else
1400 {
1401 LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
1402 LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n");
1403 LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n");
1404 LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n");
1405 LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
1406 }
1407 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
1408 if (NULL == my_private_key)
1409 {
1410 GNUNET_break (0);
1411 GNUNET_SCHEDULER_shutdown ();
1412 return;
1413 }
1414 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
1415 &my_full_id.public_key);
1416 stats = GNUNET_STATISTICS_create ("cadet",
1417 c);
1418 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1419 NULL);
1420 ats_ch = GNUNET_ATS_connectivity_init (c);
1421 /* FIXME: optimize code to allow GNUNET_YES here! */
1422 open_ports = GNUNET_CONTAINER_multihashmap_create (16,
1423 GNUNET_NO);
1424 loose_channels = GNUNET_CONTAINER_multihashmap_create (16,
1425 GNUNET_NO);
1426 peers = GNUNET_CONTAINER_multipeermap_create (16,
1427 GNUNET_YES);
1428 connections = GNUNET_CONTAINER_multishortmap_create (256,
1429 GNUNET_YES);
1430 GCH_init (c);
1431 GCD_init (c);
1432 GCO_init (c);
1433 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1434 "CADET started for peer %s\n",
1435 GNUNET_i2s (&my_full_id));
1436
1437}
1438
1439
1440/**
1441 * Define "main" method using service macro.
1442 */
1443GNUNET_SERVICE_MAIN
1444("cadet",
1445 GNUNET_SERVICE_OPTION_NONE,
1446 &run,
1447 &client_connect_cb,
1448 &client_disconnect_cb,
1449 NULL,
1450 GNUNET_MQ_hd_fixed_size (port_open,
1451 GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN,
1452 struct GNUNET_CADET_PortMessage,
1453 NULL),
1454 GNUNET_MQ_hd_fixed_size (port_close,
1455 GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
1456 struct GNUNET_CADET_PortMessage,
1457 NULL),
1458 GNUNET_MQ_hd_fixed_size (channel_create,
1459 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
1460 struct GNUNET_CADET_LocalChannelCreateMessage,
1461 NULL),
1462 GNUNET_MQ_hd_fixed_size (channel_destroy,
1463 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
1464 struct GNUNET_CADET_LocalChannelDestroyMessage,
1465 NULL),
1466 GNUNET_MQ_hd_var_size (local_data,
1467 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
1468 struct GNUNET_CADET_LocalData,
1469 NULL),
1470 GNUNET_MQ_hd_fixed_size (local_ack,
1471 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
1472 struct GNUNET_CADET_LocalAck,
1473 NULL),
1474 GNUNET_MQ_hd_fixed_size (get_peers,
1475 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
1476 struct GNUNET_MessageHeader,
1477 NULL),
1478 GNUNET_MQ_hd_fixed_size (show_peer,
1479 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER,
1480 struct GNUNET_CADET_LocalInfo,
1481 NULL),
1482 GNUNET_MQ_hd_fixed_size (info_tunnels,
1483 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
1484 struct GNUNET_MessageHeader,
1485 NULL),
1486 GNUNET_MQ_hd_fixed_size (info_tunnel,
1487 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL,
1488 struct GNUNET_CADET_LocalInfo,
1489 NULL),
1490 GNUNET_MQ_hd_fixed_size (info_dump,
1491 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP,
1492 struct GNUNET_MessageHeader,
1493 NULL),
1494 GNUNET_MQ_handler_end ());
1495
1496/* end of gnunet-service-cadet-new.c */
diff --git a/src/cadet/gnunet-service-cadet-new.h b/src/cadet/gnunet-service-cadet.h
index bee5c67cc..2f2d7baf3 100644
--- a/src/cadet/gnunet-service-cadet-new.h
+++ b/src/cadet/gnunet-service-cadet.h
@@ -20,7 +20,7 @@
20*/ 20*/
21 21
22/** 22/**
23 * @file cadet/gnunet-service-cadet-new.h 23 * @file cadet/gnunet-service-cadet.h
24 * @brief Information we track per peer. 24 * @brief Information we track per peer.
25 * @author Bartlomiej Polot 25 * @author Bartlomiej Polot
26 * @author Christian Grothoff 26 * @author Christian Grothoff
diff --git a/src/cadet/gnunet-service-cadet_channel.c b/src/cadet/gnunet-service-cadet_channel.c
index 7b7c6e57c..68e29b66b 100644
--- a/src/cadet/gnunet-service-cadet_channel.c
+++ b/src/cadet/gnunet-service-cadet_channel.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2013 GNUnet e.V. 3 Copyright (C) 2001-2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -17,31 +17,63 @@
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA. 18 Boston, MA 02110-1301, USA.
19*/ 19*/
20 20/**
21 21 * @file cadet/gnunet-service-cadet_channel.c
22 * @brief logical links between CADET clients
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - Congestion/flow control:
28 * + estimate max bandwidth using bursts and use to for CONGESTION CONTROL!
29 * (and figure out how/where to use this!)
30 * + figure out flow control without ACKs (unreliable traffic!)
31 * - revisit handling of 'unbuffered' traffic!
32 * (need to push down through tunnel into connection selection)
33 * - revisit handling of 'buffered' traffic: 4 is a rather small buffer; maybe
34 * reserve more bits in 'options' to allow for buffer size control?
35 */
22#include "platform.h" 36#include "platform.h"
23#include "gnunet_util_lib.h" 37#include "cadet.h"
24
25#include "gnunet_statistics_service.h" 38#include "gnunet_statistics_service.h"
39#include "gnunet-service-cadet_channel.h"
40#include "gnunet-service-cadet_connection.h"
41#include "gnunet-service-cadet_tunnels.h"
42#include "gnunet-service-cadet_paths.h"
26 43
27#include "cadet.h" 44#define LOG(level,...) GNUNET_log_from (level,"cadet-chn",__VA_ARGS__)
28#include "cadet_protocol.h"
29 45
30#include "gnunet-service-cadet_channel.h" 46/**
31#include "gnunet-service-cadet_local.h" 47 * How long do we initially wait before retransmitting?
32#include "gnunet-service-cadet_tunnel.h" 48 */
33#include "gnunet-service-cadet_peer.h" 49#define CADET_INITIAL_RETRANSMIT_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250)
34 50
35#define LOG(level, ...) GNUNET_log_from(level,"cadet-chn",__VA_ARGS__) 51/**
36#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-chn",__VA_ARGS__) 52 * How long do we wait before dropping state about incoming
53 * connection to closed port?
54 */
55#define TIMEOUT_CLOSED_PORT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
37 56
38#define CADET_RETRANSMIT_TIME GNUNET_TIME_relative_multiply(\ 57/**
39 GNUNET_TIME_UNIT_MILLISECONDS, 250) 58 * How long do we wait at least before retransmitting ever?
40#define CADET_RETRANSMIT_MARGIN 4 59 */
60#define MIN_RTT_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 75)
61
62/**
63 * Maximum message ID into the future we accept for out-of-order messages.
64 * If the message is more than this into the future, we drop it. This is
65 * important both to detect values that are actually in the past, as well
66 * as to limit adversarially triggerable memory consumption.
67 *
68 * Note that right now we have "max_pending_messages = 4" hard-coded in
69 * the logic below, so a value of 4 would suffice here. But we plan to
70 * allow larger windows in the future...
71 */
72#define MAX_OUT_OF_ORDER_DISTANCE 1024
41 73
42 74
43/** 75/**
44 * All the states a connection can be in. 76 * All the states a channel can be in.
45 */ 77 */
46enum CadetChannelState 78enum CadetChannelState
47{ 79{
@@ -51,9 +83,15 @@ enum CadetChannelState
51 CADET_CHANNEL_NEW, 83 CADET_CHANNEL_NEW,
52 84
53 /** 85 /**
54 * Connection create message sent, waiting for ACK. 86 * Channel is to a port that is not open, we're waiting for the
87 * port to be opened.
88 */
89 CADET_CHANNEL_LOOSE,
90
91 /**
92 * CHANNEL_OPEN message sent, waiting for CHANNEL_OPEN_ACK.
55 */ 93 */
56 CADET_CHANNEL_SENT, 94 CADET_CHANNEL_OPEN_SENT,
57 95
58 /** 96 /**
59 * Connection confirmed, ready to carry traffic. 97 * Connection confirmed, ready to carry traffic.
@@ -63,138 +101,144 @@ enum CadetChannelState
63 101
64 102
65/** 103/**
66 * Info holder for channel messages in queues. 104 * Info needed to retry a message in case it gets lost.
105 * Note that we DO use this structure also for unreliable
106 * messages.
67 */ 107 */
68struct CadetChannelQueue 108struct CadetReliableMessage
69{ 109{
70 /** 110 /**
71 * Tunnel Queue. 111 * Double linked list, FIFO style
72 */ 112 */
73 struct CadetTunnelQueue *tq; 113 struct CadetReliableMessage *next;
74 114
75 /** 115 /**
76 * Message type (DATA/DATA_ACK) 116 * Double linked list, FIFO style
77 */ 117 */
78 uint16_t type; 118 struct CadetReliableMessage *prev;
79 119
80 /** 120 /**
81 * Message copy (for DATAs, to start retransmission timer) 121 * Which channel is this message in?
82 */ 122 */
83 struct CadetReliableMessage *copy; 123 struct CadetChannel *ch;
84 124
85 /** 125 /**
86 * Reliability (for DATA_ACKs, to access rel->ack_q) 126 * Entry in the tunnels queue for this message, NULL if it has left
127 * the tunnel. Used to cancel transmission in case we receive an
128 * ACK in time.
87 */ 129 */
88 struct CadetChannelReliability *rel; 130 struct CadetTunnelQueueEntry *qe;
89};
90
91 131
92/**
93 * Info needed to retry a message in case it gets lost.
94 */
95struct CadetReliableMessage
96{
97 /** 132 /**
98 * Double linked list, FIFO style 133 * Data message we are trying to send.
99 */ 134 */
100 struct CadetReliableMessage *next; 135 struct GNUNET_CADET_ChannelAppDataMessage *data_message;
101 struct CadetReliableMessage *prev;
102 136
103 /** 137 /**
104 * Type of message (payload, channel management). 138 * How soon should we retry if we fail to get an ACK?
139 * Messages in the queue are sorted by this value.
105 */ 140 */
106 int16_t type; 141 struct GNUNET_TIME_Absolute next_retry;
107 142
108 /** 143 /**
109 * Tunnel Reliability queue this message is in. 144 * How long do we wait for an ACK after transmission?
145 * Use for the back-off calculation.
110 */ 146 */
111 struct CadetChannelReliability *rel; 147 struct GNUNET_TIME_Relative retry_delay;
112 148
113 /** 149 /**
114 * ID of the message (ACK needed to free) 150 * Time when we first successfully transmitted the message
151 * (that is, set @e num_transmissions to 1).
115 */ 152 */
116 uint32_t mid; 153 struct GNUNET_TIME_Absolute first_transmission_time;
117 154
118 /** 155 /**
119 * Tunnel Queue. 156 * Identifier of the connection that this message took when it
157 * was first transmitted. Only useful if @e num_transmissions is 1.
120 */ 158 */
121 struct CadetChannelQueue *chq; 159 struct GNUNET_CADET_ConnectionTunnelIdentifier connection_taken;
122 160
123 /** 161 /**
124 * When was this message issued (to calculate ACK delay) 162 * How often was this message transmitted? #GNUNET_SYSERR if there
163 * was an error transmitting the message, #GNUNET_NO if it was not
164 * yet transmitted ever, otherwise the number of (re) transmissions.
125 */ 165 */
126 struct GNUNET_TIME_Absolute timestamp; 166 int num_transmissions;
127 167
128 /* struct GNUNET_CADET_ChannelAppDataMessage with payload */
129}; 168};
130 169
131 170
132/** 171/**
133 * Info about the traffic state for a client in a channel. 172 * List of received out-of-order data messages.
134 */ 173 */
135struct CadetChannelReliability 174struct CadetOutOfOrderMessage
136{ 175{
137 /** 176 /**
138 * Channel this is about. 177 * Double linked list, FIFO style
139 */ 178 */
140 struct CadetChannel *ch; 179 struct CadetOutOfOrderMessage *next;
141 180
142 /** 181 /**
143 * DLL of messages sent and not yet ACK'd. 182 * Double linked list, FIFO style
144 */ 183 */
145 struct CadetReliableMessage *head_sent; 184 struct CadetOutOfOrderMessage *prev;
146 struct CadetReliableMessage *tail_sent;
147 185
148 /** 186 /**
149 * DLL of messages received out of order. 187 * ID of the message (messages up to this point needed
188 * before we give this one to the client).
150 */ 189 */
151 struct CadetReliableMessage *head_recv; 190 struct ChannelMessageIdentifier mid;
152 struct CadetReliableMessage *tail_recv;
153 191
154 /** 192 /**
155 * Messages received. 193 * The envelope with the payload of the out-of-order message
156 */ 194 */
157 unsigned int n_recv; 195 struct GNUNET_MQ_Envelope *env;
158 196
159 /** 197};
160 * Next MID to use for outgoing traffic.
161 */
162 uint32_t mid_send;
163 198
164 /**
165 * Next MID expected for incoming traffic.
166 */
167 uint32_t mid_recv;
168 199
200/**
201 * Client endpoint of a `struct CadetChannel`. A channel may be a
202 * loopback channel, in which case it has two of these endpoints.
203 * Note that flow control also is required in both directions.
204 */
205struct CadetChannelClient
206{
169 /** 207 /**
170 * Handle for queued unique data CREATE, DATA_ACK. 208 * Client handle. Not by itself sufficient to designate
209 * the client endpoint, as the same client handle may
210 * be used for both the owner and the destination, and
211 * we thus also need the channel ID to identify the client.
171 */ 212 */
172 struct CadetChannelQueue *uniq; 213 struct CadetClient *c;
173 214
174 /** 215 /**
175 * Can we send data to the client? 216 * Head of DLL of messages received out of order or while client was unready.
176 */ 217 */
177 int client_ready; 218 struct CadetOutOfOrderMessage *head_recv;
178 219
179 /** 220 /**
180 * Can the client send data to us? 221 * Tail DLL of messages received out of order or while client was unready.
181 */ 222 */
182 int client_allowed; 223 struct CadetOutOfOrderMessage *tail_recv;
183 224
184 /** 225 /**
185 * Task to resend/poll in case no ACK is received. 226 * Local tunnel number for this client.
227 * (if owner >= #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI,
228 * otherwise < #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
186 */ 229 */
187 struct GNUNET_SCHEDULER_Task * retry_task; 230 struct GNUNET_CADET_ClientChannelNumber ccn;
188 231
189 /** 232 /**
190 * Counter for exponential backoff. 233 * Number of entries currently in @a head_recv DLL.
191 */ 234 */
192 struct GNUNET_TIME_Relative retry_timer; 235 unsigned int num_recv;
193 236
194 /** 237 /**
195 * How long does it usually take to get an ACK. 238 * Can we send data to the client?
196 */ 239 */
197 struct GNUNET_TIME_Relative expected_delay; 240 int client_ready;
241
198}; 242};
199 243
200 244
@@ -209,41 +253,44 @@ struct CadetChannel
209 struct CadetTunnel *t; 253 struct CadetTunnel *t;
210 254
211 /** 255 /**
212 * Destination port of the channel. 256 * Client owner of the tunnel, if any.
257 * (Used if this channel represends the initiating end of the tunnel.)
213 */ 258 */
214 struct GNUNET_HashCode port; 259 struct CadetChannelClient *owner;
215 260
216 /** 261 /**
217 * Global channel number ( < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) 262 * Client destination of the tunnel, if any.
263 * (Used if this channel represents the listening end of the tunnel.)
218 */ 264 */
219 struct GNUNET_CADET_ChannelTunnelNumber gid; 265 struct CadetChannelClient *dest;
220 266
221 /** 267 /**
222 * Local tunnel number for root (owner) client. 268 * Last entry in the tunnel's queue relating to control messages
223 * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI or 0 ) 269 * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN or
270 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK). Used to cancel
271 * transmission in case we receive updated information.
224 */ 272 */
225 struct GNUNET_CADET_ClientChannelNumber lid_root; 273 struct CadetTunnelQueueEntry *last_control_qe;
226 274
227 /** 275 /**
228 * Local tunnel number for local destination clients (incoming number) 276 * Head of DLL of messages sent and not yet ACK'd.
229 * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV or 0).
230 */ 277 */
231 struct GNUNET_CADET_ClientChannelNumber lid_dest; 278 struct CadetReliableMessage *head_sent;
232 279
233 /** 280 /**
234 * Channel state. 281 * Tail of DLL of messages sent and not yet ACK'd.
235 */ 282 */
236 enum CadetChannelState state; 283 struct CadetReliableMessage *tail_sent;
237 284
238 /** 285 /**
239 * Is the tunnel bufferless (minimum latency)? 286 * Task to resend/poll in case no ACK is received.
240 */ 287 */
241 int nobuffer; 288 struct GNUNET_SCHEDULER_Task *retry_control_task;
242 289
243 /** 290 /**
244 * Is the tunnel reliable? 291 * Task to resend/poll in case no ACK is received.
245 */ 292 */
246 int reliable; 293 struct GNUNET_SCHEDULER_Task *retry_data_task;
247 294
248 /** 295 /**
249 * Last time the channel was used 296 * Last time the channel was used
@@ -251,21 +298,29 @@ struct CadetChannel
251 struct GNUNET_TIME_Absolute timestamp; 298 struct GNUNET_TIME_Absolute timestamp;
252 299
253 /** 300 /**
254 * Client owner of the tunnel, if any 301 * Destination port of the channel.
255 */ 302 */
256 struct CadetClient *root; 303 struct GNUNET_HashCode port;
257 304
258 /** 305 /**
259 * Client destination of the tunnel, if any. 306 * Counter for exponential backoff.
260 */ 307 */
261 struct CadetClient *dest; 308 struct GNUNET_TIME_Relative retry_time;
262 309
263 /** 310 /**
264 * Flag to signal the destruction of the channel. 311 * Bitfield of already-received messages past @e mid_recv.
265 * If this is set to #GNUNET_YES the channel will be destroyed
266 * when the queue is empty.
267 */ 312 */
268 int destroy; 313 uint64_t mid_futures;
314
315 /**
316 * Next MID expected for incoming traffic.
317 */
318 struct ChannelMessageIdentifier mid_recv;
319
320 /**
321 * Next MID to use for outgoing traffic.
322 */
323 struct ChannelMessageIdentifier mid_send;
269 324
270 /** 325 /**
271 * Total (reliable) messages pending ACK for this channel. 326 * Total (reliable) messages pending ACK for this channel.
@@ -273,2290 +328,1710 @@ struct CadetChannel
273 unsigned int pending_messages; 328 unsigned int pending_messages;
274 329
275 /** 330 /**
276 * Reliability data. 331 * Maximum (reliable) messages pending ACK for this channel
277 * Only present (non-NULL) at the owner of a tunnel. 332 * before we throttle the client.
278 */ 333 */
279 struct CadetChannelReliability *root_rel; 334 unsigned int max_pending_messages;
280 335
281 /** 336 /**
282 * Reliability data. 337 * Number identifying this channel in its tunnel.
283 * Only present (non-NULL) at the destination of a tunnel.
284 */ 338 */
285 struct CadetChannelReliability *dest_rel; 339 struct GNUNET_CADET_ChannelTunnelNumber ctn;
286 340
287}; 341 /**
342 * Channel state.
343 */
344 enum CadetChannelState state;
288 345
346 /**
347 * Count how many ACKs we skipped, used to prevent long
348 * sequences of ACK skipping.
349 */
350 unsigned int skip_ack_series;
289 351
290/******************************************************************************/ 352 /**
291/******************************* GLOBALS ***********************************/ 353 * Is the tunnel bufferless (minimum latency)?
292/******************************************************************************/ 354 */
355 int nobuffer;
293 356
294/** 357 /**
295 * Global handle to the statistics service. 358 * Is the tunnel reliable?
296 */ 359 */
297extern struct GNUNET_STATISTICS_Handle *stats; 360 int reliable;
298 361
299/** 362 /**
300 * Local peer own ID (memory efficient handle). 363 * Is the tunnel out-of-order?
301 */ 364 */
302extern GNUNET_PEER_Id myid; 365 int out_of_order;
303 366
367 /**
368 * Is this channel a loopback channel, where the destination is us again?
369 */
370 int is_loopback;
304 371
305/******************************************************************************/ 372 /**
306/******************************** STATIC ***********************************/ 373 * Flag to signal the destruction of the channel. If this is set to
307/******************************************************************************/ 374 * #GNUNET_YES the channel will be destroyed once the queue is
375 * empty.
376 */
377 int destroy;
308 378
379};
309 380
310/**
311 * Destroy a reliable message after it has been acknowledged, either by
312 * direct mid ACK or bitfield. Updates the appropriate data structures and
313 * timers and frees all memory.
314 *
315 * @param copy Message that is no longer needed: remote peer got it.
316 * @param update_time Is the timing information relevant?
317 * If this message is ACK in a batch the timing information
318 * is skewed by the retransmission, count only for the
319 * retransmitted message.
320 *
321 * @return #GNUNET_YES if channel was destroyed as a result of the call,
322 * #GNUNET_NO otherwise.
323 */
324static int
325rel_message_free (struct CadetReliableMessage *copy, int update_time);
326 381
327/** 382/**
328 * send a channel create message. 383 * Get the static string for identification of the channel.
329 * 384 *
330 * @param ch Channel for which to send. 385 * @param ch Channel.
331 */
332static void
333send_create (struct CadetChannel *ch);
334
335/**
336 * Confirm we got a channel create, FWD ack.
337 * 386 *
338 * @param ch The channel to confirm. 387 * @return Static string with the channel IDs.
339 * @param fwd Should we send a FWD ACK? (going dest->root)
340 */ 388 */
341static void 389const char *
342send_ack (struct CadetChannel *ch, int fwd); 390GCCH_2s (const struct CadetChannel *ch)
343 391{
392 static char buf[128];
393
394 GNUNET_snprintf (buf,
395 sizeof (buf),
396 "Channel %s:%s ctn:%X(%X/%X)",
397 (GNUNET_YES == ch->is_loopback)
398 ? "loopback"
399 : GNUNET_i2s (GCP_get_id (GCT_get_destination (ch->t))),
400 GNUNET_h2s (&ch->port),
401 ch->ctn,
402 (NULL == ch->owner) ? 0 : ntohl (ch->owner->ccn.channel_of_client),
403 (NULL == ch->dest) ? 0 : ntohl (ch->dest->ccn.channel_of_client));
404 return buf;
405}
344 406
345 407
346/** 408/**
347 * Test if the channel is loopback: both root and dest are on the local peer. 409 * Get the channel's public ID.
348 * 410 *
349 * @param ch Channel to test. 411 * @param ch Channel.
350 * 412 *
351 * @return #GNUNET_YES if channel is loopback, #GNUNET_NO otherwise. 413 * @return ID used to identify the channel with the remote peer.
352 */ 414 */
353static int 415struct GNUNET_CADET_ChannelTunnelNumber
354is_loopback (const struct CadetChannel *ch) 416GCCH_get_id (const struct CadetChannel *ch)
355{ 417{
356 if (NULL != ch->t) 418 return ch->ctn;
357 return GCT_is_loopback (ch->t);
358
359 return (NULL != ch->root && NULL != ch->dest);
360} 419}
361 420
362 421
363/** 422/**
364 * Save a copy of the data message for later retransmission. 423 * Release memory associated with @a ccc
365 * 424 *
366 * @param msg Message to copy. 425 * @param ccc data structure to clean up
367 * @param mid Message ID.
368 * @param rel Reliability data for retransmission.
369 */ 426 */
370static struct CadetReliableMessage * 427static void
371copy_message (const struct GNUNET_CADET_ChannelAppDataMessage *msg, uint32_t mid, 428free_channel_client (struct CadetChannelClient *ccc)
372 struct CadetChannelReliability *rel)
373{ 429{
374 struct CadetReliableMessage *copy; 430 struct CadetOutOfOrderMessage *com;
375 uint16_t size;
376 431
377 size = ntohs (msg->header.size); 432 while (NULL != (com = ccc->head_recv))
378 copy = GNUNET_malloc (sizeof (*copy) + size); 433 {
379 copy->mid = mid; 434 GNUNET_CONTAINER_DLL_remove (ccc->head_recv,
380 copy->rel = rel; 435 ccc->tail_recv,
381 copy->type = GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA; 436 com);
382 GNUNET_memcpy (&copy[1], msg, size); 437 ccc->num_recv--;
383 438 GNUNET_MQ_discard (com->env);
384 return copy; 439 GNUNET_free (com);
440 }
441 GNUNET_free (ccc);
385} 442}
386 443
444
387/** 445/**
388 * We have received a message out of order, or the client is not ready. 446 * Destroy the given channel.
389 * Buffer it until we receive an ACK from the client or the missing
390 * message from the channel.
391 * 447 *
392 * @param msg Message to buffer (MUST be of type CADET_DATA). 448 * @param ch channel to destroy
393 * @param rel Reliability data to the corresponding direction.
394 */ 449 */
395static void 450static void
396add_buffered_data (const struct GNUNET_CADET_ChannelAppDataMessage *msg, 451channel_destroy (struct CadetChannel *ch)
397 struct CadetChannelReliability *rel)
398{ 452{
399 struct CadetReliableMessage *copy; 453 struct CadetReliableMessage *crm;
400 struct CadetReliableMessage *prev;
401 uint32_t mid;
402
403 mid = ntohl (msg->mid);
404 454
405 LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data MID %u (%u)\n", 455 while (NULL != (crm = ch->head_sent))
406 mid, rel->n_recv);
407
408 rel->n_recv++;
409
410 // FIXME do something better than O(n), although n < 64...
411 // FIXME start from the end (most messages are the latest ones)
412 for (prev = rel->head_recv; NULL != prev; prev = prev->next)
413 { 456 {
414 LOG (GNUNET_ERROR_TYPE_DEBUG, " prev %u\n", prev->mid); 457 GNUNET_assert (ch == crm->ch);
415 if (prev->mid == mid) 458 if (NULL != crm->qe)
416 { 459 {
417 LOG (GNUNET_ERROR_TYPE_DEBUG, " already there!\n"); 460 GCT_send_cancel (crm->qe);
418 rel->n_recv--; 461 crm->qe = NULL;
419 return;
420 }
421 else if (GC_is_pid_bigger (prev->mid, mid))
422 {
423 LOG (GNUNET_ERROR_TYPE_DEBUG, " bingo!\n");
424 copy = copy_message (msg, mid, rel);
425 GNUNET_CONTAINER_DLL_insert_before (rel->head_recv, rel->tail_recv,
426 prev, copy);
427 return;
428 } 462 }
463 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
464 ch->tail_sent,
465 crm);
466 GNUNET_free (crm->data_message);
467 GNUNET_free (crm);
468 }
469 if (NULL != ch->owner)
470 {
471 free_channel_client (ch->owner);
472 ch->owner = NULL;
429 } 473 }
430 copy = copy_message (msg, mid, rel); 474 if (NULL != ch->dest)
431 LOG (GNUNET_ERROR_TYPE_DEBUG, " insert at tail! (now: %u)\n", rel->n_recv); 475 {
432 GNUNET_CONTAINER_DLL_insert_tail (rel->head_recv, rel->tail_recv, copy); 476 free_channel_client (ch->dest);
433 LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data END\n"); 477 ch->dest = NULL;
478 }
479 if (NULL != ch->last_control_qe)
480 {
481 GCT_send_cancel (ch->last_control_qe);
482 ch->last_control_qe = NULL;
483 }
484 if (NULL != ch->retry_data_task)
485 {
486 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
487 ch->retry_data_task = NULL;
488 }
489 if (NULL != ch->retry_control_task)
490 {
491 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
492 ch->retry_control_task = NULL;
493 }
494 if (GNUNET_NO == ch->is_loopback)
495 {
496 GCT_remove_channel (ch->t,
497 ch,
498 ch->ctn);
499 ch->t = NULL;
500 }
501 GNUNET_free (ch);
434} 502}
435 503
436 504
437/** 505/**
438 * Add a destination client to a channel, initializing all data structures 506 * Send a channel create message.
439 * in the channel and the client.
440 * 507 *
441 * @param ch Channel to which add the destination. 508 * @param cls Channel for which to send.
442 * @param c Client which to add to the channel.
443 */ 509 */
444static void 510static void
445add_destination (struct CadetChannel *ch, struct CadetClient *c) 511send_channel_open (void *cls);
446{
447 if (NULL != ch->dest)
448 {
449 GNUNET_break (0);
450 return;
451 }
452
453 /* Assign local id as destination */
454 ch->lid_dest = GML_get_next_ccn (c);
455
456 /* Store in client's hashmap */
457 GML_channel_add (c, ch->lid_dest, ch);
458
459 GNUNET_break (NULL == ch->dest_rel);
460 ch->dest_rel = GNUNET_new (struct CadetChannelReliability);
461 ch->dest_rel->ch = ch;
462 ch->dest_rel->expected_delay.rel_value_us = 0;
463 ch->dest_rel->retry_timer = CADET_RETRANSMIT_TIME;
464
465 ch->dest = c;
466}
467 512
468 513
469/** 514/**
470 * Set options in a channel, extracted from a bit flag field. 515 * Function called once the tunnel confirms that we sent the
516 * create message. Delays for a bit until we retry.
471 * 517 *
472 * @param ch Channel to set options to. 518 * @param cls our `struct CadetChannel`.
473 * @param options Bit array in host byte order. 519 * @param cid identifier of the connection within the tunnel, NULL
520 * if transmission failed
474 */ 521 */
475static void 522static void
476channel_set_options (struct CadetChannel *ch, uint32_t options) 523channel_open_sent_cb (void *cls,
524 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
477{ 525{
478 ch->nobuffer = (options & GNUNET_CADET_OPTION_NOBUFFER) != 0 ? 526 struct CadetChannel *ch = cls;
479 GNUNET_YES : GNUNET_NO; 527
480 ch->reliable = (options & GNUNET_CADET_OPTION_RELIABLE) != 0 ? 528 GNUNET_assert (NULL != ch->last_control_qe);
481 GNUNET_YES : GNUNET_NO; 529 ch->last_control_qe = NULL;
530 ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time);
531 LOG (GNUNET_ERROR_TYPE_DEBUG,
532 "Sent CADET_CHANNEL_OPEN on %s, retrying in %s\n",
533 GCCH_2s (ch),
534 GNUNET_STRINGS_relative_time_to_string (ch->retry_time,
535 GNUNET_YES));
536 ch->retry_control_task
537 = GNUNET_SCHEDULER_add_delayed (ch->retry_time,
538 &send_channel_open,
539 ch);
482} 540}
483 541
484 542
485/** 543/**
486 * Get a bit flag field with the options of a channel. 544 * Send a channel open message.
487 * 545 *
488 * @param ch Channel to get options from. 546 * @param cls Channel for which to send.
489 *
490 * @return Bit array in host byte order.
491 */ 547 */
492static uint32_t 548static void
493channel_get_options (struct CadetChannel *ch) 549send_channel_open (void *cls)
494{ 550{
551 struct CadetChannel *ch = cls;
552 struct GNUNET_CADET_ChannelOpenMessage msgcc;
495 uint32_t options; 553 uint32_t options;
496 554
555 ch->retry_control_task = NULL;
556 LOG (GNUNET_ERROR_TYPE_DEBUG,
557 "Sending CHANNEL_OPEN message for %s\n",
558 GCCH_2s (ch));
497 options = 0; 559 options = 0;
498 if (ch->nobuffer) 560 if (ch->nobuffer)
499 options |= GNUNET_CADET_OPTION_NOBUFFER; 561 options |= GNUNET_CADET_OPTION_NOBUFFER;
500 if (ch->reliable) 562 if (ch->reliable)
501 options |= GNUNET_CADET_OPTION_RELIABLE; 563 options |= GNUNET_CADET_OPTION_RELIABLE;
502 564 if (ch->out_of_order)
503 return options; 565 options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
566 msgcc.header.size = htons (sizeof (msgcc));
567 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
568 msgcc.opt = htonl (options);
569 msgcc.port = ch->port;
570 msgcc.ctn = ch->ctn;
571 ch->state = CADET_CHANNEL_OPEN_SENT;
572 if (NULL != ch->last_control_qe)
573 GCT_send_cancel (ch->last_control_qe);
574 ch->last_control_qe = GCT_send (ch->t,
575 &msgcc.header,
576 &channel_open_sent_cb,
577 ch);
578 GNUNET_assert (NULL == ch->retry_control_task);
504} 579}
505 580
506 581
507/** 582/**
508 * Notify a client that the channel is no longer valid. 583 * Function called once and only once after a channel was bound
509 * 584 * to its tunnel via #GCT_add_channel() is ready for transmission.
510 * @param ch Channel that is destroyed. 585 * Note that this is only the case for channels that this peer
511 * @param local_only Should we avoid sending it to other peers? 586 * initiates, as for incoming channels we assume that they are
587 * ready for transmission immediately upon receiving the open
588 * message. Used to bootstrap the #GCT_send() process.
589 *
590 * @param ch the channel for which the tunnel is now ready
512 */ 591 */
513static void 592void
514send_destroy (struct CadetChannel *ch, int local_only) 593GCCH_tunnel_up (struct CadetChannel *ch)
515{ 594{
516 struct GNUNET_CADET_ChannelManageMessage msg; 595 GNUNET_assert (NULL == ch->retry_control_task);
517 596 LOG (GNUNET_ERROR_TYPE_DEBUG,
518 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY); 597 "Tunnel up, sending CHANNEL_OPEN on %s now\n",
519 msg.header.size = htons (sizeof (msg)); 598 GCCH_2s (ch));
520 msg.ctn = ch->gid; 599 ch->retry_control_task
521 600 = GNUNET_SCHEDULER_add_now (&send_channel_open,
522 /* If root is not NULL, notify. 601 ch);
523 * If it's NULL, check lid_root. When a local destroy comes in, root
524 * is set to NULL but lid_root is left untouched. In this case, do nothing,
525 * the client is the one who requested the channel to be destroyed.
526 */
527 if (NULL != ch->root)
528 GML_send_channel_destroy (ch->root, ch->lid_root);
529 else if (0 == ch->lid_root.channel_of_client && GNUNET_NO == local_only)
530 GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL);
531
532 if (NULL != ch->dest)
533 GML_send_channel_destroy (ch->dest, ch->lid_dest);
534 else if (0 == ch->lid_dest.channel_of_client && GNUNET_NO == local_only)
535 GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_YES, NULL);
536} 602}
537 603
538 604
539/** 605/**
540 * Notify the destination client that a new incoming channel was created. 606 * Create a new channel.
541 * 607 *
542 * @param ch Channel that was created. 608 * @param owner local client owning the channel
609 * @param ccn local number of this channel at the @a owner
610 * @param destination peer to which we should build the channel
611 * @param port desired port at @a destination
612 * @param options options for the channel
613 * @return handle to the new channel
543 */ 614 */
544static void 615struct CadetChannel *
545send_client_create (struct CadetChannel *ch) 616GCCH_channel_local_new (struct CadetClient *owner,
617 struct GNUNET_CADET_ClientChannelNumber ccn,
618 struct CadetPeer *destination,
619 const struct GNUNET_HashCode *port,
620 uint32_t options)
546{ 621{
547 uint32_t opt; 622 struct CadetChannel *ch;
548 623 struct CadetChannelClient *ccco;
549 if (NULL == ch->dest)
550 return;
551
552 opt = 0;
553 opt |= GNUNET_YES == ch->reliable ? GNUNET_CADET_OPTION_RELIABLE : 0;
554 opt |= GNUNET_YES == ch->nobuffer ? GNUNET_CADET_OPTION_NOBUFFER : 0;
555 GML_send_channel_create (ch->dest,
556 ch->lid_dest,
557 &ch->port,
558 opt,
559 GCT_get_destination (ch->t));
560
561}
562 624
625 ccco = GNUNET_new (struct CadetChannelClient);
626 ccco->c = owner;
627 ccco->ccn = ccn;
628 ccco->client_ready = GNUNET_YES;
563 629
564/** 630 ch = GNUNET_new (struct CadetChannel);
565 * Send data to a client. 631 ch->mid_recv.mid = htonl (1); /* The OPEN_ACK counts as message 0! */
566 * 632 ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER));
567 * If the client is ready, send directly, otherwise buffer while listening 633 ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE));
568 * for a local ACK. 634 ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER));
569 * 635 ch->max_pending_messages = (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
570 * @param ch Channel 636 ch->owner = ccco;
571 * @param msg Message. 637 ch->port = *port;
572 * @param fwd Is this a fwd (root->dest) message? 638 if (0 == memcmp (&my_full_id,
573 */ 639 GCP_get_id (destination),
574static void 640 sizeof (struct GNUNET_PeerIdentity)))
575send_client_data (struct CadetChannel *ch, 641 {
576 const struct GNUNET_CADET_ChannelAppDataMessage *msg, 642 struct CadetClient *c;
577 int fwd) 643
578{ 644 ch->is_loopback = GNUNET_YES;
579 if (fwd) 645 c = GNUNET_CONTAINER_multihashmap_get (open_ports,
580 { 646 port);
581 if (ch->dest_rel->client_ready) 647 if (NULL == c)
582 { 648 {
583 GML_send_data (ch->dest, msg, ch->lid_dest); 649 /* port closed, wait for it to possibly open */
584 ch->dest_rel->client_ready = GNUNET_NO; 650 ch->state = CADET_CHANNEL_LOOSE;
585 ch->dest_rel->mid_recv++; 651 (void) GNUNET_CONTAINER_multihashmap_put (loose_channels,
652 port,
653 ch,
654 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
655 LOG (GNUNET_ERROR_TYPE_DEBUG,
656 "Created loose incoming loopback channel to port %s\n",
657 GNUNET_h2s (&ch->port));
586 } 658 }
587 else 659 else
588 add_buffered_data (msg, ch->dest_rel); 660 {
661 GCCH_bind (ch,
662 c);
663 }
589 } 664 }
590 else 665 else
591 { 666 {
592 if (ch->root_rel->client_ready) 667 ch->t = GCP_get_tunnel (destination,
593 { 668 GNUNET_YES);
594 GML_send_data (ch->root, msg, ch->lid_root); 669 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
595 ch->root_rel->client_ready = GNUNET_NO; 670 ch->ctn = GCT_add_channel (ch->t,
596 ch->root_rel->mid_recv++; 671 ch);
597 }
598 else
599 add_buffered_data (msg, ch->root_rel);
600 } 672 }
673 GNUNET_STATISTICS_update (stats,
674 "# channels",
675 1,
676 GNUNET_NO);
677 LOG (GNUNET_ERROR_TYPE_DEBUG,
678 "Created channel to port %s at peer %s for %s using %s\n",
679 GNUNET_h2s (port),
680 GCP_2s (destination),
681 GSC_2s (owner),
682 (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t));
683 return ch;
601} 684}
602 685
603 686
604/** 687/**
605 * Send a buffered message to the client, for in order delivery or 688 * We had an incoming channel to a port that is closed.
606 * as result of client ACK. 689 * It has not been opened for a while, drop it.
607 * 690 *
608 * @param ch Channel on which to empty the message buffer. 691 * @param cls the channel to drop
609 * @param c Client to send to.
610 * @param fwd Is this to send FWD data?.
611 */ 692 */
612static void 693static void
613send_client_buffered_data (struct CadetChannel *ch, 694timeout_closed_cb (void *cls)
614 struct CadetClient *c,
615 int fwd)
616{ 695{
617 struct CadetReliableMessage *copy; 696 struct CadetChannel *ch = cls;
618 struct CadetChannelReliability *rel;
619
620 LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data\n");
621 rel = fwd ? ch->dest_rel : ch->root_rel;
622 if (GNUNET_NO == rel->client_ready)
623 {
624 LOG (GNUNET_ERROR_TYPE_DEBUG, "client not ready\n");
625 return;
626 }
627 697
628 copy = rel->head_recv; 698 ch->retry_control_task = NULL;
629 /* We never buffer channel management messages */ 699 LOG (GNUNET_ERROR_TYPE_DEBUG,
630 if (NULL != copy) 700 "Closing incoming channel to port %s from peer %s due to timeout\n",
631 { 701 GNUNET_h2s (&ch->port),
632 if (copy->mid == rel->mid_recv || GNUNET_NO == ch->reliable) 702 GCP_2s (GCT_get_destination (ch->t)));
633 { 703 channel_destroy (ch);
634 struct GNUNET_CADET_ChannelAppDataMessage *msg = (struct GNUNET_CADET_ChannelAppDataMessage *) &copy[1];
635
636 LOG (GNUNET_ERROR_TYPE_DEBUG, " have %u! now expecting %u\n",
637 copy->mid, rel->mid_recv + 1);
638 send_client_data (ch, msg, fwd);
639 rel->n_recv--;
640 GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy);
641 LOG (GNUNET_ERROR_TYPE_DEBUG, " free copy recv MID %u (%p), %u left\n",
642 copy->mid, copy, rel->n_recv);
643 GNUNET_free (copy);
644 GCCH_send_data_ack (ch, fwd);
645 }
646 else
647 {
648 LOG (GNUNET_ERROR_TYPE_DEBUG, " reliable && don't have %u, next is %u\n",
649 rel->mid_recv, copy->mid);
650 if (GNUNET_YES == ch->destroy)
651 {
652 /* We don't have the next data piece and the remote peer has closed the
653 * channel. We won't receive it anymore, so just destroy the channel.
654 * FIXME: wait some time to allow other connections to
655 * deliver missing messages
656 */
657 send_destroy (ch, GNUNET_YES);
658 GCCH_destroy (ch);
659 }
660 }
661 }
662 LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data END\n");
663} 704}
664 705
665 706
666/** 707/**
667 * Allow a client to send more data. 708 * Create a new channel based on a request coming in over the network.
668 *
669 * In case the client was already allowed to send data, do nothing.
670 * 709 *
671 * @param ch Channel. 710 * @param t tunnel to the remote peer
672 * @param fwd Is this a FWD ACK? (FWD ACKs are sent to root) 711 * @param ctn identifier of this channel in the tunnel
712 * @param port desired local port
713 * @param options options for the channel
714 * @return handle to the new channel
673 */ 715 */
674static void 716struct CadetChannel *
675send_client_ack (struct CadetChannel *ch, int fwd) 717GCCH_channel_incoming_new (struct CadetTunnel *t,
718 struct GNUNET_CADET_ChannelTunnelNumber ctn,
719 const struct GNUNET_HashCode *port,
720 uint32_t options)
676{ 721{
677 struct CadetChannelReliability *rel = fwd ? ch->root_rel : ch->dest_rel; 722 struct CadetChannel *ch;
678 struct CadetClient *c = fwd ? ch->root : ch->dest; 723 struct CadetClient *c;
724
725 ch = GNUNET_new (struct CadetChannel);
726 ch->port = *port;
727 ch->t = t;
728 ch->ctn = ctn;
729 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
730 ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER));
731 ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE));
732 ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER));
733 ch->max_pending_messages = (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
734 GNUNET_STATISTICS_update (stats,
735 "# channels",
736 1,
737 GNUNET_NO);
679 738
739 c = GNUNET_CONTAINER_multihashmap_get (open_ports,
740 port);
680 if (NULL == c) 741 if (NULL == c)
681 { 742 {
682 GNUNET_break (GNUNET_NO != ch->destroy); 743 /* port closed, wait for it to possibly open */
683 return; 744 ch->state = CADET_CHANNEL_LOOSE;
745 (void) GNUNET_CONTAINER_multihashmap_put (loose_channels,
746 port,
747 ch,
748 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
749 GNUNET_assert (NULL == ch->retry_control_task);
750 ch->retry_control_task
751 = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT,
752 &timeout_closed_cb,
753 ch);
754 LOG (GNUNET_ERROR_TYPE_DEBUG,
755 "Created loose incoming channel to port %s from peer %s\n",
756 GNUNET_h2s (&ch->port),
757 GCP_2s (GCT_get_destination (ch->t)));
684 } 758 }
685 LOG (GNUNET_ERROR_TYPE_DEBUG, 759 else
686 " sending %s ack to client on channel %s\n",
687 GC_f2s (fwd), GCCH_2s (ch));
688
689 if (NULL == rel)
690 { 760 {
691 GNUNET_break (0); 761 GCCH_bind (ch,
692 return; 762 c);
693 } 763 }
694 764 GNUNET_STATISTICS_update (stats,
695 if (GNUNET_YES == rel->client_allowed) 765 "# channels",
696 { 766 1,
697 LOG (GNUNET_ERROR_TYPE_DEBUG, " already allowed\n"); 767 GNUNET_NO);
698 return; 768 return ch;
699 }
700 rel->client_allowed = GNUNET_YES;
701
702 GML_send_ack (c, fwd ? ch->lid_root : ch->lid_dest);
703} 769}
704 770
705 771
706/** 772/**
707 * Notify the root that the destination rejected the channel. 773 * Function called once the tunnel confirms that we sent the
774 * ACK message. Just remembers it was sent, we do not expect
775 * ACKs for ACKs ;-).
708 * 776 *
709 * @param ch Rejected channel. 777 * @param cls our `struct CadetChannel`.
778 * @param cid identifier of the connection within the tunnel, NULL
779 * if transmission failed
710 */ 780 */
711static void 781static void
712send_client_nack (struct CadetChannel *ch) 782send_ack_cb (void *cls,
783 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
713{ 784{
714 if (NULL == ch->root) 785 struct CadetChannel *ch = cls;
715 { 786
716 GNUNET_break (0); 787 GNUNET_assert (NULL != ch->last_control_qe);
717 return; 788 ch->last_control_qe = NULL;
718 }
719 GML_send_channel_nack (ch->root, ch->lid_root);
720} 789}
721 790
722 791
723/** 792/**
724 * We haven't received an ACK after a certain time: restransmit the message. 793 * Compute and send the current #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK to the other peer.
725 * 794 *
726 * @param cls Closure (CadetChannelReliability with the message to restransmit) 795 * @param ch channel to send the #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK for
727 */ 796 */
728static void 797static void
729channel_retransmit_message (void *cls) 798send_channel_data_ack (struct CadetChannel *ch)
730{ 799{
731 struct CadetChannelReliability *rel = cls; 800 struct GNUNET_CADET_ChannelDataAckMessage msg;
732 struct CadetReliableMessage *copy;
733 struct CadetChannel *ch;
734 struct GNUNET_CADET_ChannelAppDataMessage *payload;
735 int fwd;
736
737 rel->retry_task = NULL;
738 ch = rel->ch;
739 copy = rel->head_sent;
740 if (NULL == copy)
741 {
742 GNUNET_break (0); // FIXME tripped in rps testcase
743 return;
744 }
745
746 payload = (struct GNUNET_CADET_ChannelAppDataMessage *) &copy[1];
747 fwd = (rel == ch->root_rel);
748
749 /* Message not found in the queue that we are going to use. */
750 LOG (GNUNET_ERROR_TYPE_DEBUG, "RETRANSMIT MID %u\n", copy->mid);
751 801
752 GCCH_send_prebuilt_message (&payload->header, ch, fwd, copy); 802 if (GNUNET_NO == ch->reliable)
753 GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO); 803 return; /* no ACKs */
804 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK);
805 msg.header.size = htons (sizeof (msg));
806 msg.ctn = ch->ctn;
807 msg.mid.mid = htonl (ntohl (ch->mid_recv.mid));
808 msg.futures = GNUNET_htonll (ch->mid_futures);
809 LOG (GNUNET_ERROR_TYPE_DEBUG,
810 "Sending DATA_ACK %u:%llX via %s\n",
811 (unsigned int) ntohl (msg.mid.mid),
812 (unsigned long long) ch->mid_futures,
813 GCCH_2s (ch));
814 if (NULL != ch->last_control_qe)
815 GCT_send_cancel (ch->last_control_qe);
816 ch->last_control_qe = GCT_send (ch->t,
817 &msg.header,
818 &send_ack_cb,
819 ch);
754} 820}
755 821
756 822
757/** 823/**
758 * We haven't received an Channel ACK after a certain time: resend the CREATE. 824 * Send our initial #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the
825 * connection is up.
759 * 826 *
760 * @param cls Closure (CadetChannelReliability of the channel to recreate) 827 * @param cls the `struct CadetChannel`
761 */ 828 */
762static void 829static void
763channel_recreate (void *cls) 830send_open_ack (void *cls)
764{ 831{
765 struct CadetChannelReliability *rel = cls; 832 struct CadetChannel *ch = cls;
766 833 struct GNUNET_CADET_ChannelManageMessage msg;
767 rel->retry_task = NULL;
768 LOG (GNUNET_ERROR_TYPE_DEBUG, "RE-CREATE\n");
769 GNUNET_STATISTICS_update (stats,
770 "# data retransmitted", 1, GNUNET_NO);
771 834
772 if (rel == rel->ch->root_rel) 835 ch->retry_control_task = NULL;
773 { 836 LOG (GNUNET_ERROR_TYPE_DEBUG,
774 send_create (rel->ch); 837 "Sending CHANNEL_OPEN_ACK on %s\n",
775 } 838 GCCH_2s (ch));
776 else if (rel == rel->ch->dest_rel) 839 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK);
777 { 840 msg.header.size = htons (sizeof (msg));
778 send_ack (rel->ch, GNUNET_YES); 841 msg.reserved = htonl (0);
779 } 842 msg.ctn = ch->ctn;
780 else 843 if (NULL != ch->last_control_qe)
781 { 844 GCT_send_cancel (ch->last_control_qe);
782 GNUNET_break (0); 845 ch->last_control_qe = GCT_send (ch->t,
783 } 846 &msg.header,
847 &send_ack_cb,
848 ch);
784} 849}
785 850
786 851
787/** 852/**
788 * Message has been sent: start retransmission timer. 853 * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for
854 * this channel. If the binding was successful, (re)transmit the
855 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.
789 * 856 *
790 * @param cls Closure (queue structure). 857 * @param ch channel that got the duplicate open
791 * @param t Tunnel. 858 * @param cti identifier of the connection that delivered the message
792 * @param q Queue handler (no longer valid).
793 * @param type Type of message.
794 * @param size Size of the message.
795 */ 859 */
796static void 860void
797ch_message_sent (void *cls, 861GCCH_handle_duplicate_open (struct CadetChannel *ch,
798 struct CadetTunnel *t, 862 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
799 struct CadetTunnelQueue *q,
800 uint16_t type, size_t size)
801{ 863{
802 struct CadetChannelQueue *chq = cls; 864 if (NULL == ch->dest)
803 struct CadetReliableMessage *copy = chq->copy;
804 struct CadetChannelReliability *rel;
805
806 LOG (GNUNET_ERROR_TYPE_DEBUG, "channel_message_sent callback %s\n",
807 GC_m2s (chq->type));
808
809 switch (chq->type)
810 { 865 {
811 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA: 866 LOG (GNUNET_ERROR_TYPE_DEBUG,
812 LOG (GNUNET_ERROR_TYPE_DEBUG, "data MID %u sent\n", copy->mid); 867 "Ignoring duplicate CHANNEL_OPEN on %s: port is closed\n",
813 GNUNET_assert (chq == copy->chq); 868 GCCH_2s (ch));
814 copy->timestamp = GNUNET_TIME_absolute_get (); 869 return;
815 rel = copy->rel;
816 if (NULL == rel->retry_task)
817 {
818 LOG (GNUNET_ERROR_TYPE_DEBUG, " scheduling retry in %d * %s\n",
819 CADET_RETRANSMIT_MARGIN,
820 GNUNET_STRINGS_relative_time_to_string (rel->expected_delay,
821 GNUNET_YES));
822 if (0 != rel->expected_delay.rel_value_us)
823 {
824 rel->retry_timer =
825 GNUNET_TIME_relative_saturating_multiply (rel->expected_delay,
826 CADET_RETRANSMIT_MARGIN);
827 }
828 else
829 {
830 rel->retry_timer = CADET_RETRANSMIT_TIME;
831 }
832 LOG (GNUNET_ERROR_TYPE_DEBUG, " using delay %s\n",
833 GNUNET_STRINGS_relative_time_to_string (rel->retry_timer,
834 GNUNET_NO));
835 rel->retry_task =
836 GNUNET_SCHEDULER_add_delayed (rel->retry_timer,
837 &channel_retransmit_message, rel);
838 }
839 else
840 {
841 LOG (GNUNET_ERROR_TYPE_DEBUG, "retry running %p\n", rel->retry_task);
842 }
843 copy->chq = NULL;
844 break;
845
846
847 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
848 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
849 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
850 LOG (GNUNET_ERROR_TYPE_DEBUG, "sent %s\n", GC_m2s (chq->type));
851 rel = chq->rel;
852 GNUNET_assert (rel->uniq == chq);
853 rel->uniq = NULL;
854
855 if (CADET_CHANNEL_READY != rel->ch->state
856 && GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK != type
857 && GNUNET_NO == rel->ch->destroy)
858 {
859 GNUNET_assert (NULL == rel->retry_task);
860 LOG (GNUNET_ERROR_TYPE_DEBUG, "STD BACKOFF %s\n",
861 GNUNET_STRINGS_relative_time_to_string (rel->retry_timer,
862 GNUNET_NO));
863 rel->retry_timer = GNUNET_TIME_STD_BACKOFF (rel->retry_timer);
864 rel->retry_task = GNUNET_SCHEDULER_add_delayed (rel->retry_timer,
865 &channel_recreate, rel);
866 }
867 break;
868
869 default:
870 GNUNET_break (0);
871 } 870 }
872 871 if (NULL != ch->retry_control_task)
873 GNUNET_free (chq); 872 {
873 LOG (GNUNET_ERROR_TYPE_DEBUG,
874 "Ignoring duplicate CHANNEL_OPEN on %s: control message is pending\n",
875 GCCH_2s (ch));
876 return;
877 }
878 LOG (GNUNET_ERROR_TYPE_DEBUG,
879 "Retransmitting CHANNEL_OPEN_ACK on %s\n",
880 GCCH_2s (ch));
881 ch->retry_control_task
882 = GNUNET_SCHEDULER_add_now (&send_open_ack,
883 ch);
874} 884}
875 885
876 886
877/** 887/**
878 * send a channel create message. 888 * Send a #GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK to the client to solicit more messages.
879 * 889 *
880 * @param ch Channel for which to send. 890 * @param ch channel the ack is for
891 * @param to_owner #GNUNET_YES to send to owner,
892 * #GNUNET_NO to send to dest
881 */ 893 */
882static void 894static void
883send_create (struct CadetChannel *ch) 895send_ack_to_client (struct CadetChannel *ch,
896 int to_owner)
884{ 897{
885 struct GNUNET_CADET_ChannelOpenMessage msgcc; 898 struct GNUNET_MQ_Envelope *env;
899 struct GNUNET_CADET_LocalAck *ack;
900 struct CadetChannelClient *ccc;
886 901
887 msgcc.header.size = htons (sizeof (msgcc)); 902 ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest;
888 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN); 903 if (NULL == ccc)
889 msgcc.ctn = ch->gid; 904 {
890 msgcc.port = ch->port; 905 /* This can happen if we are just getting ACKs after
891 msgcc.opt = htonl (channel_get_options (ch)); 906 our local client already disconnected. */
892 907 GNUNET_assert (GNUNET_YES == ch->destroy);
893 GCCH_send_prebuilt_message (&msgcc.header, ch, GNUNET_YES, NULL); 908 return;
909 }
910 env = GNUNET_MQ_msg (ack,
911 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
912 ack->ccn = ccc->ccn;
913 LOG (GNUNET_ERROR_TYPE_DEBUG,
914 "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n",
915 GSC_2s (ccc->c),
916 (GNUNET_YES == to_owner) ? "owner" : "dest",
917 ntohl (ack->ccn.channel_of_client),
918 ch->pending_messages,
919 ch->max_pending_messages);
920 GSC_send_to_client (ccc->c,
921 env);
894} 922}
895 923
896 924
897/** 925/**
898 * Confirm we got a channel create or FWD ack. 926 * A client is bound to the port that we have a channel
927 * open to. Send the acknowledgement for the connection
928 * request and establish the link with the client.
899 * 929 *
900 * @param ch The channel to confirm. 930 * @param ch open incoming channel
901 * @param fwd Should we send a FWD ACK? (going dest->root) 931 * @param c client listening on the respective port
902 */ 932 */
903static void 933void
904send_ack (struct CadetChannel *ch, int fwd) 934GCCH_bind (struct CadetChannel *ch,
935 struct CadetClient *c)
905{ 936{
906 struct GNUNET_CADET_ChannelManageMessage msg; 937 uint32_t options;
938 struct CadetChannelClient *cccd;
907 939
908 msg.header.size = htons (sizeof (msg));
909 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK);
910 LOG (GNUNET_ERROR_TYPE_DEBUG, 940 LOG (GNUNET_ERROR_TYPE_DEBUG,
911 " sending channel %s ack for channel %s\n", 941 "Binding %s from %s to port %s of %s\n",
912 GC_f2s (fwd), GCCH_2s (ch)); 942 GCCH_2s (ch),
913 943 GCT_2s (ch->t),
914 msg.ctn =ch->gid; 944 GNUNET_h2s (&ch->port),
915 GCCH_send_prebuilt_message (&msg.header, ch, !fwd, NULL); 945 GSC_2s (c));
946 if (NULL != ch->retry_control_task)
947 {
948 /* there might be a timeout task here */
949 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
950 ch->retry_control_task = NULL;
951 }
952 options = 0;
953 if (ch->nobuffer)
954 options |= GNUNET_CADET_OPTION_NOBUFFER;
955 if (ch->reliable)
956 options |= GNUNET_CADET_OPTION_RELIABLE;
957 if (ch->out_of_order)
958 options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
959 cccd = GNUNET_new (struct CadetChannelClient);
960 GNUNET_assert (NULL == ch->dest);
961 ch->dest = cccd;
962 cccd->c = c;
963 cccd->client_ready = GNUNET_YES;
964 cccd->ccn = GSC_bind (c,
965 ch,
966 (GNUNET_YES == ch->is_loopback)
967 ? GCP_get (&my_full_id,
968 GNUNET_YES)
969 : GCT_get_destination (ch->t),
970 &ch->port,
971 options);
972 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
973 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
974 ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */
975 if (GNUNET_YES == ch->is_loopback)
976 {
977 ch->state = CADET_CHANNEL_OPEN_SENT;
978 GCCH_handle_channel_open_ack (ch,
979 NULL);
980 }
981 else
982 {
983 /* notify other peer that we accepted the connection */
984 ch->state = CADET_CHANNEL_READY;
985 ch->retry_control_task
986 = GNUNET_SCHEDULER_add_now (&send_open_ack,
987 ch);
988 }
989 /* give client it's initial supply of ACKs */
990 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
991 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
992 for (unsigned int i=0;i<ch->max_pending_messages;i++)
993 send_ack_to_client (ch,
994 GNUNET_NO);
916} 995}
917 996
918 997
919/** 998/**
920 * Send a message and don't keep any info about it: we won't need to cancel it 999 * One of our clients has disconnected, tell the other one that we
921 * or resend it. 1000 * are finished. Done asynchronously to avoid concurrent modification
1001 * issues if this is the same client.
922 * 1002 *
923 * @param msg Header of the message to fire away. 1003 * @param cls the `struct CadetChannel` where one of the ends is now dead
924 * @param ch Channel on which the message should go.
925 * @param force Is this a forced (undroppable) message?
926 */ 1004 */
927static void 1005static void
928fire_and_forget (const struct GNUNET_MessageHeader *msg, 1006signal_remote_destroy_cb (void *cls)
929 struct CadetChannel *ch,
930 int force)
931{ 1007{
932 GNUNET_break (NULL == 1008 struct CadetChannel *ch = cls;
933 GCT_send_prebuilt_message (msg, ch->t, NULL, 1009 struct CadetChannelClient *ccc;
934 force, NULL, NULL)); 1010
1011 /* Find which end is left... */
1012 ch->retry_control_task = NULL;
1013 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1014 GSC_handle_remote_channel_destroy (ccc->c,
1015 ccc->ccn,
1016 ch);
1017 channel_destroy (ch);
935} 1018}
936 1019
937 1020
938/** 1021/**
939 * Notify that a channel create didn't succeed. 1022 * Destroy locally created channel. Called by the local client, so no
1023 * need to tell the client.
940 * 1024 *
941 * @param ch The channel to reject. 1025 * @param ch channel to destroy
1026 * @param c client that caused the destruction
1027 * @param ccn client number of the client @a c
942 */ 1028 */
943static void 1029void
944send_nack (struct CadetChannel *ch) 1030GCCH_channel_local_destroy (struct CadetChannel *ch,
1031 struct CadetClient *c,
1032 struct GNUNET_CADET_ClientChannelNumber ccn)
945{ 1033{
946 struct GNUNET_CADET_ChannelManageMessage msg;
947
948 msg.header.size = htons (sizeof (msg));
949 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED);
950 LOG (GNUNET_ERROR_TYPE_DEBUG, 1034 LOG (GNUNET_ERROR_TYPE_DEBUG,
951 " sending channel NACK for channel %s\n", 1035 "%s asks for destruction of %s\n",
1036 GSC_2s (c),
952 GCCH_2s (ch)); 1037 GCCH_2s (ch));
1038 GNUNET_assert (NULL != c);
1039 if ( (NULL != ch->owner) &&
1040 (c == ch->owner->c) &&
1041 (ccn.channel_of_client == ch->owner->ccn.channel_of_client) )
1042 {
1043 free_channel_client (ch->owner);
1044 ch->owner = NULL;
1045 }
1046 else if ( (NULL != ch->dest) &&
1047 (c == ch->dest->c) &&
1048 (ccn.channel_of_client == ch->dest->ccn.channel_of_client) )
1049 {
1050 free_channel_client (ch->dest);
1051 ch->dest = NULL;
1052 }
1053 else
1054 {
1055 GNUNET_assert (0);
1056 }
953 1057
954 msg.ctn = ch->gid; 1058 if (GNUNET_YES == ch->destroy)
955 GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL);
956}
957
958
959/**
960 * Destroy all reliable messages queued for a channel,
961 * during a channel destruction.
962 * Frees the reliability structure itself.
963 *
964 * @param rel Reliability data for a channel.
965 */
966static void
967channel_rel_free_all (struct CadetChannelReliability *rel)
968{
969 struct CadetReliableMessage *copy;
970 struct CadetReliableMessage *next;
971
972 if (NULL == rel)
973 return;
974
975 for (copy = rel->head_recv; NULL != copy; copy = next)
976 { 1059 {
977 next = copy->next; 1060 /* other end already destroyed, with the local client gone, no need
978 GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy); 1061 to finish transmissions, just destroy immediately. */
979 LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE ALL RECV %p\n", copy); 1062 channel_destroy (ch);
980 GNUNET_break (NULL == copy->chq); 1063 return;
981 GNUNET_free (copy);
982 } 1064 }
983 for (copy = rel->head_sent; NULL != copy; copy = next) 1065 if ( (NULL != ch->head_sent) &&
1066 ( (NULL != ch->owner) ||
1067 (NULL != ch->dest) ) )
984 { 1068 {
985 next = copy->next; 1069 /* Wait for other end to destroy us as well,
986 GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy); 1070 and otherwise allow send queue to be transmitted first */
987 LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE ALL SEND %p\n", copy); 1071 ch->destroy = GNUNET_YES;
988 if (NULL != copy->chq) 1072 return;
989 {
990 if (NULL != copy->chq->tq)
991 {
992 GCT_cancel (copy->chq->tq);
993 /* ch_message_sent will free copy->q */
994 }
995 else
996 {
997 GNUNET_free (copy->chq);
998 GNUNET_break (0);
999 }
1000 }
1001 GNUNET_free (copy);
1002 } 1073 }
1003 if (NULL != rel->uniq && NULL != rel->uniq->tq) 1074 if ( (GNUNET_YES == ch->is_loopback) &&
1075 ( (NULL != ch->owner) ||
1076 (NULL != ch->dest) ) )
1004 { 1077 {
1005 GCT_cancel (rel->uniq->tq); 1078 if (NULL != ch->retry_control_task)
1006 /* ch_message_sent is called freeing uniq */ 1079 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1080 ch->retry_control_task
1081 = GNUNET_SCHEDULER_add_now (&signal_remote_destroy_cb,
1082 ch);
1083 return;
1007 } 1084 }
1008 if (NULL != rel->retry_task) 1085 if (GNUNET_NO == ch->is_loopback)
1009 { 1086 {
1010 GNUNET_SCHEDULER_cancel (rel->retry_task); 1087 /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */
1011 rel->retry_task = NULL; 1088 switch (ch->state)
1089 {
1090 case CADET_CHANNEL_NEW:
1091 /* We gave up on a channel that we created as a client to a remote
1092 target, but that never went anywhere. Nothing to do here. */
1093 break;
1094 case CADET_CHANNEL_LOOSE:
1095 GSC_drop_loose_channel (&ch->port,
1096 ch);
1097 break;
1098 default:
1099 GCT_send_channel_destroy (ch->t,
1100 ch->ctn);
1101 }
1012 } 1102 }
1013 GNUNET_free (rel); 1103 /* Nothing left to do, just finish destruction */
1104 channel_destroy (ch);
1014} 1105}
1015 1106
1016 1107
1017/** 1108/**
1018 * Mark future messages as ACK'd. 1109 * We got an acknowledgement for the creation of the channel
1019 * 1110 * (the port is open on the other side). Begin transmissions.
1020 * @param rel Reliability data.
1021 * @param msg DataACK message with a bitfield of future ACK'd messages.
1022 * 1111 *
1023 * @return How many messages have been freed. 1112 * @param ch channel to destroy
1113 * @param cti identifier of the connection that delivered the message
1024 */ 1114 */
1025static unsigned int 1115void
1026channel_rel_free_sent (struct CadetChannelReliability *rel, 1116GCCH_handle_channel_open_ack (struct CadetChannel *ch,
1027 const struct GNUNET_CADET_ChannelDataAckMessage *msg) 1117 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
1028{ 1118{
1029 struct CadetReliableMessage *copy; 1119 switch (ch->state)
1030 struct CadetReliableMessage *next;
1031 uint64_t bitfield;
1032 uint64_t mask;
1033 uint32_t mid;
1034 uint32_t target;
1035 unsigned int i;
1036 unsigned int r;
1037
1038 bitfield = msg->futures;
1039 mid = ntohl (msg->mid);
1040 LOG (GNUNET_ERROR_TYPE_DEBUG, "free_sent_reliable %u %lX\n", mid, bitfield);
1041 LOG (GNUNET_ERROR_TYPE_DEBUG, " rel %p, head %p\n", rel, rel->head_sent);
1042 for (i = 0, r = 0, copy = rel->head_sent;
1043 i < 64 && NULL != copy && 0 != bitfield;
1044 i++)
1045 { 1120 {
1046 LOG (GNUNET_ERROR_TYPE_DEBUG, " trying bit %u (mid %u)\n", i, mid + i + 1); 1121 case CADET_CHANNEL_NEW:
1047 mask = 0x1LL << i; 1122 /* this should be impossible */
1048 if (0 == (bitfield & mask)) 1123 GNUNET_break (0);
1049 continue; 1124 break;
1050 1125 case CADET_CHANNEL_LOOSE:
1051 LOG (GNUNET_ERROR_TYPE_DEBUG, " set!\n"); 1126 /* This makes no sense. */
1052 /* Bit was set, clear the bit from the bitfield */ 1127 GNUNET_break_op (0);
1053 bitfield &= ~mask; 1128 break;
1054 1129 case CADET_CHANNEL_OPEN_SENT:
1055 /* The i-th bit was set. Do we have that copy? */ 1130 if (NULL == ch->owner)
1056 /* Skip copies with mid < target */
1057 target = mid + i + 1;
1058 LOG (GNUNET_ERROR_TYPE_DEBUG, " target %u\n", target);
1059 while (NULL != copy && GC_is_pid_bigger (target, copy->mid))
1060 copy = copy->next;
1061
1062 /* Did we run out of copies? (previously freed, it's ok) */
1063 if (NULL == copy)
1064 { 1131 {
1065 LOG (GNUNET_ERROR_TYPE_DEBUG, "run out of copies...\n"); 1132 /* We're not the owner, wrong direction! */
1066 return r; 1133 GNUNET_break_op (0);
1134 return;
1067 } 1135 }
1068 1136 LOG (GNUNET_ERROR_TYPE_DEBUG,
1069 /* Did we overshoot the target? (previously freed, it's ok) */ 1137 "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n",
1070 if (GC_is_pid_bigger (copy->mid, target)) 1138 GCCH_2s (ch));
1139 if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */
1071 { 1140 {
1072 LOG (GNUNET_ERROR_TYPE_DEBUG, " next copy %u\n", copy->mid); 1141 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1073 i += copy->mid - target - 1; /* MID: 90, t = 85, i += 4 (i++ later) */ 1142 ch->retry_control_task = NULL;
1074 mask = (0x1LL << (i + 1)) - 1; /* Mask = i-th bit and all before */
1075 bitfield &= ~mask; /* Clear all bits up to MID - 1 */
1076 continue;
1077 } 1143 }
1078 1144 ch->state = CADET_CHANNEL_READY;
1079 /* Now copy->mid == target, free it */ 1145 /* On first connect, send client as many ACKs as we allow messages
1080 next = copy->next; 1146 to be buffered! */
1081 GNUNET_break (GNUNET_YES != rel_message_free (copy, GNUNET_YES)); 1147 for (unsigned int i=0;i<ch->max_pending_messages;i++)
1082 r++; 1148 send_ack_to_client (ch,
1083 copy = next; 1149 GNUNET_YES);
1150 break;
1151 case CADET_CHANNEL_READY:
1152 /* duplicate ACK, maybe we retried the CREATE. Ignore. */
1153 LOG (GNUNET_ERROR_TYPE_DEBUG,
1154 "Received duplicate channel OPEN_ACK for %s\n",
1155 GCCH_2s (ch));
1156 GNUNET_STATISTICS_update (stats,
1157 "# duplicate CREATE_ACKs",
1158 1,
1159 GNUNET_NO);
1160 break;
1084 } 1161 }
1085 LOG (GNUNET_ERROR_TYPE_DEBUG, "free_sent_reliable END\n");
1086 return r;
1087} 1162}
1088 1163
1089 1164
1090/** 1165/**
1091 * Destroy a reliable message after it has been acknowledged, either by 1166 * Test if element @a e1 comes before element @a e2.
1092 * direct mid ACK or bitfield. Updates the appropriate data structures and
1093 * timers and frees all memory.
1094 * 1167 *
1095 * @param copy Message that is no longer needed: remote peer got it. 1168 * @param cls closure, to a flag where we indicate duplicate packets
1096 * @param update_time Is the timing information relevant? 1169 * @param m1 a message of to sort
1097 * If this message is ACK in a batch the timing information 1170 * @param m2 another message to sort
1098 * is skewed by the retransmission, count only for the 1171 * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO
1099 * retransmitted message.
1100 *
1101 * @return #GNUNET_YES if channel was destroyed as a result of the call,
1102 * #GNUNET_NO otherwise.
1103 */ 1172 */
1104static int 1173static int
1105rel_message_free (struct CadetReliableMessage *copy, int update_time) 1174is_before (void *cls,
1175 struct CadetOutOfOrderMessage *m1,
1176 struct CadetOutOfOrderMessage *m2)
1106{ 1177{
1107 struct CadetChannelReliability *rel; 1178 int *duplicate = cls;
1108 struct GNUNET_TIME_Relative time; 1179 uint32_t v1 = ntohl (m1->mid.mid);
1180 uint32_t v2 = ntohl (m2->mid.mid);
1181 uint32_t delta;
1109 1182
1110 rel = copy->rel; 1183 delta = v2 - v1;
1111 LOG (GNUNET_ERROR_TYPE_DEBUG, "Freeing %u\n", copy->mid); 1184 if (0 == delta)
1112 if (GNUNET_YES == update_time) 1185 *duplicate = GNUNET_YES;
1186 if (delta > (uint32_t) INT_MAX)
1113 { 1187 {
1114 time = GNUNET_TIME_absolute_get_duration (copy->timestamp); 1188 /* in overflow range, we can safely assume we wrapped around */
1115 if (0 == rel->expected_delay.rel_value_us) 1189 return GNUNET_NO;
1116 rel->expected_delay = time;
1117 else
1118 {
1119 rel->expected_delay.rel_value_us *= 7;
1120 rel->expected_delay.rel_value_us += time.rel_value_us;
1121 rel->expected_delay.rel_value_us /= 8;
1122 }
1123 LOG (GNUNET_ERROR_TYPE_DEBUG, " message time %12s\n",
1124 GNUNET_STRINGS_relative_time_to_string (time, GNUNET_NO));
1125 LOG (GNUNET_ERROR_TYPE_DEBUG, " new delay %12s\n",
1126 GNUNET_STRINGS_relative_time_to_string (rel->expected_delay,
1127 GNUNET_NO));
1128 rel->retry_timer = rel->expected_delay;
1129 } 1190 }
1130 else 1191 else
1131 { 1192 {
1132 LOG (GNUNET_ERROR_TYPE_DEBUG, "batch free, ignoring timing\n"); 1193 /* result is small, thus v2 > v1, thus m1 < m2 */
1133 }
1134 rel->ch->pending_messages--;
1135 if (NULL != copy->chq)
1136 {
1137 GCT_cancel (copy->chq->tq);
1138 /* copy->q is set to NULL by ch_message_sent */
1139 }
1140 GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy);
1141 LOG (GNUNET_ERROR_TYPE_DEBUG, " free send copy MID %u at %p\n",
1142 copy->mid, copy);
1143 GNUNET_free (copy);
1144
1145 if (GNUNET_NO != rel->ch->destroy && 0 == rel->ch->pending_messages)
1146 {
1147 GCCH_destroy (rel->ch);
1148 return GNUNET_YES; 1194 return GNUNET_YES;
1149 } 1195 }
1150 return GNUNET_NO;
1151} 1196}
1152 1197
1153 1198
1154/** 1199/**
1155 * Channel was ACK'd by remote peer, mark as ready and cancel retransmission. 1200 * We got payload data for a channel. Pass it on to the client
1201 * and send an ACK to the other end (once flow control allows it!)
1156 * 1202 *
1157 * @param ch Channel to mark as ready. 1203 * @param ch channel that got data
1158 * @param fwd Was the ACK message a FWD ACK? (dest->root, SYNACK) 1204 * @param cti identifier of the connection that delivered the message
1205 * @param msg message that was received
1159 */ 1206 */
1160static void 1207void
1161channel_confirm (struct CadetChannel *ch, int fwd) 1208GCCH_handle_channel_plaintext_data (struct CadetChannel *ch,
1209 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1210 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
1162{ 1211{
1163 struct CadetChannelReliability *rel; 1212 struct GNUNET_MQ_Envelope *env;
1164 enum CadetChannelState oldstate; 1213 struct GNUNET_CADET_LocalData *ld;
1165 1214 struct CadetChannelClient *ccc;
1166 rel = fwd ? ch->root_rel : ch->dest_rel; 1215 size_t payload_size;
1167 if (NULL == rel) 1216 struct CadetOutOfOrderMessage *com;
1217 int duplicate;
1218 uint32_t mid_min;
1219 uint32_t mid_max;
1220 uint32_t mid_msg;
1221 uint32_t delta;
1222
1223 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1224 if ( (GNUNET_YES == ch->destroy) &&
1225 (NULL == ch->owner) &&
1226 (NULL == ch->dest) )
1227 {
1228 /* This client is gone, but we still have messages to send to
1229 the other end (which is why @a ch is not yet dead). However,
1230 we cannot pass messages to our client anymore. */
1231 LOG (GNUNET_ERROR_TYPE_DEBUG,
1232 "Dropping incoming payload on %s as this end is already closed\n",
1233 GCCH_2s (ch));
1234 /* send back DESTROY notification to stop further retransmissions! */
1235 GCT_send_channel_destroy (ch->t,
1236 ch->ctn);
1237 return;
1238 }
1239 payload_size = ntohs (msg->header.size) - sizeof (*msg);
1240 env = GNUNET_MQ_msg_extra (ld,
1241 payload_size,
1242 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1243 ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn;
1244 GNUNET_memcpy (&ld[1],
1245 &msg[1],
1246 payload_size);
1247 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1248 if ( (GNUNET_YES == ccc->client_ready) &&
1249 ( (GNUNET_YES == ch->out_of_order) ||
1250 (msg->mid.mid == ch->mid_recv.mid) ) )
1168 { 1251 {
1169 GNUNET_break (GNUNET_NO != ch->destroy); 1252 LOG (GNUNET_ERROR_TYPE_DEBUG,
1253 "Giving %u bytes of payload with MID %u from %s to client %s\n",
1254 (unsigned int) payload_size,
1255 ntohl (msg->mid.mid),
1256 GCCH_2s (ch),
1257 GSC_2s (ccc->c));
1258 ccc->client_ready = GNUNET_NO;
1259 GSC_send_to_client (ccc->c,
1260 env);
1261 ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid));
1262 ch->mid_futures >>= 1;
1263 send_channel_data_ack (ch);
1170 return; 1264 return;
1171 } 1265 }
1172 LOG (GNUNET_ERROR_TYPE_DEBUG, " channel confirm %s %s\n",
1173 GC_f2s (fwd), GCCH_2s (ch));
1174 oldstate = ch->state;
1175 ch->state = CADET_CHANNEL_READY;
1176 1266
1177 if (CADET_CHANNEL_READY != oldstate || GNUNET_YES == is_loopback (ch)) 1267 if (GNUNET_YES == ch->reliable)
1178 { 1268 {
1179 rel->client_ready = GNUNET_YES; 1269 /* check if message ought to be dropped because it is ancient/too distant/duplicate */
1180 rel->expected_delay = rel->retry_timer; 1270 mid_min = ntohl (ch->mid_recv.mid);
1181 LOG (GNUNET_ERROR_TYPE_DEBUG, " confirm retry timer %s\n", 1271 mid_max = mid_min + ch->max_pending_messages;
1182 GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, GNUNET_NO)); 1272 mid_msg = ntohl (msg->mid.mid);
1183 if (GCT_get_connections_buffer (ch->t) > 0 || GCT_is_loopback (ch->t)) 1273 if ( ( (uint32_t) (mid_msg - mid_min) > ch->max_pending_messages) ||
1184 send_client_ack (ch, fwd); 1274 ( (uint32_t) (mid_max - mid_msg) > ch->max_pending_messages) )
1185
1186 if (NULL != rel->retry_task)
1187 { 1275 {
1188 GNUNET_SCHEDULER_cancel (rel->retry_task); 1276 LOG (GNUNET_ERROR_TYPE_DEBUG,
1189 rel->retry_task = NULL; 1277 "%s at %u drops ancient or far-future message %u\n",
1190 } 1278 GCCH_2s (ch),
1191 else if (NULL != rel->uniq) 1279 (unsigned int) mid_min,
1192 { 1280 ntohl (msg->mid.mid));
1193 GCT_cancel (rel->uniq->tq); 1281
1194 /* ch_message_sent will free and NULL uniq */ 1282 GNUNET_STATISTICS_update (stats,
1283 "# duplicate DATA (ancient or future)",
1284 1,
1285 GNUNET_NO);
1286 GNUNET_MQ_discard (env);
1287 send_channel_data_ack (ch);
1288 return;
1195 } 1289 }
1196 else if (GNUNET_NO == is_loopback (ch)) 1290 /* mark bit for future ACKs */
1291 delta = mid_msg - mid_min - 1; /* overflow/underflow are OK here */
1292 if (delta < 64)
1197 { 1293 {
1198 /* We SHOULD have been trying to retransmit this! */ 1294 if (0 != (ch->mid_futures & (1LLU << delta)))
1199 GNUNET_break (0); 1295 {
1296 /* Duplicate within the queue, drop also */
1297 LOG (GNUNET_ERROR_TYPE_DEBUG,
1298 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1299 (unsigned int) payload_size,
1300 GCCH_2s (ch),
1301 ntohl (msg->mid.mid));
1302 GNUNET_STATISTICS_update (stats,
1303 "# duplicate DATA",
1304 1,
1305 GNUNET_NO);
1306 GNUNET_MQ_discard (env);
1307 send_channel_data_ack (ch);
1308 return;
1309 }
1310 ch->mid_futures |= (1LLU << delta);
1311 LOG (GNUNET_ERROR_TYPE_DEBUG,
1312 "Marked bit %llX for mid %u (base: %u); now: %llX\n",
1313 (1LLU << delta),
1314 mid_msg,
1315 mid_min,
1316 ch->mid_futures);
1200 } 1317 }
1201 } 1318 }
1202 1319 else /* ! ch->reliable */
1203 /* In case of a FWD ACK (SYNACK) send a BCK ACK (ACK). */
1204 if (GNUNET_YES == fwd)
1205 send_ack (ch, GNUNET_NO);
1206}
1207
1208
1209/**
1210 * Save a copy to retransmit in case it gets lost.
1211 *
1212 * Initializes all needed callbacks and timers.
1213 *
1214 * @param ch Channel this message goes on.
1215 * @param msg Message to copy.
1216 * @param fwd Is this fwd traffic?
1217 */
1218static struct CadetReliableMessage *
1219channel_save_copy (struct CadetChannel *ch,
1220 const struct GNUNET_MessageHeader *msg,
1221 int fwd)
1222{
1223 struct CadetChannelReliability *rel;
1224 struct CadetReliableMessage *copy;
1225 uint32_t mid;
1226 uint16_t type;
1227 uint16_t size;
1228
1229 rel = fwd ? ch->root_rel : ch->dest_rel;
1230 mid = rel->mid_send - 1;
1231 type = ntohs (msg->type);
1232 size = ntohs (msg->size);
1233
1234 LOG (GNUNET_ERROR_TYPE_DEBUG, "save MID %u %s\n", mid, GC_m2s (type));
1235 copy = GNUNET_malloc (sizeof (struct CadetReliableMessage) + size);
1236 LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", copy);
1237 copy->mid = mid;
1238 copy->rel = rel;
1239 copy->type = type;
1240 GNUNET_memcpy (&copy[1], msg, size);
1241 GNUNET_CONTAINER_DLL_insert_tail (rel->head_sent, rel->tail_sent, copy);
1242 ch->pending_messages++;
1243
1244 return copy;
1245}
1246
1247
1248/**
1249 * Create a new channel.
1250 *
1251 * @param t Tunnel this channel is in.
1252 * @param owner Client that owns the channel, NULL for foreign channels.
1253 * @param lid_root Local ID for root client.
1254 *
1255 * @return A new initialized channel. NULL on error.
1256 */
1257static struct CadetChannel *
1258channel_new (struct CadetTunnel *t,
1259 struct CadetClient *owner,
1260 struct GNUNET_CADET_ClientChannelNumber lid_root)
1261{
1262 struct CadetChannel *ch;
1263
1264 ch = GNUNET_new (struct CadetChannel);
1265 ch->root = owner;
1266 ch->lid_root = lid_root;
1267 ch->t = t;
1268
1269 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
1270
1271 if (NULL != owner)
1272 {
1273 ch->gid = GCT_get_next_ctn (t);
1274 GML_channel_add (owner, lid_root, ch);
1275 }
1276 GCT_add_channel (t, ch);
1277
1278 return ch;
1279}
1280
1281
1282/**
1283 * Handle a loopback message: call the appropriate handler for the message type.
1284 *
1285 * @param ch Channel this message is on.
1286 * @param msgh Message header.
1287 * @param fwd Is this FWD traffic?
1288 */
1289void
1290handle_loopback (struct CadetChannel *ch,
1291 const struct GNUNET_MessageHeader *msgh,
1292 int fwd)
1293{
1294 uint16_t type;
1295
1296 type = ntohs (msgh->type);
1297 LOG (GNUNET_ERROR_TYPE_DEBUG,
1298 "Loopback %s %s message!\n",
1299 GC_f2s (fwd), GC_m2s (type));
1300
1301 switch (type)
1302 { 1320 {
1303 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA: 1321 /* Channel is unreliable, so we do not ACK. But we also cannot
1304 /* Don't send hop ACK, wait for client to ACK */ 1322 allow buffering everything, so check if we have space... */
1305 LOG (GNUNET_ERROR_TYPE_DEBUG, "SEND loopback %u (%u)\n", 1323 if (ccc->num_recv >= ch->max_pending_messages)
1306 ntohl (((struct GNUNET_CADET_ChannelAppDataMessage *) msgh)->mid), ntohs (msgh->size)); 1324 {
1307 GCCH_handle_data (ch, (struct GNUNET_CADET_ChannelAppDataMessage *) msgh, fwd); 1325 struct CadetOutOfOrderMessage *drop;
1308 break;
1309
1310 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
1311 GCCH_handle_data_ack (ch,
1312 (const struct GNUNET_CADET_ChannelDataAckMessage *) msgh, fwd);
1313 break;
1314
1315 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
1316 GCCH_handle_create (ch->t,
1317 (const struct GNUNET_CADET_ChannelOpenMessage *) msgh);
1318 break;
1319
1320 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
1321 GCCH_handle_ack (ch,
1322 (const struct GNUNET_CADET_ChannelManageMessage *) msgh,
1323 fwd);
1324 break;
1325
1326 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
1327 GCCH_handle_nack (ch);
1328 break;
1329
1330 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
1331 GCCH_handle_destroy (ch,
1332 (const struct GNUNET_CADET_ChannelManageMessage *) msgh,
1333 fwd);
1334 break;
1335 1326
1336 default: 1327 /* Yep, need to drop. Drop the oldest message in
1337 GNUNET_break_op (0); 1328 the buffer. */
1338 LOG (GNUNET_ERROR_TYPE_DEBUG, 1329 LOG (GNUNET_ERROR_TYPE_DEBUG,
1339 "end-to-end message not known (%u)\n", 1330 "Queue full due slow client on %s, dropping oldest message\n",
1340 ntohs (msgh->type)); 1331 GCCH_2s (ch));
1332 GNUNET_STATISTICS_update (stats,
1333 "# messages dropped due to slow client",
1334 1,
1335 GNUNET_NO);
1336 drop = ccc->head_recv;
1337 GNUNET_CONTAINER_DLL_remove (ccc->head_recv,
1338 ccc->tail_recv,
1339 drop);
1340 ccc->num_recv--;
1341 GNUNET_MQ_discard (drop->env);
1342 GNUNET_free (drop);
1343 }
1341 } 1344 }
1342}
1343
1344
1345
1346/******************************************************************************/
1347/******************************** API ***********************************/
1348/******************************************************************************/
1349
1350/**
1351 * Destroy a channel and free all resources.
1352 *
1353 * @param ch Channel to destroy.
1354 */
1355void
1356GCCH_destroy (struct CadetChannel *ch)
1357{
1358 struct CadetClient *c;
1359 struct CadetTunnel *t;
1360 1345
1361 if (NULL == ch) 1346 /* Insert message into sorted out-of-order queue */
1347 com = GNUNET_new (struct CadetOutOfOrderMessage);
1348 com->mid = msg->mid;
1349 com->env = env;
1350 duplicate = GNUNET_NO;
1351 GNUNET_CONTAINER_DLL_insert_sorted (struct CadetOutOfOrderMessage,
1352 is_before,
1353 &duplicate,
1354 ccc->head_recv,
1355 ccc->tail_recv,
1356 com);
1357 ccc->num_recv++;
1358 if (GNUNET_YES == duplicate)
1359 {
1360 /* Duplicate within the queue, drop also (this is not covered by
1361 the case above if "delta" >= 64, which could be the case if
1362 max_pending_messages is also >= 64 or if our client is unready
1363 and we are seeing retransmissions of the message our client is
1364 blocked on. */
1365 LOG (GNUNET_ERROR_TYPE_DEBUG,
1366 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1367 (unsigned int) payload_size,
1368 GCCH_2s (ch),
1369 ntohl (msg->mid.mid));
1370 GNUNET_STATISTICS_update (stats,
1371 "# duplicate DATA",
1372 1,
1373 GNUNET_NO);
1374 GNUNET_CONTAINER_DLL_remove (ccc->head_recv,
1375 ccc->tail_recv,
1376 com);
1377 ccc->num_recv--;
1378 GNUNET_MQ_discard (com->env);
1379 GNUNET_free (com);
1380 send_channel_data_ack (ch);
1362 return; 1381 return;
1363 if (2 == ch->destroy)
1364 return; /* recursive call */
1365 ch->destroy = 2;
1366
1367 LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying channel %s:%u\n",
1368 GCT_2s (ch->t), ch->gid);
1369 GCCH_debug (ch, GNUNET_ERROR_TYPE_DEBUG);
1370
1371 c = ch->root;
1372 if (NULL != c)
1373 {
1374 GML_channel_remove (c, ch->lid_root, ch);
1375 }
1376
1377 c = ch->dest;
1378 if (NULL != c)
1379 {
1380 GML_channel_remove (c, ch->lid_dest, ch);
1381 } 1382 }
1382 1383 LOG (GNUNET_ERROR_TYPE_DEBUG,
1383 channel_rel_free_all (ch->root_rel); 1384 "Queued %s payload of %u bytes on %s-%X(%p) (mid %u, need %u first)\n",
1384 channel_rel_free_all (ch->dest_rel); 1385 (GNUNET_YES == ccc->client_ready)
1385 1386 ? "out-of-order"
1386 t = ch->t; 1387 : "client-not-ready",
1387 GCT_remove_channel (t, ch); 1388 (unsigned int) payload_size,
1388 GNUNET_STATISTICS_update (stats, "# channels", -1, GNUNET_NO); 1389 GCCH_2s (ch),
1389 1390 ntohl (ccc->ccn.channel_of_client),
1390 GNUNET_free (ch); 1391 ccc,
1391 GCT_destroy_if_empty (t); 1392 ntohl (msg->mid.mid),
1392} 1393 ntohl (ch->mid_recv.mid));
1393 1394 /* NOTE: this ACK we _could_ skip, as the packet is out-of-order and
1394 1395 the sender may already be transmitting the previous one. Needs
1395/** 1396 experimental evaluation to see if/when this ACK helps or
1396 * Get the channel's public ID. 1397 hurts. (We might even want another option.) */
1397 * 1398 send_channel_data_ack (ch);
1398 * @param ch Channel.
1399 *
1400 * @return ID used to identify the channel with the remote peer.
1401 */
1402struct GNUNET_CADET_ChannelTunnelNumber
1403GCCH_get_id (const struct CadetChannel *ch)
1404{
1405 return ch->gid;
1406}
1407
1408
1409/**
1410 * Get the channel tunnel.
1411 *
1412 * @param ch Channel to get the tunnel from.
1413 *
1414 * @return tunnel of the channel.
1415 */
1416struct CadetTunnel *
1417GCCH_get_tunnel (const struct CadetChannel *ch)
1418{
1419 return ch->t;
1420}
1421
1422
1423/**
1424 * Get free buffer space towards the client on a specific channel.
1425 *
1426 * @param ch Channel.
1427 * @param fwd Is query about FWD traffic?
1428 *
1429 * @return Free buffer space [0 - 64]
1430 */
1431unsigned int
1432GCCH_get_buffer (struct CadetChannel *ch, int fwd)
1433{
1434 struct CadetChannelReliability *rel;
1435
1436 rel = fwd ? ch->dest_rel : ch->root_rel;
1437 LOG (GNUNET_ERROR_TYPE_DEBUG, " get buffer, channel %s\n", GCCH_2s (ch));
1438 GCCH_debug (ch, GNUNET_ERROR_TYPE_DEBUG);
1439 /* If rel is NULL it means that the end is not yet created,
1440 * most probably is a loopback channel at the point of sending
1441 * the ChannelCreate to itself.
1442 */
1443 if (NULL == rel)
1444 {
1445 LOG (GNUNET_ERROR_TYPE_DEBUG, " rel is NULL: max\n");
1446 return 64;
1447 }
1448
1449 LOG (GNUNET_ERROR_TYPE_DEBUG, " n_recv %d\n", rel->n_recv);
1450 return (64 - rel->n_recv);
1451}
1452
1453
1454/**
1455 * Get flow control status of end point: is client allow to send?
1456 *
1457 * @param ch Channel.
1458 * @param fwd Is query about FWD traffic? (Request root status).
1459 *
1460 * @return #GNUNET_YES if client is allowed to send us data.
1461 */
1462int
1463GCCH_get_allowed (struct CadetChannel *ch, int fwd)
1464{
1465 struct CadetChannelReliability *rel;
1466
1467 rel = fwd ? ch->root_rel : ch->dest_rel;
1468
1469 if (NULL == rel)
1470 {
1471 /* Probably shutting down: root/dest NULL'ed to mark disconnection */
1472 GNUNET_break (GNUNET_NO != ch->destroy);
1473 return 0;
1474 }
1475
1476 return rel->client_allowed;
1477} 1399}
1478 1400
1479 1401
1480/** 1402/**
1481 * Is the root client for this channel on this peer? 1403 * Function called once the tunnel has sent one of our messages.
1482 * 1404 * If the message is unreliable, simply frees the `crm`. If the
1483 * @param ch Channel. 1405 * message was reliable, calculate retransmission time and
1484 * @param fwd Is this for fwd traffic? 1406 * wait for ACK (or retransmit).
1485 * 1407 *
1486 * @return #GNUNET_YES in case it is. 1408 * @param cls the `struct CadetReliableMessage` that was sent
1409 * @param cid identifier of the connection within the tunnel, NULL
1410 * if transmission failed
1487 */ 1411 */
1488int 1412static void
1489GCCH_is_origin (struct CadetChannel *ch, int fwd) 1413data_sent_cb (void *cls,
1490{ 1414 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
1491 struct CadetClient *c;
1492
1493 c = fwd ? ch->root : ch->dest;
1494 return NULL != c;
1495}
1496 1415
1497 1416
1498/** 1417/**
1499 * Is the destination client for this channel on this peer? 1418 * We need to retry a transmission, the last one took too long to
1500 * 1419 * be acknowledged.
1501 * @param ch Channel.
1502 * @param fwd Is this for fwd traffic?
1503 * 1420 *
1504 * @return #GNUNET_YES in case it is. 1421 * @param cls the `struct CadetChannel` where we need to retransmit
1505 */ 1422 */
1506int 1423static void
1507GCCH_is_terminal (struct CadetChannel *ch, int fwd) 1424retry_transmission (void *cls)
1508{ 1425{
1509 struct CadetClient *c; 1426 struct CadetChannel *ch = cls;
1427 struct CadetReliableMessage *crm = ch->head_sent;
1510 1428
1511 c = fwd ? ch->dest : ch->root; 1429 ch->retry_data_task = NULL;
1512 return NULL != c; 1430 GNUNET_assert (NULL == crm->qe);
1431 LOG (GNUNET_ERROR_TYPE_DEBUG,
1432 "Retrying transmission on %s of message %u\n",
1433 GCCH_2s (ch),
1434 (unsigned int) ntohl (crm->data_message->mid.mid));
1435 crm->qe = GCT_send (ch->t,
1436 &crm->data_message->header,
1437 &data_sent_cb,
1438 crm);
1439 GNUNET_assert (NULL == ch->retry_data_task);
1513} 1440}
1514 1441
1515 1442
1516/** 1443/**
1517 * Send an end-to-end ACK message for the most recent in-sequence payload. 1444 * We got an PLAINTEXT_DATA_ACK for a message in our queue, remove it from
1445 * the queue and tell our client that it can send more.
1518 * 1446 *
1519 * If channel is not reliable, do nothing. 1447 * @param ch the channel that got the PLAINTEXT_DATA_ACK
1520 * 1448 * @param cti identifier of the connection that delivered the message
1521 * @param ch Channel this is about. 1449 * @param crm the message that got acknowledged
1522 * @param fwd Is for FWD traffic? (ACK dest->owner)
1523 */ 1450 */
1524void 1451static void
1525GCCH_send_data_ack (struct CadetChannel *ch, int fwd) 1452handle_matching_ack (struct CadetChannel *ch,
1453 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1454 struct CadetReliableMessage *crm)
1526{ 1455{
1527 struct GNUNET_CADET_ChannelDataAckMessage msg; 1456 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
1528 struct CadetChannelReliability *rel; 1457 ch->tail_sent,
1529 struct CadetReliableMessage *copy; 1458 crm);
1530 unsigned int delta; 1459 ch->pending_messages--;
1531 uint64_t mask; 1460 GNUNET_assert (ch->pending_messages < ch->max_pending_messages);
1532 uint32_t ack; 1461 LOG (GNUNET_ERROR_TYPE_DEBUG,
1533 1462 "Received DATA_ACK on %s for message %u (%u ACKs pending)\n",
1534 if (GNUNET_NO == ch->reliable) 1463 GCCH_2s (ch),
1535 return; 1464 (unsigned int) ntohl (crm->data_message->mid.mid),
1536 1465 ch->pending_messages);
1537 rel = fwd ? ch->dest_rel : ch->root_rel; 1466 if (NULL != crm->qe)
1538 ack = rel->mid_recv - 1; 1467 {
1539 1468 GCT_send_cancel (crm->qe);
1540 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK); 1469 crm->qe = NULL;
1541 msg.header.size = htons (sizeof (msg)); 1470 }
1542 msg.ctn = ch->gid; 1471 if ( (1 == crm->num_transmissions) &&
1543 msg.mid = htonl (ack); 1472 (NULL != cti) )
1544 1473 {
1545 msg.futures = 0LL; 1474 GCC_ack_observed (cti);
1546 for (copy = rel->head_recv; NULL != copy; copy = copy->next) 1475 if (0 == memcmp (cti,
1547 { 1476 &crm->connection_taken,
1548 if (copy->type != GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA) 1477 sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier)))
1549 { 1478 {
1550 LOG (GNUNET_ERROR_TYPE_DEBUG, " Type %s, expected DATA\n", 1479 GCC_latency_observed (cti,
1551 GC_m2s (copy->type)); 1480 GNUNET_TIME_absolute_get_duration (crm->first_transmission_time));
1552 continue;
1553 } 1481 }
1554 GNUNET_assert (GC_is_pid_bigger(copy->mid, ack));
1555 delta = copy->mid - (ack + 1);
1556 if (63 < delta)
1557 break;
1558 mask = 0x1LL << delta;
1559 msg.futures |= mask;
1560 LOG (GNUNET_ERROR_TYPE_DEBUG,
1561 " setting bit for %u (delta %u) (%lX) -> %lX\n",
1562 copy->mid, delta, mask, msg.futures);
1563 } 1482 }
1564 1483 GNUNET_free (crm->data_message);
1565 GCCH_send_prebuilt_message (&msg.header, ch, !fwd, NULL); 1484 GNUNET_free (crm);
1566 LOG (GNUNET_ERROR_TYPE_DEBUG, "send_data_ack END\n"); 1485 send_ack_to_client (ch,
1486 (NULL == ch->owner)
1487 ? GNUNET_NO
1488 : GNUNET_YES);
1567} 1489}
1568 1490
1569 1491
1570/** 1492/**
1571 * Allow a client to send us more data, in case it was choked. 1493 * We got an acknowledgement for payload data for a channel.
1494 * Possibly resume transmissions.
1572 * 1495 *
1573 * @param ch Channel. 1496 * @param ch channel that got the ack
1574 * @param fwd Is this about FWD traffic? (Root client). 1497 * @param cti identifier of the connection that delivered the message
1498 * @param ack details about what was received
1575 */ 1499 */
1576void 1500void
1577GCCH_allow_client (struct CadetChannel *ch, int fwd) 1501GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch,
1502 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1503 const struct GNUNET_CADET_ChannelDataAckMessage *ack)
1578{ 1504{
1579 struct CadetChannelReliability *rel; 1505 struct CadetReliableMessage *crm;
1580 unsigned int buffer; 1506 struct CadetReliableMessage *crmn;
1581 1507 int found;
1582 LOG (GNUNET_ERROR_TYPE_DEBUG, "GMCH allow\n"); 1508 uint32_t mid_base;
1509 uint64_t mid_mask;
1510 unsigned int delta;
1583 1511
1584 if (CADET_CHANNEL_READY != ch->state) 1512 GNUNET_break (GNUNET_NO == ch->is_loopback);
1513 if (GNUNET_NO == ch->reliable)
1585 { 1514 {
1586 LOG (GNUNET_ERROR_TYPE_DEBUG, " channel not ready yet!\n"); 1515 /* not expecting ACKs on unreliable channel, odd */
1516 GNUNET_break_op (0);
1587 return; 1517 return;
1588 } 1518 }
1589 1519 /* mid_base is the MID of the next message that the
1590 if (GNUNET_YES == ch->reliable) 1520 other peer expects (i.e. that is missing!), everything
1591 { 1521 LOWER (but excluding mid_base itself) was received. */
1592 rel = fwd ? ch->root_rel : ch->dest_rel; 1522 mid_base = ntohl (ack->mid.mid);
1593 if (NULL == rel) 1523 mid_mask = GNUNET_htonll (ack->futures);
1594 { 1524 found = GNUNET_NO;
1595 GNUNET_break (GNUNET_NO != ch->destroy); 1525 for (crm = ch->head_sent;
1596 return; 1526 NULL != crm;
1597 } 1527 crm = crmn)
1598 if (NULL != rel->head_sent) 1528 {
1529 crmn = crm->next;
1530 delta = (unsigned int) (ntohl (crm->data_message->mid.mid) - mid_base);
1531 if (delta >= UINT_MAX - ch->max_pending_messages)
1599 { 1532 {
1600 if (64 <= rel->mid_send - rel->head_sent->mid) 1533 /* overflow, means crm was a bit in the past, so this ACK counts for it. */
1601 { 1534 LOG (GNUNET_ERROR_TYPE_DEBUG,
1602 LOG (GNUNET_ERROR_TYPE_DEBUG, " too big MID gap! Wait for ACK.\n"); 1535 "Got DATA_ACK with base %u satisfying past message %u on %s\n",
1603 return; 1536 (unsigned int) mid_base,
1604 } 1537 ntohl (crm->data_message->mid.mid),
1605 else 1538 GCCH_2s (ch));
1606 { 1539 handle_matching_ack (ch,
1607 LOG (GNUNET_ERROR_TYPE_DEBUG, " gap ok: %u - %u\n", 1540 cti,
1608 rel->head_sent->mid, rel->mid_send); 1541 crm);
1609 struct CadetReliableMessage *aux; 1542 found = GNUNET_YES;
1610 for (aux = rel->head_sent; NULL != aux; aux = aux->next) 1543 continue;
1611 {
1612 LOG (GNUNET_ERROR_TYPE_DEBUG, " - sent mid %u\n", aux->mid);
1613 }
1614 }
1615 } 1544 }
1616 else 1545 delta--;
1546 if (delta >= 64)
1547 continue;
1548 LOG (GNUNET_ERROR_TYPE_DEBUG,
1549 "Testing bit %llX for mid %u (base: %u)\n",
1550 (1LLU << delta),
1551 ntohl (crm->data_message->mid.mid),
1552 mid_base);
1553 if (0 != (mid_mask & (1LLU << delta)))
1617 { 1554 {
1618 LOG (GNUNET_ERROR_TYPE_DEBUG, " head sent is NULL\n"); 1555 LOG (GNUNET_ERROR_TYPE_DEBUG,
1556 "Got DATA_ACK with mask for %u on %s\n",
1557 ntohl (crm->data_message->mid.mid),
1558 GCCH_2s (ch));
1559 handle_matching_ack (ch,
1560 cti,
1561 crm);
1562 found = GNUNET_YES;
1619 } 1563 }
1620 } 1564 }
1621 1565 if (GNUNET_NO == found)
1622 if (is_loopback (ch))
1623 buffer = GCCH_get_buffer (ch, fwd);
1624 else
1625 buffer = GCT_get_connections_buffer (ch->t);
1626
1627 if (0 == buffer)
1628 { 1566 {
1629 LOG (GNUNET_ERROR_TYPE_DEBUG, " no buffer space.\n"); 1567 /* ACK for message we already dropped, might have been a
1568 duplicate ACK? Ignore. */
1569 LOG (GNUNET_ERROR_TYPE_DEBUG,
1570 "Duplicate DATA_ACK on %s, ignoring\n",
1571 GCCH_2s (ch));
1572 GNUNET_STATISTICS_update (stats,
1573 "# duplicate DATA_ACKs",
1574 1,
1575 GNUNET_NO);
1630 return; 1576 return;
1631 } 1577 }
1632 1578 if (NULL != ch->retry_data_task)
1633 LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space %u, allowing\n", buffer); 1579 {
1634 send_client_ack (ch, fwd); 1580 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1581 ch->retry_data_task = NULL;
1582 }
1583 if ( (NULL != ch->head_sent) &&
1584 (NULL == ch->head_sent->qe) )
1585 ch->retry_data_task
1586 = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1587 &retry_transmission,
1588 ch);
1635} 1589}
1636 1590
1637 1591
1638/** 1592/**
1639 * Log channel info. 1593 * Destroy channel, based on the other peer closing the
1594 * connection. Also needs to remove this channel from
1595 * the tunnel.
1640 * 1596 *
1641 * @param ch Channel. 1597 * @param ch channel to destroy
1642 * @param level Debug level to use. 1598 * @param cti identifier of the connection that delivered the message,
1599 * NULL if we are simulating receiving a destroy due to shutdown
1643 */ 1600 */
1644void 1601void
1645GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level) 1602GCCH_handle_remote_destroy (struct CadetChannel *ch,
1603 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
1646{ 1604{
1647 int do_log; 1605 struct CadetChannelClient *ccc;
1648 1606
1649 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), 1607 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1650 "cadet-chn", 1608 LOG (GNUNET_ERROR_TYPE_DEBUG,
1651 __FILE__, __FUNCTION__, __LINE__); 1609 "Received remote channel DESTROY for %s\n",
1652 if (0 == do_log) 1610 GCCH_2s (ch));
1653 return; 1611 if (GNUNET_YES == ch->destroy)
1654
1655 if (NULL == ch)
1656 { 1612 {
1657 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n"); 1613 /* Local client already gone, this is instant-death. */
1614 channel_destroy (ch);
1658 return; 1615 return;
1659 } 1616 }
1660 LOG2 (level, "CHN Channel %s:%X (%p)\n", GCT_2s (ch->t), ch->gid, ch); 1617 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1661 LOG2 (level, "CHN root %p/%p\n", ch->root, ch->root_rel); 1618 if ( (NULL != ccc) &&
1662 if (NULL != ch->root) 1619 (NULL != ccc->head_recv) )
1663 {
1664 LOG2 (level, "CHN cli %s\n", GML_2s (ch->root));
1665 LOG2 (level, "CHN ready %s\n", ch->root_rel->client_ready ? "YES" : "NO");
1666 LOG2 (level, "CHN id %X\n", ch->lid_root.channel_of_client);
1667 LOG2 (level, "CHN recv %d\n", ch->root_rel->n_recv);
1668 LOG2 (level, "CHN MID r: %d, s: %d\n",
1669 ch->root_rel->mid_recv, ch->root_rel->mid_send);
1670 }
1671 LOG2 (level, "CHN dest %p/%p\n",
1672 ch->dest, ch->dest_rel);
1673 if (NULL != ch->dest)
1674 { 1620 {
1675 LOG2 (level, "CHN cli %s\n", GML_2s (ch->dest)); 1621 LOG (GNUNET_ERROR_TYPE_WARNING,
1676 LOG2 (level, "CHN ready %s\n", ch->dest_rel->client_ready ? "YES" : "NO"); 1622 "Lost end of transmission due to remote shutdown on %s\n",
1677 LOG2 (level, "CHN id %X\n", ch->lid_dest); 1623 GCCH_2s (ch));
1678 LOG2 (level, "CHN recv %d\n", ch->dest_rel->n_recv); 1624 /* FIXME: change API to notify client about truncated transmission! */
1679 LOG2 (level, "CHN MID r: %d, s: %d\n",
1680 ch->dest_rel->mid_recv, ch->dest_rel->mid_send);
1681
1682 } 1625 }
1626 ch->destroy = GNUNET_YES;
1627 if (NULL != ccc)
1628 GSC_handle_remote_channel_destroy (ccc->c,
1629 ccc->ccn,
1630 ch);
1631 channel_destroy (ch);
1683} 1632}
1684 1633
1685 1634
1686/** 1635/**
1687 * Handle an ACK given by a client. 1636 * Test if element @a e1 comes before element @a e2.
1688 *
1689 * Mark client as ready and send him any buffered data we could have for him.
1690 * 1637 *
1691 * @param ch Channel. 1638 * @param cls closure, to a flag where we indicate duplicate packets
1692 * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by dest and go BCK) 1639 * @param crm1 an element of to sort
1640 * @param crm2 another element to sort
1641 * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO
1693 */ 1642 */
1694void 1643static int
1695GCCH_handle_local_ack (struct CadetChannel *ch, int fwd) 1644cmp_crm_by_next_retry (void *cls,
1645 struct CadetReliableMessage *crm1,
1646 struct CadetReliableMessage *crm2)
1696{ 1647{
1697 struct CadetChannelReliability *rel; 1648 if (crm1->next_retry.abs_value_us <
1698 struct CadetClient *c; 1649 crm2->next_retry.abs_value_us)
1699 1650 return GNUNET_YES;
1700 rel = fwd ? ch->dest_rel : ch->root_rel; 1651 return GNUNET_NO;
1701 c = fwd ? ch->dest : ch->root;
1702
1703 rel->client_ready = GNUNET_YES;
1704 send_client_buffered_data (ch, c, fwd);
1705
1706 if (GNUNET_YES == ch->destroy && 0 == rel->n_recv)
1707 {
1708 send_destroy (ch, GNUNET_YES);
1709 GCCH_destroy (ch);
1710 return;
1711 }
1712 /* if loopback is marked for destruction, no need to ACK to the other peer,
1713 * it requested the destruction and is already gone, therefore, else if.
1714 */
1715 else if (is_loopback (ch))
1716 {
1717 unsigned int buffer;
1718
1719 buffer = GCCH_get_buffer (ch, fwd);
1720 if (0 < buffer)
1721 GCCH_allow_client (ch, fwd);
1722
1723 return;
1724 }
1725 GCT_send_connection_acks (ch->t);
1726} 1652}
1727 1653
1728 1654
1729/** 1655/**
1730 * Handle data given by a client. 1656 * Function called once the tunnel has sent one of our messages.
1731 * 1657 * If the message is unreliable, simply frees the `crm`. If the
1732 * Check whether the client is allowed to send in this tunnel, save if channel 1658 * message was reliable, calculate retransmission time and
1733 * is reliable and send an ACK to the client if there is still buffer space 1659 * wait for ACK (or retransmit).
1734 * in the tunnel. 1660 *
1735 * 1661 * @param cls the `struct CadetReliableMessage` that was sent
1736 * @param ch Channel. 1662 * @param cid identifier of the connection within the tunnel, NULL
1737 * @param c Client which sent the data. 1663 * if transmission failed
1738 * @param fwd Is this a FWD data?
1739 * @param message Data message.
1740 * @param size Size of data.
1741 *
1742 * @return #GNUNET_OK if everything goes well, #GNUNET_SYSERR in case of en error.
1743 */ 1664 */
1744int 1665static void
1745GCCH_handle_local_data (struct CadetChannel *ch, 1666data_sent_cb (void *cls,
1746 struct CadetClient *c, 1667 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
1747 int fwd,
1748 const struct GNUNET_MessageHeader *message,
1749 size_t size)
1750{ 1668{
1751 struct CadetChannelReliability *rel; 1669 struct CadetReliableMessage *crm = cls;
1752 struct GNUNET_CADET_ChannelAppDataMessage *payload; 1670 struct CadetChannel *ch = crm->ch;
1753 uint16_t p2p_size = sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + size; 1671
1754 unsigned char cbuf[p2p_size]; 1672 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1755 unsigned char buffer; 1673 GNUNET_assert (NULL != crm->qe);
1756 1674 crm->qe = NULL;
1757 /* Is the client in the channel? */ 1675 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
1758 if ( !( (fwd && 1676 ch->tail_sent,
1759 ch->root == c) 1677 crm);
1760 || 1678 if (GNUNET_NO == ch->reliable)
1761 (!fwd &&
1762 ch->dest == c) ) )
1763 { 1679 {
1764 GNUNET_break_op (0); 1680 GNUNET_free (crm->data_message);
1765 return GNUNET_SYSERR; 1681 GNUNET_free (crm);
1682 ch->pending_messages--;
1683 send_ack_to_client (ch,
1684 (NULL == ch->owner)
1685 ? GNUNET_NO
1686 : GNUNET_YES);
1687 return;
1766 } 1688 }
1767 1689 if (NULL == cid)
1768 rel = fwd ? ch->root_rel : ch->dest_rel;
1769
1770 if (GNUNET_NO == rel->client_allowed)
1771 { 1690 {
1772 GNUNET_break_op (0); 1691 /* There was an error sending. */
1773 return GNUNET_SYSERR; 1692 crm->num_transmissions = GNUNET_SYSERR;
1774 } 1693 }
1775 1694 else if (GNUNET_SYSERR != crm->num_transmissions)
1776 rel->client_allowed = GNUNET_NO;
1777
1778 /* Ok, everything is correct, send the message. */
1779 payload = (struct GNUNET_CADET_ChannelAppDataMessage *) cbuf;
1780 payload->mid = htonl (rel->mid_send);
1781 rel->mid_send++;
1782 GNUNET_memcpy (&payload[1], message, size);
1783 payload->header.size = htons (p2p_size);
1784 payload->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
1785 payload->ctn = ch->gid;
1786 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n");
1787 GCCH_send_prebuilt_message (&payload->header, ch, fwd, NULL);
1788
1789 if (is_loopback (ch))
1790 buffer = GCCH_get_buffer (ch, fwd);
1791 else
1792 buffer = GCT_get_connections_buffer (ch->t);
1793
1794 if (0 < buffer)
1795 GCCH_allow_client (ch, fwd);
1796
1797 return GNUNET_OK;
1798}
1799
1800
1801/**
1802 * Handle a channel destroy requested by a client.
1803 *
1804 * TODO: add "reason" field
1805 *
1806 * Destroy the channel and the tunnel in case this was the last channel.
1807 *
1808 * @param ch Channel.
1809 * @param c Client that requested the destruction (to avoid notifying him).
1810 * @param is_root Is the request coming from root?
1811 */
1812void
1813GCCH_handle_local_destroy (struct CadetChannel *ch,
1814 struct CadetClient *c,
1815 int is_root)
1816{
1817 ch->destroy = GNUNET_YES;
1818 /* Cleanup after the tunnel */
1819 if (GNUNET_NO == is_root && c == ch->dest)
1820 { 1695 {
1821 LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is destination.\n", GML_2s (c)); 1696 /* Increment transmission counter, and possibly store @a cid
1822 GML_client_delete_channel (c, ch, ch->lid_dest); 1697 if this was the first transmission. */
1823 ch->dest = NULL; 1698 crm->num_transmissions++;
1699 if (1 == crm->num_transmissions)
1700 {
1701 crm->first_transmission_time = GNUNET_TIME_absolute_get ();
1702 crm->connection_taken = *cid;
1703 GCC_ack_expected (cid);
1704 }
1824 } 1705 }
1825 if (GNUNET_YES == is_root && c == ch->root) 1706 if ( (0 == crm->retry_delay.rel_value_us) &&
1707 (NULL != cid) )
1826 { 1708 {
1827 LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is owner.\n", GML_2s (c)); 1709 struct CadetConnection *cc = GCC_lookup (cid);
1828 GML_client_delete_channel (c, ch, ch->lid_root);
1829 ch->root = NULL;
1830 }
1831 1710
1832 send_destroy (ch, GNUNET_NO); 1711 if (NULL != cc)
1833 if (0 == ch->pending_messages) 1712 crm->retry_delay = GCC_get_metrics (cc)->aged_latency;
1834 GCCH_destroy (ch); 1713 else
1714 crm->retry_delay = ch->retry_time;
1715 }
1716 crm->retry_delay = GNUNET_TIME_STD_BACKOFF (crm->retry_delay);
1717 crm->retry_delay = GNUNET_TIME_relative_max (crm->retry_delay,
1718 MIN_RTT_DELAY);
1719 crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay);
1720
1721 GNUNET_CONTAINER_DLL_insert_sorted (struct CadetReliableMessage,
1722 cmp_crm_by_next_retry,
1723 NULL,
1724 ch->head_sent,
1725 ch->tail_sent,
1726 crm);
1727 LOG (GNUNET_ERROR_TYPE_DEBUG,
1728 "Message %u sent, next transmission on %s in %s\n",
1729 (unsigned int) ntohl (crm->data_message->mid.mid),
1730 GCCH_2s (ch),
1731 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (ch->head_sent->next_retry),
1732 GNUNET_YES));
1733 if (NULL == ch->head_sent->qe)
1734 {
1735 if (NULL != ch->retry_data_task)
1736 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1737 ch->retry_data_task
1738 = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1739 &retry_transmission,
1740 ch);
1741 }
1835} 1742}
1836 1743
1837 1744
1838/** 1745/**
1839 * Handle a channel create requested by a client. 1746 * Handle data given by a client.
1840 *
1841 * Create the channel and the tunnel in case this was the first0 channel.
1842 * 1747 *
1843 * @param c Client that requested the creation (will be the root). 1748 * Check whether the client is allowed to send in this tunnel, save if
1844 * @param msg Create Channel message. 1749 * channel is reliable and send an ACK to the client if there is still
1750 * buffer space in the tunnel.
1845 * 1751 *
1846 * @return #GNUNET_OK if everything went fine, #GNUNET_SYSERR otherwise. 1752 * @param ch Channel.
1753 * @param sender_ccn ccn of the sender
1754 * @param buf payload to transmit.
1755 * @param buf_len number of bytes in @a buf
1756 * @return #GNUNET_OK if everything goes well,
1757 * #GNUNET_SYSERR in case of an error.
1847 */ 1758 */
1848int 1759int
1849GCCH_handle_local_create (struct CadetClient *c, 1760GCCH_handle_local_data (struct CadetChannel *ch,
1850 struct GNUNET_CADET_LocalChannelCreateMessage *msg) 1761 struct GNUNET_CADET_ClientChannelNumber sender_ccn,
1762 const char *buf,
1763 size_t buf_len)
1851{ 1764{
1852 struct CadetChannel *ch; 1765 struct CadetReliableMessage *crm;
1853 struct CadetTunnel *t;
1854 struct CadetPeer *peer;
1855 struct GNUNET_CADET_ClientChannelNumber ccn;
1856
1857 LOG (GNUNET_ERROR_TYPE_DEBUG, " towards %s:%u\n",
1858 GNUNET_i2s (&msg->peer), GNUNET_h2s (&msg->port));
1859 ccn = msg->ccn;
1860
1861 /* Sanity check for duplicate channel IDs */
1862 if (NULL != GML_channel_get (c, ccn))
1863 {
1864 GNUNET_break (0);
1865 return GNUNET_SYSERR;
1866 }
1867 1766
1868 peer = GCP_get (&msg->peer, GNUNET_YES); 1767 if (ch->pending_messages > ch->max_pending_messages)
1869 GCP_add_tunnel (peer);
1870 t = GCP_get_tunnel (peer);
1871
1872 if (GCP_get_short_id (peer) == myid)
1873 {
1874 GCT_change_cstate (t, CADET_TUNNEL_READY);
1875 }
1876 else
1877 {
1878 /* FIXME change to a tunnel API, eliminate ch <-> peer connection */
1879 GCP_connect (peer);
1880 }
1881
1882 /* Create channel */
1883 ch = channel_new (t, c, ccn);
1884 if (NULL == ch)
1885 { 1768 {
1886 GNUNET_break (0); 1769 GNUNET_break (0);
1887 return GNUNET_SYSERR; 1770 return GNUNET_SYSERR;
1888 } 1771 }
1889 ch->port = msg->port; 1772 if (GNUNET_YES == ch->destroy)
1890 channel_set_options (ch, ntohl (msg->opt));
1891
1892 /* In unreliable channels, we'll use the DLL to buffer BCK data */
1893 ch->root_rel = GNUNET_new (struct CadetChannelReliability);
1894 ch->root_rel->ch = ch;
1895 ch->root_rel->retry_timer = CADET_RETRANSMIT_TIME;
1896 ch->root_rel->expected_delay.rel_value_us = 0;
1897
1898 LOG (GNUNET_ERROR_TYPE_DEBUG, "CREATED CHANNEL %s\n", GCCH_2s (ch));
1899
1900 send_create (ch);
1901
1902 return GNUNET_OK;
1903}
1904
1905
1906/**
1907 * Handler for cadet network payload traffic.
1908 *
1909 * @param ch Channel for the message.
1910 * @param msg Unencryted data message.
1911 * @param fwd Is this message fwd? This only is meaningful in loopback channels.
1912 * #GNUNET_YES if message is FWD on the respective channel (loopback)
1913 * #GNUNET_NO if message is BCK on the respective channel (loopback)
1914 * #GNUNET_SYSERR if message on a one-ended channel (remote)
1915 */
1916void
1917GCCH_handle_data (struct CadetChannel *ch,
1918 const struct GNUNET_CADET_ChannelAppDataMessage *msg,
1919 int fwd)
1920{
1921 struct CadetChannelReliability *rel;
1922 struct CadetClient *c;
1923 struct GNUNET_MessageHeader *payload_msg;
1924 uint32_t mid;
1925 uint16_t payload_type;
1926 uint16_t payload_size;
1927
1928 /* If this is a remote (non-loopback) channel, find 'fwd'. */
1929 if (GNUNET_SYSERR == fwd)
1930 { 1773 {
1931 if (is_loopback (ch)) 1774 /* we are going down, drop messages */
1932 { 1775 return GNUNET_OK;
1933 /* It is a loopback channel after all... */
1934 GNUNET_break (0);
1935 return;
1936 }
1937 fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
1938 } 1776 }
1777 ch->pending_messages++;
1939 1778
1940 /* Initialize FWD/BCK data */ 1779 if (GNUNET_YES == ch->is_loopback)
1941 c = fwd ? ch->dest : ch->root;
1942 rel = fwd ? ch->dest_rel : ch->root_rel;
1943
1944 if (NULL == c)
1945 { 1780 {
1946 GNUNET_break (GNUNET_NO != ch->destroy); 1781 struct CadetChannelClient *receiver;
1947 return; 1782 struct GNUNET_MQ_Envelope *env;
1948 } 1783 struct GNUNET_CADET_LocalData *ld;
1784 int ack_to_owner;
1949 1785
1950 if (CADET_CHANNEL_READY != ch->state) 1786 env = GNUNET_MQ_msg_extra (ld,
1951 { 1787 buf_len,
1952 if (GNUNET_NO == fwd) 1788 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1789 if ( (NULL != ch->owner) &&
1790 (sender_ccn.channel_of_client ==
1791 ch->owner->ccn.channel_of_client) )
1953 { 1792 {
1954 /* If we are the root, this means the other peer has sent traffic before 1793 receiver = ch->dest;
1955 * receiving our ACK. Even if the SYNACK goes missing, no traffic should 1794 ack_to_owner = GNUNET_YES;
1956 * be sent before the ACK.
1957 */
1958 GNUNET_break_op (0);
1959 return;
1960 } 1795 }
1961 /* If we are the dest, this means that the SYNACK got to the root but 1796 else if ( (NULL != ch->dest) &&
1962 * the ACK went missing. Treat this as an ACK. 1797 (sender_ccn.channel_of_client ==
1963 */ 1798 ch->dest->ccn.channel_of_client) )
1964 channel_confirm (ch, GNUNET_NO);
1965 }
1966
1967 payload_msg = (struct GNUNET_MessageHeader *) &msg[1];
1968 payload_type = ntohs (payload_msg->type);
1969 payload_size = ntohs (payload_msg->size);
1970
1971 GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
1972 GNUNET_STATISTICS_update (stats, "# bytes received", payload_size, GNUNET_NO);
1973
1974 mid = ntohl (msg->mid);
1975 LOG (GNUNET_ERROR_TYPE_INFO, "<== %s (%s %4u) on chan %s (%p) %s [%5u]\n",
1976 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA), GC_m2s (payload_type), mid,
1977 GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size));
1978
1979 if ( (GNUNET_NO == ch->reliable) ||
1980 ( (! GC_is_pid_bigger (rel->mid_recv, mid)) &&
1981 GC_is_pid_bigger (rel->mid_recv + 64, mid) ) )
1982 {
1983 if (GNUNET_YES == ch->reliable)
1984 { 1799 {
1985 /* Is this the exact next expected messasge? */ 1800 receiver = ch->owner;
1986 if (mid == rel->mid_recv) 1801 ack_to_owner = GNUNET_NO;
1987 {
1988 LOG (GNUNET_ERROR_TYPE_DEBUG,
1989 "as expected, sending to client\n");
1990 send_client_data (ch, msg, fwd);
1991 }
1992 else
1993 {
1994 LOG (GNUNET_ERROR_TYPE_DEBUG,
1995 "save for later\n");
1996 add_buffered_data (msg, rel);
1997 }
1998 } 1802 }
1999 else 1803 else
2000 { 1804 {
2001 /* Tunnel is unreliable: send to clients directly */ 1805 GNUNET_break (0);
2002 /* FIXME: accept Out Of Order traffic */ 1806 return GNUNET_SYSERR;
2003 rel->mid_recv = mid + 1;
2004 send_client_data (ch, msg, fwd);
2005 } 1807 }
2006 } 1808 GNUNET_assert (NULL != receiver);
2007 else 1809 ld->ccn = receiver->ccn;
2008 { 1810 GNUNET_memcpy (&ld[1],
2009 GNUNET_STATISTICS_update (stats, "# duplicate MID", 1, GNUNET_NO); 1811 buf,
2010 if (GC_is_pid_bigger (rel->mid_recv, mid)) 1812 buf_len);
1813 if (GNUNET_YES == receiver->client_ready)
2011 { 1814 {
2012 GNUNET_break_op (0); 1815 ch->pending_messages--;
2013 LOG (GNUNET_ERROR_TYPE_WARNING, 1816 GSC_send_to_client (receiver->c,
2014 "MID %u on channel %s not expected (window: %u - %u). Dropping!\n", 1817 env);
2015 mid, GCCH_2s (ch), rel->mid_recv, rel->mid_recv + 63); 1818 send_ack_to_client (ch,
1819 ack_to_owner);
2016 } 1820 }
2017 else 1821 else
2018 { 1822 {
2019 LOG (GNUNET_ERROR_TYPE_INFO, 1823 struct CadetOutOfOrderMessage *oom;
2020 "Duplicate MID %u, channel %s (expecting MID %u). Re-sending ACK!\n", 1824
2021 mid, GCCH_2s (ch), rel->mid_recv); 1825 oom = GNUNET_new (struct CadetOutOfOrderMessage);
2022 if (NULL != rel->uniq) 1826 oom->env = env;
2023 { 1827 GNUNET_CONTAINER_DLL_insert_tail (receiver->head_recv,
2024 LOG (GNUNET_ERROR_TYPE_WARNING, 1828 receiver->tail_recv,
2025 "We are trying to send an ACK, but don't seem have the " 1829 oom);
2026 "bandwidth. Have you set enough [ats] QUOTA in your config?\n"); 1830 receiver->num_recv++;
2027 }
2028
2029 } 1831 }
2030 } 1832 return GNUNET_OK;
2031 1833 }
2032 GCCH_send_data_ack (ch, fwd); 1834
1835 /* Everything is correct, send the message. */
1836 crm = GNUNET_malloc (sizeof (*crm));
1837 crm->ch = ch;
1838 crm->data_message = GNUNET_malloc (sizeof (struct GNUNET_CADET_ChannelAppDataMessage)
1839 + buf_len);
1840 crm->data_message->header.size = htons (sizeof (struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1841 crm->data_message->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
1842 ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
1843 crm->data_message->mid = ch->mid_send;
1844 crm->data_message->ctn = ch->ctn;
1845 GNUNET_memcpy (&crm->data_message[1],
1846 buf,
1847 buf_len);
1848 GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent,
1849 ch->tail_sent,
1850 crm);
1851 LOG (GNUNET_ERROR_TYPE_DEBUG,
1852 "Sending message %u from local client to %s with %u bytes\n",
1853 ntohl (crm->data_message->mid.mid),
1854 GCCH_2s (ch),
1855 buf_len);
1856 if (NULL != ch->retry_data_task)
1857 {
1858 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1859 ch->retry_data_task = NULL;
1860 }
1861 crm->qe = GCT_send (ch->t,
1862 &crm->data_message->header,
1863 &data_sent_cb,
1864 crm);
1865 GNUNET_assert (NULL == ch->retry_data_task);
1866 return GNUNET_OK;
2033} 1867}
2034 1868
2035 1869
2036/** 1870/**
2037 * Handler for cadet network traffic end-to-end ACKs. 1871 * Handle ACK from client on local channel. Means the client is ready
1872 * for more data, see if we have any for it.
2038 * 1873 *
2039 * @param ch Channel on which we got this message. 1874 * @param ch channel to destroy
2040 * @param msg Data message. 1875 * @param client_ccn ccn of the client sending the ack
2041 * @param fwd Is this message fwd? This only is meaningful in loopback channels.
2042 * #GNUNET_YES if message is FWD on the respective channel (loopback)
2043 * #GNUNET_NO if message is BCK on the respective channel (loopback)
2044 * #GNUNET_SYSERR if message on a one-ended channel (remote)
2045 */ 1876 */
2046void 1877void
2047GCCH_handle_data_ack (struct CadetChannel *ch, 1878GCCH_handle_local_ack (struct CadetChannel *ch,
2048 const struct GNUNET_CADET_ChannelDataAckMessage *msg, 1879 struct GNUNET_CADET_ClientChannelNumber client_ccn)
2049 int fwd)
2050{ 1880{
2051 struct CadetChannelReliability *rel; 1881 struct CadetChannelClient *ccc;
2052 struct CadetReliableMessage *copy; 1882 struct CadetOutOfOrderMessage *com;
2053 struct CadetReliableMessage *next; 1883
2054 uint32_t ack; 1884 if ( (NULL != ch->owner) &&
2055 int work; 1885 (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client) )
2056 1886 ccc = ch->owner;
2057 /* If this is a remote (non-loopback) channel, find 'fwd'. */ 1887 else if ( (NULL != ch->dest) &&
2058 if (GNUNET_SYSERR == fwd) 1888 (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client) )
2059 { 1889 ccc = ch->dest;
2060 if (is_loopback (ch))
2061 {
2062 /* It is a loopback channel after all... */
2063 GNUNET_break (0);
2064 return;
2065 }
2066 /* Inverted: if message came 'FWD' is a 'BCK ACK'. */
2067 fwd = (NULL != ch->dest) ? GNUNET_NO : GNUNET_YES;
2068 }
2069
2070 ack = ntohl (msg->mid);
2071 LOG (GNUNET_ERROR_TYPE_INFO,
2072 "<== %s (0x%010lX %4u) on chan %s (%p) %s [%5u]\n",
2073 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK), msg->futures, ack,
2074 GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size));
2075
2076 if (GNUNET_YES == fwd)
2077 rel = ch->root_rel;
2078 else 1890 else
2079 rel = ch->dest_rel; 1891 GNUNET_assert (0);
2080 1892 ccc->client_ready = GNUNET_YES;
2081 if (NULL == rel) 1893 com = ccc->head_recv;
1894 if (NULL == com)
2082 { 1895 {
2083 GNUNET_break (GNUNET_NO != ch->destroy); 1896 LOG (GNUNET_ERROR_TYPE_DEBUG,
2084 return; 1897 "Got LOCAL_ACK, %s-%X ready to receive more data, but none pending on %s-%X(%p)!\n",
2085 } 1898 GSC_2s (ccc->c),
2086 1899 ntohl (client_ccn.channel_of_client),
2087 /* Free ACK'd copies: no need to retransmit those anymore FIXME refactor */ 1900 GCCH_2s (ch),
2088 for (work = GNUNET_NO, copy = rel->head_sent; copy != NULL; copy = next) 1901 ntohl (ccc->ccn.channel_of_client),
2089 { 1902 ccc);
2090 if (GC_is_pid_bigger (copy->mid, ack)) 1903 return; /* none pending */
2091 { 1904 }
2092 LOG (GNUNET_ERROR_TYPE_DEBUG, " head %u, out!\n", copy->mid); 1905 if (GNUNET_YES == ch->is_loopback)
2093 if (0 < channel_rel_free_sent (rel, msg)) 1906 {
2094 work = GNUNET_YES; 1907 int to_owner;
2095 break; 1908
2096 } 1909 /* Messages are always in-order, just send */
2097 work = GNUNET_YES; 1910 GNUNET_CONTAINER_DLL_remove (ccc->head_recv,
2098 LOG (GNUNET_ERROR_TYPE_DEBUG, " id %u\n", copy->mid); 1911 ccc->tail_recv,
2099 next = copy->next; 1912 com);
2100 if (GNUNET_YES == rel_message_free (copy, GNUNET_YES)) 1913 ccc->num_recv--;
2101 { 1914 GSC_send_to_client (ccc->c,
2102 LOG (GNUNET_ERROR_TYPE_DEBUG, " channel destoyed\n"); 1915 com->env);
2103 return; 1916 /* Notify sender that we can receive more */
2104 } 1917 if ( (NULL != ch->owner) &&
2105 } 1918 (ccc->ccn.channel_of_client ==
2106 1919 ch->owner->ccn.channel_of_client) )
2107 /* ACK client if needed and possible */
2108 GCCH_allow_client (ch, fwd);
2109
2110 /* If some message was free'd, update the retransmission delay */
2111 if (GNUNET_YES == work)
2112 {
2113 if (NULL != rel->retry_task)
2114 { 1920 {
2115 GNUNET_SCHEDULER_cancel (rel->retry_task); 1921 to_owner = GNUNET_NO;
2116 rel->retry_task = NULL;
2117 if (NULL != rel->head_sent && NULL == rel->head_sent->chq)
2118 {
2119 struct GNUNET_TIME_Absolute new_target;
2120 struct GNUNET_TIME_Relative delay;
2121
2122 delay = GNUNET_TIME_relative_saturating_multiply (rel->retry_timer,
2123 CADET_RETRANSMIT_MARGIN);
2124 new_target = GNUNET_TIME_absolute_add (rel->head_sent->timestamp,
2125 delay);
2126 delay = GNUNET_TIME_absolute_get_remaining (new_target);
2127 rel->retry_task =
2128 GNUNET_SCHEDULER_add_delayed (delay,
2129 &channel_retransmit_message,
2130 rel);
2131 }
2132 } 1922 }
2133 else 1923 else
2134 { 1924 {
2135 /* Work was done but no task was pending. 1925 GNUNET_assert ( (NULL != ch->dest) &&
2136 * Task was cancelled by a retransmission that is sitting in the queue. 1926 (ccc->ccn.channel_of_client ==
2137 */ 1927 ch->dest->ccn.channel_of_client) );
2138 // FIXME add test to make sure this is the case, probably add return 1928 to_owner = GNUNET_YES;
2139 // value to GCCH_send_prebuilt_message
2140 } 1929 }
1930 send_ack_to_client (ch,
1931 to_owner);
1932 GNUNET_free (com);
1933 return;
2141 } 1934 }
2142}
2143 1935
2144 1936 if ( (com->mid.mid != ch->mid_recv.mid) &&
2145/** 1937 (GNUNET_NO == ch->out_of_order) &&
2146 * Handler for channel create messages. 1938 (GNUNET_YES == ch->reliable) )
2147 *
2148 * Does not have fwd parameter because it's always 'FWD': channel is incoming.
2149 *
2150 * @param t Tunnel this channel will be in.
2151 * @param msg Channel crate message.
2152 */
2153struct CadetChannel *
2154GCCH_handle_create (struct CadetTunnel *t,
2155 const struct GNUNET_CADET_ChannelOpenMessage *msg)
2156{
2157 struct GNUNET_CADET_ClientChannelNumber ccn;
2158 struct GNUNET_CADET_ChannelTunnelNumber gid;
2159 struct CadetChannel *ch;
2160 struct CadetClient *c;
2161 int new_channel;
2162 const struct GNUNET_HashCode *port;
2163
2164 gid = msg->ctn;
2165 ch = GCT_get_channel (t, gid);
2166 if (NULL == ch)
2167 {
2168 /* Create channel */
2169 ccn.channel_of_client = htonl (0);
2170 ch = channel_new (t, NULL, ccn);
2171 ch->gid = gid;
2172 channel_set_options (ch, ntohl (msg->opt));
2173 new_channel = GNUNET_YES;
2174 }
2175 else
2176 { 1939 {
2177 new_channel = GNUNET_NO; 1940 LOG (GNUNET_ERROR_TYPE_DEBUG,
1941 "Got LOCAL_ACK, %s-%X ready to receive more data (but next one is out-of-order %u vs. %u)!\n",
1942 GSC_2s (ccc->c),
1943 ntohl (ccc->ccn.channel_of_client),
1944 ntohl (com->mid.mid),
1945 ntohl (ch->mid_recv.mid));
1946 return; /* missing next one in-order */
2178 } 1947 }
2179 port = &msg->port;
2180
2181 LOG (GNUNET_ERROR_TYPE_INFO,
2182 "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n",
2183 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN), ccn, port,
2184 GCCH_2s (ch), ch, GC_f2s (GNUNET_YES), ntohs (msg->header.size));
2185
2186 if (GNUNET_YES == new_channel || GCT_is_loopback (t))
2187 {
2188 /* Find a destination client */
2189 ch->port = *port;
2190 LOG (GNUNET_ERROR_TYPE_DEBUG, " port %s\n", GNUNET_h2s (port));
2191 c = GML_client_get_by_port (port);
2192 if (NULL == c)
2193 {
2194 LOG (GNUNET_ERROR_TYPE_DEBUG, " no client has port registered\n");
2195 if (is_loopback (ch))
2196 {
2197 LOG (GNUNET_ERROR_TYPE_DEBUG, " loopback: destroy on handler\n");
2198 send_nack (ch);
2199 }
2200 else
2201 {
2202 LOG (GNUNET_ERROR_TYPE_DEBUG, " not loopback: destroy now\n");
2203 send_nack (ch);
2204 GCCH_destroy (ch);
2205 }
2206 return NULL;
2207 }
2208 else
2209 {
2210 LOG (GNUNET_ERROR_TYPE_DEBUG, " client %p has port registered\n", c);
2211 }
2212
2213 add_destination (ch, c);
2214 if (GNUNET_YES == ch->reliable)
2215 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reliable\n");
2216 else
2217 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not Reliable\n");
2218 1948
2219 send_client_create (ch); 1949 LOG (GNUNET_ERROR_TYPE_DEBUG,
2220 ch->state = CADET_CHANNEL_SENT; 1950 "Got LOCAL_ACK, giving payload message %u to %s-%X on %s\n",
2221 } 1951 ntohl (com->mid.mid),
2222 else 1952 GSC_2s (ccc->c),
2223 { 1953 ntohl (ccc->ccn.channel_of_client),
2224 LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate create channel\n"); 1954 GCCH_2s (ch));
2225 if (NULL != ch->dest_rel->retry_task)
2226 {
2227 LOG (GNUNET_ERROR_TYPE_DEBUG, " clearing retry task\n");
2228 /* we were waiting to re-send our 'SYNACK', wait no more! */
2229 GNUNET_SCHEDULER_cancel (ch->dest_rel->retry_task);
2230 ch->dest_rel->retry_task = NULL;
2231 }
2232 else if (NULL != ch->dest_rel->uniq)
2233 {
2234 /* we are waiting to for our 'SYNACK' to leave the queue, all done! */
2235 return ch;
2236 }
2237 }
2238 send_ack (ch, GNUNET_YES);
2239 1955
2240 return ch; 1956 /* all good, pass next message to client */
1957 GNUNET_CONTAINER_DLL_remove (ccc->head_recv,
1958 ccc->tail_recv,
1959 com);
1960 ccc->num_recv--;
1961 /* FIXME: if unreliable, this is not aggressive
1962 enough, as it would be OK to have lost some! */
1963
1964 ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid));
1965 ch->mid_futures >>= 1; /* equivalent to division by 2 */
1966 ccc->client_ready = GNUNET_NO;
1967 GSC_send_to_client (ccc->c,
1968 com->env);
1969 GNUNET_free (com);
1970 send_channel_data_ack (ch);
1971 if (NULL != ccc->head_recv)
1972 return;
1973 if (GNUNET_NO == ch->destroy)
1974 return;
1975 GCT_send_channel_destroy (ch->t,
1976 ch->ctn);
1977 channel_destroy (ch);
2241} 1978}
2242 1979
2243 1980
2244/** 1981#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-chn",__VA_ARGS__)
2245 * Handler for channel NACK messages.
2246 *
2247 * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter.
2248 *
2249 * @param ch Channel.
2250 */
2251void
2252GCCH_handle_nack (struct CadetChannel *ch)
2253{
2254 LOG (GNUNET_ERROR_TYPE_INFO,
2255 "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n",
2256 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED), ch->gid, 0,
2257 GCCH_2s (ch), ch, "---", 0);
2258
2259 send_client_nack (ch);
2260 GCCH_destroy (ch);
2261}
2262 1982
2263 1983
2264/** 1984/**
2265 * Handler for channel ack messages. 1985 * Log channel info.
2266 * 1986 *
2267 * @param ch Channel. 1987 * @param ch Channel.
2268 * @param msg Message. 1988 * @param level Debug level to use.
2269 * @param fwd Is this message fwd? This only is meaningful in loopback channels.
2270 * #GNUNET_YES if message is FWD on the respective channel (loopback)
2271 * #GNUNET_NO if message is BCK on the respective channel (loopback)
2272 * #GNUNET_SYSERR if message on a one-ended channel (remote)
2273 */
2274void
2275GCCH_handle_ack (struct CadetChannel *ch,
2276 const struct GNUNET_CADET_ChannelManageMessage *msg,
2277 int fwd)
2278{
2279 LOG (GNUNET_ERROR_TYPE_INFO,
2280 "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n",
2281 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK), ch->gid, 0,
2282 GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size));
2283
2284 /* If this is a remote (non-loopback) channel, find 'fwd'. */
2285 if (GNUNET_SYSERR == fwd)
2286 {
2287 if (is_loopback (ch))
2288 {
2289 /* It is a loopback channel after all... */
2290 GNUNET_break (0);
2291 return;
2292 }
2293 fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
2294 }
2295
2296 channel_confirm (ch, !fwd);
2297}
2298
2299
2300/**
2301 * Handler for channel destroy messages.
2302 *
2303 * @param ch Channel to be destroyed of.
2304 * @param msg Message.
2305 * @param fwd Is this message fwd? This only is meaningful in loopback channels.
2306 * #GNUNET_YES if message is FWD on the respective channel (loopback)
2307 * #GNUNET_NO if message is BCK on the respective channel (loopback)
2308 * #GNUNET_SYSERR if message on a one-ended channel (remote)
2309 */ 1989 */
2310void 1990void
2311GCCH_handle_destroy (struct CadetChannel *ch, 1991GCCH_debug (struct CadetChannel *ch,
2312 const struct GNUNET_CADET_ChannelManageMessage *msg, 1992 enum GNUNET_ErrorType level)
2313 int fwd)
2314{ 1993{
2315 struct CadetChannelReliability *rel; 1994 int do_log;
2316
2317 LOG (GNUNET_ERROR_TYPE_INFO,
2318 "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n",
2319 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY), ch->gid, 0,
2320 GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size));
2321
2322 /* If this is a remote (non-loopback) channel, find 'fwd'. */
2323 if (GNUNET_SYSERR == fwd)
2324 {
2325 if (is_loopback (ch))
2326 {
2327 /* It is a loopback channel after all... */
2328 GNUNET_break (0);
2329 return;
2330 }
2331 fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
2332 }
2333 1995
2334 GCCH_debug (ch, GNUNET_ERROR_TYPE_DEBUG); 1996 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
2335 if ( (fwd && NULL == ch->dest) || (!fwd && NULL == ch->root) ) 1997 "cadet-chn",
2336 { 1998 __FILE__, __FUNCTION__, __LINE__);
2337 /* Not for us (don't destroy twice a half-open loopback channel) */ 1999 if (0 == do_log)
2338 return; 2000 return;
2339 }
2340
2341 rel = fwd ? ch->dest_rel : ch->root_rel;
2342 if (0 == rel->n_recv)
2343 {
2344 send_destroy (ch, GNUNET_YES);
2345 GCCH_destroy (ch);
2346 }
2347 else
2348 {
2349 ch->destroy = GNUNET_YES;
2350 }
2351}
2352
2353
2354/**
2355 * Sends an already built message on a channel.
2356 *
2357 * If the channel is on a loopback tunnel, notifies the appropriate destination
2358 * client locally.
2359 *
2360 * On a normal channel passes the message to the tunnel for encryption and
2361 * sending on a connection.
2362 *
2363 * This function DOES NOT save the message for retransmission.
2364 *
2365 * @param message Message to send. Function makes a copy of it.
2366 * @param ch Channel on which this message is transmitted.
2367 * @param fwd Is this a fwd message?
2368 * @param existing_copy This is a retransmission, don't save a copy.
2369 */
2370void
2371GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2372 struct CadetChannel *ch, int fwd,
2373 void *existing_copy)
2374{
2375 struct CadetChannelQueue *chq;
2376 uint32_t data_id;
2377 uint16_t type;
2378 uint16_t size;
2379 char info[32];
2380
2381 type = ntohs (message->type);
2382 size = ntohs (message->size);
2383
2384 data_id = 0;
2385 switch (type)
2386 {
2387 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
2388 {
2389 struct GNUNET_CADET_ChannelAppDataMessage *data_msg;
2390 struct GNUNET_MessageHeader *payload_msg;
2391 uint16_t payload_type;
2392
2393 data_msg = (struct GNUNET_CADET_ChannelAppDataMessage *) message;
2394 data_id = ntohl (data_msg->mid);
2395 payload_msg = (struct GNUNET_MessageHeader *) &data_msg[1];
2396 payload_type = ntohs (payload_msg->type);
2397 strncpy (info, GC_m2s (payload_type), 31);
2398 info[31] = '\0';
2399 break;
2400 }
2401 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
2402 {
2403 struct GNUNET_CADET_ChannelDataAckMessage *ack_msg;
2404 ack_msg = (struct GNUNET_CADET_ChannelDataAckMessage *) message;
2405 data_id = ntohl (ack_msg->mid);
2406 SPRINTF (info, "0x%010lX",
2407 (unsigned long int) ack_msg->futures);
2408 break;
2409 }
2410 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
2411 {
2412 struct GNUNET_CADET_ChannelOpenMessage *cc_msg;
2413 cc_msg = (struct GNUNET_CADET_ChannelOpenMessage *) message;
2414 SPRINTF (info, " 0x%08X", ntohl (cc_msg->ctn.cn));
2415 break;
2416 }
2417 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
2418 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
2419 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
2420 {
2421 struct GNUNET_CADET_ChannelManageMessage *m_msg;
2422 m_msg = (struct GNUNET_CADET_ChannelManageMessage *) message;
2423 SPRINTF (info, " 0x%08X", ntohl (m_msg->ctn.cn));
2424 break;
2425 }
2426 default:
2427 info[0] = '\0';
2428 }
2429 LOG (GNUNET_ERROR_TYPE_INFO,
2430 "==> %s (%12s %4u) on chan %s (%p) %s [%5u]\n",
2431 GC_m2s (type), info, data_id,
2432 GCCH_2s (ch), ch, GC_f2s (fwd), size);
2433 2001
2434 if (GCT_is_loopback (ch->t)) 2002 if (NULL == ch)
2435 { 2003 {
2436 handle_loopback (ch, message, fwd); 2004 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
2437 return; 2005 return;
2438 } 2006 }
2439 2007 LOG2 (level,
2440 switch (type) 2008 "CHN %s:%X (%p)\n",
2009 GCT_2s (ch->t),
2010 ch->ctn,
2011 ch);
2012 if (NULL != ch->owner)
2441 { 2013 {
2442 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA: 2014 LOG2 (level,
2443 if (GNUNET_YES == ch->reliable) 2015 "CHN origin %s ready %s local-id: %u\n",
2444 { 2016 GSC_2s (ch->owner->c),
2445 chq = GNUNET_new (struct CadetChannelQueue); 2017 ch->owner->client_ready ? "YES" : "NO",
2446 chq->type = type; 2018 ntohl (ch->owner->ccn.channel_of_client));
2447 if (NULL == existing_copy)
2448 chq->copy = channel_save_copy (ch, message, fwd);
2449 else
2450 {
2451 chq->copy = (struct CadetReliableMessage *) existing_copy;
2452 if (NULL != chq->copy->chq)
2453 {
2454 /* Last retransmission was queued but not yet sent!
2455 * This retransmission was scheduled by a ch_message_sent which
2456 * followed a very fast RTT, so the tiny delay made the
2457 * retransmission function to execute before the previous
2458 * retransmitted message even had a chance to leave the peer.
2459 * Cancel this message and wait until the pending
2460 * retransmission leaves the peer and ch_message_sent starts
2461 * the timer for the next one.
2462 */
2463 GNUNET_free (chq);
2464 LOG (GNUNET_ERROR_TYPE_DEBUG,
2465 " exisitng copy not yet transmitted!\n");
2466 return;
2467 }
2468 LOG (GNUNET_ERROR_TYPE_DEBUG,
2469 " using existing copy: %p {r:%p q:%p t:%u}\n",
2470 existing_copy,
2471 chq->copy->rel, chq->copy->chq, chq->copy->type);
2472 }
2473 LOG (GNUNET_ERROR_TYPE_DEBUG, " new chq: %p\n", chq);
2474 chq->copy->chq = chq;
2475 chq->tq = GCT_send_prebuilt_message (message, ch->t, NULL,
2476 GNUNET_YES,
2477 &ch_message_sent, chq);
2478 /* q itself is stored in copy */
2479 GNUNET_assert (NULL != chq->tq || GNUNET_NO != ch->destroy);
2480 }
2481 else
2482 {
2483 fire_and_forget (message, ch, GNUNET_NO);
2484 }
2485 break;
2486
2487
2488 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
2489 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
2490 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
2491 chq = GNUNET_new (struct CadetChannelQueue);
2492 chq->type = type;
2493 chq->rel = fwd ? ch->root_rel : ch->dest_rel;
2494 if (NULL != chq->rel->uniq)
2495 {
2496 if (NULL != chq->rel->uniq->tq)
2497 {
2498 GCT_cancel (chq->rel->uniq->tq);
2499 /* ch_message_sent is called, freeing and NULLing uniq */
2500 GNUNET_break (NULL == chq->rel->uniq);
2501 }
2502 else
2503 {
2504 GNUNET_break (0);
2505 GNUNET_free (chq->rel->uniq);
2506 }
2507 }
2508
2509 chq->rel->uniq = chq;
2510 chq->tq = GCT_send_prebuilt_message (message, ch->t, NULL, GNUNET_YES,
2511 &ch_message_sent, chq);
2512 if (NULL == chq->tq)
2513 {
2514 GNUNET_break (0);
2515 chq->rel->uniq = NULL;
2516 GCT_debug (ch->t, GNUNET_ERROR_TYPE_ERROR);
2517 GNUNET_free (chq);
2518 chq = NULL;
2519 return;
2520 }
2521 break;
2522
2523
2524 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
2525 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
2526 fire_and_forget (message, ch, GNUNET_YES);
2527 break;
2528
2529
2530 default:
2531 GNUNET_break (0);
2532 LOG (GNUNET_ERROR_TYPE_WARNING, "type %s unknown!\n", GC_m2s (type));
2533 fire_and_forget (message, ch, GNUNET_YES);
2534 } 2019 }
2020 if (NULL != ch->dest)
2021 {
2022 LOG2 (level,
2023 "CHN destination %s ready %s local-id: %u\n",
2024 GSC_2s (ch->dest->c),
2025 ch->dest->client_ready ? "YES" : "NO",
2026 ntohl (ch->dest->ccn.channel_of_client));
2027 }
2028 LOG2 (level,
2029 "CHN Message IDs recv: %d (%LLX), send: %d\n",
2030 ntohl (ch->mid_recv.mid),
2031 (unsigned long long) ch->mid_futures,
2032 ntohl (ch->mid_send.mid));
2535} 2033}
2536 2034
2537 2035
2538/**
2539 * Get the static string for identification of the channel.
2540 *
2541 * @param ch Channel.
2542 *
2543 * @return Static string with the channel IDs.
2544 */
2545const char *
2546GCCH_2s (const struct CadetChannel *ch)
2547{
2548 static char buf[64];
2549
2550 if (NULL == ch)
2551 return "(NULL Channel)";
2552 2036
2553 SPRINTF (buf, 2037/* end of gnunet-service-cadet-new_channel.c */
2554 "%s:%s gid:%X (%X / %X)",
2555 GCT_2s (ch->t),
2556 GNUNET_h2s (&ch->port),
2557 ntohl (ch->gid.cn),
2558 ntohl (ch->lid_root.channel_of_client),
2559 ntohl (ch->lid_dest.channel_of_client));
2560
2561 return buf;
2562}
diff --git a/src/cadet/gnunet-service-cadet_channel.h b/src/cadet/gnunet-service-cadet_channel.h
index 9d4893269..a3ef9a06d 100644
--- a/src/cadet/gnunet-service-cadet_channel.h
+++ b/src/cadet/gnunet-service-cadet_channel.h
@@ -1,6 +1,7 @@
1
1/* 2/*
2 This file is part of GNUnet. 3 This file is part of GNUnet.
3 Copyright (C) 2013 GNUnet e.V. 4 Copyright (C) 2001-2017 GNUnet e.V.
4 5
5 GNUnet is free software; you can redistribute it and/or modify 6 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 7 it under the terms of the GNU General Public License as published
@@ -20,344 +21,242 @@
20 21
21/** 22/**
22 * @file cadet/gnunet-service-cadet_channel.h 23 * @file cadet/gnunet-service-cadet_channel.h
23 * @brief cadet service; dealing with end-to-end channels 24 * @brief GNUnet CADET service with encryption
24 * @author Bartlomiej Polot 25 * @author Bartlomiej Polot
25 * 26 * @author Christian Grothoff
26 * All functions in this file should use the prefix GMCH (Gnunet Cadet CHannel)
27 */ 27 */
28
29#ifndef GNUNET_SERVICE_CADET_CHANNEL_H 28#ifndef GNUNET_SERVICE_CADET_CHANNEL_H
30#define GNUNET_SERVICE_CADET_CHANNEL_H 29#define GNUNET_SERVICE_CADET_CHANNEL_H
31 30
32#ifdef __cplusplus 31#include "gnunet-service-cadet.h"
33extern "C" 32#include "gnunet-service-cadet_peer.h"
34{
35#if 0 /* keep Emacsens' auto-indent happy */
36}
37#endif
38#endif
39
40#include "platform.h"
41#include "gnunet_util_lib.h"
42
43#include "cadet_protocol.h" 33#include "cadet_protocol.h"
44#include "cadet.h"
45
46/**
47 * Struct containing all information regarding a channel to a remote client.
48 */
49struct CadetChannel;
50
51
52#include "gnunet-service-cadet_tunnel.h"
53#include "gnunet-service-cadet_local.h"
54
55
56/**
57 * Destroy a channel and free all resources.
58 *
59 * @param ch Channel to destroy.
60 */
61void
62GCCH_destroy (struct CadetChannel *ch);
63 34
64 35
65/** 36/**
66 * Get the channel's public ID. 37 * A channel is a bidirectional connection between two CADET
67 * 38 * clients. Communiation can be reliable, unreliable, in-order
68 * @param ch Channel. 39 * or out-of-order. One client is the "local" client, this
69 * 40 * one initiated the connection. The other client is the
70 * @return ID used to identify the channel with the remote peer. 41 * "incoming" client, this one listened on a port to accept
42 * the connection from the "local" client.
71 */ 43 */
72struct GNUNET_CADET_ChannelTunnelNumber 44struct CadetChannel;
73GCCH_get_id (const struct CadetChannel *ch);
74
75
76/**
77 * Get the channel tunnel.
78 *
79 * @param ch Channel to get the tunnel from.
80 *
81 * @return tunnel of the channel.
82 */
83struct CadetTunnel *
84GCCH_get_tunnel (const struct CadetChannel *ch);
85 45
86 46
87/** 47/**
88 * Get free buffer space towards the client on a specific channel. 48 * Get the static string for identification of the channel.
89 * 49 *
90 * @param ch Channel. 50 * @param ch Channel.
91 * @param fwd Is query about FWD traffic?
92 * 51 *
93 * @return Free buffer space [0 - 64] 52 * @return Static string with the channel IDs.
94 */ 53 */
95unsigned int 54const char *
96GCCH_get_buffer (struct CadetChannel *ch, int fwd); 55GCCH_2s (const struct CadetChannel *ch);
97 56
98 57
99/** 58/**
100 * Get flow control status of end point: is client allow to send? 59 * Log channel info.
101 * 60 *
102 * @param ch Channel. 61 * @param ch Channel.
103 * @param fwd Is query about FWD traffic? (Request root status). 62 * @param level Debug level to use.
104 *
105 * @return #GNUNET_YES if client is allowed to send us data.
106 */ 63 */
107int 64void
108GCCH_get_allowed (struct CadetChannel *ch, int fwd); 65GCCH_debug (struct CadetChannel *ch,
66 enum GNUNET_ErrorType level);
109 67
110 68
111/** 69/**
112 * Is the root client for this channel on this peer? 70 * Get the channel's public ID.
113 * 71 *
114 * @param ch Channel. 72 * @param ch Channel.
115 * @param fwd Is this for fwd traffic?
116 * 73 *
117 * @return #GNUNET_YES in case it is. 74 * @return ID used to identify the channel with the remote peer.
118 */ 75 */
119int 76struct GNUNET_CADET_ChannelTunnelNumber
120GCCH_is_origin (struct CadetChannel *ch, int fwd); 77GCCH_get_id (const struct CadetChannel *ch);
121 78
122/**
123 * Is the destination client for this channel on this peer?
124 *
125 * @param ch Channel.
126 * @param fwd Is this for fwd traffic?
127 *
128 * @return #GNUNET_YES in case it is.
129 */
130int
131GCCH_is_terminal (struct CadetChannel *ch, int fwd);
132 79
133/** 80/**
134 * Send an end-to-end ACK message for the most recent in-sequence payload. 81 * Create a new channel.
135 * 82 *
136 * If channel is not reliable, do nothing. 83 * @param owner local client owning the channel
137 * 84 * @param owner_id local chid of this channel at the @a owner
138 * @param ch Channel this is about. 85 * @param destination peer to which we should build the channel
139 * @param fwd Is for FWD traffic? (ACK dest->owner) 86 * @param port desired port at @a destination
87 * @param options options for the channel
88 * @return handle to the new channel
140 */ 89 */
141void 90struct CadetChannel *
142GCCH_send_data_ack (struct CadetChannel *ch, int fwd); 91GCCH_channel_local_new (struct CadetClient *owner,
92 struct GNUNET_CADET_ClientChannelNumber owner_id,
93 struct CadetPeer *destination,
94 const struct GNUNET_HashCode *port,
95 uint32_t options);
143 96
144/**
145 * Notify the destination client that a new incoming channel was created.
146 *
147 * @param ch Channel that was created.
148 */
149void
150GCCH_send_create (struct CadetChannel *ch);
151 97
152/** 98/**
153 * Allow a client to send us more data, in case it was choked. 99 * A client is bound to the port that we have a channel
100 * open to. Send the acknowledgement for the connection
101 * request and establish the link with the client.
154 * 102 *
155 * @param ch Channel. 103 * @param ch open incoming channel
156 * @param fwd Is this about FWD traffic? (Root client). 104 * @param c client listening on the respective port
157 */ 105 */
158void 106void
159GCCH_allow_client (struct CadetChannel *ch, int fwd); 107GCCH_bind (struct CadetChannel *ch,
108 struct CadetClient *c);
160 109
161/**
162 * Log channel info.
163 *
164 * @param ch Channel.
165 * @param level Debug level to use.
166 */
167void
168GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level);
169 110
170/** 111/**
171 * Handle an ACK given by a client. 112 * Destroy locally created channel. Called by the
113 * local client, so no need to tell the client.
172 * 114 *
173 * Mark client as ready and send him any buffered data we could have for him. 115 * @param ch channel to destroy
174 * 116 * @param c client that caused the destruction
175 * @param ch Channel. 117 * @param ccn client number of the client @a c
176 * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by root and go BCK)
177 */ 118 */
178void 119void
179GCCH_handle_local_ack (struct CadetChannel *ch, int fwd); 120GCCH_channel_local_destroy (struct CadetChannel *ch,
121 struct CadetClient *c,
122 struct GNUNET_CADET_ClientChannelNumber ccn);
180 123
181/**
182 * Handle data given by a client.
183 *
184 * Check whether the client is allowed to send in this tunnel, save if channel
185 * is reliable and send an ACK to the client if there is still buffer space
186 * in the tunnel.
187 *
188 * @param ch Channel.
189 * @param c Client which sent the data.
190 * @param fwd Is this a FWD data?
191 * @param message Data message.
192 * @param size Size of data.
193 *
194 * @return GNUNET_OK if everything goes well, GNUNET_SYSERR in case of en error.
195 */
196int
197GCCH_handle_local_data (struct CadetChannel *ch,
198 struct CadetClient *c, int fwd,
199 const struct GNUNET_MessageHeader *message,
200 size_t size);
201 124
202/** 125/**
203 * Handle a channel destroy requested by a client. 126 * Function called once and only once after a channel was bound
204 * 127 * to its tunnel via #GCT_add_channel() is ready for transmission.
205 * Destroy the channel and the tunnel in case this was the last channel. 128 * Note that this is only the case for channels that this peer
206 * 129 * initiates, as for incoming channels we assume that they are
207 * @param ch Channel. 130 * ready for transmission immediately upon receiving the open
208 * @param c Client that requested the destruction (to avoid notifying him). 131 * message. Used to bootstrap the #GCT_send() process.
209 * @param is_root Is the request coming from root? 132 *
133 * @param ch the channel for which the tunnel is now ready
210 */ 134 */
211void 135void
212GCCH_handle_local_destroy (struct CadetChannel *ch, 136GCCH_tunnel_up (struct CadetChannel *ch);
213 struct CadetClient *c,
214 int is_root);
215 137
216 138
217/** 139/**
218 * Handle a channel create requested by a client. 140 * Create a new channel based on a request coming in over the network.
219 * 141 *
220 * Create the channel and the tunnel in case this was the first0 channel. 142 * @param t tunnel to the remote peer
221 * 143 * @param chid identifier of this channel in the tunnel
222 * @param c Client that requested the creation (will be the root). 144 * @param origin peer to who initiated the channel
223 * @param msg Create Channel message. 145 * @param port desired local port
224 * 146 * @param options options for the channel
225 * @return #GNUNET_OK if everything went fine, #GNUNET_SYSERR otherwise. 147 * @return handle to the new channel
226 */ 148 */
227int 149struct CadetChannel *
228GCCH_handle_local_create (struct CadetClient *c, 150GCCH_channel_incoming_new (struct CadetTunnel *t,
229 struct GNUNET_CADET_LocalChannelCreateMessage *msg); 151 struct GNUNET_CADET_ChannelTunnelNumber chid,
230 152 const struct GNUNET_HashCode *port,
231/** 153 uint32_t options);
232 * Handler for cadet network payload traffic.
233 *
234 * @param ch Channel for the message.
235 * @param msg Unencryted data message.
236 * @param fwd Is this message fwd? This only is meaningful in loopback channels.
237 * #GNUNET_YES if message is FWD on the respective channel (loopback)
238 * #GNUNET_NO if message is BCK on the respective channel (loopback)
239 * #GNUNET_SYSERR if message on a one-ended channel (remote)
240 */
241void
242GCCH_handle_data (struct CadetChannel *ch,
243 const struct GNUNET_CADET_ChannelAppDataMessage *msg,
244 int fwd);
245 154
246 155
247/** 156/**
248 * Handler for cadet network traffic end-to-end ACKs. 157 * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for
158 * this channel. If the binding was successful, (re)transmit the
159 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.
249 * 160 *
250 * @param ch Channel on which we got this message. 161 * @param ch channel that got the duplicate open
251 * @param msg Data message. 162 * @param cti identifier of the connection that delivered the message
252 * @param fwd Is this message fwd? This only is meaningful in loopback channels.
253 * #GNUNET_YES if message is FWD on the respective channel (loopback)
254 * #GNUNET_NO if message is BCK on the respective channel (loopback)
255 * #GNUNET_SYSERR if message on a one-ended channel (remote)
256 */ 163 */
257void 164void
258GCCH_handle_data_ack (struct CadetChannel *ch, 165GCCH_handle_duplicate_open (struct CadetChannel *ch,
259 const struct GNUNET_CADET_ChannelDataAckMessage *msg, 166 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti);
260 int fwd);
261 167
262 168
263/**
264 * Handler for channel create messages.
265 *
266 * Does not have fwd parameter because it's always 'FWD': channel is incoming.
267 *
268 * @param t Tunnel this channel will be in.
269 * @param msg Channel crate message.
270 */
271struct CadetChannel *
272GCCH_handle_create (struct CadetTunnel *t,
273 const struct GNUNET_CADET_ChannelOpenMessage *msg);
274
275 169
276/** 170/**
277 * Handler for channel NACK messages. 171 * We got payload data for a channel. Pass it on to the client.
278 * 172 *
279 * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter. 173 * @param ch channel that got data
280 * 174 * @param cti identifier of the connection that delivered the message
281 * @param ch Channel. 175 * @param msg message that was received
282 */ 176 */
283void 177void
284GCCH_handle_nack (struct CadetChannel *ch); 178GCCH_handle_channel_plaintext_data (struct CadetChannel *ch,
179 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
180 const struct GNUNET_CADET_ChannelAppDataMessage *msg);
285 181
286 182
287/** 183/**
288 * Handler for channel ack messages. 184 * We got an acknowledgement for payload data for a channel.
185 * Possibly resume transmissions.
289 * 186 *
290 * @param ch Channel this channel is to be created in. 187 * @param ch channel that got the ack
291 * @param msg Message. 188 * @param cti identifier of the connection that delivered the message
292 * @param fwd Is this message fwd? This only is meaningful in loopback channels. 189 * @param ack details about what was received
293 * #GNUNET_YES if message is FWD on the respective channel (loopback)
294 * #GNUNET_NO if message is BCK on the respective channel (loopback)
295 * #GNUNET_SYSERR if message on a one-ended channel (remote)
296 */ 190 */
297void 191void
298GCCH_handle_ack (struct CadetChannel *ch, 192GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch,
299 const struct GNUNET_CADET_ChannelManageMessage *msg, 193 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
300 int fwd); 194 const struct GNUNET_CADET_ChannelDataAckMessage *ack);
301 195
302 196
303/** 197/**
304 * Handler for channel destroy messages. 198 * We got an acknowledgement for the creation of the channel
199 * (the port is open on the other side). Begin transmissions.
305 * 200 *
306 * @param ch Channel this channel is to be destroyed of. 201 * @param ch channel to destroy
307 * @param msg Message. 202 * @param cti identifier of the connection that delivered the message,
308 * @param fwd Is this message fwd? This only is meaningful in loopback channels. 203 * NULL if the ACK was inferred because we got payload or are on loopback
309 * #GNUNET_YES if message is FWD on the respective channel (loopback)
310 * #GNUNET_NO if message is BCK on the respective channel (loopback)
311 * #GNUNET_SYSERR if message on a one-ended channel (remote)
312 */ 204 */
313void 205void
314GCCH_handle_destroy (struct CadetChannel *ch, 206GCCH_handle_channel_open_ack (struct CadetChannel *ch,
315 const struct GNUNET_CADET_ChannelManageMessage *msg, 207 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti);
316 int fwd);
317 208
318 209
319/** 210/**
320 * Sends an already built message on a channel. 211 * Destroy channel, based on the other peer closing the
212 * connection. Also needs to remove this channel from
213 * the tunnel.
321 * 214 *
322 * If the channel is on a loopback tunnel, notifies the appropriate destination 215 * FIXME: need to make it possible to defer destruction until we have
323 * client locally. 216 * received all messages up to the destroy, and right now the destroy
217 * message (and this API) fails to give is the information we need!
324 * 218 *
325 * On a normal channel passes the message to the tunnel for encryption and 219 * FIXME: also need to know if the other peer got a destroy from
326 * sending on a connection. 220 * us before!
327 * 221 *
328 * This function DOES NOT save the message for retransmission. 222 * @param ch channel to destroy
329 * 223 * @param cti identifier of the connection that delivered the message,
330 * @param message Message to send. Function makes a copy of it. 224 * NULL during shutdown
331 * @param ch Channel on which this message is transmitted.
332 * @param fwd Is this a fwd message?
333 * @param existing_copy This is a retransmission, don't save a copy.
334 */ 225 */
335void 226void
336GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message, 227GCCH_handle_remote_destroy (struct CadetChannel *ch,
337 struct CadetChannel *ch, int fwd, 228 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti);
338 void *existing_copy);
339 229
340 230
341/** 231/**
342 * Get the static string for identification of the channel. 232 * Handle data given by a client.
343 * 233 *
344 * @param ch Channel.i 234 * Check whether the client is allowed to send in this tunnel, save if
235 * channel is reliable and send an ACK to the client if there is still
236 * buffer space in the tunnel.
345 * 237 *
346 * @return Static string with the channel IDs. 238 * @param ch Channel.
239 * @param sender_ccn ccn of the sender
240 * @param buf payload to transmit.
241 * @param buf_len number of bytes in @a buf
242 * @return #GNUNET_OK if everything goes well,
243 * #GNUNET_SYSERR in case of an error.
347 */ 244 */
348const char * 245int
349GCCH_2s (const struct CadetChannel *ch); 246GCCH_handle_local_data (struct CadetChannel *ch,
350 247 struct GNUNET_CADET_ClientChannelNumber sender_ccn,
351 248 const char *buf,
249 size_t buf_len);
352 250
353 251
354#if 0 /* keep Emacsens' auto-indent happy */ 252/**
355{ 253 * Handle ACK from client on local channel.
356#endif 254 *
357#ifdef __cplusplus 255 * @param ch channel to destroy
358} 256 * @param client_ccn ccn of the client sending the ack
359#endif 257 */
258void
259GCCH_handle_local_ack (struct CadetChannel *ch,
260 struct GNUNET_CADET_ClientChannelNumber client_ccn);
360 261
361/* ifndef GNUNET_SERVICE_CADET_CHANNEL_H */
362#endif 262#endif
363/* end of gnunet-service-cadet_channel.h */
diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c
index 2d5087f81..7b66f61a2 100644
--- a/src/cadet/gnunet-service-cadet_connection.c
+++ b/src/cadet/gnunet-service-cadet_connection.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2001-2015 GNUnet e.V. 3 Copyright (C) 2001-2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -17,242 +17,126 @@
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA. 18 Boston, MA 02110-1301, USA.
19*/ 19*/
20
20/** 21/**
21 * @file cadet/gnunet-service-cadet_connection.c 22 * @file cadet/gnunet-service-cadet_connection.c
22 * @brief GNUnet CADET service connection handling 23 * @brief management of CORE-level end-to-end connections; establishes
24 * end-to-end routes and transmits messages along the route
23 * @author Bartlomiej Polot 25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
24 */ 27 */
25#include "platform.h" 28#include "platform.h"
26#include "gnunet_util_lib.h" 29#include "gnunet-service-cadet_connection.h"
30#include "gnunet-service-cadet_channel.h"
31#include "gnunet-service-cadet_paths.h"
32#include "gnunet-service-cadet_tunnels.h"
33#include "gnunet_cadet_service.h"
27#include "gnunet_statistics_service.h" 34#include "gnunet_statistics_service.h"
28#include "cadet_path.h"
29#include "cadet_protocol.h" 35#include "cadet_protocol.h"
30#include "cadet.h"
31#include "gnunet-service-cadet_connection.h"
32#include "gnunet-service-cadet_peer.h"
33#include "gnunet-service-cadet_tunnel.h"
34
35
36/**
37 * Should we run somewhat expensive checks on our invariants?
38 */
39#define CHECK_INVARIANTS 0
40
41
42#define LOG(level, ...) GNUNET_log_from (level,"cadet-con",__VA_ARGS__)
43#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
44
45
46#define CADET_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\
47 GNUNET_TIME_UNIT_MINUTES,\
48 10)
49#define AVG_MSGS 32
50
51
52/******************************************************************************/
53/******************************** STRUCTS **********************************/
54/******************************************************************************/
55
56/**
57 * Handle for messages queued but not yet sent.
58 */
59struct CadetConnectionQueue
60{
61 36
62 struct CadetConnectionQueue *next;
63 struct CadetConnectionQueue *prev;
64 37
65 /** 38#define LOG(level, ...) GNUNET_log_from(level,"cadet-con",__VA_ARGS__)
66 * Peer queue handle, to cancel if necessary.
67 */
68 struct CadetPeerQueue *peer_q;
69
70 /**
71 * Continuation to call once sent.
72 */
73 GCC_sent cont;
74
75 /**
76 * Closure for @e cont.
77 */
78 void *cont_cls;
79
80 /**
81 * Was this a forced message? (Do not account for it)
82 */
83 int forced;
84};
85 39
86 40
87/** 41/**
88 * Struct to encapsulate all the Flow Control information to a peer to which 42 * All the states a connection can be in.
89 * we are directly connected (on a core level).
90 */ 43 */
91struct CadetFlowControl 44enum CadetConnectionState
92{ 45{
93 /** 46 /**
94 * Connection this controls. 47 * Uninitialized status, we have not yet even gotten the message queue.
95 */
96 struct CadetConnection *c;
97
98 struct CadetConnectionQueue *q_head;
99 struct CadetConnectionQueue *q_tail;
100
101 /**
102 * How many messages are in the queue on this connection.
103 */
104 unsigned int queue_n;
105
106 /**
107 * How many messages do we accept in the queue.
108 * If 0, the connection is broken in this direction (next hop disconnected).
109 */
110 unsigned int queue_max;
111
112 /**
113 * ID of the next packet to send.
114 */
115 struct CadetEncryptedMessageIdentifier next_pid;
116
117 /**
118 * ID of the last packet sent towards the peer.
119 */
120 struct CadetEncryptedMessageIdentifier last_pid_sent;
121
122 /**
123 * ID of the last packet received from the peer.
124 */
125 struct CadetEncryptedMessageIdentifier last_pid_recv;
126
127 /**
128 * Bitmap of past 32 messages received:
129 * - LSB being @c last_pid_recv.
130 * - MSB being @c last_pid_recv - 31 (mod UINTMAX).
131 */
132 uint32_t recv_bitmap;
133
134 /**
135 * Last ACK sent to the peer (peer is not allowed to send
136 * messages with PIDs higher than this value).
137 */ 48 */
138 struct CadetEncryptedMessageIdentifier last_ack_sent; 49 CADET_CONNECTION_NEW,
139 50
140 /** 51 /**
141 * Last ACK sent towards the origin (for traffic towards leaf node). 52 * Connection create message in queue, awaiting transmission by CORE.
142 */ 53 */
143 struct CadetEncryptedMessageIdentifier last_ack_recv; 54 CADET_CONNECTION_SENDING_CREATE,
144 55
145 /** 56 /**
146 * Task to poll the peer in case of a lost ACK causes stall. 57 * Connection create message sent, waiting for ACK.
147 */ 58 */
148 struct GNUNET_SCHEDULER_Task *poll_task; 59 CADET_CONNECTION_SENT,
149 60
150 /** 61 /**
151 * How frequently to poll for ACKs. 62 * We are an inbound connection, and received a CREATE. Need to
63 * send an CREATE_ACK back.
152 */ 64 */
153 struct GNUNET_TIME_Relative poll_time; 65 CADET_CONNECTION_CREATE_RECEIVED,
154 66
155 /** 67 /**
156 * Queued poll message, to cancel if not necessary anymore (got ACK). 68 * Connection confirmed, ready to carry traffic.
157 */ 69 */
158 struct CadetConnectionQueue *poll_msg; 70 CADET_CONNECTION_READY
159 71
160 /**
161 * Queued poll message, to cancel if not necessary anymore (got ACK).
162 */
163 struct CadetConnectionQueue *ack_msg;
164}; 72};
165 73
74
166/** 75/**
167 * Keep a record of the last messages sent on this connection. 76 * Low-level connection to a destination.
168 */ 77 */
169struct CadetConnectionPerformance 78struct CadetConnection
170{ 79{
171 /**
172 * Circular buffer for storing measurements.
173 */
174 double usecsperbyte[AVG_MSGS];
175 80
176 /** 81 /**
177 * Running average of @c usecsperbyte. 82 * ID of the connection.
178 */
179 double avg;
180
181 /**
182 * How many values of @c usecsperbyte are valid.
183 */
184 uint16_t size;
185
186 /**
187 * Index of the next "free" position in @c usecsperbyte.
188 */ 83 */
189 uint16_t idx; 84 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
190};
191
192 85
193/**
194 * Struct containing all information regarding a connection to a peer.
195 */
196struct CadetConnection
197{
198 /** 86 /**
199 * Tunnel this connection is part of. 87 * To which peer does this connection go?
200 */ 88 */
201 struct CadetTunnel *t; 89 struct CadetPeer *destination;
202 90
203 /** 91 /**
204 * Flow control information for traffic fwd. 92 * Which tunnel is using this connection?
205 */ 93 */
206 struct CadetFlowControl fwd_fc; 94 struct CadetTConnection *ct;
207 95
208 /** 96 /**
209 * Flow control information for traffic bck. 97 * Path we are using to our destination.
210 */ 98 */
211 struct CadetFlowControl bck_fc; 99 struct CadetPeerPath *path;
212 100
213 /** 101 /**
214 * Measure connection performance on the endpoint. 102 * Pending message, NULL if we are ready to transmit.
215 */ 103 */
216 struct CadetConnectionPerformance *perf; 104 struct GNUNET_MQ_Envelope *env;
217 105
218 /** 106 /**
219 * ID of the connection. 107 * Handle for calling #GCP_request_mq_cancel() once we are finished.
220 */ 108 */
221 struct GNUNET_CADET_ConnectionTunnelIdentifier id; 109 struct GCP_MessageQueueManager *mq_man;
222 110
223 /** 111 /**
224 * Path being used for the tunnel. At the origin of the connection 112 * Task for connection maintenance.
225 * it's a pointer to the destination's path pool, otherwise just a copy.
226 */ 113 */
227 struct CadetPeerPath *path; 114 struct GNUNET_SCHEDULER_Task *task;
228 115
229 /** 116 /**
230 * Task to keep the used paths alive at the owner, 117 * Queue entry for keepalive messages.
231 * time tunnel out on all the other peers.
232 */ 118 */
233 struct GNUNET_SCHEDULER_Task *fwd_maintenance_task; 119 struct CadetTunnelQueueEntry *keepalive_qe;
234 120
235 /** 121 /**
236 * Task to keep the used paths alive at the destination, 122 * Function to call once we are ready to transmit.
237 * time tunnel out on all the other peers.
238 */ 123 */
239 struct GNUNET_SCHEDULER_Task *bck_maintenance_task; 124 GCC_ReadyCallback ready_cb;
240 125
241 /** 126 /**
242 * Queue handle for maintainance traffic. One handle for FWD and BCK since 127 * Closure for @e ready_cb.
243 * one peer never needs to maintain both directions (no loopback connections).
244 */ 128 */
245 struct CadetPeerQueue *maintenance_q; 129 void *ready_cb_cls;
246 130
247 /** 131 /**
248 * Should equal #get_next_hop(), or NULL if that peer disconnected. 132 * How long do we wait before we try again with a CREATE message?
249 */ 133 */
250 struct CadetPeer *next_peer; 134 struct GNUNET_TIME_Relative retry_delay;
251 135
252 /** 136 /**
253 * Should equal #get_prev_hop(), or NULL if that peer disconnected. 137 * Performance metrics for this connection.
254 */ 138 */
255 struct CadetPeer *prev_peer; 139 struct CadetConnectionMetrics metrics;
256 140
257 /** 141 /**
258 * State of the connection. 142 * State of the connection.
@@ -260,221 +144,36 @@ struct CadetConnection
260 enum CadetConnectionState state; 144 enum CadetConnectionState state;
261 145
262 /** 146 /**
263 * Position of the local peer in the path. 147 * Options for the route, control buffering.
264 */ 148 */
265 unsigned int own_pos; 149 enum GNUNET_CADET_ChannelOption options;
266 150
267 /** 151 /**
268 * Pending message count. 152 * How many latency observations did we make for this connection?
269 */ 153 */
270 unsigned int pending_messages; 154 unsigned int latency_datapoints;
271 155
272 /** 156 /**
273 * Destroy flag: 157 * Offset of our @e destination in @e path.
274 * - if 0, connection in use.
275 * - if 1, destroy on last message.
276 * - if 2, connection is being destroyed don't re-enter.
277 */ 158 */
278 int destroy; 159 unsigned int off;
279 160
280 /** 161 /**
281 * In-connection-map flag. Sometimes, when @e destroy is set but 162 * Are we ready to transmit via @e mq_man right now?
282 * actual destruction is delayed to enable us to finish processing
283 * queues (i.e. in the direction that is still working), we remove
284 * the connection from the map to prevent it from still being
285 * found (and used) by accident. This flag is set to #GNUNET_YES
286 * for a connection that is not in the #connections map. Should
287 * only be #GNUNET_YES if #destroy is also non-zero.
288 */ 163 */
289 int was_removed; 164 int mqm_ready;
290 165
291 /**
292 * Counter to do exponential backoff when creating a connection (max 64).
293 */
294 unsigned short create_retry;
295
296 /**
297 * Task to check if connection has duplicates.
298 */
299 struct GNUNET_SCHEDULER_Task *check_duplicates_task;
300}; 166};
301 167
302 168
303/******************************************************************************/
304/******************************* GLOBALS ***********************************/
305/******************************************************************************/
306
307/**
308 * Global handle to the statistics service.
309 */
310extern struct GNUNET_STATISTICS_Handle *stats;
311
312/**
313 * Local peer own ID (memory efficient handle).
314 */
315extern GNUNET_PEER_Id myid;
316
317/**
318 * Local peer own ID (full value).
319 */
320extern struct GNUNET_PeerIdentity my_full_id;
321
322/**
323 * Connections known, indexed by cid (CadetConnection).
324 */
325static struct GNUNET_CONTAINER_MultiShortmap *connections;
326
327/**
328 * How many connections are we willing to maintain.
329 * Local connections are always allowed,
330 * even if there are more connections than max.
331 */
332static unsigned long long max_connections;
333
334/**
335 * How many messages *in total* are we willing to queue, divide by number of
336 * connections to get connection queue size.
337 */
338static unsigned long long max_msgs_queue;
339
340/**
341 * How often to send path keepalives. Paths timeout after 4 missed.
342 */
343static struct GNUNET_TIME_Relative refresh_connection_time;
344
345/**
346 * How often to send path create / ACKs.
347 */
348static struct GNUNET_TIME_Relative create_connection_time;
349
350
351/******************************************************************************/
352/******************************** STATIC ***********************************/
353/******************************************************************************/
354
355
356
357#if 0 // avoid compiler warning for unused static function
358static void
359fc_debug (struct CadetFlowControl *fc)
360{
361 LOG (GNUNET_ERROR_TYPE_DEBUG, " IN: %u/%u\n",
362 ntohl (fc->last_pid_recv.pid),
363 ntohl (fc->last_ack_sent.pid));
364 LOG (GNUNET_ERROR_TYPE_DEBUG, " OUT: %u/%u\n",
365 fc->last_pid_sent, fc->last_ack_recv);
366 LOG (GNUNET_ERROR_TYPE_DEBUG, " QUEUE: %u/%u\n",
367 fc->queue_n, fc->queue_max);
368}
369
370static void
371connection_debug (struct CadetConnection *c)
372{
373 if (NULL == c)
374 {
375 LOG (GNUNET_ERROR_TYPE_INFO, "DEBUG NULL CONNECTION\n");
376 return;
377 }
378 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
379 peer2s (c->t->peer), GCC_2s (c));
380 LOG (GNUNET_ERROR_TYPE_DEBUG, " state: %u, pending msgs: %u\n",
381 c->state, c->pending_messages);
382 LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n");
383 fc_debug (&c->fwd_fc);
384 LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n");
385 fc_debug (&c->bck_fc);
386}
387#endif
388
389
390/**
391 * Schedule next keepalive task, taking in consideration
392 * the connection state and number of retries.
393 *
394 * @param c Connection for which to schedule the next keepalive.
395 * @param fwd Direction for the next keepalive.
396 */
397static void
398schedule_next_keepalive (struct CadetConnection *c, int fwd);
399
400
401/**
402 * Resets the connection timeout task, some other message has done the
403 * task's job.
404 * - For the first peer on the direction this means to send
405 * a keepalive or a path confirmation message (either create or ACK).
406 * - For all other peers, this means to destroy the connection,
407 * due to lack of activity.
408 * Starts the timeout if no timeout was running (connection just created).
409 *
410 * @param c Connection whose timeout to reset.
411 * @param fwd Is this forward?
412 */
413static void
414connection_reset_timeout (struct CadetConnection *c, int fwd);
415
416
417/**
418 * Get string description for tunnel state. Reentrant.
419 *
420 * @param s Tunnel state.
421 *
422 * @return String representation.
423 */
424static const char *
425GCC_state2s (enum CadetConnectionState s)
426{
427 switch (s)
428 {
429 case CADET_CONNECTION_NEW:
430 return "CADET_CONNECTION_NEW";
431 case CADET_CONNECTION_SENT:
432 return "CADET_CONNECTION_SENT";
433 case CADET_CONNECTION_ACK:
434 return "CADET_CONNECTION_ACK";
435 case CADET_CONNECTION_READY:
436 return "CADET_CONNECTION_READY";
437 case CADET_CONNECTION_DESTROYED:
438 return "CADET_CONNECTION_DESTROYED";
439 case CADET_CONNECTION_BROKEN:
440 return "CADET_CONNECTION_BROKEN";
441 default:
442 GNUNET_break (0);
443 LOG (GNUNET_ERROR_TYPE_ERROR, " conn state %u unknown!\n", s);
444 return "CADET_CONNECTION_STATE_ERROR";
445 }
446}
447
448
449/** 169/**
450 * Initialize a Flow Control structure to the initial state. 170 * Lookup a connection by its identifier.
451 * 171 *
452 * @param fc Flow Control structure to initialize. 172 * @param cid identifier to resolve
173 * @return NULL if connection was not found
453 */ 174 */
454static void 175struct CadetConnection *
455fc_init (struct CadetFlowControl *fc) 176GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
456{
457 fc->next_pid.pid = 0;
458 fc->last_pid_sent.pid = htonl (UINT32_MAX);
459 fc->last_pid_recv.pid = htonl (UINT32_MAX);
460 fc->last_ack_sent.pid = (uint32_t) 0;
461 fc->last_ack_recv.pid = (uint32_t) 0;
462 fc->poll_task = NULL;
463 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
464 fc->queue_n = 0;
465 fc->queue_max = (max_msgs_queue / max_connections) + 1;
466}
467
468
469/**
470 * Find a connection.
471 *
472 * @param cid Connection ID.
473 *
474 * @return conntection with the given ID @cid or NULL if not found.
475 */
476static struct CadetConnection *
477connection_get (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
478{ 177{
479 return GNUNET_CONTAINER_multishortmap_get (connections, 178 return GNUNET_CONTAINER_multishortmap_get (connections,
480 &cid->connection_of_tunnel); 179 &cid->connection_of_tunnel);
@@ -482,3232 +181,911 @@ connection_get (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
482 181
483 182
484/** 183/**
485 * Change the connection state. Cannot change a connection marked as destroyed. 184 * Update the connection state. Also triggers the necessary
185 * MQM notifications.
486 * 186 *
487 * @param c Connection to change. 187 * @param cc connection to update the state for
488 * @param state New state to set. 188 * @param new_state new state for @a cc
189 * @param new_mqm_ready new `mqm_ready` state for @a cc
489 */ 190 */
490static void 191static void
491connection_change_state (struct CadetConnection* c, 192update_state (struct CadetConnection *cc,
492 enum CadetConnectionState state) 193 enum CadetConnectionState new_state,
194 int new_mqm_ready)
493{ 195{
494 LOG (GNUNET_ERROR_TYPE_DEBUG, 196 int old_ready;
495 "Connection %s state %s -> %s\n", 197 int new_ready;
496 GCC_2s (c), GCC_state2s (c->state), GCC_state2s (state));
497 if (CADET_CONNECTION_DESTROYED <= c->state) /* Destroyed or broken. */
498 {
499 LOG (GNUNET_ERROR_TYPE_DEBUG, "state not changing anymore\n");
500 return;
501 }
502 c->state = state;
503 if (CADET_CONNECTION_READY == state)
504 c->create_retry = 1;
505}
506
507 198
508/** 199 if ( (new_state == cc->state) &&
509 * Mark a connection as "destroyed", to send all pending traffic and freeing 200 (new_mqm_ready == cc->mqm_ready) )
510 * all associated resources, without accepting new status changes on it. 201 return; /* no change, nothing to do */
511 * 202 old_ready = ( (CADET_CONNECTION_READY == cc->state) &&
512 * @param c Connection to mark as destroyed. 203 (GNUNET_YES == cc->mqm_ready) );
513 */ 204 new_ready = ( (CADET_CONNECTION_READY == new_state) &&
514static void 205 (GNUNET_YES == new_mqm_ready) );
515mark_destroyed (struct CadetConnection *c) 206 cc->state = new_state;
516{ 207 cc->mqm_ready = new_mqm_ready;
517 c->destroy = GNUNET_YES; 208 if (old_ready != new_ready)
518 connection_change_state (c, CADET_CONNECTION_DESTROYED); 209 cc->ready_cb (cc->ready_cb_cls,
210 new_ready);
519} 211}
520 212
521 213
522/** 214/**
523 * Function called if a connection has been stalled for a while, 215 * Destroy a connection, part of the internal implementation. Called
524 * possibly due to a missed ACK. Poll the neighbor about its ACK status. 216 * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel().
525 *
526 * @param cls Closure (poll ctx).
527 */
528static void
529send_poll (void *cls);
530
531
532/**
533 * Send an ACK on the connection, informing the predecessor about
534 * the available buffer space. Should not be called in case the peer
535 * is origin (no predecessor) in the @c fwd direction.
536 *
537 * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
538 * the ACK itself goes "back" (dest->root).
539 * 217 *
540 * @param c Connection on which to send the ACK. 218 * @param cc connection to destroy
541 * @param buffer How much space free to advertise?
542 * @param fwd Is this FWD ACK? (Going dest -> root)
543 * @param force Don't optimize out.
544 */ 219 */
545static void 220static void
546send_ack (struct CadetConnection *c, 221GCC_destroy (struct CadetConnection *cc)
547 unsigned int buffer,
548 int fwd,
549 int force)
550{ 222{
551 static struct CadetEncryptedMessageIdentifier zero;
552 struct CadetFlowControl *next_fc;
553 struct CadetFlowControl *prev_fc;
554 struct GNUNET_CADET_ConnectionEncryptedAckMessage msg;
555 struct CadetEncryptedMessageIdentifier ack_cemi;
556 int delta;
557
558 GCC_check_connections ();
559 GNUNET_assert (GNUNET_NO == GCC_is_origin (c, fwd));
560
561 next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
562 prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
563
564 LOG (GNUNET_ERROR_TYPE_DEBUG, "send %s ack on %s\n",
565 GC_f2s (fwd), GCC_2s (c));
566
567 /* Check if we need to transmit the ACK. */
568 delta = ntohl (prev_fc->last_ack_sent.pid) - ntohl (prev_fc->last_pid_recv.pid);
569 if (3 < delta && buffer < delta && GNUNET_NO == force)
570 {
571 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, delta > 3\n");
572 LOG (GNUNET_ERROR_TYPE_DEBUG,
573 " last pid recv: %u, last ack sent: %u\n",
574 ntohl (prev_fc->last_pid_recv.pid),
575 ntohl (prev_fc->last_ack_sent.pid));
576 GCC_check_connections ();
577 return;
578 }
579
580 /* Ok, ACK might be necessary, what PID to ACK? */
581 ack_cemi.pid = htonl (ntohl (prev_fc->last_pid_recv.pid) + buffer);
582 LOG (GNUNET_ERROR_TYPE_DEBUG, 223 LOG (GNUNET_ERROR_TYPE_DEBUG,
583 " ACK %u, last PID %u, last ACK %u, qmax %u, q %u\n", 224 "Destroying %s\n",
584 ntohl (ack_cemi.pid), 225 GCC_2s (cc));
585 ntohl (prev_fc->last_pid_recv.pid), 226 if (NULL != cc->mq_man)
586 ntohl (prev_fc->last_ack_sent.pid),
587 next_fc->queue_max, next_fc->queue_n);
588 if ( (ack_cemi.pid == prev_fc->last_ack_sent.pid) &&
589 (GNUNET_NO == force) )
590 {
591 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
592 GCC_check_connections ();
593 return;
594 }
595
596 /* Check if message is already in queue */
597 if (NULL != prev_fc->ack_msg)
598 {
599 if (GC_is_pid_bigger (ntohl (ack_cemi.pid),
600 ntohl (prev_fc->last_ack_sent.pid)))
601 {
602 LOG (GNUNET_ERROR_TYPE_DEBUG, " canceling old ACK\n");
603 GCC_cancel (prev_fc->ack_msg);
604 /* GCC_cancel triggers ack_sent(), which clears fc->ack_msg */
605 }
606 else
607 {
608 LOG (GNUNET_ERROR_TYPE_DEBUG, " same ACK already in queue\n");
609 GCC_check_connections ();
610 return;
611 }
612 }
613 GNUNET_break (GC_is_pid_bigger (ntohl (ack_cemi.pid),
614 ntohl (prev_fc->last_ack_sent.pid)));
615 prev_fc->last_ack_sent = ack_cemi;
616
617 /* Build ACK message and send on conn */
618 msg.header.size = htons (sizeof (msg));
619 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK);
620 msg.cemi_max = ack_cemi;
621 msg.cid = c->id;
622
623 prev_fc->ack_msg = GCC_send_prebuilt_message (&msg.header,
624 UINT16_MAX,
625 zero,
626 c,
627 !fwd,
628 GNUNET_YES,
629 NULL, NULL);
630 GNUNET_assert (NULL != prev_fc->ack_msg);
631 GCC_check_connections ();
632}
633
634
635/**
636 * Update performance information if we are a connection's endpoint.
637 *
638 * @param c Connection to update.
639 * @param wait How much time did we wait to send the last message.
640 * @param size Size of the last message.
641 */
642static void
643update_perf (struct CadetConnection *c,
644 struct GNUNET_TIME_Relative wait,
645 uint16_t size)
646{
647 struct CadetConnectionPerformance *p;
648 double usecsperbyte;
649
650 if (NULL == c->perf)
651 return; /* Only endpoints are interested in timing. */
652
653 p = c->perf;
654 usecsperbyte = ((double) wait.rel_value_us) / size;
655 if (p->size == AVG_MSGS)
656 {
657 /* Array is full. Substract oldest value, add new one and store. */
658 p->avg -= (p->usecsperbyte[p->idx] / AVG_MSGS);
659 p->usecsperbyte[p->idx] = usecsperbyte;
660 p->avg += (p->usecsperbyte[p->idx] / AVG_MSGS);
661 }
662 else
663 {
664 /* Array not yet full. Add current value to avg and store. */
665 p->usecsperbyte[p->idx] = usecsperbyte;
666 p->avg *= p->size;
667 p->avg += p->usecsperbyte[p->idx];
668 p->size++;
669 p->avg /= p->size;
670 }
671 p->idx = (p->idx + 1) % AVG_MSGS;
672}
673
674
675/**
676 * Callback called when a connection queued message is sent.
677 *
678 * Calculates the average time and connection packet tracking.
679 *
680 * @param cls Closure (ConnectionQueue Handle), can be NULL.
681 * @param c Connection this message was on.
682 * @param fwd Was this a FWD going message?
683 * @param sent Was it really sent? (Could have been canceled)
684 * @param type Type of message sent.
685 * @param payload_type Type of payload, if applicable.
686 * @param pid Message ID, or 0 if not applicable (create, destroy, etc).
687 * @param size Size of the message.
688 * @param wait Time spent waiting for core (only the time for THIS message)
689 */
690static void
691conn_message_sent (void *cls,
692 struct CadetConnection *c,
693 int fwd,
694 int sent,
695 uint16_t type,
696 uint16_t payload_type,
697 struct CadetEncryptedMessageIdentifier pid,
698 size_t size,
699 struct GNUNET_TIME_Relative wait)
700{
701 struct CadetConnectionQueue *q = cls;
702 struct CadetFlowControl *fc;
703 int forced;
704
705 GCC_check_connections ();
706 LOG (GNUNET_ERROR_TYPE_INFO,
707 ">>> %s (%s %4u) on conn %s (%p) %s [%5u] in queue %s\n",
708 GC_m2s (type), GC_m2s (payload_type),
709 ntohl (pid.pid),
710 GCC_2s (c),
711 c,
712 GC_f2s (fwd), size,
713 GNUNET_STRINGS_relative_time_to_string (wait, GNUNET_YES));
714
715 /* If c is NULL, nothing to update. */
716 if (NULL == c)
717 {
718 if (type != GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
719 && type != GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY)
720 {
721 LOG (GNUNET_ERROR_TYPE_ERROR, "Message %s sent on NULL connection!\n",
722 GC_m2s (type));
723 }
724 GCC_check_connections ();
725 return;
726 }
727
728 LOG (GNUNET_ERROR_TYPE_DEBUG, " %ssent %s %s pid %u\n",
729 sent ? "" : "not ", GC_f2s (fwd),
730 GC_m2s (type), GC_m2s (payload_type),
731 ntohl (pid.pid));
732 GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG);
733
734 /* Update flow control info. */
735 fc = fwd ? &c->fwd_fc : &c->bck_fc;
736
737 if (NULL != q)
738 { 227 {
739 GNUNET_CONTAINER_DLL_remove (fc->q_head, fc->q_tail, q); 228 GCP_request_mq_cancel (cc->mq_man,
740 forced = q->forced; 229 NULL);
741 if (NULL != q->cont) 230 cc->mq_man = NULL;
742 {
743 LOG (GNUNET_ERROR_TYPE_DEBUG, " calling cont\n");
744 q->cont (q->cont_cls, c, q, type, fwd, size);
745 }
746 GNUNET_free (q);
747 } 231 }
748 else /* CONN_CREATE or CONN_ACK */ 232 if (NULL != cc->task)
749 { 233 {
750 GNUNET_assert (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED != type); 234 GNUNET_SCHEDULER_cancel (cc->task);
751 forced = GNUNET_YES; 235 cc->task = NULL;
752 } 236 }
753 237 if (NULL != cc->keepalive_qe)
754 LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P- %p %u\n", c, c->pending_messages);
755 c->pending_messages--;
756 if ( (GNUNET_YES == c->destroy) &&
757 (0 == c->pending_messages) )
758 { 238 {
759 LOG (GNUNET_ERROR_TYPE_DEBUG, 239 GCT_send_cancel (cc->keepalive_qe);
760 "! destroying connection!\n"); 240 cc->keepalive_qe = NULL;
761 GCC_destroy (c);
762 GCC_check_connections ();
763 return;
764 } 241 }
765 242 GCPP_del_connection (cc->path,
766 /* Send ACK if needed, after accounting for sent ID in fc->queue_n */ 243 cc->off,
767 switch (type) 244 cc);
768 { 245 for (unsigned int i=0;i<cc->off;i++)
769 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: 246 GCP_remove_connection (GCPP_get_peer_at_offset (cc->path,
770 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK: 247 i),
771 c->maintenance_q = NULL; 248 cc);
772 /* Don't trigger a keepalive for sent ACKs, only SYN and SYNACKs */ 249 GNUNET_assert (GNUNET_YES ==
773 if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE == type || !fwd) 250 GNUNET_CONTAINER_multishortmap_remove (connections,
774 schedule_next_keepalive (c, fwd); 251 &GCC_get_id (cc)->connection_of_tunnel,
775 break; 252 cc));
776 253 GNUNET_free (cc);
777 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED:
778 if (GNUNET_YES == sent)
779 {
780 fc->last_pid_sent = pid;
781 if (GC_is_pid_bigger (ntohl (fc->last_pid_sent.pid) + 1,
782 ntohl (fc->last_ack_recv.pid)) )
783 GCC_start_poll (c, fwd);
784 GCC_send_ack (c, fwd, GNUNET_NO);
785 connection_reset_timeout (c, fwd);
786 }
787
788 LOG (GNUNET_ERROR_TYPE_DEBUG, "! Q_N- %p %u\n", fc, fc->queue_n);
789 if (GNUNET_NO == forced)
790 {
791 fc->queue_n--;
792 LOG (GNUNET_ERROR_TYPE_DEBUG,
793 "! accounting pid %u\n",
794 ntohl (fc->last_pid_sent.pid));
795 }
796 else
797 {
798 LOG (GNUNET_ERROR_TYPE_DEBUG,
799 "! forced, Q_N not accounting pid %u\n",
800 ntohl (fc->last_pid_sent.pid));
801 }
802 break;
803
804 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX:
805 if (GNUNET_YES == sent)
806 connection_reset_timeout (c, fwd);
807 break;
808
809 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL:
810 fc->poll_msg = NULL;
811 if (2 == c->destroy)
812 {
813 LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL canceled on shutdown\n");
814 return;
815 }
816 if (0 == fc->queue_max)
817 {
818 LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL cancelled: neighbor disconnected\n");
819 return;
820 }
821 LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL sent for %s, scheduling new one!\n",
822 GCC_2s (c));
823 GNUNET_assert (NULL == fc->poll_task);
824 fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
825 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
826 &send_poll, fc);
827 LOG (GNUNET_ERROR_TYPE_DEBUG, " task %u\n", fc->poll_task);
828 break;
829
830 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK:
831 fc->ack_msg = NULL;
832 break;
833
834 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
835 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
836 break;
837
838 default:
839 LOG (GNUNET_ERROR_TYPE_ERROR, "%s unknown\n", GC_m2s (type));
840 GNUNET_break (0);
841 break;
842 }
843 LOG (GNUNET_ERROR_TYPE_DEBUG, "! message sent!\n");
844
845 update_perf (c, wait, size);
846 GCC_check_connections ();
847}
848
849
850/**
851 * Get the previous hop in a connection
852 *
853 * @param c Connection.
854 *
855 * @return Previous peer in the connection.
856 */
857static struct CadetPeer *
858get_prev_hop (const struct CadetConnection *c)
859{
860 GNUNET_PEER_Id id;
861
862 if (NULL == c->path)
863 return NULL;
864 LOG (GNUNET_ERROR_TYPE_DEBUG,
865 " get prev hop %s [%u/%u]\n",
866 GCC_2s (c), c->own_pos, c->path->length);
867 if (0 == c->own_pos || c->path->length < 2)
868 id = c->path->peers[0];
869 else
870 id = c->path->peers[c->own_pos - 1];
871
872 LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n",
873 GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id);
874
875 return GCP_get_short (id, GNUNET_YES);
876}
877
878
879/**
880 * Get the next hop in a connection
881 *
882 * @param c Connection.
883 *
884 * @return Next peer in the connection.
885 */
886static struct CadetPeer *
887get_next_hop (const struct CadetConnection *c)
888{
889 GNUNET_PEER_Id id;
890
891 if (NULL == c->path)
892 return NULL;
893
894 LOG (GNUNET_ERROR_TYPE_DEBUG, " get next hop %s [%u/%u]\n",
895 GCC_2s (c), c->own_pos, c->path->length);
896 if ((c->path->length - 1) == c->own_pos || c->path->length < 2)
897 id = c->path->peers[c->path->length - 1];
898 else
899 id = c->path->peers[c->own_pos + 1];
900
901 LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n",
902 GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id);
903
904 return GCP_get_short (id, GNUNET_YES);
905} 254}
906 255
907 256
908/**
909 * Check that the direct neighbours (previous and next hop)
910 * are properly associated with this connection.
911 *
912 * @param c connection to check
913 */
914static void
915check_neighbours (const struct CadetConnection *c)
916{
917 if (NULL == c->path)
918 return; /* nothing to check */
919 GCP_check_connection (get_next_hop (c), c);
920 GCP_check_connection (get_prev_hop (c), c);
921}
922
923 257
924/** 258/**
925 * Helper for #GCC_check_connections(). Calls #check_neighbours(). 259 * Destroy a connection, called when the CORE layer is already done
260 * (i.e. has received a BROKEN message), but if we still have to
261 * communicate the destruction of the connection to the tunnel (if one
262 * exists).
926 * 263 *
927 * @param cls NULL 264 * @param cc connection to destroy
928 * @param key ignored
929 * @param value the `struct CadetConnection` to check
930 * @return #GNUNET_OK (continue to iterate)
931 */
932static int
933check_connection (void *cls,
934 const struct GNUNET_ShortHashCode *key,
935 void *value)
936{
937 struct CadetConnection *c = value;
938
939 check_neighbours (c);
940 return GNUNET_OK;
941}
942
943
944/**
945 * Check invariants for all connections using #check_neighbours().
946 */ 265 */
947void 266void
948GCC_check_connections () 267GCC_destroy_without_core (struct CadetConnection *cc)
949{
950 if (0 == CHECK_INVARIANTS)
951 return;
952 if (NULL == connections)
953 return;
954 GNUNET_CONTAINER_multishortmap_iterate (connections,
955 &check_connection,
956 NULL);
957}
958
959
960/**
961 * Get the hop in a connection.
962 *
963 * @param c Connection.
964 * @param fwd Next in the FWD direction?
965 *
966 * @return Next peer in the connection.
967 */
968static struct CadetPeer *
969get_hop (struct CadetConnection *c, int fwd)
970{
971 return (fwd) ? get_next_hop (c) : get_prev_hop (c);
972}
973
974
975/**
976 * Get a bit mask for a message received out-of-order.
977 *
978 * @param last_pid_recv Last PID we received prior to the out-of-order.
979 * @param ooo_pid PID of the out-of-order message.
980 */
981static uint32_t
982get_recv_bitmask (struct CadetEncryptedMessageIdentifier last_pid_recv,
983 struct CadetEncryptedMessageIdentifier ooo_pid)
984{
985 // FIXME: should assert that the delta is in range...
986 return 1 << (ntohl (last_pid_recv.pid) - ntohl (ooo_pid.pid));
987}
988
989
990/**
991 * Check is an out-of-order message is ok:
992 * - at most 31 messages behind.
993 * - not duplicate.
994 *
995 * @param last_pid_recv Last in-order PID received.
996 */
997static int
998is_ooo_ok (struct CadetEncryptedMessageIdentifier last_pid_recv,
999 struct CadetEncryptedMessageIdentifier ooo_pid,
1000 uint32_t ooo_bitmap)
1001{
1002 uint32_t mask;
1003
1004 if (GC_is_pid_bigger (ntohl (last_pid_recv.pid) - 31,
1005 ntohl (ooo_pid.pid)))
1006 return GNUNET_NO;
1007
1008 mask = get_recv_bitmask (last_pid_recv,
1009 ooo_pid);
1010 if (0 != (ooo_bitmap & mask))
1011 return GNUNET_NO;
1012
1013 return GNUNET_YES;
1014}
1015
1016
1017/**
1018 * Is traffic coming from this sender 'FWD' traffic?
1019 *
1020 * @param c Connection to check.
1021 * @param sender Short peer identity of neighbor.
1022 *
1023 * @return #GNUNET_YES in case the sender is the 'prev' hop and therefore
1024 * the traffic is 'FWD'.
1025 * #GNUNET_NO for BCK.
1026 * #GNUNET_SYSERR for errors (sender isn't a hop in the connection).
1027 */
1028static int
1029is_fwd (const struct CadetConnection *c,
1030 const struct CadetPeer *sender)
1031{
1032 GNUNET_PEER_Id id;
1033
1034 id = GCP_get_short_id (sender);
1035 if (GCP_get_short_id (get_prev_hop (c)) == id)
1036 return GNUNET_YES;
1037
1038 if (GCP_get_short_id (get_next_hop (c)) == id)
1039 return GNUNET_NO;
1040
1041 return GNUNET_SYSERR;
1042}
1043
1044
1045/**
1046 * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
1047 * or a first CONNECTION_ACK directed to us.
1048 *
1049 * @param c Connection to confirm.
1050 * @param fwd Should we send it FWD? (root->dest)
1051 * (First (~SYNACK) goes BCK, second (~ACK) goes FWD)
1052 */
1053static void
1054send_connection_ack (struct CadetConnection *c, int fwd)
1055{
1056 static struct CadetEncryptedMessageIdentifier zero;
1057 struct GNUNET_CADET_ConnectionCreateAckMessage msg;
1058 struct CadetTunnel *t;
1059 const uint16_t size = sizeof (struct GNUNET_CADET_ConnectionCreateAckMessage);
1060 const uint16_t type = GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK;
1061
1062 GCC_check_connections ();
1063 t = c->t;
1064 LOG (GNUNET_ERROR_TYPE_INFO,
1065 "==> %s ({ C %s ACK} 0) on conn %s (%p) %s [%5u]\n",
1066 GC_m2s (type), GC_f2s (!fwd), GCC_2s (c), c, GC_f2s (fwd), size);
1067
1068 msg.header.size = htons (size);
1069 msg.header.type = htons (type);
1070 msg.reserved = htonl (0);
1071 msg.cid = c->id;
1072
1073 GNUNET_assert (NULL == c->maintenance_q);
1074 c->maintenance_q = GCP_send (get_hop (c, fwd),
1075 &msg.header,
1076 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
1077 zero,
1078 c,
1079 fwd,
1080 &conn_message_sent, NULL);
1081 LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u (conn`ACK)\n",
1082 c, c->pending_messages);
1083 c->pending_messages++;
1084
1085 if (CADET_TUNNEL_NEW == GCT_get_cstate (t))
1086 GCT_change_cstate (t, CADET_TUNNEL_WAITING);
1087 if (CADET_CONNECTION_READY != c->state)
1088 connection_change_state (c, CADET_CONNECTION_SENT);
1089 GCC_check_connections ();
1090}
1091
1092
1093/**
1094 * Send a notification that a connection is broken.
1095 *
1096 * @param c Connection that is broken.
1097 * @param id1 Peer that has disconnected.
1098 * @param id2 Peer that has disconnected.
1099 * @param fwd Direction towards which to send it.
1100 */
1101static void
1102send_broken (struct CadetConnection *c,
1103 const struct GNUNET_PeerIdentity *id1,
1104 const struct GNUNET_PeerIdentity *id2,
1105 int fwd)
1106{
1107 static struct CadetEncryptedMessageIdentifier zero;
1108 struct GNUNET_CADET_ConnectionBrokenMessage msg;
1109
1110 GCC_check_connections ();
1111 msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBrokenMessage));
1112 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
1113 msg.cid = c->id;
1114 msg.reserved = htonl (0);
1115 msg.peer1 = *id1;
1116 msg.peer2 = *id2;
1117 (void) GCC_send_prebuilt_message (&msg.header,
1118 UINT16_MAX,
1119 zero,
1120 c,
1121 fwd,
1122 GNUNET_YES,
1123 NULL, NULL);
1124 GCC_check_connections ();
1125}
1126
1127
1128/**
1129 * Send a notification that a connection is broken, when a connection
1130 * isn't even known to the local peer or soon to be destroyed.
1131 *
1132 * @param connection_id Connection ID.
1133 * @param id1 Peer that has disconnected, probably local peer.
1134 * @param id2 Peer that has disconnected can be NULL if unknown.
1135 * @param neighbor Peer to notify (neighbor who sent the connection).
1136 */
1137static void
1138send_broken_unknown (const struct GNUNET_CADET_ConnectionTunnelIdentifier *connection_id,
1139 const struct GNUNET_PeerIdentity *id1,
1140 const struct GNUNET_PeerIdentity *id2,
1141 struct CadetPeer *neighbor)
1142{
1143 static struct CadetEncryptedMessageIdentifier zero;
1144 struct GNUNET_CADET_ConnectionBrokenMessage msg;
1145
1146 GCC_check_connections ();
1147 LOG (GNUNET_ERROR_TYPE_INFO, "--> BROKEN on unknown connection %s\n",
1148 GNUNET_sh2s (&connection_id->connection_of_tunnel));
1149
1150 msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBrokenMessage));
1151 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
1152 msg.cid = *connection_id;
1153 msg.reserved = htonl (0);
1154 msg.peer1 = *id1;
1155 if (NULL != id2)
1156 msg.peer2 = *id2;
1157 else
1158 memset (&msg.peer2, 0, sizeof (msg.peer2));
1159 GNUNET_assert (NULL != GCP_send (neighbor,
1160 &msg.header,
1161 UINT16_MAX,
1162 zero,
1163 NULL,
1164 GNUNET_SYSERR, /* connection, fwd */
1165 NULL, NULL)); /* continuation */
1166 GCC_check_connections ();
1167}
1168
1169
1170/**
1171 * Send keepalive packets for a connection.
1172 *
1173 * @param c Connection to keep alive..
1174 * @param fwd Is this a FWD keepalive? (owner -> dest).
1175 */
1176static void
1177send_connection_keepalive (struct CadetConnection *c, int fwd)
1178{ 268{
1179 struct GNUNET_MessageHeader msg; 269 if (NULL != cc->ct)
1180 struct CadetFlowControl *fc;
1181 int tunnel_ready;
1182
1183 GCC_check_connections ();
1184 LOG (GNUNET_ERROR_TYPE_INFO,
1185 "keepalive %s for connection %s\n",
1186 GC_f2s (fwd), GCC_2s (c));
1187
1188 GNUNET_assert (NULL != c->t);
1189 fc = fwd ? &c->fwd_fc : &c->bck_fc;
1190 tunnel_ready = GNUNET_YES == GCT_has_queued_traffic (c->t)
1191 && CADET_TUNNEL_KEY_OK <= GCT_get_estate (c->t);
1192 if (0 < fc->queue_n || tunnel_ready)
1193 { 270 {
1194 LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, traffic in queue\n"); 271 GCT_connection_lost (cc->ct);
1195 return; 272 cc->ct = NULL;
1196 } 273 }
1197 274 GCC_destroy (cc);
1198 GNUNET_STATISTICS_update (stats, "# keepalives sent", 1, GNUNET_NO);
1199
1200 GNUNET_assert (NULL != c->t);
1201 msg.size = htons (sizeof (msg));
1202 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
1203
1204 GNUNET_assert (NULL ==
1205 GCT_send_prebuilt_message (&msg, c->t, c,
1206 GNUNET_NO, NULL, NULL));
1207 GCC_check_connections ();
1208}
1209
1210
1211/**
1212 * Send CONNECTION_{CREATE/ACK} packets for a connection.
1213 *
1214 * @param c Connection for which to send the message.
1215 * @param fwd If #GNUNET_YES, send CREATE, otherwise send ACK.
1216 */
1217static void
1218connection_recreate (struct CadetConnection *c, int fwd)
1219{
1220 LOG (GNUNET_ERROR_TYPE_DEBUG,
1221 "sending connection recreate\n");
1222 if (fwd)
1223 GCC_send_create (c);
1224 else
1225 send_connection_ack (c, GNUNET_NO);
1226} 275}
1227 276
1228 277
1229/** 278/**
1230 * Generic connection timer management. 279 * Destroy a connection, called if the tunnel association with the
1231 * Depending on the role of the peer in the connection will send the 280 * connection was already broken, but we still need to notify the CORE
1232 * appropriate message (build or keepalive) 281 * layer about the breakage.
1233 * 282 *
1234 * @param c Conncetion to maintain. 283 * @param cc connection to destroy
1235 * @param fwd Is FWD?
1236 */ 284 */
1237static void 285void
1238connection_maintain (struct CadetConnection *c, int fwd) 286GCC_destroy_without_tunnel (struct CadetConnection *cc)
1239{ 287{
1240 if (GNUNET_NO != c->destroy) 288 cc->ct = NULL;
289 if ( (CADET_CONNECTION_SENDING_CREATE != cc->state) &&
290 (NULL != cc->mq_man) )
1241 { 291 {
1242 LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, being destroyed\n"); 292 struct GNUNET_MQ_Envelope *env;
1243 return; 293 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
1244 }
1245
1246 if (NULL == c->t)
1247 {
1248 GNUNET_break (0);
1249 GCC_debug (c, GNUNET_ERROR_TYPE_ERROR);
1250 return;
1251 }
1252 294
1253 if (CADET_TUNNEL_SEARCHING == GCT_get_cstate (c->t)) 295 /* Need to notify next hop that we are down. */
1254 { 296 env = GNUNET_MQ_msg (destroy_msg,
1255 /* If status is SEARCHING, why is there a connection? Should be WAITING */ 297 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
1256 GNUNET_break (0); 298 destroy_msg->cid = cc->cid;
1257 GCT_debug (c->t, GNUNET_ERROR_TYPE_ERROR); 299 GCP_request_mq_cancel (cc->mq_man,
1258 LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, tunnel SEARCHING\n"); 300 env);
1259 schedule_next_keepalive (c, fwd); 301 cc->mq_man = NULL;
1260 return;
1261 }
1262 switch (c->state)
1263 {
1264 case CADET_CONNECTION_NEW:
1265 GNUNET_break (0);
1266 /* fall-through */
1267 case CADET_CONNECTION_SENT:
1268 connection_recreate (c, fwd);
1269 break;
1270 case CADET_CONNECTION_READY:
1271 send_connection_keepalive (c, fwd);
1272 break;
1273 default:
1274 break;
1275 } 302 }
303 GCC_destroy (cc);
1276} 304}
1277 305
1278 306
1279/** 307/**
1280 * Keep the connection alive. 308 * Return the tunnel associated with this connection.
1281 * 309 *
1282 * @param c Connection to keep alive. 310 * @param cc connection to query
1283 * @param fwd Direction. 311 * @return corresponding entry in the tunnel's connection list
1284 */ 312 */
1285static void 313struct CadetTConnection *
1286connection_keepalive (struct CadetConnection *c, 314GCC_get_ct (struct CadetConnection *cc)
1287 int fwd)
1288{ 315{
1289 GCC_check_connections (); 316 return cc->ct;
1290 LOG (GNUNET_ERROR_TYPE_DEBUG,
1291 "%s keepalive for %s\n",
1292 GC_f2s (fwd), GCC_2s (c));
1293
1294 if (fwd)
1295 c->fwd_maintenance_task = NULL;
1296 else
1297 c->bck_maintenance_task = NULL;
1298 connection_maintain (c, fwd);
1299 GCC_check_connections ();
1300 /* Next execution will be scheduled by message_sent or _maintain*/
1301} 317}
1302 318
1303 319
1304/** 320/**
1305 * Keep the connection alive in the FWD direction. 321 * Obtain performance @a metrics from @a cc.
1306 * 322 *
1307 * @param cls Closure (connection to keepalive). 323 * @param cc connection to query
324 * @return the metrics
1308 */ 325 */
1309static void 326const struct CadetConnectionMetrics *
1310connection_fwd_keepalive (void *cls) 327GCC_get_metrics (struct CadetConnection *cc)
1311{ 328{
1312 struct CadetConnection *c = cls; 329 return &cc->metrics;
1313
1314 GCC_check_connections ();
1315 connection_keepalive (c,
1316 GNUNET_YES);
1317 GCC_check_connections ();
1318} 330}
1319 331
1320 332
1321/** 333/**
1322 * Keep the connection alive in the BCK direction. 334 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
335 * tunnel to prevent it from timing out.
1323 * 336 *
1324 * @param cls Closure (connection to keepalive). 337 * @param cls the `struct CadetConnection` to keep alive.
1325 */ 338 */
1326static void 339static void
1327connection_bck_keepalive (void *cls) 340send_keepalive (void *cls);
1328{
1329 struct CadetConnection *c = cls;
1330
1331 GCC_check_connections ();
1332 connection_keepalive (c,
1333 GNUNET_NO);
1334 GCC_check_connections ();
1335}
1336 341
1337 342
1338/** 343/**
1339 * Schedule next keepalive task, taking in consideration 344 * Keepalive was transmitted. Remember this, and possibly
1340 * the connection state and number of retries. 345 * schedule the next one.
1341 * 346 *
1342 * If the peer is not the origin, do nothing. 347 * @param cls the `struct CadetConnection` to keep alive.
1343 * 348 * @param cid identifier of the connection within the tunnel, NULL
1344 * @param c Connection for which to schedule the next keepalive. 349 * if transmission failed
1345 * @param fwd Direction for the next keepalive.
1346 */ 350 */
1347static void 351static void
1348schedule_next_keepalive (struct CadetConnection *c, int fwd) 352keepalive_done (void *cls,
353 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
1349{ 354{
1350 struct GNUNET_TIME_Relative delay; 355 struct CadetConnection *cc = cls;
1351 struct GNUNET_SCHEDULER_Task * *task_id;
1352 GNUNET_SCHEDULER_TaskCallback keepalive_task;
1353
1354 GCC_check_connections ();
1355 if (GNUNET_NO == GCC_is_origin (c, fwd))
1356 return;
1357
1358 /* Calculate delay to use, depending on the state of the connection */
1359 if (CADET_CONNECTION_READY == c->state)
1360 {
1361 delay = refresh_connection_time;
1362 }
1363 else
1364 {
1365 if (1 > c->create_retry)
1366 c->create_retry = 1;
1367 delay = GNUNET_TIME_relative_saturating_multiply (create_connection_time,
1368 c->create_retry);
1369 if (c->create_retry < 64) // TODO make configurable
1370 c->create_retry *= 2;
1371 }
1372
1373 /* Select direction-dependent parameters */
1374 if (GNUNET_YES == fwd)
1375 {
1376 task_id = &c->fwd_maintenance_task;
1377 keepalive_task = &connection_fwd_keepalive;
1378 }
1379 else
1380 {
1381 task_id = &c->bck_maintenance_task;
1382 keepalive_task = &connection_bck_keepalive;
1383 }
1384 356
1385 /* Check that no one scheduled it before us */ 357 cc->keepalive_qe = NULL;
1386 if (NULL != *task_id) 358 if ( (GNUNET_YES == cc->mqm_ready) &&
1387 { 359 (NULL == cc->task) )
1388 /* No need for a _break. It can happen for instance when sending a SYNACK 360 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
1389 * for a duplicate SYN: the first SYNACK scheduled the task. */ 361 &send_keepalive,
1390 GNUNET_SCHEDULER_cancel (*task_id); 362 cc);
1391 }
1392
1393 /* Schedule the task */
1394 *task_id = GNUNET_SCHEDULER_add_delayed (delay,
1395 keepalive_task,
1396 c);
1397 LOG (GNUNET_ERROR_TYPE_INFO,
1398 "next keepalive for %s in in %s\n",
1399 GCC_2s (c), GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
1400 GCC_check_connections ();
1401} 363}
1402 364
1403 365
1404/** 366/**
1405 * Cancel all transmissions that belong to a certain connection. 367 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
368 * tunnel to prevent it from timing out.
1406 * 369 *
1407 * If the connection is scheduled for destruction and no more messages are left, 370 * @param cls the `struct CadetConnection` to keep alive.
1408 * the connection will be destroyed by the continuation call.
1409 *
1410 * @param c Connection which to cancel. Might be destroyed during this call.
1411 * @param fwd Cancel fwd traffic?
1412 */ 371 */
1413static void 372static void
1414connection_cancel_queues (struct CadetConnection *c, 373send_keepalive (void *cls)
1415 int fwd)
1416{ 374{
1417 struct CadetFlowControl *fc; 375 struct CadetConnection *cc = cls;
376 struct GNUNET_MessageHeader msg;
1418 377
1419 GCC_check_connections (); 378 cc->task = NULL;
1420 LOG (GNUNET_ERROR_TYPE_DEBUG, 379 if (CADET_TUNNEL_KEY_OK != GCT_get_estate (cc->ct->t))
1421 "Cancel %s queues for connection %s\n",
1422 GC_f2s (fwd), GCC_2s (c));
1423 if (NULL == c)
1424 { 380 {
1425 GNUNET_break (0); 381 /* Tunnel not yet ready, wait with keepalives... */
382 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
383 &send_keepalive,
384 cc);
1426 return; 385 return;
1427 } 386 }
1428 387 GNUNET_assert (NULL != cc->ct);
1429 fc = fwd ? &c->fwd_fc : &c->bck_fc; 388 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
1430 if (NULL != fc->poll_task) 389 GNUNET_assert (NULL == cc->keepalive_qe);
1431 {
1432 GNUNET_SCHEDULER_cancel (fc->poll_task);
1433 fc->poll_task = NULL;
1434 LOG (GNUNET_ERROR_TYPE_DEBUG, " cancelled POLL task for fc %p\n", fc);
1435 }
1436 if (NULL != fc->poll_msg)
1437 {
1438 GCC_cancel (fc->poll_msg);
1439 LOG (GNUNET_ERROR_TYPE_DEBUG, " cancelled POLL msg for fc %p\n", fc);
1440 }
1441
1442 while (NULL != fc->q_head)
1443 {
1444 GCC_cancel (fc->q_head);
1445 }
1446 GCC_check_connections ();
1447}
1448
1449
1450/**
1451 * Function called if a connection has been stalled for a while,
1452 * possibly due to a missed ACK. Poll the neighbor about its ACK status.
1453 *
1454 * @param cls Closure (poll ctx).
1455 */
1456static void
1457send_poll (void *cls)
1458{
1459 static struct CadetEncryptedMessageIdentifier zero;
1460 struct CadetFlowControl *fc = cls;
1461 struct GNUNET_CADET_ConnectionHopByHopPollMessage msg;
1462 struct CadetConnection *c;
1463 int fwd;
1464
1465 fc->poll_task = NULL;
1466 GCC_check_connections ();
1467 c = fc->c;
1468 fwd = fc == &c->fwd_fc;
1469 LOG (GNUNET_ERROR_TYPE_DEBUG, "Polling connection %s %s\n",
1470 GCC_2s (c), GC_f2s (fwd));
1471
1472 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL);
1473 msg.header.size = htons (sizeof (msg));
1474 msg.cid = c->id;
1475 msg.cemi = fc->last_pid_sent;
1476 LOG (GNUNET_ERROR_TYPE_DEBUG, " last pid sent: %u\n", ntohl (fc->last_pid_sent.pid));
1477 fc->poll_msg
1478 = GCC_send_prebuilt_message (&msg.header,
1479 UINT16_MAX,
1480 zero,
1481 c,
1482 fc == &c->fwd_fc,
1483 GNUNET_YES,
1484 NULL,
1485 NULL);
1486 GNUNET_assert (NULL != fc->poll_msg);
1487 GCC_check_connections ();
1488}
1489
1490
1491/**
1492 * Generic connection timeout implementation.
1493 *
1494 * Timeout function due to lack of keepalive/traffic from an endpoint.
1495 * Destroys connection if called.
1496 *
1497 * @param c Connection to destroy.
1498 * @param fwd Was the timeout from the origin? (FWD timeout)
1499 */
1500static void
1501connection_timeout (struct CadetConnection *c, int fwd)
1502{
1503 GCC_check_connections ();
1504
1505 LOG (GNUNET_ERROR_TYPE_INFO, 390 LOG (GNUNET_ERROR_TYPE_INFO,
1506 "Connection %s %s timed out. Destroying.\n", 391 "Sending KEEPALIVE on behalf of %s via %s\n",
1507 GCC_2s (c), 392 GCC_2s (cc),
1508 GC_f2s (fwd)); 393 GCT_2s (cc->ct->t));
1509 GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG); 394 GNUNET_STATISTICS_update (stats,
1510 395 "# keepalives sent",
1511 if (GCC_is_origin (c, fwd)) /* Loopback? Something is wrong! */ 396 1,
1512 { 397 GNUNET_NO);
1513 GNUNET_break (0); 398 msg.size = htons (sizeof (msg));
1514 return; 399 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
1515 }
1516
1517 /* If dest, send "broken" notification. */
1518 if (GCC_is_terminal (c, fwd))
1519 {
1520 struct CadetPeer *next_hop;
1521
1522 next_hop = fwd ? get_prev_hop (c) : get_next_hop (c);
1523 send_broken_unknown (&c->id, &my_full_id, NULL, next_hop);
1524 }
1525
1526 GCC_destroy (c);
1527 GCC_check_connections ();
1528}
1529
1530
1531/**
1532 * Timeout function due to lack of keepalive/traffic from the owner.
1533 * Destroys connection if called.
1534 *
1535 * @param cls Closure (connection to destroy).
1536 */
1537static void
1538connection_fwd_timeout (void *cls)
1539{
1540 struct CadetConnection *c = cls;
1541
1542 c->fwd_maintenance_task = NULL;
1543 GCC_check_connections ();
1544 connection_timeout (c, GNUNET_YES);
1545 GCC_check_connections ();
1546}
1547
1548
1549/**
1550 * Timeout function due to lack of keepalive/traffic from the destination.
1551 * Destroys connection if called.
1552 *
1553 * @param cls Closure (connection to destroy).
1554 */
1555static void
1556connection_bck_timeout (void *cls)
1557{
1558 struct CadetConnection *c = cls;
1559 400
1560 c->bck_maintenance_task = NULL; 401 cc->keepalive_qe
1561 GCC_check_connections (); 402 = GCT_send (cc->ct->t,
1562 connection_timeout (c, GNUNET_NO); 403 &msg,
1563 GCC_check_connections (); 404 &keepalive_done,
405 cc);
1564} 406}
1565 407
1566 408
1567/** 409/**
1568 * Resets the connection timeout task, some other message has done the 410 * We sent a message for which we expect to receive an ACK via
1569 * task's job. 411 * the connection identified by @a cti.
1570 * - For the first peer on the direction this means to send
1571 * a keepalive or a path confirmation message (either create or ACK).
1572 * - For all other peers, this means to destroy the connection,
1573 * due to lack of activity.
1574 * Starts the timeout if no timeout was running (connection just created).
1575 *
1576 * @param c Connection whose timeout to reset.
1577 * @param fwd Is this forward?
1578 * 412 *
1579 * TODO use heap to improve efficiency of scheduler. 413 * @param cid connection identifier where we expect an ACK
1580 */ 414 */
1581static void 415void
1582connection_reset_timeout (struct CadetConnection *c, int fwd) 416GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
1583{ 417{
1584 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s reset timeout\n", GC_f2s (fwd)); 418 struct CadetConnection *cc;
1585 if (GCC_is_origin (c, fwd)) /* Startpoint */
1586 {
1587 schedule_next_keepalive (c, fwd);
1588 if (NULL != c->maintenance_q)
1589 {
1590 GCP_send_cancel (c->maintenance_q);
1591 c->maintenance_q = NULL; /* Is set to NULL by conn_message_sent anyway */
1592 }
1593 }
1594 else /* Relay, endpoint. */
1595 {
1596 struct GNUNET_TIME_Relative delay;
1597 struct GNUNET_SCHEDULER_Task * *ti;
1598 GNUNET_SCHEDULER_TaskCallback f;
1599
1600 ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task;
1601 419
1602 if (NULL != *ti) 420 cc = GCC_lookup (cid);
1603 GNUNET_SCHEDULER_cancel (*ti); 421 if (NULL == cc)
1604 delay = GNUNET_TIME_relative_saturating_multiply (refresh_connection_time, 4); 422 return; /* whopise, connection alredy down? */
1605 LOG (GNUNET_ERROR_TYPE_DEBUG, 423 cc->metrics.num_acked_transmissions++;
1606 " timing out in %s\n",
1607 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_NO));
1608 f = fwd ? &connection_fwd_timeout : &connection_bck_timeout;
1609 *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c);
1610 }
1611} 424}
1612 425
1613 426
1614/** 427/**
1615 * Iterator to compare each connection's path with the path of a new connection. 428 * We observed an ACK for a message that was originally sent via
429 * the connection identified by @a cti.
1616 * 430 *
1617 * If the connection coincides, the c member of path is set to the connection 431 * @param cti connection identifier where we got an ACK for a message
1618 * and the destroy flag of the connection is set. 432 * that was originally sent via this connection (the ACK
1619 * 433 * may have gotten back to us via a different connection).
1620 * @param cls Closure (new path).
1621 * @param c Connection in the tunnel to check.
1622 */ 434 */
1623static void 435void
1624check_path (void *cls, struct CadetConnection *c) 436GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
1625{ 437{
1626 struct CadetConnection *new_conn = cls; 438 struct CadetConnection *cc;
1627 struct CadetPeerPath *path = new_conn->path;
1628
1629 LOG (GNUNET_ERROR_TYPE_DEBUG, " checking %s (%p), length %u\n",
1630 GCC_2s (c), c, c->path->length);
1631 439
1632 if (c != new_conn 440 cc = GCC_lookup (cid);
1633 && GNUNET_NO == c->destroy 441 if (NULL == cc)
1634 && CADET_CONNECTION_BROKEN != c->state 442 return; /* whopise, connection alredy down? */
1635 && CADET_CONNECTION_DESTROYED != c->state 443 cc->metrics.num_successes++;
1636 && path_equivalent (path, c->path))
1637 {
1638 new_conn->destroy = GNUNET_YES; /* Do not mark_destroyed, */
1639 new_conn->path->c = c; /* this is only a flag for the Iterator. */
1640 LOG (GNUNET_ERROR_TYPE_DEBUG, " MATCH!\n");
1641 }
1642} 444}
1643 445
1644 446
1645/** 447/**
1646 * Finds out if this path is already being used by an existing connection. 448 * We observed some the given @a latency on the connection
1647 * 449 * identified by @a cti. (The same connection was taken
1648 * Checks the tunnel towards the destination to see if it contains 450 * in both directions.)
1649 * any connection with the same path.
1650 * 451 *
1651 * If the existing connection is ready, it is kept. 452 * @param cid connection identifier where we measured latency
1652 * Otherwise if the sender has a smaller ID that ours, we accept it (and 453 * @param latency the observed latency
1653 * the peer will eventually reject our attempt).
1654 *
1655 * @param path Path to check.
1656 * @return #GNUNET_YES if the tunnel has a connection with the same path,
1657 * #GNUNET_NO otherwise.
1658 */ 454 */
1659static int 455void
1660does_connection_exist (struct CadetConnection *conn) 456GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
457 struct GNUNET_TIME_Relative latency)
1661{ 458{
1662 struct CadetPeer *p; 459 struct CadetConnection *cc;
1663 struct CadetTunnel *t; 460 double weight;
1664 struct CadetConnection *c; 461 double result;
1665
1666 p = GCP_get_short (conn->path->peers[0], GNUNET_NO);
1667 if (NULL == p)
1668 return GNUNET_NO;
1669 t = GCP_get_tunnel (p);
1670 if (NULL == t)
1671 return GNUNET_NO;
1672
1673 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking for duplicates\n");
1674 462
1675 GCT_iterate_connections (t, &check_path, conn); 463 cc = GCC_lookup (cid);
1676 464 if (NULL == cc)
1677 if (GNUNET_YES == conn->destroy) 465 return; /* whopise, connection alredy down? */
1678 { 466 GNUNET_STATISTICS_update (stats,
1679 c = conn->path->c; 467 "# latencies observed",
1680 conn->destroy = GNUNET_NO; 468 1,
1681 conn->path->c = conn; 469 GNUNET_NO);
1682 LOG (GNUNET_ERROR_TYPE_DEBUG, " found duplicate of %s\n", GCC_2s (conn)); 470 cc->latency_datapoints++;
1683 LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate: %s\n", GCC_2s (c)); 471 if (cc->latency_datapoints >= 7)
1684 GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG); 472 weight = 7.0;
1685 if (CADET_CONNECTION_READY == c->state)
1686 {
1687 /* The other peer confirmed a live connection with this path,
1688 * why are they trying to duplicate it? */
1689 GNUNET_STATISTICS_update (stats, "# duplicate connections", 1, GNUNET_NO);
1690 return GNUNET_YES;
1691 }
1692 LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate not ready, connection unique\n");
1693 return GNUNET_NO;
1694 }
1695 else 473 else
1696 { 474 weight = cc->latency_datapoints;
1697 LOG (GNUNET_ERROR_TYPE_DEBUG, " %s has no duplicates\n", GCC_2s (conn)); 475 /* Compute weighted average, giving at MOST weight 7 to the
1698 return GNUNET_NO; 476 existing values, or less if that value is based on fewer than 7
1699 } 477 measurements. */
478 result = (weight * cc->metrics.aged_latency.rel_value_us) + 1.0 * latency.rel_value_us;
479 result /= (weight + 1.0);
480 cc->metrics.aged_latency.rel_value_us = (uint64_t) result;
1700} 481}
1701 482
1702 483
1703/** 484/**
1704 * @brief Check if the tunnel this connection belongs to has any other 485 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for this connection, implying
1705 * connection with the same path, and destroy one if so. 486 * that the end-to-end connection is up. Process it.
1706 * 487 *
1707 * @param cls Closure (connection to check). 488 * @param cc the connection that got the ACK.
1708 */
1709static void
1710check_duplicates (void *cls)
1711{
1712 struct CadetConnection *c = cls;
1713
1714 c->check_duplicates_task = NULL;
1715 if (GNUNET_YES == does_connection_exist (c))
1716 {
1717 GCT_debug (c->t, GNUNET_ERROR_TYPE_DEBUG);
1718 send_broken (c, &my_full_id, &my_full_id, GCC_is_origin (c, GNUNET_YES));
1719 GCC_destroy (c);
1720 }
1721}
1722
1723
1724/**
1725 * Wait for enough time to let any dead connections time out and check for
1726 * any remaining duplicates.
1727 *
1728 * @param c Connection that is a potential duplicate.
1729 */
1730static void
1731schedule_check_duplicates (struct CadetConnection *c)
1732{
1733 struct GNUNET_TIME_Relative delay;
1734
1735 if (NULL != c->check_duplicates_task)
1736 return;
1737 delay = GNUNET_TIME_relative_saturating_multiply (refresh_connection_time, 5);
1738 c->check_duplicates_task = GNUNET_SCHEDULER_add_delayed (delay,
1739 &check_duplicates,
1740 c);
1741}
1742
1743
1744/**
1745 * Add the connection to the list of both neighbors.
1746 *
1747 * @param c Connection.
1748 *
1749 * @return #GNUNET_OK if everything went fine
1750 * #GNUNET_SYSERR if the was an error and @c c is malformed.
1751 */
1752static int
1753register_neighbors (struct CadetConnection *c)
1754{
1755 c->next_peer = get_next_hop (c);
1756 c->prev_peer = get_prev_hop (c);
1757 GNUNET_assert (c->next_peer != c->prev_peer);
1758 LOG (GNUNET_ERROR_TYPE_DEBUG,
1759 "register neighbors for connection %s\n",
1760 GCC_2s (c));
1761 path_debug (c->path);
1762 LOG (GNUNET_ERROR_TYPE_DEBUG,
1763 "own pos %u\n", c->own_pos);
1764 LOG (GNUNET_ERROR_TYPE_DEBUG,
1765 "putting connection %s to next peer %p\n",
1766 GCC_2s (c),
1767 c->next_peer);
1768 LOG (GNUNET_ERROR_TYPE_DEBUG, "next peer %p %s\n",
1769 c->next_peer,
1770 GCP_2s (c->next_peer));
1771 LOG (GNUNET_ERROR_TYPE_DEBUG,
1772 "putting connection %s to prev peer %p\n",
1773 GCC_2s (c),
1774 c->prev_peer);
1775 LOG (GNUNET_ERROR_TYPE_DEBUG,
1776 "prev peer %p %s\n",
1777 c->prev_peer,
1778 GCP_2s (c->prev_peer));
1779
1780 if ( (GNUNET_NO == GCP_is_neighbor (c->next_peer)) ||
1781 (GNUNET_NO == GCP_is_neighbor (c->prev_peer)) )
1782 {
1783 if (GCC_is_origin (c, GNUNET_YES))
1784 GNUNET_STATISTICS_update (stats, "# local bad paths", 1, GNUNET_NO);
1785 GNUNET_STATISTICS_update (stats, "# bad paths", 1, GNUNET_NO);
1786
1787 LOG (GNUNET_ERROR_TYPE_DEBUG,
1788 " register neighbors failed\n");
1789 LOG (GNUNET_ERROR_TYPE_DEBUG,
1790 " prev: %s, neighbor?: %d\n",
1791 GCP_2s (c->prev_peer),
1792 GCP_is_neighbor (c->prev_peer));
1793 LOG (GNUNET_ERROR_TYPE_DEBUG,
1794 " next: %s, neighbor?: %d\n",
1795 GCP_2s (c->next_peer),
1796 GCP_is_neighbor (c->next_peer));
1797 return GNUNET_SYSERR;
1798 }
1799 GCP_add_connection (c->next_peer, c, GNUNET_NO);
1800 GCP_add_connection (c->prev_peer, c, GNUNET_YES);
1801
1802 return GNUNET_OK;
1803}
1804
1805
1806/**
1807 * Remove the connection from the list of both neighbors.
1808 *
1809 * @param c Connection.
1810 */
1811static void
1812unregister_neighbors (struct CadetConnection *c)
1813{
1814// struct CadetPeer *peer; FIXME dont use next_peer, prev_peer
1815 /* Either already unregistered or never got registered, it's ok either way. */
1816 if (NULL == c->path)
1817 return;
1818 if (NULL != c->next_peer)
1819 {
1820 GCP_remove_connection (c->next_peer, c);
1821 c->next_peer = NULL;
1822 }
1823 if (NULL != c->prev_peer)
1824 {
1825 GCP_remove_connection (c->prev_peer, c);
1826 c->prev_peer = NULL;
1827 }
1828}
1829
1830
1831/**
1832 * Invalidates all paths towards all peers that comprise the connection which
1833 * rely on the disconnected peer.
1834 *
1835 * ~O(n^3) (peers in connection * paths/peer * links/path)
1836 *
1837 * @param c Connection whose peers' paths to clean.
1838 * @param disconnected Peer that disconnected.
1839 */
1840static void
1841invalidate_paths (struct CadetConnection *c,
1842 struct CadetPeer *disconnected)
1843{
1844 struct CadetPeer *peer;
1845 unsigned int i;
1846
1847 for (i = 0; i < c->path->length; i++)
1848 {
1849 peer = GCP_get_short (c->path->peers[i], GNUNET_NO);
1850 if (NULL != peer)
1851 GCP_notify_broken_link (peer, &my_full_id, GCP_get_id (disconnected));
1852 }
1853}
1854
1855
1856/**
1857 * Bind the connection to the peer and the tunnel to that peer.
1858 *
1859 * If the peer has no tunnel, create one. Update tunnel and connection
1860 * data structres to reflect new status.
1861 *
1862 * @param c Connection.
1863 * @param peer Peer.
1864 */
1865static void
1866add_to_peer (struct CadetConnection *c,
1867 struct CadetPeer *peer)
1868{
1869 GCP_add_tunnel (peer);
1870 c->t = GCP_get_tunnel (peer);
1871 GCT_add_connection (c->t, c);
1872}
1873
1874
1875/**
1876 * Log receipt of message on stderr (INFO level).
1877 *
1878 * @param message Message received.
1879 * @param peer Peer who sent the message.
1880 * @param conn_id Connection ID of the message.
1881 */
1882static void
1883log_message (const struct GNUNET_MessageHeader *message,
1884 const struct CadetPeer *peer,
1885 const struct GNUNET_CADET_ConnectionTunnelIdentifier *conn_id)
1886{
1887 uint16_t size;
1888 uint16_t type;
1889 char *arrow;
1890
1891 size = ntohs (message->size);
1892 type = ntohs (message->type);
1893 switch (type)
1894 {
1895 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
1896 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK:
1897 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
1898 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
1899 arrow = "==";
1900 break;
1901 default:
1902 arrow = "--";
1903 }
1904 LOG (GNUNET_ERROR_TYPE_INFO,
1905 "<%s %s on conn %s from %s, %6u bytes\n",
1906 arrow,
1907 GC_m2s (type),
1908 GNUNET_sh2s (&conn_id->connection_of_tunnel),
1909 GCP_2s(peer),
1910 (unsigned int) size);
1911}
1912
1913/******************************************************************************/
1914/******************************** API ***********************************/
1915/******************************************************************************/
1916
1917/**
1918 * Handler for connection creation.
1919 *
1920 * @param peer Message sender (neighbor).
1921 * @param msg Message itself.
1922 */ 489 */
1923void 490void
1924GCC_handle_create (struct CadetPeer *peer, 491GCC_handle_connection_create_ack (struct CadetConnection *cc)
1925 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
1926{ 492{
1927 static struct CadetEncryptedMessageIdentifier zero; 493 LOG (GNUNET_ERROR_TYPE_DEBUG,
1928 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid; 494 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
1929 struct GNUNET_PeerIdentity *id; 495 GCC_2s (cc),
1930 struct CadetPeerPath *path; 496 cc->state,
1931 struct CadetPeer *dest_peer; 497 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
1932 struct CadetPeer *orig_peer; 498 if (CADET_CONNECTION_READY == cc->state)
1933 struct CadetConnection *c; 499 return; /* Duplicate ACK, ignore */
1934 unsigned int own_pos; 500 if (NULL != cc->task)
1935 uint16_t size;
1936
1937 GCC_check_connections ();
1938 size = ntohs (msg->header.size);
1939
1940 /* Calculate hops */
1941 size -= sizeof (struct GNUNET_CADET_ConnectionCreateMessage);
1942 if (0 != size % sizeof (struct GNUNET_PeerIdentity))
1943 {
1944 GNUNET_break_op (0);
1945 return;
1946 }
1947 size /= sizeof (struct GNUNET_PeerIdentity);
1948 if (1 > size)
1949 {
1950 GNUNET_break_op (0);
1951 return;
1952 }
1953 LOG (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size);
1954
1955 /* Get parameters */
1956 cid = &msg->cid;
1957 log_message (&msg->header, peer, cid);
1958 id = (struct GNUNET_PeerIdentity *) &msg[1];
1959 LOG (GNUNET_ERROR_TYPE_DEBUG, " origin: %s\n", GNUNET_i2s (id));
1960
1961 /* Create connection */
1962 c = connection_get (cid);
1963 if (NULL == c)
1964 {
1965 path = path_build_from_peer_ids ((struct GNUNET_PeerIdentity *) &msg[1],
1966 size, myid, &own_pos);
1967 if (NULL == path)
1968 {
1969 /* Path was malformed, probably our own ID was not in it. */
1970 GNUNET_STATISTICS_update (stats, "# malformed paths", 1, GNUNET_NO);
1971 GNUNET_break_op (0);
1972 return;
1973 }
1974 if (0 == own_pos)
1975 {
1976 /* We received this request from a neighbor, we cannot be origin */
1977 GNUNET_STATISTICS_update (stats, "# fake paths", 1, GNUNET_NO);
1978 GNUNET_break_op (0);
1979 path_destroy (path);
1980 return;
1981 }
1982
1983 LOG (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos);
1984 LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating connection\n");
1985 c = GCC_new (cid, NULL, path, own_pos);
1986 if (NULL == c)
1987 {
1988 if (path->length - 1 == own_pos)
1989 {
1990 /* If we are destination, why did the creation fail? */
1991 GNUNET_break (0);
1992 path_destroy (path);
1993 GCC_check_connections ();
1994 return;
1995 }
1996 send_broken_unknown (cid, &my_full_id,
1997 GNUNET_PEER_resolve2 (path->peers[own_pos + 1]),
1998 peer);
1999 path_destroy (path);
2000 GCC_check_connections ();
2001 return;
2002 }
2003 GCP_add_path_to_all (path, GNUNET_NO);
2004 connection_reset_timeout (c, GNUNET_YES);
2005 }
2006 else
2007 {
2008 path = path_duplicate (c->path);
2009 }
2010 if (CADET_CONNECTION_NEW == c->state)
2011 connection_change_state (c, CADET_CONNECTION_SENT);
2012
2013 /* Remember peers */
2014 dest_peer = GCP_get (&id[size - 1], GNUNET_YES);
2015 orig_peer = GCP_get (&id[0], GNUNET_YES);
2016
2017 /* Is it a connection to us? */
2018 if (c->own_pos == path->length - 1)
2019 {
2020 LOG (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n");
2021 GCP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_YES);
2022
2023 add_to_peer (c, orig_peer);
2024 if (GNUNET_YES == does_connection_exist (c))
2025 {
2026 /* Peer created a connection equal to one we think exists
2027 * and is fine.
2028 * Solution: Keep both and postpone disambiguation. In the meantime
2029 * the connection will time out or peer will inform us it is broken.
2030 *
2031 * Other options:
2032 * - Use explicit duplicate.
2033 * - Accept new conn and destroy the old. (interruption in higher level)
2034 * - Keep the one with higher ID / created by peer with higher ID. */
2035 schedule_check_duplicates (c);
2036 }
2037
2038 if (CADET_TUNNEL_NEW == GCT_get_cstate (c->t))
2039 GCT_change_cstate (c->t, CADET_TUNNEL_WAITING);
2040 if (NULL == c->maintenance_q)
2041 send_connection_ack (c, GNUNET_NO);
2042 if (CADET_CONNECTION_SENT == c->state)
2043 connection_change_state (c, CADET_CONNECTION_ACK);
2044 }
2045 else
2046 { 501 {
2047 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); 502 GNUNET_SCHEDULER_cancel (cc->task);
2048 GCP_add_path (dest_peer, path_duplicate (path), GNUNET_NO); 503 cc->task = NULL;
2049 GCP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_NO);
2050 (void) GCC_send_prebuilt_message (&msg->header,
2051 0,
2052 zero,
2053 c,
2054 GNUNET_YES, GNUNET_YES,
2055 NULL, NULL);
2056 } 504 }
2057 path_destroy (path); 505 cc->metrics.age = GNUNET_TIME_absolute_get ();
2058 GCC_check_connections (); 506 update_state (cc,
507 CADET_CONNECTION_READY,
508 cc->mqm_ready);
509 if ( (NULL == cc->keepalive_qe) &&
510 (GNUNET_YES == cc->mqm_ready) &&
511 (NULL == cc->task) )
512 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
513 &send_keepalive,
514 cc);
2059} 515}
2060 516
2061 517
2062/** 518/**
2063 * Handler for connection confirmations. 519 * Handle KX message.
2064 * 520 *
2065 * @param peer Message sender (neighbor). 521 * @param cc connection that received encrypted message
2066 * @param msg Message itself. 522 * @param msg the key exchange message
2067 */ 523 */
2068void 524void
2069GCC_handle_confirm (struct CadetPeer *peer, 525GCC_handle_kx (struct CadetConnection *cc,
2070 const struct GNUNET_CADET_ConnectionCreateAckMessage *msg) 526 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
2071{ 527{
2072 static struct CadetEncryptedMessageIdentifier zero; 528 if (CADET_CONNECTION_SENT == cc->state)
2073 struct CadetConnection *c;
2074 enum CadetConnectionState oldstate;
2075 int fwd;
2076
2077 GCC_check_connections ();
2078 log_message (&msg->header, peer, &msg->cid);
2079 c = connection_get (&msg->cid);
2080 if (NULL == c)
2081 {
2082 GNUNET_STATISTICS_update (stats, "# control on unknown connection",
2083 1, GNUNET_NO);
2084 LOG (GNUNET_ERROR_TYPE_DEBUG,
2085 " don't know the connection!\n");
2086 send_broken_unknown (&msg->cid, &my_full_id, NULL, peer);
2087 GCC_check_connections ();
2088 return;
2089 }
2090 if (GNUNET_NO != c->destroy)
2091 { 529 {
2092 GNUNET_assert (CADET_CONNECTION_DESTROYED == c->state); 530 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
2093 GNUNET_STATISTICS_update (stats, "# control on dying connection", 531 clearly something is working, so pretend we got an ACK. */
2094 1, GNUNET_NO);
2095 LOG (GNUNET_ERROR_TYPE_DEBUG, 532 LOG (GNUNET_ERROR_TYPE_DEBUG,
2096 "connection %s being destroyed, ignoring confirm\n", 533 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
2097 GCC_2s (c)); 534 GCC_2s (cc));
2098 GCC_check_connections (); 535 GCC_handle_connection_create_ack (cc);
2099 return;
2100 }
2101
2102 oldstate = c->state;
2103 LOG (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", GCP_2s (peer));
2104 if (get_next_hop (c) == peer)
2105 {
2106 LOG (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n");
2107 fwd = GNUNET_NO;
2108 if (CADET_CONNECTION_SENT == oldstate)
2109 connection_change_state (c, CADET_CONNECTION_ACK);
2110 }
2111 else if (get_prev_hop (c) == peer)
2112 {
2113 LOG (GNUNET_ERROR_TYPE_DEBUG, " FINAL ACK\n");
2114 fwd = GNUNET_YES;
2115 connection_change_state (c, CADET_CONNECTION_READY);
2116 }
2117 else
2118 {
2119 GNUNET_STATISTICS_update (stats, "# control on connection from wrong peer",
2120 1, GNUNET_NO);
2121 GNUNET_break_op (0);
2122 return;
2123 }
2124
2125 connection_reset_timeout (c, fwd);
2126
2127 GNUNET_assert (NULL != c->path);
2128 GCP_add_path_to_all (c->path, GNUNET_YES);
2129
2130 /* Message for us as creator? */
2131 if (GNUNET_YES == GCC_is_origin (c, GNUNET_YES))
2132 {
2133 if (GNUNET_NO != fwd)
2134 {
2135 GNUNET_break (0);
2136 return;
2137 }
2138 LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection (SYN)ACK for us!\n");
2139
2140 /* If just created, cancel the short timeout and start a long one */
2141 if (CADET_CONNECTION_SENT == oldstate)
2142 {
2143 c->create_retry = 1;
2144 connection_reset_timeout (c, GNUNET_YES);
2145 }
2146
2147 /* Change connection state, send ACK */
2148 connection_change_state (c, CADET_CONNECTION_READY);
2149 send_connection_ack (c, GNUNET_YES);
2150
2151 /* Change tunnel state, trigger KX */
2152 if (CADET_TUNNEL_WAITING == GCT_get_cstate (c->t))
2153 GCT_change_cstate (c->t, CADET_TUNNEL_READY);
2154 GCC_check_connections ();
2155 return;
2156 }
2157
2158 /* Message for us as destination? */
2159 if (GCC_is_terminal (c, GNUNET_YES))
2160 {
2161 if (GNUNET_YES != fwd)
2162 {
2163 GNUNET_break (0);
2164 return;
2165 }
2166 LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection ACK for us!\n");
2167
2168 /* If just created, cancel the short timeout and start a long one */
2169 if (CADET_CONNECTION_ACK == oldstate)
2170 connection_reset_timeout (c, GNUNET_NO);
2171
2172 /* Change tunnel state */
2173 if (CADET_TUNNEL_WAITING == GCT_get_cstate (c->t))
2174 GCT_change_cstate (c->t, CADET_TUNNEL_READY);
2175 GCC_check_connections ();
2176 } 536 }
2177 else 537 GCT_handle_kx (cc->ct,
2178 { 538 msg);
2179 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
2180 (void) GCC_send_prebuilt_message (&msg->header, 0,
2181 zero,
2182 c,
2183 fwd,
2184 GNUNET_YES, NULL, NULL);
2185 }
2186 GCC_check_connections ();
2187} 539}
2188 540
2189 541
2190/** 542/**
2191 * Handler for notifications of broken connections. 543 * Handle KX_AUTH message.
2192 * 544 *
2193 * @param peer Message sender (neighbor). 545 * @param cc connection that received encrypted message
2194 * @param msg Message itself. 546 * @param msg the key exchange message
2195 */ 547 */
2196void 548void
2197GCC_handle_broken (struct CadetPeer *peer, 549GCC_handle_kx_auth (struct CadetConnection *cc,
2198 const struct GNUNET_CADET_ConnectionBrokenMessage *msg) 550 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
2199{ 551{
2200 static struct CadetEncryptedMessageIdentifier zero; 552 if (CADET_CONNECTION_SENT == cc->state)
2201 struct CadetConnection *c;
2202 struct CadetTunnel *t;
2203 int fwd;
2204
2205 GCC_check_connections ();
2206 log_message (&msg->header, peer, &msg->cid);
2207 LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", GNUNET_i2s (&msg->peer1));
2208 LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", GNUNET_i2s (&msg->peer2));
2209 c = connection_get (&msg->cid);
2210 if (NULL == c)
2211 {
2212 LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate CONNECTION_BROKEN\n");
2213 GNUNET_STATISTICS_update (stats, "# duplicate CONNECTION_BROKEN",
2214 1, GNUNET_NO);
2215 GCC_check_connections ();
2216 return;
2217 }
2218
2219 t = c->t;
2220
2221 fwd = is_fwd (c, peer);
2222 if (GNUNET_SYSERR == fwd)
2223 {
2224 GNUNET_break_op (0);
2225 GCC_check_connections ();
2226 return;
2227 }
2228 mark_destroyed (c);
2229 if (GCC_is_terminal (c, fwd))
2230 {
2231 struct CadetPeer *endpoint;
2232
2233 if (NULL == t)
2234 {
2235 /* A terminal connection should not have 't' set to NULL. */
2236 GNUNET_break (0);
2237 GCC_debug (c, GNUNET_ERROR_TYPE_ERROR);
2238 return;
2239 }
2240 endpoint = GCP_get_short (c->path->peers[c->path->length - 1], GNUNET_YES);
2241 if (2 < c->path->length)
2242 path_invalidate (c->path);
2243 GCP_notify_broken_link (endpoint, &msg->peer1, &msg->peer2);
2244
2245 connection_change_state (c, CADET_CONNECTION_BROKEN);
2246 GCT_remove_connection (t, c);
2247 c->t = NULL;
2248
2249 GCC_destroy (c);
2250 }
2251 else
2252 { 553 {
2253 (void) GCC_send_prebuilt_message (&msg->header, 0, 554 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
2254 zero, c, fwd, 555 clearly something is working, so pretend we got an ACK. */
2255 GNUNET_YES, NULL, NULL); 556 LOG (GNUNET_ERROR_TYPE_DEBUG,
2256 connection_cancel_queues (c, !fwd); 557 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
558 GCC_2s (cc));
559 GCC_handle_connection_create_ack (cc);
2257 } 560 }
2258 GCC_check_connections (); 561 GCT_handle_kx_auth (cc->ct,
2259 return; 562 msg);
2260} 563}
2261 564
2262 565
2263/** 566/**
2264 * Handler for notifications of destroyed connections. 567 * Handle encrypted message.
2265 * 568 *
2266 * @param peer Message sender (neighbor). 569 * @param cc connection that received encrypted message
2267 * @param msg Message itself. 570 * @param msg the encrypted message to decrypt
2268 */ 571 */
2269void 572void
2270GCC_handle_destroy (struct CadetPeer *peer, 573GCC_handle_encrypted (struct CadetConnection *cc,
2271 const struct GNUNET_CADET_ConnectionDestroyMessage *msg) 574 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
2272{ 575{
2273 static struct CadetEncryptedMessageIdentifier zero; 576 if (CADET_CONNECTION_SENT == cc->state)
2274 struct CadetConnection *c;
2275 int fwd;
2276
2277 GCC_check_connections ();
2278 log_message (&msg->header, peer, &msg->cid);
2279 c = connection_get (&msg->cid);
2280 if (NULL == c)
2281 { 577 {
2282 /* Probably already got the message from another path, 578 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
2283 * destroyed the tunnel and retransmitted to children. 579 clearly something is working, so pretend we got an ACK. */
2284 * Safe to ignore.
2285 */
2286 GNUNET_STATISTICS_update (stats,
2287 "# control on unknown connection",
2288 1, GNUNET_NO);
2289 LOG (GNUNET_ERROR_TYPE_DEBUG, 580 LOG (GNUNET_ERROR_TYPE_DEBUG,
2290 " connection unknown destroyed: previously destroyed?\n"); 581 "Faking connection ACK for %s due to ENCRYPTED payload\n",
2291 GCC_check_connections (); 582 GCC_2s (cc));
2292 return; 583 GCC_handle_connection_create_ack (cc);
2293 }
2294
2295 fwd = is_fwd (c, peer);
2296 if (GNUNET_SYSERR == fwd)
2297 {
2298 GNUNET_break_op (0);
2299 GCC_check_connections ();
2300 return;
2301 }
2302
2303 if (GNUNET_NO == GCC_is_terminal (c, fwd))
2304 {
2305 (void) GCC_send_prebuilt_message (&msg->header, 0,
2306 zero, c, fwd,
2307 GNUNET_YES, NULL, NULL);
2308 } 584 }
2309 else if (0 == c->pending_messages) 585 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
2310 { 586 GCT_handle_encrypted (cc->ct,
2311 LOG (GNUNET_ERROR_TYPE_DEBUG, " directly destroying connection!\n"); 587 msg);
2312 GCC_destroy (c);
2313 GCC_check_connections ();
2314 return;
2315 }
2316 mark_destroyed (c);
2317 if (NULL != c->t)
2318 {
2319 GCT_remove_connection (c->t, c);
2320 c->t = NULL;
2321 }
2322 GCC_check_connections ();
2323 return;
2324} 588}
2325 589
2326 590
2327/** 591/**
2328 * Handler for cadet network traffic hop-by-hop acks. 592 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
593 * first hop.
2329 * 594 *
2330 * @param peer Message sender (neighbor). 595 * @param cls the `struct CadetConnection` to initiate
2331 * @param msg Message itself.
2332 */ 596 */
2333void 597static void
2334GCC_handle_ack (struct CadetPeer *peer, 598send_create (void *cls)
2335 const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg) 599{
2336{ 600 struct CadetConnection *cc = cls;
2337 struct CadetConnection *c; 601 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
2338 struct CadetFlowControl *fc; 602 struct GNUNET_PeerIdentity *pids;
2339 struct CadetEncryptedMessageIdentifier ack; 603 struct GNUNET_MQ_Envelope *env;
2340 int fwd; 604 unsigned int path_length;
2341 605
2342 GCC_check_connections (); 606 cc->task = NULL;
2343 log_message (&msg->header, peer, &msg->cid); 607 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
2344 c = connection_get (&msg->cid); 608 path_length = GCPP_get_length (cc->path);
2345 if (NULL == c) 609 env = GNUNET_MQ_msg_extra (create_msg,
2346 { 610 (1 + path_length) * sizeof (struct GNUNET_PeerIdentity),
2347 GNUNET_STATISTICS_update (stats, 611 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
2348 "# ack on unknown connection", 612 create_msg->options = htonl ((uint32_t) cc->options);
2349 1, 613 create_msg->cid = cc->cid;
2350 GNUNET_NO); 614 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
2351 send_broken_unknown (&msg->cid, 615 pids[0] = my_full_id;
2352 &my_full_id, 616 for (unsigned int i=0;i<path_length;i++)
2353 NULL, 617 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
2354 peer); 618 i));
2355 GCC_check_connections (); 619 LOG (GNUNET_ERROR_TYPE_DEBUG,
2356 return; 620 "Sending CADET_CONNECTION_CREATE message for %s\n",
2357 } 621 GCC_2s (cc));
2358 622 cc->env = env;
2359 /* Is this a forward or backward ACK? */ 623 update_state (cc,
2360 if (get_next_hop (c) == peer) 624 CADET_CONNECTION_SENT,
2361 { 625 GNUNET_NO);
2362 fc = &c->fwd_fc; 626 GCP_send (cc->mq_man,
2363 fwd = GNUNET_YES; 627 env);
2364 }
2365 else if (get_prev_hop (c) == peer)
2366 {
2367 fc = &c->bck_fc;
2368 fwd = GNUNET_NO;
2369 }
2370 else
2371 {
2372 GNUNET_break_op (0);
2373 return;
2374 }
2375
2376 ack = msg->cemi_max;
2377 LOG (GNUNET_ERROR_TYPE_DEBUG, " %s ACK %u (was %u)\n",
2378 GC_f2s (fwd),
2379 ntohl (ack.pid),
2380 ntohl (fc->last_ack_recv.pid));
2381 if (GC_is_pid_bigger (ntohl (ack.pid),
2382 ntohl (fc->last_ack_recv.pid)))
2383 fc->last_ack_recv = ack;
2384
2385 /* Cancel polling if the ACK is big enough. */
2386 if ( (NULL != fc->poll_task) &
2387 GC_is_pid_bigger (ntohl (fc->last_ack_recv.pid),
2388 ntohl (fc->last_pid_sent.pid)))
2389 {
2390 LOG (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n");
2391 GNUNET_SCHEDULER_cancel (fc->poll_task);
2392 fc->poll_task = NULL;
2393 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
2394 }
2395
2396 GCC_check_connections ();
2397} 628}
2398 629
2399 630
2400/** 631/**
2401 * Handler for cadet network traffic hop-by-hop data counter polls. 632 * Send a CREATE_ACK message towards the origin.
2402 * 633 *
2403 * @param peer Message sender (neighbor). 634 * @param cls the `struct CadetConnection` to initiate
2404 * @param msg Message itself.
2405 */ 635 */
2406void 636static void
2407GCC_handle_poll (struct CadetPeer *peer, 637send_create_ack (void *cls)
2408 const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg)
2409{ 638{
2410 struct CadetConnection *c; 639 struct CadetConnection *cc = cls;
2411 struct CadetFlowControl *fc; 640 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
2412 struct CadetEncryptedMessageIdentifier pid; 641 struct GNUNET_MQ_Envelope *env;
2413 int fwd;
2414
2415 GCC_check_connections ();
2416 log_message (&msg->header, peer, &msg->cid);
2417 c = connection_get (&msg->cid);
2418 if (NULL == c)
2419 {
2420 GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
2421 GNUNET_NO);
2422 LOG (GNUNET_ERROR_TYPE_DEBUG,
2423 "POLL message on unknown connection %s!\n",
2424 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
2425 send_broken_unknown (&msg->cid,
2426 &my_full_id,
2427 NULL,
2428 peer);
2429 GCC_check_connections ();
2430 return;
2431 }
2432
2433 /* Is this a forward or backward ACK?
2434 * Note: a poll should never be needed in a loopback case,
2435 * since there is no possiblility of packet loss there, so
2436 * this way of discerining FWD/BCK should not be a problem.
2437 */
2438 if (get_next_hop (c) == peer)
2439 {
2440 LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n");
2441 fc = &c->fwd_fc;
2442 }
2443 else if (get_prev_hop (c) == peer)
2444 {
2445 LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n");
2446 fc = &c->bck_fc;
2447 }
2448 else
2449 {
2450 GNUNET_break_op (0);
2451 return;
2452 }
2453 642
2454 pid = msg->cemi; 643 cc->task = NULL;
644 GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state);
2455 LOG (GNUNET_ERROR_TYPE_DEBUG, 645 LOG (GNUNET_ERROR_TYPE_DEBUG,
2456 " PID %u, OLD %u\n", 646 "Sending CONNECTION_CREATE_ACK message for %s\n",
2457 ntohl (pid.pid), 647 GCC_2s (cc));
2458 ntohl (fc->last_pid_recv.pid)); 648 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
2459 fc->last_pid_recv = pid; 649 env = GNUNET_MQ_msg (ack_msg,
2460 fwd = fc == &c->bck_fc; 650 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
2461 GCC_send_ack (c, fwd, GNUNET_YES); 651 ack_msg->cid = cc->cid;
2462 GCC_check_connections (); 652 cc->env = env;
653 update_state (cc,
654 CADET_CONNECTION_READY,
655 GNUNET_NO);
656 GCP_send (cc->mq_man,
657 env);
2463} 658}
2464 659
2465 660
2466/** 661/**
2467 * Check the message against internal state and test if it goes FWD or BCK. 662 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
2468 * 663 * connection that we already have. Either our ACK got lost
2469 * Updates the PID, state and timeout values for the connection. 664 * or something is fishy. Consider retransmitting the ACK.
2470 *
2471 * @param message Message to check. It must belong to an existing connection.
2472 * @param cid Connection ID (even if @a c is NULL, the ID is still needed).
2473 * @param c Connection this message should belong. If NULL, check fails.
2474 * @param sender Neighbor that sent the message.
2475 * 665 *
2476 * @return #GNUNET_YES if the message goes FWD. 666 * @param cc connection that got the duplicate CREATE
2477 * #GNUNET_NO if it goes BCK.
2478 * #GNUNET_SYSERR if there is an error (unauthorized sender, ...).
2479 */ 667 */
2480static int 668void
2481check_message (const struct GNUNET_MessageHeader *message, 669GCC_handle_duplicate_create (struct CadetConnection *cc)
2482 const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid,
2483 struct CadetConnection *c,
2484 struct CadetPeer *sender,
2485 struct CadetEncryptedMessageIdentifier pid)
2486{ 670{
2487 struct CadetFlowControl *fc; 671 if (GNUNET_YES == cc->mqm_ready)
2488 struct CadetPeer *hop;
2489 int fwd;
2490 uint16_t type;
2491
2492 /* Check connection */
2493 if (NULL == c)
2494 { 672 {
2495 GNUNET_STATISTICS_update (stats,
2496 "# unknown connection",
2497 1, GNUNET_NO);
2498 LOG (GNUNET_ERROR_TYPE_DEBUG, 673 LOG (GNUNET_ERROR_TYPE_DEBUG,
2499 "%s on unknown connection %s\n", 674 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
2500 GC_m2s (ntohs (message->type)), 675 GCC_2s (cc),
2501 GNUNET_sh2s (&cid->connection_of_tunnel)); 676 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
2502 GNUNET_break_op (0); 677 /* Revert back to the state of having only received the 'CREATE',
2503 send_broken_unknown (cid, 678 and immediately proceed to send the CREATE_ACK. */
2504 &my_full_id, 679 update_state (cc,
2505 NULL, 680 CADET_CONNECTION_CREATE_RECEIVED,
2506 sender); 681 cc->mqm_ready);
2507 return GNUNET_SYSERR; 682 if (NULL != cc->task)
2508 } 683 GNUNET_SCHEDULER_cancel (cc->task);
2509 684 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
2510 /* Check if origin is as expected */ 685 cc);
2511 hop = get_prev_hop (c);
2512 if (sender == hop)
2513 {
2514 fwd = GNUNET_YES;
2515 } 686 }
2516 else 687 else
2517 { 688 {
2518 hop = get_next_hop (c); 689 /* We are currently sending something else back, which
2519 GNUNET_break (hop == c->next_peer); 690 can only be an ACK or payload, either of which would
2520 if (sender == hop) 691 do. So actually no need to do anything. */
2521 { 692 LOG (GNUNET_ERROR_TYPE_DEBUG,
2522 fwd = GNUNET_NO; 693 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
2523 } 694 GCC_2s (cc));
2524 else
2525 {
2526 /* Unexpected peer sending traffic on a connection. */
2527 GNUNET_break_op (0);
2528 return GNUNET_SYSERR;
2529 }
2530 }
2531
2532 /* Check PID for payload messages */
2533 type = ntohs (message->type);
2534 if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == type)
2535 {
2536 fc = fwd ? &c->bck_fc : &c->fwd_fc;
2537 LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected in interval [%u,%u])\n",
2538 ntohl (pid.pid),
2539 ntohl (fc->last_pid_recv.pid) + 1,
2540 ntohl (fc->last_ack_sent.pid));
2541 if (GC_is_pid_bigger (ntohl (pid.pid),
2542 ntohl (fc->last_ack_sent.pid)))
2543 {
2544 GNUNET_STATISTICS_update (stats,
2545 "# unsolicited message",
2546 1,
2547 GNUNET_NO);
2548 LOG (GNUNET_ERROR_TYPE_WARNING,
2549 "Received PID %u, (prev %u), ACK %u\n",
2550 pid, fc->last_pid_recv, fc->last_ack_sent);
2551 return GNUNET_SYSERR;
2552 }
2553 if (GC_is_pid_bigger (ntohl (pid.pid),
2554 ntohl (fc->last_pid_recv.pid)))
2555 {
2556 unsigned int delta;
2557
2558 delta = ntohl (pid.pid) - ntohl (fc->last_pid_recv.pid);
2559 fc->last_pid_recv = pid;
2560 fc->recv_bitmap <<= delta;
2561 fc->recv_bitmap |= 1;
2562 }
2563 else
2564 {
2565 GNUNET_STATISTICS_update (stats,
2566 "# out of order PID",
2567 1,
2568 GNUNET_NO);
2569 if (GNUNET_NO == is_ooo_ok (fc->last_pid_recv,
2570 pid,
2571 fc->recv_bitmap))
2572 {
2573 LOG (GNUNET_ERROR_TYPE_WARNING,
2574 "PID %u unexpected (%u+), dropping!\n",
2575 ntohl (pid.pid),
2576 ntohl (fc->last_pid_recv.pid) - 31);
2577 return GNUNET_SYSERR;
2578 }
2579 fc->recv_bitmap |= get_recv_bitmask (fc->last_pid_recv,
2580 pid);
2581 }
2582 }
2583
2584 /* Count as connection confirmation. */
2585 if ( (CADET_CONNECTION_SENT == c->state) ||
2586 (CADET_CONNECTION_ACK == c->state) )
2587 {
2588 connection_change_state (c, CADET_CONNECTION_READY);
2589 if (NULL != c->t)
2590 {
2591 if (CADET_TUNNEL_WAITING == GCT_get_cstate (c->t))
2592 GCT_change_cstate (c->t, CADET_TUNNEL_READY);
2593 }
2594 } 695 }
2595 connection_reset_timeout (c, fwd);
2596
2597 return fwd;
2598} 696}
2599 697
2600 698
2601/** 699/**
2602 * Handler for key exchange traffic (Axolotl KX). 700 * There has been a change in the message queue existence for our
701 * peer at the first hop. Adjust accordingly.
2603 * 702 *
2604 * @param peer Message sender (neighbor). 703 * @param cls the `struct CadetConnection`
2605 * @param msg Message itself. 704 * @param available #GNUNET_YES if sending is now possible,
705 * #GNUNET_NO if sending is no longer possible
706 * #GNUNET_SYSERR if sending is no longer possible
707 * and the last envelope was discarded
2606 */ 708 */
2607void 709static void
2608GCC_handle_kx (struct CadetPeer *peer, 710manage_first_hop_mq (void *cls,
2609 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) 711 int available)
2610{ 712{
2611 static struct CadetEncryptedMessageIdentifier zero; 713 struct CadetConnection *cc = cls;
2612 const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid;
2613 struct CadetConnection *c;
2614 int fwd;
2615
2616 GCC_check_connections ();
2617 cid = &msg->cid;
2618 log_message (&msg->header, peer, cid);
2619
2620 c = connection_get (cid);
2621 fwd = check_message (&msg->header,
2622 cid,
2623 c,
2624 peer,
2625 zero);
2626
2627 /* If something went wrong, discard message. */
2628 if (GNUNET_SYSERR == fwd)
2629 {
2630 GNUNET_break_op (0);
2631 GCC_check_connections ();
2632 return;
2633 }
2634 714
2635 /* Is this message for us? */ 715 if (GNUNET_YES != available)
2636 if (GCC_is_terminal (c, fwd))
2637 { 716 {
2638 LOG (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n"); 717 /* Connection is down, for now... */
2639 GNUNET_STATISTICS_update (stats, "# received KX", 1, GNUNET_NO); 718 LOG (GNUNET_ERROR_TYPE_DEBUG,
2640 if (NULL == c->t) 719 "Core MQ for %s went down\n",
720 GCC_2s (cc));
721 update_state (cc,
722 CADET_CONNECTION_NEW,
723 GNUNET_NO);
724 cc->retry_delay = GNUNET_TIME_UNIT_ZERO;
725 if (NULL != cc->task)
2641 { 726 {
2642 GNUNET_break (0); 727 GNUNET_SCHEDULER_cancel (cc->task);
2643 return; 728 cc->task = NULL;
2644 } 729 }
2645 GCT_handle_kx (c->t, msg);
2646 GCC_check_connections ();
2647 return;
2648 }
2649
2650 /* Message not for us: forward to next hop */
2651 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
2652 GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
2653 (void) GCC_send_prebuilt_message (&msg->header, 0,
2654 zero, c, fwd,
2655 GNUNET_NO, NULL, NULL);
2656 GCC_check_connections ();
2657}
2658
2659
2660/**
2661 * Handler for encrypted cadet network traffic (channel mgmt, data).
2662 *
2663 * @param peer Message sender (neighbor).
2664 * @param msg Message itself.
2665 */
2666void
2667GCC_handle_encrypted (struct CadetPeer *peer,
2668 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
2669{
2670 static struct CadetEncryptedMessageIdentifier zero;
2671 const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid;
2672 struct CadetConnection *c;
2673 struct CadetEncryptedMessageIdentifier pid;
2674 int fwd;
2675
2676 GCC_check_connections ();
2677 cid = &msg->cid;
2678 pid = msg->cemi;
2679 log_message (&msg->header, peer, cid);
2680
2681 c = connection_get (cid);
2682 fwd = check_message (&msg->header,
2683 cid,
2684 c,
2685 peer,
2686 pid);
2687
2688 /* If something went wrong, discard message. */
2689 if (GNUNET_SYSERR == fwd)
2690 {
2691 GCC_check_connections ();
2692 return; 730 return;
2693 } 731 }
2694 732
2695 /* Is this message for us? */ 733 update_state (cc,
2696 if (GCC_is_terminal (c, fwd)) 734 cc->state,
2697 { 735 GNUNET_YES);
2698 GNUNET_STATISTICS_update (stats, "# received encrypted", 1, GNUNET_NO); 736 LOG (GNUNET_ERROR_TYPE_DEBUG,
2699 737 "Core MQ for %s became available in state %d\n",
2700 if (NULL == c->t) 738 GCC_2s (cc),
739 cc->state);
740 switch (cc->state)
741 {
742 case CADET_CONNECTION_NEW:
743 /* Transmit immediately */
744 cc->task = GNUNET_SCHEDULER_add_now (&send_create,
745 cc);
746 break;
747 case CADET_CONNECTION_SENDING_CREATE:
748 /* Should not be possible to be called in this state. */
749 GNUNET_assert (0);
750 break;
751 case CADET_CONNECTION_SENT:
752 /* Retry a bit later... */
753 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
754 cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay,
755 &send_create,
756 cc);
757 break;
758 case CADET_CONNECTION_CREATE_RECEIVED:
759 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
760 cc->metrics.age = GNUNET_TIME_absolute_get ();
761 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
762 cc);
763 break;
764 case CADET_CONNECTION_READY:
765 if ( (NULL == cc->keepalive_qe) &&
766 (GNUNET_YES == cc->mqm_ready) &&
767 (NULL == cc->task) )
2701 { 768 {
2702 GNUNET_break (GNUNET_NO != c->destroy); 769 LOG (GNUNET_ERROR_TYPE_DEBUG,
2703 return; 770 "Scheduling keepalive for %s in %s\n",
771 GCC_2s (cc),
772 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
773 GNUNET_YES));
774 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
775 &send_keepalive,
776 cc);
2704 } 777 }
2705 GCT_handle_encrypted (c->t, msg); 778 break;
2706 GCC_send_ack (c, fwd, GNUNET_NO);
2707 GCC_check_connections ();
2708 return;
2709 } 779 }
2710
2711 /* Message not for us: forward to next hop */
2712 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
2713 GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
2714 (void) GCC_send_prebuilt_message (&msg->header, 0,
2715 zero, c, fwd,
2716 GNUNET_NO, NULL, NULL);
2717 GCC_check_connections ();
2718} 780}
2719 781
2720 782
2721/** 783/**
2722 * Initialize the connections subsystem 784 * Create a connection to @a destination via @a path and notify @a cb
785 * whenever we are ready for more data. Shared logic independent of
786 * who is initiating the connection.
2723 * 787 *
2724 * @param c Configuration handle. 788 * @param destination where to go
789 * @param path which path to take (may not be the full path)
790 * @param off offset of @a destination on @a path
791 * @param options options for the connection
792 * @param ct which tunnel uses this connection
793 * @param init_state initial state for the connection
794 * @param ready_cb function to call when ready to transmit
795 * @param ready_cb_cls closure for @a cb
796 * @return handle to the connection
2725 */ 797 */
2726void 798static struct CadetConnection *
2727GCC_init (const struct GNUNET_CONFIGURATION_Handle *c) 799connection_create (struct CadetPeer *destination,
2728{ 800 struct CadetPeerPath *path,
2729 LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); 801 unsigned int off,
2730 if (GNUNET_OK != 802 enum GNUNET_CADET_ChannelOption options,
2731 GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_MSGS_QUEUE", 803 struct CadetTConnection *ct,
2732 &max_msgs_queue)) 804 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
2733 { 805 enum CadetConnectionState init_state,
2734 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 806 GCC_ReadyCallback ready_cb,
2735 "CADET", "MAX_MSGS_QUEUE", "MISSING"); 807 void *ready_cb_cls)
2736 GNUNET_SCHEDULER_shutdown (); 808{
2737 return; 809 struct CadetConnection *cc;
2738 } 810 struct CadetPeer *first_hop;
2739 811
2740 if (GNUNET_OK != 812 cc = GNUNET_new (struct CadetConnection);
2741 GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_CONNECTIONS", 813 cc->options = options;
2742 &max_connections)) 814 cc->state = init_state;
2743 { 815 cc->ct = ct;
2744 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 816 cc->cid = *cid;
2745 "CADET", "MAX_CONNECTIONS", "MISSING");
2746 GNUNET_SCHEDULER_shutdown ();
2747 return;
2748 }
2749
2750 if (GNUNET_OK !=
2751 GNUNET_CONFIGURATION_get_value_time (c, "CADET", "REFRESH_CONNECTION_TIME",
2752 &refresh_connection_time))
2753 {
2754 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
2755 "CADET", "REFRESH_CONNECTION_TIME", "MISSING");
2756 GNUNET_SCHEDULER_shutdown ();
2757 return;
2758 }
2759 create_connection_time = GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
2760 refresh_connection_time);
2761 connections = GNUNET_CONTAINER_multishortmap_create (1024,
2762 GNUNET_YES);
2763}
2764
2765
2766/**
2767 * Destroy each connection on shutdown.
2768 *
2769 * @param cls Closure (unused).
2770 * @param key Current key code (CID, unused).
2771 * @param value Value in the hash map (`struct CadetConnection`)
2772 *
2773 * @return #GNUNET_YES, because we should continue to iterate
2774 */
2775static int
2776shutdown_iterator (void *cls,
2777 const struct GNUNET_ShortHashCode *key,
2778 void *value)
2779{
2780 struct CadetConnection *c = value;
2781
2782 c->state = CADET_CONNECTION_DESTROYED;
2783 GCC_destroy (c);
2784 return GNUNET_YES;
2785}
2786
2787
2788/**
2789 * Shut down the connections subsystem.
2790 */
2791void
2792GCC_shutdown (void)
2793{
2794 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connections\n");
2795 GCC_check_connections ();
2796 GNUNET_CONTAINER_multishortmap_iterate (connections,
2797 &shutdown_iterator,
2798 NULL);
2799 GNUNET_CONTAINER_multishortmap_destroy (connections);
2800 connections = NULL;
2801}
2802
2803
2804/**
2805 * Create a connection.
2806 *
2807 * @param cid Connection ID (either created locally or imposed remotely).
2808 * @param t Tunnel this connection belongs to (or NULL for transit connections);
2809 * @param path Path this connection has to use (copy is made).
2810 * @param own_pos Own position in the @c path path.
2811 *
2812 * @return Newly created connection.
2813 * NULL in case of error: own id not in path, wrong neighbors, ...
2814*/
2815struct CadetConnection *
2816GCC_new (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
2817 struct CadetTunnel *t,
2818 struct CadetPeerPath *path,
2819 unsigned int own_pos)
2820{
2821 struct CadetConnection *c;
2822 struct CadetPeerPath *cpath;
2823
2824 GCC_check_connections ();
2825 cpath = path_duplicate (path);
2826 GNUNET_assert (NULL != cpath);
2827 c = GNUNET_new (struct CadetConnection);
2828 c->id = *cid;
2829 GNUNET_assert (GNUNET_OK == 817 GNUNET_assert (GNUNET_OK ==
2830 GNUNET_CONTAINER_multishortmap_put (connections, 818 GNUNET_CONTAINER_multishortmap_put (connections,
2831 &c->id.connection_of_tunnel, 819 &GCC_get_id (cc)->connection_of_tunnel,
2832 c, 820 cc,
2833 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 821 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2834 fc_init (&c->fwd_fc); 822 cc->ready_cb = ready_cb;
2835 fc_init (&c->bck_fc); 823 cc->ready_cb_cls = ready_cb_cls;
2836 c->fwd_fc.c = c; 824 cc->path = path;
2837 c->bck_fc.c = c; 825 cc->off = off;
2838
2839 c->t = t;
2840 GNUNET_assert (own_pos <= cpath->length - 1);
2841 c->own_pos = own_pos;
2842 c->path = cpath;
2843 cpath->c = c;
2844 if (GNUNET_OK != register_neighbors (c))
2845 {
2846 if (0 == own_pos)
2847 {
2848 /* We were the origin of this request, this means we have invalid
2849 * info about the paths to reach the destination. We must invalidate
2850 * the *original* path to avoid trying it again in the next minute.
2851 */
2852 if (2 < path->length)
2853 path_invalidate (path);
2854 else
2855 {
2856 GNUNET_break (0);
2857 GCT_debug(t, GNUNET_ERROR_TYPE_WARNING);
2858 }
2859 c->t = NULL;
2860 }
2861 path_destroy (c->path);
2862 c->path = NULL;
2863 GCC_destroy (c);
2864 return NULL;
2865 }
2866 LOG (GNUNET_ERROR_TYPE_INFO, "New connection %s\n", GCC_2s (c));
2867 GCC_check_connections ();
2868 return c;
2869}
2870
2871
2872/**
2873 * Connection is no longer needed: destroy it.
2874 *
2875 * Cancels all pending traffic (including possible DESTROY messages), all
2876 * maintenance tasks and removes the connection from neighbor peers and tunnel.
2877 *
2878 * @param c Connection to destroy.
2879 */
2880void
2881GCC_destroy (struct CadetConnection *c)
2882{
2883 GCC_check_connections ();
2884 if (NULL == c)
2885 {
2886 GNUNET_break (0);
2887 return;
2888 }
2889
2890 if (2 == c->destroy) /* cancel queues -> GCP_queue_cancel -> q_destroy -> */
2891 return; /* -> message_sent -> GCC_destroy. Don't loop. */
2892 c->destroy = 2;
2893
2894 LOG (GNUNET_ERROR_TYPE_DEBUG,
2895 "destroying connection %s\n",
2896 GCC_2s (c));
2897 LOG (GNUNET_ERROR_TYPE_DEBUG,
2898 " fc's f: %p, b: %p\n",
2899 &c->fwd_fc, &c->bck_fc);
2900 LOG (GNUNET_ERROR_TYPE_DEBUG,
2901 " fc tasks f: %u, b: %u\n",
2902 c->fwd_fc.poll_task,
2903 c->bck_fc.poll_task);
2904
2905 /* Cancel all traffic */
2906 if (NULL != c->path)
2907 {
2908 connection_cancel_queues (c, GNUNET_YES);
2909 connection_cancel_queues (c, GNUNET_NO);
2910 if (NULL != c->maintenance_q)
2911 {
2912 GCP_send_cancel (c->maintenance_q);
2913 c->maintenance_q = NULL;
2914 }
2915 }
2916 unregister_neighbors (c);
2917 path_destroy (c->path);
2918 c->path = NULL;
2919
2920 /* Delete from tunnel */
2921 if (NULL != c->t)
2922 GCT_remove_connection (c->t, c);
2923
2924 if (NULL != c->check_duplicates_task)
2925 GNUNET_SCHEDULER_cancel (c->check_duplicates_task);
2926 if (NULL != c->fwd_maintenance_task)
2927 GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
2928 if (NULL != c->bck_maintenance_task)
2929 GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
2930
2931 if (GNUNET_NO == c->was_removed)
2932 {
2933 GNUNET_break (GNUNET_YES ==
2934 GNUNET_CONTAINER_multishortmap_remove (connections,
2935 &c->id.connection_of_tunnel,
2936 c));
2937 }
2938 GNUNET_STATISTICS_update (stats,
2939 "# connections",
2940 -1,
2941 GNUNET_NO);
2942 GNUNET_free (c);
2943 GCC_check_connections ();
2944}
2945
2946
2947/**
2948 * Get the connection ID.
2949 *
2950 * @param c Connection to get the ID from.
2951 *
2952 * @return ID of the connection.
2953 */
2954const struct GNUNET_CADET_ConnectionTunnelIdentifier *
2955GCC_get_id (const struct CadetConnection *c)
2956{
2957 return &c->id;
2958}
2959
2960
2961/**
2962 * Get the connection path.
2963 *
2964 * @param c Connection to get the path from.
2965 *
2966 * @return path used by the connection.
2967 */
2968const struct CadetPeerPath *
2969GCC_get_path (const struct CadetConnection *c)
2970{
2971 if (GNUNET_NO == c->destroy)
2972 return c->path;
2973 return NULL;
2974}
2975
2976
2977/**
2978 * Get the connection state.
2979 *
2980 * @param c Connection to get the state from.
2981 *
2982 * @return state of the connection.
2983 */
2984enum CadetConnectionState
2985GCC_get_state (const struct CadetConnection *c)
2986{
2987 return c->state;
2988}
2989
2990/**
2991 * Get the connection tunnel.
2992 *
2993 * @param c Connection to get the tunnel from.
2994 *
2995 * @return tunnel of the connection.
2996 */
2997struct CadetTunnel *
2998GCC_get_tunnel (const struct CadetConnection *c)
2999{
3000 return c->t;
3001}
3002
3003
3004/**
3005 * Get free buffer space in a connection.
3006 *
3007 * @param c Connection.
3008 * @param fwd Is query about FWD traffic?
3009 *
3010 * @return Free buffer space [0 - max_msgs_queue/max_connections]
3011 */
3012unsigned int
3013GCC_get_buffer (struct CadetConnection *c, int fwd)
3014{
3015 struct CadetFlowControl *fc;
3016
3017 fc = fwd ? &c->fwd_fc : &c->bck_fc;
3018
3019 LOG (GNUNET_ERROR_TYPE_DEBUG, " Get %s buffer on %s: %u - %u\n",
3020 GC_f2s (fwd), GCC_2s (c), fc->queue_max, fc->queue_n);
3021 GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG);
3022
3023 return (fc->queue_max - fc->queue_n);
3024}
3025
3026
3027/**
3028 * Get how many messages have we allowed to send to us from a direction.
3029 *
3030 * @param c Connection.
3031 * @param fwd Are we asking about traffic from FWD (BCK messages)?
3032 *
3033 * @return last_ack_sent - last_pid_recv
3034 */
3035unsigned int
3036GCC_get_allowed (struct CadetConnection *c, int fwd)
3037{
3038 struct CadetFlowControl *fc;
3039
3040 fc = fwd ? &c->fwd_fc : &c->bck_fc;
3041 if ( (CADET_CONNECTION_READY != c->state) ||
3042 GC_is_pid_bigger (ntohl (fc->last_pid_recv.pid),
3043 ntohl (fc->last_ack_sent.pid)) )
3044 {
3045 return 0;
3046 }
3047 return (ntohl (fc->last_ack_sent.pid) - ntohl (fc->last_pid_recv.pid));
3048}
3049
3050
3051/**
3052 * Get messages queued in a connection.
3053 *
3054 * @param c Connection.
3055 * @param fwd Is query about FWD traffic?
3056 *
3057 * @return Number of messages queued.
3058 */
3059unsigned int
3060GCC_get_qn (struct CadetConnection *c, int fwd)
3061{
3062 struct CadetFlowControl *fc;
3063
3064 fc = fwd ? &c->fwd_fc : &c->bck_fc;
3065
3066 return fc->queue_n;
3067}
3068
3069
3070/**
3071 * Get next PID to use.
3072 *
3073 * @param c Connection.
3074 * @param fwd Is query about FWD traffic?
3075 * @return Next PID to use.
3076 */
3077struct CadetEncryptedMessageIdentifier
3078GCC_get_pid (struct CadetConnection *c, int fwd)
3079{
3080 struct CadetFlowControl *fc;
3081 struct CadetEncryptedMessageIdentifier pid;
3082
3083 fc = fwd ? &c->fwd_fc : &c->bck_fc;
3084 pid = fc->next_pid;
3085 fc->next_pid.pid = htonl (1 + ntohl (pid.pid));
3086 return pid;
3087}
3088
3089
3090/**
3091 * Allow the connection to advertise a buffer of the given size.
3092 *
3093 * The connection will send an @c fwd ACK message (so: in direction !fwd)
3094 * allowing up to last_pid_recv + buffer.
3095 *
3096 * @param c Connection.
3097 * @param buffer How many more messages the connection can accept.
3098 * @param fwd Is this about FWD traffic? (The ack will go dest->root).
3099 */
3100void
3101GCC_allow (struct CadetConnection *c, unsigned int buffer, int fwd)
3102{
3103 LOG (GNUNET_ERROR_TYPE_DEBUG, " allowing %s %u messages %s\n",
3104 GCC_2s (c), buffer, GC_f2s (fwd));
3105 send_ack (c, buffer, fwd, GNUNET_NO);
3106}
3107
3108
3109/**
3110 * Notify other peers on a connection of a broken link. Mark connections
3111 * to destroy after all traffic has been sent.
3112 *
3113 * @param c Connection on which there has been a disconnection.
3114 * @param peer Peer that disconnected.
3115 */
3116void
3117GCC_neighbor_disconnected (struct CadetConnection *c, struct CadetPeer *peer)
3118{
3119 struct CadetFlowControl *fc;
3120 char peer_name[16];
3121 int fwd;
3122
3123 GCC_check_connections ();
3124 strncpy (peer_name, GCP_2s (peer), 16);
3125 peer_name[15] = '\0';
3126 LOG (GNUNET_ERROR_TYPE_DEBUG, 826 LOG (GNUNET_ERROR_TYPE_DEBUG,
3127 "shutting down %s, %s disconnected\n", 827 "Creating %s using path %s\n",
3128 GCC_2s (c), peer_name); 828 GCC_2s (cc),
3129 829 GCPP_2s (path));
3130 invalidate_paths (c, peer); 830 GCPP_add_connection (path,
3131 831 off,
3132 fwd = is_fwd (c, peer); 832 cc);
3133 if (GNUNET_SYSERR == fwd) 833 for (unsigned int i=0;i<off;i++)
3134 { 834 GCP_add_connection (GCPP_get_peer_at_offset (path,
3135 GNUNET_break (0); 835 i),
3136 return; 836 cc);
3137 } 837
3138 if ( (GNUNET_YES == GCC_is_terminal (c, fwd)) || 838 first_hop = GCPP_get_peer_at_offset (path,
3139 (GNUNET_NO != c->destroy) ) 839 0);
3140 { 840 cc->mq_man = GCP_request_mq (first_hop,
3141 /* Local shutdown, or other peer already down (hence 'c->destroy'); 841 &manage_first_hop_mq,
3142 so there is no one to notify about this, just clean up. */ 842 cc);
3143 GCC_destroy (c); 843 return cc;
3144 GCC_check_connections (); 844}
3145 return; 845
3146 } 846
3147 /* Mark FlowControl towards the peer as unavaliable. */ 847/**
3148 fc = fwd ? &c->bck_fc : &c->fwd_fc; 848 * Create a connection to @a destination via @a path and
3149 fc->queue_max = 0; 849 * notify @a cb whenever we are ready for more data. This
3150 850 * is an inbound tunnel, so we must use the existing @a cid
3151 send_broken (c, &my_full_id, GCP_get_id (peer), fwd); 851 *
3152 852 * @param destination where to go
3153 /* Connection will have at least one pending message 853 * @param path which path to take (may not be the full path)
3154 * (the one we just scheduled), so delay destruction 854 * @param options options for the connection
3155 * and remove from map so we don't use accidentally. */ 855 * @param ct which tunnel uses this connection
3156 mark_destroyed (c); 856 * @param ready_cb function to call when ready to transmit
3157 GNUNET_assert (GNUNET_NO == c->was_removed); 857 * @param ready_cb_cls closure for @a cb
3158 c->was_removed = GNUNET_YES; 858 * @return handle to the connection, NULL if we already have
3159 GNUNET_break (GNUNET_YES == 859 * a connection that takes precedence on @a path
3160 GNUNET_CONTAINER_multishortmap_remove (connections,
3161 &c->id.connection_of_tunnel,
3162 c));
3163 /* Cancel queue in the direction that just died. */
3164 connection_cancel_queues (c, ! fwd);
3165 GCC_stop_poll (c, ! fwd);
3166 unregister_neighbors (c);
3167 GCC_check_connections ();
3168}
3169
3170
3171/**
3172 * Is this peer the first one on the connection?
3173 *
3174 * @param c Connection.
3175 * @param fwd Is this about fwd traffic?
3176 *
3177 * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal.
3178 */ 860 */
3179int 861struct CadetConnection *
3180GCC_is_origin (struct CadetConnection *c, int fwd) 862GCC_create_inbound (struct CadetPeer *destination,
3181{ 863 struct CadetPeerPath *path,
3182 if (!fwd && c->path->length - 1 == c->own_pos ) 864 enum GNUNET_CADET_ChannelOption options,
3183 return GNUNET_YES; 865 struct CadetTConnection *ct,
3184 if (fwd && 0 == c->own_pos) 866 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
3185 return GNUNET_YES; 867 GCC_ReadyCallback ready_cb,
3186 return GNUNET_NO; 868 void *ready_cb_cls)
3187} 869{
3188 870 struct CadetConnection *cc;
3189 871 unsigned int off;
3190/** 872
3191 * Is this peer the last one on the connection? 873 off = GCPP_find_peer (path,
3192 * 874 destination);
3193 * @param c Connection. 875 GNUNET_assert (UINT_MAX != off);
3194 * @param fwd Is this about fwd traffic? 876 cc = GCPP_get_connection (path,
3195 * Note that the ROOT is the terminal for BCK traffic! 877 destination,
3196 * 878 off);
3197 * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin. 879 if (NULL != cc)
3198 */ 880 {
3199int 881 int cmp;
3200GCC_is_terminal (struct CadetConnection *c, int fwd) 882
3201{ 883 cmp = memcmp (cid,
3202 return GCC_is_origin (c, ! fwd); 884 &cc->cid,
3203} 885 sizeof (*cid));
3204 886 if (0 == cmp)
3205 887 {
3206/** 888 /* Two peers picked the SAME random connection identifier at the
3207 * See if we are allowed to send by the next hop in the given direction. 889 same time for the same path? Must be malicious. Drop
3208 * 890 connection (existing and inbound), even if it is the only
3209 * @param c Connection. 891 one. */
3210 * @param fwd Is this about fwd traffic? 892 GNUNET_break_op (0);
3211 * 893 GCT_connection_lost (cc->ct);
3212 * @return #GNUNET_YES in case it's OK to send. 894 GCC_destroy_without_tunnel (cc);
3213 */
3214int
3215GCC_is_sendable (struct CadetConnection *c, int fwd)
3216{
3217 struct CadetFlowControl *fc;
3218
3219 LOG (GNUNET_ERROR_TYPE_DEBUG,
3220 " checking sendability of %s traffic on %s\n",
3221 GC_f2s (fwd), GCC_2s (c));
3222 if (NULL == c)
3223 {
3224 GNUNET_break (0);
3225 return GNUNET_YES;
3226 }
3227 fc = fwd ? &c->fwd_fc : &c->bck_fc;
3228 LOG (GNUNET_ERROR_TYPE_DEBUG,
3229 " last ack recv: %u, last pid sent: %u\n",
3230 ntohl (fc->last_ack_recv.pid),
3231 ntohl (fc->last_pid_sent.pid));
3232 if (GC_is_pid_bigger (ntohl (fc->last_ack_recv.pid),
3233 ntohl (fc->last_pid_sent.pid)))
3234 {
3235 LOG (GNUNET_ERROR_TYPE_DEBUG, " sendable\n");
3236 return GNUNET_YES;
3237 }
3238 LOG (GNUNET_ERROR_TYPE_DEBUG, " not sendable\n");
3239 return GNUNET_NO;
3240}
3241
3242
3243/**
3244 * Check if this connection is a direct one (never trim a direct connection).
3245 *
3246 * @param c Connection.
3247 *
3248 * @return #GNUNET_YES in case it's a direct connection, #GNUNET_NO otherwise.
3249 */
3250int
3251GCC_is_direct (struct CadetConnection *c)
3252{
3253 return (c->path->length == 2) ? GNUNET_YES : GNUNET_NO;
3254}
3255
3256
3257/**
3258 * Sends a completely built message on a connection, properly registering
3259 * all used resources.
3260 *
3261 * @param message Message to send.
3262 * @param payload_type Type of payload, in case the message is encrypted.
3263 * 0 for restransmissions (when type is no longer known)
3264 * UINT16_MAX when not applicable.
3265 * @param payload_id ID of the payload (PID, ACK, ...).
3266 * @param c Connection on which this message is transmitted.
3267 * @param fwd Is this a fwd message?
3268 * @param force Force the connection to accept the message (buffer overfill).
3269 * @param cont Continuation called once message is sent. Can be NULL.
3270 * @param cont_cls Closure for @c cont.
3271 *
3272 * @return Handle to cancel the message before it's sent.
3273 * NULL on error.
3274 * Invalid on @c cont call.
3275 */
3276struct CadetConnectionQueue *
3277GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
3278 uint16_t payload_type,
3279 struct CadetEncryptedMessageIdentifier payload_id,
3280 struct CadetConnection *c, int fwd, int force,
3281 GCC_sent cont, void *cont_cls)
3282{
3283 struct CadetFlowControl *fc;
3284 struct CadetConnectionQueue *q;
3285 uint16_t size;
3286 uint16_t type;
3287
3288 size = ntohs (message->size);
3289 type = ntohs (message->type);
3290
3291 GCC_check_connections ();
3292 fc = fwd ? &c->fwd_fc : &c->bck_fc;
3293 if (0 == fc->queue_max)
3294 {
3295 GNUNET_break (0);
3296 return NULL;
3297 }
3298
3299 LOG (GNUNET_ERROR_TYPE_INFO,
3300 "--> %s (%s %4u) on conn %s (%p) %s [%5u]\n",
3301 GC_m2s (type), GC_m2s (payload_type), payload_id, GCC_2s (c), c,
3302 GC_f2s(fwd), size);
3303 switch (type)
3304 {
3305 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED:
3306 LOG (GNUNET_ERROR_TYPE_DEBUG, " Q_N+ %p %u, PIDsnt: %u, ACKrcv: %u\n",
3307 fc,
3308 fc->queue_n,
3309 ntohl (fc->last_pid_sent.pid),
3310 ntohl (fc->last_ack_recv.pid));
3311 if (GNUNET_NO == force)
3312 {
3313 fc->queue_n++;
3314 }
3315 break;
3316
3317 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX:
3318 /* nothing to do here */
3319 break;
3320
3321 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
3322 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK:
3323 /* Should've only be used for restransmissions. */
3324 GNUNET_break (0 == payload_type);
3325 break;
3326
3327 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK:
3328 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL:
3329 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
3330 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
3331 GNUNET_assert (GNUNET_YES == force);
3332 break;
3333
3334 default:
3335 GNUNET_break (0);
3336 return NULL; 895 return NULL;
3337 } 896 }
3338 897 if (0 < cmp)
3339 if (fc->queue_n > fc->queue_max && GNUNET_NO == force)
3340 {
3341 GNUNET_STATISTICS_update (stats, "# messages dropped (buffer full)",
3342 1, GNUNET_NO);
3343 GNUNET_break (0);
3344 LOG (GNUNET_ERROR_TYPE_DEBUG, "queue full: %u/%u\n",
3345 fc->queue_n, fc->queue_max);
3346 if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == type)
3347 { 898 {
3348 fc->queue_n--; 899 /* drop existing */
900 LOG (GNUNET_ERROR_TYPE_DEBUG,
901 "Got two connections on %s, dropping my existing %s\n",
902 GCPP_2s (path),
903 GCC_2s (cc));
904 GCT_connection_lost (cc->ct);
905 GCC_destroy_without_tunnel (cc);
3349 } 906 }
3350 return NULL; /* Drop this message */ 907 else
3351 }
3352
3353 LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %s %u\n",
3354 GCC_2s (c), c->pending_messages);
3355 c->pending_messages++;
3356
3357 q = GNUNET_new (struct CadetConnectionQueue);
3358 q->cont = cont;
3359 q->cont_cls = cont_cls;
3360 q->forced = force;
3361 GNUNET_CONTAINER_DLL_insert (fc->q_head, fc->q_tail, q);
3362 q->peer_q = GCP_send (get_hop (c, fwd),
3363 message,
3364 payload_type,
3365 payload_id,
3366 c,
3367 fwd,
3368 &conn_message_sent, q);
3369 if (NULL == q->peer_q)
3370 {
3371 LOG (GNUNET_ERROR_TYPE_DEBUG, "dropping msg on %s, NULL q\n", GCC_2s (c));
3372 GNUNET_CONTAINER_DLL_remove (fc->q_head, fc->q_tail, q);
3373 GNUNET_free (q);
3374 GCC_check_connections ();
3375 return NULL;
3376 }
3377 GCC_check_connections ();
3378 return q;
3379}
3380
3381
3382/**
3383 * Cancel a previously sent message while it's in the queue.
3384 *
3385 * ONLY can be called before the continuation given to the send function
3386 * is called. Once the continuation is called, the message is no longer in the
3387 * queue.
3388 *
3389 * @param q Handle to the queue.
3390 */
3391void
3392GCC_cancel (struct CadetConnectionQueue *q)
3393{
3394 LOG (GNUNET_ERROR_TYPE_DEBUG, "! GCC cancel message\n");
3395
3396 /* send_cancel calls message_sent, which calls q->cont and frees q */
3397 GCP_send_cancel (q->peer_q);
3398 GCC_check_connections ();
3399}
3400
3401
3402/**
3403 * Sends a CREATE CONNECTION message for a path to a peer.
3404 * Changes the connection and tunnel states if necessary.
3405 *
3406 * @param c Connection to create.
3407 */
3408void
3409GCC_send_create (struct CadetConnection *c)
3410{
3411 static struct CadetEncryptedMessageIdentifier zero;
3412 enum CadetTunnelCState state;
3413 size_t size;
3414
3415 GCC_check_connections ();
3416 size = sizeof (struct GNUNET_CADET_ConnectionCreateMessage);
3417 size += c->path->length * sizeof (struct GNUNET_PeerIdentity);
3418 {
3419 /* Allocate message on the stack */
3420 unsigned char cbuf[size];
3421 struct GNUNET_CADET_ConnectionCreateMessage *msg;
3422 struct GNUNET_PeerIdentity *peers;
3423
3424
3425 msg = (struct GNUNET_CADET_ConnectionCreateMessage *) cbuf;
3426 msg->header.size = htons (size);
3427 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
3428 msg->options = htonl (0);
3429 msg->cid = *GCC_get_id (c);
3430 peers = (struct GNUNET_PeerIdentity *) &msg[1];
3431 for (int i = 0; i < c->path->length; i++)
3432 { 908 {
3433 GNUNET_PEER_resolve (c->path->peers[i], peers++); 909 /* keep existing */
910 LOG (GNUNET_ERROR_TYPE_DEBUG,
911 "Got two connections on %s, keeping my existing %s\n",
912 GCPP_2s (path),
913 GCC_2s (cc));
914 return NULL;
3434 } 915 }
3435 GNUNET_assert (NULL == c->maintenance_q);
3436 c->maintenance_q = GCP_send (get_next_hop (c),
3437 &msg->header,
3438 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
3439 zero,
3440 c, GNUNET_YES,
3441 &conn_message_sent, NULL);
3442 } 916 }
3443 917
3444 LOG (GNUNET_ERROR_TYPE_INFO, "==> %s %19s on conn %s (%p) FWD [%5u]\n", 918 return connection_create (destination,
3445 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE), "", 919 path,
3446 GCC_2s (c), c, size); 920 off,
3447 LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u (create)\n", 921 options,
3448 c, c->pending_messages); 922 ct,
3449 c->pending_messages++; 923 cid,
3450 924 CADET_CONNECTION_CREATE_RECEIVED,
3451 state = GCT_get_cstate (c->t); 925 ready_cb,
3452 if (CADET_TUNNEL_SEARCHING == state || CADET_TUNNEL_NEW == state) 926 ready_cb_cls);
3453 GCT_change_cstate (c->t, CADET_TUNNEL_WAITING);
3454 if (CADET_CONNECTION_NEW == c->state)
3455 connection_change_state (c, CADET_CONNECTION_SENT);
3456 GCC_check_connections ();
3457} 927}
3458 928
3459 929
3460/** 930/**
3461 * Send an ACK on the appropriate connection/channel, depending on 931 * Create a connection to @a destination via @a path and
3462 * the direction and the position of the peer. 932 * notify @a cb whenever we are ready for more data.
3463 * 933 *
3464 * @param c Which connection to send the hop-by-hop ACK. 934 * @param destination where to go
3465 * @param fwd Is this a fwd ACK? (will go dest->root). 935 * @param path which path to take (may not be the full path)
3466 * @param force Send the ACK even if suboptimal (e.g. requested by POLL). 936 * @param off offset of @a destination on @a path
937 * @param options options for the connection
938 * @param ct tunnel that uses the connection
939 * @param ready_cb function to call when ready to transmit
940 * @param ready_cb_cls closure for @a cb
941 * @return handle to the connection
3467 */ 942 */
3468void 943struct CadetConnection *
3469GCC_send_ack (struct CadetConnection *c, int fwd, int force) 944GCC_create (struct CadetPeer *destination,
945 struct CadetPeerPath *path,
946 unsigned int off,
947 enum GNUNET_CADET_ChannelOption options,
948 struct CadetTConnection *ct,
949 GCC_ReadyCallback ready_cb,
950 void *ready_cb_cls)
3470{ 951{
3471 unsigned int buffer; 952 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
3472
3473 GCC_check_connections ();
3474 LOG (GNUNET_ERROR_TYPE_DEBUG, "GCC send %s ACK on %s\n",
3475 GC_f2s (fwd), GCC_2s (c));
3476
3477 if (NULL == c)
3478 {
3479 GNUNET_break (0);
3480 return;
3481 }
3482 953
3483 if (GNUNET_NO != c->destroy) 954 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
3484 { 955 &cid,
3485 LOG (GNUNET_ERROR_TYPE_DEBUG, " being destroyed, why bother...\n"); 956 sizeof (cid));
3486 GCC_check_connections (); 957 return connection_create (destination,
3487 return; 958 path,
3488 } 959 off,
3489 960 options,
3490 /* Get available buffer space */ 961 ct,
3491 if (GCC_is_terminal (c, fwd)) 962 &cid,
3492 { 963 CADET_CONNECTION_NEW,
3493 LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from all channels\n"); 964 ready_cb,
3494 buffer = GCT_get_channels_buffer (c->t); 965 ready_cb_cls);
3495 }
3496 else
3497 {
3498 LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from one connection\n");
3499 buffer = GCC_get_buffer (c, fwd);
3500 }
3501 LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer);
3502 if (0 == buffer && GNUNET_NO == force)
3503 {
3504 GCC_check_connections ();
3505 return;
3506 }
3507
3508 /* Send available buffer space */
3509 if (GNUNET_YES == GCC_is_origin (c, fwd))
3510 {
3511 GNUNET_assert (NULL != c->t);
3512 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channels...\n");
3513 GCT_unchoke_channels (c->t);
3514 }
3515 else
3516 {
3517 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on connection\n");
3518 send_ack (c, buffer, fwd, force);
3519 }
3520 GCC_check_connections ();
3521} 966}
3522 967
3523 968
3524/** 969/**
3525 * Send a message to all peers in this connection that the connection 970 * Transmit message @a msg via connection @a cc. Must only be called
3526 * is no longer valid. 971 * (once) after the connection has signalled that it is ready via the
972 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
973 * connection is right now ready for transmission.
3527 * 974 *
3528 * If some peer should not receive the message, it should be zero'ed out 975 * @param cc connection identification
3529 * before calling this function. 976 * @param env envelope with message to transmit; must NOT
3530 * 977 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
3531 * @param c The connection whose peers to notify.
3532 */ 978 */
3533void 979void
3534GCC_send_destroy (struct CadetConnection *c) 980GCC_transmit (struct CadetConnection *cc,
981 struct GNUNET_MQ_Envelope *env)
3535{ 982{
3536 static struct CadetEncryptedMessageIdentifier zero;
3537 struct GNUNET_CADET_ConnectionDestroyMessage msg;
3538
3539 if (GNUNET_YES == c->destroy)
3540 return;
3541 GCC_check_connections ();
3542 msg.header.size = htons (sizeof (msg));
3543 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
3544 msg.cid = c->id;
3545 msg.reserved = htonl (0);
3546 LOG (GNUNET_ERROR_TYPE_DEBUG, 983 LOG (GNUNET_ERROR_TYPE_DEBUG,
3547 " sending connection destroy for connection %s\n", 984 "Scheduling message for transmission on %s\n",
3548 GCC_2s (c)); 985 GCC_2s (cc));
3549 986 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
3550 if (GNUNET_NO == GCC_is_terminal (c, GNUNET_YES)) 987 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
3551 (void) GCC_send_prebuilt_message (&msg.header, 988 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
3552 UINT16_MAX, 989 cc->mqm_ready = GNUNET_NO;
3553 zero, 990 if (NULL != cc->task)
3554 c, 991 {
3555 GNUNET_YES, GNUNET_YES, NULL, NULL); 992 GNUNET_SCHEDULER_cancel (cc->task);
3556 if (GNUNET_NO == GCC_is_terminal (c, GNUNET_NO)) 993 cc->task = NULL;
3557 (void) GCC_send_prebuilt_message (&msg.header, 994 }
3558 UINT16_MAX, 995 GCP_send (cc->mq_man,
3559 zero, 996 env);
3560 c,
3561 GNUNET_NO, GNUNET_YES, NULL, NULL);
3562 mark_destroyed (c);
3563 GCC_check_connections ();
3564} 997}
3565 998
3566 999
3567/** 1000/**
3568 * @brief Start a polling timer for the connection. 1001 * Obtain the path used by this connection.
3569 *
3570 * When a neighbor does not accept more traffic on the connection it could be
3571 * caused by a simple congestion or by a lost ACK. Polling enables to check
3572 * for the lastest ACK status for a connection.
3573 * 1002 *
3574 * @param c Connection. 1003 * @param cc connection
3575 * @param fwd Should we poll in the FWD direction? 1004 * @return path to @a cc
3576 */ 1005 */
3577void 1006struct CadetPeerPath *
3578GCC_start_poll (struct CadetConnection *c, int fwd) 1007GCC_get_path (struct CadetConnection *cc)
3579{ 1008{
3580 struct CadetFlowControl *fc; 1009 return cc->path;
3581
3582 fc = fwd ? &c->fwd_fc : &c->bck_fc;
3583 LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL %s requested\n",
3584 GC_f2s (fwd));
3585 if (NULL != fc->poll_task || NULL != fc->poll_msg)
3586 {
3587 LOG (GNUNET_ERROR_TYPE_DEBUG, " POLL already in progress (t: %p, m: %p)\n",
3588 fc->poll_task, fc->poll_msg);
3589 return;
3590 }
3591 if (0 == fc->queue_max)
3592 {
3593 /* Should not be needed, traffic should've been cancelled. */
3594 GNUNET_break (0);
3595 LOG (GNUNET_ERROR_TYPE_DEBUG, " POLL not possible, peer disconnected\n");
3596 return;
3597 }
3598 LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL started on request\n");
3599 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, &send_poll, fc);
3600} 1010}
3601 1011
3602 1012
3603/** 1013/**
3604 * @brief Stop polling a connection for ACKs. 1014 * Obtain unique ID for the connection.
3605 * 1015 *
3606 * Once we have enough ACKs for future traffic, polls are no longer necessary. 1016 * @param cc connection.
3607 * 1017 * @return unique number of the connection
3608 * @param c Connection.
3609 * @param fwd Should we stop the poll in the FWD direction?
3610 */ 1018 */
3611void 1019const struct GNUNET_CADET_ConnectionTunnelIdentifier *
3612GCC_stop_poll (struct CadetConnection *c, int fwd) 1020GCC_get_id (struct CadetConnection *cc)
3613{ 1021{
3614 struct CadetFlowControl *fc; 1022 return &cc->cid;
3615
3616 fc = fwd ? &c->fwd_fc : &c->bck_fc;
3617 if (NULL != fc->poll_task)
3618 {
3619 GNUNET_SCHEDULER_cancel (fc->poll_task);
3620 fc->poll_task = NULL;
3621 }
3622 if (NULL != fc->poll_msg)
3623 {
3624 GCC_cancel (fc->poll_msg);
3625 fc->poll_msg = NULL;
3626 }
3627} 1023}
3628 1024
3629 1025
3630/** 1026/**
3631 * Get a (static) string for a connection. 1027 * Get a (static) string for a connection.
3632 * 1028 *
3633 * @param c Connection. 1029 * @param cc Connection.
3634 */ 1030 */
3635const char * 1031const char *
3636GCC_2s (const struct CadetConnection *c) 1032GCC_2s (const struct CadetConnection *cc)
3637{ 1033{
3638 if (NULL == c) 1034 static char buf[128];
3639 return "NULL";
3640 1035
3641 if (NULL != c->t) 1036 if (NULL == cc)
3642 { 1037 return "Connection(NULL)";
3643 static char buf[128];
3644 1038
3645 SPRINTF (buf, "%s (->%s)", 1039 if (NULL != cc->ct)
3646 GNUNET_sh2s (&GCC_get_id (c)->connection_of_tunnel), 1040 {
3647 GCT_2s (c->t)); 1041 GNUNET_snprintf (buf,
1042 sizeof (buf),
1043 "Connection %s (%s)",
1044 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
1045 GCT_2s (cc->ct->t));
3648 return buf; 1046 return buf;
3649 } 1047 }
3650 return GNUNET_sh2s (&c->id.connection_of_tunnel); 1048 GNUNET_snprintf (buf,
1049 sizeof (buf),
1050 "Connection %s",
1051 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
1052 return buf;
3651} 1053}
3652 1054
3653 1055
1056#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
1057
1058
3654/** 1059/**
3655 * Log all possible info about the connection state. 1060 * Log connection info.
3656 * 1061 *
3657 * @param c Connection to debug. 1062 * @param cc connection
3658 * @param level Debug level to use. 1063 * @param level Debug level to use.
3659 */ 1064 */
3660void 1065void
3661GCC_debug (const struct CadetConnection *c, enum GNUNET_ErrorType level) 1066GCC_debug (struct CadetConnection *cc,
1067 enum GNUNET_ErrorType level)
3662{ 1068{
3663 int do_log; 1069 int do_log;
3664 char *s;
3665 1070
3666 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), 1071 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
3667 "cadet-con", 1072 "cadet-con",
3668 __FILE__, __FUNCTION__, __LINE__); 1073 __FILE__, __FUNCTION__, __LINE__);
3669 if (0 == do_log) 1074 if (0 == do_log)
3670 return; 1075 return;
3671 1076 if (NULL == cc)
3672 if (NULL == c)
3673 { 1077 {
3674 LOG2 (level, "CCC DEBUG NULL CONNECTION\n"); 1078 LOG2 (level,
1079 "Connection (NULL)\n");
3675 return; 1080 return;
3676 } 1081 }
3677 1082 LOG2 (level,
3678 LOG2 (level, "CCC DEBUG CONNECTION %s\n", GCC_2s (c)); 1083 "%s to %s via path %s in state %d is %s\n",
3679 s = path_2s (c->path); 1084 GCC_2s (cc),
3680 LOG2 (level, "CCC path %s, own pos: %u\n", s, c->own_pos); 1085 GCP_2s (cc->destination),
3681 GNUNET_free (s); 1086 GCPP_2s (cc->path),
3682 LOG2 (level, "CCC state: %s, destroy: %u\n", 1087 cc->state,
3683 GCC_state2s (c->state), c->destroy); 1088 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
3684 LOG2 (level, "CCC pending messages: %u\n", c->pending_messages);
3685 if (NULL != c->perf)
3686 LOG2 (level, "CCC us/byte: %f\n", c->perf->avg);
3687
3688 LOG2 (level, "CCC FWD flow control:\n");
3689 LOG2 (level, "CCC queue: %u/%u\n", c->fwd_fc.queue_n, c->fwd_fc.queue_max);
3690 LOG2 (level, "CCC last PID sent: %5u, recv: %5u\n",
3691 ntohl (c->fwd_fc.last_pid_sent.pid),
3692 ntohl (c->fwd_fc.last_pid_recv.pid));
3693 LOG2 (level, "CCC last ACK sent: %5u, recv: %5u\n",
3694 ntohl (c->fwd_fc.last_ack_sent.pid),
3695 ntohl (c->fwd_fc.last_ack_recv.pid));
3696 LOG2 (level, "CCC recv PID bitmap: %X\n", c->fwd_fc.recv_bitmap);
3697 LOG2 (level, "CCC poll: task %d, msg %p, msg_ack %p)\n",
3698 c->fwd_fc.poll_task, c->fwd_fc.poll_msg, c->fwd_fc.ack_msg);
3699
3700 LOG2 (level, "CCC BCK flow control:\n");
3701 LOG2 (level, "CCC queue: %u/%u\n", c->bck_fc.queue_n, c->bck_fc.queue_max);
3702 LOG2 (level, "CCC last PID sent: %5u, recv: %5u\n",
3703 ntohl (c->bck_fc.last_pid_sent.pid),
3704 ntohl (c->bck_fc.last_pid_recv.pid));
3705 LOG2 (level, "CCC last ACK sent: %5u, recv: %5u\n",
3706 ntohl (c->bck_fc.last_ack_sent.pid),
3707 ntohl (c->bck_fc.last_ack_recv.pid));
3708 LOG2 (level, "CCC recv PID bitmap: %X\n", c->bck_fc.recv_bitmap);
3709 LOG2 (level, "CCC poll: task %d, msg %p, msg_ack %p)\n",
3710 c->bck_fc.poll_task, c->bck_fc.poll_msg, c->bck_fc.ack_msg);
3711
3712 LOG2 (level, "CCC DEBUG CONNECTION END\n");
3713} 1089}
1090
1091/* end of gnunet-service-cadet-new_connection.c */
diff --git a/src/cadet/gnunet-service-cadet_connection.h b/src/cadet/gnunet-service-cadet_connection.h
index 307cb42c2..fdb184366 100644
--- a/src/cadet/gnunet-service-cadet_connection.h
+++ b/src/cadet/gnunet-service-cadet_connection.h
@@ -1,6 +1,7 @@
1
1/* 2/*
2 This file is part of GNUnet. 3 This file is part of GNUnet.
3 Copyright (C) 2013 GNUnet e.V. 4 Copyright (C) 2001-2017 GNUnet e.V.
4 5
5 GNUnet is free software; you can redistribute it and/or modify 6 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 7 it under the terms of the GNU General Public License as published
@@ -20,557 +21,319 @@
20 21
21/** 22/**
22 * @file cadet/gnunet-service-cadet_connection.h 23 * @file cadet/gnunet-service-cadet_connection.h
23 * @brief cadet service; dealing with connections 24 * @brief A connection is a live end-to-end messaging mechanism
25 * where the peers are identified by a path and know how
26 * to forward along the route using a connection identifier
27 * for routing the data.
24 * @author Bartlomiej Polot 28 * @author Bartlomiej Polot
25 * 29 * @author Christian Grothoff
26 * All functions in this file use the prefix GCC (GNUnet Cadet Connection)
27 */ 30 */
28
29#ifndef GNUNET_SERVICE_CADET_CONNECTION_H 31#ifndef GNUNET_SERVICE_CADET_CONNECTION_H
30#define GNUNET_SERVICE_CADET_CONNECTION_H 32#define GNUNET_SERVICE_CADET_CONNECTION_H
31 33
32#ifdef __cplusplus
33extern "C"
34{
35#if 0 /* keep Emacsens' auto-indent happy */
36}
37#endif
38#endif
39
40#include "gnunet_util_lib.h" 34#include "gnunet_util_lib.h"
41 35#include "gnunet-service-cadet.h"
42
43/**
44 * All the states a connection can be in.
45 */
46enum CadetConnectionState
47{
48 /**
49 * Uninitialized status, should never appear in operation.
50 */
51 CADET_CONNECTION_NEW,
52
53 /**
54 * Connection create message sent, waiting for ACK.
55 */
56 CADET_CONNECTION_SENT,
57
58 /**
59 * Connection ACK sent, waiting for ACK.
60 */
61 CADET_CONNECTION_ACK,
62
63 /**
64 * Connection confirmed, ready to carry traffic.
65 */
66 CADET_CONNECTION_READY,
67
68 /**
69 * Connection to be destroyed, just waiting to empty queues.
70 */
71 CADET_CONNECTION_DESTROYED,
72
73 /**
74 * Connection to be destroyed because of a distant peer, same as DESTROYED.
75 */
76 CADET_CONNECTION_BROKEN,
77};
78
79
80/**
81 * Struct containing all information regarding a connection to a peer.
82 */
83struct CadetConnection;
84
85/**
86 * Handle for messages queued but not yet sent.
87 */
88struct CadetConnectionQueue;
89
90#include "cadet_path.h"
91#include "gnunet-service-cadet_channel.h"
92#include "gnunet-service-cadet_peer.h" 36#include "gnunet-service-cadet_peer.h"
37#include "cadet_protocol.h"
93 38
94 39
95/** 40/**
96 * Check invariants for all connections using #check_neighbours(). 41 * Function called to notify tunnel about change in our readyness.
97 */
98void
99GCC_check_connections (void);
100
101
102/**
103 * Callback called when a queued message is sent.
104 * 42 *
105 * @param cls Closure. 43 * @param cls closure
106 * @param c Connection this message was on. 44 * @param is_ready #GNUNET_YES if the connection is now ready for transmission,
107 * @param type Type of message sent. 45 * #GNUNET_NO if the connection is no longer ready for transmission
108 * @param fwd Was this a FWD going message?
109 * @param size Size of the message.
110 */ 46 */
111typedef void 47typedef void
112(*GCC_sent) (void *cls, 48(*GCC_ReadyCallback)(void *cls,
113 struct CadetConnection *c, 49 int is_ready);
114 struct CadetConnectionQueue *q,
115 uint16_t type,
116 int fwd,
117 size_t size);
118 50
119 51
120/** 52/**
121 * Handler for connection creation. 53 * Destroy a connection, called when the CORE layer is already done
54 * (i.e. has received a BROKEN message), but if we still have to
55 * communicate the destruction of the connection to the tunnel (if one
56 * exists).
122 * 57 *
123 * @param peer Message sender (neighbor). 58 * @param cc connection to destroy
124 * @param msg Message itself.
125 */ 59 */
126void 60void
127GCC_handle_create (struct CadetPeer *peer, 61GCC_destroy_without_core (struct CadetConnection *cc);
128 const struct GNUNET_CADET_ConnectionCreateMessage *msg);
129 62
130 63
131/** 64/**
132 * Handler for connection confirmations. 65 * Destroy a connection, called if the tunnel association with the
66 * connection was already broken, but we still need to notify the CORE
67 * layer about the breakage.
133 * 68 *
134 * @param peer Message sender (neighbor). 69 * @param cc connection to destroy
135 * @param msg Message itself.
136 */ 70 */
137void 71void
138GCC_handle_confirm (struct CadetPeer *peer, 72GCC_destroy_without_tunnel (struct CadetConnection *cc);
139 const struct GNUNET_CADET_ConnectionCreateAckMessage *msg);
140 73
141 74
142/** 75/**
143 * Handler for notifications of broken connections. 76 * Lookup a connection by its identifier.
144 * 77 *
145 * @param peer Message sender (neighbor). 78 * @param cid identifier to resolve
146 * @param msg Message itself. 79 * @return NULL if connection was not found
147 */ 80 */
148void 81struct CadetConnection *
149GCC_handle_broken (struct CadetPeer *peer, 82GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
150 const struct GNUNET_CADET_ConnectionBrokenMessage *msg);
151 83
152/**
153 * Handler for notifications of destroyed connections.
154 *
155 * @param peer Message sender (neighbor).
156 * @param msg Message itself.
157 */
158void
159GCC_handle_destroy (struct CadetPeer *peer,
160 const struct GNUNET_CADET_ConnectionDestroyMessage *msg);
161 84
162/** 85/**
163 * Handler for cadet network traffic hop-by-hop acks. 86 * Create a connection to @a destination via @a path and
87 * notify @a cb whenever we are ready for more data.
164 * 88 *
165 * @param peer Message sender (neighbor). 89 * @param destination where to go
166 * @param msg Message itself. 90 * @param path which path to take (may not be the full path)
91 * @param off offset of @a destination on @a path
92 * @param options options for the connection
93 * @param ct which tunnel uses this connection
94 * @param ready_cb function to call when ready to transmit
95 * @param ready_cb_cls closure for @a cb
96 * @return handle to the connection
167 */ 97 */
168void 98struct CadetConnection *
169GCC_handle_ack (struct CadetPeer *peer, 99GCC_create (struct CadetPeer *destination,
170 const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg); 100 struct CadetPeerPath *path,
101 unsigned int off,
102 enum GNUNET_CADET_ChannelOption options,
103 struct CadetTConnection *ct,
104 GCC_ReadyCallback ready_cb,
105 void *ready_cb_cls);
171 106
172/**
173 * Handler for cadet network traffic hop-by-hop data counter polls.
174 *
175 * @param peer Message sender (neighbor).
176 * @param msg Message itself.
177 */
178void
179GCC_handle_poll (struct CadetPeer *peer,
180 const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg);
181 107
182/** 108/**
183 * Handler for key exchange traffic (Axolotl KX). 109 * Create a connection to @a destination via @a path and
110 * notify @a cb whenever we are ready for more data. This
111 * is an inbound tunnel, so we must use the existing @a cid
184 * 112 *
185 * @param peer Message sender (neighbor). 113 * @param destination where to go
186 * @param msg Message itself. 114 * @param path which path to take (may not be the full path)
115 * @param options options for the connection
116 * @param ct which tunnel uses this connection
117 * @param ready_cb function to call when ready to transmit
118 * @param ready_cb_cls closure for @a cb
119 * @return handle to the connection, NULL if we already have
120 * a connection that takes precedence on @a path
187 */ 121 */
188void 122struct CadetConnection *
189GCC_handle_kx (struct CadetPeer *peer, 123GCC_create_inbound (struct CadetPeer *destination,
190 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg); 124 struct CadetPeerPath *path,
125 enum GNUNET_CADET_ChannelOption options,
126 struct CadetTConnection *ct,
127 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
128 GCC_ReadyCallback ready_cb,
129 void *ready_cb_cls);
130
191 131
192/** 132/**
193 * Handler for encrypted cadet network traffic (channel mgmt, data). 133 * Transmit message @a msg via connection @a cc. Must only be called
134 * (once) after the connection has signalled that it is ready via the
135 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
136 * connection is right now ready for transmission.
194 * 137 *
195 * @param peer Message sender (neighbor). 138 * @param cc connection identification
196 * @param msg Message itself. 139 * @param env envelope with message to transmit;
140 * the #GNUNET_MQ_notify_send() must not have yet been used
141 * for the envelope. Also, the message better match the
142 * connection identifier of this connection...
197 */ 143 */
198void 144void
199GCC_handle_encrypted (struct CadetPeer *peer, 145GCC_transmit (struct CadetConnection *cc,
200 const struct GNUNET_CADET_TunnelEncryptedMessage *msg); 146 struct GNUNET_MQ_Envelope *env);
201 147
202/**
203 * Core handler for axolotl key exchange traffic.
204 *
205 * @param cls Closure (unused).
206 * @param message Message received.
207 * @param peer Neighbor who sent the message.
208 *
209 * @return GNUNET_OK, to keep the connection open.
210 */
211int
212GCC_handle_ax_kx (void *cls, const struct GNUNET_PeerIdentity *peer,
213 const struct GNUNET_MessageHeader *message);
214 148
215/** 149/**
216 * Core handler for axolotl encrypted cadet network traffic. 150 * A CREATE_ACK was received for this connection, process it.
217 * 151 *
218 * @param cls Closure (unused). 152 * @param cc the connection that got the ACK.
219 * @param message Message received.
220 * @param peer Neighbor who sent the message.
221 *
222 * @return GNUNET_OK, to keep the connection open.
223 */ 153 */
224int 154void
225GCC_handle_ax (void *cls, const struct GNUNET_PeerIdentity *peer, 155GCC_handle_connection_create_ack (struct CadetConnection *cc);
226 struct GNUNET_MessageHeader *message);
227 156
228/**
229 * Core handler for cadet keepalives.
230 *
231 * @param cls closure
232 * @param message message
233 * @param peer peer identity this notification is about
234 * @return GNUNET_OK to keep the connection open,
235 * GNUNET_SYSERR to close it (signal serious error)
236 *
237 * TODO: Check who we got this from, to validate route.
238 */
239int
240GCC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
241 const struct GNUNET_MessageHeader *message);
242 157
243/** 158/**
244 * Send an ACK on the appropriate connection/channel, depending on 159 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
245 * the direction and the position of the peer. 160 * connection that we already have. Either our ACK got lost
161 * or something is fishy. Consider retransmitting the ACK.
246 * 162 *
247 * @param c Which connection to send the hop-by-hop ACK. 163 * @param cc connection that got the duplicate CREATE
248 * @param fwd Is this a fwd ACK? (will go dest->root).
249 * @param force Send the ACK even if suboptimal (e.g. requested by POLL).
250 */ 164 */
251void 165void
252GCC_send_ack (struct CadetConnection *c, int fwd, int force); 166GCC_handle_duplicate_create (struct CadetConnection *cc);
253 167
254/**
255 * Initialize the connections subsystem
256 *
257 * @param c Configuration handle.
258 */
259void
260GCC_init (const struct GNUNET_CONFIGURATION_Handle *c);
261 168
262/** 169/**
263 * Shut down the connections subsystem. 170 * Handle KX message.
171 *
172 * @param cc connection that received encrypted message
173 * @param msg the key exchange message
264 */ 174 */
265void 175void
266GCC_shutdown (void); 176GCC_handle_kx (struct CadetConnection *cc,
177 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
267 178
268/**
269 * Create a connection.
270 *
271 * @param cid Connection ID (either created locally or imposed remotely).
272 * @param t Tunnel this connection belongs to (or NULL for transit connections);
273 * @param path Path this connection has to use (copy is made).
274 * @param own_pos Own position in the @c path path.
275 *
276 * @return Newly created connection.
277 * NULL in case of error: own id not in path, wrong neighbors, ...
278 */
279struct CadetConnection *
280GCC_new (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
281 struct CadetTunnel *t,
282 struct CadetPeerPath *path,
283 unsigned int own_pos);
284 179
285/** 180/**
286 * Connection is no longer needed: destroy it. 181 * Handle KX_AUTH message.
287 *
288 * Cancels all pending traffic (including possible DESTROY messages), all
289 * maintenance tasks and removes the connection from neighbor peers and tunnel.
290 * 182 *
291 * @param c Connection to destroy. 183 * @param cc connection that received encrypted message
184 * @param msg the key exchange message
292 */ 185 */
293void 186void
294GCC_destroy (struct CadetConnection *c); 187GCC_handle_kx_auth (struct CadetConnection *cc,
295 188 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg);
296/**
297 * Get the connection ID.
298 *
299 * @param c Connection to get the ID from.
300 *
301 * @return ID of the connection.
302 */
303const struct GNUNET_CADET_ConnectionTunnelIdentifier *
304GCC_get_id (const struct CadetConnection *c);
305 189
306 190
307/** 191/**
308 * Get the connection path. 192 * Performance metrics for a connection.
309 *
310 * @param c Connection to get the path from.
311 *
312 * @return path used by the connection.
313 */ 193 */
314const struct CadetPeerPath * 194struct CadetConnectionMetrics
315GCC_get_path (const struct CadetConnection *c); 195{
316 196
317/** 197 /**
318 * Get the connection state. 198 * Our current best estimate of the latency, based on a weighted
319 * 199 * average of at least @a latency_datapoints values.
320 * @param c Connection to get the state from. 200 */
321 * 201 struct GNUNET_TIME_Relative aged_latency;
322 * @return state of the connection.
323 */
324enum CadetConnectionState
325GCC_get_state (const struct CadetConnection *c);
326 202
327/** 203 /**
328 * Get the connection tunnel. 204 * When was this connection first established? (by us sending or
329 * 205 * receiving the CREATE_ACK for the first time)
330 * @param c Connection to get the tunnel from. 206 */
331 * 207 struct GNUNET_TIME_Absolute age;
332 * @return tunnel of the connection.
333 */
334struct CadetTunnel *
335GCC_get_tunnel (const struct CadetConnection *c);
336 208
337/** 209 /**
338 * Get free buffer space in a connection. 210 * When was this connection last used? (by us sending or
339 * 211 * receiving a PAYLOAD message on it)
340 * @param c Connection. 212 */
341 * @param fwd Is query about FWD traffic? 213 struct GNUNET_TIME_Absolute last_use;
342 *
343 * @return Free buffer space [0 - max_msgs_queue/max_connections]
344 */
345unsigned int
346GCC_get_buffer (struct CadetConnection *c, int fwd);
347 214
348/** 215 /**
349 * Get how many messages have we allowed to send to us from a direction. 216 * How many packets that ought to generate an ACK did we send via
350 * 217 * this connection?
351 * @param c Connection. 218 */
352 * @param fwd Are we asking about traffic from FWD (BCK messages)? 219 unsigned long long num_acked_transmissions;
353 *
354 * @return last_ack_sent - last_pid_recv
355 */
356unsigned int
357GCC_get_allowed (struct CadetConnection *c, int fwd);
358 220
359/** 221 /**
360 * Get messages queued in a connection. 222 * Number of packets that were sent via this connection did actually
361 * 223 * receive an ACK? (Note: ACKs may be transmitted and lost via
362 * @param c Connection. 224 * other connections, so this value should only be interpreted
363 * @param fwd Is query about FWD traffic? 225 * relative to @e num_acked_transmissions and in relation to other
364 * 226 * connections.)
365 * @return Number of messages queued. 227 */
366 */ 228 unsigned long long num_successes;
367unsigned int
368GCC_get_qn (struct CadetConnection *c, int fwd);
369 229
370/** 230};
371 * Get next PID to use.
372 *
373 * @param c Connection.
374 * @param fwd Is query about FWD traffic?
375 * @return Next PID to use.
376 */
377struct CadetEncryptedMessageIdentifier
378GCC_get_pid (struct CadetConnection *c, int fwd);
379 231
380/**
381 * Allow the connection to advertise a buffer of the given size.
382 *
383 * The connection will send an @c fwd ACK message (so: in direction !fwd)
384 * allowing up to last_pid_recv + buffer.
385 *
386 * @param c Connection.
387 * @param buffer How many more messages the connection can accept.
388 * @param fwd Is this about FWD traffic? (The ack will go dest->root).
389 */
390void
391GCC_allow (struct CadetConnection *c, unsigned int buffer, int fwd);
392 232
393/** 233/**
394 * Send FWD keepalive packets for a connection. 234 * Obtain performance @a metrics from @a cc.
395 * 235 *
396 * @param cls Closure (connection for which to send the keepalive). 236 * @param cc connection to query
397 * @param tc Notification context. 237 * @return the metrics
398 */ 238 */
399void 239const struct CadetConnectionMetrics *
400GCC_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); 240GCC_get_metrics (struct CadetConnection *cc);
241
401 242
402/** 243/**
403 * Send BCK keepalive packets for a connection. 244 * Handle encrypted message.
404 * 245 *
405 * @param cls Closure (connection for which to send the keepalive). 246 * @param cc connection that received encrypted message
406 * @param tc Notification context. 247 * @param msg the encrypted message to decrypt
407 */ 248 */
408void 249void
409GCC_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); 250GCC_handle_encrypted (struct CadetConnection *cc,
251 const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
410 252
411 253
412/** 254/**
413 * Notify other peers on a connection of a broken link. Mark connections 255 * We sent a message for which we expect to receive an ACK via
414 * to destroy after all traffic has been sent. 256 * the connection identified by @a cti.
415 * 257 *
416 * @param c Connection on which there has been a disconnection. 258 * @param cid connection identifier where we expect an ACK
417 * @param peer Peer that disconnected.
418 */ 259 */
419void 260void
420GCC_neighbor_disconnected (struct CadetConnection *c, struct CadetPeer *peer); 261GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
421 262
422/**
423 * Is this peer the first one on the connection?
424 *
425 * @param c Connection.
426 * @param fwd Is this about fwd traffic?
427 *
428 * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal.
429 */
430int
431GCC_is_origin (struct CadetConnection *c, int fwd);
432 263
433/** 264/**
434 * Is this peer the last one on the connection? 265 * We observed an ACK for a message that was originally sent via
435 * 266 * the connection identified by @a cti.
436 * @param c Connection.
437 * @param fwd Is this about fwd traffic?
438 * Note that the ROOT is the terminal for BCK traffic!
439 * 267 *
440 * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin. 268 * @param cid connection identifier where we got an ACK for a message
269 * that was originally sent via this connection (the ACK
270 * may have gotten back to us via a different connection).
441 */ 271 */
442int 272void
443GCC_is_terminal (struct CadetConnection *c, int fwd); 273GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
444
445/**
446 * See if we are allowed to send by the next hop in the given direction.
447 *
448 * @param c Connection.
449 * @param fwd Is this about fwd traffic?
450 *
451 * @return #GNUNET_YES in case it's OK to send.
452 */
453int
454GCC_is_sendable (struct CadetConnection *c, int fwd);
455 274
456/**
457 * Check if this connection is a direct one (never trim a direct connection).
458 *
459 * @param c Connection.
460 *
461 * @return #GNUNET_YES in case it's a direct connection, #GNUNET_NO otherwise.
462 */
463int
464GCC_is_direct (struct CadetConnection *c);
465 275
466/** 276/**
467 * Cancel a previously sent message while it's in the queue. 277 * We observed some the given @a latency on the connection
278 * identified by @a cti. (The same connection was taken
279 * in both directions.)
468 * 280 *
469 * ONLY can be called before the continuation given to the send function 281 * @param cti connection identifier where we measured latency
470 * is called. Once the continuation is called, the message is no longer in the 282 * @param latency the observed latency
471 * queue.
472 *
473 * @param q Handle to the queue.
474 */ 283 */
475void 284void
476GCC_cancel (struct CadetConnectionQueue *q); 285GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
286 struct GNUNET_TIME_Relative latency);
477 287
478/**
479 * Sends an already built message on a connection, properly registering
480 * all used resources.
481 *
482 * @param message Message to send.
483 * @param payload_type Type of payload, in case the message is encrypted.
484 * 0 for restransmissions (when type is no longer known)
485 * UINT16_MAX when not applicable.
486 * @param payload_id ID of the payload (PID, ACK, ...).
487 * @param c Connection on which this message is transmitted.
488 * @param fwd Is this a fwd message?
489 * @param force Force the connection to accept the message (buffer overfill).
490 * @param cont Continuation called once message is sent. Can be NULL.
491 * @param cont_cls Closure for @c cont.
492 *
493 * @return Handle to cancel the message before it's sent.
494 * NULL on error.
495 * Invalid on @c cont call.
496 */
497struct CadetConnectionQueue *
498GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
499 uint16_t payload_type,
500 struct CadetEncryptedMessageIdentifier payload_id,
501 struct CadetConnection *c, int fwd, int force,
502 GCC_sent cont, void *cont_cls);
503 288
504/** 289/**
505 * Sends a CREATE CONNECTION message for a path to a peer. 290 * Return the tunnel associated with this connection.
506 * Changes the connection and tunnel states if necessary.
507 * 291 *
508 * @param connection Connection to create. 292 * @param cc connection to query
293 * @return corresponding entry in the tunnel's connection list
509 */ 294 */
510void 295struct CadetTConnection *
511GCC_send_create (struct CadetConnection *connection); 296GCC_get_ct (struct CadetConnection *cc);
512 297
513/**
514 * Send a message to all peers in this connection that the connection
515 * is no longer valid.
516 *
517 * If some peer should not receive the message, it should be zero'ed out
518 * before calling this function.
519 *
520 * @param c The connection whose peers to notify.
521 */
522void
523GCC_send_destroy (struct CadetConnection *c);
524 298
525/** 299/**
526 * @brief Start a polling timer for the connection. 300 * Obtain the path used by this connection.
527 * 301 *
528 * When a neighbor does not accept more traffic on the connection it could be 302 * @param cc connection
529 * caused by a simple congestion or by a lost ACK. Polling enables to check 303 * @return path to @a cc
530 * for the lastest ACK status for a connection.
531 *
532 * @param c Connection.
533 * @param fwd Should we poll in the FWD direction?
534 */ 304 */
535void 305struct CadetPeerPath *
536GCC_start_poll (struct CadetConnection *c, int fwd); 306GCC_get_path (struct CadetConnection *cc);
537 307
538 308
539/** 309/**
540 * @brief Stop polling a connection for ACKs. 310 * Obtain unique ID for the connection.
541 *
542 * Once we have enough ACKs for future traffic, polls are no longer necessary.
543 * 311 *
544 * @param c Connection. 312 * @param cc connection.
545 * @param fwd Should we stop the poll in the FWD direction? 313 * @return unique number of the connection
546 */ 314 */
547void 315const struct GNUNET_CADET_ConnectionTunnelIdentifier *
548GCC_stop_poll (struct CadetConnection *c, int fwd); 316GCC_get_id (struct CadetConnection *cc);
317
549 318
550/** 319/**
551 * Get a (static) string for a connection. 320 * Get a (static) string for a connection.
552 * 321 *
553 * @param c Connection. 322 * @param cc Connection.
554 */ 323 */
555const char * 324const char *
556GCC_2s (const struct CadetConnection *c); 325GCC_2s (const struct CadetConnection *cc);
326
557 327
558/** 328/**
559 * Log all possible info about the connection state. 329 * Log connection info.
560 * 330 *
561 * @param c Connection to debug. 331 * @param cc connection
562 * @param level Debug level to use. 332 * @param level Debug level to use.
563 */ 333 */
564void 334void
565GCC_debug (const struct CadetConnection *c, enum GNUNET_ErrorType level); 335GCC_debug (struct CadetConnection *cc,
336 enum GNUNET_ErrorType level);
566 337
567#if 0 /* keep Emacsens' auto-indent happy */
568{
569#endif
570#ifdef __cplusplus
571}
572#endif
573 338
574/* ifndef GNUNET_SERVICE_CADET_CONNECTION_H */
575#endif 339#endif
576/* end of gnunet-service-cadet_connection.h */
diff --git a/src/cadet/gnunet-service-cadet-new_core.c b/src/cadet/gnunet-service-cadet_core.c
index 3768c36a5..ae03b4f35 100644
--- a/src/cadet/gnunet-service-cadet-new_core.c
+++ b/src/cadet/gnunet-service-cadet_core.c
@@ -30,11 +30,11 @@
30 * - Optimization: given BROKEN messages, destroy paths (?) 30 * - Optimization: given BROKEN messages, destroy paths (?)
31 */ 31 */
32#include "platform.h" 32#include "platform.h"
33#include "gnunet-service-cadet-new_core.h" 33#include "gnunet-service-cadet_core.h"
34#include "gnunet-service-cadet-new_paths.h" 34#include "gnunet-service-cadet_paths.h"
35#include "gnunet-service-cadet-new_peer.h" 35#include "gnunet-service-cadet_peer.h"
36#include "gnunet-service-cadet-new_connection.h" 36#include "gnunet-service-cadet_connection.h"
37#include "gnunet-service-cadet-new_tunnels.h" 37#include "gnunet-service-cadet_tunnels.h"
38#include "gnunet_core_service.h" 38#include "gnunet_core_service.h"
39#include "gnunet_statistics_service.h" 39#include "gnunet_statistics_service.h"
40#include "cadet_protocol.h" 40#include "cadet_protocol.h"
diff --git a/src/cadet/gnunet-service-cadet-new_core.h b/src/cadet/gnunet-service-cadet_core.h
index 65b0a6ba5..65b0a6ba5 100644
--- a/src/cadet/gnunet-service-cadet-new_core.h
+++ b/src/cadet/gnunet-service-cadet_core.h
diff --git a/src/cadet/gnunet-service-cadet_dht.c b/src/cadet/gnunet-service-cadet_dht.c
index 22673b167..f00c0caf3 100644
--- a/src/cadet/gnunet-service-cadet_dht.c
+++ b/src/cadet/gnunet-service-cadet_dht.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2013 GNUnet e.V. 3 Copyright (C) 2013, 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -17,25 +17,41 @@
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA. 18 Boston, MA 02110-1301, USA.
19*/ 19*/
20 20/**
21 * @file cadet/gnunet-service-cadet_dht.c
22 * @brief Information we track per peer.
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 */
21 26
22#include "platform.h" 27#include "platform.h"
23#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
24
25#include "gnunet_dht_service.h" 29#include "gnunet_dht_service.h"
26#include "gnunet_statistics_service.h" 30#include "gnunet_statistics_service.h"
27 31#include "gnunet-service-cadet.h"
28#include "cadet_path.h"
29#include "gnunet-service-cadet_dht.h" 32#include "gnunet-service-cadet_dht.h"
30#include "gnunet-service-cadet_peer.h"
31#include "gnunet-service-cadet_hello.h" 33#include "gnunet-service-cadet_hello.h"
34#include "gnunet-service-cadet_peer.h"
35#include "gnunet-service-cadet_paths.h"
32 36
33#define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__) 37/**
38 * How long do we wait before first announcing our presence to the DHT.
39 * Used to wait for our HELLO to be available. Note that we also get
40 * notifications when our HELLO is ready, so this is just the maximum
41 * we wait for the first notification.
42 */
43#define STARTUP_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500)
34 44
45/**
46 * How long do we wait after we get an updated HELLO before publishing?
47 * Allows for the HELLO to be updated again quickly, for example in
48 * case multiple addresses changed and we got a partial update.
49 */
50#define CHANGE_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100)
51
52
53#define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__)
35 54
36/******************************************************************************/
37/******************************** STRUCTS **********************************/
38/******************************************************************************/
39 55
40/** 56/**
41 * Handle for DHT searches. 57 * Handle for DHT searches.
@@ -47,42 +63,9 @@ struct GCD_search_handle
47 */ 63 */
48 struct GNUNET_DHT_GetHandle *dhtget; 64 struct GNUNET_DHT_GetHandle *dhtget;
49 65
50 /**
51 * Provided callback to call when a path is found.
52 */
53 GCD_search_callback callback;
54
55 /**
56 * Provided closure.
57 */
58 void *cls;
59
60 /**
61 * Peer ID searched for
62 */
63 GNUNET_PEER_Id peer_id;
64}; 66};
65 67
66 68
67/******************************************************************************/
68/******************************* GLOBALS ***********************************/
69/******************************************************************************/
70
71/**
72 * Global handle to the statistics service.
73 */
74extern struct GNUNET_STATISTICS_Handle *stats;
75
76/**
77 * Own ID (short value).
78 */
79extern GNUNET_PEER_Id myid;
80
81/**
82 * Own ID (full value).
83 */
84extern struct GNUNET_PeerIdentity my_full_id;
85
86/** 69/**
87 * Handle to use DHT. 70 * Handle to use DHT.
88 */ 71 */
@@ -94,69 +77,20 @@ static struct GNUNET_DHT_Handle *dht_handle;
94static struct GNUNET_TIME_Relative id_announce_time; 77static struct GNUNET_TIME_Relative id_announce_time;
95 78
96/** 79/**
97 * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put. 80 * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put().
98 */ 81 */
99static unsigned long long dht_replication_level; 82static unsigned long long dht_replication_level;
100 83
101/** 84/**
102 * Task to periodically announce itself in the network. 85 * Task to periodically announce itself in the network.
103 */ 86 */
104static struct GNUNET_SCHEDULER_Task * announce_id_task; 87static struct GNUNET_SCHEDULER_Task *announce_id_task;
105 88
106/** 89/**
107 * Delay for the next ID announce. 90 * Delay for the next ID announce.
108 */ 91 */
109static struct GNUNET_TIME_Relative announce_delay; 92static struct GNUNET_TIME_Relative announce_delay;
110 93
111/**
112 * GET requests to stop on shutdown.
113 */
114static struct GNUNET_CONTAINER_MultiHashMap32 *get_requests;
115
116/******************************************************************************/
117/******************************** STATIC ***********************************/
118/******************************************************************************/
119
120
121/**
122 * Build a PeerPath from the paths returned from the DHT, reversing the paths
123 * to obtain a local peer -> destination path and interning the peer ids.
124 *
125 * @return Newly allocated and created path
126 *
127 * FIXME refactor and use build_path_from_peer_ids
128 */
129static struct CadetPeerPath *
130path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
131 unsigned int get_path_length,
132 const struct GNUNET_PeerIdentity *put_path,
133 unsigned int put_path_length)
134{
135 size_t size = get_path_length + put_path_length + 1;
136 struct GNUNET_PeerIdentity peers[size];
137 const struct GNUNET_PeerIdentity *peer;
138 struct CadetPeerPath *p;
139 unsigned int own_pos;
140 int i;
141
142 peers[0] = my_full_id;
143 LOG (GNUNET_ERROR_TYPE_DEBUG, " GET has %d hops.\n", get_path_length);
144 for (i = 0 ; i < get_path_length; i++)
145 {
146 peer = &get_path[get_path_length - i - 1];
147 LOG (GNUNET_ERROR_TYPE_DEBUG, " From GET: %s\n", GNUNET_i2s (peer));
148 peers[i + 1] = *peer;
149 }
150 for (i = 0 ; i < put_path_length; i++)
151 {
152 peer = &put_path[put_path_length - i - 1];
153 LOG (GNUNET_ERROR_TYPE_DEBUG, " From PUT: %s\n", GNUNET_i2s (peer));
154 peers[i + get_path_length + 1] = *peer;
155 }
156 p = path_build_from_peer_ids (peers, size, myid, &own_pos);
157 return p;
158}
159
160 94
161/** 95/**
162 * Function to process paths received for a new peer addition. The recorded 96 * Function to process paths received for a new peer addition. The recorded
@@ -176,42 +110,34 @@ path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
176 */ 110 */
177static void 111static void
178dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, 112dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
179 const struct GNUNET_HashCode * key, 113 const struct GNUNET_HashCode *key,
180 const struct GNUNET_PeerIdentity *get_path, 114 const struct GNUNET_PeerIdentity *get_path,
181 unsigned int get_path_length, 115 unsigned int get_path_length,
182 const struct GNUNET_PeerIdentity *put_path, 116 const struct GNUNET_PeerIdentity *put_path,
183 unsigned int put_path_length, enum GNUNET_BLOCK_Type type, 117 unsigned int put_path_length,
184 size_t size, const void *data) 118 enum GNUNET_BLOCK_Type type,
119 size_t size,
120 const void *data)
185{ 121{
186 struct GCD_search_handle *h = cls; 122 const struct GNUNET_HELLO_Message *hello = data;
187 struct GNUNET_HELLO_Message *hello;
188 struct CadetPeerPath *p;
189 struct CadetPeer *peer; 123 struct CadetPeer *peer;
190 char *s;
191 124
192 p = path_build_from_dht (get_path, get_path_length, 125 GCPP_try_path_from_dht (get_path,
193 put_path, put_path_length); 126 get_path_length,
194 if (NULL == p) 127 put_path,
128 put_path_length);
129 if ( (size >= sizeof (struct GNUNET_HELLO_Message)) &&
130 (ntohs (hello->header.size) == size) &&
131 (size == GNUNET_HELLO_size (hello)) )
195 { 132 {
196 GNUNET_break_op (0); 133 peer = GCP_get (&put_path[0],
197 return; 134 GNUNET_YES);
135 LOG (GNUNET_ERROR_TYPE_DEBUG,
136 "Got HELLO for %s\n",
137 GCP_2s (peer));
138 GCP_set_hello (peer,
139 hello);
198 } 140 }
199
200 s = path_2s (p);
201 LOG (GNUNET_ERROR_TYPE_INFO,
202 "Got path from DHT: %s\n",
203 s);
204 GNUNET_free_non_null (s);
205
206 peer = GCP_get_short (p->peers[p->length - 1], GNUNET_YES);
207 LOG (GNUNET_ERROR_TYPE_DEBUG,
208 "Got HELLO for %s\n",
209 GCP_2s (peer));
210 h->callback (h->cls, p);
211 path_destroy (p);
212 hello = (struct GNUNET_HELLO_Message *) data;
213 GCP_set_hello (peer, hello);
214 GCP_try_connect (peer);
215} 141}
216 142
217 143
@@ -229,19 +155,10 @@ announce_id (void *cls)
229 struct GNUNET_TIME_Absolute expiration; 155 struct GNUNET_TIME_Absolute expiration;
230 struct GNUNET_TIME_Relative next_put; 156 struct GNUNET_TIME_Relative next_put;
231 157
232 announce_id_task = NULL;
233 LOG (GNUNET_ERROR_TYPE_DEBUG, "Announce ID\n");
234 hello = GCH_get_mine (); 158 hello = GCH_get_mine ();
235 size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0; 159 size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0;
236 if ( (NULL == hello) || (0 == size) ) 160 if (0 == size)
237 { 161 {
238 /* Peerinfo gave us no hello yet, try again soon. */
239 LOG (GNUNET_ERROR_TYPE_INFO,
240 " no hello, waiting!\n");
241 GNUNET_STATISTICS_update (stats,
242 "# DHT announce skipped (no hello)",
243 1,
244 GNUNET_NO);
245 expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), 162 expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
246 announce_delay); 163 announce_delay);
247 announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay); 164 announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
@@ -252,71 +169,64 @@ announce_id (void *cls)
252 announce_delay = GNUNET_TIME_UNIT_SECONDS; 169 announce_delay = GNUNET_TIME_UNIT_SECONDS;
253 } 170 }
254 171
255 LOG (GNUNET_ERROR_TYPE_DEBUG,
256 "Hello %p size: %u\n",
257 hello,
258 size);
259 if (NULL != hello)
260 {
261 GNUNET_STATISTICS_update (stats,
262 "# DHT announce",
263 1, GNUNET_NO);
264 memset (&phash,
265 0,
266 sizeof (phash));
267 GNUNET_memcpy (&phash,
268 &my_full_id,
269 sizeof (my_full_id));
270 GNUNET_DHT_put (dht_handle, /* DHT handle */
271 &phash, /* Key to use */
272 dht_replication_level, /* Replication level */
273 GNUNET_DHT_RO_RECORD_ROUTE
274 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
275 GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */
276 size, /* Size of the data */
277 (const char *) hello, /* Data itself */
278 expiration, /* Data expiration */
279 NULL, /* Continuation */
280 NULL); /* Continuation closure */
281 }
282 /* Call again in id_announce_time, unless HELLO expires first, 172 /* Call again in id_announce_time, unless HELLO expires first,
283 * but wait at least 1s. */ 173 * but wait at least 1s. */
284 next_put = GNUNET_TIME_absolute_get_remaining (expiration); 174 next_put
285 next_put = GNUNET_TIME_relative_min (next_put, 175 = GNUNET_TIME_absolute_get_remaining (expiration);
286 id_announce_time); 176 next_put
287 next_put = GNUNET_TIME_relative_max (next_put, 177 = GNUNET_TIME_relative_min (next_put,
288 GNUNET_TIME_UNIT_SECONDS); 178 id_announce_time);
289 announce_id_task = GNUNET_SCHEDULER_add_delayed (next_put, 179 next_put
290 &announce_id, 180 = GNUNET_TIME_relative_max (next_put,
291 cls); 181 GNUNET_TIME_UNIT_SECONDS);
182 announce_id_task
183 = GNUNET_SCHEDULER_add_delayed (next_put,
184 &announce_id,
185 cls);
186 GNUNET_STATISTICS_update (stats,
187 "# DHT announce",
188 1,
189 GNUNET_NO);
190 memset (&phash,
191 0,
192 sizeof (phash));
193 GNUNET_memcpy (&phash,
194 &my_full_id,
195 sizeof (my_full_id));
196 LOG (GNUNET_ERROR_TYPE_DEBUG,
197 "Announcing my HELLO (%u bytes) in the DHT\n",
198 size);
199 GNUNET_DHT_put (dht_handle, /* DHT handle */
200 &phash, /* Key to use */
201 dht_replication_level, /* Replication level */
202 GNUNET_DHT_RO_RECORD_ROUTE
203 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
204 GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */
205 size, /* Size of the data */
206 (const char *) hello, /* Data itself */
207 expiration, /* Data expiration */
208 NULL, /* Continuation */
209 NULL); /* Continuation closure */
292} 210}
293 211
212
294/** 213/**
295 * Iterator over hash map entries and stop GET requests before disconnecting 214 * Function called by the HELLO subsystem whenever OUR hello
296 * from the DHT. 215 * changes. Re-triggers the DHT PUT immediately.
297 *
298 * @param cls Closure (unused)
299 * @param key Current peer ID.
300 * @param value Value in the hash map (GCD_search_handle).
301 *
302 * @return #GNUNET_YES, we should continue to iterate,
303 */ 216 */
304int 217void
305stop_get (void *cls, 218GCD_hello_update ()
306 uint32_t key,
307 void *value)
308{ 219{
309 struct GCD_search_handle *h = value; 220 if (NULL == announce_id_task)
310 221 return; /* too early */
311 GCD_search_stop (h); 222 GNUNET_SCHEDULER_cancel (announce_id_task);
312 return GNUNET_YES; 223 announce_id_task
224 = GNUNET_SCHEDULER_add_delayed (CHANGE_DELAY,
225 &announce_id,
226 NULL);
313} 227}
314 228
315 229
316/******************************************************************************/
317/******************************** API ***********************************/
318/******************************************************************************/
319
320/** 230/**
321 * Initialize the DHT subsystem. 231 * Initialize the DHT subsystem.
322 * 232 *
@@ -325,36 +235,40 @@ stop_get (void *cls,
325void 235void
326GCD_init (const struct GNUNET_CONFIGURATION_Handle *c) 236GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
327{ 237{
328 LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
329 if (GNUNET_OK != 238 if (GNUNET_OK !=
330 GNUNET_CONFIGURATION_get_value_number (c, "CADET", 239 GNUNET_CONFIGURATION_get_value_number (c,
240 "CADET",
331 "DHT_REPLICATION_LEVEL", 241 "DHT_REPLICATION_LEVEL",
332 &dht_replication_level)) 242 &dht_replication_level))
333 { 243 {
334 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, "CADET", 244 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
335 "DHT_REPLICATION_LEVEL", "USING DEFAULT"); 245 "CADET",
246 "DHT_REPLICATION_LEVEL",
247 "USING DEFAULT");
336 dht_replication_level = 3; 248 dht_replication_level = 3;
337 } 249 }
338 250
339 if (GNUNET_OK != 251 if (GNUNET_OK !=
340 GNUNET_CONFIGURATION_get_value_time (c, "CADET", "ID_ANNOUNCE_TIME", 252 GNUNET_CONFIGURATION_get_value_time (c,
253 "CADET",
254 "ID_ANNOUNCE_TIME",
341 &id_announce_time)) 255 &id_announce_time))
342 { 256 {
343 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "CADET", 257 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
344 "ID_ANNOUNCE_TIME", "MISSING"); 258 "CADET",
259 "ID_ANNOUNCE_TIME",
260 "MISSING");
345 GNUNET_SCHEDULER_shutdown (); 261 GNUNET_SCHEDULER_shutdown ();
346 return; 262 return;
347 } 263 }
348 264
349 dht_handle = GNUNET_DHT_connect (c, 64); 265 dht_handle = GNUNET_DHT_connect (c,
350 if (NULL == dht_handle) 266 64);
351 { 267 GNUNET_break (NULL != dht_handle);
352 GNUNET_break (0);
353 }
354
355 announce_delay = GNUNET_TIME_UNIT_SECONDS; 268 announce_delay = GNUNET_TIME_UNIT_SECONDS;
356 announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, NULL); 269 announce_id_task = GNUNET_SCHEDULER_add_delayed (STARTUP_DELAY,
357 get_requests = GNUNET_CONTAINER_multihashmap32_create (32); 270 &announce_id,
271 NULL);
358} 272}
359 273
360 274
@@ -364,10 +278,7 @@ GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
364void 278void
365GCD_shutdown (void) 279GCD_shutdown (void)
366{ 280{
367 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down DHT\n"); 281 if (NULL != dht_handle)
368 GNUNET_CONTAINER_multihashmap32_iterate (get_requests, &stop_get, NULL);
369 GNUNET_CONTAINER_multihashmap32_destroy (get_requests);
370 if (dht_handle != NULL)
371 { 282 {
372 GNUNET_DHT_disconnect (dht_handle); 283 GNUNET_DHT_disconnect (dht_handle);
373 dht_handle = NULL; 284 dht_handle = NULL;
@@ -379,22 +290,31 @@ GCD_shutdown (void)
379 } 290 }
380} 291}
381 292
293
294/**
295 * Search DHT for paths to @a peeR_id
296 *
297 * @param peer_id peer to search for
298 * @return handle to abort search
299 */
382struct GCD_search_handle * 300struct GCD_search_handle *
383GCD_search (const struct GNUNET_PeerIdentity *peer_id, 301GCD_search (const struct GNUNET_PeerIdentity *peer_id)
384 GCD_search_callback callback, void *cls)
385{ 302{
386 struct GNUNET_HashCode phash; 303 struct GNUNET_HashCode phash;
387 struct GCD_search_handle *h; 304 struct GCD_search_handle *h;
388 305
389 LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting DHT GET for peer %s\n", 306 GNUNET_STATISTICS_update (stats,
390 GNUNET_i2s (peer_id)); 307 "# DHT search",
391 GNUNET_STATISTICS_update (stats, "# DHT search", 1, GNUNET_NO); 308 1,
392 memset (&phash, 0, sizeof (phash)); 309 GNUNET_NO);
393 GNUNET_memcpy (&phash, peer_id, sizeof (*peer_id)); 310 memset (&phash,
311 0,
312 sizeof (phash));
313 GNUNET_memcpy (&phash,
314 peer_id,
315 sizeof (*peer_id));
316
394 h = GNUNET_new (struct GCD_search_handle); 317 h = GNUNET_new (struct GCD_search_handle);
395 h->peer_id = GNUNET_PEER_intern (peer_id);
396 h->callback = callback;
397 h->cls = cls;
398 h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */ 318 h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */
399 GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */ 319 GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */
400 &phash, /* key to search */ 320 &phash, /* key to search */
@@ -405,20 +325,27 @@ GCD_search (const struct GNUNET_PeerIdentity *peer_id,
405 0, /* xquery bits */ 325 0, /* xquery bits */
406 &dht_get_id_handler, 326 &dht_get_id_handler,
407 h); 327 h);
408 GNUNET_CONTAINER_multihashmap32_put (get_requests, 328 LOG (GNUNET_ERROR_TYPE_DEBUG,
409 h->peer_id, 329 "Starting DHT GET for peer %s (%p)\n",
410 h, 330 GNUNET_i2s (peer_id),
411 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 331 h);
412 return h; 332 return h;
413} 333}
414 334
415 335
336/**
337 * Stop DHT search started with #GCD_search().
338 *
339 * @param h handle to search to stop
340 */
416void 341void
417GCD_search_stop (struct GCD_search_handle *h) 342GCD_search_stop (struct GCD_search_handle *h)
418{ 343{
419 GNUNET_break (GNUNET_OK == 344 LOG (GNUNET_ERROR_TYPE_DEBUG,
420 GNUNET_CONTAINER_multihashmap32_remove (get_requests, 345 "Stopping DHT GET %p\n",
421 h->peer_id, h)); 346 h);
422 GNUNET_DHT_get_stop (h->dhtget); 347 GNUNET_DHT_get_stop (h->dhtget);
423 GNUNET_free (h); 348 GNUNET_free (h);
424} 349}
350
351/* end of gnunet-service-cadet_dht.c */
diff --git a/src/cadet/gnunet-service-cadet_dht.h b/src/cadet/gnunet-service-cadet_dht.h
index b70dfe975..5d7ab29a0 100644
--- a/src/cadet/gnunet-service-cadet_dht.h
+++ b/src/cadet/gnunet-service-cadet_dht.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2013 GNUnet e.V. 3 Copyright (C) 2013, 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -22,10 +22,10 @@
22 * @file cadet/gnunet-service-cadet_dht.h 22 * @file cadet/gnunet-service-cadet_dht.h
23 * @brief cadet service; dealing with DHT requests and results 23 * @brief cadet service; dealing with DHT requests and results
24 * @author Bartlomiej Polot 24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
25 * 26 *
26 * All functions in this file should use the prefix GMD (Gnunet Cadet Dht) 27 * All functions in this file should use the prefix GCD (Gnunet Cadet Dht)
27 */ 28 */
28
29#ifndef GNUNET_SERVICE_CADET_DHT_H 29#ifndef GNUNET_SERVICE_CADET_DHT_H
30#define GNUNET_SERVICE_CADET_DHT_H 30#define GNUNET_SERVICE_CADET_DHT_H
31 31
@@ -40,23 +40,11 @@ extern "C"
40#include "platform.h" 40#include "platform.h"
41#include "gnunet_util_lib.h" 41#include "gnunet_util_lib.h"
42 42
43struct GCD_search_handle;
44
45
46/** 43/**
47 * Callback called on each path found over the DHT. 44 * Handle for DHT search operation.
48 *
49 * @param cls Closure.
50 * @param path An unchecked, unoptimized path to the target node.
51 * After callback will no longer be valid!
52 */ 45 */
53typedef void 46struct GCD_search_handle;
54(*GCD_search_callback) (void *cls,
55 const struct CadetPeerPath *path);
56 47
57/******************************************************************************/
58/******************************** API ***********************************/
59/******************************************************************************/
60 48
61/** 49/**
62 * Initialize the DHT subsystem. 50 * Initialize the DHT subsystem.
@@ -66,6 +54,7 @@ typedef void
66void 54void
67GCD_init (const struct GNUNET_CONFIGURATION_Handle *c); 55GCD_init (const struct GNUNET_CONFIGURATION_Handle *c);
68 56
57
69/** 58/**
70 * Shut down the DHT subsystem. 59 * Shut down the DHT subsystem.
71 */ 60 */
@@ -73,14 +62,32 @@ void
73GCD_shutdown (void); 62GCD_shutdown (void);
74 63
75 64
65/**
66 * Function called by the HELLO subsystem whenever OUR hello
67 * changes. Re-triggers the DHT PUT immediately.
68 */
69void
70GCD_hello_update (void);
71
72/**
73 * Search DHT for paths to @a peeR_id
74 *
75 * @param peer_id peer to search for
76 * @return handle to abort search
77 */
76struct GCD_search_handle * 78struct GCD_search_handle *
77GCD_search (const struct GNUNET_PeerIdentity *peer_id, 79GCD_search (const struct GNUNET_PeerIdentity *peer_id);
78 GCD_search_callback callback, void *cls);
79 80
80 81
82/**
83 * Stop DHT search started with #GCD_search().
84 *
85 * @param h handle to search to stop
86 */
81void 87void
82GCD_search_stop (struct GCD_search_handle *h); 88GCD_search_stop (struct GCD_search_handle *h);
83 89
90
84#if 0 /* keep Emacsens' auto-indent happy */ 91#if 0 /* keep Emacsens' auto-indent happy */
85{ 92{
86#endif 93#endif
@@ -88,6 +95,6 @@ GCD_search_stop (struct GCD_search_handle *h);
88} 95}
89#endif 96#endif
90 97
91/* ifndef GNUNET_CADET_SERVICE_LOCAL_H */ 98/* ifndef GNUNET_CADET_SERVICE_DHT_H */
92#endif 99#endif
93/* end of gnunet-cadet-service_LOCAL.h */ 100/* end of gnunet-service-cadet_dht.h */
diff --git a/src/cadet/gnunet-service-cadet_hello.c b/src/cadet/gnunet-service-cadet_hello.c
index 3c63f3551..6d85de39f 100644
--- a/src/cadet/gnunet-service-cadet_hello.c
+++ b/src/cadet/gnunet-service-cadet_hello.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2014 GNUnet e.V. 3 Copyright (C) 2014, 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -17,58 +17,33 @@
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA. 18 Boston, MA 02110-1301, USA.
19*/ 19*/
20 20/**
21 * @file cadet/gnunet-service-cadet_hello.c
22 * @brief spread knowledge about how to contact other peers from PEERINFO
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - is most of this necessary/helpful?
28 * - should we not simply restrict this to OUR hello?
29 */
21#include "platform.h" 30#include "platform.h"
22#include "gnunet_util_lib.h" 31#include "gnunet_util_lib.h"
23 32
24#include "gnunet_statistics_service.h" 33#include "gnunet_statistics_service.h"
25#include "gnunet_peerinfo_service.h" 34#include "gnunet_peerinfo_service.h"
26
27#include "cadet_protocol.h" 35#include "cadet_protocol.h"
28#include "cadet_path.h" 36#include "gnunet-service-cadet.h"
29 37#include "gnunet-service-cadet_dht.h"
30#include "gnunet-service-cadet_hello.h" 38#include "gnunet-service-cadet_hello.h"
31#include "gnunet-service-cadet_peer.h" 39#include "gnunet-service-cadet_peer.h"
32 40
33#define LOG(level, ...) GNUNET_log_from(level,"cadet-hll",__VA_ARGS__) 41#define LOG(level, ...) GNUNET_log_from(level,"cadet-hll",__VA_ARGS__)
34 42
35
36/******************************************************************************/
37/******************************** STRUCTS **********************************/
38/******************************************************************************/
39
40
41
42/******************************************************************************/
43/******************************* GLOBALS ***********************************/
44/******************************************************************************/
45
46/**
47 * Global handle to the statistics service.
48 */
49extern struct GNUNET_STATISTICS_Handle *stats;
50
51/**
52 * Local peer own ID (memory efficient handle).
53 */
54extern GNUNET_PEER_Id myid;
55
56/**
57 * Local peer own ID (full value).
58 */
59extern struct GNUNET_PeerIdentity my_full_id;
60
61
62/**
63 * Don't try to recover tunnels if shutting down.
64 */
65extern int shutting_down;
66
67
68/** 43/**
69 * Hello message of local peer. 44 * Hello message of local peer.
70 */ 45 */
71const struct GNUNET_HELLO_Message *mine; 46static struct GNUNET_HELLO_Message *mine;
72 47
73/** 48/**
74 * Handle to peerinfo service. 49 * Handle to peerinfo service.
@@ -78,13 +53,9 @@ static struct GNUNET_PEERINFO_Handle *peerinfo;
78/** 53/**
79 * Iterator context. 54 * Iterator context.
80 */ 55 */
81struct GNUNET_PEERINFO_NotifyContext* nc; 56static struct GNUNET_PEERINFO_NotifyContext *nc;
82 57
83 58
84/******************************************************************************/
85/******************************** STATIC ***********************************/
86/******************************************************************************/
87
88/** 59/**
89 * Process each hello message received from peerinfo. 60 * Process each hello message received from peerinfo.
90 * 61 *
@@ -94,31 +65,37 @@ struct GNUNET_PEERINFO_NotifyContext* nc;
94 * @param err_msg Error message. 65 * @param err_msg Error message.
95 */ 66 */
96static void 67static void
97got_hello (void *cls, const struct GNUNET_PeerIdentity *id, 68got_hello (void *cls,
69 const struct GNUNET_PeerIdentity *id,
98 const struct GNUNET_HELLO_Message *hello, 70 const struct GNUNET_HELLO_Message *hello,
99 const char *err_msg) 71 const char *err_msg)
100{ 72{
101 struct CadetPeer *peer; 73 struct CadetPeer *peer;
102 74
103 if (NULL == id || NULL == hello) 75 if ( (NULL == id) ||
76 (NULL == hello) )
77 return;
78 if (0 == memcmp (id,
79 &my_full_id,
80 sizeof (struct GNUNET_PeerIdentity)))
104 { 81 {
105 LOG (GNUNET_ERROR_TYPE_DEBUG, " hello with id %p and msg %p\n", id, hello); 82 GNUNET_free_non_null (mine);
83 mine = (struct GNUNET_HELLO_Message *) GNUNET_copy_message (&hello->header);
84 GCD_hello_update ();
106 return; 85 return;
107 } 86 }
108 LOG (GNUNET_ERROR_TYPE_DEBUG, " hello for %s (%d bytes), expires on %s\n",
109 GNUNET_i2s (id), GNUNET_HELLO_size (hello),
110 GNUNET_STRINGS_absolute_time_to_string (GNUNET_HELLO_get_last_expiration(hello)));
111 peer = GCP_get (id, GNUNET_YES);
112 GCP_set_hello (peer, hello);
113
114 if (GCP_get_short_id (peer) == myid)
115 mine = GCP_get_hello (peer);
116}
117 87
88 LOG (GNUNET_ERROR_TYPE_DEBUG,
89 "Hello for %s (%d bytes), expires on %s\n",
90 GNUNET_i2s (id),
91 GNUNET_HELLO_size (hello),
92 GNUNET_STRINGS_absolute_time_to_string (GNUNET_HELLO_get_last_expiration (hello)));
93 peer = GCP_get (id,
94 GNUNET_YES);
95 GCP_set_hello (peer,
96 hello);
97}
118 98
119/******************************************************************************/
120/******************************** API ***********************************/
121/******************************************************************************/
122 99
123/** 100/**
124 * Initialize the hello subsystem. 101 * Initialize the hello subsystem.
@@ -128,10 +105,12 @@ got_hello (void *cls, const struct GNUNET_PeerIdentity *id,
128void 105void
129GCH_init (const struct GNUNET_CONFIGURATION_Handle *c) 106GCH_init (const struct GNUNET_CONFIGURATION_Handle *c)
130{ 107{
131 LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
132 GNUNET_assert (NULL == nc); 108 GNUNET_assert (NULL == nc);
133 peerinfo = GNUNET_PEERINFO_connect (c); 109 peerinfo = GNUNET_PEERINFO_connect (c);
134 nc = GNUNET_PEERINFO_notify (c, GNUNET_NO, &got_hello, NULL); 110 nc = GNUNET_PEERINFO_notify (c,
111 GNUNET_NO,
112 &got_hello,
113 NULL);
135} 114}
136 115
137 116
@@ -141,7 +120,6 @@ GCH_init (const struct GNUNET_CONFIGURATION_Handle *c)
141void 120void
142GCH_shutdown () 121GCH_shutdown ()
143{ 122{
144 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down channels\n");
145 if (NULL != nc) 123 if (NULL != nc)
146 { 124 {
147 GNUNET_PEERINFO_notify_cancel (nc); 125 GNUNET_PEERINFO_notify_cancel (nc);
@@ -152,6 +130,11 @@ GCH_shutdown ()
152 GNUNET_PEERINFO_disconnect (peerinfo); 130 GNUNET_PEERINFO_disconnect (peerinfo);
153 peerinfo = NULL; 131 peerinfo = NULL;
154 } 132 }
133 if (NULL != mine)
134 {
135 GNUNET_free (mine);
136 mine = NULL;
137 }
155} 138}
156 139
157 140
@@ -166,35 +149,4 @@ GCH_get_mine (void)
166 return mine; 149 return mine;
167} 150}
168 151
169 152/* end of gnunet-service-cadet-new_hello.c */
170/**
171 * Get another peer's hello message.
172 *
173 * @param id ID of the peer whose hello message is requested.
174 *
175 * @return Hello message, if any (NULL possible).
176 */
177const struct GNUNET_HELLO_Message *
178GCH_get (const struct GNUNET_PeerIdentity *id)
179{
180 struct CadetPeer *p;
181
182 p = GCP_get (id, GNUNET_NO);
183 if (NULL == p)
184 return NULL;
185 return GCP_get_hello (p);
186}
187
188
189/**
190 * Convert a hello message to a string.
191 *
192 * @param h Hello message.
193 */
194char *
195GCH_2s (const struct GNUNET_HELLO_Message *h)
196{
197 return "hello (TODO)";
198}
199
200
diff --git a/src/cadet/gnunet-service-cadet_hello.h b/src/cadet/gnunet-service-cadet_hello.h
index 34121e1e0..4291ae985 100644
--- a/src/cadet/gnunet-service-cadet_hello.h
+++ b/src/cadet/gnunet-service-cadet_hello.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2014 GNUnet e.V. 3 Copyright (C) 2014, 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -22,8 +22,9 @@
22 * @file cadet/gnunet-service-cadet_hello.h 22 * @file cadet/gnunet-service-cadet_hello.h
23 * @brief cadet service; dealing with hello messages 23 * @brief cadet service; dealing with hello messages
24 * @author Bartlomiej Polot 24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
25 * 26 *
26 * All functions in this file should use the prefix GMH (Gnunet Cadet Hello) 27 * All functions in this file should use the prefix GCH (Gnunet Cadet Hello)
27 */ 28 */
28 29
29#ifndef GNUNET_SERVICE_CADET_HELLO_H 30#ifndef GNUNET_SERVICE_CADET_HELLO_H
diff --git a/src/cadet/gnunet-service-cadet_local.c b/src/cadet/gnunet-service-cadet_local.c
deleted file mode 100644
index dea6681df..000000000
--- a/src/cadet/gnunet-service-cadet_local.c
+++ /dev/null
@@ -1,1553 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21
22#include "platform.h"
23#include "gnunet_util_lib.h"
24
25#include "gnunet_statistics_service.h"
26
27#include "cadet.h"
28#include "cadet_protocol.h" /* GNUNET_CADET_Data is shared */
29
30#include "gnunet-service-cadet_local.h"
31#include "gnunet-service-cadet_channel.h"
32
33/* INFO DEBUG */
34#include "gnunet-service-cadet_tunnel.h"
35#include "gnunet-service-cadet_peer.h"
36
37#define LOG(level, ...) GNUNET_log_from(level,"cadet-loc",__VA_ARGS__)
38
39/******************************************************************************/
40/******************************** STRUCTS **********************************/
41/******************************************************************************/
42
43/**
44 * Struct containing information about a client of the service
45 *
46 * TODO: add a list of 'waiting' ports
47 */
48struct CadetClient
49{
50 /**
51 * Linked list next
52 */
53 struct CadetClient *next;
54
55 /**
56 * Linked list prev
57 */
58 struct CadetClient *prev;
59
60 /**
61 * Tunnels that belong to this client, indexed by local id
62 */
63 struct GNUNET_CONTAINER_MultiHashMap32 *own_channels;
64
65 /**
66 * Tunnels this client has accepted, indexed by incoming local id
67 */
68 struct GNUNET_CONTAINER_MultiHashMap32 *incoming_channels;
69
70 /**
71 * Channel ID for the next incoming channel.
72 */
73 struct GNUNET_CADET_ClientChannelNumber next_ccn;
74
75 /**
76 * Handle to communicate with the client
77 */
78 struct GNUNET_SERVER_Client *handle;
79
80 /**
81 * Ports that this client has declared interest in.
82 * Indexed by port, contains *Client.
83 */
84 struct GNUNET_CONTAINER_MultiHashMap *ports;
85
86 /**
87 * Whether the client is active or shutting down (don't send confirmations
88 * to a client that is shutting down.
89 */
90 int shutting_down;
91
92 /**
93 * ID of the client, mainly for debug messages
94 */
95 unsigned int id;
96};
97
98/******************************************************************************/
99/******************************* GLOBALS ***********************************/
100/******************************************************************************/
101
102/**
103 * Global handle to the statistics service.
104 */
105extern struct GNUNET_STATISTICS_Handle *stats;
106
107/**
108 * Handle to server lib.
109 */
110static struct GNUNET_SERVER_Handle *server_handle;
111
112/**
113 * DLL with all the clients, head.
114 */
115static struct CadetClient *clients_head;
116
117/**
118 * DLL with all the clients, tail.
119 */
120static struct CadetClient *clients_tail;
121
122/**
123 * Next ID to assign to a client.
124 */
125unsigned int next_client_id;
126
127/**
128 * All ports clients of this peer have opened.
129 */
130static struct GNUNET_CONTAINER_MultiHashMap *ports;
131
132/**
133 * Notification context, to send messages to local clients.
134 */
135static struct GNUNET_SERVER_NotificationContext *nc;
136
137
138/******************************************************************************/
139/******************************** STATIC ***********************************/
140/******************************************************************************/
141
142/**
143 * Remove client's ports from the global hashmap on disconnect.
144 *
145 * @param cls Closure (unused).
146 * @param key Port.
147 * @param value Client structure.
148 *
149 * @return #GNUNET_OK, keep iterating.
150 */
151static int
152client_release_ports (void *cls,
153 const struct GNUNET_HashCode *key,
154 void *value)
155{
156 int res;
157
158 res = GNUNET_CONTAINER_multihashmap_remove (ports, key, value);
159 if (GNUNET_YES != res)
160 {
161 GNUNET_break (0);
162 LOG (GNUNET_ERROR_TYPE_WARNING,
163 "Port %s by client %p was not registered.\n",
164 GNUNET_h2s (key), value);
165 }
166 return GNUNET_OK;
167}
168
169
170/**
171 * Iterator for deleting each channel whose client endpoint disconnected.
172 *
173 * @param cls Closure (client that has disconnected).
174 * @param key The local channel id (used to access the hashmap).
175 * @param value The value stored at the key (channel to destroy).
176 *
177 * @return #GNUNET_OK, keep iterating.
178 */
179static int
180channel_destroy_iterator (void *cls,
181 uint32_t key,
182 void *value)
183{
184 struct CadetChannel *ch = value;
185 struct CadetClient *c = cls;
186
187 LOG (GNUNET_ERROR_TYPE_DEBUG,
188 " Channel %s destroy, due to client %s shutdown.\n",
189 GCCH_2s (ch), GML_2s (c));
190
191 GCCH_handle_local_destroy (ch,
192 c,
193 key < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
194 return GNUNET_OK;
195}
196
197
198/**
199 * Unregister data and free memory for a client.
200 *
201 * @param c Client to destroy. No longer valid after call.
202 */
203static void
204client_destroy (struct CadetClient *c)
205{
206 LOG (GNUNET_ERROR_TYPE_DEBUG, " client destroy: %p/%u\n", c, c->id);
207 GNUNET_SERVER_client_drop (c->handle);
208 c->shutting_down = GNUNET_YES;
209
210 if (NULL != c->own_channels)
211 {
212 GNUNET_CONTAINER_multihashmap32_iterate (c->own_channels,
213 &channel_destroy_iterator, c);
214 GNUNET_CONTAINER_multihashmap32_destroy (c->own_channels);
215 }
216 if (NULL != c->incoming_channels)
217 {
218 GNUNET_CONTAINER_multihashmap32_iterate (c->incoming_channels,
219 &channel_destroy_iterator, c);
220 GNUNET_CONTAINER_multihashmap32_destroy (c->incoming_channels);
221 }
222 if (NULL != c->ports)
223 {
224 GNUNET_CONTAINER_multihashmap_iterate (c->ports,
225 &client_release_ports, c);
226 GNUNET_CONTAINER_multihashmap_destroy (c->ports);
227 }
228
229 GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
230 GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO);
231 GNUNET_SERVER_client_set_user_context (c->handle, NULL);
232 GNUNET_free (c);
233}
234
235
236/**
237 * Create a client record, register data and initialize memory.
238 *
239 * @param client Client's handle.
240 */
241static struct CadetClient *
242client_new (struct GNUNET_SERVER_Client *client)
243{
244 struct CadetClient *c;
245
246 GNUNET_SERVER_client_keep (client);
247 GNUNET_SERVER_notification_context_add (nc, client);
248
249 c = GNUNET_new (struct CadetClient);
250 c->handle = client;
251 c->id = next_client_id++; /* overflow not important: just for debug */
252
253 c->own_channels = GNUNET_CONTAINER_multihashmap32_create (32);
254 c->incoming_channels = GNUNET_CONTAINER_multihashmap32_create (32);
255
256 GNUNET_SERVER_client_set_user_context (client, c);
257 GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
258 GNUNET_STATISTICS_update (stats, "# clients", +1, GNUNET_NO);
259
260 LOG (GNUNET_ERROR_TYPE_DEBUG, " client created: %p/%u\n", c, c->id);
261
262 return c;
263}
264
265
266/******************************************************************************/
267/******************************** HANDLES ***********************************/
268/******************************************************************************/
269
270/**
271 * Handler for client connection.
272 *
273 * @param cls Closure (unused).
274 * @param client Client handler.
275 */
276static void
277handle_client_connect (void *cls, struct GNUNET_SERVER_Client *client)
278{
279 LOG (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client);
280 if (NULL == client)
281 return;
282
283 (void) client_new (client);
284}
285
286
287/**
288 * Handler for client disconnection
289 *
290 * @param cls closure
291 * @param client identification of the client; NULL
292 * for the last call when the server is destroyed
293 */
294static void
295handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
296{
297 struct CadetClient *c;
298
299 LOG (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected: %p\n", client);
300
301 c = GML_client_get (client);
302 if (NULL != c)
303 {
304 LOG (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u, %p)\n",
305 c->id, c);
306 client_destroy (c);
307 }
308 else
309 {
310 LOG (GNUNET_ERROR_TYPE_DEBUG, " disconnecting client's context NULL\n");
311 }
312 return;
313}
314
315
316/**
317 * Handler for port open requests.
318 *
319 * @param cls Closure.
320 * @param client Identification of the client.
321 * @param message The actual message.
322 */
323static void
324handle_port_open (void *cls, struct GNUNET_SERVER_Client *client,
325 const struct GNUNET_MessageHeader *message)
326{
327 struct CadetClient *c;
328 struct GNUNET_CADET_PortMessage *pmsg;
329
330 LOG (GNUNET_ERROR_TYPE_DEBUG, "open port requested\n");
331
332 /* Sanity check for client registration */
333 if (NULL == (c = GML_client_get (client)))
334 {
335 GNUNET_break (0);
336 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
337 return;
338 }
339 LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
340
341 /* Message size sanity check */
342 if (sizeof (struct GNUNET_CADET_PortMessage) != ntohs (message->size))
343 {
344 GNUNET_break (0);
345 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
346 return;
347 }
348
349 pmsg = (struct GNUNET_CADET_PortMessage *) message;
350 if (NULL == c->ports)
351 {
352 c->ports = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_NO);
353 }
354 /* store in client's hashmap */
355 if (GNUNET_OK !=
356 GNUNET_CONTAINER_multihashmap_put (c->ports, &pmsg->port, c,
357 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
358 {
359 GNUNET_break (0);
360 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
361 return;
362 }
363 /* store in global hashmap */
364 /* FIXME only allow one client to have the port open,
365 * have a backup hashmap with waiting clients */
366 GNUNET_CONTAINER_multihashmap_put (ports, &pmsg->port, c,
367 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
368
369 GNUNET_SERVER_receive_done (client, GNUNET_OK);
370}
371
372
373/**
374 * Handler for port close requests.
375 *
376 * @param cls Closure.
377 * @param client Identification of the client.
378 * @param message The actual message.
379 */
380static void
381handle_port_close (void *cls, struct GNUNET_SERVER_Client *client,
382 const struct GNUNET_MessageHeader *message)
383{
384 struct CadetClient *c;
385 struct GNUNET_CADET_PortMessage *pmsg;
386 int removed;
387
388 LOG (GNUNET_ERROR_TYPE_DEBUG, "close port requested\n");
389
390 /* Sanity check for client registration */
391 if (NULL == (c = GML_client_get (client)))
392 {
393 GNUNET_break (0);
394 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
395 return;
396 }
397 LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
398
399 /* Message size sanity check */
400 if (sizeof (struct GNUNET_CADET_PortMessage) != ntohs (message->size))
401 {
402 GNUNET_break (0);
403 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
404 return;
405 }
406
407 pmsg = (struct GNUNET_CADET_PortMessage *) message;
408 removed = GNUNET_CONTAINER_multihashmap_remove (c->ports, &pmsg->port, c);
409 GNUNET_break_op (GNUNET_YES == removed);
410 removed = GNUNET_CONTAINER_multihashmap_remove (ports, &pmsg->port, c);
411 GNUNET_break_op (GNUNET_YES == removed);
412
413 GNUNET_SERVER_receive_done (client, GNUNET_OK);
414}
415
416
417/**
418 * Handler for requests of new channels.
419 *
420 * @param cls Closure.
421 * @param client Identification of the client.
422 * @param message The actual message.
423 */
424static void
425handle_channel_create (void *cls, struct GNUNET_SERVER_Client *client,
426 const struct GNUNET_MessageHeader *message)
427{
428 struct CadetClient *c;
429
430 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
431 LOG (GNUNET_ERROR_TYPE_DEBUG, "new channel requested\n");
432
433 /* Sanity check for client registration */
434 if (NULL == (c = GML_client_get (client)))
435 {
436 GNUNET_break (0);
437 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
438 return;
439 }
440 LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
441
442 /* Message size sanity check */
443 if (sizeof (struct GNUNET_CADET_LocalChannelCreateMessage)
444 != ntohs (message->size))
445 {
446 GNUNET_break (0);
447 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
448 return;
449 }
450
451 if (GNUNET_OK !=
452 GCCH_handle_local_create (c,
453 (struct GNUNET_CADET_LocalChannelCreateMessage *)
454 message))
455 {
456 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
457 return;
458 }
459
460 GNUNET_SERVER_receive_done (client, GNUNET_OK);
461}
462
463
464/**
465 * Handler for requests of deleting tunnels
466 *
467 * @param cls closure
468 * @param client identification of the client
469 * @param message the actual message
470 */
471static void
472handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
473 const struct GNUNET_MessageHeader *message)
474{
475 const struct GNUNET_CADET_LocalChannelDestroyMessage *msg;
476 struct CadetClient *c;
477 struct CadetChannel *ch;
478 struct GNUNET_CADET_ClientChannelNumber ccn;
479
480 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a DESTROY CHANNEL from client!\n");
481
482 /* Sanity check for client registration */
483 if (NULL == (c = GML_client_get (client)))
484 {
485 GNUNET_break (0);
486 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
487 return;
488 }
489 LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
490
491 /* Message sanity check */
492 if (sizeof (struct GNUNET_CADET_LocalChannelDestroyMessage)
493 != ntohs (message->size))
494 {
495 GNUNET_break (0);
496 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
497 return;
498 }
499
500 msg = (const struct GNUNET_CADET_LocalChannelDestroyMessage *) message;
501
502 /* Retrieve tunnel */
503 ccn = msg->ccn;
504 ch = GML_channel_get (c, ccn);
505
506 LOG (GNUNET_ERROR_TYPE_INFO, "Client %u is destroying channel %X\n",
507 c->id, ccn);
508
509 if (NULL == ch)
510 {
511 LOG (GNUNET_ERROR_TYPE_WARNING, " channel %X not found\n", ccn);
512 GNUNET_STATISTICS_update (stats,
513 "# client destroy messages on unknown channel",
514 1, GNUNET_NO);
515 GNUNET_SERVER_receive_done (client, GNUNET_OK);
516 return;
517 }
518
519 GCCH_handle_local_destroy (ch,
520 c,
521 ntohl (ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
522
523 GNUNET_SERVER_receive_done (client, GNUNET_OK);
524}
525
526
527/**
528 * Handler for client traffic
529 *
530 * @param cls closure
531 * @param client identification of the client
532 * @param message the actual message
533 */
534static void
535handle_data (void *cls, struct GNUNET_SERVER_Client *client,
536 const struct GNUNET_MessageHeader *message)
537{
538 const struct GNUNET_MessageHeader *payload;
539 struct GNUNET_CADET_LocalData *msg;
540 struct CadetClient *c;
541 struct CadetChannel *ch;
542 struct GNUNET_CADET_ClientChannelNumber ccn;
543 size_t message_size;
544 size_t payload_size;
545 size_t payload_claimed_size;
546 int fwd;
547
548 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
549 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
550 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got data from a client\n");
551
552 /* Sanity check for client registration */
553 if (NULL == (c = GML_client_get (client)))
554 {
555 GNUNET_break (0);
556 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
557 return;
558 }
559
560 /* Sanity check for message size */
561 message_size = ntohs (message->size);
562 if (sizeof (struct GNUNET_CADET_LocalData)
563 + sizeof (struct GNUNET_MessageHeader) > message_size
564 || GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < message_size)
565 {
566 GNUNET_break (0);
567 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
568 return;
569 }
570
571 /* Sanity check for payload size */
572 payload_size = message_size - sizeof (struct GNUNET_CADET_LocalData);
573 msg = (struct GNUNET_CADET_LocalData *) message;
574 payload = (struct GNUNET_MessageHeader *) &msg[1];
575 payload_claimed_size = ntohs (payload->size);
576 if (sizeof (struct GNUNET_MessageHeader) > payload_claimed_size
577 || GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < payload_claimed_size
578 || payload_claimed_size > payload_size)
579 {
580 LOG (GNUNET_ERROR_TYPE_WARNING,
581 "client claims to send %u bytes in %u payload\n",
582 payload_claimed_size, payload_size);
583 GNUNET_break (0);
584 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
585 return;
586 }
587
588 ccn = msg->ccn;
589 LOG (GNUNET_ERROR_TYPE_DEBUG, " %u bytes (%u payload) by client %u\n",
590 payload_size, payload_claimed_size, c->id);
591
592 /* Channel exists? */
593 fwd = ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
594 ch = GML_channel_get (c, ccn);
595 if (NULL == ch)
596 {
597 GNUNET_STATISTICS_update (stats,
598 "# client data messages on unknown channel",
599 1, GNUNET_NO);
600 GNUNET_SERVER_receive_done (client, GNUNET_OK);
601 return;
602 }
603
604 if (GNUNET_OK != GCCH_handle_local_data (ch, c, fwd, payload, payload_size))
605 {
606 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
607 return;
608 }
609
610 LOG (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n");
611 GNUNET_SERVER_receive_done (client, GNUNET_OK);
612
613 return;
614}
615
616
617/**
618 * Handler for client's ACKs for payload traffic.
619 *
620 * @param cls Closure (unused).
621 * @param client Identification of the client.
622 * @param message The actual message.
623 */
624static void
625handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
626 const struct GNUNET_MessageHeader *message)
627{
628 struct GNUNET_CADET_LocalAck *msg;
629 struct CadetChannel *ch;
630 struct CadetClient *c;
631 struct GNUNET_CADET_ClientChannelNumber ccn;
632 int fwd;
633
634 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
635 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n");
636
637 /* Sanity check for client registration */
638 if (NULL == (c = GML_client_get (client)))
639 {
640 GNUNET_break (0);
641 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
642 return;
643 }
644 LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
645
646 msg = (struct GNUNET_CADET_LocalAck *) message;
647
648 /* Channel exists? */
649 ccn = msg->ccn;
650 LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n",
651 ntohl (ccn.channel_of_client));
652 ch = GML_channel_get (c, ccn);
653 LOG (GNUNET_ERROR_TYPE_DEBUG, " -- ch %p\n", ch);
654 if (NULL == ch)
655 {
656 LOG (GNUNET_ERROR_TYPE_DEBUG,
657 "Channel %X unknown.\n",
658 ntohl (ccn.channel_of_client));
659 LOG (GNUNET_ERROR_TYPE_DEBUG, " for client %u.\n", c->id);
660 GNUNET_STATISTICS_update (stats,
661 "# client ack messages on unknown channel",
662 1, GNUNET_NO);
663 GNUNET_SERVER_receive_done (client, GNUNET_OK);
664 return;
665 }
666
667 /* If client is root, the ACK is going FWD, therefore this is "BCK ACK". */
668 /* If client is dest, the ACK is going BCK, therefore this is "FWD ACK" */
669 fwd = ntohl (ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
670
671 GCCH_handle_local_ack (ch, fwd);
672 GNUNET_SERVER_receive_done (client, GNUNET_OK);
673}
674
675
676/**
677 * Iterator over all peers to send a monitoring client info about each peer.
678 *
679 * @param cls Closure ().
680 * @param peer Peer ID (tunnel remote peer).
681 * @param value Peer info.
682 *
683 * @return #GNUNET_YES, to keep iterating.
684 */
685static int
686get_all_peers_iterator (void *cls,
687 const struct GNUNET_PeerIdentity * peer,
688 void *value)
689{
690 struct GNUNET_SERVER_Client *client = cls;
691 struct CadetPeer *p = value;
692 struct GNUNET_CADET_LocalInfoPeer msg;
693
694 msg.header.size = htons (sizeof (msg));
695 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
696 msg.destination = *peer;
697 msg.paths = htons (GCP_count_paths (p));
698 msg.tunnel = htons (NULL != GCP_get_tunnel (p));
699
700 LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about peer %s\n",
701 GNUNET_i2s (peer));
702
703 GNUNET_SERVER_notification_context_unicast (nc, client,
704 &msg.header, GNUNET_NO);
705 return GNUNET_YES;
706}
707
708
709/**
710 * Iterator over all peers to dump info for each peer.
711 *
712 * @param cls Closure (unused).
713 * @param peer Peer ID (tunnel remote peer).
714 * @param value Peer info.
715 *
716 * @return #GNUNET_YES, to keep iterating.
717 */
718static int
719show_peer_iterator (void *cls,
720 const struct GNUNET_PeerIdentity * peer,
721 void *value)
722{
723 struct CadetPeer *p = value;
724 struct CadetTunnel *t;
725
726 t = GCP_get_tunnel (p);
727 if (NULL != t)
728 GCT_debug (t, GNUNET_ERROR_TYPE_ERROR);
729
730 LOG (GNUNET_ERROR_TYPE_ERROR, "\n");
731
732 return GNUNET_YES;
733}
734
735
736/**
737 * Iterator over all paths of a peer to build an InfoPeer message.
738 *
739 * Message contains blocks of peers, first not included.
740 *
741 * @param cls Closure (message to build).
742 * @param peer Peer this path is towards.
743 * @param path Path itself
744 * @return #GNUNET_YES if should keep iterating.
745 * #GNUNET_NO otherwise.
746 */
747static int
748path_info_iterator (void *cls,
749 struct CadetPeer *peer,
750 struct CadetPeerPath *path)
751{
752 struct GNUNET_CADET_LocalInfoPeer *resp = cls;
753 struct GNUNET_PeerIdentity *id;
754 uint16_t msg_size;
755 uint16_t path_size;
756 unsigned int i;
757
758 msg_size = ntohs (resp->header.size);
759 path_size = sizeof (struct GNUNET_PeerIdentity) * (path->length - 1);
760
761 LOG (GNUNET_ERROR_TYPE_DEBUG, "Info Path %u\n", path->length);
762 if (msg_size + path_size > UINT16_MAX)
763 {
764 LOG (GNUNET_ERROR_TYPE_WARNING, "path too long for info message\n");
765 return GNUNET_NO;
766 }
767
768 i = msg_size - sizeof (struct GNUNET_CADET_LocalInfoPeer);
769 i = i / sizeof (struct GNUNET_PeerIdentity);
770
771 /* Set id to the address of the first free peer slot. */
772 id = (struct GNUNET_PeerIdentity *) &resp[1];
773 id = &id[i];
774
775 /* Don't copy first peers.
776 * First peer is always the local one.
777 * Last peer is always the destination (leave as 0, EOL).
778 */
779 for (i = 0; i < path->length - 1; i++)
780 {
781 GNUNET_PEER_resolve (path->peers[i + 1], &id[i]);
782 LOG (GNUNET_ERROR_TYPE_DEBUG, " %s\n", GNUNET_i2s (&id[i]));
783 }
784
785 resp->header.size = htons (msg_size + path_size);
786
787 return GNUNET_YES;
788}
789
790
791/**
792 * Handler for client's INFO PEERS request.
793 *
794 * @param cls Closure (unused).
795 * @param client Identification of the client.
796 * @param message The actual message.
797 */
798static void
799handle_get_peers (void *cls, struct GNUNET_SERVER_Client *client,
800 const struct GNUNET_MessageHeader *message)
801{
802 struct CadetClient *c;
803 struct GNUNET_MessageHeader reply;
804
805 /* Sanity check for client registration */
806 if (NULL == (c = GML_client_get (client)))
807 {
808 GNUNET_break (0);
809 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
810 return;
811 }
812
813 LOG (GNUNET_ERROR_TYPE_DEBUG,
814 "Received get peers request from client %u (%p)\n",
815 c->id, client);
816
817 GCP_iterate_all (get_all_peers_iterator, client);
818 reply.size = htons (sizeof (reply));
819 reply.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
820 GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO);
821
822 LOG (GNUNET_ERROR_TYPE_DEBUG,
823 "Get peers request from client %u completed\n", c->id);
824 GNUNET_SERVER_receive_done (client, GNUNET_OK);
825}
826
827
828/**
829 * Handler for client's SHOW_PEER request.
830 *
831 * @param cls Closure (unused).
832 * @param client Identification of the client.
833 * @param message The actual message.
834 */
835void
836handle_show_peer (void *cls, struct GNUNET_SERVER_Client *client,
837 const struct GNUNET_MessageHeader *message)
838{
839 const struct GNUNET_CADET_LocalInfo *msg;
840 struct GNUNET_CADET_LocalInfoPeer *resp;
841 struct CadetPeer *p;
842 struct CadetClient *c;
843 unsigned char cbuf[64 * 1024];
844
845 /* Sanity check for client registration */
846 if (NULL == (c = GML_client_get (client)))
847 {
848 GNUNET_break (0);
849 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
850 return;
851 }
852
853 msg = (struct GNUNET_CADET_LocalInfo *) message;
854 resp = (struct GNUNET_CADET_LocalInfoPeer *) cbuf;
855 LOG (GNUNET_ERROR_TYPE_INFO,
856 "Received peer info request from client %u for peer %s\n",
857 c->id, GNUNET_i2s_full (&msg->peer));
858
859 resp->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER);
860 resp->header.size = htons (sizeof (struct GNUNET_CADET_LocalInfoPeer));
861 resp->destination = msg->peer;
862 p = GCP_get (&msg->peer, GNUNET_NO);
863 if (NULL == p)
864 {
865 /* We don't know the peer */
866
867 LOG (GNUNET_ERROR_TYPE_INFO, "Peer %s unknown\n",
868 GNUNET_i2s_full (&msg->peer));
869 resp->paths = htons (0);
870 resp->tunnel = htons (NULL != GCP_get_tunnel (p));
871
872 GNUNET_SERVER_notification_context_unicast (nc, client,
873 &resp->header,
874 GNUNET_NO);
875 GNUNET_SERVER_receive_done (client, GNUNET_OK);
876 return;
877 }
878
879 resp->paths = htons (GCP_count_paths (p));
880 resp->tunnel = htons (NULL != GCP_get_tunnel (p));
881 GCP_iterate_paths (p, &path_info_iterator, resp);
882
883 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
884 &resp->header, GNUNET_NO);
885
886 LOG (GNUNET_ERROR_TYPE_INFO, "Show peer from client %u completed.\n", c->id);
887 GNUNET_SERVER_receive_done (client, GNUNET_OK);
888}
889
890
891/**
892 * Iterator over all tunnels to send a monitoring client info about each tunnel.
893 *
894 * @param cls Closure ().
895 * @param peer Peer ID (tunnel remote peer).
896 * @param value Tunnel info.
897 *
898 * @return #GNUNET_YES, to keep iterating.
899 */
900static int
901get_all_tunnels_iterator (void *cls,
902 const struct GNUNET_PeerIdentity * peer,
903 void *value)
904{
905 struct GNUNET_SERVER_Client *client = cls;
906 struct CadetTunnel *t = value;
907 struct GNUNET_CADET_LocalInfoTunnel msg;
908
909 msg.header.size = htons (sizeof (msg));
910 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
911 msg.destination = *peer;
912 msg.channels = htonl (GCT_count_channels (t));
913 msg.connections = htonl (GCT_count_any_connections (t));
914 msg.cstate = htons ((uint16_t) GCT_get_cstate (t));
915 msg.estate = htons ((uint16_t) GCT_get_estate (t));
916
917 LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about tunnel ->%s\n",
918 GNUNET_i2s (peer));
919
920 GNUNET_SERVER_notification_context_unicast (nc, client,
921 &msg.header, GNUNET_NO);
922 return GNUNET_YES;
923}
924
925
926/**
927 * Handler for client's INFO TUNNELS request.
928 *
929 * @param cls Closure (unused).
930 * @param client Identification of the client.
931 * @param message The actual message.
932 */
933static void
934handle_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client,
935 const struct GNUNET_MessageHeader *message)
936{
937 struct CadetClient *c;
938 struct GNUNET_MessageHeader reply;
939
940 /* Sanity check for client registration */
941 if (NULL == (c = GML_client_get (client)))
942 {
943 GNUNET_break (0);
944 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
945 return;
946 }
947
948 LOG (GNUNET_ERROR_TYPE_DEBUG,
949 "Received get tunnels request from client %u (%p)\n",
950 c->id, client);
951
952 GCT_iterate_all (get_all_tunnels_iterator, client);
953 reply.size = htons (sizeof (reply));
954 reply.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
955 GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO);
956
957 LOG (GNUNET_ERROR_TYPE_DEBUG,
958 "Get tunnels request from client %u completed\n", c->id);
959 GNUNET_SERVER_receive_done (client, GNUNET_OK);
960}
961
962
963static void
964iter_connection (void *cls, struct CadetConnection *c)
965{
966 struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
967 struct GNUNET_CADET_ConnectionTunnelIdentifier *h;
968
969 h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
970 h[msg->connections] = *(GCC_get_id (c));
971 msg->connections++;
972}
973
974static void
975iter_channel (void *cls, struct CadetChannel *ch)
976{
977 struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
978 struct GNUNET_CADET_ConnectionTunnelIdentifier *h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
979 struct GNUNET_CADET_ChannelTunnelNumber *chn = (struct GNUNET_CADET_ChannelTunnelNumber *) &h[msg->connections];
980
981 chn[msg->channels] = GCCH_get_id (ch);
982 msg->channels++;
983}
984
985
986/**
987 * Handler for client's SHOW_TUNNEL request.
988 *
989 * @param cls Closure (unused).
990 * @param client Identification of the client.
991 * @param message The actual message.
992 */
993void
994handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
995 const struct GNUNET_MessageHeader *message)
996{
997 const struct GNUNET_CADET_LocalInfo *msg;
998 struct GNUNET_CADET_LocalInfoTunnel *resp;
999 struct CadetClient *c;
1000 struct CadetTunnel *t;
1001 unsigned int ch_n;
1002 unsigned int c_n;
1003 size_t size;
1004
1005 /* Sanity check for client registration */
1006 if (NULL == (c = GML_client_get (client)))
1007 {
1008 GNUNET_break (0);
1009 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1010 return;
1011 }
1012
1013 msg = (struct GNUNET_CADET_LocalInfo *) message;
1014 LOG (GNUNET_ERROR_TYPE_DEBUG,
1015 "Received tunnel info request from client %u for tunnel %s\n",
1016 c->id, GNUNET_i2s_full(&msg->peer));
1017
1018 t = GCP_get_tunnel (GCP_get (&msg->peer, GNUNET_NO));
1019 if (NULL == t)
1020 {
1021 /* We don't know the tunnel */
1022 struct GNUNET_CADET_LocalInfoTunnel warn;
1023
1024 LOG (GNUNET_ERROR_TYPE_INFO, "Tunnel %s unknown %u\n",
1025 GNUNET_i2s_full(&msg->peer), sizeof (warn));
1026 warn.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
1027 warn.header.size = htons (sizeof (warn));
1028 warn.destination = msg->peer;
1029 warn.channels = htonl (0);
1030 warn.connections = htonl (0);
1031 warn.cstate = htons (0);
1032 warn.estate = htons (0);
1033
1034 GNUNET_SERVER_notification_context_unicast (nc, client,
1035 &warn.header,
1036 GNUNET_NO);
1037 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1038 return;
1039 }
1040
1041 /* Initialize context */
1042 ch_n = GCT_count_channels (t);
1043 c_n = GCT_count_any_connections (t);
1044
1045 size = sizeof (struct GNUNET_CADET_LocalInfoTunnel);
1046 size += c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier);
1047 size += ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber);
1048
1049 resp = GNUNET_malloc (size);
1050 resp->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
1051 resp->header.size = htons (size);
1052 resp->destination = msg->peer;
1053 /* Do not interleave with iterators, iter_channel needs conn in HBO */
1054 GCT_iterate_connections (t, &iter_connection, resp);
1055 GCT_iterate_channels (t, &iter_channel, resp);
1056 resp->connections = htonl (resp->connections);
1057 resp->channels = htonl (resp->channels);
1058 /* Do not interleave end */
1059 resp->cstate = htons (GCT_get_cstate (t));
1060 resp->estate = htons (GCT_get_estate (t));
1061 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1062 &resp->header, GNUNET_NO);
1063 GNUNET_free (resp);
1064
1065 LOG (GNUNET_ERROR_TYPE_DEBUG,
1066 "Show tunnel request from client %u completed. %u conn, %u ch\n",
1067 c->id, c_n, ch_n);
1068 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1069}
1070
1071
1072/**
1073 * Handler for client's INFO_DUMP request.
1074 *
1075 * @param cls Closure (unused).
1076 * @param client Identification of the client.
1077 * @param message The actual message.
1078 */
1079void
1080handle_info_dump (void *cls, struct GNUNET_SERVER_Client *client,
1081 const struct GNUNET_MessageHeader *message)
1082{
1083 struct CadetClient *c;
1084
1085 /* Sanity check for client registration */
1086 if (NULL == (c = GML_client_get (client)))
1087 {
1088 GNUNET_break (0);
1089 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1090 return;
1091 }
1092
1093 LOG (GNUNET_ERROR_TYPE_INFO, "Received dump info request from client %u\n",
1094 c->id);
1095 LOG (GNUNET_ERROR_TYPE_ERROR,
1096 "*************************** DUMP START ***************************\n");
1097
1098 for (c = clients_head; NULL != c; c = c->next)
1099 {
1100 LOG (GNUNET_ERROR_TYPE_ERROR, "Client %u (%p), handle: %p\n",
1101 c->id, c, c->handle);
1102 if (NULL != c->ports)
1103 LOG (GNUNET_ERROR_TYPE_ERROR, "\t%3u ports registered\n",
1104 GNUNET_CONTAINER_multihashmap_size (c->ports));
1105 else
1106 LOG (GNUNET_ERROR_TYPE_ERROR, "\t no ports registered\n");
1107 LOG (GNUNET_ERROR_TYPE_ERROR, "\t%3u own channles\n",
1108 GNUNET_CONTAINER_multihashmap32_size (c->own_channels));
1109 LOG (GNUNET_ERROR_TYPE_ERROR, "\t%3u incoming channles\n",
1110 GNUNET_CONTAINER_multihashmap32_size (c->incoming_channels));
1111 }
1112 LOG (GNUNET_ERROR_TYPE_ERROR, "***************************\n");
1113 GCP_iterate_all (&show_peer_iterator, NULL);
1114
1115 LOG (GNUNET_ERROR_TYPE_ERROR,
1116 "**************************** DUMP END ****************************\n");
1117
1118 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1119}
1120
1121
1122/**
1123 * Functions to handle messages from clients
1124 */
1125static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
1126 {&handle_port_open, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN,
1127 sizeof (struct GNUNET_CADET_PortMessage)},
1128 {&handle_port_close, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
1129 sizeof (struct GNUNET_CADET_PortMessage)},
1130 {&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
1131 sizeof (struct GNUNET_CADET_LocalChannelCreateMessage)},
1132 {&handle_channel_destroy, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
1133 sizeof (struct GNUNET_CADET_LocalChannelDestroyMessage)},
1134 {&handle_data, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, 0},
1135 {&handle_ack, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
1136 sizeof (struct GNUNET_CADET_LocalAck)},
1137 {&handle_get_peers, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
1138 sizeof (struct GNUNET_MessageHeader)},
1139 {&handle_show_peer, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER,
1140 sizeof (struct GNUNET_CADET_LocalInfo)},
1141 {&handle_get_tunnels, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
1142 sizeof (struct GNUNET_MessageHeader)},
1143 {&handle_show_tunnel, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL,
1144 sizeof (struct GNUNET_CADET_LocalInfo)},
1145 {&handle_info_dump, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP,
1146 sizeof (struct GNUNET_MessageHeader)},
1147 {NULL, NULL, 0, 0}
1148};
1149
1150
1151
1152/******************************************************************************/
1153/******************************** API ***********************************/
1154/******************************************************************************/
1155
1156/**
1157 * Initialize server subsystem.
1158 *
1159 * @param handle Server handle.
1160 */
1161void
1162GML_init (struct GNUNET_SERVER_Handle *handle)
1163{
1164 LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
1165 server_handle = handle;
1166 GNUNET_SERVER_suspend (server_handle);
1167 ports = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO);
1168}
1169
1170
1171/**
1172 * Install server (service) handlers and start listening to clients.
1173 */
1174void
1175GML_start (void)
1176{
1177 GNUNET_SERVER_add_handlers (server_handle, client_handlers);
1178 GNUNET_SERVER_connect_notify (server_handle, &handle_client_connect, NULL);
1179 GNUNET_SERVER_disconnect_notify (server_handle, &handle_client_disconnect,
1180 NULL);
1181 nc = GNUNET_SERVER_notification_context_create (server_handle, 1);
1182
1183 clients_head = NULL;
1184 clients_tail = NULL;
1185 next_client_id = 0;
1186 GNUNET_SERVER_resume (server_handle);
1187}
1188
1189
1190/**
1191 * Shutdown server.
1192 */
1193void
1194GML_shutdown (void)
1195{
1196 struct CadetClient *c;
1197
1198 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down local\n");
1199
1200 for (c = clients_head; NULL != clients_head; c = clients_head)
1201 client_destroy (c);
1202
1203 if (nc != NULL)
1204 {
1205 GNUNET_SERVER_notification_context_destroy (nc);
1206 nc = NULL;
1207 }
1208
1209}
1210
1211
1212/**
1213 * Get a channel from a client.
1214 *
1215 * @param c Client to check.
1216 * @param ccn Channel ID, must be local (> 0x800...).
1217 *
1218 * @return non-NULL if channel exists in the clients lists
1219 */
1220struct CadetChannel *
1221GML_channel_get (struct CadetClient *c,
1222 struct GNUNET_CADET_ClientChannelNumber ccn)
1223{
1224 struct GNUNET_CONTAINER_MultiHashMap32 *map;
1225
1226 if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
1227 map = c->own_channels;
1228 else
1229 map = c->incoming_channels;
1230
1231 if (NULL == map)
1232 {
1233 GNUNET_break (0);
1234 LOG (GNUNET_ERROR_TYPE_DEBUG,
1235 "Client %s does no t have a valid map for CCN %X\n",
1236 GML_2s (c), ccn);
1237 return NULL;
1238 }
1239 return GNUNET_CONTAINER_multihashmap32_get (map,
1240 ccn.channel_of_client);
1241}
1242
1243
1244/**
1245 * Add a channel to a client
1246 *
1247 * @param client Client.
1248 * @param ccn Channel ID.
1249 * @param ch Channel.
1250 */
1251void
1252GML_channel_add (struct CadetClient *client,
1253 struct GNUNET_CADET_ClientChannelNumber ccn,
1254 struct CadetChannel *ch)
1255{
1256 if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
1257 GNUNET_CONTAINER_multihashmap32_put (client->own_channels,
1258 ccn.channel_of_client,
1259 ch,
1260 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1261 else
1262 GNUNET_CONTAINER_multihashmap32_put (client->incoming_channels,
1263 ccn.channel_of_client,
1264 ch,
1265 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1266}
1267
1268
1269/**
1270 * Remove a channel from a client.
1271 *
1272 * @param client Client.
1273 * @param ccn Channel ID.
1274 * @param ch Channel.
1275 */
1276void
1277GML_channel_remove (struct CadetClient *client,
1278 struct GNUNET_CADET_ClientChannelNumber ccn,
1279 struct CadetChannel *ch)
1280{
1281 if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
1282 GNUNET_CONTAINER_multihashmap32_remove (client->own_channels,
1283 ccn.channel_of_client,
1284 ch);
1285 else
1286 GNUNET_CONTAINER_multihashmap32_remove (client->incoming_channels,
1287 ccn.channel_of_client,
1288 ch);
1289}
1290
1291
1292/**
1293 * Get the tunnel's next free local channel ID.
1294 *
1295 * @param c Client.
1296 *
1297 * @return LID of a channel free to use.
1298 */
1299struct GNUNET_CADET_ClientChannelNumber
1300GML_get_next_ccn (struct CadetClient *c)
1301{
1302 struct GNUNET_CADET_ClientChannelNumber ccn;
1303
1304 while (NULL != GML_channel_get (c,
1305 c->next_ccn))
1306 {
1307 LOG (GNUNET_ERROR_TYPE_DEBUG,
1308 "Channel %u exists...\n",
1309 c->next_ccn);
1310 c->next_ccn.channel_of_client
1311 = htonl (1 + (ntohl (c->next_ccn.channel_of_client)));
1312 if (ntohl (c->next_ccn.channel_of_client) >=
1313 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
1314 c->next_ccn.channel_of_client = htonl (0);
1315 }
1316 ccn = c->next_ccn;
1317 c->next_ccn.channel_of_client
1318 = htonl (1 + (ntohl (c->next_ccn.channel_of_client)));
1319
1320 return ccn;
1321}
1322
1323
1324/**
1325 * Check if client has registered with the service and has not disconnected
1326 *
1327 * @param client the client to check
1328 *
1329 * @return non-NULL if client exists in the global DLL
1330 */
1331struct CadetClient *
1332GML_client_get (struct GNUNET_SERVER_Client *client)
1333{
1334 if (NULL == client)
1335 return NULL;
1336 return GNUNET_SERVER_client_get_user_context (client,
1337 struct CadetClient);
1338}
1339
1340
1341/**
1342 * Find a client that has opened a port
1343 *
1344 * @param port Port to check.
1345 *
1346 * @return non-NULL if a client has the port.
1347 */
1348struct CadetClient *
1349GML_client_get_by_port (const struct GNUNET_HashCode *port)
1350{
1351 return GNUNET_CONTAINER_multihashmap_get (ports, port);
1352}
1353
1354
1355/**
1356 * Deletes a channel from a client (either owner or destination).
1357 *
1358 * @param c Client whose tunnel to delete.
1359 * @param ch Channel which should be deleted.
1360 * @param id Channel ID.
1361 */
1362void
1363GML_client_delete_channel (struct CadetClient *c,
1364 struct CadetChannel *ch,
1365 struct GNUNET_CADET_ClientChannelNumber id)
1366{
1367 int res;
1368
1369 if (ntohl (id.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
1370 {
1371 res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels,
1372 id.channel_of_client,
1373 ch);
1374 if (GNUNET_YES != res)
1375 LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel root KO\n");
1376 }
1377 else
1378 {
1379 res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels,
1380 id.channel_of_client,
1381 ch);
1382 if (GNUNET_YES != res)
1383 LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel dest KO\n");
1384 }
1385}
1386
1387/**
1388 * Build a local ACK message and send it to a local client, if needed.
1389 *
1390 * If the client was already allowed to send data, do nothing.
1391 *
1392 * @param c Client to whom send the ACK.
1393 * @param ccn Channel ID to use
1394 */
1395void
1396GML_send_ack (struct CadetClient *c,
1397 struct GNUNET_CADET_ClientChannelNumber ccn)
1398{
1399 struct GNUNET_CADET_LocalAck msg;
1400
1401 LOG (GNUNET_ERROR_TYPE_DEBUG,
1402 "send local %s ack on %X towards %p\n",
1403 ntohl (ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI
1404 ? "FWD" : "BCK",
1405 ntohl (ccn.channel_of_client),
1406 c);
1407
1408 msg.header.size = htons (sizeof (msg));
1409 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
1410 msg.ccn = ccn;
1411 GNUNET_SERVER_notification_context_unicast (nc,
1412 c->handle,
1413 &msg.header,
1414 GNUNET_NO);
1415
1416}
1417
1418
1419
1420/**
1421 * Notify the client that a new incoming channel was created.
1422 *
1423 * @param c Client to notify.
1424 * @param ccn Channel ID.
1425 * @param port Channel's destination port.
1426 * @param opt Options (bit array).
1427 * @param peer Origin peer.
1428 */
1429void
1430GML_send_channel_create (struct CadetClient *c,
1431 struct GNUNET_CADET_ClientChannelNumber ccn,
1432 const struct GNUNET_HashCode *port,
1433 uint32_t opt,
1434 const struct GNUNET_PeerIdentity *peer)
1435{
1436 struct GNUNET_CADET_LocalChannelCreateMessage msg;
1437
1438 msg.header.size = htons (sizeof (msg));
1439 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
1440 msg.ccn = ccn;
1441 msg.port = *port;
1442 msg.opt = htonl (opt);
1443 msg.peer = *peer;
1444 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1445 &msg.header, GNUNET_NO);
1446}
1447
1448
1449/**
1450 * Build a local channel NACK message and send it to a local client.
1451 *
1452 * @param c Client to whom send the NACK.
1453 * @param ccn Channel ID to use
1454 */
1455void
1456GML_send_channel_nack (struct CadetClient *c,
1457 struct GNUNET_CADET_ClientChannelNumber ccn)
1458{
1459 struct GNUNET_CADET_LocalAck msg;
1460
1461 LOG (GNUNET_ERROR_TYPE_DEBUG,
1462 "send local nack on %X towards %p\n",
1463 ntohl (ccn.channel_of_client),
1464 c);
1465
1466 msg.header.size = htons (sizeof (msg));
1467 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED);
1468 msg.ccn = ccn;
1469 GNUNET_SERVER_notification_context_unicast (nc,
1470 c->handle,
1471 &msg.header,
1472 GNUNET_NO);
1473
1474}
1475
1476/**
1477 * Notify a client that a channel is no longer valid.
1478 *
1479 * @param c Client.
1480 * @param ccn ID of the channel that is destroyed.
1481 */
1482void
1483GML_send_channel_destroy (struct CadetClient *c,
1484 struct GNUNET_CADET_ClientChannelNumber ccn)
1485{
1486 struct GNUNET_CADET_LocalChannelDestroyMessage msg;
1487
1488 if (NULL == c)
1489 {
1490 GNUNET_break (0);
1491 return;
1492 }
1493 if (GNUNET_YES == c->shutting_down)
1494 return;
1495 msg.header.size = htons (sizeof (msg));
1496 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
1497 msg.ccn = ccn;
1498 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1499 &msg.header, GNUNET_NO);
1500}
1501
1502
1503/**
1504 * Modify the cadet message ID from global to local and send to client.
1505 *
1506 * @param c Client to send to.
1507 * @param msg Message to modify and send.
1508 * @param ccn Channel ID to use (c can be both owner and client).
1509 */
1510void
1511GML_send_data (struct CadetClient *c,
1512 const struct GNUNET_CADET_ChannelAppDataMessage *msg,
1513 struct GNUNET_CADET_ClientChannelNumber ccn)
1514{
1515 struct GNUNET_CADET_LocalData *copy;
1516 uint16_t size = ntohs (msg->header.size) - sizeof (struct GNUNET_CADET_ChannelAppDataMessage);
1517 char cbuf[size + sizeof (struct GNUNET_CADET_LocalData)];
1518
1519 if (size < sizeof (struct GNUNET_MessageHeader))
1520 {
1521 GNUNET_break_op (0);
1522 return;
1523 }
1524 if (NULL == c)
1525 {
1526 GNUNET_break (0);
1527 return;
1528 }
1529 copy = (struct GNUNET_CADET_LocalData *) cbuf;
1530 GNUNET_memcpy (&copy[1], &msg[1], size);
1531 copy->header.size = htons (sizeof (struct GNUNET_CADET_LocalData) + size);
1532 copy->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1533 copy->ccn = ccn;
1534 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1535 &copy->header, GNUNET_NO);
1536}
1537
1538
1539/**
1540 * Get the static string to represent a client.
1541 *
1542 * @param c Client.
1543 *
1544 * @return Static string for the client.
1545 */
1546const char *
1547GML_2s (const struct CadetClient *c)
1548{
1549 static char buf[32];
1550
1551 SPRINTF (buf, "%u", c->id);
1552 return buf;
1553}
diff --git a/src/cadet/gnunet-service-cadet_local.h b/src/cadet/gnunet-service-cadet_local.h
deleted file mode 100644
index 113c2f489..000000000
--- a/src/cadet/gnunet-service-cadet_local.h
+++ /dev/null
@@ -1,234 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/gnunet-service-cadet_local.h
23 * @brief cadet service; dealing with local clients
24 * @author Bartlomiej Polot
25 *
26 * All functions in this file should use the prefix GML (Gnunet Cadet Local)
27 */
28
29#ifndef GNUNET_SERVICE_CADET_LOCAL_H
30#define GNUNET_SERVICE_CADET_LOCAL_H
31
32#ifdef __cplusplus
33extern "C"
34{
35#if 0 /* keep Emacsens' auto-indent happy */
36}
37#endif
38#endif
39
40#include "platform.h"
41#include "gnunet_util_lib.h"
42
43/**
44 * Struct containing information about a client of the service
45 */
46struct CadetClient;
47
48#include "gnunet-service-cadet_channel.h"
49
50/******************************************************************************/
51/******************************** API ***********************************/
52/******************************************************************************/
53
54/**
55 * Initialize server subsystem.
56 *
57 * @param handle Server handle.
58 */
59void
60GML_init (struct GNUNET_SERVER_Handle *handle);
61
62/**
63 * Install server (service) handlers and start listening to clients.
64 */
65void
66GML_start (void);
67
68/**
69 * Shutdown server.
70 */
71void
72GML_shutdown (void);
73
74/**
75 * Get a channel from a client.
76 *
77 * @param c Client to check.
78 * @param ccn Channel ID, must be local (> 0x800...).
79 *
80 * @return non-NULL if channel exists in the clients lists
81 */
82struct CadetChannel *
83GML_channel_get (struct CadetClient *c,
84 struct GNUNET_CADET_ClientChannelNumber ccn);
85
86/**
87 * Add a channel to a client
88 *
89 * @param client Client.
90 * @param ccn Channel ID.
91 * @param ch Channel.
92 */
93void
94GML_channel_add (struct CadetClient *client,
95 struct GNUNET_CADET_ClientChannelNumber ccn,
96 struct CadetChannel *ch);
97
98/**
99 * Remove a channel from a client
100 *
101 * @param client Client.
102 * @param ccn Channel ID.
103 * @param ch Channel.
104 */
105void
106GML_channel_remove (struct CadetClient *client,
107 struct GNUNET_CADET_ClientChannelNumber ccn,
108 struct CadetChannel *ch);
109
110/**
111 * Get the tunnel's next free local channel ID.
112 *
113 * @param c Client.
114 *
115 * @return LID of a channel free to use.
116 */
117struct GNUNET_CADET_ClientChannelNumber
118GML_get_next_ccn (struct CadetClient *c);
119
120/**
121 * Check if client has registered with the service and has not disconnected
122 *
123 * @param client the client to check
124 *
125 * @return non-NULL if client exists in the global DLL
126 */
127struct CadetClient *
128GML_client_get (struct GNUNET_SERVER_Client *client);
129
130/**
131 * Find a client that has opened a port
132 *
133 * @param port Port to check.
134 *
135 * @return non-NULL if a client has the port.
136 */
137struct CadetClient *
138GML_client_get_by_port (const struct GNUNET_HashCode *port);
139
140/**
141 * Deletes a tunnel from a client (either owner or destination).
142 *
143 * @param c Client whose tunnel to delete.
144 * @param ch Channel which should be deleted.
145 * @param id Channel ID.
146 */
147void
148GML_client_delete_channel (struct CadetClient *c,
149 struct CadetChannel *ch,
150 struct GNUNET_CADET_ClientChannelNumber id);
151
152/**
153 * Build a local ACK message and send it to a local client, if needed.
154 *
155 * If the client was already allowed to send data, do nothing.
156 *
157 * @param c Client to whom send the ACK.
158 * @param id Channel ID to use
159 */
160void
161GML_send_ack (struct CadetClient *c,
162 struct GNUNET_CADET_ClientChannelNumber id);
163
164/**
165 * Notify the appropriate client that a new incoming channel was created.
166 *
167 * @param c Client to notify.
168 * @param id Channel ID.
169 * @param port Channel's destination port.
170 * @param opt Options (bit array).
171 * @param peer Origin peer.
172 */
173void
174GML_send_channel_create (struct CadetClient *c,
175 struct GNUNET_CADET_ClientChannelNumber id,
176 const struct GNUNET_HashCode *port,
177 uint32_t opt,
178 const struct GNUNET_PeerIdentity *peer);
179
180/**
181 * Build a local channel NACK message and send it to a local client.
182 *
183 * @param c Client to whom send the NACK.
184 * @param id Channel ID to use
185 */
186void
187GML_send_channel_nack (struct CadetClient *c,
188 struct GNUNET_CADET_ClientChannelNumber id);
189
190
191/**
192 * Notify a client that a channel is no longer valid.
193 *
194 * @param c Client.
195 * @param id ID of the channel that is destroyed.
196 */
197void
198GML_send_channel_destroy (struct CadetClient *c,
199 struct GNUNET_CADET_ClientChannelNumber id);
200
201
202/**
203 * Modify the cadet message ID from global to local and send to client.
204 *
205 * @param c Client to send to.
206 * @param msg Message to modify and send.
207 * @param id Channel ID to use (c can be both owner and client).
208 */
209void
210GML_send_data (struct CadetClient *c,
211 const struct GNUNET_CADET_ChannelAppDataMessage *msg,
212 struct GNUNET_CADET_ClientChannelNumber id);
213
214/**
215 * Get the static string to represent a client.
216 *
217 * @param c Client.
218 *
219 * @return Static string for the client.
220 */
221const char *
222GML_2s (const struct CadetClient *c);
223
224
225#if 0 /* keep Emacsens' auto-indent happy */
226{
227#endif
228#ifdef __cplusplus
229}
230#endif
231
232/* ifndef GNUNET_CADET_SERVICE_LOCAL_H */
233#endif
234/* end of gnunet-cadet-service_LOCAL.h */
diff --git a/src/cadet/gnunet-service-cadet-new_paths.c b/src/cadet/gnunet-service-cadet_paths.c
index c6121a133..13752643c 100644
--- a/src/cadet/gnunet-service-cadet-new_paths.c
+++ b/src/cadet/gnunet-service-cadet_paths.c
@@ -18,16 +18,16 @@
18 Boston, MA 02110-1301, USA. 18 Boston, MA 02110-1301, USA.
19*/ 19*/
20/** 20/**
21 * @file cadet/gnunet-service-cadet-new_paths.c 21 * @file cadet/gnunet-service-cadet_paths.c
22 * @brief Information we track per path. 22 * @brief Information we track per path.
23 * @author Bartlomiej Polot 23 * @author Bartlomiej Polot
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 */ 25 */
26#include "platform.h" 26#include "platform.h"
27#include "gnunet-service-cadet-new_connection.h" 27#include "gnunet-service-cadet_connection.h"
28#include "gnunet-service-cadet-new_tunnels.h" 28#include "gnunet-service-cadet_tunnels.h"
29#include "gnunet-service-cadet-new_peer.h" 29#include "gnunet-service-cadet_peer.h"
30#include "gnunet-service-cadet-new_paths.h" 30#include "gnunet-service-cadet_paths.h"
31 31
32 32
33#define LOG(level, ...) GNUNET_log_from(level,"cadet-pat",__VA_ARGS__) 33#define LOG(level, ...) GNUNET_log_from(level,"cadet-pat",__VA_ARGS__)
diff --git a/src/cadet/gnunet-service-cadet-new_paths.h b/src/cadet/gnunet-service-cadet_paths.h
index 7310d75e6..6b7bef640 100644
--- a/src/cadet/gnunet-service-cadet-new_paths.h
+++ b/src/cadet/gnunet-service-cadet_paths.h
@@ -29,7 +29,7 @@
29#define GNUNET_SERVICE_CADET_PATHS_H 29#define GNUNET_SERVICE_CADET_PATHS_H
30 30
31#include "gnunet_util_lib.h" 31#include "gnunet_util_lib.h"
32#include "gnunet-service-cadet-new.h" 32#include "gnunet-service-cadet.h"
33 33
34/** 34/**
35 * Create a peer path based on the result of a DHT lookup. If we 35 * Create a peer path based on the result of a DHT lookup. If we
diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c
index fa3f2be80..71c7c67d0 100644
--- a/src/cadet/gnunet-service-cadet_peer.c
+++ b/src/cadet/gnunet-service-cadet_peer.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2013, 2015 GNUnet e.V. 3 Copyright (C) 2001-2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -17,2193 +17,1461 @@
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA. 18 Boston, MA 02110-1301, USA.
19*/ 19*/
20
20/** 21/**
21 * @file cadet/gnunet-service-cadet_peer.c 22 * @file cadet/gnunet-service-cadet_peer.c
22 * @brief GNUnet CADET service connection handling 23 * @brief Information we track per peer.
23 * @author Bartlomiej Polot 24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * TODO:
28 * - optimize stopping/restarting DHT search to situations
29 * where we actually need it (i.e. not if we have a direct connection,
30 * or if we already have plenty of good short ones, or maybe even
31 * to take a break if we have some connections and have searched a lot (?))
24 */ 32 */
25#include "platform.h" 33#include "platform.h"
26#include "gnunet_util_lib.h" 34#include "gnunet_util_lib.h"
35#include "gnunet_hello_lib.h"
27#include "gnunet_signatures.h" 36#include "gnunet_signatures.h"
28#include "gnunet_transport_service.h" 37#include "gnunet_transport_service.h"
29#include "gnunet_ats_service.h" 38#include "gnunet_ats_service.h"
30#include "gnunet_core_service.h" 39#include "gnunet_core_service.h"
31#include "gnunet_statistics_service.h" 40#include "gnunet_statistics_service.h"
32#include "cadet_protocol.h" 41#include "cadet_protocol.h"
33#include "gnunet-service-cadet_peer.h"
34#include "gnunet-service-cadet_dht.h"
35#include "gnunet-service-cadet_connection.h" 42#include "gnunet-service-cadet_connection.h"
36#include "gnunet-service-cadet_tunnel.h" 43#include "gnunet-service-cadet_dht.h"
37#include "cadet_path.h" 44#include "gnunet-service-cadet_peer.h"
45#include "gnunet-service-cadet_paths.h"
46#include "gnunet-service-cadet_tunnels.h"
38 47
39#define LOG(level, ...) GNUNET_log_from (level,"cadet-p2p",__VA_ARGS__)
40#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-p2p",__VA_ARGS__)
41 48
49#define LOG(level, ...) GNUNET_log_from(level,"cadet-per",__VA_ARGS__)
42 50
43/******************************************************************************/
44/******************************** STRUCTS **********************************/
45/******************************************************************************/
46 51
47/** 52/**
48 * Information about a queued message on the peer level. 53 * How long do we wait until tearing down an idle peer?
49 */ 54 */
50struct CadetPeerQueue { 55#define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
51
52 struct CadetPeerQueue *next;
53 struct CadetPeerQueue *prev;
54
55 /**
56 * Envelope to cancel message before MQ sends it.
57 */
58 struct GNUNET_MQ_Envelope *env;
59
60 /**
61 * Peer (neighbor) this message is being sent to.
62 */
63 struct CadetPeer *peer;
64
65 /**
66 * Continuation to call to notify higher layers about message sent.
67 */
68 GCP_sent cont;
69
70 /**
71 * Closure for @a cont.
72 */
73 void *cont_cls;
74
75 /**
76 * Task to asynchronously run the drop continuation.
77 */
78 struct GNUNET_SCHEDULER_Task *drop_task;
79
80 /**
81 * Time when message was queued for sending.
82 */
83 struct GNUNET_TIME_Absolute queue_timestamp;
84
85 /**
86 * #GNUNET_YES if message was management traffic (POLL, ACK, ...).
87 */
88 int management_traffic;
89
90 /**
91 * Message type.
92 */
93 uint16_t type;
94
95 /**
96 * Message size.
97 */
98 uint16_t size;
99
100 /**
101 * Type of the message's payload, if it was encrypted data.
102 */
103 uint16_t payload_type;
104
105 /**
106 * ID of the payload (PID, ACK #, ...).
107 */
108 struct CadetEncryptedMessageIdentifier payload_id;
109
110 /**
111 * Connection this message was sent on.
112 */
113 struct CadetConnection *c;
114
115 /**
116 * Direction in @a c this message was send on (#GNUNET_YES = FWD).
117 */
118 int c_fwd;
119};
120
121 56
122/** 57/**
123 * Struct containing all information regarding a given peer 58 * How long do we keep paths around if we no longer care about the peer?
124 */ 59 */
125struct CadetPeer 60#define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
126{
127 /**
128 * ID of the peer
129 */
130 GNUNET_PEER_Id id;
131
132 struct CadetPeerQueue *q_head;
133 struct CadetPeerQueue *q_tail;
134
135 /**
136 * Last time we heard from this peer
137 */
138 struct GNUNET_TIME_Absolute last_contact;
139
140 /**
141 * Paths to reach the peer, ordered by ascending hop count
142 */
143 struct CadetPeerPath *path_head;
144
145 /**
146 * Paths to reach the peer, ordered by ascending hop count
147 */
148 struct CadetPeerPath *path_tail;
149
150 /**
151 * Handle to stop the DHT search for paths to this peer
152 */
153 struct GCD_search_handle *search_h;
154
155 /**
156 * Handle to stop the DHT search for paths to this peer
157 */
158 struct GNUNET_SCHEDULER_Task *search_delayed;
159
160 /**
161 * Tunnel to this peer, if any.
162 */
163 struct CadetTunnel *tunnel;
164
165 /**
166 * Connections that go through this peer; indexed by tid.
167 */
168 struct GNUNET_CONTAINER_MultiShortmap *connections;
169
170 /**
171 * Handle for core transmissions.
172 */
173 struct GNUNET_MQ_Handle *core_mq;
174
175 /**
176 * How many messages are in the queue to this peer.
177 */
178 unsigned int queue_n;
179
180 /**
181 * Hello message.
182 */
183 struct GNUNET_HELLO_Message* hello;
184
185 /**
186 * Handle to us offering the HELLO to the transport.
187 */
188 struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
189
190 /**
191 * Handle to our ATS request asking ATS to suggest an address
192 * to TRANSPORT for this peer (to establish a direct link).
193 */
194 struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
195 61
196};
197
198
199/******************************************************************************/
200/******************************* GLOBALS ***********************************/
201/******************************************************************************/
202
203/**
204 * Global handle to the statistics service.
205 */
206extern struct GNUNET_STATISTICS_Handle *stats;
207 62
208/**
209 * Local peer own ID (full value).
210 */
211extern struct GNUNET_PeerIdentity my_full_id;
212 63
213/**
214 * Local peer own ID (short)
215 */
216extern GNUNET_PEER_Id myid;
217 64
218/** 65/**
219 * Peers known, indexed by PeerIdentity, values of type `struct CadetPeer`. 66 * Data structure used to track whom we have to notify about changes
67 * to our message queue.
220 */ 68 */
221static struct GNUNET_CONTAINER_MultiPeerMap *peers; 69struct GCP_MessageQueueManager
222 70{
223/**
224 * How many peers do we want to remember?
225 */
226static unsigned long long max_peers;
227 71
228/** 72 /**
229 * Percentage of messages that will be dropped (for test purposes only). 73 * Kept in a DLL.
230 */ 74 */
231static unsigned long long drop_percent; 75 struct GCP_MessageQueueManager *next;
232 76
233/** 77 /**
234 * Handle to communicate with CORE. 78 * Kept in a DLL.
235 */ 79 */
236static struct GNUNET_CORE_Handle *core_handle; 80 struct GCP_MessageQueueManager *prev;
237 81
238/** 82 /**
239 * Our configuration; 83 * Function to call with updated message queue object.
240 */ 84 */
241static const struct GNUNET_CONFIGURATION_Handle *cfg; 85 GCP_MessageQueueNotificationCallback cb;
242 86
243/** 87 /**
244 * Handle to communicate with ATS. 88 * Closure for @e cb.
245 */ 89 */
246static struct GNUNET_ATS_ConnectivityHandle *ats_ch; 90 void *cb_cls;
247 91
248/** 92 /**
249 * Shutdown falg. 93 * The peer this is for.
250 */ 94 */
251static int in_shutdown; 95 struct CadetPeer *cp;
252 96
97 /**
98 * Envelope this manager would like to transmit once it is its turn.
99 */
100 struct GNUNET_MQ_Envelope *env;
253 101
254/******************************************************************************/ 102};
255/***************************** CORE HELPERS *********************************/
256/******************************************************************************/
257 103
258 104
259/** 105/**
260 * Iterator to notify all connections of a broken link. Mark connections 106 * Struct containing all information regarding a given peer
261 * to destroy after all traffic has been sent.
262 *
263 * @param cls Closure (disconnected peer).
264 * @param key Current key code (peer id).
265 * @param value Value in the hash map (connection).
266 *
267 * @return #GNUNET_YES to continue to iterate.
268 */ 107 */
269static int 108struct CadetPeer
270notify_broken (void *cls,
271 const struct GNUNET_ShortHashCode *key,
272 void *value)
273{ 109{
274 struct CadetPeer *peer = cls; 110 /**
275 struct CadetConnection *c = value; 111 * ID of the peer
112 */
113 struct GNUNET_PeerIdentity pid;
114
115 /**
116 * Last time we heard from this peer (currently not used!)
117 */
118 struct GNUNET_TIME_Absolute last_contactXXX;
119
120 /**
121 * Array of DLLs of paths traversing the peer, organized by the
122 * offset of the peer on the larger path.
123 */
124 struct CadetPeerPathEntry **path_heads;
125
126 /**
127 * Array of DLL of paths traversing the peer, organized by the
128 * offset of the peer on the larger path.
129 */
130 struct CadetPeerPathEntry **path_tails;
131
132 /**
133 * Notifications to call when @e core_mq changes.
134 */
135 struct GCP_MessageQueueManager *mqm_head;
136
137 /**
138 * Notifications to call when @e core_mq changes.
139 */
140 struct GCP_MessageQueueManager *mqm_tail;
141
142 /**
143 * Pointer to first "ready" entry in @e mqm_head.
144 */
145 struct GCP_MessageQueueManager *mqm_ready_ptr;
146
147 /**
148 * MIN-heap of paths owned by this peer (they also end at this
149 * peer). Ordered by desirability.
150 */
151 struct GNUNET_CONTAINER_Heap *path_heap;
152
153 /**
154 * Handle to stop the DHT search for paths to this peer
155 */
156 struct GCD_search_handle *search_h;
157
158 /**
159 * Task to clean up @e path_heap asynchronously.
160 */
161 struct GNUNET_SCHEDULER_Task *heap_cleanup_task;
162
163 /**
164 * Task to destroy this entry.
165 */
166 struct GNUNET_SCHEDULER_Task *destroy_task;
167
168 /**
169 * Tunnel to this peer, if any.
170 */
171 struct CadetTunnel *t;
172
173 /**
174 * Connections that go through this peer; indexed by tid.
175 */
176 struct GNUNET_CONTAINER_MultiShortmap *connections;
177
178 /**
179 * Handle for core transmissions.
180 */
181 struct GNUNET_MQ_Handle *core_mq;
182
183 /**
184 * Hello message of the peer.
185 */
186 struct GNUNET_HELLO_Message *hello;
187
188 /**
189 * Handle to us offering the HELLO to the transport.
190 */
191 struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
192
193 /**
194 * Handle to our ATS request asking ATS to suggest an address
195 * to TRANSPORT for this peer (to establish a direct link).
196 */
197 struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
198
199 /**
200 * How many messages are in the queue to this peer.
201 */
202 unsigned int queue_n;
203
204 /**
205 * How many paths do we have to this peer (in all @e path_heads DLLs combined).
206 */
207 unsigned int num_paths;
208
209 /**
210 * Sum over all of the offsets of all of the paths in the @a path_heads DLLs.
211 * Used to speed-up @GCP_get_desirability_of_path() calculation.
212 */
213 unsigned int off_sum;
214
215 /**
216 * Number of message queue managers of this peer that have a message in waiting.
217 *
218 * Used to quickly see if we need to bother scanning the @e msm_head DLL.
219 * TODO: could be replaced by another DLL that would then allow us to avoid
220 * the O(n)-scan of the DLL for ready entries!
221 */
222 unsigned int mqm_ready_counter;
223
224 /**
225 * Current length of the @e path_heads and @path_tails arrays.
226 * The arrays should be grown as needed.
227 */
228 unsigned int path_dll_length;
276 229
277 LOG (GNUNET_ERROR_TYPE_DEBUG, 230};
278 "Notifying %s due to %s disconnect\n",
279 GCC_2s (c), GCP_2s (peer));
280 GCC_neighbor_disconnected (c, peer);
281 return GNUNET_YES;
282}
283 231
284 232
285/** 233/**
286 * Remove the direct path to the peer. 234 * Get the static string for a peer ID.
287 *
288 * @param peer Peer to remove the direct path from.
289 */
290static struct CadetPeerPath *
291pop_direct_path (struct CadetPeer *peer)
292{
293 struct CadetPeerPath *iter;
294
295 for (iter = peer->path_head; NULL != iter; iter = iter->next)
296 {
297 if (2 >= iter->length)
298 {
299 GNUNET_CONTAINER_DLL_remove (peer->path_head,
300 peer->path_tail,
301 iter);
302 return iter;
303 }
304 }
305 return NULL;
306}
307
308/**
309 * Call the continuation after a message has been sent or dropped.
310 *
311 * This funcion removes the message from the queue.
312 * 235 *
313 * @param q Queue handle. 236 * @param cp Peer.
314 * @param sent #GNUNET_YES if was sent to CORE, #GNUNET_NO if dropped. 237 * @return Static string for it's ID.
315 */ 238 */
316static void 239const char *
317call_peer_cont (struct CadetPeerQueue *q, int sent); 240GCP_2s (const struct CadetPeer *cp)
241{
242 static char buf[32];
243
244 GNUNET_snprintf (buf,
245 sizeof (buf),
246 "P(%s)",
247 GNUNET_i2s (&cp->pid));
248 return buf;
249}
250
251
252/**
253 * Calculate how desirable a path is for @a cp if @a cp
254 * is at offset @a off.
255 *
256 * The 'desirability_table.c' program can be used to compute a list of
257 * sample outputs for different scenarios. Basically, we score paths
258 * lower if there are many alternatives, and higher if they are
259 * shorter than average, and very high if they are much shorter than
260 * average and without many alternatives.
261 *
262 * @param cp a peer reachable via a path
263 * @param off offset of @a cp in the path
264 * @return score how useful a path is to reach @a cp,
265 * positive scores mean path is more desirable
266 */
267double
268GCP_get_desirability_of_path (struct CadetPeer *cp,
269 unsigned int off)
270{
271 unsigned int num_alts = cp->num_paths;
272 unsigned int off_sum;
273 double avg_sum;
274 double path_delta;
275 double weight_alts;
276
277 GNUNET_assert (num_alts >= 1); /* 'path' should be in there! */
278 GNUNET_assert (0 != cp->path_dll_length);
279
280 /* We maintain 'off_sum' in 'peer' and thereby
281 avoid the SLOW recalculation each time. Kept here
282 just to document what is going on. */
283#if SLOW
284 off_sum = 0;
285 for (unsigned int j=0;j<cp->path_dll_length;j++)
286 for (struct CadetPeerPathEntry *pe = cp->path_heads[j];
287 NULL != pe;
288 pe = pe->next)
289 off_sum += j;
290 GNUNET_assert (off_sum == cp->off_sum);
291#else
292 off_sum = cp->off_sum;
293#endif
294 avg_sum = off_sum * 1.0 / cp->path_dll_length;
295 path_delta = off - avg_sum;
296 /* path_delta positiv: path off of peer above average (bad path for peer),
297 path_delta negativ: path off of peer below average (good path for peer) */
298 if (path_delta <= - 1.0)
299 weight_alts = - num_alts / path_delta; /* discount alternative paths */
300 else if (path_delta >= 1.0)
301 weight_alts = num_alts * path_delta; /* overcount alternative paths */
302 else
303 weight_alts = num_alts; /* count alternative paths normally */
318 304
319 305
320/******************************************************************************/ 306 /* off+1: long paths are generally harder to find and thus count
321/***************************** CORE CALLBACKS *********************************/ 307 a bit more as they get longer. However, above-average paths
322/******************************************************************************/ 308 still need to count less, hence the squaring of that factor. */
309 return (off + 1.0) / (weight_alts * weight_alts);
310}
323 311
324 312
325/** 313/**
326 * Method called whenever a given peer connects. 314 * This peer is no longer be needed, clean it up now.
327 * 315 *
328 * @param cls Core closure (unused). 316 * @param cls peer to clean up
329 * @param peer Peer identity this notification is about
330 * @param mq Message Queue to this peer.
331 *
332 * @return Internal closure for handlers (CadetPeer struct).
333 */ 317 */
334static void * 318static void
335core_connect_handler (void *cls, 319destroy_peer (void *cls)
336 const struct GNUNET_PeerIdentity *peer, 320{
337 struct GNUNET_MQ_Handle *mq) 321 struct CadetPeer *cp = cls;
338{ 322
339 struct CadetPeer *neighbor; 323 LOG (GNUNET_ERROR_TYPE_DEBUG,
340 struct CadetPeerPath *path; 324 "Destroying state about peer %s\n",
341 char own_id[16]; 325 GCP_2s (cp));
342 326 cp->destroy_task = NULL;
343 GCC_check_connections (); 327 GNUNET_assert (NULL == cp->t);
344 GNUNET_snprintf (own_id, 328 GNUNET_assert (NULL == cp->core_mq);
345 sizeof (own_id), 329 GNUNET_assert (0 == cp->num_paths);
346 "%s", 330 for (unsigned int i=0;i<cp->path_dll_length;i++)
347 GNUNET_i2s (&my_full_id)); 331 GNUNET_assert (NULL == cp->path_heads[i]);
348 332 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections));
349 /* Save a path to the neighbor */ 333 GNUNET_assert (GNUNET_YES ==
350 neighbor = GCP_get (peer, GNUNET_YES); 334 GNUNET_CONTAINER_multipeermap_remove (peers,
351 if (myid == neighbor->id) 335 &cp->pid,
352 { 336 cp));
353 LOG (GNUNET_ERROR_TYPE_INFO, 337 GNUNET_free_non_null (cp->path_heads);
354 "CONNECTED %s (self)\n", 338 GNUNET_free_non_null (cp->path_tails);
355 own_id); 339 cp->path_dll_length = 0;
356 path = path_new (1); 340 if (NULL != cp->search_h)
357 } 341 {
358 else 342 GCD_search_stop (cp->search_h);
359 { 343 cp->search_h = NULL;
360 LOG (GNUNET_ERROR_TYPE_INFO, 344 }
361 "CONNECTED %s <= %s\n", 345 /* FIXME: clean up search_delayedXXX! */
362 own_id,
363 GNUNET_i2s (peer));
364 path = path_new (2);
365 path->peers[1] = neighbor->id;
366 GNUNET_PEER_change_rc (neighbor->id, 1);
367 GNUNET_assert (NULL == neighbor->core_mq);
368 neighbor->core_mq = mq;
369 }
370 path->peers[0] = myid;
371 GNUNET_PEER_change_rc (myid, 1);
372 GCP_add_path (neighbor, path, GNUNET_YES);
373
374 /* Create the connections hashmap */
375 GNUNET_assert (NULL == neighbor->connections);
376 neighbor->connections = GNUNET_CONTAINER_multishortmap_create (16,
377 GNUNET_YES);
378 GNUNET_STATISTICS_update (stats,
379 "# peers",
380 1,
381 GNUNET_NO);
382
383 if ( (NULL != GCP_get_tunnel (neighbor)) &&
384 (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, peer)) )
385 {
386 GCP_connect (neighbor);
387 }
388 GCC_check_connections ();
389 346
390 return neighbor; 347 if (NULL != cp->hello_offer)
348 {
349 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
350 cp->hello_offer = NULL;
351 }
352 if (NULL != cp->connectivity_suggestion)
353 {
354 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
355 cp->connectivity_suggestion = NULL;
356 }
357 GNUNET_CONTAINER_multishortmap_destroy (cp->connections);
358 if (NULL != cp->path_heap)
359 {
360 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
361 cp->path_heap = NULL;
362 }
363 if (NULL != cp->heap_cleanup_task)
364 {
365 GNUNET_SCHEDULER_cancel (cp->heap_cleanup_task);
366 cp->heap_cleanup_task = NULL;
367 }
368 GNUNET_free_non_null (cp->hello);
369 /* Peer should not be freed if paths exist; if there are no paths,
370 there ought to be no connections, and without connections, no
371 notifications. Thus we can assert that mqm_head is empty at this
372 point. */
373 GNUNET_assert (NULL == cp->mqm_head);
374 GNUNET_assert (NULL == cp->mqm_ready_ptr);
375 GNUNET_free (cp);
391} 376}
392 377
393 378
394/** 379/**
395 * Method called whenever a peer disconnects. 380 * This peer is now on more "active" duty, activate processes related to it.
396 * 381 *
397 * @param cls Core closure (unused). 382 * @param cp the more-active peer
398 * @param peer Peer identity this notification is about.
399 * @param internal_cls Internal closure (CadetPeer struct).
400 */ 383 */
401static void 384static void
402core_disconnect_handler (void *cls, 385consider_peer_activate (struct CadetPeer *cp)
403 const struct GNUNET_PeerIdentity *peer,
404 void *internal_cls)
405{ 386{
406 struct CadetPeer *p = internal_cls; 387 uint32_t strength;
407 struct CadetPeerPath *direct_path; 388
408 char own_id[16]; 389 LOG (GNUNET_ERROR_TYPE_DEBUG,
409 390 "Updating peer %s activation state (%u connections)%s%s\n",
410 GCC_check_connections (); 391 GCP_2s (cp),
411 strncpy (own_id, GNUNET_i2s (&my_full_id), 16); 392 GNUNET_CONTAINER_multishortmap_size (cp->connections),
412 own_id[15] = '\0'; 393 (NULL == cp->t) ? "" : " with tunnel",
413 if (myid == p->id) 394 (NULL == cp->core_mq) ? "" : " with CORE link");
414 { 395 if (NULL != cp->destroy_task)
415 LOG (GNUNET_ERROR_TYPE_INFO, 396 {
416 "DISCONNECTED %s (self)\n", 397 /* It's active, do not destory! */
417 own_id); 398 GNUNET_SCHEDULER_cancel (cp->destroy_task);
418 } 399 cp->destroy_task = NULL;
419 else 400 }
401 if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
402 (NULL == cp->t) )
403 {
404 /* We're just on a path or directly connected; don't bother too much */
405 if (NULL != cp->connectivity_suggestion)
420 { 406 {
421 LOG (GNUNET_ERROR_TYPE_INFO, 407 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
422 "DISCONNECTED %s <= %s\n", 408 cp->connectivity_suggestion = NULL;
423 own_id, GNUNET_i2s (peer));
424 p->core_mq = NULL;
425 } 409 }
426 direct_path = pop_direct_path (p); 410 if (NULL != cp->search_h)
427 if (NULL != p->connections)
428 { 411 {
429 GNUNET_CONTAINER_multishortmap_iterate (p->connections, 412 GCD_search_stop (cp->search_h);
430 &notify_broken, 413 cp->search_h = NULL;
431 p);
432 GNUNET_CONTAINER_multishortmap_destroy (p->connections);
433 p->connections = NULL;
434 } 414 }
435 GNUNET_STATISTICS_update (stats, 415 return;
436 "# peers", 416 }
437 -1, 417 if (NULL == cp->core_mq)
438 GNUNET_NO); 418 {
439 path_destroy (direct_path); 419 /* Lacks direct connection, try to create one by querying the DHT */
440 GCC_check_connections (); 420 if ( (NULL == cp->search_h) &&
441} 421 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
442 422 cp->search_h
443 423 = GCD_search (&cp->pid);
444/******************************************************************************/ 424 }
445/******************************************************************************/ 425 else
446/******************************************************************************/ 426 {
447/******************************************************************************/ 427 /* Have direct connection, stop DHT search if active */
448/******************************************************************************/ 428 if (NULL != cp->search_h)
449
450/**
451 * Check if the create_connection message has the appropriate size.
452 *
453 * @param cls Closure (unused).
454 * @param msg Message to check.
455 *
456 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
457 */
458static int
459check_create (void *cls, const struct GNUNET_CADET_ConnectionCreateMessage *msg)
460{
461 uint16_t size;
462
463 size = ntohs (msg->header.size);
464 if (size < sizeof (*msg))
465 { 429 {
466 GNUNET_break_op (0); 430 GCD_search_stop (cp->search_h);
467 return GNUNET_NO; 431 cp->search_h = NULL;
468 } 432 }
469 return GNUNET_YES; 433 }
470}
471
472/**
473 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
474 *
475 * @param cls Closure (CadetPeer for neighbor that sent the message).
476 * @param msg Message itself.
477 */
478static void
479handle_create (void *cls, const struct GNUNET_CADET_ConnectionCreateMessage *msg)
480{
481 struct CadetPeer *peer = cls;
482 GCC_handle_create (peer, msg);
483}
484
485
486/**
487 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
488 *
489 * @param cls Closure (CadetPeer for neighbor that sent the message).
490 * @param msg Message itself.
491 */
492static void
493handle_confirm (void *cls, const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
494{
495 struct CadetPeer *peer = cls;
496 GCC_handle_confirm (peer, msg);
497}
498
499 434
500/** 435 /* If we have a tunnel, our urge for connections is much bigger */
501 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN 436 strength = (NULL != cp->t) ? 32 : 1;
502 * 437 if (NULL != cp->connectivity_suggestion)
503 * @param cls Closure (CadetPeer for neighbor that sent the message). 438 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
504 * @param msg Message itself. 439 cp->connectivity_suggestion
505 */ 440 = GNUNET_ATS_connectivity_suggest (ats_ch,
506static void 441 &cp->pid,
507handle_broken (void *cls, const struct GNUNET_CADET_ConnectionBrokenMessage *msg) 442 strength);
508{
509 struct CadetPeer *peer = cls;
510 GCC_handle_broken (peer, msg);
511} 443}
512 444
513 445
514/** 446/**
515 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY 447 * This peer may no longer be needed, consider cleaning it up.
516 * 448 *
517 * @param cls Closure (CadetPeer for neighbor that sent the message). 449 * @param cp peer to clean up
518 * @param msg Message itself.
519 */ 450 */
520static void 451static void
521handle_destroy (void *cls, const struct GNUNET_CADET_ConnectionDestroyMessage *msg) 452consider_peer_destroy (struct CadetPeer *cp);
522{
523 struct CadetPeer *peer = cls;
524 GCC_handle_destroy (peer, msg);
525}
526 453
527 454
528/** 455/**
529 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK 456 * We really no longere care about a peer, stop hogging memory with paths to it.
457 * Afterwards, see if there is more to be cleaned up about this peer.
530 * 458 *
531 * @param cls Closure (CadetPeer for neighbor that sent the message). 459 * @param cls a `struct CadetPeer`.
532 * @param msg Message itself.
533 */ 460 */
534static void 461static void
535handle_ack (void *cls, const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg) 462drop_paths (void *cls)
536{ 463{
537 struct CadetPeer *peer = cls; 464 struct CadetPeer *cp = cls;
538 GCC_handle_ack (peer, msg); 465 struct CadetPeerPath *path;
539}
540 466
541 467 cp->destroy_task = NULL;
542/** 468 while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
543 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL 469 GCPP_release (path);
544 * 470 consider_peer_destroy (cp);
545 * @param cls Closure (CadetPeer for neighbor that sent the message).
546 * @param msg Message itself.
547 */
548static void
549handle_poll (void *cls, const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg)
550{
551 struct CadetPeer *peer = cls;
552 GCC_handle_poll (peer, msg);
553} 471}
554 472
555 473
556/** 474/**
557 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX 475 * This peer may no longer be needed, consider cleaning it up.
558 * 476 *
559 * @param cls Closure (CadetPeer for neighbor that sent the message). 477 * @param cp peer to clean up
560 * @param msg Message itself.
561 */ 478 */
562static void 479static void
563handle_kx (void *cls, const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) 480consider_peer_destroy (struct CadetPeer *cp)
564{
565 struct CadetPeer *peer = cls;
566 GCC_handle_kx (peer, msg);
567}
568
569
570/**
571 * Check if the encrypted message has the appropriate size.
572 *
573 * @param cls Closure (unused).
574 * @param msg Message to check.
575 *
576 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
577 */
578static int
579check_encrypted (void *cls, const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
580{ 481{
581 uint16_t size; 482 struct GNUNET_TIME_Relative exp;
582 uint16_t minimum_size;
583
584 size = ntohs (msg->header.size);
585 minimum_size = sizeof (struct GNUNET_CADET_TunnelEncryptedMessage)
586 + sizeof (struct GNUNET_MessageHeader);
587
588 if (size < minimum_size)
589 {
590 GNUNET_break_op (0);
591 return GNUNET_NO;
592 }
593 return GNUNET_YES;
594}
595 483
596/** 484 if (NULL != cp->destroy_task)
597 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED. 485 {
598 * 486 GNUNET_SCHEDULER_cancel (cp->destroy_task);
599 * @param cls Closure (CadetPeer for neighbor that sent the message). 487 cp->destroy_task = NULL;
600 * @param msg Message itself. 488 }
601 */ 489 if (NULL != cp->t)
602static void 490 return; /* still relevant! */
603handle_encrypted (void *cls, const struct GNUNET_CADET_TunnelEncryptedMessage *msg) 491 if (NULL != cp->core_mq)
604{ 492 return; /* still relevant! */
605 struct CadetPeer *peer = cls; 493 if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
606 GCC_handle_encrypted (peer, msg); 494 return; /* still relevant! */
607} 495 if ( (NULL != cp->path_heap) &&
608 496 (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap)) )
609 497 {
610/** 498 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
611 * To be called on core init/fail. 499 &drop_paths,
612 * 500 cp);
613 * @param cls Closure (config) 501 return;
614 * @param identity The public identity of this peer. 502 }
615 */ 503 if (0 != cp->num_paths)
616static void 504 return; /* still relevant! */
617core_init_notify (void *cls, 505 if (NULL != cp->hello)
618 const struct GNUNET_PeerIdentity *identity); 506 {
619 507 /* relevant only until HELLO expires */
620 508 exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
621static void 509 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
622connect_to_core (const struct GNUNET_CONFIGURATION_Handle *c) 510 &destroy_peer,
623{ 511 cp);
624 struct GNUNET_MQ_MessageHandler core_handlers[] = { 512 return;
625 GNUNET_MQ_hd_var_size (create, 513 }
626 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 514 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
627 struct GNUNET_CADET_ConnectionCreateMessage, 515 &destroy_peer,
628 NULL), 516 cp);
629 GNUNET_MQ_hd_fixed_size (confirm,
630 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
631 struct GNUNET_CADET_ConnectionCreateAckMessage,
632 NULL),
633 GNUNET_MQ_hd_fixed_size (broken,
634 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
635 struct GNUNET_CADET_ConnectionBrokenMessage,
636 NULL),
637 GNUNET_MQ_hd_fixed_size (destroy,
638 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
639 struct GNUNET_CADET_ConnectionDestroyMessage,
640 NULL),
641 GNUNET_MQ_hd_fixed_size (ack,
642 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK,
643 struct GNUNET_CADET_ConnectionEncryptedAckMessage,
644 NULL),
645 GNUNET_MQ_hd_fixed_size (poll,
646 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL,
647 struct GNUNET_CADET_ConnectionHopByHopPollMessage,
648 NULL),
649 GNUNET_MQ_hd_fixed_size (kx,
650 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
651 struct GNUNET_CADET_TunnelKeyExchangeMessage,
652 NULL),
653 GNUNET_MQ_hd_var_size (encrypted,
654 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
655 struct GNUNET_CADET_TunnelEncryptedMessage,
656 NULL),
657 GNUNET_MQ_handler_end ()
658 };
659 core_handle = GNUNET_CORE_connect (c, NULL,
660 &core_init_notify,
661 &core_connect_handler,
662 &core_disconnect_handler,
663 core_handlers);
664}
665
666/******************************************************************************/
667/******************************************************************************/
668/******************************************************************************/
669/******************************************************************************/
670/******************************************************************************/
671
672/**
673 * To be called on core init/fail.
674 *
675 * @param cls Closure (config)
676 * @param identity The public identity of this peer.
677 */
678static void
679core_init_notify (void *cls,
680 const struct GNUNET_PeerIdentity *core_identity)
681{
682 const struct GNUNET_CONFIGURATION_Handle *c = cls;
683
684 LOG (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
685 if (0 != memcmp (core_identity, &my_full_id, sizeof (my_full_id)))
686 {
687 LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
688 LOG (GNUNET_ERROR_TYPE_ERROR, " core id %s\n", GNUNET_i2s (core_identity));
689 LOG (GNUNET_ERROR_TYPE_ERROR, " my id %s\n", GNUNET_i2s (&my_full_id));
690 GNUNET_CORE_disconnect (core_handle);
691 connect_to_core (c);
692 return;
693 }
694 GML_start ();
695} 517}
696 518
697 519
698/******************************************************************************/
699/******************************** STATIC ***********************************/
700/******************************************************************************/
701
702
703/** 520/**
704 * Get priority for a queued message. 521 * Set the message queue to @a mq for peer @a cp and notify watchers.
705 *
706 * @param q Queued message
707 *
708 * @return CORE priority to use.
709 * 522 *
710 * FIXME make static 523 * @param cp peer to modify
711 * FIXME use when sending 524 * @param mq message queue to set (can be NULL)
712 */ 525 */
713enum GNUNET_CORE_Priority 526void
714get_priority (struct CadetPeerQueue *q) 527GCP_set_mq (struct CadetPeer *cp,
715{ 528 struct GNUNET_MQ_Handle *mq)
716 enum GNUNET_CORE_Priority low; 529{
717 enum GNUNET_CORE_Priority high; 530 LOG (GNUNET_ERROR_TYPE_DEBUG,
718 531 "Message queue for peer %s is now %p\n",
719 if (NULL == q) 532 GCP_2s (cp),
720 { 533 mq);
721 GNUNET_break (0); 534 cp->core_mq = mq;
722 return GNUNET_CORE_PRIO_BACKGROUND; 535 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head, *next;
723 } 536 NULL != mqm;
724 537 mqm = next)
725 /* Relayed traffic has lower priority, our own traffic has higher */ 538 {
726 if (NULL == q->c || GNUNET_NO == GCC_is_origin (q->c, q->c_fwd)) 539 /* Save next pointer in case mqm gets freed by the callback */
540 next = mqm->next;
541 if (NULL == mq)
727 { 542 {
728 low = GNUNET_CORE_PRIO_BEST_EFFORT; 543 if (NULL != mqm->env)
729 high = GNUNET_CORE_PRIO_URGENT; 544 {
545 GNUNET_MQ_discard (mqm->env);
546 mqm->env = NULL;
547 mqm->cb (mqm->cb_cls,
548 GNUNET_SYSERR);
549 }
550 else
551 {
552 mqm->cb (mqm->cb_cls,
553 GNUNET_NO);
554 }
730 } 555 }
731 else 556 else
732 { 557 {
733 low = GNUNET_CORE_PRIO_URGENT; 558 GNUNET_assert (NULL == mqm->env);
734 high = GNUNET_CORE_PRIO_CRITICAL_CONTROL; 559 mqm->cb (mqm->cb_cls,
560 GNUNET_YES);
735 } 561 }
562 }
563 if ( (NULL != mq) ||
564 (NULL != cp->t) )
565 consider_peer_activate (cp);
566 else
567 consider_peer_destroy (cp);
736 568
737 /* Bulky payload has lower priority, control traffic has higher. */ 569 if ( (NULL != mq) &&
738 if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == q->type) 570 (NULL != cp->t) )
739 return low; 571 {
740 return high; 572 /* have a new, direct path to the target, notify tunnel */
741} 573 struct CadetPeerPath *path;
742
743
744/**
745 * Cancel all messages queued to CORE MQ towards this peer.
746 *
747 * @param peer Peer towards which to cancel all messages.
748 */
749static void
750cancel_queued_messages (struct CadetPeer *peer)
751{
752 while (NULL != peer->q_head)
753 {
754 struct CadetPeerQueue *q;
755
756 q = peer->q_head;
757 call_peer_cont (q, GNUNET_NO);
758 GNUNET_free (q);
759 }
760}
761
762
763/**
764 * Destroy the peer_info and free any allocated resources linked to it
765 *
766 * @param peer The peer_info to destroy.
767 * @return #GNUNET_OK on success
768 */
769static int
770peer_destroy (struct CadetPeer *peer)
771{
772 struct GNUNET_PeerIdentity id;
773 struct CadetPeerPath *p;
774 struct CadetPeerPath *nextp;
775
776 GNUNET_PEER_resolve (peer->id, &id);
777 GNUNET_PEER_change_rc (peer->id, -1);
778
779 LOG (GNUNET_ERROR_TYPE_INFO,
780 "destroying peer %s\n",
781 GNUNET_i2s (&id));
782
783 if (GNUNET_YES !=
784 GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer))
785 {
786 GNUNET_break (0);
787 LOG (GNUNET_ERROR_TYPE_WARNING, " peer not in peermap!!\n");
788 }
789 GCP_stop_search (peer);
790 p = peer->path_head;
791 while (NULL != p)
792 {
793 nextp = p->next;
794 GNUNET_CONTAINER_DLL_remove (peer->path_head,
795 peer->path_tail,
796 p);
797 path_destroy (p);
798 p = nextp;
799 }
800 if (NULL != peer->tunnel)
801 GCT_destroy_empty (peer->tunnel);
802 if (NULL != peer->connections)
803 {
804 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (peer->connections));
805 GNUNET_CONTAINER_multishortmap_destroy (peer->connections);
806 peer->connections = NULL;
807 }
808 if (NULL != peer->hello_offer)
809 {
810 GNUNET_TRANSPORT_offer_hello_cancel (peer->hello_offer);
811 peer->hello_offer = NULL;
812 }
813 if (NULL != peer->connectivity_suggestion)
814 {
815 GNUNET_ATS_connectivity_suggest_cancel (peer->connectivity_suggestion);
816 peer->connectivity_suggestion = NULL;
817 }
818 cancel_queued_messages (peer);
819 574
820 GNUNET_free_non_null (peer->hello); 575 path = GCPP_get_path_from_route (1,
821 GNUNET_free (peer); 576 &cp->pid);
822 return GNUNET_OK; 577 GCT_consider_path (cp->t,
578 path,
579 0);
580 }
823} 581}
824 582
825 583
826/** 584/**
827 * Iterator over peer hash map entries to destroy the peer during in_shutdown. 585 * Debug function should NEVER return true in production code, useful to
586 * simulate losses for testcases.
828 * 587 *
829 * @param cls closure 588 * @return #GNUNET_YES or #GNUNET_NO with the decision to drop.
830 * @param key current key code
831 * @param value value in the hash map
832 * @return #GNUNET_YES if we should continue to iterate,
833 * #GNUNET_NO if not.
834 */ 589 */
835static int 590static int
836shutdown_peer (void *cls, 591should_I_drop (void)
837 const struct GNUNET_PeerIdentity *key,
838 void *value)
839{ 592{
840 struct CadetPeer *p = value; 593 if (0 == drop_percent)
841 struct CadetTunnel *t = p->tunnel; 594 return GNUNET_NO;
842 595 if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
843 LOG (GNUNET_ERROR_TYPE_DEBUG, " shutting down %s\n", GCP_2s (p)); 596 101) < drop_percent)
844 if (NULL != t)
845 GCT_destroy (t);
846 p->tunnel = NULL;
847 peer_destroy (p);
848 return GNUNET_YES; 597 return GNUNET_YES;
598 return GNUNET_NO;
849} 599}
850 600
851 601
852/** 602/**
853 * Check if peer is searching for a path (either active or delayed search). 603 * Function called when CORE took one of the messages from
854 * 604 * a message queue manager and transmitted it.
855 * @param peer Peer to check
856 * @return #GNUNET_YES if there is a search active.
857 * #GNUNET_NO otherwise.
858 */
859static int
860is_searching (const struct CadetPeer *peer)
861{
862 return ( (NULL == peer->search_h) &&
863 (NULL == peer->search_delayed) ) ?
864 GNUNET_NO : GNUNET_YES;
865}
866
867
868/**
869 * @brief Start a search for a peer.
870 * 605 *
871 * @param cls Closure (Peer to search for). 606 * @param cls the `struct CadetPeeer` where we made progress
872 */ 607 */
873static void 608static void
874delayed_search (void *cls) 609mqm_send_done (void *cls);
875{
876 struct CadetPeer *peer = cls;
877
878 peer->search_delayed = NULL;
879 GCC_check_connections ();
880 GCP_start_search (peer);
881 GCC_check_connections ();
882}
883 610
884 611
885/** 612/**
886 * Returns if peer is used (has a tunnel or is neighbor). 613 * Transmit current envelope from this @a mqm.
887 * 614 *
888 * @param peer Peer to check. 615 * @param mqm mqm to transmit message for now
889 * @return #GNUNET_YES if peer is in use.
890 */ 616 */
891static int 617static void
892peer_is_used (struct CadetPeer *peer) 618mqm_execute (struct GCP_MessageQueueManager *mqm)
893{
894 struct CadetPeerPath *p;
895
896 if (NULL != peer->tunnel)
897 return GNUNET_YES;
898
899 for (p = peer->path_head; NULL != p; p = p->next)
900 {
901 if (p->length < 3)
902 return GNUNET_YES;
903 }
904 return GNUNET_NO;
905}
906
907
908/**
909 * Iterator over all the peers to get the oldest timestamp.
910 *
911 * @param cls Closure (unsued).
912 * @param key ID of the peer.
913 * @param value Peer_Info of the peer.
914 */
915static int
916peer_get_oldest (void *cls,
917 const struct GNUNET_PeerIdentity *key,
918 void *value)
919{ 619{
920 struct CadetPeer *p = value; 620 struct CadetPeer *cp = mqm->cp;
921 struct GNUNET_TIME_Absolute *abs = cls;
922
923 /* Don't count active peers */
924 if (GNUNET_YES == peer_is_used (p))
925 return GNUNET_YES;
926 621
927 if (abs->abs_value_us < p->last_contact.abs_value_us) 622 /* Move ready pointer to the next entry that might be ready. */
928 abs->abs_value_us = p->last_contact.abs_value_us; 623 if ( (mqm == cp->mqm_ready_ptr) &&
929 624 (NULL != mqm->next) )
930 return GNUNET_YES; 625 cp->mqm_ready_ptr = mqm->next;
626 /* Move entry to the end of the DLL, to be fair. */
627 if (mqm != cp->mqm_tail)
628 {
629 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
630 cp->mqm_tail,
631 mqm);
632 GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
633 cp->mqm_tail,
634 mqm);
635 }
636 cp->mqm_ready_counter--;
637 if (GNUNET_YES == should_I_drop ())
638 {
639 LOG (GNUNET_ERROR_TYPE_DEBUG,
640 "DROPPING message to peer %s from MQM %p\n",
641 GCP_2s (cp),
642 mqm);
643 GNUNET_MQ_discard (mqm->env);
644 mqm->env = NULL;
645 mqm_send_done (cp);
646 }
647 else
648 {
649 LOG (GNUNET_ERROR_TYPE_DEBUG,
650 "Sending to peer %s from MQM %p\n",
651 GCP_2s (cp),
652 mqm);
653 GNUNET_MQ_send (cp->core_mq,
654 mqm->env);
655 mqm->env = NULL;
656 }
657 mqm->cb (mqm->cb_cls,
658 GNUNET_YES);
931} 659}
932 660
933 661
934/** 662/**
935 * Iterator over all the peers to remove the oldest entry. 663 * Find the next ready message in the queue (starting
664 * the search from the `cp->mqm_ready_ptr`) and if possible
665 * execute the transmission.
936 * 666 *
937 * @param cls Closure (unsued). 667 * @param cp peer to try to send the next ready message to
938 * @param key ID of the peer.
939 * @param value Peer_Info of the peer.
940 */
941static int
942peer_timeout (void *cls,
943 const struct GNUNET_PeerIdentity *key,
944 void *value)
945{
946 struct CadetPeer *p = value;
947 struct GNUNET_TIME_Absolute *abs = cls;
948
949 LOG (GNUNET_ERROR_TYPE_WARNING,
950 "peer %s timeout\n", GNUNET_i2s (key));
951
952 if (p->last_contact.abs_value_us == abs->abs_value_us &&
953 GNUNET_NO == peer_is_used (p))
954 {
955 peer_destroy (p);
956 return GNUNET_NO;
957 }
958 return GNUNET_YES;
959}
960
961
962/**
963 * Delete oldest unused peer.
964 */ 668 */
965static void 669static void
966peer_delete_oldest (void) 670send_next_ready (struct CadetPeer *cp)
967{ 671{
968 struct GNUNET_TIME_Absolute abs; 672 struct GCP_MessageQueueManager *mqm;
969
970 abs = GNUNET_TIME_UNIT_FOREVER_ABS;
971
972 GNUNET_CONTAINER_multipeermap_iterate (peers,
973 &peer_get_oldest,
974 &abs);
975 GNUNET_CONTAINER_multipeermap_iterate (peers,
976 &peer_timeout,
977 &abs);
978}
979
980 673
981/** 674 if (0 == cp->mqm_ready_counter)
982 * Choose the best (yet unused) path towards a peer, 675 return;
983 * considering the tunnel properties. 676 while ( (NULL != (mqm = cp->mqm_ready_ptr)) &&
984 * 677 (NULL == mqm->env) )
985 * @param peer The destination peer. 678 cp->mqm_ready_ptr = mqm->next;
986 * @return Best current known path towards the peer, if any. 679 if (NULL == mqm)
987 */ 680 return; /* nothing to do */
988static struct CadetPeerPath * 681 mqm_execute (mqm);
989peer_get_best_path (const struct CadetPeer *peer)
990{
991 struct CadetPeerPath *best_p;
992 struct CadetPeerPath *p;
993 unsigned int best_cost;
994 unsigned int cost;
995
996 best_cost = UINT_MAX;
997 best_p = NULL;
998 for (p = peer->path_head; NULL != p; p = p->next)
999 {
1000 if (GNUNET_NO == path_is_valid (p))
1001 continue; /* Don't use invalid paths. */
1002 if (GNUNET_YES == GCT_is_path_used (peer->tunnel, p))
1003 continue; /* If path is already in use, skip it. */
1004
1005 if ((cost = GCT_get_path_cost (peer->tunnel, p)) < best_cost)
1006 {
1007 best_cost = cost;
1008 best_p = p;
1009 }
1010 }
1011 return best_p;
1012} 682}
1013 683
1014 684
1015/** 685/**
1016 * Function to process paths received for a new peer addition. The recorded 686 * Function called when CORE took one of the messages from
1017 * paths form the initial tunnel, which can be optimized later. 687 * a message queue manager and transmitted it.
1018 * Called on each result obtained for the DHT search.
1019 * 688 *
1020 * @param cls Closure (peer towards a path has been found). 689 * @param cls the `struct CadetPeeer` where we made progress
1021 * @param path Path created from the DHT query. Will be freed afterwards.
1022 */ 690 */
1023static void 691static void
1024search_handler (void *cls, const struct CadetPeerPath *path) 692mqm_send_done (void *cls)
1025{ 693{
1026 struct CadetPeer *peer = cls; 694 struct CadetPeer *cp = cls;
1027 unsigned int connection_count;
1028
1029 GCC_check_connections ();
1030 GCP_add_path_to_all (path, GNUNET_NO);
1031
1032 /* Count connections */
1033 connection_count = GCT_count_connections (peer->tunnel);
1034 695
1035 /* If we already have our minimum (or more) connections, it's enough */ 696 LOG (GNUNET_ERROR_TYPE_DEBUG,
1036 if (CONNECTIONS_PER_TUNNEL <= connection_count) 697 "Sending to peer %s completed\n",
1037 { 698 GCP_2s (cp));
1038 GCC_check_connections (); 699 send_next_ready (cp);
1039 return;
1040 }
1041
1042 if (CADET_TUNNEL_SEARCHING == GCT_get_cstate (peer->tunnel))
1043 {
1044 LOG (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
1045 GCP_connect (peer);
1046 }
1047 GCC_check_connections ();
1048}
1049
1050
1051/**
1052 * Test if a message type is connection management traffic
1053 * or regular payload traffic.
1054 *
1055 * @param type Message type.
1056 *
1057 * @return #GNUNET_YES if connection management, #GNUNET_NO otherwise.
1058 */
1059static int
1060is_connection_management (uint16_t type)
1061{
1062 return type == GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK ||
1063 type == GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL;
1064} 700}
1065 701
1066 702
1067/** 703/**
1068 * Debug function should NEVER return true in production code, useful to 704 * Send the message in @a env to @a cp.
1069 * simulate losses for testcases.
1070 * 705 *
1071 * @return #GNUNET_YES or #GNUNET_NO with the decision to drop. 706 * @param mqm the message queue manager to use for transmission
707 * @param env envelope with the message to send; must NOT
708 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
1072 */ 709 */
1073static int 710void
1074should_I_drop (void) 711GCP_send (struct GCP_MessageQueueManager *mqm,
712 struct GNUNET_MQ_Envelope *env)
1075{ 713{
1076 if (0 == drop_percent) 714 struct CadetPeer *cp = mqm->cp;
1077 return GNUNET_NO;
1078 715
1079 if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 101) < drop_percent) 716 GNUNET_assert (NULL != env);
1080 return GNUNET_YES; 717 LOG (GNUNET_ERROR_TYPE_DEBUG,
1081 718 "Queueing message to peer %s in MQM %p\n",
1082 return GNUNET_NO; 719 GCP_2s (cp),
720 mqm);
721 GNUNET_assert (NULL != cp->core_mq);
722 GNUNET_assert (NULL == mqm->env);
723 GNUNET_MQ_notify_sent (env,
724 &mqm_send_done,
725 cp);
726 mqm->env = env;
727 cp->mqm_ready_counter++;
728 if (mqm != cp->mqm_ready_ptr)
729 cp->mqm_ready_ptr = cp->mqm_head;
730 if (1 == cp->mqm_ready_counter)
731 cp->mqm_ready_ptr = mqm;
732 if (0 != GNUNET_MQ_get_length (cp->core_mq))
733 return;
734 send_next_ready (cp);
1083} 735}
1084 736
1085 737
1086/******************************************************************************/
1087/******************************** API ***********************************/
1088/******************************************************************************/
1089
1090/** 738/**
1091 * Call the continuation after a message has been sent or dropped. 739 * Function called to destroy a peer now.
1092 * 740 *
1093 * This funcion removes the message from the queue. 741 * @param cls NULL
1094 * 742 * @param pid identity of the peer (unused)
1095 * @param q Queue handle. 743 * @param value the `struct CadetPeer` to clean up
1096 * @param sent #GNUNET_YES if was sent to CORE, #GNUNET_NO if dropped. 744 * @return #GNUNET_OK (continue to iterate)
1097 */ 745 */
1098static void 746static int
1099call_peer_cont (struct CadetPeerQueue *q, int sent) 747destroy_iterator_cb (void *cls,
1100{ 748 const struct GNUNET_PeerIdentity *pid,
1101 LOG (GNUNET_ERROR_TYPE_DEBUG, " core mq just sent %s\n", GC_m2s (q->type)); 749 void *value)
1102 if (NULL != q->cont)
1103 {
1104 struct GNUNET_TIME_Relative wait_time;
1105
1106 wait_time = GNUNET_TIME_absolute_get_duration (q->queue_timestamp);
1107 LOG (GNUNET_ERROR_TYPE_DEBUG,
1108 " calling callback on %s after %s\n",
1109 GCC_2s (q->c),
1110 GNUNET_STRINGS_relative_time_to_string (wait_time, GNUNET_NO));
1111 q->cont (q->cont_cls,
1112 q->c, q->c_fwd, sent,
1113 q->type,
1114 q->payload_type,
1115 q->payload_id,
1116 q->size, wait_time);
1117 q->cont = NULL;
1118 }
1119 GNUNET_CONTAINER_DLL_remove (q->peer->q_head, q->peer->q_tail, q);
1120}
1121
1122
1123/**
1124 * Function called by MQ when a message is sent to CORE.
1125 *
1126 * @param cls Closure (queue handle).
1127 */
1128static void
1129mq_sent (void *cls)
1130{ 750{
1131 struct CadetPeerQueue *q = cls; 751 struct CadetPeer *cp = value;
1132 752
1133 if (GNUNET_NO == q->management_traffic) 753 if (NULL != cp->destroy_task)
1134 { 754 {
1135 q->peer->queue_n--; 755 GNUNET_SCHEDULER_cancel (cp->destroy_task);
1136 } 756 cp->destroy_task = NULL;
1137 call_peer_cont (q, GNUNET_YES); 757 }
1138 GNUNET_free (q); 758 destroy_peer (cp);
759 return GNUNET_OK;
1139} 760}
1140 761
1141 762
1142/** 763/**
1143 * Finish the drop operation. 764 * Clean up all entries about all peers.
1144 * 765 * Must only be called after all tunnels, CORE-connections and
1145 * @param cls queue entry to finish drop for 766 * connections are down.
1146 */ 767 */
1147static void 768void
1148drop_cb (void *cls) 769GCP_destroy_all_peers ()
1149{ 770{
1150 struct CadetPeerQueue *q = cls; 771 LOG (GNUNET_ERROR_TYPE_DEBUG,
1151 772 "Destroying all peers now\n");
1152 GNUNET_MQ_discard (q->env); 773 GNUNET_CONTAINER_multipeermap_iterate (peers,
1153 call_peer_cont (q, GNUNET_YES); 774 &destroy_iterator_cb,
1154 GNUNET_free (q); 775 NULL);
1155} 776}
1156 777
1157 778
1158/** 779/**
1159 * @brief Send a message to another peer (using CORE). 780 * Drop all paths owned by this peer, and do not
781 * allow new ones to be added: We are shutting down.
1160 * 782 *
1161 * @param peer Peer towards which to queue the message. 783 * @param cp peer to drop paths to
1162 * @param message Message to send.
1163 * @param payload_type Type of the message's payload, for debug messages.
1164 * 0 if the message is a retransmission (unknown payload).
1165 * UINT16_MAX if the message does not have payload.
1166 * @param payload_id ID of the payload (MID, ACK #, etc)
1167 * @param c Connection this message belongs to (can be NULL).
1168 * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!)
1169 * @param cont Continuation to be called once CORE has sent the message.
1170 * @param cont_cls Closure for @c cont.
1171 *
1172 * @return A handle to the message in the queue or NULL (if dropped).
1173 */ 784 */
1174struct CadetPeerQueue * 785void
1175GCP_send (struct CadetPeer *peer, 786GCP_drop_owned_paths (struct CadetPeer *cp)
1176 const struct GNUNET_MessageHeader *message,
1177 uint16_t payload_type,
1178 struct CadetEncryptedMessageIdentifier payload_id,
1179 struct CadetConnection *c,
1180 int fwd,
1181 GCP_sent cont,
1182 void *cont_cls)
1183{ 787{
1184 struct CadetPeerQueue *q; 788 struct CadetPeerPath *path;
1185 uint16_t type;
1186 uint16_t size;
1187
1188 GCC_check_connections ();
1189 type = ntohs (message->type);
1190 size = ntohs (message->size);
1191 LOG (GNUNET_ERROR_TYPE_DEBUG,
1192 "que %s (%s %4u) on conn %s (%p) %s towards %s (size %u)\n",
1193 GC_m2s (type), GC_m2s (payload_type),
1194 ntohl (payload_id.pid),
1195 GCC_2s (c), c, GC_f2s (fwd), GCP_2s (peer), size);
1196
1197 if (NULL == peer->connections)
1198 {
1199 /* We are not connected to this peer, ignore request. */
1200 GNUNET_break (0);
1201 LOG (GNUNET_ERROR_TYPE_INFO, "%s not a neighbor\n", GCP_2s (peer));
1202 GNUNET_STATISTICS_update (stats, "# messages dropped due to wrong hop", 1,
1203 GNUNET_NO);
1204 return NULL;
1205 }
1206 789
1207 q = GNUNET_new (struct CadetPeerQueue); 790 LOG (GNUNET_ERROR_TYPE_DEBUG,
1208 q->env = GNUNET_MQ_msg_copy (message); 791 "Destroying all paths to %s\n",
1209 q->peer = peer; 792 GCP_2s (cp));
1210 q->cont = cont; 793 while (NULL != (path =
1211 q->cont_cls = cont_cls; 794 GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
1212 q->queue_timestamp = GNUNET_TIME_absolute_get (); 795 GCPP_release (path);
1213 q->management_traffic = is_connection_management (type); 796 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
1214 q->type = type; 797 cp->path_heap = NULL;
1215 q->size = size;
1216 q->payload_type = payload_type;
1217 q->payload_id = payload_id;
1218 q->c = c;
1219 q->c_fwd = fwd;
1220 GNUNET_MQ_notify_sent (q->env, &mq_sent, q);
1221 GNUNET_CONTAINER_DLL_insert (peer->q_head, peer->q_tail, q);
1222
1223 if (GNUNET_YES == q->management_traffic)
1224 {
1225 GNUNET_MQ_send (peer->core_mq, q->env); // FIXME implement "_urgent", use
1226 }
1227 else
1228 {
1229 if (GNUNET_YES == should_I_drop ())
1230 {
1231 LOG (GNUNET_ERROR_TYPE_WARNING,
1232 "DD %s (%s %u) on conn %s %s (random drop for testing)\n",
1233 GC_m2s (q->type),
1234 GC_m2s (q->payload_type),
1235 ntohl (q->payload_id.pid),
1236 GCC_2s (c),
1237 GC_f2s (q->c_fwd));
1238 q->drop_task = GNUNET_SCHEDULER_add_now (&drop_cb,
1239 q);
1240 return q;
1241 }
1242 GNUNET_MQ_send (peer->core_mq, q->env);
1243 peer->queue_n++;
1244 }
1245
1246 GCC_check_connections ();
1247 return q;
1248} 798}
1249 799
1250 800
1251/** 801/**
1252 * Cancel sending a message. Message must have been sent with 802 * Add an entry to the DLL of all of the paths that this peer is on.
1253 * #GCP_send before. May not be called after the notify sent
1254 * callback has been called.
1255 *
1256 * It DOES call the continuation given to #GCP_send.
1257 * 803 *
1258 * @param q Queue handle to cancel 804 * @param cp peer to modify
805 * @param entry an entry on a path
806 * @param off offset of this peer on the path
1259 */ 807 */
1260void 808void
1261GCP_send_cancel (struct CadetPeerQueue *q) 809GCP_path_entry_add (struct CadetPeer *cp,
1262{ 810 struct CadetPeerPathEntry *entry,
1263 if (NULL != q->drop_task) 811 unsigned int off)
812{
813 GNUNET_assert (cp == GCPP_get_peer_at_offset (entry->path,
814 off));
815 LOG (GNUNET_ERROR_TYPE_DEBUG,
816 "Discovered that peer %s is on path %s at offset %u\n",
817 GCP_2s (cp),
818 GCPP_2s (entry->path),
819 off);
820 if (off >= cp->path_dll_length)
1264 { 821 {
1265 GNUNET_SCHEDULER_cancel (q->drop_task); 822 unsigned int len = cp->path_dll_length;
1266 q->drop_task = NULL; 823
1267 GNUNET_MQ_discard (q->env); 824 GNUNET_array_grow (cp->path_heads,
825 len,
826 off + 4);
827 GNUNET_array_grow (cp->path_tails,
828 cp->path_dll_length,
829 off + 4);
1268 } 830 }
1269 else 831 GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
832 cp->path_tails[off],
833 entry);
834 cp->off_sum += off;
835 cp->num_paths++;
836
837 /* If we have a tunnel to this peer, tell the tunnel that there is a
838 new path available. */
839 if (NULL != cp->t)
840 GCT_consider_path (cp->t,
841 entry->path,
842 off);
843
844 if ( (NULL != cp->search_h) &&
845 (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths) )
1270 { 846 {
1271 GNUNET_MQ_send_cancel (q->env); 847 /* Now I have enough paths, stop search */
848 GCD_search_stop (cp->search_h);
849 cp->search_h = NULL;
850 }
851 if (NULL != cp->destroy_task)
852 {
853 /* paths changed, this resets the destroy timeout counter
854 and aborts a destroy task that may no longer be valid
855 to have (as we now have more paths via this peer). */
856 consider_peer_destroy (cp);
1272 } 857 }
1273 call_peer_cont (q, GNUNET_NO);
1274 GNUNET_free (q);
1275} 858}
1276 859
1277 860
1278/** 861/**
1279 * Initialize the peer subsystem. 862 * Remove an entry from the DLL of all of the paths that this peer is on.
1280 * 863 *
1281 * @param c Configuration. 864 * @param cp peer to modify
1282 */ 865 * @param entry an entry on a path
1283void 866 * @param off offset of this peer on the path
1284GCP_init (const struct GNUNET_CONFIGURATION_Handle *c)
1285{
1286 cfg = c;
1287 LOG (GNUNET_ERROR_TYPE_DEBUG,
1288 "GCP_init\n");
1289 in_shutdown = GNUNET_NO;
1290 peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
1291 if (GNUNET_OK !=
1292 GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_PEERS",
1293 &max_peers))
1294 {
1295 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1296 "CADET", "MAX_PEERS", "USING DEFAULT");
1297 max_peers = 1000;
1298 }
1299
1300 if (GNUNET_OK !=
1301 GNUNET_CONFIGURATION_get_value_number (c, "CADET", "DROP_PERCENT",
1302 &drop_percent))
1303 {
1304 drop_percent = 0;
1305 }
1306 else
1307 {
1308 LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
1309 LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n");
1310 LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n");
1311 LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n");
1312 LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
1313 }
1314 ats_ch = GNUNET_ATS_connectivity_init (c);
1315 connect_to_core (c);
1316 if (NULL == core_handle)
1317 {
1318 GNUNET_break (0);
1319 GNUNET_SCHEDULER_shutdown ();
1320 }
1321}
1322
1323
1324/**
1325 * Shut down the peer subsystem.
1326 */ 867 */
1327void 868void
1328GCP_shutdown (void) 869GCP_path_entry_remove (struct CadetPeer *cp,
1329{ 870 struct CadetPeerPathEntry *entry,
1330 LOG (GNUNET_ERROR_TYPE_DEBUG, 871 unsigned int off)
1331 "Shutting down peer subsystem\n"); 872{
1332 in_shutdown = GNUNET_YES; 873 LOG (GNUNET_ERROR_TYPE_DEBUG,
1333 if (NULL != core_handle) 874 "Removing knowledge about peer %s beging on path %s at offset %u\n",
1334 { 875 GCP_2s (cp),
1335 GNUNET_CORE_disconnect (core_handle); 876 GCPP_2s (entry->path),
1336 core_handle = NULL; 877 off);
1337 } 878 GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
1338 GNUNET_PEER_change_rc (myid, -1); 879 cp->path_tails[off],
1339 /* With MQ API, CORE calls the disconnect handler for every peer 880 entry);
1340 * after calling GNUNET_CORE_disconnect, shutdown must occur *after* that. 881 GNUNET_assert (0 < cp->num_paths);
1341 */ 882 cp->off_sum -= off;
1342 GNUNET_CONTAINER_multipeermap_iterate (peers, 883 cp->num_paths--;
1343 &shutdown_peer, 884 if ( (NULL == cp->core_mq) &&
1344 NULL); 885 (NULL != cp->t) &&
1345 if (NULL != ats_ch) 886 (NULL == cp->search_h) &&
1346 { 887 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
1347 GNUNET_ATS_connectivity_done (ats_ch); 888 cp->search_h
1348 ats_ch = NULL; 889 = GCD_search (&cp->pid);
1349 } 890 if (NULL == cp->destroy_task)
1350 GNUNET_CONTAINER_multipeermap_destroy (peers); 891 {
1351 peers = NULL; 892 /* paths changed, we might now be ready for destruction, check again */
1352} 893 consider_peer_destroy (cp);
1353 894 }
1354
1355/**
1356 * Retrieve the CadetPeer stucture associated with the peer. Optionally create
1357 * one and insert it in the appropriate structures if the peer is not known yet.
1358 *
1359 * @param peer_id Full identity of the peer.
1360 * @param create #GNUNET_YES if a new peer should be created if unknown.
1361 * #GNUNET_NO otherwise.
1362 *
1363 * @return Existing or newly created peer structure.
1364 * NULL if unknown and not requested @a create
1365 */
1366struct CadetPeer *
1367GCP_get (const struct GNUNET_PeerIdentity *peer_id, int create)
1368{
1369 struct CadetPeer *peer;
1370
1371 peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id);
1372 if (NULL == peer)
1373 {
1374 peer = GNUNET_new (struct CadetPeer);
1375 if (GNUNET_CONTAINER_multipeermap_size (peers) > max_peers)
1376 {
1377 peer_delete_oldest ();
1378 }
1379 GNUNET_assert (GNUNET_OK ==
1380 GNUNET_CONTAINER_multipeermap_put (peers,
1381 peer_id,
1382 peer,
1383 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1384 peer->id = GNUNET_PEER_intern (peer_id);
1385 }
1386 peer->last_contact = GNUNET_TIME_absolute_get ();
1387
1388 return peer;
1389}
1390
1391
1392/**
1393 * Retrieve the CadetPeer stucture associated with the
1394 * peer. Optionally create one and insert it in the appropriate
1395 * structures if the peer is not known yet.
1396 *
1397 * @param peer Short identity of the peer.
1398 * @param create #GNUNET_YES if a new peer should be created if unknown.
1399 * #GNUNET_NO otherwise.
1400 *
1401 * @return Existing or newly created peer structure.
1402 * NULL if unknown and not requested @a create
1403 */
1404struct CadetPeer *
1405GCP_get_short (const GNUNET_PEER_Id peer, int create)
1406{
1407 return GCP_get (GNUNET_PEER_resolve2 (peer), create);
1408} 895}
1409 896
1410 897
1411/** 898/**
1412 * Function called once #GNUNET_TRANSPORT_offer_hello() is done. 899 * Prune down the number of paths to this peer, we seem to
1413 * Marks the operation as finished. 900 * have way too many.
1414 * 901 *
1415 * @param cls Closure (our `struct CadetPeer`). 902 * @param cls the `struct CadetPeer` to maintain the path heap for
1416 */ 903 */
1417static void 904static void
1418hello_offer_done (void *cls) 905path_heap_cleanup (void *cls)
1419{ 906{
1420 struct CadetPeer *peer = cls; 907 struct CadetPeer *cp = cls;
908 struct CadetPeerPath *root;
1421 909
1422 peer->hello_offer = NULL; 910 cp->heap_cleanup_task = NULL;
911 while (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
912 2 * DESIRED_CONNECTIONS_PER_TUNNEL)
913 {
914 /* Now we have way too many, drop least desirable UNLESS it is in use!
915 (Note that this intentionally keeps highly desireable, but currently
916 unused paths around in the hope that we might be able to switch, even
917 if the number of paths exceeds the threshold.) */
918 root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
919 GNUNET_assert (NULL != root);
920 if (NULL !=
921 GCPP_get_connection (root,
922 cp,
923 GCPP_get_length (root) - 1))
924 break; /* can't fix */
925 /* Got plenty of paths to this destination, and this is a low-quality
926 one that we don't care about. Allow it to die. */
927 GNUNET_assert (root ==
928 GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
929 GCPP_release (root);
930 }
1423} 931}
1424 932
1425 933
1426/** 934/**
1427 * Try to establish a new connection to this peer (in its tunnel). 935 * Try adding a @a path to this @a peer. If the peer already
1428 * If the peer doesn't have any path to it yet, try to get one. 936 * has plenty of paths, return NULL.
1429 * If the peer already has some path, send a CREATE CONNECTION towards it.
1430 * 937 *
1431 * @param peer Peer to connect to. 938 * @param cp peer to which the @a path leads to
939 * @param path a path looking for an owner; may not be fully initialized yet!
940 * @param off offset of @a cp in @a path
941 * @param force force attaching the path
942 * @return NULL if this peer does not care to become a new owner,
943 * otherwise the node in the peer's path heap for the @a path.
1432 */ 944 */
1433void 945struct GNUNET_CONTAINER_HeapNode *
1434GCP_connect (struct CadetPeer *peer) 946GCP_attach_path (struct CadetPeer *cp,
947 struct CadetPeerPath *path,
948 unsigned int off,
949 int force)
1435{ 950{
1436 struct CadetTunnel *t; 951 GNUNET_CONTAINER_HeapCostType desirability;
1437 struct CadetPeerPath *path; 952 struct CadetPeerPath *root;
1438 struct CadetConnection *c; 953 GNUNET_CONTAINER_HeapCostType root_desirability;
1439 int rerun_search; 954 struct GNUNET_CONTAINER_HeapNode *hn;
1440
1441 GCC_check_connections ();
1442 LOG (GNUNET_ERROR_TYPE_DEBUG,
1443 "peer_connect towards %s\n",
1444 GCP_2s (peer));
1445 /* If we have a current hello, try to connect using it. */
1446 GCP_try_connect (peer);
1447 955
1448 t = peer->tunnel; 956 GNUNET_assert (off == GCPP_get_length (path) - 1);
1449 c = NULL; 957 GNUNET_assert (cp == GCPP_get_peer_at_offset (path,
1450 rerun_search = GNUNET_NO; 958 off));
1451 959 if (NULL == cp->path_heap)
1452 if (NULL != peer->path_head) 960 {
961 /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */
962 GNUNET_assert (GNUNET_NO == force);
963 return NULL;
964 }
965 desirability = GCPP_get_desirability (path);
966 if (GNUNET_NO == force)
967 {
968 /* FIXME: desirability is not yet initialized; tricky! */
969 if (GNUNET_NO ==
970 GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
971 (void **) &root,
972 &root_desirability))
1453 { 973 {
1454 LOG (GNUNET_ERROR_TYPE_DEBUG, " some path exists\n"); 974 root = NULL;
1455 path = peer_get_best_path (peer); 975 root_desirability = 0;
1456 if (NULL != path)
1457 {
1458 char *s;
1459
1460 s = path_2s (path);
1461 LOG (GNUNET_ERROR_TYPE_DEBUG, " path to use: %s\n", s);
1462 GNUNET_free (s);
1463
1464 c = GCT_use_path (t, path);
1465 if (NULL == c)
1466 {
1467 /* This case can happen when the path includes a first hop that is
1468 * not yet known to be connected.
1469 *
1470 * This happens quite often during testing when running cadet
1471 * under valgrind: core connect notifications come very late
1472 * and the DHT result has already come and created a valid
1473 * path. In this case, the peer->connections
1474 * hashmaps will be NULL and tunnel_use_path will not be able
1475 * to create a connection from that path.
1476 *
1477 * Re-running the DHT GET should give core time to callback.
1478 *
1479 * GCT_use_path -> GCC_new -> register_neighbors takes care of
1480 * updating statistics about this issue.
1481 */
1482 rerun_search = GNUNET_YES;
1483 }
1484 else
1485 {
1486 GCC_send_create (c);
1487 return;
1488 }
1489 }
1490 else
1491 {
1492 LOG (GNUNET_ERROR_TYPE_DEBUG, " but is NULL, all paths are in use\n");
1493 }
1494 } 976 }
1495 977
1496 if (GNUNET_YES == rerun_search) 978 if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
979 (desirability < root_desirability) )
1497 { 980 {
1498 struct GNUNET_TIME_Relative delay; 981 LOG (GNUNET_ERROR_TYPE_DEBUG,
1499 982 "Decided to not attach path %p to peer %s due to undesirability\n",
1500 GCP_stop_search (peer); 983 GCPP_2s (path),
1501 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100); 984 GCP_2s (cp));
1502 peer->search_delayed = GNUNET_SCHEDULER_add_delayed (delay, 985 return NULL;
1503 &delayed_search,
1504 peer);
1505 GCC_check_connections ();
1506 return;
1507 } 986 }
987 }
1508 988
1509 if (GNUNET_NO == is_searching (peer)) 989 LOG (GNUNET_ERROR_TYPE_DEBUG,
1510 GCP_start_search (peer); 990 "Attaching path %s to peer %s (%s)\n",
1511 GCC_check_connections (); 991 GCPP_2s (path),
1512} 992 GCP_2s (cp),
1513 993 (GNUNET_NO == force) ? "desirable" : "forced");
1514
1515/**
1516 * Chech whether there is a direct (core level) connection to peer.
1517 *
1518 * @param peer Peer to check.
1519 *
1520 * @return #GNUNET_YES if there is a direct connection.
1521 */
1522int
1523GCP_is_neighbor (const struct CadetPeer *peer)
1524{
1525 struct CadetPeerPath *path;
1526
1527 if (NULL == peer->connections)
1528 return GNUNET_NO;
1529 994
1530 for (path = peer->path_head; NULL != path; path = path->next) 995 /* Yes, we'd like to add this path, add to our heap */
1531 { 996 hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
1532 if (3 > path->length) 997 path,
1533 return GNUNET_YES; 998 desirability);
1534 }
1535 999
1536 /* Is not a neighbor but connections is not NULL, probably disconnecting */ 1000 /* Consider maybe dropping other paths because of the new one */
1537 return GNUNET_NO; 1001 if ( (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
1002 2 * DESIRED_CONNECTIONS_PER_TUNNEL) &&
1003 (NULL != cp->heap_cleanup_task) )
1004 cp->heap_cleanup_task = GNUNET_SCHEDULER_add_now (&path_heap_cleanup,
1005 cp);
1006 return hn;
1538} 1007}
1539 1008
1540 1009
1541/** 1010/**
1542 * Create and initialize a new tunnel towards a peer, in case it has none. 1011 * This peer can no longer own @a path as the path
1543 * In case the peer already has a tunnel, nothing is done. 1012 * has been extended and a peer further down the line
1013 * is now the new owner.
1544 * 1014 *
1545 * Does not generate any traffic, just creates the local data structures. 1015 * @param cp old owner of the @a path
1546 * 1016 * @param path path where the ownership is lost
1547 * @param peer Peer towards which to create the tunnel. 1017 * @param hn note in @a cp's path heap that must be deleted
1548 */ 1018 */
1549void 1019void
1550GCP_add_tunnel (struct CadetPeer *peer) 1020GCP_detach_path (struct CadetPeer *cp,
1021 struct CadetPeerPath *path,
1022 struct GNUNET_CONTAINER_HeapNode *hn)
1551{ 1023{
1552 GCC_check_connections (); 1024 LOG (GNUNET_ERROR_TYPE_DEBUG,
1553 if (NULL != peer->tunnel) 1025 "Detatching path %s from peer %s\n",
1554 return; 1026 GCPP_2s (path),
1555 peer->tunnel = GCT_new (peer); 1027 GCP_2s (cp));
1556 GCC_check_connections (); 1028 GNUNET_assert (path ==
1029 GNUNET_CONTAINER_heap_remove_node (hn));
1557} 1030}
1558 1031
1559 1032
1560/** 1033/**
1561 * Add a connection to a neighboring peer. 1034 * Add a @a connection to this @a cp.
1562 *
1563 * Store that the peer is the first hop of the connection in one
1564 * direction and that on peer disconnect the connection must be
1565 * notified and destroyed, for it will no longer be valid.
1566 * 1035 *
1567 * @param peer Peer to add connection to. 1036 * @param cp peer via which the @a connection goes
1568 * @param c Connection to add. 1037 * @param cc the connection to add
1569 * @param pred #GNUNET_YES if we are predecessor, #GNUNET_NO if we are successor
1570 */ 1038 */
1571void 1039void
1572GCP_add_connection (struct CadetPeer *peer, 1040GCP_add_connection (struct CadetPeer *cp,
1573 struct CadetConnection *c, 1041 struct CadetConnection *cc)
1574 int pred) 1042{
1575{ 1043 LOG (GNUNET_ERROR_TYPE_DEBUG,
1576 LOG (GNUNET_ERROR_TYPE_DEBUG, 1044 "Adding connection %s to peer %s\n",
1577 "adding connection %s\n", 1045 GCC_2s (cc),
1578 GCC_2s (c)); 1046 GCP_2s (cp));
1579 LOG (GNUNET_ERROR_TYPE_DEBUG, 1047 GNUNET_assert (GNUNET_OK ==
1580 "to peer %s\n", 1048 GNUNET_CONTAINER_multishortmap_put (cp->connections,
1581 GCP_2s (peer)); 1049 &GCC_get_id (cc)->connection_of_tunnel,
1582 GNUNET_assert (NULL != peer->connections); 1050 cc,
1583 GNUNET_assert (GNUNET_OK == 1051 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1584 GNUNET_CONTAINER_multishortmap_put (peer->connections, 1052 if (NULL != cp->destroy_task)
1585 &GCC_get_id (c)->connection_of_tunnel, 1053 {
1586 c, 1054 GNUNET_SCHEDULER_cancel (cp->destroy_task);
1587 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 1055 cp->destroy_task = NULL;
1588 LOG (GNUNET_ERROR_TYPE_DEBUG, 1056 }
1589 "Peer %s has now %u connections.\n",
1590 GCP_2s (peer),
1591 GNUNET_CONTAINER_multishortmap_size (peer->connections));
1592}
1593
1594
1595/**
1596 * Add the path to the peer and update the path used to reach it in case this
1597 * is the shortest.
1598 *
1599 * @param peer Destination peer to add the path to.
1600 * @param path New path to add. Last peer must be @c peer.
1601 * Path will be either used of freed if already known.
1602 * @param trusted Do we trust that this path is real?
1603 *
1604 * @return path if path was taken, pointer to existing duplicate if exists
1605 * NULL on error.
1606 */
1607struct CadetPeerPath *
1608GCP_add_path (struct CadetPeer *peer,
1609 struct CadetPeerPath *path,
1610 int trusted)
1611{
1612 struct CadetPeerPath *aux;
1613 unsigned int l;
1614 unsigned int l2;
1615
1616 GCC_check_connections ();
1617 LOG (GNUNET_ERROR_TYPE_DEBUG,
1618 "adding path [%u] to peer %s\n",
1619 path->length, GCP_2s (peer));
1620
1621 if (NULL == peer || NULL == path
1622 || path->peers[path->length - 1] != peer->id)
1623 {
1624 GNUNET_break (0);
1625 path_destroy (path);
1626 return NULL;
1627 }
1628
1629 for (l = 1; l < path->length; l++)
1630 {
1631 if (path->peers[l] == myid)
1632 {
1633 LOG (GNUNET_ERROR_TYPE_DEBUG, " shortening path by %u\n", l);
1634 for (l2 = 0; l2 < path->length - l; l2++)
1635 {
1636 path->peers[l2] = path->peers[l + l2];
1637 }
1638 path->length -= l;
1639 l = 1;
1640 path->peers = GNUNET_realloc (path->peers,
1641 path->length * sizeof (GNUNET_PEER_Id));
1642 }
1643 }
1644
1645 LOG (GNUNET_ERROR_TYPE_DEBUG, " final length: %u\n", path->length);
1646
1647 if (2 >= path->length && GNUNET_NO == trusted)
1648 {
1649 /* Only allow CORE to tell us about direct paths */
1650 path_destroy (path);
1651 return NULL;
1652 }
1653
1654 l = path_get_length (path);
1655 if (0 == l)
1656 {
1657 path_destroy (path);
1658 return NULL;
1659 }
1660
1661 GNUNET_assert (peer->id == path->peers[path->length - 1]);
1662 for (aux = peer->path_head; aux != NULL; aux = aux->next)
1663 {
1664 l2 = path_get_length (aux);
1665 if (l2 > l)
1666 {
1667 LOG (GNUNET_ERROR_TYPE_DEBUG, " added\n");
1668 GNUNET_CONTAINER_DLL_insert_before (peer->path_head,
1669 peer->path_tail, aux, path);
1670 goto finish;
1671 }
1672 else
1673 {
1674 if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
1675 {
1676 LOG (GNUNET_ERROR_TYPE_DEBUG, " already known\n");
1677 path_destroy (path);
1678 return aux;
1679 }
1680 }
1681 }
1682 GNUNET_CONTAINER_DLL_insert_tail (peer->path_head,
1683 peer->path_tail,
1684 path);
1685 LOG (GNUNET_ERROR_TYPE_DEBUG, " added last\n");
1686
1687finish:
1688 if (NULL != peer->tunnel
1689 && CONNECTIONS_PER_TUNNEL > GCT_count_connections (peer->tunnel)
1690 && 2 < path->length) /* Direct paths are handled by core_connect */
1691 {
1692 GCP_connect (peer);
1693 }
1694 GCC_check_connections ();
1695 return path;
1696} 1057}
1697 1058
1698 1059
1699/** 1060/**
1700 * Add the path to the origin peer and update the path used to reach it in case 1061 * Remove a @a connection that went via this @a cp.
1701 * this is the shortest.
1702 * The path is given in peer_info -> destination, therefore we turn the path
1703 * upside down first.
1704 *
1705 * @param peer Peer to add the path to, being the origin of the path.
1706 * @param path New path to add after being inversed.
1707 * Path will be either used or freed.
1708 * @param trusted Do we trust that this path is real?
1709 * 1062 *
1710 * @return path if path was taken, pointer to existing duplicate if exists 1063 * @param cp peer via which the @a connection went
1711 * NULL on error. 1064 * @param cc the connection to remove
1712 */ 1065 */
1713struct CadetPeerPath * 1066void
1714GCP_add_path_to_origin (struct CadetPeer *peer, 1067GCP_remove_connection (struct CadetPeer *cp,
1715 struct CadetPeerPath *path, 1068 struct CadetConnection *cc)
1716 int trusted)
1717{ 1069{
1718 if (NULL == path) 1070 LOG (GNUNET_ERROR_TYPE_DEBUG,
1719 return NULL; 1071 "Removing connection %s from peer %s\n",
1720 path_invert (path); 1072 GCC_2s (cc),
1721 return GCP_add_path (peer, path, trusted); 1073 GCP_2s (cp));
1074 GNUNET_assert (GNUNET_YES ==
1075 GNUNET_CONTAINER_multishortmap_remove (cp->connections,
1076 &GCC_get_id (cc)->connection_of_tunnel,
1077 cc));
1078 consider_peer_destroy (cp);
1722} 1079}
1723 1080
1724 1081
1725/** 1082/**
1726 * Adds a path to the info of all the peers in the path 1083 * Retrieve the CadetPeer stucture associated with the
1084 * peer. Optionally create one and insert it in the appropriate
1085 * structures if the peer is not known yet.
1727 * 1086 *
1728 * @param p Path to process. 1087 * @param peer_id Full identity of the peer.
1729 * @param confirmed Whether we know if the path works or not. 1088 * @param create #GNUNET_YES if a new peer should be created if unknown.
1089 * #GNUNET_NO to return NULL if peer is unknown.
1090 * @return Existing or newly created peer structure.
1091 * NULL if unknown and not requested @a create
1730 */ 1092 */
1731void 1093struct CadetPeer *
1732GCP_add_path_to_all (const struct CadetPeerPath *p, int confirmed) 1094GCP_get (const struct GNUNET_PeerIdentity *peer_id,
1095 int create)
1733{ 1096{
1734 unsigned int i; 1097 struct CadetPeer *cp;
1735 1098
1736 /* TODO: invert and add to origin */ 1099 cp = GNUNET_CONTAINER_multipeermap_get (peers,
1737 /* TODO: replace all "GCP_add_path" with this, make the other one static */ 1100 peer_id);
1738 GCC_check_connections (); 1101 if (NULL != cp)
1739 for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ; 1102 return cp;
1740 for (i++; i < p->length; i++) 1103 if (GNUNET_NO == create)
1741 { 1104 return NULL;
1742 struct CadetPeer *peer; 1105 cp = GNUNET_new (struct CadetPeer);
1743 struct CadetPeerPath *copy; 1106 cp->pid = *peer_id;
1744 1107 cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
1745 peer = GCP_get_short (p->peers[i], GNUNET_YES); 1108 GNUNET_YES);
1746 copy = path_duplicate (p); 1109 cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1747 copy->length = i + 1; 1110 GNUNET_assert (GNUNET_YES ==
1748 GCP_add_path (peer, copy, 3 > p->length ? GNUNET_NO : confirmed); 1111 GNUNET_CONTAINER_multipeermap_put (peers,
1749 } 1112 &cp->pid,
1750 GCC_check_connections (); 1113 cp,
1114 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1115 LOG (GNUNET_ERROR_TYPE_DEBUG,
1116 "Creating peer %s\n",
1117 GCP_2s (cp));
1118 return cp;
1751} 1119}
1752 1120
1753 1121
1754/** 1122/**
1755 * Remove any path to the peer that has the exact same peers as the one given. 1123 * Obtain the peer identity for a `struct CadetPeer`.
1756 * 1124 *
1757 * @param peer Peer to remove the path from. 1125 * @param cp our peer handle
1758 * @param path Path to remove. Is always destroyed . 1126 * @return the peer identity
1759 */ 1127 */
1760void 1128const struct GNUNET_PeerIdentity *
1761GCP_remove_path (struct CadetPeer *peer, 1129GCP_get_id (struct CadetPeer *cp)
1762 struct CadetPeerPath *path)
1763{ 1130{
1764 struct CadetPeerPath *iter; 1131 return &cp->pid;
1765 struct CadetPeerPath *next;
1766
1767 GCC_check_connections ();
1768 GNUNET_assert (myid == path->peers[0]);
1769 GNUNET_assert (peer->id == path->peers[path->length - 1]);
1770
1771 LOG (GNUNET_ERROR_TYPE_INFO,
1772 "Removing path %p (%u) from %s\n",
1773 path, path->length, GCP_2s (peer));
1774
1775 for (iter = peer->path_head; NULL != iter; iter = next)
1776 {
1777 next = iter->next;
1778 if (0 == path_cmp (path, iter))
1779 {
1780 GNUNET_CONTAINER_DLL_remove (peer->path_head,
1781 peer->path_tail,
1782 iter);
1783 if (iter != path)
1784 path_destroy (iter);
1785 }
1786 }
1787 path_destroy (path);
1788 GCC_check_connections ();
1789} 1132}
1790 1133
1791 1134
1792/** 1135/**
1793 * Check that we are aware of a connection from a neighboring peer. 1136 * Iterate over all known peers.
1794 * 1137 *
1795 * @param peer Peer to the connection is with 1138 * @param iter Iterator.
1796 * @param c Connection that should be in the map with this peer. 1139 * @param cls Closure for @c iter.
1797 */ 1140 */
1798void 1141void
1799GCP_check_connection (const struct CadetPeer *peer, 1142GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
1800 const struct CadetConnection *c) 1143 void *cls)
1801{ 1144{
1802 GNUNET_assert (NULL != peer); 1145 GNUNET_CONTAINER_multipeermap_iterate (peers,
1803 GNUNET_assert (NULL != peer->connections); 1146 iter,
1804 return; // ???? 1147 cls);
1805 GNUNET_assert (GNUNET_YES ==
1806 GNUNET_CONTAINER_multishortmap_contains_value (peer->connections,
1807 &GCC_get_id (c)->connection_of_tunnel,
1808 c));
1809} 1148}
1810 1149
1811 1150
1812/** 1151/**
1813 * Remove a connection from a neighboring peer. 1152 * Count the number of known paths toward the peer.
1814 * 1153 *
1815 * @param peer Peer to remove connection from. 1154 * @param cp Peer to get path info.
1816 * @param c Connection to remove. 1155 * @return Number of known paths.
1817 */ 1156 */
1818void 1157unsigned int
1819GCP_remove_connection (struct CadetPeer *peer, 1158GCP_count_paths (const struct CadetPeer *cp)
1820 const struct CadetConnection *c)
1821{ 1159{
1822 LOG (GNUNET_ERROR_TYPE_DEBUG, 1160 return cp->num_paths;
1823 "Removing connection %s\n",
1824 GCC_2s (c));
1825 LOG (GNUNET_ERROR_TYPE_DEBUG,
1826 "from peer %s\n",
1827 GCP_2s (peer));
1828 if ( (NULL == peer) ||
1829 (NULL == peer->connections) )
1830 return;
1831 GNUNET_assert (GNUNET_YES ==
1832 GNUNET_CONTAINER_multishortmap_remove (peer->connections,
1833 &GCC_get_id (c)->connection_of_tunnel,
1834 c));
1835 LOG (GNUNET_ERROR_TYPE_DEBUG,
1836 "Peer %s remains with %u connections.\n",
1837 GCP_2s (peer),
1838 GNUNET_CONTAINER_multishortmap_size (peer->connections));
1839} 1161}
1840 1162
1841 1163
1842/** 1164/**
1843 * Start the DHT search for new paths towards the peer: we don't have 1165 * Iterate over the paths to a peer.
1844 * enough good connections.
1845 * 1166 *
1846 * @param peer Destination peer. 1167 * @param cp Peer to get path info.
1168 * @param callback Function to call for every path.
1169 * @param callback_cls Closure for @a callback.
1170 * @return Number of iterated paths.
1847 */ 1171 */
1848void 1172unsigned int
1849GCP_start_search (struct CadetPeer *peer) 1173GCP_iterate_paths (struct CadetPeer *cp,
1174 GCP_PathIterator callback,
1175 void *callback_cls)
1850{ 1176{
1851 const struct GNUNET_PeerIdentity *id; 1177 unsigned int ret = 0;
1852 struct CadetTunnel *t = peer->tunnel;
1853
1854 GCC_check_connections ();
1855 if (NULL != peer->search_h)
1856 {
1857 GNUNET_break (0);
1858 return;
1859 }
1860
1861 if (NULL != peer->search_delayed)
1862 GCP_stop_search (peer);
1863
1864 id = GNUNET_PEER_resolve2 (peer->id);
1865 peer->search_h = GCD_search (id, &search_handler, peer);
1866
1867 if (NULL == t)
1868 {
1869 /* Why would we search for a peer with no tunnel towards it? */
1870 GNUNET_break (0);
1871 return;
1872 }
1873
1874 if (CADET_TUNNEL_NEW == GCT_get_cstate (t)
1875 || 0 == GCT_count_any_connections (t))
1876 {
1877 GCT_change_cstate (t, CADET_TUNNEL_SEARCHING);
1878 }
1879 GCC_check_connections ();
1880}
1881 1178
1179 LOG (GNUNET_ERROR_TYPE_DEBUG,
1180 "Iterating over paths to peer %s%s\n",
1181 GCP_2s (cp),
1182 (NULL == cp->core_mq) ? "" : " including direct link");
1183 if (NULL != cp->core_mq)
1184 {
1185 struct CadetPeerPath *path;
1882 1186
1883/** 1187 path = GCPP_get_path_from_route (1,
1884 * Stop the DHT search for new paths towards the peer: we already have 1188 &cp->pid);
1885 * enough good connections. 1189 ret++;
1886 * 1190 if (GNUNET_NO ==
1887 * @param peer Destination peer. 1191 callback (callback_cls,
1888 */ 1192 path,
1889void 1193 0))
1890GCP_stop_search (struct CadetPeer *peer) 1194 return ret;
1891{ 1195 }
1892 GCC_check_connections (); 1196 for (unsigned int i=0;i<cp->path_dll_length;i++)
1893 if (NULL != peer->search_h) 1197 {
1894 { 1198 for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1895 GCD_search_stop (peer->search_h); 1199 NULL != pe;
1896 peer->search_h = NULL; 1200 pe = pe->next)
1897 }
1898 if (NULL != peer->search_delayed)
1899 { 1201 {
1900 GNUNET_SCHEDULER_cancel (peer->search_delayed); 1202 ret++;
1901 peer->search_delayed = NULL; 1203 if (GNUNET_NO ==
1204 callback (callback_cls,
1205 pe->path,
1206 i))
1207 return ret;
1902 } 1208 }
1903 GCC_check_connections (); 1209 }
1904} 1210 return ret;
1905
1906
1907/**
1908 * Get the Full ID of a peer.
1909 *
1910 * @param peer Peer to get from.
1911 *
1912 * @return Full ID of peer.
1913 */
1914const struct GNUNET_PeerIdentity *
1915GCP_get_id (const struct CadetPeer *peer)
1916{
1917 return GNUNET_PEER_resolve2 (peer->id);
1918} 1211}
1919 1212
1920 1213
1921/** 1214/**
1922 * Get the Short ID of a peer. 1215 * Iterate over the paths to @a cp where
1923 * 1216 * @a cp is at distance @a dist from us.
1924 * @param peer Peer to get from.
1925 * 1217 *
1926 * @return Short ID of peer. 1218 * @param cp Peer to get path info.
1219 * @param dist desired distance of @a cp to us on the path
1220 * @param callback Function to call for every path.
1221 * @param callback_cls Closure for @a callback.
1222 * @return Number of iterated paths.
1927 */ 1223 */
1928GNUNET_PEER_Id 1224unsigned int
1929GCP_get_short_id (const struct CadetPeer *peer) 1225GCP_iterate_paths_at (struct CadetPeer *cp,
1226 unsigned int dist,
1227 GCP_PathIterator callback,
1228 void *callback_cls)
1930{ 1229{
1931 return peer->id; 1230 unsigned int ret = 0;
1932}
1933
1934 1231
1935/** 1232 if (dist >= cp->path_dll_length)
1936 * Set tunnel. 1233 {
1937 * 1234 LOG (GNUNET_ERROR_TYPE_DEBUG,
1938 * If tunnel is NULL and there was a search active, stop it, as it's useless. 1235 "Asked to look for paths at distance %u, but maximum for me is < %u\n",
1939 * 1236 dist,
1940 * @param peer Peer. 1237 cp->path_dll_length);
1941 * @param t Tunnel. 1238 return 0;
1942 */ 1239 }
1943void 1240 for (struct CadetPeerPathEntry *pe = cp->path_heads[dist];
1944GCP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel *t) 1241 NULL != pe;
1945{ 1242 pe = pe->next)
1946 peer->tunnel = t; 1243 {
1947 if (NULL == t && GNUNET_YES == is_searching (peer)) 1244 if (GNUNET_NO ==
1948 { 1245 callback (callback_cls,
1949 GCP_stop_search (peer); 1246 pe->path,
1950 } 1247 dist))
1248 return ret;
1249 ret++;
1250 }
1251 return ret;
1951} 1252}
1952 1253
1953 1254
1954/** 1255/**
1955 * Get the tunnel towards a peer. 1256 * Get the tunnel towards a peer.
1956 * 1257 *
1957 * @param peer Peer to get from. 1258 * @param cp Peer to get from.
1958 * 1259 * @param create #GNUNET_YES to create a tunnel if we do not have one
1959 * @return Tunnel towards peer. 1260 * @return Tunnel towards peer.
1960 */ 1261 */
1961struct CadetTunnel * 1262struct CadetTunnel *
1962GCP_get_tunnel (const struct CadetPeer *peer) 1263GCP_get_tunnel (struct CadetPeer *cp,
1264 int create)
1963{ 1265{
1964 if (NULL == peer) 1266 if (NULL == cp)
1965 return NULL; 1267 return NULL;
1966 return peer->tunnel; 1268 if ( (NULL != cp->t) ||
1269 (GNUNET_NO == create) )
1270 return cp->t;
1271 cp->t = GCT_create_tunnel (cp);
1272 consider_peer_activate (cp);
1273 return cp->t;
1967} 1274}
1968 1275
1969 1276
1970/** 1277/**
1971 * Set the hello message. 1278 * Hello offer was passed to the transport service. Mark it
1279 * as done.
1972 * 1280 *
1973 * @param peer Peer whose message to set. 1281 * @param cls the `struct CadetPeer` where the offer completed
1974 * @param hello Hello message.
1975 */ 1282 */
1976void 1283static void
1977GCP_set_hello (struct CadetPeer *peer, 1284hello_offer_done (void *cls)
1978 const struct GNUNET_HELLO_Message *hello)
1979{ 1285{
1980 struct GNUNET_HELLO_Message *old; 1286 struct CadetPeer *cp = cls;
1981 size_t size;
1982 1287
1983 GCC_check_connections (); 1288 cp->hello_offer = NULL;
1984 LOG (GNUNET_ERROR_TYPE_DEBUG, "set hello for %s\n", GCP_2s (peer));
1985 if (NULL == hello)
1986 return;
1987
1988 old = GCP_get_hello (peer);
1989 if (NULL == old)
1990 {
1991 size = GNUNET_HELLO_size (hello);
1992 peer->hello = GNUNET_malloc (size);
1993 GNUNET_memcpy (peer->hello, hello, size);
1994 }
1995 else
1996 {
1997 peer->hello = GNUNET_HELLO_merge (old, hello);
1998 GNUNET_free (old);
1999 }
2000 GCC_check_connections ();
2001} 1289}
2002 1290
2003 1291
2004/** 1292/**
2005 * Get the hello message. 1293 * We got a HELLO for a @a peer, remember it, and possibly
2006 * 1294 * trigger adequate actions (like trying to connect).
2007 * @param peer Peer whose message to get.
2008 * 1295 *
2009 * @return Hello message. 1296 * @param cp the peer we got a HELLO for
1297 * @param hello the HELLO to remember
2010 */ 1298 */
2011struct GNUNET_HELLO_Message * 1299void
2012GCP_get_hello (struct CadetPeer *peer) 1300GCP_set_hello (struct CadetPeer *cp,
1301 const struct GNUNET_HELLO_Message *hello)
2013{ 1302{
2014 struct GNUNET_TIME_Absolute expiration; 1303 struct GNUNET_HELLO_Message *mrg;
2015 struct GNUNET_TIME_Relative remaining;
2016
2017 if (NULL == peer->hello)
2018 return NULL;
2019 1304
2020 expiration = GNUNET_HELLO_get_last_expiration (peer->hello); 1305 LOG (GNUNET_ERROR_TYPE_DEBUG,
2021 remaining = GNUNET_TIME_absolute_get_remaining (expiration); 1306 "Got %u byte HELLO for peer %s\n",
2022 if (0 == remaining.rel_value_us) 1307 (unsigned int) GNUNET_HELLO_size (hello),
2023 { 1308 GCP_2s (cp));
2024 LOG (GNUNET_ERROR_TYPE_DEBUG, " get - hello expired on %s\n", 1309 if (NULL != cp->hello_offer)
2025 GNUNET_STRINGS_absolute_time_to_string (expiration)); 1310 {
2026 GNUNET_free (peer->hello); 1311 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
2027 peer->hello = NULL; 1312 cp->hello_offer = NULL;
2028 } 1313 }
2029 return peer->hello; 1314 if (NULL != cp->hello)
1315 {
1316 mrg = GNUNET_HELLO_merge (hello,
1317 cp->hello);
1318 GNUNET_free (cp->hello);
1319 cp->hello = mrg;
1320 }
1321 else
1322 {
1323 cp->hello = GNUNET_memdup (hello,
1324 GNUNET_HELLO_size (hello));
1325 }
1326 cp->hello_offer
1327 = GNUNET_TRANSPORT_offer_hello (cfg,
1328 GNUNET_HELLO_get_header (cp->hello) ,
1329 &hello_offer_done,
1330 cp);
1331 /* New HELLO means cp's destruction time may change... */
1332 consider_peer_destroy (cp);
2030} 1333}
2031 1334
2032 1335
2033/** 1336/**
2034 * Try to connect to a peer on TRANSPORT level. 1337 * The tunnel to the given peer no longer exists, remove it from our
1338 * data structures, and possibly clean up the peer itself.
2035 * 1339 *
2036 * @param peer Peer to whom to connect. 1340 * @param cp the peer affected
1341 * @param t the dead tunnel
2037 */ 1342 */
2038void 1343void
2039GCP_try_connect (struct CadetPeer *peer) 1344GCP_drop_tunnel (struct CadetPeer *cp,
1345 struct CadetTunnel *t)
2040{ 1346{
2041 struct GNUNET_HELLO_Message *hello; 1347 LOG (GNUNET_ERROR_TYPE_DEBUG,
2042 struct GNUNET_MessageHeader *mh; 1348 "Dropping tunnel %s to peer %s\n",
2043 1349 GCT_2s (t),
2044 if (GNUNET_YES != 1350 GCP_2s (cp));
2045 GNUNET_CONFIGURATION_get_value_yesno (cfg, 1351 GNUNET_assert (cp->t == t);
2046 "CADET", 1352 cp->t = NULL;
2047 "DISABLE_TRY_CONNECT")) 1353 consider_peer_destroy (cp);
2048 return;
2049 GCC_check_connections ();
2050 if (GNUNET_YES == GCP_is_neighbor (peer))
2051 return;
2052 hello = GCP_get_hello (peer);
2053 if (NULL == hello)
2054 return;
2055
2056 mh = GNUNET_HELLO_get_header (hello);
2057 if (NULL != peer->hello_offer)
2058 {
2059 GNUNET_TRANSPORT_offer_hello_cancel (peer->hello_offer);
2060 peer->hello_offer = NULL;
2061 }
2062 peer->hello_offer = GNUNET_TRANSPORT_offer_hello (cfg,
2063 mh,
2064 &hello_offer_done,
2065 peer);
2066 if (NULL == peer->connectivity_suggestion)
2067 peer->connectivity_suggestion
2068 = GNUNET_ATS_connectivity_suggest (ats_ch,
2069 GCP_get_id (peer),
2070 1); /* strength */
2071 GCC_check_connections ();
2072} 1354}
2073 1355
2074 1356
2075/** 1357/**
2076 * Notify a peer that a link between two other peers is broken. If any path 1358 * Test if @a cp has a core-level connection
2077 * used that link, eliminate it.
2078 * 1359 *
2079 * @param peer Peer affected by the change. 1360 * @param cp peer to test
2080 * @param peer1 Peer whose link is broken. 1361 * @return #GNUNET_YES if @a cp has a core-level connection
2081 * @param peer2 Peer whose link is broken.
2082 */ 1362 */
2083void 1363int
2084GCP_notify_broken_link (struct CadetPeer *peer, 1364GCP_has_core_connection (struct CadetPeer *cp)
2085 const struct GNUNET_PeerIdentity *peer1,
2086 const struct GNUNET_PeerIdentity *peer2)
2087{ 1365{
2088 struct CadetPeerPath *iter; 1366 return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
2089 struct CadetPeerPath *next;
2090 unsigned int i;
2091 GNUNET_PEER_Id p1;
2092 GNUNET_PEER_Id p2;
2093
2094 GCC_check_connections ();
2095 p1 = GNUNET_PEER_search (peer1);
2096 p2 = GNUNET_PEER_search (peer2);
2097
2098 LOG (GNUNET_ERROR_TYPE_DEBUG, "Link %u-%u broken\n", p1, p2);
2099 if (0 == p1 || 0 == p2)
2100 {
2101 /* We don't even know them */
2102 return;
2103 }
2104
2105 for (iter = peer->path_head; NULL != iter; iter = next)
2106 {
2107 next = iter->next;
2108 for (i = 0; i < iter->length - 1; i++)
2109 {
2110 if ((iter->peers[i] == p1 && iter->peers[i + 1] == p2)
2111 || (iter->peers[i] == p2 && iter->peers[i + 1] == p1))
2112 {
2113 char *s;
2114
2115 s = path_2s (iter);
2116 LOG (GNUNET_ERROR_TYPE_DEBUG, " - invalidating %s\n", s);
2117 GNUNET_free (s);
2118
2119 path_invalidate (iter);
2120 }
2121 }
2122 }
2123 GCC_check_connections ();
2124} 1367}
2125 1368
2126 1369
2127/** 1370/**
2128 * Count the number of known paths toward the peer. 1371 * Start message queue change notifications.
2129 *
2130 * @param peer Peer to get path info.
2131 * 1372 *
2132 * @return Number of known paths. 1373 * @param cp peer to notify for
1374 * @param cb function to call if mq becomes available or unavailable
1375 * @param cb_cls closure for @a cb
1376 * @return handle to cancel request
2133 */ 1377 */
2134unsigned int 1378struct GCP_MessageQueueManager *
2135GCP_count_paths (const struct CadetPeer *peer) 1379GCP_request_mq (struct CadetPeer *cp,
1380 GCP_MessageQueueNotificationCallback cb,
1381 void *cb_cls)
2136{ 1382{
2137 struct CadetPeerPath *iter; 1383 struct GCP_MessageQueueManager *mqm;
2138 unsigned int i;
2139 1384
2140 for (iter = peer->path_head, i = 0; NULL != iter; iter = iter->next) 1385 mqm = GNUNET_new (struct GCP_MessageQueueManager);
2141 i++; 1386 mqm->cb = cb;
2142 1387 mqm->cb_cls = cb_cls;
2143 return i; 1388 mqm->cp = cp;
1389 GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
1390 cp->mqm_tail,
1391 mqm);
1392 LOG (GNUNET_ERROR_TYPE_DEBUG,
1393 "Creating MQM %p for peer %s\n",
1394 mqm,
1395 GCP_2s (cp));
1396 if (NULL != cp->core_mq)
1397 cb (cb_cls,
1398 GNUNET_YES);
1399 return mqm;
2144} 1400}
2145 1401
2146 1402
2147/** 1403/**
2148 * Iterate over the paths to a peer. 1404 * Stops message queue change notifications.
2149 * 1405 *
2150 * @param peer Peer to get path info. 1406 * @param mqm handle matching request to cancel
2151 * @param callback Function to call for every path. 1407 * @param last_env final message to transmit, or NULL
2152 * @param cls Closure for @a callback.
2153 *
2154 * @return Number of iterated paths.
2155 */ 1408 */
2156unsigned int 1409void
2157GCP_iterate_paths (struct CadetPeer *peer, 1410GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
2158 GCP_path_iterator callback, 1411 struct GNUNET_MQ_Envelope *last_env)
2159 void *cls) 1412{
2160{ 1413 struct CadetPeer *cp = mqm->cp;
2161 struct CadetPeerPath *iter; 1414
2162 unsigned int i; 1415 LOG (GNUNET_ERROR_TYPE_DEBUG,
2163 1416 "Destroying MQM %p for peer %s%s\n",
2164 for (iter = peer->path_head, i = 0; NULL != iter; iter = iter->next) 1417 mqm,
1418 GCP_2s (cp),
1419 (NULL == last_env) ? "" : " with last ditch transmission");
1420 if (NULL != mqm->env)
1421 GNUNET_MQ_discard (mqm->env);
1422 if (NULL != last_env)
1423 {
1424 if (NULL != cp->core_mq)
2165 { 1425 {
2166 i++; 1426 GNUNET_MQ_notify_sent (last_env,
2167 if (GNUNET_YES != callback (cls, peer, iter)) 1427 &mqm_send_done,
2168 break; 1428 cp);
1429 GNUNET_MQ_send (cp->core_mq,
1430 last_env);
2169 } 1431 }
2170 1432 else
2171 return i; 1433 {
1434 GNUNET_MQ_discard (last_env);
1435 }
1436 }
1437 if (cp->mqm_ready_ptr == mqm)
1438 cp->mqm_ready_ptr = mqm->next;
1439 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1440 cp->mqm_tail,
1441 mqm);
1442 GNUNET_free (mqm);
2172} 1443}
2173 1444
2174 1445
2175/** 1446/**
2176 * Iterate all known peers. 1447 * Send the message in @a env to @a cp, overriding queueing logic.
1448 * This function should only be used to send error messages outside
1449 * of flow and congestion control, similar to ICMP. Note that
1450 * the envelope may be silently discarded as well.
2177 * 1451 *
2178 * @param iter Iterator. 1452 * @param cp peer to send the message to
2179 * @param cls Closure for @c iter. 1453 * @param env envelope with the message to send
2180 */ 1454 */
2181void 1455void
2182GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, 1456GCP_send_ooo (struct CadetPeer *cp,
2183 void *cls) 1457 struct GNUNET_MQ_Envelope *env)
2184{ 1458{
2185 GCC_check_connections (); 1459 LOG (GNUNET_ERROR_TYPE_DEBUG,
2186 GNUNET_CONTAINER_multipeermap_iterate (peers, 1460 "Sending message to %s out of management\n",
2187 iter, 1461 GCP_2s (cp));
2188 cls); 1462 if (NULL == cp->core_mq)
2189 GCC_check_connections (); 1463 {
1464 GNUNET_MQ_discard (env);
1465 return;
1466 }
1467 GNUNET_MQ_notify_sent (env,
1468 &mqm_send_done,
1469 cp);
1470 GNUNET_MQ_send (cp->core_mq,
1471 env);
2190} 1472}
2191 1473
2192 1474
2193/**
2194 * Get the static string for a peer ID.
2195 *
2196 * @param peer Peer.
2197 *
2198 * @return Static string for it's ID.
2199 */
2200const char *
2201GCP_2s (const struct CadetPeer *peer)
2202{
2203 if (NULL == peer)
2204 return "(NULL)";
2205 return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id));
2206}
2207 1475
2208 1476
2209/* end of gnunet-service-cadet_peer.c */ 1477/* end of gnunet-service-cadet-new_peer.c */
diff --git a/src/cadet/gnunet-service-cadet_peer.h b/src/cadet/gnunet-service-cadet_peer.h
index 1e206e10f..a2a6c6a92 100644
--- a/src/cadet/gnunet-service-cadet_peer.h
+++ b/src/cadet/gnunet-service-cadet_peer.h
@@ -1,6 +1,7 @@
1
1/* 2/*
2 This file is part of GNUnet. 3 This file is part of GNUnet.
3 Copyright (C) 2013 GNUnet e.V. 4 Copyright (C) 2001-2017 GNUnet e.V.
4 5
5 GNUnet is free software; you can redistribute it and/or modify 6 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 7 it under the terms of the GNU General Public License as published
@@ -19,465 +20,375 @@
19*/ 20*/
20 21
21/** 22/**
22 * @file cadet/gnunet-service-cadet_peer.h 23 * @file cadet/gnunet-service-cadet-new_peer.h
23 * @brief cadet service; dealing with remote peers 24 * @brief Information we track per peer.
24 * @author Bartlomiej Polot 25 * @author Bartlomiej Polot
25 * 26 * @author Christian Grothoff
26 * All functions in this file should use the prefix GMP (Gnunet Cadet Peer)
27 */ 27 */
28
29#ifndef GNUNET_SERVICE_CADET_PEER_H 28#ifndef GNUNET_SERVICE_CADET_PEER_H
30#define GNUNET_SERVICE_CADET_PEER_H 29#define GNUNET_SERVICE_CADET_PEER_H
31 30
32#ifdef __cplusplus 31#include "gnunet-service-cadet.h"
33extern "C" 32#include "gnunet_hello_lib.h"
34{
35#if 0 /* keep Emacsens' auto-indent happy */
36}
37#endif
38#endif
39
40#include "platform.h"
41#include "gnunet_util_lib.h"
42#include "cadet_path.h"
43
44/**
45 * Struct containing all information regarding a given peer
46 */
47struct CadetPeer;
48 33
49/**
50 * Handle to queued messages on a peer level.
51 */
52struct CadetPeerQueue;
53
54#include "gnunet-service-cadet_connection.h"
55
56
57/**
58 * Callback called when a queued message is sent.
59 *
60 * @param cls Closure.
61 * @param c Connection this message was on.
62 * @param fwd Was this a FWD going message?
63 * @param sent Was it really sent? (Could have been canceled)
64 * @param type Type of message sent.
65 * @param payload_type Type of payload, if applicable.
66 * @param pid Message ID, or 0 if not applicable (create, destroy, etc).
67 * @param size Size of the message.
68 * @param wait Time spent waiting for core (only the time for THIS message)
69 */
70typedef void
71(*GCP_sent) (void *cls,
72 struct CadetConnection *c,
73 int fwd,
74 int sent,
75 uint16_t type,
76 uint16_t payload_type,
77 struct CadetEncryptedMessageIdentifier pid,
78 size_t size,
79 struct GNUNET_TIME_Relative wait);
80 34
81/** 35/**
82 * Peer path iterator. 36 * Get the static string for a peer ID.
83 * 37 *
84 * @param cls Closure. 38 * @param peer Peer.
85 * @param peer Peer this path is towards.
86 * @param path Path itself
87 * @return #GNUNET_YES if should keep iterating.
88 * #GNUNET_NO otherwise.
89 */
90typedef int
91(*GCP_path_iterator) (void *cls,
92 struct CadetPeer *peer,
93 struct CadetPeerPath *path);
94
95
96/******************************************************************************/
97/******************************** API ***********************************/
98/******************************************************************************/
99
100/**
101 * Initialize peer subsystem.
102 * 39 *
103 * @param c Configuration. 40 * @return Static string for it's ID.
104 */
105void
106GCP_init (const struct GNUNET_CONFIGURATION_Handle *c);
107
108/**
109 * Shut down the peer subsystem.
110 */ 41 */
111void 42const char *
112GCP_shutdown (void); 43GCP_2s (const struct CadetPeer *peer);
113 44
114 45
115/** 46/**
116 * Retrieve the CadetPeer stucture associated with the peer. Optionally create 47 * Retrieve the CadetPeer stucture associated with the
117 * one and insert it in the appropriate structures if the peer is not known yet. 48 * peer. Optionally create one and insert it in the appropriate
49 * structures if the peer is not known yet.
118 * 50 *
119 * @param peer_id Full identity of the peer. 51 * @param peer_id Full identity of the peer.
120 * @param create #GNUNET_YES if a new peer should be created if unknown. 52 * @param create #GNUNET_YES if a new peer should be created if unknown.
121 * #GNUNET_NO otherwise. 53 * #GNUNET_NO to return NULL if peer is unknown.
122 *
123 * @return Existing or newly created peer structure. 54 * @return Existing or newly created peer structure.
124 * NULL if unknown and not requested @a create 55 * NULL if unknown and not requested @a create
125 */ 56 */
126struct CadetPeer * 57struct CadetPeer *
127GCP_get (const struct GNUNET_PeerIdentity *peer_id, int create); 58GCP_get (const struct GNUNET_PeerIdentity *peer_id,
59 int create);
128 60
129 61
130/** 62/**
131 * Retrieve the CadetPeer stucture associated with the peer. Optionally create 63 * Calculate how desirable a path is for @a cp if
132 * one and insert it in the appropriate structures if the peer is not known yet. 64 * @a cp is at offset @a off in the path.
133 *
134 * @param peer Short identity of the peer.
135 * @param create #GNUNET_YES if a new peer should be created if unknown.
136 * #GNUNET_NO otherwise.
137 * 65 *
138 * @return Existing or newly created peer structure. 66 * @param cp a peer reachable via a path
139 * NULL if unknown and not requested @a create 67 * @param off offset of @a cp in a path
68 * @return score how useful a path is to reach @a cp,
69 * positive scores mean path is more desirable
140 */ 70 */
141struct CadetPeer * 71double
142GCP_get_short (const GNUNET_PEER_Id peer, int create); 72GCP_get_desirability_of_path (struct CadetPeer *cp,
143 73 unsigned int off);
144 74
145/**
146 * Try to establish a new connection to this peer (in its tunnel).
147 * If the peer doesn't have any path to it yet, try to get one.
148 * If the peer already has some path, send a CREATE CONNECTION towards it.
149 *
150 * @param peer Peer to connect to.
151 */
152void
153GCP_connect (struct CadetPeer *peer);
154 75
155/** 76/**
156 * @brief Send a message to another peer (using CORE). 77 * Obtain the peer identity for a `struct CadetPeer`.
157 * 78 *
158 * @param peer Peer towards which to queue the message. 79 * @param cp our peer handle
159 * @param message Message to send. 80 * @return the peer identity
160 * @param payload_type Type of the message's payload, for debug messages.
161 * 0 if the message is a retransmission (unknown payload).
162 * UINT16_MAX if the message does not have payload.
163 * @param payload_id ID of the payload (MID, ACK #, etc)
164 * @param c Connection this message belongs to (can be NULL).
165 * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!)
166 * @param cont Continuation to be called once CORE has sent the message.
167 * @param cont_cls Closure for @c cont.
168 */ 81 */
169struct CadetPeerQueue * 82const struct GNUNET_PeerIdentity *
170GCP_send (struct CadetPeer *peer, 83GCP_get_id (struct CadetPeer *cp);
171 const struct GNUNET_MessageHeader *message,
172 uint16_t payload_type,
173 struct CadetEncryptedMessageIdentifier payload_id,
174 struct CadetConnection *c,
175 int fwd,
176 GCP_sent cont,
177 void *cont_cls);
178 84
179/**
180 * Cancel sending a message. Message must have been sent with
181 * #GCP_send before. May not be called after the notify sent
182 * callback has been called.
183 *
184 * It does NOT call the continuation given to #GCP_send.
185 *
186 * @param q Queue handle to cancel
187 */
188void
189GCP_send_cancel (struct CadetPeerQueue *q);
190 85
191/** 86/**
192 * Set tunnel. 87 * Iterate over all known peers.
193 * 88 *
194 * @param peer Peer. 89 * @param iter Iterator.
195 * @param t Tunnel. 90 * @param cls Closure for @c iter.
196 */ 91 */
197void 92void
198GCP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel *t); 93GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
94 void *cls);
199 95
200 96
201/** 97/**
202 * Check whether there is a direct (core level) connection to peer. 98 * Count the number of known paths toward the peer.
203 *
204 * @param peer Peer to check.
205 * 99 *
206 * @return #GNUNET_YES if there is a direct connection. 100 * @param cp Peer to get path info.
101 * @return Number of known paths.
207 */ 102 */
208int 103unsigned int
209GCP_is_neighbor (const struct CadetPeer *peer); 104GCP_count_paths (const struct CadetPeer *cp);
210 105
211 106
212/** 107/**
213 * Create and initialize a new tunnel towards a peer, in case it has none. 108 * Drop all paths owned by this peer, and do not
214 * 109 * allow new ones to be added: We are shutting down.
215 * Does not generate any traffic, just creates the local data structures.
216 * 110 *
217 * @param peer Peer towards which to create the tunnel. 111 * @param cp peer to drop paths to
218 */ 112 */
219void 113void
220GCP_add_tunnel (struct CadetPeer *peer); 114GCP_drop_owned_paths (struct CadetPeer *cp);
221 115
222 116
223/** 117/**
224 * Add a connection to a neighboring peer. 118 * Peer path iterator.
225 *
226 * Store that the peer is the first hop of the connection in one
227 * direction and that on peer disconnect the connection must be
228 * notified and destroyed, for it will no longer be valid.
229 * 119 *
230 * @param peer Peer to add connection to. 120 * @param cls Closure.
231 * @param c Connection to add. 121 * @param path Path itself
232 * @param pred #GNUNET_YES if we are predecessor, #GNUNET_NO if we are successor 122 * @param off offset of the target peer in @a path
123 * @return #GNUNET_YES if should keep iterating.
124 * #GNUNET_NO otherwise.
233 */ 125 */
234void 126typedef int
235GCP_add_connection (struct CadetPeer *peer, 127(*GCP_PathIterator) (void *cls,
236 struct CadetConnection *c, 128 struct CadetPeerPath *path,
237 int pred); 129 unsigned int off);
238 130
239 131
240/** 132/**
241 * Add the path to the peer and update the path used to reach it in case this 133 * Iterate over the paths to a peer.
242 * is the shortest.
243 *
244 * @param peer Destination peer to add the path to.
245 * @param path New path to add. Last peer must be the peer in arg 1.
246 * Path will be either used of freed if already known.
247 * @param trusted Do we trust that this path is real?
248 * 134 *
249 * @return path if path was taken, pointer to existing duplicate if exists 135 * @param cp Peer to get path info.
250 * NULL on error. 136 * @param callback Function to call for every path.
137 * @param callback_cls Closure for @a callback.
138 * @return Number of iterated paths.
251 */ 139 */
252struct CadetPeerPath * 140unsigned int
253GCP_add_path (struct CadetPeer *peer, 141GCP_iterate_paths (struct CadetPeer *cp,
254 struct CadetPeerPath *p, 142 GCP_PathIterator callback,
255 int trusted); 143 void *callback_cls);
256 144
257 145
258/** 146/**
259 * Add the path to the origin peer and update the path used to reach it in case 147 * Iterate over the paths to @a peer where
260 * this is the shortest. 148 * @a peer is at distance @a dist from us.
261 * The path is given in peer_info -> destination, therefore we turn the path
262 * upside down first.
263 * 149 *
264 * @param peer Peer to add the path to, being the origin of the path. 150 * @param cp Peer to get path info.
265 * @param path New path to add after being inversed. 151 * @param dist desired distance of @a peer to us on the path
266 * Path will be either used or freed. 152 * @param callback Function to call for every path.
267 * @param trusted Do we trust that this path is real? 153 * @param callback_cls Closure for @a callback.
268 * 154 * @return Number of iterated paths.
269 * @return path if path was taken, pointer to existing duplicate if exists
270 * NULL on error.
271 */ 155 */
272struct CadetPeerPath * 156unsigned int
273GCP_add_path_to_origin (struct CadetPeer *peer, 157GCP_iterate_paths_at (struct CadetPeer *cp,
274 struct CadetPeerPath *path, 158 unsigned int dist,
275 int trusted); 159 GCP_PathIterator callback,
160 void *callback_cls);
161
276 162
277/** 163/**
278 * Adds a path to the info of all the peers in the path 164 * Remove an entry from the DLL of all of the paths that this peer is on.
279 * 165 *
280 * @param p Path to process. 166 * @param cp peer to modify
281 * @param confirmed Whether we know if the path works or not. 167 * @param entry an entry on a path
168 * @param off offset of this peer on the path
282 */ 169 */
283void 170void
284GCP_add_path_to_all (const struct CadetPeerPath *p, int confirmed); 171GCP_path_entry_remove (struct CadetPeer *cp,
172 struct CadetPeerPathEntry *entry,
173 unsigned int off);
285 174
286 175
287/** 176/**
288 * Remove any path to the peer that has the extact same peers as the one given. 177 * Add an entry to the DLL of all of the paths that this peer is on.
289 * 178 *
290 * @param peer Peer to remove the path from. 179 * @param cp peer to modify
291 * @param path Path to remove. Is always destroyed . 180 * @param entry an entry on a path
181 * @param off offset of this peer on the path
292 */ 182 */
293void 183void
294GCP_remove_path (struct CadetPeer *peer, 184GCP_path_entry_add (struct CadetPeer *cp,
295 struct CadetPeerPath *path); 185 struct CadetPeerPathEntry *entry,
186 unsigned int off);
296 187
297 188
298/** 189/**
299 * Check that we are aware of a connection from a neighboring peer. 190 * Get the tunnel towards a peer.
300 * 191 *
301 * @param peer Peer to the connection is with 192 * @param cp Peer to get from.
302 * @param c Connection that should be in the map with this peer. 193 * @param create #GNUNET_YES to create a tunnel if we do not have one
194 * @return Tunnel towards peer.
303 */ 195 */
304void 196struct CadetTunnel *
305GCP_check_connection (const struct CadetPeer *peer, 197GCP_get_tunnel (struct CadetPeer *cp,
306 const struct CadetConnection *c); 198 int create);
307 199
308 200
309/** 201/**
310 * Remove a connection from a neighboring peer. 202 * The tunnel to the given peer no longer exists, remove it from our
203 * data structures, and possibly clean up the peer itself.
311 * 204 *
312 * @param peer Peer to remove connection from. 205 * @param cp the peer affected
313 * @param c Connection to remove. 206 * @param t the dead tunnel
314 */ 207 */
315void 208void
316GCP_remove_connection (struct CadetPeer *peer, 209GCP_drop_tunnel (struct CadetPeer *cp,
317 const struct CadetConnection *c); 210 struct CadetTunnel *t);
318 211
319 212
320/** 213/**
321 * Start the DHT search for new paths towards the peer: we don't have 214 * Try adding a @a path to this @a cp. If the peer already
322 * enough good connections. 215 * has plenty of paths, return NULL.
323 * 216 *
324 * @param peer Destination peer. 217 * @param cp peer to which the @a path leads to
218 * @param path a path looking for an owner; may not be fully initialized yet!
219 * @param off offset of @a cp in @a path
220 * @param force for attaching the path
221 * @return NULL if this peer does not care to become a new owner,
222 * otherwise the node in the peer's path heap for the @a path.
325 */ 223 */
326void 224struct GNUNET_CONTAINER_HeapNode *
327GCP_start_search (struct CadetPeer *peer); 225GCP_attach_path (struct CadetPeer *cp,
226 struct CadetPeerPath *path,
227 unsigned int off,
228 int force);
328 229
329 230
330/** 231/**
331 * Stop the DHT search for new paths towards the peer: we already have 232 * This peer can no longer own @a path as the path
332 * enough good connections. 233 * has been extended and a peer further down the line
234 * is now the new owner.
333 * 235 *
334 * @param peer Destination peer. 236 * @param cp old owner of the @a path
237 * @param path path where the ownership is lost
238 * @param hn note in @a cp's path heap that must be deleted
335 */ 239 */
336void 240void
337GCP_stop_search (struct CadetPeer *peer); 241GCP_detach_path (struct CadetPeer *cp,
242 struct CadetPeerPath *path,
243 struct GNUNET_CONTAINER_HeapNode *hn);
338 244
339 245
340/** 246/**
341 * Get the Full ID of a peer. 247 * Add a @a connection to this @a cp.
342 *
343 * @param peer Peer to get from.
344 * 248 *
345 * @return Full ID of peer. 249 * @param cp peer via which the @a connection goes
250 * @param cc the connection to add
346 */ 251 */
347const struct GNUNET_PeerIdentity * 252void
348GCP_get_id (const struct CadetPeer *peer); 253GCP_add_connection (struct CadetPeer *cp,
254 struct CadetConnection *cc);
349 255
350 256
351/** 257/**
352 * Get the Short ID of a peer. 258 * Remove a @a connection that went via this @a cp.
353 * 259 *
354 * @param peer Peer to get from. 260 * @param cp peer via which the @a connection went
355 * 261 * @param cc the connection to remove
356 * @return Short ID of peer.
357 */ 262 */
358GNUNET_PEER_Id 263void
359GCP_get_short_id (const struct CadetPeer *peer); 264GCP_remove_connection (struct CadetPeer *cp,
265 struct CadetConnection *cc);
360 266
361 267
362/** 268/**
363 * Get the tunnel towards a peer. 269 * We got a HELLO for a @a cp, remember it, and possibly
364 * 270 * trigger adequate actions (like trying to connect).
365 * @param peer Peer to get from.
366 * 271 *
367 * @return Tunnel towards peer. 272 * @param cp the peer we got a HELLO for
273 * @param hello the HELLO to remember
368 */ 274 */
369struct CadetTunnel * 275void
370GCP_get_tunnel (const struct CadetPeer *peer); 276GCP_set_hello (struct CadetPeer *cp,
277 const struct GNUNET_HELLO_Message *hello);
371 278
372 279
373/** 280/**
374 * Set the hello message. 281 * Clean up all entries about all peers.
375 * 282 * Must only be called after all tunnels, CORE-connections and
376 * @param peer Peer whose message to set. 283 * connections are down.
377 * @param hello Hello message.
378 */ 284 */
379void 285void
380GCP_set_hello (struct CadetPeer *peer, 286GCP_destroy_all_peers (void);
381 const struct GNUNET_HELLO_Message *hello);
382 287
383 288
384/** 289/**
385 * Get the hello message. 290 * Data structure used to track whom we have to notify about changes
386 * 291 * in our ability to transmit to a given peer.
387 * @param peer Peer whose message to get.
388 * 292 *
389 * @return Hello message. 293 * All queue managers will be given equal chance for sending messages
294 * to @a cp. This construct this guarantees fairness for access to @a
295 * cp among the different message queues. Each connection or route
296 * will have its respective message queue managers for each direction.
390 */ 297 */
391struct GNUNET_HELLO_Message * 298struct GCP_MessageQueueManager;
392GCP_get_hello (struct CadetPeer *peer);
393 299
394 300
395/** 301/**
396 * Try to connect to a peer on TRANSPORT level. 302 * Function to call with updated message queue object.
397 * 303 *
398 * @param peer Peer to whom to connect. 304 * @param cls closure
305 * @param available #GNUNET_YES if sending is now possible,
306 * #GNUNET_NO if sending is no longer possible
307 * #GNUNET_SYSERR if sending is no longer possible
308 * and the last envelope was discarded
399 */ 309 */
400void 310typedef void
401GCP_try_connect (struct CadetPeer *peer); 311(*GCP_MessageQueueNotificationCallback)(void *cls,
312 int available);
313
402 314
403/** 315/**
404 * Notify a peer that a link between two other peers is broken. If any path 316 * Start message queue change notifications. Will create a new slot
405 * used that link, eliminate it. 317 * to manage the message queue to the given @a cp.
406 * 318 *
407 * @param peer Peer affected by the change. 319 * @param cp peer to notify for
408 * @param peer1 Peer whose link is broken. 320 * @param cb function to call if mq becomes available or unavailable
409 * @param peer2 Peer whose link is broken. 321 * @param cb_cls closure for @a cb
322 * @return handle to cancel request
410 */ 323 */
411void 324struct GCP_MessageQueueManager *
412GCP_notify_broken_link (struct CadetPeer *peer, 325GCP_request_mq (struct CadetPeer *cp,
413 const struct GNUNET_PeerIdentity *peer1, 326 GCP_MessageQueueNotificationCallback cb,
414 const struct GNUNET_PeerIdentity *peer2); 327 void *cb_cls);
415 328
416 329
417/** 330/**
418 * Count the number of known paths toward the peer. 331 * Test if @a cp has a core-level connection
419 *
420 * @param peer Peer to get path info.
421 * 332 *
422 * @return Number of known paths. 333 * @param cp peer to test
334 * @return #GNUNET_YES if @a cp has a core-level connection
423 */ 335 */
424unsigned int 336int
425GCP_count_paths (const struct CadetPeer *peer); 337GCP_has_core_connection (struct CadetPeer *cp);
338
426 339
427/** 340/**
428 * Iterate over the paths to a peer. 341 * Send the message in @a env via a @a mqm. Must only be called at
429 * 342 * most once after the respective
430 * @param peer Peer to get path info. 343 * #GCP_MessageQueueNotificationCallback was called with `available`
431 * @param callback Function to call for every path. 344 * set to #GNUNET_YES, and not after the callback was called with
432 * @param cls Closure for @a callback. 345 * `available` set to #GNUNET_NO or #GNUNET_SYSERR.
433 * 346 *
434 * @return Number of iterated paths. 347 * @param mqm message queue manager for the transmission
348 * @param env envelope with the message to send; must NOT
349 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
435 */ 350 */
436unsigned int 351void
437GCP_iterate_paths (struct CadetPeer *peer, 352GCP_send (struct GCP_MessageQueueManager *mqm,
438 GCP_path_iterator callback, 353 struct GNUNET_MQ_Envelope *env);
439 void *cls);
440 354
441 355
442/** 356/**
443 * Iterate all known peers. 357 * Send the message in @a env to @a cp, overriding queueing logic.
358 * This function should only be used to send error messages outside
359 * of flow and congestion control, similar to ICMP. Note that
360 * the envelope may be silently discarded as well.
444 * 361 *
445 * @param iter Iterator. 362 * @param cp peer to send the message to
446 * @param cls Closure for @c iter. 363 * @param env envelope with the message to send
447 */ 364 */
448void 365void
449GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, 366GCP_send_ooo (struct CadetPeer *cp,
450 void *cls); 367 struct GNUNET_MQ_Envelope *env);
451 368
452 369
453/** 370/**
454 * Get the static string for a peer ID. 371 * Stops message queue change notifications and sends a last message.
455 * 372 * In practice, this is implemented by sending that @a last_env
456 * @param peer Peer. 373 * message immediately (if any), ignoring queue order.
457 * 374 *
458 * @return Static string for it's ID. 375 * @param mqm handle matching request to cancel
376 * @param last_env final message to transmit, or NULL
459 */ 377 */
460const char * 378void
461GCP_2s (const struct CadetPeer *peer); 379GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
380 struct GNUNET_MQ_Envelope *last_env);
462 381
463 382
464/** 383/**
465 * Log all kinds of info about a peer. 384 * Set the message queue to @a mq for peer @a cp and notify watchers.
466 * 385 *
467 * @param peer Peer. 386 * @param cp peer to modify
387 * @param mq message queue to set (can be NULL)
468 */ 388 */
469void 389void
470GCP_debug (const struct CadetPeer *p, 390GCP_set_mq (struct CadetPeer *cp,
471 enum GNUNET_ErrorType level); 391 struct GNUNET_MQ_Handle *mq);
472
473 392
474#if 0 /* keep Emacsens' auto-indent happy */
475{
476#endif
477#ifdef __cplusplus
478}
479#endif
480 393
481/* ifndef GNUNET_CADET_SERVICE_PEER_H */
482#endif 394#endif
483/* end of gnunet-cadet-service_peer.h */
diff --git a/src/cadet/gnunet-service-cadet_tunnel.c b/src/cadet/gnunet-service-cadet_tunnel.c
deleted file mode 100644
index a94e8f4ff..000000000
--- a/src/cadet/gnunet-service-cadet_tunnel.c
+++ /dev/null
@@ -1,3501 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file cadet/gnunet-service-cadet_tunnel.c
22 * @brief logical links between CADET clients
23 * @author Bartlomiej Polot
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_signatures.h"
28#include "gnunet_statistics_service.h"
29#include "cadet_protocol.h"
30#include "cadet_path.h"
31#include "gnunet-service-cadet_tunnel.h"
32#include "gnunet-service-cadet_connection.h"
33#include "gnunet-service-cadet_channel.h"
34#include "gnunet-service-cadet_peer.h"
35
36#define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__)
37#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-tun",__VA_ARGS__)
38
39#define REKEY_WAIT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5)
40
41#if !defined(GNUNET_CULL_LOGGING)
42 #define DUMP_KEYS_TO_STDERR GNUNET_YES
43#else
44 #define DUMP_KEYS_TO_STDERR GNUNET_NO
45#endif
46
47#define MIN_TUNNEL_BUFFER 8
48#define MAX_TUNNEL_BUFFER 64
49#define MAX_SKIPPED_KEYS 64
50#define MAX_KEY_GAP 256
51#define AX_HEADER_SIZE (sizeof (uint32_t) * 2\
52 + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey))
53
54/******************************************************************************/
55/******************************** STRUCTS **********************************/
56/******************************************************************************/
57
58struct CadetTChannel
59{
60 struct CadetTChannel *next;
61 struct CadetTChannel *prev;
62 struct CadetChannel *ch;
63};
64
65
66/**
67 * Entry in list of connections used by tunnel, with metadata.
68 */
69struct CadetTConnection
70{
71 /**
72 * Next in DLL.
73 */
74 struct CadetTConnection *next;
75
76 /**
77 * Prev in DLL.
78 */
79 struct CadetTConnection *prev;
80
81 /**
82 * Connection handle.
83 */
84 struct CadetConnection *c;
85
86 /**
87 * Creation time, to keep oldest connection alive.
88 */
89 struct GNUNET_TIME_Absolute created;
90
91 /**
92 * Connection throughput, to keep fastest connection alive.
93 */
94 uint32_t throughput;
95};
96
97
98/**
99 * Struct to old keys for skipped messages while advancing the Axolotl ratchet.
100 */
101struct CadetTunnelSkippedKey
102{
103 /**
104 * DLL next.
105 */
106 struct CadetTunnelSkippedKey *next;
107
108 /**
109 * DLL prev.
110 */
111 struct CadetTunnelSkippedKey *prev;
112
113 /**
114 * When was this key stored (for timeout).
115 */
116 struct GNUNET_TIME_Absolute timestamp;
117
118 /**
119 * Header key.
120 */
121 struct GNUNET_CRYPTO_SymmetricSessionKey HK;
122
123 /**
124 * Message key.
125 */
126 struct GNUNET_CRYPTO_SymmetricSessionKey MK;
127
128 /**
129 * Key number for a given HK.
130 */
131 unsigned int Kn;
132};
133
134
135/**
136 * Axolotl data, according to https://github.com/trevp/axolotl/wiki .
137 */
138struct CadetTunnelAxolotl
139{
140 /**
141 * A (double linked) list of stored message keys and associated header keys
142 * for "skipped" messages, i.e. messages that have not been
143 * received despite the reception of more recent messages, (head).
144 */
145 struct CadetTunnelSkippedKey *skipped_head;
146
147 /**
148 * Skipped messages' keys DLL, tail.
149 */
150 struct CadetTunnelSkippedKey *skipped_tail;
151
152 /**
153 * Elements in @a skipped_head <-> @a skipped_tail.
154 */
155 unsigned int skipped;
156
157 /**
158 * 32-byte root key which gets updated by DH ratchet.
159 */
160 struct GNUNET_CRYPTO_SymmetricSessionKey RK;
161
162 /**
163 * 32-byte header key (send).
164 */
165 struct GNUNET_CRYPTO_SymmetricSessionKey HKs;
166
167 /**
168 * 32-byte header key (recv)
169 */
170 struct GNUNET_CRYPTO_SymmetricSessionKey HKr;
171
172 /**
173 * 32-byte next header key (send).
174 */
175 struct GNUNET_CRYPTO_SymmetricSessionKey NHKs;
176
177 /**
178 * 32-byte next header key (recv).
179 */
180 struct GNUNET_CRYPTO_SymmetricSessionKey NHKr;
181
182 /**
183 * 32-byte chain keys (used for forward-secrecy updating, send).
184 */
185 struct GNUNET_CRYPTO_SymmetricSessionKey CKs;
186
187 /**
188 * 32-byte chain keys (used for forward-secrecy updating, recv).
189 */
190 struct GNUNET_CRYPTO_SymmetricSessionKey CKr;
191
192 /**
193 * ECDH for key exchange (A0 / B0).
194 */
195 struct GNUNET_CRYPTO_EcdhePrivateKey *kx_0;
196
197 /**
198 * ECDH Ratchet key (send).
199 */
200 struct GNUNET_CRYPTO_EcdhePrivateKey *DHRs;
201
202 /**
203 * ECDH Ratchet key (recv).
204 */
205 struct GNUNET_CRYPTO_EcdhePublicKey DHRr;
206
207 /**
208 * Message number (reset to 0 with each new ratchet, next message to send).
209 */
210 uint32_t Ns;
211
212 /**
213 * Message number (reset to 0 with each new ratchet, next message to recv).
214 */
215 uint32_t Nr;
216
217 /**
218 * Previous message numbers (# of msgs sent under prev ratchet)
219 */
220 uint32_t PNs;
221
222 /**
223 * True (#GNUNET_YES) if we have to send a new ratchet key in next msg.
224 */
225 int ratchet_flag;
226
227 /**
228 * Number of messages recieved since our last ratchet advance.
229 * - If this counter = 0, we cannot send a new ratchet key in next msg.
230 * - If this counter > 0, we can (but don't yet have to) send a new key.
231 */
232 unsigned int ratchet_allowed;
233
234 /**
235 * Number of messages recieved since our last ratchet advance.
236 * - If this counter = 0, we cannot send a new ratchet key in next msg.
237 * - If this counter > 0, we can (but don't yet have to) send a new key.
238 */
239 unsigned int ratchet_counter;
240
241 /**
242 * When does this ratchet expire and a new one is triggered.
243 */
244 struct GNUNET_TIME_Absolute ratchet_expiration;
245};
246
247
248/**
249 * Struct containing all information regarding a tunnel to a peer.
250 */
251struct CadetTunnel
252{
253 /**
254 * Endpoint of the tunnel.
255 */
256 struct CadetPeer *peer;
257
258 /**
259 * Axolotl info.
260 */
261 struct CadetTunnelAxolotl *ax;
262
263 /**
264 * State of the tunnel connectivity.
265 */
266 enum CadetTunnelCState cstate;
267
268 /**
269 * State of the tunnel encryption.
270 */
271 enum CadetTunnelEState estate;
272
273 /**
274 * Peer's ephemeral key, to recreate @c e_key and @c d_key when own ephemeral
275 * key changes.
276 */
277 struct GNUNET_CRYPTO_EcdhePublicKey peers_ephemeral_key;
278
279 /**
280 * Encryption ("our") key. It is only "confirmed" if kx_ctx is NULL.
281 */
282 struct GNUNET_CRYPTO_SymmetricSessionKey e_key;
283
284 /**
285 * Decryption ("their") key. It is only "confirmed" if kx_ctx is NULL.
286 */
287 struct GNUNET_CRYPTO_SymmetricSessionKey d_key;
288
289 /**
290 * Task to start the rekey process.
291 */
292 struct GNUNET_SCHEDULER_Task *rekey_task;
293
294 /**
295 * Paths that are actively used to reach the destination peer.
296 */
297 struct CadetTConnection *connection_head;
298 struct CadetTConnection *connection_tail;
299
300 /**
301 * Next connection number.
302 */
303 uint32_t next_cid;
304
305 /**
306 * Channels inside this tunnel.
307 */
308 struct CadetTChannel *channel_head;
309 struct CadetTChannel *channel_tail;
310
311 /**
312 * Channel ID for the next created channel.
313 */
314 struct GNUNET_CADET_ChannelTunnelNumber next_ctn;
315
316 /**
317 * Destroy flag: if true, destroy on last message.
318 */
319 struct GNUNET_SCHEDULER_Task * destroy_task;
320
321 /**
322 * Queued messages, to transmit once tunnel gets connected.
323 */
324 struct CadetTunnelDelayed *tq_head;
325 struct CadetTunnelDelayed *tq_tail;
326
327 /**
328 * Task to trim connections if too many are present.
329 */
330 struct GNUNET_SCHEDULER_Task * trim_connections_task;
331
332 /**
333 * Ephemeral message in the queue (to avoid queueing more than one).
334 */
335 struct CadetConnectionQueue *ephm_h;
336
337 /**
338 * Pong message in the queue.
339 */
340 struct CadetConnectionQueue *pong_h;
341};
342
343
344/**
345 * Struct used to save messages in a non-ready tunnel to send once connected.
346 */
347struct CadetTunnelDelayed
348{
349 /**
350 * DLL
351 */
352 struct CadetTunnelDelayed *next;
353 struct CadetTunnelDelayed *prev;
354
355 /**
356 * Tunnel.
357 */
358 struct CadetTunnel *t;
359
360 /**
361 * Tunnel queue given to the channel to cancel request. Update on send_queued.
362 */
363 struct CadetTunnelQueue *tq;
364
365 /**
366 * Message to send.
367 */
368 /* struct GNUNET_MessageHeader *msg; */
369};
370
371
372/**
373 * Handle for messages queued but not yet sent.
374 */
375struct CadetTunnelQueue
376{
377 /**
378 * Connection queue handle, to cancel if necessary.
379 */
380 struct CadetConnectionQueue *cq;
381
382 /**
383 * Handle in case message hasn't been given to a connection yet.
384 */
385 struct CadetTunnelDelayed *tqd;
386
387 /**
388 * Continuation to call once sent.
389 */
390 GCT_sent cont;
391
392 /**
393 * Closure for @c cont.
394 */
395 void *cont_cls;
396};
397
398
399/******************************************************************************/
400/******************************* GLOBALS ***********************************/
401/******************************************************************************/
402
403/**
404 * Global handle to the statistics service.
405 */
406extern struct GNUNET_STATISTICS_Handle *stats;
407
408/**
409 * Local peer own ID (memory efficient handle).
410 */
411extern GNUNET_PEER_Id myid;
412
413/**
414 * Local peer own ID (full value).
415 */
416extern struct GNUNET_PeerIdentity my_full_id;
417
418
419/**
420 * Don't try to recover tunnels if shutting down.
421 */
422extern int shutting_down;
423
424
425/**
426 * Set of all tunnels, in order to trigger a new exchange on rekey.
427 * Indexed by peer's ID.
428 */
429static struct GNUNET_CONTAINER_MultiPeerMap *tunnels;
430
431/**
432 * Own Peer ID private key.
433 */
434const static struct GNUNET_CRYPTO_EddsaPrivateKey *id_key;
435
436
437/******************************** AXOLOTL ************************************/
438
439/**
440 * How many messages are needed to trigger a ratchet advance.
441 */
442static unsigned long long ratchet_messages;
443
444/**
445 * How long until we trigger a ratched advance.
446 */
447static struct GNUNET_TIME_Relative ratchet_time;
448
449
450/******************************************************************************/
451/******************************** STATIC ***********************************/
452/******************************************************************************/
453
454/**
455 * Get string description for tunnel connectivity state.
456 *
457 * @param cs Tunnel state.
458 *
459 * @return String representation.
460 */
461static const char *
462cstate2s (enum CadetTunnelCState cs)
463{
464 static char buf[32];
465
466 switch (cs)
467 {
468 case CADET_TUNNEL_NEW:
469 return "CADET_TUNNEL_NEW";
470 case CADET_TUNNEL_SEARCHING:
471 return "CADET_TUNNEL_SEARCHING";
472 case CADET_TUNNEL_WAITING:
473 return "CADET_TUNNEL_WAITING";
474 case CADET_TUNNEL_READY:
475 return "CADET_TUNNEL_READY";
476 case CADET_TUNNEL_SHUTDOWN:
477 return "CADET_TUNNEL_SHUTDOWN";
478 default:
479 SPRINTF (buf, "%u (UNKNOWN STATE)", cs);
480 return buf;
481 }
482 return "";
483}
484
485
486/**
487 * Get string description for tunnel encryption state.
488 *
489 * @param es Tunnel state.
490 *
491 * @return String representation.
492 */
493static const char *
494estate2s (enum CadetTunnelEState es)
495{
496 static char buf[32];
497
498 switch (es)
499 {
500 case CADET_TUNNEL_KEY_UNINITIALIZED:
501 return "CADET_TUNNEL_KEY_UNINITIALIZED";
502 case CADET_TUNNEL_KEY_AX_SENT:
503 return "CADET_TUNNEL_KEY_AX_SENT";
504 case CADET_TUNNEL_KEY_AX_AUTH_SENT:
505 return "CADET_TUNNEL_KEY_AX_AUTH_SENT";
506 case CADET_TUNNEL_KEY_OK:
507 return "CADET_TUNNEL_KEY_OK";
508 case CADET_TUNNEL_KEY_REKEY:
509 return "CADET_TUNNEL_KEY_REKEY";
510 default:
511 SPRINTF (buf, "%u (UNKNOWN STATE)", es);
512 return buf;
513 }
514 return "";
515}
516
517
518/**
519 * @brief Check if tunnel is ready to send traffic.
520 *
521 * Tunnel must be connected and with encryption correctly set up.
522 *
523 * @param t Tunnel to check.
524 *
525 * @return #GNUNET_YES if ready, #GNUNET_NO otherwise
526 */
527static int
528is_ready (struct CadetTunnel *t)
529{
530 int ready;
531 int conn_ok;
532 int enc_ok;
533
534 conn_ok = CADET_TUNNEL_READY == t->cstate;
535 enc_ok = CADET_TUNNEL_KEY_OK == t->estate
536 || CADET_TUNNEL_KEY_REKEY == t->estate
537 || CADET_TUNNEL_KEY_AX_AUTH_SENT == t->estate;
538 ready = conn_ok && enc_ok;
539 ready = ready || GCT_is_loopback (t);
540 return ready;
541}
542
543
544/**
545 * Get the channel's buffer. ONLY FOR NON-LOOPBACK CHANNELS!!
546 *
547 * @param tch Tunnel's channel handle.
548 *
549 * @return Amount of messages the channel can still buffer towards the client.
550 */
551static unsigned int
552get_channel_buffer (const struct CadetTChannel *tch)
553{
554 int fwd;
555
556 /* If channel is incoming, is terminal in the FWD direction and fwd is YES */
557 fwd = GCCH_is_terminal (tch->ch, GNUNET_YES);
558
559 return GCCH_get_buffer (tch->ch, fwd);
560}
561
562
563/**
564 * Get the channel's allowance status.
565 *
566 * @param tch Tunnel's channel handle.
567 *
568 * @return #GNUNET_YES if we allowed the client to send data to us.
569 */
570static int
571get_channel_allowed (const struct CadetTChannel *tch)
572{
573 int fwd;
574
575 /* If channel is outgoing, is origin in the FWD direction and fwd is YES */
576 fwd = GCCH_is_origin (tch->ch, GNUNET_YES);
577
578 return GCCH_get_allowed (tch->ch, fwd);
579}
580
581
582/**
583 * Get the connection's buffer.
584 *
585 * @param tc Tunnel's connection handle.
586 *
587 * @return Amount of messages the connection can still buffer.
588 */
589static unsigned int
590get_connection_buffer (const struct CadetTConnection *tc)
591{
592 int fwd;
593
594 /* If connection is outgoing, is origin in the FWD direction and fwd is YES */
595 fwd = GCC_is_origin (tc->c, GNUNET_YES);
596
597 return GCC_get_buffer (tc->c, fwd);
598}
599
600
601/**
602 * Get the connection's allowance.
603 *
604 * @param tc Tunnel's connection handle.
605 *
606 * @return Amount of messages we have allowed the next peer to send us.
607 */
608static unsigned int
609get_connection_allowed (const struct CadetTConnection *tc)
610{
611 int fwd;
612
613 /* If connection is outgoing, is origin in the FWD direction and fwd is YES */
614 fwd = GCC_is_origin (tc->c, GNUNET_YES);
615
616 return GCC_get_allowed (tc->c, fwd);
617}
618
619
620/**
621 * Create a new Axolotl ephemeral (ratchet) key.
622 *
623 * @param t Tunnel.
624 */
625static void
626new_ephemeral (struct CadetTunnel *t)
627{
628 GNUNET_free_non_null (t->ax->DHRs);
629 t->ax->DHRs = GNUNET_CRYPTO_ecdhe_key_create();
630 #if DUMP_KEYS_TO_STDERR
631 {
632 struct GNUNET_CRYPTO_EcdhePublicKey pub;
633 GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->DHRs, &pub);
634 LOG (GNUNET_ERROR_TYPE_DEBUG, " new DHRs generated: pub %s\n",
635 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &pub));
636 }
637 #endif
638}
639
640
641/**
642 * Calculate HMAC.
643 *
644 * @param plaintext Content to HMAC.
645 * @param size Size of @c plaintext.
646 * @param iv Initialization vector for the message.
647 * @param key Key to use.
648 * @param hmac[out] Destination to store the HMAC.
649 */
650static void
651t_hmac (const void *plaintext, size_t size,
652 uint32_t iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
653 struct GNUNET_ShortHashCode *hmac)
654{
655 static const char ctx[] = "cadet authentication key";
656 struct GNUNET_CRYPTO_AuthKey auth_key;
657 struct GNUNET_HashCode hash;
658
659#if DUMP_KEYS_TO_STDERR
660 LOG (GNUNET_ERROR_TYPE_INFO, " HMAC %u bytes with key %s\n", size,
661 GNUNET_i2s ((struct GNUNET_PeerIdentity *) key));
662#endif
663 GNUNET_CRYPTO_hmac_derive_key (&auth_key, key,
664 &iv, sizeof (iv),
665 key, sizeof (*key),
666 ctx, sizeof (ctx),
667 NULL);
668 /* Two step: CADET_Hash is only 256 bits, HashCode is 512. */
669 GNUNET_CRYPTO_hmac (&auth_key, plaintext, size, &hash);
670 GNUNET_memcpy (hmac, &hash, sizeof (*hmac));
671}
672
673
674/**
675 * Perform a HMAC.
676 *
677 * @param key Key to use.
678 * @param hash[out] Resulting HMAC.
679 * @param source Source key material (data to HMAC).
680 * @param len Length of @a source.
681 */
682static void
683t_ax_hmac_hash (struct GNUNET_CRYPTO_SymmetricSessionKey *key,
684 struct GNUNET_HashCode *hash,
685 void *source, unsigned int len)
686{
687 static const char ctx[] = "axolotl HMAC-HASH";
688 struct GNUNET_CRYPTO_AuthKey auth_key;
689
690 GNUNET_CRYPTO_hmac_derive_key (&auth_key, key,
691 ctx, sizeof (ctx),
692 NULL);
693 GNUNET_CRYPTO_hmac (&auth_key, source, len, hash);
694}
695
696
697/**
698 * Derive a key from a HMAC-HASH.
699 *
700 * @param key Key to use for the HMAC.
701 * @param out Key to generate.
702 * @param source Source key material (data to HMAC).
703 * @param len Length of @a source.
704 */
705static void
706t_hmac_derive_key (struct GNUNET_CRYPTO_SymmetricSessionKey *key,
707 struct GNUNET_CRYPTO_SymmetricSessionKey *out,
708 void *source, unsigned int len)
709{
710 static const char ctx[] = "axolotl derive key";
711 struct GNUNET_HashCode h;
712
713 t_ax_hmac_hash (key, &h, source, len);
714 GNUNET_CRYPTO_kdf (out, sizeof (*out), ctx, sizeof (ctx),
715 &h, sizeof (h), NULL);
716}
717
718
719/**
720 * Encrypt data with the axolotl tunnel key.
721 *
722 * @param t Tunnel whose key to use.
723 * @param dst Destination for the encrypted data.
724 * @param src Source of the plaintext. Can overlap with @c dst.
725 * @param size Size of the plaintext.
726 *
727 * @return Size of the encrypted data.
728 */
729static int
730t_ax_encrypt (struct CadetTunnel *t, void *dst, const void *src, size_t size)
731{
732 struct GNUNET_CRYPTO_SymmetricSessionKey MK;
733 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
734 struct CadetTunnelAxolotl *ax;
735 size_t out_size;
736
737 CADET_TIMING_START;
738
739 ax = t->ax;
740 ax->ratchet_counter++;
741 if (GNUNET_YES == ax->ratchet_allowed
742 && (ratchet_messages <= ax->ratchet_counter
743 || 0 == GNUNET_TIME_absolute_get_remaining (ax->ratchet_expiration).rel_value_us))
744 {
745 ax->ratchet_flag = GNUNET_YES;
746 }
747
748 if (GNUNET_YES == ax->ratchet_flag)
749 {
750 /* Advance ratchet */
751 struct GNUNET_CRYPTO_SymmetricSessionKey keys[3];
752 struct GNUNET_HashCode dh;
753 struct GNUNET_HashCode hmac;
754 static const char ctx[] = "axolotl ratchet";
755
756 new_ephemeral (t);
757 ax->HKs = ax->NHKs;
758
759 /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */
760 GNUNET_CRYPTO_ecc_ecdh (ax->DHRs, &ax->DHRr, &dh);
761 t_ax_hmac_hash (&ax->RK, &hmac, &dh, sizeof (dh));
762 GNUNET_CRYPTO_kdf (keys, sizeof (keys), ctx, sizeof (ctx),
763 &hmac, sizeof (hmac), NULL);
764 ax->RK = keys[0];
765 ax->NHKs = keys[1];
766 ax->CKs = keys[2];
767
768 ax->PNs = ax->Ns;
769 ax->Ns = 0;
770 ax->ratchet_flag = GNUNET_NO;
771 ax->ratchet_allowed = GNUNET_NO;
772 ax->ratchet_counter = 0;
773 ax->ratchet_expiration =
774 GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), ratchet_time);
775 }
776
777 t_hmac_derive_key (&ax->CKs, &MK, "0", 1);
778 GNUNET_CRYPTO_symmetric_derive_iv (&iv, &MK, NULL, 0, NULL);
779
780 #if DUMP_KEYS_TO_STDERR
781 LOG (GNUNET_ERROR_TYPE_DEBUG, " CKs: %s\n",
782 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->CKs));
783 LOG (GNUNET_ERROR_TYPE_INFO, " AX_ENC with key %u: %s\n", ax->Ns,
784 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &MK));
785 #endif
786
787 out_size = GNUNET_CRYPTO_symmetric_encrypt (src, size, &MK, &iv, dst);
788 t_hmac_derive_key (&ax->CKs, &ax->CKs, "1", 1);
789
790 CADET_TIMING_END;
791
792 return out_size;
793}
794
795
796/**
797 * Decrypt data with the axolotl tunnel key.
798 *
799 * @param t Tunnel whose key to use.
800 * @param dst Destination for the decrypted data.
801 * @param src Source of the ciphertext. Can overlap with @c dst.
802 * @param size Size of the ciphertext.
803 *
804 * @return Size of the decrypted data.
805 */
806static int
807t_ax_decrypt (struct CadetTunnel *t, void *dst, const void *src, size_t size)
808{
809 struct GNUNET_CRYPTO_SymmetricSessionKey MK;
810 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
811 struct CadetTunnelAxolotl *ax;
812 size_t out_size;
813
814 CADET_TIMING_START;
815
816 ax = t->ax;
817
818 t_hmac_derive_key (&ax->CKr, &MK, "0", 1);
819 GNUNET_CRYPTO_symmetric_derive_iv (&iv, &MK, NULL, 0, NULL);
820
821 #if DUMP_KEYS_TO_STDERR
822 LOG (GNUNET_ERROR_TYPE_DEBUG, " CKr: %s\n",
823 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->CKr));
824 LOG (GNUNET_ERROR_TYPE_INFO, " AX_DEC with key %u: %s\n", ax->Nr,
825 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &MK));
826 #endif
827
828 GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
829 out_size = GNUNET_CRYPTO_symmetric_decrypt (src, size, &MK, &iv, dst);
830 GNUNET_assert (out_size == size);
831
832 t_hmac_derive_key (&ax->CKr, &ax->CKr, "1", 1);
833
834 CADET_TIMING_END;
835
836 return out_size;
837}
838
839
840/**
841 * Encrypt header with the axolotl header key.
842 *
843 * @param t Tunnel whose key to use.
844 * @param msg Message whose header to encrypt.
845 */
846static void
847t_h_encrypt (struct CadetTunnel *t, struct GNUNET_CADET_TunnelEncryptedMessage *msg)
848{
849 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
850 struct CadetTunnelAxolotl *ax;
851 size_t out_size;
852
853 CADET_TIMING_START;
854 ax = t->ax;
855 GNUNET_CRYPTO_symmetric_derive_iv (&iv, &ax->HKs, NULL, 0, NULL);
856
857 #if DUMP_KEYS_TO_STDERR
858 LOG (GNUNET_ERROR_TYPE_INFO, " AX_ENC_H with key %s\n",
859 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->HKs));
860 #endif
861
862 out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->Ns, AX_HEADER_SIZE,
863 &ax->HKs, &iv, &msg->Ns);
864
865 GNUNET_assert (AX_HEADER_SIZE == out_size);
866 CADET_TIMING_END;
867}
868
869
870/**
871 * Decrypt header with the current axolotl header key.
872 *
873 * @param t Tunnel whose current ax HK to use.
874 * @param src Message whose header to decrypt.
875 * @param dst Where to decrypt header to.
876 */
877static void
878t_h_decrypt (struct CadetTunnel *t, const struct GNUNET_CADET_TunnelEncryptedMessage *src,
879 struct GNUNET_CADET_TunnelEncryptedMessage *dst)
880{
881 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
882 struct CadetTunnelAxolotl *ax;
883 size_t out_size;
884
885 CADET_TIMING_START;
886
887 ax = t->ax;
888 GNUNET_CRYPTO_symmetric_derive_iv (&iv, &ax->HKr, NULL, 0, NULL);
889
890 #if DUMP_KEYS_TO_STDERR
891 LOG (GNUNET_ERROR_TYPE_INFO, " AX_DEC_H with key %s\n",
892 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->HKr));
893 #endif
894
895 out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns, AX_HEADER_SIZE,
896 &ax->HKr, &iv, &dst->Ns);
897
898 GNUNET_assert (AX_HEADER_SIZE == out_size);
899
900 CADET_TIMING_END;
901}
902
903
904/**
905 * Decrypt and verify data with the appropriate tunnel key and verify that the
906 * data has not been altered since it was sent by the remote peer.
907 *
908 * @param t Tunnel whose key to use.
909 * @param dst Destination for the plaintext.
910 * @param src Source of the message. Can overlap with @c dst.
911 * @param size Size of the message.
912 *
913 * @return Size of the decrypted data, -1 if an error was encountered.
914 */
915static int
916try_old_ax_keys (struct CadetTunnel *t, void *dst,
917 const struct GNUNET_CADET_TunnelEncryptedMessage *src, size_t size)
918{
919 struct CadetTunnelSkippedKey *key;
920 struct GNUNET_ShortHashCode *hmac;
921 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
922 struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
923 struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK;
924 size_t esize;
925 size_t res;
926 size_t len;
927 unsigned int N;
928
929 LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying old keys\n");
930 hmac = &plaintext_header.hmac;
931 esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
932
933 /* Find a correct Header Key */
934 for (key = t->ax->skipped_head; NULL != key; key = key->next)
935 {
936 #if DUMP_KEYS_TO_STDERR
937 LOG (GNUNET_ERROR_TYPE_DEBUG, " Trying hmac with key %s\n",
938 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->HK));
939 #endif
940 t_hmac (&src->Ns, AX_HEADER_SIZE + esize, 0, &key->HK, hmac);
941 if (0 == memcmp (hmac, &src->hmac, sizeof (*hmac)))
942 {
943 LOG (GNUNET_ERROR_TYPE_DEBUG, " hmac correct\n");
944 valid_HK = &key->HK;
945 break;
946 }
947 }
948 if (NULL == key)
949 return -1;
950
951 /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */
952 GNUNET_assert (size > sizeof (struct GNUNET_CADET_TunnelEncryptedMessage));
953 len = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
954 GNUNET_assert (len >= sizeof (struct GNUNET_MessageHeader));
955
956 /* Decrypt header */
957 GNUNET_CRYPTO_symmetric_derive_iv (&iv, &key->HK, NULL, 0, NULL);
958 res = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns, AX_HEADER_SIZE,
959 &key->HK, &iv, &plaintext_header.Ns);
960 GNUNET_assert (AX_HEADER_SIZE == res);
961 LOG (GNUNET_ERROR_TYPE_DEBUG, " Message %u, previous: %u\n",
962 ntohl (plaintext_header.Ns), ntohl (plaintext_header.PNs));
963
964 /* Find the correct Message Key */
965 N = ntohl (plaintext_header.Ns);
966 while (NULL != key && N != key->Kn)
967 key = key->next;
968 if (NULL == key || 0 != memcmp (&key->HK, valid_HK, sizeof (*valid_HK)))
969 return -1;
970
971 #if DUMP_KEYS_TO_STDERR
972 LOG (GNUNET_ERROR_TYPE_INFO, " AX_DEC_H with skipped key %s\n",
973 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->HK));
974 LOG (GNUNET_ERROR_TYPE_INFO, " AX_DEC with skipped key %u: %s\n",
975 key->Kn, GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->MK));
976 #endif
977
978 /* Decrypt payload */
979 GNUNET_CRYPTO_symmetric_derive_iv (&iv, &key->MK, NULL, 0, NULL);
980 res = GNUNET_CRYPTO_symmetric_decrypt (&src[1], len, &key->MK, &iv, dst);
981
982 /* Remove key */
983 GNUNET_CONTAINER_DLL_remove (t->ax->skipped_head, t->ax->skipped_tail, key);
984 t->ax->skipped--;
985 GNUNET_free (key); /* GNUNET_free overwrites memory with 0xbaadf00d */
986
987 return res;
988}
989
990
991/**
992 * Delete a key from the list of skipped keys.
993 *
994 * @param t Tunnel to delete from.
995 * @param HKr Header Key to use.
996 */
997static void
998store_skipped_key (struct CadetTunnel *t,
999 const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr)
1000{
1001 struct CadetTunnelSkippedKey *key;
1002
1003 key = GNUNET_new (struct CadetTunnelSkippedKey);
1004 key->timestamp = GNUNET_TIME_absolute_get ();
1005 key->Kn = t->ax->Nr;
1006 key->HK = t->ax->HKr;
1007 t_hmac_derive_key (&t->ax->CKr, &key->MK, "0", 1);
1008 #if DUMP_KEYS_TO_STDERR
1009 LOG (GNUNET_ERROR_TYPE_DEBUG, " storing MK for Nr %u: %s\n",
1010 key->Kn, GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->MK));
1011 LOG (GNUNET_ERROR_TYPE_DEBUG, " for CKr: %s\n",
1012 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &t->ax->CKr));
1013 #endif
1014 t_hmac_derive_key (&t->ax->CKr, &t->ax->CKr, "1", 1);
1015 GNUNET_CONTAINER_DLL_insert (t->ax->skipped_head, t->ax->skipped_tail, key);
1016 t->ax->Nr++;
1017 t->ax->skipped++;
1018}
1019
1020
1021/**
1022 * Delete a key from the list of skipped keys.
1023 *
1024 * @param t Tunnel to delete from.
1025 * @param key Key to delete.
1026 */
1027static void
1028delete_skipped_key (struct CadetTunnel *t, struct CadetTunnelSkippedKey *key)
1029{
1030 GNUNET_CONTAINER_DLL_remove (t->ax->skipped_head, t->ax->skipped_tail, key);
1031 GNUNET_free (key);
1032 t->ax->skipped--;
1033}
1034
1035
1036/**
1037 * Stage skipped AX keys and calculate the message key.
1038 *
1039 * Stores each HK and MK for skipped messages.
1040 *
1041 * @param t Tunnel where to stage the keys.
1042 * @param HKr Header key.
1043 * @param Np Received meesage number.
1044 *
1045 * @return GNUNET_OK if keys were stored.
1046 * GNUNET_SYSERR if an error ocurred (Np not expected).
1047 */
1048static int
1049store_ax_keys (struct CadetTunnel *t,
1050 const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr,
1051 uint32_t Np)
1052{
1053 int gap;
1054
1055
1056 gap = Np - t->ax->Nr;
1057 LOG (GNUNET_ERROR_TYPE_INFO, "Storing keys [%u, %u)\n", t->ax->Nr, Np);
1058 if (MAX_KEY_GAP < gap)
1059 {
1060 /* Avoid DoS (forcing peer to do 2*33 chain HMAC operations) */
1061 /* TODO: start new key exchange on return */
1062 GNUNET_break_op (0);
1063 LOG (GNUNET_ERROR_TYPE_WARNING, "Got message %u, expected %u+\n",
1064 Np, t->ax->Nr);
1065 return GNUNET_SYSERR;
1066 }
1067 if (0 > gap)
1068 {
1069 /* Delayed message: don't store keys, flag to try old keys. */
1070 return GNUNET_SYSERR;
1071 }
1072
1073 while (t->ax->Nr < Np)
1074 store_skipped_key (t, HKr);
1075
1076 while (t->ax->skipped > MAX_SKIPPED_KEYS)
1077 delete_skipped_key (t, t->ax->skipped_tail);
1078
1079 return GNUNET_OK;
1080}
1081
1082
1083/**
1084 * Decrypt and verify data with the appropriate tunnel key and verify that the
1085 * data has not been altered since it was sent by the remote peer.
1086 *
1087 * @param t Tunnel whose key to use.
1088 * @param dst Destination for the plaintext.
1089 * @param src Source of the message. Can overlap with @c dst.
1090 * @param size Size of the message.
1091 *
1092 * @return Size of the decrypted data, -1 if an error was encountered.
1093 */
1094static int
1095t_ax_decrypt_and_validate (struct CadetTunnel *t, void *dst,
1096 const struct GNUNET_CADET_TunnelEncryptedMessage *src,
1097 size_t size)
1098{
1099 struct CadetTunnelAxolotl *ax;
1100 struct GNUNET_ShortHashCode msg_hmac;
1101 struct GNUNET_HashCode hmac;
1102 struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
1103 uint32_t Np;
1104 uint32_t PNp;
1105 size_t esize; /* Size of encryped payload */
1106 size_t osize; /* Size of output (decrypted payload) */
1107
1108 esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
1109 ax = t->ax;
1110 if (NULL == ax)
1111 return -1;
1112
1113 /* Try current HK */
1114 t_hmac (&src->Ns, AX_HEADER_SIZE + esize, 0, &ax->HKr, &msg_hmac);
1115 if (0 != memcmp (&msg_hmac, &src->hmac, sizeof (msg_hmac)))
1116 {
1117 static const char ctx[] = "axolotl ratchet";
1118 struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; /* RKp, NHKp, CKp */
1119 struct GNUNET_CRYPTO_SymmetricSessionKey HK;
1120 struct GNUNET_HashCode dh;
1121 struct GNUNET_CRYPTO_EcdhePublicKey *DHRp;
1122
1123 /* Try Next HK */
1124 LOG (GNUNET_ERROR_TYPE_DEBUG, " trying next HK\n");
1125 t_hmac (&src->Ns, AX_HEADER_SIZE + esize, 0, &ax->NHKr, &msg_hmac);
1126 if (0 != memcmp (&msg_hmac, &src->hmac, sizeof (msg_hmac)))
1127 {
1128 /* Try the skipped keys, if that fails, we're out of luck. */
1129 return try_old_ax_keys (t, dst, src, size);
1130 }
1131 LOG (GNUNET_ERROR_TYPE_INFO, "next HK worked\n");
1132
1133 HK = ax->HKr;
1134 ax->HKr = ax->NHKr;
1135 t_h_decrypt (t, src, &plaintext_header);
1136 Np = ntohl (plaintext_header.Ns);
1137 PNp = ntohl (plaintext_header.PNs);
1138 DHRp = &plaintext_header.DHRs;
1139 store_ax_keys (t, &HK, PNp);
1140
1141 /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */
1142 GNUNET_CRYPTO_ecc_ecdh (ax->DHRs, DHRp, &dh);
1143 t_ax_hmac_hash (&ax->RK, &hmac, &dh, sizeof (dh));
1144 GNUNET_CRYPTO_kdf (keys, sizeof (keys), ctx, sizeof (ctx),
1145 &hmac, sizeof (hmac), NULL);
1146
1147 /* Commit "purported" keys */
1148 ax->RK = keys[0];
1149 ax->NHKr = keys[1];
1150 ax->CKr = keys[2];
1151 ax->DHRr = *DHRp;
1152 ax->Nr = 0;
1153 ax->ratchet_allowed = GNUNET_YES;
1154 }
1155 else
1156 {
1157 LOG (GNUNET_ERROR_TYPE_DEBUG, "current HK\n");
1158 t_h_decrypt (t, src, &plaintext_header);
1159 Np = ntohl (plaintext_header.Ns);
1160 PNp = ntohl (plaintext_header.PNs);
1161 }
1162 LOG (GNUNET_ERROR_TYPE_INFO, " got AX Nr %u\n", Np);
1163 if (Np != ax->Nr)
1164 if (GNUNET_OK != store_ax_keys (t, &ax->HKr, Np))
1165 /* Try the skipped keys, if that fails, we're out of luck. */
1166 return try_old_ax_keys (t, dst, src, size);
1167
1168 osize = t_ax_decrypt (t, dst, &src[1], esize);
1169 ax->Nr = Np + 1;
1170
1171 if (osize != esize)
1172 {
1173 GNUNET_break_op (0);
1174 return -1;
1175 }
1176
1177 return osize;
1178}
1179
1180
1181/**
1182 * Pick a connection on which send the next data message.
1183 *
1184 * @param t Tunnel on which to send the message.
1185 *
1186 * @return The connection on which to send the next message.
1187 */
1188static struct CadetConnection *
1189tunnel_get_connection (struct CadetTunnel *t)
1190{
1191 struct CadetTConnection *iter;
1192 struct CadetConnection *best;
1193 unsigned int qn;
1194 unsigned int lowest_q;
1195
1196 LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel_get_connection %s\n", GCT_2s (t));
1197 best = NULL;
1198 lowest_q = UINT_MAX;
1199 for (iter = t->connection_head; NULL != iter; iter = iter->next)
1200 {
1201 LOG (GNUNET_ERROR_TYPE_DEBUG, " connection %s: %u\n",
1202 GCC_2s (iter->c), GCC_get_state (iter->c));
1203 if (CADET_CONNECTION_READY == GCC_get_state (iter->c))
1204 {
1205 qn = GCC_get_qn (iter->c, GCC_is_origin (iter->c, GNUNET_YES));
1206 LOG (GNUNET_ERROR_TYPE_DEBUG, " q_n %u, \n", qn);
1207 if (qn < lowest_q)
1208 {
1209 best = iter->c;
1210 lowest_q = qn;
1211 }
1212 }
1213 }
1214 LOG (GNUNET_ERROR_TYPE_DEBUG, " selected: connection %s\n", GCC_2s (best));
1215 return best;
1216}
1217
1218
1219/**
1220 * Callback called when a queued message is sent.
1221 *
1222 * Calculates the average time and connection packet tracking.
1223 *
1224 * @param cls Closure (TunnelQueue handle).
1225 * @param c Connection this message was on.
1226 * @param q Connection queue handle (unused).
1227 * @param type Type of message sent.
1228 * @param fwd Was this a FWD going message?
1229 * @param size Size of the message.
1230 */
1231static void
1232tun_message_sent (void *cls,
1233 struct CadetConnection *c,
1234 struct CadetConnectionQueue *q,
1235 uint16_t type, int fwd, size_t size)
1236{
1237 struct CadetTunnelQueue *qt = cls;
1238 struct CadetTunnel *t;
1239
1240 LOG (GNUNET_ERROR_TYPE_DEBUG, "tun_message_sent\n");
1241
1242 GNUNET_assert (NULL != qt->cont);
1243 t = NULL == c ? NULL : GCC_get_tunnel (c);
1244 qt->cont (qt->cont_cls, t, qt, type, size);
1245 GNUNET_free (qt);
1246}
1247
1248
1249static unsigned int
1250count_queued_data (const struct CadetTunnel *t)
1251{
1252 struct CadetTunnelDelayed *iter;
1253 unsigned int count;
1254
1255 for (count = 0, iter = t->tq_head; iter != NULL; iter = iter->next)
1256 count++;
1257
1258 return count;
1259}
1260
1261/**
1262 * Delete a queued message: either was sent or the channel was destroyed
1263 * before the tunnel's key exchange had a chance to finish.
1264 *
1265 * @param tqd Delayed queue handle.
1266 */
1267static void
1268unqueue_data (struct CadetTunnelDelayed *tqd)
1269{
1270 GNUNET_CONTAINER_DLL_remove (tqd->t->tq_head, tqd->t->tq_tail, tqd);
1271 GNUNET_free (tqd);
1272}
1273
1274
1275/**
1276 * Cache a message to be sent once tunnel is online.
1277 *
1278 * @param t Tunnel to hold the message.
1279 * @param msg Message itself (copy will be made).
1280 */
1281static struct CadetTunnelDelayed *
1282queue_data (struct CadetTunnel *t, const struct GNUNET_MessageHeader *msg)
1283{
1284 struct CadetTunnelDelayed *tqd;
1285 uint16_t size = ntohs (msg->size);
1286
1287 LOG (GNUNET_ERROR_TYPE_DEBUG, "queue data on Tunnel %s\n", GCT_2s (t));
1288
1289 GNUNET_assert (GNUNET_NO == is_ready (t));
1290
1291 tqd = GNUNET_malloc (sizeof (struct CadetTunnelDelayed) + size);
1292
1293 tqd->t = t;
1294 GNUNET_memcpy (&tqd[1], msg, size);
1295 GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, t->tq_tail, tqd);
1296 return tqd;
1297}
1298
1299
1300/**
1301 * Sends an already built message on a tunnel, encrypting it and
1302 * choosing the best connection.
1303 *
1304 * @param message Message to send. Function modifies it.
1305 * @param t Tunnel on which this message is transmitted.
1306 * @param c Connection to use (autoselect if NULL).
1307 * @param force Force the tunnel to take the message (buffer overfill).
1308 * @param cont Continuation to call once message is really sent.
1309 * @param cont_cls Closure for @c cont.
1310 * @param existing_q In case this a transmission of previously queued data,
1311 * this should be TunnelQueue given to the client.
1312 * Otherwise, NULL.
1313 * @return Handle to cancel message.
1314 * NULL if @c cont is NULL or an error happens and message is dropped.
1315 */
1316static struct CadetTunnelQueue *
1317send_prebuilt_message (const struct GNUNET_MessageHeader *message,
1318 struct CadetTunnel *t,
1319 struct CadetConnection *c,
1320 int force,
1321 GCT_sent cont,
1322 void *cont_cls,
1323 struct CadetTunnelQueue *existing_q)
1324{
1325 struct GNUNET_MessageHeader *msg;
1326 struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg;
1327 struct CadetTunnelQueue *tq;
1328 size_t size = ntohs (message->size);
1329 char cbuf[sizeof (struct GNUNET_CADET_TunnelEncryptedMessage) + size] GNUNET_ALIGN;
1330 size_t esize;
1331 uint16_t type;
1332 int fwd;
1333
1334 LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT Send on Tunnel %s\n", GCT_2s (t));
1335
1336 if (GNUNET_NO == is_ready (t))
1337 {
1338 struct CadetTunnelDelayed *tqd;
1339 /* A non null existing_q indicates sending of queued data.
1340 * Should only happen after tunnel becomes ready.
1341 */
1342 GNUNET_assert (NULL == existing_q);
1343 tqd = queue_data (t, message);
1344 if (NULL == cont)
1345 return NULL;
1346 tq = GNUNET_new (struct CadetTunnelQueue);
1347 tq->tqd = tqd;
1348 tqd->tq = tq;
1349 tq->cont = cont;
1350 tq->cont_cls = cont_cls;
1351 return tq;
1352 }
1353
1354 GNUNET_assert (GNUNET_NO == GCT_is_loopback (t));
1355
1356 ax_msg = (struct GNUNET_CADET_TunnelEncryptedMessage *) cbuf;
1357 msg = &ax_msg->header;
1358 msg->size = htons (sizeof (struct GNUNET_CADET_TunnelEncryptedMessage) + size);
1359 msg->type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED);
1360 esize = t_ax_encrypt (t, &ax_msg[1], message, size);
1361 ax_msg->Ns = htonl (t->ax->Ns++);
1362 ax_msg->PNs = htonl (t->ax->PNs);
1363 GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->DHRs, &ax_msg->DHRs);
1364 t_h_encrypt (t, ax_msg);
1365 t_hmac (&ax_msg->Ns, AX_HEADER_SIZE + esize, 0, &t->ax->HKs, &ax_msg->hmac);
1366 GNUNET_assert (esize == size);
1367
1368 if (NULL == c)
1369 c = tunnel_get_connection (t);
1370 if (NULL == c)
1371 {
1372 /* Why is tunnel 'ready'? Should have been queued! */
1373 if (NULL != t->destroy_task)
1374 {
1375 GNUNET_break (0);
1376 GCT_debug (t, GNUNET_ERROR_TYPE_WARNING);
1377 }
1378 return NULL; /* Drop... */
1379 }
1380 fwd = GCC_is_origin (c, GNUNET_YES);
1381 ax_msg->cid = *GCC_get_id (c);
1382 ax_msg->cemi = GCC_get_pid (c, fwd);
1383
1384 type = htons (message->type);
1385 LOG (GNUNET_ERROR_TYPE_DEBUG,
1386 "Sending message of type %s with CEMI %u and CID %s\n",
1387 GC_m2s (type),
1388 htonl (ax_msg->cemi.pid),
1389 GNUNET_sh2s (&ax_msg->cid.connection_of_tunnel));
1390
1391 if (NULL == cont)
1392 {
1393 (void) GCC_send_prebuilt_message (msg,
1394 type,
1395 ax_msg->cemi,
1396 c,
1397 fwd,
1398 force, NULL, NULL);
1399 return NULL;
1400 }
1401 if (NULL == existing_q)
1402 {
1403 tq = GNUNET_new (struct CadetTunnelQueue); /* FIXME valgrind: leak*/
1404 }
1405 else
1406 {
1407 tq = existing_q;
1408 tq->tqd = NULL;
1409 }
1410 tq->cont = cont;
1411 tq->cont_cls = cont_cls;
1412 tq->cq = GCC_send_prebuilt_message (msg,
1413 type,
1414 ax_msg->cemi,
1415 c,
1416 fwd,
1417 force,
1418 &tun_message_sent, tq);
1419 GNUNET_assert (NULL != tq->cq);
1420
1421 return tq;
1422}
1423
1424
1425/**
1426 * Send all cached messages that we can, tunnel is online.
1427 *
1428 * @param t Tunnel that holds the messages. Cannot be loopback.
1429 */
1430static void
1431send_queued_data (struct CadetTunnel *t)
1432{
1433 struct CadetTunnelDelayed *tqd;
1434 struct CadetTunnelDelayed *next;
1435 unsigned int room;
1436
1437 LOG (GNUNET_ERROR_TYPE_INFO, "Send queued data, tunnel %s\n", GCT_2s (t));
1438
1439 if (GCT_is_loopback (t))
1440 {
1441 GNUNET_break (0);
1442 return;
1443 }
1444
1445 if (GNUNET_NO == is_ready (t))
1446 {
1447 LOG (GNUNET_ERROR_TYPE_WARNING, " not ready yet: %s/%s\n",
1448 estate2s (t->estate), cstate2s (t->cstate));
1449 return;
1450 }
1451
1452 room = GCT_get_connections_buffer (t);
1453 LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space: %u\n", room);
1454 LOG (GNUNET_ERROR_TYPE_DEBUG, " tq head: %p\n", t->tq_head);
1455 for (tqd = t->tq_head; NULL != tqd && room > 0; tqd = next)
1456 {
1457 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending queued data\n");
1458 next = tqd->next;
1459 room--;
1460 send_prebuilt_message ((struct GNUNET_MessageHeader *) &tqd[1],
1461 tqd->t, NULL, GNUNET_YES,
1462 NULL != tqd->tq ? tqd->tq->cont : NULL,
1463 NULL != tqd->tq ? tqd->tq->cont_cls : NULL,
1464 tqd->tq);
1465 unqueue_data (tqd);
1466 }
1467 LOG (GNUNET_ERROR_TYPE_DEBUG, "GCT_send_queued_data end\n", GCP_2s (t->peer));
1468}
1469
1470
1471/**
1472 * @brief Resend the KX until we complete the handshake.
1473 *
1474 * @param cls Closure (tunnel).
1475 */
1476static void
1477kx_resend (void *cls)
1478{
1479 struct CadetTunnel *t = cls;
1480
1481 t->rekey_task = NULL;
1482 if (CADET_TUNNEL_KEY_OK == t->estate)
1483 {
1484 /* Should have been canceled on estate change */
1485 GNUNET_break (0);
1486 return;
1487 }
1488
1489 GCT_send_kx (t, CADET_TUNNEL_KEY_AX_SENT >= t->estate);
1490}
1491
1492
1493/**
1494 * Callback called when a queued message is sent.
1495 *
1496 * @param cls Closure.
1497 * @param c Connection this message was on.
1498 * @param type Type of message sent.
1499 * @param fwd Was this a FWD going message?
1500 * @param size Size of the message.
1501 */
1502static void
1503ephm_sent (void *cls,
1504 struct CadetConnection *c,
1505 struct CadetConnectionQueue *q,
1506 uint16_t type, int fwd, size_t size)
1507{
1508 struct CadetTunnel *t = cls;
1509 LOG (GNUNET_ERROR_TYPE_DEBUG, "ephemeral sent %s\n", GC_m2s (type));
1510
1511 t->ephm_h = NULL;
1512
1513 if (CADET_TUNNEL_KEY_OK == t->estate)
1514 return;
1515
1516 if (NULL != t->rekey_task)
1517 {
1518 GNUNET_break (0);
1519 GCT_debug (t, GNUNET_ERROR_TYPE_WARNING);
1520 GNUNET_SCHEDULER_cancel (t->rekey_task);
1521 }
1522 t->rekey_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
1523 &kx_resend, t);
1524
1525}
1526
1527
1528/**
1529 * Called only on shutdown, destroy every tunnel.
1530 *
1531 * @param cls Closure (unused).
1532 * @param key Current public key.
1533 * @param value Value in the hash map (tunnel).
1534 *
1535 * @return #GNUNET_YES, so we should continue to iterate,
1536 */
1537static int
1538destroy_iterator (void *cls,
1539 const struct GNUNET_PeerIdentity *key,
1540 void *value)
1541{
1542 struct CadetTunnel *t = value;
1543
1544 LOG (GNUNET_ERROR_TYPE_DEBUG,
1545 "GCT_shutdown destroying tunnel at %p\n", t);
1546 GCT_destroy (t);
1547 return GNUNET_YES;
1548}
1549
1550
1551/**
1552 * Notify remote peer that we don't know a channel he is talking about,
1553 * probably CHANNEL_DESTROY was missed.
1554 *
1555 * @param t Tunnel on which to notify.
1556 * @param gid ID of the channel.
1557 */
1558static void
1559send_channel_destroy (struct CadetTunnel *t,
1560 struct GNUNET_CADET_ChannelTunnelNumber gid)
1561{
1562 struct GNUNET_CADET_ChannelManageMessage msg;
1563
1564 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
1565 msg.header.size = htons (sizeof (msg));
1566 msg.ctn = gid;
1567
1568 LOG (GNUNET_ERROR_TYPE_DEBUG,
1569 "WARNING destroying unknown channel %u on tunnel %s\n",
1570 ntohl (gid.cn),
1571 GCT_2s (t));
1572 send_prebuilt_message (&msg.header, t, NULL, GNUNET_YES, NULL, NULL, NULL);
1573}
1574
1575
1576/**
1577 * Demultiplex data per channel and call appropriate channel handler.
1578 *
1579 * @param t Tunnel on which the data came.
1580 * @param msg Data message.
1581 * @param fwd Is this message fwd? This only is meaningful in loopback channels.
1582 * #GNUNET_YES if message is FWD on the respective channel (loopback)
1583 * #GNUNET_NO if message is BCK on the respective channel (loopback)
1584 * #GNUNET_SYSERR if message on a one-ended channel (remote)
1585 */
1586static void
1587handle_data (struct CadetTunnel *t,
1588 const struct GNUNET_CADET_ChannelAppDataMessage *msg,
1589 int fwd)
1590{
1591 struct CadetChannel *ch;
1592 char buf[128];
1593 size_t size;
1594 uint16_t type;
1595
1596 /* Check size */
1597 size = ntohs (msg->header.size);
1598 if (size <
1599 sizeof (struct GNUNET_CADET_ChannelAppDataMessage) +
1600 sizeof (struct GNUNET_MessageHeader))
1601 {
1602 GNUNET_break (0);
1603 return;
1604 }
1605 type = ntohs (msg[1].header.type);
1606 LOG (GNUNET_ERROR_TYPE_DEBUG, " payload of type %s\n", GC_m2s (type));
1607 SPRINTF (buf, "# received payload of type %hu", type);
1608 GNUNET_STATISTICS_update (stats, buf, 1, GNUNET_NO);
1609
1610
1611 /* Check channel */
1612 ch = GCT_get_channel (t, msg->ctn);
1613 if (NULL == ch)
1614 {
1615 GNUNET_STATISTICS_update (stats,
1616 "# data on unknown channel",
1617 1,
1618 GNUNET_NO);
1619 LOG (GNUNET_ERROR_TYPE_DEBUG,
1620 "channel 0x%X unknown\n",
1621 ntohl (msg->ctn.cn));
1622 send_channel_destroy (t, msg->ctn);
1623 return;
1624 }
1625
1626 GCCH_handle_data (ch, msg, fwd);
1627}
1628
1629
1630/**
1631 * Demultiplex data ACKs per channel and update appropriate channel buffer info.
1632 *
1633 * @param t Tunnel on which the DATA ACK came.
1634 * @param msg DATA ACK message.
1635 * @param fwd Is this message fwd? This only is meaningful in loopback channels.
1636 * #GNUNET_YES if message is FWD on the respective channel (loopback)
1637 * #GNUNET_NO if message is BCK on the respective channel (loopback)
1638 * #GNUNET_SYSERR if message on a one-ended channel (remote)
1639 */
1640static void
1641handle_data_ack (struct CadetTunnel *t,
1642 const struct GNUNET_CADET_ChannelDataAckMessage *msg,
1643 int fwd)
1644{
1645 struct CadetChannel *ch;
1646 size_t size;
1647
1648 /* Check size */
1649 size = ntohs (msg->header.size);
1650 if (size != sizeof (struct GNUNET_CADET_ChannelDataAckMessage))
1651 {
1652 GNUNET_break (0);
1653 return;
1654 }
1655
1656 /* Check channel */
1657 ch = GCT_get_channel (t, msg->ctn);
1658 if (NULL == ch)
1659 {
1660 GNUNET_STATISTICS_update (stats, "# data ack on unknown channel",
1661 1, GNUNET_NO);
1662 LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n",
1663 ntohl (msg->ctn.cn));
1664 return;
1665 }
1666
1667 GCCH_handle_data_ack (ch, msg, fwd);
1668}
1669
1670
1671/**
1672 * Handle channel create.
1673 *
1674 * @param t Tunnel on which the message came.
1675 * @param msg ChannelCreate message.
1676 */
1677static void
1678handle_ch_create (struct CadetTunnel *t,
1679 const struct GNUNET_CADET_ChannelOpenMessage *msg)
1680{
1681 struct CadetChannel *ch;
1682 size_t size;
1683
1684 /* Check size */
1685 size = ntohs (msg->header.size);
1686 if (size != sizeof (struct GNUNET_CADET_ChannelOpenMessage))
1687 {
1688 GNUNET_break_op (0);
1689 return;
1690 }
1691
1692 /* Check channel */
1693 ch = GCT_get_channel (t, msg->ctn);
1694 if (NULL != ch && ! GCT_is_loopback (t))
1695 {
1696 /* Probably a retransmission, safe to ignore */
1697 LOG (GNUNET_ERROR_TYPE_DEBUG, " already exists...\n");
1698 }
1699 ch = GCCH_handle_create (t, msg);
1700 if (NULL != ch)
1701 GCT_add_channel (t, ch);
1702}
1703
1704
1705
1706/**
1707 * Handle channel NACK: check correctness and call channel handler for NACKs.
1708 *
1709 * @param t Tunnel on which the NACK came.
1710 * @param msg NACK message.
1711 */
1712static void
1713handle_ch_nack (struct CadetTunnel *t,
1714 const struct GNUNET_CADET_ChannelManageMessage *msg)
1715{
1716 struct CadetChannel *ch;
1717 size_t size;
1718
1719 /* Check size */
1720 size = ntohs (msg->header.size);
1721 if (size != sizeof (struct GNUNET_CADET_ChannelManageMessage))
1722 {
1723 GNUNET_break (0);
1724 return;
1725 }
1726
1727 /* Check channel */
1728 ch = GCT_get_channel (t, msg->ctn);
1729 if (NULL == ch)
1730 {
1731 GNUNET_STATISTICS_update (stats, "# channel NACK on unknown channel",
1732 1, GNUNET_NO);
1733 LOG (GNUNET_ERROR_TYPE_DEBUG,
1734 "WARNING channel %u unknown\n",
1735 ntohl (msg->ctn.cn));
1736 return;
1737 }
1738
1739 GCCH_handle_nack (ch);
1740}
1741
1742
1743/**
1744 * Handle a CHANNEL ACK (SYNACK/ACK).
1745 *
1746 * @param t Tunnel on which the CHANNEL ACK came.
1747 * @param msg CHANNEL ACK message.
1748 * @param fwd Is this message fwd? This only is meaningful in loopback channels.
1749 * #GNUNET_YES if message is FWD on the respective channel (loopback)
1750 * #GNUNET_NO if message is BCK on the respective channel (loopback)
1751 * #GNUNET_SYSERR if message on a one-ended channel (remote)
1752 */
1753static void
1754handle_ch_ack (struct CadetTunnel *t,
1755 const struct GNUNET_CADET_ChannelManageMessage *msg,
1756 int fwd)
1757{
1758 struct CadetChannel *ch;
1759 size_t size;
1760
1761 /* Check size */
1762 size = ntohs (msg->header.size);
1763 if (size != sizeof (struct GNUNET_CADET_ChannelManageMessage))
1764 {
1765 GNUNET_break (0);
1766 return;
1767 }
1768
1769 /* Check channel */
1770 ch = GCT_get_channel (t, msg->ctn);
1771 if (NULL == ch)
1772 {
1773 GNUNET_STATISTICS_update (stats,
1774 "# channel ack on unknown channel",
1775 1,
1776 GNUNET_NO);
1777 LOG (GNUNET_ERROR_TYPE_DEBUG,
1778 "WARNING channel %u unknown\n",
1779 ntohl (msg->ctn.cn));
1780 return;
1781 }
1782
1783 GCCH_handle_ack (ch, msg, fwd);
1784}
1785
1786
1787/**
1788 * Handle a channel destruction message.
1789 *
1790 * @param t Tunnel on which the message came.
1791 * @param msg Channel destroy message.
1792 * @param fwd Is this message fwd? This only is meaningful in loopback channels.
1793 * #GNUNET_YES if message is FWD on the respective channel (loopback)
1794 * #GNUNET_NO if message is BCK on the respective channel (loopback)
1795 * #GNUNET_SYSERR if message on a one-ended channel (remote)
1796 */
1797static void
1798handle_ch_destroy (struct CadetTunnel *t,
1799 const struct GNUNET_CADET_ChannelManageMessage *msg,
1800 int fwd)
1801{
1802 struct CadetChannel *ch;
1803 size_t size;
1804
1805 /* Check size */
1806 size = ntohs (msg->header.size);
1807 if (size != sizeof (struct GNUNET_CADET_ChannelManageMessage))
1808 {
1809 GNUNET_break (0);
1810 return;
1811 }
1812
1813 /* Check channel */
1814 ch = GCT_get_channel (t, msg->ctn);
1815 if (NULL == ch)
1816 {
1817 /* Probably a retransmission, safe to ignore */
1818 return;
1819 }
1820
1821 GCCH_handle_destroy (ch, msg, fwd);
1822}
1823
1824
1825/**
1826 * Free Axolotl data.
1827 *
1828 * @param t Tunnel.
1829 */
1830static void
1831destroy_ax (struct CadetTunnel *t)
1832{
1833 if (NULL == t->ax)
1834 return;
1835
1836 GNUNET_free_non_null (t->ax->DHRs);
1837 GNUNET_free_non_null (t->ax->kx_0);
1838 while (NULL != t->ax->skipped_head)
1839 delete_skipped_key (t, t->ax->skipped_head);
1840 GNUNET_assert (0 == t->ax->skipped);
1841
1842 GNUNET_free (t->ax);
1843 t->ax = NULL;
1844
1845 if (NULL != t->rekey_task)
1846 {
1847 GNUNET_SCHEDULER_cancel (t->rekey_task);
1848 t->rekey_task = NULL;
1849 }
1850 if (NULL != t->ephm_h)
1851 {
1852 GCC_cancel (t->ephm_h);
1853 t->ephm_h = NULL;
1854 }
1855}
1856
1857
1858/**
1859 * Demultiplex by message type and call appropriate handler for a message
1860 * towards a channel of a local tunnel.
1861 *
1862 * @param t Tunnel this message came on.
1863 * @param msgh Message header.
1864 * @param fwd Is this message fwd? This only is meaningful in loopback channels.
1865 * #GNUNET_YES if message is FWD on the respective channel (loopback)
1866 * #GNUNET_NO if message is BCK on the respective channel (loopback)
1867 * #GNUNET_SYSERR if message on a one-ended channel (remote)
1868 */
1869static void
1870handle_decrypted (struct CadetTunnel *t,
1871 const struct GNUNET_MessageHeader *msgh,
1872 int fwd)
1873{
1874 uint16_t type;
1875 char buf[256];
1876
1877 type = ntohs (msgh->type);
1878 LOG (GNUNET_ERROR_TYPE_DEBUG, "<-- %s on %s\n", GC_m2s (type), GCT_2s (t));
1879 SPRINTF (buf, "# received encrypted of type %hu (%s)", type, GC_m2s (type));
1880 GNUNET_STATISTICS_update (stats, buf, 1, GNUNET_NO);
1881
1882 switch (type)
1883 {
1884 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE:
1885 /* Do nothing, connection aleady got updated. */
1886 GNUNET_STATISTICS_update (stats, "# keepalives received", 1, GNUNET_NO);
1887 break;
1888
1889 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
1890 /* Don't send hop ACK, wait for client to ACK */
1891 handle_data (t, (struct GNUNET_CADET_ChannelAppDataMessage *) msgh, fwd);
1892 break;
1893
1894 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
1895 handle_data_ack (t, (struct GNUNET_CADET_ChannelDataAckMessage *) msgh, fwd);
1896 break;
1897
1898 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
1899 handle_ch_create (t, (struct GNUNET_CADET_ChannelOpenMessage *) msgh);
1900 break;
1901
1902 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
1903 handle_ch_nack (t, (struct GNUNET_CADET_ChannelManageMessage *) msgh);
1904 break;
1905
1906 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
1907 handle_ch_ack (t, (struct GNUNET_CADET_ChannelManageMessage *) msgh, fwd);
1908 break;
1909
1910 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
1911 handle_ch_destroy (t, (struct GNUNET_CADET_ChannelManageMessage *) msgh, fwd);
1912 break;
1913
1914 default:
1915 GNUNET_break_op (0);
1916 LOG (GNUNET_ERROR_TYPE_WARNING,
1917 "end-to-end message not known (%u)\n",
1918 ntohs (msgh->type));
1919 GCT_debug (t, GNUNET_ERROR_TYPE_WARNING);
1920 }
1921}
1922
1923
1924/******************************************************************************/
1925/******************************** API ***********************************/
1926/******************************************************************************/
1927
1928/**
1929 * Decrypt and process an encrypted message.
1930 *
1931 * Calls the appropriate handler for a message in a channel of a local tunnel.
1932 *
1933 * @param t Tunnel this message came on.
1934 * @param msg Message header.
1935 */
1936void
1937GCT_handle_encrypted (struct CadetTunnel *t,
1938 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1939{
1940 uint16_t size = ntohs (msg->header.size);
1941 char cbuf [size];
1942 int decrypted_size;
1943 const struct GNUNET_MessageHeader *msgh;
1944 unsigned int off;
1945
1946 GNUNET_STATISTICS_update (stats, "# received encrypted", 1, GNUNET_NO);
1947
1948 decrypted_size = t_ax_decrypt_and_validate (t, cbuf, msg, size);
1949
1950 if (-1 == decrypted_size)
1951 {
1952 GNUNET_STATISTICS_update (stats, "# unable to decrypt", 1, GNUNET_NO);
1953 if (CADET_TUNNEL_KEY_AX_AUTH_SENT <= t->estate)
1954 {
1955 GNUNET_break_op (0);
1956 LOG (GNUNET_ERROR_TYPE_WARNING, "Wrong crypto, tunnel %s\n", GCT_2s (t));
1957 GCT_debug (t, GNUNET_ERROR_TYPE_WARNING);
1958 }
1959 return;
1960 }
1961 GCT_change_estate (t, CADET_TUNNEL_KEY_OK);
1962
1963 /* FIXME: this is bad, as the structs returned from
1964 this loop may be unaligned, see util's MST for
1965 how to do this right. */
1966 off = 0;
1967 while (off + sizeof (struct GNUNET_MessageHeader) <= decrypted_size)
1968 {
1969 uint16_t msize;
1970
1971 msgh = (const struct GNUNET_MessageHeader *) &cbuf[off];
1972 msize = ntohs (msgh->size);
1973 if (msize < sizeof (struct GNUNET_MessageHeader))
1974 {
1975 GNUNET_break_op (0);
1976 return;
1977 }
1978 if (off + msize < decrypted_size)
1979 {
1980 GNUNET_break_op (0);
1981 return;
1982 }
1983 handle_decrypted (t, msgh, GNUNET_SYSERR);
1984 off += msize;
1985 }
1986}
1987
1988
1989/**
1990 * Handle a Key eXchange message.
1991 *
1992 * @param t Tunnel on which the message came.
1993 * @param msg KX message itself.
1994 */
1995void
1996GCT_handle_kx (struct CadetTunnel *t,
1997 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
1998{
1999 struct CadetTunnelAxolotl *ax;
2000 struct GNUNET_HashCode key_material[3];
2001 struct GNUNET_CRYPTO_SymmetricSessionKey keys[5];
2002 const char salt[] = "CADET Axolotl salt";
2003 const struct GNUNET_PeerIdentity *pid;
2004 int am_I_alice;
2005
2006 CADET_TIMING_START;
2007
2008 LOG (GNUNET_ERROR_TYPE_INFO, "<== { KX} on %s\n", GCT_2s (t));
2009
2010 if (NULL == t->ax)
2011 {
2012 /* Something is wrong if ax is NULL. Whose fault it is? */
2013 return;
2014 }
2015 ax = t->ax;
2016
2017 pid = GCT_get_destination (t);
2018 if (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, pid))
2019 am_I_alice = GNUNET_YES;
2020 else if (0 < GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, pid))
2021 am_I_alice = GNUNET_NO;
2022 else
2023 {
2024 GNUNET_break_op (0);
2025 return;
2026 }
2027
2028 if (0 != (GNUNET_CADET_KX_FLAG_FORCE_REPLY & ntohl (msg->flags)))
2029 {
2030 if (NULL != t->rekey_task)
2031 {
2032 GNUNET_SCHEDULER_cancel (t->rekey_task);
2033 t->rekey_task = NULL;
2034 }
2035 GCT_send_kx (t, GNUNET_NO);
2036 }
2037
2038 if (0 == memcmp (&ax->DHRr, &msg->ratchet_key, sizeof(msg->ratchet_key)))
2039 {
2040 LOG (GNUNET_ERROR_TYPE_INFO, " known ratchet key, exit\n");
2041 return;
2042 }
2043
2044 LOG (GNUNET_ERROR_TYPE_INFO, " is Alice? %s\n", am_I_alice ? "YES" : "NO");
2045
2046 ax->DHRr = msg->ratchet_key;
2047
2048 /* ECDH A B0 */
2049 if (GNUNET_YES == am_I_alice)
2050 {
2051 GNUNET_CRYPTO_eddsa_ecdh (id_key, /* A */
2052 &msg->ephemeral_key, /* B0 */
2053 &key_material[0]);
2054 }
2055 else
2056 {
2057 GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0, /* B0 */
2058 &pid->public_key, /* A */
2059 &key_material[0]);
2060 }
2061
2062 /* ECDH A0 B */
2063 if (GNUNET_YES == am_I_alice)
2064 {
2065 GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0, /* A0 */
2066 &pid->public_key, /* B */
2067 &key_material[1]);
2068 }
2069 else
2070 {
2071 GNUNET_CRYPTO_eddsa_ecdh (id_key, /* A */
2072 &msg->ephemeral_key, /* B0 */
2073 &key_material[1]);
2074
2075
2076 }
2077
2078 /* ECDH A0 B0 */
2079 /* (This is the triple-DH, we could probably safely skip this,
2080 as A0/B0 are already in the key material.) */
2081 GNUNET_CRYPTO_ecc_ecdh (ax->kx_0, /* A0 or B0 */
2082 &msg->ephemeral_key, /* B0 or A0 */
2083 &key_material[2]);
2084
2085 #if DUMP_KEYS_TO_STDERR
2086 {
2087 unsigned int i;
2088 for (i = 0; i < 3; i++)
2089 LOG (GNUNET_ERROR_TYPE_INFO, "km[%u]: %s\n",
2090 i, GNUNET_h2s (&key_material[i]));
2091 }
2092 #endif
2093
2094 /* KDF */
2095 GNUNET_CRYPTO_kdf (keys, sizeof (keys),
2096 salt, sizeof (salt),
2097 &key_material, sizeof (key_material), NULL);
2098
2099 if (0 == memcmp (&ax->RK, &keys[0], sizeof(ax->RK)))
2100 {
2101 LOG (GNUNET_ERROR_TYPE_INFO, " known handshake key, exit\n");
2102 return;
2103 }
2104 ax->RK = keys[0];
2105 if (GNUNET_YES == am_I_alice)
2106 {
2107 ax->HKr = keys[1];
2108 ax->NHKs = keys[2];
2109 ax->NHKr = keys[3];
2110 ax->CKr = keys[4];
2111 ax->ratchet_flag = GNUNET_YES;
2112 }
2113 else
2114 {
2115 ax->HKs = keys[1];
2116 ax->NHKr = keys[2];
2117 ax->NHKs = keys[3];
2118 ax->CKs = keys[4];
2119 ax->ratchet_flag = GNUNET_NO;
2120 ax->ratchet_allowed = GNUNET_NO;
2121 ax->ratchet_counter = 0;
2122 ax->ratchet_expiration =
2123 GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), ratchet_time);
2124 }
2125 ax->PNs = 0;
2126 ax->Nr = 0;
2127 ax->Ns = 0;
2128
2129 GCT_change_estate (t, CADET_TUNNEL_KEY_AX_AUTH_SENT);
2130 send_queued_data (t);
2131
2132 CADET_TIMING_END;
2133}
2134
2135/**
2136 * Initialize the tunnel subsystem.
2137 *
2138 * @param c Configuration handle.
2139 * @param key ECC private key, to derive all other keys and do crypto.
2140 */
2141void
2142GCT_init (const struct GNUNET_CONFIGURATION_Handle *c,
2143 const struct GNUNET_CRYPTO_EddsaPrivateKey *key)
2144{
2145 unsigned int expected_overhead;
2146
2147 LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
2148
2149 expected_overhead = 0;
2150 expected_overhead += sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
2151 expected_overhead += sizeof (struct GNUNET_CADET_ChannelAppDataMessage);
2152 expected_overhead += sizeof (struct GNUNET_CADET_ConnectionEncryptedAckMessage);
2153 GNUNET_assert (GNUNET_CONSTANTS_CADET_P2P_OVERHEAD == expected_overhead);
2154
2155 if (GNUNET_OK !=
2156 GNUNET_CONFIGURATION_get_value_number (c,
2157 "CADET",
2158 "RATCHET_MESSAGES",
2159 &ratchet_messages))
2160 {
2161 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
2162 "CADET",
2163 "RATCHET_MESSAGES",
2164 "USING DEFAULT");
2165 ratchet_messages = 64;
2166 }
2167 if (GNUNET_OK !=
2168 GNUNET_CONFIGURATION_get_value_time (c,
2169 "CADET",
2170 "RATCHET_TIME",
2171 &ratchet_time))
2172 {
2173 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
2174 "CADET", "RATCHET_TIME", "USING DEFAULT");
2175 ratchet_time = GNUNET_TIME_UNIT_HOURS;
2176 }
2177
2178
2179 id_key = key;
2180 tunnels = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES);
2181}
2182
2183
2184/**
2185 * Shut down the tunnel subsystem.
2186 */
2187void
2188GCT_shutdown (void)
2189{
2190 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down tunnels\n");
2191 GNUNET_CONTAINER_multipeermap_iterate (tunnels, &destroy_iterator, NULL);
2192 GNUNET_CONTAINER_multipeermap_destroy (tunnels);
2193}
2194
2195
2196/**
2197 * Create a tunnel.
2198 *
2199 * @param destination Peer this tunnel is towards.
2200 */
2201struct CadetTunnel *
2202GCT_new (struct CadetPeer *destination)
2203{
2204 struct CadetTunnel *t;
2205
2206 t = GNUNET_new (struct CadetTunnel);
2207 t->next_ctn.cn = 0;
2208 t->peer = destination;
2209
2210 if (GNUNET_OK !=
2211 GNUNET_CONTAINER_multipeermap_put (tunnels, GCP_get_id (destination), t,
2212 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
2213 {
2214 GNUNET_break (0);
2215 GNUNET_free (t);
2216 return NULL;
2217 }
2218 t->ax = GNUNET_new (struct CadetTunnelAxolotl);
2219 new_ephemeral (t);
2220 t->ax->kx_0 = GNUNET_CRYPTO_ecdhe_key_create ();
2221 return t;
2222}
2223
2224
2225/**
2226 * Change the tunnel's connection state.
2227 *
2228 * @param t Tunnel whose connection state to change.
2229 * @param cstate New connection state.
2230 */
2231void
2232GCT_change_cstate (struct CadetTunnel* t, enum CadetTunnelCState cstate)
2233{
2234 if (NULL == t)
2235 return;
2236 LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s cstate %s => %s\n",
2237 GCP_2s (t->peer), cstate2s (t->cstate), cstate2s (cstate));
2238 if (myid != GCP_get_short_id (t->peer) &&
2239 CADET_TUNNEL_READY != t->cstate &&
2240 CADET_TUNNEL_READY == cstate)
2241 {
2242 t->cstate = cstate;
2243 if (CADET_TUNNEL_KEY_OK == t->estate)
2244 {
2245 LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate triggered send queued data\n");
2246 send_queued_data (t);
2247 }
2248 else if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate)
2249 {
2250 LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate triggered KX\n");
2251 GCT_send_kx (t, GNUNET_NO);
2252 }
2253 else
2254 {
2255 LOG (GNUNET_ERROR_TYPE_DEBUG, "estate %s\n", estate2s (t->estate));
2256 }
2257 }
2258 t->cstate = cstate;
2259
2260 if (CADET_TUNNEL_READY == cstate
2261 && CONNECTIONS_PER_TUNNEL <= GCT_count_connections (t))
2262 {
2263 LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate triggered stop dht\n");
2264 GCP_stop_search (t->peer);
2265 }
2266}
2267
2268
2269/**
2270 * Change the tunnel encryption state.
2271 *
2272 * If the encryption state changes to OK, stop the rekey task.
2273 *
2274 * @param t Tunnel whose encryption state to change, or NULL.
2275 * @param state New encryption state.
2276 */
2277void
2278GCT_change_estate (struct CadetTunnel* t, enum CadetTunnelEState state)
2279{
2280 enum CadetTunnelEState old;
2281
2282 if (NULL == t)
2283 return;
2284
2285 old = t->estate;
2286 t->estate = state;
2287 LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s estate was %s\n",
2288 GCP_2s (t->peer), estate2s (old));
2289 LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s estate is now %s\n",
2290 GCP_2s (t->peer), estate2s (t->estate));
2291
2292 if (CADET_TUNNEL_KEY_OK != old && CADET_TUNNEL_KEY_OK == t->estate)
2293 {
2294 if (NULL != t->rekey_task)
2295 {
2296 GNUNET_SCHEDULER_cancel (t->rekey_task);
2297 t->rekey_task = NULL;
2298 }
2299 /* Send queued data if tunnel is not loopback */
2300 if (myid != GCP_get_short_id (t->peer))
2301 send_queued_data (t);
2302 }
2303}
2304
2305
2306/**
2307 * @brief Check if tunnel has too many connections, and remove one if necessary.
2308 *
2309 * Currently this means the newest connection, unless it is a direct one.
2310 * Implemented as a task to avoid freeing a connection that is in the middle
2311 * of being created/processed.
2312 *
2313 * @param cls Closure (Tunnel to check).
2314 */
2315static void
2316trim_connections (void *cls)
2317{
2318 struct CadetTunnel *t = cls;
2319
2320 t->trim_connections_task = NULL;
2321 if (GCT_count_connections (t) > 2 * CONNECTIONS_PER_TUNNEL)
2322 {
2323 struct CadetTConnection *iter;
2324 struct CadetTConnection *c;
2325
2326 for (c = iter = t->connection_head; NULL != iter; iter = iter->next)
2327 {
2328 if ((iter->created.abs_value_us > c->created.abs_value_us)
2329 && GNUNET_NO == GCC_is_direct (iter->c))
2330 {
2331 c = iter;
2332 }
2333 }
2334 if (NULL != c)
2335 {
2336 LOG (GNUNET_ERROR_TYPE_DEBUG, "Too many connections on tunnel %s\n",
2337 GCT_2s (t));
2338 LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying connection %s\n",
2339 GCC_2s (c->c));
2340 GCC_destroy (c->c);
2341 }
2342 else
2343 {
2344 GNUNET_break (0);
2345 }
2346 }
2347}
2348
2349
2350/**
2351 * Add a connection to a tunnel.
2352 *
2353 * @param t Tunnel.
2354 * @param c Connection.
2355 */
2356void
2357GCT_add_connection (struct CadetTunnel *t, struct CadetConnection *c)
2358{
2359 struct CadetTConnection *aux;
2360
2361 GNUNET_assert (NULL != c);
2362
2363 LOG (GNUNET_ERROR_TYPE_DEBUG, "add connection %s\n", GCC_2s (c));
2364 LOG (GNUNET_ERROR_TYPE_DEBUG, " to tunnel %s\n", GCT_2s (t));
2365 for (aux = t->connection_head; aux != NULL; aux = aux->next)
2366 if (aux->c == c)
2367 return;
2368
2369 aux = GNUNET_new (struct CadetTConnection);
2370 aux->c = c;
2371 aux->created = GNUNET_TIME_absolute_get ();
2372
2373 GNUNET_CONTAINER_DLL_insert (t->connection_head, t->connection_tail, aux);
2374
2375 if (CADET_TUNNEL_SEARCHING == t->cstate)
2376 GCT_change_cstate (t, CADET_TUNNEL_WAITING);
2377
2378 if (NULL != t->trim_connections_task)
2379 t->trim_connections_task = GNUNET_SCHEDULER_add_now (&trim_connections, t);
2380}
2381
2382
2383/**
2384 * Remove a connection from a tunnel.
2385 *
2386 * @param t Tunnel.
2387 * @param c Connection.
2388 */
2389void
2390GCT_remove_connection (struct CadetTunnel *t,
2391 struct CadetConnection *c)
2392{
2393 struct CadetTConnection *aux;
2394 struct CadetTConnection *next;
2395 unsigned int conns;
2396
2397 LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing connection %s from tunnel %s\n",
2398 GCC_2s (c), GCT_2s (t));
2399 for (aux = t->connection_head; aux != NULL; aux = next)
2400 {
2401 next = aux->next;
2402 if (aux->c == c)
2403 {
2404 GNUNET_CONTAINER_DLL_remove (t->connection_head, t->connection_tail, aux);
2405 GNUNET_free (aux);
2406 }
2407 }
2408
2409 conns = GCT_count_connections (t);
2410 if (0 == conns
2411 && NULL == t->destroy_task
2412 && CADET_TUNNEL_SHUTDOWN != t->cstate
2413 && GNUNET_NO == shutting_down)
2414 {
2415 if (0 == GCT_count_any_connections (t))
2416 GCT_change_cstate (t, CADET_TUNNEL_SEARCHING);
2417 else
2418 GCT_change_cstate (t, CADET_TUNNEL_WAITING);
2419 }
2420
2421 /* Start new connections if needed */
2422 if (CONNECTIONS_PER_TUNNEL > conns
2423 && CADET_TUNNEL_SHUTDOWN != t->cstate
2424 && GNUNET_NO == shutting_down)
2425 {
2426 LOG (GNUNET_ERROR_TYPE_DEBUG, " too few connections, getting new ones\n");
2427 GCP_connect (t->peer); /* Will change cstate to WAITING when possible */
2428 return;
2429 }
2430
2431 /* If not marked as ready, no change is needed */
2432 if (CADET_TUNNEL_READY != t->cstate)
2433 return;
2434
2435 /* Check if any connection is ready to maintain cstate */
2436 for (aux = t->connection_head; aux != NULL; aux = aux->next)
2437 if (CADET_CONNECTION_READY == GCC_get_state (aux->c))
2438 return;
2439}
2440
2441
2442/**
2443 * Add a channel to a tunnel.
2444 *
2445 * @param t Tunnel.
2446 * @param ch Channel.
2447 */
2448void
2449GCT_add_channel (struct CadetTunnel *t,
2450 struct CadetChannel *ch)
2451{
2452 struct CadetTChannel *aux;
2453
2454 GNUNET_assert (NULL != ch);
2455
2456 LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding channel %p to tunnel %p\n", ch, t);
2457
2458 for (aux = t->channel_head; aux != NULL; aux = aux->next)
2459 {
2460 LOG (GNUNET_ERROR_TYPE_DEBUG, " already there %p\n", aux->ch);
2461 if (aux->ch == ch)
2462 return;
2463 }
2464
2465 aux = GNUNET_new (struct CadetTChannel);
2466 aux->ch = ch;
2467 LOG (GNUNET_ERROR_TYPE_DEBUG,
2468 " adding %p to %p\n", aux, t->channel_head);
2469 GNUNET_CONTAINER_DLL_insert_tail (t->channel_head,
2470 t->channel_tail,
2471 aux);
2472
2473 if (NULL != t->destroy_task)
2474 {
2475 GNUNET_SCHEDULER_cancel (t->destroy_task);
2476 t->destroy_task = NULL;
2477 LOG (GNUNET_ERROR_TYPE_DEBUG, " undo destroy!\n");
2478 }
2479}
2480
2481
2482/**
2483 * Remove a channel from a tunnel.
2484 *
2485 * @param t Tunnel.
2486 * @param ch Channel.
2487 */
2488void
2489GCT_remove_channel (struct CadetTunnel *t, struct CadetChannel *ch)
2490{
2491 struct CadetTChannel *aux;
2492
2493 LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing channel %p from tunnel %p\n", ch, t);
2494 for (aux = t->channel_head; aux != NULL; aux = aux->next)
2495 {
2496 if (aux->ch == ch)
2497 {
2498 LOG (GNUNET_ERROR_TYPE_DEBUG, " found! %s\n", GCCH_2s (ch));
2499 GNUNET_CONTAINER_DLL_remove (t->channel_head,
2500 t->channel_tail,
2501 aux);
2502 GNUNET_free (aux);
2503 return;
2504 }
2505 }
2506}
2507
2508
2509/**
2510 * Search for a channel by global ID.
2511 *
2512 * @param t Tunnel containing the channel.
2513 * @param ctn Public channel number.
2514 *
2515 * @return channel handler, NULL if doesn't exist
2516 */
2517struct CadetChannel *
2518GCT_get_channel (struct CadetTunnel *t,
2519 struct GNUNET_CADET_ChannelTunnelNumber ctn)
2520{
2521 struct CadetTChannel *iter;
2522
2523 if (NULL == t)
2524 return NULL;
2525
2526 for (iter = t->channel_head; NULL != iter; iter = iter->next)
2527 {
2528 if (GCCH_get_id (iter->ch).cn == ctn.cn)
2529 break;
2530 }
2531
2532 return NULL == iter ? NULL : iter->ch;
2533}
2534
2535
2536/**
2537 * @brief Destroy a tunnel and free all resources.
2538 *
2539 * Should only be called a while after the tunnel has been marked as destroyed,
2540 * in case there is a new channel added to the same peer shortly after marking
2541 * the tunnel. This way we avoid a new public key handshake.
2542 *
2543 * @param cls Closure (tunnel to destroy).
2544 */
2545static void
2546delayed_destroy (void *cls)
2547{
2548 struct CadetTunnel *t = cls;
2549 struct CadetTConnection *iter;
2550
2551 t->destroy_task = NULL;
2552 LOG (GNUNET_ERROR_TYPE_DEBUG,
2553 "delayed destroying tunnel %p\n",
2554 t);
2555 t->cstate = CADET_TUNNEL_SHUTDOWN;
2556 for (iter = t->connection_head; NULL != iter; iter = iter->next)
2557 {
2558 GCC_send_destroy (iter->c);
2559 }
2560 GCT_destroy (t);
2561}
2562
2563
2564/**
2565 * Tunnel is empty: destroy it.
2566 *
2567 * Notifies all connections about the destruction.
2568 *
2569 * @param t Tunnel to destroy.
2570 */
2571void
2572GCT_destroy_empty (struct CadetTunnel *t)
2573{
2574 if (GNUNET_YES == shutting_down)
2575 return; /* Will be destroyed immediately anyway */
2576
2577 if (NULL != t->destroy_task)
2578 {
2579 LOG (GNUNET_ERROR_TYPE_WARNING,
2580 "Tunnel %s is already scheduled for destruction. Tunnel debug dump:\n",
2581 GCT_2s (t));
2582 GCT_debug (t, GNUNET_ERROR_TYPE_WARNING);
2583 GNUNET_break (0);
2584 /* should never happen, tunnel can only become empty once, and the
2585 * task identifier should be NO_TASK (cleaned when the tunnel was created
2586 * or became un-empty)
2587 */
2588 return;
2589 }
2590
2591 LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s empty: scheduling destruction\n",
2592 GCT_2s (t));
2593
2594 // FIXME make delay a config option
2595 t->destroy_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
2596 &delayed_destroy, t);
2597 LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduled destroy of %p as %p\n",
2598 t, t->destroy_task);
2599}
2600
2601
2602/**
2603 * Destroy tunnel if empty (no more channels).
2604 *
2605 * @param t Tunnel to destroy if empty.
2606 */
2607void
2608GCT_destroy_if_empty (struct CadetTunnel *t)
2609{
2610 LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s destroy if empty\n", GCT_2s (t));
2611 if (0 < GCT_count_channels (t))
2612 return;
2613
2614 GCT_destroy_empty (t);
2615}
2616
2617
2618/**
2619 * Destroy the tunnel.
2620 *
2621 * This function does not generate any warning traffic to clients or peers.
2622 *
2623 * Tasks:
2624 * Cancel messages belonging to this tunnel queued to neighbors.
2625 * Free any allocated resources linked to the tunnel.
2626 *
2627 * @param t The tunnel to destroy.
2628 */
2629void
2630GCT_destroy (struct CadetTunnel *t)
2631{
2632 struct CadetTConnection *iter_c;
2633 struct CadetTConnection *next_c;
2634 struct CadetTChannel *iter_ch;
2635 struct CadetTChannel *next_ch;
2636 unsigned int keepalives_queued;
2637
2638 if (NULL == t)
2639 return;
2640
2641 LOG (GNUNET_ERROR_TYPE_DEBUG,
2642 "destroying tunnel %s\n",
2643 GCP_2s (t->peer));
2644 GNUNET_break (GNUNET_YES ==
2645 GNUNET_CONTAINER_multipeermap_remove (tunnels,
2646 GCP_get_id (t->peer), t));
2647
2648 for (iter_c = t->connection_head; NULL != iter_c; iter_c = next_c)
2649 {
2650 next_c = iter_c->next;
2651 GCC_destroy (iter_c->c);
2652 }
2653 for (iter_ch = t->channel_head; NULL != iter_ch; iter_ch = next_ch)
2654 {
2655 next_ch = iter_ch->next;
2656 GCCH_destroy (iter_ch->ch);
2657 /* Should only happen on shutdown, but it's ok. */
2658 }
2659 keepalives_queued = 0;
2660 while (NULL != t->tq_head)
2661 {
2662 /* Should have been cleaned by destuction of channel. */
2663 struct GNUNET_MessageHeader *mh;
2664 uint16_t type;
2665
2666 mh = (struct GNUNET_MessageHeader *) &t->tq_head[1];
2667 type = ntohs (mh->type);
2668 if (0 == keepalives_queued && GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE == type)
2669 {
2670 keepalives_queued = 1;
2671 LOG (GNUNET_ERROR_TYPE_DEBUG,
2672 "one keepalive left behind on tunnel shutdown\n");
2673 }
2674 else if (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY == type)
2675 {
2676 LOG (GNUNET_ERROR_TYPE_WARNING,
2677 "tunnel destroyed before a CHANNEL_DESTROY was sent to peer\n");
2678 }
2679 else
2680 {
2681 GNUNET_break (0);
2682 LOG (GNUNET_ERROR_TYPE_ERROR,
2683 "message left behind on tunnel shutdown: %s\n",
2684 GC_m2s (type));
2685 }
2686 unqueue_data (t->tq_head);
2687 }
2688
2689
2690 if (NULL != t->destroy_task)
2691 {
2692 LOG (GNUNET_ERROR_TYPE_DEBUG,
2693 "cancelling dest: %p\n",
2694 t->destroy_task);
2695 GNUNET_SCHEDULER_cancel (t->destroy_task);
2696 t->destroy_task = NULL;
2697 }
2698
2699 if (NULL != t->trim_connections_task)
2700 {
2701 LOG (GNUNET_ERROR_TYPE_DEBUG, "cancelling trim: %p\n",
2702 t->trim_connections_task);
2703 GNUNET_SCHEDULER_cancel (t->trim_connections_task);
2704 t->trim_connections_task = NULL;
2705 }
2706
2707 GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO);
2708 GCP_set_tunnel (t->peer, NULL);
2709
2710 if (NULL != t->rekey_task)
2711 {
2712 GNUNET_SCHEDULER_cancel (t->rekey_task);
2713 t->rekey_task = NULL;
2714 }
2715 if (NULL != t->ax)
2716 destroy_ax (t);
2717
2718 GNUNET_free (t);
2719}
2720
2721
2722/**
2723 * @brief Use the given path for the tunnel.
2724 * Update the next and prev hops (and RCs).
2725 * (Re)start the path refresh in case the tunnel is locally owned.
2726 *
2727 * @param t Tunnel to update.
2728 * @param p Path to use.
2729 *
2730 * @return Connection created.
2731 */
2732struct CadetConnection *
2733GCT_use_path (struct CadetTunnel *t, struct CadetPeerPath *path)
2734{
2735 struct CadetConnection *c;
2736 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
2737 unsigned int own_pos;
2738
2739 if (NULL == t || NULL == path)
2740 {
2741 GNUNET_break (0);
2742 return NULL;
2743 }
2744
2745 if (CADET_TUNNEL_SHUTDOWN == t->cstate)
2746 {
2747 GNUNET_break (0);
2748 return NULL;
2749 }
2750
2751 for (own_pos = 0; own_pos < path->length; own_pos++)
2752 {
2753 if (path->peers[own_pos] == myid)
2754 break;
2755 }
2756 if (own_pos >= path->length)
2757 {
2758 GNUNET_break_op (0);
2759 return NULL;
2760 }
2761
2762 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof (cid));
2763 c = GCC_new (&cid, t, path, own_pos);
2764 if (NULL == c)
2765 {
2766 /* Path was flawed */
2767 return NULL;
2768 }
2769 GCT_add_connection (t, c);
2770 return c;
2771}
2772
2773
2774/**
2775 * Count all created connections of a tunnel. Not necessarily ready connections!
2776 *
2777 * @param t Tunnel on which to count.
2778 *
2779 * @return Number of connections created, either being established or ready.
2780 */
2781unsigned int
2782GCT_count_any_connections (struct CadetTunnel *t)
2783{
2784 struct CadetTConnection *iter;
2785 unsigned int count;
2786
2787 if (NULL == t)
2788 return 0;
2789
2790 for (count = 0, iter = t->connection_head; NULL != iter; iter = iter->next)
2791 count++;
2792
2793 return count;
2794}
2795
2796
2797/**
2798 * Count established (ready) connections of a tunnel.
2799 *
2800 * @param t Tunnel on which to count.
2801 *
2802 * @return Number of connections.
2803 */
2804unsigned int
2805GCT_count_connections (struct CadetTunnel *t)
2806{
2807 struct CadetTConnection *iter;
2808 unsigned int count;
2809
2810 if (NULL == t)
2811 return 0;
2812
2813 for (count = 0, iter = t->connection_head; NULL != iter; iter = iter->next)
2814 if (CADET_CONNECTION_READY == GCC_get_state (iter->c))
2815 count++;
2816
2817 return count;
2818}
2819
2820
2821/**
2822 * Count channels of a tunnel.
2823 *
2824 * @param t Tunnel on which to count.
2825 *
2826 * @return Number of channels.
2827 */
2828unsigned int
2829GCT_count_channels (struct CadetTunnel *t)
2830{
2831 struct CadetTChannel *iter;
2832 unsigned int count;
2833
2834 for (count = 0, iter = t->channel_head;
2835 NULL != iter;
2836 iter = iter->next, count++) /* skip */;
2837
2838 return count;
2839}
2840
2841
2842/**
2843 * Get the connectivity state of a tunnel.
2844 *
2845 * @param t Tunnel.
2846 *
2847 * @return Tunnel's connectivity state.
2848 */
2849enum CadetTunnelCState
2850GCT_get_cstate (struct CadetTunnel *t)
2851{
2852 if (NULL == t)
2853 {
2854 GNUNET_assert (0);
2855 return (enum CadetTunnelCState) -1;
2856 }
2857 return t->cstate;
2858}
2859
2860
2861/**
2862 * Get the encryption state of a tunnel.
2863 *
2864 * @param t Tunnel.
2865 *
2866 * @return Tunnel's encryption state.
2867 */
2868enum CadetTunnelEState
2869GCT_get_estate (struct CadetTunnel *t)
2870{
2871 if (NULL == t)
2872 {
2873 GNUNET_break (0);
2874 return (enum CadetTunnelEState) -1;
2875 }
2876 return t->estate;
2877}
2878
2879/**
2880 * Get the maximum buffer space for a tunnel towards a local client.
2881 *
2882 * @param t Tunnel.
2883 *
2884 * @return Biggest buffer space offered by any channel in the tunnel.
2885 */
2886unsigned int
2887GCT_get_channels_buffer (struct CadetTunnel *t)
2888{
2889 struct CadetTChannel *iter;
2890 unsigned int buffer;
2891 unsigned int ch_buf;
2892
2893 if (NULL == t->channel_head)
2894 {
2895 /* Probably getting buffer for a channel create/handshake. */
2896 LOG (GNUNET_ERROR_TYPE_DEBUG, " no channels, allow max\n");
2897 return MIN_TUNNEL_BUFFER;
2898 }
2899
2900 buffer = 0;
2901 for (iter = t->channel_head; NULL != iter; iter = iter->next)
2902 {
2903 ch_buf = get_channel_buffer (iter);
2904 if (ch_buf > buffer)
2905 buffer = ch_buf;
2906 }
2907 if (MIN_TUNNEL_BUFFER > buffer)
2908 return MIN_TUNNEL_BUFFER;
2909
2910 if (MAX_TUNNEL_BUFFER < buffer)
2911 {
2912 GNUNET_break (0);
2913 return MAX_TUNNEL_BUFFER;
2914 }
2915 return buffer;
2916}
2917
2918
2919/**
2920 * Get the total buffer space for a tunnel for P2P traffic.
2921 *
2922 * @param t Tunnel.
2923 *
2924 * @return Buffer space offered by all connections in the tunnel.
2925 */
2926unsigned int
2927GCT_get_connections_buffer (struct CadetTunnel *t)
2928{
2929 struct CadetTConnection *iter;
2930 unsigned int buffer;
2931
2932 if (GNUNET_NO == is_ready (t))
2933 {
2934 if (count_queued_data (t) >= 3)
2935 return 0;
2936 else
2937 return 1;
2938 }
2939
2940 buffer = 0;
2941 for (iter = t->connection_head; NULL != iter; iter = iter->next)
2942 {
2943 if (GCC_get_state (iter->c) != CADET_CONNECTION_READY)
2944 {
2945 continue;
2946 }
2947 buffer += get_connection_buffer (iter);
2948 }
2949
2950 return buffer;
2951}
2952
2953
2954/**
2955 * Get the tunnel's destination.
2956 *
2957 * @param t Tunnel.
2958 *
2959 * @return ID of the destination peer.
2960 */
2961const struct GNUNET_PeerIdentity *
2962GCT_get_destination (struct CadetTunnel *t)
2963{
2964 return GCP_get_id (t->peer);
2965}
2966
2967
2968/**
2969 * Get the tunnel's next free global channel ID.
2970 *
2971 * @param t Tunnel.
2972 *
2973 * @return GID of a channel free to use.
2974 */
2975struct GNUNET_CADET_ChannelTunnelNumber
2976GCT_get_next_ctn (struct CadetTunnel *t)
2977{
2978 struct GNUNET_CADET_ChannelTunnelNumber ctn;
2979 struct GNUNET_CADET_ChannelTunnelNumber mask;
2980 int result;
2981
2982 /* Set bit 30 depending on the ID relationship. Bit 31 is always 0 for GID.
2983 * If our ID is bigger or loopback tunnel, start at 0, bit 30 = 0
2984 * If peer's ID is bigger, start at 0x4... bit 30 = 1
2985 */
2986 result = GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, GCP_get_id (t->peer));
2987 if (0 > result)
2988 mask.cn = htonl (0x40000000);
2989 else
2990 mask.cn = 0x0;
2991 t->next_ctn.cn |= mask.cn;
2992
2993 while (NULL != GCT_get_channel (t, t->next_ctn))
2994 {
2995 LOG (GNUNET_ERROR_TYPE_DEBUG,
2996 "Channel %u exists...\n",
2997 t->next_ctn.cn);
2998 t->next_ctn.cn = htonl ((ntohl (t->next_ctn.cn) + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
2999 t->next_ctn.cn |= mask.cn;
3000 }
3001 ctn = t->next_ctn;
3002 t->next_ctn.cn = (t->next_ctn.cn + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
3003 t->next_ctn.cn |= mask.cn;
3004
3005 return ctn;
3006}
3007
3008
3009/**
3010 * Send ACK on one or more channels due to buffer in connections.
3011 *
3012 * @param t Channel which has some free buffer space.
3013 */
3014void
3015GCT_unchoke_channels (struct CadetTunnel *t)
3016{
3017 struct CadetTChannel *iter;
3018 unsigned int buffer;
3019 unsigned int channels = GCT_count_channels (t);
3020 unsigned int choked_n;
3021 struct CadetChannel *choked[channels];
3022
3023 LOG (GNUNET_ERROR_TYPE_DEBUG, "GCT_unchoke_channels on %s\n", GCT_2s (t));
3024 LOG (GNUNET_ERROR_TYPE_DEBUG, " head: %p\n", t->channel_head);
3025 if (NULL != t->channel_head)
3026 LOG (GNUNET_ERROR_TYPE_DEBUG, " head ch: %p\n", t->channel_head->ch);
3027
3028 if (NULL != t->tq_head)
3029 send_queued_data (t);
3030
3031 /* Get buffer space */
3032 buffer = GCT_get_connections_buffer (t);
3033 if (0 == buffer)
3034 {
3035 return;
3036 }
3037
3038 /* Count and remember choked channels */
3039 choked_n = 0;
3040 for (iter = t->channel_head; NULL != iter; iter = iter->next)
3041 {
3042 if (GNUNET_NO == get_channel_allowed (iter))
3043 {
3044 choked[choked_n++] = iter->ch;
3045 }
3046 }
3047
3048 /* Unchoke random channels */
3049 while (0 < buffer && 0 < choked_n)
3050 {
3051 unsigned int r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
3052 choked_n);
3053 GCCH_allow_client (choked[r], GCCH_is_origin (choked[r], GNUNET_YES));
3054 choked_n--;
3055 buffer--;
3056 choked[r] = choked[choked_n];
3057 }
3058}
3059
3060
3061/**
3062 * Send ACK on one or more connections due to buffer space to the client.
3063 *
3064 * Iterates all connections of the tunnel and sends ACKs appropriately.
3065 *
3066 * @param t Tunnel.
3067 */
3068void
3069GCT_send_connection_acks (struct CadetTunnel *t)
3070{
3071 struct CadetTConnection *iter;
3072 uint32_t allowed;
3073 uint32_t to_allow;
3074 uint32_t allow_per_connection;
3075 unsigned int cs;
3076 unsigned int buffer;
3077
3078 LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel send connection ACKs on %s\n",
3079 GCT_2s (t));
3080
3081 if (NULL == t)
3082 {
3083 GNUNET_break (0);
3084 return;
3085 }
3086
3087 if (CADET_TUNNEL_READY != t->cstate)
3088 return;
3089
3090 buffer = GCT_get_channels_buffer (t);
3091 LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer %u\n", buffer);
3092
3093 /* Count connections, how many messages are already allowed */
3094 cs = GCT_count_connections (t);
3095 for (allowed = 0, iter = t->connection_head; NULL != iter; iter = iter->next)
3096 {
3097 allowed += get_connection_allowed (iter);
3098 }
3099 LOG (GNUNET_ERROR_TYPE_DEBUG, " allowed %u\n", allowed);
3100
3101 /* Make sure there is no overflow */
3102 if (allowed > buffer)
3103 return;
3104
3105 /* Authorize connections to send more data */
3106 to_allow = buffer - allowed;
3107
3108 for (iter = t->connection_head;
3109 NULL != iter && to_allow > 0;
3110 iter = iter->next)
3111 {
3112 if (CADET_CONNECTION_READY != GCC_get_state (iter->c)
3113 || get_connection_allowed (iter) > 64 / 3)
3114 {
3115 continue;
3116 }
3117 GNUNET_assert(cs != 0);
3118 allow_per_connection = to_allow/cs;
3119 to_allow -= allow_per_connection;
3120 cs--;
3121 GCC_allow (iter->c, allow_per_connection,
3122 GCC_is_origin (iter->c, GNUNET_NO));
3123 }
3124
3125 if (0 != to_allow)
3126 {
3127 /* Since we don't allow if it's allowed to send 64/3, this can happen. */
3128 LOG (GNUNET_ERROR_TYPE_DEBUG, " reminding to_allow: %u\n", to_allow);
3129 }
3130}
3131
3132
3133/**
3134 * Cancel a previously sent message while it's in the queue.
3135 *
3136 * ONLY can be called before the continuation given to the send function
3137 * is called. Once the continuation is called, the message is no longer in the
3138 * queue.
3139 *
3140 * @param q Handle to the queue.
3141 */
3142void
3143GCT_cancel (struct CadetTunnelQueue *q)
3144{
3145 if (NULL != q->cq)
3146 {
3147 GNUNET_assert (NULL == q->tqd);
3148 GCC_cancel (q->cq);
3149 /* tun_message_sent() will be called and free q */
3150 }
3151 else if (NULL != q->tqd)
3152 {
3153 unqueue_data (q->tqd);
3154 q->tqd = NULL;
3155 if (NULL != q->cont)
3156 q->cont (q->cont_cls, NULL, q, 0, 0);
3157 GNUNET_free (q);
3158 }
3159 else
3160 {
3161 GNUNET_break (0);
3162 }
3163}
3164
3165
3166/**
3167 * Check if the tunnel has queued traffic.
3168 *
3169 * @param t Tunnel to check.
3170 *
3171 * @return #GNUNET_YES if there is queued traffic
3172 * #GNUNET_NO otherwise
3173 */
3174int
3175GCT_has_queued_traffic (struct CadetTunnel *t)
3176{
3177 return (NULL != t->tq_head) ? GNUNET_YES : GNUNET_NO;
3178}
3179
3180
3181/**
3182 * Sends an already built message on a tunnel, encrypting it and
3183 * choosing the best connection if not provided.
3184 *
3185 * @param message Message to send. Function modifies it.
3186 * @param t Tunnel on which this message is transmitted.
3187 * @param c Connection to use (autoselect if NULL).
3188 * @param force Force the tunnel to take the message (buffer overfill).
3189 * @param cont Continuation to call once message is really sent.
3190 * @param cont_cls Closure for @c cont.
3191 *
3192 * @return Handle to cancel message. NULL if @c cont is NULL.
3193 */
3194struct CadetTunnelQueue *
3195GCT_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
3196 struct CadetTunnel *t,
3197 struct CadetConnection *c,
3198 int force, GCT_sent cont, void *cont_cls)
3199{
3200 return send_prebuilt_message (message, t, c, force, cont, cont_cls, NULL);
3201}
3202
3203
3204/**
3205 * Send a KX message.
3206 *
3207 * @param t Tunnel on which to send it.
3208 * @param force_reply Force the other peer to reply with a KX message.
3209 */
3210void
3211GCT_send_kx (struct CadetTunnel *t, int force_reply)
3212{
3213 static struct CadetEncryptedMessageIdentifier zero;
3214 struct CadetConnection *c;
3215 struct GNUNET_CADET_TunnelKeyExchangeMessage msg;
3216 enum GNUNET_CADET_KX_Flags flags;
3217
3218 LOG (GNUNET_ERROR_TYPE_INFO, "==> { KX} on %s\n", GCT_2s (t));
3219 if (NULL != t->ephm_h)
3220 {
3221 LOG (GNUNET_ERROR_TYPE_INFO, " already queued, nop\n");
3222 return;
3223 }
3224 GNUNET_assert (GNUNET_NO == GCT_is_loopback (t));
3225
3226 c = tunnel_get_connection (t);
3227 if (NULL == c)
3228 {
3229 if (NULL == t->destroy_task && CADET_TUNNEL_READY == t->cstate)
3230 {
3231 GNUNET_break (0);
3232 GCT_debug (t, GNUNET_ERROR_TYPE_ERROR);
3233 }
3234 return;
3235 }
3236
3237 msg.header.size = htons (sizeof (msg));
3238 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX);
3239 flags = GNUNET_CADET_KX_FLAG_NONE;
3240 if (GNUNET_YES == force_reply)
3241 flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY;
3242 msg.flags = htonl (flags);
3243 msg.cid = *GCC_get_id (c);
3244 GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->kx_0, &msg.ephemeral_key);
3245 GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->DHRs, &msg.ratchet_key);
3246
3247 t->ephm_h = GCC_send_prebuilt_message (&msg.header,
3248 UINT16_MAX,
3249 zero,
3250 c,
3251 GCC_is_origin (c, GNUNET_YES),
3252 GNUNET_YES, &ephm_sent, t);
3253 if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate)
3254 GCT_change_estate (t, CADET_TUNNEL_KEY_AX_SENT);
3255}
3256
3257
3258/**
3259 * Is the tunnel directed towards the local peer?
3260 *
3261 * @param t Tunnel.
3262 *
3263 * @return #GNUNET_YES if it is loopback.
3264 */
3265int
3266GCT_is_loopback (const struct CadetTunnel *t)
3267{
3268 return (myid == GCP_get_short_id (t->peer));
3269}
3270
3271
3272/**
3273 * Is the tunnel this path already?
3274 *
3275 * @param t Tunnel.
3276 * @param p Path.
3277 *
3278 * @return #GNUNET_YES a connection uses this path.
3279 */
3280int
3281GCT_is_path_used (const struct CadetTunnel *t, const struct CadetPeerPath *p)
3282{
3283 struct CadetTConnection *iter;
3284
3285 for (iter = t->connection_head; NULL != iter; iter = iter->next)
3286 if (path_equivalent (GCC_get_path (iter->c), p))
3287 return GNUNET_YES;
3288
3289 return GNUNET_NO;
3290}
3291
3292
3293/**
3294 * Get a cost of a path for a tunnel considering existing connections.
3295 *
3296 * @param t Tunnel.
3297 * @param path Candidate path.
3298 *
3299 * @return Cost of the path (path length + number of overlapping nodes)
3300 */
3301unsigned int
3302GCT_get_path_cost (const struct CadetTunnel *t,
3303 const struct CadetPeerPath *path)
3304{
3305 struct CadetTConnection *iter;
3306 const struct CadetPeerPath *aux;
3307 unsigned int overlap;
3308 unsigned int i;
3309 unsigned int j;
3310
3311 if (NULL == path)
3312 return 0;
3313
3314 overlap = 0;
3315 GNUNET_assert (NULL != t);
3316
3317 for (i = 0; i < path->length; i++)
3318 {
3319 for (iter = t->connection_head; NULL != iter; iter = iter->next)
3320 {
3321 aux = GCC_get_path (iter->c);
3322 if (NULL == aux)
3323 continue;
3324
3325 for (j = 0; j < aux->length; j++)
3326 {
3327 if (path->peers[i] == aux->peers[j])
3328 {
3329 overlap++;
3330 break;
3331 }
3332 }
3333 }
3334 }
3335 return path->length + overlap;
3336}
3337
3338
3339/**
3340 * Get the static string for the peer this tunnel is directed.
3341 *
3342 * @param t Tunnel.
3343 *
3344 * @return Static string the destination peer's ID.
3345 */
3346const char *
3347GCT_2s (const struct CadetTunnel *t)
3348{
3349 if (NULL == t)
3350 return "(NULL)";
3351
3352 return GCP_2s (t->peer);
3353}
3354
3355
3356/******************************************************************************/
3357/***************************** INFO/DEBUG *******************************/
3358/******************************************************************************/
3359
3360static void
3361ax_debug (const struct CadetTunnelAxolotl *ax, enum GNUNET_ErrorType level)
3362{
3363 struct GNUNET_CRYPTO_EcdhePublicKey pub;
3364 struct CadetTunnelSkippedKey *iter;
3365
3366 LOG2 (level, "TTT RK \t %s\n",
3367 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->RK));
3368
3369 LOG2 (level, "TTT HKs \t %s\n",
3370 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->HKs));
3371 LOG2 (level, "TTT HKr \t %s\n",
3372 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->HKr));
3373 LOG2 (level, "TTT NHKs\t %s\n",
3374 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->NHKs));
3375 LOG2 (level, "TTT NHKr\t %s\n",
3376 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->NHKr));
3377
3378 LOG2 (level, "TTT CKs \t %s\n",
3379 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->CKs));
3380 LOG2 (level, "TTT CKr \t %s\n",
3381 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->CKr));
3382
3383 GNUNET_CRYPTO_ecdhe_key_get_public (ax->DHRs, &pub);
3384 LOG2 (level, "TTT DHRs\t %s\n",
3385 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &pub));
3386 LOG2 (level, "TTT DHRr\t %s\n",
3387 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->DHRr));
3388
3389 LOG2 (level, "TTT Nr\t %u\tNs\t%u\n", ax->Nr, ax->Ns);
3390 LOG2 (level, "TTT PNs\t %u\tSkipped\t%u\n", ax->PNs, ax->skipped);
3391 LOG2 (level, "TTT Ratchet\t%u\n", ax->ratchet_flag);
3392
3393 for (iter = ax->skipped_head; NULL != iter; iter = iter->next)
3394 {
3395 LOG2 (level, "TTT HK\t %s\n",
3396 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &iter->HK));
3397 LOG2 (level, "TTT MK\t %s\n",
3398 GNUNET_i2s ((struct GNUNET_PeerIdentity *) &iter->MK));
3399 }
3400}
3401
3402/**
3403 * Log all possible info about the tunnel state.
3404 *
3405 * @param t Tunnel to debug.
3406 * @param level Debug level to use.
3407 */
3408void
3409GCT_debug (const struct CadetTunnel *t, enum GNUNET_ErrorType level)
3410{
3411 struct CadetTChannel *iter_ch;
3412 struct CadetTConnection *iter_c;
3413 int do_log;
3414
3415 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
3416 "cadet-tun",
3417 __FILE__, __FUNCTION__, __LINE__);
3418 if (0 == do_log)
3419 return;
3420
3421 LOG2 (level, "TTT DEBUG TUNNEL TOWARDS %s\n", GCT_2s (t));
3422 LOG2 (level, "TTT cstate %s, estate %s\n",
3423 cstate2s (t->cstate), estate2s (t->estate));
3424#if DUMP_KEYS_TO_STDERR
3425 ax_debug (t->ax, level);
3426#endif
3427 LOG2 (level, "TTT tq_head %p, tq_tail %p\n", t->tq_head, t->tq_tail);
3428 LOG2 (level, "TTT destroy %p\n", t->destroy_task);
3429 LOG2 (level, "TTT channels:\n");
3430 for (iter_ch = t->channel_head; NULL != iter_ch; iter_ch = iter_ch->next)
3431 {
3432 GCCH_debug (iter_ch->ch, level);
3433 }
3434
3435 LOG2 (level, "TTT connections:\n");
3436 for (iter_c = t->connection_head; NULL != iter_c; iter_c = iter_c->next)
3437 {
3438 GCC_debug (iter_c->c, level);
3439 }
3440
3441 LOG2 (level, "TTT DEBUG TUNNEL END\n");
3442}
3443
3444
3445/**
3446 * Iterate all tunnels.
3447 *
3448 * @param iter Iterator.
3449 * @param cls Closure for @c iter.
3450 */
3451void
3452GCT_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls)
3453{
3454 GNUNET_CONTAINER_multipeermap_iterate (tunnels, iter, cls);
3455}
3456
3457
3458/**
3459 * Count all tunnels.
3460 *
3461 * @return Number of tunnels to remote peers kept by this peer.
3462 */
3463unsigned int
3464GCT_count_all (void)
3465{
3466 return GNUNET_CONTAINER_multipeermap_size (tunnels);
3467}
3468
3469
3470/**
3471 * Iterate all connections of a tunnel.
3472 *
3473 * @param t Tunnel whose connections to iterate.
3474 * @param iter Iterator.
3475 * @param cls Closure for @c iter.
3476 */
3477void
3478GCT_iterate_connections (struct CadetTunnel *t, GCT_conn_iter iter, void *cls)
3479{
3480 struct CadetTConnection *ct;
3481
3482 for (ct = t->connection_head; NULL != ct; ct = ct->next)
3483 iter (cls, ct->c);
3484}
3485
3486
3487/**
3488 * Iterate all channels of a tunnel.
3489 *
3490 * @param t Tunnel whose channels to iterate.
3491 * @param iter Iterator.
3492 * @param cls Closure for @c iter.
3493 */
3494void
3495GCT_iterate_channels (struct CadetTunnel *t, GCT_chan_iter iter, void *cls)
3496{
3497 struct CadetTChannel *cht;
3498
3499 for (cht = t->channel_head; NULL != cht; cht = cht->next)
3500 iter (cls, cht->ch);
3501}
diff --git a/src/cadet/gnunet-service-cadet_tunnel.h b/src/cadet/gnunet-service-cadet_tunnel.h
deleted file mode 100644
index 1b56a0632..000000000
--- a/src/cadet/gnunet-service-cadet_tunnel.h
+++ /dev/null
@@ -1,616 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/gnunet-service-cadet_tunnel.h
23 * @brief cadet service; dealing with tunnels and crypto
24 * @author Bartlomiej Polot
25 *
26 * All functions in this file should use the prefix GMT (Gnunet Cadet Tunnel)
27 */
28
29#ifndef GNUNET_SERVICE_CADET_TUNNEL_H
30#define GNUNET_SERVICE_CADET_TUNNEL_H
31
32#ifdef __cplusplus
33extern "C"
34{
35#if 0 /* keep Emacsens' auto-indent happy */
36}
37#endif
38#endif
39
40#include "platform.h"
41#include "gnunet_util_lib.h"
42
43#define CONNECTIONS_PER_TUNNEL 3
44
45/**
46 * All the connectivity states a tunnel can be in.
47 */
48enum CadetTunnelCState
49{
50 /**
51 * Uninitialized status, should never appear in operation.
52 */
53 CADET_TUNNEL_NEW,
54
55 /**
56 * No path to the peer known yet.
57 */
58 CADET_TUNNEL_SEARCHING,
59
60 /**
61 * Request sent, not yet answered.
62 */
63 CADET_TUNNEL_WAITING,
64
65 /**
66 * Peer connected and ready to accept data.
67 */
68 CADET_TUNNEL_READY,
69
70 /**
71 * Tunnel being shut down, don't try to keep it alive.
72 */
73 CADET_TUNNEL_SHUTDOWN
74};
75
76
77/**
78 * All the encryption states a tunnel can be in.
79 */
80enum CadetTunnelEState
81{
82 /**
83 * Uninitialized status, should never appear in operation.
84 */
85 CADET_TUNNEL_KEY_UNINITIALIZED,
86
87 /**
88 * Ephemeral key sent, waiting for peer's key.
89 */
90 CADET_TUNNEL_KEY_AX_SENT,
91
92 /**
93 * In OTR: New ephemeral key and ping sent, waiting for pong.
94 *
95 * This means that we DO have the peer's ephemeral key, otherwise the
96 * state would be KEY_SENT. We DO NOT have a valid session key (either no
97 * previous key or previous key expired).
98 *
99 *
100 * In Axolotl: Key sent and received but no deciphered traffic yet.
101 *
102 * This means that we can send traffic (otherwise we would never complete
103 * the handshake), but we don't have complete confirmation. Since the first
104 * traffic MUST be a complete channel creation 3-way handshake, no payload
105 * will be sent before confirmation.
106 */
107 CADET_TUNNEL_KEY_AX_AUTH_SENT,
108
109 /**
110 * Handshake completed: session key available.
111 */
112 CADET_TUNNEL_KEY_OK,
113
114 /**
115 * New ephemeral key and ping sent, waiting for pong. Unlike KEY_PING,
116 * we still have a valid session key and therefore we *can* still send
117 * traffic on the tunnel.
118 */
119 CADET_TUNNEL_KEY_REKEY
120};
121
122/**
123 * Struct containing all information regarding a given peer
124 */
125struct CadetTunnel;
126
127
128#include "gnunet-service-cadet_channel.h"
129#include "gnunet-service-cadet_connection.h"
130#include "gnunet-service-cadet_peer.h"
131
132/**
133 * Handle for messages queued but not yet sent.
134 */
135struct CadetTunnelQueue;
136
137/**
138 * Callback called when a queued message is sent.
139 *
140 * @param cls Closure.
141 * @param t Tunnel this message was on.
142 * @param type Type of message sent.
143 * @param size Size of the message.
144 */
145typedef void
146(*GCT_sent) (void *cls,
147 struct CadetTunnel *t,
148 struct CadetTunnelQueue *q,
149 uint16_t type, size_t size);
150
151typedef void
152(*GCT_conn_iter) (void *cls, struct CadetConnection *c);
153
154
155typedef void
156(*GCT_chan_iter) (void *cls, struct CadetChannel *ch);
157
158
159/******************************************************************************/
160/******************************** API ***********************************/
161/******************************************************************************/
162
163/**
164 * Initialize tunnel subsystem.
165 *
166 * @param c Configuration handle.
167 * @param key ECC private key, to derive all other keys and do crypto.
168 */
169void
170GCT_init (const struct GNUNET_CONFIGURATION_Handle *c,
171 const struct GNUNET_CRYPTO_EddsaPrivateKey *key);
172
173
174/**
175 * Shut down the tunnel subsystem.
176 */
177void
178GCT_shutdown (void);
179
180
181/**
182 * Create a tunnel.
183 *
184 * @param destination Peer this tunnel is towards.
185 */
186struct CadetTunnel *
187GCT_new (struct CadetPeer *destination);
188
189
190/**
191 * Tunnel is empty: destroy it.
192 *
193 * Notifies all connections about the destruction.
194 *
195 * @param t Tunnel to destroy.
196 */
197void
198GCT_destroy_empty (struct CadetTunnel *t);
199
200
201/**
202 * Destroy tunnel if empty (no more channels).
203 *
204 * @param t Tunnel to destroy if empty.
205 */
206void
207GCT_destroy_if_empty (struct CadetTunnel *t);
208
209
210/**
211 * Destroy the tunnel.
212 *
213 * This function does not generate any warning traffic to clients or peers.
214 *
215 * Tasks:
216 * Cancel messages belonging to this tunnel queued to neighbors.
217 * Free any allocated resources linked to the tunnel.
218 *
219 * @param t The tunnel to destroy.
220 */
221void
222GCT_destroy (struct CadetTunnel *t);
223
224
225/**
226 * Change the tunnel's connection state.
227 *
228 * @param t Tunnel whose connection state to change.
229 * @param cstate New connection state.
230 */
231void
232GCT_change_cstate (struct CadetTunnel* t, enum CadetTunnelCState cstate);
233
234
235/**
236 * Change the tunnel encryption state.
237 *
238 * @param t Tunnel whose encryption state to change.
239 * @param state New encryption state.
240 */
241void
242GCT_change_estate (struct CadetTunnel* t, enum CadetTunnelEState state);
243
244
245/**
246 * Add a connection to a tunnel.
247 *
248 * @param t Tunnel.
249 * @param c Connection.
250 */
251void
252GCT_add_connection (struct CadetTunnel *t, struct CadetConnection *c);
253
254
255/**
256 * Remove a connection from a tunnel.
257 *
258 * @param t Tunnel.
259 * @param c Connection.
260 */
261void
262GCT_remove_connection (struct CadetTunnel *t, struct CadetConnection *c);
263
264
265/**
266 * Add a channel to a tunnel.
267 *
268 * @param t Tunnel.
269 * @param ch Channel.
270 */
271void
272GCT_add_channel (struct CadetTunnel *t, struct CadetChannel *ch);
273
274
275/**
276 * Remove a channel from a tunnel.
277 *
278 * @param t Tunnel.
279 * @param ch Channel.
280 */
281void
282GCT_remove_channel (struct CadetTunnel *t, struct CadetChannel *ch);
283
284
285/**
286 * Search for a channel by global ID.
287 *
288 * @param t Tunnel containing the channel.
289 * @param ctn Public channel number.
290 *
291 * @return channel handler, NULL if doesn't exist
292 */
293struct CadetChannel *
294GCT_get_channel (struct CadetTunnel *t, struct GNUNET_CADET_ChannelTunnelNumber ctn);
295
296
297/**
298 * Decrypt and process an encrypted message.
299 *
300 * Calls the appropriate handler for a message in a channel of a local tunnel.
301 *
302 * @param t Tunnel this message came on.
303 * @param msg Message header.
304 */
305void
306GCT_handle_encrypted (struct CadetTunnel *t,
307 const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
308
309
310/**
311 * Handle a Key eXchange message.
312 *
313 * @param t Tunnel on which the message came.
314 * @param msg KX message itself.
315 */
316void
317GCT_handle_kx (struct CadetTunnel *t,
318 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
319
320
321/**
322 * @brief Use the given path for the tunnel.
323 * Update the next and prev hops (and RCs).
324 * (Re)start the path refresh in case the tunnel is locally owned.
325 *
326 * @param t Tunnel to update.
327 * @param p Path to use.
328 *
329 * @return Connection created.
330 */
331struct CadetConnection *
332GCT_use_path (struct CadetTunnel *t, struct CadetPeerPath *p);
333
334
335/**
336 * Count all created connections of a tunnel. Not necessarily ready connections!
337 *
338 * @param t Tunnel on which to count.
339 *
340 * @return Number of connections created, either being established or ready.
341 */
342unsigned int
343GCT_count_any_connections (struct CadetTunnel *t);
344
345
346/**
347 * Count established (ready) connections of a tunnel.
348 *
349 * @param t Tunnel on which to count.
350 *
351 * @return Number of connections.
352 */
353unsigned int
354GCT_count_connections (struct CadetTunnel *t);
355
356
357/**
358 * Count channels of a tunnel.
359 *
360 * @param t Tunnel on which to count.
361 *
362 * @return Number of channels.
363 */
364unsigned int
365GCT_count_channels (struct CadetTunnel *t);
366
367
368/**
369 * Get the connectivity state of a tunnel.
370 *
371 * @param t Tunnel.
372 *
373 * @return Tunnel's connectivity state.
374 */
375enum CadetTunnelCState
376GCT_get_cstate (struct CadetTunnel *t);
377
378
379/**
380 * Get the encryption state of a tunnel.
381 *
382 * @param t Tunnel.
383 *
384 * @return Tunnel's encryption state.
385 */
386enum CadetTunnelEState
387GCT_get_estate (struct CadetTunnel *t);
388
389
390/**
391 * Get the maximum buffer space for a tunnel towards a local client.
392 *
393 * @param t Tunnel.
394 *
395 * @return Biggest buffer space offered by any channel in the tunnel.
396 */
397unsigned int
398GCT_get_channels_buffer (struct CadetTunnel *t);
399
400
401/**
402 * Get the total buffer space for a tunnel for P2P traffic.
403 *
404 * @param t Tunnel.
405 *
406 * @return Buffer space offered by all connections in the tunnel.
407 */
408unsigned int
409GCT_get_connections_buffer (struct CadetTunnel *t);
410
411
412/**
413 * Get the tunnel's destination.
414 *
415 * @param t Tunnel.
416 *
417 * @return ID of the destination peer.
418 */
419const struct GNUNET_PeerIdentity *
420GCT_get_destination (struct CadetTunnel *t);
421
422
423/**
424 * Get the tunnel's next free Channel ID.
425 *
426 * @param t Tunnel.
427 *
428 * @return ID of a channel free to use.
429 */
430struct GNUNET_CADET_ChannelTunnelNumber
431GCT_get_next_ctn (struct CadetTunnel *t);
432
433
434/**
435 * Send ACK on one or more channels due to buffer in connections.
436 *
437 * @param t Channel which has some free buffer space.
438 */
439void
440GCT_unchoke_channels (struct CadetTunnel *t);
441
442
443/**
444 * Send ACK on one or more connections due to buffer space to the client.
445 *
446 * Iterates all connections of the tunnel and sends ACKs appropriately.
447 *
448 * @param t Tunnel which has some free buffer space.
449 */
450void
451GCT_send_connection_acks (struct CadetTunnel *t);
452
453
454/**
455 * Cancel a previously sent message while it's in the queue.
456 *
457 * ONLY can be called before the continuation given to the send function
458 * is called. Once the continuation is called, the message is no longer in the
459 * queue.
460 *
461 * @param q Handle to the queue.
462 */
463void
464GCT_cancel (struct CadetTunnelQueue *q);
465
466
467/**
468 * Check if the tunnel has queued traffic.
469 *
470 * @param t Tunnel to check.
471 *
472 * @return #GNUNET_YES if there is queued traffic
473 * #GNUNET_NO otherwise
474 */
475int
476GCT_has_queued_traffic (struct CadetTunnel *t);
477
478/**
479 * Sends an already built message on a tunnel, encrypting it and
480 * choosing the best connection.
481 *
482 * @param message Message to send. Function modifies it.
483 * @param t Tunnel on which this message is transmitted.
484 * @param c Connection to use (autoselect if NULL).
485 * @param force Force the tunnel to take the message (buffer overfill).
486 * @param cont Continuation to call once message is really sent.
487 * @param cont_cls Closure for @c cont.
488 *
489 * @return Handle to cancel message. NULL if @c cont is NULL.
490 */
491struct CadetTunnelQueue *
492GCT_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
493 struct CadetTunnel *t, struct CadetConnection *c,
494 int force, GCT_sent cont, void *cont_cls);
495
496
497/**
498 * Send a KX message.
499 *
500 * @param t Tunnel on which to send it.
501 * @param force_reply Force the other peer to reply with a KX message.
502 */
503void
504GCT_send_kx (struct CadetTunnel *t, int force_reply);
505
506
507/**
508 * Is the tunnel directed towards the local peer?
509 *
510 * @param t Tunnel.
511 *
512 * @return #GNUNET_YES if it is loopback.
513 */
514int
515GCT_is_loopback (const struct CadetTunnel *t);
516
517
518/**
519 * Is the tunnel using this path already?
520 *
521 * @param t Tunnel.
522 * @param p Path.
523 *
524 * @return #GNUNET_YES a connection uses this path.
525 */
526int
527GCT_is_path_used (const struct CadetTunnel *t, const struct CadetPeerPath *p);
528
529
530/**
531 * Get a cost of a path for a tunnel considering existing connections.
532 *
533 * @param t Tunnel.
534 * @param path Candidate path.
535 *
536 * @return Cost of the path (path length + number of overlapping nodes)
537 */
538unsigned int
539GCT_get_path_cost (const struct CadetTunnel *t,
540 const struct CadetPeerPath *path);
541
542
543/**
544 * Get the static string for the peer this tunnel is directed.
545 *
546 * @param t Tunnel.
547 *
548 * @return Static string the destination peer's ID.
549 */
550const char *
551GCT_2s (const struct CadetTunnel *t);
552
553
554/**
555 * Log all possible info about the tunnel state.
556 *
557 * @param t Tunnel to debug.
558 * @param level Debug level to use.
559 */
560void
561GCT_debug (const struct CadetTunnel *t, enum GNUNET_ErrorType level);
562
563
564/**
565 * Iterate all tunnels.
566 *
567 * @param iter Iterator.
568 * @param cls Closure for @c iter.
569 */
570void
571GCT_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls);
572
573
574/**
575 * Count all tunnels.
576 *
577 * @return Number of tunnels to remote peers kept by this peer.
578 */
579unsigned int
580GCT_count_all (void);
581
582
583/**
584 * Iterate all connections of a tunnel.
585 *
586 * @param t Tunnel whose connections to iterate.
587 * @param iter Iterator.
588 * @param cls Closure for @c iter.
589 */
590void
591GCT_iterate_connections (struct CadetTunnel *t, GCT_conn_iter iter, void *cls);
592
593
594/**
595 * Iterate all channels of a tunnel.
596 *
597 * @param t Tunnel whose channels to iterate.
598 * @param iter Iterator.
599 * @param cls Closure for @c iter.
600 */
601void
602GCT_iterate_channels (struct CadetTunnel *t,
603 GCT_chan_iter iter,
604 void *cls);
605
606
607#if 0 /* keep Emacsens' auto-indent happy */
608{
609#endif
610#ifdef __cplusplus
611}
612#endif
613
614/* ifndef GNUNET_CADET_SERVICE_TUNNEL_H */
615#endif
616/* end of gnunet-cadet-service_tunnel.h */
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.c b/src/cadet/gnunet-service-cadet_tunnels.c
index d50860629..bcdeeb4da 100644
--- a/src/cadet/gnunet-service-cadet-new_tunnels.c
+++ b/src/cadet/gnunet-service-cadet_tunnels.c
@@ -18,7 +18,7 @@
18 Boston, MA 02110-1301, USA. 18 Boston, MA 02110-1301, USA.
19*/ 19*/
20/** 20/**
21 * @file cadet/gnunet-service-cadet-new_tunnels.c 21 * @file cadet/gnunet-service-cadet_tunnels.c
22 * @brief Information we track per tunnel. 22 * @brief Information we track per tunnel.
23 * @author Bartlomiej Polot 23 * @author Bartlomiej Polot
24 * @author Christian Grothoff 24 * @author Christian Grothoff
@@ -34,13 +34,12 @@
34#include "gnunet_util_lib.h" 34#include "gnunet_util_lib.h"
35#include "gnunet_statistics_service.h" 35#include "gnunet_statistics_service.h"
36#include "gnunet_signatures.h" 36#include "gnunet_signatures.h"
37#include "gnunet-service-cadet-new.h"
38#include "cadet_protocol.h" 37#include "cadet_protocol.h"
39#include "gnunet-service-cadet-new_channel.h" 38#include "gnunet-service-cadet_channel.h"
40#include "gnunet-service-cadet-new_connection.h" 39#include "gnunet-service-cadet_connection.h"
41#include "gnunet-service-cadet-new_tunnels.h" 40#include "gnunet-service-cadet_tunnels.h"
42#include "gnunet-service-cadet-new_peer.h" 41#include "gnunet-service-cadet_peer.h"
43#include "gnunet-service-cadet-new_paths.h" 42#include "gnunet-service-cadet_paths.h"
44 43
45 44
46#define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__) 45#define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__)
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.h b/src/cadet/gnunet-service-cadet_tunnels.h
index a81bc2341..4a3619ab6 100644
--- a/src/cadet/gnunet-service-cadet-new_tunnels.h
+++ b/src/cadet/gnunet-service-cadet_tunnels.h
@@ -20,7 +20,7 @@
20*/ 20*/
21 21
22/** 22/**
23 * @file cadet/gnunet-service-cadet-new_tunnels.h 23 * @file cadet/gnunet-service-cadet_tunnels.h
24 * @brief Information we track per tunnel. 24 * @brief Information we track per tunnel.
25 * @author Bartlomiej Polot 25 * @author Bartlomiej Polot
26 * @author Christian Grothoff 26 * @author Christian Grothoff
@@ -28,7 +28,7 @@
28#ifndef GNUNET_SERVICE_CADET_TUNNELS_H 28#ifndef GNUNET_SERVICE_CADET_TUNNELS_H
29#define GNUNET_SERVICE_CADET_TUNNELS_H 29#define GNUNET_SERVICE_CADET_TUNNELS_H
30 30
31#include "gnunet-service-cadet-new.h" 31#include "gnunet-service-cadet.h"
32#include "cadet_protocol.h" 32#include "cadet_protocol.h"
33 33
34 34
diff --git a/src/cadet/test_cadet.c b/src/cadet/test_cadet.c
index e57c01be2..4fe43b3bf 100644
--- a/src/cadet/test_cadet.c
+++ b/src/cadet/test_cadet.c
@@ -21,7 +21,7 @@
21 * @file cadet/test_cadet.c 21 * @file cadet/test_cadet.c
22 * @author Bart Polot 22 * @author Bart Polot
23 * @author Christian Grothoff 23 * @author Christian Grothoff
24 * @brief Test for the cadet service: retransmission of traffic. 24 * @brief Test for the cadet service using mq API.
25 */ 25 */
26#include <stdio.h> 26#include <stdio.h>
27#include "platform.h" 27#include "platform.h"
@@ -32,9 +32,20 @@
32 32
33 33
34/** 34/**
35 * How many messages to send 35 * Ugly workaround to unify data handlers on incoming and outgoing channels.
36 */ 36 */
37#define TOTAL_PACKETS 500 /* Cannot exceed 64k! */ 37struct CadetTestChannelWrapper
38{
39 /**
40 * Channel pointer.
41 */
42 struct GNUNET_CADET_Channel *ch;
43};
44
45/**
46 * How many messages to send by default.
47 */
48#define TOTAL_PACKETS 500 /* Cannot exceed 64k! */
38 49
39/** 50/**
40 * How long until we give up on connecting the peers? 51 * How long until we give up on connecting the peers?
@@ -42,7 +53,7 @@
42#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) 53#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
43 54
44/** 55/**
45 * Time to wait for stuff that should be rather fast 56 * Time to wait by default for stuff that should be rather fast.
46 */ 57 */
47#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20) 58#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
48 59
@@ -73,6 +84,16 @@ static char *test_name;
73static int test_backwards = GNUNET_NO; 84static int test_backwards = GNUNET_NO;
74 85
75/** 86/**
87 * How many packets to send.
88 */
89static unsigned int total_packets;
90
91/**
92 * Time to wait for fast operations.
93 */
94static struct GNUNET_TIME_Relative short_time;
95
96/**
76 * How many events have happened 97 * How many events have happened
77 */ 98 */
78static int ok; 99static int ok;
@@ -83,9 +104,9 @@ static int ok;
83static int ok_goal; 104static int ok_goal;
84 105
85/** 106/**
86 * Size of each test packet 107 * Size of each test packet's payload
87 */ 108 */
88static size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t); 109static size_t size_payload = sizeof (uint32_t);
89 110
90/** 111/**
91 * Operation to get peer ids. 112 * Operation to get peer ids.
@@ -158,9 +179,9 @@ static struct GNUNET_SCHEDULER_Task *disconnect_task;
158static struct GNUNET_SCHEDULER_Task *test_task; 179static struct GNUNET_SCHEDULER_Task *test_task;
159 180
160/** 181/**
161 * Task runnining #data_task(). 182 * Task runnining #send_next_msg().
162 */ 183 */
163static struct GNUNET_SCHEDULER_Task *data_job; 184static struct GNUNET_SCHEDULER_Task *send_next_msg_task;
164 185
165/** 186/**
166 * Cadet handle for the root peer 187 * Cadet handle for the root peer
@@ -175,7 +196,7 @@ static struct GNUNET_CADET_Handle *h2;
175/** 196/**
176 * Channel handle for the root peer 197 * Channel handle for the root peer
177 */ 198 */
178static struct GNUNET_CADET_Channel *ch; 199static struct GNUNET_CADET_Channel *outgoing_ch;
179 200
180/** 201/**
181 * Channel handle for the dest peer 202 * Channel handle for the dest peer
@@ -183,17 +204,6 @@ static struct GNUNET_CADET_Channel *ch;
183static struct GNUNET_CADET_Channel *incoming_ch; 204static struct GNUNET_CADET_Channel *incoming_ch;
184 205
185/** 206/**
186 * Transmit handle for root data calls
187 */
188static struct GNUNET_CADET_TransmitHandle *th;
189
190/**
191 * Transmit handle for root data calls
192 */
193static struct GNUNET_CADET_TransmitHandle *incoming_th;
194
195
196/**
197 * Time we started the data transmission (after channel has been established 207 * Time we started the data transmission (after channel has been established
198 * and initilized). 208 * and initilized).
199 */ 209 */
@@ -225,20 +235,26 @@ static unsigned int ka_received;
225static unsigned int msg_dropped; 235static unsigned int msg_dropped;
226 236
227 237
238/******************************************************************************/
239
240
241/******************************************************************************/
242
243
228/** 244/**
229 * Get the client number considered as the "target" or "receiver", depending on 245 * Get the channel considered as the "target" or "receiver", depending on
230 * the test type and size. 246 * the test type and size.
231 * 247 *
232 * @return Peer # of the target client, either 0 (for backward tests) or 248 * @return Channel handle of the target client, either 0 (for backward tests)
233 * the last peer in the line (for other tests). 249 * or the last peer in the line (for other tests).
234 */ 250 */
235static unsigned int 251static struct GNUNET_CADET_Channel *
236get_expected_target () 252get_target_channel ()
237{ 253{
238 if (SPEED == test && GNUNET_YES == test_backwards) 254 if (SPEED == test && GNUNET_YES == test_backwards)
239 return 0; 255 return outgoing_ch;
240 else 256 else
241 return peers_requested - 1; 257 return incoming_ch;
242} 258}
243 259
244 260
@@ -251,18 +267,15 @@ show_end_data (void)
251 static struct GNUNET_TIME_Absolute end_time; 267 static struct GNUNET_TIME_Absolute end_time;
252 static struct GNUNET_TIME_Relative total_time; 268 static struct GNUNET_TIME_Relative total_time;
253 269
254 end_time = GNUNET_TIME_absolute_get(); 270 end_time = GNUNET_TIME_absolute_get ();
255 total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time); 271 total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time);
256 FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name); 272 FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name);
257 FPRINTF (stderr, "Test time %s\n", 273 FPRINTF (stderr, "Test time %s\n",
258 GNUNET_STRINGS_relative_time_to_string (total_time, 274 GNUNET_STRINGS_relative_time_to_string (total_time, GNUNET_YES));
259 GNUNET_YES)); 275 FPRINTF (stderr, "Test bandwidth: %f kb/s\n", 4 * total_packets * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms
260 FPRINTF (stderr, "Test bandwidth: %f kb/s\n", 276 FPRINTF (stderr, "Test throughput: %f packets/s\n\n", total_packets * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms
261 4 * TOTAL_PACKETS * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms
262 FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
263 TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms
264 GAUGER ("CADET", test_name, 277 GAUGER ("CADET", test_name,
265 TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000), 278 total_packets * 1000.0 / (total_time.rel_value_us / 1000),
266 "packets/s"); 279 "packets/s");
267} 280}
268 281
@@ -281,29 +294,19 @@ disconnect_cadet_peers (void *cls)
281 294
282 disconnect_task = NULL; 295 disconnect_task = NULL;
283 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 296 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
284 "disconnecting cadet service of peers, called from line %ld\n", 297 "disconnecting cadet service of peers, called from line %ld\n",
285 line); 298 line);
286 for (i = 0; i < 2; i++) 299 for (i = 0; i < 2; i++)
287 { 300 {
288 GNUNET_TESTBED_operation_done (t_op[i]); 301 GNUNET_TESTBED_operation_done (t_op[i]);
289 } 302 }
290 if (NULL != ch) 303 if (NULL != outgoing_ch)
291 { 304 {
292 if (NULL != th) 305 GNUNET_CADET_channel_destroy (outgoing_ch);
293 { 306 outgoing_ch = NULL;
294 GNUNET_CADET_notify_transmit_ready_cancel (th);
295 th = NULL;
296 }
297 GNUNET_CADET_channel_destroy (ch);
298 ch = NULL;
299 } 307 }
300 if (NULL != incoming_ch) 308 if (NULL != incoming_ch)
301 { 309 {
302 if (NULL != incoming_th)
303 {
304 GNUNET_CADET_notify_transmit_ready_cancel (incoming_th);
305 incoming_th = NULL;
306 }
307 GNUNET_CADET_channel_destroy (incoming_ch); 310 GNUNET_CADET_channel_destroy (incoming_ch);
308 incoming_ch = NULL; 311 incoming_ch = NULL;
309 } 312 }
@@ -322,10 +325,10 @@ static void
322shutdown_task (void *cls) 325shutdown_task (void *cls)
323{ 326{
324 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n"); 327 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n");
325 if (NULL != data_job) 328 if (NULL != send_next_msg_task)
326 { 329 {
327 GNUNET_SCHEDULER_cancel (data_job); 330 GNUNET_SCHEDULER_cancel (send_next_msg_task);
328 data_job = NULL; 331 send_next_msg_task = NULL;
329 } 332 }
330 if (NULL != test_task) 333 if (NULL != test_task)
331 { 334 {
@@ -335,8 +338,8 @@ shutdown_task (void *cls)
335 if (NULL != disconnect_task) 338 if (NULL != disconnect_task)
336 { 339 {
337 GNUNET_SCHEDULER_cancel (disconnect_task); 340 GNUNET_SCHEDULER_cancel (disconnect_task);
338 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, 341 disconnect_task =
339 (void *) __LINE__); 342 GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) __LINE__);
340 } 343 }
341} 344}
342 345
@@ -351,17 +354,11 @@ shutdown_task (void *cls)
351 * operation has executed successfully. 354 * operation has executed successfully.
352 */ 355 */
353static void 356static void
354stats_cont (void *cls, 357stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
355 struct GNUNET_TESTBED_Operation *op,
356 const char *emsg)
357{ 358{
358 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 359 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " KA sent: %u, KA received: %u\n",
359 " KA sent: %u, KA received: %u\n", 360 ka_sent, ka_received);
360 ka_sent, 361 if ((KEEPALIVE == test) && ((ka_sent < 2) || (ka_sent > ka_received + 1)))
361 ka_received);
362 if ( (KEEPALIVE == test) &&
363 ( (ka_sent < 2) ||
364 (ka_sent > ka_received + 1)) )
365 { 362 {
366 GNUNET_break (0); 363 GNUNET_break (0);
367 ok--; 364 ok--;
@@ -370,8 +367,7 @@ stats_cont (void *cls,
370 367
371 if (NULL != disconnect_task) 368 if (NULL != disconnect_task)
372 GNUNET_SCHEDULER_cancel (disconnect_task); 369 GNUNET_SCHEDULER_cancel (disconnect_task);
373 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, 370 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, cls);
374 cls);
375} 371}
376 372
377 373
@@ -387,11 +383,8 @@ stats_cont (void *cls,
387 * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration 383 * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
388 */ 384 */
389static int 385static int
390stats_iterator (void *cls, 386stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer,
391 const struct GNUNET_TESTBED_Peer *peer, 387 const char *subsystem, const char *name, uint64_t value,
392 const char *subsystem,
393 const char *name,
394 uint64_t value,
395 int is_persistent) 388 int is_persistent)
396{ 389{
397 static const char *s_sent = "# keepalives sent"; 390 static const char *s_sent = "# keepalives sent";
@@ -401,19 +394,15 @@ stats_iterator (void *cls,
401 uint32_t i; 394 uint32_t i;
402 395
403 i = GNUNET_TESTBED_get_index (peer); 396 i = GNUNET_TESTBED_get_index (peer);
404 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 397 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "STATS PEER %u - %s [%s]: %llu\n", i,
405 "STATS PEER %u - %s [%s]: %llu\n", 398 subsystem, name, (unsigned long long) value);
406 i,
407 subsystem,
408 name,
409 (unsigned long long) value);
410 if (0 == strncmp (s_sent, name, strlen (s_sent)) && 0 == i) 399 if (0 == strncmp (s_sent, name, strlen (s_sent)) && 0 == i)
411 ka_sent = value; 400 ka_sent = value;
412 if (0 == strncmp(s_recv, name, strlen (s_recv)) && peers_requested - 1 == i) 401 if (0 == strncmp (s_recv, name, strlen (s_recv)) && peers_requested - 1 == i)
413 ka_received = value; 402 ka_received = value;
414 if (0 == strncmp(rdrops, name, strlen (rdrops))) 403 if (0 == strncmp (rdrops, name, strlen (rdrops)))
415 msg_dropped += value; 404 msg_dropped += value;
416 if (0 == strncmp(cdrops, name, strlen (cdrops))) 405 if (0 == strncmp (cdrops, name, strlen (cdrops)))
417 msg_dropped += value; 406 msg_dropped += value;
418 407
419 return GNUNET_OK; 408 return GNUNET_OK;
@@ -423,7 +412,7 @@ stats_iterator (void *cls,
423/** 412/**
424 * Task to gather all statistics. 413 * Task to gather all statistics.
425 * 414 *
426 * @param cls Closure (NULL). 415 * @param cls Closure (line from which the task was scheduled).
427 */ 416 */
428static void 417static void
429gather_stats_and_exit (void *cls) 418gather_stats_and_exit (void *cls)
@@ -432,21 +421,20 @@ gather_stats_and_exit (void *cls)
432 421
433 disconnect_task = NULL; 422 disconnect_task = NULL;
434 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 423 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
435 "gathering statistics from line %d\n", 424 "gathering statistics from line %ld\n",
436 (int) l); 425 l);
437 if (NULL != ch) 426 if (NULL != outgoing_ch)
438 { 427 {
439 if (NULL != th) 428 GNUNET_CADET_channel_destroy (outgoing_ch);
440 { 429 outgoing_ch = NULL;
441 GNUNET_CADET_notify_transmit_ready_cancel (th);
442 th = NULL;
443 }
444 GNUNET_CADET_channel_destroy (ch);
445 ch = NULL;
446 } 430 }
447 stats_op = GNUNET_TESTBED_get_statistics (peers_running, testbed_peers, 431 stats_op = GNUNET_TESTBED_get_statistics (peers_running,
448 "cadet", NULL, 432 testbed_peers,
449 &stats_iterator, stats_cont, cls); 433 "cadet",
434 NULL,
435 &stats_iterator,
436 stats_cont,
437 cls);
450} 438}
451 439
452 440
@@ -462,163 +450,151 @@ abort_test (long line)
462 if (NULL != disconnect_task) 450 if (NULL != disconnect_task)
463 { 451 {
464 GNUNET_SCHEDULER_cancel (disconnect_task); 452 GNUNET_SCHEDULER_cancel (disconnect_task);
465 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 453 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting test from %ld\n", line);
466 "Aborting test from %ld\n", line); 454 disconnect_task =
467 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, 455 GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) line);
468 (void *) line);
469 } 456 }
470} 457}
471 458
472/**
473 * Transmit ready callback.
474 *
475 * @param cls Closure (message type).
476 * @param size Size of the tranmist buffer.
477 * @param buf Pointer to the beginning of the buffer.
478 *
479 * @return Number of bytes written to buf.
480 */
481static size_t
482tmt_rdy (void *cls, size_t size, void *buf);
483
484 459
485/** 460/**
486 * Task to request a new data transmission. 461 * Send a message on the channel with the appropriate size and payload.
462 *
463 * Update the appropriate *_sent counter.
487 * 464 *
488 * @param cls Closure (peer #). 465 * @param channel Channel to send the message on.
489 */ 466 */
490static void 467static void
491data_task (void *cls) 468send_test_message (struct GNUNET_CADET_Channel *channel)
492{ 469{
493 struct GNUNET_CADET_Channel *channel; 470 struct GNUNET_MQ_Envelope *env;
494 static struct GNUNET_CADET_TransmitHandle **pth; 471 struct GNUNET_MessageHeader *msg;
495 long src; 472 uint32_t *data;
473 int payload;
474 int size;
496 475
497 data_job = NULL; 476 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
498 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data task\n"); 477 "Sending test message on channel %p\n",
499 if (GNUNET_YES == test_backwards) 478 channel);
500 { 479 size = size_payload;
501 channel = incoming_ch; 480 if (GNUNET_NO == initialized)
502 pth = &incoming_th;
503 src = peers_requested - 1;
504 }
505 else
506 { 481 {
507 channel = ch; 482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending INITIALIZER\n");
508 pth = &th; 483 size += 1000;
509 src = 0; 484 payload = data_sent;
485 if (SPEED_ACK == test) // FIXME unify SPEED_ACK with an initializer
486 data_sent++;
510 } 487 }
511 488 else if (SPEED == test || SPEED_ACK == test)
512 GNUNET_assert (NULL != channel);
513 GNUNET_assert (NULL == *pth);
514
515 *pth = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
516 GNUNET_TIME_UNIT_FOREVER_REL,
517 size_payload + data_sent,
518 &tmt_rdy, (void *) src);
519 if (NULL == *pth)
520 { 489 {
521 unsigned long i = (unsigned long) cls; 490 if (get_target_channel() == channel)
522
523 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Retransmission\n");
524 if (0 == i)
525 { 491 {
526 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " in 1 ms\n"); 492 payload = ack_sent;
527 data_job = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, 493 size += ack_sent;
528 &data_task, (void *) 1L); 494 ack_sent++;
495 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
496 "Sending ACK %u [%d bytes]\n",
497 payload, size);
529 } 498 }
530 else 499 else
531 { 500 {
532 i++; 501 payload = data_sent;
533 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 502 size += data_sent;
534 "in %llu ms\n", 503 data_sent++;
535 (unsigned long long) i); 504 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
536 data_job = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 505 "Sending DATA %u [%d bytes]\n",
537 i), 506 data_sent, size);
538 &data_task, (void *) i);
539 } 507 }
540 } 508 }
541} 509 else if (FORWARD == test)
510 {
511 payload = ack_sent;
512 }
513 else if (P2P_SIGNAL == test)
514 {
515 payload = data_sent;
516 }
517 else
518 {
519 GNUNET_assert (0);
520 }
521 env = GNUNET_MQ_msg_extra (msg, size, GNUNET_MESSAGE_TYPE_DUMMY);
542 522
523 data = (uint32_t *) &msg[1];
524 *data = htonl (payload);
525 GNUNET_MQ_send (GNUNET_CADET_get_mq (channel), env);
526}
543 527
544/** 528/**
545 * Transmit ready callback 529 * Task to request a new data transmission in a SPEED test, without waiting
530 * for previous messages to be sent/arrrive.
546 * 531 *
547 * @param cls Closure (peer # which is sending the data). 532 * @param cls Closure (unused).
548 * @param size Size of the buffer we have.
549 * @param buf Buffer to copy data to.
550 */ 533 */
551static size_t 534static void
552tmt_rdy (void *cls, size_t size, void *buf) 535send_next_msg (void *cls)
553{ 536{
554 struct GNUNET_MessageHeader *msg = buf; 537 struct GNUNET_CADET_Channel *channel;
555 size_t msg_size;
556 uint32_t *data;
557 long id = (long) cls;
558 unsigned int counter;
559 538
560 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 539 send_next_msg_task = NULL;
561 "tmt_rdy on %ld, filling buffer\n", 540 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending next message: %d\n", data_sent);
562 id); 541
563 if (0 == id) 542 channel = GNUNET_YES == test_backwards ? incoming_ch : outgoing_ch;
564 th = NULL; 543 GNUNET_assert (NULL != channel);
565 else if ((peers_requested - 1) == id) 544 GNUNET_assert (SPEED == test);
566 incoming_th = NULL; 545 send_test_message (channel);
567 else 546 if (data_sent < total_packets)
568 GNUNET_assert (0);
569 counter = get_expected_target () == id ? ack_sent : data_sent;
570 msg_size = size_payload + counter;
571 GNUNET_assert (msg_size > sizeof (struct GNUNET_MessageHeader));
572 if ( (size < msg_size) ||
573 (NULL == buf) )
574 {
575 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
576 "size %u, buf %p, data_sent %u, ack_received %u\n",
577 (unsigned int) size,
578 buf,
579 data_sent,
580 ack_received);
581 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ok %u, ok goal %u\n", ok, ok_goal);
582 GNUNET_break (ok >= ok_goal - 2);
583
584 return 0;
585 }
586 msg->size = htons (msg_size);
587 msg->type = htons (GNUNET_MESSAGE_TYPE_DUMMY);
588 data = (uint32_t *) &msg[1];
589 *data = htonl (counter);
590 if (GNUNET_NO == initialized)
591 { 547 {
548 /* SPEED test: Send all messages as soon as possible */
592 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 549 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
593 "sending initializer\n"); 550 "Scheduling message %d\n",
594 msg_size = size_payload + 1000; 551 data_sent + 1);
595 msg->size = htons (msg_size); 552 send_next_msg_task =
596 if (SPEED_ACK == test) 553 GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_SECONDS,
597 data_sent++; 554 &send_next_msg,
555 NULL);
598 } 556 }
599 else if ( (SPEED == test) || 557}
600 (SPEED_ACK == test) ) 558
559
560/**
561 * Every few messages cancel the timeout task and re-schedule it again, to
562 * avoid timing out when traffic keeps coming.
563 *
564 * @param line Code line number to log if a timeout occurs.
565 */
566static void
567reschedule_timeout_task (long line)
568{
569 if ((ok % 10) == 0)
601 { 570 {
602 if (get_expected_target() == id) 571 if (NULL != disconnect_task)
603 ack_sent++;
604 else
605 data_sent++;
606 counter++;
607 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
608 " Sent message %u size %u\n",
609 counter,
610 (unsigned int) msg_size);
611 if ( (data_sent < TOTAL_PACKETS) &&
612 (SPEED == test) )
613 { 572 {
614 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 573 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
615 " Scheduling message %d\n", 574 " reschedule timeout every 10 messages\n");
616 counter + 1); 575 GNUNET_SCHEDULER_cancel (disconnect_task);
617 data_job = GNUNET_SCHEDULER_add_now (&data_task, NULL); 576 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
577 &gather_stats_and_exit,
578 (void *) line);
618 } 579 }
619 } 580 }
581}
620 582
621 return msg_size; 583
584/**
585 * Check if payload is sane (size contains payload).
586 *
587 * @param cls should match #ch
588 * @param message The actual message.
589 * @return #GNUNET_OK to keep the channel open,
590 * #GNUNET_SYSERR to close it (signal serious error).
591 */
592static int
593check_data (void *cls, const struct GNUNET_MessageHeader *message)
594{
595 if (sizeof (struct GNUNET_MessageHeader) >= ntohs (message->size))
596 return GNUNET_SYSERR;
597 return GNUNET_OK; /* all is well-formed */
622} 598}
623 599
624 600
@@ -626,75 +602,50 @@ tmt_rdy (void *cls, size_t size, void *buf)
626 * Function is called whenever a message is received. 602 * Function is called whenever a message is received.
627 * 603 *
628 * @param cls closure (set from GNUNET_CADET_connect(), peer number) 604 * @param cls closure (set from GNUNET_CADET_connect(), peer number)
629 * @param channel connection to the other end
630 * @param channel_ctx place to store local state associated with the channel
631 * @param message the actual message 605 * @param message the actual message
632 * @return #GNUNET_OK to keep the connection open,
633 * #GNUNET_SYSERR to close it (signal serious error)
634 */ 606 */
635static int 607static void
636data_callback (void *cls, 608handle_data (void *cls, const struct GNUNET_MessageHeader *message)
637 struct GNUNET_CADET_Channel *channel,
638 void **channel_ctx,
639 const struct GNUNET_MessageHeader *message)
640{ 609{
641 struct GNUNET_CADET_TransmitHandle **pth; 610 struct CadetTestChannelWrapper *ch = cls;
642 long client = (long) cls; 611 struct GNUNET_CADET_Channel *channel = ch->ch;
643 long expected_target_client;
644 uint32_t *data; 612 uint32_t *data;
645 uint32_t payload; 613 uint32_t payload;
646 unsigned int counter; 614 int *counter;
647 615
648 ok++; 616 ok++;
649 counter = get_expected_target () == client ? data_received : ack_received;
650
651 GNUNET_CADET_receive_done (channel); 617 GNUNET_CADET_receive_done (channel);
618 counter = get_target_channel () == channel ? &data_received : &ack_received;
652 619
653 if ((ok % 10) == 0) 620 reschedule_timeout_task ((long) __LINE__);
621
622 if (channel == outgoing_ch)
654 { 623 {
655 if (NULL != disconnect_task) 624 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message.\n");
656 {
657 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
658 " reschedule timeout\n");
659 GNUNET_SCHEDULER_cancel (disconnect_task);
660 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
661 &gather_stats_and_exit,
662 (void *) __LINE__);
663 }
664 } 625 }
665 626 else if (channel == incoming_ch)
666 switch (client)
667 { 627 {
668 case 0L: 628 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Leaf client got a message.\n");
669 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n"); 629 }
670 GNUNET_assert (channel == ch); 630 else
671 pth = &th; 631 {
672 break; 632 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unknown channel %p.\n", channel);
673 case 1L:
674 case 4L:
675 GNUNET_assert (client == peers_requested - 1);
676 GNUNET_assert (channel == incoming_ch);
677 pth = &incoming_th;
678 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Leaf client %ld got a message.\n",
679 client);
680 break;
681 default:
682 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Client %ld not valid.\n", client);
683 GNUNET_assert (0); 633 GNUNET_assert (0);
684 } 634 }
635
685 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal); 636 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal);
686 data = (uint32_t *) &message[1]; 637 data = (uint32_t *) &message[1];
687 payload = ntohl (*data); 638 payload = ntohl (*data);
688 if (payload == counter) 639 if (payload == *counter)
689 { 640 {
690 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload as expected: %u\n", payload); 641 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload as expected: %u\n", payload);
691 } 642 }
692 else 643 else
693 { 644 {
694 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " payload %u, expected: %u\n", 645 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
695 payload, counter); 646 " payload %u, expected: %u\n",
647 payload, *counter);
696 } 648 }
697 expected_target_client = get_expected_target ();
698 649
699 if (GNUNET_NO == initialized) 650 if (GNUNET_NO == initialized)
700 { 651 {
@@ -702,189 +653,152 @@ data_callback (void *cls,
702 start_time = GNUNET_TIME_absolute_get (); 653 start_time = GNUNET_TIME_absolute_get ();
703 if (SPEED == test) 654 if (SPEED == test)
704 { 655 {
705 GNUNET_assert (peers_requested - 1 == client); 656 GNUNET_assert (incoming_ch == channel);
706 data_job = GNUNET_SCHEDULER_add_now (&data_task, NULL); 657 send_next_msg_task = GNUNET_SCHEDULER_add_now (&send_next_msg, NULL);
707 return GNUNET_OK; 658 return;
708 } 659 }
709 } 660 }
710 661
711 counter++; 662 (*counter)++;
712 if (client == expected_target_client) /* Normally 4 */ 663 if (get_target_channel () == channel) /* Got "data" */
713 { 664 {
714 data_received++;
715 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received); 665 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received);
716 if (SPEED != test || (ok_goal - 2) == ok) 666 if (SPEED != test || (ok_goal - 2) == ok)
717 { 667 {
718 /* Send ACK */ 668 /* Send ACK */
719 GNUNET_assert (NULL == *pth); 669 send_test_message (channel);
720 *pth = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO, 670 return;
721 GNUNET_TIME_UNIT_FOREVER_REL,
722 size_payload + ack_sent,
723 &tmt_rdy, (void *) client);
724 return GNUNET_OK;
725 } 671 }
726 else 672 else
727 { 673 {
728 if (data_received < TOTAL_PACKETS) 674 if (data_received < total_packets)
729 return GNUNET_OK; 675 return;
730 } 676 }
731 } 677 }
732 else /* Normally 0 */ 678 else /* Got "ack" */
733 { 679 {
734 if (SPEED_ACK == test || SPEED == test) 680 if (SPEED_ACK == test || SPEED == test)
735 { 681 {
736 ack_received++;
737 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", ack_received); 682 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", ack_received);
738 /* send more data */ 683 /* Send more data */
739 GNUNET_assert (NULL == *pth); 684 send_test_message (channel);
740 *pth = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO, 685 if (ack_received < total_packets && SPEED != test)
741 GNUNET_TIME_UNIT_FOREVER_REL, 686 return;
742 size_payload + data_sent,
743 &tmt_rdy, (void *) client);
744 if (ack_received < TOTAL_PACKETS && SPEED != test)
745 return GNUNET_OK;
746 if (ok == 2 && SPEED == test) 687 if (ok == 2 && SPEED == test)
747 return GNUNET_OK; 688 return;
748 show_end_data(); 689 show_end_data ();
749 } 690 }
750 if (test == P2P_SIGNAL) 691 if (test == P2P_SIGNAL)
751 { 692 {
752 if (NULL != incoming_th)
753 {
754 GNUNET_CADET_notify_transmit_ready_cancel (incoming_th);
755 incoming_th = NULL;
756 }
757 GNUNET_CADET_channel_destroy (incoming_ch); 693 GNUNET_CADET_channel_destroy (incoming_ch);
758 incoming_ch = NULL; 694 incoming_ch = NULL;
759 } 695 }
760 else 696 else
761 { 697 {
762 if (NULL != th) 698 GNUNET_CADET_channel_destroy (outgoing_ch);
763 { 699 outgoing_ch = NULL;
764 GNUNET_CADET_notify_transmit_ready_cancel (th);
765 th = NULL;
766 }
767 GNUNET_CADET_channel_destroy (ch);
768 ch = NULL;
769 } 700 }
770 } 701 }
771
772 return GNUNET_OK;
773} 702}
774 703
775 704
776/** 705/**
777 * Data handlers for every message type of CADET's payload. 706 * Method called whenever a peer connects to a port in MQ-based CADET.
778 * {callback_function, message_type, size_expected}
779 */
780static struct GNUNET_CADET_MessageHandler handlers[] = {
781 {&data_callback,
782 GNUNET_MESSAGE_TYPE_DUMMY,
783 sizeof (struct GNUNET_MessageHeader)},
784 {NULL, 0, 0}
785};
786
787
788/**
789 * Method called whenever another peer has added us to a channel
790 * the other peer initiated.
791 * 707 *
792 * @param cls Closure. 708 * @param cls Closure from #GNUNET_CADET_open_porT (peer # as long).
793 * @param channel New handle to the channel. 709 * @param channel New handle to the channel.
794 * @param initiator Peer that started the channel. 710 * @param source Peer that started this channel.
795 * @param port Port this channel is connected to. 711 * @return Closure for the incoming @a channel. It's given to:
796 * @param options channel option flags 712 * - The #GNUNET_CADET_DisconnectEventHandler (given to
797 * @return Initial channel context for the channel 713 * #GNUNET_CADET_open_porT) when the channel dies.
798 * (can be NULL -- that's not an error). 714 * - Each the #GNUNET_MQ_MessageCallback handlers for each message
715 * received on the @a channel.
799 */ 716 */
800static void * 717static void *
801incoming_channel (void *cls, 718connect_handler (void *cls, struct GNUNET_CADET_Channel *channel,
802 struct GNUNET_CADET_Channel *channel, 719 const struct GNUNET_PeerIdentity *source)
803 const struct GNUNET_PeerIdentity *initiator,
804 const struct GNUNET_HashCode *port,
805 enum GNUNET_CADET_ChannelOption options)
806{ 720{
721 struct CadetTestChannelWrapper *ch;
722 long peer = (long) cls;
723
807 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 724 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
808 "Incoming channel from %s to peer %d:%s\n", 725 "Incoming channel from %s to %ld: %p\n",
809 GNUNET_i2s (initiator), 726 GNUNET_i2s (source), peer, channel);
810 (int) (long) cls, GNUNET_h2s (port));
811 ok++; 727 ok++;
812 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); 728 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
813 if ((long) cls == peers_requested - 1) 729 if (peer == peers_requested - 1)
814 { 730 {
815 if (NULL != incoming_ch) 731 if (NULL != incoming_ch)
816 { 732 {
817 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 733 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
818 "Duplicate incoming channel for client %lu\n", 734 "Duplicate incoming channel for client %lu\n", (long) cls);
819 (long) cls); 735 GNUNET_assert (0);
820 GNUNET_break(0);
821 } 736 }
822 incoming_ch = channel; 737 incoming_ch = channel;
823 } 738 }
824 else 739 else
825 { 740 {
826 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 741 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
827 "Incoming channel for unexpected peer #%lu\n", 742 "Incoming channel for unexpected peer #%lu\n", (long) cls);
828 (long) cls); 743 GNUNET_assert (0);
829 GNUNET_break (0);
830 } 744 }
831 if (NULL != disconnect_task) 745 if (NULL != disconnect_task)
832 { 746 {
833 GNUNET_SCHEDULER_cancel (disconnect_task); 747 GNUNET_SCHEDULER_cancel (disconnect_task);
834 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, 748 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
835 &gather_stats_and_exit, 749 &gather_stats_and_exit,
836 (void *) __LINE__); 750 (void *) __LINE__);
837 } 751 }
838 752
839 return NULL; 753 /* TODO: cannot return channel as-is, in order to unify the data handlers */
754 ch = GNUNET_new (struct CadetTestChannelWrapper);
755 ch->ch = channel;
756
757 return ch;
840} 758}
841 759
842 760
843/** 761/**
844 * Function called whenever an inbound channel is destroyed. Should clean up 762 * Function called whenever an MQ-channel is destroyed, even if the destruction
845 * any associated state. 763 * was requested by #GNUNET_CADET_channel_destroy.
764 * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
846 * 765 *
847 * @param cls closure (set from GNUNET_CADET_connect, peer number) 766 * It should clean up any associated state, including cancelling any pending
848 * @param channel connection to the other end (henceforth invalid) 767 * transmission on this channel.
849 * @param channel_ctx place where local state associated 768 *
850 * with the channel is stored 769 * @param cls Channel closure (channel wrapper).
770 * @param channel Connection to the other end (henceforth invalid).
851 */ 771 */
852static void 772static void
853channel_cleaner (void *cls, 773disconnect_handler (void *cls, const struct GNUNET_CADET_Channel *channel)
854 const struct GNUNET_CADET_Channel *channel,
855 void *channel_ctx)
856{ 774{
857 long i = (long) cls; 775 struct CadetTestChannelWrapper *ch_w = cls;
858 776
859 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 777 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Channel disconnected\n");
860 "Incoming channel disconnected at peer %ld\n", 778 GNUNET_assert (ch_w->ch == channel);
861 i); 779 if (channel == incoming_ch)
862 if (peers_running - 1 == i)
863 { 780 {
864 ok++; 781 ok++;
865 GNUNET_break (channel == incoming_ch);
866 incoming_ch = NULL; 782 incoming_ch = NULL;
867 } 783 }
868 else if (0L == i) 784 else if (outgoing_ch == channel
785 )
869 { 786 {
870 if (P2P_SIGNAL == test) 787 if (P2P_SIGNAL == test)
871 { 788 {
872 ok++; 789 ok++;
873 } 790 }
874 GNUNET_break (channel == ch); 791 outgoing_ch = NULL;
875 ch = NULL;
876 } 792 }
877 else 793 else
878 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 794 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unknown channel! %p\n", channel);
879 "Unknown peer! %d\n",
880 (int) i);
881 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); 795 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
882 796
883 if (NULL != disconnect_task) 797 if (NULL != disconnect_task)
884 { 798 {
885 GNUNET_SCHEDULER_cancel (disconnect_task); 799 GNUNET_SCHEDULER_cancel (disconnect_task);
886 disconnect_task = GNUNET_SCHEDULER_add_now (&gather_stats_and_exit, 800 disconnect_task =
887 (void *) __LINE__); 801 GNUNET_SCHEDULER_add_now (&gather_stats_and_exit, (void *) __LINE__);
888 } 802 }
889} 803}
890 804
@@ -898,13 +812,20 @@ channel_cleaner (void *cls,
898 * @param cls Closure (unused). 812 * @param cls Closure (unused).
899 */ 813 */
900static void 814static void
901do_test (void *cls) 815start_test (void *cls)
902{ 816{
817 struct GNUNET_MQ_MessageHandler handlers[] = {
818 GNUNET_MQ_hd_var_size (data,
819 GNUNET_MESSAGE_TYPE_DUMMY,
820 struct GNUNET_MessageHeader,
821 NULL),
822 GNUNET_MQ_handler_end ()
823 };
824 struct CadetTestChannelWrapper *ch;
903 enum GNUNET_CADET_ChannelOption flags; 825 enum GNUNET_CADET_ChannelOption flags;
904 826
905 test_task = NULL; 827 test_task = NULL;
906 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "start_test\n");
907 "do_test\n");
908 if (NULL != disconnect_task) 829 if (NULL != disconnect_task)
909 { 830 {
910 GNUNET_SCHEDULER_cancel (disconnect_task); 831 GNUNET_SCHEDULER_cancel (disconnect_task);
@@ -918,30 +839,33 @@ do_test (void *cls)
918 flags |= GNUNET_CADET_OPTION_RELIABLE; 839 flags |= GNUNET_CADET_OPTION_RELIABLE;
919 } 840 }
920 841
921 ch = GNUNET_CADET_channel_create (h1, 842 ch = GNUNET_new (struct CadetTestChannelWrapper);
922 NULL, 843 outgoing_ch = GNUNET_CADET_channel_creatE (h1,
923 p_id[1], 844 ch,
924 &port, 845 p_id[1],
925 flags); 846 &port,
847 flags,
848 NULL,
849 &disconnect_handler,
850 handlers);
851
852 ch->ch = outgoing_ch;
926 853
927 disconnect_task 854 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
928 = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, 855 &gather_stats_and_exit,
929 &gather_stats_and_exit, 856 (void *) __LINE__);
930 (void *) __LINE__);
931 if (KEEPALIVE == test) 857 if (KEEPALIVE == test)
932 return; /* Don't send any data. */ 858 return; /* Don't send any data. */
859
933 860
934 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
935 "Sending data initializer...\n");
936 data_received = 0; 861 data_received = 0;
937 data_sent = 0; 862 data_sent = 0;
938 ack_received = 0; 863 ack_received = 0;
939 ack_sent = 0; 864 ack_sent = 0;
940 th = GNUNET_CADET_notify_transmit_ready (ch, 865 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
941 GNUNET_NO, 866 "Sending data initializer on channel %p...\n",
942 GNUNET_TIME_UNIT_FOREVER_REL, 867 outgoing_ch);
943 size_payload + 1000, 868 send_test_message (outgoing_ch);
944 &tmt_rdy, (void *) 0L);
945} 869}
946 870
947 871
@@ -955,35 +879,26 @@ do_test (void *cls)
955 * NULL if the operation is successfull 879 * NULL if the operation is successfull
956 */ 880 */
957static void 881static void
958pi_cb (void *cls, 882pi_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
959 struct GNUNET_TESTBED_Operation *op, 883 const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg)
960 const struct GNUNET_TESTBED_PeerInformation *pinfo,
961 const char *emsg)
962{ 884{
963 long i = (long) cls; 885 long i = (long) cls;
964 886
965 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 887 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ID callback for %ld\n", i);
966 "id callback for %ld\n", i);
967 888
968 if ( (NULL == pinfo) || 889 if ((NULL == pinfo) || (NULL != emsg))
969 (NULL != emsg) )
970 { 890 {
971 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 891 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
972 "pi_cb: %s\n", emsg);
973 abort_test (__LINE__); 892 abort_test (__LINE__);
974 return; 893 return;
975 } 894 }
976 p_id[i] = pinfo->result.id; 895 p_id[i] = pinfo->result.id;
977 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 896 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i]));
978 " id: %s\n", GNUNET_i2s (p_id[i]));
979 p_ids++; 897 p_ids++;
980 if (p_ids < 2) 898 if (p_ids < 2)
981 return; 899 return;
982 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 900 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n");
983 "Got all IDs, starting test\n"); 901 test_task = GNUNET_SCHEDULER_add_now (&start_test, NULL);
984 test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
985 &do_test,
986 NULL);
987} 902}
988 903
989 904
@@ -994,7 +909,7 @@ pi_cb (void *cls,
994 * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end. 909 * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end.
995 * @param num_peers Number of peers that are running. 910 * @param num_peers Number of peers that are running.
996 * @param peers Array of peers. 911 * @param peers Array of peers.
997 * @param cadetes Handle to each of the CADETs of the peers. 912 * @param cadets Handle to each of the CADETs of the peers.
998 */ 913 */
999static void 914static void
1000tmain (void *cls, 915tmain (void *cls,
@@ -1011,16 +926,18 @@ tmain (void *cls,
1011 testbed_peers = peers; 926 testbed_peers = peers;
1012 h1 = cadets[0]; 927 h1 = cadets[0];
1013 h2 = cadets[num_peers - 1]; 928 h2 = cadets[num_peers - 1];
1014 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, 929 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
1015 &disconnect_cadet_peers, 930 &disconnect_cadet_peers,
1016 (void *) __LINE__); 931 (void *) __LINE__);
1017 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); 932 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1018 t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0], 933 t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
1019 GNUNET_TESTBED_PIT_IDENTITY, 934 GNUNET_TESTBED_PIT_IDENTITY,
1020 &pi_cb, (void *) 0L); 935 &pi_cb,
936 (void *) 0L);
1021 t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1], 937 t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
1022 GNUNET_TESTBED_PIT_IDENTITY, 938 GNUNET_TESTBED_PIT_IDENTITY,
1023 &pi_cb, (void *) 1L); 939 &pi_cb,
940 (void *) 1L);
1024 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n"); 941 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n");
1025} 942}
1026 943
@@ -1031,16 +948,42 @@ tmain (void *cls,
1031int 948int
1032main (int argc, char *argv[]) 949main (int argc, char *argv[])
1033{ 950{
951 struct GNUNET_MQ_MessageHandler handlers[] = {
952 GNUNET_MQ_hd_var_size (data,
953 GNUNET_MESSAGE_TYPE_DUMMY,
954 struct GNUNET_MessageHeader,
955 NULL),
956 GNUNET_MQ_handler_end ()
957 };
958
1034 initialized = GNUNET_NO; 959 initialized = GNUNET_NO;
1035 static const struct GNUNET_HashCode *ports[2]; 960 static const struct GNUNET_HashCode *ports[2];
1036 const char *config_file; 961 const char *config_file;
1037 char port_id[] = "test port"; 962 char port_id[] = "test port";
1038 GNUNET_CRYPTO_hash (port_id, sizeof (port_id), &port); 963
964 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
965 {'t', "time", "short_time",
966 gettext_noop ("set short timeout"),
967 GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &short_time},
968 {'m', "messages", "NUM_MESSAGES",
969 gettext_noop ("set number of messages to send"),
970 GNUNET_YES, &GNUNET_GETOPT_set_uint, &total_packets},
971
972 GNUNET_GETOPT_OPTION_END
973 };
1039 974
1040 GNUNET_log_setup ("test", "DEBUG", NULL); 975 GNUNET_log_setup ("test", "DEBUG", NULL);
1041 config_file = "test_cadet.conf";
1042 976
1043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n"); 977 total_packets = TOTAL_PACKETS;
978 short_time = SHORT_TIME;
979 if (-1 == GNUNET_GETOPT_run (argv[0], options, argc, argv))
980 {
981 FPRINTF (stderr, "test failed: problem with CLI parameters\n");
982 exit (1);
983 }
984
985 config_file = "test_cadet.conf";
986 GNUNET_CRYPTO_hash (port_id, sizeof (port_id), &port);
1044 987
1045 /* Find out requested size */ 988 /* Find out requested size */
1046 if (strstr (argv[0], "_2_") != NULL) 989 if (strstr (argv[0], "_2_") != NULL)
@@ -1078,11 +1021,11 @@ main (int argc, char *argv[])
1078 { 1021 {
1079 /* Test is supposed to generate the following callbacks: 1022 /* Test is supposed to generate the following callbacks:
1080 * 1 incoming channel (@dest) 1023 * 1 incoming channel (@dest)
1081 * TOTAL_PACKETS received data packet (@dest) 1024 * total_packets received data packet (@dest)
1082 * TOTAL_PACKETS received data packet (@orig) 1025 * total_packets received data packet (@orig)
1083 * 1 received channel destroy (@dest) 1026 * 1 received channel destroy (@dest)
1084 */ 1027 */
1085 ok_goal = TOTAL_PACKETS * 2 + 2; 1028 ok_goal = total_packets * 2 + 2;
1086 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n"); 1029 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n");
1087 test = SPEED_ACK; 1030 test = SPEED_ACK;
1088 test_name = "speed ack"; 1031 test_name = "speed ack";
@@ -1092,11 +1035,11 @@ main (int argc, char *argv[])
1092 /* Test is supposed to generate the following callbacks: 1035 /* Test is supposed to generate the following callbacks:
1093 * 1 incoming channel (@dest) 1036 * 1 incoming channel (@dest)
1094 * 1 initial packet (@dest) 1037 * 1 initial packet (@dest)
1095 * TOTAL_PACKETS received data packet (@dest) 1038 * total_packets received data packet (@dest)
1096 * 1 received data packet (@orig) 1039 * 1 received data packet (@orig)
1097 * 1 received channel destroy (@dest) 1040 * 1 received channel destroy (@dest)
1098 */ 1041 */
1099 ok_goal = TOTAL_PACKETS + 4; 1042 ok_goal = total_packets + 4;
1100 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n"); 1043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n");
1101 if (strstr (argv[0], "_reliable") != NULL) 1044 if (strstr (argv[0], "_reliable") != NULL)
1102 { 1045 {
@@ -1137,22 +1080,22 @@ main (int argc, char *argv[])
1137 p_ids = 0; 1080 p_ids = 0;
1138 ports[0] = &port; 1081 ports[0] = &port;
1139 ports[1] = NULL; 1082 ports[1] = NULL;
1140 GNUNET_CADET_TEST_run ("test_cadet_small", 1083 GNUNET_CADET_TEST_ruN ("test_cadet_small",
1141 config_file, 1084 config_file,
1142 peers_requested, 1085 peers_requested,
1143 &tmain, 1086 &tmain,
1144 NULL, /* tmain cls */ 1087 NULL, /* tmain cls */
1145 &incoming_channel, 1088 &connect_handler,
1146 &channel_cleaner, 1089 NULL,
1147 handlers, 1090 &disconnect_handler,
1148 ports); 1091 handlers,
1092 ports);
1149 if (NULL != strstr (argv[0], "_reliable")) 1093 if (NULL != strstr (argv[0], "_reliable"))
1150 msg_dropped = 0; /* dropped should be retransmitted */ 1094 msg_dropped = 0; /* dropped should be retransmitted */
1151 1095
1152 if (ok_goal > ok - msg_dropped) 1096 if (ok_goal > ok - msg_dropped)
1153 { 1097 {
1154 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1098 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "FAILED! (%d/%d)\n", ok, ok_goal);
1155 "FAILED! (%d/%d)\n", ok, ok_goal);
1156 return 1; 1099 return 1;
1157 } 1100 }
1158 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n"); 1101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n");
diff --git a/src/cadet/test_cadet_local.c b/src/cadet/test_cadet_local.c
deleted file mode 100644
index 2b915ab81..000000000
--- a/src/cadet/test_cadet_local.c
+++ /dev/null
@@ -1,351 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/test_cadet_local.c
23 * @brief test cadet local: test of cadet channels with just one peer
24 * @author Bartlomiej Polot
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_dht_service.h"
30#include "gnunet_testing_lib.h"
31#include "gnunet_cadet_service.h"
32
33struct GNUNET_TESTING_Peer *me;
34
35static struct GNUNET_CADET_Handle *cadet_peer_1;
36
37static struct GNUNET_CADET_Handle *cadet_peer_2;
38
39static struct GNUNET_CADET_Channel *ch;
40
41static int result = GNUNET_OK;
42
43static int got_data = GNUNET_NO;
44
45static struct GNUNET_SCHEDULER_Task *abort_task;
46
47static struct GNUNET_SCHEDULER_Task *connect_task;
48
49static struct GNUNET_CADET_TransmitHandle *mth;
50
51
52/**
53 * Connect to other client and send data
54 *
55 * @param cls Closue (unused).
56 */
57static void
58do_connect (void *cls);
59
60
61/**
62 * Shutdown nicely
63 */
64static void
65do_shutdown (void *cls)
66{
67 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
68 "shutdown\n");
69 if (NULL != abort_task)
70 {
71 GNUNET_SCHEDULER_cancel (abort_task);
72 abort_task = NULL;
73 }
74 if (NULL != ch)
75 {
76 GNUNET_CADET_channel_destroy (ch);
77 ch = NULL;
78 }
79 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
80 "Disconnect client 1\n");
81 if (NULL != cadet_peer_1)
82 {
83 GNUNET_CADET_disconnect (cadet_peer_1);
84 cadet_peer_1 = NULL;
85 }
86 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
87 "Disconnect client 2\n");
88 if (NULL != cadet_peer_2)
89 {
90 GNUNET_CADET_disconnect (cadet_peer_2);
91 cadet_peer_2 = NULL;
92 }
93 if (NULL != connect_task)
94 {
95 GNUNET_SCHEDULER_cancel (connect_task);
96 connect_task = NULL;
97 }
98}
99
100
101/**
102 * Something went wrong and timed out. Kill everything and set error flag
103 */
104static void
105do_abort (void *cls)
106{
107 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ABORT\n");
108 result = GNUNET_SYSERR;
109 abort_task = NULL;
110 GNUNET_SCHEDULER_shutdown ();
111}
112
113
114/**
115 * Function is called whenever a message is received.
116 *
117 * @param cls closure (set from GNUNET_CADET_connect)
118 * @param channel connection to the other end
119 * @param channel_ctx place to store local state associated with the channel
120 * @param message the actual message
121 * @return #GNUNET_OK to keep the connection open,
122 * #GNUNET_SYSERR to close it (signal serious error)
123 */
124static int
125data_callback (void *cls,
126 struct GNUNET_CADET_Channel *channel,
127 void **channel_ctx,
128 const struct GNUNET_MessageHeader *message)
129{
130 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
131 "Data callback! Shutting down.\n");
132 got_data = GNUNET_YES;
133 GNUNET_SCHEDULER_shutdown ();
134 GNUNET_CADET_receive_done (channel);
135 return GNUNET_OK;
136}
137
138
139/**
140 * Method called whenever another peer has added us to a channel
141 * the other peer initiated.
142 *
143 * @param cls closure
144 * @param channel new handle to the channel
145 * @param initiator peer that started the channel
146 * @param port port number
147 * @param options channel options
148 * @return initial channel context for the channel
149 * (can be NULL -- that's not an error)
150 */
151static void *
152inbound_channel (void *cls,
153 struct GNUNET_CADET_Channel *channel,
154 const struct GNUNET_PeerIdentity *initiator,
155 const struct GNUNET_HashCode *port,
156 enum GNUNET_CADET_ChannelOption options)
157{
158 long id = (long) cls;
159
160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
161 "received incoming channel on peer %d, port %s\n",
162 (int) id,
163 GNUNET_h2s (port));
164 if (id != 2L)
165 {
166 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
167 "wrong peer\n");
168 result = GNUNET_SYSERR;
169 }
170 return NULL;
171}
172
173
174/**
175 * Function called whenever an channel is destroyed. Should clean up
176 * any associated state.
177 *
178 * @param cls closure (set from GNUNET_CADET_connect)
179 * @param channel connection to the other end (henceforth invalid)
180 * @param channel_ctx place where local state associated
181 * with the channel is stored
182 */
183static void
184channel_end (void *cls,
185 const struct GNUNET_CADET_Channel *channel,
186 void *channel_ctx)
187{
188 long id = (long) cls;
189
190 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
191 "incoming channel closed at peer %ld\n",
192 id);
193 if (NULL != mth)
194 {
195 GNUNET_CADET_notify_transmit_ready_cancel (mth);
196 mth = NULL;
197 }
198 if (channel == ch)
199 ch = NULL;
200 if (GNUNET_NO == got_data)
201 {
202 if (NULL == connect_task)
203 connect_task
204 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
205 2),
206 &do_connect,
207 NULL);
208 }
209}
210
211
212/**
213 * Handler array for traffic received on peer1
214 */
215static struct GNUNET_CADET_MessageHandler handlers1[] = {
216 {&data_callback, 1, 0},
217 {NULL, 0, 0}
218};
219
220
221/**
222 * Handler array for traffic received on peer2 (none expected)
223 */
224static struct GNUNET_CADET_MessageHandler handlers2[] = {
225 {&data_callback, 1, 0},
226 {NULL, 0, 0}
227};
228
229
230/**
231 * Data send callback: fillbuffer with test packet.
232 *
233 * @param cls Closure (unused).
234 * @param size Buffer size.
235 * @param buf Buffer to fill.
236 *
237 * @return size of test packet.
238 */
239static size_t
240do_send (void *cls, size_t size, void *buf)
241{
242 struct GNUNET_MessageHeader *m = buf;
243
244 mth = NULL;
245 if (NULL == buf)
246 {
247 GNUNET_break (0);
248 result = GNUNET_SYSERR;
249 return 0;
250 }
251 m->size = htons (sizeof (struct GNUNET_MessageHeader));
252 m->type = htons (1);
253 GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
254 return sizeof (struct GNUNET_MessageHeader);
255}
256
257
258/**
259 * Connect to other client and send data
260 *
261 * @param cls Closue (unused).
262 */
263static void
264do_connect (void *cls)
265{
266 struct GNUNET_PeerIdentity id;
267
268 connect_task = NULL;
269 GNUNET_TESTING_peer_get_identity (me, &id);
270 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
271 "CONNECT BY PORT\n");
272 ch = GNUNET_CADET_channel_create (cadet_peer_1,
273 NULL,
274 &id, GC_u2h (1),
275 GNUNET_CADET_OPTION_DEFAULT);
276 mth = GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO,
277 GNUNET_TIME_UNIT_FOREVER_REL,
278 sizeof (struct GNUNET_MessageHeader),
279 &do_send, NULL);
280}
281
282
283/**
284 * Initialize framework and start test
285 *
286 * @param cls Closure (unused).
287 * @param cfg Configuration handle.
288 * @param peer Testing peer handle.
289 */
290static void
291run (void *cls,
292 const struct GNUNET_CONFIGURATION_Handle *cfg,
293 struct GNUNET_TESTING_Peer *peer)
294{
295 me = peer;
296 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
297 NULL);
298 abort_task =
299 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
300 (GNUNET_TIME_UNIT_SECONDS, 15),
301 &do_abort,
302 NULL);
303 cadet_peer_1 = GNUNET_CADET_connect (cfg, /* configuration */
304 (void *) 1L, /* cls */
305 &channel_end, /* channel end hndlr */
306 handlers1); /* traffic handlers */
307 cadet_peer_2 = GNUNET_CADET_connect (cfg, /* configuration */
308 (void *) 2L, /* cls */
309 &channel_end, /* channel end hndlr */
310 handlers2); /* traffic handlers */
311
312 if ( (NULL == cadet_peer_1) ||
313 (NULL == cadet_peer_2) )
314 {
315 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
316 "Couldn't connect to cadet :(\n");
317 result = GNUNET_SYSERR;
318 GNUNET_SCHEDULER_shutdown ();
319 return;
320 }
321 GNUNET_CADET_open_port (cadet_peer_2,
322 GC_u2h (1),
323 &inbound_channel,
324 (void *) 2L);
325 if (NULL == connect_task)
326 connect_task
327 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
328 2),
329 &do_connect,
330 NULL);
331}
332
333
334/**
335 * Main
336 */
337int
338main (int argc, char *argv[])
339{
340 if (0 != GNUNET_TESTING_peer_run ("test-cadet-local",
341 "test_cadet.conf",
342 &run, NULL))
343 {
344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "run failed\n");
345 return 2;
346 }
347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Final result: %d\n", result);
348 return (result == GNUNET_OK) ? 0 : 1;
349}
350
351/* end of test_cadet_local_1.c */
diff --git a/src/cadet/test_cadet_new.c b/src/cadet/test_cadet_new.c
deleted file mode 100644
index 374e86bf3..000000000
--- a/src/cadet/test_cadet_new.c
+++ /dev/null
@@ -1,1105 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file cadet/test_cadet_mq.c
22 * @author Bart Polot
23 * @author Christian Grothoff
24 * @brief Test for the cadet service using mq API.
25 */
26#include <stdio.h>
27#include "platform.h"
28#include "cadet_test_lib_new.h"
29#include "gnunet_cadet_service.h"
30#include "gnunet_statistics_service.h"
31#include <gauger.h>
32
33
34/**
35 * Ugly workaround to unify data handlers on incoming and outgoing channels.
36 */
37struct CadetTestChannelWrapper
38{
39 /**
40 * Channel pointer.
41 */
42 struct GNUNET_CADET_Channel *ch;
43};
44
45/**
46 * How many messages to send by default.
47 */
48#define TOTAL_PACKETS 500 /* Cannot exceed 64k! */
49
50/**
51 * How long until we give up on connecting the peers?
52 */
53#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
54
55/**
56 * Time to wait by default for stuff that should be rather fast.
57 */
58#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
59
60/**
61 * DIFFERENT TESTS TO RUN
62 */
63#define SETUP 0
64#define FORWARD 1
65#define KEEPALIVE 2
66#define SPEED 3
67#define SPEED_ACK 4
68#define SPEED_REL 8
69#define P2P_SIGNAL 10
70
71/**
72 * Which test are we running?
73 */
74static int test;
75
76/**
77 * String with test name
78 */
79static char *test_name;
80
81/**
82 * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic.
83 */
84static int test_backwards = GNUNET_NO;
85
86/**
87 * How many packets to send.
88 */
89static unsigned int total_packets;
90
91/**
92 * Time to wait for fast operations.
93 */
94static struct GNUNET_TIME_Relative short_time;
95
96/**
97 * How many events have happened
98 */
99static int ok;
100
101/**
102 * Number of events expected to conclude the test successfully.
103 */
104static int ok_goal;
105
106/**
107 * Size of each test packet's payload
108 */
109static size_t size_payload = sizeof (uint32_t);
110
111/**
112 * Operation to get peer ids.
113 */
114static struct GNUNET_TESTBED_Operation *t_op[2];
115
116/**
117 * Peer ids.
118 */
119static struct GNUNET_PeerIdentity *p_id[2];
120
121/**
122 * Port ID
123 */
124static struct GNUNET_HashCode port;
125
126/**
127 * Peer ids counter.
128 */
129static unsigned int p_ids;
130
131/**
132 * Is the setup initialized?
133 */
134static int initialized;
135
136/**
137 * Number of payload packes sent.
138 */
139static int data_sent;
140
141/**
142 * Number of payload packets received.
143 */
144static int data_received;
145
146/**
147 * Number of payload packed acknowledgements sent.
148 */
149static int ack_sent;
150
151/**
152 * Number of payload packed explicitly (app level) acknowledged.
153 */
154static int ack_received;
155
156/**
157 * Total number of peers asked to run.
158 */
159static unsigned long long peers_requested;
160
161/**
162 * Number of currently running peers (should be same as @c peers_requested).
163 */
164static unsigned long long peers_running;
165
166/**
167 * Test context (to shut down).
168 */
169struct GNUNET_CADET_TEST_Context *test_ctx;
170
171/**
172 * Task called to disconnect peers.
173 */
174static struct GNUNET_SCHEDULER_Task *disconnect_task;
175
176/**
177 * Task To perform tests
178 */
179static struct GNUNET_SCHEDULER_Task *test_task;
180
181/**
182 * Task runnining #send_next_msg().
183 */
184static struct GNUNET_SCHEDULER_Task *send_next_msg_task;
185
186/**
187 * Cadet handle for the root peer
188 */
189static struct GNUNET_CADET_Handle *h1;
190
191/**
192 * Cadet handle for the first leaf peer
193 */
194static struct GNUNET_CADET_Handle *h2;
195
196/**
197 * Channel handle for the root peer
198 */
199static struct GNUNET_CADET_Channel *outgoing_ch;
200
201/**
202 * Channel handle for the dest peer
203 */
204static struct GNUNET_CADET_Channel *incoming_ch;
205
206/**
207 * Time we started the data transmission (after channel has been established
208 * and initilized).
209 */
210static struct GNUNET_TIME_Absolute start_time;
211
212/**
213 * Peers handle.
214 */
215static struct GNUNET_TESTBED_Peer **testbed_peers;
216
217/**
218 * Statistics operation handle.
219 */
220static struct GNUNET_TESTBED_Operation *stats_op;
221
222/**
223 * Keepalives sent.
224 */
225static unsigned int ka_sent;
226
227/**
228 * Keepalives received.
229 */
230static unsigned int ka_received;
231
232/**
233 * How many messages were dropped by CADET because of full buffers?
234 */
235static unsigned int msg_dropped;
236
237
238/******************************************************************************/
239
240
241/******************************************************************************/
242
243
244/**
245 * Get the channel considered as the "target" or "receiver", depending on
246 * the test type and size.
247 *
248 * @return Channel handle of the target client, either 0 (for backward tests)
249 * or the last peer in the line (for other tests).
250 */
251static struct GNUNET_CADET_Channel *
252get_target_channel ()
253{
254 if (SPEED == test && GNUNET_YES == test_backwards)
255 return outgoing_ch;
256 else
257 return incoming_ch;
258}
259
260
261/**
262 * Show the results of the test (banwidth acheived) and log them to GAUGER
263 */
264static void
265show_end_data (void)
266{
267 static struct GNUNET_TIME_Absolute end_time;
268 static struct GNUNET_TIME_Relative total_time;
269
270 end_time = GNUNET_TIME_absolute_get ();
271 total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time);
272 FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name);
273 FPRINTF (stderr, "Test time %s\n",
274 GNUNET_STRINGS_relative_time_to_string (total_time, GNUNET_YES));
275 FPRINTF (stderr, "Test bandwidth: %f kb/s\n", 4 * total_packets * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms
276 FPRINTF (stderr, "Test throughput: %f packets/s\n\n", total_packets * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms
277 GAUGER ("CADET", test_name,
278 total_packets * 1000.0 / (total_time.rel_value_us / 1000),
279 "packets/s");
280}
281
282
283/**
284 * Disconnect from cadet services af all peers, call shutdown.
285 *
286 * @param cls Closure (line number from which termination was requested).
287 * @param tc Task Context.
288 */
289static void
290disconnect_cadet_peers (void *cls)
291{
292 long line = (long) cls;
293 unsigned int i;
294
295 disconnect_task = NULL;
296 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
297 "disconnecting cadet service of peers, called from line %ld\n",
298 line);
299 for (i = 0; i < 2; i++)
300 {
301 GNUNET_TESTBED_operation_done (t_op[i]);
302 }
303 if (NULL != outgoing_ch)
304 {
305 GNUNET_CADET_channel_destroy (outgoing_ch);
306 outgoing_ch = NULL;
307 }
308 if (NULL != incoming_ch)
309 {
310 GNUNET_CADET_channel_destroy (incoming_ch);
311 incoming_ch = NULL;
312 }
313 GNUNET_CADET_TEST_cleanup (test_ctx);
314 GNUNET_SCHEDULER_shutdown ();
315}
316
317
318/**
319 * Shut down peergroup, clean up.
320 *
321 * @param cls Closure (unused).
322 * @param tc Task Context.
323 */
324static void
325shutdown_task (void *cls)
326{
327 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n");
328 if (NULL != send_next_msg_task)
329 {
330 GNUNET_SCHEDULER_cancel (send_next_msg_task);
331 send_next_msg_task = NULL;
332 }
333 if (NULL != test_task)
334 {
335 GNUNET_SCHEDULER_cancel (test_task);
336 test_task = NULL;
337 }
338 if (NULL != disconnect_task)
339 {
340 GNUNET_SCHEDULER_cancel (disconnect_task);
341 disconnect_task =
342 GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) __LINE__);
343 }
344}
345
346
347/**
348 * Stats callback. Finish the stats testbed operation and when all stats have
349 * been iterated, shutdown the test.
350 *
351 * @param cls Closure (line number from which termination was requested).
352 * @param op the operation that has been finished
353 * @param emsg error message in case the operation has failed; will be NULL if
354 * operation has executed successfully.
355 */
356static void
357stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
358{
359 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " KA sent: %u, KA received: %u\n",
360 ka_sent, ka_received);
361 if ((KEEPALIVE == test) && ((ka_sent < 2) || (ka_sent > ka_received + 1)))
362 {
363 GNUNET_break (0);
364 ok--;
365 }
366 GNUNET_TESTBED_operation_done (stats_op);
367
368 if (NULL != disconnect_task)
369 GNUNET_SCHEDULER_cancel (disconnect_task);
370 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, cls);
371}
372
373
374/**
375 * Process statistic values.
376 *
377 * @param cls closure (line number, unused)
378 * @param peer the peer the statistic belong to
379 * @param subsystem name of subsystem that created the statistic
380 * @param name the name of the datum
381 * @param value the current value
382 * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
383 * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
384 */
385static int
386stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer,
387 const char *subsystem, const char *name, uint64_t value,
388 int is_persistent)
389{
390 static const char *s_sent = "# keepalives sent";
391 static const char *s_recv = "# keepalives received";
392 static const char *rdrops = "# messages dropped due to full buffer";
393 static const char *cdrops = "# messages dropped due to slow client";
394 uint32_t i;
395
396 i = GNUNET_TESTBED_get_index (peer);
397 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "STATS PEER %u - %s [%s]: %llu\n", i,
398 subsystem, name, (unsigned long long) value);
399 if (0 == strncmp (s_sent, name, strlen (s_sent)) && 0 == i)
400 ka_sent = value;
401 if (0 == strncmp (s_recv, name, strlen (s_recv)) && peers_requested - 1 == i)
402 ka_received = value;
403 if (0 == strncmp (rdrops, name, strlen (rdrops)))
404 msg_dropped += value;
405 if (0 == strncmp (cdrops, name, strlen (cdrops)))
406 msg_dropped += value;
407
408 return GNUNET_OK;
409}
410
411
412/**
413 * Task to gather all statistics.
414 *
415 * @param cls Closure (line from which the task was scheduled).
416 */
417static void
418gather_stats_and_exit (void *cls)
419{
420 long l = (long) cls;
421
422 disconnect_task = NULL;
423 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
424 "gathering statistics from line %ld\n",
425 l);
426 if (NULL != outgoing_ch)
427 {
428 GNUNET_CADET_channel_destroy (outgoing_ch);
429 outgoing_ch = NULL;
430 }
431 stats_op = GNUNET_TESTBED_get_statistics (peers_running,
432 testbed_peers,
433 "cadet",
434 NULL,
435 &stats_iterator,
436 stats_cont,
437 cls);
438}
439
440
441
442/**
443 * Abort test: schedule disconnect and shutdown immediately
444 *
445 * @param line Line in the code the abort is requested from (__LINE__).
446 */
447static void
448abort_test (long line)
449{
450 if (NULL != disconnect_task)
451 {
452 GNUNET_SCHEDULER_cancel (disconnect_task);
453 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting test from %ld\n", line);
454 disconnect_task =
455 GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) line);
456 }
457}
458
459
460/**
461 * Send a message on the channel with the appropriate size and payload.
462 *
463 * Update the appropriate *_sent counter.
464 *
465 * @param channel Channel to send the message on.
466 */
467static void
468send_test_message (struct GNUNET_CADET_Channel *channel)
469{
470 struct GNUNET_MQ_Envelope *env;
471 struct GNUNET_MessageHeader *msg;
472 uint32_t *data;
473 int payload;
474 int size;
475
476 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
477 "Sending test message on channel %p\n",
478 channel);
479 size = size_payload;
480 if (GNUNET_NO == initialized)
481 {
482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending INITIALIZER\n");
483 size += 1000;
484 payload = data_sent;
485 if (SPEED_ACK == test) // FIXME unify SPEED_ACK with an initializer
486 data_sent++;
487 }
488 else if (SPEED == test || SPEED_ACK == test)
489 {
490 if (get_target_channel() == channel)
491 {
492 payload = ack_sent;
493 size += ack_sent;
494 ack_sent++;
495 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
496 "Sending ACK %u [%d bytes]\n",
497 payload, size);
498 }
499 else
500 {
501 payload = data_sent;
502 size += data_sent;
503 data_sent++;
504 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
505 "Sending DATA %u [%d bytes]\n",
506 data_sent, size);
507 }
508 }
509 else if (FORWARD == test)
510 {
511 payload = ack_sent;
512 }
513 else if (P2P_SIGNAL == test)
514 {
515 payload = data_sent;
516 }
517 else
518 {
519 GNUNET_assert (0);
520 }
521 env = GNUNET_MQ_msg_extra (msg, size, GNUNET_MESSAGE_TYPE_DUMMY);
522
523 data = (uint32_t *) &msg[1];
524 *data = htonl (payload);
525 GNUNET_MQ_send (GNUNET_CADET_get_mq (channel), env);
526}
527
528/**
529 * Task to request a new data transmission in a SPEED test, without waiting
530 * for previous messages to be sent/arrrive.
531 *
532 * @param cls Closure (unused).
533 */
534static void
535send_next_msg (void *cls)
536{
537 struct GNUNET_CADET_Channel *channel;
538
539 send_next_msg_task = NULL;
540 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending next message: %d\n", data_sent);
541
542 channel = GNUNET_YES == test_backwards ? incoming_ch : outgoing_ch;
543 GNUNET_assert (NULL != channel);
544 GNUNET_assert (SPEED == test);
545 send_test_message (channel);
546 if (data_sent < total_packets)
547 {
548 /* SPEED test: Send all messages as soon as possible */
549 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
550 "Scheduling message %d\n",
551 data_sent + 1);
552 send_next_msg_task =
553 GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_SECONDS,
554 &send_next_msg,
555 NULL);
556 }
557}
558
559
560/**
561 * Every few messages cancel the timeout task and re-schedule it again, to
562 * avoid timing out when traffic keeps coming.
563 *
564 * @param line Code line number to log if a timeout occurs.
565 */
566static void
567reschedule_timeout_task (long line)
568{
569 if ((ok % 10) == 0)
570 {
571 if (NULL != disconnect_task)
572 {
573 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
574 " reschedule timeout every 10 messages\n");
575 GNUNET_SCHEDULER_cancel (disconnect_task);
576 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
577 &gather_stats_and_exit,
578 (void *) line);
579 }
580 }
581}
582
583
584/**
585 * Check if payload is sane (size contains payload).
586 *
587 * @param cls should match #ch
588 * @param message The actual message.
589 * @return #GNUNET_OK to keep the channel open,
590 * #GNUNET_SYSERR to close it (signal serious error).
591 */
592static int
593check_data (void *cls, const struct GNUNET_MessageHeader *message)
594{
595 if (sizeof (struct GNUNET_MessageHeader) >= ntohs (message->size))
596 return GNUNET_SYSERR;
597 return GNUNET_OK; /* all is well-formed */
598}
599
600
601/**
602 * Function is called whenever a message is received.
603 *
604 * @param cls closure (set from GNUNET_CADET_connect(), peer number)
605 * @param message the actual message
606 */
607static void
608handle_data (void *cls, const struct GNUNET_MessageHeader *message)
609{
610 struct CadetTestChannelWrapper *ch = cls;
611 struct GNUNET_CADET_Channel *channel = ch->ch;
612 uint32_t *data;
613 uint32_t payload;
614 int *counter;
615
616 ok++;
617 GNUNET_CADET_receive_done (channel);
618 counter = get_target_channel () == channel ? &data_received : &ack_received;
619
620 reschedule_timeout_task ((long) __LINE__);
621
622 if (channel == outgoing_ch)
623 {
624 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message.\n");
625 }
626 else if (channel == incoming_ch)
627 {
628 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Leaf client got a message.\n");
629 }
630 else
631 {
632 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unknown channel %p.\n", channel);
633 GNUNET_assert (0);
634 }
635
636 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal);
637 data = (uint32_t *) &message[1];
638 payload = ntohl (*data);
639 if (payload == *counter)
640 {
641 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload as expected: %u\n", payload);
642 }
643 else
644 {
645 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
646 " payload %u, expected: %u\n",
647 payload, *counter);
648 }
649
650 if (GNUNET_NO == initialized)
651 {
652 initialized = GNUNET_YES;
653 start_time = GNUNET_TIME_absolute_get ();
654 if (SPEED == test)
655 {
656 GNUNET_assert (incoming_ch == channel);
657 send_next_msg_task = GNUNET_SCHEDULER_add_now (&send_next_msg, NULL);
658 return;
659 }
660 }
661
662 (*counter)++;
663 if (get_target_channel () == channel) /* Got "data" */
664 {
665 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received);
666 if (SPEED != test || (ok_goal - 2) == ok)
667 {
668 /* Send ACK */
669 send_test_message (channel);
670 return;
671 }
672 else
673 {
674 if (data_received < total_packets)
675 return;
676 }
677 }
678 else /* Got "ack" */
679 {
680 if (SPEED_ACK == test || SPEED == test)
681 {
682 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", ack_received);
683 /* Send more data */
684 send_test_message (channel);
685 if (ack_received < total_packets && SPEED != test)
686 return;
687 if (ok == 2 && SPEED == test)
688 return;
689 show_end_data ();
690 }
691 if (test == P2P_SIGNAL)
692 {
693 GNUNET_CADET_channel_destroy (incoming_ch);
694 incoming_ch = NULL;
695 }
696 else
697 {
698 GNUNET_CADET_channel_destroy (outgoing_ch);
699 outgoing_ch = NULL;
700 }
701 }
702}
703
704
705/**
706 * Method called whenever a peer connects to a port in MQ-based CADET.
707 *
708 * @param cls Closure from #GNUNET_CADET_open_porT (peer # as long).
709 * @param channel New handle to the channel.
710 * @param source Peer that started this channel.
711 * @return Closure for the incoming @a channel. It's given to:
712 * - The #GNUNET_CADET_DisconnectEventHandler (given to
713 * #GNUNET_CADET_open_porT) when the channel dies.
714 * - Each the #GNUNET_MQ_MessageCallback handlers for each message
715 * received on the @a channel.
716 */
717static void *
718connect_handler (void *cls, struct GNUNET_CADET_Channel *channel,
719 const struct GNUNET_PeerIdentity *source)
720{
721 struct CadetTestChannelWrapper *ch;
722 long peer = (long) cls;
723
724 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
725 "Incoming channel from %s to %ld: %p\n",
726 GNUNET_i2s (source), peer, channel);
727 ok++;
728 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
729 if (peer == peers_requested - 1)
730 {
731 if (NULL != incoming_ch)
732 {
733 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
734 "Duplicate incoming channel for client %lu\n", (long) cls);
735 GNUNET_assert (0);
736 }
737 incoming_ch = channel;
738 }
739 else
740 {
741 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
742 "Incoming channel for unexpected peer #%lu\n", (long) cls);
743 GNUNET_assert (0);
744 }
745 if (NULL != disconnect_task)
746 {
747 GNUNET_SCHEDULER_cancel (disconnect_task);
748 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
749 &gather_stats_and_exit,
750 (void *) __LINE__);
751 }
752
753 /* TODO: cannot return channel as-is, in order to unify the data handlers */
754 ch = GNUNET_new (struct CadetTestChannelWrapper);
755 ch->ch = channel;
756
757 return ch;
758}
759
760
761/**
762 * Function called whenever an MQ-channel is destroyed, even if the destruction
763 * was requested by #GNUNET_CADET_channel_destroy.
764 * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
765 *
766 * It should clean up any associated state, including cancelling any pending
767 * transmission on this channel.
768 *
769 * @param cls Channel closure (channel wrapper).
770 * @param channel Connection to the other end (henceforth invalid).
771 */
772static void
773disconnect_handler (void *cls, const struct GNUNET_CADET_Channel *channel)
774{
775 struct CadetTestChannelWrapper *ch_w = cls;
776
777 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Channel disconnected\n");
778 GNUNET_assert (ch_w->ch == channel);
779 if (channel == incoming_ch)
780 {
781 ok++;
782 incoming_ch = NULL;
783 }
784 else if (outgoing_ch == channel
785 )
786 {
787 if (P2P_SIGNAL == test)
788 {
789 ok++;
790 }
791 outgoing_ch = NULL;
792 }
793 else
794 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unknown channel! %p\n", channel);
795 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
796
797 if (NULL != disconnect_task)
798 {
799 GNUNET_SCHEDULER_cancel (disconnect_task);
800 disconnect_task =
801 GNUNET_SCHEDULER_add_now (&gather_stats_and_exit, (void *) __LINE__);
802 }
803}
804
805
806/**
807 * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES.
808 *
809 * Testcase continues when the root receives confirmation of connected peers,
810 * on callback function ch.
811 *
812 * @param cls Closure (unused).
813 */
814static void
815start_test (void *cls)
816{
817 struct GNUNET_MQ_MessageHandler handlers[] = {
818 GNUNET_MQ_hd_var_size (data,
819 GNUNET_MESSAGE_TYPE_DUMMY,
820 struct GNUNET_MessageHeader,
821 NULL),
822 GNUNET_MQ_handler_end ()
823 };
824 struct CadetTestChannelWrapper *ch;
825 enum GNUNET_CADET_ChannelOption flags;
826
827 test_task = NULL;
828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "start_test\n");
829 if (NULL != disconnect_task)
830 {
831 GNUNET_SCHEDULER_cancel (disconnect_task);
832 disconnect_task = NULL;
833 }
834
835 flags = GNUNET_CADET_OPTION_DEFAULT;
836 if (SPEED_REL == test)
837 {
838 test = SPEED;
839 flags |= GNUNET_CADET_OPTION_RELIABLE;
840 }
841
842 ch = GNUNET_new (struct CadetTestChannelWrapper);
843 outgoing_ch = GNUNET_CADET_channel_creatE (h1,
844 ch,
845 p_id[1],
846 &port,
847 flags,
848 NULL,
849 &disconnect_handler,
850 handlers);
851
852 ch->ch = outgoing_ch;
853
854 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
855 &gather_stats_and_exit,
856 (void *) __LINE__);
857 if (KEEPALIVE == test)
858 return; /* Don't send any data. */
859
860
861 data_received = 0;
862 data_sent = 0;
863 ack_received = 0;
864 ack_sent = 0;
865 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
866 "Sending data initializer on channel %p...\n",
867 outgoing_ch);
868 send_test_message (outgoing_ch);
869}
870
871
872/**
873 * Callback to be called when the requested peer information is available
874 *
875 * @param cls the closure from GNUNET_TESTBED_peer_get_information()
876 * @param op the operation this callback corresponds to
877 * @param pinfo the result; will be NULL if the operation has failed
878 * @param emsg error message if the operation has failed;
879 * NULL if the operation is successfull
880 */
881static void
882pi_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
883 const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg)
884{
885 long i = (long) cls;
886
887 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ID callback for %ld\n", i);
888
889 if ((NULL == pinfo) || (NULL != emsg))
890 {
891 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
892 abort_test (__LINE__);
893 return;
894 }
895 p_id[i] = pinfo->result.id;
896 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i]));
897 p_ids++;
898 if (p_ids < 2)
899 return;
900 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n");
901 test_task = GNUNET_SCHEDULER_add_now (&start_test, NULL);
902}
903
904
905/**
906 * test main: start test when all peers are connected
907 *
908 * @param cls Closure.
909 * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end.
910 * @param num_peers Number of peers that are running.
911 * @param peers Array of peers.
912 * @param cadets Handle to each of the CADETs of the peers.
913 */
914static void
915tmain (void *cls,
916 struct GNUNET_CADET_TEST_Context *ctx,
917 unsigned int num_peers,
918 struct GNUNET_TESTBED_Peer **peers,
919 struct GNUNET_CADET_Handle **cadets)
920{
921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n");
922 ok = 0;
923 test_ctx = ctx;
924 peers_running = num_peers;
925 GNUNET_assert (peers_running == peers_requested);
926 testbed_peers = peers;
927 h1 = cadets[0];
928 h2 = cadets[num_peers - 1];
929 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
930 &disconnect_cadet_peers,
931 (void *) __LINE__);
932 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
933 t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
934 GNUNET_TESTBED_PIT_IDENTITY,
935 &pi_cb,
936 (void *) 0L);
937 t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
938 GNUNET_TESTBED_PIT_IDENTITY,
939 &pi_cb,
940 (void *) 1L);
941 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n");
942}
943
944
945/**
946 * Main: start test
947 */
948int
949main (int argc, char *argv[])
950{
951 struct GNUNET_MQ_MessageHandler handlers[] = {
952 GNUNET_MQ_hd_var_size (data,
953 GNUNET_MESSAGE_TYPE_DUMMY,
954 struct GNUNET_MessageHeader,
955 NULL),
956 GNUNET_MQ_handler_end ()
957 };
958
959 initialized = GNUNET_NO;
960 static const struct GNUNET_HashCode *ports[2];
961 const char *config_file;
962 char port_id[] = "test port";
963
964 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
965 {'t', "time", "short_time",
966 gettext_noop ("set short timeout"),
967 GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &short_time},
968 {'m', "messages", "NUM_MESSAGES",
969 gettext_noop ("set number of messages to send"),
970 GNUNET_YES, &GNUNET_GETOPT_set_uint, &total_packets},
971
972 GNUNET_GETOPT_OPTION_END
973 };
974
975 GNUNET_log_setup ("test", "DEBUG", NULL);
976
977 total_packets = TOTAL_PACKETS;
978 short_time = SHORT_TIME;
979 if (-1 == GNUNET_GETOPT_run (argv[0], options, argc, argv))
980 {
981 FPRINTF (stderr, "test failed: problem with CLI parameters\n");
982 exit (1);
983 }
984
985 config_file = "test_cadet.conf";
986 GNUNET_CRYPTO_hash (port_id, sizeof (port_id), &port);
987
988 /* Find out requested size */
989 if (strstr (argv[0], "_2_") != NULL)
990 {
991 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DIRECT CONNECTIONs\n");
992 peers_requested = 2;
993 }
994 else if (strstr (argv[0], "_5_") != NULL)
995 {
996 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "5 PEER LINE\n");
997 peers_requested = 5;
998 }
999 else
1000 {
1001 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "SIZE UNKNOWN, USING 2\n");
1002 peers_requested = 2;
1003 }
1004
1005 /* Find out requested test */
1006 if (strstr (argv[0], "_forward") != NULL)
1007 {
1008 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n");
1009 test = FORWARD;
1010 test_name = "unicast";
1011 ok_goal = 4;
1012 }
1013 else if (strstr (argv[0], "_signal") != NULL)
1014 {
1015 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n");
1016 test = P2P_SIGNAL;
1017 test_name = "signal";
1018 ok_goal = 4;
1019 }
1020 else if (strstr (argv[0], "_speed_ack") != NULL)
1021 {
1022 /* Test is supposed to generate the following callbacks:
1023 * 1 incoming channel (@dest)
1024 * total_packets received data packet (@dest)
1025 * total_packets received data packet (@orig)
1026 * 1 received channel destroy (@dest)
1027 */
1028 ok_goal = total_packets * 2 + 2;
1029 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n");
1030 test = SPEED_ACK;
1031 test_name = "speed ack";
1032 }
1033 else if (strstr (argv[0], "_speed") != NULL)
1034 {
1035 /* Test is supposed to generate the following callbacks:
1036 * 1 incoming channel (@dest)
1037 * 1 initial packet (@dest)
1038 * total_packets received data packet (@dest)
1039 * 1 received data packet (@orig)
1040 * 1 received channel destroy (@dest)
1041 */
1042 ok_goal = total_packets + 4;
1043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n");
1044 if (strstr (argv[0], "_reliable") != NULL)
1045 {
1046 test = SPEED_REL;
1047 test_name = "speed reliable";
1048 config_file = "test_cadet_drop.conf";
1049 }
1050 else
1051 {
1052 test = SPEED;
1053 test_name = "speed";
1054 }
1055 }
1056 else if (strstr (argv[0], "_keepalive") != NULL)
1057 {
1058 test = KEEPALIVE;
1059 /* Test is supposed to generate the following callbacks:
1060 * 1 incoming channel (@dest)
1061 * [wait]
1062 * 1 received channel destroy (@dest)
1063 */
1064 ok_goal = 2;
1065 }
1066 else
1067 {
1068 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n");
1069 test = SETUP;
1070 ok_goal = 0;
1071 }
1072
1073 if (strstr (argv[0], "backwards") != NULL)
1074 {
1075 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n");
1076 test_backwards = GNUNET_YES;
1077 GNUNET_asprintf (&test_name, "backwards %s", test_name);
1078 }
1079
1080 p_ids = 0;
1081 ports[0] = &port;
1082 ports[1] = NULL;
1083 GNUNET_CADET_TEST_ruN ("test_cadet_small",
1084 config_file,
1085 peers_requested,
1086 &tmain,
1087 NULL, /* tmain cls */
1088 &connect_handler,
1089 NULL,
1090 &disconnect_handler,
1091 handlers,
1092 ports);
1093 if (NULL != strstr (argv[0], "_reliable"))
1094 msg_dropped = 0; /* dropped should be retransmitted */
1095
1096 if (ok_goal > ok - msg_dropped)
1097 {
1098 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "FAILED! (%d/%d)\n", ok, ok_goal);
1099 return 1;
1100 }
1101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n");
1102 return 0;
1103}
1104
1105/* end of test_cadet.c */
diff --git a/src/cadet/test_cadet_single.c b/src/cadet/test_cadet_single.c
deleted file mode 100644
index b45b0af5d..000000000
--- a/src/cadet/test_cadet_single.c
+++ /dev/null
@@ -1,354 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/test_cadet_single.c
23 * @brief test cadet single: test of cadet channels with just one client
24 * @author Bartlomiej Polot
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_dht_service.h"
30#include "gnunet_testing_lib.h"
31#include "gnunet_cadet_service.h"
32
33#define REPETITIONS 5
34#define DATA_SIZE 35000
35
36struct GNUNET_TESTING_Peer *me;
37
38static struct GNUNET_CADET_Handle *cadet;
39
40static struct GNUNET_CADET_Channel *ch1;
41
42static struct GNUNET_CADET_Channel *ch2;
43
44static int result;
45
46static struct GNUNET_SCHEDULER_Task *abort_task;
47
48static struct GNUNET_SCHEDULER_Task *connect_task;
49
50static unsigned int repetition;
51
52static struct GNUNET_CADET_TransmitHandle *nth;
53
54static struct GNUNET_CADET_Port *port;
55
56
57/* forward declaration */
58static size_t
59do_send (void *cls, size_t size, void *buf);
60
61
62/**
63 * Shutdown nicely
64 */
65static void
66do_shutdown (void *cls)
67{
68 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
69 "shutdown\n");
70 if (NULL != port)
71 {
72 GNUNET_CADET_close_port (port);
73 port = NULL;
74 }
75 if (NULL != nth)
76 {
77 GNUNET_CADET_notify_transmit_ready_cancel (nth);
78 nth = NULL;
79 }
80 if (NULL != abort_task)
81 {
82 GNUNET_SCHEDULER_cancel (abort_task);
83 abort_task = NULL;
84 }
85 if (NULL != connect_task)
86 {
87 GNUNET_SCHEDULER_cancel (connect_task);
88 connect_task = NULL;
89 }
90 if (NULL != ch1)
91 {
92 GNUNET_CADET_channel_destroy (ch1);
93 ch1 = NULL;
94 }
95 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
96 "Disconnect clients\n");
97 if (NULL != cadet)
98 {
99 GNUNET_CADET_disconnect (cadet);
100 cadet = NULL;
101 }
102 else
103 {
104 GNUNET_break (0);
105 }
106}
107
108
109/**
110 * Something went wrong and timed out. Kill everything and set error flag
111 */
112static void
113do_abort (void *cls)
114{
115 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ABORT\n");
116 result = GNUNET_SYSERR;
117 abort_task = NULL;
118 GNUNET_SCHEDULER_shutdown ();
119}
120
121
122/**
123 * Function is called whenever a message is received.
124 *
125 * @param cls closure (set from GNUNET_CADET_connect)
126 * @param channel connection to the other end
127 * @param channel_ctx place to store local state associated with the channel
128 * @param message the actual message
129 * @return #GNUNET_OK to keep the connection open,
130 * #GNUNET_SYSERR to close it (signal serious error)
131 */
132static int
133data_callback (void *cls,
134 struct GNUNET_CADET_Channel *channel,
135 void **channel_ctx,
136 const struct GNUNET_MessageHeader *message)
137{
138 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
139 "Data callback! Repetition %u/%u\n",
140 repetition, REPETITIONS);
141 repetition++;
142 if (repetition < REPETITIONS)
143 {
144 struct GNUNET_CADET_Channel *my_channel;
145 if (0 == repetition % 2)
146 my_channel = ch1;
147 else
148 my_channel = ch2;
149 nth = GNUNET_CADET_notify_transmit_ready (my_channel,
150 GNUNET_NO,
151 GNUNET_TIME_UNIT_FOREVER_REL,
152 sizeof (struct GNUNET_MessageHeader)
153 + DATA_SIZE,
154 &do_send, NULL);
155 GNUNET_CADET_receive_done (channel);
156 return GNUNET_OK;
157 }
158 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
159 "All data OK. Destroying channel.\n");
160 GNUNET_assert (NULL == nth);
161 GNUNET_CADET_channel_destroy (ch1);
162 ch1 = NULL;
163 return GNUNET_OK;
164}
165
166
167/**
168 * Method called whenever another peer has added us to a channel
169 * the other peer initiated.
170 *
171 * @param cls closure
172 * @param channel new handle to the channel
173 * @param initiator peer that started the channel
174 * @param port port number
175 * @param options channel option flags
176 * @return initial channel context for the channel
177 * (can be NULL -- that's not an error)
178 */
179static void *
180inbound_channel (void *cls,
181 struct GNUNET_CADET_Channel *channel,
182 const struct GNUNET_PeerIdentity *initiator,
183 const struct GNUNET_HashCode *port,
184 enum GNUNET_CADET_ChannelOption options)
185{
186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
187 "received incoming channel on port %s\n",
188 GNUNET_h2s (port));
189 ch2 = channel;
190 return NULL;
191}
192
193
194/**
195 * Function called whenever an inbound channel is destroyed. Should clean up
196 * any associated state.
197 *
198 * @param cls closure (set from GNUNET_CADET_connect)
199 * @param channel connection to the other end (henceforth invalid)
200 * @param channel_ctx place where local state associated
201 * with the channel is stored
202 */
203static void
204channel_end (void *cls,
205 const struct GNUNET_CADET_Channel *channel,
206 void *channel_ctx)
207{
208 long id = (long) cls;
209
210 nth = NULL;
211 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
212 "incoming channel closed at peer %ld\n",
213 id);
214 if ( (REPETITIONS == repetition) &&
215 (channel == ch2) )
216 {
217 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
218 "everything fine! finishing!\n");
219 result = GNUNET_OK;
220 GNUNET_SCHEDULER_shutdown ();
221 }
222 if (channel == ch2)
223 ch2 = NULL;
224 if (channel == ch1)
225 ch1 = NULL;
226}
227
228
229/**
230 * Handler array for traffic received on peer1
231 */
232static struct GNUNET_CADET_MessageHandler handlers1[] = {
233 {&data_callback, 1, 0},
234 {NULL, 0, 0}
235};
236
237
238/**
239 * Data send callback: fillbuffer with test packet.
240 *
241 * @param cls Closure (unused).
242 * @param size Buffer size.
243 * @param buf Buffer to fill.
244 * @return size of test packet.
245 */
246static size_t
247do_send (void *cls, size_t size, void *buf)
248{
249 struct GNUNET_MessageHeader *m = buf;
250
251 nth = NULL;
252 if (NULL == buf)
253 {
254 GNUNET_break (0);
255 result = GNUNET_SYSERR;
256 return 0;
257 }
258 m->size = htons (sizeof (struct GNUNET_MessageHeader) + DATA_SIZE);
259 m->type = htons (1);
260 memset (&m[1], 0, DATA_SIZE);
261 GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader) + DATA_SIZE);
262 return sizeof (struct GNUNET_MessageHeader) + DATA_SIZE;
263}
264
265/**
266 * Connect to other client and send data
267 *
268 * @param cls Closue (unused).
269 */
270static void
271do_connect (void *cls)
272{
273 struct GNUNET_PeerIdentity id;
274 size_t size = sizeof (struct GNUNET_MessageHeader) + DATA_SIZE;
275
276 connect_task = NULL;
277 GNUNET_TESTING_peer_get_identity (me, &id);
278 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONNECT BY PORT\n");
279 ch1 = GNUNET_CADET_channel_create (cadet, NULL, &id, GC_u2h (1),
280 GNUNET_CADET_OPTION_DEFAULT);
281 nth = GNUNET_CADET_notify_transmit_ready (ch1,
282 GNUNET_NO,
283 GNUNET_TIME_UNIT_FOREVER_REL,
284 size,
285 &do_send,
286 NULL);
287}
288
289
290/**
291 * Initialize framework and start test
292 *
293 * @param cls Closure (unused).
294 * @param cfg Configuration handle.
295 * @param peer Testing peer handle.
296 */
297static void
298run (void *cls,
299 const struct GNUNET_CONFIGURATION_Handle *cfg,
300 struct GNUNET_TESTING_Peer *peer)
301{
302 me = peer;
303 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
304 abort_task =
305 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
306 (GNUNET_TIME_UNIT_SECONDS, 15), &do_abort,
307 NULL);
308 cadet = GNUNET_CADET_connect (cfg, /* configuration */
309 (void *) 1L, /* cls */
310 &channel_end, /* inbound end hndlr */
311 handlers1); /* traffic handlers */
312 port = GNUNET_CADET_open_port (cadet,
313 GC_u2h (1),
314 &inbound_channel,
315 (void *) 1L);
316
317
318 if (NULL == cadet)
319 {
320 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
321 "Couldn't connect to cadet :(\n");
322 result = GNUNET_SYSERR;
323 return;
324 }
325 connect_task
326 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
327 &do_connect,
328 NULL);
329}
330
331
332/**
333 * Main
334 */
335int
336main (int argc,
337 char *argv[])
338{
339 result = GNUNET_NO;
340 if (0 != GNUNET_TESTING_peer_run ("test-cadet-local",
341 "test_cadet.conf",
342 &run, NULL))
343 {
344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
345 "run failed\n");
346 return 2;
347 }
348 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
349 "Final result: %d\n",
350 result);
351 return (result == GNUNET_OK) ? 0 : 1;
352}
353
354/* end of test_cadet_single.c */
diff --git a/src/datacache/Makefile.am b/src/datacache/Makefile.am
index 431b3179e..670a64926 100644
--- a/src/datacache/Makefile.am
+++ b/src/datacache/Makefile.am
@@ -53,6 +53,7 @@ libgnunet_plugin_datacache_sqlite_la_SOURCES = \
53 plugin_datacache_sqlite.c 53 plugin_datacache_sqlite.c
54libgnunet_plugin_datacache_sqlite_la_LIBADD = \ 54libgnunet_plugin_datacache_sqlite_la_LIBADD = \
55 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 55 $(top_builddir)/src/statistics/libgnunetstatistics.la \
56 $(top_builddir)/src/sq/libgnunetsq.la \
56 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ 57 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \
57 $(LTLIBINTL) 58 $(LTLIBINTL)
58libgnunet_plugin_datacache_sqlite_la_LDFLAGS = \ 59libgnunet_plugin_datacache_sqlite_la_LDFLAGS = \
diff --git a/src/datacache/plugin_datacache_sqlite.c b/src/datacache/plugin_datacache_sqlite.c
index 5567077d3..5cc48b26c 100644
--- a/src/datacache/plugin_datacache_sqlite.c
+++ b/src/datacache/plugin_datacache_sqlite.c
@@ -26,6 +26,7 @@
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_util_lib.h" 27#include "gnunet_util_lib.h"
28#include "gnunet_datacache_plugin.h" 28#include "gnunet_datacache_plugin.h"
29#include "gnunet_sq_lib.h"
29#include <sqlite3.h> 30#include <sqlite3.h>
30 31
31#define LOG(kind,...) GNUNET_log_from (kind, "datacache-sqlite", __VA_ARGS__) 32#define LOG(kind,...) GNUNET_log_from (kind, "datacache-sqlite", __VA_ARGS__)
@@ -60,6 +61,41 @@ struct Plugin
60 char *fn; 61 char *fn;
61 62
62 /** 63 /**
64 * Prepared statement for #sqlite_plugin_put.
65 */
66 sqlite3_stmt *insert_stmt;
67
68 /**
69 * Prepared statement for #sqlite_plugin_get.
70 */
71 sqlite3_stmt *get_count_stmt;
72
73 /**
74 * Prepared statement for #sqlite_plugin_get.
75 */
76 sqlite3_stmt *get_stmt;
77
78 /**
79 * Prepared statement for #sqlite_plugin_del.
80 */
81 sqlite3_stmt *del_select_stmt;
82
83 /**
84 * Prepared statement for #sqlite_plugin_del.
85 */
86 sqlite3_stmt *del_stmt;
87
88 /**
89 * Prepared statement for #sqlite_plugin_get_random.
90 */
91 sqlite3_stmt *get_random_stmt;
92
93 /**
94 * Prepared statement for #sqlite_plugin_get_closest.
95 */
96 sqlite3_stmt *get_closest_stmt;
97
98 /**
63 * Number of key-value pairs in the database. 99 * Number of key-value pairs in the database.
64 */ 100 */
65 unsigned int num_items; 101 unsigned int num_items;
@@ -132,60 +168,47 @@ sqlite_plugin_put (void *cls,
132 const struct GNUNET_PeerIdentity *path_info) 168 const struct GNUNET_PeerIdentity *path_info)
133{ 169{
134 struct Plugin *plugin = cls; 170 struct Plugin *plugin = cls;
135 sqlite3_stmt *stmt; 171 uint32_t type32 = type;
136 int64_t dval; 172 struct GNUNET_SQ_QueryParam params[] = {
173 GNUNET_SQ_query_param_uint32 (&type32),
174 GNUNET_SQ_query_param_absolute_time (&discard_time),
175 GNUNET_SQ_query_param_auto_from_type (key),
176 GNUNET_SQ_query_param_fixed_size (data, size),
177 GNUNET_SQ_query_param_fixed_size (path_info,
178 path_info_len * sizeof (struct GNUNET_PeerIdentity)),
179 GNUNET_SQ_query_param_end
180 };
137 181
138 LOG (GNUNET_ERROR_TYPE_DEBUG, 182 LOG (GNUNET_ERROR_TYPE_DEBUG,
139 "Processing PUT of %u bytes with key `%4s' and expiration %s\n", 183 "Processing PUT of %u bytes with key `%s' and expiration %s\n",
140 (unsigned int) size, 184 (unsigned int) size,
141 GNUNET_h2s (key), 185 GNUNET_h2s (key),
142 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (discard_time), GNUNET_YES)); 186 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (discard_time),
143 dval = (int64_t) discard_time.abs_value_us; 187 GNUNET_YES));
144 if (dval < 0) 188 if (GNUNET_OK !=
145 dval = INT64_MAX; 189 GNUNET_SQ_bind (plugin->insert_stmt,
146 if (sq_prepare 190 params))
147 (plugin->dbh,
148 "INSERT INTO ds090 (type, expire, key, value, path) VALUES (?, ?, ?, ?, ?)",
149 &stmt) != SQLITE_OK)
150 {
151 LOG_SQLITE (plugin->dbh,
152 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
153 "sq_prepare");
154 return -1;
155 }
156 if ((SQLITE_OK != sqlite3_bind_int (stmt, 1, type)) ||
157 (SQLITE_OK != sqlite3_bind_int64 (stmt, 2, dval)) ||
158 (SQLITE_OK !=
159 sqlite3_bind_blob (stmt, 3,
160 key, sizeof (struct GNUNET_HashCode),
161 SQLITE_TRANSIENT)) ||
162 (SQLITE_OK != sqlite3_bind_blob (stmt, 4,
163 data, size,
164 SQLITE_TRANSIENT)) ||
165 (SQLITE_OK != sqlite3_bind_blob (stmt, 5,
166 path_info,
167 path_info_len * sizeof (struct GNUNET_PeerIdentity),
168 SQLITE_TRANSIENT)))
169 { 191 {
170 LOG_SQLITE (plugin->dbh, 192 LOG_SQLITE (plugin->dbh,
171 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 193 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
172 "sqlite3_bind_xxx"); 194 "sqlite3_bind_xxx");
173 sqlite3_finalize (stmt); 195 GNUNET_SQ_reset (plugin->dbh,
196 plugin->insert_stmt);
174 return -1; 197 return -1;
175 } 198 }
176 if (SQLITE_DONE != sqlite3_step (stmt)) 199 if (SQLITE_DONE !=
200 sqlite3_step (plugin->insert_stmt))
177 { 201 {
178 LOG_SQLITE (plugin->dbh, 202 LOG_SQLITE (plugin->dbh,
179 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 203 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
180 "sqlite3_step"); 204 "sqlite3_step");
181 sqlite3_finalize (stmt); 205 GNUNET_SQ_reset (plugin->dbh,
206 plugin->insert_stmt);
182 return -1; 207 return -1;
183 } 208 }
184 plugin->num_items++; 209 plugin->num_items++;
185 if (SQLITE_OK != sqlite3_finalize (stmt)) 210 GNUNET_SQ_reset (plugin->dbh,
186 LOG_SQLITE (plugin->dbh, 211 plugin->insert_stmt);
187 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
188 "sqlite3_finalize");
189 return size + OVERHEAD; 212 return size + OVERHEAD;
190} 213}
191 214
@@ -209,120 +232,119 @@ sqlite_plugin_get (void *cls,
209 void *iter_cls) 232 void *iter_cls)
210{ 233{
211 struct Plugin *plugin = cls; 234 struct Plugin *plugin = cls;
212 sqlite3_stmt *stmt; 235 uint32_t type32 = type;
213 struct GNUNET_TIME_Absolute now; 236 struct GNUNET_TIME_Absolute now;
214 struct GNUNET_TIME_Absolute exp; 237 struct GNUNET_TIME_Absolute exp;
215 unsigned int size; 238 size_t size;
216 const char *dat; 239 void *dat;
217 unsigned int cnt; 240 unsigned int cnt;
218 unsigned int off; 241 uint32_t off;
219 unsigned int total; 242 unsigned int total;
220 unsigned int psize; 243 size_t psize;
221 char scratch[256]; 244 struct GNUNET_PeerIdentity *path;
222 int64_t ntime; 245 struct GNUNET_SQ_QueryParam params_count[] = {
223 const struct GNUNET_PeerIdentity *path; 246 GNUNET_SQ_query_param_auto_from_type (key),
247 GNUNET_SQ_query_param_uint32 (&type32),
248 GNUNET_SQ_query_param_absolute_time (&now),
249 GNUNET_SQ_query_param_end
250 };
251 struct GNUNET_SQ_QueryParam params_select[] = {
252 GNUNET_SQ_query_param_auto_from_type (key),
253 GNUNET_SQ_query_param_uint32 (&type32),
254 GNUNET_SQ_query_param_absolute_time (&now),
255 GNUNET_SQ_query_param_uint32 (&off),
256 GNUNET_SQ_query_param_end
257 };
258 struct GNUNET_SQ_ResultSpec rs[] = {
259 GNUNET_SQ_result_spec_variable_size (&dat,
260 &size),
261 GNUNET_SQ_result_spec_absolute_time (&exp),
262 GNUNET_SQ_result_spec_variable_size ((void **) &path,
263 &psize),
264 GNUNET_SQ_result_spec_end
265 };
224 266
225 now = GNUNET_TIME_absolute_get (); 267 now = GNUNET_TIME_absolute_get ();
226 LOG (GNUNET_ERROR_TYPE_DEBUG, 268 LOG (GNUNET_ERROR_TYPE_DEBUG,
227 "Processing GET for key `%4s'\n", 269 "Processing GET for key `%s'\n",
228 GNUNET_h2s (key)); 270 GNUNET_h2s (key));
229 if (sq_prepare 271
230 (plugin->dbh, 272 if (GNUNET_OK !=
231 "SELECT count(*) FROM ds090 WHERE key=? AND type=? AND expire >= ?", 273 GNUNET_SQ_bind (plugin->get_count_stmt,
232 &stmt) != SQLITE_OK) 274 params_count))
233 {
234 LOG_SQLITE (plugin->dbh,
235 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
236 "sq_prepare");
237 return 0;
238 }
239 ntime = (int64_t) now.abs_value_us;
240 GNUNET_assert (ntime >= 0);
241 if ((SQLITE_OK !=
242 sqlite3_bind_blob (stmt, 1, key, sizeof (struct GNUNET_HashCode),
243 SQLITE_TRANSIENT)) ||
244 (SQLITE_OK != sqlite3_bind_int (stmt, 2, type)) ||
245 (SQLITE_OK != sqlite3_bind_int64 (stmt, 3, now.abs_value_us)))
246 { 275 {
247 LOG_SQLITE (plugin->dbh, 276 LOG_SQLITE (plugin->dbh,
248 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 277 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
249 "sqlite3_bind_xxx"); 278 "sqlite3_bind_xxx");
250 sqlite3_finalize (stmt); 279 GNUNET_SQ_reset (plugin->dbh,
280 plugin->get_count_stmt);
251 return 0; 281 return 0;
252 } 282 }
253 283 if (SQLITE_ROW !=
254 if (SQLITE_ROW != sqlite3_step (stmt)) 284 sqlite3_step (plugin->get_count_stmt))
255 { 285 {
256 LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 286 LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
257 "sqlite_step"); 287 "sqlite_step");
258 sqlite3_finalize (stmt); 288 GNUNET_SQ_reset (plugin->dbh,
289 plugin->get_count_stmt);
259 LOG (GNUNET_ERROR_TYPE_DEBUG, 290 LOG (GNUNET_ERROR_TYPE_DEBUG,
260 "No content found when processing GET for key `%4s'\n", 291 "No content found when processing GET for key `%s'\n",
261 GNUNET_h2s (key)); 292 GNUNET_h2s (key));
262 return 0; 293 return 0;
263 } 294 }
264 total = sqlite3_column_int (stmt, 0); 295 total = sqlite3_column_int (plugin->get_count_stmt,
265 sqlite3_finalize (stmt); 296 0);
266 if ((0 == total) || (NULL == iter)) 297 GNUNET_SQ_reset (plugin->dbh,
298 plugin->get_count_stmt);
299 if ( (0 == total) ||
300 (NULL == iter) )
267 { 301 {
268 if (0 == total) 302 if (0 == total)
269 LOG (GNUNET_ERROR_TYPE_DEBUG, 303 LOG (GNUNET_ERROR_TYPE_DEBUG,
270 "No content found when processing GET for key `%4s'\n", 304 "No content found when processing GET for key `%s'\n",
271 GNUNET_h2s (key)); 305 GNUNET_h2s (key));
272 return total; 306 return total;
273 } 307 }
274 308
275 cnt = 0; 309 cnt = 0;
276 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total); 310 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
311 total);
277 while (cnt < total) 312 while (cnt < total)
278 { 313 {
279 off = (off + 1) % total; 314 off = (off + 1) % total;
280 GNUNET_snprintf (scratch, sizeof (scratch), 315 if (GNUNET_OK !=
281 "SELECT value,expire,path FROM ds090 WHERE key=? AND type=? AND expire >= ? LIMIT 1 OFFSET %u", 316 GNUNET_SQ_bind (plugin->get_stmt,
282 off); 317 params_select))
283 if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK)
284 {
285 LOG_SQLITE (plugin->dbh,
286 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
287 "sq_prepare");
288 return cnt;
289 }
290 if ((SQLITE_OK !=
291 sqlite3_bind_blob (stmt, 1,
292 key,
293 sizeof (struct GNUNET_HashCode),
294 SQLITE_TRANSIENT)) ||
295 (SQLITE_OK != sqlite3_bind_int (stmt, 2, type)) ||
296 (SQLITE_OK != sqlite3_bind_int64 (stmt, 3, now.abs_value_us)))
297 { 318 {
298 LOG_SQLITE (plugin->dbh, 319 LOG_SQLITE (plugin->dbh,
299 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 320 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
300 "sqlite3_bind_xxx"); 321 "sqlite3_bind_xxx");
301 sqlite3_finalize (stmt); 322 GNUNET_SQ_reset (plugin->dbh,
323 plugin->get_stmt);
302 return cnt; 324 return cnt;
303 } 325 }
304 if (sqlite3_step (stmt) != SQLITE_ROW) 326 if (SQLITE_ROW !=
327 sqlite3_step (plugin->get_stmt))
305 break; 328 break;
306 size = sqlite3_column_bytes (stmt, 0); 329 if (GNUNET_OK !=
307 dat = sqlite3_column_blob (stmt, 0); 330 GNUNET_SQ_extract_result (plugin->get_stmt,
308 exp.abs_value_us = sqlite3_column_int64 (stmt, 1); 331 rs))
309 psize = sqlite3_column_bytes (stmt, 2); 332 {
333 GNUNET_break (0);
334 GNUNET_SQ_reset (plugin->dbh,
335 plugin->get_stmt);
336 break;
337 }
310 if (0 != psize % sizeof (struct GNUNET_PeerIdentity)) 338 if (0 != psize % sizeof (struct GNUNET_PeerIdentity))
311 { 339 {
312 GNUNET_break (0); 340 GNUNET_break (0);
313 psize = 0; 341 psize = 0;
342 path = NULL;
314 } 343 }
315 psize /= sizeof (struct GNUNET_PeerIdentity); 344 psize /= sizeof (struct GNUNET_PeerIdentity);
316 if (0 != psize)
317 path = sqlite3_column_blob (stmt, 2);
318 else
319 path = NULL;
320 ntime = (int64_t) exp.abs_value_us;
321 if (ntime == INT64_MAX)
322 exp = GNUNET_TIME_UNIT_FOREVER_ABS;
323 cnt++; 345 cnt++;
324 LOG (GNUNET_ERROR_TYPE_DEBUG, 346 LOG (GNUNET_ERROR_TYPE_DEBUG,
325 "Found %u-byte result when processing GET for key `%4s'\n", 347 "Found %u-byte result when processing GET for key `%s'\n",
326 (unsigned int) size, 348 (unsigned int) size,
327 GNUNET_h2s (key)); 349 GNUNET_h2s (key));
328 if (GNUNET_OK != iter (iter_cls, 350 if (GNUNET_OK != iter (iter_cls,
@@ -334,11 +356,17 @@ sqlite_plugin_get (void *cls,
334 psize, 356 psize,
335 path)) 357 path))
336 { 358 {
337 sqlite3_finalize (stmt); 359 GNUNET_SQ_cleanup_result (rs);
360 GNUNET_SQ_reset (plugin->dbh,
361 plugin->get_stmt);
338 break; 362 break;
339 } 363 }
340 sqlite3_finalize (stmt); 364 GNUNET_SQ_cleanup_result (rs);
365 GNUNET_SQ_reset (plugin->dbh,
366 plugin->get_stmt);
341 } 367 }
368 GNUNET_SQ_reset (plugin->dbh,
369 plugin->get_stmt);
342 return cnt; 370 return cnt;
343} 371}
344 372
@@ -354,79 +382,73 @@ static int
354sqlite_plugin_del (void *cls) 382sqlite_plugin_del (void *cls)
355{ 383{
356 struct Plugin *plugin = cls; 384 struct Plugin *plugin = cls;
357 unsigned long long rowid; 385 uint64_t rowid;
358 unsigned int dsize; 386 void *data;
359 sqlite3_stmt *stmt; 387 size_t dsize;
360 sqlite3_stmt *dstmt;
361 struct GNUNET_HashCode hc; 388 struct GNUNET_HashCode hc;
389 struct GNUNET_SQ_ResultSpec rs[] = {
390 GNUNET_SQ_result_spec_uint64 (&rowid),
391 GNUNET_SQ_result_spec_auto_from_type (&hc),
392 GNUNET_SQ_result_spec_variable_size ((void **) &data,
393 &dsize),
394 GNUNET_SQ_result_spec_end
395 };
396 struct GNUNET_SQ_QueryParam params[] = {
397 GNUNET_SQ_query_param_uint64 (&rowid),
398 GNUNET_SQ_query_param_end
399 };
362 400
363 LOG (GNUNET_ERROR_TYPE_DEBUG, 401 LOG (GNUNET_ERROR_TYPE_DEBUG,
364 "Processing DEL\n"); 402 "Processing DEL\n");
365 stmt = NULL; 403 if (SQLITE_ROW !=
366 dstmt = NULL; 404 sqlite3_step (plugin->del_select_stmt))
367 if (SQLITE_OK !=
368 sq_prepare (plugin->dbh,
369 "SELECT _ROWID_,key,value FROM ds090 ORDER BY expire ASC LIMIT 1",
370 &stmt))
371 {
372 LOG_SQLITE (plugin->dbh,
373 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
374 "sq_prepare");
375 if (stmt != NULL)
376 (void) sqlite3_finalize (stmt);
377 return GNUNET_SYSERR;
378 }
379 if (SQLITE_ROW != sqlite3_step (stmt))
380 { 405 {
381 LOG_SQLITE (plugin->dbh, 406 LOG_SQLITE (plugin->dbh,
382 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 407 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
383 "sqlite3_step"); 408 "sqlite3_step");
384 (void) sqlite3_finalize (stmt); 409 GNUNET_SQ_reset (plugin->dbh,
410 plugin->del_select_stmt);
385 return GNUNET_SYSERR; 411 return GNUNET_SYSERR;
386 } 412 }
387 rowid = sqlite3_column_int64 (stmt, 0); 413 if (GNUNET_OK !=
388 GNUNET_assert (sqlite3_column_bytes (stmt, 1) == sizeof (struct GNUNET_HashCode)); 414 GNUNET_SQ_extract_result (plugin->del_select_stmt,
389 GNUNET_memcpy (&hc, sqlite3_column_blob (stmt, 1), sizeof (struct GNUNET_HashCode)); 415 rs))
390 dsize = sqlite3_column_bytes (stmt, 2);
391 if (SQLITE_OK != sqlite3_finalize (stmt))
392 LOG_SQLITE (plugin->dbh,
393 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
394 "sqlite3_step");
395 if (SQLITE_OK !=
396 sq_prepare (plugin->dbh,
397 "DELETE FROM ds090 WHERE _ROWID_=?", &dstmt))
398 { 416 {
399 LOG_SQLITE (plugin->dbh, 417 GNUNET_break (0);
400 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 418 GNUNET_SQ_reset (plugin->dbh,
401 "sq_prepare"); 419 plugin->del_select_stmt);
402 if (stmt != NULL)
403 (void) sqlite3_finalize (stmt);
404 return GNUNET_SYSERR; 420 return GNUNET_SYSERR;
405 } 421 }
406 if (SQLITE_OK != sqlite3_bind_int64 (dstmt, 1, rowid)) 422 GNUNET_SQ_cleanup_result (rs);
423 GNUNET_SQ_reset (plugin->dbh,
424 plugin->del_select_stmt);
425 if (GNUNET_OK !=
426 GNUNET_SQ_bind (plugin->del_stmt,
427 params))
407 { 428 {
408 LOG_SQLITE (plugin->dbh, 429 LOG_SQLITE (plugin->dbh,
409 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 430 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
410 "sqlite3_bind"); 431 "sqlite3_bind");
411 (void) sqlite3_finalize (dstmt); 432 GNUNET_SQ_reset (plugin->dbh,
433 plugin->del_stmt);
412 return GNUNET_SYSERR; 434 return GNUNET_SYSERR;
413 } 435 }
414 if (SQLITE_DONE != sqlite3_step (dstmt)) 436 if (SQLITE_DONE !=
437 sqlite3_step (plugin->del_stmt))
415 { 438 {
416 LOG_SQLITE (plugin->dbh, 439 LOG_SQLITE (plugin->dbh,
417 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 440 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
418 "sqlite3_step"); 441 "sqlite3_step");
419 (void) sqlite3_finalize (dstmt); 442 GNUNET_SQ_reset (plugin->dbh,
443 plugin->del_stmt);
420 return GNUNET_SYSERR; 444 return GNUNET_SYSERR;
421 } 445 }
422 plugin->num_items--; 446 plugin->num_items--;
423 plugin->env->delete_notify (plugin->env->cls, 447 plugin->env->delete_notify (plugin->env->cls,
424 &hc, 448 &hc,
425 dsize + OVERHEAD); 449 dsize + OVERHEAD);
426 if (SQLITE_OK != sqlite3_finalize (dstmt)) 450 GNUNET_SQ_reset (plugin->dbh,
427 LOG_SQLITE (plugin->dbh, 451 plugin->del_stmt);
428 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
429 "sqlite3_finalize");
430 return GNUNET_OK; 452 return GNUNET_OK;
431} 453}
432 454
@@ -445,17 +467,28 @@ sqlite_plugin_get_random (void *cls,
445 void *iter_cls) 467 void *iter_cls)
446{ 468{
447 struct Plugin *plugin = cls; 469 struct Plugin *plugin = cls;
448 sqlite3_stmt *stmt;
449 struct GNUNET_TIME_Absolute exp; 470 struct GNUNET_TIME_Absolute exp;
450 unsigned int size; 471 size_t size;
451 const char *dat; 472 void *dat;
452 unsigned int off; 473 uint32_t off;
453 unsigned int psize; 474 size_t psize;
454 unsigned int type; 475 uint32_t type;
455 char scratch[256]; 476 struct GNUNET_PeerIdentity *path;
456 int64_t ntime; 477 struct GNUNET_HashCode key;
457 const struct GNUNET_PeerIdentity *path; 478 struct GNUNET_SQ_QueryParam params[] = {
458 const struct GNUNET_HashCode *key; 479 GNUNET_SQ_query_param_uint32 (&off),
480 GNUNET_SQ_query_param_end
481 };
482 struct GNUNET_SQ_ResultSpec rs[] = {
483 GNUNET_SQ_result_spec_variable_size (&dat,
484 &size),
485 GNUNET_SQ_result_spec_absolute_time (&exp),
486 GNUNET_SQ_result_spec_variable_size ((void **) &path,
487 &psize),
488 GNUNET_SQ_result_spec_auto_from_type (&key),
489 GNUNET_SQ_result_spec_uint32 (&type),
490 GNUNET_SQ_result_spec_end
491 };
459 492
460 if (0 == plugin->num_items) 493 if (0 == plugin->num_items)
461 return 0; 494 return 0;
@@ -463,60 +496,51 @@ sqlite_plugin_get_random (void *cls,
463 return 1; 496 return 1;
464 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, 497 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
465 plugin->num_items); 498 plugin->num_items);
466 GNUNET_snprintf (scratch, 499 if (GNUNET_OK !=
467 sizeof (scratch), 500 GNUNET_SQ_bind (plugin->get_random_stmt,
468 "SELECT value,expire,path,key,type FROM ds090 ORDER BY key LIMIT 1 OFFSET %u", 501 params))
469 off);
470 if (SQLITE_OK !=
471 sq_prepare (plugin->dbh, scratch, &stmt))
472 { 502 {
473 LOG_SQLITE (plugin->dbh,
474 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
475 "sq_prepare");
476 return 0; 503 return 0;
477 } 504 }
478 if (SQLITE_ROW != sqlite3_step (stmt)) 505 if (SQLITE_ROW !=
506 sqlite3_step (plugin->get_random_stmt))
507 {
508 GNUNET_break (0);
509 GNUNET_SQ_reset (plugin->dbh,
510 plugin->get_random_stmt);
511 return 0;
512 }
513 if (GNUNET_OK !=
514 GNUNET_SQ_extract_result (plugin->get_random_stmt,
515 rs))
479 { 516 {
480 GNUNET_break (0); 517 GNUNET_break (0);
481 sqlite3_finalize (stmt); 518 GNUNET_SQ_reset (plugin->dbh,
519 plugin->get_random_stmt);
482 return 0; 520 return 0;
483 } 521 }
484 size = sqlite3_column_bytes (stmt, 0);
485 dat = sqlite3_column_blob (stmt, 0);
486 exp.abs_value_us = sqlite3_column_int64 (stmt, 1);
487 psize = sqlite3_column_bytes (stmt, 2);
488 if (0 != psize % sizeof (struct GNUNET_PeerIdentity)) 522 if (0 != psize % sizeof (struct GNUNET_PeerIdentity))
489 { 523 {
490 GNUNET_break (0); 524 GNUNET_break (0);
491 psize = 0; 525 psize = 0;
526 path = NULL;
492 } 527 }
493 psize /= sizeof (struct GNUNET_PeerIdentity); 528 psize /= sizeof (struct GNUNET_PeerIdentity);
494 if (0 != psize)
495 path = sqlite3_column_blob (stmt, 2);
496 else
497 path = NULL;
498
499 GNUNET_assert (sizeof (struct GNUNET_HashCode) ==
500 sqlite3_column_bytes (stmt, 3));
501 key = sqlite3_column_blob (stmt, 3);
502 type = sqlite3_column_int (stmt, 4);
503
504 ntime = (int64_t) exp.abs_value_us;
505 if (ntime == INT64_MAX)
506 exp = GNUNET_TIME_UNIT_FOREVER_ABS;
507 LOG (GNUNET_ERROR_TYPE_DEBUG, 529 LOG (GNUNET_ERROR_TYPE_DEBUG,
508 "Found %u-byte result with key %s when processing GET-RANDOM\n", 530 "Found %u-byte result with key %s when processing GET-RANDOM\n",
509 (unsigned int) size, 531 (unsigned int) size,
510 GNUNET_h2s (key)); 532 GNUNET_h2s (&key));
511 (void) iter (iter_cls, 533 (void) iter (iter_cls,
512 key, 534 &key,
513 size, 535 size,
514 dat, 536 dat,
515 type, 537 (enum GNUNET_BLOCK_Type) type,
516 exp, 538 exp,
517 psize, 539 psize,
518 path); 540 path);
519 sqlite3_finalize (stmt); 541 GNUNET_SQ_cleanup_result (rs);
542 GNUNET_SQ_reset (plugin->dbh,
543 plugin->get_random_stmt);
520 return 1; 544 return 1;
521} 545}
522 546
@@ -542,83 +566,73 @@ sqlite_plugin_get_closest (void *cls,
542 void *iter_cls) 566 void *iter_cls)
543{ 567{
544 struct Plugin *plugin = cls; 568 struct Plugin *plugin = cls;
545 sqlite3_stmt *stmt; 569 uint32_t num_results32 = num_results;
546 struct GNUNET_TIME_Absolute now; 570 struct GNUNET_TIME_Absolute now;
547 struct GNUNET_TIME_Absolute exp; 571 struct GNUNET_TIME_Absolute exp;
548 unsigned int size; 572 size_t size;
549 const char *dat; 573 void *dat;
550 unsigned int cnt; 574 unsigned int cnt;
551 unsigned int psize; 575 size_t psize;
552 unsigned int type; 576 uint32_t type;
553 int64_t ntime; 577 struct GNUNET_HashCode hc;
554 const struct GNUNET_PeerIdentity *path; 578 struct GNUNET_PeerIdentity *path;
579 struct GNUNET_SQ_QueryParam params[] = {
580 GNUNET_SQ_query_param_auto_from_type (key),
581 GNUNET_SQ_query_param_absolute_time (&now),
582 GNUNET_SQ_query_param_uint32 (&num_results32),
583 GNUNET_SQ_query_param_end
584 };
585 struct GNUNET_SQ_ResultSpec rs[] = {
586 GNUNET_SQ_result_spec_variable_size (&dat,
587 &size),
588 GNUNET_SQ_result_spec_absolute_time (&exp),
589 GNUNET_SQ_result_spec_variable_size ((void **) &path,
590 &psize),
591 GNUNET_SQ_result_spec_uint32 (&type),
592 GNUNET_SQ_result_spec_auto_from_type (&hc),
593 GNUNET_SQ_result_spec_end
594 };
555 595
556 now = GNUNET_TIME_absolute_get (); 596 now = GNUNET_TIME_absolute_get ();
557 LOG (GNUNET_ERROR_TYPE_DEBUG, 597 LOG (GNUNET_ERROR_TYPE_DEBUG,
558 "Processing GET_CLOSEST for key `%4s'\n", 598 "Processing GET_CLOSEST for key `%s'\n",
559 GNUNET_h2s (key)); 599 GNUNET_h2s (key));
560 if (SQLITE_OK != 600 if (GNUNET_OK !=
561 sq_prepare (plugin->dbh, 601 GNUNET_SQ_bind (plugin->get_closest_stmt,
562 "SELECT value,expire,path,type,key FROM ds090 WHERE key>=? AND expire >= ? ORDER BY KEY ASC LIMIT ?", 602 params))
563 &stmt))
564 {
565 LOG_SQLITE (plugin->dbh,
566 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
567 "sq_prepare");
568 return 0;
569 }
570 ntime = (int64_t) now.abs_value_us;
571 GNUNET_assert (ntime >= 0);
572 if ((SQLITE_OK !=
573 sqlite3_bind_blob (stmt,
574 1,
575 key,
576 sizeof (struct GNUNET_HashCode),
577 SQLITE_TRANSIENT)) ||
578 (SQLITE_OK != sqlite3_bind_int64 (stmt, 2, now.abs_value_us)) ||
579 (SQLITE_OK != sqlite3_bind_int (stmt, 3, num_results)) )
580 { 603 {
581 LOG_SQLITE (plugin->dbh, 604 LOG_SQLITE (plugin->dbh,
582 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 605 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
583 "sqlite3_bind_xxx"); 606 "sqlite3_bind_xxx");
584 sqlite3_finalize (stmt); 607 GNUNET_SQ_reset (plugin->dbh,
608 plugin->get_closest_stmt);
585 return 0; 609 return 0;
586 } 610 }
587 cnt = 0; 611 cnt = 0;
588 while (SQLITE_ROW == sqlite3_step (stmt)) 612 while (SQLITE_ROW ==
613 sqlite3_step (plugin->get_closest_stmt))
589 { 614 {
590 if (sizeof (struct GNUNET_HashCode) != 615 if (GNUNET_OK !=
591 sqlite3_column_bytes (stmt, 4)) 616 GNUNET_SQ_extract_result (plugin->get_closest_stmt,
617 rs))
592 { 618 {
593 GNUNET_break (0); 619 GNUNET_break (0);
594 break; 620 break;
595 } 621 }
596 size = sqlite3_column_bytes (stmt, 0);
597 dat = sqlite3_column_blob (stmt, 0);
598 exp.abs_value_us = sqlite3_column_int64 (stmt, 1);
599 psize = sqlite3_column_bytes (stmt, 2);
600 type = sqlite3_column_int (stmt, 3);
601 key = sqlite3_column_blob (stmt, 4);
602 if (0 != psize % sizeof (struct GNUNET_PeerIdentity)) 622 if (0 != psize % sizeof (struct GNUNET_PeerIdentity))
603 { 623 {
604 GNUNET_break (0); 624 GNUNET_break (0);
605 psize = 0; 625 psize = 0;
626 path = NULL;
606 } 627 }
607 psize /= sizeof (struct GNUNET_PeerIdentity); 628 psize /= sizeof (struct GNUNET_PeerIdentity);
608 if (0 != psize)
609 path = sqlite3_column_blob (stmt, 2);
610 else
611 path = NULL;
612 ntime = (int64_t) exp.abs_value_us;
613 if (ntime == INT64_MAX)
614 exp = GNUNET_TIME_UNIT_FOREVER_ABS;
615 cnt++; 629 cnt++;
616 LOG (GNUNET_ERROR_TYPE_DEBUG, 630 LOG (GNUNET_ERROR_TYPE_DEBUG,
617 "Found %u-byte result at %s when processing GET_CLOSE\n", 631 "Found %u-byte result at %s when processing GET_CLOSE\n",
618 (unsigned int) size, 632 (unsigned int) size,
619 GNUNET_h2s (key)); 633 GNUNET_h2s (&hc));
620 if (GNUNET_OK != iter (iter_cls, 634 if (GNUNET_OK != iter (iter_cls,
621 key, 635 &hc,
622 size, 636 size,
623 dat, 637 dat,
624 type, 638 type,
@@ -626,11 +640,13 @@ sqlite_plugin_get_closest (void *cls,
626 psize, 640 psize,
627 path)) 641 path))
628 { 642 {
629 sqlite3_finalize (stmt); 643 GNUNET_SQ_cleanup_result (rs);
630 break; 644 break;
631 } 645 }
646 GNUNET_SQ_cleanup_result (rs);
632 } 647 }
633 sqlite3_finalize (stmt); 648 GNUNET_SQ_reset (plugin->dbh,
649 plugin->get_closest_stmt);
634 return cnt; 650 return cnt;
635} 651}
636 652
@@ -703,6 +719,50 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
703 plugin->env = env; 719 plugin->env = env;
704 plugin->dbh = dbh; 720 plugin->dbh = dbh;
705 plugin->fn = fn_utf8; 721 plugin->fn = fn_utf8;
722
723 if ( (SQLITE_OK !=
724 sq_prepare (plugin->dbh,
725 "INSERT INTO ds090 (type, expire, key, value, path) "
726 "VALUES (?, ?, ?, ?, ?)",
727 &plugin->insert_stmt)) ||
728 (SQLITE_OK !=
729 sq_prepare (plugin->dbh,
730 "SELECT count(*) FROM ds090 "
731 "WHERE key=? AND type=? AND expire >= ?",
732 &plugin->get_count_stmt)) ||
733 (SQLITE_OK !=
734 sq_prepare (plugin->dbh,
735 "SELECT value,expire,path FROM ds090 "
736 "WHERE key=? AND type=? AND expire >= ? LIMIT 1 OFFSET ?",
737 &plugin->get_stmt)) ||
738 (SQLITE_OK !=
739 sq_prepare (plugin->dbh,
740 "SELECT _ROWID_,key,value FROM ds090 ORDER BY expire ASC LIMIT 1",
741 &plugin->del_select_stmt)) ||
742 (SQLITE_OK !=
743 sq_prepare (plugin->dbh,
744 "DELETE FROM ds090 WHERE _ROWID_=?",
745 &plugin->del_stmt)) ||
746 (SQLITE_OK !=
747 sq_prepare (plugin->dbh,
748 "SELECT value,expire,path,key,type FROM ds090 "
749 "ORDER BY key LIMIT 1 OFFSET ?",
750 &plugin->get_random_stmt)) ||
751 (SQLITE_OK !=
752 sq_prepare (plugin->dbh,
753 "SELECT value,expire,path,type,key FROM ds090 "
754 "WHERE key>=? AND expire >= ? ORDER BY KEY ASC LIMIT ?",
755 &plugin->get_closest_stmt))
756 )
757 {
758 LOG_SQLITE (plugin->dbh,
759 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
760 "sq_prepare");
761 (void) sqlite3_close (plugin->dbh);
762 GNUNET_free (plugin);
763 return NULL;
764 }
765
706 api = GNUNET_new (struct GNUNET_DATACACHE_PluginFunctions); 766 api = GNUNET_new (struct GNUNET_DATACACHE_PluginFunctions);
707 api->cls = plugin; 767 api->cls = plugin;
708 api->get = &sqlite_plugin_get; 768 api->get = &sqlite_plugin_get;
@@ -741,6 +801,13 @@ libgnunet_plugin_datacache_sqlite_done (void *cls)
741 plugin->fn); 801 plugin->fn);
742 GNUNET_free_non_null (plugin->fn); 802 GNUNET_free_non_null (plugin->fn);
743#endif 803#endif
804 sqlite3_finalize (plugin->insert_stmt);
805 sqlite3_finalize (plugin->get_count_stmt);
806 sqlite3_finalize (plugin->get_stmt);
807 sqlite3_finalize (plugin->del_select_stmt);
808 sqlite3_finalize (plugin->del_stmt);
809 sqlite3_finalize (plugin->get_random_stmt);
810 sqlite3_finalize (plugin->get_closest_stmt);
744 result = sqlite3_close (plugin->dbh); 811 result = sqlite3_close (plugin->dbh);
745#if SQLITE_VERSION_NUMBER >= 3007000 812#if SQLITE_VERSION_NUMBER >= 3007000
746 if (SQLITE_BUSY == result) 813 if (SQLITE_BUSY == result)
diff --git a/src/datastore/plugin_datastore_sqlite.c b/src/datastore/plugin_datastore_sqlite.c
index 9c67d242e..491f73ed5 100644
--- a/src/datastore/plugin_datastore_sqlite.c
+++ b/src/datastore/plugin_datastore_sqlite.c
@@ -128,6 +128,46 @@ struct Plugin
128 sqlite3_stmt *insertContent; 128 sqlite3_stmt *insertContent;
129 129
130 /** 130 /**
131 * Precompiled SQL for selection
132 */
133 sqlite3_stmt *count_key;
134
135 /**
136 * Precompiled SQL for selection
137 */
138 sqlite3_stmt *count_key_vhash;
139
140 /**
141 * Precompiled SQL for selection
142 */
143 sqlite3_stmt *count_key_type;
144
145 /**
146 * Precompiled SQL for selection
147 */
148 sqlite3_stmt *count_key_vhash_type;
149
150 /**
151 * Precompiled SQL for selection
152 */
153 sqlite3_stmt *get_key;
154
155 /**
156 * Precompiled SQL for selection
157 */
158 sqlite3_stmt *get_key_vhash;
159
160 /**
161 * Precompiled SQL for selection
162 */
163 sqlite3_stmt *get_key_type;
164
165 /**
166 * Precompiled SQL for selection
167 */
168 sqlite3_stmt *get_key_vhash_type;
169
170 /**
131 * Should the database be dropped on shutdown? 171 * Should the database be dropped on shutdown?
132 */ 172 */
133 int drop_on_shutdown; 173 int drop_on_shutdown;
@@ -151,11 +191,17 @@ sq_prepare (sqlite3 *dbh,
151 char *dummy; 191 char *dummy;
152 int result; 192 int result;
153 193
154 result = 194 result = sqlite3_prepare_v2 (dbh,
155 sqlite3_prepare_v2 (dbh, zSql, strlen (zSql), ppStmt, 195 zSql,
156 (const char **) &dummy); 196 strlen (zSql),
157 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", 197 ppStmt,
158 "Prepared `%s' / %p: %d\n", zSql, *ppStmt, result); 198 (const char **) &dummy);
199 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
200 "sqlite",
201 "Prepared `%s' / %p: %d\n",
202 zSql,
203 *ppStmt,
204 result);
159 return result; 205 return result;
160} 206}
161 207
@@ -311,80 +357,134 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg,
311 * we do math or inequality tests, so we can't handle the entire range of uint32_t. 357 * we do math or inequality tests, so we can't handle the entire range of uint32_t.
312 * This will also cause problems for expiration times after 294247-01-10-04:00:54 UTC. 358 * This will also cause problems for expiration times after 294247-01-10-04:00:54 UTC.
313 */ 359 */
314 if ((sqlite3_step (stmt) == SQLITE_DONE) && 360 if ( (SQLITE_DONE ==
315 (sqlite3_exec 361 sqlite3_step (stmt)) &&
316 (plugin->dbh, 362 (SQLITE_OK !=
317 "CREATE TABLE gn090 (" " repl INT4 NOT NULL DEFAULT 0," 363 sqlite3_exec (plugin->dbh,
318 " type INT4 NOT NULL DEFAULT 0," " prio INT4 NOT NULL DEFAULT 0," 364 "CREATE TABLE gn090 (" " repl INT4 NOT NULL DEFAULT 0,"
319 " anonLevel INT4 NOT NULL DEFAULT 0," 365 " type INT4 NOT NULL DEFAULT 0," " prio INT4 NOT NULL DEFAULT 0,"
320 " expire INT8 NOT NULL DEFAULT 0," " rvalue INT8 NOT NULL," 366 " anonLevel INT4 NOT NULL DEFAULT 0,"
321 " hash TEXT NOT NULL DEFAULT ''," " vhash TEXT NOT NULL DEFAULT ''," 367 " expire INT8 NOT NULL DEFAULT 0," " rvalue INT8 NOT NULL,"
322 " value BLOB NOT NULL DEFAULT '')", NULL, NULL, NULL) != SQLITE_OK)) 368 " hash TEXT NOT NULL DEFAULT ''," " vhash TEXT NOT NULL DEFAULT '',"
369 " value BLOB NOT NULL DEFAULT '')",
370 NULL,
371 NULL,
372 NULL)) )
323 { 373 {
324 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec"); 374 LOG_SQLITE (plugin,
375 GNUNET_ERROR_TYPE_ERROR,
376 "sqlite3_exec");
325 sqlite3_finalize (stmt); 377 sqlite3_finalize (stmt);
326 return GNUNET_SYSERR; 378 return GNUNET_SYSERR;
327 } 379 }
328 sqlite3_finalize (stmt); 380 sqlite3_finalize (stmt);
329 create_indices (plugin->dbh); 381 create_indices (plugin->dbh);
330 382
331 if ((sq_prepare 383 if ( (SQLITE_OK !=
332 (plugin->dbh, 384 sq_prepare (plugin->dbh,
333 "UPDATE gn090 " 385 "UPDATE gn090 "
334 "SET prio = prio + ?, expire = MAX(expire,?) WHERE _ROWID_ = ?", 386 "SET prio = prio + ?, expire = MAX(expire,?) WHERE _ROWID_ = ?",
335 &plugin->updPrio) != SQLITE_OK) || 387 &plugin->updPrio)) ||
336 (sq_prepare 388 (SQLITE_OK !=
337 (plugin->dbh, 389 sq_prepare (plugin->dbh,
338 "UPDATE gn090 " "SET repl = MAX (0, repl - 1) WHERE _ROWID_ = ?", 390 "UPDATE gn090 " "SET repl = MAX (0, repl - 1) WHERE _ROWID_ = ?",
339 &plugin->updRepl) != SQLITE_OK) || 391 &plugin->updRepl)) ||
340 (sq_prepare 392 (SQLITE_OK !=
341 (plugin->dbh, 393 sq_prepare (plugin->dbh,
342 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ " "FROM gn090 " 394 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ " "FROM gn090 "
343#if SQLITE_VERSION_NUMBER >= 3007000 395#if SQLITE_VERSION_NUMBER >= 3007000
344 "INDEXED BY idx_repl_rvalue " 396 "INDEXED BY idx_repl_rvalue "
345#endif 397#endif
346 "WHERE repl=?2 AND " " (rvalue>=?1 OR " 398 "WHERE repl=?2 AND " " (rvalue>=?1 OR "
347 " NOT EXISTS (SELECT 1 FROM gn090 " 399 " NOT EXISTS (SELECT 1 FROM gn090 "
348#if SQLITE_VERSION_NUMBER >= 3007000 400#if SQLITE_VERSION_NUMBER >= 3007000
349 "INDEXED BY idx_repl_rvalue " 401 "INDEXED BY idx_repl_rvalue "
350#endif 402#endif
351 "WHERE repl=?2 AND rvalue>=?1 LIMIT 1) ) " 403 "WHERE repl=?2 AND rvalue>=?1 LIMIT 1) ) "
352 "ORDER BY rvalue ASC LIMIT 1", &plugin->selRepl) != SQLITE_OK) || 404 "ORDER BY rvalue ASC LIMIT 1",
353 (sq_prepare (plugin->dbh, "SELECT MAX(repl) FROM gn090" 405 &plugin->selRepl)) ||
406 (SQLITE_OK !=
407 sq_prepare (plugin->dbh,
408 "SELECT MAX(repl) FROM gn090"
354#if SQLITE_VERSION_NUMBER >= 3007000 409#if SQLITE_VERSION_NUMBER >= 3007000
355 " INDEXED BY idx_repl_rvalue" 410 " INDEXED BY idx_repl_rvalue"
356#endif 411#endif
357 "", &plugin->maxRepl) != SQLITE_OK) || 412 "",
358 (sq_prepare 413 &plugin->maxRepl)) ||
359 (plugin->dbh, 414 (SQLITE_OK !=
360 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ " "FROM gn090 " 415 sq_prepare (plugin->dbh,
416 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ " "FROM gn090 "
361#if SQLITE_VERSION_NUMBER >= 3007000 417#if SQLITE_VERSION_NUMBER >= 3007000
362 "INDEXED BY idx_expire " 418 "INDEXED BY idx_expire "
363#endif 419#endif
364 "WHERE NOT EXISTS (SELECT 1 FROM gn090 WHERE expire < ?1 LIMIT 1) OR (expire < ?1) " 420 "WHERE NOT EXISTS (SELECT 1 FROM gn090 WHERE expire < ?1 LIMIT 1) OR (expire < ?1) "
365 "ORDER BY expire ASC LIMIT 1", &plugin->selExpi) != SQLITE_OK) || 421 "ORDER BY expire ASC LIMIT 1",
366 (sq_prepare 422 &plugin->selExpi)) ||
367 (plugin->dbh, 423 (SQLITE_OK !=
368 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ " "FROM gn090 " 424 sq_prepare (plugin->dbh,
425 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ " "FROM gn090 "
369#if SQLITE_VERSION_NUMBER >= 3007000 426#if SQLITE_VERSION_NUMBER >= 3007000
370 "INDEXED BY idx_anon_type_hash " 427 "INDEXED BY idx_anon_type_hash "
371#endif 428#endif
372 "WHERE (anonLevel = 0 AND type=?1) " 429 "WHERE (anonLevel = 0 AND type=?1) "
373 "ORDER BY hash DESC LIMIT 1 OFFSET ?2", 430 "ORDER BY hash DESC LIMIT 1 OFFSET ?2",
374 &plugin->selZeroAnon) != SQLITE_OK) || 431 &plugin->selZeroAnon)) ||
375 (sq_prepare 432 (SQLITE_OK !=
376 (plugin->dbh, 433 sq_prepare (plugin->dbh,
377 "INSERT INTO gn090 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) " 434 "INSERT INTO gn090 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) "
378 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", 435 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
379 &plugin->insertContent) != SQLITE_OK) || 436 &plugin->insertContent)) ||
380 (sq_prepare 437 (SQLITE_OK !=
381 (plugin->dbh, "DELETE FROM gn090 WHERE _ROWID_ = ?", 438 sq_prepare (plugin->dbh,
382 &plugin->delRow) != SQLITE_OK)) 439 "SELECT count(*) FROM gn090 WHERE hash=?",
440 &plugin->count_key)) ||
441 (SQLITE_OK !=
442 sq_prepare (plugin->dbh,
443 "SELECT count(*) FROM gn090 WHERE hash=? AND vhash=?",
444 &plugin->count_key_vhash)) ||
445 (SQLITE_OK !=
446 sq_prepare (plugin->dbh,
447 "SELECT count(*) FROM gn090 WHERE hash=? AND type=?",
448 &plugin->count_key_type)) ||
449 (SQLITE_OK !=
450 sq_prepare (plugin->dbh,
451 "SELECT count(*) FROM gn090 WHERE hash=? AND vhash=? AND type=?",
452 &plugin->count_key_vhash_type)) ||
453 (SQLITE_OK !=
454 sq_prepare (plugin->dbh,
455 "SELECT type, prio, anonLevel, expire, hash, value, _ROWID_ FROM gn090 "
456 "WHERE hash=?"
457 "ORDER BY _ROWID_ ASC LIMIT 1 OFFSET ?",
458 &plugin->get_key)) ||
459 (SQLITE_OK !=
460 sq_prepare (plugin->dbh,
461 "SELECT type, prio, anonLevel, expire, hash, value, _ROWID_ FROM gn090 "
462 "WHERE hash=? AND vhash=?"
463 "ORDER BY _ROWID_ ASC LIMIT 1 OFFSET ?",
464 &plugin->get_key_vhash)) ||
465 (SQLITE_OK !=
466 sq_prepare (plugin->dbh,
467 "SELECT type, prio, anonLevel, expire, hash, value, _ROWID_ FROM gn090 "
468 "WHERE hash=? AND type=?"
469 "ORDER BY _ROWID_ ASC LIMIT 1 OFFSET ?",
470 &plugin->get_key_type)) ||
471 (SQLITE_OK !=
472 sq_prepare (plugin->dbh,
473 "SELECT type, prio, anonLevel, expire, hash, value, _ROWID_ FROM gn090 "
474 "WHERE hash=? AND vhash=? AND type=?"
475 "ORDER BY _ROWID_ ASC LIMIT 1 OFFSET ?",
476 &plugin->get_key_vhash_type)) ||
477 (SQLITE_OK !=
478 sq_prepare (plugin->dbh,
479 "DELETE FROM gn090 WHERE _ROWID_ = ?",
480 &plugin->delRow))
481 )
383 { 482 {
384 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "precompiling"); 483 LOG_SQLITE (plugin,
484 GNUNET_ERROR_TYPE_ERROR,
485 "precompiling");
385 return GNUNET_SYSERR; 486 return GNUNET_SYSERR;
386 } 487 }
387
388 return GNUNET_OK; 488 return GNUNET_OK;
389} 489}
390 490
@@ -399,51 +499,74 @@ static void
399database_shutdown (struct Plugin *plugin) 499database_shutdown (struct Plugin *plugin)
400{ 500{
401 int result; 501 int result;
402
403#if SQLITE_VERSION_NUMBER >= 3007000 502#if SQLITE_VERSION_NUMBER >= 3007000
404 sqlite3_stmt *stmt; 503 sqlite3_stmt *stmt;
405#endif 504#endif
406 505
407 if (plugin->delRow != NULL) 506 if (NULL != plugin->delRow)
408 sqlite3_finalize (plugin->delRow); 507 sqlite3_finalize (plugin->delRow);
409 if (plugin->updPrio != NULL) 508 if (NULL != plugin->updPrio)
410 sqlite3_finalize (plugin->updPrio); 509 sqlite3_finalize (plugin->updPrio);
411 if (plugin->updRepl != NULL) 510 if (NULL != plugin->updRepl)
412 sqlite3_finalize (plugin->updRepl); 511 sqlite3_finalize (plugin->updRepl);
413 if (plugin->selRepl != NULL) 512 if (NULL != plugin->selRepl)
414 sqlite3_finalize (plugin->selRepl); 513 sqlite3_finalize (plugin->selRepl);
415 if (plugin->maxRepl != NULL) 514 if (NULL != plugin->maxRepl)
416 sqlite3_finalize (plugin->maxRepl); 515 sqlite3_finalize (plugin->maxRepl);
417 if (plugin->selExpi != NULL) 516 if (NULL != plugin->selExpi)
418 sqlite3_finalize (plugin->selExpi); 517 sqlite3_finalize (plugin->selExpi);
419 if (plugin->selZeroAnon != NULL) 518 if (NULL != plugin->selZeroAnon)
420 sqlite3_finalize (plugin->selZeroAnon); 519 sqlite3_finalize (plugin->selZeroAnon);
421 if (plugin->insertContent != NULL) 520 if (NULL != plugin->insertContent)
422 sqlite3_finalize (plugin->insertContent); 521 sqlite3_finalize (plugin->insertContent);
522 if (NULL != plugin->count_key)
523 sqlite3_finalize (plugin->count_key);
524 if (NULL != plugin->count_key_vhash)
525 sqlite3_finalize (plugin->count_key_vhash);
526 if (NULL != plugin->count_key_type)
527 sqlite3_finalize (plugin->count_key_type);
528 if (NULL != plugin->count_key_vhash_type)
529 sqlite3_finalize (plugin->count_key_vhash_type);
530 if (NULL != plugin->count_key)
531 sqlite3_finalize (plugin->get_key);
532 if (NULL != plugin->count_key_vhash)
533 sqlite3_finalize (plugin->get_key_vhash);
534 if (NULL != plugin->count_key_type)
535 sqlite3_finalize (plugin->get_key_type);
536 if (NULL != plugin->count_key_vhash_type)
537 sqlite3_finalize (plugin->get_key_vhash_type);
423 result = sqlite3_close (plugin->dbh); 538 result = sqlite3_close (plugin->dbh);
424#if SQLITE_VERSION_NUMBER >= 3007000 539#if SQLITE_VERSION_NUMBER >= 3007000
425 if (result == SQLITE_BUSY) 540 if (result == SQLITE_BUSY)
426 { 541 {
427 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite", 542 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
428 _ 543 "sqlite",
429 ("Tried to close sqlite without finalizing all prepared statements.\n")); 544 _("Tried to close sqlite without finalizing all prepared statements.\n"));
430 stmt = sqlite3_next_stmt (plugin->dbh, NULL); 545 stmt = sqlite3_next_stmt (plugin->dbh,
431 while (stmt != NULL) 546 NULL);
547 while (NULL != stmt)
432 { 548 {
433 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", 549 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
434 "Closing statement %p\n", stmt); 550 "sqlite",
551 "Closing statement %p\n",
552 stmt);
435 result = sqlite3_finalize (stmt); 553 result = sqlite3_finalize (stmt);
436 if (result != SQLITE_OK) 554 if (result != SQLITE_OK)
437 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite", 555 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
438 "Failed to close statement %p: %d\n", stmt, result); 556 "sqlite",
439 stmt = sqlite3_next_stmt (plugin->dbh, NULL); 557 "Failed to close statement %p: %d\n",
558 stmt,
559 result);
560 stmt = sqlite3_next_stmt (plugin->dbh,
561 NULL);
440 } 562 }
441 result = sqlite3_close (plugin->dbh); 563 result = sqlite3_close (plugin->dbh);
442 } 564 }
443#endif 565#endif
444 if (SQLITE_OK != result) 566 if (SQLITE_OK != result)
445 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close"); 567 LOG_SQLITE (plugin,
446 568 GNUNET_ERROR_TYPE_ERROR,
569 "sqlite3_close");
447 GNUNET_free_non_null (plugin->fn); 570 GNUNET_free_non_null (plugin->fn);
448} 571}
449 572
@@ -472,15 +595,12 @@ delete_by_rowid (struct Plugin *plugin,
472 { 595 {
473 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 596 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
474 "sqlite3_step"); 597 "sqlite3_step");
475 if (SQLITE_OK != sqlite3_reset (plugin->delRow)) 598 GNUNET_SQ_reset (plugin->dbh,
476 LOG_SQLITE (plugin, 599 plugin->delRow);
477 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
478 "sqlite3_reset");
479 return GNUNET_SYSERR; 600 return GNUNET_SYSERR;
480 } 601 }
481 if (SQLITE_OK != sqlite3_reset (plugin->delRow)) 602 GNUNET_SQ_reset (plugin->dbh,
482 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 603 plugin->delRow);
483 "sqlite3_reset");
484 return GNUNET_OK; 604 return GNUNET_OK;
485} 605}
486 606
@@ -515,9 +635,10 @@ sqlite_plugin_put (void *cls,
515{ 635{
516 uint64_t rvalue; 636 uint64_t rvalue;
517 struct GNUNET_HashCode vhash; 637 struct GNUNET_HashCode vhash;
638 uint32_t type32 = (uint32_t) type;
518 struct GNUNET_SQ_QueryParam params[] = { 639 struct GNUNET_SQ_QueryParam params[] = {
519 GNUNET_SQ_query_param_uint32 (&replication), 640 GNUNET_SQ_query_param_uint32 (&replication),
520 GNUNET_SQ_query_param_uint32 (&type), 641 GNUNET_SQ_query_param_uint32 (&type32),
521 GNUNET_SQ_query_param_uint32 (&priority), 642 GNUNET_SQ_query_param_uint32 (&priority),
522 GNUNET_SQ_query_param_uint32 (&anonymity), 643 GNUNET_SQ_query_param_uint32 (&anonymity),
523 GNUNET_SQ_query_param_absolute_time (&expiration), 644 GNUNET_SQ_query_param_absolute_time (&expiration),
@@ -578,19 +699,16 @@ sqlite_plugin_put (void *cls,
578 default: 699 default:
579 LOG_SQLITE_MSG (plugin, &msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 700 LOG_SQLITE_MSG (plugin, &msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
580 "sqlite3_step"); 701 "sqlite3_step");
581 if (SQLITE_OK != sqlite3_reset (stmt)) 702 GNUNET_SQ_reset (plugin->dbh,
582 LOG_SQLITE (plugin, 703 stmt);
583 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
584 "sqlite3_reset");
585 database_shutdown (plugin); 704 database_shutdown (plugin);
586 database_setup (plugin->env->cfg, plugin); 705 database_setup (plugin->env->cfg, plugin);
587 cont (cont_cls, key, size, GNUNET_SYSERR, msg); 706 cont (cont_cls, key, size, GNUNET_SYSERR, msg);
588 GNUNET_free_non_null(msg); 707 GNUNET_free_non_null(msg);
589 return; 708 return;
590 } 709 }
591 if (SQLITE_OK != sqlite3_reset (stmt)) 710 GNUNET_SQ_reset (plugin->dbh,
592 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 711 stmt);
593 "sqlite3_reset");
594 cont (cont_cls, key, size, ret, msg); 712 cont (cont_cls, key, size, ret, msg);
595 GNUNET_free_non_null(msg); 713 GNUNET_free_non_null(msg);
596} 714}
@@ -644,9 +762,8 @@ sqlite_plugin_update (void *cls,
644 return; 762 return;
645 } 763 }
646 n = sqlite3_step (plugin->updPrio); 764 n = sqlite3_step (plugin->updPrio);
647 if (SQLITE_OK != sqlite3_reset (plugin->updPrio)) 765 GNUNET_SQ_reset (plugin->dbh,
648 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 766 plugin->updPrio);
649 "sqlite3_reset");
650 switch (n) 767 switch (n)
651 { 768 {
652 case SQLITE_DONE: 769 case SQLITE_DONE:
@@ -687,75 +804,84 @@ execute_get (struct Plugin *plugin,
687{ 804{
688 int n; 805 int n;
689 struct GNUNET_TIME_Absolute expiration; 806 struct GNUNET_TIME_Absolute expiration;
690 unsigned long long rowid; 807 uint32_t type;
691 unsigned int size; 808 uint32_t priority;
809 uint32_t anonymity;
810 uint64_t rowid;
811 void *value;
812 size_t value_size;
813 struct GNUNET_HashCode key;
692 int ret; 814 int ret;
815 struct GNUNET_SQ_ResultSpec rs[] = {
816 GNUNET_SQ_result_spec_uint32 (&type),
817 GNUNET_SQ_result_spec_uint32 (&priority),
818 GNUNET_SQ_result_spec_uint32 (&anonymity),
819 GNUNET_SQ_result_spec_absolute_time (&expiration),
820 GNUNET_SQ_result_spec_auto_from_type (&key),
821 GNUNET_SQ_result_spec_variable_size (&value,
822 &value_size),
823 GNUNET_SQ_result_spec_uint64 (&rowid),
824 GNUNET_SQ_result_spec_end
825 };
693 826
694 n = sqlite3_step (stmt); 827 n = sqlite3_step (stmt);
695 switch (n) 828 switch (n)
696 { 829 {
697 case SQLITE_ROW: 830 case SQLITE_ROW:
698 size = sqlite3_column_bytes (stmt, 5); 831 if (GNUNET_OK !=
699 rowid = sqlite3_column_int64 (stmt, 6); 832 GNUNET_SQ_extract_result (stmt,
700 if (sqlite3_column_bytes (stmt, 4) != sizeof (struct GNUNET_HashCode)) 833 rs))
701 { 834 {
702 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite", 835 GNUNET_break (0);
703 _("Invalid data in database. Trying to fix (by deletion).\n"));
704 if (SQLITE_OK != sqlite3_reset (stmt))
705 LOG_SQLITE (plugin,
706 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
707 "sqlite3_reset");
708 if ( (GNUNET_OK == delete_by_rowid (plugin, rowid)) &&
709 (NULL != plugin->env->duc) )
710 plugin->env->duc (plugin->env->cls,
711 -(size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
712 break; 836 break;
713 } 837 }
714 expiration.abs_value_us = sqlite3_column_int64 (stmt, 3); 838 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
715 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", 839 "sqlite",
716 "Found reply in database with expiration %s\n", 840 "Found reply in database with expiration %s\n",
717 GNUNET_STRINGS_absolute_time_to_string (expiration)); 841 GNUNET_STRINGS_absolute_time_to_string (expiration));
718 ret = proc (proc_cls, sqlite3_column_blob (stmt, 4) /* key */ , 842 ret = proc (proc_cls,
719 size, sqlite3_column_blob (stmt, 5) /* data */ , 843 &key,
720 sqlite3_column_int (stmt, 0) /* type */ , 844 value_size,
721 sqlite3_column_int (stmt, 1) /* priority */ , 845 value,
722 sqlite3_column_int (stmt, 2) /* anonymity */ , 846 type,
723 expiration, rowid); 847 priority,
724 if (SQLITE_OK != sqlite3_reset (stmt)) 848 anonymity,
725 LOG_SQLITE (plugin, 849 expiration,
726 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 850 rowid);
727 "sqlite3_reset"); 851 GNUNET_SQ_cleanup_result (rs);
852 GNUNET_SQ_reset (plugin->dbh,
853 stmt);
728 if ( (GNUNET_NO == ret) && 854 if ( (GNUNET_NO == ret) &&
729 (GNUNET_OK == delete_by_rowid (plugin, rowid)) && 855 (GNUNET_OK == delete_by_rowid (plugin,
856 rowid)) &&
730 (NULL != plugin->env->duc) ) 857 (NULL != plugin->env->duc) )
731 plugin->env->duc (plugin->env->cls, 858 plugin->env->duc (plugin->env->cls,
732 -(size + GNUNET_DATASTORE_ENTRY_OVERHEAD)); 859 -(value_size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
733 return; 860 return;
734 case SQLITE_DONE: 861 case SQLITE_DONE:
735 /* database must be empty */ 862 /* database must be empty */
736 if (SQLITE_OK != sqlite3_reset (stmt))
737 LOG_SQLITE (plugin,
738 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
739 "sqlite3_reset");
740 break; 863 break;
741 case SQLITE_BUSY: 864 case SQLITE_BUSY:
742 case SQLITE_ERROR: 865 case SQLITE_ERROR:
743 case SQLITE_MISUSE: 866 case SQLITE_MISUSE:
744 default: 867 default:
745 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 868 LOG_SQLITE (plugin,
869 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
746 "sqlite3_step"); 870 "sqlite3_step");
747 if (SQLITE_OK != sqlite3_reset (stmt)) 871 if (SQLITE_OK !=
872 sqlite3_reset (stmt))
748 LOG_SQLITE (plugin, 873 LOG_SQLITE (plugin,
749 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 874 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
750 "sqlite3_reset"); 875 "sqlite3_reset");
751 GNUNET_break (0); 876 GNUNET_break (0);
877 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
752 database_shutdown (plugin); 878 database_shutdown (plugin);
753 database_setup (plugin->env->cfg, plugin); 879 database_setup (plugin->env->cfg,
754 break; 880 plugin);
881 return;
755 } 882 }
756 if (SQLITE_OK != sqlite3_reset (stmt)) 883 GNUNET_SQ_reset (plugin->dbh,
757 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 884 stmt);
758 "sqlite3_reset");
759 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 885 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
760} 886}
761 887
@@ -774,7 +900,8 @@ execute_get (struct Plugin *plugin,
774 * @param proc_cls closure for @a proc 900 * @param proc_cls closure for @a proc
775 */ 901 */
776static void 902static void
777sqlite_plugin_get_zero_anonymity (void *cls, uint64_t offset, 903sqlite_plugin_get_zero_anonymity (void *cls,
904 uint64_t offset,
778 enum GNUNET_BLOCK_Type type, 905 enum GNUNET_BLOCK_Type type,
779 PluginDatumProcessor proc, 906 PluginDatumProcessor proc,
780 void *proc_cls) 907 void *proc_cls)
@@ -826,97 +953,133 @@ sqlite_plugin_get_key (void *cls,
826 void *proc_cls) 953 void *proc_cls)
827{ 954{
828 struct Plugin *plugin = cls; 955 struct Plugin *plugin = cls;
956 uint32_t type32 = (uint32_t) type;
829 int ret; 957 int ret;
830 int total; 958 int total;
831 int limit_off; 959 uint32_t limit_off;
832 unsigned int sqoff; 960 struct GNUNET_SQ_QueryParam count_params_key[] = {
833 sqlite3_stmt *stmt; 961 GNUNET_SQ_query_param_auto_from_type (key),
834 char scratch[256]; 962 GNUNET_SQ_query_param_end
835 963 };
836 GNUNET_assert (proc != NULL); 964 struct GNUNET_SQ_QueryParam count_params_key_vhash[] = {
837 GNUNET_assert (key != NULL); 965 GNUNET_SQ_query_param_auto_from_type (key),
838 GNUNET_snprintf (scratch, sizeof (scratch), 966 GNUNET_SQ_query_param_auto_from_type (vhash),
839 "SELECT count(*) FROM gn090 WHERE hash=?%s%s", 967 GNUNET_SQ_query_param_end
840 vhash == NULL ? "" : " AND vhash=?", 968 };
841 type == 0 ? "" : " AND type=?"); 969 struct GNUNET_SQ_QueryParam count_params_key_type[] = {
842 if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK) 970 GNUNET_SQ_query_param_auto_from_type (key),
971 GNUNET_SQ_query_param_uint32 (&type32),
972 GNUNET_SQ_query_param_end
973 };
974 struct GNUNET_SQ_QueryParam count_params_key_vhash_type[] = {
975 GNUNET_SQ_query_param_auto_from_type (key),
976 GNUNET_SQ_query_param_auto_from_type (vhash),
977 GNUNET_SQ_query_param_uint32 (&type32),
978 GNUNET_SQ_query_param_end
979 };
980 struct GNUNET_SQ_QueryParam get_params_key[] = {
981 GNUNET_SQ_query_param_auto_from_type (key),
982 GNUNET_SQ_query_param_uint32 (&limit_off),
983 GNUNET_SQ_query_param_end
984 };
985 struct GNUNET_SQ_QueryParam get_params_key_vhash[] = {
986 GNUNET_SQ_query_param_auto_from_type (key),
987 GNUNET_SQ_query_param_auto_from_type (vhash),
988 GNUNET_SQ_query_param_uint32 (&limit_off),
989 GNUNET_SQ_query_param_end
990 };
991 struct GNUNET_SQ_QueryParam get_params_key_type[] = {
992 GNUNET_SQ_query_param_auto_from_type (key),
993 GNUNET_SQ_query_param_uint32 (&type32),
994 GNUNET_SQ_query_param_uint32 (&limit_off),
995 GNUNET_SQ_query_param_end
996 };
997 struct GNUNET_SQ_QueryParam get_params_key_vhash_type[] = {
998 GNUNET_SQ_query_param_auto_from_type (key),
999 GNUNET_SQ_query_param_auto_from_type (vhash),
1000 GNUNET_SQ_query_param_uint32 (&type32),
1001 GNUNET_SQ_query_param_uint32 (&limit_off),
1002 GNUNET_SQ_query_param_end
1003 };
1004 struct GNUNET_SQ_QueryParam *count_params;
1005 sqlite3_stmt *count_stmt;
1006 struct GNUNET_SQ_QueryParam *get_params;
1007 sqlite3_stmt *get_stmt;
1008
1009 if (NULL == vhash)
843 { 1010 {
844 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 1011 if (GNUNET_BLOCK_TYPE_ANY == type)
845 "sqlite_prepare"); 1012 {
846 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 1013 count_params = count_params_key;
847 return; 1014 count_stmt = plugin->count_key;
1015 get_params = get_params_key;
1016 get_stmt = plugin->get_key;
1017 }
1018 else
1019 {
1020 count_params = count_params_key_type;
1021 count_stmt = plugin->count_key_type;
1022 get_params = get_params_key_type;
1023 get_stmt = plugin->get_key_type;
1024 }
848 } 1025 }
849 sqoff = 1; 1026 else
850 ret = 1027 {
851 sqlite3_bind_blob (stmt, sqoff++, key, sizeof (struct GNUNET_HashCode), 1028 if (GNUNET_BLOCK_TYPE_ANY == type)
852 SQLITE_TRANSIENT); 1029 {
853 if ((vhash != NULL) && (ret == SQLITE_OK)) 1030 count_params = count_params_key_vhash;
854 ret = 1031 count_stmt = plugin->count_key_vhash;
855 sqlite3_bind_blob (stmt, sqoff++, vhash, sizeof (struct GNUNET_HashCode), 1032 get_params = get_params_key_vhash;
856 SQLITE_TRANSIENT); 1033 get_stmt = plugin->get_key_vhash;
857 if ((type != 0) && (ret == SQLITE_OK)) 1034 }
858 ret = sqlite3_bind_int (stmt, sqoff++, type); 1035 else
859 if (SQLITE_OK != ret) 1036 {
1037 count_params = count_params_key_vhash_type;
1038 count_stmt = plugin->count_key_vhash_type;
1039 get_params = get_params_key_vhash_type;
1040 get_stmt = plugin->get_key_vhash_type;
1041 }
1042 }
1043 if (GNUNET_OK !=
1044 GNUNET_SQ_bind (count_stmt,
1045 count_params))
860 { 1046 {
861 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_bind");
862 sqlite3_finalize (stmt);
863 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 1047 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
864 return; 1048 return;
865 } 1049 }
866 ret = sqlite3_step (stmt); 1050 ret = sqlite3_step (count_stmt);
867 if (ret != SQLITE_ROW) 1051 if (ret != SQLITE_ROW)
868 { 1052 {
869 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 1053 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
870 "sqlite_step"); 1054 "sqlite_step");
871 sqlite3_finalize (stmt); 1055 GNUNET_SQ_reset (plugin->dbh,
1056 count_stmt);
872 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 1057 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
873 return; 1058 return;
874 } 1059 }
875 total = sqlite3_column_int (stmt, 0); 1060 total = sqlite3_column_int (count_stmt,
876 sqlite3_finalize (stmt); 1061 0);
1062 GNUNET_SQ_reset (plugin->dbh,
1063 count_stmt);
877 if (0 == total) 1064 if (0 == total)
878 { 1065 {
879 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 1066 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
880 return; 1067 return;
881 } 1068 }
882 limit_off = (int) (offset % total); 1069 limit_off = (uint32_t) (offset % total);
883 if (limit_off < 0) 1070 if (GNUNET_OK !=
884 limit_off += total; 1071 GNUNET_SQ_bind (get_stmt,
885 GNUNET_snprintf (scratch, sizeof (scratch), 1072 get_params))
886 "SELECT type, prio, anonLevel, expire, hash, value, _ROWID_ "
887 "FROM gn090 WHERE hash=?%s%s "
888 "ORDER BY _ROWID_ ASC LIMIT 1 OFFSET ?",
889 vhash == NULL ? "" : " AND vhash=?",
890 type == 0 ? "" : " AND type=?");
891 if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK)
892 {
893 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
894 "sqlite_prepare");
895 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
896 return;
897 }
898 sqoff = 1;
899 ret = sqlite3_bind_blob (stmt, sqoff++, key,
900 sizeof (struct GNUNET_HashCode),
901 SQLITE_TRANSIENT);
902 if ((vhash != NULL) && (ret == SQLITE_OK))
903 ret = sqlite3_bind_blob (stmt, sqoff++, vhash,
904 sizeof (struct GNUNET_HashCode),
905 SQLITE_TRANSIENT);
906 if ((type != 0) && (ret == SQLITE_OK))
907 ret = sqlite3_bind_int (stmt, sqoff++, type);
908 if (ret == SQLITE_OK)
909 ret = sqlite3_bind_int64 (stmt, sqoff++, limit_off);
910 if (ret != SQLITE_OK)
911 { 1073 {
912 LOG_SQLITE (plugin,
913 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
914 "sqlite_bind");
915 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 1074 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
916 return; 1075 return;
917 } 1076 }
918 execute_get (plugin, stmt, proc, proc_cls); 1077 execute_get (plugin,
919 sqlite3_finalize (stmt); 1078 get_stmt,
1079 proc,
1080 proc_cls);
1081 GNUNET_SQ_reset (plugin->dbh,
1082 get_stmt);
920} 1083}
921 1084
922 1085
@@ -980,13 +1143,17 @@ repl_proc (void *cls,
980 struct ReplCtx *rc = cls; 1143 struct ReplCtx *rc = cls;
981 int ret; 1144 int ret;
982 1145
1146 if (GNUNET_SYSERR == rc->have_uid)
1147 rc->have_uid = GNUNET_NO;
983 ret = rc->proc (rc->proc_cls, 1148 ret = rc->proc (rc->proc_cls,
984 key, 1149 key,
985 size, data, 1150 size,
1151 data,
986 type, 1152 type,
987 priority, 1153 priority,
988 anonymity, 1154 anonymity,
989 expiration, uid); 1155 expiration,
1156 uid);
990 if (NULL != key) 1157 if (NULL != key)
991 { 1158 {
992 rc->uid = uid; 1159 rc->uid = uid;
@@ -1007,7 +1174,8 @@ repl_proc (void *cls,
1007 * @param proc_cls closure for @a proc 1174 * @param proc_cls closure for @a proc
1008 */ 1175 */
1009static void 1176static void
1010sqlite_plugin_get_replication (void *cls, PluginDatumProcessor proc, 1177sqlite_plugin_get_replication (void *cls,
1178 PluginDatumProcessor proc,
1011 void *proc_cls) 1179 void *proc_cls)
1012{ 1180{
1013 struct Plugin *plugin = cls; 1181 struct Plugin *plugin = cls;
@@ -1027,24 +1195,21 @@ sqlite_plugin_get_replication (void *cls, PluginDatumProcessor proc,
1027 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1195 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1028 "datastore-sqlite", 1196 "datastore-sqlite",
1029 "Getting random block based on replication order.\n"); 1197 "Getting random block based on replication order.\n");
1030 rc.have_uid = GNUNET_NO; 1198 if (SQLITE_ROW !=
1031 rc.proc = proc; 1199 sqlite3_step (plugin->maxRepl))
1032 rc.proc_cls = proc_cls;
1033 if (SQLITE_ROW != sqlite3_step (plugin->maxRepl))
1034 { 1200 {
1035 if (SQLITE_OK != sqlite3_reset (plugin->maxRepl)) 1201 GNUNET_SQ_reset (plugin->dbh,
1036 LOG_SQLITE (plugin, 1202 plugin->maxRepl);
1037 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1038 "sqlite3_reset");
1039 /* DB empty */ 1203 /* DB empty */
1040 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 1204 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1041 return; 1205 return;
1042 } 1206 }
1043 repl = sqlite3_column_int (plugin->maxRepl, 0); 1207 repl = sqlite3_column_int (plugin->maxRepl,
1044 if (SQLITE_OK != sqlite3_reset (plugin->maxRepl)) 1208 0);
1045 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 1209 GNUNET_SQ_reset (plugin->dbh,
1046 "sqlite3_reset"); 1210 plugin->maxRepl);
1047 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); 1211 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1212 UINT64_MAX);
1048 if (GNUNET_OK != 1213 if (GNUNET_OK !=
1049 GNUNET_SQ_bind (plugin->selRepl, 1214 GNUNET_SQ_bind (plugin->selRepl,
1050 params_sel_repl)) 1215 params_sel_repl))
@@ -1052,7 +1217,13 @@ sqlite_plugin_get_replication (void *cls, PluginDatumProcessor proc,
1052 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 1217 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1053 return; 1218 return;
1054 } 1219 }
1055 execute_get (plugin, plugin->selRepl, &repl_proc, &rc); 1220 rc.have_uid = GNUNET_SYSERR;
1221 rc.proc = proc;
1222 rc.proc_cls = proc_cls;
1223 execute_get (plugin,
1224 plugin->selRepl,
1225 &repl_proc,
1226 &rc);
1056 if (GNUNET_YES == rc.have_uid) 1227 if (GNUNET_YES == rc.have_uid)
1057 { 1228 {
1058 if (GNUNET_OK != 1229 if (GNUNET_OK !=
@@ -1062,14 +1233,18 @@ sqlite_plugin_get_replication (void *cls, PluginDatumProcessor proc,
1062 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 1233 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1063 return; 1234 return;
1064 } 1235 }
1065 if (SQLITE_DONE != sqlite3_step (plugin->updRepl)) 1236 if (SQLITE_DONE !=
1237 sqlite3_step (plugin->updRepl))
1066 LOG_SQLITE (plugin, 1238 LOG_SQLITE (plugin,
1067 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 1239 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1068 "sqlite3_step"); 1240 "sqlite3_step");
1069 if (SQLITE_OK != sqlite3_reset (plugin->updRepl)) 1241 GNUNET_SQ_reset (plugin->dbh,
1070 LOG_SQLITE (plugin, 1242 plugin->updRepl);
1071 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 1243 }
1072 "sqlite3_reset"); 1244 if (GNUNET_SYSERR == rc.have_uid)
1245 {
1246 /* proc was not called at all so far, do it now. */
1247 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1073 } 1248 }
1074} 1249}
1075 1250
@@ -1094,7 +1269,8 @@ sqlite_plugin_get_expiration (void *cls, PluginDatumProcessor proc,
1094 GNUNET_SQ_query_param_end 1269 GNUNET_SQ_query_param_end
1095 }; 1270 };
1096 1271
1097 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", 1272 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1273 "sqlite",
1098 "Getting random block based on expiration and priority order.\n"); 1274 "Getting random block based on expiration and priority order.\n");
1099 now = GNUNET_TIME_absolute_get (); 1275 now = GNUNET_TIME_absolute_get ();
1100 stmt = plugin->selExpi; 1276 stmt = plugin->selExpi;
@@ -1131,11 +1307,17 @@ sqlite_plugin_get_keys (void *cls,
1131 int ret; 1307 int ret;
1132 1308
1133 GNUNET_assert (NULL != proc); 1309 GNUNET_assert (NULL != proc);
1134 if (sq_prepare (plugin->dbh, "SELECT hash FROM gn090", &stmt) != SQLITE_OK) 1310 if (SQLITE_OK !=
1311 sq_prepare (plugin->dbh,
1312 "SELECT hash FROM gn090",
1313 &stmt))
1135 { 1314 {
1136 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 1315 LOG_SQLITE (plugin,
1316 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1137 "sqlite_prepare"); 1317 "sqlite_prepare");
1138 proc (proc_cls, NULL, 0); 1318 proc (proc_cls,
1319 NULL,
1320 0);
1139 return; 1321 return;
1140 } 1322 }
1141 while (SQLITE_ROW == (ret = sqlite3_step (stmt))) 1323 while (SQLITE_ROW == (ret = sqlite3_step (stmt)))
@@ -1143,14 +1325,20 @@ sqlite_plugin_get_keys (void *cls,
1143 if (GNUNET_OK == 1325 if (GNUNET_OK ==
1144 GNUNET_SQ_extract_result (stmt, 1326 GNUNET_SQ_extract_result (stmt,
1145 results)) 1327 results))
1146 proc (proc_cls, &key, 1); 1328 proc (proc_cls,
1329 &key,
1330 1);
1147 else 1331 else
1148 GNUNET_break (0); 1332 GNUNET_break (0);
1149 } 1333 }
1150 if (SQLITE_DONE != ret) 1334 if (SQLITE_DONE != ret)
1151 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step"); 1335 LOG_SQLITE (plugin,
1336 GNUNET_ERROR_TYPE_ERROR,
1337 "sqlite_step");
1152 sqlite3_finalize (stmt); 1338 sqlite3_finalize (stmt);
1153 proc (proc_cls, NULL, 0); 1339 proc (proc_cls,
1340 NULL,
1341 0);
1154} 1342}
1155 1343
1156 1344
@@ -1176,7 +1364,8 @@ sqlite_plugin_drop (void *cls)
1176 * @return the size of the database on disk (estimate) 1364 * @return the size of the database on disk (estimate)
1177 */ 1365 */
1178static void 1366static void
1179sqlite_plugin_estimate_size (void *cls, unsigned long long *estimate) 1367sqlite_plugin_estimate_size (void *cls,
1368 unsigned long long *estimate)
1180{ 1369{
1181 struct Plugin *plugin = cls; 1370 struct Plugin *plugin = cls;
1182 sqlite3_stmt *stmt; 1371 sqlite3_stmt *stmt;
@@ -1191,29 +1380,45 @@ sqlite_plugin_estimate_size (void *cls, unsigned long long *estimate)
1191 return; 1380 return;
1192 if (SQLITE_VERSION_NUMBER < 3006000) 1381 if (SQLITE_VERSION_NUMBER < 3006000)
1193 { 1382 {
1194 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "datastore-sqlite", 1383 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
1195 _ 1384 "datastore-sqlite",
1196 ("sqlite version to old to determine size, assuming zero\n")); 1385 _("sqlite version to old to determine size, assuming zero\n"));
1197 *estimate = 0; 1386 *estimate = 0;
1198 return; 1387 return;
1199 } 1388 }
1200 CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "VACUUM", NULL, NULL, ENULL));
1201 CHECK (SQLITE_OK == 1389 CHECK (SQLITE_OK ==
1202 sqlite3_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL", NULL, 1390 sqlite3_exec (plugin->dbh,
1391 "VACUUM",
1392 NULL,
1393 NULL,
1394 ENULL));
1395 CHECK (SQLITE_OK ==
1396 sqlite3_exec (plugin->dbh,
1397 "PRAGMA auto_vacuum=INCREMENTAL",
1398 NULL,
1203 NULL, ENULL)); 1399 NULL, ENULL));
1204 CHECK (SQLITE_OK == sq_prepare (plugin->dbh, "PRAGMA page_count", &stmt)); 1400 CHECK (SQLITE_OK ==
1401 sq_prepare (plugin->dbh,
1402 "PRAGMA page_count",
1403 &stmt));
1205 if (SQLITE_ROW == sqlite3_step (stmt)) 1404 if (SQLITE_ROW == sqlite3_step (stmt))
1206 pages = sqlite3_column_int64 (stmt, 0); 1405 pages = sqlite3_column_int64 (stmt,
1406 0);
1207 else 1407 else
1208 pages = 0; 1408 pages = 0;
1209 sqlite3_finalize (stmt); 1409 sqlite3_finalize (stmt);
1210 CHECK (SQLITE_OK == sq_prepare (plugin->dbh, "PRAGMA page_size", &stmt)); 1410 CHECK (SQLITE_OK ==
1211 CHECK (SQLITE_ROW == sqlite3_step (stmt)); 1411 sq_prepare (plugin->dbh,
1412 "PRAGMA page_size",
1413 &stmt));
1414 CHECK (SQLITE_ROW ==
1415 sqlite3_step (stmt));
1212 page_size = sqlite3_column_int64 (stmt, 0); 1416 page_size = sqlite3_column_int64 (stmt, 0);
1213 sqlite3_finalize (stmt); 1417 sqlite3_finalize (stmt);
1214 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1418 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1215 _("Using sqlite page utilization to estimate payload (%llu pages of size %llu bytes)\n"), 1419 _("Using sqlite page utilization to estimate payload (%llu pages of size %llu bytes)\n"),
1216 (unsigned long long) pages, (unsigned long long) page_size); 1420 (unsigned long long) pages,
1421 (unsigned long long) page_size);
1217 *estimate = pages * page_size; 1422 *estimate = pages * page_size;
1218} 1423}
1219 1424
@@ -1231,9 +1436,11 @@ libgnunet_plugin_datastore_sqlite_init (void *cls)
1231 struct GNUNET_DATASTORE_PluginEnvironment *env = cls; 1436 struct GNUNET_DATASTORE_PluginEnvironment *env = cls;
1232 struct GNUNET_DATASTORE_PluginFunctions *api; 1437 struct GNUNET_DATASTORE_PluginFunctions *api;
1233 1438
1234 if (plugin.env != NULL) 1439 if (NULL != plugin.env)
1235 return NULL; /* can only initialize once! */ 1440 return NULL; /* can only initialize once! */
1236 memset (&plugin, 0, sizeof (struct Plugin)); 1441 memset (&plugin,
1442 0,
1443 sizeof (struct Plugin));
1237 plugin.env = env; 1444 plugin.env = env;
1238 if (GNUNET_OK != database_setup (env->cfg, &plugin)) 1445 if (GNUNET_OK != database_setup (env->cfg, &plugin))
1239 { 1446 {
@@ -1251,7 +1458,8 @@ libgnunet_plugin_datastore_sqlite_init (void *cls)
1251 api->get_zero_anonymity = &sqlite_plugin_get_zero_anonymity; 1458 api->get_zero_anonymity = &sqlite_plugin_get_zero_anonymity;
1252 api->get_keys = &sqlite_plugin_get_keys; 1459 api->get_keys = &sqlite_plugin_get_keys;
1253 api->drop = &sqlite_plugin_drop; 1460 api->drop = &sqlite_plugin_drop;
1254 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "sqlite", 1461 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
1462 "sqlite",
1255 _("Sqlite database running\n")); 1463 _("Sqlite database running\n"));
1256 return api; 1464 return api;
1257} 1465}
@@ -1270,13 +1478,12 @@ libgnunet_plugin_datastore_sqlite_done (void *cls)
1270 struct GNUNET_DATASTORE_PluginFunctions *api = cls; 1478 struct GNUNET_DATASTORE_PluginFunctions *api = cls;
1271 struct Plugin *plugin = api->cls; 1479 struct Plugin *plugin = api->cls;
1272 1480
1273 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", 1481 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1482 "sqlite",
1274 "sqlite plugin is done\n"); 1483 "sqlite plugin is done\n");
1275 fn = NULL; 1484 fn = NULL;
1276 if (plugin->drop_on_shutdown) 1485 if (plugin->drop_on_shutdown)
1277 fn = GNUNET_strdup (plugin->fn); 1486 fn = GNUNET_strdup (plugin->fn);
1278 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
1279 "Shutting down database\n");
1280 database_shutdown (plugin); 1487 database_shutdown (plugin);
1281 plugin->env = NULL; 1488 plugin->env = NULL;
1282 GNUNET_free (api); 1489 GNUNET_free (api);
@@ -1288,9 +1495,6 @@ libgnunet_plugin_datastore_sqlite_done (void *cls)
1288 fn); 1495 fn);
1289 GNUNET_free (fn); 1496 GNUNET_free (fn);
1290 } 1497 }
1291 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1292 "sqlite",
1293 "sqlite plugin is finished\n");
1294 return NULL; 1498 return NULL;
1295} 1499}
1296 1500
diff --git a/src/include/gnunet_sq_lib.h b/src/include/gnunet_sq_lib.h
index 4d2510ee5..c196d7767 100644
--- a/src/include/gnunet_sq_lib.h
+++ b/src/include/gnunet_sq_lib.h
@@ -194,6 +194,17 @@ GNUNET_SQ_bind (sqlite3_stmt *stmt,
194 194
195 195
196/** 196/**
197 * Reset @a stmt and log error.
198 *
199 * @param dbh database handle
200 * @param stmt statement to reset
201 */
202void
203GNUNET_SQ_reset (sqlite3 *dbh,
204 sqlite3_stmt *stmt);
205
206
207/**
197 * Extract data from a Postgres database @a result at row @a row. 208 * Extract data from a Postgres database @a result at row @a row.
198 * 209 *
199 * @param cls closure 210 * @param cls closure
diff --git a/src/revocation/test_revocation.c b/src/revocation/test_revocation.c
index d3bbb879a..8d5593694 100644
--- a/src/revocation/test_revocation.c
+++ b/src/revocation/test_revocation.c
@@ -104,8 +104,8 @@ revocation_remote_cb (void *cls,
104 104
105 if (GNUNET_NO == is_valid) 105 if (GNUNET_NO == is_valid)
106 { 106 {
107 fprintf (stderr, 107 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
108 "Local revocation successful\n"); 108 "Local revocation successful\n");
109 ok = 0; 109 ok = 0;
110 GNUNET_SCHEDULER_shutdown (); 110 GNUNET_SCHEDULER_shutdown ();
111 return; 111 return;
@@ -118,8 +118,8 @@ revocation_remote_cb (void *cls,
118 NULL); 118 NULL);
119 return; 119 return;
120 } 120 }
121 fprintf (stderr, 121 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
122 "Flooding of revocation failed\n"); 122 "Flooding of revocation failed\n");
123 ok = 2; 123 ok = 2;
124 GNUNET_SCHEDULER_shutdown (); 124 GNUNET_SCHEDULER_shutdown ();
125} 125}
@@ -141,8 +141,8 @@ revocation_cb (void *cls,
141 testpeers[1].revok_handle = NULL; 141 testpeers[1].revok_handle = NULL;
142 if (GNUNET_NO == is_valid) 142 if (GNUNET_NO == is_valid)
143 { 143 {
144 fprintf (stderr, 144 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
145 "Revocation successful\n"); 145 "Revocation successful\n");
146 check_revocation (NULL); 146 check_revocation (NULL);
147 } 147 }
148} 148}
@@ -386,8 +386,8 @@ test_connection (void *cls,
386 /* We are generating a CLIQUE */ 386 /* We are generating a CLIQUE */
387 if (NUM_TEST_PEERS * (NUM_TEST_PEERS -1) == links_succeeded) 387 if (NUM_TEST_PEERS * (NUM_TEST_PEERS -1) == links_succeeded)
388 { 388 {
389 fprintf (stderr, 389 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
390 "Testbed connected peers, initializing test\n"); 390 "Testbed connected peers, initializing test\n");
391 for (c = 0; c < num_peers; c++) 391 for (c = 0; c < num_peers; c++)
392 { 392 {
393 testpeers[c].p = peers[c]; 393 testpeers[c].p = peers[c];
@@ -403,8 +403,8 @@ test_connection (void *cls,
403 } 403 }
404 else 404 else
405 { 405 {
406 fprintf (stderr, 406 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
407 "Testbed failed to connect peers\n"); 407 "Testbed failed to connect peers\n");
408 ok = 5; 408 ok = 5;
409 GNUNET_SCHEDULER_shutdown (); 409 GNUNET_SCHEDULER_shutdown ();
410 return; 410 return;
diff --git a/src/set/Makefile.am b/src/set/Makefile.am
index cfe95bc1a..03c258352 100644
--- a/src/set/Makefile.am
+++ b/src/set/Makefile.am
@@ -51,7 +51,7 @@ gnunet_set_ibf_profiler_LDADD = \
51 51
52gnunet_service_set_SOURCES = \ 52gnunet_service_set_SOURCES = \
53 gnunet-service-set.c gnunet-service-set.h \ 53 gnunet-service-set.c gnunet-service-set.h \
54 gnunet-service-set_union.c \ 54 gnunet-service-set_union.c gnunet-service-set_union.h \
55 gnunet-service-set_intersection.c \ 55 gnunet-service-set_intersection.c \
56 ibf.c ibf.h \ 56 ibf.c ibf.h \
57 gnunet-service-set_union_strata_estimator.c gnunet-service-set_union_strata_estimator.h \ 57 gnunet-service-set_union_strata_estimator.c gnunet-service-set_union_strata_estimator.h \
diff --git a/src/set/gnunet-service-set.c b/src/set/gnunet-service-set.c
index 454ad9784..8f1506c6a 100644
--- a/src/set/gnunet-service-set.c
+++ b/src/set/gnunet-service-set.c
@@ -24,6 +24,8 @@
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 */ 25 */
26#include "gnunet-service-set.h" 26#include "gnunet-service-set.h"
27#include "gnunet-service-set_union.h"
28#include "gnunet-service-set_intersection.h"
27#include "gnunet-service-set_protocol.h" 29#include "gnunet-service-set_protocol.h"
28#include "gnunet_statistics_service.h" 30#include "gnunet_statistics_service.h"
29 31
@@ -476,6 +478,7 @@ _GSS_operation_destroy (struct Operation *op,
476 op->channel = NULL; 478 op->channel = NULL;
477 GNUNET_CADET_channel_destroy (channel); 479 GNUNET_CADET_channel_destroy (channel);
478 } 480 }
481
479 if (GNUNET_YES == gc) 482 if (GNUNET_YES == gc)
480 collect_generation_garbage (set); 483 collect_generation_garbage (set);
481 /* We rely on the channel end handler to free 'op'. When 'op->channel' was NULL, 484 /* We rely on the channel end handler to free 'op'. When 'op->channel' was NULL,
@@ -682,7 +685,7 @@ client_disconnect_cb (void *cls,
682 { 685 {
683 struct Operation *curr = op; 686 struct Operation *curr = op;
684 op = op->next; 687 op = op->next;
685 if ( (GNUNET_YES == curr->is_incoming) && 688 if ( (GNUNET_YES == curr->is_incoming) &&
686 (curr->listener == listener) ) 689 (curr->listener == listener) )
687 incoming_destroy (curr); 690 incoming_destroy (curr);
688 } 691 }
@@ -733,6 +736,38 @@ incoming_suggest (struct Operation *incoming,
733 736
734 737
735/** 738/**
739 * Check a request for a set operation from another peer.
740 *
741 * @param cls the operation state
742 * @param msg the received message
743 * @return #GNUNET_OK if the channel should be kept alive,
744 * #GNUNET_SYSERR to destroy the channel
745 */
746static int
747check_incoming_msg (void *cls,
748 const struct OperationRequestMessage *msg)
749{
750 struct Operation *op = cls;
751 const struct GNUNET_MessageHeader *nested_context;
752
753 /* double operation request */
754 if (NULL != op->spec)
755 {
756 GNUNET_break_op (0);
757 return GNUNET_SYSERR;
758 }
759 nested_context = GNUNET_MQ_extract_nested_mh (msg);
760 if ( (NULL != nested_context) &&
761 (ntohs (nested_context->size) > GNUNET_SET_CONTEXT_MESSAGE_MAX_SIZE) )
762 {
763 GNUNET_break_op (0);
764 return GNUNET_SYSERR;
765 }
766 return GNUNET_OK;
767}
768
769
770/**
736 * Handle a request for a set operation from another peer. Checks if we 771 * Handle a request for a set operation from another peer. Checks if we
737 * have a listener waiting for such a request (and in that case initiates 772 * have a listener waiting for such a request (and in that case initiates
738 * asking the listener about accepting the connection). If no listener 773 * asking the listener about accepting the connection). If no listener
@@ -744,42 +779,23 @@ incoming_suggest (struct Operation *incoming,
744 * our virtual table and subsequent msgs would be routed differently (as 779 * our virtual table and subsequent msgs would be routed differently (as
745 * we then know what type of operation this is). 780 * we then know what type of operation this is).
746 * 781 *
747 * @param op the operation state 782 * @param cls the operation state
748 * @param mh the received message 783 * @param msg the received message
749 * @return #GNUNET_OK if the channel should be kept alive, 784 * @return #GNUNET_OK if the channel should be kept alive,
750 * #GNUNET_SYSERR to destroy the channel 785 * #GNUNET_SYSERR to destroy the channel
751 */ 786 */
752static int 787static void
753handle_incoming_msg (struct Operation *op, 788handle_incoming_msg (void *cls,
754 const struct GNUNET_MessageHeader *mh) 789 const struct OperationRequestMessage *msg)
755{ 790{
756 const struct OperationRequestMessage *msg; 791 struct Operation *op = cls;
757 struct Listener *listener = op->listener; 792 struct Listener *listener = op->listener;
758 struct OperationSpecification *spec; 793 struct OperationSpecification *spec;
759 const struct GNUNET_MessageHeader *nested_context; 794 const struct GNUNET_MessageHeader *nested_context;
760 795
761 msg = (const struct OperationRequestMessage *) mh;
762 GNUNET_assert (GNUNET_YES == op->is_incoming); 796 GNUNET_assert (GNUNET_YES == op->is_incoming);
763 if (GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST != ntohs (mh->type))
764 {
765 GNUNET_break_op (0);
766 return GNUNET_SYSERR;
767 }
768 /* double operation request */
769 if (NULL != op->spec)
770 {
771 GNUNET_break_op (0);
772 return GNUNET_SYSERR;
773 }
774 spec = GNUNET_new (struct OperationSpecification); 797 spec = GNUNET_new (struct OperationSpecification);
775 nested_context = GNUNET_MQ_extract_nested_mh (msg); 798 nested_context = GNUNET_MQ_extract_nested_mh (msg);
776 if ( (NULL != nested_context) &&
777 (ntohs (nested_context->size) > GNUNET_SET_CONTEXT_MESSAGE_MAX_SIZE) )
778 {
779 GNUNET_break_op (0);
780 GNUNET_free (spec);
781 return GNUNET_SYSERR;
782 }
783 /* Make a copy of the nested_context (application-specific context 799 /* Make a copy of the nested_context (application-specific context
784 information that is opaque to set) so we can pass it to the 800 information that is opaque to set) so we can pass it to the
785 listener later on */ 801 listener later on */
@@ -792,7 +808,6 @@ handle_incoming_msg (struct Operation *op,
792 spec->peer = op->peer; 808 spec->peer = op->peer;
793 spec->remote_element_count = ntohl (msg->element_count); 809 spec->remote_element_count = ntohl (msg->element_count);
794 op->spec = spec; 810 op->spec = spec;
795
796 listener = op->listener; 811 listener = op->listener;
797 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 812 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
798 "Received P2P operation request (op %u, port %s) for active listener\n", 813 "Received P2P operation request (op %u, port %s) for active listener\n",
@@ -800,7 +815,6 @@ handle_incoming_msg (struct Operation *op,
800 GNUNET_h2s (&listener->app_id)); 815 GNUNET_h2s (&listener->app_id));
801 incoming_suggest (op, 816 incoming_suggest (op,
802 listener); 817 listener);
803 return GNUNET_OK;
804} 818}
805 819
806 820
@@ -1103,9 +1117,11 @@ handle_client_create_set (void *cls,
1103 { 1117 {
1104 case GNUNET_SET_OPERATION_INTERSECTION: 1118 case GNUNET_SET_OPERATION_INTERSECTION:
1105 set->vt = _GSS_intersection_vt (); 1119 set->vt = _GSS_intersection_vt ();
1120 set->type = OT_INTERSECTION;
1106 break; 1121 break;
1107 case GNUNET_SET_OPERATION_UNION: 1122 case GNUNET_SET_OPERATION_UNION:
1108 set->vt = _GSS_union_vt (); 1123 set->vt = _GSS_union_vt ();
1124 set->type = OT_UNION;
1109 break; 1125 break;
1110 default: 1126 default:
1111 GNUNET_free (set); 1127 GNUNET_free (set);
@@ -1196,7 +1212,6 @@ channel_new_cb (void *cls,
1196 const struct GNUNET_PeerIdentity *source) 1212 const struct GNUNET_PeerIdentity *source)
1197{ 1213{
1198 static const struct SetVT incoming_vt = { 1214 static const struct SetVT incoming_vt = {
1199 .msg_handler = &handle_incoming_msg,
1200 .peer_disconnect = &handle_incoming_disconnect 1215 .peer_disconnect = &handle_incoming_disconnect
1201 }; 1216 };
1202 struct Listener *listener = cls; 1217 struct Listener *listener = cls;
@@ -1290,60 +1305,6 @@ channel_window_cb (void *cls,
1290 /* FIXME: not implemented, we could do flow control here... */ 1305 /* FIXME: not implemented, we could do flow control here... */
1291} 1306}
1292 1307
1293/**
1294 * FIXME: hack-job. Migrate to proper handler array use!
1295 *
1296 * @param cls local state associated with the channel.
1297 * @param message The actual message.
1298 */
1299static int
1300check_p2p_message (void *cls,
1301 const struct GNUNET_MessageHeader *message)
1302{
1303 return GNUNET_OK;
1304}
1305
1306
1307/**
1308 * FIXME: hack-job. Migrate to proper handler array use!
1309 *
1310 * Functions with this signature are called whenever a message is
1311 * received via a cadet channel.
1312 *
1313 * The msg_handler is a virtual table set in initially either when a peer
1314 * creates a new channel with us, or once we create a new channel
1315 * ourselves (evaluate).
1316 *
1317 * Once we know the exact type of operation (union/intersection), the vt is
1318 * replaced with an operation specific instance (_GSS_[op]_vt).
1319 *
1320 * @param cls local state associated with the channel.
1321 * @param message The actual message.
1322 */
1323static void
1324handle_p2p_message (void *cls,
1325 const struct GNUNET_MessageHeader *message)
1326{
1327 struct Operation *op = cls;
1328 int ret;
1329
1330 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1331 "Dispatching cadet message (type: %u)\n",
1332 ntohs (message->type));
1333 /* do this before the handler, as the handler might kill the channel */
1334 GNUNET_CADET_receive_done (op->channel);
1335 if (NULL != op->vt)
1336 ret = op->vt->msg_handler (op,
1337 message);
1338 else
1339 ret = GNUNET_SYSERR;
1340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1341 "Handled cadet message (type: %u)\n",
1342 ntohs (message->type));
1343 if (GNUNET_OK != ret)
1344 GNUNET_CADET_channel_destroy (op->channel);
1345}
1346
1347 1308
1348/** 1309/**
1349 * Called when a client wants to create a new listener. 1310 * Called when a client wants to create a new listener.
@@ -1357,66 +1318,66 @@ handle_client_listen (void *cls,
1357{ 1318{
1358 struct GNUNET_SERVICE_Client *client = cls; 1319 struct GNUNET_SERVICE_Client *client = cls;
1359 struct GNUNET_MQ_MessageHandler cadet_handlers[] = { 1320 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1360 GNUNET_MQ_hd_var_size (p2p_message, 1321 GNUNET_MQ_hd_var_size (incoming_msg,
1361 GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST, 1322 GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST,
1362 struct GNUNET_MessageHeader, 1323 struct OperationRequestMessage,
1363 NULL), 1324 NULL),
1364 GNUNET_MQ_hd_var_size (p2p_message, 1325 GNUNET_MQ_hd_var_size (union_p2p_ibf,
1365 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF, 1326 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF,
1366 struct GNUNET_MessageHeader, 1327 struct IBFMessage,
1367 NULL), 1328 NULL),
1368 GNUNET_MQ_hd_var_size (p2p_message, 1329 GNUNET_MQ_hd_var_size (union_p2p_elements,
1369 GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS, 1330 GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS,
1370 struct GNUNET_MessageHeader, 1331 struct GNUNET_SET_ElementMessage,
1371 NULL), 1332 NULL),
1372 GNUNET_MQ_hd_var_size (p2p_message, 1333 GNUNET_MQ_hd_var_size (union_p2p_offer,
1373 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_OFFER, 1334 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_OFFER,
1374 struct GNUNET_MessageHeader, 1335 struct GNUNET_MessageHeader,
1375 NULL), 1336 NULL),
1376 GNUNET_MQ_hd_var_size (p2p_message, 1337 GNUNET_MQ_hd_var_size (union_p2p_inquiry,
1377 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_INQUIRY, 1338 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_INQUIRY,
1378 struct GNUNET_MessageHeader, 1339 struct InquiryMessage,
1379 NULL), 1340 NULL),
1380 GNUNET_MQ_hd_var_size (p2p_message, 1341 GNUNET_MQ_hd_var_size (union_p2p_demand,
1381 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND, 1342 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND,
1382 struct GNUNET_MessageHeader, 1343 struct GNUNET_MessageHeader,
1383 NULL), 1344 NULL),
1384 GNUNET_MQ_hd_var_size (p2p_message, 1345 GNUNET_MQ_hd_fixed_size (union_p2p_done,
1385 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE, 1346 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE,
1386 struct GNUNET_MessageHeader, 1347 struct GNUNET_MessageHeader,
1387 NULL), 1348 NULL),
1388 GNUNET_MQ_hd_var_size (p2p_message, 1349 GNUNET_MQ_hd_fixed_size (union_p2p_full_done,
1389 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE, 1350 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE,
1390 struct GNUNET_MessageHeader, 1351 struct GNUNET_MessageHeader,
1391 NULL), 1352 NULL),
1392 GNUNET_MQ_hd_var_size (p2p_message, 1353 GNUNET_MQ_hd_fixed_size (union_p2p_request_full,
1393 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL, 1354 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL,
1394 struct GNUNET_MessageHeader, 1355 struct GNUNET_MessageHeader,
1395 NULL), 1356 NULL),
1396 GNUNET_MQ_hd_var_size (p2p_message, 1357 GNUNET_MQ_hd_var_size (union_p2p_strata_estimator,
1397 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE, 1358 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE,
1398 struct GNUNET_MessageHeader, 1359 struct StrataEstimatorMessage,
1399 NULL), 1360 NULL),
1400 GNUNET_MQ_hd_var_size (p2p_message, 1361 GNUNET_MQ_hd_var_size (union_p2p_strata_estimator,
1401 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC, 1362 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC,
1402 struct GNUNET_MessageHeader, 1363 struct StrataEstimatorMessage,
1403 NULL), 1364 NULL),
1404 GNUNET_MQ_hd_var_size (p2p_message, 1365 GNUNET_MQ_hd_var_size (union_p2p_full_element,
1405 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT, 1366 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT,
1406 struct GNUNET_MessageHeader, 1367 struct GNUNET_SET_ElementMessage,
1407 NULL), 1368 NULL),
1408 GNUNET_MQ_hd_var_size (p2p_message, 1369 GNUNET_MQ_hd_fixed_size (intersection_p2p_element_info,
1409 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO, 1370 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO,
1410 struct GNUNET_MessageHeader, 1371 struct IntersectionElementInfoMessage,
1411 NULL), 1372 NULL),
1412 GNUNET_MQ_hd_var_size (p2p_message, 1373 GNUNET_MQ_hd_var_size (intersection_p2p_bf,
1413 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF, 1374 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF,
1414 struct GNUNET_MessageHeader, 1375 struct BFMessage,
1415 NULL),
1416 GNUNET_MQ_hd_var_size (p2p_message,
1417 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_DONE,
1418 struct GNUNET_MessageHeader,
1419 NULL), 1376 NULL),
1377 GNUNET_MQ_hd_fixed_size (intersection_p2p_done,
1378 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_DONE,
1379 struct IntersectionDoneMessage,
1380 NULL),
1420 GNUNET_MQ_handler_end () 1381 GNUNET_MQ_handler_end ()
1421 }; 1382 };
1422 struct Listener *listener; 1383 struct Listener *listener;
@@ -1623,66 +1584,66 @@ handle_client_evaluate (void *cls,
1623 struct GNUNET_SERVICE_Client *client = cls; 1584 struct GNUNET_SERVICE_Client *client = cls;
1624 struct Operation *op = GNUNET_new (struct Operation); 1585 struct Operation *op = GNUNET_new (struct Operation);
1625 const struct GNUNET_MQ_MessageHandler cadet_handlers[] = { 1586 const struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1626 GNUNET_MQ_hd_var_size (p2p_message, 1587 GNUNET_MQ_hd_var_size (incoming_msg,
1627 GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST, 1588 GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST,
1628 struct GNUNET_MessageHeader, 1589 struct OperationRequestMessage,
1629 op), 1590 op),
1630 GNUNET_MQ_hd_var_size (p2p_message, 1591 GNUNET_MQ_hd_var_size (union_p2p_ibf,
1631 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF, 1592 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF,
1632 struct GNUNET_MessageHeader, 1593 struct IBFMessage,
1633 op), 1594 op),
1634 GNUNET_MQ_hd_var_size (p2p_message, 1595 GNUNET_MQ_hd_var_size (union_p2p_elements,
1635 GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS, 1596 GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS,
1636 struct GNUNET_MessageHeader, 1597 struct GNUNET_SET_ElementMessage,
1637 op), 1598 op),
1638 GNUNET_MQ_hd_var_size (p2p_message, 1599 GNUNET_MQ_hd_var_size (union_p2p_offer,
1639 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_OFFER, 1600 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_OFFER,
1640 struct GNUNET_MessageHeader, 1601 struct GNUNET_MessageHeader,
1641 op), 1602 op),
1642 GNUNET_MQ_hd_var_size (p2p_message, 1603 GNUNET_MQ_hd_var_size (union_p2p_inquiry,
1643 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_INQUIRY, 1604 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_INQUIRY,
1644 struct GNUNET_MessageHeader, 1605 struct InquiryMessage,
1645 op), 1606 op),
1646 GNUNET_MQ_hd_var_size (p2p_message, 1607 GNUNET_MQ_hd_var_size (union_p2p_demand,
1647 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND, 1608 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND,
1648 struct GNUNET_MessageHeader, 1609 struct GNUNET_MessageHeader,
1649 op), 1610 op),
1650 GNUNET_MQ_hd_var_size (p2p_message, 1611 GNUNET_MQ_hd_fixed_size (union_p2p_done,
1651 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE, 1612 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE,
1652 struct GNUNET_MessageHeader, 1613 struct GNUNET_MessageHeader,
1653 op), 1614 op),
1654 GNUNET_MQ_hd_var_size (p2p_message, 1615 GNUNET_MQ_hd_fixed_size (union_p2p_full_done,
1616 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE,
1617 struct GNUNET_MessageHeader,
1618 op),
1619 GNUNET_MQ_hd_fixed_size (union_p2p_request_full,
1620 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL,
1621 struct GNUNET_MessageHeader,
1622 op),
1623 GNUNET_MQ_hd_var_size (union_p2p_strata_estimator,
1655 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE, 1624 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE,
1656 struct GNUNET_MessageHeader, 1625 struct StrataEstimatorMessage,
1657 op), 1626 op),
1658 GNUNET_MQ_hd_var_size (p2p_message, 1627 GNUNET_MQ_hd_var_size (union_p2p_strata_estimator,
1659 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC, 1628 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC,
1660 struct GNUNET_MessageHeader, 1629 struct StrataEstimatorMessage,
1661 op),
1662 GNUNET_MQ_hd_var_size (p2p_message,
1663 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE,
1664 struct GNUNET_MessageHeader,
1665 op),
1666 GNUNET_MQ_hd_var_size (p2p_message,
1667 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL,
1668 struct GNUNET_MessageHeader,
1669 op), 1630 op),
1670 GNUNET_MQ_hd_var_size (p2p_message, 1631 GNUNET_MQ_hd_var_size (union_p2p_full_element,
1671 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT, 1632 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT,
1672 struct GNUNET_MessageHeader, 1633 struct GNUNET_SET_ElementMessage,
1673 op),
1674 GNUNET_MQ_hd_var_size (p2p_message,
1675 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO,
1676 struct GNUNET_MessageHeader,
1677 op), 1634 op),
1678 GNUNET_MQ_hd_var_size (p2p_message, 1635 GNUNET_MQ_hd_fixed_size (intersection_p2p_element_info,
1636 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO,
1637 struct IntersectionElementInfoMessage,
1638 op),
1639 GNUNET_MQ_hd_var_size (intersection_p2p_bf,
1679 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF, 1640 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF,
1680 struct GNUNET_MessageHeader, 1641 struct BFMessage,
1681 op),
1682 GNUNET_MQ_hd_var_size (p2p_message,
1683 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_DONE,
1684 struct GNUNET_MessageHeader,
1685 op), 1642 op),
1643 GNUNET_MQ_hd_fixed_size (intersection_p2p_done,
1644 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_DONE,
1645 struct IntersectionDoneMessage,
1646 op),
1686 GNUNET_MQ_handler_end () 1647 GNUNET_MQ_handler_end ()
1687 }; 1648 };
1688 struct Set *set; 1649 struct Set *set;
@@ -1717,7 +1678,7 @@ handle_client_evaluate (void *cls,
1717 // mutations won't interfer with the running operation. 1678 // mutations won't interfer with the running operation.
1718 op->generation_created = set->current_generation; 1679 op->generation_created = set->current_generation;
1719 advance_generation (set); 1680 advance_generation (set);
1720 1681 op->type = set->type;
1721 op->vt = set->vt; 1682 op->vt = set->vt;
1722 GNUNET_CONTAINER_DLL_insert (set->ops_head, 1683 GNUNET_CONTAINER_DLL_insert (set->ops_head,
1723 set->ops_tail, 1684 set->ops_tail,
@@ -1886,9 +1847,11 @@ handle_client_copy_lazy_connect (void *cls,
1886 { 1847 {
1887 case GNUNET_SET_OPERATION_INTERSECTION: 1848 case GNUNET_SET_OPERATION_INTERSECTION:
1888 set->vt = _GSS_intersection_vt (); 1849 set->vt = _GSS_intersection_vt ();
1850 set->type = OT_INTERSECTION;
1889 break; 1851 break;
1890 case GNUNET_SET_OPERATION_UNION: 1852 case GNUNET_SET_OPERATION_UNION:
1891 set->vt = _GSS_union_vt (); 1853 set->vt = _GSS_union_vt ();
1854 set->type = OT_UNION;
1892 break; 1855 break;
1893 default: 1856 default:
1894 GNUNET_assert (0); 1857 GNUNET_assert (0);
@@ -2057,6 +2020,7 @@ handle_client_accept (void *cls,
2057 advance_generation (set); 2020 advance_generation (set);
2058 2021
2059 op->vt = set->vt; 2022 op->vt = set->vt;
2023 op->type = set->type;
2060 op->vt->accept (op); 2024 op->vt->accept (op);
2061 GNUNET_SERVICE_client_continue (client); 2025 GNUNET_SERVICE_client_continue (client);
2062} 2026}
diff --git a/src/set/gnunet-service-set.h b/src/set/gnunet-service-set.h
index 68d8fe81f..c981430ef 100644
--- a/src/set/gnunet-service-set.h
+++ b/src/set/gnunet-service-set.h
@@ -213,20 +213,6 @@ typedef void
213 213
214 214
215/** 215/**
216 * Signature of functions that implement the message handling for
217 * the different set operations.
218 *
219 * @param op operation state
220 * @param msg received message
221 * @return #GNUNET_OK on success, #GNUNET_SYSERR to
222 * destroy the operation and the tunnel
223 */
224typedef int
225(*MsgHandlerImpl) (struct Operation *op,
226 const struct GNUNET_MessageHeader *msg);
227
228
229/**
230 * Signature of functions that implement operation cancellation 216 * Signature of functions that implement operation cancellation
231 * 217 *
232 * @param op operation state 218 * @param op operation state
@@ -276,11 +262,6 @@ struct SetVT
276 DestroySetImpl destroy_set; 262 DestroySetImpl destroy_set;
277 263
278 /** 264 /**
279 * Callback for handling operation-specific messages.
280 */
281 MsgHandlerImpl msg_handler;
282
283 /**
284 * Callback for handling the remote peer's disconnect. 265 * Callback for handling the remote peer's disconnect.
285 */ 266 */
286 PeerDisconnectImpl peer_disconnect; 267 PeerDisconnectImpl peer_disconnect;
@@ -364,6 +345,27 @@ struct Listener;
364 345
365 346
366/** 347/**
348 * Possible set operations.
349 */
350enum OperationType {
351 /**
352 * Operation type unknown.
353 */
354 OT_UNKNOWN = 0,
355
356 /**
357 * We are performing a union.
358 */
359 OT_UNION,
360
361 /**
362 * We are performing an intersection.
363 */
364 OT_INTERSECTION
365};
366
367
368/**
367 * Operation context used to execute a set operation. 369 * Operation context used to execute a set operation.
368 */ 370 */
369struct Operation 371struct Operation
@@ -427,6 +429,11 @@ struct Operation
427 struct GNUNET_SCHEDULER_Task *timeout_task; 429 struct GNUNET_SCHEDULER_Task *timeout_task;
428 430
429 /** 431 /**
432 * What type of operation is this?
433 */
434 enum OperationType type;
435
436 /**
430 * Unique request id for the request from a remote peer, sent to the 437 * Unique request id for the request from a remote peer, sent to the
431 * client, which will accept or reject the request. Set to '0' iff 438 * client, which will accept or reject the request. Set to '0' iff
432 * the request has not been suggested yet. 439 * the request has not been suggested yet.
@@ -582,6 +589,11 @@ struct Set
582 struct Operation *ops_tail; 589 struct Operation *ops_tail;
583 590
584 /** 591 /**
592 * What type of operation is this set for?
593 */
594 enum OperationType type;
595
596 /**
585 * Current generation, that is, number of previously executed 597 * Current generation, that is, number of previously executed
586 * operations and lazy copies on the underlying set content. 598 * operations and lazy copies on the underlying set content.
587 */ 599 */
diff --git a/src/set/gnunet-service-set_intersection.c b/src/set/gnunet-service-set_intersection.c
index 9fe1eabe6..b298f7b41 100644
--- a/src/set/gnunet-service-set_intersection.c
+++ b/src/set/gnunet-service-set_intersection.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2013, 2014 GNUnet e.V. 3 Copyright (C) 2013-2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -28,6 +28,7 @@
28#include "gnunet-service-set.h" 28#include "gnunet-service-set.h"
29#include "gnunet_block_lib.h" 29#include "gnunet_block_lib.h"
30#include "gnunet-service-set_protocol.h" 30#include "gnunet-service-set_protocol.h"
31#include "gnunet-service-set_intersection.h"
31#include <gcrypt.h> 32#include <gcrypt.h>
32 33
33 34
@@ -550,6 +551,8 @@ send_remaining_elements (void *cls)
550 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 551 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
551 "Sending done and destroy because iterator ran out\n"); 552 "Sending done and destroy because iterator ran out\n");
552 op->keep--; 553 op->keep--;
554 GNUNET_CONTAINER_multihashmap_iterator_destroy (op->state->full_result_iter);
555 op->state->full_result_iter = NULL;
553 send_client_done_and_destroy (op); 556 send_client_done_and_destroy (op);
554 return; 557 return;
555 } 558 }
@@ -627,9 +630,6 @@ process_bf (struct Operation *op)
627 case PHASE_COUNT_SENT: 630 case PHASE_COUNT_SENT:
628 /* This is the first BF being sent, build our initial map with 631 /* This is the first BF being sent, build our initial map with
629 filtering in place */ 632 filtering in place */
630 op->state->my_elements
631 = GNUNET_CONTAINER_multihashmap_create (op->spec->remote_element_count,
632 GNUNET_YES);
633 op->state->my_element_count = 0; 633 op->state->my_element_count = 0;
634 GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->content->elements, 634 GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->content->elements,
635 &filtered_map_initialization, 635 &filtered_map_initialization,
@@ -665,41 +665,53 @@ process_bf (struct Operation *op)
665 665
666 666
667/** 667/**
668 * Check an BF message from a remote peer.
669 *
670 * @param cls the intersection operation
671 * @param msg the header of the message
672 * @return #GNUNET_OK if @a msg is well-formed
673 */
674int
675check_intersection_p2p_bf (void *cls,
676 const struct BFMessage *msg)
677{
678 struct Operation *op = cls;
679
680 if (OT_INTERSECTION != op->type)
681 {
682 GNUNET_break_op (0);
683 return GNUNET_SYSERR;
684 }
685 return GNUNET_OK;
686}
687
688
689/**
668 * Handle an BF message from a remote peer. 690 * Handle an BF message from a remote peer.
669 * 691 *
670 * @param cls the intersection operation 692 * @param cls the intersection operation
671 * @param mh the header of the message 693 * @param msg the header of the message
672 */ 694 */
673static void 695void
674handle_p2p_bf (void *cls, 696handle_intersection_p2p_bf (void *cls,
675 const struct GNUNET_MessageHeader *mh) 697 const struct BFMessage *msg)
676{ 698{
677 struct Operation *op = cls; 699 struct Operation *op = cls;
678 const struct BFMessage *msg;
679 uint32_t bf_size; 700 uint32_t bf_size;
680 uint32_t chunk_size; 701 uint32_t chunk_size;
681 uint32_t bf_bits_per_element; 702 uint32_t bf_bits_per_element;
682 uint16_t msize;
683 703
684 msize = htons (mh->size);
685 if (msize < sizeof (struct BFMessage))
686 {
687 GNUNET_break_op (0);
688 fail_intersection_operation (op);
689 return;
690 }
691 msg = (const struct BFMessage *) mh;
692 switch (op->state->phase) 704 switch (op->state->phase)
693 { 705 {
694 case PHASE_INITIAL: 706 case PHASE_INITIAL:
695 GNUNET_break_op (0); 707 GNUNET_break_op (0);
696 fail_intersection_operation (op); 708 fail_intersection_operation (op);
697 break; 709 return;
698 case PHASE_COUNT_SENT: 710 case PHASE_COUNT_SENT:
699 case PHASE_BF_EXCHANGE: 711 case PHASE_BF_EXCHANGE:
700 bf_size = ntohl (msg->bloomfilter_total_length); 712 bf_size = ntohl (msg->bloomfilter_total_length);
701 bf_bits_per_element = ntohl (msg->bits_per_element); 713 bf_bits_per_element = ntohl (msg->bits_per_element);
702 chunk_size = msize - sizeof (struct BFMessage); 714 chunk_size = htons (msg->header.size) - sizeof (struct BFMessage);
703 op->state->other_xor = msg->element_xor_hash; 715 op->state->other_xor = msg->element_xor_hash;
704 if (bf_size == chunk_size) 716 if (bf_size == chunk_size)
705 { 717 {
@@ -717,7 +729,7 @@ handle_p2p_bf (void *cls,
717 op->state->salt = ntohl (msg->sender_mutator); 729 op->state->salt = ntohl (msg->sender_mutator);
718 op->spec->remote_element_count = ntohl (msg->sender_element_count); 730 op->spec->remote_element_count = ntohl (msg->sender_element_count);
719 process_bf (op); 731 process_bf (op);
720 return; 732 break;
721 } 733 }
722 /* multipart chunk */ 734 /* multipart chunk */
723 if (NULL == op->state->bf_data) 735 if (NULL == op->state->bf_data)
@@ -764,8 +776,9 @@ handle_p2p_bf (void *cls,
764 default: 776 default:
765 GNUNET_break_op (0); 777 GNUNET_break_op (0);
766 fail_intersection_operation (op); 778 fail_intersection_operation (op);
767 break; 779 return;
768 } 780 }
781 GNUNET_CADET_receive_done (op->channel);
769} 782}
770 783
771 784
@@ -836,6 +849,7 @@ static void
836begin_bf_exchange (struct Operation *op) 849begin_bf_exchange (struct Operation *op)
837{ 850{
838 op->state->phase = PHASE_BF_EXCHANGE; 851 op->state->phase = PHASE_BF_EXCHANGE;
852 GNUNET_assert (NULL == op->state->my_elements);
839 op->state->my_elements 853 op->state->my_elements
840 = GNUNET_CONTAINER_multihashmap_create (op->state->my_element_count, 854 = GNUNET_CONTAINER_multihashmap_create (op->state->my_element_count,
841 GNUNET_YES); 855 GNUNET_YES);
@@ -853,20 +867,18 @@ begin_bf_exchange (struct Operation *op)
853 * @param cls the intersection operation 867 * @param cls the intersection operation
854 * @param mh the header of the message 868 * @param mh the header of the message
855 */ 869 */
856static void 870void
857handle_p2p_element_info (void *cls, 871handle_intersection_p2p_element_info (void *cls,
858 const struct GNUNET_MessageHeader *mh) 872 const struct IntersectionElementInfoMessage *msg)
859{ 873{
860 struct Operation *op = cls; 874 struct Operation *op = cls;
861 const struct IntersectionElementInfoMessage *msg;
862 875
863 if (ntohs (mh->size) != sizeof (struct IntersectionElementInfoMessage)) 876 if (OT_INTERSECTION != op->type)
864 { 877 {
865 GNUNET_break_op (0); 878 GNUNET_break_op (0);
866 fail_intersection_operation(op); 879 fail_intersection_operation(op);
867 return; 880 return;
868 } 881 }
869 msg = (const struct IntersectionElementInfoMessage *) mh;
870 op->spec->remote_element_count = ntohl (msg->sender_element_count); 882 op->spec->remote_element_count = ntohl (msg->sender_element_count);
871 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 883 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
872 "Received remote element count (%u), I have %u\n", 884 "Received remote element count (%u), I have %u\n",
@@ -884,6 +896,7 @@ handle_p2p_element_info (void *cls,
884 } 896 }
885 GNUNET_break (NULL == op->state->remote_bf); 897 GNUNET_break (NULL == op->state->remote_bf);
886 begin_bf_exchange (op); 898 begin_bf_exchange (op);
899 GNUNET_CADET_receive_done (op->channel);
887} 900}
888 901
889 902
@@ -955,28 +968,26 @@ filter_all (void *cls,
955 * @param cls the intersection operation 968 * @param cls the intersection operation
956 * @param mh the message 969 * @param mh the message
957 */ 970 */
958static void 971void
959handle_p2p_done (void *cls, 972handle_intersection_p2p_done (void *cls,
960 const struct GNUNET_MessageHeader *mh) 973 const struct IntersectionDoneMessage *idm)
961{ 974{
962 struct Operation *op = cls; 975 struct Operation *op = cls;
963 const struct IntersectionDoneMessage *idm;
964 976
965 if (PHASE_BF_EXCHANGE != op->state->phase) 977 if (OT_INTERSECTION != op->type)
966 { 978 {
967 /* wrong phase to conclude? FIXME: Or should we allow this
968 if the other peer has _initially_ already an empty set? */
969 GNUNET_break_op (0); 979 GNUNET_break_op (0);
970 fail_intersection_operation (op); 980 fail_intersection_operation(op);
971 return; 981 return;
972 } 982 }
973 if (ntohs (mh->size) != sizeof (struct IntersectionDoneMessage)) 983 if (PHASE_BF_EXCHANGE != op->state->phase)
974 { 984 {
985 /* wrong phase to conclude? FIXME: Or should we allow this
986 if the other peer has _initially_ already an empty set? */
975 GNUNET_break_op (0); 987 GNUNET_break_op (0);
976 fail_intersection_operation (op); 988 fail_intersection_operation (op);
977 return; 989 return;
978 } 990 }
979 idm = (const struct IntersectionDoneMessage *) mh;
980 if (0 == ntohl (idm->final_element_count)) 991 if (0 == ntohl (idm->final_element_count))
981 { 992 {
982 /* other peer determined empty set is the intersection, 993 /* other peer determined empty set is the intersection,
@@ -1000,6 +1011,7 @@ handle_p2p_done (void *cls,
1000 op->state->my_element_count); 1011 op->state->my_element_count);
1001 op->state->phase = PHASE_FINISHED; 1012 op->state->phase = PHASE_FINISHED;
1002 finish_and_destroy (op); 1013 finish_and_destroy (op);
1014 GNUNET_CADET_receive_done (op->channel);
1003} 1015}
1004 1016
1005 1017
@@ -1064,11 +1076,11 @@ intersection_accept (struct Operation *op)
1064 op->state->phase = PHASE_INITIAL; 1076 op->state->phase = PHASE_INITIAL;
1065 op->state->my_element_count 1077 op->state->my_element_count
1066 = op->spec->set->state->current_set_element_count; 1078 = op->spec->set->state->current_set_element_count;
1079 GNUNET_assert (NULL == op->state->my_elements);
1067 op->state->my_elements 1080 op->state->my_elements
1068 = GNUNET_CONTAINER_multihashmap_create 1081 = GNUNET_CONTAINER_multihashmap_create (GNUNET_MIN (op->state->my_element_count,
1069 (GNUNET_MIN (op->state->my_element_count, 1082 op->spec->remote_element_count),
1070 op->spec->remote_element_count), 1083 GNUNET_YES);
1071 GNUNET_YES);
1072 if (op->spec->remote_element_count < op->state->my_element_count) 1084 if (op->spec->remote_element_count < op->state->my_element_count)
1073 { 1085 {
1074 /* If the other peer (Alice) has fewer elements than us (Bob), 1086 /* If the other peer (Alice) has fewer elements than us (Bob),
@@ -1083,43 +1095,6 @@ intersection_accept (struct Operation *op)
1083 1095
1084 1096
1085/** 1097/**
1086 * Dispatch messages for a intersection operation.
1087 *
1088 * @param op the state of the intersection evaluate operation
1089 * @param mh the received message
1090 * @return #GNUNET_SYSERR if the tunnel should be disconnected,
1091 * #GNUNET_OK otherwise
1092 */
1093static int
1094intersection_handle_p2p_message (struct Operation *op,
1095 const struct GNUNET_MessageHeader *mh)
1096{
1097 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1098 "Received p2p message (t: %u, s: %u)\n",
1099 ntohs (mh->type), ntohs (mh->size));
1100 switch (ntohs (mh->type))
1101 {
1102 /* this message handler is not active until after we received an
1103 * operation request message, thus the ops request is not handled here
1104 */
1105 case GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO:
1106 handle_p2p_element_info (op, mh);
1107 break;
1108 case GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF:
1109 handle_p2p_bf (op, mh);
1110 break;
1111 case GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_DONE:
1112 handle_p2p_done (op, mh);
1113 break;
1114 default:
1115 /* something wrong with cadet's message handlers? */
1116 GNUNET_assert (0);
1117 }
1118 return GNUNET_OK;
1119}
1120
1121
1122/**
1123 * Handler for peer-disconnects, notifies the client about the aborted 1098 * Handler for peer-disconnects, notifies the client about the aborted
1124 * operation. If we did not expect anything from the other peer, we 1099 * operation. If we did not expect anything from the other peer, we
1125 * gracefully terminate the operation. 1100 * gracefully terminate the operation.
@@ -1168,6 +1143,11 @@ intersection_op_cancel (struct Operation *op)
1168 GNUNET_CONTAINER_multihashmap_destroy (op->state->my_elements); 1143 GNUNET_CONTAINER_multihashmap_destroy (op->state->my_elements);
1169 op->state->my_elements = NULL; 1144 op->state->my_elements = NULL;
1170 } 1145 }
1146 if (NULL != op->state->full_result_iter)
1147 {
1148 GNUNET_CONTAINER_multihashmap_iterator_destroy (op->state->full_result_iter);
1149 op->state->full_result_iter = NULL;
1150 }
1171 GNUNET_free (op->state); 1151 GNUNET_free (op->state);
1172 op->state = NULL; 1152 op->state = NULL;
1173 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1153 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1245,7 +1225,6 @@ _GSS_intersection_vt ()
1245{ 1225{
1246 static const struct SetVT intersection_vt = { 1226 static const struct SetVT intersection_vt = {
1247 .create = &intersection_set_create, 1227 .create = &intersection_set_create,
1248 .msg_handler = &intersection_handle_p2p_message,
1249 .add = &intersection_add, 1228 .add = &intersection_add,
1250 .remove = &intersection_remove, 1229 .remove = &intersection_remove,
1251 .destroy_set = &intersection_set_destroy, 1230 .destroy_set = &intersection_set_destroy,
diff --git a/src/set/gnunet-service-set_union.c b/src/set/gnunet-service-set_union.c
index b5b602074..1ff3d7716 100644
--- a/src/set/gnunet-service-set_union.c
+++ b/src/set/gnunet-service-set_union.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2013-2016 GNUnet e.V. 3 Copyright (C) 2013-2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -19,15 +19,16 @@
19*/ 19*/
20/** 20/**
21 * @file set/gnunet-service-set_union.c 21 * @file set/gnunet-service-set_union.c
22
23 * @brief two-peer set operations 22 * @brief two-peer set operations
24 * @author Florian Dold 23 * @author Florian Dold
24 * @author Christian Grothoff
25 */ 25 */
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_util_lib.h" 27#include "gnunet_util_lib.h"
28#include "gnunet_statistics_service.h" 28#include "gnunet_statistics_service.h"
29#include "gnunet-service-set.h" 29#include "gnunet-service-set.h"
30#include "ibf.h" 30#include "ibf.h"
31#include "gnunet-service-set_union.h"
31#include "gnunet-service-set_union_strata_estimator.h" 32#include "gnunet-service-set_union_strata_estimator.h"
32#include "gnunet-service-set_protocol.h" 33#include "gnunet-service-set_protocol.h"
33#include <gcrypt.h> 34#include <gcrypt.h>
@@ -786,11 +787,18 @@ send_element_iterator (void *cls,
786 struct GNUNET_SET_Element *el = &ee->element; 787 struct GNUNET_SET_Element *el = &ee->element;
787 struct GNUNET_MQ_Envelope *ev; 788 struct GNUNET_MQ_Envelope *ev;
788 789
789 790 LOG (GNUNET_ERROR_TYPE_INFO,
790 ev = GNUNET_MQ_msg_extra (emsg, el->size, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT); 791 "Sending element %s\n",
792 GNUNET_h2s (key));
793 ev = GNUNET_MQ_msg_extra (emsg,
794 el->size,
795 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT);
791 emsg->element_type = htons (el->element_type); 796 emsg->element_type = htons (el->element_type);
792 GNUNET_memcpy (&emsg[1], el->data, el->size); 797 GNUNET_memcpy (&emsg[1],
793 GNUNET_MQ_send (op->mq, ev); 798 el->data,
799 el->size);
800 GNUNET_MQ_send (op->mq,
801 ev);
794 return GNUNET_YES; 802 return GNUNET_YES;
795} 803}
796 804
@@ -801,11 +809,14 @@ send_full_set (struct Operation *op)
801 struct GNUNET_MQ_Envelope *ev; 809 struct GNUNET_MQ_Envelope *ev;
802 810
803 op->state->phase = PHASE_FULL_SENDING; 811 op->state->phase = PHASE_FULL_SENDING;
804 812 /* FIXME: use a more memory-friendly way of doing this with an
813 iterator, just as we do in the non-full case! */
805 (void) GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->content->elements, 814 (void) GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->content->elements,
806 &send_element_iterator, op); 815 &send_element_iterator,
816 op);
807 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE); 817 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE);
808 GNUNET_MQ_send (op->mq, ev); 818 GNUNET_MQ_send (op->mq,
819 ev);
809} 820}
810 821
811 822
@@ -813,42 +824,56 @@ send_full_set (struct Operation *op)
813 * Handle a strata estimator from a remote peer 824 * Handle a strata estimator from a remote peer
814 * 825 *
815 * @param cls the union operation 826 * @param cls the union operation
816 * @param mh the message 827 * @param msg the message
817 * @param is_compressed #GNUNET_YES if the estimator is compressed
818 * @return #GNUNET_SYSERR if the tunnel should be disconnected,
819 * #GNUNET_OK otherwise
820 */ 828 */
821static int 829int
822handle_p2p_strata_estimator (void *cls, 830check_union_p2p_strata_estimator (void *cls,
823 const struct GNUNET_MessageHeader *mh, 831 const struct StrataEstimatorMessage *msg)
824 int is_compressed)
825{ 832{
826 struct Operation *op = cls; 833 struct Operation *op = cls;
827 struct StrataEstimator *remote_se; 834 int is_compressed;
828 struct StrataEstimatorMessage *msg = (void *) mh;
829 unsigned int diff;
830 uint64_t other_size;
831 size_t len; 835 size_t len;
832 836
833 GNUNET_STATISTICS_update (_GSS_statistics,
834 "# bytes of SE received",
835 ntohs (mh->size),
836 GNUNET_NO);
837
838 if (op->state->phase != PHASE_EXPECT_SE) 837 if (op->state->phase != PHASE_EXPECT_SE)
839 { 838 {
840 GNUNET_break (0); 839 GNUNET_break (0);
841 fail_union_operation (op);
842 return GNUNET_SYSERR; 840 return GNUNET_SYSERR;
843 } 841 }
844 len = ntohs (mh->size) - sizeof (struct StrataEstimatorMessage); 842 is_compressed = (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC == htons (msg->header.type));
843 len = ntohs (msg->header.size) - sizeof (struct StrataEstimatorMessage);
845 if ( (GNUNET_NO == is_compressed) && 844 if ( (GNUNET_NO == is_compressed) &&
846 (len != SE_STRATA_COUNT * SE_IBF_SIZE * IBF_BUCKET_SIZE) ) 845 (len != SE_STRATA_COUNT * SE_IBF_SIZE * IBF_BUCKET_SIZE) )
847 { 846 {
848 fail_union_operation (op);
849 GNUNET_break (0); 847 GNUNET_break (0);
850 return GNUNET_SYSERR; 848 return GNUNET_SYSERR;
851 } 849 }
850 return GNUNET_OK;
851}
852
853
854/**
855 * Handle a strata estimator from a remote peer
856 *
857 * @param cls the union operation
858 * @param msg the message
859 */
860void
861handle_union_p2p_strata_estimator (void *cls,
862 const struct StrataEstimatorMessage *msg)
863{
864 struct Operation *op = cls;
865 struct StrataEstimator *remote_se;
866 unsigned int diff;
867 uint64_t other_size;
868 size_t len;
869 int is_compressed;
870
871 is_compressed = (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC == htons (msg->header.type));
872 GNUNET_STATISTICS_update (_GSS_statistics,
873 "# bytes of SE received",
874 ntohs (msg->header.size),
875 GNUNET_NO);
876 len = ntohs (msg->header.size) - sizeof (struct StrataEstimatorMessage);
852 other_size = GNUNET_ntohll (msg->set_size); 877 other_size = GNUNET_ntohll (msg->set_size);
853 remote_se = strata_estimator_create (SE_STRATA_COUNT, 878 remote_se = strata_estimator_create (SE_STRATA_COUNT,
854 SE_IBF_SIZE, 879 SE_IBF_SIZE,
@@ -857,7 +882,7 @@ handle_p2p_strata_estimator (void *cls,
857 { 882 {
858 /* insufficient resources, fail */ 883 /* insufficient resources, fail */
859 fail_union_operation (op); 884 fail_union_operation (op);
860 return GNUNET_SYSERR; 885 return;
861 } 886 }
862 if (GNUNET_OK != 887 if (GNUNET_OK !=
863 strata_estimator_read (&msg[1], 888 strata_estimator_read (&msg[1],
@@ -866,18 +891,16 @@ handle_p2p_strata_estimator (void *cls,
866 remote_se)) 891 remote_se))
867 { 892 {
868 /* decompression failed */ 893 /* decompression failed */
869 fail_union_operation (op);
870 strata_estimator_destroy (remote_se); 894 strata_estimator_destroy (remote_se);
871 return GNUNET_SYSERR; 895 fail_union_operation (op);
896 return;
872 } 897 }
873 GNUNET_assert (NULL != op->state->se); 898 GNUNET_assert (NULL != op->state->se);
874 diff = strata_estimator_difference (remote_se, 899 diff = strata_estimator_difference (remote_se,
875 op->state->se); 900 op->state->se);
876 901
877 if (diff > 200) 902 if (diff > 200)
878 diff = diff * 3 / 2; 903 diff = diff * 3 / 2;
879
880
881 904
882 strata_estimator_destroy (remote_se); 905 strata_estimator_destroy (remote_se);
883 strata_estimator_destroy (op->state->se); 906 strata_estimator_destroy (op->state->se);
@@ -885,12 +908,14 @@ handle_p2p_strata_estimator (void *cls,
885 LOG (GNUNET_ERROR_TYPE_DEBUG, 908 LOG (GNUNET_ERROR_TYPE_DEBUG,
886 "got se diff=%d, using ibf size %d\n", 909 "got se diff=%d, using ibf size %d\n",
887 diff, 910 diff,
888 1<<get_order_from_difference (diff)); 911 1U << get_order_from_difference (diff));
889 912
890 { 913 {
891 char *set_debug; 914 char *set_debug;
915
892 set_debug = getenv ("GNUNET_SET_BENCHMARK"); 916 set_debug = getenv ("GNUNET_SET_BENCHMARK");
893 if ( (NULL != set_debug) && (0 == strcmp (set_debug, "1")) ) 917 if ( (NULL != set_debug) &&
918 (0 == strcmp (set_debug, "1")) )
894 { 919 {
895 FILE *f = fopen ("set.log", "a"); 920 FILE *f = fopen ("set.log", "a");
896 fprintf (f, "%llu\n", (unsigned long long) diff); 921 fprintf (f, "%llu\n", (unsigned long long) diff);
@@ -898,34 +923,41 @@ handle_p2p_strata_estimator (void *cls,
898 } 923 }
899 } 924 }
900 925
901 if ((GNUNET_YES == op->spec->byzantine) && (other_size < op->spec->byzantine_lower_bound)) 926 if ( (GNUNET_YES == op->spec->byzantine) &&
927 (other_size < op->spec->byzantine_lower_bound) )
902 { 928 {
903 GNUNET_break (0); 929 GNUNET_break (0);
904 fail_union_operation (op); 930 fail_union_operation (op);
905 return GNUNET_SYSERR; 931 return;
906 } 932 }
907 933
908 934 if ( (GNUNET_YES == op->spec->force_full) ||
909 if ( (GNUNET_YES == op->spec->force_full) || (diff > op->state->initial_size / 4)) 935 (diff > op->state->initial_size / 4) ||
936 (0 == other_size) )
910 { 937 {
911 LOG (GNUNET_ERROR_TYPE_INFO, 938 LOG (GNUNET_ERROR_TYPE_INFO,
912 "Sending full set (diff=%d, own set=%u)\n", 939 "Deciding to go for full set transmission (diff=%d, own set=%u)\n",
913 diff, 940 diff,
914 op->state->initial_size); 941 op->state->initial_size);
915 GNUNET_STATISTICS_update (_GSS_statistics, 942 GNUNET_STATISTICS_update (_GSS_statistics,
916 "# of full sends", 943 "# of full sends",
917 1, 944 1,
918 GNUNET_NO); 945 GNUNET_NO);
919 if (op->state->initial_size <= other_size) 946 if ( (op->state->initial_size <= other_size) ||
947 (0 == other_size) )
920 { 948 {
921 send_full_set (op); 949 send_full_set (op);
922 } 950 }
923 else 951 else
924 { 952 {
925 struct GNUNET_MQ_Envelope *ev; 953 struct GNUNET_MQ_Envelope *ev;
954
955 LOG (GNUNET_ERROR_TYPE_INFO,
956 "Telling other peer that we expect its full set\n");
926 op->state->phase = PHASE_EXPECT_IBF; 957 op->state->phase = PHASE_EXPECT_IBF;
927 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL); 958 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL);
928 GNUNET_MQ_send (op->mq, ev); 959 GNUNET_MQ_send (op->mq,
960 ev);
929 } 961 }
930 } 962 }
931 else 963 else
@@ -942,11 +974,10 @@ handle_p2p_strata_estimator (void *cls,
942 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 974 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
943 "Failed to send IBF, closing connection\n"); 975 "Failed to send IBF, closing connection\n");
944 fail_union_operation (op); 976 fail_union_operation (op);
945 return GNUNET_SYSERR; 977 return;
946 } 978 }
947 } 979 }
948 980 GNUNET_CADET_receive_done (op->channel);
949 return GNUNET_OK;
950} 981}
951 982
952 983
@@ -1164,99 +1195,116 @@ decode_and_send (struct Operation *op)
1164 1195
1165 1196
1166/** 1197/**
1167 * Handle an IBF message from a remote peer. 1198 * Check an IBF message from a remote peer.
1168 * 1199 *
1169 * Reassemble the IBF from multiple pieces, and 1200 * Reassemble the IBF from multiple pieces, and
1170 * process the whole IBF once possible. 1201 * process the whole IBF once possible.
1171 * 1202 *
1172 * @param cls the union operation 1203 * @param cls the union operation
1173 * @param mh the header of the message 1204 * @param msg the header of the message
1174 * @return #GNUNET_SYSERR if the tunnel should be disconnected, 1205 * @return #GNUNET_OK if @a msg is well-formed
1175 * #GNUNET_OK otherwise
1176 */ 1206 */
1177static int 1207int
1178handle_p2p_ibf (void *cls, 1208check_union_p2p_ibf (void *cls,
1179 const struct GNUNET_MessageHeader *mh) 1209 const struct IBFMessage *msg)
1180{ 1210{
1181 struct Operation *op = cls; 1211 struct Operation *op = cls;
1182 const struct IBFMessage *msg;
1183 unsigned int buckets_in_message; 1212 unsigned int buckets_in_message;
1184 1213
1185 if (ntohs (mh->size) < sizeof (struct IBFMessage)) 1214 if (OT_UNION != op->type)
1186 { 1215 {
1187 GNUNET_break_op (0); 1216 GNUNET_break_op (0);
1188 fail_union_operation (op);
1189 return GNUNET_SYSERR; 1217 return GNUNET_SYSERR;
1190 } 1218 }
1191 msg = (const struct IBFMessage *) mh; 1219 buckets_in_message = (ntohs (msg->header.size) - sizeof *msg) / IBF_BUCKET_SIZE;
1192 if ( (op->state->phase == PHASE_INVENTORY_PASSIVE) || 1220 if (0 == buckets_in_message)
1193 (op->state->phase == PHASE_EXPECT_IBF) )
1194 { 1221 {
1195 op->state->phase = PHASE_EXPECT_IBF_CONT; 1222 GNUNET_break_op (0);
1196 GNUNET_assert (NULL == op->state->remote_ibf); 1223 return GNUNET_SYSERR;
1197 LOG (GNUNET_ERROR_TYPE_DEBUG, 1224 }
1198 "Creating new ibf of size %u\n", 1225 if ((ntohs (msg->header.size) - sizeof *msg) != buckets_in_message * IBF_BUCKET_SIZE)
1199 1 << msg->order); 1226 {
1200 op->state->remote_ibf = ibf_create (1<<msg->order, SE_IBF_HASH_NUM); 1227 GNUNET_break_op (0);
1201 op->state->salt_receive = ntohl (msg->salt); 1228 return GNUNET_SYSERR;
1202 LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving new IBF with salt %u\n", op->state->salt_receive);
1203 if (NULL == op->state->remote_ibf)
1204 {
1205 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1206 "Failed to parse remote IBF, closing connection\n");
1207 fail_union_operation (op);
1208 return GNUNET_SYSERR;
1209 }
1210 op->state->ibf_buckets_received = 0;
1211 if (0 != ntohl (msg->offset))
1212 {
1213 GNUNET_break_op (0);
1214 fail_union_operation (op);
1215 return GNUNET_SYSERR;
1216 }
1217 } 1229 }
1218 else if (op->state->phase == PHASE_EXPECT_IBF_CONT) 1230 if (op->state->phase == PHASE_EXPECT_IBF_CONT)
1219 { 1231 {
1220 if (ntohl (msg->offset) != op->state->ibf_buckets_received) 1232 if (ntohl (msg->offset) != op->state->ibf_buckets_received)
1221 { 1233 {
1222 GNUNET_break_op (0); 1234 GNUNET_break_op (0);
1223 fail_union_operation (op);
1224 return GNUNET_SYSERR; 1235 return GNUNET_SYSERR;
1225 } 1236 }
1226 if (1<<msg->order != op->state->remote_ibf->size) 1237 if (1<<msg->order != op->state->remote_ibf->size)
1227 { 1238 {
1228 GNUNET_break_op (0); 1239 GNUNET_break_op (0);
1229 fail_union_operation (op);
1230 return GNUNET_SYSERR; 1240 return GNUNET_SYSERR;
1231 } 1241 }
1232 if (ntohl (msg->salt) != op->state->salt_receive) 1242 if (ntohl (msg->salt) != op->state->salt_receive)
1233 { 1243 {
1234 GNUNET_break_op (0); 1244 GNUNET_break_op (0);
1235 fail_union_operation (op);
1236 return GNUNET_SYSERR; 1245 return GNUNET_SYSERR;
1237 } 1246 }
1238 } 1247 }
1239 else 1248 else if ( (op->state->phase != PHASE_INVENTORY_PASSIVE) &&
1249 (op->state->phase != PHASE_EXPECT_IBF) )
1240 { 1250 {
1241 GNUNET_assert (0); 1251 GNUNET_break_op (0);
1252 return GNUNET_SYSERR;
1242 } 1253 }
1243 1254
1244 buckets_in_message = (ntohs (msg->header.size) - sizeof *msg) / IBF_BUCKET_SIZE; 1255 return GNUNET_OK;
1256}
1245 1257
1246 if (0 == buckets_in_message) 1258
1259/**
1260 * Handle an IBF message from a remote peer.
1261 *
1262 * Reassemble the IBF from multiple pieces, and
1263 * process the whole IBF once possible.
1264 *
1265 * @param cls the union operation
1266 * @param msg the header of the message
1267 */
1268void
1269handle_union_p2p_ibf (void *cls,
1270 const struct IBFMessage *msg)
1271{
1272 struct Operation *op = cls;
1273 unsigned int buckets_in_message;
1274
1275 buckets_in_message = (ntohs (msg->header.size) - sizeof *msg) / IBF_BUCKET_SIZE;
1276 if ( (op->state->phase == PHASE_INVENTORY_PASSIVE) ||
1277 (op->state->phase == PHASE_EXPECT_IBF) )
1247 { 1278 {
1248 GNUNET_break_op (0); 1279 op->state->phase = PHASE_EXPECT_IBF_CONT;
1249 fail_union_operation (op); 1280 GNUNET_assert (NULL == op->state->remote_ibf);
1250 return GNUNET_SYSERR; 1281 LOG (GNUNET_ERROR_TYPE_DEBUG,
1282 "Creating new ibf of size %u\n",
1283 1 << msg->order);
1284 op->state->remote_ibf = ibf_create (1<<msg->order, SE_IBF_HASH_NUM);
1285 op->state->salt_receive = ntohl (msg->salt);
1286 LOG (GNUNET_ERROR_TYPE_DEBUG,
1287 "Receiving new IBF with salt %u\n",
1288 op->state->salt_receive);
1289 if (NULL == op->state->remote_ibf)
1290 {
1291 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1292 "Failed to parse remote IBF, closing connection\n");
1293 fail_union_operation (op);
1294 return;
1295 }
1296 op->state->ibf_buckets_received = 0;
1297 if (0 != ntohl (msg->offset))
1298 {
1299 GNUNET_break_op (0);
1300 fail_union_operation (op);
1301 return;
1302 }
1251 } 1303 }
1252 1304 else
1253 if ((ntohs (msg->header.size) - sizeof *msg) != buckets_in_message * IBF_BUCKET_SIZE)
1254 { 1305 {
1255 GNUNET_break_op (0); 1306 GNUNET_assert (op->state->phase == PHASE_EXPECT_IBF_CONT);
1256 fail_union_operation (op);
1257 return GNUNET_SYSERR;
1258 } 1307 }
1259
1260 GNUNET_assert (NULL != op->state->remote_ibf); 1308 GNUNET_assert (NULL != op->state->remote_ibf);
1261 1309
1262 ibf_read_slice (&msg[1], 1310 ibf_read_slice (&msg[1],
@@ -1276,10 +1324,11 @@ handle_p2p_ibf (void *cls,
1276 /* Internal error, best we can do is shut down */ 1324 /* Internal error, best we can do is shut down */
1277 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1325 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1278 "Failed to decode IBF, closing connection\n"); 1326 "Failed to decode IBF, closing connection\n");
1279 return GNUNET_SYSERR; 1327 fail_union_operation (op);
1328 return;
1280 } 1329 }
1281 } 1330 }
1282 return GNUNET_OK; 1331 GNUNET_CADET_receive_done (op->channel);
1283} 1332}
1284 1333
1285 1334
@@ -1343,6 +1392,11 @@ send_done_and_destroy (void *cls)
1343} 1392}
1344 1393
1345 1394
1395/**
1396 * Tests if the operation is finished, and if so notify.
1397 *
1398 * @param op operation to check
1399 */
1346static void 1400static void
1347maybe_finish (struct Operation *op) 1401maybe_finish (struct Operation *op)
1348{ 1402{
@@ -1382,46 +1436,59 @@ maybe_finish (struct Operation *op)
1382 1436
1383 1437
1384/** 1438/**
1385 * Handle an element message from a remote peer. 1439 * Check an element message from a remote peer.
1386 * Sent by the other peer either because we decoded an IBF and placed a demand,
1387 * or because the other peer switched to full set transmission.
1388 * 1440 *
1389 * @param cls the union operation 1441 * @param cls the union operation
1390 * @param mh the message 1442 * @param emsg the message
1391 */ 1443 */
1392static void 1444int
1393handle_p2p_elements (void *cls, 1445check_union_p2p_elements (void *cls,
1394 const struct GNUNET_MessageHeader *mh) 1446 const struct GNUNET_SET_ElementMessage *emsg)
1395{ 1447{
1396 struct Operation *op = cls; 1448 struct Operation *op = cls;
1397 struct ElementEntry *ee;
1398 const struct GNUNET_SET_ElementMessage *emsg;
1399 uint16_t element_size;
1400 1449
1401 if (0 == GNUNET_CONTAINER_multihashmap_size (op->state->demanded_hashes)) 1450 if (OT_UNION != op->type)
1402 { 1451 {
1403 GNUNET_break_op (0); 1452 GNUNET_break_op (0);
1404 fail_union_operation (op); 1453 return GNUNET_SYSERR;
1405 return;
1406 } 1454 }
1407 if (ntohs (mh->size) < sizeof (struct GNUNET_SET_ElementMessage)) 1455 if (0 == GNUNET_CONTAINER_multihashmap_size (op->state->demanded_hashes))
1408 { 1456 {
1409 GNUNET_break_op (0); 1457 GNUNET_break_op (0);
1410 fail_union_operation (op); 1458 return GNUNET_SYSERR;
1411 return;
1412 } 1459 }
1460 return GNUNET_OK;
1461}
1462
1413 1463
1414 emsg = (const struct GNUNET_SET_ElementMessage *) mh; 1464/**
1465 * Handle an element message from a remote peer.
1466 * Sent by the other peer either because we decoded an IBF and placed a demand,
1467 * or because the other peer switched to full set transmission.
1468 *
1469 * @param cls the union operation
1470 * @param emsg the message
1471 */
1472void
1473handle_union_p2p_elements (void *cls,
1474 const struct GNUNET_SET_ElementMessage *emsg)
1475{
1476 struct Operation *op = cls;
1477 struct ElementEntry *ee;
1478 struct KeyEntry *ke;
1479 uint16_t element_size;
1415 1480
1416 element_size = ntohs (mh->size) - sizeof (struct GNUNET_SET_ElementMessage); 1481 element_size = ntohs (emsg->header.size) - sizeof (struct GNUNET_SET_ElementMessage);
1417 ee = GNUNET_malloc (sizeof (struct ElementEntry) + element_size); 1482 ee = GNUNET_malloc (sizeof (struct ElementEntry) + element_size);
1418 GNUNET_memcpy (&ee[1], &emsg[1], element_size); 1483 GNUNET_memcpy (&ee[1],
1484 &emsg[1],
1485 element_size);
1419 ee->element.size = element_size; 1486 ee->element.size = element_size;
1420 ee->element.data = &ee[1]; 1487 ee->element.data = &ee[1];
1421 ee->element.element_type = ntohs (emsg->element_type); 1488 ee->element.element_type = ntohs (emsg->element_type);
1422 ee->remote = GNUNET_YES; 1489 ee->remote = GNUNET_YES;
1423 GNUNET_SET_element_hash (&ee->element, &ee->element_hash); 1490 GNUNET_SET_element_hash (&ee->element,
1424 1491 &ee->element_hash);
1425 if (GNUNET_NO == 1492 if (GNUNET_NO ==
1426 GNUNET_CONTAINER_multihashmap_remove (op->state->demanded_hashes, 1493 GNUNET_CONTAINER_multihashmap_remove (op->state->demanded_hashes,
1427 &ee->element_hash, 1494 &ee->element_hash,
@@ -1429,7 +1496,6 @@ handle_p2p_elements (void *cls,
1429 { 1496 {
1430 /* We got something we didn't demand, since it's not in our map. */ 1497 /* We got something we didn't demand, since it's not in our map. */
1431 GNUNET_break_op (0); 1498 GNUNET_break_op (0);
1432 GNUNET_free (ee);
1433 fail_union_operation (op); 1499 fail_union_operation (op);
1434 return; 1500 return;
1435 } 1501 }
@@ -1448,10 +1514,9 @@ handle_p2p_elements (void *cls,
1448 1, 1514 1,
1449 GNUNET_NO); 1515 GNUNET_NO);
1450 1516
1451 op->state->received_total += 1; 1517 op->state->received_total++;
1452
1453 struct KeyEntry *ke = op_get_element (op, &ee->element_hash);
1454 1518
1519 ke = op_get_element (op, &ee->element_hash);
1455 if (NULL != ke) 1520 if (NULL != ke)
1456 { 1521 {
1457 /* Got repeated element. Should not happen since 1522 /* Got repeated element. Should not happen since
@@ -1467,7 +1532,7 @@ handle_p2p_elements (void *cls,
1467 { 1532 {
1468 LOG (GNUNET_ERROR_TYPE_DEBUG, 1533 LOG (GNUNET_ERROR_TYPE_DEBUG,
1469 "Registering new element from remote peer\n"); 1534 "Registering new element from remote peer\n");
1470 op->state->received_fresh += 1; 1535 op->state->received_fresh++;
1471 op_register_element (op, ee, GNUNET_YES); 1536 op_register_element (op, ee, GNUNET_YES);
1472 /* only send results immediately if the client wants it */ 1537 /* only send results immediately if the client wants it */
1473 switch (op->spec->result_mode) 1538 switch (op->spec->result_mode)
@@ -1485,43 +1550,57 @@ handle_p2p_elements (void *cls,
1485 } 1550 }
1486 } 1551 }
1487 1552
1488 if (op->state->received_total > 8 && op->state->received_fresh < op->state->received_total / 3) 1553 if ( (op->state->received_total > 8) &&
1554 (op->state->received_fresh < op->state->received_total / 3) )
1489 { 1555 {
1490 /* The other peer gave us lots of old elements, there's something wrong. */ 1556 /* The other peer gave us lots of old elements, there's something wrong. */
1491 GNUNET_break_op (0); 1557 GNUNET_break_op (0);
1492 fail_union_operation (op); 1558 fail_union_operation (op);
1493 return; 1559 return;
1494 } 1560 }
1495 1561 GNUNET_CADET_receive_done (op->channel);
1496 maybe_finish (op); 1562 maybe_finish (op);
1497} 1563}
1498 1564
1499 1565
1500/** 1566/**
1501 * Handle an element message from a remote peer. 1567 * Check a full element message from a remote peer.
1502 * 1568 *
1503 * @param cls the union operation 1569 * @param cls the union operation
1504 * @param mh the message 1570 * @param emsg the message
1505 */ 1571 */
1506static void 1572int
1507handle_p2p_full_element (void *cls, 1573check_union_p2p_full_element (void *cls,
1508 const struct GNUNET_MessageHeader *mh) 1574 const struct GNUNET_SET_ElementMessage *emsg)
1509{ 1575{
1510 struct Operation *op = cls; 1576 struct Operation *op = cls;
1511 struct ElementEntry *ee;
1512 const struct GNUNET_SET_ElementMessage *emsg;
1513 uint16_t element_size;
1514 1577
1515 if (ntohs (mh->size) < sizeof (struct GNUNET_SET_ElementMessage)) 1578 if (OT_UNION != op->type)
1516 { 1579 {
1517 GNUNET_break_op (0); 1580 GNUNET_break_op (0);
1518 fail_union_operation (op); 1581 return GNUNET_SYSERR;
1519 return;
1520 } 1582 }
1583 // FIXME: check that we expect full elements here?
1584 return GNUNET_OK;
1585}
1521 1586
1522 emsg = (const struct GNUNET_SET_ElementMessage *) mh;
1523 1587
1524 element_size = ntohs (mh->size) - sizeof (struct GNUNET_SET_ElementMessage); 1588/**
1589 * Handle an element message from a remote peer.
1590 *
1591 * @param cls the union operation
1592 * @param emsg the message
1593 */
1594void
1595handle_union_p2p_full_element (void *cls,
1596 const struct GNUNET_SET_ElementMessage *emsg)
1597{
1598 struct Operation *op = cls;
1599 struct ElementEntry *ee;
1600 struct KeyEntry *ke;
1601 uint16_t element_size;
1602
1603 element_size = ntohs (emsg->header.size) - sizeof (struct GNUNET_SET_ElementMessage);
1525 ee = GNUNET_malloc (sizeof (struct ElementEntry) + element_size); 1604 ee = GNUNET_malloc (sizeof (struct ElementEntry) + element_size);
1526 GNUNET_memcpy (&ee[1], &emsg[1], element_size); 1605 GNUNET_memcpy (&ee[1], &emsg[1], element_size);
1527 ee->element.size = element_size; 1606 ee->element.size = element_size;
@@ -1544,10 +1623,9 @@ handle_p2p_full_element (void *cls,
1544 1, 1623 1,
1545 GNUNET_NO); 1624 GNUNET_NO);
1546 1625
1547 op->state->received_total += 1; 1626 op->state->received_total++;
1548
1549 struct KeyEntry *ke = op_get_element (op, &ee->element_hash);
1550 1627
1628 ke = op_get_element (op, &ee->element_hash);
1551 if (NULL != ke) 1629 if (NULL != ke)
1552 { 1630 {
1553 /* Got repeated element. Should not happen since 1631 /* Got repeated element. Should not happen since
@@ -1563,7 +1641,7 @@ handle_p2p_full_element (void *cls,
1563 { 1641 {
1564 LOG (GNUNET_ERROR_TYPE_DEBUG, 1642 LOG (GNUNET_ERROR_TYPE_DEBUG,
1565 "Registering new element from remote peer\n"); 1643 "Registering new element from remote peer\n");
1566 op->state->received_fresh += 1; 1644 op->state->received_fresh++;
1567 op_register_element (op, ee, GNUNET_YES); 1645 op_register_element (op, ee, GNUNET_YES);
1568 /* only send results immediately if the client wants it */ 1646 /* only send results immediately if the client wants it */
1569 switch (op->spec->result_mode) 1647 switch (op->spec->result_mode)
@@ -1581,8 +1659,8 @@ handle_p2p_full_element (void *cls,
1581 } 1659 }
1582 } 1660 }
1583 1661
1584 if ( (GNUNET_YES == op->spec->byzantine) && 1662 if ( (GNUNET_YES == op->spec->byzantine) &&
1585 (op->state->received_total > 384 + op->state->received_fresh * 4) && 1663 (op->state->received_total > 384 + op->state->received_fresh * 4) &&
1586 (op->state->received_fresh < op->state->received_total / 6) ) 1664 (op->state->received_fresh < op->state->received_total / 6) )
1587 { 1665 {
1588 /* The other peer gave us lots of old elements, there's something wrong. */ 1666 /* The other peer gave us lots of old elements, there's something wrong. */
@@ -1594,51 +1672,73 @@ handle_p2p_full_element (void *cls,
1594 fail_union_operation (op); 1672 fail_union_operation (op);
1595 return; 1673 return;
1596 } 1674 }
1675 GNUNET_CADET_receive_done (op->channel);
1597} 1676}
1598 1677
1678
1599/** 1679/**
1600 * Send offers (for GNUNET_Hash-es) in response 1680 * Send offers (for GNUNET_Hash-es) in response
1601 * to inquiries (for IBF_Key-s). 1681 * to inquiries (for IBF_Key-s).
1602 * 1682 *
1603 * @param cls the union operation 1683 * @param cls the union operation
1604 * @param mh the message 1684 * @param msg the message
1605 */ 1685 */
1606static void 1686int
1607handle_p2p_inquiry (void *cls, 1687check_union_p2p_inquiry (void *cls,
1608 const struct GNUNET_MessageHeader *mh) 1688 const struct InquiryMessage *msg)
1609{ 1689{
1610 struct Operation *op = cls; 1690 struct Operation *op = cls;
1611 const struct IBF_Key *ibf_key;
1612 unsigned int num_keys; 1691 unsigned int num_keys;
1613 struct InquiryMessage *msg;
1614 1692
1615 /* look up elements and send them */ 1693 if (OT_UNION != op->type)
1694 {
1695 GNUNET_break_op (0);
1696 return GNUNET_SYSERR;
1697 }
1616 if (op->state->phase != PHASE_INVENTORY_PASSIVE) 1698 if (op->state->phase != PHASE_INVENTORY_PASSIVE)
1617 { 1699 {
1618 GNUNET_break_op (0); 1700 GNUNET_break_op (0);
1619 fail_union_operation (op); 1701 return GNUNET_SYSERR;
1620 return;
1621 } 1702 }
1622 num_keys = (ntohs (mh->size) - sizeof (struct InquiryMessage)) 1703 num_keys = (ntohs (msg->header.size) - sizeof (struct InquiryMessage))
1623 / sizeof (struct IBF_Key); 1704 / sizeof (struct IBF_Key);
1624 if ((ntohs (mh->size) - sizeof (struct InquiryMessage)) 1705 if ((ntohs (msg->header.size) - sizeof (struct InquiryMessage))
1625 != num_keys * sizeof (struct IBF_Key)) 1706 != num_keys * sizeof (struct IBF_Key))
1626 { 1707 {
1627 GNUNET_break_op (0); 1708 GNUNET_break_op (0);
1628 fail_union_operation (op); 1709 return GNUNET_SYSERR;
1629 return;
1630 } 1710 }
1711 return GNUNET_OK;
1712}
1713
1631 1714
1632 msg = (struct InquiryMessage *) mh; 1715/**
1716 * Send offers (for GNUNET_Hash-es) in response
1717 * to inquiries (for IBF_Key-s).
1718 *
1719 * @param cls the union operation
1720 * @param msg the message
1721 */
1722void
1723handle_union_p2p_inquiry (void *cls,
1724 const struct InquiryMessage *msg)
1725{
1726 struct Operation *op = cls;
1727 const struct IBF_Key *ibf_key;
1728 unsigned int num_keys;
1633 1729
1730 num_keys = (ntohs (msg->header.size) - sizeof (struct InquiryMessage))
1731 / sizeof (struct IBF_Key);
1634 ibf_key = (const struct IBF_Key *) &msg[1]; 1732 ibf_key = (const struct IBF_Key *) &msg[1];
1635 while (0 != num_keys--) 1733 while (0 != num_keys--)
1636 { 1734 {
1637 struct IBF_Key unsalted_key; 1735 struct IBF_Key unsalted_key;
1736
1638 unsalt_key (ibf_key, ntohl (msg->salt), &unsalted_key); 1737 unsalt_key (ibf_key, ntohl (msg->salt), &unsalted_key);
1639 send_offers_for_key (op, unsalted_key); 1738 send_offers_for_key (op, unsalted_key);
1640 ibf_key++; 1739 ibf_key++;
1641 } 1740 }
1741 GNUNET_CADET_receive_done (op->channel);
1642} 1742}
1643 1743
1644 1744
@@ -1677,27 +1777,36 @@ send_missing_elements_iter (void *cls,
1677 1777
1678 1778
1679/** 1779/**
1680 * Handle a 1780 * Handle a request for full set transmission.
1681 * 1781 *
1682 * @parem cls closure, a set union operation 1782 * @parem cls closure, a set union operation
1683 * @param mh the demand message 1783 * @param mh the demand message
1684 */ 1784 */
1685static void 1785void
1686handle_p2p_request_full (void *cls, 1786handle_union_p2p_request_full (void *cls,
1687 const struct GNUNET_MessageHeader *mh) 1787 const struct GNUNET_MessageHeader *mh)
1688{ 1788{
1689 struct Operation *op = cls; 1789 struct Operation *op = cls;
1690 1790
1691 if (PHASE_EXPECT_IBF != op->state->phase) 1791 LOG (GNUNET_ERROR_TYPE_INFO,
1792 "Received request for full set transmission\n");
1793 if (OT_UNION != op->type)
1692 { 1794 {
1795 GNUNET_break_op (0);
1693 fail_union_operation (op); 1796 fail_union_operation (op);
1797 return;
1798 }
1799 if (PHASE_EXPECT_IBF != op->state->phase)
1800 {
1694 GNUNET_break_op (0); 1801 GNUNET_break_op (0);
1802 fail_union_operation (op);
1695 return; 1803 return;
1696 } 1804 }
1697 1805
1698 // FIXME: we need to check that our set is larger than the 1806 // FIXME: we need to check that our set is larger than the
1699 // byzantine_lower_bound by some threshold 1807 // byzantine_lower_bound by some threshold
1700 send_full_set (op); 1808 send_full_set (op);
1809 GNUNET_CADET_receive_done (op->channel);
1701} 1810}
1702 1811
1703 1812
@@ -1707,56 +1816,97 @@ handle_p2p_request_full (void *cls,
1707 * @parem cls closure, a set union operation 1816 * @parem cls closure, a set union operation
1708 * @param mh the demand message 1817 * @param mh the demand message
1709 */ 1818 */
1710static void 1819void
1711handle_p2p_full_done (void *cls, 1820handle_union_p2p_full_done (void *cls,
1712 const struct GNUNET_MessageHeader *mh) 1821 const struct GNUNET_MessageHeader *mh)
1713{ 1822{
1714 struct Operation *op = cls; 1823 struct Operation *op = cls;
1715 1824
1716 if (PHASE_EXPECT_IBF == op->state->phase) 1825 switch (op->state->phase)
1717 { 1826 {
1718 struct GNUNET_MQ_Envelope *ev; 1827 case PHASE_EXPECT_IBF:
1719 1828 {
1720 LOG (GNUNET_ERROR_TYPE_DEBUG, "got FULL DONE, sending elements that other peer is missing\n"); 1829 struct GNUNET_MQ_Envelope *ev;
1721 1830
1722 /* send all the elements that did not come from the remote peer */ 1831 LOG (GNUNET_ERROR_TYPE_DEBUG,
1723 GNUNET_CONTAINER_multihashmap32_iterate (op->state->key_to_element, 1832 "got FULL DONE, sending elements that other peer is missing\n");
1724 &send_missing_elements_iter,
1725 op);
1726 1833
1727 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE); 1834 /* send all the elements that did not come from the remote peer */
1728 GNUNET_MQ_send (op->mq, ev); 1835 GNUNET_CONTAINER_multihashmap32_iterate (op->state->key_to_element,
1729 op->state->phase = PHASE_DONE; 1836 &send_missing_elements_iter,
1837 op);
1730 1838
1731 /* we now wait until the other peer shuts the tunnel down*/ 1839 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE);
1840 GNUNET_MQ_send (op->mq, ev);
1841 op->state->phase = PHASE_DONE;
1842 /* we now wait until the other peer shuts the tunnel down*/
1843 }
1844 break;
1845 case PHASE_FULL_SENDING:
1846 {
1847 LOG (GNUNET_ERROR_TYPE_DEBUG,
1848 "got FULL DONE, finishing\n");
1849 /* We sent the full set, and got the response for that. We're done. */
1850 op->state->phase = PHASE_DONE;
1851 GNUNET_CADET_receive_done (op->channel);
1852 send_done_and_destroy (op);
1853 return;
1854 }
1855 break;
1856 default:
1857 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1858 "Handle full done phase is %u\n",
1859 (unsigned) op->state->phase);
1860 GNUNET_break_op (0);
1861 fail_union_operation (op);
1862 return;
1732 } 1863 }
1733 else if (PHASE_FULL_SENDING == op->state->phase) 1864 GNUNET_CADET_receive_done (op->channel);
1865}
1866
1867
1868/**
1869 * Check a demand by the other peer for elements based on a list
1870 * of `struct GNUNET_HashCode`s.
1871 *
1872 * @parem cls closure, a set union operation
1873 * @param mh the demand message
1874 * @return #GNUNET_OK if @a mh is well-formed
1875 */
1876int
1877check_union_p2p_demand (void *cls,
1878 const struct GNUNET_MessageHeader *mh)
1879{
1880 struct Operation *op = cls;
1881 unsigned int num_hashes;
1882
1883 if (OT_UNION != op->type)
1734 { 1884 {
1735 LOG (GNUNET_ERROR_TYPE_DEBUG, "got FULL DONE, finishing\n"); 1885 GNUNET_break_op (0);
1736 /* We sent the full set, and got the response for that. We're done. */ 1886 return GNUNET_SYSERR;
1737 op->state->phase = PHASE_DONE;
1738 send_done_and_destroy (op);
1739 } 1887 }
1740 else 1888 num_hashes = (ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader))
1889 / sizeof (struct GNUNET_HashCode);
1890 if ((ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader))
1891 != num_hashes * sizeof (struct GNUNET_HashCode))
1741 { 1892 {
1742 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "handle full done phase is %u\n", (unsigned) op->state->phase);
1743 GNUNET_break_op (0); 1893 GNUNET_break_op (0);
1744 fail_union_operation (op); 1894 return GNUNET_SYSERR;
1745 return;
1746 } 1895 }
1896 return GNUNET_OK;
1747} 1897}
1748 1898
1749 1899
1750/** 1900/**
1751 * Handle a demand by the other peer for elements based on a list 1901 * Handle a demand by the other peer for elements based on a list
1752 * of GNUNET_HashCode-s. 1902 * of `struct GNUNET_HashCode`s.
1753 * 1903 *
1754 * @parem cls closure, a set union operation 1904 * @parem cls closure, a set union operation
1755 * @param mh the demand message 1905 * @param mh the demand message
1756 */ 1906 */
1757static void 1907void
1758handle_p2p_demand (void *cls, 1908handle_union_p2p_demand (void *cls,
1759 const struct GNUNET_MessageHeader *mh) 1909 const struct GNUNET_MessageHeader *mh)
1760{ 1910{
1761 struct Operation *op = cls; 1911 struct Operation *op = cls;
1762 struct ElementEntry *ee; 1912 struct ElementEntry *ee;
@@ -1767,19 +1917,12 @@ handle_p2p_demand (void *cls,
1767 1917
1768 num_hashes = (ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader)) 1918 num_hashes = (ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader))
1769 / sizeof (struct GNUNET_HashCode); 1919 / sizeof (struct GNUNET_HashCode);
1770 if ((ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader))
1771 != num_hashes * sizeof (struct GNUNET_HashCode))
1772 {
1773 GNUNET_break_op (0);
1774 fail_union_operation (op);
1775 return;
1776 }
1777
1778 for (hash = (const struct GNUNET_HashCode *) &mh[1]; 1920 for (hash = (const struct GNUNET_HashCode *) &mh[1];
1779 num_hashes > 0; 1921 num_hashes > 0;
1780 hash++, num_hashes--) 1922 hash++, num_hashes--)
1781 { 1923 {
1782 ee = GNUNET_CONTAINER_multihashmap_get (op->spec->set->content->elements, hash); 1924 ee = GNUNET_CONTAINER_multihashmap_get (op->spec->set->content->elements,
1925 hash);
1783 if (NULL == ee) 1926 if (NULL == ee)
1784 { 1927 {
1785 /* Demand for non-existing element. */ 1928 /* Demand for non-existing element. */
@@ -1823,31 +1966,35 @@ handle_p2p_demand (void *cls,
1823 break; 1966 break;
1824 } 1967 }
1825 } 1968 }
1969 GNUNET_CADET_receive_done (op->channel);
1826} 1970}
1827 1971
1828 1972
1829/** 1973/**
1830 * Handle offers (of GNUNET_HashCode-s) and 1974 * Check offer (of `struct GNUNET_HashCode`s).
1831 * respond with demands (of GNUNET_HashCode-s).
1832 * 1975 *
1833 * @param cls the union operation 1976 * @param cls the union operation
1834 * @param mh the message 1977 * @param mh the message
1978 * @return #GNUNET_OK if @a mh is well-formed
1835 */ 1979 */
1836static void 1980int
1837handle_p2p_offer (void *cls, 1981check_union_p2p_offer (void *cls,
1838 const struct GNUNET_MessageHeader *mh) 1982 const struct GNUNET_MessageHeader *mh)
1839{ 1983{
1840 struct Operation *op = cls; 1984 struct Operation *op = cls;
1841 const struct GNUNET_HashCode *hash;
1842 unsigned int num_hashes; 1985 unsigned int num_hashes;
1843 1986
1987 if (OT_UNION != op->type)
1988 {
1989 GNUNET_break_op (0);
1990 return GNUNET_SYSERR;
1991 }
1844 /* look up elements and send them */ 1992 /* look up elements and send them */
1845 if ( (op->state->phase != PHASE_INVENTORY_PASSIVE) && 1993 if ( (op->state->phase != PHASE_INVENTORY_PASSIVE) &&
1846 (op->state->phase != PHASE_INVENTORY_ACTIVE)) 1994 (op->state->phase != PHASE_INVENTORY_ACTIVE))
1847 { 1995 {
1848 GNUNET_break_op (0); 1996 GNUNET_break_op (0);
1849 fail_union_operation (op); 1997 return GNUNET_SYSERR;
1850 return;
1851 } 1998 }
1852 num_hashes = (ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader)) 1999 num_hashes = (ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader))
1853 / sizeof (struct GNUNET_HashCode); 2000 / sizeof (struct GNUNET_HashCode);
@@ -1855,10 +2002,29 @@ handle_p2p_offer (void *cls,
1855 != num_hashes * sizeof (struct GNUNET_HashCode)) 2002 != num_hashes * sizeof (struct GNUNET_HashCode))
1856 { 2003 {
1857 GNUNET_break_op (0); 2004 GNUNET_break_op (0);
1858 fail_union_operation (op); 2005 return GNUNET_SYSERR;
1859 return;
1860 } 2006 }
2007 return GNUNET_OK;
2008}
2009
2010
2011/**
2012 * Handle offers (of `struct GNUNET_HashCode`s) and
2013 * respond with demands (of `struct GNUNET_HashCode`s).
2014 *
2015 * @param cls the union operation
2016 * @param mh the message
2017 */
2018void
2019handle_union_p2p_offer (void *cls,
2020 const struct GNUNET_MessageHeader *mh)
2021{
2022 struct Operation *op = cls;
2023 const struct GNUNET_HashCode *hash;
2024 unsigned int num_hashes;
1861 2025
2026 num_hashes = (ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader))
2027 / sizeof (struct GNUNET_HashCode);
1862 for (hash = (const struct GNUNET_HashCode *) &mh[1]; 2028 for (hash = (const struct GNUNET_HashCode *) &mh[1];
1863 num_hashes > 0; 2029 num_hashes > 0;
1864 hash++, num_hashes--) 2030 hash++, num_hashes--)
@@ -1897,6 +2063,7 @@ handle_p2p_offer (void *cls,
1897 *(struct GNUNET_HashCode *) &demands[1] = *hash; 2063 *(struct GNUNET_HashCode *) &demands[1] = *hash;
1898 GNUNET_MQ_send (op->mq, ev); 2064 GNUNET_MQ_send (op->mq, ev);
1899 } 2065 }
2066 GNUNET_CADET_receive_done (op->channel);
1900} 2067}
1901 2068
1902 2069
@@ -1906,16 +2073,22 @@ handle_p2p_offer (void *cls,
1906 * @param cls the union operation 2073 * @param cls the union operation
1907 * @param mh the message 2074 * @param mh the message
1908 */ 2075 */
1909static void 2076void
1910handle_p2p_done (void *cls, 2077handle_union_p2p_done (void *cls,
1911 const struct GNUNET_MessageHeader *mh) 2078 const struct GNUNET_MessageHeader *mh)
1912{ 2079{
1913 struct Operation *op = cls; 2080 struct Operation *op = cls;
1914 2081
1915 if (op->state->phase == PHASE_INVENTORY_PASSIVE) 2082 if (OT_UNION != op->type)
1916 { 2083 {
2084 GNUNET_break_op (0);
2085 fail_union_operation (op);
2086 return;
2087 }
2088 switch (op->state->phase)
2089 {
2090 case PHASE_INVENTORY_PASSIVE:
1917 /* We got all requests, but still have to send our elements in response. */ 2091 /* We got all requests, but still have to send our elements in response. */
1918
1919 op->state->phase = PHASE_FINISH_WAITING; 2092 op->state->phase = PHASE_FINISH_WAITING;
1920 2093
1921 LOG (GNUNET_ERROR_TYPE_DEBUG, 2094 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -1929,11 +2102,10 @@ handle_p2p_done (void *cls,
1929 * all our demands are satisfied, so that the active 2102 * all our demands are satisfied, so that the active
1930 * peer can quit if we gave him everything. 2103 * peer can quit if we gave him everything.
1931 */ 2104 */
2105 GNUNET_CADET_receive_done (op->channel);
1932 maybe_finish (op); 2106 maybe_finish (op);
1933 return; 2107 return;
1934 } 2108 case PHASE_INVENTORY_ACTIVE:
1935 if (op->state->phase == PHASE_INVENTORY_ACTIVE)
1936 {
1937 LOG (GNUNET_ERROR_TYPE_DEBUG, 2109 LOG (GNUNET_ERROR_TYPE_DEBUG,
1938 "got DONE (as active partner), waiting to finish\n"); 2110 "got DONE (as active partner), waiting to finish\n");
1939 /* All demands of the other peer are satisfied, 2111 /* All demands of the other peer are satisfied,
@@ -1944,11 +2116,14 @@ handle_p2p_done (void *cls,
1944 * to the other peer once our demands are met. 2116 * to the other peer once our demands are met.
1945 */ 2117 */
1946 op->state->phase = PHASE_FINISH_CLOSING; 2118 op->state->phase = PHASE_FINISH_CLOSING;
2119 GNUNET_CADET_receive_done (op->channel);
1947 maybe_finish (op); 2120 maybe_finish (op);
1948 return; 2121 return;
2122 default:
2123 GNUNET_break_op (0);
2124 fail_union_operation (op);
2125 return;
1949 } 2126 }
1950 GNUNET_break_op (0);
1951 fail_union_operation (op);
1952} 2127}
1953 2128
1954 2129
@@ -2119,62 +2294,6 @@ union_set_destroy (struct SetState *set_state)
2119 2294
2120 2295
2121/** 2296/**
2122 * Dispatch messages for a union operation.
2123 *
2124 * @param op the state of the union evaluate operation
2125 * @param mh the received message
2126 * @return #GNUNET_SYSERR if the tunnel should be disconnected,
2127 * #GNUNET_OK otherwise
2128 */
2129int
2130union_handle_p2p_message (struct Operation *op,
2131 const struct GNUNET_MessageHeader *mh)
2132{
2133 //LOG (GNUNET_ERROR_TYPE_DEBUG,
2134 // "received p2p message (t: %u, s: %u)\n",
2135 // ntohs (mh->type),
2136 // ntohs (mh->size));
2137 switch (ntohs (mh->type))
2138 {
2139 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF:
2140 return handle_p2p_ibf (op, mh);
2141 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE:
2142 return handle_p2p_strata_estimator (op, mh, GNUNET_NO);
2143 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC:
2144 return handle_p2p_strata_estimator (op, mh, GNUNET_YES);
2145 case GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS:
2146 handle_p2p_elements (op, mh);
2147 break;
2148 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT:
2149 handle_p2p_full_element (op, mh);
2150 break;
2151 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_INQUIRY:
2152 handle_p2p_inquiry (op, mh);
2153 break;
2154 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE:
2155 handle_p2p_done (op, mh);
2156 break;
2157 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_OFFER:
2158 handle_p2p_offer (op, mh);
2159 break;
2160 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND:
2161 handle_p2p_demand (op, mh);
2162 break;
2163 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE:
2164 handle_p2p_full_done (op, mh);
2165 break;
2166 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL:
2167 handle_p2p_request_full (op, mh);
2168 break;
2169 default:
2170 /* Something wrong with cadet's message handlers? */
2171 GNUNET_assert (0);
2172 }
2173 return GNUNET_OK;
2174}
2175
2176
2177/**
2178 * Handler for peer-disconnects, notifies the client 2297 * Handler for peer-disconnects, notifies the client
2179 * about the aborted operation in case the op was not concluded. 2298 * about the aborted operation in case the op was not concluded.
2180 * 2299 *
@@ -2240,7 +2359,6 @@ _GSS_union_vt ()
2240{ 2359{
2241 static const struct SetVT union_vt = { 2360 static const struct SetVT union_vt = {
2242 .create = &union_set_create, 2361 .create = &union_set_create,
2243 .msg_handler = &union_handle_p2p_message,
2244 .add = &union_add, 2362 .add = &union_add,
2245 .remove = &union_remove, 2363 .remove = &union_remove,
2246 .destroy_set = &union_set_destroy, 2364 .destroy_set = &union_set_destroy,
diff --git a/src/set/set_api.c b/src/set/set_api.c
index 04a4e4910..bc428f9f6 100644
--- a/src/set/set_api.c
+++ b/src/set/set_api.c
@@ -76,6 +76,8 @@ struct GNUNET_SET_Handle
76 76
77 /** 77 /**
78 * Should the set be destroyed once all operations are gone? 78 * Should the set be destroyed once all operations are gone?
79 * #GNUNET_SYSERR if #GNUNET_SET_destroy() must raise this flag,
80 * #GNUNET_YES if #GNUNET_SET_destroy() did raise this flag.
79 */ 81 */
80 int destroy_requested; 82 int destroy_requested;
81 83
@@ -345,11 +347,13 @@ handle_iter_done (void *cls,
345 347
346 if (NULL == iter) 348 if (NULL == iter)
347 return; 349 return;
350 set->destroy_requested = GNUNET_SYSERR;
348 set->iterator = NULL; 351 set->iterator = NULL;
349 set->iteration_id++; 352 set->iteration_id++;
350 iter (set->iterator_cls, 353 iter (set->iterator_cls,
351 NULL); 354 NULL);
352 355 if (GNUNET_SYSERR == set->destroy_requested)
356 set->destroy_requested = GNUNET_NO;
353 if (GNUNET_YES == set->destroy_requested) 357 if (GNUNET_YES == set->destroy_requested)
354 GNUNET_SET_destroy (set); 358 GNUNET_SET_destroy (set);
355} 359}
@@ -736,7 +740,9 @@ GNUNET_SET_destroy (struct GNUNET_SET_Handle *set)
736 /* destroying set while iterator is active is currently 740 /* destroying set while iterator is active is currently
737 not supported; we should expand the API to allow 741 not supported; we should expand the API to allow
738 clients to explicitly cancel the iteration! */ 742 clients to explicitly cancel the iteration! */
739 if ( (NULL != set->ops_head) || (NULL != set->iterator) ) 743 if ( (NULL != set->ops_head) ||
744 (NULL != set->iterator) ||
745 (GNUNET_SYSERR == set->destroy_requested) )
740 { 746 {
741 LOG (GNUNET_ERROR_TYPE_DEBUG, 747 LOG (GNUNET_ERROR_TYPE_DEBUG,
742 "Set operations are pending, delaying set destruction\n"); 748 "Set operations are pending, delaying set destruction\n");
@@ -809,7 +815,7 @@ GNUNET_SET_prepare (const struct GNUNET_PeerIdentity *other_peer,
809 msg->force_delta = GNUNET_YES; 815 msg->force_delta = GNUNET_YES;
810 break; 816 break;
811 default: 817 default:
812 LOG (GNUNET_ERROR_TYPE_ERROR, 818 LOG (GNUNET_ERROR_TYPE_ERROR,
813 "Option with type %d not recognized\n", (int) opt->type); 819 "Option with type %d not recognized\n", (int) opt->type);
814 } 820 }
815 } 821 }
diff --git a/src/set/test_set_union_copy.c b/src/set/test_set_union_copy.c
index c887a8958..a1eba6311 100644
--- a/src/set/test_set_union_copy.c
+++ b/src/set/test_set_union_copy.c
@@ -122,6 +122,7 @@ check_count_iter (void *cls,
122 return GNUNET_NO; 122 return GNUNET_NO;
123 } 123 }
124 ci_cls->cont (ci_cls->cont_cls); 124 ci_cls->cont (ci_cls->cont_cls);
125 GNUNET_free (ci_cls);
125 return GNUNET_NO; 126 return GNUNET_NO;
126 } 127 }
127 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 128 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
diff --git a/src/sq/sq.c b/src/sq/sq.c
index 114de2d88..089ebf0ff 100644
--- a/src/sq/sq.c
+++ b/src/sq/sq.c
@@ -90,7 +90,12 @@ GNUNET_SQ_extract_result (sqlite3_stmt *result,
90 j, 90 j,
91 rs[i].result_size, 91 rs[i].result_size,
92 rs[i].dst)) 92 rs[i].dst))
93 {
94 for (unsigned int k=0;k<i;k++)
95 if (NULL != rs[k].cleaner)
96 rs[k].cleaner (rs[k].cls);
93 return GNUNET_SYSERR; 97 return GNUNET_SYSERR;
98 }
94 GNUNET_assert (0 != rs[i].num_params); 99 GNUNET_assert (0 != rs[i].num_params);
95 j += rs[i].num_params; 100 j += rs[i].num_params;
96 } 101 }
@@ -112,4 +117,24 @@ GNUNET_SQ_cleanup_result (struct GNUNET_SQ_ResultSpec *rs)
112 rs[i].cleaner (rs[i].cls); 117 rs[i].cleaner (rs[i].cls);
113} 118}
114 119
120
121/**
122 * Reset @a stmt and log error.
123 *
124 * @param dbh database handle
125 * @param stmt statement to reset
126 */
127void
128GNUNET_SQ_reset (sqlite3 *dbh,
129 sqlite3_stmt *stmt)
130{
131 if (SQLITE_OK !=
132 sqlite3_reset (stmt))
133 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
134 "sqlite",
135 _("Failed to reset sqlite statement with error: %s\n"),
136 sqlite3_errmsg (dbh));
137}
138
139
115/* end of sq.c */ 140/* end of sq.c */
diff --git a/src/sq/sq_query_helper.c b/src/sq/sq_query_helper.c
index 5529c5e6c..a04b4ced4 100644
--- a/src/sq/sq_query_helper.c
+++ b/src/sq/sq_query_helper.c
@@ -235,6 +235,40 @@ GNUNET_SQ_query_param_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *x)
235 235
236 236
237/** 237/**
238 * Function called to convert input argument into SQL parameters.
239 *
240 * @param cls closure
241 * @param data pointer to input argument
242 * @param data_len number of bytes in @a data (if applicable)
243 * @param stmt sqlite statement to bind parameters for
244 * @param off offset of the argument to bind in @a stmt, numbered from 1,
245 * so immediately suitable for passing to `sqlite3_bind`-functions.
246 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
247 */
248static int
249bind_abstime (void *cls,
250 const void *data,
251 size_t data_len,
252 sqlite3_stmt *stmt,
253 unsigned int off)
254{
255 const struct GNUNET_TIME_Absolute *u = data;
256 struct GNUNET_TIME_Absolute abs;
257
258 abs = *u;
259 if (abs.abs_value_us > INT64_MAX)
260 abs.abs_value_us = INT64_MAX;
261 GNUNET_assert (sizeof (uint64_t) == data_len);
262 if (SQLITE_OK !=
263 sqlite3_bind_int64 (stmt,
264 (int) off,
265 (sqlite3_int64) abs.abs_value_us))
266 return GNUNET_SYSERR;
267 return GNUNET_OK;
268}
269
270
271/**
238 * Generate query parameter for an absolute time value. 272 * Generate query parameter for an absolute time value.
239 * The database must store a 64-bit integer. 273 * The database must store a 64-bit integer.
240 * 274 *
@@ -243,7 +277,13 @@ GNUNET_SQ_query_param_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *x)
243struct GNUNET_SQ_QueryParam 277struct GNUNET_SQ_QueryParam
244GNUNET_SQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x) 278GNUNET_SQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x)
245{ 279{
246 return GNUNET_SQ_query_param_uint64 (&x->abs_value_us); 280 struct GNUNET_SQ_QueryParam qp = {
281 .conv = &bind_abstime,
282 .data = x,
283 .size = sizeof (struct GNUNET_TIME_Absolute),
284 .num_params = 1
285 };
286 return qp;
247} 287}
248 288
249 289
@@ -269,6 +309,8 @@ bind_nbotime (void *cls,
269 struct GNUNET_TIME_Absolute abs; 309 struct GNUNET_TIME_Absolute abs;
270 310
271 abs = GNUNET_TIME_absolute_ntoh (*u); 311 abs = GNUNET_TIME_absolute_ntoh (*u);
312 if (abs.abs_value_us > INT64_MAX)
313 abs.abs_value_us = INT64_MAX;
272 GNUNET_assert (sizeof (uint64_t) == data_len); 314 GNUNET_assert (sizeof (uint64_t) == data_len);
273 if (SQLITE_OK != 315 if (SQLITE_OK !=
274 sqlite3_bind_int64 (stmt, 316 sqlite3_bind_int64 (stmt,
diff --git a/src/sq/sq_result_helper.c b/src/sq/sq_result_helper.c
index eaf606aa4..fad3f3c8d 100644
--- a/src/sq/sq_result_helper.c
+++ b/src/sq/sq_result_helper.c
@@ -46,6 +46,15 @@ extract_var_blob (void *cls,
46 const void *ret; 46 const void *ret;
47 void **rdst = (void **) dst; 47 void **rdst = (void **) dst;
48 48
49 if (SQLITE_NULL ==
50 sqlite3_column_type (result,
51 column))
52 {
53 *rdst = NULL;
54 *dst_size = 0;
55 return GNUNET_YES;
56 }
57
49 if (SQLITE_BLOB != 58 if (SQLITE_BLOB !=
50 sqlite3_column_type (result, 59 sqlite3_column_type (result,
51 column)) 60 column))
@@ -142,6 +151,14 @@ extract_fixed_blob (void *cls,
142 int have; 151 int have;
143 const void *ret; 152 const void *ret;
144 153
154 if ( (0 == *dst_size) &&
155 (SQLITE_NULL ==
156 sqlite3_column_type (result,
157 column)) )
158 {
159 return GNUNET_YES;
160 }
161
145 if (SQLITE_BLOB != 162 if (SQLITE_BLOB !=
146 sqlite3_column_type (result, 163 sqlite3_column_type (result,
147 column)) 164 column))
@@ -459,6 +476,45 @@ GNUNET_SQ_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig)
459 476
460 477
461/** 478/**
479 * Extract absolute time value from a Postgres database @a result at row @a row.
480 *
481 * @param cls closure
482 * @param result where to extract data from
483 * @param column column to extract data from
484 * @param[in,out] dst_size where to store size of result, may be NULL
485 * @param[out] dst where to store the result
486 * @return
487 * #GNUNET_YES if all results could be extracted
488 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
489 */
490static int
491extract_abs_time (void *cls,
492 sqlite3_stmt *result,
493 unsigned int column,
494 size_t *dst_size,
495 void *dst)
496{
497 struct GNUNET_TIME_Absolute *u = dst;
498 struct GNUNET_TIME_Absolute t;
499
500 GNUNET_assert (sizeof (uint64_t) == *dst_size);
501 if (SQLITE_INTEGER !=
502 sqlite3_column_type (result,
503 column))
504 {
505 GNUNET_break (0);
506 return GNUNET_SYSERR;
507 }
508 t.abs_value_us = (uint64_t) sqlite3_column_int64 (result,
509 column);
510 if (INT64_MAX == t.abs_value_us)
511 t = GNUNET_TIME_UNIT_FOREVER_ABS;
512 *u = t;
513 return GNUNET_OK;
514}
515
516
517/**
462 * Absolute time expected. 518 * Absolute time expected.
463 * 519 *
464 * @param[out] at where to store the result 520 * @param[out] at where to store the result
@@ -467,7 +523,14 @@ GNUNET_SQ_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig)
467struct GNUNET_SQ_ResultSpec 523struct GNUNET_SQ_ResultSpec
468GNUNET_SQ_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at) 524GNUNET_SQ_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
469{ 525{
470 return GNUNET_SQ_result_spec_uint64 (&at->abs_value_us); 526 struct GNUNET_SQ_ResultSpec rs = {
527 .conv = &extract_abs_time,
528 .dst = at,
529 .dst_size = sizeof (struct GNUNET_TIME_Absolute),
530 .num_params = 1
531 };
532
533 return rs;
471} 534}
472 535
473 536
@@ -503,6 +566,8 @@ extract_abs_time_nbo (void *cls,
503 } 566 }
504 t.abs_value_us = (uint64_t) sqlite3_column_int64 (result, 567 t.abs_value_us = (uint64_t) sqlite3_column_int64 (result,
505 column); 568 column);
569 if (INT64_MAX == t.abs_value_us)
570 t = GNUNET_TIME_UNIT_FOREVER_ABS;
506 *u = GNUNET_TIME_absolute_hton (t); 571 *u = GNUNET_TIME_absolute_hton (t);
507 return GNUNET_OK; 572 return GNUNET_OK;
508} 573}