GNUnet  0.19.3
transport-testing-main2.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2016 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  */
25 #include "platform.h"
26 #include "transport-testing2.h"
27 
28 
33 {
38 
43 
48 
53 
58 
63 };
64 
65 
71 static void
72 do_shutdown (void *cls)
73 {
76 
78  "Testcase shutting down\n");
79  if (NULL != ccc->shutdown_task)
81  if (NULL != ccc->timeout_task)
82  {
84  ccc->timeout_task = NULL;
85  }
86  if (NULL != ccc->connect_task)
87  {
89  ccc->connect_task = NULL;
90  }
91  while (NULL != (crl = ccc->crl_head))
92  {
94  ccc->crl_tail,
95  crl);
97  GNUNET_free (crl);
98  }
99  for (unsigned int i = 0; i < ccc->num_peers; i++)
100  {
101  if (NULL != ccc->p[i])
102  {
104  ccc->p[i] = NULL;
105  }
106  }
107 }
108 
109 
115 static void
116 do_timeout (void *cls)
117 {
119 
120  ccc->timeout_task = NULL;
122  "Testcase timed out\n");
123  ccc->global_ret = GNUNET_SYSERR;
125 }
126 
127 
134 {
139 
143  unsigned int off;
144 };
145 
146 
150 struct ConnectPairInfo
151 {
155  const struct GNUNET_PeerIdentity *sender;
156 
161 };
162 
163 
170 static void
171 connect_cb (void *cls)
172 {
175 
177  ccc->crl_tail,
178  crl);
179  {
180  char *p1_c = GNUNET_strdup (GNUNET_i2s (&crl->p1->id));
181 
183  "Peers connected: %u (%s) <-> %u (%s)\n",
184  crl->p1->no,
185  p1_c,
186  crl->p2->no,
187  GNUNET_i2s (&crl->p2->id));
188  GNUNET_free (p1_c);
189  GNUNET_free (crl);
190  }
191  if (NULL == ccc->crl_head)
192  {
194  "All connections UP, launching custom test logic.\n");
197  }
198 }
199 
200 
211  *ccc,
212  const struct GNUNET_PeerIdentity *peer)
213 {
214  for (unsigned int i = 0; i < ccc->num_peers; i++)
215  if ((NULL != ccc->p[i]) &&
216  (0 == memcmp (peer,
217  &ccc->p[i]->id,
218  sizeof(*peer))))
219  return ccc->p[i];
220  return NULL;
221 }
222 
223 
232 static void *
233 my_nc (void *cls,
234  const struct GNUNET_PeerIdentity *peer,
235  struct GNUNET_MQ_Handle *mq)
236 {
239  struct ConnectPairInfo *cpi;
240 
241  if (NULL != ccc->nc)
242  ccc->nc (ccc->cls,
243  ccc->p[ipi->off],
244  peer);
245  cpi = GNUNET_new (struct ConnectPairInfo);
246  cpi->ipi = ipi;
247  cpi->sender = peer; /* valid until disconnect */
248  return cpi;
249 }
250 
251 
259 static void
260 my_nd (void *cls,
261  const struct GNUNET_PeerIdentity *peer,
262  void *custom_cls)
263 {
266  struct ConnectPairInfo *cpi = custom_cls;
267 
268  if (NULL != ccc->nd)
269  ccc->nd (ccc->cls,
270  ccc->p[ipi->off],
271  peer);
272  GNUNET_free (cpi);
273 }
274 
275 
283 static int
284 check_test (void *cls,
285  const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
286 {
287  return GNUNET_OK;
288 }
289 
290 
297 static void
298 handle_test (void *cls,
299  const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
300 {
301  struct ConnectPairInfo *cpi = cls;
304 
305  if (NULL != ccc->rec)
306  ccc->rec (ccc->cls,
307  ccc->p[ipi->off],
308  cpi->sender,
309  message);
310 }
311 
312 
320 static int
322  const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
323 {
324  return GNUNET_OK;
325 }
326 
327 
334 static void
336  const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
337 {
338  struct ConnectPairInfo *cpi = cls;
341 
342  if (NULL != ccc->rec)
343  ccc->rec (ccc->cls,
344  ccc->p[ipi->off],
345  cpi->sender,
346  message);
347 }
348 
349 
355 static void
357 {
359 
360  ccc->connect_task = NULL;
361  for (unsigned int i = 0; i < ccc->num_peers; i++)
362  for (unsigned int j = (ccc->bi_directional ? 0 : i + 1); j < ccc->num_peers;
363  j++)
364  {
366 
367  if (i == j)
368  continue;
371  ccc->crl_tail,
372  crl);
373  crl->ccc = ccc;
374  crl->p1 = ccc->p[i];
375  crl->p2 = ccc->p[j];
376  {
377  char *sender_c = GNUNET_strdup (GNUNET_i2s (&ccc->p[0]->id));
378 
380  "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n",
381  ccc->p[0]->no,
382  sender_c,
383  ccc->p[1]->no,
384  GNUNET_i2s (&ccc->p[1]->id));
385  GNUNET_free (sender_c);
386  }
388  ccc->p[j],
389  &connect_cb,
390  crl);
391  }
392 }
393 
394 
402 static void
403 start_cb (void *cls)
404 {
407  struct GNUNET_TRANSPORT_TESTING_PeerContext *p = ccc->p[ipi->off];
408 
409  ccc->started++;
411  "Peer %u (`%s') started\n",
412  p->no,
413  GNUNET_i2s (&p->id));
414  if (ccc->started != ccc->num_peers)
415  return;
416  if (NULL != ccc->pre_connect_task)
417  {
418  /* Run the custom per-connect job, then give it a second to
419  go into effect before we continue connecting peers. */
422  &do_connect,
423  ccc);
424  }
425  else
426  {
427  do_connect (ccc);
428  }
429 }
430 
431 
442 static void
443 connect_check_run (void *cls,
444  char *const *args,
445  const char *cfgfile,
446  const struct GNUNET_CONFIGURATION_Handle *cfg)
447 {
449  int ok;
450 
451  ccc->cfg = cfg;
453  &do_timeout,
454  ccc);
456  ccc);
457  ok = GNUNET_OK;
458  for (unsigned int i = 0; i < ccc->num_peers; i++)
459  {
461  GNUNET_MQ_hd_var_size (test,
464  NULL),
465  GNUNET_MQ_hd_var_size (test2,
468  NULL),
470  };
471  ccc->p[i] = GNUNET_TRANSPORT_TESTING_start_peer (ccc->tth,
472  ccc->cfg_files[i],
473  i + 1,
474  handlers,
475  &my_nc,
476  &my_nd,
477  &ccc->ip[i],
478  &start_cb,
479  &ccc->ip[i]);
480  if (NULL == ccc->p[i])
481  ok = GNUNET_SYSERR;
482  }
483  if (GNUNET_OK != ok)
484  {
486  "Fail! Could not start peers!\n");
488  }
489 }
490 
491 
507 int
510  tth_,
511  const char *test_plugin_,
512  const char *test_name_,
513  unsigned int num_peers,
514  char *cfg_files[])
515 {
516  static struct GNUNET_GETOPT_CommandLineOption options[] = {
518  };
522  char *argv[] = {
523  (char *) test_name_,
524  "-c",
525  (char *) ccc->config_file,
526  NULL
527  };
528 
530  ccc->cfg_files = cfg_files;
531  ccc->test_plugin = test_plugin_;
532  ccc->test_name = test_name_;
533  ccc->tth = tth_;
535  ccc->p = p;
536  ccc->ip = ip;
537  for (unsigned int i = 0; i < num_peers; i++)
538  {
539  ip[i].off = i;
540  ip[i].ccc = ccc;
541  }
542  if (GNUNET_OK !=
543  GNUNET_PROGRAM_run ((sizeof(argv) / sizeof(char *)) - 1,
544  argv,
545  test_name_,
546  "nohelp",
547  options,
549  ccc))
550  return GNUNET_SYSERR;
551  return ccc->global_ret;
552 }
553 
554 
565 int
567  const char *filename,
568  unsigned int num_peers,
570  void *check_cls)
571 {
573  char *test_name;
574  char *test_source;
575  char *test_plugin;
576  char *cfg_names[num_peers];
577  int ret;
578 
579  ret = GNUNET_OK;
580  test_name = GNUNET_TRANSPORT_TESTING_get_test_name (argv0);
581  GNUNET_log_setup (test_name,
582  "WARNING",
583  NULL);
586  test_source);
587  for (unsigned int i = 0; i < num_peers; i++)
588  cfg_names[i] = GNUNET_TRANSPORT_TESTING_get_config_name (argv0,
589  i + 1);
591  if (NULL == tth)
592  {
593  ret = GNUNET_SYSERR;
594  }
595  else
596  {
597  ret = check (check_cls,
598  tth,
599  test_plugin,
600  test_name,
601  num_peers,
602  cfg_names);
604  }
605  for (unsigned int i = 0; i < num_peers; i++)
606  GNUNET_free (cfg_names[i]);
607  GNUNET_free (test_source);
608  GNUNET_free (test_plugin);
609  GNUNET_free (test_name);
610  return ret;
611 }
612 
613 
614 /* end of transport-testing-main.c */
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_CADET_MessageHandler handlers[]
Handlers, for diverse services.
static unsigned int num_peers
static char * filename
static int ok
Return value from 'main' (0 == success)
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_log(kind,...)
void * cls
Closure for mv and cb.
@ GNUNET_OK
@ GNUNET_SYSERR
int GNUNET_log_setup(const char *comp, const char *loglevel, const char *logfile)
Setup logging.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition: program.c:400
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:562
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1299
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,...
Definition: scheduler.c:1334
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1272
#define GNUNET_TIME_UNIT_SECONDS
One second.
Information tracked per connected peer.
const struct GNUNET_PeerIdentity * sender
Peer this is about.
struct GNUNET_TRANSPORT_TESTING_InternalPeerContext * ipi
Information about the receiving peer.
Definition of a command line option.
Handle to a message queue.
Definition: mq.c:87
Message handler for a specific message type.
The identity of the host (wraps the signing key of the peer).
Closure that must be passed to GNUNET_TRANSPORT_TESTING_connect_check.
struct GNUNET_SCHEDULER_Task * timeout_task
Task run on timeout.
const char * test_plugin
Name of the plugin.
GNUNET_TRANSPORT_TESTING_NotifyConnect nc
Notify connect argument to give for peers we start.
struct GNUNET_TRANSPORT_TESTING_Handle * tth
Main testing handle.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration object for the testcase.
unsigned int num_peers
Number of peers involved in the test.
int global_ret
Result from the main function, set to GNUNET_OK on success.
struct GNUNET_TRANSPORT_TESTING_ConnectRequestList * crl_tail
DLL of active connect requests.
const char * test_name
Name of the testcase.
GNUNET_SCHEDULER_TaskCallback shutdown_task
Custom task to run on shutdown.
GNUNET_TRANSPORT_TESTING_ReceiveCallback rec
Receiver argument to give for peers we start.
GNUNET_SCHEDULER_TaskCallback connect_continuation
How should we continue after the connect?
GNUNET_TRANSPORT_TESTING_NotifyDisconnect nd
Notify disconnect argument to give for peers we start.
GNUNET_SCHEDULER_TaskCallback pre_connect_task
Custom task to run after peers were started but before we try to connect them.
struct GNUNET_TRANSPORT_TESTING_ConnectRequestList * crl_head
DLL of active connect requests.
void * connect_continuation_cls
Closure for connect_continuation.
void * cls
Closure for rec, nc and nd.
struct GNUNET_SCHEDULER_Task * connect_task
Task run to connect peers.
void * pre_connect_task_cls
Closure for shutdown_task.
int bi_directional
Should we try to create connections in both directions?
unsigned int started
Number of peers that have been started.
const char * config_file
Which configuration file should we pass to the GNUNET_PROGRAM_run() of the testcase?
char ** cfg_files
Configuration files we have, array with num_peers entries.
struct GNUNET_TRANSPORT_TESTING_PeerContext ** p
Array with num_peers entries.
struct GNUNET_TIME_Relative timeout
When should the testcase time out?
void * shutdown_task_cls
Closure for shutdown_task.
struct GNUNET_TRANSPORT_TESTING_InternalPeerContext * ip
Array with num_peers entries.
struct GNUNET_TRANSPORT_TESTING_ConnectRequestList * next
Stored in a DLL.
struct GNUNET_TRANSPORT_TESTING_PeerContext * p1
Peer being connected.
struct GNUNET_TRANSPORT_TESTING_PeerContext * p2
Peer being connected.
struct GNUNET_TRANSPORT_TESTING_ConnectRequestList * prev
Stored in a DLL.
struct GNUNET_TRANSPORT_TESTING_ConnectRequest * cr
Connect request this is about.
struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext * ccc
Overall context we are in.
Handle for a request to connect two peers.
unsigned int off
Offset of the peer this is about.
struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext * ccc
Overall context of the callback.
unsigned int no
An unique number to identify the peer.
struct GNUNET_PeerIdentity id
Peer identity.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
char * GNUNET_TRANSPORT_TESTING_get_test_plugin_name(const char *file, const char *test)
Extracts the plugin anme from an absolute file name and the test name.
char * GNUNET_TRANSPORT_TESTING_get_test_source_name(const char *file)
Extracts the filename from an absolute file name and removes the extension.
char * GNUNET_TRANSPORT_TESTING_get_test_name(const char *file)
Extracts the test filename from an absolute file name and removes the extension.
char * GNUNET_TRANSPORT_TESTING_get_config_name(const char *file, int count)
This function takes the filename (e.g.
static void connect_check_run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
Function run from GNUNET_TRANSPORT_TESTING_connect_check once the scheduler is up.
static int check_test2(void *cls, const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
Wrapper around receiving data.
static void * my_nc(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MQ_Handle *mq)
Wrapper around peers connecting.
static void connect_cb(void *cls)
Function called when we connected two peers.
static void start_cb(void *cls)
Function called once we have successfully launched a peer.
static void do_timeout(void *cls)
Testcase hit timeout, shut it down with error.
static void do_connect(void *cls)
Connect the peers as a clique.
static void do_shutdown(void *cls)
Shutdown function for the test.
int GNUNET_TRANSPORT_TESTING_connect_check(void *cls, struct GNUNET_TRANSPORT_TESTING_Handle *tth_, const char *test_plugin_, const char *test_name_, unsigned int num_peers, char *cfg_files[])
Common implementation of the GNUNET_TRANSPORT_TESTING_CheckCallback.
static int check_test(void *cls, const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
Wrapper around receiving data.
static void my_nd(void *cls, const struct GNUNET_PeerIdentity *peer, void *custom_cls)
Wrapper around peers disconnecting.
static void handle_test(void *cls, const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
Wrapper around receiving data.
struct GNUNET_TRANSPORT_TESTING_PeerContext * GNUNET_TRANSPORT_TESTING_find_peer(struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc, const struct GNUNET_PeerIdentity *peer)
Find peer by peer ID.
int GNUNET_TRANSPORT_TESTING_main_(const char *argv0, const char *filename, unsigned int num_peers, GNUNET_TRANSPORT_TESTING_CheckCallback check, void *check_cls)
Setup testcase.
static void handle_test2(void *cls, const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
Wrapper around receiving data.
void GNUNET_TRANSPORT_TESTING_stop_peer(struct GNUNET_TRANSPORT_TESTING_PeerContext *p)
Shutdown the given peer.
struct GNUNET_TRANSPORT_TESTING_PeerContext * GNUNET_TRANSPORT_TESTING_start_peer(struct GNUNET_TRANSPORT_TESTING_Handle *tth, const char *cfgname, int peer_id, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_TRANSPORT_NotifyConnect nc, GNUNET_TRANSPORT_NotifyDisconnect nd, void *cb_cls, GNUNET_SCHEDULER_TaskCallback start_cb, void *start_cb_cls)
Start a peer with the given configuration.
struct GNUNET_TRANSPORT_TESTING_ConnectRequest * GNUNET_TRANSPORT_TESTING_connect_peers(struct GNUNET_TRANSPORT_TESTING_PeerContext *p1, struct GNUNET_TRANSPORT_TESTING_PeerContext *p2, GNUNET_SCHEDULER_TaskCallback cb, void *cls)
Initiate a connection from p1 to p2 by offering p1 p2's HELLO message.
void GNUNET_TRANSPORT_TESTING_done(struct GNUNET_TRANSPORT_TESTING_Handle *tth)
Clean up the transport testing.
struct GNUNET_TRANSPORT_TESTING_Handle * GNUNET_TRANSPORT_TESTING_init()
Initialize the transport testing.
void GNUNET_TRANSPORT_TESTING_connect_peers_cancel(struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc)
Cancel the request to connect two peers Tou MUST cancel the request if you stop the peers before the ...
int(* GNUNET_TRANSPORT_TESTING_CheckCallback)(void *cls, struct GNUNET_TRANSPORT_TESTING_Handle *tth_, const char *test_plugin_, const char *test_name_, unsigned int num_peers, char *cfg_files[])
Main function of a testcase.
#define GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE
Message type used by GNUNET_TRANSPORT_TESTING_simple_send().
#define GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE2
Alternative message type for tests.