removing remenants of abstract unix domain socket handling, this finishes addressing...
[oweals/gnunet.git] / src / testbed / gnunet-service-testbed_peers.c
index 34c1bf085bffd129d158cade9d50719525a5254b..74aff7d470b94c9f0b3be34b943268b13e013865 100644 (file)
@@ -4,7 +4,7 @@
 
   GNUnet is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 2, or (at your
+  by the Free Software Foundation; either version 3, or (at your
   option) any later version.
 
   GNUnet is distributed in the hope that it will be useful, but
@@ -22,7 +22,7 @@
 /**
  * @file testbed/gnunet-service-testbed_peers.c
  * @brief implementation of TESTBED service that deals with peer management
- * @author Sree Harsha Totakura <sreeharsha@totakura.in> 
+ * @author Sree Harsha Totakura <sreeharsha@totakura.in>
  */
 
 #include "gnunet-service-testbed.h"
  */
 struct Peer **GST_peer_list;
 
+/**
+ * The current number of peers running locally under this controller
+ */
+unsigned int GST_num_local_peers;
+
 
 /**
  * Context information to manage peers' services
@@ -65,12 +70,12 @@ struct ManageServiceContext
    * The client which requested to manage the peer's service
    */
   struct GNUNET_SERVER_Client *client;
-  
+
   /**
    * The operation id of the associated request
    */
   uint64_t op_id;
-  
+
   /**
    * 1 if the service at the peer has to be started; 0 if it has to be stopped
    */
@@ -80,7 +85,7 @@ struct ManageServiceContext
    * Is this context expired?  Do not work on this context if it is set to
    * GNUNET_YES
    */
-  uint8_t expired;  
+  uint8_t expired;
 };
 
 
@@ -162,6 +167,8 @@ peer_list_add (struct Peer *peer)
     GST_array_grow_large_enough (GST_peer_list, GST_peer_list_size, peer->id);
   GNUNET_assert (NULL == GST_peer_list[peer->id]);
   GST_peer_list[peer->id] = peer;
+  if (GNUNET_NO == peer->is_remote)
+    GST_num_local_peers++;
 }
 
 
@@ -176,6 +183,8 @@ peer_list_remove (struct Peer *peer)
   unsigned int orig_size;
   uint32_t id;
 
+  if (GNUNET_NO == peer->is_remote)
+    GST_num_local_peers--;
   GST_peer_list[peer->id] = NULL;
   orig_size = GST_peer_list_size;
   while (GST_peer_list_size >= LIST_GROW_STEP)
@@ -334,7 +343,7 @@ GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
     return;
   }
   if (UINT32_MAX == peer_id)
-  {    
+  {
     GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
                                  "Cannot create peer with given ID");
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
@@ -721,7 +730,7 @@ GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client,
   reply = GNUNET_realloc (xconfig, msize);
   (void) memmove (&reply[1], reply, xc_size);
   reply->header.size = htons (msize);
-  reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION);
+  reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION);
   reply->peer_id = msg->peer_id;
   reply->operation_id = msg->operation_id;
   GNUNET_TESTING_peer_get_identity (GST_peer_list[peer_id]->details.local.peer,
@@ -770,11 +779,37 @@ GST_free_prcq ()
 }
 
 
+/**
+ * Update peer configuration
+ *
+ * @param peer the peer to update
+ * @param cfg the new configuration
+ * @return error message (freshly allocated); NULL upon success
+ */
+static char *
+update_peer_config (struct Peer *peer,
+                    struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  char *emsg;
+
+  GNUNET_TESTING_peer_destroy (peer->details.local.peer);
+  GNUNET_CONFIGURATION_destroy (peer->details.local.cfg);
+  peer->details.local.cfg = cfg;
+  emsg = NULL;  
+  peer->details.local.peer
+      = GNUNET_TESTING_peer_configure (GST_context->system,
+                                       peer->details.local.cfg, peer->id,
+                                       NULL /* Peer id */ ,
+                                       &emsg);
+  return emsg;
+}
+
+
 /**
  * Callback to inform whether the peer is running or stopped.
  *
  * @param cls the closure given to GNUNET_TESTING_peer_stop_async()
- * @param peer the respective peer whose status is being reported
+ * @param p the respective peer whose status is being reported
  * @param success GNUNET_YES if the peer is stopped; GNUNET_SYSERR upon any
  *          error
  */
@@ -784,35 +819,26 @@ prc_stop_cb (void *cls, struct GNUNET_TESTING_Peer *p, int success)
   struct PeerReconfigureContext *prc = cls;
   struct Peer *peer;
   char *emsg;
-  
+
   GNUNET_assert (VALID_PEER_ID (prc->peer_id));
   peer = GST_peer_list [prc->peer_id];
   GNUNET_assert (GNUNET_NO == peer->is_remote);
-  GNUNET_TESTING_peer_destroy (peer->details.local.peer);
-  GNUNET_CONFIGURATION_destroy (peer->details.local.cfg);
-  peer->details.local.cfg = prc->cfg;
+  emsg = update_peer_config (peer, prc->cfg);
   prc->cfg = NULL;
   prc->stopped = 1;
-  emsg = NULL;
-  peer->details.local.peer
-      = GNUNET_TESTING_peer_configure (GST_context->system,
-                                       peer->details.local.cfg, peer->id,
-                                       NULL /* Peer id */ ,
-                                       &emsg);
-  if (NULL == peer->details.local.peer)
+  if (NULL != emsg)
   {
     GST_send_operation_fail_msg (prc->client, prc->op_id, emsg);
     goto cleanup;
   }
   if (GNUNET_OK != start_peer (peer))
   {
-    
     GST_send_operation_fail_msg (prc->client, prc->op_id,
                                  "Failed to start reconfigured peer");
     goto cleanup;
   }
   GST_send_operation_success_msg (prc->client, prc->op_id);
-  
+
  cleanup:
   cleanup_prc (prc);
   return;
@@ -837,10 +863,11 @@ GST_handle_peer_reconfigure (void *cls, struct GNUNET_SERVER_Client *client,
   struct GNUNET_CONFIGURATION_Handle *cfg;
   struct ForwardedOperationContext *fopc;
   struct PeerReconfigureContext *prc;
+  char *emsg;
   uint64_t op_id;
   uint32_t peer_id;
   uint16_t msize;
-  
+
   msize = ntohs (message->size);
   if (msize <= sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage))
   {
@@ -898,19 +925,40 @@ GST_handle_peer_reconfigure (void *cls, struct GNUNET_SERVER_Client *client,
   cfg = GNUNET_TESTBED_extract_config_ (message);
   if (NULL == cfg)
   {
-    GNUNET_break (0);    
+    GNUNET_break (0);
     GST_send_operation_fail_msg (client, op_id, "Compression error");
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
   }
+  if (GNUNET_NO == peer->details.local.is_running)
+  {
+    emsg = update_peer_config (peer, cfg);
+    if (NULL != emsg)
+      GST_send_operation_fail_msg (client, op_id, emsg);
+    GST_send_operation_success_msg (client, op_id);
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    return;
+  }
   prc = GNUNET_malloc (sizeof (struct PeerReconfigureContext));
+  if (GNUNET_OK != 
+      GNUNET_TESTING_peer_stop_async (peer->details.local.peer, &prc_stop_cb,
+                                      prc))
+  {
+    GNUNET_assert (0 < GNUNET_asprintf (&emsg,
+                                        "Error trying to stop peer %u asynchronously\n", 
+                                        peer_id));
+    LOG (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
+    GST_send_operation_fail_msg (client, op_id, emsg);
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_free (prc);
+    return;
+  }
   prc->cfg = cfg;
   prc->peer_id = peer_id;
   prc->op_id = op_id;
-  prc->client = client;  
+  prc->client = client;
   GNUNET_SERVER_client_keep (client);
   GNUNET_CONTAINER_DLL_insert_tail (prc_head, prc_tail, prc);
-  GNUNET_TESTING_peer_stop_async (peer->details.local.peer, prc_stop_cb, prc);
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
 }
 
@@ -1023,8 +1071,8 @@ arm_ret_string (enum GNUNET_ARM_Result result)
  * @param result result of the operation
  */
 static void
-service_manage_result_cb (void *cls, 
-                          enum GNUNET_ARM_RequestStatus rs, 
+service_manage_result_cb (void *cls,
+                          enum GNUNET_ARM_RequestStatus rs,
                           const char *service, enum GNUNET_ARM_Result result)
 {
   struct ManageServiceContext *mctx = cls;
@@ -1063,7 +1111,7 @@ service_manage_result_cb (void *cls,
     goto ret;
   }
   /* service started successfully */
-  
+
  ret:
   if (NULL != emsg)
   {
@@ -1098,17 +1146,17 @@ GST_handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client,
   uint64_t op_id;
   uint32_t peer_id;
   uint16_t msize;
-  
+
 
   msize = ntohs (message->size);
   if (msize <= sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage))
   {
-    GNUNET_break_op (0);  
+    GNUNET_break_op (0);
     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
     return;
   }
   msg = (const struct GNUNET_TESTBED_ManagePeerServiceMessage *) message;
-  service = (const char *) &msg[1];  
+  service = (const char *) &msg[1];
   if ('\0' != service[msize - sizeof
                       (struct GNUNET_TESTBED_ManagePeerServiceMessage) - 1])
   {
@@ -1120,7 +1168,7 @@ GST_handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client,
   {
     GNUNET_break_op (0);
     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;    
+    return;
   }
   peer_id = ntohl (msg->peer_id);
   op_id = GNUNET_ntohll (msg->operation_id);
@@ -1161,6 +1209,11 @@ GST_handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client,
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
   }
+  if (GNUNET_NO == peer->details.local.is_running)
+  {
+    emsg = GNUNET_strdup ("Peer not running\n");
+    goto err_ret;
+  }
   if ((0 != peer->reference_cnt)
       && ( (0 == strcasecmp ("core", service))
            || (0 == strcasecmp ("transport", service)) )  )
@@ -1238,7 +1291,7 @@ GST_destroy_peers ()
   {
     peer = GST_peer_list[id];
     if (NULL == peer)
-      continue;    
+      continue;
     if (GNUNET_NO == peer->is_remote)
     {
       if (GNUNET_YES == peer->details.local.is_running)
@@ -1273,9 +1326,13 @@ shutdown_peers_timeout_cb (void *cls,
   GNUNET_assert (0 < hc->nslaves);
   hc->nslaves--;
   if (0 == hc->nslaves)
+  {
     GST_send_operation_fail_msg (fo_ctxt->client, fo_ctxt->operation_id,
                                  "Timeout at a slave controller");
-  GNUNET_TESTBED_forward_operation_msg_cancel_ (fo_ctxt->opc);  
+    GNUNET_free (hc);
+    hc = NULL;
+  }
+  GNUNET_TESTBED_forward_operation_msg_cancel_ (fo_ctxt->opc);
   GNUNET_SERVER_client_drop (fo_ctxt->client);
   GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fo_ctxt);
   GNUNET_free (fo_ctxt);
@@ -1296,14 +1353,14 @@ shutdown_peers_reply_cb (void *cls,
 {
   struct ForwardedOperationContext *fo_ctxt = cls;
   struct HandlerContext_ShutdownPeers *hc;
-  
+
   hc = fo_ctxt->cls;
   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != fo_ctxt->timeout_task);
   GNUNET_SCHEDULER_cancel (fo_ctxt->timeout_task);
   fo_ctxt->timeout_task = GNUNET_SCHEDULER_NO_TASK;
   GNUNET_assert (0 < hc->nslaves);
   hc->nslaves--;
-  if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS != 
+  if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS !=
       ntohs (msg->type))
     hc->timeout = GNUNET_YES;
   if (0 == hc->nslaves)
@@ -1313,6 +1370,8 @@ shutdown_peers_reply_cb (void *cls,
                                    "Timeout at a slave controller");
     else
       GST_send_operation_success_msg (fo_ctxt->client, fo_ctxt->operation_id);
+    GNUNET_free (hc);
+    hc = NULL;
   }
   GNUNET_SERVER_client_drop (fo_ctxt->client);
   GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fo_ctxt);
@@ -1383,5 +1442,5 @@ GST_handle_shutdown_peers (void *cls, struct GNUNET_SERVER_Client *client,
     GST_send_operation_success_msg (client, op_id);
     GNUNET_free (hc);
   }
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);  
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
 }