aboutsummaryrefslogtreecommitdiff
path: root/src/lib/testing/testing.c
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 14:01:07 +0200
committerMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 14:01:07 +0200
commitcc90a65e1a562889778d748c129bff2920e3dd21 (patch)
treee7571f96719cebf325e5490a85c865c10efbe536 /src/lib/testing/testing.c
parent00407f6a36880fda570604cf4e64858bb08a025b (diff)
downloadgnunet-cc90a65e1a562889778d748c129bff2920e3dd21.tar.gz
gnunet-cc90a65e1a562889778d748c129bff2920e3dd21.zip
BUILD: Move testing to lib
Diffstat (limited to 'src/lib/testing/testing.c')
-rw-r--r--src/lib/testing/testing.c2830
1 files changed, 2830 insertions, 0 deletions
diff --git a/src/lib/testing/testing.c b/src/lib/testing/testing.c
new file mode 100644
index 000000000..fdfa80d87
--- /dev/null
+++ b/src/lib/testing/testing.c
@@ -0,0 +1,2830 @@
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#include "gnunet_testing_plugin.h"
38#include "gnunet_testing_barrier.h"
39#include "gnunet_testing_netjail_lib.h"
40#include "testing_cmds.h"
41
42#define LOG(kind, ...) GNUNET_log_from (kind, "testing-api", __VA_ARGS__)
43
44#define CONNECT_ADDRESS_TEMPLATE "%s-192.168.15.%u"
45
46#define ROUTER_CONNECT_ADDRESS_TEMPLATE "%s-92.68.150.%u"
47
48#define KNOWN_CONNECT_ADDRESS_TEMPLATE "%s-92.68.151.%u"
49
50/* Use the IP addresses below instead of the public ones,
51 * if the start script was not started from within a new namespace
52 * created by unshare. The UPNP test case needs public IP
53 * addresse for miniupnpd to function.
54 * FIXME We should introduce a switch indicating if public
55 * addresses should be used or not. This info has to be
56 * propagated from the start script to the c code.
57#define ROUTER_CONNECT_ADDRESS_TEMPLATE "%s-172.16.150.%u"
58
59#define KNOWN_CONNECT_ADDRESS_TEMPLATE "%s-172.16.151.%u"
60*/
61
62#define PREFIX_TCP "tcp"
63
64#define PREFIX_UDP "udp"
65
66#define PREFIX_TCP_NATTED "tcp_natted"
67
68#define PREFIX_UDP_NATTED "udp_natted"
69
70/**
71 * Lowest port used for GNUnet testing. Should be high enough to not
72 * conflict with other applications running on the hosts but be low
73 * enough to not conflict with client-ports (typically starting around
74 * 32k).
75 */
76#define LOW_PORT 12000
77
78/**
79 * Highest port used for GNUnet testing. Should be low enough to not
80 * conflict with the port range for "local" ports (client apps; see
81 * /proc/sys/net/ipv4/ip_local_port_range on Linux for example).
82 */
83#define HIGH_PORT 56000
84
85
86struct SharedServiceInstance
87{
88 struct SharedService *ss;
89
90 char *cfg_fn;
91
92 struct GNUNET_OS_Process *proc;
93
94 char *unix_sock;
95
96 char *port_str;
97
98 unsigned int n_refs;
99};
100
101struct SharedService
102{
103 char *sname;
104
105 struct SharedServiceInstance **instances;
106
107 struct GNUNET_CONFIGURATION_Handle *cfg;
108
109 unsigned int n_peers;
110
111 unsigned int share;
112
113 unsigned int n_instances;
114};
115
116
117/**
118 * Handle for a system on which GNUnet peers are executed;
119 * a system is used for reserving unique paths and ports.
120 */
121struct GNUNET_TESTING_System
122{
123 /**
124 * Prefix (e.g. "/tmp/gnunet-testing/") we prepend to each
125 * GNUNET_HOME.
126 */
127 char *tmppath;
128
129 /**
130 * The trusted ip. Can either be a single ip address or a network address in
131 * CIDR notation.
132 */
133 char *trusted_ip;
134
135 /**
136 * our hostname
137 */
138 char *hostname;
139
140 /**
141 * Hostkeys data, contains "GNUNET_TESTING_HOSTKEYFILESIZE * total_hostkeys" bytes.
142 */
143 char *hostkeys_data;
144
145 /**
146 * memory map for @e hostkeys_data.
147 */
148 struct GNUNET_DISK_MapHandle *map;
149
150 struct SharedService *shared_services;
151
152 unsigned int n_shared_services;
153
154 /**
155 * Bitmap where each port that has already been reserved for some GNUnet peer
156 * is recorded. Note that we make no distinction between TCP and UDP ports
157 * and test if a port is already in use before assigning it to a peer/service.
158 * If we detect that a port is already in use, we also mark it in this bitmap.
159 * So all the bits that are zero merely indicate ports that MIGHT be available
160 * for peers.
161 */
162 uint32_t reserved_ports[65536 / 32];
163
164 /**
165 * Counter we use to make service home paths unique on this system;
166 * the full path consists of the tmppath and this number. Each
167 * UNIXPATH for a peer is also modified to include the respective
168 * path counter to ensure uniqueness. This field is incremented
169 * by one for each configured peer. Even if peers are destroyed,
170 * we never re-use path counters.
171 */
172 uint32_t path_counter;
173
174 /**
175 * The number of hostkeys
176 */
177 uint32_t total_hostkeys;
178
179 /**
180 * Lowest port we are allowed to use.
181 */
182 uint16_t lowport;
183
184 /**
185 * Highest port we are allowed to use.
186 */
187 uint16_t highport;
188};
189
190
191/**
192 * Handle for a GNUnet peer controlled by testing.
193 */
194struct GNUNET_TESTING_Peer
195{
196 /**
197 * The TESTING system associated with this peer
198 */
199 struct GNUNET_TESTING_System *system;
200
201 /**
202 * Path to the configuration file for this peer.
203 */
204 char *cfgfile;
205
206 /**
207 * Binary to be executed during 'GNUNET_TESTING_peer_start'.
208 * Typically 'gnunet-service-arm' (but can be set to a
209 * specific service by 'GNUNET_TESTING_service_run' if
210 * necessary).
211 */
212 char *main_binary;
213 char *args;
214
215 /**
216 * Handle to the running binary of the service, NULL if the
217 * peer/service is currently not running.
218 */
219 struct GNUNET_OS_Process *main_process;
220
221 /**
222 * The handle to the peer's ARM service
223 */
224 struct GNUNET_ARM_Handle *ah;
225
226 /**
227 * The config of the peer
228 */
229 struct GNUNET_CONFIGURATION_Handle *cfg;
230
231 /**
232 * The callback to call asynchronously when a peer is stopped
233 */
234 GNUNET_TESTING_PeerStopCallback cb;
235
236 /**
237 * The closure for the above callback
238 */
239 void *cb_cls;
240
241 /**
242 * The cached identity of this peer. Will be populated on call to
243 * GNUNET_TESTING_peer_get_identity()
244 */
245 struct GNUNET_PeerIdentity *id;
246
247 struct SharedServiceInstance **ss_instances;
248
249 /**
250 * Array of ports currently allocated to this peer. These ports will be
251 * released upon peer destroy and can be used by other peers which are
252 * configured after.
253 */
254 uint16_t *ports;
255
256 /**
257 * The number of ports in the above array
258 */
259 unsigned int nports;
260
261 /**
262 * The keynumber of this peer's hostkey
263 */
264 uint32_t key_number;
265};
266
267
268/**
269 * Testing includes a number of pre-created hostkeys for faster peer
270 * startup. This function loads such keys into memory from a file.
271 *
272 * @param system the testing system handle
273 * @return #GNUNET_OK on success; #GNUNET_SYSERR on error
274 */
275static enum GNUNET_GenericReturnValue
276hostkeys_load (struct GNUNET_TESTING_System *system)
277{
278 uint64_t fs;
279 char *data_dir;
280 char *filename;
281 struct GNUNET_DISK_FileHandle *fd;
282
283 GNUNET_assert (NULL == system->hostkeys_data);
284 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
285 GNUNET_asprintf (&filename, "%s/testing_hostkeys.ecc", data_dir);
286 GNUNET_free (data_dir);
287
288 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
289 {
290 LOG (GNUNET_ERROR_TYPE_ERROR,
291 _ ("Hostkeys file not found: %s\n"),
292 filename);
293 GNUNET_free (filename);
294 return GNUNET_SYSERR;
295 }
296 /* Check hostkey file size, read entire thing into memory */
297 if (GNUNET_OK !=
298 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
299 fs = 0;
300 if (0 == fs)
301 {
302 GNUNET_free (filename);
303 return GNUNET_SYSERR; /* File is empty */
304 }
305 if (0 != (fs % GNUNET_TESTING_HOSTKEYFILESIZE))
306 {
307 LOG (GNUNET_ERROR_TYPE_ERROR,
308 _ ("Incorrect hostkey file format: %s\n"),
309 filename);
310 GNUNET_free (filename);
311 return GNUNET_SYSERR;
312 }
313 fd = GNUNET_DISK_file_open (filename,
314 GNUNET_DISK_OPEN_READ,
315 GNUNET_DISK_PERM_NONE);
316 if (NULL == fd)
317 {
318 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
319 GNUNET_free (filename);
320 return GNUNET_SYSERR;
321 }
322 GNUNET_free (filename);
323 system->hostkeys_data =
324 GNUNET_DISK_file_map (fd, &system->map, GNUNET_DISK_MAP_TYPE_READ, fs);
325 GNUNET_DISK_file_close (fd);
326 if (NULL == system->hostkeys_data)
327 return GNUNET_SYSERR;
328 system->total_hostkeys = fs / GNUNET_TESTING_HOSTKEYFILESIZE;
329 return GNUNET_OK;
330}
331
332
333/**
334 * Function to remove the loaded hostkeys
335 *
336 * @param system the testing system handle
337 */
338static void
339hostkeys_unload (struct GNUNET_TESTING_System *system)
340{
341 GNUNET_break (NULL != system->hostkeys_data);
342 system->hostkeys_data = NULL;
343 GNUNET_DISK_file_unmap (system->map);
344 system->map = NULL;
345 system->hostkeys_data = NULL;
346 system->total_hostkeys = 0;
347}
348
349
350/**
351 * Function to iterate over options.
352 *
353 * @param cls closure
354 * @param section name of the section
355 * @param option name of the option
356 * @param value value of the option
357 */
358static void
359cfg_copy_iterator (void *cls,
360 const char *section,
361 const char *option,
362 const char *value)
363{
364 struct GNUNET_CONFIGURATION_Handle *cfg2 = cls;
365
366 GNUNET_CONFIGURATION_set_value_string (cfg2, section, option, value);
367}
368
369
370/**
371 * Create a system handle. There must only be one system
372 * handle per operating system.
373 *
374 * @param testdir only the directory name without any path. This is used for
375 * all service homes; the directory will be created in a temporary
376 * location depending on the underlying OS. This variable will be
377 * overridden with the value of the environmental variable
378 * GNUNET_TESTING_PREFIX, if it exists.
379 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
380 * service configurations generated to allow control connections from
381 * this ip. This can either be a single ip address or a network address
382 * in CIDR notation.
383 * @param hostname the hostname of the system we are using for testing; NULL for
384 * localhost
385 * @param shared_services NULL terminated array describing services that are to
386 * be shared among peers
387 * @param lowport lowest port number this system is allowed to allocate (inclusive)
388 * @param highport highest port number this system is allowed to allocate (exclusive)
389 * @return handle to this system, NULL on error
390 */
391struct GNUNET_TESTING_System *
392GNUNET_TESTING_system_create_with_portrange (
393 const char *testdir,
394 const char *trusted_ip,
395 const char *hostname,
396 const struct GNUNET_TESTING_SharedService *shared_services,
397 uint16_t lowport,
398 uint16_t highport)
399{
400 struct GNUNET_TESTING_System *system;
401 struct GNUNET_TESTING_SharedService tss;
402 struct SharedService ss;
403 unsigned int cnt;
404
405 GNUNET_assert (NULL != testdir);
406 system = GNUNET_new (struct GNUNET_TESTING_System);
407 if (NULL == (system->tmppath = getenv (GNUNET_TESTING_PREFIX)))
408 system->tmppath = GNUNET_DISK_mkdtemp (testdir);
409 else
410 system->tmppath = GNUNET_strdup (system->tmppath);
411 system->lowport = lowport;
412 system->highport = highport;
413 if (NULL == system->tmppath)
414 {
415 GNUNET_free (system);
416 return NULL;
417 }
418 if (NULL != trusted_ip)
419 system->trusted_ip = GNUNET_strdup (trusted_ip);
420 if (NULL != hostname)
421 system->hostname = GNUNET_strdup (hostname);
422 if (GNUNET_OK != hostkeys_load (system))
423 {
424 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
425 return NULL;
426 }
427 if (NULL == shared_services)
428 return system;
429 for (cnt = 0; NULL != shared_services[cnt].service; cnt++)
430 {
431 tss = shared_services[cnt];
432 memset (&ss, 0, sizeof (ss));
433 ss.sname = GNUNET_strdup (tss.service);
434 ss.cfg = GNUNET_CONFIGURATION_create ();
435 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg,
436 ss.sname,
437 &cfg_copy_iterator,
438 ss.cfg);
439 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg,
440 "TESTING",
441 &cfg_copy_iterator,
442 ss.cfg);
443 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg,
444 "PATHS",
445 &cfg_copy_iterator,
446 ss.cfg);
447 ss.share = tss.share;
448 GNUNET_array_append (system->shared_services,
449 system->n_shared_services,
450 ss);
451 }
452 return system;
453}
454
455
456/**
457 * Create a system handle. There must only be one system handle per operating
458 * system. Uses a default range for allowed ports. Ports are still tested for
459 * availability.
460 *
461 * @param testdir only the directory name without any path. This is used for all
462 * service homes; the directory will be created in a temporary location
463 * depending on the underlying OS. This variable will be
464 * overridden with the value of the environmental variable
465 * GNUNET_TESTING_PREFIX, if it exists.
466 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
467 * service configurations generated to allow control connections from
468 * this ip. This can either be a single ip address or a network address
469 * in CIDR notation.
470 * @param hostname the hostname of the system we are using for testing; NULL for
471 * localhost
472 * @param shared_services NULL terminated array describing services that are to
473 * be shared among peers
474 * @return handle to this system, NULL on error
475 */
476struct GNUNET_TESTING_System *
477GNUNET_TESTING_system_create (
478 const char *testdir,
479 const char *trusted_ip,
480 const char *hostname,
481 const struct GNUNET_TESTING_SharedService *shared_services)
482{
483 return GNUNET_TESTING_system_create_with_portrange (testdir,
484 trusted_ip,
485 hostname,
486 shared_services,
487 LOW_PORT,
488 HIGH_PORT);
489}
490
491
492static void
493cleanup_shared_service_instance (struct SharedServiceInstance *i)
494{
495 if (NULL != i->cfg_fn)
496 {
497 (void) unlink (i->cfg_fn);
498 GNUNET_free (i->cfg_fn);
499 }
500 GNUNET_free (i->unix_sock);
501 GNUNET_free (i->port_str);
502 GNUNET_break (NULL == i->proc);
503 GNUNET_break (0 == i->n_refs);
504 GNUNET_free (i);
505}
506
507
508static enum GNUNET_GenericReturnValue
509start_shared_service_instance (struct SharedServiceInstance *i)
510{
511 char *binary;
512 char *libexec_binary;
513
514 GNUNET_assert (NULL == i->proc);
515 GNUNET_assert (NULL != i->cfg_fn);
516 (void) GNUNET_asprintf (&binary, "gnunet-service-%s", i->ss->sname);
517 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
518 GNUNET_free (binary);
519 i->proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
520 NULL,
521 NULL,
522 NULL,
523 libexec_binary,
524 libexec_binary,
525 "-c",
526 i->cfg_fn,
527 NULL);
528 GNUNET_free (libexec_binary);
529 if (NULL == i->proc)
530 return GNUNET_SYSERR;
531 return GNUNET_OK;
532}
533
534
535static void
536stop_shared_service_instance (struct SharedServiceInstance *i)
537{
538 GNUNET_break (0 == i->n_refs);
539 if (0 != GNUNET_OS_process_kill (i->proc, GNUNET_TERM_SIG))
540 LOG (GNUNET_ERROR_TYPE_WARNING,
541 "Killing shared service instance (%s) failed\n",
542 i->ss->sname);
543 (void) GNUNET_OS_process_wait (i->proc);
544 GNUNET_OS_process_destroy (i->proc);
545 i->proc = NULL;
546}
547
548
549/**
550 * Free system resources.
551 *
552 * @param system system to be freed
553 * @param remove_paths should the 'testdir' and all subdirectories
554 * be removed (clean up on shutdown)?
555 */
556void
557GNUNET_TESTING_system_destroy (struct GNUNET_TESTING_System *system,
558 int remove_paths)
559{
560 struct SharedService *ss;
561 struct SharedServiceInstance *i;
562 unsigned int ss_cnt;
563 unsigned int i_cnt;
564
565 if (NULL != system->hostkeys_data)
566 hostkeys_unload (system);
567 for (ss_cnt = 0; ss_cnt < system->n_shared_services; ss_cnt++)
568 {
569 ss = &system->shared_services[ss_cnt];
570 for (i_cnt = 0; i_cnt < ss->n_instances; i_cnt++)
571 {
572 i = ss->instances[i_cnt];
573 if (NULL != i->proc)
574 stop_shared_service_instance (i);
575 cleanup_shared_service_instance (i);
576 }
577 GNUNET_free (ss->instances);
578 GNUNET_CONFIGURATION_destroy (ss->cfg);
579 GNUNET_free (ss->sname);
580 }
581 GNUNET_free (system->shared_services);
582 if (GNUNET_YES == remove_paths)
583 GNUNET_DISK_directory_remove (system->tmppath);
584 GNUNET_free (system->tmppath);
585 GNUNET_free (system->trusted_ip);
586 GNUNET_free (system->hostname);
587 GNUNET_free (system);
588}
589
590
591/**
592 * Reserve a TCP or UDP port for a peer.
593 *
594 * @param system system to use for reservation tracking
595 * @return 0 if no free port was available
596 */
597uint16_t
598GNUNET_TESTING_reserve_port (struct GNUNET_TESTING_System *system)
599{
600 struct GNUNET_NETWORK_Handle *socket;
601 struct addrinfo hint;
602 struct addrinfo *ret;
603 struct addrinfo *ai;
604 uint32_t *port_buckets;
605 char *open_port_str;
606 int bind_status;
607 uint32_t xor_image;
608 uint16_t index;
609 uint16_t open_port;
610 uint16_t pos;
611
612 /*
613 FIXME: Instead of using getaddrinfo we should try to determine the port
614 status by the following heurestics.
615
616 On systems which support both IPv4 and IPv6, only ports open on both
617 address families are considered open.
618 On system with either IPv4 or IPv6. A port is considered open if it's
619 open in the respective address family
620 */hint.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
621 hint.ai_socktype = 0;
622 hint.ai_protocol = 0;
623 hint.ai_addrlen = 0;
624 hint.ai_addr = NULL;
625 hint.ai_canonname = NULL;
626 hint.ai_next = NULL;
627 hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */
628 port_buckets = system->reserved_ports;
629 for (index = (system->lowport / 32) + 1; index < (system->highport / 32);
630 index++)
631 {
632 xor_image = (UINT32_MAX ^ port_buckets[index]);
633 if (0 == xor_image) /* Ports in the bucket are full */
634 continue;
635 pos = system->lowport % 32;
636 while (pos < 32)
637 {
638 if (0 == ((xor_image >> pos) & 1U))
639 {
640 pos++;
641 continue;
642 }
643 open_port = (index * 32) + pos;
644 if (open_port >= system->highport)
645 return 0;
646 GNUNET_asprintf (&open_port_str, "%u", (unsigned int) open_port);
647 ret = NULL;
648 GNUNET_assert (0 == getaddrinfo (NULL, open_port_str, &hint, &ret));
649 GNUNET_free (open_port_str);
650 bind_status = GNUNET_NO;
651 for (ai = ret; NULL != ai; ai = ai->ai_next)
652 {
653 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_STREAM, 0);
654 if (NULL == socket)
655 continue;
656 bind_status =
657 GNUNET_NETWORK_socket_bind (socket, ai->ai_addr, ai->ai_addrlen);
658 GNUNET_NETWORK_socket_close (socket);
659 if (GNUNET_OK != bind_status)
660 break;
661 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_DGRAM, 0);
662 if (NULL == socket)
663 continue;
664 bind_status =
665 GNUNET_NETWORK_socket_bind (socket, ai->ai_addr, ai->ai_addrlen);
666 GNUNET_NETWORK_socket_close (socket);
667 if (GNUNET_OK != bind_status)
668 break;
669 }
670 port_buckets[index] |= (1U << pos); /* Set the port bit */
671 freeaddrinfo (ret);
672 if (GNUNET_OK == bind_status)
673 {
674 LOG (GNUNET_ERROR_TYPE_DEBUG,
675 "Found a free port %u\n",
676 (unsigned int) open_port);
677 return open_port;
678 }
679 pos++;
680 }
681 }
682 return 0;
683}
684
685
686/**
687 * Release reservation of a TCP or UDP port for a peer
688 * (used during #GNUNET_TESTING_peer_destroy()).
689 *
690 * @param system system to use for reservation tracking
691 * @param port reserved port to release
692 */
693void
694GNUNET_TESTING_release_port (struct GNUNET_TESTING_System *system,
695 uint16_t port)
696{
697 uint32_t *port_buckets;
698 uint16_t bucket;
699 uint16_t pos;
700
701 port_buckets = system->reserved_ports;
702 bucket = port / 32;
703 pos = port % 32;
704 LOG (GNUNET_ERROR_TYPE_DEBUG, "Releasing port %u\n", port);
705 if (0 == (port_buckets[bucket] & (1U << pos)))
706 {
707 GNUNET_break (0); /* Port was not reserved by us using reserve_port() */
708 return;
709 }
710 port_buckets[bucket] &= ~(1U << pos);
711}
712
713
714/**
715 * Testing includes a number of pre-created hostkeys for
716 * faster peer startup. This function can be used to
717 * access the n-th key of those pre-created hostkeys; note
718 * that these keys are ONLY useful for testing and not
719 * secure as the private keys are part of the public
720 * GNUnet source code.
721 *
722 * This is primarily a helper function used internally
723 * by #GNUNET_TESTING_peer_configure.
724 *
725 * @param system the testing system handle
726 * @param key_number desired pre-created hostkey to obtain
727 * @param id set to the peer's identity (hash of the public
728 * key; if NULL, NULL is returned immediately
729 * @return NULL on error (not enough keys)
730 */
731struct GNUNET_CRYPTO_EddsaPrivateKey *
732GNUNET_TESTING_hostkey_get (const struct GNUNET_TESTING_System *system,
733 uint32_t key_number,
734 struct GNUNET_PeerIdentity *id)
735{
736 struct GNUNET_CRYPTO_EddsaPrivateKey *private_key;
737
738 if ((NULL == id) || (NULL == system->hostkeys_data))
739 return NULL;
740 if (key_number >= system->total_hostkeys)
741 {
742 LOG (GNUNET_ERROR_TYPE_ERROR,
743 _ ("Key number %u does not exist\n"),
744 key_number);
745 return NULL;
746 }
747 private_key = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
748 GNUNET_memcpy (private_key,
749 system->hostkeys_data
750 + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
751 GNUNET_TESTING_HOSTKEYFILESIZE);
752 GNUNET_CRYPTO_eddsa_key_get_public (private_key, &id->public_key);
753 return private_key;
754}
755
756
757/**
758 * Structure for holding data to build new configurations from a configuration
759 * template
760 */
761struct UpdateContext
762{
763 /**
764 * The system for which we are building configurations
765 */
766 struct GNUNET_TESTING_System *system;
767
768 /**
769 * The configuration we are building
770 */
771 struct GNUNET_CONFIGURATION_Handle *cfg;
772
773 /**
774 * The customized service home path for this peer
775 */
776 char *gnunet_home;
777
778 /**
779 * Array of ports currently allocated to this peer. These ports will be
780 * released upon peer destroy and can be used by other peers which are
781 * configured after.
782 */
783 uint16_t *ports;
784
785 /**
786 * The number of ports in the above array
787 */
788 unsigned int nports;
789
790 /**
791 * build status - to signal error while building a configuration
792 */
793 int status;
794};
795
796
797/**
798 * Function to iterate over options. Copies
799 * the options to the target configuration,
800 * updating PORT values as needed.
801 *
802 * @param cls the UpdateContext
803 * @param section name of the section
804 * @param option name of the option
805 * @param value value of the option
806 */
807static void
808update_config (void *cls,
809 const char *section,
810 const char *option,
811 const char *value)
812{
813 struct UpdateContext *uc = cls;
814 unsigned int ival;
815 char cval[12];
816 char uval[PATH_MAX];
817 char *single_variable;
818 char *per_host_variable;
819 unsigned long long num_per_host;
820 uint16_t new_port;
821
822 if (GNUNET_OK != uc->status)
823 return;
824 if (! ((0 == strcmp (option, "PORT")) || (0 == strcmp (option, "UNIXPATH")) ||
825 (0 == strcmp (option, "HOSTNAME"))))
826 return;
827 GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
828 GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
829 if ((0 == strcmp (option, "PORT")) && (1 == sscanf (value, "%u", &ival)))
830 {
831 if ((ival != 0) &&
832 (GNUNET_YES != GNUNET_CONFIGURATION_get_value_yesno (uc->cfg,
833 "testing",
834 single_variable)))
835 {
836 new_port = GNUNET_TESTING_reserve_port (uc->system);
837 if (0 == new_port)
838 {
839 uc->status = GNUNET_SYSERR;
840 GNUNET_free (single_variable);
841 GNUNET_free (per_host_variable);
842 return;
843 }
844 GNUNET_snprintf (cval, sizeof(cval), "%u", new_port);
845 value = cval;
846 GNUNET_array_append (uc->ports, uc->nports, new_port);
847 }
848 else if ((ival != 0) &&
849 (GNUNET_YES ==
850 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg,
851 "testing",
852 single_variable)) &&
853 GNUNET_CONFIGURATION_get_value_number (uc->cfg,
854 "testing",
855 per_host_variable,
856 &num_per_host))
857 {
858 /* GNUNET_snprintf (cval, sizeof (cval), "%u", */
859 /* ival + ctx->fdnum % num_per_host); */
860 /* value = cval; */
861 GNUNET_break (0); /* FIXME */
862 }
863 }
864 if (0 == strcmp (option, "UNIXPATH"))
865 {
866 if (GNUNET_YES != GNUNET_CONFIGURATION_get_value_yesno (uc->cfg,
867 "testing",
868 single_variable))
869 {
870 GNUNET_snprintf (uval,
871 sizeof(uval),
872 "%s/%s.sock",
873 uc->gnunet_home,
874 section);
875 value = uval;
876 }
877 else if ((GNUNET_YES ==
878 GNUNET_CONFIGURATION_get_value_number (uc->cfg,
879 "testing",
880 per_host_variable,
881 &num_per_host)) &&
882 (num_per_host > 0))
883 {
884 GNUNET_break (0); /* FIXME */
885 }
886 }
887 if (0 == strcmp (option, "HOSTNAME"))
888 {
889 value = (NULL == uc->system->hostname) ? "localhost" : uc->system->hostname;
890 }
891 GNUNET_free (single_variable);
892 GNUNET_free (per_host_variable);
893 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, option, value);
894}
895
896
897/**
898 * Section iterator to set ACCEPT_FROM/ACCEPT_FROM6 to include the address of
899 * 'trusted_hosts' in all sections
900 *
901 * @param cls the UpdateContext
902 * @param section name of the section
903 */
904static void
905update_config_sections (void *cls, const char *section)
906{
907 struct UpdateContext *uc = cls;
908 char **ikeys;
909 char *val;
910 char *ptr;
911 char *orig_allowed_hosts;
912 char *allowed_hosts;
913 char *ACCEPT_FROM_key;
914 uint16_t ikeys_cnt;
915 uint16_t key;
916
917 ikeys_cnt = 0;
918 val = NULL;
919 /* Ignore certain options from sections. See
920 https://gnunet.org/bugs/view.php?id=2476 */
921 if (GNUNET_YES ==
922 GNUNET_CONFIGURATION_have_value (uc->cfg, section, "TESTING_IGNORE_KEYS"))
923 {
924 GNUNET_assert (GNUNET_YES ==
925 GNUNET_CONFIGURATION_get_value_string (uc->cfg,
926 section,
927 "TESTING_IGNORE_KEYS",
928 &val));
929 ptr = val;
930 for (ikeys_cnt = 0; NULL != (ptr = strstr (ptr, ";")); ikeys_cnt++)
931 ptr++;
932 if (0 == ikeys_cnt)
933 GNUNET_break (0);
934 else
935 {
936 ikeys = GNUNET_malloc ((sizeof(char *)) * ikeys_cnt);
937 ptr = val;
938 for (key = 0; key < ikeys_cnt; key++)
939 {
940 ikeys[key] = ptr;
941 ptr = strstr (ptr, ";");
942 GNUNET_assert (NULL != ptr); /* worked just before... */
943 *ptr = '\0';
944 ptr++;
945 }
946 }
947 }
948 if (0 != ikeys_cnt)
949 {
950 for (key = 0; key < ikeys_cnt; key++)
951 {
952 if (NULL != strstr (ikeys[key], "ADVERTISED_PORT"))
953 break;
954 }
955 if ((key == ikeys_cnt) &&
956 (GNUNET_YES ==
957 GNUNET_CONFIGURATION_have_value (uc->cfg, section, "ADVERTISED_PORT")))
958 {
959 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (uc->cfg,
960 section,
961 "PORT",
962 &ptr))
963 {
964 GNUNET_CONFIGURATION_set_value_string (uc->cfg,
965 section,
966 "ADVERTISED_PORT",
967 ptr);
968 GNUNET_free (ptr);
969 }
970 }
971 for (key = 0; key < ikeys_cnt; key++)
972 {
973 if (NULL != strstr (ikeys[key], "ACCEPT_FROM"))
974 {
975 GNUNET_free (ikeys);
976 GNUNET_free (val);
977 return;
978 }
979 }
980 GNUNET_free (ikeys);
981 }
982 GNUNET_free (val);
983 ACCEPT_FROM_key = "ACCEPT_FROM";
984 if ((NULL != uc->system->trusted_ip) &&
985 (NULL != strstr (uc->system->trusted_ip, ":"))) /* IPv6 in use */
986 ACCEPT_FROM_key = "ACCEPT_FROM6";
987 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (uc->cfg,
988 section,
989 ACCEPT_FROM_key,
990 &orig_allowed_hosts))
991 {
992 orig_allowed_hosts = GNUNET_strdup ("127.0.0.1;");
993 }
994 if (NULL == uc->system->trusted_ip)
995 allowed_hosts = GNUNET_strdup (orig_allowed_hosts);
996 else
997 GNUNET_asprintf (&allowed_hosts,
998 "%s%s;",
999 orig_allowed_hosts,
1000 uc->system->trusted_ip);
1001 GNUNET_free (orig_allowed_hosts);
1002 GNUNET_CONFIGURATION_set_value_string (uc->cfg,
1003 section,
1004 ACCEPT_FROM_key,
1005 allowed_hosts);
1006 GNUNET_free (allowed_hosts);
1007}
1008
1009
1010static struct SharedServiceInstance *
1011associate_shared_service (struct GNUNET_TESTING_System *system,
1012 struct SharedService *ss,
1013 struct GNUNET_CONFIGURATION_Handle *cfg)
1014{
1015 struct SharedServiceInstance *i;
1016 struct GNUNET_CONFIGURATION_Handle *temp;
1017 char *gnunet_home;
1018 uint32_t port;
1019
1020 ss->n_peers++;
1021 if (((0 == ss->share) && (NULL == ss->instances)) ||
1022 ((0 != ss->share) &&
1023 (ss->n_instances < ((ss->n_peers + ss->share - 1) / ss->share))))
1024 {
1025 i = GNUNET_new (struct SharedServiceInstance);
1026 i->ss = ss;
1027 (void) GNUNET_asprintf (&gnunet_home,
1028 "%s/shared/%s/%u",
1029 system->tmppath,
1030 ss->sname,
1031 ss->n_instances);
1032 (void) GNUNET_asprintf (&i->unix_sock, "%s/sock", gnunet_home);
1033 port = GNUNET_TESTING_reserve_port (system);
1034 if (0 == port)
1035 {
1036 GNUNET_free (gnunet_home);
1037 cleanup_shared_service_instance (i);
1038 return NULL;
1039 }
1040 GNUNET_array_append (ss->instances, ss->n_instances, i);
1041 temp = GNUNET_CONFIGURATION_dup (ss->cfg);
1042 (void) GNUNET_asprintf (&i->port_str, "%u", port);
1043 (void) GNUNET_asprintf (&i->cfg_fn, "%s/config", gnunet_home);
1044 GNUNET_CONFIGURATION_set_value_string (temp,
1045 "PATHS",
1046 "GNUNET_HOME",
1047 gnunet_home);
1048 GNUNET_free (gnunet_home);
1049 GNUNET_CONFIGURATION_set_value_string (temp,
1050 ss->sname,
1051 "UNIXPATH",
1052 i->unix_sock);
1053 GNUNET_CONFIGURATION_set_value_string (temp,
1054 ss->sname,
1055 "PORT",
1056 i->port_str);
1057 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write (temp, i->cfg_fn))
1058 {
1059 GNUNET_CONFIGURATION_destroy (temp);
1060 cleanup_shared_service_instance (i);
1061 return NULL;
1062 }
1063 GNUNET_CONFIGURATION_destroy (temp);
1064 }
1065 else
1066 {
1067 GNUNET_assert (NULL != ss->instances);
1068 GNUNET_assert (0 < ss->n_instances);
1069 i = ss->instances[ss->n_instances - 1];
1070 }
1071 GNUNET_CONFIGURATION_iterate_section_values (ss->cfg,
1072 ss->sname,
1073 &cfg_copy_iterator,
1074 cfg);
1075 GNUNET_CONFIGURATION_set_value_string (cfg,
1076 ss->sname,
1077 "UNIXPATH",
1078 i->unix_sock);
1079 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "PORT", i->port_str);
1080 return i;
1081}
1082
1083
1084/**
1085 * Create a new configuration using the given configuration as a template;
1086 * ports and paths will be modified to select available ports on the local
1087 * system. The default configuration will be available in PATHS section under
1088 * the option DEFAULTCONFIG after the call. GNUNET_HOME is also set in PATHS
1089 * section to the temporary directory specific to this configuration. If we run
1090 * out of "*port" numbers, return #GNUNET_SYSERR.
1091 *
1092 * This is primarily a helper function used internally
1093 * by 'GNUNET_TESTING_peer_configure'.
1094 *
1095 * @param system system to use to coordinate resource usage
1096 * @param cfg template configuration to update
1097 * @param ports array with port numbers used in the created configuration.
1098 * Will be updated upon successful return. Can be NULL
1099 * @param nports the size of the `ports' array. Will be updated.
1100 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - the configuration will
1101 * be incomplete and should not be used there upon
1102 */
1103static int
1104GNUNET_TESTING_configuration_create_ (struct GNUNET_TESTING_System *system,
1105 struct GNUNET_CONFIGURATION_Handle *cfg,
1106 uint16_t **ports,
1107 unsigned int *nports)
1108{
1109 struct UpdateContext uc;
1110 char *default_config;
1111
1112 uc.system = system;
1113 uc.cfg = cfg;
1114 uc.status = GNUNET_OK;
1115 uc.ports = NULL;
1116 uc.nports = 0;
1117 GNUNET_asprintf (&uc.gnunet_home,
1118 "%s/%u",
1119 system->tmppath,
1120 system->path_counter++);
1121 GNUNET_asprintf (&default_config, "%s/config", uc.gnunet_home);
1122 GNUNET_CONFIGURATION_set_value_string (cfg,
1123 "PATHS",
1124 "DEFAULTCONFIG",
1125 default_config);
1126 GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG", default_config);
1127 GNUNET_free (default_config);
1128 GNUNET_CONFIGURATION_set_value_string (cfg,
1129 "PATHS",
1130 "GNUNET_HOME",
1131 uc.gnunet_home);
1132 /* make PORTs and UNIXPATHs unique */
1133 GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
1134 /* allow connections to services from system trusted_ip host */
1135 GNUNET_CONFIGURATION_iterate_sections (cfg, &update_config_sections, &uc);
1136 /* enable loopback-based connections between peers */
1137 GNUNET_CONFIGURATION_set_value_string (cfg, "nat", "USE_LOCALADDR", "YES");
1138 GNUNET_free (uc.gnunet_home);
1139 if ((NULL != ports) && (NULL != nports))
1140 {
1141 *ports = uc.ports;
1142 *nports = uc.nports;
1143 }
1144 else
1145 GNUNET_free (uc.ports);
1146 return uc.status;
1147}
1148
1149
1150/**
1151 * Create a new configuration using the given configuration as a template;
1152 * ports and paths will be modified to select available ports on the local
1153 * system. The default configuration will be available in PATHS section under
1154 * the option DEFAULTCONFIG after the call. GNUNET_HOME is also set in PATHS
1155 * section to the temporary directory specific to this configuration. If we run
1156 * out of "*port" numbers, return #GNUNET_SYSERR.
1157 *
1158 * This is primarily a helper function used internally
1159 * by #GNUNET_TESTING_peer_configure().
1160 *
1161 * @param system system to use to coordinate resource usage
1162 * @param cfg template configuration to update
1163 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - the configuration will
1164 * be incomplete and should not be used there upon
1165 */
1166int
1167GNUNET_TESTING_configuration_create (struct GNUNET_TESTING_System *system,
1168 struct GNUNET_CONFIGURATION_Handle *cfg)
1169{
1170 return GNUNET_TESTING_configuration_create_ (system, cfg, NULL, NULL);
1171}
1172
1173
1174/**
1175 * Configure a GNUnet peer. GNUnet must be installed on the local
1176 * system and available in the PATH.
1177 *
1178 * @param system system to use to coordinate resource usage
1179 * @param cfg configuration to use; will be UPDATED (to reflect needed
1180 * changes in port numbers and paths)
1181 * @param key_number number of the hostkey to use for the peer
1182 * @param id identifier for the daemon, will be set, can be NULL
1183 * @param emsg set to freshly allocated error message (set to NULL on success),
1184 * can be NULL
1185 * @return handle to the peer, NULL on error
1186 */
1187struct GNUNET_TESTING_Peer *
1188GNUNET_TESTING_peer_configure (struct GNUNET_TESTING_System *system,
1189 struct GNUNET_CONFIGURATION_Handle *cfg,
1190 uint32_t key_number,
1191 struct GNUNET_PeerIdentity *id,
1192 char **emsg)
1193{
1194 struct GNUNET_TESTING_Peer *peer;
1195 struct GNUNET_DISK_FileHandle *fd;
1196 char *hostkey_filename;
1197 char *config_filename;
1198 char *libexec_binary;
1199 char *emsg_;
1200 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
1201 uint16_t *ports;
1202 struct SharedService *ss;
1203 struct SharedServiceInstance **ss_instances;
1204 unsigned int cnt;
1205 unsigned int nports;
1206
1207 ports = NULL;
1208 nports = 0;
1209 ss_instances = NULL;
1210 if (NULL != emsg)
1211 *emsg = NULL;
1212 if (key_number >= system->total_hostkeys)
1213 {
1214 GNUNET_asprintf (
1215 &emsg_,
1216 _ (
1217 "You attempted to create a testbed with more than %u hosts. Please precompute more hostkeys first.\n"),
1218 (unsigned int) system->total_hostkeys);
1219 goto err_ret;
1220 }
1221 pk = NULL;
1222 if ((NULL != id) &&
1223 (NULL == (pk = GNUNET_TESTING_hostkey_get (system, key_number, id))))
1224 {
1225 GNUNET_asprintf (&emsg_,
1226 _ ("Failed to initialize hostkey for peer %u\n"),
1227 (unsigned int) key_number);
1228 goto err_ret;
1229 }
1230 if (NULL != pk)
1231 GNUNET_free (pk);
1232 if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (cfg, "PEER", "PRIVATE_KEY"))
1233 {
1234 GNUNET_asprintf (
1235 &emsg_,
1236 _ ("PRIVATE_KEY option in PEER section missing in configuration\n"));
1237 goto err_ret;
1238 }
1239 /* Remove sections for shared services */
1240 for (cnt = 0; cnt < system->n_shared_services; cnt++)
1241 {
1242 ss = &system->shared_services[cnt];
1243 GNUNET_CONFIGURATION_remove_section (cfg, ss->sname);
1244 }
1245 if (GNUNET_OK !=
1246 GNUNET_TESTING_configuration_create_ (system, cfg, &ports, &nports))
1247 {
1248 GNUNET_asprintf (&emsg_,
1249 _ ("Failed to create configuration for peer "
1250 "(not enough free ports?)\n"));
1251 goto err_ret;
1252 }
1253 GNUNET_assert (GNUNET_OK ==
1254 GNUNET_CONFIGURATION_get_value_filename (cfg,
1255 "PEER",
1256 "PRIVATE_KEY",
1257 &hostkey_filename));
1258 fd = GNUNET_DISK_file_open (hostkey_filename,
1259 GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE,
1260 GNUNET_DISK_PERM_USER_READ
1261 | GNUNET_DISK_PERM_USER_WRITE);
1262 if (NULL == fd)
1263 {
1264 GNUNET_asprintf (&emsg_,
1265 _ ("Cannot open hostkey file `%s': %s\n"),
1266 hostkey_filename,
1267 strerror (errno));
1268 GNUNET_free (hostkey_filename);
1269 goto err_ret;
1270 }
1271 GNUNET_free (hostkey_filename);
1272 if (GNUNET_TESTING_HOSTKEYFILESIZE !=
1273 GNUNET_DISK_file_write (fd,
1274 system->hostkeys_data
1275 + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
1276 GNUNET_TESTING_HOSTKEYFILESIZE))
1277 {
1278 GNUNET_asprintf (&emsg_,
1279 _ ("Failed to write hostkey file for peer %u: %s\n"),
1280 (unsigned int) key_number,
1281 strerror (errno));
1282 GNUNET_DISK_file_close (fd);
1283 goto err_ret;
1284 }
1285 GNUNET_DISK_file_close (fd);
1286 ss_instances = GNUNET_new_array (system->n_shared_services,
1287 struct SharedServiceInstance*);
1288 for (cnt = 0; cnt < system->n_shared_services; cnt++)
1289 {
1290 ss = &system->shared_services[cnt];
1291 ss_instances[cnt] = associate_shared_service (system, ss, cfg);
1292 if (NULL == ss_instances[cnt])
1293 {
1294 emsg_ = GNUNET_strdup ("FIXME");
1295 goto err_ret;
1296 }
1297 }
1298 GNUNET_assert (GNUNET_OK ==
1299 GNUNET_CONFIGURATION_get_value_filename (cfg,
1300 "PATHS",
1301 "DEFAULTCONFIG",
1302 &config_filename));
1303 if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config_filename))
1304 {
1305 GNUNET_asprintf (&emsg_,
1306 _ (
1307 "Failed to write configuration file `%s' for peer %u: %s\n"),
1308 config_filename,
1309 (unsigned int) key_number,
1310 strerror (errno));
1311 GNUNET_free (config_filename);
1312 goto err_ret;
1313 }
1314 peer = GNUNET_new (struct GNUNET_TESTING_Peer);
1315 peer->ss_instances = ss_instances;
1316 peer->cfgfile = config_filename; /* Free in peer_destroy */
1317 peer->cfg = GNUNET_CONFIGURATION_dup (cfg);
1318 libexec_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
1319 if (GNUNET_SYSERR ==
1320 GNUNET_CONFIGURATION_get_value_string (cfg,
1321 "arm",
1322 "PREFIX",
1323 &peer->main_binary))
1324 {
1325 /* No prefix */
1326 GNUNET_asprintf (&peer->main_binary, "%s", libexec_binary);
1327 peer->args = GNUNET_strdup ("");
1328 }
1329 else
1330 {
1331 peer->args = GNUNET_strdup (libexec_binary);
1332 }
1333 peer->system = system;
1334 peer->key_number = key_number;
1335 GNUNET_free (libexec_binary);
1336 peer->ports = ports; /* Free in peer_destroy */
1337 peer->nports = nports;
1338 return peer;
1339
1340err_ret:
1341 GNUNET_free (ss_instances);
1342 GNUNET_free (ports);
1343 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_);
1344 if (NULL != emsg)
1345 *emsg = emsg_;
1346 else
1347 GNUNET_free (emsg_);
1348 return NULL;
1349}
1350
1351
1352/**
1353 * Obtain the peer identity from a peer handle.
1354 *
1355 * @param peer peer handle for which we want the peer's identity
1356 * @param id identifier for the daemon, will be set
1357 */
1358void
1359GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer,
1360 struct GNUNET_PeerIdentity *id)
1361{
1362 if (NULL != peer->id)
1363 {
1364 GNUNET_memcpy (id, peer->id, sizeof(struct GNUNET_PeerIdentity));
1365 return;
1366 }
1367 peer->id = GNUNET_new (struct GNUNET_PeerIdentity);
1368 GNUNET_free_nz (
1369 GNUNET_TESTING_hostkey_get (peer->system, peer->key_number, peer->id));
1370 GNUNET_memcpy (id, peer->id, sizeof(struct GNUNET_PeerIdentity));
1371}
1372
1373
1374/**
1375 * Start the peer.
1376 *
1377 * @param peer peer to start
1378 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error (i.e. peer already running)
1379 */
1380int
1381GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer)
1382{
1383 struct SharedServiceInstance *i;
1384 unsigned int cnt;
1385
1386 if (NULL != peer->main_process)
1387 {
1388 GNUNET_break (0);
1389 return GNUNET_SYSERR;
1390 }
1391 GNUNET_assert (NULL != peer->cfgfile);
1392 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1393 {
1394 i = peer->ss_instances[cnt];
1395 if ((0 == i->n_refs) &&
1396 (GNUNET_SYSERR == start_shared_service_instance (i)))
1397 return GNUNET_SYSERR;
1398 i->n_refs++;
1399 }
1400 peer->main_binary =
1401 GNUNET_CONFIGURATION_expand_dollar (peer->cfg, peer->main_binary);
1402 peer->main_process =
1403 GNUNET_OS_start_process_s (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
1404 NULL,
1405 peer->main_binary,
1406 peer->args,
1407 "-c",
1408 peer->cfgfile,
1409 NULL);
1410 if (NULL == peer->main_process)
1411 {
1412 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1413 _ ("Failed to start `%s': %s\n"),
1414 peer->main_binary,
1415 strerror (errno));
1416 return GNUNET_SYSERR;
1417 }
1418 return GNUNET_OK;
1419}
1420
1421
1422/**
1423 * Sends SIGTERM to the peer's main process
1424 *
1425 * @param peer the handle to the peer
1426 * @return #GNUNET_OK if successful; #GNUNET_SYSERR if the main process is NULL
1427 * or upon any error while sending SIGTERM
1428 */
1429int
1430GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer)
1431{
1432 struct SharedServiceInstance *i;
1433 unsigned int cnt;
1434
1435 if (NULL == peer->main_process)
1436 {
1437 GNUNET_break (0);
1438 return GNUNET_SYSERR;
1439 }
1440 if (0 != GNUNET_OS_process_kill (peer->main_process, GNUNET_TERM_SIG))
1441 return GNUNET_SYSERR;
1442 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1443 {
1444 i = peer->ss_instances[cnt];
1445 GNUNET_assert (0 != i->n_refs);
1446 i->n_refs--;
1447 if (0 == i->n_refs)
1448 stop_shared_service_instance (i);
1449 }
1450 return GNUNET_OK;
1451}
1452
1453
1454/**
1455 * Waits for a peer to terminate. The peer's main process will also be destroyed.
1456 *
1457 * @param peer the handle to the peer
1458 * @return #GNUNET_OK if successful; #GNUNET_SYSERR if the main process is NULL
1459 * or upon any error while waiting
1460 */
1461int
1462GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer)
1463{
1464 int ret;
1465
1466 if (NULL == peer->main_process)
1467 {
1468 GNUNET_break (0);
1469 return GNUNET_SYSERR;
1470 }
1471 ret = GNUNET_OS_process_wait (peer->main_process);
1472 GNUNET_OS_process_destroy (peer->main_process);
1473 peer->main_process = NULL;
1474 return ret;
1475}
1476
1477
1478/**
1479 * Stop the peer.
1480 *
1481 * @param peer peer to stop
1482 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1483 */
1484int
1485GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer)
1486{
1487 if (GNUNET_SYSERR == GNUNET_TESTING_peer_kill (peer))
1488 return GNUNET_SYSERR;
1489 if (GNUNET_SYSERR == GNUNET_TESTING_peer_wait (peer))
1490 return GNUNET_SYSERR;
1491 return GNUNET_OK;
1492}
1493
1494
1495/**
1496 * Function called whenever we connect to or disconnect from ARM.
1497 *
1498 * @param cls closure
1499 * @param connected #GNUNET_YES if connected, #GNUNET_NO if disconnected,
1500 * #GNUNET_SYSERR on error.
1501 */
1502static void
1503disconn_status (void *cls, int connected)
1504{
1505 struct GNUNET_TESTING_Peer *peer = cls;
1506
1507 if (GNUNET_SYSERR == connected)
1508 {
1509 peer->cb (peer->cb_cls, peer, connected);
1510 return;
1511 }
1512 if (GNUNET_YES == connected)
1513 {
1514 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_kill (peer));
1515 return;
1516 }
1517 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer));
1518 GNUNET_ARM_disconnect (peer->ah);
1519 peer->ah = NULL;
1520 peer->cb (peer->cb_cls, peer, GNUNET_YES);
1521}
1522
1523
1524int
1525GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer,
1526 GNUNET_TESTING_PeerStopCallback cb,
1527 void *cb_cls)
1528{
1529 if (NULL == peer->main_process)
1530 return GNUNET_SYSERR;
1531 peer->ah = GNUNET_ARM_connect (peer->cfg, &disconn_status, peer);
1532 if (NULL == peer->ah)
1533 return GNUNET_SYSERR;
1534 peer->cb = cb;
1535 peer->cb_cls = cb_cls;
1536 return GNUNET_OK;
1537}
1538
1539
1540/**
1541 * Cancel a previous asynchronous peer stop request.
1542 * GNUNET_TESTING_peer_stop_async() should have been called before on the given
1543 * peer. It is an error to call this function if the peer stop callback was
1544 * already called
1545 *
1546 * @param peer the peer on which GNUNET_TESTING_peer_stop_async() was called
1547 * before.
1548 */
1549void
1550GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer)
1551{
1552 GNUNET_assert (NULL != peer->ah);
1553 GNUNET_ARM_disconnect (peer->ah);
1554 peer->ah = NULL;
1555}
1556
1557
1558/**
1559 * Destroy the peer. Releases resources locked during peer configuration.
1560 * If the peer is still running, it will be stopped AND a warning will be
1561 * printed (users of the API should stop the peer explicitly first).
1562 *
1563 * @param peer peer to destroy
1564 */
1565void
1566GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer)
1567{
1568 unsigned int cnt;
1569
1570 if (NULL != peer->main_process)
1571 GNUNET_TESTING_peer_stop (peer);
1572 if (NULL != peer->ah)
1573 GNUNET_ARM_disconnect (peer->ah);
1574 GNUNET_free (peer->cfgfile);
1575 if (NULL != peer->cfg)
1576 GNUNET_CONFIGURATION_destroy (peer->cfg);
1577 GNUNET_free (peer->main_binary);
1578 GNUNET_free (peer->args);
1579 GNUNET_free (peer->id);
1580 GNUNET_free (peer->ss_instances);
1581 if (NULL != peer->ports)
1582 {
1583 for (cnt = 0; cnt < peer->nports; cnt++)
1584 GNUNET_TESTING_release_port (peer->system, peer->ports[cnt]);
1585 GNUNET_free (peer->ports);
1586 }
1587 GNUNET_free (peer);
1588}
1589
1590
1591int
1592GNUNET_TESTING_peer_run (const char *testdir,
1593 const char *cfgfilename,
1594 GNUNET_TESTING_TestMain tm,
1595 void *tm_cls)
1596{
1597 return GNUNET_TESTING_service_run (testdir, "arm", cfgfilename, tm, tm_cls);
1598}
1599
1600
1601/**
1602 * Structure for holding service data
1603 */
1604struct ServiceContext
1605{
1606 /**
1607 * The configuration of the peer in which the service is run
1608 */
1609 const struct GNUNET_CONFIGURATION_Handle *cfg;
1610
1611 /**
1612 * Callback to signal service startup
1613 */
1614 GNUNET_TESTING_TestMain tm;
1615
1616 /**
1617 * The peer in which the service is run.
1618 */
1619 struct GNUNET_TESTING_Peer *peer;
1620
1621 /**
1622 * Closure for the above callback
1623 */
1624 void *tm_cls;
1625};
1626
1627
1628/**
1629 * Callback to be called when SCHEDULER has been started
1630 *
1631 * @param cls the ServiceContext
1632 */
1633static void
1634service_run_main (void *cls)
1635{
1636 struct ServiceContext *sc = cls;
1637
1638 sc->tm (sc->tm_cls, sc->cfg, sc->peer);
1639}
1640
1641
1642int
1643GNUNET_TESTING_service_run (const char *testdir,
1644 const char *service_name,
1645 const char *cfgfilename,
1646 GNUNET_TESTING_TestMain tm,
1647 void *tm_cls)
1648{
1649 struct ServiceContext sc;
1650 struct GNUNET_TESTING_System *system;
1651 struct GNUNET_TESTING_Peer *peer;
1652 struct GNUNET_CONFIGURATION_Handle *cfg;
1653 char *binary;
1654 char *libexec_binary;
1655
1656 GNUNET_log_setup (testdir, "WARNING", NULL);
1657 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL);
1658 if (NULL == system)
1659 return 1;
1660 cfg = GNUNET_CONFIGURATION_create ();
1661 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgfilename))
1662 {
1663 LOG (GNUNET_ERROR_TYPE_ERROR,
1664 _ ("Failed to load configuration from %s\n"),
1665 cfgfilename);
1666 GNUNET_CONFIGURATION_destroy (cfg);
1667 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1668 return 1;
1669 }
1670 peer = GNUNET_TESTING_peer_configure (system, cfg, 0, NULL, NULL);
1671 if (NULL == peer)
1672 {
1673 GNUNET_CONFIGURATION_destroy (cfg);
1674 hostkeys_unload (system);
1675 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1676 return 1;
1677 }
1678 GNUNET_free (peer->main_binary);
1679 GNUNET_free (peer->args);
1680 GNUNET_asprintf (&binary, "gnunet-service-%s", service_name);
1681 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
1682 if (GNUNET_SYSERR ==
1683 GNUNET_CONFIGURATION_get_value_string (cfg,
1684 service_name,
1685 "PREFIX",
1686 &peer->main_binary))
1687 {
1688 /* No prefix */
1689 GNUNET_asprintf (&peer->main_binary, "%s", libexec_binary);
1690 peer->args = GNUNET_strdup ("");
1691 }
1692 else
1693 peer->args = GNUNET_strdup (libexec_binary);
1694
1695 GNUNET_free (libexec_binary);
1696 GNUNET_free (binary);
1697 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer))
1698 {
1699 GNUNET_TESTING_peer_destroy (peer);
1700 GNUNET_CONFIGURATION_destroy (cfg);
1701 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1702 return 1;
1703 }
1704 sc.cfg = cfg;
1705 sc.tm = tm;
1706 sc.tm_cls = tm_cls;
1707 sc.peer = peer;
1708 GNUNET_SCHEDULER_run (&service_run_main, &sc); /* Scheduler loop */
1709 if ((NULL != peer->main_process) &&
1710 (GNUNET_OK != GNUNET_TESTING_peer_stop (peer)))
1711 {
1712 GNUNET_TESTING_peer_destroy (peer);
1713 GNUNET_CONFIGURATION_destroy (cfg);
1714 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1715 return 1;
1716 }
1717 GNUNET_TESTING_peer_destroy (peer);
1718 GNUNET_CONFIGURATION_destroy (cfg);
1719 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1720 return 0;
1721}
1722
1723
1724/**
1725 * Every line in the topology configuration starts with a string indicating which
1726 * kind of information will be configured with this line. Configuration values following
1727 * this string are seperated by special sequences of characters. An integer value seperated
1728 * by ':' is returned by this function.
1729 *
1730 * @param line The line of configuration.
1731 * @return An integer value.
1732 */
1733static unsigned int
1734get_first_value (const char *line)
1735{
1736 char *copy;
1737 size_t slen;
1738 char *token;
1739 unsigned int ret;
1740 char *rest = NULL;
1741
1742 slen = strlen (line) + 1;
1743 copy = GNUNET_malloc (slen);
1744 memcpy (copy, line, slen);
1745 token = strtok_r (copy, ":", &rest);
1746 token = strtok_r (NULL, ":", &rest);
1747 GNUNET_assert (1 == sscanf (token, "%u", &ret));
1748 GNUNET_free (copy);
1749 return ret;
1750}
1751
1752
1753/**
1754 * Every line in the topology configuration starts with a string indicating which
1755 * kind of information will be configured with this line. This string is returned by this function.
1756 *
1757 * @param line The line of configuration.
1758 * @return The leading string of this configuration line.
1759 */
1760static char *
1761get_key (const char *line)
1762{
1763 char *copy;
1764 size_t slen;
1765 size_t tlen;
1766 char *token;
1767 char *ret;
1768 char *rest = NULL;
1769
1770 slen = strlen (line) + 1;
1771 copy = GNUNET_malloc (slen);
1772 memcpy (copy, line, slen);
1773 token = strtok_r (copy, ":", &rest);
1774 tlen = strlen (token) + 1;
1775 ret = GNUNET_malloc (tlen);
1776 memcpy (ret, token, tlen);
1777 GNUNET_free (copy);
1778 return ret;
1779}
1780
1781
1782/**
1783 * Every line in the topology configuration starts with a string indicating which
1784 * kind of information will be configured with this line. Configuration values following
1785 * this string are seperated by special sequences of characters. A string value seperated
1786 * by ':' is returned by this function.
1787 *
1788 * @param line The line of configuration.
1789 * @return A string value.
1790 */
1791static char *
1792get_first_string_value (const char *line)
1793{
1794 char *copy;
1795 size_t slen, slen_token;
1796 char *token;
1797 char *ret;
1798 char *rest = NULL;
1799
1800 slen = strlen (line) + 1;
1801 copy = GNUNET_malloc (slen);
1802 memcpy (copy, line, slen);
1803 token = strtok_r (copy, ":", &rest);
1804 token = strtok_r (NULL, ":", &rest);
1805 LOG (GNUNET_ERROR_TYPE_DEBUG,
1806 "first token %s\n",
1807 token);
1808 slen_token = strlen (token);
1809 ret = GNUNET_malloc (slen_token + 1);
1810 memcpy (ret, token, slen_token + 1);
1811 GNUNET_free (copy);
1812 return ret;
1813}
1814
1815
1816/**
1817 * Every line in the topology configuration starts with a string indicating which
1818 * kind of information will be configured with this line. Configuration values following
1819 * this string are seperated by special sequences of characters. A second integer value
1820 * seperated by ':' from a first value is returned by this function.
1821 *
1822 * @param line The line of configuration.
1823 * @return An integer value.
1824 */
1825static unsigned int
1826get_second_value (const char *line)
1827{
1828 char *copy;
1829 char *token;
1830 unsigned int ret;
1831 char *rest = NULL;
1832
1833 copy = GNUNET_strdup (line);
1834 token = strtok_r (copy, ":", &rest);
1835 token = strtok_r (NULL, ":", &rest);
1836 token = strtok_r (NULL, ":", &rest);
1837 LOG (GNUNET_ERROR_TYPE_ERROR,
1838 "Format error in configuration line: %s\n",
1839 line);
1840 GNUNET_assert (1 == sscanf (token, "%u", &ret));
1841 GNUNET_free (copy);
1842 return ret;
1843}
1844
1845
1846/**
1847 * Every line in the topology configuration starts with a string indicating which
1848 * kind of information will be configured with this line. Configuration values following
1849 * this string are seperated by special sequences of characters. A value might be
1850 * a key value pair.
1851 * This function returns the value for a specific key in a configuration line.
1852 *
1853 * @param key The key of the key value pair.
1854 * @return The value of the key value pair.
1855 */
1856static char *
1857get_value (const char *key, const char *line)
1858{
1859 char copy[strlen (line) + 1];
1860 size_t slen;
1861 char *token;
1862 char *token2;
1863 char *temp;
1864 char *rest = NULL;
1865
1866 slen = strlen (line) + 1;
1867 memcpy (copy, line, slen);
1868 temp = strstr (copy, key);
1869 if (NULL == temp)
1870 return NULL;
1871 token = strtok_r (temp, ":", &rest);
1872 if (NULL == token)
1873 return NULL;
1874 token = strtok_r (NULL, ":", &rest);
1875 if (NULL == token)
1876 return NULL;
1877 token2 = strtok_r (token, "}", &rest);
1878 if (NULL == token2)
1879 return NULL;
1880 return GNUNET_strdup (token2);
1881}
1882
1883
1884/**
1885 * Every line in the topology configuration starts with a string indicating which
1886 * kind of information will be configured with this line. Configuration values following
1887 * this string are seperated by special sequences of characters. A value might be
1888 * a key value pair. A special key is the 'connect' key which can appear more than once.
1889 * The value is the information about a connection via some protocol to some other node.
1890 * This function returns the struct GNUNET_TESTING_NodeConnection which holds the information
1891 * of the connect value.
1892 *
1893 * @param value The value of the connect key value pair.
1894 * @return The struct GNUNET_TESTING_NodeConnection.
1895 */
1896static struct GNUNET_TESTING_NodeConnection *
1897get_connect_value (const char *line,
1898 struct GNUNET_TESTING_NetjailNode *node)
1899{
1900 struct GNUNET_TESTING_NodeConnection *node_connection;
1901 char *copy;
1902 char *token;
1903 char *token2;
1904 unsigned int node_n;
1905 unsigned int namespace_n;
1906 char *rest = NULL;
1907 char *rest2 = NULL;
1908 struct GNUNET_TESTING_AddressPrefix *prefix;
1909 unsigned int sscanf_ret;
1910
1911 node_connection = GNUNET_new (struct GNUNET_TESTING_NodeConnection);
1912 node_connection->node = node;
1913
1914 copy = GNUNET_strdup (line);
1915 token = strtok_r (copy, ":", &rest);
1916 if (0 == strcmp ("{K", token))
1917 {
1918 node_connection->node_type = GNUNET_TESTING_GLOBAL_NODE;
1919 token = strtok_r (NULL, ":", &rest);
1920 GNUNET_assert (1 == sscanf (token, "%u", &node_n));
1921 LOG (GNUNET_ERROR_TYPE_DEBUG,
1922 "node_n %u\n",
1923 node_n);
1924 node_connection->node_n = node_n;
1925 node_connection->namespace_n = 0;
1926 }
1927 else if (0 == strcmp ("{P", token))
1928 {
1929 node_connection->node_type = GNUNET_TESTING_SUBNET_NODE;
1930 token = strtok_r (NULL, ":", &rest);
1931 errno = 0;
1932 sscanf_ret = sscanf (token, "%u", &namespace_n);
1933 if (errno != 0)
1934 {
1935 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
1936 }
1937 GNUNET_assert (0 < sscanf_ret);
1938 node_connection->namespace_n = namespace_n;
1939 token = strtok_r (NULL, ":", &rest);
1940 errno = 0;
1941 sscanf_ret = sscanf (token, "%u", &node_n);
1942 if (errno != 0)
1943 {
1944 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
1945 }
1946 GNUNET_assert (0 < sscanf_ret);
1947 node_connection->node_n = node_n;
1948 LOG (GNUNET_ERROR_TYPE_DEBUG,
1949 "node_n %u namespace_n %u node->node_n %u node->namespace_n %u\n",
1950 node_n,
1951 namespace_n,
1952 node->node_n,
1953 node->namespace_n);
1954 }
1955 else
1956 {
1957 GNUNET_break (0);
1958 GNUNET_free (node_connection);
1959 GNUNET_free (copy);
1960 return NULL;
1961 }
1962
1963 while (NULL != (token = strtok_r (NULL, ":", &rest)))
1964 {
1965 prefix = GNUNET_new (struct GNUNET_TESTING_AddressPrefix);
1966 token2 = strtok_r (token, "}", &rest2);
1967 if (NULL != token2)
1968 prefix->address_prefix = GNUNET_strdup (token2);
1969 else
1970 prefix->address_prefix = GNUNET_strdup (token);
1971
1972 LOG (GNUNET_ERROR_TYPE_DEBUG,
1973 "address_prefix %s\n",
1974 prefix->address_prefix);
1975
1976 GNUNET_CONTAINER_DLL_insert (node_connection->address_prefixes_head,
1977 node_connection->address_prefixes_tail,
1978 prefix);
1979 LOG (GNUNET_ERROR_TYPE_DEBUG,
1980 "address_prefix %s\n",
1981 prefix->address_prefix);
1982 }
1983
1984 GNUNET_free (copy);
1985 return node_connection;
1986}
1987
1988
1989/**
1990 * Every line in the topology configuration starts with a string indicating which
1991 * kind of information will be configured with this line. Configuration values following
1992 * this string are seperated by special sequences of characters. A value might be
1993 * a key value pair. A special key is the 'connect' key.
1994 * The value is the information about a connections via some protocol to other nodes.
1995 * Each connection itself is a key value pair separated by the character '|' and
1996 * surrounded by the characters '{' and '}'.
1997 * The struct GNUNET_TESTING_NodeConnection holds the information of each connection value.
1998 * This function extracts the values of each connection into a DLL of
1999 * struct GNUNET_TESTING_NodeConnection which will be added to a node.
2000 *
2001 * @param line The line of configuration.
2002 * @param node The struct GNUNET_TESTING_NetjailNode to which the DLL of
2003 * struct GNUNET_TESTING_NodeConnection will be added.
2004 */
2005static void
2006node_connections (const char *line, struct GNUNET_TESTING_NetjailNode *node)
2007{
2008 char *value, *value2;
2009 char *temp;
2010 char *copy;
2011 char *rest = NULL;
2012 char *rest2 = NULL;
2013 struct GNUNET_TESTING_NodeConnection *node_connection;
2014
2015
2016 temp = strstr (line, "connect");
2017 if (NULL != temp)
2018 {
2019 copy = GNUNET_strdup (temp);
2020 strtok_r (copy, ":", &rest);
2021 value = strtok_r (rest, "|", &rest2);
2022
2023 while (NULL != value)
2024 {
2025 LOG (GNUNET_ERROR_TYPE_DEBUG,
2026 "node_connections value %s\n",
2027 value);
2028 node_connection = get_connect_value (value, node);
2029 if (NULL == node_connection)
2030 {
2031 LOG (GNUNET_ERROR_TYPE_WARNING,
2032 "connect key was not expected in this configuration line: %s\n",
2033 line);
2034 break;
2035 }
2036 GNUNET_CONTAINER_DLL_insert (node->node_connections_head,
2037 node->node_connections_tail,
2038 node_connection);
2039 value2 = strstr (value, "}}");
2040 if (NULL != value2)
2041 break;
2042 value = strtok_r (NULL, "|", &rest2);
2043
2044 }
2045 GNUNET_free (copy);
2046 }
2047}
2048
2049
2050/**
2051 * A helper function to log information about individual nodes.
2052 *
2053 * @param cls This is not used actually.
2054 * @param id The key of this value in the map.
2055 * @param value A struct GNUNET_TESTING_NetjailNode which holds information about a node.
2056 * return GNUNET_YES to continue with iterating, GNUNET_NO otherwise.
2057 */
2058static int
2059log_nodes (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
2060{
2061 struct GNUNET_TESTING_NetjailNode *node = value;
2062 struct GNUNET_TESTING_NodeConnection *pos_connection;
2063 struct GNUNET_TESTING_AddressPrefix *pos_prefix;
2064
2065 LOG (GNUNET_ERROR_TYPE_DEBUG,
2066 "plugin: %s space: %u node: %u global: %u\n",
2067 node->plugin,
2068 node->namespace_n,
2069 node->node_n,
2070 node->is_global);
2071
2072 for (pos_connection = node->node_connections_head; NULL != pos_connection;
2073 pos_connection = pos_connection->next)
2074 {
2075
2076 LOG (GNUNET_ERROR_TYPE_DEBUG,
2077 "namespace_n: %u node_n: %u node_type: %u\n",
2078 pos_connection->namespace_n,
2079 pos_connection->node_n,
2080 pos_connection->node_type);
2081
2082 for (pos_prefix = pos_connection->address_prefixes_head; NULL != pos_prefix;
2083 pos_prefix =
2084 pos_prefix->next)
2085 {
2086 LOG (GNUNET_ERROR_TYPE_DEBUG,
2087 "prefix: %s\n",
2088 pos_prefix->address_prefix);
2089 }
2090 }
2091 return GNUNET_YES;
2092}
2093
2094
2095/**
2096 * Helper function to log information about namespaces.
2097 *
2098 * @param cls This is not used actually.
2099 * @param id The key of this value in the map.
2100 * @param value A struct GNUNET_TESTING_NetjailNamespace which holds information about a subnet.
2101 * return GNUNET_YES to continue with iterating, GNUNET_NO otherwise.
2102 */
2103static int
2104log_namespaces (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
2105{
2106 struct GNUNET_TESTING_NetjailNamespace *namespace = value;
2107
2108 GNUNET_CONTAINER_multishortmap_iterate (namespace->nodes, &log_nodes, NULL);
2109 return GNUNET_YES;
2110}
2111
2112
2113/**
2114 * Helper function to log the configuration in case of a problem with configuration.
2115 *
2116 * @param topology The struct GNUNET_TESTING_NetjailTopology holding the configuration information.
2117 */
2118static int
2119log_topo (const struct GNUNET_TESTING_NetjailTopology *topology)
2120{
2121 LOG (GNUNET_ERROR_TYPE_DEBUG,
2122 "plugin: %s spaces: %u nodes: %u known: %u\n",
2123 topology->plugin,
2124 topology->namespaces_n,
2125 topology->nodes_m,
2126 topology->nodes_x);
2127
2128 GNUNET_CONTAINER_multishortmap_iterate (topology->map_namespaces,
2129 log_namespaces, NULL);
2130 GNUNET_CONTAINER_multishortmap_iterate (topology->map_globals, &log_nodes,
2131 NULL);
2132 return GNUNET_YES;
2133}
2134
2135
2136/**
2137 * This function extracts information about a specific node from the topology.
2138 *
2139 * @param num The global index number of the node.
2140 * @param[out] node_ex A struct GNUNET_TESTING_NetjailNode with information about the node.
2141 * @param[out] namespace_ex A struct GNUNET_TESTING_NetjailNamespace with information about the namespace
2142 the node is in or NULL, if the node is a global node.
2143 * @param[out] node_connections_ex A struct GNUNET_TESTING_NodeConnection with information about the connection
2144 of this node to other nodes.
2145*/
2146static void
2147get_node_info (unsigned int num,
2148 const struct GNUNET_TESTING_NetjailTopology *topology,
2149 struct GNUNET_TESTING_NetjailNode **node_ex,
2150 struct GNUNET_TESTING_NetjailNamespace **namespace_ex,
2151 struct GNUNET_TESTING_NodeConnection **node_connections_ex)
2152{
2153 struct GNUNET_ShortHashCode hkey;
2154 struct GNUNET_HashCode hc;
2155 unsigned int namespace_n;
2156 unsigned int node_m;
2157 struct GNUNET_TESTING_NetjailNode *node;
2158 struct GNUNET_TESTING_NetjailNamespace *namespace;
2159 struct GNUNET_TESTING_NodeConnection *node_connections = NULL;
2160
2161 log_topo (topology);
2162 LOG (GNUNET_ERROR_TYPE_DEBUG,
2163 "num: %u \n",
2164 num);
2165 if (topology->nodes_x >= num)
2166 {
2167
2168 GNUNET_CRYPTO_hash (&num, sizeof(num), &hc);
2169 memcpy (&hkey,
2170 &hc,
2171 sizeof (hkey));
2172 node = GNUNET_CONTAINER_multishortmap_get (topology->map_globals,
2173 &hkey);
2174 if (NULL != node)
2175 {
2176 *node_ex = node;
2177 *node_connections_ex = node->node_connections_head;
2178 }
2179 }
2180 else
2181 {
2182 namespace_n = (unsigned int) ceil ((double) (num - topology->nodes_x)
2183 / topology->nodes_m);
2184 LOG (GNUNET_ERROR_TYPE_DEBUG,
2185 "ceil num: %u nodes_x: %u nodes_m: %u namespace_n: %u\n",
2186 num,
2187 topology->nodes_x,
2188 topology->nodes_m,
2189 namespace_n);
2190 GNUNET_CRYPTO_hash (&namespace_n, sizeof(namespace_n), &hc);
2191 memcpy (&hkey,
2192 &hc,
2193 sizeof (hkey));
2194 namespace = GNUNET_CONTAINER_multishortmap_get (topology->map_namespaces,
2195 &hkey);
2196 if (NULL != namespace)
2197 {
2198 node_m = num - topology->nodes_x - topology->nodes_m * (namespace_n - 1);
2199 GNUNET_CRYPTO_hash (&node_m, sizeof(node_m), &hc);
2200 memcpy (&hkey,
2201 &hc,
2202 sizeof (hkey));
2203 node = GNUNET_CONTAINER_multishortmap_get (namespace->nodes,
2204 &hkey);
2205 if (NULL != node)
2206 {
2207 LOG (GNUNET_ERROR_TYPE_DEBUG,
2208 "node additional_connects: %u %p\n",
2209 node->additional_connects,
2210 node);
2211 node_connections = node->node_connections_head;
2212 }
2213 *node_ex = node;
2214 *namespace_ex = namespace;
2215 *node_connections_ex = node_connections;
2216 }
2217 }
2218}
2219
2220
2221/**
2222 * Get a node from the topology.
2223 *
2224 * @param num The specific node we want the connections for.
2225 * @param topology The topology we get the connections from.
2226 * @return The connections of the node.
2227 */
2228struct GNUNET_TESTING_NetjailNode *
2229GNUNET_TESTING_get_node (unsigned int num,
2230 struct GNUNET_TESTING_NetjailTopology *topology)
2231{
2232 struct GNUNET_TESTING_NetjailNode *node;
2233 struct GNUNET_TESTING_NetjailNamespace *namespace;
2234 struct GNUNET_TESTING_NodeConnection *node_connections;
2235
2236 get_node_info (num, topology, &node, &namespace, &node_connections);
2237
2238 return node;
2239
2240}
2241
2242
2243/**
2244 * Get the connections to other nodes for a specific node.
2245 *
2246 * @param num The specific node we want the connections for.
2247 * @param topology The topology we get the connections from.
2248 * @return The connections of the node.
2249 */
2250struct GNUNET_TESTING_NodeConnection *
2251GNUNET_TESTING_get_connections (unsigned int num,
2252 const struct
2253 GNUNET_TESTING_NetjailTopology *topology)
2254{
2255 struct GNUNET_TESTING_NetjailNode *node;
2256 struct GNUNET_TESTING_NetjailNamespace *namespace;
2257 struct GNUNET_TESTING_NodeConnection *node_connections;
2258
2259 LOG (GNUNET_ERROR_TYPE_DEBUG,
2260 "get_connections\n");
2261
2262 get_node_info (num, topology, &node, &namespace, &node_connections);
2263
2264 return node_connections;
2265}
2266
2267
2268/**
2269 * Retrieve the peer identity from the test system with the unique node id.
2270 *
2271 * @param num The unique node id.
2272 * @param tl_system The test system.
2273 * @return The peer identity wrapping the public key.
2274 */
2275struct GNUNET_PeerIdentity *
2276GNUNET_TESTING_get_peer (unsigned int num,
2277 const struct GNUNET_TESTING_System *tl_system)
2278{
2279 struct GNUNET_PeerIdentity *peer = GNUNET_new (struct GNUNET_PeerIdentity);
2280 struct GNUNET_CRYPTO_EddsaPrivateKey *priv_key;
2281
2282 priv_key = GNUNET_TESTING_hostkey_get (tl_system,
2283 num,
2284 peer);
2285
2286 GNUNET_CRYPTO_eddsa_key_get_public (priv_key,
2287 &peer->public_key);
2288 GNUNET_free (priv_key);
2289 return peer;
2290}
2291
2292
2293int
2294free_nodes_cb (void *cls,
2295 const struct GNUNET_ShortHashCode *key,
2296 void *value)
2297{
2298 (void) cls;
2299 struct GNUNET_TESTING_NetjailNode *node = value;
2300 struct GNUNET_TESTING_NodeConnection *pos_connection;
2301 struct GNUNET_TESTING_AddressPrefix *pos_prefix;
2302
2303 while (NULL != (pos_connection = node->node_connections_head))
2304 {
2305 while (NULL != (pos_prefix = pos_connection->address_prefixes_head))
2306 {
2307 GNUNET_CONTAINER_DLL_remove (pos_connection->address_prefixes_head,
2308 pos_connection->address_prefixes_tail,
2309 pos_prefix);
2310 GNUNET_free (pos_prefix->address_prefix);
2311 GNUNET_free (pos_prefix);
2312 }
2313 GNUNET_CONTAINER_DLL_remove (node->node_connections_head,
2314 node->node_connections_tail,
2315 pos_connection);
2316 GNUNET_free (pos_connection);
2317 }
2318
2319 GNUNET_free (node->plugin);
2320 GNUNET_free (node);
2321 return GNUNET_OK;
2322}
2323
2324
2325int
2326free_namespaces_cb (void *cls,
2327 const struct GNUNET_ShortHashCode *key,
2328 void *value)
2329{
2330 (void) cls;
2331 struct GNUNET_TESTING_NetjailNamespace *namespace = value;
2332
2333 GNUNET_free (namespace->router);
2334 GNUNET_CONTAINER_multishortmap_iterate (namespace->nodes, free_nodes_cb,
2335 namespace->nodes);
2336 return GNUNET_OK;
2337
2338}
2339
2340
2341/**
2342 * Deallocate memory of the struct GNUNET_TESTING_NetjailTopology.
2343 *
2344 * @param topology The GNUNET_TESTING_NetjailTopology to be deallocated.
2345 */
2346void
2347GNUNET_TESTING_free_topology (struct GNUNET_TESTING_NetjailTopology *topology)
2348{
2349 GNUNET_CONTAINER_multishortmap_iterate (topology->map_namespaces,
2350 free_namespaces_cb, NULL);
2351 GNUNET_CONTAINER_multishortmap_destroy (topology->map_namespaces);
2352 GNUNET_CONTAINER_multishortmap_iterate (topology->map_globals, free_nodes_cb,
2353 NULL);
2354 GNUNET_CONTAINER_multishortmap_destroy (topology->map_globals);
2355 GNUNET_free (topology->plugin);
2356 GNUNET_free (topology);
2357}
2358
2359
2360unsigned int
2361GNUNET_TESTING_calculate_num (
2362 struct GNUNET_TESTING_NodeConnection *node_connection,
2363 struct GNUNET_TESTING_NetjailTopology *topology)
2364{
2365 unsigned int n, m, num;
2366
2367 n = node_connection->namespace_n;
2368 m = node_connection->node_n;
2369
2370 if (0 == n)
2371 num = m;
2372 else
2373 num = (n - 1) * topology->nodes_m + m + topology->nodes_x;
2374
2375 return num;
2376}
2377
2378
2379/**
2380 * Get the address for a specific communicator from a connection.
2381 *
2382 * @param connection The connection we like to have the address from.
2383 * @param prefix The communicator protocol prefix.
2384 * @return The address of the communicator.
2385 */
2386char *
2387GNUNET_TESTING_get_address (struct GNUNET_TESTING_NodeConnection *connection,
2388 const char *prefix)
2389{
2390 struct GNUNET_TESTING_NetjailNode *node;
2391 char *addr;
2392 char *template;
2393 unsigned int node_n;
2394
2395 LOG (GNUNET_ERROR_TYPE_DEBUG,
2396 "get address prefix: %s node_n: %u\n",
2397 prefix,
2398 connection->node_n);
2399
2400 node = connection->node;
2401 if (connection->namespace_n == node->namespace_n)
2402 {
2403 template = CONNECT_ADDRESS_TEMPLATE;
2404 node_n = connection->node_n;
2405 }
2406 else if (0 == connection->namespace_n)
2407 {
2408 template = KNOWN_CONNECT_ADDRESS_TEMPLATE;
2409 node_n = connection->node_n;
2410 }
2411 else if (1 == connection->node_n)
2412 {
2413 template = ROUTER_CONNECT_ADDRESS_TEMPLATE;
2414 node_n = connection->namespace_n;
2415 }
2416 else
2417 {
2418 return NULL;
2419 }
2420
2421 if (0 == strcmp (PREFIX_TCP, prefix) ||
2422 0 == strcmp (PREFIX_UDP, prefix) ||
2423 0 == strcmp (PREFIX_UDP_NATTED, prefix) ||
2424 0 == strcmp (PREFIX_TCP_NATTED, prefix))
2425 {
2426 GNUNET_asprintf (&addr,
2427 template,
2428 prefix,
2429 node_n);
2430 }
2431 else
2432 {
2433 GNUNET_assert (0);
2434 }
2435
2436 return addr;
2437}
2438
2439
2440/**
2441 * Get the number of unintentional additional connections the node waits for.
2442 *
2443 * @param num The specific node we want the additional connects for.
2444 * @return The number of additional connects
2445 */
2446unsigned int
2447GNUNET_TESTING_get_additional_connects (unsigned int num,
2448 struct GNUNET_TESTING_NetjailTopology *
2449 topology)
2450{
2451 struct GNUNET_TESTING_NetjailNode *node;
2452 struct GNUNET_TESTING_NetjailNamespace *namespace;
2453 struct GNUNET_TESTING_NodeConnection *node_connections;
2454
2455 LOG (GNUNET_ERROR_TYPE_DEBUG,
2456 "get_additional_connects\n");
2457
2458 get_node_info (num, topology, &node, &namespace, &node_connections);
2459
2460 if (NULL == node)
2461 {
2462 LOG (GNUNET_ERROR_TYPE_WARNING,
2463 "No info found for node %d\n", num);
2464 return 0;
2465 }
2466 LOG (GNUNET_ERROR_TYPE_DEBUG,
2467 "node additional_connects for node %p\n",
2468 node);
2469 LOG (GNUNET_ERROR_TYPE_DEBUG,
2470 "node additional_connects: %u\n",
2471 node->additional_connects);
2472
2473 return node->additional_connects;
2474}
2475
2476
2477static void
2478parse_ac (struct GNUNET_TESTING_NetjailNode *p_node, const char *token)
2479{
2480 char *ac_value;
2481 int ret;
2482
2483 ac_value = get_value ("AC", token);
2484 if (NULL != ac_value)
2485 {
2486 LOG (GNUNET_ERROR_TYPE_DEBUG,
2487 "ac value: %s\n",
2488 ac_value);
2489 errno = 0;
2490 ret = sscanf (ac_value, "%u", &p_node->additional_connects);
2491 if (errno != 0)
2492 {
2493 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
2494 }
2495 GNUNET_assert (0 < ret);
2496 LOG (GNUNET_ERROR_TYPE_DEBUG,
2497 "AC %u\n",
2498 p_node->additional_connects);
2499 }
2500 else
2501 {
2502 p_node->additional_connects = 0;
2503 }
2504 GNUNET_free (ac_value);
2505}
2506
2507
2508/**
2509 * Parse the topology data.
2510 *
2511 * @param data The topology data.
2512 * @return The GNUNET_TESTING_NetjailTopology
2513 */
2514struct GNUNET_TESTING_NetjailTopology *
2515GNUNET_TESTING_get_topo_from_string (const char *input)
2516{
2517 char *token;
2518 char *key = NULL;
2519 unsigned int out;
2520 char *rest = NULL;
2521 char *value = NULL;
2522 char *value2;
2523 char *data;
2524 int ret;
2525 struct GNUNET_TESTING_NetjailTopology *topo;
2526 struct GNUNET_TESTING_NetjailRouter *router;
2527 struct GNUNET_TESTING_NetjailNamespace *namespace;
2528 struct GNUNET_HashCode hc;
2529
2530 data = GNUNET_strdup (input);
2531 token = strtok_r (data, "\n", &rest);
2532 topo = GNUNET_new (struct GNUNET_TESTING_NetjailTopology);
2533 topo->map_namespaces =
2534 GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
2535 topo->map_globals =
2536 GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
2537
2538 while (NULL != token)
2539 {
2540 if (NULL != key)
2541 GNUNET_free (key);
2542 key = get_key (token);
2543 LOG (GNUNET_ERROR_TYPE_DEBUG,
2544 "In the loop with token: %s beginning with %s\n",
2545 token,
2546 key);
2547 if (0 == strcmp (key, "M"))
2548 {
2549 LOG (GNUNET_ERROR_TYPE_DEBUG,
2550 "Get first Value for M.\n");
2551 out = get_first_value (token);
2552 LOG (GNUNET_ERROR_TYPE_DEBUG,
2553 "M: %u\n",
2554 out);
2555 topo->nodes_m = out;
2556 }
2557 else if (0 == strcmp (key, "N"))
2558 {
2559 LOG (GNUNET_ERROR_TYPE_DEBUG,
2560 "Get first Value for N.\n");
2561 out = get_first_value (token);
2562 LOG (GNUNET_ERROR_TYPE_DEBUG,
2563 "N: %u\n",
2564 out);
2565 topo->namespaces_n = out;
2566 }
2567 else if (0 == strcmp (key, "X"))
2568 {
2569 LOG (GNUNET_ERROR_TYPE_DEBUG,
2570 "Get first Value for X.\n");
2571 out = get_first_value (token);
2572 LOG (GNUNET_ERROR_TYPE_DEBUG,
2573 "X: %u\n",
2574 out);
2575 topo->nodes_x = out;
2576 }
2577 else if (0 == strcmp (key, "AC"))
2578 {
2579 LOG (GNUNET_ERROR_TYPE_DEBUG,
2580 "Get first Value for AC.\n");
2581 out = get_first_value (token);
2582 LOG (GNUNET_ERROR_TYPE_DEBUG,
2583 "AC: %u\n",
2584 out);
2585 topo->additional_connects = out;
2586 }
2587 else if (0 == strcmp (key, "T"))
2588 {
2589 LOG (GNUNET_ERROR_TYPE_DEBUG,
2590 "Get first string value for T.\n");
2591 value = get_first_string_value (token);
2592 LOG (GNUNET_ERROR_TYPE_DEBUG,
2593 "value: %s\n",
2594 value);
2595 topo->plugin = value;
2596 }
2597 else if (0 == strcmp (key, "K"))
2598 {
2599 struct GNUNET_ShortHashCode hkey_k;
2600 struct GNUNET_TESTING_NetjailNode *k_node = GNUNET_new (struct
2601 GNUNET_TESTING_NetjailNode);
2602
2603 LOG (GNUNET_ERROR_TYPE_DEBUG,
2604 "Get first Value for K.\n");
2605 out = get_first_value (token);
2606 LOG (GNUNET_ERROR_TYPE_DEBUG,
2607 "K: %u\n",
2608 out);
2609 k_node->node_n = out;
2610 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2611 memcpy (&hkey_k,
2612 &hc,
2613 sizeof (hkey_k));
2614 k_node->is_global = GNUNET_YES;
2615
2616 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (
2617 topo->map_globals,
2618 &hkey_k))
2619 GNUNET_break (0);
2620 else
2621 GNUNET_CONTAINER_multishortmap_put (topo->map_globals,
2622 &hkey_k,
2623 k_node,
2624 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2625 LOG (GNUNET_ERROR_TYPE_DEBUG,
2626 "Get value for key value on K.\n");
2627 value = get_value ("plugin", token);
2628 LOG (GNUNET_ERROR_TYPE_DEBUG,
2629 "value: %s\n",
2630 value);
2631 k_node->plugin = value;
2632 parse_ac (k_node, token);
2633 node_connections (token, k_node);
2634 GNUNET_free (value);
2635 }
2636 else if (0 == strcmp (key, "R"))
2637 {
2638 struct GNUNET_ShortHashCode hkey_r;
2639 router = GNUNET_new (struct GNUNET_TESTING_NetjailRouter);
2640
2641 LOG (GNUNET_ERROR_TYPE_DEBUG,
2642 "Get first Value for R.\n");
2643 out = get_first_value (token);
2644 LOG (GNUNET_ERROR_TYPE_DEBUG,
2645 "R: %u\n",
2646 out);
2647 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2648 memcpy (&hkey_r,
2649 &hc,
2650 sizeof (hkey_r));
2651 LOG (GNUNET_ERROR_TYPE_DEBUG,
2652 "Get value for key tcp_port on R.\n");
2653 value = get_value ("tcp_port", token);
2654 LOG (GNUNET_ERROR_TYPE_DEBUG,
2655 "tcp_port: %s\n",
2656 value);
2657 ret = sscanf (value, "%u", &(router->tcp_port));
2658 GNUNET_free (value);
2659 GNUNET_break (0 != ret && 1 >= router->tcp_port);
2660
2661 LOG (GNUNET_ERROR_TYPE_DEBUG,
2662 "Get value for key udp_port on R.\n");
2663 value2 = get_value ("udp_port", token);
2664 ret = sscanf (value2, "%u", &(router->udp_port));
2665 GNUNET_free (value2);
2666 GNUNET_break (0 != ret && 1 >= router->udp_port);
2667 LOG (GNUNET_ERROR_TYPE_DEBUG,
2668 "udp_port: %s\n",
2669 value2);
2670 GNUNET_free (value2);
2671 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (
2672 topo->map_namespaces,
2673 &hkey_r))
2674 {
2675 namespace = GNUNET_CONTAINER_multishortmap_get (topo->map_namespaces,
2676 &hkey_r);
2677 }
2678 else
2679 {
2680 namespace = GNUNET_new (struct GNUNET_TESTING_NetjailNamespace);
2681 namespace->namespace_n = out;
2682 namespace->nodes = GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
2683 GNUNET_CONTAINER_multishortmap_put (topo->map_namespaces,
2684 &hkey_r,
2685 namespace,
2686 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2687 }
2688 namespace->router = router;
2689
2690 }
2691 else if (0 == strcmp (key, "P"))
2692 {
2693 struct GNUNET_TESTING_NetjailNode *p_node = GNUNET_new (struct
2694 GNUNET_TESTING_NetjailNode);
2695 struct GNUNET_ShortHashCode hkey_p;
2696
2697 LOG (GNUNET_ERROR_TYPE_DEBUG,
2698 "Get first Value for P.\n");
2699 out = get_first_value (token);
2700 LOG (GNUNET_ERROR_TYPE_DEBUG,
2701 "P: %u\n",
2702 out);
2703 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2704 memcpy (&hkey_p,
2705 &hc,
2706 sizeof (hkey_p));
2707
2708 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (
2709 topo->map_namespaces,
2710 &hkey_p))
2711 {
2712 namespace = GNUNET_CONTAINER_multishortmap_get (topo->map_namespaces,
2713 &hkey_p);
2714 }
2715 else
2716 {
2717 namespace = GNUNET_new (struct GNUNET_TESTING_NetjailNamespace);
2718 namespace->nodes = GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
2719 namespace->namespace_n = out;
2720 GNUNET_CONTAINER_multishortmap_put (topo->map_namespaces,
2721 &hkey_p,
2722 namespace,
2723 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2724 }
2725 LOG (GNUNET_ERROR_TYPE_DEBUG,
2726 "Get second Value for P.\n");
2727 out = get_second_value (token);
2728 LOG (GNUNET_ERROR_TYPE_DEBUG,
2729 "P: %u\n",
2730 out);
2731 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2732 memcpy (&hkey_p,
2733 &hc,
2734 sizeof (hkey_p));
2735 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (
2736 namespace->nodes,
2737 &hkey_p))
2738 {
2739 GNUNET_break (0);
2740 }
2741 else
2742 {
2743
2744 GNUNET_CONTAINER_multishortmap_put (namespace->nodes,
2745 &hkey_p,
2746 p_node,
2747 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2748 LOG (GNUNET_ERROR_TYPE_DEBUG,
2749 "Get value for key plugin on P.\n");
2750 value = get_value ("plugin", token);
2751 if (NULL != value)
2752 {
2753 LOG (GNUNET_ERROR_TYPE_DEBUG,
2754 "plugin: %s\n",
2755 value);
2756 p_node->plugin = value;
2757 }
2758 p_node->node_n = out;
2759 p_node->namespace_n = namespace->namespace_n;
2760 }
2761 LOG (GNUNET_ERROR_TYPE_DEBUG,
2762 "Get AC Value for P.\n");
2763 parse_ac (p_node, token);
2764 node_connections (token, p_node);
2765 }
2766 token = strtok_r (NULL, "\n", &rest);
2767 if (NULL != token)
2768 LOG (GNUNET_ERROR_TYPE_DEBUG,
2769 "Next token %s\n",
2770 token);
2771 }
2772 if (NULL != key)
2773 GNUNET_free (key);
2774 GNUNET_free (data);
2775 return topo;
2776}
2777
2778
2779/**
2780 * Getting the topology from file.
2781 *
2782 * @param filename The name of the topology file.
2783 * @return The GNUNET_TESTING_NetjailTopology
2784 */
2785struct GNUNET_TESTING_NetjailTopology *
2786GNUNET_TESTING_get_topo_from_file (const char *filename)
2787{
2788 uint64_t fs;
2789 char *data;
2790 struct GNUNET_TESTING_NetjailTopology *topo;
2791
2792 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
2793 {
2794 LOG (GNUNET_ERROR_TYPE_ERROR,
2795 _ ("Topology file %s not found\n"),
2796 filename);
2797 return NULL;
2798 }
2799 if (GNUNET_OK !=
2800 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
2801 {
2802 LOG (GNUNET_ERROR_TYPE_ERROR,
2803 _ ("Topology file %s has no data\n"),
2804 filename);
2805 return NULL;
2806 }
2807 data = GNUNET_malloc (fs + 1);
2808 if (fs != GNUNET_DISK_fn_read (filename, data, fs))
2809 {
2810 LOG (GNUNET_ERROR_TYPE_ERROR,
2811 _ ("Topology file %s cannot be read\n"),
2812 filename);
2813 GNUNET_free (data);
2814 return NULL;
2815 }
2816
2817 LOG (GNUNET_ERROR_TYPE_DEBUG,
2818 "file length %" PRIu64 "\n",
2819 fs);
2820 data[fs] = '\0';
2821
2822 topo = GNUNET_TESTING_get_topo_from_string (data);
2823
2824 GNUNET_free (data);
2825
2826 return topo;
2827}
2828
2829
2830/* end of testing.c */