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