-fix warning
[oweals/gnunet.git] / src / sensor / gnunet-sensor-profiler.c
index 4cd6b808d450f9c0b64584c2a5ce524658af5c8b..21574774d881cf98ff798e79f59834885520c553 100644 (file)
@@ -57,35 +57,18 @@ struct PeerInfo
    */
   int index;
 
-};
-
-struct DisconnectionContext
-{
-
-  struct DisconnectionContext *prev;
-
-  struct DisconnectionContext *next;
-
-  struct PeerInfo *p1;
-
-  struct PeerInfo *p2;
-
-  struct GNUNET_TESTBED_Operation *p1_transport_op;
-
-  struct GNUNET_TRANSPORT_Blacklist *blacklist;
-
-};
-
-struct ConnectionContext
-{
-
-  struct PeerInfo *p1;
+  /**
+   * TESTBED operation used to connect to statistics service
+   */
+  struct GNUNET_TESTBED_Operation *statistics_op;
 
-  struct PeerInfo *p2;
+  /**
+   * Handle to the peer's statistics service
+   */
+  struct GNUNET_STATISTICS_Handle *statistics;
 
 };
 
-
 /**
  * Name of the configuration file used
  */
@@ -126,6 +109,11 @@ static unsigned int sensors_interval = 0;
  */
 static char *topology_file;
 
+/**
+ * Number of peers to simulate anomalies on (Option -a)
+ */
+static unsigned int anomalous_peers = 0;
+
 /**
  * Array of peer info for all peers
  */
@@ -171,16 +159,6 @@ static unsigned int sensor_names_size = 0;
  */
 static GNUNET_SCHEDULER_TaskIdentifier delayed_task = GNUNET_SCHEDULER_NO_TASK;
 
-/**
- * Head of list of disconnection contexts
- */
-static struct DisconnectionContext *dc_head;
-
-/*
- * Tail of list of disconnection contexts
- */
-static struct DisconnectionContext *dc_tail;
-
 
 /**
  * Copy directory recursively
@@ -193,33 +171,6 @@ static int
 copy_dir (const char *src, const char *dst);
 
 
-/**
- * Prompt the user to disconnect two peers
- */
-static void
-prompt_peer_disconnection ();
-
-
-/**
- * Destroy a DisconnectionContext struct
- */
-static void
-destroy_dc (struct DisconnectionContext *dc)
-{
-  if (NULL != dc->blacklist)
-  {
-    GNUNET_TRANSPORT_blacklist_cancel (dc->blacklist);
-    dc->blacklist = NULL;
-  }
-  if (NULL != dc->p1_transport_op)
-  {
-    GNUNET_TESTBED_operation_done (dc->p1_transport_op);
-    dc->p1_transport_op = NULL;
-  }
-  GNUNET_free (dc);
-}
-
-
 /**
  * Do clean up and shutdown scheduler
  */
@@ -227,7 +178,6 @@ static void
 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   int i;
-  struct DisconnectionContext *dc;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down.\n");
   if (GNUNET_SCHEDULER_NO_TASK != delayed_task)
@@ -235,12 +185,13 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     GNUNET_SCHEDULER_cancel (delayed_task);
     delayed_task = GNUNET_SCHEDULER_NO_TASK;
   }
-  dc = dc_head;
-  while (NULL != dc)
+  for (i = 0; i < num_peers; i++)
   {
-    GNUNET_CONTAINER_DLL_remove (dc_head, dc_tail, dc);
-    destroy_dc (dc);
-    dc = dc_head;
+    if (NULL != all_peers_info[i].statistics_op)
+    {
+      GNUNET_TESTBED_operation_done (all_peers_info[i].statistics_op);
+      all_peers_info[i].statistics_op = NULL;
+    }
   }
   if (NULL != peerstore_op)
   {
@@ -267,207 +218,6 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 }
 
 
-/*****************************************************************************/
-/****************************** DISCONNECT PEERS *****************************/
-/*****************************************************************************/
-
-
-/**
- * Function to call with result of the TRANSPORT try disconnect request.
- *
- * @param cls closure
- * @param result #GNUNET_OK if message was transmitted to transport service
- *               #GNUNET_SYSERR if message was not transmitted to transport service
- */
-static void
-transport_disconnect_cb (void *cls, const int result)
-{
-  struct DisconnectionContext *dc = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Peer disconnection request sent: %d,%d\n", dc->p1->index,
-              dc->p2->index);
-}
-
-
-/**
- * Callback to be called when transport service connect operation is completed
- *
- * @param cls the callback closure from functions generating an operation
- * @param op the operation that has been finished
- * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
- * @param emsg error message in case the operation has failed; will be NULL if
- *          operation has executed successfully.
- */
-static void
-transport_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
-                      void *ca_result, const char *emsg)
-{
-  struct DisconnectionContext *dc = cls;
-  struct GNUNET_TRANSPORT_Handle *transport = ca_result;
-
-  if (NULL != emsg)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ERROR: %s.\n", emsg);
-    GNUNET_assert (0);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "transport_connect_cb().\n");
-  GNUNET_TRANSPORT_try_disconnect (transport, &dc->p2->peer_id,
-                                   &transport_disconnect_cb, dc);
-}
-
-
-/**
- * Callback from TRANSPORT service to ask if the given peer ID is blacklisted.
- *
- * @param cls closure, DisconnectionContext
- * @param pid peer to approve or disapproave
- * @return #GNUNET_OK if the connection is allowed, #GNUNET_SYSERR if not
- */
-static int
-blacklist_cb (void *cls, const struct GNUNET_PeerIdentity *pid)
-{
-  struct DisconnectionContext *dc = cls;
-
-  if (0 == GNUNET_CRYPTO_cmp_peer_identity (&dc->p2->peer_id, pid))
-    return GNUNET_SYSERR;
-  return GNUNET_OK;
-}
-
-
-/**
- * Adapter function called to establish a connection to transport service.
- *
- * @param cls closure
- * @param cfg configuration of the peer to connect to; will be available until
- *          GNUNET_TESTBED_operation_done() is called on the operation returned
- *          from GNUNET_TESTBED_service_connect()
- * @return service handle to return in 'op_result', NULL on error
- */
-static void *
-transport_connect_adapter (void *cls,
-                           const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  struct DisconnectionContext *dc = cls;
-  struct GNUNET_TRANSPORT_Handle *transport;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "transport_connect_adapter().\n");
-  dc->blacklist = GNUNET_TRANSPORT_blacklist (cfg, &blacklist_cb, dc);
-  GNUNET_assert (NULL != dc->blacklist);
-  transport = GNUNET_TRANSPORT_connect (cfg, NULL, NULL, NULL, NULL, NULL);
-  GNUNET_assert (NULL != transport);
-  return transport;
-}
-
-
-/**
- * Adapter function called to destroy a connection to transport service.
- *
- * @param cls closure
- * @param op_result service handle returned from the connect adapter
- */
-static void
-transport_disconnect_adapter (void *cls, void *op_result)
-{
-  struct GNUNET_TRANSPORT_Handle *transport = op_result;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "transport_disconnect_adapter().\n");
-  GNUNET_TRANSPORT_disconnect (transport);
-}
-
-
-/**
- * Kill any connection between two peers. Has no effect if the peers are not
- * connected.
- */
-static void
-disconnect_peers (struct PeerInfo *p1, struct PeerInfo *p2)
-{
-  struct DisconnectionContext *dc;
-
-  GNUNET_assert (p1 != p2);
-  dc = GNUNET_new (struct DisconnectionContext);
-
-  dc->p1 = p1;
-  dc->p2 = p2;
-  GNUNET_CONTAINER_DLL_insert (dc_head, dc_tail, dc);
-  dc->p1_transport_op =
-      GNUNET_TESTBED_service_connect (NULL, p1->testbed_peer, "transport",
-                                      &transport_connect_cb, dc,
-                                      &transport_connect_adapter,
-                                      &transport_disconnect_adapter, dc);
-}
-
-
-/*****************************************************************************/
-/**************************** END DISCONNECT PEERS ***************************/
-/*****************************************************************************/
-
-/*****************************************************************************/
-/******************************* CONNECT PEERS *******************************/
-/*****************************************************************************/
-
-/**
- * Callback to be called when overlay connection operation is completed
- *
- * @param cls the callback closure from functions generating an operation
- * @param op the operation that has been finished
- * @param emsg error message in case the operation has failed; will be NULL if
- *          operation has executed successfully.
- */
-static void
-overlay_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
-                      const char *emsg)
-{
-  struct ConnectionContext *cc = cls;
-
-  if (NULL != emsg)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ERROR: %s.\n", emsg);
-    GNUNET_assert (0);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer connection request sent: %d,%d\n",
-              cc->p1->index, cc->p2->index);
-  GNUNET_free (cc);
-  GNUNET_TESTBED_operation_done (op);
-}
-
-
-/**
- * Connect two peers together
- */
-static void
-connect_peers (struct PeerInfo *p1, struct PeerInfo *p2)
-{
-  struct DisconnectionContext *dc;
-  struct ConnectionContext *cc;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connect_peers()\n");
-  /* Check if we have a disconnection request before */
-  dc = dc_head;
-  while (NULL != dc)
-  {
-    if ((dc->p1 == p1 && dc->p2 == p2) || (dc->p1 == p2 && dc->p2 == p1))
-      break;
-    dc = dc_head->next;
-  }
-  if (NULL != dc)
-  {
-    GNUNET_CONTAINER_DLL_remove (dc_head, dc_tail, dc);
-    destroy_dc (dc);
-  }
-  /* Connect peers using testbed */
-  cc = GNUNET_new (struct ConnectionContext);
-  cc->p1 = p1;
-  cc->p2 = p2;
-  GNUNET_TESTBED_overlay_connect (cc, &overlay_connect_cb, cc,
-                                  p1->testbed_peer, p2->testbed_peer);
-}
-
-/*****************************************************************************/
-/****************************** END CONNECT PEERS ****************************/
-/*****************************************************************************/
-
 /**
  * Function called with each file/folder inside a directory that is being copied.
  *
@@ -552,8 +302,8 @@ sensor_dir_scanner (void *cls, const char *filename)
                    GNUNET_CONFIGURATION_parse (sensor_cfg, filename));
     GNUNET_CONFIGURATION_set_value_string (sensor_cfg, file_basename,
                                            "COLLECTION_POINT",
-                                           GNUNET_i2s_full (&all_peers_info[0].
-                                                            peer_id));
+                                           GNUNET_i2s_full (&all_peers_info
+                                                            [0].peer_id));
     if (sensors_interval > 0)
     {
       GNUNET_CONFIGURATION_set_value_number (sensor_cfg, file_basename,
@@ -615,8 +365,9 @@ dashboard_started (void *cls, struct GNUNET_TESTBED_Operation *op,
  * @return #GNUNET_YES to continue iterating, #GNUNET_NO to stop
  */
 static int
-peerstore_watch_cb (void *cls, struct GNUNET_PEERSTORE_Record *record,
-                    char *emsg)
+peerstore_watch_cb (void *cls,
+                    const struct GNUNET_PEERSTORE_Record *record,
+                    const char *emsg)
 {
   struct PeerInfo *peer = cls;
   struct GNUNET_SENSOR_DashboardAnomalyEntry *anomaly;
@@ -713,61 +464,65 @@ peerstore_disconnect_adapter (void *cls, void *op_result)
 
 
 /**
- * Prompty the user to reconnect two peers
+ * Callback to be called when statistics service connect operation is completed
+ *
+ * @param cls the callback closure from functions generating an operation
+ * @param op the operation that has been finished
+ * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
+ * @param emsg error message in case the operation has failed; will be NULL if
+ *          operation has executed successfully.
  */
 static void
-prompt_peer_reconnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+statistics_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
+                      void *ca_result, const char *emsg)
 {
-  int p1;
-  int p2;
-  char line[10];
+  struct PeerInfo *peer = cls;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connect peers (e.g. '0,2') or empty line to execute:\n");
-  if (NULL == fgets (line, sizeof (line), stdin) || 1 == strlen (line))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Continuing.\n");
-    return;
-  }
-  if (2 != sscanf (line, "%d,%d", &p1, &p2) || p1 >= num_peers ||
-      p2 >= num_peers || p1 < 0 || p2 < 0 || p1 == p2)
+  if (NULL != emsg)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Invalid input.\n");
-    prompt_peer_reconnection (NULL, NULL);
-    return;
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ERROR: %s.\n", emsg);
+    GNUNET_assert (0);
   }
-  connect_peers (&all_peers_info[p1], &all_peers_info[p2]);
-  prompt_peer_reconnection (NULL, NULL);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+      "Connected to statistics service on peer `%s'.\n", GNUNET_i2s (&peer->peer_id));
+  GNUNET_STATISTICS_set (peer->statistics, "# peers connected", 0, GNUNET_NO);
 }
 
 
 /**
- * Prompt the user to disconnect two peers
+ * Adapter function called to establish a connection to statistics service.
+ *
+ * @param cls closure
+ * @param cfg configuration of the peer to connect to; will be available until
+ *          GNUNET_TESTBED_operation_done() is called on the operation returned
+ *          from GNUNET_TESTBED_service_connect()
+ * @return service handle to return in 'op_result', NULL on error
+ */
+static void *
+statistics_connect_adapter (void *cls,
+                           const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct PeerInfo *peer = cls;
+
+  peer->statistics = GNUNET_STATISTICS_create ("core", cfg);
+  GNUNET_assert (NULL != peer->statistics);
+  return peer->statistics;
+}
+
+
+/**
+ * Adapter function called to destroy a connection to statistics service.
+ *
+ * @param cls closure
+ * @param op_result service handle returned from the connect adapter
  */
 static void
-prompt_peer_disconnection ()
+statistics_disconnect_adapter (void *cls, void *op_result)
 {
-  int p1;
-  int p2;
-  char line[10];
+  struct PeerInfo *peer = cls;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Disconnect peers (e.g. '0,2') or empty line to execute:\n");
-  if (NULL == fgets (line, sizeof (line), stdin) || 1 == strlen (line))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Will prompt for reconnection in 1 min.\n");
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 1) ,&prompt_peer_reconnection, NULL);
-    return;
-  }
-  if (2 != sscanf (line, "%d,%d", &p1, &p2) || p1 >= num_peers ||
-      p2 >= num_peers || p1 < 0 || p2 < 0 || p1 == p2)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Invalid input.\n");
-    prompt_peer_disconnection ();
-    return;
-  }
-  disconnect_peers (&all_peers_info[p1], &all_peers_info[p2]);
-  prompt_peer_disconnection ();
+  GNUNET_STATISTICS_destroy (peer->statistics, GNUNET_NO);
+  peer->statistics = NULL;
 }
 
 
@@ -777,10 +532,33 @@ prompt_peer_disconnection ()
 static void
 simulate_anomalies (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
+  int i;
+  uint32_t an_peer;
+  struct GNUNET_TIME_Relative shutdown_delay;
+
   delayed_task = GNUNET_SCHEDULER_NO_TASK;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Training period over, simulating anomalies now.\n");
-  prompt_peer_disconnection ();
+  GNUNET_assert (anomalous_peers <= num_peers);
+  for (i = 0; i < anomalous_peers; i++)
+  {
+    an_peer = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, num_peers);
+    if (NULL != all_peers_info[an_peer].statistics_op)
+    {
+      i--;
+      continue;
+    }
+    all_peers_info[an_peer].statistics_op =
+    GNUNET_TESTBED_service_connect (NULL, all_peers_info[an_peer].testbed_peer,
+                                    "statistics", &statistics_connect_cb,
+                                    &all_peers_info[an_peer], &statistics_connect_adapter,
+                                    &statistics_disconnect_adapter, &all_peers_info[an_peer]);
+  }
+  shutdown_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, num_peers * 6);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down in %s\n",
+      GNUNET_STRINGS_relative_time_to_string (shutdown_delay, GNUNET_NO));
+  GNUNET_SCHEDULER_cancel (shutdown_task);
+  shutdown_task = GNUNET_SCHEDULER_add_delayed (shutdown_delay, &do_shutdown, NULL);
 }
 
 
@@ -924,7 +702,6 @@ test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num,
               "%d peers started. %d links succeeded. %d links failed.\n",
               num_peers, links_succeeded, links_failed);
   GNUNET_assert (num == num_peers);
-  GNUNET_assert (0 == links_failed);
   /* Collect peer information */
   all_peers_info = GNUNET_new_array (num_peers, struct PeerInfo);
 
@@ -1009,6 +786,9 @@ main (int argc, char *const *argv)
     {'i', "sensors-interval", "INTERVAL",
      gettext_noop ("Change the interval of running sensors to given value"),
      GNUNET_YES, &GNUNET_GETOPT_set_uint, &sensors_interval},
+    {'a', "anomalous-peers", "COUNT",
+     gettext_noop ("Number of peers to simulate anomalies on"), GNUNET_YES,
+     &GNUNET_GETOPT_set_uint, &anomalous_peers},
     GNUNET_GETOPT_OPTION_END
   };