Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2018-2020 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify
6 : it under the terms of the GNU General Public License as
7 : published by the Free Software Foundation; either version 3, or
8 : (at your option) any later version.
9 :
10 : TALER 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
13 : GNU General Public License for more details.
14 :
15 : You should have received a copy of the GNU General Public
16 : License along with TALER; see the file COPYING. If not, see
17 : <http://www.gnu.org/licenses/>
18 : */
19 :
20 : /**
21 : * @file testing/testing_api_helpers_exchange.c
22 : * @brief helper functions
23 : * @author Christian Grothoff
24 : * @author Marcello Stanisci
25 : */
26 : #include "platform.h"
27 : #include "taler_json_lib.h"
28 : #include <gnunet/gnunet_curl_lib.h>
29 : #include "taler_signatures.h"
30 : #include "taler_extensions.h"
31 : #include "taler_testing_lib.h"
32 :
33 : /**
34 : * Run multiple taler-exchange-httpd processes in
35 : * parallel using GNU parallel?
36 : */
37 : #define GNU_PARALLEL 0
38 :
39 :
40 : void
41 18 : TALER_TESTING_cleanup_files (const char *config_name)
42 : {
43 18 : if (GNUNET_OK !=
44 18 : GNUNET_CONFIGURATION_parse_and_run (config_name,
45 : &TALER_TESTING_cleanup_files_cfg,
46 : NULL))
47 0 : exit (77);
48 18 : }
49 :
50 :
51 : /**
52 : * Remove @a option directory from @a section in @a cfg.
53 : *
54 : * @return #GNUNET_OK on success
55 : */
56 : static enum GNUNET_GenericReturnValue
57 36 : remove_dir (const struct GNUNET_CONFIGURATION_Handle *cfg,
58 : const char *section,
59 : const char *option)
60 : {
61 : char *dir;
62 :
63 36 : if (GNUNET_OK !=
64 36 : GNUNET_CONFIGURATION_get_value_filename (cfg,
65 : section,
66 : option,
67 : &dir))
68 : {
69 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
70 : section,
71 : option);
72 0 : return GNUNET_SYSERR;
73 : }
74 36 : if (GNUNET_YES ==
75 36 : GNUNET_DISK_directory_test (dir,
76 : GNUNET_NO))
77 0 : GNUNET_break (GNUNET_OK ==
78 : GNUNET_DISK_directory_remove (dir));
79 36 : GNUNET_free (dir);
80 36 : return GNUNET_OK;
81 : }
82 :
83 :
84 : enum GNUNET_GenericReturnValue
85 18 : TALER_TESTING_cleanup_files_cfg (void *cls,
86 : const struct GNUNET_CONFIGURATION_Handle *cfg)
87 : {
88 : char *dir;
89 :
90 : (void) cls;
91 18 : if (GNUNET_OK !=
92 18 : GNUNET_CONFIGURATION_get_value_filename (cfg,
93 : "exchange-offline",
94 : "SECM_TOFU_FILE",
95 : &dir))
96 : {
97 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
98 : "exchange-offline",
99 : "SECM_TOFU_FILE");
100 0 : return GNUNET_SYSERR;
101 : }
102 18 : if ( (0 != unlink (dir)) &&
103 18 : (ENOENT != errno) )
104 : {
105 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
106 : "unlink",
107 : dir);
108 0 : GNUNET_free (dir);
109 0 : return GNUNET_SYSERR;
110 : }
111 18 : GNUNET_free (dir);
112 18 : if (GNUNET_OK !=
113 18 : remove_dir (cfg,
114 : "taler-exchange-secmod-eddsa",
115 : "KEY_DIR"))
116 0 : return GNUNET_SYSERR;
117 18 : if (GNUNET_OK !=
118 18 : remove_dir (cfg,
119 : "taler-exchange-secmod-rsa",
120 : "KEY_DIR"))
121 0 : return GNUNET_SYSERR;
122 18 : return GNUNET_OK;
123 : }
124 :
125 :
126 : enum GNUNET_GenericReturnValue
127 0 : TALER_TESTING_run_auditor_exchange (const char *config_filename,
128 : const char *exchange_master_pub,
129 : const char *exchange_base_url,
130 : int do_remove)
131 : {
132 : struct GNUNET_OS_Process *proc;
133 : enum GNUNET_OS_ProcessStatusType type;
134 : unsigned long code;
135 :
136 0 : TALER_LOG_DEBUG ("Add exchange (%s,%s) to the auditor\n",
137 : exchange_base_url,
138 : exchange_master_pub);
139 :
140 0 : proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
141 : NULL, NULL, NULL,
142 : "taler-auditor-exchange",
143 : "taler-auditor-exchange",
144 : "-c", config_filename,
145 : "-u", exchange_base_url,
146 : "-m", exchange_master_pub,
147 : (GNUNET_YES == do_remove)
148 : ? "-r"
149 : : NULL,
150 : NULL);
151 0 : if (NULL == proc)
152 : {
153 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
154 : "Failed to run `taler-auditor-exchange`, is your PATH correct?\n");
155 0 : return GNUNET_SYSERR;
156 : }
157 0 : GNUNET_assert (GNUNET_OK ==
158 : GNUNET_OS_process_wait_status (proc,
159 : &type,
160 : &code));
161 0 : GNUNET_OS_process_destroy (proc);
162 0 : if ( (0 != code) ||
163 0 : (GNUNET_OS_PROCESS_EXITED != type) )
164 : {
165 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
166 : "taler-auditor-exchange terminated with error (%d/%d)\n",
167 : (int) type,
168 : (int) code);
169 0 : return GNUNET_SYSERR;
170 : }
171 0 : return GNUNET_OK;
172 : }
173 :
174 :
175 : enum GNUNET_GenericReturnValue
176 18 : TALER_TESTING_exchange_db_reset (const char *config_filename)
177 : {
178 : struct GNUNET_OS_Process *proc;
179 : enum GNUNET_OS_ProcessStatusType type;
180 : unsigned long code;
181 :
182 18 : proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
183 : NULL, NULL, NULL,
184 : "taler-exchange-dbinit",
185 : "taler-exchange-dbinit",
186 : "-c", config_filename,
187 : "-L", "WARNING",
188 : "-r",
189 : NULL);
190 18 : if (NULL == proc)
191 : {
192 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
193 : "Failed to run `taler-exchange-dbinit`, is your PATH correct?\n");
194 0 : return GNUNET_NO;
195 : }
196 18 : if (GNUNET_SYSERR ==
197 18 : GNUNET_OS_process_wait_status (proc,
198 : &type,
199 : &code))
200 : {
201 0 : GNUNET_break (0);
202 0 : GNUNET_OS_process_destroy (proc);
203 0 : return GNUNET_SYSERR;
204 : }
205 18 : GNUNET_OS_process_destroy (proc);
206 18 : if ( (type == GNUNET_OS_PROCESS_EXITED) &&
207 18 : (0 != code) )
208 : {
209 18 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
210 : "Failed to setup (exchange) database, exit code %d\n",
211 : (int) code);
212 18 : return GNUNET_NO;
213 : }
214 0 : if ( (type != GNUNET_OS_PROCESS_EXITED) ||
215 0 : (0 != code) )
216 : {
217 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
218 : "Unexpected error (%d/%d) running `taler-exchange-dbinit'!\n",
219 : (int) type,
220 : (int) code);
221 0 : return GNUNET_SYSERR;
222 : }
223 0 : return GNUNET_OK;
224 : }
225 :
226 :
227 : enum GNUNET_GenericReturnValue
228 0 : TALER_TESTING_auditor_db_reset (const char *config_filename)
229 : {
230 : struct GNUNET_OS_Process *proc;
231 : enum GNUNET_OS_ProcessStatusType type;
232 : unsigned long code;
233 :
234 0 : proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
235 : NULL, NULL, NULL,
236 : "taler-auditor-dbinit",
237 : "taler-auditor-dbinit",
238 : "-c", config_filename,
239 : "-R",
240 : NULL);
241 0 : if (NULL == proc)
242 : {
243 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
244 : "Failed to run `taler-auditor-dbinit`, is your PATH correct?\n");
245 0 : return GNUNET_NO;
246 : }
247 0 : if (GNUNET_SYSERR ==
248 0 : GNUNET_OS_process_wait_status (proc,
249 : &type,
250 : &code))
251 : {
252 0 : GNUNET_break (0);
253 0 : GNUNET_OS_process_destroy (proc);
254 0 : return GNUNET_SYSERR;
255 : }
256 0 : GNUNET_OS_process_destroy (proc);
257 0 : if ( (type == GNUNET_OS_PROCESS_EXITED) &&
258 0 : (0 != code) )
259 : {
260 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
261 : "Failed to setup (auditor) database, exit code %d\n",
262 : (int) code);
263 0 : return GNUNET_NO;
264 : }
265 0 : if ( (type != GNUNET_OS_PROCESS_EXITED) ||
266 0 : (0 != code) )
267 : {
268 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
269 : "Unexpected error (%d/%d) running `taler-auditor-dbinit'!\n",
270 : (int) type,
271 : (int) code);
272 0 : return GNUNET_SYSERR;
273 : }
274 0 : return GNUNET_OK;
275 : }
276 :
277 :
278 : /**
279 : * Type of closure for
280 : * #sign_keys_for_exchange.
281 : */
282 : struct SignInfo
283 : {
284 : /**
285 : * Members will be set to the exchange configuration.
286 : */
287 : struct TALER_TESTING_ExchangeConfiguration *ec;
288 :
289 : /**
290 : * Name of the configuration file to use.
291 : */
292 : const char *config_filename;
293 :
294 : /**
295 : * Did we reset the database?
296 : */
297 : int db_reset;
298 : };
299 :
300 :
301 : /**
302 : * Sign the keys for an exchange given configuration @a cfg.
303 : * The information to be signed must be in a file "auditor.in".
304 : *
305 : * @param[in,out] cls a `struct SignInfo` with further parameters
306 : * @param cfg configuration to use
307 : * @return #GNUNET_OK on success
308 : */
309 : static enum GNUNET_GenericReturnValue
310 0 : sign_keys_for_exchange (void *cls,
311 : const struct GNUNET_CONFIGURATION_Handle *cfg)
312 : {
313 0 : struct SignInfo *si = cls;
314 : char *exchange_master_pub;
315 : int ret;
316 :
317 : /* Load the age restriction mask from the configuration */
318 0 : TALER_extensions_load_taler_config (cfg);
319 :
320 0 : if (GNUNET_OK !=
321 0 : GNUNET_CONFIGURATION_get_value_string (cfg,
322 : "exchange",
323 : "BASE_URL",
324 0 : &si->ec->exchange_url))
325 : {
326 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
327 : "exchange",
328 : "BASE_URL");
329 0 : si->ec->exchange_url = NULL;
330 0 : return GNUNET_NO;
331 : }
332 0 : if (GNUNET_OK !=
333 0 : GNUNET_CONFIGURATION_get_value_string (cfg,
334 : "auditor",
335 : "BASE_URL",
336 0 : &si->ec->auditor_url))
337 : {
338 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
339 : "auditor",
340 : "BASE_URL");
341 0 : GNUNET_free (si->ec->exchange_url);
342 0 : si->ec->exchange_url = NULL;
343 0 : si->ec->auditor_url = NULL;
344 0 : return GNUNET_SYSERR;
345 : }
346 0 : if (GNUNET_OK !=
347 0 : GNUNET_CONFIGURATION_get_value_string (cfg,
348 : "exchange",
349 : "MASTER_PUBLIC_KEY",
350 : &exchange_master_pub))
351 : {
352 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
353 : "exchange",
354 : "MASTER_PUBLIC_KEY");
355 0 : ret = GNUNET_SYSERR;
356 0 : goto fail;
357 : }
358 0 : if ( (GNUNET_OK !=
359 0 : TALER_TESTING_run_auditor_exchange (si->config_filename,
360 : exchange_master_pub,
361 0 : si->ec->exchange_url,
362 0 : GNUNET_NO)) &&
363 0 : (GNUNET_YES == si->db_reset) )
364 : {
365 0 : ret = GNUNET_NO;
366 0 : goto fail;
367 : }
368 0 : GNUNET_free (exchange_master_pub);
369 0 : return GNUNET_OK;
370 0 : fail:
371 0 : GNUNET_free (si->ec->exchange_url);
372 0 : GNUNET_free (si->ec->auditor_url);
373 0 : si->ec->exchange_url = NULL;
374 0 : si->ec->auditor_url = NULL;
375 0 : return ret;
376 : }
377 :
378 :
379 : enum GNUNET_GenericReturnValue
380 18 : TALER_TESTING_prepare_exchange (const char *config_filename,
381 : int reset_db,
382 : struct TALER_TESTING_ExchangeConfiguration *ec)
383 : {
384 18 : struct SignInfo si = {
385 : .config_filename = config_filename,
386 : .ec = ec,
387 : .db_reset = reset_db
388 : };
389 :
390 18 : if (GNUNET_YES == reset_db)
391 : {
392 18 : if (GNUNET_OK !=
393 18 : TALER_TESTING_exchange_db_reset (config_filename))
394 18 : return GNUNET_NO;
395 0 : if (GNUNET_OK !=
396 0 : TALER_TESTING_auditor_db_reset (config_filename))
397 0 : return GNUNET_NO;
398 : }
399 0 : if (GNUNET_OK !=
400 0 : GNUNET_CONFIGURATION_parse_and_run (config_filename,
401 : &sign_keys_for_exchange,
402 : &si))
403 0 : return GNUNET_NO;
404 0 : return GNUNET_OK;
405 : }
406 :
407 :
408 : const struct TALER_EXCHANGE_DenomPublicKey *
409 0 : TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys,
410 : const struct TALER_Amount *amount,
411 : bool age_restricted)
412 : {
413 : struct GNUNET_TIME_Timestamp now;
414 : struct TALER_EXCHANGE_DenomPublicKey *pk;
415 : char *str;
416 :
417 0 : now = GNUNET_TIME_timestamp_get ();
418 0 : for (unsigned int i = 0; i<keys->num_denom_keys; i++)
419 : {
420 0 : pk = &keys->denom_keys[i];
421 0 : if ( (0 == TALER_amount_cmp (amount,
422 0 : &pk->value)) &&
423 0 : (GNUNET_TIME_timestamp_cmp (now,
424 : >=,
425 0 : pk->valid_from)) &&
426 0 : (GNUNET_TIME_timestamp_cmp (now,
427 : <,
428 0 : pk->withdraw_valid_until)) &&
429 0 : (age_restricted == (0 != pk->key.age_mask.bits)) )
430 0 : return pk;
431 : }
432 : /* do 2nd pass to check if expiration times are to blame for
433 : * failure */
434 0 : str = TALER_amount_to_string (amount);
435 0 : for (unsigned int i = 0; i<keys->num_denom_keys; i++)
436 : {
437 0 : pk = &keys->denom_keys[i];
438 0 : if ( (0 == TALER_amount_cmp (amount,
439 0 : &pk->value)) &&
440 0 : (GNUNET_TIME_timestamp_cmp (now,
441 : <,
442 0 : pk->valid_from) ||
443 0 : GNUNET_TIME_timestamp_cmp (now,
444 : >,
445 0 : pk->withdraw_valid_until) ) &&
446 0 : (age_restricted == (0 != pk->key.age_mask.bits)) )
447 : {
448 0 : GNUNET_log
449 : (GNUNET_ERROR_TYPE_WARNING,
450 : "Have denomination key for `%s', but with wrong"
451 : " expiration range %llu vs [%llu,%llu)\n",
452 : str,
453 : (unsigned long long) now.abs_time.abs_value_us,
454 : (unsigned long long) pk->valid_from.abs_time.abs_value_us,
455 : (unsigned long long) pk->withdraw_valid_until.abs_time.abs_value_us);
456 0 : GNUNET_free (str);
457 0 : return NULL;
458 : }
459 : }
460 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
461 : "No denomination key for amount %s found\n",
462 : str);
463 0 : GNUNET_free (str);
464 0 : return NULL;
465 : }
466 :
467 :
468 : int
469 0 : TALER_TESTING_wait_exchange_ready (const char *base_url)
470 : {
471 : char *wget_cmd;
472 : unsigned int iter;
473 :
474 0 : GNUNET_asprintf (&wget_cmd,
475 : "wget -q -t 1 -T 1 %sseed -o /dev/null -O /dev/null",
476 : base_url); // make sure ends with '/'
477 : /* give child time to start and bind against the socket */
478 0 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
479 : "Waiting for `taler-exchange-httpd` service to be ready (check with: %s)\n",
480 : wget_cmd);
481 0 : iter = 0;
482 : do
483 : {
484 0 : if (10 == iter)
485 : {
486 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
487 : "Failed to launch `taler-exchange-httpd` service (or `wget')\n");
488 0 : GNUNET_free (wget_cmd);
489 0 : return 77;
490 : }
491 0 : sleep (1);
492 0 : iter++;
493 : }
494 0 : while (0 != system (wget_cmd));
495 0 : GNUNET_free (wget_cmd);
496 0 : return 0;
497 : }
498 :
499 :
500 : int
501 0 : TALER_TESTING_wait_httpd_ready (const char *base_url)
502 : {
503 : char *wget_cmd;
504 : unsigned int iter;
505 :
506 0 : GNUNET_asprintf (&wget_cmd,
507 : "wget -q -t 1 -T 1 %s -o /dev/null -O /dev/null",
508 : base_url); // make sure ends with '/'
509 : /* give child time to start and bind against the socket */
510 0 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
511 : "Waiting for HTTP service to be ready (check with: %s)\n",
512 : wget_cmd);
513 0 : iter = 0;
514 : do
515 : {
516 0 : if (10 == iter)
517 : {
518 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
519 : "Failed to launch HTTP service (or `wget')\n");
520 0 : GNUNET_free (wget_cmd);
521 0 : return 77;
522 : }
523 0 : sleep (1);
524 0 : iter++;
525 : }
526 0 : while (0 != system (wget_cmd));
527 0 : GNUNET_free (wget_cmd);
528 0 : return 0;
529 : }
530 :
531 :
532 : /**
533 : * Wait for the auditor to have started. Waits for at
534 : * most 10s, after that returns 77 to indicate an error.
535 : *
536 : * @param base_url what URL should we expect the auditor
537 : * to be running at
538 : * @return 0 on success
539 : */
540 : int
541 2 : TALER_TESTING_wait_auditor_ready (const char *base_url)
542 : {
543 : char *wget_cmd;
544 : unsigned int iter;
545 :
546 2 : GNUNET_asprintf (&wget_cmd,
547 : "wget -q -t 1 -T 1 %sversion -o /dev/null -O /dev/null",
548 : base_url); // make sure ends with '/'
549 : /* give child time to start and bind against the socket */
550 2 : fprintf (stderr,
551 : "Waiting for `taler-auditor-httpd' to be ready at %s\n",
552 : base_url);
553 2 : iter = 0;
554 : do
555 : {
556 22 : if (10 == iter)
557 : {
558 2 : fprintf (stderr,
559 : "Failed to launch `taler-auditor-httpd' (or `wget')\n");
560 2 : GNUNET_free (wget_cmd);
561 2 : return 77;
562 : }
563 20 : fprintf (stderr, ".\n");
564 20 : sleep (1);
565 20 : iter++;
566 : }
567 20 : while (0 != system (wget_cmd));
568 0 : GNUNET_free (wget_cmd);
569 0 : return 0;
570 : }
571 :
572 :
573 : enum GNUNET_GenericReturnValue
574 0 : TALER_TESTING_setup_with_exchange (TALER_TESTING_Main main_cb,
575 : void *main_cb_cls,
576 : const char *config_file)
577 : {
578 0 : struct TALER_TESTING_SetupContext setup_ctx = {
579 : .config_filename = config_file,
580 : .main_cb = main_cb,
581 : .main_cb_cls = main_cb_cls
582 : };
583 : enum GNUNET_GenericReturnValue result;
584 :
585 : result =
586 0 : GNUNET_CONFIGURATION_parse_and_run (config_file,
587 : &TALER_TESTING_setup_with_exchange_cfg,
588 : &setup_ctx);
589 0 : if (GNUNET_OK != result)
590 0 : return result;
591 0 : return GNUNET_OK;
592 : }
593 :
594 :
595 : /**
596 : * Stop taler-exchange-crypto helpers.
597 : *
598 : * @param[in] helpers the process handles.
599 : */
600 : static void
601 0 : stop_helpers (struct GNUNET_OS_Process *helpers[3])
602 : {
603 0 : for (unsigned int i = 0; i<3; i++)
604 : {
605 0 : if (NULL == helpers[i])
606 0 : continue;
607 0 : GNUNET_break (0 ==
608 : GNUNET_OS_process_kill (helpers[i],
609 : SIGTERM));
610 0 : GNUNET_break (GNUNET_OK ==
611 : GNUNET_OS_process_wait (helpers[i]));
612 0 : GNUNET_OS_process_destroy (helpers[i]);
613 : }
614 0 : }
615 :
616 :
617 : /**
618 : * Start taler-exchange-crypto helpers.
619 : *
620 : * @param config_filename configuration file to use
621 : * @param[out] helpers where to store the process handles.
622 : */
623 : static enum GNUNET_GenericReturnValue
624 0 : start_helpers (const char *config_filename,
625 : struct GNUNET_OS_Process *helpers[3])
626 : {
627 : char *dir;
628 : const struct GNUNET_OS_ProjectData *pd;
629 :
630 0 : pd = GNUNET_OS_project_data_get ();
631 0 : GNUNET_OS_init (TALER_project_data_default ());
632 0 : dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR);
633 0 : GNUNET_OS_init (pd);
634 0 : if (NULL == dir)
635 : {
636 0 : GNUNET_break (0);
637 0 : return GNUNET_SYSERR;
638 : }
639 : {
640 : char *fn;
641 :
642 0 : GNUNET_asprintf (&fn,
643 : "%s/%s",
644 : dir,
645 : "taler-exchange-secmod-eddsa");
646 0 : helpers[0] = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
647 : NULL, NULL, NULL,
648 : fn,
649 : "taler-exchange-secmod-eddsa",
650 : "-c", config_filename,
651 : "-L", "INFO",
652 : NULL);
653 0 : GNUNET_free (fn);
654 : }
655 : {
656 : char *fn;
657 :
658 0 : GNUNET_asprintf (&fn,
659 : "%s/%s",
660 : dir,
661 : "taler-exchange-secmod-rsa");
662 0 : helpers[1] = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
663 : NULL, NULL, NULL,
664 : fn,
665 : "taler-exchange-secmod-rsa",
666 : "-c", config_filename,
667 : "-L", "INFO",
668 : NULL);
669 0 : GNUNET_free (fn);
670 : }
671 : {
672 : char *fn;
673 :
674 0 : GNUNET_asprintf (&fn,
675 : "%s/%s",
676 : dir,
677 : "taler-exchange-secmod-cs");
678 0 : helpers[2] = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
679 : NULL, NULL, NULL,
680 : fn,
681 : "taler-exchange-secmod-cs",
682 : "-c", config_filename,
683 : "-L", "INFO",
684 : NULL);
685 0 : GNUNET_free (fn);
686 : }
687 0 : GNUNET_free (dir);
688 0 : if ( (NULL == helpers[0]) ||
689 0 : (NULL == helpers[1]) ||
690 0 : (NULL == helpers[2]) )
691 : {
692 0 : stop_helpers (helpers);
693 0 : return GNUNET_SYSERR;
694 : }
695 0 : return GNUNET_OK;
696 : }
697 :
698 :
699 : enum GNUNET_GenericReturnValue
700 0 : TALER_TESTING_setup_with_exchange_cfg (
701 : void *cls,
702 : const struct GNUNET_CONFIGURATION_Handle *cfg)
703 : {
704 0 : const struct TALER_TESTING_SetupContext *setup_ctx = cls;
705 : struct GNUNET_OS_Process *exchanged;
706 : struct GNUNET_OS_Process *helpers[3];
707 : unsigned long long port;
708 : char *serve;
709 : char *base_url;
710 : int result;
711 :
712 0 : if (GNUNET_OK !=
713 0 : GNUNET_CONFIGURATION_get_value_string (cfg,
714 : "exchange",
715 : "SERVE",
716 : &serve))
717 : {
718 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
719 : "exchange",
720 : "SERVE");
721 0 : return GNUNET_NO;
722 : }
723 :
724 0 : if (0 == strcmp ("tcp",
725 : serve))
726 : {
727 0 : if (GNUNET_OK !=
728 0 : GNUNET_CONFIGURATION_get_value_number (cfg,
729 : "exchange",
730 : "PORT",
731 : &port))
732 : {
733 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
734 : "exchange",
735 : "PORT");
736 0 : GNUNET_free (serve);
737 0 : return GNUNET_NO;
738 : }
739 :
740 0 : if (GNUNET_OK !=
741 0 : GNUNET_NETWORK_test_port_free (IPPROTO_TCP,
742 0 : (uint16_t) port))
743 : {
744 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
745 : "Required port %llu not available, skipping.\n",
746 : port);
747 0 : GNUNET_free (serve);
748 0 : return GNUNET_NO;
749 : }
750 : }
751 0 : GNUNET_free (serve);
752 0 : if (GNUNET_OK !=
753 0 : start_helpers (setup_ctx->config_filename,
754 : helpers))
755 : {
756 0 : GNUNET_break (0);
757 0 : return 77;
758 : }
759 0 : exchanged = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
760 : NULL, NULL, NULL,
761 : #if GNU_PARALLEL
762 : "parallel",
763 : #endif
764 : "taler-exchange-httpd",
765 : "taler-exchange-httpd",
766 : "-L", "INFO",
767 : "-a", /* some tests may need timetravel */
768 : "-c", setup_ctx->config_filename,
769 : #if GNU_PARALLEL
770 : "-r",
771 : ":::",
772 : "-",
773 : "-",
774 : "-",
775 : "-",
776 : #endif
777 : NULL);
778 0 : if (NULL == exchanged)
779 : {
780 0 : GNUNET_break (0);
781 0 : stop_helpers (helpers);
782 0 : return 77;
783 : }
784 0 : if (GNUNET_OK !=
785 0 : GNUNET_CONFIGURATION_get_value_string (cfg,
786 : "exchange",
787 : "BASE_URL",
788 : &base_url))
789 : {
790 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
791 : "exchange",
792 : "BASE_URL");
793 0 : stop_helpers (helpers);
794 0 : return GNUNET_NO;
795 : }
796 :
797 0 : if (0 != TALER_TESTING_wait_exchange_ready (base_url))
798 : {
799 0 : GNUNET_free (base_url);
800 0 : stop_helpers (helpers);
801 0 : GNUNET_break (0 ==
802 : GNUNET_OS_process_kill (exchanged,
803 : SIGTERM));
804 : #if GNU_PARALLEL
805 : /* GNU Parallel kills on 2nd SIGTERM, need to give it a
806 : chance to process the 1st signal first... */
807 : sleep (1);
808 : GNUNET_break (0 ==
809 : GNUNET_OS_process_kill (exchanged,
810 : SIGTERM));
811 : #endif
812 0 : GNUNET_break (GNUNET_OK ==
813 : GNUNET_OS_process_wait (exchanged));
814 0 : GNUNET_OS_process_destroy (exchanged);
815 0 : return 77;
816 : }
817 0 : GNUNET_free (base_url);
818 :
819 : /* NOTE: this call blocks. */
820 0 : result = TALER_TESTING_setup (setup_ctx->main_cb,
821 : setup_ctx->main_cb_cls,
822 : cfg,
823 : exchanged,
824 : GNUNET_YES);
825 0 : GNUNET_break (0 ==
826 : GNUNET_OS_process_kill (exchanged,
827 : SIGTERM));
828 : #if GNU_PARALLEL
829 : /* GNU Parallel kills on 2nd SIGTERM, need to give it a
830 : chance to process the 1st signal first... */
831 : sleep (1);
832 : GNUNET_break (0 ==
833 : GNUNET_OS_process_kill (exchanged,
834 : SIGTERM));
835 : #endif
836 0 : GNUNET_break (GNUNET_OK ==
837 : GNUNET_OS_process_wait (exchanged));
838 0 : GNUNET_OS_process_destroy (exchanged);
839 0 : stop_helpers (helpers);
840 0 : return result;
841 : }
842 :
843 :
844 : enum GNUNET_GenericReturnValue
845 0 : TALER_TESTING_setup_with_auditor_and_exchange_cfg (
846 : void *cls,
847 : const struct GNUNET_CONFIGURATION_Handle *cfg)
848 : {
849 0 : const struct TALER_TESTING_SetupContext *setup_ctx = cls;
850 : struct GNUNET_OS_Process *auditord;
851 : unsigned long long port;
852 : char *serve;
853 : char *base_url;
854 : int result;
855 :
856 0 : if (GNUNET_OK !=
857 0 : GNUNET_CONFIGURATION_get_value_string (cfg,
858 : "auditor",
859 : "SERVE",
860 : &serve))
861 : {
862 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
863 : "auditor",
864 : "SERVE");
865 0 : return GNUNET_NO;
866 : }
867 :
868 0 : if (0 == strcmp ("tcp", serve))
869 : {
870 0 : if (GNUNET_OK !=
871 0 : GNUNET_CONFIGURATION_get_value_number (cfg,
872 : "auditor",
873 : "PORT",
874 : &port))
875 : {
876 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
877 : "auditor",
878 : "PORT");
879 0 : GNUNET_free (serve);
880 0 : return GNUNET_NO;
881 : }
882 :
883 0 : if (GNUNET_OK !=
884 0 : GNUNET_NETWORK_test_port_free (IPPROTO_TCP,
885 0 : (uint16_t) port))
886 : {
887 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
888 : "Required port %llu not available, skipping.\n",
889 : port);
890 0 : GNUNET_free (serve);
891 0 : return GNUNET_NO;
892 : }
893 : }
894 0 : GNUNET_free (serve);
895 0 : auditord = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
896 : NULL, NULL, NULL,
897 : "taler-auditor-httpd",
898 : "taler-auditor-httpd",
899 : "-c", setup_ctx->config_filename,
900 : NULL);
901 :
902 0 : if (GNUNET_OK !=
903 0 : GNUNET_CONFIGURATION_get_value_string (cfg,
904 : "auditor",
905 : "BASE_URL",
906 : &base_url))
907 : {
908 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
909 : "auditor",
910 : "BASE_URL");
911 0 : return GNUNET_NO;
912 : }
913 :
914 0 : if (0 != TALER_TESTING_wait_auditor_ready (base_url))
915 : {
916 0 : GNUNET_free (base_url);
917 0 : GNUNET_break (0 ==
918 : GNUNET_OS_process_kill (auditord,
919 : SIGTERM));
920 0 : GNUNET_break (GNUNET_OK ==
921 : GNUNET_OS_process_wait (auditord));
922 0 : GNUNET_OS_process_destroy (auditord);
923 0 : return 77;
924 : }
925 0 : GNUNET_free (base_url);
926 :
927 : /* NOTE: this call blocks. */
928 0 : result = TALER_TESTING_setup_with_exchange_cfg ((void *) setup_ctx,
929 : cfg);
930 0 : GNUNET_break (0 ==
931 : GNUNET_OS_process_kill (auditord,
932 : SIGTERM));
933 0 : GNUNET_break (GNUNET_OK ==
934 : GNUNET_OS_process_wait (auditord));
935 0 : GNUNET_OS_process_destroy (auditord);
936 0 : return result;
937 : }
938 :
939 :
940 : enum GNUNET_GenericReturnValue
941 0 : TALER_TESTING_setup_with_auditor_and_exchange (TALER_TESTING_Main main_cb,
942 : void *main_cb_cls,
943 : const char *config_file)
944 : {
945 0 : struct TALER_TESTING_SetupContext setup_ctx = {
946 : .config_filename = config_file,
947 : .main_cb = main_cb,
948 : .main_cb_cls = main_cb_cls
949 : };
950 :
951 0 : return GNUNET_CONFIGURATION_parse_and_run (
952 : config_file,
953 : &TALER_TESTING_setup_with_auditor_and_exchange_cfg,
954 : &setup_ctx);
955 : }
956 :
957 :
958 : enum GNUNET_GenericReturnValue
959 15 : TALER_TESTING_url_port_free (const char *url)
960 : {
961 : const char *port;
962 : long pnum;
963 :
964 15 : port = strrchr (url,
965 : (unsigned char) ':');
966 15 : if (NULL == port)
967 0 : pnum = 80;
968 : else
969 15 : pnum = strtol (port + 1, NULL, 10);
970 15 : if (GNUNET_OK !=
971 15 : GNUNET_NETWORK_test_port_free (IPPROTO_TCP,
972 : pnum))
973 : {
974 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
975 : "Port %u not available.\n",
976 : (unsigned int) pnum);
977 0 : return GNUNET_SYSERR;
978 : }
979 15 : return GNUNET_OK;
980 : }
981 :
982 :
983 : /* end of testing_api_helpers_exchange.c */
|