X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftestbed%2Fgnunet-service-testbed.c;h=a1d6aed0951bb5bae4ccea565e876a18799a438a;hb=0f7e55e885e3d9c4e26432b53cf2cfe120df7cf5;hp=cbf10fcee81306a68a688a0c6b5c7fb622dbe9dd;hpb=b67d0aa2e982ad992ef0ccd80146d38e05258cc7;p=oweals%2Fgnunet.git diff --git a/src/testbed/gnunet-service-testbed.c b/src/testbed/gnunet-service-testbed.c index cbf10fcee..a1d6aed09 100644 --- a/src/testbed/gnunet-service-testbed.c +++ b/src/testbed/gnunet-service-testbed.c @@ -1,10 +1,10 @@ /* This file is part of GNUnet. - (C) 2012 Christian Grothoff (and other contributing authors) + (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 + 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,85 +25,27 @@ */ #include "gnunet-service-testbed.h" - -#include - - -/** - * The message queue for sending messages to clients - */ -struct MessageQueue -{ - /** - * The message to be sent - */ - struct GNUNET_MessageHeader *msg; - - /** - * The client to send the message to - */ - struct GNUNET_SERVER_Client *client; - - /** - * next pointer for DLL - */ - struct MessageQueue *next; - - /** - * prev pointer for DLL - */ - struct MessageQueue *prev; -}; - - -/** - * The master context; generated with the first INIT message - */ -struct Context *TESTBED_context; - -/** - * Our hostname; we give this to all the peers we start - */ -static char *hostname; - +#include "gnunet-service-testbed_barriers.h" +#include "gnunet-service-testbed_connectionpool.h" /***********/ -/* Handles */ +/* Globals */ /***********/ /** * Our configuration */ -struct GNUNET_CONFIGURATION_Handle *our_config; - -/** - * Current Transmit Handle; NULL if no notify transmit exists currently - */ -static struct GNUNET_SERVER_TransmitHandle *transmit_handle; - -/****************/ -/* Lists & Maps */ -/****************/ - -/** - * The head for the LCF queue - */ -static struct LCFContextQueue *lcfq_head; +struct GNUNET_CONFIGURATION_Handle *GST_config; /** - * The tail for the LCF queue - */ -static struct LCFContextQueue *lcfq_tail; - -/** - * The message queue head + * The master context; generated with the first INIT message */ -static struct MessageQueue *mq_head; +struct Context *GST_context; /** - * The message queue tail + * Array of hosts */ -static struct MessageQueue *mq_tail; +struct GNUNET_TESTBED_Host **GST_host_list; /** * DLL head for forwarded operation contexts @@ -116,63 +58,76 @@ struct ForwardedOperationContext *fopcq_head; struct ForwardedOperationContext *fopcq_tail; /** - * Array of hosts + * Operation queue for open file descriptors */ -struct GNUNET_TESTBED_Host **TESTBED_host_list; +struct OperationQueue *GST_opq_openfds; /** - * A list of routes + * Timeout for operations which may take some time */ -static struct Route **route_list; +const struct GNUNET_TIME_Relative GST_timeout; /** - * A list of directly linked neighbours + * The size of the host list */ -struct Slave **TESTBED_slave_list; +unsigned int GST_host_list_size; /** - * A list of peers we know about + * The size of the peer list */ -struct Peer **TESTBED_peer_list; +unsigned int GST_peer_list_size; -/** - * The hashmap of shared services - */ -static struct GNUNET_CONTAINER_MultiHashMap *ss_map; -/** - * The event mask for the events we listen from sub-controllers - */ -static uint64_t event_mask; +/***********************************/ +/* Local definitions and variables */ +/***********************************/ /** - * The size of the host list + * The message queue for sending messages to clients */ -unsigned int TESTBED_host_list_size; +struct MessageQueue +{ + /** + * The message to be sent + */ + struct GNUNET_MessageHeader *msg; + + /** + * The client to send the message to + */ + struct GNUNET_SERVER_Client *client; + + /** + * next pointer for DLL + */ + struct MessageQueue *next; + + /** + * prev pointer for DLL + */ + struct MessageQueue *prev; +}; /** - * The size of the route list + * Our hostname; we give this to all the peers we start */ -static unsigned int route_list_size; +static char *hostname; /** - * The size of directly linked neighbours list + * Current Transmit Handle; NULL if no notify transmit exists currently */ -unsigned int TESTBED_slave_list_size; +static struct GNUNET_SERVER_TransmitHandle *transmit_handle; /** - * The size of the peer list + * The message queue head */ -unsigned int TESTBED_peer_list_size; - -/*********/ -/* Tasks */ -/*********/ +static struct MessageQueue *mq_head; /** - * The lcf_task handle + * The message queue tail */ -static GNUNET_SCHEDULER_TaskIdentifier lcf_proc_task_id; +static struct MessageQueue *mq_tail; + /** * The shutdown task handle @@ -225,8 +180,8 @@ transmit_ready_notify (void *cls, size_t size, void *buf) * @param msg the message to queue */ void -TESTBED_queue_message (struct GNUNET_SERVER_Client *client, - struct GNUNET_MessageHeader *msg) +GST_queue_message (struct GNUNET_SERVER_Client *client, + struct GNUNET_MessageHeader *msg) { struct MessageQueue *mq_entry; uint16_t type; @@ -236,7 +191,7 @@ TESTBED_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); @@ -251,30 +206,6 @@ TESTBED_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 * @@ -288,131 +219,18 @@ host_list_add (struct GNUNET_TESTBED_Host *host) uint32_t host_id; host_id = GNUNET_TESTBED_host_get_id_ (host); - if (TESTBED_host_list_size <= host_id) - array_grow_large_enough (TESTBED_host_list, TESTBED_host_list_size, host_id); - if (NULL != TESTBED_host_list[host_id]) + if (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); return GNUNET_SYSERR; } - TESTBED_host_list[host_id] = host; + GST_host_list[host_id] = host; return GNUNET_OK; } -/** - * 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 >= TESTBED_slave_list_size) - array_grow_large_enough (TESTBED_slave_list, TESTBED_slave_list_size, slave->host_id); - GNUNET_assert (NULL == TESTBED_slave_list[slave->host_id]); - TESTBED_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 >= TESTBED_peer_list_size) - array_grow_large_enough (TESTBED_peer_list, TESTBED_peer_list_size, peer->id); - GNUNET_assert (NULL == TESTBED_peer_list[peer->id]); - TESTBED_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; - - TESTBED_peer_list[peer->id] = NULL; - orig_size = TESTBED_peer_list_size; - while (TESTBED_peer_list_size >= LIST_GROW_STEP) - { - for (id = TESTBED_peer_list_size - 1; - (id >= TESTBED_peer_list_size - LIST_GROW_STEP) && (id != UINT32_MAX); id--) - if (NULL != TESTBED_peer_list[id]) - break; - if (id != ((TESTBED_peer_list_size - LIST_GROW_STEP) - 1)) - break; - TESTBED_peer_list_size -= LIST_GROW_STEP; - } - if (orig_size == TESTBED_peer_list_size) - return; - TESTBED_peer_list = - GNUNET_realloc (TESTBED_peer_list, sizeof (struct Peer *) * TESTBED_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 * -TESTBED_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 == TESTBED_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 * @@ -421,8 +239,8 @@ route_message (uint32_t host_id, const struct GNUNET_MessageHeader *msg) * @param emsg the error message; can be NULL */ void -TESTBED_send_operation_fail_msg (struct GNUNET_SERVER_Client *client, - uint64_t operation_id, const char *emsg) +GST_send_operation_fail_msg (struct GNUNET_SERVER_Client *client, + uint64_t operation_id, const char *emsg) { struct GNUNET_TESTBED_OperationFailureEventMessage *msg; uint16_t msize; @@ -433,12 +251,12 @@ TESTBED_send_operation_fail_msg (struct GNUNET_SERVER_Client *client, msize += emsg_len; msg = GNUNET_malloc (msize); msg->header.size = htons (msize); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT); + msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT); msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED); msg->operation_id = GNUNET_htonll (operation_id); if (0 != emsg_len) memcpy (&msg[1], emsg, emsg_len); - TESTBED_queue_message (client, &msg->header); + GST_queue_message (client, &msg->header); } @@ -448,9 +266,9 @@ TESTBED_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; @@ -458,20 +276,20 @@ send_operation_success_msg (struct GNUNET_SERVER_Client *client, msize = sizeof (struct GNUNET_TESTBED_GenericOperationSuccessEventMessage); msg = GNUNET_malloc (msize); msg->header.size = htons (msize); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GENERICOPSUCCESS); + msg->header.type = + htons (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS); msg->operation_id = GNUNET_htonll (operation_id); msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED); - TESTBED_queue_message (client, &msg->header); + GST_queue_message (client, &msg->header); } - /** - * Callback which will be called to after a host registration succeeded or failed + * Callback which will be called after a host registration succeeded or failed * * @param cls the handle to the slave at which the registration is completed * @param emsg the error message; NULL if host registration is successful */ -static void +static void hr_completion (void *cls, const char *emsg); @@ -485,18 +303,16 @@ static void register_next_host (struct Slave *slave) { struct HostRegistration *hr; - + hr = slave->hr_dll_head; GNUNET_assert (NULL != hr); GNUNET_assert (NULL == slave->rhandle); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Registering host %u at %u\n", + LOG (GNUNET_ERROR_TYPE_DEBUG, "Registering host %u at %u\n", GNUNET_TESTBED_host_get_id_ (hr->host), - GNUNET_TESTBED_host_get_id_ (TESTBED_host_list[slave->host_id])); - slave->rhandle = GNUNET_TESTBED_register_host (slave->controller, - hr->host, - hr_completion, - slave); + GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id])); + slave->rhandle = + GNUNET_TESTBED_register_host (slave->controller, hr->host, hr_completion, + slave); } @@ -506,7 +322,7 @@ register_next_host (struct Slave *slave) * @param cls the handle to the slave at which the registration is completed * @param emsg the error message; NULL if host registration is successful */ -static void +static void hr_completion (void *cls, const char *emsg) { struct Slave *slave = cls; @@ -515,13 +331,10 @@ hr_completion (void *cls, const char *emsg) slave->rhandle = NULL; hr = slave->hr_dll_head; GNUNET_assert (NULL != hr); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Registering host %u at %u successful\n", + LOG (GNUNET_ERROR_TYPE_DEBUG, "Registering host %u at %u successful\n", GNUNET_TESTBED_host_get_id_ (hr->host), - GNUNET_TESTBED_host_get_id_ (TESTBED_host_list[slave->host_id])); - GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head, - slave->hr_dll_tail, - hr); + GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id])); + GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head, slave->hr_dll_tail, hr); if (NULL != hr->cb) hr->cb (hr->cb_cls, emsg); GNUNET_free (hr); @@ -534,16 +347,15 @@ hr_completion (void *cls, const char *emsg) * Adds a host registration's request to a slave's registration queue * * @param slave the slave controller at which the given host has to be - * registered + * registered * @param cb the host registration completion callback * @param cb_cls the closure for the host registration completion callback * @param host the host which has to be registered */ void -TESTBED_queue_host_registration (struct Slave *slave, - GNUNET_TESTBED_HostRegistrationCompletion cb, - void *cb_cls, - struct GNUNET_TESTBED_Host *host) +GST_queue_host_registration (struct Slave *slave, + GNUNET_TESTBED_HostRegistrationCompletion cb, + void *cb_cls, struct GNUNET_TESTBED_Host *host) { struct HostRegistration *hr; int call_register; @@ -551,69 +363,18 @@ TESTBED_queue_host_registration (struct Slave *slave, LOG (GNUNET_ERROR_TYPE_DEBUG, "Queueing host registration for host %u at %u\n", GNUNET_TESTBED_host_get_id_ (host), - GNUNET_TESTBED_host_get_id_ (TESTBED_host_list[slave->host_id])); - hr = GNUNET_malloc (sizeof (struct HostRegistration)); + GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id])); + hr = GNUNET_new (struct HostRegistration); hr->cb = cb; hr->cb_cls = cb_cls; hr->host = host; call_register = (NULL == slave->hr_dll_head) ? GNUNET_YES : GNUNET_NO; - GNUNET_CONTAINER_DLL_insert_tail (slave->hr_dll_head, - slave->hr_dll_tail, - hr); + GNUNET_CONTAINER_DLL_insert_tail (slave->hr_dll_head, slave->hr_dll_tail, hr); if (GNUNET_YES == call_register) register_next_host (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 * @@ -621,8 +382,8 @@ lcf_proc_cc (void *cls, const char *emsg) * @param msg the message to relay */ void -TESTBED_forwarded_operation_reply_relay (void *cls, - const struct GNUNET_MessageHeader *msg) +GST_forwarded_operation_reply_relay (void *cls, + const struct GNUNET_MessageHeader *msg) { struct ForwardedOperationContext *fopc = cls; struct GNUNET_MessageHeader *dup_msg; @@ -632,7 +393,7 @@ TESTBED_forwarded_operation_reply_relay (void *cls, LOG_DEBUG ("Relaying message with type: %u, size: %u\n", ntohs (msg->type), msize); dup_msg = GNUNET_copy_message (msg); - TESTBED_queue_message (fopc->client, dup_msg); + GST_queue_message (fopc->client, dup_msg); GNUNET_SERVER_client_drop (fopc->client); GNUNET_SCHEDULER_cancel (fopc->timeout_task); GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc); @@ -647,14 +408,15 @@ TESTBED_forwarded_operation_reply_relay (void *cls, * @param tc the task context from scheduler */ void -TESTBED_forwarded_operation_timeout (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +GST_forwarded_operation_timeout (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ForwardedOperationContext *fopc = cls; GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc); - LOG (GNUNET_ERROR_TYPE_WARNING, "A forwarded operation has timed out\n"); - TESTBED_send_operation_fail_msg (fopc->client, fopc->operation_id, "Timeout"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "A forwarded operation has timed out\n"); + GST_send_operation_fail_msg (fopc->client, fopc->operation_id, + "A forwarded operation has timed out"); GNUNET_SERVER_client_drop (fopc->client); GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc); GNUNET_free (fopc); @@ -662,272 +424,88 @@ TESTBED_forwarded_operation_timeout (void *cls, /** - * 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); - - -/** - * Callback to be called when forwarded link controllers operation is - * successfull. We have to relay the reply msg back to the client - * - * @param cls the LCFContext - * @param msg the message to relay - */ -static void -lcf_forwarded_operation_reply_relay (void *cls, - const struct GNUNET_MessageHeader *msg) -{ - struct LCFContext *lcf = cls; - - GNUNET_assert (NULL != lcf->fopc); - TESTBED_forwarded_operation_reply_relay (lcf->fopc, msg); - lcf->fopc = NULL; - GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id); - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); -} - - -/** - * 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; - - GNUNET_assert (NULL != lcf->fopc); - lcf->fopc->timeout_task = GNUNET_SCHEDULER_NO_TASK; - TESTBED_forwarded_operation_timeout (lcf->fopc, tc); - lcf->fopc = NULL; - 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 - * - * @param cls the LCFContext - * @param tc the Task context from scheduler - */ -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; + 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) - lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK; - switch (lcf->state) + slist = NULL; + n = 0; + ss.cfg = cfg; + for (; NULL != (arg = strtok (ss_str, " ")); ss_str = NULL) { - case INIT: - if (GNUNET_NO == - GNUNET_TESTBED_is_host_registered_ (TESTBED_host_list[lcf->delegated_host_id], - lcf->gateway->controller)) - { - TESTBED_queue_host_registration (lcf->gateway, - lcf_proc_cc, lcf, - TESTBED_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_ (TESTBED_host_list[lcf->slave_host_id], - lcf->gateway->controller)) - { - TESTBED_queue_host_registration (lcf->gateway, - lcf_proc_cc, lcf, - TESTBED_host_list[lcf->slave_host_id]); - } - else + ss.service = NULL; + ss.share = 0; + if (2 != sscanf (arg, "%255[^:]:%u", service, &ss.share)) { - lcf->state = SLAVE_HOST_REGISTERED; - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); + LOG (GNUNET_ERROR_TYPE_WARNING, "Ignoring shared service spec: %s", arg); + continue; } - break; - case SLAVE_HOST_REGISTERED: - lcf->fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); - lcf->fopc->client = lcf->client; - lcf->fopc->operation_id = lcf->operation_id; - lcf->fopc->type = OP_LINK_CONTROLLERS; - lcf->fopc->opc = - GNUNET_TESTBED_forward_operation_msg_ (lcf->gateway->controller, - lcf->operation_id, - &lcf->msg->header, - &lcf_forwarded_operation_reply_relay, - lcf); - lcf->fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &lcf_forwarded_operation_timeout, - lcf); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, lcf->fopc); - lcf->state = FINISHED; - break; - case FINISHED: - lcfq = lcfq_head; - GNUNET_assert (lcfq->lcf == lcf); - GNUNET_free (lcf->msg); - 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); + LOG_DEBUG ("Will be sharing %s service among %u peers\n", service, ss.share); + ss.service = GNUNET_strdup (service); + GROW_SS; } -} - - -/** - * 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 GNUNET_CONFIGURATION_Handle *cfg; - struct GNUNET_TESTBED_Operation *old_op; - - /* We currently only get here when working on RegisteredHostContexts */ - GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type); - rhc = event->details.operation_finished.op_cls; - GNUNET_assert (rhc->sub_op == event->details.operation_finished.operation); - switch (rhc->state) + if (NULL != slist) { - 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; - TESTBED_process_next_focc (rhc); - break; - default: - GNUNET_assert (0); + /* Add trailing NULL block */ + (void) memset (&ss, 0, sizeof (struct GNUNET_TESTING_SharedService)); + GROW_SS; } + return slist; +#undef GROW_SS } /** - * Callback to signal successfull startup of the controller process + * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages * - * @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 + * @param cls NULL + * @param client identification of the client + * @param message the actual message */ static void -slave_status_callback (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, - int status) +handle_init (void *cls, struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) { - struct Slave *slave = cls; - struct LinkControllersContext *lcc; + 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; - lcc = slave->lcc; - if (GNUNET_SYSERR == status) + if (NULL != GST_context) { - slave->controller_proc = NULL; - TESTBED_slave_list[slave->host_id] = NULL; - if (NULL != slave->cfg) - GNUNET_CONFIGURATION_destroy (slave->cfg); - 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 ("We are being connected to laterally\n"); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; } - slave->controller = - GNUNET_TESTBED_controller_connect (cfg, TESTBED_host_list[slave->host_id], - event_mask, - &slave_event_callback, slave); - if (NULL != slave->controller) + msg = (const struct GNUNET_TESTBED_InitMessage *) message; + msize = ntohs (message->size); + if (msize <= sizeof (struct GNUNET_TESTBED_InitMessage)) { - send_operation_success_msg (lcc->client, lcc->operation_id); - slave->cfg = GNUNET_CONFIGURATION_dup (cfg); - } - else - { - TESTBED_send_operation_fail_msg (lcc->client, lcc->operation_id, - "Could not connect to delegated controller"); - GNUNET_TESTBED_controller_stop (slave->controller_proc); - TESTBED_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); - } - if (NULL != slave) - slave->lcc = NULL; -} - - -/** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages - * - * @param cls NULL - * @param client identification of the client - * @param message the actual message - */ -static void -handle_init (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - const struct GNUNET_TESTBED_InitMessage *msg; - struct GNUNET_TESTBED_Host *host; - const char *controller_hostname; - uint16_t msize; - - if (NULL != TESTBED_context) - { - LOG_DEBUG ("We are being connected to laterally\n"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - msg = (const struct GNUNET_TESTBED_InitMessage *) message; - msize = ntohs (message->size); - if (msize <= sizeof (struct GNUNET_TESTBED_InitMessage)) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; } msize -= sizeof (struct GNUNET_TESTBED_InitMessage); controller_hostname = (const char *) &msg[1]; @@ -937,22 +515,41 @@ handle_init (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - TESTBED_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); - TESTBED_context->client = client; - TESTBED_context->host_id = ntohl (msg->host_id); - TESTBED_context->master_ip = GNUNET_strdup (controller_hostname); - LOG_DEBUG ("Our IP: %s\n", TESTBED_context->master_ip); - TESTBED_context->system = - GNUNET_TESTING_system_create ("testbed", TESTBED_context->master_ip, hostname); + GST_context->client = client; + GST_context->host_id = ntohl (msg->host_id); + GST_context->master_ip = GNUNET_strdup (controller_hostname); + LOG_DEBUG ("Our IP: %s\n", GST_context->master_ip); + GST_context->system = + GNUNET_TESTING_system_create ("testbed", GST_context->master_ip, + 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 (TESTBED_context->host_id, - TESTBED_context->master_ip, - NULL, - 0); + GNUNET_TESTBED_host_create_with_id (GST_context->host_id, + GST_context->master_ip, NULL, + GST_config, 0); host_list_add (host); - LOG_DEBUG ("Created master context with host ID: %u\n", - TESTBED_context->host_id); + LOG_DEBUG ("Created master context with host ID: %u\n", GST_context->host_id); GNUNET_SERVER_receive_done (client, GNUNET_OK); } @@ -971,9 +568,11 @@ handle_add_host (void *cls, struct GNUNET_SERVER_Client *client, struct GNUNET_TESTBED_Host *host; const struct GNUNET_TESTBED_AddHostMessage *msg; struct GNUNET_TESTBED_HostConfirmedMessage *reply; + struct GNUNET_CONFIGURATION_Handle *host_cfg; char *username; char *hostname; char *emsg; + const void *ptr; uint32_t host_id; uint16_t username_length; uint16_t hostname_length; @@ -982,869 +581,91 @@ handle_add_host (void *cls, struct GNUNET_SERVER_Client *client, msg = (const struct GNUNET_TESTBED_AddHostMessage *) message; msize = ntohs (msg->header.size); - username = (char *) &msg[1]; - username_length = ntohs (msg->user_name_length); - if (0 != username_length) - username_length++; - /* msg must contain hostname */ - GNUNET_assert (msize > (sizeof (struct GNUNET_TESTBED_AddHostMessage) + - username_length + 1)); - if (0 != username_length) - GNUNET_assert ('\0' == username[username_length - 1]); - hostname = username + username_length; - hostname_length = - msize - (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length); - GNUNET_assert ('\0' == hostname[hostname_length - 1]); - GNUNET_assert (strlen (hostname) == hostname_length - 1); - host_id = ntohl (msg->host_id); - LOG_DEBUG ("Received ADDHOST %u message\n", host_id); - LOG_DEBUG ("-------host id: %u\n", host_id); - LOG_DEBUG ("-------hostname: %s\n", hostname); - if (0 != username_length) - LOG_DEBUG ("-------username: %s\n", username); - else - { - LOG_DEBUG ("-------username: NULL\n"); - username = NULL; - } - LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port)); - host = - GNUNET_TESTBED_host_create_with_id (host_id, hostname, username, - ntohs (msg->ssh_port)); - GNUNET_assert (NULL != host); - reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage); - if (GNUNET_OK != host_list_add (host)) - { - /* We are unable to add a host */ - emsg = "A host exists with given host-id"; - LOG_DEBUG ("%s: %u", emsg, host_id); - GNUNET_TESTBED_host_destroy (host); - reply_size += strlen (emsg) + 1; - reply = GNUNET_malloc (reply_size); - memcpy (&reply[1], emsg, strlen (emsg) + 1); - } - else - { - LOG_DEBUG ("Added host %u at %u\n", - host_id, TESTBED_context->host_id); - reply = GNUNET_malloc (reply_size); - } - reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM); - reply->header.size = htons (reply_size); - reply->host_id = htonl (host_id); - TESTBED_queue_message (client, &reply->header); - 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. - */ -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 - * - * @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) -{ - 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)) - { - 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) != TESTBED_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_ControllerLinkMessage *msg; - struct GNUNET_CONFIGURATION_Handle *cfg; - struct LCFContextQueue *lcfq; - struct Route *route; - struct Route *new_route; - char *config; - uLongf dest_size; - size_t config_size; - uint32_t delegated_host_id; - uint32_t slave_host_id; - uint16_t msize; - - if (NULL == TESTBED_context) + if (msize <= sizeof (struct GNUNET_TESTBED_AddHostMessage)) { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - msize = ntohs (message->size); - if (sizeof (struct GNUNET_TESTBED_ControllerLinkMessage) >= msize) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - msg = (const struct GNUNET_TESTBED_ControllerLinkMessage *) message; - delegated_host_id = ntohl (msg->delegated_host_id); - if (delegated_host_id == TESTBED_context->host_id) - { - GNUNET_break (0); - LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n"); + GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - if ((delegated_host_id >= TESTBED_host_list_size) || - (NULL == TESTBED_host_list[delegated_host_id])) + username_length = ntohs (msg->username_length); + hostname_length = ntohs (msg->hostname_length); + /* msg must contain hostname */ + if ((msize <= (sizeof (struct GNUNET_TESTBED_AddHostMessage) + + username_length)) + || (0 == hostname_length)) { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Delegated host %u not registered with us\n", delegated_host_id); + GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - slave_host_id = ntohl (msg->slave_host_id); - if ((slave_host_id >= TESTBED_host_list_size) || (NULL == TESTBED_host_list[slave_host_id])) + /* msg must contain configuration */ + if (msize <= (sizeof (struct GNUNET_TESTBED_AddHostMessage) + + username_length + hostname_length)) { - LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host %u not registered with us\n", - slave_host_id); + GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - if (slave_host_id == delegated_host_id) + username = NULL; + hostname = NULL; + ptr = &msg[1]; + if (0 != username_length) { - LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n"); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; + username = GNUNET_malloc (username_length + 1); + strncpy (username, ptr, username_length); + ptr += username_length; } - - if (slave_host_id == TESTBED_context->host_id) /* Link from us */ + hostname = GNUNET_malloc (hostname_length + 1); + strncpy (hostname, ptr, hostname_length); + if (NULL == (host_cfg = GNUNET_TESTBED_extract_config_ (message))) { - struct Slave *slave; - struct LinkControllersContext *lcc; - - msize -= sizeof (struct GNUNET_TESTBED_ControllerLinkMessage); - config_size = ntohs (msg->config_size); - if ((delegated_host_id < TESTBED_slave_list_size) && (NULL != TESTBED_slave_list[delegated_host_id])) /* We have already added */ - { - LOG (GNUNET_ERROR_TYPE_WARNING, "Host %u already connected\n", - delegated_host_id); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - config = GNUNET_malloc (config_size); - dest_size = (uLongf) config_size; - if (Z_OK != - uncompress ((Bytef *) config, &dest_size, (const Bytef *) &msg[1], - (uLong) msize)) - { - GNUNET_break (0); /* Compression error */ - GNUNET_free (config); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - if (config_size != dest_size) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "Uncompressed config size mismatch\n"); - GNUNET_free (config); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - cfg = GNUNET_CONFIGURATION_create (); /* Free here or in lcfcontext */ - 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); - if ((delegated_host_id < TESTBED_slave_list_size) && - (NULL != TESTBED_slave_list[delegated_host_id])) - { - GNUNET_break (0); /* Configuration parsing error */ - 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, TESTBED_host_list[slave->host_id], - event_mask, - &slave_event_callback, slave); - slave->cfg = cfg; - if (NULL != slave->controller) - send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id)); - else - TESTBED_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), - "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 (TESTBED_context->master_ip, - TESTBED_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 = TESTBED_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_free_non_null (username); + GNUNET_free_non_null (hostname); + GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue)); - lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext)); - lcfq->lcf->delegated_host_id = delegated_host_id; - lcfq->lcf->slave_host_id = slave_host_id; - route = TESTBED_find_dest_route (slave_host_id); - GNUNET_assert (NULL != route); /* because we add routes carefully */ - GNUNET_assert (route->dest < TESTBED_slave_list_size); - GNUNET_assert (NULL != TESTBED_slave_list[route->dest]); - lcfq->lcf->state = INIT; - lcfq->lcf->operation_id = GNUNET_ntohll (msg->operation_id); - lcfq->lcf->gateway = TESTBED_slave_list[route->dest]; - lcfq->lcf->msg = GNUNET_malloc (msize); - (void) memcpy (lcfq->lcf->msg, msg, msize); - 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); - } + host_id = ntohl (msg->host_id); + LOG_DEBUG ("Received ADDHOST %u message\n", host_id); + LOG_DEBUG ("-------host id: %u\n", host_id); + LOG_DEBUG ("-------hostname: %s\n", hostname); + if (NULL != username) + LOG_DEBUG ("-------username: %s\n", username); 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])) + LOG_DEBUG ("-------username: \n"); + LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port)); + host = + GNUNET_TESTBED_host_create_with_id (host_id, hostname, username, + host_cfg, ntohs (msg->ssh_port)); + GNUNET_free_non_null (username); + GNUNET_free (hostname); + GNUNET_CONFIGURATION_destroy (host_cfg); + if (NULL == host) { - GNUNET_break_op (0); /* Are you trying to link delegated host twice - with is subordinate flag set to GNUNET_YES? */ + GNUNET_break_op (0); 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); - TESTBED_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_PEERCREATESUCCESS) - { - GNUNET_assert (NULL != fopc->cls); - remote_peer = fopc->cls; - peer_list_add (remote_peer); - } - TESTBED_forwarded_operation_reply_relay (fopc, msg); -} - - -/** - * Function to destroy a peer - * - * @param peer the peer structure to destroy - */ -void -TESTBED_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_GENERICOPSUCCESS == ntohs (msg->type)) - { - remote_peer = fopc->cls; - GNUNET_assert (NULL != remote_peer); - remote_peer->destroy_flag = GNUNET_YES; - if (0 == remote_peer->reference_cnt) - TESTBED_destroy_peer (remote_peer); - } - TESTBED_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) - { - TESTBED_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 == TESTBED_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 (TESTBED_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_PEERCREATESUCCESS); - reply->peer_id = msg->peer_id; - reply->operation_id = msg->operation_id; - TESTBED_queue_message (client, &reply->header); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - - /* Forward peer create request */ - route = TESTBED_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 = TESTBED_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; //TESTBED_slave_list[route->dest]->controller; - fo_ctxt->type = OP_PEER_CREATE; - fo_ctxt->opc = - GNUNET_TESTBED_forward_operation_msg_ (TESTBED_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 (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 ((TESTBED_peer_list_size <= peer_id) || (NULL == TESTBED_peer_list[peer_id])) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Asked to destroy a non existent peer with id: %u\n", peer_id); - TESTBED_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), - "Peer doesn't exist"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - peer = TESTBED_peer_list[peer_id]; - if (GNUNET_YES == peer->is_remote) + reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage); + if (GNUNET_OK != host_list_add (host)) { - /* 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 (TIMEOUT, &TESTBED_forwarded_operation_timeout, - fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; + /* We are unable to add a host */ + emsg = "A host exists with given host-id"; + LOG_DEBUG ("%s: %u", emsg, host_id); + GNUNET_TESTBED_host_destroy (host); + reply_size += strlen (emsg) + 1; + reply = GNUNET_malloc (reply_size); + memcpy (&reply[1], emsg, strlen (emsg) + 1); } - peer->destroy_flag = GNUNET_YES; - if (0 == peer->reference_cnt) - TESTBED_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 >= TESTBED_peer_list_size) || (NULL == TESTBED_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 = TESTBED_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, - &TESTBED_forwarded_operation_reply_relay, - fopc); - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &TESTBED_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)) - { - TESTBED_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_PEEREVENT); - reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); - reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START); - reply->host_id = htonl (TESTBED_context->host_id); - reply->peer_id = msg->peer_id; - reply->operation_id = msg->operation_id; - TESTBED_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 >= TESTBED_peer_list_size) || (NULL == TESTBED_peer_list[peer_id])) - { - TESTBED_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), - "Peer not found"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - peer = TESTBED_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, - &TESTBED_forwarded_operation_reply_relay, - fopc); - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &TESTBED_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_stop (peer->details.local.peer)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "Stopping peer %u failed\n", peer_id); - TESTBED_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_PEEREVENT); - reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); - reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP); - reply->host_id = htonl (TESTBED_context->host_id); - reply->peer_id = msg->peer_id; - reply->operation_id = msg->operation_id; - TESTBED_queue_message (client, &reply->header); - GNUNET_SERVER_receive_done (client, GNUNET_OK); -} - - -/** - * 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 >= TESTBED_peer_list_size) || (NULL == TESTBED_peer_list[peer_id])) { - TESTBED_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), - "Peer not found"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - peer = TESTBED_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, - &TESTBED_forwarded_operation_reply_relay, - fopc); - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &TESTBED_forwarded_operation_timeout, - fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; + LOG_DEBUG ("Added host %u at %u\n", host_id, GST_context->host_id); + reply = GNUNET_malloc (reply_size); } - LOG_DEBUG ("Received PEER_GET_CONFIG for peer: %u\n", peer_id); - config = - GNUNET_CONFIGURATION_serialize (TESTBED_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_PEERCONFIG); - reply->peer_id = msg->peer_id; - reply->operation_id = msg->operation_id; - GNUNET_TESTING_peer_get_identity (TESTBED_peer_list[peer_id]->details.local.peer, - &reply->peer_identity); - reply->config_size = htons ((uint16_t) c_size); - TESTBED_queue_message (client, &reply->header); + reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS); + reply->header.size = htons (reply_size); + reply->host_id = htonl (host_id); + GST_queue_message (client, &reply->header); GNUNET_SERVER_receive_done (client, GNUNET_OK); } @@ -1858,11 +679,12 @@ handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client, */ static void handle_slave_get_config (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) + const struct GNUNET_MessageHeader *message) { struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg; - struct Slave *slave; + struct Slave *slave; struct GNUNET_TESTBED_SlaveConfiguration *reply; + const struct GNUNET_CONFIGURATION_Handle *cfg; char *config; char *xconfig; size_t config_size; @@ -1874,121 +696,42 @@ handle_slave_get_config (void *cls, struct GNUNET_SERVER_Client *client, msg = (struct GNUNET_TESTBED_SlaveGetConfigurationMessage *) message; slave_id = ntohl (msg->slave_id); op_id = GNUNET_ntohll (msg->operation_id); - if ((TESTBED_slave_list_size <= slave_id) || (NULL == TESTBED_slave_list[slave_id])) + if ((GST_slave_list_size <= slave_id) || (NULL == GST_slave_list[slave_id])) { /* FIXME: Add forwardings for this type of message here.. */ - TESTBED_send_operation_fail_msg (client, op_id, "Slave not found"); + GST_send_operation_fail_msg (client, op_id, "Slave not found"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } - slave = TESTBED_slave_list[slave_id]; - if (NULL == slave->cfg) - { - TESTBED_send_operation_fail_msg (client, op_id, - "Configuration not found (slave not started by me)"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - config = GNUNET_CONFIGURATION_serialize (slave->cfg, &config_size); - xconfig_size = GNUNET_TESTBED_compress_config_ (config, config_size, - &xconfig); - GNUNET_free (config); + slave = GST_slave_list[slave_id]; + GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (GST_host_list[slave->host_id]))); + config = GNUNET_CONFIGURATION_serialize (cfg, &config_size); + xconfig_size = + GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig); + GNUNET_free (config); reply_size = xconfig_size + sizeof (struct GNUNET_TESTBED_SlaveConfiguration); GNUNET_break (reply_size <= UINT16_MAX); GNUNET_break (config_size <= UINT16_MAX); reply = GNUNET_realloc (xconfig, reply_size); (void) memmove (&reply[1], reply, xconfig_size); - reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG); + reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION); reply->header.size = htons ((uint16_t) reply_size); reply->slave_id = msg->slave_id; reply->operation_id = msg->operation_id; reply->config_size = htons ((uint16_t) config_size); - TESTBED_queue_message (client, &reply->header); + GST_queue_message (client, &reply->header); 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); - TESTBED_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 - * - * @param cls NULL - * @param tc the TaskContext from scheduler + * Clears the forwarded operations queue */ -static void -shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +void +GST_clear_fopcq () { - struct LCFContextQueue *lcfq; struct ForwardedOperationContext *fopc; - 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); - /* cleanup any remaining forwarded operations */ while (NULL != (fopc = fopcq_head)) { GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc); @@ -2001,6 +744,16 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) case OP_PEER_CREATE: GNUNET_free (fopc->cls); break; + case OP_SHUTDOWN_PEERS: + { + struct HandlerContext_ShutdownPeers *hc = fopc->cls; + + GNUNET_assert (0 < hc->nslaves); + hc->nslaves--; + if (0 == hc->nslaves) + GNUNET_free (hc); + } + break; case OP_PEER_START: case OP_PEER_STOP: case OP_PEER_DESTROY: @@ -2008,116 +761,78 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) case OP_OVERLAY_CONNECT: case OP_LINK_CONTROLLERS: case OP_GET_SLAVE_CONFIG: + case OP_MANAGE_SERVICE: + case OP_PEER_RECONFIGURE: break; case OP_FORWARDED: GNUNET_assert (0); }; GNUNET_free (fopc); } - 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_free (lcfq->lcf->msg); - GNUNET_free (lcfq->lcf); - GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq); - GNUNET_free (lcfq); - } - TESTBED_free_occq (); - TESTBED_free_roccq (); +} + + +/** + * Task to clean up and shutdown nicely + * + * @param cls NULL + * @param tc the TaskContext from scheduler + */ +static void +shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct MessageQueue *mq_entry; + uint32_t id; + + shutdown_task_id = GNUNET_SCHEDULER_NO_TASK; + LOG_DEBUG ("Shutting down testbed service\n"); + /* cleanup any remaining forwarded operations */ + 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 */ - for (id = 0; id < TESTBED_peer_list_size; id++) - if (NULL != TESTBED_peer_list[id]) - { - /* 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 == TESTBED_peer_list[id]->destroy_flag); - /* counter should be zero as we free all contexts before */ - GNUNET_break (0 == TESTBED_peer_list[id]->reference_cnt); - if ( (GNUNET_NO == TESTBED_peer_list[id]->is_remote) - && (GNUNET_YES == TESTBED_peer_list[id]->details.local.is_running)) - GNUNET_TESTING_peer_kill (TESTBED_peer_list[id]->details.local.peer); - } - for (id = 0; id < TESTBED_peer_list_size; id++) - if (NULL != TESTBED_peer_list[id]) - { - if (GNUNET_NO == TESTBED_peer_list[id]->is_remote) - { - if (GNUNET_YES == TESTBED_peer_list[id]->details.local.is_running) - GNUNET_TESTING_peer_wait (TESTBED_peer_list[id]->details.local.peer); - GNUNET_TESTING_peer_destroy (TESTBED_peer_list[id]->details.local.peer); - GNUNET_CONFIGURATION_destroy (TESTBED_peer_list[id]->details.local.cfg); - } - GNUNET_free (TESTBED_peer_list[id]); - } - GNUNET_free_non_null (TESTBED_peer_list); - /* Clear host list */ - for (id = 0; id < TESTBED_host_list_size; id++) - if (NULL != TESTBED_host_list[id]) - GNUNET_TESTBED_host_destroy (TESTBED_host_list[id]); - GNUNET_free_non_null (TESTBED_host_list); + GST_destroy_peers (); /* 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 TESTBED_slave_list */ - for (id = 0; id < TESTBED_slave_list_size; id++) - if (NULL != TESTBED_slave_list[id]) - { - struct HostRegistration *hr_entry; - - while (NULL != (hr_entry = TESTBED_slave_list[id]->hr_dll_head)) - { - GNUNET_CONTAINER_DLL_remove (TESTBED_slave_list[id]->hr_dll_head, - TESTBED_slave_list[id]->hr_dll_tail, - hr_entry); - GNUNET_free (hr_entry); - } - if (NULL != TESTBED_slave_list[id]->rhandle) - GNUNET_TESTBED_cancel_registration (TESTBED_slave_list[id]->rhandle); - (void) GNUNET_CONTAINER_multihashmap_iterate (TESTBED_slave_list[id]->reghost_map, - reghost_free_iterator, - TESTBED_slave_list[id]); - GNUNET_CONTAINER_multihashmap_destroy (TESTBED_slave_list[id]->reghost_map); - if (NULL != TESTBED_slave_list[id]->cfg) - GNUNET_CONFIGURATION_destroy (TESTBED_slave_list[id]->cfg); - if (NULL != TESTBED_slave_list[id]->controller) - GNUNET_TESTBED_controller_disconnect (TESTBED_slave_list[id]->controller); - if (NULL != TESTBED_slave_list[id]->controller_proc) - GNUNET_TESTBED_controller_stop (TESTBED_slave_list[id]->controller_proc); - GNUNET_free (TESTBED_slave_list[id]); - } - GNUNET_free_non_null (TESTBED_slave_list); - if (NULL != TESTBED_context) - { - GNUNET_free_non_null (TESTBED_context->master_ip); - if (NULL != TESTBED_context->system) - GNUNET_TESTING_system_destroy (TESTBED_context->system, GNUNET_YES); - GNUNET_SERVER_client_drop (TESTBED_context->client); - GNUNET_free (TESTBED_context); - TESTBED_context = NULL; + 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); + if (NULL != GST_context) + { + GNUNET_free_non_null (GST_context->master_ip); + if (NULL != GST_context->system) + GNUNET_TESTING_system_destroy (GST_context->system, GNUNET_YES); + GNUNET_SERVER_client_drop (GST_context->client); + GNUNET_free (GST_context); + GST_context = NULL; } if (NULL != transmit_handle) - GNUNET_SERVER_notify_transmit_ready_cancel (transmit_handle); + GNUNET_SERVER_notify_transmit_ready_cancel (transmit_handle); while (NULL != (mq_entry = mq_head)) { GNUNET_free (mq_entry->msg); GNUNET_SERVER_client_drop (mq_entry->client); - GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry); + GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry); GNUNET_free (mq_entry); - } + } GNUNET_free_non_null (hostname); - GNUNET_CONFIGURATION_destroy (our_config); /* Free hello cache */ - TESTBED_cache_clear (); + 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); } @@ -2130,9 +845,9 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static void client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client) { - if (NULL == TESTBED_context) + if (NULL == GST_context) return; - if (client == TESTBED_context->client) + if (client == GST_context->client) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n"); /* should not be needed as we're terminated by failure to read @@ -2158,56 +873,82 @@ 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_ADDHOST, 0}, - {&handle_configure_shared_service, NULL, - GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE, 0}, - {&handle_link_controllers, NULL, - GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS, 0}, - {&handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER, 0}, - {&handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER, + {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, 0}, + {&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_STARTPEER, + {&GST_handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_START_PEER, sizeof (struct GNUNET_TESTBED_PeerStartMessage)}, - {&handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOPPEER, + {&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_GETPEERCONFIG, + {&GST_handle_peer_get_config, NULL, + GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION, sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)}, - {&TESTBED_handle_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT, + {&GST_handle_overlay_connect, NULL, + GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT, sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)}, - {&TESTBED_handle_overlay_request_connect, NULL, - GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT, 0}, - {handle_slave_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG, + {&GST_handle_remote_overlay_connect, NULL, + GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT, 0}, + {&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)}, - {NULL} + {&GST_handle_shutdown_peers, NULL, GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS, + sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage)}, + {&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; - if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, - "TESTBED", - "LOG_FILE", - &logfile)) + LOG_DEBUG ("Starting testbed\n"); + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED", "LOG_FILE", + &logfile)) { GNUNET_break (GNUNET_OK == GNUNET_log_setup ("testbed", "DEBUG", logfile)); GNUNET_free (logfile); } - GNUNET_assert (GNUNET_OK == + GNUNET_assert (GNUNET_OK == + 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", - "HELLO_CACHE_SIZE", - &num)); - TESTBED_cache_init ((unsigned int) num); - GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string - (cfg, "testbed", "HOSTNAME", &hostname)); - our_config = GNUNET_CONFIGURATION_dup (cfg); + "MAX_OPEN_FDS", &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", + (struct + GNUNET_TIME_Relative *) + &GST_timeout)); + GNUNET_assert (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (cfg, "testbed", + "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); }