GNUnet  0.10.x
gnunet-testing.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 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 
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_testing_lib.h"
29 
30 
31 #define LOG(kind,...) \
32  GNUNET_log_from (kind, "gnunet-testing", __VA_ARGS__)
33 
34 
38 static int ret;
39 
44 static char *create_hostkey;
45 
49 static int create_cfg;
50 
54 static unsigned int create_no;
55 
59 static char *create_cfg_template;
60 
64 static char *run_service_name;
65 
69 static struct GNUNET_DISK_FileHandle *fh;
70 
74 static char *tmpfilename;
75 
79 static struct GNUNET_SCHEDULER_Task *tid;
80 
85 
86 
87 
88 static int
89 create_unique_cfgs (const char * template, const unsigned int no)
90 {
91  struct GNUNET_TESTING_System *system;
92  int fail;
93  unsigned int cur;
94  char *cur_file;
95  struct GNUNET_CONFIGURATION_Handle *cfg_new;
96  struct GNUNET_CONFIGURATION_Handle *cfg_tmpl;
97 
98  if (GNUNET_NO == GNUNET_DISK_file_test(template))
99  {
100  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Configuration template `%s': file not found\n", create_cfg_template);
101  return 1;
102  }
103  cfg_tmpl = GNUNET_CONFIGURATION_create();
104 
105  /* load template */
107  {
108  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load template `%s'\n", create_cfg_template);
109  GNUNET_CONFIGURATION_destroy (cfg_tmpl);
110 
111  return 1;
112  }
113  /* load defaults */
114  if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg_tmpl, NULL))
115  {
116  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load template `%s'\n", create_cfg_template);
117  GNUNET_CONFIGURATION_destroy (cfg_tmpl);
118  return 1;
119  }
120 
121  fail = GNUNET_NO;
122  system = GNUNET_TESTING_system_create ("testing", NULL /* controller */,
123  NULL, NULL);
124  for (cur = 0; cur < no; cur++)
125  {
126  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating configuration no. %u \n", cur);
127  if (create_cfg_template != NULL)
128  GNUNET_asprintf (&cur_file,"%04u-%s",cur, create_cfg_template);
129  else
130  GNUNET_asprintf (&cur_file,"%04u%s",cur, ".conf");
131 
132  cfg_new = GNUNET_CONFIGURATION_dup (cfg_tmpl);
133  if (GNUNET_OK !=
134  GNUNET_TESTING_configuration_create (system, cfg_new))
135  {
136  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not create another configuration\n");
138  fail = GNUNET_YES;
139  break;
140  }
142  "Writing configuration no. %u to file `%s' \n", cur, cur_file);
143  if (GNUNET_OK != GNUNET_CONFIGURATION_write(cfg_new, cur_file))
144  {
145  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write configuration no. %u \n", cur);
146  fail = GNUNET_YES;
147  }
149  GNUNET_free (cur_file);
150  if (GNUNET_YES == fail)
151  break;
152  }
155  if (GNUNET_YES == fail)
156  return 1;
157  return 0;
158 }
159 
160 
161 static int
162 create_hostkeys (const unsigned int no)
163 {
164  struct GNUNET_TESTING_System *system;
165  struct GNUNET_PeerIdentity id;
166  struct GNUNET_DISK_FileHandle *fd;
168 
169  system = GNUNET_TESTING_system_create ("testing", NULL, NULL, NULL);
170  pk = GNUNET_TESTING_hostkey_get (system, create_no, &id);
171  if (NULL == pk)
172  {
173  fprintf (stderr, _("Could not extract hostkey %u (offset too large?)\n"), create_no);
175  return 1;
176  }
183  GNUNET_assert (fd != NULL);
184  ret = GNUNET_DISK_file_write (fd, pk,
185  sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
187  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
188  "Wrote hostkey to file: `%s'\n", create_hostkey);
189  GNUNET_free (pk);
191  return 0;
192 }
193 
194 
201 static void
202 cleanup (void *cls)
203 {
204  if (NULL != tmpfilename)
205  {
206  if (0 != UNLINK (tmpfilename))
208  }
209  if (NULL != tid)
210  {
212  tid = NULL;
213  }
214  if (NULL != fh)
215  {
217  fh = NULL;
218  }
219 }
220 
221 
227 static void
228 stdin_cb (void *cls)
229 {
230  int c;
231 
232  tid = NULL;
233  c = getchar ();
234  switch (c)
235  {
236  case EOF:
237  case 'q':
239  return;
240  case 'r':
241  if (GNUNET_OK != GNUNET_TESTING_peer_stop (my_peer))
242  LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to stop the peer\n");
243  if (GNUNET_OK != GNUNET_TESTING_peer_start (my_peer))
244  LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to start the peer\n");
245  printf ("restarted\n");
246  fflush (stdout);
247  break;
248  case '\n':
249  case '\r':
250  /* ignore whitespace */
251  break;
252  default:
253  fprintf (stderr, _("Unknown command, use 'q' to quit or 'r' to restart peer\n"));
254  break;
255  }
257  fh,
258  &stdin_cb, NULL);
259 }
260 
261 
270 static void
271 testing_main (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
272  struct GNUNET_TESTING_Peer *peer)
273 {
274  my_peer = peer;
275  if (NULL == (tmpfilename = GNUNET_DISK_mktemp ("gnunet-testing")))
276  {
277  GNUNET_break (0);
279  return;
280  }
281  if (GNUNET_SYSERR ==
283  tmpfilename))
284  {
285  GNUNET_break (0);
286  return;
287  }
288  printf("ok\n%s\n", tmpfilename);
289  fflush(stdout);
293  fh,
294  &stdin_cb, NULL);
295 }
296 
297 
298 
307 static void
308 run_no_scheduler (void *cls, char *const *args, const char *cfgfile,
309  const struct GNUNET_CONFIGURATION_Handle *cfg)
310 {
311  if (NULL != run_service_name)
312  {
313  ret = GNUNET_TESTING_service_run ("gnunet_service_test", run_service_name,
314  cfgfile, &testing_main, NULL);
315  return;
316  }
317 
318  if (GNUNET_YES == create_cfg)
319  {
320  if (create_no > 0)
321  {
323  "Creating %u configuration files based on template `%s'\n", create_no, create_cfg_template);
325  }
326  else
327  {
328  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing arguments! \n");
329  ret = 1;
330  }
331  }
332  if (NULL != create_hostkey)
333  {
334  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Extracting hostkey %u\n", create_no);
336  }
338 }
339 
340 
348 int
349 main (int argc, char *const *argv)
350 {
351  struct GNUNET_GETOPT_CommandLineOption options[] = {
353  "cfg",
354  gettext_noop ("create unique configuration files"),
355  &create_cfg),
357  "key",
358  "FILENAME",
359  gettext_noop ("extract hostkey file from pre-computed hostkey list"),
360  &create_hostkey),
361 
363  "number",
364  "NUMBER",
365  gettext_noop ("number of unique configuration files to create, or number of the hostkey to extract"),
366  &create_no),
367 
368 
370  "template",
371  "FILENAME",
372  gettext_noop ("configuration template"),
374 
376  "run",
377  "SERVICE",
378  gettext_noop ("run the given service, wait on stdin for 'r' (restart) or 'q' (quit)"),
381  };
382  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
383  return 2;
384 
385  /* Run without scheduler, because we may want to call
386  * GNUNET_TESTING_service_run, which starts the scheduler on its own.
387  * Furthermore, the other functionality currently does not require the scheduler, too,
388  * but beware when extending gnunet-testing. */
389  ret = (GNUNET_OK ==
390  GNUNET_PROGRAM_run2 (argc, argv, "gnunet-testing",
391  gettext_noop ("Command line tool to access the testing library"), options, &run_no_scheduler,
392  NULL, GNUNET_YES)) ? ret : 1;
393  GNUNET_free ((void*) argv);
394  return ret;
395 }
396 
397 /* end of gnunet-testing.c */
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:669
int main(int argc, char *const *argv)
The main function.
Create file if it doesn&#39;t exist.
static struct GNUNET_CRYPTO_EddsaPrivateKey * pk
Private key of this peer.
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1817
int GNUNET_CONFIGURATION_write(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Write configuration file.
static void stdin_cb(void *cls)
Called whenever we can read stdin non-blocking.
int GNUNET_PROGRAM_run2(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls, int run_without_scheduler)
Run a standard GNUnet command startup sequence (initialize loggers and configuration, parse options).
Definition: program.c:141
static void testing_main(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer)
Main function called by the testing library.
int GNUNET_TESTING_peer_start(struct GNUNET_TESTING_Peer *peer)
Start the peer.
Definition: testing.c:1315
Handle for a GNUnet peer controlled by testing.
Definition: testing.c:175
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1293
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1521
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_TESTING_hostkey_get(const struct GNUNET_TESTING_System *system, uint32_t key_number, struct GNUNET_PeerIdentity *id)
Testing includes a number of pre-created hostkeys for faster peer startup.
Definition: testing.c:704
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:833
#define GNUNET_NO
Definition: gnunet_common.h:81
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1643
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
Definition of a command line option.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(void)
Create a new configuration object.
static char * create_hostkey
Filename of the hostkey file we should write, null if we should not write a hostkey file...
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:524
int GNUNET_TESTING_peer_stop(struct GNUNET_TESTING_Peer *peer)
Stop the peer.
Definition: testing.c:1418
int GNUNET_TESTING_configuration_create(struct GNUNET_TESTING_System *system, struct GNUNET_CONFIGURATION_Handle *cfg)
Create a new configuration using the given configuration as a template; ports and paths will be modif...
Definition: testing.c:1113
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_string(char shortName, const char *name, const char *argumentHelp, const char *description, char **str)
Allow user to specify a string.
int GNUNET_CONFIGURATION_load(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Load configuration.
#define UNLINK(f)
Definition: plibc.h:666
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
char * GNUNET_DISK_mktemp(const char *t)
Create an (empty) temporary file on disk.
Definition: disk.c:593
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:1049
int GNUNET_TESTING_service_run(const char *testdir, const char *service_name, const char *cfgfilename, GNUNET_TESTING_TestMain tm, void *tm_cls)
Start a single service (no ARM, except of course if the given service name is &#39;arm&#39;) and run a test u...
Definition: testing.c:1626
static struct GNUNET_SCHEDULER_Task * tid
Task identifier of the task that waits for stdin.
static char * create_cfg_template
Filename of the config template to be written.
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define LOG(kind,...)
static unsigned int create_no
Number of config files to create.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
struct GNUNET_TESTING_System * GNUNET_TESTING_system_create(const char *testdir, const char *trusted_ip, const char *hostname, const struct GNUNET_TESTING_SharedService *shared_services)
Create a system handle.
Definition: testing.c:449
void GNUNET_TESTING_system_destroy(struct GNUNET_TESTING_System *system, int remove_paths)
Free system resources.
Definition: testing.c:527
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static char * run_service_name
Service we are supposed to run.
static void run_no_scheduler(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
Main function that will be running without scheduler.
Handle for a system on which GNUnet peers are executed; a system is used for reserving unique paths a...
Definition: testing.c:102
static struct GNUNET_TESTING_Peer * my_peer
Peer started for &#39;-r&#39;.
static int create_unique_cfgs(const char *template, const unsigned int no)
static int create_hostkeys(const unsigned int no)
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_dup(const struct GNUNET_CONFIGURATION_Handle *cfg)
Duplicate an existing configuration object.
Private ECC key encoded for transmission.
The identity of the host (wraps the signing key of the peer).
configuration data
Definition: configuration.c:85
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_flag(char shortName, const char *name, const char *description, int *val)
Allow user to specify a flag (which internally means setting an integer to 1/GNUNET_YES/GNUNET_OK.
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
Open the file for both reading and writing.
static int ret
Final status code.
static char * tmpfilename
Temporary filename, used with &#39;-r&#39; to write the configuration to.
#define GNUNET_YES
Definition: gnunet_common.h:80
int fd
File handle on other OSes.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_native(FILE *fd)
Get a handle from a native FD.
Definition: disk.c:1970
static void cleanup(void *cls)
Cleanup called by signal handlers and when stdin is closed.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_uint(char shortName, const char *name, const char *argumentHelp, const char *description, unsigned int *val)
Allow user to specify an unsigned int.
#define GNUNET_log_from(kind, comp,...)
static int create_cfg
Non-zero if we should create config files.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1673
Handle used to access files (and pipes).
#define GNUNET_free(ptr)
Wrapper around free.
#define gettext_noop(String)
Definition: gettext.h:69
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
static struct GNUNET_DISK_FileHandle * fh
File handle to STDIN, for reading restart/quit commands.