+ if (NULL != end)
+ GNUNET_SCHEDULER_cancel (end);
+ end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
+ return;
+ }
+
+ if ( (GNUNET_NO == iterate_all) &&
+ (GNUNET_NO == GNUNET_TRANSPORT_is_connected(state)))
+ return; /* Display only connected peers */
+
+ if (NULL != op_timeout)
+ GNUNET_SCHEDULER_cancel (op_timeout);
+ op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT,
+ &operation_timeout,
+ NULL);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received address for peer `%s': %s\n",
+ GNUNET_i2s (peer),
+ address->transport_name);
+
+ if (NULL != address)
+ resolve_peer_address (address,
+ numeric,
+ state,
+ state_timeout);
+ else
+ print_info (peer,
+ NULL,
+ NULL,
+ state,
+ state_timeout);
+}
+
+
+/**
+ * Context for address resolution by #plugin_monitoring_cb().
+ */
+struct PluginMonitorAddress
+{
+
+ /**
+ * Ongoing resolution request.
+ */
+ struct GNUNET_TRANSPORT_AddressToStringContext *asc;
+
+ /**
+ * Resolved address as string.
+ */
+ char *str;
+
+ /**
+ * Last event we got and did not yet print because
+ * @e str was NULL (address not yet resolved).
+ */
+ struct GNUNET_TRANSPORT_SessionInfo si;
+};
+
+
+/**
+ * Print information about a plugin monitoring event.
+ *
+ * @param addr out internal context
+ * @param info the monitoring information
+ */
+static void
+print_plugin_event_info (struct PluginMonitorAddress *addr,
+ const struct GNUNET_TRANSPORT_SessionInfo *info)
+{
+ const char *state;
+
+ switch (info->state)
+ {
+ case GNUNET_TRANSPORT_SS_INIT:
+ state = "INIT";
+ break;
+ case GNUNET_TRANSPORT_SS_HANDSHAKE:
+ state = "HANDSHAKE";
+ break;
+ case GNUNET_TRANSPORT_SS_UP:
+ state = "UP";
+ break;
+ case GNUNET_TRANSPORT_SS_UPDATE:
+ state = "UPDATE";
+ break;
+ case GNUNET_TRANSPORT_SS_DONE:
+ state = "DONE";
+ break;
+ default:
+ state = "UNKNOWN";
+ break;
+ }
+ fprintf (stdout,
+ "%s: state %s timeout in %s @ %s%s\n",
+ GNUNET_i2s (&info->address->peer),
+ state,
+ GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (info->session_timeout),
+ GNUNET_YES),
+ addr->str,
+ (info->is_inbound == GNUNET_YES) ? " (INBOUND)" : "");
+ fprintf (stdout,
+ "%s: queue has %3u messages and %6u bytes\n",
+ GNUNET_i2s (&info->address->peer),
+ info->num_msg_pending,
+ info->num_bytes_pending);
+ if (0 != GNUNET_TIME_absolute_get_remaining (info->receive_delay).rel_value_us)
+ fprintf (stdout,
+ "%s: receiving blocked until %s\n",
+ GNUNET_i2s (&info->address->peer),
+ GNUNET_STRINGS_absolute_time_to_string (info->receive_delay));
+}
+
+
+/**
+ * Function called with a textual representation of an address. This
+ * function will be called several times with different possible
+ * textual representations, and a last time with @a address being NULL
+ * to signal the end of the iteration. Note that @a address NULL
+ * always is the last call, regardless of the value in @a res.
+ *
+ * @param cls closure
+ * @param address NULL on end of iteration,
+ * otherwise 0-terminated printable UTF-8 string,
+ * in particular an empty string if @a res is #GNUNET_NO
+ * @param res result of the address to string conversion:
+ * if #GNUNET_OK: conversion successful
+ * if #GNUNET_NO: address was invalid (or not supported)
+ * if #GNUNET_SYSERR: communication error (IPC error)
+ */
+static void
+address_cb (void *cls,
+ const char *address,
+ int res)
+{
+ struct PluginMonitorAddress *addr = cls;
+
+ if (NULL == address)
+ {
+ addr->asc = NULL;
+ return;
+ }
+ if (NULL != addr->str)
+ return;
+ addr->str = GNUNET_strdup (address);
+ print_plugin_event_info (addr,
+ &addr->si);
+}
+
+
+/**
+ * Function called by the plugin with information about the
+ * current sessions managed by the plugin (for monitoring).
+ *
+ * @param cls closure (NULL)
+ * @param session session handle this information is about,
+ * NULL to indicate that we are "in sync" (initial
+ * iteration complete)
+ * @param session_ctx storage location where the application
+ * can store data; will point to NULL on #GNUNET_TRANSPORT_SS_INIT,
+ * and must be reset to NULL on #GNUNET_TRANSPORT_SS_DONE
+ * @param info information about the state of the session,
+ * NULL if @a session is also NULL and we are
+ * merely signalling that the initial iteration is over;
+ * NULL with @a session being non-NULL if the monitor
+ * was being cancelled while sessions were active
+ */
+static void
+plugin_monitoring_cb (void *cls,
+ struct GNUNET_TRANSPORT_PluginSession *session,
+ void **session_ctx,
+ const struct GNUNET_TRANSPORT_SessionInfo *info)
+{
+ struct PluginMonitorAddress *addr;
+
+ if ( (NULL == info) &&
+ (NULL == session) )
+ return; /* in sync with transport service */
+ addr = *session_ctx;
+ if (NULL == info)
+ {
+ if (NULL != addr)
+ {
+ if (NULL != addr->asc)
+ {
+ GNUNET_TRANSPORT_address_to_string_cancel (addr->asc);
+ addr->asc = NULL;
+ }
+ GNUNET_free_non_null (addr->str);
+ GNUNET_free (addr);
+ *session_ctx = NULL;
+ }
+ return; /* shutdown */
+ }
+ if ( (NULL != cpid) &&
+ (0 != memcmp (&info->address->peer,
+ cpid,
+ sizeof (struct GNUNET_PeerIdentity))) )
+ return; /* filtered */
+ if (NULL == addr)
+ {
+ addr = GNUNET_new (struct PluginMonitorAddress);
+ addr->asc = GNUNET_TRANSPORT_address_to_string (cfg,
+ info->address,
+ numeric,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ &address_cb,
+ addr);
+ *session_ctx = addr;
+ }
+ if (NULL == addr->str)
+ addr->si = *info;
+ else
+ print_plugin_event_info (addr,
+ info);
+ if (GNUNET_TRANSPORT_SS_DONE == info->state)
+ {
+ if (NULL != addr->asc)
+ {
+ GNUNET_TRANSPORT_address_to_string_cancel (addr->asc);
+ addr->asc = NULL;
+ }
+ GNUNET_free_non_null (addr->str);
+ GNUNET_free (addr);
+ *session_ctx = NULL;
+ }
+}
+
+
+/**
+ * Function called with information about a peers
+ *
+ * @param cls closure, NULL
+ * @param peer identity of the peer, NULL for final callback when operation done
+ * @param address binary address used to communicate with this peer,
+ * NULL on disconnect or when done
+ * @param state current state this peer is in
+ * @param state_timeout time out for the current state
+ */
+static void
+process_peer_monitoring_cb (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Address *address,
+ enum GNUNET_TRANSPORT_PeerState state,
+ struct GNUNET_TIME_Absolute state_timeout)
+{
+ struct MonitoredPeer *m;
+
+ if (NULL == peer)
+ {
+ FPRINTF (stdout,
+ "%s",
+ _("Monitor disconnected from transport service. Reconnecting.\n"));