aboutsummaryrefslogtreecommitdiff
path: root/src/testing/testing_api_cmd_netjail_start_testsystem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing/testing_api_cmd_netjail_start_testsystem.c')
-rw-r--r--src/testing/testing_api_cmd_netjail_start_testsystem.c541
1 files changed, 541 insertions, 0 deletions
diff --git a/src/testing/testing_api_cmd_netjail_start_testsystem.c b/src/testing/testing_api_cmd_netjail_start_testsystem.c
new file mode 100644
index 000000000..5c2f71168
--- /dev/null
+++ b/src/testing/testing_api_cmd_netjail_start_testsystem.c
@@ -0,0 +1,541 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_cmd_hello_world.c
23 * @brief Command to start the netjail peers.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_ng_lib.h"
28#include "testing_cmds.h"
29
30#define NETJAIL_EXEC_SCRIPT "./../testing/netjail_exec.sh"
31
32struct HelperMessage;
33
34struct HelperMessage
35{
36
37 struct HelperMessage *next;
38
39 struct HelperMessage *prev;
40
41 /**
42 * Size of the original message.
43 */
44 uint16_t bytes_msg;
45
46 /* Followed by @e bytes_msg of msg.*/
47};
48
49
50
51struct NetJailState
52{
53
54 unsigned int *rv;
55
56 struct HelperMessage *hp_messages_head;
57
58 struct HelperMessage *hp_messages_tail;
59
60 /**
61 * The process handle
62 */
63 struct GNUNET_HELPER_Handle **helper;
64
65 unsigned int n_helper;
66
67 char *binary_name;
68
69 char *local_m;
70
71 char *global_n;
72
73 /**
74 * The send handle for the helper
75 */
76 struct GNUNET_HELPER_SendHandle **shandle;
77
78 unsigned int n_shandle;
79
80 /**
81 * The message corresponding to send handle
82 */
83 struct GNUNET_MessageHeader **msg;
84
85 unsigned int n_msg;
86
87 unsigned int number_of_testsystems_started;
88
89 unsigned int number_of_peers_started;
90
91 unsigned int number_of_local_test_finished;
92
93 char *plugin_name;
94};
95
96struct TestingSystemCount
97{
98 unsigned int count;
99
100 struct NetJailState *ns;
101};
102
103/**
104*
105*
106* @param cls closure
107* @param cmd current CMD being cleaned up.
108*/
109static void
110netjail_exec_cleanup (void *cls,
111 const struct GNUNET_TESTING_Command *cmd)
112{
113 struct NetJailState *ns = cls;
114
115 GNUNET_free (ns->binary_name);
116}
117
118
119/**
120*
121*
122* @param cls closure.
123* @param[out] ret result
124* @param trait name of the trait.
125* @param index index number of the object to offer.
126* @return #GNUNET_OK on success.
127*/
128static int
129netjail_exec_traits (void *cls,
130 const void **ret,
131 const char *trait,
132 unsigned int index)
133{
134 struct NetJailState *ns = cls;
135 struct GNUNET_HELPER_Handle **helper = ns->helper;
136 struct HelperMessage *hp_messages_head = ns->hp_messages_head;
137
138
139 struct GNUNET_TESTING_Trait traits[] = {
140 {
141 .index = 0,
142 .trait_name = "helper_handles",
143 .ptr = (const void *) helper,
144 },
145 {
146 .index = 1,
147 .trait_name = "hp_msgs_head",
148 .ptr = (const void *) hp_messages_head,
149 },
150 GNUNET_TESTING_trait_end ()
151 };
152
153 return GNUNET_TESTING_get_trait (traits,
154 ret,
155 trait,
156 index);
157}
158
159
160/**
161 * Offer handles to testing cmd helper from trait
162 *
163 * @param cmd command to extract the message from.
164 * @param pt pointer to message.
165 * @return #GNUNET_OK on success.
166 */
167int
168GNUNET_TESTING_get_trait_helper_handles (const struct
169 GNUNET_TESTING_Command *cmd,
170 struct GNUNET_HELPER_Handle ***helper)
171{
172 return cmd->traits (cmd->cls,
173 (const void **) helper,
174 "helper_handles",
175 (unsigned int) 0);
176}
177
178/**
179 * Offer messages received via testing cmd helper from trait
180 *
181 * @param cmd command to extract the message from.
182 * @param pt pointer to message.
183 * @return #GNUNET_OK on success.
184 */
185int
186GNUNET_TESTING_get_trait_helper_messages (const struct
187 GNUNET_TESTING_Command *cmd,
188 struct HelperMessage ***
189 hp_messages_head)
190{
191 return cmd->traits (cmd->cls,
192 (const void **) hp_messages_head,
193 "hp_msgs_head",
194 (unsigned int) 1);
195}
196
197
198/**
199 * Continuation function from GNUNET_HELPER_send()
200 *
201 * @param cls closure
202 * @param result GNUNET_OK on success,
203 * GNUNET_NO if helper process died
204 * GNUNET_SYSERR during GNUNET_HELPER_stop
205 */
206static void
207clear_msg (void *cls, int result)
208{
209 struct TestingSystemCount *tbc = cls;
210 struct NetJailState *ns = tbc->ns;
211
212 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
213 "clear_msg tbc->count: %d\n",
214 tbc->count);
215 GNUNET_assert (NULL != ns->shandle[tbc->count - 1]);
216 ns->shandle[tbc->count - 1] = NULL;
217 GNUNET_free (ns->msg[tbc->count - 1]);
218 ns->msg[tbc->count - 1] = NULL;
219}
220
221
222/**
223 * Functions with this signature are called whenever a
224 * complete message is received by the tokenizer.
225 *
226 * Do not call GNUNET_SERVER_mst_destroy in callback
227 *
228 * @param cls closure
229 * @param client identification of the client
230 * @param message the actual message
231 *
232 * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
233 */
234static int
235helper_mst (void *cls, const struct GNUNET_MessageHeader *message)
236{
237 struct TestingSystemCount *tbc = cls;
238 struct NetJailState *ns = tbc->ns;
239 struct HelperMessage *hp_msg;
240
241 if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY == ntohs (message->type))
242 {
243 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
244 "helper_mst tbc->count: %d\n",
245 tbc->count);
246 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
247 "Received message from helper.\n");
248 ns->number_of_testsystems_started++;
249 }
250 else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED == ntohs (
251 message->type))
252 {
253 ns->number_of_peers_started++;
254 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
255 "number_of_peers_started: %d\n",
256 ns->number_of_peers_started);
257 }
258 else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED == ntohs (
259 message->type))
260 {
261 ns->number_of_local_test_finished++;
262 }
263 else
264 {
265 hp_msg = GNUNET_new (struct HelperMessage);
266 hp_msg->bytes_msg = message->size;
267 memcpy (&hp_msg[1], message, message->size);
268 GNUNET_CONTAINER_DLL_insert (ns->hp_messages_head, ns->hp_messages_tail,
269 hp_msg);
270 }
271
272 return GNUNET_OK;
273}
274
275
276static void
277exp_cb (void *cls)
278{
279 struct NetJailState *ns = cls;
280 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called exp_cb.\n");
281 *ns->rv = 1;
282}
283
284
285static struct GNUNET_CMDS_HelperInit *
286create_helper_init_msg_ (char *m_char,
287 char *n_char,
288 const char *plugin_name)
289{
290 struct GNUNET_CMDS_HelperInit *msg;
291 uint16_t plugin_name_len;
292 uint16_t msg_size;
293
294 GNUNET_assert (NULL != plugin_name);
295 plugin_name_len = strlen (plugin_name);
296 msg_size = sizeof(struct GNUNET_CMDS_HelperInit) + plugin_name_len;
297 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
298 "msg_size: %d \n",
299 msg_size);
300 msg = GNUNET_malloc (msg_size);
301 msg->header.size = htons (msg_size);
302 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT);
303 msg->plugin_name_size = htons (plugin_name_len);
304 GNUNET_memcpy ((char *) &msg[1],
305 plugin_name,
306 plugin_name_len);
307 return msg;
308}
309
310
311static void
312start_helper (struct NetJailState *ns, struct
313 GNUNET_CONFIGURATION_Handle *config,
314 char *m_char,
315 char *n_char)
316{
317 // struct GNUNET_CONFIGURATION_Handle *cfg;
318 struct GNUNET_CMDS_HelperInit *msg;
319 struct TestingSystemCount *tbc;
320 char *const script_argv[] = {NETJAIL_EXEC_SCRIPT,
321 m_char,
322 n_char,
323 GNUNET_OS_get_libexec_binary_path (
324 HELPER_CMDS_BINARY),
325 ns->global_n,
326 ns->local_m,
327 NULL};
328 unsigned int m = atoi (m_char);
329 unsigned int n = atoi (n_char);
330 unsigned int helper_check = GNUNET_OS_check_helper_binary (
331 NETJAIL_EXEC_SCRIPT,
332 GNUNET_YES,
333 NULL);
334
335 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
336 "m: %d n: %d\n",
337 m,
338 n);
339
340 tbc = GNUNET_new (struct TestingSystemCount);
341 tbc->ns = ns;
342 tbc->count = (n - 1) * atoi (ns->local_m) + m;
343
344
345 if (GNUNET_NO == helper_check)
346 {
347 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
348 "No SUID for %s!\n",
349 NETJAIL_EXEC_SCRIPT);
350 *ns->rv = 1;
351 }
352 else if (GNUNET_NO == helper_check)
353 {
354 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
355 "%s not found!\n",
356 NETJAIL_EXEC_SCRIPT);
357 *ns->rv = 1;
358 }
359
360 GNUNET_array_append (ns->helper, ns->n_helper, GNUNET_HELPER_start (
361 GNUNET_YES,
362 NETJAIL_EXEC_SCRIPT,
363 script_argv,
364 &helper_mst,
365 &exp_cb,
366 tbc));
367
368 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
369 "First using helper %d %d\n",
370 tbc->count - 1,
371 ns->n_helper);
372 struct GNUNET_HELPER_Handle *helper = ns->helper[tbc->count - 1];
373
374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
375 "First using helper %d %d %p\n",
376 tbc->count - 1,
377 ns->n_helper,
378 helper);
379
380 msg = create_helper_init_msg_ (m_char,
381 n_char,
382 ns->plugin_name);
383 GNUNET_array_append (ns->msg, ns->n_msg, &msg->header);
384
385 GNUNET_array_append (ns->shandle, ns->n_shandle, GNUNET_HELPER_send (
386 helper,
387 &msg->header,
388 GNUNET_NO,
389 &clear_msg,
390 tbc));
391
392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
393 "Message %d send!\n",
394 tbc->count);
395
396 if (NULL == ns->shandle[tbc->count - 1])
397 {
398 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
399 "Send handle is NULL!\n");
400 GNUNET_free (msg);
401 *ns->rv = 1;
402 }
403}
404
405
406/**
407* Run the "hello world" CMD.
408*
409* @param cls closure.
410* @param cmd CMD being run.
411* @param is interpreter state.
412*/
413static void
414netjail_exec_run (void *cls,
415 const struct GNUNET_TESTING_Command *cmd,
416 struct GNUNET_TESTING_Interpreter *is)
417{
418 char str_m[12];
419 char str_n[12];
420 struct NetJailState *ns = cls;
421 struct GNUNET_CONFIGURATION_Handle *config =
422 GNUNET_CONFIGURATION_create ();
423
424 for (int i = 1; i <= atoi (ns->global_n); i++) {
425 for (int j = 1; j <= atoi (ns->local_m); j++)
426 {
427 sprintf (str_n, "%d", i);
428 sprintf (str_m, "%d", j);
429 start_helper (ns, config,
430 str_m,
431 str_n);
432 }
433 }
434}
435
436
437static int
438netjail_start_finish (void *cls,
439 GNUNET_SCHEDULER_TaskCallback cont,
440 void *cont_cls)
441{
442 unsigned int ret = GNUNET_NO;
443 struct NetJailState *ns = cls;
444 unsigned int total_number = atoi (ns->local_m) * atoi (ns->global_n);
445 struct GNUNET_CMDS_ALL_PEERS_STARTED *reply;
446 size_t msg_length;
447 struct GNUNET_HELPER_Handle *helper;
448 struct TestingSystemCount *tbc;
449
450 if (ns->number_of_local_test_finished == total_number)
451 {
452 ret = GNUNET_YES;
453 cont (cont_cls);
454 }
455
456 if (ns->number_of_testsystems_started == total_number)
457 {
458 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
459 "All helpers started!\n");
460 ns->number_of_testsystems_started = 0;
461 }
462
463 if (ns->number_of_peers_started == total_number)
464 {
465 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
466 "All peers started!\n");
467
468 for (int i = 1; i <= atoi (ns->global_n); i++) {
469 for (int j = 1; j <= atoi (ns->local_m); j++)
470 {
471 tbc = GNUNET_new (struct TestingSystemCount);
472 tbc->ns = ns;
473 // TODO This needs to be more generic. As we send more messages back and forth, we can not grow the arrays again and again, because this is to error prone.
474 tbc->count = (i - 1) * atoi (ns->local_m) + j + total_number;
475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
476 "Second using helper %d %d %d\n",
477 tbc->count - 1 - total_number,
478 i,
479 j);
480 helper = ns->helper[tbc->count - 1 - total_number];
481 msg_length = sizeof(struct GNUNET_CMDS_ALL_PEERS_STARTED);
482 reply = GNUNET_new (struct GNUNET_CMDS_ALL_PEERS_STARTED);
483 reply->header.type = htons (
484 GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED);
485 reply->header.size = htons ((uint16_t) msg_length);
486
487 GNUNET_array_append (ns->msg, ns->n_msg, &reply->header);
488
489 struct GNUNET_HELPER_SendHandle *sh = GNUNET_HELPER_send (
490 helper,
491 &reply->header,
492 GNUNET_NO,
493 &clear_msg,
494 tbc);
495
496 GNUNET_array_append (ns->shandle, ns->n_shandle, sh);
497
498 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
499 "All peers started message %d send!\n",
500 tbc->count);
501 }
502 }
503 ns->number_of_peers_started = 0;
504 }
505 return ret;
506}
507
508
509/**
510 * Create command.
511 *
512 * @param label name for command.
513 * @param binaryname to exec.
514 * @return command.
515 */
516struct GNUNET_TESTING_Command
517GNUNET_TESTING_cmd_netjail_start_testing_system (const char *label,
518 char *local_m,
519 char *global_n,
520 char *plugin_name,
521 unsigned int *rv)
522{
523 struct NetJailState *ns;
524
525 ns = GNUNET_new (struct NetJailState);
526 ns->local_m = local_m;
527 ns->global_n = global_n;
528 ns->plugin_name = plugin_name;
529 ns->rv = rv;
530
531 struct GNUNET_TESTING_Command cmd = {
532 .cls = ns,
533 .label = label,
534 .run = &netjail_exec_run,
535 .finish = &netjail_start_finish,
536 .cleanup = &netjail_exec_cleanup,
537 .traits = &netjail_exec_traits
538 };
539
540 return cmd;
541}