X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftestbed%2Fgnunet-service-testbed.c;h=a1d6aed0951bb5bae4ccea565e876a18799a438a;hb=0f7e55e885e3d9c4e26432b53cf2cfe120df7cf5;hp=4aaf426201fc306cffa4c30c38e56873f9c50422;hpb=6d04a07b8b6f0553f535e224d22c9bfe4df4a704;p=oweals%2Fgnunet.git diff --git a/src/testbed/gnunet-service-testbed.c b/src/testbed/gnunet-service-testbed.c index 4aaf42620..a1d6aed09 100644 --- a/src/testbed/gnunet-service-testbed.c +++ b/src/testbed/gnunet-service-testbed.c @@ -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 @@ -25,29 +25,8 @@ */ #include "gnunet-service-testbed.h" -#include "gnunet_arm_service.h" - -#include - - -/** - * Context data for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS handler - */ -struct HandlerContext_ShutdownPeers -{ - /** - * The number of slave we expect to hear from since we forwarded the - * GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS message to them - */ - unsigned int nslaves; - - /** - * Did we observe a timeout with respect to this operation at any of the - * slaves - */ - int timeout; -}; - +#include "gnunet-service-testbed_barriers.h" +#include "gnunet-service-testbed_connectionpool.h" /***********/ /* Globals */ @@ -56,23 +35,13 @@ struct HandlerContext_ShutdownPeers /** * Our configuration */ -struct GNUNET_CONFIGURATION_Handle *our_config; +struct GNUNET_CONFIGURATION_Handle *GST_config; /** * The master context; generated with the first INIT message */ struct Context *GST_context; -/** - * A list of directly linked neighbours - */ -struct Slave **GST_slave_list; - -/** - * A list of peers we know about - */ -struct Peer **GST_peer_list; - /** * Array of hosts */ @@ -103,11 +72,6 @@ const struct GNUNET_TIME_Relative GST_timeout; */ unsigned int GST_host_list_size; -/** - * The size of directly linked neighbours list - */ -unsigned int GST_slave_list_size; - /** * The size of the peer list */ @@ -154,16 +118,6 @@ static char *hostname; */ static struct GNUNET_SERVER_TransmitHandle *transmit_handle; -/** - * The head for the LCF queue - */ -static struct LCFContextQueue *lcfq_head; - -/** - * The tail for the LCF queue - */ -static struct LCFContextQueue *lcfq_tail; - /** * The message queue head */ @@ -174,30 +128,6 @@ static struct MessageQueue *mq_head; */ static struct MessageQueue *mq_tail; -/** - * The hashmap of shared services - */ -static struct GNUNET_CONTAINER_MultiHashMap *ss_map; - -/** - * A list of routes - */ -static struct Route **route_list; - -/** - * The event mask for the events we listen from sub-controllers - */ -static uint64_t event_mask; - -/** - * The size of the route list - */ -static unsigned int route_list_size; - -/** - * The lcf_task handle - */ -static GNUNET_SCHEDULER_TaskIdentifier lcf_proc_task_id; /** * The shutdown task handle @@ -261,7 +191,7 @@ GST_queue_message (struct GNUNET_SERVER_Client *client, 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 = GNUNET_new (struct MessageQueue); mq_entry->msg = msg; mq_entry->client = client; GNUNET_SERVER_client_keep (client); @@ -276,30 +206,6 @@ GST_queue_message (struct GNUNET_SERVER_Client *client, } -/** - * Similar to GNUNET_array_grow(); however instead of calling GNUNET_array_grow() - * several times we call it only once. The array is also made to grow in steps - * of LIST_GROW_STEP. - * - * @param ptr the array pointer to grow - * @param size the size of array - * @param accommodate_size the size which the array has to accommdate; after - * this call the array will be big enough to accommdate sizes upto - * accommodate_size - */ -#define array_grow_large_enough(ptr, size, accommodate_size) \ - do \ - { \ - unsigned int growth_size; \ - GNUNET_assert (size <= accommodate_size); \ - growth_size = size; \ - while (growth_size <= accommodate_size) \ - growth_size += LIST_GROW_STEP; \ - GNUNET_array_grow (ptr, size, growth_size); \ - GNUNET_assert (size > accommodate_size); \ - } while (0) - - /** * Function to add a host to the current list of known hosts * @@ -314,7 +220,7 @@ host_list_add (struct GNUNET_TESTBED_Host *host) host_id = GNUNET_TESTBED_host_get_id_ (host); if (GST_host_list_size <= host_id) - array_grow_large_enough (GST_host_list, GST_host_list_size, host_id); + GST_array_grow_large_enough (GST_host_list, GST_host_list_size, host_id); if (NULL != GST_host_list[host_id]) { LOG_DEBUG ("A host with id: %u already exists\n", host_id); @@ -325,122 +231,6 @@ host_list_add (struct GNUNET_TESTBED_Host *host) } -/** - * Adds a route to the route list - * - * @param route the route to add - */ -static void -route_list_add (struct Route *route) -{ - if (route->dest >= route_list_size) - array_grow_large_enough (route_list, route_list_size, route->dest); - GNUNET_assert (NULL == route_list[route->dest]); - route_list[route->dest] = route; -} - - -/** - * Adds a slave to the slave array - * - * @param slave the slave controller to add - */ -static void -slave_list_add (struct Slave *slave) -{ - if (slave->host_id >= GST_slave_list_size) - array_grow_large_enough (GST_slave_list, GST_slave_list_size, - slave->host_id); - GNUNET_assert (NULL == GST_slave_list[slave->host_id]); - GST_slave_list[slave->host_id] = slave; -} - - -/** - * Adds a peer to the peer array - * - * @param peer the peer to add - */ -static void -peer_list_add (struct Peer *peer) -{ - if (peer->id >= GST_peer_list_size) - 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; -} - - -/** - * Removes a the give peer from the peer array - * - * @param peer the peer to be removed - */ -static void -peer_list_remove (struct Peer *peer) -{ - unsigned int orig_size; - uint32_t id; - - GST_peer_list[peer->id] = NULL; - orig_size = GST_peer_list_size; - while (GST_peer_list_size >= LIST_GROW_STEP) - { - for (id = GST_peer_list_size - 1; - (id >= GST_peer_list_size - LIST_GROW_STEP) && (id != UINT32_MAX); - id--) - if (NULL != GST_peer_list[id]) - break; - if (id != ((GST_peer_list_size - LIST_GROW_STEP) - 1)) - break; - GST_peer_list_size -= LIST_GROW_STEP; - } - if (orig_size == GST_peer_list_size) - return; - GST_peer_list = - GNUNET_realloc (GST_peer_list, - sizeof (struct Peer *) * GST_peer_list_size); -} - - -/** - * Finds the route with directly connected host as destination through which - * the destination host can be reached - * - * @param host_id the id of the destination host - * @return the route with directly connected destination host; NULL if no route - * is found - */ -struct Route * -GST_find_dest_route (uint32_t host_id) -{ - struct Route *route; - - if (route_list_size <= host_id) - return NULL; - while (NULL != (route = route_list[host_id])) - { - if (route->thru == GST_context->host_id) - break; - host_id = route->thru; - } - return route; -} - - -/** - * Routes message to a host given its host_id - * - * @param host_id the id of the destination host - * @param msg the message to be routed - */ -static void -route_message (uint32_t host_id, const struct GNUNET_MessageHeader *msg) -{ - GNUNET_break (0); -} - - /** * Send operation failure message to client * @@ -476,9 +266,9 @@ GST_send_operation_fail_msg (struct GNUNET_SERVER_Client *client, * @param client the client to send the message to * @param operation_id the id of the operation which was successful */ -static void -send_operation_success_msg (struct GNUNET_SERVER_Client *client, - uint64_t operation_id) +void +GST_send_operation_success_msg (struct GNUNET_SERVER_Client *client, + uint64_t operation_id) { struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg; uint16_t msize; @@ -493,61 +283,6 @@ send_operation_success_msg (struct GNUNET_SERVER_Client *client, GST_queue_message (client, &msg->header); } - -/** - * Function to send a failure reponse for controller link operation - * - * @param client the client to send the message to - * @param operation_id the operation ID of the controller link request - * @param cfg the configuration with which the delegated controller is started. - * Can be NULL if the delegated controller is not started but just - * linked to. - * @param emsg set to an error message explaining why the controller link - * failed. Setting this to NULL signifies success. !This should be - * NULL if cfg is set! - */ -static void -send_controller_link_response (struct GNUNET_SERVER_Client *client, - uint64_t operation_id, - const struct GNUNET_CONFIGURATION_Handle - *cfg, - const char *emsg) -{ - struct GNUNET_TESTBED_ControllerLinkResponse *msg; - char *xconfig; - size_t config_size; - size_t xconfig_size; - uint16_t msize; - - GNUNET_assert ((NULL == cfg) || (NULL == emsg)); - xconfig = NULL; - xconfig_size = 0; - config_size = 0; - msize = sizeof (struct GNUNET_TESTBED_ControllerLinkResponse); - if (NULL != cfg) - { - xconfig = GNUNET_TESTBED_compress_cfg_ (cfg, - &config_size, - &xconfig_size); - msize += xconfig_size; - } - if (NULL != emsg) - msize += strlen (emsg); - msg = GNUNET_malloc (msize); - msg->header.type = htons - (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT); - msg->header.size = htons (msize); - if (NULL == emsg) - msg->success = htons (GNUNET_YES); - msg->operation_id = GNUNET_htonll (operation_id); - msg->config_size = htons ((uint16_t) config_size); - if (NULL != xconfig) - memcpy (&msg[1], xconfig, xconfig_size); - if (NULL != emsg) - memcpy (&msg[1], emsg, strlen (emsg)); - GST_queue_message (client, &msg->header); -} - /** * Callback which will be called after a host registration succeeded or failed * @@ -629,7 +364,7 @@ GST_queue_host_registration (struct Slave *slave, "Queueing host registration for host %u at %u\n", GNUNET_TESTBED_host_get_id_ (host), GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id])); - hr = GNUNET_malloc (sizeof (struct HostRegistration)); + hr = GNUNET_new (struct HostRegistration); hr->cb = cb; hr->cb_cls = cb_cls; hr->host = host; @@ -640,55 +375,6 @@ GST_queue_host_registration (struct Slave *slave, } -/** - * The Link Controller forwarding task - * - * @param cls the LCFContext - * @param tc the Task context from scheduler - */ -static void -lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); - - -/** - * Completion callback for host registrations while forwarding Link Controller messages - * - * @param cls the LCFContext - * @param emsg the error message; NULL if host registration is successful - */ -static void -lcf_proc_cc (void *cls, const char *emsg) -{ - struct LCFContext *lcf = cls; - - GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id); - switch (lcf->state) - { - case INIT: - if (NULL != emsg) - goto registration_error; - lcf->state = DELEGATED_HOST_REGISTERED; - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); - break; - case DELEGATED_HOST_REGISTERED: - if (NULL != emsg) - goto registration_error; - lcf->state = SLAVE_HOST_REGISTERED; - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); - break; - default: - GNUNET_assert (0); /* Shouldn't reach here */ - } - return; - -registration_error: - LOG (GNUNET_ERROR_TYPE_WARNING, "Host registration failed with message: %s\n", - emsg); - lcf->state = FINISHED; - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); -} - - /** * Callback to relay the reply msg of a forwarded operation back to the client * @@ -738,240 +424,53 @@ GST_forwarded_operation_timeout (void *cls, /** - * The Link Controller forwarding task - * - * @param cls the LCFContext - * @param tc the Task context from scheduler - */ -static void -lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); - - -/** - * Task to free resources when forwarded link controllers has been timedout - * - * @param cls the LCFContext - * @param tc the task context from scheduler - */ -static void -lcf_forwarded_operation_timeout (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct LCFContext *lcf = cls; - - lcf->timeout_task = GNUNET_SCHEDULER_NO_TASK; - // GST_forwarded_operation_timeout (lcf->fopc, tc); - LOG (GNUNET_ERROR_TYPE_WARNING, - "A forwarded controller link operation has timed out\n"); - send_controller_link_response (lcf->client, lcf->operation_id, NULL, - "A forwarded controller link operation has " - "timed out\n"); - GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id); - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); -} - - -/** - * The Link Controller forwarding task + * Parse service sharing specification line. + * Format is "[] [] ..." * - * @param cls the LCFContext - * @param tc the Task context from scheduler + * @param ss_str the spec string to be parsed + * @param cfg the configuration to use for shared services + * @return an array suitable to pass to GNUNET_TESTING_system_create(). NULL + * upon empty service sharing specification. */ -static void -lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +static struct GNUNET_TESTING_SharedService * +parse_shared_services (char *ss_str, struct GNUNET_CONFIGURATION_Handle *cfg) { - struct LCFContext *lcf = cls; - struct LCFContextQueue *lcfq; - - lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK; - switch (lcf->state) - { - case INIT: - if (GNUNET_NO == - GNUNET_TESTBED_is_host_registered_ (GST_host_list - [lcf->delegated_host_id], - lcf->gateway->controller)) - { - GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf, - GST_host_list[lcf->delegated_host_id]); - } - else - { - lcf->state = DELEGATED_HOST_REGISTERED; - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); - } - break; - case DELEGATED_HOST_REGISTERED: - if (GNUNET_NO == - GNUNET_TESTBED_is_host_registered_ (GST_host_list[lcf->slave_host_id], - lcf->gateway->controller)) - { - GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf, - GST_host_list[lcf->slave_host_id]); - } - else - { - lcf->state = SLAVE_HOST_REGISTERED; - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); - } - break; - case SLAVE_HOST_REGISTERED: - lcf->op = GNUNET_TESTBED_controller_link (lcf, - lcf->gateway->controller, - GST_host_list[lcf->delegated_host_id], - GST_host_list[lcf->slave_host_id], - NULL, - lcf->is_subordinate); - lcf->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, &lcf_forwarded_operation_timeout, - lcf); - lcf->state = FINISHED; - break; - case FINISHED: - lcfq = lcfq_head; - GNUNET_assert (lcfq->lcf == lcf); - GNUNET_assert (NULL != lcf->cfg); - GNUNET_CONFIGURATION_destroy (lcf->cfg); - GNUNET_SERVER_client_drop (lcf->client); - GNUNET_TESTBED_operation_done (lcf->op); - GNUNET_free (lcf); - GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq); - GNUNET_free (lcfq); - if (NULL != lcfq_head) - lcf_proc_task_id = - GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq_head->lcf); - } -} - + struct GNUNET_TESTING_SharedService ss; + struct GNUNET_TESTING_SharedService *slist; + char service[256]; + char *arg; + unsigned int n; +#define GROW_SS \ + do { \ + GNUNET_array_grow (slist, n, n+1); \ + (void) memcpy (&slist[n - 1], &ss, \ + sizeof (struct GNUNET_TESTING_SharedService)); \ + } while (0) -/** - * Callback for event from slave controllers - * - * @param cls struct Slave * - * @param event information about the event - */ -static void -slave_event_callback (void *cls, - const struct GNUNET_TESTBED_EventInformation *event) -{ - struct RegisteredHostContext *rhc; - struct LCFContext *lcf; - struct GNUNET_CONFIGURATION_Handle *cfg; - struct GNUNET_TESTBED_Operation *old_op; - - /* We currently only get here when working on RegisteredHostContexts and - LCFContexts */ - GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type); - rhc = event->op_cls; - if (CLOSURE_TYPE_RHC == rhc->type) + slist = NULL; + n = 0; + ss.cfg = cfg; + for (; NULL != (arg = strtok (ss_str, " ")); ss_str = NULL) { - GNUNET_assert (rhc->sub_op == event->op); - switch (rhc->state) + ss.service = NULL; + ss.share = 0; + if (2 != sscanf (arg, "%255[^:]:%u", service, &ss.share)) { - case RHC_GET_CFG: - cfg = event->details.operation_finished.generic; - old_op = rhc->sub_op; - rhc->state = RHC_LINK; - rhc->sub_op = - GNUNET_TESTBED_controller_link (rhc, rhc->gateway->controller, - rhc->reg_host, rhc->host, cfg, - GNUNET_NO); - GNUNET_TESTBED_operation_done (old_op); - break; - case RHC_LINK: - LOG_DEBUG ("OL: Linking controllers successfull\n"); - GNUNET_TESTBED_operation_done (rhc->sub_op); - rhc->sub_op = NULL; - rhc->state = RHC_OL_CONNECT; - GST_process_next_focc (rhc); - break; - default: - GNUNET_assert (0); + LOG (GNUNET_ERROR_TYPE_WARNING, "Ignoring shared service spec: %s", arg); + continue; } - return; - } - lcf = event->op_cls; - if (CLOSURE_TYPE_LCF == lcf->type) - { - GNUNET_assert (lcf->op == event->op); - 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_ - (GST_host_list[lcf->delegated_host_id]), - NULL); - else - send_controller_link_response (lcf->client, lcf->operation_id, - NULL, - event->details.operation_finished.emsg); - GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id); - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); - return; - } - GNUNET_assert (0); -} - - -/** - * Callback to signal successfull startup of the controller process - * - * @param cls the handle to the slave whose status is to be found here - * @param cfg the configuration with which the controller has been started; - * NULL if status is not GNUNET_OK - * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not, - * GNUNET_TESTBED_controller_stop() shouldn't be called in this case - */ -static void -slave_status_callback (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, - int status) -{ - struct Slave *slave = cls; - struct LinkControllersContext *lcc; - - lcc = slave->lcc; - if (GNUNET_SYSERR == status) - { - slave->controller_proc = NULL; - GST_slave_list[slave->host_id] = NULL; - GNUNET_free (slave); - slave = NULL; - LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected slave shutdown\n"); - GNUNET_SCHEDULER_shutdown (); /* We too shutdown */ - goto clean_lcc; + LOG_DEBUG ("Will be sharing %s service among %u peers\n", service, ss.share); + ss.service = GNUNET_strdup (service); + GROW_SS; } - slave->controller = - GNUNET_TESTBED_controller_connect (cfg, GST_host_list[slave->host_id], - event_mask, &slave_event_callback, - slave); - if (NULL != slave->controller) + if (NULL != slist) { - send_controller_link_response (lcc->client, lcc->operation_id, cfg, NULL); - } - else - { - 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); - slave = NULL; - } - -clean_lcc: - if (NULL != lcc) - { - if (NULL != lcc->client) - { - GNUNET_SERVER_receive_done (lcc->client, GNUNET_OK); - GNUNET_SERVER_client_drop (lcc->client); - lcc->client = NULL; - } - GNUNET_free (lcc); + /* Add trailing NULL block */ + (void) memset (&ss, 0, sizeof (struct GNUNET_TESTING_SharedService)); + GROW_SS; } - if (NULL != slave) - slave->lcc = NULL; + return slist; +#undef GROW_SS } @@ -989,6 +488,9 @@ handle_init (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_TESTBED_InitMessage *msg; struct GNUNET_TESTBED_Host *host; const char *controller_hostname; + char *ss_str; + struct GNUNET_TESTING_SharedService *ss; + unsigned int cnt; uint16_t msize; if (NULL != GST_context) @@ -1013,7 +515,17 @@ handle_init (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - GST_context = GNUNET_malloc (sizeof (struct Context)); + ss_str = NULL; + ss = NULL; + if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (GST_config, "TESTBED", + "SHARED_SERVICES", + &ss_str)) + { + ss = parse_shared_services (ss_str, GST_config); + GNUNET_free (ss_str); + ss_str = NULL; + } + GST_context = GNUNET_new (struct Context); GNUNET_SERVER_client_keep (client); GST_context->client = client; GST_context->host_id = ntohl (msg->host_id); @@ -1021,11 +533,21 @@ handle_init (void *cls, struct GNUNET_SERVER_Client *client, LOG_DEBUG ("Our IP: %s\n", GST_context->master_ip); GST_context->system = GNUNET_TESTING_system_create ("testbed", GST_context->master_ip, - hostname); + hostname, ss); + if (NULL != ss) + { + for (cnt = 0; NULL != ss[cnt].service; cnt++) + { + ss_str = (char *) ss[cnt].service; + GNUNET_free (ss_str); + } + GNUNET_free (ss); + ss = NULL; + } host = GNUNET_TESTBED_host_create_with_id (GST_context->host_id, GST_context->master_ip, NULL, - our_config, 0); + GST_config, 0); host_list_add (host); LOG_DEBUG ("Created master context with host ID: %u\n", GST_context->host_id); GNUNET_SERVER_receive_done (client, GNUNET_OK); @@ -1068,7 +590,7 @@ handle_add_host (void *cls, struct GNUNET_SERVER_Client *client, username_length = ntohs (msg->username_length); hostname_length = ntohs (msg->hostname_length); /* msg must contain hostname */ - if ((msize <= (sizeof (struct GNUNET_TESTBED_AddHostMessage) + + if ((msize <= (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length)) || (0 == hostname_length)) { @@ -1095,7 +617,6 @@ handle_add_host (void *cls, struct GNUNET_SERVER_Client *client, } hostname = GNUNET_malloc (hostname_length + 1); strncpy (hostname, ptr, hostname_length); - ptr += hostname_length; if (NULL == (host_cfg = GNUNET_TESTBED_extract_config_ (message))) { GNUNET_free_non_null (username); @@ -1150,825 +671,36 @@ handle_add_host (void *cls, struct GNUNET_SERVER_Client *client, /** - * Iterator over hash map entries. - * - * @param cls closure - * @param key current key code - * @param value value in the hash map - * @return GNUNET_YES if we should continue to - * iterate, - * GNUNET_NO if not. - */ -int -ss_exists_iterator (void *cls, const struct GNUNET_HashCode *key, void *value) -{ - struct SharedService *queried_ss = cls; - struct SharedService *ss = value; - - if (0 == strcmp (ss->name, queried_ss->name)) - return GNUNET_NO; - else - return GNUNET_YES; -} - - -/** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages + * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ static void -handle_configure_shared_service (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_slave_get_config (void *cls, struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) { - const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg; - struct SharedService *ss; - char *service_name; - struct GNUNET_HashCode hash; - uint16_t msg_size; - uint16_t service_name_size; - - msg = (const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *) message; - msg_size = ntohs (message->size); - if (msg_size <= sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage)) + struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg; + struct Slave *slave; + struct GNUNET_TESTBED_SlaveConfiguration *reply; + const struct GNUNET_CONFIGURATION_Handle *cfg; + char *config; + char *xconfig; + size_t config_size; + size_t xconfig_size; + size_t reply_size; + uint64_t op_id; + uint32_t slave_id; + + msg = (struct GNUNET_TESTBED_SlaveGetConfigurationMessage *) message; + slave_id = ntohl (msg->slave_id); + op_id = GNUNET_ntohll (msg->operation_id); + if ((GST_slave_list_size <= slave_id) || (NULL == GST_slave_list[slave_id])) { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - service_name_size = - msg_size - sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage); - service_name = (char *) &msg[1]; - if ('\0' != service_name[service_name_size - 1]) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - LOG_DEBUG ("Received service sharing request for %s, with %d peers\n", - service_name, ntohl (msg->num_peers)); - if (ntohl (msg->host_id) != GST_context->host_id) - { - route_message (ntohl (msg->host_id), message); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - GNUNET_SERVER_receive_done (client, GNUNET_OK); - ss = GNUNET_malloc (sizeof (struct SharedService)); - ss->name = strdup (service_name); - ss->num_shared = ntohl (msg->num_peers); - GNUNET_CRYPTO_hash (ss->name, service_name_size, &hash); - if (GNUNET_SYSERR == - GNUNET_CONTAINER_multihashmap_get_multiple (ss_map, &hash, - &ss_exists_iterator, ss)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Service %s already configured as a shared service. " - "Ignoring service sharing request \n", ss->name); - GNUNET_free (ss->name); - GNUNET_free (ss); - return; - } - GNUNET_CONTAINER_multihashmap_put (ss_map, &hash, ss, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); -} - - -/** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message - * - * @param cls NULL - * @param client identification of the client - * @param message the actual message - */ -static void -handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - const struct GNUNET_TESTBED_ControllerLinkRequest *msg; - struct GNUNET_CONFIGURATION_Handle *cfg; - struct LCFContextQueue *lcfq; - struct Route *route; - struct Route *new_route; - uint32_t delegated_host_id; - uint32_t slave_host_id; - uint16_t msize; - - if (NULL == GST_context) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - msize = ntohs (message->size); - if (sizeof (struct GNUNET_TESTBED_ControllerLinkRequest) >= msize) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - msg = (const struct GNUNET_TESTBED_ControllerLinkRequest *) message; - delegated_host_id = ntohl (msg->delegated_host_id); - if (delegated_host_id == GST_context->host_id) - { - GNUNET_break (0); - LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n"); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - if ((delegated_host_id >= GST_host_list_size) || - (NULL == GST_host_list[delegated_host_id])) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Delegated host %u not registered with us\n", delegated_host_id); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - slave_host_id = ntohl (msg->slave_host_id); - if ((slave_host_id >= GST_host_list_size) || - (NULL == GST_host_list[slave_host_id])) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host %u not registered with us\n", - slave_host_id); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - if (slave_host_id == delegated_host_id) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n"); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - cfg = GNUNET_TESTBED_extract_config_ (message); /* destroy cfg here or in lcfcontext */ - if (NULL == cfg) - { - GNUNET_break (0); /* Configuration parsing error */ - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - if (slave_host_id == GST_context->host_id) /* Link from us */ - { - struct Slave *slave; - struct LinkControllersContext *lcc; - - if ((delegated_host_id < GST_slave_list_size) && - (NULL != GST_slave_list[delegated_host_id])) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - 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 (cfg, 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); - GNUNET_SERVER_client_keep (client); - lcc->client = client; - slave->lcc = lcc; - slave->controller_proc = - GNUNET_TESTBED_controller_start (GST_context->master_ip, - GST_host_list[slave->host_id], cfg, - &slave_status_callback, slave); - GNUNET_CONFIGURATION_destroy (cfg); - new_route = GNUNET_malloc (sizeof (struct Route)); - new_route->dest = delegated_host_id; - new_route->thru = GST_context->host_id; - route_list_add (new_route); - return; - } - - /* Route the request */ - if (slave_host_id >= route_list_size) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host"); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue)); - lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext)); - lcfq->lcf->type = CLOSURE_TYPE_LCF; - lcfq->lcf->delegated_host_id = delegated_host_id; - lcfq->lcf->slave_host_id = slave_host_id; - route = GST_find_dest_route (slave_host_id); - GNUNET_assert (NULL != route); /* because we add routes carefully */ - GNUNET_assert (route->dest < GST_slave_list_size); - GNUNET_assert (NULL != GST_slave_list[route->dest]); - 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->gateway = GST_slave_list[route->dest]; - GNUNET_SERVER_client_keep (client); - lcfq->lcf->client = client; - if (NULL == lcfq_head) - { - GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id); - GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq); - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq->lcf); - } - else - GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq); - /* FIXME: Adding a new route should happen after the controllers are linked - * successfully */ - if (1 != msg->is_subordinate) - { - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - if ((delegated_host_id < route_list_size) && - (NULL != route_list[delegated_host_id])) - { - GNUNET_break_op (0); /* Are you trying to link delegated host twice - * with is subordinate flag set to GNUNET_YES? */ - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - new_route = GNUNET_malloc (sizeof (struct Route)); - new_route->dest = delegated_host_id; - new_route->thru = route->dest; - route_list_add (new_route); - GNUNET_SERVER_receive_done (client, GNUNET_OK); -} - - -/** - * The task to be executed if the forwarded peer create operation has been - * timed out - * - * @param cls the FowardedOperationContext - * @param tc the TaskContext from the scheduler - */ -static void -peer_create_forward_timeout (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct ForwardedOperationContext *fopc = cls; - - GNUNET_free (fopc->cls); - GST_forwarded_operation_timeout (fopc, tc); -} - - -/** - * Callback to be called when forwarded peer create operation is successfull. We - * have to relay the reply msg back to the client - * - * @param cls ForwardedOperationContext - * @param msg the peer create success message - */ -static void -peer_create_success_cb (void *cls, const struct GNUNET_MessageHeader *msg) -{ - struct ForwardedOperationContext *fopc = cls; - struct Peer *remote_peer; - - if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS) - { - GNUNET_assert (NULL != fopc->cls); - remote_peer = fopc->cls; - peer_list_add (remote_peer); - } - GST_forwarded_operation_reply_relay (fopc, msg); -} - - -/** - * Function to destroy a peer - * - * @param peer the peer structure to destroy - */ -void -GST_destroy_peer (struct Peer *peer) -{ - GNUNET_break (0 == peer->reference_cnt); - if (GNUNET_YES == peer->is_remote) - { - peer_list_remove (peer); - GNUNET_free (peer); - return; - } - if (GNUNET_YES == peer->details.local.is_running) - { - GNUNET_TESTING_peer_stop (peer->details.local.peer); - peer->details.local.is_running = GNUNET_NO; - } - GNUNET_TESTING_peer_destroy (peer->details.local.peer); - GNUNET_CONFIGURATION_destroy (peer->details.local.cfg); - peer_list_remove (peer); - GNUNET_free (peer); -} - - -/** - * Callback to be called when forwarded peer destroy operation is successfull. We - * have to relay the reply msg back to the client - * - * @param cls ForwardedOperationContext - * @param msg the peer create success message - */ -static void -peer_destroy_success_cb (void *cls, const struct GNUNET_MessageHeader *msg) -{ - struct ForwardedOperationContext *fopc = cls; - struct Peer *remote_peer; - - if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS == - ntohs (msg->type)) - { - remote_peer = fopc->cls; - GNUNET_assert (NULL != remote_peer); - remote_peer->destroy_flag = GNUNET_YES; - if (0 == remote_peer->reference_cnt) - GST_destroy_peer (remote_peer); - } - GST_forwarded_operation_reply_relay (fopc, msg); -} - - - -/** - * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages - * - * @param cls NULL - * @param client identification of the client - * @param message the actual message - */ -static void -handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - const struct GNUNET_TESTBED_PeerCreateMessage *msg; - struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply; - struct GNUNET_CONFIGURATION_Handle *cfg; - struct ForwardedOperationContext *fo_ctxt; - struct Route *route; - struct Peer *peer; - char *config; - size_t dest_size; - int ret; - uint32_t config_size; - uint32_t host_id; - uint32_t peer_id; - uint16_t msize; - - - msize = ntohs (message->size); - if (msize <= sizeof (struct GNUNET_TESTBED_PeerCreateMessage)) - { - GNUNET_break (0); /* We need configuration */ - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message; - host_id = ntohl (msg->host_id); - peer_id = ntohl (msg->peer_id); - 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); - return; - } - if (host_id == GST_context->host_id) - { - char *emsg; - - /* We are responsible for this peer */ - msize -= sizeof (struct GNUNET_TESTBED_PeerCreateMessage); - config_size = ntohl (msg->config_size); - config = GNUNET_malloc (config_size); - dest_size = config_size; - if (Z_OK != - (ret = - uncompress ((Bytef *) config, (uLongf *) & dest_size, - (const Bytef *) &msg[1], (uLong) msize))) - { - GNUNET_break (0); /* uncompression error */ - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - if (config_size != dest_size) - { - GNUNET_break (0); /* Uncompressed config size mismatch */ - GNUNET_free (config); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - cfg = GNUNET_CONFIGURATION_create (); - if (GNUNET_OK != - GNUNET_CONFIGURATION_deserialize (cfg, config, config_size, GNUNET_NO)) - { - GNUNET_break (0); /* Configuration parsing error */ - GNUNET_free (config); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - GNUNET_free (config); - GNUNET_CONFIGURATION_set_value_number (cfg, "TESTBED", "PEERID", - (unsigned long long) peer_id); - peer = GNUNET_malloc (sizeof (struct Peer)); - peer->is_remote = GNUNET_NO; - peer->details.local.cfg = cfg; - peer->id = peer_id; - LOG_DEBUG ("Creating peer with id: %u\n", (unsigned int) peer->id); - 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) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg); - GNUNET_free (emsg); - GNUNET_free (peer); - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - peer->details.local.is_running = GNUNET_NO; - peer_list_add (peer); - reply = - GNUNET_malloc (sizeof - (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage)); - reply->header.size = - htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage)); - reply->header.type = - htons (GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS); - reply->peer_id = msg->peer_id; - reply->operation_id = msg->operation_id; - GST_queue_message (client, &reply->header); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - - /* Forward peer create request */ - route = GST_find_dest_route (host_id); - if (NULL == route) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - - peer = GNUNET_malloc (sizeof (struct Peer)); - peer->is_remote = GNUNET_YES; - peer->id = peer_id; - peer->details.remote.slave = GST_slave_list[route->dest]; - peer->details.remote.remote_host_id = host_id; - fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); - GNUNET_SERVER_client_keep (client); - fo_ctxt->client = client; - fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id); - fo_ctxt->cls = peer; //GST_slave_list[route->dest]->controller; - fo_ctxt->type = OP_PEER_CREATE; - fo_ctxt->opc = - GNUNET_TESTBED_forward_operation_msg_ (GST_slave_list - [route->dest]->controller, - fo_ctxt->operation_id, - &msg->header, - peer_create_success_cb, fo_ctxt); - fo_ctxt->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, &peer_create_forward_timeout, - fo_ctxt); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fo_ctxt); - GNUNET_SERVER_receive_done (client, GNUNET_OK); -} - - -/** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages - * - * @param cls NULL - * @param client identification of the client - * @param message the actual message - */ -static void -handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - const struct GNUNET_TESTBED_PeerDestroyMessage *msg; - struct ForwardedOperationContext *fopc; - struct Peer *peer; - uint32_t peer_id; - - msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message; - peer_id = ntohl (msg->peer_id); - LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n", - peer_id, GNUNET_ntohll (msg->operation_id)); - if ((GST_peer_list_size <= peer_id) || (NULL == GST_peer_list[peer_id])) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Asked to destroy a non existent peer with id: %u\n", peer_id); - GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), - "Peer doesn't exist"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - peer = GST_peer_list[peer_id]; - if (GNUNET_YES == peer->is_remote) - { - /* Forward the destory message to sub controller */ - fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); - GNUNET_SERVER_client_keep (client); - fopc->client = client; - fopc->cls = peer; - fopc->type = OP_PEER_DESTROY; - fopc->operation_id = GNUNET_ntohll (msg->operation_id); - fopc->opc = - GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. - slave->controller, - fopc->operation_id, &msg->header, - &peer_destroy_success_cb, fopc); - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, - fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - peer->destroy_flag = GNUNET_YES; - if (0 == peer->reference_cnt) - GST_destroy_peer (peer); - else - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Delaying peer destroy as peer is currently in use\n"); - send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id)); - GNUNET_SERVER_receive_done (client, GNUNET_OK); -} - - -/** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages - * - * @param cls NULL - * @param client identification of the client - * @param message the actual message - */ -static void -handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - const struct GNUNET_TESTBED_PeerStartMessage *msg; - struct GNUNET_TESTBED_PeerEventMessage *reply; - struct ForwardedOperationContext *fopc; - struct Peer *peer; - uint32_t peer_id; - - msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message; - peer_id = ntohl (msg->peer_id); - if ((peer_id >= GST_peer_list_size) || (NULL == GST_peer_list[peer_id])) - { - GNUNET_break (0); - LOG (GNUNET_ERROR_TYPE_ERROR, - "Asked to start a non existent peer with id: %u\n", peer_id); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - peer = GST_peer_list[peer_id]; - if (GNUNET_YES == peer->is_remote) - { - fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); - GNUNET_SERVER_client_keep (client); - fopc->client = client; - fopc->operation_id = GNUNET_ntohll (msg->operation_id); - fopc->type = OP_PEER_START; - fopc->opc = - GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. - slave->controller, - fopc->operation_id, &msg->header, - &GST_forwarded_operation_reply_relay, - fopc); - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, - fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - if (GNUNET_OK != GNUNET_TESTING_peer_start (peer->details.local.peer)) - { - GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), - "Failed to start"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - peer->details.local.is_running = GNUNET_YES; - reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); - reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); - reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); - reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START); - reply->host_id = htonl (GST_context->host_id); - reply->peer_id = msg->peer_id; - reply->operation_id = msg->operation_id; - GST_queue_message (client, &reply->header); - GNUNET_SERVER_receive_done (client, GNUNET_OK); -} - - -/** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages - * - * @param cls NULL - * @param client identification of the client - * @param message the actual message - */ -static void -handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - const struct GNUNET_TESTBED_PeerStopMessage *msg; - struct GNUNET_TESTBED_PeerEventMessage *reply; - struct ForwardedOperationContext *fopc; - struct Peer *peer; - uint32_t peer_id; - - msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message; - peer_id = ntohl (msg->peer_id); - LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PEER_STOP for peer %u\n", peer_id); - if ((peer_id >= GST_peer_list_size) || (NULL == GST_peer_list[peer_id])) - { - GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), - "Peer not found"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - peer = GST_peer_list[peer_id]; - if (GNUNET_YES == peer->is_remote) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "Forwarding PEER_STOP for peer %u\n", - peer_id); - fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); - GNUNET_SERVER_client_keep (client); - fopc->client = client; - fopc->operation_id = GNUNET_ntohll (msg->operation_id); - fopc->type = OP_PEER_STOP; - fopc->opc = - GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. - slave->controller, - fopc->operation_id, &msg->header, - &GST_forwarded_operation_reply_relay, - fopc); - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, - fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - if (GNUNET_OK != GNUNET_TESTING_peer_kill (peer->details.local.peer)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "Stopping peer %u failed\n", peer_id); - GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), - "Peer not running"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %u successfully stopped\n", peer_id); - peer->details.local.is_running = GNUNET_NO; - reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); - reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); - reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); - reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP); - reply->host_id = htonl (GST_context->host_id); - reply->peer_id = msg->peer_id; - reply->operation_id = msg->operation_id; - GST_queue_message (client, &reply->header); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - GNUNET_TESTING_peer_wait (peer->details.local.peer); -} - - -/** - * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages - * - * @param cls NULL - * @param client identification of the client - * @param message the actual message - */ -static void -handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg; - struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply; - struct Peer *peer; - char *config; - char *xconfig; - size_t c_size; - size_t xc_size; - uint32_t peer_id; - uint16_t msize; - - msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message; - peer_id = ntohl (msg->peer_id); - if ((peer_id >= GST_peer_list_size) || (NULL == GST_peer_list[peer_id])) - { - GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), - "Peer not found"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - peer = GST_peer_list[peer_id]; - if (GNUNET_YES == peer->is_remote) - { - struct ForwardedOperationContext *fopc; - - LOG_DEBUG ("Forwarding PEER_GET_CONFIG for peer: %u\n", peer_id); - fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); - GNUNET_SERVER_client_keep (client); - fopc->client = client; - fopc->operation_id = GNUNET_ntohll (msg->operation_id); - fopc->type = OP_PEER_INFO; - fopc->opc = - GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. - slave->controller, - fopc->operation_id, &msg->header, - &GST_forwarded_operation_reply_relay, - fopc); - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, - fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - LOG_DEBUG ("Received PEER_GET_CONFIG for peer: %u\n", peer_id); - config = - GNUNET_CONFIGURATION_serialize (GST_peer_list[peer_id]->details.local.cfg, - &c_size); - xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig); - GNUNET_free (config); - msize = - xc_size + - sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage); - 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->peer_id = msg->peer_id; - reply->operation_id = msg->operation_id; - GNUNET_TESTING_peer_get_identity (GST_peer_list[peer_id]->details.local.peer, - &reply->peer_identity); - reply->config_size = htons ((uint16_t) c_size); - GST_queue_message (client, &reply->header); - GNUNET_SERVER_receive_done (client, GNUNET_OK); -} - - -/** - * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages - * - * @param cls NULL - * @param client identification of the client - * @param message the actual message - */ -static void -handle_slave_get_config (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg; - struct Slave *slave; - struct GNUNET_TESTBED_SlaveConfiguration *reply; - const struct GNUNET_CONFIGURATION_Handle *cfg; - char *config; - char *xconfig; - size_t config_size; - size_t xconfig_size; - size_t reply_size; - uint64_t op_id; - uint32_t slave_id; - - msg = (struct GNUNET_TESTBED_SlaveGetConfigurationMessage *) message; - slave_id = ntohl (msg->slave_id); - op_id = GNUNET_ntohll (msg->operation_id); - if ((GST_slave_list_size <= slave_id) || (NULL == GST_slave_list[slave_id])) - { - /* FIXME: Add forwardings for this type of message here.. */ - GST_send_operation_fail_msg (client, op_id, "Slave not found"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + /* FIXME: Add forwardings for this type of message here.. */ + GST_send_operation_fail_msg (client, op_id, "Slave not found"); + GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } slave = GST_slave_list[slave_id]; @@ -1991,289 +723,15 @@ handle_slave_get_config (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_SERVER_receive_done (client, GNUNET_OK); } -struct ManageServiceContext -{ - - struct ManageServiceContext *next; - - struct ManageServiceContext *prev; - - struct GNUNET_ARM_Handle *ah; - - struct Peer *peer; - - struct GNUNET_SERVER_Client *client; - - uint64_t op_id; - - uint8_t start; - - uint8_t expired; - -}; - -static struct ManageServiceContext *mctx_head; - -static struct ManageServiceContext *mctx_tail; - -static void -cleanup_mctx (struct ManageServiceContext *mctx) -{ - mctx->expired = GNUNET_YES; - GNUNET_CONTAINER_DLL_remove (mctx_head, mctx_tail, mctx); - GNUNET_SERVER_client_drop (mctx->client); - GNUNET_ARM_disconnect_and_free (mctx->ah); - GNUNET_assert (0 < mctx->peer->reference_cnt); - mctx->peer->reference_cnt--; - if ( (GNUNET_YES == mctx->peer->destroy_flag) - && (0 == mctx->peer->reference_cnt) ) - GST_destroy_peer (mctx->peer); - GNUNET_free (mctx); -} - -static void -free_mctxq () -{ - while (NULL != mctx_head) - cleanup_mctx (mctx_head); -} - -static const char * -arm_req_string (enum GNUNET_ARM_RequestStatus rs) -{ - switch (rs) - { - case GNUNET_ARM_REQUEST_SENT_OK: - return _("Message was sent successfully"); - case GNUNET_ARM_REQUEST_CONFIGURATION_ERROR: - return _("Misconfiguration (can't connect to the ARM service)"); - case GNUNET_ARM_REQUEST_DISCONNECTED: - return _("We disconnected from ARM before we could send a request"); - case GNUNET_ARM_REQUEST_BUSY: - return _("ARM API is busy"); - case GNUNET_ARM_REQUEST_TOO_LONG: - return _("Request doesn't fit into a message"); - case GNUNET_ARM_REQUEST_TIMEOUT: - return _("Request timed out"); - } - return _("Unknown request status"); -} - -static const char * -arm_ret_string (enum GNUNET_ARM_Result result) -{ - switch (result) - { - case GNUNET_ARM_RESULT_STOPPED: - return _("%s is stopped"); - case GNUNET_ARM_RESULT_STARTING: - return _("%s is starting"); - case GNUNET_ARM_RESULT_STOPPING: - return _("%s is stopping"); - case GNUNET_ARM_RESULT_IS_STARTING_ALREADY: - return _("%s is starting already"); - case GNUNET_ARM_RESULT_IS_STOPPING_ALREADY: - return _("%s is stopping already"); - case GNUNET_ARM_RESULT_IS_STARTED_ALREADY: - return _("%s is started already"); - case GNUNET_ARM_RESULT_IS_STOPPED_ALREADY: - return _("%s is stopped already"); - case GNUNET_ARM_RESULT_IS_NOT_KNOWN: - return _("%s service is not known to ARM"); - case GNUNET_ARM_RESULT_START_FAILED: - return _("%s service failed to start"); - case GNUNET_ARM_RESULT_IN_SHUTDOWN: - return _("%s service can't be started because ARM is shutting down"); - } - return _("%.s Unknown result code."); -} - -static void -service_manage_result_cb (void *cls, struct GNUNET_ARM_Handle *arm, - enum GNUNET_ARM_RequestStatus rs, - const char *service, enum GNUNET_ARM_Result result) -{ - struct ManageServiceContext *mctx = cls; - char *emsg; - - emsg = NULL; - if (GNUNET_YES == mctx->expired) - return; - if (GNUNET_ARM_REQUEST_SENT_OK != rs) - { - GNUNET_asprintf (&emsg, "Error communicating with Peer %u's ARM: %s", - mctx->peer->id, arm_req_string (rs)); - goto ret; - } - if (1 == mctx->start) - goto service_start_check; - if (! ((GNUNET_ARM_RESULT_STOPPED == result) - || (GNUNET_ARM_RESULT_STOPPING == result) - || (GNUNET_ARM_RESULT_IS_STOPPING_ALREADY == result) - || (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY == result)) ) - { - /* stopping a service failed */ - GNUNET_asprintf (&emsg, arm_ret_string (result), service); - goto ret; - } - /* service stopped successfully */ - goto ret; - - service_start_check: - if (! ((GNUNET_ARM_RESULT_STARTING == result) - || (GNUNET_ARM_RESULT_IS_STARTING_ALREADY == result) - || (GNUNET_ARM_RESULT_IS_STARTED_ALREADY == result)) ) - { - /* starting a service failed */ - GNUNET_asprintf (&emsg, arm_ret_string (result), service); - goto ret; - } - /* service started successfully */ - - ret: - if (NULL != emsg) - { - LOG_DEBUG ("%s\n", emsg); - GST_send_operation_fail_msg (mctx->client, mctx->op_id, emsg); - } - else - send_operation_success_msg (mctx->client, mctx->op_id); - GNUNET_free_non_null (emsg); - cleanup_mctx (mctx); -} - -static void -handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - const struct GNUNET_TESTBED_ManagePeerServiceMessage *msg; - const char* service; - struct Peer *peer; - char *emsg; - struct GNUNET_ARM_Handle *ah; - struct ManageServiceContext *mctx; - struct ForwardedOperationContext *fopc; - 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_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - msg = (const struct GNUNET_TESTBED_ManagePeerServiceMessage *) message; - service = (const char *) &msg[1]; - if ('\0' != service[msize - sizeof - (struct GNUNET_TESTBED_ManagePeerServiceMessage) - 1]) - { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - if (1 < msg->start) - { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - peer_id = ntohl (msg->peer_id); - op_id = GNUNET_ntohll (msg->operation_id); - LOG_DEBUG ("Received request to manage service %s on peer %u\n", - service, (unsigned int) peer_id); - if ((GST_peer_list_size <= peer_id) - || (NULL == (peer = GST_peer_list[peer_id]))) - { - GNUNET_asprintf (&emsg, "Asked to manage service of a non existent peer " - "with id: %u", peer_id); - goto err_ret; - } - if (0 == strcasecmp ("arm", service)) - { - emsg = GNUNET_strdup ("Cannot start/stop peer's ARM service. " - "Use peer start/stop for that"); - goto err_ret; - } - if (GNUNET_YES == peer->is_remote) - { - /* Forward the destory message to sub controller */ - fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); - GNUNET_SERVER_client_keep (client); - fopc->client = client; - fopc->cls = peer; - fopc->type = OP_MANAGE_SERVICE; - fopc->operation_id = op_id; - fopc->opc = - GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. - slave->controller, - fopc->operation_id, &msg->header, - &GST_forwarded_operation_reply_relay, - fopc); - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, - fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - if ((0 != peer->reference_cnt) - && ( (0 == strcasecmp ("core", service)) - || (0 == strcasecmp ("transport", service)) ) ) - { - GNUNET_asprintf (&emsg, "Cannot stop %s service of peer with id: %u " - "since it is required by existing operations", - service, peer_id); - goto err_ret; - } - ah = GNUNET_ARM_connect (peer->details.local.cfg, NULL, NULL); - if (NULL == ah) - { - GNUNET_asprintf (&emsg, - "Cannot connect to ARM service of peer with id: %u", - peer_id); - goto err_ret; - } - mctx = GNUNET_malloc (sizeof (struct ManageServiceContext)); - mctx->peer = peer; - peer->reference_cnt++; - mctx->op_id = op_id; - mctx->ah = ah; - GNUNET_SERVER_client_keep (client); - mctx->client = client; - mctx->start = msg->start; - GNUNET_CONTAINER_DLL_insert_tail (mctx_head, mctx_tail, mctx); - if (1 == mctx->start) - GNUNET_ARM_request_service_start (mctx->ah, service, - GNUNET_OS_INHERIT_STD_ERR, - GST_timeout, - service_manage_result_cb, - mctx); - else - GNUNET_ARM_request_service_stop (mctx->ah, service, - GST_timeout, - service_manage_result_cb, - mctx); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - - err_ret: - LOG (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg); - GST_send_operation_fail_msg (client, op_id, emsg); - GNUNET_free (emsg); - GNUNET_SERVER_receive_done (client, GNUNET_OK); -} /** * Clears the forwarded operations queue */ -static void -clear_fopcq () +void +GST_clear_fopcq () { struct ForwardedOperationContext *fopc; - + while (NULL != (fopc = fopcq_head)) { GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc); @@ -2289,7 +747,7 @@ clear_fopcq () case OP_SHUTDOWN_PEERS: { struct HandlerContext_ShutdownPeers *hc = fopc->cls; - + GNUNET_assert (0 < hc->nslaves); hc->nslaves--; if (0 == hc->nslaves) @@ -2304,6 +762,7 @@ clear_fopcq () case OP_LINK_CONTROLLERS: case OP_GET_SLAVE_CONFIG: case OP_MANAGE_SERVICE: + case OP_PEER_RECONFIGURE: break; case OP_FORWARDED: GNUNET_assert (0); @@ -2313,242 +772,6 @@ clear_fopcq () } -/** - * Task run upon timeout of forwarded SHUTDOWN_PEERS operation - * - * @param cls the ForwardedOperationContext - * @param tc the scheduler task context - */ -static void -shutdown_peers_timeout_cb (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct ForwardedOperationContext *fo_ctxt = cls; - struct HandlerContext_ShutdownPeers *hc; - - fo_ctxt->timeout_task = GNUNET_SCHEDULER_NO_TASK; - hc = fo_ctxt->cls; - hc->timeout = GNUNET_YES; - 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_SERVER_client_drop (fo_ctxt->client); - GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fo_ctxt); - GNUNET_free (fo_ctxt); -} - - -/** - * The reply msg handler forwarded SHUTDOWN_PEERS operation. Checks if a - * success reply is received from all clients and then sends the success message - * to the client - * - * @param cls ForwardedOperationContext - * @param msg the message to relay - */ -static void -shutdown_peers_reply_cb (void *cls, - const struct GNUNET_MessageHeader *msg) -{ - 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 != - ntohs (msg->type)) - hc->timeout = GNUNET_YES; - if (0 == hc->nslaves) - { - if (GNUNET_YES == hc->timeout) - GST_send_operation_fail_msg (fo_ctxt->client, fo_ctxt->operation_id, - "Timeout at a slave controller"); - else - send_operation_success_msg (fo_ctxt->client, fo_ctxt->operation_id); - } - GNUNET_SERVER_client_drop (fo_ctxt->client); - GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fo_ctxt); - GNUNET_free (fo_ctxt); -} - - -/** - * Stops and destroys all peers - */ -static void -destroy_peers () -{ - struct Peer *peer; - unsigned int id; - - if (NULL == GST_peer_list) - return; - for (id = 0; id < GST_peer_list_size; id++) - { - peer = GST_peer_list[id]; - if (NULL == peer) - continue; - /* If destroy flag is set it means that this peer should have been - * destroyed by a context which we destroy before */ - GNUNET_break (GNUNET_NO == peer->destroy_flag); - /* counter should be zero as we free all contexts before */ - GNUNET_break (0 == peer->reference_cnt); - if ((GNUNET_NO == peer->is_remote) && - (GNUNET_YES == peer->details.local.is_running)) - GNUNET_TESTING_peer_kill (peer->details.local.peer); - } - for (id = 0; id < GST_peer_list_size; id++) - { - peer = GST_peer_list[id]; - if (NULL == peer) - continue; - if (GNUNET_NO == peer->is_remote) - { - if (GNUNET_YES == peer->details.local.is_running) - GNUNET_TESTING_peer_wait (peer->details.local.peer); - GNUNET_TESTING_peer_destroy (peer->details.local.peer); - GNUNET_CONFIGURATION_destroy (peer->details.local.cfg); - } - GNUNET_free (peer); - } - GNUNET_free_non_null (GST_peer_list); - GST_peer_list = NULL; - GST_peer_list_size = 0; -} - - -/** - * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages - * - * @param cls NULL - * @param client identification of the client - * @param message the actual message - */ -static void -handle_shutdown_peers (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - const struct GNUNET_TESTBED_ShutdownPeersMessage *msg; - struct HandlerContext_ShutdownPeers *hc; - struct Slave *slave; - struct ForwardedOperationContext *fo_ctxt; - uint64_t op_id; - unsigned int cnt; - - msg = (const struct GNUNET_TESTBED_ShutdownPeersMessage *) message; - LOG_DEBUG ("Received SHUTDOWN_PEERS\n"); - /* Stop and destroy all peers */ - free_mctxq (); - GST_free_occq (); - GST_free_roccq (); - clear_fopcq (); - /* Forward to all slaves which we have started */ - op_id = GNUNET_ntohll (msg->operation_id); - hc = GNUNET_malloc (sizeof (struct HandlerContext_ShutdownPeers)); - /* FIXME: have a better implementation where we track which slaves are - started by this controller */ - for (cnt = 0; cnt < GST_slave_list_size; cnt++) - { - slave = GST_slave_list[cnt]; - if (NULL == slave) - continue; - if (NULL == slave->controller_proc) /* We didn't start the slave */ - continue; - LOG_DEBUG ("Forwarding SHUTDOWN_PEERS\n"); - hc->nslaves++; - fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); - GNUNET_SERVER_client_keep (client); - fo_ctxt->client = client; - fo_ctxt->operation_id = op_id; - fo_ctxt->cls = hc; - fo_ctxt->type = OP_SHUTDOWN_PEERS; - fo_ctxt->opc = - GNUNET_TESTBED_forward_operation_msg_ (slave->controller, - fo_ctxt->operation_id, - &msg->header, - shutdown_peers_reply_cb, - fo_ctxt); - fo_ctxt->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, &shutdown_peers_timeout_cb, - fo_ctxt); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fo_ctxt); - } - LOG_DEBUG ("Shutting down peers\n"); - destroy_peers (); - if (0 == hc->nslaves) - { - send_operation_success_msg (client, op_id); - GNUNET_free (hc); - } - GNUNET_SERVER_receive_done (client, GNUNET_OK); -} - - -/** - * Iterator over hash map entries. - * - * @param cls closure - * @param key current key code - * @param value value in the hash map - * @return GNUNET_YES if we should continue to - * iterate, - * GNUNET_NO if not. - */ -static int -ss_map_free_iterator (void *cls, const struct GNUNET_HashCode *key, void *value) -{ - struct SharedService *ss = value; - - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (ss_map, key, value)); - GNUNET_free (ss->name); - GNUNET_free (ss); - return GNUNET_YES; -} - - -/** - * Iterator for freeing hash map entries in a slave's reghost_map - * - * @param cls handle to the slave - * @param key current key code - * @param value value in the hash map - * @return GNUNET_YES if we should continue to - * iterate, - * GNUNET_NO if not. - */ -static int -reghost_free_iterator (void *cls, const struct GNUNET_HashCode *key, - void *value) -{ - struct Slave *slave = cls; - struct RegisteredHostContext *rhc = value; - struct ForwardedOverlayConnectContext *focc; - - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (slave->reghost_map, key, - value)); - while (NULL != (focc = rhc->focc_dll_head)) - { - GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc); - GST_cleanup_focc (focc); - } - if (NULL != rhc->sub_op) - GNUNET_TESTBED_operation_done (rhc->sub_op); - if (NULL != rhc->client) - GNUNET_SERVER_client_drop (rhc->client); - GNUNET_free (value); - return GNUNET_YES; -} - - /** * Task to clean up and shutdown nicely * @@ -2558,77 +781,31 @@ reghost_free_iterator (void *cls, const struct GNUNET_HashCode *key, static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct LCFContextQueue *lcfq; struct MessageQueue *mq_entry; uint32_t id; shutdown_task_id = GNUNET_SCHEDULER_NO_TASK; - LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n"); - (void) GNUNET_CONTAINER_multihashmap_iterate (ss_map, &ss_map_free_iterator, - NULL); - GNUNET_CONTAINER_multihashmap_destroy (ss_map); + LOG_DEBUG ("Shutting down testbed service\n"); /* cleanup any remaining forwarded operations */ - clear_fopcq (); - if (NULL != lcfq_head) - { - if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id) - { - GNUNET_SCHEDULER_cancel (lcf_proc_task_id); - lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK; - } - } - 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_assert (NULL != lcfq->lcf->cfg); - GNUNET_CONFIGURATION_destroy (lcfq->lcf->cfg); - GNUNET_free (lcfq->lcf); - GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq); - GNUNET_free (lcfq); - } - free_mctxq (); + GST_clear_fopcq (); + GST_free_lcfq (); + GST_free_mctxq (); GST_free_occq (); GST_free_roccq (); + GST_free_nccq (); + GST_neighbour_list_clean(); + GST_free_prcq (); /* Clear peer list */ - destroy_peers (); + GST_destroy_peers (); + /* Clear route list */ + GST_route_list_clear (); + /* Clear GST_slave_list */ + GST_slave_list_clear (); /* Clear host list */ for (id = 0; id < GST_host_list_size; id++) if (NULL != GST_host_list[id]) GNUNET_TESTBED_host_destroy (GST_host_list[id]); GNUNET_free_non_null (GST_host_list); - /* Clear route list */ - for (id = 0; id < route_list_size; id++) - if (NULL != route_list[id]) - GNUNET_free (route_list[id]); - GNUNET_free_non_null (route_list); - /* Clear GST_slave_list */ - for (id = 0; id < GST_slave_list_size; id++) - if (NULL != GST_slave_list[id]) - { - struct HostRegistration *hr_entry; - - 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 != GST_slave_list[id]->controller_proc) - GNUNET_TESTBED_controller_stop (GST_slave_list[id]->controller_proc); - GNUNET_free (GST_slave_list[id]); - } - GNUNET_free_non_null (GST_slave_list); if (NULL != GST_context) { GNUNET_free_non_null (GST_context->master_ip); @@ -2648,11 +825,14 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_free (mq_entry); } GNUNET_free_non_null (hostname); - GNUNET_CONFIGURATION_destroy (our_config); /* Free hello cache */ GST_cache_clear (); + GST_connection_pool_destroy (); GNUNET_TESTBED_operation_queue_destroy_ (GST_opq_openfds); GST_opq_openfds = NULL; + GST_stats_destroy (); + GST_barriers_destroy (); + GNUNET_CONFIGURATION_destroy (GST_config); } @@ -2694,37 +874,45 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server, static const struct GNUNET_SERVER_MessageHandler message_handlers[] = { {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT, 0}, {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, 0}, - {&handle_configure_shared_service, NULL, - GNUNET_MESSAGE_TYPE_TESTBED_SHARE_SERVICE, 0}, - {&handle_link_controllers, NULL, - GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, 0}, - {&handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER, 0}, - {&handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER, + {&GST_handle_link_controllers, NULL, + GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, + sizeof (struct GNUNET_TESTBED_ControllerLinkRequest)}, + {&GST_handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER, 0}, + {&GST_handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER, sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)}, - {&handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_START_PEER, + {&GST_handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_START_PEER, sizeof (struct GNUNET_TESTBED_PeerStartMessage)}, - {&handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER, + {&GST_handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER, sizeof (struct GNUNET_TESTBED_PeerStopMessage)}, - {&handle_peer_get_config, NULL, - GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_CONFIGURATION, + {&GST_handle_peer_get_config, NULL, + GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION, sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)}, {&GST_handle_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT, sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)}, {&GST_handle_remote_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT, 0}, - {&handle_manage_peer_service, NULL, + {&GST_handle_manage_peer_service, NULL, GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE, 0}, {&handle_slave_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION, sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage)}, - {&handle_shutdown_peers, NULL, GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS, + {&GST_handle_shutdown_peers, NULL, GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS, sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage)}, - {NULL} + {&GST_handle_peer_reconfigure, NULL, + GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER, 0}, + {&GST_handle_barrier_init, NULL, + GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT, 0}, + {&GST_handle_barrier_cancel, NULL, + GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL, 0}, + {&GST_handle_barrier_status, NULL, + GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS, 0}, + {NULL, NULL, 0, 0} }; char *logfile; unsigned long long num; + LOG_DEBUG ("Starting testbed\n"); if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED", "LOG_FILE", &logfile)) @@ -2736,10 +924,12 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server, GNUNET_CONFIGURATION_get_value_number (cfg, "TESTBED", "CACHE_SIZE", &num)); GST_cache_init ((unsigned int) num); + GST_connection_pool_init ((unsigned int) num); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "TESTBED", "MAX_OPEN_FDS", &num)); - GST_opq_openfds = GNUNET_TESTBED_operation_queue_create_ ((unsigned int) num); + GST_opq_openfds = GNUNET_TESTBED_operation_queue_create_ + (OPERATION_QUEUE_TYPE_FIXED, (unsigned int) num); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (cfg, "TESTBED", "OPERATION_TIMEOUT", @@ -2748,17 +938,17 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server, &GST_timeout)); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "testbed", - "HOSTNAME", &hostname)); - our_config = GNUNET_CONFIGURATION_dup (cfg); + "HOSTNAME", &hostname)); + GST_config = GNUNET_CONFIGURATION_dup (cfg); GNUNET_SERVER_add_handlers (server, message_handlers); GNUNET_SERVER_disconnect_notify (server, &client_disconnect_cb, NULL); - ss_map = GNUNET_CONTAINER_multihashmap_create (5, GNUNET_NO); shutdown_task_id = GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_SCHEDULER_PRIORITY_IDLE, &shutdown_task, NULL); LOG_DEBUG ("Testbed startup complete\n"); - event_mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED; + GST_stats_init (GST_config); + GST_barriers_init (GST_config); }