gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r33032 - in gnunet/src: core include


From: gnunet
Subject: [GNUnet-SVN] r33032 - in gnunet/src: core include
Date: Fri, 11 Apr 2014 13:49:51 +0200

Author: grothoff
Date: 2014-04-11 13:49:51 +0200 (Fri, 11 Apr 2014)
New Revision: 33032

Modified:
   gnunet/src/core/core.h
   gnunet/src/core/core_api_iterate_peers.c
   gnunet/src/core/gnunet-core.c
   gnunet/src/core/gnunet-service-core.c
   gnunet/src/core/gnunet-service-core_clients.c
   gnunet/src/core/gnunet-service-core_kx.c
   gnunet/src/core/gnunet-service-core_kx.h
   gnunet/src/core/gnunet-service-core_sessions.c
   gnunet/src/core/gnunet-service-core_sessions.h
   gnunet/src/include/gnunet_core_service.h
   gnunet/src/include/gnunet_protocols.h
Log:
towards fixing #3363: replacing old iteration API with new monitoring API for 
core (needs testing, gnunet-core incomplete)

Modified: gnunet/src/core/core.h
===================================================================
--- gnunet/src/core/core.h      2014-04-10 17:05:39 UTC (rev 33031)
+++ gnunet/src/core/core.h      2014-04-11 11:49:51 UTC (rev 33032)
@@ -62,7 +62,7 @@
 {
 
   /**
-   * Header with type GNUNET_MESSAGE_TYPE_CORE_INIT.
+   * Header with type #GNUNET_MESSAGE_TYPE_CORE_INIT.
    */
   struct GNUNET_MessageHeader header;
 
@@ -82,7 +82,7 @@
 {
 
   /**
-   * Header with type GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY
+   * Header with type #GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY
    */
   struct GNUNET_MessageHeader header;
 
@@ -106,7 +106,7 @@
 struct ConnectNotifyMessage
 {
   /**
-   * Header with type GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT
+   * Header with type #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT
    */
   struct GNUNET_MessageHeader header;
 
@@ -130,7 +130,7 @@
 struct DisconnectNotifyMessage
 {
   /**
-   * Header with type GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT.
+   * Header with type #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT.
    */
   struct GNUNET_MessageHeader header;
 
@@ -159,8 +159,8 @@
 struct NotifyTrafficMessage
 {
   /**
-   * Header with type GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND
-   * or GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND.
+   * Header with type #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND
+   * or #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND.
    */
   struct GNUNET_MessageHeader header;
 
@@ -291,6 +291,35 @@
 };
 
 
+/**
+ * Message sent by the service to monitor clients to notify them
+ * about a peer changing status.
+ */
+struct MonitorNotifyMessage
+{
+  /**
+   * Header with type #GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * New peer state, an `enum GNUNET_CORE_KxState` in NBO.
+   */
+  uint32_t state GNUNET_PACKED;
+
+  /**
+   * Identity of the peer.
+   */
+  struct GNUNET_PeerIdentity peer;
+
+  /**
+   * How long will we stay in this state (if nothing else happens)?
+   */
+  struct GNUNET_TIME_AbsoluteNBO timeout;
+
+};
+
+
 GNUNET_NETWORK_STRUCT_END
 #endif
 /* end of core.h */

Modified: gnunet/src/core/core_api_iterate_peers.c
===================================================================
--- gnunet/src/core/core_api_iterate_peers.c    2014-04-10 17:05:39 UTC (rev 
33031)
+++ gnunet/src/core/core_api_iterate_peers.c    2014-04-11 11:49:51 UTC (rev 
33032)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2009, 2010 Christian Grothoff (and other contributing authors)
+     (C) 2009-2014 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -19,7 +19,7 @@
 */
 
 /**
- * @file core/core_api_iterate_peers.c
+ * @file core/core_api_monitor_peers.c
  * @brief implementation of the peer_iterate function
  * @author Christian Grothoff
  * @author Nathan Evans
@@ -29,15 +29,23 @@
 #include "core.h"
 
 
-struct GNUNET_CORE_RequestContext
+/**
+ * Handle to a CORE monitoring operation.
+ */
+struct GNUNET_CORE_MonitorHandle
 {
+
   /**
+   * Our configuration.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
    * Our connection to the service.
    */
   struct GNUNET_CLIENT_Connection *client;
 
   /**
-
    * Handle for transmitting a request.
    */
   struct GNUNET_CLIENT_TransmitHandle *th;
@@ -45,140 +53,200 @@
   /**
    * Function called with the peer.
    */
-  GNUNET_CORE_ConnectEventHandler peer_cb;
+  GNUNET_CORE_MonitorCallback peer_cb;
 
   /**
-   * Peer to check for.
+   * Closure for @e peer_cb.
    */
-  struct GNUNET_PeerIdentity *peer;
+  void *peer_cb_cls;
 
-  /**
-   * Closure for peer_cb.
-   */
-  void *cb_cls;
-
 };
 
 
 /**
- * Receive reply from core service with information about a peer.
+ * Transmits the monitor request to the CORE service.
  *
- * @param cls our 'struct  GNUNET_CORE_RequestContext *'
+ * Function is called to notify a client about the socket begin ready
+ * to queue more data.  @a buf will be NULL and @a size zero if the
+ * socket was closed for writing in the meantime.
+ *
+ * @param cls closure, our `struct GNUNET_CORE_MonitorHandle *`
+ * @param size number of bytes available in @a buf
+ * @param buf where the callee should write the message
+ * @return number of bytes written to @a buf
+ */
+static size_t
+transmit_monitor_request (void *cls,
+                          size_t size,
+                          void *buf);
+
+
+/**
+ * Protocol error, reconnect to CORE service and notify
+ * client.
+ *
+ * @param mh monitoring session to reconnect to CORE
+ */
+static void
+reconnect (struct GNUNET_CORE_MonitorHandle *mh)
+{
+  GNUNET_CLIENT_disconnect (mh->client);
+  /* FIXME: use backoff? */
+  mh->client = GNUNET_CLIENT_connect ("core", mh->cfg);
+  GNUNET_assert (NULL != mh->client);
+  mh->th =
+    GNUNET_CLIENT_notify_transmit_ready (mh->client,
+                                         sizeof (struct GNUNET_MessageHeader),
+                                         GNUNET_TIME_UNIT_FOREVER_REL,
+                                         GNUNET_YES,
+                                         &transmit_monitor_request, mh);
+  /* notify callback about reconnect */
+  mh->peer_cb (mh->peer_cb_cls,
+               NULL,
+               GNUNET_CORE_KX_CORE_DISCONNECT,
+               GNUNET_TIME_UNIT_FOREVER_ABS);
+}
+
+
+/**
+ * Receive reply from CORE service with information about a peer.
+ *
+ * @param cls our `struct  GNUNET_CORE_MonitorHandle *`
  * @param msg NULL on error or last entry
  */
 static void
-receive_info (void *cls, const struct GNUNET_MessageHeader *msg)
+receive_info (void *cls,
+              const struct GNUNET_MessageHeader *msg)
 {
-  struct GNUNET_CORE_RequestContext *request_context = cls;
-  const struct ConnectNotifyMessage *connect_message;
+  struct GNUNET_CORE_MonitorHandle *mh = cls;
+  const struct MonitorNotifyMessage *mon_message;
   uint16_t msize;
 
-  /* Handle last message or error case, disconnect and clean up */
-  if ((msg == NULL) ||
-      ((ntohs (msg->type) == GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END) &&
-       (ntohs (msg->size) == sizeof (struct GNUNET_MessageHeader))))
+  if (NULL == msg)
   {
-    if (request_context->peer_cb != NULL)
-      request_context->peer_cb (request_context->cb_cls, NULL);
-    GNUNET_CLIENT_disconnect (request_context->client);
-    GNUNET_free (request_context);
+    reconnect (mh);
     return;
   }
-
   msize = ntohs (msg->size);
   /* Handle incorrect message type or size, disconnect and clean up */
-  if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT) ||
-      (msize < sizeof (struct ConnectNotifyMessage)))
+  if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY) ||
+      (sizeof (struct MonitorNotifyMessage) != msize))
   {
     GNUNET_break (0);
-    if (request_context->peer_cb != NULL)
-      request_context->peer_cb (request_context->cb_cls, NULL);
-    GNUNET_CLIENT_disconnect (request_context->client);
-    GNUNET_free (request_context);
+    reconnect (mh);
     return;
   }
-  connect_message = (const struct ConnectNotifyMessage *) msg;
-  if (msize != sizeof (struct ConnectNotifyMessage))
-  {
-    GNUNET_break (0);
-    if (request_context->peer_cb != NULL)
-      request_context->peer_cb (request_context->cb_cls, NULL);
-    GNUNET_CLIENT_disconnect (request_context->client);
-    GNUNET_free (request_context);
-    return;
-  }
-  /* Normal case */
-  if (request_context->peer_cb != NULL)
-    request_context->peer_cb (request_context->cb_cls, &connect_message->peer);
-  GNUNET_CLIENT_receive (request_context->client, &receive_info,
-                         request_context, GNUNET_TIME_UNIT_FOREVER_REL);
+  mon_message = (const struct MonitorNotifyMessage *) msg;
+  GNUNET_CLIENT_receive (mh->client,
+                         &receive_info, mh,
+                         GNUNET_TIME_UNIT_FOREVER_REL);
+  mh->peer_cb (mh->peer_cb_cls,
+               &mon_message->peer,
+               (enum GNUNET_CORE_KxState) ntohl (mon_message->state),
+               GNUNET_TIME_absolute_ntoh (mon_message->timeout));
 }
 
 
 /**
- * Function called to notify a client about the socket
- * begin ready to queue more data.  "buf" will be
- * NULL and "size" zero if the socket was closed for
- * writing in the meantime.
+ * Transmits the monitor request to the CORE service.
  *
- * @param cls closure, always NULL
- * @param size number of bytes available in buf
+ * Function is called to notify a client about the socket begin ready
+ * to queue more data.  @a buf will be NULL and @a size zero if the
+ * socket was closed for writing in the meantime.
+ *
+ * @param cls closure, our `struct GNUNET_CORE_MonitorHandle *`
+ * @param size number of bytes available in @a buf
  * @param buf where the callee should write the message
- * @return number of bytes written to buf
+ * @return number of bytes written to @a buf
  */
 static size_t
-transmit_request (void *cls, size_t size, void *buf)
+transmit_monitor_request (void *cls,
+                          size_t size,
+                          void *buf)
 {
+  struct GNUNET_CORE_MonitorHandle *mh = cls;
   struct GNUNET_MessageHeader *msg;
   int msize;
 
   msize = sizeof (struct GNUNET_MessageHeader);
-  if ((size < msize) || (buf == NULL))
+  if ((size < msize) || (NULL == buf))
+  {
+    reconnect (mh);
     return 0;
+  }
   msg = (struct GNUNET_MessageHeader *) buf;
   msg->size = htons (msize);
-  msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS);
-
+  msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS);
+  GNUNET_CLIENT_receive (mh->client,
+                         &receive_info, mh,
+                         GNUNET_TIME_UNIT_FOREVER_REL);
   return msize;
 }
 
 
 /**
- * Iterate over all currently connected peers.
- * Calls peer_cb with each connected peer, and then
- * once with NULL to indicate that all peers have
- * been handled.
+ * Monitor connectivity and KX status of all peers known to CORE.
+ * Calls @a peer_cb with the current status for each connected peer,
+ * and then once with NULL to indicate that all peers that are
+ * currently active have been handled.  After that, the iteration
+ * continues until it is cancelled.  Normal users of the CORE API are
+ * not expected to use this function.  It is different in that it
+ * truly lists all connections (including those where the KX is in
+ * progress), not just those relevant to the application.  This
+ * function is used by special applications for diagnostics.
  *
- * @param cfg configuration to use
+ * @param cfg configuration handle
  * @param peer_cb function to call with the peer information
- * @param cb_cls closure for @a peer_cb
- * @return #GNUNET_OK if iterating, #GNUNET_SYSERR on error
+ * @param peer_cb_cls closure for @a peer_cb
+ * @return NULL on error
  */
-int
-GNUNET_CORE_iterate_peers (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                           GNUNET_CORE_ConnectEventHandler peer_cb,
-                           void *cb_cls)
+struct GNUNET_CORE_MonitorHandle *
+GNUNET_CORE_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                           GNUNET_CORE_MonitorCallback peer_cb,
+                           void *peer_cb_cls)
 {
-  struct GNUNET_CORE_RequestContext *request_context;
+  struct GNUNET_CORE_MonitorHandle *mh;
   struct GNUNET_CLIENT_Connection *client;
 
+  GNUNET_assert (NULL != peer_cb);
   client = GNUNET_CLIENT_connect ("core", cfg);
-  if (client == NULL)
-    return GNUNET_SYSERR;
-  request_context = GNUNET_new (struct GNUNET_CORE_RequestContext);
-  request_context->client = client;
-  request_context->peer_cb = peer_cb;
-  request_context->cb_cls = cb_cls;
+  if (NULL == client)
+    return NULL;
+  mh = GNUNET_new (struct GNUNET_CORE_MonitorHandle);
+  mh->cfg = cfg;
+  mh->client = client;
+  mh->peer_cb = peer_cb;
+  mh->peer_cb_cls = peer_cb_cls;
+  mh->th =
+    GNUNET_CLIENT_notify_transmit_ready (client,
+                                         sizeof (struct GNUNET_MessageHeader),
+                                         GNUNET_TIME_UNIT_FOREVER_REL,
+                                         GNUNET_YES,
+                                         &transmit_monitor_request, mh);
+  return mh;
+}
 
-  request_context->th =
-      GNUNET_CLIENT_notify_transmit_ready (client,
-                                           sizeof (struct 
GNUNET_MessageHeader),
-                                           GNUNET_TIME_UNIT_FOREVER_REL,
-                                           GNUNET_YES, &transmit_request, 
NULL);
 
-  GNUNET_CLIENT_receive (client, &receive_info, request_context,
-                         GNUNET_TIME_UNIT_FOREVER_REL);
-  return GNUNET_OK;
+/**
+ * Stop monitoring CORE activity.
+ *
+ * @param mh monitor to stop
+ */
+void
+GNUNET_CORE_monitor_stop (struct GNUNET_CORE_MonitorHandle *mh)
+{
+  if (NULL != mh->th)
+  {
+    GNUNET_CLIENT_notify_transmit_ready_cancel (mh->th);
+    mh->th = NULL;
+  }
+  if (NULL != mh->client)
+  {
+    GNUNET_CLIENT_disconnect (mh->client);
+    mh->client = NULL;
+  }
+  GNUNET_free (mh);
 }
 
-/* end of core_api_iterate_peers.c */
+
+/* end of core_api_monitor_peers.c */

Modified: gnunet/src/core/gnunet-core.c
===================================================================
--- gnunet/src/core/gnunet-core.c       2014-04-10 17:05:39 UTC (rev 33031)
+++ gnunet/src/core/gnunet-core.c       2014-04-11 11:49:51 UTC (rev 33032)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2011, 2012 Christian Grothoff (and other contributing authors)
+     (C) 2011, 2012, 2014 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -24,14 +24,10 @@
  * @author Nathan Evans
  */
 #include "platform.h"
-#include "gnunet_crypto_lib.h"
-#include "gnunet_configuration_lib.h"
-#include "gnunet_getopt_lib.h"
-#include "gnunet_peerinfo_service.h"
-#include "gnunet_transport_service.h"
+#include "gnunet_util_lib.h"
 #include "gnunet_core_service.h"
-#include "gnunet_program_lib.h"
 
+
 /**
  * Option -m.
  */
@@ -40,11 +36,13 @@
 /**
  * Current number of connections in monitor mode
  */
-static int monitor_connections_counter;
+// static unsigned int monitor_connections_counter;
 
-static struct GNUNET_CORE_Handle *ch;
+/**
+ * Handle to the CORE monitor.
+ */
+static struct GNUNET_CORE_MonitorHandle *mh;
 
-static struct GNUNET_PeerIdentity my_id;
 
 /**
  * Task run in monitor mode when the user presses CTRL-C to abort.
@@ -57,143 +55,81 @@
 shutdown_task (void *cls,
                const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  if (NULL != ch)
+  if (NULL != mh)
   {
-    GNUNET_CORE_disconnect (ch);
-    ch = NULL;
+    GNUNET_CORE_monitor_stop (mh);
+    mh = NULL;
   }
 }
 
 
 /**
- * Callback for retrieving a list of connected peers.
- *
- * @param cls closure (unused)
- * @param peer peer identity this notification is about
- */
-static void
-connected_peer_callback (void *cls,
-                        const struct GNUNET_PeerIdentity *peer)
-{
-  if (NULL == peer)
-    return;
-  printf (_("Peer `%s'\n"),
-         GNUNET_i2s_full (peer));
-}
-
-
-static void
-monitor_notify_startup (void *cls,
-                       const struct GNUNET_PeerIdentity *my_identity)
-{
-  my_id = (*my_identity);
-}
-
-
-/**
  * Function called to notify core users that another
- * peer connected to us.
+ * peer changed its state with us.
  *
  * @param cls closure
- * @param peer the peer that connected
+ * @param peer the peer that changed state
+ * @param state new state of the peer
+ * @param timeout timeout for the new state
  */
 static void
-monitor_notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
+monitor_cb (void *cls,
+            const struct GNUNET_PeerIdentity *peer,
+            enum GNUNET_CORE_KxState state,
+            struct GNUNET_TIME_Absolute timeout)
 {
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get();
   const char *now_str;
 
-  if (0 != memcmp (&my_id, peer, sizeof (my_id)))
+  if ( (NULL == peer) &&
+       (GNUNET_NO == monitor_connections) )
   {
-    monitor_connections_counter ++;
-    now_str = GNUNET_STRINGS_absolute_time_to_string (now);
-    FPRINTF (stdout, _("%24s: %-17s %4s   (%u connections in total)\n"),
-             now_str,
-             _("Connected to"),
-             GNUNET_i2s (peer),
-             monitor_connections_counter);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
   }
+  now_str = GNUNET_STRINGS_absolute_time_to_string (now);
+  FPRINTF (stdout,
+           _("%24s: %-17s %d %4s\n"),
+           now_str,
+           "FIXME",
+           state,
+           GNUNET_i2s (peer));
 }
 
 
 /**
- * Function called to notify core users that another
- * peer disconnected from us.
- *
- * @param cls closure
- * @param peer the peer that disconnected
- */
-static void
-monitor_notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
-  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get();
-  const char *now_str;
-
-  if (0 != memcmp (&my_id, peer, sizeof (my_id)))
-  {
-    now_str = GNUNET_STRINGS_absolute_time_to_string (now);
-
-    GNUNET_assert (monitor_connections_counter > 0);
-    monitor_connections_counter--;
-    FPRINTF (stdout, _("%24s: %-17s %4s   (%u connections in total)\n"),
-             now_str,
-             _("Disconnected from"),
-             GNUNET_i2s (peer),
-             monitor_connections_counter);
-  }
-}
-
-/**
- * Function called with the result of the check if the 'transport'
+ * Function called with the result of the check if the CORE
  * service is running.
  *
  * @param cls closure with our configuration
- * @param result #GNUNET_YES if transport is running
+ * @param result #GNUNET_YES if CORE is running
  */
 static void
-testservice_task (void *cls, int result)
+testservice_task (void *cls,
+                  int result)
 {
   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
-  static const struct GNUNET_CORE_MessageHandler handlers[] = {
-    {NULL, 0, 0}
-  };
 
-  if (result != GNUNET_OK)
-    {
-      FPRINTF (stderr, _("Service `%s' is not running\n"), "core");
-      return;
-    }
-
-  if (GNUNET_NO == monitor_connections)
+  if (GNUNET_OK != result)
   {
-    if (GNUNET_OK != GNUNET_CORE_iterate_peers (cfg, &connected_peer_callback, 
NULL))
-    {
-      fprintf (stderr, ("Failed to connect to CORE service to iterate 
peers!\n"));
-      return;
-    }
+    FPRINTF (stderr, _("Service `%s' is not running\n"), "core");
+    return;
   }
-  else
+
+  mh = GNUNET_CORE_monitor_start (cfg,
+                                  &monitor_cb,
+                                  NULL);
+  if (NULL == mh)
   {
-    memset(&my_id, '\0', sizeof (my_id));
-    ch = GNUNET_CORE_connect (cfg, NULL,
-                              monitor_notify_startup,
-                              monitor_notify_connect,
-                              monitor_notify_disconnect,
-                              NULL, GNUNET_NO,
-                              NULL, GNUNET_NO,
-                              handlers);
-
-    if (NULL == ch)
-    {
-      GNUNET_SCHEDULER_add_now (shutdown_task, NULL);
-      fprintf (stderr, ("Failed to connect to CORE service!\n"));
-      return;
-    }
-    else
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, 
shutdown_task, NULL);
+    GNUNET_SCHEDULER_add_now (shutdown_task, NULL);
+    fprintf (stderr, ("Failed to connect to CORE service!\n"));
+    return;
   }
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+                                &shutdown_task, NULL);
 }
 
+
 /**
  * Main function that will be run by the scheduler.
  *
@@ -206,19 +142,21 @@
 run (void *cls, char *const *args, const char *cfgfile,
      const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
-  if (args[0] != NULL)
+  if (NULL != args[0])
   {
-    FPRINTF (stderr, _("Invalid command line argument `%s'\n"), args[0]);
+    FPRINTF (stderr,
+             _("Invalid command line argument `%s'\n"),
+             args[0]);
     return;
   }
-
-  GNUNET_CLIENT_service_test ("core", cfg, GNUNET_TIME_UNIT_SECONDS,
-      &testservice_task, (void *) cfg);
+  GNUNET_CLIENT_service_test ("core", cfg,
+                              GNUNET_TIME_UNIT_SECONDS,
+                              &testservice_task, (void *) cfg);
 }
 
 
 /**
- * The main function to obtain peer information.
+ * The main function to obtain peer information from CORE.
  *
  * @param argc number of arguments from the command line
  * @param argv command line arguments
@@ -237,19 +175,15 @@
 
   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
     return 2;
-
-
   res = GNUNET_PROGRAM_run (argc, argv, "gnunet-core",
-                      gettext_noop
-                      ("Print information about connected peers."),
-                      options, &run, NULL);
+                            gettext_noop
+                            ("Print information about connected peers."),
+                            options, &run, NULL);
 
   GNUNET_free ((void *) argv);
-
   if (GNUNET_OK == res)
     return 0;
-  else
-    return 1;
+  return 1;
 }
 
 /* end of gnunet-core.c */

Modified: gnunet/src/core/gnunet-service-core.c
===================================================================
--- gnunet/src/core/gnunet-service-core.c       2014-04-10 17:05:39 UTC (rev 
33031)
+++ gnunet/src/core/gnunet-service-core.c       2014-04-11 11:49:51 UTC (rev 
33032)
@@ -101,20 +101,21 @@
                                                &keyfile))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("Core service is lacking HOSTKEY configuration setting.  
Exiting.\n"));
+                _("Core service is lacking HOSTKEY configuration setting.  
Exiting.\n"));
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
   GSC_stats = GNUNET_STATISTICS_create ("core", GSC_cfg);
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+                                &shutdown_task,
                                 NULL);
   GNUNET_SERVER_suspend (server);
   GSC_TYPEMAP_init ();
   pk = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile);
   GNUNET_free (keyfile);
   GNUNET_assert (NULL != pk);
-  if ((GNUNET_OK != GSC_KX_init (pk)) ||
+  if ((GNUNET_OK != GSC_KX_init (pk,
+                                 server)) ||
       (GNUNET_OK != GSC_NEIGHBOURS_init ()))
   {
     GNUNET_SCHEDULER_shutdown ();
@@ -123,7 +124,8 @@
   GSC_SESSIONS_init ();
   GSC_CLIENTS_init (GSC_server);
   GNUNET_SERVER_resume (GSC_server);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Core service of `%4s' ready.\n"),
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              _("Core service of `%4s' ready.\n"),
               GNUNET_i2s (&GSC_my_identity));
 }
 
@@ -139,7 +141,8 @@
 main (int argc, char *const *argv)
 {
   return (GNUNET_OK ==
-          GNUNET_SERVICE_run (argc, argv, "core", GNUNET_SERVICE_OPTION_NONE,
+          GNUNET_SERVICE_run (argc, argv, "core",
+                              GNUNET_SERVICE_OPTION_NONE,
                               &run, NULL)) ? 0 : 1;
 }
 

Modified: gnunet/src/core/gnunet-service-core_clients.c
===================================================================
--- gnunet/src/core/gnunet-service-core_clients.c       2014-04-10 17:05:39 UTC 
(rev 33031)
+++ gnunet/src/core/gnunet-service-core_clients.c       2014-04-11 11:49:51 UTC 
(rev 33032)
@@ -600,11 +600,12 @@
  * @param client identification of the client
  */
 static void
-handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
+handle_client_disconnect (void *cls,
+                          struct GNUNET_SERVER_Client *client)
 {
   struct GSC_Client *c;
 
-  if (client == NULL)
+  if (NULL == client)
     return;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Client %p has disconnected from core service.\n", client);
@@ -840,8 +841,8 @@
   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
     {&handle_client_init, NULL,
      GNUNET_MESSAGE_TYPE_CORE_INIT, 0},
-    {&GSC_SESSIONS_handle_client_iterate_peers, NULL,
-     GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS,
+    {&GSC_KX_handle_client_monitor_peers, NULL,
+     GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS,
      sizeof (struct GNUNET_MessageHeader)},
     {&handle_client_send_request, NULL,
      GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST,
@@ -855,7 +856,8 @@
   client_mst = GNUNET_SERVER_mst_create (&client_tokenizer_callback, NULL);
   notifier =
       GNUNET_SERVER_notification_context_create (server, MAX_NOTIFY_QUEUE);
-  GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
+  GNUNET_SERVER_disconnect_notify (server,
+                                   &handle_client_disconnect, NULL);
   GNUNET_SERVER_add_handlers (server, handlers);
 }
 

Modified: gnunet/src/core/gnunet-service-core_kx.c
===================================================================
--- gnunet/src/core/gnunet-service-core_kx.c    2014-04-10 17:05:39 UTC (rev 
33031)
+++ gnunet/src/core/gnunet-service-core_kx.c    2014-04-11 11:49:51 UTC (rev 
33032)
@@ -237,50 +237,6 @@
 
 
 /**
- * State machine for our P2P encryption handshake.  Everyone starts in
- * "DOWN", if we receive the other peer's key (other peer initiated)
- * we start in state RECEIVED (since we will immediately send our
- * own); otherwise we start in SENT.  If we get back a PONG from
- * within either state, we move up to CONFIRMED (the PONG will always
- * be sent back encrypted with the key we sent to the other peer).
- */
-enum KxStateMachine
-{
-  /**
-   * No handshake yet.
-   */
-  KX_STATE_DOWN,
-
-  /**
-   * We've sent our session key.
-   */
-  KX_STATE_KEY_SENT,
-
-  /**
-   * We've received the other peers session key.
-   */
-  KX_STATE_KEY_RECEIVED,
-
-  /**
-   * The other peer has confirmed our session key + PING with a PONG
-   * message encrypted with his session key (which we got).  Key
-   * exchange is done.
-   */
-  KX_STATE_UP,
-
-  /**
-   * We're rekeying (or had a timeout), so we have sent the other peer
-   * our new ephemeral key, but we did not get a matching PONG yet.
-   * This is equivalent to being 'KX_STATE_KEY_RECEIVED', except that
-   * the session is marked as 'up' with sessions (as we don't want to
-   * drop and re-establish P2P connections simply due to rekeying).
-   */
-  KX_STATE_REKEY_SENT
-
-};
-
-
-/**
  * Information about the status of a key exchange with another peer.
  */
 struct GSC_KeyExchangeInfo
@@ -373,7 +329,7 @@
   /**
    * What is our connection status?
    */
-  enum KxStateMachine status;
+  enum GNUNET_CORE_KxState status;
 
 };
 
@@ -414,8 +370,59 @@
  */
 static GNUNET_SCHEDULER_TaskIdentifier rekey_task;
 
+/**
+ * Notification context for all monitors.
+ */
+static struct GNUNET_SERVER_NotificationContext *nc;
 
+
 /**
+ * Inform the given monitor about the KX state of
+ * the given peer.
+ *
+ * @param mc monitor to inform
+ * @param kx key exchange state to inform about
+ */
+static void
+monitor_notify (struct GNUNET_SERVER_Client *client,
+                struct GSC_KeyExchangeInfo *kx)
+{
+  struct MonitorNotifyMessage msg;
+
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
+  msg.header.size = htons (sizeof (msg));
+  msg.state = htonl ((uint32_t) kx->status);
+  msg.peer = kx->peer;
+  msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout);
+  GNUNET_SERVER_notification_context_unicast (nc,
+                                              client,
+                                              &msg.header,
+                                              GNUNET_NO);
+}
+
+
+/**
+ * Inform all monitors about the KX state of the given peer.
+ *
+ * @param kx key exchange state to inform about
+ */
+static void
+monitor_notify_all (struct GSC_KeyExchangeInfo *kx)
+{
+  struct MonitorNotifyMessage msg;
+
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
+  msg.header.size = htons (sizeof (msg));
+  msg.state = htonl ((uint32_t) kx->status);
+  msg.peer = kx->peer;
+  msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout);
+  GNUNET_SERVER_notification_context_broadcast (nc,
+                                                &msg.header,
+                                                GNUNET_NO);
+}
+
+
+/**
  * Derive an authentication key from "set key" information
  *
  * @param akey authentication key to derive
@@ -570,8 +577,9 @@
     GNUNET_break (0);
     return GNUNET_NO;
   }
-  if ( (kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP) &&
-       (kx->status != KX_STATE_REKEY_SENT) )
+  if ( (kx->status != GNUNET_CORE_KX_STATE_KEY_RECEIVED) &&
+       (kx->status != GNUNET_CORE_KX_STATE_UP) &&
+       (kx->status != GNUNET_CORE_KX_STATE_REKEY_SENT) )
   {
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
@@ -622,7 +630,7 @@
 
   kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
   kx->set_key_retry_frequency = GNUNET_TIME_STD_BACKOFF 
(kx->set_key_retry_frequency);
-  GNUNET_assert (KX_STATE_DOWN != kx->status);
+  GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
   send_key (kx);
 }
 
@@ -678,10 +686,14 @@
   GNUNET_CONTAINER_DLL_insert (kx_head,
                               kx_tail,
                               kx);
-  GNUNET_CRYPTO_hash (pid, sizeof (struct GNUNET_PeerIdentity), &h1);
-  GNUNET_CRYPTO_hash (&GSC_my_identity, sizeof (struct GNUNET_PeerIdentity), 
&h2);
-
-  kx->status = KX_STATE_KEY_SENT;
+  kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
+  monitor_notify_all (kx);
+  GNUNET_CRYPTO_hash (pid,
+                      sizeof (struct GNUNET_PeerIdentity),
+                      &h1);
+  GNUNET_CRYPTO_hash (&GSC_my_identity,
+                      sizeof (struct GNUNET_PeerIdentity),
+                      &h2);
   if (0 < GNUNET_CRYPTO_hash_cmp (&h1,
                                  &h2))
   {
@@ -722,6 +734,8 @@
     GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
     kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK;
   }
+  kx->status = GNUNET_CORE_KX_PEER_DISCONNECT;
+  monitor_notify_all (kx);
   GNUNET_CONTAINER_DLL_remove (kx_head,
                               kx_tail,
                               kx);
@@ -791,7 +805,7 @@
   struct GNUNET_TIME_Absolute start_t;
   struct GNUNET_TIME_Absolute end_t;
   struct GNUNET_TIME_Absolute now;
-  enum KxStateMachine sender_status;
+  enum GNUNET_CORE_KxState sender_status;
   uint16_t size;
 
   size = ntohs (msg->size);
@@ -802,9 +816,9 @@
   }
   m = (const struct EphemeralKeyMessage *) msg;
   end_t = GNUNET_TIME_absolute_ntoh (m->expiration_time);
-  if ( ( (KX_STATE_KEY_RECEIVED == kx->status) ||
-        (KX_STATE_UP == kx->status) ||
-        (KX_STATE_REKEY_SENT == kx->status) ) &&
+  if ( ( (GNUNET_CORE_KX_STATE_KEY_RECEIVED == kx->status) ||
+        (GNUNET_CORE_KX_STATE_UP == kx->status) ||
+        (GNUNET_CORE_KX_STATE_REKEY_SENT == kx->status) ) &&
        (end_t.abs_value_us <= kx->foreign_key_expires.abs_value_us) )
   {
     GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# old ephemeral keys 
ignored"),
@@ -862,18 +876,18 @@
                             GNUNET_NO);
 
   /* check if we still need to send the sender our key */
-  sender_status = (enum KxStateMachine) ntohl (m->sender_status);
+  sender_status = (enum GNUNET_CORE_KxState) ntohl (m->sender_status);
   switch (sender_status)
   {
-  case KX_STATE_DOWN:
+  case GNUNET_CORE_KX_STATE_DOWN:
     GNUNET_break_op (0);
     break;
-  case KX_STATE_KEY_SENT:
+  case GNUNET_CORE_KX_STATE_KEY_SENT:
     /* fine, need to send our key after updating our status, see below */
     break;
-  case KX_STATE_KEY_RECEIVED:
-  case KX_STATE_UP:
-  case KX_STATE_REKEY_SENT:
+  case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
+  case GNUNET_CORE_KX_STATE_UP:
+  case GNUNET_CORE_KX_STATE_REKEY_SENT:
     /* other peer already got our key */
     break;
   default:
@@ -883,35 +897,38 @@
   /* check if we need to confirm everything is fine via PING + PONG */
   switch (kx->status)
   {
-  case KX_STATE_DOWN:
+  case GNUNET_CORE_KX_STATE_DOWN:
     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task);
-    kx->status = KX_STATE_KEY_RECEIVED;
-    if (KX_STATE_KEY_SENT == sender_status)
+    kx->status = GNUNET_CORE_KX_STATE_KEY_RECEIVED;
+    monitor_notify_all (kx);
+    if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
       send_key (kx);
     send_ping (kx);
     break;
-  case KX_STATE_KEY_SENT:
+  case GNUNET_CORE_KX_STATE_KEY_SENT:
     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task);
-    kx->status = KX_STATE_KEY_RECEIVED;
-    if (KX_STATE_KEY_SENT == sender_status)
+    kx->status = GNUNET_CORE_KX_STATE_KEY_RECEIVED;
+    monitor_notify_all (kx);
+    if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
       send_key (kx);
     send_ping (kx);
     break;
-  case KX_STATE_KEY_RECEIVED:
+  case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task);
-    if (KX_STATE_KEY_SENT == sender_status)
+    if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
       send_key (kx);
     send_ping (kx);
     break;
-  case KX_STATE_UP:
-    kx->status = KX_STATE_REKEY_SENT;
-    if (KX_STATE_KEY_SENT == sender_status)
+  case GNUNET_CORE_KX_STATE_UP:
+    kx->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
+    monitor_notify_all (kx);
+    if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
       send_key (kx);
     /* we got a new key, need to reconfirm! */
     send_ping (kx);
     break;
-  case KX_STATE_REKEY_SENT:
-    if (KX_STATE_KEY_SENT == sender_status)
+  case GNUNET_CORE_KX_STATE_REKEY_SENT:
+    if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
       send_key (kx);
     /* we got a new key, need to reconfirm! */
     send_ping (kx);
@@ -950,9 +967,9 @@
   GNUNET_STATISTICS_update (GSC_stats,
                             gettext_noop ("# PING messages received"), 1,
                             GNUNET_NO);
-  if ( (kx->status != KX_STATE_KEY_RECEIVED) &&
-       (kx->status != KX_STATE_UP) &&
-       (kx->status != KX_STATE_REKEY_SENT))
+  if ( (kx->status != GNUNET_CORE_KX_STATE_KEY_RECEIVED) &&
+       (kx->status != GNUNET_CORE_KX_STATE_UP) &&
+       (kx->status != GNUNET_CORE_KX_STATE_REKEY_SENT))
   {
     /* ignore */
     GNUNET_STATISTICS_update (GSC_stats,
@@ -1029,7 +1046,8 @@
                               gettext_noop ("# sessions terminated by 
timeout"),
                               1, GNUNET_NO);
     GSC_SESSIONS_end (&kx->peer);
-    kx->status = KX_STATE_KEY_SENT;
+    kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
+    monitor_notify_all (kx);
     send_key (kx);
     return;
   }
@@ -1097,21 +1115,21 @@
                             GNUNET_NO);
   switch (kx->status)
   {
-  case KX_STATE_DOWN:
+  case GNUNET_CORE_KX_STATE_DOWN:
     GNUNET_STATISTICS_update (GSC_stats,
                              gettext_noop ("# PONG messages dropped 
(connection down)"), 1,
                              GNUNET_NO);
     return;
-  case KX_STATE_KEY_SENT:
+  case GNUNET_CORE_KX_STATE_KEY_SENT:
     GNUNET_STATISTICS_update (GSC_stats,
                              gettext_noop ("# PONG messages dropped (out of 
order)"), 1,
                              GNUNET_NO);
     return;
-  case KX_STATE_KEY_RECEIVED:
+  case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
     break;
-  case KX_STATE_UP:
+  case GNUNET_CORE_KX_STATE_UP:
     break;
-  case KX_STATE_REKEY_SENT:
+  case GNUNET_CORE_KX_STATE_REKEY_SENT:
     break;
   default:
     GNUNET_break (0);
@@ -1159,35 +1177,37 @@
   }
   switch (kx->status)
   {
-  case KX_STATE_DOWN:
+  case GNUNET_CORE_KX_STATE_DOWN:
     GNUNET_assert (0);           /* should be impossible */
     return;
-  case KX_STATE_KEY_SENT:
+  case GNUNET_CORE_KX_STATE_KEY_SENT:
     GNUNET_assert (0);           /* should be impossible */
     return;
-  case KX_STATE_KEY_RECEIVED:
+  case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
     GNUNET_STATISTICS_update (GSC_stats,
                               gettext_noop
                               ("# session keys confirmed via PONG"), 1,
                               GNUNET_NO);
-    kx->status = KX_STATE_UP;
+    kx->status = GNUNET_CORE_KX_STATE_UP;
+    monitor_notify_all (kx);
     GSC_SESSIONS_create (&kx->peer, kx);
     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task);
     update_timeout (kx);
     break;
-  case KX_STATE_UP:
+  case GNUNET_CORE_KX_STATE_UP:
     GNUNET_STATISTICS_update (GSC_stats,
                               gettext_noop
                               ("# timeouts prevented via PONG"), 1,
                               GNUNET_NO);
     update_timeout (kx);
     break;
-  case KX_STATE_REKEY_SENT:
+  case GNUNET_CORE_KX_STATE_REKEY_SENT:
     GNUNET_STATISTICS_update (GSC_stats,
                               gettext_noop
                               ("# rekey operations confirmed via PONG"), 1,
                               GNUNET_NO);
-    kx->status = KX_STATE_UP;
+    kx->status = GNUNET_CORE_KX_STATE_UP;
+    monitor_notify_all (kx);
     update_timeout (kx);
     break;
   default:
@@ -1205,7 +1225,7 @@
 static void
 send_key (struct GSC_KeyExchangeInfo *kx)
 {
-  GNUNET_assert (KX_STATE_DOWN != kx->status);
+  GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
   if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task)
   {
      GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
@@ -1321,7 +1341,7 @@
     return;
   }
   m = (const struct EncryptedMessage *) msg;
-  if (KX_STATE_UP != kx->status)
+  if (GNUNET_CORE_KX_STATE_UP != kx->status)
   {
     GNUNET_STATISTICS_update (GSC_stats,
                               gettext_noop
@@ -1343,7 +1363,8 @@
       GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
       kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK;
     }
-    kx->status = KX_STATE_KEY_SENT;
+    kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
+    monitor_notify_all (kx);
     send_key (kx);
     return;
   }
@@ -1473,7 +1494,7 @@
 {
   struct DeliverMessageContext *dmc = client;
 
-  if (KX_STATE_UP != dmc->kx->status)
+  if (GNUNET_CORE_KX_STATE_UP != dmc->kx->status)
   {
     GNUNET_STATISTICS_update (GSC_stats,
                               gettext_noop
@@ -1560,15 +1581,18 @@
   sign_ephemeral_key ();
   for (pos = kx_head; NULL != pos; pos = pos->next)
   {
-    if (KX_STATE_UP == pos->status)
+    if (GNUNET_CORE_KX_STATE_UP == pos->status)
     {
-      pos->status = KX_STATE_REKEY_SENT;
+      pos->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
+      monitor_notify_all (pos);
       derive_session_keys (pos);
     }
-    if (KX_STATE_DOWN == pos->status)
+    if (GNUNET_CORE_KX_STATE_DOWN == pos->status)
     {
-      pos->status = KX_STATE_KEY_SENT;
+      pos->status = GNUNET_CORE_KX_STATE_KEY_SENT;
+      monitor_notify_all (pos);
     }
+    monitor_notify_all (pos);
     send_key (pos);
   }
 }
@@ -1578,11 +1602,15 @@
  * Initialize KX subsystem.
  *
  * @param pk private key to use for the peer
+ * @param server the server of the CORE service
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
  */
 int
-GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
+GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk,
+             struct GNUNET_SERVER_Handle *server)
 {
+  nc = GNUNET_SERVER_notification_context_create (server,
+                                                  1);
   my_private_key = pk;
   GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
                                                  &GSC_my_identity.public_key);
@@ -1629,6 +1657,46 @@
     GNUNET_SERVER_mst_destroy (mst);
     mst = NULL;
   }
+  if (NULL != nc)
+  {
+    GNUNET_SERVER_notification_context_destroy (nc);
+    nc = NULL;
+  }
 }
 
+
+/**
+ * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request.  For this
+ * request type, the client does not have to have transmitted an INIT
+ * request.  All current peers are returned, regardless of which
+ * message types they accept.
+ *
+ * @param cls unused
+ * @param client client sending the iteration request
+ * @param message iteration request message
+ */
+void
+GSC_KX_handle_client_monitor_peers (void *cls,
+                                    struct GNUNET_SERVER_Client *client,
+                                    const struct GNUNET_MessageHeader *message)
+{
+  struct MonitorNotifyMessage done_msg;
+  struct GSC_KeyExchangeInfo *kx;
+
+  GNUNET_SERVER_notification_context_add (nc,
+                                          client);
+  for (kx = kx_head; NULL != kx; kx = kx->next)
+    monitor_notify (client, kx);
+  done_msg.header.size = htons (sizeof (struct MonitorNotifyMessage));
+  done_msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
+  done_msg.state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
+  memset (&done_msg.peer, 0, sizeof (struct GNUNET_PeerIdentity));
+  done_msg.timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
+  GNUNET_SERVER_notification_context_unicast (nc,
+                                              client,
+                                              &done_msg.header,
+                                              GNUNET_NO);
+}
+
+
 /* end of gnunet-service-core_kx.c */

Modified: gnunet/src/core/gnunet-service-core_kx.h
===================================================================
--- gnunet/src/core/gnunet-service-core_kx.h    2014-04-10 17:05:39 UTC (rev 
33031)
+++ gnunet/src/core/gnunet-service-core_kx.h    2014-04-11 11:49:51 UTC (rev 
33032)
@@ -118,10 +118,12 @@
  * Initialize KX subsystem.
  *
  * @param pk private key to use for the peer
+ * @param server the server of the CORE service
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
  */
 int
-GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk);
+GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk,
+             struct GNUNET_SERVER_Handle *server);
 
 
 /**
@@ -130,5 +132,22 @@
 void
 GSC_KX_done (void);
 
+
+/**
+ * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request.  For this
+ * request type, the client does not have to have transmitted an INIT
+ * request.  All current peers are returned, regardless of which
+ * message types they accept.
+ *
+ * @param cls unused
+ * @param client client sending the iteration request
+ * @param message iteration request message
+ */
+void
+GSC_KX_handle_client_monitor_peers (void *cls,
+                                    struct GNUNET_SERVER_Client *client,
+                                    const struct GNUNET_MessageHeader 
*message);
+
+
 #endif
 /* end of gnunet-service-core_kx.h */

Modified: gnunet/src/core/gnunet-service-core_sessions.c
===================================================================
--- gnunet/src/core/gnunet-service-core_sessions.c      2014-04-10 17:05:39 UTC 
(rev 33031)
+++ gnunet/src/core/gnunet-service-core_sessions.c      2014-04-11 11:49:51 UTC 
(rev 33032)
@@ -732,59 +732,6 @@
 
 
 /**
- * Helper function for #GSC_SESSIONS_handle_client_iterate_peers().
- *
- * @param cls the `struct GNUNET_SERVER_TransmitContext` to queue replies
- * @param key identity of the connected peer
- * @param value the `struct Neighbour` for the peer
- * @return #GNUNET_OK (continue to iterate)
- */
-static int
-queue_connect_message (void *cls,
-                       const struct GNUNET_PeerIdentity *key,
-                       void *value)
-{
-  struct GNUNET_SERVER_TransmitContext *tc = cls;
-  struct Session *session = value;
-  struct ConnectNotifyMessage cnm;
-
-  /* FIXME: code duplication with clients... */
-  cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
-  cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
-  cnm.reserved = htonl (0);
-  cnm.peer = session->peer;
-  GNUNET_SERVER_transmit_context_append_message (tc, &cnm.header);
-  return GNUNET_OK;
-}
-
-
-/**
- * Handle CORE_ITERATE_PEERS request. For this request type, the client
- * does not have to have transmitted an INIT request.  All current peers
- * are returned, regardless of which message types they accept.
- *
- * @param cls unused
- * @param client client sending the iteration request
- * @param message iteration request message
- */
-void
-GSC_SESSIONS_handle_client_iterate_peers (void *cls,
-                                          struct GNUNET_SERVER_Client *client,
-                                          const struct GNUNET_MessageHeader 
*message)
-{
-  struct GNUNET_MessageHeader done_msg;
-  struct GNUNET_SERVER_TransmitContext *tc;
-
-  tc = GNUNET_SERVER_transmit_context_create (client);
-  GNUNET_CONTAINER_multipeermap_iterate (sessions, &queue_connect_message, tc);
-  done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
-  done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END);
-  GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
-  GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
-}
-
-
-/**
  * We've received a typemap message from a peer, update ours.
  * Notifies clients about the session.
  *

Modified: gnunet/src/core/gnunet-service-core_sessions.h
===================================================================
--- gnunet/src/core/gnunet-service-core_sessions.h      2014-04-10 17:05:39 UTC 
(rev 33031)
+++ gnunet/src/core/gnunet-service-core_sessions.h      2014-04-11 11:49:51 UTC 
(rev 33032)
@@ -118,6 +118,7 @@
 void
 GSC_SESSIONS_notify_client_about_sessions (struct GSC_Client *client);
 
+
 /**
  * We've received a typemap message from a peer, update ours.
  * Notifies clients about the session.
@@ -144,22 +145,6 @@
 
 
 /**
- * Handle CORE_ITERATE_PEERS request.  For this request type, the client
- * does not have to have transmitted an INIT request.  All current peers
- * are returned, regardless of which message types they accept.
- *
- * @param cls unused
- * @param client client sending the iteration request
- * @param message iteration request message
- */
-void
-GSC_SESSIONS_handle_client_iterate_peers (void *cls,
-                                          struct GNUNET_SERVER_Client *client,
-                                          const struct GNUNET_MessageHeader
-                                          *message);
-
-
-/**
  * Initialize sessions subsystem.
  */
 void

Modified: gnunet/src/include/gnunet_core_service.h
===================================================================
--- gnunet/src/include/gnunet_core_service.h    2014-04-10 17:05:39 UTC (rev 
33031)
+++ gnunet/src/include/gnunet_core_service.h    2014-04-11 11:49:51 UTC (rev 
33032)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2009-2013 Christian Grothoff (and other contributing authors)
+     (C) 2009-2014 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -280,34 +280,135 @@
  * @param th handle that was returned by "notify_transmit_ready".
  */
 void
-GNUNET_CORE_notify_transmit_ready_cancel (struct GNUNET_CORE_TransmitHandle
-                                          *th);
+GNUNET_CORE_notify_transmit_ready_cancel (struct GNUNET_CORE_TransmitHandle 
*th);
 
 
 /**
- * Iterate over all connected peers.  Calls @a peer_cb with each
- * connected peer, and then once with NULL to indicate that all peers
- * have been handled.  Normal users of the CORE API are not expected
- * to use this function.  It is different in that it truly lists
- * all connections, not just those relevant to the application.  This
- * function is used by special applications for diagnostics.  This
- * function is NOT part of the 'versioned', 'official' API.
+ * Handle to a CORE monitoring operation.
+ */
+struct GNUNET_CORE_MonitorHandle;
+
+
+/**
+ * State machine for our P2P encryption handshake.  Everyone starts in
+ * #GNUNET_CORE_KX_STATE_DOWN, if we receive the other peer's key
+ * (other peer initiated) we start in state
+ * #GNUNET_CORE_KX_STATE_KEY_RECEIVED (since we will immediately send
+ * our own); otherwise we start in #GNUNET_CORE_KX_STATE_KEY_SENT.  If
+ * we get back a PONG from within either state, we move up to
+ * #GNUNET_CORE_KX_STATE_UP (the PONG will always be sent back
+ * encrypted with the key we sent to the other peer).  Eventually,
+ * we will try to rekey, for this we will enter
+ * #GNUNET_CORE_KX_STATE_REKEY_SENT until the rekey operation is
+ * confirmed by a PONG from the other peer.
+ */
+enum GNUNET_CORE_KxState
+{
+  /**
+   * No handshake yet.
+   */
+  GNUNET_CORE_KX_STATE_DOWN,
+
+  /**
+   * We've sent our session key.
+   */
+  GNUNET_CORE_KX_STATE_KEY_SENT,
+
+  /**
+   * We've received the other peers session key.
+   */
+  GNUNET_CORE_KX_STATE_KEY_RECEIVED,
+
+  /**
+   * The other peer has confirmed our session key + PING with a PONG
+   * message encrypted with his session key (which we got).  Key
+   * exchange is done.
+   */
+  GNUNET_CORE_KX_STATE_UP,
+
+  /**
+   * We're rekeying (or had a timeout), so we have sent the other peer
+   * our new ephemeral key, but we did not get a matching PONG yet.
+   * This is equivalent to being #GNUNET_CORE_KX_STATE_KEY_RECEIVED,
+   * except that the session is marked as 'up' with sessions (as we
+   * don't want to drop and re-establish P2P connections simply due to
+   * rekeying).
+   */
+  GNUNET_CORE_KX_STATE_REKEY_SENT,
+
+  /**
+   * Last state of a KX (when it is being terminated).  Set
+   * just before CORE frees the internal state for this peer.
+   */
+  GNUNET_CORE_KX_PEER_DISCONNECT,
+
+  /**
+   * This is not a state in a peer's state machine, but a special
+   * value used with the #GNUNET_CORE_MonitorCallback to indicate
+   * that we finished the initial iteration over the peers.
+   */
+  GNUNET_CORE_KX_ITERATION_FINISHED,
+
+  /**
+   * This is not a state in a peer's state machine, but a special
+   * value used with the #GNUNET_CORE_MonitorCallback to indicate
+   * that we lost the connection to the CORE service (and will try
+   * to reconnect).  If this happens, most likely the CORE service
+   * crashed and thus all connection state should be assumed lost.
+   */
+  GNUNET_CORE_KX_CORE_DISCONNECT
+
+};
+
+
+/**
+ * Function called by the monitor callback whenever
+ * a peer's connection status changes.
  *
- * FIXME: we should probably make it possible to 'cancel' the
- * operation...
+ * @param cls closure
+ * @param pid identity of the peer this update is about
+ * @param state current key exchange state of the peer
+ * @param timeout when does the current state expire
+ */
+typedef void
+(*GNUNET_CORE_MonitorCallback)(void *cls,
+                               const struct GNUNET_PeerIdentity *pid,
+                               enum GNUNET_CORE_KxState state,
+                               struct GNUNET_TIME_Absolute timeout);
+
+
+/**
+ * Monitor connectivity and KX status of all peers known to CORE.
+ * Calls @a peer_cb with the current status for each connected peer,
+ * and then once with NULL to indicate that all peers that are
+ * currently active have been handled.  After that, the iteration
+ * continues until it is cancelled.  Normal users of the CORE API are
+ * not expected to use this function.  It is different in that it
+ * truly lists all connections (including those where the KX is in
+ * progress), not just those relevant to the application.  This
+ * function is used by special applications for diagnostics.
  *
  * @param cfg configuration handle
  * @param peer_cb function to call with the peer information
- * @param cb_cls closure for @a peer_cb
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
+ * @param peer_cb_cls closure for @a peer_cb
+ * @return NULL on error
  */
-int
-GNUNET_CORE_iterate_peers (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                           GNUNET_CORE_ConnectEventHandler peer_cb,
-                           void *cb_cls);
+struct GNUNET_CORE_MonitorHandle *
+GNUNET_CORE_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                           GNUNET_CORE_MonitorCallback peer_cb,
+                           void *peer_cb_cls);
 
 
 /**
+ * Stop monitoring CORE activity.
+ *
+ * @param mh monitor to stop
+ */
+void
+GNUNET_CORE_monitor_stop (struct GNUNET_CORE_MonitorHandle *mh);
+
+
+/**
  * Check if the given peer is currently connected. This function is for special
  * cirumstances (GNUNET_TESTBED uses it), normal users of the CORE API are
  * expected to track which peers are connected based on the connect/disconnect

Modified: gnunet/src/include/gnunet_protocols.h
===================================================================
--- gnunet/src/include/gnunet_protocols.h       2014-04-10 17:05:39 UTC (rev 
33031)
+++ gnunet/src/include/gnunet_protocols.h       2014-04-11 11:49:51 UTC (rev 
33032)
@@ -334,14 +334,14 @@
 #define GNUNET_MESSAGE_TYPE_CORE_SEND 76
 
 /**
- * Request for peer iteration from CORE service.
+ * Request for connection monitoring from CORE service.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS 78
+#define GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS 78
 
 /**
- * Last reply from core to request for peer iteration from CORE service.
+ * Reply for monitor by CORE service.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END 79
+#define GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY 79
 
 /**
  * Encapsulation for an encrypted message between peers.




reply via email to

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