50a9cc80e39398cc5f4b099a95d55acd86b142ee
[oweals/gnunet.git] / src / transport / test_transport_api_reliability.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010 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  * @file transport/test_transport_api_reliability.c
22  * @brief base test case for transport implementations
23  *
24  * This test case serves as a base for tcp and http
25  * transport test cases to check that the transports
26  * achieve reliable message delivery.
27  */
28 #include "platform.h"
29 #include "gnunet_common.h"
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_getopt_lib.h"
32 #include "gnunet_os_lib.h"
33 #include "gnunet_program_lib.h"
34 #include "gnunet_scheduler_lib.h"
35 #include "gnunet_server_lib.h"
36 #include "gnunet_transport_service.h"
37 #include "gauger.h"
38 #include "transport.h"
39 #include "transport-testing.h"
40
41 #define VERBOSE GNUNET_NO
42
43 #define VERBOSE_ARM GNUNET_NO
44
45 #define START_ARM GNUNET_YES
46
47 /**
48  * Note that this value must not significantly exceed
49  * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise
50  * messages may be dropped even for a reliable transport.
51  */
52 #define TOTAL_MSGS (10000 * 2)
53
54 /**
55  * How long until we give up on transmitting the message?
56  */
57 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500)
58
59 #define MTYPE 12345
60
61 static struct PeerContext p1;
62
63 static struct PeerContext p2;
64
65 static int ok;
66
67 static int is_tcp;
68
69 static int is_tcp_nat;
70
71 static int is_http;
72
73 static int is_https;
74
75 static int is_udp;
76
77 static int is_unix;
78
79 static int is_wlan;
80
81 static int connected;
82
83 static unsigned long long total_bytes;
84
85 static struct GNUNET_TIME_Absolute start_time;
86
87 static GNUNET_SCHEDULER_TaskIdentifier die_task;
88
89 static GNUNET_SCHEDULER_TaskIdentifier tct;
90
91 struct GNUNET_TRANSPORT_TransmitHandle * th_p2;
92
93 static char * key_file_p1;
94 static char * cert_file_p1;
95
96 static char * key_file_p2;
97 static char * cert_file_p2;
98 static char *test_name;
99 static int msg_scheduled;
100 static int msg_sent;
101 static int msg_recv_expected;
102 static int msg_recv;
103
104 #if VERBOSE
105 #define OKPP do { ok++; fprintf (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
106 #else
107 #define OKPP do { ok++; } while (0)
108 #endif
109
110
111 static void
112 end ()
113 {
114   unsigned long long delta;
115   char *value_name;
116
117   if (die_task != GNUNET_SCHEDULER_NO_TASK)
118     GNUNET_SCHEDULER_cancel (die_task);
119   die_task = GNUNET_SCHEDULER_NO_TASK;
120 #if VERBOSE
121   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from transports!\n");
122 #endif
123
124   if (th_p2 != NULL)
125     GNUNET_TRANSPORT_notify_transmit_ready_cancel(th_p2);
126   th_p2 = NULL;
127
128   GNUNET_TRANSPORT_disconnect (p1.th);
129   GNUNET_TRANSPORT_disconnect (p2.th);
130 #if VERBOSE
131   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
132               "Transports disconnected, returning success!\n");
133 #endif
134   delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value;
135   fprintf (stderr,
136            "\nThroughput was %llu kb/s\n",
137            total_bytes * 1000 / 1024 / delta);
138   GNUNET_asprintf(&value_name, "reliable_%s", test_name);
139   GAUGER ("TRANSPORT", value_name, (int)(total_bytes * 1000 / 1024 /delta), "kb/s");
140   GNUNET_free(value_name);
141   ok = 0;
142
143 }
144
145
146
147 static void
148 stop_arm (struct PeerContext *p)
149 {
150 #if START_ARM
151   if (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM))
152     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
153   GNUNET_OS_process_wait (p->arm_proc);
154   GNUNET_OS_process_close (p->arm_proc);
155   p->arm_proc = NULL;
156 #endif
157   GNUNET_CONFIGURATION_destroy (p->cfg);
158 }
159
160
161 static void
162 end_badly (void *cls,
163            const struct GNUNET_SCHEDULER_TaskContext *tc)
164 {
165   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
166               "Reliability failed: Last message sent %u, Next message scheduled %u, Last message received %u, Message expected %u\n",
167               msg_sent, 
168               msg_scheduled, 
169               msg_recv, 
170               msg_recv_expected);
171   if (th_p2 != NULL)
172     GNUNET_TRANSPORT_notify_transmit_ready_cancel(th_p2);
173   th_p2 = NULL;
174
175   GNUNET_break (0);
176   GNUNET_TRANSPORT_disconnect (p1.th);
177   GNUNET_TRANSPORT_disconnect (p2.th);
178   if (GNUNET_SCHEDULER_NO_TASK != tct)
179     {
180       GNUNET_SCHEDULER_cancel (tct);
181       tct = GNUNET_SCHEDULER_NO_TASK;
182     }
183   ok = 1;
184 }
185
186
187 struct TestMessage
188 {
189   struct GNUNET_MessageHeader header;
190   uint32_t num;
191 };
192
193
194 static unsigned int
195 get_size (unsigned int iter)
196 {
197   unsigned int ret;
198
199   if (iter < 60000)
200     return iter + sizeof (struct TestMessage);
201   ret = (iter * iter * iter);
202   return sizeof (struct TestMessage) + (ret % 60000);
203 }
204
205
206 static void
207 notify_receive (void *cls,
208                 const struct GNUNET_PeerIdentity *peer,
209                 const struct GNUNET_MessageHeader *message,
210                 const struct GNUNET_TRANSPORT_ATS_Information *ats,
211                 uint32_t ats_count)
212 {
213   static int n;
214   unsigned int s;
215   char cbuf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
216   const struct TestMessage *hdr;
217
218   hdr = (const struct TestMessage*) message;
219   s = get_size (n);
220   if (MTYPE != ntohs (message->type))
221     return;
222   msg_recv_expected = n;
223   msg_recv = ntohl(hdr->num);
224   if (ntohs (message->size) != s)
225     {
226       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
227                   "Expected message %u of size %u, got %u bytes of message %u\n",
228                   n, s,
229                   ntohs (message->size),
230                   ntohl (hdr->num));
231       if (die_task != GNUNET_SCHEDULER_NO_TASK)
232         GNUNET_SCHEDULER_cancel (die_task);
233       die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
234       return;
235     }
236   if (ntohl (hdr->num) != n)
237     {
238       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
239                   "Expected message %u of size %u, got %u bytes of message %u\n",
240                   n, s,
241                   ntohs (message->size),
242                   ntohl (hdr->num));
243       if (die_task != GNUNET_SCHEDULER_NO_TASK)
244         GNUNET_SCHEDULER_cancel (die_task);
245       die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
246       return;
247     }
248   memset (cbuf, n, s - sizeof (struct TestMessage));
249   if (0 != memcmp (cbuf,
250                    &hdr[1],
251                    s - sizeof (struct TestMessage)))
252     {
253       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
254                   "Expected message %u with bits %u, but body did not match\n",
255                   n, (unsigned char) n);
256       if (die_task != GNUNET_SCHEDULER_NO_TASK)
257         GNUNET_SCHEDULER_cancel (die_task);
258       die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
259       return;
260     }
261 #if VERBOSE
262   if (ntohl(hdr->num) % 5000 == 0)
263     {
264       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
265                   "Got message %u of size %u\n",
266                   ntohl (hdr->num),
267                   ntohs (message->size));
268     }
269 #endif
270   n++;
271   if (0 == (n % (TOTAL_MSGS/100)))
272     {
273       fprintf (stderr, ".");
274       if (die_task != GNUNET_SCHEDULER_NO_TASK)
275         GNUNET_SCHEDULER_cancel (die_task);
276       die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
277                                                &end_badly,
278                                                NULL);
279     }
280   if (n == TOTAL_MSGS)
281     end ();
282 }
283
284
285 static size_t
286 notify_ready (void *cls, size_t size, void *buf)
287 {
288   static int n;
289   char *cbuf = buf;
290   struct TestMessage hdr;
291   unsigned int s;
292   unsigned int ret;
293
294   if (buf == NULL)
295     {
296       GNUNET_break (0);
297       ok = 42;
298       return 0;
299     }
300   th_p2 = NULL;
301   ret = 0;
302   s = get_size (n);
303   GNUNET_assert (size >= s);
304   GNUNET_assert (buf != NULL);
305   cbuf = buf;
306   do
307     {
308       hdr.header.size = htons (s);
309       hdr.header.type = htons (MTYPE);
310       hdr.num = htonl (n);
311       msg_sent = n;
312       memcpy (&cbuf[ret], &hdr, sizeof (struct TestMessage));
313       ret += sizeof (struct TestMessage);
314       memset (&cbuf[ret], n, s - sizeof (struct TestMessage));
315       ret += s - sizeof (struct TestMessage);
316 #if VERBOSE
317       if (n % 5000 == 0)
318         {
319           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
320                       "Sending message %u of size %u\n",
321                       n,
322                       s);
323         }
324 #endif
325       n++;
326       s = get_size (n);
327       if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16))
328         break; /* sometimes pack buffer full, sometimes not */
329     }
330   while (size - ret >= s);
331   if (n < TOTAL_MSGS)
332   {
333     th_p2 = GNUNET_TRANSPORT_notify_transmit_ready (p2.th,
334                                             &p1.id,
335                                             s, 0, TIMEOUT,
336                                             &notify_ready,
337                                             NULL);
338     msg_scheduled = n;
339   }
340   if (n % 5000 == 0)
341     {
342       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
343                   "Returning total message block of size %u\n",
344                   ret);
345     }
346   total_bytes += ret;
347   return ret;
348 }
349
350
351 static void
352 notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
353 {
354   connected--;
355 #if VERBOSE
356   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
357               "Peer `%4s' disconnected (%p)!\n",
358               GNUNET_i2s (peer), cls);
359 #endif
360 }
361
362
363 static void
364 exchange_hello_last (void *cls,
365                      const struct GNUNET_MessageHeader *message)
366 {
367   struct PeerContext *me = cls;
368
369   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
370               "Exchanging HELLO of size %d with peer (%s)!\n", 
371               (int) GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message),
372               GNUNET_i2s (&me->id));
373   GNUNET_assert (message != NULL);
374   GNUNET_assert (GNUNET_OK ==
375                  GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
376                                       message, &me->id));
377   GNUNET_TRANSPORT_offer_hello (p1.th, message, NULL, NULL);
378 }
379
380
381
382 static void
383 exchange_hello (void *cls,
384                 const struct GNUNET_MessageHeader *message)
385 {
386   struct PeerContext *me = cls;
387
388   GNUNET_assert (message != NULL);
389   GNUNET_assert (GNUNET_OK ==
390                  GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
391                                       message, &me->id));
392   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
393               "Exchanging HELLO of size %d from peer %s!\n", 
394               (int) GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message),
395               GNUNET_i2s (&me->id));
396   GNUNET_TRANSPORT_offer_hello (p2.th, message, NULL, NULL);
397 }
398
399
400 static void
401 notify_connect (void *cls,
402                 const struct GNUNET_PeerIdentity *peer,
403                 const struct GNUNET_TRANSPORT_ATS_Information *ats,
404                 uint32_t ats_count)
405 {
406   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
407               "Peer `%4s' connected to us (%p)!\n", 
408               GNUNET_i2s (peer), 
409               cls);
410   connected++;
411   if (cls == &p1)
412     {
413       GNUNET_TRANSPORT_set_quota (p1.th,
414                                   &p2.id,
415                                   GNUNET_BANDWIDTH_value_init (1024 * 1024 * 1024),
416                                   GNUNET_BANDWIDTH_value_init (1024 * 1024 * 1024));
417       start_time = GNUNET_TIME_absolute_get ();
418     }
419   else
420     {
421       GNUNET_TRANSPORT_set_quota (p2.th,
422                                   &p1.id,
423                                   GNUNET_BANDWIDTH_value_init (1024 * 1024 * 1024),
424                                   GNUNET_BANDWIDTH_value_init (1024 * 1024 * 1024));
425     }
426   if (2 == connected)
427     {
428       if (die_task != GNUNET_SCHEDULER_NO_TASK)
429         GNUNET_SCHEDULER_cancel (die_task);
430       if (tct != GNUNET_SCHEDULER_NO_TASK)
431       GNUNET_SCHEDULER_cancel (tct);
432       tct = GNUNET_SCHEDULER_NO_TASK;
433       GNUNET_TRANSPORT_get_hello_cancel (p2.th, &exchange_hello_last, &p2);
434       GNUNET_TRANSPORT_get_hello_cancel (p1.th, &exchange_hello, &p1);
435       die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
436                                                &end_badly, NULL);
437       th_p2 = GNUNET_TRANSPORT_notify_transmit_ready (p2.th,
438                                               &p1.id,
439                                               get_size (0), 0, TIMEOUT,
440                                               &notify_ready,
441                                               NULL);
442       
443     }
444 }
445
446
447 static void
448 setup_peer (struct PeerContext *p, const char *cfgname)
449 {
450   p->cfg = GNUNET_CONFIGURATION_create ();
451   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
452   if (GNUNET_CONFIGURATION_have_value (p->cfg,"PATHS", "SERVICEHOME"))
453       GNUNET_CONFIGURATION_get_value_string (p->cfg, "PATHS", "SERVICEHOME", &p->servicehome);
454   GNUNET_DISK_directory_remove (p->servicehome);
455
456 #if START_ARM
457   p->arm_proc = GNUNET_OS_start_process (NULL, NULL,
458                                         "gnunet-service-arm",
459                                         "gnunet-service-arm",
460 #if VERBOSE_ARM
461                                         "-L", "DEBUG",
462 #endif
463                                         "-c", cfgname, NULL);
464 #endif
465
466   if (is_https)
467     {
468       struct stat sbuf;
469       if (p==&p1)
470         {
471           if (GNUNET_CONFIGURATION_have_value (p->cfg,
472                                                "transport-https", "KEY_FILE"))
473             GNUNET_CONFIGURATION_get_value_string (p->cfg, "transport-https", "KEY_FILE", &key_file_p1);
474           if (key_file_p1 == NULL)
475             GNUNET_asprintf(&key_file_p1,"https_p1.key");
476           if (0 == stat (key_file_p1, &sbuf ))
477             {
478               if (0 == remove(key_file_p1))
479                 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
480                             "Successfully removed existing private key file `%s'\n",
481                             key_file_p1);
482               else
483                 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
484                             "Failed to remove private key file `%s'\n",
485                             key_file_p1);
486             }
487           if (GNUNET_CONFIGURATION_have_value (p->cfg,"transport-https", "CERT_FILE"))
488             GNUNET_CONFIGURATION_get_value_string (p->cfg, "transport-https", "CERT_FILE", &cert_file_p1);
489           if (cert_file_p1 == NULL)
490             GNUNET_asprintf(&cert_file_p1,"https_p1.cert");
491           if (0 == stat (cert_file_p1, &sbuf ))
492             {
493               if (0 == remove(cert_file_p1))
494                 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
495                             "Successfully removed existing certificate file `%s'\n",
496                             cert_file_p1);
497               else
498                 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
499                             "Failed to remove existing certificate file `%s'\n",
500                             cert_file_p1);
501             }
502         }
503       else if (p==&p2)
504         {
505           if (GNUNET_CONFIGURATION_have_value (p->cfg,
506                                                "transport-https", "KEY_FILE"))
507             GNUNET_CONFIGURATION_get_value_string (p->cfg, "transport-https", "KEY_FILE", &key_file_p2);
508           if (key_file_p2 == NULL)
509             GNUNET_asprintf(&key_file_p2,"https_p2.key");
510           if (0 == stat (key_file_p2, &sbuf ))
511             {
512               if (0 == remove(key_file_p2))
513                 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
514                             "Successfully removed existing private key file `%s'\n",
515                             key_file_p2);
516               else
517                 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
518                             "Failed to remove private key file `%s'\n",
519                             key_file_p2);
520             }
521           if (GNUNET_CONFIGURATION_have_value (p->cfg,"transport-https", "CERT_FILE"))
522             GNUNET_CONFIGURATION_get_value_string (p->cfg, "transport-https", "CERT_FILE", &cert_file_p2);
523           if (cert_file_p2 == NULL)
524             GNUNET_asprintf(&cert_file_p2,"https_p2.cert");
525           if (0 == stat (cert_file_p2, &sbuf ))
526             {
527               if (0 == remove(cert_file_p2))
528                 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
529                             "Successfully removed existing certificate file `%s'\n",
530                             cert_file_p2);
531               else
532                 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
533                             "Failed to remove existing certificate file `%s'\n",
534                             cert_file_p2);
535             }
536         }
537     }
538   p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL,
539                                     p,
540                                     &notify_receive,
541                                     &notify_connect,
542                                     &notify_disconnect);
543   GNUNET_assert (p->th != NULL);
544 }
545
546
547 /**
548  * Return the actual path to a file found in the current
549  * PATH environment variable.
550  *
551  * @param binary the name of the file to find
552  */
553 static char *
554 get_path_from_PATH (char *binary)
555 {
556   char *path;
557   char *pos;
558   char *end;
559   char *buf;
560   const char *p;
561
562   p = getenv ("PATH");
563   if (p == NULL)
564     {
565       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
566                   _("PATH environment variable is unset.\n"));
567       return NULL;
568     }
569   path = GNUNET_strdup (p);     /* because we write on it */
570   buf = GNUNET_malloc (strlen (path) + 20);
571   pos = path;
572
573   while (NULL != (end = strchr (pos, PATH_SEPARATOR)))
574     {
575       *end = '\0';
576       sprintf (buf, "%s/%s", pos, binary);
577       if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
578         {
579           GNUNET_free (path);
580           return buf;
581         }
582       pos = end + 1;
583     }
584   sprintf (buf, "%s/%s", pos, binary);
585   if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
586     {
587       GNUNET_free (path);
588       return buf;
589     }
590   GNUNET_free (buf);
591   GNUNET_free (path);
592   return NULL;
593 }
594
595 /**
596  * Check whether the suid bit is set on a file.
597  * Attempts to find the file using the current
598  * PATH environment variable as a search path.
599  *
600  * @param binary the name of the file to check
601  *
602  * @return GNUNET_YES if the binary is found and
603  *         can be run properly, GNUNET_NO otherwise
604  */
605 static int
606 check_gnunet_nat_binary(char *binary)
607 {
608   struct stat statbuf;
609   char *p;
610 #ifdef MINGW
611   SOCKET rawsock;
612 #endif
613
614 #ifdef MINGW
615   char *binaryexe;
616   GNUNET_asprintf (&binaryexe, "%s.exe", binary);
617   p = get_path_from_PATH (binaryexe);
618   free (binaryexe);
619 #else
620   p = get_path_from_PATH (binary);
621 #endif
622   if (p == NULL)
623     {
624       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
625                   _("Could not find binary `%s' in PATH!\n"),
626                   binary);
627       return GNUNET_NO;
628     }
629   if (0 != STAT (p, &statbuf))
630     {
631       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
632                   _("stat (%s) failed: %s\n"),
633                   p,
634                   STRERROR (errno));
635       GNUNET_free (p);
636       return GNUNET_SYSERR;
637     }
638   GNUNET_free (p);
639 #ifndef MINGW
640   if ( (0 != (statbuf.st_mode & S_ISUID)) &&
641        (statbuf.st_uid == 0) )
642     return GNUNET_YES;
643   return GNUNET_NO;
644 #else
645   rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
646   if (INVALID_SOCKET == rawsock)
647     {
648       DWORD err = GetLastError ();
649       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
650                   "socket (AF_INET, SOCK_RAW, IPPROTO_ICMP) have failed! GLE = %d\n", err);
651       return GNUNET_NO; /* not running as administrator */
652     }
653   closesocket (rawsock);
654   return GNUNET_YES;
655 #endif
656 }
657
658
659 static void
660 try_connect (void *cls,
661              const struct GNUNET_SCHEDULER_TaskContext *tc)
662 {
663   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
664               "Asking peers to connect...\n");
665   GNUNET_TRANSPORT_try_connect (p2.th,
666                                 &p1.id);
667   GNUNET_TRANSPORT_try_connect (p1.th,
668                                 &p2.id);
669   tct = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
670                                       &try_connect,
671                                       NULL);
672 }
673
674
675 static void
676 run (void *cls,
677      char *const *args,
678      const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
679 {
680   GNUNET_assert (ok == 1);
681   OKPP;
682   die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
683                                            &end_badly,
684                                            NULL);
685   if (is_tcp)
686     {
687       setup_peer (&p1, "test_transport_api_tcp_peer1.conf");
688       setup_peer (&p2, "test_transport_api_tcp_peer2.conf");
689     }
690   else if (is_http)
691     {
692       setup_peer (&p1, "test_transport_api_rel_http_peer1.conf");
693       setup_peer (&p2, "test_transport_api_rel_http_peer2.conf");
694     }
695   else if (is_https)
696     {
697       setup_peer (&p1, "test_transport_api_rel_https_peer1.conf");
698       setup_peer (&p2, "test_transport_api_rel_https_peer2.conf");
699     }
700   else if (is_udp)
701     {
702       setup_peer (&p1, "test_transport_api_udp_peer1.conf");
703       setup_peer (&p2, "test_transport_api_udp_peer2.conf");
704     }
705   else if (is_unix)
706     {
707       setup_peer (&p1, "test_transport_api_unix_peer1.conf");
708       setup_peer (&p2, "test_transport_api_unix_peer2.conf");
709     }
710   else if (is_tcp_nat)
711     {
712       setup_peer (&p1, "test_transport_api_tcp_nat_peer1.conf");
713       setup_peer (&p2, "test_transport_api_tcp_nat_peer2.conf");
714     }
715   else if (is_wlan)
716     {
717       setup_peer (&p1, "test_transport_api_wlan_peer1.conf");
718       setup_peer (&p2, "test_transport_api_wlan_peer2.conf");
719     }
720   else
721     GNUNET_assert (0);
722   GNUNET_assert(p1.th != NULL);
723   GNUNET_assert(p2.th != NULL);
724   GNUNET_TRANSPORT_get_hello (p1.th, &exchange_hello, &p1);
725   GNUNET_TRANSPORT_get_hello (p2.th, &exchange_hello_last, &p2);
726   tct = GNUNET_SCHEDULER_add_now (&try_connect, NULL);
727 }
728
729
730 static int
731 check ()
732 {
733   char *const argv[] = { "test-transport-api-reliability",
734     "-c",
735     "test_transport_api_data.conf",
736 #if VERBOSE
737     "-L", "DEBUG",
738 #endif
739     NULL
740   };
741   struct GNUNET_GETOPT_CommandLineOption options[] = {
742     GNUNET_GETOPT_OPTION_END
743   };
744
745 #if WRITECONFIG
746   setTransportOptions("test_transport_api_data.conf");
747 #endif
748   ok = 1;
749
750   if ((GNUNET_YES == is_tcp_nat) && (check_gnunet_nat_binary("gnunet-nat-server") != GNUNET_YES))
751     {
752       GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
753                  "Not running NAT test case, binaries not properly installed.\n");
754       return 0;
755     }
756
757   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
758                       argv, "test-transport-api-reliability", "nohelp",
759                       options, &run, &ok);
760   stop_arm (&p1);
761   stop_arm (&p2);
762
763   if (is_https)
764   {
765     struct stat sbuf;
766     if (0 == stat (cert_file_p1, &sbuf ))
767     {
768       if (0 == remove(cert_file_p1))
769         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
770                     "Successfully removed existing certificate file `%s'\n",
771                     cert_file_p1);
772       else
773         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
774                     "Failed to remove certfile `%s'\n",
775                     cert_file_p1);
776     }
777
778     if (0 == stat (key_file_p1, &sbuf ))
779     {
780       if (0 == remove(key_file_p1))
781         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
782                     "Successfully removed private key file `%s'\n",
783                     key_file_p1);
784       else
785         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
786                     "Failed to private key file `%s'\n",key_file_p1);
787     }
788
789     if (0 == stat (cert_file_p2, &sbuf ))
790     {
791       if (0 == remove(cert_file_p2))
792         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
793                     "Successfully removed existing certificate file `%s'\n",
794                     cert_file_p2);
795       else
796         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
797                     "Failed to remove certfile `%s'\n",cert_file_p2);
798     }
799
800     if (0 == stat (key_file_p2, &sbuf ))
801     {
802       if (0 == remove(key_file_p2))
803         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
804                     "Successfully removed private key file `%s'\n",
805                     key_file_p2);
806       else
807         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
808                     "Failed to private key file `%s'\n",
809                     key_file_p2);
810     }
811     GNUNET_free(key_file_p1);
812     GNUNET_free(key_file_p2);
813     GNUNET_free(cert_file_p1);
814     GNUNET_free(cert_file_p2);
815     GNUNET_free(p1.servicehome);
816     GNUNET_free(p2.servicehome);
817   }
818
819   return ok;
820 }
821
822
823 int
824 main (int argc, char *argv[])
825 {
826   int ret;
827 #ifdef MINGW
828   return GNUNET_SYSERR;
829 #endif
830
831   if (strstr(argv[0], "tcp_nat") != NULL)
832     {
833       is_tcp_nat = GNUNET_YES;
834       GNUNET_asprintf(&test_name, "tcp_nat");
835     }
836   else if (strstr(argv[0], "tcp") != NULL)
837     {
838       is_tcp = GNUNET_YES;
839       GNUNET_asprintf(&test_name, "tcp");
840     }
841   else if (strstr(argv[0], "https") != NULL)
842     {
843       is_https = GNUNET_YES;
844       GNUNET_asprintf(&test_name, "https");
845     }
846   else if (strstr(argv[0], "http") != NULL)
847     {
848       is_http = GNUNET_YES;
849       GNUNET_asprintf(&test_name, "http");
850     }
851   else if (strstr(argv[0], "udp") != NULL)
852     {
853       is_udp = GNUNET_YES;
854       GNUNET_asprintf(&test_name, "udp");
855     }
856   else if (strstr(argv[0], "unix") != NULL)
857     {
858       is_unix = GNUNET_YES;
859       GNUNET_asprintf(&test_name, "unix");
860     }
861   else if (strstr(argv[0], "wlan") != NULL)
862     {
863        is_wlan = GNUNET_YES;
864     }
865   GNUNET_log_setup ("test-transport-api-reliability",
866 #if VERBOSE
867                     "DEBUG",
868 #else
869                     "WARNING",
870 #endif
871                     NULL);
872   ret = check ();
873   GNUNET_DISK_directory_remove (p1.servicehome);
874   GNUNET_DISK_directory_remove (p2.servicehome);
875   return ret;
876 }
877
878 /* end of test_transport_api_reliability.c */