aboutsummaryrefslogtreecommitdiff
path: root/src/mesh
diff options
context:
space:
mode:
authorBart Polot <bart@net.in.tum.de>2013-06-28 14:34:55 +0000
committerBart Polot <bart@net.in.tum.de>2013-06-28 14:34:55 +0000
commitcf19b5082fe8de33e38957f54d28647635b46b60 (patch)
treee6e41da7d5cb14d9a342ef6533633ecb2f34b18d /src/mesh
parent166d8f9122bf7ebbaa2a662d09a3fa4d34f6d092 (diff)
downloadgnunet-cf19b5082fe8de33e38957f54d28647635b46b60.tar.gz
gnunet-cf19b5082fe8de33e38957f54d28647635b46b60.zip
Replace mesh with new version
Diffstat (limited to 'src/mesh')
-rw-r--r--src/mesh/Makefile.am279
-rw-r--r--src/mesh/gnunet-mesh.c28
-rw-r--r--src/mesh/gnunet-service-mesh-new.c5205
-rw-r--r--src/mesh/gnunet-service-mesh.c5695
-rw-r--r--src/mesh/mesh.h185
-rw-r--r--src/mesh/mesh2.h349
-rw-r--r--src/mesh/mesh2_api.c1787
-rw-r--r--src/mesh/mesh2_protocol.h316
-rw-r--r--src/mesh/mesh2_test_lib.c283
-rw-r--r--src/mesh/mesh2_test_lib.h106
-rw-r--r--src/mesh/mesh_api.c1188
-rw-r--r--src/mesh/mesh_path.c2
-rw-r--r--src/mesh/mesh_path.h2
-rw-r--r--src/mesh/mesh_protocol.h116
-rw-r--r--src/mesh/mesh_test_lib.c30
-rw-r--r--src/mesh/mesh_test_lib.h4
-rw-r--r--src/mesh/plugin_block_mesh.c5
-rw-r--r--src/mesh/test_mesh.conf33
-rw-r--r--src/mesh/test_mesh2.conf89
-rw-r--r--src/mesh/test_mesh2_small.c833
-rw-r--r--src/mesh/test_mesh_2dtorus.c128
-rw-r--r--src/mesh/test_mesh_2dtorus.conf71
-rw-r--r--src/mesh/test_mesh_api.c138
-rw-r--r--src/mesh/test_mesh_local.c (renamed from src/mesh/test_mesh2_local.c)8
-rw-r--r--src/mesh/test_mesh_local_1.c294
-rw-r--r--src/mesh/test_mesh_local_2.c290
-rw-r--r--src/mesh/test_mesh_local_traffic.c526
-rw-r--r--src/mesh/test_mesh_small.c336
-rw-r--r--src/mesh/test_mesh_small.conf78
-rw-r--r--src/mesh/test_mesh_tree_api.c409
30 files changed, 1757 insertions, 17056 deletions
diff --git a/src/mesh/Makefile.am b/src/mesh/Makefile.am
index c0d66ace3..e1c607d7f 100644
--- a/src/mesh/Makefile.am
+++ b/src/mesh/Makefile.am
@@ -20,21 +20,6 @@ plugindir = $(libdir)/gnunet
20 20
21AM_CLFAGS = -g 21AM_CLFAGS = -g
22 22
23if HAVE_EXPERIMENTAL
24 noinst_LIB_EXP = libgnunetmesh2test.a
25 EXP_LIB = libgnunetmesh2.la
26 EXP_LIBEXEC = gnunet-service-mesh-new
27 EXP_TESTS = \
28 test_mesh2_local \
29 test_mesh2_small_forward \
30 test_mesh2_small_signal \
31 test_mesh2_small_speed \
32 test_mesh2_small_speed_ack \
33 test_mesh2_small_speed_nobuf \
34 test_mesh2_small_speed_backwards \
35 test_mesh2_small_speed_nobuf_backwards
36endif
37
38libexec_PROGRAMS = \ 23libexec_PROGRAMS = \
39 gnunet-service-mesh $(EXP_LIBEXEC) 24 gnunet-service-mesh $(EXP_LIBEXEC)
40 25
@@ -58,6 +43,7 @@ libgnunet_plugin_block_mesh_la_DEPENDENCIES = \
58 $(top_builddir)/src/block/libgnunetblock.la \ 43 $(top_builddir)/src/block/libgnunetblock.la \
59 $(top_builddir)/src/util/libgnunetutil.la 44 $(top_builddir)/src/util/libgnunetutil.la
60 45
46
61libgnunetmesh_la_SOURCES = \ 47libgnunetmesh_la_SOURCES = \
62 mesh_api.c mesh_common.c 48 mesh_api.c mesh_common.c
63libgnunetmesh_la_LIBADD = \ 49libgnunetmesh_la_LIBADD = \
@@ -66,41 +52,7 @@ libgnunetmesh_la_LIBADD = \
66 $(LTLIBINTL) 52 $(LTLIBINTL)
67libgnunetmesh_la_LDFLAGS = \ 53libgnunetmesh_la_LDFLAGS = \
68 $(GN_LIB_LDFLAGS) $(WINFLAGS) \ 54 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
69 -version-info 2:1:1 55 -version-info 3:0:0
70
71libgnunetmesh2_la_SOURCES = \
72 mesh2_api.c mesh_common.c
73libgnunetmesh2_la_LIBADD = \
74 $(top_builddir)/src/util/libgnunetutil.la \
75 $(XLIB) \
76 $(LTLIBINTL)
77libgnunetmesh2_la_LDFLAGS = \
78 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
79 -version-info 2:2:1
80
81
82gnunet_service_mesh_SOURCES = \
83 gnunet-service-mesh.c \
84 mesh_tunnel_tree.c mesh_tunnel_tree.h \
85 mesh_common.c
86gnunet_service_mesh_CFLAGS = $(AM_CFLAGS)
87gnunet_service_mesh_LDADD = \
88 $(top_builddir)/src/statistics/libgnunetstatistics.la \
89 $(top_builddir)/src/regex/libgnunetregex.la \
90 $(top_builddir)/src/util/libgnunetutil.la \
91 $(top_builddir)/src/core/libgnunetcore.la \
92 $(top_builddir)/src/dht/libgnunetdht.la \
93 $(top_builddir)/src/block/libgnunetblock.la
94gnunet_service_mesh_DEPENDENCIES = \
95 $(top_builddir)/src/util/libgnunetutil.la \
96 $(top_builddir)/src/core/libgnunetcore.la \
97 $(top_builddir)/src/dht/libgnunetdht.la \
98 $(top_builddir)/src/statistics/libgnunetstatistics.la \
99 $(top_builddir)/src/block/libgnunetblock.la \
100 $(top_builddir)/src/regex/libgnunetregex.la
101if LINUX
102gnunet_service_mesh_LDFLAGS = -lrt
103endif
104 56
105gnunet_mesh_SOURCES = \ 57gnunet_mesh_SOURCES = \
106 gnunet-mesh.c 58 gnunet-mesh.c
@@ -110,25 +62,25 @@ gnunet_mesh_LDADD = \
110gnunet_mesh_DEPENDENCIES = \ 62gnunet_mesh_DEPENDENCIES = \
111 libgnunetmesh.la 63 libgnunetmesh.la
112 64
113gnunet_service_mesh_new_SOURCES = \ 65gnunet_service_mesh_SOURCES = \
114 gnunet-service-mesh-new.c \ 66 gnunet-service-mesh.c \
115 mesh_path.c \ 67 mesh_path.c \
116 mesh_common.c 68 mesh_common.c
117gnunet_service_mesh_new_CFLAGS = $(AM_CFLAGS) 69gnunet_service_mesh_CFLAGS = $(AM_CFLAGS)
118gnunet_service_mesh_new_LDADD = \ 70gnunet_service_mesh_LDADD = \
119 $(top_builddir)/src/util/libgnunetutil.la \ 71 $(top_builddir)/src/util/libgnunetutil.la \
120 $(top_builddir)/src/core/libgnunetcore.la \ 72 $(top_builddir)/src/core/libgnunetcore.la \
121 $(top_builddir)/src/dht/libgnunetdht.la \ 73 $(top_builddir)/src/dht/libgnunetdht.la \
122 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 74 $(top_builddir)/src/statistics/libgnunetstatistics.la \
123 $(top_builddir)/src/block/libgnunetblock.la 75 $(top_builddir)/src/block/libgnunetblock.la
124gnunet_service_mesh_new_DEPENDENCIES = \ 76gnunet_service_mesh_DEPENDENCIES = \
125 $(top_builddir)/src/util/libgnunetutil.la \ 77 $(top_builddir)/src/util/libgnunetutil.la \
126 $(top_builddir)/src/core/libgnunetcore.la \ 78 $(top_builddir)/src/core/libgnunetcore.la \
127 $(top_builddir)/src/dht/libgnunetdht.la \ 79 $(top_builddir)/src/dht/libgnunetdht.la \
128 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 80 $(top_builddir)/src/statistics/libgnunetstatistics.la \
129 $(top_builddir)/src/block/libgnunetblock.la 81 $(top_builddir)/src/block/libgnunetblock.la
130if LINUX 82if LINUX
131gnunet_service_mesh_new_LDFLAGS = -lrt 83 gnunet_service_mesh_LDFLAGS = -lrt
132endif 84endif
133 85
134if HAVE_TESTING 86if HAVE_TESTING
@@ -144,222 +96,75 @@ libgnunetmeshtest_a_LIBADD = \
144libgnunetmeshtest_a_DEPENDENCIES = \ 96libgnunetmeshtest_a_DEPENDENCIES = \
145 libgnunetmesh.la 97 libgnunetmesh.la
146 98
147libgnunetmesh2test_a_SOURCES = \
148 mesh2_test_lib.c mesh2_test_lib.h
149libgnunetmesh2test_a_LIBADD = \
150 $(top_builddir)/src/util/libgnunetutil.la \
151 $(top_builddir)/src/testbed/libgnunettestbed.la \
152 $(top_builddir)/src/mesh/libgnunetmesh2.la
153libgnunetmesh2test_a_DEPENDENCIES = \
154 libgnunetmesh2.la
155
156if HAVE_TESTING 99if HAVE_TESTING
157check_PROGRAMS = \ 100check_PROGRAMS = \
158 test_mesh_api \ 101 test_mesh_local \
159 test_mesh_tree_api \ 102 test_mesh_small_forward \
160 test_mesh_local_1 \ 103 test_mesh_small_signal \
161 test_mesh_local_2 \ 104 test_mesh_small_speed \
162 test_mesh_local_traffic_fwd \ 105 test_mesh_small_speed_ack \
163 test_mesh_local_traffic_bck \ 106 test_mesh_small_speed_nobuf \
164 test_mesh_local_traffic_both \ 107 test_mesh_small_speed_backwards \
165 test_mesh_2dtorus \ 108 test_mesh_small_speed_nobuf_backwards
166 test_mesh_small_unicast \
167 test_mesh_small_signal \
168 test_mesh_small_speed \
169 test_mesh_small_speed_nobuf \
170 test_mesh_small_speed_backwards \
171 test_mesh_small_speed_nobuf_backwards \
172 test_mesh_small_speed_ack \
173 $(EXP_TESTS)
174endif 109endif
175 110
176test_mesh_api_SOURCES = \
177 test_mesh_api.c
178test_mesh_api_LDADD = \
179 $(top_builddir)/src/util/libgnunetutil.la \
180 $(top_builddir)/src/testing/libgnunettesting.la \
181 $(top_builddir)/src/mesh/libgnunetmesh.la
182test_mesh_api_DEPENDENCIES = \
183 libgnunetmesh.la \
184 $(top_builddir)/src/util/libgnunetutil.la
185
186test_mesh_tree_api_SOURCES = \
187 test_mesh_tree_api.c
188test_mesh_tree_api_LDADD = \
189 $(top_builddir)/src/util/libgnunetutil.la \
190 $(top_builddir)/src/dht/libgnunetdht.la
191test_mesh_tree_api_DEPENDENCIES = \
192 libgnunetmesh.la \
193 $(top_builddir)/src/dht/libgnunetdht.la
194
195test_mesh_local_1_SOURCES = \
196 test_mesh_local_1.c
197test_mesh_local_1_LDADD = \
198 $(top_builddir)/src/util/libgnunetutil.la \
199 $(top_builddir)/src/testing/libgnunettesting.la \
200 $(top_builddir)/src/mesh/libgnunetmesh.la
201test_mesh_local_1_DEPENDENCIES = \
202 libgnunetmesh.la
203
204test_mesh_local_2_SOURCES = \
205 test_mesh_local_2.c
206test_mesh_local_2_LDADD = \
207 $(top_builddir)/src/util/libgnunetutil.la \
208 $(top_builddir)/src/testing/libgnunettesting.la \
209 $(top_builddir)/src/mesh/libgnunetmesh.la
210test_mesh_local_2_DEPENDENCIES = \
211 libgnunetmesh.la
212
213test_mesh_local_traffic_fwd_SOURCES = \
214 test_mesh_local_traffic.c
215test_mesh_local_traffic_fwd_LDADD = \
216 $(top_builddir)/src/util/libgnunetutil.la \
217 $(top_builddir)/src/testing/libgnunettesting.la \
218 $(top_builddir)/src/mesh/libgnunetmesh.la
219test_mesh_local_traffic_fwd_DEPENDENCIES = \
220 libgnunetmesh.la
221
222test_mesh_local_traffic_bck_SOURCES = \
223 test_mesh_local_traffic.c
224test_mesh_local_traffic_bck_LDADD = \
225 $(top_builddir)/src/util/libgnunetutil.la \
226 $(top_builddir)/src/testing/libgnunettesting.la \
227 $(top_builddir)/src/mesh/libgnunetmesh.la
228test_mesh_local_traffic_bck_DEPENDENCIES = \
229 libgnunetmesh.la
230
231test_mesh_local_traffic_both_SOURCES = \
232 test_mesh_local_traffic.c
233test_mesh_local_traffic_both_LDADD = \
234 $(top_builddir)/src/util/libgnunetutil.la \
235 $(top_builddir)/src/testing/libgnunettesting.la \
236 $(top_builddir)/src/mesh/libgnunetmesh.la
237test_mesh_local_traffic_both_DEPENDENCIES = \
238 libgnunetmesh.la
239
240
241ld_mesh_test_lib = \ 111ld_mesh_test_lib = \
242 $(top_builddir)/src/mesh/libgnunetmeshtest.a \ 112 $(top_builddir)/src/util/libgnunetutil.la \
243 $(top_builddir)/src/mesh/libgnunetmesh.la \ 113 $(top_builddir)/src/testing/libgnunettesting.la \
244 $(top_builddir)/src/testbed/libgnunettestbed.la \ 114 $(top_builddir)/src/testbed/libgnunettestbed.la \
245 $(top_builddir)/src/util/libgnunetutil.la 115 $(top_builddir)/src/mesh/libgnunetmesh.la \
116 $(top_builddir)/src/mesh/libgnunetmeshtest.a
246 117
247dep_mesh_test_lib = \ 118dep_mesh_test_lib = \
248 libgnunetmeshtest.a \ 119 libgnunetmesh.la \
249 libgnunetmesh.la 120 libgnunetmeshtest.a
250 121
251test_mesh_2dtorus_SOURCES = \ 122test_mesh_local_SOURCES = \
252 test_mesh_2dtorus.c 123 test_mesh_local.c
253test_mesh_2dtorus_LDADD = $(ld_mesh_test_lib) 124test_mesh_local_LDADD = $(ld_mesh_test_lib)
254test_mesh_2dtorus_DEPENDENCIES = $(dep_mesh_test_lib) 125test_mesh_local_DEPENDENCIES = $(dep_mesh_test_lib)
255 126
256test_mesh_small_unicast_SOURCES = \ 127test_mesh_small_forward_SOURCES = \
257 test_mesh_small.c 128 test_mesh_small.c
258test_mesh_small_unicast_LDADD = $(ld_mesh_test_lib) 129test_mesh_small_forward_LDADD = $(ld_mesh_test_lib)
259test_mesh_small_unicast_DEPENDENCIES = $(dep_mesh_test_lib) 130test_mesh_small_forward_DEPENDENCIES = $(dep_mesh_test_lib)
260 131
261test_mesh_small_signal_SOURCES = \ 132test_mesh_small_signal_SOURCES = \
262 test_mesh_small.c 133 test_mesh_small.c
263test_mesh_small_signal_LDADD = $(ld_mesh_test_lib) 134test_mesh_small_signal_LDADD = $(ld_mesh_test_lib)
264test_mesh_small_signal_DEPENDENCIES = $(dep_mesh_test_lib) 135test_mesh_small_signal_DEPENDENCIES = $(dep_mesh_test_lib)
265 136
266test_mesh_small_speed_ack_SOURCES = \
267 test_mesh_small.c
268test_mesh_small_speed_ack_LDADD = $(ld_mesh_test_lib)
269test_mesh_small_speed_ack_DEPENDENCIES = $(dep_mesh_test_lib)
270
271test_mesh_small_speed_SOURCES = \ 137test_mesh_small_speed_SOURCES = \
272 test_mesh_small.c 138 test_mesh_small.c
273test_mesh_small_speed_LDADD = $(ld_mesh_test_lib) 139test_mesh_small_speed_LDADD = $(ld_mesh_test_lib)
274test_mesh_small_speed_DEPENDENCIES = $(dep_mesh_test_lib) 140test_mesh_small_speed_DEPENDENCIES = $(dep_mesh_test_lib)
275 141
142test_mesh_small_speed_ack_SOURCES = \
143 test_mesh_small.c
144test_mesh_small_speed_ack_LDADD = $(ld_mesh_test_lib)
145test_mesh_small_speed_ack_DEPENDENCIES = $(dep_mesh_test_lib)
146
276test_mesh_small_speed_nobuf_SOURCES = \ 147test_mesh_small_speed_nobuf_SOURCES = \
277 test_mesh_small.c 148 test_mesh_small.c
278test_mesh_small_speed_nobuf_LDADD = $(ld_mesh_test_lib) 149test_mesh_small_speed_nobuf_LDADD = $(ld_mesh_test_lib)
279test_mesh_small_speed_nobuf_DEPENDENCIES = $(dep_mesh_test_lib) 150test_mesh_small_speed_nobuf_DEPENDENCIES = $(dep_mesh_test_lib)
280 151
281test_mesh_small_speed_backwards_SOURCES = \ 152test_mesh_small_speed_backwards_SOURCES = \
282 test_mesh_small.c 153 test_mesh_small.c
283test_mesh_small_speed_backwards_LDADD = $(ld_mesh_test_lib) 154test_mesh_small_speed_backwards_LDADD = $(ld_mesh_test_lib)
284test_mesh_small_speed_backwards_DEPENDENCIES = $(dep_mesh_test_lib) 155test_mesh_small_speed_backwards_DEPENDENCIES = $(dep_mesh_test_lib)
285 156
286test_mesh_small_speed_nobuf_backwards_SOURCES = \ 157test_mesh_small_speed_nobuf_backwards_SOURCES = \
287 test_mesh_small.c 158 test_mesh_small.c
288test_mesh_small_speed_nobuf_backwards_LDADD = $(ld_mesh_test_lib) 159test_mesh_small_speed_nobuf_backwards_LDADD = $(ld_mesh_test_lib)
289test_mesh_small_speed_nobuf_backwards_DEPENDENCIES = $(dep_mesh_test_lib) 160test_mesh_small_speed_nobuf_backwards_DEPENDENCIES = $(dep_mesh_test_lib)
290 161
291 162
292ld_mesh2_test_lib = \
293 $(top_builddir)/src/mesh/libgnunetmesh2test.a \
294 $(top_builddir)/src/mesh/libgnunetmesh2.la \
295 $(top_builddir)/src/testing/libgnunettesting.la \
296 $(top_builddir)/src/testbed/libgnunettestbed.la \
297 $(top_builddir)/src/util/libgnunetutil.la
298
299dep_mesh2_test_lib = \
300 libgnunetmesh2test.a \
301 libgnunetmesh2.la
302
303test_mesh2_local_SOURCES = \
304 test_mesh2_local.c
305test_mesh2_local_LDADD = $(ld_mesh2_test_lib)
306test_mesh2_local_DEPENDENCIES = $(dep_mesh2_test_lib)
307
308test_mesh2_small_forward_SOURCES = \
309 test_mesh2_small.c
310test_mesh2_small_forward_LDADD = $(ld_mesh2_test_lib)
311test_mesh2_small_forward_DEPENDENCIES = $(dep_mesh2_test_lib)
312
313test_mesh2_small_signal_SOURCES = \
314 test_mesh2_small.c
315test_mesh2_small_signal_LDADD = $(ld_mesh2_test_lib)
316test_mesh2_small_signal_DEPENDENCIES = $(dep_mesh2_test_lib)
317
318test_mesh2_small_speed_SOURCES = \
319 test_mesh2_small.c
320test_mesh2_small_speed_LDADD = $(ld_mesh2_test_lib)
321test_mesh2_small_speed_DEPENDENCIES = $(dep_mesh2_test_lib)
322
323test_mesh2_small_speed_ack_SOURCES = \
324 test_mesh2_small.c
325test_mesh2_small_speed_ack_LDADD = $(ld_mesh2_test_lib)
326test_mesh2_small_speed_ack_DEPENDENCIES = $(dep_mesh2_test_lib)
327
328test_mesh2_small_speed_nobuf_SOURCES = \
329 test_mesh2_small.c
330test_mesh2_small_speed_nobuf_LDADD = $(ld_mesh2_test_lib)
331test_mesh2_small_speed_nobuf_DEPENDENCIES = $(dep_mesh2_test_lib)
332
333test_mesh2_small_speed_backwards_SOURCES = \
334 test_mesh2_small.c
335test_mesh2_small_speed_backwards_LDADD = $(ld_mesh2_test_lib)
336test_mesh2_small_speed_backwards_DEPENDENCIES = $(dep_mesh2_test_lib)
337
338test_mesh2_small_speed_nobuf_backwards_SOURCES = \
339 test_mesh2_small.c
340test_mesh2_small_speed_nobuf_backwards_LDADD = $(ld_mesh2_test_lib)
341test_mesh2_small_speed_nobuf_backwards_DEPENDENCIES = $(dep_mesh2_test_lib)
342
343
344if ENABLE_TEST_RUN 163if ENABLE_TEST_RUN
345TESTS = \ 164TESTS = \
346 $(EXP_TESTS) \ 165 $(check_PROGRAMS)
347 test_mesh_api \
348 test_mesh_tree_api \
349 test_mesh_local_1 test_mesh_local_2 \
350 test_mesh_local_traffic_fwd \
351 test_mesh_local_traffic_bck \
352 test_mesh_local_traffic_both \
353 test_mesh_2dtorus \
354 test_mesh_small_unicast \
355 test_mesh_small_signal \
356 test_mesh_small_speed \
357 test_mesh_small_speed_nobuf \
358 test_mesh_small_speed_backwards
359endif 166endif
360 167
361EXTRA_DIST = \ 168EXTRA_DIST = \
362 mesh.h mesh_protocol.h \ 169 mesh.h mesh_protocol.h \
363 test_mesh.conf \ 170 test_mesh.conf
364 test_mesh_2dtorus.conf \
365 test_mesh_small.conf
diff --git a/src/mesh/gnunet-mesh.c b/src/mesh/gnunet-mesh.c
index 21a3f7d60..f9cc1295c 100644
--- a/src/mesh/gnunet-mesh.c
+++ b/src/mesh/gnunet-mesh.c
@@ -73,25 +73,19 @@ shutdown_task (void *cls,
73 * Method called to retrieve information about each tunnel the mesh peer 73 * Method called to retrieve information about each tunnel the mesh peer
74 * is aware of. 74 * is aware of.
75 * 75 *
76 * @param cls Closure (unused). 76 * @param cls Closure.
77 * @param initiator Peer that started the tunnel (owner).
78 * @param tunnel_number Tunnel number. 77 * @param tunnel_number Tunnel number.
79 * @param peers Array of peer identities that participate in the tunnel. 78 * @param origin that started the tunnel (owner).
80 * @param npeers Number of peers in peers. 79 * @param target other endpoint of the tunnel
81 */ 80 */
82static void 81static void
83tunnels_callback (void *cls, 82tunnels_callback (void *cls,
84 const struct GNUNET_PeerIdentity *initiator, 83 uint32_t tunnel_number,
85 unsigned int tunnel_number, 84 const struct GNUNET_PeerIdentity *origin,
86 const struct GNUNET_PeerIdentity *peers, 85 const struct GNUNET_PeerIdentity *target)
87 unsigned int npeers)
88{ 86{
89 unsigned int i; 87 fprintf (stdout, "Tunnel %s [%u]\n",
90 88 GNUNET_i2s_full (origin), tunnel_number);
91 fprintf (stdout, "Tunnel %s [%u]: %u peers\n",
92 GNUNET_i2s_full (initiator), tunnel_number, npeers);
93 for (i = 0; i < npeers; i++)
94 fprintf (stdout, " * %s\n", GNUNET_i2s_full (&peers[i]));
95 fprintf (stdout, "\n"); 89 fprintf (stdout, "\n");
96} 90}
97 91
@@ -169,7 +163,7 @@ run (void *cls, char *const *args, const char *cfgfile,
169 static const struct GNUNET_MESH_MessageHandler handlers[] = { 163 static const struct GNUNET_MESH_MessageHandler handlers[] = {
170 {NULL, 0, 0} /* FIXME add option to monitor msg types */ 164 {NULL, 0, 0} /* FIXME add option to monitor msg types */
171 }; 165 };
172 GNUNET_MESH_ApplicationType apps = 0; /* FIXME add option to monitor apps */ 166 /* FIXME add option to monitor apps */
173 167
174 if (args[0] != NULL) 168 if (args[0] != NULL)
175 { 169 {
@@ -178,10 +172,10 @@ run (void *cls, char *const *args, const char *cfgfile,
178 } 172 }
179 mh = GNUNET_MESH_connect (cfg, 173 mh = GNUNET_MESH_connect (cfg,
180 NULL, /* cls */ 174 NULL, /* cls */
181 NULL, /* nt */ 175 NULL, /* new tunnel */
182 NULL, /* cleaner */ 176 NULL, /* cleaner */
183 handlers, 177 handlers,
184 &apps); 178 NULL);
185 if (NULL == mh) 179 if (NULL == mh)
186 GNUNET_SCHEDULER_add_now (shutdown_task, NULL); 180 GNUNET_SCHEDULER_add_now (shutdown_task, NULL);
187 else 181 else
diff --git a/src/mesh/gnunet-service-mesh-new.c b/src/mesh/gnunet-service-mesh-new.c
deleted file mode 100644
index 7925b5241..000000000
--- a/src/mesh/gnunet-service-mesh-new.c
+++ /dev/null
@@ -1,5205 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001-2013 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file mesh/gnunet-service-mesh-new.c
23 * @brief GNUnet MESH service
24 * @author Bartlomiej Polot
25 *
26 * TODO:
27 * - relay corking down to core
28 * - set ttl relative to path length
29 * - add signatures
30 * - add encryption
31 * - keep queues until receiving ACK
32 * TODO END
33 */
34
35#include "platform.h"
36#include "mesh2.h"
37#include "mesh2_protocol.h"
38#include "mesh_path.h"
39#include "block_mesh.h"
40#include "gnunet_dht_service.h"
41#include "gnunet_statistics_service.h"
42
43#define MESH_BLOOM_SIZE 128
44
45#define MESH_DEBUG_DHT GNUNET_NO
46#define MESH_DEBUG_CONNECTION GNUNET_NO
47#define MESH_DEBUG_TIMING __LINUX__ && GNUNET_NO
48
49#define MESH_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\
50 GNUNET_TIME_UNIT_MINUTES,\
51 10)
52
53#if MESH_DEBUG_CONNECTION
54#define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
55#else
56#define DEBUG_CONN(...)
57#endif
58
59#if MESH_DEBUG_DHT
60#define DEBUG_DHT(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
61#else
62#define DEBUG_DHT(...)
63#endif
64
65#if MESH_DEBUG_TIMING
66#include <time.h>
67double __sum;
68uint64_t __count;
69struct timespec __mesh_start;
70struct timespec __mesh_end;
71#define INTERVAL_START clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(__mesh_start))
72#define INTERVAL_END \
73do {\
74 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(__mesh_end));\
75 double __diff = __mesh_end.tv_nsec - __mesh_start.tv_nsec;\
76 if (__diff < 0) __diff += 1000000000;\
77 __sum += __diff;\
78 __count++;\
79} while (0)
80#define INTERVAL_SHOW \
81if (0 < __count)\
82 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "AVG process time: %f ns\n", __sum/__count)
83#else
84#define INTERVAL_START
85#define INTERVAL_END
86#define INTERVAL_SHOW
87#endif
88
89/******************************************************************************/
90/************************ DATA STRUCTURES ****************************/
91/******************************************************************************/
92
93/** FWD declaration */
94struct MeshPeerInfo;
95struct MeshClient;
96
97
98/**
99 * Struct containing info about a queued transmission to this peer
100 */
101struct MeshPeerQueue
102{
103 /**
104 * DLL next
105 */
106 struct MeshPeerQueue *next;
107
108 /**
109 * DLL previous
110 */
111 struct MeshPeerQueue *prev;
112
113 /**
114 * Peer this transmission is directed to.
115 */
116 struct MeshPeerInfo *peer;
117
118 /**
119 * Tunnel this message belongs to.
120 */
121 struct MeshTunnel *tunnel;
122
123 /**
124 * Pointer to info stucture used as cls.
125 */
126 void *cls;
127
128 /**
129 * Type of message
130 */
131 uint16_t type;
132
133 /**
134 * Size of the message
135 */
136 size_t size;
137};
138
139
140/**
141 * Struct containing all information regarding a given peer
142 */
143struct MeshPeerInfo
144{
145 /**
146 * ID of the peer
147 */
148 GNUNET_PEER_Id id;
149
150 /**
151 * Last time we heard from this peer
152 */
153 struct GNUNET_TIME_Absolute last_contact;
154
155 /**
156 * Number of attempts to reconnect so far
157 */
158 int n_reconnect_attempts;
159
160 /**
161 * Paths to reach the peer, ordered by ascending hop count
162 */
163 struct MeshPeerPath *path_head;
164
165 /**
166 * Paths to reach the peer, ordered by ascending hop count
167 */
168 struct MeshPeerPath *path_tail;
169
170 /**
171 * Handle to stop the DHT search for a path to this peer
172 */
173 struct GNUNET_DHT_GetHandle *dhtget;
174
175 /**
176 * Array of tunnels this peer is the target of.
177 * Most probably a small amount, therefore not a hashmap.
178 * When the path to the peer changes, notify these tunnels to let them
179 * re-adjust their path trees.
180 */
181 struct MeshTunnel **tunnels;
182
183 /**
184 * Number of tunnels this peers participates in
185 */
186 unsigned int ntunnels;
187
188 /**
189 * Transmission queue to core DLL head
190 */
191 struct MeshPeerQueue *queue_head;
192
193 /**
194 * Transmission queue to core DLL tail
195 */
196 struct MeshPeerQueue *queue_tail;
197
198 /**
199 * How many messages are in the queue to this peer.
200 */
201 unsigned int queue_n;
202
203 /**
204 * Handle for queued transmissions
205 */
206 struct GNUNET_CORE_TransmitHandle *core_transmit;
207};
208
209
210/**
211 * Struct to encapsulate all the Flow Control information to a peer in the
212 * context of a tunnel: Same peer in different tunnels will have independent
213 * flow control structures, allowing to choke/free tunnels according to its
214 * own criteria.
215 */
216struct MeshFlowControl
217{
218 /**
219 * ID of the last packet sent towards the peer.
220 */
221 uint32_t last_pid_sent;
222
223 /**
224 * ID of the last packet received from the peer.
225 */
226 uint32_t last_pid_recv;
227
228 /**
229 * Last ACK sent to the peer (peer can't send more than this PID).
230 */
231 uint32_t last_ack_sent;
232
233 /**
234 * Last ACK sent towards the origin (for traffic towards leaf node).
235 */
236 uint32_t last_ack_recv;
237
238 /**
239 * How many payload messages are in the queue towards this peer.
240 */
241 uint32_t queue_n;
242
243 /**
244 * Task to poll the peer in case of a lost ACK causes stall.
245 */
246 GNUNET_SCHEDULER_TaskIdentifier poll_task;
247
248 /**
249 * How frequently to poll for ACKs.
250 */
251 struct GNUNET_TIME_Relative poll_time;
252
253 /**
254 * On which tunnel to poll.
255 * Using an explicit poll_ctx would not help memory wise,
256 * since the allocated context would have to be stored in the
257 * fc struct in order to free it upon cancelling poll_task.
258 */
259 struct MeshTunnel *t;
260};
261
262
263/**
264 * Globally unique tunnel identification (owner + number)
265 * DO NOT USE OVER THE NETWORK
266 */
267struct MESH_TunnelID
268{
269 /**
270 * Node that owns the tunnel
271 */
272 GNUNET_PEER_Id oid;
273
274 /**
275 * Tunnel number to differentiate all the tunnels owned by the node oid
276 * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_CLI )
277 */
278 MESH_TunnelNumber tid;
279};
280
281
282/**
283 * Struct containing all information regarding a tunnel
284 * For an intermediate node the improtant info used will be:
285 * - id Tunnel unique identification
286 * - paths[0] To know where to send it next
287 * - metainfo: ready, speeds, accounting
288 */
289struct MeshTunnel
290{
291 /**
292 * Tunnel ID
293 */
294 struct MESH_TunnelID id;
295
296 /**
297 * Port of the tunnel.
298 */
299 uint32_t port;
300
301 /**
302 * State of the tunnel.
303 */
304 enum MeshTunnelState state;
305
306 /**
307 * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI or 0 )
308 */
309 MESH_TunnelNumber local_tid;
310
311 /**
312 * Local tunnel number for local destination clients (incoming number)
313 * ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV or 0). All clients share the same
314 * number.
315 */
316 MESH_TunnelNumber local_tid_dest;
317
318 /**
319 * Is the tunnel bufferless (minimum latency)?
320 */
321 int nobuffer;
322
323 /**
324 * Force sending ACK? Flag to allow duplicate ACK on POLL.
325 */
326 int force_ack;
327
328 /**
329 * How many messages do we accept in the forward queue.
330 */
331 unsigned int queue_max;
332
333 /**
334 * Last time the tunnel was used
335 */
336 struct GNUNET_TIME_Absolute timestamp;
337
338 /**
339 * Destination of the tunnel.
340 */
341 GNUNET_PEER_Id dest;
342
343 /**
344 * Next hop in the tunnel. If 0, @c client must be set.
345 */
346 GNUNET_PEER_Id next_hop;
347
348 /**
349 * Previous hop in the tunnel. If 0, @c owner must be set.
350 */
351 GNUNET_PEER_Id prev_hop;
352
353 /**
354 * Flow control information about @c next_hop or @c client.
355 */
356 struct MeshFlowControl next_fc;
357
358 /**
359 * Flow control information about @c prev_hop or @c owner.
360 */
361 struct MeshFlowControl prev_fc;
362
363 /**
364 * Client owner of the tunnel, if any
365 */
366 struct MeshClient *owner;
367
368 /**
369 * Client destination of the tunnel, if any.
370 */
371 struct MeshClient *client;
372
373 /**
374 * Task to keep the used paths alive at the owner,
375 * time tunnel out on all the other peers.
376 */
377 GNUNET_SCHEDULER_TaskIdentifier maintenance_task;
378
379 /**
380 * Path being used for the tunnel.
381 */
382 struct MeshPeerPath *path;
383
384 /**
385 * Flag to signal the destruction of the tunnel.
386 * If this is set GNUNET_YES the tunnel will be destroyed
387 * when the queue is empty.
388 */
389 int destroy;
390
391 /**
392 * Total messages pending for this tunnels, payload or not.
393 */
394 unsigned int pending_messages;
395};
396
397
398/**
399 * Struct containing information about a client of the service
400 *
401 * TODO: add a list of 'waiting' ports
402 */
403struct MeshClient
404{
405 /**
406 * Linked list next
407 */
408 struct MeshClient *next;
409
410 /**
411 * Linked list prev
412 */
413 struct MeshClient *prev;
414
415 /**
416 * Tunnels that belong to this client, indexed by local id
417 */
418 struct GNUNET_CONTAINER_MultiHashMap *own_tunnels;
419
420 /**
421 * Tunnels this client has accepted, indexed by incoming local id
422 */
423 struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels;
424
425 /**
426 * Handle to communicate with the client
427 */
428 struct GNUNET_SERVER_Client *handle;
429
430 /**
431 * Ports that this client has declared interest in.
432 * Indexed by a GMC_hash32 (type), contains *Client.
433 */
434 struct GNUNET_CONTAINER_MultiHashMap *ports;
435
436 /**
437 * Whether the client is active or shutting down (don't send confirmations
438 * to a client that is shutting down.
439 */
440 int shutting_down;
441
442 /**
443 * ID of the client, mainly for debug messages
444 */
445 unsigned int id;
446
447};
448
449
450/******************************************************************************/
451/************************ DEBUG FUNCTIONS ****************************/
452/******************************************************************************/
453
454#if MESH_DEBUG
455/**
456 * GNUNET_SCHEDULER_Task for printing a message after some operation is done
457 * @param cls string to print
458 * @param success GNUNET_OK if the PUT was transmitted,
459 * GNUNET_NO on timeout,
460 * GNUNET_SYSERR on disconnect from service
461 * after the PUT message was transmitted
462 * (so we don't know if it was received or not)
463 */
464
465#if 0
466static void
467mesh_debug (void *cls, int success)
468{
469 char *s = cls;
470
471 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s (%d)\n", s, success);
472}
473#endif
474
475/* FIXME */
476unsigned int debug_fwd_ack;
477unsigned int debug_bck_ack;
478
479#endif
480
481/******************************************************************************/
482/*********************** GLOBAL VARIABLES ****************************/
483/******************************************************************************/
484
485/************************** Configuration parameters **************************/
486
487/**
488 * How often to send tunnel keepalives. Tunnels timeout after 4 missed.
489 */
490static struct GNUNET_TIME_Relative refresh_path_time;
491
492/**
493 * How often to PUT own ID in the DHT.
494 */
495static struct GNUNET_TIME_Relative id_announce_time;
496
497/**
498 * Maximum time allowed to connect to a peer found by string.
499 */
500static struct GNUNET_TIME_Relative connect_timeout;
501
502/**
503 * Default TTL for payload packets.
504 */
505static unsigned long long default_ttl;
506
507/**
508 * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put.
509 */
510static unsigned long long dht_replication_level;
511
512/**
513 * How many tunnels are we willing to maintain.
514 * Local tunnels are always allowed, even if there are more tunnels than max.
515 */
516static unsigned long long max_tunnels;
517
518/**
519 * How many messages *in total* are we willing to queue, divided by number of
520 * tunnels to get tunnel queue size.
521 */
522static unsigned long long max_msgs_queue;
523
524/**
525 * How many peers do we want to remember?
526 */
527static unsigned long long max_peers;
528
529
530/*************************** Static global variables **************************/
531
532/**
533 * Hostkey generation context
534 */
535static struct GNUNET_CRYPTO_EccKeyGenerationContext *keygen;
536
537/**
538 * DLL with all the clients, head.
539 */
540static struct MeshClient *clients_head;
541
542/**
543 * DLL with all the clients, tail.
544 */
545static struct MeshClient *clients_tail;
546
547/**
548 * Tunnels known, indexed by MESH_TunnelID (MeshTunnel).
549 */
550static struct GNUNET_CONTAINER_MultiHashMap *tunnels;
551
552/**
553 * Number of tunnels known.
554 */
555static unsigned long long n_tunnels;
556
557/**
558 * Tunnels incoming, indexed by MESH_TunnelNumber
559 * (which is greater than GNUNET_MESH_LOCAL_TUNNEL_ID_SERV).
560 */
561static struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels;
562
563/**
564 * Peers known, indexed by PeerIdentity (MeshPeerInfo).
565 */
566static struct GNUNET_CONTAINER_MultiHashMap *peers;
567
568/*
569 * Handle to communicate with transport
570 */
571// static struct GNUNET_TRANSPORT_Handle *transport_handle;
572
573/**
574 * Handle to communicate with core.
575 */
576static struct GNUNET_CORE_Handle *core_handle;
577
578/**
579 * Handle to use DHT.
580 */
581static struct GNUNET_DHT_Handle *dht_handle;
582
583/**
584 * Handle to server.
585 */
586static struct GNUNET_SERVER_Handle *server_handle;
587
588/**
589 * Handle to the statistics service.
590 */
591static struct GNUNET_STATISTICS_Handle *stats;
592
593/**
594 * Notification context, to send messages to local clients.
595 */
596static struct GNUNET_SERVER_NotificationContext *nc;
597
598/**
599 * Local peer own ID (memory efficient handle).
600 */
601static GNUNET_PEER_Id myid;
602
603/**
604 * Local peer own ID (full value).
605 */
606static struct GNUNET_PeerIdentity my_full_id;
607
608/**
609 * Own private key.
610 */
611static struct GNUNET_CRYPTO_EccPrivateKey *my_private_key;
612
613/**
614 * Own public key.
615 */
616static struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded my_public_key;
617
618/**
619 * Tunnel ID for the next created tunnel (global tunnel number).
620 */
621static MESH_TunnelNumber next_tid;
622
623/**
624 * Tunnel ID for the next incoming tunnel (local tunnel number).
625 */
626static MESH_TunnelNumber next_local_tid;
627
628/**
629 * All ports clients of this peer have opened.
630 */
631static struct GNUNET_CONTAINER_MultiHashMap *ports;
632
633/**
634 * Task to periodically announce itself in the network.
635 */
636GNUNET_SCHEDULER_TaskIdentifier announce_id_task;
637
638/**
639 * Next ID to assign to a client.
640 */
641unsigned int next_client_id;
642
643
644/******************************************************************************/
645/*********************** DECLARATIONS **************************/
646/******************************************************************************/
647
648/**
649 * Function to process paths received for a new peer addition. The recorded
650 * paths form the initial tunnel, which can be optimized later.
651 * Called on each result obtained for the DHT search.
652 *
653 * @param cls closure
654 * @param exp when will this value expire
655 * @param key key of the result
656 * @param type type of the result
657 * @param size number of bytes in data
658 * @param data pointer to the result data
659 */
660static void
661dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
662 const struct GNUNET_HashCode * key,
663 const struct GNUNET_PeerIdentity *get_path,
664 unsigned int get_path_length,
665 const struct GNUNET_PeerIdentity *put_path,
666 unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
667 size_t size, const void *data);
668
669
670/**
671 * Retrieve the MeshPeerInfo stucture associated with the peer, create one
672 * and insert it in the appropriate structures if the peer is not known yet.
673 *
674 * @param peer Full identity of the peer.
675 *
676 * @return Existing or newly created peer info.
677 */
678static struct MeshPeerInfo *
679peer_get (const struct GNUNET_PeerIdentity *peer);
680
681
682/**
683 * Retrieve the MeshPeerInfo stucture associated with the peer, create one
684 * and insert it in the appropriate structures if the peer is not known yet.
685 *
686 * @param peer Short identity of the peer.
687 *
688 * @return Existing or newly created peer info.
689 */
690static struct MeshPeerInfo *
691peer_get_short (const GNUNET_PEER_Id peer);
692
693
694/**
695 * Build a PeerPath from the paths returned from the DHT, reversing the paths
696 * to obtain a local peer -> destination path and interning the peer ids.
697 *
698 * @return Newly allocated and created path
699 */
700static struct MeshPeerPath *
701path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
702 unsigned int get_path_length,
703 const struct GNUNET_PeerIdentity *put_path,
704 unsigned int put_path_length);
705
706
707/**
708 * Adds a path to the peer_infos of all the peers in the path
709 *
710 * @param p Path to process.
711 * @param confirmed Whether we know if the path works or not.
712 */
713static void
714path_add_to_peers (struct MeshPeerPath *p, int confirmed);
715
716
717
718/**
719 * Search for a tunnel by global ID using full PeerIdentities.
720 *
721 * @param oid owner of the tunnel.
722 * @param tid global tunnel number.
723 *
724 * @return tunnel handler, NULL if doesn't exist.
725 */
726static struct MeshTunnel *
727tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid);
728
729
730/**
731 * Notify a tunnel that a connection has broken that affects at least
732 * some of its peers.
733 *
734 * @param t Tunnel affected.
735 * @param p1 Peer that got disconnected from p2.
736 * @param p2 Peer that got disconnected from p1.
737 *
738 * @return Short ID of the peer disconnected (either p1 or p2).
739 * 0 if the tunnel remained unaffected.
740 */
741static GNUNET_PEER_Id
742tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
743 GNUNET_PEER_Id p2);
744
745
746/**
747 * @brief Use the given path for the tunnel.
748 * Update the next and prev hops (and RCs).
749 * (Re)start the path refresh in case the tunnel is locally owned.
750 *
751 * @param t Tunnel to update.
752 * @param p Path to use.
753 */
754static void
755tunnel_use_path (struct MeshTunnel *t, struct MeshPeerPath *p);
756
757/**
758 * Tunnel is empty: destroy it.
759 *
760 * Notifies all participants (peers, cleints) about the destruction.
761 *
762 * @param t Tunnel to destroy.
763 */
764static void
765tunnel_destroy_empty (struct MeshTunnel *t);
766
767/**
768 * @brief Queue and pass message to core when possible.
769 *
770 * If type is payload (UNICAST, TO_ORIGIN, MULTICAST) checks for queue status
771 * and accounts for it. In case the queue is full, the message is dropped and
772 * a break issued.
773 *
774 * Otherwise, message is treated as internal and allowed to go regardless of
775 * queue status.
776 *
777 * @param cls Closure (@c type dependant). It will be used by queue_send to
778 * build the message to be sent if not already prebuilt.
779 * @param type Type of the message, 0 for a raw message.
780 * @param size Size of the message.
781 * @param dst Neighbor to send message to.
782 * @param t Tunnel this message belongs to.
783 */
784static void
785queue_add (void *cls, uint16_t type, size_t size,
786 struct MeshPeerInfo *dst, struct MeshTunnel *t);
787
788
789/**
790 * Free a transmission that was already queued with all resources
791 * associated to the request.
792 *
793 * @param queue Queue handler to cancel.
794 * @param clear_cls Is it necessary to free associated cls?
795 */
796static void
797queue_destroy (struct MeshPeerQueue *queue, int clear_cls);
798
799
800/**
801 * @brief Get the next transmittable message from the queue.
802 *
803 * This will be the head, except in the case of being a data packet
804 * not allowed by the destination peer.
805 *
806 * @param peer Destination peer.
807 *
808 * @return The next viable MeshPeerQueue element to send to that peer.
809 * NULL when there are no transmittable messages.
810 */
811struct MeshPeerQueue *
812queue_get_next (const struct MeshPeerInfo *peer);
813
814
815/**
816 * Core callback to write a queued packet to core buffer
817 *
818 * @param cls Closure (peer info).
819 * @param size Number of bytes available in buf.
820 * @param buf Where the to write the message.
821 *
822 * @return number of bytes written to buf
823 */
824static size_t
825queue_send (void *cls, size_t size, void *buf);
826
827
828/******************************************************************************/
829/************************ PERIODIC FUNCTIONS ****************************/
830/******************************************************************************/
831
832/**
833 * Periodically announce self id in the DHT
834 *
835 * @param cls closure
836 * @param tc task context
837 */
838static void
839announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
840{
841 struct PBlock block;
842
843 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
844 {
845 announce_id_task = GNUNET_SCHEDULER_NO_TASK;
846 return;
847 }
848 /* TODO
849 * - Set data expiration in function of X
850 * - Adapt X to churn
851 */
852 DEBUG_DHT ("DHT_put for ID %s started.\n", GNUNET_i2s (&my_full_id));
853
854 block.id = my_full_id;
855 block.type = htonl (0);
856 GNUNET_DHT_put (dht_handle, /* DHT handle */
857 &my_full_id.hashPubKey, /* Key to use */
858 dht_replication_level, /* Replication level */
859 GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
860 GNUNET_BLOCK_TYPE_MESH_PEER, /* Block type */
861 sizeof (block), /* Size of the data */
862 (const char *) &block, /* Data itself */
863 GNUNET_TIME_UNIT_FOREVER_ABS, /* Data expiration */
864 GNUNET_TIME_UNIT_FOREVER_REL, /* Retry time */
865 NULL, /* Continuation */
866 NULL); /* Continuation closure */
867 announce_id_task =
868 GNUNET_SCHEDULER_add_delayed (id_announce_time, &announce_id, cls);
869}
870
871
872/******************************************************************************/
873/****************** GENERAL HELPER FUNCTIONS ************************/
874/******************************************************************************/
875
876
877/**
878 * Check if client has registered with the service and has not disconnected
879 *
880 * @param client the client to check
881 *
882 * @return non-NULL if client exists in the global DLL
883 */
884static struct MeshClient *
885client_get (struct GNUNET_SERVER_Client *client)
886{
887 struct MeshClient *c;
888
889 c = clients_head;
890 while (NULL != c)
891 {
892 if (c->handle == client)
893 return c;
894 c = c->next;
895 }
896 return NULL;
897}
898
899
900/**
901 * Deletes a tunnel from a client (either owner or destination). To be used on
902 * tunnel destroy.
903 *
904 * @param c Client whose tunnel to delete.
905 * @param t Tunnel which should be deleted.
906 */
907static void
908client_delete_tunnel (struct MeshClient *c, struct MeshTunnel *t)
909{
910 struct GNUNET_HashCode hash;
911
912 if (c == t->owner)
913 {
914 GMC_hash32 (t->local_tid, &hash);
915 GNUNET_assert (GNUNET_YES ==
916 GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels,
917 &hash,
918 t));
919 }
920 else if (c == t->client)
921 {
922 GMC_hash32 (t->local_tid_dest, &hash);
923 GNUNET_assert (GNUNET_YES ==
924 GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels,
925 &hash,
926 t));
927 }
928 else
929 {
930 GNUNET_break (0);
931 }
932}
933
934/**
935 * Notify the appropriate client that a new incoming tunnel was created.
936 *
937 * @param t Tunnel that was created.
938 */
939static void
940send_client_tunnel_create (struct MeshTunnel *t)
941{
942 struct GNUNET_MESH_TunnelMessage msg;
943
944 if (NULL == t->client)
945 return;
946 msg.header.size = htons (sizeof (msg));
947 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
948 msg.tunnel_id = htonl (t->local_tid_dest);
949 msg.port = htonl (t->port);
950 GNUNET_PEER_resolve (t->id.oid, &msg.peer);
951 GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
952 &msg.header, GNUNET_NO);
953}
954
955
956/**
957 * Notify dest client that the incoming tunnel is no longer valid.
958 *
959 * @param c Client to notify..
960 * @param t Tunnel that is destroyed.
961 */
962static void
963send_client_tunnel_destroy (struct MeshClient *c, struct MeshTunnel *t)
964{
965 struct GNUNET_MESH_TunnelMessage msg;
966
967 if (NULL == c)
968 {
969 GNUNET_break (0);
970 return;
971 }
972 if (c != t->client && c != t->owner)
973 {
974 GNUNET_break (0);
975 return;
976 }
977 msg.header.size = htons (sizeof (msg));
978 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
979 msg.tunnel_id = htonl (t->local_tid_dest);
980 msg.port = htonl (0);
981 memset(&msg.peer, 0, sizeof (msg.peer));
982 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
983 &msg.header, GNUNET_NO);
984}
985
986
987/**
988 * Iterator over all the peers to remove the oldest not-used entry.
989 *
990 * @param cls Closure (unsued).
991 * @param key ID of the peer.
992 * @param value Peer_Info of the peer.
993 *
994 * FIXME implement
995 */
996static int
997peer_info_timeout (void *cls,
998 const struct GNUNET_HashCode *key,
999 void *value)
1000{
1001 return GNUNET_YES;
1002}
1003
1004/**
1005 * Retrieve the MeshPeerInfo stucture associated with the peer, create one
1006 * and insert it in the appropriate structures if the peer is not known yet.
1007 *
1008 * @param peer Full identity of the peer.
1009 *
1010 * @return Existing or newly created peer info.
1011 */
1012static struct MeshPeerInfo *
1013peer_get (const struct GNUNET_PeerIdentity *peer)
1014{
1015 struct MeshPeerInfo *peer_info;
1016
1017 peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
1018 if (NULL == peer_info)
1019 {
1020 peer_info =
1021 (struct MeshPeerInfo *) GNUNET_malloc (sizeof (struct MeshPeerInfo));
1022 if (GNUNET_CONTAINER_multihashmap_size (peers) > max_peers)
1023 {
1024 GNUNET_CONTAINER_multihashmap_iterate (peers,
1025 &peer_info_timeout,
1026 NULL);
1027 }
1028 GNUNET_CONTAINER_multihashmap_put (peers, &peer->hashPubKey, peer_info,
1029 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1030 peer_info->id = GNUNET_PEER_intern (peer);
1031 }
1032 peer_info->last_contact = GNUNET_TIME_absolute_get();
1033
1034 return peer_info;
1035}
1036
1037
1038/**
1039 * Retrieve the MeshPeerInfo stucture associated with the peer, create one
1040 * and insert it in the appropriate structures if the peer is not known yet.
1041 *
1042 * @param peer Short identity of the peer.
1043 *
1044 * @return Existing or newly created peer info.
1045 */
1046static struct MeshPeerInfo *
1047peer_get_short (const GNUNET_PEER_Id peer)
1048{
1049 struct GNUNET_PeerIdentity id;
1050
1051 GNUNET_PEER_resolve (peer, &id);
1052 return peer_get (&id);
1053}
1054
1055
1056/**
1057 * Choose the best path towards a peer considering the tunnel properties.
1058 *
1059 * @param peer The destination peer.
1060 * @param t The tunnel the path is for.
1061 *
1062 * @return Best current known path towards the peer, if any.
1063 */
1064static struct MeshPeerPath *
1065peer_get_best_path (const struct MeshPeerInfo *peer, const struct MeshTunnel *t)
1066{
1067 struct MeshPeerPath *best_p;
1068 struct MeshPeerPath *p;
1069 unsigned int best_cost;
1070 unsigned int cost;
1071
1072 best_p = p = peer->path_head;
1073 best_cost = cost = p->length;
1074 while (NULL != p)
1075 {
1076 if ((cost = p->length) < best_cost)
1077 {
1078 best_cost = cost;
1079 best_p = p;
1080 }
1081 p = p->next;
1082 }
1083 return best_p;
1084}
1085
1086/**
1087 * Core callback to write a pre-constructed data packet to core buffer
1088 *
1089 * @param cls Closure (MeshTransmissionDescriptor with data in "data" member).
1090 * @param size Number of bytes available in buf.
1091 * @param buf Where the to write the message.
1092 *
1093 * @return number of bytes written to buf
1094 */
1095static size_t
1096send_core_data_raw (void *cls, size_t size, void *buf)
1097{
1098 struct GNUNET_MessageHeader *msg = cls;
1099 size_t total_size;
1100
1101 GNUNET_assert (NULL != msg);
1102 total_size = ntohs (msg->size);
1103
1104 if (total_size > size)
1105 {
1106 GNUNET_break (0);
1107 return 0;
1108 }
1109 memcpy (buf, msg, total_size);
1110 GNUNET_free (cls);
1111 return total_size;
1112}
1113
1114
1115/**
1116 * Sends an already built message to a peer, properly registrating
1117 * all used resources.
1118 *
1119 * @param message Message to send. Function makes a copy of it.
1120 * @param peer Short ID of the neighbor whom to send the message.
1121 * @param t Tunnel on which this message is transmitted.
1122 */
1123static void
1124send_prebuilt_message (const struct GNUNET_MessageHeader *message,
1125 GNUNET_PEER_Id peer,
1126 struct MeshTunnel *t)
1127{
1128 struct GNUNET_PeerIdentity id;
1129 struct MeshPeerInfo *neighbor;
1130 struct MeshPeerPath *p;
1131 void *data;
1132 size_t size;
1133 uint16_t type;
1134
1135// GNUNET_TRANSPORT_try_connect(); FIXME use?
1136
1137 if (0 == peer)
1138 return;
1139
1140 size = ntohs (message->size);
1141 data = GNUNET_malloc (size);
1142 memcpy (data, message, size);
1143 type = ntohs(message->type);
1144 if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type ||
1145 GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == type)
1146 {
1147 struct GNUNET_MESH_Data *u;
1148
1149 u = (struct GNUNET_MESH_Data *) data;
1150 u->ttl = htonl (ntohl (u->ttl) - 1);
1151 }
1152 GNUNET_PEER_resolve (peer, &id);
1153 neighbor = peer_get (&id);
1154 for (p = neighbor->path_head; NULL != p; p = p->next)
1155 {
1156 if (2 >= p->length)
1157 {
1158 break;
1159 }
1160 }
1161 if (NULL == p)
1162 {
1163#if MESH_DEBUG
1164 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1165 " %s IS NOT DIRECTLY CONNECTED\n",
1166 GNUNET_i2s(&id));
1167 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1168 " PATHS TO %s:\n",
1169 GNUNET_i2s(&id));
1170 for (p = neighbor->path_head; NULL != p; p = p->next)
1171 {
1172 struct GNUNET_PeerIdentity debug_id;
1173 unsigned int i;
1174
1175 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1176 " path with %u hops through:\n",
1177 p->length);
1178 for (i = 0; i < p->length; i++)
1179 {
1180 GNUNET_PEER_resolve(p->peers[i], &debug_id);
1181 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1182 " hop %u: %s\n",
1183 i, GNUNET_i2s(&debug_id));
1184 }
1185 }
1186#endif
1187 GNUNET_break (0); // FIXME sometimes fails (testing disconnect?)
1188 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1189 " no direct connection to %s\n",
1190 GNUNET_i2s (&id));
1191 GNUNET_free (data);
1192 return;
1193 }
1194 if (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK == type)
1195 type = 0;
1196 queue_add (data,
1197 type,
1198 size,
1199 neighbor,
1200 t);
1201}
1202
1203
1204/**
1205 * Sends a CREATE PATH message for a path to a peer, properly registrating
1206 * all used resources.
1207 *
1208 * @param t Tunnel for which the path is created.
1209 */
1210static void
1211send_create_path (struct MeshTunnel *t)
1212{
1213 struct MeshPeerInfo *neighbor;
1214
1215 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send create path\n");
1216 neighbor = peer_get_short (t->next_hop);
1217 queue_add (t,
1218 GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE,
1219 sizeof (struct GNUNET_MESH_CreateTunnel) +
1220 (t->path->length * sizeof (struct GNUNET_PeerIdentity)),
1221 neighbor,
1222 t);
1223 t->state = MESH_TUNNEL_WAITING;
1224}
1225
1226
1227/**
1228 * Sends a PATH ACK message in reponse to a received PATH_CREATE directed to us.
1229 *
1230 * @param t Tunnel which to confirm.
1231 */
1232static void
1233send_path_ack (struct MeshTunnel *t)
1234{
1235 struct MeshPeerInfo *peer;
1236
1237 peer = peer_get_short (t->prev_hop);
1238
1239 queue_add (t,
1240 GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
1241 sizeof (struct GNUNET_MESH_PathACK),
1242 peer,
1243 t);
1244}
1245
1246
1247/**
1248 * Try to establish a new connection to this peer in the given tunnel.
1249 * If the peer doesn't have any path to it yet, try to get one.
1250 * If the peer already has some path, send a CREATE PATH towards it.
1251 *
1252 * @param peer PeerInfo of the peer.
1253 * @param t Tunnel for which to create the path, if possible.
1254 */
1255static void
1256peer_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t)
1257{
1258 struct MeshPeerPath *p;
1259
1260 if (NULL != peer->path_head)
1261 {
1262 p = peer_get_best_path (peer, t);
1263 tunnel_use_path (t, p);
1264 send_create_path (t);
1265 }
1266 else if (NULL == peer->dhtget)
1267 {
1268 struct GNUNET_PeerIdentity id;
1269
1270 GNUNET_PEER_resolve (peer->id, &id);
1271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1272 " Starting DHT GET for peer %s\n", GNUNET_i2s (&id));
1273 peer->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */
1274 GNUNET_BLOCK_TYPE_MESH_PEER, /* type */
1275 &id.hashPubKey, /* key to search */
1276 dht_replication_level, /* replication level */
1277 GNUNET_DHT_RO_RECORD_ROUTE |
1278 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
1279 NULL, /* xquery */
1280 0, /* xquery bits */
1281 &dht_get_id_handler, peer);
1282 t->state = MESH_TUNNEL_SEARCHING;
1283 }
1284 else
1285 {
1286 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1287 "There is no path but the DHT GET is already started.\n");
1288 }
1289}
1290
1291
1292/**
1293 * Destroy the peer_info and free any allocated resources linked to it
1294 *
1295 * @param pi The peer_info to destroy.
1296 *
1297 * @return GNUNET_OK on success
1298 */
1299static int
1300peer_info_destroy (struct MeshPeerInfo *pi)
1301{
1302 struct GNUNET_PeerIdentity id;
1303 struct MeshPeerPath *p;
1304 struct MeshPeerPath *nextp;
1305 unsigned int i;
1306
1307 GNUNET_PEER_resolve (pi->id, &id);
1308 GNUNET_PEER_change_rc (pi->id, -1);
1309
1310 if (GNUNET_YES !=
1311 GNUNET_CONTAINER_multihashmap_remove (peers, &id.hashPubKey, pi))
1312 {
1313 GNUNET_break (0);
1314 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1315 "removing peer %s, not in hashmap\n", GNUNET_i2s (&id));
1316 }
1317 if (NULL != pi->dhtget)
1318 {
1319 GNUNET_DHT_get_stop (pi->dhtget);
1320 }
1321 p = pi->path_head;
1322 while (NULL != p)
1323 {
1324 nextp = p->next;
1325 GNUNET_CONTAINER_DLL_remove (pi->path_head, pi->path_tail, p);
1326 path_destroy (p);
1327 p = nextp;
1328 }
1329 for (i = 0; i < pi->ntunnels; i++)
1330 tunnel_destroy_empty (pi->tunnels[i]);
1331 GNUNET_array_grow (pi->tunnels, pi->ntunnels, 0);
1332 GNUNET_free (pi);
1333 return GNUNET_OK;
1334}
1335
1336
1337/**
1338 * Remove all paths that rely on a direct connection between p1 and p2
1339 * from the peer itself and notify all tunnels about it.
1340 *
1341 * @param peer PeerInfo of affected peer.
1342 * @param p1 GNUNET_PEER_Id of one peer.
1343 * @param p2 GNUNET_PEER_Id of another peer that was connected to the first and
1344 * no longer is.
1345 *
1346 * TODO: optimize (see below)
1347 */
1348static void
1349peer_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1,
1350 GNUNET_PEER_Id p2)
1351{
1352 struct MeshPeerPath *p;
1353 struct MeshPeerPath *next;
1354 struct MeshPeerInfo *peer_d;
1355 GNUNET_PEER_Id d;
1356 unsigned int destroyed;
1357 unsigned int i;
1358
1359 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path\n");
1360 destroyed = 0;
1361 for (p = peer->path_head; NULL != p; p = next)
1362 {
1363 next = p->next;
1364 for (i = 0; i < (p->length - 1); i++)
1365 {
1366 if ((p->peers[i] == p1 && p->peers[i + 1] == p2) ||
1367 (p->peers[i] == p2 && p->peers[i + 1] == p1))
1368 {
1369 GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p);
1370 path_destroy (p);
1371 destroyed++;
1372 break;
1373 }
1374 }
1375 }
1376 if (0 == destroyed)
1377 return;
1378
1379 for (i = 0; i < peer->ntunnels; i++)
1380 {
1381 d = tunnel_notify_connection_broken (peer->tunnels[i], p1, p2);
1382 if (0 == d)
1383 continue;
1384
1385 peer_d = peer_get_short (d);
1386 next = peer_get_best_path (peer_d, peer->tunnels[i]);
1387 tunnel_use_path (peer->tunnels[i], next);
1388 peer_connect (peer_d, peer->tunnels[i]);
1389 }
1390 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path END\n");
1391}
1392
1393
1394/**
1395 * Add the path to the peer and update the path used to reach it in case this
1396 * is the shortest.
1397 *
1398 * @param peer_info Destination peer to add the path to.
1399 * @param path New path to add. Last peer must be the peer in arg 1.
1400 * Path will be either used of freed if already known.
1401 * @param trusted Do we trust that this path is real?
1402 */
1403void
1404peer_info_add_path (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path,
1405 int trusted)
1406{
1407 struct MeshPeerPath *aux;
1408 unsigned int l;
1409 unsigned int l2;
1410
1411 if ((NULL == peer_info) || (NULL == path))
1412 {
1413 GNUNET_break (0);
1414 path_destroy (path);
1415 return;
1416 }
1417 if (path->peers[path->length - 1] != peer_info->id)
1418 {
1419 GNUNET_break (0);
1420 path_destroy (path);
1421 return;
1422 }
1423 if (2 >= path->length && GNUNET_NO == trusted)
1424 {
1425 /* Only allow CORE to tell us about direct paths */
1426 path_destroy (path);
1427 return;
1428 }
1429 for (l = 1; l < path->length; l++)
1430 {
1431 if (path->peers[l] == myid)
1432 {
1433 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shortening path by %u\n", l);
1434 for (l2 = 0; l2 < path->length - l; l2++)
1435 {
1436 path->peers[l2] = path->peers[l + l2];
1437 }
1438 path->length -= l;
1439 l = 1;
1440 path->peers =
1441 GNUNET_realloc (path->peers, path->length * sizeof (GNUNET_PEER_Id));
1442 }
1443 }
1444#if MESH_DEBUG
1445 {
1446 struct GNUNET_PeerIdentity id;
1447
1448 GNUNET_PEER_resolve (peer_info->id, &id);
1449 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n",
1450 path->length, GNUNET_i2s (&id));
1451 }
1452#endif
1453 l = path_get_length (path);
1454 if (0 == l)
1455 {
1456 path_destroy (path);
1457 return;
1458 }
1459
1460 GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
1461 for (aux = peer_info->path_head; aux != NULL; aux = aux->next)
1462 {
1463 l2 = path_get_length (aux);
1464 if (l2 > l)
1465 {
1466 GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head,
1467 peer_info->path_tail, aux, path);
1468 return;
1469 }
1470 else
1471 {
1472 if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
1473 {
1474 path_destroy (path);
1475 return;
1476 }
1477 }
1478 }
1479 GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail,
1480 path);
1481 return;
1482}
1483
1484
1485/**
1486 * Add the path to the origin peer and update the path used to reach it in case
1487 * this is the shortest.
1488 * The path is given in peer_info -> destination, therefore we turn the path
1489 * upside down first.
1490 *
1491 * @param peer_info Peer to add the path to, being the origin of the path.
1492 * @param path New path to add after being inversed.
1493 * Path will be either used or freed.
1494 * @param trusted Do we trust that this path is real?
1495 */
1496static void
1497peer_info_add_path_to_origin (struct MeshPeerInfo *peer_info,
1498 struct MeshPeerPath *path, int trusted)
1499{
1500 path_invert (path);
1501 peer_info_add_path (peer_info, path, trusted);
1502}
1503
1504
1505/**
1506 * Add a tunnel to the list of tunnels a peer participates in.
1507 * Update the tunnel's destination.
1508 *
1509 * @param p Peer to add to.
1510 * @param t Tunnel to add.
1511 */
1512static void
1513peer_info_add_tunnel (struct MeshPeerInfo *p, struct MeshTunnel *t)
1514{
1515 if (0 != t->dest)
1516 {
1517 GNUNET_break (t->dest == p->id);
1518 return;
1519 }
1520 t->dest = p->id;
1521 GNUNET_PEER_change_rc (t->dest, 1);
1522 GNUNET_array_append (p->tunnels, p->ntunnels, t);
1523}
1524
1525
1526/**
1527 * Remove a tunnel from the list of tunnels a peer participates in.
1528 * Free the tunnel's destination.
1529 *
1530 * @param p Peer to clean.
1531 * @param t Tunnel to remove.
1532 */
1533static void
1534peer_info_remove_tunnel (struct MeshPeerInfo *p, struct MeshTunnel *t)
1535{
1536 unsigned int i;
1537
1538 if (t->dest == p->id)
1539 {
1540 GNUNET_PEER_change_rc (t->dest, -1);
1541 t->dest = 0;
1542 }
1543 for (i = 0; i < p->ntunnels; i++)
1544 {
1545 if (p->tunnels[i] == t)
1546 {
1547 p->tunnels[i] = p->tunnels[p->ntunnels - 1];
1548 GNUNET_array_grow (p->tunnels, p->ntunnels, p->ntunnels - 1);
1549 return;
1550 }
1551 }
1552}
1553
1554
1555/**
1556 * Function called if the connection to the peer has been stalled for a while,
1557 * possibly due to a missed ACK. Poll the peer about its ACK status.
1558 *
1559 * @param cls Closure (poll ctx).
1560 * @param tc TaskContext.
1561 */
1562static void
1563tunnel_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1564{
1565 struct MeshFlowControl *fc = cls;
1566 struct GNUNET_MESH_Poll msg;
1567 struct MeshTunnel *t = fc->t;
1568 GNUNET_PEER_Id peer;
1569
1570 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
1571 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1572 {
1573 return;
1574 }
1575
1576 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL);
1577 msg.header.size = htons (sizeof (msg));
1578 msg.tid = htonl (t->id.tid);
1579 GNUNET_PEER_resolve (t->id.oid, &msg.oid);
1580
1581 if (fc == &t->prev_fc)
1582 {
1583 peer = t->prev_hop;
1584 }
1585 else if (fc == &t->next_fc)
1586 {
1587 peer = t->next_hop;
1588 }
1589 else
1590 {
1591 GNUNET_break (0);
1592 return;
1593 }
1594 send_prebuilt_message (&msg.header, peer, t);
1595 fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
1596 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
1597 &tunnel_poll, fc);
1598}
1599
1600
1601/**
1602 * Build a PeerPath from the paths returned from the DHT, reversing the paths
1603 * to obtain a local peer -> destination path and interning the peer ids.
1604 *
1605 * @return Newly allocated and created path
1606 */
1607static struct MeshPeerPath *
1608path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
1609 unsigned int get_path_length,
1610 const struct GNUNET_PeerIdentity *put_path,
1611 unsigned int put_path_length)
1612{
1613 struct MeshPeerPath *p;
1614 GNUNET_PEER_Id id;
1615 int i;
1616
1617 p = path_new (1);
1618 p->peers[0] = myid;
1619 GNUNET_PEER_change_rc (myid, 1);
1620 i = get_path_length;
1621 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " GET has %d hops.\n", i);
1622 for (i--; i >= 0; i--)
1623 {
1624 id = GNUNET_PEER_intern (&get_path[i]);
1625 if (p->length > 0 && id == p->peers[p->length - 1])
1626 {
1627 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Optimizing 1 hop out.\n");
1628 GNUNET_PEER_change_rc (id, -1);
1629 }
1630 else
1631 {
1632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Adding from GET: %s.\n",
1633 GNUNET_i2s (&get_path[i]));
1634 p->length++;
1635 p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length);
1636 p->peers[p->length - 1] = id;
1637 }
1638 }
1639 i = put_path_length;
1640 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " PUT has %d hops.\n", i);
1641 for (i--; i >= 0; i--)
1642 {
1643 id = GNUNET_PEER_intern (&put_path[i]);
1644 if (id == myid)
1645 {
1646 /* PUT path went through us, so discard the path up until now and start
1647 * from here to get a much shorter (and loop-free) path.
1648 */
1649 path_destroy (p);
1650 p = path_new (0);
1651 }
1652 if (p->length > 0 && id == p->peers[p->length - 1])
1653 {
1654 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Optimizing 1 hop out.\n");
1655 GNUNET_PEER_change_rc (id, -1);
1656 }
1657 else
1658 {
1659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Adding from PUT: %s.\n",
1660 GNUNET_i2s (&put_path[i]));
1661 p->length++;
1662 p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length);
1663 p->peers[p->length - 1] = id;
1664 }
1665 }
1666#if MESH_DEBUG
1667 if (get_path_length > 0)
1668 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (first of GET: %s)\n",
1669 GNUNET_i2s (&get_path[0]));
1670 if (put_path_length > 0)
1671 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (first of PUT: %s)\n",
1672 GNUNET_i2s (&put_path[0]));
1673 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " In total: %d hops\n",
1674 p->length);
1675 for (i = 0; i < p->length; i++)
1676 {
1677 struct GNUNET_PeerIdentity peer_id;
1678
1679 GNUNET_PEER_resolve (p->peers[i], &peer_id);
1680 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %u: %s\n", p->peers[i],
1681 GNUNET_i2s (&peer_id));
1682 }
1683#endif
1684 return p;
1685}
1686
1687
1688/**
1689 * Adds a path to the peer_infos of all the peers in the path
1690 *
1691 * @param p Path to process.
1692 * @param confirmed Whether we know if the path works or not.
1693 */
1694static void
1695path_add_to_peers (struct MeshPeerPath *p, int confirmed)
1696{
1697 unsigned int i;
1698
1699 /* TODO: invert and add */
1700 for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ;
1701 for (i++; i < p->length; i++)
1702 {
1703 struct MeshPeerInfo *aux;
1704 struct MeshPeerPath *copy;
1705
1706 aux = peer_get_short (p->peers[i]);
1707 copy = path_duplicate (p);
1708 copy->length = i + 1;
1709 peer_info_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed);
1710 }
1711}
1712
1713
1714/**
1715 * Send keepalive packets for a peer
1716 *
1717 * @param cls Closure (tunnel for which to send the keepalive).
1718 * @param tc Notification context.
1719 */
1720static void
1721path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1722
1723
1724/**
1725 * Search for a tunnel among the incoming tunnels
1726 *
1727 * @param tid the local id of the tunnel
1728 *
1729 * @return tunnel handler, NULL if doesn't exist
1730 */
1731static struct MeshTunnel *
1732tunnel_get_incoming (MESH_TunnelNumber tid)
1733{
1734 struct GNUNET_HashCode hash;
1735
1736 GNUNET_assert (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV);
1737 GMC_hash32 (tid, &hash);
1738 return GNUNET_CONTAINER_multihashmap_get (incoming_tunnels, &hash);
1739}
1740
1741
1742/**
1743 * Search for a tunnel among the tunnels for a client
1744 *
1745 * @param c the client whose tunnels to search in
1746 * @param tid the local id of the tunnel
1747 *
1748 * @return tunnel handler, NULL if doesn't exist
1749 */
1750static struct MeshTunnel *
1751tunnel_get_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
1752{
1753 if (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1754 {
1755 return tunnel_get_incoming (tid);
1756 }
1757 else
1758 {
1759 struct GNUNET_HashCode hash;
1760
1761 GMC_hash32 (tid, &hash);
1762 return GNUNET_CONTAINER_multihashmap_get (c->own_tunnels, &hash);
1763 }
1764}
1765
1766
1767/**
1768 * Search for a tunnel by global ID using PEER_ID
1769 *
1770 * @param pi owner of the tunnel
1771 * @param tid global tunnel number
1772 *
1773 * @return tunnel handler, NULL if doesn't exist
1774 */
1775static struct MeshTunnel *
1776tunnel_get_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
1777{
1778 struct MESH_TunnelID id;
1779 struct GNUNET_HashCode hash;
1780
1781 id.oid = pi;
1782 id.tid = tid;
1783
1784 GNUNET_CRYPTO_hash (&id, sizeof (struct MESH_TunnelID), &hash);
1785 return GNUNET_CONTAINER_multihashmap_get (tunnels, &hash);
1786}
1787
1788
1789/**
1790 * Search for a tunnel by global ID using full PeerIdentities
1791 *
1792 * @param oid owner of the tunnel
1793 * @param tid global tunnel number
1794 *
1795 * @return tunnel handler, NULL if doesn't exist
1796 */
1797static struct MeshTunnel *
1798tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
1799{
1800 return tunnel_get_by_pi (GNUNET_PEER_search (oid), tid);
1801}
1802
1803
1804/**
1805 * Add a client to a tunnel, initializing all needed data structures.
1806 *
1807 * @param t Tunnel to which add the client.
1808 * @param c Client which to add to the tunnel.
1809 */
1810static void
1811tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c)
1812{
1813 struct GNUNET_HashCode hash;
1814
1815 if (NULL != t->client)
1816 {
1817 GNUNET_break(0);
1818 return;
1819 }
1820 GMC_hash32 (t->local_tid_dest, &hash);
1821 if (GNUNET_OK !=
1822 GNUNET_CONTAINER_multihashmap_put (c->incoming_tunnels, &hash, t,
1823 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
1824 {
1825 GNUNET_break (0);
1826 return;
1827 }
1828 if (GNUNET_OK !=
1829 GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
1830 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
1831 {
1832 GNUNET_break (0);
1833 return;
1834 }
1835 t->client = c;
1836}
1837
1838
1839static void
1840tunnel_use_path (struct MeshTunnel *t, struct MeshPeerPath *p)
1841{
1842 unsigned int own_pos;
1843
1844 for (own_pos = 0; own_pos < p->length; own_pos++)
1845 {
1846 if (p->peers[own_pos] == myid)
1847 break;
1848 }
1849 if (own_pos > p->length - 1)
1850 {
1851 GNUNET_break (0);
1852 return;
1853 }
1854
1855 if (own_pos < p->length - 1)
1856 t->next_hop = p->peers[own_pos + 1];
1857 else
1858 t->next_hop = p->peers[own_pos];
1859 GNUNET_PEER_change_rc (t->next_hop, 1);
1860 if (0 < own_pos)
1861 t->prev_hop = p->peers[own_pos - 1];
1862 else
1863 t->prev_hop = p->peers[0];
1864 GNUNET_PEER_change_rc (t->prev_hop, 1);
1865
1866 if (NULL != t->path)
1867 path_destroy (t->path);
1868 t->path = path_duplicate (p);
1869 if (0 == own_pos)
1870 {
1871 if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task)
1872 GNUNET_SCHEDULER_cancel (t->maintenance_task);
1873 t->maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_path_time,
1874 &path_refresh, t);
1875 }
1876}
1877
1878
1879/**
1880 * Notifies a tunnel that a connection has broken that affects at least
1881 * some of its peers. Sends a notification towards the root of the tree.
1882 * In case the peer is the owner of the tree, notifies the client that owns
1883 * the tunnel and tries to reconnect.
1884 *
1885 * @param t Tunnel affected.
1886 * @param p1 Peer that got disconnected from p2.
1887 * @param p2 Peer that got disconnected from p1.
1888 *
1889 * @return Short ID of the peer disconnected (either p1 or p2).
1890 * 0 if the tunnel remained unaffected.
1891 */
1892static GNUNET_PEER_Id
1893tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
1894 GNUNET_PEER_Id p2)
1895{
1896// if (myid != p1 && myid != p2) FIXME
1897// {
1898// return;
1899// }
1900//
1901// if (tree_get_predecessor (t->tree) != 0)
1902// {
1903// /* We are the peer still connected, notify owner of the disconnection. */
1904// struct GNUNET_MESH_PathBroken msg;
1905// struct GNUNET_PeerIdentity neighbor;
1906//
1907// msg.header.size = htons (sizeof (msg));
1908// msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN);
1909// GNUNET_PEER_resolve (t->id.oid, &msg.oid);
1910// msg.tid = htonl (t->id.tid);
1911// msg.peer1 = my_full_id;
1912// GNUNET_PEER_resolve (pid, &msg.peer2);
1913// GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor);
1914// send_prebuilt_message (&msg.header, &neighbor, t);
1915// }
1916 return 0;
1917}
1918
1919
1920/**
1921 * Build a local ACK message and send it to a local client.
1922 *
1923 * @param t Tunnel on which to send the ACK.
1924 * @param c Client to whom send the ACK.
1925 * @param ack Value of the ACK.
1926 */
1927static void
1928send_local_ack (struct MeshTunnel *t, struct MeshClient *c, uint32_t ack)
1929{
1930 struct GNUNET_MESH_LocalAck msg;
1931
1932 msg.header.size = htons (sizeof (msg));
1933 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
1934 msg.tunnel_id = htonl (t->owner == c ? t->local_tid : t->local_tid_dest);
1935 msg.ack = htonl (ack);
1936 GNUNET_SERVER_notification_context_unicast(nc,
1937 c->handle,
1938 &msg.header,
1939 GNUNET_NO);
1940}
1941
1942/**
1943 * Build an ACK message and queue it to send to the given peer.
1944 *
1945 * @param t Tunnel on which to send the ACK.
1946 * @param peer Peer to whom send the ACK.
1947 * @param ack Value of the ACK.
1948 */
1949static void
1950send_ack (struct MeshTunnel *t, GNUNET_PEER_Id peer, uint32_t ack)
1951{
1952 struct GNUNET_MESH_ACK msg;
1953
1954 GNUNET_PEER_resolve (t->id.oid, &msg.oid);
1955 msg.header.size = htons (sizeof (msg));
1956 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
1957 msg.pid = htonl (ack);
1958 msg.tid = htonl (t->id.tid);
1959
1960 send_prebuilt_message (&msg.header, peer, t);
1961}
1962
1963
1964/**
1965 * Send an ACK informing the predecessor about the available buffer space.
1966 * In case there is no predecessor, inform the owning client.
1967 * If buffering is off, send only on behalf of children or self if endpoint.
1968 * If buffering is on, send when sent to children and buffer space is free.
1969 * Note that although the name is fwd_ack, the FWD mean forward *traffic*,
1970 * the ACK itself goes "back" (towards root).
1971 *
1972 * @param t Tunnel on which to send the ACK.
1973 * @param type Type of message that triggered the ACK transmission.
1974 */
1975static void
1976tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type)
1977{
1978 uint32_t ack;
1979
1980 /* Is it after unicast retransmission? */
1981 switch (type)
1982 {
1983 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1984 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1985 "ACK due to FWD DATA retransmission\n");
1986 if (GNUNET_YES == t->nobuffer)
1987 {
1988 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, nobuffer\n");
1989 return;
1990 }
1991 break;
1992 case GNUNET_MESSAGE_TYPE_MESH_ACK:
1993 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
1994 break;
1995 case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
1996 case GNUNET_MESSAGE_TYPE_MESH_POLL:
1997 t->force_ack = GNUNET_YES;
1998 break;
1999 default:
2000 GNUNET_break (0);
2001 }
2002
2003 /* Check if we need to transmit the ACK */
2004 if (t->queue_max > t->next_fc.queue_n * 4 &&
2005 GMC_is_pid_bigger(t->prev_fc.last_ack_sent, t->prev_fc.last_pid_recv) &&
2006 GNUNET_NO == t->force_ack)
2007 {
2008 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer free\n");
2009 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2010 " t->qmax: %u, t->qn: %u\n",
2011 t->queue_max, t->next_fc.queue_n);
2012 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2013 " t->pid: %u, t->ack: %u\n",
2014 t->prev_fc.last_pid_recv, t->prev_fc.last_ack_sent);
2015 return;
2016 }
2017
2018 /* Ok, ACK might be necessary, what PID to ACK? */
2019 ack = t->prev_fc.last_pid_recv + t->queue_max - t->next_fc.queue_n;
2020 if (ack == t->prev_fc.last_ack_sent && GNUNET_NO == t->force_ack)
2021 {
2022 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
2023 return;
2024 }
2025
2026 t->prev_fc.last_ack_sent = ack;
2027 if (NULL != t->owner)
2028 send_local_ack (t, t->owner, ack);
2029 else if (0 != t->prev_hop)
2030 send_ack (t, t->prev_hop, ack);
2031 else
2032 GNUNET_break (0);
2033 debug_fwd_ack++;
2034 t->force_ack = GNUNET_NO;
2035}
2036
2037
2038/**
2039 * Send an ACK informing the children node/client about the available
2040 * buffer space.
2041 * If buffering is off, send only on behalf of root (can be self).
2042 * If buffering is on, send when sent to predecessor and buffer space is free.
2043 * Note that although the name is bck_ack, the BCK mean backwards *traffic*,
2044 * the ACK itself goes "forward" (towards children/clients).
2045 *
2046 * @param t Tunnel on which to send the ACK.
2047 * @param type Type of message that triggered the ACK transmission.
2048 */
2049static void
2050tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type)
2051{
2052 uint32_t ack;
2053 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2054 "Sending BCK ACK on tunnel %u [%u] due to %s\n",
2055 t->id.oid, t->id.tid, GNUNET_MESH_DEBUG_M2S(type));
2056 /* Is it after data to_origin retransmission? */
2057 switch (type)
2058 {
2059 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
2060 if (GNUNET_YES == t->nobuffer)
2061 {
2062 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2063 " Not sending ACK, nobuffer + traffic\n");
2064 return;
2065 }
2066 break;
2067 case GNUNET_MESSAGE_TYPE_MESH_ACK:
2068 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
2069 break;
2070 case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
2071 case GNUNET_MESSAGE_TYPE_MESH_POLL:
2072 t->force_ack = GNUNET_YES;
2073 break;
2074 default:
2075 GNUNET_break (0);
2076 }
2077
2078 /* TODO: Check if we need to transmit the ACK (as in fwd) */
2079
2080 ack = t->next_fc.last_pid_recv + t->queue_max - t->prev_fc.queue_n;
2081
2082 if (t->next_fc.last_ack_sent == ack && GNUNET_NO == t->force_ack)
2083 {
2084 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2085 " Not sending ACK, not needed, last ack sent was %u\n",
2086 t->next_fc.last_ack_sent);
2087 return;
2088 }
2089 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2090 " Sending BCK ACK %u (last sent: %u)\n",
2091 ack, t->next_fc.last_ack_sent);
2092 t->next_fc.last_ack_sent = ack;
2093
2094 if (NULL != t->client)
2095 send_local_ack (t, t->client, ack);
2096 else if (0 != t->next_hop)
2097 send_ack (t, t->next_hop, ack);
2098 else
2099 GNUNET_break (0);
2100 t->force_ack = GNUNET_NO;
2101}
2102
2103
2104/**
2105 * Modify the unicast message TID from global to local and send to client.
2106 *
2107 * @param t Tunnel on which to send the message.
2108 * @param msg Message to modify and send.
2109 */
2110static void
2111tunnel_send_client_ucast (struct MeshTunnel *t,
2112 const struct GNUNET_MESH_Data *msg)
2113{
2114 struct GNUNET_MESH_Data *copy;
2115 uint16_t size = ntohs (msg->header.size);
2116 char cbuf[size];
2117
2118 if (size < sizeof (struct GNUNET_MESH_Data) +
2119 sizeof (struct GNUNET_MessageHeader))
2120 {
2121 GNUNET_break_op (0);
2122 return;
2123 }
2124 if (NULL == t->client)
2125 {
2126 GNUNET_break (0);
2127 return;
2128 }
2129 copy = (struct GNUNET_MESH_Data *) cbuf;
2130 memcpy (copy, msg, size);
2131 copy->tid = htonl (t->local_tid_dest);
2132 GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
2133 &copy->header, GNUNET_NO);
2134}
2135
2136
2137/**
2138 * Modify the to_origin message TID from global to local and send to client.
2139 *
2140 * @param t Tunnel on which to send the message.
2141 * @param msg Message to modify and send.
2142 */
2143static void
2144tunnel_send_client_to_orig (struct MeshTunnel *t,
2145 const struct GNUNET_MESH_Data *msg)
2146{
2147 struct GNUNET_MESH_Data *copy;
2148 uint16_t size = ntohs (msg->header.size);
2149 char cbuf[size];
2150
2151 if (size < sizeof (struct GNUNET_MESH_Data) +
2152 sizeof (struct GNUNET_MessageHeader))
2153 {
2154 GNUNET_break_op (0);
2155 return;
2156 }
2157 if (NULL == t->owner)
2158 {
2159 GNUNET_break (0);
2160 return;
2161 }
2162 copy = (struct GNUNET_MESH_Data *) cbuf;
2163 memcpy (cbuf, msg, size);
2164 copy->tid = htonl (t->local_tid);
2165 GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
2166 &copy->header, GNUNET_NO);
2167}
2168
2169
2170/**
2171 * @brief Re-initiate traffic to this peer if necessary.
2172 *
2173 * Check if there is traffic queued towards this peer
2174 * and the core transmit handle is NULL (traffic was stalled).
2175 * If so, call core tmt rdy.
2176 *
2177 * @param peer_id Short ID of peer to which initiate traffic.
2178 */
2179static void
2180peer_unlock_queue(GNUNET_PEER_Id peer_id)
2181{
2182 struct MeshPeerInfo *peer;
2183 struct GNUNET_PeerIdentity id;
2184 struct MeshPeerQueue *q;
2185 size_t size;
2186
2187 peer = peer_get_short (peer_id);
2188 if (NULL != peer->core_transmit)
2189 return;
2190
2191 q = queue_get_next (peer);
2192 if (NULL == q)
2193 {
2194 /* Might br multicast traffic already sent to this particular peer but
2195 * not to other children in this tunnel.
2196 * This way t->queue_n would be > 0 but the queue of this particular peer
2197 * would be empty.
2198 */
2199 return;
2200 }
2201 size = q->size;
2202 GNUNET_PEER_resolve (peer->id, &id);
2203 peer->core_transmit =
2204 GNUNET_CORE_notify_transmit_ready(core_handle,
2205 0,
2206 0,
2207 GNUNET_TIME_UNIT_FOREVER_REL,
2208 &id,
2209 size,
2210 &queue_send,
2211 peer);
2212 return;
2213}
2214
2215
2216/**
2217 * Send a message to all peers and clients in this tunnel that the tunnel
2218 * is no longer valid. If some peer or client should not receive the message,
2219 * should be zero'ed out before calling this function.
2220 *
2221 * @param t The tunnel whose peers and clients to notify.
2222 */
2223static void
2224tunnel_send_destroy (struct MeshTunnel *t)
2225{
2226 struct GNUNET_MESH_TunnelDestroy msg;
2227 struct GNUNET_PeerIdentity id;
2228
2229 msg.header.size = htons (sizeof (msg));
2230 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY);
2231 GNUNET_PEER_resolve (t->id.oid, &msg.oid);
2232 msg.tid = htonl (t->id.tid);
2233 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2234 " sending tunnel destroy for tunnel: %s [%X]\n",
2235 GNUNET_i2s (&msg.oid), t->id.tid);
2236
2237 if (NULL == t->client && 0 != t->next_hop)
2238 {
2239 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " child: %u\n", t->next_hop);
2240 GNUNET_PEER_resolve (t->next_hop, &id);
2241 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2242 " sending forward to %s\n",
2243 GNUNET_i2s (&id));
2244 send_prebuilt_message (&msg.header, t->next_hop, t);
2245 }
2246 if (NULL == t->owner && 0 != t->prev_hop)
2247 {
2248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " parent: %u\n", t->prev_hop);
2249 GNUNET_PEER_resolve (t->prev_hop, &id);
2250 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2251 " sending back to %s\n",
2252 GNUNET_i2s (&id));
2253 send_prebuilt_message (&msg.header, t->prev_hop, t);
2254 }
2255 if (NULL != t->owner)
2256 {
2257 send_client_tunnel_destroy (t->owner, t);
2258 }
2259 if (NULL != t->client)
2260 {
2261 send_client_tunnel_destroy (t->client, t);
2262 }
2263}
2264
2265
2266/**
2267 * Cancel all transmissions towards a neighbor that belongs to a certain tunnel.
2268 *
2269 * @param t Tunnel which to cancel.
2270 * @param neighbor Short ID of the neighbor to whom cancel the transmissions.
2271 */
2272static void
2273peer_cancel_queues (GNUNET_PEER_Id neighbor, struct MeshTunnel *t)
2274{
2275 struct MeshPeerInfo *peer_info;
2276 struct MeshPeerQueue *pq;
2277 struct MeshPeerQueue *next;
2278
2279 if (0 == neighbor)
2280 return; /* Was local peer, 0'ed in tunnel_destroy_iterator */
2281 peer_info = peer_get_short (neighbor);
2282 for (pq = peer_info->queue_head; NULL != pq; pq = next)
2283 {
2284 next = pq->next;
2285 if (pq->tunnel == t)
2286 {
2287 if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == pq->type ||
2288 GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == pq->type)
2289 {
2290 /* Should have been removed on destroy children */
2291 GNUNET_break (0);
2292 }
2293 queue_destroy (pq, GNUNET_YES);
2294 }
2295 }
2296 if (NULL == peer_info->queue_head && NULL != peer_info->core_transmit)
2297 {
2298 GNUNET_CORE_notify_transmit_ready_cancel(peer_info->core_transmit);
2299 peer_info->core_transmit = NULL;
2300 }
2301}
2302
2303
2304/**
2305 * Destroy the tunnel.
2306 *
2307 * This function does not generate any warning traffic to clients or peers.
2308 *
2309 * Tasks:
2310 * Remove the tunnel from peer_info's and clients' hashmaps.
2311 * Cancel messages belonging to this tunnel queued to neighbors.
2312 * Free any allocated resources linked to the tunnel.
2313 *
2314 * @param t the tunnel to destroy
2315 *
2316 * @return GNUNET_OK on success
2317 */
2318static int
2319tunnel_destroy (struct MeshTunnel *t)
2320{
2321 struct MeshClient *c;
2322 struct GNUNET_HashCode hash;
2323 int r;
2324
2325 if (NULL == t)
2326 return GNUNET_OK;
2327
2328 r = GNUNET_OK;
2329 c = t->owner;
2330#if MESH_DEBUG
2331 {
2332 struct GNUNET_PeerIdentity id;
2333
2334 GNUNET_PEER_resolve (t->id.oid, &id);
2335 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying tunnel %s [%x]\n",
2336 GNUNET_i2s (&id), t->id.tid);
2337 if (NULL != c)
2338 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
2339 }
2340#endif
2341
2342 GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
2343 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (tunnels, &hash, t))
2344 {
2345 GNUNET_break (0);
2346 r = GNUNET_SYSERR;
2347 }
2348
2349 if (NULL != c)
2350 {
2351 GMC_hash32 (t->local_tid, &hash);
2352 if (GNUNET_YES !=
2353 GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels, &hash, t))
2354 {
2355 GNUNET_break (0);
2356 r = GNUNET_SYSERR;
2357 }
2358 }
2359
2360 if (NULL != t->client)
2361 {
2362 c = t->client;
2363 GMC_hash32 (t->local_tid_dest, &hash);
2364 if (GNUNET_YES !=
2365 GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, &hash, t))
2366 {
2367 GNUNET_break (0);
2368 r = GNUNET_SYSERR;
2369 }
2370 if (GNUNET_YES !=
2371 GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t))
2372 {
2373 GNUNET_break (0);
2374 r = GNUNET_SYSERR;
2375 }
2376 }
2377
2378 if (0 != t->prev_hop)
2379 {
2380 peer_cancel_queues (t->prev_hop, t);
2381 GNUNET_PEER_change_rc (t->prev_hop, -1);
2382 }
2383 if (0 != t->next_hop)
2384 {
2385 peer_cancel_queues (t->next_hop, t);
2386 GNUNET_PEER_change_rc (t->next_hop, -1);
2387 }
2388 if (0 != t->dest) {
2389 peer_info_remove_tunnel (peer_get_short (t->dest), t);
2390 }
2391
2392 if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task)
2393 GNUNET_SCHEDULER_cancel (t->maintenance_task);
2394
2395 n_tunnels--;
2396 GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO);
2397 path_destroy (t->path);
2398 GNUNET_free (t);
2399 return r;
2400}
2401
2402/**
2403 * Tunnel is empty: destroy it.
2404 *
2405 * Notifies all participants (peers, cleints) about the destruction.
2406 *
2407 * @param t Tunnel to destroy.
2408 */
2409static void
2410tunnel_destroy_empty (struct MeshTunnel *t)
2411{
2412 #if MESH_DEBUG
2413 {
2414 struct GNUNET_PeerIdentity id;
2415
2416 GNUNET_PEER_resolve (t->id.oid, &id);
2417 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2418 "executing destruction of empty tunnel %s [%X]\n",
2419 GNUNET_i2s (&id), t->id.tid);
2420 }
2421 #endif
2422
2423 if (GNUNET_NO == t->destroy)
2424 tunnel_send_destroy (t);
2425 if (0 == t->pending_messages)
2426 tunnel_destroy (t);
2427 else
2428 t->destroy = GNUNET_YES;
2429}
2430
2431/**
2432 * Initialize a Flow Control structure to the initial state.
2433 *
2434 * @param fc Flow Control structure to initialize.
2435 */
2436static void
2437fc_init (struct MeshFlowControl *fc)
2438{
2439 fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */
2440 fc->last_pid_recv = (uint32_t) -1;
2441 fc->last_ack_sent = (uint32_t) -1; /* No traffic allowed yet */
2442 fc->last_ack_recv = (uint32_t) -1;
2443 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
2444 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
2445 fc->queue_n = 0;
2446}
2447
2448/**
2449 * Create a new tunnel
2450 *
2451 * @param owner Who is the owner of the tunnel (short ID).
2452 * @param tid Tunnel Number of the tunnel.
2453 * @param client Clients that owns the tunnel, NULL for foreign tunnels.
2454 * @param local Tunnel Number for the tunnel, for the client point of view.
2455 *
2456 * @return A new initialized tunnel. NULL on error.
2457 */
2458static struct MeshTunnel *
2459tunnel_new (GNUNET_PEER_Id owner,
2460 MESH_TunnelNumber tid,
2461 struct MeshClient *client,
2462 MESH_TunnelNumber local)
2463{
2464 struct MeshTunnel *t;
2465 struct GNUNET_HashCode hash;
2466
2467 if (n_tunnels >= max_tunnels && NULL == client)
2468 return NULL;
2469
2470 t = GNUNET_malloc (sizeof (struct MeshTunnel));
2471 t->id.oid = owner;
2472 t->id.tid = tid;
2473 t->queue_max = (max_msgs_queue / max_tunnels) + 1;
2474 t->owner = client;
2475 fc_init (&t->next_fc);
2476 fc_init (&t->prev_fc);
2477 t->local_tid = local;
2478 n_tunnels++;
2479 GNUNET_STATISTICS_update (stats, "# tunnels", 1, GNUNET_NO);
2480
2481 GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
2482 if (GNUNET_OK !=
2483 GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t,
2484 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2485 {
2486 GNUNET_break (0);
2487 tunnel_destroy (t);
2488 if (NULL != client)
2489 {
2490 GNUNET_break (0);
2491 GNUNET_SERVER_receive_done (client->handle, GNUNET_SYSERR);
2492 }
2493 return NULL;
2494 }
2495
2496 if (NULL != client)
2497 {
2498 GMC_hash32 (t->local_tid, &hash);
2499 if (GNUNET_OK !=
2500 GNUNET_CONTAINER_multihashmap_put (client->own_tunnels, &hash, t,
2501 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2502 {
2503 tunnel_destroy (t);
2504 GNUNET_break (0);
2505 GNUNET_SERVER_receive_done (client->handle, GNUNET_SYSERR);
2506 return NULL;
2507 }
2508 }
2509
2510 return t;
2511}
2512
2513
2514
2515/**
2516 * Iterator for deleting each tunnel whose client endpoint disconnected.
2517 *
2518 * @param cls Closure (client that has disconnected).
2519 * @param key The hash of the local tunnel id (used to access the hashmap).
2520 * @param value The value stored at the key (tunnel to destroy).
2521 *
2522 * @return GNUNET_OK, keep iterating.
2523 */
2524static int
2525tunnel_destroy_iterator (void *cls,
2526 const struct GNUNET_HashCode * key,
2527 void *value)
2528{
2529 struct MeshTunnel *t = value;
2530 struct MeshClient *c = cls;
2531
2532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2533 " Tunnel %X / %X destroy, due to client %u shutdown.\n",
2534 t->local_tid, t->local_tid_dest, c->id);
2535 client_delete_tunnel (c, t);
2536 if (c == t->client)
2537 {
2538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Client %u is destination.\n", c->id);
2539 t->client = NULL;
2540 if (0 != t->next_hop) { /* destroy could come before a path is used */
2541 GNUNET_PEER_change_rc (t->next_hop, -1);
2542 t->next_hop = 0;
2543 }
2544 }
2545 else if (c == t->owner)
2546 {
2547 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Client %u is owner.\n", c->id);
2548 t->owner = NULL;
2549 if (0 != t->prev_hop) { /* destroy could come before a path is used */
2550 GNUNET_PEER_change_rc (t->prev_hop, -1);
2551 t->prev_hop = 0;
2552 }
2553 }
2554 else
2555 {
2556 GNUNET_break (0);
2557 }
2558 tunnel_destroy_empty (t);
2559
2560 return GNUNET_OK;
2561}
2562
2563
2564/**
2565 * Timeout function, destroys tunnel if called
2566 *
2567 * @param cls Closure (tunnel to destroy).
2568 * @param tc TaskContext
2569 */
2570static void
2571tunnel_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2572{
2573 struct MeshTunnel *t = cls;
2574 struct GNUNET_PeerIdentity id;
2575
2576 t->maintenance_task = GNUNET_SCHEDULER_NO_TASK;
2577 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
2578 return;
2579 GNUNET_PEER_resolve(t->id.oid, &id);
2580 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2581 "Tunnel %s [%X] timed out. Destroying.\n",
2582 GNUNET_i2s(&id), t->id.tid);
2583 if (NULL != t->client)
2584 send_client_tunnel_destroy (t->client, t);
2585 tunnel_destroy (t); /* Do not notify other */
2586}
2587
2588
2589/**
2590 * Resets the tunnel timeout. Starts it if no timeout was running.
2591 *
2592 * @param t Tunnel whose timeout to reset.
2593 *
2594 * TODO use heap to improve efficiency of scheduler.
2595 */
2596static void
2597tunnel_reset_timeout (struct MeshTunnel *t)
2598{
2599 if (NULL != t->owner || 0 != t->local_tid || 0 == t->prev_hop)
2600 return;
2601 if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task)
2602 GNUNET_SCHEDULER_cancel (t->maintenance_task);
2603 t->maintenance_task =
2604 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
2605 (refresh_path_time, 4), &tunnel_timeout, t);
2606}
2607
2608
2609/******************************************************************************/
2610/**************** MESH NETWORK HANDLER HELPERS ***********************/
2611/******************************************************************************/
2612
2613/**
2614 * Function to send a create path packet to a peer.
2615 *
2616 * @param cls closure
2617 * @param size number of bytes available in buf
2618 * @param buf where the callee should write the message
2619 * @return number of bytes written to buf
2620 */
2621static size_t
2622send_core_path_create (void *cls, size_t size, void *buf)
2623{
2624 struct MeshTunnel *t = cls;
2625 struct GNUNET_MESH_CreateTunnel *msg;
2626 struct GNUNET_PeerIdentity *peer_ptr;
2627 struct MeshPeerPath *p = t->path;
2628 size_t size_needed;
2629 uint32_t opt;
2630 int i;
2631
2632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATE PATH sending...\n");
2633 size_needed =
2634 sizeof (struct GNUNET_MESH_CreateTunnel) +
2635 p->length * sizeof (struct GNUNET_PeerIdentity);
2636
2637 if (size < size_needed || NULL == buf)
2638 {
2639 GNUNET_break (0);
2640 return 0;
2641 }
2642 msg = (struct GNUNET_MESH_CreateTunnel *) buf;
2643 msg->header.size = htons (size_needed);
2644 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
2645 msg->tid = ntohl (t->id.tid);
2646
2647 opt = 0;
2648 if (GNUNET_YES == t->nobuffer)
2649 opt |= MESH_TUNNEL_OPT_NOBUFFER;
2650 msg->opt = htonl (opt);
2651 msg->port = htonl (t->port);
2652
2653 peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
2654 for (i = 0; i < p->length; i++)
2655 {
2656 GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
2657 }
2658
2659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2660 "CREATE PATH (%u bytes long) sent!\n", size_needed);
2661 return size_needed;
2662}
2663
2664
2665/**
2666 * Creates a path ack message in buf and frees all unused resources.
2667 *
2668 * @param cls closure (MeshTransmissionDescriptor)
2669 * @param size number of bytes available in buf
2670 * @param buf where the callee should write the message
2671 * @return number of bytes written to buf
2672 */
2673static size_t
2674send_core_path_ack (void *cls, size_t size, void *buf)
2675{
2676 struct MeshTunnel *t = cls;
2677 struct GNUNET_MESH_PathACK *msg = buf;
2678
2679 GNUNET_assert (NULL != t);
2680 if (sizeof (struct GNUNET_MESH_PathACK) > size)
2681 {
2682 GNUNET_break (0);
2683 return 0;
2684 }
2685 t->prev_fc.last_ack_sent = t->nobuffer ? 0 : t->queue_max - 1;
2686 msg->header.size = htons (sizeof (struct GNUNET_MESH_PathACK));
2687 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
2688 GNUNET_PEER_resolve (t->id.oid, &msg->oid);
2689 msg->tid = htonl (t->id.tid);
2690 msg->peer_id = my_full_id;
2691 msg->ack = htonl (t->prev_fc.last_ack_sent);
2692
2693 /* TODO add signature */
2694
2695 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH ACK sent!\n");
2696 return sizeof (struct GNUNET_MESH_PathACK);
2697}
2698
2699
2700/**
2701 * Free a transmission that was already queued with all resources
2702 * associated to the request.
2703 *
2704 * @param queue Queue handler to cancel.
2705 * @param clear_cls Is it necessary to free associated cls?
2706 */
2707static void
2708queue_destroy (struct MeshPeerQueue *queue, int clear_cls)
2709{
2710 struct MeshFlowControl *fc;
2711
2712 if (GNUNET_YES == clear_cls)
2713 {
2714 switch (queue->type)
2715 {
2716 case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
2717 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " cancelling TUNNEL_DESTROY\n");
2718 GNUNET_break (GNUNET_YES == queue->tunnel->destroy);
2719 /* fall through */
2720 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
2721 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
2722 case GNUNET_MESSAGE_TYPE_MESH_ACK:
2723 case GNUNET_MESSAGE_TYPE_MESH_POLL:
2724 case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE:
2725 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2726 " prebuilt message\n");
2727 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2728 " type %s\n",
2729 GNUNET_MESH_DEBUG_M2S (queue->type));
2730 break;
2731 case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
2732 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " type create path\n");
2733 break;
2734 default:
2735 GNUNET_break (0);
2736 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2737 " type %s unknown!\n",
2738 GNUNET_MESH_DEBUG_M2S (queue->type));
2739 }
2740 GNUNET_free_non_null (queue->cls);
2741 }
2742 GNUNET_CONTAINER_DLL_remove (queue->peer->queue_head,
2743 queue->peer->queue_tail,
2744 queue);
2745
2746 /* Delete from appropriate fc in the tunnel */
2747 if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == queue->type ||
2748 GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == queue->type )
2749 {
2750 if (queue->peer->id == queue->tunnel->prev_hop)
2751 fc = &queue->tunnel->prev_fc;
2752 else if (queue->peer->id == queue->tunnel->next_hop)
2753 fc = &queue->tunnel->next_fc;
2754 else
2755 {
2756 GNUNET_break (0);
2757 return;
2758 }
2759 fc->queue_n--;
2760 }
2761 GNUNET_free (queue);
2762}
2763
2764
2765/**
2766 * @brief Get the next transmittable message from the queue.
2767 *
2768 * This will be the head, except in the case of being a data packet
2769 * not allowed by the destination peer.
2770 *
2771 * @param peer Destination peer.
2772 *
2773 * @return The next viable MeshPeerQueue element to send to that peer.
2774 * NULL when there are no transmittable messages.
2775 */
2776struct MeshPeerQueue *
2777queue_get_next (const struct MeshPeerInfo *peer)
2778{
2779 struct MeshPeerQueue *q;
2780
2781 struct GNUNET_MESH_Data *dmsg;
2782 struct MeshTunnel* t;
2783 uint32_t pid;
2784 uint32_t ack;
2785
2786 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* selecting message\n");
2787 for (q = peer->queue_head; NULL != q; q = q->next)
2788 {
2789 t = q->tunnel;
2790 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2791 "* %s\n",
2792 GNUNET_MESH_DEBUG_M2S (q->type));
2793 dmsg = (struct GNUNET_MESH_Data *) q->cls;
2794 pid = ntohl (dmsg->pid);
2795 switch (q->type)
2796 {
2797 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
2798 ack = t->next_fc.last_ack_recv;
2799 break;
2800 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
2801 ack = t->prev_fc.last_ack_recv;
2802 break;
2803 default:
2804 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2805 "* OK!\n");
2806 return q;
2807 }
2808 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2809 "* ACK: %u, PID: %u\n",
2810 ack, pid);
2811 if (GNUNET_NO == GMC_is_pid_bigger (pid, ack))
2812 {
2813 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2814 "* OK!\n");
2815 return q;
2816 }
2817 else
2818 {
2819 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2820 "* NEXT!\n");
2821 }
2822 }
2823 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2824 "* nothing found\n");
2825 return NULL;
2826}
2827
2828
2829static size_t
2830queue_send (void *cls, size_t size, void *buf)
2831{
2832 struct MeshPeerInfo *peer = cls;
2833 struct GNUNET_MessageHeader *msg;
2834 struct MeshPeerQueue *queue;
2835 struct MeshTunnel *t;
2836 struct GNUNET_PeerIdentity dst_id;
2837 struct MeshFlowControl *fc;
2838 size_t data_size;
2839 uint32_t pid;
2840 uint16_t type;
2841
2842 peer->core_transmit = NULL;
2843
2844 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Queue send\n");
2845 queue = queue_get_next (peer);
2846
2847 /* Queue has no internal mesh traffic nor sendable payload */
2848 if (NULL == queue)
2849 {
2850 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* not ready, return\n");
2851 if (NULL == peer->queue_head)
2852 GNUNET_break (0); /* Core tmt_rdy should've been canceled */
2853 return 0;
2854 }
2855 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* not empty\n");
2856
2857 GNUNET_PEER_resolve (peer->id, &dst_id);
2858 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2859 "* towards %s\n",
2860 GNUNET_i2s (&dst_id));
2861 /* Check if buffer size is enough for the message */
2862 if (queue->size > size)
2863 {
2864 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2865 "* not enough room, reissue\n");
2866 peer->core_transmit =
2867 GNUNET_CORE_notify_transmit_ready (core_handle,
2868 GNUNET_NO,
2869 0,
2870 GNUNET_TIME_UNIT_FOREVER_REL,
2871 &dst_id,
2872 queue->size,
2873 &queue_send,
2874 peer);
2875 return 0;
2876 }
2877 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* size ok\n");
2878
2879 t = queue->tunnel;
2880 GNUNET_assert (0 < t->pending_messages);
2881 t->pending_messages--;
2882 type = 0;
2883
2884 /* Fill buf */
2885 switch (queue->type)
2886 {
2887 case 0:
2888 case GNUNET_MESSAGE_TYPE_MESH_ACK:
2889 case GNUNET_MESSAGE_TYPE_MESH_POLL:
2890 case GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN:
2891 case GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY:
2892 case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
2893 case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE:
2894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2895 "* raw: %s\n",
2896 GNUNET_MESH_DEBUG_M2S (queue->type));
2897 /* Fall through */
2898 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
2899 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
2900 data_size = send_core_data_raw (queue->cls, size, buf);
2901 msg = (struct GNUNET_MessageHeader *) buf;
2902 type = ntohs (msg->type);
2903 break;
2904 case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
2905 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* path create\n");
2906 data_size = send_core_path_create (queue->cls, size, buf);
2907 break;
2908 case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
2909 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* path ack\n");
2910 data_size = send_core_path_ack (queue->cls, size, buf);
2911 break;
2912 default:
2913 GNUNET_break (0);
2914 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2915 "* type unknown: %u\n",
2916 queue->type);
2917 data_size = 0;
2918 }
2919
2920 /* Free queue, but cls was freed by send_core_* */
2921 queue_destroy (queue, GNUNET_NO);
2922
2923 /* Send ACK if needed, after accounting for sent ID in fc->queue_n */
2924 pid = ((struct GNUNET_MESH_Data *) buf)->pid;
2925 switch (type)
2926 {
2927 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
2928 t->next_fc.last_pid_sent = pid;
2929 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST);
2930 break;
2931 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
2932 t->prev_fc.last_pid_sent = pid;
2933 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
2934 break;
2935 default:
2936 break;
2937 }
2938
2939 if (GNUNET_YES == t->destroy && 0 == t->pending_messages)
2940 {
2941 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* destroying tunnel!\n");
2942 tunnel_destroy (t);
2943 }
2944
2945 /* If more data in queue, send next */
2946 queue = queue_get_next (peer);
2947 if (NULL != queue)
2948 {
2949 struct GNUNET_PeerIdentity id;
2950
2951 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* more data!\n");
2952 GNUNET_PEER_resolve (peer->id, &id);
2953 peer->core_transmit =
2954 GNUNET_CORE_notify_transmit_ready(core_handle,
2955 0,
2956 0,
2957 GNUNET_TIME_UNIT_FOREVER_REL,
2958 &id,
2959 queue->size,
2960 &queue_send,
2961 peer);
2962 }
2963 else if (NULL != peer->queue_head)
2964 {
2965 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2966 "* %s stalled\n",
2967 GNUNET_i2s (&my_full_id));
2968 if (peer->id == t->next_hop)
2969 fc = &t->next_fc;
2970 else if (peer->id == t->prev_hop)
2971 fc = &t->prev_fc;
2972 else
2973 {
2974 GNUNET_break (0);
2975 fc = NULL;
2976 }
2977 if (NULL != fc && GNUNET_SCHEDULER_NO_TASK == fc->poll_task)
2978 {
2979 fc->t = t;
2980 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
2981 &tunnel_poll, fc);
2982 }
2983 }
2984 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Return %d\n", data_size);
2985 return data_size;
2986}
2987
2988
2989/**
2990 * @brief Queue and pass message to core when possible.
2991 *
2992 * If type is payload (UNICAST, TO_ORIGIN) checks for queue status and
2993 * accounts for it. In case the queue is full, the message is dropped and
2994 * a break issued.
2995 *
2996 * Otherwise, message is treated as internal and allowed to go regardless of
2997 * queue status.
2998 *
2999 * @param cls Closure (@c type dependant). It will be used by queue_send to
3000 * build the message to be sent if not already prebuilt.
3001 * @param type Type of the message, 0 for a raw message.
3002 * @param size Size of the message.
3003 * @param dst Neighbor to send message to.
3004 * @param t Tunnel this message belongs to.
3005 */
3006static void
3007queue_add (void *cls, uint16_t type, size_t size,
3008 struct MeshPeerInfo *dst, struct MeshTunnel *t)
3009{
3010 struct MeshPeerQueue *queue;
3011 struct GNUNET_PeerIdentity id;
3012 unsigned int *n;
3013
3014 n = NULL;
3015 if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type)
3016 {
3017 n = &t->next_fc.queue_n;
3018 }
3019 else if (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == type)
3020 {
3021 n = &t->prev_fc.queue_n;
3022 }
3023 if (NULL != n)
3024 {
3025 if (*n >= t->queue_max)
3026 {
3027 GNUNET_break(0);
3028 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3029 "queue full: %u/%u\n",
3030 *n, t->queue_max);
3031 GNUNET_STATISTICS_update(stats,
3032 "# messages dropped (buffer full)",
3033 1, GNUNET_NO);
3034 return; /* Drop message */
3035 }
3036 (*n)++;
3037 }
3038 queue = GNUNET_malloc (sizeof (struct MeshPeerQueue));
3039 queue->cls = cls;
3040 queue->type = type;
3041 queue->size = size;
3042 queue->peer = dst;
3043 queue->tunnel = t;
3044 GNUNET_CONTAINER_DLL_insert_tail (dst->queue_head, dst->queue_tail, queue);
3045 if (NULL == dst->core_transmit)
3046 {
3047 GNUNET_PEER_resolve (dst->id, &id);
3048 dst->core_transmit =
3049 GNUNET_CORE_notify_transmit_ready (core_handle,
3050 0,
3051 0,
3052 GNUNET_TIME_UNIT_FOREVER_REL,
3053 &id,
3054 size,
3055 &queue_send,
3056 dst);
3057 }
3058 t->pending_messages++;
3059}
3060
3061
3062/******************************************************************************/
3063/******************** MESH NETWORK HANDLERS **************************/
3064/******************************************************************************/
3065
3066
3067/**
3068 * Core handler for path creation
3069 *
3070 * @param cls closure
3071 * @param message message
3072 * @param peer peer identity this notification is about
3073 *
3074 * @return GNUNET_OK to keep the connection open,
3075 * GNUNET_SYSERR to close it (signal serious error)
3076 */
3077static int
3078handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
3079 const struct GNUNET_MessageHeader *message)
3080{
3081 unsigned int own_pos;
3082 uint16_t size;
3083 uint16_t i;
3084 MESH_TunnelNumber tid;
3085 struct GNUNET_MESH_CreateTunnel *msg;
3086 struct GNUNET_PeerIdentity *pi;
3087 struct MeshPeerPath *path;
3088 struct MeshPeerInfo *dest_peer_info;
3089 struct MeshPeerInfo *orig_peer_info;
3090 struct MeshTunnel *t;
3091
3092 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3093 "Received a path create msg [%s]\n",
3094 GNUNET_i2s (&my_full_id));
3095 size = ntohs (message->size);
3096 if (size < sizeof (struct GNUNET_MESH_CreateTunnel))
3097 {
3098 GNUNET_break_op (0);
3099 return GNUNET_OK;
3100 }
3101
3102 size -= sizeof (struct GNUNET_MESH_CreateTunnel);
3103 if (size % sizeof (struct GNUNET_PeerIdentity))
3104 {
3105 GNUNET_break_op (0);
3106 return GNUNET_OK;
3107 }
3108 size /= sizeof (struct GNUNET_PeerIdentity);
3109 if (size < 1)
3110 {
3111 GNUNET_break_op (0);
3112 return GNUNET_OK;
3113 }
3114 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size);
3115 msg = (struct GNUNET_MESH_CreateTunnel *) message;
3116
3117 tid = ntohl (msg->tid);
3118 pi = (struct GNUNET_PeerIdentity *) &msg[1];
3119 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3120 " path is for tunnel %s[%X].\n", GNUNET_i2s (pi), tid);
3121 t = tunnel_get (pi, tid);
3122 if (NULL == t) /* might be a local tunnel */
3123 {
3124 uint32_t opt;
3125
3126 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating tunnel\n");
3127 t = tunnel_new (GNUNET_PEER_intern (pi), tid, NULL, 0);
3128 if (NULL == t)
3129 {
3130 GNUNET_break (0);
3131 return GNUNET_OK;
3132 }
3133 t->port = ntohl (msg->port);
3134 opt = ntohl (msg->opt);
3135 if (0 != (opt & MESH_TUNNEL_OPT_NOBUFFER))
3136 {
3137 t->nobuffer = GNUNET_YES;
3138 t->queue_max = 1;
3139 }
3140 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " nobuffer:%d\n", t->nobuffer);
3141
3142 tunnel_reset_timeout (t);
3143 }
3144 t->state = MESH_TUNNEL_WAITING;
3145 dest_peer_info =
3146 GNUNET_CONTAINER_multihashmap_get (peers, &pi[size - 1].hashPubKey);
3147 if (NULL == dest_peer_info)
3148 {
3149 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3150 " Creating PeerInfo for destination.\n");
3151 dest_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
3152 dest_peer_info->id = GNUNET_PEER_intern (&pi[size - 1]);
3153 GNUNET_CONTAINER_multihashmap_put (peers, &pi[size - 1].hashPubKey,
3154 dest_peer_info,
3155 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
3156 }
3157 orig_peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &pi->hashPubKey);
3158 if (NULL == orig_peer_info)
3159 {
3160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3161 " Creating PeerInfo for origin.\n");
3162 orig_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
3163 orig_peer_info->id = GNUNET_PEER_intern (pi);
3164 GNUNET_CONTAINER_multihashmap_put (peers, &pi->hashPubKey, orig_peer_info,
3165 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
3166 }
3167 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n");
3168 path = path_new (size);
3169 own_pos = 0;
3170 for (i = 0; i < size; i++)
3171 {
3172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... adding %s\n",
3173 GNUNET_i2s (&pi[i]));
3174 path->peers[i] = GNUNET_PEER_intern (&pi[i]);
3175 if (path->peers[i] == myid)
3176 own_pos = i;
3177 }
3178 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos);
3179 if (own_pos == 0 && path->peers[own_pos] != myid)
3180 {
3181 /* create path: self not found in path through self */
3182 GNUNET_break_op (0);
3183 path_destroy (path);
3184 tunnel_destroy (t);
3185 return GNUNET_OK;
3186 }
3187 path_add_to_peers (path, GNUNET_NO);
3188 tunnel_use_path (t, path);
3189
3190 peer_info_add_tunnel (dest_peer_info, t);
3191
3192 if (own_pos == size - 1)
3193 {
3194 struct MeshClient *c;
3195 struct GNUNET_HashCode hc;
3196
3197 /* Find target client */
3198 GMC_hash32 (t->port, &hc);
3199 c = GNUNET_CONTAINER_multihashmap_get (ports, &hc);
3200 if (NULL == c)
3201 {
3202 /* TODO send reject */
3203 return GNUNET_OK;
3204 }
3205
3206 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n");
3207 peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_YES);
3208
3209 /* Assign local tid */
3210 while (NULL != tunnel_get_incoming (next_local_tid))
3211 next_local_tid = (next_local_tid + 1) | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
3212 t->local_tid_dest = next_local_tid++;
3213 next_local_tid = next_local_tid | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
3214
3215 tunnel_add_client (t, c);
3216 send_client_tunnel_create (t);
3217 send_path_ack (t);
3218 }
3219 else
3220 {
3221 struct MeshPeerPath *path2;
3222
3223 t->next_hop = path->peers[own_pos + 1];
3224 GNUNET_PEER_change_rc(t->next_hop, 1);
3225
3226 /* It's for somebody else! Retransmit. */
3227 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n");
3228 path2 = path_duplicate (path);
3229 peer_info_add_path (dest_peer_info, path2, GNUNET_NO);
3230 peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_NO);
3231 send_create_path (t);
3232 }
3233 return GNUNET_OK;
3234}
3235
3236
3237
3238/**
3239 * Core handler for path ACKs
3240 *
3241 * @param cls closure
3242 * @param message message
3243 * @param peer peer identity this notification is about
3244 *
3245 * @return GNUNET_OK to keep the connection open,
3246 * GNUNET_SYSERR to close it (signal serious error)
3247 */
3248static int
3249handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
3250 const struct GNUNET_MessageHeader *message)
3251{
3252 struct GNUNET_MESH_PathACK *msg;
3253 struct MeshPeerInfo *peer_info;
3254 struct MeshPeerPath *p;
3255 struct MeshTunnel *t;
3256
3257 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a path ACK msg [%s]\n",
3258 GNUNET_i2s (&my_full_id));
3259 msg = (struct GNUNET_MESH_PathACK *) message;
3260 t = tunnel_get (&msg->oid, ntohl(msg->tid));
3261 if (NULL == t)
3262 {
3263 /* TODO notify that we don't know the tunnel */
3264 GNUNET_STATISTICS_update (stats, "# control on unknown tunnel", 1, GNUNET_NO);
3265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " don't know the tunnel %s [%X]!\n",
3266 GNUNET_i2s (&msg->oid), ntohl(msg->tid));
3267 return GNUNET_OK;
3268 }
3269 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %s [%X]\n",
3270 GNUNET_i2s (&msg->oid), ntohl(msg->tid));
3271
3272 peer_info = peer_get (&msg->peer_id);
3273 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by peer %s\n",
3274 GNUNET_i2s (&msg->peer_id));
3275 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n",
3276 GNUNET_i2s (peer));
3277
3278 /* Add path to peers? */
3279 p = t->path;
3280 if (NULL != p)
3281 {
3282 path_add_to_peers (p, GNUNET_YES);
3283 }
3284 else
3285 {
3286 GNUNET_break (0);
3287 }
3288 t->state = MESH_TUNNEL_READY;
3289 t->next_fc.last_ack_recv = (NULL == t->client) ? ntohl (msg->ack) : 0;
3290 t->prev_fc.last_ack_sent = ntohl (msg->ack);
3291
3292 /* Message for us? */
3293 if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct GNUNET_PeerIdentity)))
3294 {
3295 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n");
3296 if (NULL == t->owner)
3297 {
3298 GNUNET_break_op (0);
3299 return GNUNET_OK;
3300 }
3301 if (NULL != peer_info->dhtget)
3302 {
3303 GNUNET_DHT_get_stop (peer_info->dhtget);
3304 peer_info->dhtget = NULL;
3305 }
3306 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
3307 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
3308 return GNUNET_OK;
3309 }
3310
3311 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3312 " not for us, retransmitting...\n");
3313 peer_info = peer_get (&msg->oid);
3314 send_prebuilt_message (message, t->prev_hop, t);
3315 return GNUNET_OK;
3316}
3317
3318
3319/**
3320 * Core handler for notifications of broken paths
3321 *
3322 * @param cls closure
3323 * @param message message
3324 * @param peer peer identity this notification is about
3325 *
3326 * @return GNUNET_OK to keep the connection open,
3327 * GNUNET_SYSERR to close it (signal serious error)
3328 */
3329static int
3330handle_mesh_path_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
3331 const struct GNUNET_MessageHeader *message)
3332{
3333 struct GNUNET_MESH_PathBroken *msg;
3334 struct MeshTunnel *t;
3335
3336 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3337 "Received a PATH BROKEN msg from %s\n", GNUNET_i2s (peer));
3338 msg = (struct GNUNET_MESH_PathBroken *) message;
3339 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n",
3340 GNUNET_i2s (&msg->peer1));
3341 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n",
3342 GNUNET_i2s (&msg->peer2));
3343 t = tunnel_get (&msg->oid, ntohl (msg->tid));
3344 if (NULL == t)
3345 {
3346 GNUNET_break_op (0);
3347 return GNUNET_OK;
3348 }
3349 tunnel_notify_connection_broken (t, GNUNET_PEER_search (&msg->peer1),
3350 GNUNET_PEER_search (&msg->peer2));
3351 return GNUNET_OK;
3352
3353}
3354
3355
3356/**
3357 * Core handler for tunnel destruction
3358 *
3359 * @param cls closure
3360 * @param message message
3361 * @param peer peer identity this notification is about
3362 *
3363 * @return GNUNET_OK to keep the connection open,
3364 * GNUNET_SYSERR to close it (signal serious error)
3365 */
3366static int
3367handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
3368 const struct GNUNET_MessageHeader *message)
3369{
3370 struct GNUNET_MESH_TunnelDestroy *msg;
3371 struct MeshTunnel *t;
3372
3373 msg = (struct GNUNET_MESH_TunnelDestroy *) message;
3374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3375 "Got a TUNNEL DESTROY packet from %s\n",
3376 GNUNET_i2s (peer));
3377 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3378 " for tunnel %s [%u]\n",
3379 GNUNET_i2s (&msg->oid), ntohl (msg->tid));
3380 t = tunnel_get (&msg->oid, ntohl (msg->tid));
3381 if (NULL == t)
3382 {
3383 /* Probably already got the message from another path,
3384 * destroyed the tunnel and retransmitted to children.
3385 * Safe to ignore.
3386 */
3387 GNUNET_STATISTICS_update (stats, "# control on unknown tunnel",
3388 1, GNUNET_NO);
3389 return GNUNET_OK;
3390 }
3391 if (t->local_tid_dest >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
3392 {
3393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "INCOMING TUNNEL %X %X\n",
3394 t->local_tid, t->local_tid_dest);
3395 }
3396 if (GNUNET_PEER_search (peer) == t->prev_hop)
3397 {
3398 // TODO check owner's signature
3399 // TODO add owner's signatue to tunnel for retransmission
3400 peer_cancel_queues (t->prev_hop, t);
3401 GNUNET_PEER_change_rc (t->prev_hop, -1);
3402 t->prev_hop = 0;
3403 }
3404 else if (GNUNET_PEER_search (peer) == t->next_hop)
3405 {
3406 // TODO check dest's signature
3407 // TODO add dest's signatue to tunnel for retransmission
3408 peer_cancel_queues (t->next_hop, t);
3409 GNUNET_PEER_change_rc (t->next_hop, -1);
3410 t->next_hop = 0;
3411 }
3412 else
3413 {
3414 GNUNET_break_op (0);
3415 // TODO check both owner AND destination's signature to see which matches
3416 // TODO restransmit in appropriate direction
3417 return GNUNET_OK;
3418 }
3419 tunnel_destroy_empty (t);
3420
3421 // TODO: add timeout to destroy the tunnel anyway
3422 return GNUNET_OK;
3423}
3424
3425
3426/**
3427 * Core handler for mesh network traffic going from the origin to a peer
3428 *
3429 * @param cls closure
3430 * @param peer peer identity this notification is about
3431 * @param message message
3432 * @return GNUNET_OK to keep the connection open,
3433 * GNUNET_SYSERR to close it (signal serious error)
3434 */
3435static int
3436handle_mesh_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
3437 const struct GNUNET_MessageHeader *message)
3438{
3439 struct GNUNET_MESH_Data *msg;
3440 struct MeshTunnel *t;
3441 uint32_t pid;
3442 uint32_t ttl;
3443 size_t size;
3444
3445 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a unicast packet from %s\n",
3446 GNUNET_i2s (peer));
3447 /* Check size */
3448 size = ntohs (message->size);
3449 if (size <
3450 sizeof (struct GNUNET_MESH_Data) +
3451 sizeof (struct GNUNET_MessageHeader))
3452 {
3453 GNUNET_break (0);
3454 return GNUNET_OK;
3455 }
3456 msg = (struct GNUNET_MESH_Data *) message;
3457 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n",
3458 GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type)));
3459 /* Check tunnel */
3460 t = tunnel_get (&msg->oid, ntohl (msg->tid));
3461 if (NULL == t)
3462 {
3463 /* TODO notify back: we don't know this tunnel */
3464 GNUNET_STATISTICS_update (stats, "# data on unknown tunnel", 1, GNUNET_NO);
3465 GNUNET_break_op (0);
3466 return GNUNET_OK;
3467 }
3468 pid = ntohl (msg->pid);
3469 if (t->prev_fc.last_pid_recv == pid)
3470 {
3471 GNUNET_STATISTICS_update (stats, "# duplicate PID drops", 1, GNUNET_NO);
3472 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3473 " Already seen pid %u, DROPPING!\n", pid);
3474 return GNUNET_OK;
3475 }
3476 else
3477 {
3478 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3479 " pid %u not seen yet, forwarding\n", pid);
3480 }
3481
3482 if (GMC_is_pid_bigger (pid, t->prev_fc.last_ack_sent))
3483 {
3484 GNUNET_STATISTICS_update (stats, "# unsolicited unicast", 1, GNUNET_NO);
3485 GNUNET_break_op (0);
3486 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3487 "Received PID %u, ACK %u\n",
3488 pid, t->prev_fc.last_ack_sent);
3489 tunnel_send_fwd_ack(t, GNUNET_MESSAGE_TYPE_MESH_POLL);
3490 return GNUNET_OK;
3491 }
3492 t->prev_fc.last_pid_recv = pid;
3493
3494 tunnel_reset_timeout (t);
3495 if (t->dest == myid)
3496 {
3497 /* TODO signature verification */
3498 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3499 " it's for us! sending to clients...\n");
3500 GNUNET_STATISTICS_update (stats, "# unicast received", 1, GNUNET_NO);
3501 tunnel_send_client_ucast (t, msg);
3502 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST);
3503 return GNUNET_OK;
3504 }
3505 if (0 == t->next_hop)
3506 {
3507 GNUNET_break (0);
3508 return GNUNET_OK;
3509 }
3510 ttl = ntohl (msg->ttl);
3511 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl);
3512 if (ttl == 0)
3513 {
3514 GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
3515 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
3516 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
3517 return GNUNET_OK;
3518 }
3519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3520 " not for us, retransmitting...\n");
3521
3522 send_prebuilt_message (message, t->next_hop, t);
3523 GNUNET_STATISTICS_update (stats, "# unicast forwarded", 1, GNUNET_NO);
3524 return GNUNET_OK;
3525}
3526
3527
3528/**
3529 * Core handler for mesh network traffic toward the owner of a tunnel
3530 *
3531 * @param cls closure
3532 * @param message message
3533 * @param peer peer identity this notification is about
3534 *
3535 * @return GNUNET_OK to keep the connection open,
3536 * GNUNET_SYSERR to close it (signal serious error)
3537 */
3538static int
3539handle_mesh_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
3540 const struct GNUNET_MessageHeader *message)
3541{
3542 struct GNUNET_MESH_Data *msg;
3543 struct MeshTunnel *t;
3544 size_t size;
3545 uint32_t pid;
3546 uint32_t ttl;
3547
3548 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a ToOrigin packet from %s\n",
3549 GNUNET_i2s (peer));
3550 size = ntohs (message->size);
3551 if (size < sizeof (struct GNUNET_MESH_Data) + /* Payload must be */
3552 sizeof (struct GNUNET_MessageHeader)) /* at least a header */
3553 {
3554 GNUNET_break_op (0);
3555 return GNUNET_OK;
3556 }
3557 msg = (struct GNUNET_MESH_Data *) message;
3558 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n",
3559 GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type)));
3560 t = tunnel_get (&msg->oid, ntohl (msg->tid));
3561 pid = ntohl (msg->pid);
3562
3563 if (NULL == t)
3564 {
3565 /* TODO notify that we dont know this tunnel (whom)? */
3566 GNUNET_STATISTICS_update (stats, "# data on unknown tunnel", 1, GNUNET_NO);
3567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3568 "Received to_origin with PID %u on unknown tunnel %s [%u]\n",
3569 pid, GNUNET_i2s (&msg->oid), ntohl (msg->tid));
3570 return GNUNET_OK;
3571 }
3572
3573 if (t->next_fc.last_pid_recv == pid)
3574 {
3575 /* already seen this packet, drop */
3576 GNUNET_STATISTICS_update (stats, "# duplicate PID drops BCK", 1, GNUNET_NO);
3577 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3578 " Already seen pid %u, DROPPING!\n", pid);
3579 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
3580 return GNUNET_OK;
3581 }
3582
3583 if (GMC_is_pid_bigger (pid, t->next_fc.last_ack_sent))
3584 {
3585 GNUNET_STATISTICS_update (stats, "# unsolicited to_orig", 1, GNUNET_NO);
3586 GNUNET_break_op (0);
3587 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3588 "Received PID %u, ACK %u\n",
3589 pid, t->next_fc.last_ack_sent);
3590 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL);
3591 return GNUNET_OK;
3592 }
3593 t->next_fc.last_pid_recv = pid;
3594 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3595 " pid %u not seen yet, forwarding\n", pid);
3596
3597 if (myid == t->id.oid)
3598 {
3599 /* TODO signature verification */
3600 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3601 " it's for us! sending to clients...\n");
3602 GNUNET_STATISTICS_update (stats, "# to origin received", 1, GNUNET_NO);
3603 tunnel_send_client_to_orig (t, msg);
3604 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
3605 return GNUNET_OK;
3606 }
3607 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3608 " not for us, retransmitting...\n");
3609
3610 if (0 == t->prev_hop) /* No owner AND no prev hop */
3611 {
3612 if (GNUNET_YES == t->destroy)
3613 {
3614 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3615 "to orig received on a dying tunnel %s [%X]\n",
3616 GNUNET_i2s (&msg->oid), ntohl(msg->tid));
3617 return GNUNET_OK;
3618 }
3619 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3620 "unknown to origin at %s\n",
3621 GNUNET_i2s (&my_full_id));
3622 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3623 "from peer %s\n",
3624 GNUNET_i2s (peer));
3625 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3626 "on tunnel %s [%X]\n",
3627 GNUNET_i2s (&msg->oid), ntohl(msg->tid));
3628 return GNUNET_OK;
3629 }
3630 ttl = ntohl (msg->ttl);
3631 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl);
3632 if (ttl == 0)
3633 {
3634 GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
3635 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
3636 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
3637 return GNUNET_OK;
3638 }
3639 send_prebuilt_message (message, t->prev_hop, t);
3640 GNUNET_STATISTICS_update (stats, "# to origin forwarded", 1, GNUNET_NO);
3641
3642 return GNUNET_OK;
3643}
3644
3645
3646/**
3647 * Core handler for mesh network traffic point-to-point acks.
3648 *
3649 * @param cls closure
3650 * @param message message
3651 * @param peer peer identity this notification is about
3652 *
3653 * @return GNUNET_OK to keep the connection open,
3654 * GNUNET_SYSERR to close it (signal serious error)
3655 */
3656static int
3657handle_mesh_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
3658 const struct GNUNET_MessageHeader *message)
3659{
3660 struct GNUNET_MESH_ACK *msg;
3661 struct MeshTunnel *t;
3662 GNUNET_PEER_Id id;
3663 uint32_t ack;
3664
3665 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
3666 GNUNET_i2s (peer));
3667 msg = (struct GNUNET_MESH_ACK *) message;
3668
3669 t = tunnel_get (&msg->oid, ntohl (msg->tid));
3670
3671 if (NULL == t)
3672 {
3673 /* TODO notify that we dont know this tunnel (whom)? */
3674 GNUNET_STATISTICS_update (stats, "# ack on unknown tunnel", 1, GNUNET_NO);
3675 return GNUNET_OK;
3676 }
3677 ack = ntohl (msg->pid);
3678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
3679
3680 /* Is this a forward or backward ACK? */
3681 id = GNUNET_PEER_search (peer);
3682 if (t->next_hop == id)
3683 {
3684 debug_fwd_ack++;
3685 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n");
3686 if (GNUNET_SCHEDULER_NO_TASK != t->next_fc.poll_task &&
3687 GMC_is_pid_bigger (ack, t->next_fc.last_ack_recv))
3688 {
3689 GNUNET_SCHEDULER_cancel (t->next_fc.poll_task);
3690 t->next_fc.poll_task = GNUNET_SCHEDULER_NO_TASK;
3691 t->next_fc.poll_time = GNUNET_TIME_UNIT_SECONDS;
3692 }
3693 t->next_fc.last_ack_recv = ack;
3694 peer_unlock_queue (t->next_hop);
3695 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
3696 }
3697 else if (t->prev_hop == id)
3698 {
3699 debug_bck_ack++;
3700 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n");
3701 if (GNUNET_SCHEDULER_NO_TASK != t->prev_fc.poll_task &&
3702 GMC_is_pid_bigger (ack, t->prev_fc.last_ack_recv))
3703 {
3704 GNUNET_SCHEDULER_cancel (t->prev_fc.poll_task);
3705 t->prev_fc.poll_task = GNUNET_SCHEDULER_NO_TASK;
3706 t->prev_fc.poll_time = GNUNET_TIME_UNIT_SECONDS;
3707 }
3708 t->prev_fc.last_ack_recv = ack;
3709 peer_unlock_queue (t->prev_hop);
3710 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
3711 }
3712 else
3713 GNUNET_break_op (0);
3714 return GNUNET_OK;
3715}
3716
3717
3718/**
3719 * Core handler for mesh network traffic point-to-point ack polls.
3720 *
3721 * @param cls closure
3722 * @param message message
3723 * @param peer peer identity this notification is about
3724 *
3725 * @return GNUNET_OK to keep the connection open,
3726 * GNUNET_SYSERR to close it (signal serious error)
3727 */
3728static int
3729handle_mesh_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
3730 const struct GNUNET_MessageHeader *message)
3731{
3732 struct GNUNET_MESH_Poll *msg;
3733 struct MeshTunnel *t;
3734 GNUNET_PEER_Id id;
3735
3736 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an POLL packet from %s!\n",
3737 GNUNET_i2s (peer));
3738
3739 msg = (struct GNUNET_MESH_Poll *) message;
3740
3741 t = tunnel_get (&msg->oid, ntohl (msg->tid));
3742
3743 if (NULL == t)
3744 {
3745 /* TODO notify that we dont know this tunnel (whom)? */
3746 GNUNET_STATISTICS_update (stats, "# poll on unknown tunnel", 1, GNUNET_NO);
3747 GNUNET_break_op (0);
3748 return GNUNET_OK;
3749 }
3750
3751 /* Is this a forward or backward ACK? */
3752 id = GNUNET_PEER_search(peer);
3753 if (t->next_hop == id)
3754 {
3755 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " from FWD\n");
3756 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL);
3757 }
3758 else if (t->prev_hop == id)
3759 {
3760 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " from BCK\n");
3761 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL);
3762 }
3763 else
3764 GNUNET_break (0);
3765
3766 return GNUNET_OK;
3767}
3768
3769
3770/**
3771 * Core handler for mesh keepalives.
3772 *
3773 * @param cls closure
3774 * @param message message
3775 * @param peer peer identity this notification is about
3776 * @return GNUNET_OK to keep the connection open,
3777 * GNUNET_SYSERR to close it (signal serious error)
3778 *
3779 * TODO: Check who we got this from, to validate route.
3780 */
3781static int
3782handle_mesh_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
3783 const struct GNUNET_MessageHeader *message)
3784{
3785 struct GNUNET_MESH_TunnelKeepAlive *msg;
3786 struct MeshTunnel *t;
3787
3788 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
3789 GNUNET_i2s (peer));
3790
3791 msg = (struct GNUNET_MESH_TunnelKeepAlive *) message;
3792 t = tunnel_get (&msg->oid, ntohl (msg->tid));
3793
3794 if (NULL == t)
3795 {
3796 /* TODO notify that we dont know that tunnel */
3797 GNUNET_STATISTICS_update (stats, "# keepalive on unknown tunnel", 1,
3798 GNUNET_NO);
3799 return GNUNET_OK;
3800 }
3801
3802 tunnel_reset_timeout (t);
3803
3804 GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
3805 send_prebuilt_message (message, t->next_hop, t);
3806 return GNUNET_OK;
3807 }
3808
3809
3810
3811/**
3812 * Functions to handle messages from core
3813 */
3814static struct GNUNET_CORE_MessageHandler core_handlers[] = {
3815 {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
3816 {&handle_mesh_path_broken, GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN,
3817 sizeof (struct GNUNET_MESH_PathBroken)},
3818 {&handle_mesh_tunnel_destroy, GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY,
3819 sizeof (struct GNUNET_MESH_TunnelDestroy)},
3820 {&handle_mesh_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
3821 {&handle_mesh_keepalive, GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE,
3822 sizeof (struct GNUNET_MESH_TunnelKeepAlive)},
3823 {&handle_mesh_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
3824 {&handle_mesh_ack, GNUNET_MESSAGE_TYPE_MESH_ACK,
3825 sizeof (struct GNUNET_MESH_ACK)},
3826 {&handle_mesh_poll, GNUNET_MESSAGE_TYPE_MESH_POLL,
3827 sizeof (struct GNUNET_MESH_Poll)},
3828 {&handle_mesh_path_ack, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
3829 sizeof (struct GNUNET_MESH_PathACK)},
3830 {NULL, 0, 0}
3831};
3832
3833
3834
3835/******************************************************************************/
3836/**************** MESH LOCAL HANDLER HELPERS ***********************/
3837/******************************************************************************/
3838
3839
3840#if LATER
3841/**
3842 * notify_client_connection_failure: notify a client that the connection to the
3843 * requested remote peer is not possible (for instance, no route found)
3844 * Function called when the socket is ready to queue more data. "buf" will be
3845 * NULL and "size" zero if the socket was closed for writing in the meantime.
3846 *
3847 * @param cls closure
3848 * @param size number of bytes available in buf
3849 * @param buf where the callee should write the message
3850 * @return number of bytes written to buf
3851 */
3852static size_t
3853notify_client_connection_failure (void *cls, size_t size, void *buf)
3854{
3855 int size_needed;
3856 struct MeshPeerInfo *peer_info;
3857 struct GNUNET_MESH_PeerControl *msg;
3858 struct GNUNET_PeerIdentity id;
3859
3860 if (0 == size && NULL == buf)
3861 {
3862 // TODO retry? cancel?
3863 return 0;
3864 }
3865
3866 size_needed = sizeof (struct GNUNET_MESH_PeerControl);
3867 peer_info = (struct MeshPeerInfo *) cls;
3868 msg = (struct GNUNET_MESH_PeerControl *) buf;
3869 msg->header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
3870 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
3871// msg->tunnel_id = htonl(peer_info->t->tid);
3872 GNUNET_PEER_resolve (peer_info->id, &id);
3873 memcpy (&msg->peer, &id, sizeof (struct GNUNET_PeerIdentity));
3874
3875 return size_needed;
3876}
3877#endif
3878
3879
3880/**
3881 * Send keepalive packets for a tunnel.
3882 *
3883 * @param cls Closure (tunnel for which to send the keepalive).
3884 * @param tc Notification context.
3885 *
3886 * FIXME: add a refresh reset in case of normal unicast traffic is doing the job
3887 */
3888static void
3889path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3890{
3891 struct MeshTunnel *t = cls;
3892 struct GNUNET_MESH_TunnelKeepAlive *msg;
3893 size_t size = sizeof (struct GNUNET_MESH_TunnelKeepAlive);
3894 char cbuf[size];
3895
3896 t->maintenance_task = GNUNET_SCHEDULER_NO_TASK;
3897 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) ||
3898 NULL == t->owner || 0 == t->local_tid)
3899 {
3900 return;
3901 }
3902
3903 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3904 "sending keepalive for tunnel %d\n", t->id.tid);
3905
3906 msg = (struct GNUNET_MESH_TunnelKeepAlive *) cbuf;
3907 msg->header.size = htons (size);
3908 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE);
3909 msg->oid = my_full_id;
3910 msg->tid = htonl (t->id.tid);
3911 send_prebuilt_message (&msg->header, t->next_hop, t);
3912
3913 t->maintenance_task =
3914 GNUNET_SCHEDULER_add_delayed (refresh_path_time, &path_refresh, t);
3915}
3916
3917
3918/**
3919 * Function to process paths received for a new peer addition. The recorded
3920 * paths form the initial tunnel, which can be optimized later.
3921 * Called on each result obtained for the DHT search.
3922 *
3923 * @param cls closure
3924 * @param exp when will this value expire
3925 * @param key key of the result
3926 * @param get_path path of the get request
3927 * @param get_path_length lenght of get_path
3928 * @param put_path path of the put request
3929 * @param put_path_length length of the put_path
3930 * @param type type of the result
3931 * @param size number of bytes in data
3932 * @param data pointer to the result data
3933 */
3934static void
3935dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
3936 const struct GNUNET_HashCode * key,
3937 const struct GNUNET_PeerIdentity *get_path,
3938 unsigned int get_path_length,
3939 const struct GNUNET_PeerIdentity *put_path,
3940 unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
3941 size_t size, const void *data)
3942{
3943 struct MeshPeerInfo *peer = cls;
3944 struct MeshPeerPath *p;
3945 struct GNUNET_PeerIdentity pi;
3946 int i;
3947
3948 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got results from DHT!\n");
3949 GNUNET_PEER_resolve (peer->id, &pi);
3950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for %s\n", GNUNET_i2s (&pi));
3951
3952 p = path_build_from_dht (get_path, get_path_length,
3953 put_path, put_path_length);
3954 path_add_to_peers (p, GNUNET_NO);
3955 path_destroy (p);
3956 for (i = 0; i < peer->ntunnels; i++)
3957 {
3958 struct GNUNET_PeerIdentity id;
3959
3960 GNUNET_PEER_resolve (peer->tunnels[i]->id.oid, &id);
3961 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... tunnel %s:%X (%X / %X)\n",
3962 GNUNET_i2s (&id), peer->tunnels[i]->id.tid,
3963 peer->tunnels[i]->local_tid,
3964 peer->tunnels[i]->local_tid_dest);
3965 if (peer->tunnels[i]->state == MESH_TUNNEL_SEARCHING)
3966 {
3967 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
3968 peer_connect (peer, peer->tunnels[i]);
3969 }
3970 }
3971
3972 return;
3973}
3974
3975
3976/******************************************************************************/
3977/********************* MESH LOCAL HANDLES **************************/
3978/******************************************************************************/
3979
3980
3981/**
3982 * Handler for client disconnection
3983 *
3984 * @param cls closure
3985 * @param client identification of the client; NULL
3986 * for the last call when the server is destroyed
3987 */
3988static void
3989handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
3990{
3991 struct MeshClient *c;
3992 struct MeshClient *next;
3993
3994 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected: %p\n", client);
3995 if (client == NULL)
3996 {
3997 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (SERVER DOWN)\n");
3998 return;
3999 }
4000
4001 c = clients_head;
4002 while (NULL != c)
4003 {
4004 if (c->handle != client)
4005 {
4006 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4007 " ... searching %p (%u)\n",
4008 c->handle, c->id);
4009 c = c->next;
4010 continue;
4011 }
4012 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u)\n",
4013 c->id);
4014 GNUNET_SERVER_client_drop (c->handle);
4015 c->shutting_down = GNUNET_YES;
4016 GNUNET_CONTAINER_multihashmap_iterate (c->own_tunnels,
4017 &tunnel_destroy_iterator, c);
4018 GNUNET_CONTAINER_multihashmap_iterate (c->incoming_tunnels,
4019 &tunnel_destroy_iterator, c);
4020 GNUNET_CONTAINER_multihashmap_destroy (c->own_tunnels);
4021 GNUNET_CONTAINER_multihashmap_destroy (c->incoming_tunnels);
4022
4023 if (NULL != c->ports)
4024 GNUNET_CONTAINER_multihashmap_destroy (c->ports);
4025 next = c->next;
4026 GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
4027 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " CLIENT FREE at %p\n", c);
4028 GNUNET_free (c);
4029 GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO);
4030 c = next;
4031 }
4032 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done!\n");
4033 return;
4034}
4035
4036
4037/**
4038 * Handler for new clients
4039 *
4040 * @param cls closure
4041 * @param client identification of the client
4042 * @param message the actual message, which includes messages the client wants
4043 */
4044static void
4045handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client,
4046 const struct GNUNET_MessageHeader *message)
4047{
4048 struct GNUNET_MESH_ClientConnect *cc_msg;
4049 struct MeshClient *c;
4050 unsigned int size;
4051 uint32_t *p;
4052 unsigned int i;
4053
4054 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client);
4055
4056 /* Check data sanity */
4057 size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect);
4058 cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
4059 if (0 != (size % sizeof (uint32_t)))
4060 {
4061 GNUNET_break (0);
4062 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4063 return;
4064 }
4065 size /= sizeof (uint32_t);
4066
4067 /* Create new client structure */
4068 c = GNUNET_malloc (sizeof (struct MeshClient));
4069 c->id = next_client_id++; /* overflow not important: just for debug */
4070 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client id %u\n", c->id);
4071 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client has %u ports\n", size);
4072 c->handle = client;
4073 GNUNET_SERVER_client_keep (client);
4074 if (size > 0)
4075 {
4076 uint32_t u32;
4077 struct GNUNET_HashCode hc;
4078
4079 p = (uint32_t *) &cc_msg[1];
4080 c->ports = GNUNET_CONTAINER_multihashmap_create (size, GNUNET_NO);
4081 for (i = 0; i < size; i++)
4082 {
4083 u32 = ntohl (p[i]);
4084 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " port: %u\n", u32);
4085 GMC_hash32 (u32, &hc);
4086
4087 /* store in client's hashmap */
4088 GNUNET_CONTAINER_multihashmap_put (c->ports, &hc, c,
4089 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
4090 /* store in global hashmap */
4091 /* FIXME only allow one client to have the port open,
4092 * have a backup hashmap with waiting clients */
4093 GNUNET_CONTAINER_multihashmap_put (ports, &hc, c,
4094 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
4095 }
4096 }
4097
4098 GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
4099 c->own_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
4100 c->incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
4101 GNUNET_SERVER_notification_context_add (nc, client);
4102 GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO);
4103
4104 GNUNET_SERVER_receive_done (client, GNUNET_OK);
4105 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client processed\n");
4106}
4107
4108
4109/**
4110 * Handler for requests of new tunnels
4111 *
4112 * @param cls Closure.
4113 * @param client Identification of the client.
4114 * @param message The actual message.
4115 */
4116static void
4117handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
4118 const struct GNUNET_MessageHeader *message)
4119{
4120 struct GNUNET_MESH_TunnelMessage *t_msg;
4121 struct MeshPeerInfo *peer_info;
4122 struct MeshTunnel *t;
4123 struct MeshClient *c;
4124 MESH_TunnelNumber tid;
4125
4126 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new tunnel requested\n");
4127
4128 /* Sanity check for client registration */
4129 if (NULL == (c = client_get (client)))
4130 {
4131 GNUNET_break (0);
4132 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4133 return;
4134 }
4135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
4136
4137 /* Message size sanity check */
4138 if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
4139 {
4140 GNUNET_break (0);
4141 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4142 return;
4143 }
4144
4145 t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
4146 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " towards %s\n",
4147 GNUNET_i2s (&t_msg->peer));
4148 /* Sanity check for tunnel numbering */
4149 tid = ntohl (t_msg->tunnel_id);
4150 if (0 == (tid & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI))
4151 {
4152 GNUNET_break (0);
4153 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4154 return;
4155 }
4156 /* Sanity check for duplicate tunnel IDs */
4157 if (NULL != tunnel_get_by_local_id (c, tid))
4158 {
4159 GNUNET_break (0);
4160 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4161 return;
4162 }
4163
4164 /* Create tunnel */
4165 while (NULL != tunnel_get_by_pi (myid, next_tid))
4166 next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
4167 t = tunnel_new (myid, next_tid, c, tid);
4168 next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
4169 if (NULL == t)
4170 {
4171 GNUNET_break (0);
4172 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4173 return;
4174 }
4175 t->port = ntohl (t_msg->port);
4176 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATED TUNNEL %s[%x]:%u (%x)\n",
4177 GNUNET_i2s (&my_full_id), t->id.tid, t->port, t->local_tid);
4178
4179 peer_info = peer_get (&t_msg->peer);
4180 peer_info_add_tunnel (peer_info, t);
4181 peer_connect (peer_info, t);
4182 GNUNET_SERVER_receive_done (client, GNUNET_OK);
4183 return;
4184}
4185
4186
4187/**
4188 * Handler for requests of deleting tunnels
4189 *
4190 * @param cls closure
4191 * @param client identification of the client
4192 * @param message the actual message
4193 */
4194static void
4195handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
4196 const struct GNUNET_MessageHeader *message)
4197{
4198 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
4199 struct MeshClient *c;
4200 struct MeshTunnel *t;
4201 MESH_TunnelNumber tid;
4202
4203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4204 "Got a DESTROY TUNNEL from client!\n");
4205
4206 /* Sanity check for client registration */
4207 if (NULL == (c = client_get (client)))
4208 {
4209 GNUNET_break (0);
4210 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4211 return;
4212 }
4213 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
4214
4215 /* Message sanity check */
4216 if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
4217 {
4218 GNUNET_break (0);
4219 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4220 return;
4221 }
4222
4223 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
4224
4225 /* Retrieve tunnel */
4226 tid = ntohl (tunnel_msg->tunnel_id);
4227 t = tunnel_get_by_local_id(c, tid);
4228 if (NULL == t)
4229 {
4230 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " tunnel %X not found\n", tid);
4231 GNUNET_break (0);
4232 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4233 return;
4234 }
4235
4236 /* Cleanup after the tunnel */
4237 client_delete_tunnel (c, t);
4238 if (c == t->client)
4239 {
4240 t->client = NULL;
4241 }
4242 else if (c == t->owner)
4243 {
4244 peer_info_remove_tunnel (peer_get_short (t->dest), t);
4245 t->owner = NULL;
4246 }
4247
4248 /* The tunnel will be destroyed when the last message is transmitted. */
4249 tunnel_destroy_empty (t);
4250
4251 GNUNET_SERVER_receive_done (client, GNUNET_OK);
4252 return;
4253}
4254
4255
4256/**
4257 * Handler for requests of seeting tunnel's buffering policy.
4258 *
4259 * @param cls Closure (unused).
4260 * @param client Identification of the client.
4261 * @param message The actual message.
4262 */
4263static void
4264handle_local_tunnel_buffer (void *cls, struct GNUNET_SERVER_Client *client,
4265 const struct GNUNET_MessageHeader *message)
4266{
4267 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
4268 struct MeshClient *c;
4269 struct MeshTunnel *t;
4270 MESH_TunnelNumber tid;
4271
4272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4273 "Got a BUFFER request from client!\n");
4274
4275 /* Sanity check for client registration */
4276 if (NULL == (c = client_get (client)))
4277 {
4278 GNUNET_break (0);
4279 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4280 return;
4281 }
4282 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
4283
4284 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
4285
4286 /* Retrieve tunnel */
4287 tid = ntohl (tunnel_msg->tunnel_id);
4288 t = tunnel_get_by_local_id(c, tid);
4289 if (NULL == t)
4290 {
4291 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " tunnel %X not found\n", tid);
4292 GNUNET_break (0);
4293 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4294 return;
4295 }
4296
4297 switch (ntohs(message->type))
4298 {
4299 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER:
4300 t->nobuffer = GNUNET_NO;
4301 break;
4302 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER:
4303 t->nobuffer = GNUNET_YES;
4304 break;
4305 default:
4306 GNUNET_break (0);
4307 }
4308
4309 GNUNET_SERVER_receive_done (client, GNUNET_OK);
4310}
4311
4312
4313/**
4314 * Handler for client traffic directed to one peer
4315 *
4316 * @param cls closure
4317 * @param client identification of the client
4318 * @param message the actual message
4319 */
4320static void
4321handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client,
4322 const struct GNUNET_MessageHeader *message)
4323{
4324 struct MeshClient *c;
4325 struct MeshTunnel *t;
4326 struct GNUNET_MESH_Data *data_msg;
4327 MESH_TunnelNumber tid;
4328 size_t size;
4329
4330 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4331 "Got a unicast request from a client!\n");
4332
4333 /* Sanity check for client registration */
4334 if (NULL == (c = client_get (client)))
4335 {
4336 GNUNET_break (0);
4337 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4338 return;
4339 }
4340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
4341
4342 data_msg = (struct GNUNET_MESH_Data *) message;
4343
4344 /* Sanity check for message size */
4345 size = ntohs (message->size);
4346 if (sizeof (struct GNUNET_MESH_Data) +
4347 sizeof (struct GNUNET_MessageHeader) > size)
4348 {
4349 GNUNET_break (0);
4350 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4351 return;
4352 }
4353
4354 /* Tunnel exists? */
4355 tid = ntohl (data_msg->tid);
4356 t = tunnel_get_by_local_id (c, tid);
4357 if (NULL == t)
4358 {
4359 GNUNET_break (0);
4360 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4361 return;
4362 }
4363
4364 /* Is it a local tunnel? Then, does client own the tunnel? */
4365 if (t->owner->handle != client)
4366 {
4367 GNUNET_break (0);
4368 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4369 return;
4370 }
4371
4372 /* PID should be as expected: client<->service communication */
4373 if (ntohl (data_msg->pid) != t->prev_fc.last_pid_recv + 1)
4374 {
4375 GNUNET_break (0);
4376 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
4377 "Unicast PID, expected %u, got %u\n",
4378 t->prev_fc.last_pid_recv + 1, ntohl (data_msg->pid));
4379 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4380 return;
4381 }
4382
4383 /* Ok, everything is correct, send the message
4384 * (pretend we got it from a mesh peer)
4385 */
4386 {
4387 /* Work around const limitation */
4388 char buf[ntohs (message->size)] GNUNET_ALIGN;
4389 struct GNUNET_MESH_Data *copy;
4390
4391 copy = (struct GNUNET_MESH_Data *) buf;
4392 memcpy (buf, data_msg, size);
4393 copy->oid = my_full_id;
4394 copy->tid = htonl (t->id.tid);
4395 copy->ttl = htonl (default_ttl);
4396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4397 " calling generic handler...\n");
4398 handle_mesh_unicast (NULL, &my_full_id, &copy->header);
4399 }
4400 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n");
4401 GNUNET_SERVER_receive_done (client, GNUNET_OK);
4402
4403 return;
4404}
4405
4406
4407/**
4408 * Handler for client traffic directed to the origin
4409 *
4410 * @param cls closure
4411 * @param client identification of the client
4412 * @param message the actual message
4413 */
4414static void
4415handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client,
4416 const struct GNUNET_MessageHeader *message)
4417{
4418 struct GNUNET_MESH_Data *data_msg;
4419 struct MeshFlowControl *fc;
4420 struct MeshClient *c;
4421 struct MeshTunnel *t;
4422 MESH_TunnelNumber tid;
4423 size_t size;
4424
4425 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4426 "Got a ToOrigin request from a client!\n");
4427 /* Sanity check for client registration */
4428 if (NULL == (c = client_get (client)))
4429 {
4430 GNUNET_break (0);
4431 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4432 return;
4433 }
4434 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
4435
4436 data_msg = (struct GNUNET_MESH_Data *) message;
4437
4438 /* Sanity check for message size */
4439 size = ntohs (message->size);
4440 if (sizeof (struct GNUNET_MESH_Data) +
4441 sizeof (struct GNUNET_MessageHeader) > size)
4442 {
4443 GNUNET_break (0);
4444 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4445 return;
4446 }
4447
4448 /* Tunnel exists? */
4449 tid = ntohl (data_msg->tid);
4450 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", tid);
4451 if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
4452 {
4453 GNUNET_break (0);
4454 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4455 return;
4456 }
4457 t = tunnel_get_by_local_id (c, tid);
4458 if (NULL == t)
4459 {
4460 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tunnel %X unknown.\n", tid);
4461 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " for client %u.\n", c->id);
4462 GNUNET_break (0);
4463 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4464 return;
4465 }
4466
4467 /* It should be sent by someone who has this as incoming tunnel. */
4468 if (t->client != c)
4469 {
4470 GNUNET_break (0);
4471 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4472 return;
4473 }
4474
4475 /* PID should be as expected */
4476 fc = &t->next_fc;
4477 if (ntohl (data_msg->pid) != fc->last_pid_recv + 1)
4478 {
4479 GNUNET_break (0);
4480 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
4481 "To Origin PID, expected %u, got %u\n",
4482 fc->last_pid_recv + 1,
4483 ntohl (data_msg->pid));
4484 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4485 return;
4486 }
4487
4488 /* Ok, everything is correct, send the message
4489 * (pretend we got it from a mesh peer)
4490 */
4491 {
4492 char buf[ntohs (message->size)] GNUNET_ALIGN;
4493 struct GNUNET_MESH_Data *copy;
4494
4495 /* Work around 'const' limitation */
4496 memcpy (buf, data_msg, size);
4497 copy = (struct GNUNET_MESH_Data *) buf;
4498 GNUNET_PEER_resolve (t->id.oid, &copy->oid);
4499 copy->tid = htonl (t->id.tid);
4500 copy->ttl = htonl (default_ttl);
4501
4502 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4503 " calling generic handler...\n");
4504 handle_mesh_to_orig (NULL, &my_full_id, &copy->header);
4505 }
4506 GNUNET_SERVER_receive_done (client, GNUNET_OK);
4507
4508 return;
4509}
4510
4511
4512/**
4513 * Handler for client's ACKs for payload traffic.
4514 *
4515 * @param cls Closure (unused).
4516 * @param client Identification of the client.
4517 * @param message The actual message.
4518 */
4519static void
4520handle_local_ack (void *cls, struct GNUNET_SERVER_Client *client,
4521 const struct GNUNET_MessageHeader *message)
4522{
4523 struct GNUNET_MESH_LocalAck *msg;
4524 struct MeshTunnel *t;
4525 struct MeshClient *c;
4526 MESH_TunnelNumber tid;
4527 uint32_t ack;
4528
4529 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n");
4530 /* Sanity check for client registration */
4531 if (NULL == (c = client_get (client)))
4532 {
4533 GNUNET_break (0);
4534 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4535 return;
4536 }
4537 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
4538
4539 msg = (struct GNUNET_MESH_LocalAck *) message;
4540
4541 /* Tunnel exists? */
4542 tid = ntohl (msg->tunnel_id);
4543 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", tid);
4544 t = tunnel_get_by_local_id (c, tid);
4545 if (NULL == t)
4546 {
4547 GNUNET_break (0);
4548 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tunnel %X unknown.\n", tid);
4549 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " for client %u.\n", c->id);
4550 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4551 return;
4552 }
4553
4554 ack = ntohl (msg->ack);
4555 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ack);
4556
4557 /* Does client own tunnel? I.E: Is this an ACK for BCK traffic? */
4558 if (t->owner == c)
4559 {
4560 /* The client owns the tunnel, ACK is for data to_origin, send BCK ACK. */
4561 t->prev_fc.last_ack_recv = ack;
4562 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
4563 }
4564 else
4565 {
4566 /* The client doesn't own the tunnel, this ACK is for FWD traffic. */
4567 t->next_fc.last_ack_recv = ack;
4568 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
4569 }
4570
4571 GNUNET_SERVER_receive_done (client, GNUNET_OK);
4572
4573 return;
4574}
4575
4576
4577
4578/**
4579 * Iterator over all tunnels to send a monitoring client info about each tunnel.
4580 *
4581 * @param cls Closure (client handle).
4582 * @param key Key (hashed tunnel ID, unused).
4583 * @param value Tunnel info.
4584 *
4585 * @return GNUNET_YES, to keep iterating.
4586 */
4587static int
4588monitor_all_tunnels_iterator (void *cls,
4589 const struct GNUNET_HashCode * key,
4590 void *value)
4591{
4592 struct GNUNET_SERVER_Client *client = cls;
4593 struct MeshTunnel *t = value;
4594 struct GNUNET_MESH_LocalMonitor *msg;
4595
4596 msg = GNUNET_malloc (sizeof(struct GNUNET_MESH_LocalMonitor));
4597 GNUNET_PEER_resolve(t->id.oid, &msg->owner);
4598 msg->tunnel_id = htonl (t->id.tid);
4599 msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
4600 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
4601 GNUNET_PEER_resolve (t->dest, &msg->destination);
4602
4603 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4604 "* sending info about tunnel %s [%u]\n",
4605 GNUNET_i2s (&msg->owner), t->id.tid);
4606
4607 GNUNET_SERVER_notification_context_unicast (nc, client,
4608 &msg->header, GNUNET_NO);
4609 return GNUNET_YES;
4610}
4611
4612
4613/**
4614 * Handler for client's MONITOR request.
4615 *
4616 * @param cls Closure (unused).
4617 * @param client Identification of the client.
4618 * @param message The actual message.
4619 */
4620static void
4621handle_local_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client,
4622 const struct GNUNET_MessageHeader *message)
4623{
4624 struct MeshClient *c;
4625
4626 /* Sanity check for client registration */
4627 if (NULL == (c = client_get (client)))
4628 {
4629 GNUNET_break (0);
4630 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4631 return;
4632 }
4633
4634 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4635 "Received get tunnels request from client %u\n",
4636 c->id);
4637 GNUNET_CONTAINER_multihashmap_iterate (tunnels,
4638 monitor_all_tunnels_iterator,
4639 client);
4640 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4641 "Get tunnels request from client %u completed\n",
4642 c->id);
4643 GNUNET_SERVER_receive_done (client, GNUNET_OK);
4644}
4645
4646
4647/**
4648 * Handler for client's MONITOR_TUNNEL request.
4649 *
4650 * @param cls Closure (unused).
4651 * @param client Identification of the client.
4652 * @param message The actual message.
4653 */
4654static void
4655handle_local_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
4656 const struct GNUNET_MessageHeader *message)
4657{
4658 const struct GNUNET_MESH_LocalMonitor *msg;
4659 struct GNUNET_MESH_LocalMonitor *resp;
4660 struct MeshClient *c;
4661 struct MeshTunnel *t;
4662
4663 /* Sanity check for client registration */
4664 if (NULL == (c = client_get (client)))
4665 {
4666 GNUNET_break (0);
4667 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4668 return;
4669 }
4670
4671 msg = (struct GNUNET_MESH_LocalMonitor *) message;
4672 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4673 "Received tunnel info request from client %u for tunnel %s[%X]\n",
4674 c->id,
4675 &msg->owner,
4676 ntohl (msg->tunnel_id));
4677 t = tunnel_get (&msg->owner, ntohl (msg->tunnel_id));
4678 if (NULL == t)
4679 {
4680 /* We don't know the tunnel FIXME */
4681 struct GNUNET_MESH_LocalMonitor warn;
4682
4683 warn = *msg;
4684 GNUNET_SERVER_notification_context_unicast (nc, client,
4685 &warn.header,
4686 GNUNET_NO);
4687 GNUNET_SERVER_receive_done (client, GNUNET_OK);
4688 return;
4689 }
4690
4691 /* Initialize context */
4692 resp = GNUNET_malloc (sizeof (struct GNUNET_MESH_LocalMonitor));
4693 *resp = *msg;
4694 GNUNET_PEER_resolve (t->dest, &resp->destination);
4695 resp->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
4696 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
4697 &resp->header, GNUNET_NO);
4698 GNUNET_free (resp);
4699
4700 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4701 "Monitor tunnel request from client %u completed\n",
4702 c->id);
4703 GNUNET_SERVER_receive_done (client, GNUNET_OK);
4704}
4705
4706
4707/**
4708 * Functions to handle messages from clients
4709 */
4710static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
4711 {&handle_local_new_client, NULL,
4712 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
4713 {&handle_local_tunnel_create, NULL,
4714 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
4715 sizeof (struct GNUNET_MESH_TunnelMessage)},
4716 {&handle_local_tunnel_destroy, NULL,
4717 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
4718 sizeof (struct GNUNET_MESH_TunnelMessage)},
4719 {&handle_local_tunnel_buffer, NULL,
4720 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER,
4721 sizeof (struct GNUNET_MESH_TunnelMessage)},
4722 {&handle_local_tunnel_buffer, NULL,
4723 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER,
4724 sizeof (struct GNUNET_MESH_TunnelMessage)},
4725 {&handle_local_unicast, NULL,
4726 GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
4727 {&handle_local_to_origin, NULL,
4728 GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
4729 {&handle_local_ack, NULL,
4730 GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK,
4731 sizeof (struct GNUNET_MESH_LocalAck)},
4732 {&handle_local_get_tunnels, NULL,
4733 GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS,
4734 sizeof (struct GNUNET_MessageHeader)},
4735 {&handle_local_show_tunnel, NULL,
4736 GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL,
4737 sizeof (struct GNUNET_MESH_LocalMonitor)},
4738 {NULL, NULL, 0, 0}
4739};
4740
4741
4742/**
4743 * Method called whenever a given peer connects.
4744 *
4745 * @param cls closure
4746 * @param peer peer identity this notification is about
4747 */
4748static void
4749core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
4750{
4751 struct MeshPeerInfo *peer_info;
4752 struct MeshPeerPath *path;
4753
4754 DEBUG_CONN ("Peer connected\n");
4755 DEBUG_CONN (" %s\n", GNUNET_i2s (&my_full_id));
4756 peer_info = peer_get (peer);
4757 if (myid == peer_info->id)
4758 {
4759 DEBUG_CONN (" (self)\n");
4760 path = path_new (1);
4761 }
4762 else
4763 {
4764 DEBUG_CONN (" %s\n", GNUNET_i2s (peer));
4765 path = path_new (2);
4766 path->peers[1] = peer_info->id;
4767 GNUNET_PEER_change_rc (peer_info->id, 1);
4768 GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO);
4769 }
4770 path->peers[0] = myid;
4771 GNUNET_PEER_change_rc (myid, 1);
4772 peer_info_add_path (peer_info, path, GNUNET_YES);
4773 return;
4774}
4775
4776
4777/**
4778 * Method called whenever a peer disconnects.
4779 *
4780 * @param cls closure
4781 * @param peer peer identity this notification is about
4782 */
4783static void
4784core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
4785{
4786 struct MeshPeerInfo *pi;
4787 struct MeshPeerQueue *q;
4788 struct MeshPeerQueue *n;
4789
4790 DEBUG_CONN ("Peer disconnected\n");
4791 pi = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
4792 if (NULL == pi)
4793 {
4794 GNUNET_break (0);
4795 return;
4796 }
4797 q = pi->queue_head;
4798 while (NULL != q)
4799 {
4800 n = q->next;
4801 /* TODO try to reroute this traffic instead */
4802 queue_destroy(q, GNUNET_YES);
4803 q = n;
4804 }
4805 if (NULL != pi->core_transmit)
4806 {
4807 GNUNET_CORE_notify_transmit_ready_cancel(pi->core_transmit);
4808 pi->core_transmit = NULL;
4809 }
4810 peer_remove_path (pi, pi->id, myid);
4811 if (myid == pi->id)
4812 {
4813 DEBUG_CONN (" (self)\n");
4814 }
4815 GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO);
4816 return;
4817}
4818
4819
4820/**
4821 * Install server (service) handlers and start listening to clients.
4822 */
4823static void
4824server_init (void)
4825{
4826 GNUNET_SERVER_add_handlers (server_handle, client_handlers);
4827 GNUNET_SERVER_disconnect_notify (server_handle,
4828 &handle_local_client_disconnect, NULL);
4829 nc = GNUNET_SERVER_notification_context_create (server_handle, 1);
4830
4831 clients_head = NULL;
4832 clients_tail = NULL;
4833 next_client_id = 0;
4834 GNUNET_SERVER_resume (server_handle);
4835}
4836
4837
4838/**
4839 * To be called on core init/fail.
4840 *
4841 * @param cls Closure (config)
4842 * @param server handle to the server for this service
4843 * @param identity the public identity of this peer
4844 */
4845static void
4846core_init (void *cls, struct GNUNET_CORE_Handle *server,
4847 const struct GNUNET_PeerIdentity *identity)
4848{
4849 const struct GNUNET_CONFIGURATION_Handle *c = cls;
4850 static int i = 0;
4851
4852 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
4853 GNUNET_break (core_handle == server);
4854 if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)) ||
4855 NULL == server)
4856 {
4857 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
4858 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4859 " core id %s\n",
4860 GNUNET_i2s (identity));
4861 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4862 " my id %s\n",
4863 GNUNET_i2s (&my_full_id));
4864 GNUNET_CORE_disconnect (core_handle);
4865 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
4866 NULL, /* Closure passed to MESH functions */
4867 &core_init, /* Call core_init once connected */
4868 &core_connect, /* Handle connects */
4869 &core_disconnect, /* remove peers on disconnects */
4870 NULL, /* Don't notify about all incoming messages */
4871 GNUNET_NO, /* For header only in notification */
4872 NULL, /* Don't notify about all outbound messages */
4873 GNUNET_NO, /* For header-only out notification */
4874 core_handlers); /* Register these handlers */
4875 if (10 < i++)
4876 GNUNET_abort();
4877 }
4878 server_init ();
4879 return;
4880}
4881
4882
4883/******************************************************************************/
4884/************************ MAIN FUNCTIONS ****************************/
4885/******************************************************************************/
4886
4887/**
4888 * Iterator over tunnel hash map entries to destroy the tunnel during shutdown.
4889 *
4890 * @param cls closure
4891 * @param key current key code
4892 * @param value value in the hash map
4893 * @return GNUNET_YES if we should continue to iterate,
4894 * GNUNET_NO if not.
4895 */
4896static int
4897shutdown_tunnel (void *cls, const struct GNUNET_HashCode * key, void *value)
4898{
4899 struct MeshTunnel *t = value;
4900
4901 tunnel_destroy (t);
4902 return GNUNET_YES;
4903}
4904
4905/**
4906 * Iterator over peer hash map entries to destroy the tunnel during shutdown.
4907 *
4908 * @param cls closure
4909 * @param key current key code
4910 * @param value value in the hash map
4911 * @return GNUNET_YES if we should continue to iterate,
4912 * GNUNET_NO if not.
4913 */
4914static int
4915shutdown_peer (void *cls, const struct GNUNET_HashCode * key, void *value)
4916{
4917 struct MeshPeerInfo *p = value;
4918 struct MeshPeerQueue *q;
4919 struct MeshPeerQueue *n;
4920
4921 q = p->queue_head;
4922 while (NULL != q)
4923 {
4924 n = q->next;
4925 if (q->peer == p)
4926 {
4927 queue_destroy(q, GNUNET_YES);
4928 }
4929 q = n;
4930 }
4931 peer_info_destroy (p);
4932 return GNUNET_YES;
4933}
4934
4935
4936/**
4937 * Task run during shutdown.
4938 *
4939 * @param cls unused
4940 * @param tc unused
4941 */
4942static void
4943shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
4944{
4945 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n");
4946
4947 if (core_handle != NULL)
4948 {
4949 GNUNET_CORE_disconnect (core_handle);
4950 core_handle = NULL;
4951 }
4952 if (NULL != keygen)
4953 {
4954 GNUNET_CRYPTO_ecc_key_create_stop (keygen);
4955 keygen = NULL;
4956 }
4957 GNUNET_CONTAINER_multihashmap_iterate (tunnels, &shutdown_tunnel, NULL);
4958 GNUNET_CONTAINER_multihashmap_iterate (peers, &shutdown_peer, NULL);
4959 if (dht_handle != NULL)
4960 {
4961 GNUNET_DHT_disconnect (dht_handle);
4962 dht_handle = NULL;
4963 }
4964 if (nc != NULL)
4965 {
4966 GNUNET_SERVER_notification_context_destroy (nc);
4967 nc = NULL;
4968 }
4969 if (GNUNET_SCHEDULER_NO_TASK != announce_id_task)
4970 {
4971 GNUNET_SCHEDULER_cancel (announce_id_task);
4972 announce_id_task = GNUNET_SCHEDULER_NO_TASK;
4973 }
4974 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n");
4975}
4976
4977
4978/**
4979 * Callback for hostkey read/generation.
4980 *
4981 * @param cls Closure (Configuration handle).
4982 * @param pk The ECC private key.
4983 * @param emsg Error message, if any.
4984 */
4985static void
4986key_generation_cb (void *cls,
4987 struct GNUNET_CRYPTO_EccPrivateKey *pk,
4988 const char *emsg)
4989{
4990 const struct GNUNET_CONFIGURATION_Handle *c = cls;
4991
4992 keygen = NULL;
4993 if (NULL == pk)
4994 {
4995 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4996 _("Could not access hostkey: %s. Exiting.\n"),
4997 emsg);
4998 GNUNET_SCHEDULER_shutdown ();
4999 return;
5000 }
5001 my_private_key = pk;
5002 GNUNET_CRYPTO_ecc_key_get_public (my_private_key, &my_public_key);
5003 GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key),
5004 &my_full_id.hashPubKey);
5005 myid = GNUNET_PEER_intern (&my_full_id);
5006 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
5007 "Mesh for peer [%s] starting\n",
5008 GNUNET_i2s(&my_full_id));
5009
5010 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
5011 NULL, /* Closure passed to MESH functions */
5012 &core_init, /* Call core_init once connected */
5013 &core_connect, /* Handle connects */
5014 &core_disconnect, /* remove peers on disconnects */
5015 NULL, /* Don't notify about all incoming messages */
5016 GNUNET_NO, /* For header only in notification */
5017 NULL, /* Don't notify about all outbound messages */
5018 GNUNET_NO, /* For header-only out notification */
5019 core_handlers); /* Register these handlers */
5020 if (core_handle == NULL)
5021 {
5022 GNUNET_break (0);
5023 GNUNET_SCHEDULER_shutdown ();
5024 return;
5025 }
5026
5027 next_tid = 0;
5028 next_local_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
5029
5030 announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls);
5031
5032 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh service running\n");
5033}
5034
5035
5036/**
5037 * Process mesh requests.
5038 *
5039 * @param cls closure
5040 * @param server the initialized server
5041 * @param c configuration to use
5042 */
5043static void
5044run (void *cls, struct GNUNET_SERVER_Handle *server,
5045 const struct GNUNET_CONFIGURATION_Handle *c)
5046{
5047 char *keyfile;
5048
5049 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n");
5050 server_handle = server;
5051 GNUNET_SERVER_suspend (server_handle);
5052
5053 if (GNUNET_OK !=
5054 GNUNET_CONFIGURATION_get_value_filename (c, "PEER", "PRIVATE_KEY",
5055 &keyfile))
5056 {
5057 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5058 _
5059 ("%s service is lacking key configuration settings (%s). Exiting.\n"),
5060 "mesh", "peer/privatekey");
5061 GNUNET_SCHEDULER_shutdown ();
5062 return;
5063 }
5064
5065 if (GNUNET_OK !=
5066 GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_PATH_TIME",
5067 &refresh_path_time))
5068 {
5069 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5070 _
5071 ("%s service is lacking key configuration settings (%s). Exiting.\n"),
5072 "mesh", "refresh path time");
5073 GNUNET_SCHEDULER_shutdown ();
5074 return;
5075 }
5076
5077 if (GNUNET_OK !=
5078 GNUNET_CONFIGURATION_get_value_time (c, "MESH", "ID_ANNOUNCE_TIME",
5079 &id_announce_time))
5080 {
5081 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5082 _
5083 ("%s service is lacking key configuration settings (%s). Exiting.\n"),
5084 "mesh", "id announce time");
5085 GNUNET_SCHEDULER_shutdown ();
5086 return;
5087 }
5088
5089 if (GNUNET_OK !=
5090 GNUNET_CONFIGURATION_get_value_time (c, "MESH", "CONNECT_TIMEOUT",
5091 &connect_timeout))
5092 {
5093 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5094 _
5095 ("%s service is lacking key configuration settings (%s). Exiting.\n"),
5096 "mesh", "connect timeout");
5097 GNUNET_SCHEDULER_shutdown ();
5098 return;
5099 }
5100
5101 if (GNUNET_OK !=
5102 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE",
5103 &max_msgs_queue))
5104 {
5105 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5106 _
5107 ("%s service is lacking key configuration settings (%s). Exiting.\n"),
5108 "mesh", "max msgs queue");
5109 GNUNET_SCHEDULER_shutdown ();
5110 return;
5111 }
5112
5113 if (GNUNET_OK !=
5114 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_TUNNELS",
5115 &max_tunnels))
5116 {
5117 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5118 _
5119 ("%s service is lacking key configuration settings (%s). Exiting.\n"),
5120 "mesh", "max tunnels");
5121 GNUNET_SCHEDULER_shutdown ();
5122 return;
5123 }
5124
5125 if (GNUNET_OK !=
5126 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DEFAULT_TTL",
5127 &default_ttl))
5128 {
5129 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
5130 _
5131 ("%s service is lacking key configuration settings (%s). Using default (%u).\n"),
5132 "mesh", "default ttl", 64);
5133 default_ttl = 64;
5134 }
5135
5136 if (GNUNET_OK !=
5137 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_PEERS",
5138 &max_peers))
5139 {
5140 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
5141 _("%s service is lacking key configuration settings (%s). Using default (%u).\n"),
5142 "mesh", "max peers", 1000);
5143 max_peers = 1000;
5144 }
5145
5146 if (GNUNET_OK !=
5147 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DHT_REPLICATION_LEVEL",
5148 &dht_replication_level))
5149 {
5150 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
5151 _
5152 ("%s service is lacking key configuration settings (%s). Using default (%u).\n"),
5153 "mesh", "dht replication level", 3);
5154 dht_replication_level = 3;
5155 }
5156
5157 tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
5158 incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
5159 peers = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
5160 ports = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
5161
5162 dht_handle = GNUNET_DHT_connect (c, 64);
5163 if (NULL == dht_handle)
5164 {
5165 GNUNET_break (0);
5166 }
5167 stats = GNUNET_STATISTICS_create ("mesh", c);
5168
5169 /* Scheduled the task to clean up when shutdown is called */
5170 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
5171 NULL);
5172 keygen = GNUNET_CRYPTO_ecc_key_create_start (keyfile,
5173 &key_generation_cb,
5174 (void *) c);
5175 GNUNET_free (keyfile);
5176}
5177
5178
5179/**
5180 * The main function for the mesh service.
5181 *
5182 * @param argc number of arguments from the command line
5183 * @param argv command line arguments
5184 * @return 0 ok, 1 on error
5185 */
5186int
5187main (int argc, char *const *argv)
5188{
5189 int ret;
5190 int r;
5191
5192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main()\n");
5193 r = GNUNET_SERVICE_run (argc, argv, "mesh", GNUNET_SERVICE_OPTION_NONE, &run,
5194 NULL);
5195 ret = (GNUNET_OK == r) ? 0 : 1;
5196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main() END\n");
5197
5198 INTERVAL_SHOW;
5199
5200 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
5201 "Mesh for peer [%s] FWD ACKs %u, BCK ACKs %u\n",
5202 GNUNET_i2s(&my_full_id), debug_fwd_ack, debug_bck_ack);
5203
5204 return ret;
5205}
diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c
index 0ba69882f..622d399b4 100644
--- a/src/mesh/gnunet-service-mesh.c
+++ b/src/mesh/gnunet-service-mesh.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2001-2012 Christian Grothoff (and other contributing authors) 3 (C) 2001-2013 Christian Grothoff (and other contributing authors)
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
@@ -23,40 +23,25 @@
23 * @brief GNUnet MESH service 23 * @brief GNUnet MESH service
24 * @author Bartlomiej Polot 24 * @author Bartlomiej Polot
25 * 25 *
26 * STRUCTURE:
27 * - DATA STRUCTURES
28 * - GLOBAL VARIABLES
29 * - GENERAL HELPERS
30 * - PERIODIC FUNCTIONS
31 * - MESH NETWORK HANDLER HELPERS
32 * - MESH NETWORK HANDLES
33 * - MESH LOCAL HANDLER HELPERS
34 * - MESH LOCAL HANDLES
35 * - MAIN FUNCTIONS (main & run)
36 *
37 * TODO: 26 * TODO:
38 * - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message!
39 * - partial disconnect reporting -- same as error reporting?
40 * - add ping message
41 * - relay corking down to core 27 * - relay corking down to core
42 * - set ttl relative to tree depth 28 * - set ttl relative to path length
43 * - Add data ACK count in path ACK 29 * - add signatures
44 * - Make common GNUNET_MESH_Data header for unicast, to_orig, multicast 30 * - add encryption
31 * - keep queues until receiving ACK
45 * TODO END 32 * TODO END
46 */ 33 */
47 34
48#include "platform.h" 35#include "platform.h"
49#include "mesh.h" 36#include "mesh.h"
50#include "mesh_protocol.h" 37#include "mesh_protocol.h"
51#include "mesh_tunnel_tree.h" 38#include "mesh_path.h"
52#include "block_mesh.h" 39#include "block_mesh.h"
53#include "gnunet_dht_service.h" 40#include "gnunet_dht_service.h"
54#include "gnunet_statistics_service.h" 41#include "gnunet_statistics_service.h"
55#include "gnunet_regex_service.h"
56 42
57#define MESH_BLOOM_SIZE 128 43#define MESH_BLOOM_SIZE 128
58 44
59#define MESH_DEBUG_REGEX GNUNET_YES
60#define MESH_DEBUG_DHT GNUNET_NO 45#define MESH_DEBUG_DHT GNUNET_NO
61#define MESH_DEBUG_CONNECTION GNUNET_NO 46#define MESH_DEBUG_CONNECTION GNUNET_NO
62#define MESH_DEBUG_TIMING __LINUX__ && GNUNET_NO 47#define MESH_DEBUG_TIMING __LINUX__ && GNUNET_NO
@@ -65,7 +50,6 @@
65 GNUNET_TIME_UNIT_MINUTES,\ 50 GNUNET_TIME_UNIT_MINUTES,\
66 10) 51 10)
67 52
68
69#if MESH_DEBUG_CONNECTION 53#if MESH_DEBUG_CONNECTION
70#define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) 54#define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
71#else 55#else
@@ -78,12 +62,6 @@
78#define DEBUG_DHT(...) 62#define DEBUG_DHT(...)
79#endif 63#endif
80 64
81#if MESH_DEBUG_REGEX
82#define DEBUG_REGEX(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
83#else
84#define DEBUG_REGEX(...)
85#endif
86
87#if MESH_DEBUG_TIMING 65#if MESH_DEBUG_TIMING
88#include <time.h> 66#include <time.h>
89double __sum; 67double __sum;
@@ -118,28 +96,6 @@ struct MeshClient;
118 96
119 97
120/** 98/**
121 * Struct representing a piece of data being sent to other peers
122 */
123struct MeshData
124{
125 /** Tunnel it belongs to. */
126 struct MeshTunnel *t;
127
128 /** How many remaining neighbors still hav't got it. */
129 unsigned int reference_counter;
130
131 /** How many remaining neighbors we need to send this to. */
132 unsigned int total_out;
133
134 /** Size of the data. */
135 size_t data_len;
136
137 /** Data itself */
138 void *data;
139};
140
141
142/**
143 * Struct containing info about a queued transmission to this peer 99 * Struct containing info about a queued transmission to this peer
144 */ 100 */
145struct MeshPeerQueue 101struct MeshPeerQueue
@@ -182,99 +138,6 @@ struct MeshPeerQueue
182 138
183 139
184/** 140/**
185 * Struct to store regex information announced by clients.
186 */
187struct MeshRegexDescriptor
188{
189 /**
190 * Regular expression itself.
191 */
192 char *regex;
193
194 /**
195 * How many characters per edge can we squeeze?
196 */
197 uint16_t compression;
198
199 /**
200 * Handle to announce the regex.
201 */
202 struct GNUNET_REGEX_Announcement *h;
203};
204
205
206/**
207 * Struct to keep information of searches of services described by a regex
208 * using a user-provided string service description.
209 */
210struct MeshRegexSearchInfo
211{
212 /**
213 * Which tunnel is this for
214 */
215 struct MeshTunnel *t;
216
217 /**
218 * User provided description of the searched service.
219 */
220 char *description;
221
222 /**
223 * Regex search handle.
224 */
225 struct GNUNET_REGEX_Search *search_handle;
226
227 /**
228 * Peer that is connecting via connect_by_string. When connected, free ctx.
229 */
230 GNUNET_PEER_Id peer;
231
232 /**
233 * Other peers that are found but not yet being connected to.
234 */
235 GNUNET_PEER_Id *peers;
236
237 /**
238 * Number of elements in peers.
239 */
240 unsigned int n_peers;
241
242 /**
243 * Next peer to try to connect to.
244 */
245 unsigned int i_peer;
246
247 /**
248 * Timeout for a connect attempt.
249 * When reached, try to connect to a different peer, if any. If not,
250 * try the same peer again.
251 */
252 GNUNET_SCHEDULER_TaskIdentifier timeout;
253
254};
255
256
257/**
258 * Struct containing all info possibly needed to build a package when called
259 * back by core.
260 */
261struct MeshTransmissionDescriptor
262{
263 /** ID of the tunnel this packet travels in */
264 struct MESH_TunnelID *origin;
265
266 /** Who was this message being sent to */
267 struct MeshPeerInfo *peer;
268
269 /** Ultimate destination of the packet */
270 GNUNET_PEER_Id destination;
271
272 /** Data descriptor */
273 struct MeshData* mesh_data;
274};
275
276
277/**
278 * Struct containing all information regarding a given peer 141 * Struct containing all information regarding a given peer
279 */ 142 */
280struct MeshPeerInfo 143struct MeshPeerInfo
@@ -290,11 +153,6 @@ struct MeshPeerInfo
290 struct GNUNET_TIME_Absolute last_contact; 153 struct GNUNET_TIME_Absolute last_contact;
291 154
292 /** 155 /**
293 * Task handler for delayed connect task;
294 */
295 GNUNET_SCHEDULER_TaskIdentifier connect_task;
296
297 /**
298 * Number of attempts to reconnect so far 156 * Number of attempts to reconnect so far
299 */ 157 */
300 int n_reconnect_attempts; 158 int n_reconnect_attempts;
@@ -315,13 +173,8 @@ struct MeshPeerInfo
315 struct GNUNET_DHT_GetHandle *dhtget; 173 struct GNUNET_DHT_GetHandle *dhtget;
316 174
317 /** 175 /**
318 * Closure given to the DHT GET 176 * Array of tunnels this peer is the target of.
319 */ 177 * Most probably a small amount, therefore not a hashmap.
320 struct MeshPathInfo *dhtgetcls;
321
322 /**
323 * Array of tunnels this peer participates in
324 * (most probably a small amount, therefore not a hashmap)
325 * When the path to the peer changes, notify these tunnels to let them 178 * When the path to the peer changes, notify these tunnels to let them
326 * re-adjust their path trees. 179 * re-adjust their path trees.
327 */ 180 */
@@ -348,13 +201,66 @@ struct MeshPeerInfo
348 unsigned int queue_n; 201 unsigned int queue_n;
349 202
350 /** 203 /**
351 * Handle to for queued transmissions 204 * Handle for queued transmissions
352 */ 205 */
353 struct GNUNET_CORE_TransmitHandle *core_transmit; 206 struct GNUNET_CORE_TransmitHandle *core_transmit;
354}; 207};
355 208
356 209
357/** 210/**
211 * Struct to encapsulate all the Flow Control information to a peer in the
212 * context of a tunnel: Same peer in different tunnels will have independent
213 * flow control structures, allowing to choke/free tunnels according to its
214 * own criteria.
215 */
216struct MeshFlowControl
217{
218 /**
219 * ID of the last packet sent towards the peer.
220 */
221 uint32_t last_pid_sent;
222
223 /**
224 * ID of the last packet received from the peer.
225 */
226 uint32_t last_pid_recv;
227
228 /**
229 * Last ACK sent to the peer (peer can't send more than this PID).
230 */
231 uint32_t last_ack_sent;
232
233 /**
234 * Last ACK sent towards the origin (for traffic towards leaf node).
235 */
236 uint32_t last_ack_recv;
237
238 /**
239 * How many payload messages are in the queue towards this peer.
240 */
241 uint32_t queue_n;
242
243 /**
244 * Task to poll the peer in case of a lost ACK causes stall.
245 */
246 GNUNET_SCHEDULER_TaskIdentifier poll_task;
247
248 /**
249 * How frequently to poll for ACKs.
250 */
251 struct GNUNET_TIME_Relative poll_time;
252
253 /**
254 * On which tunnel to poll.
255 * Using an explicit poll_ctx would not help memory wise,
256 * since the allocated context would have to be stored in the
257 * fc struct in order to free it upon cancelling poll_task.
258 */
259 struct MeshTunnel *t;
260};
261
262
263/**
358 * Globally unique tunnel identification (owner + number) 264 * Globally unique tunnel identification (owner + number)
359 * DO NOT USE OVER THE NETWORK 265 * DO NOT USE OVER THE NETWORK
360 */ 266 */
@@ -388,6 +294,16 @@ struct MeshTunnel
388 struct MESH_TunnelID id; 294 struct MESH_TunnelID id;
389 295
390 /** 296 /**
297 * Port of the tunnel.
298 */
299 uint32_t port;
300
301 /**
302 * State of the tunnel.
303 */
304 enum MeshTunnelState state;
305
306 /**
391 * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI or 0 ) 307 * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI or 0 )
392 */ 308 */
393 MESH_TunnelNumber local_tid; 309 MESH_TunnelNumber local_tid;
@@ -400,77 +316,19 @@ struct MeshTunnel
400 MESH_TunnelNumber local_tid_dest; 316 MESH_TunnelNumber local_tid_dest;
401 317
402 /** 318 /**
403 * Is the speed on the tunnel limited to the slowest peer?
404 */
405 int speed_min;
406
407 /**
408 * Is the tunnel bufferless (minimum latency)? 319 * Is the tunnel bufferless (minimum latency)?
409 */ 320 */
410 int nobuffer; 321 int nobuffer;
411 322
412 /** 323 /**
413 * Packet ID of the last fwd packet seen (sent/retransmitted/received).
414 */
415 uint32_t fwd_pid;
416
417 /**
418 * Packet ID of the last bck packet sent (unique counter per hop).
419 */
420 uint32_t bck_pid;
421
422 /**
423 * SKIP value for this tunnel.
424 */
425 uint32_t skip;
426
427 /**
428 * Force sending ACK? Flag to allow duplicate ACK on POLL. 324 * Force sending ACK? Flag to allow duplicate ACK on POLL.
429 */ 325 */
430 int force_ack; 326 int force_ack;
431 327
432 /** 328 /**
433 * MeshTunnelChildInfo of all children, indexed by GNUNET_PEER_Id.
434 * Contains the Flow Control info: FWD ACK value received,
435 * last BCK ACK sent, PID and SKIP values.
436 */
437 struct GNUNET_CONTAINER_MultiHashMap *children_fc;
438
439 /**
440 * Last ACK sent towards the origin (for traffic towards leaf node).
441 */
442 uint32_t last_fwd_ack;
443
444 /**
445 * BCK ACK value received from the hop towards the owner of the tunnel,
446 * (previous node / owner): up to what message PID can we sent back to him.
447 */
448 uint32_t bck_ack;
449
450 /**
451 * How many messages are in the forward queue (towards leaves).
452 */
453 unsigned int fwd_queue_n;
454
455 /**
456 * How many messages do we accept in the forward queue. 329 * How many messages do we accept in the forward queue.
457 */ 330 */
458 unsigned int fwd_queue_max; 331 unsigned int queue_max;
459
460 /**
461 * How many messages are in the backward queue (towards origin).
462 */
463 unsigned int bck_queue_n;
464
465 /**
466 * How many messages do we accept in the backward queue.
467 */
468 unsigned int bck_queue_max;
469
470 /**
471 * Task to poll peer in case of a stall.
472 */
473 GNUNET_SCHEDULER_TaskIdentifier fc_poll_bck;
474 332
475 /** 333 /**
476 * Last time the tunnel was used 334 * Last time the tunnel was used
@@ -478,93 +336,50 @@ struct MeshTunnel
478 struct GNUNET_TIME_Absolute timestamp; 336 struct GNUNET_TIME_Absolute timestamp;
479 337
480 /** 338 /**
481 * Peers in the tunnel, indexed by PeerIdentity -> (MeshPeerInfo) 339 * Destination of the tunnel.
482 * containing peers added by id or by type, not intermediate peers.
483 */
484 struct GNUNET_CONTAINER_MultiHashMap *peers;
485
486 /**
487 * Number of peers that are connected and potentially ready to receive data
488 */
489 unsigned int peers_ready;
490
491 /**
492 * Client owner of the tunnel, if any
493 */
494 struct MeshClient *owner;
495
496 /**
497 * Clients that have been informed about and want to stay in the tunnel.
498 */
499 struct MeshClient **clients;
500
501 /**
502 * Flow control info for each client.
503 */ 340 */
504 struct MeshTunnelClientInfo *clients_fc; 341 GNUNET_PEER_Id dest;
505
506 /**
507 * Number of elements in clients/clients_fc
508 */
509 unsigned int nclients;
510
511 /**
512 * Clients that have been informed but requested to leave the tunnel.
513 */
514 struct MeshClient **ignore;
515 342
516 /** 343 /**
517 * Number of elements in clients 344 * Next hop in the tunnel. If 0, @c client must be set.
518 */ 345 */
519 unsigned int nignore; 346 GNUNET_PEER_Id next_hop;
520 347
521 /** 348 /**
522 * Blacklisted peers 349 * Previous hop in the tunnel. If 0, @c owner must be set.
523 */ 350 */
524 GNUNET_PEER_Id *blacklisted; 351 GNUNET_PEER_Id prev_hop;
525 352
526 /** 353 /**
527 * Number of elements in blacklisted 354 * Flow control information about @c next_hop or @c client.
528 */ 355 */
529 unsigned int nblacklisted; 356 struct MeshFlowControl next_fc;
530 357
531 /** 358 /**
532 * Bloomfilter (for peer identities) to stop circular routes 359 * Flow control information about @c prev_hop or @c owner.
533 */ 360 */
534 char bloomfilter[MESH_BLOOM_SIZE]; 361 struct MeshFlowControl prev_fc;
535
536 /**
537 * Tunnel paths
538 */
539 struct MeshTunnelTree *tree;
540
541 /**
542 * Application type we are looking for in this tunnel
543 */
544 GNUNET_MESH_ApplicationType type;
545 362
546 /** 363 /**
547 * Used to search peers offering a service 364 * Client owner of the tunnel, if any
548 */ 365 */
549 struct GNUNET_DHT_GetHandle *dht_get_type; 366 struct MeshClient *owner;
550 367
551 /** 368 /**
552 * Handle for the regex search for a connect_by_string 369 * Client destination of the tunnel, if any.
553 */ 370 */
554 struct MeshRegexSearchInfo *regex_search; 371 struct MeshClient *client;
555 372
556 /** 373 /**
557 * Task to keep the used paths alive 374 * Task to keep the used paths alive at the owner,
375 * time tunnel out on all the other peers.
558 */ 376 */
559 GNUNET_SCHEDULER_TaskIdentifier path_refresh_task; 377 GNUNET_SCHEDULER_TaskIdentifier maintenance_task;
560 378
561 /** 379 /**
562 * Task to destroy the tunnel after timeout 380 * Path being used for the tunnel.
563 *
564 * FIXME: merge the two? a tunnel will have either
565 * a path refresh OR a timeout, never both!
566 */ 381 */
567 GNUNET_SCHEDULER_TaskIdentifier timeout_task; 382 struct MeshPeerPath *path;
568 383
569 /** 384 /**
570 * Flag to signal the destruction of the tunnel. 385 * Flag to signal the destruction of the tunnel.
@@ -577,163 +392,13 @@ struct MeshTunnel
577 * Total messages pending for this tunnels, payload or not. 392 * Total messages pending for this tunnels, payload or not.
578 */ 393 */
579 unsigned int pending_messages; 394 unsigned int pending_messages;
580
581 /**
582 * If the tunnel is empty, destoy it.
583 */
584 GNUNET_SCHEDULER_TaskIdentifier delayed_destroy;
585};
586
587
588/**
589 * Info about a child node in a tunnel, needed to perform flow control.
590 */
591struct MeshTunnelChildInfo
592{
593 /**
594 * ID of the child node.
595 */
596 GNUNET_PEER_Id id;
597
598 /**
599 * SKIP value.
600 */
601 uint32_t skip;
602
603 /**
604 * Last sent PID.
605 */
606 uint32_t fwd_pid;
607
608 /**
609 * Last received PID.
610 */
611 uint32_t bck_pid;
612
613 /**
614 * Maximum PID allowed (FWD ACK received).
615 */
616 uint32_t fwd_ack;
617
618 /**
619 * Last ACK sent to that child (BCK ACK).
620 */
621 uint32_t bck_ack;
622
623 /**
624 * Circular buffer pointing to MeshPeerQueue elements for all
625 * payload traffic going to this child.
626 * Size determined by the tunnel queue size (@c t->fwd_queue_max).
627 */
628 struct MeshPeerQueue **send_buffer;
629
630 /**
631 * Index of the oldest element in the send_buffer.
632 */
633 unsigned int send_buffer_start;
634
635 /**
636 * How many elements are already in the buffer.
637 */
638 unsigned int send_buffer_n;
639
640 /**
641 * Tunnel this info is about
642 */
643 struct MeshTunnel *t;
644
645 /**
646 * Task to poll peer in case of a stall.
647 */
648 GNUNET_SCHEDULER_TaskIdentifier fc_poll;
649
650 /**
651 * Time to use for next polling call.
652 */
653 struct GNUNET_TIME_Relative fc_poll_time;
654};
655
656
657/**
658 * Info about a leaf client of a tunnel, needed to perform flow control.
659 */
660struct MeshTunnelClientInfo
661{
662 /**
663 * PID of the last packet sent to the client (FWD).
664 */
665 uint32_t fwd_pid;
666
667 /**
668 * PID of the last packet received from the client (BCK).
669 */
670 uint32_t bck_pid;
671
672 /**
673 * Maximum PID allowed (FWD ACK received).
674 */
675 uint32_t fwd_ack;
676
677 /**
678 * Last ACK sent to that child (BCK ACK).
679 */
680 uint32_t bck_ack;
681};
682
683
684
685/**
686 * Info collected during iteration of child nodes in order to get the ACK value
687 * for a tunnel.
688 */
689struct MeshTunnelChildIteratorContext
690{
691 /**
692 * Tunnel whose info is being collected.
693 */
694 struct MeshTunnel *t;
695
696 /**
697 * Is this context initialized? Is the value in max_child_ack valid?
698 */
699 int init;
700
701 /**
702 * Maximum child ACK so far.
703 */
704 uint32_t max_child_ack;
705
706 /**
707 * Number of children nodes
708 */
709 unsigned int nchildren;
710};
711
712
713/**
714 * Info needed to work with tunnel paths and peers
715 */
716struct MeshPathInfo
717{
718 /**
719 * Tunnel
720 */
721 struct MeshTunnel *t;
722
723 /**
724 * Neighbouring peer to whom we send the packet to
725 */
726 struct MeshPeerInfo *peer;
727
728 /**
729 * Path itself
730 */
731 struct MeshPeerPath *path;
732}; 395};
733 396
734 397
735/** 398/**
736 * Struct containing information about a client of the service 399 * Struct containing information about a client of the service
400 *
401 * TODO: add a list of 'waiting' ports
737 */ 402 */
738struct MeshClient 403struct MeshClient
739{ 404{
@@ -757,24 +422,16 @@ struct MeshClient
757 */ 422 */
758 struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels; 423 struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels;
759 424
760 /**
761 * Tunnels this client has rejected, indexed by incoming local id
762 */
763 struct GNUNET_CONTAINER_MultiHashMap *ignore_tunnels;
764 /** 425 /**
765 * Handle to communicate with the client 426 * Handle to communicate with the client
766 */ 427 */
767 struct GNUNET_SERVER_Client *handle; 428 struct GNUNET_SERVER_Client *handle;
768 429
769 /** 430 /**
770 * Applications that this client has claimed to provide: H(app) = app. 431 * Ports that this client has declared interest in.
771 */ 432 * Indexed by a GMC_hash32 (type), contains *Client.
772 struct GNUNET_CONTAINER_MultiHashMap *apps;
773
774 /**
775 * Messages that this client has declared interest in
776 */ 433 */
777 struct GNUNET_CONTAINER_MultiHashMap *types; 434 struct GNUNET_CONTAINER_MultiHashMap *ports;
778 435
779 /** 436 /**
780 * Whether the client is active or shutting down (don't send confirmations 437 * Whether the client is active or shutting down (don't send confirmations
@@ -786,26 +443,6 @@ struct MeshClient
786 * ID of the client, mainly for debug messages 443 * ID of the client, mainly for debug messages
787 */ 444 */
788 unsigned int id; 445 unsigned int id;
789
790 /**
791 * Regular expressions describing the services offered by this client.
792 */
793 struct MeshRegexDescriptor *regexes; // FIXME regex add timeout? API to remove a regex?
794
795 /**
796 * Number of regular expressions in regexes.
797 */
798 unsigned int n_regex;
799
800 /**
801 * Task to refresh all regular expresions in the DHT.
802 */
803 GNUNET_SCHEDULER_TaskIdentifier regex_announce_task;
804
805 /**
806 * Tmp store for partially retrieved regex.
807 */
808 char *partial_regex;
809 446
810}; 447};
811 448
@@ -835,6 +472,7 @@ mesh_debug (void *cls, int success)
835} 472}
836#endif 473#endif
837 474
475/* FIXME */
838unsigned int debug_fwd_ack; 476unsigned int debug_fwd_ack;
839unsigned int debug_bck_ack; 477unsigned int debug_bck_ack;
840 478
@@ -852,11 +490,6 @@ unsigned int debug_bck_ack;
852static struct GNUNET_TIME_Relative refresh_path_time; 490static struct GNUNET_TIME_Relative refresh_path_time;
853 491
854/** 492/**
855 * How often to PUT local application numbers in the DHT.
856 */
857static struct GNUNET_TIME_Relative app_announce_time;
858
859/**
860 * How often to PUT own ID in the DHT. 493 * How often to PUT own ID in the DHT.
861 */ 494 */
862static struct GNUNET_TIME_Relative id_announce_time; 495static struct GNUNET_TIME_Relative id_announce_time;
@@ -904,7 +537,7 @@ static struct GNUNET_CRYPTO_EccKeyGenerationContext *keygen;
904/** 537/**
905 * DLL with all the clients, head. 538 * DLL with all the clients, head.
906 */ 539 */
907static struct MeshClient *clients; 540static struct MeshClient *clients_head;
908 541
909/** 542/**
910 * DLL with all the clients, tail. 543 * DLL with all the clients, tail.
@@ -932,10 +565,10 @@ static struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels;
932 */ 565 */
933static struct GNUNET_CONTAINER_MultiHashMap *peers; 566static struct GNUNET_CONTAINER_MultiHashMap *peers;
934 567
935/** 568/*
936 * Configuration handle 569 * Handle to communicate with transport
937 */ 570 */
938static const struct GNUNET_CONFIGURATION_Handle *cfg; 571// static struct GNUNET_TRANSPORT_Handle *transport_handle;
939 572
940/** 573/**
941 * Handle to communicate with core. 574 * Handle to communicate with core.
@@ -993,19 +626,9 @@ static MESH_TunnelNumber next_tid;
993static MESH_TunnelNumber next_local_tid; 626static MESH_TunnelNumber next_local_tid;
994 627
995/** 628/**
996 * All application types provided by this peer: H(app) = *Client. 629 * All ports clients of this peer have opened.
997 */
998static struct GNUNET_CONTAINER_MultiHashMap *applications;
999
1000/**
1001 * All message types clients of this peer are interested in.
1002 */ 630 */
1003static struct GNUNET_CONTAINER_MultiHashMap *types; 631static struct GNUNET_CONTAINER_MultiHashMap *ports;
1004
1005/**
1006 * Task to periodically announce provided applications.
1007 */
1008GNUNET_SCHEDULER_TaskIdentifier announce_applications_task;
1009 632
1010/** 633/**
1011 * Task to periodically announce itself in the network. 634 * Task to periodically announce itself in the network.
@@ -1046,39 +669,26 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
1046 669
1047/** 670/**
1048 * Retrieve the MeshPeerInfo stucture associated with the peer, create one 671 * Retrieve the MeshPeerInfo stucture associated with the peer, create one
1049 * and insert it in the appropiate structures if the peer is not known yet. 672 * and insert it in the appropriate structures if the peer is not known yet.
1050 * 673 *
1051 * @param peer Full identity of the peer. 674 * @param peer Full identity of the peer.
1052 * 675 *
1053 * @return Existing or newly created peer info. 676 * @return Existing or newly created peer info.
1054 */ 677 */
1055static struct MeshPeerInfo * 678static struct MeshPeerInfo *
1056peer_info_get (const struct GNUNET_PeerIdentity *peer); 679peer_get (const struct GNUNET_PeerIdentity *peer);
1057 680
1058 681
1059/** 682/**
1060 * Retrieve the MeshPeerInfo stucture associated with the peer, create one 683 * Retrieve the MeshPeerInfo stucture associated with the peer, create one
1061 * and insert it in the appropiate structures if the peer is not known yet. 684 * and insert it in the appropriate structures if the peer is not known yet.
1062 * 685 *
1063 * @param peer Short identity of the peer. 686 * @param peer Short identity of the peer.
1064 * 687 *
1065 * @return Existing or newly created peer info. 688 * @return Existing or newly created peer info.
1066 */ 689 */
1067static struct MeshPeerInfo * 690static struct MeshPeerInfo *
1068peer_info_get_short (const GNUNET_PEER_Id peer); 691peer_get_short (const GNUNET_PEER_Id peer);
1069
1070
1071/**
1072 * Try to establish a new connection to this peer.
1073 * Use the best path for the given tunnel.
1074 * If the peer doesn't have any path to it yet, try to get one.
1075 * If the peer already has some path, send a CREATE PATH towards it.
1076 *
1077 * @param peer PeerInfo of the peer.
1078 * @param t Tunnel for which to create the path, if possible.
1079 */
1080static void
1081peer_info_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t);
1082 692
1083 693
1084/** 694/**
@@ -1104,30 +714,6 @@ static void
1104path_add_to_peers (struct MeshPeerPath *p, int confirmed); 714path_add_to_peers (struct MeshPeerPath *p, int confirmed);
1105 715
1106 716
1107/**
1108 * Add a peer to a tunnel, accomodating paths accordingly and initializing all
1109 * needed rescources.
1110 * If peer already exists, reevaluate shortest path and change if different.
1111 *
1112 * @param t Tunnel we want to add a new peer to
1113 * @param peer PeerInfo of the peer being added
1114 *
1115 */
1116static void
1117tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer);
1118
1119
1120/**
1121 * Removes an explicit path from a tunnel, freeing all intermediate nodes
1122 * that are no longer needed, as well as nodes of no longer reachable peers.
1123 * The tunnel itself is also destoyed if results in a remote empty tunnel.
1124 *
1125 * @param t Tunnel from which to remove the path.
1126 * @param peer Short id of the peer which should be removed.
1127 */
1128static void
1129tunnel_delete_peer (struct MeshTunnel *t, GNUNET_PEER_Id peer);
1130
1131 717
1132/** 718/**
1133 * Search for a tunnel by global ID using full PeerIdentities. 719 * Search for a tunnel by global ID using full PeerIdentities.
@@ -1142,15 +728,6 @@ tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid);
1142 728
1143 729
1144/** 730/**
1145 * Delete an active client from the tunnel.
1146 *
1147 * @param t Tunnel.
1148 * @param c Client.
1149 */
1150static void
1151tunnel_delete_active_client (struct MeshTunnel *t, const struct MeshClient *c);
1152
1153/**
1154 * Notify a tunnel that a connection has broken that affects at least 731 * Notify a tunnel that a connection has broken that affects at least
1155 * some of its peers. 732 * some of its peers.
1156 * 733 *
@@ -1167,26 +744,25 @@ tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
1167 744
1168 745
1169/** 746/**
1170 * Get the current ack value for a tunnel, for data going from root to leaves, 747 * @brief Use the given path for the tunnel.
1171 * taking in account the tunnel mode and the status of all children and clients. 748 * Update the next and prev hops (and RCs).
1172 * 749 * (Re)start the path refresh in case the tunnel is locally owned.
1173 * @param t Tunnel. 750 *
1174 * 751 * @param t Tunnel to update.
1175 * @return Maximum PID allowed. 752 * @param p Path to use.
1176 */ 753 */
1177static uint32_t 754static void
1178tunnel_get_fwd_ack (struct MeshTunnel *t); 755tunnel_use_path (struct MeshTunnel *t, struct MeshPeerPath *p);
1179
1180 756
1181/** 757/**
1182 * Add a client to a tunnel, initializing all needed data structures. 758 * Tunnel is empty: destroy it.
1183 * 759 *
1184 * @param t Tunnel to which add the client. 760 * Notifies all participants (peers, cleints) about the destruction.
1185 * @param c Client which to add to the tunnel. 761 *
762 * @param t Tunnel to destroy.
1186 */ 763 */
1187static void 764static void
1188tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c); 765tunnel_destroy_empty (struct MeshTunnel *t);
1189
1190 766
1191/** 767/**
1192 * @brief Queue and pass message to core when possible. 768 * @brief Queue and pass message to core when possible.
@@ -1248,255 +824,12 @@ queue_get_next (const struct MeshPeerInfo *peer);
1248static size_t 824static size_t
1249queue_send (void *cls, size_t size, void *buf); 825queue_send (void *cls, size_t size, void *buf);
1250 826
1251/******************************************************************************/
1252/************************ REGEX INTEGRATION ****************************/
1253/******************************************************************************/
1254
1255/**
1256 * Cancel a mesh regex search and free resources.
1257 */
1258static void
1259regex_cancel_search (struct MeshRegexSearchInfo *regex_search)
1260{
1261 DEBUG_REGEX ("Search for %s canelled.\n", regex_search->description);
1262 GNUNET_REGEX_search_cancel (regex_search->search_handle);
1263 if (0 < regex_search->n_peers)
1264 GNUNET_free (regex_search->peers);
1265 if (GNUNET_SCHEDULER_NO_TASK != regex_search->timeout)
1266 {
1267 GNUNET_SCHEDULER_cancel(regex_search->timeout);
1268 }
1269 GNUNET_free (regex_search);
1270}
1271
1272
1273/**
1274 * Function called if the connect attempt to a peer found via
1275 * connect_by_string times out. Try to connect to another peer, if any.
1276 * Otherwise try to reconnect to the same peer.
1277 *
1278 * @param cls Closure (info about regex search).
1279 * @param tc TaskContext.
1280 */
1281static void
1282regex_connect_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1283{
1284 struct MeshRegexSearchInfo *info = cls;
1285 struct MeshPeerInfo *peer_info;
1286 GNUNET_PEER_Id id;
1287 GNUNET_PEER_Id old;
1288
1289 DEBUG_REGEX ("Regex connect timeout\n");
1290 info->timeout = GNUNET_SCHEDULER_NO_TASK;
1291 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1292 {
1293 DEBUG_REGEX (" due to shutdown\n");
1294 return;
1295 }
1296
1297 old = info->peer;
1298 DEBUG_REGEX (" timed out: %u\n", old);
1299
1300 if (0 < info->n_peers)
1301 {
1302 // Select next peer, put current in that spot.
1303 id = info->peers[info->i_peer];
1304 info->peers[info->i_peer] = info->peer;
1305 info->i_peer = (info->i_peer + 1) % info->n_peers;
1306 }
1307 else
1308 {
1309 // Try to connect to same peer again.
1310 id = info->peer;
1311 }
1312 DEBUG_REGEX (" trying: %u\n", id);
1313
1314 peer_info = peer_info_get_short(id);
1315 tunnel_add_peer (info->t, peer_info);
1316 if (old != id)
1317 tunnel_delete_peer (info->t, old);
1318 peer_info_connect (peer_info, info->t);
1319 info->timeout = GNUNET_SCHEDULER_add_delayed (connect_timeout,
1320 &regex_connect_timeout,
1321 info);
1322 DEBUG_REGEX ("Regex connect timeout END\n");
1323}
1324
1325
1326/**
1327 * Function to process DHT string to regex matching.
1328 * Called on each result obtained for the DHT search.
1329 *
1330 * @param cls Closure provided in GNUNET_REGEX_search.
1331 * @param id Peer providing a regex that matches the string.
1332 * @param get_path Path of the get request.
1333 * @param get_path_length Lenght of get_path.
1334 * @param put_path Path of the put request.
1335 * @param put_path_length Length of the put_path.
1336 */
1337static void
1338regex_found_handler (void *cls,
1339 const struct GNUNET_PeerIdentity *id,
1340 const struct GNUNET_PeerIdentity *get_path,
1341 unsigned int get_path_length,
1342 const struct GNUNET_PeerIdentity *put_path,
1343 unsigned int put_path_length)
1344{
1345 struct MeshRegexSearchInfo *info = cls;
1346 struct MeshPeerPath *p;
1347 struct MeshPeerInfo *peer_info;
1348
1349 DEBUG_REGEX ("Got regex results from DHT!\n");
1350 DEBUG_REGEX (" for %s\n", info->description);
1351
1352 peer_info = peer_info_get (id);
1353 p = path_build_from_dht (get_path, get_path_length,
1354 put_path, put_path_length);
1355 path_add_to_peers (p, GNUNET_NO);
1356 path_destroy(p);
1357
1358 tunnel_add_peer (info->t, peer_info);
1359 peer_info_connect (peer_info, info->t);
1360 if (0 == info->peer)
1361 {
1362 info->peer = peer_info->id;
1363 }
1364 else
1365 {
1366 GNUNET_array_append (info->peers, info->n_peers, peer_info->id);
1367 }
1368
1369 if (GNUNET_SCHEDULER_NO_TASK != info->timeout)
1370 return;
1371
1372 info->timeout = GNUNET_SCHEDULER_add_delayed (connect_timeout,
1373 &regex_connect_timeout,
1374 info);
1375
1376 return;
1377}
1378
1379
1380/**
1381 * Store the regular expression describing a local service into the DHT.
1382 *
1383 * @param regex The regular expresion.
1384 */
1385static void
1386regex_put (struct MeshRegexDescriptor *regex)
1387{
1388 DEBUG_REGEX (" regex_put (%s) start\n", regex->regex);
1389 if (NULL == regex->h)
1390 {
1391 DEBUG_REGEX (" first put, creating DFA\n");
1392 regex->h = GNUNET_REGEX_announce (cfg,
1393 regex->regex,
1394 app_announce_time,
1395 regex->compression);
1396 }
1397 DEBUG_REGEX (" regex_put (%s) end\n", regex->regex);
1398}
1399
1400
1401/**
1402 * Periodically announce what applications are provided by local clients
1403 * (by regex)
1404 *
1405 * @param cls closure
1406 * @param tc task context
1407 */
1408static void
1409regex_announce (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1410{
1411 struct MeshClient *c = cls;
1412 unsigned int i;
1413
1414 c->regex_announce_task = GNUNET_SCHEDULER_NO_TASK;
1415 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1416 return;
1417 DEBUG_REGEX ("Starting announce for regex\n");
1418 for (i = 0; i < c->n_regex; i++)
1419 regex_put (&c->regexes[i]);
1420 c->regex_announce_task = GNUNET_SCHEDULER_add_delayed (app_announce_time,
1421 &regex_announce,
1422 cls);
1423 DEBUG_REGEX ("Finished announce for regex\n");
1424}
1425
1426 827
1427/******************************************************************************/ 828/******************************************************************************/
1428/************************ PERIODIC FUNCTIONS ****************************/ 829/************************ PERIODIC FUNCTIONS ****************************/
1429/******************************************************************************/ 830/******************************************************************************/
1430 831
1431/** 832/**
1432 * Announce iterator over for each application provided by the peer
1433 *
1434 * @param cls closure
1435 * @param key current key code
1436 * @param value value in the hash map
1437 * @return GNUNET_YES if we should continue to
1438 * iterate,
1439 * GNUNET_NO if not.
1440 */
1441static int
1442announce_application (void *cls, const struct GNUNET_HashCode * key, void *value)
1443{
1444 struct PBlock block;
1445 struct MeshClient *c;
1446
1447 block.id = my_full_id;
1448 c = GNUNET_CONTAINER_multihashmap_get (applications, key);
1449 GNUNET_assert(NULL != c);
1450 block.type = (long) GNUNET_CONTAINER_multihashmap_get (c->apps, key);
1451 if (0 == block.type)
1452 {
1453 GNUNET_break(0);
1454 return GNUNET_YES;
1455 }
1456 block.type = htonl (block.type);
1457 DEBUG_DHT ("Putting APP key: %s\n", GNUNET_h2s (key));
1458 GNUNET_break (NULL !=
1459 GNUNET_DHT_put (dht_handle, key,
1460 dht_replication_level,
1461 GNUNET_DHT_RO_RECORD_ROUTE |
1462 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
1463 GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE,
1464 sizeof (block),
1465 (const char *) &block,
1466 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS), /* FIXME: this should be an option */
1467 app_announce_time, NULL, NULL));
1468 return GNUNET_OK;
1469}
1470
1471
1472/**
1473 * Periodically announce what applications are provided by local clients
1474 * (by type)
1475 *
1476 * @param cls closure
1477 * @param tc task context
1478 */
1479static void
1480announce_applications (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1481{
1482 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1483 {
1484 announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
1485 return;
1486 }
1487
1488 DEBUG_DHT ("Starting PUT for apps\n");
1489
1490 GNUNET_CONTAINER_multihashmap_iterate (applications, &announce_application,
1491 NULL);
1492 announce_applications_task =
1493 GNUNET_SCHEDULER_add_delayed (app_announce_time, &announce_applications,
1494 cls);
1495 DEBUG_DHT ("Finished PUT for apps\n");
1496}
1497
1498
1499/**
1500 * Periodically announce self id in the DHT 833 * Periodically announce self id in the DHT
1501 * 834 *
1502 * @param cls closure 835 * @param cls closure
@@ -1519,7 +852,6 @@ announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1519 DEBUG_DHT ("DHT_put for ID %s started.\n", GNUNET_i2s (&my_full_id)); 852 DEBUG_DHT ("DHT_put for ID %s started.\n", GNUNET_i2s (&my_full_id));
1520 853
1521 block.id = my_full_id; 854 block.id = my_full_id;
1522 block.type = htonl (0);
1523 GNUNET_DHT_put (dht_handle, /* DHT handle */ 855 GNUNET_DHT_put (dht_handle, /* DHT handle */
1524 &my_full_id.hashPubKey, /* Key to use */ 856 &my_full_id.hashPubKey, /* Key to use */
1525 dht_replication_level, /* Replication level */ 857 dht_replication_level, /* Replication level */
@@ -1540,23 +872,6 @@ announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1540/****************** GENERAL HELPER FUNCTIONS ************************/ 872/****************** GENERAL HELPER FUNCTIONS ************************/
1541/******************************************************************************/ 873/******************************************************************************/
1542 874
1543/**
1544 * Decrements the reference counter and frees all resources if needed
1545 *
1546 * @param mesh_data Data Descriptor used in a multicast message.
1547 * Freed no longer needed (last message).
1548 */
1549static void
1550data_descriptor_decrement_rc (struct MeshData *mesh_data)
1551{
1552 if (0 == --(mesh_data->reference_counter))
1553 {
1554 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last copy!\n");
1555 GNUNET_free (mesh_data->data);
1556 GNUNET_free (mesh_data);
1557 }
1558}
1559
1560 875
1561/** 876/**
1562 * Check if client has registered with the service and has not disconnected 877 * Check if client has registered with the service and has not disconnected
@@ -1570,7 +885,7 @@ client_get (struct GNUNET_SERVER_Client *client)
1570{ 885{
1571 struct MeshClient *c; 886 struct MeshClient *c;
1572 887
1573 c = clients; 888 c = clients_head;
1574 while (NULL != c) 889 while (NULL != c)
1575 { 890 {
1576 if (c->handle == client) 891 if (c->handle == client)
@@ -1582,104 +897,8 @@ client_get (struct GNUNET_SERVER_Client *client)
1582 897
1583 898
1584/** 899/**
1585 * Checks if a given client has subscribed to certain message type
1586 *
1587 * @param message_type Type of message to check
1588 * @param c Client to check
1589 *
1590 * @return GNUNET_YES or GNUNET_NO, depending on subscription status
1591 *
1592 * FIXME: use of crypto_hash slows it down
1593 * The hash function alone takes 8-10us out of the ~55us for the whole
1594 * process of retransmitting the message from one local client to another.
1595 * Find faster implementation!
1596 */
1597static int
1598client_is_subscribed (uint16_t message_type, struct MeshClient *c)
1599{
1600 struct GNUNET_HashCode hc;
1601
1602 if (NULL == c->types)
1603 return GNUNET_NO;
1604
1605 GNUNET_CRYPTO_hash (&message_type, sizeof (uint16_t), &hc);
1606 return GNUNET_CONTAINER_multihashmap_contains (c->types, &hc);
1607}
1608
1609
1610/**
1611 * Check whether client wants traffic from a tunnel.
1612 *
1613 * @param c Client to check.
1614 * @param t Tunnel to be found.
1615 *
1616 * @return GNUNET_YES if client knows tunnel.
1617 *
1618 * TODO look in client hashmap
1619 */
1620static int
1621client_wants_tunnel (struct MeshClient *c, struct MeshTunnel *t)
1622{
1623 unsigned int i;
1624
1625 for (i = 0; i < t->nclients; i++)
1626 if (t->clients[i] == c)
1627 return GNUNET_YES;
1628 return GNUNET_NO;
1629}
1630
1631
1632/**
1633 * Check whether client has been informed about a tunnel.
1634 *
1635 * @param c Client to check.
1636 * @param t Tunnel to be found.
1637 *
1638 * @return GNUNET_YES if client knows tunnel.
1639 *
1640 * TODO look in client hashmap
1641 */
1642static int
1643client_knows_tunnel (struct MeshClient *c, struct MeshTunnel *t)
1644{
1645 unsigned int i;
1646
1647 for (i = 0; i < t->nignore; i++)
1648 if (t->ignore[i] == c)
1649 return GNUNET_YES;
1650 return client_wants_tunnel(c, t);
1651}
1652
1653
1654/**
1655 * Marks a client as uninterested in traffic from the tunnel, updating both
1656 * client and tunnel to reflect this.
1657 *
1658 * @param c Client that doesn't want traffic anymore.
1659 * @param t Tunnel which should be ignored.
1660 *
1661 * FIXME when to delete an incoming tunnel?
1662 */
1663static void
1664client_ignore_tunnel (struct MeshClient *c, struct MeshTunnel *t)
1665{
1666 struct GNUNET_HashCode hash;
1667
1668 GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
1669 GNUNET_break (GNUNET_YES ==
1670 GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels,
1671 &hash, t));
1672 GNUNET_break (GNUNET_YES ==
1673 GNUNET_CONTAINER_multihashmap_put (c->ignore_tunnels, &hash, t,
1674 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
1675 tunnel_delete_active_client (t, c);
1676 GNUNET_array_append (t->ignore, t->nignore, c);
1677}
1678
1679
1680/**
1681 * Deletes a tunnel from a client (either owner or destination). To be used on 900 * Deletes a tunnel from a client (either owner or destination). To be used on
1682 * tunnel destroy, otherwise, use client_ignore_tunnel. 901 * tunnel destroy.
1683 * 902 *
1684 * @param c Client whose tunnel to delete. 903 * @param c Client whose tunnel to delete.
1685 * @param t Tunnel which should be deleted. 904 * @param t Tunnel which should be deleted.
@@ -1691,240 +910,76 @@ client_delete_tunnel (struct MeshClient *c, struct MeshTunnel *t)
1691 910
1692 if (c == t->owner) 911 if (c == t->owner)
1693 { 912 {
1694 GNUNET_CRYPTO_hash(&t->local_tid, sizeof (MESH_TunnelNumber), &hash); 913 GMC_hash32 (t->local_tid, &hash);
1695 GNUNET_assert (GNUNET_YES == 914 GNUNET_assert (GNUNET_YES ==
1696 GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels, 915 GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels,
1697 &hash, 916 &hash,
1698 t)); 917 t));
1699 } 918 }
1700 else 919 else if (c == t->client)
1701 { 920 {
1702 GNUNET_CRYPTO_hash(&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash); 921 GMC_hash32 (t->local_tid_dest, &hash);
1703 // FIXME XOR?
1704 GNUNET_assert (GNUNET_YES == 922 GNUNET_assert (GNUNET_YES ==
1705 GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, 923 GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels,
1706 &hash, 924 &hash,
1707 t) ||
1708 GNUNET_YES ==
1709 GNUNET_CONTAINER_multihashmap_remove (c->ignore_tunnels,
1710 &hash,
1711 t)); 925 t));
1712 } 926 }
1713} 927 else
1714
1715
1716/**
1717 * Notify the owner of a tunnel that a peer has disconnected.
1718 *
1719 * @param c Client (owner of tunnel).
1720 * @param t Tunnel this message is about.
1721 * @param peer_id Short ID of the disconnected peer.
1722 */
1723void
1724client_notify_peer_disconnected (struct MeshClient *c,
1725 struct MeshTunnel *t,
1726 GNUNET_PEER_Id peer_id)
1727{
1728 struct GNUNET_MESH_PeerControl msg;
1729
1730 if (NULL == t->owner || NULL == nc)
1731 return;
1732
1733 msg.header.size = htons (sizeof (msg));
1734 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
1735 msg.tunnel_id = htonl (t->local_tid);
1736 GNUNET_PEER_resolve (peer_id, &msg.peer);
1737 GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
1738 &msg.header, GNUNET_NO);
1739}
1740
1741
1742/**
1743 * Send the message to all clients that have subscribed to its type
1744 *
1745 * @param msg Pointer to the message itself
1746 * @param payload Pointer to the payload of the message.
1747 * @param t The tunnel to whose clients this message goes.
1748 *
1749 * @return number of clients this message was sent to
1750 */
1751static unsigned int
1752send_subscribed_clients (const struct GNUNET_MessageHeader *msg,
1753 const struct GNUNET_MessageHeader *payload,
1754 struct MeshTunnel *t)
1755{
1756 struct MeshClient *c;
1757 MESH_TunnelNumber *tid;
1758 unsigned int count;
1759 uint16_t type;
1760 char cbuf[htons (msg->size)];
1761
1762 type = ntohs (payload->type);
1763 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending to clients...\n");
1764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "message of type %s\n",
1765 GNUNET_MESH_DEBUG_M2S (type));
1766
1767 memcpy (cbuf, msg, sizeof (cbuf));
1768 switch (htons (msg->type))
1769 {
1770 struct GNUNET_MESH_Unicast *uc;
1771 struct GNUNET_MESH_Multicast *mc;
1772 struct GNUNET_MESH_ToOrigin *to;
1773
1774 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1775 uc = (struct GNUNET_MESH_Unicast *) cbuf;
1776 tid = &uc->tid;
1777 break;
1778 case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1779 mc = (struct GNUNET_MESH_Multicast *) cbuf;
1780 tid = &mc->tid;
1781 break;
1782 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1783 to = (struct GNUNET_MESH_ToOrigin *) cbuf;
1784 tid = &to->tid;
1785 break;
1786 default:
1787 GNUNET_break (0);
1788 return 0;
1789 }
1790
1791 for (count = 0, c = clients; c != NULL; c = c->next)
1792 { 928 {
1793 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client %u\n", c->id); 929 GNUNET_break (0);
1794 if (client_is_subscribed (type, c))
1795 {
1796 if (htons (msg->type) == GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN)
1797 {
1798 if (c != t->owner)
1799 continue;
1800 *tid = htonl (t->local_tid);
1801 }
1802 else
1803 {
1804 if (GNUNET_NO == client_knows_tunnel (c, t))
1805 {
1806 /* This client doesn't know the tunnel */
1807 struct GNUNET_MESH_TunnelNotification tmsg;
1808 struct GNUNET_HashCode hash;
1809
1810 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending tunnel create\n");
1811 tmsg.header.size = htons (sizeof (tmsg));
1812 tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
1813 GNUNET_PEER_resolve (t->id.oid, &tmsg.peer);
1814 tmsg.tunnel_id = htonl (t->local_tid_dest);
1815 tmsg.opt = 0;
1816 if (GNUNET_YES == t->speed_min)
1817 tmsg.opt |= MESH_TUNNEL_OPT_SPEED_MIN;
1818 if (GNUNET_YES == t->nobuffer)
1819 tmsg.opt |= MESH_TUNNEL_OPT_NOBUFFER;
1820 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1821 &tmsg.header, GNUNET_NO);
1822 tunnel_add_client (t, c);
1823 GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber),
1824 &hash);
1825 GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (
1826 c->incoming_tunnels, &hash, t,
1827 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
1828 }
1829 *tid = htonl (t->local_tid_dest);
1830 }
1831
1832 /* Check if the client wants to get traffic from the tunnel */
1833 if (GNUNET_NO == client_wants_tunnel(c, t))
1834 continue;
1835 count++;
1836 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending\n");
1837 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1838 (struct GNUNET_MessageHeader
1839 *) cbuf, GNUNET_NO);
1840 }
1841 } 930 }
1842
1843 return count;
1844}
1845
1846
1847/**
1848 * Notify the client that owns the tunnel that a peer has connected to it
1849 * (the requested path to it has been confirmed).
1850 *
1851 * @param t Tunnel whose owner to notify
1852 * @param id Short id of the peer that has connected
1853 */
1854static void
1855send_client_peer_connected (const struct MeshTunnel *t, const GNUNET_PEER_Id id)
1856{
1857 struct GNUNET_MESH_PeerControl pc;
1858
1859 if (NULL == t->owner || GNUNET_YES == t->destroy)
1860 return;
1861
1862 pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
1863 pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
1864 pc.tunnel_id = htonl (t->local_tid);
1865 GNUNET_PEER_resolve (id, &pc.peer);
1866 GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle, &pc.header,
1867 GNUNET_NO);
1868} 931}
1869 932
1870
1871/** 933/**
1872 * Notify all clients (not depending on registration status) that the incoming 934 * Notify the appropriate client that a new incoming tunnel was created.
1873 * tunnel is no longer valid.
1874 * 935 *
1875 * @param t Tunnel that was destroyed. 936 * @param t Tunnel that was created.
1876 */ 937 */
1877static void 938static void
1878send_clients_tunnel_destroy (struct MeshTunnel *t) 939send_client_tunnel_create (struct MeshTunnel *t)
1879{ 940{
1880 struct GNUNET_MESH_TunnelMessage msg; 941 struct GNUNET_MESH_TunnelMessage msg;
1881 942
943 if (NULL == t->client)
944 return;
1882 msg.header.size = htons (sizeof (msg)); 945 msg.header.size = htons (sizeof (msg));
1883 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); 946 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
1884 msg.tunnel_id = htonl (t->local_tid_dest); 947 msg.tunnel_id = htonl (t->local_tid_dest);
1885 GNUNET_SERVER_notification_context_broadcast (nc, &msg.header, GNUNET_NO); 948 msg.port = htonl (t->port);
949 GNUNET_PEER_resolve (t->id.oid, &msg.peer);
950 GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
951 &msg.header, GNUNET_NO);
1886} 952}
1887 953
1888 954
1889/** 955/**
1890 * Notify clients of tunnel disconnections, if needed. 956 * Notify dest client that the incoming tunnel is no longer valid.
1891 * In case the origin disconnects, the destination clients get a tunnel destroy
1892 * notification. If the last destination disconnects (only one remaining client
1893 * in tunnel), the origin gets a (local ID) peer disconnected.
1894 * Note that the function must be called BEFORE removing the client from
1895 * the tunnel.
1896 * 957 *
1897 * @param t Tunnel that was destroyed. 958 * @param c Client to notify..
1898 * @param c Client that disconnected. 959 * @param t Tunnel that is destroyed.
1899 */ 960 */
1900static void 961static void
1901send_client_tunnel_disconnect (struct MeshTunnel *t, struct MeshClient *c) 962send_client_tunnel_destroy (struct MeshClient *c, struct MeshTunnel *t)
1902{ 963{
1903 unsigned int i; 964 struct GNUNET_MESH_TunnelMessage msg;
1904 965
1905 if (c == t->owner) 966 if (NULL == c)
1906 { 967 {
1907 struct GNUNET_MESH_TunnelMessage msg; 968 GNUNET_break (0);
1908 969 return;
1909 msg.header.size = htons (sizeof (msg));
1910 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1911 msg.tunnel_id = htonl (t->local_tid_dest);
1912 for (i = 0; i < t->nclients; i++)
1913 GNUNET_SERVER_notification_context_unicast (nc, t->clients[i]->handle,
1914 &msg.header, GNUNET_NO);
1915 } 970 }
1916 // FIXME when to disconnect an incoming tunnel? 971 if (c != t->client && c != t->owner)
1917 else if (1 == t->nclients && NULL != t->owner)
1918 { 972 {
1919 struct GNUNET_MESH_PeerControl msg; 973 GNUNET_break (0);
1920 974 return;
1921 msg.header.size = htons (sizeof (msg));
1922 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
1923 msg.tunnel_id = htonl (t->local_tid);
1924 msg.peer = my_full_id;
1925 GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
1926 &msg.header, GNUNET_NO);
1927 } 975 }
976 msg.header.size = htons (sizeof (msg));
977 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
978 msg.tunnel_id = htonl (t->local_tid_dest);
979 msg.port = htonl (0);
980 memset(&msg.peer, 0, sizeof (msg.peer));
981 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
982 &msg.header, GNUNET_NO);
1928} 983}
1929 984
1930 985
@@ -1947,14 +1002,14 @@ peer_info_timeout (void *cls,
1947 1002
1948/** 1003/**
1949 * Retrieve the MeshPeerInfo stucture associated with the peer, create one 1004 * Retrieve the MeshPeerInfo stucture associated with the peer, create one
1950 * and insert it in the appropiate structures if the peer is not known yet. 1005 * and insert it in the appropriate structures if the peer is not known yet.
1951 * 1006 *
1952 * @param peer Full identity of the peer. 1007 * @param peer Full identity of the peer.
1953 * 1008 *
1954 * @return Existing or newly created peer info. 1009 * @return Existing or newly created peer info.
1955 */ 1010 */
1956static struct MeshPeerInfo * 1011static struct MeshPeerInfo *
1957peer_info_get (const struct GNUNET_PeerIdentity *peer) 1012peer_get (const struct GNUNET_PeerIdentity *peer)
1958{ 1013{
1959 struct MeshPeerInfo *peer_info; 1014 struct MeshPeerInfo *peer_info;
1960 1015
@@ -1981,56 +1036,52 @@ peer_info_get (const struct GNUNET_PeerIdentity *peer)
1981 1036
1982/** 1037/**
1983 * Retrieve the MeshPeerInfo stucture associated with the peer, create one 1038 * Retrieve the MeshPeerInfo stucture associated with the peer, create one
1984 * and insert it in the appropiate structures if the peer is not known yet. 1039 * and insert it in the appropriate structures if the peer is not known yet.
1985 * 1040 *
1986 * @param peer Short identity of the peer. 1041 * @param peer Short identity of the peer.
1987 * 1042 *
1988 * @return Existing or newly created peer info. 1043 * @return Existing or newly created peer info.
1989 */ 1044 */
1990static struct MeshPeerInfo * 1045static struct MeshPeerInfo *
1991peer_info_get_short (const GNUNET_PEER_Id peer) 1046peer_get_short (const GNUNET_PEER_Id peer)
1992{ 1047{
1993 struct GNUNET_PeerIdentity id; 1048 struct GNUNET_PeerIdentity id;
1994 1049
1995 GNUNET_PEER_resolve (peer, &id); 1050 GNUNET_PEER_resolve (peer, &id);
1996 return peer_info_get (&id); 1051 return peer_get (&id);
1997} 1052}
1998 1053
1999 1054
2000/** 1055/**
2001 * Iterator to remove the tunnel from the list of tunnels a peer participates 1056 * Choose the best path towards a peer considering the tunnel properties.
2002 * in. 1057 *
2003 * 1058 * @param peer The destination peer.
2004 * @param cls Closure (tunnel info) 1059 * @param t The tunnel the path is for.
2005 * @param key GNUNET_PeerIdentity of the peer (unused)
2006 * @param value PeerInfo of the peer
2007 * 1060 *
2008 * @return always GNUNET_YES, to keep iterating 1061 * @return Best current known path towards the peer, if any.
2009 */ 1062 */
2010static int 1063static struct MeshPeerPath *
2011peer_info_delete_tunnel (void *cls, const struct GNUNET_HashCode * key, void *value) 1064peer_get_best_path (const struct MeshPeerInfo *peer, const struct MeshTunnel *t)
2012{ 1065{
2013 struct MeshTunnel *t = cls; 1066 struct MeshPeerPath *best_p;
2014 struct MeshPeerInfo *peer = value; 1067 struct MeshPeerPath *p;
2015 unsigned int i; 1068 unsigned int best_cost;
1069 unsigned int cost;
2016 1070
2017 for (i = 0; i < peer->ntunnels; i++) 1071 best_p = p = peer->path_head;
1072 best_cost = cost = p->length;
1073 while (NULL != p)
2018 { 1074 {
2019 if (0 == 1075 if ((cost = p->length) < best_cost)
2020 memcmp (&peer->tunnels[i]->id, &t->id, sizeof (struct MESH_TunnelID)))
2021 { 1076 {
2022 peer->ntunnels--; 1077 best_cost = cost;
2023 peer->tunnels[i] = peer->tunnels[peer->ntunnels]; 1078 best_p = p;
2024 peer->tunnels =
2025 GNUNET_realloc (peer->tunnels,
2026 peer->ntunnels * sizeof(struct MeshTunnel *));
2027 return GNUNET_YES;
2028 } 1079 }
1080 p = p->next;
2029 } 1081 }
2030 return GNUNET_YES; 1082 return best_p;
2031} 1083}
2032 1084
2033
2034/** 1085/**
2035 * Core callback to write a pre-constructed data packet to core buffer 1086 * Core callback to write a pre-constructed data packet to core buffer
2036 * 1087 *
@@ -2043,13 +1094,10 @@ peer_info_delete_tunnel (void *cls, const struct GNUNET_HashCode * key, void *va
2043static size_t 1094static size_t
2044send_core_data_raw (void *cls, size_t size, void *buf) 1095send_core_data_raw (void *cls, size_t size, void *buf)
2045{ 1096{
2046 struct MeshTransmissionDescriptor *info = cls; 1097 struct GNUNET_MessageHeader *msg = cls;
2047 struct GNUNET_MessageHeader *msg;
2048 size_t total_size; 1098 size_t total_size;
2049 1099
2050 GNUNET_assert (NULL != info); 1100 GNUNET_assert (NULL != msg);
2051 GNUNET_assert (NULL != info->mesh_data);
2052 msg = (struct GNUNET_MessageHeader *) info->mesh_data->data;
2053 total_size = ntohs (msg->size); 1101 total_size = ntohs (msg->size);
2054 1102
2055 if (total_size > size) 1103 if (total_size > size)
@@ -2058,15 +1106,14 @@ send_core_data_raw (void *cls, size_t size, void *buf)
2058 return 0; 1106 return 0;
2059 } 1107 }
2060 memcpy (buf, msg, total_size); 1108 memcpy (buf, msg, total_size);
2061 data_descriptor_decrement_rc (info->mesh_data); 1109 GNUNET_free (cls);
2062 GNUNET_free (info);
2063 return total_size; 1110 return total_size;
2064} 1111}
2065 1112
2066 1113
2067/** 1114/**
2068 * Sends an already built non-multicast message to a peer, 1115 * Sends an already built message to a peer, properly registrating
2069 * properly registrating all used resources. 1116 * all used resources.
2070 * 1117 *
2071 * @param message Message to send. Function makes a copy of it. 1118 * @param message Message to send. Function makes a copy of it.
2072 * @param peer Short ID of the neighbor whom to send the message. 1119 * @param peer Short ID of the neighbor whom to send the message.
@@ -2074,41 +1121,35 @@ send_core_data_raw (void *cls, size_t size, void *buf)
2074 */ 1121 */
2075static void 1122static void
2076send_prebuilt_message (const struct GNUNET_MessageHeader *message, 1123send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2077 const struct GNUNET_PeerIdentity *peer, 1124 GNUNET_PEER_Id peer,
2078 struct MeshTunnel *t) 1125 struct MeshTunnel *t)
2079{ 1126{
2080 struct MeshTransmissionDescriptor *info; 1127 struct GNUNET_PeerIdentity id;
2081 struct MeshPeerInfo *neighbor; 1128 struct MeshPeerInfo *neighbor;
2082 struct MeshPeerPath *p; 1129 struct MeshPeerPath *p;
1130 void *data;
2083 size_t size; 1131 size_t size;
2084 uint16_t type; 1132 uint16_t type;
2085 1133
2086// GNUNET_TRANSPORT_try_connect(); FIXME use? 1134// GNUNET_TRANSPORT_try_connect(); FIXME use?
2087 1135
1136 if (0 == peer)
1137 return;
1138
2088 size = ntohs (message->size); 1139 size = ntohs (message->size);
2089 info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor)); 1140 data = GNUNET_malloc (size);
2090 info->mesh_data = GNUNET_malloc (sizeof (struct MeshData)); 1141 memcpy (data, message, size);
2091 info->mesh_data->data = GNUNET_malloc (size);
2092 memcpy (info->mesh_data->data, message, size);
2093 type = ntohs(message->type); 1142 type = ntohs(message->type);
2094 switch (type) 1143 if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type ||
1144 GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == type)
2095 { 1145 {
2096 struct GNUNET_MESH_Unicast *m; 1146 struct GNUNET_MESH_Data *u;
2097 struct GNUNET_MESH_ToOrigin *to;
2098 1147
2099 case GNUNET_MESSAGE_TYPE_MESH_UNICAST: 1148 u = (struct GNUNET_MESH_Data *) data;
2100 m = (struct GNUNET_MESH_Unicast *) info->mesh_data->data; 1149 u->ttl = htonl (ntohl (u->ttl) - 1);
2101 m->ttl = htonl (ntohl (m->ttl) - 1); 1150 }
2102 break; 1151 GNUNET_PEER_resolve (peer, &id);
2103 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: 1152 neighbor = peer_get (&id);
2104 to = (struct GNUNET_MESH_ToOrigin *) info->mesh_data->data;
2105 t->bck_pid++;
2106 to->pid = htonl(t->bck_pid);
2107 }
2108 info->mesh_data->data_len = size;
2109 info->mesh_data->reference_counter = 1;
2110 info->mesh_data->total_out = 1;
2111 neighbor = peer_info_get (peer);
2112 for (p = neighbor->path_head; NULL != p; p = p->next) 1153 for (p = neighbor->path_head; NULL != p; p = p->next)
2113 { 1154 {
2114 if (2 >= p->length) 1155 if (2 >= p->length)
@@ -2121,10 +1162,10 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2121#if MESH_DEBUG 1162#if MESH_DEBUG
2122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1163 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2123 " %s IS NOT DIRECTLY CONNECTED\n", 1164 " %s IS NOT DIRECTLY CONNECTED\n",
2124 GNUNET_i2s(peer)); 1165 GNUNET_i2s(&id));
2125 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1166 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2126 " PATHS TO %s:\n", 1167 " PATHS TO %s:\n",
2127 GNUNET_i2s(peer)); 1168 GNUNET_i2s(&id));
2128 for (p = neighbor->path_head; NULL != p; p = p->next) 1169 for (p = neighbor->path_head; NULL != p; p = p->next)
2129 { 1170 {
2130 struct GNUNET_PeerIdentity debug_id; 1171 struct GNUNET_PeerIdentity debug_id;
@@ -2143,18 +1184,15 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2143 } 1184 }
2144#endif 1185#endif
2145 GNUNET_break (0); // FIXME sometimes fails (testing disconnect?) 1186 GNUNET_break (0); // FIXME sometimes fails (testing disconnect?)
2146 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1187 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2147 " no direct connection to %s\n", 1188 " no direct connection to %s\n",
2148 GNUNET_i2s (peer)); 1189 GNUNET_i2s (&id));
2149 GNUNET_free (info->mesh_data->data); 1190 GNUNET_free (data);
2150 GNUNET_free (info->mesh_data);
2151 GNUNET_free (info);
2152 return; 1191 return;
2153 } 1192 }
2154 info->peer = neighbor;
2155 if (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK == type) 1193 if (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK == type)
2156 type = 0; 1194 type = 0;
2157 queue_add (info, 1195 queue_add (data,
2158 type, 1196 type,
2159 size, 1197 size,
2160 neighbor, 1198 neighbor,
@@ -2166,94 +1204,22 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2166 * Sends a CREATE PATH message for a path to a peer, properly registrating 1204 * Sends a CREATE PATH message for a path to a peer, properly registrating
2167 * all used resources. 1205 * all used resources.
2168 * 1206 *
2169 * @param peer PeerInfo of the final peer for whom this path is being created.
2170 * @param p Path itself.
2171 * @param t Tunnel for which the path is created. 1207 * @param t Tunnel for which the path is created.
2172 */ 1208 */
2173static void 1209static void
2174send_create_path (struct MeshPeerInfo *peer, struct MeshPeerPath *p, 1210send_create_path (struct MeshTunnel *t)
2175 struct MeshTunnel *t)
2176{ 1211{
2177 struct GNUNET_PeerIdentity id;
2178 struct MeshPathInfo *path_info;
2179 struct MeshPeerInfo *neighbor; 1212 struct MeshPeerInfo *neighbor;
2180 1213
2181 unsigned int i; 1214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send create path\n");
2182 1215 neighbor = peer_get_short (t->next_hop);
2183 if (NULL == p) 1216 queue_add (t,
2184 {
2185 p = tree_get_path_to_peer (t->tree, peer->id);
2186 if (NULL == p)
2187 {
2188 GNUNET_break (0);
2189 return;
2190 }
2191 }
2192 for (i = 0; i < p->length; i++)
2193 {
2194 if (p->peers[i] == myid)
2195 break;
2196 }
2197 if (i >= p->length - 1)
2198 {
2199 path_destroy (p);
2200 GNUNET_break (0);
2201 return;
2202 }
2203 GNUNET_PEER_resolve (p->peers[i + 1], &id);
2204
2205 path_info = GNUNET_malloc (sizeof (struct MeshPathInfo));
2206 path_info->path = p;
2207 path_info->t = t;
2208 neighbor = peer_info_get (&id);
2209 path_info->peer = neighbor;
2210 queue_add (path_info,
2211 GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 1217 GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE,
2212 sizeof (struct GNUNET_MESH_ManipulatePath) + 1218 sizeof (struct GNUNET_MESH_CreateTunnel) +
2213 (p->length * sizeof (struct GNUNET_PeerIdentity)), 1219 (t->path->length * sizeof (struct GNUNET_PeerIdentity)),
2214 neighbor, 1220 neighbor,
2215 t); 1221 t);
2216} 1222 t->state = MESH_TUNNEL_WAITING;
2217
2218
2219/**
2220 * Sends a DESTROY PATH message to free resources for a path in a tunnel
2221 *
2222 * @param t Tunnel whose path to destroy.
2223 * @param destination Short ID of the peer to whom the path to destroy.
2224 */
2225static void
2226send_destroy_path (struct MeshTunnel *t, GNUNET_PEER_Id destination)
2227{
2228 struct MeshPeerPath *p;
2229 size_t size;
2230
2231 p = tree_get_path_to_peer (t->tree, destination);
2232 if (NULL == p)
2233 {
2234 GNUNET_break (0);
2235 return;
2236 }
2237 size = sizeof (struct GNUNET_MESH_ManipulatePath);
2238 size += p->length * sizeof (struct GNUNET_PeerIdentity);
2239 {
2240 struct GNUNET_MESH_ManipulatePath *msg;
2241 struct GNUNET_PeerIdentity *pi;
2242 char cbuf[size];
2243 unsigned int i;
2244
2245 msg = (struct GNUNET_MESH_ManipulatePath *) cbuf;
2246 msg->header.size = htons (size);
2247 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY);
2248 msg->tid = htonl (t->id.tid);
2249 pi = (struct GNUNET_PeerIdentity *) &msg[1];
2250 for (i = 0; i < p->length; i++)
2251 {
2252 GNUNET_PEER_resolve (p->peers[i], &pi[i]);
2253 }
2254 send_prebuilt_message (&msg->header, tree_get_first_hop (t->tree, destination), t);
2255 }
2256 path_destroy (p);
2257} 1223}
2258 1224
2259 1225
@@ -2265,28 +1231,20 @@ send_destroy_path (struct MeshTunnel *t, GNUNET_PEER_Id destination)
2265static void 1231static void
2266send_path_ack (struct MeshTunnel *t) 1232send_path_ack (struct MeshTunnel *t)
2267{ 1233{
2268 struct MeshTransmissionDescriptor *info; 1234 struct MeshPeerInfo *peer;
2269 struct GNUNET_PeerIdentity id;
2270 GNUNET_PEER_Id peer;
2271 1235
2272 peer = tree_get_predecessor (t->tree); 1236 peer = peer_get_short (t->prev_hop);
2273 GNUNET_PEER_resolve (peer, &id);
2274 info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor));
2275 info->origin = &t->id;
2276 info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &id.hashPubKey);
2277 GNUNET_assert (NULL != info->peer);
2278 1237
2279 queue_add (info, 1238 queue_add (t,
2280 GNUNET_MESSAGE_TYPE_MESH_PATH_ACK, 1239 GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
2281 sizeof (struct GNUNET_MESH_PathACK), 1240 sizeof (struct GNUNET_MESH_PathACK),
2282 info->peer, 1241 peer,
2283 t); 1242 t);
2284} 1243}
2285 1244
2286 1245
2287/** 1246/**
2288 * Try to establish a new connection to this peer. 1247 * Try to establish a new connection to this peer in the given tunnel.
2289 * Use the best path for the given tunnel.
2290 * If the peer doesn't have any path to it yet, try to get one. 1248 * If the peer doesn't have any path to it yet, try to get one.
2291 * If the peer already has some path, send a CREATE PATH towards it. 1249 * If the peer already has some path, send a CREATE PATH towards it.
2292 * 1250 *
@@ -2294,90 +1252,39 @@ send_path_ack (struct MeshTunnel *t)
2294 * @param t Tunnel for which to create the path, if possible. 1252 * @param t Tunnel for which to create the path, if possible.
2295 */ 1253 */
2296static void 1254static void
2297peer_info_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t) 1255peer_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t)
2298{ 1256{
2299 struct MeshPeerPath *p; 1257 struct MeshPeerPath *p;
2300 struct MeshPathInfo *path_info;
2301 1258
2302 if (NULL != peer->path_head) 1259 if (NULL != peer->path_head)
2303 { 1260 {
2304 p = tree_get_path_to_peer (t->tree, peer->id); 1261 p = peer_get_best_path (peer, t);
2305 if (NULL == p) 1262 tunnel_use_path (t, p);
2306 { 1263 send_create_path (t);
2307 GNUNET_break (0);
2308 return;
2309 }
2310
2311 // FIXME always send create path to self
2312 if (p->length > 1)
2313 {
2314 send_create_path (peer, p, t);
2315 }
2316 else
2317 {
2318 struct GNUNET_HashCode hash;
2319
2320 path_destroy (p);
2321 send_client_peer_connected (t, myid);
2322 t->local_tid_dest = next_local_tid++;
2323 GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber),
2324 &hash);
2325 if (GNUNET_OK !=
2326 GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
2327 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
2328 {
2329 GNUNET_break (0);
2330 return;
2331 }
2332 }
2333 } 1264 }
2334 else if (NULL == peer->dhtget) 1265 else if (NULL == peer->dhtget)
2335 { 1266 {
2336 struct GNUNET_PeerIdentity id; 1267 struct GNUNET_PeerIdentity id;
2337 1268
2338 GNUNET_PEER_resolve (peer->id, &id); 1269 GNUNET_PEER_resolve (peer->id, &id);
2339 path_info = GNUNET_malloc (sizeof (struct MeshPathInfo));
2340 path_info->peer = peer;
2341 path_info->t = t;
2342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1270 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2343 " Starting DHT GET for peer %s\n", GNUNET_i2s (&id)); 1271 " Starting DHT GET for peer %s\n", GNUNET_i2s (&id));
2344 peer->dhtgetcls = path_info;
2345 peer->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */ 1272 peer->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */
2346 GNUNET_BLOCK_TYPE_MESH_PEER, /* type */ 1273 GNUNET_BLOCK_TYPE_MESH_PEER, /* type */
2347 &id.hashPubKey, /* key to search */ 1274 &id.hashPubKey, /* key to search */
2348 dht_replication_level, /* replication level */ 1275 dht_replication_level, /* replication level */
2349 GNUNET_DHT_RO_RECORD_ROUTE | 1276 GNUNET_DHT_RO_RECORD_ROUTE |
2350 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, 1277 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
2351 NULL, /* xquery */ // FIXME BLOOMFILTER 1278 NULL, /* xquery */
2352 0, /* xquery bits */ // FIXME BLOOMFILTER SIZE 1279 0, /* xquery bits */
2353 &dht_get_id_handler, path_info); 1280 &dht_get_id_handler, peer);
1281 t->state = MESH_TUNNEL_SEARCHING;
2354 } 1282 }
2355 /* Otherwise, there is no path but the DHT get is already started. */ 1283 else
2356}
2357
2358
2359/**
2360 * Task to delay the connection of a peer
2361 *
2362 * @param cls Closure (path info with tunnel and peer to connect).
2363 * Will be free'd on exection.
2364 * @param tc TaskContext
2365 */
2366static void
2367peer_info_connect_task (void *cls,
2368 const struct GNUNET_SCHEDULER_TaskContext *tc)
2369{
2370 struct MeshPathInfo *path_info = cls;
2371
2372 path_info->peer->connect_task = GNUNET_SCHEDULER_NO_TASK;
2373
2374 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
2375 { 1284 {
2376 GNUNET_free (cls); 1285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2377 return; 1286 "There is no path but the DHT GET is already started.\n");
2378 } 1287 }
2379 peer_info_connect (path_info->peer, path_info->t);
2380 GNUNET_free (cls);
2381} 1288}
2382 1289
2383 1290
@@ -2394,6 +1301,7 @@ peer_info_destroy (struct MeshPeerInfo *pi)
2394 struct GNUNET_PeerIdentity id; 1301 struct GNUNET_PeerIdentity id;
2395 struct MeshPeerPath *p; 1302 struct MeshPeerPath *p;
2396 struct MeshPeerPath *nextp; 1303 struct MeshPeerPath *nextp;
1304 unsigned int i;
2397 1305
2398 GNUNET_PEER_resolve (pi->id, &id); 1306 GNUNET_PEER_resolve (pi->id, &id);
2399 GNUNET_PEER_change_rc (pi->id, -1); 1307 GNUNET_PEER_change_rc (pi->id, -1);
@@ -2408,7 +1316,6 @@ peer_info_destroy (struct MeshPeerInfo *pi)
2408 if (NULL != pi->dhtget) 1316 if (NULL != pi->dhtget)
2409 { 1317 {
2410 GNUNET_DHT_get_stop (pi->dhtget); 1318 GNUNET_DHT_get_stop (pi->dhtget);
2411 GNUNET_free (pi->dhtgetcls);
2412 } 1319 }
2413 p = pi->path_head; 1320 p = pi->path_head;
2414 while (NULL != p) 1321 while (NULL != p)
@@ -2418,10 +1325,9 @@ peer_info_destroy (struct MeshPeerInfo *pi)
2418 path_destroy (p); 1325 path_destroy (p);
2419 p = nextp; 1326 p = nextp;
2420 } 1327 }
2421 if (GNUNET_SCHEDULER_NO_TASK != pi->connect_task) 1328 for (i = 0; i < pi->ntunnels; i++)
2422 { 1329 tunnel_destroy_empty (pi->tunnels[i]);
2423 GNUNET_free (GNUNET_SCHEDULER_cancel (pi->connect_task)); 1330 GNUNET_array_grow (pi->tunnels, pi->ntunnels, 0);
2424 }
2425 GNUNET_free (pi); 1331 GNUNET_free (pi);
2426 return GNUNET_OK; 1332 return GNUNET_OK;
2427} 1333}
@@ -2439,24 +1345,21 @@ peer_info_destroy (struct MeshPeerInfo *pi)
2439 * TODO: optimize (see below) 1345 * TODO: optimize (see below)
2440 */ 1346 */
2441static void 1347static void
2442peer_info_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1, 1348peer_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1,
2443 GNUNET_PEER_Id p2) 1349 GNUNET_PEER_Id p2)
2444{ 1350{
2445 struct MeshPeerPath *p; 1351 struct MeshPeerPath *p;
2446 struct MeshPeerPath *aux; 1352 struct MeshPeerPath *next;
2447 struct MeshPeerInfo *peer_d; 1353 struct MeshPeerInfo *peer_d;
2448 GNUNET_PEER_Id d; 1354 GNUNET_PEER_Id d;
2449 unsigned int destroyed; 1355 unsigned int destroyed;
2450 unsigned int best;
2451 unsigned int cost;
2452 unsigned int i; 1356 unsigned int i;
2453 1357
2454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path\n"); 1358 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path\n");
2455 destroyed = 0; 1359 destroyed = 0;
2456 p = peer->path_head; 1360 for (p = peer->path_head; NULL != p; p = next)
2457 while (NULL != p)
2458 { 1361 {
2459 aux = p->next; 1362 next = p->next;
2460 for (i = 0; i < (p->length - 1); i++) 1363 for (i = 0; i < (p->length - 1); i++)
2461 { 1364 {
2462 if ((p->peers[i] == p1 && p->peers[i + 1] == p2) || 1365 if ((p->peers[i] == p1 && p->peers[i + 1] == p2) ||
@@ -2468,7 +1371,6 @@ peer_info_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1,
2468 break; 1371 break;
2469 } 1372 }
2470 } 1373 }
2471 p = aux;
2472 } 1374 }
2473 if (0 == destroyed) 1375 if (0 == destroyed)
2474 return; 1376 return;
@@ -2478,39 +1380,11 @@ peer_info_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1,
2478 d = tunnel_notify_connection_broken (peer->tunnels[i], p1, p2); 1380 d = tunnel_notify_connection_broken (peer->tunnels[i], p1, p2);
2479 if (0 == d) 1381 if (0 == d)
2480 continue; 1382 continue;
2481 /* TODO 1383
2482 * Problem: one or more peers have been deleted from the tunnel tree. 1384 peer_d = peer_get_short (d);
2483 * We don't know who they are to try to add them again. 1385 next = peer_get_best_path (peer_d, peer->tunnels[i]);
2484 * We need to try to find a new path for each of the disconnected peers. 1386 tunnel_use_path (peer->tunnels[i], next);
2485 * Some of them might already have a path to reach them that does not 1387 peer_connect (peer_d, peer->tunnels[i]);
2486 * involve p1 and p2. Adding all anew might render in a better tree than
2487 * the trivial immediate fix.
2488 *
2489 * Trivial immiediate fix: try to reconnect to the disconnected node. All
2490 * its children will be reachable trough him.
2491 */
2492 peer_d = peer_info_get_short (d);
2493 best = UINT_MAX;
2494 aux = NULL;
2495 for (p = peer_d->path_head; NULL != p; p = p->next)
2496 {
2497 if ((cost = tree_get_path_cost (peer->tunnels[i]->tree, p)) < best)
2498 {
2499 best = cost;
2500 aux = p;
2501 }
2502 }
2503 if (NULL != aux)
2504 {
2505 /* No callback, as peer will be already disconnected and a connection
2506 * scheduled by tunnel_notify_connection_broken.
2507 */
2508 tree_add_path (peer->tunnels[i]->tree, aux, NULL, NULL);
2509 }
2510 else
2511 {
2512 peer_info_connect (peer_d, peer->tunnels[i]);
2513 }
2514 } 1388 }
2515 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path END\n"); 1389 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path END\n");
2516} 1390}
@@ -2545,13 +1419,12 @@ peer_info_add_path (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path,
2545 path_destroy (path); 1419 path_destroy (path);
2546 return; 1420 return;
2547 } 1421 }
2548 if (path->length <= 2 && GNUNET_NO == trusted) 1422 if (2 >= path->length && GNUNET_NO == trusted)
2549 { 1423 {
2550 /* Only allow CORE to tell us about direct paths */ 1424 /* Only allow CORE to tell us about direct paths */
2551 path_destroy (path); 1425 path_destroy (path);
2552 return; 1426 return;
2553 } 1427 }
2554 GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
2555 for (l = 1; l < path->length; l++) 1428 for (l = 1; l < path->length; l++)
2556 { 1429 {
2557 if (path->peers[l] == myid) 1430 if (path->peers[l] == myid)
@@ -2579,7 +1452,7 @@ peer_info_add_path (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path,
2579 l = path_get_length (path); 1452 l = path_get_length (path);
2580 if (0 == l) 1453 if (0 == l)
2581 { 1454 {
2582 GNUNET_free (path); 1455 path_destroy (path);
2583 return; 1456 return;
2584 } 1457 }
2585 1458
@@ -2616,6 +1489,7 @@ peer_info_add_path (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path,
2616 * 1489 *
2617 * @param peer_info Peer to add the path to, being the origin of the path. 1490 * @param peer_info Peer to add the path to, being the origin of the path.
2618 * @param path New path to add after being inversed. 1491 * @param path New path to add after being inversed.
1492 * Path will be either used or freed.
2619 * @param trusted Do we trust that this path is real? 1493 * @param trusted Do we trust that this path is real?
2620 */ 1494 */
2621static void 1495static void
@@ -2628,40 +1502,98 @@ peer_info_add_path_to_origin (struct MeshPeerInfo *peer_info,
2628 1502
2629 1503
2630/** 1504/**
1505 * Add a tunnel to the list of tunnels a peer participates in.
1506 * Update the tunnel's destination.
1507 *
1508 * @param p Peer to add to.
1509 * @param t Tunnel to add.
1510 */
1511static void
1512peer_info_add_tunnel (struct MeshPeerInfo *p, struct MeshTunnel *t)
1513{
1514 if (0 != t->dest)
1515 {
1516 GNUNET_break (t->dest == p->id);
1517 return;
1518 }
1519 t->dest = p->id;
1520 GNUNET_PEER_change_rc (t->dest, 1);
1521 GNUNET_array_append (p->tunnels, p->ntunnels, t);
1522}
1523
1524
1525/**
1526 * Remove a tunnel from the list of tunnels a peer participates in.
1527 * Free the tunnel's destination.
1528 *
1529 * @param p Peer to clean.
1530 * @param t Tunnel to remove.
1531 */
1532static void
1533peer_info_remove_tunnel (struct MeshPeerInfo *p, struct MeshTunnel *t)
1534{
1535 unsigned int i;
1536
1537 if (t->dest == p->id)
1538 {
1539 GNUNET_PEER_change_rc (t->dest, -1);
1540 t->dest = 0;
1541 }
1542 for (i = 0; i < p->ntunnels; i++)
1543 {
1544 if (p->tunnels[i] == t)
1545 {
1546 p->tunnels[i] = p->tunnels[p->ntunnels - 1];
1547 GNUNET_array_grow (p->tunnels, p->ntunnels, p->ntunnels - 1);
1548 return;
1549 }
1550 }
1551}
1552
1553
1554/**
2631 * Function called if the connection to the peer has been stalled for a while, 1555 * Function called if the connection to the peer has been stalled for a while,
2632 * possibly due to a missed ACK. Poll the peer about its ACK status. 1556 * possibly due to a missed ACK. Poll the peer about its ACK status.
2633 * 1557 *
2634 * @param cls Closure (cinfo). 1558 * @param cls Closure (poll ctx).
2635 * @param tc TaskContext. 1559 * @param tc TaskContext.
2636 */ 1560 */
2637static void 1561static void
2638tunnel_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 1562tunnel_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2639{ 1563{
2640 struct MeshTunnelChildInfo *cinfo = cls; 1564 struct MeshFlowControl *fc = cls;
2641 struct GNUNET_MESH_Poll msg; 1565 struct GNUNET_MESH_Poll msg;
2642 struct GNUNET_PeerIdentity id; 1566 struct MeshTunnel *t = fc->t;
2643 struct MeshTunnel *t; 1567 GNUNET_PEER_Id peer;
2644 1568
2645 cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK; 1569 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
2646 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) 1570 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
2647 { 1571 {
2648 return; 1572 return;
2649 } 1573 }
2650 1574
2651 t = cinfo->t;
2652 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL); 1575 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL);
2653 msg.header.size = htons (sizeof (msg)); 1576 msg.header.size = htons (sizeof (msg));
2654 msg.tid = htonl (t->id.tid); 1577 msg.tid = htonl (t->id.tid);
2655 GNUNET_PEER_resolve (t->id.oid, &msg.oid); 1578 GNUNET_PEER_resolve (t->id.oid, &msg.oid);
2656 msg.last_ack = htonl (cinfo->fwd_ack); 1579
2657 1580 if (fc == &t->prev_fc)
2658 GNUNET_PEER_resolve (cinfo->id, &id); 1581 {
2659 send_prebuilt_message (&msg.header, &id, cinfo->t); 1582 peer = t->prev_hop;
2660 cinfo->fc_poll_time = GNUNET_TIME_relative_min ( 1583 }
2661 MESH_MAX_POLL_TIME, 1584 else if (fc == &t->next_fc)
2662 GNUNET_TIME_relative_multiply (cinfo->fc_poll_time, 2)); 1585 {
2663 cinfo->fc_poll = GNUNET_SCHEDULER_add_delayed (cinfo->fc_poll_time, 1586 peer = t->next_hop;
2664 &tunnel_poll, cinfo); 1587 }
1588 else
1589 {
1590 GNUNET_break (0);
1591 return;
1592 }
1593 send_prebuilt_message (&msg.header, peer, t);
1594 fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
1595 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
1596 &tunnel_poll, fc);
2665} 1597}
2666 1598
2667 1599
@@ -2770,10 +1702,10 @@ path_add_to_peers (struct MeshPeerPath *p, int confirmed)
2770 struct MeshPeerInfo *aux; 1702 struct MeshPeerInfo *aux;
2771 struct MeshPeerPath *copy; 1703 struct MeshPeerPath *copy;
2772 1704
2773 aux = peer_info_get_short (p->peers[i]); 1705 aux = peer_get_short (p->peers[i]);
2774 copy = path_duplicate (p); 1706 copy = path_duplicate (p);
2775 copy->length = i + 1; 1707 copy->length = i + 1;
2776 peer_info_add_path (aux, copy, GNUNET_NO); 1708 peer_info_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed);
2777 } 1709 }
2778} 1710}
2779 1711
@@ -2783,8 +1715,6 @@ path_add_to_peers (struct MeshPeerPath *p, int confirmed)
2783 * 1715 *
2784 * @param cls Closure (tunnel for which to send the keepalive). 1716 * @param cls Closure (tunnel for which to send the keepalive).
2785 * @param tc Notification context. 1717 * @param tc Notification context.
2786 *
2787 * TODO: implement explicit multicast keepalive?
2788 */ 1718 */
2789static void 1719static void
2790path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); 1720path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
@@ -2803,7 +1733,7 @@ tunnel_get_incoming (MESH_TunnelNumber tid)
2803 struct GNUNET_HashCode hash; 1733 struct GNUNET_HashCode hash;
2804 1734
2805 GNUNET_assert (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV); 1735 GNUNET_assert (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV);
2806 GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash); 1736 GMC_hash32 (tid, &hash);
2807 return GNUNET_CONTAINER_multihashmap_get (incoming_tunnels, &hash); 1737 return GNUNET_CONTAINER_multihashmap_get (incoming_tunnels, &hash);
2808} 1738}
2809 1739
@@ -2827,7 +1757,7 @@ tunnel_get_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
2827 { 1757 {
2828 struct GNUNET_HashCode hash; 1758 struct GNUNET_HashCode hash;
2829 1759
2830 GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash); 1760 GMC_hash32 (tid, &hash);
2831 return GNUNET_CONTAINER_multihashmap_get (c->own_tunnels, &hash); 1761 return GNUNET_CONTAINER_multihashmap_get (c->own_tunnels, &hash);
2832 } 1762 }
2833} 1763}
@@ -2871,240 +1801,77 @@ tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
2871 1801
2872 1802
2873/** 1803/**
2874 * Delete an active client from the tunnel. 1804 * Add a client to a tunnel, initializing all needed data structures.
2875 *
2876 * @param t Tunnel.
2877 * @param c Client.
2878 */
2879static void
2880tunnel_delete_active_client (struct MeshTunnel *t, const struct MeshClient *c)
2881{
2882 unsigned int i;
2883
2884 for (i = 0; i < t->nclients; i++)
2885 {
2886 if (t->clients[i] == c)
2887 {
2888 t->clients[i] = t->clients[t->nclients - 1];
2889 t->clients_fc[i] = t->clients_fc[t->nclients - 1];
2890 GNUNET_array_grow (t->clients, t->nclients, t->nclients - 1);
2891 t->nclients++;
2892 GNUNET_array_grow (t->clients_fc, t->nclients, t->nclients - 1);
2893 break;
2894 }
2895 }
2896}
2897
2898
2899/**
2900 * Delete an ignored client from the tunnel.
2901 * 1805 *
2902 * @param t Tunnel. 1806 * @param t Tunnel to which add the client.
2903 * @param c Client. 1807 * @param c Client which to add to the tunnel.
2904 */ 1808 */
2905static void 1809static void
2906tunnel_delete_ignored_client (struct MeshTunnel *t, const struct MeshClient *c) 1810tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c)
2907{ 1811{
2908 unsigned int i; 1812 struct GNUNET_HashCode hash;
2909 1813
2910 for (i = 0; i < t->nignore; i++) 1814 if (NULL != t->client)
2911 { 1815 {
2912 if (t->ignore[i] == c) 1816 GNUNET_break(0);
2913 { 1817 return;
2914 t->ignore[i] = t->ignore[t->nignore - 1];
2915 GNUNET_array_grow (t->ignore, t->nignore, t->nignore - 1);
2916 break;
2917 }
2918 } 1818 }
2919} 1819 GMC_hash32 (t->local_tid_dest, &hash);
2920 1820 if (GNUNET_OK !=
2921 1821 GNUNET_CONTAINER_multihashmap_put (c->incoming_tunnels, &hash, t,
2922/** 1822 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
2923 * Delete a client from the tunnel. It should be only done on
2924 * client disconnection, otherwise use client_ignore_tunnel.
2925 *
2926 * @param t Tunnel.
2927 * @param c Client.
2928 */
2929static void
2930tunnel_delete_client (struct MeshTunnel *t, const struct MeshClient *c)
2931{
2932 tunnel_delete_ignored_client (t, c);
2933 tunnel_delete_active_client (t, c);
2934}
2935
2936
2937/**
2938 * @brief Iterator to destroy MeshTunnelChildInfo of tunnel children.
2939 *
2940 * Destroys queue elements of all waiting transmissions and frees all memory
2941 * used by the struct and its elements.
2942 *
2943 * @param cls Closure (tunnel info).
2944 * @param key Hash of GNUNET_PEER_Id (unused).
2945 * @param value MeshTunnelChildInfo of the child.
2946 *
2947 * @return always GNUNET_YES, to keep iterating
2948 */
2949static int
2950tunnel_destroy_child (void *cls,
2951 const struct GNUNET_HashCode * key,
2952 void *value)
2953{
2954 struct MeshTunnelChildInfo *cinfo = value;
2955 struct MeshTunnel *t = cls;
2956 struct MeshPeerQueue *q;
2957 unsigned int c;
2958 unsigned int i;
2959
2960 for (c = 0; c < cinfo->send_buffer_n; c++)
2961 { 1823 {
2962 i = (cinfo->send_buffer_start + c) % t->fwd_queue_max; 1824 GNUNET_break (0);
2963 q = cinfo->send_buffer[i]; 1825 return;
2964 cinfo->send_buffer[i] = NULL;
2965 if (NULL != q)
2966 queue_destroy (q, GNUNET_YES);
2967 else
2968 GNUNET_break (0);
2969 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u %u\n", c, cinfo->send_buffer_n);
2970 } 1826 }
2971 GNUNET_free_non_null (cinfo->send_buffer); 1827 if (GNUNET_OK !=
2972 if (GNUNET_SCHEDULER_NO_TASK != cinfo->fc_poll) 1828 GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
1829 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
2973 { 1830 {
2974 GNUNET_SCHEDULER_cancel (cinfo->fc_poll); 1831 GNUNET_break (0);
2975 cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK; 1832 return;
2976 } 1833 }
2977 GNUNET_free (cinfo); 1834 t->client = c;
2978 return GNUNET_YES;
2979} 1835}
2980 1836
2981 1837
2982/**
2983 * Callback used to notify a client owner of a tunnel that a peer has
2984 * disconnected, most likely because of a path change.
2985 *
2986 * @param cls Closure (tunnel this notification is about).
2987 * @param peer_id Short ID of disconnected peer.
2988 */
2989void
2990tunnel_notify_client_peer_disconnected (void *cls, GNUNET_PEER_Id peer_id)
2991{
2992 struct MeshTunnel *t = cls;
2993 struct MeshPeerInfo *peer;
2994 struct MeshPathInfo *path_info;
2995
2996 client_notify_peer_disconnected (t->owner, t, peer_id);
2997
2998 peer = peer_info_get_short (peer_id);
2999 path_info = GNUNET_malloc (sizeof (struct MeshPathInfo));
3000 path_info->peer = peer;
3001 path_info->t = t;
3002 peer->connect_task = GNUNET_SCHEDULER_add_now (&peer_info_connect_task,
3003 path_info);
3004}
3005
3006
3007/**
3008 * Add a peer to a tunnel, accomodating paths accordingly and initializing all
3009 * needed rescources.
3010 * If peer already exists, reevaluate shortest path and change if different.
3011 *
3012 * @param t Tunnel we want to add a new peer to
3013 * @param peer PeerInfo of the peer being added
3014 *
3015 */
3016static void 1838static void
3017tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer) 1839tunnel_use_path (struct MeshTunnel *t, struct MeshPeerPath *p)
3018{ 1840{
3019 struct GNUNET_PeerIdentity id; 1841 unsigned int own_pos;
3020 struct MeshPeerPath *best_p;
3021 struct MeshPeerPath *p;
3022 unsigned int best_cost;
3023 unsigned int cost;
3024
3025 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_peer\n");
3026 GNUNET_PEER_resolve (peer->id, &id);
3027 if (GNUNET_NO ==
3028 GNUNET_CONTAINER_multihashmap_contains (t->peers, &id.hashPubKey))
3029 {
3030 GNUNET_array_append (peer->tunnels, peer->ntunnels, t);
3031 GNUNET_assert (GNUNET_OK ==
3032 GNUNET_CONTAINER_multihashmap_put (t->peers, &id.hashPubKey,
3033 peer,
3034 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
3035 }
3036 1842
3037 if (NULL != (p = peer->path_head)) 1843 for (own_pos = 0; own_pos < p->length; own_pos++)
3038 { 1844 {
3039 best_p = p; 1845 if (p->peers[own_pos] == myid)
3040 best_cost = tree_get_path_cost (t->tree, p); 1846 break;
3041 while (NULL != p)
3042 {
3043 if ((cost = tree_get_path_cost (t->tree, p)) < best_cost)
3044 {
3045 best_cost = cost;
3046 best_p = p;
3047 }
3048 p = p->next;
3049 }
3050 tree_add_path (t->tree, best_p, &tunnel_notify_client_peer_disconnected, t);
3051 if (GNUNET_SCHEDULER_NO_TASK == t->path_refresh_task)
3052 t->path_refresh_task =
3053 GNUNET_SCHEDULER_add_delayed (refresh_path_time, &path_refresh, t);
3054 } 1847 }
3055 else 1848 if (own_pos > p->length - 1)
3056 { 1849 {
3057 /* Start a DHT get */ 1850 GNUNET_break (0);
3058 peer_info_connect (peer, t); 1851 return;
3059 } 1852 }
3060 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_peer END\n");
3061}
3062
3063/**
3064 * Add a path to a tunnel which we don't own, just to remember the next hop.
3065 * If destination node was already in the tunnel, the first hop information
3066 * will be replaced with the new path.
3067 *
3068 * @param t Tunnel we want to add a new peer to
3069 * @param p Path to add
3070 * @param own_pos Position of local node in path.
3071 *
3072 */
3073static void
3074tunnel_add_path (struct MeshTunnel *t, struct MeshPeerPath *p,
3075 unsigned int own_pos)
3076{
3077 struct GNUNET_PeerIdentity id;
3078 1853
3079 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_path\n");
3080 GNUNET_assert (0 != own_pos);
3081 tree_add_path (t->tree, p, NULL, NULL);
3082 if (own_pos < p->length - 1) 1854 if (own_pos < p->length - 1)
1855 t->next_hop = p->peers[own_pos + 1];
1856 else
1857 t->next_hop = p->peers[own_pos];
1858 GNUNET_PEER_change_rc (t->next_hop, 1);
1859 if (0 < own_pos)
1860 t->prev_hop = p->peers[own_pos - 1];
1861 else
1862 t->prev_hop = p->peers[0];
1863 GNUNET_PEER_change_rc (t->prev_hop, 1);
1864
1865 if (NULL != t->path)
1866 path_destroy (t->path);
1867 t->path = path_duplicate (p);
1868 if (0 == own_pos)
3083 { 1869 {
3084 GNUNET_PEER_resolve (p->peers[own_pos + 1], &id); 1870 if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task)
3085 tree_update_first_hops (t->tree, myid, &id); 1871 GNUNET_SCHEDULER_cancel (t->maintenance_task);
1872 t->maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_path_time,
1873 &path_refresh, t);
3086 } 1874 }
3087 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_path END\n");
3088}
3089
3090/**
3091 * Add a client to a tunnel, initializing all needed data structures.
3092 *
3093 * @param t Tunnel to which add the client.
3094 * @param c Client which to add to the tunnel.
3095 */
3096static void
3097tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c)
3098{
3099 struct MeshTunnelClientInfo clinfo;
3100
3101 GNUNET_array_append (t->clients, t->nclients, c);
3102 clinfo.fwd_ack = t->fwd_pid + 1;
3103 clinfo.bck_ack = t->nobuffer ? 1 : INITIAL_WINDOW_SIZE - 1;
3104 clinfo.fwd_pid = t->fwd_pid;
3105 clinfo.bck_pid = (uint32_t) -1; // Expected next: 0
3106 t->nclients--;
3107 GNUNET_array_append (t->clients_fc, t->nclients, clinfo);
3108} 1875}
3109 1876
3110 1877
@@ -3125,452 +1892,27 @@ static GNUNET_PEER_Id
3125tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1, 1892tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
3126 GNUNET_PEER_Id p2) 1893 GNUNET_PEER_Id p2)
3127{ 1894{
3128 GNUNET_PEER_Id pid; 1895// if (myid != p1 && myid != p2) FIXME
3129 1896// {
3130 pid = 1897// return;
3131 tree_notify_connection_broken (t->tree, p1, p2, 1898// }
3132 &tunnel_notify_client_peer_disconnected, 1899//
3133 t); 1900// if (tree_get_predecessor (t->tree) != 0)
3134 if (myid != p1 && myid != p2) 1901// {
3135 { 1902// /* We are the peer still connected, notify owner of the disconnection. */
3136 return pid; 1903// struct GNUNET_MESH_PathBroken msg;
3137 } 1904// struct GNUNET_PeerIdentity neighbor;
3138 if (pid != myid) 1905//
3139 { 1906// msg.header.size = htons (sizeof (msg));
3140 if (tree_get_predecessor (t->tree) != 0) 1907// msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN);
3141 { 1908// GNUNET_PEER_resolve (t->id.oid, &msg.oid);
3142 /* We are the peer still connected, notify owner of the disconnection. */ 1909// msg.tid = htonl (t->id.tid);
3143 struct GNUNET_MESH_PathBroken msg; 1910// msg.peer1 = my_full_id;
3144 struct GNUNET_PeerIdentity neighbor; 1911// GNUNET_PEER_resolve (pid, &msg.peer2);
3145 1912// GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor);
3146 msg.header.size = htons (sizeof (msg)); 1913// send_prebuilt_message (&msg.header, &neighbor, t);
3147 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN); 1914// }
3148 GNUNET_PEER_resolve (t->id.oid, &msg.oid); 1915 return 0;
3149 msg.tid = htonl (t->id.tid);
3150 msg.peer1 = my_full_id;
3151 GNUNET_PEER_resolve (pid, &msg.peer2);
3152 GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor);
3153 send_prebuilt_message (&msg.header, &neighbor, t);
3154 }
3155 }
3156 return pid;
3157}
3158
3159
3160/**
3161 * Send a multicast packet to a neighbor.
3162 *
3163 * @param cls Closure (Info about the multicast packet)
3164 * @param neighbor_id Short ID of the neighbor to send the packet to.
3165 */
3166static void
3167tunnel_send_multicast_iterator (void *cls, GNUNET_PEER_Id neighbor_id)
3168{
3169 struct MeshData *mdata = cls;
3170 struct MeshTransmissionDescriptor *info;
3171 struct GNUNET_PeerIdentity neighbor;
3172 struct GNUNET_MessageHeader *msg;
3173
3174 info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor));
3175
3176 info->mesh_data = mdata;
3177 (mdata->reference_counter) ++;
3178 info->destination = neighbor_id;
3179 GNUNET_PEER_resolve (neighbor_id, &neighbor);
3180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending to %s...\n",
3181 GNUNET_i2s (&neighbor));
3182 info->peer = peer_info_get (&neighbor);
3183 GNUNET_assert (NULL != info->peer);
3184 msg = (struct GNUNET_MessageHeader *) mdata->data;
3185 queue_add(info,
3186 ntohs (msg->type),
3187 info->mesh_data->data_len,
3188 info->peer,
3189 mdata->t);
3190}
3191
3192
3193/**
3194 * Queue a message in a tunnel in multicast, sending a copy to each child node
3195 * down the local one in the tunnel tree.
3196 *
3197 * @param t Tunnel in which to send the data.
3198 * @param msg Message to be sent.
3199 */
3200static void
3201tunnel_send_multicast (struct MeshTunnel *t,
3202 const struct GNUNET_MessageHeader *msg)
3203{
3204 struct MeshData *mdata;
3205
3206 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3207 " sending a multicast packet...\n");
3208
3209 mdata = GNUNET_malloc (sizeof (struct MeshData));
3210 mdata->data_len = ntohs (msg->size);
3211 mdata->t = t;
3212 mdata->data = GNUNET_malloc (mdata->data_len);
3213 memcpy (mdata->data, msg, mdata->data_len);
3214 if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_MESH_MULTICAST)
3215 {
3216 struct GNUNET_MESH_Multicast *mcast;
3217
3218 mcast = (struct GNUNET_MESH_Multicast *) mdata->data;
3219 if (t->fwd_queue_n >= t->fwd_queue_max)
3220 {
3221 GNUNET_break (0);
3222 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " queue full!\n");
3223 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3224 " message from %s!\n",
3225 GNUNET_i2s(&mcast->oid));
3226 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3227 " message at %s!\n",
3228 GNUNET_i2s(&my_full_id));
3229 GNUNET_free (mdata->data);
3230 GNUNET_free (mdata);
3231 return;
3232 }
3233 t->fwd_queue_n++;
3234 mcast->ttl = htonl (ntohl (mcast->ttl) - 1);
3235 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " data packet, ttl: %u\n",
3236 ntohl (mcast->ttl));
3237 }
3238 else
3239 {
3240 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not a data packet, no ttl\n");
3241 }
3242
3243 tree_iterate_children (t->tree, &tunnel_send_multicast_iterator, mdata);
3244 if (mdata->reference_counter == 0)
3245 {
3246 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3247 " no one to send data to\n");
3248 GNUNET_free (mdata->data);
3249 GNUNET_free (mdata);
3250 if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_MESH_MULTICAST)
3251 t->fwd_queue_n--;
3252 }
3253 else
3254 {
3255 mdata->total_out = mdata->reference_counter;
3256 }
3257 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3258 " sending a multicast packet done\n");
3259 return;
3260}
3261
3262
3263/**
3264 * Increase the SKIP value of all peers that
3265 * have not received a unicast message.
3266 *
3267 * @param cls Closure (ID of the peer that HAS received the message).
3268 * @param key ID of the neighbor.
3269 * @param value Information about the neighbor.
3270 *
3271 * @return GNUNET_YES to keep iterating.
3272 */
3273static int
3274tunnel_add_skip (void *cls,
3275 const struct GNUNET_HashCode * key,
3276 void *value)
3277{
3278 struct GNUNET_PeerIdentity *neighbor = cls;
3279 struct MeshTunnelChildInfo *cinfo = value;
3280
3281 /* TODO compare only pointers? key == neighbor? */
3282 if (0 == memcmp (&neighbor->hashPubKey, key, sizeof (struct GNUNET_HashCode)))
3283 {
3284 return GNUNET_YES;
3285 }
3286 cinfo->skip++;
3287 return GNUNET_YES;
3288}
3289
3290
3291/**
3292 * @brief Get neighbor's Flow Control information.
3293 *
3294 * Retrieves the MeshTunnelChildInfo containing Flow Control data about a direct
3295 * descendant of the local node in a certain tunnel.
3296 * If the info is not yet there (recently created path), creates the data struct
3297 * and inserts it into the tunnel info, initialized to the current tunnel ACK
3298 * values.
3299 *
3300 * @param t Tunnel related.
3301 * @param peer Neighbor whose Flow Control info is needed.
3302 *
3303 * @return Neighbor's Flow Control info.
3304 */
3305static struct MeshTunnelChildInfo *
3306tunnel_get_neighbor_fc (struct MeshTunnel *t,
3307 const struct GNUNET_PeerIdentity *peer)
3308{
3309 struct MeshTunnelChildInfo *cinfo;
3310
3311 if (NULL == t->children_fc)
3312 return NULL;
3313
3314 cinfo = GNUNET_CONTAINER_multihashmap_get (t->children_fc,
3315 &peer->hashPubKey);
3316 if (NULL == cinfo)
3317 {
3318 uint32_t delta;
3319
3320 cinfo = GNUNET_malloc (sizeof (struct MeshTunnelChildInfo));
3321 cinfo->id = GNUNET_PEER_intern (peer);
3322 cinfo->skip = t->fwd_pid;
3323 cinfo->t = t;
3324
3325 delta = t->nobuffer ? 1 : INITIAL_WINDOW_SIZE;
3326 cinfo->fwd_ack = t->fwd_pid + delta;
3327 cinfo->bck_ack = delta;
3328 cinfo->bck_pid = -1;
3329
3330 cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK;
3331 cinfo->fc_poll_time = GNUNET_TIME_UNIT_SECONDS;
3332
3333 cinfo->send_buffer =
3334 GNUNET_malloc (sizeof(struct MeshPeerQueue *) * t->fwd_queue_max);
3335
3336 GNUNET_assert (GNUNET_OK ==
3337 GNUNET_CONTAINER_multihashmap_put (t->children_fc,
3338 &peer->hashPubKey,
3339 cinfo,
3340 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
3341 }
3342 return cinfo;
3343}
3344
3345
3346/**
3347 * Get the Flow Control info of a client.
3348 *
3349 * @param t Tunnel on which to look.
3350 * @param c Client whose ACK to get.
3351 *
3352 * @return ACK value.
3353 */
3354static struct MeshTunnelClientInfo *
3355tunnel_get_client_fc (struct MeshTunnel *t,
3356 struct MeshClient *c)
3357{
3358 unsigned int i;
3359
3360 for (i = 0; i < t->nclients; i++)
3361 {
3362 if (t->clients[i] != c)
3363 continue;
3364 return &t->clients_fc[i];
3365 }
3366 GNUNET_assert (0);
3367 return NULL; // avoid compiler / coverity complaints
3368}
3369
3370
3371/**
3372 * Iterator to get the appropiate ACK value from all children nodes.
3373 *
3374 * @param cls Closue (tunnel).
3375 * @param id Id of the child node.
3376 */
3377static void
3378tunnel_get_child_fwd_ack (void *cls,
3379 GNUNET_PEER_Id id)
3380{
3381 struct GNUNET_PeerIdentity peer_id;
3382 struct MeshTunnelChildInfo *cinfo;
3383 struct MeshTunnelChildIteratorContext *ctx = cls;
3384 struct MeshTunnel *t = ctx->t;
3385 uint32_t ack;
3386
3387 GNUNET_PEER_resolve (id, &peer_id);
3388 cinfo = tunnel_get_neighbor_fc (t, &peer_id);
3389 ack = cinfo->fwd_ack;
3390
3391 ctx->nchildren++;
3392 if (GNUNET_NO == ctx->init)
3393 {
3394 ctx->max_child_ack = ack;
3395 ctx->init = GNUNET_YES;
3396 }
3397
3398 if (GNUNET_YES == t->speed_min)
3399 {
3400 ctx->max_child_ack = ctx->max_child_ack > ack ? ack : ctx->max_child_ack;
3401 }
3402 else
3403 {
3404 ctx->max_child_ack = ctx->max_child_ack > ack ? ctx->max_child_ack : ack;
3405 }
3406
3407}
3408
3409
3410/**
3411 * Get the maximum PID allowed to transmit to any
3412 * tunnel child of the local peer, depending on the tunnel
3413 * buffering/speed settings.
3414 *
3415 * @param t Tunnel.
3416 *
3417 * @return Maximum PID allowed (uint32 MAX), -1LL if node has no children.
3418 */
3419static int64_t
3420tunnel_get_children_fwd_ack (struct MeshTunnel *t)
3421{
3422 struct MeshTunnelChildIteratorContext ctx;
3423 ctx.t = t;
3424 ctx.max_child_ack = 0;
3425 ctx.nchildren = 0;
3426 ctx.init = GNUNET_NO;
3427 tree_iterate_children (t->tree, tunnel_get_child_fwd_ack, &ctx);
3428
3429 if (0 == ctx.nchildren)
3430 {
3431 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3432 " tunnel has no children, no FWD ACK\n");
3433 return -1LL;
3434 }
3435
3436 if (GNUNET_YES == t->nobuffer && GMC_is_pid_bigger(ctx.max_child_ack, t->fwd_pid))
3437 ctx.max_child_ack = t->fwd_pid + 1; // Might overflow, it's ok.
3438
3439 return (int64_t) ctx.max_child_ack;
3440}
3441
3442
3443/**
3444 * Set the FWD ACK value of a client in a particular tunnel.
3445 *
3446 * @param t Tunnel affected.
3447 * @param c Client whose ACK to set.
3448 * @param ack ACK value.
3449 */
3450static void
3451tunnel_set_client_fwd_ack (struct MeshTunnel *t,
3452 struct MeshClient *c,
3453 uint32_t ack)
3454{
3455 unsigned int i;
3456
3457 for (i = 0; i < t->nclients; i++)
3458 {
3459 if (t->clients[i] != c)
3460 continue;
3461 t->clients_fc[i].fwd_ack = ack;
3462 return;
3463 }
3464 GNUNET_break (0);
3465}
3466
3467
3468/**
3469 * Get the highest ACK value of all clients in a particular tunnel,
3470 * according to the buffering/speed settings.
3471 *
3472 * @param t Tunnel on which to look.
3473 *
3474 * @return Corresponding ACK value (max uint32_t).
3475 * If no clients are suscribed, -1LL.
3476 */
3477static int64_t
3478tunnel_get_clients_fwd_ack (struct MeshTunnel *t)
3479{
3480 unsigned int i;
3481 int64_t ack;
3482
3483 if (0 == t->nclients)
3484 {
3485 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3486 " tunnel has no clients, no FWD ACK\n");
3487 return -1LL;
3488 }
3489
3490 for (ack = -1LL, i = 0; i < t->nclients; i++)
3491 {
3492 if (-1LL == ack ||
3493 (GNUNET_YES == t->speed_min &&
3494 GNUNET_YES == GMC_is_pid_bigger (ack, t->clients_fc[i].fwd_ack)) ||
3495 (GNUNET_NO == t->speed_min &&
3496 GNUNET_YES == GMC_is_pid_bigger (t->clients_fc[i].fwd_ack, ack)))
3497 {
3498 ack = t->clients_fc[i].fwd_ack;
3499 }
3500 }
3501
3502 if (GNUNET_YES == t->nobuffer && GMC_is_pid_bigger(ack, t->fwd_pid))
3503 ack = (uint32_t) t->fwd_pid + 1; // Might overflow, it's ok.
3504
3505 return (uint32_t) ack;
3506}
3507
3508
3509/**
3510 * Get the current fwd ack value for a tunnel, taking in account the tunnel
3511 * mode and the status of all children nodes.
3512 *
3513 * @param t Tunnel.
3514 *
3515 * @return Maximum PID allowed.
3516 */
3517static uint32_t
3518tunnel_get_fwd_ack (struct MeshTunnel *t)
3519{
3520 uint32_t ack;
3521 uint32_t count;
3522 uint32_t buffer_free;
3523 int64_t child_ack;
3524 int64_t client_ack;
3525
3526 count = t->fwd_pid - t->skip;
3527 buffer_free = t->fwd_queue_max - t->fwd_queue_n;
3528 child_ack = tunnel_get_children_fwd_ack (t);
3529 client_ack = tunnel_get_clients_fwd_ack (t);
3530 if (GNUNET_YES == t->nobuffer)
3531 {
3532 ack = count;
3533 if (-1LL == child_ack)
3534 child_ack = client_ack;
3535 if (-1LL == child_ack)
3536 {
3537 GNUNET_break (0);
3538 client_ack = child_ack = ack;
3539 }
3540 }
3541 else
3542 {
3543 ack = count + buffer_free; // Overflow? OK!
3544 }
3545 if (-1LL == child_ack)
3546 {
3547 // Node has no children, child_ack AND core buffer are irrelevant.
3548 if (-1LL == client_ack) // No children AND no clients? Not good!
3549 {
3550 GNUNET_STATISTICS_update (stats, "# mesh acks with no target",
3551 1, GNUNET_NO);
3552
3553 }
3554 return (uint32_t) client_ack;
3555 }
3556 if (-1LL == client_ack)
3557 {
3558 client_ack = ack;
3559 }
3560 if (GNUNET_YES == t->speed_min)
3561 {
3562 ack = GMC_min_pid ((uint32_t) child_ack, ack);
3563 ack = GMC_min_pid ((uint32_t) client_ack, ack);
3564 }
3565 else
3566 {
3567 ack = GMC_max_pid ((uint32_t) child_ack, ack);
3568 ack = GMC_max_pid ((uint32_t) client_ack, ack);
3569 }
3570 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3571 "c %u, bf %u, ch %lld, cl %lld, ACK: %u\n",
3572 count, buffer_free, child_ack, client_ack, ack);
3573 return ack;
3574} 1916}
3575 1917
3576 1918
@@ -3589,7 +1931,7 @@ send_local_ack (struct MeshTunnel *t, struct MeshClient *c, uint32_t ack)
3589 msg.header.size = htons (sizeof (msg)); 1931 msg.header.size = htons (sizeof (msg));
3590 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); 1932 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
3591 msg.tunnel_id = htonl (t->owner == c ? t->local_tid : t->local_tid_dest); 1933 msg.tunnel_id = htonl (t->owner == c ? t->local_tid : t->local_tid_dest);
3592 msg.max_pid = htonl (ack); 1934 msg.ack = htonl (ack);
3593 GNUNET_SERVER_notification_context_unicast(nc, 1935 GNUNET_SERVER_notification_context_unicast(nc,
3594 c->handle, 1936 c->handle,
3595 &msg.header, 1937 &msg.header,
@@ -3604,7 +1946,7 @@ send_local_ack (struct MeshTunnel *t, struct MeshClient *c, uint32_t ack)
3604 * @param ack Value of the ACK. 1946 * @param ack Value of the ACK.
3605 */ 1947 */
3606static void 1948static void
3607send_ack (struct MeshTunnel *t, struct GNUNET_PeerIdentity *peer, uint32_t ack) 1949send_ack (struct MeshTunnel *t, GNUNET_PEER_Id peer, uint32_t ack)
3608{ 1950{
3609 struct GNUNET_MESH_ACK msg; 1951 struct GNUNET_MESH_ACK msg;
3610 1952
@@ -3619,36 +1961,6 @@ send_ack (struct MeshTunnel *t, struct GNUNET_PeerIdentity *peer, uint32_t ack)
3619 1961
3620 1962
3621/** 1963/**
3622 * Notify a the owner of a tunnel about how many more
3623 * payload packages will we accept on a given tunnel.
3624 *
3625 * @param t Tunnel on which to send the ACK.
3626 */
3627static void
3628tunnel_send_client_fwd_ack (struct MeshTunnel *t)
3629{
3630 uint32_t ack;
3631
3632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3633 "Sending client FWD ACK on tunnel %X\n",
3634 t->local_tid);
3635
3636 ack = tunnel_get_fwd_ack (t);
3637
3638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ack);
3639 if (t->last_fwd_ack == ack)
3640 {
3641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " same as last, not sending!\n");
3642 return;
3643 }
3644
3645 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending!\n");
3646 t->last_fwd_ack = ack;
3647 send_local_ack (t, t->owner, ack);
3648}
3649
3650
3651/**
3652 * Send an ACK informing the predecessor about the available buffer space. 1964 * Send an ACK informing the predecessor about the available buffer space.
3653 * In case there is no predecessor, inform the owning client. 1965 * In case there is no predecessor, inform the owning client.
3654 * If buffering is off, send only on behalf of children or self if endpoint. 1966 * If buffering is off, send only on behalf of children or self if endpoint.
@@ -3662,19 +1974,12 @@ tunnel_send_client_fwd_ack (struct MeshTunnel *t)
3662static void 1974static void
3663tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type) 1975tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type)
3664{ 1976{
3665 struct GNUNET_PeerIdentity id;
3666 uint32_t ack; 1977 uint32_t ack;
3667 1978
3668 if (NULL != t->owner) 1979 /* Is it after unicast retransmission? */
3669 {
3670 tunnel_send_client_fwd_ack (t);
3671 return;
3672 }
3673 /* Is it after unicast / multicast retransmission? */
3674 switch (type) 1980 switch (type)
3675 { 1981 {
3676 case GNUNET_MESSAGE_TYPE_MESH_UNICAST: 1982 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
3677 case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
3678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1983 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3679 "ACK due to FWD DATA retransmission\n"); 1984 "ACK due to FWD DATA retransmission\n");
3680 if (GNUNET_YES == t->nobuffer) 1985 if (GNUNET_YES == t->nobuffer)
@@ -3686,6 +1991,7 @@ tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type)
3686 case GNUNET_MESSAGE_TYPE_MESH_ACK: 1991 case GNUNET_MESSAGE_TYPE_MESH_ACK:
3687 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: 1992 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
3688 break; 1993 break;
1994 case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
3689 case GNUNET_MESSAGE_TYPE_MESH_POLL: 1995 case GNUNET_MESSAGE_TYPE_MESH_POLL:
3690 t->force_ack = GNUNET_YES; 1996 t->force_ack = GNUNET_YES;
3691 break; 1997 break;
@@ -3694,136 +2000,43 @@ tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type)
3694 } 2000 }
3695 2001
3696 /* Check if we need to transmit the ACK */ 2002 /* Check if we need to transmit the ACK */
3697 if (t->fwd_queue_max > t->fwd_queue_n * 4 && 2003 if (t->queue_max > t->next_fc.queue_n * 4 &&
3698 GMC_is_pid_bigger(t->last_fwd_ack, t->fwd_pid) && 2004 GMC_is_pid_bigger(t->prev_fc.last_ack_sent, t->prev_fc.last_pid_recv) &&
3699 GNUNET_NO == t->force_ack) 2005 GNUNET_NO == t->force_ack)
3700 { 2006 {
3701 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer free\n"); 2007 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer free\n");
3702 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2008 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3703 " t->qmax: %u, t->qn: %u\n", 2009 " t->qmax: %u, t->qn: %u\n",
3704 t->fwd_queue_max, t->fwd_queue_n); 2010 t->queue_max, t->next_fc.queue_n);
3705 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2011 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3706 " t->pid: %u, t->ack: %u\n", 2012 " t->pid: %u, t->ack: %u\n",
3707 t->fwd_pid, t->last_fwd_ack); 2013 t->prev_fc.last_pid_recv, t->prev_fc.last_ack_sent);
3708 return; 2014 return;
3709 } 2015 }
3710 2016
3711 /* Ok, ACK might be necessary, what PID to ACK? */ 2017 /* Ok, ACK might be necessary, what PID to ACK? */
3712 ack = tunnel_get_fwd_ack (t); 2018 ack = t->prev_fc.last_pid_recv + t->queue_max - t->next_fc.queue_n;
3713 2019 if (ack == t->prev_fc.last_ack_sent && GNUNET_NO == t->force_ack)
3714 /* If speed_min and not all children have ack'd, dont send yet */
3715 if (ack == t->last_fwd_ack && GNUNET_NO == t->force_ack)
3716 { 2020 {
3717 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not ready\n"); 2021 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
3718 return; 2022 return;
3719 } 2023 }
3720 2024
3721 t->last_fwd_ack = ack; 2025 t->prev_fc.last_ack_sent = ack;
3722 GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &id); 2026 if (NULL != t->owner)
3723 send_ack (t, &id, ack); 2027 send_local_ack (t, t->owner, ack);
2028 else if (0 != t->prev_hop)
2029 send_ack (t, t->prev_hop, ack);
2030 else
2031 GNUNET_break (0);
3724 debug_fwd_ack++; 2032 debug_fwd_ack++;
3725 t->force_ack = GNUNET_NO; 2033 t->force_ack = GNUNET_NO;
3726} 2034}
3727 2035
3728 2036
3729/** 2037/**
3730 * Iterator to send a child node a BCK ACK to allow him to send more 2038 * Send an ACK informing the children node/client about the available
3731 * to_origin data. 2039 * buffer space.
3732 *
3733 * @param cls Closure (tunnel).
3734 * @param id Id of the child node.
3735 */
3736static void
3737tunnel_send_child_bck_ack (void *cls,
3738 GNUNET_PEER_Id id)
3739{
3740 struct MeshTunnel *t = cls;
3741 struct MeshTunnelChildInfo *cinfo;
3742 struct GNUNET_PeerIdentity peer;
3743 uint32_t ack;
3744
3745 GNUNET_PEER_resolve (id, &peer);
3746 cinfo = tunnel_get_neighbor_fc (t, &peer);
3747 ack = cinfo->bck_pid + t->bck_queue_max - t->bck_queue_n;
3748
3749 if (cinfo->bck_ack == ack && GNUNET_NO == t->force_ack)
3750 {
3751 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3752 " Not sending ACK, not needed\n");
3753 return;
3754 }
3755 cinfo->bck_ack = ack;
3756
3757 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3758 " Sending BCK ACK %u (last sent: %u)\n",
3759 ack, cinfo->bck_ack);
3760 send_ack (t, &peer, ack);
3761}
3762
3763
3764/**
3765 * @brief Send BCK ACKs to clients to allow them more to_origin traffic
3766 *
3767 * Iterates over all clients and sends BCK ACKs to the ones that need it.
3768 *
3769 * FIXME fc: what happens if we have 2 clients but q_size is 1?
3770 * - implement a size 1 buffer in each client_fc AND children_fc
3771 * to hold at least 1 message per "child".
3772 * problem: violates no buffer policy
3773 * - ack 0 and make "children" poll for transmission slots
3774 * problem: big overhead, extra latency even in low traffic
3775 * settings
3776 *
3777 * @param t Tunnel on which to send the BCK ACKs.
3778 */
3779static void
3780tunnel_send_clients_bck_ack (struct MeshTunnel *t)
3781{
3782 unsigned int i;
3783 unsigned int tunnel_delta;
3784
3785 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Sending BCK ACK to clients\n");
3786
3787 tunnel_delta = t->bck_queue_max - t->bck_queue_n;
3788 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " tunnel delta: %u\n", tunnel_delta);
3789
3790 /* Find client whom to allow to send to origin (with lowest buffer space) */
3791 for (i = 0; i < t->nclients; i++)
3792 {
3793 struct MeshTunnelClientInfo *clinfo;
3794 unsigned int delta;
3795
3796 clinfo = &t->clients_fc[i];
3797 delta = clinfo->bck_ack - clinfo->bck_pid;
3798 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client %u delta: %u\n",
3799 t->clients[i]->id, delta);
3800
3801 if ((GNUNET_NO == t->nobuffer && tunnel_delta > delta) ||
3802 (GNUNET_YES == t->nobuffer && 0 == delta))
3803 {
3804 uint32_t ack;
3805
3806 ack = clinfo->bck_pid;
3807 ack += t->nobuffer ? 1 : tunnel_delta;
3808 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3809 " sending ack to client %u: %u\n",
3810 t->clients[i]->id, ack);
3811 send_local_ack (t, t->clients[i], ack);
3812 clinfo->bck_ack = ack;
3813 }
3814 else
3815 {
3816 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3817 " not sending ack to client %u (td %u, d %u)\n",
3818 t->clients[i]->id, tunnel_delta, delta);
3819 }
3820 }
3821}
3822
3823
3824/**
3825 * Send an ACK informing the children nodes and destination clients about
3826 * the available buffer space.
3827 * If buffering is off, send only on behalf of root (can be self). 2040 * If buffering is off, send only on behalf of root (can be self).
3828 * If buffering is on, send when sent to predecessor and buffer space is free. 2041 * If buffering is on, send when sent to predecessor and buffer space is free.
3829 * Note that although the name is bck_ack, the BCK mean backwards *traffic*, 2042 * Note that although the name is bck_ack, the BCK mean backwards *traffic*,
@@ -3835,6 +2048,7 @@ tunnel_send_clients_bck_ack (struct MeshTunnel *t)
3835static void 2048static void
3836tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type) 2049tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type)
3837{ 2050{
2051 uint32_t ack;
3838 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2052 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3839 "Sending BCK ACK on tunnel %u [%u] due to %s\n", 2053 "Sending BCK ACK on tunnel %u [%u] due to %s\n",
3840 t->id.oid, t->id.tid, GNUNET_MESH_DEBUG_M2S(type)); 2054 t->id.oid, t->id.tid, GNUNET_MESH_DEBUG_M2S(type));
@@ -3845,13 +2059,14 @@ tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type)
3845 if (GNUNET_YES == t->nobuffer) 2059 if (GNUNET_YES == t->nobuffer)
3846 { 2060 {
3847 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2061 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3848 " Not sending ACK, nobuffer\n"); 2062 " Not sending ACK, nobuffer + traffic\n");
3849 return; 2063 return;
3850 } 2064 }
3851 break; 2065 break;
3852 case GNUNET_MESSAGE_TYPE_MESH_ACK: 2066 case GNUNET_MESSAGE_TYPE_MESH_ACK:
3853 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: 2067 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
3854 break; 2068 break;
2069 case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
3855 case GNUNET_MESSAGE_TYPE_MESH_POLL: 2070 case GNUNET_MESSAGE_TYPE_MESH_POLL:
3856 t->force_ack = GNUNET_YES; 2071 t->force_ack = GNUNET_YES;
3857 break; 2072 break;
@@ -3859,35 +2074,120 @@ tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type)
3859 GNUNET_break (0); 2074 GNUNET_break (0);
3860 } 2075 }
3861 2076
3862 tunnel_send_clients_bck_ack (t); 2077 /* TODO: Check if we need to transmit the ACK (as in fwd) */
3863 tree_iterate_children (t->tree, &tunnel_send_child_bck_ack, t); 2078
2079 ack = t->next_fc.last_pid_recv + t->queue_max - t->prev_fc.queue_n;
2080
2081 if (t->next_fc.last_ack_sent == ack && GNUNET_NO == t->force_ack)
2082 {
2083 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2084 " Not sending ACK, not needed, last ack sent was %u\n",
2085 t->next_fc.last_ack_sent);
2086 return;
2087 }
2088 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2089 " Sending BCK ACK %u (last sent: %u)\n",
2090 ack, t->next_fc.last_ack_sent);
2091 t->next_fc.last_ack_sent = ack;
2092
2093 if (NULL != t->client)
2094 send_local_ack (t, t->client, ack);
2095 else if (0 != t->next_hop)
2096 send_ack (t, t->next_hop, ack);
2097 else
2098 GNUNET_break (0);
3864 t->force_ack = GNUNET_NO; 2099 t->force_ack = GNUNET_NO;
3865} 2100}
3866 2101
3867 2102
3868/** 2103/**
2104 * Modify the unicast message TID from global to local and send to client.
2105 *
2106 * @param t Tunnel on which to send the message.
2107 * @param msg Message to modify and send.
2108 */
2109static void
2110tunnel_send_client_ucast (struct MeshTunnel *t,
2111 const struct GNUNET_MESH_Data *msg)
2112{
2113 struct GNUNET_MESH_Data *copy;
2114 uint16_t size = ntohs (msg->header.size);
2115 char cbuf[size];
2116
2117 if (size < sizeof (struct GNUNET_MESH_Data) +
2118 sizeof (struct GNUNET_MessageHeader))
2119 {
2120 GNUNET_break_op (0);
2121 return;
2122 }
2123 if (NULL == t->client)
2124 {
2125 GNUNET_break (0);
2126 return;
2127 }
2128 copy = (struct GNUNET_MESH_Data *) cbuf;
2129 memcpy (copy, msg, size);
2130 copy->tid = htonl (t->local_tid_dest);
2131 GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
2132 &copy->header, GNUNET_NO);
2133}
2134
2135
2136/**
2137 * Modify the to_origin message TID from global to local and send to client.
2138 *
2139 * @param t Tunnel on which to send the message.
2140 * @param msg Message to modify and send.
2141 */
2142static void
2143tunnel_send_client_to_orig (struct MeshTunnel *t,
2144 const struct GNUNET_MESH_Data *msg)
2145{
2146 struct GNUNET_MESH_Data *copy;
2147 uint16_t size = ntohs (msg->header.size);
2148 char cbuf[size];
2149
2150 if (size < sizeof (struct GNUNET_MESH_Data) +
2151 sizeof (struct GNUNET_MessageHeader))
2152 {
2153 GNUNET_break_op (0);
2154 return;
2155 }
2156 if (NULL == t->owner)
2157 {
2158 GNUNET_break (0);
2159 return;
2160 }
2161 copy = (struct GNUNET_MESH_Data *) cbuf;
2162 memcpy (cbuf, msg, size);
2163 copy->tid = htonl (t->local_tid);
2164 GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
2165 &copy->header, GNUNET_NO);
2166}
2167
2168
2169/**
3869 * @brief Re-initiate traffic to this peer if necessary. 2170 * @brief Re-initiate traffic to this peer if necessary.
3870 * 2171 *
3871 * Check if there is traffic queued towards this peer 2172 * Check if there is traffic queued towards this peer
3872 * and the core transmit handle is NULL (traffic was stalled). 2173 * and the core transmit handle is NULL (traffic was stalled).
3873 * If so, call core tmt rdy. 2174 * If so, call core tmt rdy.
3874 * 2175 *
3875 * @param cls Closure (unused)
3876 * @param peer_id Short ID of peer to which initiate traffic. 2176 * @param peer_id Short ID of peer to which initiate traffic.
3877 */ 2177 */
3878static void 2178static void
3879peer_unlock_queue(void *cls, GNUNET_PEER_Id peer_id) 2179peer_unlock_queue(GNUNET_PEER_Id peer_id)
3880{ 2180{
3881 struct MeshPeerInfo *peer; 2181 struct MeshPeerInfo *peer;
3882 struct GNUNET_PeerIdentity id; 2182 struct GNUNET_PeerIdentity id;
3883 struct MeshPeerQueue *q; 2183 struct MeshPeerQueue *q;
3884 size_t size; 2184 size_t size;
3885 2185
3886 peer = peer_info_get_short(peer_id); 2186 peer = peer_get_short (peer_id);
3887 if (NULL != peer->core_transmit) 2187 if (NULL != peer->core_transmit)
3888 return; 2188 return;
3889 2189
3890 q = queue_get_next(peer); 2190 q = queue_get_next (peer);
3891 if (NULL == q) 2191 if (NULL == q)
3892 { 2192 {
3893 /* Might br multicast traffic already sent to this particular peer but 2193 /* Might br multicast traffic already sent to this particular peer but
@@ -3913,50 +2213,14 @@ peer_unlock_queue(void *cls, GNUNET_PEER_Id peer_id)
3913 2213
3914 2214
3915/** 2215/**
3916 * @brief Allow transmission of FWD traffic on this tunnel 2216 * Send a message to all peers and clients in this tunnel that the tunnel
3917 * 2217 * is no longer valid. If some peer or client should not receive the message,
3918 * Check if there is traffic queued towards any children 2218 * should be zero'ed out before calling this function.
3919 * and the core transmit handle is NULL, and if so, call core tmt rdy.
3920 *
3921 * @param t Tunnel on which to unlock FWD traffic.
3922 */
3923static void
3924tunnel_unlock_fwd_queues (struct MeshTunnel *t)
3925{
3926 if (0 == t->fwd_queue_n)
3927 return;
3928
3929 tree_iterate_children (t->tree, &peer_unlock_queue, NULL);
3930}
3931
3932
3933/**
3934 * @brief Allow transmission of BCK traffic on this tunnel
3935 * 2219 *
3936 * Check if there is traffic queued towards the root of the tree 2220 * @param t The tunnel whose peers and clients to notify.
3937 * and the core transmit handle is NULL, and if so, call core tmt rdy.
3938 *
3939 * @param t Tunnel on which to unlock BCK traffic.
3940 */ 2221 */
3941static void 2222static void
3942tunnel_unlock_bck_queue (struct MeshTunnel *t) 2223tunnel_send_destroy (struct MeshTunnel *t)
3943{
3944 if (0 == t->bck_queue_n)
3945 return;
3946
3947 peer_unlock_queue(NULL, tree_get_predecessor(t->tree));
3948}
3949
3950
3951/**
3952 * Send a message to all peers in this tunnel that the tunnel is no longer
3953 * valid.
3954 *
3955 * @param t The tunnel whose peers to notify.
3956 * @param parent ID of the parent, in case the tree is already destroyed.
3957 */
3958static void
3959tunnel_send_destroy (struct MeshTunnel *t, GNUNET_PEER_Id parent)
3960{ 2224{
3961 struct GNUNET_MESH_TunnelDestroy msg; 2225 struct GNUNET_MESH_TunnelDestroy msg;
3962 struct GNUNET_PeerIdentity id; 2226 struct GNUNET_PeerIdentity id;
@@ -3968,50 +2232,61 @@ tunnel_send_destroy (struct MeshTunnel *t, GNUNET_PEER_Id parent)
3968 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2232 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3969 " sending tunnel destroy for tunnel: %s [%X]\n", 2233 " sending tunnel destroy for tunnel: %s [%X]\n",
3970 GNUNET_i2s (&msg.oid), t->id.tid); 2234 GNUNET_i2s (&msg.oid), t->id.tid);
3971 if (tree_count_children(t->tree) > 0) 2235
2236 if (NULL == t->client && 0 != t->next_hop)
3972 { 2237 {
3973 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending multicast to children\n"); 2238 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " child: %u\n", t->next_hop);
3974 tunnel_send_multicast (t, &msg.header); 2239 GNUNET_PEER_resolve (t->next_hop, &id);
2240 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2241 " sending forward to %s\n",
2242 GNUNET_i2s (&id));
2243 send_prebuilt_message (&msg.header, t->next_hop, t);
2244 }
2245 if (NULL == t->owner && 0 != t->prev_hop)
2246 {
2247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " parent: %u\n", t->prev_hop);
2248 GNUNET_PEER_resolve (t->prev_hop, &id);
2249 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2250 " sending back to %s\n",
2251 GNUNET_i2s (&id));
2252 send_prebuilt_message (&msg.header, t->prev_hop, t);
2253 }
2254 if (NULL != t->owner)
2255 {
2256 send_client_tunnel_destroy (t->owner, t);
2257 }
2258 if (NULL != t->client)
2259 {
2260 send_client_tunnel_destroy (t->client, t);
3975 } 2261 }
3976 if (0 == parent)
3977 parent = tree_get_predecessor (t->tree);
3978 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " parent: %u\n", parent);
3979 if (0 == parent)
3980 return;
3981
3982 GNUNET_PEER_resolve (parent, &id);
3983 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3984 " sending back to %s\n",
3985 GNUNET_i2s (&id));
3986 send_prebuilt_message (&msg.header, &id, t);
3987} 2262}
3988 2263
3989 2264
3990/** 2265/**
3991 * Cancel all transmissions towards a neighbor that belong to a certain tunnel. 2266 * Cancel all transmissions towards a neighbor that belongs to a certain tunnel.
3992 * 2267 *
3993 * @param cls Closure (Tunnel which to cancel). 2268 * @param t Tunnel which to cancel.
3994 * @param neighbor_id Short ID of the neighbor to whom cancel the transmissions. 2269 * @param neighbor Short ID of the neighbor to whom cancel the transmissions.
3995 */ 2270 */
3996static void 2271static void
3997tunnel_cancel_queues (void *cls, GNUNET_PEER_Id neighbor_id) 2272peer_cancel_queues (GNUNET_PEER_Id neighbor, struct MeshTunnel *t)
3998{ 2273{
3999 struct MeshTunnel *t = cls;
4000 struct MeshPeerInfo *peer_info; 2274 struct MeshPeerInfo *peer_info;
4001 struct MeshPeerQueue *pq; 2275 struct MeshPeerQueue *pq;
4002 struct MeshPeerQueue *next; 2276 struct MeshPeerQueue *next;
4003 2277
4004 peer_info = peer_info_get_short (neighbor_id); 2278 if (0 == neighbor)
2279 return; /* Was local peer, 0'ed in tunnel_destroy_iterator */
2280 peer_info = peer_get_short (neighbor);
4005 for (pq = peer_info->queue_head; NULL != pq; pq = next) 2281 for (pq = peer_info->queue_head; NULL != pq; pq = next)
4006 { 2282 {
4007 next = pq->next; 2283 next = pq->next;
4008 if (pq->tunnel == t) 2284 if (pq->tunnel == t)
4009 { 2285 {
4010 if (GNUNET_MESSAGE_TYPE_MESH_MULTICAST == pq->type || 2286 if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == pq->type ||
4011 GNUNET_MESSAGE_TYPE_MESH_UNICAST == pq->type ||
4012 GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == pq->type) 2287 GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == pq->type)
4013 { 2288 {
4014 // Should have been removed on destroy children 2289 /* Should have been removed on destroy children */
4015 GNUNET_break (0); 2290 GNUNET_break (0);
4016 } 2291 }
4017 queue_destroy (pq, GNUNET_YES); 2292 queue_destroy (pq, GNUNET_YES);
@@ -4024,8 +2299,16 @@ tunnel_cancel_queues (void *cls, GNUNET_PEER_Id neighbor_id)
4024 } 2299 }
4025} 2300}
4026 2301
2302
4027/** 2303/**
4028 * Destroy the tunnel and free any allocated resources linked to it. 2304 * Destroy the tunnel.
2305 *
2306 * This function does not generate any warning traffic to clients or peers.
2307 *
2308 * Tasks:
2309 * Remove the tunnel from peer_info's and clients' hashmaps.
2310 * Cancel messages belonging to this tunnel queued to neighbors.
2311 * Free any allocated resources linked to the tunnel.
4029 * 2312 *
4030 * @param t the tunnel to destroy 2313 * @param t the tunnel to destroy
4031 * 2314 *
@@ -4036,7 +2319,6 @@ tunnel_destroy (struct MeshTunnel *t)
4036{ 2319{
4037 struct MeshClient *c; 2320 struct MeshClient *c;
4038 struct GNUNET_HashCode hash; 2321 struct GNUNET_HashCode hash;
4039 unsigned int i;
4040 int r; 2322 int r;
4041 2323
4042 if (NULL == t) 2324 if (NULL == t)
@@ -4065,7 +2347,7 @@ tunnel_destroy (struct MeshTunnel *t)
4065 2347
4066 if (NULL != c) 2348 if (NULL != c)
4067 { 2349 {
4068 GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash); 2350 GMC_hash32 (t->local_tid, &hash);
4069 if (GNUNET_YES != 2351 if (GNUNET_YES !=
4070 GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels, &hash, t)) 2352 GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels, &hash, t))
4071 { 2353 {
@@ -4074,86 +2356,58 @@ tunnel_destroy (struct MeshTunnel *t)
4074 } 2356 }
4075 } 2357 }
4076 2358
4077 GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash); 2359 if (NULL != t->client)
4078 for (i = 0; i < t->nclients; i++)
4079 { 2360 {
4080 c = t->clients[i]; 2361 c = t->client;
2362 GMC_hash32 (t->local_tid_dest, &hash);
4081 if (GNUNET_YES != 2363 if (GNUNET_YES !=
4082 GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, &hash, t)) 2364 GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, &hash, t))
4083 { 2365 {
4084 GNUNET_break (0); 2366 GNUNET_break (0);
4085 r = GNUNET_SYSERR; 2367 r = GNUNET_SYSERR;
4086 } 2368 }
4087 } 2369 if (GNUNET_YES !=
4088 for (i = 0; i < t->nignore; i++) 2370 GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t))
4089 {
4090 c = t->ignore[i];
4091 if (GNUNET_YES !=
4092 GNUNET_CONTAINER_multihashmap_remove (c->ignore_tunnels, &hash, t))
4093 { 2371 {
4094 GNUNET_break (0); 2372 GNUNET_break (0);
4095 r = GNUNET_SYSERR; 2373 r = GNUNET_SYSERR;
4096 } 2374 }
4097 } 2375 }
4098 2376
4099 (void) GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t); 2377 if (0 != t->prev_hop)
4100 GNUNET_free_non_null (t->clients);
4101 GNUNET_free_non_null (t->ignore);
4102 GNUNET_free_non_null (t->clients_fc);
4103
4104 if (NULL != t->peers)
4105 { 2378 {
4106 GNUNET_CONTAINER_multihashmap_iterate (t->peers, &peer_info_delete_tunnel, 2379 peer_cancel_queues (t->prev_hop, t);
4107 t); 2380 GNUNET_PEER_change_rc (t->prev_hop, -1);
4108 GNUNET_CONTAINER_multihashmap_destroy (t->peers); 2381 }
2382 if (0 != t->next_hop)
2383 {
2384 peer_cancel_queues (t->next_hop, t);
2385 GNUNET_PEER_change_rc (t->next_hop, -1);
2386 }
2387 if (0 != t->dest) {
2388 peer_info_remove_tunnel (peer_get_short (t->dest), t);
4109 } 2389 }
4110 2390
4111 GNUNET_CONTAINER_multihashmap_iterate (t->children_fc, 2391 if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task)
4112 &tunnel_destroy_child, 2392 GNUNET_SCHEDULER_cancel (t->maintenance_task);
4113 t);
4114 GNUNET_CONTAINER_multihashmap_destroy (t->children_fc);
4115 t->children_fc = NULL;
4116
4117 tree_iterate_children (t->tree, &tunnel_cancel_queues, t);
4118 tree_destroy (t->tree);
4119
4120 if (NULL != t->regex_search)
4121 GNUNET_REGEX_search_cancel (t->regex_search->search_handle);
4122 if (NULL != t->dht_get_type)
4123 GNUNET_DHT_get_stop (t->dht_get_type);
4124 if (GNUNET_SCHEDULER_NO_TASK != t->timeout_task)
4125 GNUNET_SCHEDULER_cancel (t->timeout_task);
4126 if (GNUNET_SCHEDULER_NO_TASK != t->path_refresh_task)
4127 GNUNET_SCHEDULER_cancel (t->path_refresh_task);
4128 2393
4129 n_tunnels--; 2394 n_tunnels--;
4130 GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO); 2395 GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO);
2396 path_destroy (t->path);
4131 GNUNET_free (t); 2397 GNUNET_free (t);
4132 return r; 2398 return r;
4133} 2399}
4134 2400
4135#define TUNNEL_DESTROY_EMPTY_TIME GNUNET_TIME_UNIT_MILLISECONDS
4136
4137/** 2401/**
4138 * Tunnel is empty: destroy it. 2402 * Tunnel is empty: destroy it.
4139 * 2403 *
4140 * @param cls Closure (Tunnel). 2404 * Notifies all participants (peers, cleints) about the destruction.
4141 * @param tc TaskContext. 2405 *
2406 * @param t Tunnel to destroy.
4142 */ 2407 */
4143static void 2408static void
4144tunnel_destroy_empty_delayed (void *cls, 2409tunnel_destroy_empty (struct MeshTunnel *t)
4145 const struct GNUNET_SCHEDULER_TaskContext *tc)
4146{ 2410{
4147 struct MeshTunnel *t = cls;
4148
4149 t->delayed_destroy = GNUNET_SCHEDULER_NO_TASK;
4150 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
4151 return;
4152
4153 if (0 != t->nclients ||
4154 0 != tree_count_children (t->tree))
4155 return;
4156
4157 #if MESH_DEBUG 2411 #if MESH_DEBUG
4158 { 2412 {
4159 struct GNUNET_PeerIdentity id; 2413 struct GNUNET_PeerIdentity id;
@@ -4165,50 +2419,31 @@ tunnel_destroy_empty_delayed (void *cls,
4165 } 2419 }
4166 #endif 2420 #endif
4167 2421
4168 tunnel_send_destroy (t, 0); 2422 if (GNUNET_NO == t->destroy)
2423 tunnel_send_destroy (t);
4169 if (0 == t->pending_messages) 2424 if (0 == t->pending_messages)
4170 tunnel_destroy (t); 2425 tunnel_destroy (t);
4171 else 2426 else
4172 t->destroy = GNUNET_YES; 2427 t->destroy = GNUNET_YES;
4173} 2428}
4174 2429
4175
4176/** 2430/**
4177 * Schedule tunnel destruction if is empty and no new traffic comes in a time. 2431 * Initialize a Flow Control structure to the initial state.
4178 * 2432 *
4179 * @param t Tunnel to destroy if empty. 2433 * @param fc Flow Control structure to initialize.
4180 */ 2434 */
4181static void 2435static void
4182tunnel_destroy_empty (struct MeshTunnel *t) 2436fc_init (struct MeshFlowControl *fc)
4183{ 2437{
4184 if (GNUNET_SCHEDULER_NO_TASK != t->delayed_destroy || 2438 fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */
4185 0 != t->nclients || 2439 fc->last_pid_recv = (uint32_t) -1;
4186 0 != tree_count_children (t->tree)) 2440 fc->last_ack_sent = (uint32_t) -1; /* No traffic allowed yet */
4187 { 2441 fc->last_ack_recv = (uint32_t) -1;
4188 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2442 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
4189 "%u %u %u\n", 2443 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
4190 t->delayed_destroy, t->nclients, tree_count_children(t->tree)); 2444 fc->queue_n = 0;
4191 return;
4192 }
4193
4194 #if MESH_DEBUG
4195 {
4196 struct GNUNET_PeerIdentity id;
4197
4198 GNUNET_PEER_resolve (t->id.oid, &id);
4199 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4200 "scheduling destruction of empty tunnel %s [%X]\n",
4201 GNUNET_i2s (&id), t->id.tid);
4202 }
4203 #endif
4204
4205 t->delayed_destroy =
4206 GNUNET_SCHEDULER_add_delayed (TUNNEL_DESTROY_EMPTY_TIME,
4207 &tunnel_destroy_empty_delayed,
4208 t);
4209} 2445}
4210 2446
4211
4212/** 2447/**
4213 * Create a new tunnel 2448 * Create a new tunnel
4214 * 2449 *
@@ -4234,16 +2469,11 @@ tunnel_new (GNUNET_PEER_Id owner,
4234 t = GNUNET_malloc (sizeof (struct MeshTunnel)); 2469 t = GNUNET_malloc (sizeof (struct MeshTunnel));
4235 t->id.oid = owner; 2470 t->id.oid = owner;
4236 t->id.tid = tid; 2471 t->id.tid = tid;
4237 t->fwd_queue_max = (max_msgs_queue / max_tunnels) + 1; 2472 t->queue_max = (max_msgs_queue / max_tunnels) + 1;
4238 t->bck_queue_max = t->fwd_queue_max;
4239 t->tree = tree_new (owner);
4240 t->owner = client; 2473 t->owner = client;
4241 t->fwd_pid = (uint32_t) -1; // Next (expected) = 0 2474 fc_init (&t->next_fc);
4242 t->bck_pid = (uint32_t) -1; // Next (expected) = 0 2475 fc_init (&t->prev_fc);
4243 t->bck_ack = INITIAL_WINDOW_SIZE - 1;
4244 t->last_fwd_ack = INITIAL_WINDOW_SIZE - 1;
4245 t->local_tid = local; 2476 t->local_tid = local;
4246 t->children_fc = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
4247 n_tunnels++; 2477 n_tunnels++;
4248 GNUNET_STATISTICS_update (stats, "# tunnels", 1, GNUNET_NO); 2478 GNUNET_STATISTICS_update (stats, "# tunnels", 1, GNUNET_NO);
4249 2479
@@ -4264,7 +2494,7 @@ tunnel_new (GNUNET_PEER_Id owner,
4264 2494
4265 if (NULL != client) 2495 if (NULL != client)
4266 { 2496 {
4267 GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash); 2497 GMC_hash32 (t->local_tid, &hash);
4268 if (GNUNET_OK != 2498 if (GNUNET_OK !=
4269 GNUNET_CONTAINER_multihashmap_put (client->own_tunnels, &hash, t, 2499 GNUNET_CONTAINER_multihashmap_put (client->own_tunnels, &hash, t,
4270 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) 2500 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
@@ -4279,52 +2509,14 @@ tunnel_new (GNUNET_PEER_Id owner,
4279 return t; 2509 return t;
4280} 2510}
4281 2511
4282/**
4283 * Callback when removing children from a tunnel tree. Notify owner.
4284 *
4285 * @param cls Closure (tunnel).
4286 * @param peer_id Short ID of the peer deleted.
4287 */
4288void
4289tunnel_child_removed (void *cls, GNUNET_PEER_Id peer_id)
4290{
4291 struct MeshTunnel *t = cls;
4292
4293 client_notify_peer_disconnected (t->owner, t, peer_id);
4294}
4295
4296/**
4297 * Removes an explicit path from a tunnel, freeing all intermediate nodes
4298 * that are no longer needed, as well as nodes of no longer reachable peers.
4299 * The tunnel itself is also destoyed if results in a remote empty tunnel.
4300 *
4301 * @param t Tunnel from which to remove the path.
4302 * @param peer Short id of the peer which should be removed.
4303 */
4304static void
4305tunnel_delete_peer (struct MeshTunnel *t, GNUNET_PEER_Id peer)
4306{
4307 int r;
4308
4309 r = tree_del_peer (t->tree, peer, &tunnel_child_removed, t);
4310 if (GNUNET_NO == r)
4311 {
4312 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4313 "Tunnel %u [%u] has no more nodes\n",
4314 t->id.oid, t->id.tid);
4315 }
4316}
4317 2512
4318 2513
4319/** 2514/**
4320 * tunnel_destroy_iterator: iterator for deleting each tunnel that belongs to a 2515 * Iterator for deleting each tunnel whose client endpoint disconnected.
4321 * client when the client disconnects. If the client is not the owner, the
4322 * owner will get notified if no more clients are in the tunnel and the client
4323 * get removed from the tunnel's list.
4324 * 2516 *
4325 * @param cls closure (client that is disconnecting) 2517 * @param cls Closure (client that has disconnected).
4326 * @param key the hash of the local tunnel id (used to access the hashmap) 2518 * @param key The hash of the local tunnel id (used to access the hashmap).
4327 * @param value the value stored at the key (tunnel to destroy) 2519 * @param value The value stored at the key (tunnel to destroy).
4328 * 2520 *
4329 * @return GNUNET_OK, keep iterating. 2521 * @return GNUNET_OK, keep iterating.
4330 */ 2522 */
@@ -4336,18 +2528,33 @@ tunnel_destroy_iterator (void *cls,
4336 struct MeshTunnel *t = value; 2528 struct MeshTunnel *t = value;
4337 struct MeshClient *c = cls; 2529 struct MeshClient *c = cls;
4338 2530
4339 send_client_tunnel_disconnect (t, c); 2531 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4340 if (c != t->owner) 2532 " Tunnel %X / %X destroy, due to client %u shutdown.\n",
2533 t->local_tid, t->local_tid_dest, c->id);
2534 client_delete_tunnel (c, t);
2535 if (c == t->client)
4341 { 2536 {
4342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %u is destination.\n", c->id); 2537 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Client %u is destination.\n", c->id);
4343 tunnel_delete_client (t, c); 2538 t->client = NULL;
4344 client_delete_tunnel (c, t); 2539 if (0 != t->next_hop) { /* destroy could come before a path is used */
4345 tunnel_destroy_empty (t); 2540 GNUNET_PEER_change_rc (t->next_hop, -1);
4346 return GNUNET_OK; 2541 t->next_hop = 0;
2542 }
2543 }
2544 else if (c == t->owner)
2545 {
2546 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Client %u is owner.\n", c->id);
2547 t->owner = NULL;
2548 if (0 != t->prev_hop) { /* destroy could come before a path is used */
2549 GNUNET_PEER_change_rc (t->prev_hop, -1);
2550 t->prev_hop = 0;
2551 }
4347 } 2552 }
4348 tunnel_send_destroy (t, 0); 2553 else
4349 t->owner = NULL; 2554 {
4350 t->destroy = GNUNET_YES; 2555 GNUNET_break (0);
2556 }
2557 tunnel_destroy_empty (t);
4351 2558
4352 return GNUNET_OK; 2559 return GNUNET_OK;
4353} 2560}
@@ -4365,17 +2572,19 @@ tunnel_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
4365 struct MeshTunnel *t = cls; 2572 struct MeshTunnel *t = cls;
4366 struct GNUNET_PeerIdentity id; 2573 struct GNUNET_PeerIdentity id;
4367 2574
4368 t->timeout_task = GNUNET_SCHEDULER_NO_TASK; 2575 t->maintenance_task = GNUNET_SCHEDULER_NO_TASK;
4369 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) 2576 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
4370 return; 2577 return;
4371 GNUNET_PEER_resolve(t->id.oid, &id); 2578 GNUNET_PEER_resolve(t->id.oid, &id);
4372 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2579 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4373 "Tunnel %s [%X] timed out. Destroying.\n", 2580 "Tunnel %s [%X] timed out. Destroying.\n",
4374 GNUNET_i2s(&id), t->id.tid); 2581 GNUNET_i2s(&id), t->id.tid);
4375 send_clients_tunnel_destroy (t); 2582 if (NULL != t->client)
4376 tunnel_destroy (t); 2583 send_client_tunnel_destroy (t->client, t);
2584 tunnel_destroy (t); /* Do not notify other */
4377} 2585}
4378 2586
2587
4379/** 2588/**
4380 * Resets the tunnel timeout. Starts it if no timeout was running. 2589 * Resets the tunnel timeout. Starts it if no timeout was running.
4381 * 2590 *
@@ -4386,9 +2595,11 @@ tunnel_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
4386static void 2595static void
4387tunnel_reset_timeout (struct MeshTunnel *t) 2596tunnel_reset_timeout (struct MeshTunnel *t)
4388{ 2597{
4389 if (GNUNET_SCHEDULER_NO_TASK != t->timeout_task) 2598 if (NULL != t->owner || 0 != t->local_tid || 0 == t->prev_hop)
4390 GNUNET_SCHEDULER_cancel (t->timeout_task); 2599 return;
4391 t->timeout_task = 2600 if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task)
2601 GNUNET_SCHEDULER_cancel (t->maintenance_task);
2602 t->maintenance_task =
4392 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply 2603 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
4393 (refresh_path_time, 4), &tunnel_timeout, t); 2604 (refresh_path_time, 4), &tunnel_timeout, t);
4394} 2605}
@@ -4409,18 +2620,17 @@ tunnel_reset_timeout (struct MeshTunnel *t)
4409static size_t 2620static size_t
4410send_core_path_create (void *cls, size_t size, void *buf) 2621send_core_path_create (void *cls, size_t size, void *buf)
4411{ 2622{
4412 struct MeshPathInfo *info = cls; 2623 struct MeshTunnel *t = cls;
4413 struct GNUNET_MESH_ManipulatePath *msg; 2624 struct GNUNET_MESH_CreateTunnel *msg;
4414 struct GNUNET_PeerIdentity *peer_ptr; 2625 struct GNUNET_PeerIdentity *peer_ptr;
4415 struct MeshTunnel *t = info->t; 2626 struct MeshPeerPath *p = t->path;
4416 struct MeshPeerPath *p = info->path;
4417 size_t size_needed; 2627 size_t size_needed;
4418 uint32_t opt; 2628 uint32_t opt;
4419 int i; 2629 int i;
4420 2630
4421 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATE PATH sending...\n"); 2631 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATE PATH sending...\n");
4422 size_needed = 2632 size_needed =
4423 sizeof (struct GNUNET_MESH_ManipulatePath) + 2633 sizeof (struct GNUNET_MESH_CreateTunnel) +
4424 p->length * sizeof (struct GNUNET_PeerIdentity); 2634 p->length * sizeof (struct GNUNET_PeerIdentity);
4425 2635
4426 if (size < size_needed || NULL == buf) 2636 if (size < size_needed || NULL == buf)
@@ -4428,18 +2638,16 @@ send_core_path_create (void *cls, size_t size, void *buf)
4428 GNUNET_break (0); 2638 GNUNET_break (0);
4429 return 0; 2639 return 0;
4430 } 2640 }
4431 msg = (struct GNUNET_MESH_ManipulatePath *) buf; 2641 msg = (struct GNUNET_MESH_CreateTunnel *) buf;
4432 msg->header.size = htons (size_needed); 2642 msg->header.size = htons (size_needed);
4433 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE); 2643 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
4434 msg->tid = ntohl (t->id.tid); 2644 msg->tid = ntohl (t->id.tid);
4435 2645
4436 opt = 0; 2646 opt = 0;
4437 if (GNUNET_YES == t->speed_min)
4438 opt |= MESH_TUNNEL_OPT_SPEED_MIN;
4439 if (GNUNET_YES == t->nobuffer) 2647 if (GNUNET_YES == t->nobuffer)
4440 opt |= MESH_TUNNEL_OPT_NOBUFFER; 2648 opt |= MESH_TUNNEL_OPT_NOBUFFER;
4441 msg->opt = htonl(opt); 2649 msg->opt = htonl (opt);
4442 msg->reserved = 0; 2650 msg->port = htonl (t->port);
4443 2651
4444 peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1]; 2652 peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
4445 for (i = 0; i < p->length; i++) 2653 for (i = 0; i < p->length; i++)
@@ -4447,9 +2655,6 @@ send_core_path_create (void *cls, size_t size, void *buf)
4447 GNUNET_PEER_resolve (p->peers[i], peer_ptr++); 2655 GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
4448 } 2656 }
4449 2657
4450 path_destroy (p);
4451 GNUNET_free (info);
4452
4453 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2658 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4454 "CREATE PATH (%u bytes long) sent!\n", size_needed); 2659 "CREATE PATH (%u bytes long) sent!\n", size_needed);
4455 return size_needed; 2660 return size_needed;
@@ -4457,65 +2662,6 @@ send_core_path_create (void *cls, size_t size, void *buf)
4457 2662
4458 2663
4459/** 2664/**
4460 * Fill the core buffer
4461 *
4462 * @param cls closure (data itself)
4463 * @param size number of bytes available in buf
4464 * @param buf where the callee should write the message
4465 *
4466 * @return number of bytes written to buf
4467 */
4468static size_t
4469send_core_data_multicast (void *cls, size_t size, void *buf)
4470{
4471 struct MeshTransmissionDescriptor *info = cls;
4472 size_t total_size;
4473
4474 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Multicast callback.\n");
4475 GNUNET_assert (NULL != info);
4476 GNUNET_assert (NULL != info->peer);
4477 total_size = info->mesh_data->data_len;
4478 GNUNET_assert (total_size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
4479
4480 if (total_size > size)
4481 {
4482 GNUNET_break (0);
4483 return 0;
4484 }
4485 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " copying data...\n");
4486 memcpy (buf, info->mesh_data->data, total_size);
4487#if MESH_DEBUG
4488 {
4489 struct GNUNET_MESH_Multicast *mc;
4490 struct GNUNET_MessageHeader *mh;
4491
4492 mh = buf;
4493 if (ntohs (mh->type) == GNUNET_MESSAGE_TYPE_MESH_MULTICAST)
4494 {
4495 mc = (struct GNUNET_MESH_Multicast *) mh;
4496 mh = (struct GNUNET_MessageHeader *) &mc[1];
4497 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4498 " multicast, payload type %s\n",
4499 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
4500 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4501 " multicast, payload size %u\n", ntohs (mh->size));
4502 }
4503 else
4504 {
4505 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " type %s\n",
4506 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
4507 }
4508 }
4509#endif
4510 data_descriptor_decrement_rc (info->mesh_data);
4511 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "freeing info...\n");
4512 GNUNET_free (info);
4513 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "return %u\n", total_size);
4514 return total_size;
4515}
4516
4517
4518/**
4519 * Creates a path ack message in buf and frees all unused resources. 2665 * Creates a path ack message in buf and frees all unused resources.
4520 * 2666 *
4521 * @param cls closure (MeshTransmissionDescriptor) 2667 * @param cls closure (MeshTransmissionDescriptor)
@@ -4526,22 +2672,23 @@ send_core_data_multicast (void *cls, size_t size, void *buf)
4526static size_t 2672static size_t
4527send_core_path_ack (void *cls, size_t size, void *buf) 2673send_core_path_ack (void *cls, size_t size, void *buf)
4528{ 2674{
4529 struct MeshTransmissionDescriptor *info = cls; 2675 struct MeshTunnel *t = cls;
4530 struct GNUNET_MESH_PathACK *msg = buf; 2676 struct GNUNET_MESH_PathACK *msg = buf;
4531 2677
4532 GNUNET_assert (NULL != info); 2678 GNUNET_assert (NULL != t);
4533 if (sizeof (struct GNUNET_MESH_PathACK) > size) 2679 if (sizeof (struct GNUNET_MESH_PathACK) > size)
4534 { 2680 {
4535 GNUNET_break (0); 2681 GNUNET_break (0);
4536 return 0; 2682 return 0;
4537 } 2683 }
2684 t->prev_fc.last_ack_sent = t->nobuffer ? 0 : t->queue_max - 1;
4538 msg->header.size = htons (sizeof (struct GNUNET_MESH_PathACK)); 2685 msg->header.size = htons (sizeof (struct GNUNET_MESH_PathACK));
4539 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK); 2686 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
4540 GNUNET_PEER_resolve (info->origin->oid, &msg->oid); 2687 GNUNET_PEER_resolve (t->id.oid, &msg->oid);
4541 msg->tid = htonl (info->origin->tid); 2688 msg->tid = htonl (t->id.tid);
4542 msg->peer_id = my_full_id; 2689 msg->peer_id = my_full_id;
2690 msg->ack = htonl (t->prev_fc.last_ack_sent);
4543 2691
4544 GNUNET_free (info);
4545 /* TODO add signature */ 2692 /* TODO add signature */
4546 2693
4547 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH ACK sent!\n"); 2694 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH ACK sent!\n");
@@ -4559,12 +2706,7 @@ send_core_path_ack (void *cls, size_t size, void *buf)
4559static void 2706static void
4560queue_destroy (struct MeshPeerQueue *queue, int clear_cls) 2707queue_destroy (struct MeshPeerQueue *queue, int clear_cls)
4561{ 2708{
4562 struct MeshTransmissionDescriptor *dd; 2709 struct MeshFlowControl *fc;
4563 struct MeshPathInfo *path_info;
4564 struct MeshTunnelChildInfo *cinfo;
4565 struct GNUNET_PeerIdentity id;
4566 unsigned int i;
4567 unsigned int max;
4568 2710
4569 if (GNUNET_YES == clear_cls) 2711 if (GNUNET_YES == clear_cls)
4570 { 2712 {
@@ -4575,7 +2717,6 @@ queue_destroy (struct MeshPeerQueue *queue, int clear_cls)
4575 GNUNET_break (GNUNET_YES == queue->tunnel->destroy); 2717 GNUNET_break (GNUNET_YES == queue->tunnel->destroy);
4576 /* fall through */ 2718 /* fall through */
4577 case GNUNET_MESSAGE_TYPE_MESH_UNICAST: 2719 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
4578 case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
4579 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: 2720 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
4580 case GNUNET_MESSAGE_TYPE_MESH_ACK: 2721 case GNUNET_MESSAGE_TYPE_MESH_ACK:
4581 case GNUNET_MESSAGE_TYPE_MESH_POLL: 2722 case GNUNET_MESSAGE_TYPE_MESH_POLL:
@@ -4584,20 +2725,16 @@ queue_destroy (struct MeshPeerQueue *queue, int clear_cls)
4584 " prebuilt message\n"); 2725 " prebuilt message\n");
4585 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2726 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4586 " type %s\n", 2727 " type %s\n",
4587 GNUNET_MESH_DEBUG_M2S(queue->type)); 2728 GNUNET_MESH_DEBUG_M2S (queue->type));
4588 dd = queue->cls;
4589 data_descriptor_decrement_rc (dd->mesh_data);
4590 break; 2729 break;
4591 case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE: 2730 case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
4592 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " type create path\n"); 2731 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " type create path\n");
4593 path_info = queue->cls;
4594 path_destroy (path_info->path);
4595 break; 2732 break;
4596 default: 2733 default:
4597 GNUNET_break (0); 2734 GNUNET_break (0);
4598 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2735 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4599 " type %s unknown!\n", 2736 " type %s unknown!\n",
4600 GNUNET_MESH_DEBUG_M2S(queue->type)); 2737 GNUNET_MESH_DEBUG_M2S (queue->type));
4601 } 2738 }
4602 GNUNET_free_non_null (queue->cls); 2739 GNUNET_free_non_null (queue->cls);
4603 } 2740 }
@@ -4605,36 +2742,21 @@ queue_destroy (struct MeshPeerQueue *queue, int clear_cls)
4605 queue->peer->queue_tail, 2742 queue->peer->queue_tail,
4606 queue); 2743 queue);
4607 2744
4608 /* Delete from child_fc in the appropiate tunnel */ 2745 /* Delete from appropriate fc in the tunnel */
4609 max = queue->tunnel->fwd_queue_max; 2746 if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == queue->type ||
4610 GNUNET_PEER_resolve (queue->peer->id, &id); 2747 GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == queue->type )
4611 cinfo = tunnel_get_neighbor_fc (queue->tunnel, &id);
4612 if (NULL != cinfo)
4613 { 2748 {
4614 for (i = 0; i < cinfo->send_buffer_n; i++) 2749 if (queue->peer->id == queue->tunnel->prev_hop)
2750 fc = &queue->tunnel->prev_fc;
2751 else if (queue->peer->id == queue->tunnel->next_hop)
2752 fc = &queue->tunnel->next_fc;
2753 else
4615 { 2754 {
4616 unsigned int i2; 2755 GNUNET_break (0);
4617 i2 = (cinfo->send_buffer_start + i) % max; 2756 return;
4618 if (cinfo->send_buffer[i2] == queue)
4619 {
4620 /* Found corresponding entry in the send_buffer. Move all others back. */
4621 unsigned int j;
4622 unsigned int j2;
4623 unsigned int j3;
4624
4625 for (j = i, j2 = 0, j3 = 0; j < cinfo->send_buffer_n - 1; j++)
4626 {
4627 j2 = (cinfo->send_buffer_start + j) % max;
4628 j3 = (cinfo->send_buffer_start + j + 1) % max;
4629 cinfo->send_buffer[j2] = cinfo->send_buffer[j3];
4630 }
4631
4632 cinfo->send_buffer[j3] = NULL;
4633 cinfo->send_buffer_n--;
4634 }
4635 } 2757 }
2758 fc->queue_n--;
4636 } 2759 }
4637
4638 GNUNET_free (queue); 2760 GNUNET_free (queue);
4639} 2761}
4640 2762
@@ -4654,308 +2776,220 @@ struct MeshPeerQueue *
4654queue_get_next (const struct MeshPeerInfo *peer) 2776queue_get_next (const struct MeshPeerInfo *peer)
4655{ 2777{
4656 struct MeshPeerQueue *q; 2778 struct MeshPeerQueue *q;
4657 struct MeshTunnel *t; 2779
4658 struct MeshTransmissionDescriptor *info; 2780 struct GNUNET_MESH_Data *dmsg;
4659 struct MeshTunnelChildInfo *cinfo; 2781 struct MeshTunnel* t;
4660 struct GNUNET_MESH_Unicast *ucast;
4661 struct GNUNET_MESH_ToOrigin *to_orig;
4662 struct GNUNET_MESH_Multicast *mcast;
4663 struct GNUNET_PeerIdentity id;
4664 uint32_t pid; 2782 uint32_t pid;
4665 uint32_t ack; 2783 uint32_t ack;
4666 2784
4667 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* selecting message\n"); 2785 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* selecting message\n");
4668 for (q = peer->queue_head; NULL != q; q = q->next) 2786 for (q = peer->queue_head; NULL != q; q = q->next)
4669 { 2787 {
4670 t = q->tunnel; 2788 t = q->tunnel;
4671 info = q->cls;
4672 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2789 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4673 "********* %s\n", 2790 "* %s\n",
4674 GNUNET_MESH_DEBUG_M2S(q->type)); 2791 GNUNET_MESH_DEBUG_M2S (q->type));
2792 dmsg = (struct GNUNET_MESH_Data *) q->cls;
2793 pid = ntohl (dmsg->pid);
4675 switch (q->type) 2794 switch (q->type)
4676 { 2795 {
4677 case GNUNET_MESSAGE_TYPE_MESH_UNICAST: 2796 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
4678 ucast = (struct GNUNET_MESH_Unicast *) info->mesh_data->data; 2797 ack = t->next_fc.last_ack_recv;
4679 pid = ntohl (ucast->pid);
4680 GNUNET_PEER_resolve (info->peer->id, &id);
4681 cinfo = tunnel_get_neighbor_fc(t, &id);
4682 ack = cinfo->fwd_ack;
4683 break; 2798 break;
4684 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: 2799 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
4685 to_orig = (struct GNUNET_MESH_ToOrigin *) info->mesh_data->data; 2800 ack = t->prev_fc.last_ack_recv;
4686 pid = ntohl (to_orig->pid);
4687 ack = t->bck_ack;
4688 break;
4689 case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
4690 mcast = (struct GNUNET_MESH_Multicast *) info->mesh_data->data;
4691 if (GNUNET_MESSAGE_TYPE_MESH_MULTICAST != ntohs(mcast->header.type))
4692 {
4693 // Not a multicast payload: multicast control traffic (destroy, etc)
4694 return q;
4695 }
4696 pid = ntohl (mcast->pid);
4697 GNUNET_PEER_resolve (info->peer->id, &id);
4698 cinfo = tunnel_get_neighbor_fc(t, &id);
4699 ack = cinfo->fwd_ack;
4700 break; 2801 break;
4701 default: 2802 default:
4702 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2803 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4703 "********* OK!\n"); 2804 "* OK!\n");
4704 return q; 2805 return q;
4705 } 2806 }
4706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4707 "********* ACK: %u, PID: %u\n", 2808 "* ACK: %u, PID: %u\n",
4708 ack, pid); 2809 ack, pid);
4709 if (GNUNET_NO == GMC_is_pid_bigger(pid, ack)) 2810 if (GNUNET_NO == GMC_is_pid_bigger (pid, ack))
4710 { 2811 {
4711 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2812 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4712 "********* OK!\n"); 2813 "* OK!\n");
4713 return q; 2814 return q;
4714 } 2815 }
4715 else 2816 else
4716 { 2817 {
4717 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2818 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4718 "********* NEXT!\n"); 2819 "* NEXT!\n");
4719 } 2820 }
4720 } 2821 }
4721 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2822 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4722 "********* nothing found\n"); 2823 "* nothing found\n");
4723 return NULL; 2824 return NULL;
4724} 2825}
4725 2826
4726 2827
4727/**
4728 * Core callback to write a queued packet to core buffer
4729 *
4730 * @param cls Closure (peer info).
4731 * @param size Number of bytes available in buf.
4732 * @param buf Where the to write the message.
4733 *
4734 * @return number of bytes written to buf
4735 */
4736static size_t 2828static size_t
4737queue_send (void *cls, size_t size, void *buf) 2829queue_send (void *cls, size_t size, void *buf)
4738{ 2830{
4739 struct MeshPeerInfo *peer = cls; 2831 struct MeshPeerInfo *peer = cls;
4740 struct GNUNET_MessageHeader *msg; 2832 struct GNUNET_MessageHeader *msg;
4741 struct MeshPeerQueue *queue; 2833 struct MeshPeerQueue *queue;
4742 struct MeshTunnel *t; 2834 struct MeshTunnel *t;
4743 struct MeshTunnelChildInfo *cinfo; 2835 struct GNUNET_PeerIdentity dst_id;
4744 struct GNUNET_PeerIdentity dst_id; 2836 struct MeshFlowControl *fc;
4745 size_t data_size; 2837 size_t data_size;
4746 2838 uint32_t pid;
4747 peer->core_transmit = NULL; 2839 uint16_t type;
4748 cinfo = NULL; 2840
4749 2841 peer->core_transmit = NULL;
4750 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* Queue send\n"); 2842
4751 queue = queue_get_next (peer); 2843 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Queue send\n");
4752 2844 queue = queue_get_next (peer);
4753 /* Queue has no internal mesh traffic nor sendable payload */ 2845
4754 if (NULL == queue) 2846 /* Queue has no internal mesh traffic nor sendable payload */
4755 { 2847 if (NULL == queue)
4756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* not ready, return\n"); 2848 {
4757 if (NULL == peer->queue_head) 2849 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* not ready, return\n");
4758 GNUNET_break (0); // Should've been canceled 2850 if (NULL == peer->queue_head)
2851 GNUNET_break (0); /* Core tmt_rdy should've been canceled */
2852 return 0;
2853 }
2854 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* not empty\n");
2855
2856 GNUNET_PEER_resolve (peer->id, &dst_id);
2857 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2858 "* towards %s\n",
2859 GNUNET_i2s (&dst_id));
2860 /* Check if buffer size is enough for the message */
2861 if (queue->size > size)
2862 {
2863 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2864 "* not enough room, reissue\n");
2865 peer->core_transmit =
2866 GNUNET_CORE_notify_transmit_ready (core_handle,
2867 GNUNET_NO,
2868 0,
2869 GNUNET_TIME_UNIT_FOREVER_REL,
2870 &dst_id,
2871 queue->size,
2872 &queue_send,
2873 peer);
4759 return 0; 2874 return 0;
4760 } 2875 }
4761 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* not empty\n"); 2876 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* size ok\n");
4762 2877
4763 GNUNET_PEER_resolve (peer->id, &dst_id); 2878 t = queue->tunnel;
4764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2879 GNUNET_assert (0 < t->pending_messages);
4765 "********* towards %s\n", 2880 t->pending_messages--;
4766 GNUNET_i2s(&dst_id)); 2881 type = 0;
4767 /* Check if buffer size is enough for the message */
4768 if (queue->size > size)
4769 {
4770 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4771 "********* not enough room, reissue\n");
4772 peer->core_transmit =
4773 GNUNET_CORE_notify_transmit_ready (core_handle,
4774 0,
4775 0,
4776 GNUNET_TIME_UNIT_FOREVER_REL,
4777 &dst_id,
4778 queue->size,
4779 &queue_send,
4780 peer);
4781 return 0;
4782 }
4783 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* size ok\n");
4784 2882
4785 t = queue->tunnel; 2883 /* Fill buf */
4786 GNUNET_assert (0 < t->pending_messages); 2884 switch (queue->type)
4787 t->pending_messages--; 2885 {
4788 if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == queue->type) 2886 case 0:
4789 { 2887 case GNUNET_MESSAGE_TYPE_MESH_ACK:
4790 t->fwd_queue_n--; 2888 case GNUNET_MESSAGE_TYPE_MESH_POLL:
2889 case GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN:
2890 case GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY:
2891 case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
2892 case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE:
4791 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2893 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4792 "********* unicast: t->q (%u/%u)\n", 2894 "* raw: %s\n",
4793 t->fwd_queue_n, t->fwd_queue_max); 2895 GNUNET_MESH_DEBUG_M2S (queue->type));
4794 } 2896 /* Fall through */
4795 else if (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == queue->type) 2897 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
4796 { 2898 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
4797 t->bck_queue_n--; 2899 data_size = send_core_data_raw (queue->cls, size, buf);
4798 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* to origin\n"); 2900 msg = (struct GNUNET_MessageHeader *) buf;
4799 } 2901 type = ntohs (msg->type);
2902 break;
2903 case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
2904 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* path create\n");
2905 data_size = send_core_path_create (queue->cls, size, buf);
2906 break;
2907 case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
2908 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* path ack\n");
2909 data_size = send_core_path_ack (queue->cls, size, buf);
2910 break;
2911 default:
2912 GNUNET_break (0);
2913 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2914 "* type unknown: %u\n",
2915 queue->type);
2916 data_size = 0;
2917 }
4800 2918
4801 /* Fill buf */ 2919 /* Free queue, but cls was freed by send_core_* */
4802 switch (queue->type) 2920 queue_destroy (queue, GNUNET_NO);
4803 { 2921
4804 case 0: 2922 /* Send ACK if needed, after accounting for sent ID in fc->queue_n */
4805 case GNUNET_MESSAGE_TYPE_MESH_ACK: 2923 pid = ((struct GNUNET_MESH_Data *) buf)->pid;
4806 case GNUNET_MESSAGE_TYPE_MESH_POLL: 2924 switch (type)
4807 case GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN: 2925 {
4808 case GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY: 2926 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
4809 case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY: 2927 t->next_fc.last_pid_sent = pid;
4810 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2928 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST);
4811 "********* raw: %s\n", 2929 break;
4812 GNUNET_MESH_DEBUG_M2S (queue->type)); 2930 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
4813 /* Fall through */ 2931 t->prev_fc.last_pid_sent = pid;
4814 case GNUNET_MESSAGE_TYPE_MESH_UNICAST: 2932 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
4815 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: 2933 break;
4816 data_size = send_core_data_raw (queue->cls, size, buf); 2934 default:
4817 msg = (struct GNUNET_MessageHeader *) buf; 2935 break;
4818 switch (ntohs (msg->type)) // Type of preconstructed message 2936 }
4819 {
4820 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
4821 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST);
4822 break;
4823 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
4824 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
4825 break;
4826 default:
4827 break;
4828 }
4829 break;
4830 case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
4831 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* multicast\n");
4832 {
4833 struct MeshTransmissionDescriptor *info = queue->cls;
4834
4835 if ((1 == info->mesh_data->reference_counter
4836 && GNUNET_YES == t->speed_min)
4837 ||
4838 (info->mesh_data->total_out == info->mesh_data->reference_counter
4839 && GNUNET_NO == t->speed_min))
4840 {
4841 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4842 "********* considered sent\n");
4843 t->fwd_queue_n--;
4844 }
4845 else
4846 {
4847 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4848 "********* NOT considered sent yet\n");
4849 t->pending_messages++;
4850 }
4851 }
4852 data_size = send_core_data_multicast(queue->cls, size, buf);
4853 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
4854 break;
4855 case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
4856 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* path create\n");
4857 data_size = send_core_path_create (queue->cls, size, buf);
4858 break;
4859 case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
4860 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* path ack\n");
4861 data_size = send_core_path_ack (queue->cls, size, buf);
4862 break;
4863 case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE:
4864 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* path keepalive\n");
4865 data_size = send_core_data_multicast (queue->cls, size, buf);
4866 break;
4867 default:
4868 GNUNET_break (0);
4869 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
4870 "********* type unknown: %u\n",
4871 queue->type);
4872 data_size = 0;
4873 }
4874 switch (queue->type)
4875 {
4876 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
4877 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
4878 case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
4879 cinfo = tunnel_get_neighbor_fc (t, &dst_id);
4880 if (cinfo->send_buffer[cinfo->send_buffer_start] != queue)
4881 {
4882 GNUNET_break (0);
4883 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4884 "at pos %u (%p) != %p\n",
4885 cinfo->send_buffer_start,
4886 cinfo->send_buffer[cinfo->send_buffer_start],
4887 queue);
4888 }
4889 if (cinfo->send_buffer_n > 0)
4890 {
4891 cinfo->send_buffer[cinfo->send_buffer_start] = NULL;
4892 cinfo->send_buffer_n--;
4893 cinfo->send_buffer_start++;
4894 cinfo->send_buffer_start %= t->fwd_queue_max;
4895 }
4896 else
4897 {
4898 GNUNET_break (0);
4899 }
4900 break;
4901 default:
4902 break;
4903 }
4904 2937
4905 /* Free queue, but cls was freed by send_core_* */ 2938 if (GNUNET_YES == t->destroy && 0 == t->pending_messages)
4906 queue_destroy (queue, GNUNET_NO); 2939 {
2940 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* destroying tunnel!\n");
2941 tunnel_destroy (t);
2942 }
4907 2943
4908 if (GNUNET_YES == t->destroy && 0 == t->pending_messages) 2944 /* If more data in queue, send next */
4909 { 2945 queue = queue_get_next (peer);
4910 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* destroying tunnel!\n"); 2946 if (NULL != queue)
4911 tunnel_destroy (t); 2947 {
4912 } 2948 struct GNUNET_PeerIdentity id;
4913 2949
4914 /* If more data in queue, send next */ 2950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* more data!\n");
4915 queue = queue_get_next(peer); 2951 GNUNET_PEER_resolve (peer->id, &id);
4916 if (NULL != queue) 2952 peer->core_transmit =
2953 GNUNET_CORE_notify_transmit_ready(core_handle,
2954 0,
2955 0,
2956 GNUNET_TIME_UNIT_FOREVER_REL,
2957 &id,
2958 queue->size,
2959 &queue_send,
2960 peer);
2961 }
2962 else if (NULL != peer->queue_head)
2963 {
2964 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2965 "* %s stalled\n",
2966 GNUNET_i2s (&my_full_id));
2967 if (peer->id == t->next_hop)
2968 fc = &t->next_fc;
2969 else if (peer->id == t->prev_hop)
2970 fc = &t->prev_fc;
2971 else
4917 { 2972 {
4918 struct GNUNET_PeerIdentity id; 2973 GNUNET_break (0);
4919 2974 fc = NULL;
4920 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* more data!\n");
4921 GNUNET_PEER_resolve (peer->id, &id);
4922 peer->core_transmit =
4923 GNUNET_CORE_notify_transmit_ready(core_handle,
4924 0,
4925 0,
4926 GNUNET_TIME_UNIT_FOREVER_REL,
4927 &id,
4928 queue->size,
4929 &queue_send,
4930 peer);
4931 } 2975 }
4932 else 2976 if (NULL != fc && GNUNET_SCHEDULER_NO_TASK == fc->poll_task)
4933 { 2977 {
4934 if (NULL != peer->queue_head) 2978 fc->t = t;
4935 { 2979 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
4936 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2980 &tunnel_poll, fc);
4937 "********* %s stalled\n",
4938 GNUNET_i2s(&my_full_id));
4939 if (NULL == cinfo)
4940 cinfo = tunnel_get_neighbor_fc (t, &dst_id);
4941 // FIXME unify bck/fwd structures, bck does not have cinfo right now
4942 if (NULL != cinfo && GNUNET_SCHEDULER_NO_TASK == cinfo->fc_poll)
4943 {
4944 cinfo->fc_poll = GNUNET_SCHEDULER_add_delayed (cinfo->fc_poll_time,
4945 &tunnel_poll, cinfo);
4946 }
4947 }
4948 } 2981 }
4949 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* return %d\n", data_size); 2982 }
4950 return data_size; 2983 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Return %d\n", data_size);
2984 return data_size;
4951} 2985}
4952 2986
4953 2987
4954/** 2988/**
4955 * @brief Queue and pass message to core when possible. 2989 * @brief Queue and pass message to core when possible.
4956 * 2990 *
4957 * If type is payload (UNICAST, TO_ORIGIN, MULTICAST) checks for queue status 2991 * If type is payload (UNICAST, TO_ORIGIN) checks for queue status and
4958 * and accounts for it. In case the queue is full, the message is dropped and 2992 * accounts for it. In case the queue is full, the message is dropped and
4959 * a break issued. 2993 * a break issued.
4960 * 2994 *
4961 * Otherwise, message is treated as internal and allowed to go regardless of 2995 * Otherwise, message is treated as internal and allowed to go regardless of
@@ -4973,33 +3007,30 @@ queue_add (void *cls, uint16_t type, size_t size,
4973 struct MeshPeerInfo *dst, struct MeshTunnel *t) 3007 struct MeshPeerInfo *dst, struct MeshTunnel *t)
4974{ 3008{
4975 struct MeshPeerQueue *queue; 3009 struct MeshPeerQueue *queue;
4976 struct MeshTunnelChildInfo *cinfo;
4977 struct GNUNET_PeerIdentity id; 3010 struct GNUNET_PeerIdentity id;
4978 unsigned int *max;
4979 unsigned int *n; 3011 unsigned int *n;
4980 unsigned int i;
4981 3012
4982 n = NULL; 3013 n = NULL;
4983 if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type || 3014 if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type)
4984 GNUNET_MESSAGE_TYPE_MESH_MULTICAST == type)
4985 { 3015 {
4986 n = &t->fwd_queue_n; 3016 n = &t->next_fc.queue_n;
4987 max = &t->fwd_queue_max;
4988 } 3017 }
4989 else if (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == type) 3018 else if (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == type)
4990 { 3019 {
4991 n = &t->bck_queue_n; 3020 n = &t->prev_fc.queue_n;
4992 max = &t->bck_queue_max;
4993 } 3021 }
4994 if (NULL != n) 3022 if (NULL != n)
4995 { 3023 {
4996 if (*n >= *max) 3024 if (*n >= t->queue_max)
4997 { 3025 {
4998 GNUNET_break(0); 3026 GNUNET_break(0);
3027 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3028 "queue full: %u/%u\n",
3029 *n, t->queue_max);
4999 GNUNET_STATISTICS_update(stats, 3030 GNUNET_STATISTICS_update(stats,
5000 "# messages dropped (buffer full)", 3031 "# messages dropped (buffer full)",
5001 1, GNUNET_NO); 3032 1, GNUNET_NO);
5002 return; // Drop message 3033 return; /* Drop message */
5003 } 3034 }
5004 (*n)++; 3035 (*n)++;
5005 } 3036 }
@@ -5010,43 +3041,20 @@ queue_add (void *cls, uint16_t type, size_t size,
5010 queue->peer = dst; 3041 queue->peer = dst;
5011 queue->tunnel = t; 3042 queue->tunnel = t;
5012 GNUNET_CONTAINER_DLL_insert_tail (dst->queue_head, dst->queue_tail, queue); 3043 GNUNET_CONTAINER_DLL_insert_tail (dst->queue_head, dst->queue_tail, queue);
5013 GNUNET_PEER_resolve (dst->id, &id);
5014 if (NULL == dst->core_transmit) 3044 if (NULL == dst->core_transmit)
5015 { 3045 {
5016 dst->core_transmit = 3046 GNUNET_PEER_resolve (dst->id, &id);
5017 GNUNET_CORE_notify_transmit_ready (core_handle, 3047 dst->core_transmit =
5018 0, 3048 GNUNET_CORE_notify_transmit_ready (core_handle,
5019 0, 3049 0,
5020 GNUNET_TIME_UNIT_FOREVER_REL, 3050 0,
5021 &id, 3051 GNUNET_TIME_UNIT_FOREVER_REL,
5022 size, 3052 &id,
5023 &queue_send, 3053 size,
5024 dst); 3054 &queue_send,
3055 dst);
5025 } 3056 }
5026 t->pending_messages++; 3057 t->pending_messages++;
5027 if (NULL == n) // Is this internal mesh traffic?
5028 return;
5029
5030 // It's payload, keep track of buffer per peer.
5031 cinfo = tunnel_get_neighbor_fc(t, &id);
5032 i = (cinfo->send_buffer_start + cinfo->send_buffer_n) % t->fwd_queue_max;
5033 if (NULL != cinfo->send_buffer[i])
5034 {
5035 GNUNET_break (cinfo->send_buffer_n == t->fwd_queue_max); // aka i == start
5036 queue_destroy (cinfo->send_buffer[cinfo->send_buffer_start], GNUNET_YES);
5037 cinfo->send_buffer_start++;
5038 cinfo->send_buffer_start %= t->fwd_queue_max;
5039 }
5040 else
5041 {
5042 cinfo->send_buffer_n++;
5043 }
5044 cinfo->send_buffer[i] = queue;
5045 if (cinfo->send_buffer_n > t->fwd_queue_max)
5046 {
5047 GNUNET_break (0);
5048 cinfo->send_buffer_n = t->fwd_queue_max;
5049 }
5050} 3058}
5051 3059
5052 3060
@@ -5073,9 +3081,8 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
5073 uint16_t size; 3081 uint16_t size;
5074 uint16_t i; 3082 uint16_t i;
5075 MESH_TunnelNumber tid; 3083 MESH_TunnelNumber tid;
5076 struct GNUNET_MESH_ManipulatePath *msg; 3084 struct GNUNET_MESH_CreateTunnel *msg;
5077 struct GNUNET_PeerIdentity *pi; 3085 struct GNUNET_PeerIdentity *pi;
5078 struct GNUNET_HashCode hash;
5079 struct MeshPeerPath *path; 3086 struct MeshPeerPath *path;
5080 struct MeshPeerInfo *dest_peer_info; 3087 struct MeshPeerInfo *dest_peer_info;
5081 struct MeshPeerInfo *orig_peer_info; 3088 struct MeshPeerInfo *orig_peer_info;
@@ -5085,33 +3092,33 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
5085 "Received a path create msg [%s]\n", 3092 "Received a path create msg [%s]\n",
5086 GNUNET_i2s (&my_full_id)); 3093 GNUNET_i2s (&my_full_id));
5087 size = ntohs (message->size); 3094 size = ntohs (message->size);
5088 if (size < sizeof (struct GNUNET_MESH_ManipulatePath)) 3095 if (size < sizeof (struct GNUNET_MESH_CreateTunnel))
5089 { 3096 {
5090 GNUNET_break_op (0); 3097 GNUNET_break_op (0);
5091 return GNUNET_OK; 3098 return GNUNET_OK;
5092 } 3099 }
5093 3100
5094 size -= sizeof (struct GNUNET_MESH_ManipulatePath); 3101 size -= sizeof (struct GNUNET_MESH_CreateTunnel);
5095 if (size % sizeof (struct GNUNET_PeerIdentity)) 3102 if (size % sizeof (struct GNUNET_PeerIdentity))
5096 { 3103 {
5097 GNUNET_break_op (0); 3104 GNUNET_break_op (0);
5098 return GNUNET_OK; 3105 return GNUNET_OK;
5099 } 3106 }
5100 size /= sizeof (struct GNUNET_PeerIdentity); 3107 size /= sizeof (struct GNUNET_PeerIdentity);
5101 if (size < 2) 3108 if (size < 1)
5102 { 3109 {
5103 GNUNET_break_op (0); 3110 GNUNET_break_op (0);
5104 return GNUNET_OK; 3111 return GNUNET_OK;
5105 } 3112 }
5106 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size); 3113 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size);
5107 msg = (struct GNUNET_MESH_ManipulatePath *) message; 3114 msg = (struct GNUNET_MESH_CreateTunnel *) message;
5108 3115
5109 tid = ntohl (msg->tid); 3116 tid = ntohl (msg->tid);
5110 pi = (struct GNUNET_PeerIdentity *) &msg[1]; 3117 pi = (struct GNUNET_PeerIdentity *) &msg[1];
5111 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3118 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5112 " path is for tunnel %s [%X].\n", GNUNET_i2s (pi), tid); 3119 " path is for tunnel %s[%X].\n", GNUNET_i2s (pi), tid);
5113 t = tunnel_get (pi, tid); 3120 t = tunnel_get (pi, tid);
5114 if (NULL == t) // FIXME only for INCOMING tunnels? 3121 if (NULL == t) /* might be a local tunnel */
5115 { 3122 {
5116 uint32_t opt; 3123 uint32_t opt;
5117 3124
@@ -5119,45 +3126,21 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
5119 t = tunnel_new (GNUNET_PEER_intern (pi), tid, NULL, 0); 3126 t = tunnel_new (GNUNET_PEER_intern (pi), tid, NULL, 0);
5120 if (NULL == t) 3127 if (NULL == t)
5121 { 3128 {
5122 // FIXME notify failure 3129 GNUNET_break (0);
5123 return GNUNET_OK; 3130 return GNUNET_OK;
5124 } 3131 }
3132 t->port = ntohl (msg->port);
5125 opt = ntohl (msg->opt); 3133 opt = ntohl (msg->opt);
5126 t->speed_min = (0 != (opt & MESH_TUNNEL_OPT_SPEED_MIN)) ?
5127 GNUNET_YES : GNUNET_NO;
5128 if (0 != (opt & MESH_TUNNEL_OPT_NOBUFFER)) 3134 if (0 != (opt & MESH_TUNNEL_OPT_NOBUFFER))
5129 { 3135 {
5130 t->nobuffer = GNUNET_YES; 3136 t->nobuffer = GNUNET_YES;
5131 t->last_fwd_ack = t->fwd_pid + 1; 3137 t->queue_max = 1;
5132 }
5133 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5134 " speed_min: %d, nobuffer:%d\n",
5135 t->speed_min, t->nobuffer);
5136
5137 if (GNUNET_YES == t->nobuffer)
5138 {
5139 t->bck_queue_max = 1;
5140 t->fwd_queue_max = 1;
5141 } 3138 }
5142 3139 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " nobuffer:%d\n", t->nobuffer);
5143 // FIXME only assign a local tid if a local client is interested (on demand)
5144 while (NULL != tunnel_get_incoming (next_local_tid))
5145 next_local_tid = (next_local_tid + 1) | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
5146 t->local_tid_dest = next_local_tid++;
5147 next_local_tid = next_local_tid | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
5148 // FIXME end
5149 3140
5150 tunnel_reset_timeout (t); 3141 tunnel_reset_timeout (t);
5151 GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
5152 if (GNUNET_OK !=
5153 GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
5154 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
5155 {
5156 tunnel_destroy (t);
5157 GNUNET_break (0);
5158 return GNUNET_OK;
5159 }
5160 } 3142 }
3143 t->state = MESH_TUNNEL_WAITING;
5161 dest_peer_info = 3144 dest_peer_info =
5162 GNUNET_CONTAINER_multihashmap_get (peers, &pi[size - 1].hashPubKey); 3145 GNUNET_CONTAINER_multihashmap_get (peers, &pi[size - 1].hashPubKey);
5163 if (NULL == dest_peer_info) 3146 if (NULL == dest_peer_info)
@@ -5192,9 +3175,8 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
5192 own_pos = i; 3175 own_pos = i;
5193 } 3176 }
5194 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos); 3177 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos);
5195 if (own_pos == 0) 3178 if (own_pos == 0 && path->peers[own_pos] != myid)
5196 { 3179 {
5197 /* cannot be self, must be 'not found' */
5198 /* create path: self not found in path through self */ 3180 /* create path: self not found in path through self */
5199 GNUNET_break_op (0); 3181 GNUNET_break_op (0);
5200 path_destroy (path); 3182 path_destroy (path);
@@ -5202,43 +3184,58 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
5202 return GNUNET_OK; 3184 return GNUNET_OK;
5203 } 3185 }
5204 path_add_to_peers (path, GNUNET_NO); 3186 path_add_to_peers (path, GNUNET_NO);
5205 tunnel_add_path (t, path, own_pos); 3187 tunnel_use_path (t, path);
3188
3189 peer_info_add_tunnel (dest_peer_info, t);
3190
5206 if (own_pos == size - 1) 3191 if (own_pos == size - 1)
5207 { 3192 {
5208 /* It is for us! Send ack. */ 3193 struct MeshClient *c;
5209 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n"); 3194 struct GNUNET_HashCode hc;
5210 peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_NO); 3195
5211 if (NULL == t->peers) 3196 /* Find target client */
3197 GMC_hash32 (t->port, &hc);
3198 c = GNUNET_CONTAINER_multihashmap_get (ports, &hc);
3199 if (NULL == c)
5212 { 3200 {
5213 /* New tunnel! Notify clients on first payload message. */ 3201 /* TODO send reject */
5214 t->peers = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_NO); 3202 return GNUNET_OK;
5215 } 3203 }
5216 GNUNET_break (GNUNET_SYSERR != 3204
5217 GNUNET_CONTAINER_multihashmap_put (t->peers, 3205 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n");
5218 &my_full_id.hashPubKey, 3206 peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_YES);
5219 peer_info_get 3207
5220 (&my_full_id), 3208 /* Assign local tid */
5221 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE)); 3209 while (NULL != tunnel_get_incoming (next_local_tid))
3210 next_local_tid = (next_local_tid + 1) | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
3211 t->local_tid_dest = next_local_tid++;
3212 next_local_tid = next_local_tid | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
3213
3214 tunnel_add_client (t, c);
3215 send_client_tunnel_create (t);
5222 send_path_ack (t); 3216 send_path_ack (t);
5223 } 3217 }
5224 else 3218 else
5225 { 3219 {
5226 struct MeshPeerPath *path2; 3220 struct MeshPeerPath *path2;
5227 3221
3222 t->next_hop = path->peers[own_pos + 1];
3223 GNUNET_PEER_change_rc(t->next_hop, 1);
3224
5228 /* It's for somebody else! Retransmit. */ 3225 /* It's for somebody else! Retransmit. */
5229 path2 = path_duplicate (path);
5230 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n"); 3226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n");
5231 peer_info_add_path (dest_peer_info, path2, GNUNET_NO);
5232 path2 = path_duplicate (path); 3227 path2 = path_duplicate (path);
5233 peer_info_add_path_to_origin (orig_peer_info, path2, GNUNET_NO); 3228 peer_info_add_path (dest_peer_info, path2, GNUNET_NO);
5234 send_create_path (dest_peer_info, path, t); 3229 peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_NO);
3230 send_create_path (t);
5235 } 3231 }
5236 return GNUNET_OK; 3232 return GNUNET_OK;
5237} 3233}
5238 3234
5239 3235
3236
5240/** 3237/**
5241 * Core handler for path destruction 3238 * Core handler for path ACKs
5242 * 3239 *
5243 * @param cls closure 3240 * @param cls closure
5244 * @param message message 3241 * @param message message
@@ -5248,71 +3245,72 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
5248 * GNUNET_SYSERR to close it (signal serious error) 3245 * GNUNET_SYSERR to close it (signal serious error)
5249 */ 3246 */
5250static int 3247static int
5251handle_mesh_path_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, 3248handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
5252 const struct GNUNET_MessageHeader *message) 3249 const struct GNUNET_MessageHeader *message)
5253{ 3250{
5254 struct GNUNET_MESH_ManipulatePath *msg; 3251 struct GNUNET_MESH_PathACK *msg;
5255 struct GNUNET_PeerIdentity *pi; 3252 struct MeshPeerInfo *peer_info;
5256 struct MeshPeerPath *path; 3253 struct MeshPeerPath *p;
5257 struct MeshTunnel *t; 3254 struct MeshTunnel *t;
5258 unsigned int own_pos;
5259 unsigned int i;
5260 size_t size;
5261 3255
5262 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a path ACK msg [%s]\n",
5263 "Received a PATH DESTROY msg from %s\n", GNUNET_i2s (peer)); 3257 GNUNET_i2s (&my_full_id));
5264 size = ntohs (message->size); 3258 msg = (struct GNUNET_MESH_PathACK *) message;
5265 if (size < sizeof (struct GNUNET_MESH_ManipulatePath)) 3259 t = tunnel_get (&msg->oid, ntohl(msg->tid));
3260 if (NULL == t)
5266 { 3261 {
5267 GNUNET_break_op (0); 3262 /* TODO notify that we don't know the tunnel */
3263 GNUNET_STATISTICS_update (stats, "# control on unknown tunnel", 1, GNUNET_NO);
3264 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " don't know the tunnel %s [%X]!\n",
3265 GNUNET_i2s (&msg->oid), ntohl(msg->tid));
5268 return GNUNET_OK; 3266 return GNUNET_OK;
5269 } 3267 }
3268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %s [%X]\n",
3269 GNUNET_i2s (&msg->oid), ntohl(msg->tid));
5270 3270
5271 size -= sizeof (struct GNUNET_MESH_ManipulatePath); 3271 peer_info = peer_get (&msg->peer_id);
5272 if (size % sizeof (struct GNUNET_PeerIdentity)) 3272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by peer %s\n",
3273 GNUNET_i2s (&msg->peer_id));
3274 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n",
3275 GNUNET_i2s (peer));
3276
3277 /* Add path to peers? */
3278 p = t->path;
3279 if (NULL != p)
5273 { 3280 {
5274 GNUNET_break_op (0); 3281 path_add_to_peers (p, GNUNET_YES);
5275 return GNUNET_OK;
5276 } 3282 }
5277 size /= sizeof (struct GNUNET_PeerIdentity); 3283 else
5278 if (size < 2)
5279 { 3284 {
5280 GNUNET_break_op (0); 3285 GNUNET_break (0);
5281 return GNUNET_OK;
5282 } 3286 }
5283 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size); 3287 t->state = MESH_TUNNEL_READY;
3288 t->next_fc.last_ack_recv = (NULL == t->client) ? ntohl (msg->ack) : 0;
3289 t->prev_fc.last_ack_sent = ntohl (msg->ack);
5284 3290
5285 msg = (struct GNUNET_MESH_ManipulatePath *) message; 3291 /* Message for us? */
5286 pi = (struct GNUNET_PeerIdentity *) &msg[1]; 3292 if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct GNUNET_PeerIdentity)))
5287 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5288 " path is for tunnel %s [%X].\n", GNUNET_i2s (pi),
5289 msg->tid);
5290 t = tunnel_get (pi, ntohl (msg->tid));
5291 if (NULL == t)
5292 { 3293 {
5293 /* TODO notify back: we don't know this tunnel */ 3294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n");
5294 GNUNET_break_op (0); 3295 if (NULL == t->owner)
3296 {
3297 GNUNET_break_op (0);
3298 return GNUNET_OK;
3299 }
3300 if (NULL != peer_info->dhtget)
3301 {
3302 GNUNET_DHT_get_stop (peer_info->dhtget);
3303 peer_info->dhtget = NULL;
3304 }
3305 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
3306 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
5295 return GNUNET_OK; 3307 return GNUNET_OK;
5296 } 3308 }
5297 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n");
5298 path = path_new (size);
5299 own_pos = 0;
5300 for (i = 0; i < size; i++)
5301 {
5302 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... adding %s\n",
5303 GNUNET_i2s (&pi[i]));
5304 path->peers[i] = GNUNET_PEER_intern (&pi[i]);
5305 if (path->peers[i] == myid)
5306 own_pos = i;
5307 }
5308 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos);
5309 if (own_pos < path->length - 1)
5310 send_prebuilt_message (message, &pi[own_pos + 1], t);
5311 else
5312 send_client_tunnel_disconnect(t, NULL);
5313 3309
5314 tunnel_delete_peer (t, path->peers[path->length - 1]); 3310 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5315 path_destroy (path); 3311 " not for us, retransmitting...\n");
3312 peer_info = peer_get (&msg->oid);
3313 send_prebuilt_message (message, t->prev_hop, t);
5316 return GNUNET_OK; 3314 return GNUNET_OK;
5317} 3315}
5318 3316
@@ -5370,8 +3368,6 @@ handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
5370{ 3368{
5371 struct GNUNET_MESH_TunnelDestroy *msg; 3369 struct GNUNET_MESH_TunnelDestroy *msg;
5372 struct MeshTunnel *t; 3370 struct MeshTunnel *t;
5373 GNUNET_PEER_Id parent;
5374 GNUNET_PEER_Id pid;
5375 3371
5376 msg = (struct GNUNET_MESH_TunnelDestroy *) message; 3372 msg = (struct GNUNET_MESH_TunnelDestroy *) message;
5377 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3373 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -5381,7 +3377,6 @@ handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
5381 " for tunnel %s [%u]\n", 3377 " for tunnel %s [%u]\n",
5382 GNUNET_i2s (&msg->oid), ntohl (msg->tid)); 3378 GNUNET_i2s (&msg->oid), ntohl (msg->tid));
5383 t = tunnel_get (&msg->oid, ntohl (msg->tid)); 3379 t = tunnel_get (&msg->oid, ntohl (msg->tid));
5384 /* Check signature */
5385 if (NULL == t) 3380 if (NULL == t)
5386 { 3381 {
5387 /* Probably already got the message from another path, 3382 /* Probably already got the message from another path,
@@ -5392,31 +3387,36 @@ handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
5392 1, GNUNET_NO); 3387 1, GNUNET_NO);
5393 return GNUNET_OK; 3388 return GNUNET_OK;
5394 } 3389 }
5395 parent = tree_get_predecessor (t->tree);
5396 pid = GNUNET_PEER_search (peer);
5397 if (pid != parent)
5398 {
5399 unsigned int nc;
5400
5401 tree_del_peer (t->tree, pid, &tunnel_child_removed, t);
5402 nc = tree_count_children (t->tree);
5403 if (nc > 0 || NULL != t->owner || t->nclients > 0)
5404 {
5405 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5406 "still in use: %u cl, %u ch\n",
5407 t->nclients, nc);
5408 return GNUNET_OK;
5409 }
5410 }
5411 if (t->local_tid_dest >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) 3390 if (t->local_tid_dest >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
5412 { 3391 {
5413 /* Tunnel was incoming, notify clients */
5414 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "INCOMING TUNNEL %X %X\n", 3392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "INCOMING TUNNEL %X %X\n",
5415 t->local_tid, t->local_tid_dest); 3393 t->local_tid, t->local_tid_dest);
5416 send_clients_tunnel_destroy (t);
5417 } 3394 }
5418 tunnel_send_destroy (t, parent); 3395 if (GNUNET_PEER_search (peer) == t->prev_hop)
5419 t->destroy = GNUNET_YES; 3396 {
3397 // TODO check owner's signature
3398 // TODO add owner's signatue to tunnel for retransmission
3399 peer_cancel_queues (t->prev_hop, t);
3400 GNUNET_PEER_change_rc (t->prev_hop, -1);
3401 t->prev_hop = 0;
3402 }
3403 else if (GNUNET_PEER_search (peer) == t->next_hop)
3404 {
3405 // TODO check dest's signature
3406 // TODO add dest's signatue to tunnel for retransmission
3407 peer_cancel_queues (t->next_hop, t);
3408 GNUNET_PEER_change_rc (t->next_hop, -1);
3409 t->next_hop = 0;
3410 }
3411 else
3412 {
3413 GNUNET_break_op (0);
3414 // TODO check both owner AND destination's signature to see which matches
3415 // TODO restransmit in appropriate direction
3416 return GNUNET_OK;
3417 }
3418 tunnel_destroy_empty (t);
3419
5420 // TODO: add timeout to destroy the tunnel anyway 3420 // TODO: add timeout to destroy the tunnel anyway
5421 return GNUNET_OK; 3421 return GNUNET_OK;
5422} 3422}
@@ -5432,14 +3432,11 @@ handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
5432 * GNUNET_SYSERR to close it (signal serious error) 3432 * GNUNET_SYSERR to close it (signal serious error)
5433 */ 3433 */
5434static int 3434static int
5435handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, 3435handle_mesh_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
5436 const struct GNUNET_MessageHeader *message) 3436 const struct GNUNET_MessageHeader *message)
5437{ 3437{
5438 struct GNUNET_MESH_Unicast *msg; 3438 struct GNUNET_MESH_Data *msg;
5439 struct GNUNET_PeerIdentity *neighbor;
5440 struct MeshTunnelChildInfo *cinfo;
5441 struct MeshTunnel *t; 3439 struct MeshTunnel *t;
5442 GNUNET_PEER_Id dest_id;
5443 uint32_t pid; 3440 uint32_t pid;
5444 uint32_t ttl; 3441 uint32_t ttl;
5445 size_t size; 3442 size_t size;
@@ -5449,13 +3446,13 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
5449 /* Check size */ 3446 /* Check size */
5450 size = ntohs (message->size); 3447 size = ntohs (message->size);
5451 if (size < 3448 if (size <
5452 sizeof (struct GNUNET_MESH_Unicast) + 3449 sizeof (struct GNUNET_MESH_Data) +
5453 sizeof (struct GNUNET_MessageHeader)) 3450 sizeof (struct GNUNET_MessageHeader))
5454 { 3451 {
5455 GNUNET_break (0); 3452 GNUNET_break (0);
5456 return GNUNET_OK; 3453 return GNUNET_OK;
5457 } 3454 }
5458 msg = (struct GNUNET_MESH_Unicast *) message; 3455 msg = (struct GNUNET_MESH_Data *) message;
5459 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n", 3456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n",
5460 GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type))); 3457 GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type)));
5461 /* Check tunnel */ 3458 /* Check tunnel */
@@ -5468,7 +3465,7 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
5468 return GNUNET_OK; 3465 return GNUNET_OK;
5469 } 3466 }
5470 pid = ntohl (msg->pid); 3467 pid = ntohl (msg->pid);
5471 if (t->fwd_pid == pid) 3468 if (t->prev_fc.last_pid_recv == pid)
5472 { 3469 {
5473 GNUNET_STATISTICS_update (stats, "# duplicate PID drops", 1, GNUNET_NO); 3470 GNUNET_STATISTICS_update (stats, "# duplicate PID drops", 1, GNUNET_NO);
5474 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3471 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -5481,30 +3478,34 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
5481 " pid %u not seen yet, forwarding\n", pid); 3478 " pid %u not seen yet, forwarding\n", pid);
5482 } 3479 }
5483 3480
5484 t->skip += (pid - t->fwd_pid) - 1; 3481 if (GMC_is_pid_bigger (pid, t->prev_fc.last_ack_sent))
5485 t->fwd_pid = pid;
5486
5487 if (GMC_is_pid_bigger (pid, t->last_fwd_ack))
5488 { 3482 {
5489 GNUNET_STATISTICS_update (stats, "# unsolicited unicast", 1, GNUNET_NO); 3483 GNUNET_STATISTICS_update (stats, "# unsolicited unicast", 1, GNUNET_NO);
5490 GNUNET_break_op (0); 3484 GNUNET_break_op (0);
5491 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3485 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5492 "Received PID %u, ACK %u\n", 3486 "Received PID %u, ACK %u\n",
5493 pid, t->last_fwd_ack); 3487 pid, t->prev_fc.last_ack_sent);
3488 tunnel_send_fwd_ack(t, GNUNET_MESSAGE_TYPE_MESH_POLL);
5494 return GNUNET_OK; 3489 return GNUNET_OK;
5495 } 3490 }
3491 t->prev_fc.last_pid_recv = pid;
5496 3492
5497 tunnel_reset_timeout (t); 3493 tunnel_reset_timeout (t);
5498 dest_id = GNUNET_PEER_search (&msg->destination); 3494 if (t->dest == myid)
5499 if (dest_id == myid)
5500 { 3495 {
3496 /* TODO signature verification */
5501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3497 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5502 " it's for us! sending to clients...\n"); 3498 " it's for us! sending to clients...\n");
5503 GNUNET_STATISTICS_update (stats, "# unicast received", 1, GNUNET_NO); 3499 GNUNET_STATISTICS_update (stats, "# unicast received", 1, GNUNET_NO);
5504 send_subscribed_clients (message, &msg[1].header, t); 3500 tunnel_send_client_ucast (t, msg);
5505 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST); 3501 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST);
5506 return GNUNET_OK; 3502 return GNUNET_OK;
5507 } 3503 }
3504 if (0 == t->next_hop)
3505 {
3506 GNUNET_break (0);
3507 return GNUNET_OK;
3508 }
5508 ttl = ntohl (msg->ttl); 3509 ttl = ntohl (msg->ttl);
5509 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl); 3510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl);
5510 if (ttl == 0) 3511 if (ttl == 0)
@@ -5517,107 +3518,13 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
5517 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3518 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5518 " not for us, retransmitting...\n"); 3519 " not for us, retransmitting...\n");
5519 3520
5520 neighbor = tree_get_first_hop (t->tree, dest_id); 3521 send_prebuilt_message (message, t->next_hop, t);
5521 cinfo = tunnel_get_neighbor_fc (t, neighbor);
5522 cinfo->fwd_pid = pid;
5523 GNUNET_CONTAINER_multihashmap_iterate (t->children_fc,
5524 &tunnel_add_skip,
5525 &neighbor);
5526 if (GNUNET_YES == t->nobuffer &&
5527 GNUNET_YES == GMC_is_pid_bigger (pid, cinfo->fwd_ack))
5528 {
5529 GNUNET_STATISTICS_update (stats, "# unsolicited unicast", 1, GNUNET_NO);
5530 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " %u > %u\n", pid, cinfo->fwd_ack);
5531 GNUNET_break_op (0);
5532 return GNUNET_OK;
5533 }
5534 send_prebuilt_message (message, neighbor, t);
5535 GNUNET_STATISTICS_update (stats, "# unicast forwarded", 1, GNUNET_NO); 3522 GNUNET_STATISTICS_update (stats, "# unicast forwarded", 1, GNUNET_NO);
5536 return GNUNET_OK; 3523 return GNUNET_OK;
5537} 3524}
5538 3525
5539 3526
5540/** 3527/**
5541 * Core handler for mesh network traffic going from the origin to all peers
5542 *
5543 * @param cls closure
5544 * @param message message
5545 * @param peer peer identity this notification is about
5546 * @return GNUNET_OK to keep the connection open,
5547 * GNUNET_SYSERR to close it (signal serious error)
5548 *
5549 * TODO: Check who we got this from, to validate route.
5550 */
5551static int
5552handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer,
5553 const struct GNUNET_MessageHeader *message)
5554{
5555 struct GNUNET_MESH_Multicast *msg;
5556 struct MeshTunnel *t;
5557 size_t size;
5558 uint32_t pid;
5559
5560 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a multicast packet from %s\n",
5561 GNUNET_i2s (peer));
5562 size = ntohs (message->size);
5563 if (sizeof (struct GNUNET_MESH_Multicast) +
5564 sizeof (struct GNUNET_MessageHeader) > size)
5565 {
5566 GNUNET_break_op (0);
5567 return GNUNET_OK;
5568 }
5569 msg = (struct GNUNET_MESH_Multicast *) message;
5570 t = tunnel_get (&msg->oid, ntohl (msg->tid));
5571
5572 if (NULL == t)
5573 {
5574 /* TODO notify that we dont know that tunnel */
5575 GNUNET_STATISTICS_update (stats, "# data on unknown tunnel", 1, GNUNET_NO);
5576 GNUNET_break_op (0);
5577 return GNUNET_OK;
5578 }
5579 pid = ntohl (msg->pid);
5580 if (t->fwd_pid == pid)
5581 {
5582 /* already seen this packet, drop */
5583 GNUNET_STATISTICS_update (stats, "# duplicate PID drops", 1, GNUNET_NO);
5584 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5585 " Already seen pid %u, DROPPING!\n", pid);
5586 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
5587 return GNUNET_OK;
5588 }
5589 else
5590 {
5591 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5592 " pid %u not seen yet, forwarding\n", pid);
5593 }
5594 t->skip += (pid - t->fwd_pid) - 1;
5595 t->fwd_pid = pid;
5596 tunnel_reset_timeout (t);
5597
5598 /* Transmit to locally interested clients */
5599 if (NULL != t->peers &&
5600 GNUNET_CONTAINER_multihashmap_contains (t->peers, &my_full_id.hashPubKey))
5601 {
5602 GNUNET_STATISTICS_update (stats, "# multicast received", 1, GNUNET_NO);
5603 send_subscribed_clients (message, &msg[1].header, t);
5604 tunnel_send_fwd_ack(t, GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
5605 }
5606 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ntohl (msg->ttl));
5607 if (ntohl (msg->ttl) == 0)
5608 {
5609 GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
5610 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
5611 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
5612 return GNUNET_OK;
5613 }
5614 GNUNET_STATISTICS_update (stats, "# multicast forwarded", 1, GNUNET_NO);
5615 tunnel_send_multicast (t, message);
5616 return GNUNET_OK;
5617}
5618
5619
5620/**
5621 * Core handler for mesh network traffic toward the owner of a tunnel 3528 * Core handler for mesh network traffic toward the owner of a tunnel
5622 * 3529 *
5623 * @param cls closure 3530 * @param cls closure
@@ -5628,28 +3535,25 @@ handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer,
5628 * GNUNET_SYSERR to close it (signal serious error) 3535 * GNUNET_SYSERR to close it (signal serious error)
5629 */ 3536 */
5630static int 3537static int
5631handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, 3538handle_mesh_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
5632 const struct GNUNET_MessageHeader *message) 3539 const struct GNUNET_MessageHeader *message)
5633{ 3540{
5634 struct GNUNET_MESH_ToOrigin *msg; 3541 struct GNUNET_MESH_Data *msg;
5635 struct GNUNET_PeerIdentity id;
5636 struct MeshPeerInfo *peer_info;
5637 struct MeshTunnel *t; 3542 struct MeshTunnel *t;
5638 struct MeshTunnelChildInfo *cinfo;
5639 GNUNET_PEER_Id predecessor;
5640 size_t size; 3543 size_t size;
5641 uint32_t pid; 3544 uint32_t pid;
3545 uint32_t ttl;
5642 3546
5643 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a ToOrigin packet from %s\n", 3547 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a ToOrigin packet from %s\n",
5644 GNUNET_i2s (peer)); 3548 GNUNET_i2s (peer));
5645 size = ntohs (message->size); 3549 size = ntohs (message->size);
5646 if (size < sizeof (struct GNUNET_MESH_ToOrigin) + /* Payload must be */ 3550 if (size < sizeof (struct GNUNET_MESH_Data) + /* Payload must be */
5647 sizeof (struct GNUNET_MessageHeader)) /* at least a header */ 3551 sizeof (struct GNUNET_MessageHeader)) /* at least a header */
5648 { 3552 {
5649 GNUNET_break_op (0); 3553 GNUNET_break_op (0);
5650 return GNUNET_OK; 3554 return GNUNET_OK;
5651 } 3555 }
5652 msg = (struct GNUNET_MESH_ToOrigin *) message; 3556 msg = (struct GNUNET_MESH_Data *) message;
5653 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n", 3557 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n",
5654 GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type))); 3558 GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type)));
5655 t = tunnel_get (&msg->oid, ntohl (msg->tid)); 3559 t = tunnel_get (&msg->oid, ntohl (msg->tid));
@@ -5665,14 +3569,7 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
5665 return GNUNET_OK; 3569 return GNUNET_OK;
5666 } 3570 }
5667 3571
5668 cinfo = tunnel_get_neighbor_fc(t, peer); 3572 if (t->next_fc.last_pid_recv == pid)
5669 if (NULL == cinfo)
5670 {
5671 GNUNET_break (0);
5672 return GNUNET_OK;
5673 }
5674
5675 if (cinfo->bck_pid == pid)
5676 { 3573 {
5677 /* already seen this packet, drop */ 3574 /* already seen this packet, drop */
5678 GNUNET_STATISTICS_update (stats, "# duplicate PID drops BCK", 1, GNUNET_NO); 3575 GNUNET_STATISTICS_update (stats, "# duplicate PID drops BCK", 1, GNUNET_NO);
@@ -5682,41 +3579,34 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
5682 return GNUNET_OK; 3579 return GNUNET_OK;
5683 } 3580 }
5684 3581
3582 if (GMC_is_pid_bigger (pid, t->next_fc.last_ack_sent))
3583 {
3584 GNUNET_STATISTICS_update (stats, "# unsolicited to_orig", 1, GNUNET_NO);
3585 GNUNET_break_op (0);
3586 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3587 "Received PID %u, ACK %u\n",
3588 pid, t->next_fc.last_ack_sent);
3589 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL);
3590 return GNUNET_OK;
3591 }
3592 t->next_fc.last_pid_recv = pid;
5685 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3593 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5686 " pid %u not seen yet, forwarding\n", pid); 3594 " pid %u not seen yet, forwarding\n", pid);
5687 cinfo->bck_pid = pid;
5688 3595
5689 if (NULL != t->owner) 3596 if (myid == t->id.oid)
5690 { 3597 {
5691 char cbuf[size]; 3598 /* TODO signature verification */
5692 struct GNUNET_MESH_ToOrigin *copy;
5693
5694 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3599 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5695 " it's for us! sending to clients...\n"); 3600 " it's for us! sending to clients...\n");
5696 /* TODO signature verification */
5697 memcpy (cbuf, message, size);
5698 copy = (struct GNUNET_MESH_ToOrigin *) cbuf;
5699 copy->tid = htonl (t->local_tid);
5700 t->bck_pid++;
5701 copy->pid = htonl (t->bck_pid);
5702 GNUNET_STATISTICS_update (stats, "# to origin received", 1, GNUNET_NO); 3601 GNUNET_STATISTICS_update (stats, "# to origin received", 1, GNUNET_NO);
5703 GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle, 3602 tunnel_send_client_to_orig (t, msg);
5704 &copy->header, GNUNET_NO);
5705 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN); 3603 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
5706 return GNUNET_OK; 3604 return GNUNET_OK;
5707 } 3605 }
5708 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3606 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5709 " not for us, retransmitting...\n"); 3607 " not for us, retransmitting...\n");
5710 3608
5711 peer_info = peer_info_get (&msg->oid); 3609 if (0 == t->prev_hop) /* No owner AND no prev hop */
5712 if (NULL == peer_info)
5713 {
5714 /* unknown origin of tunnel */
5715 GNUNET_break (0);
5716 return GNUNET_OK;
5717 }
5718 predecessor = tree_get_predecessor (t->tree);
5719 if (0 == predecessor)
5720 { 3610 {
5721 if (GNUNET_YES == t->destroy) 3611 if (GNUNET_YES == t->destroy)
5722 { 3612 {
@@ -5732,15 +3622,20 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
5732 "from peer %s\n", 3622 "from peer %s\n",
5733 GNUNET_i2s (peer)); 3623 GNUNET_i2s (peer));
5734 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3624 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5735 "for tunnel %s [%X]\n", 3625 "on tunnel %s [%X]\n",
5736 GNUNET_i2s (&msg->oid), ntohl(msg->tid)); 3626 GNUNET_i2s (&msg->oid), ntohl(msg->tid));
5737 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5738 "current tree:\n");
5739 tree_debug (t->tree);
5740 return GNUNET_OK; 3627 return GNUNET_OK;
5741 } 3628 }
5742 GNUNET_PEER_resolve (predecessor, &id); 3629 ttl = ntohl (msg->ttl);
5743 send_prebuilt_message (message, &id, t); 3630 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl);
3631 if (ttl == 0)
3632 {
3633 GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
3634 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
3635 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
3636 return GNUNET_OK;
3637 }
3638 send_prebuilt_message (message, t->prev_hop, t);
5744 GNUNET_STATISTICS_update (stats, "# to origin forwarded", 1, GNUNET_NO); 3639 GNUNET_STATISTICS_update (stats, "# to origin forwarded", 1, GNUNET_NO);
5745 3640
5746 return GNUNET_OK; 3641 return GNUNET_OK;
@@ -5763,6 +3658,7 @@ handle_mesh_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
5763{ 3658{
5764 struct GNUNET_MESH_ACK *msg; 3659 struct GNUNET_MESH_ACK *msg;
5765 struct MeshTunnel *t; 3660 struct MeshTunnel *t;
3661 GNUNET_PEER_Id id;
5766 uint32_t ack; 3662 uint32_t ack;
5767 3663
5768 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n", 3664 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
@@ -5781,30 +3677,39 @@ handle_mesh_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
5781 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack); 3677 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
5782 3678
5783 /* Is this a forward or backward ACK? */ 3679 /* Is this a forward or backward ACK? */
5784 if (tree_get_predecessor(t->tree) != GNUNET_PEER_search(peer)) 3680 id = GNUNET_PEER_search (peer);
3681 if (t->next_hop == id)
5785 { 3682 {
5786 struct MeshTunnelChildInfo *cinfo; 3683 debug_fwd_ack++;
5787
5788 debug_bck_ack++;
5789 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n"); 3684 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n");
5790 cinfo = tunnel_get_neighbor_fc (t, peer); 3685 if (GNUNET_SCHEDULER_NO_TASK != t->next_fc.poll_task &&
5791 cinfo->fwd_ack = ack; 3686 GMC_is_pid_bigger (ack, t->next_fc.last_ack_recv))
5792 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
5793 tunnel_unlock_fwd_queues (t);
5794 if (GNUNET_SCHEDULER_NO_TASK != cinfo->fc_poll)
5795 { 3687 {
5796 GNUNET_SCHEDULER_cancel (cinfo->fc_poll); 3688 GNUNET_SCHEDULER_cancel (t->next_fc.poll_task);
5797 cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK; 3689 t->next_fc.poll_task = GNUNET_SCHEDULER_NO_TASK;
5798 cinfo->fc_poll_time = GNUNET_TIME_UNIT_SECONDS; 3690 t->next_fc.poll_time = GNUNET_TIME_UNIT_SECONDS;
5799 } 3691 }
3692 t->next_fc.last_ack_recv = ack;
3693 peer_unlock_queue (t->next_hop);
3694 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
5800 } 3695 }
5801 else 3696 else if (t->prev_hop == id)
5802 { 3697 {
3698 debug_bck_ack++;
5803 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n"); 3699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n");
5804 t->bck_ack = ack; 3700 if (GNUNET_SCHEDULER_NO_TASK != t->prev_fc.poll_task &&
3701 GMC_is_pid_bigger (ack, t->prev_fc.last_ack_recv))
3702 {
3703 GNUNET_SCHEDULER_cancel (t->prev_fc.poll_task);
3704 t->prev_fc.poll_task = GNUNET_SCHEDULER_NO_TASK;
3705 t->prev_fc.poll_time = GNUNET_TIME_UNIT_SECONDS;
3706 }
3707 t->prev_fc.last_ack_recv = ack;
3708 peer_unlock_queue (t->prev_hop);
5805 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK); 3709 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
5806 tunnel_unlock_bck_queue (t);
5807 } 3710 }
3711 else
3712 GNUNET_break_op (0);
5808 return GNUNET_OK; 3713 return GNUNET_OK;
5809} 3714}
5810 3715
@@ -5825,6 +3730,7 @@ handle_mesh_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
5825{ 3730{
5826 struct GNUNET_MESH_Poll *msg; 3731 struct GNUNET_MESH_Poll *msg;
5827 struct MeshTunnel *t; 3732 struct MeshTunnel *t;
3733 GNUNET_PEER_Id id;
5828 3734
5829 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an POLL packet from %s!\n", 3735 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an POLL packet from %s!\n",
5830 GNUNET_i2s (peer)); 3736 GNUNET_i2s (peer));
@@ -5842,117 +3748,20 @@ handle_mesh_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
5842 } 3748 }
5843 3749
5844 /* Is this a forward or backward ACK? */ 3750 /* Is this a forward or backward ACK? */
5845 if (tree_get_predecessor(t->tree) != GNUNET_PEER_search(peer)) 3751 id = GNUNET_PEER_search(peer);
3752 if (t->next_hop == id)
5846 { 3753 {
5847 struct MeshTunnelChildInfo *cinfo;
5848
5849 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " from FWD\n"); 3754 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " from FWD\n");
5850 cinfo = tunnel_get_neighbor_fc (t, peer);
5851 cinfo->bck_ack = cinfo->fwd_pid; // mark as ready to send
5852 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL); 3755 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL);
5853 } 3756 }
5854 else 3757 else if (t->prev_hop == id)
5855 { 3758 {
5856 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " from BCK\n"); 3759 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " from BCK\n");
5857 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL); 3760 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL);
5858 } 3761 }
5859
5860 return GNUNET_OK;
5861}
5862
5863/**
5864 * Core handler for path ACKs
5865 *
5866 * @param cls closure
5867 * @param message message
5868 * @param peer peer identity this notification is about
5869 *
5870 * @return GNUNET_OK to keep the connection open,
5871 * GNUNET_SYSERR to close it (signal serious error)
5872 */
5873static int
5874handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
5875 const struct GNUNET_MessageHeader *message)
5876{
5877 struct GNUNET_MESH_PathACK *msg;
5878 struct GNUNET_PeerIdentity id;
5879 struct MeshPeerInfo *peer_info;
5880 struct MeshPeerPath *p;
5881 struct MeshTunnel *t;
5882
5883 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a path ACK msg [%s]\n",
5884 GNUNET_i2s (&my_full_id));
5885 msg = (struct GNUNET_MESH_PathACK *) message;
5886 t = tunnel_get (&msg->oid, ntohl(msg->tid));
5887 if (NULL == t)
5888 {
5889 /* TODO notify that we don't know the tunnel */
5890 GNUNET_STATISTICS_update (stats, "# control on unknown tunnel", 1, GNUNET_NO);
5891 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " don't know the tunnel %s [%X]!\n",
5892 GNUNET_i2s (&msg->oid), ntohl(msg->tid));
5893 return GNUNET_OK;
5894 }
5895 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %s [%X]\n",
5896 GNUNET_i2s (&msg->oid), ntohl(msg->tid));
5897
5898 peer_info = peer_info_get (&msg->peer_id);
5899 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by peer %s\n",
5900 GNUNET_i2s (&msg->peer_id));
5901 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n",
5902 GNUNET_i2s (peer));
5903
5904 if (NULL != t->regex_search && t->regex_search->peer == peer_info->id)
5905 {
5906 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5907 "connect_by_string completed, stopping search\n");
5908 regex_cancel_search (t->regex_search);
5909 t->regex_search = NULL;
5910 }
5911
5912 /* Add paths to peers? */
5913 p = tree_get_path_to_peer (t->tree, peer_info->id);
5914 if (NULL != p)
5915 {
5916 path_add_to_peers (p, GNUNET_YES);
5917 path_destroy (p);
5918 }
5919 else 3762 else
5920 {
5921 GNUNET_break (0); 3763 GNUNET_break (0);
5922 }
5923 3764
5924 /* Message for us? */
5925 if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct GNUNET_PeerIdentity)))
5926 {
5927 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n");
5928 if (NULL == t->owner)
5929 {
5930 GNUNET_break_op (0);
5931 return GNUNET_OK;
5932 }
5933 if (NULL != t->dht_get_type)
5934 {
5935 GNUNET_DHT_get_stop (t->dht_get_type);
5936 t->dht_get_type = NULL;
5937 }
5938 if (tree_get_status (t->tree, peer_info->id) != MESH_PEER_READY)
5939 {
5940 tree_set_status (t->tree, peer_info->id, MESH_PEER_READY);
5941 send_client_peer_connected (t, peer_info->id);
5942 }
5943 if (NULL != peer_info->dhtget)
5944 {
5945 GNUNET_DHT_get_stop (peer_info->dhtget);
5946 peer_info->dhtget = NULL;
5947 }
5948 return GNUNET_OK;
5949 }
5950
5951 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5952 " not for us, retransmitting...\n");
5953 GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &id);
5954 peer_info = peer_info_get (&msg->oid);
5955 send_prebuilt_message (message, &id, t);
5956 return GNUNET_OK; 3765 return GNUNET_OK;
5957} 3766}
5958 3767
@@ -5992,7 +3801,7 @@ handle_mesh_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
5992 tunnel_reset_timeout (t); 3801 tunnel_reset_timeout (t);
5993 3802
5994 GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO); 3803 GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
5995 tunnel_send_multicast (t, message); 3804 send_prebuilt_message (message, t->next_hop, t);
5996 return GNUNET_OK; 3805 return GNUNET_OK;
5997 } 3806 }
5998 3807
@@ -6003,16 +3812,14 @@ handle_mesh_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
6003 */ 3812 */
6004static struct GNUNET_CORE_MessageHandler core_handlers[] = { 3813static struct GNUNET_CORE_MessageHandler core_handlers[] = {
6005 {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0}, 3814 {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
6006 {&handle_mesh_path_destroy, GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY, 0},
6007 {&handle_mesh_path_broken, GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN, 3815 {&handle_mesh_path_broken, GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN,
6008 sizeof (struct GNUNET_MESH_PathBroken)}, 3816 sizeof (struct GNUNET_MESH_PathBroken)},
6009 {&handle_mesh_tunnel_destroy, GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY, 3817 {&handle_mesh_tunnel_destroy, GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY,
6010 sizeof (struct GNUNET_MESH_TunnelDestroy)}, 3818 sizeof (struct GNUNET_MESH_TunnelDestroy)},
6011 {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0}, 3819 {&handle_mesh_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
6012 {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
6013 {&handle_mesh_keepalive, GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE, 3820 {&handle_mesh_keepalive, GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE,
6014 sizeof (struct GNUNET_MESH_TunnelKeepAlive)}, 3821 sizeof (struct GNUNET_MESH_TunnelKeepAlive)},
6015 {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0}, 3822 {&handle_mesh_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
6016 {&handle_mesh_ack, GNUNET_MESSAGE_TYPE_MESH_ACK, 3823 {&handle_mesh_ack, GNUNET_MESSAGE_TYPE_MESH_ACK,
6017 sizeof (struct GNUNET_MESH_ACK)}, 3824 sizeof (struct GNUNET_MESH_ACK)},
6018 {&handle_mesh_poll, GNUNET_MESSAGE_TYPE_MESH_POLL, 3825 {&handle_mesh_poll, GNUNET_MESSAGE_TYPE_MESH_POLL,
@@ -6028,24 +3835,6 @@ static struct GNUNET_CORE_MessageHandler core_handlers[] = {
6028/**************** MESH LOCAL HANDLER HELPERS ***********************/ 3835/**************** MESH LOCAL HANDLER HELPERS ***********************/
6029/******************************************************************************/ 3836/******************************************************************************/
6030 3837
6031/**
6032 * deregister_app: iterator for removing each application registered by a client
6033 *
6034 * @param cls closure
6035 * @param key the hash of the application id (used to access the hashmap)
6036 * @param value the value stored at the key (client)
6037 *
6038 * @return GNUNET_OK on success
6039 */
6040static int
6041deregister_app (void *cls, const struct GNUNET_HashCode * key, void *value)
6042{
6043 struct MeshClient *c = cls;
6044
6045 GNUNET_break (GNUNET_YES ==
6046 GNUNET_CONTAINER_multihashmap_remove (applications, key, c));
6047 return GNUNET_OK;
6048}
6049 3838
6050#if LATER 3839#if LATER
6051/** 3840/**
@@ -6088,10 +3877,12 @@ notify_client_connection_failure (void *cls, size_t size, void *buf)
6088 3877
6089 3878
6090/** 3879/**
6091 * Send keepalive packets for a peer 3880 * Send keepalive packets for a tunnel.
6092 * 3881 *
6093 * @param cls Closure (tunnel for which to send the keepalive). 3882 * @param cls Closure (tunnel for which to send the keepalive).
6094 * @param tc Notification context. 3883 * @param tc Notification context.
3884 *
3885 * FIXME: add a refresh reset in case of normal unicast traffic is doing the job
6095 */ 3886 */
6096static void 3887static void
6097path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 3888path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
@@ -6101,8 +3892,9 @@ path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
6101 size_t size = sizeof (struct GNUNET_MESH_TunnelKeepAlive); 3892 size_t size = sizeof (struct GNUNET_MESH_TunnelKeepAlive);
6102 char cbuf[size]; 3893 char cbuf[size];
6103 3894
6104 t->path_refresh_task = GNUNET_SCHEDULER_NO_TASK; 3895 t->maintenance_task = GNUNET_SCHEDULER_NO_TASK;
6105 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) 3896 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) ||
3897 NULL == t->owner || 0 == t->local_tid)
6106 { 3898 {
6107 return; 3899 return;
6108 } 3900 }
@@ -6115,11 +3907,10 @@ path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
6115 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE); 3907 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE);
6116 msg->oid = my_full_id; 3908 msg->oid = my_full_id;
6117 msg->tid = htonl (t->id.tid); 3909 msg->tid = htonl (t->id.tid);
6118 tunnel_send_multicast (t, &msg->header); 3910 send_prebuilt_message (&msg->header, t->next_hop, t);
6119 3911
6120 t->path_refresh_task = 3912 t->maintenance_task =
6121 GNUNET_SCHEDULER_add_delayed (refresh_path_time, &path_refresh, t); 3913 GNUNET_SCHEDULER_add_delayed (refresh_path_time, &path_refresh, t);
6122 tunnel_reset_timeout(t);
6123} 3914}
6124 3915
6125 3916
@@ -6138,8 +3929,6 @@ path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
6138 * @param type type of the result 3929 * @param type type of the result
6139 * @param size number of bytes in data 3930 * @param size number of bytes in data
6140 * @param data pointer to the result data 3931 * @param data pointer to the result data
6141 *
6142 * TODO: re-issue the request after certain time? cancel after X results?
6143 */ 3932 */
6144static void 3933static void
6145dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, 3934dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
@@ -6150,83 +3939,36 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
6150 unsigned int put_path_length, enum GNUNET_BLOCK_Type type, 3939 unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
6151 size_t size, const void *data) 3940 size_t size, const void *data)
6152{ 3941{
6153 struct MeshPathInfo *path_info = cls; 3942 struct MeshPeerInfo *peer = cls;
6154 struct MeshPeerPath *p; 3943 struct MeshPeerPath *p;
6155 struct GNUNET_PeerIdentity pi; 3944 struct GNUNET_PeerIdentity pi;
6156 int i; 3945 int i;
6157 3946
6158 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got results from DHT!\n"); 3947 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got results from DHT!\n");
6159 GNUNET_PEER_resolve (path_info->peer->id, &pi); 3948 GNUNET_PEER_resolve (peer->id, &pi);
6160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for %s\n", GNUNET_i2s (&pi)); 3949 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for %s\n", GNUNET_i2s (&pi));
6161 3950
6162 p = path_build_from_dht (get_path, get_path_length, 3951 p = path_build_from_dht (get_path, get_path_length,
6163 put_path, put_path_length); 3952 put_path, put_path_length);
6164 path_add_to_peers (p, GNUNET_NO); 3953 path_add_to_peers (p, GNUNET_NO);
6165 path_destroy (p); 3954 path_destroy (p);
6166 for (i = 0; i < path_info->peer->ntunnels; i++) 3955 for (i = 0; i < peer->ntunnels; i++)
6167 { 3956 {
6168 tunnel_add_peer (path_info->peer->tunnels[i], path_info->peer); 3957 struct GNUNET_PeerIdentity id;
6169 peer_info_connect (path_info->peer, path_info->t);
6170 }
6171
6172 return;
6173}
6174
6175
6176/**
6177 * Function to process paths received for a new peer addition. The recorded
6178 * paths form the initial tunnel, which can be optimized later.
6179 * Called on each result obtained for the DHT search.
6180 *
6181 * @param cls closure
6182 * @param exp when will this value expire
6183 * @param key key of the result
6184 * @param get_path path of the get request
6185 * @param get_path_length lenght of get_path
6186 * @param put_path path of the put request
6187 * @param put_path_length length of the put_path
6188 * @param type type of the result
6189 * @param size number of bytes in data
6190 * @param data pointer to the result data
6191 */
6192static void
6193dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp,
6194 const struct GNUNET_HashCode * key,
6195 const struct GNUNET_PeerIdentity *get_path,
6196 unsigned int get_path_length,
6197 const struct GNUNET_PeerIdentity *put_path,
6198 unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
6199 size_t size, const void *data)
6200{
6201 const struct PBlock *pb = data;
6202 const struct GNUNET_PeerIdentity *pi = &pb->id;
6203 struct MeshTunnel *t = cls;
6204 struct MeshPeerInfo *peer_info;
6205 struct MeshPeerPath *p;
6206 3958
6207 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got type DHT result!\n"); 3959 GNUNET_PEER_resolve (peer->tunnels[i]->id.oid, &id);
6208 if (size != sizeof (struct PBlock)) 3960 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... tunnel %s:%X (%X / %X)\n",
6209 { 3961 GNUNET_i2s (&id), peer->tunnels[i]->id.tid,
6210 GNUNET_break_op (0); 3962 peer->tunnels[i]->local_tid,
6211 return; 3963 peer->tunnels[i]->local_tid_dest);
6212 } 3964 if (peer->tunnels[i]->state == MESH_TUNNEL_SEARCHING)
6213 if (ntohl(pb->type) != t->type) 3965 {
6214 { 3966 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
6215 GNUNET_break_op (0); 3967 peer_connect (peer, peer->tunnels[i]);
6216 return; 3968 }
6217 } 3969 }
6218 GNUNET_assert (NULL != t->owner);
6219 peer_info = peer_info_get (pi);
6220 (void) GNUNET_CONTAINER_multihashmap_put (t->peers, &pi->hashPubKey,
6221 peer_info,
6222 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
6223 3970
6224 p = path_build_from_dht (get_path, get_path_length, put_path, 3971 return;
6225 put_path_length);
6226 path_add_to_peers (p, GNUNET_NO);
6227 path_destroy(p);
6228 tunnel_add_peer (t, peer_info);
6229 peer_info_connect (peer_info, t);
6230} 3972}
6231 3973
6232 3974
@@ -6247,21 +3989,22 @@ handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
6247{ 3989{
6248 struct MeshClient *c; 3990 struct MeshClient *c;
6249 struct MeshClient *next; 3991 struct MeshClient *next;
6250 unsigned int i;
6251 3992
6252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected\n"); 3993 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected: %p\n", client);
6253 if (client == NULL) 3994 if (client == NULL)
6254 { 3995 {
6255 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (SERVER DOWN)\n"); 3996 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (SERVER DOWN)\n");
6256 return; 3997 return;
6257 } 3998 }
6258 3999
6259 c = clients; 4000 c = clients_head;
6260 while (NULL != c) 4001 while (NULL != c)
6261 { 4002 {
6262 if (c->handle != client) 4003 if (c->handle != client)
6263 { 4004 {
6264 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... searching\n"); 4005 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4006 " ... searching %p (%u)\n",
4007 c->handle, c->id);
6265 c = c->next; 4008 c = c->next;
6266 continue; 4009 continue;
6267 } 4010 }
@@ -6269,49 +4012,24 @@ handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
6269 c->id); 4012 c->id);
6270 GNUNET_SERVER_client_drop (c->handle); 4013 GNUNET_SERVER_client_drop (c->handle);
6271 c->shutting_down = GNUNET_YES; 4014 c->shutting_down = GNUNET_YES;
6272 GNUNET_assert (NULL != c->own_tunnels);
6273 GNUNET_assert (NULL != c->incoming_tunnels);
6274 GNUNET_CONTAINER_multihashmap_iterate (c->own_tunnels, 4015 GNUNET_CONTAINER_multihashmap_iterate (c->own_tunnels,
6275 &tunnel_destroy_iterator, c); 4016 &tunnel_destroy_iterator, c);
6276 GNUNET_CONTAINER_multihashmap_iterate (c->incoming_tunnels, 4017 GNUNET_CONTAINER_multihashmap_iterate (c->incoming_tunnels,
6277 &tunnel_destroy_iterator, c); 4018 &tunnel_destroy_iterator, c);
6278 GNUNET_CONTAINER_multihashmap_iterate (c->ignore_tunnels,
6279 &tunnel_destroy_iterator, c);
6280 GNUNET_CONTAINER_multihashmap_destroy (c->own_tunnels); 4019 GNUNET_CONTAINER_multihashmap_destroy (c->own_tunnels);
6281 GNUNET_CONTAINER_multihashmap_destroy (c->incoming_tunnels); 4020 GNUNET_CONTAINER_multihashmap_destroy (c->incoming_tunnels);
6282 GNUNET_CONTAINER_multihashmap_destroy (c->ignore_tunnels);
6283 4021
6284 /* deregister clients applications */ 4022 if (NULL != c->ports)
6285 if (NULL != c->apps) 4023 GNUNET_CONTAINER_multihashmap_destroy (c->ports);
6286 {
6287 GNUNET_CONTAINER_multihashmap_iterate (c->apps, &deregister_app, c);
6288 GNUNET_CONTAINER_multihashmap_destroy (c->apps);
6289 }
6290 if (0 == GNUNET_CONTAINER_multihashmap_size (applications) &&
6291 GNUNET_SCHEDULER_NO_TASK != announce_applications_task)
6292 {
6293 GNUNET_SCHEDULER_cancel (announce_applications_task);
6294 announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
6295 }
6296 if (NULL != c->types)
6297 GNUNET_CONTAINER_multihashmap_destroy (c->types);
6298 for (i = 0; i < c->n_regex; i++)
6299 {
6300 GNUNET_free (c->regexes[i].regex);
6301 if (NULL != c->regexes[i].h)
6302 GNUNET_REGEX_announce_cancel (c->regexes[i].h);
6303 }
6304 GNUNET_free_non_null (c->regexes);
6305 if (GNUNET_SCHEDULER_NO_TASK != c->regex_announce_task)
6306 GNUNET_SCHEDULER_cancel (c->regex_announce_task);
6307 next = c->next; 4024 next = c->next;
6308 GNUNET_CONTAINER_DLL_remove (clients, clients_tail, c); 4025 GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
6309 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " CLIENT FREE at %p\n", c); 4026 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " CLIENT FREE at %p\n", c);
6310 GNUNET_free (c); 4027 GNUNET_free (c);
6311 GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO); 4028 GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO);
6312 c = next; 4029 c = next;
6313 } 4030 }
6314 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " done!\n"); 4031 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done!\n");
4032 return;
6315} 4033}
6316 4034
6317 4035
@@ -6328,85 +4046,57 @@ handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client,
6328{ 4046{
6329 struct GNUNET_MESH_ClientConnect *cc_msg; 4047 struct GNUNET_MESH_ClientConnect *cc_msg;
6330 struct MeshClient *c; 4048 struct MeshClient *c;
6331 GNUNET_MESH_ApplicationType *a;
6332 unsigned int size; 4049 unsigned int size;
6333 uint16_t ntypes; 4050 uint32_t *p;
6334 uint16_t *t; 4051 unsigned int i;
6335 uint16_t napps; 4052
6336 uint16_t i; 4053 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client);
6337 4054
6338 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client connected\n");
6339 /* Check data sanity */ 4055 /* Check data sanity */
6340 size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect); 4056 size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect);
6341 cc_msg = (struct GNUNET_MESH_ClientConnect *) message; 4057 cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
6342 ntypes = ntohs (cc_msg->types); 4058 if (0 != (size % sizeof (uint32_t)))
6343 napps = ntohs (cc_msg->applications);
6344 if (size !=
6345 ntypes * sizeof (uint16_t) + napps * sizeof (GNUNET_MESH_ApplicationType))
6346 { 4059 {
6347 GNUNET_break (0); 4060 GNUNET_break (0);
6348 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 4061 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6349 return; 4062 return;
6350 } 4063 }
4064 size /= sizeof (uint32_t);
6351 4065
6352 /* Create new client structure */ 4066 /* Create new client structure */
6353 c = GNUNET_malloc (sizeof (struct MeshClient)); 4067 c = GNUNET_malloc (sizeof (struct MeshClient));
6354 c->id = next_client_id++; 4068 c->id = next_client_id++; /* overflow not important: just for debug */
6355 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " CLIENT NEW %u\n", c->id); 4069 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client id %u\n", c->id);
4070 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client has %u ports\n", size);
6356 c->handle = client; 4071 c->handle = client;
6357 GNUNET_SERVER_client_keep (client); 4072 GNUNET_SERVER_client_keep (client);
6358 a = (GNUNET_MESH_ApplicationType *) &cc_msg[1]; 4073 if (size > 0)
6359 if (napps > 0)
6360 { 4074 {
6361 GNUNET_MESH_ApplicationType at; 4075 uint32_t u32;
6362 struct GNUNET_HashCode hc; 4076 struct GNUNET_HashCode hc;
6363 4077
6364 c->apps = GNUNET_CONTAINER_multihashmap_create (napps, GNUNET_NO); 4078 p = (uint32_t *) &cc_msg[1];
6365 for (i = 0; i < napps; i++) 4079 c->ports = GNUNET_CONTAINER_multihashmap_create (size, GNUNET_NO);
4080 for (i = 0; i < size; i++)
6366 { 4081 {
6367 at = ntohl (a[i]); 4082 u32 = ntohl (p[i]);
6368 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " app type: %u\n", at); 4083 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " port: %u\n", u32);
6369 GNUNET_CRYPTO_hash (&at, sizeof (at), &hc); 4084 GMC_hash32 (u32, &hc);
6370 /* store in clients hashmap */
6371 GNUNET_CONTAINER_multihashmap_put (c->apps, &hc, (void *) (long) at,
6372 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
6373 /* store in global hashmap, for announcements */
6374 GNUNET_CONTAINER_multihashmap_put (applications, &hc, c,
6375 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
6376 }
6377 if (GNUNET_SCHEDULER_NO_TASK == announce_applications_task)
6378 announce_applications_task =
6379 GNUNET_SCHEDULER_add_now (&announce_applications, NULL);
6380
6381 }
6382 if (ntypes > 0)
6383 {
6384 uint16_t u16;
6385 struct GNUNET_HashCode hc;
6386 4085
6387 t = (uint16_t *) & a[napps]; 4086 /* store in client's hashmap */
6388 c->types = GNUNET_CONTAINER_multihashmap_create (ntypes, GNUNET_NO); 4087 GNUNET_CONTAINER_multihashmap_put (c->ports, &hc, c,
6389 for (i = 0; i < ntypes; i++) 4088 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
6390 {
6391 u16 = ntohs (t[i]);
6392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " msg type: %u\n", u16);
6393 GNUNET_CRYPTO_hash (&u16, sizeof (u16), &hc);
6394
6395 /* store in clients hashmap */
6396 GNUNET_CONTAINER_multihashmap_put (c->types, &hc, c,
6397 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
6398 /* store in global hashmap */ 4089 /* store in global hashmap */
6399 GNUNET_CONTAINER_multihashmap_put (types, &hc, c, 4090 /* FIXME only allow one client to have the port open,
4091 * have a backup hashmap with waiting clients */
4092 GNUNET_CONTAINER_multihashmap_put (ports, &hc, c,
6400 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 4093 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
6401 } 4094 }
6402 } 4095 }
6403 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6404 " client has %u+%u subscriptions\n", napps, ntypes);
6405 4096
6406 GNUNET_CONTAINER_DLL_insert (clients, clients_tail, c); 4097 GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
6407 c->own_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); 4098 c->own_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
6408 c->incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); 4099 c->incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
6409 c->ignore_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
6410 GNUNET_SERVER_notification_context_add (nc, client); 4100 GNUNET_SERVER_notification_context_add (nc, client);
6411 GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO); 4101 GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO);
6412 4102
@@ -6416,96 +4106,18 @@ handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client,
6416 4106
6417 4107
6418/** 4108/**
6419 * Handler for clients announcing available services by a regular expression.
6420 *
6421 * @param cls closure
6422 * @param client identification of the client
6423 * @param message the actual message, which includes messages the client wants
6424 */
6425static void
6426handle_local_announce_regex (void *cls, struct GNUNET_SERVER_Client *client,
6427 const struct GNUNET_MessageHeader *message)
6428{
6429 const struct GNUNET_MESH_RegexAnnounce *msg;
6430 struct MeshRegexDescriptor rd;
6431 struct MeshClient *c;
6432 char *regex;
6433 size_t len;
6434 size_t offset;
6435
6436 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "announce regex started\n");
6437
6438 /* Sanity check for client registration */
6439 if (NULL == (c = client_get (client)))
6440 {
6441 GNUNET_break (0);
6442 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6443 return;
6444 }
6445 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
6446
6447 msg = (const struct GNUNET_MESH_RegexAnnounce *) message;
6448
6449 len = ntohs (message->size) - sizeof(struct GNUNET_MESH_RegexAnnounce);
6450 if (NULL != c->partial_regex)
6451 {
6452 regex = c->partial_regex;
6453 offset = strlen (c->partial_regex);
6454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6455 " continuation, already have %u bytes\n",
6456 offset);
6457 }
6458 else
6459 {
6460 regex = NULL;
6461 offset = 0;
6462 }
6463
6464 regex = GNUNET_realloc (regex, offset + len + 1);
6465 memcpy (&regex[offset], &msg[1], len);
6466 regex[offset + len] = '\0';
6467 if (0 == ntohs (msg->last))
6468 {
6469 c->partial_regex = regex;
6470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6471 " not ended, stored %u bytes for later\n",
6472 len);
6473 GNUNET_SERVER_receive_done (client, GNUNET_OK);
6474 return;
6475 }
6476 rd.regex = regex;
6477 rd.compression = ntohs (msg->compression_characters);
6478 rd.h = NULL;
6479 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " length %u\n", len);
6480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regex %s\n", regex);
6481 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " compr %u\n", ntohs (rd.compression));
6482 GNUNET_array_append (c->regexes, c->n_regex, rd);
6483 c->partial_regex = NULL;
6484 if (GNUNET_SCHEDULER_NO_TASK == c->regex_announce_task)
6485 {
6486 c->regex_announce_task = GNUNET_SCHEDULER_add_now (&regex_announce, c);
6487 }
6488 else
6489 {
6490 regex_put (&rd);
6491 }
6492 GNUNET_SERVER_receive_done (client, GNUNET_OK);
6493 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "announce regex processed\n");
6494}
6495
6496
6497/**
6498 * Handler for requests of new tunnels 4109 * Handler for requests of new tunnels
6499 * 4110 *
6500 * @param cls closure 4111 * @param cls Closure.
6501 * @param client identification of the client 4112 * @param client Identification of the client.
6502 * @param message the actual message 4113 * @param message The actual message.
6503 */ 4114 */
6504static void 4115static void
6505handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, 4116handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
6506 const struct GNUNET_MessageHeader *message) 4117 const struct GNUNET_MessageHeader *message)
6507{ 4118{
6508 struct GNUNET_MESH_TunnelMessage *t_msg; 4119 struct GNUNET_MESH_TunnelMessage *t_msg;
4120 struct MeshPeerInfo *peer_info;
6509 struct MeshTunnel *t; 4121 struct MeshTunnel *t;
6510 struct MeshClient *c; 4122 struct MeshClient *c;
6511 MESH_TunnelNumber tid; 4123 MESH_TunnelNumber tid;
@@ -6521,7 +4133,7 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
6521 } 4133 }
6522 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); 4134 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
6523 4135
6524 /* Message sanity check */ 4136 /* Message size sanity check */
6525 if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size)) 4137 if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
6526 { 4138 {
6527 GNUNET_break (0); 4139 GNUNET_break (0);
@@ -6530,6 +4142,8 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
6530 } 4142 }
6531 4143
6532 t_msg = (struct GNUNET_MESH_TunnelMessage *) message; 4144 t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
4145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " towards %s\n",
4146 GNUNET_i2s (&t_msg->peer));
6533 /* Sanity check for tunnel numbering */ 4147 /* Sanity check for tunnel numbering */
6534 tid = ntohl (t_msg->tunnel_id); 4148 tid = ntohl (t_msg->tunnel_id);
6535 if (0 == (tid & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI)) 4149 if (0 == (tid & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI))
@@ -6546,22 +4160,24 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
6546 return; 4160 return;
6547 } 4161 }
6548 4162
4163 /* Create tunnel */
6549 while (NULL != tunnel_get_by_pi (myid, next_tid)) 4164 while (NULL != tunnel_get_by_pi (myid, next_tid))
6550 next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; 4165 next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
6551 t = tunnel_new (myid, next_tid++, c, tid); 4166 t = tunnel_new (myid, next_tid, c, tid);
4167 next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
6552 if (NULL == t) 4168 if (NULL == t)
6553 { 4169 {
6554 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Tunnel creation failed.\n");
6555 GNUNET_break (0); 4170 GNUNET_break (0);
6556 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 4171 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6557 return; 4172 return;
6558 } 4173 }
6559 next_tid = next_tid & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; 4174 t->port = ntohl (t_msg->port);
6560 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATED TUNNEL %s [%x] (%x)\n", 4175 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATED TUNNEL %s[%x]:%u (%x)\n",
6561 GNUNET_i2s (&my_full_id), t->id.tid, t->local_tid); 4176 GNUNET_i2s (&my_full_id), t->id.tid, t->port, t->local_tid);
6562 t->peers = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
6563 4177
6564 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new tunnel created\n"); 4178 peer_info = peer_get (&t_msg->peer);
4179 peer_info_add_tunnel (peer_info, t);
4180 peer_connect (peer_info, t);
6565 GNUNET_SERVER_receive_done (client, GNUNET_OK); 4181 GNUNET_SERVER_receive_done (client, GNUNET_OK);
6566 return; 4182 return;
6567} 4183}
@@ -6615,80 +4231,24 @@ handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
6615 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 4231 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6616 return; 4232 return;
6617 } 4233 }
6618 if (c != t->owner || tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
6619 {
6620 client_ignore_tunnel (c, t);
6621 tunnel_destroy_empty (t);
6622 GNUNET_SERVER_receive_done (client, GNUNET_OK);
6623 return;
6624 }
6625 send_client_tunnel_disconnect (t, c);
6626 client_delete_tunnel (c, t);
6627 4234
6628 /* Don't try to ACK the client about the tunnel_destroy multicast packet */ 4235 /* Cleanup after the tunnel */
6629 t->owner = NULL; 4236 client_delete_tunnel (c, t);
6630 tunnel_send_destroy (t, 0); 4237 if (c == t->client)
6631 t->destroy = GNUNET_YES;
6632 /* The tunnel will be destroyed when the last message is transmitted. */
6633 GNUNET_SERVER_receive_done (client, GNUNET_OK);
6634 return;
6635}
6636
6637
6638/**
6639 * Handler for requests of seeting tunnel's speed.
6640 *
6641 * @param cls Closure (unused).
6642 * @param client Identification of the client.
6643 * @param message The actual message.
6644 */
6645static void
6646handle_local_tunnel_speed (void *cls, struct GNUNET_SERVER_Client *client,
6647 const struct GNUNET_MessageHeader *message)
6648{
6649 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
6650 struct MeshClient *c;
6651 struct MeshTunnel *t;
6652 MESH_TunnelNumber tid;
6653
6654 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6655 "Got a SPEED request from client!\n");
6656
6657 /* Sanity check for client registration */
6658 if (NULL == (c = client_get (client)))
6659 { 4238 {
6660 GNUNET_break (0); 4239 t->client = NULL;
6661 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6662 return;
6663 } 4240 }
6664 4241 else if (c == t->owner)
6665 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
6666
6667 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
6668
6669 /* Retrieve tunnel */
6670 tid = ntohl (tunnel_msg->tunnel_id);
6671 t = tunnel_get_by_local_id(c, tid);
6672 if (NULL == t)
6673 { 4242 {
6674 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " tunnel %X not found\n", tid); 4243 peer_info_remove_tunnel (peer_get_short (t->dest), t);
6675 GNUNET_break (0); 4244 t->owner = NULL;
6676 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6677 return;
6678 } 4245 }
6679 4246
6680 switch (ntohs(message->type)) 4247 /* The tunnel will be destroyed when the last message is transmitted. */
6681 { 4248 tunnel_destroy_empty (t);
6682 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MIN: 4249
6683 t->speed_min = GNUNET_YES;
6684 break;
6685 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MAX:
6686 t->speed_min = GNUNET_NO;
6687 break;
6688 default:
6689 GNUNET_break (0);
6690 }
6691 GNUNET_SERVER_receive_done (client, GNUNET_OK); 4250 GNUNET_SERVER_receive_done (client, GNUNET_OK);
4251 return;
6692} 4252}
6693 4253
6694 4254
@@ -6750,479 +4310,6 @@ handle_local_tunnel_buffer (void *cls, struct GNUNET_SERVER_Client *client,
6750 4310
6751 4311
6752/** 4312/**
6753 * Handler for connection requests to new peers
6754 *
6755 * @param cls closure
6756 * @param client identification of the client
6757 * @param message the actual message (PeerControl)
6758 */
6759static void
6760handle_local_connect_add (void *cls, struct GNUNET_SERVER_Client *client,
6761 const struct GNUNET_MessageHeader *message)
6762{
6763 struct GNUNET_MESH_PeerControl *peer_msg;
6764 struct MeshPeerInfo *peer_info;
6765 struct MeshClient *c;
6766 struct MeshTunnel *t;
6767 MESH_TunnelNumber tid;
6768
6769 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got connection request\n");
6770 /* Sanity check for client registration */
6771 if (NULL == (c = client_get (client)))
6772 {
6773 GNUNET_break (0);
6774 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6775 return;
6776 }
6777 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
6778
6779 peer_msg = (struct GNUNET_MESH_PeerControl *) message;
6780
6781 /* Sanity check for message size */
6782 if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
6783 {
6784 GNUNET_break (0);
6785 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6786 return;
6787 }
6788
6789 /* Tunnel exists? */
6790 tid = ntohl (peer_msg->tunnel_id);
6791 t = tunnel_get_by_local_id (c, tid);
6792 if (NULL == t)
6793 {
6794 GNUNET_break (0);
6795 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6796 return;
6797 }
6798
6799 /* Does client own tunnel? */
6800 if (t->owner->handle != client)
6801 {
6802 GNUNET_break (0);
6803 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6804 return;
6805 }
6806 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for %s\n",
6807 GNUNET_i2s (&peer_msg->peer));
6808 peer_info = peer_info_get (&peer_msg->peer);
6809
6810 tunnel_add_peer (t, peer_info);
6811 peer_info_connect (peer_info, t);
6812
6813 GNUNET_SERVER_receive_done (client, GNUNET_OK);
6814 return;
6815}
6816
6817
6818/**
6819 * Handler for disconnection requests of peers in a tunnel
6820 *
6821 * @param cls closure
6822 * @param client identification of the client
6823 * @param message the actual message (PeerControl)
6824 */
6825static void
6826handle_local_connect_del (void *cls, struct GNUNET_SERVER_Client *client,
6827 const struct GNUNET_MessageHeader *message)
6828{
6829 struct GNUNET_MESH_PeerControl *peer_msg;
6830 struct MeshPeerInfo *peer_info;
6831 struct MeshClient *c;
6832 struct MeshTunnel *t;
6833 MESH_TunnelNumber tid;
6834
6835 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a PEER DEL request\n");
6836 /* Sanity check for client registration */
6837 if (NULL == (c = client_get (client)))
6838 {
6839 GNUNET_break (0);
6840 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6841 return;
6842 }
6843 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
6844
6845 peer_msg = (struct GNUNET_MESH_PeerControl *) message;
6846
6847 /* Sanity check for message size */
6848 if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
6849 {
6850 GNUNET_break (0);
6851 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6852 return;
6853 }
6854
6855 /* Tunnel exists? */
6856 tid = ntohl (peer_msg->tunnel_id);
6857 t = tunnel_get_by_local_id (c, tid);
6858 if (NULL == t)
6859 {
6860 GNUNET_break (0);
6861 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6862 return;
6863 }
6864 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", t->id.tid);
6865
6866 /* Does client own tunnel? */
6867 if (t->owner->handle != client)
6868 {
6869 GNUNET_break (0);
6870 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6871 return;
6872 }
6873
6874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for peer %s\n",
6875 GNUNET_i2s (&peer_msg->peer));
6876 /* Is the peer in the tunnel? */
6877 peer_info =
6878 GNUNET_CONTAINER_multihashmap_get (t->peers, &peer_msg->peer.hashPubKey);
6879 if (NULL == peer_info)
6880 {
6881 GNUNET_break (0);
6882 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6883 return;
6884 }
6885
6886 /* Ok, delete peer from tunnel */
6887 GNUNET_CONTAINER_multihashmap_remove_all (t->peers,
6888 &peer_msg->peer.hashPubKey);
6889
6890 send_destroy_path (t, peer_info->id);
6891 tunnel_delete_peer (t, peer_info->id);
6892 GNUNET_SERVER_receive_done (client, GNUNET_OK);
6893 return;
6894}
6895
6896/**
6897 * Handler for blacklist requests of peers in a tunnel
6898 *
6899 * @param cls closure
6900 * @param client identification of the client
6901 * @param message the actual message (PeerControl)
6902 *
6903 * FIXME implement DHT block bloomfilter
6904 */
6905static void
6906handle_local_blacklist (void *cls, struct GNUNET_SERVER_Client *client,
6907 const struct GNUNET_MessageHeader *message)
6908{
6909 struct GNUNET_MESH_PeerControl *peer_msg;
6910 struct MeshClient *c;
6911 struct MeshTunnel *t;
6912 MESH_TunnelNumber tid;
6913
6914 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a PEER BLACKLIST request\n");
6915 /* Sanity check for client registration */
6916 if (NULL == (c = client_get (client)))
6917 {
6918 GNUNET_break (0);
6919 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6920 return;
6921 }
6922 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
6923
6924 peer_msg = (struct GNUNET_MESH_PeerControl *) message;
6925
6926 /* Sanity check for message size */
6927 if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
6928 {
6929 GNUNET_break (0);
6930 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6931 return;
6932 }
6933
6934 /* Tunnel exists? */
6935 tid = ntohl (peer_msg->tunnel_id);
6936 t = tunnel_get_by_local_id (c, tid);
6937 if (NULL == t)
6938 {
6939 GNUNET_break (0);
6940 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6941 return;
6942 }
6943 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", t->id.tid);
6944
6945 GNUNET_array_append(t->blacklisted, t->nblacklisted,
6946 GNUNET_PEER_intern(&peer_msg->peer));
6947}
6948
6949
6950/**
6951 * Handler for unblacklist requests of peers in a tunnel
6952 *
6953 * @param cls closure
6954 * @param client identification of the client
6955 * @param message the actual message (PeerControl)
6956 */
6957static void
6958handle_local_unblacklist (void *cls, struct GNUNET_SERVER_Client *client,
6959 const struct GNUNET_MessageHeader *message)
6960{
6961 struct GNUNET_MESH_PeerControl *peer_msg;
6962 struct MeshClient *c;
6963 struct MeshTunnel *t;
6964 MESH_TunnelNumber tid;
6965 GNUNET_PEER_Id pid;
6966 unsigned int i;
6967
6968 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a PEER UNBLACKLIST request\n");
6969 /* Sanity check for client registration */
6970 if (NULL == (c = client_get (client)))
6971 {
6972 GNUNET_break (0);
6973 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6974 return;
6975 }
6976 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
6977
6978 peer_msg = (struct GNUNET_MESH_PeerControl *) message;
6979
6980 /* Sanity check for message size */
6981 if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
6982 {
6983 GNUNET_break (0);
6984 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6985 return;
6986 }
6987
6988 /* Tunnel exists? */
6989 tid = ntohl (peer_msg->tunnel_id);
6990 t = tunnel_get_by_local_id (c, tid);
6991 if (NULL == t)
6992 {
6993 GNUNET_break (0);
6994 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
6995 return;
6996 }
6997 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", t->id.tid);
6998
6999 /* if peer is not known, complain */
7000 pid = GNUNET_PEER_search (&peer_msg->peer);
7001 if (0 == pid)
7002 {
7003 GNUNET_break (0);
7004 return;
7005 }
7006
7007 /* search and remove from list */
7008 for (i = 0; i < t->nblacklisted; i++)
7009 {
7010 if (t->blacklisted[i] == pid)
7011 {
7012 t->blacklisted[i] = t->blacklisted[t->nblacklisted - 1];
7013 GNUNET_array_grow (t->blacklisted, t->nblacklisted, t->nblacklisted - 1);
7014 return;
7015 }
7016 }
7017
7018 /* if peer hasn't been blacklisted, complain */
7019 GNUNET_break (0);
7020}
7021
7022
7023/**
7024 * Handler for connection requests to new peers by type
7025 *
7026 * @param cls closure
7027 * @param client identification of the client
7028 * @param message the actual message (ConnectPeerByType)
7029 */
7030static void
7031handle_local_connect_by_type (void *cls, struct GNUNET_SERVER_Client *client,
7032 const struct GNUNET_MessageHeader *message)
7033{
7034 struct GNUNET_MESH_ConnectPeerByType *connect_msg;
7035 struct MeshClient *c;
7036 struct MeshTunnel *t;
7037 struct GNUNET_HashCode hash;
7038 MESH_TunnelNumber tid;
7039
7040 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got connect by type request\n");
7041 /* Sanity check for client registration */
7042 if (NULL == (c = client_get (client)))
7043 {
7044 GNUNET_break (0);
7045 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7046 return;
7047 }
7048 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
7049
7050 connect_msg = (struct GNUNET_MESH_ConnectPeerByType *) message;
7051
7052 /* Sanity check for message size */
7053 if (sizeof (struct GNUNET_MESH_ConnectPeerByType) !=
7054 ntohs (connect_msg->header.size))
7055 {
7056 GNUNET_break (0);
7057 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7058 return;
7059 }
7060
7061 /* Tunnel exists? */
7062 tid = ntohl (connect_msg->tunnel_id);
7063 t = tunnel_get_by_local_id (c, tid);
7064 if (NULL == t)
7065 {
7066 GNUNET_break (0);
7067 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7068 return;
7069 }
7070
7071 /* Does client own tunnel? */
7072 if (t->owner->handle != client)
7073 {
7074 GNUNET_break (0);
7075 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7076 return;
7077 }
7078
7079 /* Do WE have the service? */
7080 t->type = ntohl (connect_msg->type);
7081 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " type requested: %u\n", t->type);
7082 GNUNET_CRYPTO_hash (&t->type, sizeof (GNUNET_MESH_ApplicationType), &hash);
7083 if (GNUNET_CONTAINER_multihashmap_contains (applications, &hash) ==
7084 GNUNET_YES)
7085 {
7086 /* Yes! Fast forward, add ourselves to the tunnel and send the
7087 * good news to the client, and alert the destination client of
7088 * an incoming tunnel.
7089 *
7090 * FIXME send a path create to self, avoid code duplication
7091 */
7092 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " available locally\n");
7093 GNUNET_CONTAINER_multihashmap_put (t->peers, &my_full_id.hashPubKey,
7094 peer_info_get (&my_full_id),
7095 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
7096
7097 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " notifying client\n");
7098 send_client_peer_connected (t, myid);
7099 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Done\n");
7100 GNUNET_SERVER_receive_done (client, GNUNET_OK);
7101
7102 t->local_tid_dest = next_local_tid++;
7103 GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
7104 GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
7105 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
7106
7107 return;
7108 }
7109 /* Ok, lets find a peer offering the service */
7110 if (NULL != t->dht_get_type)
7111 {
7112 GNUNET_DHT_get_stop (t->dht_get_type);
7113 }
7114 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " looking in DHT for %s\n",
7115 GNUNET_h2s (&hash));
7116 t->dht_get_type =
7117 GNUNET_DHT_get_start (dht_handle,
7118 GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE,
7119 &hash,
7120 dht_replication_level,
7121 GNUNET_DHT_RO_RECORD_ROUTE |
7122 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
7123 NULL, 0,
7124 &dht_get_type_handler, t);
7125
7126 GNUNET_SERVER_receive_done (client, GNUNET_OK);
7127 return;
7128}
7129
7130
7131/**
7132 * Handler for connection requests to new peers by a string service description.
7133 *
7134 * @param cls closure
7135 * @param client identification of the client
7136 * @param message the actual message, which includes messages the client wants
7137 */
7138static void
7139handle_local_connect_by_string (void *cls, struct GNUNET_SERVER_Client *client,
7140 const struct GNUNET_MessageHeader *message)
7141{
7142 struct GNUNET_MESH_ConnectPeerByString *msg;
7143 struct MeshRegexSearchInfo *info;
7144 struct MeshTunnel *t;
7145 struct MeshClient *c;
7146 MESH_TunnelNumber tid;
7147 const char *string;
7148 size_t size;
7149 size_t len;
7150
7151 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7152 "Connect by string started\n");
7153 msg = (struct GNUNET_MESH_ConnectPeerByString *) message;
7154 size = htons (message->size);
7155
7156 /* Sanity check for client registration */
7157 if (NULL == (c = client_get (client)))
7158 {
7159 GNUNET_break (0);
7160 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7161 return;
7162 }
7163 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
7164
7165 /* Message size sanity check */
7166 if (sizeof(struct GNUNET_MESH_ConnectPeerByString) >= size)
7167 {
7168 GNUNET_break (0);
7169 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7170 return;
7171 }
7172
7173 /* Tunnel exists? */
7174 tid = ntohl (msg->tunnel_id);
7175 t = tunnel_get_by_local_id (c, tid);
7176 if (NULL == t)
7177 {
7178 GNUNET_break (0);
7179 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7180 return;
7181 }
7182
7183 /* Does client own tunnel? */
7184 if (t->owner->handle != client)
7185 {
7186 GNUNET_break (0);
7187 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7188 return;
7189 }
7190
7191 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7192 " on tunnel %s [%u]\n",
7193 GNUNET_i2s(&my_full_id),
7194 t->id.tid);
7195
7196 /* Only one connect_by_string allowed at the same time! */
7197 /* FIXME: allow more, return handle at api level to cancel, document */
7198 if (NULL != t->regex_search)
7199 {
7200 GNUNET_break (0);
7201 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7202 return;
7203 }
7204
7205 /* Find string itself */
7206 len = size - sizeof(struct GNUNET_MESH_ConnectPeerByString);
7207 string = (const char *) &msg[1];
7208
7209 info = GNUNET_malloc (sizeof (struct MeshRegexSearchInfo));
7210 info->t = t;
7211 info->description = GNUNET_strndup (string, len);
7212 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " string: %s\n", info->description);
7213
7214 t->regex_search = info;
7215
7216 info->search_handle = GNUNET_REGEX_search (cfg,
7217 info->description,
7218 &regex_found_handler, info);
7219
7220 GNUNET_SERVER_receive_done (client, GNUNET_OK);
7221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connect by string processed\n");
7222}
7223
7224
7225/**
7226 * Handler for client traffic directed to one peer 4313 * Handler for client traffic directed to one peer
7227 * 4314 *
7228 * @param cls closure 4315 * @param cls closure
@@ -7235,8 +4322,7 @@ handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client,
7235{ 4322{
7236 struct MeshClient *c; 4323 struct MeshClient *c;
7237 struct MeshTunnel *t; 4324 struct MeshTunnel *t;
7238 struct MeshPeerInfo *pi; 4325 struct GNUNET_MESH_Data *data_msg;
7239 struct GNUNET_MESH_Unicast *data_msg;
7240 MESH_TunnelNumber tid; 4326 MESH_TunnelNumber tid;
7241 size_t size; 4327 size_t size;
7242 4328
@@ -7252,11 +4338,11 @@ handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client,
7252 } 4338 }
7253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); 4339 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
7254 4340
7255 data_msg = (struct GNUNET_MESH_Unicast *) message; 4341 data_msg = (struct GNUNET_MESH_Data *) message;
7256 4342
7257 /* Sanity check for message size */ 4343 /* Sanity check for message size */
7258 size = ntohs (message->size); 4344 size = ntohs (message->size);
7259 if (sizeof (struct GNUNET_MESH_Unicast) + 4345 if (sizeof (struct GNUNET_MESH_Data) +
7260 sizeof (struct GNUNET_MessageHeader) > size) 4346 sizeof (struct GNUNET_MessageHeader) > size)
7261 { 4347 {
7262 GNUNET_break (0); 4348 GNUNET_break (0);
@@ -7282,23 +4368,13 @@ handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client,
7282 return; 4368 return;
7283 } 4369 }
7284 4370
7285 pi = GNUNET_CONTAINER_multihashmap_get (t->peers, 4371 /* PID should be as expected: client<->service communication */
7286 &data_msg->destination.hashPubKey); 4372 if (ntohl (data_msg->pid) != t->prev_fc.last_pid_recv + 1)
7287 /* Is the selected peer in the tunnel? */
7288 if (NULL == pi)
7289 {
7290 GNUNET_break (0);
7291 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7292 return;
7293 }
7294
7295 /* PID should be as expected */
7296 if (ntohl (data_msg->pid) != t->fwd_pid + 1)
7297 { 4373 {
7298 GNUNET_break (0); 4374 GNUNET_break (0);
7299 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 4375 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
7300 "Unicast PID, expected %u, got %u\n", 4376 "Unicast PID, expected %u, got %u\n",
7301 t->fwd_pid + 1, ntohl (data_msg->pid)); 4377 t->prev_fc.last_pid_recv + 1, ntohl (data_msg->pid));
7302 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 4378 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7303 return; 4379 return;
7304 } 4380 }
@@ -7309,16 +4385,16 @@ handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client,
7309 { 4385 {
7310 /* Work around const limitation */ 4386 /* Work around const limitation */
7311 char buf[ntohs (message->size)] GNUNET_ALIGN; 4387 char buf[ntohs (message->size)] GNUNET_ALIGN;
7312 struct GNUNET_MESH_Unicast *copy; 4388 struct GNUNET_MESH_Data *copy;
7313 4389
7314 copy = (struct GNUNET_MESH_Unicast *) buf; 4390 copy = (struct GNUNET_MESH_Data *) buf;
7315 memcpy (buf, data_msg, size); 4391 memcpy (buf, data_msg, size);
7316 copy->oid = my_full_id; 4392 copy->oid = my_full_id;
7317 copy->tid = htonl (t->id.tid); 4393 copy->tid = htonl (t->id.tid);
7318 copy->ttl = htonl (default_ttl); 4394 copy->ttl = htonl (default_ttl);
7319 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 4395 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7320 " calling generic handler...\n"); 4396 " calling generic handler...\n");
7321 handle_mesh_data_unicast (NULL, &my_full_id, &copy->header); 4397 handle_mesh_unicast (NULL, &my_full_id, &copy->header);
7322 } 4398 }
7323 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n"); 4399 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n");
7324 GNUNET_SERVER_receive_done (client, GNUNET_OK); 4400 GNUNET_SERVER_receive_done (client, GNUNET_OK);
@@ -7338,8 +4414,8 @@ static void
7338handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client, 4414handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client,
7339 const struct GNUNET_MessageHeader *message) 4415 const struct GNUNET_MessageHeader *message)
7340{ 4416{
7341 struct GNUNET_MESH_ToOrigin *data_msg; 4417 struct GNUNET_MESH_Data *data_msg;
7342 struct MeshTunnelClientInfo *clinfo; 4418 struct MeshFlowControl *fc;
7343 struct MeshClient *c; 4419 struct MeshClient *c;
7344 struct MeshTunnel *t; 4420 struct MeshTunnel *t;
7345 MESH_TunnelNumber tid; 4421 MESH_TunnelNumber tid;
@@ -7356,11 +4432,11 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client,
7356 } 4432 }
7357 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); 4433 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
7358 4434
7359 data_msg = (struct GNUNET_MESH_ToOrigin *) message; 4435 data_msg = (struct GNUNET_MESH_Data *) message;
7360 4436
7361 /* Sanity check for message size */ 4437 /* Sanity check for message size */
7362 size = ntohs (message->size); 4438 size = ntohs (message->size);
7363 if (sizeof (struct GNUNET_MESH_ToOrigin) + 4439 if (sizeof (struct GNUNET_MESH_Data) +
7364 sizeof (struct GNUNET_MessageHeader) > size) 4440 sizeof (struct GNUNET_MessageHeader) > size)
7365 { 4441 {
7366 GNUNET_break (0); 4442 GNUNET_break (0);
@@ -7388,7 +4464,7 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client,
7388 } 4464 }
7389 4465
7390 /* It should be sent by someone who has this as incoming tunnel. */ 4466 /* It should be sent by someone who has this as incoming tunnel. */
7391 if (GNUNET_NO == client_knows_tunnel (c, t)) 4467 if (t->client != c)
7392 { 4468 {
7393 GNUNET_break (0); 4469 GNUNET_break (0);
7394 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 4470 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
@@ -7396,38 +4472,35 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client,
7396 } 4472 }
7397 4473
7398 /* PID should be as expected */ 4474 /* PID should be as expected */
7399 clinfo = tunnel_get_client_fc (t, c); 4475 fc = &t->next_fc;
7400 if (ntohl (data_msg->pid) != clinfo->bck_pid + 1) 4476 if (ntohl (data_msg->pid) != fc->last_pid_recv + 1)
7401 { 4477 {
7402 GNUNET_break (0); 4478 GNUNET_break (0);
7403 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 4479 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
7404 "To Origin PID, expected %u, got %u\n", 4480 "To Origin PID, expected %u, got %u\n",
7405 clinfo->bck_pid + 1, 4481 fc->last_pid_recv + 1,
7406 ntohl (data_msg->pid)); 4482 ntohl (data_msg->pid));
7407 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 4483 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7408 return; 4484 return;
7409 } 4485 }
7410 clinfo->bck_pid++;
7411 4486
7412 /* Ok, everything is correct, send the message 4487 /* Ok, everything is correct, send the message
7413 * (pretend we got it from a mesh peer) 4488 * (pretend we got it from a mesh peer)
7414 */ 4489 */
7415 { 4490 {
7416 char buf[ntohs (message->size)] GNUNET_ALIGN; 4491 char buf[ntohs (message->size)] GNUNET_ALIGN;
7417 struct GNUNET_MESH_ToOrigin *copy; 4492 struct GNUNET_MESH_Data *copy;
7418 4493
7419 /* Work around const limitation */ 4494 /* Work around 'const' limitation */
7420 copy = (struct GNUNET_MESH_ToOrigin *) buf;
7421 memcpy (buf, data_msg, size); 4495 memcpy (buf, data_msg, size);
4496 copy = (struct GNUNET_MESH_Data *) buf;
7422 GNUNET_PEER_resolve (t->id.oid, &copy->oid); 4497 GNUNET_PEER_resolve (t->id.oid, &copy->oid);
7423 copy->tid = htonl (t->id.tid); 4498 copy->tid = htonl (t->id.tid);
7424 copy->ttl = htonl (default_ttl); 4499 copy->ttl = htonl (default_ttl);
7425 copy->pid = htonl (t->bck_pid + 1);
7426 4500
7427 copy->sender = my_full_id;
7428 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 4501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7429 " calling generic handler...\n"); 4502 " calling generic handler...\n");
7430 handle_mesh_data_to_orig (NULL, &my_full_id, &copy->header); 4503 handle_mesh_to_orig (NULL, &my_full_id, &copy->header);
7431 } 4504 }
7432 GNUNET_SERVER_receive_done (client, GNUNET_OK); 4505 GNUNET_SERVER_receive_done (client, GNUNET_OK);
7433 4506
@@ -7436,97 +4509,6 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client,
7436 4509
7437 4510
7438/** 4511/**
7439 * Handler for client traffic directed to all peers in a tunnel
7440 *
7441 * @param cls closure
7442 * @param client identification of the client
7443 * @param message the actual message
7444 */
7445static void
7446handle_local_multicast (void *cls, struct GNUNET_SERVER_Client *client,
7447 const struct GNUNET_MessageHeader *message)
7448{
7449 struct MeshClient *c;
7450 struct MeshTunnel *t;
7451 struct GNUNET_MESH_Multicast *data_msg;
7452 MESH_TunnelNumber tid;
7453
7454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7455 "Got a multicast request from a client!\n");
7456
7457 /* Sanity check for client registration */
7458 if (NULL == (c = client_get (client)))
7459 {
7460 GNUNET_break (0);
7461 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7462 return;
7463 }
7464 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
7465
7466 data_msg = (struct GNUNET_MESH_Multicast *) message;
7467
7468 /* Sanity check for message size */
7469 if (sizeof (struct GNUNET_MESH_Multicast) +
7470 sizeof (struct GNUNET_MessageHeader) > ntohs (data_msg->header.size))
7471 {
7472 GNUNET_break (0);
7473 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7474 return;
7475 }
7476
7477 /* Tunnel exists? */
7478 tid = ntohl (data_msg->tid);
7479 t = tunnel_get_by_local_id (c, tid);
7480 if (NULL == t)
7481 {
7482 GNUNET_break (0);
7483 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tunnel %X unknown.\n", tid);
7484 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " for client %u.\n", c->id);
7485 GNUNET_break (0);
7486 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7487 return;
7488 }
7489
7490 /* Does client own tunnel? */
7491 if (t->owner->handle != client)
7492 {
7493 GNUNET_break (0);
7494 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7495 return;
7496 }
7497
7498 /* PID should be as expected */
7499 if (ntohl (data_msg->pid) != t->fwd_pid + 1)
7500 {
7501 GNUNET_break (0);
7502 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
7503 "Multicast PID, expected %u, got %u\n",
7504 t->fwd_pid + 1, ntohl (data_msg->pid));
7505 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
7506 return;
7507 }
7508
7509 {
7510 char buf[ntohs (message->size)] GNUNET_ALIGN;
7511 struct GNUNET_MESH_Multicast *copy;
7512
7513 copy = (struct GNUNET_MESH_Multicast *) buf;
7514 memcpy (buf, message, ntohs (message->size));
7515 copy->oid = my_full_id;
7516 copy->tid = htonl (t->id.tid);
7517 copy->ttl = htonl (default_ttl);
7518 GNUNET_assert (ntohl (copy->pid) == (t->fwd_pid + 1));
7519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7520 " calling generic handler...\n");
7521 handle_mesh_data_multicast (client, &my_full_id, &copy->header);
7522 }
7523
7524 GNUNET_SERVER_receive_done (t->owner->handle, GNUNET_OK);
7525 return;
7526}
7527
7528
7529/**
7530 * Handler for client's ACKs for payload traffic. 4512 * Handler for client's ACKs for payload traffic.
7531 * 4513 *
7532 * @param cls Closure (unused). 4514 * @param cls Closure (unused).
@@ -7568,20 +4550,20 @@ handle_local_ack (void *cls, struct GNUNET_SERVER_Client *client,
7568 return; 4550 return;
7569 } 4551 }
7570 4552
7571 ack = ntohl (msg->max_pid); 4553 ack = ntohl (msg->ack);
7572 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ack); 4554 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ack);
7573 4555
7574 /* Does client own tunnel? I.E: Is this an ACK for BCK traffic? */ 4556 /* Does client own tunnel? I.E: Is this an ACK for BCK traffic? */
7575 if (NULL != t->owner && t->owner->handle == client) 4557 if (t->owner == c)
7576 { 4558 {
7577 /* The client owns the tunnel, ACK is for data to_origin, send BCK ACK. */ 4559 /* The client owns the tunnel, ACK is for data to_origin, send BCK ACK. */
7578 t->bck_ack = ack; 4560 t->prev_fc.last_ack_recv = ack;
7579 tunnel_send_bck_ack(t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); 4561 tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
7580 } 4562 }
7581 else 4563 else
7582 { 4564 {
7583 /* The client doesn't own the tunnel, this ACK is for FWD traffic. */ 4565 /* The client doesn't own the tunnel, this ACK is for FWD traffic. */
7584 tunnel_set_client_fwd_ack (t, c, ack); 4566 t->next_fc.last_ack_recv = ack;
7585 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); 4567 tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
7586 } 4568 }
7587 4569
@@ -7591,36 +4573,6 @@ handle_local_ack (void *cls, struct GNUNET_SERVER_Client *client,
7591} 4573}
7592 4574
7593 4575
7594/**
7595 * Iterator over all peers to send a monitoring client info about a tunnel.
7596 *
7597 * @param cls Closure (message being built).
7598 * @param key Key (hashed tunnel ID, unused).
7599 * @param value Peer info.
7600 *
7601 * @return GNUNET_YES, to keep iterating.
7602 */
7603static int
7604monitor_peers_iterator (void *cls,
7605 const struct GNUNET_HashCode * key,
7606 void *value)
7607{
7608 struct GNUNET_MESH_LocalMonitor *msg = cls;
7609 struct GNUNET_PeerIdentity *id;
7610 struct MeshPeerInfo *info = value;
7611
7612 id = (struct GNUNET_PeerIdentity *) &msg[1];
7613 GNUNET_PEER_resolve (info->id, &id[msg->npeers]);
7614 msg->npeers++;
7615
7616 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
7617 "* sending info about peer %s [%u]\n",
7618 GNUNET_i2s (&id[msg->npeers - 1]), msg->npeers);
7619
7620 return GNUNET_YES;
7621}
7622
7623
7624 4576
7625/** 4577/**
7626 * Iterator over all tunnels to send a monitoring client info about each tunnel. 4578 * Iterator over all tunnels to send a monitoring client info about each tunnel.
@@ -7639,37 +4591,21 @@ monitor_all_tunnels_iterator (void *cls,
7639 struct GNUNET_SERVER_Client *client = cls; 4591 struct GNUNET_SERVER_Client *client = cls;
7640 struct MeshTunnel *t = value; 4592 struct MeshTunnel *t = value;
7641 struct GNUNET_MESH_LocalMonitor *msg; 4593 struct GNUNET_MESH_LocalMonitor *msg;
7642 uint32_t npeers; 4594
7643 4595 msg = GNUNET_malloc (sizeof(struct GNUNET_MESH_LocalMonitor));
7644 npeers = GNUNET_CONTAINER_multihashmap_size (t->peers);
7645 msg = GNUNET_malloc (sizeof(struct GNUNET_MESH_LocalMonitor) +
7646 npeers * sizeof (struct GNUNET_PeerIdentity));
7647 GNUNET_PEER_resolve(t->id.oid, &msg->owner); 4596 GNUNET_PEER_resolve(t->id.oid, &msg->owner);
7648 msg->tunnel_id = htonl (t->id.tid); 4597 msg->tunnel_id = htonl (t->id.tid);
7649 msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor) + 4598 msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
7650 npeers * sizeof (struct GNUNET_PeerIdentity));
7651 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS); 4599 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
7652 msg->npeers = 0; 4600 GNUNET_PEER_resolve (t->dest, &msg->destination);
7653 (void) GNUNET_CONTAINER_multihashmap_iterate (t->peers, 4601
7654 monitor_peers_iterator,
7655 msg);
7656
7657 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4602 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
7658 "* sending info about tunnel %s [%u] (%u peers)\n", 4603 "* sending info about tunnel %s [%u]\n",
7659 GNUNET_i2s (&msg->owner), t->id.tid, npeers); 4604 GNUNET_i2s (&msg->owner), t->id.tid);
7660 4605
7661 if (msg->npeers != npeers) 4606 GNUNET_SERVER_notification_context_unicast (nc, client,
7662 { 4607 &msg->header, GNUNET_NO);
7663 GNUNET_break (0); 4608 return GNUNET_YES;
7664 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
7665 "Get tunnels fail: size %u - iter %u\n",
7666 npeers, msg->npeers);
7667 }
7668
7669 msg->npeers = htonl (npeers);
7670 GNUNET_SERVER_notification_context_unicast (nc, client,
7671 &msg->header, GNUNET_NO);
7672 return GNUNET_YES;
7673} 4609}
7674 4610
7675 4611
@@ -7708,107 +4644,6 @@ handle_local_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client,
7708 4644
7709 4645
7710/** 4646/**
7711 * Data needed to build a Monitor_Tunnel message.
7712 */
7713struct MeshMonitorTunnelContext
7714{
7715 /**
7716 * Partial message, including peer count.
7717 */
7718 struct GNUNET_MESH_LocalMonitor *msg;
7719
7720 /**
7721 * Hashmap with positions: peer->position.
7722 */
7723 struct GNUNET_CONTAINER_MultiHashMap *lookup;
7724
7725 /**
7726 * Index of the parent of each peer in the message, realtive to the absolute
7727 * order in the array (can be in a previous message).
7728 */
7729 uint32_t parents[1024];
7730
7731 /**
7732 * Peers visited so far in the tree, aka position of the current peer.
7733 */
7734 unsigned int npeers;
7735
7736 /**
7737 * Client requesting the info.
7738 */
7739 struct MeshClient *c;
7740};
7741
7742
7743/**
7744 * Send a client a message about the structure of a tunnel.
7745 *
7746 * @param ctx Context of the tunnel iteration, with info regarding the state
7747 * of the execution and the number of peers visited for this message.
7748 */
7749static void
7750send_client_tunnel_info (struct MeshMonitorTunnelContext *ctx)
7751{
7752 struct GNUNET_MESH_LocalMonitor *resp = ctx->msg;
7753 struct GNUNET_PeerIdentity *pid;
7754 unsigned int *parent;
7755 size_t size;
7756
7757 size = sizeof (struct GNUNET_MESH_LocalMonitor);
7758 size += (sizeof (struct GNUNET_PeerIdentity) + sizeof (int)) * resp->npeers;
7759 resp->header.size = htons (size);
7760 pid = (struct GNUNET_PeerIdentity *) &resp[1];
7761 parent = (unsigned int *) &pid[resp->npeers];
7762 memcpy (parent, ctx->parents, sizeof(uint32_t) * resp->npeers);
7763 GNUNET_SERVER_notification_context_unicast (nc, ctx->c->handle,
7764 &resp->header, GNUNET_NO);
7765}
7766
7767/**
7768 * Iterator over a tunnel tree to build a message containing all peers
7769 * the in the tunnel, including relay nodes.
7770 *
7771 * @param cls Closure (pointer to pointer of message being built).
7772 * @param peer Short ID of a peer.
7773 * @param parent Short ID of the @c peer 's parent.
7774 */
7775static void
7776tunnel_tree_iterator (void *cls,
7777 GNUNET_PEER_Id peer,
7778 GNUNET_PEER_Id parent)
7779{
7780 struct MeshMonitorTunnelContext *ctx = cls;
7781 struct GNUNET_MESH_LocalMonitor *msg;
7782 struct GNUNET_PeerIdentity *pid;
7783 struct GNUNET_PeerIdentity ppid;
7784
7785 msg = ctx->msg;
7786 pid = (struct GNUNET_PeerIdentity *) &msg[1];
7787 GNUNET_PEER_resolve (peer, &pid[msg->npeers]);
7788 GNUNET_CONTAINER_multihashmap_put (ctx->lookup,
7789 &pid[msg->npeers].hashPubKey,
7790 (void *) (long) ctx->npeers,
7791 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
7792 GNUNET_PEER_resolve (parent, &ppid);
7793 ctx->parents[msg->npeers] =
7794 htonl ((long) GNUNET_CONTAINER_multihashmap_get (ctx->lookup,
7795 &ppid.hashPubKey));
7796
7797 ctx->npeers++;
7798 msg->npeers++;
7799
7800 if (sizeof (struct GNUNET_MESH_LocalMonitor) +
7801 (msg->npeers + 1) *
7802 (sizeof (struct GNUNET_PeerIdentity) + sizeof (uint32_t))
7803 > USHRT_MAX)
7804 {
7805 send_client_tunnel_info (ctx);
7806 msg->npeers = 0;
7807 }
7808}
7809
7810
7811/**
7812 * Handler for client's MONITOR_TUNNEL request. 4647 * Handler for client's MONITOR_TUNNEL request.
7813 * 4648 *
7814 * @param cls Closure (unused). 4649 * @param cls Closure (unused).
@@ -7821,7 +4656,6 @@ handle_local_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
7821{ 4656{
7822 const struct GNUNET_MESH_LocalMonitor *msg; 4657 const struct GNUNET_MESH_LocalMonitor *msg;
7823 struct GNUNET_MESH_LocalMonitor *resp; 4658 struct GNUNET_MESH_LocalMonitor *resp;
7824 struct MeshMonitorTunnelContext ctx;
7825 struct MeshClient *c; 4659 struct MeshClient *c;
7826 struct MeshTunnel *t; 4660 struct MeshTunnel *t;
7827 4661
@@ -7842,11 +4676,10 @@ handle_local_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
7842 t = tunnel_get (&msg->owner, ntohl (msg->tunnel_id)); 4676 t = tunnel_get (&msg->owner, ntohl (msg->tunnel_id));
7843 if (NULL == t) 4677 if (NULL == t)
7844 { 4678 {
7845 /* We don't know the tunnel */ 4679 /* We don't know the tunnel FIXME */
7846 struct GNUNET_MESH_LocalMonitor warn; 4680 struct GNUNET_MESH_LocalMonitor warn;
7847 4681
7848 warn = *msg; 4682 warn = *msg;
7849 warn.npeers = htonl (UINT_MAX);
7850 GNUNET_SERVER_notification_context_unicast (nc, client, 4683 GNUNET_SERVER_notification_context_unicast (nc, client,
7851 &warn.header, 4684 &warn.header,
7852 GNUNET_NO); 4685 GNUNET_NO);
@@ -7855,19 +4688,12 @@ handle_local_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
7855 } 4688 }
7856 4689
7857 /* Initialize context */ 4690 /* Initialize context */
7858 resp = GNUNET_malloc (USHRT_MAX); /* avoid realloc'ing on each step */ 4691 resp = GNUNET_malloc (sizeof (struct GNUNET_MESH_LocalMonitor));
7859 *resp = *msg; 4692 *resp = *msg;
7860 resp->npeers = 0; 4693 GNUNET_PEER_resolve (t->dest, &resp->destination);
7861 ctx.msg = resp; 4694 resp->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
7862 ctx.lookup = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES); 4695 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
7863 ctx.c = c; 4696 &resp->header, GNUNET_NO);
7864
7865 /* Collect and send information */
7866 tree_iterate_all (t->tree, &tunnel_tree_iterator, &ctx);
7867 send_client_tunnel_info (&ctx);
7868
7869 /* Free context */
7870 GNUNET_CONTAINER_multihashmap_destroy (ctx.lookup);
7871 GNUNET_free (resp); 4697 GNUNET_free (resp);
7872 4698
7873 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4699 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -7883,49 +4709,22 @@ handle_local_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
7883static struct GNUNET_SERVER_MessageHandler client_handlers[] = { 4709static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
7884 {&handle_local_new_client, NULL, 4710 {&handle_local_new_client, NULL,
7885 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0}, 4711 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
7886 {&handle_local_announce_regex, NULL,
7887 GNUNET_MESSAGE_TYPE_MESH_LOCAL_ANNOUNCE_REGEX, 0},
7888 {&handle_local_tunnel_create, NULL, 4712 {&handle_local_tunnel_create, NULL,
7889 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE, 4713 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
7890 sizeof (struct GNUNET_MESH_TunnelMessage)}, 4714 sizeof (struct GNUNET_MESH_TunnelMessage)},
7891 {&handle_local_tunnel_destroy, NULL, 4715 {&handle_local_tunnel_destroy, NULL,
7892 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY, 4716 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
7893 sizeof (struct GNUNET_MESH_TunnelMessage)}, 4717 sizeof (struct GNUNET_MESH_TunnelMessage)},
7894 {&handle_local_tunnel_speed, NULL,
7895 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MIN,
7896 sizeof (struct GNUNET_MESH_TunnelMessage)},
7897 {&handle_local_tunnel_speed, NULL,
7898 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MAX,
7899 sizeof (struct GNUNET_MESH_TunnelMessage)},
7900 {&handle_local_tunnel_buffer, NULL, 4718 {&handle_local_tunnel_buffer, NULL,
7901 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER, 4719 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER,
7902 sizeof (struct GNUNET_MESH_TunnelMessage)}, 4720 sizeof (struct GNUNET_MESH_TunnelMessage)},
7903 {&handle_local_tunnel_buffer, NULL, 4721 {&handle_local_tunnel_buffer, NULL,
7904 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER, 4722 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER,
7905 sizeof (struct GNUNET_MESH_TunnelMessage)}, 4723 sizeof (struct GNUNET_MESH_TunnelMessage)},
7906 {&handle_local_connect_add, NULL,
7907 GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD,
7908 sizeof (struct GNUNET_MESH_PeerControl)},
7909 {&handle_local_connect_del, NULL,
7910 GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL,
7911 sizeof (struct GNUNET_MESH_PeerControl)},
7912 {&handle_local_blacklist, NULL,
7913 GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_BLACKLIST,
7914 sizeof (struct GNUNET_MESH_PeerControl)},
7915 {&handle_local_unblacklist, NULL,
7916 GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_UNBLACKLIST,
7917 sizeof (struct GNUNET_MESH_PeerControl)},
7918 {&handle_local_connect_by_type, NULL,
7919 GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE,
7920 sizeof (struct GNUNET_MESH_ConnectPeerByType)},
7921 {&handle_local_connect_by_string, NULL,
7922 GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_STRING, 0},
7923 {&handle_local_unicast, NULL, 4724 {&handle_local_unicast, NULL,
7924 GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0}, 4725 GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
7925 {&handle_local_to_origin, NULL, 4726 {&handle_local_to_origin, NULL,
7926 GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0}, 4727 GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
7927 {&handle_local_multicast, NULL,
7928 GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
7929 {&handle_local_ack, NULL, 4728 {&handle_local_ack, NULL,
7930 GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK, 4729 GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK,
7931 sizeof (struct GNUNET_MESH_LocalAck)}, 4730 sizeof (struct GNUNET_MESH_LocalAck)},
@@ -7940,38 +4739,6 @@ static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
7940 4739
7941 4740
7942/** 4741/**
7943 * To be called on core init/fail.
7944 *
7945 * @param cls service closure
7946 * @param server handle to the server for this service
7947 * @param identity the public identity of this peer
7948 */
7949static void
7950core_init (void *cls, struct GNUNET_CORE_Handle *server,
7951 const struct GNUNET_PeerIdentity *identity)
7952{
7953 static int i = 0;
7954 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
7955 core_handle = server;
7956 if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)) ||
7957 NULL == server)
7958 {
7959 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
7960 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
7961 " core id %s\n",
7962 GNUNET_i2s (identity));
7963 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
7964 " my id %s\n",
7965 GNUNET_i2s (&my_full_id));
7966 GNUNET_SCHEDULER_shutdown (); // Try gracefully
7967 if (10 < i++)
7968 GNUNET_abort(); // Try harder
7969 }
7970 return;
7971}
7972
7973
7974/**
7975 * Method called whenever a given peer connects. 4742 * Method called whenever a given peer connects.
7976 * 4743 *
7977 * @param cls closure 4744 * @param cls closure
@@ -7985,23 +4752,23 @@ core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
7985 4752
7986 DEBUG_CONN ("Peer connected\n"); 4753 DEBUG_CONN ("Peer connected\n");
7987 DEBUG_CONN (" %s\n", GNUNET_i2s (&my_full_id)); 4754 DEBUG_CONN (" %s\n", GNUNET_i2s (&my_full_id));
7988 peer_info = peer_info_get (peer); 4755 peer_info = peer_get (peer);
7989 if (myid == peer_info->id) 4756 if (myid == peer_info->id)
7990 { 4757 {
7991 DEBUG_CONN (" (self)\n"); 4758 DEBUG_CONN (" (self)\n");
7992 return; 4759 path = path_new (1);
7993 } 4760 }
7994 else 4761 else
7995 { 4762 {
7996 DEBUG_CONN (" %s\n", GNUNET_i2s (peer)); 4763 DEBUG_CONN (" %s\n", GNUNET_i2s (peer));
4764 path = path_new (2);
4765 path->peers[1] = peer_info->id;
4766 GNUNET_PEER_change_rc (peer_info->id, 1);
4767 GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO);
7997 } 4768 }
7998 path = path_new (2);
7999 path->peers[0] = myid; 4769 path->peers[0] = myid;
8000 path->peers[1] = peer_info->id;
8001 GNUNET_PEER_change_rc (myid, 1); 4770 GNUNET_PEER_change_rc (myid, 1);
8002 GNUNET_PEER_change_rc (peer_info->id, 1);
8003 peer_info_add_path (peer_info, path, GNUNET_YES); 4771 peer_info_add_path (peer_info, path, GNUNET_YES);
8004 GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO);
8005 return; 4772 return;
8006} 4773}
8007 4774
@@ -8039,7 +4806,7 @@ core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
8039 GNUNET_CORE_notify_transmit_ready_cancel(pi->core_transmit); 4806 GNUNET_CORE_notify_transmit_ready_cancel(pi->core_transmit);
8040 pi->core_transmit = NULL; 4807 pi->core_transmit = NULL;
8041 } 4808 }
8042 peer_info_remove_path (pi, pi->id, myid); 4809 peer_remove_path (pi, pi->id, myid);
8043 if (myid == pi->id) 4810 if (myid == pi->id)
8044 { 4811 {
8045 DEBUG_CONN (" (self)\n"); 4812 DEBUG_CONN (" (self)\n");
@@ -8049,6 +4816,69 @@ core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
8049} 4816}
8050 4817
8051 4818
4819/**
4820 * Install server (service) handlers and start listening to clients.
4821 */
4822static void
4823server_init (void)
4824{
4825 GNUNET_SERVER_add_handlers (server_handle, client_handlers);
4826 GNUNET_SERVER_disconnect_notify (server_handle,
4827 &handle_local_client_disconnect, NULL);
4828 nc = GNUNET_SERVER_notification_context_create (server_handle, 1);
4829
4830 clients_head = NULL;
4831 clients_tail = NULL;
4832 next_client_id = 0;
4833 GNUNET_SERVER_resume (server_handle);
4834}
4835
4836
4837/**
4838 * To be called on core init/fail.
4839 *
4840 * @param cls Closure (config)
4841 * @param server handle to the server for this service
4842 * @param identity the public identity of this peer
4843 */
4844static void
4845core_init (void *cls, struct GNUNET_CORE_Handle *server,
4846 const struct GNUNET_PeerIdentity *identity)
4847{
4848 const struct GNUNET_CONFIGURATION_Handle *c = cls;
4849 static int i = 0;
4850
4851 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
4852 GNUNET_break (core_handle == server);
4853 if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)) ||
4854 NULL == server)
4855 {
4856 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
4857 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4858 " core id %s\n",
4859 GNUNET_i2s (identity));
4860 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4861 " my id %s\n",
4862 GNUNET_i2s (&my_full_id));
4863 GNUNET_CORE_disconnect (core_handle);
4864 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
4865 NULL, /* Closure passed to MESH functions */
4866 &core_init, /* Call core_init once connected */
4867 &core_connect, /* Handle connects */
4868 &core_disconnect, /* remove peers on disconnects */
4869 NULL, /* Don't notify about all incoming messages */
4870 GNUNET_NO, /* For header only in notification */
4871 NULL, /* Don't notify about all outbound messages */
4872 GNUNET_NO, /* For header-only out notification */
4873 core_handlers); /* Register these handlers */
4874 if (10 < i++)
4875 GNUNET_abort();
4876 }
4877 server_init ();
4878 return;
4879}
4880
4881
8052/******************************************************************************/ 4882/******************************************************************************/
8053/************************ MAIN FUNCTIONS ****************************/ 4883/************************ MAIN FUNCTIONS ****************************/
8054/******************************************************************************/ 4884/******************************************************************************/
@@ -8140,11 +4970,6 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
8140 GNUNET_SCHEDULER_cancel (announce_id_task); 4970 GNUNET_SCHEDULER_cancel (announce_id_task);
8141 announce_id_task = GNUNET_SCHEDULER_NO_TASK; 4971 announce_id_task = GNUNET_SCHEDULER_NO_TASK;
8142 } 4972 }
8143 if (GNUNET_SCHEDULER_NO_TASK != announce_applications_task)
8144 {
8145 GNUNET_SCHEDULER_cancel (announce_applications_task);
8146 announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
8147 }
8148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n"); 4973 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n");
8149} 4974}
8150 4975
@@ -8162,10 +4987,8 @@ key_generation_cb (void *cls,
8162 const char *emsg) 4987 const char *emsg)
8163{ 4988{
8164 const struct GNUNET_CONFIGURATION_Handle *c = cls; 4989 const struct GNUNET_CONFIGURATION_Handle *c = cls;
8165 struct MeshPeerInfo *peer;
8166 struct MeshPeerPath *p;
8167 4990
8168 keygen = NULL; 4991 keygen = NULL;
8169 if (NULL == pk) 4992 if (NULL == pk)
8170 { 4993 {
8171 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4994 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -8193,7 +5016,6 @@ key_generation_cb (void *cls,
8193 NULL, /* Don't notify about all outbound messages */ 5016 NULL, /* Don't notify about all outbound messages */
8194 GNUNET_NO, /* For header-only out notification */ 5017 GNUNET_NO, /* For header-only out notification */
8195 core_handlers); /* Register these handlers */ 5018 core_handlers); /* Register these handlers */
8196
8197 if (core_handle == NULL) 5019 if (core_handle == NULL)
8198 { 5020 {
8199 GNUNET_break (0); 5021 GNUNET_break (0);
@@ -8204,27 +5026,8 @@ key_generation_cb (void *cls,
8204 next_tid = 0; 5026 next_tid = 0;
8205 next_local_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; 5027 next_local_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
8206 5028
8207
8208 GNUNET_SERVER_add_handlers (server_handle, client_handlers);
8209 nc = GNUNET_SERVER_notification_context_create (server_handle, 1);
8210 GNUNET_SERVER_disconnect_notify (server_handle,
8211 &handle_local_client_disconnect, NULL);
8212
8213
8214 clients = NULL;
8215 clients_tail = NULL;
8216 next_client_id = 0;
8217
8218 announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
8219 announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls); 5029 announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls);
8220 5030
8221 /* Create a peer_info for the local peer */
8222 peer = peer_info_get (&my_full_id);
8223 p = path_new (1);
8224 p->peers[0] = myid;
8225 GNUNET_PEER_change_rc (myid, 1);
8226 peer_info_add_path (peer, p, GNUNET_YES);
8227 GNUNET_SERVER_resume (server_handle);
8228 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh service running\n"); 5031 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh service running\n");
8229} 5032}
8230 5033
@@ -8242,9 +5045,9 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
8242{ 5045{
8243 char *keyfile; 5046 char *keyfile;
8244 5047
8245 cfg = c;
8246 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n"); 5048 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n");
8247 server_handle = server; 5049 server_handle = server;
5050 GNUNET_SERVER_suspend (server_handle);
8248 5051
8249 if (GNUNET_OK != 5052 if (GNUNET_OK !=
8250 GNUNET_CONFIGURATION_get_value_filename (c, "PEER", "PRIVATE_KEY", 5053 GNUNET_CONFIGURATION_get_value_filename (c, "PEER", "PRIVATE_KEY",
@@ -8271,20 +5074,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
8271 } 5074 }
8272 5075
8273 if (GNUNET_OK != 5076 if (GNUNET_OK !=
8274 GNUNET_CONFIGURATION_get_value_time (c, "MESH", "APP_ANNOUNCE_TIME",
8275 &app_announce_time))
8276 {
8277 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
8278 _
8279 ("%s service is lacking key configuration settings (%s). Exiting.\n"),
8280 "mesh", "app announce time");
8281 GNUNET_SCHEDULER_shutdown ();
8282 return;
8283 }
8284 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8285 "APP_ANNOUNCE_TIME %llu ms\n",
8286 app_announce_time.rel_value);
8287 if (GNUNET_OK !=
8288 GNUNET_CONFIGURATION_get_value_time (c, "MESH", "ID_ANNOUNCE_TIME", 5077 GNUNET_CONFIGURATION_get_value_time (c, "MESH", "ID_ANNOUNCE_TIME",
8289 &id_announce_time)) 5078 &id_announce_time))
8290 { 5079 {
@@ -8367,8 +5156,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
8367 tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); 5156 tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
8368 incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); 5157 incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
8369 peers = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); 5158 peers = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
8370 applications = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); 5159 ports = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
8371 types = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
8372 5160
8373 dht_handle = GNUNET_DHT_connect (c, 64); 5161 dht_handle = GNUNET_DHT_connect (c, 64);
8374 if (NULL == dht_handle) 5162 if (NULL == dht_handle)
@@ -8377,7 +5165,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
8377 } 5165 }
8378 stats = GNUNET_STATISTICS_create ("mesh", c); 5166 stats = GNUNET_STATISTICS_create ("mesh", c);
8379 5167
8380 GNUNET_SERVER_suspend (server_handle);
8381 /* Scheduled the task to clean up when shutdown is called */ 5168 /* Scheduled the task to clean up when shutdown is called */
8382 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, 5169 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
8383 NULL); 5170 NULL);
diff --git a/src/mesh/mesh.h b/src/mesh/mesh.h
index a5a817c48..360bfabb4 100644
--- a/src/mesh/mesh.h
+++ b/src/mesh/mesh.h
@@ -38,9 +38,6 @@ extern "C"
38 38
39#define MESH_DEBUG GNUNET_YES 39#define MESH_DEBUG GNUNET_YES
40 40
41#define INITIAL_WINDOW_SIZE 8
42#define ACK_THRESHOLD INITIAL_WINDOW_SIZE / 2
43
44#include "platform.h" 41#include "platform.h"
45#include "gnunet_common.h" 42#include "gnunet_common.h"
46#include "gnunet_util_lib.h" 43#include "gnunet_util_lib.h"
@@ -63,18 +60,8 @@ extern "C"
63 * 60 *
64 * tunnel_create GNUNET_MESH_TunnelMessage 61 * tunnel_create GNUNET_MESH_TunnelMessage
65 * tunnel_destroy GNUNET_MESH_TunnelMessage 62 * tunnel_destroy GNUNET_MESH_TunnelMessage
66 * tunnel_speed_max GNUNET_MESH_TunnelMessage
67 * tunnel_speed_min GNUNET_MESH_TunnelMessage
68 * tunnel_buffer GNUNET_MESH_TunnelMessage 63 * tunnel_buffer GNUNET_MESH_TunnelMessage
69 * 64 *
70 * peer_request_connect_add GNUNET_MESH_PeerControl
71 * peer_request_connect_del GNUNET_MESH_PeerControl
72 * peer_request_connect_by_type GNUNET_MESH_ConnectPeerByType
73 * peer_request_connect_by_string GNUNET_MESH_ConnectPeerByString
74 *
75 * peer_blacklist GNUNET_MESH_PeerControl
76 * peer_unblacklist GNUNET_MESH_PeerControl
77 *
78 * notify_transmit_ready None (queue / GNUNET_CLIENT_ntf_tmt_rdy) 65 * notify_transmit_ready None (queue / GNUNET_CLIENT_ntf_tmt_rdy)
79 * notify_transmit_ready_cancel None (clear of internal data structures) 66 * notify_transmit_ready_cancel None (clear of internal data structures)
80 * 67 *
@@ -87,8 +74,8 @@ extern "C"
87 * data ack GNUNET_MESH_LocalAck 74 * data ack GNUNET_MESH_LocalAck
88 * 75 *
89 * new incoming tunnel GNUNET_MESH_PeerControl 76 * new incoming tunnel GNUNET_MESH_PeerControl
90 * peer connects to a tunnel GNUNET_MESH_PeerControl 77 * peer connects to a tunnel FIXME
91 * peer disconnects from a tunnel GNUNET_MESH_PeerControl 78 * peer disconnects from a tunnel FIXME
92 */ 79 */
93 80
94/******************************************************************************/ 81/******************************************************************************/
@@ -122,10 +109,7 @@ struct GNUNET_MESH_ClientConnect
122 * sizeof(uint16_t) * types 109 * sizeof(uint16_t) * types
123 */ 110 */
124 struct GNUNET_MessageHeader header; 111 struct GNUNET_MessageHeader header;
125 uint16_t applications GNUNET_PACKED; 112 /* uint32_t list_ports[] */
126 uint16_t types GNUNET_PACKED;
127 /* uint32_t list_apps[applications] */
128 /* uint16_t list_types[types] */
129}; 113};
130 114
131 115
@@ -137,6 +121,7 @@ struct GNUNET_MESH_ClientConnect
137 */ 121 */
138typedef uint32_t MESH_TunnelNumber; 122typedef uint32_t MESH_TunnelNumber;
139 123
124
140/** 125/**
141 * Message for a client to create and destroy tunnels. 126 * Message for a client to create and destroy tunnels.
142 */ 127 */
@@ -144,26 +129,6 @@ struct GNUNET_MESH_TunnelMessage
144{ 129{
145 /** 130 /**
146 * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_[CREATE|DESTROY] 131 * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_[CREATE|DESTROY]
147 * GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_[MAX|MIN]
148 *
149 * Size: sizeof(struct GNUNET_MESH_TunnelMessage)
150 */
151 struct GNUNET_MessageHeader header;
152
153 /**
154 * ID of a tunnel controlled by this client.
155 */
156 MESH_TunnelNumber tunnel_id GNUNET_PACKED;
157};
158
159
160/**
161 * Message for the service to let a client know about created tunnels.
162 */
163struct GNUNET_MESH_TunnelNotification
164{
165 /**
166 * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE
167 * 132 *
168 * Size: sizeof(struct GNUNET_MESH_TunnelMessage) 133 * Size: sizeof(struct GNUNET_MESH_TunnelMessage)
169 */ 134 */
@@ -175,60 +140,26 @@ struct GNUNET_MESH_TunnelNotification
175 MESH_TunnelNumber tunnel_id GNUNET_PACKED; 140 MESH_TunnelNumber tunnel_id GNUNET_PACKED;
176 141
177 /** 142 /**
178 * Peer at the other end, if any 143 * Tunnel's peer
179 */ 144 */
180 struct GNUNET_PeerIdentity peer; 145 struct GNUNET_PeerIdentity peer;
181 146
182 /** 147 /**
183 * Tunnel options (speed, buffering) 148 * Port of the tunnel.
184 */
185 uint32_t opt;
186};
187
188/**
189 * Message for announce of regular expressions.
190 */
191struct GNUNET_MESH_RegexAnnounce
192{
193 /**
194 * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_ANNOUNCE_REGEX
195 *
196 * Size: sizeof(struct GNUNET_MESH_RegexAnnounce) + strlen (regex)
197 */
198 struct GNUNET_MessageHeader header;
199
200 /**
201 * How many characters do we want to put in an edge label.
202 */
203 uint16_t compression_characters;
204
205 /**
206 * Is this the last message for this regex? (for regex > 65k)
207 */ 149 */
208 int16_t last; 150 uint32_t port GNUNET_PACKED;
209
210 /* regex payload */
211}; 151};
212 152
213 153
214/** 154/**
215 * Message for: 155 * Message for the service to let a client know about created tunnels.
216 * - request adding and deleting peers from a tunnel
217 * - notify the client that peers have connected:
218 * -- requested
219 * -- unrequested (new incoming tunnels)
220 * - notify the client that peers have disconnected
221 */ 156 */
222struct GNUNET_MESH_PeerControl 157struct GNUNET_MESH_TunnelNotification
223{ 158{
224
225 /** 159 /**
226 * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_[ADD|DEL|[UN]BLACKLIST] 160 * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE
227 * (client to service, client created tunnel)
228 * GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_[CONNECTED|DISCONNECTED]
229 * (service to client)
230 * 161 *
231 * Size: sizeof(struct GNUNET_MESH_PeerControl) 162 * Size: sizeof(struct GNUNET_MESH_TunnelMessage)
232 */ 163 */
233 struct GNUNET_MessageHeader header; 164 struct GNUNET_MessageHeader header;
234 165
@@ -238,55 +169,19 @@ struct GNUNET_MESH_PeerControl
238 MESH_TunnelNumber tunnel_id GNUNET_PACKED; 169 MESH_TunnelNumber tunnel_id GNUNET_PACKED;
239 170
240 /** 171 /**
241 * Peer to connect/disconnect. 172 * Peer at the other end.
242 */ 173 */
243 struct GNUNET_PeerIdentity peer; 174 struct GNUNET_PeerIdentity peer;
244};
245
246
247/**
248 * Message for connecting to peers offering a service, by service number.
249 */
250struct GNUNET_MESH_ConnectPeerByType
251{
252 /**
253 * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE |
254 * GNUNET_MESSAGE_TYPE_MESH_LOCAL_DISCONNECT_PEER_BY_TYPE
255 *
256 * Size: sizeof(struct GNUNET_MESH_ConnectPeerByType)
257 */
258 struct GNUNET_MessageHeader header;
259
260 /**
261 * ID of a tunnel controlled by this client.
262 */
263 MESH_TunnelNumber tunnel_id GNUNET_PACKED;
264 175
265 /** 176 /**
266 * Type specification 177 * Port for this tunnel
267 */
268 GNUNET_MESH_ApplicationType type GNUNET_PACKED;
269};
270
271
272/**
273 * Message for connecting to peers offering a service, by service string.
274 */
275struct GNUNET_MESH_ConnectPeerByString
276{
277 /**
278 * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_STRING
279 *
280 * Size: sizeof(struct GNUNET_MESH_ConnectPeerByString) + strlen (string)
281 */ 178 */
282 struct GNUNET_MessageHeader header; 179 uint32_t port GNUNET_PACKED;
283 180
284 /** 181 /**
285 * ID of a tunnel controlled by this client. 182 * Tunnel options (speed, buffering)
286 */ 183 */
287 MESH_TunnelNumber tunnel_id GNUNET_PACKED; 184 uint32_t opt GNUNET_PACKED;
288
289 /* String describing the service */
290}; 185};
291 186
292 187
@@ -309,7 +204,7 @@ struct GNUNET_MESH_LocalAck
309 /** 204 /**
310 * ID of the last packet allowed. 205 * ID of the last packet allowed.
311 */ 206 */
312 uint32_t max_pid GNUNET_PACKED; 207 uint32_t ack GNUNET_PACKED;
313}; 208};
314 209
315 210
@@ -329,11 +224,6 @@ struct GNUNET_MESH_LocalMonitor
329 MESH_TunnelNumber tunnel_id GNUNET_PACKED; 224 MESH_TunnelNumber tunnel_id GNUNET_PACKED;
330 225
331 /** 226 /**
332 * Number of peers in the tunnel.
333 */
334 uint32_t npeers GNUNET_PACKED;
335
336 /**
337 * Alignment. 227 * Alignment.
338 */ 228 */
339 uint32_t reserved GNUNET_PACKED; 229 uint32_t reserved GNUNET_PACKED;
@@ -343,7 +233,10 @@ struct GNUNET_MESH_LocalMonitor
343 */ 233 */
344 struct GNUNET_PeerIdentity owner; 234 struct GNUNET_PeerIdentity owner;
345 235
346 /* struct GNUNET_PeerIdentity peers[npeers] */ 236 /**
237 * ID of the destination of the tunnel (can be local peer).
238 */
239 struct GNUNET_PeerIdentity destination;
347}; 240};
348 241
349 242
@@ -354,44 +247,34 @@ GNUNET_NETWORK_STRUCT_END
354/******************************************************************************/ 247/******************************************************************************/
355 248
356/** 249/**
357 * All the states a peer participating in a tunnel can be in. 250 * All the states a tunnel can be in.
358 */ 251 */
359enum MeshPeerState 252enum MeshTunnelState
360{ 253{
361 /** 254 /**
362 * Uninitialized status, should never appear in operation. 255 * Uninitialized status, should never appear in operation.
363 */ 256 */
364 MESH_PEER_INVALID, 257 MESH_TUNNEL_NEW,
365
366 /**
367 * Peer is the root and owner of the tree
368 */
369 MESH_PEER_ROOT,
370
371 /**
372 * Peer only retransmits traffic, is not a final destination
373 */
374 MESH_PEER_RELAY,
375 258
376 /** 259 /**
377 * Path to the peer not known yet 260 * Path to the peer not known yet
378 */ 261 */
379 MESH_PEER_SEARCHING, 262 MESH_TUNNEL_SEARCHING,
380 263
381 /** 264 /**
382 * Request sent, not yet answered. 265 * Request sent, not yet answered.
383 */ 266 */
384 MESH_PEER_WAITING, 267 MESH_TUNNEL_WAITING,
385 268
386 /** 269 /**
387 * Peer connected and ready to accept data 270 * Peer connected and ready to accept data
388 */ 271 */
389 MESH_PEER_READY, 272 MESH_TUNNEL_READY,
390 273
391 /** 274 /**
392 * Peer connected previosly but not responding 275 * Peer connected previosly but not responding
393 */ 276 */
394 MESH_PEER_RECONNECTING 277 MESH_TUNNEL_RECONNECTING
395}; 278};
396 279
397 280
@@ -432,6 +315,18 @@ GMC_min_pid (uint32_t a, uint32_t b);
432 315
433 316
434/** 317/**
318 * Expand a 32 bit value (message type) into a hash for a MultiHashMap (fast).
319 * WARNING: do not use for anything other than MultiHashMap!
320 * does not alter anything other than bits used by idx_of !
321 *
322 * @param i 32 bit integer value.
323 * @param h Hash code to fill.
324 */
325void
326GMC_hash32 (uint32_t i, struct GNUNET_HashCode *h);
327
328
329/**
435 * Convert a message type into a string to help debug 330 * Convert a message type into a string to help debug
436 * Generated with: 331 * Generated with:
437 * FIND: "#define ([^ ]+)[ ]*([0-9]+)" 332 * FIND: "#define ([^ ]+)[ ]*([0-9]+)"
diff --git a/src/mesh/mesh2.h b/src/mesh/mesh2.h
deleted file mode 100644
index 360bfabb4..000000000
--- a/src/mesh/mesh2.h
+++ /dev/null
@@ -1,349 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @author Bartlomiej Polot
23 * @file mesh/mesh.h
24 */
25
26#ifndef MESH_H_
27#define MESH_H_
28
29#ifdef __cplusplus
30extern "C"
31{
32#if 0 /* keep Emacsens' auto-indent happy */
33}
34#endif
35#endif
36
37#include <stdint.h>
38
39#define MESH_DEBUG GNUNET_YES
40
41#include "platform.h"
42#include "gnunet_common.h"
43#include "gnunet_util_lib.h"
44#include "gnunet_peer_lib.h"
45#include "gnunet_core_service.h"
46#include "gnunet_protocols.h"
47#include <gnunet_mesh_service.h>
48
49/******************************************************************************/
50/******************** MESH LOCAL MESSAGES *************************/
51/******************************************************************************/
52/* Any API call should be documented in the folowing table under API CALL.
53 * Also, any message type should be documented in the following table, with the
54 * associated event.
55 *
56 * API CALL (GNUNET_MESH_*) MESSAGE USED
57 * ------------------------ ------------
58 * connect GNUNET_MESH_ClientConnect
59 * disconnect None (network level disconnect)
60 *
61 * tunnel_create GNUNET_MESH_TunnelMessage
62 * tunnel_destroy GNUNET_MESH_TunnelMessage
63 * tunnel_buffer GNUNET_MESH_TunnelMessage
64 *
65 * notify_transmit_ready None (queue / GNUNET_CLIENT_ntf_tmt_rdy)
66 * notify_transmit_ready_cancel None (clear of internal data structures)
67 *
68 *
69 * EVENT MESSAGE USED
70 * ----- ------------
71 * data GNUNET_MESH_Unicast OR
72 * GNUNET_MESH_Multicast OR
73 * GNUNET_MESH_ToOrigin
74 * data ack GNUNET_MESH_LocalAck
75 *
76 * new incoming tunnel GNUNET_MESH_PeerControl
77 * peer connects to a tunnel FIXME
78 * peer disconnects from a tunnel FIXME
79 */
80
81/******************************************************************************/
82/************************** CONSTANTS ******************************/
83/******************************************************************************/
84
85#define GNUNET_MESH_LOCAL_TUNNEL_ID_CLI 0x80000000
86#define GNUNET_MESH_LOCAL_TUNNEL_ID_SERV 0xB0000000
87
88#define HIGH_PID 0xFFFF0000
89#define LOW_PID 0x0000FFFF
90
91#define PID_OVERFLOW(pid, max) (pid > HIGH_PID && max < LOW_PID)
92
93/******************************************************************************/
94/************************** MESSAGES ******************************/
95/******************************************************************************/
96
97GNUNET_NETWORK_STRUCT_BEGIN
98
99/**
100 * Message for a client to register to the service
101 */
102struct GNUNET_MESH_ClientConnect
103{
104 /**
105 * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT
106 *
107 * Size: sizeof(struct GNUNET_MESH_ClientConnect) +
108 * sizeof(MESH_ApplicationType) * applications +
109 * sizeof(uint16_t) * types
110 */
111 struct GNUNET_MessageHeader header;
112 /* uint32_t list_ports[] */
113};
114
115
116/**
117 * Type for tunnel numbering.
118 * - Local tunnel numbers given by the service (incoming) are >= 0xB0000000
119 * - Local tunnel numbers given by the client (created) are >= 0x80000000
120 * - Global tunnel numbers are < 0x80000000
121 */
122typedef uint32_t MESH_TunnelNumber;
123
124
125/**
126 * Message for a client to create and destroy tunnels.
127 */
128struct GNUNET_MESH_TunnelMessage
129{
130 /**
131 * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_[CREATE|DESTROY]
132 *
133 * Size: sizeof(struct GNUNET_MESH_TunnelMessage)
134 */
135 struct GNUNET_MessageHeader header;
136
137 /**
138 * ID of a tunnel controlled by this client.
139 */
140 MESH_TunnelNumber tunnel_id GNUNET_PACKED;
141
142 /**
143 * Tunnel's peer
144 */
145 struct GNUNET_PeerIdentity peer;
146
147 /**
148 * Port of the tunnel.
149 */
150 uint32_t port GNUNET_PACKED;
151};
152
153
154/**
155 * Message for the service to let a client know about created tunnels.
156 */
157struct GNUNET_MESH_TunnelNotification
158{
159 /**
160 * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE
161 *
162 * Size: sizeof(struct GNUNET_MESH_TunnelMessage)
163 */
164 struct GNUNET_MessageHeader header;
165
166 /**
167 * ID of a tunnel controlled by this client.
168 */
169 MESH_TunnelNumber tunnel_id GNUNET_PACKED;
170
171 /**
172 * Peer at the other end.
173 */
174 struct GNUNET_PeerIdentity peer;
175
176 /**
177 * Port for this tunnel
178 */
179 uint32_t port GNUNET_PACKED;
180
181 /**
182 * Tunnel options (speed, buffering)
183 */
184 uint32_t opt GNUNET_PACKED;
185};
186
187
188/**
189 * Message to allow the client send more data to the service
190 * (always service -> client).
191 */
192struct GNUNET_MESH_LocalAck
193{
194 /**
195 * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK
196 */
197 struct GNUNET_MessageHeader header;
198
199 /**
200 * ID of the tunnel allowed to send more data.
201 */
202 MESH_TunnelNumber tunnel_id GNUNET_PACKED;
203
204 /**
205 * ID of the last packet allowed.
206 */
207 uint32_t ack GNUNET_PACKED;
208};
209
210
211/**
212 * Message to inform the client about tunnels in the service.
213 */
214struct GNUNET_MESH_LocalMonitor
215{
216 /**
217 * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR[_TUNNEL]
218 */
219 struct GNUNET_MessageHeader header;
220
221 /**
222 * ID of the tunnel allowed to send more data.
223 */
224 MESH_TunnelNumber tunnel_id GNUNET_PACKED;
225
226 /**
227 * Alignment.
228 */
229 uint32_t reserved GNUNET_PACKED;
230
231 /**
232 * ID of the owner of the tunnel (can be local peer).
233 */
234 struct GNUNET_PeerIdentity owner;
235
236 /**
237 * ID of the destination of the tunnel (can be local peer).
238 */
239 struct GNUNET_PeerIdentity destination;
240};
241
242
243GNUNET_NETWORK_STRUCT_END
244
245/******************************************************************************/
246/************************ ENUMERATIONS ****************************/
247/******************************************************************************/
248
249/**
250 * All the states a tunnel can be in.
251 */
252enum MeshTunnelState
253{
254 /**
255 * Uninitialized status, should never appear in operation.
256 */
257 MESH_TUNNEL_NEW,
258
259 /**
260 * Path to the peer not known yet
261 */
262 MESH_TUNNEL_SEARCHING,
263
264 /**
265 * Request sent, not yet answered.
266 */
267 MESH_TUNNEL_WAITING,
268
269 /**
270 * Peer connected and ready to accept data
271 */
272 MESH_TUNNEL_READY,
273
274 /**
275 * Peer connected previosly but not responding
276 */
277 MESH_TUNNEL_RECONNECTING
278};
279
280
281/**
282 * Check if one pid is bigger than other, accounting for overflow.
283 *
284 * @param bigger Argument that should be bigger.
285 * @param smaller Argument that should be smaller.
286 *
287 * @return True if bigger (arg1) has a higher value than smaller (arg 2).
288 */
289int
290GMC_is_pid_bigger (uint32_t bigger, uint32_t smaller);
291
292
293/**
294 * Get the higher ACK value out of two values, taking in account overflow.
295 *
296 * @param a First ACK value.
297 * @param b Second ACK value.
298 *
299 * @return Highest ACK value from the two.
300 */
301uint32_t
302GMC_max_pid (uint32_t a, uint32_t b);
303
304
305/**
306 * Get the lower ACK value out of two values, taking in account overflow.
307 *
308 * @param a First ACK value.
309 * @param b Second ACK value.
310 *
311 * @return Lowest ACK value from the two.
312 */
313uint32_t
314GMC_min_pid (uint32_t a, uint32_t b);
315
316
317/**
318 * Expand a 32 bit value (message type) into a hash for a MultiHashMap (fast).
319 * WARNING: do not use for anything other than MultiHashMap!
320 * does not alter anything other than bits used by idx_of !
321 *
322 * @param i 32 bit integer value.
323 * @param h Hash code to fill.
324 */
325void
326GMC_hash32 (uint32_t i, struct GNUNET_HashCode *h);
327
328
329/**
330 * Convert a message type into a string to help debug
331 * Generated with:
332 * FIND: "#define ([^ ]+)[ ]*([0-9]+)"
333 * REPLACE: " case \2: return "\1"; break;"
334 *
335 * @param m Message type.
336 *
337 * @return Human readable string description.
338 */
339const char *
340GNUNET_MESH_DEBUG_M2S (uint16_t m);
341
342#if 0 /* keep Emacsens' auto-indent happy */
343{
344#endif
345#ifdef __cplusplus
346}
347#endif
348
349#endif
diff --git a/src/mesh/mesh2_api.c b/src/mesh/mesh2_api.c
deleted file mode 100644
index ef940f7e4..000000000
--- a/src/mesh/mesh2_api.c
+++ /dev/null
@@ -1,1787 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
4 GNUnet is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published
6 by the Free Software Foundation; either version 3, or (at your
7 option) any later version.
8 GNUnet is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with GNUnet; see the file COPYING. If not, write to the
14 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15 Boston, MA 02111-1307, USA.
16*/
17
18/**
19 * @file mesh/mesh2_api.c
20 * @brief mesh2 api: client implementation of new mesh service
21 * @author Bartlomiej Polot
22 *
23 * STRUCTURE:
24 * - DATA STRUCTURES
25 * - DECLARATIONS
26 * - AUXILIARY FUNCTIONS
27 * - RECEIVE HANDLERS
28 * - SEND FUNCTIONS
29 * - API CALL DEFINITIONS
30 *
31 * TODO: add regex to reconnect
32 */
33#include "platform.h"
34#include "gnunet_common.h"
35#include "gnunet_client_lib.h"
36#include "gnunet_util_lib.h"
37#include "gnunet_peer_lib.h"
38#include "gnunet_mesh2_service.h"
39#include "mesh2.h"
40#include "mesh2_protocol.h"
41
42#define LOG(kind,...) GNUNET_log_from (kind, "mesh2-api",__VA_ARGS__)
43#define DEBUG_ACK GNUNET_YES
44
45/******************************************************************************/
46/************************ DATA STRUCTURES ****************************/
47/******************************************************************************/
48
49/**
50 * Transmission queue to the service
51 */
52struct GNUNET_MESH_TransmitHandle
53{
54
55 /**
56 * Double Linked list
57 */
58 struct GNUNET_MESH_TransmitHandle *next;
59
60 /**
61 * Double Linked list
62 */
63 struct GNUNET_MESH_TransmitHandle *prev;
64
65 /**
66 * Tunnel this message is sent on / for (may be NULL for control messages).
67 */
68 struct GNUNET_MESH_Tunnel *tunnel;
69
70 /**
71 * Callback to obtain the message to transmit, or NULL if we
72 * got the message in 'data'. Notice that messages built
73 * by 'notify' need to be encapsulated with information about
74 * the 'target'.
75 */
76 GNUNET_CONNECTION_TransmitReadyNotify notify;
77
78 /**
79 * Closure for 'notify'
80 */
81 void *notify_cls;
82
83 /**
84 * How long is this message valid. Once the timeout has been
85 * reached, the message must no longer be sent. If this
86 * is a message with a 'notify' callback set, the 'notify'
87 * function should be called with 'buf' NULL and size 0.
88 */
89 struct GNUNET_TIME_Absolute timeout;
90
91 /**
92 * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER.
93 */
94 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
95
96 /**
97 * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL.
98 */
99 size_t size;
100};
101
102
103/**
104 * Opaque handle to the service.
105 */
106struct GNUNET_MESH_Handle
107{
108
109 /**
110 * Handle to the server connection, to send messages later
111 */
112 struct GNUNET_CLIENT_Connection *client;
113
114 /**
115 * Set of handlers used for processing incoming messages in the tunnels
116 */
117 const struct GNUNET_MESH_MessageHandler *message_handlers;
118
119 /**
120 * Number of handlers in the handlers array.
121 */
122 unsigned int n_handlers;
123
124 /**
125 * Ports open.
126 */
127 const uint32_t *ports;
128
129 /**
130 * Number of ports.
131 */
132 unsigned int n_ports;
133
134 /**
135 * Double linked list of the tunnels this client is connected to, head.
136 */
137 struct GNUNET_MESH_Tunnel *tunnels_head;
138
139 /**
140 * Double linked list of the tunnels this client is connected to, tail.
141 */
142 struct GNUNET_MESH_Tunnel *tunnels_tail;
143
144 /**
145 * Callback for inbound tunnel creation
146 */
147 GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
148
149 /**
150 * Callback for inbound tunnel disconnection
151 */
152 GNUNET_MESH_TunnelEndHandler *cleaner;
153
154 /**
155 * Handle to cancel pending transmissions in case of disconnection
156 */
157 struct GNUNET_CLIENT_TransmitHandle *th;
158
159 /**
160 * Closure for all the handlers given by the client
161 */
162 void *cls;
163
164 /**
165 * Messages to send to the service, head.
166 */
167 struct GNUNET_MESH_TransmitHandle *th_head;
168
169 /**
170 * Messages to send to the service, tail.
171 */
172 struct GNUNET_MESH_TransmitHandle *th_tail;
173
174 /**
175 * tid of the next tunnel to create (to avoid reusing IDs often)
176 */
177 MESH_TunnelNumber next_tid;
178
179 /**
180 * Have we started the task to receive messages from the service
181 * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message.
182 */
183 int in_receive;
184
185 /**
186 * Configuration given by the client, in case of reconnection
187 */
188 const struct GNUNET_CONFIGURATION_Handle *cfg;
189
190 /**
191 * Time to the next reconnect in case one reconnect fails
192 */
193 struct GNUNET_TIME_Relative reconnect_time;
194
195 /**
196 * Task for trying to reconnect.
197 */
198 GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
199
200 /**
201 * Monitor callback
202 */
203 GNUNET_MESH_TunnelsCB tunnels_cb;
204
205 /**
206 * Monitor callback closure.
207 */
208 void *tunnels_cls;
209
210 /**
211 * Tunnel callback.
212 */
213 GNUNET_MESH_TunnelCB tunnel_cb;
214
215 /**
216 * Tunnel callback closure.
217 */
218 void *tunnel_cls;
219
220#if DEBUG_ACK
221 unsigned int acks_sent;
222 unsigned int acks_recv;
223#endif
224};
225
226
227/**
228 * Description of a peer
229 */
230struct GNUNET_MESH_Peer
231{
232 /**
233 * ID of the peer in short form
234 */
235 GNUNET_PEER_Id id;
236
237 /**
238 * Tunnel this peer belongs to
239 */
240 struct GNUNET_MESH_Tunnel *t;
241
242 /**
243 * Flag indicating whether service has informed about its connection
244 */
245 int connected;
246
247};
248
249
250/**
251 * Opaque handle to a tunnel.
252 */
253struct GNUNET_MESH_Tunnel
254{
255
256 /**
257 * DLL next
258 */
259 struct GNUNET_MESH_Tunnel *next;
260
261 /**
262 * DLL prev
263 */
264 struct GNUNET_MESH_Tunnel *prev;
265
266 /**
267 * Handle to the mesh this tunnel belongs to
268 */
269 struct GNUNET_MESH_Handle *mesh;
270
271 /**
272 * Local ID of the tunnel
273 */
274 MESH_TunnelNumber tid;
275
276 /**
277 * Port number.
278 */
279 uint32_t port;
280
281 /**
282 * Other end of the tunnel.
283 */
284 GNUNET_PEER_Id peer;
285
286 /**
287 * Any data the caller wants to put in here
288 */
289 void *ctx;
290
291 /**
292 * Size of packet queued in this tunnel
293 */
294 unsigned int packet_size;
295
296 /**
297 * Is the tunnel allowed to buffer?
298 */
299 int buffering;
300
301 /**
302 * Maximum allowed PID to send (last ACK recevied).
303 */
304 uint32_t last_ack_recv;
305
306 /**
307 * Last PID received from the service.
308 */
309 uint32_t last_pid_recv;
310
311 /**
312 * Last packet ID sent to the service.
313 */
314 uint32_t last_pid_sent;
315
316 /**
317 * Last ACK value sent to the service: how much are we willing to accept?
318 */
319 uint32_t last_ack_sent;
320};
321
322
323/**
324 * Implementation state for mesh's message queue.
325 */
326struct MeshMQState
327{
328 /**
329 * The current transmit handle, or NULL
330 * if no transmit is active.
331 */
332 struct GNUNET_MESH_TransmitHandle *th;
333
334 /**
335 * Tunnel to send the data over.
336 */
337 struct GNUNET_MESH_Tunnel *tunnel;
338};
339
340
341/******************************************************************************/
342/*********************** DECLARATIONS *************************/
343/******************************************************************************/
344
345/**
346 * Function called to send a message to the service.
347 * "buf" will be NULL and "size" zero if the socket was closed for writing in
348 * the meantime.
349 *
350 * @param cls closure, the mesh handle
351 * @param size number of bytes available in buf
352 * @param buf where the callee should write the connect message
353 * @return number of bytes written to buf
354 */
355static size_t
356send_callback (void *cls, size_t size, void *buf);
357
358
359/******************************************************************************/
360/*********************** AUXILIARY FUNCTIONS *************************/
361/******************************************************************************/
362
363/**
364 * Check if transmission is a payload packet.
365 *
366 * @param th Transmission handle.
367 *
368 * @return GNUNET_YES if it is a payload packet,
369 * GNUNET_NO if it is a mesh management packet.
370 */
371static int
372th_is_payload (struct GNUNET_MESH_TransmitHandle *th)
373{
374 return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO;
375}
376
377
378/**
379 * Check whether there is any message ready in the queue and find the size.
380 *
381 * @param h Mesh handle.
382 *
383 * @return The size of the first ready message in the queue,
384 * 0 if there is none.
385 */
386static size_t
387message_ready_size (struct GNUNET_MESH_Handle *h)
388{
389 struct GNUNET_MESH_TransmitHandle *th;
390 struct GNUNET_MESH_Tunnel *t;
391
392 for (th = h->th_head; NULL != th; th = th->next)
393 {
394 t = th->tunnel;
395 if (GNUNET_NO == th_is_payload (th))
396 {
397 LOG (GNUNET_ERROR_TYPE_DEBUG, "# message internal\n");
398 return th->size;
399 }
400 if (GNUNET_YES == GMC_is_pid_bigger(t->last_ack_recv, t->last_pid_sent))
401 {
402 LOG (GNUNET_ERROR_TYPE_DEBUG, "# message payload ok (%u =< %u)\n",
403 t->last_pid_sent + 1, t->last_ack_recv);
404 return th->size;
405 }
406 }
407 return 0;
408}
409
410
411/**
412 * Get the tunnel handler for the tunnel specified by id from the given handle
413 * @param h Mesh handle
414 * @param tid ID of the wanted tunnel
415 * @return handle to the required tunnel or NULL if not found
416 */
417static struct GNUNET_MESH_Tunnel *
418retrieve_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
419{
420 struct GNUNET_MESH_Tunnel *t;
421
422 t = h->tunnels_head;
423 while (t != NULL)
424 {
425 if (t->tid == tid)
426 return t;
427 t = t->next;
428 }
429 return NULL;
430}
431
432
433/**
434 * Create a new tunnel and insert it in the tunnel list of the mesh handle
435 * @param h Mesh handle
436 * @param tid desired tid of the tunnel, 0 to assign one automatically
437 * @return handle to the created tunnel
438 */
439static struct GNUNET_MESH_Tunnel *
440create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
441{
442 struct GNUNET_MESH_Tunnel *t;
443
444 t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel));
445 GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t);
446 t->mesh = h;
447 if (0 == tid)
448 {
449 t->tid = h->next_tid;
450 while (NULL != retrieve_tunnel (h, h->next_tid))
451 {
452 h->next_tid++;
453 h->next_tid &= ~GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
454 h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
455 }
456 }
457 else
458 {
459 t->tid = tid;
460 }
461 t->last_ack_recv = (uint32_t) -1;
462 t->last_pid_recv = (uint32_t) -1;
463 t->last_ack_sent = (uint32_t) -1;
464 t->last_pid_sent = (uint32_t) -1;
465 t->buffering = GNUNET_YES;
466 return t;
467}
468
469
470/**
471 * Destroy the specified tunnel.
472 * - Destroys all peers, calling the disconnect callback on each if needed
473 * - Cancels all outgoing traffic for that tunnel, calling respective notifys
474 * - Calls cleaner if tunnel was inbound
475 * - Frees all memory used
476 *
477 * @param t Pointer to the tunnel.
478 * @param call_cleaner Whether to call the cleaner handler.
479 *
480 * @return Handle to the required tunnel or NULL if not found.
481 */
482static void
483destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner)
484{
485 struct GNUNET_MESH_Handle *h;
486 struct GNUNET_MESH_TransmitHandle *th;
487 struct GNUNET_MESH_TransmitHandle *next;
488
489 LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid);
490
491 if (NULL == t)
492 {
493 GNUNET_break (0);
494 return;
495 }
496 h = t->mesh;
497
498 GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t);
499
500 /* signal tunnel destruction */
501 if ( (NULL != h->cleaner) && (0 != t->peer) && (GNUNET_YES == call_cleaner) )
502 h->cleaner (h->cls, t, t->ctx);
503
504 /* check that clients did not leave messages behind in the queue */
505 for (th = h->th_head; NULL != th; th = next)
506 {
507 next = th->next;
508 if (th->tunnel != t)
509 continue;
510 /* Clients should have aborted their requests already.
511 * Management traffic should be ok, as clients can't cancel that */
512 GNUNET_break (GNUNET_NO == th_is_payload(th));
513 GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
514
515 /* clean up request */
516 if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
517 GNUNET_SCHEDULER_cancel (th->timeout_task);
518 GNUNET_free (th);
519 }
520
521 /* if there are no more pending requests with mesh service, cancel active request */
522 /* Note: this should be unnecessary... */
523 if ((0 == message_ready_size (h)) && (NULL != h->th))
524 {
525 GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
526 h->th = NULL;
527 }
528
529 if (0 != t->peer)
530 GNUNET_PEER_change_rc (t->peer, -1);
531 GNUNET_free (t);
532 return;
533}
534
535
536/**
537 * Notify client that the transmission has timed out
538 *
539 * @param cls closure
540 * @param tc task context
541 */
542static void
543timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
544{
545 struct GNUNET_MESH_TransmitHandle *th = cls;
546 struct GNUNET_MESH_Handle *mesh;
547
548 mesh = th->tunnel->mesh;
549 GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
550 th->tunnel->packet_size = 0;
551 if (GNUNET_YES == th_is_payload (th))
552 th->notify (th->notify_cls, 0, NULL);
553 GNUNET_free (th);
554 if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
555 {
556 /* nothing ready to transmit, no point in asking for transmission */
557 GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
558 mesh->th = NULL;
559 }
560}
561
562
563/**
564 * Add a transmit handle to the transmission queue and set the
565 * timeout if needed.
566 *
567 * @param h mesh handle with the queue head and tail
568 * @param th handle to the packet to be transmitted
569 */
570static void
571add_to_queue (struct GNUNET_MESH_Handle *h,
572 struct GNUNET_MESH_TransmitHandle *th)
573{
574 GNUNET_CONTAINER_DLL_insert_tail (h->th_head, h->th_tail, th);
575 if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value == th->timeout.abs_value)
576 return;
577 th->timeout_task =
578 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
579 (th->timeout), &timeout_transmission, th);
580}
581
582
583/**
584 * Auxiliary function to send an already constructed packet to the service.
585 * Takes care of creating a new queue element, copying the message and
586 * calling the tmt_rdy function if necessary.
587 *
588 * @param h mesh handle
589 * @param msg message to transmit
590 * @param tunnel tunnel this send is related to (NULL if N/A)
591 */
592static void
593send_packet (struct GNUNET_MESH_Handle *h,
594 const struct GNUNET_MessageHeader *msg,
595 struct GNUNET_MESH_Tunnel *tunnel);
596
597
598/**
599 * Send an ack on the tunnel to confirm the processing of a message.
600 *
601 * @param h Mesh handle.
602 * @param t Tunnel on which to send the ACK.
603 */
604static void
605send_ack (struct GNUNET_MESH_Tunnel *t)
606{
607 struct GNUNET_MESH_LocalAck msg;
608
609 t->last_ack_sent = t->last_pid_recv + 1;
610 LOG (GNUNET_ERROR_TYPE_DEBUG,
611 "Sending ACK on tunnel %X: %u\n",
612 t->tid, t->last_ack_sent);
613 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
614 msg.header.size = htons (sizeof (msg));
615 msg.tunnel_id = htonl (t->tid);
616 msg.ack = htonl (t->last_ack_sent);
617
618#if DEBUG_ACK
619 t->mesh->acks_sent++;
620#endif
621
622 send_packet (t->mesh, &msg.header, t);
623 return;
624}
625
626
627
628/**
629 * Reconnect callback: tries to reconnect again after a failer previous
630 * reconnecttion
631 * @param cls closure (mesh handle)
632 * @param tc task context
633 */
634static void
635reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
636
637
638/**
639 * Send a connect packet to the service with the applications and types
640 * requested by the user.
641 *
642 * @param h The mesh handle.
643 *
644 */
645static void
646send_connect (struct GNUNET_MESH_Handle *h)
647{
648 size_t size;
649
650 size = sizeof (struct GNUNET_MESH_ClientConnect);
651 size += h->n_ports * sizeof (uint32_t);
652 {
653 char buf[size] GNUNET_ALIGN;
654 struct GNUNET_MESH_ClientConnect *msg;
655 uint32_t *ports;
656 uint16_t i;
657
658 /* build connection packet */
659 msg = (struct GNUNET_MESH_ClientConnect *) buf;
660 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT);
661 msg->header.size = htons (size);
662 ports = (uint32_t *) &msg[1];
663 for (i = 0; i < h->n_ports; i++)
664 {
665 ports[i] = htonl (h->ports[i]);
666 LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n",
667 h->ports[i]);
668 }
669 LOG (GNUNET_ERROR_TYPE_DEBUG,
670 "Sending %lu bytes long message with %u ports\n",
671 ntohs (msg->header.size), h->n_ports);
672 send_packet (h, &msg->header, NULL);
673 }
674}
675
676
677/**
678 * Reconnect to the service, retransmit all infomation to try to restore the
679 * original state.
680 *
681 * @param h handle to the mesh
682 *
683 * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
684 */
685static int
686do_reconnect (struct GNUNET_MESH_Handle *h)
687{
688 struct GNUNET_MESH_Tunnel *t;
689
690 LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
691 LOG (GNUNET_ERROR_TYPE_DEBUG, "******* RECONNECT *******\n");
692 LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
693 LOG (GNUNET_ERROR_TYPE_DEBUG, "******** on %p *******\n", h);
694 LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
695
696 /* disconnect */
697 if (NULL != h->th)
698 {
699 GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
700 h->th = NULL;
701 }
702 if (NULL != h->client)
703 {
704 GNUNET_CLIENT_disconnect (h->client);
705 }
706
707 /* connect again */
708 h->client = GNUNET_CLIENT_connect ("mesh", h->cfg);
709 if (h->client == NULL)
710 {
711 h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
712 &reconnect_cbk, h);
713 h->reconnect_time =
714 GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
715 GNUNET_TIME_relative_multiply
716 (h->reconnect_time, 2));
717 LOG (GNUNET_ERROR_TYPE_DEBUG,
718 "Next retry in %s\n",
719 GNUNET_STRINGS_relative_time_to_string (h->reconnect_time,
720 GNUNET_NO));
721 GNUNET_break (0);
722 return GNUNET_NO;
723 }
724 else
725 {
726 h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
727 }
728 send_connect (h);
729 /* Rebuild all tunnels */
730 for (t = h->tunnels_head; NULL != t; t = t->next)
731 {
732 struct GNUNET_MESH_TunnelMessage tmsg;
733
734 if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
735 {
736 /* Tunnel was created by service (incoming tunnel) */
737 /* TODO: Notify service of missing tunnel, to request
738 * creator to recreate path (find a path to him via DHT?)
739 */
740 continue;
741 }
742 t->last_ack_sent = (uint32_t) -1;
743 t->last_pid_sent = (uint32_t) -1;
744 t->last_ack_recv = (uint32_t) -1;
745 t->last_pid_recv = (uint32_t) -1;
746 tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
747 tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
748 tmsg.tunnel_id = htonl (t->tid);
749 GNUNET_PEER_resolve (t->peer, &tmsg.peer);
750 send_packet (h, &tmsg.header, t);
751
752 if (GNUNET_NO == t->buffering)
753 GNUNET_MESH_tunnel_buffer (t, GNUNET_NO);
754 }
755 return GNUNET_YES;
756}
757
758/**
759 * Reconnect callback: tries to reconnect again after a failer previous
760 * reconnecttion
761 * @param cls closure (mesh handle)
762 * @param tc task context
763 */
764static void
765reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
766{
767 struct GNUNET_MESH_Handle *h = cls;
768
769 h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
770 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
771 return;
772 do_reconnect (h);
773}
774
775
776/**
777 * Reconnect to the service, retransmit all infomation to try to restore the
778 * original state.
779 *
780 * @param h handle to the mesh
781 *
782 * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
783 */
784static void
785reconnect (struct GNUNET_MESH_Handle *h)
786{
787 LOG (GNUNET_ERROR_TYPE_DEBUG, "Requested RECONNECT\n");
788 h->in_receive = GNUNET_NO;
789 if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task)
790 h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
791 &reconnect_cbk, h);
792}
793
794
795/******************************************************************************/
796/*********************** RECEIVE HANDLERS ****************************/
797/******************************************************************************/
798
799/**
800 * Process the new tunnel notification and add it to the tunnels in the handle
801 *
802 * @param h The mesh handle
803 * @param msg A message with the details of the new incoming tunnel
804 */
805static void
806process_tunnel_created (struct GNUNET_MESH_Handle *h,
807 const struct GNUNET_MESH_TunnelNotification *msg)
808{
809 struct GNUNET_MESH_Tunnel *t;
810 MESH_TunnelNumber tid;
811
812 tid = ntohl (msg->tunnel_id);
813 LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming tunnel %X\n", tid);
814 if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
815 {
816 GNUNET_break (0);
817 return;
818 }
819 if (NULL != h->new_tunnel)
820 {
821 t = create_tunnel (h, tid);
822 t->last_ack_sent = 0;
823 t->peer = GNUNET_PEER_intern (&msg->peer);
824 t->mesh = h;
825 t->tid = tid;
826 t->port = ntohl (msg->port);
827 if (0 != (msg->opt & MESH_TUNNEL_OPT_NOBUFFER))
828 t->buffering = GNUNET_NO;
829 else
830 t->buffering = GNUNET_YES;
831 LOG (GNUNET_ERROR_TYPE_DEBUG, " created tunnel %p\n", t);
832 t->ctx = h->new_tunnel (h->cls, t, &msg->peer, t->port);
833 LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n");
834 }
835 else
836 {
837 struct GNUNET_MESH_TunnelMessage d_msg;
838
839 LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming tunnels\n");
840
841 d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
842 d_msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
843 d_msg.tunnel_id = msg->tunnel_id;
844
845 send_packet (h, &d_msg.header, NULL);
846 }
847 return;
848}
849
850
851/**
852 * Process the tunnel destroy notification and free associated resources
853 *
854 * @param h The mesh handle
855 * @param msg A message with the details of the tunnel being destroyed
856 */
857static void
858process_tunnel_destroy (struct GNUNET_MESH_Handle *h,
859 const struct GNUNET_MESH_TunnelMessage *msg)
860{
861 struct GNUNET_MESH_Tunnel *t;
862 MESH_TunnelNumber tid;
863
864 tid = ntohl (msg->tunnel_id);
865 t = retrieve_tunnel (h, tid);
866
867 if (NULL == t)
868 {
869 return;
870 }
871 LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid);
872 destroy_tunnel (t, GNUNET_YES);
873 return;
874}
875
876
877/**
878 * Process the incoming data packets, call appropriate handlers.
879 *
880 * @param h The mesh handle
881 * @param message A message encapsulating the data
882 */
883static void
884process_incoming_data (struct GNUNET_MESH_Handle *h,
885 const struct GNUNET_MessageHeader *message)
886{
887 const struct GNUNET_MessageHeader *payload;
888 const struct GNUNET_MESH_MessageHandler *handler;
889 const struct GNUNET_PeerIdentity *peer;
890 struct GNUNET_PeerIdentity id;
891 struct GNUNET_MESH_Data *dmsg;
892 struct GNUNET_MESH_Tunnel *t;
893 unsigned int i;
894 uint32_t pid;
895 uint16_t type;
896
897 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n");
898 type = ntohs (message->type);
899 switch (type)
900 {
901 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
902 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
903 dmsg = (struct GNUNET_MESH_Data *) message;
904
905 t = retrieve_tunnel (h, ntohl (dmsg->tid));
906 payload = (struct GNUNET_MessageHeader *) &dmsg[1];
907 GNUNET_PEER_resolve (t->peer, &id);
908 peer = &id;
909 pid = ntohl (dmsg->pid);
910 LOG (GNUNET_ERROR_TYPE_DEBUG, " %s data on tunnel %s [%X]\n",
911 type == GNUNET_MESSAGE_TYPE_MESH_UNICAST ? "fwd" : "bck",
912 GNUNET_i2s (peer), ntohl (dmsg->tid));
913 break;
914 default:
915 GNUNET_break (0);
916 return;
917 }
918 LOG (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", pid);
919 if (NULL == t)
920 {
921 /* Tunnel was ignored/destroyed, probably service didn't get it yet */
922 LOG (GNUNET_ERROR_TYPE_DEBUG, " ignored!\n");
923 return;
924 }
925 if (GNUNET_YES ==
926 GMC_is_pid_bigger(pid, t->last_ack_sent))
927 {
928 GNUNET_break (0);
929 LOG (GNUNET_ERROR_TYPE_WARNING,
930 " unauthorized message! (%u, ACK %u)\n",
931 pid, t->last_ack_sent);
932 // FIXME fc what now? accept? reject?
933 return;
934 }
935 t->last_pid_recv = pid;
936 type = ntohs (payload->type);
937 for (i = 0; i < h->n_handlers; i++)
938 {
939 handler = &h->message_handlers[i];
940 if (handler->type == type)
941 {
942 if (GNUNET_OK !=
943 handler->callback (h->cls, t, &t->ctx, payload))
944 {
945 LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n");
946 GNUNET_MESH_tunnel_destroy (t);
947 return;
948 }
949 else
950 {
951 LOG (GNUNET_ERROR_TYPE_DEBUG,
952 "callback completed successfully\n");
953 }
954 }
955 }
956}
957
958
959/**
960 * Process a local ACK message, enabling the client to send
961 * more data to the service.
962 *
963 * @param h Mesh handle.
964 * @param message Message itself.
965 */
966static void
967process_ack (struct GNUNET_MESH_Handle *h,
968 const struct GNUNET_MessageHeader *message)
969{
970 struct GNUNET_MESH_LocalAck *msg;
971 struct GNUNET_MESH_Tunnel *t;
972 uint32_t ack;
973
974 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n");
975 h->acks_recv++;
976 msg = (struct GNUNET_MESH_LocalAck *) message;
977
978 t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
979
980 if (NULL == t)
981 {
982 LOG (GNUNET_ERROR_TYPE_WARNING,
983 "ACK on unknown tunnel %X\n",
984 ntohl (msg->tunnel_id));
985 return;
986 }
987 ack = ntohl (msg->ack);
988 LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X, ack %u!\n", t->tid, ack);
989 if (GNUNET_YES == GMC_is_pid_bigger(ack, t->last_ack_recv))
990 t->last_ack_recv = ack;
991 else
992 return;
993 if (NULL == h->th && 0 < t->packet_size)
994 {
995 LOG (GNUNET_ERROR_TYPE_DEBUG, " tmt rdy was NULL, requesting!\n", t->tid, ack);
996 h->th =
997 GNUNET_CLIENT_notify_transmit_ready (h->client, t->packet_size,
998 GNUNET_TIME_UNIT_FOREVER_REL,
999 GNUNET_YES, &send_callback, h);
1000 }
1001}
1002
1003
1004/**
1005 * Process a local reply about info on all tunnels, pass info to the user.
1006 *
1007 * @param h Mesh handle.
1008 * @param message Message itself.
1009 */
1010static void
1011process_get_tunnels (struct GNUNET_MESH_Handle *h,
1012 const struct GNUNET_MessageHeader *message)
1013{
1014 struct GNUNET_MESH_LocalMonitor *msg;
1015
1016 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Tunnels messasge received\n");
1017
1018 if (NULL == h->tunnels_cb)
1019 {
1020 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n");
1021 return;
1022 }
1023
1024 msg = (struct GNUNET_MESH_LocalMonitor *) message;
1025 if (ntohs (message->size) !=
1026 (sizeof (struct GNUNET_MESH_LocalMonitor) +
1027 sizeof (struct GNUNET_PeerIdentity)))
1028 {
1029 GNUNET_break_op (0);
1030 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1031 "Get tunnels message: size %hu - expected %u\n",
1032 ntohs (message->size),
1033 sizeof (struct GNUNET_MESH_LocalMonitor));
1034 return;
1035 }
1036 h->tunnels_cb (h->tunnels_cls,
1037 ntohl (msg->tunnel_id),
1038 &msg->owner,
1039 &msg->destination);
1040}
1041
1042
1043
1044/**
1045 * Process a local monitor_tunnel reply, pass info to the user.
1046 *
1047 * @param h Mesh handle.
1048 * @param message Message itself.
1049 */
1050static void
1051process_show_tunnel (struct GNUNET_MESH_Handle *h,
1052 const struct GNUNET_MessageHeader *message)
1053{
1054 struct GNUNET_MESH_LocalMonitor *msg;
1055 size_t esize;
1056
1057 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Tunnel messasge received\n");
1058
1059 if (NULL == h->tunnel_cb)
1060 {
1061 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n");
1062 return;
1063 }
1064
1065 /* Verify message sanity */
1066 msg = (struct GNUNET_MESH_LocalMonitor *) message;
1067 esize = sizeof (struct GNUNET_MESH_LocalMonitor);
1068 if (ntohs (message->size) != esize)
1069 {
1070 GNUNET_break_op (0);
1071 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1072 "Show tunnel message: size %hu - expected %u\n",
1073 ntohs (message->size),
1074 esize);
1075
1076 h->tunnel_cb (h->tunnel_cls, NULL, NULL);
1077 h->tunnel_cb = NULL;
1078 h->tunnel_cls = NULL;
1079
1080 return;
1081 }
1082
1083 h->tunnel_cb (h->tunnel_cls,
1084 &msg->destination,
1085 &msg->owner);
1086}
1087
1088
1089/**
1090 * Function to process all messages received from the service
1091 *
1092 * @param cls closure
1093 * @param msg message received, NULL on timeout or fatal error
1094 */
1095static void
1096msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
1097{
1098 struct GNUNET_MESH_Handle *h = cls;
1099
1100 if (msg == NULL)
1101 {
1102 LOG (GNUNET_ERROR_TYPE_DEBUG,
1103 "Mesh service disconnected, reconnecting\n", h);
1104 reconnect (h);
1105 return;
1106 }
1107 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n",
1108 GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1109 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n",
1110 GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1111 switch (ntohs (msg->type))
1112 {
1113 /* Notify of a new incoming tunnel */
1114 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE:
1115 process_tunnel_created (h, (struct GNUNET_MESH_TunnelNotification *) msg);
1116 break;
1117 /* Notify of a tunnel disconnection */
1118 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1119 process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg);
1120 break;
1121 /* Notify of a new data packet in the tunnel */
1122 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1123 case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1124 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1125 process_incoming_data (h, msg);
1126 break;
1127 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
1128 process_ack (h, msg);
1129 break;
1130 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
1131 process_get_tunnels (h, msg);
1132 break;
1133 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
1134 process_show_tunnel (h, msg);
1135 break;
1136 default:
1137 /* We shouldn't get any other packages, log and ignore */
1138 LOG (GNUNET_ERROR_TYPE_WARNING,
1139 "unsolicited message form service (type %s)\n",
1140 GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1141 }
1142 LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n");
1143 if (GNUNET_YES == h->in_receive)
1144 {
1145 GNUNET_CLIENT_receive (h->client, &msg_received, h,
1146 GNUNET_TIME_UNIT_FOREVER_REL);
1147 }
1148 else
1149 {
1150 LOG (GNUNET_ERROR_TYPE_DEBUG,
1151 "in receive off, not calling CLIENT_receive\n");
1152 }
1153}
1154
1155
1156/******************************************************************************/
1157/************************ SEND FUNCTIONS ****************************/
1158/******************************************************************************/
1159
1160/**
1161 * Function called to send a message to the service.
1162 * "buf" will be NULL and "size" zero if the socket was closed for writing in
1163 * the meantime.
1164 *
1165 * @param cls closure, the mesh handle
1166 * @param size number of bytes available in buf
1167 * @param buf where the callee should write the connect message
1168 * @return number of bytes written to buf
1169 */
1170static size_t
1171send_callback (void *cls, size_t size, void *buf)
1172{
1173 struct GNUNET_MESH_Handle *h = cls;
1174 struct GNUNET_MESH_TransmitHandle *th;
1175 struct GNUNET_MESH_TransmitHandle *next;
1176 struct GNUNET_MESH_Tunnel *t;
1177 char *cbuf = buf;
1178 size_t tsize;
1179 size_t psize;
1180 size_t nsize;
1181
1182 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
1183 LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() Buffer %u\n", size);
1184 if ((0 == size) || (NULL == buf))
1185 {
1186 LOG (GNUNET_ERROR_TYPE_DEBUG, "# Received NULL send callback on %p\n", h);
1187 reconnect (h);
1188 h->th = NULL;
1189 return 0;
1190 }
1191 tsize = 0;
1192 next = h->th_head;
1193 nsize = message_ready_size (h);
1194 while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize))
1195 {
1196 t = th->tunnel;
1197 if (GNUNET_YES == th_is_payload (th))
1198 {
1199 struct GNUNET_MESH_Data *dmsg;
1200 struct GNUNET_MessageHeader *mh;
1201
1202 LOG (GNUNET_ERROR_TYPE_DEBUG, "# payload\n");
1203 if (GNUNET_NO == GMC_is_pid_bigger (t->last_ack_recv, t->last_pid_sent))
1204 {
1205 /* This tunnel is not ready to transmit yet, try next message */
1206 next = th->next;
1207 continue;
1208 }
1209 t->packet_size = 0;
1210 GNUNET_assert (size >= th->size);
1211 dmsg = (struct GNUNET_MESH_Data *) cbuf;
1212 mh = (struct GNUNET_MessageHeader *) &dmsg[1];
1213 psize = th->notify (th->notify_cls,
1214 size - sizeof (struct GNUNET_MESH_Data),
1215 mh);
1216 if (psize > 0)
1217 {
1218 psize += sizeof (struct GNUNET_MESH_Data);
1219 GNUNET_assert (size >= psize);
1220 dmsg->header.size = htons (psize);
1221 dmsg->tid = htonl (t->tid);
1222 dmsg->pid = htonl (t->last_pid_sent + 1);
1223 dmsg->ttl = 0;
1224 memset (&dmsg->oid, 0, sizeof (struct GNUNET_PeerIdentity));
1225 t->last_pid_sent++;
1226 }
1227 if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1228 {
1229 dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
1230 LOG (GNUNET_ERROR_TYPE_DEBUG, "# to origin, type %s\n",
1231 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1232 }
1233 else
1234 {
1235 dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
1236 LOG (GNUNET_ERROR_TYPE_DEBUG, "# unicast, type %s\n",
1237 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1238 }
1239 }
1240 else
1241 {
1242 struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1];
1243
1244 LOG (GNUNET_ERROR_TYPE_DEBUG, "# mesh traffic, type %s\n",
1245 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1246 memcpy (cbuf, &th[1], th->size);
1247 psize = th->size;
1248 }
1249 if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1250 GNUNET_SCHEDULER_cancel (th->timeout_task);
1251 GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1252 GNUNET_free (th);
1253 next = h->th_head;
1254 nsize = message_ready_size (h);
1255 cbuf += psize;
1256 size -= psize;
1257 tsize += psize;
1258 }
1259 LOG (GNUNET_ERROR_TYPE_DEBUG, "# total size: %u\n", tsize);
1260 h->th = NULL;
1261 size = message_ready_size (h);
1262 if (0 != size)
1263 {
1264 LOG (GNUNET_ERROR_TYPE_DEBUG, "# next size: %u\n", size);
1265 h->th =
1266 GNUNET_CLIENT_notify_transmit_ready (h->client, size,
1267 GNUNET_TIME_UNIT_FOREVER_REL,
1268 GNUNET_YES, &send_callback, h);
1269 }
1270 else
1271 {
1272 if (NULL != h->th_head)
1273 LOG (GNUNET_ERROR_TYPE_DEBUG, "# can't transmit any more\n");
1274 else
1275 LOG (GNUNET_ERROR_TYPE_DEBUG, "# nothing left to transmit\n");
1276 }
1277 if (GNUNET_NO == h->in_receive)
1278 {
1279 LOG (GNUNET_ERROR_TYPE_DEBUG, "# start receiving from service\n");
1280 h->in_receive = GNUNET_YES;
1281 GNUNET_CLIENT_receive (h->client, &msg_received, h,
1282 GNUNET_TIME_UNIT_FOREVER_REL);
1283 }
1284 LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() END\n");
1285 return tsize;
1286}
1287
1288
1289/**
1290 * Auxiliary function to send an already constructed packet to the service.
1291 * Takes care of creating a new queue element, copying the message and
1292 * calling the tmt_rdy function if necessary.
1293 *
1294 * @param h mesh handle
1295 * @param msg message to transmit
1296 * @param tunnel tunnel this send is related to (NULL if N/A)
1297 */
1298static void
1299send_packet (struct GNUNET_MESH_Handle *h,
1300 const struct GNUNET_MessageHeader *msg,
1301 struct GNUNET_MESH_Tunnel *tunnel)
1302{
1303 struct GNUNET_MESH_TransmitHandle *th;
1304 size_t msize;
1305
1306 LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n",
1307 GNUNET_MESH_DEBUG_M2S(ntohs(msg->type)));
1308 msize = ntohs (msg->size);
1309 th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize);
1310 th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1311 th->size = msize;
1312 th->tunnel = tunnel;
1313 memcpy (&th[1], msg, msize);
1314 add_to_queue (h, th);
1315 LOG (GNUNET_ERROR_TYPE_DEBUG, " queued\n");
1316 if (NULL != h->th)
1317 return;
1318 LOG (GNUNET_ERROR_TYPE_DEBUG, " calling ntfy tmt rdy for %u bytes\n", msize);
1319 h->th =
1320 GNUNET_CLIENT_notify_transmit_ready (h->client, msize,
1321 GNUNET_TIME_UNIT_FOREVER_REL,
1322 GNUNET_YES, &send_callback, h);
1323}
1324
1325
1326/******************************************************************************/
1327/********************** API CALL DEFINITIONS *************************/
1328/******************************************************************************/
1329
1330struct GNUNET_MESH_Handle *
1331GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
1332 GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
1333 GNUNET_MESH_TunnelEndHandler cleaner,
1334 const struct GNUNET_MESH_MessageHandler *handlers,
1335 const uint32_t *ports)
1336{
1337 struct GNUNET_MESH_Handle *h;
1338
1339 LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n");
1340 h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
1341 LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h);
1342 h->cfg = cfg;
1343 h->new_tunnel = new_tunnel;
1344 h->cleaner = cleaner;
1345 h->client = GNUNET_CLIENT_connect ("mesh", cfg);
1346 if (h->client == NULL)
1347 {
1348 GNUNET_break (0);
1349 GNUNET_free (h);
1350 return NULL;
1351 }
1352 h->cls = cls;
1353 h->message_handlers = handlers;
1354 h->ports = ports;
1355 h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
1356 h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
1357 h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1358
1359 /* count handlers */
1360 for (h->n_handlers = 0;
1361 handlers && handlers[h->n_handlers].type;
1362 h->n_handlers++) ;
1363 for (h->n_ports = 0;
1364 ports && ports[h->n_ports];
1365 h->n_ports++) ;
1366 send_connect (h);
1367 LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n");
1368 return h;
1369}
1370
1371
1372void
1373GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
1374{
1375 struct GNUNET_MESH_Tunnel *t;
1376 struct GNUNET_MESH_Tunnel *aux;
1377 struct GNUNET_MESH_TransmitHandle *th;
1378
1379 LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH DISCONNECT\n");
1380
1381#if DEBUG_ACK
1382 LOG (GNUNET_ERROR_TYPE_INFO, "Sent %d ACKs\n", handle->acks_sent);
1383 LOG (GNUNET_ERROR_TYPE_INFO, "Recv %d ACKs\n\n", handle->acks_recv);
1384#endif
1385
1386 t = handle->tunnels_head;
1387 while (NULL != t)
1388 {
1389 aux = t->next;
1390 if (t->tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1391 {
1392 GNUNET_break (0);
1393 LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X not destroyed\n", t->tid);
1394 }
1395 destroy_tunnel (t, GNUNET_YES);
1396 t = aux;
1397 }
1398 while ( (th = handle->th_head) != NULL)
1399 {
1400 struct GNUNET_MessageHeader *msg;
1401
1402 /* Make sure it is an allowed packet (everything else should have been
1403 * already canceled).
1404 */
1405 GNUNET_break (GNUNET_NO == th_is_payload (th));
1406 msg = (struct GNUNET_MessageHeader *) &th[1];
1407 switch (ntohs(msg->type))
1408 {
1409 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT:
1410 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1411 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
1412 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
1413 break;
1414 default:
1415 GNUNET_break (0);
1416 LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n",
1417 ntohs(msg->type));
1418 }
1419
1420 GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th);
1421 GNUNET_free (th);
1422 }
1423
1424 if (NULL != handle->th)
1425 {
1426 GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
1427 handle->th = NULL;
1428 }
1429 if (NULL != handle->client)
1430 {
1431 GNUNET_CLIENT_disconnect (handle->client);
1432 handle->client = NULL;
1433 }
1434 if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task)
1435 {
1436 GNUNET_SCHEDULER_cancel(handle->reconnect_task);
1437 handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1438 }
1439 GNUNET_free (handle);
1440}
1441
1442
1443struct GNUNET_MESH_Tunnel *
1444GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h,
1445 void *tunnel_ctx,
1446 const struct GNUNET_PeerIdentity *peer,
1447 uint32_t port)
1448{
1449 struct GNUNET_MESH_Tunnel *t;
1450 struct GNUNET_MESH_TunnelMessage msg;
1451
1452 LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new tunnel\n");
1453 t = create_tunnel (h, 0);
1454 LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", t);
1455 LOG (GNUNET_ERROR_TYPE_DEBUG, " number %X\n", t->tid);
1456 t->ctx = tunnel_ctx;
1457 t->peer = GNUNET_PEER_intern (peer);
1458 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
1459 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1460 msg.tunnel_id = htonl (t->tid);
1461 msg.port = htonl (port);
1462 msg.peer = *peer;
1463 t->last_ack_sent = 0;
1464 send_packet (h, &msg.header, t);
1465 return t;
1466}
1467
1468
1469void
1470GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel)
1471{
1472 struct GNUNET_MESH_Handle *h;
1473 struct GNUNET_MESH_TunnelMessage msg;
1474 struct GNUNET_MESH_TransmitHandle *th;
1475
1476 LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying tunnel\n");
1477 h = tunnel->mesh;
1478
1479 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1480 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1481 msg.tunnel_id = htonl (tunnel->tid);
1482 th = h->th_head;
1483 while (th != NULL)
1484 {
1485 struct GNUNET_MESH_TransmitHandle *aux;
1486 if (th->tunnel == tunnel)
1487 {
1488 aux = th->next;
1489 /* FIXME call the handler? */
1490 if (GNUNET_YES == th_is_payload (th))
1491 th->notify (th->notify_cls, 0, NULL);
1492 GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1493 GNUNET_free (th);
1494 th = aux;
1495 }
1496 else
1497 th = th->next;
1498 }
1499
1500 destroy_tunnel (tunnel, GNUNET_YES);
1501 send_packet (h, &msg.header, NULL);
1502}
1503
1504
1505void
1506GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer)
1507{
1508 struct GNUNET_MESH_TunnelMessage msg;
1509 struct GNUNET_MESH_Handle *h;
1510
1511 h = tunnel->mesh;
1512 tunnel->buffering = buffer;
1513
1514 if (GNUNET_YES == buffer)
1515 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER);
1516 else
1517 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER);
1518 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1519 msg.tunnel_id = htonl (tunnel->tid);
1520
1521 send_packet (h, &msg.header, NULL);
1522}
1523
1524
1525struct GNUNET_MESH_TransmitHandle *
1526GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
1527 struct GNUNET_TIME_Relative maxdelay,
1528 size_t notify_size,
1529 GNUNET_CONNECTION_TransmitReadyNotify notify,
1530 void *notify_cls)
1531{
1532 struct GNUNET_MESH_TransmitHandle *th;
1533
1534 GNUNET_assert (NULL != tunnel);
1535 LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n");
1536 LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", tunnel->tid);
1537 if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1538 LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin\n");
1539 else
1540 LOG (GNUNET_ERROR_TYPE_DEBUG, " to destination\n");
1541 LOG (GNUNET_ERROR_TYPE_DEBUG, " payload size %u\n", notify_size);
1542 GNUNET_assert (NULL != notify);
1543 GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed
1544 th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
1545 th->tunnel = tunnel;
1546 th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
1547 th->size = notify_size + sizeof (struct GNUNET_MESH_Data);
1548 tunnel->packet_size = th->size;
1549 LOG (GNUNET_ERROR_TYPE_DEBUG, " total size %u\n", th->size);
1550 th->notify = notify;
1551 th->notify_cls = notify_cls;
1552 add_to_queue (tunnel->mesh, th);
1553 if (NULL != tunnel->mesh->th)
1554 return th;
1555 if (!GMC_is_pid_bigger (tunnel->last_ack_recv, tunnel->last_pid_sent))
1556 return th;
1557 LOG (GNUNET_ERROR_TYPE_DEBUG, " call client notify tmt rdy\n");
1558 tunnel->mesh->th =
1559 GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size,
1560 GNUNET_TIME_UNIT_FOREVER_REL,
1561 GNUNET_YES, &send_callback,
1562 tunnel->mesh);
1563 LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY END\n");
1564 return th;
1565}
1566
1567
1568void
1569GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th)
1570{
1571 struct GNUNET_MESH_Handle *mesh;
1572
1573 th->tunnel->packet_size = 0;
1574 mesh = th->tunnel->mesh;
1575 if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1576 GNUNET_SCHEDULER_cancel (th->timeout_task);
1577 GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
1578 GNUNET_free (th);
1579 if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
1580 {
1581 /* queue empty, no point in asking for transmission */
1582 GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
1583 mesh->th = NULL;
1584 }
1585}
1586
1587void
1588GNUNET_MESH_receive_done (struct GNUNET_MESH_Tunnel *tunnel)
1589{
1590 send_ack (tunnel);
1591}
1592
1593
1594/**
1595 * Request information about the running mesh peer.
1596 * The callback will be called for every tunnel known to the service,
1597 * listing all active peers that blong to the tunnel.
1598 *
1599 * If called again on the same handle, it will overwrite the previous
1600 * callback and cls. To retrieve the cls, monitor_cancel must be
1601 * called first.
1602 *
1603 * WARNING: unstable API, likely to change in the future!
1604 *
1605 * @param h Handle to the mesh peer.
1606 * @param callback Function to call with the requested data.
1607 * @param callback_cls Closure for @c callback.
1608 */
1609void
1610GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h,
1611 GNUNET_MESH_TunnelsCB callback,
1612 void *callback_cls)
1613{
1614 struct GNUNET_MessageHeader msg;
1615
1616 msg.size = htons (sizeof (msg));
1617 msg.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
1618 send_packet (h, &msg, NULL);
1619 h->tunnels_cb = callback;
1620 h->tunnels_cls = callback_cls;
1621
1622 return;
1623}
1624
1625
1626/**
1627 * Cancel a monitor request. The monitor callback will not be called.
1628 *
1629 * @param h Mesh handle.
1630 *
1631 * @return Closure given to GNUNET_MESH_monitor, if any.
1632 */
1633void *
1634GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h)
1635{
1636 void *cls;
1637
1638 cls = h->tunnels_cls;
1639 h->tunnels_cb = NULL;
1640 h->tunnels_cls = NULL;
1641 return cls;
1642}
1643
1644
1645/**
1646 * Request information about a specific tunnel of the running mesh peer.
1647 *
1648 * WARNING: unstable API, likely to change in the future!
1649 * FIXME Add destination option.
1650 *
1651 * @param h Handle to the mesh peer.
1652 * @param initiator ID of the owner of the tunnel.
1653 * @param tunnel_number Tunnel number.
1654 * @param callback Function to call with the requested data.
1655 * @param callback_cls Closure for @c callback.
1656 */
1657void
1658GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h,
1659 struct GNUNET_PeerIdentity *initiator,
1660 unsigned int tunnel_number,
1661 GNUNET_MESH_TunnelCB callback,
1662 void *callback_cls)
1663{
1664 struct GNUNET_MESH_LocalMonitor msg;
1665
1666 msg.header.size = htons (sizeof (msg));
1667 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL);
1668 msg.owner = *initiator;
1669 msg.tunnel_id = htonl (tunnel_number);
1670 msg.reserved = 0;
1671 send_packet (h, &msg.header, NULL);
1672 h->tunnel_cb = callback;
1673 h->tunnel_cls = callback_cls;
1674
1675 return;
1676}
1677
1678
1679/**
1680 * Function called to notify a client about the connection
1681 * begin ready to queue more data. "buf" will be
1682 * NULL and "size" zero if the connection was closed for
1683 * writing in the meantime.
1684 *
1685 * @param cls closure
1686 * @param size number of bytes available in buf
1687 * @param buf where the callee should write the message
1688 * @return number of bytes written to buf
1689 */
1690static size_t
1691mesh_mq_ntr (void *cls, size_t size,
1692 void *buf)
1693{
1694 struct GNUNET_MQ_Handle *mq = cls;
1695 struct MeshMQState *state = GNUNET_MQ_impl_state (mq);
1696 const struct GNUNET_MessageHeader *msg = GNUNET_MQ_impl_current (mq);
1697 uint16_t msize;
1698
1699 state->th = NULL;
1700 if (NULL == buf)
1701 {
1702 GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE);
1703 return 0;
1704 }
1705 msize = ntohs (msg->size);
1706 GNUNET_assert (msize <= size);
1707 memcpy (buf, msg, msize);
1708 GNUNET_MQ_impl_send_continue (mq);
1709 return msize;
1710}
1711
1712
1713/**
1714 * Signature of functions implementing the
1715 * sending functionality of a message queue.
1716 *
1717 * @param mq the message queue
1718 * @param msg the message to send
1719 * @param impl_state state of the implementation
1720 */
1721static void
1722mesh_mq_send_impl (struct GNUNET_MQ_Handle *mq,
1723 const struct GNUNET_MessageHeader *msg, void *impl_state)
1724{
1725 struct MeshMQState *state = impl_state;
1726
1727 GNUNET_assert (NULL == state->th);
1728 GNUNET_MQ_impl_send_commit (mq);
1729 state->th =
1730 GNUNET_MESH_notify_transmit_ready (state->tunnel,
1731 /* FIXME: add option for corking */
1732 GNUNET_NO,
1733 GNUNET_TIME_UNIT_FOREVER_REL,
1734 ntohs (msg->size),
1735 mesh_mq_ntr, mq);
1736
1737}
1738
1739
1740/**
1741 * Signature of functions implementing the
1742 * destruction of a message queue.
1743 * Implementations must not free 'mq', but should
1744 * take care of 'impl_state'.
1745 *
1746 * @param mq the message queue to destroy
1747 * @param impl_state state of the implementation
1748 */
1749static void
1750mesh_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
1751{
1752 struct MeshMQState *state = impl_state;
1753
1754 if (NULL != state->th)
1755 GNUNET_MESH_notify_transmit_ready_cancel (state->th);
1756
1757 GNUNET_free (state);
1758}
1759
1760
1761/**
1762 * Create a message queue for a mesh tunnel.
1763 * The message queue can only be used to transmit messages,
1764 * not to receive them.
1765 *
1766 * @param tunnel the tunnel to create the message qeue for
1767 * @return a message queue to messages over the tunnel
1768 */
1769struct GNUNET_MQ_Handle *
1770GNUNET_MESH_mq_create (struct GNUNET_MESH_Tunnel *tunnel)
1771{
1772 struct GNUNET_MQ_Handle *mq;
1773 struct MeshMQState *state;
1774
1775 state = GNUNET_new (struct MeshMQState);
1776 state->tunnel = tunnel;
1777
1778 mq = GNUNET_MQ_queue_for_callbacks (mesh_mq_send_impl,
1779 mesh_mq_destroy_impl,
1780 NULL, /* FIXME: cancel impl. */
1781 state,
1782 NULL, /* no msg handlers */
1783 NULL, /* no err handlers */
1784 NULL); /* no handler cls */
1785 return mq;
1786}
1787
diff --git a/src/mesh/mesh2_protocol.h b/src/mesh/mesh2_protocol.h
deleted file mode 100644
index d35d7141e..000000000
--- a/src/mesh/mesh2_protocol.h
+++ /dev/null
@@ -1,316 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @author Bartlomiej Polot
23 * @file mesh/mesh_protocol.h
24 */
25
26#ifndef MESH_PROTOCOL_H_
27#define MESH_PROTOCOL_H_
28
29#ifdef __cplusplus
30extern "C"
31{
32#if 0
33 /* keep Emacsens' auto-indent happy */
34}
35#endif
36#endif
37
38#define MESH_TUNNEL_OPT_NOBUFFER 0x2
39
40
41/******************************************************************************/
42/******************** MESH NETWORK MESSAGES **************************/
43/******************************************************************************/
44
45GNUNET_NETWORK_STRUCT_BEGIN
46
47/**
48 * Message for mesh path creation.
49 */
50struct GNUNET_MESH_CreateTunnel
51{
52 /**
53 * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE
54 *
55 * Size: sizeof(struct GNUNET_MESH_ManipulatePath) +
56 * path_length * sizeof (struct GNUNET_PeerIdentity)
57 */
58 struct GNUNET_MessageHeader header;
59
60 /**
61 * Global id of the tunnel this path belongs to,
62 * unique in conjunction with the origin.
63 */
64 uint32_t tid GNUNET_PACKED;
65
66 /**
67 * Tunnel options (MESH_TUNNEL_OPT_*).
68 */
69 uint32_t opt GNUNET_PACKED;
70
71 /**
72 * Destination port.
73 */
74 uint32_t port GNUNET_PACKED;
75
76 /**
77 * FIXME do not add the first hop
78 * path_length structs defining the *whole* path from the origin [0] to the
79 * final destination [path_length-1].
80 */
81 /* struct GNUNET_PeerIdentity peers[path_length]; */
82};
83
84/**
85 * Message for mesh path destruction.
86 */
87struct GNUNET_MESH_DestroyTunnel
88{
89 /**
90 * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY
91 *
92 * Size: sizeof(struct GNUNET_MESH_ManipulatePath) +
93 * path_length * sizeof (struct GNUNET_PeerIdentity)
94 */
95 struct GNUNET_MessageHeader header;
96
97 /**
98 * Global id of the tunnel this path belongs to,
99 * unique in conjunction with the origin.
100 */
101 uint32_t tid GNUNET_PACKED;
102};
103
104
105/**
106 * Message for mesh data traffic.
107 */
108struct GNUNET_MESH_Data
109{
110 /**
111 * Type: GNUNET_MESSAGE_TYPE_MESH_UNICAST,
112 * GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN
113 */
114 struct GNUNET_MessageHeader header;
115
116 /**
117 * TID of the tunnel
118 */
119 uint32_t tid GNUNET_PACKED;
120
121 /**
122 * Number of hops to live
123 */
124 uint32_t ttl GNUNET_PACKED;
125
126 /**
127 * Unique ID of the packet
128 */
129 uint32_t pid GNUNET_PACKED;
130
131 /**
132 * OID of the tunnel
133 */
134 struct GNUNET_PeerIdentity oid;
135
136 /**
137 * Payload follows
138 */
139};
140
141
142/**
143 * Message to acknowledge mesh data traffic.
144 */
145struct GNUNET_MESH_ACK
146{
147 /**
148 * Type: GNUNET_MESSAGE_TYPE_MESH_ACK
149 */
150 struct GNUNET_MessageHeader header;
151
152 /**
153 * TID of the tunnel
154 */
155 uint32_t tid GNUNET_PACKED;
156
157 /**
158 * OID of the tunnel
159 */
160 struct GNUNET_PeerIdentity oid;
161
162 /**
163 * Maximum packet ID authorized.
164 */
165 uint32_t pid;
166
167};
168
169/**
170 * Message to query a peer about its Flow Control status regarding a tunnel.
171 */
172struct GNUNET_MESH_Poll
173{
174 /**
175 * Type: GNUNET_MESSAGE_TYPE_MESH_POLL
176 */
177 struct GNUNET_MessageHeader header;
178
179 /**
180 * TID of the tunnel
181 */
182 uint32_t tid GNUNET_PACKED;
183
184 /**
185 * OID of the tunnel
186 */
187 struct GNUNET_PeerIdentity oid;
188};
189
190/**
191 * Message for ack'ing a path
192 */
193struct GNUNET_MESH_PathACK
194{
195 /**
196 * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_ACK
197 */
198 struct GNUNET_MessageHeader header;
199
200 /**
201 * TID of the tunnel
202 */
203 uint32_t tid GNUNET_PACKED;
204
205 /**
206 * OID of the tunnel
207 */
208 struct GNUNET_PeerIdentity oid;
209
210 /**
211 * ID of the endpoint
212 */
213 struct GNUNET_PeerIdentity peer_id;
214
215 /**
216 * Initial ACK value for payload.
217 */
218 uint32_t ack GNUNET_PACKED;
219
220 /* TODO: signature */
221};
222
223
224/**
225 * Message for notifying a disconnection in a path
226 */
227struct GNUNET_MESH_PathBroken
228{
229 /**
230 * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN
231 */
232 struct GNUNET_MessageHeader header;
233
234 /**
235 * TID of the tunnel
236 */
237 uint32_t tid GNUNET_PACKED;
238
239 /**
240 * OID of the tunnel
241 */
242 struct GNUNET_PeerIdentity oid;
243
244 /**
245 * ID of the endpoint
246 */
247 struct GNUNET_PeerIdentity peer1;
248
249 /**
250 * ID of the endpoint
251 */
252 struct GNUNET_PeerIdentity peer2;
253
254 /* TODO: signature */
255};
256
257
258/**
259 * Message to destroy a tunnel
260 */
261struct GNUNET_MESH_TunnelDestroy
262{
263 /**
264 * Type: GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY
265 */
266 struct GNUNET_MessageHeader header;
267
268 /**
269 * TID of the tunnel
270 */
271 uint32_t tid GNUNET_PACKED;
272
273 /**
274 * OID of the tunnel
275 */
276 struct GNUNET_PeerIdentity oid;
277
278 /* TODO: signature */
279};
280
281
282/**
283 * Message to destroy a tunnel
284 */
285struct GNUNET_MESH_TunnelKeepAlive
286{
287 /**
288 * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE
289 */
290 struct GNUNET_MessageHeader header;
291
292 /**
293 * TID of the tunnel
294 */
295 uint32_t tid GNUNET_PACKED;
296
297 /**
298 * OID of the tunnel
299 */
300 struct GNUNET_PeerIdentity oid;
301};
302
303
304
305GNUNET_NETWORK_STRUCT_END
306
307#if 0 /* keep Emacsens' auto-indent happy */
308{
309#endif
310#ifdef __cplusplus
311}
312#endif
313
314/* ifndef MESH_PROTOCOL_H */
315#endif
316/* end of mesh_protocol.h */
diff --git a/src/mesh/mesh2_test_lib.c b/src/mesh/mesh2_test_lib.c
deleted file mode 100644
index 95de93edd..000000000
--- a/src/mesh/mesh2_test_lib.c
+++ /dev/null
@@ -1,283 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file mesh/mesh2_test_lib.c
22 * @author Bartlomiej Polot
23 * @brief library for writing MESH tests
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "mesh2_test_lib.h"
28#include "gnunet_mesh2_service.h"
29
30/**
31 * Test context for a MESH Test.
32 */
33struct GNUNET_MESH_TEST_Context
34{
35 /**
36 * Array of running peers.
37 */
38 struct GNUNET_TESTBED_Peer **peers;
39
40 /**
41 * Array of handles to the MESH for each peer.
42 */
43 struct GNUNET_MESH_Handle **meshes;
44
45 /**
46 * Operation associated with the connection to the MESH.
47 */
48 struct GNUNET_TESTBED_Operation **ops;
49
50 /**
51 * Main function of the test to run once all MESHs are available.
52 */
53 GNUNET_MESH_TEST_AppMain app_main;
54
55 /**
56 * Closure for 'app_main'.
57 */
58 void *app_main_cls;
59
60 /**
61 * Number of peers running, size of the arrays above.
62 */
63 unsigned int num_peers;
64
65 /**
66 * Handler for incoming tunnels.
67 */
68 GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
69
70 /**
71 * Cleaner for destroyed incoming tunnels.
72 */
73 GNUNET_MESH_TunnelEndHandler *cleaner;
74
75 /**
76 * Message handlers.
77 */
78 struct GNUNET_MESH_MessageHandler* handlers;
79
80 /**
81 * Application ports.
82 */
83 const uint32_t *ports;
84
85};
86
87
88/**
89 * Context for a mesh adapter callback.
90 */
91struct GNUNET_MESH_TEST_AdapterContext
92{
93 /**
94 * Peer number for the particular peer.
95 */
96 unsigned int peer;
97
98 /**
99 * General context.
100 */
101 struct GNUNET_MESH_TEST_Context *ctx;
102};
103
104
105/**
106 * Adapter function called to establish a connection to
107 * the MESH service.
108 *
109 * @param cls closure
110 * @param cfg configuration of the peer to connect to; will be available until
111 * GNUNET_TESTBED_operation_done() is called on the operation returned
112 * from GNUNET_TESTBED_service_connect()
113 * @return service handle to return in 'op_result', NULL on error
114 */
115static void *
116mesh_connect_adapter (void *cls,
117 const struct GNUNET_CONFIGURATION_Handle *cfg)
118{
119 struct GNUNET_MESH_TEST_AdapterContext *actx = cls;
120 struct GNUNET_MESH_TEST_Context *ctx = actx->ctx;
121 struct GNUNET_MESH_Handle *h;
122
123 h = GNUNET_MESH_connect (cfg,
124 (void *) (long) actx->peer,
125 ctx->new_tunnel,
126 ctx->cleaner,
127 ctx->handlers,
128 ctx->ports);
129 return h;
130}
131
132
133/**
134 * Adapter function called to destroy a connection to
135 * the MESH service.
136 *
137 * @param cls closure
138 * @param op_result service handle returned from the connect adapter
139 */
140static void
141mesh_disconnect_adapter (void *cls,
142 void *op_result)
143{
144 struct GNUNET_MESH_Handle *mesh = op_result;
145 struct GNUNET_MESH_TEST_AdapterContext *actx = cls;
146
147 GNUNET_free (actx);
148 GNUNET_MESH_disconnect (mesh);
149}
150
151
152/**
153 * Callback to be called when a service connect operation is completed.
154 *
155 * @param cls The callback closure from functions generating an operation.
156 * @param op The operation that has been finished.
157 * @param ca_result The service handle returned from
158 * GNUNET_TESTBED_ConnectAdapter() (mesh handle).
159 * @param emsg Error message in case the operation has failed.
160 * NULL if operation has executed successfully.
161 */
162static void
163mesh_connect_cb (void *cls,
164 struct GNUNET_TESTBED_Operation *op,
165 void *ca_result,
166 const char *emsg)
167{
168 struct GNUNET_MESH_TEST_Context *ctx = cls;
169 unsigned int i;
170
171 if (NULL != emsg)
172 {
173 fprintf (stderr, "Failed to connect to MESH service: %s\n",
174 emsg);
175 GNUNET_SCHEDULER_shutdown ();
176 return;
177 }
178 for (i = 0; i < ctx->num_peers; i++)
179 if (op == ctx->ops[i])
180 ctx->meshes[i] = ca_result;
181 for (i = 0; i < ctx->num_peers; i++)
182 if (NULL == ctx->meshes[i])
183 return; /* still some MESH connections missing */
184 /* all MESH connections ready! */
185 ctx->app_main (ctx->app_main_cls,
186 ctx,
187 ctx->num_peers,
188 ctx->peers,
189 ctx->meshes);
190}
191
192
193void
194GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx)
195{
196 unsigned int i;
197
198 for (i = 0; i < ctx->num_peers; i++)
199 {
200 GNUNET_assert (NULL != ctx->ops[i]);
201 GNUNET_TESTBED_operation_done (ctx->ops[i]);
202 ctx->ops[i] = NULL;
203 }
204 GNUNET_free (ctx->ops);
205 GNUNET_free (ctx->meshes);
206 GNUNET_free (ctx);
207 GNUNET_SCHEDULER_shutdown ();
208}
209
210
211/**
212 * Callback run when the testbed is ready (peers running and connected to
213 * each other)
214 *
215 * @param cls Closure (context).
216 * @param num_peers Number of peers that are running.
217 * @param peers Handles to each one of the @c num_peers peers.
218 * @param links_succeeded the number of overlay link connection attempts that
219 * succeeded
220 * @param links_failed the number of overlay link connection attempts that
221 * failed
222 */
223static void
224mesh_test_run (void *cls,
225 unsigned int num_peers,
226 struct GNUNET_TESTBED_Peer **peers,
227 unsigned int links_succeeded,
228 unsigned int links_failed)
229{
230 struct GNUNET_MESH_TEST_Context *ctx = cls;
231 unsigned int i;
232
233 GNUNET_assert (num_peers == ctx->num_peers);
234 ctx->peers = peers;
235 for (i = 0; i < num_peers; i++)
236 {
237 struct GNUNET_MESH_TEST_AdapterContext *newctx;
238 newctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_AdapterContext));
239 newctx->peer = i;
240 newctx->ctx = ctx;
241 ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
242 peers[i],
243 "mesh",
244 &mesh_connect_cb,
245 ctx,
246 &mesh_connect_adapter,
247 &mesh_disconnect_adapter,
248 newctx);
249 }
250}
251
252
253void
254GNUNET_MESH_TEST_run (const char *testname,
255 const char *cfgname,
256 unsigned int num_peers,
257 GNUNET_MESH_TEST_AppMain tmain,
258 void *tmain_cls,
259 GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
260 GNUNET_MESH_TunnelEndHandler cleaner,
261 struct GNUNET_MESH_MessageHandler* handlers,
262 const uint32_t *ports)
263{
264 struct GNUNET_MESH_TEST_Context *ctx;
265
266 ctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_Context));
267 ctx->num_peers = num_peers;
268 ctx->ops = GNUNET_malloc (num_peers * sizeof (struct GNUNET_TESTBED_Operation *));
269 ctx->meshes = GNUNET_malloc (num_peers * sizeof (struct GNUNET_MESH_Handle *));
270 ctx->app_main = tmain;
271 ctx->app_main_cls = tmain_cls;
272 ctx->new_tunnel = new_tunnel;
273 ctx->cleaner = cleaner;
274 ctx->handlers = handlers;
275 ctx->ports = ports;
276 GNUNET_TESTBED_test_run (testname,
277 cfgname,
278 num_peers,
279 0LL, NULL, NULL,
280 &mesh_test_run, ctx);
281}
282
283/* end of mesh_test_lib.c */
diff --git a/src/mesh/mesh2_test_lib.h b/src/mesh/mesh2_test_lib.h
deleted file mode 100644
index 096c0ebc1..000000000
--- a/src/mesh/mesh2_test_lib.h
+++ /dev/null
@@ -1,106 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file mesh/mesh2_test_lib.h
22 * @author Bartlomiej Polot
23 * @brief library for writing MESH tests
24 */
25#ifndef MESH_TEST_LIB_H
26#define MESH_TEST_LIB_H
27
28#ifdef __cplusplus
29extern "C"
30{
31#if 0 /* keep Emacsens' auto-indent happy */
32}
33#endif
34#endif
35
36#include "gnunet_testbed_service.h"
37#include "gnunet_mesh2_service.h"
38
39/**
40 * Test context for a MESH Test.
41 */
42struct GNUNET_MESH_TEST_Context;
43
44
45/**
46 * Main function of a MESH test.
47 *
48 * @param cls Closure.
49 * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end.
50 * @param num_peers Number of peers that are running.
51 * @param peers Array of peers.
52 * @param meshes Handle to each of the MESHs of the peers.
53 */
54typedef void (*GNUNET_MESH_TEST_AppMain) (void *cls,
55 struct GNUNET_MESH_TEST_Context *ctx,
56 unsigned int num_peers,
57 struct GNUNET_TESTBED_Peer **peers,
58 struct GNUNET_MESH_Handle **meshes);
59
60
61/**
62 * Run a test using the given name, configuration file and number of
63 * peers.
64 * All mesh callbacks will receive the peer number as the closure.
65 *
66 * @param testname Name of the test (for logging).
67 * @param cfgname Name of the configuration file.
68 * @param num_peers Number of peers to start.
69 * @param tmain Main function to run once the testbed is ready.
70 * @param tmain_cls Closure for 'tmain'.
71 * @param new_tunnel Handler for incoming tunnels.
72 * @param cleaner Cleaner for destroyed incoming tunnels.
73 * @param handlers Message handlers.
74 * @param ports Ports the peers offer.
75 */
76void
77GNUNET_MESH_TEST_run (const char *testname,
78 const char *cfgname,
79 unsigned int num_peers,
80 GNUNET_MESH_TEST_AppMain tmain,
81 void *tmain_cls,
82 GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
83 GNUNET_MESH_TunnelEndHandler cleaner,
84 struct GNUNET_MESH_MessageHandler* handlers,
85 const uint32_t* ports);
86
87
88/**
89 * Clean up the testbed.
90 *
91 * @param ctx handle for the testbed
92 */
93void
94GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_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 MESH_TEST_LIB_H */
106#endif
diff --git a/src/mesh/mesh_api.c b/src/mesh/mesh_api.c
index 8683d7f24..189580e50 100644
--- a/src/mesh/mesh_api.c
+++ b/src/mesh/mesh_api.c
@@ -17,7 +17,7 @@
17 17
18/** 18/**
19 * @file mesh/mesh_api.c 19 * @file mesh/mesh_api.c
20 * @brief mesh api: client implementation of mesh service 20 * @brief mesh api: client implementation of new mesh service
21 * @author Bartlomiej Polot 21 * @author Bartlomiej Polot
22 * 22 *
23 * STRUCTURE: 23 * STRUCTURE:
@@ -40,7 +40,6 @@
40#include "mesh_protocol.h" 40#include "mesh_protocol.h"
41 41
42#define LOG(kind,...) GNUNET_log_from (kind, "mesh-api",__VA_ARGS__) 42#define LOG(kind,...) GNUNET_log_from (kind, "mesh-api",__VA_ARGS__)
43
44#define DEBUG_ACK GNUNET_YES 43#define DEBUG_ACK GNUNET_YES
45 44
46/******************************************************************************/ 45/******************************************************************************/
@@ -95,12 +94,6 @@ struct GNUNET_MESH_TransmitHandle
95 GNUNET_SCHEDULER_TaskIdentifier timeout_task; 94 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
96 95
97 /** 96 /**
98 * Target of the message, 0 for multicast. This field
99 * is only valid if 'notify' is non-NULL.
100 */
101 GNUNET_PEER_Id target;
102
103 /**
104 * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL. 97 * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL.
105 */ 98 */
106 size_t size; 99 size_t size;
@@ -123,13 +116,20 @@ struct GNUNET_MESH_Handle
123 */ 116 */
124 const struct GNUNET_MESH_MessageHandler *message_handlers; 117 const struct GNUNET_MESH_MessageHandler *message_handlers;
125 118
126 /** 119 /**
127 * Set of applications that should be claimed to be offered at this node. 120 * Number of handlers in the handlers array.
128 * Note that this is just informative, the appropiate handlers must be 121 */
129 * registered independently and the mapping is up to the developer of the 122 unsigned int n_handlers;
130 * client application. 123
131 */ 124 /**
132 GNUNET_MESH_ApplicationType *applications; 125 * Ports open.
126 */
127 const uint32_t *ports;
128
129 /**
130 * Number of ports.
131 */
132 unsigned int n_ports;
133 133
134 /** 134 /**
135 * Double linked list of the tunnels this client is connected to, head. 135 * Double linked list of the tunnels this client is connected to, head.
@@ -177,16 +177,6 @@ struct GNUNET_MESH_Handle
177 MESH_TunnelNumber next_tid; 177 MESH_TunnelNumber next_tid;
178 178
179 /** 179 /**
180 * Number of handlers in the handlers array.
181 */
182 unsigned int n_handlers;
183
184 /**
185 * Number of applications in the applications array.
186 */
187 unsigned int n_applications;
188
189 /**
190 * Have we started the task to receive messages from the service 180 * Have we started the task to receive messages from the service
191 * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message. 181 * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message.
192 */ 182 */
@@ -227,16 +217,6 @@ struct GNUNET_MESH_Handle
227 */ 217 */
228 void *tunnel_cls; 218 void *tunnel_cls;
229 219
230 /**
231 * All the peer in the tunnel so far.
232 */
233 struct GNUNET_PeerIdentity *peers;
234
235 /**
236 * How many peers we have in this tunnel so far.
237 */
238 unsigned int tunnel_npeers;
239
240#if DEBUG_ACK 220#if DEBUG_ACK
241 unsigned int acks_sent; 221 unsigned int acks_sent;
242 unsigned int acks_recv; 222 unsigned int acks_recv;
@@ -284,21 +264,6 @@ struct GNUNET_MESH_Tunnel
284 struct GNUNET_MESH_Tunnel *prev; 264 struct GNUNET_MESH_Tunnel *prev;
285 265
286 /** 266 /**
287 * Callback to execute when peers connect to the tunnel
288 */
289 GNUNET_MESH_PeerConnectHandler connect_handler;
290
291 /**
292 * Callback to execute when peers disconnect from the tunnel
293 */
294 GNUNET_MESH_PeerDisconnectHandler disconnect_handler;
295
296 /**
297 * Closure for the connect/disconnect handlers
298 */
299 void *cls;
300
301 /**
302 * Handle to the mesh this tunnel belongs to 267 * Handle to the mesh this tunnel belongs to
303 */ 268 */
304 struct GNUNET_MESH_Handle *mesh; 269 struct GNUNET_MESH_Handle *mesh;
@@ -309,69 +274,67 @@ struct GNUNET_MESH_Tunnel
309 MESH_TunnelNumber tid; 274 MESH_TunnelNumber tid;
310 275
311 /** 276 /**
312 * Owner of the tunnel. 0 if the tunnel is the local client. 277 * Port number.
313 */ 278 */
314 GNUNET_PEER_Id owner; 279 uint32_t port;
315 280
316 /** 281 /**
317 * All peers added to the tunnel 282 * Other end of the tunnel.
318 */ 283 */
319 struct GNUNET_MESH_Peer **peers; 284 GNUNET_PEER_Id peer;
320
321 /**
322 * List of application types that have been requested for this tunnel
323 */
324 GNUNET_MESH_ApplicationType *apps;
325 285
326 /** 286 /**
327 * Any data the caller wants to put in here 287 * Any data the caller wants to put in here
328 */ 288 */
329 void *ctx; 289 void *ctx;
330 290
331 /**
332 * Number of peers added to the tunnel
333 */
334 unsigned int npeers;
335
336 /** 291 /**
337 * Size of packet queued in this tunnel 292 * Size of packet queued in this tunnel
338 */ 293 */
339 unsigned int packet_size; 294 unsigned int packet_size;
340 295
341 /** 296 /**
342 * Number of applications requested this tunnel
343 */
344 unsigned int napps;
345
346 /**
347 * Is the tunnel throttled to the slowest peer?
348 */
349 int speed_min;
350
351 /**
352 * Is the tunnel allowed to buffer? 297 * Is the tunnel allowed to buffer?
353 */ 298 */
354 int buffering; 299 int buffering;
355 300
356 /** 301 /**
357 * Next packet ID to send. 302 * Maximum allowed PID to send (last ACK recevied).
358 */ 303 */
359 uint32_t next_send_pid; 304 uint32_t last_ack_recv;
360 305
361 /** 306 /**
362 * Maximum allowed PID to send (ACK recevied). 307 * Last PID received from the service.
363 */ 308 */
364 uint32_t max_send_pid; 309 uint32_t last_pid_recv;
310
311 /**
312 * Last packet ID sent to the service.
313 */
314 uint32_t last_pid_sent;
315
316 /**
317 * Last ACK value sent to the service: how much are we willing to accept?
318 */
319 uint32_t last_ack_sent;
320};
365 321
366 /** 322
367 * Last pid received from the service. 323/**
368 */ 324 * Implementation state for mesh's message queue.
369 uint32_t last_recv_pid; 325 */
326struct MeshMQState
327{
328 /**
329 * The current transmit handle, or NULL
330 * if no transmit is active.
331 */
332 struct GNUNET_MESH_TransmitHandle *th;
370 333
371 /** 334 /**
372 * Which ACK value have we last sent to the service? 335 * Tunnel to send the data over.
373 */ 336 */
374 uint32_t max_recv_pid; 337 struct GNUNET_MESH_Tunnel *tunnel;
375}; 338};
376 339
377 340
@@ -431,13 +394,13 @@ message_ready_size (struct GNUNET_MESH_Handle *h)
431 t = th->tunnel; 394 t = th->tunnel;
432 if (GNUNET_NO == th_is_payload (th)) 395 if (GNUNET_NO == th_is_payload (th))
433 { 396 {
434 LOG (GNUNET_ERROR_TYPE_DEBUG, " message internal\n"); 397 LOG (GNUNET_ERROR_TYPE_DEBUG, "# message internal\n");
435 return th->size; 398 return th->size;
436 } 399 }
437 if (GNUNET_NO == GMC_is_pid_bigger(t->next_send_pid, t->max_send_pid)) 400 if (GNUNET_YES == GMC_is_pid_bigger(t->last_ack_recv, t->last_pid_sent))
438 { 401 {
439 LOG (GNUNET_ERROR_TYPE_DEBUG, " message payload ok (%u <= %u)\n", 402 LOG (GNUNET_ERROR_TYPE_DEBUG, "# message payload ok (%u =< %u)\n",
440 t->next_send_pid, t->max_send_pid); 403 t->last_pid_sent + 1, t->last_ack_recv);
441 return th->size; 404 return th->size;
442 } 405 }
443 } 406 }
@@ -495,8 +458,10 @@ create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
495 { 458 {
496 t->tid = tid; 459 t->tid = tid;
497 } 460 }
498 t->max_send_pid = INITIAL_WINDOW_SIZE - 1; 461 t->last_ack_recv = (uint32_t) -1;
499 t->last_recv_pid = (uint32_t) -1; 462 t->last_pid_recv = (uint32_t) -1;
463 t->last_ack_sent = (uint32_t) -1;
464 t->last_pid_sent = (uint32_t) -1;
500 t->buffering = GNUNET_YES; 465 t->buffering = GNUNET_YES;
501 return t; 466 return t;
502} 467}
@@ -518,10 +483,8 @@ static void
518destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner) 483destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner)
519{ 484{
520 struct GNUNET_MESH_Handle *h; 485 struct GNUNET_MESH_Handle *h;
521 struct GNUNET_PeerIdentity pi;
522 struct GNUNET_MESH_TransmitHandle *th; 486 struct GNUNET_MESH_TransmitHandle *th;
523 struct GNUNET_MESH_TransmitHandle *next; 487 struct GNUNET_MESH_TransmitHandle *next;
524 unsigned int i;
525 488
526 LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid); 489 LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid);
527 490
@@ -532,21 +495,10 @@ destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner)
532 } 495 }
533 h = t->mesh; 496 h = t->mesh;
534 497
535 /* disconnect all peers */
536 GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t); 498 GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t);
537 for (i = 0; i < t->npeers; i++)
538 {
539 if ( (NULL != t->disconnect_handler) && t->peers[i]->connected)
540 {
541 GNUNET_PEER_resolve (t->peers[i]->id, &pi);
542 t->disconnect_handler (t->cls, &pi);
543 }
544 GNUNET_PEER_change_rc (t->peers[i]->id, -1);
545 GNUNET_free (t->peers[i]);
546 }
547 499
548 /* signal tunnel destruction */ 500 /* signal tunnel destruction */
549 if ( (NULL != h->cleaner) && (0 != t->owner) && (GNUNET_YES == call_cleaner) ) 501 if ( (NULL != h->cleaner) && (0 != t->peer) && (GNUNET_YES == call_cleaner) )
550 h->cleaner (h->cls, t, t->ctx); 502 h->cleaner (h->cls, t, t->ctx);
551 503
552 /* check that clients did not leave messages behind in the queue */ 504 /* check that clients did not leave messages behind in the queue */
@@ -574,89 +526,14 @@ destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner)
574 h->th = NULL; 526 h->th = NULL;
575 } 527 }
576 528
577 529 if (0 != t->peer)
578 if (t->npeers > 0) 530 GNUNET_PEER_change_rc (t->peer, -1);
579 GNUNET_free (t->peers);
580 if (0 != t->owner)
581 GNUNET_PEER_change_rc (t->owner, -1);
582 if (0 != t->napps && t->apps)
583 GNUNET_free (t->apps);
584 GNUNET_free (t); 531 GNUNET_free (t);
585 return; 532 return;
586} 533}
587 534
588 535
589/** 536/**
590 * Get the peer descriptor for the peer with id from the given tunnel
591 * @param t Tunnel handle
592 * @param id Short form ID of the wanted peer
593 * @return handle to the requested peer or NULL if not found
594 */
595static struct GNUNET_MESH_Peer *
596retrieve_peer (struct GNUNET_MESH_Tunnel *t, GNUNET_PEER_Id id)
597{
598 unsigned int i;
599
600 for (i = 0; i < t->npeers; i++)
601 if (t->peers[i]->id == id)
602 return t->peers[i];
603 return NULL;
604}
605
606
607/**
608 * Add a peer into a tunnel
609 * @param t Tunnel handle
610 * @param pi Full ID of the new peer
611 * @return handle to the newly created peer
612 */
613static struct GNUNET_MESH_Peer *
614add_peer_to_tunnel (struct GNUNET_MESH_Tunnel *t,
615 const struct GNUNET_PeerIdentity *pi)
616{
617 struct GNUNET_MESH_Peer *p;
618 GNUNET_PEER_Id id;
619
620 if (0 != t->owner)
621 {
622 GNUNET_break (0);
623 return NULL;
624 }
625 id = GNUNET_PEER_intern (pi);
626
627 p = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
628 p->id = id;
629 p->t = t;
630 GNUNET_array_append (t->peers, t->npeers, p);
631 return p;
632}
633
634
635/**
636 * Remove a peer from a tunnel
637 * @param p Peer handle
638 */
639static void
640remove_peer_from_tunnel (struct GNUNET_MESH_Peer *p)
641{
642 unsigned int i;
643
644 for (i = 0; i < p->t->npeers; i++)
645 {
646 if (p->t->peers[i] == p)
647 break;
648 }
649 if (i == p->t->npeers)
650 {
651 GNUNET_break (0);
652 return;
653 }
654 p->t->peers[i] = p->t->peers[p->t->npeers - 1];
655 GNUNET_array_grow (p->t->peers, p->t->npeers, p->t->npeers - 1);
656}
657
658
659/**
660 * Notify client that the transmission has timed out 537 * Notify client that the transmission has timed out
661 * 538 *
662 * @param cls closure 539 * @param cls closure
@@ -725,36 +602,24 @@ send_packet (struct GNUNET_MESH_Handle *h,
725 * @param t Tunnel on which to send the ACK. 602 * @param t Tunnel on which to send the ACK.
726 */ 603 */
727static void 604static void
728send_ack (struct GNUNET_MESH_Handle *h, struct GNUNET_MESH_Tunnel *t) 605send_ack (struct GNUNET_MESH_Tunnel *t)
729{ 606{
730 struct GNUNET_MESH_LocalAck msg; 607 struct GNUNET_MESH_LocalAck msg;
731 uint32_t delta;
732 608
733 delta = t->max_recv_pid - t->last_recv_pid; 609 t->last_ack_sent = t->last_pid_recv + 1;
734 if (delta > ACK_THRESHOLD)
735 {
736 LOG (GNUNET_ERROR_TYPE_DEBUG,
737 "Not sending ACK on tunnel %X: ACK: %u, PID: %u, buffer %u\n",
738 t->tid, t->max_recv_pid, t->last_recv_pid, delta);
739 return;
740 }
741 if (GNUNET_YES == t->buffering)
742 t->max_recv_pid = t->last_recv_pid + INITIAL_WINDOW_SIZE;
743 else
744 t->max_recv_pid = t->last_recv_pid + 1;
745 LOG (GNUNET_ERROR_TYPE_DEBUG, 610 LOG (GNUNET_ERROR_TYPE_DEBUG,
746 "Sending ACK on tunnel %X: %u\n", 611 "Sending ACK on tunnel %X: %u\n",
747 t->tid, t->max_recv_pid); 612 t->tid, t->last_ack_sent);
748 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); 613 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
749 msg.header.size = htons (sizeof (msg)); 614 msg.header.size = htons (sizeof (msg));
750 msg.tunnel_id = htonl (t->tid); 615 msg.tunnel_id = htonl (t->tid);
751 msg.max_pid = htonl (t->max_recv_pid); 616 msg.ack = htonl (t->last_ack_sent);
752 617
753#if DEBUG_ACK 618#if DEBUG_ACK
754 t->mesh->acks_sent++; 619 t->mesh->acks_sent++;
755#endif 620#endif
756 621
757 send_packet (h, &msg.header, t); 622 send_packet (t->mesh, &msg.header, t);
758 return; 623 return;
759} 624}
760 625
@@ -783,39 +648,27 @@ send_connect (struct GNUNET_MESH_Handle *h)
783 size_t size; 648 size_t size;
784 649
785 size = sizeof (struct GNUNET_MESH_ClientConnect); 650 size = sizeof (struct GNUNET_MESH_ClientConnect);
786 size += h->n_applications * sizeof (GNUNET_MESH_ApplicationType); 651 size += h->n_ports * sizeof (uint32_t);
787 size += h->n_handlers * sizeof (uint16_t);
788 { 652 {
789 char buf[size] GNUNET_ALIGN; 653 char buf[size] GNUNET_ALIGN;
790 struct GNUNET_MESH_ClientConnect *msg; 654 struct GNUNET_MESH_ClientConnect *msg;
791 GNUNET_MESH_ApplicationType *apps; 655 uint32_t *ports;
792 uint16_t napps; 656 uint16_t i;
793 uint16_t *types;
794 uint16_t ntypes;
795 657
796 /* build connection packet */ 658 /* build connection packet */
797 msg = (struct GNUNET_MESH_ClientConnect *) buf; 659 msg = (struct GNUNET_MESH_ClientConnect *) buf;
798 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT); 660 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT);
799 msg->header.size = htons (size); 661 msg->header.size = htons (size);
800 apps = (GNUNET_MESH_ApplicationType *) &msg[1]; 662 ports = (uint32_t *) &msg[1];
801 for (napps = 0; napps < h->n_applications; napps++) 663 for (i = 0; i < h->n_ports; i++)
802 {
803 apps[napps] = htonl (h->applications[napps]);
804 LOG (GNUNET_ERROR_TYPE_DEBUG, " app %u\n",
805 h->applications[napps]);
806 }
807 types = (uint16_t *) & apps[napps];
808 for (ntypes = 0; ntypes < h->n_handlers; ntypes++)
809 { 664 {
810 types[ntypes] = htons (h->message_handlers[ntypes].type); 665 ports[i] = htonl (h->ports[i]);
811 LOG (GNUNET_ERROR_TYPE_DEBUG, " type %u\n", 666 LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n",
812 h->message_handlers[ntypes].type); 667 h->ports[i]);
813 } 668 }
814 msg->applications = htons (napps);
815 msg->types = htons (ntypes);
816 LOG (GNUNET_ERROR_TYPE_DEBUG, 669 LOG (GNUNET_ERROR_TYPE_DEBUG,
817 "Sending %lu bytes long message %d types and %d apps\n", 670 "Sending %lu bytes long message with %u ports\n",
818 ntohs (msg->header.size), ntypes, napps); 671 ntohs (msg->header.size), h->n_ports);
819 send_packet (h, &msg->header, NULL); 672 send_packet (h, &msg->header, NULL);
820 } 673 }
821} 674}
@@ -833,7 +686,6 @@ static int
833do_reconnect (struct GNUNET_MESH_Handle *h) 686do_reconnect (struct GNUNET_MESH_Handle *h)
834{ 687{
835 struct GNUNET_MESH_Tunnel *t; 688 struct GNUNET_MESH_Tunnel *t;
836 unsigned int i;
837 689
838 LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n"); 690 LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
839 LOG (GNUNET_ERROR_TYPE_DEBUG, "******* RECONNECT *******\n"); 691 LOG (GNUNET_ERROR_TYPE_DEBUG, "******* RECONNECT *******\n");
@@ -878,7 +730,6 @@ do_reconnect (struct GNUNET_MESH_Handle *h)
878 for (t = h->tunnels_head; NULL != t; t = t->next) 730 for (t = h->tunnels_head; NULL != t; t = t->next)
879 { 731 {
880 struct GNUNET_MESH_TunnelMessage tmsg; 732 struct GNUNET_MESH_TunnelMessage tmsg;
881 struct GNUNET_MESH_PeerControl pmsg;
882 733
883 if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) 734 if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
884 { 735 {
@@ -888,42 +739,18 @@ do_reconnect (struct GNUNET_MESH_Handle *h)
888 */ 739 */
889 continue; 740 continue;
890 } 741 }
891 t->next_send_pid = 0; 742 t->last_ack_sent = (uint32_t) -1;
892 t->max_send_pid = INITIAL_WINDOW_SIZE - 1; 743 t->last_pid_sent = (uint32_t) -1;
893 t->last_recv_pid = (uint32_t) -1; 744 t->last_ack_recv = (uint32_t) -1;
745 t->last_pid_recv = (uint32_t) -1;
894 tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); 746 tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
895 tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); 747 tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
896 tmsg.tunnel_id = htonl (t->tid); 748 tmsg.tunnel_id = htonl (t->tid);
749 GNUNET_PEER_resolve (t->peer, &tmsg.peer);
897 send_packet (h, &tmsg.header, t); 750 send_packet (h, &tmsg.header, t);
898 751
899 pmsg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
900 pmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
901 pmsg.tunnel_id = htonl (t->tid);
902
903 /* Reconnect all peers */
904 /* If the tunnel was "by type", dont connect individual peers */
905 for (i = 0; i < t->npeers && 0 == t->napps; i++)
906 {
907 GNUNET_PEER_resolve (t->peers[i]->id, &pmsg.peer);
908 if (NULL != t->disconnect_handler && t->peers[i]->connected)
909 t->disconnect_handler (t->cls, &pmsg.peer);
910 send_packet (t->mesh, &pmsg.header, t);
911 }
912 /* Reconnect all types, if any */
913 for (i = 0; i < t->napps; i++)
914 {
915 struct GNUNET_MESH_ConnectPeerByType msg;
916
917 msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
918 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
919 msg.tunnel_id = htonl (t->tid);
920 msg.type = htonl (t->apps[i]);
921 send_packet (t->mesh, &msg.header, t);
922 }
923 if (GNUNET_NO == t->buffering) 752 if (GNUNET_NO == t->buffering)
924 GNUNET_MESH_tunnel_buffer (t, GNUNET_NO); 753 GNUNET_MESH_tunnel_buffer (t, GNUNET_NO);
925 if (GNUNET_YES == t->speed_min)
926 GNUNET_MESH_tunnel_speed_min (t);
927 } 754 }
928 return GNUNET_YES; 755 return GNUNET_YES;
929} 756}
@@ -991,29 +818,18 @@ process_tunnel_created (struct GNUNET_MESH_Handle *h,
991 } 818 }
992 if (NULL != h->new_tunnel) 819 if (NULL != h->new_tunnel)
993 { 820 {
994 struct GNUNET_ATS_Information atsi;
995
996 t = create_tunnel (h, tid); 821 t = create_tunnel (h, tid);
997 t->owner = GNUNET_PEER_intern (&msg->peer); 822 t->last_ack_sent = 0;
998 t->npeers = 1; 823 t->peer = GNUNET_PEER_intern (&msg->peer);
999 t->peers = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer *));
1000 t->peers[0] = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
1001 t->peers[0]->t = t;
1002 t->peers[0]->connected = 1;
1003 t->peers[0]->id = t->owner;
1004 GNUNET_PEER_change_rc (t->owner, 1);
1005 t->mesh = h; 824 t->mesh = h;
1006 t->tid = tid; 825 t->tid = tid;
1007 if ((msg->opt & MESH_TUNNEL_OPT_NOBUFFER) != 0) 826 t->port = ntohl (msg->port);
827 if (0 != (msg->opt & MESH_TUNNEL_OPT_NOBUFFER))
1008 t->buffering = GNUNET_NO; 828 t->buffering = GNUNET_NO;
1009 else 829 else
1010 t->buffering = GNUNET_YES; 830 t->buffering = GNUNET_YES;
1011 if ((msg->opt & MESH_TUNNEL_OPT_SPEED_MIN) != 0)
1012 t->speed_min = GNUNET_YES;
1013 atsi.type = 0;
1014 atsi.value = 0;
1015 LOG (GNUNET_ERROR_TYPE_DEBUG, " created tunnel %p\n", t); 831 LOG (GNUNET_ERROR_TYPE_DEBUG, " created tunnel %p\n", t);
1016 t->ctx = h->new_tunnel (h->cls, t, &msg->peer, &atsi); 832 t->ctx = h->new_tunnel (h->cls, t, &msg->peer, t->port);
1017 LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n"); 833 LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n");
1018 } 834 }
1019 else 835 else
@@ -1052,10 +868,6 @@ process_tunnel_destroy (struct GNUNET_MESH_Handle *h,
1052 { 868 {
1053 return; 869 return;
1054 } 870 }
1055 if (0 == t->owner)
1056 {
1057 GNUNET_break (0);
1058 }
1059 LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid); 871 LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid);
1060 destroy_tunnel (t, GNUNET_YES); 872 destroy_tunnel (t, GNUNET_YES);
1061 return; 873 return;
@@ -1063,81 +875,20 @@ process_tunnel_destroy (struct GNUNET_MESH_Handle *h,
1063 875
1064 876
1065/** 877/**
1066 * Process the new peer event and notify the upper level of it 878 * Process the incoming data packets, call appropriate handlers.
1067 *
1068 * @param h The mesh handle
1069 * @param msg A message with the details of the peer event
1070 */
1071static void
1072process_peer_event (struct GNUNET_MESH_Handle *h,
1073 const struct GNUNET_MESH_PeerControl *msg)
1074{
1075 struct GNUNET_MESH_Tunnel *t;
1076 struct GNUNET_MESH_Peer *p;
1077 struct GNUNET_ATS_Information atsi;
1078 GNUNET_PEER_Id id;
1079 uint16_t size;
1080
1081 LOG (GNUNET_ERROR_TYPE_DEBUG, "processig peer event\n");
1082 size = ntohs (msg->header.size);
1083 if (size != sizeof (struct GNUNET_MESH_PeerControl))
1084 {
1085 GNUNET_break (0);
1086 return;
1087 }
1088 t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
1089 if (NULL == t)
1090 {
1091 GNUNET_break (0);
1092 return;
1093 }
1094 id = GNUNET_PEER_search (&msg->peer);
1095 if ((p = retrieve_peer (t, id)) == NULL)
1096 p = add_peer_to_tunnel (t, &msg->peer);
1097 if (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD == ntohs (msg->header.type))
1098 {
1099 LOG (GNUNET_ERROR_TYPE_DEBUG, "adding peer\n");
1100 if (NULL != t->connect_handler)
1101 {
1102 atsi.type = 0;
1103 atsi.value = 0;
1104 t->connect_handler (t->cls, &msg->peer, &atsi);
1105 }
1106 p->connected = 1;
1107 }
1108 else
1109 {
1110 LOG (GNUNET_ERROR_TYPE_DEBUG, "removing peer\n");
1111 if (NULL != t->disconnect_handler && p->connected)
1112 {
1113 t->disconnect_handler (t->cls, &msg->peer);
1114 }
1115 remove_peer_from_tunnel (p);
1116 GNUNET_free (p);
1117 }
1118 LOG (GNUNET_ERROR_TYPE_DEBUG, "processing peer event END\n");
1119}
1120
1121
1122/**
1123 * Process the incoming data packets
1124 * 879 *
1125 * @param h The mesh handle 880 * @param h The mesh handle
1126 * @param message A message encapsulating the data 881 * @param message A message encapsulating the data
1127 *
1128 * @return GNUNET_YES if everything went fine
1129 * GNUNET_NO if client closed connection (h no longer valid)
1130 */ 882 */
1131static int 883static void
1132process_incoming_data (struct GNUNET_MESH_Handle *h, 884process_incoming_data (struct GNUNET_MESH_Handle *h,
1133 const struct GNUNET_MessageHeader *message) 885 const struct GNUNET_MessageHeader *message)
1134{ 886{
1135 const struct GNUNET_MessageHeader *payload; 887 const struct GNUNET_MessageHeader *payload;
1136 const struct GNUNET_MESH_MessageHandler *handler; 888 const struct GNUNET_MESH_MessageHandler *handler;
1137 const struct GNUNET_PeerIdentity *peer; 889 const struct GNUNET_PeerIdentity *peer;
1138 struct GNUNET_MESH_Unicast *ucast; 890 struct GNUNET_PeerIdentity id;
1139 struct GNUNET_MESH_Multicast *mcast; 891 struct GNUNET_MESH_Data *dmsg;
1140 struct GNUNET_MESH_ToOrigin *to_orig;
1141 struct GNUNET_MESH_Tunnel *t; 892 struct GNUNET_MESH_Tunnel *t;
1142 unsigned int i; 893 unsigned int i;
1143 uint32_t pid; 894 uint32_t pid;
@@ -1148,72 +899,52 @@ process_incoming_data (struct GNUNET_MESH_Handle *h,
1148 switch (type) 899 switch (type)
1149 { 900 {
1150 case GNUNET_MESSAGE_TYPE_MESH_UNICAST: 901 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1151 ucast = (struct GNUNET_MESH_Unicast *) message;
1152
1153 t = retrieve_tunnel (h, ntohl (ucast->tid));
1154 payload = (struct GNUNET_MessageHeader *) &ucast[1];
1155 peer = &ucast->oid;
1156 pid = ntohl (ucast->pid);
1157 LOG (GNUNET_ERROR_TYPE_DEBUG, " ucast on tunnel %s [%X]\n",
1158 GNUNET_i2s (peer), ntohl (ucast->tid));
1159 break;
1160 case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1161 mcast = (struct GNUNET_MESH_Multicast *) message;
1162 t = retrieve_tunnel (h, ntohl (mcast->tid));
1163 payload = (struct GNUNET_MessageHeader *) &mcast[1];
1164 peer = &mcast->oid;
1165 pid = ntohl (mcast->pid);
1166 LOG (GNUNET_ERROR_TYPE_DEBUG, " mcast on tunnel %s [%X]\n",
1167 GNUNET_i2s (peer), ntohl (mcast->tid));
1168 break;
1169 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: 902 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1170 to_orig = (struct GNUNET_MESH_ToOrigin *) message; 903 dmsg = (struct GNUNET_MESH_Data *) message;
1171 t = retrieve_tunnel (h, ntohl (to_orig->tid)); 904
1172 payload = (struct GNUNET_MessageHeader *) &to_orig[1]; 905 t = retrieve_tunnel (h, ntohl (dmsg->tid));
1173 peer = &to_orig->sender; 906 payload = (struct GNUNET_MessageHeader *) &dmsg[1];
1174 pid = ntohl (to_orig->pid); 907 GNUNET_PEER_resolve (t->peer, &id);
1175 LOG (GNUNET_ERROR_TYPE_DEBUG, " torig on tunnel %s [%X]\n", 908 peer = &id;
1176 GNUNET_i2s (peer), ntohl (to_orig->tid)); 909 pid = ntohl (dmsg->pid);
910 LOG (GNUNET_ERROR_TYPE_DEBUG, " %s data on tunnel %s [%X]\n",
911 type == GNUNET_MESSAGE_TYPE_MESH_UNICAST ? "fwd" : "bck",
912 GNUNET_i2s (peer), ntohl (dmsg->tid));
1177 break; 913 break;
1178 default: 914 default:
1179 GNUNET_break (0); 915 GNUNET_break (0);
1180 return GNUNET_YES; 916 return;
1181 } 917 }
1182 LOG (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", pid); 918 LOG (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", pid);
1183 if (NULL == t) 919 if (NULL == t)
1184 { 920 {
1185 /* Tunnel was ignored/destroyed, probably service didn't get it yet */ 921 /* Tunnel was ignored/destroyed, probably service didn't get it yet */
1186 LOG (GNUNET_ERROR_TYPE_DEBUG, " ignored!\n"); 922 LOG (GNUNET_ERROR_TYPE_DEBUG, " ignored!\n");
1187 return GNUNET_YES; 923 return;
1188 } 924 }
1189 if (GNUNET_YES == 925 if (GNUNET_YES ==
1190 GMC_is_pid_bigger(pid, t->max_recv_pid)) 926 GMC_is_pid_bigger(pid, t->last_ack_sent))
1191 { 927 {
1192 GNUNET_break (0); 928 GNUNET_break (0);
1193 LOG (GNUNET_ERROR_TYPE_WARNING, 929 LOG (GNUNET_ERROR_TYPE_WARNING,
1194 " unauthorized message! (%u, max %u)\n", 930 " unauthorized message! (%u, ACK %u)\n",
1195 pid, t->max_recv_pid); 931 pid, t->last_ack_sent);
1196 // FIXME fc what now? accept? reject? 932 // FIXME fc what now? accept? reject?
1197 return GNUNET_YES; 933 return;
1198 } 934 }
1199 t->last_recv_pid = pid; 935 t->last_pid_recv = pid;
1200 type = ntohs (payload->type); 936 type = ntohs (payload->type);
1201 send_ack (h, t);
1202 for (i = 0; i < h->n_handlers; i++) 937 for (i = 0; i < h->n_handlers; i++)
1203 { 938 {
1204 handler = &h->message_handlers[i]; 939 handler = &h->message_handlers[i];
1205 if (handler->type == type) 940 if (handler->type == type)
1206 { 941 {
1207 struct GNUNET_ATS_Information atsi;
1208
1209 atsi.type = 0;
1210 atsi.value = 0;
1211 if (GNUNET_OK != 942 if (GNUNET_OK !=
1212 handler->callback (h->cls, t, &t->ctx, peer, payload, &atsi)) 943 handler->callback (h->cls, t, &t->ctx, payload))
1213 { 944 {
1214 LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n"); 945 LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n");
1215 GNUNET_MESH_disconnect (h); 946 GNUNET_MESH_tunnel_destroy (t);
1216 return GNUNET_NO; 947 return;
1217 } 948 }
1218 else 949 else
1219 { 950 {
@@ -1222,7 +953,6 @@ process_incoming_data (struct GNUNET_MESH_Handle *h,
1222 } 953 }
1223 } 954 }
1224 } 955 }
1225 return GNUNET_YES;
1226} 956}
1227 957
1228 958
@@ -1254,10 +984,10 @@ process_ack (struct GNUNET_MESH_Handle *h,
1254 ntohl (msg->tunnel_id)); 984 ntohl (msg->tunnel_id));
1255 return; 985 return;
1256 } 986 }
1257 ack = ntohl (msg->max_pid); 987 ack = ntohl (msg->ack);
1258 LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X, ack %u!\n", t->tid, ack); 988 LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X, ack %u!\n", t->tid, ack);
1259 if (GNUNET_YES == GMC_is_pid_bigger(ack, t->max_send_pid)) 989 if (GNUNET_YES == GMC_is_pid_bigger(ack, t->last_ack_recv))
1260 t->max_send_pid = ack; 990 t->last_ack_recv = ack;
1261 else 991 else
1262 return; 992 return;
1263 if (NULL == h->th && 0 < t->packet_size) 993 if (NULL == h->th && 0 < t->packet_size)
@@ -1282,7 +1012,6 @@ process_get_tunnels (struct GNUNET_MESH_Handle *h,
1282 const struct GNUNET_MessageHeader *message) 1012 const struct GNUNET_MessageHeader *message)
1283{ 1013{
1284 struct GNUNET_MESH_LocalMonitor *msg; 1014 struct GNUNET_MESH_LocalMonitor *msg;
1285 uint32_t npeers;
1286 1015
1287 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Tunnels messasge received\n"); 1016 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Tunnels messasge received\n");
1288 1017
@@ -1293,25 +1022,21 @@ process_get_tunnels (struct GNUNET_MESH_Handle *h,
1293 } 1022 }
1294 1023
1295 msg = (struct GNUNET_MESH_LocalMonitor *) message; 1024 msg = (struct GNUNET_MESH_LocalMonitor *) message;
1296 npeers = ntohl (msg->npeers);
1297 if (ntohs (message->size) != 1025 if (ntohs (message->size) !=
1298 (sizeof (struct GNUNET_MESH_LocalMonitor) + 1026 (sizeof (struct GNUNET_MESH_LocalMonitor) +
1299 npeers * sizeof (struct GNUNET_PeerIdentity))) 1027 sizeof (struct GNUNET_PeerIdentity)))
1300 { 1028 {
1301 GNUNET_break_op (0); 1029 GNUNET_break_op (0);
1302 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1030 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1303 "Get tunnels message: size %hu - expected %u (%u peers)\n", 1031 "Get tunnels message: size %hu - expected %u\n",
1304 ntohs (message->size), 1032 ntohs (message->size),
1305 sizeof (struct GNUNET_MESH_LocalMonitor) + 1033 sizeof (struct GNUNET_MESH_LocalMonitor));
1306 npeers * sizeof (struct GNUNET_PeerIdentity),
1307 npeers);
1308 return; 1034 return;
1309 } 1035 }
1310 h->tunnels_cb (h->tunnels_cls, 1036 h->tunnels_cb (h->tunnels_cls,
1311 &msg->owner,
1312 ntohl (msg->tunnel_id), 1037 ntohl (msg->tunnel_id),
1313 (struct GNUNET_PeerIdentity *) &msg[1], 1038 &msg->owner,
1314 npeers); 1039 &msg->destination);
1315} 1040}
1316 1041
1317 1042
@@ -1327,11 +1052,7 @@ process_show_tunnel (struct GNUNET_MESH_Handle *h,
1327 const struct GNUNET_MessageHeader *message) 1052 const struct GNUNET_MessageHeader *message)
1328{ 1053{
1329 struct GNUNET_MESH_LocalMonitor *msg; 1054 struct GNUNET_MESH_LocalMonitor *msg;
1330 struct GNUNET_PeerIdentity *new_peers;
1331 uint32_t *new_parents;
1332 size_t esize; 1055 size_t esize;
1333 uint32_t npeers;
1334 unsigned int i;
1335 1056
1336 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Tunnel messasge received\n"); 1057 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Tunnel messasge received\n");
1337 1058
@@ -1343,40 +1064,25 @@ process_show_tunnel (struct GNUNET_MESH_Handle *h,
1343 1064
1344 /* Verify message sanity */ 1065 /* Verify message sanity */
1345 msg = (struct GNUNET_MESH_LocalMonitor *) message; 1066 msg = (struct GNUNET_MESH_LocalMonitor *) message;
1346 npeers = ntohl (msg->npeers);
1347 esize = sizeof (struct GNUNET_MESH_LocalMonitor); 1067 esize = sizeof (struct GNUNET_MESH_LocalMonitor);
1348 esize += npeers * (sizeof (struct GNUNET_PeerIdentity) + sizeof (uint32_t));
1349 if (ntohs (message->size) != esize) 1068 if (ntohs (message->size) != esize)
1350 { 1069 {
1351 GNUNET_break_op (0); 1070 GNUNET_break_op (0);
1352 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1071 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1353 "Show tunnel message: size %hu - expected %u (%u peers)\n", 1072 "Show tunnel message: size %hu - expected %u\n",
1354 ntohs (message->size), 1073 ntohs (message->size),
1355 esize, 1074 esize);
1356 npeers);
1357 1075
1358 h->tunnel_cb (h->tunnel_cls, NULL, NULL); 1076 h->tunnel_cb (h->tunnel_cls, NULL, NULL);
1359 h->tunnel_cb = NULL; 1077 h->tunnel_cb = NULL;
1360 h->tunnel_cls = NULL; 1078 h->tunnel_cls = NULL;
1361 h->tunnel_npeers = 0;
1362 GNUNET_free_non_null (h->peers);
1363 h->peers = NULL;
1364 1079
1365 return; 1080 return;
1366 } 1081 }
1367 1082
1368 new_peers = (struct GNUNET_PeerIdentity *) &msg[1]; 1083 h->tunnel_cb (h->tunnel_cls,
1369 new_parents = (uint32_t *) &new_peers[npeers]; 1084 &msg->destination,
1370 1085 &msg->owner);
1371 h->peers = GNUNET_realloc (h->peers, h->tunnel_npeers + npeers);
1372 memcpy (&h->peers[h->tunnel_npeers],
1373 new_peers,
1374 npeers * sizeof (struct GNUNET_PeerIdentity));
1375 h->tunnel_npeers += npeers;
1376 for (i = 0; i < npeers; i++)
1377 h->tunnel_cb (h->tunnel_cls,
1378 &new_peers[i],
1379 &h->peers[new_parents[i]]);
1380} 1086}
1381 1087
1382 1088
@@ -1412,17 +1118,11 @@ msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
1412 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY: 1118 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1413 process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg); 1119 process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg);
1414 break; 1120 break;
1415 /* Notify of a new peer or a peer disconnect in the tunnel */
1416 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD:
1417 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL:
1418 process_peer_event (h, (struct GNUNET_MESH_PeerControl *) msg);
1419 break;
1420 /* Notify of a new data packet in the tunnel */ 1121 /* Notify of a new data packet in the tunnel */
1421 case GNUNET_MESSAGE_TYPE_MESH_UNICAST: 1122 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1422 case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: 1123 case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1423 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: 1124 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1424 if (GNUNET_NO == process_incoming_data (h, msg)) 1125 process_incoming_data (h, msg);
1425 return;
1426 break; 1126 break;
1427 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: 1127 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
1428 process_ack (h, msg); 1128 process_ack (h, msg);
@@ -1480,10 +1180,10 @@ send_callback (void *cls, size_t size, void *buf)
1480 size_t nsize; 1180 size_t nsize;
1481 1181
1482 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); 1182 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
1483 LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() Buffer %u\n", size); 1183 LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() Buffer %u\n", size);
1484 if ((0 == size) || (NULL == buf)) 1184 if ((0 == size) || (NULL == buf))
1485 { 1185 {
1486 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received NULL send callback on %p\n", h); 1186 LOG (GNUNET_ERROR_TYPE_DEBUG, "# Received NULL send callback on %p\n", h);
1487 reconnect (h); 1187 reconnect (h);
1488 h->th = NULL; 1188 h->th = NULL;
1489 return 0; 1189 return 0;
@@ -1496,95 +1196,52 @@ send_callback (void *cls, size_t size, void *buf)
1496 t = th->tunnel; 1196 t = th->tunnel;
1497 if (GNUNET_YES == th_is_payload (th)) 1197 if (GNUNET_YES == th_is_payload (th))
1498 { 1198 {
1499 LOG (GNUNET_ERROR_TYPE_DEBUG, " payload\n"); 1199 struct GNUNET_MESH_Data *dmsg;
1500 if (GNUNET_YES == GMC_is_pid_bigger(t->next_send_pid, t->max_send_pid)) 1200 struct GNUNET_MessageHeader *mh;
1201
1202 LOG (GNUNET_ERROR_TYPE_DEBUG, "# payload\n");
1203 if (GNUNET_NO == GMC_is_pid_bigger (t->last_ack_recv, t->last_pid_sent))
1501 { 1204 {
1502 /* This tunnel is not ready to transmit yet, try next message */ 1205 /* This tunnel is not ready to transmit yet, try next message */
1503 next = th->next; 1206 next = th->next;
1504 continue; 1207 continue;
1505 } 1208 }
1506 t->packet_size = 0; 1209 t->packet_size = 0;
1507 if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) 1210 GNUNET_assert (size >= th->size);
1211 dmsg = (struct GNUNET_MESH_Data *) cbuf;
1212 mh = (struct GNUNET_MessageHeader *) &dmsg[1];
1213 psize = th->notify (th->notify_cls,
1214 size - sizeof (struct GNUNET_MESH_Data),
1215 mh);
1216 if (psize > 0)
1508 { 1217 {
1509 /* traffic to origin */ 1218 psize += sizeof (struct GNUNET_MESH_Data);
1510 struct GNUNET_MESH_ToOrigin to; 1219 GNUNET_assert (size >= psize);
1511 struct GNUNET_MessageHeader *mh; 1220 dmsg->header.size = htons (psize);
1512 1221 dmsg->tid = htonl (t->tid);
1513 GNUNET_assert (size >= th->size); 1222 dmsg->pid = htonl (t->last_pid_sent + 1);
1514 mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (to)]; 1223 dmsg->ttl = 0;
1515 psize = th->notify (th->notify_cls, size - sizeof (to), mh); 1224 memset (&dmsg->oid, 0, sizeof (struct GNUNET_PeerIdentity));
1516 LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin, type %s\n", 1225 t->last_pid_sent++;
1517 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1518 if (psize > 0)
1519 {
1520 psize += sizeof (to);
1521 GNUNET_assert (size >= psize);
1522 to.header.size = htons (psize);
1523 to.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
1524 to.tid = htonl (t->tid);
1525 to.pid = htonl (t->next_send_pid);
1526 to.ttl = 0;
1527 memset (&to.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1528 memset (&to.sender, 0, sizeof (struct GNUNET_PeerIdentity));
1529 memcpy (cbuf, &to, sizeof (to));
1530 }
1531 } 1226 }
1532 else if (th->target == 0) 1227 if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1533 { 1228 {
1534 /* multicast */ 1229 dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
1535 struct GNUNET_MESH_Multicast mc; 1230 LOG (GNUNET_ERROR_TYPE_DEBUG, "# to origin, type %s\n",
1536 struct GNUNET_MessageHeader *mh;
1537
1538 GNUNET_assert (size >= th->size);
1539 mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (mc)];
1540 psize = th->notify (th->notify_cls, size - sizeof (mc), mh);
1541 LOG (GNUNET_ERROR_TYPE_DEBUG, " multicast, type %s\n",
1542 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type))); 1231 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1543 if (psize > 0)
1544 {
1545 psize += sizeof (mc);
1546 GNUNET_assert (size >= psize);
1547 mc.header.size = htons (psize);
1548 mc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
1549 mc.tid = htonl (t->tid);
1550 mc.pid = htonl (t->next_send_pid);
1551 mc.ttl = 0;
1552 memset (&mc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1553 memcpy (cbuf, &mc, sizeof (mc));
1554 }
1555 } 1232 }
1556 else 1233 else
1557 { 1234 {
1558 /* unicast */ 1235 dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
1559 struct GNUNET_MESH_Unicast uc; 1236 LOG (GNUNET_ERROR_TYPE_DEBUG, "# unicast, type %s\n",
1560 struct GNUNET_MessageHeader *mh;
1561
1562 GNUNET_assert (size >= th->size);
1563 mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (uc)];
1564 psize = th->notify (th->notify_cls, size - sizeof (uc), mh);
1565 LOG (GNUNET_ERROR_TYPE_DEBUG, " unicast, type %s\n",
1566 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type))); 1237 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1567 if (psize > 0)
1568 {
1569 psize += sizeof (uc);
1570 GNUNET_assert (size >= psize);
1571 uc.header.size = htons (psize);
1572 uc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
1573 uc.tid = htonl (t->tid);
1574 uc.pid = htonl (t->next_send_pid);
1575 uc.ttl = 0;
1576 memset (&uc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1577 GNUNET_PEER_resolve (th->target, &uc.destination);
1578 memcpy (cbuf, &uc, sizeof (uc));
1579 }
1580 } 1238 }
1581 t->next_send_pid++;
1582 } 1239 }
1583 else 1240 else
1584 { 1241 {
1585 struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1]; 1242 struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1];
1586 1243
1587 LOG (GNUNET_ERROR_TYPE_DEBUG, " mesh traffic, type %s\n", 1244 LOG (GNUNET_ERROR_TYPE_DEBUG, "# mesh traffic, type %s\n",
1588 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type))); 1245 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1589 memcpy (cbuf, &th[1], th->size); 1246 memcpy (cbuf, &th[1], th->size);
1590 psize = th->size; 1247 psize = th->size;
@@ -1599,12 +1256,12 @@ send_callback (void *cls, size_t size, void *buf)
1599 size -= psize; 1256 size -= psize;
1600 tsize += psize; 1257 tsize += psize;
1601 } 1258 }
1602 LOG (GNUNET_ERROR_TYPE_DEBUG, " total size: %u\n", tsize); 1259 LOG (GNUNET_ERROR_TYPE_DEBUG, "# total size: %u\n", tsize);
1603 h->th = NULL; 1260 h->th = NULL;
1604 size = message_ready_size (h); 1261 size = message_ready_size (h);
1605 if (0 != size) 1262 if (0 != size)
1606 { 1263 {
1607 LOG (GNUNET_ERROR_TYPE_DEBUG, " next size: %u\n", size); 1264 LOG (GNUNET_ERROR_TYPE_DEBUG, "# next size: %u\n", size);
1608 h->th = 1265 h->th =
1609 GNUNET_CLIENT_notify_transmit_ready (h->client, size, 1266 GNUNET_CLIENT_notify_transmit_ready (h->client, size,
1610 GNUNET_TIME_UNIT_FOREVER_REL, 1267 GNUNET_TIME_UNIT_FOREVER_REL,
@@ -1613,18 +1270,18 @@ send_callback (void *cls, size_t size, void *buf)
1613 else 1270 else
1614 { 1271 {
1615 if (NULL != h->th_head) 1272 if (NULL != h->th_head)
1616 LOG (GNUNET_ERROR_TYPE_DEBUG, " can't transmit any more\n"); 1273 LOG (GNUNET_ERROR_TYPE_DEBUG, "# can't transmit any more\n");
1617 else 1274 else
1618 LOG (GNUNET_ERROR_TYPE_DEBUG, " nothing left to transmit\n"); 1275 LOG (GNUNET_ERROR_TYPE_DEBUG, "# nothing left to transmit\n");
1619 } 1276 }
1620 if (GNUNET_NO == h->in_receive) 1277 if (GNUNET_NO == h->in_receive)
1621 { 1278 {
1622 LOG (GNUNET_ERROR_TYPE_DEBUG, " start receiving from service\n"); 1279 LOG (GNUNET_ERROR_TYPE_DEBUG, "# start receiving from service\n");
1623 h->in_receive = GNUNET_YES; 1280 h->in_receive = GNUNET_YES;
1624 GNUNET_CLIENT_receive (h->client, &msg_received, h, 1281 GNUNET_CLIENT_receive (h->client, &msg_received, h,
1625 GNUNET_TIME_UNIT_FOREVER_REL); 1282 GNUNET_TIME_UNIT_FOREVER_REL);
1626 } 1283 }
1627 LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() END\n"); 1284 LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() END\n");
1628 return tsize; 1285 return tsize;
1629} 1286}
1630 1287
@@ -1670,33 +1327,14 @@ send_packet (struct GNUNET_MESH_Handle *h,
1670/********************** API CALL DEFINITIONS *************************/ 1327/********************** API CALL DEFINITIONS *************************/
1671/******************************************************************************/ 1328/******************************************************************************/
1672 1329
1673/**
1674 * Connect to the mesh service.
1675 *
1676 * @param cfg configuration to use
1677 * @param cls closure for the various callbacks that follow
1678 * (including handlers in the handlers array)
1679 * @param new_tunnel function called when an *inbound* tunnel is created
1680 * @param cleaner function called when an *inbound* tunnel is destroyed by the
1681 * remote peer, it is *not* called if GNUNET_MESH_tunnel_destroy
1682 * is called on the tunnel
1683 * @param handlers callbacks for messages we care about, NULL-terminated
1684 * note that the mesh is allowed to drop notifications about
1685 * inbound messages if the client does not process them fast
1686 * enough (for this notification type, a bounded queue is used)
1687 * @param stypes list of the applications that this client claims to provide
1688 * @return handle to the mesh service NULL on error
1689 * (in this case, init is never called)
1690 */
1691struct GNUNET_MESH_Handle * 1330struct GNUNET_MESH_Handle *
1692GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, 1331GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
1693 GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel, 1332 GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
1694 GNUNET_MESH_TunnelEndHandler cleaner, 1333 GNUNET_MESH_TunnelEndHandler cleaner,
1695 const struct GNUNET_MESH_MessageHandler *handlers, 1334 const struct GNUNET_MESH_MessageHandler *handlers,
1696 const GNUNET_MESH_ApplicationType *stypes) 1335 const uint32_t *ports)
1697{ 1336{
1698 struct GNUNET_MESH_Handle *h; 1337 struct GNUNET_MESH_Handle *h;
1699 size_t size;
1700 1338
1701 LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n"); 1339 LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n");
1702 h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle)); 1340 h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
@@ -1713,38 +1351,24 @@ GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
1713 } 1351 }
1714 h->cls = cls; 1352 h->cls = cls;
1715 h->message_handlers = handlers; 1353 h->message_handlers = handlers;
1354 h->ports = ports;
1716 h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; 1355 h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
1717 h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; 1356 h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
1718 h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; 1357 h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1719 1358
1720 /* count apps */
1721 for (h->n_applications = 0;
1722 stypes && stypes[h->n_applications];
1723 h->n_applications++) ;
1724 if (0 < h->n_applications)
1725 {
1726 size = h->n_applications * sizeof (GNUNET_MESH_ApplicationType *);
1727 h->applications = GNUNET_malloc (size);
1728 memcpy (h->applications, stypes, size);
1729 }
1730 /* count handlers */ 1359 /* count handlers */
1731 for (h->n_handlers = 0; 1360 for (h->n_handlers = 0;
1732 handlers && handlers[h->n_handlers].type; 1361 handlers && handlers[h->n_handlers].type;
1733 h->n_handlers++) ; 1362 h->n_handlers++) ;
1363 for (h->n_ports = 0;
1364 ports && ports[h->n_ports];
1365 h->n_ports++) ;
1734 send_connect (h); 1366 send_connect (h);
1735 LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n"); 1367 LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n");
1736 return h; 1368 return h;
1737} 1369}
1738 1370
1739 1371
1740/**
1741 * Disconnect from the mesh service. All tunnels will be destroyed. All tunnel
1742 * disconnect callbacks will be called on any still connected peers, notifying
1743 * about their disconnection. The registered inbound tunnel cleaner will be
1744 * called should any inbound tunnels still exist.
1745 *
1746 * @param handle connection to mesh to disconnect
1747 */
1748void 1372void
1749GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle) 1373GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
1750{ 1374{
@@ -1812,75 +1436,15 @@ GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
1812 GNUNET_SCHEDULER_cancel(handle->reconnect_task); 1436 GNUNET_SCHEDULER_cancel(handle->reconnect_task);
1813 handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; 1437 handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1814 } 1438 }
1815 GNUNET_free_non_null (handle->applications);
1816 GNUNET_free (handle); 1439 GNUNET_free (handle);
1817} 1440}
1818 1441
1819 1442
1820/**
1821 * Announce to ther peer the availability of services described by the regex,
1822 * in order to be reachable to other peers via connect_by_string.
1823 *
1824 * Note that the first 8 characters are considered to be part of a prefix,
1825 * (for instance 'gnunet://'). If you put a variable part in there (*, +. ()),
1826 * all matching strings will be stored in the DHT.
1827 *
1828 * @param h Handle to mesh.
1829 * @param regex String with the regular expression describing local services.
1830 * @param compression_characters How many characters can be assigned to one
1831 * edge of the graph. The bigger the variability
1832 * of the data, the smaller this parameter should
1833 * be (down to 1).
1834 * For maximum compression, use strlen (regex)
1835 * or 0 (special value). Use with care!
1836 */
1837void
1838GNUNET_MESH_announce_regex (struct GNUNET_MESH_Handle *h,
1839 const char *regex,
1840 unsigned int compression_characters)
1841{
1842 struct GNUNET_MESH_RegexAnnounce *msg;
1843 size_t payload;
1844 size_t len;
1845 size_t msgsize;
1846 size_t offset;
1847 char buffer[UINT16_MAX];
1848
1849 len = strlen (regex);
1850 payload = UINT16_MAX - sizeof(struct GNUNET_MESH_RegexAnnounce);
1851 msg = (struct GNUNET_MESH_RegexAnnounce *) buffer;
1852 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ANNOUNCE_REGEX);
1853 msg->compression_characters = htons (compression_characters);
1854 offset = 0;
1855 do
1856 {
1857 msgsize = (len - offset > payload) ? payload : len - offset;
1858 memcpy (&msg[1], &regex[offset], msgsize);
1859 offset += msgsize;
1860 msgsize += sizeof(struct GNUNET_MESH_RegexAnnounce);
1861
1862 msg->header.size = htons (msgsize);
1863 msg->last = htons (offset >= len);
1864
1865 send_packet (h, &msg->header, NULL);
1866 } while (len > offset);
1867}
1868
1869/**
1870 * Create a new tunnel (we're initiator and will be allowed to add/remove peers
1871 * and to broadcast).
1872 *
1873 * @param h mesh handle
1874 * @param tunnel_ctx client's tunnel context to associate with the tunnel
1875 * @param connect_handler function to call when peers are actually connected
1876 * @param disconnect_handler function to call when peers are disconnected
1877 * @param handler_cls closure for connect/disconnect handlers
1878 */
1879struct GNUNET_MESH_Tunnel * 1443struct GNUNET_MESH_Tunnel *
1880GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, void *tunnel_ctx, 1444GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h,
1881 GNUNET_MESH_PeerConnectHandler connect_handler, 1445 void *tunnel_ctx,
1882 GNUNET_MESH_PeerDisconnectHandler disconnect_handler, 1446 const struct GNUNET_PeerIdentity *peer,
1883 void *handler_cls) 1447 uint32_t port)
1884{ 1448{
1885 struct GNUNET_MESH_Tunnel *t; 1449 struct GNUNET_MESH_Tunnel *t;
1886 struct GNUNET_MESH_TunnelMessage msg; 1450 struct GNUNET_MESH_TunnelMessage msg;
@@ -1889,24 +1453,19 @@ GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, void *tunnel_ctx,
1889 t = create_tunnel (h, 0); 1453 t = create_tunnel (h, 0);
1890 LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", t); 1454 LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", t);
1891 LOG (GNUNET_ERROR_TYPE_DEBUG, " number %X\n", t->tid); 1455 LOG (GNUNET_ERROR_TYPE_DEBUG, " number %X\n", t->tid);
1892 t->connect_handler = connect_handler;
1893 t->disconnect_handler = disconnect_handler;
1894 t->cls = handler_cls;
1895 t->ctx = tunnel_ctx; 1456 t->ctx = tunnel_ctx;
1457 t->peer = GNUNET_PEER_intern (peer);
1896 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); 1458 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
1897 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); 1459 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1898 msg.tunnel_id = htonl (t->tid); 1460 msg.tunnel_id = htonl (t->tid);
1461 msg.port = htonl (port);
1462 msg.peer = *peer;
1463 t->last_ack_sent = 0;
1899 send_packet (h, &msg.header, t); 1464 send_packet (h, &msg.header, t);
1900 return t; 1465 return t;
1901} 1466}
1902 1467
1903 1468
1904/**
1905 * Destroy an existing tunnel. The existing callback for the tunnel will NOT
1906 * be called.
1907 *
1908 * @param tunnel tunnel handle
1909 */
1910void 1469void
1911GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel) 1470GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel)
1912{ 1471{
@@ -1938,62 +1497,11 @@ GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel)
1938 th = th->next; 1497 th = th->next;
1939 } 1498 }
1940 1499
1941 destroy_tunnel (tunnel, GNUNET_NO); 1500 destroy_tunnel (tunnel, GNUNET_YES);
1942 send_packet (h, &msg.header, NULL); 1501 send_packet (h, &msg.header, NULL);
1943} 1502}
1944 1503
1945/**
1946 * Request that the tunnel data rate is limited to the speed of the slowest
1947 * receiver.
1948 *
1949 * @param tunnel Tunnel affected.
1950 */
1951void
1952GNUNET_MESH_tunnel_speed_min (struct GNUNET_MESH_Tunnel *tunnel)
1953{
1954 struct GNUNET_MESH_TunnelMessage msg;
1955 struct GNUNET_MESH_Handle *h;
1956
1957 h = tunnel->mesh;
1958 tunnel->speed_min = GNUNET_YES;
1959
1960 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MIN);
1961 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1962 msg.tunnel_id = htonl (tunnel->tid);
1963
1964 send_packet (h, &msg.header, NULL);
1965}
1966
1967
1968/**
1969 * Request that the tunnel data rate is limited to the speed of the fastest
1970 * receiver. This is the default behavior.
1971 *
1972 * @param tunnel Tunnel affected.
1973 */
1974void
1975GNUNET_MESH_tunnel_speed_max (struct GNUNET_MESH_Tunnel *tunnel)
1976{
1977 struct GNUNET_MESH_TunnelMessage msg;
1978 struct GNUNET_MESH_Handle *h;
1979
1980 h = tunnel->mesh;
1981 tunnel->speed_min = GNUNET_NO;
1982
1983 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MAX);
1984 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1985 msg.tunnel_id = htonl (tunnel->tid);
1986
1987 send_packet (h, &msg.header, NULL);
1988}
1989 1504
1990/**
1991 * Turn on/off the buffering status of the tunnel.
1992 *
1993 * @param tunnel Tunnel affected.
1994 * @param buffer GNUNET_YES to turn buffering on (default),
1995 * GNUNET_NO otherwise.
1996 */
1997void 1505void
1998GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer) 1506GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer)
1999{ 1507{
@@ -2002,7 +1510,6 @@ GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer)
2002 1510
2003 h = tunnel->mesh; 1511 h = tunnel->mesh;
2004 tunnel->buffering = buffer; 1512 tunnel->buffering = buffer;
2005 tunnel->max_send_pid = tunnel->next_send_pid;
2006 1513
2007 if (GNUNET_YES == buffer) 1514 if (GNUNET_YES == buffer)
2008 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER); 1515 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER);
@@ -2015,267 +1522,39 @@ GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer)
2015} 1522}
2016 1523
2017 1524
2018/**
2019 * Request that a peer should be added to the tunnel. The existing
2020 * connect handler will be called ONCE with either success or failure.
2021 * This function should NOT be called again with the same peer before the
2022 * connect handler is called.
2023 * FIXME: I think the above documentation is false. I think it should
2024 * read: "The connect handler will be called once the peer was actually
2025 * successfully added to the multicast group. This function should
2026 * not be called twice for the same peer (unless, of course,
2027 * the peer was removed using GNUNET_MESH_peer_Request_connect_del in
2028 * the meantime).
2029 *
2030 * @param tunnel handle to existing tunnel
2031 * @param peer peer to add
2032 */
2033void
2034GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
2035 const struct GNUNET_PeerIdentity *peer)
2036{
2037 struct GNUNET_MESH_PeerControl msg;
2038 GNUNET_PEER_Id peer_id;
2039 unsigned int i;
2040
2041 peer_id = GNUNET_PEER_intern (peer);
2042 for (i = 0; i < tunnel->npeers; i++)
2043 {
2044 if (tunnel->peers[i]->id == peer_id)
2045 {
2046 /* Peer already exists in tunnel */
2047 GNUNET_PEER_change_rc (peer_id, -1);
2048 GNUNET_break (0);
2049 return;
2050 }
2051 }
2052 if (NULL == add_peer_to_tunnel (tunnel, peer))
2053 return;
2054
2055 msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2056 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
2057 msg.tunnel_id = htonl (tunnel->tid);
2058 msg.peer = *peer;
2059 send_packet (tunnel->mesh, &msg.header, tunnel);
2060}
2061
2062
2063/**
2064 * Request that a peer should be removed from the tunnel. The existing
2065 * disconnect handler will be called ONCE if we were connected.
2066 *
2067 * @param tunnel handle to existing tunnel
2068 * @param peer peer to remove
2069 */
2070void
2071GNUNET_MESH_peer_request_connect_del (struct GNUNET_MESH_Tunnel *tunnel,
2072 const struct GNUNET_PeerIdentity *peer)
2073{
2074 struct GNUNET_MESH_PeerControl msg;
2075 GNUNET_PEER_Id peer_id;
2076 unsigned int i;
2077
2078 peer_id = GNUNET_PEER_search (peer);
2079 if (0 == peer_id)
2080 {
2081 GNUNET_break (0);
2082 return;
2083 }
2084 for (i = 0; i < tunnel->npeers; i++)
2085 if (tunnel->peers[i]->id == peer_id)
2086 break;
2087 if (i == tunnel->npeers)
2088 {
2089 GNUNET_break (0);
2090 return;
2091 }
2092 if (NULL != tunnel->disconnect_handler && tunnel->peers[i]->connected == 1)
2093 tunnel->disconnect_handler (tunnel->cls, peer);
2094 GNUNET_PEER_change_rc (peer_id, -1);
2095 GNUNET_free (tunnel->peers[i]);
2096 tunnel->peers[i] = tunnel->peers[tunnel->npeers - 1];
2097 GNUNET_array_grow (tunnel->peers, tunnel->npeers, tunnel->npeers - 1);
2098
2099 msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2100 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
2101 msg.tunnel_id = htonl (tunnel->tid);
2102 memcpy (&msg.peer, peer, sizeof (struct GNUNET_PeerIdentity));
2103 send_packet (tunnel->mesh, &msg.header, tunnel);
2104}
2105
2106
2107/**
2108 * Request that the mesh should try to connect to a peer supporting the given
2109 * message type.
2110 *
2111 * @param tunnel handle to existing tunnel
2112 * @param app_type application type that must be supported by the peer (MESH
2113 * should discover peer in proximity handling this type)
2114 */
2115void
2116GNUNET_MESH_peer_request_connect_by_type (struct GNUNET_MESH_Tunnel *tunnel,
2117 GNUNET_MESH_ApplicationType app_type)
2118{
2119 struct GNUNET_MESH_ConnectPeerByType msg;
2120
2121 GNUNET_array_append (tunnel->apps, tunnel->napps, app_type);
2122
2123 LOG (GNUNET_ERROR_TYPE_DEBUG, "* CONNECT BY TYPE *\n");
2124 msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
2125 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
2126 msg.tunnel_id = htonl (tunnel->tid);
2127 msg.type = htonl (app_type);
2128 send_packet (tunnel->mesh, &msg.header, tunnel);
2129}
2130
2131
2132/**
2133 * Request that the mesh should try to connect to a peer matching the
2134 * description given in the service string.
2135 *
2136 * FIXME: allow multiple? how to deal with reconnect?
2137 *
2138 * @param tunnel handle to existing tunnel
2139 * @param description string describing the destination node requirements
2140 */
2141void
2142GNUNET_MESH_peer_request_connect_by_string (struct GNUNET_MESH_Tunnel *tunnel,
2143 const char *description)
2144{
2145 struct GNUNET_MESH_ConnectPeerByString *m;
2146 size_t len;
2147 size_t msgsize;
2148
2149 len = strlen (description);
2150 msgsize = sizeof(struct GNUNET_MESH_ConnectPeerByString) + len;
2151 GNUNET_assert (UINT16_MAX > msgsize);
2152 {
2153 char buffer[msgsize];
2154
2155 m = (struct GNUNET_MESH_ConnectPeerByString *) buffer;
2156 m->header.size = htons (msgsize);
2157 m->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_STRING);
2158 m->tunnel_id = htonl (tunnel->tid);
2159 memcpy(&m[1], description, len);
2160
2161 send_packet (tunnel->mesh, &m->header, tunnel);
2162 }
2163}
2164
2165
2166/**
2167 * Request that the given peer isn't added to this tunnel in calls to
2168 * connect_by_* calls, (due to misbehaviour, bad performance, ...).
2169 *
2170 * @param tunnel handle to existing tunnel.
2171 * @param peer peer identity of the peer which should be blacklisted
2172 * for the tunnel.
2173 */
2174void
2175GNUNET_MESH_peer_blacklist (struct GNUNET_MESH_Tunnel *tunnel,
2176 const struct GNUNET_PeerIdentity *peer)
2177{
2178 struct GNUNET_MESH_PeerControl msg;
2179
2180 msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2181 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_BLACKLIST);
2182 msg.tunnel_id = htonl (tunnel->tid);
2183 msg.peer = *peer;
2184 send_packet (tunnel->mesh, &msg.header, tunnel);
2185
2186 return;
2187}
2188
2189
2190/**
2191 * Request that the given peer isn't blacklisted anymore from this tunnel,
2192 * and therefore can be added in future calls to connect_by_*.
2193 * The peer must have been previously blacklisted for this tunnel.
2194 *
2195 * @param tunnel handle to existing tunnel.
2196 * @param peer peer identity of the peer which shouldn't be blacklisted
2197 * for the tunnel anymore.
2198 */
2199void
2200GNUNET_MESH_peer_unblacklist (struct GNUNET_MESH_Tunnel *tunnel,
2201 const struct GNUNET_PeerIdentity *peer)
2202{
2203 struct GNUNET_MESH_PeerControl msg;
2204
2205 msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2206 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_UNBLACKLIST);
2207 msg.tunnel_id = htonl (tunnel->tid);
2208 msg.peer = *peer;
2209 send_packet (tunnel->mesh, &msg.header, tunnel);
2210
2211 return;
2212}
2213
2214
2215/**
2216 * Ask the mesh to call "notify" once it is ready to transmit the
2217 * given number of bytes to the specified tunnel or target.
2218 * Only one call can be active at any time, to issue another request,
2219 * wait for the callback or cancel the current request.
2220 *
2221 * @param tunnel tunnel to use for transmission
2222 * @param cork is corking allowed for this transmission?
2223 * @param maxdelay how long can the message wait?
2224 * @param target destination for the message
2225 * NULL for multicast to all tunnel targets
2226 * @param notify_size how many bytes of buffer space does notify want?
2227 * @param notify function to call when buffer space is available;
2228 * will be called with NULL on timeout or if the overall queue
2229 * for this peer is larger than queue_size and this is currently
2230 * the message with the lowest priority
2231 * @param notify_cls closure for notify
2232 * @return non-NULL if the notify callback was queued,
2233 * NULL if we can not even queue the request (insufficient
2234 * memory); if NULL is returned, "notify" will NOT be called.
2235 */
2236struct GNUNET_MESH_TransmitHandle * 1525struct GNUNET_MESH_TransmitHandle *
2237GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork, 1526GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
2238 struct GNUNET_TIME_Relative maxdelay, 1527 struct GNUNET_TIME_Relative maxdelay,
2239 const struct GNUNET_PeerIdentity *target,
2240 size_t notify_size, 1528 size_t notify_size,
2241 GNUNET_CONNECTION_TransmitReadyNotify notify, 1529 GNUNET_CONNECTION_TransmitReadyNotify notify,
2242 void *notify_cls) 1530 void *notify_cls)
2243{ 1531{
2244 struct GNUNET_MESH_TransmitHandle *th; 1532 struct GNUNET_MESH_TransmitHandle *th;
2245 size_t overhead;
2246 1533
2247 GNUNET_assert (NULL != tunnel); 1534 GNUNET_assert (NULL != tunnel);
2248 LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n"); 1535 LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n");
2249 LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", tunnel->tid); 1536 LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", tunnel->tid);
2250 if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) 1537 if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
2251 LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin\n"); 1538 LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin\n");
2252 else if (NULL != target)
2253 LOG (GNUNET_ERROR_TYPE_DEBUG, " target %s\n", GNUNET_i2s (target));
2254 else 1539 else
2255 LOG (GNUNET_ERROR_TYPE_DEBUG, " target multicast\n"); 1540 LOG (GNUNET_ERROR_TYPE_DEBUG, " to destination\n");
2256 LOG (GNUNET_ERROR_TYPE_DEBUG, " payload size %u\n", notify_size); 1541 LOG (GNUNET_ERROR_TYPE_DEBUG, " payload size %u\n", notify_size);
2257 GNUNET_assert (NULL != notify); 1542 GNUNET_assert (NULL != notify);
2258 GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed 1543 GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed
2259 th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle)); 1544 th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
2260 th->tunnel = tunnel; 1545 th->tunnel = tunnel;
2261 th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay); 1546 th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
2262 th->target = GNUNET_PEER_intern (target); 1547 th->size = notify_size + sizeof (struct GNUNET_MESH_Data);
2263 if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) 1548 tunnel->packet_size = th->size;
2264 overhead = sizeof (struct GNUNET_MESH_ToOrigin);
2265 else if (NULL == target)
2266 overhead = sizeof (struct GNUNET_MESH_Multicast);
2267 else
2268 overhead = sizeof (struct GNUNET_MESH_Unicast);
2269 tunnel->packet_size = th->size = notify_size + overhead;
2270 LOG (GNUNET_ERROR_TYPE_DEBUG, " total size %u\n", th->size); 1549 LOG (GNUNET_ERROR_TYPE_DEBUG, " total size %u\n", th->size);
2271 th->notify = notify; 1550 th->notify = notify;
2272 th->notify_cls = notify_cls; 1551 th->notify_cls = notify_cls;
2273 add_to_queue (tunnel->mesh, th); 1552 add_to_queue (tunnel->mesh, th);
2274 if (NULL != tunnel->mesh->th) 1553 if (NULL != tunnel->mesh->th)
2275 return th; 1554 return th;
2276 if (GMC_is_pid_bigger(tunnel->next_send_pid, tunnel->max_send_pid)) 1555 if (!GMC_is_pid_bigger (tunnel->last_ack_recv, tunnel->last_pid_sent))
2277 return th; 1556 return th;
2278 LOG (GNUNET_ERROR_TYPE_DEBUG, " call notify tmt rdy\n"); 1557 LOG (GNUNET_ERROR_TYPE_DEBUG, " call client notify tmt rdy\n");
2279 tunnel->mesh->th = 1558 tunnel->mesh->th =
2280 GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size, 1559 GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size,
2281 GNUNET_TIME_UNIT_FOREVER_REL, 1560 GNUNET_TIME_UNIT_FOREVER_REL,
@@ -2286,11 +1565,6 @@ GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
2286} 1565}
2287 1566
2288 1567
2289/**
2290 * Cancel the specified transmission-ready notification.
2291 *
2292 * @param th handle that was returned by "notify_transmit_ready".
2293 */
2294void 1568void
2295GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th) 1569GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th)
2296{ 1570{
@@ -2310,6 +1584,12 @@ GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th)
2310 } 1584 }
2311} 1585}
2312 1586
1587void
1588GNUNET_MESH_receive_done (struct GNUNET_MESH_Tunnel *tunnel)
1589{
1590 send_ack (tunnel);
1591}
1592
2313 1593
2314/** 1594/**
2315 * Request information about the running mesh peer. 1595 * Request information about the running mesh peer.
@@ -2366,6 +1646,7 @@ GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h)
2366 * Request information about a specific tunnel of the running mesh peer. 1646 * Request information about a specific tunnel of the running mesh peer.
2367 * 1647 *
2368 * WARNING: unstable API, likely to change in the future! 1648 * WARNING: unstable API, likely to change in the future!
1649 * FIXME Add destination option.
2369 * 1650 *
2370 * @param h Handle to the mesh peer. 1651 * @param h Handle to the mesh peer.
2371 * @param initiator ID of the owner of the tunnel. 1652 * @param initiator ID of the owner of the tunnel.
@@ -2384,7 +1665,6 @@ GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h,
2384 1665
2385 msg.header.size = htons (sizeof (msg)); 1666 msg.header.size = htons (sizeof (msg));
2386 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL); 1667 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL);
2387 msg.npeers = htonl (0);
2388 msg.owner = *initiator; 1668 msg.owner = *initiator;
2389 msg.tunnel_id = htonl (tunnel_number); 1669 msg.tunnel_id = htonl (tunnel_number);
2390 msg.reserved = 0; 1670 msg.reserved = 0;
@@ -2397,21 +1677,111 @@ GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h,
2397 1677
2398 1678
2399/** 1679/**
2400 * Transition API for tunnel ctx management 1680 * Function called to notify a client about the connection
1681 * begin ready to queue more data. "buf" will be
1682 * NULL and "size" zero if the connection was closed for
1683 * writing in the meantime.
1684 *
1685 * @param cls closure
1686 * @param size number of bytes available in buf
1687 * @param buf where the callee should write the message
1688 * @return number of bytes written to buf
2401 */ 1689 */
2402void 1690static size_t
2403GNUNET_MESH_tunnel_set_data (struct GNUNET_MESH_Tunnel *tunnel, void *data) 1691mesh_mq_ntr (void *cls, size_t size,
1692 void *buf)
2404{ 1693{
2405 tunnel->ctx = data; 1694 struct GNUNET_MQ_Handle *mq = cls;
1695 struct MeshMQState *state = GNUNET_MQ_impl_state (mq);
1696 const struct GNUNET_MessageHeader *msg = GNUNET_MQ_impl_current (mq);
1697 uint16_t msize;
1698
1699 state->th = NULL;
1700 if (NULL == buf)
1701 {
1702 GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE);
1703 return 0;
1704 }
1705 msize = ntohs (msg->size);
1706 GNUNET_assert (msize <= size);
1707 memcpy (buf, msg, msize);
1708 GNUNET_MQ_impl_send_continue (mq);
1709 return msize;
2406} 1710}
2407 1711
1712
2408/** 1713/**
2409 * Transition API for tunnel ctx management 1714 * Signature of functions implementing the
1715 * sending functionality of a message queue.
1716 *
1717 * @param mq the message queue
1718 * @param msg the message to send
1719 * @param impl_state state of the implementation
2410 */ 1720 */
2411void * 1721static void
2412GNUNET_MESH_tunnel_get_data (struct GNUNET_MESH_Tunnel *tunnel) 1722mesh_mq_send_impl (struct GNUNET_MQ_Handle *mq,
1723 const struct GNUNET_MessageHeader *msg, void *impl_state)
2413{ 1724{
2414 return tunnel->ctx; 1725 struct MeshMQState *state = impl_state;
1726
1727 GNUNET_assert (NULL == state->th);
1728 GNUNET_MQ_impl_send_commit (mq);
1729 state->th =
1730 GNUNET_MESH_notify_transmit_ready (state->tunnel,
1731 /* FIXME: add option for corking */
1732 GNUNET_NO,
1733 GNUNET_TIME_UNIT_FOREVER_REL,
1734 ntohs (msg->size),
1735 mesh_mq_ntr, mq);
1736
2415} 1737}
2416 1738
2417 1739
1740/**
1741 * Signature of functions implementing the
1742 * destruction of a message queue.
1743 * Implementations must not free 'mq', but should
1744 * take care of 'impl_state'.
1745 *
1746 * @param mq the message queue to destroy
1747 * @param impl_state state of the implementation
1748 */
1749static void
1750mesh_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
1751{
1752 struct MeshMQState *state = impl_state;
1753
1754 if (NULL != state->th)
1755 GNUNET_MESH_notify_transmit_ready_cancel (state->th);
1756
1757 GNUNET_free (state);
1758}
1759
1760
1761/**
1762 * Create a message queue for a mesh tunnel.
1763 * The message queue can only be used to transmit messages,
1764 * not to receive them.
1765 *
1766 * @param tunnel the tunnel to create the message qeue for
1767 * @return a message queue to messages over the tunnel
1768 */
1769struct GNUNET_MQ_Handle *
1770GNUNET_MESH_mq_create (struct GNUNET_MESH_Tunnel *tunnel)
1771{
1772 struct GNUNET_MQ_Handle *mq;
1773 struct MeshMQState *state;
1774
1775 state = GNUNET_new (struct MeshMQState);
1776 state->tunnel = tunnel;
1777
1778 mq = GNUNET_MQ_queue_for_callbacks (mesh_mq_send_impl,
1779 mesh_mq_destroy_impl,
1780 NULL, /* FIXME: cancel impl. */
1781 state,
1782 NULL, /* no msg handlers */
1783 NULL, /* no err handlers */
1784 NULL); /* no handler cls */
1785 return mq;
1786}
1787
diff --git a/src/mesh/mesh_path.c b/src/mesh/mesh_path.c
index 05444655a..1a3d40f9f 100644
--- a/src/mesh/mesh_path.c
+++ b/src/mesh/mesh_path.c
@@ -24,7 +24,7 @@
24 * @author Bartlomiej Polot 24 * @author Bartlomiej Polot
25 */ 25 */
26 26
27#include "mesh2.h" 27#include "mesh.h"
28#include "mesh_path.h" 28#include "mesh_path.h"
29 29
30 30
diff --git a/src/mesh/mesh_path.h b/src/mesh/mesh_path.h
index c3f3264b0..74a35b225 100644
--- a/src/mesh/mesh_path.h
+++ b/src/mesh/mesh_path.h
@@ -35,7 +35,7 @@ extern "C"
35#endif 35#endif
36#endif 36#endif
37 37
38#include "mesh2.h" 38#include "mesh.h"
39 39
40/******************************************************************************/ 40/******************************************************************************/
41/************************ DATA STRUCTURES ****************************/ 41/************************ DATA STRUCTURES ****************************/
diff --git a/src/mesh/mesh_protocol.h b/src/mesh/mesh_protocol.h
index 01f7f3487..d35d7141e 100644
--- a/src/mesh/mesh_protocol.h
+++ b/src/mesh/mesh_protocol.h
@@ -35,7 +35,6 @@ extern "C"
35#endif 35#endif
36#endif 36#endif
37 37
38#define MESH_TUNNEL_OPT_SPEED_MIN 0x1
39#define MESH_TUNNEL_OPT_NOBUFFER 0x2 38#define MESH_TUNNEL_OPT_NOBUFFER 0x2
40 39
41 40
@@ -46,12 +45,12 @@ extern "C"
46GNUNET_NETWORK_STRUCT_BEGIN 45GNUNET_NETWORK_STRUCT_BEGIN
47 46
48/** 47/**
49 * Message for mesh path management 48 * Message for mesh path creation.
50 */ 49 */
51struct GNUNET_MESH_ManipulatePath 50struct GNUNET_MESH_CreateTunnel
52{ 51{
53 /** 52 /**
54 * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_[CREATE|CHANGE|ADD|DESTROY] 53 * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE
55 * 54 *
56 * Size: sizeof(struct GNUNET_MESH_ManipulatePath) + 55 * Size: sizeof(struct GNUNET_MESH_ManipulatePath) +
57 * path_length * sizeof (struct GNUNET_PeerIdentity) 56 * path_length * sizeof (struct GNUNET_PeerIdentity)
@@ -70,11 +69,12 @@ struct GNUNET_MESH_ManipulatePath
70 uint32_t opt GNUNET_PACKED; 69 uint32_t opt GNUNET_PACKED;
71 70
72 /** 71 /**
73 * 64 bit alignment padding. 72 * Destination port.
74 */ 73 */
75 uint32_t reserved GNUNET_PACKED; 74 uint32_t port GNUNET_PACKED;
76 75
77 /** 76 /**
77 * FIXME do not add the first hop
78 * path_length structs defining the *whole* path from the origin [0] to the 78 * path_length structs defining the *whole* path from the origin [0] to the
79 * final destination [path_length-1]. 79 * final destination [path_length-1].
80 */ 80 */
@@ -82,89 +82,34 @@ struct GNUNET_MESH_ManipulatePath
82}; 82};
83 83
84/** 84/**
85 * Message for mesh data traffic to all tunnel targets. 85 * Message for mesh path destruction.
86 */ 86 */
87struct GNUNET_MESH_Multicast 87struct GNUNET_MESH_DestroyTunnel
88{ 88{
89 /** 89 /**
90 * Type: GNUNET_MESSAGE_TYPE_MESH_MULTICAST 90 * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY
91 */ 91 *
92 struct GNUNET_MessageHeader header; 92 * Size: sizeof(struct GNUNET_MESH_ManipulatePath) +
93 93 * path_length * sizeof (struct GNUNET_PeerIdentity)
94 /** 94 */
95 * TID of the tunnel
96 */
97 uint32_t tid GNUNET_PACKED;
98
99 /**
100 * Number of hops to live
101 */
102 uint32_t ttl GNUNET_PACKED;
103
104 /**
105 * Unique ID of the packet
106 */
107 uint32_t pid GNUNET_PACKED;
108
109 /**
110 * OID of the tunnel
111 */
112 struct GNUNET_PeerIdentity oid;
113
114 /**
115 * Payload follows
116 */
117};
118
119
120/**
121 * Message for mesh data traffic to a particular destination from origin.
122 */
123struct GNUNET_MESH_Unicast
124{
125 /**
126 * Type: GNUNET_MESSAGE_TYPE_MESH_UNICAST
127 */
128 struct GNUNET_MessageHeader header; 95 struct GNUNET_MessageHeader header;
129 96
130 /** 97 /**
131 * TID of the tunnel 98 * Global id of the tunnel this path belongs to,
132 */ 99 * unique in conjunction with the origin.
100 */
133 uint32_t tid GNUNET_PACKED; 101 uint32_t tid GNUNET_PACKED;
134
135 /**
136 * Number of hops to live
137 */
138 uint32_t ttl GNUNET_PACKED;
139
140 /**
141 * Unique ID of the packet
142 */
143 uint32_t pid GNUNET_PACKED;
144
145 /**
146 * OID of the tunnel
147 */
148 struct GNUNET_PeerIdentity oid;
149
150 /**
151 * Destination.
152 */
153 struct GNUNET_PeerIdentity destination;
154
155 /**
156 * Payload follows
157 */
158}; 102};
159 103
160 104
161/** 105/**
162 * Message for mesh data traffic from a tunnel participant to origin. 106 * Message for mesh data traffic.
163 */ 107 */
164struct GNUNET_MESH_ToOrigin 108struct GNUNET_MESH_Data
165{ 109{
166 /** 110 /**
167 * Type: GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN 111 * Type: GNUNET_MESSAGE_TYPE_MESH_UNICAST,
112 * GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN
168 */ 113 */
169 struct GNUNET_MessageHeader header; 114 struct GNUNET_MessageHeader header;
170 115
@@ -189,11 +134,6 @@ struct GNUNET_MESH_ToOrigin
189 struct GNUNET_PeerIdentity oid; 134 struct GNUNET_PeerIdentity oid;
190 135
191 /** 136 /**
192 * Sender of the message.
193 */
194 struct GNUNET_PeerIdentity sender;
195
196 /**
197 * Payload follows 137 * Payload follows
198 */ 138 */
199}; 139};
@@ -245,11 +185,6 @@ struct GNUNET_MESH_Poll
245 * OID of the tunnel 185 * OID of the tunnel
246 */ 186 */
247 struct GNUNET_PeerIdentity oid; 187 struct GNUNET_PeerIdentity oid;
248
249 /**
250 * Last ACK received.
251 */
252 uint32_t last_ack;
253}; 188};
254 189
255/** 190/**
@@ -277,6 +212,11 @@ struct GNUNET_MESH_PathACK
277 */ 212 */
278 struct GNUNET_PeerIdentity peer_id; 213 struct GNUNET_PeerIdentity peer_id;
279 214
215 /**
216 * Initial ACK value for payload.
217 */
218 uint32_t ack GNUNET_PACKED;
219
280 /* TODO: signature */ 220 /* TODO: signature */
281}; 221};
282 222
diff --git a/src/mesh/mesh_test_lib.c b/src/mesh/mesh_test_lib.c
index 7c4d884a6..e9ccb631f 100644
--- a/src/mesh/mesh_test_lib.c
+++ b/src/mesh/mesh_test_lib.c
@@ -78,9 +78,9 @@ struct GNUNET_MESH_TEST_Context
78 struct GNUNET_MESH_MessageHandler* handlers; 78 struct GNUNET_MESH_MessageHandler* handlers;
79 79
80 /** 80 /**
81 * Application types. 81 * Application ports.
82 */ 82 */
83 const GNUNET_MESH_ApplicationType* stypes; 83 const uint32_t *ports;
84 84
85}; 85};
86 86
@@ -125,7 +125,7 @@ mesh_connect_adapter (void *cls,
125 ctx->new_tunnel, 125 ctx->new_tunnel,
126 ctx->cleaner, 126 ctx->cleaner,
127 ctx->handlers, 127 ctx->handlers,
128 ctx->stypes); 128 ctx->ports);
129 return h; 129 return h;
130} 130}
131 131
@@ -190,11 +190,6 @@ mesh_connect_cb (void *cls,
190} 190}
191 191
192 192
193/**
194 * Clean up the testbed.
195 *
196 * @param ctx handle for the testbed
197 */
198void 193void
199GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx) 194GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx)
200{ 195{
@@ -255,21 +250,6 @@ mesh_test_run (void *cls,
255} 250}
256 251
257 252
258/**
259 * Run a test using the given name, configuration file and number of
260 * peers.
261 * All mesh callbacks will receive the peer number as the closure.
262 *
263 * @param testname Name of the test (for logging).
264 * @param cfgname Name of the configuration file.
265 * @param num_peers Number of peers to start.
266 * @param tmain Main function to run once the testbed is ready.
267 * @param tmain_cls Closure for 'tmain'.
268 * @param new_tunnel Handler for incoming tunnels.
269 * @param cleaner Cleaner for destroyed incoming tunnels.
270 * @param handlers Message handlers.
271 * @param stypes Application types.
272 */
273void 253void
274GNUNET_MESH_TEST_run (const char *testname, 254GNUNET_MESH_TEST_run (const char *testname,
275 const char *cfgname, 255 const char *cfgname,
@@ -279,7 +259,7 @@ GNUNET_MESH_TEST_run (const char *testname,
279 GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel, 259 GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
280 GNUNET_MESH_TunnelEndHandler cleaner, 260 GNUNET_MESH_TunnelEndHandler cleaner,
281 struct GNUNET_MESH_MessageHandler* handlers, 261 struct GNUNET_MESH_MessageHandler* handlers,
282 const GNUNET_MESH_ApplicationType* stypes) 262 const uint32_t *ports)
283{ 263{
284 struct GNUNET_MESH_TEST_Context *ctx; 264 struct GNUNET_MESH_TEST_Context *ctx;
285 265
@@ -292,7 +272,7 @@ GNUNET_MESH_TEST_run (const char *testname,
292 ctx->new_tunnel = new_tunnel; 272 ctx->new_tunnel = new_tunnel;
293 ctx->cleaner = cleaner; 273 ctx->cleaner = cleaner;
294 ctx->handlers = handlers; 274 ctx->handlers = handlers;
295 ctx->stypes = stypes; 275 ctx->ports = ports;
296 GNUNET_TESTBED_test_run (testname, 276 GNUNET_TESTBED_test_run (testname,
297 cfgname, 277 cfgname,
298 num_peers, 278 num_peers,
diff --git a/src/mesh/mesh_test_lib.h b/src/mesh/mesh_test_lib.h
index 554d06541..4dd2151b8 100644
--- a/src/mesh/mesh_test_lib.h
+++ b/src/mesh/mesh_test_lib.h
@@ -71,7 +71,7 @@ typedef void (*GNUNET_MESH_TEST_AppMain) (void *cls,
71 * @param new_tunnel Handler for incoming tunnels. 71 * @param new_tunnel Handler for incoming tunnels.
72 * @param cleaner Cleaner for destroyed incoming tunnels. 72 * @param cleaner Cleaner for destroyed incoming tunnels.
73 * @param handlers Message handlers. 73 * @param handlers Message handlers.
74 * @param stypes Application types. 74 * @param ports Ports the peers offer.
75 */ 75 */
76void 76void
77GNUNET_MESH_TEST_run (const char *testname, 77GNUNET_MESH_TEST_run (const char *testname,
@@ -82,7 +82,7 @@ GNUNET_MESH_TEST_run (const char *testname,
82 GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel, 82 GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
83 GNUNET_MESH_TunnelEndHandler cleaner, 83 GNUNET_MESH_TunnelEndHandler cleaner,
84 struct GNUNET_MESH_MessageHandler* handlers, 84 struct GNUNET_MESH_MessageHandler* handlers,
85 const GNUNET_MESH_ApplicationType* stypes); 85 const uint32_t* ports);
86 86
87 87
88/** 88/**
diff --git a/src/mesh/plugin_block_mesh.c b/src/mesh/plugin_block_mesh.c
index 3d99201f7..cbfd57eb4 100644
--- a/src/mesh/plugin_block_mesh.c
+++ b/src/mesh/plugin_block_mesh.c
@@ -149,7 +149,6 @@ block_plugin_mesh_get_key (void *cls, enum GNUNET_BLOCK_Type type,
149 struct GNUNET_HashCode * key) 149 struct GNUNET_HashCode * key)
150{ 150{
151 const struct PBlock *pb; 151 const struct PBlock *pb;
152 GNUNET_MESH_ApplicationType app_type;
153 pb = block; 152 pb = block;
154 153
155 switch (type) 154 switch (type)
@@ -159,10 +158,6 @@ block_plugin_mesh_get_key (void *cls, enum GNUNET_BLOCK_Type type,
159 return GNUNET_SYSERR; 158 return GNUNET_SYSERR;
160 *key = pb->id.hashPubKey; 159 *key = pb->id.hashPubKey;
161 return GNUNET_OK; 160 return GNUNET_OK;
162 case GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE:
163 app_type = ntohl (pb->type);
164 GNUNET_CRYPTO_hash (&app_type, sizeof(GNUNET_MESH_ApplicationType), key);
165 return GNUNET_OK;
166 default: 161 default:
167 GNUNET_break (0); 162 GNUNET_break (0);
168 return GNUNET_SYSERR; 163 return GNUNET_SYSERR;
diff --git a/src/mesh/test_mesh.conf b/src/mesh/test_mesh.conf
index 3b35a16b4..58dff5adc 100644
--- a/src/mesh/test_mesh.conf
+++ b/src/mesh/test_mesh.conf
@@ -1,17 +1,15 @@
1[fs] 1[PATHS]
2AUTOSTART = NO 2SERVICEHOME = /tmp/test-mesh/
3
4[resolver]
5AUTOSTART = NO
6 3
7[mesh] 4[mesh]
8AUTOSTART = YES 5BINARY = gnunet-service-mesh-new
6AUTOSTART = NO
9ACCEPT_FROM = 127.0.0.1; 7ACCEPT_FROM = 127.0.0.1;
10HOSTNAME = localhost 8HOSTNAME = localhost
11PORT = 10511 9PORT = 10511
12# PREFIX = valgrind --leak-check=full 10#PREFIX = valgrind --leak-check=full
13# PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args 11#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
14REFRESH_PATH_TIME = 3 s 12REFRESH_PATH_TIME = 2 s
15APP_ANNOUNCE_TIME = 5 s 13APP_ANNOUNCE_TIME = 5 s
16ID_ANNOUNCE_TIME = 5 s 14ID_ANNOUNCE_TIME = 5 s
17CONNECT_TIMEOUT = 30 s 15CONNECT_TIMEOUT = 30 s
@@ -20,6 +18,16 @@ DHT_REPLICATION_LEVEL = 3
20MAX_TUNNELS = 10 18MAX_TUNNELS = 10
21MAX_MSGS_QUEUE = 20 19MAX_MSGS_QUEUE = 20
22 20
21[testbed]
22NUM_PEERS = 5
23OVERLAY_TOPOLOGY = LINE
24
25[fs]
26AUTOSTART = NO
27
28[resolver]
29AUTOSTART = NO
30
23[vpn] 31[vpn]
24AUTOSTART = NO 32AUTOSTART = NO
25PORT = 10012 33PORT = 10012
@@ -30,6 +38,8 @@ ACCEPT_FROM6 = ::1;
30ACCEPT_FROM = 127.0.0.1; 38ACCEPT_FROM = 127.0.0.1;
31HOSTNAME = localhost 39HOSTNAME = localhost
32PORT = 12100 40PORT = 12100
41DISABLE_TRY_CONNECT = YES
42FORCE_NSE = 3
33 43
34[block] 44[block]
35plugins = dht test 45plugins = dht test
@@ -53,7 +63,7 @@ WAN_QUOTA_IN = 3932160
53PORT = 12092 63PORT = 12092
54 64
55[arm] 65[arm]
56DEFAULTSERVICES = core 66DEFAULTSERVICES = core mesh
57PORT = 12366 67PORT = 12366
58 68
59[transport-tcp] 69[transport-tcp]
@@ -66,9 +76,6 @@ WEAKRANDOM = YES
66[gnunetd] 76[gnunetd]
67HOSTKEY = $SERVICEHOME/.hostkey 77HOSTKEY = $SERVICEHOME/.hostkey
68 78
69[PATHS]
70SERVICEHOME = /tmp/test-mesh/
71
72[dns] 79[dns]
73AUTOSTART = NO 80AUTOSTART = NO
74 81
diff --git a/src/mesh/test_mesh2.conf b/src/mesh/test_mesh2.conf
deleted file mode 100644
index 58dff5adc..000000000
--- a/src/mesh/test_mesh2.conf
+++ /dev/null
@@ -1,89 +0,0 @@
1[PATHS]
2SERVICEHOME = /tmp/test-mesh/
3
4[mesh]
5BINARY = gnunet-service-mesh-new
6AUTOSTART = NO
7ACCEPT_FROM = 127.0.0.1;
8HOSTNAME = localhost
9PORT = 10511
10#PREFIX = valgrind --leak-check=full
11#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
12REFRESH_PATH_TIME = 2 s
13APP_ANNOUNCE_TIME = 5 s
14ID_ANNOUNCE_TIME = 5 s
15CONNECT_TIMEOUT = 30 s
16DEFAULT_TTL = 16
17DHT_REPLICATION_LEVEL = 3
18MAX_TUNNELS = 10
19MAX_MSGS_QUEUE = 20
20
21[testbed]
22NUM_PEERS = 5
23OVERLAY_TOPOLOGY = LINE
24
25[fs]
26AUTOSTART = NO
27
28[resolver]
29AUTOSTART = NO
30
31[vpn]
32AUTOSTART = NO
33PORT = 10012
34
35[dht]
36AUTOSTART = YES
37ACCEPT_FROM6 = ::1;
38ACCEPT_FROM = 127.0.0.1;
39HOSTNAME = localhost
40PORT = 12100
41DISABLE_TRY_CONNECT = YES
42FORCE_NSE = 3
43
44[block]
45plugins = dht test
46
47[dhtcache]
48QUOTA = 1 MB
49DATABASE = sqlite
50
51[transport]
52PLUGINS = tcp
53ACCEPT_FROM6 = ::1;
54ACCEPT_FROM = 127.0.0.1;
55NEIGHBOUR_LIMIT = 50
56PORT = 12365
57
58[ats]
59WAN_QUOTA_OUT = 3932160
60WAN_QUOTA_IN = 3932160
61
62[core]
63PORT = 12092
64
65[arm]
66DEFAULTSERVICES = core mesh
67PORT = 12366
68
69[transport-tcp]
70TIMEOUT = 300 s
71PORT = 12368
72
73[TESTING]
74WEAKRANDOM = YES
75
76[gnunetd]
77HOSTKEY = $SERVICEHOME/.hostkey
78
79[dns]
80AUTOSTART = NO
81
82[nse]
83AUTOSTART = NO
84
85[namestore]
86AUTOSTART = NO
87
88[consensus]
89AUTOSTART = NO
diff --git a/src/mesh/test_mesh2_small.c b/src/mesh/test_mesh2_small.c
deleted file mode 100644
index 0a184d56f..000000000
--- a/src/mesh/test_mesh2_small.c
+++ /dev/null
@@ -1,833 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file mesh/test_mesh2_small.c
22 *
23 * @brief Test for the mesh service: retransmission of traffic.
24 */
25#include <stdio.h>
26#include "platform.h"
27#include "mesh2_test_lib.h"
28#include "gnunet_mesh2_service.h"
29#include <gauger.h>
30
31
32/**
33 * How namy messages to send
34 */
35#define TOTAL_PACKETS 1000
36
37/**
38 * How long until we give up on connecting the peers?
39 */
40#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
41
42/**
43 * Time to wait for stuff that should be rather fast
44 */
45#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
46
47/**
48 * DIFFERENT TESTS TO RUN
49 */
50#define SETUP 0
51#define FORWARD 1
52#define SPEED 3
53#define SPEED_ACK 4
54#define SPEED_NOBUF 6
55#define P2P_SIGNAL 10
56
57/**
58 * Which test are we running?
59 */
60static int test;
61
62/**
63 * String with test name
64 */
65char *test_name;
66
67/**
68 * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic.
69 */
70static int test_backwards = GNUNET_NO;
71
72/**
73 * How many events have happened
74 */
75static int ok;
76
77 /**
78 * Each peer is supposed to generate the following callbacks:
79 * 1 incoming tunnel (@dest)
80 * 1 connected peer (@orig)
81 * 1 received data packet (@dest)
82 * 1 received data packet (@orig)
83 * 1 received tunnel destroy (@dest)
84 * _________________________________
85 * 5 x ok expected per peer
86 */
87int ok_goal;
88
89
90/**
91 * Size of each test packet
92 */
93size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t);
94
95/**
96 * Operation to get peer ids.
97 */
98struct GNUNET_TESTBED_Operation *t_op[2];
99
100/**
101 * Peer ids.
102 */
103struct GNUNET_PeerIdentity *p_id[2];
104
105/**
106 * Peer ids counter.
107 */
108unsigned int p_ids;
109
110/**
111 * Is the setup initialized?
112 */
113static int initialized;
114
115/**
116 * Peers that have responded
117 */
118static int peers_responded;
119
120/**
121 * Number of payload packes sent
122 */
123static int data_sent;
124
125/**
126 * Number of payload packets received
127 */
128static int data_received;
129
130/**
131 * Number of payload packed explicitly (app level) acknowledged
132 */
133static int data_ack;
134
135/**
136 * Total number of currently running peers.
137 */
138static unsigned long long peers_running;
139
140/**
141 * Test context (to shut down).
142 */
143struct GNUNET_MESH_TEST_Context *test_ctx;
144
145/**
146 * Task called to disconnect peers.
147 */
148static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
149
150/**
151 * Task To perform tests
152 */
153static GNUNET_SCHEDULER_TaskIdentifier test_task;
154
155/**
156 * Task called to shutdown test.
157 */
158static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
159
160/**
161 * Mesh handle for the root peer
162 */
163static struct GNUNET_MESH_Handle *h1;
164
165/**
166 * Mesh handle for the first leaf peer
167 */
168static struct GNUNET_MESH_Handle *h2;
169
170/**
171 * Tunnel handle for the root peer
172 */
173static struct GNUNET_MESH_Tunnel *t;
174
175/**
176 * Tunnel handle for the first leaf peer
177 */
178static struct GNUNET_MESH_Tunnel *incoming_t;
179
180/**
181 * Time we started the data transmission (after tunnel has been established
182 * and initilized).
183 */
184static struct GNUNET_TIME_Absolute start_time;
185
186
187/**
188 * Show the results of the test (banwidth acheived) and log them to GAUGER
189 */
190static void
191show_end_data (void)
192{
193 static struct GNUNET_TIME_Absolute end_time;
194 static struct GNUNET_TIME_Relative total_time;
195
196 end_time = GNUNET_TIME_absolute_get();
197 total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time);
198 FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name);
199 FPRINTF (stderr, "Test time %llu ms\n",
200 (unsigned long long) total_time.rel_value);
201 FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
202 4 * TOTAL_PACKETS * 1.0 / total_time.rel_value); // 4bytes * ms
203 FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
204 TOTAL_PACKETS * 1000.0 / total_time.rel_value); // packets * ms
205 GAUGER ("MESH", test_name,
206 TOTAL_PACKETS * 1000.0 / total_time.rel_value,
207 "packets/s");
208}
209
210
211/**
212 * Shut down peergroup, clean up.
213 *
214 * @param cls Closure (unused).
215 * @param tc Task Context.
216 */
217static void
218shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
219{
220 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n");
221 shutdown_handle = GNUNET_SCHEDULER_NO_TASK;
222}
223
224
225/**
226 * Disconnect from mesh services af all peers, call shutdown.
227 *
228 * @param cls Closure (unused).
229 * @param tc Task Context.
230 */
231static void
232disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
233{
234 long line = (long) cls;
235 unsigned int i;
236
237 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
238 "disconnecting mesh service of peers, called from line %ld\n",
239 line);
240 disconnect_task = GNUNET_SCHEDULER_NO_TASK;
241 for (i = 0; i < 2; i++)
242 {
243 GNUNET_TESTBED_operation_done (t_op[i]);
244 }
245 if (NULL != t)
246 {
247 GNUNET_MESH_tunnel_destroy (t);
248 t = NULL;
249 }
250 if (NULL != incoming_t)
251 {
252 GNUNET_MESH_tunnel_destroy (incoming_t);
253 incoming_t = NULL;
254 }
255 GNUNET_MESH_TEST_cleanup (test_ctx);
256 if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle)
257 {
258 GNUNET_SCHEDULER_cancel (shutdown_handle);
259 }
260 shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
261}
262
263
264/**
265 * Abort test: schedule disconnect and shutdown immediately
266 *
267 * @param line Line in the code the abort is requested from (__LINE__).
268 */
269static void
270abort_test (long line)
271{
272 if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
273 {
274 GNUNET_SCHEDULER_cancel (disconnect_task);
275 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers,
276 (void *) line);
277 }
278}
279
280/**
281 * Transmit ready callback.
282 *
283 * @param cls Closure (message type).
284 * @param size Size of the tranmist buffer.
285 * @param buf Pointer to the beginning of the buffer.
286 *
287 * @return Number of bytes written to buf.
288 */
289static size_t
290tmt_rdy (void *cls, size_t size, void *buf);
291
292
293/**
294 * Task to schedule a new data transmission.
295 *
296 * @param cls Closure (peer #).
297 * @param tc Task Context.
298 */
299static void
300data_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
301{
302 struct GNUNET_MESH_TransmitHandle *th;
303 struct GNUNET_MESH_Tunnel *tunnel;
304
305 if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
306 return;
307
308 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data task\n");
309 if (GNUNET_YES == test_backwards)
310 {
311 tunnel = incoming_t;
312 }
313 else
314 {
315 tunnel = t;
316 }
317 th = GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
318 GNUNET_TIME_UNIT_FOREVER_REL,
319 size_payload, &tmt_rdy, (void *) 1L);
320 if (NULL == th)
321 {
322 unsigned long i = (unsigned long) cls;
323
324 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Retransmission\n");
325 if (0 == i)
326 {
327 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " in 1 ms\n");
328 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
329 &data_task, (void *)1UL);
330 }
331 else
332 {
333 i++;
334 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "in %u ms\n", i);
335 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(
336 GNUNET_TIME_UNIT_MILLISECONDS,
337 i),
338 &data_task, (void *)i);
339 }
340 }
341}
342
343
344/**
345 * Transmit ready callback
346 *
347 * @param cls Closure (message type).
348 * @param size Size of the buffer we have.
349 * @param buf Buffer to copy data to.
350 */
351size_t
352tmt_rdy (void *cls, size_t size, void *buf)
353{
354 struct GNUNET_MessageHeader *msg = buf;
355 uint32_t *data;
356
357 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
358 " tmt_rdy called\n");
359 if (size < size_payload || NULL == buf)
360 {
361 GNUNET_break (0);
362 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
363 "size %u, buf %p, data_sent %u, data_received %u\n",
364 size,
365 buf,
366 data_sent,
367 data_received);
368 return 0;
369 }
370 msg->size = htons (size);
371 msg->type = htons ((long) cls);
372 data = (uint32_t *) &msg[1];
373 *data = htonl (data_sent);
374 if (SPEED == test && GNUNET_YES == initialized)
375 {
376 data_sent++;
377 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
378 " Sent packet %d\n", data_sent);
379 if (data_sent < TOTAL_PACKETS)
380 {
381 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
382 " Scheduling packet %d\n", data_sent + 1);
383 GNUNET_SCHEDULER_add_now(&data_task, NULL);
384 }
385 }
386 return size_payload;
387}
388
389
390/**
391 * Function is called whenever a message is received.
392 *
393 * @param cls closure (set from GNUNET_MESH_connect)
394 * @param tunnel connection to the other end
395 * @param tunnel_ctx place to store local state associated with the tunnel
396 * @param message the actual message
397 * @return GNUNET_OK to keep the connection open,
398 * GNUNET_SYSERR to close it (signal serious error)
399 */
400int
401data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
402 const struct GNUNET_MessageHeader *message)
403{
404 long client = (long) cls;
405 long expected_target_client;
406 uint32_t *data;
407
408 ok++;
409
410 GNUNET_MESH_receive_done (tunnel);
411
412 if ((ok % 20) == 0)
413 {
414 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
415 {
416 GNUNET_SCHEDULER_cancel (disconnect_task);
417 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
418 &disconnect_mesh_peers,
419 (void *) __LINE__);
420 }
421 }
422
423 switch (client)
424 {
425 case 0L:
426 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n");
427 peers_responded++;
428 break;
429 case 4L:
430 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
431 "Leaf client %li got a message.\n",
432 client);
433 client = 4L;
434 break;
435 default:
436 GNUNET_assert (0);
437 break;
438 }
439 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal);
440 data = (uint32_t *) &message[1];
441 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload: (%u)\n", ntohl (*data));
442 if (SPEED == test && GNUNET_YES == test_backwards)
443 {
444 expected_target_client = 0L;
445 }
446 else
447 {
448 expected_target_client = 4L;
449 }
450
451 if (GNUNET_NO == initialized)
452 {
453 initialized = GNUNET_YES;
454 start_time = GNUNET_TIME_absolute_get ();
455 if (SPEED == test)
456 {
457 GNUNET_assert (4L == client);
458 GNUNET_SCHEDULER_add_now (&data_task, NULL);
459 return GNUNET_OK;
460 }
461 }
462
463 if (client == expected_target_client) // Normally 3 or 4
464 {
465 data_received++;
466 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
467 " received data %u\n", data_received);
468 if (SPEED != test || (ok_goal - 2) == ok)
469 {
470 GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
471 GNUNET_TIME_UNIT_FOREVER_REL,
472 size_payload, &tmt_rdy, (void *) 1L);
473 return GNUNET_OK;
474 }
475 else
476 {
477 if (data_received < TOTAL_PACKETS)
478 return GNUNET_OK;
479 }
480 }
481 else // Normally 0
482 {
483 if (test == SPEED_ACK || test == SPEED)
484 {
485 data_ack++;
486 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
487 " received ack %u\n", data_ack);
488 GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
489 GNUNET_TIME_UNIT_FOREVER_REL,
490 size_payload, &tmt_rdy, (void *) 1L);
491 if (data_ack < TOTAL_PACKETS && SPEED != test)
492 return GNUNET_OK;
493 if (ok == 2 && SPEED == test)
494 return GNUNET_OK;
495 show_end_data();
496 }
497 if (test == P2P_SIGNAL)
498 {
499 GNUNET_MESH_tunnel_destroy (incoming_t);
500 incoming_t = NULL;
501 }
502 else
503 {
504 GNUNET_MESH_tunnel_destroy (t);
505 t = NULL;
506 }
507 }
508
509 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
510 {
511 GNUNET_SCHEDULER_cancel (disconnect_task);
512 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
513 &disconnect_mesh_peers,
514 (void *) __LINE__);
515 }
516
517 return GNUNET_OK;
518}
519
520
521/**
522 * Handlers, for diverse services
523 */
524static struct GNUNET_MESH_MessageHandler handlers[] = {
525 {&data_callback, 1, sizeof (struct GNUNET_MessageHeader)},
526 {NULL, 0, 0}
527};
528
529
530/**
531 * Method called whenever another peer has added us to a tunnel
532 * the other peer initiated.
533 *
534 * @param cls Closure.
535 * @param tunnel New handle to the tunnel.
536 * @param initiator Peer that started the tunnel.
537 * @param port Port this tunnels is connected to.
538 * @return Initial tunnel context for the tunnel
539 * (can be NULL -- that's not an error).
540 */
541static void *
542incoming_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
543 const struct GNUNET_PeerIdentity *initiator,
544 uint32_t port)
545{
546 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
547 "Incoming tunnel from %s to peer %d\n",
548 GNUNET_i2s (initiator), (long) cls);
549 ok++;
550 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
551 if ((long) cls == 4L)
552 incoming_t = tunnel;
553 else
554 {
555 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
556 "Incoming tunnel for unknown client %lu\n", (long) cls);
557 GNUNET_break(0);
558 }
559 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
560 {
561 GNUNET_SCHEDULER_cancel (disconnect_task);
562 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
563 &disconnect_mesh_peers,
564 (void *) __LINE__);
565 }
566
567 return NULL;
568}
569
570/**
571 * Function called whenever an inbound tunnel is destroyed. Should clean up
572 * any associated state.
573 *
574 * @param cls closure (set from GNUNET_MESH_connect)
575 * @param tunnel connection to the other end (henceforth invalid)
576 * @param tunnel_ctx place where local state associated
577 * with the tunnel is stored
578 */
579static void
580tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
581 void *tunnel_ctx)
582{
583 long i = (long) cls;
584
585 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
586 "Incoming tunnel disconnected at peer %d\n",
587 i);
588 if (4L == i)
589 {
590 ok++;
591 incoming_t = NULL;
592 }
593 else if (0L == i && P2P_SIGNAL == test)
594 {
595 ok ++;
596 }
597 else
598 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
599 "Unknown peer! %d\n", i);
600 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
601
602 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
603 {
604 GNUNET_SCHEDULER_cancel (disconnect_task);
605 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers,
606 (void *) __LINE__);
607 }
608
609 return;
610}
611
612
613/**
614 * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE MESH SERVICES.
615 *
616 * Testcase continues when the root receives confirmation of connected peers,
617 * on callback funtion ch.
618 *
619 * @param cls Closure (unsued).
620 * @param tc Task Context.
621 */
622static void
623do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
624{
625 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_task\n");
626 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "add peer 2\n");
627
628 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
629 "schedule timeout in TIMEOUT\n");
630 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
631 {
632 GNUNET_SCHEDULER_cancel (disconnect_task);
633 }
634 t = GNUNET_MESH_tunnel_create (h1, NULL, p_id[1], 1);
635 if (SPEED_NOBUF == test)
636 {
637 GNUNET_MESH_tunnel_buffer(t, GNUNET_NO);
638 test = SPEED;
639 }
640
641 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
642 &disconnect_mesh_peers,
643 (void *) __LINE__);
644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
645 "Sending data initializer...\n");
646 peers_responded = 0;
647 data_ack = 0;
648 data_received = 0;
649 data_sent = 0;
650 GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO,
651 GNUNET_TIME_UNIT_FOREVER_REL,
652 size_payload, &tmt_rdy, (void *) 1L);
653}
654
655/**
656 * Callback to be called when the requested peer information is available
657 *
658 * @param cls the closure from GNUNET_TESTBED_peer_get_information()
659 * @param op the operation this callback corresponds to
660 * @param pinfo the result; will be NULL if the operation has failed
661 * @param emsg error message if the operation has failed;
662 * NULL if the operation is successfull
663 */
664static void
665pi_cb (void *cls,
666 struct GNUNET_TESTBED_Operation *op,
667 const struct GNUNET_TESTBED_PeerInformation *pinfo,
668 const char *emsg)
669{
670 long i = (long) cls;
671
672 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "id callback for %ld\n", i);
673
674 if (NULL == pinfo || NULL != emsg)
675 {
676 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
677 abort_test (__LINE__);
678 return;
679 }
680 p_id[i] = pinfo->result.id;
681 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i]));
682 p_ids++;
683 if (p_ids < 2)
684 return;
685 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n");
686 test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
687 &do_test, NULL);
688}
689
690/**
691 * test main: start test when all peers are connected
692 *
693 * @param cls Closure.
694 * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end.
695 * @param num_peers Number of peers that are running.
696 * @param peers Array of peers.
697 * @param meshes Handle to each of the MESHs of the peers.
698 */
699static void
700tmain (void *cls,
701 struct GNUNET_MESH_TEST_Context *ctx,
702 unsigned int num_peers,
703 struct GNUNET_TESTBED_Peer **peers,
704 struct GNUNET_MESH_Handle **meshes)
705{
706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n");
707 ok = 0;
708 test_ctx = ctx;
709 peers_running = num_peers;
710 h1 = meshes[0];
711 h2 = meshes[num_peers - 1];
712 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
713 &disconnect_mesh_peers,
714 (void *) __LINE__);
715 shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
716 &shutdown_task, NULL);
717 t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
718 GNUNET_TESTBED_PIT_IDENTITY,
719 &pi_cb, (void *) 0L);
720 t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
721 GNUNET_TESTBED_PIT_IDENTITY,
722 &pi_cb, (void *) 1L);
723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n");
724}
725
726
727/**
728 * Main: start test
729 */
730int
731main (int argc, char *argv[])
732{
733 initialized = GNUNET_NO;
734 uint32_t ports[2];
735
736 GNUNET_log_setup ("test", "DEBUG", NULL);
737
738 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n");
739 if (strstr (argv[0], "_small_forward") != NULL)
740 {
741 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n");
742 test = FORWARD;
743 test_name = "unicast2";
744 ok_goal = 4;
745 }
746 else if (strstr (argv[0], "_small_signal") != NULL)
747 {
748 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n");
749 test = P2P_SIGNAL;
750 test_name = "signal2";
751 ok_goal = 4;
752 }
753 else if (strstr (argv[0], "_small_speed_ack") != NULL)
754 {
755 /* Each peer is supposed to generate the following callbacks:
756 * 1 incoming tunnel (@dest)
757 * TOTAL_PACKETS received data packet (@dest)
758 * TOTAL_PACKETS received data packet (@orig)
759 * 1 received tunnel destroy (@dest)
760 * _________________________________
761 * 5 x ok expected per peer
762 */
763 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n");
764 test = SPEED_ACK;
765 test_name = "speed2 ack";
766 ok_goal = TOTAL_PACKETS * 2 + 2;
767 }
768 else if (strstr (argv[0], "_small_speed") != NULL)
769 {
770 /* Each peer is supposed to generate the following callbacks:
771 * 1 incoming tunnel (@dest)
772 * 1 initial packet (@dest)
773 * TOTAL_PACKETS received data packet (@dest)
774 * 1 received data packet (@orig)
775 * 1 received tunnel destroy (@dest)
776 * _________________________________
777 */
778 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n");
779 ok_goal = TOTAL_PACKETS + 4;
780 if (strstr (argv[0], "_nobuf") != NULL)
781 {
782 test = SPEED_NOBUF;
783 test_name = "speed2 nobuf";
784 }
785 else
786 {
787 test = SPEED;
788 test_name = "speed2";
789 }
790 }
791 else
792 {
793 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n");
794 test = SETUP;
795 ok_goal = 0;
796 }
797
798 if (strstr (argv[0], "backwards") != NULL)
799 {
800 char *aux;
801
802 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n");
803 test_backwards = GNUNET_YES;
804 aux = GNUNET_malloc (32);
805 sprintf (aux, "backwards %s", test_name);
806 test_name = aux;
807 }
808
809 p_ids = 0;
810 ports[0] = 1;
811 ports[1] = 0;
812 GNUNET_MESH_TEST_run ("test_mesh2_small",
813 "test_mesh2.conf",
814 5,
815 &tmain,
816 NULL, /* tmain cls */
817 &incoming_tunnel,
818 &tunnel_cleaner,
819 handlers,
820 ports);
821
822 if (ok_goal > ok)
823 {
824 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
825 "FAILED! (%d/%d)\n", ok, ok_goal);
826 return 1;
827 }
828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n");
829 return 0;
830}
831
832/* end of test_mesh_small.c */
833
diff --git a/src/mesh/test_mesh_2dtorus.c b/src/mesh/test_mesh_2dtorus.c
deleted file mode 100644
index 4b6affcc8..000000000
--- a/src/mesh/test_mesh_2dtorus.c
+++ /dev/null
@@ -1,128 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file mesh/test_mesh_2dtorus.c
22 *
23 * @brief Test for creating a 2dtorus.
24 */
25#include "platform.h"
26#include "mesh_test_lib.h"
27#include "gnunet_mesh_service.h"
28
29#define REMOVE_DIR GNUNET_YES
30
31/**
32 * How long until we give up on connecting the peers?
33 */
34#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500)
35
36/**
37 * Time to wait for stuff that should be rather fast
38 */
39#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
40
41
42/**
43 * How many events have happened
44 */
45static int ok;
46
47/**
48 * Total number of currently running peers.
49 */
50static unsigned long long peers_running;
51
52/**
53 * Task to time out.
54 */
55static GNUNET_SCHEDULER_TaskIdentifier timeout_task;
56
57
58static void
59shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
60{
61 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down test\n");
62}
63
64
65/**
66 * test main: start test when all peers are connected
67 *
68 * @param cls Closure.
69 * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end.
70 * @param num_peers Number of peers that are running.
71 * @param peers Array of peers.
72 * @param meshes Handle to each of the MESHs of the peers.
73 */
74static void
75tmain (void *cls,
76 struct GNUNET_MESH_TEST_Context *ctx,
77 unsigned int num_peers,
78 struct GNUNET_TESTBED_Peer **peers,
79 struct GNUNET_MESH_Handle **meshes)
80{
81 if (16 != num_peers)
82 {
83 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
84 "running peers mismatch, aborting test!\n");
85 ok--;
86 GNUNET_MESH_TEST_cleanup (ctx);
87 return;
88 }
89 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
90 "testbed started successfully with ?? connections\n");
91 peers_running = num_peers;
92 timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
93 &shutdown_task, ctx);
94 ok = GNUNET_OK;
95 GNUNET_MESH_TEST_cleanup (ctx);
96}
97
98
99/**
100 * Main: start test
101 */
102int
103main (int argc, char *argv[])
104{
105 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Start\n");
106 ok = GNUNET_SYSERR;
107
108 GNUNET_MESH_TEST_run ("test_mesh_2dtorus",
109 "test_mesh_2dtorus.conf",
110 16,
111 &tmain,
112 NULL,
113 NULL,
114 NULL,
115 NULL,
116 NULL
117 );
118
119 if (GNUNET_OK != ok)
120 {
121 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "FAILED!\n");
122 return 1;
123 }
124 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n");
125 return 0;
126}
127
128/* end of test_mesh_2dtorus.c */
diff --git a/src/mesh/test_mesh_2dtorus.conf b/src/mesh/test_mesh_2dtorus.conf
deleted file mode 100644
index 708ab0a50..000000000
--- a/src/mesh/test_mesh_2dtorus.conf
+++ /dev/null
@@ -1,71 +0,0 @@
1[PATHS]
2SERVICEHOME = /tmp/test_mesh_small/
3
4[mesh]
5PORT = 10005
6ACCEPT_FROM = 127.0.0.1;
7HOSTNAME = localhost
8DHT_REPLICATION_LEVEL = 10
9# PREFIX = valgrind --leak-check=full
10# PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
11
12[testing]
13WEAKRANDOM = YES
14
15[testbed]
16NUM_PEERS = 16
17OVERLAY_TOPOLOGY = 2D_TORUS
18
19[arm]
20PORT = 10010
21DEFAULTSERVICES = core dht mesh
22
23[statistics]
24AUTOSTART = YES
25PORT = 10000
26
27[dht]
28AUTOSTART = YES
29ACCEPT_FROM6 = ::1;
30ACCEPT_FROM = 127.0.0.1;
31HOSTNAME = localhost
32PORT = 10001
33DISABLE_TRY_CONNECT = YES
34
35[nse]
36WORKBITS = 0
37
38[dns]
39AUTOSTART = NO
40PORT = 10011
41
42[vpn]
43AUTOSTART = NO
44PORT = 10012
45
46[transport]
47PORT = 10002
48AUTOSTART = YES
49
50[nat]
51DISABLEV6 = YES
52BINDTO = 127.0.0.1
53ENABLE_UPNP = NO
54BEHIND_NAT = NO
55ALLOW_NAT = NO
56INTERNAL_ADDRESS = 127.0.0.1
57EXTERNAL_ADDRESS = 127.0.0.1
58RETURN_LOCAL_ADDRESSES = YES
59USE_LOCALADDR = YES
60
61[ats]
62WAN_QUOTA_IN = 1 GB
63WAN_QUOTA_OUT = 1 GB
64
65[core]
66AUTOSTART = YES
67PORT = 10003
68
69[peerinfo]
70AUTOSTART = YES
71PORT = 10004
diff --git a/src/mesh/test_mesh_api.c b/src/mesh/test_mesh_api.c
deleted file mode 100644
index 349ec80f0..000000000
--- a/src/mesh/test_mesh_api.c
+++ /dev/null
@@ -1,138 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file mesh/test_mesh_api.c
23 * @brief test mesh api: dummy test of callbacks
24 * @author Bartlomiej Polot
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_lib.h"
29#include "gnunet_dht_service.h"
30#include "gnunet_mesh_service.h"
31
32static struct GNUNET_MESH_Handle *mesh;
33
34static struct GNUNET_MESH_Tunnel *t;
35
36static int result;
37
38static GNUNET_SCHEDULER_TaskIdentifier abort_task;
39
40
41/**
42 * Function is called whenever a message is received.
43 *
44 * @param cls closure (set from GNUNET_MESH_connect)
45 * @param tunnel connection to the other end
46 * @param tunnel_ctx place to store local state associated with the tunnel
47 * @param sender who sent the message
48 * @param message the actual message
49 * @param atsi performance data for the connection
50 * @return GNUNET_OK to keep the connection open,
51 * GNUNET_SYSERR to close it (signal serious error)
52 */
53static int
54callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
55 const struct GNUNET_PeerIdentity *sender,
56 const struct GNUNET_MessageHeader *message,
57 const struct GNUNET_ATS_Information *atsi)
58{
59 return GNUNET_OK;
60}
61
62
63static struct GNUNET_MESH_MessageHandler handlers[] = {
64 { &callback, 1, 0 },
65 { NULL, 0, 0 }
66};
67
68
69static void
70do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
71{
72 if (NULL != t)
73 {
74 GNUNET_MESH_tunnel_destroy (t);
75 }
76 if (0 != abort_task)
77 {
78 GNUNET_SCHEDULER_cancel (abort_task);
79 }
80 if (NULL != mesh)
81 {
82 GNUNET_MESH_disconnect (mesh);
83 }
84}
85
86
87static void
88do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
89{
90 result = GNUNET_SYSERR;
91 abort_task = 0;
92 do_shutdown (cls, tc);
93}
94
95
96static void
97run (void *cls,
98 const struct GNUNET_CONFIGURATION_Handle *cfg,
99 struct GNUNET_TESTING_Peer *peer)
100{
101 static const GNUNET_MESH_ApplicationType app[] =
102 { 1, 2, 3, 4, 5, 6, 7, 8, 0 };
103
104 mesh = GNUNET_MESH_connect (cfg, NULL, NULL, NULL, handlers, app);
105 if (NULL == mesh)
106 {
107 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: Couldn't connect to mesh :(\n");
108 result = GNUNET_SYSERR;
109 return;
110 }
111 else
112 {
113 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: YAY! CONNECTED TO MESH :D\n");
114 }
115 t = GNUNET_MESH_tunnel_create (mesh, NULL, NULL, NULL, NULL);
116 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
117 (GNUNET_TIME_UNIT_SECONDS, 5), &do_shutdown,
118 NULL);
119 abort_task =
120 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
121 (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort,
122 NULL);
123}
124
125
126int
127main (int argc, char *argv[])
128{
129 result = GNUNET_OK;
130 if (0 != GNUNET_TESTING_peer_run ("test-mesh-api",
131 "test_mesh.conf",
132 &run, NULL))
133 return 1;
134 return (result == GNUNET_OK) ? 0 : 1;
135}
136
137/* end of test_mesh_api.c */
138
diff --git a/src/mesh/test_mesh2_local.c b/src/mesh/test_mesh_local.c
index 483135afa..058f02af6 100644
--- a/src/mesh/test_mesh2_local.c
+++ b/src/mesh/test_mesh_local.c
@@ -19,8 +19,8 @@
19*/ 19*/
20 20
21/** 21/**
22 * @file mesh/test_mesh2_local.c 22 * @file mesh/test_mesh_local.c
23 * @brief test mesh2 local: test of mesh2 tunnels with just one peer 23 * @brief test mesh local: test of mesh tunnels with just one peer
24 * @author Bartlomiej Polot 24 * @author Bartlomiej Polot
25 */ 25 */
26 26
@@ -28,7 +28,7 @@
28#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
29#include "gnunet_dht_service.h" 29#include "gnunet_dht_service.h"
30#include "gnunet_testing_lib.h" 30#include "gnunet_testing_lib.h"
31#include "gnunet_mesh2_service.h" 31#include "gnunet_mesh_service.h"
32 32
33struct GNUNET_TESTING_Peer *me; 33struct GNUNET_TESTING_Peer *me;
34 34
@@ -286,7 +286,7 @@ int
286main (int argc, char *argv[]) 286main (int argc, char *argv[])
287{ 287{
288 if (0 != GNUNET_TESTING_peer_run ("test-mesh-local", 288 if (0 != GNUNET_TESTING_peer_run ("test-mesh-local",
289 "test_mesh2.conf", 289 "test_mesh.conf",
290 &run, NULL)) 290 &run, NULL))
291 { 291 {
292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "run failed\n"); 292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "run failed\n");
diff --git a/src/mesh/test_mesh_local_1.c b/src/mesh/test_mesh_local_1.c
deleted file mode 100644
index 4f40688f5..000000000
--- a/src/mesh/test_mesh_local_1.c
+++ /dev/null
@@ -1,294 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file mesh/test_mesh_local_1.c
23 * @brief test mesh local: test of tunnels 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_mesh_service.h"
32
33
34static struct GNUNET_MESH_Handle *mesh_peer_1;
35
36static struct GNUNET_MESH_Handle *mesh_peer_2;
37
38static struct GNUNET_MESH_Tunnel *t;
39
40static unsigned int one = 1;
41
42static unsigned int two = 2;
43
44static int result = GNUNET_OK;
45
46static GNUNET_SCHEDULER_TaskIdentifier abort_task;
47
48static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
49
50
51/**
52 * Shutdown nicely
53 */
54static void
55do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
56{
57 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: shutdown\n");
58 if (0 != abort_task)
59 {
60 GNUNET_SCHEDULER_cancel (abort_task);
61 }
62 if (NULL != t)
63 {
64 GNUNET_MESH_tunnel_destroy(t);
65 }
66 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: D1\n");
67 if (NULL != mesh_peer_1)
68 {
69 GNUNET_MESH_disconnect (mesh_peer_1);
70 }
71 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: D2\n");
72 if (NULL != mesh_peer_2)
73 {
74 GNUNET_MESH_disconnect (mesh_peer_2);
75 }
76}
77
78
79/**
80 * Something went wrong and timed out. Kill everything and set error flag
81 */
82static void
83do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
84{
85 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: ABORT\n");
86 result = GNUNET_SYSERR;
87 abort_task = 0;
88 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
89 {
90 GNUNET_SCHEDULER_cancel (shutdown_task);
91 shutdown_task = GNUNET_SCHEDULER_NO_TASK;
92 }
93 do_shutdown (cls, tc);
94}
95
96
97/**
98 * Function is called whenever a message is received.
99 *
100 * @param cls closure (set from GNUNET_MESH_connect)
101 * @param tunnel connection to the other end
102 * @param tunnel_ctx place to store local state associated with the tunnel
103 * @param sender who sent the message
104 * @param message the actual message
105 * @param atsi performance data for the connection
106 * @return GNUNET_OK to keep the connection open,
107 * GNUNET_SYSERR to close it (signal serious error)
108 */
109static int
110data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
111 const struct GNUNET_PeerIdentity *sender,
112 const struct GNUNET_MessageHeader *message,
113 const struct GNUNET_ATS_Information *atsi)
114{
115 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Data callback\n");
116 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
117 GNUNET_SCHEDULER_cancel (shutdown_task);
118 shutdown_task =
119 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
120 (GNUNET_TIME_UNIT_SECONDS, 2), &do_shutdown,
121 NULL);
122 return GNUNET_OK;
123}
124
125
126/**
127 * Method called whenever another peer has added us to a tunnel
128 * the other peer initiated.
129 *
130 * @param cls closure
131 * @param tunnel new handle to the tunnel
132 * @param initiator peer that started the tunnel
133 * @param atsi performance information for the tunnel
134 * @return initial tunnel context for the tunnel (can be NULL -- that's not an error)
135 */
136static void *
137inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
138 const struct GNUNET_PeerIdentity *initiator,
139 const struct GNUNET_ATS_Information *atsi)
140{
141 unsigned int id = *(unsigned int *) cls;
142
143 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: received incoming tunnel\n");
144 if (id != 1)
145 {
146 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
147 "test: received incoming tunnel on peer 2\n");
148 result = GNUNET_SYSERR;
149 }
150 return NULL;
151}
152
153
154/**
155 * Function called whenever an inbound tunnel is destroyed. Should clean up
156 * any associated state.
157 *
158 * @param cls closure (set from GNUNET_MESH_connect)
159 * @param tunnel connection to the other end (henceforth invalid)
160 * @param tunnel_ctx place where local state associated
161 * with the tunnel is stored
162 */
163static void
164inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
165 void *tunnel_ctx)
166{
167 unsigned int id = *(unsigned int *) cls;
168
169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: incoming tunnel closed\n");
170 if (id != 1)
171 {
172 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
173 "test: received closing tunnel on peer 2\n");
174 result = GNUNET_SYSERR;
175 }
176}
177
178
179/**
180 * Method called whenever a peer has connected to the tunnel.
181 *
182 * @param cls closure
183 * @param peer peer identity the tunnel stopped working with
184 */
185static void
186peer_conected (void *cls, const struct GNUNET_PeerIdentity *peer,
187 const struct GNUNET_ATS_Information *atsi)
188{
189 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer connected\n");
190 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
191 GNUNET_SCHEDULER_cancel(shutdown_task);
192 shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
193 &do_shutdown, NULL);
194}
195
196
197/**
198 * Method called whenever a peer has connected to the tunnel.
199 *
200 * @param cls closure
201 * @param peer peer identity the tunnel was created to, NULL on timeout
202 * @param atsi performance data for the connection
203 */
204static void
205peer_disconnected (void *cls, const struct GNUNET_PeerIdentity *peer)
206{
207 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer disconnected\n");
208}
209
210
211/**
212 * Handler array for traffic received on peer1
213 */
214static struct GNUNET_MESH_MessageHandler handlers1[] = {
215 {&data_callback, 1, 0},
216 {NULL, 0, 0}
217};
218
219
220/**
221 * Handler array for traffic received on peer2 (none expected)
222 */
223static struct GNUNET_MESH_MessageHandler handlers2[] = { {NULL, 0, 0} };
224
225
226/**
227 * Start looking for a peer by type
228 */
229static void
230do_find (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
231{
232 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: CONNECT BY TYPE\n");
233 GNUNET_MESH_peer_request_connect_by_type (t, 1);
234}
235
236
237/**
238 * Initialize framework and start test
239 */
240static void
241run (void *cls,
242 const struct GNUNET_CONFIGURATION_Handle *cfg,
243 struct GNUNET_TESTING_Peer *peer)
244{
245 static const GNUNET_MESH_ApplicationType app1[] = { 1, 0 };
246 static const GNUNET_MESH_ApplicationType app2[] = { 0 };
247
248 abort_task =
249 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
250 (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort,
251 NULL);
252 mesh_peer_1 = GNUNET_MESH_connect (cfg, /* configuration */
253 (void *) &one, /* cls */
254 &inbound_tunnel, /* inbound new hndlr */
255 &inbound_end, /* inbound end hndlr */
256 handlers1, /* traffic handlers */
257 app1); /* apps offered */
258
259 mesh_peer_2 = GNUNET_MESH_connect (cfg, /* configuration */
260 (void *) &two, /* cls */
261 &inbound_tunnel, /* inbound new hndlr */
262 &inbound_end, /* inbound end hndlr */
263 handlers2, /* traffic handlers */
264 app2); /* apps offered */
265 if (NULL == mesh_peer_1 || NULL == mesh_peer_2)
266 {
267 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: Couldn't connect to mesh :(\n");
268 result = GNUNET_SYSERR;
269 return;
270 }
271 else
272 {
273 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: YAY! CONNECTED TO MESH :D\n");
274 }
275 t = GNUNET_MESH_tunnel_create (mesh_peer_2, NULL, &peer_conected,
276 &peer_disconnected, (void *) &two);
277 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_find, NULL);
278}
279
280
281/**
282 * Main
283 */
284int
285main (int argc, char *argv[])
286{
287 if (0 != GNUNET_TESTING_peer_run ("test-mesh-local-1",
288 "test_mesh.conf",
289 &run, NULL))
290 return 1;
291 return (result == GNUNET_OK) ? 0 : 1;
292}
293
294/* end of test_mesh_local_1.c */
diff --git a/src/mesh/test_mesh_local_2.c b/src/mesh/test_mesh_local_2.c
deleted file mode 100644
index 935c3b2eb..000000000
--- a/src/mesh/test_mesh_local_2.c
+++ /dev/null
@@ -1,290 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file mesh/test_mesh_local.c
23 * @brief test mesh local: test of tunnels with just one peer
24 * @author Bartlomiej Polot
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_testing_lib.h"
30#include "gnunet_dht_service.h"
31#include "gnunet_mesh_service.h"
32
33static struct GNUNET_MESH_Handle *mesh_peer_1;
34
35static struct GNUNET_MESH_Handle *mesh_peer_2;
36
37static struct GNUNET_MESH_Tunnel *t;
38
39static unsigned int one = 1;
40
41static unsigned int two = 2;
42
43static int result = GNUNET_OK;
44
45static GNUNET_SCHEDULER_TaskIdentifier abort_task;
46
47static GNUNET_SCHEDULER_TaskIdentifier test_task;
48
49
50/**
51 * Shutdown nicely
52 */
53static void
54do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
55{
56 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: shutdown\n");
57 if (0 != abort_task)
58 {
59 GNUNET_SCHEDULER_cancel (abort_task);
60 }
61 if (NULL != t)
62 {
63 GNUNET_MESH_tunnel_destroy(t);
64 }
65 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: D1\n");
66 if (NULL != mesh_peer_1)
67 {
68 GNUNET_MESH_disconnect (mesh_peer_1);
69 }
70 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: D2\n");
71 if (NULL != mesh_peer_2)
72 {
73 GNUNET_MESH_disconnect (mesh_peer_2);
74 }
75}
76
77
78/**
79 * Something went wrong and timed out. Kill everything and set error flag
80 */
81static void
82do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
83{
84 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: ABORT\n");
85 if (0 != test_task)
86 {
87 GNUNET_SCHEDULER_cancel (test_task);
88 }
89 result = GNUNET_SYSERR;
90 abort_task = 0;
91 do_shutdown (cls, tc);
92}
93
94
95/**
96 * Function is called whenever a message is received.
97 *
98 * @param cls closure (set from GNUNET_MESH_connect)
99 * @param tunnel connection to the other end
100 * @param tunnel_ctx place to store local state associated with the tunnel
101 * @param sender who sent the message
102 * @param message the actual message
103 * @param atsi performance data for the connection
104 * @return GNUNET_OK to keep the connection open,
105 * GNUNET_SYSERR to close it (signal serious error)
106 */
107static int
108data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
109 const struct GNUNET_PeerIdentity *sender,
110 const struct GNUNET_MessageHeader *message,
111 const struct GNUNET_ATS_Information *atsi)
112{
113 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Data callback\n");
114 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
115 (GNUNET_TIME_UNIT_SECONDS, 2), &do_shutdown,
116 NULL);
117 return GNUNET_OK;
118}
119
120
121/**
122 * Method called whenever another peer has added us to a tunnel
123 * the other peer initiated.
124 *
125 * @param cls closure
126 * @param tunnel new handle to the tunnel
127 * @param initiator peer that started the tunnel
128 * @param atsi performance information for the tunnel
129 * @return initial tunnel context for the tunnel (can be NULL -- that's not an error)
130 */
131static void *
132inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
133 const struct GNUNET_PeerIdentity *initiator,
134 const struct GNUNET_ATS_Information *atsi)
135{
136 unsigned int id = *(unsigned int *) cls;
137
138 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: received incoming tunnel\n");
139 if (id != 1)
140 {
141 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
142 "test: received incoming tunnel on peer 2\n");
143 result = GNUNET_SYSERR;
144 }
145 return NULL;
146}
147
148
149/**
150 * Function called whenever an inbound tunnel is destroyed. Should clean up
151 * any associated state.
152 *
153 * @param cls closure (set from GNUNET_MESH_connect)
154 * @param tunnel connection to the other end (henceforth invalid)
155 * @param tunnel_ctx place where local state associated
156 * with the tunnel is stored
157 */
158static void
159inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
160 void *tunnel_ctx)
161{
162 unsigned int id = *(unsigned int *) cls;
163
164 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: incoming tunnel closed\n");
165 if (id != 1)
166 {
167 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
168 "test: received closing tunnel on peer 2\n");
169 result = GNUNET_SYSERR;
170 }
171}
172
173
174/**
175 * Method called whenever a peer has disconnected from the tunnel.
176 *
177 * @param cls closure
178 * @param peer peer identity the tunnel stopped working with
179 */
180static void
181peer_conected (void *cls, const struct GNUNET_PeerIdentity *peer,
182 const struct GNUNET_ATS_Information *atsi)
183{
184 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer connected\n");
185 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown, NULL);
186}
187
188
189/**
190 * Method called whenever a peer has connected to the tunnel.
191 *
192 * @param cls closure
193 * @param peer peer identity the tunnel was created to, NULL on timeout
194 * @param atsi performance data for the connection
195 */
196static void
197peer_disconnected (void *cls, const struct GNUNET_PeerIdentity *peer)
198{
199 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer disconnected\n");
200}
201
202
203/**
204 * Handler array for traffic received on peer1
205 */
206static struct GNUNET_MESH_MessageHandler handlers1[] = {
207 {&data_callback, 1, 0},
208 {NULL, 0, 0}
209};
210
211
212/**
213 * Handler array for traffic received on peer2 (none expected)
214 */
215static struct GNUNET_MESH_MessageHandler handlers2[] = { {NULL, 0, 0} };
216
217
218/**
219 * Start looking for a peer by type
220 */
221static void
222do_connect_peer_1 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
223{
224 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
225 static const GNUNET_MESH_ApplicationType app1[] = { 1, 0 };
226
227 test_task = GNUNET_SCHEDULER_NO_TASK;
228 mesh_peer_1 = GNUNET_MESH_connect (cfg, /* configuration */
229 (void *) &one, /* cls */
230 &inbound_tunnel, /* inbound new hndlr */
231 &inbound_end, /* inbound end hndlr */
232 handlers1, /* traffic handlers */
233 app1); /* apps offered */
234}
235
236
237/**
238 * Initialize framework and start test
239 */
240static void
241run (void *cls,
242 const struct GNUNET_CONFIGURATION_Handle *cfg,
243 struct GNUNET_TESTING_Peer *peer)
244{
245 static const GNUNET_MESH_ApplicationType app2[] = { 0 };
246
247 abort_task =
248 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
249 (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort,
250 NULL);
251 mesh_peer_2 = GNUNET_MESH_connect (cfg, /* configuration */
252 (void *) &two, /* cls */
253 &inbound_tunnel, /* inbound new hndlr */
254 &inbound_end, /* inbound end hndlr */
255 handlers2, /* traffic handlers */
256 app2); /* apps offered */
257 if (NULL == mesh_peer_2)
258 {
259 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: Couldn't connect to mesh :(\n");
260 result = GNUNET_SYSERR;
261 return;
262 }
263 else
264 {
265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: YAY! CONNECTED TO MESH :D\n");
266 }
267 t = GNUNET_MESH_tunnel_create (mesh_peer_2, NULL, &peer_conected,
268 &peer_disconnected, (void *) &two);
269 GNUNET_MESH_peer_request_connect_by_type (t, 1);
270 test_task =
271 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
272 (GNUNET_TIME_UNIT_SECONDS, 5),
273 &do_connect_peer_1, (void*) cfg);
274}
275
276
277/**
278 * Main
279 */
280int
281main (int argc, char *argv[])
282{
283 if (0 != GNUNET_TESTING_peer_run ("test-mesh-local-2",
284 "test_mesh.conf",
285 &run, NULL))
286 return 1;
287 return (result == GNUNET_OK) ? 0 : 1;
288}
289
290/* end of test_mesh_local_2.c */
diff --git a/src/mesh/test_mesh_local_traffic.c b/src/mesh/test_mesh_local_traffic.c
deleted file mode 100644
index cd54ea8eb..000000000
--- a/src/mesh/test_mesh_local_traffic.c
+++ /dev/null
@@ -1,526 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file mesh/test_mesh_local_traffic.c
23 * @brief test mesh local traffic: test of tunnels with just one peer
24 * @author Bartlomiej Polot
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_mesh_service.h"
30#include "gnunet_testing_lib.h"
31#include <gauger.h>
32
33#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
34
35#define TARGET 1000
36
37/**
38 * DIFFERENT TESTS TO RUN
39 */
40#define FWD 0
41#define BCK 1
42#define BOTH 2
43
44
45GNUNET_NETWORK_STRUCT_BEGIN
46
47struct test_traffic_message
48{
49 struct GNUNET_MessageHeader header;
50 uint32_t data GNUNET_PACKED;
51};
52
53GNUNET_NETWORK_STRUCT_END
54
55
56/** Which test to run, based on executable name */
57static int test;
58
59static int started;
60
61/** How many packets to send from root to leaf */
62static unsigned int to_send_fwd;
63
64/** How many packets to send from leaf to root */
65static unsigned int to_send_bck;
66
67static unsigned int sent_fwd = 0;
68
69static unsigned int got_fwd = 0;
70
71static unsigned int sent_bck = 0;
72
73static unsigned int got_bck = 0;
74
75static struct GNUNET_MESH_Handle *mesh_peer_1;
76
77static struct GNUNET_MESH_Handle *mesh_peer_2;
78
79static struct GNUNET_MESH_Tunnel *t_fwd;
80
81static struct GNUNET_MESH_Tunnel *t_bck;
82
83static unsigned int one = 1;
84
85static unsigned int two = 2;
86
87static int result = GNUNET_SYSERR;
88
89static GNUNET_SCHEDULER_TaskIdentifier abort_task;
90
91static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
92
93static struct GNUNET_TIME_Absolute start_time;
94
95static struct GNUNET_TIME_Absolute end_time;
96
97static struct GNUNET_PeerIdentity peer_id;
98
99
100/**
101 * Shutdown nicely
102 */
103static void
104do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
105{
106 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutdown\n");
107 if (0 != abort_task)
108 {
109 GNUNET_SCHEDULER_cancel (abort_task);
110 }
111 if (NULL != t_fwd)
112 {
113 GNUNET_MESH_tunnel_destroy(t_fwd);
114 }
115 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "D1\n");
116 if (NULL != mesh_peer_1)
117 {
118 GNUNET_MESH_disconnect (mesh_peer_1);
119 }
120 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "D2\n");
121 if (NULL != mesh_peer_2)
122 {
123 GNUNET_MESH_disconnect (mesh_peer_2);
124 }
125}
126
127
128/**
129 * Something went wrong and timed out. Kill everything and set error flag
130 */
131static void
132do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
133{
134 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "ABORT\n");
135 result = GNUNET_SYSERR;
136 abort_task = 0;
137 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
138 {
139 GNUNET_SCHEDULER_cancel (shutdown_task);
140 shutdown_task = GNUNET_SCHEDULER_NO_TASK;
141 }
142 do_shutdown (cls, tc);
143}
144
145static void
146finish(void)
147{
148 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
149 GNUNET_SCHEDULER_cancel(shutdown_task);
150 shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
151 &do_shutdown, NULL);
152}
153
154
155/**
156 * Transmit ready callback.
157 *
158 * @param cls Closure (peer number of peer sending the data).
159 * @param size Buffer size.
160 * @param buf Buffer.
161 */
162static size_t
163tmt_rdy (void *cls, size_t size, void *buf)
164{
165 unsigned int peer_number = *(unsigned int *) cls;
166 struct GNUNET_MessageHeader *m = buf;
167 struct GNUNET_MESH_Tunnel *t;
168 struct test_traffic_message *msg = buf;
169 size_t msize = sizeof (struct test_traffic_message);
170 unsigned int *sent;
171 unsigned int target;
172 char *s;
173
174 if (0 == size || NULL == buf)
175 return 0;
176
177 if (1 == peer_number)
178 {
179 sent = &sent_fwd;
180 target = to_send_fwd;
181 t = t_fwd;
182 s = "FWD";
183 }
184 else if (2 == peer_number)
185 {
186 sent = &sent_bck;
187 target = to_send_bck;
188 t = t_bck;
189 s = "BCK";
190 }
191 else
192 GNUNET_abort();
193
194 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %s data packet # %4u\n",
195 s, *sent);
196 GNUNET_assert (size >= msize);
197 if (GNUNET_YES == started)
198 {
199 (*sent)++;
200 if (target > *sent) {
201 GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO,
202 GNUNET_TIME_UNIT_FOREVER_REL,
203 &peer_id, msize, &tmt_rdy, cls);
204 }
205 }
206 m->size = htons (msize);
207 m->type = htons (1);
208 msg->data = htonl (*sent - 1);
209 return msize;
210}
211
212
213/**
214 * Function is called whenever a message is received.
215 *
216 * @param cls closure (set from GNUNET_MESH_connect)
217 * @param tunnel connection to the other end
218 * @param tunnel_ctx place to store local state associated with the tunnel
219 * @param sender who sent the message
220 * @param message the actual message
221 * @param atsi performance data for the connection
222 * @return GNUNET_OK to keep the connection open,
223 * GNUNET_SYSERR to close it (signal serious error)
224 */
225static int
226data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
227 const struct GNUNET_PeerIdentity *sender,
228 const struct GNUNET_MessageHeader *message,
229 const struct GNUNET_ATS_Information *atsi)
230{
231 struct test_traffic_message *msg;
232 unsigned int *peer_number = cls;
233 unsigned int *got;
234 unsigned int target;
235
236 if (GNUNET_NO == started)
237 {
238 GNUNET_break (2 == *peer_number);
239 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got initial data packet\n");
240 started = GNUNET_YES;
241 start_time = GNUNET_TIME_absolute_get();
242 if (FWD != test) // Send leaf -> root
243 {
244 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending first BCK data\n");
245 GNUNET_MESH_notify_transmit_ready (t_bck, GNUNET_NO,
246 GNUNET_TIME_UNIT_FOREVER_REL,
247 NULL,
248 sizeof (struct test_traffic_message),
249 &tmt_rdy, &two);
250 }
251 if (BCK != test) // Send root -> leaf
252 {
253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending first FWD data\n");
254 GNUNET_MESH_notify_transmit_ready (t_fwd, GNUNET_NO,
255 GNUNET_TIME_UNIT_FOREVER_REL,
256 &peer_id,
257 sizeof (struct test_traffic_message),
258 &tmt_rdy, &one);
259 }
260 return GNUNET_OK;
261 }
262
263 if (*peer_number == 1)
264 {
265 got = &got_bck;
266 target = to_send_bck;
267 }
268 else if (*peer_number == 2)
269 {
270 got = &got_fwd;
271 target = to_send_fwd;
272 }
273 else
274 {
275 GNUNET_abort();
276 }
277 msg = (struct test_traffic_message *) message;
278 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got data packet # %u [%u]\n",
279 ntohl (msg->data), *got + 1);
280 (*got)++;
281 if (target == *got)
282 {
283 if (to_send_bck == sent_bck && to_send_fwd == sent_fwd) {
284 end_time = GNUNET_TIME_absolute_get();
285 result = GNUNET_OK;
286 finish();
287 }
288 return GNUNET_OK;
289 }
290 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
291 GNUNET_SCHEDULER_cancel (shutdown_task);
292 shutdown_task =
293 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &do_shutdown,
294 NULL);
295 return GNUNET_OK;
296}
297
298
299/**
300 * Method called whenever another peer has added us to a tunnel
301 * the other peer initiated.
302 *
303 * @param cls closure
304 * @param tunnel new handle to the tunnel
305 * @param initiator peer that started the tunnel
306 * @param atsi performance information for the tunnel
307 * @return initial tunnel context for the tunnel (can be NULL -- that's not an error)
308 */
309static void *
310inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
311 const struct GNUNET_PeerIdentity *initiator,
312 const struct GNUNET_ATS_Information *atsi)
313{
314 unsigned int id = *(unsigned int *) cls;
315
316 t_bck = tunnel;
317 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "received incoming tunnel %p\n", tunnel);
318 if (id != 2)
319 {
320 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
321 "received incoming tunnel on peer 1\n");
322 result = GNUNET_SYSERR;
323 }
324 return NULL;
325}
326
327
328/**
329 * Function called whenever an inbound tunnel is destroyed. Should clean up
330 * any associated state.
331 *
332 * @param cls closure (set from GNUNET_MESH_connect)
333 * @param tunnel connection to the other end (henceforth invalid)
334 * @param tunnel_ctx place where local state associated
335 * with the tunnel is stored
336 */
337static void
338inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
339 void *tunnel_ctx)
340{
341 unsigned int id = *(unsigned int *) cls;
342
343 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "incoming tunnel closed\n");
344 if (id != 2)
345 {
346 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
347 "received closing tunnel on peer 1\n");
348 result = GNUNET_SYSERR;
349 }
350}
351
352
353/**
354 * Method called whenever a peer has connected to the tunnel.
355 *
356 * @param cls Closure.
357 * @param peer Peer identity of connected peer.
358 */
359static void
360peer_connected (void *cls, const struct GNUNET_PeerIdentity *peer,
361 const struct GNUNET_ATS_Information *atsi)
362{
363 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer connected\n");
364 peer_id = *peer;
365 /* Force an inbound tunnel notification on peer 2 */
366 GNUNET_MESH_notify_transmit_ready (t_fwd, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL,
367 peer, sizeof (struct test_traffic_message),
368 &tmt_rdy, &one);
369}
370
371
372/**
373 * Method called whenever a peer has connected to the tunnel.
374 *
375 * @param cls closure
376 * @param peer peer identity the tunnel was created to, NULL on timeout
377 * @param atsi performance data for the connection
378 */
379static void
380peer_disconnected (void *cls, const struct GNUNET_PeerIdentity *peer)
381{
382 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer disconnected\n");
383}
384
385
386/**
387 * Handler array for traffic received on peer1
388 */
389static struct GNUNET_MESH_MessageHandler handlers[] = {
390 {&data_callback, 1, sizeof (struct test_traffic_message)},
391 {NULL, 0, 0}
392};
393
394
395/**
396 * Handler array for traffic received on peer2 (none expected)
397 */
398static struct GNUNET_MESH_MessageHandler handlers_null[] = { {NULL, 0, 0} };
399
400
401/**
402 * Initialize framework and start test
403 */
404static void
405run (void *cls,
406 const struct GNUNET_CONFIGURATION_Handle *cfg,
407 struct GNUNET_TESTING_Peer *peer)
408{
409 static const GNUNET_MESH_ApplicationType app1[] = { 0 };
410 static const GNUNET_MESH_ApplicationType app2[] = { 1, 0 };
411
412 abort_task =
413 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
414 (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort,
415 NULL);
416 mesh_peer_1 = GNUNET_MESH_connect (cfg, /* configuration */
417 (void *) &one, /* cls */
418 NULL, /* inbound new hndlr */
419 NULL, /* inbound end hndlr */
420 /* traffic handlers */
421 test == FWD ? handlers_null : handlers,
422 app1); /* apps offered */
423
424 mesh_peer_2 = GNUNET_MESH_connect (cfg, /* configuration */
425 (void *) &two, /* cls */
426 &inbound_tunnel, /* inbound new hndlr */
427 &inbound_end, /* inbound end hndlr */
428 handlers, /* traffic handlers */
429 app2); /* apps offered */
430 if (NULL == mesh_peer_1 || NULL == mesh_peer_2)
431 {
432 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh\n");
433 result = GNUNET_SYSERR;
434 return;
435 }
436 else
437 {
438 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to mesh\n");
439 }
440 t_fwd = GNUNET_MESH_tunnel_create (mesh_peer_1, NULL, &peer_connected,
441 &peer_disconnected, (void *) &two);
442 GNUNET_MESH_peer_request_connect_by_type (t_fwd, 1);
443}
444
445
446/**
447 * Main
448 */
449int
450main (int argc, char *argv[])
451{
452 if (strstr (argv[0], "test_mesh_local_traffic_fwd") != NULL)
453 {
454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FWD\n");
455 test = FWD;
456 to_send_fwd = TARGET;
457 }
458 else if (strstr (argv[0], "test_mesh_local_traffic_bck") != NULL)
459 {
460 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BCK\n");
461 test = BCK;
462 to_send_bck = TARGET;
463 }
464 else if (strstr (argv[0], "test_mesh_local_traffic_both") != NULL)
465 {
466 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BOTH\n");
467 test = BOTH;
468 to_send_bck = to_send_fwd = TARGET;
469 }
470 else
471 {
472 return 1;
473 }
474
475 if (0 != GNUNET_TESTING_peer_run ("test-mesh-local-traffic",
476 "test_mesh.conf",
477 &run, NULL))
478 return 1;
479 if (result != GNUNET_OK)
480 {
481 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
482 "Failed.\nFWD expected: %u, Sent: %u, Got: %u\n",
483 to_send_fwd, sent_fwd, got_fwd);
484 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
485 "BCK expected: %u, Sent: %u, Got: %u\n",
486 to_send_bck, sent_bck, got_bck);
487 return 1;
488 }
489 else
490 {
491 struct GNUNET_TIME_Relative total_time;
492 unsigned int total_traffic;
493 char *name;
494
495 total_traffic = BOTH == test ? 2 * TARGET : TARGET;
496 switch (test)
497 {
498 case FWD:
499 name = "Local traffic Root to Leaf";
500 break;
501 case BCK:
502 name = "Local traffic Leaf to Root";
503 break;
504 case BOTH:
505 name = "Local traffic bidirectional";
506 break;
507 default:
508 GNUNET_assert (0);
509 }
510
511 total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time);
512 FPRINTF (stderr, "\nTest time %llu ms\n",
513 (unsigned long long) total_time.rel_value);
514 FPRINTF (stderr, "Test payload bandwidth: %f kb/s\n",
515 total_traffic * 4.0 / total_time.rel_value); // 4bytes * kb/ms
516 FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
517 total_traffic * 1000.0 / total_time.rel_value); // 1000 packets * ms
518 GAUGER ("MESH",
519 name,
520 total_traffic * 1000.0 / total_time.rel_value,
521 "packets/s");
522 }
523 return 0;
524}
525
526/* end of test_mesh_local_traffic.c */
diff --git a/src/mesh/test_mesh_small.c b/src/mesh/test_mesh_small.c
index efe939876..81f9c566c 100644
--- a/src/mesh/test_mesh_small.c
+++ b/src/mesh/test_mesh_small.c
@@ -48,11 +48,9 @@
48 * DIFFERENT TESTS TO RUN 48 * DIFFERENT TESTS TO RUN
49 */ 49 */
50#define SETUP 0 50#define SETUP 0
51#define UNICAST 1 51#define FORWARD 1
52#define MULTICAST 2
53#define SPEED 3 52#define SPEED 3
54#define SPEED_ACK 4 53#define SPEED_ACK 4
55#define SPEED_MIN 5
56#define SPEED_NOBUF 6 54#define SPEED_NOBUF 6
57#define P2P_SIGNAL 10 55#define P2P_SIGNAL 10
58 56
@@ -97,12 +95,12 @@ size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t);
97/** 95/**
98 * Operation to get peer ids. 96 * Operation to get peer ids.
99 */ 97 */
100struct GNUNET_TESTBED_Operation *t_op[3]; 98struct GNUNET_TESTBED_Operation *t_op[2];
101 99
102/** 100/**
103 * Peer ids. 101 * Peer ids.
104 */ 102 */
105struct GNUNET_PeerIdentity *p_id[3]; 103struct GNUNET_PeerIdentity *p_id[2];
106 104
107/** 105/**
108 * Peer ids counter. 106 * Peer ids counter.
@@ -115,11 +113,6 @@ unsigned int p_ids;
115static int initialized; 113static int initialized;
116 114
117/** 115/**
118 * Peers that have been connected
119 */
120static int peers_in_tunnel;
121
122/**
123 * Peers that have responded 116 * Peers that have responded
124 */ 117 */
125static int peers_responded; 118static int peers_responded;
@@ -175,11 +168,6 @@ static struct GNUNET_MESH_Handle *h1;
175static struct GNUNET_MESH_Handle *h2; 168static struct GNUNET_MESH_Handle *h2;
176 169
177/** 170/**
178 * Mesh handle for the second leaf peer
179 */
180static struct GNUNET_MESH_Handle *h3;
181
182/**
183 * Tunnel handle for the root peer 171 * Tunnel handle for the root peer
184 */ 172 */
185static struct GNUNET_MESH_Tunnel *t; 173static struct GNUNET_MESH_Tunnel *t;
@@ -190,11 +178,6 @@ static struct GNUNET_MESH_Tunnel *t;
190static struct GNUNET_MESH_Tunnel *incoming_t; 178static struct GNUNET_MESH_Tunnel *incoming_t;
191 179
192/** 180/**
193 * Tunnel handle for the second leaf peer
194 */
195static struct GNUNET_MESH_Tunnel *incoming_t2;
196
197/**
198 * Time we started the data transmission (after tunnel has been established 181 * Time we started the data transmission (after tunnel has been established
199 * and initilized). 182 * and initilized).
200 */ 183 */
@@ -251,16 +234,14 @@ disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
251 long line = (long) cls; 234 long line = (long) cls;
252 unsigned int i; 235 unsigned int i;
253 236
254 for (i = 0; i < 3; i++)
255 if (NULL != t_op[i])
256 {
257 GNUNET_TESTBED_operation_done (t_op[i]);
258 t_op[i] = NULL;
259 }
260 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 237 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
261 "disconnecting mesh service of peers, called from line %ld\n", 238 "disconnecting mesh service of peers, called from line %ld\n",
262 line); 239 line);
263 disconnect_task = GNUNET_SCHEDULER_NO_TASK; 240 disconnect_task = GNUNET_SCHEDULER_NO_TASK;
241 for (i = 0; i < 2; i++)
242 {
243 GNUNET_TESTBED_operation_done (t_op[i]);
244 }
264 if (NULL != t) 245 if (NULL != t)
265 { 246 {
266 GNUNET_MESH_tunnel_destroy (t); 247 GNUNET_MESH_tunnel_destroy (t);
@@ -271,11 +252,6 @@ disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
271 GNUNET_MESH_tunnel_destroy (incoming_t); 252 GNUNET_MESH_tunnel_destroy (incoming_t);
272 incoming_t = NULL; 253 incoming_t = NULL;
273 } 254 }
274 if (NULL != incoming_t2)
275 {
276 GNUNET_MESH_tunnel_destroy (incoming_t2);
277 incoming_t2 = NULL;
278 }
279 GNUNET_MESH_TEST_cleanup (test_ctx); 255 GNUNET_MESH_TEST_cleanup (test_ctx);
280 if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle) 256 if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle)
281 { 257 {
@@ -290,16 +266,15 @@ disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
290 * 266 *
291 * @param line Line in the code the abort is requested from (__LINE__). 267 * @param line Line in the code the abort is requested from (__LINE__).
292 */ 268 */
293void 269static void
294abort_test (long line) 270abort_test (long line)
295{ 271{
296 if (disconnect_task != GNUNET_SCHEDULER_NO_TASK) 272 if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
297 { 273 {
298 GNUNET_SCHEDULER_cancel (disconnect_task); 274 GNUNET_SCHEDULER_cancel (disconnect_task);
275 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers,
276 (void *) line);
299 } 277 }
300 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
301 &disconnect_mesh_peers,
302 (void *) line);
303} 278}
304 279
305/** 280/**
@@ -326,7 +301,6 @@ data_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
326{ 301{
327 struct GNUNET_MESH_TransmitHandle *th; 302 struct GNUNET_MESH_TransmitHandle *th;
328 struct GNUNET_MESH_Tunnel *tunnel; 303 struct GNUNET_MESH_Tunnel *tunnel;
329 struct GNUNET_PeerIdentity *destination;
330 304
331 if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) 305 if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
332 return; 306 return;
@@ -335,18 +309,14 @@ data_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
335 if (GNUNET_YES == test_backwards) 309 if (GNUNET_YES == test_backwards)
336 { 310 {
337 tunnel = incoming_t; 311 tunnel = incoming_t;
338 destination = p_id[0];
339 } 312 }
340 else 313 else
341 { 314 {
342 tunnel = t; 315 tunnel = t;
343 destination = p_id[2];
344 } 316 }
345 th = GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO, 317 th = GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
346 GNUNET_TIME_UNIT_FOREVER_REL, 318 GNUNET_TIME_UNIT_FOREVER_REL,
347 destination, 319 size_payload, &tmt_rdy, (void *) 1L);
348 size_payload,
349 &tmt_rdy, (void *) 1L);
350 if (NULL == th) 320 if (NULL == th)
351 { 321 {
352 unsigned long i = (unsigned long) cls; 322 unsigned long i = (unsigned long) cls;
@@ -423,17 +393,13 @@ tmt_rdy (void *cls, size_t size, void *buf)
423 * @param cls closure (set from GNUNET_MESH_connect) 393 * @param cls closure (set from GNUNET_MESH_connect)
424 * @param tunnel connection to the other end 394 * @param tunnel connection to the other end
425 * @param tunnel_ctx place to store local state associated with the tunnel 395 * @param tunnel_ctx place to store local state associated with the tunnel
426 * @param sender who sent the message
427 * @param message the actual message 396 * @param message the actual message
428 * @param atsi performance data for the connection
429 * @return GNUNET_OK to keep the connection open, 397 * @return GNUNET_OK to keep the connection open,
430 * GNUNET_SYSERR to close it (signal serious error) 398 * GNUNET_SYSERR to close it (signal serious error)
431 */ 399 */
432int 400int
433data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, 401data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
434 const struct GNUNET_PeerIdentity *sender, 402 const struct GNUNET_MessageHeader *message)
435 const struct GNUNET_MessageHeader *message,
436 const struct GNUNET_ATS_Information *atsi)
437{ 403{
438 long client = (long) cls; 404 long client = (long) cls;
439 long expected_target_client; 405 long expected_target_client;
@@ -441,15 +407,17 @@ data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
441 407
442 ok++; 408 ok++;
443 409
410 GNUNET_MESH_receive_done (tunnel);
411
444 if ((ok % 20) == 0) 412 if ((ok % 20) == 0)
445 { 413 {
446 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) 414 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
447 { 415 {
448 GNUNET_SCHEDULER_cancel (disconnect_task); 416 GNUNET_SCHEDULER_cancel (disconnect_task);
417 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
418 &disconnect_mesh_peers,
419 (void *) __LINE__);
449 } 420 }
450 disconnect_task =
451 GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers,
452 (void *) __LINE__);
453 } 421 }
454 422
455 switch (client) 423 switch (client)
@@ -457,10 +425,7 @@ data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
457 case 0L: 425 case 0L:
458 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n"); 426 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n");
459 peers_responded++; 427 peers_responded++;
460 if (test == MULTICAST && peers_responded < 2)
461 return GNUNET_OK;
462 break; 428 break;
463 case 3L:
464 case 4L: 429 case 4L:
465 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 430 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
466 "Leaf client %li got a message.\n", 431 "Leaf client %li got a message.\n",
@@ -503,9 +468,8 @@ data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
503 if (SPEED != test || (ok_goal - 2) == ok) 468 if (SPEED != test || (ok_goal - 2) == ok)
504 { 469 {
505 GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO, 470 GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
506 GNUNET_TIME_UNIT_FOREVER_REL, sender, 471 GNUNET_TIME_UNIT_FOREVER_REL,
507 size_payload, 472 size_payload, &tmt_rdy, (void *) 1L);
508 &tmt_rdy, (void *) 1L);
509 return GNUNET_OK; 473 return GNUNET_OK;
510 } 474 }
511 else 475 else
@@ -522,9 +486,8 @@ data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
522 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 486 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
523 " received ack %u\n", data_ack); 487 " received ack %u\n", data_ack);
524 GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO, 488 GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
525 GNUNET_TIME_UNIT_FOREVER_REL, sender, 489 GNUNET_TIME_UNIT_FOREVER_REL,
526 size_payload, 490 size_payload, &tmt_rdy, (void *) 1L);
527 &tmt_rdy, (void *) 1L);
528 if (data_ack < TOTAL_PACKETS && SPEED != test) 491 if (data_ack < TOTAL_PACKETS && SPEED != test)
529 return GNUNET_OK; 492 return GNUNET_OK;
530 if (ok == 2 && SPEED == test) 493 if (ok == 2 && SPEED == test)
@@ -546,10 +509,10 @@ data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
546 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) 509 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
547 { 510 {
548 GNUNET_SCHEDULER_cancel (disconnect_task); 511 GNUNET_SCHEDULER_cancel (disconnect_task);
512 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
513 &disconnect_mesh_peers,
514 (void *) __LINE__);
549 } 515 }
550 disconnect_task =
551 GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers,
552 (void *) __LINE__);
553 516
554 return GNUNET_OK; 517 return GNUNET_OK;
555} 518}
@@ -568,17 +531,17 @@ static struct GNUNET_MESH_MessageHandler handlers[] = {
568 * Method called whenever another peer has added us to a tunnel 531 * Method called whenever another peer has added us to a tunnel
569 * the other peer initiated. 532 * the other peer initiated.
570 * 533 *
571 * @param cls closure 534 * @param cls Closure.
572 * @param tunnel new handle to the tunnel 535 * @param tunnel New handle to the tunnel.
573 * @param initiator peer that started the tunnel 536 * @param initiator Peer that started the tunnel.
574 * @param atsi performance information for the tunnel 537 * @param port Port this tunnels is connected to.
575 * @return initial tunnel context for the tunnel 538 * @return Initial tunnel context for the tunnel
576 * (can be NULL -- that's not an error) 539 * (can be NULL -- that's not an error).
577 */ 540 */
578static void * 541static void *
579incoming_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel, 542incoming_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
580 const struct GNUNET_PeerIdentity *initiator, 543 const struct GNUNET_PeerIdentity *initiator,
581 const struct GNUNET_ATS_Information *atsi) 544 uint32_t port)
582{ 545{
583 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 546 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
584 "Incoming tunnel from %s to peer %d\n", 547 "Incoming tunnel from %s to peer %d\n",
@@ -587,8 +550,6 @@ incoming_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
587 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); 550 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
588 if ((long) cls == 4L) 551 if ((long) cls == 4L)
589 incoming_t = tunnel; 552 incoming_t = tunnel;
590 else if ((long) cls == 3L)
591 incoming_t2 = tunnel;
592 else 553 else
593 { 554 {
594 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 555 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -598,10 +559,10 @@ incoming_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
598 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) 559 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
599 { 560 {
600 GNUNET_SCHEDULER_cancel (disconnect_task); 561 GNUNET_SCHEDULER_cancel (disconnect_task);
562 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
563 &disconnect_mesh_peers,
564 (void *) __LINE__);
601 } 565 }
602 disconnect_task =
603 GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers,
604 (void *) __LINE__);
605 566
606 return NULL; 567 return NULL;
607} 568}
@@ -629,129 +590,22 @@ tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
629 ok++; 590 ok++;
630 incoming_t = NULL; 591 incoming_t = NULL;
631 } 592 }
632 else if (3L == i) 593 else if (0L == i && P2P_SIGNAL == test)
633 { 594 {
634 ok++; 595 ok ++;
635 incoming_t2 = NULL;
636 } 596 }
637 else 597 else
638 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 598 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
639 "Unknown peer! %d\n", i); 599 "Unknown peer! %d\n", i);
640 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); 600 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
641 peers_in_tunnel--;
642 if (peers_in_tunnel > 0)
643 return;
644 601
645 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) 602 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
646 { 603 {
647 GNUNET_SCHEDULER_cancel (disconnect_task); 604 GNUNET_SCHEDULER_cancel (disconnect_task);
648 }
649 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers,
650 (void *) __LINE__);
651
652 return;
653}
654
655
656/**
657 * Method called whenever a tunnel falls apart.
658 *
659 * @param cls closure
660 * @param peer peer identity the tunnel stopped working with
661 */
662static void
663dh (void *cls, const struct GNUNET_PeerIdentity *peer)
664{
665 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
666 "peer %s disconnected\n",
667 GNUNET_i2s (peer));
668 if (P2P_SIGNAL == test)
669 {
670 ok ++;
671 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
672 {
673 GNUNET_SCHEDULER_cancel (disconnect_task);
674 }
675 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers, 605 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers,
676 (void *) __LINE__); 606 (void *) __LINE__);
677 } 607 }
678 return;
679}
680
681
682/**
683 * Method called whenever a peer connects to a tunnel.
684 *
685 * @param cls closure
686 * @param peer peer identity the tunnel was created to, NULL on timeout
687 * @param atsi performance data for the connection
688 */
689static void
690ch (void *cls, const struct GNUNET_PeerIdentity *peer,
691 const struct GNUNET_ATS_Information *atsi)
692{
693 long i = (long) cls;
694
695 struct GNUNET_PeerIdentity *dest;
696 608
697 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
698 "%ld peer %s connected\n", i, GNUNET_i2s (peer));
699
700 if (0 == memcmp (p_id[2], peer, sizeof (struct GNUNET_PeerIdentity)) &&
701 i == 0L)
702 {
703 ok++;
704 }
705 if (test == MULTICAST &&
706 0 == memcmp (p_id[1], peer, sizeof (struct GNUNET_PeerIdentity)) &&
707 i == 0L)
708 {
709 ok++;
710 }
711 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
712 switch (test)
713 {
714 case UNICAST:
715 case P2P_SIGNAL:
716 case SPEED:
717 case SPEED_ACK:
718 // incoming_t is NULL unless we send a relevant data packet
719 dest = p_id[2];
720 break;
721 case MULTICAST:
722 peers_in_tunnel++;
723 if (peers_in_tunnel < 2)
724 return;
725 dest = NULL;
726 break;
727 default:
728 GNUNET_assert (0);
729 return;
730 }
731 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
732 {
733 GNUNET_SCHEDULER_cancel (disconnect_task);
734 disconnect_task =
735 GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers,
736 (void *) __LINE__);
737 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
738 "Sending data initializer...\n");
739 peers_responded = 0;
740 data_ack = 0;
741 data_received = 0;
742 data_sent = 0;
743 GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO,
744 GNUNET_TIME_UNIT_FOREVER_REL, dest,
745 size_payload,
746 &tmt_rdy, (void *) 1L);
747 }
748 else
749 {
750 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
751 "Disconnect already run?\n");
752 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
753 "Aborting...\n");
754 }
755 return; 609 return;
756} 610}
757 611
@@ -770,14 +624,6 @@ do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
770{ 624{
771 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_task\n"); 625 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_task\n");
772 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "add peer 2\n"); 626 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "add peer 2\n");
773 GNUNET_MESH_peer_request_connect_add (t, p_id[2]);
774
775 if (test == MULTICAST)
776 {
777 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
778 "add peer 3\n");
779 GNUNET_MESH_peer_request_connect_add (t, p_id[1]);
780 }
781 627
782 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 628 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
783 "schedule timeout in TIMEOUT\n"); 629 "schedule timeout in TIMEOUT\n");
@@ -785,21 +631,37 @@ do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
785 { 631 {
786 GNUNET_SCHEDULER_cancel (disconnect_task); 632 GNUNET_SCHEDULER_cancel (disconnect_task);
787 } 633 }
788 disconnect_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, 634 t = GNUNET_MESH_tunnel_create (h1, NULL, p_id[1], 1);
635 if (SPEED_NOBUF == test)
636 {
637 GNUNET_MESH_tunnel_buffer(t, GNUNET_NO);
638 test = SPEED;
639 }
640
641 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
789 &disconnect_mesh_peers, 642 &disconnect_mesh_peers,
790 (void *) __LINE__); 643 (void *) __LINE__);
644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
645 "Sending data initializer...\n");
646 peers_responded = 0;
647 data_ack = 0;
648 data_received = 0;
649 data_sent = 0;
650 GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO,
651 GNUNET_TIME_UNIT_FOREVER_REL,
652 size_payload, &tmt_rdy, (void *) 1L);
791} 653}
792 654
793/** 655/**
794 * Callback to be called when the requested peer information is available 656 * Callback to be called when the requested peer information is available
795 * 657 *
796 * @param cls the closure from GNUNET_TETSBED_peer_get_information() 658 * @param cls the closure from GNUNET_TESTBED_peer_get_information()
797 * @param op the operation this callback corresponds to 659 * @param op the operation this callback corresponds to
798 * @param pinfo the result; will be NULL if the operation has failed 660 * @param pinfo the result; will be NULL if the operation has failed
799 * @param emsg error message if the operation has failed; 661 * @param emsg error message if the operation has failed;
800 * NULL if the operation is successfull 662 * NULL if the operation is successfull
801 */ 663 */
802void 664static void
803pi_cb (void *cls, 665pi_cb (void *cls,
804 struct GNUNET_TESTBED_Operation *op, 666 struct GNUNET_TESTBED_Operation *op,
805 const struct GNUNET_TESTBED_PeerInformation *pinfo, 667 const struct GNUNET_TESTBED_PeerInformation *pinfo,
@@ -808,6 +670,7 @@ pi_cb (void *cls,
808 long i = (long) cls; 670 long i = (long) cls;
809 671
810 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "id callback for %ld\n", i); 672 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "id callback for %ld\n", i);
673
811 if (NULL == pinfo || NULL != emsg) 674 if (NULL == pinfo || NULL != emsg)
812 { 675 {
813 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg); 676 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
@@ -817,7 +680,7 @@ pi_cb (void *cls,
817 p_id[i] = pinfo->result.id; 680 p_id[i] = pinfo->result.id;
818 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i])); 681 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i]));
819 p_ids++; 682 p_ids++;
820 if ((MULTICAST == test && p_ids < 3) || p_ids < 2) 683 if (p_ids < 2)
821 return; 684 return;
822 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n"); 685 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n");
823 test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, 686 test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
@@ -846,18 +709,6 @@ tmain (void *cls,
846 peers_running = num_peers; 709 peers_running = num_peers;
847 h1 = meshes[0]; 710 h1 = meshes[0];
848 h2 = meshes[num_peers - 1]; 711 h2 = meshes[num_peers - 1];
849 t = GNUNET_MESH_tunnel_create (h1, NULL, &ch, &dh, (void *) 0L);
850 if (SPEED_MIN == test)
851 {
852 GNUNET_MESH_tunnel_speed_min(t);
853 test = SPEED;
854 }
855 if (SPEED_NOBUF == test)
856 {
857 GNUNET_MESH_tunnel_buffer(t, GNUNET_NO);
858 test = SPEED;
859 }
860 peers_in_tunnel = 0;
861 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, 712 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
862 &disconnect_mesh_peers, 713 &disconnect_mesh_peers,
863 (void *) __LINE__); 714 (void *) __LINE__);
@@ -866,20 +717,9 @@ tmain (void *cls,
866 t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0], 717 t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
867 GNUNET_TESTBED_PIT_IDENTITY, 718 GNUNET_TESTBED_PIT_IDENTITY,
868 &pi_cb, (void *) 0L); 719 &pi_cb, (void *) 0L);
869 t_op[2] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1], 720 t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
870 GNUNET_TESTBED_PIT_IDENTITY, 721 GNUNET_TESTBED_PIT_IDENTITY,
871 &pi_cb, (void *) 2L); 722 &pi_cb, (void *) 1L);
872 if (MULTICAST == test)
873 {
874 h3 = meshes[num_peers - 2];
875 t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 2],
876 GNUNET_TESTBED_PIT_IDENTITY,
877 &pi_cb, (void *) 1L);
878 }
879 else
880 {
881 t_op[1] = NULL;
882 }
883 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n"); 723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n");
884} 724}
885 725
@@ -891,36 +731,29 @@ int
891main (int argc, char *argv[]) 731main (int argc, char *argv[])
892{ 732{
893 initialized = GNUNET_NO; 733 initialized = GNUNET_NO;
734 uint32_t ports[2];
894 735
895 GNUNET_log_setup ("test", "DEBUG", NULL); 736 GNUNET_log_setup ("test", "DEBUG", NULL);
896 737
897 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n"); 738 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n");
898 if (strstr (argv[0], "test_mesh_small_unicast") != NULL) 739 if (strstr (argv[0], "_small_forward") != NULL)
899 {
900 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNICAST\n");
901 test = UNICAST;
902 test_name = "unicast";
903 ok_goal = 5;
904 }
905 else if (strstr (argv[0], "test_mesh_small_multicast") != NULL)
906 { 740 {
907 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MULTICAST\n"); 741 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n");
908 test = MULTICAST; 742 test = FORWARD;
909 test_name = "multicast"; 743 test_name = "unicast2";
910 ok_goal = 10; 744 ok_goal = 4;
911 } 745 }
912 else if (strstr (argv[0], "test_mesh_small_signal") != NULL) 746 else if (strstr (argv[0], "_small_signal") != NULL)
913 { 747 {
914 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n"); 748 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n");
915 test = P2P_SIGNAL; 749 test = P2P_SIGNAL;
916 test_name = "signal"; 750 test_name = "signal2";
917 ok_goal = 5; 751 ok_goal = 4;
918 } 752 }
919 else if (strstr (argv[0], "test_mesh_small_speed_ack") != NULL) 753 else if (strstr (argv[0], "_small_speed_ack") != NULL)
920 { 754 {
921 /* Each peer is supposed to generate the following callbacks: 755 /* Each peer is supposed to generate the following callbacks:
922 * 1 incoming tunnel (@dest) 756 * 1 incoming tunnel (@dest)
923 * 1 connected peer (@orig)
924 * TOTAL_PACKETS received data packet (@dest) 757 * TOTAL_PACKETS received data packet (@dest)
925 * TOTAL_PACKETS received data packet (@orig) 758 * TOTAL_PACKETS received data packet (@orig)
926 * 1 received tunnel destroy (@dest) 759 * 1 received tunnel destroy (@dest)
@@ -929,14 +762,13 @@ main (int argc, char *argv[])
929 */ 762 */
930 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n"); 763 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n");
931 test = SPEED_ACK; 764 test = SPEED_ACK;
932 test_name = "speed ack"; 765 test_name = "speed2 ack";
933 ok_goal = TOTAL_PACKETS * 2 + 3; 766 ok_goal = TOTAL_PACKETS * 2 + 2;
934 } 767 }
935 else if (strstr (argv[0], "test_mesh_small_speed") != NULL) 768 else if (strstr (argv[0], "_small_speed") != NULL)
936 { 769 {
937 /* Each peer is supposed to generate the following callbacks: 770 /* Each peer is supposed to generate the following callbacks:
938 * 1 incoming tunnel (@dest) 771 * 1 incoming tunnel (@dest)
939 * 1 connected peer (@orig)
940 * 1 initial packet (@dest) 772 * 1 initial packet (@dest)
941 * TOTAL_PACKETS received data packet (@dest) 773 * TOTAL_PACKETS received data packet (@dest)
942 * 1 received data packet (@orig) 774 * 1 received data packet (@orig)
@@ -944,21 +776,16 @@ main (int argc, char *argv[])
944 * _________________________________ 776 * _________________________________
945 */ 777 */
946 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n"); 778 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n");
947 ok_goal = TOTAL_PACKETS + 5; 779 ok_goal = TOTAL_PACKETS + 4;
948 if (strstr (argv[0], "_min") != NULL) 780 if (strstr (argv[0], "_nobuf") != NULL)
949 {
950 test = SPEED_MIN;
951 test_name = "speed min";
952 }
953 else if (strstr (argv[0], "_nobuf") != NULL)
954 { 781 {
955 test = SPEED_NOBUF; 782 test = SPEED_NOBUF;
956 test_name = "speed nobuf"; 783 test_name = "speed2 nobuf";
957 } 784 }
958 else 785 else
959 { 786 {
960 test = SPEED; 787 test = SPEED;
961 test_name = "speed"; 788 test_name = "speed2";
962 } 789 }
963 } 790 }
964 else 791 else
@@ -980,15 +807,17 @@ main (int argc, char *argv[])
980 } 807 }
981 808
982 p_ids = 0; 809 p_ids = 0;
810 ports[0] = 1;
811 ports[1] = 0;
983 GNUNET_MESH_TEST_run ("test_mesh_small", 812 GNUNET_MESH_TEST_run ("test_mesh_small",
984 "test_mesh_small.conf", 813 "test_mesh.conf",
985 5, 814 5,
986 &tmain, 815 &tmain,
987 NULL, 816 NULL, /* tmain cls */
988 &incoming_tunnel, 817 &incoming_tunnel,
989 &tunnel_cleaner, 818 &tunnel_cleaner,
990 handlers, 819 handlers,
991 NULL); 820 ports);
992 821
993 if (ok_goal > ok) 822 if (ok_goal > ok)
994 { 823 {
@@ -1001,3 +830,4 @@ main (int argc, char *argv[])
1001} 830}
1002 831
1003/* end of test_mesh_small.c */ 832/* end of test_mesh_small.c */
833
diff --git a/src/mesh/test_mesh_small.conf b/src/mesh/test_mesh_small.conf
deleted file mode 100644
index 943ef3638..000000000
--- a/src/mesh/test_mesh_small.conf
+++ /dev/null
@@ -1,78 +0,0 @@
1[PATHS]
2SERVICEHOME = /tmp/test_mesh_small/
3
4[mesh]
5PORT = 10005
6ACCEPT_FROM = 127.0.0.1;
7HOSTNAME = localhost
8REFRESH_PATH_TIME = 5 s
9APP_ANNOUNCE_TIME = 2 s
10ID_ANNOUNCE_TIME = 2 s
11CONNECT_TIMEOUT = 30 s
12DEFAULT_TTL = 64
13DHT_REPLICAITON_LEVEL = 3
14# PREFIX = valgrind --leak-check=full --suppressions=valgrind-mesh.supp
15# PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
16
17[testbed]
18NUM_PEERS = 5
19OVERLAY_TOPOLOGY = LINE
20
21[arm]
22PORT = 10010
23DEFAULTSERVICES = core dht mesh
24
25[statistics]
26AUTOSTART = YES
27PORT = 10000
28
29[dht]
30AUTOSTART = YES
31ACCEPT_FROM6 = ::1;
32ACCEPT_FROM = 127.0.0.1;
33HOSTNAME = localhost
34PORT = 10001
35
36[nse]
37WORKBITS = 0
38INTERVAL = 60 s
39WORKDELAY = 500 ms
40
41[dns]
42AUTOSTART = NO
43PORT = 10011
44
45[vpn]
46AUTOSTART = NO
47PORT = 10012
48
49[transport]
50PORT = 10002
51AUTOSTART = YES
52
53[nat]
54DISABLEV6 = YES
55BINDTO = 127.0.0.1
56ENABLE_UPNP = NO
57BEHIND_NAT = NO
58ALLOW_NAT = NO
59INTERNAL_ADDRESS = 127.0.0.1
60EXTERNAL_ADDRESS = 127.0.0.1
61RETURN_LOCAL_ADDRESSES = YES
62USE_LOCALADDR = YES
63
64[ats]
65WAN_QUOTA_IN = 1 GB
66WAN_QUOTA_OUT = 1 GB
67
68[core]
69AUTOSTART = YES
70PORT = 10003
71
72[peerinfo]
73AUTOSTART = YES
74PORT = 10004
75
76[testing]
77WEAKRANDOM = YES
78
diff --git a/src/mesh/test_mesh_tree_api.c b/src/mesh/test_mesh_tree_api.c
deleted file mode 100644
index 3bdb82e0f..000000000
--- a/src/mesh/test_mesh_tree_api.c
+++ /dev/null
@@ -1,409 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file mesh/test_mesh_tree_api.c
23 * @brief test mesh tree api: test of tree & path management api
24 * @author Bartlomiej Polot
25 */
26
27#include "platform.h"
28#include "gnunet_common.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_dht_service.h"
31#include "gnunet_mesh_service.h"
32#include "mesh.h"
33#ifndef MESH_TUNNEL_TREE_C
34#include "mesh_tunnel_tree.c"
35#define MESH_TUNNEL_TREE_C
36#endif
37
38static int failed;
39static int cb_call;
40static struct GNUNET_PeerIdentity *pi[10];
41static struct MeshTunnelTree *tree;
42
43
44/**
45 * Whole tree iterator.
46 *
47 * @param cls Closure (unused).
48 * @param peer_id Short ID of the node.
49 * @param parent_id Short ID of the parent node.
50 */
51static void
52tree_cb (void *cls, GNUNET_PEER_Id peer_id, GNUNET_PEER_Id parent_id)
53{
54 fprintf (stdout, "%u -> %u\n", peer_id, parent_id);;
55}
56
57
58/**
59 * Node children iterator.
60 *
61 * @param cls Closure (unused).
62 * @param peer_idShort ID of the child.
63 */
64static void
65cb (void *cls, GNUNET_PEER_Id peer_id)
66{
67 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: CB: Disconnected %u\n", peer_id);
68 if (0 == cb_call)
69 {
70 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: and it shouldn't!\n");
71 failed++;
72 }
73 cb_call--;
74}
75
76
77/**
78 * Print debug information about the state of the tree.
79 *
80 * @param tree Tree to debug-print.
81 */
82static void
83test_debug (struct MeshTunnelTree *tree)
84{
85 tree_debug (tree);
86 tree_iterate_all (tree, &tree_cb, NULL);
87}
88
89
90/**
91 * Check if a node has all expected properties.
92 *
93 * @param peer_id Short ID of the peer to test.
94 * @param status Expected status of the peer.
95 * @param children Expected number of children of the peer.
96 * @param first_hop Short ID of the expected first hop towards the peer.
97 */
98static void
99test_assert (GNUNET_PEER_Id peer_id, enum MeshPeerState status,
100 unsigned int children, GNUNET_PEER_Id first_hop)
101{
102 struct MeshTunnelTreeNode *n;
103 struct MeshTunnelTreeNode *c;
104 unsigned int i;
105 int pre_failed;
106
107 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Checking peer %u\n", peer_id);
108 pre_failed = failed;
109 n = tree_find_peer (tree, peer_id);
110 if (n->peer != peer_id)
111 {
112 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
113 "Retrieved peer has wrong ID! (Got %u, expected %u)\n", n->peer,
114 peer_id);
115 failed++;
116 }
117 if (n->status != status)
118 {
119 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
120 "Retrieved peer has wrong status! (Got %u, expected %u)\n",
121 n->status, status);
122 failed++;
123 }
124 for (c = n->children_head, i = 0; NULL != c; c = c->next, i++) ;
125 if (i != children)
126 {
127 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
128 "Retrieved peer wrong has number of children! (Got %u, expected %u)\n",
129 i, children);
130 failed++;
131 }
132 if (0 != first_hop &&
133 GNUNET_PEER_search (tree_get_first_hop (tree, peer_id)) != first_hop)
134 {
135 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
136 "Wrong first hop! (Got %u, expected %u)\n",
137 GNUNET_PEER_search (tree_get_first_hop (tree, peer_id)),
138 first_hop);
139 failed++;
140 }
141 if (pre_failed != failed)
142 {
143 struct GNUNET_PeerIdentity id;
144
145 GNUNET_PEER_resolve (peer_id, &id);
146 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
147 "*** Peer %s (%u) has failed %d checks!\n", GNUNET_i2s (&id),
148 peer_id, failed - pre_failed);
149 }
150}
151
152
153/**
154 * Clean up and free all memory.
155 */
156static void
157finish (void)
158{
159 unsigned int i;
160
161 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Finishing...\n");
162 for (i = 0; i < 10; i++)
163 {
164 GNUNET_free (pi[i]);
165 }
166}
167
168/**
169 * Convert an integer int to a peer identity
170 */
171static struct GNUNET_PeerIdentity *
172get_pi (uint32_t id)
173{
174 struct GNUNET_PeerIdentity *pi;
175
176 pi = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
177 pi->hashPubKey.bits[0] = id + 1;
178 return pi;
179}
180
181
182int
183main (int argc, char *argv[])
184{
185 struct MeshTunnelTreeNode *node;
186 struct MeshPeerPath *path;
187 struct MeshPeerPath *path1;
188 unsigned int i;
189
190 failed = 0;
191 cb_call = 0;
192 GNUNET_log_setup ("test_mesh_api_tree",
193 "WARNING",
194 NULL);
195 for (i = 0; i < 10; i++)
196 {
197 pi[i] = get_pi (i);
198 GNUNET_break (i + 1 == GNUNET_PEER_intern (pi[i]));
199 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u: %s\n", i + 1,
200 GNUNET_h2s (&pi[i]->hashPubKey));
201 }
202 tree = tree_new (1);
203 tree->me = tree->root;
204 path = path_new (5);
205 path->peers[0] = 1;
206 path->peers[1] = 2;
207 path->peers[2] = 3;
208 path->peers[3] = 4;
209 path->length = 4;
210
211 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 1 2 3 4\n");
212 tree_add_path (tree, path, &cb, NULL);
213 test_debug (tree);
214 path1 = tree_get_path_to_peer (tree, 4);
215 if (NULL == path1 || path->length != path1->length ||
216 memcmp (path->peers, path1->peers, path->length) != 0)
217 {
218 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Retrieved path != original\n");
219 failed++;
220 }
221 path_destroy (path1);
222 test_assert (4, MESH_PEER_SEARCHING, 0, 2);
223 test_assert (3, MESH_PEER_RELAY, 1, 0);
224 test_assert (2, MESH_PEER_RELAY, 1, 0);
225 test_assert (1, MESH_PEER_ROOT, 1, 0);
226
227 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding second path: 1 2 3\n");
228 path->length--;
229 tree_add_path (tree, path, &cb, NULL);
230 test_debug (tree);
231
232 test_assert (4, MESH_PEER_SEARCHING, 0, 2);
233 test_assert (3, MESH_PEER_SEARCHING, 1, 2);
234 test_assert (2, MESH_PEER_RELAY, 1, 0);
235 test_assert (1, MESH_PEER_ROOT, 1, 0);
236
237 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding third path 1 2 3 5\n");
238 path->length++;
239 path->peers[3] = 5;
240 tree_add_path (tree, path, &cb, NULL);
241 test_debug (tree);
242
243 test_assert (5, MESH_PEER_SEARCHING, 0, 2);
244 test_assert (4, MESH_PEER_SEARCHING, 0, 2);
245 test_assert (3, MESH_PEER_SEARCHING, 2, 2);
246 test_assert (2, MESH_PEER_RELAY, 1, 0);
247 test_assert (1, MESH_PEER_ROOT, 1, 0);
248
249 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Calculating costs...\n");
250 for (i = 1; i < 5; i++)
251 {
252 path->length = i;
253 if (tree_get_path_cost (tree, path) != 0)
254 {
255 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n",
256 i);
257 failed++;
258 }
259 }
260 path->length++;
261 path->peers[4] = 6;
262 if (tree_get_path_cost (tree, path) != 1)
263 {
264 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n", i);
265 failed++;
266 }
267 path->peers[3] = 7;
268 if (tree_get_path_cost (tree, path) != 2)
269 {
270 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n", i);
271 failed++;
272 }
273 path->length--;
274 if (tree_get_path_cost (tree, path) != 1)
275 {
276 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n", i);
277 failed++;
278 }
279 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Deleting third path (5)\n");
280 tree_set_status (tree, 5, MESH_PEER_READY);
281 cb_call = 1;
282 node = tree_del_path (tree, 5, &cb, NULL);
283 test_debug (tree);
284 if (cb_call != 0)
285 {
286 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%u callbacks missed!\n", cb_call);
287 failed++;
288 }
289 if (node->peer != 5)
290 {
291 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Retrieved peer != original\n");
292 failed++;
293 }
294
295 test_assert (4, MESH_PEER_SEARCHING, 0, 2);
296 test_assert (3, MESH_PEER_SEARCHING, 1, 2);
297 test_assert (2, MESH_PEER_RELAY, 1, 0);
298 test_assert (1, MESH_PEER_ROOT, 1, 0);
299
300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Destroying node copy...\n");
301 GNUNET_free (node);
302
303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
304 "test: Adding new shorter first path...\n");
305 path->length = 2;
306 path->peers[1] = 4;
307 cb_call = 1;
308 tree_find_peer (tree, 4)->status = MESH_PEER_READY;
309 tree_add_path (tree, path, &cb, NULL);
310 test_debug (tree);
311 if (cb_call != 0)
312 {
313 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%u callbacks missed!\n", cb_call);
314 failed++;
315 }
316
317 test_assert (4, MESH_PEER_SEARCHING, 0, 4);
318 test_assert (3, MESH_PEER_SEARCHING, 0, 2);
319 test_assert (2, MESH_PEER_RELAY, 1, 0);
320 test_assert (1, MESH_PEER_ROOT, 2, 0);
321
322 GNUNET_free (path->peers);
323 GNUNET_free (path);
324 tree_destroy (tree);
325
326 /****************************************************************************/
327
328 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:\n");
329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Testing relay trees\n");
330 for (i = 0; i < 10; i++)
331 {
332 GNUNET_break (i + 1 == GNUNET_PEER_intern (pi[i]));
333 }
334 tree = tree_new (2);
335 path = path_new (8);
336 path->peers[0] = 2;
337 path->peers[1] = 1;
338 path->peers[2] = 3;
339 path->length = 3;
340
341 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 2 1 3\n");
342 tree_add_path (tree, path, &cb, NULL);
343 test_debug (tree);
344
345 test_assert (3, MESH_PEER_SEARCHING, 0, 3);
346 test_assert (1, MESH_PEER_RELAY, 1, 0);
347 test_assert (2, MESH_PEER_ROOT, 1, 0);
348
349 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding long path: 2 1 4 5 3\n");
350 path->peers[2] = 4;
351 path->peers[3] = 5;
352 path->peers[4] = 3;
353 path->length = 5;
354 tree_add_path (tree, path, &cb, NULL);
355 test_debug (tree);
356
357 test_assert (3, MESH_PEER_SEARCHING, 0, 4);
358 test_assert (5, MESH_PEER_RELAY, 1, 4);
359 test_assert (4, MESH_PEER_RELAY, 1, 4);
360 test_assert (1, MESH_PEER_RELAY, 1, 0);
361 test_assert (2, MESH_PEER_ROOT, 1, 0);
362
363 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
364 "test: Even longer path: 2 6 1 7 8 4 5 3\n");
365 path->peers[0] = 2;
366 path->peers[1] = 6;
367 path->peers[2] = 1;
368 path->peers[3] = 7;
369 path->peers[4] = 8;
370 path->peers[5] = 4;
371 path->peers[6] = 5;
372 path->peers[7] = 3;
373 path->length = 8;
374 tree_add_path (tree, path, &cb, NULL);
375 test_debug (tree);
376
377 test_assert (3, MESH_PEER_SEARCHING, 0, 7);
378 test_assert (5, MESH_PEER_RELAY, 1, 7);
379 test_assert (4, MESH_PEER_RELAY, 1, 7);
380 test_assert (8, MESH_PEER_RELAY, 1, 7);
381 test_assert (7, MESH_PEER_RELAY, 1, 7);
382 test_assert (1, MESH_PEER_RELAY, 1, 0);
383 test_assert (6, MESH_PEER_RELAY, 1, 0);
384 test_assert (2, MESH_PEER_ROOT, 1, 0);
385
386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 2 1 3\n");
387 path->peers[1] = 1;
388 path->peers[2] = 3;
389 path->length = 3;
390 tree_add_path (tree, path, &cb, NULL);
391 test_debug (tree);
392
393 test_assert (3, MESH_PEER_SEARCHING, 0, 3);
394 test_assert (1, MESH_PEER_RELAY, 1, 0);
395 test_assert (2, MESH_PEER_ROOT, 1, 0);
396
397 GNUNET_free (path->peers);
398 GNUNET_free (path);
399 tree_destroy (tree);
400 finish ();
401 if (failed > 0)
402 {
403 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%u tests failed\n", failed);
404 return 1;
405 }
406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: OK\n");
407
408 return 0;
409}