aboutsummaryrefslogtreecommitdiff
path: root/src/testing/testing.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing/testing.c')
-rw-r--r--src/testing/testing.c2155
1 files changed, 0 insertions, 2155 deletions
diff --git a/src/testing/testing.c b/src/testing/testing.c
deleted file mode 100644
index fcde39901..000000000
--- a/src/testing/testing.c
+++ /dev/null
@@ -1,2155 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 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.c
23 * @brief convenience API for writing testcases for GNUnet
24 * Many testcases need to start and stop a peer/service
25 * and this library is supposed to make that easier
26 * for TESTCASES. Normal programs should always
27 * use functions from gnunet_{util,arm}_lib.h. This API is
28 * ONLY for writing testcases (or internal use of the testbed).
29 * @author Christian Grothoff
30 *
31 */
32#include "platform.h"
33#include "gnunet_util_lib.h"
34#include "gnunet_arm_service.h"
35#include "gnunet_testing_lib.h"
36#include "gnunet_testing_ng_lib.h"
37
38#define LOG(kind, ...) GNUNET_log_from (kind, "testing-api", __VA_ARGS__)
39
40
41/**
42 * Lowest port used for GNUnet testing. Should be high enough to not
43 * conflict with other applications running on the hosts but be low
44 * enough to not conflict with client-ports (typically starting around
45 * 32k).
46 */
47#define LOW_PORT 12000
48
49/**
50 * Highest port used for GNUnet testing. Should be low enough to not
51 * conflict with the port range for "local" ports (client apps; see
52 * /proc/sys/net/ipv4/ip_local_port_range on Linux for example).
53 */
54#define HIGH_PORT 56000
55
56
57struct SharedServiceInstance
58{
59 struct SharedService *ss;
60
61 char *cfg_fn;
62
63 struct GNUNET_OS_Process *proc;
64
65 char *unix_sock;
66
67 char *port_str;
68
69 unsigned int n_refs;
70};
71
72struct SharedService
73{
74 char *sname;
75
76 struct SharedServiceInstance **instances;
77
78 struct GNUNET_CONFIGURATION_Handle *cfg;
79
80 unsigned int n_peers;
81
82 unsigned int share;
83
84 unsigned int n_instances;
85};
86
87
88/**
89 * Handle for a system on which GNUnet peers are executed;
90 * a system is used for reserving unique paths and ports.
91 */
92struct GNUNET_TESTING_System
93{
94 /**
95 * Prefix (e.g. "/tmp/gnunet-testing/") we prepend to each
96 * GNUNET_HOME.
97 */
98 char *tmppath;
99
100 /**
101 * The trusted ip. Can either be a single ip address or a network address in
102 * CIDR notation.
103 */
104 char *trusted_ip;
105
106 /**
107 * our hostname
108 */
109 char *hostname;
110
111 /**
112 * Hostkeys data, contains "GNUNET_TESTING_HOSTKEYFILESIZE * total_hostkeys" bytes.
113 */
114 char *hostkeys_data;
115
116 /**
117 * memory map for @e hostkeys_data.
118 */
119 struct GNUNET_DISK_MapHandle *map;
120
121 struct SharedService **shared_services;
122
123 unsigned int n_shared_services;
124
125 /**
126 * Bitmap where each port that has already been reserved for some GNUnet peer
127 * is recorded. Note that we make no distinction between TCP and UDP ports
128 * and test if a port is already in use before assigning it to a peer/service.
129 * If we detect that a port is already in use, we also mark it in this bitmap.
130 * So all the bits that are zero merely indicate ports that MIGHT be available
131 * for peers.
132 */
133 uint32_t reserved_ports[65536 / 32];
134
135 /**
136 * Counter we use to make service home paths unique on this system;
137 * the full path consists of the tmppath and this number. Each
138 * UNIXPATH for a peer is also modified to include the respective
139 * path counter to ensure uniqueness. This field is incremented
140 * by one for each configured peer. Even if peers are destroyed,
141 * we never re-use path counters.
142 */
143 uint32_t path_counter;
144
145 /**
146 * The number of hostkeys
147 */
148 uint32_t total_hostkeys;
149
150 /**
151 * Lowest port we are allowed to use.
152 */
153 uint16_t lowport;
154
155 /**
156 * Highest port we are allowed to use.
157 */
158 uint16_t highport;
159};
160
161
162/**
163 * Handle for a GNUnet peer controlled by testing.
164 */
165struct GNUNET_TESTING_Peer
166{
167 /**
168 * The TESTING system associated with this peer
169 */
170 struct GNUNET_TESTING_System *system;
171
172 /**
173 * Path to the configuration file for this peer.
174 */
175 char *cfgfile;
176
177 /**
178 * Binary to be executed during 'GNUNET_TESTING_peer_start'.
179 * Typically 'gnunet-service-arm' (but can be set to a
180 * specific service by 'GNUNET_TESTING_service_run' if
181 * necessary).
182 */
183 char *main_binary;
184 char *args;
185
186 /**
187 * Handle to the running binary of the service, NULL if the
188 * peer/service is currently not running.
189 */
190 struct GNUNET_OS_Process *main_process;
191
192 /**
193 * The handle to the peer's ARM service
194 */
195 struct GNUNET_ARM_Handle *ah;
196
197 /**
198 * The config of the peer
199 */
200 struct GNUNET_CONFIGURATION_Handle *cfg;
201
202 /**
203 * The callback to call asynchronously when a peer is stopped
204 */
205 GNUNET_TESTING_PeerStopCallback cb;
206
207 /**
208 * The closure for the above callback
209 */
210 void *cb_cls;
211
212 /**
213 * The cached identity of this peer. Will be populated on call to
214 * GNUNET_TESTING_peer_get_identity()
215 */
216 struct GNUNET_PeerIdentity *id;
217
218 struct SharedServiceInstance **ss_instances;
219
220 /**
221 * Array of ports currently allocated to this peer. These ports will be
222 * released upon peer destroy and can be used by other peers which are
223 * configured after.
224 */
225 uint16_t *ports;
226
227 /**
228 * The number of ports in the above array
229 */
230 unsigned int nports;
231
232 /**
233 * The keynumber of this peer's hostkey
234 */
235 uint32_t key_number;
236};
237
238
239/**
240 * Testing includes a number of pre-created hostkeys for faster peer
241 * startup. This function loads such keys into memory from a file.
242 *
243 * @param system the testing system handle
244 * @return #GNUNET_OK on success; #GNUNET_SYSERR on error
245 */
246static int
247hostkeys_load (struct GNUNET_TESTING_System *system)
248{
249 uint64_t fs;
250 char *data_dir;
251 char *filename;
252 struct GNUNET_DISK_FileHandle *fd;
253
254 GNUNET_assert (NULL == system->hostkeys_data);
255 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
256 GNUNET_asprintf (&filename, "%s/testing_hostkeys.ecc", data_dir);
257 GNUNET_free (data_dir);
258
259 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
260 {
261 LOG (GNUNET_ERROR_TYPE_ERROR,
262 _ ("Hostkeys file not found: %s\n"),
263 filename);
264 GNUNET_free (filename);
265 return GNUNET_SYSERR;
266 }
267 /* Check hostkey file size, read entire thing into memory */
268 if (GNUNET_OK !=
269 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
270 fs = 0;
271 if (0 == fs)
272 {
273 GNUNET_free (filename);
274 return GNUNET_SYSERR; /* File is empty */
275 }
276 if (0 != (fs % GNUNET_TESTING_HOSTKEYFILESIZE))
277 {
278 LOG (GNUNET_ERROR_TYPE_ERROR,
279 _ ("Incorrect hostkey file format: %s\n"),
280 filename);
281 GNUNET_free (filename);
282 return GNUNET_SYSERR;
283 }
284 fd = GNUNET_DISK_file_open (filename,
285 GNUNET_DISK_OPEN_READ,
286 GNUNET_DISK_PERM_NONE);
287 if (NULL == fd)
288 {
289 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
290 GNUNET_free (filename);
291 return GNUNET_SYSERR;
292 }
293 GNUNET_free (filename);
294 system->hostkeys_data =
295 GNUNET_DISK_file_map (fd, &system->map, GNUNET_DISK_MAP_TYPE_READ, fs);
296 GNUNET_DISK_file_close (fd);
297 if (NULL == system->hostkeys_data)
298 return GNUNET_SYSERR;
299 system->total_hostkeys = fs / GNUNET_TESTING_HOSTKEYFILESIZE;
300 return GNUNET_OK;
301}
302
303
304/**
305 * Function to remove the loaded hostkeys
306 *
307 * @param system the testing system handle
308 */
309static void
310hostkeys_unload (struct GNUNET_TESTING_System *system)
311{
312 GNUNET_break (NULL != system->hostkeys_data);
313 system->hostkeys_data = NULL;
314 GNUNET_DISK_file_unmap (system->map);
315 system->map = NULL;
316 system->hostkeys_data = NULL;
317 system->total_hostkeys = 0;
318}
319
320
321/**
322 * Function to iterate over options.
323 *
324 * @param cls closure
325 * @param section name of the section
326 * @param option name of the option
327 * @param value value of the option
328 */
329static void
330cfg_copy_iterator (void *cls,
331 const char *section,
332 const char *option,
333 const char *value)
334{
335 struct GNUNET_CONFIGURATION_Handle *cfg2 = cls;
336
337 GNUNET_CONFIGURATION_set_value_string (cfg2, section, option, value);
338}
339
340
341/**
342 * Create a system handle. There must only be one system
343 * handle per operating system.
344 *
345 * @param testdir only the directory name without any path. This is used for
346 * all service homes; the directory will be created in a temporary
347 * location depending on the underlying OS. This variable will be
348 * overridden with the value of the environmental variable
349 * GNUNET_TESTING_PREFIX, if it exists.
350 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
351 * service configurations generated to allow control connections from
352 * this ip. This can either be a single ip address or a network address
353 * in CIDR notation.
354 * @param hostname the hostname of the system we are using for testing; NULL for
355 * localhost
356 * @param shared_services NULL terminated array describing services that are to
357 * be shared among peers
358 * @param lowport lowest port number this system is allowed to allocate (inclusive)
359 * @param highport highest port number this system is allowed to allocate (exclusive)
360 * @return handle to this system, NULL on error
361 */
362struct GNUNET_TESTING_System *
363GNUNET_TESTING_system_create_with_portrange (
364 const char *testdir,
365 const char *trusted_ip,
366 const char *hostname,
367 const struct GNUNET_TESTING_SharedService *shared_services,
368 uint16_t lowport,
369 uint16_t highport)
370{
371 struct GNUNET_TESTING_System *system;
372 struct GNUNET_TESTING_SharedService tss;
373 struct SharedService *ss;
374 unsigned int cnt;
375
376 GNUNET_assert (NULL != testdir);
377 system = GNUNET_new (struct GNUNET_TESTING_System);
378 if (NULL == (system->tmppath = getenv (GNUNET_TESTING_PREFIX)))
379 system->tmppath = GNUNET_DISK_mkdtemp (testdir);
380 else
381 system->tmppath = GNUNET_strdup (system->tmppath);
382 system->lowport = lowport;
383 system->highport = highport;
384 if (NULL == system->tmppath)
385 {
386 GNUNET_free (system);
387 return NULL;
388 }
389 if (NULL != trusted_ip)
390 system->trusted_ip = GNUNET_strdup (trusted_ip);
391 if (NULL != hostname)
392 system->hostname = GNUNET_strdup (hostname);
393 if (GNUNET_OK != hostkeys_load (system))
394 {
395 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
396 return NULL;
397 }
398 if (NULL == shared_services)
399 return system;
400 for (cnt = 0; NULL != shared_services[cnt].service; cnt++)
401 {
402 tss = shared_services[cnt];
403 ss = GNUNET_new (struct SharedService);
404 ss->sname = GNUNET_strdup (tss.service);
405 ss->cfg = GNUNET_CONFIGURATION_create ();
406 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg,
407 ss->sname,
408 &cfg_copy_iterator,
409 ss->cfg);
410 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg,
411 "TESTING",
412 &cfg_copy_iterator,
413 ss->cfg);
414 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg,
415 "PATHS",
416 &cfg_copy_iterator,
417 ss->cfg);
418 ss->share = tss.share;
419 GNUNET_array_append (system->shared_services,
420 system->n_shared_services,
421 ss);
422 }
423 return system;
424}
425
426
427/**
428 * Create a system handle. There must only be one system handle per operating
429 * system. Uses a default range for allowed ports. Ports are still tested for
430 * availability.
431 *
432 * @param testdir only the directory name without any path. This is used for all
433 * service homes; the directory will be created in a temporary location
434 * depending on the underlying OS. This variable will be
435 * overridden with the value of the environmental variable
436 * GNUNET_TESTING_PREFIX, if it exists.
437 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
438 * service configurations generated to allow control connections from
439 * this ip. This can either be a single ip address or a network address
440 * in CIDR notation.
441 * @param hostname the hostname of the system we are using for testing; NULL for
442 * localhost
443 * @param shared_services NULL terminated array describing services that are to
444 * be shared among peers
445 * @return handle to this system, NULL on error
446 */
447struct GNUNET_TESTING_System *
448GNUNET_TESTING_system_create (
449 const char *testdir,
450 const char *trusted_ip,
451 const char *hostname,
452 const struct GNUNET_TESTING_SharedService *shared_services)
453{
454 return GNUNET_TESTING_system_create_with_portrange (testdir,
455 trusted_ip,
456 hostname,
457 shared_services,
458 LOW_PORT,
459 HIGH_PORT);
460}
461
462
463static void
464cleanup_shared_service_instance (struct SharedServiceInstance *i)
465{
466 if (NULL != i->cfg_fn)
467 {
468 (void) unlink (i->cfg_fn);
469 GNUNET_free (i->cfg_fn);
470 }
471 GNUNET_free (i->unix_sock);
472 GNUNET_free (i->port_str);
473 GNUNET_break (NULL == i->proc);
474 GNUNET_break (0 == i->n_refs);
475 GNUNET_free (i);
476}
477
478
479static int
480start_shared_service_instance (struct SharedServiceInstance *i)
481{
482 char *binary;
483 char *libexec_binary;
484
485 GNUNET_assert (NULL == i->proc);
486 GNUNET_assert (NULL != i->cfg_fn);
487 (void) GNUNET_asprintf (&binary, "gnunet-service-%s", i->ss->sname);
488 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
489 GNUNET_free (binary);
490 i->proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
491 NULL,
492 NULL,
493 NULL,
494 libexec_binary,
495 libexec_binary,
496 "-c",
497 i->cfg_fn,
498 NULL);
499 GNUNET_free (libexec_binary);
500 if (NULL == i->proc)
501 return GNUNET_SYSERR;
502 return GNUNET_OK;
503}
504
505
506static void
507stop_shared_service_instance (struct SharedServiceInstance *i)
508{
509 GNUNET_break (0 == i->n_refs);
510 if (0 != GNUNET_OS_process_kill (i->proc, GNUNET_TERM_SIG))
511 LOG (GNUNET_ERROR_TYPE_WARNING,
512 "Killing shared service instance (%s) failed\n",
513 i->ss->sname);
514 (void) GNUNET_OS_process_wait (i->proc);
515 GNUNET_OS_process_destroy (i->proc);
516 i->proc = NULL;
517}
518
519
520/**
521 * Free system resources.
522 *
523 * @param system system to be freed
524 * @param remove_paths should the 'testdir' and all subdirectories
525 * be removed (clean up on shutdown)?
526 */
527void
528GNUNET_TESTING_system_destroy (struct GNUNET_TESTING_System *system,
529 int remove_paths)
530{
531 struct SharedService *ss;
532 struct SharedServiceInstance *i;
533 unsigned int ss_cnt;
534 unsigned int i_cnt;
535
536 if (NULL != system->hostkeys_data)
537 hostkeys_unload (system);
538 for (ss_cnt = 0; ss_cnt < system->n_shared_services; ss_cnt++)
539 {
540 ss = system->shared_services[ss_cnt];
541 for (i_cnt = 0; i_cnt < ss->n_instances; i_cnt++)
542 {
543 i = ss->instances[i_cnt];
544 if (NULL != i->proc)
545 stop_shared_service_instance (i);
546 cleanup_shared_service_instance (i);
547 }
548 GNUNET_free (ss->instances);
549 GNUNET_CONFIGURATION_destroy (ss->cfg);
550 GNUNET_free (ss->sname);
551 GNUNET_free (ss);
552 }
553 GNUNET_free (system->shared_services);
554 if (GNUNET_YES == remove_paths)
555 GNUNET_DISK_directory_remove (system->tmppath);
556 GNUNET_free (system->tmppath);
557 GNUNET_free (system->trusted_ip);
558 GNUNET_free (system->hostname);
559 GNUNET_free (system);
560}
561
562
563/**
564 * Reserve a TCP or UDP port for a peer.
565 *
566 * @param system system to use for reservation tracking
567 * @return 0 if no free port was available
568 */
569uint16_t
570GNUNET_TESTING_reserve_port (struct GNUNET_TESTING_System *system)
571{
572 struct GNUNET_NETWORK_Handle *socket;
573 struct addrinfo hint;
574 struct addrinfo *ret;
575 struct addrinfo *ai;
576 uint32_t *port_buckets;
577 char *open_port_str;
578 int bind_status;
579 uint32_t xor_image;
580 uint16_t index;
581 uint16_t open_port;
582 uint16_t pos;
583
584 /*
585 FIXME: Instead of using getaddrinfo we should try to determine the port
586 status by the following heurestics.
587
588 On systems which support both IPv4 and IPv6, only ports open on both
589 address families are considered open.
590 On system with either IPv4 or IPv6. A port is considered open if it's
591 open in the respective address family
592 */hint.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
593 hint.ai_socktype = 0;
594 hint.ai_protocol = 0;
595 hint.ai_addrlen = 0;
596 hint.ai_addr = NULL;
597 hint.ai_canonname = NULL;
598 hint.ai_next = NULL;
599 hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */
600 port_buckets = system->reserved_ports;
601 for (index = (system->lowport / 32) + 1; index < (system->highport / 32);
602 index++)
603 {
604 xor_image = (UINT32_MAX ^ port_buckets[index]);
605 if (0 == xor_image) /* Ports in the bucket are full */
606 continue;
607 pos = system->lowport % 32;
608 while (pos < 32)
609 {
610 if (0 == ((xor_image >> pos) & 1U))
611 {
612 pos++;
613 continue;
614 }
615 open_port = (index * 32) + pos;
616 if (open_port >= system->highport)
617 return 0;
618 GNUNET_asprintf (&open_port_str, "%u", (unsigned int) open_port);
619 ret = NULL;
620 GNUNET_assert (0 == getaddrinfo (NULL, open_port_str, &hint, &ret));
621 GNUNET_free (open_port_str);
622 bind_status = GNUNET_NO;
623 for (ai = ret; NULL != ai; ai = ai->ai_next)
624 {
625 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_STREAM, 0);
626 if (NULL == socket)
627 continue;
628 bind_status =
629 GNUNET_NETWORK_socket_bind (socket, ai->ai_addr, ai->ai_addrlen);
630 GNUNET_NETWORK_socket_close (socket);
631 if (GNUNET_OK != bind_status)
632 break;
633 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_DGRAM, 0);
634 if (NULL == socket)
635 continue;
636 bind_status =
637 GNUNET_NETWORK_socket_bind (socket, ai->ai_addr, ai->ai_addrlen);
638 GNUNET_NETWORK_socket_close (socket);
639 if (GNUNET_OK != bind_status)
640 break;
641 }
642 port_buckets[index] |= (1U << pos); /* Set the port bit */
643 freeaddrinfo (ret);
644 if (GNUNET_OK == bind_status)
645 {
646 LOG (GNUNET_ERROR_TYPE_DEBUG,
647 "Found a free port %u\n",
648 (unsigned int) open_port);
649 return open_port;
650 }
651 pos++;
652 }
653 }
654 return 0;
655}
656
657
658/**
659 * Release reservation of a TCP or UDP port for a peer
660 * (used during #GNUNET_TESTING_peer_destroy()).
661 *
662 * @param system system to use for reservation tracking
663 * @param port reserved port to release
664 */
665void
666GNUNET_TESTING_release_port (struct GNUNET_TESTING_System *system,
667 uint16_t port)
668{
669 uint32_t *port_buckets;
670 uint16_t bucket;
671 uint16_t pos;
672
673 port_buckets = system->reserved_ports;
674 bucket = port / 32;
675 pos = port % 32;
676 LOG (GNUNET_ERROR_TYPE_DEBUG, "Releasing port %u\n", port);
677 if (0 == (port_buckets[bucket] & (1U << pos)))
678 {
679 GNUNET_break (0); /* Port was not reserved by us using reserve_port() */
680 return;
681 }
682 port_buckets[bucket] &= ~(1U << pos);
683}
684
685
686/**
687 * Testing includes a number of pre-created hostkeys for
688 * faster peer startup. This function can be used to
689 * access the n-th key of those pre-created hostkeys; note
690 * that these keys are ONLY useful for testing and not
691 * secure as the private keys are part of the public
692 * GNUnet source code.
693 *
694 * This is primarily a helper function used internally
695 * by #GNUNET_TESTING_peer_configure.
696 *
697 * @param system the testing system handle
698 * @param key_number desired pre-created hostkey to obtain
699 * @param id set to the peer's identity (hash of the public
700 * key; if NULL, NULL is returned immediately
701 * @return NULL on error (not enough keys)
702 */
703struct GNUNET_CRYPTO_EddsaPrivateKey *
704GNUNET_TESTING_hostkey_get (const struct GNUNET_TESTING_System *system,
705 uint32_t key_number,
706 struct GNUNET_PeerIdentity *id)
707{
708 struct GNUNET_CRYPTO_EddsaPrivateKey *private_key;
709
710 if ((NULL == id) || (NULL == system->hostkeys_data))
711 return NULL;
712 if (key_number >= system->total_hostkeys)
713 {
714 LOG (GNUNET_ERROR_TYPE_ERROR,
715 _ ("Key number %u does not exist\n"),
716 key_number);
717 return NULL;
718 }
719 private_key = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
720 GNUNET_memcpy (private_key,
721 system->hostkeys_data
722 + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
723 GNUNET_TESTING_HOSTKEYFILESIZE);
724 GNUNET_CRYPTO_eddsa_key_get_public (private_key, &id->public_key);
725 return private_key;
726}
727
728
729/**
730 * Structure for holding data to build new configurations from a configuration
731 * template
732 */
733struct UpdateContext
734{
735 /**
736 * The system for which we are building configurations
737 */
738 struct GNUNET_TESTING_System *system;
739
740 /**
741 * The configuration we are building
742 */
743 struct GNUNET_CONFIGURATION_Handle *cfg;
744
745 /**
746 * The customized service home path for this peer
747 */
748 char *gnunet_home;
749
750 /**
751 * Array of ports currently allocated to this peer. These ports will be
752 * released upon peer destroy and can be used by other peers which are
753 * configured after.
754 */
755 uint16_t *ports;
756
757 /**
758 * The number of ports in the above array
759 */
760 unsigned int nports;
761
762 /**
763 * build status - to signal error while building a configuration
764 */
765 int status;
766};
767
768
769/**
770 * Function to iterate over options. Copies
771 * the options to the target configuration,
772 * updating PORT values as needed.
773 *
774 * @param cls the UpdateContext
775 * @param section name of the section
776 * @param option name of the option
777 * @param value value of the option
778 */
779static void
780update_config (void *cls,
781 const char *section,
782 const char *option,
783 const char *value)
784{
785 struct UpdateContext *uc = cls;
786 unsigned int ival;
787 char cval[12];
788 char uval[PATH_MAX];
789 char *single_variable;
790 char *per_host_variable;
791 unsigned long long num_per_host;
792 uint16_t new_port;
793
794 if (GNUNET_OK != uc->status)
795 return;
796 if (! ((0 == strcmp (option, "PORT")) || (0 == strcmp (option, "UNIXPATH")) ||
797 (0 == strcmp (option, "HOSTNAME"))))
798 return;
799 GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
800 GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
801 if ((0 == strcmp (option, "PORT")) && (1 == sscanf (value, "%u", &ival)))
802 {
803 if ((ival != 0) &&
804 (GNUNET_YES != GNUNET_CONFIGURATION_get_value_yesno (uc->cfg,
805 "testing",
806 single_variable)))
807 {
808 new_port = GNUNET_TESTING_reserve_port (uc->system);
809 if (0 == new_port)
810 {
811 uc->status = GNUNET_SYSERR;
812 GNUNET_free (single_variable);
813 GNUNET_free (per_host_variable);
814 return;
815 }
816 GNUNET_snprintf (cval, sizeof(cval), "%u", new_port);
817 value = cval;
818 GNUNET_array_append (uc->ports, uc->nports, new_port);
819 }
820 else if ((ival != 0) &&
821 (GNUNET_YES ==
822 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg,
823 "testing",
824 single_variable)) &&
825 GNUNET_CONFIGURATION_get_value_number (uc->cfg,
826 "testing",
827 per_host_variable,
828 &num_per_host))
829 {
830 /* GNUNET_snprintf (cval, sizeof (cval), "%u", */
831 /* ival + ctx->fdnum % num_per_host); */
832 /* value = cval; */
833 GNUNET_break (0); /* FIXME */
834 }
835 }
836 if (0 == strcmp (option, "UNIXPATH"))
837 {
838 if (GNUNET_YES != GNUNET_CONFIGURATION_get_value_yesno (uc->cfg,
839 "testing",
840 single_variable))
841 {
842 GNUNET_snprintf (uval,
843 sizeof(uval),
844 "%s/%s.sock",
845 uc->gnunet_home,
846 section);
847 value = uval;
848 }
849 else if ((GNUNET_YES ==
850 GNUNET_CONFIGURATION_get_value_number (uc->cfg,
851 "testing",
852 per_host_variable,
853 &num_per_host)) &&
854 (num_per_host > 0))
855 {
856 GNUNET_break (0); /* FIXME */
857 }
858 }
859 if (0 == strcmp (option, "HOSTNAME"))
860 {
861 value = (NULL == uc->system->hostname) ? "localhost" : uc->system->hostname;
862 }
863 GNUNET_free (single_variable);
864 GNUNET_free (per_host_variable);
865 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, option, value);
866}
867
868
869/**
870 * Section iterator to set ACCEPT_FROM/ACCEPT_FROM6 to include the address of
871 * 'trusted_hosts' in all sections
872 *
873 * @param cls the UpdateContext
874 * @param section name of the section
875 */
876static void
877update_config_sections (void *cls, const char *section)
878{
879 struct UpdateContext *uc = cls;
880 char **ikeys;
881 char *val;
882 char *ptr;
883 char *orig_allowed_hosts;
884 char *allowed_hosts;
885 char *ACCEPT_FROM_key;
886 uint16_t ikeys_cnt;
887 uint16_t key;
888
889 ikeys_cnt = 0;
890 val = NULL;
891 /* Ignore certain options from sections. See
892 https://gnunet.org/bugs/view.php?id=2476 */
893 if (GNUNET_YES ==
894 GNUNET_CONFIGURATION_have_value (uc->cfg, section, "TESTING_IGNORE_KEYS"))
895 {
896 GNUNET_assert (GNUNET_YES ==
897 GNUNET_CONFIGURATION_get_value_string (uc->cfg,
898 section,
899 "TESTING_IGNORE_KEYS",
900 &val));
901 ptr = val;
902 for (ikeys_cnt = 0; NULL != (ptr = strstr (ptr, ";")); ikeys_cnt++)
903 ptr++;
904 if (0 == ikeys_cnt)
905 GNUNET_break (0);
906 else
907 {
908 ikeys = GNUNET_malloc ((sizeof(char *)) * ikeys_cnt);
909 ptr = val;
910 for (key = 0; key < ikeys_cnt; key++)
911 {
912 ikeys[key] = ptr;
913 ptr = strstr (ptr, ";");
914 GNUNET_assert (NULL != ptr); /* worked just before... */
915 *ptr = '\0';
916 ptr++;
917 }
918 }
919 }
920 if (0 != ikeys_cnt)
921 {
922 for (key = 0; key < ikeys_cnt; key++)
923 {
924 if (NULL != strstr (ikeys[key], "ADVERTISED_PORT"))
925 break;
926 }
927 if ((key == ikeys_cnt) &&
928 (GNUNET_YES ==
929 GNUNET_CONFIGURATION_have_value (uc->cfg, section, "ADVERTISED_PORT")))
930 {
931 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (uc->cfg,
932 section,
933 "PORT",
934 &ptr))
935 {
936 GNUNET_CONFIGURATION_set_value_string (uc->cfg,
937 section,
938 "ADVERTISED_PORT",
939 ptr);
940 GNUNET_free (ptr);
941 }
942 }
943 for (key = 0; key < ikeys_cnt; key++)
944 {
945 if (NULL != strstr (ikeys[key], "ACCEPT_FROM"))
946 {
947 GNUNET_free (ikeys);
948 GNUNET_free (val);
949 return;
950 }
951 }
952 GNUNET_free (ikeys);
953 }
954 GNUNET_free (val);
955 ACCEPT_FROM_key = "ACCEPT_FROM";
956 if ((NULL != uc->system->trusted_ip) &&
957 (NULL != strstr (uc->system->trusted_ip, ":"))) /* IPv6 in use */
958 ACCEPT_FROM_key = "ACCEPT_FROM6";
959 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (uc->cfg,
960 section,
961 ACCEPT_FROM_key,
962 &orig_allowed_hosts))
963 {
964 orig_allowed_hosts = GNUNET_strdup ("127.0.0.1;");
965 }
966 if (NULL == uc->system->trusted_ip)
967 allowed_hosts = GNUNET_strdup (orig_allowed_hosts);
968 else
969 GNUNET_asprintf (&allowed_hosts,
970 "%s%s;",
971 orig_allowed_hosts,
972 uc->system->trusted_ip);
973 GNUNET_free (orig_allowed_hosts);
974 GNUNET_CONFIGURATION_set_value_string (uc->cfg,
975 section,
976 ACCEPT_FROM_key,
977 allowed_hosts);
978 GNUNET_free (allowed_hosts);
979}
980
981
982static struct SharedServiceInstance *
983associate_shared_service (struct GNUNET_TESTING_System *system,
984 struct SharedService *ss,
985 struct GNUNET_CONFIGURATION_Handle *cfg)
986{
987 struct SharedServiceInstance *i;
988 struct GNUNET_CONFIGURATION_Handle *temp;
989 char *gnunet_home;
990 uint32_t port;
991
992 ss->n_peers++;
993 if (((0 == ss->share) && (NULL == ss->instances)) ||
994 ((0 != ss->share) &&
995 (ss->n_instances < ((ss->n_peers + ss->share - 1) / ss->share))))
996 {
997 i = GNUNET_new (struct SharedServiceInstance);
998 i->ss = ss;
999 (void) GNUNET_asprintf (&gnunet_home,
1000 "%s/shared/%s/%u",
1001 system->tmppath,
1002 ss->sname,
1003 ss->n_instances);
1004 (void) GNUNET_asprintf (&i->unix_sock, "%s/sock", gnunet_home);
1005 port = GNUNET_TESTING_reserve_port (system);
1006 if (0 == port)
1007 {
1008 GNUNET_free (gnunet_home);
1009 cleanup_shared_service_instance (i);
1010 return NULL;
1011 }
1012 GNUNET_array_append (ss->instances, ss->n_instances, i);
1013 temp = GNUNET_CONFIGURATION_dup (ss->cfg);
1014 (void) GNUNET_asprintf (&i->port_str, "%u", port);
1015 (void) GNUNET_asprintf (&i->cfg_fn, "%s/config", gnunet_home);
1016 GNUNET_CONFIGURATION_set_value_string (temp,
1017 "PATHS",
1018 "GNUNET_HOME",
1019 gnunet_home);
1020 GNUNET_free (gnunet_home);
1021 GNUNET_CONFIGURATION_set_value_string (temp,
1022 ss->sname,
1023 "UNIXPATH",
1024 i->unix_sock);
1025 GNUNET_CONFIGURATION_set_value_string (temp,
1026 ss->sname,
1027 "PORT",
1028 i->port_str);
1029 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write (temp, i->cfg_fn))
1030 {
1031 GNUNET_CONFIGURATION_destroy (temp);
1032 cleanup_shared_service_instance (i);
1033 return NULL;
1034 }
1035 GNUNET_CONFIGURATION_destroy (temp);
1036 }
1037 else
1038 {
1039 GNUNET_assert (NULL != ss->instances);
1040 GNUNET_assert (0 < ss->n_instances);
1041 i = ss->instances[ss->n_instances - 1];
1042 }
1043 GNUNET_CONFIGURATION_iterate_section_values (ss->cfg,
1044 ss->sname,
1045 &cfg_copy_iterator,
1046 cfg);
1047 GNUNET_CONFIGURATION_set_value_string (cfg,
1048 ss->sname,
1049 "UNIXPATH",
1050 i->unix_sock);
1051 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "PORT", i->port_str);
1052 return i;
1053}
1054
1055
1056/**
1057 * Create a new configuration using the given configuration as a template;
1058 * ports and paths will be modified to select available ports on the local
1059 * system. The default configuration will be available in PATHS section under
1060 * the option DEFAULTCONFIG after the call. GNUNET_HOME is also set in PATHS
1061 * section to the temporary directory specific to this configuration. If we run
1062 * out of "*port" numbers, return #GNUNET_SYSERR.
1063 *
1064 * This is primarily a helper function used internally
1065 * by 'GNUNET_TESTING_peer_configure'.
1066 *
1067 * @param system system to use to coordinate resource usage
1068 * @param cfg template configuration to update
1069 * @param ports array with port numbers used in the created configuration.
1070 * Will be updated upon successful return. Can be NULL
1071 * @param nports the size of the `ports' array. Will be updated.
1072 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - the configuration will
1073 * be incomplete and should not be used there upon
1074 */
1075static int
1076GNUNET_TESTING_configuration_create_ (struct GNUNET_TESTING_System *system,
1077 struct GNUNET_CONFIGURATION_Handle *cfg,
1078 uint16_t **ports,
1079 unsigned int *nports)
1080{
1081 struct UpdateContext uc;
1082 char *default_config;
1083
1084 uc.system = system;
1085 uc.cfg = cfg;
1086 uc.status = GNUNET_OK;
1087 uc.ports = NULL;
1088 uc.nports = 0;
1089 GNUNET_asprintf (&uc.gnunet_home,
1090 "%s/%u",
1091 system->tmppath,
1092 system->path_counter++);
1093 GNUNET_asprintf (&default_config, "%s/config", uc.gnunet_home);
1094 GNUNET_CONFIGURATION_set_value_string (cfg,
1095 "PATHS",
1096 "DEFAULTCONFIG",
1097 default_config);
1098 GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG", default_config);
1099 GNUNET_free (default_config);
1100 GNUNET_CONFIGURATION_set_value_string (cfg,
1101 "PATHS",
1102 "GNUNET_HOME",
1103 uc.gnunet_home);
1104 /* make PORTs and UNIXPATHs unique */
1105 GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
1106 /* allow connections to services from system trusted_ip host */
1107 GNUNET_CONFIGURATION_iterate_sections (cfg, &update_config_sections, &uc);
1108 /* enable loopback-based connections between peers */
1109 GNUNET_CONFIGURATION_set_value_string (cfg, "nat", "USE_LOCALADDR", "YES");
1110 GNUNET_free (uc.gnunet_home);
1111 if ((NULL != ports) && (NULL != nports))
1112 {
1113 *ports = uc.ports;
1114 *nports = uc.nports;
1115 }
1116 else
1117 GNUNET_free (uc.ports);
1118 return uc.status;
1119}
1120
1121
1122/**
1123 * Create a new configuration using the given configuration as a template;
1124 * ports and paths will be modified to select available ports on the local
1125 * system. The default configuration will be available in PATHS section under
1126 * the option DEFAULTCONFIG after the call. GNUNET_HOME is also set in PATHS
1127 * section to the temporary directory specific to this configuration. If we run
1128 * out of "*port" numbers, return #GNUNET_SYSERR.
1129 *
1130 * This is primarily a helper function used internally
1131 * by #GNUNET_TESTING_peer_configure().
1132 *
1133 * @param system system to use to coordinate resource usage
1134 * @param cfg template configuration to update
1135 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - the configuration will
1136 * be incomplete and should not be used there upon
1137 */
1138int
1139GNUNET_TESTING_configuration_create (struct GNUNET_TESTING_System *system,
1140 struct GNUNET_CONFIGURATION_Handle *cfg)
1141{
1142 return GNUNET_TESTING_configuration_create_ (system, cfg, NULL, NULL);
1143}
1144
1145
1146/**
1147 * Configure a GNUnet peer. GNUnet must be installed on the local
1148 * system and available in the PATH.
1149 *
1150 * @param system system to use to coordinate resource usage
1151 * @param cfg configuration to use; will be UPDATED (to reflect needed
1152 * changes in port numbers and paths)
1153 * @param key_number number of the hostkey to use for the peer
1154 * @param id identifier for the daemon, will be set, can be NULL
1155 * @param emsg set to freshly allocated error message (set to NULL on success),
1156 * can be NULL
1157 * @return handle to the peer, NULL on error
1158 */
1159struct GNUNET_TESTING_Peer *
1160GNUNET_TESTING_peer_configure (struct GNUNET_TESTING_System *system,
1161 struct GNUNET_CONFIGURATION_Handle *cfg,
1162 uint32_t key_number,
1163 struct GNUNET_PeerIdentity *id,
1164 char **emsg)
1165{
1166 struct GNUNET_TESTING_Peer *peer;
1167 struct GNUNET_DISK_FileHandle *fd;
1168 char *hostkey_filename;
1169 char *config_filename;
1170 char *libexec_binary;
1171 char *emsg_;
1172 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
1173 uint16_t *ports;
1174 struct SharedService *ss;
1175 struct SharedServiceInstance **ss_instances;
1176 unsigned int cnt;
1177 unsigned int nports;
1178
1179 ports = NULL;
1180 nports = 0;
1181 ss_instances = NULL;
1182 if (NULL != emsg)
1183 *emsg = NULL;
1184 if (key_number >= system->total_hostkeys)
1185 {
1186 GNUNET_asprintf (
1187 &emsg_,
1188 _ (
1189 "You attempted to create a testbed with more than %u hosts. Please precompute more hostkeys first.\n"),
1190 (unsigned int) system->total_hostkeys);
1191 goto err_ret;
1192 }
1193 pk = NULL;
1194 if ((NULL != id) &&
1195 (NULL == (pk = GNUNET_TESTING_hostkey_get (system, key_number, id))))
1196 {
1197 GNUNET_asprintf (&emsg_,
1198 _ ("Failed to initialize hostkey for peer %u\n"),
1199 (unsigned int) key_number);
1200 goto err_ret;
1201 }
1202 if (NULL != pk)
1203 GNUNET_free (pk);
1204 if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (cfg, "PEER", "PRIVATE_KEY"))
1205 {
1206 GNUNET_asprintf (
1207 &emsg_,
1208 _ ("PRIVATE_KEY option in PEER section missing in configuration\n"));
1209 goto err_ret;
1210 }
1211 /* Remove sections for shared services */
1212 for (cnt = 0; cnt < system->n_shared_services; cnt++)
1213 {
1214 ss = system->shared_services[cnt];
1215 GNUNET_CONFIGURATION_remove_section (cfg, ss->sname);
1216 }
1217 if (GNUNET_OK !=
1218 GNUNET_TESTING_configuration_create_ (system, cfg, &ports, &nports))
1219 {
1220 GNUNET_asprintf (&emsg_,
1221 _ ("Failed to create configuration for peer "
1222 "(not enough free ports?)\n"));
1223 goto err_ret;
1224 }
1225 GNUNET_assert (GNUNET_OK ==
1226 GNUNET_CONFIGURATION_get_value_filename (cfg,
1227 "PEER",
1228 "PRIVATE_KEY",
1229 &hostkey_filename));
1230 fd = GNUNET_DISK_file_open (hostkey_filename,
1231 GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE,
1232 GNUNET_DISK_PERM_USER_READ
1233 | GNUNET_DISK_PERM_USER_WRITE);
1234 if (NULL == fd)
1235 {
1236 GNUNET_asprintf (&emsg_,
1237 _ ("Cannot open hostkey file `%s': %s\n"),
1238 hostkey_filename,
1239 strerror (errno));
1240 GNUNET_free (hostkey_filename);
1241 goto err_ret;
1242 }
1243 GNUNET_free (hostkey_filename);
1244 if (GNUNET_TESTING_HOSTKEYFILESIZE !=
1245 GNUNET_DISK_file_write (fd,
1246 system->hostkeys_data
1247 + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
1248 GNUNET_TESTING_HOSTKEYFILESIZE))
1249 {
1250 GNUNET_asprintf (&emsg_,
1251 _ ("Failed to write hostkey file for peer %u: %s\n"),
1252 (unsigned int) key_number,
1253 strerror (errno));
1254 GNUNET_DISK_file_close (fd);
1255 goto err_ret;
1256 }
1257 GNUNET_DISK_file_close (fd);
1258 ss_instances = GNUNET_malloc (sizeof(struct SharedServiceInstance *)
1259 * system->n_shared_services);
1260 for (cnt = 0; cnt < system->n_shared_services; cnt++)
1261 {
1262 ss = system->shared_services[cnt];
1263 ss_instances[cnt] = associate_shared_service (system, ss, cfg);
1264 if (NULL == ss_instances[cnt])
1265 {
1266 emsg_ = GNUNET_strdup ("FIXME");
1267 goto err_ret;
1268 }
1269 }
1270 GNUNET_assert (GNUNET_OK ==
1271 GNUNET_CONFIGURATION_get_value_filename (cfg,
1272 "PATHS",
1273 "DEFAULTCONFIG",
1274 &config_filename));
1275 if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config_filename))
1276 {
1277 GNUNET_asprintf (&emsg_,
1278 _ (
1279 "Failed to write configuration file `%s' for peer %u: %s\n"),
1280 config_filename,
1281 (unsigned int) key_number,
1282 strerror (errno));
1283 GNUNET_free (config_filename);
1284 goto err_ret;
1285 }
1286 peer = GNUNET_new (struct GNUNET_TESTING_Peer);
1287 peer->ss_instances = ss_instances;
1288 peer->cfgfile = config_filename; /* Free in peer_destroy */
1289 peer->cfg = GNUNET_CONFIGURATION_dup (cfg);
1290 libexec_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
1291 if (GNUNET_SYSERR ==
1292 GNUNET_CONFIGURATION_get_value_string (cfg,
1293 "arm",
1294 "PREFIX",
1295 &peer->main_binary))
1296 {
1297 /* No prefix */
1298 GNUNET_asprintf (&peer->main_binary, "%s", libexec_binary);
1299 peer->args = GNUNET_strdup ("");
1300 }
1301 else
1302 {
1303 peer->args = GNUNET_strdup (libexec_binary);
1304 }
1305 peer->system = system;
1306 peer->key_number = key_number;
1307 GNUNET_free (libexec_binary);
1308 peer->ports = ports; /* Free in peer_destroy */
1309 peer->nports = nports;
1310 return peer;
1311
1312 err_ret:
1313 GNUNET_free (ss_instances);
1314 GNUNET_free (ports);
1315 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_);
1316 if (NULL != emsg)
1317 *emsg = emsg_;
1318 else
1319 GNUNET_free (emsg_);
1320 return NULL;
1321}
1322
1323
1324/**
1325 * Obtain the peer identity from a peer handle.
1326 *
1327 * @param peer peer handle for which we want the peer's identity
1328 * @param id identifier for the daemon, will be set
1329 */
1330void
1331GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer,
1332 struct GNUNET_PeerIdentity *id)
1333{
1334 if (NULL != peer->id)
1335 {
1336 GNUNET_memcpy (id, peer->id, sizeof(struct GNUNET_PeerIdentity));
1337 return;
1338 }
1339 peer->id = GNUNET_new (struct GNUNET_PeerIdentity);
1340 GNUNET_free_nz (
1341 GNUNET_TESTING_hostkey_get (peer->system, peer->key_number, peer->id));
1342 GNUNET_memcpy (id, peer->id, sizeof(struct GNUNET_PeerIdentity));
1343}
1344
1345
1346/**
1347 * Start the peer.
1348 *
1349 * @param peer peer to start
1350 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error (i.e. peer already running)
1351 */
1352int
1353GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer)
1354{
1355 struct SharedServiceInstance *i;
1356 unsigned int cnt;
1357
1358 if (NULL != peer->main_process)
1359 {
1360 GNUNET_break (0);
1361 return GNUNET_SYSERR;
1362 }
1363 GNUNET_assert (NULL != peer->cfgfile);
1364 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1365 {
1366 i = peer->ss_instances[cnt];
1367 if ((0 == i->n_refs) &&
1368 (GNUNET_SYSERR == start_shared_service_instance (i)))
1369 return GNUNET_SYSERR;
1370 i->n_refs++;
1371 }
1372 peer->main_binary =
1373 GNUNET_CONFIGURATION_expand_dollar (peer->cfg, peer->main_binary);
1374 peer->main_process =
1375 GNUNET_OS_start_process_s (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
1376 NULL,
1377 peer->main_binary,
1378 peer->args,
1379 "-c",
1380 peer->cfgfile,
1381 NULL);
1382 if (NULL == peer->main_process)
1383 {
1384 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1385 _ ("Failed to start `%s': %s\n"),
1386 peer->main_binary,
1387 strerror (errno));
1388 return GNUNET_SYSERR;
1389 }
1390 return GNUNET_OK;
1391}
1392
1393
1394/**
1395 * Sends SIGTERM to the peer's main process
1396 *
1397 * @param peer the handle to the peer
1398 * @return #GNUNET_OK if successful; #GNUNET_SYSERR if the main process is NULL
1399 * or upon any error while sending SIGTERM
1400 */
1401int
1402GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer)
1403{
1404 struct SharedServiceInstance *i;
1405 unsigned int cnt;
1406
1407 if (NULL == peer->main_process)
1408 {
1409 GNUNET_break (0);
1410 return GNUNET_SYSERR;
1411 }
1412 if (0 != GNUNET_OS_process_kill (peer->main_process, GNUNET_TERM_SIG))
1413 return GNUNET_SYSERR;
1414 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1415 {
1416 i = peer->ss_instances[cnt];
1417 GNUNET_assert (0 != i->n_refs);
1418 i->n_refs--;
1419 if (0 == i->n_refs)
1420 stop_shared_service_instance (i);
1421 }
1422 return GNUNET_OK;
1423}
1424
1425
1426/**
1427 * Waits for a peer to terminate. The peer's main process will also be destroyed.
1428 *
1429 * @param peer the handle to the peer
1430 * @return #GNUNET_OK if successful; #GNUNET_SYSERR if the main process is NULL
1431 * or upon any error while waiting
1432 */
1433int
1434GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer)
1435{
1436 int ret;
1437
1438 if (NULL == peer->main_process)
1439 {
1440 GNUNET_break (0);
1441 return GNUNET_SYSERR;
1442 }
1443 ret = GNUNET_OS_process_wait (peer->main_process);
1444 GNUNET_OS_process_destroy (peer->main_process);
1445 peer->main_process = NULL;
1446 return ret;
1447}
1448
1449
1450/**
1451 * Stop the peer.
1452 *
1453 * @param peer peer to stop
1454 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1455 */
1456int
1457GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer)
1458{
1459 if (GNUNET_SYSERR == GNUNET_TESTING_peer_kill (peer))
1460 return GNUNET_SYSERR;
1461 if (GNUNET_SYSERR == GNUNET_TESTING_peer_wait (peer))
1462 return GNUNET_SYSERR;
1463 return GNUNET_OK;
1464}
1465
1466
1467/**
1468 * Function called whenever we connect to or disconnect from ARM.
1469 *
1470 * @param cls closure
1471 * @param connected #GNUNET_YES if connected, #GNUNET_NO if disconnected,
1472 * #GNUNET_SYSERR on error.
1473 */
1474static void
1475disconn_status (void *cls, int connected)
1476{
1477 struct GNUNET_TESTING_Peer *peer = cls;
1478
1479 if (GNUNET_SYSERR == connected)
1480 {
1481 peer->cb (peer->cb_cls, peer, connected);
1482 return;
1483 }
1484 if (GNUNET_YES == connected)
1485 {
1486 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_kill (peer));
1487 return;
1488 }
1489 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer));
1490 GNUNET_ARM_disconnect (peer->ah);
1491 peer->ah = NULL;
1492 peer->cb (peer->cb_cls, peer, GNUNET_YES);
1493}
1494
1495
1496/**
1497 * Stop a peer asynchronously using ARM API. Peer's shutdown is signaled
1498 * through the GNUNET_TESTING_PeerStopCallback().
1499 *
1500 * @param peer the peer to stop
1501 * @param cb the callback to signal peer shutdown
1502 * @param cb_cls closure for the above callback
1503 * @return #GNUNET_OK upon successfully giving the request to the ARM API (this
1504 * does not mean that the peer is successfully stopped); #GNUNET_SYSERR
1505 * upon any error.
1506 */
1507int
1508GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer,
1509 GNUNET_TESTING_PeerStopCallback cb,
1510 void *cb_cls)
1511{
1512 if (NULL == peer->main_process)
1513 return GNUNET_SYSERR;
1514 peer->ah = GNUNET_ARM_connect (peer->cfg, &disconn_status, peer);
1515 if (NULL == peer->ah)
1516 return GNUNET_SYSERR;
1517 peer->cb = cb;
1518 peer->cb_cls = cb_cls;
1519 return GNUNET_OK;
1520}
1521
1522
1523/**
1524 * Cancel a previous asynchronous peer stop request.
1525 * GNUNET_TESTING_peer_stop_async() should have been called before on the given
1526 * peer. It is an error to call this function if the peer stop callback was
1527 * already called
1528 *
1529 * @param peer the peer on which GNUNET_TESTING_peer_stop_async() was called
1530 * before.
1531 */
1532void
1533GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer)
1534{
1535 GNUNET_assert (NULL != peer->ah);
1536 GNUNET_ARM_disconnect (peer->ah);
1537 peer->ah = NULL;
1538}
1539
1540
1541/**
1542 * Destroy the peer. Releases resources locked during peer configuration.
1543 * If the peer is still running, it will be stopped AND a warning will be
1544 * printed (users of the API should stop the peer explicitly first).
1545 *
1546 * @param peer peer to destroy
1547 */
1548void
1549GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer)
1550{
1551 unsigned int cnt;
1552
1553 if (NULL != peer->main_process)
1554 GNUNET_TESTING_peer_stop (peer);
1555 if (NULL != peer->ah)
1556 GNUNET_ARM_disconnect (peer->ah);
1557 GNUNET_free (peer->cfgfile);
1558 if (NULL != peer->cfg)
1559 GNUNET_CONFIGURATION_destroy (peer->cfg);
1560 GNUNET_free (peer->main_binary);
1561 GNUNET_free (peer->args);
1562 GNUNET_free (peer->id);
1563 GNUNET_free (peer->ss_instances);
1564 if (NULL != peer->ports)
1565 {
1566 for (cnt = 0; cnt < peer->nports; cnt++)
1567 GNUNET_TESTING_release_port (peer->system, peer->ports[cnt]);
1568 GNUNET_free (peer->ports);
1569 }
1570 GNUNET_free (peer);
1571}
1572
1573
1574/**
1575 * Start a single peer and run a test using the testing library.
1576 * Starts a peer using the given configuration and then invokes the
1577 * given callback. This function ALSO initializes the scheduler loop
1578 * and should thus be called directly from "main". The testcase
1579 * should self-terminate by invoking #GNUNET_SCHEDULER_shutdown().
1580 *
1581 * @param testdir only the directory name without any path. This is used for
1582 * all service homes; the directory will be created in a temporary
1583 * location depending on the underlying OS
1584 * @param cfgfilename name of the configuration file to use;
1585 * use NULL to only run with defaults
1586 * @param tm main function of the testcase
1587 * @param tm_cls closure for @a tm
1588 * @return 0 on success, 1 on error
1589 */
1590int
1591GNUNET_TESTING_peer_run (const char *testdir,
1592 const char *cfgfilename,
1593 GNUNET_TESTING_TestMain tm,
1594 void *tm_cls)
1595{
1596 return GNUNET_TESTING_service_run (testdir, "arm", cfgfilename, tm, tm_cls);
1597}
1598
1599
1600/**
1601 * Structure for holding service data
1602 */
1603struct ServiceContext
1604{
1605 /**
1606 * The configuration of the peer in which the service is run
1607 */
1608 const struct GNUNET_CONFIGURATION_Handle *cfg;
1609
1610 /**
1611 * Callback to signal service startup
1612 */
1613 GNUNET_TESTING_TestMain tm;
1614
1615 /**
1616 * The peer in which the service is run.
1617 */
1618 struct GNUNET_TESTING_Peer *peer;
1619
1620 /**
1621 * Closure for the above callback
1622 */
1623 void *tm_cls;
1624};
1625
1626
1627/**
1628 * Callback to be called when SCHEDULER has been started
1629 *
1630 * @param cls the ServiceContext
1631 */
1632static void
1633service_run_main (void *cls)
1634{
1635 struct ServiceContext *sc = cls;
1636
1637 sc->tm (sc->tm_cls, sc->cfg, sc->peer);
1638}
1639
1640
1641/**
1642 * Start a single service (no ARM, except of course if the given
1643 * service name is 'arm') and run a test using the testing library.
1644 * Starts a service using the given configuration and then invokes the
1645 * given callback. This function ALSO initializes the scheduler loop
1646 * and should thus be called directly from "main". The testcase
1647 * should self-terminate by invoking #GNUNET_SCHEDULER_shutdown().
1648 *
1649 * This function is useful if the testcase is for a single service
1650 * and if that service doesn't itself depend on other services.
1651 *
1652 * @param testdir only the directory name without any path. This is used for
1653 * all service homes; the directory will be created in a temporary
1654 * location depending on the underlying OS
1655 * @param service_name name of the service to run
1656 * @param cfgfilename name of the configuration file to use;
1657 * use NULL to only run with defaults
1658 * @param tm main function of the testcase
1659 * @param tm_cls closure for @a tm
1660 * @return 0 on success, 1 on error
1661 */
1662int
1663GNUNET_TESTING_service_run (const char *testdir,
1664 const char *service_name,
1665 const char *cfgfilename,
1666 GNUNET_TESTING_TestMain tm,
1667 void *tm_cls)
1668{
1669 struct ServiceContext sc;
1670 struct GNUNET_TESTING_System *system;
1671 struct GNUNET_TESTING_Peer *peer;
1672 struct GNUNET_CONFIGURATION_Handle *cfg;
1673 char *binary;
1674 char *libexec_binary;
1675
1676 GNUNET_log_setup (testdir, "WARNING", NULL);
1677 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL);
1678 if (NULL == system)
1679 return 1;
1680 cfg = GNUNET_CONFIGURATION_create ();
1681 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgfilename))
1682 {
1683 LOG (GNUNET_ERROR_TYPE_ERROR,
1684 _ ("Failed to load configuration from %s\n"),
1685 cfgfilename);
1686 GNUNET_CONFIGURATION_destroy (cfg);
1687 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1688 return 1;
1689 }
1690 peer = GNUNET_TESTING_peer_configure (system, cfg, 0, NULL, NULL);
1691 if (NULL == peer)
1692 {
1693 GNUNET_CONFIGURATION_destroy (cfg);
1694 hostkeys_unload (system);
1695 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1696 return 1;
1697 }
1698 GNUNET_free (peer->main_binary);
1699 GNUNET_free (peer->args);
1700 GNUNET_asprintf (&binary, "gnunet-service-%s", service_name);
1701 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
1702 if (GNUNET_SYSERR ==
1703 GNUNET_CONFIGURATION_get_value_string (cfg,
1704 service_name,
1705 "PREFIX",
1706 &peer->main_binary))
1707 {
1708 /* No prefix */
1709 GNUNET_asprintf (&peer->main_binary, "%s", libexec_binary);
1710 peer->args = GNUNET_strdup ("");
1711 }
1712 else
1713 peer->args = GNUNET_strdup (libexec_binary);
1714
1715 GNUNET_free (libexec_binary);
1716 GNUNET_free (binary);
1717 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer))
1718 {
1719 GNUNET_TESTING_peer_destroy (peer);
1720 GNUNET_CONFIGURATION_destroy (cfg);
1721 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1722 return 1;
1723 }
1724 sc.cfg = cfg;
1725 sc.tm = tm;
1726 sc.tm_cls = tm_cls;
1727 sc.peer = peer;
1728 GNUNET_SCHEDULER_run (&service_run_main, &sc); /* Scheduler loop */
1729 if ((NULL != peer->main_process) &&
1730 (GNUNET_OK != GNUNET_TESTING_peer_stop (peer)))
1731 {
1732 GNUNET_TESTING_peer_destroy (peer);
1733 GNUNET_CONFIGURATION_destroy (cfg);
1734 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1735 return 1;
1736 }
1737 GNUNET_TESTING_peer_destroy (peer);
1738 GNUNET_CONFIGURATION_destroy (cfg);
1739 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1740 return 0;
1741}
1742
1743
1744/**
1745 * Sometimes we use the binary name to determine which specific
1746 * test to run. In those cases, the string after the last "_"
1747 * in 'argv[0]' specifies a string that determines the configuration
1748 * file or plugin to use.
1749 *
1750 * This function returns the respective substring, taking care
1751 * of issues such as binaries ending in '.exe' on W32.
1752 *
1753 * @param argv0 the name of the binary
1754 * @return string between the last '_' and the '.exe' (or the end of the string),
1755 * NULL if argv0 has no '_'
1756 */
1757char *
1758GNUNET_TESTING_get_testname_from_underscore (const char *argv0)
1759{
1760 size_t slen = strlen (argv0) + 1;
1761 char sbuf[slen];
1762 char *ret;
1763 char *dot;
1764
1765 GNUNET_memcpy (sbuf, argv0, slen);
1766 ret = strrchr (sbuf, '_');
1767 if (NULL == ret)
1768 return NULL;
1769 ret++; /* skip underscore */
1770 dot = strchr (ret, '.');
1771 if (NULL != dot)
1772 *dot = '\0';
1773 return GNUNET_strdup (ret);
1774}
1775
1776
1777static unsigned int
1778get_first_value (char *line)
1779{
1780 char *copy;
1781 size_t slen;
1782 char *token;
1783 unsigned int ret;
1784 char *rest = NULL;
1785
1786 slen = strlen (line) + 1;
1787 copy = malloc (slen);
1788 memcpy (copy, line, slen);
1789 token = strtok_r (copy, ":", &rest);
1790 token = strtok_r (NULL, ":", &rest);
1791 sscanf (token, "%u", &ret);
1792 free (copy);
1793 return ret;
1794}
1795
1796
1797static char *
1798get_key (char *line)
1799{
1800 char *copy;
1801 size_t slen;
1802 char *token;
1803 char *ret;
1804 char *rest = NULL;
1805
1806 slen = strlen (line) + 1;
1807 copy = malloc (slen);
1808 memcpy (copy, line, slen);
1809 token = strtok_r (copy, ":", &rest);
1810 ret = malloc (2);
1811 memcpy (ret, token, 2);
1812 free (copy);
1813 return ret;
1814}
1815
1816
1817static char *
1818get_first_string_value (char *line)
1819{
1820 char *copy;
1821 size_t slen, slen_token;
1822 char *token;
1823 char *ret;
1824 char *rest = NULL;
1825
1826 slen = strlen (line) + 1;
1827 copy = malloc (slen);
1828 memcpy (copy, line, slen);
1829 token = strtok_r (copy, ":", &rest);
1830 token = strtok_r (NULL, ":", &rest);
1831 LOG (GNUNET_ERROR_TYPE_DEBUG,
1832 "first token %s\n",
1833 token);
1834 slen_token = strlen (token);
1835 ret = malloc (slen_token + 1);
1836 memcpy (ret, token, slen_token + 1);
1837 free (copy);
1838 return ret;
1839}
1840
1841
1842static unsigned int
1843get_second_value (char *line)
1844{
1845 char *copy;
1846 size_t slen;
1847 char *token;
1848 unsigned int ret;
1849 char *rest = NULL;
1850
1851 slen = strlen (line) + 1;
1852 copy = malloc (slen);
1853 memcpy (copy, line, slen);
1854 token = strtok_r (copy, ":", &rest);
1855 token = strtok_r (NULL, ":", &rest);
1856 token = strtok_r (NULL, ":", &rest);
1857 sscanf (token, "%u", &ret);
1858 free (copy);
1859 return ret;
1860}
1861
1862
1863static char *
1864get_value (char *key, char *line)
1865{
1866 char *copy;
1867 size_t slen, slen_token;
1868 char *token;
1869 char *token2;
1870 char *temp;
1871 char *rest = NULL;
1872 char *ret;
1873
1874 slen = strlen (line) + 1;
1875 copy = malloc (slen);
1876 memcpy (copy, line, slen);
1877 temp = strstr (copy, key);
1878 if (NULL == temp)
1879 return NULL;
1880 token = strtok_r (temp, ":", &rest);
1881 token = strtok_r (NULL, ":", &rest);
1882 token2 = strtok_r (token, "}", &rest);
1883 slen_token = strlen (token2);
1884 ret = malloc (slen_token + 1);
1885 memcpy (ret, token2, slen_token + 1);
1886 free (copy);
1887 return ret;
1888}
1889
1890
1891/**
1892 * Getting the topology from file.
1893 *
1894 * @param filename The name of the topology file.
1895 * @return The GNUNET_TESTING_NetjailTopology
1896 */
1897struct GNUNET_TESTING_NetjailTopology *
1898GNUNET_TESTING_get_topo_from_file (const char *filename)
1899{
1900 uint64_t fs;
1901 char *data;
1902 char *token;
1903 char *key;
1904 unsigned int out;
1905 char *rest = NULL;
1906 char *value;
1907 int ret;
1908 struct GNUNET_TESTING_NetjailTopology *topo = GNUNET_new (struct
1909 GNUNET_TESTING_NetjailTopology);
1910 struct GNUNET_TESTING_NetjailNode *node;
1911 struct GNUNET_TESTING_NetjailRouter *router;
1912 struct GNUNET_TESTING_NetjailNamespace *namespace;
1913 struct GNUNET_ShortHashCode *hkey;
1914 struct GNUNET_HashCode hc;
1915 topo->map_namespaces =
1916 GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
1917 topo->map_globals =
1918 GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
1919
1920 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
1921 {
1922 LOG (GNUNET_ERROR_TYPE_ERROR,
1923 _ ("Topology file %s not found\n"),
1924 filename);
1925 return NULL;
1926 }
1927 if (GNUNET_OK !=
1928 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
1929 {
1930 LOG (GNUNET_ERROR_TYPE_ERROR,
1931 _ ("Topology file %s has no data\n"),
1932 filename);
1933 return NULL;
1934 }
1935 data = GNUNET_malloc (fs);
1936 if (fs != GNUNET_DISK_fn_read (filename, data, fs))
1937 {
1938 LOG (GNUNET_ERROR_TYPE_ERROR,
1939 _ ("Topology file %s cannot be read\n"),
1940 filename);
1941 GNUNET_free (data);
1942 return NULL;
1943 }
1944
1945 LOG (GNUNET_ERROR_TYPE_DEBUG,
1946 "data: %s\n",
1947 data);
1948
1949 token = strtok_r (data, "\n", &rest);
1950
1951 while (NULL != token)
1952 {
1953 key = get_key (token);
1954 LOG (GNUNET_ERROR_TYPE_DEBUG,
1955 "In the loop with token: %s beginning with %s\n",
1956 token,
1957 key);
1958 if (0 == strcmp (key, "M"))
1959 {
1960 LOG (GNUNET_ERROR_TYPE_DEBUG,
1961 "Get first Value for M.\n");
1962 out = get_first_value (token);
1963 LOG (GNUNET_ERROR_TYPE_DEBUG,
1964 "M: %u\n",
1965 out);
1966 topo->nodes_m = out;
1967 }
1968 else if (0 == strcmp (key, "N"))
1969 {
1970 LOG (GNUNET_ERROR_TYPE_DEBUG,
1971 "Get first Value for N.\n");
1972 out = get_first_value (token);
1973 LOG (GNUNET_ERROR_TYPE_DEBUG,
1974 "N: %u\n",
1975 out);
1976 topo->namespaces_n = out;
1977 }
1978 else if (0 == strcmp (key, "X"))
1979 {
1980 LOG (GNUNET_ERROR_TYPE_DEBUG,
1981 "Get first Value for X.\n");
1982 out = get_first_value (token);
1983 LOG (GNUNET_ERROR_TYPE_DEBUG,
1984 "X: %u\n",
1985 out);
1986 topo->nodes_x = out;
1987 }
1988 else if (0 == strcmp (key, "T"))
1989 {
1990 LOG (GNUNET_ERROR_TYPE_DEBUG,
1991 "Get first string value for T.\n");
1992 value = get_first_string_value (token);
1993 LOG (GNUNET_ERROR_TYPE_DEBUG,
1994 "value: %s\n",
1995 value);
1996 topo->plugin = value;
1997 }
1998 else if (0 == strcmp (key, "K"))
1999 {
2000 hkey = GNUNET_new (struct GNUNET_ShortHashCode);
2001 node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
2002
2003 LOG (GNUNET_ERROR_TYPE_DEBUG,
2004 "Get first Value for K.\n");
2005 out = get_first_value (token);
2006 LOG (GNUNET_ERROR_TYPE_DEBUG,
2007 "K: %u\n",
2008 out);
2009 node->node_n = out;
2010 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2011 memcpy (hkey,
2012 &hc,
2013 sizeof (*hkey));
2014 node->is_global = GNUNET_YES;
2015 LOG (GNUNET_ERROR_TYPE_DEBUG,
2016 "Get value for key value on K.\n");
2017 value = get_value ("plugin", token);
2018 LOG (GNUNET_ERROR_TYPE_DEBUG,
2019 "value: %s\n",
2020 value);
2021 if (0 == GNUNET_CONTAINER_multishortmap_contains (topo->map_globals,
2022 hkey))
2023 GNUNET_break (0);
2024 else
2025 GNUNET_CONTAINER_multishortmap_put (topo->map_globals,
2026 hkey,
2027 node,
2028 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2029 }
2030 else if (0 == strcmp (key, "R"))
2031 {
2032 hkey = GNUNET_new (struct GNUNET_ShortHashCode);
2033 router = GNUNET_new (struct GNUNET_TESTING_NetjailRouter);
2034 node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
2035
2036 LOG (GNUNET_ERROR_TYPE_DEBUG,
2037 "Get first Value for R.\n");
2038 out = get_first_value (token);
2039 LOG (GNUNET_ERROR_TYPE_DEBUG,
2040 "R: %u\n",
2041 out);
2042 node->node_n = out;
2043 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2044 memcpy (hkey,
2045 &hc,
2046 sizeof (*hkey));
2047 LOG (GNUNET_ERROR_TYPE_DEBUG,
2048 "Get value for key tcp_port on R.\n");
2049 value = get_value ("tcp_port", token);
2050 LOG (GNUNET_ERROR_TYPE_DEBUG,
2051 "tcp_port: %s\n",
2052 value);
2053 ret = sscanf (value, "%u", &(router->tcp_port));
2054
2055 GNUNET_break (0 == ret || 1 < router->tcp_port);
2056
2057 LOG (GNUNET_ERROR_TYPE_DEBUG,
2058 "Get value for key udp_port on R.\n");
2059 value = get_value ("udp_port", token);
2060 ret = sscanf (value, "%u", &(router->udp_port));
2061 GNUNET_break (0 == ret || 1 < router->udp_port);
2062 LOG (GNUNET_ERROR_TYPE_DEBUG,
2063 "udp_port: %s\n",
2064 value);
2065
2066 if (0 == GNUNET_CONTAINER_multishortmap_contains (topo->map_namespaces,
2067 hkey))
2068 {
2069 namespace = GNUNET_CONTAINER_multishortmap_get (topo->map_namespaces,
2070 hkey);
2071 }
2072 else
2073 {
2074 namespace = GNUNET_new (struct GNUNET_TESTING_NetjailNamespace);
2075 namespace->namespace_n = out;
2076 GNUNET_CONTAINER_multishortmap_put (topo->map_namespaces,
2077 hkey,
2078 namespace,
2079 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2080 }
2081 namespace->router = router;
2082
2083 }
2084 else if (0 == strcmp (key, "P"))
2085 {
2086 hkey = GNUNET_new (struct GNUNET_ShortHashCode);
2087 node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
2088
2089 LOG (GNUNET_ERROR_TYPE_DEBUG,
2090 "Get first Value for P.\n");
2091 out = get_first_value (token);
2092 LOG (GNUNET_ERROR_TYPE_DEBUG,
2093 "P: %u\n",
2094 out);
2095 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2096 memcpy (hkey,
2097 &hc,
2098 sizeof (*hkey));
2099
2100 LOG (GNUNET_ERROR_TYPE_DEBUG,
2101 "Get value for key plugin on P.\n");
2102 value = get_value ("plugin", token);
2103 LOG (GNUNET_ERROR_TYPE_DEBUG,
2104 "plugin: %s\n",
2105 value);
2106 if (0 == GNUNET_CONTAINER_multishortmap_contains (topo->map_namespaces,
2107 hkey))
2108 {
2109 namespace = GNUNET_CONTAINER_multishortmap_get (topo->map_namespaces,
2110 hkey);
2111 }
2112 else
2113 {
2114 namespace = GNUNET_new (struct GNUNET_TESTING_NetjailNamespace);
2115 namespace->namespace_n = out;
2116 GNUNET_CONTAINER_multishortmap_put (topo->map_namespaces,
2117 hkey,
2118 namespace,
2119 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2120 }
2121 LOG (GNUNET_ERROR_TYPE_DEBUG,
2122 "Get second Value for P.\n");
2123 out = get_second_value (token);
2124 LOG (GNUNET_ERROR_TYPE_DEBUG,
2125 "P: %u\n",
2126 out);
2127 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2128 memcpy (hkey,
2129 &hc,
2130 sizeof (*hkey));
2131 if (0 == GNUNET_CONTAINER_multishortmap_contains (namespace->nodes,
2132 hkey))
2133 {
2134 GNUNET_break (0);
2135 }
2136 else
2137 {
2138 node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
2139 GNUNET_CONTAINER_multishortmap_put (namespace->nodes,
2140 hkey,
2141 node,
2142 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2143 node->plugin = value;
2144 node->node_n = out;
2145 node->namespace_n = namespace->namespace_n;
2146 }
2147 }
2148 token = strtok_r (NULL, "\n", &rest);
2149 }
2150
2151 return topo;
2152}
2153
2154
2155/* end of testing.c */