log
[oweals/gnunet.git] / src / transport / gnunet-transport.c
index b3af97c209f8e8d5d3f222b4473ae6d171ce7680..fb8ec60ebff18470e9995815cf176c19fe643954 100644 (file)
@@ -123,6 +123,11 @@ static int monitor_validation;
  */
 static int try_connect;
 
+/**
+ * Option -D.
+ */
+static int try_disconnect;
+
 /**
  * Option -n.
  */
@@ -258,6 +263,27 @@ struct TestContext
 
 };
 
+static struct ValidationResolutionContext *vc_head;
+static struct ValidationResolutionContext *vc_tail;
+
+struct ValidationResolutionContext
+{
+  struct ValidationResolutionContext *next;
+  struct ValidationResolutionContext *prev;
+
+  struct GNUNET_PeerIdentity id;
+  struct GNUNET_HELLO_Address *addrcp;
+  struct GNUNET_TIME_Absolute last_validation;
+  struct GNUNET_TIME_Absolute valid_until;
+  struct GNUNET_TIME_Absolute next_validation;
+  enum GNUNET_TRANSPORT_ValidationState state;
+
+  struct GNUNET_TRANSPORT_AddressToStringContext *asc;
+
+  char *transport;
+  int printed;
+};
+
 struct MonitoredPeer
 {
   enum GNUNET_TRANSPORT_PeerState state;
@@ -288,6 +314,8 @@ static void
 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct GNUNET_TIME_Relative duration;
+  struct ValidationResolutionContext *cur;
+  struct ValidationResolutionContext *next;
   end = GNUNET_SCHEDULER_NO_TASK;
   if (GNUNET_SCHEDULER_NO_TASK != op_timeout)
   {
@@ -309,6 +337,19 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     GNUNET_TRANSPORT_monitor_validation_entries_cancel (vic);
     vic = NULL;
   }
+
+  next = vc_head;
+  for (cur = next; NULL != cur; cur = next)
+  {
+    next = cur->next;
+
+    GNUNET_TRANSPORT_address_to_string_cancel (cur->asc);
+    GNUNET_CONTAINER_DLL_remove (vc_head, vc_tail, cur);
+    GNUNET_free (cur->transport);
+    GNUNET_HELLO_address_free (cur->addrcp);
+    GNUNET_free (cur);
+  }
+
   if (NULL != th)
   {
     GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
@@ -360,26 +401,7 @@ struct PeerResolutionContext
   int printed;
 };
 
-static struct ValidationResolutionContext *vc_head;
-static struct ValidationResolutionContext *vc_tail;
-
-struct ValidationResolutionContext
-{
-  struct ValidationResolutionContext *next;
-  struct ValidationResolutionContext *prev;
-
-  struct GNUNET_PeerIdentity id;
-  struct GNUNET_HELLO_Address *addrcp;
-  struct GNUNET_TIME_Absolute last_validation;
-  struct GNUNET_TIME_Absolute valid_until;
-  struct GNUNET_TIME_Absolute next_validation;
-  enum GNUNET_TRANSPORT_ValidationState state;
-
-  struct GNUNET_TRANSPORT_AddressToStringContext *asc;
 
-  char *transport;
-  int printed;
-};
 
 static void
 operation_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
@@ -836,6 +858,25 @@ notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
   if (0 != memcmp (&pid, peer, sizeof(struct GNUNET_PeerIdentity)))
     return;
 
+  if (try_disconnect)
+  {
+    /* all done, terminate instantly */
+    FPRINTF (stdout, _("Successfully disconnected from `%s'\n"),
+        GNUNET_i2s_full (peer));
+    ret = 0;
+
+    if (GNUNET_SCHEDULER_NO_TASK != op_timeout)
+    {
+      GNUNET_SCHEDULER_cancel (op_timeout);
+      op_timeout = GNUNET_SCHEDULER_NO_TASK;
+    }
+
+    if (GNUNET_SCHEDULER_NO_TASK != end)
+      GNUNET_SCHEDULER_cancel (end);
+    end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL );
+    return;
+  }
+
   if (NULL != th)
   {
     GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
@@ -926,7 +967,9 @@ print_info (const struct GNUNET_PeerIdentity *id, const char *transport,
     const char *addr, enum GNUNET_TRANSPORT_PeerState state,
     struct GNUNET_TIME_Absolute state_timeout)
 {
-  if ((GNUNET_YES == iterate_all) || (GNUNET_YES == monitor_connections) )
+
+  if ( ((GNUNET_YES == iterate_connections) && (GNUNET_YES == iterate_all)) ||
+       (GNUNET_YES == monitor_connections) )
   {
     FPRINTF (stdout, _("Peer `%s': %s %s in state `%s' until %s\n"),
         GNUNET_i2s (id),
@@ -935,12 +978,12 @@ print_info (const struct GNUNET_PeerIdentity *id, const char *transport,
         GNUNET_TRANSPORT_ps2s (state),
         GNUNET_STRINGS_absolute_time_to_string (state_timeout));
   }
-  else
+  else if ( (GNUNET_YES == iterate_connections) &&
+             (GNUNET_TRANSPORT_is_connected(state)) )
   {
     /* Only connected peers, skip state */
     FPRINTF (stdout, _("Peer `%s': %s %s\n"), GNUNET_i2s (id), transport, addr);
   }
-
 }
 
 static void
@@ -1113,12 +1156,11 @@ process_peer_monitoring_cb (void *cls, const struct GNUNET_PeerIdentity *peer,
     {
       return; /* No real change */
     }
-    if ( ((NULL != address) && (NULL != m->address)) &&
+    if ( (m->state == state) && ((NULL != address) && (NULL != m->address)) &&
         (0 == GNUNET_HELLO_address_cmp(m->address, address)) )
       return; /* No real change */
   }
 
-
   if (NULL != m->address)
   {
     GNUNET_free (m->address);
@@ -1160,6 +1202,31 @@ try_connect_cb (void *cls, const int result)
   }
 }
 
+static void
+try_disconnect_cb (void *cls, const int result)
+{
+  static int retries = 0;
+  if (GNUNET_OK == result)
+  {
+    tc_handle = NULL;
+    return;
+  }
+  retries++;
+  if (retries < 10)
+    tc_handle = GNUNET_TRANSPORT_try_disconnect (handle, &pid, try_disconnect_cb,
+        NULL );
+  else
+  {
+    FPRINTF (stderr, "%s",
+        _("Failed to send connect request to transport service\n") );
+    if (GNUNET_SCHEDULER_NO_TASK != end)
+      GNUNET_SCHEDULER_cancel (end);
+    ret = 1;
+    end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL );
+    return;
+  }
+}
+
 /**
  * Function called with the result of the check if the 'transport'
  * service is running.
@@ -1189,7 +1256,7 @@ testservice_task (void *cls, int result)
   }
 
   counter = benchmark_send + benchmark_receive + iterate_connections
-      + monitor_connections + monitor_connects + try_connect
+      + monitor_connections + monitor_connects + try_connect + try_disconnect +
       + iterate_validation + monitor_validation;
 
   if (1 < counter)
@@ -1238,6 +1305,36 @@ testservice_task (void *cls, int result)
     op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout,
         NULL );
 
+  }
+  else if (try_disconnect) /* -D: Disconnect from peer */
+  {
+    if (NULL == cpid)
+    {
+      FPRINTF (stderr, _("Option `%s' makes no sense without option `%s'.\n"),
+          "-D", "-p");
+      ret = 1;
+      return;
+    }
+    handle = GNUNET_TRANSPORT_connect (cfg, NULL, NULL, &notify_receive,
+        &notify_connect, &notify_disconnect);
+    if (NULL == handle)
+    {
+      FPRINTF (stderr, "%s", _("Failed to connect to transport service\n") );
+      ret = 1;
+      return;
+    }
+    tc_handle = GNUNET_TRANSPORT_try_disconnect (handle, &pid, try_disconnect_cb,
+        NULL );
+    if (NULL == tc_handle)
+    {
+      FPRINTF (stderr, "%s",
+          _("Failed to send request to transport service\n") );
+      ret = 1;
+      return;
+    }
+    op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout,
+        NULL );
+
   }
   else if (benchmark_send) /* -s: Benchmark sending */
   {
@@ -1329,7 +1426,7 @@ testservice_task (void *cls, int result)
     GNUNET_break(0);
     return;
   }
-
+  GNUNET_break (0);
   end = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
       &shutdown_task, NULL );
 
@@ -1368,9 +1465,13 @@ main (int argc, char * const *argv)
               0, &GNUNET_GETOPT_set_one, &iterate_all },
           { 'b', "benchmark", NULL,
               gettext_noop ("measure how fast we are receiving data from all peers (until CTRL-C)"),
-              0, &GNUNET_GETOPT_set_one, &benchmark_receive }, { 'C', "connect",
+              0, &GNUNET_GETOPT_set_one, &benchmark_receive },
+          { 'C', "connect",
               NULL, gettext_noop ("connect to a peer"), 0,
               &GNUNET_GETOPT_set_one, &try_connect },
+          { 'D', "disconnect",
+              NULL, gettext_noop ("disconnect to a peer"), 0,
+              &GNUNET_GETOPT_set_one, &try_disconnect },
           { 'd', "validation", NULL,
               gettext_noop ("print information for all pending validations "),
               0, &GNUNET_GETOPT_set_one, &iterate_validation },