indentation
[oweals/gnunet.git] / src / transport / test_transport_api_reliability.c
index 27b86b388607f86a30a14e6004fba84d605459aa..60191394d1e3902f8f8e0226510fb7bb721ef7ea 100644 (file)
@@ -4,7 +4,7 @@
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
@@ -34,7 +34,9 @@
 #include "gnunet_scheduler_lib.h"
 #include "gnunet_server_lib.h"
 #include "gnunet_transport_service.h"
 #include "gnunet_scheduler_lib.h"
 #include "gnunet_server_lib.h"
 #include "gnunet_transport_service.h"
+#include "gauger.h"
 #include "transport.h"
 #include "transport.h"
+#include "transport-testing.h"
 
 #define VERBOSE GNUNET_NO
 
 
 #define VERBOSE GNUNET_NO
 
 
 #define START_ARM GNUNET_YES
 
 
 #define START_ARM GNUNET_YES
 
-/**
- * Note that this value must not significantly exceed
- * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise
- * messages may be dropped even for a reliable transport.
- */
-#define TOTAL_MSGS (60000 * 2)
-
 /**
  * How long until we give up on transmitting the message?
  */
 /**
  * How long until we give up on transmitting the message?
  */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 150)
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500)
 
 
-#define MTYPE 12345
+static int ok;
 
 
-struct PeerContext
-{
-  struct GNUNET_CONFIGURATION_Handle *cfg;
-  struct GNUNET_TRANSPORT_Handle *th;
-  struct GNUNET_PeerIdentity id;
-#if START_ARM
-  pid_t arm_pid;
-#endif
-};
+static GNUNET_SCHEDULER_TaskIdentifier die_task;
 
 
-static struct PeerContext p1;
+struct PeerContext *p1;
 
 
-static struct PeerContext p2;
+struct PeerContext *p2;
 
 
-static struct GNUNET_SCHEDULER_Handle *sched;
+struct GNUNET_TRANSPORT_TransmitHandle *th;
 
 
-static int ok;
+char *cfg_file_p1;
 
 
-static int is_tcp;
+char *cfg_file_p2;
 
 
-static int is_tcp_nat;
+/*
+ * Testcase specific declarations
+ */
 
 
-static int is_http;
+/**
+ * Note that this value must not significantly exceed
+ * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise
+ * messages may be dropped even for a reliable transport.
+ */
+#define TOTAL_MSGS (1024 * 2)
 
 
-static int connected;
+#define MTYPE 12345
+
+struct TestMessage
+{
+  struct GNUNET_MessageHeader header;
+  uint32_t num;
+};
+
+static int msg_scheduled;
+static int msg_sent;
+static int msg_recv_expected;
+static int msg_recv;
+
+static int test_failed;
 
 static unsigned long long total_bytes;
 
 static struct GNUNET_TIME_Absolute start_time;
 
 
 static unsigned long long total_bytes;
 
 static struct GNUNET_TIME_Absolute start_time;
 
-static GNUNET_SCHEDULER_TaskIdentifier die_task;
+/*
+ * END Testcase specific declarations
+ */
 
 #if VERBOSE
 #define OKPP do { ok++; fprintf (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
 
 #if VERBOSE
 #define OKPP do { ok++; fprintf (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
@@ -100,53 +109,45 @@ end ()
 {
   unsigned long long delta;
 
 {
   unsigned long long delta;
 
-  GNUNET_SCHEDULER_cancel (sched, die_task);
-  die_task = GNUNET_SCHEDULER_NO_TASK;
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from transports!\n");
-#endif
-  GNUNET_TRANSPORT_disconnect (p1.th);
-  GNUNET_TRANSPORT_disconnect (p2.th);
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
-             "Transports disconnected, returning success!\n");
-#endif
-  delta = GNUNET_TIME_absolute_get_duration (start_time).value;
+  //char *value_name;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n");
+
+  delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value;
   fprintf (stderr,
   fprintf (stderr,
-          "\nThroughput was %llu kb/s\n",
-          total_bytes * 1000 / 1024 / delta);
-  ok = 0;
-}
+           "\nThroughput was %llu kb/s\n", total_bytes * 1000 / 1024 / delta);
+  //GNUNET_asprintf(&value_name, "reliable_%s", test_name);
+  //GAUGER ("TRANSPORT", value_name, (int)(total_bytes * 1000 / 1024 /delta), "kb/s");
+  //GNUNET_free(value_name);
 
 
+  if (die_task != GNUNET_SCHEDULER_NO_TASK)
+    GNUNET_SCHEDULER_cancel (die_task);
 
 
-static void
-stop_arm (struct PeerContext *p)
-{
-#if START_ARM
-  if (0 != PLIBC_KILL (p->arm_pid, SIGTERM))
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
-  GNUNET_OS_process_wait (p->arm_pid);
-#endif
-  GNUNET_CONFIGURATION_destroy (p->cfg);
-}
+  if (th != NULL)
+    GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
+  th = NULL;
 
 
+  GNUNET_TRANSPORT_TESTING_stop_peer (p1);
+  GNUNET_TRANSPORT_TESTING_stop_peer (p2);
+}
 
 static void
 
 static void
-end_badly (void *cls,
-          const struct GNUNET_SCHEDULER_TaskContext *tc)
+end_badly ()
 {
 {
-  GNUNET_break (0);
-  GNUNET_TRANSPORT_disconnect (p1.th);
-  GNUNET_TRANSPORT_disconnect (p2.th);
-  ok = 1;
-}
+  die_task = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n");
 
 
+  if (th != NULL)
+    GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
+  th = NULL;
 
 
-struct TestMessage 
-{
-  struct GNUNET_MessageHeader header;
-  uint32_t num;
-};
+  if (p1 != NULL)
+    GNUNET_TRANSPORT_TESTING_stop_peer (p1);
+  if (p2 != NULL)
+    GNUNET_TRANSPORT_TESTING_stop_peer (p2);
+
+  ok = GNUNET_SYSERR;
+}
 
 
 static unsigned int
 
 
 static unsigned int
@@ -154,8 +155,6 @@ get_size (unsigned int iter)
 {
   unsigned int ret;
 
 {
   unsigned int ret;
 
-  if (iter < 60000)
-    return iter + sizeof (struct TestMessage);
   ret = (iter * iter * iter);
   return sizeof (struct TestMessage) + (ret % 60000);
 }
   ret = (iter * iter * iter);
   return sizeof (struct TestMessage) + (ret % 60000);
 }
@@ -165,73 +164,76 @@ static void
 notify_receive (void *cls,
                 const struct GNUNET_PeerIdentity *peer,
                 const struct GNUNET_MessageHeader *message,
 notify_receive (void *cls,
                 const struct GNUNET_PeerIdentity *peer,
                 const struct GNUNET_MessageHeader *message,
-                struct GNUNET_TIME_Relative latency,
-               uint32_t distance)
+                const struct GNUNET_TRANSPORT_ATS_Information *ats,
+                uint32_t ats_count)
 {
   static int n;
   unsigned int s;
   char cbuf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
   const struct TestMessage *hdr;
 
 {
   static int n;
   unsigned int s;
   char cbuf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
   const struct TestMessage *hdr;
 
-  hdr = (const struct TestMessage*) message;
+  hdr = (const struct TestMessage *) message;
   s = get_size (n);
   if (MTYPE != ntohs (message->type))
     return;
   s = get_size (n);
   if (MTYPE != ntohs (message->type))
     return;
-  if (ntohs (message->size) != s)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "Expected message %u of size %u, got %u bytes of message %u\n",
-                 n, s,
-                 ntohs (message->size),
-                 ntohl (hdr->num));
-      GNUNET_SCHEDULER_cancel (sched, die_task);
-      die_task = GNUNET_SCHEDULER_add_now (sched, &end_badly, NULL);
-      return;
-    }
+  msg_recv_expected = n;
+  msg_recv = ntohl (hdr->num);
+  if (ntohs (message->size) != (s))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Expected message %u of size %u, got %u bytes of message %u\n",
+                n, s, ntohs (message->size), ntohl (hdr->num));
+    if (die_task != GNUNET_SCHEDULER_NO_TASK)
+      GNUNET_SCHEDULER_cancel (die_task);
+    test_failed = GNUNET_YES;
+    die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
+    return;
+  }
   if (ntohl (hdr->num) != n)
   if (ntohl (hdr->num) != n)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "Expected message %u of size %u, got %u bytes of message %u\n",
-                 n, s,
-                 ntohs (message->size),
-                 ntohl (hdr->num));
-      GNUNET_SCHEDULER_cancel (sched, die_task);
-      die_task = GNUNET_SCHEDULER_add_now (sched, &end_badly, NULL);
-      return;
-    }
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Expected message %u of size %u, got %u bytes of message %u\n",
+                n, s, ntohs (message->size), ntohl (hdr->num));
+    if (die_task != GNUNET_SCHEDULER_NO_TASK)
+      GNUNET_SCHEDULER_cancel (die_task);
+    test_failed = GNUNET_YES;
+    die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
+    return;
+  }
   memset (cbuf, n, s - sizeof (struct TestMessage));
   memset (cbuf, n, s - sizeof (struct TestMessage));
-  if (0 != memcmp (cbuf,
-                  &hdr[1],
-                  s - sizeof (struct TestMessage)))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "Expected message %u with bits %u, but body did not match\n",
-                 n, (unsigned char) n);
-      GNUNET_SCHEDULER_cancel (sched, die_task);
-      die_task = GNUNET_SCHEDULER_add_now (sched, &end_badly, NULL);
-      return;
-    }
+  if (0 != memcmp (cbuf, &hdr[1], s - sizeof (struct TestMessage)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Expected message %u with bits %u, but body did not match\n",
+                n, (unsigned char) n);
+    if (die_task != GNUNET_SCHEDULER_NO_TASK)
+      GNUNET_SCHEDULER_cancel (die_task);
+    test_failed = GNUNET_YES;
+    die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
+    return;
+  }
 #if VERBOSE
 #if VERBOSE
-  if (ntohl(hdr->num) % 5000 == 0)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Got message %u of size %u\n",
-                  ntohl (hdr->num),
-                  ntohs (message->size));
-    }
+  if (ntohl (hdr->num) % 5000 == 0)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Got message %u of size %u\n",
+                ntohl (hdr->num), ntohs (message->size));
+  }
 #endif
   n++;
 #endif
   n++;
-  if (0 == (n % (TOTAL_MSGS/100)))
-    {
-      fprintf (stderr, ".");
-      GNUNET_SCHEDULER_cancel (sched, die_task);
-      die_task = GNUNET_SCHEDULER_add_delayed (sched,
-                                              TIMEOUT,
-                                              &end_badly,
-                                              NULL);    
-    }
+  if (0 == (n % (TOTAL_MSGS / 100)))
+  {
+    fprintf (stderr, ".");
+    if (die_task != GNUNET_SCHEDULER_NO_TASK)
+      GNUNET_SCHEDULER_cancel (die_task);
+    die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
+  }
   if (n == TOTAL_MSGS)
   if (n == TOTAL_MSGS)
+  {
+    ok = 0;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All messages received\n");
     end ();
     end ();
+  }
 }
 
 
 }
 
 
@@ -245,53 +247,59 @@ notify_ready (void *cls, size_t size, void *buf)
   unsigned int ret;
 
   if (buf == NULL)
   unsigned int ret;
 
   if (buf == NULL)
-    {
-      GNUNET_break (0);
-      ok = 42;
-      return 0;
-    }
+  {
+    GNUNET_break (0);
+    ok = 42;
+    return 0;
+  }
+  th = NULL;
   ret = 0;
   s = get_size (n);
   GNUNET_assert (size >= s);
   GNUNET_assert (buf != NULL);
   cbuf = buf;
   do
   ret = 0;
   s = get_size (n);
   GNUNET_assert (size >= s);
   GNUNET_assert (buf != NULL);
   cbuf = buf;
   do
-    {
-      hdr.header.size = htons (s);
-      hdr.header.type = htons (MTYPE);
-      hdr.num = htonl (n);
-      memcpy (&cbuf[ret], &hdr, sizeof (struct TestMessage));
-      ret += sizeof (struct TestMessage);
-      memset (&cbuf[ret], n, s - sizeof (struct TestMessage));
-      ret += s - sizeof (struct TestMessage);
+  {
+    hdr.header.size = htons (s);
+    hdr.header.type = htons (MTYPE);
+    hdr.num = htonl (n);
+    msg_sent = n;
+    memcpy (&cbuf[ret], &hdr, sizeof (struct TestMessage));
+    ret += sizeof (struct TestMessage);
+    memset (&cbuf[ret], n, s - sizeof (struct TestMessage));
+    ret += s - sizeof (struct TestMessage);
 #if VERBOSE
 #if VERBOSE
-      if (n % 5000 == 0)
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                      "Sending message %u of size %u\n",
-                      n,
-                      s);
-        }
-#endif
-      n++;
-      s = get_size (n);
-      if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16))
-       break; /* sometimes pack buffer full, sometimes not */
+    if (n % 5000 == 0)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Sending message %u of size %u\n", n, s);
     }
     }
+#endif
+    n++;
+    s = get_size (n);
+    if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16))
+      break;                    /* sometimes pack buffer full, sometimes not */
+  }
   while (size - ret >= s);
   if (n < TOTAL_MSGS)
   while (size - ret >= s);
   if (n < TOTAL_MSGS)
-    GNUNET_TRANSPORT_notify_transmit_ready (p1.th,
-                                           &p2.id,
-                                           s, 0, TIMEOUT, 
-                                           &notify_ready,
-                                           NULL);
+  {
+    if (th == NULL)
+      th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th,
+                                                   &p1->id,
+                                                   s, 0, TIMEOUT,
+                                                   &notify_ready, NULL);
+    msg_scheduled = n;
+  }
   if (n % 5000 == 0)
   if (n % 5000 == 0)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Returning total message block of size %u\n",
-                  ret);
-    }
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Returning total message block of size %u\n", ret);
+  }
   total_bytes += ret;
   total_bytes += ret;
+  if (n == TOTAL_MSGS)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All messages sent\n");
+  }
   return ret;
 }
 
   return ret;
 }
 
@@ -299,171 +307,87 @@ notify_ready (void *cls, size_t size, void *buf)
 static void
 notify_connect (void *cls,
                 const struct GNUNET_PeerIdentity *peer,
 static void
 notify_connect (void *cls,
                 const struct GNUNET_PeerIdentity *peer,
-                struct GNUNET_TIME_Relative latency,
-               uint32_t distance)
+                const struct GNUNET_TRANSPORT_ATS_Information *ats,
+                uint32_t ats_count)
 {
 {
-  if (cls == &p1)
-    {
-      GNUNET_TRANSPORT_set_quota (p1.th,
-                                 &p2.id,
-                                 GNUNET_BANDWIDTH_value_init (1024 * 1024 * 1024),
-                                 GNUNET_BANDWIDTH_value_init (1024 * 1024 * 1024),
-                                 GNUNET_TIME_UNIT_FOREVER_REL,
-                                 NULL, NULL);
-      start_time = GNUNET_TIME_absolute_get ();
-      connected++;
-    }
-  else
-    {
-      GNUNET_TRANSPORT_set_quota (p2.th,
-                                 &p1.id,
-                                 GNUNET_BANDWIDTH_value_init (1024 * 1024 * 1024),
-                                 GNUNET_BANDWIDTH_value_init (1024 * 1024 * 1024),
-                                 GNUNET_TIME_UNIT_FOREVER_REL,
-                                 NULL, NULL);
-      connected++;
-    }
 
 
-  if (connected == 2)
-    {
-      GNUNET_TRANSPORT_notify_transmit_ready (p1.th,
-                                              &p2.id,
-                                              get_size (0), 0, TIMEOUT,
-                                              &notify_ready,
-                                              NULL);
-    }
-#if VERBOSE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Peer `%4s' connected to us (%p)!\n", GNUNET_i2s (peer), cls);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Peer `%4s' connected to us (%p)!\n", GNUNET_i2s (peer), cls);
-#endif
+
+  if (cls == p1)
+  {
+    GNUNET_TRANSPORT_set_quota (p1->th,
+                                &p2->id,
+                                GNUNET_BANDWIDTH_value_init (1024 * 1024 *
+                                                             1024),
+                                GNUNET_BANDWIDTH_value_init (1024 * 1024 *
+                                                             1024));
+  }
+  else if (cls == p2)
+  {
+    GNUNET_TRANSPORT_set_quota (p2->th,
+                                &p1->id,
+                                GNUNET_BANDWIDTH_value_init (1024 * 1024 *
+                                                             1024),
+                                GNUNET_BANDWIDTH_value_init (1024 * 1024 *
+                                                             1024));
+  }
 }
 
 
 static void
 notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
 {
 }
 
 
 static void
 notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
 {
-#if VERBOSE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Peer `%4s' disconnected (%p)!\n",
-             GNUNET_i2s (peer), cls);
-#endif
+              "Peer `%4s' disconnected (%p)!\n", GNUNET_i2s (peer), cls);
 }
 
 }
 
-
 static void
 static void
-setup_peer (struct PeerContext *p, const char *cfgname)
+sendtask ()
 {
 {
-  p->cfg = GNUNET_CONFIGURATION_create ();
-#if START_ARM
-  p->arm_pid = GNUNET_OS_start_process (NULL, NULL, 
-                                       "gnunet-service-arm",
-                                        "gnunet-service-arm",
-#if VERBOSE_ARM
-                                        "-L", "DEBUG",
-#endif
-                                        "-c", cfgname, NULL);
-#endif
-  GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
-  p->th = GNUNET_TRANSPORT_connect (sched, p->cfg,
-                                    p,
-                                    &notify_receive,
-                                    &notify_connect, 
-                                   &notify_disconnect);
-  GNUNET_assert (p->th != NULL);
+  start_time = GNUNET_TIME_absolute_get ();
+  th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th,
+                                               &p1->id,
+                                               get_size (0), 0, TIMEOUT,
+                                               &notify_ready, NULL);
 }
 
 }
 
-
 static void
 static void
-exchange_hello_last (void *cls,
-                     const struct GNUNET_MessageHeader *message)
+testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls)
 {
 {
-  struct PeerContext *me = cls;
-
-  GNUNET_TRANSPORT_get_hello_cancel (p2.th, &exchange_hello_last, me);
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Exchanging HELLO with peer (%p)!\n", cls);
-#endif
-  GNUNET_assert (ok >= 3);
-  OKPP;
-  GNUNET_assert (message != NULL);
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
-                                      message, &me->id));
-  /* both HELLOs exchanged, get ready to test transmission! */
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Finished exchanging HELLOs, now waiting for transmission!\n");
-}
-
+  char *p1_c = strdup (GNUNET_i2s (&p1->id));
 
 
-static void
-exchange_hello (void *cls,
-                const struct GNUNET_MessageHeader *message)
-{
-  struct PeerContext *me = cls;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %s <-> %s\n",
+              p1_c, GNUNET_i2s (&p2->id));
+  GNUNET_free (p1_c);
 
 
-  GNUNET_TRANSPORT_get_hello_cancel (p1.th, &exchange_hello, me);
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Exchanging HELLO with peer (%p)!\n", cls);
-#endif
-  GNUNET_assert (ok >= 2);
-  OKPP;
-  GNUNET_assert (message != NULL);
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
-                                      message, &me->id));
-
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received HELLO size %d\n", 
-             GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message));
-#endif
-  GNUNET_TRANSPORT_offer_hello (p2.th, message);
-  GNUNET_TRANSPORT_get_hello (p2.th, &exchange_hello_last, &p2);
+  // FIXME: THIS IS REQUIRED! SEEMS TO BE A BUG!
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &sendtask, NULL);
 }
 
 }
 
-
 static void
 run (void *cls,
 static void
 run (void *cls,
-     struct GNUNET_SCHEDULER_Handle *s,
      char *const *args,
      const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
      char *const *args,
      const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
-  GNUNET_assert (ok == 1);
-  OKPP;
-  sched = s;
-  die_task = GNUNET_SCHEDULER_add_delayed (sched,
-                                          TIMEOUT,
-                                          &end_badly,
-                                          NULL);
-  if (is_tcp)
-    {
-      setup_peer (&p1, "test_transport_api_tcp_peer1.conf");
-      setup_peer (&p2, "test_transport_api_tcp_peer2.conf");
-    }
-  else if (is_http)
-    {
-      setup_peer (&p1, "test_transport_api_http_peer1.conf");
-      setup_peer (&p2, "test_transport_api_http_peer2.conf");
-    }
-  else if (is_tcp_nat)
-    {
-      setup_peer (&p1, "test_transport_api_tcp_nat_peer1.conf");
-      setup_peer (&p2, "test_transport_api_tcp_nat_peer2.conf");
-    }
-  else
-    GNUNET_assert (0);
-  GNUNET_assert(p1.th != NULL);
-  GNUNET_assert(p2.th != NULL);
-  GNUNET_TRANSPORT_get_hello (p1.th, &exchange_hello, &p1);
+  die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
+
+  p1 = GNUNET_TRANSPORT_TESTING_start_peer (cfg_file_p1,
+                                            &notify_receive,
+                                            &notify_connect,
+                                            &notify_disconnect, NULL);
+  p2 = GNUNET_TRANSPORT_TESTING_start_peer (cfg_file_p2,
+                                            &notify_receive,
+                                            &notify_connect,
+                                            &notify_disconnect, NULL);
+
+  GNUNET_TRANSPORT_TESTING_connect_peers (p1, p2, &testing_connect_cb, NULL);
 }
 
 }
 
-
 static int
 check ()
 {
 static int
 check ()
 {
-  char *const argv[] = { "test-transport-api-reliability",
+  static char *const argv[] = { "test-transport-api",
     "-c",
     "test_transport_api_data.conf",
 #if VERBOSE
     "-c",
     "test_transport_api_data.conf",
 #if VERBOSE
@@ -471,53 +395,195 @@ check ()
 #endif
     NULL
   };
 #endif
     NULL
   };
-  struct GNUNET_GETOPT_CommandLineOption options[] = {
+  static struct GNUNET_GETOPT_CommandLineOption options[] = {
     GNUNET_GETOPT_OPTION_END
   };
 
 #if WRITECONFIG
     GNUNET_GETOPT_OPTION_END
   };
 
 #if WRITECONFIG
-  setTransportOptions("test_transport_api_data.conf");
+  setTransportOptions ("test_transport_api_data.conf");
 #endif
   ok = 1;
   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
 #endif
   ok = 1;
   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
-                      argv, "test-transport-api-reliability", "nohelp",
-                      options, &run, &ok);
-  stop_arm (&p1);
-  stop_arm (&p2);
+                      argv, "test-transport-api", "nohelp", options, &run, &ok);
+
   return ok;
 }
 
   return ok;
 }
 
+/**
+ * Return the actual path to a file found in the current
+ * PATH environment variable.
+ *
+ * @param binary the name of the file to find
+ */
+static char *
+get_path_from_PATH (char *binary)
+{
+  char *path;
+  char *pos;
+  char *end;
+  char *buf;
+  const char *p;
+
+  p = getenv ("PATH");
+  if (p == NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("PATH environment variable is unset.\n"));
+    return NULL;
+  }
+  path = GNUNET_strdup (p);     /* because we write on it */
+  buf = GNUNET_malloc (strlen (path) + 20);
+  pos = path;
+
+  while (NULL != (end = strchr (pos, PATH_SEPARATOR)))
+  {
+    *end = '\0';
+    sprintf (buf, "%s/%s", pos, binary);
+    if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
+    {
+      GNUNET_free (path);
+      return buf;
+    }
+    pos = end + 1;
+  }
+  sprintf (buf, "%s/%s", pos, binary);
+  if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
+  {
+    GNUNET_free (path);
+    return buf;
+  }
+  GNUNET_free (buf);
+  GNUNET_free (path);
+  return NULL;
+}
+
+/**
+ * Check whether the suid bit is set on a file.
+ * Attempts to find the file using the current
+ * PATH environment variable as a search path.
+ *
+ * @param binary the name of the file to check
+ *
+ * @return GNUNET_YES if the binary is found and
+ *         can be run properly, GNUNET_NO otherwise
+ */
+static int
+check_gnunet_nat_binary (char *binary)
+{
+  struct stat statbuf;
+  char *p;
+
+#ifdef MINGW
+  SOCKET rawsock;
+#endif
+
+#ifdef MINGW
+  char *binaryexe;
+
+  GNUNET_asprintf (&binaryexe, "%s.exe", binary);
+  p = get_path_from_PATH (binaryexe);
+  free (binaryexe);
+#else
+  p = get_path_from_PATH (binary);
+#endif
+  if (p == NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Could not find binary `%s' in PATH!\n"), binary);
+    return GNUNET_NO;
+  }
+  if (0 != STAT (p, &statbuf))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("stat (%s) failed: %s\n"), p, STRERROR (errno));
+    GNUNET_free (p);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (p);
+#ifndef MINGW
+  if ((0 != (statbuf.st_mode & S_ISUID)) && (statbuf.st_uid == 0))
+    return GNUNET_YES;
+  return GNUNET_NO;
+#else
+  rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
+  if (INVALID_SOCKET == rawsock)
+  {
+    DWORD err = GetLastError ();
+
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "socket (AF_INET, SOCK_RAW, IPPROTO_ICMP) have failed! GLE = %d\n",
+                err);
+    return GNUNET_NO;           /* not running as administrator */
+  }
+  closesocket (rawsock);
+  return GNUNET_YES;
+#endif
+}
 
 int
 main (int argc, char *argv[])
 {
   int ret;
 
 int
 main (int argc, char *argv[])
 {
   int ret;
-#ifdef MINGW
-  return GNUNET_SYSERR;
-#endif
-  if (strstr(argv[0], "tcp_nat") != NULL)
-    {
-      is_tcp_nat = GNUNET_YES;
-    }
-  else if (strstr(argv[0], "tcp") != NULL)
-    {
-      is_tcp = GNUNET_YES;
-    }
-  else if (strstr(argv[0], "http") != NULL)
-    {
-      is_http = GNUNET_YES;
-    }
-  GNUNET_log_setup ("test-transport-api-reliability",
+
+  GNUNET_log_setup ("test-transport-api",
 #if VERBOSE
                     "DEBUG",
 #else
                     "WARNING",
 #endif
                     NULL);
 #if VERBOSE
                     "DEBUG",
 #else
                     "WARNING",
 #endif
                     NULL);
+
+  char *pch = strdup (argv[0]);
+  char *backup = pch;
+  char *filename = NULL;
+  char *dotexe;
+
+  /* get executable filename */
+  pch = strtok (pch, "/");
+  while (pch != NULL)
+  {
+    pch = strtok (NULL, "/");
+    if (pch != NULL)
+      filename = pch;
+  }
+  /* remove "lt-" */
+  filename = strstr (filename, "tes");
+  if (NULL != (dotexe = strstr (filename, ".exe")))
+    dotexe[0] = '\0';
+
+  /* create cfg filename */
+  GNUNET_asprintf (&cfg_file_p1, "%s_peer1.conf", filename);
+  GNUNET_asprintf (&cfg_file_p2, "%s_peer2.conf", filename);
+  GNUNET_free (backup);
+
+  if (strstr (argv[0], "tcp_nat") != NULL)
+  {
+    if (GNUNET_YES != check_gnunet_nat_binary ("gnunet-nat-server"))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "`%s' not properly installed, cannot run NAT test!\n",
+                  "gnunet-nat-server");
+      return 0;
+    }
+  }
+  else if (strstr (argv[0], "udp_nat") != NULL)
+  {
+    if (GNUNET_YES != check_gnunet_nat_binary ("gnunet-nat-server"))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "`%s' not properly installed, cannot run NAT test!\n",
+                  "gnunet-nat-server");
+      return 0;
+    }
+  }
+
   ret = check ();
   ret = check ();
-  GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-transport-peer-1");
-  GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-transport-peer-2");
+
+  GNUNET_free (cfg_file_p1);
+  GNUNET_free (cfg_file_p2);
+
   return ret;
 }
 
   return ret;
 }
 
+
 /* end of test_transport_api_reliability.c */
 /* end of test_transport_api_reliability.c */