transport validation monitoring API (not yet complete) + CLI
authorMatthias Wachs <wachs@net.in.tum.de>
Wed, 15 Jan 2014 17:18:11 +0000 (17:18 +0000)
committerMatthias Wachs <wachs@net.in.tum.de>
Wed, 15 Jan 2014 17:18:11 +0000 (17:18 +0000)
+ fix for crash in transport/plugin_transport_udp.c

14 files changed:
src/transport/Makefile.am
src/transport/gnunet-service-transport.c
src/transport/gnunet-service-transport_clients.c
src/transport/gnunet-service-transport_clients.h
src/transport/gnunet-service-transport_neighbours.c
src/transport/gnunet-service-transport_validation.c
src/transport/gnunet-service-transport_validation.h
src/transport/gnunet-transport.c
src/transport/plugin_transport_udp.c
src/transport/test_transport_api_monitoring.c
src/transport/test_transport_api_monitoring_validation_peer1.conf [new file with mode: 0644]
src/transport/test_transport_api_monitoring_validation_peer2.conf [new file with mode: 0644]
src/transport/transport.h
src/transport/transport_api_monitoring.c

index 76dc50af925238dcd339a2deed5275fafd1bae38..acfaa940355df1dbac4da00acaf0232b9f1a4edd 100644 (file)
@@ -408,6 +408,7 @@ check_PROGRAMS = \
  $(BT_TIMEOUT_TEST) \
  test_transport_api_multi \
  test_transport_api_monitoring \
+ test_transport_api_monitoring_validation \
  test_transport_blacklisting_no_bl \
  test_transport_blacklisting_outbound_bl_full \
  test_transport_blacklisting_outbound_bl_plugin \
@@ -473,6 +474,7 @@ TESTS = \
  $(BT_TIMEOUT_TEST) \
  test_transport_api_multi \
  test_transport_api_monitoring \
+ test_transport_api_monitoring_validation \
  test_transport_blacklisting_no_bl \
  test_transport_blacklisting_outbound_bl_full \
  test_transport_blacklisting_outbound_bl_plugin \
@@ -1100,7 +1102,6 @@ test_transport_api_multi_LDADD = \
  $(top_builddir)/src/util/libgnunetutil.la \
  $(top_builddir)/src/transport/libgnunettransporttesting.la
 
-
 test_transport_api_monitoring_SOURCES = \
  test_transport_api_monitoring.c
 test_transport_api_monitoring_LDADD = \
@@ -1109,6 +1110,14 @@ test_transport_api_monitoring_LDADD = \
  $(top_builddir)/src/util/libgnunetutil.la \
  $(top_builddir)/src/transport/libgnunettransporttesting.la
 
+test_transport_api_monitoring_validation_SOURCES = \
+ test_transport_api_monitoring_validation.c
+test_transport_api_monitoring_validation_LDADD = \
+ $(top_builddir)/src/transport/libgnunettransport.la \
+ $(top_builddir)/src/hello/libgnunethello.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/transport/libgnunettransporttesting.la
+
 
 EXTRA_DIST = \
 test_plugin_hostkey \
@@ -1207,6 +1216,8 @@ test_transport_api_bluetooth_peer1.conf\
 test_transport_api_bluetooth_peer2.conf\
 test_transport_api_monitoring_peer1.conf\
 test_transport_api_monitoring_peer2.conf\
+test_transport_api_monitoring_validation_peer1.conf\
+test_transport_api_monitoring_validation_peer2.conf\
 test_transport_defaults.conf\
 test_transport_startonly.conf\
 test_transport_api_disconnect_tcp_peer1.conf\
index d52d6ab699db612a27fb7966d49ecaa79620d8f2..66f1771454591c757357fe249fbc052e2608c735 100644 (file)
@@ -764,12 +764,42 @@ neighbours_changed_notification (void *cls,
       "Notifying about change for peer `%s' with address `%s' in state `%s' timing out at %s\n",
       GNUNET_i2s (peer),
       (NULL != address) ? GST_plugins_a2s (address) : "<none>",
-      GNUNET_TRANSPORT_p2s (state),
+      GNUNET_TRANSPORT_ps2s (state),
       GNUNET_STRINGS_absolute_time_to_string (state_timeout));
 
   GST_clients_broadcast_peer_notification (peer, address, state, state_timeout);
 }
 
+/**
+ * Function called to notify transport users that a neighbour peer changed its
+ * active address.
+ *
+ * @param cls closure
+ * @param peer peer this update is about (never NULL)
+ * @param address address, NULL on disconnect
+ * @param state current state this peer is in
+ * @param state_timeout timeout for the current state of the peer
+ * @param bandwidth_in bandwidth assigned inbound
+ * @param bandwidth_out bandwidth assigned outbound
+ */
+static void
+validation_changed_notification (void *cls,
+    const struct GNUNET_PeerIdentity *peer,
+    const struct GNUNET_HELLO_Address *address,
+    struct GNUNET_TIME_Absolute last_validation,
+    struct GNUNET_TIME_Absolute valid_until,
+    struct GNUNET_TIME_Absolute next_validation,
+    enum GNUNET_TRANSPORT_ValidationState state)
+{
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+      "Notifying about change for for validation entry for peer `%s' with address `%s'\n",
+      GNUNET_i2s (peer),
+      (NULL != address) ? GST_plugins_a2s (address) : "<none>");
+
+  GST_clients_broadcast_validation_notification (peer, address,
+      last_validation, valid_until, next_validation, state);
+}
+
 /**
  * Function called when the service shuts down.  Unloads our plugins
  * and cancels pending validations.
@@ -918,7 +948,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
       &neighbours_disconnect_notification, &neighbours_changed_notification,
       (max_fd / 3) * 2);
   GST_clients_start (GST_server);
-  GST_validation_start ((max_fd / 3));
+  GST_validation_start (&validation_changed_notification, NULL, (max_fd / 3));
 }
 
 /**
index ca7a40539686b067ce3248d98725100cc2eedb58..fb848d0afdc37087f18bca9978f31b740749d8c5 100644 (file)
@@ -190,19 +190,34 @@ struct AddressToStringContext *a2s_tail;
 /**
  * Head of linked list of monitoring clients.
  */
-static struct MonitoringClient *monitoring_clients_head;
+static struct MonitoringClient *peer_monitoring_clients_head;
 
 /**
  * Tail of linked list of monitoring clients.
  */
-static struct MonitoringClient *monitoring_clients_tail;
+static struct MonitoringClient *peer_monitoring_clients_tail;
+
+/**
+ * Head of linked list of validation monitoring clients.
+ */
+static struct MonitoringClient *val_monitoring_clients_head;
+
+/**
+ * Tail of linked list of validation monitoring clients.
+ */
+static struct MonitoringClient *val_monitoring_clients_tail;
 
 /**
  * Notification context, to send updates on changes to active addresses
  * of our neighbours.
  */
-static struct GNUNET_SERVER_NotificationContext *nc;
+static struct GNUNET_SERVER_NotificationContext *peer_nc;
 
+/**
+ * Notification context, to send updates on changes to active addresses
+ * of our neighbours.
+ */
+static struct GNUNET_SERVER_NotificationContext *val_nc;
 
 /**
  * Find the internal handle associated with the given client handle
@@ -251,11 +266,12 @@ setup_client (struct GNUNET_SERVER_Client *client)
  * @return handle to the monitoring client
  */
 static struct MonitoringClient *
-lookup_monitoring_client (struct GNUNET_SERVER_Client *client)
+lookup_monitoring_client (struct MonitoringClient *head,
+    struct GNUNET_SERVER_Client *client)
 {
   struct MonitoringClient *mc;
 
-  for (mc = monitoring_clients_head; NULL != mc; mc = mc->next)
+  for (mc = head; NULL != mc; mc = mc->next)
     if (mc->client == client)
       return mc;
   return NULL;
@@ -272,27 +288,58 @@ lookup_monitoring_client (struct GNUNET_SERVER_Client *client)
  * @return handle to the new monitoring client
  */
 static struct MonitoringClient *
-setup_monitoring_client (struct GNUNET_SERVER_Client *client,
+setup_peer_monitoring_client (struct GNUNET_SERVER_Client *client,
                          struct GNUNET_PeerIdentity *peer)
 {
   struct MonitoringClient *mc;
   static struct GNUNET_PeerIdentity all_zeros;
 
-  GNUNET_assert (lookup_monitoring_client (client) == NULL);
+  GNUNET_assert (lookup_monitoring_client (peer_monitoring_clients_head, client) == NULL);
   mc = GNUNET_new (struct MonitoringClient);
   mc->client = client;
   mc->peer = *peer;
-  GNUNET_CONTAINER_DLL_insert (monitoring_clients_head,
-                               monitoring_clients_tail,
-                               mc);
-  GNUNET_SERVER_notification_context_add (nc, client);
+  GNUNET_CONTAINER_DLL_insert (peer_monitoring_clients_head, peer_monitoring_clients_tail, mc);
+  GNUNET_SERVER_notification_context_add (peer_nc, client);
 
   if (0 != memcmp (peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity)))
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Client %p started monitoring of the peer `%s'\n",
                 mc, GNUNET_i2s (peer));
   else
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Client %p started monitoring all peers\n", mc);
+  return mc;
+}
+
+/**
+ * Setup a new monitoring client using the given server client handle and
+ * the peer identity.
+ *
+ * @param client server's client handle to create our internal handle for
+ * @param peer identity of the peer to monitor the addresses of,
+ *             zero to monitor all neighrours.
+ * @return handle to the new monitoring client
+ */
+static struct MonitoringClient *
+setup_val_monitoring_client (struct GNUNET_SERVER_Client *client,
+                         struct GNUNET_PeerIdentity *peer)
+{
+  struct MonitoringClient *mc;
+  static struct GNUNET_PeerIdentity all_zeros;
+
+  GNUNET_assert (lookup_monitoring_client (val_monitoring_clients_head, client) == NULL);
+  mc = GNUNET_new (struct MonitoringClient);
+  mc->client = client;
+  mc->peer = *peer;
+  GNUNET_CONTAINER_DLL_insert (val_monitoring_clients_head, val_monitoring_clients_tail, mc);
+  GNUNET_SERVER_notification_context_add (val_nc, client);
+
+  if (0 != memcmp (peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity)))
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Client %p started monitoring of the peer `%s'\n",
+                mc, GNUNET_i2s (peer));
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Client %p started monitoring all peers\n", mc);
   return mc;
 }
@@ -425,11 +472,19 @@ client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
 
   if (client == NULL)
     return;
-  mc = lookup_monitoring_client (client);
+  mc = lookup_monitoring_client (peer_monitoring_clients_head, client);
   if (mc != NULL)
   {
-    GNUNET_CONTAINER_DLL_remove (monitoring_clients_head,
-                                 monitoring_clients_tail,
+    GNUNET_CONTAINER_DLL_remove (peer_monitoring_clients_head,
+                                 peer_monitoring_clients_tail,
+                                 mc);
+    GNUNET_free (mc);
+  }
+  mc = lookup_monitoring_client (val_monitoring_clients_head, client);
+  if (mc != NULL)
+  {
+    GNUNET_CONTAINER_DLL_remove (val_monitoring_clients_head,
+                                 val_monitoring_clients_tail,
                                  mc);
     GNUNET_free (mc);
   }
@@ -852,7 +907,7 @@ clients_handle_address_to_string (void *cls,
 
 
 /**
- * Compose AddressIterateResponseMessage using the given peer and address.
+ * Compose #PeerIterateResponseMessage using the given peer and address.
  *
  * @param peer identity of the peer
  * @param address the address, NULL on disconnect
@@ -896,8 +951,52 @@ compose_address_iterate_response_message (const struct GNUNET_PeerIdentity *peer
   return msg;
 }
 
+/**
+ * Compose #PeerIterateResponseMessage using the given peer and address.
+ *
+ * @param peer identity of the peer
+ * @param address the address, NULL on disconnect
+ * @return composed message
+ */
+static struct ValidationIterateResponseMessage *
+compose_validation_iterate_response_message (const struct GNUNET_PeerIdentity *peer,
+                                          const struct GNUNET_HELLO_Address *address)
+{
+  struct ValidationIterateResponseMessage *msg;
+  size_t size;
+  size_t tlen;
+  size_t alen;
+  char *addr;
+
+  GNUNET_assert (NULL != peer);
+  if (NULL != address)
+  {
+    tlen = strlen (address->transport_name) + 1;
+    alen = address->address_length;
+  }
+  else
+    tlen = alen = 0;
+  size = (sizeof (struct ValidationIterateResponseMessage) + alen + tlen);
+  msg = GNUNET_malloc (size);
+  msg->header.size = htons (size);
+  msg->header.type =
+      htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE);
+  msg->reserved = htonl (0);
+  msg->peer = *peer;
+  msg->addrlen = htonl (alen);
+  msg->pluginlen = htonl (tlen);
+
+  if (NULL != address)
+  {
+    msg->local_address_info = htonl((uint32_t) address->local_info);
+    addr = (char *) &msg[1];
+    memcpy (addr, address->address, alen);
+    memcpy (&addr[alen], address->transport_name, tlen);
+  }
+  return msg;
+}
 
-struct PeerIterationContext
+struct IterationContext
 {
   struct GNUNET_SERVER_TransmitContext *tc;
 
@@ -906,6 +1005,46 @@ struct PeerIterationContext
   int all;
 };
 
+/**
+ * Output information of neighbours to the given client.
+ *
+ * @param cls the 'struct PeerIterationContext'
+ * @param peer identity of the neighbour
+ * @param address the address
+ * @param state current state this peer is in
+ * @param state_timeout timeout for the current state of the peer
+ * @param bandwidth_in inbound quota in NBO
+ * @param bandwidth_out outbound quota in NBO
+ */
+static void
+send_validation_information (void *cls,
+    const struct GNUNET_PeerIdentity *peer,
+    const struct GNUNET_HELLO_Address *address,
+    struct GNUNET_TIME_Absolute last_validation,
+    struct GNUNET_TIME_Absolute valid_until,
+    struct GNUNET_TIME_Absolute next_validation,
+    enum GNUNET_TRANSPORT_ValidationState state)
+{
+  struct IterationContext *pc = cls;
+  struct ValidationIterateResponseMessage *msg;
+
+  if ( (GNUNET_YES == pc->all) ||
+       (0 == memcmp (peer, &pc->id, sizeof (pc->id))) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+        "Sending information about for validation entry for peer `%s' using address `%s'\n",
+        GNUNET_i2s(peer), (address != NULL) ? GST_plugins_a2s (address) : "<none>");
+    msg = compose_validation_iterate_response_message (peer, address);
+    msg->last_validation = GNUNET_TIME_absolute_hton(last_validation);
+    msg->valid_until = GNUNET_TIME_absolute_hton(valid_until);
+    msg->next_validation = GNUNET_TIME_absolute_hton(next_validation);
+    msg->state = htonl ((uint32_t) state);
+    GNUNET_SERVER_transmit_context_append_message (pc->tc, &msg->header);
+    GNUNET_free (msg);
+  }
+}
+
+
 /**
  * Output information of neighbours to the given client.
  *
@@ -926,7 +1065,7 @@ send_peer_information (void *cls,
     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
 {
-  struct PeerIterationContext *pc = cls;
+  struct IterationContext *pc = cls;
   struct PeerIterateResponseMessage *msg;
 
   if ( (GNUNET_YES == pc->all) ||
@@ -936,7 +1075,7 @@ send_peer_information (void *cls,
         "Sending information about `%s' using address `%s' in state `%s'\n",
         GNUNET_i2s(peer),
         (address != NULL) ? GST_plugins_a2s (address) : "<none>",
-        GNUNET_TRANSPORT_p2s (state));
+        GNUNET_TRANSPORT_ps2s (state));
     msg = compose_address_iterate_response_message (peer, address);
     msg->state = htonl (state);
     msg->state_timeout = GNUNET_TIME_absolute_hton(state_timeout);
@@ -947,7 +1086,6 @@ send_peer_information (void *cls,
 
 
 
-
 /**
  * Client asked to obtain information about a specific or all peers
  * Process the request.
@@ -963,7 +1101,7 @@ clients_handle_monitor_peers (void *cls, struct GNUNET_SERVER_Client *client,
   static struct GNUNET_PeerIdentity all_zeros;
   struct GNUNET_SERVER_TransmitContext *tc;
   struct PeerMonitorMessage *msg;
-  struct PeerIterationContext pc;
+  struct IterationContext pc;
 
   if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST)
   {
@@ -979,7 +1117,7 @@ clients_handle_monitor_peers (void *cls, struct GNUNET_SERVER_Client *client,
   }
   msg = (struct PeerMonitorMessage *) message;
   if ( (GNUNET_YES != ntohl (msg->one_shot)) &&
-       (NULL != lookup_monitoring_client (client)) )
+       (NULL != lookup_monitoring_client (peer_monitoring_clients_head, client)) )
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
                "ServerClient %p tried to start monitoring twice\n",
@@ -1008,7 +1146,7 @@ clients_handle_monitor_peers (void *cls, struct GNUNET_SERVER_Client *client,
 
   if (GNUNET_YES != ntohl (msg->one_shot))
   {
-    setup_monitoring_client (client, &msg->peer);
+    setup_peer_monitoring_client (client, &msg->peer);
   }
   else
   {
@@ -1020,6 +1158,78 @@ clients_handle_monitor_peers (void *cls, struct GNUNET_SERVER_Client *client,
 }
 
 
+/**
+ * Client asked to obtain information about a specific or all validation
+ * processes
+ *
+ * @param cls unused
+ * @param client the client
+ * @param message the peer address information request
+ */
+static void
+clients_handle_monitor_validation (void *cls, struct GNUNET_SERVER_Client *client,
+                                const struct GNUNET_MessageHeader *message)
+{
+  static struct GNUNET_PeerIdentity all_zeros;
+  struct GNUNET_SERVER_TransmitContext *tc;
+  struct PeerMonitorMessage *msg;
+  struct IterationContext pc;
+
+  if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  if (ntohs (message->size) != sizeof (struct ValidationMonitorMessage))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  msg = (struct PeerMonitorMessage *) message;
+  if ( (GNUNET_YES != ntohl (msg->one_shot)) &&
+       (NULL != lookup_monitoring_client (val_monitoring_clients_head, client)) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
+                "ServerClient %p tried to start monitoring twice\n",
+                client);
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  GNUNET_SERVER_disable_receive_done_warning (client);
+  pc.tc = tc = GNUNET_SERVER_transmit_context_create (client);
+
+  /* Send initial list */
+  if (0 == memcmp (&msg->peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity)))
+  {
+    /* iterate over all neighbours */
+    pc.all = GNUNET_YES;
+    pc.id = msg->peer;
+  }
+  else
+  {
+    /* just return one neighbour */
+    pc.all = GNUNET_NO;
+    pc.id = msg->peer;
+  }
+
+  GST_validation_iterate (&send_validation_information, &pc);
+
+  if (GNUNET_YES != ntohl (msg->one_shot))
+  {
+    GNUNET_break (0);
+    setup_val_monitoring_client (client, &msg->peer);
+  }
+  else
+  {
+    GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
+        GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE);
+  }
+  GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
+}
+
 /**
  * Start handling requests from clients.
  *
@@ -1043,6 +1253,9 @@ GST_clients_start (struct GNUNET_SERVER_Handle *server)
     {&clients_handle_monitor_peers, NULL,
      GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST,
      sizeof (struct PeerMonitorMessage)},
+    {&clients_handle_monitor_validation, NULL,
+     GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST,
+     sizeof (struct ValidationMonitorMessage)},
     {&GST_blacklist_handle_init, NULL,
      GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT,
      sizeof (struct GNUNET_MessageHeader)},
@@ -1053,7 +1266,8 @@ GST_clients_start (struct GNUNET_SERVER_Handle *server)
      GNUNET_MESSAGE_TYPE_TRANSPORT_TRAFFIC_METRIC, 0},
     {NULL, NULL, 0, 0}
   };
-  nc = GNUNET_SERVER_notification_context_create (server, 0);
+  peer_nc = GNUNET_SERVER_notification_context_create (server, 0);
+  val_nc = GNUNET_SERVER_notification_context_create (server, 0);
   GNUNET_SERVER_add_handlers (server, handlers);
   GNUNET_SERVER_disconnect_notify (server, &client_disconnect_notification,
                                    NULL);
@@ -1074,10 +1288,15 @@ GST_clients_stop ()
     GNUNET_CONTAINER_DLL_remove (a2s_head, a2s_tail, cur);
     GNUNET_free (cur);
   }
-  if (NULL != nc)
+  if (NULL != peer_nc)
+  {
+    GNUNET_SERVER_notification_context_destroy (peer_nc);
+    peer_nc = NULL;
+  }
+  if (NULL != val_nc)
   {
-    GNUNET_SERVER_notification_context_destroy (nc);
-    nc = NULL;
+    GNUNET_SERVER_notification_context_destroy (val_nc);
+    val_nc = NULL;
   }
 }
 
@@ -1142,7 +1361,7 @@ GST_clients_broadcast_peer_notification (const struct GNUNET_PeerIdentity *peer,
   msg = compose_address_iterate_response_message (peer, address);
   msg->state = htonl (state);
   msg->state_timeout = GNUNET_TIME_absolute_hton (state_timeout);
-  mc = monitoring_clients_head;
+  mc = peer_monitoring_clients_head;
   while (mc != NULL)
   {
     if ((0 == memcmp (&mc->peer, &all_zeros,
@@ -1150,7 +1369,7 @@ GST_clients_broadcast_peer_notification (const struct GNUNET_PeerIdentity *peer,
         (0 == memcmp (&mc->peer, peer,
                       sizeof (struct GNUNET_PeerIdentity))))
     {
-      GNUNET_SERVER_notification_context_unicast (nc, mc->client,
+      GNUNET_SERVER_notification_context_unicast (peer_nc, mc->client,
                                                   &msg->header, GNUNET_NO);
     }
 
@@ -1159,5 +1378,52 @@ GST_clients_broadcast_peer_notification (const struct GNUNET_PeerIdentity *peer,
   GNUNET_free (msg);
 }
 
+/**
+ * Broadcast the new active address to all clients monitoring the peer.
+ *
+ * @param peer peer this update is about (never NULL)
+ * @param address address, NULL on disconnect
+ * @param state the current state of the peer
+ * @param state_timeout the time out for the state
+ */
+void
+GST_clients_broadcast_validation_notification (
+    const struct GNUNET_PeerIdentity *peer,
+    const struct GNUNET_HELLO_Address *address,
+    struct GNUNET_TIME_Absolute last_validation,
+    struct GNUNET_TIME_Absolute valid_until,
+    struct GNUNET_TIME_Absolute next_validation,
+    enum GNUNET_TRANSPORT_ValidationState state)
+{
+  struct ValidationIterateResponseMessage *msg;
+  struct MonitoringClient *mc;
+  static struct GNUNET_PeerIdentity all_zeros;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+      "Sending information about for validation entry for peer `%s' using address `%s'\n",
+      GNUNET_i2s(peer), (address != NULL) ? GST_plugins_a2s (address) : "<none>");
+
+  msg = compose_validation_iterate_response_message (peer, address);
+  msg->last_validation = GNUNET_TIME_absolute_hton(last_validation);
+  msg->valid_until = GNUNET_TIME_absolute_hton(valid_until);
+  msg->next_validation = GNUNET_TIME_absolute_hton(next_validation);
+  msg->state = htonl ((uint32_t) state);
+  mc = val_monitoring_clients_head;
+  while (mc != NULL)
+  {
+    if ((0 == memcmp (&mc->peer, &all_zeros,
+                      sizeof (struct GNUNET_PeerIdentity))) ||
+        (0 == memcmp (&mc->peer, peer,
+                      sizeof (struct GNUNET_PeerIdentity))))
+    {
+      GNUNET_SERVER_notification_context_unicast (val_nc, mc->client,
+                                                  &msg->header, GNUNET_NO);
+
+    }
+    mc = mc->next;
+  }
+  GNUNET_free (msg);
+}
+
 
 /* end of file gnunet-service-transport_clients.c */
index 5b151382c514c71e62f9d68a9fe861afab178df3..29c46c06b5be82c12e64c160788e7a1e14401739 100644 (file)
@@ -85,6 +85,15 @@ GST_clients_broadcast_peer_notification (const struct GNUNET_PeerIdentity *peer,
     enum GNUNET_TRANSPORT_PeerState state,
     struct GNUNET_TIME_Absolute state_timeout);
 
+void
+GST_clients_broadcast_validation_notification (
+    const struct GNUNET_PeerIdentity *peer,
+    const struct GNUNET_HELLO_Address *address,
+    struct GNUNET_TIME_Absolute last_validation,
+    struct GNUNET_TIME_Absolute valid_until,
+    struct GNUNET_TIME_Absolute next_validation,
+    enum GNUNET_TRANSPORT_ValidationState state);
+
 
 #endif
 /* end of file gnunet-service-transport_clients.h */
index 2090c71b51c2652b07fa82cdfc52b6bff8ba4b34..fbd524f3b65accda8c061ec5e8f6d1a6ee2d452d 100644 (file)
@@ -589,7 +589,7 @@ set_state (struct NeighbourMapEntry *n, enum GNUNET_TRANSPORT_PeerState s)
   n->state = s;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Neighbour `%s' changed state to %s\n",
       GNUNET_i2s (&n->id),
-      GNUNET_TRANSPORT_p2s(s));
+      GNUNET_TRANSPORT_ps2s(s));
   neighbour_change_cb (callback_cls,
       &n->id,
       n->primary_address.address,
@@ -615,7 +615,7 @@ set_state_and_timeout (struct NeighbourMapEntry *n,
   n->timeout = timeout;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Neighbour `%s' changed state to %s with timeout %s\n",
       GNUNET_i2s (&n->id),
-      GNUNET_TRANSPORT_p2s(s),
+      GNUNET_TRANSPORT_ps2s(s),
       GNUNET_STRINGS_absolute_time_to_string (timeout));
   neighbour_change_cb (callback_cls,
       &n->id,
@@ -1029,7 +1029,7 @@ disconnect_neighbour (struct NeighbourMapEntry *n)
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Disconnecting from peer %s in state %s\n",
               GNUNET_i2s (&n->id),
-              GNUNET_TRANSPORT_p2s (n->state));
+              GNUNET_TRANSPORT_ps2s (n->state));
   /* depending on state, notify neighbour and/or upper layers of this peer
      about disconnect */
   switch (n->state)
@@ -1091,7 +1091,7 @@ disconnect_neighbour (struct NeighbourMapEntry *n)
   default:
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Unhandled state `%s'\n",
-                GNUNET_TRANSPORT_p2s (n->state));
+                GNUNET_TRANSPORT_ps2s (n->state));
     GNUNET_break (0);
     break;
   }
@@ -1775,7 +1775,7 @@ GST_neighbours_try_connect (const struct GNUNET_PeerIdentity *target)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
              "Asked to connect to peer `%s' (state: %s)\n",
               GNUNET_i2s (target),
-              (NULL != n) ? GNUNET_TRANSPORT_p2s(n->state) : "NEW PEER");
+              (NULL != n) ? GNUNET_TRANSPORT_ps2s(n->state) : "NEW PEER");
   if (NULL != n)
   {
     switch (n->state)
@@ -1816,7 +1816,7 @@ GST_neighbours_try_connect (const struct GNUNET_PeerIdentity *target)
     default:
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   "Unhandled state `%s'\n",
-                  GNUNET_TRANSPORT_p2s (n->state));
+                  GNUNET_TRANSPORT_ps2s (n->state));
       GNUNET_break (0);
       free_neighbour (n, GNUNET_NO);
       break;
@@ -1876,7 +1876,7 @@ handle_test_blacklist_cont (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Received blacklist result for peer `%s' in state %s/%d\n",
               GNUNET_i2s (peer),
-              GNUNET_TRANSPORT_p2s (n->state),
+              GNUNET_TRANSPORT_ps2s (n->state),
               n->send_connect_ack);
   switch (n->state)
   {
@@ -2066,7 +2066,7 @@ handle_test_blacklist_cont (void *cls,
   default:
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Unhandled state `%s'\n",
-                GNUNET_TRANSPORT_p2s (n->state));
+                GNUNET_TRANSPORT_ps2s (n->state));
     GNUNET_break (0);
     free_neighbour (n, GNUNET_NO);
     break;
@@ -2167,7 +2167,7 @@ GST_neighbours_handle_connect (const struct GNUNET_MessageHeader *message,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Received SESSION_CONNECT for peer `%s' in state %s/%d\n",
               GNUNET_i2s (peer),
-              GNUNET_TRANSPORT_p2s (n->state),
+              GNUNET_TRANSPORT_ps2s (n->state),
               n->send_connect_ack);
   switch (n->state)
   {
@@ -2234,7 +2234,7 @@ GST_neighbours_handle_connect (const struct GNUNET_MessageHeader *message,
   default:
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Unhandled state `%s'\n",
-                GNUNET_TRANSPORT_p2s (n->state));
+                GNUNET_TRANSPORT_ps2s (n->state));
     GNUNET_break (0);
     return GNUNET_SYSERR;
   }
@@ -2311,7 +2311,7 @@ GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
     GST_plugins_a2s (address),
     session,
     GNUNET_i2s (peer),
-    GNUNET_TRANSPORT_p2s (n->state),
+    GNUNET_TRANSPORT_ps2s (n->state),
     n->send_connect_ack,
     ntohl (bandwidth_in.value__),
     ntohl (bandwidth_out.value__));
@@ -2471,7 +2471,7 @@ GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
   default:
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Unhandled state `%s'\n",
-                GNUNET_TRANSPORT_p2s (n->state));
+                GNUNET_TRANSPORT_ps2s (n->state));
     GNUNET_break (0);
     break;
   }
@@ -2638,7 +2638,7 @@ master_task (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Master task runs for neighbour `%s' in state %s with timeout in %s\n",
              GNUNET_i2s (&n->id),
-             GNUNET_TRANSPORT_p2s(n->state),
+             GNUNET_TRANSPORT_ps2s(n->state),
              GNUNET_STRINGS_relative_time_to_string (delay,
                                                      GNUNET_YES));
   switch (n->state)
@@ -2809,7 +2809,7 @@ master_task (void *cls,
   default:
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Unhandled state `%s'\n",
-                GNUNET_TRANSPORT_p2s (n->state));
+                GNUNET_TRANSPORT_ps2s (n->state));
     GNUNET_break (0);
     break;
   }
@@ -2993,7 +2993,7 @@ GST_neighbours_handle_connect_ack (const struct GNUNET_MessageHeader *message,
   default:
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Unhandled state `%s'\n",
-                GNUNET_TRANSPORT_p2s (n->state));
+                GNUNET_TRANSPORT_ps2s (n->state));
     GNUNET_break (0);
     return GNUNET_SYSERR;
   }
@@ -3112,7 +3112,7 @@ GST_neighbours_session_terminated (const struct GNUNET_PeerIdentity *peer,
   default:
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Unhandled state `%s'\n",
-                GNUNET_TRANSPORT_p2s (n->state));
+                GNUNET_TRANSPORT_ps2s (n->state));
     GNUNET_break (0);
     break;
   }
@@ -3169,7 +3169,7 @@ GST_neighbours_handle_session_ack (const struct GNUNET_MessageHeader *message,
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Received SESSION_ACK message from peer `%s' in state %s/%d\n",
                 GNUNET_i2s (peer),
-                GNUNET_TRANSPORT_p2s (n->state),
+                GNUNET_TRANSPORT_ps2s (n->state),
                 n->send_connect_ack);
     GNUNET_STATISTICS_update (GST_stats,
                               gettext_noop ("# unexpected SESSION_ACK messages"), 1,
@@ -3467,7 +3467,7 @@ GST_neighbour_get_latency (const struct GNUNET_PeerIdentity *peer)
   default:
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Unhandled state `%s'\n",
-                GNUNET_TRANSPORT_p2s (n->state));
+                GNUNET_TRANSPORT_ps2s (n->state));
     GNUNET_break (0);
     break;
   }
index 07ed2eeca11233c9bc203f739955dcd7f0abef38..e184125882675d7688c2cebe1ea2b8a317276742 100644 (file)
@@ -217,6 +217,11 @@ struct ValidationEntry
    */
   struct GNUNET_TIME_Absolute send_time;
 
+  /**
+   * At what time do we send the next validation request (PING)?
+   */
+  struct GNUNET_TIME_Absolute next_validation;
+
   /**
    * Until when is this address valid?
    * ZERO if it is not currently considered valid.
@@ -243,6 +248,10 @@ struct ValidationEntry
    */
   struct GNUNET_TIME_Relative latency;
 
+  /**
+   * Current state of this validation entry
+   */
+  enum GNUNET_TRANSPORT_ValidationState state;
   /**
    * Challenge number we used.
    */
@@ -336,6 +345,9 @@ static unsigned int validations_fast_start_threshold;
  */
 static struct GNUNET_TIME_Absolute validation_next;
 
+static GST_ValidationChangedCallback validation_entry_changed_cb;
+static void *validation_entry_changed_cb_cls;
+
 /**
  * Context for the validation entry match function.
  */
@@ -377,6 +389,24 @@ validation_entry_match (void *cls, const struct GNUNET_PeerIdentity * key, void
   return GNUNET_YES;
 }
 
+static void
+validation_entry_changed (struct ValidationEntry *ve, enum GNUNET_TRANSPORT_ValidationState state)
+{
+  char *t_sent = GNUNET_strdup(GNUNET_STRINGS_absolute_time_to_string(ve->send_time));
+  char *t_valid = GNUNET_strdup(GNUNET_STRINGS_absolute_time_to_string(ve->valid_until));
+  char *t_next = GNUNET_strdup(GNUNET_STRINGS_absolute_time_to_string(ve->next_validation));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Validation entry changed for peer `%s' address `%s':\n\tSent:  %s\n\tValid: %s\n\tNext:  %s\n",
+      GNUNET_i2s(&ve->pid), GST_plugins_a2s(ve->address),
+      t_sent, t_valid, t_next);
+  ve->state = state;
+
+  GNUNET_free (t_sent);
+  GNUNET_free (t_valid);
+  GNUNET_free (t_next);
+  validation_entry_changed_cb (validation_entry_changed_cb_cls, &ve->pid,
+      ve->address, ve->send_time, ve->valid_until, ve->next_validation, state);
+}
+
 
 /**
  * Iterate over validation entries and free them.
@@ -391,6 +421,12 @@ cleanup_validation_entry (void *cls, const struct GNUNET_PeerIdentity * key, voi
 {
   struct ValidationEntry *ve = value;
 
+  ve->next_validation = GNUNET_TIME_absolute_get_zero_();
+  ve->valid_until = GNUNET_TIME_UNIT_ZERO_ABS;
+
+  /* Notify about deleted entry */
+  validation_entry_changed (ve, GNUNET_TRANSPORT_VS_REMOVE);
+
   if (NULL != ve->bc)
   {
     GST_blacklist_test_cancel (ve->bc);
@@ -586,6 +622,8 @@ transmit_ping_if_allowed (void *cls,
          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                      "Validation started, %u validation processes running\n",
                      validations_running);
+    /*  Notify about PING sent */
+    validation_entry_changed (ve, GNUNET_TRANSPORT_VS_UPDATE);
   }
 }
 
@@ -631,6 +669,7 @@ revalidate_address (void *cls,
                 GST_plugins_a2s (ve->address));
     ve->revalidation_task =
         GNUNET_SCHEDULER_add_delayed (delay, &revalidate_address, ve);
+    ve->next_validation =  GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), delay);
     return;
   }
   blocked_for = GNUNET_TIME_absolute_get_remaining(validation_next);
@@ -645,6 +684,7 @@ revalidate_address (void *cls,
                 GST_plugins_a2s (ve->address));
     ve->revalidation_task =
       GNUNET_SCHEDULER_add_delayed (blocked_for, &revalidate_address, ve);
+    ve->next_validation =  GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), blocked_for);
     return;
   }
   ve->revalidation_block = GNUNET_TIME_relative_to_absolute (canonical_delay);
@@ -675,6 +715,7 @@ revalidate_address (void *cls,
               GST_plugins_a2s (ve->address));
   ve->revalidation_task =
       GNUNET_SCHEDULER_add_delayed (delay, &revalidate_address, ve);
+  ve->next_validation =  GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), delay);
 
   /* start PINGing by checking blacklist */
   GNUNET_STATISTICS_update (GST_stats,
@@ -730,6 +771,7 @@ find_validation_entry (const struct GNUNET_CRYPTO_EddsaPublicKey *public_key,
   GNUNET_CONTAINER_multipeermap_put (validation_map, &address->peer,
                                      ve,
                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+  validation_entry_changed (ve, GNUNET_TRANSPORT_VS_NEW);
   ve->expecting_pong = GNUNET_NO;
   return ve;
 }
@@ -779,8 +821,10 @@ add_valid_address (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Starting revalidations for valid address `%s'\n",
               GST_plugins_a2s (ve->address));
+    ve->next_validation = GNUNET_TIME_absolute_get();
     ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address, ve);
   }
+  validation_entry_changed (ve, GNUNET_TRANSPORT_VS_UPDATE);
 
   ats.type = htonl (GNUNET_ATS_NETWORK_TYPE);
   ats.value = htonl (ve->network);
@@ -822,7 +866,7 @@ process_peerinfo_hello (void *cls, const struct GNUNET_PeerIdentity *peer,
  * @param max_fds maximum number of fds to use
  */
 void
-GST_validation_start (unsigned int max_fds)
+GST_validation_start (GST_ValidationChangedCallback cb, void *cb_cls, unsigned int max_fds)
 {
   /**
    * Initialization for validation throttling
@@ -840,6 +884,8 @@ GST_validation_start (unsigned int max_fds)
   validation_delay.rel_value_us = (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value_us) / (max_fds / 2);
   validations_fast_start_threshold = (max_fds / 2);
   validations_running = 0;
+  validation_entry_changed_cb = cb;
+  validation_entry_changed_cb_cls = cb_cls;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Validation uses a fast start threshold of %u connections and a delay between of %s\n ",
               validations_fast_start_threshold,
               GNUNET_STRINGS_relative_time_to_string (validation_delay,
@@ -1396,6 +1442,9 @@ GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender,
     GNUNET_break (0);
   }
 
+  /* Notify about new validity */
+  validation_entry_changed (ve, GNUNET_TRANSPORT_VS_UPDATE);
+
   /* build HELLO to store in PEERINFO */
   ve->copied = GNUNET_NO;
   hello = GNUNET_HELLO_create (&ve->public_key,
@@ -1600,5 +1649,54 @@ GST_validation_get_address_latency (const struct GNUNET_PeerIdentity *sender,
   return ve->latency;
 }
 
+/**
+ * Closure for the validation_entries_iterate function.
+ */
+struct ValidationIteratorContext
+{
+  /**
+   * Function to call on each validation entry
+   */
+  GST_ValidationChangedCallback cb;
+
+  /**
+   * Closure for 'cb'.
+   */
+  void *cb_cls;
+};
+
+static int
+validation_entries_iterate (void *cls,
+                           const struct GNUNET_PeerIdentity *key,
+                           void *value)
+{
+  struct ValidationIteratorContext *ic = cls;
+  struct ValidationEntry *ve = value;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Notifying about validation entry for peer `%s' address `%s' \n",
+      GNUNET_i2s (&ve->pid), GST_plugins_a2s (ve->address));
+  ic->cb (ic->cb_cls, &ve->pid, ve->address, ve->send_time,
+      ve->valid_until, ve->next_validation, ve->state);
+
+  return GNUNET_OK;
+}
+
+/**
+ * Iterate over all iteration entries
+ *
+ * @param cb function to call
+ * @param cb_cls closure for cb
+ */
+void
+GST_validation_iterate (GST_ValidationChangedCallback cb, void *cb_cls)
+{
+  struct ValidationIteratorContext ic;
+
+  if (NULL == validation_map)
+    return; /* can happen during shutdown */
+  ic.cb = cb;
+  ic.cb_cls = cb_cls;
+  GNUNET_CONTAINER_multipeermap_iterate (validation_map, &validation_entries_iterate, &ic);
+}
 
 /* end of file gnunet-service-transport_validation.c */
index e07afc40969733b31824931492fe4010726b2058..d117faca5c80e713507100d4c53fbaf1f23d4746 100644 (file)
 #include "gnunet_util_lib.h"
 #include "gnunet_hello_lib.h"
 
+/**
+ * Function called for each address (or address status change) that
+ * the validation module is aware of (for the given target).
+ *
+ * @param cls closure
+ * @param public_key public key for the peer, never NULL
+ * @param valid_until is ZERO if we never validated the address,
+ *                    otherwise a time up to when we consider it (or was) valid
+ * @param validation_block  is FOREVER if the address is for an unsupported plugin (from PEERINFO)
+ *                          is ZERO if the address is considered valid (no validation needed)
+ *                          otherwise a time in the future if we're currently denying re-validation
+ * @param address the address
+ */
+typedef void (*GST_ValidationChangedCallback) (void *cls,
+    const struct GNUNET_PeerIdentity *peer,
+    const struct GNUNET_HELLO_Address *address,
+    struct GNUNET_TIME_Absolute last_validation,
+    struct GNUNET_TIME_Absolute valid_until,
+    struct GNUNET_TIME_Absolute next_validation,
+    enum GNUNET_TRANSPORT_ValidationState state);
 
 /**
  * Start the validation subsystem.
@@ -38,7 +58,7 @@
  * @param max_fds maximum number of fds to use
  */
 void
-GST_validation_start (unsigned int max_fds);
+GST_validation_start (GST_ValidationChangedCallback cb, void *cb_cls, unsigned int max_fds);
 
 
 /**
@@ -79,6 +99,14 @@ GST_validation_get_address_latency (const struct GNUNET_PeerIdentity *sender,
                                     const struct GNUNET_HELLO_Address *address,
                                     struct Session *session);
 
+/**
+ * Iterate over all iteration entries
+ *
+ * @param cb function to call
+ * @param cb_cls closure for cb
+ */
+void
+GST_validation_iterate (GST_ValidationChangedCallback cb, void *cb_cls);
 
 /**
  * We've received a PING.  If appropriate, generate a PONG.
index c2d35cd6644060018705a1a92cfdc4d674065f29..c8408b757ced4ab0d08aff89a57c14dba94fc023 100644 (file)
@@ -88,6 +88,11 @@ static int benchmark_receive;
  */
 static int iterate_connections;
 
+/**
+ * Option -d.
+ */
+static int iterate_validation;
+
 /**
  * Option -a.
  */
@@ -156,7 +161,9 @@ static struct GNUNET_CONTAINER_MultiPeerMap *monitored_peers;
 /**
  *
  */
-struct GNUNET_TRANSPORT_PeerMonitoringContext *pic;
+static struct GNUNET_TRANSPORT_PeerMonitoringContext *pic;
+
+static struct GNUNET_TRANSPORT_ValidationMonitoringContext *vic;
 
 /**
  * Identity of the peer we transmit to / connect to.
@@ -269,6 +276,11 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     GNUNET_TRANSPORT_monitor_peers_cancel (pic);
     pic = NULL;
   }
+  if (NULL != vic)
+  {
+    GNUNET_TRANSPORT_monitor_validation_entries_cancel (vic);
+    vic = NULL;
+  }
   if (NULL != th)
   {
     GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
@@ -430,6 +442,17 @@ fail_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   display_test_result (tstc, GNUNET_NO);
 }
 
+void process_validation_cb (void *cls,
+    const struct GNUNET_PeerIdentity *peer,
+    const struct GNUNET_HELLO_Address *address,
+    struct GNUNET_TIME_Absolute last_validation,
+    struct GNUNET_TIME_Absolute valid_until,
+    struct GNUNET_TIME_Absolute next_validation,
+    enum GNUNET_TRANSPORT_ValidationState state)
+{
+  GNUNET_break (0);
+}
+
 /**
  * Test our plugin's configuration (NAT traversal, etc.).
  *
@@ -694,7 +717,7 @@ print_info (const struct GNUNET_PeerIdentity *id, const char *transport,
         GNUNET_i2s (id),
         (NULL == transport) ? "<none>" : transport,
         (NULL == transport) ? "<none>" : addr,
-        GNUNET_TRANSPORT_p2s (state),
+        GNUNET_TRANSPORT_ps2s (state),
         GNUNET_STRINGS_absolute_time_to_string (state_timeout));
   }
   else
@@ -951,7 +974,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 + iterate_validation;
 
   if (1 < counter)
   {
@@ -1060,6 +1083,11 @@ testservice_task (void *cls, int result)
     pic = GNUNET_TRANSPORT_monitor_peers (cfg, (NULL == cpid) ? NULL : &pid,
         GNUNET_NO, TIMEOUT, &process_peer_monitoring_cb, (void *) cfg);
   }
+  else if (iterate_validation) /* -d: Print information about validations */
+  {
+    vic = GNUNET_TRANSPORT_monitor_validation_entries (cfg, (NULL == cpid) ? NULL : &pid,
+        GNUNET_YES, TIMEOUT, &process_validation_cb, (void *) cfg);
+  }
   else if (monitor_connects) /* -e : Monitor (dis)connect events continuously */
   {
     monitor_connect_counter = 0;
@@ -1120,6 +1148,9 @@ main (int argc, char * const *argv)
               0, &GNUNET_GETOPT_set_one, &benchmark_receive }, { 'C', "connect",
               NULL, gettext_noop ("connect to a peer"), 0,
               &GNUNET_GETOPT_set_one, &try_connect },
+          { 'd', "validation", NULL,
+              gettext_noop ("print information for all pending validations "),
+              0, &GNUNET_GETOPT_set_one, &iterate_validation },
           { 'i', "information", NULL,
               gettext_noop ("provide information about all current connections (once)"),
               0, &GNUNET_GETOPT_set_one, &iterate_connections },
index 9e3fc4fdf03dfacc62bac729a69e3214eb5aa9d3..e7ab1a818800f36af45b8c6dc076b96879d53606 100644 (file)
@@ -1308,7 +1308,7 @@ session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
       "Session %p was idle for %s, disconnecting\n", s,
       GNUNET_STRINGS_relative_time_to_string (UDP_SESSION_TIME_OUT, GNUNET_YES));
   /* call session destroy function */
-  udp_disconnect_session (s->plugin, s);
+  udp_disconnect_session (plugin, s);
 }
 
 /**
index f726344dd0e18bf5d8018e8934c8238de93daae9..0767893edcb4b5dde08a3aa7126839607d232836 100644 (file)
@@ -98,15 +98,20 @@ end ()
     GNUNET_SCHEDULER_cancel (send_task);
 
   if (die_task != GNUNET_SCHEDULER_NO_TASK)
+  {
     GNUNET_SCHEDULER_cancel (die_task);
+    die_task = GNUNET_SCHEDULER_NO_TASK;
+  }
 
   if (th != NULL)
     GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
   th = NULL;
 
-  GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1);
+  if (NULL != p1)
+    GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1);
   p1 = NULL;
-  GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2);
+  if (NULL != p2)
+    GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2);
   p2 = NULL;
 
   if (NULL != pmc_p1)
@@ -382,8 +387,8 @@ static void monitor1_cb (void *cls,
   if ((NULL == peer) || (NULL == p1))
     return;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Monitor 1: %s %s %s\n",
-      GNUNET_i2s (peer), GNUNET_TRANSPORT_p2s(state), GNUNET_STRINGS_absolute_time_to_string(state_timeout));
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Monitor 1: %s %s %s\n",
+      GNUNET_i2s (peer), GNUNET_TRANSPORT_ps2s(state), GNUNET_STRINGS_absolute_time_to_string(state_timeout));
   if ((0 == memcmp (peer, &p2->id, sizeof (p2->id)) &&
       (GNUNET_YES == GNUNET_TRANSPORT_is_connected(state)) &&
       GNUNET_NO == p1_c) )
@@ -404,8 +409,8 @@ static void monitor2_cb (void *cls,
   if ((NULL == peer) || (NULL == p2))
     return;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Monitor 2: %s %s %s\n",
-      GNUNET_i2s (peer), GNUNET_TRANSPORT_p2s (state), GNUNET_STRINGS_absolute_time_to_string(state_timeout));
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Monitor 2: %s %s %s\n",
+      GNUNET_i2s (peer), GNUNET_TRANSPORT_ps2s (state), GNUNET_STRINGS_absolute_time_to_string(state_timeout));
   if ((0 == memcmp (peer, &p1->id, sizeof (p1->id)) &&
       (GNUNET_YES == GNUNET_TRANSPORT_is_connected(state)) &&
       GNUNET_NO == p2_c) )
@@ -432,13 +437,14 @@ run (void *cls, char *const *args, const char *cfgfile,
                                             &notify_disconnect, &start_cb,
                                             NULL);
   pmc_p1 = GNUNET_TRANSPORT_monitor_peers (p1->cfg, NULL, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, &monitor1_cb, NULL);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 started\n");
 
   p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2,
                                             &notify_receive, &notify_connect,
                                             &notify_disconnect, &start_cb,
                                             NULL);
   pmc_p2 = GNUNET_TRANSPORT_monitor_peers (p2->cfg, NULL, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, &monitor2_cb, NULL);
-
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 started\n");
   if ((p1 == NULL) || (p2 == NULL))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n");
diff --git a/src/transport/test_transport_api_monitoring_validation_peer1.conf b/src/transport/test_transport_api_monitoring_validation_peer1.conf
new file mode 100644 (file)
index 0000000..aca9c1e
--- /dev/null
@@ -0,0 +1,6 @@
+@INLINE@ template_cfg_peer1.conf
+[PATHS]
+GNUNET_TEST_HOME = /tmp/test-transport/api-monitoring-val-p1/
+
+[transport]
+PLUGINS=tcp
diff --git a/src/transport/test_transport_api_monitoring_validation_peer2.conf b/src/transport/test_transport_api_monitoring_validation_peer2.conf
new file mode 100644 (file)
index 0000000..86dfcbb
--- /dev/null
@@ -0,0 +1,7 @@
+@INLINE@ template_cfg_peer2.conf
+[PATHS]
+GNUNET_TEST_HOME = /tmp/test-transport/api-monitoring-val-p2/
+
+[TRANSPORT]
+PLUGINS=tcp
+
index 5a2f040568deecc2528a957a2a488846be8e9b22..dab5415c26331cc9b84126361f174984df315ced 100644 (file)
@@ -341,15 +341,20 @@ struct AddressLookupMessage
 };
 
 
-#if 0
 /**
- * Message from the library to the transport service
- * asking for human readable addresses known for a peer.
+ * Message from the transport service to the library containing information
+ * about a peer. Information contained are:
+ * - current address used to communicate with this peer
+ * - state
+ * - state timeout
+ *
+ * Memory layout:
+ * [AddressIterateResponseMessage][address[addrlen]][transportname[pluginlen]]
  */
-struct PeerLookupMessage
+struct ValidationIterateResponseMessage
 {
   /**
-   * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PEER_ADDRESS_LOOKUP
+   * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE
    */
   struct GNUNET_MessageHeader header;
 
@@ -359,16 +364,59 @@ struct PeerLookupMessage
   uint32_t reserved;
 
   /**
-   * timeout to give up.  FIXME: remove in the future.
+   * Peer identity
    */
-  struct GNUNET_TIME_RelativeNBO timeout;
+  struct GNUNET_PeerIdentity peer;
+
+  /**
+   * Local info about the address
+   */
+  uint32_t local_address_info GNUNET_PACKED;
+
+  /**
+   * Address length
+   */
+  uint32_t addrlen GNUNET_PACKED;
+
+  /**
+   * Length of the plugin name
+   */
+  uint32_t pluginlen GNUNET_PACKED;
+
+  /**
+   * State
+   */
+  uint32_t state GNUNET_PACKED;
+
+  struct GNUNET_TIME_AbsoluteNBO last_validation;
+
+  struct GNUNET_TIME_AbsoluteNBO valid_until;
+
+  struct GNUNET_TIME_AbsoluteNBO next_validation;
+};
+
+/**
+ * Message from the library to the transport service
+ * asking for binary addresses known for a peer.
+ */
+struct ValidationMonitorMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * One shot call or continous replies?
+   */
+  uint32_t one_shot;
 
   /**
    * The identity of the peer to look up.
    */
   struct GNUNET_PeerIdentity peer;
+
 };
-#endif
 
 
 /**
@@ -378,7 +426,7 @@ struct PeerLookupMessage
 struct PeerMonitorMessage
 {
   /**
-   * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE
+   * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST
    */
   struct GNUNET_MessageHeader header;
 
@@ -387,11 +435,6 @@ struct PeerMonitorMessage
    */
   uint32_t one_shot;
 
-  /**
-   * timeout to give up.  FIXME: remove in the future
-   */
-  struct GNUNET_TIME_AbsoluteNBO timeout;
-
   /**
    * The identity of the peer to look up.
    */
index 50517cc6cfff8d53e13ef915686e574a14691dcd..9820151d5f5a8ab175d2682bc38ec21bc9921477 100644 (file)
@@ -173,7 +173,7 @@ GNUNET_TRANSPORT_is_connected (enum GNUNET_TRANSPORT_PeerState state)
   default:
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Unhandled state `%s' \n",
-                GNUNET_TRANSPORT_p2s (state));
+                GNUNET_TRANSPORT_ps2s (state));
     GNUNET_break (0);
     break;
   }
@@ -181,13 +181,13 @@ GNUNET_TRANSPORT_is_connected (enum GNUNET_TRANSPORT_PeerState state)
 }
 
 /**
- * Convert state to human-readable string.
+ * Convert peer state to human-readable string.
  *
  * @param state the state value
  * @return corresponding string
  */
 const char *
-GNUNET_TRANSPORT_p2s (enum GNUNET_TRANSPORT_PeerState state)
+GNUNET_TRANSPORT_ps2s (enum GNUNET_TRANSPORT_PeerState state)
 {
   switch (state)
   {
@@ -229,6 +229,31 @@ GNUNET_TRANSPORT_p2s (enum GNUNET_TRANSPORT_PeerState state)
   }
 }
 
+/**
+ * Convert validation state to human-readable string.
+ *
+ * @param state the state value
+ * @return corresponding string
+ */
+const char *
+GNUNET_TRANSPORT_vs2s (enum GNUNET_TRANSPORT_ValidationState state)
+{
+  switch (state)
+  {
+  case GNUNET_TRANSPORT_VS_NEW:
+    return "NEW";
+  case GNUNET_TRANSPORT_VS_REMOVE:
+    return "REMOVE";
+  case GNUNET_TRANSPORT_VS_TIMEOUT:
+    return "TIMEOUT";
+  case GNUNET_TRANSPORT_VS_UPDATE:
+    return "UPDATE";
+  default:
+    GNUNET_break (0);
+    return "UNDEFINED";
+  }
+}
+
 
 /**
  * Function called with responses from the service.
@@ -238,34 +263,66 @@ GNUNET_TRANSPORT_p2s (enum GNUNET_TRANSPORT_PeerState state)
  *        message with the human-readable address
  */
 static void
-peer_response_processor (void *cls,
-                                 const struct GNUNET_MessageHeader *msg);
+peer_response_processor (void *cls, const struct GNUNET_MessageHeader *msg);
 
 
+/**
+ * Function called with responses from the service.
+ *
+ * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*'
+ * @param msg NULL on timeout or error, otherwise presumably a
+ *        message with the human-readable address
+ */
+static void
+val_response_processor (void *cls, const struct GNUNET_MessageHeader *msg);
+
 /**
  * Send our subscription request to the service.
  *
  * @param pal_ctx our context
  */
 static void
-send_request (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
+send_peer_mon_request (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
 {
   struct PeerMonitorMessage msg;
 
   msg.header.size = htons (sizeof (struct PeerMonitorMessage));
   msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST);
   msg.one_shot = htonl (pal_ctx->one_shot);
-  msg.timeout = GNUNET_TIME_absolute_hton (pal_ctx->timeout);
   msg.peer = pal_ctx->peer;
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CLIENT_transmit_and_get_response (pal_ctx->client,
-                                                         &msg.header,
-                                                          GNUNET_TIME_absolute_get_remaining (pal_ctx->timeout),
-                                                         GNUNET_YES,
-                                                          &peer_response_processor,
-                                                          pal_ctx));
+                    &msg.header,
+                    GNUNET_TIME_absolute_get_remaining (pal_ctx->timeout),
+                    GNUNET_YES,
+                    &peer_response_processor,
+                    pal_ctx));
 }
 
+/**
+ * Send our subscription request to the service.
+ *
+ * @param pal_ctx our context
+ */
+static void
+send_val_mon_request (struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx)
+{
+  struct ValidationMonitorMessage msg;
+
+  msg.header.size = htons (sizeof (struct PeerMonitorMessage));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST);
+  msg.one_shot = htonl (val_ctx->one_shot);
+  msg.peer = val_ctx->peer;
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CLIENT_transmit_and_get_response (val_ctx->client,
+                    &msg.header,
+                    GNUNET_TIME_absolute_get_remaining (val_ctx->timeout),
+                    GNUNET_YES,
+                    &val_response_processor,
+                    val_ctx));
+}
+
+
 /**
  * Task run to re-establish the connection.
  *
@@ -281,7 +338,7 @@ do_connect (void *cls,
   pal_ctx->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
   pal_ctx->client = GNUNET_CLIENT_connect ("transport", pal_ctx->cfg);
   GNUNET_assert (NULL != pal_ctx->client);
-  send_request (pal_ctx);
+  send_peer_mon_request (pal_ctx);
 }
 
 
@@ -302,6 +359,154 @@ reconnect (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
                                                          pal_ctx);
 }
 
+/**
+ * Function called with responses from the service.
+ *
+ * @param cls our 'struct GNUNET_TRANSPORT_PeerMonitoringContext*'
+ * @param msg NULL on timeout or error, otherwise presumably a
+ *        message with the human-readable address
+ */
+static void
+val_response_processor (void *cls, const struct GNUNET_MessageHeader *msg)
+{
+  struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx = cls;
+  GNUNET_break (0);
+  if (msg == NULL)
+  {
+    GNUNET_break (0);
+    if (val_ctx->one_shot)
+    {
+      /* Disconnect */
+      val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
+          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
+          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_TIMEOUT);
+      GNUNET_TRANSPORT_monitor_peers_cancel (val_ctx);
+    }
+    else
+    {
+      reconnect (val_ctx);
+    }
+    return;
+  }
+
+  /* expect more replies */
+  GNUNET_CLIENT_receive (val_ctx->client, &val_response_processor,
+      val_ctx, GNUNET_TIME_absolute_get_remaining (val_ctx->timeout));
+
+  return;
+
+  struct ValidationIterateResponseMessage *vir_msg;
+  struct GNUNET_HELLO_Address *address;
+  const char *addr;
+  const char *transport_name;
+  uint16_t size;
+  size_t alen;
+  size_t tlen;
+#if 0
+
+  size = ntohs (msg->size);
+  GNUNET_break (ntohs (msg->type) ==
+      GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE);
+  if (size == sizeof (struct GNUNET_MessageHeader))
+  {
+    /* Done! */
+    if (pal_ctx->one_shot)
+    {
+      pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
+          GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
+      GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
+    }
+    else
+    {
+      reconnect (pal_ctx);
+    }
+    return;
+  }
+
+  if ((size < sizeof (struct PeerIterateResponseMessage)) ||
+      (ntohs (msg->type) !=
+          GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE))
+  {
+    GNUNET_break (0);
+    if (pal_ctx->one_shot)
+    {
+      pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
+          GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
+      GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
+    }
+    else
+    {
+      reconnect (pal_ctx);
+    }
+    return;
+  }
+
+  pir_msg = (struct PeerIterateResponseMessage *) msg;
+  tlen = ntohl (pir_msg->pluginlen);
+  alen = ntohl (pir_msg->addrlen);
+
+  if (size != sizeof (struct PeerIterateResponseMessage) + tlen + alen)
+  {
+    GNUNET_break (0);
+    if (pal_ctx->one_shot)
+    {
+      pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
+          GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
+      GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
+    }
+    else
+    {
+      reconnect (pal_ctx);
+    }
+    return;
+  }
+
+  if ( (0 == tlen) && (0 == alen) )
+  {
+    /* No address available */
+    pal_ctx->cb (pal_ctx->cb_cls, &pir_msg->peer, NULL,
+        ntohl(pir_msg->state),
+        GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout));
+  }
+  else
+  {
+    if (0 == tlen)
+    {
+      GNUNET_break (0); /* This must not happen: address without plugin */
+      return;
+    }
+    addr = (const char *) &pir_msg[1];
+    transport_name = &addr[alen];
+
+    if (transport_name[tlen - 1] != '\0')
+    {
+      /* Corrupt plugin name */
+      GNUNET_break (0);
+      if (pal_ctx->one_shot)
+      {
+        pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
+            GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
+        GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
+      }
+      else
+      {
+        reconnect (pal_ctx);
+      }
+      return;
+    }
+
+    /* notify client */
+    address = GNUNET_HELLO_address_allocate (&pir_msg->peer,
+        transport_name, addr, alen, ntohl(pir_msg->local_address_info));
+    pal_ctx->cb (pal_ctx->cb_cls, &pir_msg->peer, address,
+        ntohl(pir_msg->state),
+        GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout));
+    GNUNET_HELLO_address_free (address);
+  }
+#endif
+
+}
+
 
 /**
  * Function called with responses from the service.
@@ -321,7 +526,7 @@ peer_response_processor (void *cls, const struct GNUNET_MessageHeader *msg)
   uint16_t size;
   size_t alen;
   size_t tlen;
-
+  GNUNET_break (0);
   if (msg == NULL)
   {
     if (pal_ctx->one_shot)
@@ -394,7 +599,6 @@ peer_response_processor (void *cls, const struct GNUNET_MessageHeader *msg)
     return;
   }
 
-
   if ( (0 == tlen) && (0 == alen) )
   {
     /* No address available */
@@ -498,7 +702,7 @@ GNUNET_TRANSPORT_monitor_peers (const struct GNUNET_CONFIGURATION_Handle *cfg,
     pal_ctx->peer = *peer;
   pal_ctx->one_shot = one_shot;
   pal_ctx->client = client;
-  send_request (pal_ctx);
+  send_peer_mon_request (pal_ctx);
 
   return pal_ctx;
 }
@@ -548,8 +752,26 @@ GNUNET_TRANSPORT_monitor_validation_entries (const struct
                                 GNUNET_TRANSPORT_ValidationIterateCallback validation_callback,
                                 void *validation_callback_cls)
 {
-  /* Not implemented */
-  return NULL;
+  struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx;
+  struct GNUNET_CLIENT_Connection *client;
+
+  client = GNUNET_CLIENT_connect ("transport", cfg);
+  if (client == NULL)
+    return NULL;
+  if (GNUNET_YES != one_shot)
+    timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+  val_ctx = GNUNET_new (struct GNUNET_TRANSPORT_ValidationMonitoringContext);
+  val_ctx->cb = validation_callback;
+  val_ctx->cb_cls = validation_callback_cls;
+  val_ctx->cfg = cfg;
+  val_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
+  if (NULL != peer)
+    val_ctx->peer = *peer;
+  val_ctx->one_shot = one_shot;
+  val_ctx->client = client;
+  send_val_mon_request (val_ctx);
+
+  return val_ctx;
 }
 
 
@@ -561,7 +783,17 @@ GNUNET_TRANSPORT_monitor_validation_entries (const struct
 void
 GNUNET_TRANSPORT_monitor_validation_entries_cancel (struct GNUNET_TRANSPORT_ValidationMonitoringContext *vic)
 {
-  /* Not implemented */
+  if (NULL != vic->client)
+  {
+    GNUNET_CLIENT_disconnect (vic->client);
+    vic->client = NULL;
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != vic->reconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (vic->reconnect_task);
+    vic->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  GNUNET_free (vic);
 }