- manage services of peers (client API)
authorSree Harsha Totakura <totakura@in.tum.de>
Tue, 2 Apr 2013 13:31:20 +0000 (13:31 +0000)
committerSree Harsha Totakura <totakura@in.tum.de>
Tue, 2 Apr 2013 13:31:20 +0000 (13:31 +0000)
src/include/gnunet_protocols.h
src/testbed/testbed.h
src/testbed/testbed_api.c
src/testbed/testbed_api.h
src/testbed/testbed_api_peers.c
src/testbed/testbed_api_peers.h

index 0293c1c90a58c4147da0c53b97ea37b9c3650a29..a012a7c53af89ca8e32bc7e840e863fdf47a09f2 100644 (file)
@@ -1629,6 +1629,11 @@ extern "C"
  */
 #define GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS 483
 
+/**
+ * Message to start/stop a service of a peer
+ */
+#define GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE 484
+
 /**
  * Not really a message, but for careful checks on the testbed messages; Should
  * always be the maximum and never be used to send messages with this type
index c9692c088ab4cad35f1da7f11179e4ab2e17d137..82747de5c18e6f5ee626384497b872ef745d3351 100644 (file)
@@ -768,6 +768,37 @@ struct GNUNET_TESTBED_ShutdownPeersMessage
 };
 
 
+/**
+ * Message to start/stop services of a peer
+ */
+struct GNUNET_TESTBED_ManagePeerServiceMessage
+{
+  /**
+   * Type is GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique ID of the peer whose service has to be managed.
+   */
+  uint32_t peer_id GNUNET_PACKED;
+
+  /**
+   * Operation ID
+   */
+  uint64_t operation_id GNUNET_PACKED;
+
+  /**
+   * set this to 1 to start the service; 0 to stop the service
+   */
+  uint8_t start;
+  
+  /**
+   * The NULL-terminated name of the service to start/stop follows here
+   */
+};
+
+
 GNUNET_NETWORK_STRUCT_END
 #endif
 /* end of testbed.h */
index e85fbb8f1aca638556454dacbacabc8d5343deb3..95ff9e4325cf40229c4f4a1e81790f62efffd8c4 100644 (file)
@@ -178,11 +178,23 @@ struct ExpireOperationEntry
   const struct GNUNET_TESTBED_Operation *op;
 };
 
+
+/**
+ * DLL head for list of operations marked for expiry
+ */
 static struct ExpireOperationEntry *exop_head;
 
+/**
+ * DLL tail for list of operation marked for expiry
+ */
 static struct ExpireOperationEntry *exop_tail;
 
 
+/**
+ * Inserts an operation into the list of operations marked for expiry
+ *
+ * @param op the operation to insert
+ */
 static void
 exop_insert (struct GNUNET_TESTBED_Operation *op)
 {
@@ -194,6 +206,17 @@ exop_insert (struct GNUNET_TESTBED_Operation *op)
 }
 
 
+/**
+ * Checks if an operation is present in the list of operations marked for
+ * expiry.  If the operation is found, it and the tail of operations after it
+ * are removed from the list.
+ *
+ * @param op the operation to check
+ * @return GNUNET_NO if the operation is not present in the list; GNUNET_YES if
+ *           the operation is found in the list (the operation is then removed
+ *           from the list -- calling this function again with the same
+ *           paramenter will return GNUNET_NO)
+ */
 static int
 exop_check (const struct GNUNET_TESTBED_Operation *const op)
 {
@@ -337,6 +360,17 @@ handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
     GNUNET_TESTBED_cleanup_peers_ ();
   }
     break;
+  case OP_MANAGE_SERVICE:
+  {
+    struct ManageServiceData *data;
+
+    GNUNET_assert (NULL != (data = opc->data));
+    op_comp_cb = data->cb;
+    op_comp_cb_cls = data->cb_cls;
+    GNUNET_free (data);
+    opc->data = NULL;
+  }
+    break;
   default:
     GNUNET_assert (0);
   }
@@ -691,14 +725,14 @@ handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
     GNUNET_free (data);
     return GNUNET_YES;          /* We do not call controller callback for peer info */
   }
+  event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
+  event.op = opc->op;
+  event.op_cls = opc->op_cls;
+  event.details.operation_finished.emsg = emsg;
+  event.details.operation_finished.generic = NULL;
   if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
       (NULL != c->cc))
   {
-    event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
-    event.op = opc->op;
-    event.op_cls = opc->op_cls;
-    event.details.operation_finished.emsg = emsg;
-    event.details.operation_finished.generic = NULL;
     exop_insert (event.op);
     c->cc (c->cc_cls, &event);
     if (GNUNET_NO == exop_check (event.op))
@@ -755,6 +789,24 @@ handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
     opc->data = NULL;
   }
     break;
+  case OP_MANAGE_SERVICE:
+  {
+    struct ManageServiceData *data = opc->data;
+      GNUNET_TESTBED_OperationCompletionCallback cb;
+    void *cb_cls;
+
+    GNUNET_assert (NULL != data);
+    cb = data->cb;
+    cb_cls = data->cb_cls;
+    GNUNET_free (data);
+    opc->data = NULL;
+    exop_insert (event.op);
+    if (NULL != cb)
+      cb (cb_cls, opc->op, emsg);
+    /* You could have marked the operation as done by now */
+    GNUNET_break (GNUNET_NO == exop_check (event.op));
+  }
+    break;
   default:
     GNUNET_break (0);
   }
index 65e9efe361827178786c5158cfb7d8c2e24ef02b..c3b7027558a0600ab4da48718e8d6119c63fb14c 100644 (file)
@@ -90,7 +90,12 @@ enum OperationType
   /**
    * Stop and destroy all peers  
    */
-  OP_SHUTDOWN_PEERS
+  OP_SHUTDOWN_PEERS,
+
+  /**
+   * Start/stop service at a peer
+   */
+  OP_MANAGE_SERVICE
 };
 
 
index 8944ec7763cee8ac645db6df7799777e474331a2..25213131348eceb8490dcdb7fe2ff1eb0ae2a3d3 100644 (file)
@@ -774,5 +774,93 @@ GNUNET_TESTBED_overlay_connect (void *op_cls,
 }
 
 
+static void
+opstart_manage_service (void *cls)
+{
+  struct OperationContext *opc = cls;
+  struct GNUNET_TESTBED_ManagePeerServiceMessage *msg;
+  struct ManageServiceData *data;
+  
+  GNUNET_assert (NULL != (data = opc->data));  
+  msg = GNUNET_malloc (data->msize);
+  msg->header.size = htons (data->msize);
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE);
+  msg->peer_id = htonl (data->peer->unique_id);
+  msg->operation_id = GNUNET_htonll (opc->id);
+  msg->start = (uint8_t) data->start;
+  (void) memcpy (&msg[1], data->service_name, data->msize 
+                 - sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage));
+  GNUNET_free (data->service_name);
+  data->service_name = NULL;
+  opc->state = OPC_STATE_STARTED;
+  GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
+  GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
+}
+
+
+static void
+oprelease_manage_service (void *cls)
+{
+  struct OperationContext *opc = cls;
+  struct ManageServiceData *data;
+
+  data = opc->data;
+  switch (opc->state)
+  {
+  case OPC_STATE_STARTED:
+    GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
+    break;
+  case OPC_STATE_INIT:
+    GNUNET_assert (NULL != data);
+    GNUNET_free (data->service_name);
+    break;
+  case OPC_STATE_FINISHED:
+    break;
+  }
+  GNUNET_free_non_null (data);
+  GNUNET_free (opc);
+}
+
+
+struct GNUNET_TESTBED_Operation *
+GNUNET_TESTBED_peer_manage_service (void *op_cls,
+                                    struct GNUNET_TESTBED_Peer *peer,
+                                    const char *service_name,
+                                    GNUNET_TESTBED_OperationCompletionCallback cb,
+                                    void *cb_cls,
+                                    unsigned int start)
+{
+  struct ManageServiceData *data;
+  struct OperationContext *opc;
+  size_t msize;
+
+  GNUNET_assert (PS_STARTED == peer->state); /* peer is not running? */
+  msize = strlen (service_name) + 1;
+  msize += sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage);
+  if (GNUNET_SERVER_MAX_MESSAGE_SIZE < msize)
+    return NULL;
+  data = GNUNET_malloc (sizeof (struct ManageServiceData));
+  data->cb = cb;
+  data->cb_cls = cb_cls;
+  data->peer = peer;
+  data->service_name = GNUNET_strdup (service_name);
+  data->start = start;
+  data->msize = (uint16_t) msize;
+  opc = GNUNET_malloc (sizeof (struct OperationContext));
+  opc->data = data;
+  opc->c = peer->controller;
+  opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
+  opc->type = OP_MANAGE_SERVICE;
+  opc->op_cls = op_cls;
+  opc->op =
+      GNUNET_TESTBED_operation_create_ (opc, &opstart_manage_service,
+                                        &oprelease_manage_service);
+  GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
+                                          opc->op);
+  GNUNET_TESTBED_operation_begin_wait_ (opc->op);
+  return opc->op;
+}
+
+
 
 /* end of testbed_api_peers.c */
index 49f8756077beb21f890582fc68322d0b79a26681..96b7180269bb69297849e596985981dd33428589 100644 (file)
@@ -246,6 +246,22 @@ struct OverlayConnectData
 };
 
 
+struct ManageServiceData {
+  GNUNET_TESTBED_OperationCompletionCallback cb;
+  
+  void *cb_cls;
+  
+  struct GNUNET_TESTBED_Peer *peer;
+
+  char *service_name;
+  
+  unsigned int start;
+
+  uint16_t msize;
+
+};
+
+
 /**
  * Generate PeerGetConfigurationMessage
  *