- fix
[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
117
118 /**
119  * Event Mask for operation callbacks
120  */
121 uint64_t event_mask;
122
123 /**
124  * Testbed operation handle
125  */
126 static struct GNUNET_TESTBED_Operation *op[NUM_HOSTS];
127
128 static enum SetupState state[NUM_HOSTS];
129
130 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
131
132 /**
133  * Global test result
134  */
135 static int result;
136
137 /**
138  * Hosts successfully registered
139  */
140 static unsigned int host_registered;
141
142 /**
143  * Peers successfully started
144  */
145 static unsigned int peers_started;
146
147 /**
148  * The master controller host
149  */
150 struct GNUNET_TESTBED_Host* master_host;
151
152 /**
153  * The master controller process
154  */
155 static struct GNUNET_TESTBED_ControllerProc *master_proc;
156
157 /**
158  * Handle to master controller
159  */
160 static struct GNUNET_TESTBED_Controller *master_ctrl;
161
162 /**
163  * Slave host IP addresses
164  */
165 static char *slave_ips[NUM_HOSTS] = {"131.159.20.34", "131.159.20.59"};
166
167 /**
168  * The slave hosts
169  */
170 struct GNUNET_TESTBED_Host *slave_hosts[NUM_HOSTS];
171
172 /**
173  * Slave host registration handles
174  */
175 static struct GNUNET_TESTBED_HostRegistrationHandle *rh;
176
177 /**
178  * The peers
179  */
180 struct GNUNET_TESTBED_Peer *peers[TOTAL_PEERS];
181
182 /**
183  * Handle to global configuration
184  */
185 static struct GNUNET_CONFIGURATION_Handle *cfg;
186
187
188 /**
189  * Completion callback for shutdown
190  *
191  * @param cls the closure from GNUNET_STREAM_shutdown call
192  * @param operation the operation that was shutdown (SHUT_RD, SHUT_WR,
193  *          SHUT_RDWR)
194  */
195 // static void
196 // shutdown_completion (void *cls,
197 //                      int operation)
198 // {
199 //   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "STREAM shutdown successful\n");
200 //   GNUNET_SCHEDULER_add_now (&do_close, cls);
201 // }
202
203
204
205 /**
206  * Shutdown sockets gracefully
207  */
208 // static void
209 // do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
210 // {
211 //   result = GNUNET_OK;
212 //   peer1.shutdown_handle = GNUNET_STREAM_shutdown (peer1.socket, SHUT_RDWR,
213 //                                                   &shutdown_completion, cls);
214 // }
215
216
217 /**
218  * Something went wrong and timed out. Kill everything and set error flag
219  */
220 static void
221 do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
222 {
223   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: ABORT\n");
224   result = GNUNET_SYSERR;
225   abort_task = 0;
226 }
227
228
229 /**
230  * Adapter function called to destroy a connection to
231  * a service.
232  *
233  * @param cls closure
234  * @param op_result service handle returned from the connect adapter
235  */
236 // static void
237 // stream_da (void *cls, void *op_result)
238 // {
239 //   struct GNUNET_STREAM_ListenSocket *lsocket;
240 //   struct GNUNET_STREAM_Socket *socket;
241 //
242 //   if (&peer1 == cls)
243 //   {
244 //     lsocket = op_result;
245 //     GNUNET_STREAM_listen_close (lsocket);
246 //     GNUNET_TESTBED_operation_done (peer2.op);
247 //     return;
248 //   }
249 //   if (&peer2 == cls)
250 //   {
251 //     socket = op_result;
252 //     GNUNET_STREAM_close (socket);
253 //     GNUNET_SCHEDULER_shutdown (); /* Exit point of the test */
254 //     return;
255 //   }
256 //   GNUNET_assert (0);
257 // }
258
259
260 /**
261  * Adapter function called to establish a connection to
262  * a service.
263  *
264  * @param cls closure
265  * @param cfg configuration of the peer to connect to; will be available until
266  *          GNUNET_TESTBED_operation_done() is called on the operation returned
267  *          from GNUNET_TESTBED_service_connect()
268  * @return service handle to return in 'op_result', NULL on error
269  */
270 // static void *
271 // stream_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
272 // {
273 //   struct GNUNET_STREAM_ListenSocket *lsocket;
274 //
275 //   switch (setup_state)
276 //   {
277 //   case PEER1_STREAM_CONNECT:
278 //     lsocket = GNUNET_STREAM_listen (cfg, 10, &stream_listen_cb, NULL,
279 //                                     GNUNET_STREAM_OPTION_SIGNAL_LISTEN_SUCCESS,
280 //                                     &stream_connect, GNUNET_STREAM_OPTION_END);
281 //     return lsocket;
282 //   case PEER2_STREAM_CONNECT:
283 //     peer2.socket = GNUNET_STREAM_open (cfg, &peer1.our_id, 10, &stream_open_cb,
284 //                                        &peer2, GNUNET_STREAM_OPTION_END);
285 //     return peer2.socket;
286 //   default:
287 //     GNUNET_assert (0);
288 //   }
289 // }
290
291
292 /**
293  * Listen success callback; connects a peer to stream as client
294  */
295 // static void
296 // stream_connect (void)
297 // {
298 //   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stream listen open successful\n");
299 //   peer2.op = GNUNET_TESTBED_service_connect (&peer2, peer2.peer, "stream",
300 //                                              NULL, NULL,
301 //                                              stream_ca, stream_da, &peer2);
302 //   setup_state = PEER2_STREAM_CONNECT;
303 // }
304
305
306 /**
307  * Callback to be called when the requested peer information is available
308  *
309  * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
310  * @param op the operation this callback corresponds to
311  * @param pinfo the result; will be NULL if the operation has failed
312  * @param emsg error message if the operation has failed; will be NULL if the
313  *          operation is successfull
314  */
315 // static void
316 // peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_,
317 //              const struct GNUNET_TESTBED_PeerInformation *pinfo,
318 //              const char *emsg)
319 // {
320 //   GNUNET_assert (NULL == emsg);
321 //   GNUNET_assert (op == op_);
322 //   switch (setup_state)
323 //     {
324 //     case PEER1_GET_IDENTITY:
325 //       memcpy (&peer1.our_id, pinfo->result.id,
326 //               sizeof (struct GNUNET_PeerIdentity));
327 //       GNUNET_TESTBED_operation_done (op);
328 //       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 id: %s\n", GNUNET_i2s
329 //                   (&peer1.our_id));
330 //       op = GNUNET_TESTBED_peer_get_information (peer2.peer,
331 //                                                 GNUNET_TESTBED_PIT_IDENTITY,
332 //                                                 &peerinfo_cb, NULL);
333 //       setup_state = PEER2_GET_IDENTITY;
334 //       break;
335 //     case PEER2_GET_IDENTITY:
336 //       memcpy (&peer2.our_id, pinfo->result.id,
337 //               sizeof (struct GNUNET_PeerIdentity));
338 //       GNUNET_TESTBED_operation_done (op);
339 //       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 2 id: %s\n", GNUNET_i2s
340 //                   (&peer2.our_id));
341 //       peer1.op = GNUNET_TESTBED_service_connect (&peer1, peer1.peer, "stream",
342 //                                                  NULL, NULL, stream_ca,
343 //                                                  stream_da, &peer1);
344 //       setup_state = PEER1_STREAM_CONNECT;
345 //       break;
346 //     default:
347 //       GNUNET_assert (0);
348 //     }
349 // }
350
351
352 /**
353  * Controller event callback
354  *
355  * @param cls NULL
356  * @param event the controller event
357  */
358 // static void
359 // controller_event_cb (void *cls,
360 //                      const struct GNUNET_TESTBED_EventInformation *event)
361 // {
362 //   switch (event->type)
363 //   {
364 //   case GNUNET_TESTBED_ET_CONNECT:
365 //     GNUNET_assert (INIT == setup_state);
366 //     GNUNET_TESTBED_operation_done (op);
367 //     /* Get the peer identity and configuration of peers */
368 //     op = GNUNET_TESTBED_peer_get_information (peer1.peer,
369 //                                               GNUNET_TESTBED_PIT_IDENTITY,
370 //                                               &peerinfo_cb, NULL);
371 //     setup_state = PEER1_GET_IDENTITY;
372 //     break;
373 //   case GNUNET_TESTBED_ET_OPERATION_FINISHED:
374 //     switch (setup_state)
375 //     {
376 //     case PEER1_STREAM_CONNECT:
377 //     case PEER2_STREAM_CONNECT:
378 //       GNUNET_assert (NULL == event->details.operation_finished.emsg);
379 //       break;
380 //     default:
381 //       GNUNET_assert (0);
382 //     }
383 //     break;
384 //   default:
385 //     GNUNET_assert (0);
386 //   }
387 // }
388
389
390 /**
391  * Signature of a main function for a testcase.
392  *
393  * @param cls closure
394  * @param num_peers number of peers in 'peers'
395  * @param peers handle to peers run in the testbed
396  */
397 // static void
398 // test_master (void *cls, unsigned int num_peers,
399 //              struct GNUNET_TESTBED_Peer **peers)
400 // {
401 //   GNUNET_assert (NULL != peers);
402 //   GNUNET_assert (NULL != peers[0]);
403 //   GNUNET_assert (NULL != peers[1]);
404 //   peer1.peer = peers[0];
405 //   peer2.peer = peers[1];
406 //   op = GNUNET_TESTBED_overlay_connect (NULL, NULL, NULL, peer2.peer, peer1.peer);
407 //   setup_state = INIT;
408 //   abort_task =
409 //     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
410 //                                   (GNUNET_TIME_UNIT_SECONDS, 40), &do_abort,
411 //                                   NULL);
412 // }
413
414 /**
415  * Functions of this signature are called when a peer has been successfully
416  * started or stopped.
417  *
418  * @param cls the closure from GNUNET_TESTBED_peer_start/stop()
419  * @param emsg NULL on success; otherwise an error description
420  */
421 static void
422 peer_start_cb (void *cls, const char *emsg)
423 {
424   long i = (long) cls;
425   GNUNET_TESTBED_operation_done(op[i]);
426   peers_started++;
427   // FIXME create and start rest of PEERS_PER_HOST
428
429   if (TOTAL_PEERS == peers_started)
430   {
431     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ok\n");
432   }
433 }
434
435
436 /**
437  * Functions of this signature are called when a peer has been successfully
438  * created
439  *
440  * @param cls the closure from GNUNET_TESTBED_peer_create()
441  * @param peer the handle for the created peer; NULL on any error during
442  *          creation
443  * @param emsg NULL if peer is not NULL; else MAY contain the error description
444  */
445 static void
446 peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
447 {
448   long i = (long) cls;
449   long peer_id;
450
451   GNUNET_TESTBED_operation_done(op[i]);
452   peer_id = i; // FIXME  A * i + B
453   peers[peer_id] = peer;
454   op[i] = GNUNET_TESTBED_peer_start (peer, peer_start_cb, (void *) i);
455 }
456
457 /**
458  * Signature of the event handler function called by the
459  * respective event controller.
460  *
461  * @param cls closure
462  * @param event information about the event
463  */
464 static void
465 controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
466 {
467   long i;
468
469   switch (event->type)
470   {
471   case GNUNET_TESTBED_ET_PEER_START:
472     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Peer started\n");
473 //     event->details.peer_start.peer;
474     break;
475   case GNUNET_TESTBED_ET_PEER_STOP:
476   case GNUNET_TESTBED_ET_CONNECT:
477     break;
478   case GNUNET_TESTBED_ET_OPERATION_FINISHED:
479     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Operation finished\n");
480     if (NULL != event->details.operation_finished.emsg)
481     {
482       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
483                   event->details.operation_finished.emsg);
484       GNUNET_assert (0);
485     }
486     GNUNET_TESTBED_operation_done (event->details.operation_finished.operation);
487     i = (long) event->details.operation_finished.op_cls;
488     op[i] = NULL;
489     switch (state[i])
490     {
491       case INIT:
492         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Init\n");
493         op[i] = GNUNET_TESTBED_peer_create (master_ctrl,
494                                             slave_hosts[i],
495                                             cfg,
496                                             peer_create_cb,
497                                             (void *) i);
498         break;
499       case LINKING:
500         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Link\n");
501         break;
502       default:
503         GNUNET_break (0);
504     }
505     break;
506   default:
507     GNUNET_break (0);
508   }
509 }
510
511 /**
512  * Callback which will be called to after a host registration succeeded or failed
513  *
514  * @param cls the host which has been registered
515  * @param emsg the error message; NULL if host registration is successful
516  */
517 static void
518 registration_cont (void *cls, const char *emsg)
519 {
520   if (NULL != emsg)
521   {
522     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
523     GNUNET_assert (0);
524   }
525
526   state[host_registered] = LINKING;
527   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
528               " Linking host %u\n", host_registered);
529   op[host_registered] = GNUNET_TESTBED_controller_link (master_ctrl,
530                                                         slave_hosts[host_registered],
531                                                         NULL,
532                                                         cfg,
533                                                         GNUNET_YES);
534
535   host_registered++;
536   if (NUM_HOSTS != host_registered)
537   {
538     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Registering host %u\n",
539                 host_registered);
540     rh = GNUNET_TESTBED_register_host (master_ctrl,
541                                        slave_hosts[host_registered],
542                                        &registration_cont,
543                                        NULL);
544     return;
545   }
546 }
547
548 /**
549  * Callback to signal successfull startup of the controller process
550  *
551  * @param cls the closure from GNUNET_TESTBED_controller_start()
552  * @param cfg the configuration with which the controller has been started;
553  *          NULL if status is not GNUNET_OK
554  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
555  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
556  */
557 static void
558 status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config,
559            int status)
560 {
561   unsigned int i;
562
563   event_mask = 0;
564   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START);
565   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP);
566   event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT);
567   event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED);
568   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to master controller\n");
569   master_ctrl = GNUNET_TESTBED_controller_connect (config,
570                                                    master_host,
571                                                    event_mask,
572                                                    &controller_cb,
573                                                    NULL);
574   GNUNET_assert (NULL != master_ctrl);
575
576   for (i = 0; i < NUM_HOSTS; i++)
577   {
578     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating host %u\n", i);
579     slave_hosts[i] = GNUNET_TESTBED_host_create_with_id (i+1, slave_ips[i], NULL, 0);
580     GNUNET_assert (NULL != slave_hosts[i]);
581   }
582   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Registering host 0\n");
583   rh = GNUNET_TESTBED_register_host (master_ctrl, slave_hosts[0],
584                                      &registration_cont,
585                                      NULL);
586   GNUNET_assert (NULL != rh);
587 }
588
589
590 /**
591  * Main run function.
592  *
593  * @param cls NULL
594  * @param args arguments passed to GNUNET_PROGRAM_run
595  * @param cfgfile the path to configuration file
596  * @param cfg the configuration file handle
597  */
598 static void
599 run (void *cls, char *const *args, const char *cfgfile,
600      const struct GNUNET_CONFIGURATION_Handle *config)
601 {
602   master_host = GNUNET_TESTBED_host_create (NULL, NULL, 0);
603   GNUNET_assert (NULL != master_host);
604   cfg = GNUNET_CONFIGURATION_dup (config);
605   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting master controller\n");
606   master_proc = GNUNET_TESTBED_controller_start ("127.0.0.1",
607                                                  master_host,
608                                                  cfg,
609                                                  status_cb,
610                                                  NULL);
611   abort_task =
612       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
613                                     (GNUNET_TIME_UNIT_MINUTES, 60), &do_abort,
614                                     NULL);
615 }
616
617 /**
618  * Main function
619  */
620 int main (int argc, char **argv)
621 {
622   int ret;
623   unsigned int i;
624
625   struct GNUNET_GETOPT_CommandLineOption options[] = {
626     GNUNET_GETOPT_OPTION_END
627   };
628   char *const argv2[] = { "test_big",
629     "-c", "test_regex_big.conf",
630     NULL
631   };
632
633   for (i = 0; i < NUM_HOSTS; i++)
634   {
635     char *const remote_args[] = {
636       "ssh", "-o", "BatchMode=yes", slave_ips[i], "echo", "Hello", "World", NULL
637     };
638     struct GNUNET_OS_Process *auxp;
639     enum GNUNET_OS_ProcessStatusType type;
640     unsigned long code;
641
642     auxp =
643       GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL,
644                                  NULL, "ssh", remote_args);
645     GNUNET_assert (NULL != auxp);
646     do
647     {
648       ret = GNUNET_OS_process_status (auxp, &type, &code);
649       GNUNET_assert (GNUNET_SYSERR != ret);
650       (void) usleep (300);
651     }
652     while (GNUNET_NO == ret);
653     (void) GNUNET_OS_process_wait (auxp);
654     GNUNET_OS_process_destroy (auxp);
655     if (0 != code)
656     {
657       (void) printf("Unable to run the test as this system is not configured "
658                     "to use password less SSH logins to host %s.\n"
659                     "Marking test as successful\n", slave_ips[i]);
660       return 0;
661     }
662   }
663
664   result = GNUNET_SYSERR;
665
666   ret =
667       GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
668                           "test_regex_big", "nohelp", options,
669                           &run, NULL);
670
671   if (GNUNET_SYSERR == result || 0 != ret)
672     return 1;
673   return 0;
674 }