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