diff options
Diffstat (limited to 'src/multicast')
-rw-r--r-- | src/multicast/.gitignore | 7 | ||||
-rw-r--r-- | src/multicast/Makefile.am | 79 | ||||
-rw-r--r-- | src/multicast/gnunet-multicast.c | 79 | ||||
-rw-r--r-- | src/multicast/gnunet-service-multicast.c | 2234 | ||||
-rw-r--r-- | src/multicast/multicast.conf.in | 22 | ||||
-rw-r--r-- | src/multicast/multicast.h | 303 | ||||
-rw-r--r-- | src/multicast/multicast_api.c | 1399 | ||||
-rw-r--r-- | src/multicast/test_multicast.c | 758 | ||||
-rw-r--r-- | src/multicast/test_multicast.conf | 56 | ||||
-rw-r--r-- | src/multicast/test_multicast_2peers.c | 520 | ||||
-rw-r--r-- | src/multicast/test_multicast_line.conf | 63 | ||||
-rw-r--r-- | src/multicast/test_multicast_multipeer.c | 643 | ||||
-rw-r--r-- | src/multicast/test_multicast_star.conf | 64 |
13 files changed, 0 insertions, 6227 deletions
diff --git a/src/multicast/.gitignore b/src/multicast/.gitignore deleted file mode 100644 index a97844e81..000000000 --- a/src/multicast/.gitignore +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | gnunet-service-multicast | ||
2 | gnunet-multicast | ||
3 | test_multicast | ||
4 | test_multicast_multipeer | ||
5 | test_multicast_2peers | ||
6 | test_multicast_multipeer_line | ||
7 | test_multicast_multipeer_star | ||
diff --git a/src/multicast/Makefile.am b/src/multicast/Makefile.am deleted file mode 100644 index 61a9f8bf6..000000000 --- a/src/multicast/Makefile.am +++ /dev/null | |||
@@ -1,79 +0,0 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
5 | |||
6 | libexecdir= $(pkglibdir)/libexec/ | ||
7 | |||
8 | pkgcfg_DATA = \ | ||
9 | multicast.conf | ||
10 | |||
11 | if MINGW | ||
12 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
13 | endif | ||
14 | |||
15 | if USE_COVERAGE | ||
16 | AM_CFLAGS = -fprofile-arcs -ftest-coverage | ||
17 | endif | ||
18 | |||
19 | lib_LTLIBRARIES = libgnunetmulticast.la | ||
20 | |||
21 | libgnunetmulticast_la_SOURCES = \ | ||
22 | multicast_api.c multicast.h | ||
23 | libgnunetmulticast_la_LIBADD = \ | ||
24 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
25 | $(GN_LIBINTL) $(XLIB) | ||
26 | libgnunetmulticast_la_LDFLAGS = \ | ||
27 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | ||
28 | -version-info 0:0:0 | ||
29 | |||
30 | |||
31 | bin_PROGRAMS = \ | ||
32 | gnunet-multicast | ||
33 | |||
34 | libexec_PROGRAMS = \ | ||
35 | gnunet-service-multicast \ | ||
36 | $(EXP_LIBEXEC) | ||
37 | |||
38 | gnunet_multicast_SOURCES = \ | ||
39 | gnunet-multicast.c | ||
40 | gnunet_multicast_LDADD = \ | ||
41 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
42 | $(GN_LIBINTL) | ||
43 | |||
44 | gnunet_service_multicast_SOURCES = \ | ||
45 | gnunet-service-multicast.c | ||
46 | gnunet_service_multicast_LDADD = \ | ||
47 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
48 | $(top_builddir)/src/cadet/libgnunetcadet.la \ | ||
49 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
50 | $(GN_LIBINTL) | ||
51 | |||
52 | check_PROGRAMS = \ | ||
53 | test_multicast \ | ||
54 | test_multicast_multipeer_star \ | ||
55 | test_multicast_multipeer_line | ||
56 | |||
57 | if ENABLE_TEST_RUN | ||
58 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@}; export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; unset XDG_DATA_HOME; unset XDG_CONFIG_HOME; | ||
59 | TESTS = $(check_PROGRAMS) | ||
60 | endif | ||
61 | |||
62 | test_multicast_SOURCES = \ | ||
63 | test_multicast.c | ||
64 | test_multicast_LDADD = \ | ||
65 | libgnunetmulticast.la \ | ||
66 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
67 | $(top_builddir)/src/util/libgnunetutil.la | ||
68 | test_multicast_multipeer_star_SOURCES = \ | ||
69 | test_multicast_multipeer.c | ||
70 | test_multicast_multipeer_star_LDADD = \ | ||
71 | libgnunetmulticast.la \ | ||
72 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
73 | $(top_builddir)/src/util/libgnunetutil.la | ||
74 | test_multicast_multipeer_line_SOURCES = \ | ||
75 | test_multicast_multipeer.c | ||
76 | test_multicast_multipeer_line_LDADD = \ | ||
77 | libgnunetmulticast.la \ | ||
78 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
79 | $(top_builddir)/src/util/libgnunetutil.la | ||
diff --git a/src/multicast/gnunet-multicast.c b/src/multicast/gnunet-multicast.c deleted file mode 100644 index 63e1d52aa..000000000 --- a/src/multicast/gnunet-multicast.c +++ /dev/null | |||
@@ -1,79 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file multicast/gnunet-multicast.c | ||
23 | * @brief multicast for writing a tool | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | /* #include "gnunet_multicast_service.h" */ | ||
29 | |||
30 | /** | ||
31 | * Final status code. | ||
32 | */ | ||
33 | static int ret; | ||
34 | |||
35 | /** | ||
36 | * Main function that will be run by the scheduler. | ||
37 | * | ||
38 | * @param cls closure | ||
39 | * @param args remaining command-line arguments | ||
40 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
41 | * @param cfg configuration | ||
42 | */ | ||
43 | static void | ||
44 | run (void *cls, char *const *args, const char *cfgfile, | ||
45 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
46 | { | ||
47 | /* main code here */ | ||
48 | puts( gettext_noop ("This command doesn't do anything yet.") ); | ||
49 | ret = -1; | ||
50 | } | ||
51 | |||
52 | |||
53 | /** | ||
54 | * The main function. | ||
55 | * | ||
56 | * @param argc number of arguments from the command line | ||
57 | * @param argv command line arguments | ||
58 | * @return 0 ok, 1 on error | ||
59 | */ | ||
60 | int | ||
61 | main (int argc, char *const *argv) | ||
62 | { | ||
63 | static const struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
64 | /* FIMXE: add options here */ | ||
65 | GNUNET_GETOPT_OPTION_END | ||
66 | }; | ||
67 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
68 | return 2; | ||
69 | |||
70 | ret = (GNUNET_OK == | ||
71 | GNUNET_PROGRAM_run (argc, argv, "gnunet-multicast", | ||
72 | gettext_noop ("This command doesn't do anything yet."), | ||
73 | options, &run, | ||
74 | NULL)) ? ret : 1; | ||
75 | GNUNET_free ((void*) argv); | ||
76 | return ret; | ||
77 | } | ||
78 | |||
79 | /* end of gnunet-multicast.c */ | ||
diff --git a/src/multicast/gnunet-service-multicast.c b/src/multicast/gnunet-service-multicast.c deleted file mode 100644 index 18c366118..000000000 --- a/src/multicast/gnunet-service-multicast.c +++ /dev/null | |||
@@ -1,2234 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file multicast/gnunet-service-multicast.c | ||
23 | * @brief program that does multicast | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_signatures.h" | ||
29 | #include "gnunet_applications.h" | ||
30 | #include "gnunet_statistics_service.h" | ||
31 | #include "gnunet_cadet_service.h" | ||
32 | #include "gnunet_multicast_service.h" | ||
33 | #include "multicast.h" | ||
34 | |||
35 | /** | ||
36 | * Handle to our current configuration. | ||
37 | */ | ||
38 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
39 | |||
40 | /** | ||
41 | * Service handle. | ||
42 | */ | ||
43 | static struct GNUNET_SERVICE_Handle *service; | ||
44 | |||
45 | /** | ||
46 | * CADET handle. | ||
47 | */ | ||
48 | static struct GNUNET_CADET_Handle *cadet; | ||
49 | |||
50 | /** | ||
51 | * Identity of this peer. | ||
52 | */ | ||
53 | static struct GNUNET_PeerIdentity this_peer; | ||
54 | |||
55 | /** | ||
56 | * Handle to the statistics service. | ||
57 | */ | ||
58 | static struct GNUNET_STATISTICS_Handle *stats; | ||
59 | |||
60 | /** | ||
61 | * All connected origin clients. | ||
62 | * Group's pub_key_hash -> struct Origin * (uniq) | ||
63 | */ | ||
64 | static struct GNUNET_CONTAINER_MultiHashMap *origins; | ||
65 | |||
66 | /** | ||
67 | * All connected member clients. | ||
68 | * Group's pub_key_hash -> struct Member * (multi) | ||
69 | */ | ||
70 | static struct GNUNET_CONTAINER_MultiHashMap *members; | ||
71 | |||
72 | /** | ||
73 | * Connected member clients per group. | ||
74 | * Group's pub_key_hash -> Member's pub_key_hash (uniq) -> struct Member * (uniq) | ||
75 | */ | ||
76 | static struct GNUNET_CONTAINER_MultiHashMap *group_members; | ||
77 | |||
78 | /** | ||
79 | * Incoming CADET channels with connected children in the tree. | ||
80 | * Group's pub_key_hash -> struct Channel * (multi) | ||
81 | */ | ||
82 | static struct GNUNET_CONTAINER_MultiHashMap *channels_in; | ||
83 | |||
84 | /** | ||
85 | * Outgoing CADET channels connecting to parents in the tree. | ||
86 | * Group's pub_key_hash -> struct Channel * (multi) | ||
87 | */ | ||
88 | static struct GNUNET_CONTAINER_MultiHashMap *channels_out; | ||
89 | |||
90 | /** | ||
91 | * Incoming replay requests from CADET. | ||
92 | * Group's pub_key_hash -> | ||
93 | * H(fragment_id, message_id, fragment_offset, flags) -> struct Channel * | ||
94 | */ | ||
95 | static struct GNUNET_CONTAINER_MultiHashMap *replay_req_cadet; | ||
96 | |||
97 | /** | ||
98 | * Incoming replay requests from clients. | ||
99 | * Group's pub_key_hash -> | ||
100 | * H(fragment_id, message_id, fragment_offset, flags) -> struct GNUNET_SERVICE_Client * | ||
101 | */ | ||
102 | static struct GNUNET_CONTAINER_MultiHashMap *replay_req_client; | ||
103 | |||
104 | |||
105 | /** | ||
106 | * Join status of a remote peer. | ||
107 | */ | ||
108 | enum JoinStatus | ||
109 | { | ||
110 | JOIN_REFUSED = -1, | ||
111 | JOIN_NOT_ASKED = 0, | ||
112 | JOIN_WAITING = 1, | ||
113 | JOIN_ADMITTED = 2, | ||
114 | }; | ||
115 | |||
116 | enum ChannelDirection | ||
117 | { | ||
118 | DIR_INCOMING = 0, | ||
119 | DIR_OUTGOING = 1, | ||
120 | }; | ||
121 | |||
122 | |||
123 | /** | ||
124 | * Context for a CADET channel. | ||
125 | */ | ||
126 | struct Channel | ||
127 | { | ||
128 | /** | ||
129 | * Group the channel belongs to. | ||
130 | * | ||
131 | * Only set for outgoing channels. | ||
132 | */ | ||
133 | struct Group *group; | ||
134 | |||
135 | /** | ||
136 | * CADET channel. | ||
137 | */ | ||
138 | struct GNUNET_CADET_Channel *channel; | ||
139 | |||
140 | // FIXME: not used | ||
141 | /** | ||
142 | * CADET transmission handle. | ||
143 | */ | ||
144 | struct GNUNET_CADET_TransmitHandle *tmit_handle; | ||
145 | |||
146 | /** | ||
147 | * Public key of the target group. | ||
148 | */ | ||
149 | struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key; | ||
150 | |||
151 | /** | ||
152 | * Hash of @a group_pub_key. | ||
153 | */ | ||
154 | struct GNUNET_HashCode group_pub_hash; | ||
155 | |||
156 | /** | ||
157 | * Public key of the joining member. | ||
158 | */ | ||
159 | struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key; | ||
160 | |||
161 | /** | ||
162 | * Remote peer identity. | ||
163 | */ | ||
164 | struct GNUNET_PeerIdentity peer; | ||
165 | |||
166 | /** | ||
167 | * Current window size, set by cadet_notify_window_change() | ||
168 | */ | ||
169 | int32_t window_size; | ||
170 | |||
171 | /** | ||
172 | * Is the connection established? | ||
173 | */ | ||
174 | int8_t is_connected; | ||
175 | |||
176 | /** | ||
177 | * Is the remote peer admitted to the group? | ||
178 | * @see enum JoinStatus | ||
179 | */ | ||
180 | int8_t join_status; | ||
181 | |||
182 | /** | ||
183 | * Number of messages waiting to be sent to CADET. | ||
184 | */ | ||
185 | uint8_t msgs_pending; | ||
186 | |||
187 | /** | ||
188 | * Channel direction. | ||
189 | * @see enum ChannelDirection | ||
190 | */ | ||
191 | uint8_t direction; | ||
192 | }; | ||
193 | |||
194 | |||
195 | /** | ||
196 | * List of connected clients. | ||
197 | */ | ||
198 | struct ClientList | ||
199 | { | ||
200 | struct ClientList *prev; | ||
201 | struct ClientList *next; | ||
202 | struct GNUNET_SERVICE_Client *client; | ||
203 | }; | ||
204 | |||
205 | |||
206 | /** | ||
207 | * Client context for an origin or member. | ||
208 | */ | ||
209 | struct Group | ||
210 | { | ||
211 | struct ClientList *clients_head; | ||
212 | struct ClientList *clients_tail; | ||
213 | |||
214 | /** | ||
215 | * Public key of the group. | ||
216 | */ | ||
217 | struct GNUNET_CRYPTO_EddsaPublicKey pub_key; | ||
218 | |||
219 | /** | ||
220 | * Hash of @a pub_key. | ||
221 | */ | ||
222 | struct GNUNET_HashCode pub_key_hash; | ||
223 | |||
224 | /** | ||
225 | * CADET port hash. | ||
226 | */ | ||
227 | struct GNUNET_HashCode cadet_port_hash; | ||
228 | |||
229 | /** | ||
230 | * Is the client disconnected? #GNUNET_YES or #GNUNET_NO | ||
231 | */ | ||
232 | uint8_t is_disconnected; | ||
233 | |||
234 | /** | ||
235 | * Is this an origin (#GNUNET_YES), or member (#GNUNET_NO)? | ||
236 | */ | ||
237 | uint8_t is_origin; | ||
238 | |||
239 | union { | ||
240 | struct Origin *origin; | ||
241 | struct Member *member; | ||
242 | }; | ||
243 | }; | ||
244 | |||
245 | |||
246 | /** | ||
247 | * Client context for a group's origin. | ||
248 | */ | ||
249 | struct Origin | ||
250 | { | ||
251 | struct Group group; | ||
252 | |||
253 | /** | ||
254 | * Private key of the group. | ||
255 | */ | ||
256 | struct GNUNET_CRYPTO_EddsaPrivateKey priv_key; | ||
257 | |||
258 | /** | ||
259 | * CADET port. | ||
260 | */ | ||
261 | struct GNUNET_CADET_Port *cadet_port; | ||
262 | |||
263 | /** | ||
264 | * Last message fragment ID sent to the group. | ||
265 | */ | ||
266 | uint64_t max_fragment_id; | ||
267 | }; | ||
268 | |||
269 | |||
270 | /** | ||
271 | * Client context for a group member. | ||
272 | */ | ||
273 | struct Member | ||
274 | { | ||
275 | struct Group group; | ||
276 | |||
277 | /** | ||
278 | * Private key of the member. | ||
279 | */ | ||
280 | struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key; | ||
281 | |||
282 | /** | ||
283 | * Public key of the member. | ||
284 | */ | ||
285 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; | ||
286 | |||
287 | /** | ||
288 | * Hash of @a pub_key. | ||
289 | */ | ||
290 | struct GNUNET_HashCode pub_key_hash; | ||
291 | |||
292 | /** | ||
293 | * Join request sent to the origin / members. | ||
294 | */ | ||
295 | struct MulticastJoinRequestMessage *join_req; | ||
296 | |||
297 | /** | ||
298 | * Join decision sent in reply to our request. | ||
299 | * | ||
300 | * Only a positive decision is stored here, in case of a negative decision the | ||
301 | * client is disconnected. | ||
302 | */ | ||
303 | struct MulticastJoinDecisionMessageHeader *join_dcsn; | ||
304 | |||
305 | /** | ||
306 | * CADET channel to the origin. | ||
307 | */ | ||
308 | struct Channel *origin_channel; | ||
309 | |||
310 | /** | ||
311 | * Peer identity of origin. | ||
312 | */ | ||
313 | struct GNUNET_PeerIdentity origin; | ||
314 | |||
315 | /** | ||
316 | * Peer identity of relays (other members to connect). | ||
317 | */ | ||
318 | struct GNUNET_PeerIdentity *relays; | ||
319 | |||
320 | /** | ||
321 | * Last request fragment ID sent to the origin. | ||
322 | */ | ||
323 | uint64_t max_fragment_id; | ||
324 | |||
325 | /** | ||
326 | * Number of @a relays. | ||
327 | */ | ||
328 | uint32_t relay_count; | ||
329 | }; | ||
330 | |||
331 | |||
332 | /** | ||
333 | * Client context. | ||
334 | */ | ||
335 | struct Client { | ||
336 | struct GNUNET_SERVICE_Client *client; | ||
337 | struct Group *group; | ||
338 | }; | ||
339 | |||
340 | |||
341 | struct ReplayRequestKey | ||
342 | { | ||
343 | uint64_t fragment_id; | ||
344 | uint64_t message_id; | ||
345 | uint64_t fragment_offset; | ||
346 | uint64_t flags; | ||
347 | }; | ||
348 | |||
349 | |||
350 | static struct Channel * | ||
351 | cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer); | ||
352 | |||
353 | static void | ||
354 | cadet_channel_destroy (struct Channel *chn); | ||
355 | |||
356 | static void | ||
357 | client_send_join_decision (struct Member *mem, | ||
358 | const struct MulticastJoinDecisionMessageHeader *hdcsn); | ||
359 | |||
360 | |||
361 | /** | ||
362 | * Task run during shutdown. | ||
363 | * | ||
364 | * @param cls unused | ||
365 | */ | ||
366 | static void | ||
367 | shutdown_task (void *cls) | ||
368 | { | ||
369 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
370 | "shutting down\n"); | ||
371 | if (NULL != cadet) | ||
372 | { | ||
373 | GNUNET_CADET_disconnect (cadet); | ||
374 | cadet = NULL; | ||
375 | } | ||
376 | if (NULL != stats) | ||
377 | { | ||
378 | GNUNET_STATISTICS_destroy (stats, GNUNET_YES); | ||
379 | stats = NULL; | ||
380 | } | ||
381 | /* FIXME: do more clean up here */ | ||
382 | } | ||
383 | |||
384 | |||
385 | /** | ||
386 | * Clean up origin data structures after a client disconnected. | ||
387 | */ | ||
388 | static void | ||
389 | cleanup_origin (struct Origin *orig) | ||
390 | { | ||
391 | struct Group *grp = &orig->group; | ||
392 | GNUNET_CONTAINER_multihashmap_remove (origins, &grp->pub_key_hash, orig); | ||
393 | if (NULL != orig->cadet_port) | ||
394 | { | ||
395 | GNUNET_CADET_close_port (orig->cadet_port); | ||
396 | orig->cadet_port = NULL; | ||
397 | } | ||
398 | GNUNET_free (orig); | ||
399 | } | ||
400 | |||
401 | |||
402 | /** | ||
403 | * Clean up member data structures after a client disconnected. | ||
404 | */ | ||
405 | static void | ||
406 | cleanup_member (struct Member *mem) | ||
407 | { | ||
408 | struct Group *grp = &mem->group; | ||
409 | struct GNUNET_CONTAINER_MultiHashMap * | ||
410 | grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, | ||
411 | &grp->pub_key_hash); | ||
412 | GNUNET_assert (NULL != grp_mem); | ||
413 | GNUNET_CONTAINER_multihashmap_remove (grp_mem, &mem->pub_key_hash, mem); | ||
414 | |||
415 | if (0 == GNUNET_CONTAINER_multihashmap_size (grp_mem)) | ||
416 | { | ||
417 | GNUNET_CONTAINER_multihashmap_remove (group_members, &grp->pub_key_hash, | ||
418 | grp_mem); | ||
419 | GNUNET_CONTAINER_multihashmap_destroy (grp_mem); | ||
420 | } | ||
421 | if (NULL != mem->join_dcsn) | ||
422 | { | ||
423 | GNUNET_free (mem->join_dcsn); | ||
424 | mem->join_dcsn = NULL; | ||
425 | } | ||
426 | if (NULL != mem->origin_channel) | ||
427 | { | ||
428 | GNUNET_CADET_channel_destroy (mem->origin_channel->channel); | ||
429 | mem->origin_channel = NULL; | ||
430 | } | ||
431 | GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem); | ||
432 | GNUNET_free (mem); | ||
433 | } | ||
434 | |||
435 | |||
436 | /** | ||
437 | * Clean up group data structures after a client disconnected. | ||
438 | */ | ||
439 | static void | ||
440 | cleanup_group (struct Group *grp) | ||
441 | { | ||
442 | (GNUNET_YES == grp->is_origin) | ||
443 | ? cleanup_origin (grp->origin) | ||
444 | : cleanup_member (grp->member); | ||
445 | } | ||
446 | |||
447 | |||
448 | void | ||
449 | replay_key_hash (uint64_t fragment_id, uint64_t message_id, | ||
450 | uint64_t fragment_offset, uint64_t flags, | ||
451 | struct GNUNET_HashCode *key_hash) | ||
452 | { | ||
453 | struct ReplayRequestKey key = { | ||
454 | .fragment_id = fragment_id, | ||
455 | .message_id = message_id, | ||
456 | .fragment_offset = fragment_offset, | ||
457 | .flags = flags, | ||
458 | }; | ||
459 | GNUNET_CRYPTO_hash (&key, sizeof (key), key_hash); | ||
460 | } | ||
461 | |||
462 | |||
463 | /** | ||
464 | * Remove channel from replay request hashmap. | ||
465 | * | ||
466 | * @param chn | ||
467 | * Channel to remove. | ||
468 | * | ||
469 | * @return #GNUNET_YES if there are more entries to process, | ||
470 | * #GNUNET_NO when reached end of hashmap. | ||
471 | */ | ||
472 | static int | ||
473 | replay_req_remove_cadet (struct Channel *chn) | ||
474 | { | ||
475 | if (NULL == chn || NULL == chn->group) | ||
476 | return GNUNET_SYSERR; | ||
477 | |||
478 | struct GNUNET_CONTAINER_MultiHashMap * | ||
479 | grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet, | ||
480 | &chn->group->pub_key_hash); | ||
481 | if (NULL == grp_replay_req) | ||
482 | return GNUNET_NO; | ||
483 | |||
484 | struct GNUNET_CONTAINER_MultiHashMapIterator * | ||
485 | it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req); | ||
486 | struct GNUNET_HashCode key; | ||
487 | const struct Channel *c; | ||
488 | while (GNUNET_YES | ||
489 | == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key, | ||
490 | (const void **) &c)) | ||
491 | { | ||
492 | if (c == chn) | ||
493 | { | ||
494 | GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, chn); | ||
495 | GNUNET_CONTAINER_multihashmap_iterator_destroy (it); | ||
496 | return GNUNET_YES; | ||
497 | } | ||
498 | } | ||
499 | GNUNET_CONTAINER_multihashmap_iterator_destroy (it); | ||
500 | return GNUNET_NO; | ||
501 | } | ||
502 | |||
503 | |||
504 | /** | ||
505 | * Remove client from replay request hashmap. | ||
506 | * | ||
507 | * @param client | ||
508 | * Client to remove. | ||
509 | * | ||
510 | * @return #GNUNET_YES if there are more entries to process, | ||
511 | * #GNUNET_NO when reached end of hashmap. | ||
512 | */ | ||
513 | static int | ||
514 | replay_req_remove_client (struct Group *grp, struct GNUNET_SERVICE_Client *client) | ||
515 | { | ||
516 | struct GNUNET_CONTAINER_MultiHashMap * | ||
517 | grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client, | ||
518 | &grp->pub_key_hash); | ||
519 | if (NULL == grp_replay_req) | ||
520 | return GNUNET_NO; | ||
521 | |||
522 | struct GNUNET_CONTAINER_MultiHashMapIterator * | ||
523 | it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req); | ||
524 | struct GNUNET_HashCode key; | ||
525 | const struct GNUNET_SERVICE_Client *c; | ||
526 | while (GNUNET_YES | ||
527 | == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key, | ||
528 | (const void **) &c)) | ||
529 | { | ||
530 | if (c == client) | ||
531 | { | ||
532 | GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, client); | ||
533 | GNUNET_CONTAINER_multihashmap_iterator_destroy (it); | ||
534 | return GNUNET_YES; | ||
535 | } | ||
536 | } | ||
537 | GNUNET_CONTAINER_multihashmap_iterator_destroy (it); | ||
538 | return GNUNET_NO; | ||
539 | } | ||
540 | |||
541 | |||
542 | /** | ||
543 | * Send message to a client. | ||
544 | */ | ||
545 | static void | ||
546 | client_send (struct GNUNET_SERVICE_Client *client, | ||
547 | const struct GNUNET_MessageHeader *msg) | ||
548 | { | ||
549 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
550 | "%p Sending message to client.\n", client); | ||
551 | |||
552 | struct GNUNET_MQ_Envelope * | ||
553 | env = GNUNET_MQ_msg_copy (msg); | ||
554 | |||
555 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), | ||
556 | env); | ||
557 | } | ||
558 | |||
559 | |||
560 | /** | ||
561 | * Send message to all clients connected to the group. | ||
562 | */ | ||
563 | static void | ||
564 | client_send_group_keep_envelope (const struct Group *grp, | ||
565 | struct GNUNET_MQ_Envelope *env) | ||
566 | { | ||
567 | struct ClientList *cli = grp->clients_head; | ||
568 | |||
569 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
570 | "%p Sending message to all clients of the group.\n", | ||
571 | grp); | ||
572 | while (NULL != cli) | ||
573 | { | ||
574 | GNUNET_MQ_send_copy (GNUNET_SERVICE_client_get_mq (cli->client), | ||
575 | env); | ||
576 | cli = cli->next; | ||
577 | } | ||
578 | } | ||
579 | |||
580 | |||
581 | /** | ||
582 | * Send message to all clients connected to the group and | ||
583 | * takes care of freeing @env. | ||
584 | */ | ||
585 | static void | ||
586 | client_send_group (const struct Group *grp, | ||
587 | struct GNUNET_MQ_Envelope *env) | ||
588 | { | ||
589 | client_send_group_keep_envelope (grp, env); | ||
590 | GNUNET_MQ_discard (env); | ||
591 | } | ||
592 | |||
593 | |||
594 | /** | ||
595 | * Iterator callback for sending a message to origin clients. | ||
596 | */ | ||
597 | static int | ||
598 | client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash, | ||
599 | void *origin) | ||
600 | { | ||
601 | struct GNUNET_MQ_Envelope *env = cls; | ||
602 | struct Member *orig = origin; | ||
603 | |||
604 | client_send_group_keep_envelope (&orig->group, env); | ||
605 | return GNUNET_YES; | ||
606 | } | ||
607 | |||
608 | |||
609 | /** | ||
610 | * Iterator callback for sending a message to member clients. | ||
611 | */ | ||
612 | static int | ||
613 | client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash, | ||
614 | void *member) | ||
615 | { | ||
616 | struct GNUNET_MQ_Envelope *env = cls; | ||
617 | struct Member *mem = member; | ||
618 | |||
619 | if (NULL != mem->join_dcsn) | ||
620 | { /* Only send message to admitted members */ | ||
621 | client_send_group_keep_envelope (&mem->group, env); | ||
622 | } | ||
623 | return GNUNET_YES; | ||
624 | } | ||
625 | |||
626 | |||
627 | /** | ||
628 | * Send message to all origin and member clients connected to the group. | ||
629 | * | ||
630 | * @param pub_key_hash | ||
631 | * H(key_pub) of the group. | ||
632 | * @param msg | ||
633 | * Message to send. | ||
634 | */ | ||
635 | static int | ||
636 | client_send_all (struct GNUNET_HashCode *pub_key_hash, | ||
637 | struct GNUNET_MQ_Envelope *env) | ||
638 | { | ||
639 | int n = 0; | ||
640 | n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash, | ||
641 | client_send_origin_cb, | ||
642 | (void *) env); | ||
643 | n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash, | ||
644 | client_send_member_cb, | ||
645 | (void *) env); | ||
646 | GNUNET_MQ_discard (env); | ||
647 | return n; | ||
648 | } | ||
649 | |||
650 | |||
651 | /** | ||
652 | * Send message to a random origin client or a random member client. | ||
653 | * | ||
654 | * @param grp The group to send @a msg to. | ||
655 | * @param msg Message to send. | ||
656 | */ | ||
657 | static int | ||
658 | client_send_random (struct GNUNET_HashCode *pub_key_hash, | ||
659 | struct GNUNET_MQ_Envelope *env) | ||
660 | { | ||
661 | int n = 0; | ||
662 | n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb, | ||
663 | (void *) env); | ||
664 | if (n <= 0) | ||
665 | n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb, | ||
666 | (void *) env); | ||
667 | GNUNET_MQ_discard (env); | ||
668 | return n; | ||
669 | } | ||
670 | |||
671 | |||
672 | /** | ||
673 | * Send message to all origin clients connected to the group. | ||
674 | * | ||
675 | * @param pub_key_hash | ||
676 | * H(key_pub) of the group. | ||
677 | * @param msg | ||
678 | * Message to send. | ||
679 | */ | ||
680 | static int | ||
681 | client_send_origin (struct GNUNET_HashCode *pub_key_hash, | ||
682 | struct GNUNET_MQ_Envelope *env) | ||
683 | { | ||
684 | int n = 0; | ||
685 | n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash, | ||
686 | client_send_origin_cb, | ||
687 | (void *) env); | ||
688 | return n; | ||
689 | } | ||
690 | |||
691 | |||
692 | /** | ||
693 | * Send fragment acknowledgement to all clients of the channel. | ||
694 | * | ||
695 | * @param pub_key_hash | ||
696 | * H(key_pub) of the group. | ||
697 | */ | ||
698 | static void | ||
699 | client_send_ack (struct GNUNET_HashCode *pub_key_hash) | ||
700 | { | ||
701 | struct GNUNET_MQ_Envelope *env; | ||
702 | |||
703 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
704 | "Sending message ACK to client.\n"); | ||
705 | env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK); | ||
706 | client_send_all (pub_key_hash, env); | ||
707 | } | ||
708 | |||
709 | |||
710 | struct CadetTransmitClosure | ||
711 | { | ||
712 | struct Channel *chn; | ||
713 | const struct GNUNET_MessageHeader *msg; | ||
714 | }; | ||
715 | |||
716 | |||
717 | /** | ||
718 | * Send a message to a CADET channel. | ||
719 | * | ||
720 | * @param chn Channel. | ||
721 | * @param msg Message. | ||
722 | */ | ||
723 | static void | ||
724 | cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg) | ||
725 | { | ||
726 | struct GNUNET_MQ_Envelope * | ||
727 | env = GNUNET_MQ_msg_copy (msg); | ||
728 | |||
729 | GNUNET_MQ_send (GNUNET_CADET_get_mq (chn->channel), env); | ||
730 | |||
731 | if (0 < chn->window_size) | ||
732 | { | ||
733 | client_send_ack (&chn->group_pub_hash); | ||
734 | } | ||
735 | else | ||
736 | { | ||
737 | chn->msgs_pending++; | ||
738 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
739 | "%p Queuing message. Pending messages: %u\n", | ||
740 | chn, chn->msgs_pending); | ||
741 | } | ||
742 | } | ||
743 | |||
744 | |||
745 | /** | ||
746 | * Create CADET channel and send a join request. | ||
747 | */ | ||
748 | static void | ||
749 | cadet_send_join_request (struct Member *mem) | ||
750 | { | ||
751 | mem->origin_channel = cadet_channel_create (&mem->group, &mem->origin); | ||
752 | cadet_send_channel (mem->origin_channel, &mem->join_req->header); | ||
753 | |||
754 | uint32_t i; | ||
755 | for (i = 0; i < mem->relay_count; i++) | ||
756 | { | ||
757 | struct Channel * | ||
758 | chn = cadet_channel_create (&mem->group, &mem->relays[i]); | ||
759 | cadet_send_channel (chn, &mem->join_req->header); | ||
760 | } | ||
761 | } | ||
762 | |||
763 | |||
764 | static int | ||
765 | cadet_send_join_decision_cb (void *cls, | ||
766 | const struct GNUNET_HashCode *group_pub_hash, | ||
767 | void *channel) | ||
768 | { | ||
769 | const struct MulticastJoinDecisionMessageHeader *hdcsn = cls; | ||
770 | struct Channel *chn = channel; | ||
771 | |||
772 | const struct MulticastJoinDecisionMessage *dcsn = | ||
773 | (struct MulticastJoinDecisionMessage *) &hdcsn[1]; | ||
774 | |||
775 | if (0 == memcmp (&hdcsn->member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key)) | ||
776 | && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer))) | ||
777 | { | ||
778 | if (GNUNET_YES == ntohl (dcsn->is_admitted)) | ||
779 | { | ||
780 | chn->join_status = JOIN_ADMITTED; | ||
781 | } | ||
782 | else | ||
783 | { | ||
784 | chn->join_status = JOIN_REFUSED; | ||
785 | } | ||
786 | cadet_send_channel (chn, &hdcsn->header); | ||
787 | return GNUNET_YES; | ||
788 | } | ||
789 | |||
790 | // return GNUNET_YES to continue the multihashmap_get iteration | ||
791 | return GNUNET_YES; | ||
792 | } | ||
793 | |||
794 | |||
795 | /** | ||
796 | * Send join decision to a remote peer. | ||
797 | */ | ||
798 | static void | ||
799 | cadet_send_join_decision (struct Group *grp, | ||
800 | const struct MulticastJoinDecisionMessageHeader *hdcsn) | ||
801 | { | ||
802 | GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, &grp->pub_key_hash, | ||
803 | &cadet_send_join_decision_cb, | ||
804 | (void *) hdcsn); | ||
805 | } | ||
806 | |||
807 | |||
808 | /** | ||
809 | * Iterator callback for sending a message to origin clients. | ||
810 | */ | ||
811 | static int | ||
812 | cadet_send_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash, | ||
813 | void *channel) | ||
814 | { | ||
815 | const struct GNUNET_MessageHeader *msg = cls; | ||
816 | struct Channel *chn = channel; | ||
817 | if (JOIN_ADMITTED == chn->join_status) | ||
818 | cadet_send_channel (chn, msg); | ||
819 | return GNUNET_YES; | ||
820 | } | ||
821 | |||
822 | |||
823 | /** | ||
824 | * Send message to all connected children. | ||
825 | */ | ||
826 | static int | ||
827 | cadet_send_children (struct GNUNET_HashCode *pub_key_hash, | ||
828 | const struct GNUNET_MessageHeader *msg) | ||
829 | { | ||
830 | int n = 0; | ||
831 | if (channels_in != NULL) | ||
832 | n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, pub_key_hash, | ||
833 | cadet_send_cb, (void *) msg); | ||
834 | return n; | ||
835 | } | ||
836 | |||
837 | |||
838 | #if 0 // unused as yet | ||
839 | /** | ||
840 | * Send message to all connected parents. | ||
841 | */ | ||
842 | static int | ||
843 | cadet_send_parents (struct GNUNET_HashCode *pub_key_hash, | ||
844 | const struct GNUNET_MessageHeader *msg) | ||
845 | { | ||
846 | int n = 0; | ||
847 | if (channels_in != NULL) | ||
848 | n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_out, pub_key_hash, | ||
849 | cadet_send_cb, (void *) msg); | ||
850 | return n; | ||
851 | } | ||
852 | #endif | ||
853 | |||
854 | |||
855 | /** | ||
856 | * CADET channel connect handler. | ||
857 | * | ||
858 | * @see GNUNET_CADET_ConnectEventHandler() | ||
859 | */ | ||
860 | static void * | ||
861 | cadet_notify_connect (void *cls, | ||
862 | struct GNUNET_CADET_Channel *channel, | ||
863 | const struct GNUNET_PeerIdentity *source) | ||
864 | { | ||
865 | struct Channel *chn = GNUNET_malloc (sizeof (struct Channel)); | ||
866 | chn->group = cls; | ||
867 | chn->channel = channel; | ||
868 | chn->direction = DIR_INCOMING; | ||
869 | chn->join_status = JOIN_NOT_ASKED; | ||
870 | |||
871 | GNUNET_CONTAINER_multihashmap_put (channels_in, &chn->group->pub_key_hash, chn, | ||
872 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
873 | return chn; | ||
874 | } | ||
875 | |||
876 | |||
877 | /** | ||
878 | * CADET window size change handler. | ||
879 | * | ||
880 | * @see GNUNET_CADET_WindowSizeEventHandler() | ||
881 | */ | ||
882 | static void | ||
883 | cadet_notify_window_change (void *cls, | ||
884 | const struct GNUNET_CADET_Channel *channel, | ||
885 | int window_size) | ||
886 | { | ||
887 | struct Channel *chn = cls; | ||
888 | |||
889 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
890 | "%p Window size changed to %d. Pending messages: %u\n", | ||
891 | chn, window_size, chn->msgs_pending); | ||
892 | |||
893 | chn->is_connected = GNUNET_YES; | ||
894 | chn->window_size = (int32_t) window_size; | ||
895 | |||
896 | for (int i = 0; i < window_size; i++) | ||
897 | { | ||
898 | if (0 < chn->msgs_pending) | ||
899 | { | ||
900 | client_send_ack (&chn->group_pub_hash); | ||
901 | chn->msgs_pending--; | ||
902 | } | ||
903 | else | ||
904 | { | ||
905 | break; | ||
906 | } | ||
907 | } | ||
908 | } | ||
909 | |||
910 | |||
911 | /** | ||
912 | * CADET channel disconnect handler. | ||
913 | * | ||
914 | * @see GNUNET_CADET_DisconnectEventHandler() | ||
915 | */ | ||
916 | static void | ||
917 | cadet_notify_disconnect (void *cls, | ||
918 | const struct GNUNET_CADET_Channel *channel) | ||
919 | { | ||
920 | if (NULL == cls) | ||
921 | return; | ||
922 | |||
923 | struct Channel *chn = cls; | ||
924 | if (NULL != chn->group) | ||
925 | { | ||
926 | if (GNUNET_NO == chn->group->is_origin) | ||
927 | { | ||
928 | struct Member *mem = (struct Member *) chn->group; | ||
929 | if (chn == mem->origin_channel) | ||
930 | mem->origin_channel = NULL; | ||
931 | } | ||
932 | } | ||
933 | |||
934 | int ret; | ||
935 | do | ||
936 | { | ||
937 | ret = replay_req_remove_cadet (chn); | ||
938 | } | ||
939 | while (GNUNET_YES == ret); | ||
940 | |||
941 | GNUNET_free (chn); | ||
942 | } | ||
943 | |||
944 | |||
945 | static int | ||
946 | check_cadet_join_request (void *cls, | ||
947 | const struct MulticastJoinRequestMessage *req) | ||
948 | { | ||
949 | struct Channel *chn = cls; | ||
950 | |||
951 | if (NULL == chn | ||
952 | || JOIN_NOT_ASKED != chn->join_status) | ||
953 | { | ||
954 | return GNUNET_SYSERR; | ||
955 | } | ||
956 | |||
957 | uint16_t size = ntohs (req->header.size); | ||
958 | if (size < sizeof (*req)) | ||
959 | { | ||
960 | GNUNET_break_op (0); | ||
961 | return GNUNET_SYSERR; | ||
962 | } | ||
963 | if (ntohl (req->purpose.size) != (size | ||
964 | - sizeof (req->header) | ||
965 | - sizeof (req->reserved) | ||
966 | - sizeof (req->signature))) | ||
967 | { | ||
968 | GNUNET_break_op (0); | ||
969 | return GNUNET_SYSERR; | ||
970 | } | ||
971 | if (GNUNET_OK != | ||
972 | GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST, | ||
973 | &req->purpose, &req->signature, | ||
974 | &req->member_pub_key)) | ||
975 | { | ||
976 | GNUNET_break_op (0); | ||
977 | return GNUNET_SYSERR; | ||
978 | } | ||
979 | |||
980 | return GNUNET_OK; | ||
981 | } | ||
982 | |||
983 | |||
984 | /** | ||
985 | * Incoming join request message from CADET. | ||
986 | */ | ||
987 | static void | ||
988 | handle_cadet_join_request (void *cls, | ||
989 | const struct MulticastJoinRequestMessage *req) | ||
990 | { | ||
991 | struct Channel *chn = cls; | ||
992 | GNUNET_CADET_receive_done (chn->channel); | ||
993 | |||
994 | struct GNUNET_HashCode group_pub_hash; | ||
995 | GNUNET_CRYPTO_hash (&req->group_pub_key, sizeof (req->group_pub_key), &group_pub_hash); | ||
996 | chn->group_pub_key = req->group_pub_key; | ||
997 | chn->group_pub_hash = group_pub_hash; | ||
998 | chn->member_pub_key = req->member_pub_key; | ||
999 | chn->peer = req->peer; | ||
1000 | chn->join_status = JOIN_WAITING; | ||
1001 | |||
1002 | client_send_all (&group_pub_hash, | ||
1003 | GNUNET_MQ_msg_copy (&req->header)); | ||
1004 | } | ||
1005 | |||
1006 | |||
1007 | static int | ||
1008 | check_cadet_join_decision (void *cls, | ||
1009 | const struct MulticastJoinDecisionMessageHeader *hdcsn) | ||
1010 | { | ||
1011 | uint16_t size = ntohs (hdcsn->header.size); | ||
1012 | if (size < sizeof (struct MulticastJoinDecisionMessageHeader) + | ||
1013 | sizeof (struct MulticastJoinDecisionMessage)) | ||
1014 | { | ||
1015 | GNUNET_break_op (0); | ||
1016 | return GNUNET_SYSERR; | ||
1017 | } | ||
1018 | |||
1019 | struct Channel *chn = cls; | ||
1020 | if (NULL == chn) | ||
1021 | { | ||
1022 | GNUNET_break (0); | ||
1023 | return GNUNET_SYSERR; | ||
1024 | } | ||
1025 | if (NULL == chn->group || GNUNET_NO != chn->group->is_origin) | ||
1026 | { | ||
1027 | GNUNET_break (0); | ||
1028 | return GNUNET_SYSERR; | ||
1029 | } | ||
1030 | switch (chn->join_status) | ||
1031 | { | ||
1032 | case JOIN_REFUSED: | ||
1033 | return GNUNET_SYSERR; | ||
1034 | |||
1035 | case JOIN_ADMITTED: | ||
1036 | return GNUNET_OK; | ||
1037 | |||
1038 | case JOIN_NOT_ASKED: | ||
1039 | case JOIN_WAITING: | ||
1040 | break; | ||
1041 | } | ||
1042 | |||
1043 | return GNUNET_OK; | ||
1044 | } | ||
1045 | |||
1046 | |||
1047 | /** | ||
1048 | * Incoming join decision message from CADET. | ||
1049 | */ | ||
1050 | static void | ||
1051 | handle_cadet_join_decision (void *cls, | ||
1052 | const struct MulticastJoinDecisionMessageHeader *hdcsn) | ||
1053 | { | ||
1054 | const struct MulticastJoinDecisionMessage * | ||
1055 | dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1]; | ||
1056 | |||
1057 | struct Channel *chn = cls; | ||
1058 | GNUNET_CADET_receive_done (chn->channel); | ||
1059 | |||
1060 | // FIXME: do we need to copy chn->peer or compare it with hdcsn->peer? | ||
1061 | struct Member *mem = (struct Member *) chn->group; | ||
1062 | client_send_join_decision (mem, hdcsn); | ||
1063 | if (GNUNET_YES == ntohl (dcsn->is_admitted)) | ||
1064 | { | ||
1065 | chn->join_status = JOIN_ADMITTED; | ||
1066 | } | ||
1067 | else | ||
1068 | { | ||
1069 | chn->join_status = JOIN_REFUSED; | ||
1070 | cadet_channel_destroy (chn); | ||
1071 | } | ||
1072 | } | ||
1073 | |||
1074 | |||
1075 | static int | ||
1076 | check_cadet_message (void *cls, | ||
1077 | const struct GNUNET_MULTICAST_MessageHeader *msg) | ||
1078 | { | ||
1079 | uint16_t size = ntohs (msg->header.size); | ||
1080 | if (size < sizeof (*msg)) | ||
1081 | { | ||
1082 | GNUNET_break_op (0); | ||
1083 | return GNUNET_SYSERR; | ||
1084 | } | ||
1085 | |||
1086 | struct Channel *chn = cls; | ||
1087 | if (NULL == chn) | ||
1088 | { | ||
1089 | GNUNET_break (0); | ||
1090 | return GNUNET_SYSERR; | ||
1091 | } | ||
1092 | if (ntohl (msg->purpose.size) != (size | ||
1093 | - sizeof (msg->header) | ||
1094 | - sizeof (msg->hop_counter) | ||
1095 | - sizeof (msg->signature))) | ||
1096 | { | ||
1097 | GNUNET_break_op (0); | ||
1098 | return GNUNET_SYSERR; | ||
1099 | } | ||
1100 | if (GNUNET_OK != | ||
1101 | GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE, | ||
1102 | &msg->purpose, &msg->signature, | ||
1103 | &chn->group_pub_key)) | ||
1104 | { | ||
1105 | GNUNET_break_op (0); | ||
1106 | return GNUNET_SYSERR; | ||
1107 | } | ||
1108 | |||
1109 | return GNUNET_OK; | ||
1110 | } | ||
1111 | |||
1112 | |||
1113 | /** | ||
1114 | * Incoming multicast message from CADET. | ||
1115 | */ | ||
1116 | static void | ||
1117 | handle_cadet_message (void *cls, | ||
1118 | const struct GNUNET_MULTICAST_MessageHeader *msg) | ||
1119 | { | ||
1120 | struct Channel *chn = cls; | ||
1121 | GNUNET_CADET_receive_done (chn->channel); | ||
1122 | client_send_all (&chn->group_pub_hash, | ||
1123 | GNUNET_MQ_msg_copy (&msg->header)); | ||
1124 | } | ||
1125 | |||
1126 | |||
1127 | static int | ||
1128 | check_cadet_request (void *cls, | ||
1129 | const struct GNUNET_MULTICAST_RequestHeader *req) | ||
1130 | { | ||
1131 | uint16_t size = ntohs (req->header.size); | ||
1132 | if (size < sizeof (*req)) | ||
1133 | { | ||
1134 | GNUNET_break_op (0); | ||
1135 | return GNUNET_SYSERR; | ||
1136 | } | ||
1137 | |||
1138 | struct Channel *chn = cls; | ||
1139 | if (NULL == chn) | ||
1140 | { | ||
1141 | GNUNET_break (0); | ||
1142 | return GNUNET_SYSERR; | ||
1143 | } | ||
1144 | if (ntohl (req->purpose.size) != (size | ||
1145 | - sizeof (req->header) | ||
1146 | - sizeof (req->member_pub_key) | ||
1147 | - sizeof (req->signature))) | ||
1148 | { | ||
1149 | GNUNET_break_op (0); | ||
1150 | return GNUNET_SYSERR; | ||
1151 | } | ||
1152 | if (GNUNET_OK != | ||
1153 | GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST, | ||
1154 | &req->purpose, &req->signature, | ||
1155 | &req->member_pub_key)) | ||
1156 | { | ||
1157 | GNUNET_break_op (0); | ||
1158 | return GNUNET_SYSERR; | ||
1159 | } | ||
1160 | |||
1161 | return GNUNET_OK; | ||
1162 | } | ||
1163 | |||
1164 | |||
1165 | /** | ||
1166 | * Incoming multicast request message from CADET. | ||
1167 | */ | ||
1168 | static void | ||
1169 | handle_cadet_request (void *cls, | ||
1170 | const struct GNUNET_MULTICAST_RequestHeader *req) | ||
1171 | { | ||
1172 | struct Channel *chn = cls; | ||
1173 | GNUNET_CADET_receive_done (chn->channel); | ||
1174 | client_send_origin (&chn->group_pub_hash, | ||
1175 | GNUNET_MQ_msg_copy (&req->header)); | ||
1176 | } | ||
1177 | |||
1178 | |||
1179 | // FIXME: do checks in handle_cadet_replay_request | ||
1180 | //static int | ||
1181 | //check_cadet_replay_request (void *cls, | ||
1182 | // const struct MulticastReplayRequestMessage *req) | ||
1183 | //{ | ||
1184 | // uint16_t size = ntohs (req->header.size); | ||
1185 | // if (size < sizeof (*req)) | ||
1186 | // { | ||
1187 | // GNUNET_break_op (0); | ||
1188 | // return GNUNET_SYSERR; | ||
1189 | // } | ||
1190 | // | ||
1191 | // struct Channel *chn = cls; | ||
1192 | // if (NULL == chn) | ||
1193 | // { | ||
1194 | // GNUNET_break_op (0); | ||
1195 | // return GNUNET_SYSERR; | ||
1196 | // } | ||
1197 | // | ||
1198 | // return GNUNET_OK; | ||
1199 | //} | ||
1200 | |||
1201 | |||
1202 | /** | ||
1203 | * Incoming multicast replay request from CADET. | ||
1204 | */ | ||
1205 | static void | ||
1206 | handle_cadet_replay_request (void *cls, | ||
1207 | const struct MulticastReplayRequestMessage *req) | ||
1208 | { | ||
1209 | struct Channel *chn = cls; | ||
1210 | |||
1211 | GNUNET_CADET_receive_done (chn->channel); | ||
1212 | |||
1213 | struct MulticastReplayRequestMessage rep = *req; | ||
1214 | GNUNET_memcpy (&rep.member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key)); | ||
1215 | |||
1216 | struct GNUNET_CONTAINER_MultiHashMap * | ||
1217 | grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet, | ||
1218 | &chn->group->pub_key_hash); | ||
1219 | if (NULL == grp_replay_req) | ||
1220 | { | ||
1221 | grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); | ||
1222 | GNUNET_CONTAINER_multihashmap_put (replay_req_cadet, | ||
1223 | &chn->group->pub_key_hash, grp_replay_req, | ||
1224 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1225 | } | ||
1226 | struct GNUNET_HashCode key_hash; | ||
1227 | replay_key_hash (rep.fragment_id, | ||
1228 | rep.message_id, | ||
1229 | rep.fragment_offset, | ||
1230 | rep.flags, | ||
1231 | &key_hash); | ||
1232 | GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn, | ||
1233 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
1234 | |||
1235 | client_send_random (&chn->group_pub_hash, | ||
1236 | GNUNET_MQ_msg_copy (&rep.header)); | ||
1237 | } | ||
1238 | |||
1239 | |||
1240 | static int | ||
1241 | check_cadet_replay_response (void *cls, | ||
1242 | const struct MulticastReplayResponseMessage *res) | ||
1243 | { | ||
1244 | struct Channel *chn = cls; | ||
1245 | if (NULL == chn) | ||
1246 | { | ||
1247 | GNUNET_break (0); | ||
1248 | return GNUNET_SYSERR; | ||
1249 | } | ||
1250 | return GNUNET_OK; | ||
1251 | } | ||
1252 | |||
1253 | |||
1254 | /** | ||
1255 | * Incoming multicast replay response from CADET. | ||
1256 | */ | ||
1257 | static void | ||
1258 | handle_cadet_replay_response (void *cls, | ||
1259 | const struct MulticastReplayResponseMessage *res) | ||
1260 | { | ||
1261 | struct Channel *chn = cls; | ||
1262 | GNUNET_CADET_receive_done (chn->channel); | ||
1263 | |||
1264 | /* @todo FIXME: got replay error response, send request to other members */ | ||
1265 | } | ||
1266 | |||
1267 | |||
1268 | static void | ||
1269 | group_set_cadet_port_hash (struct Group *grp) | ||
1270 | { | ||
1271 | struct CadetPort { | ||
1272 | struct GNUNET_CRYPTO_EddsaPublicKey pub_key; | ||
1273 | uint32_t app_type; | ||
1274 | } port = { | ||
1275 | grp->pub_key, | ||
1276 | GNUNET_APPLICATION_TYPE_MULTICAST, | ||
1277 | }; | ||
1278 | GNUNET_CRYPTO_hash (&port, sizeof (port), &grp->cadet_port_hash); | ||
1279 | } | ||
1280 | |||
1281 | |||
1282 | |||
1283 | /** | ||
1284 | * Create new outgoing CADET channel. | ||
1285 | * | ||
1286 | * @param peer | ||
1287 | * Peer to connect to. | ||
1288 | * @param group_pub_key | ||
1289 | * Public key of group the channel belongs to. | ||
1290 | * @param group_pub_hash | ||
1291 | * Hash of @a group_pub_key. | ||
1292 | * | ||
1293 | * @return Channel. | ||
1294 | */ | ||
1295 | static struct Channel * | ||
1296 | cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer) | ||
1297 | { | ||
1298 | struct Channel *chn = GNUNET_malloc (sizeof (*chn)); | ||
1299 | chn->group = grp; | ||
1300 | chn->group_pub_key = grp->pub_key; | ||
1301 | chn->group_pub_hash = grp->pub_key_hash; | ||
1302 | chn->peer = *peer; | ||
1303 | chn->direction = DIR_OUTGOING; | ||
1304 | chn->is_connected = GNUNET_NO; | ||
1305 | chn->join_status = JOIN_WAITING; | ||
1306 | |||
1307 | struct GNUNET_MQ_MessageHandler cadet_handlers[] = { | ||
1308 | GNUNET_MQ_hd_var_size (cadet_message, | ||
1309 | GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, | ||
1310 | struct GNUNET_MULTICAST_MessageHeader, | ||
1311 | chn), | ||
1312 | |||
1313 | GNUNET_MQ_hd_var_size (cadet_join_decision, | ||
1314 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, | ||
1315 | struct MulticastJoinDecisionMessageHeader, | ||
1316 | chn), | ||
1317 | |||
1318 | GNUNET_MQ_hd_fixed_size (cadet_replay_request, | ||
1319 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, | ||
1320 | struct MulticastReplayRequestMessage, | ||
1321 | chn), | ||
1322 | |||
1323 | GNUNET_MQ_hd_var_size (cadet_replay_response, | ||
1324 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, | ||
1325 | struct MulticastReplayResponseMessage, | ||
1326 | chn), | ||
1327 | |||
1328 | GNUNET_MQ_handler_end () | ||
1329 | }; | ||
1330 | |||
1331 | chn->channel = GNUNET_CADET_channel_create (cadet, chn, &chn->peer, | ||
1332 | &grp->cadet_port_hash, | ||
1333 | GNUNET_CADET_OPTION_RELIABLE, | ||
1334 | cadet_notify_window_change, | ||
1335 | cadet_notify_disconnect, | ||
1336 | cadet_handlers); | ||
1337 | GNUNET_CONTAINER_multihashmap_put (channels_out, &chn->group_pub_hash, chn, | ||
1338 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
1339 | return chn; | ||
1340 | } | ||
1341 | |||
1342 | |||
1343 | /** | ||
1344 | * Destroy outgoing CADET channel. | ||
1345 | */ | ||
1346 | static void | ||
1347 | cadet_channel_destroy (struct Channel *chn) | ||
1348 | { | ||
1349 | GNUNET_CADET_channel_destroy (chn->channel); | ||
1350 | GNUNET_CONTAINER_multihashmap_remove_all (channels_out, &chn->group_pub_hash); | ||
1351 | GNUNET_free (chn); | ||
1352 | } | ||
1353 | |||
1354 | /** | ||
1355 | * Handle a connecting client starting an origin. | ||
1356 | */ | ||
1357 | static void | ||
1358 | handle_client_origin_start (void *cls, | ||
1359 | const struct MulticastOriginStartMessage *msg) | ||
1360 | { | ||
1361 | struct Client *c = cls; | ||
1362 | struct GNUNET_SERVICE_Client *client = c->client; | ||
1363 | |||
1364 | struct GNUNET_CRYPTO_EddsaPublicKey pub_key; | ||
1365 | struct GNUNET_HashCode pub_key_hash; | ||
1366 | |||
1367 | GNUNET_CRYPTO_eddsa_key_get_public (&msg->group_key, &pub_key); | ||
1368 | GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash); | ||
1369 | |||
1370 | struct Origin * | ||
1371 | orig = GNUNET_CONTAINER_multihashmap_get (origins, &pub_key_hash); | ||
1372 | struct Group *grp; | ||
1373 | |||
1374 | if (NULL == orig) | ||
1375 | { | ||
1376 | orig = GNUNET_new (struct Origin); | ||
1377 | orig->priv_key = msg->group_key; | ||
1378 | orig->max_fragment_id = GNUNET_ntohll (msg->max_fragment_id); | ||
1379 | |||
1380 | grp = c->group = &orig->group; | ||
1381 | grp->origin = orig; | ||
1382 | grp->is_origin = GNUNET_YES; | ||
1383 | grp->pub_key = pub_key; | ||
1384 | grp->pub_key_hash = pub_key_hash; | ||
1385 | grp->is_disconnected = GNUNET_NO; | ||
1386 | |||
1387 | GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig, | ||
1388 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1389 | |||
1390 | group_set_cadet_port_hash (grp); | ||
1391 | |||
1392 | struct GNUNET_MQ_MessageHandler cadet_handlers[] = { | ||
1393 | GNUNET_MQ_hd_var_size (cadet_message, | ||
1394 | GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, | ||
1395 | struct GNUNET_MULTICAST_MessageHeader, | ||
1396 | grp), | ||
1397 | |||
1398 | GNUNET_MQ_hd_var_size (cadet_request, | ||
1399 | GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, | ||
1400 | struct GNUNET_MULTICAST_RequestHeader, | ||
1401 | grp), | ||
1402 | |||
1403 | GNUNET_MQ_hd_var_size (cadet_join_request, | ||
1404 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, | ||
1405 | struct MulticastJoinRequestMessage, | ||
1406 | grp), | ||
1407 | |||
1408 | GNUNET_MQ_hd_fixed_size (cadet_replay_request, | ||
1409 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, | ||
1410 | struct MulticastReplayRequestMessage, | ||
1411 | grp), | ||
1412 | |||
1413 | GNUNET_MQ_hd_var_size (cadet_replay_response, | ||
1414 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, | ||
1415 | struct MulticastReplayResponseMessage, | ||
1416 | grp), | ||
1417 | |||
1418 | GNUNET_MQ_handler_end () | ||
1419 | }; | ||
1420 | |||
1421 | |||
1422 | orig->cadet_port = GNUNET_CADET_open_port (cadet, | ||
1423 | &grp->cadet_port_hash, | ||
1424 | cadet_notify_connect, | ||
1425 | grp, | ||
1426 | cadet_notify_window_change, | ||
1427 | cadet_notify_disconnect, | ||
1428 | cadet_handlers); | ||
1429 | } | ||
1430 | else | ||
1431 | { | ||
1432 | grp = &orig->group; | ||
1433 | } | ||
1434 | |||
1435 | struct ClientList *cl = GNUNET_new (struct ClientList); | ||
1436 | cl->client = client; | ||
1437 | GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl); | ||
1438 | |||
1439 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1440 | "%p Client connected as origin to group %s.\n", | ||
1441 | orig, GNUNET_h2s (&grp->pub_key_hash)); | ||
1442 | GNUNET_SERVICE_client_continue (client); | ||
1443 | } | ||
1444 | |||
1445 | |||
1446 | static int | ||
1447 | check_client_member_join (void *cls, | ||
1448 | const struct MulticastMemberJoinMessage *msg) | ||
1449 | { | ||
1450 | uint16_t msg_size = ntohs (msg->header.size); | ||
1451 | struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1]; | ||
1452 | uint32_t relay_count = ntohl (msg->relay_count); | ||
1453 | |||
1454 | if (0 != relay_count) | ||
1455 | { | ||
1456 | if (UINT32_MAX / relay_count < sizeof (*relays)){ | ||
1457 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1458 | "relay_count (%lu) * sizeof (*relays) (%lu) exceeds UINT32_MAX!\n", | ||
1459 | (unsigned long)relay_count, | ||
1460 | sizeof (*relays)); | ||
1461 | return GNUNET_SYSERR; | ||
1462 | } | ||
1463 | } | ||
1464 | uint32_t relay_size = relay_count * sizeof (*relays); | ||
1465 | struct GNUNET_MessageHeader *join_msg = NULL; | ||
1466 | uint16_t join_msg_size = 0; | ||
1467 | if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader) | ||
1468 | <= msg_size) | ||
1469 | { | ||
1470 | join_msg = (struct GNUNET_MessageHeader *) | ||
1471 | (((char *) &msg[1]) + relay_size); | ||
1472 | join_msg_size = ntohs (join_msg->size); | ||
1473 | if (UINT16_MAX - join_msg_size < sizeof (struct MulticastJoinRequestMessage)){ | ||
1474 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1475 | "join_msg_size (%u) + sizeof (struct MulticastJoinRequestMessage) (%lu) exceeds UINT16_MAX!\n", | ||
1476 | (unsigned)join_msg_size, | ||
1477 | (unsigned long)sizeof (struct MulticastJoinRequestMessage)); | ||
1478 | return GNUNET_SYSERR; | ||
1479 | } | ||
1480 | } | ||
1481 | if (msg_size != (sizeof (*msg) + relay_size + join_msg_size)){ | ||
1482 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1483 | "msg_size does not match real size of message!\n"); | ||
1484 | return GNUNET_SYSERR; | ||
1485 | }else{ | ||
1486 | return GNUNET_OK; | ||
1487 | } | ||
1488 | } | ||
1489 | |||
1490 | |||
1491 | /** | ||
1492 | * Handle a connecting client joining a group. | ||
1493 | */ | ||
1494 | static void | ||
1495 | handle_client_member_join (void *cls, | ||
1496 | const struct MulticastMemberJoinMessage *msg) | ||
1497 | { | ||
1498 | struct Client *c = cls; | ||
1499 | struct GNUNET_SERVICE_Client *client = c->client; | ||
1500 | |||
1501 | uint16_t msg_size = ntohs (msg->header.size); | ||
1502 | |||
1503 | struct GNUNET_CRYPTO_EcdsaPublicKey mem_pub_key; | ||
1504 | struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash; | ||
1505 | |||
1506 | GNUNET_CRYPTO_ecdsa_key_get_public (&msg->member_key, &mem_pub_key); | ||
1507 | GNUNET_CRYPTO_hash (&mem_pub_key, sizeof (mem_pub_key), &mem_pub_key_hash); | ||
1508 | GNUNET_CRYPTO_hash (&msg->group_pub_key, sizeof (msg->group_pub_key), &pub_key_hash); | ||
1509 | |||
1510 | struct GNUNET_CONTAINER_MultiHashMap * | ||
1511 | grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, &pub_key_hash); | ||
1512 | struct Member *mem = NULL; | ||
1513 | struct Group *grp; | ||
1514 | |||
1515 | if (NULL != grp_mem) | ||
1516 | { | ||
1517 | mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &mem_pub_key_hash); | ||
1518 | } | ||
1519 | |||
1520 | if (NULL == mem) | ||
1521 | { | ||
1522 | mem = GNUNET_new (struct Member); | ||
1523 | mem->origin = msg->origin; | ||
1524 | mem->priv_key = msg->member_key; | ||
1525 | mem->pub_key = mem_pub_key; | ||
1526 | mem->pub_key_hash = mem_pub_key_hash; | ||
1527 | mem->max_fragment_id = 0; // FIXME | ||
1528 | |||
1529 | grp = c->group = &mem->group; | ||
1530 | grp->member = mem; | ||
1531 | grp->is_origin = GNUNET_NO; | ||
1532 | grp->pub_key = msg->group_pub_key; | ||
1533 | grp->pub_key_hash = pub_key_hash; | ||
1534 | grp->is_disconnected = GNUNET_NO; | ||
1535 | group_set_cadet_port_hash (grp); | ||
1536 | |||
1537 | if (NULL == grp_mem) | ||
1538 | { | ||
1539 | grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); | ||
1540 | GNUNET_CONTAINER_multihashmap_put (group_members, &grp->pub_key_hash, grp_mem, | ||
1541 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1542 | } | ||
1543 | GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem, | ||
1544 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1545 | |||
1546 | // FIXME: should the members hash map have option UNIQUE_FAST? | ||
1547 | GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem, | ||
1548 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
1549 | } | ||
1550 | else | ||
1551 | { | ||
1552 | grp = &mem->group; | ||
1553 | } | ||
1554 | |||
1555 | struct ClientList *cl = GNUNET_new (struct ClientList); | ||
1556 | cl->client = client; | ||
1557 | GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl); | ||
1558 | |||
1559 | char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key); | ||
1560 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1561 | "Client connected to group %s as member %s (%s). size = %d\n", | ||
1562 | GNUNET_h2s (&grp->pub_key_hash), | ||
1563 | GNUNET_h2s2 (&mem->pub_key_hash), | ||
1564 | str, | ||
1565 | GNUNET_CONTAINER_multihashmap_size (members)); | ||
1566 | GNUNET_free (str); | ||
1567 | |||
1568 | if (NULL != mem->join_dcsn) | ||
1569 | { /* Already got a join decision, send it to client. */ | ||
1570 | struct GNUNET_MQ_Envelope * | ||
1571 | env = GNUNET_MQ_msg_copy (&mem->join_dcsn->header); | ||
1572 | |||
1573 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), | ||
1574 | env); | ||
1575 | } | ||
1576 | else | ||
1577 | { /* First client of the group, send join request. */ | ||
1578 | struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1]; | ||
1579 | uint32_t relay_count = ntohl (msg->relay_count); | ||
1580 | uint16_t relay_size = relay_count * sizeof (*relays); | ||
1581 | struct GNUNET_MessageHeader *join_msg = NULL; | ||
1582 | uint16_t join_msg_size = 0; | ||
1583 | if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader) | ||
1584 | <= msg_size) | ||
1585 | { | ||
1586 | join_msg = (struct GNUNET_MessageHeader *) | ||
1587 | (((char *) &msg[1]) + relay_size); | ||
1588 | join_msg_size = ntohs (join_msg->size); | ||
1589 | } | ||
1590 | |||
1591 | uint16_t req_msg_size = sizeof (struct MulticastJoinRequestMessage) + join_msg_size; | ||
1592 | struct MulticastJoinRequestMessage * | ||
1593 | req = GNUNET_malloc (req_msg_size); | ||
1594 | req->header.size = htons (req_msg_size); | ||
1595 | req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST); | ||
1596 | req->group_pub_key = grp->pub_key; | ||
1597 | req->peer = this_peer; | ||
1598 | GNUNET_CRYPTO_ecdsa_key_get_public (&mem->priv_key, &req->member_pub_key); | ||
1599 | if (0 < join_msg_size) | ||
1600 | GNUNET_memcpy (&req[1], join_msg, join_msg_size); | ||
1601 | |||
1602 | req->member_pub_key = mem->pub_key; | ||
1603 | req->purpose.size = htonl (req_msg_size | ||
1604 | - sizeof (req->header) | ||
1605 | - sizeof (req->reserved) | ||
1606 | - sizeof (req->signature)); | ||
1607 | req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST); | ||
1608 | |||
1609 | if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &req->purpose, | ||
1610 | &req->signature)) | ||
1611 | { | ||
1612 | /* FIXME: handle error */ | ||
1613 | GNUNET_assert (0); | ||
1614 | } | ||
1615 | |||
1616 | if (NULL != mem->join_req) | ||
1617 | GNUNET_free (mem->join_req); | ||
1618 | mem->join_req = req; | ||
1619 | |||
1620 | if (0 == | ||
1621 | client_send_origin (&grp->pub_key_hash, | ||
1622 | GNUNET_MQ_msg_copy (&mem->join_req->header))) | ||
1623 | { /* No local origins, send to remote origin */ | ||
1624 | cadet_send_join_request (mem); | ||
1625 | } | ||
1626 | } | ||
1627 | GNUNET_SERVICE_client_continue (client); | ||
1628 | } | ||
1629 | |||
1630 | |||
1631 | static void | ||
1632 | client_send_join_decision (struct Member *mem, | ||
1633 | const struct MulticastJoinDecisionMessageHeader *hdcsn) | ||
1634 | { | ||
1635 | client_send_group (&mem->group, GNUNET_MQ_msg_copy (&hdcsn->header)); | ||
1636 | |||
1637 | const struct MulticastJoinDecisionMessage * | ||
1638 | dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1]; | ||
1639 | if (GNUNET_YES == ntohl (dcsn->is_admitted)) | ||
1640 | { /* Member admitted, store join_decision. */ | ||
1641 | uint16_t dcsn_size = ntohs (dcsn->header.size); | ||
1642 | mem->join_dcsn = GNUNET_malloc (dcsn_size); | ||
1643 | GNUNET_memcpy (mem->join_dcsn, dcsn, dcsn_size); | ||
1644 | } | ||
1645 | else | ||
1646 | { /* Refused entry, but replay would be still possible for past members. */ | ||
1647 | } | ||
1648 | } | ||
1649 | |||
1650 | |||
1651 | static int | ||
1652 | check_client_join_decision (void *cls, | ||
1653 | const struct MulticastJoinDecisionMessageHeader *hdcsn) | ||
1654 | { | ||
1655 | return GNUNET_OK; | ||
1656 | } | ||
1657 | |||
1658 | |||
1659 | /** | ||
1660 | * Join decision from client. | ||
1661 | */ | ||
1662 | static void | ||
1663 | handle_client_join_decision (void *cls, | ||
1664 | const struct MulticastJoinDecisionMessageHeader *hdcsn) | ||
1665 | { | ||
1666 | struct Client *c = cls; | ||
1667 | struct GNUNET_SERVICE_Client *client = c->client; | ||
1668 | struct Group *grp = c->group; | ||
1669 | |||
1670 | if (NULL == grp) | ||
1671 | { | ||
1672 | GNUNET_break (0); | ||
1673 | GNUNET_SERVICE_client_drop (client); | ||
1674 | return; | ||
1675 | } | ||
1676 | GNUNET_assert (GNUNET_NO == grp->is_disconnected); | ||
1677 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1678 | "%p got join decision from client for group %s..\n", | ||
1679 | grp, GNUNET_h2s (&grp->pub_key_hash)); | ||
1680 | |||
1681 | struct GNUNET_CONTAINER_MultiHashMap * | ||
1682 | grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, | ||
1683 | &grp->pub_key_hash); | ||
1684 | struct Member *mem = NULL; | ||
1685 | if (NULL != grp_mem) | ||
1686 | { | ||
1687 | struct GNUNET_HashCode member_key_hash; | ||
1688 | GNUNET_CRYPTO_hash (&hdcsn->member_pub_key, sizeof (hdcsn->member_pub_key), | ||
1689 | &member_key_hash); | ||
1690 | mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &member_key_hash); | ||
1691 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1692 | "%p ..and member %s: %p\n", | ||
1693 | grp, GNUNET_h2s (&member_key_hash), mem); | ||
1694 | } | ||
1695 | |||
1696 | if (NULL != mem) | ||
1697 | { /* Found local member */ | ||
1698 | client_send_join_decision (mem, hdcsn); | ||
1699 | } | ||
1700 | else | ||
1701 | { /* Look for remote member */ | ||
1702 | cadet_send_join_decision (grp, hdcsn); | ||
1703 | } | ||
1704 | GNUNET_SERVICE_client_continue (client); | ||
1705 | } | ||
1706 | |||
1707 | |||
1708 | static void | ||
1709 | handle_client_part_request (void *cls, | ||
1710 | const struct GNUNET_MessageHeader *msg) | ||
1711 | { | ||
1712 | struct Client *c = cls; | ||
1713 | struct GNUNET_SERVICE_Client *client = c->client; | ||
1714 | struct Group *grp = c->group; | ||
1715 | struct GNUNET_MQ_Envelope *env; | ||
1716 | |||
1717 | if (NULL == grp) | ||
1718 | { | ||
1719 | GNUNET_break (0); | ||
1720 | GNUNET_SERVICE_client_drop (client); | ||
1721 | return; | ||
1722 | } | ||
1723 | GNUNET_assert (GNUNET_NO == grp->is_disconnected); | ||
1724 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1725 | "%p got part request from client for group %s.\n", | ||
1726 | grp, GNUNET_h2s (&grp->pub_key_hash)); | ||
1727 | grp->is_disconnected = GNUNET_YES; | ||
1728 | env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK); | ||
1729 | client_send_group (grp, env); | ||
1730 | GNUNET_SERVICE_client_continue (client); | ||
1731 | } | ||
1732 | |||
1733 | |||
1734 | static int | ||
1735 | check_client_multicast_message (void *cls, | ||
1736 | const struct GNUNET_MULTICAST_MessageHeader *msg) | ||
1737 | { | ||
1738 | return GNUNET_OK; | ||
1739 | } | ||
1740 | |||
1741 | |||
1742 | /** | ||
1743 | * Incoming message from a client. | ||
1744 | */ | ||
1745 | static void | ||
1746 | handle_client_multicast_message (void *cls, | ||
1747 | const struct GNUNET_MULTICAST_MessageHeader *msg) | ||
1748 | { | ||
1749 | // FIXME: what if GNUNET_YES == grp->is_disconnected? Do we allow sending messages? | ||
1750 | struct Client *c = cls; | ||
1751 | struct GNUNET_SERVICE_Client *client = c->client; | ||
1752 | struct Group *grp = c->group; | ||
1753 | |||
1754 | if (NULL == grp) | ||
1755 | { | ||
1756 | GNUNET_break (0); | ||
1757 | GNUNET_SERVICE_client_drop (client); | ||
1758 | return; | ||
1759 | } | ||
1760 | GNUNET_assert (GNUNET_YES == grp->is_origin); | ||
1761 | struct Origin *orig = grp->origin; | ||
1762 | |||
1763 | // FIXME: use GNUNET_MQ_msg_copy | ||
1764 | /* FIXME: yucky, should use separate message structs for P2P and CS! */ | ||
1765 | struct GNUNET_MULTICAST_MessageHeader * | ||
1766 | out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (&msg->header); | ||
1767 | out->fragment_id = GNUNET_htonll (++orig->max_fragment_id); | ||
1768 | out->purpose.size = htonl (ntohs (out->header.size) | ||
1769 | - sizeof (out->header) | ||
1770 | - sizeof (out->hop_counter) | ||
1771 | - sizeof (out->signature)); | ||
1772 | out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE); | ||
1773 | |||
1774 | if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&orig->priv_key, &out->purpose, | ||
1775 | &out->signature)) | ||
1776 | { | ||
1777 | GNUNET_assert (0); | ||
1778 | } | ||
1779 | |||
1780 | client_send_all (&grp->pub_key_hash, GNUNET_MQ_msg_copy (&out->header)); | ||
1781 | cadet_send_children (&grp->pub_key_hash, &out->header); | ||
1782 | client_send_ack (&grp->pub_key_hash); | ||
1783 | GNUNET_free (out); | ||
1784 | |||
1785 | GNUNET_SERVICE_client_continue (client); | ||
1786 | } | ||
1787 | |||
1788 | |||
1789 | static int | ||
1790 | check_client_multicast_request (void *cls, | ||
1791 | const struct GNUNET_MULTICAST_RequestHeader *req) | ||
1792 | { | ||
1793 | return GNUNET_OK; | ||
1794 | } | ||
1795 | |||
1796 | |||
1797 | /** | ||
1798 | * Incoming request from a client. | ||
1799 | */ | ||
1800 | static void | ||
1801 | handle_client_multicast_request (void *cls, | ||
1802 | const struct GNUNET_MULTICAST_RequestHeader *req) | ||
1803 | { | ||
1804 | struct Client *c = cls; | ||
1805 | struct GNUNET_SERVICE_Client *client = c->client; | ||
1806 | struct Group *grp = c->group; | ||
1807 | |||
1808 | if (NULL == grp) | ||
1809 | { | ||
1810 | GNUNET_break (0); | ||
1811 | GNUNET_SERVICE_client_drop (client); | ||
1812 | return; | ||
1813 | } | ||
1814 | GNUNET_assert (GNUNET_NO == grp->is_disconnected); | ||
1815 | GNUNET_assert (GNUNET_NO == grp->is_origin); | ||
1816 | struct Member *mem = grp->member; | ||
1817 | |||
1818 | /* FIXME: yucky, should use separate message structs for P2P and CS! */ | ||
1819 | struct GNUNET_MULTICAST_RequestHeader * | ||
1820 | out = (struct GNUNET_MULTICAST_RequestHeader *) GNUNET_copy_message (&req->header); | ||
1821 | out->member_pub_key = mem->pub_key; | ||
1822 | out->fragment_id = GNUNET_ntohll (++mem->max_fragment_id); | ||
1823 | out->purpose.size = htonl (ntohs (out->header.size) | ||
1824 | - sizeof (out->header) | ||
1825 | - sizeof (out->member_pub_key) | ||
1826 | - sizeof (out->signature)); | ||
1827 | out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST); | ||
1828 | |||
1829 | if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &out->purpose, | ||
1830 | &out->signature)) | ||
1831 | { | ||
1832 | GNUNET_assert (0); | ||
1833 | } | ||
1834 | |||
1835 | uint8_t send_ack = GNUNET_YES; | ||
1836 | if (0 == | ||
1837 | client_send_origin (&grp->pub_key_hash, | ||
1838 | GNUNET_MQ_msg_copy (&out->header))) | ||
1839 | { /* No local origins, send to remote origin */ | ||
1840 | if (NULL != mem->origin_channel) | ||
1841 | { | ||
1842 | cadet_send_channel (mem->origin_channel, &out->header); | ||
1843 | send_ack = GNUNET_NO; | ||
1844 | } | ||
1845 | else | ||
1846 | { | ||
1847 | /* FIXME: not yet connected to origin */ | ||
1848 | GNUNET_SERVICE_client_drop (client); | ||
1849 | GNUNET_free (out); | ||
1850 | return; | ||
1851 | } | ||
1852 | } | ||
1853 | if (GNUNET_YES == send_ack) | ||
1854 | { | ||
1855 | client_send_ack (&grp->pub_key_hash); | ||
1856 | } | ||
1857 | GNUNET_free (out); | ||
1858 | GNUNET_SERVICE_client_continue (client); | ||
1859 | } | ||
1860 | |||
1861 | |||
1862 | /** | ||
1863 | * Incoming replay request from a client. | ||
1864 | */ | ||
1865 | static void | ||
1866 | handle_client_replay_request (void *cls, | ||
1867 | const struct MulticastReplayRequestMessage *rep) | ||
1868 | { | ||
1869 | struct Client *c = cls; | ||
1870 | struct GNUNET_SERVICE_Client *client = c->client; | ||
1871 | struct Group *grp = c->group; | ||
1872 | |||
1873 | if (NULL == grp) | ||
1874 | { | ||
1875 | GNUNET_break (0); | ||
1876 | GNUNET_SERVICE_client_drop (client); | ||
1877 | return; | ||
1878 | } | ||
1879 | GNUNET_assert (GNUNET_NO == grp->is_disconnected); | ||
1880 | GNUNET_assert (GNUNET_NO == grp->is_origin); | ||
1881 | struct Member *mem = grp->member; | ||
1882 | |||
1883 | struct GNUNET_CONTAINER_MultiHashMap * | ||
1884 | grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client, | ||
1885 | &grp->pub_key_hash); | ||
1886 | if (NULL == grp_replay_req) | ||
1887 | { | ||
1888 | grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); | ||
1889 | GNUNET_CONTAINER_multihashmap_put (replay_req_client, | ||
1890 | &grp->pub_key_hash, grp_replay_req, | ||
1891 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1892 | } | ||
1893 | |||
1894 | struct GNUNET_HashCode key_hash; | ||
1895 | replay_key_hash (rep->fragment_id, rep->message_id, rep->fragment_offset, | ||
1896 | rep->flags, &key_hash); | ||
1897 | GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client, | ||
1898 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
1899 | |||
1900 | if (0 == | ||
1901 | client_send_origin (&grp->pub_key_hash, | ||
1902 | GNUNET_MQ_msg_copy (&rep->header))) | ||
1903 | { /* No local origin, replay from remote members / origin. */ | ||
1904 | if (NULL != mem->origin_channel) | ||
1905 | { | ||
1906 | cadet_send_channel (mem->origin_channel, &rep->header); | ||
1907 | } | ||
1908 | else | ||
1909 | { | ||
1910 | /* FIXME: not yet connected to origin */ | ||
1911 | |||
1912 | GNUNET_assert (0); | ||
1913 | GNUNET_SERVICE_client_drop (client); | ||
1914 | return; | ||
1915 | } | ||
1916 | } | ||
1917 | GNUNET_SERVICE_client_continue (client); | ||
1918 | } | ||
1919 | |||
1920 | |||
1921 | static int | ||
1922 | cadet_send_replay_response_cb (void *cls, | ||
1923 | const struct GNUNET_HashCode *key_hash, | ||
1924 | void *value) | ||
1925 | { | ||
1926 | struct Channel *chn = value; | ||
1927 | struct GNUNET_MessageHeader *msg = cls; | ||
1928 | |||
1929 | cadet_send_channel (chn, msg); | ||
1930 | return GNUNET_OK; | ||
1931 | } | ||
1932 | |||
1933 | |||
1934 | static int | ||
1935 | client_send_replay_response_cb (void *cls, | ||
1936 | const struct GNUNET_HashCode *key_hash, | ||
1937 | void *value) | ||
1938 | { | ||
1939 | struct GNUNET_SERVICE_Client *client = value; | ||
1940 | struct GNUNET_MessageHeader *msg = cls; | ||
1941 | |||
1942 | client_send (client, msg); | ||
1943 | return GNUNET_OK; | ||
1944 | } | ||
1945 | |||
1946 | |||
1947 | static int | ||
1948 | check_client_replay_response_end (void *cls, | ||
1949 | const struct MulticastReplayResponseMessage *res) | ||
1950 | { | ||
1951 | return GNUNET_OK; | ||
1952 | } | ||
1953 | |||
1954 | |||
1955 | /** | ||
1956 | * End of replay response from a client. | ||
1957 | */ | ||
1958 | static void | ||
1959 | handle_client_replay_response_end (void *cls, | ||
1960 | const struct MulticastReplayResponseMessage *res) | ||
1961 | { | ||
1962 | struct Client *c = cls; | ||
1963 | struct GNUNET_SERVICE_Client *client = c->client; | ||
1964 | struct Group *grp = c->group; | ||
1965 | |||
1966 | if (NULL == grp) | ||
1967 | { | ||
1968 | GNUNET_break (0); | ||
1969 | GNUNET_SERVICE_client_drop (client); | ||
1970 | return; | ||
1971 | } | ||
1972 | GNUNET_assert (GNUNET_NO == grp->is_disconnected); | ||
1973 | |||
1974 | struct GNUNET_HashCode key_hash; | ||
1975 | replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset, | ||
1976 | res->flags, &key_hash); | ||
1977 | |||
1978 | struct GNUNET_CONTAINER_MultiHashMap * | ||
1979 | grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet, | ||
1980 | &grp->pub_key_hash); | ||
1981 | if (NULL != grp_replay_req_cadet) | ||
1982 | { | ||
1983 | GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_cadet, &key_hash); | ||
1984 | } | ||
1985 | struct GNUNET_CONTAINER_MultiHashMap * | ||
1986 | grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client, | ||
1987 | &grp->pub_key_hash); | ||
1988 | if (NULL != grp_replay_req_client) | ||
1989 | { | ||
1990 | GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_client, &key_hash); | ||
1991 | } | ||
1992 | GNUNET_SERVICE_client_continue (client); | ||
1993 | } | ||
1994 | |||
1995 | |||
1996 | static int | ||
1997 | check_client_replay_response (void *cls, | ||
1998 | const struct MulticastReplayResponseMessage *res) | ||
1999 | { | ||
2000 | const struct GNUNET_MessageHeader *msg; | ||
2001 | if (GNUNET_MULTICAST_REC_OK == res->error_code) | ||
2002 | { | ||
2003 | msg = GNUNET_MQ_extract_nested_mh (res); | ||
2004 | if (NULL == msg) | ||
2005 | { | ||
2006 | return GNUNET_SYSERR; | ||
2007 | } | ||
2008 | } | ||
2009 | return GNUNET_OK; | ||
2010 | } | ||
2011 | |||
2012 | |||
2013 | /** | ||
2014 | * Incoming replay response from a client. | ||
2015 | * | ||
2016 | * Respond with a multicast message on success, or otherwise with an error code. | ||
2017 | */ | ||
2018 | static void | ||
2019 | handle_client_replay_response (void *cls, | ||
2020 | const struct MulticastReplayResponseMessage *res) | ||
2021 | { | ||
2022 | struct Client *c = cls; | ||
2023 | struct GNUNET_SERVICE_Client *client = c->client; | ||
2024 | struct Group *grp = c->group; | ||
2025 | |||
2026 | if (NULL == grp) | ||
2027 | { | ||
2028 | GNUNET_break (0); | ||
2029 | GNUNET_SERVICE_client_drop (client); | ||
2030 | return; | ||
2031 | } | ||
2032 | GNUNET_assert (GNUNET_NO == grp->is_disconnected); | ||
2033 | |||
2034 | const struct GNUNET_MessageHeader *msg = &res->header; | ||
2035 | if (GNUNET_MULTICAST_REC_OK == res->error_code) | ||
2036 | { | ||
2037 | msg = GNUNET_MQ_extract_nested_mh (res); | ||
2038 | } | ||
2039 | |||
2040 | struct GNUNET_HashCode key_hash; | ||
2041 | replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset, | ||
2042 | res->flags, &key_hash); | ||
2043 | |||
2044 | struct GNUNET_CONTAINER_MultiHashMap * | ||
2045 | grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet, | ||
2046 | &grp->pub_key_hash); | ||
2047 | if (NULL != grp_replay_req_cadet) | ||
2048 | { | ||
2049 | GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_cadet, &key_hash, | ||
2050 | cadet_send_replay_response_cb, | ||
2051 | (void *) msg); | ||
2052 | } | ||
2053 | if (GNUNET_MULTICAST_REC_OK == res->error_code) | ||
2054 | { | ||
2055 | struct GNUNET_CONTAINER_MultiHashMap * | ||
2056 | grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client, | ||
2057 | &grp->pub_key_hash); | ||
2058 | if (NULL != grp_replay_req_client) | ||
2059 | { | ||
2060 | GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_client, &key_hash, | ||
2061 | client_send_replay_response_cb, | ||
2062 | (void *) msg); | ||
2063 | } | ||
2064 | } | ||
2065 | else | ||
2066 | { | ||
2067 | handle_client_replay_response_end (c, res); | ||
2068 | return; | ||
2069 | } | ||
2070 | GNUNET_SERVICE_client_continue (client); | ||
2071 | } | ||
2072 | |||
2073 | |||
2074 | /** | ||
2075 | * A new client connected. | ||
2076 | * | ||
2077 | * @param cls NULL | ||
2078 | * @param client client to add | ||
2079 | * @param mq message queue for @a client | ||
2080 | * @return @a client | ||
2081 | */ | ||
2082 | static void * | ||
2083 | client_notify_connect (void *cls, | ||
2084 | struct GNUNET_SERVICE_Client *client, | ||
2085 | struct GNUNET_MQ_Handle *mq) | ||
2086 | { | ||
2087 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client); | ||
2088 | /* FIXME: send connect ACK */ | ||
2089 | |||
2090 | struct Client *c = GNUNET_new (struct Client); | ||
2091 | c->client = client; | ||
2092 | |||
2093 | return c; | ||
2094 | } | ||
2095 | |||
2096 | |||
2097 | /** | ||
2098 | * Called whenever a client is disconnected. | ||
2099 | * Frees our resources associated with that client. | ||
2100 | * | ||
2101 | * @param cls closure | ||
2102 | * @param client identification of the client | ||
2103 | * @param app_ctx must match @a client | ||
2104 | */ | ||
2105 | static void | ||
2106 | client_notify_disconnect (void *cls, | ||
2107 | struct GNUNET_SERVICE_Client *client, | ||
2108 | void *app_ctx) | ||
2109 | { | ||
2110 | struct Client *c = app_ctx; | ||
2111 | struct Group *grp = c->group; | ||
2112 | GNUNET_free (c); | ||
2113 | |||
2114 | if (NULL == grp) | ||
2115 | { | ||
2116 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2117 | "%p User context is NULL in client_disconnect()\n", grp); | ||
2118 | GNUNET_break (0); | ||
2119 | return; | ||
2120 | } | ||
2121 | |||
2122 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2123 | "%p Client (%s) disconnected from group %s\n", | ||
2124 | grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member", | ||
2125 | GNUNET_h2s (&grp->pub_key_hash)); | ||
2126 | |||
2127 | // FIXME (due to protocol change): here we must not remove all clients, | ||
2128 | // only the one we were notified about! | ||
2129 | struct ClientList *cl = grp->clients_head; | ||
2130 | while (NULL != cl) | ||
2131 | { | ||
2132 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2133 | "iterating clients for group %p\n", | ||
2134 | grp); | ||
2135 | if (cl->client == client) | ||
2136 | { | ||
2137 | GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl); | ||
2138 | GNUNET_free (cl); | ||
2139 | break; | ||
2140 | } | ||
2141 | cl = cl->next; | ||
2142 | } | ||
2143 | |||
2144 | while (GNUNET_YES == replay_req_remove_client (grp, client)); | ||
2145 | |||
2146 | if (NULL == grp->clients_head) | ||
2147 | { /* Last client disconnected. */ | ||
2148 | cleanup_group (grp); | ||
2149 | } | ||
2150 | } | ||
2151 | |||
2152 | |||
2153 | /** | ||
2154 | * Service started. | ||
2155 | * | ||
2156 | * @param cls closure | ||
2157 | * @param server the initialized server | ||
2158 | * @param cfg configuration to use | ||
2159 | */ | ||
2160 | static void | ||
2161 | run (void *cls, | ||
2162 | const struct GNUNET_CONFIGURATION_Handle *c, | ||
2163 | struct GNUNET_SERVICE_Handle *svc) | ||
2164 | { | ||
2165 | cfg = c; | ||
2166 | service = svc; | ||
2167 | GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer); | ||
2168 | |||
2169 | stats = GNUNET_STATISTICS_create ("multicast", cfg); | ||
2170 | origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); | ||
2171 | members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); | ||
2172 | group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); | ||
2173 | channels_in = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); | ||
2174 | channels_out = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); | ||
2175 | replay_req_cadet = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); | ||
2176 | replay_req_client = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); | ||
2177 | |||
2178 | cadet = GNUNET_CADET_connect (cfg); | ||
2179 | |||
2180 | GNUNET_assert (NULL != cadet); | ||
2181 | |||
2182 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, | ||
2183 | NULL); | ||
2184 | } | ||
2185 | |||
2186 | |||
2187 | /** | ||
2188 | * Define "main" method using service macro. | ||
2189 | */ | ||
2190 | GNUNET_SERVICE_MAIN | ||
2191 | ("multicast", | ||
2192 | GNUNET_SERVICE_OPTION_NONE, | ||
2193 | &run, | ||
2194 | &client_notify_connect, | ||
2195 | &client_notify_disconnect, | ||
2196 | NULL, | ||
2197 | GNUNET_MQ_hd_fixed_size (client_origin_start, | ||
2198 | GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START, | ||
2199 | struct MulticastOriginStartMessage, | ||
2200 | NULL), | ||
2201 | GNUNET_MQ_hd_var_size (client_member_join, | ||
2202 | GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN, | ||
2203 | struct MulticastMemberJoinMessage, | ||
2204 | NULL), | ||
2205 | GNUNET_MQ_hd_var_size (client_join_decision, | ||
2206 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, | ||
2207 | struct MulticastJoinDecisionMessageHeader, | ||
2208 | NULL), | ||
2209 | GNUNET_MQ_hd_fixed_size (client_part_request, | ||
2210 | GNUNET_MESSAGE_TYPE_MULTICAST_PART_REQUEST, | ||
2211 | struct GNUNET_MessageHeader, | ||
2212 | NULL), | ||
2213 | GNUNET_MQ_hd_var_size (client_multicast_message, | ||
2214 | GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, | ||
2215 | struct GNUNET_MULTICAST_MessageHeader, | ||
2216 | NULL), | ||
2217 | GNUNET_MQ_hd_var_size (client_multicast_request, | ||
2218 | GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, | ||
2219 | struct GNUNET_MULTICAST_RequestHeader, | ||
2220 | NULL), | ||
2221 | GNUNET_MQ_hd_fixed_size (client_replay_request, | ||
2222 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, | ||
2223 | struct MulticastReplayRequestMessage, | ||
2224 | NULL), | ||
2225 | GNUNET_MQ_hd_var_size (client_replay_response, | ||
2226 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, | ||
2227 | struct MulticastReplayResponseMessage, | ||
2228 | NULL), | ||
2229 | GNUNET_MQ_hd_var_size (client_replay_response_end, | ||
2230 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END, | ||
2231 | struct MulticastReplayResponseMessage, | ||
2232 | NULL)); | ||
2233 | |||
2234 | /* end of gnunet-service-multicast.c */ | ||
diff --git a/src/multicast/multicast.conf.in b/src/multicast/multicast.conf.in deleted file mode 100644 index 97a541336..000000000 --- a/src/multicast/multicast.conf.in +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | [multicast] | ||
2 | START_ON_DEMAND = @START_ON_DEMAND@ | ||
3 | BINARY = gnunet-service-multicast | ||
4 | |||
5 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock | ||
6 | UNIX_MATCH_UID = YES | ||
7 | UNIX_MATCH_GID = YES | ||
8 | |||
9 | @UNIXONLY@PORT = 2109 | ||
10 | HOSTNAME = localhost | ||
11 | ACCEPT_FROM = 127.0.0.1; | ||
12 | ACCEPT_FROM6 = ::1; | ||
13 | |||
14 | # DISABLE_SOCKET_FORWARDING = NO | ||
15 | # USERNAME = | ||
16 | # MAXBUF = | ||
17 | # TIMEOUT = | ||
18 | # DISABLEV6 = | ||
19 | # BINDTO = | ||
20 | # REJECT_FROM = | ||
21 | # REJECT_FROM6 = | ||
22 | # PREFIX = | ||
diff --git a/src/multicast/multicast.h b/src/multicast/multicast.h deleted file mode 100644 index 8a3ca14c8..000000000 --- a/src/multicast/multicast.h +++ /dev/null | |||
@@ -1,303 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012, 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file multicast/multicast.h | ||
23 | * @brief multicast IPC messages | ||
24 | * @author Christian Grothoff | ||
25 | * @author Gabor X Toth | ||
26 | */ | ||
27 | #ifndef MULTICAST_H | ||
28 | #define MULTICAST_H | ||
29 | |||
30 | #include "platform.h" | ||
31 | #include "gnunet_multicast_service.h" | ||
32 | |||
33 | GNUNET_NETWORK_STRUCT_BEGIN | ||
34 | |||
35 | |||
36 | /** | ||
37 | * Header of a join request sent to the origin or another member. | ||
38 | */ | ||
39 | struct MulticastJoinRequestMessage | ||
40 | { | ||
41 | /** | ||
42 | * Type: GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST | ||
43 | */ | ||
44 | struct GNUNET_MessageHeader header; | ||
45 | |||
46 | /** | ||
47 | * Always zero. | ||
48 | */ | ||
49 | uint32_t reserved; | ||
50 | |||
51 | /** | ||
52 | * ECC signature of the rest of the fields of the join request. | ||
53 | * | ||
54 | * Signature must match the public key of the joining member. | ||
55 | */ | ||
56 | struct GNUNET_CRYPTO_EcdsaSignature signature; | ||
57 | |||
58 | /** | ||
59 | * Purpose for the signature and size of the signed data. | ||
60 | */ | ||
61 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | ||
62 | |||
63 | /** | ||
64 | * Public key of the target group. | ||
65 | */ | ||
66 | struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key; | ||
67 | |||
68 | /** | ||
69 | * Public key of the joining member. | ||
70 | */ | ||
71 | struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key; | ||
72 | |||
73 | /** | ||
74 | * Peer identity of the joining member. | ||
75 | */ | ||
76 | struct GNUNET_PeerIdentity peer; | ||
77 | |||
78 | /* Followed by struct GNUNET_MessageHeader join_message */ | ||
79 | }; | ||
80 | |||
81 | |||
82 | /** | ||
83 | * Header of a join decision message sent to a peer requesting join. | ||
84 | */ | ||
85 | struct MulticastJoinDecisionMessage | ||
86 | { | ||
87 | /** | ||
88 | * Type: GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION | ||
89 | */ | ||
90 | struct GNUNET_MessageHeader header; | ||
91 | |||
92 | /** | ||
93 | * #GNUNET_YES if the peer was admitted | ||
94 | * #GNUNET_NO if entry was refused, | ||
95 | * #GNUNET_SYSERR if the request could not be answered. | ||
96 | */ | ||
97 | int32_t is_admitted; | ||
98 | |||
99 | /** | ||
100 | * Number of relays given. | ||
101 | */ | ||
102 | uint32_t relay_count; | ||
103 | |||
104 | /* Followed by relay_count peer identities */ | ||
105 | |||
106 | /* Followed by the join response message */ | ||
107 | }; | ||
108 | |||
109 | |||
110 | /** | ||
111 | * Header added to a struct MulticastJoinDecisionMessage | ||
112 | * when sent between the client and service. | ||
113 | */ | ||
114 | struct MulticastJoinDecisionMessageHeader | ||
115 | { | ||
116 | /** | ||
117 | * Type: GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION | ||
118 | */ | ||
119 | struct GNUNET_MessageHeader header; | ||
120 | |||
121 | /** | ||
122 | * C->S: Peer to send the join decision to. | ||
123 | * S->C: Peer we received the join decision from. | ||
124 | */ | ||
125 | struct GNUNET_PeerIdentity peer; | ||
126 | |||
127 | /** | ||
128 | * C->S: Public key of the member requesting join. | ||
129 | * S->C: Unused. | ||
130 | */ | ||
131 | struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key; | ||
132 | |||
133 | /* Followed by struct MulticastJoinDecisionMessage */ | ||
134 | }; | ||
135 | |||
136 | |||
137 | /** | ||
138 | * Message sent from the client to the service to notify the service | ||
139 | * about the result of a membership test. | ||
140 | */ | ||
141 | struct MulticastMembershipTestResultMessage | ||
142 | { | ||
143 | /** | ||
144 | * Type: GNUNET_MESSAGE_TYPE_MULTICAST_MEMBERSHIP_TEST_RESULT | ||
145 | */ | ||
146 | struct GNUNET_MessageHeader header; | ||
147 | |||
148 | /** | ||
149 | * Unique ID that identifies the associated membership test. | ||
150 | */ | ||
151 | uint32_t uid; | ||
152 | |||
153 | /** | ||
154 | * #GNUNET_YES if the peer is a member | ||
155 | * #GNUNET_NO if peer is not a member, | ||
156 | * #GNUNET_SYSERR if the test could not be answered. | ||
157 | */ | ||
158 | int32_t is_admitted; | ||
159 | }; | ||
160 | |||
161 | |||
162 | /** | ||
163 | * Message sent from the client to the service OR the service to the | ||
164 | * client asking for a message fragment to be replayed. | ||
165 | */ | ||
166 | struct MulticastReplayRequestMessage | ||
167 | { | ||
168 | |||
169 | /** | ||
170 | * The message type should be | ||
171 | * #GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST. | ||
172 | */ | ||
173 | struct GNUNET_MessageHeader header; | ||
174 | |||
175 | /** | ||
176 | * S->C: Public key of the member requesting replay. | ||
177 | * C->S: Unused. | ||
178 | */ | ||
179 | struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key; | ||
180 | |||
181 | /** | ||
182 | * ID of the message that is being requested. | ||
183 | */ | ||
184 | uint64_t fragment_id; | ||
185 | |||
186 | /** | ||
187 | * ID of the message that is being requested. | ||
188 | */ | ||
189 | uint64_t message_id; | ||
190 | |||
191 | /** | ||
192 | * Offset of the fragment that is being requested. | ||
193 | */ | ||
194 | uint64_t fragment_offset; | ||
195 | |||
196 | /** | ||
197 | * Additional flags for the request. | ||
198 | */ | ||
199 | uint64_t flags; | ||
200 | |||
201 | /** | ||
202 | * Replay request ID. | ||
203 | */ | ||
204 | uint32_t uid; | ||
205 | }; | ||
206 | |||
207 | |||
208 | /** | ||
209 | * Message sent from the client to the service to give the service | ||
210 | * a replayed message. | ||
211 | */ | ||
212 | struct MulticastReplayResponseMessage | ||
213 | { | ||
214 | |||
215 | /** | ||
216 | * Type: GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE | ||
217 | * or GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END | ||
218 | */ | ||
219 | struct GNUNET_MessageHeader header; | ||
220 | |||
221 | /** | ||
222 | * ID of the message that is being requested. | ||
223 | */ | ||
224 | uint64_t fragment_id; | ||
225 | |||
226 | /** | ||
227 | * ID of the message that is being requested. | ||
228 | */ | ||
229 | uint64_t message_id; | ||
230 | |||
231 | /** | ||
232 | * Offset of the fragment that is being requested. | ||
233 | */ | ||
234 | uint64_t fragment_offset; | ||
235 | |||
236 | /** | ||
237 | * Additional flags for the request. | ||
238 | */ | ||
239 | uint64_t flags; | ||
240 | |||
241 | /** | ||
242 | * An `enum GNUNET_MULTICAST_ReplayErrorCode` identifying issues (in NBO). | ||
243 | */ | ||
244 | int32_t error_code; | ||
245 | |||
246 | /* followed by replayed message */ | ||
247 | }; | ||
248 | |||
249 | |||
250 | /** | ||
251 | * Message sent from the client to the service to notify the service | ||
252 | * about the starting of a multicast group with this peers as its origin. | ||
253 | */ | ||
254 | struct MulticastOriginStartMessage | ||
255 | { | ||
256 | /** | ||
257 | * Type: GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START | ||
258 | */ | ||
259 | struct GNUNET_MessageHeader header; | ||
260 | |||
261 | /** | ||
262 | * Always zero. | ||
263 | */ | ||
264 | uint32_t reserved; | ||
265 | |||
266 | /** | ||
267 | * Private, non-ephemeral key for the multicast group. | ||
268 | */ | ||
269 | struct GNUNET_CRYPTO_EddsaPrivateKey group_key; | ||
270 | |||
271 | /** | ||
272 | * Last fragment ID sent to the group, used to continue counting fragments if | ||
273 | * we resume operating * a group. | ||
274 | */ | ||
275 | uint64_t max_fragment_id; | ||
276 | }; | ||
277 | |||
278 | |||
279 | struct MulticastMemberJoinMessage | ||
280 | { | ||
281 | /** | ||
282 | * Type: GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN | ||
283 | */ | ||
284 | struct GNUNET_MessageHeader header; | ||
285 | |||
286 | uint32_t relay_count GNUNET_PACKED; | ||
287 | |||
288 | struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key; | ||
289 | |||
290 | struct GNUNET_CRYPTO_EcdsaPrivateKey member_key; | ||
291 | |||
292 | struct GNUNET_PeerIdentity origin; | ||
293 | |||
294 | /* Followed by struct GNUNET_PeerIdentity relays[relay_count] */ | ||
295 | |||
296 | /* Followed by struct GNUNET_MessageHeader join_msg */ | ||
297 | }; | ||
298 | |||
299 | |||
300 | GNUNET_NETWORK_STRUCT_END | ||
301 | |||
302 | #endif | ||
303 | /* end of multicast.h */ | ||
diff --git a/src/multicast/multicast_api.c b/src/multicast/multicast_api.c deleted file mode 100644 index e5e830225..000000000 --- a/src/multicast/multicast_api.c +++ /dev/null | |||
@@ -1,1399 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012, 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file multicast/multicast_api.c | ||
23 | * @brief Multicast service; implements multicast groups using CADET connections. | ||
24 | * @author Christian Grothoff | ||
25 | * @author Gabor X Toth | ||
26 | */ | ||
27 | |||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_multicast_service.h" | ||
31 | #include "multicast.h" | ||
32 | |||
33 | #define LOG(kind,...) GNUNET_log_from (kind, "multicast-api",__VA_ARGS__) | ||
34 | |||
35 | |||
36 | /** | ||
37 | * Handle for a request to send a message to all multicast group members | ||
38 | * (from the origin). | ||
39 | */ | ||
40 | struct GNUNET_MULTICAST_OriginTransmitHandle | ||
41 | { | ||
42 | GNUNET_MULTICAST_OriginTransmitNotify notify; | ||
43 | void *notify_cls; | ||
44 | struct GNUNET_MULTICAST_Origin *origin; | ||
45 | |||
46 | uint64_t message_id; | ||
47 | uint64_t group_generation; | ||
48 | uint64_t fragment_offset; | ||
49 | }; | ||
50 | |||
51 | |||
52 | /** | ||
53 | * Handle for a message to be delivered from a member to the origin. | ||
54 | */ | ||
55 | struct GNUNET_MULTICAST_MemberTransmitHandle | ||
56 | { | ||
57 | GNUNET_MULTICAST_MemberTransmitNotify notify; | ||
58 | void *notify_cls; | ||
59 | struct GNUNET_MULTICAST_Member *member; | ||
60 | |||
61 | uint64_t request_id; | ||
62 | uint64_t fragment_offset; | ||
63 | }; | ||
64 | |||
65 | |||
66 | struct GNUNET_MULTICAST_Group | ||
67 | { | ||
68 | /** | ||
69 | * Configuration to use. | ||
70 | */ | ||
71 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
72 | |||
73 | /** | ||
74 | * Client connection to the service. | ||
75 | */ | ||
76 | struct GNUNET_MQ_Handle *mq; | ||
77 | |||
78 | /** | ||
79 | * Message to send on connect. | ||
80 | */ | ||
81 | struct GNUNET_MQ_Envelope *connect_env; | ||
82 | |||
83 | /** | ||
84 | * Time to wait until we try to reconnect on failure. | ||
85 | */ | ||
86 | struct GNUNET_TIME_Relative reconnect_delay; | ||
87 | |||
88 | /** | ||
89 | * Task for reconnecting when the listener fails. | ||
90 | */ | ||
91 | struct GNUNET_SCHEDULER_Task *reconnect_task; | ||
92 | |||
93 | GNUNET_MULTICAST_JoinRequestCallback join_req_cb; | ||
94 | GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb; | ||
95 | GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb; | ||
96 | GNUNET_MULTICAST_MessageCallback message_cb; | ||
97 | void *cb_cls; | ||
98 | |||
99 | /** | ||
100 | * Function called after disconnected from the service. | ||
101 | */ | ||
102 | GNUNET_ContinuationCallback disconnect_cb; | ||
103 | |||
104 | /** | ||
105 | * Closure for @a disconnect_cb. | ||
106 | */ | ||
107 | void *disconnect_cls; | ||
108 | |||
109 | /** | ||
110 | * Are we currently transmitting a message? | ||
111 | */ | ||
112 | uint8_t in_transmit; | ||
113 | |||
114 | /** | ||
115 | * Number of MULTICAST_FRAGMENT_ACK messages we are still waiting for. | ||
116 | */ | ||
117 | uint8_t acks_pending; | ||
118 | |||
119 | /** | ||
120 | * Is this the origin or a member? | ||
121 | */ | ||
122 | uint8_t is_origin; | ||
123 | |||
124 | /** | ||
125 | * Is this channel in the process of disconnecting from the service? | ||
126 | * #GNUNET_YES or #GNUNET_NO | ||
127 | */ | ||
128 | uint8_t is_disconnecting; | ||
129 | }; | ||
130 | |||
131 | |||
132 | /** | ||
133 | * Handle for the origin of a multicast group. | ||
134 | */ | ||
135 | struct GNUNET_MULTICAST_Origin | ||
136 | { | ||
137 | struct GNUNET_MULTICAST_Group grp; | ||
138 | struct GNUNET_MULTICAST_OriginTransmitHandle tmit; | ||
139 | |||
140 | GNUNET_MULTICAST_RequestCallback request_cb; | ||
141 | }; | ||
142 | |||
143 | |||
144 | /** | ||
145 | * Handle for a multicast group member. | ||
146 | */ | ||
147 | struct GNUNET_MULTICAST_Member | ||
148 | { | ||
149 | struct GNUNET_MULTICAST_Group grp; | ||
150 | struct GNUNET_MULTICAST_MemberTransmitHandle tmit; | ||
151 | |||
152 | GNUNET_MULTICAST_JoinDecisionCallback join_dcsn_cb; | ||
153 | |||
154 | /** | ||
155 | * Replay fragment -> struct GNUNET_MULTICAST_MemberReplayHandle * | ||
156 | */ | ||
157 | struct GNUNET_CONTAINER_MultiHashMap *replay_reqs; | ||
158 | |||
159 | uint64_t next_fragment_id; | ||
160 | }; | ||
161 | |||
162 | |||
163 | /** | ||
164 | * Handle that identifies a join request. | ||
165 | * | ||
166 | * Used to match calls to #GNUNET_MULTICAST_JoinRequestCallback to the | ||
167 | * corresponding calls to #GNUNET_MULTICAST_join_decision(). | ||
168 | */ | ||
169 | struct GNUNET_MULTICAST_JoinHandle | ||
170 | { | ||
171 | struct GNUNET_MULTICAST_Group *group; | ||
172 | |||
173 | /** | ||
174 | * Public key of the member requesting join. | ||
175 | */ | ||
176 | struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key; | ||
177 | |||
178 | /** | ||
179 | * Peer identity of the member requesting join. | ||
180 | */ | ||
181 | struct GNUNET_PeerIdentity peer; | ||
182 | }; | ||
183 | |||
184 | |||
185 | /** | ||
186 | * Opaque handle to a replay request from the multicast service. | ||
187 | */ | ||
188 | struct GNUNET_MULTICAST_ReplayHandle | ||
189 | { | ||
190 | struct GNUNET_MULTICAST_Group *grp; | ||
191 | struct MulticastReplayRequestMessage req; | ||
192 | }; | ||
193 | |||
194 | |||
195 | /** | ||
196 | * Handle for a replay request. | ||
197 | */ | ||
198 | struct GNUNET_MULTICAST_MemberReplayHandle | ||
199 | { | ||
200 | }; | ||
201 | |||
202 | |||
203 | static void | ||
204 | origin_to_all (struct GNUNET_MULTICAST_Origin *orig); | ||
205 | |||
206 | static void | ||
207 | member_to_origin (struct GNUNET_MULTICAST_Member *mem); | ||
208 | |||
209 | |||
210 | /** | ||
211 | * Check join request message. | ||
212 | */ | ||
213 | static int | ||
214 | check_group_join_request (void *cls, | ||
215 | const struct MulticastJoinRequestMessage *jreq) | ||
216 | { | ||
217 | uint16_t size = ntohs (jreq->header.size); | ||
218 | |||
219 | if (sizeof (*jreq) == size) | ||
220 | return GNUNET_OK; | ||
221 | |||
222 | if (sizeof (*jreq) + sizeof (struct GNUNET_MessageHeader) <= size) | ||
223 | return GNUNET_OK; | ||
224 | |||
225 | return GNUNET_SYSERR; | ||
226 | } | ||
227 | |||
228 | |||
229 | /** | ||
230 | * Receive join request from service. | ||
231 | */ | ||
232 | static void | ||
233 | handle_group_join_request (void *cls, | ||
234 | const struct MulticastJoinRequestMessage *jreq) | ||
235 | { | ||
236 | struct GNUNET_MULTICAST_Group *grp = cls; | ||
237 | struct GNUNET_MULTICAST_JoinHandle *jh; | ||
238 | const struct GNUNET_MessageHeader *jmsg = NULL; | ||
239 | |||
240 | if (NULL == grp) | ||
241 | { | ||
242 | GNUNET_break (0); | ||
243 | return; | ||
244 | } | ||
245 | if (NULL == grp->join_req_cb) | ||
246 | return; | ||
247 | |||
248 | if (sizeof (*jreq) + sizeof (*jmsg) <= ntohs (jreq->header.size)) | ||
249 | jmsg = (const struct GNUNET_MessageHeader *) &jreq[1]; | ||
250 | |||
251 | jh = GNUNET_malloc (sizeof (*jh)); | ||
252 | jh->group = grp; | ||
253 | jh->member_pub_key = jreq->member_pub_key; | ||
254 | jh->peer = jreq->peer; | ||
255 | grp->join_req_cb (grp->cb_cls, &jreq->member_pub_key, jmsg, jh); | ||
256 | |||
257 | grp->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS; | ||
258 | } | ||
259 | |||
260 | |||
261 | /** | ||
262 | * Check multicast message. | ||
263 | */ | ||
264 | static int | ||
265 | check_group_message (void *cls, | ||
266 | const struct GNUNET_MULTICAST_MessageHeader *mmsg) | ||
267 | { | ||
268 | return GNUNET_OK; | ||
269 | } | ||
270 | |||
271 | |||
272 | /** | ||
273 | * Receive multicast message from service. | ||
274 | */ | ||
275 | static void | ||
276 | handle_group_message (void *cls, | ||
277 | const struct GNUNET_MULTICAST_MessageHeader *mmsg) | ||
278 | { | ||
279 | struct GNUNET_MULTICAST_Group *grp = cls; | ||
280 | |||
281 | if (GNUNET_YES == grp->is_disconnecting) | ||
282 | return; | ||
283 | |||
284 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
285 | "Calling message callback with a message of size %u.\n", | ||
286 | ntohs (mmsg->header.size)); | ||
287 | |||
288 | if (NULL != grp->message_cb) | ||
289 | grp->message_cb (grp->cb_cls, mmsg); | ||
290 | |||
291 | grp->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS; | ||
292 | } | ||
293 | |||
294 | |||
295 | /** | ||
296 | * Receive message/request fragment acknowledgement from service. | ||
297 | */ | ||
298 | static void | ||
299 | handle_group_fragment_ack (void *cls, | ||
300 | const struct GNUNET_MessageHeader *msg) | ||
301 | { | ||
302 | struct GNUNET_MULTICAST_Group *grp = cls; | ||
303 | |||
304 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
305 | "%p Got fragment ACK. in_transmit=%u, acks_pending=%u\n", | ||
306 | grp, grp->in_transmit, grp->acks_pending); | ||
307 | |||
308 | if (0 == grp->acks_pending) | ||
309 | { | ||
310 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
311 | "%p Ignoring extraneous fragment ACK.\n", grp); | ||
312 | return; | ||
313 | } | ||
314 | grp->acks_pending--; | ||
315 | |||
316 | if (GNUNET_YES != grp->in_transmit) | ||
317 | return; | ||
318 | |||
319 | if (GNUNET_YES == grp->is_origin) | ||
320 | origin_to_all ((struct GNUNET_MULTICAST_Origin *) grp); | ||
321 | else | ||
322 | member_to_origin ((struct GNUNET_MULTICAST_Member *) grp); | ||
323 | |||
324 | grp->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS; | ||
325 | } | ||
326 | |||
327 | |||
328 | /** | ||
329 | * Check unicast request. | ||
330 | */ | ||
331 | static int | ||
332 | check_origin_request (void *cls, | ||
333 | const struct GNUNET_MULTICAST_RequestHeader *req) | ||
334 | { | ||
335 | return GNUNET_OK; | ||
336 | } | ||
337 | |||
338 | |||
339 | /** | ||
340 | * Origin receives unicast request from a member. | ||
341 | */ | ||
342 | static void | ||
343 | handle_origin_request (void *cls, | ||
344 | const struct GNUNET_MULTICAST_RequestHeader *req) | ||
345 | { | ||
346 | struct GNUNET_MULTICAST_Group *grp; | ||
347 | struct GNUNET_MULTICAST_Origin *orig = cls; | ||
348 | grp = &orig->grp; | ||
349 | |||
350 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
351 | "Calling request callback with a request of size %u.\n", | ||
352 | ntohs (req->header.size)); | ||
353 | |||
354 | if (NULL != orig->request_cb) | ||
355 | orig->request_cb (grp->cb_cls, req); | ||
356 | |||
357 | grp->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS; | ||
358 | } | ||
359 | |||
360 | |||
361 | /** | ||
362 | * Receive multicast replay request from service. | ||
363 | */ | ||
364 | static void | ||
365 | handle_group_replay_request (void *cls, | ||
366 | const struct MulticastReplayRequestMessage *rep) | ||
367 | |||
368 | { | ||
369 | struct GNUNET_MULTICAST_Group *grp = cls; | ||
370 | |||
371 | if (GNUNET_YES == grp->is_disconnecting) | ||
372 | return; | ||
373 | |||
374 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got replay request.\n"); | ||
375 | |||
376 | if (0 != rep->fragment_id) | ||
377 | { | ||
378 | if (NULL != grp->replay_frag_cb) | ||
379 | { | ||
380 | struct GNUNET_MULTICAST_ReplayHandle * rh = GNUNET_malloc (sizeof (*rh)); | ||
381 | rh->grp = grp; | ||
382 | rh->req = *rep; | ||
383 | grp->replay_frag_cb (grp->cb_cls, &rep->member_pub_key, | ||
384 | GNUNET_ntohll (rep->fragment_id), | ||
385 | GNUNET_ntohll (rep->flags), rh); | ||
386 | } | ||
387 | } | ||
388 | else if (0 != rep->message_id) | ||
389 | { | ||
390 | if (NULL != grp->replay_msg_cb) | ||
391 | { | ||
392 | struct GNUNET_MULTICAST_ReplayHandle * rh = GNUNET_malloc (sizeof (*rh)); | ||
393 | rh->grp = grp; | ||
394 | rh->req = *rep; | ||
395 | grp->replay_msg_cb (grp->cb_cls, &rep->member_pub_key, | ||
396 | GNUNET_ntohll (rep->message_id), | ||
397 | GNUNET_ntohll (rep->fragment_offset), | ||
398 | GNUNET_ntohll (rep->flags), rh); | ||
399 | } | ||
400 | } | ||
401 | |||
402 | grp->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS; | ||
403 | } | ||
404 | |||
405 | |||
406 | /** | ||
407 | * Check replay response. | ||
408 | */ | ||
409 | static int | ||
410 | check_member_replay_response (void *cls, | ||
411 | const struct MulticastReplayResponseMessage *res) | ||
412 | { | ||
413 | uint16_t size = ntohs (res->header.size); | ||
414 | |||
415 | if (sizeof (*res) == size) | ||
416 | return GNUNET_OK; | ||
417 | |||
418 | if (sizeof (*res) + sizeof (struct GNUNET_MULTICAST_MessageHeader) <= size) | ||
419 | return GNUNET_OK; | ||
420 | |||
421 | return GNUNET_SYSERR; | ||
422 | } | ||
423 | |||
424 | |||
425 | /** | ||
426 | * Receive replay response from service. | ||
427 | */ | ||
428 | static void | ||
429 | handle_member_replay_response (void *cls, | ||
430 | const struct MulticastReplayResponseMessage *res) | ||
431 | { | ||
432 | struct GNUNET_MULTICAST_Group *grp; | ||
433 | struct GNUNET_MULTICAST_Member *mem = cls; | ||
434 | grp = &mem->grp; | ||
435 | |||
436 | if (GNUNET_YES == grp->is_disconnecting) | ||
437 | return; | ||
438 | |||
439 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got replay response.\n"); | ||
440 | |||
441 | // FIXME: return result | ||
442 | } | ||
443 | |||
444 | |||
445 | /** | ||
446 | * Check join decision. | ||
447 | */ | ||
448 | static int | ||
449 | check_member_join_decision (void *cls, | ||
450 | const struct MulticastJoinDecisionMessageHeader *hdcsn) | ||
451 | { | ||
452 | return GNUNET_OK; // checked in handle below | ||
453 | } | ||
454 | |||
455 | |||
456 | /** | ||
457 | * Member receives join decision. | ||
458 | */ | ||
459 | static void | ||
460 | handle_member_join_decision (void *cls, | ||
461 | const struct MulticastJoinDecisionMessageHeader *hdcsn) | ||
462 | { | ||
463 | struct GNUNET_MULTICAST_Group *grp; | ||
464 | struct GNUNET_MULTICAST_Member *mem = cls; | ||
465 | grp = &mem->grp; | ||
466 | |||
467 | const struct MulticastJoinDecisionMessage * | ||
468 | dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1]; | ||
469 | |||
470 | uint16_t dcsn_size = ntohs (dcsn->header.size); | ||
471 | int is_admitted = ntohl (dcsn->is_admitted); | ||
472 | |||
473 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
474 | "%p Member got join decision from multicast: %d\n", | ||
475 | mem, is_admitted); | ||
476 | |||
477 | const struct GNUNET_MessageHeader *join_resp = NULL; | ||
478 | uint16_t join_resp_size = 0; | ||
479 | |||
480 | uint16_t relay_count = ntohl (dcsn->relay_count); | ||
481 | const struct GNUNET_PeerIdentity *relays = NULL; | ||
482 | uint16_t relay_size = relay_count * sizeof (*relays); | ||
483 | if (0 < relay_count) | ||
484 | { | ||
485 | if (dcsn_size < sizeof (*dcsn) + relay_size) | ||
486 | { | ||
487 | GNUNET_break_op (0); | ||
488 | is_admitted = GNUNET_SYSERR; | ||
489 | } | ||
490 | else | ||
491 | { | ||
492 | relays = (struct GNUNET_PeerIdentity *) &dcsn[1]; | ||
493 | } | ||
494 | } | ||
495 | |||
496 | if (sizeof (*dcsn) + relay_size + sizeof (*join_resp) <= dcsn_size) | ||
497 | { | ||
498 | join_resp = (const struct GNUNET_MessageHeader *) ((char *) &dcsn[1] + relay_size); | ||
499 | join_resp_size = ntohs (join_resp->size); | ||
500 | } | ||
501 | if (dcsn_size < sizeof (*dcsn) + relay_size + join_resp_size) | ||
502 | { | ||
503 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
504 | "Received invalid join decision message from multicast: %u < %u + %u + %u\n", | ||
505 | dcsn_size , sizeof (*dcsn), relay_size, join_resp_size); | ||
506 | GNUNET_break_op (0); | ||
507 | is_admitted = GNUNET_SYSERR; | ||
508 | } | ||
509 | |||
510 | if (NULL != mem->join_dcsn_cb) | ||
511 | mem->join_dcsn_cb (grp->cb_cls, is_admitted, &hdcsn->peer, | ||
512 | relay_count, relays, join_resp); | ||
513 | |||
514 | // FIXME: | ||
515 | //if (GNUNET_YES != is_admitted) | ||
516 | // GNUNET_MULTICAST_member_part (mem); | ||
517 | |||
518 | grp->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS; | ||
519 | } | ||
520 | |||
521 | |||
522 | static void | ||
523 | group_cleanup (struct GNUNET_MULTICAST_Group *grp) | ||
524 | { | ||
525 | if (NULL != grp->connect_env) | ||
526 | { | ||
527 | GNUNET_MQ_discard (grp->connect_env); | ||
528 | grp->connect_env = NULL; | ||
529 | } | ||
530 | if (NULL != grp->mq) | ||
531 | { | ||
532 | GNUNET_MQ_destroy (grp->mq); | ||
533 | grp->mq = NULL; | ||
534 | } | ||
535 | if (NULL != grp->disconnect_cb) | ||
536 | { | ||
537 | grp->disconnect_cb (grp->disconnect_cls); | ||
538 | grp->disconnect_cb = NULL; | ||
539 | } | ||
540 | GNUNET_free (grp); | ||
541 | } | ||
542 | |||
543 | |||
544 | static void | ||
545 | handle_group_part_ack (void *cls, | ||
546 | const struct GNUNET_MessageHeader *msg) | ||
547 | { | ||
548 | struct GNUNET_MULTICAST_Group *grp = cls; | ||
549 | |||
550 | group_cleanup (grp); | ||
551 | } | ||
552 | |||
553 | |||
554 | /** | ||
555 | * Function to call with the decision made for a join request. | ||
556 | * | ||
557 | * Must be called once and only once in response to an invocation of the | ||
558 | * #GNUNET_MULTICAST_JoinRequestCallback. | ||
559 | * | ||
560 | * @param join | ||
561 | * Join request handle. | ||
562 | * @param is_admitted | ||
563 | * #GNUNET_YES if the join is approved, | ||
564 | * #GNUNET_NO if it is disapproved, | ||
565 | * #GNUNET_SYSERR if we cannot answer the request. | ||
566 | * @param relay_count | ||
567 | * Number of relays given. | ||
568 | * @param relays | ||
569 | * Array of suggested peers that might be useful relays to use | ||
570 | * when joining the multicast group (essentially a list of peers that | ||
571 | * are already part of the multicast group and might thus be willing | ||
572 | * to help with routing). If empty, only this local peer (which must | ||
573 | * be the multicast origin) is a good candidate for building the | ||
574 | * multicast tree. Note that it is unnecessary to specify our own | ||
575 | * peer identity in this array. | ||
576 | * @param join_resp | ||
577 | * Message to send in response to the joining peer; | ||
578 | * can also be used to redirect the peer to a different group at the | ||
579 | * application layer; this response is to be transmitted to the | ||
580 | * peer that issued the request even if admission is denied. | ||
581 | */ | ||
582 | struct GNUNET_MULTICAST_ReplayHandle * | ||
583 | GNUNET_MULTICAST_join_decision (struct GNUNET_MULTICAST_JoinHandle *join, | ||
584 | int is_admitted, | ||
585 | uint16_t relay_count, | ||
586 | const struct GNUNET_PeerIdentity *relays, | ||
587 | const struct GNUNET_MessageHeader *join_resp) | ||
588 | { | ||
589 | struct GNUNET_MULTICAST_Group *grp = join->group; | ||
590 | uint16_t join_resp_size = (NULL != join_resp) ? ntohs (join_resp->size) : 0; | ||
591 | uint16_t relay_size = relay_count * sizeof (*relays); | ||
592 | |||
593 | struct MulticastJoinDecisionMessageHeader *hdcsn; | ||
594 | struct MulticastJoinDecisionMessage *dcsn; | ||
595 | struct GNUNET_MQ_Envelope * | ||
596 | env = GNUNET_MQ_msg_extra (hdcsn, sizeof (*dcsn) + relay_size + join_resp_size, | ||
597 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION); | ||
598 | hdcsn->member_pub_key = join->member_pub_key; | ||
599 | hdcsn->peer = join->peer; | ||
600 | |||
601 | dcsn = (struct MulticastJoinDecisionMessage *) &hdcsn[1]; | ||
602 | dcsn->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION); | ||
603 | dcsn->header.size = htons (sizeof (*dcsn) + relay_size + join_resp_size); | ||
604 | dcsn->is_admitted = htonl (is_admitted); | ||
605 | dcsn->relay_count = htonl (relay_count); | ||
606 | if (0 < relay_size) | ||
607 | GNUNET_memcpy (&dcsn[1], relays, relay_size); | ||
608 | if (0 < join_resp_size) | ||
609 | GNUNET_memcpy (((char *) &dcsn[1]) + relay_size, join_resp, join_resp_size); | ||
610 | |||
611 | GNUNET_MQ_send (grp->mq, env); | ||
612 | GNUNET_free (join); | ||
613 | return NULL; | ||
614 | } | ||
615 | |||
616 | |||
617 | /** | ||
618 | * Replay a message fragment for the multicast group. | ||
619 | * | ||
620 | * @param rh | ||
621 | * Replay handle identifying which replay operation was requested. | ||
622 | * @param msg | ||
623 | * Replayed message fragment, NULL if not found / an error occurred. | ||
624 | * @param ec | ||
625 | * Error code. See enum GNUNET_MULTICAST_ReplayErrorCode | ||
626 | * If not #GNUNET_MULTICAST_REC_OK, the replay handle is invalidated. | ||
627 | */ | ||
628 | void | ||
629 | GNUNET_MULTICAST_replay_response (struct GNUNET_MULTICAST_ReplayHandle *rh, | ||
630 | const struct GNUNET_MessageHeader *msg, | ||
631 | enum GNUNET_MULTICAST_ReplayErrorCode ec) | ||
632 | { | ||
633 | uint8_t msg_size = (NULL != msg) ? ntohs (msg->size) : 0; | ||
634 | struct MulticastReplayResponseMessage *res; | ||
635 | struct GNUNET_MQ_Envelope * | ||
636 | env = GNUNET_MQ_msg_extra (res, msg_size, | ||
637 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE); | ||
638 | res->fragment_id = rh->req.fragment_id; | ||
639 | res->message_id = rh->req.message_id; | ||
640 | res->fragment_offset = rh->req.fragment_offset; | ||
641 | res->flags = rh->req.flags; | ||
642 | res->error_code = htonl (ec); | ||
643 | |||
644 | if (GNUNET_MULTICAST_REC_OK == ec) | ||
645 | { | ||
646 | GNUNET_assert (NULL != msg); | ||
647 | GNUNET_memcpy (&res[1], msg, msg_size); | ||
648 | } | ||
649 | |||
650 | GNUNET_MQ_send (rh->grp->mq, env); | ||
651 | |||
652 | if (GNUNET_MULTICAST_REC_OK != ec) | ||
653 | GNUNET_free (rh); | ||
654 | } | ||
655 | |||
656 | |||
657 | /** | ||
658 | * Indicate the end of the replay session. | ||
659 | * | ||
660 | * Invalidates the replay handle. | ||
661 | * | ||
662 | * @param rh | ||
663 | * Replay session to end. | ||
664 | */ | ||
665 | void | ||
666 | GNUNET_MULTICAST_replay_response_end (struct GNUNET_MULTICAST_ReplayHandle *rh) | ||
667 | { | ||
668 | struct MulticastReplayResponseMessage *end; | ||
669 | struct GNUNET_MQ_Envelope * | ||
670 | env = GNUNET_MQ_msg (end, GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END); | ||
671 | |||
672 | end->fragment_id = rh->req.fragment_id; | ||
673 | end->message_id = rh->req.message_id; | ||
674 | end->fragment_offset = rh->req.fragment_offset; | ||
675 | end->flags = rh->req.flags; | ||
676 | |||
677 | GNUNET_MQ_send (rh->grp->mq, env); | ||
678 | GNUNET_free (rh); | ||
679 | } | ||
680 | |||
681 | |||
682 | /** | ||
683 | * Replay a message for the multicast group. | ||
684 | * | ||
685 | * @param rh | ||
686 | * Replay handle identifying which replay operation was requested. | ||
687 | * @param notify | ||
688 | * Function to call to get the message. | ||
689 | * @param notify_cls | ||
690 | * Closure for @a notify. | ||
691 | */ | ||
692 | void | ||
693 | GNUNET_MULTICAST_replay_response2 (struct GNUNET_MULTICAST_ReplayHandle *rh, | ||
694 | GNUNET_MULTICAST_ReplayTransmitNotify notify, | ||
695 | void *notify_cls) | ||
696 | { | ||
697 | } | ||
698 | |||
699 | |||
700 | static void | ||
701 | origin_connect (struct GNUNET_MULTICAST_Origin *orig); | ||
702 | |||
703 | |||
704 | static void | ||
705 | origin_reconnect (void *cls) | ||
706 | { | ||
707 | origin_connect (cls); | ||
708 | } | ||
709 | |||
710 | |||
711 | /** | ||
712 | * Origin client disconnected from service. | ||
713 | * | ||
714 | * Reconnect after backoff period. | ||
715 | */ | ||
716 | static void | ||
717 | origin_disconnected (void *cls, enum GNUNET_MQ_Error error) | ||
718 | { | ||
719 | struct GNUNET_MULTICAST_Origin *orig = cls; | ||
720 | struct GNUNET_MULTICAST_Group *grp = &orig->grp; | ||
721 | |||
722 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
723 | "Origin client disconnected (%d), re-connecting\n", | ||
724 | (int) error); | ||
725 | if (NULL != grp->mq) | ||
726 | { | ||
727 | GNUNET_MQ_destroy (grp->mq); | ||
728 | grp->mq = NULL; | ||
729 | } | ||
730 | |||
731 | grp->reconnect_task = GNUNET_SCHEDULER_add_delayed (grp->reconnect_delay, | ||
732 | origin_reconnect, | ||
733 | orig); | ||
734 | grp->reconnect_delay = GNUNET_TIME_STD_BACKOFF (grp->reconnect_delay); | ||
735 | } | ||
736 | |||
737 | |||
738 | /** | ||
739 | * Connect to service as origin. | ||
740 | */ | ||
741 | static void | ||
742 | origin_connect (struct GNUNET_MULTICAST_Origin *orig) | ||
743 | { | ||
744 | struct GNUNET_MULTICAST_Group *grp = &orig->grp; | ||
745 | |||
746 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
747 | GNUNET_MQ_hd_var_size (group_message, | ||
748 | GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, | ||
749 | struct GNUNET_MULTICAST_MessageHeader, | ||
750 | grp), | ||
751 | GNUNET_MQ_hd_var_size (origin_request, | ||
752 | GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, | ||
753 | struct GNUNET_MULTICAST_RequestHeader, | ||
754 | orig), | ||
755 | GNUNET_MQ_hd_fixed_size (group_fragment_ack, | ||
756 | GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK, | ||
757 | struct GNUNET_MessageHeader, | ||
758 | grp), | ||
759 | GNUNET_MQ_hd_var_size (group_join_request, | ||
760 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, | ||
761 | struct MulticastJoinRequestMessage, | ||
762 | grp), | ||
763 | GNUNET_MQ_hd_fixed_size (group_part_ack, | ||
764 | GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK, | ||
765 | struct GNUNET_MessageHeader, | ||
766 | grp), | ||
767 | GNUNET_MQ_hd_fixed_size (group_replay_request, | ||
768 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, | ||
769 | struct MulticastReplayRequestMessage, | ||
770 | grp), | ||
771 | GNUNET_MQ_handler_end () | ||
772 | }; | ||
773 | |||
774 | grp->mq = GNUNET_CLIENT_connect (grp->cfg, "multicast", | ||
775 | handlers, origin_disconnected, orig); | ||
776 | GNUNET_assert (NULL != grp->mq); | ||
777 | GNUNET_MQ_send_copy (grp->mq, grp->connect_env); | ||
778 | } | ||
779 | |||
780 | |||
781 | /** | ||
782 | * Start a multicast group. | ||
783 | * | ||
784 | * Will advertise the origin in the P2P overlay network under the respective | ||
785 | * public key so that other peer can find this peer to join it. Peers that | ||
786 | * issue GNUNET_MULTICAST_member_join() can then transmit a join request to | ||
787 | * either an existing group member or to the origin. If the joining is | ||
788 | * approved, the member is cleared for @e replay and will begin to receive | ||
789 | * messages transmitted to the group. If joining is disapproved, the failed | ||
790 | * candidate will be given a response. Members in the group can send messages | ||
791 | * to the origin (one at a time). | ||
792 | * | ||
793 | * @param cfg | ||
794 | * Configuration to use. | ||
795 | * @param priv_key | ||
796 | * ECC key that will be used to sign messages for this | ||
797 | * multicast session; public key is used to identify the multicast group; | ||
798 | * @param max_fragment_id | ||
799 | * Maximum fragment ID already sent to the group. | ||
800 | * 0 for a new group. | ||
801 | * @param join_request_cb | ||
802 | * Function called to approve / disapprove joining of a peer. | ||
803 | * @param replay_frag_cb | ||
804 | * Function that can be called to replay a message fragment. | ||
805 | * @param replay_msg_cb | ||
806 | * Function that can be called to replay a message. | ||
807 | * @param request_cb | ||
808 | * Function called with message fragments from group members. | ||
809 | * @param message_cb | ||
810 | * Function called with the message fragments sent to the | ||
811 | * network by GNUNET_MULTICAST_origin_to_all(). These message fragments | ||
812 | * should be stored for answering replay requests later. | ||
813 | * @param cls | ||
814 | * Closure for the various callbacks that follow. | ||
815 | * | ||
816 | * @return Handle for the origin, NULL on error. | ||
817 | */ | ||
818 | struct GNUNET_MULTICAST_Origin * | ||
819 | GNUNET_MULTICAST_origin_start (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
820 | const struct GNUNET_CRYPTO_EddsaPrivateKey *priv_key, | ||
821 | uint64_t max_fragment_id, | ||
822 | GNUNET_MULTICAST_JoinRequestCallback join_request_cb, | ||
823 | GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb, | ||
824 | GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb, | ||
825 | GNUNET_MULTICAST_RequestCallback request_cb, | ||
826 | GNUNET_MULTICAST_MessageCallback message_cb, | ||
827 | void *cls) | ||
828 | { | ||
829 | struct GNUNET_MULTICAST_Origin *orig = GNUNET_malloc (sizeof (*orig)); | ||
830 | struct GNUNET_MULTICAST_Group *grp = &orig->grp; | ||
831 | |||
832 | struct MulticastOriginStartMessage *start; | ||
833 | grp->connect_env = GNUNET_MQ_msg (start, | ||
834 | GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START); | ||
835 | start->max_fragment_id = max_fragment_id; | ||
836 | start->group_key = *priv_key; | ||
837 | |||
838 | grp->cfg = cfg; | ||
839 | grp->is_origin = GNUNET_YES; | ||
840 | grp->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS; | ||
841 | |||
842 | grp->cb_cls = cls; | ||
843 | grp->join_req_cb = join_request_cb; | ||
844 | grp->replay_frag_cb = replay_frag_cb; | ||
845 | grp->replay_msg_cb = replay_msg_cb; | ||
846 | grp->message_cb = message_cb; | ||
847 | |||
848 | orig->request_cb = request_cb; | ||
849 | |||
850 | origin_connect (orig); | ||
851 | return orig; | ||
852 | } | ||
853 | |||
854 | |||
855 | /** | ||
856 | * Stop a multicast group. | ||
857 | * | ||
858 | * @param origin | ||
859 | * Multicast group to stop. | ||
860 | */ | ||
861 | void | ||
862 | GNUNET_MULTICAST_origin_stop (struct GNUNET_MULTICAST_Origin *orig, | ||
863 | GNUNET_ContinuationCallback stop_cb, | ||
864 | void *stop_cls) | ||
865 | { | ||
866 | struct GNUNET_MULTICAST_Group *grp = &orig->grp; | ||
867 | struct GNUNET_MQ_Envelope *env; | ||
868 | |||
869 | grp->is_disconnecting = GNUNET_YES; | ||
870 | grp->disconnect_cb = stop_cb; | ||
871 | grp->disconnect_cls = stop_cls; | ||
872 | env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_PART_REQUEST); | ||
873 | GNUNET_MQ_send (grp->mq, env); | ||
874 | } | ||
875 | |||
876 | |||
877 | static void | ||
878 | origin_to_all (struct GNUNET_MULTICAST_Origin *orig) | ||
879 | { | ||
880 | LOG (GNUNET_ERROR_TYPE_DEBUG, "%p origin_to_all()\n", orig); | ||
881 | struct GNUNET_MULTICAST_Group *grp = &orig->grp; | ||
882 | struct GNUNET_MULTICAST_OriginTransmitHandle *tmit = &orig->tmit; | ||
883 | GNUNET_assert (GNUNET_YES == grp->in_transmit); | ||
884 | |||
885 | size_t buf_size = GNUNET_MULTICAST_FRAGMENT_MAX_SIZE; | ||
886 | struct GNUNET_MULTICAST_MessageHeader *msg; | ||
887 | struct GNUNET_MQ_Envelope * | ||
888 | env = GNUNET_MQ_msg_extra (msg, buf_size - sizeof(*msg), | ||
889 | GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE); | ||
890 | |||
891 | int ret = tmit->notify (tmit->notify_cls, &buf_size, &msg[1]); | ||
892 | |||
893 | if (! (GNUNET_YES == ret || GNUNET_NO == ret) | ||
894 | || GNUNET_MULTICAST_FRAGMENT_MAX_SIZE < buf_size) | ||
895 | { | ||
896 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
897 | "%p OriginTransmitNotify() returned error or invalid message size.\n", | ||
898 | orig); | ||
899 | /* FIXME: handle error */ | ||
900 | GNUNET_MQ_discard (env); | ||
901 | return; | ||
902 | } | ||
903 | |||
904 | if (GNUNET_NO == ret && 0 == buf_size) | ||
905 | { | ||
906 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
907 | "%p OriginTransmitNotify() - transmission paused.\n", orig); | ||
908 | GNUNET_MQ_discard (env); | ||
909 | return; /* Transmission paused. */ | ||
910 | } | ||
911 | |||
912 | msg->header.size = htons (sizeof (*msg) + buf_size); | ||
913 | msg->message_id = GNUNET_htonll (tmit->message_id); | ||
914 | msg->group_generation = tmit->group_generation; | ||
915 | msg->fragment_offset = GNUNET_htonll (tmit->fragment_offset); | ||
916 | tmit->fragment_offset += sizeof (*msg) + buf_size; | ||
917 | |||
918 | grp->acks_pending++; | ||
919 | GNUNET_MQ_send (grp->mq, env); | ||
920 | |||
921 | if (GNUNET_YES == ret) | ||
922 | grp->in_transmit = GNUNET_NO; | ||
923 | } | ||
924 | |||
925 | |||
926 | /** | ||
927 | * Send a message to the multicast group. | ||
928 | * | ||
929 | * @param orig | ||
930 | * Handle to the multicast group. | ||
931 | * @param message_id | ||
932 | * Application layer ID for the message. Opaque to multicast. | ||
933 | * @param group_generation | ||
934 | * Group generation of the message. | ||
935 | * Documented in struct GNUNET_MULTICAST_MessageHeader. | ||
936 | * @param notify | ||
937 | * Function to call to get the message. | ||
938 | * @param notify_cls | ||
939 | * Closure for @a notify. | ||
940 | * | ||
941 | * @return Message handle on success, | ||
942 | * NULL on error (i.e. another request is already pending). | ||
943 | */ | ||
944 | struct GNUNET_MULTICAST_OriginTransmitHandle * | ||
945 | GNUNET_MULTICAST_origin_to_all (struct GNUNET_MULTICAST_Origin *orig, | ||
946 | uint64_t message_id, | ||
947 | uint64_t group_generation, | ||
948 | GNUNET_MULTICAST_OriginTransmitNotify notify, | ||
949 | void *notify_cls) | ||
950 | { | ||
951 | struct GNUNET_MULTICAST_Group *grp = &orig->grp; | ||
952 | if (GNUNET_YES == grp->in_transmit) | ||
953 | return NULL; | ||
954 | grp->in_transmit = GNUNET_YES; | ||
955 | |||
956 | struct GNUNET_MULTICAST_OriginTransmitHandle *tmit = &orig->tmit; | ||
957 | tmit->origin = orig; | ||
958 | tmit->message_id = message_id; | ||
959 | tmit->fragment_offset = 0; | ||
960 | tmit->group_generation = group_generation; | ||
961 | tmit->notify = notify; | ||
962 | tmit->notify_cls = notify_cls; | ||
963 | |||
964 | origin_to_all (orig); | ||
965 | return tmit; | ||
966 | } | ||
967 | |||
968 | |||
969 | /** | ||
970 | * Resume message transmission to multicast group. | ||
971 | * | ||
972 | * @param th | ||
973 | * Transmission to cancel. | ||
974 | */ | ||
975 | void | ||
976 | GNUNET_MULTICAST_origin_to_all_resume (struct GNUNET_MULTICAST_OriginTransmitHandle *th) | ||
977 | { | ||
978 | struct GNUNET_MULTICAST_Group *grp = &th->origin->grp; | ||
979 | if (0 != grp->acks_pending || GNUNET_YES != grp->in_transmit) | ||
980 | return; | ||
981 | origin_to_all (th->origin); | ||
982 | } | ||
983 | |||
984 | |||
985 | /** | ||
986 | * Cancel request for message transmission to multicast group. | ||
987 | * | ||
988 | * @param th | ||
989 | * Transmission to cancel. | ||
990 | */ | ||
991 | void | ||
992 | GNUNET_MULTICAST_origin_to_all_cancel (struct GNUNET_MULTICAST_OriginTransmitHandle *th) | ||
993 | { | ||
994 | th->origin->grp.in_transmit = GNUNET_NO; | ||
995 | } | ||
996 | |||
997 | |||
998 | static void | ||
999 | member_connect (struct GNUNET_MULTICAST_Member *mem); | ||
1000 | |||
1001 | |||
1002 | static void | ||
1003 | member_reconnect (void *cls) | ||
1004 | { | ||
1005 | member_connect (cls); | ||
1006 | } | ||
1007 | |||
1008 | |||
1009 | /** | ||
1010 | * Member client disconnected from service. | ||
1011 | * | ||
1012 | * Reconnect after backoff period. | ||
1013 | */ | ||
1014 | static void | ||
1015 | member_disconnected (void *cls, enum GNUNET_MQ_Error error) | ||
1016 | { | ||
1017 | struct GNUNET_MULTICAST_Member *mem = cls; | ||
1018 | struct GNUNET_MULTICAST_Group *grp = &mem->grp; | ||
1019 | |||
1020 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1021 | "Member client disconnected (%d), re-connecting\n", | ||
1022 | (int) error); | ||
1023 | GNUNET_MQ_destroy (grp->mq); | ||
1024 | grp->mq = NULL; | ||
1025 | |||
1026 | grp->reconnect_task = GNUNET_SCHEDULER_add_delayed (grp->reconnect_delay, | ||
1027 | member_reconnect, | ||
1028 | mem); | ||
1029 | grp->reconnect_delay = GNUNET_TIME_STD_BACKOFF (grp->reconnect_delay); | ||
1030 | } | ||
1031 | |||
1032 | |||
1033 | /** | ||
1034 | * Connect to service as member. | ||
1035 | */ | ||
1036 | static void | ||
1037 | member_connect (struct GNUNET_MULTICAST_Member *mem) | ||
1038 | { | ||
1039 | struct GNUNET_MULTICAST_Group *grp = &mem->grp; | ||
1040 | |||
1041 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
1042 | GNUNET_MQ_hd_var_size (group_message, | ||
1043 | GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, | ||
1044 | struct GNUNET_MULTICAST_MessageHeader, | ||
1045 | grp), | ||
1046 | GNUNET_MQ_hd_fixed_size (group_fragment_ack, | ||
1047 | GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK, | ||
1048 | struct GNUNET_MessageHeader, | ||
1049 | grp), | ||
1050 | GNUNET_MQ_hd_var_size (group_join_request, | ||
1051 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, | ||
1052 | struct MulticastJoinRequestMessage, | ||
1053 | grp), | ||
1054 | GNUNET_MQ_hd_var_size (member_join_decision, | ||
1055 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, | ||
1056 | struct MulticastJoinDecisionMessageHeader, | ||
1057 | mem), | ||
1058 | GNUNET_MQ_hd_fixed_size (group_part_ack, | ||
1059 | GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK, | ||
1060 | struct GNUNET_MessageHeader, | ||
1061 | grp), | ||
1062 | GNUNET_MQ_hd_fixed_size (group_replay_request, | ||
1063 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, | ||
1064 | struct MulticastReplayRequestMessage, | ||
1065 | grp), | ||
1066 | GNUNET_MQ_hd_var_size (member_replay_response, | ||
1067 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, | ||
1068 | struct MulticastReplayResponseMessage, | ||
1069 | mem), | ||
1070 | GNUNET_MQ_handler_end () | ||
1071 | }; | ||
1072 | |||
1073 | grp->mq = GNUNET_CLIENT_connect (grp->cfg, "multicast", | ||
1074 | handlers, member_disconnected, mem); | ||
1075 | GNUNET_assert (NULL != grp->mq); | ||
1076 | GNUNET_MQ_send_copy (grp->mq, grp->connect_env); | ||
1077 | } | ||
1078 | |||
1079 | |||
1080 | /** | ||
1081 | * Join a multicast group. | ||
1082 | * | ||
1083 | * The entity joining is always the local peer. Further information about the | ||
1084 | * candidate can be provided in the @a join_request message. If the join fails, the | ||
1085 | * @a message_cb is invoked with a (failure) response and then with NULL. If | ||
1086 | * the join succeeds, outstanding (state) messages and ongoing multicast | ||
1087 | * messages will be given to the @a message_cb until the member decides to part | ||
1088 | * the group. The @a replay_cb function may be called at any time by the | ||
1089 | * multicast service to support relaying messages to other members of the group. | ||
1090 | * | ||
1091 | * @param cfg | ||
1092 | * Configuration to use. | ||
1093 | * @param group_key | ||
1094 | * ECC public key that identifies the group to join. | ||
1095 | * @param member_key | ||
1096 | * ECC key that identifies the member | ||
1097 | * and used to sign requests sent to the origin. | ||
1098 | * @param origin | ||
1099 | * Peer ID of the origin to send unicast requsets to. If NULL, | ||
1100 | * unicast requests are sent back via multiple hops on the reverse path | ||
1101 | * of multicast messages. | ||
1102 | * @param relay_count | ||
1103 | * Number of peers in the @a relays array. | ||
1104 | * @param relays | ||
1105 | * Peer identities of members of the group, which serve as relays | ||
1106 | * and can be used to join the group at. and send the @a join_request to. | ||
1107 | * If empty, the @a join_request is sent directly to the @a origin. | ||
1108 | * @param join_msg | ||
1109 | * Application-dependent join message to be passed to the peer @a origin. | ||
1110 | * @param join_request_cb | ||
1111 | * Function called to approve / disapprove joining of a peer. | ||
1112 | * @param join_decision_cb | ||
1113 | * Function called to inform about the join decision. | ||
1114 | * @param replay_frag_cb | ||
1115 | * Function that can be called to replay message fragments | ||
1116 | * this peer already knows from this group. NULL if this | ||
1117 | * client is unable to support replay. | ||
1118 | * @param replay_msg_cb | ||
1119 | * Function that can be called to replay message fragments | ||
1120 | * this peer already knows from this group. NULL if this | ||
1121 | * client is unable to support replay. | ||
1122 | * @param message_cb | ||
1123 | * Function to be called for all message fragments we | ||
1124 | * receive from the group, excluding those our @a replay_cb | ||
1125 | * already has. | ||
1126 | * @param cls | ||
1127 | * Closure for callbacks. | ||
1128 | * | ||
1129 | * @return Handle for the member, NULL on error. | ||
1130 | */ | ||
1131 | struct GNUNET_MULTICAST_Member * | ||
1132 | GNUNET_MULTICAST_member_join (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
1133 | const struct GNUNET_CRYPTO_EddsaPublicKey *group_pub_key, | ||
1134 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *member_key, | ||
1135 | const struct GNUNET_PeerIdentity *origin, | ||
1136 | uint16_t relay_count, | ||
1137 | const struct GNUNET_PeerIdentity *relays, | ||
1138 | const struct GNUNET_MessageHeader *join_msg, | ||
1139 | GNUNET_MULTICAST_JoinRequestCallback join_request_cb, | ||
1140 | GNUNET_MULTICAST_JoinDecisionCallback join_decision_cb, | ||
1141 | GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb, | ||
1142 | GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb, | ||
1143 | GNUNET_MULTICAST_MessageCallback message_cb, | ||
1144 | void *cls) | ||
1145 | { | ||
1146 | struct GNUNET_MULTICAST_Member *mem = GNUNET_malloc (sizeof (*mem)); | ||
1147 | struct GNUNET_MULTICAST_Group *grp = &mem->grp; | ||
1148 | |||
1149 | uint16_t relay_size = relay_count * sizeof (*relays); | ||
1150 | uint16_t join_msg_size = (NULL != join_msg) ? ntohs (join_msg->size) : 0; | ||
1151 | struct MulticastMemberJoinMessage *join; | ||
1152 | grp->connect_env = GNUNET_MQ_msg_extra (join, relay_size + join_msg_size, | ||
1153 | GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN); | ||
1154 | join->group_pub_key = *group_pub_key; | ||
1155 | join->member_key = *member_key; | ||
1156 | join->origin = *origin; | ||
1157 | join->relay_count = ntohl (relay_count); | ||
1158 | if (0 < relay_size) | ||
1159 | GNUNET_memcpy (&join[1], relays, relay_size); | ||
1160 | if (0 < join_msg_size) | ||
1161 | GNUNET_memcpy (((char *) &join[1]) + relay_size, join_msg, join_msg_size); | ||
1162 | |||
1163 | grp->cfg = cfg; | ||
1164 | grp->is_origin = GNUNET_NO; | ||
1165 | grp->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS; | ||
1166 | |||
1167 | mem->join_dcsn_cb = join_decision_cb; | ||
1168 | grp->join_req_cb = join_request_cb; | ||
1169 | grp->replay_frag_cb = replay_frag_cb; | ||
1170 | grp->replay_msg_cb = replay_msg_cb; | ||
1171 | grp->message_cb = message_cb; | ||
1172 | grp->cb_cls = cls; | ||
1173 | |||
1174 | member_connect (mem); | ||
1175 | return mem; | ||
1176 | } | ||
1177 | |||
1178 | |||
1179 | /** | ||
1180 | * Part a multicast group. | ||
1181 | * | ||
1182 | * Disconnects from all group members and invalidates the @a member handle. | ||
1183 | * | ||
1184 | * An application-dependent part message can be transmitted beforehand using | ||
1185 | * #GNUNET_MULTICAST_member_to_origin()) | ||
1186 | * | ||
1187 | * @param member | ||
1188 | * Membership handle. | ||
1189 | */ | ||
1190 | void | ||
1191 | GNUNET_MULTICAST_member_part (struct GNUNET_MULTICAST_Member *mem, | ||
1192 | GNUNET_ContinuationCallback part_cb, | ||
1193 | void *part_cls) | ||
1194 | { | ||
1195 | struct GNUNET_MULTICAST_Group *grp = &mem->grp; | ||
1196 | struct GNUNET_MQ_Envelope *env; | ||
1197 | |||
1198 | mem->join_dcsn_cb = NULL; | ||
1199 | grp->join_req_cb = NULL; | ||
1200 | grp->message_cb = NULL; | ||
1201 | grp->replay_msg_cb = NULL; | ||
1202 | grp->replay_frag_cb = NULL; | ||
1203 | grp->is_disconnecting = GNUNET_YES; | ||
1204 | grp->disconnect_cb = part_cb; | ||
1205 | grp->disconnect_cls = part_cls; | ||
1206 | env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_PART_REQUEST); | ||
1207 | GNUNET_MQ_send (grp->mq, env); | ||
1208 | } | ||
1209 | |||
1210 | |||
1211 | void | ||
1212 | member_replay_request (struct GNUNET_MULTICAST_Member *mem, | ||
1213 | uint64_t fragment_id, | ||
1214 | uint64_t message_id, | ||
1215 | uint64_t fragment_offset, | ||
1216 | uint64_t flags) | ||
1217 | { | ||
1218 | struct MulticastReplayRequestMessage *rep; | ||
1219 | struct GNUNET_MQ_Envelope * | ||
1220 | env = GNUNET_MQ_msg (rep, GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST); | ||
1221 | |||
1222 | rep->fragment_id = GNUNET_htonll (fragment_id); | ||
1223 | rep->message_id = GNUNET_htonll (message_id); | ||
1224 | rep->fragment_offset = GNUNET_htonll (fragment_offset); | ||
1225 | rep->flags = GNUNET_htonll (flags); | ||
1226 | |||
1227 | GNUNET_MQ_send (mem->grp.mq, env); | ||
1228 | } | ||
1229 | |||
1230 | |||
1231 | /** | ||
1232 | * Request a fragment to be replayed by fragment ID. | ||
1233 | * | ||
1234 | * Useful if messages below the @e max_known_fragment_id given when joining are | ||
1235 | * needed and not known to the client. | ||
1236 | * | ||
1237 | * @param member | ||
1238 | * Membership handle. | ||
1239 | * @param fragment_id | ||
1240 | * ID of a message fragment that this client would like to see replayed. | ||
1241 | * @param flags | ||
1242 | * Additional flags for the replay request. | ||
1243 | * It is used and defined by GNUNET_MULTICAST_ReplayFragmentCallback | ||
1244 | * | ||
1245 | * @return Replay request handle. | ||
1246 | */ | ||
1247 | struct GNUNET_MULTICAST_MemberReplayHandle * | ||
1248 | GNUNET_MULTICAST_member_replay_fragment (struct GNUNET_MULTICAST_Member *mem, | ||
1249 | uint64_t fragment_id, | ||
1250 | uint64_t flags) | ||
1251 | { | ||
1252 | member_replay_request (mem, fragment_id, 0, 0, flags); | ||
1253 | // FIXME: return something useful | ||
1254 | return NULL; | ||
1255 | } | ||
1256 | |||
1257 | |||
1258 | /** | ||
1259 | * Request a message fragment to be replayed. | ||
1260 | * | ||
1261 | * Useful if messages below the @e max_known_fragment_id given when joining are | ||
1262 | * needed and not known to the client. | ||
1263 | * | ||
1264 | * @param member | ||
1265 | * Membership handle. | ||
1266 | * @param message_id | ||
1267 | * ID of the message this client would like to see replayed. | ||
1268 | * @param fragment_offset | ||
1269 | * Offset of the fragment within the message to replay. | ||
1270 | * @param flags | ||
1271 | * Additional flags for the replay request. | ||
1272 | * It is used & defined by GNUNET_MULTICAST_ReplayMessageCallback | ||
1273 | * | ||
1274 | * @return Replay request handle, NULL on error. | ||
1275 | */ | ||
1276 | struct GNUNET_MULTICAST_MemberReplayHandle * | ||
1277 | GNUNET_MULTICAST_member_replay_message (struct GNUNET_MULTICAST_Member *mem, | ||
1278 | uint64_t message_id, | ||
1279 | uint64_t fragment_offset, | ||
1280 | uint64_t flags) | ||
1281 | { | ||
1282 | member_replay_request (mem, 0, message_id, fragment_offset, flags); | ||
1283 | // FIXME: return something useful | ||
1284 | return NULL; | ||
1285 | } | ||
1286 | |||
1287 | |||
1288 | static void | ||
1289 | member_to_origin (struct GNUNET_MULTICAST_Member *mem) | ||
1290 | { | ||
1291 | LOG (GNUNET_ERROR_TYPE_DEBUG, "member_to_origin()\n"); | ||
1292 | struct GNUNET_MULTICAST_Group *grp = &mem->grp; | ||
1293 | struct GNUNET_MULTICAST_MemberTransmitHandle *tmit = &mem->tmit; | ||
1294 | GNUNET_assert (GNUNET_YES == grp->in_transmit); | ||
1295 | |||
1296 | size_t buf_size = GNUNET_MULTICAST_FRAGMENT_MAX_SIZE; | ||
1297 | struct GNUNET_MULTICAST_RequestHeader *req; | ||
1298 | struct GNUNET_MQ_Envelope * | ||
1299 | env = GNUNET_MQ_msg_extra (req, buf_size - sizeof(*req), | ||
1300 | GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST); | ||
1301 | |||
1302 | int ret = tmit->notify (tmit->notify_cls, &buf_size, &req[1]); | ||
1303 | |||
1304 | if (! (GNUNET_YES == ret || GNUNET_NO == ret) | ||
1305 | || GNUNET_MULTICAST_FRAGMENT_MAX_SIZE < buf_size) | ||
1306 | { | ||
1307 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1308 | "MemberTransmitNotify() returned error or invalid message size. " | ||
1309 | "ret=%d, buf_size=%u\n", ret, buf_size); | ||
1310 | /* FIXME: handle error */ | ||
1311 | GNUNET_MQ_discard (env); | ||
1312 | return; | ||
1313 | } | ||
1314 | |||
1315 | if (GNUNET_NO == ret && 0 == buf_size) | ||
1316 | { | ||
1317 | /* Transmission paused. */ | ||
1318 | GNUNET_MQ_discard (env); | ||
1319 | return; | ||
1320 | } | ||
1321 | |||
1322 | req->header.size = htons (sizeof (*req) + buf_size); | ||
1323 | req->request_id = GNUNET_htonll (tmit->request_id); | ||
1324 | req->fragment_offset = GNUNET_ntohll (tmit->fragment_offset); | ||
1325 | tmit->fragment_offset += sizeof (*req) + buf_size; | ||
1326 | |||
1327 | GNUNET_MQ_send (grp->mq, env); | ||
1328 | |||
1329 | if (GNUNET_YES == ret) | ||
1330 | grp->in_transmit = GNUNET_NO; | ||
1331 | } | ||
1332 | |||
1333 | |||
1334 | /** | ||
1335 | * Send a message to the origin of the multicast group. | ||
1336 | * | ||
1337 | * @param mem | ||
1338 | * Membership handle. | ||
1339 | * @param request_id | ||
1340 | * Application layer ID for the request. Opaque to multicast. | ||
1341 | * @param notify | ||
1342 | * Callback to call to get the message. | ||
1343 | * @param notify_cls | ||
1344 | * Closure for @a notify. | ||
1345 | * | ||
1346 | * @return Handle to cancel request, NULL on error (i.e. request already pending). | ||
1347 | */ | ||
1348 | struct GNUNET_MULTICAST_MemberTransmitHandle * | ||
1349 | GNUNET_MULTICAST_member_to_origin (struct GNUNET_MULTICAST_Member *mem, | ||
1350 | uint64_t request_id, | ||
1351 | GNUNET_MULTICAST_MemberTransmitNotify notify, | ||
1352 | void *notify_cls) | ||
1353 | { | ||
1354 | if (GNUNET_YES == mem->grp.in_transmit) | ||
1355 | return NULL; | ||
1356 | mem->grp.in_transmit = GNUNET_YES; | ||
1357 | |||
1358 | struct GNUNET_MULTICAST_MemberTransmitHandle *tmit = &mem->tmit; | ||
1359 | tmit->member = mem; | ||
1360 | tmit->request_id = request_id; | ||
1361 | tmit->fragment_offset = 0; | ||
1362 | tmit->notify = notify; | ||
1363 | tmit->notify_cls = notify_cls; | ||
1364 | |||
1365 | member_to_origin (mem); | ||
1366 | return tmit; | ||
1367 | } | ||
1368 | |||
1369 | |||
1370 | /** | ||
1371 | * Resume message transmission to origin. | ||
1372 | * | ||
1373 | * @param th | ||
1374 | * Transmission to cancel. | ||
1375 | */ | ||
1376 | void | ||
1377 | GNUNET_MULTICAST_member_to_origin_resume (struct GNUNET_MULTICAST_MemberTransmitHandle *th) | ||
1378 | { | ||
1379 | struct GNUNET_MULTICAST_Group *grp = &th->member->grp; | ||
1380 | if (0 != grp->acks_pending || GNUNET_YES != grp->in_transmit) | ||
1381 | return; | ||
1382 | member_to_origin (th->member); | ||
1383 | } | ||
1384 | |||
1385 | |||
1386 | /** | ||
1387 | * Cancel request for message transmission to origin. | ||
1388 | * | ||
1389 | * @param th | ||
1390 | * Transmission to cancel. | ||
1391 | */ | ||
1392 | void | ||
1393 | GNUNET_MULTICAST_member_to_origin_cancel (struct GNUNET_MULTICAST_MemberTransmitHandle *th) | ||
1394 | { | ||
1395 | th->member->grp.in_transmit = GNUNET_NO; | ||
1396 | } | ||
1397 | |||
1398 | |||
1399 | /* end of multicast_api.c */ | ||
diff --git a/src/multicast/test_multicast.c b/src/multicast/test_multicast.c deleted file mode 100644 index 70efdcbfb..000000000 --- a/src/multicast/test_multicast.c +++ /dev/null | |||
@@ -1,758 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of GNUnet | ||
3 | * Copyright (C) 2013 GNUnet e.V. | ||
4 | * | ||
5 | * GNUnet is free software: you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU Affero General Public License as published | ||
7 | * by the Free Software Foundation, either version 3 of the License, | ||
8 | * or (at your option) any later version. | ||
9 | * | ||
10 | * GNUnet is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file multicast/test_multicast.c | ||
23 | * @brief Tests for the Multicast API. | ||
24 | * @author Gabor X Toth | ||
25 | */ | ||
26 | |||
27 | #include <inttypes.h> | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_crypto_lib.h" | ||
31 | #include "gnunet_common.h" | ||
32 | #include "gnunet_util_lib.h" | ||
33 | #include "gnunet_testing_lib.h" | ||
34 | #include "gnunet_multicast_service.h" | ||
35 | |||
36 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) | ||
37 | |||
38 | /** | ||
39 | * Return value from 'main'. | ||
40 | */ | ||
41 | static int res; | ||
42 | |||
43 | /** | ||
44 | * Handle for task for timeout termination. | ||
45 | */ | ||
46 | static struct GNUNET_SCHEDULER_Task * end_badly_task; | ||
47 | |||
48 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
49 | |||
50 | struct GNUNET_PeerIdentity this_peer; | ||
51 | |||
52 | struct GNUNET_MULTICAST_Origin *origin; | ||
53 | struct GNUNET_MULTICAST_Member *member; | ||
54 | |||
55 | struct GNUNET_CRYPTO_EddsaPrivateKey *group_key; | ||
56 | struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key; | ||
57 | |||
58 | struct GNUNET_CRYPTO_EcdsaPrivateKey *member_key; | ||
59 | struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key; | ||
60 | |||
61 | struct TransmitClosure { | ||
62 | struct GNUNET_MULTICAST_OriginTransmitHandle *orig_tmit; | ||
63 | struct GNUNET_MULTICAST_MemberTransmitHandle *mem_tmit; | ||
64 | char * data[16]; | ||
65 | uint8_t data_delay[16]; | ||
66 | uint8_t data_count; | ||
67 | uint8_t paused; | ||
68 | uint8_t n; | ||
69 | } tmit_cls; | ||
70 | |||
71 | struct OriginClosure { | ||
72 | uint8_t msgs_expected; | ||
73 | uint8_t n; | ||
74 | } origin_cls; | ||
75 | |||
76 | struct MemberClosure { | ||
77 | uint8_t msgs_expected; | ||
78 | size_t n; | ||
79 | } member_cls; | ||
80 | |||
81 | struct GNUNET_MessageHeader *join_req, *join_resp; | ||
82 | |||
83 | enum | ||
84 | { | ||
85 | TEST_NONE = 0, | ||
86 | TEST_ORIGIN_START = 1, | ||
87 | TEST_MEMBER_JOIN_REFUSE = 2, | ||
88 | TEST_MEMBER_JOIN_ADMIT = 3, | ||
89 | TEST_ORIGIN_TO_ALL = 4, | ||
90 | TEST_ORIGIN_TO_ALL_RECV = 5, | ||
91 | TEST_MEMBER_TO_ORIGIN = 6, | ||
92 | TEST_MEMBER_REPLAY_ERROR = 7, | ||
93 | TEST_MEMBER_REPLAY_OK = 8, | ||
94 | TEST_MEMBER_PART = 9, | ||
95 | TEST_ORIGIN_STOP = 10, | ||
96 | } test; | ||
97 | |||
98 | uint64_t replay_fragment_id; | ||
99 | uint64_t replay_flags; | ||
100 | |||
101 | static void | ||
102 | member_join (int t); | ||
103 | |||
104 | |||
105 | /** | ||
106 | * Clean up all resources used. | ||
107 | */ | ||
108 | static void | ||
109 | cleanup () | ||
110 | { | ||
111 | if (NULL != member) | ||
112 | { | ||
113 | GNUNET_MULTICAST_member_part (member, NULL, NULL); | ||
114 | member = NULL; | ||
115 | } | ||
116 | if (NULL != origin) | ||
117 | { | ||
118 | GNUNET_MULTICAST_origin_stop (origin, NULL, NULL); | ||
119 | origin = NULL; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | |||
124 | /** | ||
125 | * Terminate the test case (failure). | ||
126 | * | ||
127 | * @param cls NULL | ||
128 | */ | ||
129 | static void | ||
130 | end_badly (void *cls) | ||
131 | { | ||
132 | res = 1; | ||
133 | cleanup (); | ||
134 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test FAILED.\n"); | ||
135 | } | ||
136 | |||
137 | |||
138 | /** | ||
139 | * Terminate the test case (success). | ||
140 | * | ||
141 | * @param cls NULL | ||
142 | */ | ||
143 | static void | ||
144 | end_normally (void *cls) | ||
145 | { | ||
146 | res = 0; | ||
147 | cleanup (); | ||
148 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test PASSED.\n"); | ||
149 | } | ||
150 | |||
151 | |||
152 | /** | ||
153 | * Finish the test case (successfully). | ||
154 | */ | ||
155 | static void | ||
156 | end () | ||
157 | { | ||
158 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending tests.\n"); | ||
159 | |||
160 | if (end_badly_task != NULL) | ||
161 | { | ||
162 | GNUNET_SCHEDULER_cancel (end_badly_task); | ||
163 | end_badly_task = NULL; | ||
164 | } | ||
165 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, | ||
166 | &end_normally, NULL); | ||
167 | } | ||
168 | |||
169 | |||
170 | static void | ||
171 | tmit_resume (void *cls) | ||
172 | { | ||
173 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission resumed.\n"); | ||
174 | struct TransmitClosure *tmit = cls; | ||
175 | if (NULL != tmit->orig_tmit) | ||
176 | GNUNET_MULTICAST_origin_to_all_resume (tmit->orig_tmit); | ||
177 | else if (NULL != tmit->mem_tmit) | ||
178 | GNUNET_MULTICAST_member_to_origin_resume (tmit->mem_tmit); | ||
179 | } | ||
180 | |||
181 | |||
182 | static int | ||
183 | tmit_notify (void *cls, size_t *data_size, void *data) | ||
184 | { | ||
185 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
186 | "Test #%u: origin_tmit_notify()\n", test); | ||
187 | struct TransmitClosure *tmit = cls; | ||
188 | |||
189 | if (0 == tmit->data_count) | ||
190 | { | ||
191 | *data_size = 0; | ||
192 | return GNUNET_YES; | ||
193 | } | ||
194 | |||
195 | uint16_t size = strlen (tmit->data[tmit->n]); | ||
196 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
197 | "Transmit notify data: %u bytes available, processing fragment %u/%u (size %u).\n", | ||
198 | (unsigned int) *data_size, | ||
199 | tmit->n + 1, | ||
200 | tmit->data_count, | ||
201 | size); | ||
202 | if (*data_size < size) | ||
203 | { | ||
204 | *data_size = 0; | ||
205 | GNUNET_assert (0); | ||
206 | return GNUNET_SYSERR; | ||
207 | } | ||
208 | |||
209 | if (GNUNET_YES != tmit->paused && 0 < tmit->data_delay[tmit->n]) | ||
210 | { | ||
211 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission paused.\n"); | ||
212 | tmit->paused = GNUNET_YES; | ||
213 | GNUNET_SCHEDULER_add_delayed ( | ||
214 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, | ||
215 | tmit->data_delay[tmit->n]), | ||
216 | tmit_resume, tmit); | ||
217 | *data_size = 0; | ||
218 | return GNUNET_NO; | ||
219 | } | ||
220 | tmit->paused = GNUNET_NO; | ||
221 | |||
222 | *data_size = size; | ||
223 | GNUNET_memcpy (data, tmit->data[tmit->n], size); | ||
224 | |||
225 | return ++tmit->n < tmit->data_count ? GNUNET_NO : GNUNET_YES; | ||
226 | } | ||
227 | |||
228 | |||
229 | static void | ||
230 | member_recv_join_request (void *cls, | ||
231 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key, | ||
232 | const struct GNUNET_MessageHeader *join_msg, | ||
233 | struct GNUNET_MULTICAST_JoinHandle *jh) | ||
234 | { | ||
235 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
236 | "Test #%u: member_recv_join_request()\n", test); | ||
237 | } | ||
238 | |||
239 | |||
240 | static void | ||
241 | origin_stopped (void *cls) | ||
242 | { | ||
243 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
244 | "Test #%u: origin_stopped()\n", test); | ||
245 | end (); | ||
246 | } | ||
247 | |||
248 | |||
249 | static void | ||
250 | schedule_origin_stop (void *cls) | ||
251 | { | ||
252 | test = TEST_ORIGIN_STOP; | ||
253 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
254 | "Test #%u: origin_stop()\n", test); | ||
255 | GNUNET_MULTICAST_origin_stop (origin, origin_stopped, NULL); | ||
256 | origin = NULL; | ||
257 | } | ||
258 | |||
259 | |||
260 | static void | ||
261 | member_parted (void *cls) | ||
262 | { | ||
263 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
264 | "Test #%u: member_parted()\n", test); | ||
265 | member = NULL; | ||
266 | |||
267 | switch (test) | ||
268 | { | ||
269 | case TEST_MEMBER_JOIN_REFUSE: | ||
270 | // Test 3 starts here | ||
271 | member_join (TEST_MEMBER_JOIN_ADMIT); | ||
272 | break; | ||
273 | |||
274 | case TEST_MEMBER_PART: | ||
275 | GNUNET_SCHEDULER_add_now (&schedule_origin_stop, NULL); | ||
276 | break; | ||
277 | |||
278 | default: | ||
279 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
280 | "Invalid test #%d in member_parted()\n", test); | ||
281 | GNUNET_assert (0); | ||
282 | } | ||
283 | } | ||
284 | |||
285 | |||
286 | static void | ||
287 | schedule_member_part (void *cls) | ||
288 | { | ||
289 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
290 | "Test #%u: schedule_member_part()\n", test); | ||
291 | GNUNET_MULTICAST_member_part (member, member_parted, NULL); | ||
292 | } | ||
293 | |||
294 | |||
295 | static void | ||
296 | member_part () | ||
297 | { | ||
298 | test = TEST_MEMBER_PART; | ||
299 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
300 | "Test #%u: member_part()\n", test); | ||
301 | // Test 10 starts here | ||
302 | GNUNET_SCHEDULER_add_now (&schedule_member_part, NULL); | ||
303 | } | ||
304 | |||
305 | |||
306 | static void | ||
307 | member_replay_ok () | ||
308 | { | ||
309 | // Execution of test 8 here | ||
310 | test = TEST_MEMBER_REPLAY_OK; | ||
311 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
312 | "Test #%u: member_replay_ok()\n", test); | ||
313 | replay_fragment_id = 1; | ||
314 | replay_flags = 1 | 1<<11; | ||
315 | GNUNET_MULTICAST_member_replay_fragment (member, replay_fragment_id, | ||
316 | replay_flags); | ||
317 | } | ||
318 | |||
319 | |||
320 | static void | ||
321 | member_replay_error () | ||
322 | { | ||
323 | test = TEST_MEMBER_REPLAY_ERROR; | ||
324 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
325 | "Test #%u: member_replay_error()\n", test); | ||
326 | replay_fragment_id = 1234; | ||
327 | replay_flags = 11 | 1<<11; | ||
328 | GNUNET_MULTICAST_member_replay_fragment (member, replay_fragment_id, | ||
329 | replay_flags); | ||
330 | } | ||
331 | |||
332 | |||
333 | static void | ||
334 | origin_recv_replay_msg (void *cls, | ||
335 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key, | ||
336 | uint64_t message_id, | ||
337 | uint64_t fragment_offset, | ||
338 | uint64_t flags, | ||
339 | struct GNUNET_MULTICAST_ReplayHandle *rh) | ||
340 | { | ||
341 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
342 | "Test #%u: origin_recv_replay_msg()\n", test); | ||
343 | GNUNET_assert (0); | ||
344 | } | ||
345 | |||
346 | |||
347 | static void | ||
348 | member_recv_replay_msg (void *cls, | ||
349 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key, | ||
350 | uint64_t message_id, | ||
351 | uint64_t fragment_offset, | ||
352 | uint64_t flags, | ||
353 | struct GNUNET_MULTICAST_ReplayHandle *rh) | ||
354 | { | ||
355 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
356 | "Test #%u: member_recv_replay_msg()\n", test); | ||
357 | GNUNET_assert (0); | ||
358 | } | ||
359 | |||
360 | |||
361 | static void | ||
362 | origin_recv_replay_frag (void *cls, | ||
363 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key, | ||
364 | uint64_t fragment_id, | ||
365 | uint64_t flags, | ||
366 | struct GNUNET_MULTICAST_ReplayHandle *rh) | ||
367 | { | ||
368 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
369 | "Test #%u: origin_recv_replay_frag()" | ||
370 | " - fragment_id=%" PRIu64 " flags=%" PRIu64 "\n", | ||
371 | test, fragment_id, flags); | ||
372 | GNUNET_assert (replay_fragment_id == fragment_id && replay_flags == flags); | ||
373 | switch (test) | ||
374 | { | ||
375 | case TEST_MEMBER_REPLAY_ERROR: | ||
376 | // Test 8 starts here | ||
377 | GNUNET_MULTICAST_replay_response (rh, NULL, GNUNET_SYSERR); | ||
378 | member_replay_ok (); | ||
379 | break; | ||
380 | |||
381 | case TEST_MEMBER_REPLAY_OK: | ||
382 | { | ||
383 | struct GNUNET_MULTICAST_MessageHeader mmsg = { | ||
384 | .header = { | ||
385 | .type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE), | ||
386 | .size = htons (sizeof (mmsg)), | ||
387 | }, | ||
388 | .fragment_id = GNUNET_htonll (1), | ||
389 | .message_id = GNUNET_htonll (1), | ||
390 | .fragment_offset = 0, | ||
391 | .group_generation = GNUNET_htonll (1), | ||
392 | .flags = 0, | ||
393 | }; | ||
394 | member_cls.n = 0; | ||
395 | member_cls.msgs_expected = 1; | ||
396 | GNUNET_MULTICAST_replay_response (rh, &mmsg.header, GNUNET_MULTICAST_REC_OK); | ||
397 | GNUNET_MULTICAST_replay_response_end (rh); | ||
398 | break; | ||
399 | } | ||
400 | |||
401 | default: | ||
402 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
403 | "Invalid test #%d in origin_recv_replay_frag()\n", test); | ||
404 | GNUNET_assert (0); | ||
405 | } | ||
406 | } | ||
407 | |||
408 | |||
409 | static void | ||
410 | member_recv_replay_frag (void *cls, | ||
411 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key, | ||
412 | uint64_t fragment_id, | ||
413 | uint64_t flags, | ||
414 | struct GNUNET_MULTICAST_ReplayHandle *rh) | ||
415 | { | ||
416 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
417 | "Test #%u: member_recv_replay_frag()\n", test); | ||
418 | GNUNET_assert (0); | ||
419 | } | ||
420 | |||
421 | |||
422 | static void | ||
423 | origin_recv_request (void *cls, | ||
424 | const struct GNUNET_MULTICAST_RequestHeader *req) | ||
425 | { | ||
426 | struct OriginClosure *ocls = cls; | ||
427 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
428 | "Test #%u: origin_recv_request()\n", test); | ||
429 | if (++ocls->n != ocls->msgs_expected) | ||
430 | return; | ||
431 | |||
432 | GNUNET_assert (0 == memcmp (&req->member_pub_key, | ||
433 | &member_pub_key, sizeof (member_pub_key))); | ||
434 | |||
435 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
436 | "Test #%u: verify message content, take first 3 bytes: %.3s\n", | ||
437 | test, (char *)&req[1]); | ||
438 | GNUNET_assert (0 == memcmp (&req[1], "abc", 3)); | ||
439 | |||
440 | // Test 7 starts here | ||
441 | member_replay_error (); | ||
442 | } | ||
443 | |||
444 | |||
445 | static void | ||
446 | member_to_origin () | ||
447 | { | ||
448 | test = TEST_MEMBER_TO_ORIGIN; | ||
449 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
450 | "Test #%u: member_to_origin()\n", test); | ||
451 | |||
452 | struct TransmitClosure *tmit = &tmit_cls; | ||
453 | *tmit = (struct TransmitClosure) {}; | ||
454 | tmit->data[0] = "abc def"; | ||
455 | tmit->data[1] = "ghi jkl mno"; | ||
456 | tmit->data_delay[1] = 2; | ||
457 | tmit->data[2] = "pqr stuw xyz"; | ||
458 | tmit->data_count = 3; | ||
459 | |||
460 | origin_cls.n = 0; | ||
461 | origin_cls.msgs_expected = 1; | ||
462 | |||
463 | tmit->mem_tmit = GNUNET_MULTICAST_member_to_origin (member, 1, | ||
464 | tmit_notify, tmit); | ||
465 | } | ||
466 | |||
467 | |||
468 | static void | ||
469 | member_recv_message (void *cls, | ||
470 | const struct GNUNET_MULTICAST_MessageHeader *msg) | ||
471 | { | ||
472 | struct MemberClosure *mcls = cls; | ||
473 | |||
474 | // Test 5 starts here after message has been received from origin | ||
475 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
476 | "Test #%u: member_recv_message() %u/%u\n", | ||
477 | test, | ||
478 | (unsigned int) (mcls->n + 1), | ||
479 | mcls->msgs_expected); | ||
480 | if (++mcls->n != mcls->msgs_expected) | ||
481 | return; | ||
482 | |||
483 | // FIXME: check message content | ||
484 | |||
485 | switch (test) | ||
486 | { | ||
487 | case TEST_ORIGIN_TO_ALL: | ||
488 | test = TEST_ORIGIN_TO_ALL_RECV; | ||
489 | break; | ||
490 | |||
491 | case TEST_ORIGIN_TO_ALL_RECV: | ||
492 | // Test 6 starts here | ||
493 | member_to_origin (); | ||
494 | break; | ||
495 | |||
496 | case TEST_MEMBER_REPLAY_OK: | ||
497 | // Test 9 starts here | ||
498 | GNUNET_assert (replay_fragment_id == GNUNET_ntohll (msg->fragment_id)); | ||
499 | member_part (); | ||
500 | break; | ||
501 | |||
502 | default: | ||
503 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
504 | "Invalid test #%d in origin_recv_message()\n", test); | ||
505 | GNUNET_assert (0); | ||
506 | } | ||
507 | } | ||
508 | |||
509 | |||
510 | static void | ||
511 | origin_recv_message (void *cls, | ||
512 | const struct GNUNET_MULTICAST_MessageHeader *msg) | ||
513 | { | ||
514 | struct OriginClosure *ocls = cls; | ||
515 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
516 | "Test #%u: origin_recv_message() %u/%u\n", | ||
517 | test, ocls->n + 1, ocls->msgs_expected); | ||
518 | if (++ocls->n != ocls->msgs_expected) | ||
519 | return; | ||
520 | |||
521 | // FIXME: check message content | ||
522 | |||
523 | switch (test) | ||
524 | { | ||
525 | case TEST_ORIGIN_TO_ALL: | ||
526 | // Prepare to execute test 5 | ||
527 | test = TEST_ORIGIN_TO_ALL_RECV; | ||
528 | break; | ||
529 | |||
530 | case TEST_ORIGIN_TO_ALL_RECV: | ||
531 | // Test 6 starts here | ||
532 | member_to_origin (); | ||
533 | break; | ||
534 | |||
535 | default: | ||
536 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
537 | "Invalid test #%d in origin_recv_message()\n", test); | ||
538 | GNUNET_assert (0); | ||
539 | } | ||
540 | } | ||
541 | |||
542 | |||
543 | static void | ||
544 | origin_to_all () | ||
545 | { | ||
546 | test = TEST_ORIGIN_TO_ALL; | ||
547 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
548 | "Test #%u: origin_to_all()\n", test); | ||
549 | |||
550 | struct TransmitClosure *tmit = &tmit_cls; | ||
551 | *tmit = (struct TransmitClosure) {}; | ||
552 | tmit->data[0] = "ABC DEF"; | ||
553 | tmit->data[1] = GNUNET_malloc (GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD + 1); | ||
554 | uint16_t i; | ||
555 | for (i = 0; i < GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD; i++) | ||
556 | tmit->data[1][i] = (0 == i % 10000) ? '0' + i / 10000 : '_'; | ||
557 | tmit->data[2] = "GHI JKL MNO"; | ||
558 | tmit->data_delay[2] = 2; | ||
559 | tmit->data[3] = "PQR STUW XYZ"; | ||
560 | tmit->data_count = 4; | ||
561 | |||
562 | origin_cls.n = member_cls.n = 0; | ||
563 | origin_cls.msgs_expected = member_cls.msgs_expected = tmit->data_count; | ||
564 | |||
565 | tmit->orig_tmit = GNUNET_MULTICAST_origin_to_all (origin, 1, 1, | ||
566 | tmit_notify, tmit); | ||
567 | } | ||
568 | |||
569 | |||
570 | static void | ||
571 | member_recv_join_decision (void *cls, | ||
572 | int is_admitted, | ||
573 | const struct GNUNET_PeerIdentity *peer, | ||
574 | uint16_t relay_count, | ||
575 | const struct GNUNET_PeerIdentity *relays, | ||
576 | const struct GNUNET_MessageHeader *join_msg) | ||
577 | { | ||
578 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
579 | "Test #%u: member_recv_join_decision() - is_admitted: %d\n", | ||
580 | test, is_admitted); | ||
581 | |||
582 | GNUNET_assert (join_msg->size == join_resp->size); | ||
583 | GNUNET_assert (join_msg->type == join_resp->type); | ||
584 | GNUNET_assert (0 == memcmp (join_msg, join_resp, ntohs (join_resp->size))); | ||
585 | |||
586 | switch (test) | ||
587 | { | ||
588 | case TEST_MEMBER_JOIN_REFUSE: | ||
589 | GNUNET_assert (0 == relay_count); | ||
590 | // Test 3 starts here | ||
591 | GNUNET_SCHEDULER_add_now (&schedule_member_part, NULL); | ||
592 | break; | ||
593 | |||
594 | case TEST_MEMBER_JOIN_ADMIT: | ||
595 | GNUNET_assert (1 == relay_count); | ||
596 | GNUNET_assert (0 == memcmp (relays, &this_peer, sizeof (this_peer))); | ||
597 | // Test 4 starts here | ||
598 | origin_to_all (); | ||
599 | break; | ||
600 | |||
601 | default: | ||
602 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
603 | "Invalid test #%d in member_recv_join_decision()\n", test); | ||
604 | GNUNET_assert (0); | ||
605 | } | ||
606 | } | ||
607 | |||
608 | /** | ||
609 | * Test: origin receives join request | ||
610 | */ | ||
611 | static void | ||
612 | origin_recv_join_request (void *cls, | ||
613 | const struct GNUNET_CRYPTO_EcdsaPublicKey *mem_key, | ||
614 | const struct GNUNET_MessageHeader *join_msg, | ||
615 | struct GNUNET_MULTICAST_JoinHandle *jh) | ||
616 | { | ||
617 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
618 | "Test #%u: origin_recv_join_request()\n", test); | ||
619 | |||
620 | GNUNET_assert (0 == memcmp (mem_key, &member_pub_key, sizeof (member_pub_key))); | ||
621 | GNUNET_assert (join_msg->size == join_req->size); | ||
622 | GNUNET_assert (join_msg->type == join_req->type); | ||
623 | GNUNET_assert (0 == memcmp (join_msg, join_req, ntohs (join_req->size))); | ||
624 | |||
625 | char data[] = "here's the decision"; | ||
626 | uint8_t data_size = strlen (data) + 1; | ||
627 | join_resp = GNUNET_malloc (sizeof (join_resp) + data_size); | ||
628 | join_resp->size = htons (sizeof (join_resp) + data_size); | ||
629 | join_resp->type = htons (456); | ||
630 | GNUNET_memcpy (&join_resp[1], data, data_size); | ||
631 | |||
632 | switch (test) | ||
633 | { | ||
634 | case TEST_MEMBER_JOIN_REFUSE: | ||
635 | // Test 3 starts here | ||
636 | GNUNET_MULTICAST_join_decision (jh, GNUNET_NO, 0, NULL, join_resp); | ||
637 | break; | ||
638 | |||
639 | case TEST_MEMBER_JOIN_ADMIT: | ||
640 | // Test 3 is running | ||
641 | GNUNET_MULTICAST_join_decision (jh, GNUNET_YES, 1, &this_peer, join_resp); | ||
642 | break; | ||
643 | |||
644 | default: | ||
645 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
646 | "Invalid test #%d in origin_recv_join_request()\n", test); | ||
647 | GNUNET_assert (0); | ||
648 | break; | ||
649 | } | ||
650 | } | ||
651 | |||
652 | /** | ||
653 | * Test: member joins multicast group | ||
654 | */ | ||
655 | static void | ||
656 | member_join (int t) | ||
657 | { | ||
658 | test = t; | ||
659 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
660 | "Test #%u: member_join()\n", test); | ||
661 | |||
662 | member_key = GNUNET_CRYPTO_ecdsa_key_create (); | ||
663 | GNUNET_CRYPTO_ecdsa_key_get_public (member_key, &member_pub_key); | ||
664 | |||
665 | if (NULL != join_req) | ||
666 | GNUNET_free (join_req); | ||
667 | |||
668 | char data[] = "let me in!"; | ||
669 | uint8_t data_size = strlen (data) + 1; | ||
670 | join_req = GNUNET_malloc (sizeof (join_req) + data_size); | ||
671 | join_req->size = htons (sizeof (join_req) + data_size); | ||
672 | join_req->type = htons (123); | ||
673 | GNUNET_memcpy (&join_req[1], data, data_size); | ||
674 | |||
675 | member = GNUNET_MULTICAST_member_join (cfg, &group_pub_key, member_key, | ||
676 | &this_peer, 1, &this_peer, join_req, | ||
677 | member_recv_join_request, | ||
678 | member_recv_join_decision, | ||
679 | member_recv_replay_frag, | ||
680 | member_recv_replay_msg, | ||
681 | member_recv_message, | ||
682 | &member_cls); | ||
683 | } | ||
684 | |||
685 | /** | ||
686 | * Test: Start a multicast group as origin | ||
687 | */ | ||
688 | static void | ||
689 | origin_start () | ||
690 | { | ||
691 | test = TEST_ORIGIN_START; | ||
692 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
693 | "Test #%u: origin_start()\n", test); | ||
694 | |||
695 | group_key = GNUNET_CRYPTO_eddsa_key_create (); | ||
696 | GNUNET_CRYPTO_eddsa_key_get_public (group_key, &group_pub_key); | ||
697 | |||
698 | origin = GNUNET_MULTICAST_origin_start (cfg, group_key, 0, | ||
699 | origin_recv_join_request, | ||
700 | origin_recv_replay_frag, | ||
701 | origin_recv_replay_msg, | ||
702 | origin_recv_request, | ||
703 | origin_recv_message, | ||
704 | &origin_cls); | ||
705 | // Test 2 starts here | ||
706 | member_join (TEST_MEMBER_JOIN_REFUSE); | ||
707 | } | ||
708 | |||
709 | |||
710 | /** | ||
711 | * Main function of the test, run from scheduler. | ||
712 | * | ||
713 | * @param cls NULL | ||
714 | * @param cfg configuration we use (also to connect to Multicast service) | ||
715 | * @param peer handle to access more of the peer (not used) | ||
716 | */ | ||
717 | static void | ||
718 | #if DEBUG_TEST_MULTICAST | ||
719 | run (void *cls, | ||
720 | char *const *args, | ||
721 | const char *cfgfile, | ||
722 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
723 | #else | ||
724 | run (void *cls, | ||
725 | const struct GNUNET_CONFIGURATION_Handle *c, | ||
726 | struct GNUNET_TESTING_Peer *peer) | ||
727 | #endif | ||
728 | { | ||
729 | cfg = c; | ||
730 | end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
731 | &end_badly, NULL); | ||
732 | GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer); | ||
733 | |||
734 | // Test 1 starts here | ||
735 | origin_start (); | ||
736 | } | ||
737 | |||
738 | |||
739 | int | ||
740 | main (int argc, char *argv[]) | ||
741 | { | ||
742 | res = 1; | ||
743 | #if DEBUG_TEST_MULTICAST | ||
744 | const struct GNUNET_GETOPT_CommandLineOption opts[] = { | ||
745 | GNUNET_GETOPT_OPTION_END | ||
746 | }; | ||
747 | if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test-multicast", | ||
748 | "test-multicast [options]", | ||
749 | opts, &run, NULL)) | ||
750 | return 1; | ||
751 | #else | ||
752 | if (0 != GNUNET_TESTING_peer_run ("test-multicast", "test_multicast.conf", &run, NULL)) | ||
753 | return 1; | ||
754 | #endif | ||
755 | return res; | ||
756 | } | ||
757 | |||
758 | /* end of test_multicast.c */ | ||
diff --git a/src/multicast/test_multicast.conf b/src/multicast/test_multicast.conf deleted file mode 100644 index b2f1a764b..000000000 --- a/src/multicast/test_multicast.conf +++ /dev/null | |||
@@ -1,56 +0,0 @@ | |||
1 | [testbed] | ||
2 | HOSTNAME = localhost | ||
3 | |||
4 | [arm] | ||
5 | GLOBAL_POSTFIX=-L ERROR | ||
6 | |||
7 | [multicast] | ||
8 | #PREFIX = tmux new-window gdb -x ./cmd.gdb --args | ||
9 | #PREFIX = valgrind --leak-check=full | ||
10 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock | ||
11 | |||
12 | [vpn] | ||
13 | START_ON_DEMAND = NO | ||
14 | |||
15 | [peerinfo] | ||
16 | # Do not use shipped gnunet HELLOs | ||
17 | USE_INCLUDED_HELLOS = NO | ||
18 | |||
19 | # Option to disable all disk IO; only useful for testbed runs | ||
20 | # (large-scale experiments); disables persistence of HELLOs! | ||
21 | NO_IO = YES | ||
22 | |||
23 | [hostlist] | ||
24 | IMMEDIATE_START = NO | ||
25 | START_ON_DEMAND = NO | ||
26 | |||
27 | [nat] | ||
28 | ENABLE_UPNP = NO | ||
29 | |||
30 | [fs] | ||
31 | IMMEDIATE_START = NO | ||
32 | START_ON_DEMAND = NO | ||
33 | |||
34 | [vpn] | ||
35 | IMMEDIATE_START = NO | ||
36 | START_ON_DEMAND = NO | ||
37 | |||
38 | [revocation] | ||
39 | IMMEDIATE_START = NO | ||
40 | START_ON_DEMAND = NO | ||
41 | |||
42 | [gns] | ||
43 | IMMEDIATE_START = NO | ||
44 | START_ON_DEMAND = NO | ||
45 | |||
46 | [namestore] | ||
47 | IMMEDIATE_START = NO | ||
48 | START_ON_DEMAND = NO | ||
49 | |||
50 | [namecache] | ||
51 | IMMEDIATE_START = NO | ||
52 | START_ON_DEMAND = NO | ||
53 | |||
54 | [topology] | ||
55 | IMMEDIATE_START = NO | ||
56 | START_ON_DEMAND = NO | ||
diff --git a/src/multicast/test_multicast_2peers.c b/src/multicast/test_multicast_2peers.c deleted file mode 100644 index ea996026c..000000000 --- a/src/multicast/test_multicast_2peers.c +++ /dev/null | |||
@@ -1,520 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of GNUnet | ||
3 | * Copyright (C) 2013 GNUnet e.V. | ||
4 | * | ||
5 | * GNUnet is free software: you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU Affero General Public License as published | ||
7 | * by the Free Software Foundation, either version 3 of the License, | ||
8 | * or (at your option) any later version. | ||
9 | * | ||
10 | * GNUnet is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file multicast/test_multicast_2peers.c | ||
23 | * @brief Tests for the Multicast API with two peers doing the ping | ||
24 | * pong test. | ||
25 | * @author xrs | ||
26 | */ | ||
27 | |||
28 | #include <inttypes.h> | ||
29 | |||
30 | #include "platform.h" | ||
31 | #include "gnunet_crypto_lib.h" | ||
32 | #include "gnunet_common.h" | ||
33 | #include "gnunet_util_lib.h" | ||
34 | #include "gnunet_testbed_service.h" | ||
35 | #include "gnunet_multicast_service.h" | ||
36 | |||
37 | #define NUM_PEERS 2 | ||
38 | |||
39 | static struct GNUNET_TESTBED_Operation *op0; | ||
40 | static struct GNUNET_TESTBED_Operation *op1; | ||
41 | static struct GNUNET_TESTBED_Operation *pi_op0; | ||
42 | static struct GNUNET_TESTBED_Operation *pi_op1; | ||
43 | |||
44 | static struct GNUNET_TESTBED_Peer **peers; | ||
45 | const struct GNUNET_PeerIdentity *peer_id[2]; | ||
46 | |||
47 | static struct GNUNET_SCHEDULER_Task *timeout_tid; | ||
48 | |||
49 | static struct GNUNET_MULTICAST_Origin *origin; | ||
50 | static struct GNUNET_MULTICAST_Member *member; | ||
51 | |||
52 | struct GNUNET_CRYPTO_EddsaPrivateKey *group_key; | ||
53 | struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key; | ||
54 | |||
55 | struct GNUNET_CRYPTO_EcdsaPrivateKey *member_key; | ||
56 | struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key; | ||
57 | |||
58 | /** | ||
59 | * Global result for testcase. | ||
60 | */ | ||
61 | static int result; | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Function run on CTRL-C or shutdown (i.e. success/timeout/etc.). | ||
66 | * Cleans up. | ||
67 | */ | ||
68 | static void | ||
69 | shutdown_task (void *cls) | ||
70 | { | ||
71 | if (NULL != op0) | ||
72 | { | ||
73 | GNUNET_TESTBED_operation_done (op0); | ||
74 | op0 = NULL; | ||
75 | } | ||
76 | if (NULL != op1) | ||
77 | { | ||
78 | GNUNET_TESTBED_operation_done (op1); | ||
79 | op1 = NULL; | ||
80 | } | ||
81 | if (NULL != pi_op0) | ||
82 | { | ||
83 | GNUNET_TESTBED_operation_done (pi_op0); | ||
84 | pi_op0 = NULL; | ||
85 | } | ||
86 | if (NULL != pi_op1) | ||
87 | { | ||
88 | GNUNET_TESTBED_operation_done (pi_op1); | ||
89 | pi_op1 = NULL; | ||
90 | } | ||
91 | if (NULL != timeout_tid) | ||
92 | { | ||
93 | GNUNET_SCHEDULER_cancel (timeout_tid); | ||
94 | timeout_tid = NULL; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | |||
99 | static void | ||
100 | timeout_task (void *cls) | ||
101 | { | ||
102 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
103 | "Timeout!\n"); | ||
104 | result = GNUNET_SYSERR; | ||
105 | GNUNET_SCHEDULER_shutdown (); | ||
106 | } | ||
107 | |||
108 | |||
109 | static void | ||
110 | member_join_request (void *cls, | ||
111 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key, | ||
112 | const struct GNUNET_MessageHeader *join_msg, | ||
113 | struct GNUNET_MULTICAST_JoinHandle *jh) | ||
114 | { | ||
115 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
116 | "Member sent a join request.\n"); | ||
117 | |||
118 | } | ||
119 | |||
120 | |||
121 | static int | ||
122 | notify (void *cls, | ||
123 | size_t *data_size, | ||
124 | void *data) | ||
125 | { | ||
126 | |||
127 | char text[] = "ping"; | ||
128 | *data_size = strlen(text)+1; | ||
129 | GNUNET_memcpy(data, text, *data_size); | ||
130 | |||
131 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
132 | "Member sents message to origin: %s\n", text); | ||
133 | |||
134 | return GNUNET_YES; | ||
135 | } | ||
136 | |||
137 | |||
138 | static void | ||
139 | member_join_decision (void *cls, | ||
140 | int is_admitted, | ||
141 | const struct GNUNET_PeerIdentity *peer, | ||
142 | uint16_t relay_count, | ||
143 | const struct GNUNET_PeerIdentity *relays, | ||
144 | const struct GNUNET_MessageHeader *join_msg) | ||
145 | { | ||
146 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
147 | "Member received a decision from origin: %s\n", | ||
148 | (GNUNET_YES == is_admitted) | ||
149 | ? "accepted" | ||
150 | : "rejected"); | ||
151 | |||
152 | if (GNUNET_YES == is_admitted) | ||
153 | { | ||
154 | struct GNUNET_MULTICAST_MemberTransmitHandle *req; | ||
155 | |||
156 | // FIXME: move to MQ-style API! | ||
157 | req = GNUNET_MULTICAST_member_to_origin (member, | ||
158 | 0, | ||
159 | ¬ify, | ||
160 | NULL); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | |||
165 | static void | ||
166 | member_message (void *cls, | ||
167 | const struct GNUNET_MULTICAST_MessageHeader *msg) | ||
168 | { | ||
169 | if (0 != strncmp ("pong", (char *)&msg[1], 4)) | ||
170 | { | ||
171 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "member did not receive pong\n"); | ||
172 | result = GNUNET_SYSERR; | ||
173 | GNUNET_SCHEDULER_shutdown (); | ||
174 | } | ||
175 | |||
176 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
177 | "member receives: %s\n", (char *)&msg[1]); | ||
178 | |||
179 | // Testcase ends here. | ||
180 | result = GNUNET_YES; | ||
181 | GNUNET_SCHEDULER_shutdown (); | ||
182 | } | ||
183 | |||
184 | |||
185 | static void | ||
186 | origin_join_request (void *cls, | ||
187 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key, | ||
188 | const struct GNUNET_MessageHeader *join_msg, | ||
189 | struct GNUNET_MULTICAST_JoinHandle *jh) | ||
190 | { | ||
191 | struct GNUNET_MessageHeader *join_resp; | ||
192 | |||
193 | uint8_t data_size = ntohs (join_msg->size); | ||
194 | |||
195 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
196 | "origin got a join request...\n"); | ||
197 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
198 | "origin receives: '%s'\n", (char *)&join_msg[1]); | ||
199 | |||
200 | const char data[] = "Come in!"; | ||
201 | data_size = strlen (data) + 1; | ||
202 | join_resp = GNUNET_malloc (sizeof (join_resp) + data_size); | ||
203 | join_resp->size = htons (sizeof (join_resp) + data_size); | ||
204 | join_resp->type = htons (123); | ||
205 | GNUNET_memcpy (&join_resp[1], data, data_size); | ||
206 | |||
207 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
208 | "origin sends: '%s'\n", data); | ||
209 | |||
210 | GNUNET_MULTICAST_join_decision (jh, | ||
211 | GNUNET_YES, | ||
212 | 0, | ||
213 | NULL, | ||
214 | join_resp); | ||
215 | GNUNET_free (join_resp); | ||
216 | result = GNUNET_OK; | ||
217 | } | ||
218 | |||
219 | |||
220 | int | ||
221 | origin_notify (void *cls, | ||
222 | size_t *data_size, | ||
223 | void *data) | ||
224 | { | ||
225 | char text[] = "pong"; | ||
226 | |||
227 | *data_size = strlen(text)+1; | ||
228 | GNUNET_memcpy (data, | ||
229 | text, | ||
230 | *data_size); | ||
231 | |||
232 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin sends (to all): %s\n", text); | ||
233 | |||
234 | return GNUNET_YES; | ||
235 | } | ||
236 | |||
237 | |||
238 | static void | ||
239 | origin_request (void *cls, | ||
240 | const struct GNUNET_MULTICAST_RequestHeader *req) | ||
241 | { | ||
242 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin receives: %s\n", (char *)&req[1]); | ||
243 | |||
244 | if (0 != strncmp ("ping", (char *)&req[1], 4)) | ||
245 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "origin didn't reveice a correct request"); | ||
246 | |||
247 | GNUNET_MULTICAST_origin_to_all (origin, | ||
248 | 0, | ||
249 | 0, | ||
250 | origin_notify, | ||
251 | NULL); | ||
252 | } | ||
253 | |||
254 | |||
255 | static void | ||
256 | origin_message (void *cls, | ||
257 | const struct GNUNET_MULTICAST_MessageHeader *msg) | ||
258 | { | ||
259 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin message msg\n"); | ||
260 | } | ||
261 | |||
262 | |||
263 | static void | ||
264 | service_connect1 (void *cls, | ||
265 | struct GNUNET_TESTBED_Operation *op, | ||
266 | void *ca_result, | ||
267 | const char *emsg) | ||
268 | { | ||
269 | member = ca_result; | ||
270 | |||
271 | if (NULL == member) | ||
272 | { | ||
273 | result = GNUNET_SYSERR; | ||
274 | GNUNET_SCHEDULER_shutdown (); | ||
275 | } | ||
276 | else | ||
277 | { | ||
278 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to multicast service of member\n"); | ||
279 | } | ||
280 | } | ||
281 | |||
282 | |||
283 | static void | ||
284 | multicast_da1 (void *cls, | ||
285 | void * op_result) | ||
286 | { | ||
287 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
288 | "Member parting from multicast group\n"); | ||
289 | |||
290 | GNUNET_MULTICAST_member_part (member, NULL, NULL); | ||
291 | } | ||
292 | |||
293 | |||
294 | static void * | ||
295 | multicast_ca1 (void *cls, | ||
296 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
297 | { | ||
298 | struct GNUNET_MessageHeader *join_msg; | ||
299 | void *ret; | ||
300 | |||
301 | // Get members keys | ||
302 | member_key = GNUNET_CRYPTO_ecdsa_key_create (); | ||
303 | GNUNET_CRYPTO_ecdsa_key_get_public (member_key, &member_pub_key); | ||
304 | |||
305 | char data[] = "Hi, can I enter?"; | ||
306 | uint8_t data_size = strlen (data) + 1; | ||
307 | join_msg = GNUNET_malloc (sizeof (join_msg) + data_size); | ||
308 | join_msg->size = htons (sizeof (join_msg) + data_size); | ||
309 | join_msg->type = htons (123); | ||
310 | GNUNET_memcpy (&join_msg[1], data, data_size); | ||
311 | |||
312 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
313 | "Members tries to join multicast group\n"); | ||
314 | |||
315 | ret = GNUNET_MULTICAST_member_join (cfg, | ||
316 | &group_pub_key, | ||
317 | member_key, | ||
318 | peer_id[0], | ||
319 | 0, | ||
320 | NULL, | ||
321 | join_msg, /* join message */ | ||
322 | member_join_request, | ||
323 | member_join_decision, | ||
324 | NULL, /* no test for member_replay_frag */ | ||
325 | NULL, /* no test for member_replay_msg */ | ||
326 | member_message, | ||
327 | NULL); | ||
328 | GNUNET_free (join_msg); | ||
329 | return ret; | ||
330 | } | ||
331 | |||
332 | |||
333 | static void | ||
334 | peer_information_cb (void *cls, | ||
335 | struct GNUNET_TESTBED_Operation *op, | ||
336 | const struct GNUNET_TESTBED_PeerInformation *pinfo, | ||
337 | const char *emsg) | ||
338 | { | ||
339 | int i = (int) (long) cls; | ||
340 | |||
341 | if (NULL == pinfo) | ||
342 | { | ||
343 | result = GNUNET_SYSERR; | ||
344 | GNUNET_SCHEDULER_shutdown (); | ||
345 | } | ||
346 | |||
347 | peer_id[i] = pinfo->result.id; | ||
348 | |||
349 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
350 | "Got peer information of %s (%s)\n", (0==i)?"origin":"member" ,GNUNET_i2s(pinfo->result.id)); | ||
351 | |||
352 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
353 | "Create member peer\n"); | ||
354 | |||
355 | if (0 == i) | ||
356 | { | ||
357 | /* connect to multicast service of member */ | ||
358 | op1 = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */ | ||
359 | peers[1], /* The peer whose service to connect to */ | ||
360 | "multicast", /* The name of the service */ | ||
361 | service_connect1, /* callback to call after a handle to service | ||
362 | is opened */ | ||
363 | NULL, /* closure for the above callback */ | ||
364 | multicast_ca1, /* callback to call with peer's configuration; | ||
365 | this should open the needed service connection */ | ||
366 | multicast_da1, /* callback to be called when closing the | ||
367 | opened service connection */ | ||
368 | NULL); /* closure for the above two callbacks */ | ||
369 | } | ||
370 | } | ||
371 | |||
372 | |||
373 | /** | ||
374 | * Test logic of peer "0" being origin starts here. | ||
375 | * | ||
376 | * @param cls closure, for the example: NULL | ||
377 | * @param op should be equal to "dht_op" | ||
378 | * @param ca_result result of the connect operation, the | ||
379 | * connection to the DHT service | ||
380 | * @param emsg error message, if testbed somehow failed to | ||
381 | * connect to the DHT. | ||
382 | */ | ||
383 | static void | ||
384 | service_connect0 (void *cls, | ||
385 | struct GNUNET_TESTBED_Operation *op, | ||
386 | void *ca_result, | ||
387 | const char *emsg) | ||
388 | { | ||
389 | origin = ca_result; | ||
390 | |||
391 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
392 | "Connected to multicast service of origin\n"); | ||
393 | |||
394 | // Get GNUnet identity of origin | ||
395 | pi_op0 = GNUNET_TESTBED_peer_get_information (peers[0], | ||
396 | GNUNET_TESTBED_PIT_IDENTITY, | ||
397 | peer_information_cb, | ||
398 | (void *) 0); | ||
399 | // Get GNUnet identity of member | ||
400 | pi_op1 = GNUNET_TESTBED_peer_get_information (peers[1], | ||
401 | GNUNET_TESTBED_PIT_IDENTITY, | ||
402 | peer_information_cb, | ||
403 | (void *) 1); | ||
404 | |||
405 | /* Connection to service successful. Here we'd usually do something with | ||
406 | * the service. */ | ||
407 | result = GNUNET_OK; | ||
408 | //GNUNET_SCHEDULER_shutdown (); /* Also kills the testbed */ | ||
409 | } | ||
410 | |||
411 | |||
412 | |||
413 | /** | ||
414 | * Function run when service multicast has started and is providing us | ||
415 | * with a configuration file. | ||
416 | */ | ||
417 | static void * | ||
418 | multicast_ca0 (void *cls, | ||
419 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
420 | { | ||
421 | group_key = GNUNET_CRYPTO_eddsa_key_create (); | ||
422 | GNUNET_CRYPTO_eddsa_key_get_public (group_key, &group_pub_key); | ||
423 | |||
424 | return GNUNET_MULTICAST_origin_start (cfg, | ||
425 | group_key, | ||
426 | 0, | ||
427 | origin_join_request, | ||
428 | NULL, /* no test for origin_replay_frag */ | ||
429 | NULL, /* no test for origin_replay_msg */ | ||
430 | origin_request, | ||
431 | origin_message, | ||
432 | NULL); | ||
433 | } | ||
434 | |||
435 | static void | ||
436 | multicast_da0 (void *cls, | ||
437 | void *op_result) | ||
438 | { | ||
439 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
440 | "Origin closes multicast group\n"); | ||
441 | |||
442 | GNUNET_MULTICAST_origin_stop (origin, NULL, NULL); | ||
443 | } | ||
444 | |||
445 | |||
446 | /** | ||
447 | * Main function inovked from TESTBED once all of the | ||
448 | * peers are up and running. This one then connects | ||
449 | * just to the multicast service of peer 0 and 1. | ||
450 | * Peer 0 is going to be origin. | ||
451 | * Peer 1 is going to be one member. | ||
452 | * Origin will start a multicast group and the member will try to join it. | ||
453 | * After that we execute some multicast test. | ||
454 | * | ||
455 | * @param cls closure | ||
456 | * @param h the run handle | ||
457 | * @param peers started peers for the test | ||
458 | * @param num_peers size of the 'peers' array | ||
459 | * @param links_succeeded number of links between peers that were created | ||
460 | * @param links_failed number of links testbed was unable to establish | ||
461 | */ | ||
462 | static void | ||
463 | testbed_master (void *cls, | ||
464 | struct GNUNET_TESTBED_RunHandle *h, | ||
465 | unsigned int num_peers, | ||
466 | struct GNUNET_TESTBED_Peer **p, | ||
467 | unsigned int links_succeeded, | ||
468 | unsigned int links_failed) | ||
469 | { | ||
470 | /* Testbed is ready with peers running and connected in a pre-defined overlay | ||
471 | topology (FIXME) */ | ||
472 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
473 | "Connected to testbed_master()\n"); | ||
474 | |||
475 | peers = p; | ||
476 | |||
477 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
478 | "Create origin peer\n"); | ||
479 | op0 = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */ | ||
480 | peers[0], /* The peer whose service to connect to */ | ||
481 | "multicast", /* The name of the service */ | ||
482 | service_connect0, /* callback to call after a handle to service | ||
483 | is opened */ | ||
484 | NULL, /* closure for the above callback */ | ||
485 | multicast_ca0, /* callback to call with peer's configuration; | ||
486 | this should open the needed service connection */ | ||
487 | multicast_da0, /* callback to be called when closing the | ||
488 | opened service connection */ | ||
489 | NULL); /* closure for the above two callbacks */ | ||
490 | |||
491 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); /* Schedule a new task on shutdown */ | ||
492 | |||
493 | /* Schedule the shutdown task with a delay of a few Seconds */ | ||
494 | timeout_tid = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 50), | ||
495 | &timeout_task, NULL); | ||
496 | } | ||
497 | |||
498 | |||
499 | int | ||
500 | main (int argc, char *argv[]) | ||
501 | { | ||
502 | int ret; | ||
503 | |||
504 | result = GNUNET_SYSERR; | ||
505 | ret = GNUNET_TESTBED_test_run | ||
506 | ("test-multicast-2peers", /* test case name */ | ||
507 | "test_multicast.conf", /* template configuration */ | ||
508 | NUM_PEERS, /* number of peers to start */ | ||
509 | 0LL, /* Event mask - set to 0 for no event notifications */ | ||
510 | NULL, /* Controller event callback */ | ||
511 | NULL, /* Closure for controller event callback */ | ||
512 | testbed_master, /* continuation callback to be called when testbed setup is complete */ | ||
513 | NULL); /* Closure for the test_master callback */ | ||
514 | if ( (GNUNET_OK != ret) || (GNUNET_OK != result) ) | ||
515 | return 1; | ||
516 | return 0; | ||
517 | } | ||
518 | |||
519 | |||
520 | /* end of test_multicast_2peers.c */ | ||
diff --git a/src/multicast/test_multicast_line.conf b/src/multicast/test_multicast_line.conf deleted file mode 100644 index c1ce7c63f..000000000 --- a/src/multicast/test_multicast_line.conf +++ /dev/null | |||
@@ -1,63 +0,0 @@ | |||
1 | [testbed] | ||
2 | HOSTNAME = localhost | ||
3 | OVERLAY_TOPOLOGY = LINE | ||
4 | |||
5 | [arm] | ||
6 | GLOBAL_POSTFIX=-L ERROR | ||
7 | |||
8 | [multicast] | ||
9 | #PREFIX = tmux new-window gdb -x ./cmd.gdb --args | ||
10 | #PREFIX = valgrind --leak-check=full | ||
11 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock | ||
12 | |||
13 | [vpn] | ||
14 | START_ON_DEMAND = NO | ||
15 | |||
16 | [peerinfo] | ||
17 | # Do not use shipped gnunet HELLOs | ||
18 | USE_INCLUDED_HELLOS = NO | ||
19 | |||
20 | # Option to disable all disk IO; only useful for testbed runs | ||
21 | # (large-scale experiments); disables persistence of HELLOs! | ||
22 | NO_IO = YES | ||
23 | |||
24 | [cadet] | ||
25 | ID_ANNOUNCE_TIME = 5 s | ||
26 | |||
27 | [hostlist] | ||
28 | IMMEDIATE_START = NO | ||
29 | START_ON_DEMAND = NO | ||
30 | |||
31 | [nat] | ||
32 | ENABLE_UPNP = NO | ||
33 | |||
34 | [fs] | ||
35 | IMMEDIATE_START = NO | ||
36 | START_ON_DEMAND = NO | ||
37 | |||
38 | [vpn] | ||
39 | IMMEDIATE_START = NO | ||
40 | START_ON_DEMAND = NO | ||
41 | |||
42 | [revocation] | ||
43 | IMMEDIATE_START = NO | ||
44 | START_ON_DEMAND = NO | ||
45 | |||
46 | [gns] | ||
47 | IMMEDIATE_START = NO | ||
48 | START_ON_DEMAND = NO | ||
49 | |||
50 | [namestore] | ||
51 | IMMEDIATE_START = NO | ||
52 | START_ON_DEMAND = NO | ||
53 | |||
54 | [namecache] | ||
55 | IMMEDIATE_START = NO | ||
56 | START_ON_DEMAND = NO | ||
57 | |||
58 | [topology] | ||
59 | IMMEDIATE_START = NO | ||
60 | START_ON_DEMAND = NO | ||
61 | |||
62 | [nse] | ||
63 | WORKBITS = 0 | ||
diff --git a/src/multicast/test_multicast_multipeer.c b/src/multicast/test_multicast_multipeer.c deleted file mode 100644 index 9b44e05db..000000000 --- a/src/multicast/test_multicast_multipeer.c +++ /dev/null | |||
@@ -1,643 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of GNUnet | ||
3 | * Copyright (C) 2013 GNUnet e.V. | ||
4 | * | ||
5 | * GNUnet is free software: you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU Affero General Public License as published | ||
7 | * by the Free Software Foundation, either version 3 of the License, | ||
8 | * or (at your option) any later version. | ||
9 | * | ||
10 | * GNUnet is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file multicast/test_multicast_multipeers.c | ||
23 | * @brief Tests for the Multicast API with multiple peers. | ||
24 | * @author xrs | ||
25 | */ | ||
26 | |||
27 | #include <inttypes.h> | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_crypto_lib.h" | ||
31 | #include "gnunet_common.h" | ||
32 | #include "gnunet_util_lib.h" | ||
33 | #include "gnunet_testbed_service.h" | ||
34 | #include "gnunet_multicast_service.h" | ||
35 | |||
36 | #define PEERS_REQUESTED 12 | ||
37 | |||
38 | struct MulticastPeerContext | ||
39 | { | ||
40 | int peer; /* peer number */ | ||
41 | struct GNUNET_CRYPTO_EcdsaPrivateKey *key; | ||
42 | const struct GNUNET_PeerIdentity *id; | ||
43 | struct GNUNET_TESTBED_Operation *op; /* not yet in use */ | ||
44 | struct GNUNET_TESTBED_Operation *pi_op; /* not yet in use */ | ||
45 | int test_ok; | ||
46 | }; | ||
47 | |||
48 | enum pingpong | ||
49 | { | ||
50 | PING = 1, | ||
51 | PONG = 2 | ||
52 | }; | ||
53 | |||
54 | struct pingpong_msg | ||
55 | { | ||
56 | int peer; | ||
57 | enum pingpong msg; | ||
58 | }; | ||
59 | |||
60 | static void service_connect (void *cls, | ||
61 | struct GNUNET_TESTBED_Operation *op, | ||
62 | void *ca_result, | ||
63 | const char *emsg); | ||
64 | |||
65 | static struct MulticastPeerContext **multicast_peers; | ||
66 | static struct GNUNET_TESTBED_Peer **peers; | ||
67 | |||
68 | static struct GNUNET_TESTBED_Operation *op[PEERS_REQUESTED]; | ||
69 | static struct GNUNET_TESTBED_Operation *pi_op[PEERS_REQUESTED]; | ||
70 | |||
71 | static struct GNUNET_MULTICAST_Origin *origin; | ||
72 | static struct GNUNET_MULTICAST_Member *members[PEERS_REQUESTED]; /* first element always empty */ | ||
73 | |||
74 | static struct GNUNET_SCHEDULER_Task *timeout_tid; | ||
75 | |||
76 | static struct GNUNET_CRYPTO_EddsaPrivateKey *group_key; | ||
77 | static struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key; | ||
78 | static struct GNUNET_HashCode group_pub_key_hash; | ||
79 | |||
80 | /** | ||
81 | * Global result for testcase. | ||
82 | */ | ||
83 | static int result; | ||
84 | |||
85 | /** | ||
86 | * Function run on CTRL-C or shutdown (i.e. success/timeout/etc.). | ||
87 | * Cleans up. | ||
88 | */ | ||
89 | static void | ||
90 | shutdown_task (void *cls) | ||
91 | { | ||
92 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
93 | "shutdown_task!\n"); | ||
94 | for (int i=0;i<PEERS_REQUESTED;i++) | ||
95 | { | ||
96 | if (NULL != op[i]) | ||
97 | { | ||
98 | GNUNET_TESTBED_operation_done(op[i]); | ||
99 | op[i] = NULL; | ||
100 | } | ||
101 | if (NULL != pi_op[i]) | ||
102 | { | ||
103 | GNUNET_TESTBED_operation_done (pi_op[i]); | ||
104 | pi_op[i] = NULL; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | if (NULL != multicast_peers) | ||
109 | { | ||
110 | for (int i=0; i < PEERS_REQUESTED; i++) | ||
111 | { | ||
112 | GNUNET_free_non_null (multicast_peers[i]->key); | ||
113 | GNUNET_free (multicast_peers[i]); | ||
114 | multicast_peers[i] = NULL; | ||
115 | } | ||
116 | GNUNET_free (multicast_peers); | ||
117 | multicast_peers = NULL; | ||
118 | } | ||
119 | |||
120 | if (NULL != timeout_tid) | ||
121 | { | ||
122 | GNUNET_SCHEDULER_cancel (timeout_tid); | ||
123 | timeout_tid = NULL; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | |||
128 | static void | ||
129 | timeout_task (void *cls) | ||
130 | { | ||
131 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
132 | "Timeout!\n"); | ||
133 | result = GNUNET_SYSERR; | ||
134 | GNUNET_SCHEDULER_shutdown (); | ||
135 | } | ||
136 | |||
137 | |||
138 | static void | ||
139 | member_join_request (void *cls, | ||
140 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key, | ||
141 | const struct GNUNET_MessageHeader *join_msg, | ||
142 | struct GNUNET_MULTICAST_JoinHandle *jh) | ||
143 | { | ||
144 | struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls; | ||
145 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
146 | "Peer #%u (%s) sent a join request.\n", | ||
147 | mc_peer->peer, | ||
148 | GNUNET_i2s (multicast_peers[mc_peer->peer]->id)); | ||
149 | } | ||
150 | |||
151 | |||
152 | static int | ||
153 | notify (void *cls, | ||
154 | size_t *data_size, | ||
155 | void *data) | ||
156 | { | ||
157 | struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls; | ||
158 | |||
159 | struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg); | ||
160 | pp_msg->peer = mc_peer->peer; | ||
161 | pp_msg->msg = PING; | ||
162 | |||
163 | *data_size = sizeof (struct pingpong_msg); | ||
164 | GNUNET_memcpy(data, pp_msg, *data_size); | ||
165 | GNUNET_free (pp_msg); | ||
166 | |||
167 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
168 | "Peer #%u sents ping to origin\n", mc_peer->peer); | ||
169 | |||
170 | return GNUNET_YES; | ||
171 | } | ||
172 | |||
173 | |||
174 | static void | ||
175 | member_join_decision (void *cls, | ||
176 | int is_admitted, | ||
177 | const struct GNUNET_PeerIdentity *peer, | ||
178 | uint16_t relay_count, | ||
179 | const struct GNUNET_PeerIdentity *relays, | ||
180 | const struct GNUNET_MessageHeader *join_msg) | ||
181 | { | ||
182 | struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls; | ||
183 | |||
184 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
185 | "Peer #%u (%s) received a decision from origin: %s\n", | ||
186 | mc_peer->peer, | ||
187 | GNUNET_i2s (multicast_peers[mc_peer->peer]->id), | ||
188 | (GNUNET_YES == is_admitted)?"accepted":"rejected"); | ||
189 | |||
190 | if (GNUNET_YES == is_admitted) | ||
191 | { | ||
192 | GNUNET_MULTICAST_member_to_origin (members[mc_peer->peer], | ||
193 | 0, | ||
194 | notify, | ||
195 | cls); | ||
196 | |||
197 | } | ||
198 | } | ||
199 | |||
200 | |||
201 | static void | ||
202 | member_replay_frag () | ||
203 | { | ||
204 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
205 | "member replay frag...\n"); | ||
206 | } | ||
207 | |||
208 | |||
209 | static void | ||
210 | member_replay_msg () | ||
211 | { | ||
212 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
213 | "member replay msg...\n"); | ||
214 | } | ||
215 | |||
216 | |||
217 | static void | ||
218 | origin_disconnected_cb (void *cls) | ||
219 | { | ||
220 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
221 | "Origin disconnected. Shutting down.\n"); | ||
222 | result = GNUNET_YES; | ||
223 | GNUNET_SCHEDULER_shutdown (); | ||
224 | } | ||
225 | |||
226 | |||
227 | static void | ||
228 | member_disconnected_cb (void *cls) | ||
229 | { | ||
230 | for (int i = 1; i < PEERS_REQUESTED; ++i) | ||
231 | if (GNUNET_NO == multicast_peers[i]->test_ok) | ||
232 | return; | ||
233 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
234 | "All member disconnected. Stopping origin.\n"); | ||
235 | GNUNET_MULTICAST_origin_stop (origin, origin_disconnected_cb, cls); | ||
236 | } | ||
237 | |||
238 | |||
239 | static void | ||
240 | member_message (void *cls, | ||
241 | const struct GNUNET_MULTICAST_MessageHeader *msg) | ||
242 | { | ||
243 | struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls; | ||
244 | struct pingpong_msg *pp_msg = (struct pingpong_msg*) &(msg[1]); | ||
245 | |||
246 | if (PONG == pp_msg->msg && mc_peer->peer == pp_msg->peer) | ||
247 | { | ||
248 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
249 | "peer #%i (%s) receives a pong\n", | ||
250 | mc_peer->peer, | ||
251 | GNUNET_i2s (multicast_peers[mc_peer->peer]->id)); | ||
252 | mc_peer->test_ok = GNUNET_OK; | ||
253 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
254 | "peer #%u (%s) parting from multicast group\n", | ||
255 | mc_peer->peer, | ||
256 | GNUNET_i2s (multicast_peers[mc_peer->peer]->id)); | ||
257 | |||
258 | GNUNET_MULTICAST_member_part (members[mc_peer->peer], member_disconnected_cb, cls); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | |||
263 | static void | ||
264 | origin_join_request (void *cls, | ||
265 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key, | ||
266 | const struct GNUNET_MessageHeader *join_msg, | ||
267 | struct GNUNET_MULTICAST_JoinHandle *jh) | ||
268 | { | ||
269 | struct GNUNET_MessageHeader *join_resp; | ||
270 | |||
271 | uint8_t data_size = ntohs (join_msg->size); | ||
272 | |||
273 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
274 | "origin got a join request...\n"); | ||
275 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
276 | "origin receives: '%s'\n", (char *)&join_msg[1]); | ||
277 | |||
278 | char data[] = "Come in!"; | ||
279 | data_size = strlen (data) + 1; | ||
280 | join_resp = GNUNET_malloc (sizeof (join_resp) + data_size); | ||
281 | join_resp->size = htons (sizeof (join_resp) + data_size); | ||
282 | join_resp->type = htons (123); | ||
283 | GNUNET_memcpy (&join_resp[1], data, data_size); | ||
284 | |||
285 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
286 | "origin sends: '%s'\n", data); | ||
287 | |||
288 | GNUNET_MULTICAST_join_decision (jh, | ||
289 | GNUNET_YES, | ||
290 | 0, | ||
291 | NULL, | ||
292 | join_resp); | ||
293 | |||
294 | result = GNUNET_OK; | ||
295 | } | ||
296 | |||
297 | |||
298 | static void | ||
299 | origin_replay_frag (void *cls, | ||
300 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key, | ||
301 | uint64_t fragment_id, | ||
302 | uint64_t flags, | ||
303 | struct GNUNET_MULTICAST_ReplayHandle *rh) | ||
304 | { | ||
305 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay fraq msg\n"); | ||
306 | } | ||
307 | |||
308 | |||
309 | static void | ||
310 | origin_replay_msg (void *cls, | ||
311 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key, | ||
312 | uint64_t message_id, | ||
313 | uint64_t fragment_offset, | ||
314 | uint64_t flags, | ||
315 | struct GNUNET_MULTICAST_ReplayHandle *rh) | ||
316 | { | ||
317 | |||
318 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay msg\n"); | ||
319 | } | ||
320 | |||
321 | |||
322 | static int | ||
323 | origin_notify (void *cls, | ||
324 | size_t *data_size, | ||
325 | void *data) | ||
326 | { | ||
327 | struct pingpong_msg *rcv_pp_msg = (struct pingpong_msg*)cls; | ||
328 | struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg); | ||
329 | |||
330 | pp_msg->peer = rcv_pp_msg->peer; | ||
331 | pp_msg->msg = PONG; | ||
332 | *data_size = sizeof (struct pingpong_msg); | ||
333 | GNUNET_memcpy(data, pp_msg, *data_size); | ||
334 | GNUNET_free (pp_msg); | ||
335 | |||
336 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin sends pong\n"); | ||
337 | |||
338 | return GNUNET_YES; | ||
339 | } | ||
340 | |||
341 | |||
342 | static void | ||
343 | origin_request (void *cls, | ||
344 | const struct GNUNET_MULTICAST_RequestHeader *req) | ||
345 | { | ||
346 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin receives a msg\n"); | ||
347 | |||
348 | req++; | ||
349 | struct pingpong_msg *pp_msg = (struct pingpong_msg *) req; | ||
350 | |||
351 | if (1 != pp_msg->msg) { | ||
352 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "origin didn't reveice a correct request"); | ||
353 | } | ||
354 | |||
355 | GNUNET_MULTICAST_origin_to_all (origin, | ||
356 | 0, | ||
357 | 0, | ||
358 | origin_notify, | ||
359 | pp_msg); | ||
360 | } | ||
361 | |||
362 | |||
363 | static void | ||
364 | origin_message (void *cls, | ||
365 | const struct GNUNET_MULTICAST_MessageHeader *msg) | ||
366 | { | ||
367 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin message msg\n"); | ||
368 | } | ||
369 | |||
370 | |||
371 | static void | ||
372 | multicast_disconnect (void *cls, | ||
373 | void *op_result) | ||
374 | { | ||
375 | |||
376 | } | ||
377 | |||
378 | |||
379 | static void * | ||
380 | multicast_connect (void *cls, | ||
381 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
382 | { | ||
383 | struct MulticastPeerContext *multicast_peer = cls; | ||
384 | struct GNUNET_MessageHeader *join_msg; | ||
385 | char data[64]; | ||
386 | |||
387 | if (0 == multicast_peer->peer) | ||
388 | { | ||
389 | group_key = GNUNET_CRYPTO_eddsa_key_create (); | ||
390 | GNUNET_CRYPTO_eddsa_key_get_public (group_key, &group_pub_key); | ||
391 | |||
392 | GNUNET_CRYPTO_hash (&group_pub_key, sizeof (group_pub_key), &group_pub_key_hash); | ||
393 | origin = GNUNET_MULTICAST_origin_start (cfg, | ||
394 | group_key, | ||
395 | 0, | ||
396 | origin_join_request, | ||
397 | origin_replay_frag, | ||
398 | origin_replay_msg, | ||
399 | origin_request, | ||
400 | origin_message, | ||
401 | cls); | ||
402 | if (NULL == origin) | ||
403 | { | ||
404 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
405 | "Peer #%u could not create a multicast group", | ||
406 | multicast_peer->peer); | ||
407 | return NULL; | ||
408 | } | ||
409 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
410 | "Peer #%u connected as origin to group %s\n", | ||
411 | multicast_peer->peer, | ||
412 | GNUNET_h2s (&group_pub_key_hash)); | ||
413 | return origin; | ||
414 | } | ||
415 | else | ||
416 | { | ||
417 | multicast_peer->key = GNUNET_CRYPTO_ecdsa_key_create (); | ||
418 | |||
419 | sprintf(data, "Hi, I am peer #%u (%s). Can I enter?", | ||
420 | multicast_peer->peer, | ||
421 | GNUNET_i2s (multicast_peers[multicast_peer->peer]->id)); | ||
422 | uint8_t data_size = strlen (data) + 1; | ||
423 | join_msg = GNUNET_malloc (sizeof (join_msg) + data_size); | ||
424 | join_msg->size = htons (sizeof (join_msg) + data_size); | ||
425 | join_msg->type = htons (123); | ||
426 | GNUNET_memcpy (&join_msg[1], data, data_size); | ||
427 | |||
428 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
429 | "Peer #%u (%s) tries to join multicast group %s\n", | ||
430 | multicast_peer->peer, | ||
431 | GNUNET_i2s (multicast_peers[multicast_peer->peer]->id), | ||
432 | GNUNET_h2s (&group_pub_key_hash)); | ||
433 | |||
434 | members[multicast_peer->peer] = | ||
435 | GNUNET_MULTICAST_member_join (cfg, | ||
436 | &group_pub_key, | ||
437 | multicast_peer->key, | ||
438 | multicast_peers[0]->id, | ||
439 | 0, | ||
440 | NULL, | ||
441 | join_msg, /* join message */ | ||
442 | member_join_request, | ||
443 | member_join_decision, | ||
444 | member_replay_frag, | ||
445 | member_replay_msg, | ||
446 | member_message, | ||
447 | cls); | ||
448 | return members[multicast_peer->peer]; | ||
449 | } | ||
450 | } | ||
451 | |||
452 | |||
453 | static void | ||
454 | peer_information_cb (void *cls, | ||
455 | struct GNUNET_TESTBED_Operation *operation, | ||
456 | const struct GNUNET_TESTBED_PeerInformation *pinfo, | ||
457 | const char *emsg) | ||
458 | { | ||
459 | struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls; | ||
460 | |||
461 | if (NULL == pinfo) { | ||
462 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got no peer information\n"); | ||
463 | result = GNUNET_SYSERR; | ||
464 | GNUNET_SCHEDULER_shutdown (); | ||
465 | } | ||
466 | |||
467 | multicast_peers[mc_peer->peer]->id = pinfo->result.id; | ||
468 | |||
469 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
470 | "Got peer information of %s (%s)\n", | ||
471 | (0 == mc_peer->peer)? "origin" : "member", | ||
472 | GNUNET_i2s (pinfo->result.id)); | ||
473 | |||
474 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
475 | "Create peer #%u (%s)\n", | ||
476 | mc_peer->peer, | ||
477 | GNUNET_i2s (multicast_peers[mc_peer->peer]->id)); | ||
478 | |||
479 | if (0 != mc_peer->peer) | ||
480 | { | ||
481 | /* connect to multicast service of members */ | ||
482 | op[mc_peer->peer] = | ||
483 | GNUNET_TESTBED_service_connect (/* Closure for operation */ | ||
484 | NULL, | ||
485 | /* The peer whose service to connect to */ | ||
486 | peers[mc_peer->peer], | ||
487 | /* The name of the service */ | ||
488 | "multicast", | ||
489 | /* called after a handle to service is opened */ | ||
490 | service_connect, | ||
491 | /* closure for the above callback */ | ||
492 | cls, | ||
493 | /* called when opening the service connection */ | ||
494 | multicast_connect, | ||
495 | /* called when closing the service connection */ | ||
496 | multicast_disconnect, | ||
497 | /* closure for the above two callbacks */ | ||
498 | cls); | ||
499 | } | ||
500 | } | ||
501 | |||
502 | |||
503 | static void | ||
504 | service_connect (void *cls, | ||
505 | struct GNUNET_TESTBED_Operation *op, | ||
506 | void *ca_result, | ||
507 | const char *emsg) | ||
508 | { | ||
509 | struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls; | ||
510 | |||
511 | if (NULL == ca_result) | ||
512 | { | ||
513 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
514 | "Connection adapter not created for peer #%u (%s)\n", | ||
515 | mc_peer->peer, | ||
516 | GNUNET_i2s (multicast_peers[mc_peer->peer]->id)); | ||
517 | |||
518 | result = GNUNET_SYSERR; | ||
519 | GNUNET_SCHEDULER_shutdown(); | ||
520 | } | ||
521 | |||
522 | if (0 == mc_peer->peer) | ||
523 | { | ||
524 | // Get GNUnet identity of members | ||
525 | for (int i = 0; i<PEERS_REQUESTED; i++) | ||
526 | { | ||
527 | pi_op[i] = GNUNET_TESTBED_peer_get_information (peers[i], | ||
528 | GNUNET_TESTBED_PIT_IDENTITY, | ||
529 | peer_information_cb, | ||
530 | multicast_peers[i]); | ||
531 | } | ||
532 | } | ||
533 | } | ||
534 | |||
535 | |||
536 | |||
537 | /** | ||
538 | * Main function inovked from TESTBED once all of the | ||
539 | * peers are up and running. This one then connects | ||
540 | * just to the multicast service of peer 0 and 1. | ||
541 | * Peer 0 is going to be origin. | ||
542 | * Peer 1 is going to be one member. | ||
543 | * Origin will start a multicast group and the member will try to join it. | ||
544 | * After that we execute some multicast test. | ||
545 | * | ||
546 | * @param cls closure | ||
547 | * @param h the run handle | ||
548 | * @param peers started peers for the test | ||
549 | * @param PEERS_REQUESTED size of the 'peers' array | ||
550 | * @param links_succeeded number of links between peers that were created | ||
551 | * @param links_failed number of links testbed was unable to establish | ||
552 | */ | ||
553 | static void | ||
554 | testbed_master (void *cls, | ||
555 | struct GNUNET_TESTBED_RunHandle *h, | ||
556 | unsigned int num_peers, | ||
557 | struct GNUNET_TESTBED_Peer **p, | ||
558 | unsigned int links_succeeded, | ||
559 | unsigned int links_failed) | ||
560 | { | ||
561 | /* Testbed is ready with peers running and connected in a pre-defined overlay | ||
562 | topology (FIXME) */ | ||
563 | peers = p; | ||
564 | multicast_peers = GNUNET_new_array (PEERS_REQUESTED, struct MulticastPeerContext*); | ||
565 | |||
566 | // Create test contexts for members | ||
567 | for (int i = 0; i<PEERS_REQUESTED; i++) | ||
568 | { | ||
569 | multicast_peers[i] = GNUNET_new (struct MulticastPeerContext); | ||
570 | multicast_peers[i]->peer = i; | ||
571 | multicast_peers[i]->test_ok = GNUNET_NO; | ||
572 | } | ||
573 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
574 | "Create origin peer\n"); | ||
575 | op[0] = | ||
576 | GNUNET_TESTBED_service_connect (/* Closure for operation */ | ||
577 | NULL, | ||
578 | /* The peer whose service to connect to */ | ||
579 | peers[0], | ||
580 | /* The name of the service */ | ||
581 | "multicast", | ||
582 | /* called after a handle to service is opened */ | ||
583 | service_connect, | ||
584 | /* closure for the above callback */ | ||
585 | multicast_peers[0], | ||
586 | /* called when opening the service connection */ | ||
587 | multicast_connect, | ||
588 | /* called when closing the service connection */ | ||
589 | multicast_disconnect, | ||
590 | /* closure for the above two callbacks */ | ||
591 | multicast_peers[0]); | ||
592 | /* Schedule a new task on shutdown */ | ||
593 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); | ||
594 | /* Schedule the shutdown task with a delay of a few Seconds */ | ||
595 | timeout_tid = | ||
596 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
597 | (GNUNET_TIME_UNIT_SECONDS, 400), | ||
598 | &timeout_task, | ||
599 | NULL); | ||
600 | } | ||
601 | |||
602 | |||
603 | int | ||
604 | main (int argc, char *argv[]) | ||
605 | { | ||
606 | int ret; | ||
607 | char const *config_file; | ||
608 | |||
609 | if (strstr (argv[0], "_line") != NULL) | ||
610 | { | ||
611 | config_file = "test_multicast_line.conf"; | ||
612 | } | ||
613 | else if (strstr(argv[0], "_star") != NULL) | ||
614 | { | ||
615 | config_file = "test_multicast_star.conf"; | ||
616 | } | ||
617 | else | ||
618 | { | ||
619 | config_file = "test_multicast_star.conf"; | ||
620 | } | ||
621 | |||
622 | result = GNUNET_SYSERR; | ||
623 | ret = | ||
624 | GNUNET_TESTBED_test_run ("test-multicast-multipeer", | ||
625 | config_file, | ||
626 | /* number of peers to start */ | ||
627 | PEERS_REQUESTED, | ||
628 | /* Event mask - set to 0 for no event notifications */ | ||
629 | 0LL, | ||
630 | /* Controller event callback */ | ||
631 | NULL, | ||
632 | /* Closure for controller event callback */ | ||
633 | NULL, | ||
634 | /* called when testbed setup is complete */ | ||
635 | testbed_master, | ||
636 | /* Closure for the test_master callback */ | ||
637 | NULL); | ||
638 | if ( (GNUNET_OK != ret) || (GNUNET_OK != result) ) | ||
639 | return 1; | ||
640 | return 0; | ||
641 | } | ||
642 | |||
643 | /* end of test_multicast_multipeer.c */ | ||
diff --git a/src/multicast/test_multicast_star.conf b/src/multicast/test_multicast_star.conf deleted file mode 100644 index 516c0e302..000000000 --- a/src/multicast/test_multicast_star.conf +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | [testbed] | ||
2 | HOSTNAME = localhost | ||
3 | OVERLAY_TOPOLOGY = STAR | ||
4 | |||
5 | [arm] | ||
6 | GLOBAL_POSTFIX=-L ERROR | ||
7 | |||
8 | [multicast] | ||
9 | #PREFIX = tmux new-window gdb -x ./cmd.gdb --args | ||
10 | #PREFIX = valgrind --leak-check=full | ||
11 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock | ||
12 | |||
13 | [vpn] | ||
14 | START_ON_DEMAND = NO | ||
15 | |||
16 | [peerinfo] | ||
17 | # Do not use shipped gnunet HELLOs | ||
18 | USE_INCLUDED_HELLOS = NO | ||
19 | |||
20 | # Option to disable all disk IO; only useful for testbed runs | ||
21 | # (large-scale experiments); disables persistence of HELLOs! | ||
22 | NO_IO = YES | ||
23 | |||
24 | [cadet] | ||
25 | ID_ANNOUNCE_TIME = 5 s | ||
26 | |||
27 | [hostlist] | ||
28 | IMMEDIATE_START = NO | ||
29 | START_ON_DEMAND = NO | ||
30 | |||
31 | [nat] | ||
32 | ENABLE_UPNP = NO | ||
33 | |||
34 | [fs] | ||
35 | IMMEDIATE_START = NO | ||
36 | START_ON_DEMAND = NO | ||
37 | |||
38 | [vpn] | ||
39 | IMMEDIATE_START = NO | ||
40 | START_ON_DEMAND = NO | ||
41 | |||
42 | [revocation] | ||
43 | IMMEDIATE_START = NO | ||
44 | START_ON_DEMAND = NO | ||
45 | |||
46 | [gns] | ||
47 | IMMEDIATE_START = NO | ||
48 | START_ON_DEMAND = NO | ||
49 | |||
50 | [namestore] | ||
51 | IMMEDIATE_START = NO | ||
52 | START_ON_DEMAND = NO | ||
53 | |||
54 | [namecache] | ||
55 | IMMEDIATE_START = NO | ||
56 | START_ON_DEMAND = NO | ||
57 | |||
58 | [topology] | ||
59 | IMMEDIATE_START = NO | ||
60 | START_ON_DEMAND = NO | ||
61 | |||
62 | [nse] | ||
63 | WORKBITS = 0 | ||
64 | |||