/*
This file is part of GNUnet.
- (C) 2008--2013 Christian Grothoff (and other contributing authors)
+ Copyright (C) 2008--2013 GNUnet e.V.
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
You should have received a copy of the GNU General Public License
along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
*/
/**
*/
#include "gnunet-service-testbed.h"
-
+#include "gnunet-service-testbed_barriers.h"
+#include "gnunet-service-testbed_connectionpool.h"
/***********/
/* Globals */
/**
* Our configuration
*/
-struct GNUNET_CONFIGURATION_Handle *our_config;
+struct GNUNET_CONFIGURATION_Handle *GST_config;
/**
* The master context; generated with the first INIT message
*/
static struct MessageQueue *mq_tail;
-/**
- * The hashmap of shared services
- */
-static struct GNUNET_CONTAINER_MultiHashMap *ss_map;
-
-/**
- * The shutdown task handle
- */
-static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
-
/**
* Function called to notify a client about the connection begin ready to queue
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);
}
-/**
- * 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
*
"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;
* Task to free resources when forwarded operation has been timedout
*
* @param cls the ForwardedOperationContext
- * @param tc the task context from scheduler
*/
void
-GST_forwarded_operation_timeout (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
+GST_forwarded_operation_timeout (void *cls)
{
struct ForwardedOperationContext *fopc = cls;
}
+/**
+ * Parse service sharing specification line.
+ * Format is "[<service:share>] [<service:share>] ..."
+ *
+ * @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
*
* @param message the actual message
*/
static void
-handle_init (void *cls, struct GNUNET_SERVER_Client *client,
+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;
+ char *ss_str;
+ struct GNUNET_TESTING_SharedService *ss;
+ unsigned int cnt;
uint16_t msize;
if (NULL != GST_context)
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);
LOG_DEBUG ("Our IP: %s\n", GST_context->master_ip);
GST_context->system =
GNUNET_TESTING_system_create ("testbed", GST_context->master_ip,
- hostname);
+ hostname, ss);
+ if (NULL != ss)
+ {
+ for (cnt = 0; NULL != ss[cnt].service; cnt++)
+ {
+ ss_str = (char *) ss[cnt].service;
+ GNUNET_free (ss_str);
+ }
+ GNUNET_free (ss);
+ ss = NULL;
+ }
host =
GNUNET_TESTBED_host_create_with_id (GST_context->host_id,
GST_context->master_ip, NULL,
- our_config, 0);
+ GST_config, 0);
host_list_add (host);
LOG_DEBUG ("Created master context with host ID: %u\n", GST_context->host_id);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
/**
- * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
+ * 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_add_host (void *cls, struct GNUNET_SERVER_Client *client,
+handle_add_host (void *cls,
+ struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *message)
{
struct GNUNET_TESTBED_Host *host;
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))
{
}
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);
/**
- * 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
+ * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages
*
* @param cls NULL
* @param client identification of the client
* @param message the actual message
*/
static void
-handle_slave_get_config (void *cls, struct GNUNET_SERVER_Client *client,
+handle_slave_get_config (void *cls,
+ struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *message)
{
struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
GST_clear_fopcq ()
{
struct ForwardedOperationContext *fopc;
-
+
while (NULL != (fopc = fopcq_head))
{
GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc);
GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc);
- if (GNUNET_SCHEDULER_NO_TASK != fopc->timeout_task)
+ if (NULL != fopc->timeout_task)
GNUNET_SCHEDULER_cancel (fopc->timeout_task);
GNUNET_SERVER_client_drop (fopc->client);
switch (fopc->type)
case OP_SHUTDOWN_PEERS:
{
struct HandlerContext_ShutdownPeers *hc = fopc->cls;
-
+
GNUNET_assert (0 < hc->nslaves);
hc->nslaves--;
if (0 == hc->nslaves)
case OP_LINK_CONTROLLERS:
case OP_GET_SLAVE_CONFIG:
case OP_MANAGE_SERVICE:
+ case OP_PEER_RECONFIGURE:
break;
case OP_FORWARDED:
GNUNET_assert (0);
}
-/**
- * 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
*
* @param cls NULL
- * @param tc the TaskContext from scheduler
*/
static void
-shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+shutdown_task (void *cls)
{
struct MessageQueue *mq_entry;
uint32_t id;
- shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n");
- (void) GNUNET_CONTAINER_multihashmap_iterate (ss_map, &ss_map_free_iterator,
- NULL);
- GNUNET_CONTAINER_multihashmap_destroy (ss_map);
+ LOG_DEBUG ("Shutting down testbed service\n");
/* cleanup any remaining forwarded operations */
GST_clear_fopcq ();
GST_free_lcfq ();
GST_free_roccq ();
GST_free_nccq ();
GST_neighbour_list_clean();
+ GST_free_prcq ();
/* Clear peer list */
GST_destroy_peers ();
+ /* Clear route list */
+ GST_route_list_clear ();
+ /* Clear GST_slave_list */
+ GST_slave_list_clear ();
/* Clear host list */
for (id = 0; id < GST_host_list_size; id++)
if (NULL != GST_host_list[id])
GNUNET_TESTBED_host_destroy (GST_host_list[id]);
GNUNET_free_non_null (GST_host_list);
- /* Clear route list */
- GST_route_list_clear ();
- /* Clear GST_slave_list */
- GST_slave_list_clear ();
if (NULL != GST_context)
{
GNUNET_free_non_null (GST_context->master_ip);
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);
}
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, 0},
+ 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)},
{&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,
sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage)},
{&GST_handle_shutdown_peers, NULL, GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS,
sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage)},
- {NULL}
+ {&GST_handle_peer_reconfigure, NULL,
+ GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER, 0},
+ {&GST_handle_barrier_init, NULL,
+ GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT, 0},
+ {&GST_handle_barrier_cancel, NULL,
+ GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL, 0},
+ {&GST_handle_barrier_status, NULL,
+ GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS, 0},
+ {NULL, NULL, 0, 0}
};
char *logfile;
unsigned long long num;
+ LOG_DEBUG ("Starting testbed\n");
if (GNUNET_OK ==
GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED", "LOG_FILE",
&logfile))
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",
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);
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
LOG_DEBUG ("Testbed startup complete\n");
- GST_stats_init (our_config);
+ GST_stats_init (GST_config);
+ GST_barriers_init (GST_config);
}
int
main (int argc, char *const *argv)
{
- //sleep (15); /* Debugging */
return (GNUNET_OK ==
- GNUNET_SERVICE_run (argc, argv, "testbed", GNUNET_SERVICE_OPTION_NONE,
+ GNUNET_SERVICE_run (argc, argv,
+ "testbed",
+ GNUNET_SERVICE_OPTION_NONE,
&testbed_run, NULL)) ? 0 : 1;
}