gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r26855 - gnunet/src/testbed


From: gnunet
Subject: [GNUnet-SVN] r26855 - gnunet/src/testbed
Date: Thu, 11 Apr 2013 18:35:18 +0200

Author: harsha
Date: 2013-04-11 18:35:18 +0200 (Thu, 11 Apr 2013)
New Revision: 26855

Added:
   gnunet/src/testbed/gnunet-service-testbed_links.h
Modified:
   gnunet/src/testbed/gnunet-service-testbed.c
   gnunet/src/testbed/gnunet-service-testbed.h
   gnunet/src/testbed/gnunet-service-testbed_links.c
   gnunet/src/testbed/gnunet-service-testbed_oc.c
Log:
- towards on-demand controller linking


Modified: gnunet/src/testbed/gnunet-service-testbed.c
===================================================================
--- gnunet/src/testbed/gnunet-service-testbed.c 2013-04-11 14:07:58 UTC (rev 
26854)
+++ gnunet/src/testbed/gnunet-service-testbed.c 2013-04-11 16:35:18 UTC (rev 
26855)
@@ -847,6 +847,8 @@
   GST_free_mctxq ();
   GST_free_occq ();
   GST_free_roccq ();
+  GST_free_nccq ();
+  GST_neighbour_list_clean();
   /* Clear peer list */
   GST_destroy_peers ();
   /* Clear host list */

Modified: gnunet/src/testbed/gnunet-service-testbed.h
===================================================================
--- gnunet/src/testbed/gnunet-service-testbed.h 2013-04-11 14:07:58 UTC (rev 
26854)
+++ gnunet/src/testbed/gnunet-service-testbed.h 2013-04-11 16:35:18 UTC (rev 
26855)
@@ -35,6 +35,7 @@
 #include "testbed_api_operations.h"
 #include "testbed_api_hosts.h"
 #include "gnunet_testing_lib.h"
+#include "gnunet-service-testbed_links.h"
 
 
 /**
@@ -171,55 +172,6 @@
 
 
 /**
- * Structure representing a connected(directly-linked) controller
- */
-struct Slave
-{
-  /**
-   * The controller process handle if we had started the controller
-   */
-  struct GNUNET_TESTBED_ControllerProc *controller_proc;
-
-  /**
-   * The controller handle
-   */
-  struct GNUNET_TESTBED_Controller *controller;
-
-  /**
-   * handle to lcc which is associated with this slave startup. Should be set 
to
-   * NULL when the slave has successfully started up
-   */
-  struct LinkControllersContext *lcc;
-
-  /**
-   * Head of the host registration DLL
-   */
-  struct HostRegistration *hr_dll_head;
-
-  /**
-   * Tail of the host registration DLL
-   */
-  struct HostRegistration *hr_dll_tail;
-
-  /**
-   * The current host registration handle
-   */
-  struct GNUNET_TESTBED_HostRegistrationHandle *rhandle;
-
-  /**
-   * Hashmap to hold Registered host contexts
-   */
-  struct GNUNET_CONTAINER_MultiHashMap *reghost_map;
-
-  /**
-   * The id of the host this controller is running on
-   */
-  uint32_t host_id;
-
-};
-
-
-/**
  * A peer
  */
 
@@ -487,119 +439,6 @@
 
 
 /**
- * States of LCFContext
- */
-enum LCFContextState
-{
-  /**
-   * The Context has been initialized; Nothing has been done on it
-   */
-  INIT,
-
-  /**
-   * Delegated host has been registered at the forwarding controller
-   */
-  DELEGATED_HOST_REGISTERED,
-
-  /**
-   * The slave host has been registred at the forwarding controller
-   */
-  SLAVE_HOST_REGISTERED,
-
-  /**
-   * The context has been finished (may have error)
-   */
-  FINISHED
-};
-
-
-/**
- * Link controllers request forwarding context
- */
-struct LCFContext
-{
-  /**
-   * The type of this data structure. Set this to CLOSURE_TYPE_LCF
-   */
-  enum ClosureType type;
-  
-  /**
-   * The gateway which will pass the link message to delegated host
-   */
-  struct Slave *gateway;
-
-  /**
-   * The client which has asked to perform this operation
-   */
-  struct GNUNET_SERVER_Client *client;
-
-  /**
-   * Handle for operations which are forwarded while linking controllers
-   */
-  struct GNUNET_TESTBED_Operation *op;
-
-  /**
-   * The configuration which has to be either used as a template while starting
-   * the delegated controller or for connecting to the delegated controller
-   */
-  struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * The timeout task
-   */
-  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-
-  /**
-   * The id of the operation which created this context
-   */
-  uint64_t operation_id;
-  
-  /**
-   * should the slave controller start the delegated controller?
-   */
-  int is_subordinate;
-
-  /**
-   * The state of this context
-   */
-  enum LCFContextState state;
-
-  /**
-   * The delegated host
-   */
-  uint32_t delegated_host_id;
-
-  /**
-   * The slave host
-   */
-  uint32_t slave_host_id;
-
-};
-
-
-/**
- * Structure of a queue entry in LCFContext request queue
- */
-struct LCFContextQueue
-{
-  /**
-   * The LCFContext
-   */
-  struct LCFContext *lcf;
-
-  /**
-   * Head prt for DLL
-   */
-  struct LCFContextQueue *next;
-
-  /**
-   * Tail ptr for DLL
-   */
-  struct LCFContextQueue *prev;
-};
-
-
-/**
  * Context data for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS handler
  */
 struct HandlerContext_ShutdownPeers
@@ -649,11 +488,6 @@
 extern struct GNUNET_TESTBED_Host **GST_host_list;
 
 /**
- * A list of directly linked neighbours
- */
-extern struct Slave **GST_slave_list;
-
-/**
  * Operation queue for open file descriptors
  */
 extern struct OperationQueue *GST_opq_openfds;
@@ -674,11 +508,6 @@
 extern unsigned int GST_host_list_size;
 
 /**
- * The size of directly linked neighbours list
- */
-extern unsigned int GST_slave_list_size;
-
-/**
  * The directory where to store load statistics data
  */
 extern char *GST_stats_dir;
@@ -748,18 +577,6 @@
 
 
 /**
- * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
- *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
- */
-void
-GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
-                             const struct GNUNET_MessageHeader *message);
-
-
-/**
  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
  *
  * @param cls NULL
@@ -957,13 +774,6 @@
 
 
 /**
- * Cleans up the slave list
- */
-void
-GST_slave_list_clear ();
-
-
-/**
  * Processes a forwarded overlay connect context in the queue of the given 
RegisteredHostContext
  *
  * @param rhc the RegisteredHostContext

Modified: gnunet/src/testbed/gnunet-service-testbed_links.c
===================================================================
--- gnunet/src/testbed/gnunet-service-testbed_links.c   2013-04-11 14:07:58 UTC 
(rev 26854)
+++ gnunet/src/testbed/gnunet-service-testbed_links.c   2013-04-11 16:35:18 UTC 
(rev 26855)
@@ -19,19 +19,200 @@
 */
 
 /**
- * @file testbed/gnunet-service-testbed.c
- * @brief implementation of the TESTBED service
+ * @file testbed/gnunet-service-testbed_links.c
+ * @brief TESTBED service components that deals with starting slave controllers
+ *          and establishing lateral links between controllers
  * @author Sree Harsha Totakura
  */
 
 #include "gnunet-service-testbed.h"
 
 /**
+ * Redefine LOG with a changed log component string
+ */
+#ifdef LOG
+#undef LOG
+#endif
+#define LOG(kind,...)                                   \
+  GNUNET_log_from (kind, "testbed-links", __VA_ARGS__)
+
+/**
  * The event mask for the events we listen from sub-controllers
  */
 #define EVENT_MASK (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED)
 
+
 /**
+ * States of LCFContext
+ */
+enum LCFContextState
+{
+  /**
+   * The Context has been initialized; Nothing has been done on it
+   */
+  INIT,
+
+  /**
+   * Delegated host has been registered at the forwarding controller
+   */
+  DELEGATED_HOST_REGISTERED,
+
+  /**
+   * The slave host has been registred at the forwarding controller
+   */
+  SLAVE_HOST_REGISTERED,
+
+  /**
+   * The context has been finished (may have error)
+   */
+  FINISHED
+};
+
+
+/**
+ * Link controllers request forwarding context
+ */
+struct LCFContext
+{
+  /**
+   * The type of this data structure. Set this to CLOSURE_TYPE_LCF
+   */
+  enum ClosureType type;
+  
+  /**
+   * The gateway which will pass the link message to delegated host
+   */
+  struct Slave *gateway;
+
+  /**
+   * The client which has asked to perform this operation
+   */
+  struct GNUNET_SERVER_Client *client;
+
+  /**
+   * Handle for operations which are forwarded while linking controllers
+   */
+  struct GNUNET_TESTBED_Operation *op;
+
+  /**
+   * The configuration which has to be either used as a template while starting
+   * the delegated controller or for connecting to the delegated controller
+   */
+  struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * The timeout task
+   */
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+
+  /**
+   * The id of the operation which created this context
+   */
+  uint64_t operation_id;
+  
+  /**
+   * should the slave controller start the delegated controller?
+   */
+  int is_subordinate;
+
+  /**
+   * The state of this context
+   */
+  enum LCFContextState state;
+
+  /**
+   * The delegated host
+   */
+  uint32_t delegated_host_id;
+
+  /**
+   * The slave host
+   */
+  uint32_t slave_host_id;
+
+};
+
+
+/**
+ * Structure of a queue entry in LCFContext request queue
+ */
+struct LCFContextQueue
+{
+  /**
+   * The LCFContext
+   */
+  struct LCFContext *lcf;
+
+  /**
+   * Head prt for DLL
+   */
+  struct LCFContextQueue *next;
+
+  /**
+   * Tail ptr for DLL
+   */
+  struct LCFContextQueue *prev;
+};
+
+struct NeighbourConnectNotification
+{
+  struct NeighbourConnectNotification *next;
+  struct NeighbourConnectNotification *prev;
+  struct Neighbour *n;
+  GST_NeigbourConnectNotifyCallback cb;
+  void *cb_cls;
+};
+  
+/**
+ * A connected controller which is not our child
+ */
+struct Neighbour
+{
+  /**
+   * The controller handle
+   */
+  struct GNUNET_TESTBED_Controller *controller;
+  
+  /**
+   * Operation handle for opening a lateral connection to another controller.
+   * Will be NULL if the slave controller is started by this controller
+   */
+  struct GNUNET_TESTBED_Operation *conn_op;
+
+  struct NeighbourConnectNotification *nl_head;
+
+  struct NeighbourConnectNotification *nl_tail;
+
+  GNUNET_SCHEDULER_TaskIdentifier notify_task;
+
+  unsigned int reference_cnt;
+  
+  /**
+   * The id of the host this controller is running on
+   */
+  uint32_t host_id;
+  
+  int8_t inactive;
+};
+
+static struct Neighbour **neighbour_list;
+static unsigned int neighbour_list_size;
+
+struct NeighbourConnectCtxt
+{
+  struct NeighbourConnectCtxt *next;
+  struct NeighbourConnectCtxt *prev;
+  struct Neighbour *n;
+  struct GNUNET_SERVER_Client *client;
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+  struct NeighbourConnectNotification *nh;
+  uint64_t op_id;
+};
+
+struct NeighbourConnectCtxt *ncc_head;
+struct NeighbourConnectCtxt *ncc_tail;
+
+/**
  * A list of directly linked neighbours
  */
 struct Slave **GST_slave_list;
@@ -97,7 +278,16 @@
   route_list[route->dest] = route;
 }
 
+static void
+neighbour_list_add (struct Neighbour *n)
+{
+  if (n->host_id >= neighbour_list_size)
+    GST_array_grow_large_enough (neighbour_list, neighbour_list_size, 
n->host_id);
+  GNUNET_assert (NULL == neighbour_list[n->host_id]);
+  neighbour_list[n->host_id] = n;
+}
 
+
 /**
  * Cleans up the route list
  */
@@ -425,7 +615,7 @@
 /**
  * Callback for event from slave controllers
  *
- * @param cls struct Slave *
+ * @param cls NULL
  * @param event information about the event
  */
 static void
@@ -491,6 +681,9 @@
   GNUNET_assert (0);
 }
 
+static void
+slave_status_callback (void *cls, const struct GNUNET_CONFIGURATION_Handle 
*cfg,
+                       int status);
 
 /**
  * Callback to signal successfull startup of the controller process
@@ -552,7 +745,202 @@
     slave->lcc = NULL;
 }
 
+static void
+neighbour_connect_notify_task (void *cls, 
+                               const struct GNUNET_SCHEDULER_TaskContext *tc);
 
+static void
+trigger_notifications (struct Neighbour *n)
+{
+  GNUNET_assert (NULL != n->conn_op);
+  if (NULL == n->nl_head)
+    return;
+  if (NULL == n->controller)
+    return;
+  if (GNUNET_SCHEDULER_NO_TASK != n->notify_task)
+    return;
+  n->notify_task = 
+      GNUNET_SCHEDULER_add_now (&neighbour_connect_notify_task, n->nl_head);
+}
+
+static void
+neighbour_connect_notify_task (void *cls, 
+                               const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct NeighbourConnectNotification *h = cls;
+  struct Neighbour *n;
+
+  n = h->n;  
+  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != n->notify_task);  
+  n->notify_task = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_assert (NULL != n->controller);
+  GNUNET_CONTAINER_DLL_remove (n->nl_head, n->nl_tail, h);  
+  trigger_notifications (n);
+  if ((0 == n->reference_cnt) && (1 == n->inactive))
+  {
+    GNUNET_TESTBED_operation_activate_ (n->conn_op);
+    n->inactive = 0;
+  }
+  n->reference_cnt++;
+  h->cb (h->cb_cls, n->controller);
+}
+
+static void
+opstart_neighbour_conn (void *cls)
+{
+  struct Neighbour *n = cls;
+  
+  GNUNET_assert (NULL != n->conn_op);
+  GNUNET_assert (NULL == n->controller);
+  LOG_DEBUG ("Opening connection to controller on host %u\n", n->host_id);
+  n->controller = GNUNET_TESTBED_controller_connect (GST_host_list[n->host_id],
+                                                     EVENT_MASK,
+                                                     &slave_event_callback,
+                                                     NULL);
+  trigger_notifications (n);
+}
+
+static void
+oprelease_neighbour_conn (void *cls)
+{
+   struct Neighbour *n = cls;
+
+   GNUNET_assert (0 == n->reference_cnt);
+   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == n->notify_task);
+   GNUNET_assert (NULL == n->nl_head);
+   LOG_DEBUG ("Closing connection to controller on host %u\n", n->host_id);
+   GNUNET_TESTBED_controller_disconnect (n->controller);
+   n->controller = NULL;
+   n->conn_op = NULL;
+}
+
+struct NeighbourConnectNotification *
+GST_neighbour_get_connection (struct Neighbour *n,
+                              GST_NeigbourConnectNotifyCallback cb,
+                              void *cb_cls)
+{
+  struct NeighbourConnectNotification *h;
+
+  GNUNET_assert (NULL != cb);
+  LOG_DEBUG ("Attempting to get connection to controller on host %u\n",
+             n->host_id);
+  h = GNUNET_malloc (sizeof (struct NeighbourConnectNotification));
+  h->n = n;
+  h->cb  = cb;
+  h->cb_cls = cb_cls;
+  GNUNET_CONTAINER_DLL_insert_tail (n->nl_head, n->nl_tail, h);
+  if (NULL == n->conn_op)
+  {
+    GNUNET_assert (NULL == n->controller);
+    n->conn_op = GNUNET_TESTBED_operation_create_ (n, &opstart_neighbour_conn,
+                                                   &oprelease_neighbour_conn);
+    GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds, n->conn_op);
+    GNUNET_TESTBED_operation_begin_wait_ (n->conn_op);
+    return h;
+  }
+  trigger_notifications (n);
+  return h;
+}
+
+void
+GST_neighbour_get_connection_cancel (struct NeighbourConnectNotification *h)
+{
+  struct Neighbour *n;
+  
+  n = h->n;
+  if ((h == n->nl_head) && (GNUNET_SCHEDULER_NO_TASK != n->notify_task))
+  {
+    GNUNET_SCHEDULER_cancel (n->notify_task);
+    n->notify_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  GNUNET_CONTAINER_DLL_remove (n->nl_head, n->nl_tail, h);
+  GNUNET_free (h);
+}
+
+void
+GST_neighbour_release_connection (struct Neighbour *n)
+{
+  GNUNET_assert (0 == n->inactive);
+  GNUNET_assert (0 < n->reference_cnt);
+  n->reference_cnt--;
+  if (0 == n->reference_cnt)
+  {
+    GNUNET_TESTBED_operation_inactivate_ (n->conn_op);
+    n->inactive = 1;
+  }
+}
+
+static void
+cleanup_ncc (struct NeighbourConnectCtxt *ncc)
+{
+  if (NULL != ncc->nh)
+    GST_neighbour_get_connection_cancel (ncc->nh);
+  if (GNUNET_SCHEDULER_NO_TASK != ncc->timeout_task)
+    GNUNET_SCHEDULER_cancel (ncc->timeout_task);
+  GNUNET_SERVER_client_drop (ncc->client);
+  GNUNET_CONTAINER_DLL_remove (ncc_head, ncc_tail, ncc);
+  GNUNET_free (ncc);
+}
+
+void
+GST_neighbour_list_clean()
+{
+  struct Neighbour *n;
+  unsigned int id;
+
+  for (id = 0; id < neighbour_list_size; id++)
+  {
+    if (NULL == (n = neighbour_list[id]))
+      continue;
+    if (NULL != n->conn_op)
+      GNUNET_TESTBED_operation_release_ (n->conn_op);
+    GNUNET_free (n);
+    neighbour_list[id] = NULL;
+  }
+  GNUNET_free_non_null (neighbour_list);
+}
+
+struct Neighbour *
+GST_get_neighbour (uint32_t id)
+{
+  if (neighbour_list_size <= id)
+    return NULL;
+  else
+    return neighbour_list[id];
+}
+
+void
+GST_free_nccq ()
+{
+  while (NULL != ncc_head)
+    cleanup_ncc (ncc_head);
+}
+
+static void
+timeout_neighbour_connect (void *cls, 
+                           const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct NeighbourConnectCtxt *ncc = cls;
+
+ ncc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ send_controller_link_response (ncc->client, ncc->op_id, NULL,
+                                "Could not connect to delegated controller");
+ cleanup_ncc (ncc);
+}
+
+static void
+neighbour_connect_cb (void *cls, struct GNUNET_TESTBED_Controller *c)
+{
+  struct NeighbourConnectCtxt *ncc = cls;
+
+  GNUNET_SCHEDULER_cancel (ncc->timeout_task);
+  ncc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  ncc->nh = NULL;
+  GST_neighbour_release_connection (ncc->n);
+  send_controller_link_response (ncc->client, ncc->op_id, NULL, NULL);
+  cleanup_ncc (ncc);
+}
+
 /**
  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
  *
@@ -569,6 +957,7 @@
   struct LCFContextQueue *lcfq;
   struct Route *route;
   struct Route *new_route;
+  uint64_t op_id;
   uint32_t delegated_host_id;
   uint32_t slave_host_id;
   uint16_t msize;
@@ -625,11 +1014,43 @@
     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
     return;
   }
+  op_id = GNUNET_ntohll (msg->operation_id);
   if (slave_host_id == GST_context->host_id)    /* Link from us */
   {
     struct Slave *slave;
     struct LinkControllersContext *lcc;
 
+    
+    if (1 != msg->is_subordinate)
+    {
+      struct Neighbour *n;
+      struct NeighbourConnectCtxt *ncc;
+
+      if ((delegated_host_id < neighbour_list_size) &&
+        (NULL != neighbour_list[delegated_host_id]))
+      {
+        GNUNET_break (0);
+        GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+        return;
+      }
+      LOG_DEBUG ("Received request to establish a link to host %u\n",
+                 delegated_host_id);
+      n = GNUNET_malloc (sizeof (struct Neighbour));
+      n->host_id = delegated_host_id;
+      neighbour_list_add (n);   /* just add; connect on-demand */
+      ncc = GNUNET_malloc (sizeof (struct NeighbourConnectCtxt));
+      ncc->n = n;
+      ncc->op_id = op_id;
+      ncc->client = client;
+      GNUNET_SERVER_client_keep (client);      
+      ncc->nh = GST_neighbour_get_connection (n, neighbour_connect_cb, ncc);
+      ncc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout,
+                                                        
&timeout_neighbour_connect,
+                                                        ncc);
+      GNUNET_CONTAINER_DLL_insert_tail (ncc_head, ncc_tail, ncc);      
+      GNUNET_SERVER_receive_done (client, GNUNET_OK);
+      return;
+    }
     if ((delegated_host_id < GST_slave_list_size) &&
         (NULL != GST_slave_list[delegated_host_id]))
     {
@@ -637,31 +1058,14 @@
       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
       return;
     }
+    LOG_DEBUG ("Received request to start and establish a link to host %u\n",
+               delegated_host_id);
     slave = GNUNET_malloc (sizeof (struct Slave));
     slave->host_id = delegated_host_id;
     slave->reghost_map = GNUNET_CONTAINER_multihashmap_create (100, GNUNET_NO);
     slave_list_add (slave);
-    if (1 != msg->is_subordinate)
-    {
-      slave->controller =
-          GNUNET_TESTBED_controller_connect (GST_host_list[slave->host_id],
-                                             EVENT_MASK, &slave_event_callback,
-                                             slave);
-      if (NULL != slave->controller)
-        send_controller_link_response (client,
-                                       GNUNET_ntohll (msg->operation_id),
-                                       NULL,
-                                       NULL);
-      else
-        send_controller_link_response (client,
-                                       GNUNET_ntohll (msg->operation_id),
-                                       NULL,
-                                       "Could not connect to delegated 
controller");
-      GNUNET_SERVER_receive_done (client, GNUNET_OK);
-      return;
-    }
     lcc = GNUNET_malloc (sizeof (struct LinkControllersContext));
-    lcc->operation_id = GNUNET_ntohll (msg->operation_id);
+    lcc->operation_id = op_id;
     GNUNET_SERVER_client_keep (client);
     lcc->client = client;
     slave->lcc = lcc;
@@ -696,7 +1100,7 @@
   lcfq->lcf->cfg = cfg;
   lcfq->lcf->is_subordinate = msg->is_subordinate;
   lcfq->lcf->state = INIT;
-  lcfq->lcf->operation_id = GNUNET_ntohll (msg->operation_id);
+  lcfq->lcf->operation_id = op_id;
   lcfq->lcf->gateway = GST_slave_list[route->dest];
   GNUNET_SERVER_client_keep (client);
   lcfq->lcf->client = client;

Added: gnunet/src/testbed/gnunet-service-testbed_links.h
===================================================================
--- gnunet/src/testbed/gnunet-service-testbed_links.h                           
(rev 0)
+++ gnunet/src/testbed/gnunet-service-testbed_links.h   2013-04-11 16:35:18 UTC 
(rev 26855)
@@ -0,0 +1,138 @@
+/*
+  This file is part of GNUnet.
+  (C) 2008--2013 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
+  by the Free Software Foundation; either version 2, or (at your
+  option) any later version.
+
+  GNUnet is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with GNUnet; see the file COPYING.  If not, write to the
+  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+  Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file testbed/gnunet-service-testbed_links.h
+ * @brief TESTBED service components that deals with starting slave controllers
+ *          and establishing lateral links between controllers
+ * @author Sree Harsha Totakura
+ */
+
+struct Neighbour;
+
+
+/**
+ * Structure representing a connected(directly-linked) controller
+ */
+struct Slave
+{
+  /**
+   * The controller process handle if we had started the controller
+   */
+  struct GNUNET_TESTBED_ControllerProc *controller_proc;
+
+  /**
+   * The controller handle
+   */
+  struct GNUNET_TESTBED_Controller *controller;
+
+  /**
+   * handle to lcc which is associated with this slave startup. Should be set 
to
+   * NULL when the slave has successfully started up
+   */
+  struct LinkControllersContext *lcc;
+
+  /**
+   * Head of the host registration DLL
+   */
+  struct HostRegistration *hr_dll_head;
+
+  /**
+   * Tail of the host registration DLL
+   */
+  struct HostRegistration *hr_dll_tail;
+
+  /**
+   * The current host registration handle
+   */
+  struct GNUNET_TESTBED_HostRegistrationHandle *rhandle;
+
+  /**
+   * Hashmap to hold Registered host contexts
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *reghost_map;
+
+  /**
+   * Operation handle for opening a lateral connection to another controller.
+   * Will be NULL if the slave controller is started by this controller
+   */
+  struct GNUNET_TESTBED_Operation *conn_op;
+
+  /**
+   * The id of the host this controller is running on
+   */
+  uint32_t host_id;
+
+};
+
+/**
+ * A list of directly linked neighbours
+ */
+extern struct Slave **GST_slave_list;
+
+/**
+ * The size of directly linked neighbours list
+ */
+extern unsigned int GST_slave_list_size;
+
+void
+GST_neighbour_list_clean();
+
+struct Neighbour *
+GST_get_neighbour (uint32_t id);
+
+void
+GST_free_nccq ();
+
+struct NeighbourConnectNotification;
+
+typedef void (*GST_NeigbourConnectNotifyCallback) (void *cls,
+                                                   struct
+                                                   GNUNET_TESTBED_Controller
+                                                   *controller);
+
+struct NeighbourConnectNotification *
+GST_neighbour_get_connection (struct Neighbour *n,
+                              GST_NeigbourConnectNotifyCallback cb,
+                              void *cb_cls);
+
+void
+GST_neighbour_get_connection_cancel (struct NeighbourConnectNotification *h);
+
+void
+GST_neighbour_release_connection (struct Neighbour *n);
+
+/**
+ * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
+ *
+ * @param cls NULL
+ * @param client identification of the client
+ * @param message the actual message
+ */
+void
+GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
+                             const struct GNUNET_MessageHeader *message);
+
+
+/**
+ * Cleans up the slave list
+ */
+void
+GST_slave_list_clear ();

Modified: gnunet/src/testbed/gnunet-service-testbed_oc.c
===================================================================
--- gnunet/src/testbed/gnunet-service-testbed_oc.c      2013-04-11 14:07:58 UTC 
(rev 26854)
+++ gnunet/src/testbed/gnunet-service-testbed_oc.c      2013-04-11 16:35:18 UTC 
(rev 26855)
@@ -150,10 +150,15 @@
   struct OperationContext *opc;
 
   /**
-   * Controller of peer 2; NULL if the peer is a local peer
+   * Controller of peer 2; NULL if the peer is a local peer or until the
+   * connection to the controller is established
    */
-  struct GNUNET_TESTBED_Controller *peer2_controller;
+  struct GNUNET_TESTBED_Controller *p2c;
+  
+  struct NeighbourConnectNotification *p2_ncn;
 
+  struct Neighbour *p2n;
+
   /**
    * The transport TryConnectContext. This will be NULL if the second peer is a
    * remote peer
@@ -418,16 +423,23 @@
     GST_cache_get_handle_done (occ->cgh_p1th);
   if (NULL != occ->tcc.cgh_th)
     GST_cache_get_handle_done (occ->tcc.cgh_th);
+  if (NULL != occ->p2n)
+  {
+    if (NULL != occ->p2_ncn)
+      GST_neighbour_get_connection_cancel (occ->p2_ncn);
+    if (NULL != occ->p2c)
+      GST_neighbour_release_connection (occ->p2n);
+  }
   GNUNET_assert (NULL != GST_peer_list);
   GNUNET_assert (occ->peer->reference_cnt > 0);  
   occ->peer->reference_cnt--;
   if ( (GNUNET_YES == occ->peer->destroy_flag) &&
        (0 == occ->peer->reference_cnt) )
     GST_destroy_peer (occ->peer);
-  if (NULL == occ->peer2_controller)
+  if ( (occ->other_peer_id < GST_peer_list_size)
+       && (NULL != (other_peer = GST_peer_list[occ->other_peer_id]))
+       && (GNUNET_YES != other_peer->is_remote) )
   {
-    other_peer = GST_peer_list[occ->other_peer_id];
-    GNUNET_assert (NULL != other_peer);
     GNUNET_assert (other_peer->reference_cnt > 0);
     other_peer->reference_cnt--;
     if ( (GNUNET_YES == other_peer->destroy_flag) &&
@@ -675,7 +687,7 @@
     return;
   GNUNET_assert (NULL != occ->hello);
   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
-  if (NULL != occ->peer2_controller)
+  if (NULL != occ->p2c)
   {
     struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
     uint16_t msize;
@@ -697,7 +709,7 @@
     (void) memcpy (&msg->peer_identity, &occ->peer_identity,
                    sizeof (struct GNUNET_PeerIdentity));
     memcpy (msg->hello, occ->hello, hello_size);
-    GNUNET_TESTBED_queue_message_ (occ->peer2_controller, &msg->header);
+    GNUNET_TESTBED_queue_message_ (occ->p2c, &msg->header);
   }
   else
   {
@@ -767,7 +779,7 @@
   GNUNET_assert (NULL == occ->ghh);
   GNUNET_assert (NULL == occ->p1th_);
   GNUNET_assert (NULL == occ->cgh_p1th);
-  if (NULL == occ->peer2_controller)
+  if (NULL == occ->p2c)
   {
     GNUNET_assert (NULL != GST_peer_list[occ->other_peer_id]);
     occ->tcc.cgh_th =
@@ -1069,7 +1081,32 @@
   return hash;
 }
 
+static void
+p2_controller_connect_cb (void *cls, struct GNUNET_TESTBED_Controller *c)
+{
+  struct OverlayConnectContext *occ = cls;
+  struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
 
+  occ->p2_ncn = NULL;
+  occ->p2c = c;
+  cmsg.header.size =
+      htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
+  cmsg.header.type =
+      htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_CONFIGURATION);
+  cmsg.peer_id = htonl (occ->other_peer_id);
+  cmsg.operation_id = GNUNET_htonll (occ->op_id);
+  occ->opc =
+      GNUNET_TESTBED_forward_operation_msg_ (occ->p2c,
+                                             occ->op_id, &cmsg.header,
+                                             &overlay_connect_get_config,
+                                             occ);
+  GNUNET_free_non_null (occ->emsg);
+  GNUNET_asprintf (&occ->emsg,
+                   "0x%llx: Timeout while getting peer identity of peer "
+                   "with id: %u", occ->op_id, occ->other_peer_id);
+}
+
+
 /**
  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
  *
@@ -1084,7 +1121,7 @@
   const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
   struct Peer *peer;
   struct OverlayConnectContext *occ;
-  struct GNUNET_TESTBED_Controller *peer2_controller;
+  struct GNUNET_TESTBED_Controller *p2c;
   uint64_t operation_id;
   uint32_t p1;
   uint32_t p2;
@@ -1225,31 +1262,25 @@
     return;
   }
 
-  peer2_controller = NULL;
+  struct Neighbour *p2n;
+  p2n = NULL;
+  p2c = NULL;
   if ((p2 >= GST_peer_list_size) || (NULL == GST_peer_list[p2]))
   {
-    if ((peer2_host_id >= GST_slave_list_size) ||
-        (NULL == GST_slave_list[peer2_host_id]))
+    if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
     {
       GNUNET_break (0);
       LOG (GNUNET_ERROR_TYPE_WARNING,
-           "0x%llx: Configuration of peer2's controller missing for connecting 
peers"
-           "%u and %u\n", operation_id, p1, p2);
+           "0x%llx: Peer %u's host not in our neighbours list\n",
+           operation_id, p2);
       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
       return;
     }
-    peer2_controller = GST_slave_list[peer2_host_id]->controller;
-    if (NULL == peer2_controller)
-    {
-      GNUNET_break (0);         /* What's going on? */
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
   }
   else
   {
     if (GNUNET_YES == GST_peer_list[p2]->is_remote)
-      peer2_controller = GST_peer_list[p2]->details.remote.slave->controller;
+      p2c = GST_peer_list[p2]->details.remote.slave->controller;
   }
   occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
   GNUNET_CONTAINER_DLL_insert_tail (occq_head, occq_tail, occ);
@@ -1258,33 +1289,28 @@
   occ->other_peer_id = p2;
   GST_peer_list[p1]->reference_cnt++;
   occ->peer = GST_peer_list[p1];  
-  occ->op_id = GNUNET_ntohll (msg->operation_id);
-  occ->peer2_controller = peer2_controller;
+  occ->op_id = operation_id;
+  occ->p2n = p2n;
   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == occ->timeout_task);
   occ->timeout_task =
       GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_overlay_connect, 
occ);
   /* Get the identity of the second peer */
-  if (NULL != occ->peer2_controller)
+  if (NULL != p2n)
   {
-    struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
-
-    cmsg.header.size =
-        htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
-    cmsg.header.type =
-        htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_CONFIGURATION);
-    cmsg.peer_id = msg->peer2;
-    cmsg.operation_id = msg->operation_id;
-    occ->opc =
-        GNUNET_TESTBED_forward_operation_msg_ (occ->peer2_controller,
-                                               occ->op_id, &cmsg.header,
-                                               &overlay_connect_get_config,
-                                               occ);
     GNUNET_asprintf (&occ->emsg,
-                     "0x%llx: Timeout while getting peer identity of peer "
-                     "with id: %u", occ->op_id, occ->other_peer_id);
+                     "0x%llx: Timeout while acquiring connection to peer %u's "
+                     "host: %u\n", occ->op_id, occ->other_peer_id, 
peer2_host_id);
+    occ->p2_ncn = GST_neighbour_get_connection (p2n, &p2_controller_connect_cb,
+                                                occ);
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
   }
+  if (NULL != p2c)
+  {
+    p2_controller_connect_cb (occ, p2c);
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    return;
+  }
   GST_peer_list[occ->other_peer_id]->reference_cnt++;
   GNUNET_TESTING_peer_get_identity (GST_peer_list[occ->other_peer_id]->
                                     details.local.peer,




reply via email to

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