-testbed controller startup
authorSree Harsha Totakura <totakura@in.tum.de>
Wed, 13 Jun 2012 10:56:34 +0000 (10:56 +0000)
committerSree Harsha Totakura <totakura@in.tum.de>
Wed, 13 Jun 2012 10:56:34 +0000 (10:56 +0000)
src/include/gnunet_protocols.h
src/testbed/testbed_api.c
src/testbed/testbed_api_hosts.c
src/testbed/testbed_api_hosts.h

index b194cf6c46b398ccf8f656eca8737d0bf8c0a14c..e5f303f5d9a64302c2005ffecf4285c5e7fd49d2 100644 (file)
@@ -1403,6 +1403,12 @@ extern "C"
  */
 #define GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG 478
 
+/**
+ * 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
+ */
+#define GNUNET_MESSAGE_TYPE_TESTBED_MAX 479
+
 
 /**
  *  Next available: 500
index 51680812b4637b32eae628355431bf1890b448d4..f12ed64fc83c49bd0d716331474529bcbf849672 100644 (file)
 #include "gnunet_transport_service.h"
 #include "gnunet_hello_lib.h"
 
+#include "testbed.h"
+#include "testbed_api_hosts.h"
 
 
+#define LOG(kind, ...)                          \
+  GNUNET_log_from (kind, "testbed-api", __VA_ARGS__);
+
+
+/**
+ * The message queue for sending messages to the controller service
+ */
+struct MessageQueue
+{
+  /**
+   * The message to be sent
+   */
+  struct GNUNET_MessageHeader *msg;
+
+  /**
+   * next pointer for DLL
+   */
+  struct MessageQueue *next;
+  
+  /**
+   * prev pointer for DLL
+   */
+  struct MessageQueue *prev;
+};
+
+
+/**
+ * Handle to interact with a GNUnet testbed controller.  Each
+ * controller has at least one master handle which is created when the
+ * controller is created; this master handle interacts with the
+ * controller process, destroying it destroys the controller (by
+ * closing stdin of the controller process).  Additionally,
+ * controllers can interact with each other (in a P2P fashion); those
+ * links are established via TCP/IP on the controller's service port.
+ */
+struct GNUNET_TESTBED_Controller
+{
+
+  /**
+   * The host where the controller is running
+   */
+  const struct GNUNET_TESTBED_Host *host;
+
+  /**
+   * The helper handle
+   */
+  struct GNUNET_HELPER_Handle *h;
+
+  /**
+   * The controller callback
+   */
+  GNUNET_TESTBED_ControllerCallback cc;
+
+  /**
+   * The closure for controller callback
+   */
+  void *cc_cls;
+
+  /**
+   * The configuration to use while connecting to controller
+   */
+  struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * The client connection handle to the controller service
+   */
+  struct GNUNET_CLIENT_Connection *client;
+  
+  /**
+   * The head of the message queue
+   */
+  struct MessageQueue *mq_head;
+
+  /**
+   * The tail of the message queue
+   */
+  struct MessageQueue *mq_tail;
+
+  /**
+   * The client transmit handle
+   */
+  struct GNUNET_CLIENT_TransmitHandle *th;
+
+  /**
+   * The controller event mask
+   */
+  uint64_t event_mask;
+};
+
+
+/**
+ * Function called to notify a client about the connection begin ready to queue
+ * more data.  "buf" will be NULL and "size" zero if the connection was closed
+ * for writing in the meantime.
+ *
+ * @param cls closure
+ * @param size number of bytes available in buf
+ * @param buf where the callee should write the message
+ * @return number of bytes written to buf
+ */
+static size_t
+transmit_ready_notify (void *cls, size_t size, void *buf)
+{
+  struct GNUNET_TESTBED_Controller *c = cls;
+  struct MessageQueue *mq_entry;
+
+  mq_entry = c->mq_head;
+  GNUNET_assert (NULL != mq_entry);
+  GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
+  size = ntohs (mq_entry->msg->size);
+  memcpy (buf, mq_entry->msg, size);
+  GNUNET_free (mq_entry->msg);
+  GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
+  GNUNET_free (mq_entry);
+  mq_entry = c->mq_head;
+  if (NULL != mq_entry)
+    c->th = 
+      GNUNET_CLIENT_notify_transmit_ready (c->client,
+                                           ntohs (mq_entry->msg->size),
+                                           GNUNET_TIME_UNIT_FOREVER_REL,
+                                           GNUNET_NO, &transmit_ready_notify,
+                                           c);
+  return size;
+}
+
+
+/**
+ * Queues a message in send queue for sending to the service
+ *
+ * @param controller the handle to the controller
+ * @param msg the message to queue
+ */
+static void
+queue_message (struct GNUNET_TESTBED_Controller *controller,
+               struct GNUNET_MessageHeader *msg)
+{
+  struct MessageQueue *mq_entry;
+  uint16_t type;
+  uint16_t size;
+
+  type = ntohs (msg->type);
+  size = ntohs (msg->size);
+  GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
+                 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));                 
+  mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
+  mq_entry->msg = msg;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Queueing message of type %u, size %u for sending\n", type,
+       ntohs (msg->size));
+  GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
+                                    mq_entry);
+  if (NULL == controller->th)
+    controller->th = 
+      GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
+                                           GNUNET_TIME_UNIT_FOREVER_REL,
+                                           GNUNET_NO, &transmit_ready_notify,
+                                           controller);
+ }
+
+
+/**
+ * Handler for messages from controller (testbed service)
+ *
+ * @param cls the controller handler
+ * @param msg message received, NULL on timeout or fatal error
+ */
+static void 
+message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
+{
+  struct GNUNET_TESTBED_Controller *c = cls;
+
+  /* FIXME: Add checks for message integrity */
+  switch (ntohs (msg->type))
+  {
+  default:
+    GNUNET_break (0);
+  }
+  GNUNET_CLIENT_receive (c->client, &message_handler, c,
+                         GNUNET_TIME_UNIT_FOREVER_REL);
+}
+
+
+/**
+ * ?Callback for messages recevied from server? 
+ *
+ * Do not call GNUNET_SERVER_mst_destroy in callback
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ *
+ * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing
+ */
+static int 
+server_mst_cb (void *cls, void *client,
+               const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_TESTBED_Controller *c = cls;
+  struct GNUNET_TESTBED_Message *msg;
+  
+  c->client = GNUNET_CLIENT_connect ("testbed", c->cfg);
+  if (NULL == c->client)
+    return GNUNET_SYSERR;       /* FIXME: Call controller startup_cb ? */
+  GNUNET_CLIENT_receive (c->client, &message_handler, c,
+                         GNUNET_TIME_UNIT_FOREVER_REL);
+  msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Message));
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
+  msg->header.size = htons (sizeof (struct GNUNET_TESTBED_Message));
+  msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (c->host));
+  msg->event_mask = GNUNET_htonll (c->event_mask);
+  queue_message (c, (struct GNUNET_MessageHeader *) msg);
+  return GNUNET_OK;
+}
+
 
 /**
  * Start a controller process using the given configuration at the
@@ -56,8 +272,24 @@ GNUNET_TESTBED_controller_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
                                 GNUNET_TESTBED_ControllerCallback cc,
                                 void *cc_cls)
 {
-  GNUNET_break (0);
-  return NULL;
+  struct GNUNET_TESTBED_Controller *controller;
+  char * binary_argv[] = {"gnunet-service-testbed",
+                          "gnunet-service-testbed",
+                          NULL};
+  controller = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Controller));
+  controller->h = GNUNET_TESTBED_host_run_ (host, binary_argv,
+                                            &server_mst_cb, controller);
+  if (NULL == controller->h)
+  {
+    GNUNET_free (controller);
+    return NULL;
+  }
+  controller->host = host;
+  controller->cc = cc;
+  controller->cc_cls = cc_cls;
+  controller->event_mask = event_mask;
+  controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
+  return controller;
 }
 
 
index 58866a45c920fa1532e459fa7799468947ab7f8f..4af409af0113d238bcce9a40e1447dc62ac39651 100644 (file)
@@ -130,7 +130,7 @@ GNUNET_TESTBED_host_create_by_id_ (uint32_t id)
  *         'localhost', but then obviously not globally unique)
  */
 uint32_t
-GNUNET_TESTBED_host_get_id_ (struct GNUNET_TESTBED_Host *host)
+GNUNET_TESTBED_host_get_id_ (const struct GNUNET_TESTBED_Host *host)
 {
     return host->unique_id;
 }
index 401d4e0d7e7e7d06e42d2214ac2a4a536b00025f..835866653b29e939ff2143ba9987fae47dc28ef5 100644 (file)
@@ -81,7 +81,7 @@ GNUNET_TESTBED_host_create_with_id_ (uint32_t id,
  *         'localhost', but then obviously not globally unique)
  */
 uint32_t
-GNUNET_TESTBED_host_get_id_ (struct GNUNET_TESTBED_Host *host);
+GNUNET_TESTBED_host_get_id_ (const struct GNUNET_TESTBED_Host *host);
 
 
 /**