gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r31919 - gnunet/src/transport


From: gnunet
Subject: [GNUnet-SVN] r31919 - gnunet/src/transport
Date: Wed, 15 Jan 2014 18:18:11 +0100

Author: wachs
Date: 2014-01-15 18:18:11 +0100 (Wed, 15 Jan 2014)
New Revision: 31919

Added:
   gnunet/src/transport/test_transport_api_monitoring_validation_peer1.conf
   gnunet/src/transport/test_transport_api_monitoring_validation_peer2.conf
Modified:
   gnunet/src/transport/Makefile.am
   gnunet/src/transport/gnunet-service-transport.c
   gnunet/src/transport/gnunet-service-transport_clients.c
   gnunet/src/transport/gnunet-service-transport_clients.h
   gnunet/src/transport/gnunet-service-transport_neighbours.c
   gnunet/src/transport/gnunet-service-transport_validation.c
   gnunet/src/transport/gnunet-service-transport_validation.h
   gnunet/src/transport/gnunet-transport.c
   gnunet/src/transport/plugin_transport_udp.c
   gnunet/src/transport/test_transport_api_monitoring.c
   gnunet/src/transport/transport.h
   gnunet/src/transport/transport_api_monitoring.c
Log:
transport validation monitoring API (not yet complete) + CLI
+ fix for crash in transport/plugin_transport_udp.c


Modified: gnunet/src/transport/Makefile.am
===================================================================
--- gnunet/src/transport/Makefile.am    2014-01-15 17:16:10 UTC (rev 31918)
+++ gnunet/src/transport/Makefile.am    2014-01-15 17:18:11 UTC (rev 31919)
@@ -408,6 +408,7 @@
  $(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 @@
  $(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 @@
  $(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,7 +1110,15 @@
  $(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 \
 test_plugin_hostkey.ecc \
@@ -1207,6 +1216,8 @@
 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\

Modified: gnunet/src/transport/gnunet-service-transport.c
===================================================================
--- gnunet/src/transport/gnunet-service-transport.c     2014-01-15 17:16:10 UTC 
(rev 31918)
+++ gnunet/src/transport/gnunet-service-transport.c     2014-01-15 17:18:11 UTC 
(rev 31919)
@@ -764,13 +764,43 @@
       "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 @@
       &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));
 }
 
 /**

Modified: gnunet/src/transport/gnunet-service-transport_clients.c
===================================================================
--- gnunet/src/transport/gnunet-service-transport_clients.c     2014-01-15 
17:16:10 UTC (rev 31918)
+++ gnunet/src/transport/gnunet-service-transport_clients.c     2014-01-15 
17:18:11 UTC (rev 31919)
@@ -190,19 +190,34 @@
 /**
  * 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 @@
  * @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,32 +288,63 @@
  * @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;
+}
+
+
 /**
  * Function called to notify a client about the socket being ready to
  * queue more data.  "buf" will be NULL and "size" zero if the socket
@@ -425,14 +472,22 @@
 
   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);
+  }
   tc = lookup_client (client);
   if (tc == NULL)
     return;
@@ -852,7 +907,7 @@
 
 
 /**
- * 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 @@
   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;
 
-struct PeerIterationContext
+  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 IterationContext
 {
   struct GNUNET_SERVER_TransmitContext *tc;
 
@@ -918,6 +1017,46 @@
  * @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.
+ *
+ * @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_peer_information (void *cls,
     const struct GNUNET_PeerIdentity *peer,
     const struct GNUNET_HELLO_Address *address,
@@ -926,7 +1065,7 @@
     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 @@
         "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 @@
 
 
 
-
 /**
  * Client asked to obtain information about a specific or all peers
  * Process the request.
@@ -963,7 +1101,7 @@
   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 @@
   }
   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 @@
 
   if (GNUNET_YES != ntohl (msg->one_shot))
   {
-    setup_monitoring_client (client, &msg->peer);
+    setup_peer_monitoring_client (client, &msg->peer);
   }
   else
   {
@@ -1021,6 +1159,78 @@
 
 
 /**
+ * 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.
  *
  * @param server server used to accept clients from.
@@ -1043,6 +1253,9 @@
     {&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 @@
      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,11 +1288,16 @@
     GNUNET_CONTAINER_DLL_remove (a2s_head, a2s_tail, cur);
     GNUNET_free (cur);
   }
-  if (NULL != nc)
+  if (NULL != peer_nc)
   {
-    GNUNET_SERVER_notification_context_destroy (nc);
-    nc = NULL;
+    GNUNET_SERVER_notification_context_destroy (peer_nc);
+    peer_nc = NULL;
   }
+  if (NULL != val_nc)
+  {
+    GNUNET_SERVER_notification_context_destroy (val_nc);
+    val_nc = NULL;
+  }
 }
 
 
@@ -1142,7 +1361,7 @@
   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 @@
         (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 @@
   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 */

Modified: gnunet/src/transport/gnunet-service-transport_clients.h
===================================================================
--- gnunet/src/transport/gnunet-service-transport_clients.h     2014-01-15 
17:16:10 UTC (rev 31918)
+++ gnunet/src/transport/gnunet-service-transport_clients.h     2014-01-15 
17:18:11 UTC (rev 31919)
@@ -85,6 +85,15 @@
     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 */

Modified: gnunet/src/transport/gnunet-service-transport_neighbours.c
===================================================================
--- gnunet/src/transport/gnunet-service-transport_neighbours.c  2014-01-15 
17:16:10 UTC (rev 31918)
+++ gnunet/src/transport/gnunet-service-transport_neighbours.c  2014-01-15 
17:18:11 UTC (rev 31919)
@@ -589,7 +589,7 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
     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 @@
   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 @@
   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 @@
   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 @@
   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_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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
     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 @@
   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;
   }

Modified: gnunet/src/transport/gnunet-service-transport_validation.c
===================================================================
--- gnunet/src/transport/gnunet-service-transport_validation.c  2014-01-15 
17:16:10 UTC (rev 31918)
+++ gnunet/src/transport/gnunet-service-transport_validation.c  2014-01-15 
17:18:11 UTC (rev 31919)
@@ -218,6 +218,11 @@
   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.
    */
@@ -244,6 +249,10 @@
   struct GNUNET_TIME_Relative latency;
 
   /**
+   * Current state of this validation entry
+   */
+  enum GNUNET_TRANSPORT_ValidationState state;
+  /**
    * Challenge number we used.
    */
   uint32_t challenge;
@@ -336,6 +345,9 @@
  */
 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,7 +389,25 @@
   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 @@
 {
   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 @@
          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 @@
                 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 @@
                 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 @@
               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 @@
   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 @@
     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 @@
  * @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 @@
   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 @@
     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 @@
   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 */

Modified: gnunet/src/transport/gnunet-service-transport_validation.h
===================================================================
--- gnunet/src/transport/gnunet-service-transport_validation.h  2014-01-15 
17:16:10 UTC (rev 31918)
+++ gnunet/src/transport/gnunet-service-transport_validation.h  2014-01-15 
17:18:11 UTC (rev 31919)
@@ -31,6 +31,26 @@
 #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 @@
                                     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.

Modified: gnunet/src/transport/gnunet-transport.c
===================================================================
--- gnunet/src/transport/gnunet-transport.c     2014-01-15 17:16:10 UTC (rev 
31918)
+++ gnunet/src/transport/gnunet-transport.c     2014-01-15 17:18:11 UTC (rev 
31919)
@@ -89,6 +89,11 @@
 static int iterate_connections;
 
 /**
+ * Option -d.
+ */
+static int iterate_validation;
+
+/**
  * Option -a.
  */
 static int iterate_all;
@@ -156,8 +161,10 @@
 /**
  *
  */
-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.
  * (equivalent to 'cpid' string).
@@ -269,6 +276,11 @@
     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 @@
   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 @@
         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 @@
   }
 
   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 @@
     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 @@
               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 },

Modified: gnunet/src/transport/plugin_transport_udp.c
===================================================================
--- gnunet/src/transport/plugin_transport_udp.c 2014-01-15 17:16:10 UTC (rev 
31918)
+++ gnunet/src/transport/plugin_transport_udp.c 2014-01-15 17:18:11 UTC (rev 
31919)
@@ -1308,7 +1308,7 @@
       "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);
 }
 
 /**

Modified: gnunet/src/transport/test_transport_api_monitoring.c
===================================================================
--- gnunet/src/transport/test_transport_api_monitoring.c        2014-01-15 
17:16:10 UTC (rev 31918)
+++ gnunet/src/transport/test_transport_api_monitoring.c        2014-01-15 
17:18:11 UTC (rev 31919)
@@ -98,15 +98,20 @@
     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 @@
   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 @@
   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 @@
                                             &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");

Added: gnunet/src/transport/test_transport_api_monitoring_validation_peer1.conf
===================================================================
--- gnunet/src/transport/test_transport_api_monitoring_validation_peer1.conf    
                        (rev 0)
+++ gnunet/src/transport/test_transport_api_monitoring_validation_peer1.conf    
2014-01-15 17:18:11 UTC (rev 31919)
@@ -0,0 +1,6 @@
address@hidden@ template_cfg_peer1.conf
+[PATHS]
+GNUNET_TEST_HOME = /tmp/test-transport/api-monitoring-val-p1/
+
+[transport]
+PLUGINS=tcp

Added: gnunet/src/transport/test_transport_api_monitoring_validation_peer2.conf
===================================================================
--- gnunet/src/transport/test_transport_api_monitoring_validation_peer2.conf    
                        (rev 0)
+++ gnunet/src/transport/test_transport_api_monitoring_validation_peer2.conf    
2014-01-15 17:18:11 UTC (rev 31919)
@@ -0,0 +1,7 @@
address@hidden@ template_cfg_peer2.conf
+[PATHS]
+GNUNET_TEST_HOME = /tmp/test-transport/api-monitoring-val-p2/
+
+[TRANSPORT]
+PLUGINS=tcp
+

Modified: gnunet/src/transport/transport.h
===================================================================
--- gnunet/src/transport/transport.h    2014-01-15 17:16:10 UTC (rev 31918)
+++ gnunet/src/transport/transport.h    2014-01-15 17:18:11 UTC (rev 31919)
@@ -341,15 +341,20 @@
 };
 
 
-#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 @@
   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 PeerMonitorMessage
 {
   /**
-   * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE
+   * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST
    */
   struct GNUNET_MessageHeader header;
 
@@ -388,11 +436,6 @@
   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.
    */
   struct GNUNET_PeerIdentity peer;

Modified: gnunet/src/transport/transport_api_monitoring.c
===================================================================
--- gnunet/src/transport/transport_api_monitoring.c     2014-01-15 17:16:10 UTC 
(rev 31918)
+++ gnunet/src/transport/transport_api_monitoring.c     2014-01-15 17:18:11 UTC 
(rev 31919)
@@ -173,7 +173,7 @@
   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 @@
 }
 
 /**
- * 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,7 +229,32 @@
   }
 }
 
+/**
+ * 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,35 +263,67 @@
  *        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.
  *
  * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*'
@@ -281,7 +338,7 @@
   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,7 +359,155 @@
                                                          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 @@
   uint16_t size;
   size_t alen;
   size_t tlen;
-
+  GNUNET_break (0);
   if (msg == NULL)
   {
     if (pal_ctx->one_shot)
@@ -394,7 +599,6 @@
     return;
   }
 
-
   if ( (0 == tlen) && (0 == alen) )
   {
     /* No address available */
@@ -498,7 +702,7 @@
     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_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 @@
 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);
 }
 
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]