aboutsummaryrefslogtreecommitdiff
path: root/src/service/testing/testing_api_cmd_netjail_start_cmds_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/testing/testing_api_cmd_netjail_start_cmds_helper.c')
-rw-r--r--src/service/testing/testing_api_cmd_netjail_start_cmds_helper.c917
1 files changed, 917 insertions, 0 deletions
diff --git a/src/service/testing/testing_api_cmd_netjail_start_cmds_helper.c b/src/service/testing/testing_api_cmd_netjail_start_cmds_helper.c
new file mode 100644
index 000000000..792d7a8cf
--- /dev/null
+++ b/src/service/testing/testing_api_cmd_netjail_start_cmds_helper.c
@@ -0,0 +1,917 @@
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 "gnunet_testing_plugin.h"
29#include "gnunet_testing_barrier.h"
30#include "gnunet_testing_netjail_lib.h"
31#include "testing.h"
32#include "testing_cmds.h"
33
34#define NETJAIL_EXEC_SCRIPT "netjail_exec.sh"
35
36#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
37
38/**
39 * Generic logging shortcut
40 */
41#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
42
43/**
44 * Struct to store messages send/received by the helper into a DLL
45 *
46 */
47struct HelperMessage
48{
49
50 /**
51 * Kept in a DLL.
52 */
53 struct HelperMessage *next;
54
55 /**
56 * Kept in a DLL.
57 */
58 struct HelperMessage *prev;
59
60 /**
61 * Size of the original message.
62 */
63 uint16_t bytes_msg;
64
65 /* Followed by @e bytes_msg of msg.*/
66};
67
68
69/**
70 * Struct to store information handed over to callbacks.
71 *
72 */
73struct NetJailState
74{
75 /**
76 * Global state of the interpreter, used by a command
77 * to access information about other commands.
78 */
79 struct GNUNET_TESTING_Interpreter *is;
80
81 /**
82 * Context for our asynchronous completion.
83 */
84 struct GNUNET_TESTING_AsyncContext ac;
85
86 /**
87 * The complete topology information.
88 */
89 struct GNUNET_TESTING_NetjailTopology *topology;
90
91 /**
92 * Array with handles of helper processes.
93 */
94 const struct GNUNET_HELPER_Handle **helper;
95
96 /**
97 * Size of the array NetJailState#helper.
98 *
99 */
100 unsigned int n_helper;
101
102 /**
103 * Number of nodes in a natted subnet.
104 *
105 */
106 unsigned int local_m;
107
108 /**
109 * Number of natted subnets.
110 *
111 */
112 unsigned int global_n;
113
114 /**
115 * Number of global known nodes.
116 *
117 */
118 unsigned int known;
119
120
121 /**
122 * Number of test environments started.
123 *
124 */
125 unsigned int number_of_testsystems_started;
126
127 /**
128 * Number of peers started.
129 *
130 */
131 unsigned int number_of_peers_started;
132
133 /**
134 * Number of local tests finished.
135 *
136 */
137 unsigned int number_of_local_tests_finished;
138
139 /**
140 * Number of local tests prepared to finish.
141 *
142 */
143 unsigned int number_of_local_tests_prepared;
144
145 /**
146 * Name of the test case plugin the helper will load.
147 *
148 */
149 char *plugin_name;
150
151 /**
152 * Shall we read the topology from file, or from a string.
153 */
154 unsigned int *read_file;
155
156 /**
157 * String with topology data or name of topology file.
158 */
159 char *topology_data;
160
161 /**
162 * Time after this cmd has to finish.
163 */
164 struct GNUNET_TIME_Relative timeout;
165
166 /**
167 * Timeout task.
168 */
169 struct GNUNET_SCHEDULER_Task *timeout_task;
170};
171
172/**
173 * Struct containing the number of the netjail node and the NetJailState which
174 * will be handed to callbacks specific to a test environment.
175 */
176struct TestingSystemCount
177{
178 /**
179 * The plugin correlated to this netjail node.
180 */
181 struct TestcasePlugin *plugin;
182
183 /**
184 * Kept in a DLL.
185 */
186 struct TestingSystemCount *next;
187
188 /**
189 * Kept in a DLL.
190 */
191 struct TestingSystemCount *prev;
192
193 /**
194 * The send handle for the helper
195 */
196 struct GNUNET_HELPER_SendHandle *shandle;
197
198 /**
199 * Struct to store information handed over to callbacks.
200 *
201 */
202 struct NetJailState *ns;
203
204 /**
205 * The messages send to the helper.
206 */
207 struct GNUNET_MessageHeader *msg;
208};
209
210
211/**
212* Code to clean up resource this cmd used.
213*
214* @param cls closure
215*/
216static void
217netjail_exec_cleanup (void *cls)
218{
219 struct NetJailState *ns = cls;
220 GNUNET_free (ns);
221}
222
223
224/**
225 * This function prepares an array with traits.
226 *
227 */
228static enum GNUNET_GenericReturnValue
229netjail_exec_traits (void *cls,
230 const void **ret,
231 const char *trait,
232 unsigned int index)
233{
234 struct NetJailState *ns = cls;
235 const struct GNUNET_HELPER_Handle **helper = ns->helper;
236
237
238 struct GNUNET_TESTING_Trait traits[] = {
239 GNUNET_TESTING_make_trait_helper_handles (helper),
240 GNUNET_TESTING_trait_end ()
241 };
242
243 return GNUNET_TESTING_get_trait (traits,
244 ret,
245 trait,
246 index);
247}
248
249
250/**
251 * Continuation function from GNUNET_HELPER_send()
252 *
253 * @param cls closure
254 * @param result GNUNET_OK on success,
255 * GNUNET_NO if helper process died
256 * GNUNET_SYSERR during GNUNET_HELPER_stop
257 */
258static void
259clear_msg (void *cls, int result)
260{
261 struct TestingSystemCount *tbc = cls;
262
263 GNUNET_assert (NULL != tbc->shandle);
264 // GNUNET_free (tbc->shandle);
265 GNUNET_free (tbc->plugin);
266 tbc->shandle = NULL;
267 GNUNET_free (tbc);
268}
269
270
271static void
272send_message_to_locals (
273 unsigned int i,
274 unsigned int j,
275 struct NetJailState *ns,
276 struct GNUNET_MessageHeader *header
277 )
278{
279 const struct GNUNET_HELPER_Handle *helper;
280 struct TestingSystemCount *tbc;
281 unsigned int count;
282
283 LOG (GNUNET_ERROR_TYPE_DEBUG,
284 "send message of type %u to locals\n",
285 header->type);
286 tbc = GNUNET_new (struct TestingSystemCount);
287 tbc->ns = ns;
288 if (0 == i)
289 count = j;
290 else
291 count = (i - 1) * ns->local_m + j + ns->known;
292
293 helper = ns->helper[count - 1];
294
295
296 struct GNUNET_HELPER_SendHandle *sh = GNUNET_HELPER_send (
297 (struct GNUNET_HELPER_Handle *) helper,
298 header,
299 GNUNET_NO,
300 &clear_msg,
301 tbc);
302
303 tbc->shandle = sh;
304}
305
306
307static void
308send_all_local_tests_prepared (unsigned int i, unsigned int j, struct
309 NetJailState *ns)
310{
311 struct GNUNET_TESTING_CommandAllLocalTestsPrepared *reply;
312 size_t msg_length;
313
314
315 msg_length = sizeof(struct GNUNET_TESTING_CommandAllLocalTestsPrepared);
316 reply = GNUNET_new (struct GNUNET_TESTING_CommandAllLocalTestsPrepared);
317 reply->header.type = htons (
318 GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_LOCAL_TESTS_PREPARED);
319 reply->header.size = htons ((uint16_t) msg_length);
320
321 send_message_to_locals (i, j, ns, &reply->header);
322 GNUNET_free (reply);
323}
324
325
326static void
327send_all_peers_started (unsigned int i, unsigned int j, struct NetJailState *ns)
328{
329 struct GNUNET_TESTING_CommandAllPeersStarted *reply;
330 size_t msg_length;
331
332 msg_length = sizeof(struct GNUNET_TESTING_CommandAllPeersStarted);
333 reply = GNUNET_new (struct GNUNET_TESTING_CommandAllPeersStarted);
334 reply->header.type = htons (
335 GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED);
336 reply->header.size = htons ((uint16_t) msg_length);
337
338 send_message_to_locals (i, j, ns, &reply->header);
339 GNUNET_free (reply);
340}
341
342
343void
344barrier_attached (struct NetJailState *ns, const struct
345 GNUNET_MessageHeader *message)
346{
347 struct CommandBarrierAttached *am;
348 struct GNUNET_TESTING_NetjailNode *node;
349 struct GNUNET_TESTING_Barrier *barrier;
350 struct GNUNET_ShortHashCode key;
351 struct GNUNET_HashCode hc;
352 const char *barrier_name;
353
354 am = (struct CommandBarrierAttached *) message;
355 barrier_name = (const char *) &am[1];
356 barrier = GNUNET_TESTING_get_barrier_ (ns->is,
357 barrier_name);
358 GNUNET_assert (NULL != barrier);
359 node = GNUNET_TESTING_barrier_get_node (barrier,
360 am->node_number);
361 if (NULL == node)
362 {
363 node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
364 node->node_number = am->node_number;
365
366 GNUNET_CRYPTO_hash (&(node->node_number), sizeof(node->node_number), &hc);
367 memcpy (&key, &hc, sizeof (key));
368 GNUNET_CONTAINER_multishortmap_put (barrier->nodes,
369 &key,
370 node,
371 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
372 }
373 node->expected_reaches = node->expected_reaches + am->expected_reaches;
374 barrier->expected_reaches = barrier->expected_reaches + am->expected_reaches;
375}
376
377
378void
379barrier_reached (struct NetJailState *ns,
380 const struct GNUNET_MessageHeader *message)
381{
382 struct GNUNET_TESTING_Barrier *barrier;
383 const char *barrier_name;
384 const struct GNUNET_TESTING_CommandBarrierReached *rm;
385
386 rm = (const struct GNUNET_TESTING_CommandBarrierReached *) message;
387 barrier_name = (const char *) &rm[1];
388 barrier = GNUNET_TESTING_get_barrier_ (ns->is,
389 barrier_name);
390 GNUNET_assert (NULL != barrier);
391 LOG (GNUNET_ERROR_TYPE_DEBUG,
392 "barrier %s reached %p %u\n",
393 barrier_name,
394 barrier,
395 barrier->reached);
396 barrier->reached++;
397 LOG (GNUNET_ERROR_TYPE_DEBUG,
398 "%u %p\n",
399 barrier->reached,
400 barrier);
401 if (GNUNET_TESTING_barrier_crossable_ (barrier))
402 {
403 LOG (GNUNET_ERROR_TYPE_DEBUG,
404 "%s can be crossed\n",
405 barrier_name);
406 GNUNET_TESTING_finish_barrier_ (ns->is,
407 barrier->name);
408 }
409 LOG (GNUNET_ERROR_TYPE_DEBUG,
410 "barrier %s reached finished\n",
411 barrier_name);
412}
413
414
415/**
416 * Functions with this signature are called whenever a
417 * complete message is received by the tokenizer.
418 *
419 * Do not call GNUNET_SERVER_mst_destroy in callback
420 *
421 * @param cls closure
422 * @param client identification of the client
423 * @param message the actual message
424 *
425 * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
426 */
427static int
428helper_mst (void *cls, const struct GNUNET_MessageHeader *message)
429{
430 struct NetJailState *ns = cls;
431 unsigned int total_number = ns->local_m * ns->global_n + ns->known;
432 uint16_t message_type = ntohs (message->type);
433 struct GNUNET_TESTING_CommandLocalFinished *lf;
434
435 switch (message_type)
436 {
437 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_BARRIER_ATTACHED:
438 barrier_attached (ns, message);
439 break;
440 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_BARRIER_REACHED:
441 barrier_reached (ns, message);
442 break;
443 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY:
444 ns->number_of_testsystems_started++;
445 break;
446 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED:
447 ns->number_of_peers_started++;
448 if (ns->number_of_peers_started == total_number)
449 {
450 for (int i = 1; i <= ns->known; i++)
451 {
452 send_all_peers_started (0,i, ns);
453 }
454 for (int i = 1; i <= ns->global_n; i++)
455 {
456 for (int j = 1; j <= ns->local_m; j++)
457 {
458 send_all_peers_started (i,j, ns);
459 }
460 }
461 ns->number_of_peers_started = 0;
462 }
463 break;
464 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_TEST_PREPARED:
465 ns->number_of_local_tests_prepared++;
466 if (ns->number_of_local_tests_prepared == total_number)
467 {
468 for (int i = 1; i <= ns->known; i++)
469 {
470 send_all_local_tests_prepared (0,i, ns);
471 }
472
473 for (int i = 1; i <= ns->global_n; i++)
474 {
475 for (int j = 1; j <= ns->local_m; j++)
476 {
477 send_all_local_tests_prepared (i,j, ns);
478 }
479 }
480 }
481 break;
482 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED:
483 lf = (struct GNUNET_TESTING_CommandLocalFinished *) message;
484
485 ns->number_of_local_tests_finished++;
486 if (GNUNET_OK != lf->rv)
487 {
488 GNUNET_TESTING_async_fail (&(ns->ac));
489 }
490 else if (ns->number_of_local_tests_finished == total_number)
491 {
492 GNUNET_SCHEDULER_cancel (ns->timeout_task);
493 ns->timeout_task = NULL;
494 GNUNET_TESTING_async_finish (&ns->ac);
495 }
496 break;
497 default:
498 // We received a message we can not handle.
499 GNUNET_assert (0);
500 }
501
502 LOG (GNUNET_ERROR_TYPE_DEBUG,
503 "total %u sysstarted %u peersstarted %u prep %u finished %u %u %u %u\n",
504 total_number,
505 ns->number_of_testsystems_started,
506 ns->number_of_peers_started,
507 ns->number_of_local_tests_prepared,
508 ns->number_of_local_tests_finished,
509 ns->local_m,
510 ns->global_n,
511 ns->known);
512
513
514 return GNUNET_OK;
515}
516
517
518/**
519 * Callback called if there was an exception during execution of the helper.
520 *
521 */
522static void
523exp_cb (void *cls)
524{
525 struct NetJailState *ns = cls;
526
527 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called exp_cb.\n");
528 if (NULL != ns->timeout_task)
529 GNUNET_SCHEDULER_cancel (ns->timeout_task);
530 GNUNET_TESTING_async_fail (&(ns->ac));
531}
532
533
534/**
535 * Function to initialize a init message for the helper.
536 *
537 * @param plugin_name Name of the test case plugin the helper will load.
538 *
539 */
540static struct GNUNET_TESTING_CommandHelperInit *
541create_helper_init_msg_ (const char *plugin_name)
542{
543 struct GNUNET_TESTING_CommandHelperInit *msg;
544 uint16_t plugin_name_len;
545 uint16_t msg_size;
546
547 GNUNET_assert (NULL != plugin_name);
548 plugin_name_len = strlen (plugin_name);
549 msg_size = sizeof(struct GNUNET_TESTING_CommandHelperInit) + plugin_name_len;
550 msg = GNUNET_malloc (msg_size);
551 msg->header.size = htons (msg_size);
552 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT);
553 msg->plugin_name_size = htons (plugin_name_len);
554 GNUNET_memcpy ((char *) &msg[1],
555 plugin_name,
556 plugin_name_len);
557 return msg;
558}
559
560
561/**
562 * Function which start a single helper process.
563 *
564 */
565static void
566start_helper (struct NetJailState *ns,
567 unsigned int m,
568 unsigned int n)
569{
570 struct TestcasePlugin *plugin;
571 struct GNUNET_HELPER_Handle *helper;
572 struct GNUNET_TESTING_CommandHelperInit *msg;
573 struct TestingSystemCount *tbc;
574 char *m_char;
575 char *n_char;
576 char *global_n_char;
577 char *local_m_char;
578 char *known_char;
579 char *node_id;
580 char *plugin_name;
581 char *read_file;
582 pid_t pid;
583 unsigned int script_num;
584 struct GNUNET_ShortHashCode *hkey;
585 struct GNUNET_ShortHashCode key;
586 struct GNUNET_HashCode hc;
587 struct GNUNET_TESTING_NetjailTopology *topology = ns->topology;
588 struct GNUNET_TESTING_NetjailNode *node;
589 struct GNUNET_TESTING_NetjailNode *barrier_node;
590 struct GNUNET_TESTING_NetjailNamespace *namespace;
591 char *data_dir;
592 char *script_name;
593 struct GNUNET_TESTING_BarrierListEntry *pos;
594 struct GNUNET_TESTING_Barrier *barrier;
595 struct GNUNET_TESTING_BarrierList *barriers;
596 unsigned int node_num;
597 char *binary_path;
598
599 if (0 == n)
600 {
601 node_num = m;
602 script_num = m - 1;
603 }
604 else
605 {
606 node_num = (n - 1) * ns->local_m + m + ns->known;
607 script_num = n - 1 + (n - 1) * ns->local_m + m + ns->known;
608 }
609 pid = getpid ();
610
611 GNUNET_asprintf (&m_char, "%u", m);
612 GNUNET_asprintf (&n_char, "%u", n);
613 GNUNET_asprintf (&local_m_char, "%u", ns->local_m);
614 GNUNET_asprintf (&global_n_char, "%u",ns->global_n);
615 GNUNET_asprintf (&known_char, "%u",ns->known);
616 GNUNET_asprintf (&node_id, "%s%06x-%06x\n",
617 "if",
618 pid,
619 script_num);
620 // GNUNET_asprintf (&topology_data, "'%s'", ns->topology_data);
621 GNUNET_asprintf (&read_file,
622 "%u",
623 *(ns->read_file));
624
625 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
626 GNUNET_asprintf (&script_name,
627 "%s%s",
628 data_dir,
629 NETJAIL_EXEC_SCRIPT);
630 unsigned int helper_check = GNUNET_OS_check_helper_binary (
631 script_name,
632 GNUNET_YES,
633 NULL);
634
635 tbc = GNUNET_new (struct TestingSystemCount);
636 tbc->ns = ns;
637
638 if (GNUNET_NO == helper_check)
639 {
640 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
641 "No SUID for %s!\n",
642 script_name);
643 GNUNET_TESTING_interpreter_fail (ns->is);
644 // FIXME: why continue here, instead of returning?
645 }
646 else if (GNUNET_NO == helper_check)
647 {
648 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
649 "%s not found!\n",
650 script_name);
651 GNUNET_TESTING_interpreter_fail (ns->is);
652 }
653
654 binary_path = GNUNET_OS_get_libexec_binary_path (HELPER_CMDS_BINARY);
655
656 LOG (GNUNET_ERROR_TYPE_DEBUG,
657 "sysstarted %u peersstarted %u prep %u finished %u %u %u %u\n",
658 ns->number_of_testsystems_started,
659 ns->number_of_peers_started,
660 ns->number_of_local_tests_prepared,
661 ns->number_of_local_tests_finished,
662 ns->local_m,
663 ns->global_n,
664 ns->known);
665 {
666 char *const script_argv[] = {script_name,
667 m_char,
668 n_char,
669 binary_path,
670 global_n_char,
671 local_m_char,
672 node_id,
673 read_file,
674 ns->topology_data,
675 NULL};
676 helper = GNUNET_HELPER_start (
677 GNUNET_YES,
678 script_name,
679 script_argv,
680 &helper_mst,
681 &exp_cb,
682 ns);
683 GNUNET_array_append (ns->helper,
684 ns->n_helper,
685 helper);
686 }
687 GNUNET_TESTING_add_netjail_helper_ (ns->is,
688 helper);
689 plugin_name = topology->plugin;
690
691 hkey = GNUNET_new (struct GNUNET_ShortHashCode);
692 node = NULL;
693 if (0 == n)
694 {
695 GNUNET_CRYPTO_hash (&m,
696 sizeof(m),
697 &hc);
698 memcpy (hkey,
699 &hc,
700 sizeof (*hkey));
701 if (1 == GNUNET_CONTAINER_multishortmap_contains (topology->map_globals,
702 hkey))
703 {
704 node = GNUNET_CONTAINER_multishortmap_get (topology->map_globals,
705 hkey);
706 if (NULL != node->plugin)
707 plugin_name = node->plugin;
708 }
709 }
710 else
711 {
712 GNUNET_CRYPTO_hash (&n, sizeof(n), &hc);
713 memcpy (hkey,
714 &hc,
715 sizeof (*hkey));
716 if (1 == GNUNET_CONTAINER_multishortmap_contains (topology->map_namespaces,
717 hkey))
718 {
719 namespace = GNUNET_CONTAINER_multishortmap_get (topology->map_namespaces,
720 hkey);
721 GNUNET_CRYPTO_hash (&m, sizeof(m), &hc);
722 memcpy (hkey,
723 &hc,
724 sizeof (*hkey));
725 if (1 == GNUNET_CONTAINER_multishortmap_contains (namespace->nodes,
726 hkey))
727 {
728 node = GNUNET_CONTAINER_multishortmap_get (namespace->nodes,
729 hkey);
730 if (NULL != node->plugin)
731 plugin_name = node->plugin;
732 }
733 }
734
735
736 }
737 GNUNET_assert (NULL != node);
738 node->node_number = node_num;
739 plugin = GNUNET_new (struct TestcasePlugin);
740 plugin->api = GNUNET_PLUGIN_load (plugin_name,
741 NULL);
742 barriers = plugin->api->get_waiting_for_barriers ();
743
744
745 for (pos = barriers->head; NULL != pos; pos = pos->next)
746 {
747 barrier = GNUNET_TESTING_get_barrier_ (ns->is,
748 pos->barrier_name);
749 if (NULL == barrier)
750 {
751 barrier = GNUNET_new (struct GNUNET_TESTING_Barrier);
752 barrier->name = pos->barrier_name;
753 barrier->shadow = GNUNET_YES;
754 GNUNET_TESTING_add_barrier_ (ns->is,
755 barrier);
756 }
757 barrier_node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
758 barrier_node->node_number = node->node_number;
759 barrier_node->expected_reaches = pos->expected_reaches;
760 barrier->expected_reaches = barrier->expected_reaches
761 + pos->expected_reaches;
762 if (GNUNET_YES == barrier->shadow)
763 barrier->number_to_be_reached++;
764 LOG (GNUNET_ERROR_TYPE_DEBUG,
765 "Adding barrier %p %s node %u with reach target %u\n",
766 barrier,
767 pos->barrier_name,
768 node->node_number,
769 barrier->number_to_be_reached);
770 GNUNET_CRYPTO_hash (&node->node_number,
771 sizeof(node->node_number),
772 &hc);
773 memcpy (&key, &hc, sizeof (key));
774 if (NULL == barrier->nodes)
775 barrier->nodes
776 = GNUNET_CONTAINER_multishortmap_create (16,
777 GNUNET_NO);
778 GNUNET_CONTAINER_multishortmap_put (barrier->nodes,
779 &key,
780 barrier_node,
781 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
782 }
783
784 tbc->plugin = plugin;
785 msg = create_helper_init_msg_ (plugin_name);
786 tbc->shandle = GNUNET_HELPER_send (
787 helper,
788 &msg->header,
789 GNUNET_NO,
790 &clear_msg,
791 tbc);
792
793 if (NULL == tbc->shandle)
794 {
795 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
796 "Send handle is NULL!\n");
797 GNUNET_TESTING_interpreter_fail (ns->is);
798 }
799 GNUNET_free (pos);
800 GNUNET_free (binary_path);
801 GNUNET_free (hkey);
802 GNUNET_free (msg);
803 GNUNET_free (m_char);
804 GNUNET_free (n_char);
805 GNUNET_free (local_m_char);
806 GNUNET_free (global_n_char);
807 GNUNET_free (known_char);
808 GNUNET_free (node_id);
809 GNUNET_free (read_file);
810 GNUNET_free (data_dir);
811 GNUNET_free (script_name);
812 GNUNET_free (barriers);
813}
814
815
816/**
817 * Function run when the cmd terminates (good or bad) with timeout.
818 *
819 * @param cls the interpreter state
820 */
821static void
822do_timeout (void *cls)
823{
824 struct NetJailState *ns = cls;
825 struct GNUNET_TESTING_Command *cmd;
826
827 ns->timeout_task = NULL;
828 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
829 "Terminating cmd due to global timeout\n");
830 cmd = GNUNET_TESTING_interpreter_get_current_command (ns->is);
831 GNUNET_TESTING_async_finish (cmd->ac);
832}
833
834
835/**
836* This function starts a helper process for each node.
837*
838* @param cls closure.
839* @param cmd CMD being run.
840* @param is interpreter state.
841*/
842static void
843netjail_exec_run (void *cls,
844 struct GNUNET_TESTING_Interpreter *is)
845{
846 struct NetJailState *ns = cls;
847
848 ns->is = is;
849 for (int i = 1; i <= ns->known; i++)
850 {
851 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
852 "i %u\n",
853 i);
854 start_helper (ns,
855 i,
856 0);
857 }
858
859 for (int i = 1; i <= ns->global_n; i++)
860 {
861 for (int j = 1; j <= ns->local_m; j++)
862 {
863 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
864 "i %u j %u\n",
865 i,
866 j);
867 start_helper (ns,
868 j,
869 i);
870 }
871 }
872 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
873 "Adding timeout %s\n",
874 GNUNET_STRINGS_relative_time_to_string (ns->timeout, GNUNET_NO));
875 ns->timeout_task
876 = GNUNET_SCHEDULER_add_delayed (ns->timeout,
877 &do_timeout,
878 ns);
879}
880
881
882/**
883 * Create command.
884 *
885 * @param label Name for the command.
886 * @param topology The complete topology information.
887 * @param read_file Flag indicating if the the name of the topology file is send to the helper, or a string with the topology data.
888 * @param topology_data If read_file is GNUNET_NO, topology_data holds the string with the topology.
889 * @param timeout Before this timeout is reached this cmd MUST finish.
890 * @return command.
891 */
892struct GNUNET_TESTING_Command
893GNUNET_TESTING_cmd_netjail_start_cmds_helper (
894 const char *label,
895 struct GNUNET_TESTING_NetjailTopology *topology,
896 unsigned int *read_file,
897 char *topology_data,
898 struct GNUNET_TIME_Relative timeout)
899{
900 struct NetJailState *ns;
901
902 ns = GNUNET_new (struct NetJailState);
903 ns->local_m = topology->nodes_m;
904 ns->global_n = topology->namespaces_n;
905 ns->known = topology->nodes_x;
906 ns->plugin_name = topology->plugin;
907 ns->topology = topology;
908 ns->read_file = read_file;
909 ns->topology_data = topology_data;
910 ns->timeout = GNUNET_TIME_relative_subtract (timeout, TIMEOUT);
911
912 return GNUNET_TESTING_command_new (ns, label,
913 &netjail_exec_run,
914 &netjail_exec_cleanup,
915 &netjail_exec_traits,
916 &ns->ac);
917}