- use tunnel encryption state to select decryption key
[oweals/gnunet.git] / src / testbed / gnunet-service-testbed_links.c
index d34d0c040d8b8d4148dfd6317dcd493b5efa278d..766c47471342f36919a906324d521bfc23cd8e59 100644 (file)
@@ -98,7 +98,7 @@ struct LCFContext
    * The id of the operation which created this context
    */
   uint64_t operation_id;
-  
+
   /**
    * should the slave controller start the delegated controller?
    */
@@ -186,7 +186,7 @@ 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
@@ -217,11 +217,11 @@ struct Neighbour
    * Is the conn_op inactivated?
    */
   unsigned int inactive;
-  
+
   /**
    * The id of the host this controller is running on
    */
-  uint32_t host_id;  
+  uint32_t host_id;
 };
 
 
@@ -256,7 +256,7 @@ struct NeighbourConnectCtxt
    * The neighbour to whom connection should be made
    */
   struct Neighbour *n;
-  
+
   /**
    * The client requesting the connection
    */
@@ -379,7 +379,7 @@ void
 GST_route_list_clear ()
 {
   unsigned int id;
-  
+
   for (id = 0; id < route_list_size; id++)
     if (NULL != route_list[id])
       GNUNET_free (route_list[id]);
@@ -419,52 +419,79 @@ reghost_free_iterator (void *cls, const struct GNUNET_HashCode *key,
 }
 
 
+/**
+ * Kill a #Slave object
+ *
+ * @param slave the #Slave object
+ */
+static void
+kill_slave (struct Slave *slave)
+{
+  struct HostRegistration *hr_entry;
+
+  while (NULL != (hr_entry = slave->hr_dll_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head, slave->hr_dll_tail,
+                                 hr_entry);
+    GNUNET_free (hr_entry);
+  }
+  if (NULL != slave->rhandle)
+    GNUNET_TESTBED_cancel_registration (slave->rhandle);
+  GNUNET_assert (GNUNET_SYSERR !=
+                 GNUNET_CONTAINER_multihashmap_iterate (slave->reghost_map,
+                                                        reghost_free_iterator,
+                                                        slave));
+  GNUNET_CONTAINER_multihashmap_destroy (slave->reghost_map);
+  if (NULL != slave->controller)
+    GNUNET_TESTBED_controller_disconnect (slave->controller);
+  if (NULL != slave->controller_proc)
+  {
+    LOG_DEBUG ("Stopping a slave\n");
+    GNUNET_TESTBED_controller_kill_ (slave->controller_proc);
+  }
+}
+
+
+/**
+ * Destroy a #Slave object
+ *
+ * @param slave the #Slave object
+ */
+static void
+destroy_slave (struct Slave *slave)
+{
+  if (NULL != slave->controller_proc)
+  {
+    GNUNET_TESTBED_controller_destroy_ (slave->controller_proc);
+    LOG_DEBUG ("Slave stopped\n");
+  }
+  GST_slave_list[slave->host_id] = NULL;
+  GNUNET_free (slave);
+}
+
+
 /**
  * Cleans up the slave list
  */
 void
 GST_slave_list_clear ()
 {
-  struct HostRegistration *hr_entry;
-  struct GNUNET_TESTBED_ControllerProc *cproc;
+  struct Slave *slave;
   unsigned int id;
 
   for (id = 0; id < GST_slave_list_size; id++)
   {
-    if (NULL == GST_slave_list[id])
+    slave = GST_slave_list[id];
+    if (NULL == slave)
       continue;
-    while (NULL != (hr_entry = GST_slave_list[id]->hr_dll_head))
-    {
-      GNUNET_CONTAINER_DLL_remove (GST_slave_list[id]->hr_dll_head,
-                                   GST_slave_list[id]->hr_dll_tail, hr_entry);
-      GNUNET_free (hr_entry);
-    }
-    if (NULL != GST_slave_list[id]->rhandle)
-      GNUNET_TESTBED_cancel_registration (GST_slave_list[id]->rhandle);
-    (void)
-        GNUNET_CONTAINER_multihashmap_iterate (GST_slave_list
-                                               [id]->reghost_map,
-                                               reghost_free_iterator,
-                                               GST_slave_list[id]);
-    GNUNET_CONTAINER_multihashmap_destroy (GST_slave_list[id]->reghost_map);
-    if (NULL != GST_slave_list[id]->controller)
-      GNUNET_TESTBED_controller_disconnect (GST_slave_list[id]->controller);
-    if (NULL != (cproc = GST_slave_list[id]->controller_proc))
-    {
-      LOG_DEBUG ("Stopping a slave\n");
-      GNUNET_TESTBED_controller_kill_ (cproc);
-    }
+    kill_slave (slave);
   }
   for (id = 0; id < GST_slave_list_size; id++)
   {
-    if (NULL == GST_slave_list[id])
+    slave = GST_slave_list[id];
+    if (NULL == slave)
       continue;
-    if (NULL != (cproc = GST_slave_list[id]->controller_proc))
-    {
-      GNUNET_TESTBED_controller_destroy_ (cproc);
-      LOG_DEBUG ("Slave stopped\n");
-    }
-    GNUNET_free (GST_slave_list[id]);
+    destroy_slave (slave);
   }
   GNUNET_free_non_null (GST_slave_list);
   GST_slave_list = NULL;
@@ -518,7 +545,7 @@ send_controller_link_response (struct GNUNET_SERVER_Client *client,
   struct GNUNET_TESTBED_ControllerLinkResponse *msg;
   char *xconfig;
   size_t config_size;
-  size_t xconfig_size;  
+  size_t xconfig_size;
   uint16_t msize;
 
   GNUNET_assert ((NULL == cfg) || (NULL == emsg));
@@ -696,7 +723,8 @@ lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     lcfq = lcfq_head;
     GNUNET_assert (lcfq->lcf == lcf);
     GNUNET_SERVER_client_drop (lcf->client);
-    GNUNET_TESTBED_operation_done (lcf->op);
+    if (NULL != lcf->op)
+      GNUNET_TESTBED_operation_done (lcf->op);
     GNUNET_free (lcf);
     GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
     GNUNET_free (lcfq);
@@ -718,17 +746,18 @@ slave_event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
 {
   struct LCFContext *lcf;
 
-  /* We currently only get here when working on RegisteredHostContexts and
-     LCFContexts */
+  /* We currently only get here when working on LCFContexts */
   GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
   lcf = event->op_cls;
   GNUNET_assert (lcf->op == event->op);
+  GNUNET_TESTBED_operation_done (lcf->op);
+  lcf->op = NULL;
   GNUNET_assert (FINISHED == lcf->state);
   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != lcf->timeout_task);
   GNUNET_SCHEDULER_cancel (lcf->timeout_task);
   if (NULL == event->details.operation_finished.emsg)
     send_controller_link_response (lcf->client, lcf->operation_id,
-                                   GNUNET_TESTBED_host_get_cfg_ 
+                                   GNUNET_TESTBED_host_get_cfg_
                                    (GST_host_list[lcf->delegated_host_id]),
                                    NULL);
   else
@@ -761,8 +790,13 @@ slave_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
   if (GNUNET_SYSERR == status)
   {
     slave->controller_proc = NULL;
-    GST_slave_list[slave->host_id] = NULL;
-    GNUNET_free (slave);
+    /* Stop all link controller forwarding tasks since we shutdown here anyway
+       and as these tasks they depend on the operation queues which are created
+       through GNUNET_TESTBED_controller_connect() and in kill_slave() we call
+       the destructor function GNUNET_TESTBED_controller_disconnect() */
+    GST_free_lcfq ();
+    kill_slave (slave);
+    destroy_slave (slave);
     slave = NULL;
     LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected slave shutdown\n");
     GNUNET_SCHEDULER_shutdown ();       /* We too shutdown */
@@ -780,13 +814,12 @@ slave_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
   {
     send_controller_link_response (lcc->client, lcc->operation_id, NULL,
                                    "Could not connect to delegated controller");
-    GNUNET_TESTBED_controller_stop (slave->controller_proc);
-    GST_slave_list[slave->host_id] = NULL;
-    GNUNET_free (slave);
+    kill_slave (slave);
+    destroy_slave (slave);
     slave = NULL;
   }
 
-clean_lcc:
+ clean_lcc:
   if (NULL != lcc)
   {
     if (NULL != lcc->client)
@@ -822,17 +855,17 @@ trigger_notifications (struct Neighbour *n);
  * @param tc scheduler task context
  */
 static void
-neighbour_connect_notify_task (void *cls, 
+neighbour_connect_notify_task (void *cls,
                                const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct Neighbour *n = cls;
   struct NeighbourConnectNotification *h;
 
   GNUNET_assert (NULL != (h = n->nl_head));
-  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != n->notify_task);  
+  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);  
+  GNUNET_CONTAINER_DLL_remove (n->nl_head, n->nl_tail, h);
   trigger_notifications (n);
   h->cb (h->cb_cls, n->controller);
   GNUNET_free (h);
@@ -856,7 +889,7 @@ trigger_notifications (struct Neighbour *n)
   if (NULL == n->controller)
     return;
   if (GNUNET_SCHEDULER_NO_TASK != n->notify_task)
-    return;  
+    return;
   if (1 == n->inactive)
   {
     GNUNET_assert (0 == n->reference_cnt);
@@ -864,7 +897,7 @@ trigger_notifications (struct Neighbour *n)
     n->inactive = 0;
   }
   n->reference_cnt++;
-  n->notify_task = 
+  n->notify_task =
       GNUNET_SCHEDULER_add_now (&neighbour_connect_notify_task, n);
 }
 
@@ -880,7 +913,7 @@ 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);
@@ -966,7 +999,7 @@ GST_neighbour_get_connection_cancel (struct NeighbourConnectNotification *h)
 {
   struct Neighbour *n;
   int cleanup_task;
-  
+
   n = h->n;
   cleanup_task = (h == n->nl_head) ? GNUNET_YES : GNUNET_NO;
   GNUNET_CONTAINER_DLL_remove (n->nl_head, n->nl_tail, h);
@@ -1088,7 +1121,7 @@ GST_free_nccq ()
  * @param tc the scheduler task context
  */
 static void
-timeout_neighbour_connect (void *cls, 
+timeout_neighbour_connect (void *cls,
                            const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
  struct NeighbourConnectCtxt *ncc = cls;
@@ -1200,7 +1233,7 @@ GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
     struct Slave *slave;
     struct LinkControllersContext *lcc;
 
-    
+
     if (1 != msg->is_subordinate)
     {
       struct Neighbour *n;
@@ -1220,12 +1253,12 @@ GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
       ncc->n = n;
       ncc->op_id = op_id;
       ncc->client = client;
-      GNUNET_SERVER_client_keep (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_CONTAINER_DLL_insert_tail (ncc_head, ncc_tail, ncc);
       GNUNET_SERVER_receive_done (client, GNUNET_OK);
       return;
     }
@@ -1317,7 +1350,8 @@ void
 GST_free_lcfq ()
 {
   struct LCFContextQueue *lcfq;
-  
+  struct LCFContext *lcf;
+
   if (NULL != lcfq_head)
   {
     if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id)
@@ -1329,8 +1363,13 @@ GST_free_lcfq ()
   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
   for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head)
   {
-    GNUNET_SERVER_client_drop (lcfq->lcf->client);
-    GNUNET_free (lcfq->lcf);
+    lcf = lcfq->lcf;
+    GNUNET_SERVER_client_drop (lcf->client);
+    if (NULL != lcf->op)
+      GNUNET_TESTBED_operation_done (lcf->op);
+    if (GNUNET_SCHEDULER_NO_TASK != lcf->timeout_task)
+      GNUNET_SCHEDULER_cancel (lcf->timeout_task);
+    GNUNET_free (lcf);
     GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
     GNUNET_free (lcfq);
   }