X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftestbed%2Fgnunet-service-testbed.c;h=a1d6aed0951bb5bae4ccea565e876a18799a438a;hb=0f7e55e885e3d9c4e26432b53cf2cfe120df7cf5;hp=d9a2a6c133ca0e6ec9c16285a2b355441a827834;hpb=3b691360358390bee96bf66568b4416e41c33d59;p=oweals%2Fgnunet.git diff --git a/src/testbed/gnunet-service-testbed.c b/src/testbed/gnunet-service-testbed.c index d9a2a6c13..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,7 +25,8 @@ */ #include "gnunet-service-testbed.h" - +#include "gnunet-service-testbed_barriers.h" +#include "gnunet-service-testbed_connectionpool.h" /***********/ /* Globals */ @@ -34,7 +35,7 @@ /** * Our configuration */ -struct GNUNET_CONFIGURATION_Handle *our_config; +struct GNUNET_CONFIGURATION_Handle *GST_config; /** * The master context; generated with the first INIT message @@ -127,10 +128,6 @@ static struct MessageQueue *mq_head; */ static struct MessageQueue *mq_tail; -/** - * The hashmap of shared services - */ -static struct GNUNET_CONTAINER_MultiHashMap *ss_map; /** * The shutdown task handle @@ -194,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); @@ -234,19 +231,6 @@ host_list_add (struct GNUNET_TESTBED_Host *host) } -/** - * 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 * @@ -380,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; @@ -439,6 +423,57 @@ GST_forwarded_operation_timeout (void *cls, } +/** + * Parse service sharing specification line. + * Format is "[] [] ..." + * + * @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 struct GNUNET_TESTING_SharedService * +parse_shared_services (char *ss_str, struct GNUNET_CONFIGURATION_Handle *cfg) +{ + 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) + + slist = NULL; + n = 0; + ss.cfg = cfg; + for (; NULL != (arg = strtok (ss_str, " ")); ss_str = NULL) + { + ss.service = NULL; + ss.share = 0; + if (2 != sscanf (arg, "%255[^:]:%u", service, &ss.share)) + { + LOG (GNUNET_ERROR_TYPE_WARNING, "Ignoring shared service spec: %s", arg); + continue; + } + LOG_DEBUG ("Will be sharing %s service among %u peers\n", service, ss.share); + ss.service = GNUNET_strdup (service); + GROW_SS; + } + if (NULL != slist) + { + /* Add trailing NULL block */ + (void) memset (&ss, 0, sizeof (struct GNUNET_TESTING_SharedService)); + GROW_SS; + } + return slist; +#undef GROW_SS +} + + /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages * @@ -453,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) @@ -477,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); @@ -485,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, NULL); + 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); @@ -532,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)) { @@ -559,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); @@ -613,93 +670,6 @@ 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 - * - * @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) != 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); -} - - /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages * @@ -761,7 +731,7 @@ void GST_clear_fopcq () { struct ForwardedOperationContext *fopc; - + while (NULL != (fopc = fopcq_head)) { GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc); @@ -777,7 +747,7 @@ GST_clear_fopcq () case OP_SHUTDOWN_PEERS: { struct HandlerContext_ShutdownPeers *hc = fopc->cls; - + GNUNET_assert (0 < hc->nslaves); hc->nslaves--; if (0 == hc->nslaves) @@ -792,6 +762,7 @@ GST_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); @@ -801,29 +772,6 @@ GST_clear_fopcq () } -/** - * 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; -} - - /** * Task to clean up and shutdown nicely * @@ -837,10 +785,7 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 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 */ GST_clear_fopcq (); GST_free_lcfq (); @@ -849,6 +794,7 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GST_free_roccq (); GST_free_nccq (); GST_neighbour_list_clean(); + GST_free_prcq (); /* Clear peer list */ GST_destroy_peers (); /* Clear route list */ @@ -879,12 +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); } @@ -926,8 +874,6 @@ 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}, {&GST_handle_link_controllers, NULL, GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, sizeof (struct GNUNET_TESTBED_ControllerLinkRequest)}, @@ -939,7 +885,7 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server, {&GST_handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER, sizeof (struct GNUNET_TESTBED_PeerStopMessage)}, {&GST_handle_peer_get_config, NULL, - GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_CONFIGURATION, + GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION, sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)}, {&GST_handle_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT, @@ -953,11 +899,20 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server, sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage)}, {&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; + LOG_DEBUG ("Starting testbed\n"); if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED", "LOG_FILE", &logfile)) @@ -969,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", @@ -982,16 +939,16 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server, GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "testbed", "HOSTNAME", &hostname)); - our_config = GNUNET_CONFIGURATION_dup (cfg); + 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"); - GST_stats_init (our_config); + GST_stats_init (GST_config); + GST_barriers_init (GST_config); }