-makefile for new test_stream_local (commented)
[oweals/gnunet.git] / src / transport / gnunet-transport.c
index 1dc85a9039a6cd75b0eae4dac7a27529a8b50972..6ef273c45456a87cad06db055c7b42e40ca79d43 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
+     (C) 2011 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
 /**
  * How long do we wait for the NAT test to report success?
+ * Should match NAT_SERVER_TIMEOUT in 'nat_test.c'.
  */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
+#define RESOLUTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
 
 /**
  * Which peer should we connect to?
@@ -75,6 +77,16 @@ static int iterate_connections;
  */
 static int test_configuration;
 
+/**
+ * Option -m.
+ */
+static int monitor_connections;
+
+/**
+ * Option -n.
+ */
+static int numeric;
+
 /**
  * Global return value (0 success).
  */
@@ -111,6 +123,8 @@ static struct GNUNET_PeerIdentity pid;
  */
 static GNUNET_SCHEDULER_TaskIdentifier end;
 
+static struct GNUNET_CONTAINER_MultiHashMap *peers;
+
 /**
  * Selected level of verbosity.
  */
@@ -162,11 +176,11 @@ display_test_result (struct TestContext *tc, int result)
 {
   if (GNUNET_YES != result)
   {
-    fprintf (stderr, "Configuration for plugin `%s' did not work!\n", tc->name);
+    FPRINTF (stderr, "Configuration for plugin `%s' did not work!\n", tc->name);
   }
   else
   {
-    fprintf (stderr, "Configuration for plugin `%s' is working!\n", tc->name);
+    FPRINTF (stderr, "Configuration for plugin `%s' is working!\n", tc->name);
   }
   if (GNUNET_SCHEDULER_NO_TASK != tc->tsk)
   {
@@ -240,8 +254,9 @@ do_test_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg)
       GNUNET_CONFIGURATION_get_value_string (cfg, "transport", "plugins",
                                              &plugins))
   {
-    fprintf (stderr,
-             _
+    FPRINTF (stderr,
+             "%s",
+            _
              ("No transport plugins configured, peer will never communicate\n"));
     ret = 4;
     return;
@@ -254,7 +269,7 @@ do_test_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg)
     if (GNUNET_OK !=
         GNUNET_CONFIGURATION_get_value_number (cfg, section, "PORT", &bnd_port))
     {
-      fprintf (stderr,
+      FPRINTF (stderr,
                _("No port configured for plugin `%s', cannot test it\n"), tok);
       continue;
     }
@@ -264,7 +279,7 @@ do_test_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg)
       adv_port = bnd_port;
     if (NULL == resolver)
       resolver =
-          GNUNET_OS_start_process (NULL, NULL, "gnunet-service-resolver",
+         GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-resolver",
                                    "gnunet-service-resolver", NULL);
     resolver_users++;
     GNUNET_RESOLVER_connect (cfg);
@@ -305,14 +320,14 @@ do_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   if (benchmark_receive)
   {
     duration = GNUNET_TIME_absolute_get_duration (start_time);
-    fprintf (stdout, _("Received %llu bytes/s (%llu bytes in %llu ms)\n"),
+    FPRINTF (stdout, _("Received %llu bytes/s (%llu bytes in %llu ms)\n"),
              1000 * traffic_received / (1 + duration.rel_value),
              traffic_received, (unsigned long long) duration.rel_value);
   }
   if (benchmark_send)
   {
     duration = GNUNET_TIME_absolute_get_duration (start_time);
-    fprintf (stdout, _("Transmitted %llu bytes/s (%llu bytes in %llu ms)\n"),
+    FPRINTF (stdout, _("Transmitted %llu bytes/s (%llu bytes in %llu ms)\n"),
              1000 * traffic_sent / (1 + duration.rel_value), traffic_sent,
              (unsigned long long) duration.rel_value);
   }
@@ -345,7 +360,7 @@ transmit_data (void *cls, size_t size, void *buf)
                                                GNUNET_TIME_UNIT_FOREVER_REL,
                                                &transmit_data, NULL);
   if (verbosity > 0)
-    fprintf (stdout, _("Transmitting %u bytes to %s\n"), (unsigned int) size,
+    FPRINTF (stdout, _("Transmitting %u bytes to %s\n"), (unsigned int) size,
              GNUNET_i2s (&pid));
   return size;
 }
@@ -365,7 +380,7 @@ notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
                 const struct GNUNET_ATS_Information *ats, uint32_t ats_count)
 {
   if (verbosity > 0)
-    fprintf (stdout, _("Connected to %s\n"), GNUNET_i2s (peer));
+    FPRINTF (stdout, _("Connected to %s\n"), GNUNET_i2s (peer));
   if (0 != memcmp (&pid, peer, sizeof (struct GNUNET_PeerIdentity)))
     return;
   ret = 0;
@@ -396,7 +411,7 @@ static void
 notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
 {
   if (verbosity > 0)
-    fprintf (stdout, _("Disconnected from %s\n"), GNUNET_i2s (peer));
+    FPRINTF (stdout, _("Disconnected from %s\n"), GNUNET_i2s (peer));
   if ((0 == memcmp (&pid, peer, sizeof (struct GNUNET_PeerIdentity))) &&
       (NULL != th))
   {
@@ -425,46 +440,104 @@ notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
   if (!benchmark_receive)
     return;
   if (verbosity > 0)
-    fprintf (stdout, _("Received %u bytes from %s\n"),
+    FPRINTF (stdout, _("Received %u bytes from %s\n"),
              (unsigned int) ntohs (message->size), GNUNET_i2s (peer));
   if (traffic_received == 0)
     start_time = GNUNET_TIME_absolute_get ();
   traffic_received += ntohs (message->size);
 }
 
+struct ResolutionContext
+{
+  struct GNUNET_HELLO_Address *addrcp;
+
+  int printed;
+};
+
+void
+process_string (void *cls, const char *address)
+{
+  struct ResolutionContext *rc = cls;
+  struct GNUNET_HELLO_Address *addrcp = rc->addrcp;
+
+  if (address != NULL)
+  {
+    FPRINTF (stdout, _("Peer `%s': %s %s\n"), GNUNET_i2s (&addrcp->peer), addrcp->transport_name, address);
+    rc->printed = GNUNET_YES;
+  }
+  else
+  {
+    /* done */
+    if (GNUNET_NO == rc->printed)
+      FPRINTF (stdout, _("Peer `%s': %s <unable to resolve address>\n"), GNUNET_i2s (&addrcp->peer), addrcp->transport_name);
+    GNUNET_free (rc->addrcp);
+    GNUNET_free (rc);
+  }
+}
 
 /**
- * Function to call with a human-readable format of an address
+ * Function to call with a binary address
  *
  * @param cls closure
  * @param peer identity of the peer
- * @param transport name of the plugin
- * @param addr binary address
- * @param addrlen number of bytes in addr
+ * @param address binary address (NULL on disconnect)
+ */
+static void
+process_address (void *cls, const struct GNUNET_PeerIdentity *peer,
+                 const struct GNUNET_HELLO_Address *address)
+{
+  const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+  struct ResolutionContext *rc;
+
+  if (peer == NULL)
+  {
+    /* done */
+    return;
+  }
+
+  if (address == NULL)
+  {
+    FPRINTF (stdout, _("Peer `%s' disconnected\n"), GNUNET_i2s (peer));
+    return;
+  }
+
+  rc = GNUNET_malloc(sizeof (struct ResolutionContext));
+  rc->addrcp = GNUNET_HELLO_address_copy(address);
+  rc->printed = GNUNET_NO;
+
+  GNUNET_assert (NULL != rc);
+
+  /* Resolve address to string */
+  GNUNET_TRANSPORT_address_to_string (cfg, address, numeric,
+                                      RESOLUTION_TIMEOUT, &process_string,
+                                      rc);
+}
+
+
+/**
+ * Task run in monitor mode when the user presses CTRL-C to abort.
+ * Stops monitoring activity.
+ * 
+ * @param cls the 'struct GNUNET_TRANSPORT_PeerIterateContext *'
+ * @param tc scheduler context
  */
 static void
-process_address (void *cls, const struct GNUNET_HELLO_Address *address)
+shutdown_task (void *cls,
+              const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  if ((address->transport_name != NULL) ||
-      ((address->address != NULL) && (address->address_length > 0)))
+  struct GNUNET_TRANSPORT_PeerIterateContext *pic = cls;
+
+  GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pic);
+
+  if (NULL != peers)
   {
-    /* Call GNUNET_TRANSPORT_address_to_string to convert to human readable */
-    //GNUNET_TRANSPORT_address_to_string(cfg, address, GNUNET_NO)
-
-#if 0
-    fprintf (stdout, _("Peer `%s' plugin: `%s' address `%s'\n"),
-             (peer != NULL) ? GNUNET_i2s (peer) : "<unknown>",
-             (transport != NULL) ? transport : "<unknown>", ((addr != NULL) &&
-                                                             (addrlen > 0) &&
-                                                             (transport !=
-                                                              NULL)) ?
-             "how do i resolve the name without transport service?" :
-             "<unknown>");
-#endif
+    GNUNET_CONTAINER_multihashmap_destroy (peers);
+    peers = NULL;
   }
 }
 
 
+
 /**
  * Main function that will be run by the scheduler.
  *
@@ -483,7 +556,7 @@ run (void *cls, char *const *args, const char *cfgfile,
   }
   if (benchmark_send && (NULL == cpid))
   {
-    fprintf (stderr, _("Option `%s' makes no sense without option `%s'.\n"),
+    FPRINTF (stderr, _("Option `%s' makes no sense without option `%s'.\n"),
              "-s", "-C");
     return;
   }
@@ -492,7 +565,7 @@ run (void *cls, char *const *args, const char *cfgfile,
     ret = 1;
     if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (cpid, &pid.hashPubKey))
     {
-      fprintf (stderr, _("Failed to parse peer identity `%s'\n"), cpid);
+      FPRINTF (stderr, _("Failed to parse peer identity `%s'\n"), cpid);
       return;
     }
     handle =
@@ -517,8 +590,21 @@ run (void *cls, char *const *args, const char *cfgfile,
   }
   if (iterate_connections)
   {
-    GNUNET_TRANSPORT_address_iterate (cfg, GNUNET_TIME_UNIT_MINUTES,
-                                      &process_address, NULL);
+    peers = GNUNET_CONTAINER_multihashmap_create (20);
+    GNUNET_TRANSPORT_peer_get_active_addresses (cfg, NULL, GNUNET_YES,
+                                                TIMEOUT,
+                                                &process_address, (void *) cfg);
+  }
+  if (monitor_connections)
+  {
+    struct GNUNET_TRANSPORT_PeerIterateContext *pic;
+
+    pic = GNUNET_TRANSPORT_peer_get_active_addresses (cfg, NULL, GNUNET_NO,
+                                                     GNUNET_TIME_UNIT_FOREVER_REL,
+                                                     &process_address, (void *) cfg);
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+                                 &shutdown_task,
+                                 pic);
   }
 }
 
@@ -536,6 +622,12 @@ main (int argc, char *const *argv)
     {'i', "information", NULL,
      gettext_noop ("provide information about all current connections (once)"),
      0, &GNUNET_GETOPT_set_one, &iterate_connections},
+    {'m', "monitor", NULL,
+     gettext_noop ("provide information about all current connections (continuously)"),
+     0, &GNUNET_GETOPT_set_one, &monitor_connections},
+    {'n', "numeric", NULL,
+     gettext_noop ("do not resolve hostnames"),
+     0, &GNUNET_GETOPT_set_one, &numeric},
     {'s', "send", NULL,
      gettext_noop
      ("send data for benchmarking to the other peer (until CTRL-C)"),