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