- WiP
[oweals/gnunet.git] / src / regex / test_regex_big.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011, 2012 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file regex/test_regex_big.c
23  * @brief Stream API testing between 2 peers using testing API
24  * @author Bart Polot
25  * @author Max Szengel
26  */
27
28 #include <string.h>
29
30 #include "platform.h"
31 #include "gnunet_util_lib.h"
32 #include "gnunet_mesh_service.h"
33 #include "gnunet_stream_lib.h"
34 #include "gnunet_testbed_service.h"
35
36
37 #define NUM_HOSTS 2
38
39 #define PEER_PER_HOST 1
40
41 #define TOTAL_PEERS NUM_HOSTS * PEER_PER_HOST
42
43 /**
44  * Shorthand for Relative time in seconds
45  */
46 #define TIME_REL_SECS(sec) \
47   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
48
49 /**
50  * Structure for holding peer's sockets and IO Handles
51  */
52 struct PeerData
53 {
54   /**
55    * Handle to testbed peer
56    */
57   struct GNUNET_TESTBED_Peer *peer;
58
59   /**
60    * Peer's stream socket
61    */
62   struct GNUNET_STREAM_Socket *socket;
63
64   /**
65    * Peer's io write handle
66    */
67   struct GNUNET_STREAM_IOWriteHandle *io_write_handle;
68
69   /**
70    * Peer's io read handle
71    */
72   struct GNUNET_STREAM_IOReadHandle *io_read_handle;
73
74   /**
75    * Peer's shutdown handle
76    */
77   struct GNUNET_STREAM_ShutdownHandle *shutdown_handle;
78
79   /**
80    * The service connect operation to stream
81    */
82   struct GNUNET_TESTBED_Operation *op;
83
84   /**
85    * Our Peer id
86    */
87   struct GNUNET_PeerIdentity our_id;
88
89   /**
90    * Bytes the peer has written
91    */
92   unsigned int bytes_wrote;
93
94   /**
95    * Byte the peer has read
96    */
97   unsigned int bytes_read;
98 };
99
100
101 /**
102  * Different states in test setup
103  */
104 enum SetupState
105 {
106   /**
107    * The initial state
108    */
109   INIT,
110
111   /**
112    * Connecting to slave controller
113    */
114   LINKING,
115
116   CREATING_PEER,
117
118   STARTING_PEER,
119 };
120
121
122 /**
123  * Event Mask for operation callbacks
124  */
125 uint64_t event_mask;
126
127 /**
128  * Testbed operation handle
129  */
130 static struct GNUNET_TESTBED_Operation *op[NUM_HOSTS];
131
132 static enum SetupState state[NUM_HOSTS];
133
134 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
135
136 /**
137  * Global test result
138  */
139 static int result;
140
141 /**
142  * Hosts successfully registered
143  */
144 static unsigned int host_registered;
145
146 /**
147  * Peers successfully started
148  */
149 static unsigned int peers_started;
150
151 /**
152  * The master controller host
153  */
154 struct GNUNET_TESTBED_Host* master_host;
155
156 /**
157  * The master controller process
158  */
159 static struct GNUNET_TESTBED_ControllerProc *master_proc;
160
161 /**
162  * Handle to master controller
163  */
164 static struct GNUNET_TESTBED_Controller *master_ctrl;
165
166 /**
167  * Slave host IP addresses
168  */
169 static char *slave_ips[NUM_HOSTS] = {"131.159.20.34", "131.159.20.59"};
170
171 /**
172  * The slave hosts
173  */
174 struct GNUNET_TESTBED_Host *slave_hosts[NUM_HOSTS];
175
176 /**
177  * Slave host registration handles
178  */
179 static struct GNUNET_TESTBED_HostRegistrationHandle *rh;
180
181 /**
182  * The peers
183  */
184 struct GNUNET_TESTBED_Peer *peers[TOTAL_PEERS];
185
186 /**
187  * Handle to global configuration
188  */
189 static struct GNUNET_CONFIGURATION_Handle *cfg;
190
191
192 /**
193  * Completion callback for shutdown
194  *
195  * @param cls the closure from GNUNET_STREAM_shutdown call
196  * @param operation the operation that was shutdown (SHUT_RD, SHUT_WR,
197  *          SHUT_RDWR)
198  */
199 // static void
200 // shutdown_completion (void *cls,
201 //                      int operation)
202 // {
203 //   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "STREAM shutdown successful\n");
204 //   GNUNET_SCHEDULER_add_now (&do_close, cls);
205 // }
206
207
208
209 /**
210  * Shutdown sockets gracefully
211  */
212 // static void
213 // do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
214 // {
215 //   result = GNUNET_OK;
216 //   peer1.shutdown_handle = GNUNET_STREAM_shutdown (peer1.socket, SHUT_RDWR,
217 //                                                   &shutdown_completion, cls);
218 // }
219
220
221 /**
222  * Something went wrong and timed out. Kill everything and set error flag
223  */
224 static void
225 do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
226 {
227   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: ABORT\n");
228   result = GNUNET_SYSERR;
229   abort_task = 0;
230 }
231
232
233 /**
234  * Adapter function called to destroy a connection to
235  * a service.
236  *
237  * @param cls closure
238  * @param op_result service handle returned from the connect adapter
239  */
240 // static void
241 // stream_da (void *cls, void *op_result)
242 // {
243 //   struct GNUNET_STREAM_ListenSocket *lsocket;
244 //   struct GNUNET_STREAM_Socket *socket;
245 //
246 //   if (&peer1 == cls)
247 //   {
248 //     lsocket = op_result;
249 //     GNUNET_STREAM_listen_close (lsocket);
250 //     GNUNET_TESTBED_operation_done (peer2.op);
251 //     return;
252 //   }
253 //   if (&peer2 == cls)
254 //   {
255 //     socket = op_result;
256 //     GNUNET_STREAM_close (socket);
257 //     GNUNET_SCHEDULER_shutdown (); /* Exit point of the test */
258 //     return;
259 //   }
260 //   GNUNET_assert (0);
261 // }
262
263
264 /**
265  * Adapter function called to establish a connection to
266  * a service.
267  *
268  * @param cls closure
269  * @param cfg configuration of the peer to connect to; will be available until
270  *          GNUNET_TESTBED_operation_done() is called on the operation returned
271  *          from GNUNET_TESTBED_service_connect()
272  * @return service handle to return in 'op_result', NULL on error
273  */
274 // static void *
275 // stream_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
276 // {
277 //   struct GNUNET_STREAM_ListenSocket *lsocket;
278 //
279 //   switch (setup_state)
280 //   {
281 //   case PEER1_STREAM_CONNECT:
282 //     lsocket = GNUNET_STREAM_listen (cfg, 10, &stream_listen_cb, NULL,
283 //                                     GNUNET_STREAM_OPTION_SIGNAL_LISTEN_SUCCESS,
284 //                                     &stream_connect, GNUNET_STREAM_OPTION_END);
285 //     return lsocket;
286 //   case PEER2_STREAM_CONNECT:
287 //     peer2.socket = GNUNET_STREAM_open (cfg, &peer1.our_id, 10, &stream_open_cb,
288 //                                        &peer2, GNUNET_STREAM_OPTION_END);
289 //     return peer2.socket;
290 //   default:
291 //     GNUNET_assert (0);
292 //   }
293 // }
294
295
296 /**
297  * Listen success callback; connects a peer to stream as client
298  */
299 // static void
300 // stream_connect (void)
301 // {
302 //   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stream listen open successful\n");
303 //   peer2.op = GNUNET_TESTBED_service_connect (&peer2, peer2.peer, "stream",
304 //                                              NULL, NULL,
305 //                                              stream_ca, stream_da, &peer2);
306 //   setup_state = PEER2_STREAM_CONNECT;
307 // }
308
309
310 /**
311  * Callback to be called when the requested peer information is available
312  *
313  * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
314  * @param op the operation this callback corresponds to
315  * @param pinfo the result; will be NULL if the operation has failed
316  * @param emsg error message if the operation has failed; will be NULL if the
317  *          operation is successfull
318  */
319 // static void
320 // peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_,
321 //              const struct GNUNET_TESTBED_PeerInformation *pinfo,
322 //              const char *emsg)
323 // {
324 //   GNUNET_assert (NULL == emsg);
325 //   GNUNET_assert (op == op_);
326 //   switch (setup_state)
327 //     {
328 //     case PEER1_GET_IDENTITY:
329 //       memcpy (&peer1.our_id, pinfo->result.id,
330 //               sizeof (struct GNUNET_PeerIdentity));
331 //       GNUNET_TESTBED_operation_done (op);
332 //       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 id: %s\n", GNUNET_i2s
333 //                   (&peer1.our_id));
334 //       op = GNUNET_TESTBED_peer_get_information (peer2.peer,
335 //                                                 GNUNET_TESTBED_PIT_IDENTITY,
336 //                                                 &peerinfo_cb, NULL);
337 //       setup_state = PEER2_GET_IDENTITY;
338 //       break;
339 //     case PEER2_GET_IDENTITY:
340 //       memcpy (&peer2.our_id, pinfo->result.id,
341 //               sizeof (struct GNUNET_PeerIdentity));
342 //       GNUNET_TESTBED_operation_done (op);
343 //       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 2 id: %s\n", GNUNET_i2s
344 //                   (&peer2.our_id));
345 //       peer1.op = GNUNET_TESTBED_service_connect (&peer1, peer1.peer, "stream",
346 //                                                  NULL, NULL, stream_ca,
347 //                                                  stream_da, &peer1);
348 //       setup_state = PEER1_STREAM_CONNECT;
349 //       break;
350 //     default:
351 //       GNUNET_assert (0);
352 //     }
353 // }
354
355
356 /**
357  * Controller event callback
358  *
359  * @param cls NULL
360  * @param event the controller event
361  */
362 // static void
363 // controller_event_cb (void *cls,
364 //                      const struct GNUNET_TESTBED_EventInformation *event)
365 // {
366 //   switch (event->type)
367 //   {
368 //   case GNUNET_TESTBED_ET_CONNECT:
369 //     GNUNET_assert (INIT == setup_state);
370 //     GNUNET_TESTBED_operation_done (op);
371 //     /* Get the peer identity and configuration of peers */
372 //     op = GNUNET_TESTBED_peer_get_information (peer1.peer,
373 //                                               GNUNET_TESTBED_PIT_IDENTITY,
374 //                                               &peerinfo_cb, NULL);
375 //     setup_state = PEER1_GET_IDENTITY;
376 //     break;
377 //   case GNUNET_TESTBED_ET_OPERATION_FINISHED:
378 //     switch (setup_state)
379 //     {
380 //     case PEER1_STREAM_CONNECT:
381 //     case PEER2_STREAM_CONNECT:
382 //       GNUNET_assert (NULL == event->details.operation_finished.emsg);
383 //       break;
384 //     default:
385 //       GNUNET_assert (0);
386 //     }
387 //     break;
388 //   default:
389 //     GNUNET_assert (0);
390 //   }
391 // }
392
393
394 /**
395  * Signature of a main function for a testcase.
396  *
397  * @param cls closure
398  * @param num_peers number of peers in 'peers'
399  * @param peers handle to peers run in the testbed
400  */
401 // static void
402 // test_master (void *cls, unsigned int num_peers,
403 //              struct GNUNET_TESTBED_Peer **peers)
404 // {
405 //   GNUNET_assert (NULL != peers);
406 //   GNUNET_assert (NULL != peers[0]);
407 //   GNUNET_assert (NULL != peers[1]);
408 //   peer1.peer = peers[0];
409 //   peer2.peer = peers[1];
410 //   op = GNUNET_TESTBED_overlay_connect (NULL, NULL, NULL, peer2.peer, peer1.peer);
411 //   setup_state = INIT;
412 //   abort_task =
413 //     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
414 //                                   (GNUNET_TIME_UNIT_SECONDS, 40), &do_abort,
415 //                                   NULL);
416 // }
417
418 /**
419  * Functions of this signature are called when a peer has been successfully
420  * started or stopped.
421  *
422  * @param cls the closure from GNUNET_TESTBED_peer_start/stop()
423  * @param emsg NULL on success; otherwise an error description
424  */
425 static void
426 peer_start_cb (void *cls, const char *emsg)
427 {
428   long i = (long) cls;
429   GNUNET_TESTBED_operation_done(op[i]);
430   peers_started++;
431   // FIXME create and start rest of PEERS_PER_HOST
432
433   if (TOTAL_PEERS == peers_started)
434   {
435     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ok\n");
436   }
437 }
438
439
440 /**
441  * Functions of this signature are called when a peer has been successfully
442  * created
443  *
444  * @param cls the closure from GNUNET_TESTBED_peer_create()
445  * @param peer the handle for the created peer; NULL on any error during
446  *          creation
447  * @param emsg NULL if peer is not NULL; else MAY contain the error description
448  */
449 static void
450 peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
451 {
452   long i = (long) cls;
453   long peer_id;
454
455 //   GNUNET_TESTBED_operation_done(op[i]);
456   peer_id = i; // FIXME  A * i + B
457   peers[peer_id] = peer;
458   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Peer created\n");
459   op[i] = GNUNET_TESTBED_peer_start (peer, peer_start_cb, (void *) i);
460 }
461
462
463 /**
464  * Signature of the event handler function called by the
465  * respective event controller.
466  *
467  * @param cls closure
468  * @param event information about the event
469  */
470 static void
471 controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
472 {
473   long i;
474
475   switch (event->type)
476   {
477   case GNUNET_TESTBED_ET_PEER_START:
478     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Peer started\n");
479 //     event->details.peer_start.peer;
480     break;
481   case GNUNET_TESTBED_ET_PEER_STOP:
482   case GNUNET_TESTBED_ET_CONNECT:
483     break;
484   case GNUNET_TESTBED_ET_OPERATION_FINISHED:
485     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Operation finished\n");
486     if (NULL != event->details.operation_finished.emsg)
487     {
488       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
489                   event->details.operation_finished.emsg);
490       GNUNET_assert (0);
491     }
492     GNUNET_TESTBED_operation_done (event->details.operation_finished.operation);
493     i = (long) event->details.operation_finished.op_cls;
494     op[i] = NULL;
495     switch (state[i])
496     {
497       case INIT:
498         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Init\n");
499         break;
500       case LINKING:
501         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Link\n");
502         state[i] = CREATING_PEER;
503         op[i] = GNUNET_TESTBED_peer_create (master_ctrl,
504                                             slave_hosts[i],
505                                             cfg,
506                                             peer_create_cb,
507                                             (void *) i);
508         break;
509       case CREATING_PEER:
510         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Peer create\n");
511         break;
512       default:
513         GNUNET_break (0);
514     }
515     break;
516   default:
517     GNUNET_break (0);
518   }
519 }
520
521 /**
522  * Callback which will be called to after a host registration succeeded or failed
523  *
524  * @param cls the host which has been registered
525  * @param emsg the error message; NULL if host registration is successful
526  */
527 static void
528 registration_cont (void *cls, const char *emsg)
529 {
530   if (NULL != emsg)
531   {
532     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
533     GNUNET_assert (0);
534   }
535
536   state[host_registered] = LINKING;
537   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
538               " Linking host %u\n", host_registered);
539   op[host_registered] = GNUNET_TESTBED_controller_link (master_ctrl,
540                                                         slave_hosts[host_registered],
541                                                         NULL,
542                                                         cfg,
543                                                         GNUNET_YES);
544
545   host_registered++;
546   if (NUM_HOSTS != host_registered)
547   {
548     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Registering host %u\n",
549                 host_registered);
550     rh = GNUNET_TESTBED_register_host (master_ctrl,
551                                        slave_hosts[host_registered],
552                                        &registration_cont,
553                                        NULL);
554     return;
555   }
556 }
557
558 /**
559  * Callback to signal successfull startup of the controller process
560  *
561  * @param cls the closure from GNUNET_TESTBED_controller_start()
562  * @param cfg the configuration with which the controller has been started;
563  *          NULL if status is not GNUNET_OK
564  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
565  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
566  */
567 static void
568 status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config,
569            int status)
570 {
571   unsigned int i;
572
573   if (NULL == config)
574     return;
575
576   event_mask = 0;
577   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START);
578   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP);
579   event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT);
580   event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED);
581   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to master controller\n");
582   master_ctrl = GNUNET_TESTBED_controller_connect (config,
583                                                    master_host,
584                                                    event_mask,
585                                                    &controller_cb,
586                                                    NULL);
587   GNUNET_assert (NULL != master_ctrl);
588
589   for (i = 0; i < NUM_HOSTS; i++)
590   {
591     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating host %u\n", i);
592     slave_hosts[i] = GNUNET_TESTBED_host_create_with_id (i+1, slave_ips[i], NULL, 0);
593     GNUNET_assert (NULL != slave_hosts[i]);
594   }
595   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Registering host 0\n");
596   rh = GNUNET_TESTBED_register_host (master_ctrl, slave_hosts[0],
597                                      &registration_cont,
598                                      NULL);
599   GNUNET_assert (NULL != rh);
600 }
601
602
603 /**
604  * Main run function.
605  *
606  * @param cls NULL
607  * @param args arguments passed to GNUNET_PROGRAM_run
608  * @param cfgfile the path to configuration file
609  * @param cfg the configuration file handle
610  */
611 static void
612 run (void *cls, char *const *args, const char *cfgfile,
613      const struct GNUNET_CONFIGURATION_Handle *config)
614 {
615   master_host = GNUNET_TESTBED_host_create (NULL, NULL, 0);
616   GNUNET_assert (NULL != master_host);
617   cfg = GNUNET_CONFIGURATION_dup (config);
618   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting master controller\n");
619   master_proc = GNUNET_TESTBED_controller_start ("127.0.0.1",
620                                                  master_host,
621                                                  cfg,
622                                                  status_cb,
623                                                  NULL);
624   abort_task =
625       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
626                                     (GNUNET_TIME_UNIT_MINUTES, 60), &do_abort,
627                                     NULL);
628 }
629
630 /**
631  * Main function
632  */
633 int main (int argc, char **argv)
634 {
635   int ret;
636   int test_hosts;
637   unsigned int i;
638
639   struct GNUNET_GETOPT_CommandLineOption options[] = {
640     GNUNET_GETOPT_OPTION_END
641   };
642   char *const argv2[] = { "test_big",
643     "-c", "test_regex_big.conf",
644     NULL
645   };
646
647   test_hosts = GNUNET_OK;
648   for (i = 0; i < NUM_HOSTS; i++)
649   {
650     char *const remote_args[] = {
651       "ssh", "-o", "BatchMode=yes", slave_ips[i],
652       ". .bashrc; gnunet-helper-testbed --help > /dev/null", NULL
653     };
654     struct GNUNET_OS_Process *auxp;
655     enum GNUNET_OS_ProcessStatusType type;
656     unsigned long code;
657
658     fprintf (stderr, "Testing host %i\n", i);
659     auxp =
660       GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL,
661                                  NULL, "ssh", remote_args);
662     GNUNET_assert (NULL != auxp);
663     do
664     {
665       ret = GNUNET_OS_process_status (auxp, &type, &code);
666       GNUNET_assert (GNUNET_SYSERR != ret);
667       (void) usleep (300);
668     }
669     while (GNUNET_NO == ret);
670     (void) GNUNET_OS_process_wait (auxp);
671     GNUNET_OS_process_destroy (auxp);
672     if (0 != code)
673     {
674       fprintf (stderr,
675                "Unable to run the test as this system is not configured "
676                "to use password less SSH logins to host %s.\n",
677                slave_ips[i]);
678       test_hosts = GNUNET_SYSERR;
679     }
680   }
681   if (test_hosts != GNUNET_OK)
682   {
683     fprintf (stderr, "Some hosts have failed the ssh check. Exiting.\n");
684     return 1;
685   }
686   fprintf (stderr, "START.\n");
687
688   result = GNUNET_SYSERR;
689
690   ret =
691       GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
692                           "test_regex_big", "nohelp", options,
693                           &run, NULL);
694
695   fprintf (stderr, "END.\n");
696
697   if (GNUNET_SYSERR == result || GNUNET_OK != ret)
698     return 1;
699   return 0;
700 }