diff options
author | tg(x) <*@tg-x.net> | 2017-03-22 10:08:01 +0100 |
---|---|---|
committer | tg(x) <*@tg-x.net> | 2017-03-22 10:08:01 +0100 |
commit | aa98f144e6db0da5a0a4cad83fe64a80bbab6692 (patch) | |
tree | 5a072b4e1b689bf4330b2a412bdadc705d33ff75 /src/cadet | |
parent | caeeec6cacaa5354883494cb64b0a38e5c75da5d (diff) | |
parent | b424335cc632a11bd76bad5791cef10e8c985720 (diff) | |
download | gnunet-aa98f144e6db0da5a0a4cad83fe64a80bbab6692.tar.gz gnunet-aa98f144e6db0da5a0a4cad83fe64a80bbab6692.zip |
Merge branch 'master' of gnunet.org:gnunet
Diffstat (limited to 'src/cadet')
53 files changed, 6457 insertions, 29340 deletions
diff --git a/src/cadet/Makefile.am b/src/cadet/Makefile.am index b52079b2e..ce30ebe46 100644 --- a/src/cadet/Makefile.am +++ b/src/cadet/Makefile.am | |||
@@ -23,84 +23,48 @@ AM_CLFAGS = -g | |||
23 | 23 | ||
24 | libexec_PROGRAMS = \ | 24 | libexec_PROGRAMS = \ |
25 | gnunet-service-cadet \ | 25 | gnunet-service-cadet \ |
26 | gnunet-service-cadet-new \ | ||
27 | $(EXP_LIBEXEC) | 26 | $(EXP_LIBEXEC) |
28 | 27 | ||
29 | bin_PROGRAMS = \ | 28 | bin_PROGRAMS = \ |
30 | gnunet-cadet | 29 | gnunet-cadet |
31 | 30 | ||
32 | lib_LTLIBRARIES = \ | 31 | lib_LTLIBRARIES = \ |
33 | libgnunetcadetnew.la \ | ||
34 | libgnunetcadet.la \ | 32 | libgnunetcadet.la \ |
35 | $(EXP_LIB) | 33 | $(EXP_LIB) |
36 | 34 | ||
37 | libgnunetcadet_la_SOURCES = \ | 35 | libgnunetcadet_la_SOURCES = \ |
38 | cadet_api.c cadet_common.c | 36 | cadet_api.c |
39 | libgnunetcadet_la_LIBADD = \ | 37 | libgnunetcadet_la_LIBADD = \ |
40 | $(top_builddir)/src/util/libgnunetutil.la \ | 38 | $(top_builddir)/src/util/libgnunetutil.la \ |
41 | $(XLIB) \ | 39 | $(XLIB) \ |
42 | $(LTLIBINTL) | 40 | $(LTLIBINTL) |
43 | libgnunetcadet_la_LDFLAGS = \ | 41 | libgnunetcadet_la_LDFLAGS = \ |
44 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | 42 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ |
45 | -version-info 5:0:0 | 43 | -version-info 7:0:0 |
46 | |||
47 | |||
48 | libgnunetcadetnew_la_SOURCES = \ | ||
49 | cadet_api_new.c | ||
50 | libgnunetcadetnew_la_LIBADD = \ | ||
51 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
52 | $(XLIB) \ | ||
53 | $(LTLIBINTL) | ||
54 | libgnunetcadetnew_la_LDFLAGS = \ | ||
55 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | ||
56 | -version-info 6:0:0 | ||
57 | 44 | ||
58 | gnunet_cadet_SOURCES = \ | 45 | gnunet_cadet_SOURCES = \ |
59 | gnunet-cadet.c | 46 | gnunet-cadet.c |
60 | gnunet_cadet_LDADD = \ | 47 | gnunet_cadet_LDADD = \ |
61 | libgnunetcadetnew.la \ | 48 | libgnunetcadet.la \ |
62 | $(top_builddir)/src/util/libgnunetutil.la | 49 | $(top_builddir)/src/util/libgnunetutil.la |
63 | 50 | ||
64 | gnunet_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 | ||
74 | gnunet_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 | |||
85 | gnunet_service_cadet_SOURCES = \ | 51 | gnunet_service_cadet_SOURCES = \ |
86 | gnunet-service-cadet_tunnel.c gnunet-service-cadet_tunnel.h \ | 52 | 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 \ | 53 | gnunet-service-cadet_channel.c gnunet-service-cadet_channel.h \ |
89 | gnunet-service-cadet_local.c gnunet-service-cadet_local.h \ | 54 | gnunet-service-cadet_connection.c gnunet-service-cadet_connection.h \ |
90 | gnunet-service-cadet_peer.c gnunet-service-cadet_peer.h \ | 55 | gnunet-service-cadet_core.c gnunet-service-cadet_core.h \ |
91 | gnunet-service-cadet_dht.c gnunet-service-cadet_dht.h \ | 56 | gnunet-service-cadet_dht.c gnunet-service-cadet_dht.h \ |
92 | gnunet-service-cadet_hello.c gnunet-service-cadet_hello.h \ | 57 | gnunet-service-cadet_hello.c gnunet-service-cadet_hello.h \ |
93 | cadet_path.c cadet_path.h \ | 58 | gnunet-service-cadet_tunnels.c gnunet-service-cadet_tunnels.h \ |
94 | cadet_common.c \ | 59 | gnunet-service-cadet_paths.c gnunet-service-cadet_paths.h \ |
95 | gnunet-service-cadet.c | 60 | gnunet-service-cadet_peer.c gnunet-service-cadet_peer.h |
96 | gnunet_service_cadet_CFLAGS = $(AM_CFLAGS) | ||
97 | gnunet_service_cadet_LDADD = \ | 61 | gnunet_service_cadet_LDADD = \ |
98 | $(top_builddir)/src/util/libgnunetutil.la \ | 62 | $(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 \ | 63 | $(top_builddir)/src/ats/libgnunetats.la \ |
64 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
102 | $(top_builddir)/src/dht/libgnunetdht.la \ | 65 | $(top_builddir)/src/dht/libgnunetdht.la \ |
103 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 66 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
67 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
104 | $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ | 68 | $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ |
105 | $(top_builddir)/src/hello/libgnunethello.la \ | 69 | $(top_builddir)/src/hello/libgnunethello.la \ |
106 | $(top_builddir)/src/block/libgnunetblock.la | 70 | $(top_builddir)/src/block/libgnunetblock.la |
@@ -110,39 +74,14 @@ endif | |||
110 | 74 | ||
111 | 75 | ||
112 | if HAVE_TESTING | 76 | if HAVE_TESTING |
113 | noinst_LTLIBRARIES = libgnunetcadettest.la libgnunetcadettestnew.la $(noinst_LIB_EXP) | 77 | noinst_LTLIBRARIES = libgnunetcadettest.la $(noinst_LIB_EXP) |
114 | noinst_PROGRAMS = gnunet-cadet-profiler | 78 | # noinst_PROGRAMS = gnunet-cadet-profiler |
115 | endif | 79 | endif |
116 | 80 | ||
117 | libgnunetcadettest_la_SOURCES = \ | ||
118 | cadet_test_lib.c cadet_test_lib.h | ||
119 | libgnunetcadettest_la_LIBADD = \ | ||
120 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
121 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
122 | libgnunetcadet.la | ||
123 | |||
124 | if HAVE_TESTING | 81 | if HAVE_TESTING |
125 | check_PROGRAMS = \ | 82 | check_PROGRAMS = \ |
126 | test_cadet_local_mq \ | 83 | test_cadet_local_mq \ |
127 | test_cadet_2_forward_new \ | 84 | 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 \ | 85 | test_cadet_2_forward \ |
147 | test_cadet_2_signal \ | 86 | test_cadet_2_signal \ |
148 | test_cadet_2_keepalive \ | 87 | test_cadet_2_keepalive \ |
@@ -161,41 +100,39 @@ check_PROGRAMS = \ | |||
161 | test_cadet_5_speed_backwards | 100 | test_cadet_5_speed_backwards |
162 | endif | 101 | endif |
163 | 102 | ||
103 | |||
104 | #gnunet_cadet_profiler_SOURCES = \ | ||
105 | # gnunet-cadet-profiler.c | ||
106 | #gnunet_cadet_profiler_LDADD = $(ld_cadet_test_lib) | ||
107 | |||
108 | |||
109 | test_cadet_local_mq_SOURCES = \ | ||
110 | test_cadet_local_mq.c | ||
111 | test_cadet_local_mq_LDADD = \ | ||
112 | libgnunetcadet.la \ | ||
113 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
114 | $(top_builddir)/src/util/libgnunetutil.la | ||
115 | |||
116 | |||
117 | libgnunetcadettest_la_SOURCES = \ | ||
118 | cadet_test_lib.c cadet_test_lib.h | ||
119 | libgnunetcadettest_la_LIBADD = \ | ||
120 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
121 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
122 | libgnunetcadet.la | ||
123 | |||
164 | ld_cadet_test_lib = \ | 124 | ld_cadet_test_lib = \ |
165 | $(top_builddir)/src/util/libgnunetutil.la \ | 125 | $(top_builddir)/src/util/libgnunetutil.la \ |
166 | $(top_builddir)/src/testing/libgnunettesting.la \ | 126 | $(top_builddir)/src/testing/libgnunettesting.la \ |
167 | libgnunetcadettest.la \ | ||
168 | libgnunetcadet.la \ | 127 | libgnunetcadet.la \ |
128 | libgnunetcadettest.la \ | ||
169 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | 129 | $(top_builddir)/src/testbed/libgnunettestbed.la \ |
170 | $(top_builddir)/src/statistics/libgnunetstatistics.la | 130 | $(top_builddir)/src/statistics/libgnunetstatistics.la |
171 | |||
172 | dep_cadet_test_lib = \ | 131 | dep_cadet_test_lib = \ |
173 | libgnunetcadet.la \ | 132 | libgnunetcadet.la \ |
174 | libgnunetcadettest.la \ | 133 | libgnunetcadettest.la \ |
175 | $(top_builddir)/src/statistics/libgnunetstatistics.la | 134 | $(top_builddir)/src/statistics/libgnunetstatistics.la |
176 | 135 | ||
177 | |||
178 | gnunet_cadet_profiler_SOURCES = \ | ||
179 | gnunet-cadet-profiler.c | ||
180 | gnunet_cadet_profiler_LDADD = $(ld_cadet_test_lib) | ||
181 | |||
182 | |||
183 | test_cadet_single_SOURCES = \ | ||
184 | test_cadet_single.c | ||
185 | test_cadet_single_LDADD = $(ld_cadet_test_lib) | ||
186 | |||
187 | test_cadet_local_SOURCES = \ | ||
188 | test_cadet_local.c | ||
189 | test_cadet_local_LDADD = $(ld_cadet_test_lib) | ||
190 | |||
191 | |||
192 | test_cadet_local_mq_SOURCES = \ | ||
193 | test_cadet_local_mq.c | ||
194 | test_cadet_local_mq_LDADD = \ | ||
195 | libgnunetcadetnew.la \ | ||
196 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
197 | $(top_builddir)/src/util/libgnunetutil.la | ||
198 | |||
199 | test_cadet_2_forward_SOURCES = \ | 136 | test_cadet_2_forward_SOURCES = \ |
200 | test_cadet.c | 137 | test_cadet.c |
201 | test_cadet_2_forward_LDADD = $(ld_cadet_test_lib) | 138 | test_cadet_2_forward_LDADD = $(ld_cadet_test_lib) |
@@ -228,7 +165,6 @@ test_cadet_2_speed_reliable_backwards_SOURCES = \ | |||
228 | test_cadet.c | 165 | test_cadet.c |
229 | test_cadet_2_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib) | 166 | test_cadet_2_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib) |
230 | 167 | ||
231 | |||
232 | test_cadet_5_forward_SOURCES = \ | 168 | test_cadet_5_forward_SOURCES = \ |
233 | test_cadet.c | 169 | test_cadet.c |
234 | test_cadet_5_forward_LDADD = $(ld_cadet_test_lib) | 170 | test_cadet_5_forward_LDADD = $(ld_cadet_test_lib) |
@@ -262,92 +198,6 @@ test_cadet_5_speed_reliable_backwards_SOURCES = \ | |||
262 | test_cadet_5_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib) | 198 | test_cadet_5_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib) |
263 | 199 | ||
264 | 200 | ||
265 | # NEW TESTS | ||
266 | libgnunetcadettestnew_la_SOURCES = \ | ||
267 | cadet_test_lib_new.c cadet_test_lib_new.h | ||
268 | libgnunetcadettestnew_la_LIBADD = \ | ||
269 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
270 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
271 | libgnunetcadetnew.la | ||
272 | |||
273 | ld_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 | ||
280 | dep_cadet_test_lib_new = \ | ||
281 | libgnunetcadetnew.la \ | ||
282 | libgnunetcadettestnew.la \ | ||
283 | $(top_builddir)/src/statistics/libgnunetstatistics.la | ||
284 | |||
285 | test_cadet_2_forward_new_SOURCES = \ | ||
286 | test_cadet_new.c | ||
287 | test_cadet_2_forward_new_LDADD = $(ld_cadet_test_lib_new) | ||
288 | |||
289 | test_cadet_2_signal_new_SOURCES = \ | ||
290 | test_cadet_new.c | ||
291 | test_cadet_2_signal_new_LDADD = $(ld_cadet_test_lib_new) | ||
292 | |||
293 | test_cadet_2_keepalive_new_SOURCES = \ | ||
294 | test_cadet_new.c | ||
295 | test_cadet_2_keepalive_new_LDADD = $(ld_cadet_test_lib_new) | ||
296 | |||
297 | test_cadet_2_speed_new_SOURCES = \ | ||
298 | test_cadet_new.c | ||
299 | test_cadet_2_speed_new_LDADD = $(ld_cadet_test_lib_new) | ||
300 | |||
301 | test_cadet_2_speed_ack_new_SOURCES = \ | ||
302 | test_cadet_new.c | ||
303 | test_cadet_2_speed_ack_new_LDADD = $(ld_cadet_test_lib_new) | ||
304 | |||
305 | test_cadet_2_speed_backwards_new_SOURCES = \ | ||
306 | test_cadet_new.c | ||
307 | test_cadet_2_speed_backwards_new_LDADD = $(ld_cadet_test_lib_new) | ||
308 | |||
309 | test_cadet_2_speed_reliable_new_SOURCES = \ | ||
310 | test_cadet_new.c | ||
311 | test_cadet_2_speed_reliable_new_LDADD = $(ld_cadet_test_lib_new) | ||
312 | |||
313 | test_cadet_2_speed_reliable_backwards_new_SOURCES = \ | ||
314 | test_cadet_new.c | ||
315 | test_cadet_2_speed_reliable_backwards_new_LDADD = $(ld_cadet_test_lib_new) | ||
316 | |||
317 | |||
318 | test_cadet_5_forward_new_SOURCES = \ | ||
319 | test_cadet_new.c | ||
320 | test_cadet_5_forward_new_LDADD = $(ld_cadet_test_lib_new) | ||
321 | |||
322 | test_cadet_5_signal_new_SOURCES = \ | ||
323 | test_cadet_new.c | ||
324 | test_cadet_5_signal_new_LDADD = $(ld_cadet_test_lib_new) | ||
325 | |||
326 | test_cadet_5_keepalive_new_SOURCES = \ | ||
327 | test_cadet_new.c | ||
328 | test_cadet_5_keepalive_new_LDADD = $(ld_cadet_test_lib_new) | ||
329 | |||
330 | test_cadet_5_speed_new_SOURCES = \ | ||
331 | test_cadet_new.c | ||
332 | test_cadet_5_speed_new_LDADD = $(ld_cadet_test_lib_new) | ||
333 | |||
334 | test_cadet_5_speed_ack_new_SOURCES = \ | ||
335 | test_cadet_new.c | ||
336 | test_cadet_5_speed_ack_new_LDADD = $(ld_cadet_test_lib_new) | ||
337 | |||
338 | test_cadet_5_speed_backwards_new_SOURCES = \ | ||
339 | test_cadet_new.c | ||
340 | test_cadet_5_speed_backwards_new_LDADD = $(ld_cadet_test_lib_new) | ||
341 | |||
342 | test_cadet_5_speed_reliable_new_SOURCES = \ | ||
343 | test_cadet_new.c | ||
344 | test_cadet_5_speed_reliable_new_LDADD = $(ld_cadet_test_lib_new) | ||
345 | |||
346 | test_cadet_5_speed_reliable_backwards_new_SOURCES = \ | ||
347 | test_cadet_new.c | ||
348 | test_cadet_5_speed_reliable_backwards_new_LDADD = $(ld_cadet_test_lib_new) | ||
349 | |||
350 | |||
351 | if ENABLE_TEST_RUN | 201 | if ENABLE_TEST_RUN |
352 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | 202 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; |
353 | TESTS = \ | 203 | TESTS = \ |
diff --git a/src/cadet/TODO b/src/cadet/TODO index 820efab7a..06567b0ad 100644 --- a/src/cadet/TODO +++ b/src/cadet/TODO | |||
@@ -1,6 +1,10 @@ | |||
1 | - URGENT: Congestion/flow control (CHANNEL): | 1 | - URGENT: |
2 | + estimate max bandwidth using bursts and use to for CONGESTION CONTROL! | 2 | + if 'client-not-ready', we do not ACK at all, and sender keeps |
3 | (and figure out how/where to use this!) | 3 | retransmitting again and again; would be good to do flow-control notification instead |
4 | of not ACKing that we got the data but are simply not ready for more! | ||
5 | + Congestion/flow control (CHANNEL): | ||
6 | estimate max bandwidth using bursts and use to for CONGESTION CONTROL! | ||
7 | (and figure out how/where to use this!) | ||
4 | 8 | ||
5 | - HIGH: revisit handling of 'unbuffered' traffic! (CHANNEL/TUNNEL) | 9 | - HIGH: revisit handling of 'unbuffered' traffic! (CHANNEL/TUNNEL) |
6 | (need to push down through tunnel into connection selection); | 10 | (need to push down through tunnel into connection selection); |
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 | |||
3 | AUTOSTART = @AUTOSTART@ | 3 | AUTOSTART = @AUTOSTART@ |
4 | @JAVAPORT@PORT = 2096 | 4 | @JAVAPORT@PORT = 2096 |
5 | HOSTNAME = localhost | 5 | HOSTNAME = localhost |
6 | BINARY = gnunet-service-cadet-new | 6 | BINARY = gnunet-service-cadet |
7 | # PREFIX = valgrind --leak-check=yes | 7 | # PREFIX = valgrind --leak-check=yes |
8 | ACCEPT_FROM = 127.0.0.1; | 8 | ACCEPT_FROM = 127.0.0.1; |
9 | ACCEPT_FROM6 = ::1; | 9 | ACCEPT_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_api.c b/src/cadet/cadet_api.c index 7b9ac62b3..decf473a9 100644 --- a/src/cadet/cadet_api.c +++ b/src/cadet/cadet_api.c | |||
@@ -21,8 +21,8 @@ | |||
21 | * @file cadet/cadet_api.c | 21 | * @file cadet/cadet_api.c |
22 | * @brief cadet api: client implementation of cadet service | 22 | * @brief cadet api: client implementation of cadet service |
23 | * @author Bartlomiej Polot | 23 | * @author Bartlomiej Polot |
24 | * @author Christian Grothoff | ||
24 | */ | 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_constants.h" | 28 | #include "gnunet_constants.h" |
@@ -32,57 +32,9 @@ | |||
32 | 32 | ||
33 | #define LOG(kind,...) GNUNET_log_from (kind, "cadet-api",__VA_ARGS__) | 33 | #define LOG(kind,...) GNUNET_log_from (kind, "cadet-api",__VA_ARGS__) |
34 | 34 | ||
35 | /******************************************************************************/ | ||
36 | /************************ DATA STRUCTURES ****************************/ | ||
37 | /******************************************************************************/ | ||
38 | |||
39 | /** | 35 | /** |
40 | * Transmission queue to the service | 36 | * Ugly legacy hack. |
41 | * | ||
42 | * @deprecated | ||
43 | */ | 37 | */ |
44 | struct GNUNET_CADET_TransmitHandle | ||
45 | { | ||
46 | /** | ||
47 | * Double Linked list | ||
48 | */ | ||
49 | struct GNUNET_CADET_TransmitHandle *next; | ||
50 | |||
51 | /** | ||
52 | * Double Linked list | ||
53 | */ | ||
54 | struct GNUNET_CADET_TransmitHandle *prev; | ||
55 | |||
56 | /** | ||
57 | * Channel this message is sent on / for (may be NULL for control messages). | ||
58 | */ | ||
59 | struct GNUNET_CADET_Channel *channel; | ||
60 | |||
61 | /** | ||
62 | * Request data task. | ||
63 | */ | ||
64 | struct GNUNET_SCHEDULER_Task *request_data_task; | ||
65 | |||
66 | /** | ||
67 | * Callback to obtain the message to transmit, or NULL if we | ||
68 | * got the message in 'data'. Notice that messages built | ||
69 | * by 'notify' need to be encapsulated with information about | ||
70 | * the 'target'. | ||
71 | */ | ||
72 | GNUNET_CONNECTION_TransmitReadyNotify notify; | ||
73 | |||
74 | /** | ||
75 | * Closure for 'notify' | ||
76 | */ | ||
77 | void *notify_cls; | ||
78 | |||
79 | /** | ||
80 | * Size of the payload. | ||
81 | */ | ||
82 | size_t size; | ||
83 | }; | ||
84 | |||
85 | |||
86 | union CadetInfoCB | 38 | union CadetInfoCB |
87 | { | 39 | { |
88 | 40 | ||
@@ -119,69 +71,19 @@ union CadetInfoCB | |||
119 | struct GNUNET_CADET_Handle | 71 | struct GNUNET_CADET_Handle |
120 | { | 72 | { |
121 | /** | 73 | /** |
122 | * Flag to indicate old or MQ API. | 74 | * Message queue. |
123 | */ | ||
124 | int mq_api; | ||
125 | |||
126 | /** | ||
127 | * Message queue (if available). | ||
128 | */ | 75 | */ |
129 | struct GNUNET_MQ_Handle *mq; | 76 | struct GNUNET_MQ_Handle *mq; |
130 | 77 | ||
131 | /** | 78 | /** |
132 | * Set of handlers used for processing incoming messages in the channels | ||
133 | * | ||
134 | * @deprecated | ||
135 | */ | ||
136 | const struct GNUNET_CADET_MessageHandler *message_handlers; | ||
137 | |||
138 | /** | ||
139 | * Number of handlers in the handlers array. | ||
140 | * | ||
141 | * @deprecated | ||
142 | */ | ||
143 | unsigned int n_handlers; | ||
144 | |||
145 | /** | ||
146 | * Ports open. | 79 | * Ports open. |
147 | */ | 80 | */ |
148 | struct GNUNET_CONTAINER_MultiHashMap *ports; | 81 | struct GNUNET_CONTAINER_MultiHashMap *ports; |
149 | 82 | ||
150 | /** | 83 | /** |
151 | * Double linked list of the channels this client is connected to, head. | 84 | * Channels open. |
152 | */ | 85 | */ |
153 | struct GNUNET_CADET_Channel *channels_head; | 86 | struct GNUNET_CONTAINER_MultiHashMap32 *channels; |
154 | |||
155 | /** | ||
156 | * Double linked list of the channels this client is connected to, tail. | ||
157 | */ | ||
158 | struct GNUNET_CADET_Channel *channels_tail; | ||
159 | |||
160 | /** | ||
161 | * Callback for inbound channel disconnection | ||
162 | */ | ||
163 | GNUNET_CADET_ChannelEndHandler *cleaner; | ||
164 | |||
165 | /** | ||
166 | * Closure for all the handlers given by the client | ||
167 | * | ||
168 | * @deprecated | ||
169 | */ | ||
170 | void *cls; | ||
171 | |||
172 | /** | ||
173 | * Messages to send to the service, head. | ||
174 | * | ||
175 | * @deprecated | ||
176 | */ | ||
177 | struct GNUNET_CADET_TransmitHandle *th_head; | ||
178 | |||
179 | /** | ||
180 | * Messages to send to the service, tail. | ||
181 | * | ||
182 | * @deprecated | ||
183 | */ | ||
184 | struct GNUNET_CADET_TransmitHandle *th_tail; | ||
185 | 87 | ||
186 | /** | 88 | /** |
187 | * child of the next channel to create (to avoid reusing IDs often) | 89 | * child of the next channel to create (to avoid reusing IDs often) |
@@ -194,14 +96,9 @@ struct GNUNET_CADET_Handle | |||
194 | const struct GNUNET_CONFIGURATION_Handle *cfg; | 96 | const struct GNUNET_CONFIGURATION_Handle *cfg; |
195 | 97 | ||
196 | /** | 98 | /** |
197 | * Time to the next reconnect in case one reconnect fails | ||
198 | */ | ||
199 | struct GNUNET_TIME_Relative reconnect_time; | ||
200 | |||
201 | /** | ||
202 | * Task for trying to reconnect. | 99 | * Task for trying to reconnect. |
203 | */ | 100 | */ |
204 | struct GNUNET_SCHEDULER_Task * reconnect_task; | 101 | struct GNUNET_SCHEDULER_Task *reconnect_task; |
205 | 102 | ||
206 | /** | 103 | /** |
207 | * Callback for an info task (only one active at a time). | 104 | * Callback for an info task (only one active at a time). |
@@ -212,23 +109,12 @@ struct GNUNET_CADET_Handle | |||
212 | * Info callback closure for @c info_cb. | 109 | * Info callback closure for @c info_cb. |
213 | */ | 110 | */ |
214 | void *info_cls; | 111 | void *info_cls; |
215 | }; | ||
216 | |||
217 | 112 | ||
218 | /** | ||
219 | * Description of a peer | ||
220 | */ | ||
221 | struct GNUNET_CADET_Peer | ||
222 | { | ||
223 | /** | 113 | /** |
224 | * ID of the peer in short form | 114 | * Time to the next reconnect in case one reconnect fails |
225 | */ | 115 | */ |
226 | GNUNET_PEER_Id id; | 116 | struct GNUNET_TIME_Relative reconnect_time; |
227 | 117 | ||
228 | /** | ||
229 | * Channel this peer belongs to | ||
230 | */ | ||
231 | struct GNUNET_CADET_Channel *t; | ||
232 | }; | 118 | }; |
233 | 119 | ||
234 | 120 | ||
@@ -237,15 +123,11 @@ struct GNUNET_CADET_Peer | |||
237 | */ | 123 | */ |
238 | struct GNUNET_CADET_Channel | 124 | struct GNUNET_CADET_Channel |
239 | { | 125 | { |
240 | /** | ||
241 | * DLL next | ||
242 | */ | ||
243 | struct GNUNET_CADET_Channel *next; | ||
244 | 126 | ||
245 | /** | 127 | /** |
246 | * DLL prev | 128 | * Other end of the channel. |
247 | */ | 129 | */ |
248 | struct GNUNET_CADET_Channel *prev; | 130 | struct GNUNET_PeerIdentity peer; |
249 | 131 | ||
250 | /** | 132 | /** |
251 | * Handle to the cadet this channel belongs to | 133 | * Handle to the cadet this channel belongs to |
@@ -253,40 +135,18 @@ struct GNUNET_CADET_Channel | |||
253 | struct GNUNET_CADET_Handle *cadet; | 135 | struct GNUNET_CADET_Handle *cadet; |
254 | 136 | ||
255 | /** | 137 | /** |
256 | * Local ID of the channel | ||
257 | */ | ||
258 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
259 | |||
260 | /** | ||
261 | * Channel's port, if incoming. | 138 | * Channel's port, if incoming. |
262 | */ | 139 | */ |
263 | struct GNUNET_CADET_Port *incoming_port; | 140 | struct GNUNET_CADET_Port *incoming_port; |
264 | 141 | ||
265 | /** | 142 | /** |
266 | * Other end of the channel. | 143 | * Any data the caller wants to put in here, used for the |
267 | */ | 144 | * various callbacks (@e disconnects, @e window_changes, handlers). |
268 | GNUNET_PEER_Id peer; | ||
269 | |||
270 | /** | ||
271 | * Any data the caller wants to put in here | ||
272 | */ | 145 | */ |
273 | void *ctx; | 146 | void *ctx; |
274 | 147 | ||
275 | /** | 148 | /** |
276 | * Channel options: reliability, etc. | 149 | * Message Queue for the channel (which we are implementing). |
277 | */ | ||
278 | enum GNUNET_CADET_ChannelOption options; | ||
279 | |||
280 | /** | ||
281 | * Are we allowed to send to the service? | ||
282 | * | ||
283 | * @deprecated? | ||
284 | */ | ||
285 | unsigned int allow_send; | ||
286 | |||
287 | /***************************** MQ ************************************/ | ||
288 | /** | ||
289 | * Message Queue for the channel. | ||
290 | */ | 150 | */ |
291 | struct GNUNET_MQ_Handle *mq; | 151 | struct GNUNET_MQ_Handle *mq; |
292 | 152 | ||
@@ -296,7 +156,9 @@ struct GNUNET_CADET_Channel | |||
296 | struct GNUNET_SCHEDULER_Task *mq_cont; | 156 | struct GNUNET_SCHEDULER_Task *mq_cont; |
297 | 157 | ||
298 | /** | 158 | /** |
299 | * Pending envelope in case we don't have an ACK from the service. | 159 | * Pending envelope with a message to be transmitted to the |
160 | * service as soon as we are allowed to. Should only be | ||
161 | * non-NULL if @e allow_send is 0. | ||
300 | */ | 162 | */ |
301 | struct GNUNET_MQ_Envelope *pending_env; | 163 | struct GNUNET_MQ_Envelope *pending_env; |
302 | 164 | ||
@@ -310,6 +172,21 @@ struct GNUNET_CADET_Channel | |||
310 | */ | 172 | */ |
311 | GNUNET_CADET_DisconnectEventHandler disconnects; | 173 | GNUNET_CADET_DisconnectEventHandler disconnects; |
312 | 174 | ||
175 | /** | ||
176 | * Local ID of the channel, #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI bit is set if outbound. | ||
177 | */ | ||
178 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
179 | |||
180 | /** | ||
181 | * Channel options: reliability, etc. | ||
182 | */ | ||
183 | enum GNUNET_CADET_ChannelOption options; | ||
184 | |||
185 | /** | ||
186 | * How many messages are we allowed to send to the service right now? | ||
187 | */ | ||
188 | unsigned int allow_send; | ||
189 | |||
313 | }; | 190 | }; |
314 | 191 | ||
315 | 192 | ||
@@ -318,35 +195,22 @@ struct GNUNET_CADET_Channel | |||
318 | */ | 195 | */ |
319 | struct GNUNET_CADET_Port | 196 | struct GNUNET_CADET_Port |
320 | { | 197 | { |
321 | /** | ||
322 | * Handle to the CADET session this port belongs to. | ||
323 | */ | ||
324 | struct GNUNET_CADET_Handle *cadet; | ||
325 | 198 | ||
326 | /** | 199 | /** |
327 | * Port ID. | 200 | * Port "number" |
328 | * | ||
329 | * @deprecated | ||
330 | */ | 201 | */ |
331 | struct GNUNET_HashCode *hash; | 202 | struct GNUNET_HashCode id; |
332 | 203 | ||
333 | /** | 204 | /** |
334 | * Callback handler for incoming channels on this port. | 205 | * Handle to the CADET session this port belongs to. |
335 | */ | 206 | */ |
336 | GNUNET_CADET_InboundChannelNotificationHandler *handler; | 207 | struct GNUNET_CADET_Handle *cadet; |
337 | 208 | ||
338 | /** | 209 | /** |
339 | * Closure for @a handler. | 210 | * Closure for @a handler. |
340 | */ | 211 | */ |
341 | void *cls; | 212 | void *cls; |
342 | 213 | ||
343 | /***************************** MQ ************************************/ | ||
344 | |||
345 | /** | ||
346 | * Port "number" | ||
347 | */ | ||
348 | struct GNUNET_HashCode id; | ||
349 | |||
350 | /** | 214 | /** |
351 | * Handler for incoming channels on this port | 215 | * Handler for incoming channels on this port |
352 | */ | 216 | */ |
@@ -355,7 +219,7 @@ struct GNUNET_CADET_Port | |||
355 | /** | 219 | /** |
356 | * Closure for @ref connects | 220 | * Closure for @ref connects |
357 | */ | 221 | */ |
358 | void * connects_cls; | 222 | void *connects_cls; |
359 | 223 | ||
360 | /** | 224 | /** |
361 | * Window size change handler. | 225 | * Window size change handler. |
@@ -363,106 +227,30 @@ struct GNUNET_CADET_Port | |||
363 | GNUNET_CADET_WindowSizeEventHandler window_changes; | 227 | GNUNET_CADET_WindowSizeEventHandler window_changes; |
364 | 228 | ||
365 | /** | 229 | /** |
366 | * Handler called when an incoming channel is destroyed.. | 230 | * Handler called when an incoming channel is destroyed. |
367 | */ | 231 | */ |
368 | GNUNET_CADET_DisconnectEventHandler disconnects; | 232 | GNUNET_CADET_DisconnectEventHandler disconnects; |
369 | 233 | ||
370 | /** | 234 | /** |
371 | * Payload handlers for incoming channels. | 235 | * Payload handlers for incoming channels. |
372 | */ | 236 | */ |
373 | const struct GNUNET_MQ_MessageHandler *handlers; | 237 | struct GNUNET_MQ_MessageHandler *handlers; |
374 | }; | 238 | }; |
375 | 239 | ||
376 | 240 | ||
377 | /** | 241 | /** |
378 | * Implementation state for cadet's message queue. | ||
379 | */ | ||
380 | struct CadetMQState | ||
381 | { | ||
382 | /** | ||
383 | * The current transmit handle, or NULL | ||
384 | * if no transmit is active. | ||
385 | */ | ||
386 | struct GNUNET_CADET_TransmitHandle *th; | ||
387 | |||
388 | /** | ||
389 | * Channel to send the data over. | ||
390 | */ | ||
391 | struct GNUNET_CADET_Channel *channel; | ||
392 | }; | ||
393 | |||
394 | |||
395 | |||
396 | /******************************************************************************/ | ||
397 | /********************* FUNCTION DECLARATIONS *************************/ | ||
398 | /******************************************************************************/ | ||
399 | |||
400 | /** | ||
401 | * Reconnect to the service, retransmit all infomation to try to restore the | ||
402 | * original state. | ||
403 | * | ||
404 | * @param h Handle to the CADET service. | ||
405 | */ | ||
406 | static void | ||
407 | schedule_reconnect (struct GNUNET_CADET_Handle *h); | ||
408 | |||
409 | |||
410 | /** | ||
411 | * Reconnect callback: tries to reconnect again after a failer previous | ||
412 | * reconnection. | ||
413 | * | ||
414 | * @param cls Closure (cadet handle). | ||
415 | */ | ||
416 | static void | ||
417 | reconnect_cbk (void *cls); | ||
418 | |||
419 | |||
420 | /** | ||
421 | * Reconnect to the service, retransmit all infomation to try to restore the | ||
422 | * original state. | ||
423 | * | ||
424 | * @param h handle to the cadet | ||
425 | */ | ||
426 | static void | ||
427 | reconnect (struct GNUNET_CADET_Handle *h); | ||
428 | |||
429 | |||
430 | /******************************************************************************/ | ||
431 | /*********************** AUXILIARY FUNCTIONS *************************/ | ||
432 | /******************************************************************************/ | ||
433 | |||
434 | /** | ||
435 | * Check if transmission is a payload packet. | ||
436 | * | ||
437 | * @param th Transmission handle. | ||
438 | * | ||
439 | * @return #GNUNET_YES if it is a payload packet, | ||
440 | * #GNUNET_NO if it is a cadet management packet. | ||
441 | */ | ||
442 | static int | ||
443 | th_is_payload (struct GNUNET_CADET_TransmitHandle *th) | ||
444 | { | ||
445 | return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO; | ||
446 | } | ||
447 | |||
448 | |||
449 | /** | ||
450 | * Find the Port struct for a hash. | 242 | * Find the Port struct for a hash. |
451 | * | 243 | * |
452 | * @param h CADET handle. | 244 | * @param h CADET handle. |
453 | * @param hash HashCode for the port number. | 245 | * @param hash HashCode for the port number. |
454 | * | ||
455 | * @return The port handle if known, NULL otherwise. | 246 | * @return The port handle if known, NULL otherwise. |
456 | */ | 247 | */ |
457 | static struct GNUNET_CADET_Port * | 248 | static struct GNUNET_CADET_Port * |
458 | find_port (const struct GNUNET_CADET_Handle *h, | 249 | find_port (const struct GNUNET_CADET_Handle *h, |
459 | const struct GNUNET_HashCode *hash) | 250 | const struct GNUNET_HashCode *hash) |
460 | { | 251 | { |
461 | struct GNUNET_CADET_Port *p; | 252 | return GNUNET_CONTAINER_multihashmap_get (h->ports, |
462 | 253 | hash); | |
463 | p = GNUNET_CONTAINER_multihashmap_get (h->ports, hash); | ||
464 | |||
465 | return p; | ||
466 | } | 254 | } |
467 | 255 | ||
468 | 256 | ||
@@ -474,15 +262,11 @@ find_port (const struct GNUNET_CADET_Handle *h, | |||
474 | * @return handle to the required channel or NULL if not found | 262 | * @return handle to the required channel or NULL if not found |
475 | */ | 263 | */ |
476 | static struct GNUNET_CADET_Channel * | 264 | static struct GNUNET_CADET_Channel * |
477 | retrieve_channel (struct GNUNET_CADET_Handle *h, | 265 | find_channel (struct GNUNET_CADET_Handle *h, |
478 | struct GNUNET_CADET_ClientChannelNumber ccn) | 266 | struct GNUNET_CADET_ClientChannelNumber ccn) |
479 | { | 267 | { |
480 | struct GNUNET_CADET_Channel *ch; | 268 | return GNUNET_CONTAINER_multihashmap32_get (h->channels, |
481 | 269 | ntohl (ccn.channel_of_client)); | |
482 | for (ch = h->channels_head; NULL != ch; ch = ch->next) | ||
483 | if (ch->ccn.channel_of_client == ccn.channel_of_client) | ||
484 | return ch; | ||
485 | return NULL; | ||
486 | } | 270 | } |
487 | 271 | ||
488 | 272 | ||
@@ -490,38 +274,37 @@ retrieve_channel (struct GNUNET_CADET_Handle *h, | |||
490 | * Create a new channel and insert it in the channel list of the cadet handle | 274 | * Create a new channel and insert it in the channel list of the cadet handle |
491 | * | 275 | * |
492 | * @param h Cadet handle | 276 | * @param h Cadet handle |
493 | * @param ccn Desired ccn of the channel, 0 to assign one automatically. | 277 | * @param ccnp pointer to desired ccn of the channel, NULL to assign one automatically. |
494 | * | ||
495 | * @return Handle to the created channel. | 278 | * @return Handle to the created channel. |
496 | */ | 279 | */ |
497 | static struct GNUNET_CADET_Channel * | 280 | static struct GNUNET_CADET_Channel * |
498 | create_channel (struct GNUNET_CADET_Handle *h, | 281 | create_channel (struct GNUNET_CADET_Handle *h, |
499 | struct GNUNET_CADET_ClientChannelNumber ccn) | 282 | const struct GNUNET_CADET_ClientChannelNumber *ccnp) |
500 | { | 283 | { |
501 | struct GNUNET_CADET_Channel *ch; | 284 | struct GNUNET_CADET_Channel *ch; |
285 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
502 | 286 | ||
503 | ch = GNUNET_new (struct GNUNET_CADET_Channel); | 287 | ch = GNUNET_new (struct GNUNET_CADET_Channel); |
504 | GNUNET_CONTAINER_DLL_insert (h->channels_head, | ||
505 | h->channels_tail, | ||
506 | ch); | ||
507 | ch->cadet = h; | 288 | ch->cadet = h; |
508 | if (0 == ccn.channel_of_client) | 289 | if (NULL == ccnp) |
509 | { | 290 | { |
510 | ch->ccn = h->next_ccn; | 291 | while (NULL != |
511 | while (NULL != retrieve_channel (h, | 292 | find_channel (h, |
512 | h->next_ccn)) | 293 | h->next_ccn)) |
513 | { | ||
514 | h->next_ccn.channel_of_client | 294 | h->next_ccn.channel_of_client |
515 | = htonl (1 + ntohl (h->next_ccn.channel_of_client)); | 295 | = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI | (1 + ntohl (h->next_ccn.channel_of_client))); |
516 | if (0 == ntohl (h->next_ccn.channel_of_client)) | 296 | ccn = h->next_ccn; |
517 | h->next_ccn.channel_of_client | ||
518 | = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
519 | } | ||
520 | } | 297 | } |
521 | else | 298 | else |
522 | { | 299 | { |
523 | ch->ccn = ccn; | 300 | ccn = *ccnp; |
524 | } | 301 | } |
302 | ch->ccn = ccn; | ||
303 | GNUNET_assert (GNUNET_OK == | ||
304 | GNUNET_CONTAINER_multihashmap32_put (h->channels, | ||
305 | ntohl (ch->ccn.channel_of_client), | ||
306 | ch, | ||
307 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
525 | return ch; | 308 | return ch; |
526 | } | 309 | } |
527 | 310 | ||
@@ -535,114 +318,106 @@ create_channel (struct GNUNET_CADET_Handle *h, | |||
535 | * | 318 | * |
536 | * @param ch Pointer to the channel. | 319 | * @param ch Pointer to the channel. |
537 | * @param call_cleaner Whether to call the cleaner handler. | 320 | * @param call_cleaner Whether to call the cleaner handler. |
538 | * | ||
539 | * @return Handle to the required channel or NULL if not found. | ||
540 | */ | 321 | */ |
541 | static void | 322 | static void |
542 | destroy_channel (struct GNUNET_CADET_Channel *ch) | 323 | destroy_channel (struct GNUNET_CADET_Channel *ch) |
543 | { | 324 | { |
544 | struct GNUNET_CADET_Handle *h; | 325 | struct GNUNET_CADET_Handle *h = ch->cadet; |
545 | struct GNUNET_CADET_TransmitHandle *th; | ||
546 | struct GNUNET_CADET_TransmitHandle *next; | ||
547 | 326 | ||
548 | if (NULL == ch) | ||
549 | { | ||
550 | GNUNET_break (0); | ||
551 | return; | ||
552 | } | ||
553 | h = ch->cadet; | ||
554 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 327 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
555 | " destroy_channel %X of %p\n", | 328 | "Destroying channel %X of %p\n", |
556 | ch->ccn, | 329 | ch->ccn, |
557 | h); | 330 | h); |
558 | 331 | GNUNET_assert (GNUNET_YES == | |
559 | GNUNET_CONTAINER_DLL_remove (h->channels_head, | 332 | GNUNET_CONTAINER_multihashmap32_remove (h->channels, |
560 | h->channels_tail, | 333 | ntohl (ch->ccn.channel_of_client), |
561 | ch); | 334 | ch)); |
562 | if (NULL != ch->mq_cont) | 335 | if (NULL != ch->mq_cont) |
563 | { | 336 | { |
564 | GNUNET_SCHEDULER_cancel (ch->mq_cont); | 337 | GNUNET_SCHEDULER_cancel (ch->mq_cont); |
565 | ch->mq_cont = NULL; | 338 | ch->mq_cont = NULL; |
566 | } | 339 | } |
567 | /* signal channel destruction */ | 340 | /* signal channel destruction */ |
568 | if (0 != ch->peer) | 341 | if (NULL != ch->disconnects) |
569 | { | 342 | ch->disconnects (ch->ctx, |
570 | if (NULL != h->cleaner) | 343 | ch); |
571 | { | 344 | if (NULL != ch->pending_env) |
572 | /** @a deprecated */ | 345 | GNUNET_MQ_discard (ch->pending_env); |
573 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 346 | GNUNET_MQ_destroy (ch->mq); |
574 | " calling cleaner\n"); | ||
575 | h->cleaner (h->cls, ch, ch->ctx); | ||
576 | } | ||
577 | else if (NULL != ch->disconnects) | ||
578 | { | ||
579 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
580 | " calling disconnect handler\n"); | ||
581 | ch->disconnects (ch->ctx, ch); | ||
582 | } | ||
583 | else | ||
584 | { | ||
585 | /* Application won't be aware of the channel destruction and use | ||
586 | * a pointer to free'd memory. | ||
587 | */ | ||
588 | GNUNET_assert (0); | ||
589 | } | ||
590 | } | ||
591 | |||
592 | /* check that clients did not leave messages behind in the queue */ | ||
593 | for (th = h->th_head; NULL != th; th = next) | ||
594 | { | ||
595 | next = th->next; | ||
596 | if (th->channel != ch) | ||
597 | continue; | ||
598 | /* Clients should have aborted their requests already. | ||
599 | * Management traffic should be ok, as clients can't cancel that. | ||
600 | * If the service crashed and we are reconnecting, it's ok. | ||
601 | */ | ||
602 | GNUNET_break (GNUNET_NO == th_is_payload (th)); | ||
603 | GNUNET_CADET_notify_transmit_ready_cancel (th); | ||
604 | } | ||
605 | |||
606 | if (0 != ch->peer) | ||
607 | GNUNET_PEER_change_rc (ch->peer, -1); | ||
608 | GNUNET_free (ch); | 347 | GNUNET_free (ch); |
609 | } | 348 | } |
610 | 349 | ||
611 | 350 | ||
612 | /** | 351 | /** |
613 | * Add a transmit handle to the transmission queue and set the | 352 | * Reconnect to the service, retransmit all infomation to try to restore the |
614 | * timeout if needed. | 353 | * original state. |
354 | * | ||
355 | * @param h handle to the cadet | ||
356 | */ | ||
357 | static void | ||
358 | reconnect (struct GNUNET_CADET_Handle *h); | ||
359 | |||
360 | |||
361 | /** | ||
362 | * Reconnect callback: tries to reconnect again after a failer previous | ||
363 | * reconnecttion | ||
615 | * | 364 | * |
616 | * @param h cadet handle with the queue head and tail | 365 | * @param cls closure (cadet handle) |
617 | * @param th handle to the packet to be transmitted | ||
618 | */ | 366 | */ |
619 | static void | 367 | static void |
620 | add_to_queue (struct GNUNET_CADET_Handle *h, | 368 | reconnect_cbk (void *cls) |
621 | struct GNUNET_CADET_TransmitHandle *th) | 369 | { |
370 | struct GNUNET_CADET_Handle *h = cls; | ||
371 | |||
372 | h->reconnect_task = NULL; | ||
373 | reconnect (h); | ||
374 | } | ||
375 | |||
376 | |||
377 | /** | ||
378 | * Function called during #reconnect() to destroy | ||
379 | * all channels that are still open. | ||
380 | * | ||
381 | * @param cls the `struct GNUNET_CADET_Handle` | ||
382 | * @param cid chanenl ID | ||
383 | * @param value a `struct GNUNET_CADET_Channel` to destroy | ||
384 | * @return #GNUNET_OK (continue to iterate) | ||
385 | */ | ||
386 | static int | ||
387 | destroy_channel_on_reconnect_cb (void *cls, | ||
388 | uint32_t cid, | ||
389 | void *value) | ||
622 | { | 390 | { |
623 | GNUNET_CONTAINER_DLL_insert_tail (h->th_head, | 391 | /* struct GNUNET_CADET_Handle *handle = cls; */ |
624 | h->th_tail, | 392 | struct GNUNET_CADET_Channel *ch = value; |
625 | th); | 393 | |
394 | destroy_channel (ch); | ||
395 | return GNUNET_OK; | ||
626 | } | 396 | } |
627 | 397 | ||
628 | 398 | ||
629 | /** | 399 | /** |
630 | * Remove a transmit handle from the transmission queue, if present. | 400 | * Reconnect to the service, retransmit all infomation to try to restore the |
401 | * original state. | ||
631 | * | 402 | * |
632 | * Safe to call even if not queued. | 403 | * @param h handle to the cadet |
633 | * | 404 | * |
634 | * @param th handle to the packet to be unqueued. | 405 | * @return #GNUNET_YES in case of sucess, #GNUNET_NO otherwise (service down...) |
635 | */ | 406 | */ |
636 | static void | 407 | static void |
637 | remove_from_queue (struct GNUNET_CADET_TransmitHandle *th) | 408 | schedule_reconnect (struct GNUNET_CADET_Handle *h) |
638 | { | 409 | { |
639 | struct GNUNET_CADET_Handle *h = th->channel->cadet; | 410 | if (NULL != h->reconnect_task) |
640 | 411 | return; | |
641 | /* It might or might not have been queued (rarely not), but check anyway. */ | 412 | GNUNET_CONTAINER_multihashmap32_iterate (h->channels, |
642 | if (NULL != th->next || h->th_tail == th) | 413 | &destroy_channel_on_reconnect_cb, |
643 | { | 414 | h); |
644 | GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th); | 415 | h->reconnect_task |
645 | } | 416 | = GNUNET_SCHEDULER_add_delayed (h->reconnect_time, |
417 | &reconnect_cbk, | ||
418 | h); | ||
419 | h->reconnect_time | ||
420 | = GNUNET_TIME_STD_BACKOFF (h->reconnect_time); | ||
646 | } | 421 | } |
647 | 422 | ||
648 | 423 | ||
@@ -655,29 +430,44 @@ static void | |||
655 | notify_window_size (struct GNUNET_CADET_Channel *ch) | 430 | notify_window_size (struct GNUNET_CADET_Channel *ch) |
656 | { | 431 | { |
657 | if (NULL != ch->window_changes) | 432 | if (NULL != ch->window_changes) |
658 | { | 433 | ch->window_changes (ch->ctx, |
659 | ch->window_changes (ch->ctx, ch, ch->allow_send); | 434 | ch, /* FIXME: remove 'ch'? */ |
660 | } | 435 | ch->allow_send); |
661 | } | 436 | } |
662 | 437 | ||
663 | /******************************************************************************/ | ||
664 | /*********************** MQ API CALLBACKS ****************************/ | ||
665 | /******************************************************************************/ | ||
666 | 438 | ||
667 | /** | 439 | /** |
668 | * Allow the MQ implementation to send the next message. | 440 | * Transmit the next message from our queue. |
669 | * | 441 | * |
670 | * @param cls Closure (channel whose mq to activate). | 442 | * @param cls Closure (channel whose mq to activate). |
671 | */ | 443 | */ |
672 | static void | 444 | static void |
673 | cadet_mq_send_continue (void *cls) | 445 | cadet_mq_send_now (void *cls) |
674 | { | 446 | { |
675 | struct GNUNET_CADET_Channel *ch = cls; | 447 | struct GNUNET_CADET_Channel *ch = cls; |
448 | struct GNUNET_MQ_Envelope *env = ch->pending_env; | ||
676 | 449 | ||
677 | ch->mq_cont = NULL; | 450 | ch->mq_cont = NULL; |
451 | if (0 == ch->allow_send) | ||
452 | { | ||
453 | /* how did we get here? */ | ||
454 | GNUNET_break (0); | ||
455 | return; | ||
456 | } | ||
457 | if (NULL == env) | ||
458 | { | ||
459 | /* how did we get here? */ | ||
460 | GNUNET_break (0); | ||
461 | return; | ||
462 | } | ||
463 | ch->allow_send--; | ||
464 | ch->pending_env = NULL; | ||
465 | GNUNET_MQ_send (ch->cadet->mq, | ||
466 | env); | ||
678 | GNUNET_MQ_impl_send_continue (ch->mq); | 467 | GNUNET_MQ_impl_send_continue (ch->mq); |
679 | } | 468 | } |
680 | 469 | ||
470 | |||
681 | /** | 471 | /** |
682 | * Implement sending functionality of a message queue for | 472 | * Implement sending functionality of a message queue for |
683 | * us sending messages to a peer. | 473 | * us sending messages to a peer. |
@@ -701,7 +491,6 @@ cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq, | |||
701 | struct GNUNET_MQ_Envelope *env; | 491 | struct GNUNET_MQ_Envelope *env; |
702 | struct GNUNET_CADET_LocalData *cadet_msg; | 492 | struct GNUNET_CADET_LocalData *cadet_msg; |
703 | 493 | ||
704 | |||
705 | if (NULL == h->mq) | 494 | if (NULL == h->mq) |
706 | { | 495 | { |
707 | /* We're currently reconnecting, pretend this worked */ | 496 | /* We're currently reconnecting, pretend this worked */ |
@@ -717,26 +506,16 @@ cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq, | |||
717 | GNUNET_MQ_impl_send_continue (mq); | 506 | GNUNET_MQ_impl_send_continue (mq); |
718 | return; | 507 | return; |
719 | } | 508 | } |
720 | |||
721 | env = GNUNET_MQ_msg_nested_mh (cadet_msg, | 509 | env = GNUNET_MQ_msg_nested_mh (cadet_msg, |
722 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, | 510 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, |
723 | msg); | 511 | msg); |
724 | cadet_msg->ccn = ch->ccn; | 512 | cadet_msg->ccn = ch->ccn; |
725 | 513 | GNUNET_assert (NULL == ch->pending_env); | |
514 | ch->pending_env = env; | ||
726 | if (0 < ch->allow_send) | 515 | if (0 < ch->allow_send) |
727 | { | 516 | ch->mq_cont |
728 | /* Service has allowed this message, just send it and continue accepting */ | 517 | = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now, |
729 | GNUNET_MQ_send (h->mq, env); | 518 | ch); |
730 | ch->allow_send--; | ||
731 | ch->mq_cont = GNUNET_SCHEDULER_add_now (&cadet_mq_send_continue, ch); | ||
732 | // notify_window_size (ch); /* FIXME add "verbose" setting? */ | ||
733 | } | ||
734 | else | ||
735 | { | ||
736 | /* Service has NOT allowed this message, queue it and wait for an ACK */ | ||
737 | GNUNET_assert (NULL == ch->pending_env); | ||
738 | ch->pending_env = env; | ||
739 | } | ||
740 | } | 519 | } |
741 | 520 | ||
742 | 521 | ||
@@ -763,14 +542,25 @@ cadet_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, | |||
763 | * the CADET service. We should just complain about it but otherwise | 542 | * the CADET service. We should just complain about it but otherwise |
764 | * continue processing. | 543 | * continue processing. |
765 | * | 544 | * |
766 | * @param cls closure | 545 | * @param cls closure with our `struct GNUNET_CADET_Channel` |
767 | * @param error error code | 546 | * @param error error code |
768 | */ | 547 | */ |
769 | static void | 548 | static void |
770 | cadet_mq_error_handler (void *cls, | 549 | cadet_mq_error_handler (void *cls, |
771 | enum GNUNET_MQ_Error error) | 550 | enum GNUNET_MQ_Error error) |
772 | { | 551 | { |
773 | GNUNET_break_op (0); | 552 | struct GNUNET_CADET_Channel *ch = cls; |
553 | |||
554 | GNUNET_break (0); | ||
555 | if (GNUNET_MQ_ERROR_NO_MATCH == error) | ||
556 | { | ||
557 | /* Got a message we did not understand, still try to continue! */ | ||
558 | GNUNET_CADET_receive_done (ch); | ||
559 | } | ||
560 | else | ||
561 | { | ||
562 | schedule_reconnect (ch->cadet); | ||
563 | } | ||
774 | } | 564 | } |
775 | 565 | ||
776 | 566 | ||
@@ -781,65 +571,20 @@ cadet_mq_error_handler (void *cls, | |||
781 | * @param mq message queue | 571 | * @param mq message queue |
782 | * @param impl_state state specific to the implementation | 572 | * @param impl_state state specific to the implementation |
783 | */ | 573 | */ |
784 | |||
785 | static void | 574 | static void |
786 | cadet_mq_cancel_impl (struct GNUNET_MQ_Handle *mq, | 575 | cadet_mq_cancel_impl (struct GNUNET_MQ_Handle *mq, |
787 | void *impl_state) | 576 | void *impl_state) |
788 | { | 577 | { |
789 | struct GNUNET_CADET_Channel *ch = impl_state; | 578 | struct GNUNET_CADET_Channel *ch = impl_state; |
790 | 579 | ||
791 | LOG (GNUNET_ERROR_TYPE_WARNING, | 580 | GNUNET_assert (NULL != ch->pending_env); |
792 | "Cannot cancel mq message on channel %X of %p\n", | 581 | GNUNET_MQ_discard (ch->pending_env); |
793 | ch->ccn.channel_of_client, ch->cadet); | 582 | ch->pending_env = NULL; |
794 | 583 | if (NULL != ch->mq_cont) | |
795 | GNUNET_break (0); | 584 | { |
796 | } | 585 | GNUNET_SCHEDULER_cancel (ch->mq_cont); |
797 | 586 | ch->mq_cont = NULL; | |
798 | 587 | } | |
799 | /******************************************************************************/ | ||
800 | /*********************** RECEIVE HANDLERS ****************************/ | ||
801 | /******************************************************************************/ | ||
802 | |||
803 | |||
804 | /** | ||
805 | * Call the @a notify callback given to #GNUNET_CADET_notify_transmit_ready to | ||
806 | * request the data to send over MQ. Since MQ manages the queue, this function | ||
807 | * is scheduled immediatly after a transmit ready notification. | ||
808 | * | ||
809 | * @param cls Closure (transmit handle). | ||
810 | */ | ||
811 | static void | ||
812 | request_data (void *cls) | ||
813 | { | ||
814 | struct GNUNET_CADET_TransmitHandle *th = cls; | ||
815 | struct GNUNET_CADET_LocalData *msg; | ||
816 | struct GNUNET_MQ_Envelope *env; | ||
817 | size_t osize; | ||
818 | |||
819 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
820 | "Requesting Data: %u bytes (allow send is %u)\n", | ||
821 | th->size, | ||
822 | th->channel->allow_send); | ||
823 | |||
824 | GNUNET_assert (0 < th->channel->allow_send); | ||
825 | th->channel->allow_send--; | ||
826 | /* NOTE: we may be allowed to send another packet immediately, | ||
827 | albeit the current logic waits for the ACK. */ | ||
828 | th->request_data_task = NULL; | ||
829 | remove_from_queue (th); | ||
830 | |||
831 | env = GNUNET_MQ_msg_extra (msg, | ||
832 | th->size, | ||
833 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); | ||
834 | msg->ccn = th->channel->ccn; | ||
835 | osize = th->notify (th->notify_cls, | ||
836 | th->size, | ||
837 | &msg[1]); | ||
838 | GNUNET_assert (osize == th->size); | ||
839 | |||
840 | GNUNET_MQ_send (th->channel->cadet->mq, | ||
841 | env); | ||
842 | GNUNET_free (th); | ||
843 | } | 588 | } |
844 | 589 | ||
845 | 590 | ||
@@ -866,7 +611,8 @@ handle_channel_created (void *cls, | |||
866 | GNUNET_break (0); | 611 | GNUNET_break (0); |
867 | return; | 612 | return; |
868 | } | 613 | } |
869 | port = find_port (h, port_number); | 614 | port = find_port (h, |
615 | port_number); | ||
870 | if (NULL == port) | 616 | if (NULL == port) |
871 | { | 617 | { |
872 | /* We could have closed the port but the service didn't know about it yet | 618 | /* We could have closed the port but the service didn't know about it yet |
@@ -875,7 +621,6 @@ handle_channel_created (void *cls, | |||
875 | struct GNUNET_CADET_LocalChannelDestroyMessage *d_msg; | 621 | struct GNUNET_CADET_LocalChannelDestroyMessage *d_msg; |
876 | struct GNUNET_MQ_Envelope *env; | 622 | struct GNUNET_MQ_Envelope *env; |
877 | 623 | ||
878 | GNUNET_break (0); | ||
879 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 624 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
880 | "No handler for incoming channel %X (on port %s, recently closed?)\n", | 625 | "No handler for incoming channel %X (on port %s, recently closed?)\n", |
881 | ntohl (ccn.channel_of_client), | 626 | ntohl (ccn.channel_of_client), |
@@ -889,10 +634,9 @@ handle_channel_created (void *cls, | |||
889 | } | 634 | } |
890 | 635 | ||
891 | ch = create_channel (h, | 636 | ch = create_channel (h, |
892 | ccn); | 637 | &ccn); |
893 | ch->peer = GNUNET_PEER_intern (&msg->peer); | 638 | ch->peer = msg->peer; |
894 | ch->cadet = h; | 639 | ch->cadet = h; |
895 | ch->ccn = ccn; | ||
896 | ch->incoming_port = port; | 640 | ch->incoming_port = port; |
897 | ch->options = ntohl (msg->opt); | 641 | ch->options = ntohl (msg->opt); |
898 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 642 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
@@ -901,34 +645,21 @@ handle_channel_created (void *cls, | |||
901 | GNUNET_h2s (port_number), | 645 | GNUNET_h2s (port_number), |
902 | ch); | 646 | ch); |
903 | 647 | ||
904 | if (NULL != port->handler) | 648 | GNUNET_assert (NULL != port->connects); |
905 | { | 649 | ch->window_changes = port->window_changes; |
906 | /** @deprecated */ | 650 | ch->disconnects = port->disconnects; |
907 | /* Old style API */ | 651 | ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl, |
908 | ch->ctx = port->handler (port->cls, | 652 | &cadet_mq_destroy_impl, |
909 | ch, | 653 | &cadet_mq_cancel_impl, |
910 | &msg->peer, | 654 | ch, |
911 | port->hash, | 655 | port->handlers, |
912 | ch->options); | 656 | &cadet_mq_error_handler, |
913 | } | 657 | ch); |
914 | else | 658 | ch->ctx = port->connects (port->cls, |
915 | { | 659 | ch, |
916 | /* MQ API */ | 660 | &msg->peer); |
917 | GNUNET_assert (NULL != port->connects); | 661 | GNUNET_MQ_set_handlers_closure (ch->mq, |
918 | ch->window_changes = port->window_changes; | 662 | ch->ctx); |
919 | ch->disconnects = port->disconnects; | ||
920 | ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl, | ||
921 | &cadet_mq_destroy_impl, | ||
922 | &cadet_mq_cancel_impl, | ||
923 | ch, | ||
924 | port->handlers, | ||
925 | &cadet_mq_error_handler, | ||
926 | ch); | ||
927 | ch->ctx = port->connects (port->cls, | ||
928 | ch, | ||
929 | &msg->peer); | ||
930 | GNUNET_MQ_set_handlers_closure (ch->mq, ch->ctx); | ||
931 | } | ||
932 | } | 663 | } |
933 | 664 | ||
934 | 665 | ||
@@ -944,22 +675,19 @@ handle_channel_destroy (void *cls, | |||
944 | { | 675 | { |
945 | struct GNUNET_CADET_Handle *h = cls; | 676 | struct GNUNET_CADET_Handle *h = cls; |
946 | struct GNUNET_CADET_Channel *ch; | 677 | struct GNUNET_CADET_Channel *ch; |
947 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
948 | |||
949 | ccn = msg->ccn; | ||
950 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
951 | "Channel %X Destroy from service\n", | ||
952 | ntohl (ccn.channel_of_client)); | ||
953 | ch = retrieve_channel (h, | ||
954 | ccn); | ||
955 | 678 | ||
679 | ch = find_channel (h, | ||
680 | msg->ccn); | ||
956 | if (NULL == ch) | 681 | if (NULL == ch) |
957 | { | 682 | { |
958 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 683 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
959 | "channel %X unknown\n", | 684 | "Received channel destroy for unknown channel %X from CADET service (recently close?)\n", |
960 | ntohl (ccn.channel_of_client)); | 685 | ntohl (msg->ccn.channel_of_client)); |
961 | return; | 686 | return; |
962 | } | 687 | } |
688 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
689 | "Received channel destroy for channel %X from CADET service\n", | ||
690 | ntohl (msg->ccn.channel_of_client)); | ||
963 | destroy_channel (ch); | 691 | destroy_channel (ch); |
964 | } | 692 | } |
965 | 693 | ||
@@ -976,25 +704,14 @@ static int | |||
976 | check_local_data (void *cls, | 704 | check_local_data (void *cls, |
977 | const struct GNUNET_CADET_LocalData *message) | 705 | const struct GNUNET_CADET_LocalData *message) |
978 | { | 706 | { |
979 | struct GNUNET_CADET_Handle *h = cls; | ||
980 | struct GNUNET_CADET_Channel *ch; | ||
981 | uint16_t size; | 707 | uint16_t size; |
982 | 708 | ||
983 | size = ntohs (message->header.size); | 709 | size = ntohs (message->header.size); |
984 | if (sizeof (*message) + sizeof (struct GNUNET_MessageHeader) > size) | 710 | if (sizeof (*message) + sizeof (struct GNUNET_MessageHeader) > size) |
985 | { | 711 | { |
986 | GNUNET_break_op (0); | 712 | GNUNET_break (0); |
987 | return GNUNET_SYSERR; | ||
988 | } | ||
989 | |||
990 | ch = retrieve_channel (h, | ||
991 | message->ccn); | ||
992 | if (NULL == ch) | ||
993 | { | ||
994 | GNUNET_break_op (0); | ||
995 | return GNUNET_SYSERR; | 713 | return GNUNET_SYSERR; |
996 | } | 714 | } |
997 | |||
998 | return GNUNET_OK; | 715 | return GNUNET_OK; |
999 | } | 716 | } |
1000 | 717 | ||
@@ -1011,62 +728,31 @@ handle_local_data (void *cls, | |||
1011 | { | 728 | { |
1012 | struct GNUNET_CADET_Handle *h = cls; | 729 | struct GNUNET_CADET_Handle *h = cls; |
1013 | const struct GNUNET_MessageHeader *payload; | 730 | const struct GNUNET_MessageHeader *payload; |
1014 | const struct GNUNET_CADET_MessageHandler *handler; | ||
1015 | struct GNUNET_CADET_Channel *ch; | 731 | struct GNUNET_CADET_Channel *ch; |
1016 | uint16_t type; | 732 | uint16_t type; |
1017 | int fwd; | 733 | int fwd; |
1018 | 734 | ||
1019 | ch = retrieve_channel (h, | 735 | ch = find_channel (h, |
1020 | message->ccn); | 736 | message->ccn); |
1021 | if (NULL == ch) | 737 | if (NULL == ch) |
1022 | { | 738 | { |
1023 | GNUNET_break_op (0); | 739 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1024 | reconnect (h); | 740 | "Unknown channel %X for incoming data (recently closed?)\n", |
741 | ntohl (message->ccn.channel_of_client)); | ||
1025 | return; | 742 | return; |
1026 | } | 743 | } |
1027 | 744 | ||
1028 | payload = (struct GNUNET_MessageHeader *) &message[1]; | 745 | payload = (const struct GNUNET_MessageHeader *) &message[1]; |
1029 | type = ntohs (payload->type); | 746 | type = ntohs (payload->type); |
1030 | fwd = ntohl (ch->ccn.channel_of_client) <= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; | 747 | fwd = ntohl (ch->ccn.channel_of_client) <= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; |
1031 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 748 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1032 | "Got a %s data on channel %s [%X] of type %s (%u)\n", | 749 | "Got a %s data on channel %s [%X] of type %u\n", |
1033 | GC_f2s (fwd), | 750 | fwd ? "FWD" : "BWD", |
1034 | GNUNET_i2s (GNUNET_PEER_resolve2 (ch->peer)), | 751 | GNUNET_i2s (&ch->peer), |
1035 | ntohl (message->ccn.channel_of_client), | 752 | ntohl (message->ccn.channel_of_client), |
1036 | GC_m2s (type), | ||
1037 | type); | 753 | type); |
1038 | if (NULL != ch->mq) | 754 | GNUNET_MQ_inject_message (ch->mq, |
1039 | { | 755 | payload); |
1040 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1041 | "injecting msg %s into mq %p\n", | ||
1042 | GC_m2s (ntohs (payload->type)), | ||
1043 | ch->mq); | ||
1044 | GNUNET_MQ_inject_message (ch->mq, payload); | ||
1045 | return; | ||
1046 | } | ||
1047 | /** @a deprecated */ | ||
1048 | for (unsigned i=0;i<h->n_handlers;i++) | ||
1049 | { | ||
1050 | handler = &h->message_handlers[i]; | ||
1051 | if (handler->type == type) | ||
1052 | { | ||
1053 | if (GNUNET_OK != | ||
1054 | handler->callback (h->cls, | ||
1055 | ch, | ||
1056 | &ch->ctx, | ||
1057 | payload)) | ||
1058 | { | ||
1059 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1060 | "callback caused disconnection\n"); | ||
1061 | GNUNET_CADET_channel_destroy (ch); | ||
1062 | return; | ||
1063 | } | ||
1064 | return; | ||
1065 | } | ||
1066 | } | ||
1067 | /* Other peer sent message we do not comprehend. */ | ||
1068 | GNUNET_break_op (0); | ||
1069 | GNUNET_CADET_receive_done (ch); | ||
1070 | } | 756 | } |
1071 | 757 | ||
1072 | 758 | ||
@@ -1083,55 +769,34 @@ handle_local_ack (void *cls, | |||
1083 | { | 769 | { |
1084 | struct GNUNET_CADET_Handle *h = cls; | 770 | struct GNUNET_CADET_Handle *h = cls; |
1085 | struct GNUNET_CADET_Channel *ch; | 771 | struct GNUNET_CADET_Channel *ch; |
1086 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
1087 | struct GNUNET_CADET_TransmitHandle *th; | ||
1088 | 772 | ||
1089 | ccn = message->ccn; | 773 | ch = find_channel (h, |
1090 | ch = retrieve_channel (h, ccn); | 774 | message->ccn); |
1091 | if (NULL == ch) | 775 | if (NULL == ch) |
1092 | { | 776 | { |
1093 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 777 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1094 | "ACK on unknown channel %X\n", | 778 | "ACK on unknown channel %X\n", |
1095 | ntohl (ccn.channel_of_client)); | 779 | ntohl (message->ccn.channel_of_client)); |
1096 | return; | 780 | return; |
1097 | } | 781 | } |
1098 | ch->allow_send++; | 782 | ch->allow_send++; |
1099 | if (NULL != ch->mq) | 783 | if (NULL == ch->pending_env) |
1100 | { | 784 | { |
1101 | if (NULL == ch->pending_env) | 785 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1102 | { | 786 | "Got an ACK on mq channel %X, allow send now %u!\n", |
1103 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 787 | ntohl (ch->ccn.channel_of_client), |
1104 | "Got an ACK on mq channel %X, allow send now %u!\n", | 788 | ch->allow_send); |
1105 | ntohl (ch->ccn.channel_of_client), | 789 | notify_window_size (ch); |
1106 | ch->allow_send); | ||
1107 | notify_window_size (ch); | ||
1108 | } | ||
1109 | else | ||
1110 | { | ||
1111 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1112 | "Got an ACK on mq channel %X, sending pending message!\n", | ||
1113 | ntohl (ch->ccn.channel_of_client)); | ||
1114 | GNUNET_MQ_send (h->mq, ch->pending_env); | ||
1115 | ch->allow_send--; | ||
1116 | ch->pending_env = NULL; | ||
1117 | ch->mq_cont = GNUNET_SCHEDULER_add_now (&cadet_mq_send_continue, ch); | ||
1118 | } | ||
1119 | return; | 790 | return; |
1120 | } | 791 | } |
1121 | 792 | if (NULL != ch->mq_cont) | |
1122 | /** @deprecated */ | 793 | return; /* already working on it! */ |
1123 | /* Old style API */ | 794 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1124 | for (th = h->th_head; NULL != th; th = th->next) | 795 | "Got an ACK on mq channel %X, sending pending message!\n", |
1125 | { | 796 | ntohl (ch->ccn.channel_of_client)); |
1126 | if ( (th->channel == ch) && | 797 | ch->mq_cont |
1127 | (NULL == th->request_data_task) ) | 798 | = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now, |
1128 | { | 799 | ch); |
1129 | th->request_data_task | ||
1130 | = GNUNET_SCHEDULER_add_now (&request_data, | ||
1131 | th); | ||
1132 | break; | ||
1133 | } | ||
1134 | } | ||
1135 | } | 800 | } |
1136 | 801 | ||
1137 | 802 | ||
@@ -1149,134 +814,15 @@ handle_mq_error (void *cls, | |||
1149 | { | 814 | { |
1150 | struct GNUNET_CADET_Handle *h = cls; | 815 | struct GNUNET_CADET_Handle *h = cls; |
1151 | 816 | ||
1152 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MQ ERROR: %u\n", error); | 817 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
818 | "MQ ERROR: %u\n", | ||
819 | error); | ||
1153 | GNUNET_MQ_destroy (h->mq); | 820 | GNUNET_MQ_destroy (h->mq); |
1154 | h->mq = NULL; | 821 | h->mq = NULL; |
1155 | reconnect (h); | 822 | reconnect (h); |
1156 | } | 823 | } |
1157 | 824 | ||
1158 | 825 | ||
1159 | /* | ||
1160 | * Process a local reply about info on all channels, pass info to the user. | ||
1161 | * | ||
1162 | * @param h Cadet handle. | ||
1163 | * @param message Message itself. | ||
1164 | */ | ||
1165 | // static void | ||
1166 | // process_get_channels (struct GNUNET_CADET_Handle *h, | ||
1167 | // const struct GNUNET_MessageHeader *message) | ||
1168 | // { | ||
1169 | // struct GNUNET_CADET_LocalInfo *msg; | ||
1170 | // | ||
1171 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Channels messasge received\n"); | ||
1172 | // | ||
1173 | // if (NULL == h->channels_cb) | ||
1174 | // { | ||
1175 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n"); | ||
1176 | // return; | ||
1177 | // } | ||
1178 | // | ||
1179 | // msg = (struct GNUNET_CADET_LocalInfo *) message; | ||
1180 | // if (ntohs (message->size) != | ||
1181 | // (sizeof (struct GNUNET_CADET_LocalInfo) + | ||
1182 | // sizeof (struct GNUNET_PeerIdentity))) | ||
1183 | // { | ||
1184 | // GNUNET_break_op (0); | ||
1185 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1186 | // "Get channels message: size %hu - expected %u\n", | ||
1187 | // ntohs (message->size), | ||
1188 | // sizeof (struct GNUNET_CADET_LocalInfo)); | ||
1189 | // return; | ||
1190 | // } | ||
1191 | // h->channels_cb (h->channels_cls, | ||
1192 | // ntohl (msg->channel_id), | ||
1193 | // &msg->owner, | ||
1194 | // &msg->destination); | ||
1195 | // } | ||
1196 | |||
1197 | |||
1198 | |||
1199 | /* | ||
1200 | * Process a local monitor_channel reply, pass info to the user. | ||
1201 | * | ||
1202 | * @param h Cadet handle. | ||
1203 | * @param message Message itself. | ||
1204 | */ | ||
1205 | // static void | ||
1206 | // process_show_channel (struct GNUNET_CADET_Handle *h, | ||
1207 | // const struct GNUNET_MessageHeader *message) | ||
1208 | // { | ||
1209 | // struct GNUNET_CADET_LocalInfo *msg; | ||
1210 | // size_t esize; | ||
1211 | // | ||
1212 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Channel messasge received\n"); | ||
1213 | // | ||
1214 | // if (NULL == h->channel_cb) | ||
1215 | // { | ||
1216 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n"); | ||
1217 | // return; | ||
1218 | // } | ||
1219 | // | ||
1220 | // /* Verify message sanity */ | ||
1221 | // msg = (struct GNUNET_CADET_LocalInfo *) message; | ||
1222 | // esize = sizeof (struct GNUNET_CADET_LocalInfo); | ||
1223 | // if (ntohs (message->size) != esize) | ||
1224 | // { | ||
1225 | // GNUNET_break_op (0); | ||
1226 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1227 | // "Show channel message: size %hu - expected %u\n", | ||
1228 | // ntohs (message->size), | ||
1229 | // esize); | ||
1230 | // | ||
1231 | // h->channel_cb (h->channel_cls, NULL, NULL); | ||
1232 | // h->channel_cb = NULL; | ||
1233 | // h->channel_cls = NULL; | ||
1234 | // | ||
1235 | // return; | ||
1236 | // } | ||
1237 | // | ||
1238 | // h->channel_cb (h->channel_cls, | ||
1239 | // &msg->destination, | ||
1240 | // &msg->owner); | ||
1241 | // } | ||
1242 | |||
1243 | |||
1244 | |||
1245 | /** | ||
1246 | * Check that message received from CADET service is well-formed. | ||
1247 | * | ||
1248 | * @param cls the `struct GNUNET_CADET_Handle` | ||
1249 | * @param message the message we got | ||
1250 | * @return #GNUNET_OK if the message is well-formed, | ||
1251 | * #GNUNET_SYSERR otherwise | ||
1252 | */ | ||
1253 | static int | ||
1254 | check_get_peers (void *cls, | ||
1255 | const struct GNUNET_CADET_LocalInfoPeer *message) | ||
1256 | { | ||
1257 | struct GNUNET_CADET_Handle *h = cls; | ||
1258 | uint16_t size; | ||
1259 | |||
1260 | if (NULL == h->info_cb.peers_cb) | ||
1261 | { | ||
1262 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1263 | " no handler for peesr monitor message!\n"); | ||
1264 | return GNUNET_SYSERR; | ||
1265 | } | ||
1266 | |||
1267 | size = ntohs (message->header.size); | ||
1268 | if (sizeof (struct GNUNET_CADET_LocalInfoPeer) > size) | ||
1269 | { | ||
1270 | h->info_cb.peers_cb (h->info_cls, NULL, -1, 0, 0); | ||
1271 | h->info_cb.peers_cb = NULL; | ||
1272 | h->info_cls = NULL; | ||
1273 | return GNUNET_SYSERR; | ||
1274 | } | ||
1275 | |||
1276 | return GNUNET_OK; | ||
1277 | } | ||
1278 | |||
1279 | |||
1280 | /** | 826 | /** |
1281 | * Process a local reply about info on all tunnels, pass info to the user. | 827 | * Process a local reply about info on all tunnels, pass info to the user. |
1282 | * | 828 | * |
@@ -1288,9 +834,13 @@ handle_get_peers (void *cls, | |||
1288 | const struct GNUNET_CADET_LocalInfoPeer *msg) | 834 | const struct GNUNET_CADET_LocalInfoPeer *msg) |
1289 | { | 835 | { |
1290 | struct GNUNET_CADET_Handle *h = cls; | 836 | struct GNUNET_CADET_Handle *h = cls; |
1291 | h->info_cb.peers_cb (h->info_cls, &msg->destination, | 837 | |
838 | if (NULL == h->info_cb.peers_cb) | ||
839 | return; | ||
840 | h->info_cb.peers_cb (h->info_cls, | ||
841 | &msg->destination, | ||
1292 | (int) ntohs (msg->tunnel), | 842 | (int) ntohs (msg->tunnel), |
1293 | (unsigned int ) ntohs (msg->paths), | 843 | (unsigned int) ntohs (msg->paths), |
1294 | 0); | 844 | 0); |
1295 | } | 845 | } |
1296 | 846 | ||
@@ -1307,62 +857,39 @@ static int | |||
1307 | check_get_peer (void *cls, | 857 | check_get_peer (void *cls, |
1308 | const struct GNUNET_CADET_LocalInfoPeer *message) | 858 | const struct GNUNET_CADET_LocalInfoPeer *message) |
1309 | { | 859 | { |
1310 | struct GNUNET_CADET_Handle *h = cls; | 860 | size_t msize = sizeof (struct GNUNET_CADET_LocalInfoPeer); |
1311 | const size_t msize = sizeof (struct GNUNET_CADET_LocalInfoPeer); | 861 | const struct GNUNET_PeerIdentity *paths_array; |
1312 | struct GNUNET_PeerIdentity *paths_array; | ||
1313 | size_t esize; | 862 | size_t esize; |
1314 | unsigned int epaths; | 863 | unsigned int epaths; |
1315 | unsigned int paths; | 864 | unsigned int paths; |
1316 | unsigned int peers; | 865 | unsigned int peers; |
1317 | 866 | ||
1318 | if (NULL == h->info_cb.peer_cb) | ||
1319 | { | ||
1320 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1321 | " no handler for peer monitor message!\n"); | ||
1322 | goto clean_cls; | ||
1323 | } | ||
1324 | |||
1325 | /* Verify message sanity */ | ||
1326 | esize = ntohs (message->header.size); | 867 | esize = ntohs (message->header.size); |
1327 | if (esize < msize) | 868 | if (esize < msize) |
1328 | { | 869 | { |
1329 | GNUNET_break_op (0); | 870 | GNUNET_break (0); |
1330 | h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL); | 871 | return GNUNET_SYSERR; |
1331 | goto clean_cls; | ||
1332 | } | 872 | } |
1333 | if (0 != ((esize - msize) % sizeof (struct GNUNET_PeerIdentity))) | 873 | if (0 != ((esize - msize) % sizeof (struct GNUNET_PeerIdentity))) |
1334 | { | 874 | { |
1335 | GNUNET_break_op (0); | 875 | GNUNET_break (0); |
1336 | h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL); | 876 | return GNUNET_SYSERR; |
1337 | goto clean_cls; | ||
1338 | |||
1339 | } | 877 | } |
1340 | peers = (esize - msize) / sizeof (struct GNUNET_PeerIdentity); | 878 | peers = (esize - msize) / sizeof (struct GNUNET_PeerIdentity); |
1341 | epaths = (unsigned int) ntohs (message->paths); | 879 | epaths = ntohs (message->paths); |
1342 | paths_array = (struct GNUNET_PeerIdentity *) &message[1]; | 880 | paths_array = (const struct GNUNET_PeerIdentity *) &message[1]; |
1343 | paths = 0; | 881 | paths = 0; |
1344 | for (int i = 0; i < peers; i++) | 882 | for (unsigned int i = 0; i < peers; i++) |
1345 | { | 883 | if (0 == memcmp (&paths_array[i], |
1346 | if (0 == memcmp (&paths_array[i], &message->destination, | 884 | &message->destination, |
1347 | sizeof (struct GNUNET_PeerIdentity))) | 885 | sizeof (struct GNUNET_PeerIdentity))) |
1348 | { | ||
1349 | paths++; | 886 | paths++; |
1350 | } | ||
1351 | } | ||
1352 | if (paths != epaths) | 887 | if (paths != epaths) |
1353 | { | 888 | { |
1354 | GNUNET_break_op (0); | 889 | GNUNET_break (0); |
1355 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "p:%u, e: %u\n", paths, epaths); | 890 | return GNUNET_SYSERR; |
1356 | h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL); | ||
1357 | goto clean_cls; | ||
1358 | } | 891 | } |
1359 | |||
1360 | return GNUNET_OK; | 892 | return GNUNET_OK; |
1361 | |||
1362 | clean_cls: | ||
1363 | h->info_cb.peer_cb = NULL; | ||
1364 | h->info_cls = NULL; | ||
1365 | return GNUNET_SYSERR; | ||
1366 | } | 893 | } |
1367 | 894 | ||
1368 | 895 | ||
@@ -1377,22 +904,26 @@ handle_get_peer (void *cls, | |||
1377 | const struct GNUNET_CADET_LocalInfoPeer *message) | 904 | const struct GNUNET_CADET_LocalInfoPeer *message) |
1378 | { | 905 | { |
1379 | struct GNUNET_CADET_Handle *h = cls; | 906 | struct GNUNET_CADET_Handle *h = cls; |
1380 | struct GNUNET_PeerIdentity *paths_array; | 907 | const struct GNUNET_PeerIdentity *paths_array; |
1381 | unsigned int paths; | 908 | unsigned int paths; |
1382 | unsigned int path_length; | 909 | unsigned int path_length; |
1383 | int neighbor; | 910 | int neighbor; |
1384 | unsigned int peers; | 911 | unsigned int peers; |
1385 | 912 | ||
1386 | paths = (unsigned int) ntohs (message->paths); | 913 | if (NULL == h->info_cb.peer_cb) |
1387 | paths_array = (struct GNUNET_PeerIdentity *) &message[1]; | 914 | return; |
915 | paths = ntohs (message->paths); | ||
916 | paths_array = (const struct GNUNET_PeerIdentity *) &message[1]; | ||
1388 | peers = (ntohs (message->header.size) - sizeof (*message)) | 917 | peers = (ntohs (message->header.size) - sizeof (*message)) |
1389 | / sizeof (struct GNUNET_PeerIdentity); | 918 | / sizeof (struct GNUNET_PeerIdentity); |
1390 | path_length = 0; | 919 | path_length = 0; |
1391 | neighbor = GNUNET_NO; | 920 | neighbor = GNUNET_NO; |
1392 | 921 | ||
1393 | for (int i = 0; i < peers; i++) | 922 | for (unsigned int i = 0; i < peers; i++) |
1394 | { | 923 | { |
1395 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n", GNUNET_i2s (&paths_array[i])); | 924 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
925 | " %s\n", | ||
926 | GNUNET_i2s (&paths_array[i])); | ||
1396 | path_length++; | 927 | path_length++; |
1397 | if (0 == memcmp (&paths_array[i], &message->destination, | 928 | if (0 == memcmp (&paths_array[i], &message->destination, |
1398 | sizeof (struct GNUNET_PeerIdentity))) | 929 | sizeof (struct GNUNET_PeerIdentity))) |
@@ -1404,7 +935,7 @@ handle_get_peer (void *cls, | |||
1404 | } | 935 | } |
1405 | 936 | ||
1406 | /* Call Callback with tunnel info. */ | 937 | /* Call Callback with tunnel info. */ |
1407 | paths_array = (struct GNUNET_PeerIdentity *) &message[1]; | 938 | paths_array = (const struct GNUNET_PeerIdentity *) &message[1]; |
1408 | h->info_cb.peer_cb (h->info_cls, | 939 | h->info_cb.peer_cb (h->info_cls, |
1409 | &message->destination, | 940 | &message->destination, |
1410 | (int) ntohs (message->tunnel), | 941 | (int) ntohs (message->tunnel), |
@@ -1415,40 +946,6 @@ handle_get_peer (void *cls, | |||
1415 | 946 | ||
1416 | 947 | ||
1417 | /** | 948 | /** |
1418 | * Check that message received from CADET service is well-formed. | ||
1419 | * | ||
1420 | * @param cls the `struct GNUNET_CADET_Handle` | ||
1421 | * @param msg the message we got | ||
1422 | * @return #GNUNET_OK if the message is well-formed, | ||
1423 | * #GNUNET_SYSERR otherwise | ||
1424 | */ | ||
1425 | static int | ||
1426 | check_get_tunnels (void *cls, | ||
1427 | const struct GNUNET_CADET_LocalInfoTunnel *msg) | ||
1428 | { | ||
1429 | struct GNUNET_CADET_Handle *h = cls; | ||
1430 | uint16_t size; | ||
1431 | |||
1432 | if (NULL == h->info_cb.tunnels_cb) | ||
1433 | { | ||
1434 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1435 | " no handler for tunnels monitor message!\n"); | ||
1436 | return GNUNET_SYSERR; | ||
1437 | } | ||
1438 | |||
1439 | size = ntohs (msg->header.size); | ||
1440 | if (sizeof (struct GNUNET_CADET_LocalInfoTunnel) > size) | ||
1441 | { | ||
1442 | h->info_cb.tunnels_cb (h->info_cls, NULL, 0, 0, 0, 0); | ||
1443 | h->info_cb.tunnels_cb = NULL; | ||
1444 | h->info_cls = NULL; | ||
1445 | return GNUNET_SYSERR; | ||
1446 | } | ||
1447 | return GNUNET_OK; | ||
1448 | } | ||
1449 | |||
1450 | |||
1451 | /** | ||
1452 | * Process a local reply about info on all tunnels, pass info to the user. | 949 | * Process a local reply about info on all tunnels, pass info to the user. |
1453 | * | 950 | * |
1454 | * @param cls Closure (Cadet handle). | 951 | * @param cls Closure (Cadet handle). |
@@ -1460,6 +957,8 @@ handle_get_tunnels (void *cls, | |||
1460 | { | 957 | { |
1461 | struct GNUNET_CADET_Handle *h = cls; | 958 | struct GNUNET_CADET_Handle *h = cls; |
1462 | 959 | ||
960 | if (NULL == h->info_cb.tunnels_cb) | ||
961 | return; | ||
1463 | h->info_cb.tunnels_cb (h->info_cls, | 962 | h->info_cb.tunnels_cb (h->info_cls, |
1464 | &msg->destination, | 963 | &msg->destination, |
1465 | ntohl (msg->channels), | 964 | ntohl (msg->channels), |
@@ -1482,28 +981,18 @@ static int | |||
1482 | check_get_tunnel (void *cls, | 981 | check_get_tunnel (void *cls, |
1483 | const struct GNUNET_CADET_LocalInfoTunnel *msg) | 982 | const struct GNUNET_CADET_LocalInfoTunnel *msg) |
1484 | { | 983 | { |
1485 | struct GNUNET_CADET_Handle *h = cls; | ||
1486 | unsigned int ch_n; | 984 | unsigned int ch_n; |
1487 | unsigned int c_n; | 985 | unsigned int c_n; |
1488 | size_t esize; | 986 | size_t esize; |
1489 | size_t msize; | 987 | size_t msize; |
1490 | 988 | ||
1491 | if (NULL == h->info_cb.tunnel_cb) | ||
1492 | { | ||
1493 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1494 | " no handler for tunnel monitor message!\n"); | ||
1495 | goto clean_cls; | ||
1496 | } | ||
1497 | |||
1498 | /* Verify message sanity */ | 989 | /* Verify message sanity */ |
1499 | msize = ntohs (msg->header.size); | 990 | msize = ntohs (msg->header.size); |
1500 | esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel); | 991 | esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel); |
1501 | if (esize > msize) | 992 | if (esize > msize) |
1502 | { | 993 | { |
1503 | GNUNET_break_op (0); | 994 | GNUNET_break (0); |
1504 | h->info_cb.tunnel_cb (h->info_cls, | 995 | return GNUNET_SYSERR; |
1505 | NULL, 0, 0, NULL, NULL, 0, 0); | ||
1506 | goto clean_cls; | ||
1507 | } | 996 | } |
1508 | ch_n = ntohl (msg->channels); | 997 | ch_n = ntohl (msg->channels); |
1509 | c_n = ntohl (msg->connections); | 998 | c_n = ntohl (msg->connections); |
@@ -1518,17 +1007,9 @@ check_get_tunnel (void *cls, | |||
1518 | (unsigned int) esize, | 1007 | (unsigned int) esize, |
1519 | ch_n, | 1008 | ch_n, |
1520 | c_n); | 1009 | c_n); |
1521 | h->info_cb.tunnel_cb (h->info_cls, | 1010 | return GNUNET_SYSERR; |
1522 | NULL, 0, 0, NULL, NULL, 0, 0); | ||
1523 | goto clean_cls; | ||
1524 | } | 1011 | } |
1525 | |||
1526 | return GNUNET_OK; | 1012 | return GNUNET_OK; |
1527 | |||
1528 | clean_cls: | ||
1529 | h->info_cb.tunnel_cb = NULL; | ||
1530 | h->info_cls = NULL; | ||
1531 | return GNUNET_SYSERR; | ||
1532 | } | 1013 | } |
1533 | 1014 | ||
1534 | 1015 | ||
@@ -1548,6 +1029,9 @@ handle_get_tunnel (void *cls, | |||
1548 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *conns; | 1029 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *conns; |
1549 | const struct GNUNET_CADET_ChannelTunnelNumber *chns; | 1030 | const struct GNUNET_CADET_ChannelTunnelNumber *chns; |
1550 | 1031 | ||
1032 | if (NULL == h->info_cb.tunnel_cb) | ||
1033 | return; | ||
1034 | |||
1551 | ch_n = ntohl (msg->channels); | 1035 | ch_n = ntohl (msg->channels); |
1552 | c_n = ntohl (msg->connections); | 1036 | c_n = ntohl (msg->connections); |
1553 | 1037 | ||
@@ -1591,44 +1075,25 @@ reconnect (struct GNUNET_CADET_Handle *h) | |||
1591 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK, | 1075 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK, |
1592 | struct GNUNET_CADET_LocalAck, | 1076 | struct GNUNET_CADET_LocalAck, |
1593 | h), | 1077 | h), |
1594 | GNUNET_MQ_hd_var_size (get_peers, | 1078 | GNUNET_MQ_hd_fixed_size (get_peers, |
1595 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS, | 1079 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS, |
1596 | struct GNUNET_CADET_LocalInfoPeer, | 1080 | struct GNUNET_CADET_LocalInfoPeer, |
1597 | h), | 1081 | h), |
1598 | GNUNET_MQ_hd_var_size (get_peer, | 1082 | GNUNET_MQ_hd_var_size (get_peer, |
1599 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER, | 1083 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER, |
1600 | struct GNUNET_CADET_LocalInfoPeer, | 1084 | struct GNUNET_CADET_LocalInfoPeer, |
1601 | h), | 1085 | h), |
1602 | GNUNET_MQ_hd_var_size (get_tunnels, | 1086 | GNUNET_MQ_hd_fixed_size (get_tunnels, |
1603 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS, | 1087 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS, |
1604 | struct GNUNET_CADET_LocalInfoTunnel, | 1088 | struct GNUNET_CADET_LocalInfoTunnel, |
1605 | h), | 1089 | h), |
1606 | GNUNET_MQ_hd_var_size (get_tunnel, | 1090 | GNUNET_MQ_hd_var_size (get_tunnel, |
1607 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL, | 1091 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL, |
1608 | struct GNUNET_CADET_LocalInfoTunnel, | 1092 | struct GNUNET_CADET_LocalInfoTunnel, |
1609 | h), | 1093 | h), |
1610 | // FIXME | ||
1611 | // GNUNET_MQ_hd_fixed_Y size (channel_destroyed, | ||
1612 | // GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED, | ||
1613 | // struct GNUNET_CADET_ChannelDestroyMessage); | ||
1614 | GNUNET_MQ_handler_end () | 1094 | GNUNET_MQ_handler_end () |
1615 | }; | 1095 | }; |
1616 | struct GNUNET_CADET_Channel *ch; | ||
1617 | |||
1618 | while (NULL != (ch = h->channels_head)) | ||
1619 | { | ||
1620 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1621 | "Destroying channel due to a reconnect\n"); | ||
1622 | destroy_channel (ch); | ||
1623 | } | ||
1624 | |||
1625 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to CADET\n"); | ||
1626 | 1096 | ||
1627 | if (NULL != h->mq) | ||
1628 | { | ||
1629 | GNUNET_MQ_destroy (h->mq); | ||
1630 | h->mq = NULL; | ||
1631 | } | ||
1632 | h->mq = GNUNET_CLIENT_connect (h->cfg, | 1097 | h->mq = GNUNET_CLIENT_connect (h->cfg, |
1633 | "cadet", | 1098 | "cadet", |
1634 | handlers, | 1099 | handlers, |
@@ -1639,85 +1104,60 @@ reconnect (struct GNUNET_CADET_Handle *h) | |||
1639 | schedule_reconnect (h); | 1104 | schedule_reconnect (h); |
1640 | return; | 1105 | return; |
1641 | } | 1106 | } |
1642 | else | 1107 | h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; |
1643 | { | ||
1644 | h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; | ||
1645 | } | ||
1646 | } | 1108 | } |
1647 | 1109 | ||
1110 | |||
1648 | /** | 1111 | /** |
1649 | * Reconnect callback: tries to reconnect again after a failer previous | 1112 | * Function called during #GNUNET_CADET_disconnect() to destroy |
1650 | * reconnecttion | 1113 | * all channels that are still open. |
1651 | * | 1114 | * |
1652 | * @param cls closure (cadet handle) | 1115 | * @param cls the `struct GNUNET_CADET_Handle` |
1116 | * @param cid chanenl ID | ||
1117 | * @param value a `struct GNUNET_CADET_Channel` to destroy | ||
1118 | * @return #GNUNET_OK (continue to iterate) | ||
1653 | */ | 1119 | */ |
1654 | static void | 1120 | static int |
1655 | reconnect_cbk (void *cls) | 1121 | destroy_channel_cb (void *cls, |
1122 | uint32_t cid, | ||
1123 | void *value) | ||
1656 | { | 1124 | { |
1657 | struct GNUNET_CADET_Handle *h = cls; | 1125 | /* struct GNUNET_CADET_Handle *handle = cls; */ |
1126 | struct GNUNET_CADET_Channel *ch = value; | ||
1658 | 1127 | ||
1659 | h->reconnect_task = NULL; | 1128 | if (ntohl (ch->ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) |
1660 | reconnect (h); | 1129 | { |
1130 | GNUNET_break (0); | ||
1131 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1132 | "channel %X not destroyed\n", | ||
1133 | ntohl (ch->ccn.channel_of_client)); | ||
1134 | } | ||
1135 | destroy_channel (ch); | ||
1136 | return GNUNET_OK; | ||
1661 | } | 1137 | } |
1662 | 1138 | ||
1663 | 1139 | ||
1664 | /** | 1140 | /** |
1665 | * Reconnect to the service, retransmit all infomation to try to restore the | 1141 | * Function called during #GNUNET_CADET_disconnect() to destroy |
1666 | * original state. | 1142 | * all ports that are still open. |
1667 | * | 1143 | * |
1668 | * @param h handle to the cadet | 1144 | * @param cls the `struct GNUNET_CADET_Handle` |
1669 | * | 1145 | * @param id port ID |
1670 | * @return #GNUNET_YES in case of sucess, #GNUNET_NO otherwise (service down...) | 1146 | * @param value a `struct GNUNET_CADET_Channel` to destroy |
1147 | * @return #GNUNET_OK (continue to iterate) | ||
1671 | */ | 1148 | */ |
1672 | static void | 1149 | static int |
1673 | schedule_reconnect (struct GNUNET_CADET_Handle *h) | 1150 | destroy_port_cb (void *cls, |
1674 | { | 1151 | const struct GNUNET_HashCode *id, |
1675 | if (NULL == h->reconnect_task) | 1152 | void *value) |
1676 | { | ||
1677 | h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time, | ||
1678 | &reconnect_cbk, h); | ||
1679 | h->reconnect_time = GNUNET_TIME_STD_BACKOFF (h->reconnect_time); | ||
1680 | } | ||
1681 | } | ||
1682 | |||
1683 | |||
1684 | /******************************************************************************/ | ||
1685 | /********************** API CALL DEFINITIONS *************************/ | ||
1686 | /******************************************************************************/ | ||
1687 | |||
1688 | struct GNUNET_CADET_Handle * | ||
1689 | GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
1690 | void *cls, | ||
1691 | GNUNET_CADET_ChannelEndHandler cleaner, | ||
1692 | const struct GNUNET_CADET_MessageHandler *handlers) | ||
1693 | { | 1153 | { |
1694 | struct GNUNET_CADET_Handle *h; | 1154 | /* struct GNUNET_CADET_Handle *handle = cls; */ |
1695 | 1155 | struct GNUNET_CADET_Port *port = value; | |
1696 | h = GNUNET_new (struct GNUNET_CADET_Handle); | ||
1697 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1698 | "GNUNET_CADET_connect() %p\n", | ||
1699 | h); | ||
1700 | h->cfg = cfg; | ||
1701 | h->cleaner = cleaner; | ||
1702 | h->ports = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_YES); | ||
1703 | reconnect (h); | ||
1704 | if (h->mq == NULL) | ||
1705 | { | ||
1706 | GNUNET_break (0); | ||
1707 | GNUNET_CADET_disconnect (h); | ||
1708 | return NULL; | ||
1709 | } | ||
1710 | h->cls = cls; | ||
1711 | h->message_handlers = handlers; | ||
1712 | h->next_ccn.channel_of_client = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
1713 | h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; | ||
1714 | h->reconnect_task = NULL; | ||
1715 | 1156 | ||
1716 | /* count handlers */ | 1157 | /* This is a warning, the app should have cleanly closed all open ports */ |
1717 | for (h->n_handlers = 0; | 1158 | GNUNET_break (0); |
1718 | handlers && handlers[h->n_handlers].type; | 1159 | GNUNET_CADET_close_port (port); |
1719 | h->n_handlers++) ; | 1160 | return GNUNET_OK; |
1720 | return h; | ||
1721 | } | 1161 | } |
1722 | 1162 | ||
1723 | 1163 | ||
@@ -1732,57 +1172,16 @@ GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
1732 | void | 1172 | void |
1733 | GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle) | 1173 | GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle) |
1734 | { | 1174 | { |
1735 | struct GNUNET_CADET_Channel *ch; | 1175 | GNUNET_CONTAINER_multihashmap_iterate (handle->ports, |
1736 | struct GNUNET_CADET_Channel *aux; | 1176 | &destroy_port_cb, |
1737 | struct GNUNET_CADET_TransmitHandle *th; | 1177 | handle); |
1738 | 1178 | GNUNET_CONTAINER_multihashmap_destroy (handle->ports); | |
1739 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1179 | handle->ports = NULL; |
1740 | "CADET DISCONNECT\n"); | 1180 | GNUNET_CONTAINER_multihashmap32_iterate (handle->channels, |
1741 | ch = handle->channels_head; | 1181 | &destroy_channel_cb, |
1742 | while (NULL != ch) | 1182 | handle); |
1743 | { | 1183 | GNUNET_CONTAINER_multihashmap32_destroy (handle->channels); |
1744 | aux = ch->next; | 1184 | handle->channels = NULL; |
1745 | if (ntohl (ch->ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
1746 | { | ||
1747 | GNUNET_break (0); | ||
1748 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1749 | "channel %X not destroyed\n", | ||
1750 | ntohl (ch->ccn.channel_of_client)); | ||
1751 | } | ||
1752 | destroy_channel (ch); | ||
1753 | ch = aux; | ||
1754 | } | ||
1755 | while (NULL != (th = handle->th_head)) | ||
1756 | { | ||
1757 | struct GNUNET_MessageHeader *msg; | ||
1758 | |||
1759 | /* Make sure it is an allowed packet (everything else should have been | ||
1760 | * already canceled). | ||
1761 | */ | ||
1762 | GNUNET_break (GNUNET_NO == th_is_payload (th)); | ||
1763 | msg = (struct GNUNET_MessageHeader *) &th[1]; | ||
1764 | switch (ntohs(msg->type)) | ||
1765 | { | ||
1766 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN: | ||
1767 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
1768 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN: | ||
1769 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE: | ||
1770 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNELS: | ||
1771 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL: | ||
1772 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER: | ||
1773 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS: | ||
1774 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL: | ||
1775 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS: | ||
1776 | break; | ||
1777 | default: | ||
1778 | GNUNET_break (0); | ||
1779 | LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected unsent msg %s\n", | ||
1780 | GC_m2s (ntohs(msg->type))); | ||
1781 | } | ||
1782 | |||
1783 | GNUNET_CADET_notify_transmit_ready_cancel (th); | ||
1784 | } | ||
1785 | |||
1786 | if (NULL != handle->mq) | 1185 | if (NULL != handle->mq) |
1787 | { | 1186 | { |
1788 | GNUNET_MQ_destroy (handle->mq); | 1187 | GNUNET_MQ_destroy (handle->mq); |
@@ -1790,58 +1189,15 @@ GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle) | |||
1790 | } | 1189 | } |
1791 | if (NULL != handle->reconnect_task) | 1190 | if (NULL != handle->reconnect_task) |
1792 | { | 1191 | { |
1793 | GNUNET_SCHEDULER_cancel(handle->reconnect_task); | 1192 | GNUNET_SCHEDULER_cancel (handle->reconnect_task); |
1794 | handle->reconnect_task = NULL; | 1193 | handle->reconnect_task = NULL; |
1795 | } | 1194 | } |
1796 | |||
1797 | GNUNET_CONTAINER_multihashmap_destroy (handle->ports); | ||
1798 | handle->ports = NULL; | ||
1799 | GNUNET_free (handle); | 1195 | GNUNET_free (handle); |
1800 | } | 1196 | } |
1801 | 1197 | ||
1802 | 1198 | ||
1803 | /** | 1199 | /** |
1804 | * Open a port to receive incomming channels. | 1200 | * Close a port opened with @a GNUNET_CADET_open_port(). |
1805 | * | ||
1806 | * @param h CADET handle. | ||
1807 | * @param port Hash representing the port number. | ||
1808 | * @param new_channel Function called when an channel is received. | ||
1809 | * @param new_channel_cls Closure for @a new_channel. | ||
1810 | * @return Port handle. | ||
1811 | */ | ||
1812 | struct GNUNET_CADET_Port * | ||
1813 | GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h, | ||
1814 | const struct GNUNET_HashCode *port, | ||
1815 | GNUNET_CADET_InboundChannelNotificationHandler | ||
1816 | new_channel, | ||
1817 | void *new_channel_cls) | ||
1818 | { | ||
1819 | struct GNUNET_CADET_PortMessage *msg; | ||
1820 | struct GNUNET_MQ_Envelope *env; | ||
1821 | struct GNUNET_CADET_Port *p; | ||
1822 | |||
1823 | GNUNET_assert (NULL != new_channel); | ||
1824 | p = GNUNET_new (struct GNUNET_CADET_Port); | ||
1825 | p->cadet = h; | ||
1826 | p->hash = GNUNET_new (struct GNUNET_HashCode); | ||
1827 | *p->hash = *port; | ||
1828 | p->handler = new_channel; | ||
1829 | p->cls = new_channel_cls; | ||
1830 | GNUNET_assert (GNUNET_OK == | ||
1831 | GNUNET_CONTAINER_multihashmap_put (h->ports, | ||
1832 | p->hash, | ||
1833 | p, | ||
1834 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1835 | |||
1836 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN); | ||
1837 | msg->port = *p->hash; | ||
1838 | GNUNET_MQ_send (h->mq, env); | ||
1839 | |||
1840 | return p; | ||
1841 | } | ||
1842 | |||
1843 | /** | ||
1844 | * Close a port opened with @a GNUNET_CADET_open_port. | ||
1845 | * The @a new_channel callback will no longer be called. | 1201 | * The @a new_channel callback will no longer be called. |
1846 | * | 1202 | * |
1847 | * @param p Port handle. | 1203 | * @param p Port handle. |
@@ -1851,111 +1207,45 @@ GNUNET_CADET_close_port (struct GNUNET_CADET_Port *p) | |||
1851 | { | 1207 | { |
1852 | struct GNUNET_CADET_PortMessage *msg; | 1208 | struct GNUNET_CADET_PortMessage *msg; |
1853 | struct GNUNET_MQ_Envelope *env; | 1209 | struct GNUNET_MQ_Envelope *env; |
1854 | struct GNUNET_HashCode *id; | ||
1855 | |||
1856 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE); | ||
1857 | 1210 | ||
1858 | id = NULL != p->hash ? p->hash : &p->id; | 1211 | env = GNUNET_MQ_msg (msg, |
1859 | msg->port = *id; | 1212 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE); |
1860 | GNUNET_MQ_send (p->cadet->mq, env); | 1213 | msg->port = p->id; |
1861 | GNUNET_CONTAINER_multihashmap_remove (p->cadet->ports, id, p); | 1214 | GNUNET_MQ_send (p->cadet->mq, |
1862 | GNUNET_free_non_null (p->hash); | 1215 | env); |
1216 | GNUNET_assert (GNUNET_YES == | ||
1217 | GNUNET_CONTAINER_multihashmap_remove (p->cadet->ports, | ||
1218 | &p->id, | ||
1219 | p)); | ||
1220 | GNUNET_free_non_null (p->handlers); | ||
1863 | GNUNET_free (p); | 1221 | GNUNET_free (p); |
1864 | } | 1222 | } |
1865 | 1223 | ||
1866 | 1224 | ||
1867 | /** | 1225 | /** |
1868 | * Create a new channel towards a remote peer. | 1226 | * Destroy an existing channel. |
1869 | * | 1227 | * |
1870 | * If the destination port is not open by any peer or the destination peer | 1228 | * The existing end callback for the channel will be called immediately. |
1871 | * does not accept the channel, #GNUNET_CADET_ChannelEndHandler will be called | 1229 | * Any pending outgoing messages will be sent but no incoming messages will be |
1872 | * for this channel. | 1230 | * accepted and no data callbacks will be called. |
1873 | * | 1231 | * |
1874 | * @param h cadet handle | 1232 | * @param channel Channel handle, becomes invalid after this call. |
1875 | * @param channel_ctx client's channel context to associate with the channel | ||
1876 | * @param peer peer identity the channel should go to | ||
1877 | * @param port Port hash (port number). | ||
1878 | * @param options CadetOption flag field, with all desired option bits set to 1. | ||
1879 | * @return handle to the channel | ||
1880 | */ | 1233 | */ |
1881 | struct GNUNET_CADET_Channel * | ||
1882 | GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h, | ||
1883 | void *channel_ctx, | ||
1884 | const struct GNUNET_PeerIdentity *peer, | ||
1885 | const struct GNUNET_HashCode *port, | ||
1886 | enum GNUNET_CADET_ChannelOption options) | ||
1887 | { | ||
1888 | struct GNUNET_CADET_LocalChannelCreateMessage *msg; | ||
1889 | struct GNUNET_MQ_Envelope *env; | ||
1890 | struct GNUNET_CADET_Channel *ch; | ||
1891 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
1892 | |||
1893 | ccn.channel_of_client = htonl (0); | ||
1894 | ch = create_channel (h, ccn); | ||
1895 | ch->ctx = channel_ctx; | ||
1896 | ch->peer = GNUNET_PEER_intern (peer); | ||
1897 | |||
1898 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1899 | "Creating new channel to %s:%u at %p number %X\n", | ||
1900 | GNUNET_i2s (peer), | ||
1901 | port, | ||
1902 | ch, | ||
1903 | ntohl (ch->ccn.channel_of_client)); | ||
1904 | env = GNUNET_MQ_msg (msg, | ||
1905 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE); | ||
1906 | msg->ccn = ch->ccn; | ||
1907 | msg->port = *port; | ||
1908 | msg->peer = *peer; | ||
1909 | msg->opt = htonl (options); | ||
1910 | GNUNET_MQ_send (h->mq, | ||
1911 | env); | ||
1912 | return ch; | ||
1913 | } | ||
1914 | |||
1915 | |||
1916 | void | 1234 | void |
1917 | GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel) | 1235 | GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel) |
1918 | { | 1236 | { |
1919 | struct GNUNET_CADET_Handle *h; | 1237 | struct GNUNET_CADET_Handle *h = channel->cadet; |
1920 | struct GNUNET_CADET_LocalChannelDestroyMessage *msg; | 1238 | struct GNUNET_CADET_LocalChannelDestroyMessage *msg; |
1921 | struct GNUNET_MQ_Envelope *env; | 1239 | struct GNUNET_MQ_Envelope *env; |
1922 | struct GNUNET_CADET_TransmitHandle *th; | ||
1923 | struct GNUNET_CADET_TransmitHandle *next; | ||
1924 | 1240 | ||
1925 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1241 | if (NULL != h->mq) |
1926 | "Destroying channel\n"); | ||
1927 | h = channel->cadet; | ||
1928 | for (th = h->th_head; th != NULL; th = next) | ||
1929 | { | 1242 | { |
1930 | next = th->next; | 1243 | env = GNUNET_MQ_msg (msg, |
1931 | if (th->channel == channel) | 1244 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); |
1932 | { | 1245 | msg->ccn = channel->ccn; |
1933 | GNUNET_break (0); | 1246 | GNUNET_MQ_send (h->mq, |
1934 | if (GNUNET_YES == th_is_payload (th)) | 1247 | env); |
1935 | { | ||
1936 | /* applications should cancel before destroying channel */ | ||
1937 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1938 | "Channel destroyed without cancelling transmission requests\n"); | ||
1939 | th->notify (th->notify_cls, 0, NULL); | ||
1940 | } | ||
1941 | else | ||
1942 | { | ||
1943 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1944 | "no meta-traffic should be queued\n"); | ||
1945 | } | ||
1946 | GNUNET_CONTAINER_DLL_remove (h->th_head, | ||
1947 | h->th_tail, | ||
1948 | th); | ||
1949 | GNUNET_CADET_notify_transmit_ready_cancel (th); | ||
1950 | } | ||
1951 | } | 1248 | } |
1952 | |||
1953 | env = GNUNET_MQ_msg (msg, | ||
1954 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); | ||
1955 | msg->ccn = channel->ccn; | ||
1956 | GNUNET_MQ_send (h->mq, | ||
1957 | env); | ||
1958 | |||
1959 | destroy_channel (channel); | 1249 | destroy_channel (channel); |
1960 | } | 1250 | } |
1961 | 1251 | ||
@@ -1971,10 +1261,10 @@ GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel) | |||
1971 | */ | 1261 | */ |
1972 | const union GNUNET_CADET_ChannelInfo * | 1262 | const union GNUNET_CADET_ChannelInfo * |
1973 | GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel, | 1263 | GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel, |
1974 | enum GNUNET_CADET_ChannelOption option, ...) | 1264 | enum GNUNET_CADET_ChannelOption option, |
1265 | ...) | ||
1975 | { | 1266 | { |
1976 | static int bool_flag; | 1267 | static int bool_flag; |
1977 | const union GNUNET_CADET_ChannelInfo *ret; | ||
1978 | 1268 | ||
1979 | switch (option) | 1269 | switch (option) |
1980 | { | 1270 | { |
@@ -1985,74 +1275,15 @@ GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel, | |||
1985 | bool_flag = GNUNET_YES; | 1275 | bool_flag = GNUNET_YES; |
1986 | else | 1276 | else |
1987 | bool_flag = GNUNET_NO; | 1277 | bool_flag = GNUNET_NO; |
1988 | ret = (const union GNUNET_CADET_ChannelInfo *) &bool_flag; | 1278 | return (const union GNUNET_CADET_ChannelInfo *) &bool_flag; |
1989 | break; | 1279 | break; |
1990 | case GNUNET_CADET_OPTION_PEER: | 1280 | case GNUNET_CADET_OPTION_PEER: |
1991 | ret = (const union GNUNET_CADET_ChannelInfo *) GNUNET_PEER_resolve2 (channel->peer); | 1281 | return (const union GNUNET_CADET_ChannelInfo *) &channel->peer; |
1992 | break; | 1282 | break; |
1993 | default: | 1283 | default: |
1994 | GNUNET_break (0); | 1284 | GNUNET_break (0); |
1995 | return NULL; | 1285 | return NULL; |
1996 | } | 1286 | } |
1997 | |||
1998 | return ret; | ||
1999 | } | ||
2000 | |||
2001 | |||
2002 | struct GNUNET_CADET_TransmitHandle * | ||
2003 | GNUNET_CADET_notify_transmit_ready (struct GNUNET_CADET_Channel *channel, | ||
2004 | int cork, | ||
2005 | struct GNUNET_TIME_Relative maxdelay, | ||
2006 | size_t notify_size, | ||
2007 | GNUNET_CONNECTION_TransmitReadyNotify notify, | ||
2008 | void *notify_cls) | ||
2009 | { | ||
2010 | struct GNUNET_CADET_TransmitHandle *th; | ||
2011 | |||
2012 | GNUNET_assert (NULL != channel); | ||
2013 | GNUNET_assert (NULL != notify); | ||
2014 | GNUNET_assert (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE >= notify_size); | ||
2015 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2016 | "CADET NOTIFY TRANSMIT READY on channel %X allow_send is %u to %s with %u bytes\n", | ||
2017 | ntohl (channel->ccn.channel_of_client), | ||
2018 | channel->allow_send, | ||
2019 | (ntohl (channel->ccn.channel_of_client) >= | ||
2020 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
2021 | ? "origin" | ||
2022 | : "destination", | ||
2023 | (unsigned int) notify_size); | ||
2024 | if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != maxdelay.rel_value_us) | ||
2025 | { | ||
2026 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
2027 | "CADET transmit ready timeout is deprected (has no effect)\n"); | ||
2028 | } | ||
2029 | |||
2030 | th = GNUNET_new (struct GNUNET_CADET_TransmitHandle); | ||
2031 | th->channel = channel; | ||
2032 | th->size = notify_size; | ||
2033 | th->notify = notify; | ||
2034 | th->notify_cls = notify_cls; | ||
2035 | if (0 != channel->allow_send) | ||
2036 | th->request_data_task | ||
2037 | = GNUNET_SCHEDULER_add_now (&request_data, | ||
2038 | th); | ||
2039 | else | ||
2040 | add_to_queue (channel->cadet, | ||
2041 | th); | ||
2042 | return th; | ||
2043 | } | ||
2044 | |||
2045 | |||
2046 | void | ||
2047 | GNUNET_CADET_notify_transmit_ready_cancel (struct GNUNET_CADET_TransmitHandle *th) | ||
2048 | { | ||
2049 | if (NULL != th->request_data_task) | ||
2050 | { | ||
2051 | GNUNET_SCHEDULER_cancel (th->request_data_task); | ||
2052 | th->request_data_task = NULL; | ||
2053 | } | ||
2054 | remove_from_queue (th); | ||
2055 | GNUNET_free (th); | ||
2056 | } | 1287 | } |
2057 | 1288 | ||
2058 | 1289 | ||
@@ -2078,18 +1309,23 @@ GNUNET_CADET_receive_done (struct GNUNET_CADET_Channel *channel) | |||
2078 | } | 1309 | } |
2079 | 1310 | ||
2080 | 1311 | ||
1312 | /** | ||
1313 | * Send message of @a type to CADET service of @a h | ||
1314 | * | ||
1315 | * @param h handle to CADET service | ||
1316 | * @param type message type of trivial information request to send | ||
1317 | */ | ||
2081 | static void | 1318 | static void |
2082 | send_info_request (struct GNUNET_CADET_Handle *h, uint16_t type) | 1319 | send_info_request (struct GNUNET_CADET_Handle *h, |
1320 | uint16_t type) | ||
2083 | { | 1321 | { |
2084 | struct GNUNET_MessageHeader *msg; | 1322 | struct GNUNET_MessageHeader *msg; |
2085 | struct GNUNET_MQ_Envelope *env; | 1323 | struct GNUNET_MQ_Envelope *env; |
2086 | 1324 | ||
2087 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1325 | env = GNUNET_MQ_msg (msg, |
2088 | " Sending %s monitor message to service\n", | 1326 | type); |
2089 | GC_m2s(type)); | 1327 | GNUNET_MQ_send (h->mq, |
2090 | 1328 | env); | |
2091 | env = GNUNET_MQ_msg (msg, type); | ||
2092 | GNUNET_MQ_send (h->mq, env); | ||
2093 | } | 1329 | } |
2094 | 1330 | ||
2095 | 1331 | ||
@@ -2103,8 +1339,8 @@ send_info_request (struct GNUNET_CADET_Handle *h, uint16_t type) | |||
2103 | void | 1339 | void |
2104 | GNUNET_CADET_request_dump (struct GNUNET_CADET_Handle *h) | 1340 | GNUNET_CADET_request_dump (struct GNUNET_CADET_Handle *h) |
2105 | { | 1341 | { |
2106 | LOG (GNUNET_ERROR_TYPE_DEBUG, "requesting dump\n"); | 1342 | send_info_request (h, |
2107 | send_info_request (h, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP); | 1343 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP); |
2108 | } | 1344 | } |
2109 | 1345 | ||
2110 | 1346 | ||
@@ -2113,13 +1349,11 @@ GNUNET_CADET_request_dump (struct GNUNET_CADET_Handle *h) | |||
2113 | * The callback will be called for every peer known to the service. | 1349 | * The callback will be called for every peer known to the service. |
2114 | * Only one info request (of any kind) can be active at once. | 1350 | * Only one info request (of any kind) can be active at once. |
2115 | * | 1351 | * |
2116 | * | ||
2117 | * WARNING: unstable API, likely to change in the future! | 1352 | * WARNING: unstable API, likely to change in the future! |
2118 | * | 1353 | * |
2119 | * @param h Handle to the cadet peer. | 1354 | * @param h Handle to the cadet peer. |
2120 | * @param callback Function to call with the requested data. | 1355 | * @param callback Function to call with the requested data. |
2121 | * @param callback_cls Closure for @c callback. | 1356 | * @param callback_cls Closure for @c callback. |
2122 | * | ||
2123 | * @return #GNUNET_OK / #GNUNET_SYSERR | 1357 | * @return #GNUNET_OK / #GNUNET_SYSERR |
2124 | */ | 1358 | */ |
2125 | int | 1359 | int |
@@ -2132,7 +1366,8 @@ GNUNET_CADET_get_peers (struct GNUNET_CADET_Handle *h, | |||
2132 | GNUNET_break (0); | 1366 | GNUNET_break (0); |
2133 | return GNUNET_SYSERR; | 1367 | return GNUNET_SYSERR; |
2134 | } | 1368 | } |
2135 | send_info_request (h, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | 1369 | send_info_request (h, |
1370 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | ||
2136 | h->info_cb.peers_cb = callback; | 1371 | h->info_cb.peers_cb = callback; |
2137 | h->info_cls = callback_cls; | 1372 | h->info_cls = callback_cls; |
2138 | return GNUNET_OK; | 1373 | return GNUNET_OK; |
@@ -2145,15 +1380,13 @@ GNUNET_CADET_get_peers (struct GNUNET_CADET_Handle *h, | |||
2145 | * WARNING: unstable API, likely to change in the future! | 1380 | * WARNING: unstable API, likely to change in the future! |
2146 | * | 1381 | * |
2147 | * @param h Cadet handle. | 1382 | * @param h Cadet handle. |
2148 | * | 1383 | * @return Closure given to GNUNET_CADET_get_peers(). |
2149 | * @return Closure given to GNUNET_CADET_get_peers. | ||
2150 | */ | 1384 | */ |
2151 | void * | 1385 | void * |
2152 | GNUNET_CADET_get_peers_cancel (struct GNUNET_CADET_Handle *h) | 1386 | GNUNET_CADET_get_peers_cancel (struct GNUNET_CADET_Handle *h) |
2153 | { | 1387 | { |
2154 | void *cls; | 1388 | void *cls = h->info_cls; |
2155 | 1389 | ||
2156 | cls = h->info_cls; | ||
2157 | h->info_cb.peers_cb = NULL; | 1390 | h->info_cb.peers_cb = NULL; |
2158 | h->info_cls = NULL; | 1391 | h->info_cls = NULL; |
2159 | return cls; | 1392 | return cls; |
@@ -2171,7 +1404,6 @@ GNUNET_CADET_get_peers_cancel (struct GNUNET_CADET_Handle *h) | |||
2171 | * @param id Peer whose tunnel to examine. | 1404 | * @param id Peer whose tunnel to examine. |
2172 | * @param callback Function to call with the requested data. | 1405 | * @param callback Function to call with the requested data. |
2173 | * @param callback_cls Closure for @c callback. | 1406 | * @param callback_cls Closure for @c callback. |
2174 | * | ||
2175 | * @return #GNUNET_OK / #GNUNET_SYSERR | 1407 | * @return #GNUNET_OK / #GNUNET_SYSERR |
2176 | */ | 1408 | */ |
2177 | int | 1409 | int |
@@ -2188,11 +1420,11 @@ GNUNET_CADET_get_peer (struct GNUNET_CADET_Handle *h, | |||
2188 | GNUNET_break (0); | 1420 | GNUNET_break (0); |
2189 | return GNUNET_SYSERR; | 1421 | return GNUNET_SYSERR; |
2190 | } | 1422 | } |
2191 | 1423 | env = GNUNET_MQ_msg (msg, | |
2192 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER); | 1424 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER); |
2193 | msg->peer = *id; | 1425 | msg->peer = *id; |
2194 | GNUNET_MQ_send (h->mq, env); | 1426 | GNUNET_MQ_send (h->mq, |
2195 | 1427 | env); | |
2196 | h->info_cb.peer_cb = callback; | 1428 | h->info_cb.peer_cb = callback; |
2197 | h->info_cls = callback_cls; | 1429 | h->info_cls = callback_cls; |
2198 | return GNUNET_OK; | 1430 | return GNUNET_OK; |
@@ -2209,7 +1441,6 @@ GNUNET_CADET_get_peer (struct GNUNET_CADET_Handle *h, | |||
2209 | * @param h Handle to the cadet peer. | 1441 | * @param h Handle to the cadet peer. |
2210 | * @param callback Function to call with the requested data. | 1442 | * @param callback Function to call with the requested data. |
2211 | * @param callback_cls Closure for @c callback. | 1443 | * @param callback_cls Closure for @c callback. |
2212 | * | ||
2213 | * @return #GNUNET_OK / #GNUNET_SYSERR | 1444 | * @return #GNUNET_OK / #GNUNET_SYSERR |
2214 | */ | 1445 | */ |
2215 | int | 1446 | int |
@@ -2222,7 +1453,8 @@ GNUNET_CADET_get_tunnels (struct GNUNET_CADET_Handle *h, | |||
2222 | GNUNET_break (0); | 1453 | GNUNET_break (0); |
2223 | return GNUNET_SYSERR; | 1454 | return GNUNET_SYSERR; |
2224 | } | 1455 | } |
2225 | send_info_request (h, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | 1456 | send_info_request (h, |
1457 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | ||
2226 | h->info_cb.tunnels_cb = callback; | 1458 | h->info_cb.tunnels_cb = callback; |
2227 | h->info_cls = callback_cls; | 1459 | h->info_cls = callback_cls; |
2228 | return GNUNET_OK; | 1460 | return GNUNET_OK; |
@@ -2233,23 +1465,19 @@ GNUNET_CADET_get_tunnels (struct GNUNET_CADET_Handle *h, | |||
2233 | * Cancel a monitor request. The monitor callback will not be called. | 1465 | * Cancel a monitor request. The monitor callback will not be called. |
2234 | * | 1466 | * |
2235 | * @param h Cadet handle. | 1467 | * @param h Cadet handle. |
2236 | * | 1468 | * @return Closure given to GNUNET_CADET_get_tunnels(). |
2237 | * @return Closure given to GNUNET_CADET_get_tunnels. | ||
2238 | */ | 1469 | */ |
2239 | void * | 1470 | void * |
2240 | GNUNET_CADET_get_tunnels_cancel (struct GNUNET_CADET_Handle *h) | 1471 | GNUNET_CADET_get_tunnels_cancel (struct GNUNET_CADET_Handle *h) |
2241 | { | 1472 | { |
2242 | void *cls; | 1473 | void *cls = h->info_cls; |
2243 | 1474 | ||
2244 | h->info_cb.tunnels_cb = NULL; | 1475 | h->info_cb.tunnels_cb = NULL; |
2245 | cls = h->info_cls; | ||
2246 | h->info_cls = NULL; | 1476 | h->info_cls = NULL; |
2247 | |||
2248 | return cls; | 1477 | return cls; |
2249 | } | 1478 | } |
2250 | 1479 | ||
2251 | 1480 | ||
2252 | |||
2253 | /** | 1481 | /** |
2254 | * Request information about a tunnel of the running cadet peer. | 1482 | * Request information about a tunnel of the running cadet peer. |
2255 | * The callback will be called for the tunnel once. | 1483 | * The callback will be called for the tunnel once. |
@@ -2261,7 +1489,6 @@ GNUNET_CADET_get_tunnels_cancel (struct GNUNET_CADET_Handle *h) | |||
2261 | * @param id Peer whose tunnel to examine. | 1489 | * @param id Peer whose tunnel to examine. |
2262 | * @param callback Function to call with the requested data. | 1490 | * @param callback Function to call with the requested data. |
2263 | * @param callback_cls Closure for @c callback. | 1491 | * @param callback_cls Closure for @c callback. |
2264 | * | ||
2265 | * @return #GNUNET_OK / #GNUNET_SYSERR | 1492 | * @return #GNUNET_OK / #GNUNET_SYSERR |
2266 | */ | 1493 | */ |
2267 | int | 1494 | int |
@@ -2278,11 +1505,11 @@ GNUNET_CADET_get_tunnel (struct GNUNET_CADET_Handle *h, | |||
2278 | GNUNET_break (0); | 1505 | GNUNET_break (0); |
2279 | return GNUNET_SYSERR; | 1506 | return GNUNET_SYSERR; |
2280 | } | 1507 | } |
2281 | 1508 | env = GNUNET_MQ_msg (msg, | |
2282 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); | 1509 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); |
2283 | msg->peer = *id; | 1510 | msg->peer = *id; |
2284 | GNUNET_MQ_send (h->mq, env); | 1511 | GNUNET_MQ_send (h->mq, |
2285 | 1512 | env); | |
2286 | h->info_cb.tunnel_cb = callback; | 1513 | h->info_cb.tunnel_cb = callback; |
2287 | h->info_cls = callback_cls; | 1514 | h->info_cls = callback_cls; |
2288 | return GNUNET_OK; | 1515 | return GNUNET_OK; |
@@ -2290,158 +1517,6 @@ GNUNET_CADET_get_tunnel (struct GNUNET_CADET_Handle *h, | |||
2290 | 1517 | ||
2291 | 1518 | ||
2292 | /** | 1519 | /** |
2293 | * Request information about a specific channel of the running cadet peer. | ||
2294 | * | ||
2295 | * WARNING: unstable API, likely to change in the future! | ||
2296 | * FIXME Add destination option. | ||
2297 | * | ||
2298 | * @param h Handle to the cadet peer. | ||
2299 | * @param initiator ID of the owner of the channel. | ||
2300 | * @param channel_number Channel number. | ||
2301 | * @param callback Function to call with the requested data. | ||
2302 | * @param callback_cls Closure for @c callback. | ||
2303 | * | ||
2304 | * @return #GNUNET_OK / #GNUNET_SYSERR | ||
2305 | */ | ||
2306 | int | ||
2307 | GNUNET_CADET_show_channel (struct GNUNET_CADET_Handle *h, | ||
2308 | struct GNUNET_PeerIdentity *initiator, | ||
2309 | unsigned int channel_number, | ||
2310 | GNUNET_CADET_ChannelCB callback, | ||
2311 | void *callback_cls) | ||
2312 | { | ||
2313 | struct GNUNET_CADET_LocalInfo *msg; | ||
2314 | struct GNUNET_MQ_Envelope *env; | ||
2315 | |||
2316 | if (NULL != h->info_cb.channel_cb) | ||
2317 | { | ||
2318 | GNUNET_break (0); | ||
2319 | return GNUNET_SYSERR; | ||
2320 | } | ||
2321 | |||
2322 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL); | ||
2323 | msg->peer = *initiator; | ||
2324 | msg->ccn.channel_of_client = htonl (channel_number); | ||
2325 | GNUNET_MQ_send (h->mq, env); | ||
2326 | |||
2327 | h->info_cb.channel_cb = callback; | ||
2328 | h->info_cls = callback_cls; | ||
2329 | return GNUNET_OK; | ||
2330 | } | ||
2331 | |||
2332 | |||
2333 | /** | ||
2334 | * Function called to notify a client about the connection | ||
2335 | * begin ready to queue more data. "buf" will be | ||
2336 | * NULL and "size" zero if the connection was closed for | ||
2337 | * writing in the meantime. | ||
2338 | * | ||
2339 | * @param cls closure | ||
2340 | * @param size number of bytes available in buf | ||
2341 | * @param buf where the callee should write the message | ||
2342 | * @return number of bytes written to buf | ||
2343 | */ | ||
2344 | static size_t | ||
2345 | cadet_mq_ntr (void *cls, size_t size, | ||
2346 | void *buf) | ||
2347 | { | ||
2348 | struct GNUNET_MQ_Handle *mq = cls; | ||
2349 | struct CadetMQState *state = GNUNET_MQ_impl_state (mq); | ||
2350 | const struct GNUNET_MessageHeader *msg = GNUNET_MQ_impl_current (mq); | ||
2351 | uint16_t msize; | ||
2352 | |||
2353 | state->th = NULL; | ||
2354 | if (NULL == buf) | ||
2355 | { | ||
2356 | GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE); | ||
2357 | return 0; | ||
2358 | } | ||
2359 | msize = ntohs (msg->size); | ||
2360 | GNUNET_assert (msize <= size); | ||
2361 | GNUNET_memcpy (buf, msg, msize); | ||
2362 | GNUNET_MQ_impl_send_continue (mq); | ||
2363 | return msize; | ||
2364 | } | ||
2365 | |||
2366 | |||
2367 | /** | ||
2368 | * Signature of functions implementing the | ||
2369 | * sending functionality of a message queue. | ||
2370 | * | ||
2371 | * @param mq the message queue | ||
2372 | * @param msg the message to send | ||
2373 | * @param impl_state state of the implementation | ||
2374 | */ | ||
2375 | static void | ||
2376 | cadet_mq_send_impl_old (struct GNUNET_MQ_Handle *mq, | ||
2377 | const struct GNUNET_MessageHeader *msg, | ||
2378 | void *impl_state) | ||
2379 | { | ||
2380 | struct CadetMQState *state = impl_state; | ||
2381 | |||
2382 | GNUNET_assert (NULL == state->th); | ||
2383 | state->th = | ||
2384 | GNUNET_CADET_notify_transmit_ready (state->channel, | ||
2385 | /* FIXME: add option for corking */ | ||
2386 | GNUNET_NO, | ||
2387 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
2388 | ntohs (msg->size), | ||
2389 | &cadet_mq_ntr, mq); | ||
2390 | |||
2391 | } | ||
2392 | |||
2393 | |||
2394 | /** | ||
2395 | * Signature of functions implementing the | ||
2396 | * destruction of a message queue. | ||
2397 | * Implementations must not free 'mq', but should | ||
2398 | * take care of 'impl_state'. | ||
2399 | * | ||
2400 | * @param mq the message queue to destroy | ||
2401 | * @param impl_state state of the implementation | ||
2402 | */ | ||
2403 | static void | ||
2404 | cadet_mq_destroy_impl_old (struct GNUNET_MQ_Handle *mq, | ||
2405 | void *impl_state) | ||
2406 | { | ||
2407 | struct CadetMQState *state = impl_state; | ||
2408 | |||
2409 | if (NULL != state->th) | ||
2410 | GNUNET_CADET_notify_transmit_ready_cancel (state->th); | ||
2411 | |||
2412 | GNUNET_free (state); | ||
2413 | } | ||
2414 | |||
2415 | |||
2416 | /** | ||
2417 | * Create a message queue for a cadet channel. | ||
2418 | * The message queue can only be used to transmit messages, | ||
2419 | * not to receive them. | ||
2420 | * | ||
2421 | * @param channel the channel to create the message qeue for | ||
2422 | * @return a message queue to messages over the channel | ||
2423 | */ | ||
2424 | struct GNUNET_MQ_Handle * | ||
2425 | GNUNET_CADET_mq_create (struct GNUNET_CADET_Channel *channel) | ||
2426 | { | ||
2427 | struct GNUNET_MQ_Handle *mq; | ||
2428 | struct CadetMQState *state; | ||
2429 | |||
2430 | state = GNUNET_new (struct CadetMQState); | ||
2431 | state->channel = channel; | ||
2432 | |||
2433 | mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl_old, | ||
2434 | &cadet_mq_destroy_impl_old, | ||
2435 | NULL, /* FIXME: cancel impl. */ | ||
2436 | state, | ||
2437 | NULL, /* no msg handlers */ | ||
2438 | NULL, /* no err handlers */ | ||
2439 | NULL); /* no handler cls */ | ||
2440 | return mq; | ||
2441 | } | ||
2442 | |||
2443 | |||
2444 | /** | ||
2445 | * Transitional function to convert an unsigned int port to a hash value. | 1520 | * Transitional function to convert an unsigned int port to a hash value. |
2446 | * WARNING: local static value returned, NOT reentrant! | 1521 | * WARNING: local static value returned, NOT reentrant! |
2447 | * WARNING: do not use this function for new code! | 1522 | * WARNING: do not use this function for new code! |
@@ -2456,19 +1531,14 @@ GC_u2h (uint32_t port) | |||
2456 | static struct GNUNET_HashCode hash; | 1531 | static struct GNUNET_HashCode hash; |
2457 | 1532 | ||
2458 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 1533 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
2459 | "This is a transitional function, " | 1534 | "This is a transitional function, use proper crypto hashes as CADET ports\n"); |
2460 | "use proper crypto hashes as CADET ports\n"); | 1535 | GNUNET_CRYPTO_hash (&port, |
2461 | GNUNET_CRYPTO_hash (&port, sizeof (port), &hash); | 1536 | sizeof (port), |
2462 | 1537 | &hash); | |
2463 | return &hash; | 1538 | return &hash; |
2464 | } | 1539 | } |
2465 | 1540 | ||
2466 | 1541 | ||
2467 | |||
2468 | /******************************************************************************/ | ||
2469 | /******************************* MQ-BASED API *********************************/ | ||
2470 | /******************************************************************************/ | ||
2471 | |||
2472 | /** | 1542 | /** |
2473 | * Connect to the MQ-based cadet service. | 1543 | * Connect to the MQ-based cadet service. |
2474 | * | 1544 | * |
@@ -2477,16 +1547,17 @@ GC_u2h (uint32_t port) | |||
2477 | * @return Handle to the cadet service NULL on error. | 1547 | * @return Handle to the cadet service NULL on error. |
2478 | */ | 1548 | */ |
2479 | struct GNUNET_CADET_Handle * | 1549 | struct GNUNET_CADET_Handle * |
2480 | GNUNET_CADET_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg) | 1550 | GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) |
2481 | { | 1551 | { |
2482 | struct GNUNET_CADET_Handle *h; | 1552 | struct GNUNET_CADET_Handle *h; |
2483 | 1553 | ||
2484 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1554 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2485 | "GNUNET_CADET_connecT()\n"); | 1555 | "GNUNET_CADET_connect()\n"); |
2486 | h = GNUNET_new (struct GNUNET_CADET_Handle); | 1556 | h = GNUNET_new (struct GNUNET_CADET_Handle); |
2487 | h->cfg = cfg; | 1557 | h->cfg = cfg; |
2488 | h->mq_api = GNUNET_YES; | 1558 | h->ports = GNUNET_CONTAINER_multihashmap_create (4, |
2489 | h->ports = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_YES); | 1559 | GNUNET_YES); |
1560 | h->channels = GNUNET_CONTAINER_multihashmap32_create (4); | ||
2490 | reconnect (h); | 1561 | reconnect (h); |
2491 | if (NULL == h->mq) | 1562 | if (NULL == h->mq) |
2492 | { | 1563 | { |
@@ -2512,11 +1583,10 @@ GNUNET_CADET_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg) | |||
2512 | * @param window_changes Function called when the transmit window size changes. | 1583 | * @param window_changes Function called when the transmit window size changes. |
2513 | * @param disconnects Function called when a channel is disconnected. | 1584 | * @param disconnects Function called when a channel is disconnected. |
2514 | * @param handlers Callbacks for messages we care about, NULL-terminated. | 1585 | * @param handlers Callbacks for messages we care about, NULL-terminated. |
2515 | * | ||
2516 | * @return Port handle. | 1586 | * @return Port handle. |
2517 | */ | 1587 | */ |
2518 | struct GNUNET_CADET_Port * | 1588 | struct GNUNET_CADET_Port * |
2519 | GNUNET_CADET_open_porT (struct GNUNET_CADET_Handle *h, | 1589 | GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h, |
2520 | const struct GNUNET_HashCode *port, | 1590 | const struct GNUNET_HashCode *port, |
2521 | GNUNET_CADET_ConnectEventHandler connects, | 1591 | GNUNET_CADET_ConnectEventHandler connects, |
2522 | void * connects_cls, | 1592 | void * connects_cls, |
@@ -2538,16 +1608,7 @@ GNUNET_CADET_open_porT (struct GNUNET_CADET_Handle *h, | |||
2538 | p->cls = connects_cls; | 1608 | p->cls = connects_cls; |
2539 | p->window_changes = window_changes; | 1609 | p->window_changes = window_changes; |
2540 | p->disconnects = disconnects; | 1610 | p->disconnects = disconnects; |
2541 | if (NULL != handlers) | 1611 | p->handlers = GNUNET_MQ_copy_handlers (handlers); |
2542 | { | ||
2543 | unsigned int i; | ||
2544 | for (i=0;NULL != handlers[i].cb; i++) ; | ||
2545 | p->handlers = GNUNET_new_array (i + 1, | ||
2546 | struct GNUNET_MQ_MessageHandler); | ||
2547 | GNUNET_memcpy ((struct GNUNET_MQ_MessageHandler *) p->handlers, | ||
2548 | handlers, | ||
2549 | i * sizeof (struct GNUNET_MQ_MessageHandler)); | ||
2550 | } | ||
2551 | 1612 | ||
2552 | GNUNET_assert (GNUNET_OK == | 1613 | GNUNET_assert (GNUNET_OK == |
2553 | GNUNET_CONTAINER_multihashmap_put (h->ports, | 1614 | GNUNET_CONTAINER_multihashmap_put (h->ports, |
@@ -2555,10 +1616,11 @@ GNUNET_CADET_open_porT (struct GNUNET_CADET_Handle *h, | |||
2555 | p, | 1616 | p, |
2556 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | 1617 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); |
2557 | 1618 | ||
2558 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN); | 1619 | env = GNUNET_MQ_msg (msg, |
1620 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN); | ||
2559 | msg->port = p->id; | 1621 | msg->port = p->id; |
2560 | GNUNET_MQ_send (h->mq, env); | 1622 | GNUNET_MQ_send (h->mq, |
2561 | 1623 | env); | |
2562 | return p; | 1624 | return p; |
2563 | } | 1625 | } |
2564 | 1626 | ||
@@ -2580,11 +1642,10 @@ GNUNET_CADET_open_porT (struct GNUNET_CADET_Handle *h, | |||
2580 | * @param window_changes Function called when the transmit window size changes. | 1642 | * @param window_changes Function called when the transmit window size changes. |
2581 | * @param disconnects Function called when the channel is disconnected. | 1643 | * @param disconnects Function called when the channel is disconnected. |
2582 | * @param handlers Callbacks for messages we care about, NULL-terminated. | 1644 | * @param handlers Callbacks for messages we care about, NULL-terminated. |
2583 | * | ||
2584 | * @return Handle to the channel. | 1645 | * @return Handle to the channel. |
2585 | */ | 1646 | */ |
2586 | struct GNUNET_CADET_Channel * | 1647 | struct GNUNET_CADET_Channel * |
2587 | GNUNET_CADET_channel_creatE (struct GNUNET_CADET_Handle *h, | 1648 | GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h, |
2588 | void *channel_cls, | 1649 | void *channel_cls, |
2589 | const struct GNUNET_PeerIdentity *destination, | 1650 | const struct GNUNET_PeerIdentity *destination, |
2590 | const struct GNUNET_HashCode *port, | 1651 | const struct GNUNET_HashCode *port, |
@@ -2594,17 +1655,14 @@ GNUNET_CADET_channel_creatE (struct GNUNET_CADET_Handle *h, | |||
2594 | const struct GNUNET_MQ_MessageHandler *handlers) | 1655 | const struct GNUNET_MQ_MessageHandler *handlers) |
2595 | { | 1656 | { |
2596 | struct GNUNET_CADET_Channel *ch; | 1657 | struct GNUNET_CADET_Channel *ch; |
2597 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
2598 | struct GNUNET_CADET_LocalChannelCreateMessage *msg; | 1658 | struct GNUNET_CADET_LocalChannelCreateMessage *msg; |
2599 | struct GNUNET_MQ_Envelope *env; | 1659 | struct GNUNET_MQ_Envelope *env; |
2600 | 1660 | ||
2601 | GNUNET_assert (NULL != disconnects); | 1661 | GNUNET_assert (NULL != disconnects); |
2602 | 1662 | ch = create_channel (h, | |
2603 | /* Save parameters */ | 1663 | NULL); |
2604 | ccn.channel_of_client = htonl (0); | ||
2605 | ch = create_channel (h, ccn); | ||
2606 | ch->ctx = channel_cls; | 1664 | ch->ctx = channel_cls; |
2607 | ch->peer = GNUNET_PEER_intern (destination); | 1665 | ch->peer = *destination; |
2608 | ch->options = options; | 1666 | ch->options = options; |
2609 | ch->window_changes = window_changes; | 1667 | ch->window_changes = window_changes; |
2610 | ch->disconnects = disconnects; | 1668 | ch->disconnects = disconnects; |
@@ -2628,7 +1686,6 @@ GNUNET_CADET_channel_creatE (struct GNUNET_CADET_Handle *h, | |||
2628 | msg->opt = htonl (options); | 1686 | msg->opt = htonl (options); |
2629 | GNUNET_MQ_send (h->mq, | 1687 | GNUNET_MQ_send (h->mq, |
2630 | env); | 1688 | env); |
2631 | |||
2632 | return ch; | 1689 | return ch; |
2633 | } | 1690 | } |
2634 | 1691 | ||
@@ -2645,3 +1702,5 @@ GNUNET_CADET_get_mq (const struct GNUNET_CADET_Channel *channel) | |||
2645 | { | 1702 | { |
2646 | return channel->mq; | 1703 | return channel->mq; |
2647 | } | 1704 | } |
1705 | |||
1706 | /* end of cadet_api.c */ | ||
diff --git a/src/cadet/cadet_api_new.c b/src/cadet/cadet_api_new.c deleted file mode 100644 index a62de0a47..000000000 --- a/src/cadet/cadet_api_new.c +++ /dev/null | |||
@@ -1,1720 +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/cadet_api.c | ||
22 | * @brief cadet api: client implementation of cadet service | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_constants.h" | ||
29 | #include "gnunet_cadet_service.h" | ||
30 | #include "cadet.h" | ||
31 | #include "cadet_protocol.h" | ||
32 | |||
33 | #define LOG(kind,...) GNUNET_log_from (kind, "cadet-api",__VA_ARGS__) | ||
34 | |||
35 | /** | ||
36 | * Ugly legacy hack. | ||
37 | */ | ||
38 | union CadetInfoCB | ||
39 | { | ||
40 | |||
41 | /** | ||
42 | * Channel callback. | ||
43 | */ | ||
44 | GNUNET_CADET_ChannelCB channel_cb; | ||
45 | |||
46 | /** | ||
47 | * Monitor callback | ||
48 | */ | ||
49 | GNUNET_CADET_PeersCB peers_cb; | ||
50 | |||
51 | /** | ||
52 | * Monitor callback | ||
53 | */ | ||
54 | GNUNET_CADET_PeerCB peer_cb; | ||
55 | |||
56 | /** | ||
57 | * Monitor callback | ||
58 | */ | ||
59 | GNUNET_CADET_TunnelsCB tunnels_cb; | ||
60 | |||
61 | /** | ||
62 | * Tunnel callback. | ||
63 | */ | ||
64 | GNUNET_CADET_TunnelCB tunnel_cb; | ||
65 | }; | ||
66 | |||
67 | |||
68 | /** | ||
69 | * Opaque handle to the service. | ||
70 | */ | ||
71 | struct GNUNET_CADET_Handle | ||
72 | { | ||
73 | /** | ||
74 | * Message queue. | ||
75 | */ | ||
76 | struct GNUNET_MQ_Handle *mq; | ||
77 | |||
78 | /** | ||
79 | * Ports open. | ||
80 | */ | ||
81 | struct GNUNET_CONTAINER_MultiHashMap *ports; | ||
82 | |||
83 | /** | ||
84 | * Channels open. | ||
85 | */ | ||
86 | struct GNUNET_CONTAINER_MultiHashMap32 *channels; | ||
87 | |||
88 | /** | ||
89 | * child of the next channel to create (to avoid reusing IDs often) | ||
90 | */ | ||
91 | struct GNUNET_CADET_ClientChannelNumber next_ccn; | ||
92 | |||
93 | /** | ||
94 | * Configuration given by the client, in case of reconnection | ||
95 | */ | ||
96 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
97 | |||
98 | /** | ||
99 | * Task for trying to reconnect. | ||
100 | */ | ||
101 | struct GNUNET_SCHEDULER_Task *reconnect_task; | ||
102 | |||
103 | /** | ||
104 | * Callback for an info task (only one active at a time). | ||
105 | */ | ||
106 | union CadetInfoCB info_cb; | ||
107 | |||
108 | /** | ||
109 | * Info callback closure for @c info_cb. | ||
110 | */ | ||
111 | void *info_cls; | ||
112 | |||
113 | /** | ||
114 | * Time to the next reconnect in case one reconnect fails | ||
115 | */ | ||
116 | struct GNUNET_TIME_Relative reconnect_time; | ||
117 | |||
118 | }; | ||
119 | |||
120 | |||
121 | /** | ||
122 | * Opaque handle to a channel. | ||
123 | */ | ||
124 | struct GNUNET_CADET_Channel | ||
125 | { | ||
126 | |||
127 | /** | ||
128 | * Other end of the channel. | ||
129 | */ | ||
130 | struct GNUNET_PeerIdentity peer; | ||
131 | |||
132 | /** | ||
133 | * Handle to the cadet this channel belongs to | ||
134 | */ | ||
135 | struct GNUNET_CADET_Handle *cadet; | ||
136 | |||
137 | /** | ||
138 | * Channel's port, if incoming. | ||
139 | */ | ||
140 | struct GNUNET_CADET_Port *incoming_port; | ||
141 | |||
142 | /** | ||
143 | * Any data the caller wants to put in here, used for the | ||
144 | * various callbacks (@e disconnects, @e window_changes, handlers). | ||
145 | */ | ||
146 | void *ctx; | ||
147 | |||
148 | /** | ||
149 | * Message Queue for the channel (which we are implementing). | ||
150 | */ | ||
151 | struct GNUNET_MQ_Handle *mq; | ||
152 | |||
153 | /** | ||
154 | * Task to allow mq to send more traffic. | ||
155 | */ | ||
156 | struct GNUNET_SCHEDULER_Task *mq_cont; | ||
157 | |||
158 | /** | ||
159 | * Pending envelope with a message to be transmitted to the | ||
160 | * service as soon as we are allowed to. Should only be | ||
161 | * non-NULL if @e allow_send is 0. | ||
162 | */ | ||
163 | struct GNUNET_MQ_Envelope *pending_env; | ||
164 | |||
165 | /** | ||
166 | * Window change handler. | ||
167 | */ | ||
168 | GNUNET_CADET_WindowSizeEventHandler window_changes; | ||
169 | |||
170 | /** | ||
171 | * Disconnect handler. | ||
172 | */ | ||
173 | GNUNET_CADET_DisconnectEventHandler disconnects; | ||
174 | |||
175 | /** | ||
176 | * Local ID of the channel, #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI bit is set if outbound. | ||
177 | */ | ||
178 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
179 | |||
180 | /** | ||
181 | * Channel options: reliability, etc. | ||
182 | */ | ||
183 | enum GNUNET_CADET_ChannelOption options; | ||
184 | |||
185 | /** | ||
186 | * How many messages are we allowed to send to the service right now? | ||
187 | */ | ||
188 | unsigned int allow_send; | ||
189 | |||
190 | }; | ||
191 | |||
192 | |||
193 | /** | ||
194 | * Opaque handle to a port. | ||
195 | */ | ||
196 | struct GNUNET_CADET_Port | ||
197 | { | ||
198 | |||
199 | /** | ||
200 | * Port "number" | ||
201 | */ | ||
202 | struct GNUNET_HashCode id; | ||
203 | |||
204 | /** | ||
205 | * Handle to the CADET session this port belongs to. | ||
206 | */ | ||
207 | struct GNUNET_CADET_Handle *cadet; | ||
208 | |||
209 | /** | ||
210 | * Callback handler for incoming channels on this port. | ||
211 | */ | ||
212 | GNUNET_CADET_InboundChannelNotificationHandler *handler; | ||
213 | |||
214 | /** | ||
215 | * Closure for @a handler. | ||
216 | */ | ||
217 | void *cls; | ||
218 | |||
219 | /** | ||
220 | * Handler for incoming channels on this port | ||
221 | */ | ||
222 | GNUNET_CADET_ConnectEventHandler connects; | ||
223 | |||
224 | /** | ||
225 | * Closure for @ref connects | ||
226 | */ | ||
227 | void *connects_cls; | ||
228 | |||
229 | /** | ||
230 | * Window size change handler. | ||
231 | */ | ||
232 | GNUNET_CADET_WindowSizeEventHandler window_changes; | ||
233 | |||
234 | /** | ||
235 | * Handler called when an incoming channel is destroyed. | ||
236 | */ | ||
237 | GNUNET_CADET_DisconnectEventHandler disconnects; | ||
238 | |||
239 | /** | ||
240 | * Payload handlers for incoming channels. | ||
241 | */ | ||
242 | struct GNUNET_MQ_MessageHandler *handlers; | ||
243 | }; | ||
244 | |||
245 | |||
246 | /** | ||
247 | * Find the Port struct for a hash. | ||
248 | * | ||
249 | * @param h CADET handle. | ||
250 | * @param hash HashCode for the port number. | ||
251 | * @return The port handle if known, NULL otherwise. | ||
252 | */ | ||
253 | static struct GNUNET_CADET_Port * | ||
254 | find_port (const struct GNUNET_CADET_Handle *h, | ||
255 | const struct GNUNET_HashCode *hash) | ||
256 | { | ||
257 | return GNUNET_CONTAINER_multihashmap_get (h->ports, | ||
258 | hash); | ||
259 | } | ||
260 | |||
261 | |||
262 | /** | ||
263 | * Get the channel handler for the channel specified by id from the given handle | ||
264 | * | ||
265 | * @param h Cadet handle | ||
266 | * @param ccn ID of the wanted channel | ||
267 | * @return handle to the required channel or NULL if not found | ||
268 | */ | ||
269 | static struct GNUNET_CADET_Channel * | ||
270 | find_channel (struct GNUNET_CADET_Handle *h, | ||
271 | struct GNUNET_CADET_ClientChannelNumber ccn) | ||
272 | { | ||
273 | return GNUNET_CONTAINER_multihashmap32_get (h->channels, | ||
274 | ntohl (ccn.channel_of_client)); | ||
275 | } | ||
276 | |||
277 | |||
278 | /** | ||
279 | * Create a new channel and insert it in the channel list of the cadet handle | ||
280 | * | ||
281 | * @param h Cadet handle | ||
282 | * @param ccnp pointer to desired ccn of the channel, NULL to assign one automatically. | ||
283 | * @return Handle to the created channel. | ||
284 | */ | ||
285 | static struct GNUNET_CADET_Channel * | ||
286 | create_channel (struct GNUNET_CADET_Handle *h, | ||
287 | const struct GNUNET_CADET_ClientChannelNumber *ccnp) | ||
288 | { | ||
289 | struct GNUNET_CADET_Channel *ch; | ||
290 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
291 | |||
292 | ch = GNUNET_new (struct GNUNET_CADET_Channel); | ||
293 | ch->cadet = h; | ||
294 | if (NULL == ccnp) | ||
295 | { | ||
296 | while (NULL != | ||
297 | find_channel (h, | ||
298 | h->next_ccn)) | ||
299 | h->next_ccn.channel_of_client | ||
300 | = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI | (1 + ntohl (h->next_ccn.channel_of_client))); | ||
301 | ccn = h->next_ccn; | ||
302 | } | ||
303 | else | ||
304 | { | ||
305 | ccn = *ccnp; | ||
306 | } | ||
307 | ch->ccn = ccn; | ||
308 | GNUNET_assert (GNUNET_OK == | ||
309 | GNUNET_CONTAINER_multihashmap32_put (h->channels, | ||
310 | ntohl (ch->ccn.channel_of_client), | ||
311 | ch, | ||
312 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
313 | return ch; | ||
314 | } | ||
315 | |||
316 | |||
317 | /** | ||
318 | * Destroy the specified channel. | ||
319 | * - Destroys all peers, calling the disconnect callback on each if needed | ||
320 | * - Cancels all outgoing traffic for that channel, calling respective notifys | ||
321 | * - Calls cleaner if channel was inbound | ||
322 | * - Frees all memory used | ||
323 | * | ||
324 | * @param ch Pointer to the channel. | ||
325 | * @param call_cleaner Whether to call the cleaner handler. | ||
326 | */ | ||
327 | static void | ||
328 | destroy_channel (struct GNUNET_CADET_Channel *ch) | ||
329 | { | ||
330 | struct GNUNET_CADET_Handle *h = ch->cadet; | ||
331 | |||
332 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
333 | "Destroying channel %X of %p\n", | ||
334 | ch->ccn, | ||
335 | h); | ||
336 | GNUNET_assert (GNUNET_YES == | ||
337 | GNUNET_CONTAINER_multihashmap32_remove (h->channels, | ||
338 | ntohl (ch->ccn.channel_of_client), | ||
339 | ch)); | ||
340 | if (NULL != ch->mq_cont) | ||
341 | { | ||
342 | GNUNET_SCHEDULER_cancel (ch->mq_cont); | ||
343 | ch->mq_cont = NULL; | ||
344 | } | ||
345 | /* signal channel destruction */ | ||
346 | if (NULL != ch->disconnects) | ||
347 | ch->disconnects (ch->ctx, | ||
348 | ch); | ||
349 | if (NULL != ch->pending_env) | ||
350 | GNUNET_MQ_discard (ch->pending_env); | ||
351 | GNUNET_MQ_destroy (ch->mq); | ||
352 | GNUNET_free (ch); | ||
353 | } | ||
354 | |||
355 | |||
356 | /** | ||
357 | * Reconnect to the service, retransmit all infomation to try to restore the | ||
358 | * original state. | ||
359 | * | ||
360 | * @param h handle to the cadet | ||
361 | */ | ||
362 | static void | ||
363 | reconnect (struct GNUNET_CADET_Handle *h); | ||
364 | |||
365 | |||
366 | /** | ||
367 | * Reconnect callback: tries to reconnect again after a failer previous | ||
368 | * reconnecttion | ||
369 | * | ||
370 | * @param cls closure (cadet handle) | ||
371 | */ | ||
372 | static void | ||
373 | reconnect_cbk (void *cls) | ||
374 | { | ||
375 | struct GNUNET_CADET_Handle *h = cls; | ||
376 | |||
377 | h->reconnect_task = NULL; | ||
378 | reconnect (h); | ||
379 | } | ||
380 | |||
381 | |||
382 | /** | ||
383 | * Function called during #reconnect() to destroy | ||
384 | * all channels that are still open. | ||
385 | * | ||
386 | * @param cls the `struct GNUNET_CADET_Handle` | ||
387 | * @param cid chanenl ID | ||
388 | * @param value a `struct GNUNET_CADET_Channel` to destroy | ||
389 | * @return #GNUNET_OK (continue to iterate) | ||
390 | */ | ||
391 | static int | ||
392 | destroy_channel_on_reconnect_cb (void *cls, | ||
393 | uint32_t cid, | ||
394 | void *value) | ||
395 | { | ||
396 | /* struct GNUNET_CADET_Handle *handle = cls; */ | ||
397 | struct GNUNET_CADET_Channel *ch = value; | ||
398 | |||
399 | destroy_channel (ch); | ||
400 | return GNUNET_OK; | ||
401 | } | ||
402 | |||
403 | |||
404 | /** | ||
405 | * Reconnect to the service, retransmit all infomation to try to restore the | ||
406 | * original state. | ||
407 | * | ||
408 | * @param h handle to the cadet | ||
409 | * | ||
410 | * @return #GNUNET_YES in case of sucess, #GNUNET_NO otherwise (service down...) | ||
411 | */ | ||
412 | static void | ||
413 | schedule_reconnect (struct GNUNET_CADET_Handle *h) | ||
414 | { | ||
415 | if (NULL != h->reconnect_task) | ||
416 | return; | ||
417 | GNUNET_CONTAINER_multihashmap32_iterate (h->channels, | ||
418 | &destroy_channel_on_reconnect_cb, | ||
419 | h); | ||
420 | h->reconnect_task | ||
421 | = GNUNET_SCHEDULER_add_delayed (h->reconnect_time, | ||
422 | &reconnect_cbk, | ||
423 | h); | ||
424 | h->reconnect_time | ||
425 | = GNUNET_TIME_STD_BACKOFF (h->reconnect_time); | ||
426 | } | ||
427 | |||
428 | |||
429 | /** | ||
430 | * Notify the application about a change in the window size (if needed). | ||
431 | * | ||
432 | * @param ch Channel to notify about. | ||
433 | */ | ||
434 | static void | ||
435 | notify_window_size (struct GNUNET_CADET_Channel *ch) | ||
436 | { | ||
437 | if (NULL != ch->window_changes) | ||
438 | ch->window_changes (ch->ctx, | ||
439 | ch, /* FIXME: remove 'ch'? */ | ||
440 | ch->allow_send); | ||
441 | } | ||
442 | |||
443 | |||
444 | /** | ||
445 | * Transmit the next message from our queue. | ||
446 | * | ||
447 | * @param cls Closure (channel whose mq to activate). | ||
448 | */ | ||
449 | static void | ||
450 | cadet_mq_send_now (void *cls) | ||
451 | { | ||
452 | struct GNUNET_CADET_Channel *ch = cls; | ||
453 | struct GNUNET_MQ_Envelope *env = ch->pending_env; | ||
454 | |||
455 | ch->mq_cont = NULL; | ||
456 | if (0 == ch->allow_send) | ||
457 | { | ||
458 | /* how did we get here? */ | ||
459 | GNUNET_break (0); | ||
460 | return; | ||
461 | } | ||
462 | if (NULL == env) | ||
463 | { | ||
464 | /* how did we get here? */ | ||
465 | GNUNET_break (0); | ||
466 | return; | ||
467 | } | ||
468 | ch->allow_send--; | ||
469 | ch->pending_env = NULL; | ||
470 | GNUNET_MQ_send (ch->cadet->mq, | ||
471 | env); | ||
472 | GNUNET_MQ_impl_send_continue (ch->mq); | ||
473 | } | ||
474 | |||
475 | |||
476 | /** | ||
477 | * Implement sending functionality of a message queue for | ||
478 | * us sending messages to a peer. | ||
479 | * | ||
480 | * Encapsulates the payload message in a #GNUNET_CADET_LocalData message | ||
481 | * in order to label the message with the channel ID and send the | ||
482 | * encapsulated message to the service. | ||
483 | * | ||
484 | * @param mq the message queue | ||
485 | * @param msg the message to send | ||
486 | * @param impl_state state of the implementation | ||
487 | */ | ||
488 | static void | ||
489 | cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq, | ||
490 | const struct GNUNET_MessageHeader *msg, | ||
491 | void *impl_state) | ||
492 | { | ||
493 | struct GNUNET_CADET_Channel *ch = impl_state; | ||
494 | struct GNUNET_CADET_Handle *h = ch->cadet; | ||
495 | uint16_t msize; | ||
496 | struct GNUNET_MQ_Envelope *env; | ||
497 | struct GNUNET_CADET_LocalData *cadet_msg; | ||
498 | |||
499 | if (NULL == h->mq) | ||
500 | { | ||
501 | /* We're currently reconnecting, pretend this worked */ | ||
502 | GNUNET_MQ_impl_send_continue (mq); | ||
503 | return; | ||
504 | } | ||
505 | |||
506 | /* check message size for sanity */ | ||
507 | msize = ntohs (msg->size); | ||
508 | if (msize > GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE) | ||
509 | { | ||
510 | GNUNET_break (0); | ||
511 | GNUNET_MQ_impl_send_continue (mq); | ||
512 | return; | ||
513 | } | ||
514 | env = GNUNET_MQ_msg_nested_mh (cadet_msg, | ||
515 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, | ||
516 | msg); | ||
517 | cadet_msg->ccn = ch->ccn; | ||
518 | GNUNET_assert (NULL == ch->pending_env); | ||
519 | ch->pending_env = env; | ||
520 | if (0 < ch->allow_send) | ||
521 | ch->mq_cont | ||
522 | = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now, | ||
523 | ch); | ||
524 | } | ||
525 | |||
526 | |||
527 | /** | ||
528 | * Handle destruction of a message queue. Implementations must not | ||
529 | * free @a mq, but should take care of @a impl_state. | ||
530 | * | ||
531 | * @param mq the message queue to destroy | ||
532 | * @param impl_state state of the implementation | ||
533 | */ | ||
534 | static void | ||
535 | cadet_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, | ||
536 | void *impl_state) | ||
537 | { | ||
538 | struct GNUNET_CADET_Channel *ch = impl_state; | ||
539 | |||
540 | GNUNET_assert (mq == ch->mq); | ||
541 | ch->mq = NULL; | ||
542 | } | ||
543 | |||
544 | |||
545 | /** | ||
546 | * We had an error processing a message we forwarded from a peer to | ||
547 | * the CADET service. We should just complain about it but otherwise | ||
548 | * continue processing. | ||
549 | * | ||
550 | * @param cls closure with our `struct GNUNET_CADET_Channel` | ||
551 | * @param error error code | ||
552 | */ | ||
553 | static void | ||
554 | cadet_mq_error_handler (void *cls, | ||
555 | enum GNUNET_MQ_Error error) | ||
556 | { | ||
557 | struct GNUNET_CADET_Channel *ch = cls; | ||
558 | |||
559 | GNUNET_break (0); | ||
560 | if (GNUNET_MQ_ERROR_NO_MATCH == error) | ||
561 | { | ||
562 | /* Got a message we did not understand, still try to continue! */ | ||
563 | GNUNET_CADET_receive_done (ch); | ||
564 | } | ||
565 | else | ||
566 | { | ||
567 | schedule_reconnect (ch->cadet); | ||
568 | } | ||
569 | } | ||
570 | |||
571 | |||
572 | /** | ||
573 | * Implementation function that cancels the currently sent message. | ||
574 | * Should basically undo whatever #mq_send_impl() did. | ||
575 | * | ||
576 | * @param mq message queue | ||
577 | * @param impl_state state specific to the implementation | ||
578 | */ | ||
579 | static void | ||
580 | cadet_mq_cancel_impl (struct GNUNET_MQ_Handle *mq, | ||
581 | void *impl_state) | ||
582 | { | ||
583 | struct GNUNET_CADET_Channel *ch = impl_state; | ||
584 | |||
585 | GNUNET_assert (NULL != ch->pending_env); | ||
586 | GNUNET_MQ_discard (ch->pending_env); | ||
587 | ch->pending_env = NULL; | ||
588 | if (NULL != ch->mq_cont) | ||
589 | { | ||
590 | GNUNET_SCHEDULER_cancel (ch->mq_cont); | ||
591 | ch->mq_cont = NULL; | ||
592 | } | ||
593 | } | ||
594 | |||
595 | |||
596 | /** | ||
597 | * Process the new channel notification and add it to the channels in the handle | ||
598 | * | ||
599 | * @param h The cadet handle | ||
600 | * @param msg A message with the details of the new incoming channel | ||
601 | */ | ||
602 | static void | ||
603 | handle_channel_created (void *cls, | ||
604 | const struct GNUNET_CADET_LocalChannelCreateMessage *msg) | ||
605 | { | ||
606 | struct GNUNET_CADET_Handle *h = cls; | ||
607 | struct GNUNET_CADET_Channel *ch; | ||
608 | struct GNUNET_CADET_Port *port; | ||
609 | const struct GNUNET_HashCode *port_number; | ||
610 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
611 | |||
612 | ccn = msg->ccn; | ||
613 | port_number = &msg->port; | ||
614 | if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
615 | { | ||
616 | GNUNET_break (0); | ||
617 | return; | ||
618 | } | ||
619 | port = find_port (h, | ||
620 | port_number); | ||
621 | if (NULL == port) | ||
622 | { | ||
623 | /* We could have closed the port but the service didn't know about it yet | ||
624 | * This is not an error. | ||
625 | */ | ||
626 | struct GNUNET_CADET_LocalChannelDestroyMessage *d_msg; | ||
627 | struct GNUNET_MQ_Envelope *env; | ||
628 | |||
629 | GNUNET_break (0); | ||
630 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
631 | "No handler for incoming channel %X (on port %s, recently closed?)\n", | ||
632 | ntohl (ccn.channel_of_client), | ||
633 | GNUNET_h2s (port_number)); | ||
634 | env = GNUNET_MQ_msg (d_msg, | ||
635 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); | ||
636 | d_msg->ccn = msg->ccn; | ||
637 | GNUNET_MQ_send (h->mq, | ||
638 | env); | ||
639 | return; | ||
640 | } | ||
641 | |||
642 | ch = create_channel (h, | ||
643 | &ccn); | ||
644 | ch->peer = msg->peer; | ||
645 | ch->cadet = h; | ||
646 | ch->incoming_port = port; | ||
647 | ch->options = ntohl (msg->opt); | ||
648 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
649 | "Creating incoming channel %X [%s] %p\n", | ||
650 | ntohl (ccn.channel_of_client), | ||
651 | GNUNET_h2s (port_number), | ||
652 | ch); | ||
653 | |||
654 | GNUNET_assert (NULL != port->connects); | ||
655 | ch->window_changes = port->window_changes; | ||
656 | ch->disconnects = port->disconnects; | ||
657 | ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl, | ||
658 | &cadet_mq_destroy_impl, | ||
659 | &cadet_mq_cancel_impl, | ||
660 | ch, | ||
661 | port->handlers, | ||
662 | &cadet_mq_error_handler, | ||
663 | ch); | ||
664 | ch->ctx = port->connects (port->cls, | ||
665 | ch, | ||
666 | &msg->peer); | ||
667 | GNUNET_MQ_set_handlers_closure (ch->mq, | ||
668 | ch->ctx); | ||
669 | } | ||
670 | |||
671 | |||
672 | /** | ||
673 | * Process the channel destroy notification and free associated resources | ||
674 | * | ||
675 | * @param h The cadet handle | ||
676 | * @param msg A message with the details of the channel being destroyed | ||
677 | */ | ||
678 | static void | ||
679 | handle_channel_destroy (void *cls, | ||
680 | const struct GNUNET_CADET_LocalChannelDestroyMessage *msg) | ||
681 | { | ||
682 | struct GNUNET_CADET_Handle *h = cls; | ||
683 | struct GNUNET_CADET_Channel *ch; | ||
684 | |||
685 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
686 | "Received channel destroy for channel %X from CADET service\n", | ||
687 | ntohl (msg->ccn.channel_of_client)); | ||
688 | ch = find_channel (h, | ||
689 | msg->ccn); | ||
690 | if (NULL == ch) | ||
691 | { | ||
692 | GNUNET_break (0); | ||
693 | return; | ||
694 | } | ||
695 | destroy_channel (ch); | ||
696 | } | ||
697 | |||
698 | |||
699 | /** | ||
700 | * Check that message received from CADET service is well-formed. | ||
701 | * | ||
702 | * @param cls the `struct GNUNET_CADET_Handle` | ||
703 | * @param message the message we got | ||
704 | * @return #GNUNET_OK if the message is well-formed, | ||
705 | * #GNUNET_SYSERR otherwise | ||
706 | */ | ||
707 | static int | ||
708 | check_local_data (void *cls, | ||
709 | const struct GNUNET_CADET_LocalData *message) | ||
710 | { | ||
711 | struct GNUNET_CADET_Handle *h = cls; | ||
712 | struct GNUNET_CADET_Channel *ch; | ||
713 | uint16_t size; | ||
714 | |||
715 | size = ntohs (message->header.size); | ||
716 | if (sizeof (*message) + sizeof (struct GNUNET_MessageHeader) > size) | ||
717 | { | ||
718 | GNUNET_break (0); | ||
719 | return GNUNET_SYSERR; | ||
720 | } | ||
721 | |||
722 | ch = find_channel (h, | ||
723 | message->ccn); | ||
724 | if (NULL == ch) | ||
725 | { | ||
726 | GNUNET_break (0); | ||
727 | return GNUNET_SYSERR; | ||
728 | } | ||
729 | |||
730 | return GNUNET_OK; | ||
731 | } | ||
732 | |||
733 | |||
734 | /** | ||
735 | * Process the incoming data packets, call appropriate handlers. | ||
736 | * | ||
737 | * @param h The cadet handle | ||
738 | * @param message A message encapsulating the data | ||
739 | */ | ||
740 | static void | ||
741 | handle_local_data (void *cls, | ||
742 | const struct GNUNET_CADET_LocalData *message) | ||
743 | { | ||
744 | struct GNUNET_CADET_Handle *h = cls; | ||
745 | const struct GNUNET_MessageHeader *payload; | ||
746 | struct GNUNET_CADET_Channel *ch; | ||
747 | uint16_t type; | ||
748 | int fwd; | ||
749 | |||
750 | ch = find_channel (h, | ||
751 | message->ccn); | ||
752 | if (NULL == ch) | ||
753 | { | ||
754 | GNUNET_break (0); | ||
755 | reconnect (h); | ||
756 | return; | ||
757 | } | ||
758 | |||
759 | payload = (const struct GNUNET_MessageHeader *) &message[1]; | ||
760 | type = ntohs (payload->type); | ||
761 | fwd = ntohl (ch->ccn.channel_of_client) <= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; | ||
762 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
763 | "Got a %s data on channel %s [%X] of type %u\n", | ||
764 | fwd ? "FWD" : "BWD", | ||
765 | GNUNET_i2s (&ch->peer), | ||
766 | ntohl (message->ccn.channel_of_client), | ||
767 | type); | ||
768 | GNUNET_MQ_inject_message (ch->mq, | ||
769 | payload); | ||
770 | } | ||
771 | |||
772 | |||
773 | /** | ||
774 | * Process a local ACK message, enabling the client to send | ||
775 | * more data to the service. | ||
776 | * | ||
777 | * @param h Cadet handle. | ||
778 | * @param message Message itself. | ||
779 | */ | ||
780 | static void | ||
781 | handle_local_ack (void *cls, | ||
782 | const struct GNUNET_CADET_LocalAck *message) | ||
783 | { | ||
784 | struct GNUNET_CADET_Handle *h = cls; | ||
785 | struct GNUNET_CADET_Channel *ch; | ||
786 | |||
787 | ch = find_channel (h, | ||
788 | message->ccn); | ||
789 | if (NULL == ch) | ||
790 | { | ||
791 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
792 | "ACK on unknown channel %X\n", | ||
793 | ntohl (message->ccn.channel_of_client)); | ||
794 | return; | ||
795 | } | ||
796 | ch->allow_send++; | ||
797 | if (NULL == ch->pending_env) | ||
798 | { | ||
799 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
800 | "Got an ACK on mq channel %X, allow send now %u!\n", | ||
801 | ntohl (ch->ccn.channel_of_client), | ||
802 | ch->allow_send); | ||
803 | notify_window_size (ch); | ||
804 | return; | ||
805 | } | ||
806 | if (NULL != ch->mq_cont) | ||
807 | return; /* already working on it! */ | ||
808 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
809 | "Got an ACK on mq channel %X, sending pending message!\n", | ||
810 | ntohl (ch->ccn.channel_of_client)); | ||
811 | ch->mq_cont | ||
812 | = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now, | ||
813 | ch); | ||
814 | } | ||
815 | |||
816 | |||
817 | /** | ||
818 | * Generic error handler, called with the appropriate error code and | ||
819 | * the same closure specified at the creation of the message queue. | ||
820 | * Not every message queue implementation supports an error handler. | ||
821 | * | ||
822 | * @param cls closure, a `struct GNUNET_CORE_Handle *` | ||
823 | * @param error error code | ||
824 | */ | ||
825 | static void | ||
826 | handle_mq_error (void *cls, | ||
827 | enum GNUNET_MQ_Error error) | ||
828 | { | ||
829 | struct GNUNET_CADET_Handle *h = cls; | ||
830 | |||
831 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
832 | "MQ ERROR: %u\n", | ||
833 | error); | ||
834 | GNUNET_MQ_destroy (h->mq); | ||
835 | h->mq = NULL; | ||
836 | reconnect (h); | ||
837 | } | ||
838 | |||
839 | |||
840 | /** | ||
841 | * Process a local reply about info on all tunnels, pass info to the user. | ||
842 | * | ||
843 | * @param cls Closure (Cadet handle). | ||
844 | * @param msg Message itself. | ||
845 | */ | ||
846 | static void | ||
847 | handle_get_peers (void *cls, | ||
848 | const struct GNUNET_CADET_LocalInfoPeer *msg) | ||
849 | { | ||
850 | struct GNUNET_CADET_Handle *h = cls; | ||
851 | |||
852 | if (NULL == h->info_cb.peers_cb) | ||
853 | return; | ||
854 | h->info_cb.peers_cb (h->info_cls, | ||
855 | &msg->destination, | ||
856 | (int) ntohs (msg->tunnel), | ||
857 | (unsigned int) ntohs (msg->paths), | ||
858 | 0); | ||
859 | } | ||
860 | |||
861 | |||
862 | /** | ||
863 | * Check that message received from CADET service is well-formed. | ||
864 | * | ||
865 | * @param cls the `struct GNUNET_CADET_Handle` | ||
866 | * @param message the message we got | ||
867 | * @return #GNUNET_OK if the message is well-formed, | ||
868 | * #GNUNET_SYSERR otherwise | ||
869 | */ | ||
870 | static int | ||
871 | check_get_peer (void *cls, | ||
872 | const struct GNUNET_CADET_LocalInfoPeer *message) | ||
873 | { | ||
874 | size_t msize = sizeof (struct GNUNET_CADET_LocalInfoPeer); | ||
875 | const struct GNUNET_PeerIdentity *paths_array; | ||
876 | size_t esize; | ||
877 | unsigned int epaths; | ||
878 | unsigned int paths; | ||
879 | unsigned int peers; | ||
880 | |||
881 | esize = ntohs (message->header.size); | ||
882 | if (esize < msize) | ||
883 | { | ||
884 | GNUNET_break (0); | ||
885 | return GNUNET_SYSERR; | ||
886 | } | ||
887 | if (0 != ((esize - msize) % sizeof (struct GNUNET_PeerIdentity))) | ||
888 | { | ||
889 | GNUNET_break (0); | ||
890 | return GNUNET_SYSERR; | ||
891 | } | ||
892 | peers = (esize - msize) / sizeof (struct GNUNET_PeerIdentity); | ||
893 | epaths = ntohs (message->paths); | ||
894 | paths_array = (const struct GNUNET_PeerIdentity *) &message[1]; | ||
895 | paths = 0; | ||
896 | for (unsigned int i = 0; i < peers; i++) | ||
897 | if (0 == memcmp (&paths_array[i], | ||
898 | &message->destination, | ||
899 | sizeof (struct GNUNET_PeerIdentity))) | ||
900 | paths++; | ||
901 | if (paths != epaths) | ||
902 | { | ||
903 | GNUNET_break (0); | ||
904 | return GNUNET_SYSERR; | ||
905 | } | ||
906 | return GNUNET_OK; | ||
907 | } | ||
908 | |||
909 | |||
910 | /** | ||
911 | * Process a local peer info reply, pass info to the user. | ||
912 | * | ||
913 | * @param cls Closure (Cadet handle). | ||
914 | * @param message Message itself. | ||
915 | */ | ||
916 | static void | ||
917 | handle_get_peer (void *cls, | ||
918 | const struct GNUNET_CADET_LocalInfoPeer *message) | ||
919 | { | ||
920 | struct GNUNET_CADET_Handle *h = cls; | ||
921 | const struct GNUNET_PeerIdentity *paths_array; | ||
922 | unsigned int paths; | ||
923 | unsigned int path_length; | ||
924 | int neighbor; | ||
925 | unsigned int peers; | ||
926 | |||
927 | if (NULL == h->info_cb.peer_cb) | ||
928 | return; | ||
929 | paths = ntohs (message->paths); | ||
930 | paths_array = (const struct GNUNET_PeerIdentity *) &message[1]; | ||
931 | peers = (ntohs (message->header.size) - sizeof (*message)) | ||
932 | / sizeof (struct GNUNET_PeerIdentity); | ||
933 | path_length = 0; | ||
934 | neighbor = GNUNET_NO; | ||
935 | |||
936 | for (unsigned int i = 0; i < peers; i++) | ||
937 | { | ||
938 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
939 | " %s\n", | ||
940 | GNUNET_i2s (&paths_array[i])); | ||
941 | path_length++; | ||
942 | if (0 == memcmp (&paths_array[i], &message->destination, | ||
943 | sizeof (struct GNUNET_PeerIdentity))) | ||
944 | { | ||
945 | if (1 == path_length) | ||
946 | neighbor = GNUNET_YES; | ||
947 | path_length = 0; | ||
948 | } | ||
949 | } | ||
950 | |||
951 | /* Call Callback with tunnel info. */ | ||
952 | paths_array = (const struct GNUNET_PeerIdentity *) &message[1]; | ||
953 | h->info_cb.peer_cb (h->info_cls, | ||
954 | &message->destination, | ||
955 | (int) ntohs (message->tunnel), | ||
956 | neighbor, | ||
957 | paths, | ||
958 | paths_array); | ||
959 | } | ||
960 | |||
961 | |||
962 | /** | ||
963 | * Process a local reply about info on all tunnels, pass info to the user. | ||
964 | * | ||
965 | * @param cls Closure (Cadet handle). | ||
966 | * @param message Message itself. | ||
967 | */ | ||
968 | static void | ||
969 | handle_get_tunnels (void *cls, | ||
970 | const struct GNUNET_CADET_LocalInfoTunnel *msg) | ||
971 | { | ||
972 | struct GNUNET_CADET_Handle *h = cls; | ||
973 | |||
974 | if (NULL == h->info_cb.tunnels_cb) | ||
975 | return; | ||
976 | h->info_cb.tunnels_cb (h->info_cls, | ||
977 | &msg->destination, | ||
978 | ntohl (msg->channels), | ||
979 | ntohl (msg->connections), | ||
980 | ntohs (msg->estate), | ||
981 | ntohs (msg->cstate)); | ||
982 | |||
983 | } | ||
984 | |||
985 | |||
986 | /** | ||
987 | * Check that message received from CADET service is well-formed. | ||
988 | * | ||
989 | * @param cls the `struct GNUNET_CADET_Handle` | ||
990 | * @param msg the message we got | ||
991 | * @return #GNUNET_OK if the message is well-formed, | ||
992 | * #GNUNET_SYSERR otherwise | ||
993 | */ | ||
994 | static int | ||
995 | check_get_tunnel (void *cls, | ||
996 | const struct GNUNET_CADET_LocalInfoTunnel *msg) | ||
997 | { | ||
998 | unsigned int ch_n; | ||
999 | unsigned int c_n; | ||
1000 | size_t esize; | ||
1001 | size_t msize; | ||
1002 | |||
1003 | /* Verify message sanity */ | ||
1004 | msize = ntohs (msg->header.size); | ||
1005 | esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel); | ||
1006 | if (esize > msize) | ||
1007 | { | ||
1008 | GNUNET_break (0); | ||
1009 | return GNUNET_SYSERR; | ||
1010 | } | ||
1011 | ch_n = ntohl (msg->channels); | ||
1012 | c_n = ntohl (msg->connections); | ||
1013 | esize += ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber); | ||
1014 | esize += c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier); | ||
1015 | if (msize != esize) | ||
1016 | { | ||
1017 | GNUNET_break_op (0); | ||
1018 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1019 | "m:%u, e: %u (%u ch, %u conn)\n", | ||
1020 | (unsigned int) msize, | ||
1021 | (unsigned int) esize, | ||
1022 | ch_n, | ||
1023 | c_n); | ||
1024 | return GNUNET_SYSERR; | ||
1025 | } | ||
1026 | return GNUNET_OK; | ||
1027 | } | ||
1028 | |||
1029 | |||
1030 | /** | ||
1031 | * Process a local tunnel info reply, pass info to the user. | ||
1032 | * | ||
1033 | * @param cls Closure (Cadet handle). | ||
1034 | * @param msg Message itself. | ||
1035 | */ | ||
1036 | static void | ||
1037 | handle_get_tunnel (void *cls, | ||
1038 | const struct GNUNET_CADET_LocalInfoTunnel *msg) | ||
1039 | { | ||
1040 | struct GNUNET_CADET_Handle *h = cls; | ||
1041 | unsigned int ch_n; | ||
1042 | unsigned int c_n; | ||
1043 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *conns; | ||
1044 | const struct GNUNET_CADET_ChannelTunnelNumber *chns; | ||
1045 | |||
1046 | if (NULL == h->info_cb.tunnel_cb) | ||
1047 | return; | ||
1048 | |||
1049 | ch_n = ntohl (msg->channels); | ||
1050 | c_n = ntohl (msg->connections); | ||
1051 | |||
1052 | /* Call Callback with tunnel info. */ | ||
1053 | conns = (const struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1]; | ||
1054 | chns = (const struct GNUNET_CADET_ChannelTunnelNumber *) &conns[c_n]; | ||
1055 | h->info_cb.tunnel_cb (h->info_cls, | ||
1056 | &msg->destination, | ||
1057 | ch_n, | ||
1058 | c_n, | ||
1059 | chns, | ||
1060 | conns, | ||
1061 | ntohs (msg->estate), | ||
1062 | ntohs (msg->cstate)); | ||
1063 | } | ||
1064 | |||
1065 | |||
1066 | /** | ||
1067 | * Reconnect to the service, retransmit all infomation to try to restore the | ||
1068 | * original state. | ||
1069 | * | ||
1070 | * @param h handle to the cadet | ||
1071 | */ | ||
1072 | static void | ||
1073 | reconnect (struct GNUNET_CADET_Handle *h) | ||
1074 | { | ||
1075 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
1076 | GNUNET_MQ_hd_fixed_size (channel_created, | ||
1077 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE, | ||
1078 | struct GNUNET_CADET_LocalChannelCreateMessage, | ||
1079 | h), | ||
1080 | GNUNET_MQ_hd_fixed_size (channel_destroy, | ||
1081 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY, | ||
1082 | struct GNUNET_CADET_LocalChannelDestroyMessage, | ||
1083 | h), | ||
1084 | GNUNET_MQ_hd_var_size (local_data, | ||
1085 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, | ||
1086 | struct GNUNET_CADET_LocalData, | ||
1087 | h), | ||
1088 | GNUNET_MQ_hd_fixed_size (local_ack, | ||
1089 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK, | ||
1090 | struct GNUNET_CADET_LocalAck, | ||
1091 | h), | ||
1092 | GNUNET_MQ_hd_fixed_size (get_peers, | ||
1093 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS, | ||
1094 | struct GNUNET_CADET_LocalInfoPeer, | ||
1095 | h), | ||
1096 | GNUNET_MQ_hd_var_size (get_peer, | ||
1097 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER, | ||
1098 | struct GNUNET_CADET_LocalInfoPeer, | ||
1099 | h), | ||
1100 | GNUNET_MQ_hd_fixed_size (get_tunnels, | ||
1101 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS, | ||
1102 | struct GNUNET_CADET_LocalInfoTunnel, | ||
1103 | h), | ||
1104 | GNUNET_MQ_hd_var_size (get_tunnel, | ||
1105 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL, | ||
1106 | struct GNUNET_CADET_LocalInfoTunnel, | ||
1107 | h), | ||
1108 | GNUNET_MQ_handler_end () | ||
1109 | }; | ||
1110 | |||
1111 | h->mq = GNUNET_CLIENT_connect (h->cfg, | ||
1112 | "cadet", | ||
1113 | handlers, | ||
1114 | &handle_mq_error, | ||
1115 | h); | ||
1116 | if (NULL == h->mq) | ||
1117 | { | ||
1118 | schedule_reconnect (h); | ||
1119 | return; | ||
1120 | } | ||
1121 | h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; | ||
1122 | } | ||
1123 | |||
1124 | |||
1125 | /** | ||
1126 | * Function called during #GNUNET_CADET_disconnect() to destroy | ||
1127 | * all channels that are still open. | ||
1128 | * | ||
1129 | * @param cls the `struct GNUNET_CADET_Handle` | ||
1130 | * @param cid chanenl ID | ||
1131 | * @param value a `struct GNUNET_CADET_Channel` to destroy | ||
1132 | * @return #GNUNET_OK (continue to iterate) | ||
1133 | */ | ||
1134 | static int | ||
1135 | destroy_channel_cb (void *cls, | ||
1136 | uint32_t cid, | ||
1137 | void *value) | ||
1138 | { | ||
1139 | /* struct GNUNET_CADET_Handle *handle = cls; */ | ||
1140 | struct GNUNET_CADET_Channel *ch = value; | ||
1141 | |||
1142 | if (ntohl (ch->ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
1143 | { | ||
1144 | GNUNET_break (0); | ||
1145 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1146 | "channel %X not destroyed\n", | ||
1147 | ntohl (ch->ccn.channel_of_client)); | ||
1148 | } | ||
1149 | destroy_channel (ch); | ||
1150 | return GNUNET_OK; | ||
1151 | } | ||
1152 | |||
1153 | |||
1154 | /** | ||
1155 | * Function called during #GNUNET_CADET_disconnect() to destroy | ||
1156 | * all ports that are still open. | ||
1157 | * | ||
1158 | * @param cls the `struct GNUNET_CADET_Handle` | ||
1159 | * @param id port ID | ||
1160 | * @param value a `struct GNUNET_CADET_Channel` to destroy | ||
1161 | * @return #GNUNET_OK (continue to iterate) | ||
1162 | */ | ||
1163 | static int | ||
1164 | destroy_port_cb (void *cls, | ||
1165 | const struct GNUNET_HashCode *id, | ||
1166 | void *value) | ||
1167 | { | ||
1168 | /* struct GNUNET_CADET_Handle *handle = cls; */ | ||
1169 | struct GNUNET_CADET_Port *port = value; | ||
1170 | |||
1171 | /* This is a warning, the app should have cleanly closed all open ports */ | ||
1172 | GNUNET_break (0); | ||
1173 | GNUNET_CADET_close_port (port); | ||
1174 | return GNUNET_OK; | ||
1175 | } | ||
1176 | |||
1177 | |||
1178 | /** | ||
1179 | * Disconnect from the cadet service. All channels will be destroyed. All channel | ||
1180 | * disconnect callbacks will be called on any still connected peers, notifying | ||
1181 | * about their disconnection. The registered inbound channel cleaner will be | ||
1182 | * called should any inbound channels still exist. | ||
1183 | * | ||
1184 | * @param handle connection to cadet to disconnect | ||
1185 | */ | ||
1186 | void | ||
1187 | GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle) | ||
1188 | { | ||
1189 | GNUNET_CONTAINER_multihashmap_iterate (handle->ports, | ||
1190 | &destroy_port_cb, | ||
1191 | handle); | ||
1192 | GNUNET_CONTAINER_multihashmap_destroy (handle->ports); | ||
1193 | handle->ports = NULL; | ||
1194 | GNUNET_CONTAINER_multihashmap32_iterate (handle->channels, | ||
1195 | &destroy_channel_cb, | ||
1196 | handle); | ||
1197 | GNUNET_CONTAINER_multihashmap32_destroy (handle->channels); | ||
1198 | handle->channels = NULL; | ||
1199 | if (NULL != handle->mq) | ||
1200 | { | ||
1201 | GNUNET_MQ_destroy (handle->mq); | ||
1202 | handle->mq = NULL; | ||
1203 | } | ||
1204 | if (NULL != handle->reconnect_task) | ||
1205 | { | ||
1206 | GNUNET_SCHEDULER_cancel (handle->reconnect_task); | ||
1207 | handle->reconnect_task = NULL; | ||
1208 | } | ||
1209 | GNUNET_free (handle); | ||
1210 | } | ||
1211 | |||
1212 | |||
1213 | /** | ||
1214 | * Close a port opened with @a GNUNET_CADET_open_port(). | ||
1215 | * The @a new_channel callback will no longer be called. | ||
1216 | * | ||
1217 | * @param p Port handle. | ||
1218 | */ | ||
1219 | void | ||
1220 | GNUNET_CADET_close_port (struct GNUNET_CADET_Port *p) | ||
1221 | { | ||
1222 | struct GNUNET_CADET_PortMessage *msg; | ||
1223 | struct GNUNET_MQ_Envelope *env; | ||
1224 | |||
1225 | env = GNUNET_MQ_msg (msg, | ||
1226 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE); | ||
1227 | msg->port = p->id; | ||
1228 | GNUNET_MQ_send (p->cadet->mq, | ||
1229 | env); | ||
1230 | GNUNET_assert (GNUNET_YES == | ||
1231 | GNUNET_CONTAINER_multihashmap_remove (p->cadet->ports, | ||
1232 | &p->id, | ||
1233 | p)); | ||
1234 | GNUNET_free_non_null (p->handlers); | ||
1235 | GNUNET_free (p); | ||
1236 | } | ||
1237 | |||
1238 | |||
1239 | /** | ||
1240 | * Destroy an existing channel. | ||
1241 | * | ||
1242 | * The existing end callback for the channel will be called immediately. | ||
1243 | * Any pending outgoing messages will be sent but no incoming messages will be | ||
1244 | * accepted and no data callbacks will be called. | ||
1245 | * | ||
1246 | * @param channel Channel handle, becomes invalid after this call. | ||
1247 | */ | ||
1248 | void | ||
1249 | GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel) | ||
1250 | { | ||
1251 | struct GNUNET_CADET_Handle *h = channel->cadet; | ||
1252 | struct GNUNET_CADET_LocalChannelDestroyMessage *msg; | ||
1253 | struct GNUNET_MQ_Envelope *env; | ||
1254 | |||
1255 | if (NULL != h->mq) | ||
1256 | { | ||
1257 | env = GNUNET_MQ_msg (msg, | ||
1258 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); | ||
1259 | msg->ccn = channel->ccn; | ||
1260 | GNUNET_MQ_send (h->mq, | ||
1261 | env); | ||
1262 | } | ||
1263 | destroy_channel (channel); | ||
1264 | } | ||
1265 | |||
1266 | |||
1267 | /** | ||
1268 | * Get information about a channel. | ||
1269 | * | ||
1270 | * @param channel Channel handle. | ||
1271 | * @param option Query (GNUNET_CADET_OPTION_*). | ||
1272 | * @param ... dependant on option, currently not used | ||
1273 | * | ||
1274 | * @return Union with an answer to the query. | ||
1275 | */ | ||
1276 | const union GNUNET_CADET_ChannelInfo * | ||
1277 | GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel, | ||
1278 | enum GNUNET_CADET_ChannelOption option, | ||
1279 | ...) | ||
1280 | { | ||
1281 | static int bool_flag; | ||
1282 | |||
1283 | switch (option) | ||
1284 | { | ||
1285 | case GNUNET_CADET_OPTION_NOBUFFER: | ||
1286 | case GNUNET_CADET_OPTION_RELIABLE: | ||
1287 | case GNUNET_CADET_OPTION_OUT_OF_ORDER: | ||
1288 | if (0 != (option & channel->options)) | ||
1289 | bool_flag = GNUNET_YES; | ||
1290 | else | ||
1291 | bool_flag = GNUNET_NO; | ||
1292 | return (const union GNUNET_CADET_ChannelInfo *) &bool_flag; | ||
1293 | break; | ||
1294 | case GNUNET_CADET_OPTION_PEER: | ||
1295 | return (const union GNUNET_CADET_ChannelInfo *) &channel->peer; | ||
1296 | break; | ||
1297 | default: | ||
1298 | GNUNET_break (0); | ||
1299 | return NULL; | ||
1300 | } | ||
1301 | } | ||
1302 | |||
1303 | |||
1304 | /** | ||
1305 | * Send an ack on the channel to confirm the processing of a message. | ||
1306 | * | ||
1307 | * @param ch Channel on which to send the ACK. | ||
1308 | */ | ||
1309 | void | ||
1310 | GNUNET_CADET_receive_done (struct GNUNET_CADET_Channel *channel) | ||
1311 | { | ||
1312 | struct GNUNET_CADET_LocalAck *msg; | ||
1313 | struct GNUNET_MQ_Envelope *env; | ||
1314 | |||
1315 | env = GNUNET_MQ_msg (msg, | ||
1316 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK); | ||
1317 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1318 | "Sending ACK on channel %X\n", | ||
1319 | ntohl (channel->ccn.channel_of_client)); | ||
1320 | msg->ccn = channel->ccn; | ||
1321 | GNUNET_MQ_send (channel->cadet->mq, | ||
1322 | env); | ||
1323 | } | ||
1324 | |||
1325 | |||
1326 | /** | ||
1327 | * Send message of @a type to CADET service of @a h | ||
1328 | * | ||
1329 | * @param h handle to CADET service | ||
1330 | * @param type message type of trivial information request to send | ||
1331 | */ | ||
1332 | static void | ||
1333 | send_info_request (struct GNUNET_CADET_Handle *h, | ||
1334 | uint16_t type) | ||
1335 | { | ||
1336 | struct GNUNET_MessageHeader *msg; | ||
1337 | struct GNUNET_MQ_Envelope *env; | ||
1338 | |||
1339 | env = GNUNET_MQ_msg (msg, | ||
1340 | type); | ||
1341 | GNUNET_MQ_send (h->mq, | ||
1342 | env); | ||
1343 | } | ||
1344 | |||
1345 | |||
1346 | /** | ||
1347 | * Request a debug dump on the service's STDERR. | ||
1348 | * | ||
1349 | * WARNING: unstable API, likely to change in the future! | ||
1350 | * | ||
1351 | * @param h cadet handle | ||
1352 | */ | ||
1353 | void | ||
1354 | GNUNET_CADET_request_dump (struct GNUNET_CADET_Handle *h) | ||
1355 | { | ||
1356 | send_info_request (h, | ||
1357 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP); | ||
1358 | } | ||
1359 | |||
1360 | |||
1361 | /** | ||
1362 | * Request information about peers known to the running cadet service. | ||
1363 | * The callback will be called for every peer known to the service. | ||
1364 | * Only one info request (of any kind) can be active at once. | ||
1365 | * | ||
1366 | * WARNING: unstable API, likely to change in the future! | ||
1367 | * | ||
1368 | * @param h Handle to the cadet peer. | ||
1369 | * @param callback Function to call with the requested data. | ||
1370 | * @param callback_cls Closure for @c callback. | ||
1371 | * @return #GNUNET_OK / #GNUNET_SYSERR | ||
1372 | */ | ||
1373 | int | ||
1374 | GNUNET_CADET_get_peers (struct GNUNET_CADET_Handle *h, | ||
1375 | GNUNET_CADET_PeersCB callback, | ||
1376 | void *callback_cls) | ||
1377 | { | ||
1378 | if (NULL != h->info_cb.peers_cb) | ||
1379 | { | ||
1380 | GNUNET_break (0); | ||
1381 | return GNUNET_SYSERR; | ||
1382 | } | ||
1383 | send_info_request (h, | ||
1384 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | ||
1385 | h->info_cb.peers_cb = callback; | ||
1386 | h->info_cls = callback_cls; | ||
1387 | return GNUNET_OK; | ||
1388 | } | ||
1389 | |||
1390 | |||
1391 | /** | ||
1392 | * Cancel a peer info request. The callback will not be called (anymore). | ||
1393 | * | ||
1394 | * WARNING: unstable API, likely to change in the future! | ||
1395 | * | ||
1396 | * @param h Cadet handle. | ||
1397 | * @return Closure given to GNUNET_CADET_get_peers(). | ||
1398 | */ | ||
1399 | void * | ||
1400 | GNUNET_CADET_get_peers_cancel (struct GNUNET_CADET_Handle *h) | ||
1401 | { | ||
1402 | void *cls = h->info_cls; | ||
1403 | |||
1404 | h->info_cb.peers_cb = NULL; | ||
1405 | h->info_cls = NULL; | ||
1406 | return cls; | ||
1407 | } | ||
1408 | |||
1409 | |||
1410 | /** | ||
1411 | * Request information about a peer known to the running cadet peer. | ||
1412 | * The callback will be called for the tunnel once. | ||
1413 | * Only one info request (of any kind) can be active at once. | ||
1414 | * | ||
1415 | * WARNING: unstable API, likely to change in the future! | ||
1416 | * | ||
1417 | * @param h Handle to the cadet peer. | ||
1418 | * @param id Peer whose tunnel to examine. | ||
1419 | * @param callback Function to call with the requested data. | ||
1420 | * @param callback_cls Closure for @c callback. | ||
1421 | * @return #GNUNET_OK / #GNUNET_SYSERR | ||
1422 | */ | ||
1423 | int | ||
1424 | GNUNET_CADET_get_peer (struct GNUNET_CADET_Handle *h, | ||
1425 | const struct GNUNET_PeerIdentity *id, | ||
1426 | GNUNET_CADET_PeerCB callback, | ||
1427 | void *callback_cls) | ||
1428 | { | ||
1429 | struct GNUNET_CADET_LocalInfo *msg; | ||
1430 | struct GNUNET_MQ_Envelope *env; | ||
1431 | |||
1432 | if (NULL != h->info_cb.peer_cb) | ||
1433 | { | ||
1434 | GNUNET_break (0); | ||
1435 | return GNUNET_SYSERR; | ||
1436 | } | ||
1437 | env = GNUNET_MQ_msg (msg, | ||
1438 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER); | ||
1439 | msg->peer = *id; | ||
1440 | GNUNET_MQ_send (h->mq, | ||
1441 | env); | ||
1442 | h->info_cb.peer_cb = callback; | ||
1443 | h->info_cls = callback_cls; | ||
1444 | return GNUNET_OK; | ||
1445 | } | ||
1446 | |||
1447 | |||
1448 | /** | ||
1449 | * Request information about tunnels of the running cadet peer. | ||
1450 | * The callback will be called for every tunnel of the service. | ||
1451 | * Only one info request (of any kind) can be active at once. | ||
1452 | * | ||
1453 | * WARNING: unstable API, likely to change in the future! | ||
1454 | * | ||
1455 | * @param h Handle to the cadet peer. | ||
1456 | * @param callback Function to call with the requested data. | ||
1457 | * @param callback_cls Closure for @c callback. | ||
1458 | * @return #GNUNET_OK / #GNUNET_SYSERR | ||
1459 | */ | ||
1460 | int | ||
1461 | GNUNET_CADET_get_tunnels (struct GNUNET_CADET_Handle *h, | ||
1462 | GNUNET_CADET_TunnelsCB callback, | ||
1463 | void *callback_cls) | ||
1464 | { | ||
1465 | if (NULL != h->info_cb.tunnels_cb) | ||
1466 | { | ||
1467 | GNUNET_break (0); | ||
1468 | return GNUNET_SYSERR; | ||
1469 | } | ||
1470 | send_info_request (h, | ||
1471 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | ||
1472 | h->info_cb.tunnels_cb = callback; | ||
1473 | h->info_cls = callback_cls; | ||
1474 | return GNUNET_OK; | ||
1475 | } | ||
1476 | |||
1477 | |||
1478 | /** | ||
1479 | * Cancel a monitor request. The monitor callback will not be called. | ||
1480 | * | ||
1481 | * @param h Cadet handle. | ||
1482 | * @return Closure given to GNUNET_CADET_get_tunnels(). | ||
1483 | */ | ||
1484 | void * | ||
1485 | GNUNET_CADET_get_tunnels_cancel (struct GNUNET_CADET_Handle *h) | ||
1486 | { | ||
1487 | void *cls = h->info_cls; | ||
1488 | |||
1489 | h->info_cb.tunnels_cb = NULL; | ||
1490 | h->info_cls = NULL; | ||
1491 | return cls; | ||
1492 | } | ||
1493 | |||
1494 | |||
1495 | /** | ||
1496 | * Request information about a tunnel of the running cadet peer. | ||
1497 | * The callback will be called for the tunnel once. | ||
1498 | * Only one info request (of any kind) can be active at once. | ||
1499 | * | ||
1500 | * WARNING: unstable API, likely to change in the future! | ||
1501 | * | ||
1502 | * @param h Handle to the cadet peer. | ||
1503 | * @param id Peer whose tunnel to examine. | ||
1504 | * @param callback Function to call with the requested data. | ||
1505 | * @param callback_cls Closure for @c callback. | ||
1506 | * @return #GNUNET_OK / #GNUNET_SYSERR | ||
1507 | */ | ||
1508 | int | ||
1509 | GNUNET_CADET_get_tunnel (struct GNUNET_CADET_Handle *h, | ||
1510 | const struct GNUNET_PeerIdentity *id, | ||
1511 | GNUNET_CADET_TunnelCB callback, | ||
1512 | void *callback_cls) | ||
1513 | { | ||
1514 | struct GNUNET_CADET_LocalInfo *msg; | ||
1515 | struct GNUNET_MQ_Envelope *env; | ||
1516 | |||
1517 | if (NULL != h->info_cb.tunnel_cb) | ||
1518 | { | ||
1519 | GNUNET_break (0); | ||
1520 | return GNUNET_SYSERR; | ||
1521 | } | ||
1522 | env = GNUNET_MQ_msg (msg, | ||
1523 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); | ||
1524 | msg->peer = *id; | ||
1525 | GNUNET_MQ_send (h->mq, | ||
1526 | env); | ||
1527 | h->info_cb.tunnel_cb = callback; | ||
1528 | h->info_cls = callback_cls; | ||
1529 | return GNUNET_OK; | ||
1530 | } | ||
1531 | |||
1532 | |||
1533 | /** | ||
1534 | * Transitional function to convert an unsigned int port to a hash value. | ||
1535 | * WARNING: local static value returned, NOT reentrant! | ||
1536 | * WARNING: do not use this function for new code! | ||
1537 | * | ||
1538 | * @param port Numerical port (unsigned int format). | ||
1539 | * | ||
1540 | * @return A GNUNET_HashCode usable for the new CADET API. | ||
1541 | */ | ||
1542 | const struct GNUNET_HashCode * | ||
1543 | GC_u2h (uint32_t port) | ||
1544 | { | ||
1545 | static struct GNUNET_HashCode hash; | ||
1546 | |||
1547 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1548 | "This is a transitional function, use proper crypto hashes as CADET ports\n"); | ||
1549 | GNUNET_CRYPTO_hash (&port, | ||
1550 | sizeof (port), | ||
1551 | &hash); | ||
1552 | return &hash; | ||
1553 | } | ||
1554 | |||
1555 | |||
1556 | /** | ||
1557 | * Connect to the MQ-based cadet service. | ||
1558 | * | ||
1559 | * @param cfg Configuration to use. | ||
1560 | * | ||
1561 | * @return Handle to the cadet service NULL on error. | ||
1562 | */ | ||
1563 | struct GNUNET_CADET_Handle * | ||
1564 | GNUNET_CADET_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
1565 | { | ||
1566 | struct GNUNET_CADET_Handle *h; | ||
1567 | |||
1568 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1569 | "GNUNET_CADET_connecT()\n"); | ||
1570 | h = GNUNET_new (struct GNUNET_CADET_Handle); | ||
1571 | h->cfg = cfg; | ||
1572 | h->ports = GNUNET_CONTAINER_multihashmap_create (4, | ||
1573 | GNUNET_YES); | ||
1574 | h->channels = GNUNET_CONTAINER_multihashmap32_create (4); | ||
1575 | reconnect (h); | ||
1576 | if (NULL == h->mq) | ||
1577 | { | ||
1578 | GNUNET_break (0); | ||
1579 | GNUNET_CADET_disconnect (h); | ||
1580 | return NULL; | ||
1581 | } | ||
1582 | h->next_ccn.channel_of_client = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
1583 | h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; | ||
1584 | h->reconnect_task = NULL; | ||
1585 | |||
1586 | return h; | ||
1587 | } | ||
1588 | |||
1589 | |||
1590 | /** | ||
1591 | * Open a port to receive incomming MQ-based channels. | ||
1592 | * | ||
1593 | * @param h CADET handle. | ||
1594 | * @param port Hash identifying the port. | ||
1595 | * @param connects Function called when an incoming channel is connected. | ||
1596 | * @param connects_cls Closure for the @a connects handler. | ||
1597 | * @param window_changes Function called when the transmit window size changes. | ||
1598 | * @param disconnects Function called when a channel is disconnected. | ||
1599 | * @param handlers Callbacks for messages we care about, NULL-terminated. | ||
1600 | * @return Port handle. | ||
1601 | */ | ||
1602 | struct GNUNET_CADET_Port * | ||
1603 | GNUNET_CADET_open_porT (struct GNUNET_CADET_Handle *h, | ||
1604 | const struct GNUNET_HashCode *port, | ||
1605 | GNUNET_CADET_ConnectEventHandler connects, | ||
1606 | void * connects_cls, | ||
1607 | GNUNET_CADET_WindowSizeEventHandler window_changes, | ||
1608 | GNUNET_CADET_DisconnectEventHandler disconnects, | ||
1609 | const struct GNUNET_MQ_MessageHandler *handlers) | ||
1610 | { | ||
1611 | struct GNUNET_CADET_PortMessage *msg; | ||
1612 | struct GNUNET_MQ_Envelope *env; | ||
1613 | struct GNUNET_CADET_Port *p; | ||
1614 | |||
1615 | GNUNET_assert (NULL != connects); | ||
1616 | GNUNET_assert (NULL != disconnects); | ||
1617 | |||
1618 | p = GNUNET_new (struct GNUNET_CADET_Port); | ||
1619 | p->cadet = h; | ||
1620 | p->id = *port; | ||
1621 | p->connects = connects; | ||
1622 | p->cls = connects_cls; | ||
1623 | p->window_changes = window_changes; | ||
1624 | p->disconnects = disconnects; | ||
1625 | p->handlers = GNUNET_MQ_copy_handlers (handlers); | ||
1626 | |||
1627 | GNUNET_assert (GNUNET_OK == | ||
1628 | GNUNET_CONTAINER_multihashmap_put (h->ports, | ||
1629 | &p->id, | ||
1630 | p, | ||
1631 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1632 | |||
1633 | env = GNUNET_MQ_msg (msg, | ||
1634 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN); | ||
1635 | msg->port = p->id; | ||
1636 | GNUNET_MQ_send (h->mq, | ||
1637 | env); | ||
1638 | return p; | ||
1639 | } | ||
1640 | |||
1641 | |||
1642 | /** | ||
1643 | * Create a new channel towards a remote peer. | ||
1644 | * | ||
1645 | * If the destination port is not open by any peer or the destination peer | ||
1646 | * does not accept the channel, #GNUNET_CADET_ChannelEndHandler will be called | ||
1647 | * for this channel. | ||
1648 | * | ||
1649 | * @param h CADET handle. | ||
1650 | * @param channel_cls Closure for the channel. It's given to: | ||
1651 | * - The disconnect handler @a disconnects | ||
1652 | * - Each message type callback in @a handlers | ||
1653 | * @param destination Peer identity the channel should go to. | ||
1654 | * @param port Identification of the destination port. | ||
1655 | * @param options CadetOption flag field, with all desired option bits set to 1. | ||
1656 | * @param window_changes Function called when the transmit window size changes. | ||
1657 | * @param disconnects Function called when the channel is disconnected. | ||
1658 | * @param handlers Callbacks for messages we care about, NULL-terminated. | ||
1659 | * @return Handle to the channel. | ||
1660 | */ | ||
1661 | struct GNUNET_CADET_Channel * | ||
1662 | GNUNET_CADET_channel_creatE (struct GNUNET_CADET_Handle *h, | ||
1663 | void *channel_cls, | ||
1664 | const struct GNUNET_PeerIdentity *destination, | ||
1665 | const struct GNUNET_HashCode *port, | ||
1666 | enum GNUNET_CADET_ChannelOption options, | ||
1667 | GNUNET_CADET_WindowSizeEventHandler window_changes, | ||
1668 | GNUNET_CADET_DisconnectEventHandler disconnects, | ||
1669 | const struct GNUNET_MQ_MessageHandler *handlers) | ||
1670 | { | ||
1671 | struct GNUNET_CADET_Channel *ch; | ||
1672 | struct GNUNET_CADET_LocalChannelCreateMessage *msg; | ||
1673 | struct GNUNET_MQ_Envelope *env; | ||
1674 | |||
1675 | GNUNET_assert (NULL != disconnects); | ||
1676 | ch = create_channel (h, | ||
1677 | NULL); | ||
1678 | ch->ctx = channel_cls; | ||
1679 | ch->peer = *destination; | ||
1680 | ch->options = options; | ||
1681 | ch->window_changes = window_changes; | ||
1682 | ch->disconnects = disconnects; | ||
1683 | |||
1684 | /* Create MQ for channel */ | ||
1685 | ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl, | ||
1686 | &cadet_mq_destroy_impl, | ||
1687 | &cadet_mq_cancel_impl, | ||
1688 | ch, | ||
1689 | handlers, | ||
1690 | &cadet_mq_error_handler, | ||
1691 | ch); | ||
1692 | GNUNET_MQ_set_handlers_closure (ch->mq, channel_cls); | ||
1693 | |||
1694 | /* Request channel creation to service */ | ||
1695 | env = GNUNET_MQ_msg (msg, | ||
1696 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE); | ||
1697 | msg->ccn = ch->ccn; | ||
1698 | msg->port = *port; | ||
1699 | msg->peer = *destination; | ||
1700 | msg->opt = htonl (options); | ||
1701 | GNUNET_MQ_send (h->mq, | ||
1702 | env); | ||
1703 | return ch; | ||
1704 | } | ||
1705 | |||
1706 | |||
1707 | /** | ||
1708 | * Obtain the message queue for a connected peer. | ||
1709 | * | ||
1710 | * @param channel The channel handle from which to get the MQ. | ||
1711 | * | ||
1712 | * @return NULL if @a channel is not yet connected. | ||
1713 | */ | ||
1714 | struct GNUNET_MQ_Handle * | ||
1715 | GNUNET_CADET_get_mq (const struct GNUNET_CADET_Channel *channel) | ||
1716 | { | ||
1717 | return channel->mq; | ||
1718 | } | ||
1719 | |||
1720 | /* end of cadet_api.c */ | ||
diff --git a/src/cadet/cadet_common.c b/src/cadet/cadet_common.c deleted file mode 100644 index 95a3144e4..000000000 --- a/src/cadet/cadet_common.c +++ /dev/null | |||
@@ -1,370 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012 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_common.c | ||
23 | * @brief CADET helper functions | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | |||
27 | #include "cadet.h" | ||
28 | |||
29 | /** | ||
30 | * @brief Translate a fwd variable into a string representation, for logging. | ||
31 | * | ||
32 | * @param fwd Is FWD? (#GNUNET_YES or #GNUNET_NO) | ||
33 | * | ||
34 | * @return String representing FWD or BCK. | ||
35 | */ | ||
36 | char * | ||
37 | GC_f2s (int fwd) | ||
38 | { | ||
39 | if (GNUNET_YES == fwd) | ||
40 | { | ||
41 | return "FWD"; | ||
42 | } | ||
43 | else if (GNUNET_NO == fwd) | ||
44 | { | ||
45 | return "BCK"; | ||
46 | } | ||
47 | else | ||
48 | { | ||
49 | /* Not an error, can happen with CONNECTION_BROKEN messages. */ | ||
50 | return "\???"; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | |||
55 | /** | ||
56 | * Test if @a bigger is larger than @a smaller. | ||
57 | * Considers the case that @a bigger just overflowed | ||
58 | * and is thus tiny while @a smaller is still below | ||
59 | * `UINT32_MAX`. | ||
60 | */ | ||
61 | int | ||
62 | GC_is_pid_bigger (uint32_t bigger, | ||
63 | uint32_t smaller) | ||
64 | { | ||
65 | return (PID_OVERFLOW (smaller, bigger) || | ||
66 | ( (bigger > smaller) && | ||
67 | (! PID_OVERFLOW (bigger, smaller))) ); | ||
68 | } | ||
69 | |||
70 | |||
71 | uint32_t | ||
72 | GC_max_pid (uint32_t a, uint32_t b) | ||
73 | { | ||
74 | if (GC_is_pid_bigger(a, b)) | ||
75 | return a; | ||
76 | return b; | ||
77 | } | ||
78 | |||
79 | |||
80 | uint32_t | ||
81 | GC_min_pid (uint32_t a, uint32_t b) | ||
82 | { | ||
83 | if (GC_is_pid_bigger(a, b)) | ||
84 | return b; | ||
85 | return a; | ||
86 | } | ||
87 | |||
88 | |||
89 | /** | ||
90 | * Allocate a string with a hexdump of any binary data. | ||
91 | * | ||
92 | * @param bin Arbitrary binary data. | ||
93 | * @param len Length of @a bin in bytes. | ||
94 | * @param output Where to write the output (if *output be NULL it's allocated). | ||
95 | * | ||
96 | * @return The size of the output. | ||
97 | */ | ||
98 | size_t | ||
99 | GC_bin2s (void *bin, unsigned int len, char **output) | ||
100 | { | ||
101 | char *data = bin; | ||
102 | char *buf; | ||
103 | unsigned int s_len; | ||
104 | unsigned int i; | ||
105 | |||
106 | s_len = 2 * len + 1; | ||
107 | if (NULL == *output) | ||
108 | *output = GNUNET_malloc (s_len); | ||
109 | buf = *output; | ||
110 | |||
111 | for (i = 0; i < len; i++) | ||
112 | { | ||
113 | SPRINTF (&buf[2 * i], "%2X", data[i]); | ||
114 | } | ||
115 | buf[s_len - 1] = '\0'; | ||
116 | |||
117 | return s_len; | ||
118 | } | ||
119 | |||
120 | |||
121 | #if !defined(GNUNET_CULL_LOGGING) | ||
122 | const char * | ||
123 | GC_m2s (uint16_t m) | ||
124 | { | ||
125 | static char buf[2][16]; | ||
126 | static int idx; | ||
127 | const char *s; | ||
128 | |||
129 | idx = (idx + 1) % 2; | ||
130 | switch (m) | ||
131 | { | ||
132 | /** | ||
133 | * Used to mark the "payload" of a non-payload message. | ||
134 | */ | ||
135 | case 0: | ||
136 | s = "retransmit"; | ||
137 | break; | ||
138 | |||
139 | /** | ||
140 | * Request the creation of a path | ||
141 | */ | ||
142 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
143 | s = "CONN_CREAT"; | ||
144 | break; | ||
145 | |||
146 | /** | ||
147 | * Request the modification of an existing path | ||
148 | */ | ||
149 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK: | ||
150 | s = "CONN_ACK"; | ||
151 | break; | ||
152 | |||
153 | /** | ||
154 | * Notify that a connection of a path is no longer valid | ||
155 | */ | ||
156 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
157 | s = "CONN_BRKN"; | ||
158 | break; | ||
159 | |||
160 | /** | ||
161 | * At some point, the route will spontaneously change | ||
162 | */ | ||
163 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_PATH_CHANGED_UNIMPLEMENTED: | ||
164 | s = "PATH_CHNGD"; | ||
165 | break; | ||
166 | |||
167 | /** | ||
168 | * Transport payload data. | ||
169 | */ | ||
170 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA: | ||
171 | s = "DATA"; | ||
172 | break; | ||
173 | |||
174 | /** | ||
175 | * Confirm receipt of payload data. | ||
176 | */ | ||
177 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK: | ||
178 | s = "DATA_ACK"; | ||
179 | break; | ||
180 | |||
181 | /** | ||
182 | * Key exchange message. | ||
183 | */ | ||
184 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX: | ||
185 | s = "KX"; | ||
186 | break; | ||
187 | |||
188 | /** | ||
189 | * Encrypted. | ||
190 | */ | ||
191 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED: | ||
192 | s = "ENCRYPTED"; | ||
193 | break; | ||
194 | |||
195 | /** | ||
196 | * Request the destuction of a path | ||
197 | */ | ||
198 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
199 | s = "CONN_DSTRY"; | ||
200 | break; | ||
201 | |||
202 | /** | ||
203 | * ACK for a data packet. | ||
204 | */ | ||
205 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK: | ||
206 | s = "ACK"; | ||
207 | break; | ||
208 | |||
209 | /** | ||
210 | * POLL for ACK. | ||
211 | */ | ||
212 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL: | ||
213 | s = "POLL"; | ||
214 | break; | ||
215 | |||
216 | /** | ||
217 | * Announce origin is still alive. | ||
218 | */ | ||
219 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE: | ||
220 | s = "KEEPALIVE"; | ||
221 | break; | ||
222 | |||
223 | /** | ||
224 | * Open port | ||
225 | */ | ||
226 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN: | ||
227 | s = "OPEN_PORT"; | ||
228 | break; | ||
229 | |||
230 | /** | ||
231 | * Close port | ||
232 | */ | ||
233 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE: | ||
234 | s = "CLOSE_PORT"; | ||
235 | break; | ||
236 | |||
237 | /** | ||
238 | * Ask the cadet service to create a new tunnel | ||
239 | */ | ||
240 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN: | ||
241 | s = "CHAN_CREAT"; | ||
242 | break; | ||
243 | |||
244 | /** | ||
245 | * Ask the cadet service to destroy a tunnel | ||
246 | */ | ||
247 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
248 | s = "CHAN_DSTRY"; | ||
249 | break; | ||
250 | |||
251 | /** | ||
252 | * Confirm the creation of a channel. | ||
253 | */ | ||
254 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK: | ||
255 | s = "CHAN_ACK"; | ||
256 | break; | ||
257 | |||
258 | /** | ||
259 | * Confirm the creation of a channel. | ||
260 | */ | ||
261 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED: | ||
262 | s = "CHAN_NACK"; | ||
263 | break; | ||
264 | |||
265 | /** | ||
266 | * Local payload traffic | ||
267 | */ | ||
268 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA: | ||
269 | s = "LOC_DATA"; | ||
270 | break; | ||
271 | |||
272 | /** | ||
273 | * Local ACK for data. | ||
274 | */ | ||
275 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK: | ||
276 | s = "LOC_ACK"; | ||
277 | break; | ||
278 | |||
279 | /** | ||
280 | * Local monitoring of channels. | ||
281 | */ | ||
282 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNELS: | ||
283 | s = "INFO_CHANS"; | ||
284 | break; | ||
285 | |||
286 | /** | ||
287 | * Local monitoring of a channel. | ||
288 | */ | ||
289 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL: | ||
290 | s = "INFO_CHAN"; | ||
291 | break; | ||
292 | |||
293 | /** | ||
294 | * Local monitoring of service. | ||
295 | */ | ||
296 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS: | ||
297 | s = "INFO_TUNS"; | ||
298 | break; | ||
299 | |||
300 | /** | ||
301 | * Local monitoring of service. | ||
302 | */ | ||
303 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL: | ||
304 | s = "INFO_TUN"; | ||
305 | break; | ||
306 | |||
307 | /** | ||
308 | * Local information about all connections of service. | ||
309 | */ | ||
310 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CONNECTIONS: | ||
311 | s = "INFO_CONNS"; | ||
312 | break; | ||
313 | |||
314 | /** | ||
315 | * Local information of service about a specific connection. | ||
316 | */ | ||
317 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CONNECTION: | ||
318 | s = "INFO_CONN"; | ||
319 | break; | ||
320 | |||
321 | /** | ||
322 | * Local information about all peers known to the service. | ||
323 | */ | ||
324 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS: | ||
325 | s = "INFO_PEERS"; | ||
326 | break; | ||
327 | |||
328 | /** | ||
329 | * Local information of service about a specific peer. | ||
330 | */ | ||
331 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER: | ||
332 | s = "INFO_PEER"; | ||
333 | break; | ||
334 | |||
335 | /** | ||
336 | * Traffic (net-cat style) used by the Command Line Interface. | ||
337 | */ | ||
338 | case GNUNET_MESSAGE_TYPE_CADET_CLI: | ||
339 | s = "CLI"; | ||
340 | break; | ||
341 | |||
342 | /** | ||
343 | * Debug request. | ||
344 | */ | ||
345 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP: | ||
346 | s = "INFO_DUMP"; | ||
347 | break; | ||
348 | |||
349 | /** | ||
350 | * Used to mark the "payload" of a non-payload message. | ||
351 | */ | ||
352 | case UINT16_MAX: | ||
353 | s = " N/A"; | ||
354 | break; | ||
355 | |||
356 | |||
357 | default: | ||
358 | SPRINTF (buf[idx], "{UNK: %5u}", m); | ||
359 | return buf[idx]; | ||
360 | } | ||
361 | SPRINTF (buf[idx], "{%10s}", s); | ||
362 | return buf[idx]; | ||
363 | } | ||
364 | #else | ||
365 | const char * | ||
366 | GC_m2s (uint16_t m) | ||
367 | { | ||
368 | return ""; | ||
369 | } | ||
370 | #endif | ||
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 | */ | ||
40 | static void | ||
41 | path_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 | */ | ||
65 | struct CadetPeerPath * | ||
66 | path_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 | */ | ||
86 | void | ||
87 | path_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 | */ | ||
106 | struct CadetPeerPath * | ||
107 | path_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 | */ | ||
130 | unsigned int | ||
131 | path_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 | */ | ||
151 | void | ||
152 | path_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 | */ | ||
177 | struct CadetPeerPath * | ||
178 | path_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 | */ | ||
239 | int | ||
240 | path_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 | */ | ||
275 | int | ||
276 | path_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 | */ | ||
289 | int | ||
290 | path_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 | */ | ||
318 | int | ||
319 | path_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 | |||
334 | char * | ||
335 | path_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 | |||
353 | void | ||
354 | path_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 | ||
31 | extern "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 | */ | ||
46 | struct 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 | */ | ||
94 | struct CadetPeerPath * | ||
95 | path_new (unsigned int length); | ||
96 | |||
97 | |||
98 | /** | ||
99 | * Invert the path. | ||
100 | * | ||
101 | * @param path The path to invert. | ||
102 | */ | ||
103 | void | ||
104 | path_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 | */ | ||
112 | struct CadetPeerPath * | ||
113 | path_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 | */ | ||
124 | unsigned int | ||
125 | path_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 | */ | ||
135 | void | ||
136 | path_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 | */ | ||
147 | int | ||
148 | path_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 | */ | ||
159 | int | ||
160 | path_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 | */ | ||
169 | int | ||
170 | path_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 | */ | ||
182 | int | ||
183 | path_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 | */ | ||
195 | struct CadetPeerPath * | ||
196 | path_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 | */ | ||
206 | char * | ||
207 | path_2s (struct CadetPeerPath *p); | ||
208 | |||
209 | /** | ||
210 | * Print info about the path for debug. | ||
211 | * | ||
212 | * @param p Path to debug. | ||
213 | */ | ||
214 | void | ||
215 | path_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 | */ | ||
360 | struct 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 | */ | ||
387 | struct 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 | */ | ||
472 | struct 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 | */ | ||
500 | struct 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 | */ |
532 | struct ChannelMessageIdentifier | 392 | struct ChannelMessageIdentifier |
@@ -595,8 +455,6 @@ struct GNUNET_CADET_ChannelDataAckMessage | |||
595 | }; | 455 | }; |
596 | 456 | ||
597 | 457 | ||
598 | #endif | ||
599 | |||
600 | GNUNET_NETWORK_STRUCT_END | 458 | GNUNET_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..1df6bff0d 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 |
@@ -27,6 +27,7 @@ | |||
27 | #include "cadet_test_lib.h" | 27 | #include "cadet_test_lib.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 | */ |
115 | static void * | 131 | static void * |
116 | cadet_connect_adapter (void *cls, | 132 | cadet_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 | */ | ||
273 | void | 326 | void |
274 | GNUNET_CADET_TEST_run (const char *testname, | 327 | GNUNET_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 | */ |
54 | typedef void (*GNUNET_CADET_TEST_AppMain) (void *cls, | 54 | typedef 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 | */ |
76 | void | 76 | void |
77 | GNUNET_CADET_TEST_run (const char *testname, | 77 | GNUNET_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 | */ | ||
34 | struct 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 | */ | ||
102 | struct 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 | */ | ||
131 | static void * | ||
132 | cadet_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 | */ | ||
166 | static void | ||
167 | cadet_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 | */ | ||
197 | static void | ||
198 | cadet_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 | |||
231 | void | ||
232 | GNUNET_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 | */ | ||
262 | static void | ||
263 | cadet_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 | */ | ||
326 | void | ||
327 | GNUNET_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 | ||
29 | extern "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 | */ | ||
42 | struct 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 | */ | ||
54 | typedef 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 | */ | ||
76 | void | ||
77 | GNUNET_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 | */ | ||
93 | void | ||
94 | GNUNET_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-cadet.c b/src/cadet/gnunet-cadet.c index c194a5bc1..57eeac735 100644 --- a/src/cadet/gnunet-cadet.c +++ b/src/cadet/gnunet-cadet.c | |||
@@ -772,15 +772,15 @@ run (void *cls, | |||
772 | && target_id != NULL) | 772 | && target_id != NULL) |
773 | { | 773 | { |
774 | FPRINTF (stderr, | 774 | FPRINTF (stderr, |
775 | _("You must NOT give a TARGET " | 775 | _("Extra arguments are not applicable " |
776 | "when using 'request all' options\n")); | 776 | "in combination with this option.\n")); |
777 | return; | 777 | return; |
778 | } | 778 | } |
779 | 779 | ||
780 | if (GNUNET_YES == dump) | 780 | if (GNUNET_YES == dump) |
781 | { | 781 | { |
782 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 782 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
783 | "requesting debug dump\n"); | 783 | "Requesting debug dump\n"); |
784 | job = GNUNET_SCHEDULER_add_now (&request_dump, | 784 | job = GNUNET_SCHEDULER_add_now (&request_dump, |
785 | NULL); | 785 | NULL); |
786 | } | 786 | } |
@@ -829,7 +829,7 @@ run (void *cls, | |||
829 | 829 | ||
830 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 830 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
831 | "Connecting to CADET service\n"); | 831 | "Connecting to CADET service\n"); |
832 | mh = GNUNET_CADET_connecT (cfg); | 832 | mh = GNUNET_CADET_connect (cfg); |
833 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, | 833 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, |
834 | NULL); | 834 | NULL); |
835 | if (NULL == mh) | 835 | if (NULL == mh) |
@@ -844,7 +844,7 @@ run (void *cls, | |||
844 | GNUNET_CRYPTO_hash (listen_port, | 844 | GNUNET_CRYPTO_hash (listen_port, |
845 | strlen (listen_port), | 845 | strlen (listen_port), |
846 | &porthash); | 846 | &porthash); |
847 | lp = GNUNET_CADET_open_porT (mh, | 847 | lp = GNUNET_CADET_open_port (mh, |
848 | &porthash, | 848 | &porthash, |
849 | &channel_incoming, | 849 | &channel_incoming, |
850 | NULL, | 850 | NULL, |
@@ -876,7 +876,7 @@ run (void *cls, | |||
876 | GNUNET_CRYPTO_hash (target_port, | 876 | GNUNET_CRYPTO_hash (target_port, |
877 | strlen(target_port), | 877 | strlen(target_port), |
878 | &porthash); | 878 | &porthash); |
879 | ch = GNUNET_CADET_channel_creatE (mh, | 879 | ch = GNUNET_CADET_channel_create (mh, |
880 | NULL, | 880 | NULL, |
881 | &pid, | 881 | &pid, |
882 | &porthash, | 882 | &porthash, |
@@ -919,32 +919,55 @@ main (int argc, | |||
919 | char *const *argv) | 919 | char *const *argv) |
920 | { | 920 | { |
921 | int res; | 921 | int res; |
922 | const char helpstr[] = "Create channels and retreive info about cadets status."; | 922 | const char helpstr[] = "Create tunnels and retrieve info about CADET's status."; |
923 | static const struct GNUNET_GETOPT_CommandLineOption options[] = { | 923 | struct GNUNET_GETOPT_CommandLineOption options[] = { |
924 | {'C', "connection", "CONNECTION_ID", | 924 | /* I would use the terminology 'circuit' here... --lynX */ |
925 | gettext_noop ("provide information about a particular connection"), | 925 | GNUNET_GETOPT_OPTION_STRING ('C', |
926 | GNUNET_YES, &GNUNET_GETOPT_set_string, &conn_id}, | 926 | "connection", |
927 | {'e', "echo", NULL, | 927 | "CONNECTION_ID", |
928 | gettext_noop ("activate echo mode"), | 928 | gettext_noop ("Provide information about a particular connection"), |
929 | GNUNET_NO, &GNUNET_GETOPT_set_one, &echo}, | 929 | &conn_id), |
930 | {'d', "dump", NULL, | 930 | |
931 | gettext_noop ("dump debug information to STDERR"), | 931 | GNUNET_GETOPT_OPTION_SET_ONE ('e', |
932 | GNUNET_NO, &GNUNET_GETOPT_set_one, &dump}, | 932 | "echo", |
933 | {'o', "open-port", "PORT", | 933 | gettext_noop ("Activate echo mode"), |
934 | gettext_noop ("port to listen to"), | 934 | &echo), |
935 | GNUNET_YES, &GNUNET_GETOPT_set_string, &listen_port}, | 935 | |
936 | {'p', "peer", "PEER_ID", | 936 | GNUNET_GETOPT_OPTION_SET_ONE ('d', |
937 | gettext_noop ("provide information about a patricular peer"), | 937 | "dump", |
938 | GNUNET_YES, &GNUNET_GETOPT_set_string, &peer_id}, | 938 | gettext_noop ("Dump debug information to STDERR"), |
939 | {'P', "peers", NULL, | 939 | &dump), |
940 | gettext_noop ("provide information about all peers"), | 940 | |
941 | GNUNET_NO, &GNUNET_GETOPT_set_one, &request_peers}, | 941 | GNUNET_GETOPT_OPTION_STRING ('o', |
942 | {'t', "tunnel", "TUNNEL_ID", | 942 | "open-port", |
943 | gettext_noop ("provide information about a particular tunnel"), | 943 | "SHARED_SECRET", |
944 | GNUNET_YES, &GNUNET_GETOPT_set_string, &tunnel_id}, | 944 | gettext_noop ("Listen for connections using a shared secret among sender and recipient"), |
945 | {'T', "tunnels", NULL, | 945 | &listen_port), |
946 | gettext_noop ("provide information about all tunnels"), | 946 | |
947 | GNUNET_NO, &GNUNET_GETOPT_set_one, &request_tunnels}, | 947 | |
948 | GNUNET_GETOPT_OPTION_STRING ('p', | ||
949 | "peer", | ||
950 | "PEER_ID", | ||
951 | gettext_noop ("Provide information about a patricular peer"), | ||
952 | &peer_id), | ||
953 | |||
954 | |||
955 | GNUNET_GETOPT_OPTION_SET_ONE ('P', | ||
956 | "peers", | ||
957 | gettext_noop ("Provide information about all peers"), | ||
958 | &request_peers), | ||
959 | |||
960 | GNUNET_GETOPT_OPTION_STRING ('t', | ||
961 | "tunnel", | ||
962 | "TUNNEL_ID", | ||
963 | gettext_noop ("Provide information about a particular tunnel"), | ||
964 | &tunnel_id), | ||
965 | |||
966 | |||
967 | GNUNET_GETOPT_OPTION_SET_ONE ('T', | ||
968 | "tunnels", | ||
969 | gettext_noop ("Provide information about all tunnels"), | ||
970 | &request_tunnels), | ||
948 | 971 | ||
949 | GNUNET_GETOPT_OPTION_END | 972 | GNUNET_GETOPT_OPTION_END |
950 | }; | 973 | }; |
@@ -955,7 +978,7 @@ main (int argc, | |||
955 | return 2; | 978 | return 2; |
956 | 979 | ||
957 | res = GNUNET_PROGRAM_run (argc, argv, | 980 | res = GNUNET_PROGRAM_run (argc, argv, |
958 | "gnunet-cadet (OPTIONS | TARGET PORT)", | 981 | "gnunet-cadet (OPTIONS | PEER_ID SHARED_SECRET)", |
959 | gettext_noop (helpstr), | 982 | gettext_noop (helpstr), |
960 | options, &run, NULL); | 983 | options, &run, NULL); |
961 | 984 | ||
diff --git a/src/cadet/gnunet-service-cadet-new.c b/src/cadet/gnunet-service-cadet-new.c deleted file mode 100644 index de85db5b6..000000000 --- a/src/cadet/gnunet-service-cadet-new.c +++ /dev/null | |||
@@ -1,1490 +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 | */ | ||
56 | struct 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 | */ | ||
111 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
112 | |||
113 | /** | ||
114 | * Handle to the statistics service. | ||
115 | */ | ||
116 | struct GNUNET_STATISTICS_Handle *stats; | ||
117 | |||
118 | /** | ||
119 | * Handle to communicate with ATS. | ||
120 | */ | ||
121 | struct GNUNET_ATS_ConnectivityHandle *ats_ch; | ||
122 | |||
123 | /** | ||
124 | * Local peer own ID. | ||
125 | */ | ||
126 | struct GNUNET_PeerIdentity my_full_id; | ||
127 | |||
128 | /** | ||
129 | * Own private key. | ||
130 | */ | ||
131 | struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; | ||
132 | |||
133 | /** | ||
134 | * Signal that shutdown is happening: prevent recovery measures. | ||
135 | */ | ||
136 | int shutting_down; | ||
137 | |||
138 | /** | ||
139 | * DLL with all the clients, head. | ||
140 | */ | ||
141 | static struct CadetClient *clients_head; | ||
142 | |||
143 | /** | ||
144 | * DLL with all the clients, tail. | ||
145 | */ | ||
146 | static struct CadetClient *clients_tail; | ||
147 | |||
148 | /** | ||
149 | * Next ID to assign to a client. | ||
150 | */ | ||
151 | static unsigned int next_client_id; | ||
152 | |||
153 | /** | ||
154 | * All ports clients of this peer have opened. | ||
155 | */ | ||
156 | struct 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 | */ | ||
163 | struct GNUNET_CONTAINER_MultiHashMap *loose_channels; | ||
164 | |||
165 | /** | ||
166 | * Map from PIDs to `struct CadetPeer` entries. | ||
167 | */ | ||
168 | struct GNUNET_CONTAINER_MultiPeerMap *peers; | ||
169 | |||
170 | /** | ||
171 | * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier` | ||
172 | * hash codes to `struct CadetConnection` objects. | ||
173 | */ | ||
174 | struct GNUNET_CONTAINER_MultiShortmap *connections; | ||
175 | |||
176 | /** | ||
177 | * How many messages are needed to trigger an AXOLOTL ratchet advance. | ||
178 | */ | ||
179 | unsigned long long ratchet_messages; | ||
180 | |||
181 | /** | ||
182 | * How long until we trigger a ratched advance due to time. | ||
183 | */ | ||
184 | struct GNUNET_TIME_Relative ratchet_time; | ||
185 | |||
186 | /** | ||
187 | * How frequently do we send KEEPALIVE messages on idle connections? | ||
188 | */ | ||
189 | struct GNUNET_TIME_Relative keepalive_period; | ||
190 | |||
191 | /** | ||
192 | * Set to non-zero values to create random drops to test retransmissions. | ||
193 | */ | ||
194 | unsigned 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 | */ | ||
203 | void | ||
204 | GSC_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 | */ | ||
218 | const char * | ||
219 | GSC_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 | */ | ||
238 | static struct CadetChannel * | ||
239 | lookup_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 | */ | ||
253 | static struct GNUNET_CADET_ClientChannelNumber | ||
254 | client_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 | */ | ||
287 | struct GNUNET_CADET_ClientChannelNumber | ||
288 | GSC_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 | */ | ||
333 | static int | ||
334 | destroy_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 | */ | ||
357 | static int | ||
358 | destroy_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 | */ | ||
372 | static void | ||
373 | shutdown_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 | */ | ||
426 | static void | ||
427 | shutdown_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 | */ | ||
447 | static int | ||
448 | bind_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 | */ | ||
474 | static void | ||
475 | handle_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 | */ | ||
518 | static void | ||
519 | handle_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 | */ | ||
551 | static void | ||
552 | handle_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 | */ | ||
609 | static void | ||
610 | handle_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 | */ | ||
650 | static int | ||
651 | check_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 | */ | ||
706 | static void | ||
707 | handle_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 | buf = (const char *) &msg[1]; | ||
728 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
729 | "Received %u bytes payload from %s for %s\n", | ||
730 | (unsigned int) payload_size, | ||
731 | GSC_2s (c), | ||
732 | GCCH_2s (ch)); | ||
733 | if (GNUNET_OK != | ||
734 | GCCH_handle_local_data (ch, | ||
735 | msg->ccn, | ||
736 | buf, | ||
737 | payload_size)) | ||
738 | { | ||
739 | GNUNET_SERVICE_client_drop (c->client); | ||
740 | return; | ||
741 | } | ||
742 | GNUNET_SERVICE_client_continue (c->client); | ||
743 | } | ||
744 | |||
745 | |||
746 | /** | ||
747 | * Handler for client's ACKs for payload traffic. | ||
748 | * | ||
749 | * @param cls identification of the client. | ||
750 | * @param msg The actual message. | ||
751 | */ | ||
752 | static void | ||
753 | handle_local_ack (void *cls, | ||
754 | const struct GNUNET_CADET_LocalAck *msg) | ||
755 | { | ||
756 | struct CadetClient *c = cls; | ||
757 | struct CadetChannel *ch; | ||
758 | |||
759 | ch = lookup_channel (c, | ||
760 | msg->ccn); | ||
761 | if (NULL == ch) | ||
762 | { | ||
763 | /* Channel does not exist! */ | ||
764 | GNUNET_break (0); | ||
765 | GNUNET_SERVICE_client_drop (c->client); | ||
766 | return; | ||
767 | } | ||
768 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
769 | "Got a local ACK from %s for %s\n", | ||
770 | GSC_2s(c), | ||
771 | GCCH_2s (ch)); | ||
772 | GCCH_handle_local_ack (ch, | ||
773 | msg->ccn); | ||
774 | GNUNET_SERVICE_client_continue (c->client); | ||
775 | } | ||
776 | |||
777 | |||
778 | /** | ||
779 | * Iterator over all peers to send a monitoring client info about each peer. | ||
780 | * | ||
781 | * @param cls Closure (). | ||
782 | * @param peer Peer ID (tunnel remote peer). | ||
783 | * @param value Peer info. | ||
784 | * @return #GNUNET_YES, to keep iterating. | ||
785 | */ | ||
786 | static int | ||
787 | get_all_peers_iterator (void *cls, | ||
788 | const struct GNUNET_PeerIdentity *peer, | ||
789 | void *value) | ||
790 | { | ||
791 | struct CadetClient *c = cls; | ||
792 | struct CadetPeer *p = value; | ||
793 | struct GNUNET_MQ_Envelope *env; | ||
794 | struct GNUNET_CADET_LocalInfoPeer *msg; | ||
795 | |||
796 | env = GNUNET_MQ_msg (msg, | ||
797 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | ||
798 | msg->destination = *peer; | ||
799 | msg->paths = htons (GCP_count_paths (p)); | ||
800 | msg->tunnel = htons (NULL != GCP_get_tunnel (p, | ||
801 | GNUNET_NO)); | ||
802 | GNUNET_MQ_send (c->mq, | ||
803 | env); | ||
804 | return GNUNET_YES; | ||
805 | } | ||
806 | |||
807 | |||
808 | /** | ||
809 | * Handler for client's INFO PEERS request. | ||
810 | * | ||
811 | * @param cls Identification of the client. | ||
812 | * @param message The actual message. | ||
813 | */ | ||
814 | static void | ||
815 | handle_get_peers (void *cls, | ||
816 | const struct GNUNET_MessageHeader *message) | ||
817 | { | ||
818 | struct CadetClient *c = cls; | ||
819 | struct GNUNET_MQ_Envelope *env; | ||
820 | struct GNUNET_MessageHeader *reply; | ||
821 | |||
822 | GCP_iterate_all (&get_all_peers_iterator, | ||
823 | c); | ||
824 | env = GNUNET_MQ_msg (reply, | ||
825 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | ||
826 | GNUNET_MQ_send (c->mq, | ||
827 | env); | ||
828 | GNUNET_SERVICE_client_continue (c->client); | ||
829 | } | ||
830 | |||
831 | |||
832 | /** | ||
833 | * Iterator over all paths of a peer to build an InfoPeer message. | ||
834 | * Message contains blocks of peers, first not included. | ||
835 | * | ||
836 | * @param cls message queue for transmission | ||
837 | * @param path Path itself | ||
838 | * @param off offset of the peer on @a path | ||
839 | * @return #GNUNET_YES if should keep iterating. | ||
840 | * #GNUNET_NO otherwise. | ||
841 | */ | ||
842 | static int | ||
843 | path_info_iterator (void *cls, | ||
844 | struct CadetPeerPath *path, | ||
845 | unsigned int off) | ||
846 | { | ||
847 | struct GNUNET_MQ_Handle *mq = cls; | ||
848 | struct GNUNET_MQ_Envelope *env; | ||
849 | struct GNUNET_MessageHeader *resp; | ||
850 | struct GNUNET_PeerIdentity *id; | ||
851 | uint16_t path_size; | ||
852 | unsigned int i; | ||
853 | unsigned int path_length; | ||
854 | |||
855 | path_length = GCPP_get_length (path); | ||
856 | path_size = sizeof (struct GNUNET_PeerIdentity) * (path_length - 1); | ||
857 | if (sizeof (*resp) + path_size > UINT16_MAX) | ||
858 | { | ||
859 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
860 | "Path of %u entries is too long for info message\n", | ||
861 | path_length); | ||
862 | return GNUNET_YES; | ||
863 | } | ||
864 | env = GNUNET_MQ_msg_extra (resp, | ||
865 | path_size, | ||
866 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER); | ||
867 | id = (struct GNUNET_PeerIdentity *) &resp[1]; | ||
868 | |||
869 | /* Don't copy first peer. First peer is always the local one. Last | ||
870 | * peer is always the destination (leave as 0, EOL). | ||
871 | */ | ||
872 | for (i = 0; i < off; i++) | ||
873 | id[i] = *GCP_get_id (GCPP_get_peer_at_offset (path, | ||
874 | i + 1)); | ||
875 | GNUNET_MQ_send (mq, | ||
876 | env); | ||
877 | return GNUNET_YES; | ||
878 | } | ||
879 | |||
880 | |||
881 | /** | ||
882 | * Handler for client's SHOW_PEER request. | ||
883 | * | ||
884 | * @param cls Identification of the client. | ||
885 | * @param msg The actual message. | ||
886 | */ | ||
887 | static void | ||
888 | handle_show_peer (void *cls, | ||
889 | const struct GNUNET_CADET_LocalInfo *msg) | ||
890 | { | ||
891 | struct CadetClient *c = cls; | ||
892 | struct CadetPeer *p; | ||
893 | struct GNUNET_MQ_Envelope *env; | ||
894 | struct GNUNET_MessageHeader *resp; | ||
895 | |||
896 | p = GCP_get (&msg->peer, | ||
897 | GNUNET_NO); | ||
898 | if (NULL != p) | ||
899 | GCP_iterate_paths (p, | ||
900 | &path_info_iterator, | ||
901 | c->mq); | ||
902 | /* Send message with 0/0 to indicate the end */ | ||
903 | env = GNUNET_MQ_msg (resp, | ||
904 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER_END); | ||
905 | GNUNET_MQ_send (c->mq, | ||
906 | env); | ||
907 | GNUNET_SERVICE_client_continue (c->client); | ||
908 | } | ||
909 | |||
910 | |||
911 | /** | ||
912 | * Iterator over all tunnels to send a monitoring client info about each tunnel. | ||
913 | * | ||
914 | * @param cls Closure (). | ||
915 | * @param peer Peer ID (tunnel remote peer). | ||
916 | * @param value a `struct CadetPeer` | ||
917 | * @return #GNUNET_YES, to keep iterating. | ||
918 | */ | ||
919 | static int | ||
920 | get_all_tunnels_iterator (void *cls, | ||
921 | const struct GNUNET_PeerIdentity *peer, | ||
922 | void *value) | ||
923 | { | ||
924 | struct CadetClient *c = cls; | ||
925 | struct CadetPeer *p = value; | ||
926 | struct GNUNET_MQ_Envelope *env; | ||
927 | struct GNUNET_CADET_LocalInfoTunnel *msg; | ||
928 | struct CadetTunnel *t; | ||
929 | |||
930 | t = GCP_get_tunnel (p, | ||
931 | GNUNET_NO); | ||
932 | if (NULL == t) | ||
933 | return GNUNET_YES; | ||
934 | env = GNUNET_MQ_msg (msg, | ||
935 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | ||
936 | msg->destination = *peer; | ||
937 | msg->channels = htonl (GCT_count_channels (t)); | ||
938 | msg->connections = htonl (GCT_count_any_connections (t)); | ||
939 | msg->cstate = htons (0); | ||
940 | msg->estate = htons ((uint16_t) GCT_get_estate (t)); | ||
941 | GNUNET_MQ_send (c->mq, | ||
942 | env); | ||
943 | return GNUNET_YES; | ||
944 | } | ||
945 | |||
946 | |||
947 | /** | ||
948 | * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS request. | ||
949 | * | ||
950 | * @param cls client Identification of the client. | ||
951 | * @param message The actual message. | ||
952 | */ | ||
953 | static void | ||
954 | handle_info_tunnels (void *cls, | ||
955 | const struct GNUNET_MessageHeader *message) | ||
956 | { | ||
957 | struct CadetClient *c = cls; | ||
958 | struct GNUNET_MQ_Envelope *env; | ||
959 | struct GNUNET_MessageHeader *reply; | ||
960 | |||
961 | GCP_iterate_all (&get_all_tunnels_iterator, | ||
962 | c); | ||
963 | env = GNUNET_MQ_msg (reply, | ||
964 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | ||
965 | GNUNET_MQ_send (c->mq, | ||
966 | env); | ||
967 | GNUNET_SERVICE_client_continue (c->client); | ||
968 | } | ||
969 | |||
970 | |||
971 | /** | ||
972 | * Update the message with information about the connection. | ||
973 | * | ||
974 | * @param cls a `struct GNUNET_CADET_LocalInfoTunnel` message to update | ||
975 | * @param ct a connection about which we should store information in @a cls | ||
976 | */ | ||
977 | static void | ||
978 | iter_connection (void *cls, | ||
979 | struct CadetTConnection *ct) | ||
980 | { | ||
981 | struct GNUNET_CADET_LocalInfoTunnel *msg = cls; | ||
982 | struct CadetConnection *cc = ct->cc; | ||
983 | struct GNUNET_CADET_ConnectionTunnelIdentifier *h; | ||
984 | |||
985 | h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1]; | ||
986 | h[msg->connections++] = *(GCC_get_id (cc)); | ||
987 | } | ||
988 | |||
989 | |||
990 | /** | ||
991 | * Update the message with information about the channel. | ||
992 | * | ||
993 | * @param cls a `struct GNUNET_CADET_LocalInfoTunnel` message to update | ||
994 | * @param ch a channel about which we should store information in @a cls | ||
995 | */ | ||
996 | static void | ||
997 | iter_channel (void *cls, | ||
998 | struct CadetChannel *ch) | ||
999 | { | ||
1000 | struct GNUNET_CADET_LocalInfoTunnel *msg = cls; | ||
1001 | struct GNUNET_CADET_ConnectionTunnelIdentifier *h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1]; | ||
1002 | struct GNUNET_CADET_ChannelTunnelNumber *chn | ||
1003 | = (struct GNUNET_CADET_ChannelTunnelNumber *) &h[msg->connections]; | ||
1004 | |||
1005 | chn[msg->channels++] = GCCH_get_id (ch); | ||
1006 | } | ||
1007 | |||
1008 | |||
1009 | /** | ||
1010 | * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL request. | ||
1011 | * | ||
1012 | * @param cls Identification of the client. | ||
1013 | * @param msg The actual message. | ||
1014 | */ | ||
1015 | static void | ||
1016 | handle_info_tunnel (void *cls, | ||
1017 | const struct GNUNET_CADET_LocalInfo *msg) | ||
1018 | { | ||
1019 | struct CadetClient *c = cls; | ||
1020 | struct GNUNET_MQ_Envelope *env; | ||
1021 | struct GNUNET_CADET_LocalInfoTunnel *resp; | ||
1022 | struct CadetTunnel *t; | ||
1023 | struct CadetPeer *p; | ||
1024 | unsigned int ch_n; | ||
1025 | unsigned int c_n; | ||
1026 | |||
1027 | p = GCP_get (&msg->peer, | ||
1028 | GNUNET_NO); | ||
1029 | t = GCP_get_tunnel (p, | ||
1030 | GNUNET_NO); | ||
1031 | if (NULL == t) | ||
1032 | { | ||
1033 | /* We don't know the tunnel */ | ||
1034 | struct GNUNET_MQ_Envelope *env; | ||
1035 | struct GNUNET_CADET_LocalInfoTunnel *warn; | ||
1036 | |||
1037 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1038 | "Tunnel to %s unknown\n", | ||
1039 | GNUNET_i2s_full (&msg->peer)); | ||
1040 | env = GNUNET_MQ_msg (warn, | ||
1041 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); | ||
1042 | warn->destination = msg->peer; | ||
1043 | GNUNET_MQ_send (c->mq, | ||
1044 | env); | ||
1045 | GNUNET_SERVICE_client_continue (c->client); | ||
1046 | return; | ||
1047 | } | ||
1048 | |||
1049 | /* Initialize context */ | ||
1050 | ch_n = GCT_count_channels (t); | ||
1051 | c_n = GCT_count_any_connections (t); | ||
1052 | env = GNUNET_MQ_msg_extra (resp, | ||
1053 | c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier) + | ||
1054 | ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber), | ||
1055 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); | ||
1056 | resp->destination = msg->peer; | ||
1057 | /* Do not reorder! #iter_channel needs counters in HBO! */ | ||
1058 | GCT_iterate_connections (t, | ||
1059 | &iter_connection, | ||
1060 | resp); | ||
1061 | GCT_iterate_channels (t, | ||
1062 | &iter_channel, | ||
1063 | resp); | ||
1064 | resp->connections = htonl (resp->connections); | ||
1065 | resp->channels = htonl (resp->channels); | ||
1066 | resp->cstate = htons (0); | ||
1067 | resp->estate = htons (GCT_get_estate (t)); | ||
1068 | GNUNET_MQ_send (c->mq, | ||
1069 | env); | ||
1070 | GNUNET_SERVICE_client_continue (c->client); | ||
1071 | } | ||
1072 | |||
1073 | |||
1074 | /** | ||
1075 | * Iterator over all peers to dump info for each peer. | ||
1076 | * | ||
1077 | * @param cls Closure (unused). | ||
1078 | * @param peer Peer ID (tunnel remote peer). | ||
1079 | * @param value Peer info. | ||
1080 | * | ||
1081 | * @return #GNUNET_YES, to keep iterating. | ||
1082 | */ | ||
1083 | static int | ||
1084 | show_peer_iterator (void *cls, | ||
1085 | const struct GNUNET_PeerIdentity *peer, | ||
1086 | void *value) | ||
1087 | { | ||
1088 | struct CadetPeer *p = value; | ||
1089 | struct CadetTunnel *t; | ||
1090 | |||
1091 | t = GCP_get_tunnel (p, | ||
1092 | GNUNET_NO); | ||
1093 | if (NULL != t) | ||
1094 | GCT_debug (t, | ||
1095 | GNUNET_ERROR_TYPE_ERROR); | ||
1096 | LOG (GNUNET_ERROR_TYPE_ERROR, "\n"); | ||
1097 | return GNUNET_YES; | ||
1098 | } | ||
1099 | |||
1100 | |||
1101 | /** | ||
1102 | * Handler for client's INFO_DUMP request. | ||
1103 | * | ||
1104 | * @param cls Identification of the client. | ||
1105 | * @param message The actual message. | ||
1106 | */ | ||
1107 | static void | ||
1108 | handle_info_dump (void *cls, | ||
1109 | const struct GNUNET_MessageHeader *message) | ||
1110 | { | ||
1111 | struct CadetClient *c = cls; | ||
1112 | |||
1113 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1114 | "Received dump info request from client %u\n", | ||
1115 | c->id); | ||
1116 | |||
1117 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1118 | "*************************** DUMP START ***************************\n"); | ||
1119 | for (struct CadetClient *ci = clients_head; | ||
1120 | NULL != ci; | ||
1121 | ci = ci->next) | ||
1122 | { | ||
1123 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1124 | "Client %u (%p), handle: %p, ports: %u, channels: %u\n", | ||
1125 | ci->id, | ||
1126 | ci, | ||
1127 | ci->client, | ||
1128 | (NULL != c->ports) | ||
1129 | ? GNUNET_CONTAINER_multihashmap_size (ci->ports) | ||
1130 | : 0, | ||
1131 | GNUNET_CONTAINER_multihashmap32_size (ci->channels)); | ||
1132 | } | ||
1133 | LOG (GNUNET_ERROR_TYPE_ERROR, "***************************\n"); | ||
1134 | GCP_iterate_all (&show_peer_iterator, | ||
1135 | NULL); | ||
1136 | |||
1137 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1138 | "**************************** DUMP END ****************************\n"); | ||
1139 | |||
1140 | GNUNET_SERVICE_client_continue (c->client); | ||
1141 | } | ||
1142 | |||
1143 | |||
1144 | |||
1145 | /** | ||
1146 | * Callback called when a client connects to the service. | ||
1147 | * | ||
1148 | * @param cls closure for the service | ||
1149 | * @param client the new client that connected to the service | ||
1150 | * @param mq the message queue used to send messages to the client | ||
1151 | * @return @a c | ||
1152 | */ | ||
1153 | static void * | ||
1154 | client_connect_cb (void *cls, | ||
1155 | struct GNUNET_SERVICE_Client *client, | ||
1156 | struct GNUNET_MQ_Handle *mq) | ||
1157 | { | ||
1158 | struct CadetClient *c; | ||
1159 | |||
1160 | c = GNUNET_new (struct CadetClient); | ||
1161 | c->client = client; | ||
1162 | c->mq = mq; | ||
1163 | c->id = next_client_id++; /* overflow not important: just for debug */ | ||
1164 | c->channels | ||
1165 | = GNUNET_CONTAINER_multihashmap32_create (32); | ||
1166 | GNUNET_CONTAINER_DLL_insert (clients_head, | ||
1167 | clients_tail, | ||
1168 | c); | ||
1169 | GNUNET_STATISTICS_update (stats, | ||
1170 | "# clients", | ||
1171 | +1, | ||
1172 | GNUNET_NO); | ||
1173 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1174 | "%s connected\n", | ||
1175 | GSC_2s (c)); | ||
1176 | return c; | ||
1177 | } | ||
1178 | |||
1179 | |||
1180 | /** | ||
1181 | * A channel was destroyed by the other peer. Tell our client. | ||
1182 | * | ||
1183 | * @param c client that lost a channel | ||
1184 | * @param ccn channel identification number for the client | ||
1185 | * @param ch the channel object | ||
1186 | */ | ||
1187 | void | ||
1188 | GSC_handle_remote_channel_destroy (struct CadetClient *c, | ||
1189 | struct GNUNET_CADET_ClientChannelNumber ccn, | ||
1190 | struct CadetChannel *ch) | ||
1191 | { | ||
1192 | struct GNUNET_MQ_Envelope *env; | ||
1193 | struct GNUNET_CADET_LocalChannelDestroyMessage *tdm; | ||
1194 | |||
1195 | env = GNUNET_MQ_msg (tdm, | ||
1196 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); | ||
1197 | tdm->ccn = ccn; | ||
1198 | GSC_send_to_client (c, | ||
1199 | env); | ||
1200 | GNUNET_assert (GNUNET_YES == | ||
1201 | GNUNET_CONTAINER_multihashmap32_remove (c->channels, | ||
1202 | ntohl (ccn.channel_of_client), | ||
1203 | ch)); | ||
1204 | } | ||
1205 | |||
1206 | |||
1207 | /** | ||
1208 | * A client that created a loose channel that was not bound to a port | ||
1209 | * disconnected, drop it from the #loose_channels list. | ||
1210 | * | ||
1211 | * @param port the port the channel was trying to bind to | ||
1212 | * @param ch the channel that was lost | ||
1213 | */ | ||
1214 | void | ||
1215 | GSC_drop_loose_channel (const struct GNUNET_HashCode *port, | ||
1216 | struct CadetChannel *ch) | ||
1217 | { | ||
1218 | GNUNET_assert (GNUNET_YES == | ||
1219 | GNUNET_CONTAINER_multihashmap_remove (loose_channels, | ||
1220 | port, | ||
1221 | ch)); | ||
1222 | } | ||
1223 | |||
1224 | |||
1225 | /** | ||
1226 | * Iterator for deleting each channel whose client endpoint disconnected. | ||
1227 | * | ||
1228 | * @param cls Closure (client that has disconnected). | ||
1229 | * @param key The local channel id in host byte order | ||
1230 | * @param value The value stored at the key (channel to destroy). | ||
1231 | * @return #GNUNET_OK, keep iterating. | ||
1232 | */ | ||
1233 | static int | ||
1234 | channel_destroy_iterator (void *cls, | ||
1235 | uint32_t key, | ||
1236 | void *value) | ||
1237 | { | ||
1238 | struct CadetClient *c = cls; | ||
1239 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
1240 | struct CadetChannel *ch = value; | ||
1241 | |||
1242 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1243 | "Destroying %s, due to %s disconnecting.\n", | ||
1244 | GCCH_2s (ch), | ||
1245 | GSC_2s (c)); | ||
1246 | ccn.channel_of_client = htonl (key); | ||
1247 | GCCH_channel_local_destroy (ch, | ||
1248 | c, | ||
1249 | ccn); | ||
1250 | GNUNET_assert (GNUNET_YES == | ||
1251 | GNUNET_CONTAINER_multihashmap32_remove (c->channels, | ||
1252 | key, | ||
1253 | ch)); | ||
1254 | return GNUNET_OK; | ||
1255 | } | ||
1256 | |||
1257 | |||
1258 | /** | ||
1259 | * Remove client's ports from the global hashmap on disconnect. | ||
1260 | * | ||
1261 | * @param cls Closure (unused). | ||
1262 | * @param key the port. | ||
1263 | * @param value the `struct CadetClient` to remove | ||
1264 | * @return #GNUNET_OK, keep iterating. | ||
1265 | */ | ||
1266 | static int | ||
1267 | client_release_ports (void *cls, | ||
1268 | const struct GNUNET_HashCode *key, | ||
1269 | void *value) | ||
1270 | { | ||
1271 | struct CadetClient *c = value; | ||
1272 | |||
1273 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1274 | "Closing port %s due to %s disconnect.\n", | ||
1275 | GNUNET_h2s (key), | ||
1276 | GSC_2s (c)); | ||
1277 | GNUNET_assert (GNUNET_YES == | ||
1278 | GNUNET_CONTAINER_multihashmap_remove (open_ports, | ||
1279 | key, | ||
1280 | value)); | ||
1281 | GNUNET_assert (GNUNET_YES == | ||
1282 | GNUNET_CONTAINER_multihashmap_remove (c->ports, | ||
1283 | key, | ||
1284 | value)); | ||
1285 | return GNUNET_OK; | ||
1286 | } | ||
1287 | |||
1288 | |||
1289 | /** | ||
1290 | * Callback called when a client disconnected from the service | ||
1291 | * | ||
1292 | * @param cls closure for the service | ||
1293 | * @param client the client that disconnected | ||
1294 | * @param internal_cls should be equal to @a c | ||
1295 | */ | ||
1296 | static void | ||
1297 | client_disconnect_cb (void *cls, | ||
1298 | struct GNUNET_SERVICE_Client *client, | ||
1299 | void *internal_cls) | ||
1300 | { | ||
1301 | struct CadetClient *c = internal_cls; | ||
1302 | |||
1303 | GNUNET_assert (c->client == client); | ||
1304 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1305 | "%s is disconnecting.\n", | ||
1306 | GSC_2s (c)); | ||
1307 | if (NULL != c->channels) | ||
1308 | { | ||
1309 | GNUNET_CONTAINER_multihashmap32_iterate (c->channels, | ||
1310 | &channel_destroy_iterator, | ||
1311 | c); | ||
1312 | GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->channels)); | ||
1313 | GNUNET_CONTAINER_multihashmap32_destroy (c->channels); | ||
1314 | } | ||
1315 | if (NULL != c->ports) | ||
1316 | { | ||
1317 | GNUNET_CONTAINER_multihashmap_iterate (c->ports, | ||
1318 | &client_release_ports, | ||
1319 | c); | ||
1320 | GNUNET_CONTAINER_multihashmap_destroy (c->ports); | ||
1321 | } | ||
1322 | GNUNET_CONTAINER_DLL_remove (clients_head, | ||
1323 | clients_tail, | ||
1324 | c); | ||
1325 | GNUNET_STATISTICS_update (stats, | ||
1326 | "# clients", | ||
1327 | -1, | ||
1328 | GNUNET_NO); | ||
1329 | GNUNET_free (c); | ||
1330 | if ( (NULL == clients_head) && | ||
1331 | (GNUNET_YES == shutting_down) ) | ||
1332 | shutdown_rest (); | ||
1333 | } | ||
1334 | |||
1335 | |||
1336 | /** | ||
1337 | * Setup CADET internals. | ||
1338 | * | ||
1339 | * @param cls closure | ||
1340 | * @param server the initialized server | ||
1341 | * @param c configuration to use | ||
1342 | */ | ||
1343 | static void | ||
1344 | run (void *cls, | ||
1345 | const struct GNUNET_CONFIGURATION_Handle *c, | ||
1346 | struct GNUNET_SERVICE_Handle *service) | ||
1347 | { | ||
1348 | cfg = c; | ||
1349 | if (GNUNET_OK != | ||
1350 | GNUNET_CONFIGURATION_get_value_number (c, | ||
1351 | "CADET", | ||
1352 | "RATCHET_MESSAGES", | ||
1353 | &ratchet_messages)) | ||
1354 | { | ||
1355 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1356 | "CADET", | ||
1357 | "RATCHET_MESSAGES", | ||
1358 | "needs to be a number"); | ||
1359 | ratchet_messages = 64; | ||
1360 | } | ||
1361 | if (GNUNET_OK != | ||
1362 | GNUNET_CONFIGURATION_get_value_time (c, | ||
1363 | "CADET", | ||
1364 | "RATCHET_TIME", | ||
1365 | &ratchet_time)) | ||
1366 | { | ||
1367 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1368 | "CADET", | ||
1369 | "RATCHET_TIME", | ||
1370 | "need delay value"); | ||
1371 | ratchet_time = GNUNET_TIME_UNIT_HOURS; | ||
1372 | } | ||
1373 | if (GNUNET_OK != | ||
1374 | GNUNET_CONFIGURATION_get_value_time (c, | ||
1375 | "CADET", | ||
1376 | "REFRESH_CONNECTION_TIME", | ||
1377 | &keepalive_period)) | ||
1378 | { | ||
1379 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1380 | "CADET", | ||
1381 | "REFRESH_CONNECTION_TIME", | ||
1382 | "need delay value"); | ||
1383 | keepalive_period = GNUNET_TIME_UNIT_MINUTES; | ||
1384 | } | ||
1385 | if (GNUNET_OK != | ||
1386 | GNUNET_CONFIGURATION_get_value_number (c, | ||
1387 | "CADET", | ||
1388 | "DROP_PERCENT", | ||
1389 | &drop_percent)) | ||
1390 | { | ||
1391 | drop_percent = 0; | ||
1392 | } | ||
1393 | else | ||
1394 | { | ||
1395 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1396 | LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n"); | ||
1397 | LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n"); | ||
1398 | LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n"); | ||
1399 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1400 | } | ||
1401 | my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c); | ||
1402 | if (NULL == my_private_key) | ||
1403 | { | ||
1404 | GNUNET_break (0); | ||
1405 | GNUNET_SCHEDULER_shutdown (); | ||
1406 | return; | ||
1407 | } | ||
1408 | GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, | ||
1409 | &my_full_id.public_key); | ||
1410 | stats = GNUNET_STATISTICS_create ("cadet", | ||
1411 | c); | ||
1412 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, | ||
1413 | NULL); | ||
1414 | ats_ch = GNUNET_ATS_connectivity_init (c); | ||
1415 | /* FIXME: optimize code to allow GNUNET_YES here! */ | ||
1416 | open_ports = GNUNET_CONTAINER_multihashmap_create (16, | ||
1417 | GNUNET_NO); | ||
1418 | loose_channels = GNUNET_CONTAINER_multihashmap_create (16, | ||
1419 | GNUNET_NO); | ||
1420 | peers = GNUNET_CONTAINER_multipeermap_create (16, | ||
1421 | GNUNET_YES); | ||
1422 | connections = GNUNET_CONTAINER_multishortmap_create (256, | ||
1423 | GNUNET_YES); | ||
1424 | GCH_init (c); | ||
1425 | GCD_init (c); | ||
1426 | GCO_init (c); | ||
1427 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1428 | "CADET started for peer %s\n", | ||
1429 | GNUNET_i2s (&my_full_id)); | ||
1430 | |||
1431 | } | ||
1432 | |||
1433 | |||
1434 | /** | ||
1435 | * Define "main" method using service macro. | ||
1436 | */ | ||
1437 | GNUNET_SERVICE_MAIN | ||
1438 | ("cadet", | ||
1439 | GNUNET_SERVICE_OPTION_NONE, | ||
1440 | &run, | ||
1441 | &client_connect_cb, | ||
1442 | &client_disconnect_cb, | ||
1443 | NULL, | ||
1444 | GNUNET_MQ_hd_fixed_size (port_open, | ||
1445 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN, | ||
1446 | struct GNUNET_CADET_PortMessage, | ||
1447 | NULL), | ||
1448 | GNUNET_MQ_hd_fixed_size (port_close, | ||
1449 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE, | ||
1450 | struct GNUNET_CADET_PortMessage, | ||
1451 | NULL), | ||
1452 | GNUNET_MQ_hd_fixed_size (channel_create, | ||
1453 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE, | ||
1454 | struct GNUNET_CADET_LocalChannelCreateMessage, | ||
1455 | NULL), | ||
1456 | GNUNET_MQ_hd_fixed_size (channel_destroy, | ||
1457 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY, | ||
1458 | struct GNUNET_CADET_LocalChannelDestroyMessage, | ||
1459 | NULL), | ||
1460 | GNUNET_MQ_hd_var_size (local_data, | ||
1461 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, | ||
1462 | struct GNUNET_CADET_LocalData, | ||
1463 | NULL), | ||
1464 | GNUNET_MQ_hd_fixed_size (local_ack, | ||
1465 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK, | ||
1466 | struct GNUNET_CADET_LocalAck, | ||
1467 | NULL), | ||
1468 | GNUNET_MQ_hd_fixed_size (get_peers, | ||
1469 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS, | ||
1470 | struct GNUNET_MessageHeader, | ||
1471 | NULL), | ||
1472 | GNUNET_MQ_hd_fixed_size (show_peer, | ||
1473 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER, | ||
1474 | struct GNUNET_CADET_LocalInfo, | ||
1475 | NULL), | ||
1476 | GNUNET_MQ_hd_fixed_size (info_tunnels, | ||
1477 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS, | ||
1478 | struct GNUNET_MessageHeader, | ||
1479 | NULL), | ||
1480 | GNUNET_MQ_hd_fixed_size (info_tunnel, | ||
1481 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL, | ||
1482 | struct GNUNET_CADET_LocalInfo, | ||
1483 | NULL), | ||
1484 | GNUNET_MQ_hd_fixed_size (info_dump, | ||
1485 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP, | ||
1486 | struct GNUNET_MessageHeader, | ||
1487 | NULL), | ||
1488 | GNUNET_MQ_handler_end ()); | ||
1489 | |||
1490 | /* 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 8769601c2..000000000 --- a/src/cadet/gnunet-service-cadet-new_channel.c +++ /dev/null | |||
@@ -1,2037 +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 | */ | ||
81 | enum 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 | */ | ||
111 | struct 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 | */ | ||
177 | struct 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 | */ | ||
208 | struct 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 | */ | ||
251 | struct 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 | */ | ||
392 | const char * | ||
393 | GCCH_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 | */ | ||
418 | struct GNUNET_CADET_ChannelTunnelNumber | ||
419 | GCCH_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 | */ | ||
430 | static void | ||
431 | free_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 | */ | ||
453 | static void | ||
454 | channel_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 | */ | ||
513 | static void | ||
514 | send_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 | */ | ||
525 | static void | ||
526 | channel_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 | */ | ||
551 | static void | ||
552 | send_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 | */ | ||
595 | void | ||
596 | GCCH_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 | */ | ||
618 | struct CadetChannel * | ||
619 | GCCH_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 | */ | ||
696 | static void | ||
697 | timeout_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 | */ | ||
719 | struct CadetChannel * | ||
720 | GCCH_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 | */ | ||
784 | static void | ||
785 | send_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 | */ | ||
800 | static void | ||
801 | send_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 | */ | ||
832 | static void | ||
833 | send_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 | */ | ||
863 | void | ||
864 | GCCH_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 | */ | ||
897 | static void | ||
898 | send_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 | */ | ||
936 | void | ||
937 | GCCH_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 | */ | ||
1008 | static void | ||
1009 | signal_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 | */ | ||
1032 | void | ||
1033 | GCCH_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 | */ | ||
1118 | void | ||
1119 | GCCH_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 | */ | ||
1176 | static int | ||
1177 | is_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 | */ | ||
1210 | void | ||
1211 | GCCH_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 | */ | ||
1415 | static void | ||
1416 | data_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 | */ | ||
1426 | static void | ||
1427 | retry_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 | */ | ||
1454 | static void | ||
1455 | handle_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 | */ | ||
1503 | void | ||
1504 | GCCH_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 | */ | ||
1604 | void | ||
1605 | GCCH_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 | */ | ||
1646 | static int | ||
1647 | cmp_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 | */ | ||
1668 | static void | ||
1669 | data_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 | */ | ||
1762 | int | ||
1763 | GCCH_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 | ld->ccn = receiver->ccn; | ||
1812 | GNUNET_memcpy (&ld[1], | ||
1813 | buf, | ||
1814 | buf_len); | ||
1815 | if (GNUNET_YES == receiver->client_ready) | ||
1816 | { | ||
1817 | ch->pending_messages--; | ||
1818 | GSC_send_to_client (receiver->c, | ||
1819 | env); | ||
1820 | send_ack_to_client (ch, | ||
1821 | ack_to_owner); | ||
1822 | } | ||
1823 | else | ||
1824 | { | ||
1825 | struct CadetOutOfOrderMessage *oom; | ||
1826 | |||
1827 | oom = GNUNET_new (struct CadetOutOfOrderMessage); | ||
1828 | oom->env = env; | ||
1829 | GNUNET_CONTAINER_DLL_insert_tail (receiver->head_recv, | ||
1830 | receiver->tail_recv, | ||
1831 | oom); | ||
1832 | receiver->num_recv++; | ||
1833 | } | ||
1834 | return GNUNET_OK; | ||
1835 | } | ||
1836 | |||
1837 | /* Everything is correct, send the message. */ | ||
1838 | crm = GNUNET_malloc (sizeof (*crm)); | ||
1839 | crm->ch = ch; | ||
1840 | crm->data_message = GNUNET_malloc (sizeof (struct GNUNET_CADET_ChannelAppDataMessage) | ||
1841 | + buf_len); | ||
1842 | crm->data_message->header.size = htons (sizeof (struct GNUNET_CADET_ChannelAppDataMessage) + buf_len); | ||
1843 | crm->data_message->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA); | ||
1844 | ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1); | ||
1845 | crm->data_message->mid = ch->mid_send; | ||
1846 | crm->data_message->ctn = ch->ctn; | ||
1847 | GNUNET_memcpy (&crm->data_message[1], | ||
1848 | buf, | ||
1849 | buf_len); | ||
1850 | GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent, | ||
1851 | ch->tail_sent, | ||
1852 | crm); | ||
1853 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1854 | "Sending message %u from local client to %s with %u bytes\n", | ||
1855 | ntohl (crm->data_message->mid.mid), | ||
1856 | GCCH_2s (ch), | ||
1857 | buf_len); | ||
1858 | if (NULL != ch->retry_data_task) | ||
1859 | { | ||
1860 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
1861 | ch->retry_data_task = NULL; | ||
1862 | } | ||
1863 | crm->qe = GCT_send (ch->t, | ||
1864 | &crm->data_message->header, | ||
1865 | &data_sent_cb, | ||
1866 | crm); | ||
1867 | GNUNET_assert (NULL == ch->retry_data_task); | ||
1868 | return GNUNET_OK; | ||
1869 | } | ||
1870 | |||
1871 | |||
1872 | /** | ||
1873 | * Handle ACK from client on local channel. Means the client is ready | ||
1874 | * for more data, see if we have any for it. | ||
1875 | * | ||
1876 | * @param ch channel to destroy | ||
1877 | * @param client_ccn ccn of the client sending the ack | ||
1878 | */ | ||
1879 | void | ||
1880 | GCCH_handle_local_ack (struct CadetChannel *ch, | ||
1881 | struct GNUNET_CADET_ClientChannelNumber client_ccn) | ||
1882 | { | ||
1883 | struct CadetChannelClient *ccc; | ||
1884 | struct CadetOutOfOrderMessage *com; | ||
1885 | |||
1886 | if ( (NULL != ch->owner) && | ||
1887 | (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client) ) | ||
1888 | ccc = ch->owner; | ||
1889 | else if ( (NULL != ch->dest) && | ||
1890 | (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client) ) | ||
1891 | ccc = ch->dest; | ||
1892 | else | ||
1893 | GNUNET_assert (0); | ||
1894 | ccc->client_ready = GNUNET_YES; | ||
1895 | com = ccc->head_recv; | ||
1896 | if (NULL == com) | ||
1897 | { | ||
1898 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1899 | "Got LOCAL_ACK, %s-%X ready to receive more data, but none pending on %s-%X(%p)!\n", | ||
1900 | GSC_2s (ccc->c), | ||
1901 | ntohl (client_ccn.channel_of_client), | ||
1902 | GCCH_2s (ch), | ||
1903 | ntohl (ccc->ccn.channel_of_client), | ||
1904 | ccc); | ||
1905 | return; /* none pending */ | ||
1906 | } | ||
1907 | if (GNUNET_YES == ch->is_loopback) | ||
1908 | { | ||
1909 | int to_owner; | ||
1910 | |||
1911 | /* Messages are always in-order, just send */ | ||
1912 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, | ||
1913 | ccc->tail_recv, | ||
1914 | com); | ||
1915 | ccc->num_recv--; | ||
1916 | GSC_send_to_client (ccc->c, | ||
1917 | com->env); | ||
1918 | /* Notify sender that we can receive more */ | ||
1919 | if (ccc->ccn.channel_of_client == | ||
1920 | ch->owner->ccn.channel_of_client) | ||
1921 | { | ||
1922 | to_owner = GNUNET_NO; | ||
1923 | } | ||
1924 | else | ||
1925 | { | ||
1926 | GNUNET_assert (ccc->ccn.channel_of_client == | ||
1927 | ch->dest->ccn.channel_of_client); | ||
1928 | to_owner = GNUNET_YES; | ||
1929 | } | ||
1930 | send_ack_to_client (ch, | ||
1931 | to_owner); | ||
1932 | GNUNET_free (com); | ||
1933 | return; | ||
1934 | } | ||
1935 | |||
1936 | if ( (com->mid.mid != ch->mid_recv.mid) && | ||
1937 | (GNUNET_NO == ch->out_of_order) && | ||
1938 | (GNUNET_YES == ch->reliable) ) | ||
1939 | { | ||
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 */ | ||
1947 | } | ||
1948 | |||
1949 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1950 | "Got LOCAL_ACK, giving payload message %u to %s-%X on %s\n", | ||
1951 | ntohl (com->mid.mid), | ||
1952 | GSC_2s (ccc->c), | ||
1953 | ntohl (ccc->ccn.channel_of_client), | ||
1954 | GCCH_2s (ch)); | ||
1955 | |||
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); | ||
1978 | } | ||
1979 | |||
1980 | |||
1981 | #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-chn",__VA_ARGS__) | ||
1982 | |||
1983 | |||
1984 | /** | ||
1985 | * Log channel info. | ||
1986 | * | ||
1987 | * @param ch Channel. | ||
1988 | * @param level Debug level to use. | ||
1989 | */ | ||
1990 | void | ||
1991 | GCCH_debug (struct CadetChannel *ch, | ||
1992 | enum GNUNET_ErrorType level) | ||
1993 | { | ||
1994 | int do_log; | ||
1995 | |||
1996 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | ||
1997 | "cadet-chn", | ||
1998 | __FILE__, __FUNCTION__, __LINE__); | ||
1999 | if (0 == do_log) | ||
2000 | return; | ||
2001 | |||
2002 | if (NULL == ch) | ||
2003 | { | ||
2004 | LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n"); | ||
2005 | return; | ||
2006 | } | ||
2007 | LOG2 (level, | ||
2008 | "CHN %s:%X (%p)\n", | ||
2009 | GCT_2s (ch->t), | ||
2010 | ch->ctn, | ||
2011 | ch); | ||
2012 | if (NULL != ch->owner) | ||
2013 | { | ||
2014 | LOG2 (level, | ||
2015 | "CHN origin %s ready %s local-id: %u\n", | ||
2016 | GSC_2s (ch->owner->c), | ||
2017 | ch->owner->client_ready ? "YES" : "NO", | ||
2018 | ntohl (ch->owner->ccn.channel_of_client)); | ||
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)); | ||
2033 | } | ||
2034 | |||
2035 | |||
2036 | |||
2037 | /* 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 | */ | ||
44 | struct 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 | */ | ||
54 | const char * | ||
55 | GCCH_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 | */ | ||
64 | void | ||
65 | GCCH_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 | */ | ||
76 | struct GNUNET_CADET_ChannelTunnelNumber | ||
77 | GCCH_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 | */ | ||
90 | struct CadetChannel * | ||
91 | GCCH_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 | */ | ||
106 | void | ||
107 | GCCH_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 | */ | ||
119 | void | ||
120 | GCCH_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 | */ | ||
135 | void | ||
136 | GCCH_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 | */ | ||
149 | struct CadetChannel * | ||
150 | GCCH_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 | */ | ||
164 | void | ||
165 | GCCH_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 | */ | ||
177 | void | ||
178 | GCCH_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 | */ | ||
191 | void | ||
192 | GCCH_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 | */ | ||
205 | void | ||
206 | GCCH_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 | */ | ||
226 | void | ||
227 | GCCH_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 | */ | ||
245 | int | ||
246 | GCCH_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 | */ | ||
258 | void | ||
259 | GCCH_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 | */ | ||
46 | enum 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 | */ | ||
80 | struct 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 | */ | ||
177 | struct CadetConnection * | ||
178 | GCC_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 | */ | ||
193 | static void | ||
194 | update_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 | */ | ||
222 | static void | ||
223 | GCC_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 | */ | ||
268 | void | ||
269 | GCC_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 | */ | ||
287 | void | ||
288 | GCC_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 | */ | ||
315 | struct CadetTConnection * | ||
316 | GCC_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 | */ | ||
328 | const struct CadetConnectionMetrics * | ||
329 | GCC_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 | */ | ||
341 | static void | ||
342 | send_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 | */ | ||
353 | static void | ||
354 | keepalive_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 | */ | ||
374 | static void | ||
375 | send_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 | */ | ||
417 | void | ||
418 | GCC_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 | */ | ||
437 | void | ||
438 | GCC_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 | */ | ||
457 | void | ||
458 | GCC_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 | */ | ||
492 | void | ||
493 | GCC_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 | */ | ||
526 | void | ||
527 | GCC_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 | */ | ||
550 | void | ||
551 | GCC_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 | */ | ||
574 | void | ||
575 | GCC_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 | */ | ||
599 | static void | ||
600 | send_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 | */ | ||
638 | static void | ||
639 | send_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 | */ | ||
670 | void | ||
671 | GCC_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 | */ | ||
711 | static void | ||
712 | manage_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 | */ | ||
800 | static struct CadetConnection * | ||
801 | connection_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 | */ | ||
863 | struct CadetConnection * | ||
864 | GCC_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 | */ | ||
945 | struct CadetConnection * | ||
946 | GCC_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 | */ | ||
981 | void | ||
982 | GCC_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 | */ | ||
1008 | struct CadetPeerPath * | ||
1009 | GCC_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 | */ | ||
1021 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | ||
1022 | GCC_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 | */ | ||
1033 | const char * | ||
1034 | GCC_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 | */ | ||
1067 | void | ||
1068 | GCC_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 | */ | ||
47 | typedef 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 | */ | ||
60 | void | ||
61 | GCC_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 | */ | ||
71 | void | ||
72 | GCC_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 | */ | ||
81 | struct CadetConnection * | ||
82 | GCC_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 | */ | ||
98 | struct CadetConnection * | ||
99 | GCC_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 | */ | ||
122 | struct CadetConnection * | ||
123 | GCC_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 | */ | ||
144 | void | ||
145 | GCC_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 | */ | ||
154 | void | ||
155 | GCC_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 | */ | ||
165 | void | ||
166 | GCC_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 | */ | ||
175 | void | ||
176 | GCC_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 | */ | ||
186 | void | ||
187 | GCC_handle_kx_auth (struct CadetConnection *cc, | ||
188 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg); | ||
189 | |||
190 | |||
191 | /** | ||
192 | * Performance metrics for a connection. | ||
193 | */ | ||
194 | struct 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 | */ | ||
239 | const struct CadetConnectionMetrics * | ||
240 | GCC_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 | */ | ||
249 | void | ||
250 | GCC_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 | */ | ||
260 | void | ||
261 | GCC_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 | */ | ||
272 | void | ||
273 | GCC_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 | */ | ||
284 | void | ||
285 | GCC_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 | */ | ||
295 | struct CadetTConnection * | ||
296 | GCC_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 | */ | ||
305 | struct CadetPeerPath * | ||
306 | GCC_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 | */ | ||
315 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | ||
316 | GCC_get_id (struct CadetConnection *cc); | ||
317 | |||
318 | |||
319 | /** | ||
320 | * Get a (static) string for a connection. | ||
321 | * | ||
322 | * @param cc Connection. | ||
323 | */ | ||
324 | const char * | ||
325 | GCC_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 | */ | ||
334 | void | ||
335 | GCC_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 | */ | ||
59 | struct 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 | */ | ||
72 | static struct GNUNET_DHT_Handle *dht_handle; | ||
73 | |||
74 | /** | ||
75 | * How often to PUT own ID in the DHT. | ||
76 | */ | ||
77 | static struct GNUNET_TIME_Relative id_announce_time; | ||
78 | |||
79 | /** | ||
80 | * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put(). | ||
81 | */ | ||
82 | static unsigned long long dht_replication_level; | ||
83 | |||
84 | /** | ||
85 | * Task to periodically announce itself in the network. | ||
86 | */ | ||
87 | static struct GNUNET_SCHEDULER_Task *announce_id_task; | ||
88 | |||
89 | /** | ||
90 | * Delay for the next ID announce. | ||
91 | */ | ||
92 | static 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 | */ | ||
111 | static void | ||
112 | dht_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 | */ | ||
149 | static void | ||
150 | announce_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 | */ | ||
217 | void | ||
218 | GCD_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 | */ | ||
235 | void | ||
236 | GCD_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 | */ | ||
278 | void | ||
279 | GCD_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 | */ | ||
300 | struct GCD_search_handle * | ||
301 | GCD_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 | */ | ||
341 | void | ||
342 | GCD_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 | ||
33 | extern "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 | */ | ||
46 | struct GCD_search_handle; | ||
47 | |||
48 | |||
49 | /** | ||
50 | * Initialize the DHT subsystem. | ||
51 | * | ||
52 | * @param c Configuration. | ||
53 | */ | ||
54 | void | ||
55 | GCD_init (const struct GNUNET_CONFIGURATION_Handle *c); | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Shut down the DHT subsystem. | ||
60 | */ | ||
61 | void | ||
62 | GCD_shutdown (void); | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Function called by the HELLO subsystem whenever OUR hello | ||
67 | * changes. Re-triggers the DHT PUT immediately. | ||
68 | */ | ||
69 | void | ||
70 | GCD_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 | */ | ||
78 | struct GCD_search_handle * | ||
79 | GCD_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 | */ | ||
87 | void | ||
88 | GCD_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 | */ | ||
46 | static struct GNUNET_HELLO_Message *mine; | ||
47 | |||
48 | /** | ||
49 | * Handle to peerinfo service. | ||
50 | */ | ||
51 | static struct GNUNET_PEERINFO_Handle *peerinfo; | ||
52 | |||
53 | /** | ||
54 | * Iterator context. | ||
55 | */ | ||
56 | static 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 | */ | ||
67 | static void | ||
68 | got_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 | */ | ||
105 | void | ||
106 | GCH_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 | */ | ||
120 | void | ||
121 | GCH_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 | */ | ||
146 | const struct GNUNET_HELLO_Message * | ||
147 | GCH_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 | ||
34 | extern "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 | */ | ||
51 | void | ||
52 | GCH_init (const struct GNUNET_CONFIGURATION_Handle *c); | ||
53 | |||
54 | |||
55 | /** | ||
56 | * Shut down the hello subsystem. | ||
57 | */ | ||
58 | void | ||
59 | GCH_shutdown (void); | ||
60 | |||
61 | |||
62 | /** | ||
63 | * Get own hello message. | ||
64 | * | ||
65 | * @return Own hello message. | ||
66 | */ | ||
67 | const struct GNUNET_HELLO_Message * | ||
68 | GCH_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 350c8efae..000000000 --- a/src/cadet/gnunet-service-cadet-new_peer.c +++ /dev/null | |||
@@ -1,1477 +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 | */ | ||
70 | struct 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 | */ | ||
109 | struct 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 | */ | ||
240 | const char * | ||
241 | GCP_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 | */ | ||
268 | double | ||
269 | GCP_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 | */ | ||
319 | static void | ||
320 | destroy_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 | */ | ||
385 | static void | ||
386 | consider_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 | */ | ||
452 | static void | ||
453 | consider_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 | */ | ||
462 | static void | ||
463 | drop_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 | */ | ||
480 | static void | ||
481 | consider_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 | */ | ||
527 | void | ||
528 | GCP_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 | */ | ||
591 | static int | ||
592 | should_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 | */ | ||
609 | static void | ||
610 | mqm_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 | */ | ||
618 | static void | ||
619 | mqm_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 | */ | ||
670 | static void | ||
671 | send_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 | */ | ||
692 | static void | ||
693 | mqm_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 | */ | ||
711 | void | ||
712 | GCP_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 | */ | ||
747 | static int | ||
748 | destroy_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 | */ | ||
769 | void | ||
770 | GCP_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 | */ | ||
786 | void | ||
787 | GCP_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 | */ | ||
809 | void | ||
810 | GCP_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 | */ | ||
869 | void | ||
870 | GCP_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 | */ | ||
905 | static void | ||
906 | path_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 | 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 | } | ||
931 | } | ||
932 | |||
933 | |||
934 | /** | ||
935 | * Try adding a @a path to this @a peer. If the peer already | ||
936 | * has plenty of paths, return NULL. | ||
937 | * | ||
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. | ||
944 | */ | ||
945 | struct GNUNET_CONTAINER_HeapNode * | ||
946 | GCP_attach_path (struct CadetPeer *cp, | ||
947 | struct CadetPeerPath *path, | ||
948 | unsigned int off, | ||
949 | int force) | ||
950 | { | ||
951 | GNUNET_CONTAINER_HeapCostType desirability; | ||
952 | struct CadetPeerPath *root; | ||
953 | GNUNET_CONTAINER_HeapCostType root_desirability; | ||
954 | struct GNUNET_CONTAINER_HeapNode *hn; | ||
955 | |||
956 | GNUNET_assert (off == GCPP_get_length (path) - 1); | ||
957 | GNUNET_assert (cp == GCPP_get_peer_at_offset (path, | ||
958 | off)); | ||
959 | if (NULL == cp->path_heap) | ||
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)) | ||
973 | { | ||
974 | root = NULL; | ||
975 | root_desirability = 0; | ||
976 | } | ||
977 | |||
978 | if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) && | ||
979 | (desirability < root_desirability) ) | ||
980 | { | ||
981 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
982 | "Decided to not attach path %p to peer %s due to undesirability\n", | ||
983 | GCPP_2s (path), | ||
984 | GCP_2s (cp)); | ||
985 | return NULL; | ||
986 | } | ||
987 | } | ||
988 | |||
989 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
990 | "Attaching path %s to peer %s (%s)\n", | ||
991 | GCPP_2s (path), | ||
992 | GCP_2s (cp), | ||
993 | (GNUNET_NO == force) ? "desirable" : "forced"); | ||
994 | |||
995 | /* Yes, we'd like to add this path, add to our heap */ | ||
996 | hn = GNUNET_CONTAINER_heap_insert (cp->path_heap, | ||
997 | path, | ||
998 | desirability); | ||
999 | |||
1000 | /* Consider maybe dropping other paths because of the new one */ | ||
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; | ||
1007 | } | ||
1008 | |||
1009 | |||
1010 | /** | ||
1011 | * This peer can no longer own @a path as the path | ||
1012 | * has been extended and a peer further down the line | ||
1013 | * is now the new owner. | ||
1014 | * | ||
1015 | * @param cp old owner of the @a path | ||
1016 | * @param path path where the ownership is lost | ||
1017 | * @param hn note in @a cp's path heap that must be deleted | ||
1018 | */ | ||
1019 | void | ||
1020 | GCP_detach_path (struct CadetPeer *cp, | ||
1021 | struct CadetPeerPath *path, | ||
1022 | struct GNUNET_CONTAINER_HeapNode *hn) | ||
1023 | { | ||
1024 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1025 | "Detatching path %s from peer %s\n", | ||
1026 | GCPP_2s (path), | ||
1027 | GCP_2s (cp)); | ||
1028 | GNUNET_assert (path == | ||
1029 | GNUNET_CONTAINER_heap_remove_node (hn)); | ||
1030 | } | ||
1031 | |||
1032 | |||
1033 | /** | ||
1034 | * Add a @a connection to this @a cp. | ||
1035 | * | ||
1036 | * @param cp peer via which the @a connection goes | ||
1037 | * @param cc the connection to add | ||
1038 | */ | ||
1039 | void | ||
1040 | GCP_add_connection (struct CadetPeer *cp, | ||
1041 | struct CadetConnection *cc) | ||
1042 | { | ||
1043 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1044 | "Adding connection %s to peer %s\n", | ||
1045 | GCC_2s (cc), | ||
1046 | GCP_2s (cp)); | ||
1047 | GNUNET_assert (GNUNET_OK == | ||
1048 | GNUNET_CONTAINER_multishortmap_put (cp->connections, | ||
1049 | &GCC_get_id (cc)->connection_of_tunnel, | ||
1050 | cc, | ||
1051 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1052 | if (NULL != cp->destroy_task) | ||
1053 | { | ||
1054 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
1055 | cp->destroy_task = NULL; | ||
1056 | } | ||
1057 | } | ||
1058 | |||
1059 | |||
1060 | /** | ||
1061 | * Remove a @a connection that went via this @a cp. | ||
1062 | * | ||
1063 | * @param cp peer via which the @a connection went | ||
1064 | * @param cc the connection to remove | ||
1065 | */ | ||
1066 | void | ||
1067 | GCP_remove_connection (struct CadetPeer *cp, | ||
1068 | struct CadetConnection *cc) | ||
1069 | { | ||
1070 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1071 | "Removing connection %s from peer %s\n", | ||
1072 | GCC_2s (cc), | ||
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); | ||
1079 | } | ||
1080 | |||
1081 | |||
1082 | /** | ||
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. | ||
1086 | * | ||
1087 | * @param peer_id Full identity of the peer. | ||
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 | ||
1092 | */ | ||
1093 | struct CadetPeer * | ||
1094 | GCP_get (const struct GNUNET_PeerIdentity *peer_id, | ||
1095 | int create) | ||
1096 | { | ||
1097 | struct CadetPeer *cp; | ||
1098 | |||
1099 | cp = GNUNET_CONTAINER_multipeermap_get (peers, | ||
1100 | peer_id); | ||
1101 | if (NULL != cp) | ||
1102 | return cp; | ||
1103 | if (GNUNET_NO == create) | ||
1104 | return NULL; | ||
1105 | cp = GNUNET_new (struct CadetPeer); | ||
1106 | cp->pid = *peer_id; | ||
1107 | cp->connections = GNUNET_CONTAINER_multishortmap_create (32, | ||
1108 | GNUNET_YES); | ||
1109 | cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); | ||
1110 | GNUNET_assert (GNUNET_YES == | ||
1111 | GNUNET_CONTAINER_multipeermap_put (peers, | ||
1112 | &cp->pid, | ||
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; | ||
1119 | } | ||
1120 | |||
1121 | |||
1122 | /** | ||
1123 | * Obtain the peer identity for a `struct CadetPeer`. | ||
1124 | * | ||
1125 | * @param cp our peer handle | ||
1126 | * @return the peer identity | ||
1127 | */ | ||
1128 | const struct GNUNET_PeerIdentity * | ||
1129 | GCP_get_id (struct CadetPeer *cp) | ||
1130 | { | ||
1131 | return &cp->pid; | ||
1132 | } | ||
1133 | |||
1134 | |||
1135 | /** | ||
1136 | * Iterate over all known peers. | ||
1137 | * | ||
1138 | * @param iter Iterator. | ||
1139 | * @param cls Closure for @c iter. | ||
1140 | */ | ||
1141 | void | ||
1142 | GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, | ||
1143 | void *cls) | ||
1144 | { | ||
1145 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
1146 | iter, | ||
1147 | cls); | ||
1148 | } | ||
1149 | |||
1150 | |||
1151 | /** | ||
1152 | * Count the number of known paths toward the peer. | ||
1153 | * | ||
1154 | * @param cp Peer to get path info. | ||
1155 | * @return Number of known paths. | ||
1156 | */ | ||
1157 | unsigned int | ||
1158 | GCP_count_paths (const struct CadetPeer *cp) | ||
1159 | { | ||
1160 | return cp->num_paths; | ||
1161 | } | ||
1162 | |||
1163 | |||
1164 | /** | ||
1165 | * Iterate over the paths to a peer. | ||
1166 | * | ||
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. | ||
1171 | */ | ||
1172 | unsigned int | ||
1173 | GCP_iterate_paths (struct CadetPeer *cp, | ||
1174 | GCP_PathIterator callback, | ||
1175 | void *callback_cls) | ||
1176 | { | ||
1177 | unsigned int ret = 0; | ||
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; | ||
1186 | |||
1187 | path = GCPP_get_path_from_route (1, | ||
1188 | &cp->pid); | ||
1189 | ret++; | ||
1190 | if (GNUNET_NO == | ||
1191 | callback (callback_cls, | ||
1192 | path, | ||
1193 | 0)) | ||
1194 | return ret; | ||
1195 | } | ||
1196 | for (unsigned int i=0;i<cp->path_dll_length;i++) | ||
1197 | { | ||
1198 | for (struct CadetPeerPathEntry *pe = cp->path_heads[i]; | ||
1199 | NULL != pe; | ||
1200 | pe = pe->next) | ||
1201 | { | ||
1202 | ret++; | ||
1203 | if (GNUNET_NO == | ||
1204 | callback (callback_cls, | ||
1205 | pe->path, | ||
1206 | i)) | ||
1207 | return ret; | ||
1208 | } | ||
1209 | } | ||
1210 | return ret; | ||
1211 | } | ||
1212 | |||
1213 | |||
1214 | /** | ||
1215 | * Iterate over the paths to @a cp where | ||
1216 | * @a cp is at distance @a dist from us. | ||
1217 | * | ||
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. | ||
1223 | */ | ||
1224 | unsigned int | ||
1225 | GCP_iterate_paths_at (struct CadetPeer *cp, | ||
1226 | unsigned int dist, | ||
1227 | GCP_PathIterator callback, | ||
1228 | void *callback_cls) | ||
1229 | { | ||
1230 | unsigned int ret = 0; | ||
1231 | |||
1232 | if (dist >= cp->path_dll_length) | ||
1233 | { | ||
1234 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1235 | "Asked to look for paths at distance %u, but maximum for me is < %u\n", | ||
1236 | dist, | ||
1237 | cp->path_dll_length); | ||
1238 | return 0; | ||
1239 | } | ||
1240 | for (struct CadetPeerPathEntry *pe = cp->path_heads[dist]; | ||
1241 | NULL != pe; | ||
1242 | pe = pe->next) | ||
1243 | { | ||
1244 | if (GNUNET_NO == | ||
1245 | callback (callback_cls, | ||
1246 | pe->path, | ||
1247 | dist)) | ||
1248 | return ret; | ||
1249 | ret++; | ||
1250 | } | ||
1251 | return ret; | ||
1252 | } | ||
1253 | |||
1254 | |||
1255 | /** | ||
1256 | * Get the tunnel towards a peer. | ||
1257 | * | ||
1258 | * @param cp Peer to get from. | ||
1259 | * @param create #GNUNET_YES to create a tunnel if we do not have one | ||
1260 | * @return Tunnel towards peer. | ||
1261 | */ | ||
1262 | struct CadetTunnel * | ||
1263 | GCP_get_tunnel (struct CadetPeer *cp, | ||
1264 | int create) | ||
1265 | { | ||
1266 | if (NULL == cp) | ||
1267 | return NULL; | ||
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; | ||
1274 | } | ||
1275 | |||
1276 | |||
1277 | /** | ||
1278 | * Hello offer was passed to the transport service. Mark it | ||
1279 | * as done. | ||
1280 | * | ||
1281 | * @param cls the `struct CadetPeer` where the offer completed | ||
1282 | */ | ||
1283 | static void | ||
1284 | hello_offer_done (void *cls) | ||
1285 | { | ||
1286 | struct CadetPeer *cp = cls; | ||
1287 | |||
1288 | cp->hello_offer = NULL; | ||
1289 | } | ||
1290 | |||
1291 | |||
1292 | /** | ||
1293 | * We got a HELLO for a @a peer, remember it, and possibly | ||
1294 | * trigger adequate actions (like trying to connect). | ||
1295 | * | ||
1296 | * @param cp the peer we got a HELLO for | ||
1297 | * @param hello the HELLO to remember | ||
1298 | */ | ||
1299 | void | ||
1300 | GCP_set_hello (struct CadetPeer *cp, | ||
1301 | const struct GNUNET_HELLO_Message *hello) | ||
1302 | { | ||
1303 | struct GNUNET_HELLO_Message *mrg; | ||
1304 | |||
1305 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1306 | "Got %u byte HELLO for peer %s\n", | ||
1307 | (unsigned int) GNUNET_HELLO_size (hello), | ||
1308 | GCP_2s (cp)); | ||
1309 | if (NULL != cp->hello_offer) | ||
1310 | { | ||
1311 | GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer); | ||
1312 | cp->hello_offer = NULL; | ||
1313 | } | ||
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); | ||
1333 | } | ||
1334 | |||
1335 | |||
1336 | /** | ||
1337 | * The tunnel to the given peer no longer exists, remove it from our | ||
1338 | * data structures, and possibly clean up the peer itself. | ||
1339 | * | ||
1340 | * @param cp the peer affected | ||
1341 | * @param t the dead tunnel | ||
1342 | */ | ||
1343 | void | ||
1344 | GCP_drop_tunnel (struct CadetPeer *cp, | ||
1345 | struct CadetTunnel *t) | ||
1346 | { | ||
1347 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1348 | "Dropping tunnel %s to peer %s\n", | ||
1349 | GCT_2s (t), | ||
1350 | GCP_2s (cp)); | ||
1351 | GNUNET_assert (cp->t == t); | ||
1352 | cp->t = NULL; | ||
1353 | consider_peer_destroy (cp); | ||
1354 | } | ||
1355 | |||
1356 | |||
1357 | /** | ||
1358 | * Test if @a cp has a core-level connection | ||
1359 | * | ||
1360 | * @param cp peer to test | ||
1361 | * @return #GNUNET_YES if @a cp has a core-level connection | ||
1362 | */ | ||
1363 | int | ||
1364 | GCP_has_core_connection (struct CadetPeer *cp) | ||
1365 | { | ||
1366 | return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO; | ||
1367 | } | ||
1368 | |||
1369 | |||
1370 | /** | ||
1371 | * Start message queue change notifications. | ||
1372 | * | ||
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 | ||
1377 | */ | ||
1378 | struct GCP_MessageQueueManager * | ||
1379 | GCP_request_mq (struct CadetPeer *cp, | ||
1380 | GCP_MessageQueueNotificationCallback cb, | ||
1381 | void *cb_cls) | ||
1382 | { | ||
1383 | struct GCP_MessageQueueManager *mqm; | ||
1384 | |||
1385 | mqm = GNUNET_new (struct GCP_MessageQueueManager); | ||
1386 | mqm->cb = cb; | ||
1387 | mqm->cb_cls = cb_cls; | ||
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; | ||
1400 | } | ||
1401 | |||
1402 | |||
1403 | /** | ||
1404 | * Stops message queue change notifications. | ||
1405 | * | ||
1406 | * @param mqm handle matching request to cancel | ||
1407 | * @param last_env final message to transmit, or NULL | ||
1408 | */ | ||
1409 | void | ||
1410 | GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm, | ||
1411 | struct GNUNET_MQ_Envelope *last_env) | ||
1412 | { | ||
1413 | struct CadetPeer *cp = mqm->cp; | ||
1414 | |||
1415 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1416 | "Destroying MQM %p for peer %s%s\n", | ||
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) | ||
1425 | { | ||
1426 | GNUNET_MQ_notify_sent (last_env, | ||
1427 | &mqm_send_done, | ||
1428 | cp); | ||
1429 | GNUNET_MQ_send (cp->core_mq, | ||
1430 | last_env); | ||
1431 | } | ||
1432 | else | ||
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); | ||
1443 | } | ||
1444 | |||
1445 | |||
1446 | /** | ||
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. | ||
1451 | * | ||
1452 | * @param cp peer to send the message to | ||
1453 | * @param env envelope with the message to send | ||
1454 | */ | ||
1455 | void | ||
1456 | GCP_send_ooo (struct CadetPeer *cp, | ||
1457 | struct GNUNET_MQ_Envelope *env) | ||
1458 | { | ||
1459 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1460 | "Sending message to %s out of management\n", | ||
1461 | GCP_2s (cp)); | ||
1462 | if (NULL == cp->core_mq) | ||
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); | ||
1472 | } | ||
1473 | |||
1474 | |||
1475 | |||
1476 | |||
1477 | /* 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 | */ | ||
42 | const char * | ||
43 | GCP_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 | */ | ||
57 | struct CadetPeer * | ||
58 | GCP_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 | */ | ||
71 | double | ||
72 | GCP_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 | */ | ||
82 | const struct GNUNET_PeerIdentity * | ||
83 | GCP_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 | */ | ||
92 | void | ||
93 | GCP_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 | */ | ||
103 | unsigned int | ||
104 | GCP_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 | */ | ||
113 | void | ||
114 | GCP_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 | */ | ||
126 | typedef 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 | */ | ||
140 | unsigned int | ||
141 | GCP_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 | */ | ||
156 | unsigned int | ||
157 | GCP_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 | */ | ||
170 | void | ||
171 | GCP_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 | */ | ||
183 | void | ||
184 | GCP_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 | */ | ||
196 | struct CadetTunnel * | ||
197 | GCP_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 | */ | ||
208 | void | ||
209 | GCP_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 | */ | ||
224 | struct GNUNET_CONTAINER_HeapNode * | ||
225 | GCP_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 | */ | ||
240 | void | ||
241 | GCP_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 | */ | ||
252 | void | ||
253 | GCP_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 | */ | ||
263 | void | ||
264 | GCP_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 | */ | ||
275 | void | ||
276 | GCP_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 | */ | ||
285 | void | ||
286 | GCP_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 | */ | ||
298 | struct 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 | */ | ||
310 | typedef 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 | */ | ||
324 | struct GCP_MessageQueueManager * | ||
325 | GCP_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 | */ | ||
336 | int | ||
337 | GCP_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 | */ | ||
351 | void | ||
352 | GCP_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 | */ | ||
365 | void | ||
366 | GCP_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 | */ | ||
378 | void | ||
379 | GCP_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 | */ | ||
389 | void | ||
390 | GCP_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 | */ | ||
56 | struct 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 | */ | ||
111 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
112 | |||
113 | /** | ||
65 | * Handle to the statistics service. | 114 | * Handle to the statistics service. |
66 | */ | 115 | */ |
67 | struct GNUNET_STATISTICS_Handle *stats; | 116 | struct GNUNET_STATISTICS_Handle *stats; |
68 | 117 | ||
69 | /** | 118 | /** |
70 | * Local peer own ID (memory efficient handle). | 119 | * Handle to communicate with ATS. |
71 | */ | 120 | */ |
72 | GNUNET_PEER_Id myid; | 121 | struct GNUNET_ATS_ConnectivityHandle *ats_ch; |
73 | 122 | ||
74 | /** | 123 | /** |
75 | * Local peer own ID (full value). | 124 | * Local peer own ID. |
76 | */ | 125 | */ |
77 | struct GNUNET_PeerIdentity my_full_id; | 126 | struct GNUNET_PeerIdentity my_full_id; |
78 | 127 | ||
128 | /** | ||
129 | * Own private key. | ||
130 | */ | ||
131 | struct 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 | */ |
83 | int shutting_down; | 136 | int shutting_down; |
84 | 137 | ||
85 | /*************************** Static global variables **************************/ | 138 | /** |
139 | * DLL with all the clients, head. | ||
140 | */ | ||
141 | static struct CadetClient *clients_head; | ||
86 | 142 | ||
87 | /** | 143 | /** |
88 | * Own private key. | 144 | * DLL with all the clients, tail. |
89 | */ | 145 | */ |
90 | static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; | 146 | static struct CadetClient *clients_tail; |
91 | 147 | ||
148 | /** | ||
149 | * Next ID to assign to a client. | ||
150 | */ | ||
151 | static unsigned int next_client_id; | ||
152 | |||
153 | /** | ||
154 | * All ports clients of this peer have opened. | ||
155 | */ | ||
156 | struct 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 | */ | ||
163 | struct GNUNET_CONTAINER_MultiHashMap *loose_channels; | ||
164 | |||
165 | /** | ||
166 | * Map from PIDs to `struct CadetPeer` entries. | ||
167 | */ | ||
168 | struct GNUNET_CONTAINER_MultiPeerMap *peers; | ||
169 | |||
170 | /** | ||
171 | * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier` | ||
172 | * hash codes to `struct CadetConnection` objects. | ||
173 | */ | ||
174 | struct GNUNET_CONTAINER_MultiShortmap *connections; | ||
175 | |||
176 | /** | ||
177 | * How many messages are needed to trigger an AXOLOTL ratchet advance. | ||
178 | */ | ||
179 | unsigned long long ratchet_messages; | ||
180 | |||
181 | /** | ||
182 | * How long until we trigger a ratched advance due to time. | ||
183 | */ | ||
184 | struct GNUNET_TIME_Relative ratchet_time; | ||
185 | |||
186 | /** | ||
187 | * How frequently do we send KEEPALIVE messages on idle connections? | ||
188 | */ | ||
189 | struct GNUNET_TIME_Relative keepalive_period; | ||
190 | |||
191 | /** | ||
192 | * Set to non-zero values to create random drops to test retransmissions. | ||
193 | */ | ||
194 | unsigned 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 | */ | ||
203 | void | ||
204 | GSC_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 | */ | ||
218 | const char * | ||
219 | GSC_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 | */ | ||
238 | static struct CadetChannel * | ||
239 | lookup_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 | */ | ||
253 | static struct GNUNET_CADET_ClientChannelNumber | ||
254 | client_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 | */ | ||
287 | struct GNUNET_CADET_ClientChannelNumber | ||
288 | GSC_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 | */ | ||
333 | static int | ||
334 | destroy_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 | */ | ||
357 | static int | ||
358 | destroy_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 | */ | ||
372 | static void | ||
373 | shutdown_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; | |||
102 | static void | 426 | static void |
103 | shutdown_task (void *cls) | 427 | shutdown_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 | */ | ||
447 | static int | ||
448 | bind_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 | */ |
129 | static void | 474 | static void |
130 | run (void *cls, struct GNUNET_SERVER_Handle *server, | 475 | handle_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 | */ | ||
518 | static void | ||
519 | handle_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 | */ |
167 | int | 551 | static void |
168 | main (int argc, char *const *argv) | 552 | handle_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 | */ | ||
609 | static void | ||
610 | handle_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 | */ | ||
650 | static int | ||
651 | check_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 | */ | ||
706 | static void | ||
707 | handle_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 | */ | ||
756 | static void | ||
757 | handle_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 | */ | ||
792 | static int | ||
793 | get_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 | */ | ||
820 | static void | ||
821 | handle_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 | */ | ||
848 | static int | ||
849 | path_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 | */ | ||
893 | static void | ||
894 | handle_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 | */ | ||
925 | static int | ||
926 | get_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 | */ | ||
959 | static void | ||
960 | handle_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 | */ | ||
983 | static void | ||
984 | iter_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 | */ | ||
1002 | static void | ||
1003 | iter_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 | */ | ||
1021 | static void | ||
1022 | handle_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 | */ | ||
1089 | static int | ||
1090 | show_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 | */ | ||
1113 | static void | ||
1114 | handle_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 | */ | ||
1159 | static void * | ||
1160 | client_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 | */ | ||
1193 | void | ||
1194 | GSC_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 | */ | ||
1220 | void | ||
1221 | GSC_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 | */ | ||
1239 | static int | ||
1240 | channel_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 | */ | ||
1272 | static int | ||
1273 | client_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 | */ | ||
1302 | static void | ||
1303 | client_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 | */ | ||
1349 | static void | ||
1350 | run (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 | */ | ||
1443 | GNUNET_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 | */ |
46 | enum CadetChannelState | 78 | enum 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 | */ |
68 | struct CadetChannelQueue | 108 | struct 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 | */ | ||
95 | struct 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 | */ |
135 | struct CadetChannelReliability | 174 | struct 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 | */ | ||
205 | struct 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 | */ |
297 | extern 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 | */ |
302 | extern 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 | */ | ||
324 | static int | ||
325 | rel_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 | */ | ||
332 | static void | ||
333 | send_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 | */ |
341 | static void | 389 | const char * |
342 | send_ack (struct CadetChannel *ch, int fwd); | 390 | GCCH_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 | */ |
353 | static int | 415 | struct GNUNET_CADET_ChannelTunnelNumber |
354 | is_loopback (const struct CadetChannel *ch) | 416 | GCCH_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 | */ |
370 | static struct CadetReliableMessage * | 427 | static void |
371 | copy_message (const struct GNUNET_CADET_ChannelAppDataMessage *msg, uint32_t mid, | 428 | free_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 (©[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 | */ |
395 | static void | 450 | static void |
396 | add_buffered_data (const struct GNUNET_CADET_ChannelAppDataMessage *msg, | 451 | channel_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 | */ |
444 | static void | 510 | static void |
445 | add_destination (struct CadetChannel *ch, struct CadetClient *c) | 511 | send_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 | */ |
475 | static void | 522 | static void |
476 | channel_set_options (struct CadetChannel *ch, uint32_t options) | 523 | channel_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 | */ |
492 | static uint32_t | 548 | static void |
493 | channel_get_options (struct CadetChannel *ch) | 549 | send_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 | */ |
513 | static void | 592 | void |
514 | send_destroy (struct CadetChannel *ch, int local_only) | 593 | GCCH_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 | */ |
544 | static void | 615 | struct CadetChannel * |
545 | send_client_create (struct CadetChannel *ch) | 616 | GCCH_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), |
574 | static void | 640 | sizeof (struct GNUNET_PeerIdentity))) |
575 | send_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 | */ |
612 | static void | 693 | static void |
613 | send_client_buffered_data (struct CadetChannel *ch, | 694 | timeout_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 *) ©[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 | */ |
674 | static void | 716 | struct CadetChannel * |
675 | send_client_ack (struct CadetChannel *ch, int fwd) | 717 | GCCH_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 | */ |
711 | static void | 781 | static void |
712 | send_client_nack (struct CadetChannel *ch) | 782 | send_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 | */ |
728 | static void | 797 | static void |
729 | channel_retransmit_message (void *cls) | 798 | send_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 *) ©[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 | */ |
762 | static void | 829 | static void |
763 | channel_recreate (void *cls) | 830 | send_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 | */ |
796 | static void | 860 | void |
797 | ch_message_sent (void *cls, | 861 | GCCH_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 | */ |
882 | static void | 894 | static void |
883 | send_create (struct CadetChannel *ch) | 895 | send_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 | */ |
903 | static void | 933 | void |
904 | send_ack (struct CadetChannel *ch, int fwd) | 934 | GCCH_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 | */ |
927 | static void | 1005 | static void |
928 | fire_and_forget (const struct GNUNET_MessageHeader *msg, | 1006 | signal_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 | */ |
943 | static void | 1029 | void |
944 | send_nack (struct CadetChannel *ch) | 1030 | GCCH_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 | */ | ||
966 | static void | ||
967 | channel_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 | */ |
1025 | static unsigned int | 1115 | void |
1026 | channel_rel_free_sent (struct CadetChannelReliability *rel, | 1116 | GCCH_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 | */ |
1104 | static int | 1173 | static int |
1105 | rel_message_free (struct CadetReliableMessage *copy, int update_time) | 1174 | is_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 | */ |
1160 | static void | 1207 | void |
1161 | channel_confirm (struct CadetChannel *ch, int fwd) | 1208 | GCCH_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 | */ | ||
1218 | static struct CadetReliableMessage * | ||
1219 | channel_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 (©[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 | */ | ||
1257 | static struct CadetChannel * | ||
1258 | channel_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 | */ | ||
1289 | void | ||
1290 | handle_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 | */ | ||
1355 | void | ||
1356 | GCCH_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 | */ | ||
1402 | struct GNUNET_CADET_ChannelTunnelNumber | ||
1403 | GCCH_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 | */ | ||
1416 | struct CadetTunnel * | ||
1417 | GCCH_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 | */ | ||
1431 | unsigned int | ||
1432 | GCCH_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 | */ | ||
1462 | int | ||
1463 | GCCH_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 | */ |
1488 | int | 1412 | static void |
1489 | GCCH_is_origin (struct CadetChannel *ch, int fwd) | 1413 | data_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 | */ |
1506 | int | 1423 | static void |
1507 | GCCH_is_terminal (struct CadetChannel *ch, int fwd) | 1424 | retry_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 | */ |
1524 | void | 1451 | static void |
1525 | GCCH_send_data_ack (struct CadetChannel *ch, int fwd) | 1452 | handle_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 | */ |
1576 | void | 1500 | void |
1577 | GCCH_allow_client (struct CadetChannel *ch, int fwd) | 1501 | GCCH_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 | */ |
1644 | void | 1601 | void |
1645 | GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level) | 1602 | GCCH_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 | */ |
1694 | void | 1643 | static int |
1695 | GCCH_handle_local_ack (struct CadetChannel *ch, int fwd) | 1644 | cmp_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 | */ |
1744 | int | 1665 | static void |
1745 | GCCH_handle_local_data (struct CadetChannel *ch, | 1666 | data_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 | */ | ||
1812 | void | ||
1813 | GCCH_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 | */ |
1848 | int | 1759 | int |
1849 | GCCH_handle_local_create (struct CadetClient *c, | 1760 | GCCH_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 | */ | ||
1916 | void | ||
1917 | GCCH_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 | */ |
2046 | void | 1877 | void |
2047 | GCCH_handle_data_ack (struct CadetChannel *ch, | 1878 | GCCH_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 | */ | ||
2153 | struct CadetChannel * | ||
2154 | GCCH_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 | */ | ||
2251 | void | ||
2252 | GCCH_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 | */ | ||
2274 | void | ||
2275 | GCCH_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 | */ |
2310 | void | 1990 | void |
2311 | GCCH_handle_destroy (struct CadetChannel *ch, | 1991 | GCCH_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 | */ | ||
2370 | void | ||
2371 | GCCH_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 | */ | ||
2545 | const char * | ||
2546 | GCCH_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" |
33 | extern "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 | */ | ||
49 | struct 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 | */ | ||
61 | void | ||
62 | GCCH_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 | */ |
72 | struct GNUNET_CADET_ChannelTunnelNumber | 44 | struct CadetChannel; |
73 | GCCH_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 | */ | ||
83 | struct CadetTunnel * | ||
84 | GCCH_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 | */ |
95 | unsigned int | 54 | const char * |
96 | GCCH_get_buffer (struct CadetChannel *ch, int fwd); | 55 | GCCH_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 | */ |
107 | int | 64 | void |
108 | GCCH_get_allowed (struct CadetChannel *ch, int fwd); | 65 | GCCH_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 | */ |
119 | int | 76 | struct GNUNET_CADET_ChannelTunnelNumber |
120 | GCCH_is_origin (struct CadetChannel *ch, int fwd); | 77 | GCCH_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 | */ | ||
130 | int | ||
131 | GCCH_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 | */ |
141 | void | 90 | struct CadetChannel * |
142 | GCCH_send_data_ack (struct CadetChannel *ch, int fwd); | 91 | GCCH_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 | */ | ||
149 | void | ||
150 | GCCH_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 | */ |
158 | void | 106 | void |
159 | GCCH_allow_client (struct CadetChannel *ch, int fwd); | 107 | GCCH_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 | */ | ||
167 | void | ||
168 | GCCH_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 | */ |
178 | void | 119 | void |
179 | GCCH_handle_local_ack (struct CadetChannel *ch, int fwd); | 120 | GCCH_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 | */ | ||
196 | int | ||
197 | GCCH_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 | */ |
211 | void | 135 | void |
212 | GCCH_handle_local_destroy (struct CadetChannel *ch, | 136 | GCCH_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 | */ |
227 | int | 149 | struct CadetChannel * |
228 | GCCH_handle_local_create (struct CadetClient *c, | 150 | GCCH_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 | */ | ||
241 | void | ||
242 | GCCH_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 | */ |
257 | void | 164 | void |
258 | GCCH_handle_data_ack (struct CadetChannel *ch, | 165 | GCCH_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 | */ | ||
271 | struct CadetChannel * | ||
272 | GCCH_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 | */ |
283 | void | 177 | void |
284 | GCCH_handle_nack (struct CadetChannel *ch); | 178 | GCCH_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 | */ |
297 | void | 191 | void |
298 | GCCH_handle_ack (struct CadetChannel *ch, | 192 | GCCH_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 | */ |
313 | void | 205 | void |
314 | GCCH_handle_destroy (struct CadetChannel *ch, | 206 | GCCH_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 | */ |
335 | void | 226 | void |
336 | GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | 227 | GCCH_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 | */ |
348 | const char * | 245 | int |
349 | GCCH_2s (const struct CadetChannel *ch); | 246 | GCCH_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 | */ |
258 | void | ||
259 | GCCH_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 | */ | ||
59 | struct 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 | */ |
91 | struct CadetFlowControl | 44 | enum 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 | */ |
169 | struct CadetConnectionPerformance | 78 | struct 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 | */ | ||
196 | struct 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 | */ | ||
310 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
311 | |||
312 | /** | ||
313 | * Local peer own ID (memory efficient handle). | ||
314 | */ | ||
315 | extern GNUNET_PEER_Id myid; | ||
316 | |||
317 | /** | ||
318 | * Local peer own ID (full value). | ||
319 | */ | ||
320 | extern struct GNUNET_PeerIdentity my_full_id; | ||
321 | |||
322 | /** | ||
323 | * Connections known, indexed by cid (CadetConnection). | ||
324 | */ | ||
325 | static 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 | */ | ||
332 | static 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 | */ | ||
338 | static unsigned long long max_msgs_queue; | ||
339 | |||
340 | /** | ||
341 | * How often to send path keepalives. Paths timeout after 4 missed. | ||
342 | */ | ||
343 | static struct GNUNET_TIME_Relative refresh_connection_time; | ||
344 | |||
345 | /** | ||
346 | * How often to send path create / ACKs. | ||
347 | */ | ||
348 | static 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 | ||
358 | static void | ||
359 | fc_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 | |||
370 | static void | ||
371 | connection_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 | */ | ||
397 | static void | ||
398 | schedule_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 | */ | ||
413 | static void | ||
414 | connection_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 | */ | ||
424 | static const char * | ||
425 | GCC_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 | */ |
454 | static void | 175 | struct CadetConnection * |
455 | fc_init (struct CadetFlowControl *fc) | 176 | GCC_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 | */ | ||
476 | static struct CadetConnection * | ||
477 | connection_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 | */ |
490 | static void | 191 | static void |
491 | connection_change_state (struct CadetConnection* c, | 192 | update_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) && |
514 | static void | 205 | (GNUNET_YES == new_mqm_ready) ); |
515 | mark_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 | */ | ||
528 | static void | ||
529 | send_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 | */ |
545 | static void | 220 | static void |
546 | send_ack (struct CadetConnection *c, | 221 | GCC_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 | */ | ||
642 | static void | ||
643 | update_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 | */ | ||
690 | static void | ||
691 | conn_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 | */ | ||
857 | static struct CadetPeer * | ||
858 | get_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 | */ | ||
886 | static struct CadetPeer * | ||
887 | get_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 | */ | ||
914 | static void | ||
915 | check_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 | */ | ||
932 | static int | ||
933 | check_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 | */ |
947 | void | 266 | void |
948 | GCC_check_connections () | 267 | GCC_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 | */ | ||
968 | static struct CadetPeer * | ||
969 | get_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 | */ | ||
981 | static uint32_t | ||
982 | get_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 | */ | ||
997 | static int | ||
998 | is_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 | */ | ||
1028 | static int | ||
1029 | is_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 | */ | ||
1053 | static void | ||
1054 | send_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 | */ | ||
1101 | static void | ||
1102 | send_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 | */ | ||
1137 | static void | ||
1138 | send_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 | */ | ||
1176 | static void | ||
1177 | send_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 | */ | ||
1217 | static void | ||
1218 | connection_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 | */ |
1237 | static void | 285 | void |
1238 | connection_maintain (struct CadetConnection *c, int fwd) | 286 | GCC_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 | */ |
1285 | static void | 313 | struct CadetTConnection * |
1286 | connection_keepalive (struct CadetConnection *c, | 314 | GCC_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 | */ |
1309 | static void | 326 | const struct CadetConnectionMetrics * |
1310 | connection_fwd_keepalive (void *cls) | 327 | GCC_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 | */ |
1326 | static void | 339 | static void |
1327 | connection_bck_keepalive (void *cls) | 340 | send_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 | */ |
1347 | static void | 351 | static void |
1348 | schedule_next_keepalive (struct CadetConnection *c, int fwd) | 352 | keepalive_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 | */ |
1413 | static void | 372 | static void |
1414 | connection_cancel_queues (struct CadetConnection *c, | 373 | send_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 | */ | ||
1456 | static void | ||
1457 | send_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 | */ | ||
1500 | static void | ||
1501 | connection_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 | */ | ||
1537 | static void | ||
1538 | connection_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 | */ | ||
1555 | static void | ||
1556 | connection_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 | */ |
1581 | static void | 415 | void |
1582 | connection_reset_timeout (struct CadetConnection *c, int fwd) | 416 | GCC_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 | */ |
1623 | static void | 435 | void |
1624 | check_path (void *cls, struct CadetConnection *c) | 436 | GCC_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 | */ |
1659 | static int | 455 | void |
1660 | does_connection_exist (struct CadetConnection *conn) | 456 | GCC_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 | */ | ||
1709 | static void | ||
1710 | check_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 | */ | ||
1730 | static void | ||
1731 | schedule_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 | */ | ||
1752 | static int | ||
1753 | register_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 | */ | ||
1811 | static void | ||
1812 | unregister_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 | */ | ||
1840 | static void | ||
1841 | invalidate_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 | */ | ||
1865 | static void | ||
1866 | add_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 | */ | ||
1882 | static void | ||
1883 | log_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 | */ |
1923 | void | 490 | void |
1924 | GCC_handle_create (struct CadetPeer *peer, | 491 | GCC_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 | */ |
2068 | void | 524 | void |
2069 | GCC_handle_confirm (struct CadetPeer *peer, | 525 | GCC_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 | */ |
2196 | void | 548 | void |
2197 | GCC_handle_broken (struct CadetPeer *peer, | 549 | GCC_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 | */ |
2269 | void | 572 | void |
2270 | GCC_handle_destroy (struct CadetPeer *peer, | 573 | GCC_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 | */ |
2333 | void | 597 | static void |
2334 | GCC_handle_ack (struct CadetPeer *peer, | 598 | send_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 | */ |
2406 | void | 636 | static void |
2407 | GCC_handle_poll (struct CadetPeer *peer, | 637 | send_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 | */ |
2480 | static int | 668 | void |
2481 | check_message (const struct GNUNET_MessageHeader *message, | 669 | GCC_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 | */ |
2607 | void | 709 | static void |
2608 | GCC_handle_kx (struct CadetPeer *peer, | 710 | manage_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 | */ | ||
2666 | void | ||
2667 | GCC_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 | */ |
2726 | void | 798 | static struct CadetConnection * |
2727 | GCC_init (const struct GNUNET_CONFIGURATION_Handle *c) | 799 | connection_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 | */ | ||
2775 | static int | ||
2776 | shutdown_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 | */ | ||
2791 | void | ||
2792 | GCC_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 | */ | ||
2815 | struct CadetConnection * | ||
2816 | GCC_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 | */ | ||
2880 | void | ||
2881 | GCC_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 | */ | ||
2954 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | ||
2955 | GCC_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 | */ | ||
2968 | const struct CadetPeerPath * | ||
2969 | GCC_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 | */ | ||
2984 | enum CadetConnectionState | ||
2985 | GCC_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 | */ | ||
2997 | struct CadetTunnel * | ||
2998 | GCC_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 | */ | ||
3012 | unsigned int | ||
3013 | GCC_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 | */ | ||
3035 | unsigned int | ||
3036 | GCC_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 | */ | ||
3059 | unsigned int | ||
3060 | GCC_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 | */ | ||
3077 | struct CadetEncryptedMessageIdentifier | ||
3078 | GCC_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 | */ | ||
3100 | void | ||
3101 | GCC_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 | */ | ||
3116 | void | ||
3117 | GCC_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 | */ |
3179 | int | 861 | struct CadetConnection * |
3180 | GCC_is_origin (struct CadetConnection *c, int fwd) | 862 | GCC_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 | { |
3199 | int | 881 | int cmp; |
3200 | GCC_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 | */ | ||
3214 | int | ||
3215 | GCC_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 | */ | ||
3250 | int | ||
3251 | GCC_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 | */ | ||
3276 | struct CadetConnectionQueue * | ||
3277 | GCC_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 | */ | ||
3391 | void | ||
3392 | GCC_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 | */ | ||
3408 | void | ||
3409 | GCC_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 | */ |
3468 | void | 943 | struct CadetConnection * |
3469 | GCC_send_ack (struct CadetConnection *c, int fwd, int force) | 944 | GCC_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 | */ |
3533 | void | 979 | void |
3534 | GCC_send_destroy (struct CadetConnection *c) | 980 | GCC_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 | */ |
3577 | void | 1006 | struct CadetPeerPath * |
3578 | GCC_start_poll (struct CadetConnection *c, int fwd) | 1007 | GCC_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 | */ |
3611 | void | 1019 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * |
3612 | GCC_stop_poll (struct CadetConnection *c, int fwd) | 1020 | GCC_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 | */ |
3635 | const char * | 1031 | const char * |
3636 | GCC_2s (const struct CadetConnection *c) | 1032 | GCC_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 | */ |
3660 | void | 1065 | void |
3661 | GCC_debug (const struct CadetConnection *c, enum GNUNET_ErrorType level) | 1066 | GCC_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 | ||
33 | extern "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 | */ | ||
46 | enum 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 | */ | ||
83 | struct CadetConnection; | ||
84 | |||
85 | /** | ||
86 | * Handle for messages queued but not yet sent. | ||
87 | */ | ||
88 | struct 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 | */ | ||
98 | void | ||
99 | GCC_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 | */ |
111 | typedef void | 47 | typedef 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 | */ |
126 | void | 60 | void |
127 | GCC_handle_create (struct CadetPeer *peer, | 61 | GCC_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 | */ |
137 | void | 71 | void |
138 | GCC_handle_confirm (struct CadetPeer *peer, | 72 | GCC_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 | */ |
148 | void | 81 | struct CadetConnection * |
149 | GCC_handle_broken (struct CadetPeer *peer, | 82 | GCC_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 | */ | ||
158 | void | ||
159 | GCC_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 | */ |
168 | void | 98 | struct CadetConnection * |
169 | GCC_handle_ack (struct CadetPeer *peer, | 99 | GCC_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 | */ | ||
178 | void | ||
179 | GCC_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 | */ |
188 | void | 122 | struct CadetConnection * |
189 | GCC_handle_kx (struct CadetPeer *peer, | 123 | GCC_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 | */ |
198 | void | 144 | void |
199 | GCC_handle_encrypted (struct CadetPeer *peer, | 145 | GCC_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 | */ | ||
211 | int | ||
212 | GCC_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 | */ |
224 | int | 154 | void |
225 | GCC_handle_ax (void *cls, const struct GNUNET_PeerIdentity *peer, | 155 | GCC_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 | */ | ||
239 | int | ||
240 | GCC_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 | */ |
251 | void | 165 | void |
252 | GCC_send_ack (struct CadetConnection *c, int fwd, int force); | 166 | GCC_handle_duplicate_create (struct CadetConnection *cc); |
253 | 167 | ||
254 | /** | ||
255 | * Initialize the connections subsystem | ||
256 | * | ||
257 | * @param c Configuration handle. | ||
258 | */ | ||
259 | void | ||
260 | GCC_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 | */ |
265 | void | 175 | void |
266 | GCC_shutdown (void); | 176 | GCC_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 | */ | ||
279 | struct CadetConnection * | ||
280 | GCC_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 | */ |
293 | void | 186 | void |
294 | GCC_destroy (struct CadetConnection *c); | 187 | GCC_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 | */ | ||
303 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | ||
304 | GCC_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 | */ |
314 | const struct CadetPeerPath * | 194 | struct CadetConnectionMetrics |
315 | GCC_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 | */ | ||
324 | enum CadetConnectionState | ||
325 | GCC_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 | */ | ||
334 | struct CadetTunnel * | ||
335 | GCC_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 | */ | ||
345 | unsigned int | ||
346 | GCC_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 | */ | ||
356 | unsigned int | ||
357 | GCC_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; |
367 | unsigned int | ||
368 | GCC_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 | */ | ||
377 | struct CadetEncryptedMessageIdentifier | ||
378 | GCC_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 | */ | ||
390 | void | ||
391 | GCC_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 | */ |
399 | void | 239 | const struct CadetConnectionMetrics * |
400 | GCC_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | 240 | GCC_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 | */ |
408 | void | 249 | void |
409 | GCC_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | 250 | GCC_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 | */ |
419 | void | 260 | void |
420 | GCC_neighbor_disconnected (struct CadetConnection *c, struct CadetPeer *peer); | 261 | GCC_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 | */ | ||
430 | int | ||
431 | GCC_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 | */ |
442 | int | 272 | void |
443 | GCC_is_terminal (struct CadetConnection *c, int fwd); | 273 | GCC_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 | */ | ||
453 | int | ||
454 | GCC_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 | */ | ||
463 | int | ||
464 | GCC_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 | */ |
475 | void | 284 | void |
476 | GCC_cancel (struct CadetConnectionQueue *q); | 285 | GCC_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 | */ | ||
497 | struct CadetConnectionQueue * | ||
498 | GCC_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 | */ |
510 | void | 295 | struct CadetTConnection * |
511 | GCC_send_create (struct CadetConnection *connection); | 296 | GCC_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 | */ | ||
522 | void | ||
523 | GCC_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 | */ |
535 | void | 305 | struct CadetPeerPath * |
536 | GCC_start_poll (struct CadetConnection *c, int fwd); | 306 | GCC_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 | */ |
547 | void | 315 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * |
548 | GCC_stop_poll (struct CadetConnection *c, int fwd); | 316 | GCC_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 | */ |
555 | const char * | 324 | const char * |
556 | GCC_2s (const struct CadetConnection *c); | 325 | GCC_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 | */ |
564 | void | 334 | void |
565 | GCC_debug (const struct CadetConnection *c, enum GNUNET_ErrorType level); | 335 | GCC_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 | */ | ||
74 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
75 | |||
76 | /** | ||
77 | * Own ID (short value). | ||
78 | */ | ||
79 | extern GNUNET_PEER_Id myid; | ||
80 | |||
81 | /** | ||
82 | * Own ID (full value). | ||
83 | */ | ||
84 | extern 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; | |||
94 | static struct GNUNET_TIME_Relative id_announce_time; | 77 | static 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 | */ |
99 | static unsigned long long dht_replication_level; | 82 | static 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 | */ |
104 | static struct GNUNET_SCHEDULER_Task * announce_id_task; | 87 | static 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 | */ |
109 | static struct GNUNET_TIME_Relative announce_delay; | 92 | static struct GNUNET_TIME_Relative announce_delay; |
110 | 93 | ||
111 | /** | ||
112 | * GET requests to stop on shutdown. | ||
113 | */ | ||
114 | static 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 | */ | ||
129 | static struct CadetPeerPath * | ||
130 | path_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 | */ |
177 | static void | 111 | static void |
178 | dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | 112 | dht_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 | */ |
304 | int | 217 | void |
305 | stop_get (void *cls, | 218 | GCD_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, | |||
325 | void | 235 | void |
326 | GCD_init (const struct GNUNET_CONFIGURATION_Handle *c) | 236 | GCD_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) | |||
364 | void | 278 | void |
365 | GCD_shutdown (void) | 279 | GCD_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 | */ | ||
382 | struct GCD_search_handle * | 300 | struct GCD_search_handle * |
383 | GCD_search (const struct GNUNET_PeerIdentity *peer_id, | 301 | GCD_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 | */ | ||
416 | void | 341 | void |
417 | GCD_search_stop (struct GCD_search_handle *h) | 342 | GCD_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 | ||
43 | struct 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 | */ |
53 | typedef void | 46 | struct 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 | |||
66 | void | 54 | void |
67 | GCD_init (const struct GNUNET_CONFIGURATION_Handle *c); | 55 | GCD_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 | |||
73 | GCD_shutdown (void); | 62 | GCD_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 | */ | ||
69 | void | ||
70 | GCD_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 | */ | ||
76 | struct GCD_search_handle * | 78 | struct GCD_search_handle * |
77 | GCD_search (const struct GNUNET_PeerIdentity *peer_id, | 79 | GCD_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 | */ | ||
81 | void | 87 | void |
82 | GCD_search_stop (struct GCD_search_handle *h); | 88 | GCD_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 | */ | ||
49 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
50 | |||
51 | /** | ||
52 | * Local peer own ID (memory efficient handle). | ||
53 | */ | ||
54 | extern GNUNET_PEER_Id myid; | ||
55 | |||
56 | /** | ||
57 | * Local peer own ID (full value). | ||
58 | */ | ||
59 | extern struct GNUNET_PeerIdentity my_full_id; | ||
60 | |||
61 | |||
62 | /** | ||
63 | * Don't try to recover tunnels if shutting down. | ||
64 | */ | ||
65 | extern int shutting_down; | ||
66 | |||
67 | |||
68 | /** | 43 | /** |
69 | * Hello message of local peer. | 44 | * Hello message of local peer. |
70 | */ | 45 | */ |
71 | const struct GNUNET_HELLO_Message *mine; | 46 | static 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 | */ |
81 | struct GNUNET_PEERINFO_NotifyContext* nc; | 56 | static 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 | */ |
96 | static void | 67 | static void |
97 | got_hello (void *cls, const struct GNUNET_PeerIdentity *id, | 68 | got_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, | |||
128 | void | 105 | void |
129 | GCH_init (const struct GNUNET_CONFIGURATION_Handle *c) | 106 | GCH_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) | |||
141 | void | 120 | void |
142 | GCH_shutdown () | 121 | GCH_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 | */ | ||
177 | const struct GNUNET_HELLO_Message * | ||
178 | GCH_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 | */ | ||
194 | char * | ||
195 | GCH_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 | */ | ||
48 | struct 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 | */ | ||
105 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
106 | |||
107 | /** | ||
108 | * Handle to server lib. | ||
109 | */ | ||
110 | static struct GNUNET_SERVER_Handle *server_handle; | ||
111 | |||
112 | /** | ||
113 | * DLL with all the clients, head. | ||
114 | */ | ||
115 | static struct CadetClient *clients_head; | ||
116 | |||
117 | /** | ||
118 | * DLL with all the clients, tail. | ||
119 | */ | ||
120 | static struct CadetClient *clients_tail; | ||
121 | |||
122 | /** | ||
123 | * Next ID to assign to a client. | ||
124 | */ | ||
125 | unsigned int next_client_id; | ||
126 | |||
127 | /** | ||
128 | * All ports clients of this peer have opened. | ||
129 | */ | ||
130 | static struct GNUNET_CONTAINER_MultiHashMap *ports; | ||
131 | |||
132 | /** | ||
133 | * Notification context, to send messages to local clients. | ||
134 | */ | ||
135 | static 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 | */ | ||
151 | static int | ||
152 | client_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 | */ | ||
179 | static int | ||
180 | channel_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 | */ | ||
203 | static void | ||
204 | client_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 | */ | ||
241 | static struct CadetClient * | ||
242 | client_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 | */ | ||
276 | static void | ||
277 | handle_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 | */ | ||
294 | static void | ||
295 | handle_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 | */ | ||
323 | static void | ||
324 | handle_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 | */ | ||
380 | static void | ||
381 | handle_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 | */ | ||
424 | static void | ||
425 | handle_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 | */ | ||
471 | static void | ||
472 | handle_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 | */ | ||
534 | static void | ||
535 | handle_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 | */ | ||
624 | static void | ||
625 | handle_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 | */ | ||
685 | static int | ||
686 | get_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 | */ | ||
718 | static int | ||
719 | show_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 | */ | ||
747 | static int | ||
748 | path_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 | */ | ||
798 | static void | ||
799 | handle_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 | */ | ||
835 | void | ||
836 | handle_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 | */ | ||
900 | static int | ||
901 | get_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 | */ | ||
933 | static void | ||
934 | handle_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 | |||
963 | static void | ||
964 | iter_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 | |||
974 | static void | ||
975 | iter_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 | */ | ||
993 | void | ||
994 | handle_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 | */ | ||
1079 | void | ||
1080 | handle_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 | */ | ||
1125 | static 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 | */ | ||
1161 | void | ||
1162 | GML_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 | */ | ||
1174 | void | ||
1175 | GML_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 | */ | ||
1193 | void | ||
1194 | GML_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 | */ | ||
1220 | struct CadetChannel * | ||
1221 | GML_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 | */ | ||
1251 | void | ||
1252 | GML_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 | */ | ||
1276 | void | ||
1277 | GML_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 | */ | ||
1299 | struct GNUNET_CADET_ClientChannelNumber | ||
1300 | GML_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 | */ | ||
1331 | struct CadetClient * | ||
1332 | GML_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 | */ | ||
1348 | struct CadetClient * | ||
1349 | GML_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 | */ | ||
1362 | void | ||
1363 | GML_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 | */ | ||
1395 | void | ||
1396 | GML_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 | */ | ||
1429 | void | ||
1430 | GML_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 | */ | ||
1455 | void | ||
1456 | GML_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 | */ | ||
1482 | void | ||
1483 | GML_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 | */ | ||
1510 | void | ||
1511 | GML_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 (©[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 | ©->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 | */ | ||
1546 | const char * | ||
1547 | GML_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 | ||
33 | extern "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 | */ | ||
46 | struct 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 | */ | ||
59 | void | ||
60 | GML_init (struct GNUNET_SERVER_Handle *handle); | ||
61 | |||
62 | /** | ||
63 | * Install server (service) handlers and start listening to clients. | ||
64 | */ | ||
65 | void | ||
66 | GML_start (void); | ||
67 | |||
68 | /** | ||
69 | * Shutdown server. | ||
70 | */ | ||
71 | void | ||
72 | GML_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 | */ | ||
82 | struct CadetChannel * | ||
83 | GML_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 | */ | ||
93 | void | ||
94 | GML_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 | */ | ||
105 | void | ||
106 | GML_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 | */ | ||
117 | struct GNUNET_CADET_ClientChannelNumber | ||
118 | GML_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 | */ | ||
127 | struct CadetClient * | ||
128 | GML_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 | */ | ||
137 | struct CadetClient * | ||
138 | GML_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 | */ | ||
147 | void | ||
148 | GML_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 | */ | ||
160 | void | ||
161 | GML_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 | */ | ||
173 | void | ||
174 | GML_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 | */ | ||
186 | void | ||
187 | GML_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 | */ | ||
197 | void | ||
198 | GML_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 | */ | ||
209 | void | ||
210 | GML_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 | */ | ||
221 | const char * | ||
222 | GML_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 | */ |
50 | struct 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 | */ |
125 | struct 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 | */ | ||
206 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
207 | 62 | ||
208 | /** | ||
209 | * Local peer own ID (full value). | ||
210 | */ | ||
211 | extern struct GNUNET_PeerIdentity my_full_id; | ||
212 | 63 | ||
213 | /** | ||
214 | * Local peer own ID (short) | ||
215 | */ | ||
216 | extern 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 | */ |
221 | static struct GNUNET_CONTAINER_MultiPeerMap *peers; | 69 | struct GCP_MessageQueueManager |
222 | 70 | { | |
223 | /** | ||
224 | * How many peers do we want to remember? | ||
225 | */ | ||
226 | static 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 | */ |
231 | static 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 | */ |
236 | static 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 | */ |
241 | static 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 | */ |
246 | static 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 | */ |
251 | static 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 | */ |
269 | static int | 108 | struct CadetPeer |
270 | notify_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 | */ | ||
290 | static struct CadetPeerPath * | ||
291 | pop_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 | */ |
316 | static void | 239 | const char * |
317 | call_peer_cont (struct CadetPeerQueue *q, int sent); | 240 | GCP_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 | */ | ||
267 | double | ||
268 | GCP_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 | */ |
334 | static void * | 318 | static void |
335 | core_connect_handler (void *cls, | 319 | destroy_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 | */ |
401 | static void | 384 | static void |
402 | core_disconnect_handler (void *cls, | 385 | consider_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 | ¬ify_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 | */ | ||
458 | static int | ||
459 | check_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 | */ | ||
478 | static void | ||
479 | handle_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 | */ | ||
492 | static void | ||
493 | handle_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, |
506 | static void | 441 | &cp->pid, |
507 | handle_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 | */ |
520 | static void | 451 | static void |
521 | handle_destroy (void *cls, const struct GNUNET_CADET_ConnectionDestroyMessage *msg) | 452 | consider_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 | */ |
534 | static void | 461 | static void |
535 | handle_ack (void *cls, const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg) | 462 | drop_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 | */ | ||
548 | static void | ||
549 | handle_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 | */ |
562 | static void | 479 | static void |
563 | handle_kx (void *cls, const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | 480 | consider_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 | */ | ||
578 | static int | ||
579 | check_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) |
602 | static void | 490 | return; /* still relevant! */ |
603 | handle_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) |
616 | static void | 504 | return; /* still relevant! */ |
617 | core_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)); | |
621 | static void | 509 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp, |
622 | connect_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 | */ | ||
678 | static void | ||
679 | core_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 | */ |
713 | enum GNUNET_CORE_Priority | 526 | void |
714 | get_priority (struct CadetPeerQueue *q) | 527 | GCP_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 | */ | ||
749 | static void | ||
750 | cancel_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 | */ | ||
769 | static int | ||
770 | peer_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 | */ |
835 | static int | 590 | static int |
836 | shutdown_peer (void *cls, | 591 | should_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 | */ | ||
859 | static int | ||
860 | is_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 | */ |
873 | static void | 608 | static void |
874 | delayed_search (void *cls) | 609 | mqm_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 | */ |
891 | static int | 617 | static void |
892 | peer_is_used (struct CadetPeer *peer) | 618 | mqm_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 | */ | ||
915 | static int | ||
916 | peer_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 | */ | ||
941 | static int | ||
942 | peer_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 | */ |
965 | static void | 669 | static void |
966 | peer_delete_oldest (void) | 670 | send_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 */ |
988 | static struct CadetPeerPath * | 681 | mqm_execute (mqm); |
989 | peer_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 | */ |
1023 | static void | 691 | static void |
1024 | search_handler (void *cls, const struct CadetPeerPath *path) | 692 | mqm_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 | */ | ||
1059 | static int | ||
1060 | is_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 | */ |
1073 | static int | 710 | void |
1074 | should_I_drop (void) | 711 | GCP_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 | */ |
1098 | static void | 746 | static int |
1099 | call_peer_cont (struct CadetPeerQueue *q, int sent) | 747 | destroy_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 | */ | ||
1128 | static void | ||
1129 | mq_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 | */ |
1147 | static void | 768 | void |
1148 | drop_cb (void *cls) | 769 | GCP_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 | */ |
1174 | struct CadetPeerQueue * | 785 | void |
1175 | GCP_send (struct CadetPeer *peer, | 786 | GCP_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 | */ |
1260 | void | 808 | void |
1261 | GCP_send_cancel (struct CadetPeerQueue *q) | 809 | GCP_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 |
1283 | void | 866 | * @param off offset of this peer on the path |
1284 | GCP_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 | */ |
1327 | void | 868 | void |
1328 | GCP_shutdown (void) | 869 | GCP_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 | */ | ||
1366 | struct CadetPeer * | ||
1367 | GCP_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 | */ | ||
1404 | struct CadetPeer * | ||
1405 | GCP_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 | */ |
1417 | static void | 904 | static void |
1418 | hello_offer_done (void *cls) | 905 | path_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 | */ |
1433 | void | 945 | struct GNUNET_CONTAINER_HeapNode * |
1434 | GCP_connect (struct CadetPeer *peer) | 946 | GCP_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 | */ | ||
1522 | int | ||
1523 | GCP_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 | */ |
1549 | void | 1019 | void |
1550 | GCP_add_tunnel (struct CadetPeer *peer) | 1020 | GCP_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 | */ |
1571 | void | 1039 | void |
1572 | GCP_add_connection (struct CadetPeer *peer, | 1040 | GCP_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 | */ | ||
1607 | struct CadetPeerPath * | ||
1608 | GCP_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 | |||
1687 | finish: | ||
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 | */ |
1713 | struct CadetPeerPath * | 1066 | void |
1714 | GCP_add_path_to_origin (struct CadetPeer *peer, | 1067 | GCP_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 | */ |
1731 | void | 1093 | struct CadetPeer * |
1732 | GCP_add_path_to_all (const struct CadetPeerPath *p, int confirmed) | 1094 | GCP_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 | */ |
1760 | void | 1128 | const struct GNUNET_PeerIdentity * |
1761 | GCP_remove_path (struct CadetPeer *peer, | 1129 | GCP_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 | */ |
1798 | void | 1141 | void |
1799 | GCP_check_connection (const struct CadetPeer *peer, | 1142 | GCP_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 | */ |
1818 | void | 1157 | unsigned int |
1819 | GCP_remove_connection (struct CadetPeer *peer, | 1158 | GCP_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 | */ |
1848 | void | 1172 | unsigned int |
1849 | GCP_start_search (struct CadetPeer *peer) | 1173 | GCP_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, |
1889 | void | 1193 | 0)) |
1890 | GCP_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 | */ | ||
1914 | const struct GNUNET_PeerIdentity * | ||
1915 | GCP_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 | */ |
1928 | GNUNET_PEER_Id | 1224 | unsigned int |
1929 | GCP_get_short_id (const struct CadetPeer *peer) | 1225 | GCP_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 | } |
1943 | void | 1240 | for (struct CadetPeerPathEntry *pe = cp->path_heads[dist]; |
1944 | GCP_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 | */ |
1961 | struct CadetTunnel * | 1262 | struct CadetTunnel * |
1962 | GCP_get_tunnel (const struct CadetPeer *peer) | 1263 | GCP_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 | */ |
1976 | void | 1283 | static void |
1977 | GCP_set_hello (struct CadetPeer *peer, | 1284 | hello_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 | */ |
2011 | struct GNUNET_HELLO_Message * | 1299 | void |
2012 | GCP_get_hello (struct CadetPeer *peer) | 1300 | GCP_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 | */ |
2038 | void | 1343 | void |
2039 | GCP_try_connect (struct CadetPeer *peer) | 1344 | GCP_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 | */ |
2083 | void | 1363 | int |
2084 | GCP_notify_broken_link (struct CadetPeer *peer, | 1364 | GCP_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 | */ |
2134 | unsigned int | 1378 | struct GCP_MessageQueueManager * |
2135 | GCP_count_paths (const struct CadetPeer *peer) | 1379 | GCP_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 | */ |
2156 | unsigned int | 1409 | void |
2157 | GCP_iterate_paths (struct CadetPeer *peer, | 1410 | GCP_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 | */ |
2181 | void | 1455 | void |
2182 | GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, | 1456 | GCP_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 | */ | ||
2200 | const char * | ||
2201 | GCP_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" |
33 | extern "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 | */ | ||
47 | struct CadetPeer; | ||
48 | 33 | ||
49 | /** | ||
50 | * Handle to queued messages on a peer level. | ||
51 | */ | ||
52 | struct 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 | */ | ||
70 | typedef 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 | */ | ||
90 | typedef 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 | */ | ||
105 | void | ||
106 | GCP_init (const struct GNUNET_CONFIGURATION_Handle *c); | ||
107 | |||
108 | /** | ||
109 | * Shut down the peer subsystem. | ||
110 | */ | 41 | */ |
111 | void | 42 | const char * |
112 | GCP_shutdown (void); | 43 | GCP_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 | */ |
126 | struct CadetPeer * | 57 | struct CadetPeer * |
127 | GCP_get (const struct GNUNET_PeerIdentity *peer_id, int create); | 58 | GCP_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 | */ |
141 | struct CadetPeer * | 71 | double |
142 | GCP_get_short (const GNUNET_PEER_Id peer, int create); | 72 | GCP_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 | */ | ||
152 | void | ||
153 | GCP_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 | */ |
169 | struct CadetPeerQueue * | 82 | const struct GNUNET_PeerIdentity * |
170 | GCP_send (struct CadetPeer *peer, | 83 | GCP_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 | */ | ||
188 | void | ||
189 | GCP_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 | */ |
197 | void | 92 | void |
198 | GCP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel *t); | 93 | GCP_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 | */ |
208 | int | 103 | unsigned int |
209 | GCP_is_neighbor (const struct CadetPeer *peer); | 104 | GCP_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 | */ |
219 | void | 113 | void |
220 | GCP_add_tunnel (struct CadetPeer *peer); | 114 | GCP_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 | */ |
234 | void | 126 | typedef int |
235 | GCP_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 | */ |
252 | struct CadetPeerPath * | 140 | unsigned int |
253 | GCP_add_path (struct CadetPeer *peer, | 141 | GCP_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 | */ |
272 | struct CadetPeerPath * | 156 | unsigned int |
273 | GCP_add_path_to_origin (struct CadetPeer *peer, | 157 | GCP_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 | */ |
283 | void | 170 | void |
284 | GCP_add_path_to_all (const struct CadetPeerPath *p, int confirmed); | 171 | GCP_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 | */ |
293 | void | 183 | void |
294 | GCP_remove_path (struct CadetPeer *peer, | 184 | GCP_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 | */ |
304 | void | 196 | struct CadetTunnel * |
305 | GCP_check_connection (const struct CadetPeer *peer, | 197 | GCP_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 | */ |
315 | void | 208 | void |
316 | GCP_remove_connection (struct CadetPeer *peer, | 209 | GCP_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 | */ |
326 | void | 224 | struct GNUNET_CONTAINER_HeapNode * |
327 | GCP_start_search (struct CadetPeer *peer); | 225 | GCP_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 | */ |
336 | void | 240 | void |
337 | GCP_stop_search (struct CadetPeer *peer); | 241 | GCP_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 | */ |
347 | const struct GNUNET_PeerIdentity * | 252 | void |
348 | GCP_get_id (const struct CadetPeer *peer); | 253 | GCP_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 | */ |
358 | GNUNET_PEER_Id | 263 | void |
359 | GCP_get_short_id (const struct CadetPeer *peer); | 264 | GCP_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 | */ |
369 | struct CadetTunnel * | 275 | void |
370 | GCP_get_tunnel (const struct CadetPeer *peer); | 276 | GCP_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 | */ |
379 | void | 285 | void |
380 | GCP_set_hello (struct CadetPeer *peer, | 286 | GCP_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 | */ |
391 | struct GNUNET_HELLO_Message * | 298 | struct GCP_MessageQueueManager; |
392 | GCP_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 | */ |
400 | void | 310 | typedef void |
401 | GCP_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 | */ |
411 | void | 324 | struct GCP_MessageQueueManager * |
412 | GCP_notify_broken_link (struct CadetPeer *peer, | 325 | GCP_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 | */ |
424 | unsigned int | 336 | int |
425 | GCP_count_paths (const struct CadetPeer *peer); | 337 | GCP_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 | */ |
436 | unsigned int | 351 | void |
437 | GCP_iterate_paths (struct CadetPeer *peer, | 352 | GCP_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 | */ |
448 | void | 365 | void |
449 | GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, | 366 | GCP_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 | */ |
460 | const char * | 378 | void |
461 | GCP_2s (const struct CadetPeer *peer); | 379 | GCP_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 | */ |
469 | void | 389 | void |
470 | GCP_debug (const struct CadetPeer *p, | 390 | GCP_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 | |||
58 | struct 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 | */ | ||
69 | struct 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 | */ | ||
101 | struct 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 | */ | ||
138 | struct 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 | */ | ||
251 | struct 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 | */ | ||
347 | struct 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 | */ | ||
375 | struct 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 | */ | ||
406 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
407 | |||
408 | /** | ||
409 | * Local peer own ID (memory efficient handle). | ||
410 | */ | ||
411 | extern GNUNET_PEER_Id myid; | ||
412 | |||
413 | /** | ||
414 | * Local peer own ID (full value). | ||
415 | */ | ||
416 | extern struct GNUNET_PeerIdentity my_full_id; | ||
417 | |||
418 | |||
419 | /** | ||
420 | * Don't try to recover tunnels if shutting down. | ||
421 | */ | ||
422 | extern 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 | */ | ||
429 | static struct GNUNET_CONTAINER_MultiPeerMap *tunnels; | ||
430 | |||
431 | /** | ||
432 | * Own Peer ID private key. | ||
433 | */ | ||
434 | const 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 | */ | ||
442 | static unsigned long long ratchet_messages; | ||
443 | |||
444 | /** | ||
445 | * How long until we trigger a ratched advance. | ||
446 | */ | ||
447 | static 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 | */ | ||
461 | static const char * | ||
462 | cstate2s (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 | */ | ||
493 | static const char * | ||
494 | estate2s (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 | */ | ||
527 | static int | ||
528 | is_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 | */ | ||
551 | static unsigned int | ||
552 | get_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 | */ | ||
570 | static int | ||
571 | get_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 | */ | ||
589 | static unsigned int | ||
590 | get_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 | */ | ||
608 | static unsigned int | ||
609 | get_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 | */ | ||
625 | static void | ||
626 | new_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 | */ | ||
650 | static void | ||
651 | t_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 | */ | ||
682 | static void | ||
683 | t_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 | */ | ||
705 | static void | ||
706 | t_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 | */ | ||
729 | static int | ||
730 | t_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 | */ | ||
806 | static int | ||
807 | t_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 | */ | ||
846 | static void | ||
847 | t_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 | */ | ||
877 | static void | ||
878 | t_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 | */ | ||
915 | static int | ||
916 | try_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 | */ | ||
997 | static void | ||
998 | store_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 | */ | ||
1027 | static void | ||
1028 | delete_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 | */ | ||
1048 | static int | ||
1049 | store_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 | */ | ||
1094 | static int | ||
1095 | t_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 | */ | ||
1188 | static struct CadetConnection * | ||
1189 | tunnel_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 | */ | ||
1231 | static void | ||
1232 | tun_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 | |||
1249 | static unsigned int | ||
1250 | count_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 | */ | ||
1267 | static void | ||
1268 | unqueue_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 | */ | ||
1281 | static struct CadetTunnelDelayed * | ||
1282 | queue_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 | */ | ||
1316 | static struct CadetTunnelQueue * | ||
1317 | send_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 | */ | ||
1430 | static void | ||
1431 | send_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 | */ | ||
1476 | static void | ||
1477 | kx_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 | */ | ||
1502 | static void | ||
1503 | ephm_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 | */ | ||
1537 | static int | ||
1538 | destroy_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 | */ | ||
1558 | static void | ||
1559 | send_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 | */ | ||
1586 | static void | ||
1587 | handle_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 | */ | ||
1640 | static void | ||
1641 | handle_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 | */ | ||
1677 | static void | ||
1678 | handle_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 | */ | ||
1712 | static void | ||
1713 | handle_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 | */ | ||
1753 | static void | ||
1754 | handle_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 | */ | ||
1797 | static void | ||
1798 | handle_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 | */ | ||
1830 | static void | ||
1831 | destroy_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 | */ | ||
1869 | static void | ||
1870 | handle_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 | */ | ||
1936 | void | ||
1937 | GCT_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 | */ | ||
1995 | void | ||
1996 | GCT_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 | */ | ||
2141 | void | ||
2142 | GCT_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 | */ | ||
2187 | void | ||
2188 | GCT_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 | */ | ||
2201 | struct CadetTunnel * | ||
2202 | GCT_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 | */ | ||
2231 | void | ||
2232 | GCT_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 | */ | ||
2277 | void | ||
2278 | GCT_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 | */ | ||
2315 | static void | ||
2316 | trim_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 | */ | ||
2356 | void | ||
2357 | GCT_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 | */ | ||
2389 | void | ||
2390 | GCT_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 | */ | ||
2448 | void | ||
2449 | GCT_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 | */ | ||
2488 | void | ||
2489 | GCT_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 | */ | ||
2517 | struct CadetChannel * | ||
2518 | GCT_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 | */ | ||
2545 | static void | ||
2546 | delayed_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 | */ | ||
2571 | void | ||
2572 | GCT_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 | */ | ||
2607 | void | ||
2608 | GCT_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 | */ | ||
2629 | void | ||
2630 | GCT_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 | */ | ||
2732 | struct CadetConnection * | ||
2733 | GCT_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 | */ | ||
2781 | unsigned int | ||
2782 | GCT_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 | */ | ||
2804 | unsigned int | ||
2805 | GCT_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 | */ | ||
2828 | unsigned int | ||
2829 | GCT_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 | */ | ||
2849 | enum CadetTunnelCState | ||
2850 | GCT_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 | */ | ||
2868 | enum CadetTunnelEState | ||
2869 | GCT_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 | */ | ||
2886 | unsigned int | ||
2887 | GCT_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 | */ | ||
2926 | unsigned int | ||
2927 | GCT_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 | */ | ||
2961 | const struct GNUNET_PeerIdentity * | ||
2962 | GCT_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 | */ | ||
2975 | struct GNUNET_CADET_ChannelTunnelNumber | ||
2976 | GCT_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 | */ | ||
3014 | void | ||
3015 | GCT_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 | */ | ||
3068 | void | ||
3069 | GCT_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 | */ | ||
3142 | void | ||
3143 | GCT_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 | */ | ||
3174 | int | ||
3175 | GCT_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 | */ | ||
3194 | struct CadetTunnelQueue * | ||
3195 | GCT_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 | */ | ||
3210 | void | ||
3211 | GCT_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 | */ | ||
3265 | int | ||
3266 | GCT_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 | */ | ||
3280 | int | ||
3281 | GCT_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 | */ | ||
3301 | unsigned int | ||
3302 | GCT_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 | */ | ||
3346 | const char * | ||
3347 | GCT_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 | |||
3360 | static void | ||
3361 | ax_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 | */ | ||
3408 | void | ||
3409 | GCT_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 | */ | ||
3451 | void | ||
3452 | GCT_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 | */ | ||
3463 | unsigned int | ||
3464 | GCT_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 | */ | ||
3477 | void | ||
3478 | GCT_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 | */ | ||
3494 | void | ||
3495 | GCT_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 | ||
33 | extern "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 | */ | ||
48 | enum 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 | */ | ||
80 | enum 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 | */ | ||
125 | struct 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 | */ | ||
135 | struct 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 | */ | ||
145 | typedef void | ||
146 | (*GCT_sent) (void *cls, | ||
147 | struct CadetTunnel *t, | ||
148 | struct CadetTunnelQueue *q, | ||
149 | uint16_t type, size_t size); | ||
150 | |||
151 | typedef void | ||
152 | (*GCT_conn_iter) (void *cls, struct CadetConnection *c); | ||
153 | |||
154 | |||
155 | typedef 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 | */ | ||
169 | void | ||
170 | GCT_init (const struct GNUNET_CONFIGURATION_Handle *c, | ||
171 | const struct GNUNET_CRYPTO_EddsaPrivateKey *key); | ||
172 | |||
173 | |||
174 | /** | ||
175 | * Shut down the tunnel subsystem. | ||
176 | */ | ||
177 | void | ||
178 | GCT_shutdown (void); | ||
179 | |||
180 | |||
181 | /** | ||
182 | * Create a tunnel. | ||
183 | * | ||
184 | * @param destination Peer this tunnel is towards. | ||
185 | */ | ||
186 | struct CadetTunnel * | ||
187 | GCT_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 | */ | ||
197 | void | ||
198 | GCT_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 | */ | ||
206 | void | ||
207 | GCT_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 | */ | ||
221 | void | ||
222 | GCT_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 | */ | ||
231 | void | ||
232 | GCT_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 | */ | ||
241 | void | ||
242 | GCT_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 | */ | ||
251 | void | ||
252 | GCT_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 | */ | ||
261 | void | ||
262 | GCT_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 | */ | ||
271 | void | ||
272 | GCT_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 | */ | ||
281 | void | ||
282 | GCT_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 | */ | ||
293 | struct CadetChannel * | ||
294 | GCT_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 | */ | ||
305 | void | ||
306 | GCT_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 | */ | ||
316 | void | ||
317 | GCT_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 | */ | ||
331 | struct CadetConnection * | ||
332 | GCT_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 | */ | ||
342 | unsigned int | ||
343 | GCT_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 | */ | ||
353 | unsigned int | ||
354 | GCT_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 | */ | ||
364 | unsigned int | ||
365 | GCT_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 | */ | ||
375 | enum CadetTunnelCState | ||
376 | GCT_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 | */ | ||
386 | enum CadetTunnelEState | ||
387 | GCT_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 | */ | ||
397 | unsigned int | ||
398 | GCT_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 | */ | ||
408 | unsigned int | ||
409 | GCT_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 | */ | ||
419 | const struct GNUNET_PeerIdentity * | ||
420 | GCT_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 | */ | ||
430 | struct GNUNET_CADET_ChannelTunnelNumber | ||
431 | GCT_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 | */ | ||
439 | void | ||
440 | GCT_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 | */ | ||
450 | void | ||
451 | GCT_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 | */ | ||
463 | void | ||
464 | GCT_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 | */ | ||
475 | int | ||
476 | GCT_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 | */ | ||
491 | struct CadetTunnelQueue * | ||
492 | GCT_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 | */ | ||
503 | void | ||
504 | GCT_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 | */ | ||
514 | int | ||
515 | GCT_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 | */ | ||
526 | int | ||
527 | GCT_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 | */ | ||
538 | unsigned int | ||
539 | GCT_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 | */ | ||
550 | const char * | ||
551 | GCT_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 | */ | ||
560 | void | ||
561 | GCT_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 | */ | ||
570 | void | ||
571 | GCT_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 | */ | ||
579 | unsigned int | ||
580 | GCT_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 | */ | ||
590 | void | ||
591 | GCT_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 | */ | ||
601 | void | ||
602 | GCT_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 bf05fae6b..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__) |
@@ -3082,10 +3081,6 @@ GCT_handle_encrypted (struct CadetTConnection *ct, | |||
3082 | break; | 3081 | break; |
3083 | } | 3082 | } |
3084 | 3083 | ||
3085 | GNUNET_STATISTICS_update (stats, | ||
3086 | "# received encrypted", | ||
3087 | 1, | ||
3088 | GNUNET_NO); | ||
3089 | decrypted_size = -1; | 3084 | decrypted_size = -1; |
3090 | if (CADET_TUNNEL_KEY_OK == t->estate) | 3085 | if (CADET_TUNNEL_KEY_OK == t->estate) |
3091 | { | 3086 | { |
@@ -3166,6 +3161,10 @@ GCT_handle_encrypted (struct CadetTConnection *ct, | |||
3166 | &t->ax); | 3161 | &t->ax); |
3167 | return; | 3162 | return; |
3168 | } | 3163 | } |
3164 | GNUNET_STATISTICS_update (stats, | ||
3165 | "# decrypted bytes", | ||
3166 | decrypted_size, | ||
3167 | GNUNET_NO); | ||
3169 | 3168 | ||
3170 | /* The MST will ultimately call #handle_decrypted() on each message. */ | 3169 | /* The MST will ultimately call #handle_decrypted() on each message. */ |
3171 | t->current_ct = ct; | 3170 | t->current_ct = ct; |
@@ -3217,6 +3216,10 @@ GCT_send (struct CadetTunnel *t, | |||
3217 | &ax_msg[1], | 3216 | &ax_msg[1], |
3218 | message, | 3217 | message, |
3219 | payload_size); | 3218 | payload_size); |
3219 | GNUNET_STATISTICS_update (stats, | ||
3220 | "# encrypted bytes", | ||
3221 | payload_size, | ||
3222 | GNUNET_NO); | ||
3220 | ax_msg->ax_header.Ns = htonl (t->ax.Ns++); | 3223 | ax_msg->ax_header.Ns = htonl (t->ax.Ns++); |
3221 | ax_msg->ax_header.PNs = htonl (t->ax.PNs); | 3224 | ax_msg->ax_header.PNs = htonl (t->ax.PNs); |
3222 | /* FIXME: we should do this once, not once per message; | 3225 | /* FIXME: we should do this once, not once per message; |
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..8963d97c9 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! */ | 37 | struct 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; | |||
73 | static int test_backwards = GNUNET_NO; | 84 | static int test_backwards = GNUNET_NO; |
74 | 85 | ||
75 | /** | 86 | /** |
87 | * How many packets to send. | ||
88 | */ | ||
89 | static unsigned int total_packets; | ||
90 | |||
91 | /** | ||
92 | * Time to wait for fast operations. | ||
93 | */ | ||
94 | static struct GNUNET_TIME_Relative short_time; | ||
95 | |||
96 | /** | ||
76 | * How many events have happened | 97 | * How many events have happened |
77 | */ | 98 | */ |
78 | static int ok; | 99 | static int ok; |
@@ -83,9 +104,9 @@ static int ok; | |||
83 | static int ok_goal; | 104 | static int ok_goal; |
84 | 105 | ||
85 | /** | 106 | /** |
86 | * Size of each test packet | 107 | * Size of each test packet's payload |
87 | */ | 108 | */ |
88 | static size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t); | 109 | static 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; | |||
158 | static struct GNUNET_SCHEDULER_Task *test_task; | 179 | static struct GNUNET_SCHEDULER_Task *test_task; |
159 | 180 | ||
160 | /** | 181 | /** |
161 | * Task runnining #data_task(). | 182 | * Task runnining #send_next_msg(). |
162 | */ | 183 | */ |
163 | static struct GNUNET_SCHEDULER_Task *data_job; | 184 | static 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 | */ |
178 | static struct GNUNET_CADET_Channel *ch; | 199 | static 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; | |||
183 | static struct GNUNET_CADET_Channel *incoming_ch; | 204 | static struct GNUNET_CADET_Channel *incoming_ch; |
184 | 205 | ||
185 | /** | 206 | /** |
186 | * Transmit handle for root data calls | ||
187 | */ | ||
188 | static struct GNUNET_CADET_TransmitHandle *th; | ||
189 | |||
190 | /** | ||
191 | * Transmit handle for root data calls | ||
192 | */ | ||
193 | static 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; | |||
225 | static unsigned int msg_dropped; | 235 | static 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 | */ |
235 | static unsigned int | 251 | static struct GNUNET_CADET_Channel * |
236 | get_expected_target () | 252 | get_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 | |||
322 | shutdown_task (void *cls) | 325 | shutdown_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 | */ |
353 | static void | 356 | static void |
354 | stats_cont (void *cls, | 357 | stats_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 | */ |
389 | static int | 385 | static int |
390 | stats_iterator (void *cls, | 386 | stats_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 | */ |
428 | static void | 417 | static void |
429 | gather_stats_and_exit (void *cls) | 418 | gather_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 | */ | ||
481 | static size_t | ||
482 | tmt_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 | */ |
490 | static void | 467 | static void |
491 | data_task (void *cls) | 468 | send_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 | */ |
551 | static size_t | 534 | static void |
552 | tmt_rdy (void *cls, size_t size, void *buf) | 535 | send_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 | */ | ||
566 | static void | ||
567 | reschedule_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 | } | ||
582 | |||
620 | 583 | ||
621 | return msg_size; | 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 | */ | ||
592 | static int | ||
593 | check_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 | */ |
635 | static int | 607 | static void |
636 | data_callback (void *cls, | 608 | handle_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 | */ | ||
780 | static 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 | */ |
800 | static void * | 717 | static void * |
801 | incoming_channel (void *cls, | 718 | connect_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. | ||
765 | * | ||
766 | * It should clean up any associated state, including cancelling any pending | ||
767 | * transmission on this channel. | ||
846 | * | 768 | * |
847 | * @param cls closure (set from GNUNET_CADET_connect, peer number) | 769 | * @param cls Channel closure (channel wrapper). |
848 | * @param channel connection to the other end (henceforth invalid) | 770 | * @param channel Connection to the other end (henceforth invalid). |
849 | * @param channel_ctx place where local state associated | ||
850 | * with the channel is stored | ||
851 | */ | 771 | */ |
852 | static void | 772 | static void |
853 | channel_cleaner (void *cls, | 773 | disconnect_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 | */ |
900 | static void | 814 | static void |
901 | do_test (void *cls) | 815 | start_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 | */ |
957 | static void | 881 | static void |
958 | pi_cb (void *cls, | 882 | pi_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 | */ |
999 | static void | 914 | static void |
1000 | tmain (void *cls, | 915 | tmain (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,46 @@ tmain (void *cls, | |||
1031 | int | 948 | int |
1032 | main (int argc, char *argv[]) | 949 | main (int argc, char *argv[]) |
1033 | { | 950 | { |
1034 | initialized = GNUNET_NO; | ||
1035 | static const struct GNUNET_HashCode *ports[2]; | 951 | static const struct GNUNET_HashCode *ports[2]; |
952 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
953 | GNUNET_MQ_hd_var_size (data, | ||
954 | GNUNET_MESSAGE_TYPE_DUMMY, | ||
955 | struct GNUNET_MessageHeader, | ||
956 | NULL), | ||
957 | GNUNET_MQ_handler_end () | ||
958 | }; | ||
1036 | const char *config_file; | 959 | const char *config_file; |
1037 | char port_id[] = "test port"; | 960 | char port_id[] = "test port"; |
1038 | GNUNET_CRYPTO_hash (port_id, sizeof (port_id), &port); | 961 | struct GNUNET_GETOPT_CommandLineOption options[] = { |
962 | GNUNET_GETOPT_OPTION_SET_RELATIVE_TIME ('t', | ||
963 | "time", | ||
964 | "short_time", | ||
965 | gettext_noop ("set short timeout"), | ||
966 | &short_time), | ||
967 | |||
968 | GNUNET_GETOPT_OPTION_SET_UINT ('m', | ||
969 | "messages", | ||
970 | "NUM_MESSAGES", | ||
971 | gettext_noop ("set number of messages to send"), | ||
972 | &total_packets), | ||
973 | |||
974 | GNUNET_GETOPT_OPTION_END | ||
975 | }; | ||
1039 | 976 | ||
977 | |||
978 | initialized = GNUNET_NO; | ||
1040 | GNUNET_log_setup ("test", "DEBUG", NULL); | 979 | GNUNET_log_setup ("test", "DEBUG", NULL); |
1041 | config_file = "test_cadet.conf"; | ||
1042 | 980 | ||
1043 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n"); | 981 | total_packets = TOTAL_PACKETS; |
982 | short_time = SHORT_TIME; | ||
983 | if (-1 == GNUNET_GETOPT_run (argv[0], options, argc, argv)) | ||
984 | { | ||
985 | FPRINTF (stderr, "test failed: problem with CLI parameters\n"); | ||
986 | exit (1); | ||
987 | } | ||
988 | |||
989 | config_file = "test_cadet.conf"; | ||
990 | GNUNET_CRYPTO_hash (port_id, sizeof (port_id), &port); | ||
1044 | 991 | ||
1045 | /* Find out requested size */ | 992 | /* Find out requested size */ |
1046 | if (strstr (argv[0], "_2_") != NULL) | 993 | if (strstr (argv[0], "_2_") != NULL) |
@@ -1078,11 +1025,11 @@ main (int argc, char *argv[]) | |||
1078 | { | 1025 | { |
1079 | /* Test is supposed to generate the following callbacks: | 1026 | /* Test is supposed to generate the following callbacks: |
1080 | * 1 incoming channel (@dest) | 1027 | * 1 incoming channel (@dest) |
1081 | * TOTAL_PACKETS received data packet (@dest) | 1028 | * total_packets received data packet (@dest) |
1082 | * TOTAL_PACKETS received data packet (@orig) | 1029 | * total_packets received data packet (@orig) |
1083 | * 1 received channel destroy (@dest) | 1030 | * 1 received channel destroy (@dest) |
1084 | */ | 1031 | */ |
1085 | ok_goal = TOTAL_PACKETS * 2 + 2; | 1032 | ok_goal = total_packets * 2 + 2; |
1086 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n"); | 1033 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n"); |
1087 | test = SPEED_ACK; | 1034 | test = SPEED_ACK; |
1088 | test_name = "speed ack"; | 1035 | test_name = "speed ack"; |
@@ -1092,11 +1039,11 @@ main (int argc, char *argv[]) | |||
1092 | /* Test is supposed to generate the following callbacks: | 1039 | /* Test is supposed to generate the following callbacks: |
1093 | * 1 incoming channel (@dest) | 1040 | * 1 incoming channel (@dest) |
1094 | * 1 initial packet (@dest) | 1041 | * 1 initial packet (@dest) |
1095 | * TOTAL_PACKETS received data packet (@dest) | 1042 | * total_packets received data packet (@dest) |
1096 | * 1 received data packet (@orig) | 1043 | * 1 received data packet (@orig) |
1097 | * 1 received channel destroy (@dest) | 1044 | * 1 received channel destroy (@dest) |
1098 | */ | 1045 | */ |
1099 | ok_goal = TOTAL_PACKETS + 4; | 1046 | ok_goal = total_packets + 4; |
1100 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n"); | 1047 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n"); |
1101 | if (strstr (argv[0], "_reliable") != NULL) | 1048 | if (strstr (argv[0], "_reliable") != NULL) |
1102 | { | 1049 | { |
@@ -1137,22 +1084,22 @@ main (int argc, char *argv[]) | |||
1137 | p_ids = 0; | 1084 | p_ids = 0; |
1138 | ports[0] = &port; | 1085 | ports[0] = &port; |
1139 | ports[1] = NULL; | 1086 | ports[1] = NULL; |
1140 | GNUNET_CADET_TEST_run ("test_cadet_small", | 1087 | GNUNET_CADET_TEST_ruN ("test_cadet_small", |
1141 | config_file, | 1088 | config_file, |
1142 | peers_requested, | 1089 | peers_requested, |
1143 | &tmain, | 1090 | &tmain, |
1144 | NULL, /* tmain cls */ | 1091 | NULL, /* tmain cls */ |
1145 | &incoming_channel, | 1092 | &connect_handler, |
1146 | &channel_cleaner, | 1093 | NULL, |
1147 | handlers, | 1094 | &disconnect_handler, |
1148 | ports); | 1095 | handlers, |
1096 | ports); | ||
1149 | if (NULL != strstr (argv[0], "_reliable")) | 1097 | if (NULL != strstr (argv[0], "_reliable")) |
1150 | msg_dropped = 0; /* dropped should be retransmitted */ | 1098 | msg_dropped = 0; /* dropped should be retransmitted */ |
1151 | 1099 | ||
1152 | if (ok_goal > ok - msg_dropped) | 1100 | if (ok_goal > ok - msg_dropped) |
1153 | { | 1101 | { |
1154 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1102 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "FAILED! (%d/%d)\n", ok, ok_goal); |
1155 | "FAILED! (%d/%d)\n", ok, ok_goal); | ||
1156 | return 1; | 1103 | return 1; |
1157 | } | 1104 | } |
1158 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n"); | 1105 | 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 | |||
33 | struct GNUNET_TESTING_Peer *me; | ||
34 | |||
35 | static struct GNUNET_CADET_Handle *cadet_peer_1; | ||
36 | |||
37 | static struct GNUNET_CADET_Handle *cadet_peer_2; | ||
38 | |||
39 | static struct GNUNET_CADET_Channel *ch; | ||
40 | |||
41 | static int result = GNUNET_OK; | ||
42 | |||
43 | static int got_data = GNUNET_NO; | ||
44 | |||
45 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
46 | |||
47 | static struct GNUNET_SCHEDULER_Task *connect_task; | ||
48 | |||
49 | static struct GNUNET_CADET_TransmitHandle *mth; | ||
50 | |||
51 | |||
52 | /** | ||
53 | * Connect to other client and send data | ||
54 | * | ||
55 | * @param cls Closue (unused). | ||
56 | */ | ||
57 | static void | ||
58 | do_connect (void *cls); | ||
59 | |||
60 | |||
61 | /** | ||
62 | * Shutdown nicely | ||
63 | */ | ||
64 | static void | ||
65 | do_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 | */ | ||
104 | static void | ||
105 | do_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 | */ | ||
124 | static int | ||
125 | data_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 | */ | ||
151 | static void * | ||
152 | inbound_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 | */ | ||
183 | static void | ||
184 | channel_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 | */ | ||
215 | static 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 | */ | ||
224 | static 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 | */ | ||
239 | static size_t | ||
240 | do_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 | */ | ||
263 | static void | ||
264 | do_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 | */ | ||
290 | static void | ||
291 | run (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 | */ | ||
337 | int | ||
338 | main (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_local_mq.c b/src/cadet/test_cadet_local_mq.c index 19bafbed1..3089c7fbb 100644 --- a/src/cadet/test_cadet_local_mq.c +++ b/src/cadet/test_cadet_local_mq.c | |||
@@ -132,12 +132,12 @@ do_abort (void *cls) | |||
132 | /** | 132 | /** |
133 | * Method called whenever a peer connects to a port in MQ-based CADET. | 133 | * Method called whenever a peer connects to a port in MQ-based CADET. |
134 | * | 134 | * |
135 | * @param cls Closure from #GNUNET_CADET_open_porT. | 135 | * @param cls Closure from #GNUNET_CADET_open_port. |
136 | * @param channel New handle to the channel. | 136 | * @param channel New handle to the channel. |
137 | * @param source Peer that started this channel. | 137 | * @param source Peer that started this channel. |
138 | * @return Closure for the incoming @a channel. It's given to: | 138 | * @return Closure for the incoming @a channel. It's given to: |
139 | * - The #GNUNET_CADET_DisconnectEventHandler (given to | 139 | * - The #GNUNET_CADET_DisconnectEventHandler (given to |
140 | * #GNUNET_CADET_open_porT) when the channel dies. | 140 | * #GNUNET_CADET_open_port) when the channel dies. |
141 | * - Each the #GNUNET_MQ_MessageCallback handlers for each message | 141 | * - Each the #GNUNET_MQ_MessageCallback handlers for each message |
142 | * received on the @a channel. | 142 | * received on the @a channel. |
143 | */ | 143 | */ |
@@ -235,7 +235,7 @@ do_connect (void *cls) | |||
235 | GNUNET_TESTING_peer_get_identity (me, &id); | 235 | GNUNET_TESTING_peer_get_identity (me, &id); |
236 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 236 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
237 | "creating channel\n"); | 237 | "creating channel\n"); |
238 | ch = GNUNET_CADET_channel_creatE (cadet_peer_1, /* cadet handle */ | 238 | ch = GNUNET_CADET_channel_create (cadet_peer_1, /* cadet handle */ |
239 | NULL, /* channel cls */ | 239 | NULL, /* channel cls */ |
240 | &id, /* destination */ | 240 | &id, /* destination */ |
241 | GC_u2h (TEST_MESSAGE_TYPE), /* port */ | 241 | GC_u2h (TEST_MESSAGE_TYPE), /* port */ |
@@ -282,8 +282,8 @@ run (void *cls, | |||
282 | abort_task = GNUNET_SCHEDULER_add_delayed (delay, | 282 | abort_task = GNUNET_SCHEDULER_add_delayed (delay, |
283 | &do_abort, | 283 | &do_abort, |
284 | (void *) (long) __LINE__); | 284 | (void *) (long) __LINE__); |
285 | cadet_peer_1 = GNUNET_CADET_connecT (cfg); | 285 | cadet_peer_1 = GNUNET_CADET_connect (cfg); |
286 | cadet_peer_2 = GNUNET_CADET_connecT (cfg); | 286 | cadet_peer_2 = GNUNET_CADET_connect (cfg); |
287 | 287 | ||
288 | if ( (NULL == cadet_peer_1) || | 288 | if ( (NULL == cadet_peer_1) || |
289 | (NULL == cadet_peer_2) ) | 289 | (NULL == cadet_peer_2) ) |
@@ -297,7 +297,7 @@ run (void *cls, | |||
297 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CADET 1: %p\n", cadet_peer_1); | 297 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CADET 1: %p\n", cadet_peer_1); |
298 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CADET 2: %p\n", cadet_peer_2); | 298 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CADET 2: %p\n", cadet_peer_2); |
299 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "handlers 2: %p\n", handlers); | 299 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "handlers 2: %p\n", handlers); |
300 | GNUNET_CADET_open_porT (cadet_peer_2, /* cadet handle */ | 300 | GNUNET_CADET_open_port (cadet_peer_2, /* cadet handle */ |
301 | GC_u2h (TEST_PORT_ID), /* port id */ | 301 | GC_u2h (TEST_PORT_ID), /* port id */ |
302 | &connected, /* connect handler */ | 302 | &connected, /* connect handler */ |
303 | (void *) 2L, /* handle for #connected */ | 303 | (void *) 2L, /* handle for #connected */ |
diff --git a/src/cadet/test_cadet_new.c b/src/cadet/test_cadet_new.c deleted file mode 100644 index d32404815..000000000 --- a/src/cadet/test_cadet_new.c +++ /dev/null | |||
@@ -1,1048 +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 | */ | ||
37 | struct CadetTestChannelWrapper | ||
38 | { | ||
39 | /** | ||
40 | * Channel pointer. | ||
41 | */ | ||
42 | struct GNUNET_CADET_Channel *ch; | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * How many messages to send | ||
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 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 | */ | ||
74 | static int test; | ||
75 | |||
76 | /** | ||
77 | * String with test name | ||
78 | */ | ||
79 | static char *test_name; | ||
80 | |||
81 | /** | ||
82 | * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic. | ||
83 | */ | ||
84 | static int test_backwards = GNUNET_NO; | ||
85 | |||
86 | /** | ||
87 | * How many events have happened | ||
88 | */ | ||
89 | static int ok; | ||
90 | |||
91 | /** | ||
92 | * Number of events expected to conclude the test successfully. | ||
93 | */ | ||
94 | static int ok_goal; | ||
95 | |||
96 | /** | ||
97 | * Size of each test packet's payload | ||
98 | */ | ||
99 | static size_t size_payload = sizeof (uint32_t); | ||
100 | |||
101 | /** | ||
102 | * Operation to get peer ids. | ||
103 | */ | ||
104 | static struct GNUNET_TESTBED_Operation *t_op[2]; | ||
105 | |||
106 | /** | ||
107 | * Peer ids. | ||
108 | */ | ||
109 | static struct GNUNET_PeerIdentity *p_id[2]; | ||
110 | |||
111 | /** | ||
112 | * Port ID | ||
113 | */ | ||
114 | static struct GNUNET_HashCode port; | ||
115 | |||
116 | /** | ||
117 | * Peer ids counter. | ||
118 | */ | ||
119 | static unsigned int p_ids; | ||
120 | |||
121 | /** | ||
122 | * Is the setup initialized? | ||
123 | */ | ||
124 | static int initialized; | ||
125 | |||
126 | /** | ||
127 | * Number of payload packes sent. | ||
128 | */ | ||
129 | static int data_sent; | ||
130 | |||
131 | /** | ||
132 | * Number of payload packets received. | ||
133 | */ | ||
134 | static int data_received; | ||
135 | |||
136 | /** | ||
137 | * Number of payload packed acknowledgements sent. | ||
138 | */ | ||
139 | static int ack_sent; | ||
140 | |||
141 | /** | ||
142 | * Number of payload packed explicitly (app level) acknowledged. | ||
143 | */ | ||
144 | static int ack_received; | ||
145 | |||
146 | /** | ||
147 | * Total number of peers asked to run. | ||
148 | */ | ||
149 | static unsigned long long peers_requested; | ||
150 | |||
151 | /** | ||
152 | * Number of currently running peers (should be same as @c peers_requested). | ||
153 | */ | ||
154 | static unsigned long long peers_running; | ||
155 | |||
156 | /** | ||
157 | * Test context (to shut down). | ||
158 | */ | ||
159 | struct GNUNET_CADET_TEST_Context *test_ctx; | ||
160 | |||
161 | /** | ||
162 | * Task called to disconnect peers. | ||
163 | */ | ||
164 | static struct GNUNET_SCHEDULER_Task *disconnect_task; | ||
165 | |||
166 | /** | ||
167 | * Task To perform tests | ||
168 | */ | ||
169 | static struct GNUNET_SCHEDULER_Task *test_task; | ||
170 | |||
171 | /** | ||
172 | * Task runnining #send_next_msg(). | ||
173 | */ | ||
174 | static struct GNUNET_SCHEDULER_Task *send_next_msg_task; | ||
175 | |||
176 | /** | ||
177 | * Cadet handle for the root peer | ||
178 | */ | ||
179 | static struct GNUNET_CADET_Handle *h1; | ||
180 | |||
181 | /** | ||
182 | * Cadet handle for the first leaf peer | ||
183 | */ | ||
184 | static struct GNUNET_CADET_Handle *h2; | ||
185 | |||
186 | /** | ||
187 | * Channel handle for the root peer | ||
188 | */ | ||
189 | static struct GNUNET_CADET_Channel *outgoing_ch; | ||
190 | |||
191 | /** | ||
192 | * Channel handle for the dest peer | ||
193 | */ | ||
194 | static struct GNUNET_CADET_Channel *incoming_ch; | ||
195 | |||
196 | /** | ||
197 | * Time we started the data transmission (after channel has been established | ||
198 | * and initilized). | ||
199 | */ | ||
200 | static struct GNUNET_TIME_Absolute start_time; | ||
201 | |||
202 | /** | ||
203 | * Peers handle. | ||
204 | */ | ||
205 | static struct GNUNET_TESTBED_Peer **testbed_peers; | ||
206 | |||
207 | /** | ||
208 | * Statistics operation handle. | ||
209 | */ | ||
210 | static struct GNUNET_TESTBED_Operation *stats_op; | ||
211 | |||
212 | /** | ||
213 | * Keepalives sent. | ||
214 | */ | ||
215 | static unsigned int ka_sent; | ||
216 | |||
217 | /** | ||
218 | * Keepalives received. | ||
219 | */ | ||
220 | static unsigned int ka_received; | ||
221 | |||
222 | /** | ||
223 | * How many messages were dropped by CADET because of full buffers? | ||
224 | */ | ||
225 | static unsigned int msg_dropped; | ||
226 | |||
227 | |||
228 | /******************************************************************************/ | ||
229 | |||
230 | |||
231 | /******************************************************************************/ | ||
232 | |||
233 | |||
234 | /** | ||
235 | * Get the channel considered as the "target" or "receiver", depending on | ||
236 | * the test type and size. | ||
237 | * | ||
238 | * @return Channel handle of the target client, either 0 (for backward tests) | ||
239 | * or the last peer in the line (for other tests). | ||
240 | */ | ||
241 | static struct GNUNET_CADET_Channel * | ||
242 | get_target_channel () | ||
243 | { | ||
244 | if (SPEED == test && GNUNET_YES == test_backwards) | ||
245 | return outgoing_ch; | ||
246 | else | ||
247 | return incoming_ch; | ||
248 | } | ||
249 | |||
250 | |||
251 | /** | ||
252 | * Show the results of the test (banwidth acheived) and log them to GAUGER | ||
253 | */ | ||
254 | static void | ||
255 | show_end_data (void) | ||
256 | { | ||
257 | static struct GNUNET_TIME_Absolute end_time; | ||
258 | static struct GNUNET_TIME_Relative total_time; | ||
259 | |||
260 | end_time = GNUNET_TIME_absolute_get (); | ||
261 | total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time); | ||
262 | FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name); | ||
263 | FPRINTF (stderr, "Test time %s\n", | ||
264 | GNUNET_STRINGS_relative_time_to_string (total_time, GNUNET_YES)); | ||
265 | FPRINTF (stderr, "Test bandwidth: %f kb/s\n", 4 * TOTAL_PACKETS * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms | ||
266 | FPRINTF (stderr, "Test throughput: %f packets/s\n\n", TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms | ||
267 | GAUGER ("CADET", test_name, | ||
268 | TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000), | ||
269 | "packets/s"); | ||
270 | } | ||
271 | |||
272 | |||
273 | /** | ||
274 | * Disconnect from cadet services af all peers, call shutdown. | ||
275 | * | ||
276 | * @param cls Closure (line number from which termination was requested). | ||
277 | * @param tc Task Context. | ||
278 | */ | ||
279 | static void | ||
280 | disconnect_cadet_peers (void *cls) | ||
281 | { | ||
282 | long line = (long) cls; | ||
283 | unsigned int i; | ||
284 | |||
285 | disconnect_task = NULL; | ||
286 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
287 | "disconnecting cadet service of peers, called from line %ld\n", | ||
288 | line); | ||
289 | for (i = 0; i < 2; i++) | ||
290 | { | ||
291 | GNUNET_TESTBED_operation_done (t_op[i]); | ||
292 | } | ||
293 | if (NULL != outgoing_ch) | ||
294 | { | ||
295 | GNUNET_CADET_channel_destroy (outgoing_ch); | ||
296 | outgoing_ch = NULL; | ||
297 | } | ||
298 | if (NULL != incoming_ch) | ||
299 | { | ||
300 | GNUNET_CADET_channel_destroy (incoming_ch); | ||
301 | incoming_ch = NULL; | ||
302 | } | ||
303 | GNUNET_CADET_TEST_cleanup (test_ctx); | ||
304 | GNUNET_SCHEDULER_shutdown (); | ||
305 | } | ||
306 | |||
307 | |||
308 | /** | ||
309 | * Shut down peergroup, clean up. | ||
310 | * | ||
311 | * @param cls Closure (unused). | ||
312 | * @param tc Task Context. | ||
313 | */ | ||
314 | static void | ||
315 | shutdown_task (void *cls) | ||
316 | { | ||
317 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n"); | ||
318 | if (NULL != send_next_msg_task) | ||
319 | { | ||
320 | GNUNET_SCHEDULER_cancel (send_next_msg_task); | ||
321 | send_next_msg_task = NULL; | ||
322 | } | ||
323 | if (NULL != test_task) | ||
324 | { | ||
325 | GNUNET_SCHEDULER_cancel (test_task); | ||
326 | test_task = NULL; | ||
327 | } | ||
328 | if (NULL != disconnect_task) | ||
329 | { | ||
330 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
331 | disconnect_task = | ||
332 | GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) __LINE__); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | |||
337 | /** | ||
338 | * Stats callback. Finish the stats testbed operation and when all stats have | ||
339 | * been iterated, shutdown the test. | ||
340 | * | ||
341 | * @param cls Closure (line number from which termination was requested). | ||
342 | * @param op the operation that has been finished | ||
343 | * @param emsg error message in case the operation has failed; will be NULL if | ||
344 | * operation has executed successfully. | ||
345 | */ | ||
346 | static void | ||
347 | stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) | ||
348 | { | ||
349 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " KA sent: %u, KA received: %u\n", | ||
350 | ka_sent, ka_received); | ||
351 | if ((KEEPALIVE == test) && ((ka_sent < 2) || (ka_sent > ka_received + 1))) | ||
352 | { | ||
353 | GNUNET_break (0); | ||
354 | ok--; | ||
355 | } | ||
356 | GNUNET_TESTBED_operation_done (stats_op); | ||
357 | |||
358 | if (NULL != disconnect_task) | ||
359 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
360 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, cls); | ||
361 | } | ||
362 | |||
363 | |||
364 | /** | ||
365 | * Process statistic values. | ||
366 | * | ||
367 | * @param cls closure (line number, unused) | ||
368 | * @param peer the peer the statistic belong to | ||
369 | * @param subsystem name of subsystem that created the statistic | ||
370 | * @param name the name of the datum | ||
371 | * @param value the current value | ||
372 | * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not | ||
373 | * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration | ||
374 | */ | ||
375 | static int | ||
376 | stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer, | ||
377 | const char *subsystem, const char *name, uint64_t value, | ||
378 | int is_persistent) | ||
379 | { | ||
380 | static const char *s_sent = "# keepalives sent"; | ||
381 | static const char *s_recv = "# keepalives received"; | ||
382 | static const char *rdrops = "# messages dropped due to full buffer"; | ||
383 | static const char *cdrops = "# messages dropped due to slow client"; | ||
384 | uint32_t i; | ||
385 | |||
386 | i = GNUNET_TESTBED_get_index (peer); | ||
387 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "STATS PEER %u - %s [%s]: %llu\n", i, | ||
388 | subsystem, name, (unsigned long long) value); | ||
389 | if (0 == strncmp (s_sent, name, strlen (s_sent)) && 0 == i) | ||
390 | ka_sent = value; | ||
391 | if (0 == strncmp (s_recv, name, strlen (s_recv)) && peers_requested - 1 == i) | ||
392 | ka_received = value; | ||
393 | if (0 == strncmp (rdrops, name, strlen (rdrops))) | ||
394 | msg_dropped += value; | ||
395 | if (0 == strncmp (cdrops, name, strlen (cdrops))) | ||
396 | msg_dropped += value; | ||
397 | |||
398 | return GNUNET_OK; | ||
399 | } | ||
400 | |||
401 | |||
402 | /** | ||
403 | * Task to gather all statistics. | ||
404 | * | ||
405 | * @param cls Closure (line from which the task was scheduled). | ||
406 | */ | ||
407 | static void | ||
408 | gather_stats_and_exit (void *cls) | ||
409 | { | ||
410 | long l = (long) cls; | ||
411 | |||
412 | disconnect_task = NULL; | ||
413 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
414 | "gathering statistics from line %ld\n", | ||
415 | l); | ||
416 | if (NULL != outgoing_ch) | ||
417 | { | ||
418 | GNUNET_CADET_channel_destroy (outgoing_ch); | ||
419 | outgoing_ch = NULL; | ||
420 | } | ||
421 | stats_op = GNUNET_TESTBED_get_statistics (peers_running, | ||
422 | testbed_peers, | ||
423 | "cadet", | ||
424 | NULL, | ||
425 | &stats_iterator, | ||
426 | stats_cont, | ||
427 | cls); | ||
428 | } | ||
429 | |||
430 | |||
431 | |||
432 | /** | ||
433 | * Abort test: schedule disconnect and shutdown immediately | ||
434 | * | ||
435 | * @param line Line in the code the abort is requested from (__LINE__). | ||
436 | */ | ||
437 | static void | ||
438 | abort_test (long line) | ||
439 | { | ||
440 | if (NULL != disconnect_task) | ||
441 | { | ||
442 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
443 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting test from %ld\n", line); | ||
444 | disconnect_task = | ||
445 | GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) line); | ||
446 | } | ||
447 | } | ||
448 | |||
449 | |||
450 | /** | ||
451 | * Send a message on the channel with the appropriate size and payload. | ||
452 | * | ||
453 | * Update the appropriate *_sent counter. | ||
454 | * | ||
455 | * @param channel Channel to send the message on. | ||
456 | */ | ||
457 | static void | ||
458 | send_test_message (struct GNUNET_CADET_Channel *channel) | ||
459 | { | ||
460 | struct GNUNET_MQ_Envelope *env; | ||
461 | struct GNUNET_MessageHeader *msg; | ||
462 | uint32_t *data; | ||
463 | int *counter; | ||
464 | int size; | ||
465 | |||
466 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
467 | "Sending test message on channel %p\n", | ||
468 | channel); | ||
469 | size = size_payload; | ||
470 | if (GNUNET_NO == initialized) | ||
471 | { | ||
472 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending INITIALIZER\n"); | ||
473 | size += 1000; | ||
474 | counter = &data_sent; | ||
475 | if (SPEED_ACK == test) // FIXME unify SPEED_ACK with an initializer | ||
476 | data_sent++; | ||
477 | } | ||
478 | else if (SPEED == test || SPEED_ACK == test) | ||
479 | { | ||
480 | counter = get_target_channel() == channel ? &ack_sent : &data_sent; | ||
481 | size += *counter; | ||
482 | *counter = *counter + 1; | ||
483 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending message %u\n", *counter); | ||
484 | } | ||
485 | else | ||
486 | { | ||
487 | counter = &ack_sent; | ||
488 | } | ||
489 | env = GNUNET_MQ_msg_extra (msg, size, GNUNET_MESSAGE_TYPE_DUMMY); | ||
490 | |||
491 | data = (uint32_t *) &msg[1]; | ||
492 | *data = htonl (*counter); | ||
493 | GNUNET_MQ_send (GNUNET_CADET_get_mq (channel), env); | ||
494 | } | ||
495 | |||
496 | /** | ||
497 | * Task to request a new data transmission in a SPEED test, without waiting | ||
498 | * for previous messages to be sent/arrrive. | ||
499 | * | ||
500 | * @param cls Closure (unused). | ||
501 | */ | ||
502 | static void | ||
503 | send_next_msg (void *cls) | ||
504 | { | ||
505 | struct GNUNET_CADET_Channel *channel; | ||
506 | |||
507 | send_next_msg_task = NULL; | ||
508 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending next message: %d\n", data_sent); | ||
509 | |||
510 | channel = GNUNET_YES == test_backwards ? incoming_ch : outgoing_ch; | ||
511 | GNUNET_assert (NULL != channel); | ||
512 | GNUNET_assert (SPEED == test); | ||
513 | send_test_message (channel); | ||
514 | if (data_sent < TOTAL_PACKETS) | ||
515 | { | ||
516 | /* SPEED test: Send all messages as soon as possible */ | ||
517 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
518 | "Scheduling message %d\n", | ||
519 | data_sent + 1); | ||
520 | send_next_msg_task = GNUNET_SCHEDULER_add_now (&send_next_msg, NULL); | ||
521 | } | ||
522 | } | ||
523 | |||
524 | |||
525 | /** | ||
526 | * Every few messages cancel the timeout task and re-schedule it again, to | ||
527 | * avoid timing out when traffic keeps coming. | ||
528 | * | ||
529 | * @param line Code line number to log if a timeout occurs. | ||
530 | */ | ||
531 | static void | ||
532 | reschedule_timeout_task (long line) | ||
533 | { | ||
534 | if ((ok % 10) == 0) | ||
535 | { | ||
536 | if (NULL != disconnect_task) | ||
537 | { | ||
538 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
539 | " reschedule timeout every 10 messages\n"); | ||
540 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
541 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
542 | &gather_stats_and_exit, | ||
543 | (void *) line); | ||
544 | } | ||
545 | } | ||
546 | } | ||
547 | |||
548 | |||
549 | /** | ||
550 | * Check if payload is sane (size contains payload). | ||
551 | * | ||
552 | * @param cls should match #ch | ||
553 | * @param message The actual message. | ||
554 | * @return #GNUNET_OK to keep the channel open, | ||
555 | * #GNUNET_SYSERR to close it (signal serious error). | ||
556 | */ | ||
557 | static int | ||
558 | check_data (void *cls, const struct GNUNET_MessageHeader *message) | ||
559 | { | ||
560 | if (sizeof (struct GNUNET_MessageHeader) >= ntohs (message->size)) | ||
561 | return GNUNET_SYSERR; | ||
562 | return GNUNET_OK; /* all is well-formed */ | ||
563 | } | ||
564 | |||
565 | |||
566 | /** | ||
567 | * Function is called whenever a message is received. | ||
568 | * | ||
569 | * @param cls closure (set from GNUNET_CADET_connect(), peer number) | ||
570 | * @param message the actual message | ||
571 | */ | ||
572 | static void | ||
573 | handle_data (void *cls, const struct GNUNET_MessageHeader *message) | ||
574 | { | ||
575 | struct CadetTestChannelWrapper *ch = cls; | ||
576 | struct GNUNET_CADET_Channel *channel = ch->ch; | ||
577 | uint32_t *data; | ||
578 | uint32_t payload; | ||
579 | int *counter; | ||
580 | |||
581 | ok++; | ||
582 | counter = get_target_channel () == channel ? &data_received : &ack_received; | ||
583 | |||
584 | reschedule_timeout_task ((long) __LINE__); | ||
585 | |||
586 | if (channel == outgoing_ch) | ||
587 | { | ||
588 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n"); | ||
589 | } | ||
590 | else if (channel == incoming_ch) | ||
591 | { | ||
592 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Leaf client got a message.\n"); | ||
593 | } | ||
594 | else | ||
595 | { | ||
596 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unknown channel %p.\n", channel); | ||
597 | GNUNET_assert (0); | ||
598 | } | ||
599 | |||
600 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal); | ||
601 | data = (uint32_t *) &message[1]; | ||
602 | payload = ntohl (*data); | ||
603 | if (payload == *counter) | ||
604 | { | ||
605 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload as expected: %u\n", payload); | ||
606 | } | ||
607 | else | ||
608 | { | ||
609 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
610 | " payload %u, expected: %u\n", | ||
611 | payload, *counter); | ||
612 | } | ||
613 | |||
614 | if (GNUNET_NO == initialized) | ||
615 | { | ||
616 | initialized = GNUNET_YES; | ||
617 | start_time = GNUNET_TIME_absolute_get (); | ||
618 | if (SPEED == test) | ||
619 | { | ||
620 | GNUNET_assert (incoming_ch == channel); | ||
621 | send_next_msg_task = GNUNET_SCHEDULER_add_now (&send_next_msg, NULL); | ||
622 | return; | ||
623 | } | ||
624 | } | ||
625 | |||
626 | (*counter)++; | ||
627 | if (get_target_channel () == channel) /* Got "data" */ | ||
628 | { | ||
629 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received); | ||
630 | if (SPEED != test || (ok_goal - 2) == ok) | ||
631 | { | ||
632 | /* Send ACK */ | ||
633 | send_test_message (channel); | ||
634 | return; | ||
635 | } | ||
636 | else | ||
637 | { | ||
638 | if (data_received < TOTAL_PACKETS) | ||
639 | return; | ||
640 | } | ||
641 | } | ||
642 | else /* Got "ack" */ | ||
643 | { | ||
644 | if (SPEED_ACK == test || SPEED == test) | ||
645 | { | ||
646 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", ack_received); | ||
647 | /* Send more data */ | ||
648 | send_test_message (channel); | ||
649 | if (ack_received < TOTAL_PACKETS && SPEED != test) | ||
650 | return; | ||
651 | if (ok == 2 && SPEED == test) | ||
652 | return; | ||
653 | show_end_data (); | ||
654 | } | ||
655 | if (test == P2P_SIGNAL) | ||
656 | { | ||
657 | GNUNET_CADET_channel_destroy (incoming_ch); | ||
658 | incoming_ch = NULL; | ||
659 | } | ||
660 | else | ||
661 | { | ||
662 | GNUNET_CADET_channel_destroy (outgoing_ch); | ||
663 | outgoing_ch = NULL; | ||
664 | } | ||
665 | } | ||
666 | } | ||
667 | |||
668 | |||
669 | /** | ||
670 | * Method called whenever a peer connects to a port in MQ-based CADET. | ||
671 | * | ||
672 | * @param cls Closure from #GNUNET_CADET_open_porT (peer # as long). | ||
673 | * @param channel New handle to the channel. | ||
674 | * @param source Peer that started this channel. | ||
675 | * @return Closure for the incoming @a channel. It's given to: | ||
676 | * - The #GNUNET_CADET_DisconnectEventHandler (given to | ||
677 | * #GNUNET_CADET_open_porT) when the channel dies. | ||
678 | * - Each the #GNUNET_MQ_MessageCallback handlers for each message | ||
679 | * received on the @a channel. | ||
680 | */ | ||
681 | static void * | ||
682 | connect_handler (void *cls, struct GNUNET_CADET_Channel *channel, | ||
683 | const struct GNUNET_PeerIdentity *source) | ||
684 | { | ||
685 | struct CadetTestChannelWrapper *ch; | ||
686 | long peer = (long) cls; | ||
687 | |||
688 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Incoming channel from %s to peer %ld\n", | ||
689 | GNUNET_i2s (source), peer); | ||
690 | ok++; | ||
691 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); | ||
692 | if (peer == peers_requested - 1) | ||
693 | { | ||
694 | if (NULL != incoming_ch) | ||
695 | { | ||
696 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
697 | "Duplicate incoming channel for client %lu\n", (long) cls); | ||
698 | GNUNET_assert (0); | ||
699 | } | ||
700 | incoming_ch = channel; | ||
701 | } | ||
702 | else | ||
703 | { | ||
704 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
705 | "Incoming channel for unexpected peer #%lu\n", (long) cls); | ||
706 | GNUNET_assert (0); | ||
707 | } | ||
708 | if (NULL != disconnect_task) | ||
709 | { | ||
710 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
711 | disconnect_task = | ||
712 | GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &gather_stats_and_exit, | ||
713 | (void *) __LINE__); | ||
714 | } | ||
715 | |||
716 | /* TODO: cannot return channel as-is, in order to unify the data handlers */ | ||
717 | ch = GNUNET_new (struct CadetTestChannelWrapper); | ||
718 | ch->ch = channel; | ||
719 | |||
720 | return ch; | ||
721 | } | ||
722 | |||
723 | |||
724 | /** | ||
725 | * Function called whenever an MQ-channel is destroyed, even if the destruction | ||
726 | * was requested by #GNUNET_CADET_channel_destroy. | ||
727 | * It must NOT call #GNUNET_CADET_channel_destroy on the channel. | ||
728 | * | ||
729 | * It should clean up any associated state, including cancelling any pending | ||
730 | * transmission on this channel. | ||
731 | * | ||
732 | * @param cls Channel closure (channel wrapper). | ||
733 | * @param channel Connection to the other end (henceforth invalid). | ||
734 | */ | ||
735 | static void | ||
736 | disconnect_handler (void *cls, const struct GNUNET_CADET_Channel *channel) | ||
737 | { | ||
738 | struct CadetTestChannelWrapper *ch_w = cls; | ||
739 | |||
740 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Channel disconnected\n"); | ||
741 | GNUNET_assert (ch_w->ch == channel); | ||
742 | if (channel == incoming_ch) | ||
743 | { | ||
744 | ok++; | ||
745 | incoming_ch = NULL; | ||
746 | } | ||
747 | else if (outgoing_ch == channel | ||
748 | ) | ||
749 | { | ||
750 | if (P2P_SIGNAL == test) | ||
751 | { | ||
752 | ok++; | ||
753 | } | ||
754 | outgoing_ch = NULL; | ||
755 | } | ||
756 | else | ||
757 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unknown channel! %p\n", channel); | ||
758 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); | ||
759 | |||
760 | if (NULL != disconnect_task) | ||
761 | { | ||
762 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
763 | disconnect_task = | ||
764 | GNUNET_SCHEDULER_add_now (&gather_stats_and_exit, (void *) __LINE__); | ||
765 | } | ||
766 | } | ||
767 | |||
768 | |||
769 | /** | ||
770 | * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES. | ||
771 | * | ||
772 | * Testcase continues when the root receives confirmation of connected peers, | ||
773 | * on callback function ch. | ||
774 | * | ||
775 | * @param cls Closure (unused). | ||
776 | */ | ||
777 | static void | ||
778 | start_test (void *cls) | ||
779 | { | ||
780 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
781 | GNUNET_MQ_hd_var_size (data, | ||
782 | GNUNET_MESSAGE_TYPE_DUMMY, | ||
783 | struct GNUNET_MessageHeader, | ||
784 | NULL), | ||
785 | GNUNET_MQ_handler_end () | ||
786 | }; | ||
787 | struct CadetTestChannelWrapper *ch; | ||
788 | enum GNUNET_CADET_ChannelOption flags; | ||
789 | |||
790 | test_task = NULL; | ||
791 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "start_test\n"); | ||
792 | if (NULL != disconnect_task) | ||
793 | { | ||
794 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
795 | disconnect_task = NULL; | ||
796 | } | ||
797 | |||
798 | flags = GNUNET_CADET_OPTION_DEFAULT; | ||
799 | if (SPEED_REL == test) | ||
800 | { | ||
801 | test = SPEED; | ||
802 | flags |= GNUNET_CADET_OPTION_RELIABLE; | ||
803 | } | ||
804 | |||
805 | ch = GNUNET_new (struct CadetTestChannelWrapper); | ||
806 | outgoing_ch = GNUNET_CADET_channel_creatE (h1, | ||
807 | ch, | ||
808 | p_id[1], | ||
809 | &port, | ||
810 | flags, | ||
811 | NULL, | ||
812 | &disconnect_handler, | ||
813 | handlers); | ||
814 | ch->ch = outgoing_ch; | ||
815 | |||
816 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
817 | &gather_stats_and_exit, | ||
818 | (void *) __LINE__); | ||
819 | if (KEEPALIVE == test) | ||
820 | return; /* Don't send any data. */ | ||
821 | |||
822 | |||
823 | data_received = 0; | ||
824 | data_sent = 0; | ||
825 | ack_received = 0; | ||
826 | ack_sent = 0; | ||
827 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending data initializer...\n"); | ||
828 | send_test_message (outgoing_ch); | ||
829 | } | ||
830 | |||
831 | |||
832 | /** | ||
833 | * Callback to be called when the requested peer information is available | ||
834 | * | ||
835 | * @param cls the closure from GNUNET_TESTBED_peer_get_information() | ||
836 | * @param op the operation this callback corresponds to | ||
837 | * @param pinfo the result; will be NULL if the operation has failed | ||
838 | * @param emsg error message if the operation has failed; | ||
839 | * NULL if the operation is successfull | ||
840 | */ | ||
841 | static void | ||
842 | pi_cb (void *cls, struct GNUNET_TESTBED_Operation *op, | ||
843 | const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg) | ||
844 | { | ||
845 | long i = (long) cls; | ||
846 | |||
847 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ID callback for %ld\n", i); | ||
848 | |||
849 | if ((NULL == pinfo) || (NULL != emsg)) | ||
850 | { | ||
851 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg); | ||
852 | abort_test (__LINE__); | ||
853 | return; | ||
854 | } | ||
855 | p_id[i] = pinfo->result.id; | ||
856 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i])); | ||
857 | p_ids++; | ||
858 | if (p_ids < 2) | ||
859 | return; | ||
860 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n"); | ||
861 | test_task = GNUNET_SCHEDULER_add_now (&start_test, NULL); | ||
862 | } | ||
863 | |||
864 | |||
865 | /** | ||
866 | * test main: start test when all peers are connected | ||
867 | * | ||
868 | * @param cls Closure. | ||
869 | * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end. | ||
870 | * @param num_peers Number of peers that are running. | ||
871 | * @param peers Array of peers. | ||
872 | * @param cadets Handle to each of the CADETs of the peers. | ||
873 | */ | ||
874 | static void | ||
875 | tmain (void *cls, | ||
876 | struct GNUNET_CADET_TEST_Context *ctx, | ||
877 | unsigned int num_peers, | ||
878 | struct GNUNET_TESTBED_Peer **peers, | ||
879 | struct GNUNET_CADET_Handle **cadets) | ||
880 | { | ||
881 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n"); | ||
882 | ok = 0; | ||
883 | test_ctx = ctx; | ||
884 | peers_running = num_peers; | ||
885 | GNUNET_assert (peers_running == peers_requested); | ||
886 | testbed_peers = peers; | ||
887 | h1 = cadets[0]; | ||
888 | h2 = cadets[num_peers - 1]; | ||
889 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
890 | &disconnect_cadet_peers, | ||
891 | (void *) __LINE__); | ||
892 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); | ||
893 | t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0], | ||
894 | GNUNET_TESTBED_PIT_IDENTITY, | ||
895 | &pi_cb, | ||
896 | (void *) 0L); | ||
897 | t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1], | ||
898 | GNUNET_TESTBED_PIT_IDENTITY, | ||
899 | &pi_cb, | ||
900 | (void *) 1L); | ||
901 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n"); | ||
902 | } | ||
903 | |||
904 | |||
905 | /** | ||
906 | * Main: start test | ||
907 | */ | ||
908 | int | ||
909 | main (int argc, char *argv[]) | ||
910 | { | ||
911 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
912 | GNUNET_MQ_hd_var_size (data, | ||
913 | GNUNET_MESSAGE_TYPE_DUMMY, | ||
914 | struct GNUNET_MessageHeader, | ||
915 | NULL), | ||
916 | GNUNET_MQ_handler_end () | ||
917 | }; | ||
918 | |||
919 | initialized = GNUNET_NO; | ||
920 | static const struct GNUNET_HashCode *ports[2]; | ||
921 | const char *config_file; | ||
922 | char port_id[] = "test port"; | ||
923 | |||
924 | GNUNET_CRYPTO_hash (port_id, sizeof (port_id), &port); | ||
925 | |||
926 | GNUNET_log_setup ("test", "DEBUG", NULL); | ||
927 | config_file = "test_cadet.conf"; | ||
928 | |||
929 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n"); | ||
930 | |||
931 | /* Find out requested size */ | ||
932 | if (strstr (argv[0], "_2_") != NULL) | ||
933 | { | ||
934 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DIRECT CONNECTIONs\n"); | ||
935 | peers_requested = 2; | ||
936 | } | ||
937 | else if (strstr (argv[0], "_5_") != NULL) | ||
938 | { | ||
939 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "5 PEER LINE\n"); | ||
940 | peers_requested = 5; | ||
941 | } | ||
942 | else | ||
943 | { | ||
944 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "SIZE UNKNOWN, USING 2\n"); | ||
945 | peers_requested = 2; | ||
946 | } | ||
947 | |||
948 | /* Find out requested test */ | ||
949 | if (strstr (argv[0], "_forward") != NULL) | ||
950 | { | ||
951 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n"); | ||
952 | test = FORWARD; | ||
953 | test_name = "unicast"; | ||
954 | ok_goal = 4; | ||
955 | } | ||
956 | else if (strstr (argv[0], "_signal") != NULL) | ||
957 | { | ||
958 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n"); | ||
959 | test = P2P_SIGNAL; | ||
960 | test_name = "signal"; | ||
961 | ok_goal = 4; | ||
962 | } | ||
963 | else if (strstr (argv[0], "_speed_ack") != NULL) | ||
964 | { | ||
965 | /* Test is supposed to generate the following callbacks: | ||
966 | * 1 incoming channel (@dest) | ||
967 | * TOTAL_PACKETS received data packet (@dest) | ||
968 | * TOTAL_PACKETS received data packet (@orig) | ||
969 | * 1 received channel destroy (@dest) | ||
970 | */ | ||
971 | ok_goal = TOTAL_PACKETS * 2 + 2; | ||
972 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n"); | ||
973 | test = SPEED_ACK; | ||
974 | test_name = "speed ack"; | ||
975 | } | ||
976 | else if (strstr (argv[0], "_speed") != NULL) | ||
977 | { | ||
978 | /* Test is supposed to generate the following callbacks: | ||
979 | * 1 incoming channel (@dest) | ||
980 | * 1 initial packet (@dest) | ||
981 | * TOTAL_PACKETS received data packet (@dest) | ||
982 | * 1 received data packet (@orig) | ||
983 | * 1 received channel destroy (@dest) | ||
984 | */ | ||
985 | ok_goal = TOTAL_PACKETS + 4; | ||
986 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n"); | ||
987 | if (strstr (argv[0], "_reliable") != NULL) | ||
988 | { | ||
989 | test = SPEED_REL; | ||
990 | test_name = "speed reliable"; | ||
991 | config_file = "test_cadet_drop.conf"; | ||
992 | } | ||
993 | else | ||
994 | { | ||
995 | test = SPEED; | ||
996 | test_name = "speed"; | ||
997 | } | ||
998 | } | ||
999 | else if (strstr (argv[0], "_keepalive") != NULL) | ||
1000 | { | ||
1001 | test = KEEPALIVE; | ||
1002 | /* Test is supposed to generate the following callbacks: | ||
1003 | * 1 incoming channel (@dest) | ||
1004 | * [wait] | ||
1005 | * 1 received channel destroy (@dest) | ||
1006 | */ | ||
1007 | ok_goal = 2; | ||
1008 | } | ||
1009 | else | ||
1010 | { | ||
1011 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n"); | ||
1012 | test = SETUP; | ||
1013 | ok_goal = 0; | ||
1014 | } | ||
1015 | |||
1016 | if (strstr (argv[0], "backwards") != NULL) | ||
1017 | { | ||
1018 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n"); | ||
1019 | test_backwards = GNUNET_YES; | ||
1020 | GNUNET_asprintf (&test_name, "backwards %s", test_name); | ||
1021 | } | ||
1022 | |||
1023 | p_ids = 0; | ||
1024 | ports[0] = &port; | ||
1025 | ports[1] = NULL; | ||
1026 | GNUNET_CADET_TEST_ruN ("test_cadet_small", | ||
1027 | config_file, | ||
1028 | peers_requested, | ||
1029 | &tmain, | ||
1030 | NULL, /* tmain cls */ | ||
1031 | &connect_handler, | ||
1032 | NULL, | ||
1033 | &disconnect_handler, | ||
1034 | handlers, | ||
1035 | ports); | ||
1036 | if (NULL != strstr (argv[0], "_reliable")) | ||
1037 | msg_dropped = 0; /* dropped should be retransmitted */ | ||
1038 | |||
1039 | if (ok_goal > ok - msg_dropped) | ||
1040 | { | ||
1041 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "FAILED! (%d/%d)\n", ok, ok_goal); | ||
1042 | return 1; | ||
1043 | } | ||
1044 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n"); | ||
1045 | return 0; | ||
1046 | } | ||
1047 | |||
1048 | /* 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 | |||
36 | struct GNUNET_TESTING_Peer *me; | ||
37 | |||
38 | static struct GNUNET_CADET_Handle *cadet; | ||
39 | |||
40 | static struct GNUNET_CADET_Channel *ch1; | ||
41 | |||
42 | static struct GNUNET_CADET_Channel *ch2; | ||
43 | |||
44 | static int result; | ||
45 | |||
46 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
47 | |||
48 | static struct GNUNET_SCHEDULER_Task *connect_task; | ||
49 | |||
50 | static unsigned int repetition; | ||
51 | |||
52 | static struct GNUNET_CADET_TransmitHandle *nth; | ||
53 | |||
54 | static struct GNUNET_CADET_Port *port; | ||
55 | |||
56 | |||
57 | /* forward declaration */ | ||
58 | static size_t | ||
59 | do_send (void *cls, size_t size, void *buf); | ||
60 | |||
61 | |||
62 | /** | ||
63 | * Shutdown nicely | ||
64 | */ | ||
65 | static void | ||
66 | do_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 | */ | ||
112 | static void | ||
113 | do_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 | */ | ||
132 | static int | ||
133 | data_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 | */ | ||
179 | static void * | ||
180 | inbound_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 | */ | ||
203 | static void | ||
204 | channel_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 | */ | ||
232 | static 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 | */ | ||
246 | static size_t | ||
247 | do_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 | */ | ||
270 | static void | ||
271 | do_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 | */ | ||
297 | static void | ||
298 | run (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 | */ | ||
335 | int | ||
336 | main (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 */ | ||