From: Christian Grothoff Date: Mon, 10 Oct 2016 15:47:00 +0000 (+0000) Subject: migrating testbed to new service API X-Git-Tag: initial-import-from-subversion-38251~134 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=93085e8a2991fde229400b588a5930e9fcca0d75;p=oweals%2Fgnunet.git migrating testbed to new service API --- diff --git a/src/testbed/gnunet-service-test-barriers.c b/src/testbed/gnunet-service-test-barriers.c index ce5249696..874c7a363 100644 --- a/src/testbed/gnunet-service-test-barriers.c +++ b/src/testbed/gnunet-service-test-barriers.c @@ -76,7 +76,9 @@ do_shutdown (void *cls) * #GNUNET_OK if the barrier is crossed */ static void -barrier_wait_cb (void *cls, const char *name, int status) +barrier_wait_cb (void *cls, + const char *name, + int status) { GNUNET_break (NULL == cls); wh = NULL; @@ -117,10 +119,12 @@ run (void *cls, { unsigned int rsec; - rsec = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, 10); - tt = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, rsec), - &do_wait, NULL); + rsec = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, + 10); + tt = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, + rsec), + &do_wait, + NULL); GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); } @@ -139,6 +143,10 @@ main (int argc, char **argv) ret = GNUNET_PROGRAM_run (argc, argv, - "test-barriers", "nohelp", options, &run, NULL); + "test-barriers", + "nohelp", + options, + &run, + NULL); return ret; } diff --git a/src/testbed/gnunet-service-testbed.c b/src/testbed/gnunet-service-testbed.c index 9e181f85a..39697cb56 100644 --- a/src/testbed/gnunet-service-testbed.c +++ b/src/testbed/gnunet-service-testbed.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2008--2013 GNUnet e.V. + Copyright (C) 2008--2013, 2016 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 @@ -82,129 +82,17 @@ unsigned int GST_peer_list_size; /* Local definitions and variables */ /***********************************/ -/** - * 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; -}; - /** * Our hostname; we give this to all the peers we start */ static char *hostname; -/** - * Current Transmit Handle; NULL if no notify transmit exists currently - */ -static struct GNUNET_SERVER_TransmitHandle *transmit_handle; - -/** - * The message queue head - */ -static struct MessageQueue *mq_head; - -/** - * The message queue tail - */ -static struct MessageQueue *mq_tail; - - -/** - * Function called to notify a client about the connection begin ready to queue - * more data. "buf" will be NULL and "size" zero if the connection was closed - * for writing in the meantime. - * - * @param cls NULL - * @param size number of bytes available in buf - * @param buf where the callee should write the message - * @return number of bytes written to buf - */ -static size_t -transmit_ready_notify (void *cls, size_t size, void *buf) -{ - struct MessageQueue *mq_entry; - - transmit_handle = NULL; - mq_entry = mq_head; - GNUNET_assert (NULL != mq_entry); - if (0 == size) - return 0; - GNUNET_assert (ntohs (mq_entry->msg->size) <= size); - size = ntohs (mq_entry->msg->size); - GNUNET_memcpy (buf, mq_entry->msg, size); - GNUNET_free (mq_entry->msg); - GNUNET_SERVER_client_drop (mq_entry->client); - GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry); - GNUNET_free (mq_entry); - mq_entry = mq_head; - if (NULL != mq_entry) - transmit_handle = - GNUNET_SERVER_notify_transmit_ready (mq_entry->client, - ntohs (mq_entry->msg->size), - GNUNET_TIME_UNIT_FOREVER_REL, - &transmit_ready_notify, NULL); - return size; -} - - -/** - * Queues a message in send queue for sending to the service - * - * @param client the client to whom the queued message has to be sent - * @param msg the message to queue - */ -void -GST_queue_message (struct GNUNET_SERVER_Client *client, - struct GNUNET_MessageHeader *msg) -{ - struct MessageQueue *mq_entry; - uint16_t type; - uint16_t size; - - type = ntohs (msg->type); - size = ntohs (msg->size); - GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) && - (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type)); - mq_entry = GNUNET_new (struct MessageQueue); - mq_entry->msg = msg; - mq_entry->client = client; - GNUNET_SERVER_client_keep (client); - LOG_DEBUG ("Queueing message of type %u, size %u for sending\n", type, - ntohs (msg->size)); - GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq_entry); - if (NULL == transmit_handle) - transmit_handle = - GNUNET_SERVER_notify_transmit_ready (client, size, - GNUNET_TIME_UNIT_FOREVER_REL, - &transmit_ready_notify, NULL); -} - /** * Function to add a host to the current list of known hosts * * @param host the host to add - * @return GNUNET_OK on success; GNUNET_SYSERR on failure due to host-id + * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure due to host-id * already in use */ static int @@ -233,24 +121,25 @@ host_list_add (struct GNUNET_TESTBED_Host *host) * @param emsg the error message; can be NULL */ void -GST_send_operation_fail_msg (struct GNUNET_SERVER_Client *client, - uint64_t operation_id, const char *emsg) +GST_send_operation_fail_msg (struct GNUNET_SERVICE_Client *client, + uint64_t operation_id, + const char *emsg) { + struct GNUNET_MQ_Envelope *env; struct GNUNET_TESTBED_OperationFailureEventMessage *msg; - uint16_t msize; uint16_t emsg_len; - msize = sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage); emsg_len = (NULL == emsg) ? 0 : strlen (emsg) + 1; - msize += emsg_len; - msg = GNUNET_malloc (msize); - msg->header.size = htons (msize); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT); + env = GNUNET_MQ_msg_extra (msg, + emsg_len, + 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) - GNUNET_memcpy (&msg[1], emsg, emsg_len); - GST_queue_message (client, &msg->header); + GNUNET_memcpy (&msg[1], + emsg, + emsg_len); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); } @@ -261,22 +150,21 @@ GST_send_operation_fail_msg (struct GNUNET_SERVER_Client *client, * @param operation_id the id of the operation which was successful */ void -GST_send_operation_success_msg (struct GNUNET_SERVER_Client *client, +GST_send_operation_success_msg (struct GNUNET_SERVICE_Client *client, uint64_t operation_id) { + struct GNUNET_MQ_Envelope *env; struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg; - uint16_t msize; - msize = sizeof (struct GNUNET_TESTBED_GenericOperationSuccessEventMessage); - msg = GNUNET_malloc (msize); - msg->header.size = htons (msize); - msg->header.type = - htons (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS); + env = GNUNET_MQ_msg (msg, + GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS); msg->operation_id = GNUNET_htonll (operation_id); msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED); - GST_queue_message (client, &msg->header); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); } + /** * Callback which will be called after a host registration succeeded or failed * @@ -284,7 +172,8 @@ GST_send_operation_success_msg (struct GNUNET_SERVER_Client *client, * @param emsg the error message; NULL if host registration is successful */ static void -hr_completion (void *cls, const char *emsg); +hr_completion (void *cls, + const char *emsg); /** @@ -304,8 +193,10 @@ register_next_host (struct Slave *slave) LOG (GNUNET_ERROR_TYPE_DEBUG, "Registering host %u at %u\n", GNUNET_TESTBED_host_get_id_ (hr->host), GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id])); - slave->rhandle = - GNUNET_TESTBED_register_host (slave->controller, hr->host, hr_completion, + slave->rhandle + = GNUNET_TESTBED_register_host (slave->controller, + hr->host, + hr_completion, slave); } @@ -317,7 +208,8 @@ register_next_host (struct Slave *slave) * @param emsg the error message; NULL if host registration is successful */ static void -hr_completion (void *cls, const char *emsg) +hr_completion (void *cls, + const char *emsg) { struct Slave *slave = cls; struct HostRegistration *hr; @@ -325,12 +217,16 @@ 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_ (GST_host_list[slave->host_id])); - GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head, slave->hr_dll_tail, hr); + GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head, + slave->hr_dll_tail, + hr); if (NULL != hr->cb) - hr->cb (hr->cb_cls, emsg); + hr->cb (hr->cb_cls, + emsg); GNUNET_free (hr); if (NULL != slave->hr_dll_head) register_next_host (slave); @@ -349,7 +245,8 @@ hr_completion (void *cls, const char *emsg) void GST_queue_host_registration (struct Slave *slave, GNUNET_TESTBED_HostRegistrationCompletion cb, - void *cb_cls, struct GNUNET_TESTBED_Host *host) + void *cb_cls, + struct GNUNET_TESTBED_Host *host) { struct HostRegistration *hr; int call_register; @@ -363,7 +260,9 @@ GST_queue_host_registration (struct Slave *slave, 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); } @@ -380,23 +279,24 @@ GST_forwarded_operation_reply_relay (void *cls, const struct GNUNET_MessageHeader *msg) { struct ForwardedOperationContext *fopc = cls; - struct GNUNET_MessageHeader *dup_msg; - uint16_t msize; + struct GNUNET_MQ_Envelope *env; - msize = ntohs (msg->size); - LOG_DEBUG ("Relaying message with type: %u, size: %u\n", ntohs (msg->type), - msize); - dup_msg = GNUNET_copy_message (msg); - GST_queue_message (fopc->client, dup_msg); - GNUNET_SERVER_client_drop (fopc->client); + LOG_DEBUG ("Relaying message with type: %u, size: %u\n", + ntohs (msg->type), + ntohs (msg->size)); + env = GNUNET_MQ_msg_copy (msg); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (fopc->client), + env); GNUNET_SCHEDULER_cancel (fopc->timeout_task); - GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc); + GNUNET_CONTAINER_DLL_remove (fopcq_head, + fopcq_tail, + fopc); GNUNET_free (fopc); } /** - * Task to free resources when forwarded operation has been timedout + * Task to free resources when forwarded operation has been timed out * * @param cls the ForwardedOperationContext */ @@ -405,12 +305,16 @@ GST_forwarded_operation_timeout (void *cls) { struct ForwardedOperationContext *fopc = cls; + fopc->timeout_task = NULL; GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc); - LOG (GNUNET_ERROR_TYPE_DEBUG, "A forwarded operation has timed out\n"); - GST_send_operation_fail_msg (fopc->client, fopc->operation_id, + 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_CONTAINER_DLL_remove (fopcq_head, + fopcq_tail, + fopc); GNUNET_free (fopc); } @@ -425,7 +329,8 @@ GST_forwarded_operation_timeout (void *cls) * upon empty service sharing specification. */ static struct GNUNET_TESTING_SharedService * -parse_shared_services (char *ss_str, struct GNUNET_CONFIGURATION_Handle *cfg) +parse_shared_services (char *ss_str, + struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_TESTING_SharedService ss; struct GNUNET_TESTING_SharedService *slist; @@ -446,19 +351,27 @@ parse_shared_services (char *ss_str, struct GNUNET_CONFIGURATION_Handle *cfg) { ss.service = NULL; ss.share = 0; - if (2 != sscanf (arg, "%255[^:]:%u", service, &ss.share)) + if (2 != sscanf (arg, "%255[^:]:%u", + service, + &ss.share)) { - LOG (GNUNET_ERROR_TYPE_WARNING, "Ignoring shared service spec: %s", arg); + 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); + 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)); + (void) memset (&ss, + 0, + sizeof (struct GNUNET_TESTING_SharedService)); GROW_SS; } return slist; @@ -467,66 +380,78 @@ parse_shared_services (char *ss_str, struct GNUNET_CONFIGURATION_Handle *cfg) /** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages + * Check #GNUNET_MESSAGE_TYPE_TESTBED_INIT messages * - * @param cls NULL - * @param client identification of the client + * @param cls identification of the client + * @param message the actual message + * @return #GNUNET_OK if @a message is well-formed + */ +static int +check_init (void *cls, + const struct GNUNET_TESTBED_InitMessage *msg) +{ + const char *controller_hostname; + uint16_t msize; + + msize = ntohs (msg->header.size) - sizeof (struct GNUNET_TESTBED_InitMessage); + controller_hostname = (const char *) &msg[1]; + if ('\0' != controller_hostname[msize - 1]) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_INIT messages + * + * @param cls 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) { - const struct GNUNET_TESTBED_InitMessage *msg; + struct GNUNET_SERVICE_Client *client = cls; 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) { LOG_DEBUG ("We are being connected to laterally\n"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); 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; - } - msize -= sizeof (struct GNUNET_TESTBED_InitMessage); controller_hostname = (const char *) &msg[1]; - if ('\0' != controller_hostname[msize - 1]) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } ss_str = NULL; ss = NULL; - if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (GST_config, "TESTBED", - "SHARED_SERVICES", - &ss_str)) + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (GST_config, + "TESTBED", + "SHARED_SERVICES", + &ss_str)) { - ss = parse_shared_services (ss_str, GST_config); + 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); 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); + 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++) @@ -539,28 +464,64 @@ handle_init (void *cls, } host = GNUNET_TESTBED_host_create_with_id (GST_context->host_id, - GST_context->master_ip, NULL, - GST_config, 0); + GST_context->master_ip, + NULL, + 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); + LOG_DEBUG ("Created master context with host ID: %u\n", + GST_context->host_id); + GNUNET_SERVICE_client_continue (client); +} + + +/** + * Check #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages + * + * @param cls identification of the client + * @param msg the actual message + * @return #GNUNET_OK if @a message is well-formed + */ +static int +check_add_host (void *cls, + const struct GNUNET_TESTBED_AddHostMessage *msg) +{ + uint16_t username_length; + uint16_t hostname_length; + uint16_t msize; + + msize = ntohs (msg->header.size) - sizeof (struct GNUNET_TESTBED_AddHostMessage); + username_length = ntohs (msg->username_length); + hostname_length = ntohs (msg->hostname_length); + /* msg must contain hostname */ + if ( (msize <= username_length) || + (0 == hostname_length) ) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + /* msg must contain configuration */ + if (msize <= username_length + hostname_length) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; } /** * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ static void handle_add_host (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) + const struct GNUNET_TESTBED_AddHostMessage *msg) { + struct GNUNET_SERVICE_Client *client = cls; struct GNUNET_TESTBED_Host *host; - const struct GNUNET_TESTBED_AddHostMessage *msg; struct GNUNET_TESTBED_HostConfirmedMessage *reply; struct GNUNET_CONFIGURATION_Handle *host_cfg; char *username; @@ -570,36 +531,10 @@ handle_add_host (void *cls, uint32_t host_id; uint16_t username_length; uint16_t hostname_length; - uint16_t reply_size; - uint16_t msize; + struct GNUNET_MQ_Envelope *env; - msg = (const struct GNUNET_TESTBED_AddHostMessage *) message; - msize = ntohs (msg->header.size); - if (msize <= sizeof (struct GNUNET_TESTBED_AddHostMessage)) - { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } 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)) - { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - /* msg must contain configuration */ - if (msize <= (sizeof (struct GNUNET_TESTBED_AddHostMessage) + - username_length + hostname_length)) - { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } username = NULL; hostname = NULL; ptr = &msg[1]; @@ -610,13 +545,15 @@ handle_add_host (void *cls, ptr += username_length; } hostname = GNUNET_malloc (hostname_length + 1); - strncpy (hostname, ptr, hostname_length); - if (NULL == (host_cfg = GNUNET_TESTBED_extract_config_ (message))) + strncpy (hostname, + ptr, + hostname_length); + if (NULL == (host_cfg = GNUNET_TESTBED_extract_config_ (&msg->header))) { GNUNET_free_non_null (username); GNUNET_free_non_null (hostname); GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } host_id = ntohl (msg->host_id); @@ -628,94 +565,108 @@ handle_add_host (void *cls, else 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)); + 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); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } - 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); + LOG_DEBUG ("%s: %u", + emsg, + host_id); GNUNET_TESTBED_host_destroy (host); - reply_size += strlen (emsg) + 1; - reply = GNUNET_malloc (reply_size); - GNUNET_memcpy (&reply[1], emsg, strlen (emsg) + 1); + env = GNUNET_MQ_msg_extra (reply, + strlen (emsg) + 1, + GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS); + GNUNET_memcpy (&reply[1], + emsg, + strlen (emsg) + 1); } else { - LOG_DEBUG ("Added host %u at %u\n", host_id, GST_context->host_id); - reply = GNUNET_malloc (reply_size); + LOG_DEBUG ("Added host %u at %u\n", + host_id, + GST_context->host_id); + env = GNUNET_MQ_msg (reply, + GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS); } - 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); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); + GNUNET_SERVICE_client_continue (client); } /** * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ static void handle_slave_get_config (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) + const struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg) { - struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg; + struct GNUNET_SERVICE_Client *client = cls; struct Slave *slave; struct GNUNET_TESTBED_SlaveConfiguration *reply; const struct GNUNET_CONFIGURATION_Handle *cfg; + struct GNUNET_MQ_Envelope *env; char *config; char *xconfig; size_t config_size; size_t xconfig_size; - size_t reply_size; uint64_t op_id; uint32_t slave_id; - msg = (struct GNUNET_TESTBED_SlaveGetConfigurationMessage *) message; slave_id = ntohl (msg->slave_id); op_id = GNUNET_ntohll (msg->operation_id); - if ((GST_slave_list_size <= slave_id) || (NULL == GST_slave_list[slave_id])) + if ( (GST_slave_list_size <= slave_id) || + (NULL == GST_slave_list[slave_id]) ) { /* FIXME: Add forwardings for this type of message here.. */ - GST_send_operation_fail_msg (client, op_id, "Slave not found"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GST_send_operation_fail_msg (client, + op_id, + "Slave not found"); + GNUNET_SERVICE_client_continue (client); return; } 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); + config = GNUNET_CONFIGURATION_serialize (cfg, + &config_size); + /* FIXME: maybe we want to transmit the delta to the default here? */ + 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_SLAVE_CONFIGURATION); - reply->header.size = htons ((uint16_t) reply_size); + GNUNET_assert (xconfig_size + sizeof (struct GNUNET_TESTBED_SlaveConfiguration) <= UINT16_MAX); + GNUNET_assert (xconfig_size <= UINT16_MAX); + env = GNUNET_MQ_msg_extra (reply, + xconfig_size, + GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION); reply->slave_id = msg->slave_id; reply->operation_id = msg->operation_id; reply->config_size = htons ((uint16_t) config_size); - GST_queue_message (client, &reply->header); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_memcpy (&reply[1], + xconfig, + xconfig_size); + GNUNET_free (xconfig); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); + GNUNET_SERVICE_client_continue (client); } @@ -729,11 +680,12 @@ GST_clear_fopcq () while (NULL != (fopc = fopcq_head)) { - GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc); + GNUNET_CONTAINER_DLL_remove (fopcq_head, + fopcq_tail, + fopc); GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc); if (NULL != fopc->timeout_task) GNUNET_SCHEDULER_cancel (fopc->timeout_task); - GNUNET_SERVER_client_drop (fopc->client); switch (fopc->type) { case OP_PEER_CREATE: @@ -775,13 +727,12 @@ GST_clear_fopcq () static void shutdown_task (void *cls) { - struct MessageQueue *mq_entry; uint32_t id; LOG_DEBUG ("Shutting down testbed service\n"); /* cleanup any remaining forwarded operations */ GST_clear_fopcq (); - GST_free_lcfq (); + GST_free_lcf (); GST_free_mctxq (); GST_free_occq (); GST_free_roccq (); @@ -803,20 +754,11 @@ shutdown_task (void *cls) { 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_TESTING_system_destroy (GST_context->system, + GNUNET_YES); GNUNET_free (GST_context); GST_context = NULL; } - if (NULL != 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_free (mq_entry); - } GNUNET_free_non_null (hostname); /* Free hello cache */ GST_cache_clear (); @@ -829,20 +771,59 @@ shutdown_task (void *cls) } +/** + * Callback for client connect + * + * @param cls NULL + * @param client the client which has disconnected + * @param mq queue for sending messages to @a client + * @return @a client + */ +static void * +client_connect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + struct GNUNET_MQ_Handle *mq) +{ + return client; +} + + /** * Callback for client disconnect * * @param cls NULL * @param client the client which has disconnected + * @param app_ctx should match @a client */ static void -client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client) +client_disconnect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + void *app_ctx) { + struct ForwardedOperationContext *fopc; + struct ForwardedOperationContext *fopcn; + + GNUNET_assert (client == app_ctx); + GST_notify_client_disconnect_oc (client); + GST_link_notify_disconnect (client); + GST_notify_client_disconnect_peers (client); + for (fopc = fopcq_head; NULL != fopc; fopc = fopcn) + { + fopcn = fopc->next; + if (fopc->client == client) + { + /* handle as if it were a timeout */ + GNUNET_SCHEDULER_cancel (fopc->timeout_task); + GST_forwarded_operation_timeout (fopc); + } + } if (NULL == GST_context) return; if (client == GST_context->client) { - LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Master client disconnected\n"); + GST_context->client = NULL; /* should not be needed as we're terminated by failure to read * from stdin, but if stdin fails for some reason, this shouldn't * hurt for now --- might need to revise this later if we ever @@ -857,51 +838,14 @@ client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client) * Testbed setup * * @param cls closure - * @param server the initialized server * @param cfg configuration to use + * @param service the initialized server */ static void -testbed_run (void *cls, struct GNUNET_SERVER_Handle *server, - const struct GNUNET_CONFIGURATION_Handle *cfg) +testbed_run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_SERVICE_Handle *service) { - 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}, - {&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)}, - {&GST_handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_START_PEER, - sizeof (struct GNUNET_TESTBED_PeerStartMessage)}, - {&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_INFORMATION, - sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)}, - {&GST_handle_overlay_connect, NULL, - GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT, - sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)}, - {&GST_handle_remote_overlay_connect, NULL, - GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT, 0}, - {&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)}, - {&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; @@ -910,32 +854,40 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server, GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED", "LOG_FILE", &logfile)) { - GNUNET_break (GNUNET_OK == GNUNET_log_setup ("testbed", "DEBUG", logfile)); + GNUNET_break (GNUNET_OK == + GNUNET_log_setup ("testbed", + "DEBUG", + logfile)); GNUNET_free (logfile); } GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_number (cfg, "TESTBED", - "CACHE_SIZE", &num)); + 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_ - (OPERATION_QUEUE_TYPE_FIXED, (unsigned int) num); + GNUNET_CONFIGURATION_get_value_number (cfg, + "TESTBED", + "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", + GNUNET_CONFIGURATION_get_value_time (cfg, + "TESTBED", "OPERATION_TIMEOUT", - (struct - GNUNET_TIME_Relative *) + (struct GNUNET_TIME_Relative *) &GST_timeout)); GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (cfg, "testbed", - "HOSTNAME", &hostname)); + 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); - GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, + NULL); LOG_DEBUG ("Testbed startup complete\n"); GST_stats_init (GST_config); GST_barriers_init (GST_config); @@ -943,16 +895,84 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server, /** - * The starting point of execution - */ -int -main (int argc, char *const *argv) -{ - return (GNUNET_OK == - GNUNET_SERVICE_run (argc, argv, - "testbed", - GNUNET_SERVICE_OPTION_NONE, - &testbed_run, NULL)) ? 0 : 1; -} + * Define "main" method using service macro. + */ +GNUNET_SERVICE_MAIN +("testbed", + GNUNET_SERVICE_OPTION_NONE, + &testbed_run, + &client_connect_cb, + &client_disconnect_cb, + NULL, + GNUNET_MQ_hd_var_size (init, + GNUNET_MESSAGE_TYPE_TESTBED_INIT, + struct GNUNET_TESTBED_InitMessage, + NULL), + GNUNET_MQ_hd_var_size (add_host, + GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, + struct GNUNET_TESTBED_AddHostMessage, + NULL), + GNUNET_MQ_hd_fixed_size (slave_get_config, + GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION, + struct GNUNET_TESTBED_SlaveGetConfigurationMessage, + NULL), + GNUNET_MQ_hd_fixed_size (link_controllers, + GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, + struct GNUNET_TESTBED_ControllerLinkRequest, + NULL), + GNUNET_MQ_hd_var_size (remote_overlay_connect, + GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT, + struct GNUNET_TESTBED_RemoteOverlayConnectMessage, + NULL), + GNUNET_MQ_hd_fixed_size (overlay_connect, + GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT, + struct GNUNET_TESTBED_OverlayConnectMessage, + NULL), + GNUNET_MQ_hd_var_size (peer_create, + GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER, + struct GNUNET_TESTBED_PeerCreateMessage, + NULL), + GNUNET_MQ_hd_fixed_size (peer_destroy, + GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER, + struct GNUNET_TESTBED_PeerDestroyMessage, + NULL), + GNUNET_MQ_hd_fixed_size (peer_start, + GNUNET_MESSAGE_TYPE_TESTBED_START_PEER, + struct GNUNET_TESTBED_PeerStartMessage, + NULL), + GNUNET_MQ_hd_fixed_size (peer_stop, + GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER, + struct GNUNET_TESTBED_PeerStopMessage, + NULL), + GNUNET_MQ_hd_fixed_size (peer_get_config, + GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION, + struct GNUNET_TESTBED_PeerGetConfigurationMessage, + NULL), + GNUNET_MQ_hd_var_size (manage_peer_service, + GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE, + struct GNUNET_TESTBED_ManagePeerServiceMessage, + NULL), + GNUNET_MQ_hd_fixed_size (shutdown_peers, + GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS, + struct GNUNET_TESTBED_ShutdownPeersMessage, + NULL), + GNUNET_MQ_hd_var_size (peer_reconfigure, + GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER, + struct GNUNET_TESTBED_PeerReconfigureMessage, + NULL), + GNUNET_MQ_hd_var_size (barrier_init, + GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT, + struct GNUNET_TESTBED_BarrierInit, + NULL), + GNUNET_MQ_hd_var_size (barrier_cancel, + GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL, + struct GNUNET_TESTBED_BarrierCancel, + NULL), + GNUNET_MQ_hd_var_size (barrier_status, + GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS, + struct GNUNET_TESTBED_BarrierStatusMsg, + NULL), + GNUNET_MQ_handler_end ()); + /* end of gnunet-service-testbed.c */ diff --git a/src/testbed/gnunet-service-testbed.h b/src/testbed/gnunet-service-testbed.h index b19d3c516..6f797a066 100644 --- a/src/testbed/gnunet-service-testbed.h +++ b/src/testbed/gnunet-service-testbed.h @@ -96,7 +96,7 @@ struct ForwardedOperationContext /** * The client to which we have to reply */ - struct GNUNET_SERVER_Client *client; + struct GNUNET_SERVICE_Client *client; /** * Closure pointer @@ -161,7 +161,7 @@ struct LinkControllersContext /** * The client which initiated the link controller operation */ - struct GNUNET_SERVER_Client *client; + struct GNUNET_SERVICE_Client *client; /** * The ID of the operation @@ -174,7 +174,6 @@ struct LinkControllersContext /** * A peer */ - struct Peer { @@ -255,7 +254,7 @@ struct Context /** * The client handle associated with this context */ - struct GNUNET_SERVER_Client *client; + struct GNUNET_SERVICE_Client *client; /** * The network address of the master controller @@ -296,6 +295,9 @@ struct SharedService }; +struct RegisteredHostContext; + + /** * Context information to used during operations which forward the overlay * connect message @@ -312,6 +314,11 @@ struct ForwardedOverlayConnectContext */ struct ForwardedOverlayConnectContext *prev; + /** + * Which host does this FOCC belong to? + */ + struct RegisteredHostContext *rhc; + /** * A copy of the original overlay connect message */ @@ -320,7 +327,7 @@ struct ForwardedOverlayConnectContext /** * The client handle */ - struct GNUNET_SERVER_Client *client; + struct GNUNET_SERVICE_Client *client; /** * The id of the operation which created this context information @@ -391,13 +398,13 @@ struct RegisteredHostContext /** - * Context data for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS handler + * Context data for #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS handler */ struct HandlerContext_ShutdownPeers { /** * The number of slave we expect to hear from since we forwarded the - * GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS message to them + * #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS message to them */ unsigned int nslaves; @@ -506,17 +513,6 @@ extern char *GST_stats_dir; } while (0) -/** - * Queues a message in send queue for sending to the service - * - * @param client the client to whom the queued message has to be sent - * @param msg the message to queue - */ -void -GST_queue_message (struct GNUNET_SERVER_Client *client, - struct GNUNET_MessageHeader *msg); - - /** * Function to destroy a peer * @@ -530,7 +526,7 @@ GST_destroy_peer (struct Peer *peer); * Stops and destroys all peers */ void -GST_destroy_peers (); +GST_destroy_peers (void); /** @@ -546,15 +542,14 @@ GST_find_dest_route (uint32_t host_id); /** - * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages + * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT messages * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message); +handle_overlay_connect (void *cls, + const struct GNUNET_TESTBED_OverlayConnectMessage *msg); /** @@ -597,7 +592,7 @@ GST_forwarded_operation_timeout (void *cls); * Clears the forwarded operations queue */ void -GST_clear_fopcq (); +GST_clear_fopcq (void); /** @@ -608,8 +603,27 @@ GST_clear_fopcq (); * @param emsg the error message; can be NULL */ void -GST_send_operation_fail_msg (struct GNUNET_SERVER_Client *client, - uint64_t operation_id, const char *emsg); +GST_send_operation_fail_msg (struct GNUNET_SERVICE_Client *client, + uint64_t operation_id, + const char *emsg); + + +/** + * Notify OC subsystem that @a client disconnected. + * + * @param client the client that disconnected + */ +void +GST_notify_client_disconnect_oc (struct GNUNET_SERVICE_Client *client); + + +/** + * Notify peers subsystem that @a client disconnected. + * + * @param client the client that disconnected + */ +void +GST_notify_client_disconnect_peers (struct GNUNET_SERVICE_Client *client); /** @@ -619,140 +633,180 @@ GST_send_operation_fail_msg (struct GNUNET_SERVER_Client *client, * @param operation_id the id of the operation which was successful */ void -GST_send_operation_success_msg (struct GNUNET_SERVER_Client *client, +GST_send_operation_success_msg (struct GNUNET_SERVICE_Client *client, uint64_t operation_id); /** - * Handler for GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT messages + * Check #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message + * @return #GNUNET_OK if @a msg is well-formed + */ +int +check_remote_overlay_connect (void *cls, + const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg); + + +/** + * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages + * + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_remote_overlay_connect (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message); +handle_remote_overlay_connect (void *cls, + const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg); + + +/** + * Check #GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages + * + * @param cls identification of the client + * @param msg the actual message + * @return #GNUNET_OK if @a msg is well-formed + */ +int +check_peer_create (void *cls, + const struct GNUNET_TESTBED_PeerCreateMessage *msg); /** - * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages + * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages * - * @param cls NULL - * @param client identification of the client + * @param cls identification of the client * @param message the actual message */ void -GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message); +handle_peer_create (void *cls, + const struct GNUNET_TESTBED_PeerCreateMessage *msg); /** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages + * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message); +handle_peer_destroy (void *cls, + const struct GNUNET_TESTBED_PeerDestroyMessage *msg); /** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages + * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message); +handle_peer_start (void *cls, + const struct GNUNET_TESTBED_PeerStartMessage *msg); /** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages + * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages * - * @param cls NULL - * @param client identification of the client + * @param cls identification of the client * @param message the actual message */ void -GST_handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message); +handle_peer_stop (void *cls, + const struct GNUNET_TESTBED_PeerStopMessage *msg); /** - * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages + * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message); +handle_peer_get_config (void *cls, + const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg); /** - * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages + * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_shutdown_peers (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message); +handle_shutdown_peers (void *cls, + const struct GNUNET_TESTBED_ShutdownPeersMessage *msg); /** - * Handler for GNUNET_TESTBED_ManagePeerServiceMessage message + * Check #GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE message * - * @param cls NULL - * @param client identification of client - * @param message the actual message + * @param cls identification of client + * @param msg the actual message + * @return #GNUNET_OK if @a msg is well-formed + */ +int +check_manage_peer_service (void *cls, + const struct GNUNET_TESTBED_ManagePeerServiceMessage *msg); + + +/** + * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE message + * + * @param cls identification of client + * @param msg the actual message */ void -GST_handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message); +handle_manage_peer_service (void *cls, + const struct GNUNET_TESTBED_ManagePeerServiceMessage *msg); + + /** - * Handler for GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages. + * Check #GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages. + * + * @param cls identification of the client + * @param msg the actual message + * @return #GNUNET_OK if @a msg is well-formed + */ +int +check_peer_reconfigure (void *cls, + const struct GNUNET_TESTBED_PeerReconfigureMessage *msg); + + +/** + * Handler for #GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages. * Should stop the peer asyncronously, destroy it and create it again with the * new configuration. * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_peer_reconfigure (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message); +handle_peer_reconfigure (void *cls, + const struct GNUNET_TESTBED_PeerReconfigureMessage *msg); /** * Frees the ManageServiceContext queue */ void -GST_free_mctxq (); +GST_free_mctxq (void); /** * Cleans up the queue used for forwarding link controllers requests */ void -GST_free_lcfq (); +GST_free_lcf (void); /** * Cleans up the route list */ void -GST_route_list_clear (); +GST_route_list_clear (void); /** @@ -777,21 +831,21 @@ GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc); * Clears all pending overlay connect contexts in queue */ void -GST_free_occq (); +GST_free_occq (void); /** * Clears all pending remote overlay connect contexts in queue */ void -GST_free_roccq (); +GST_free_roccq (void); /** * Cleans up the Peer reconfigure context list */ void -GST_free_prcq (); +GST_free_prcq (void); /** @@ -807,7 +861,7 @@ GST_cache_init (unsigned int size); * Clear cache */ void -GST_cache_clear (); +GST_cache_clear (void); /** @@ -845,6 +899,6 @@ GST_stats_init (const struct GNUNET_CONFIGURATION_Handle *cfg); * Shutdown the status calls module. */ void -GST_stats_destroy (); +GST_stats_destroy (void); /* End of gnunet-service-testbed.h */ diff --git a/src/testbed/gnunet-service-testbed_barriers.c b/src/testbed/gnunet-service-testbed_barriers.c index c3ae82ed8..831bc3c6d 100644 --- a/src/testbed/gnunet-service-testbed_barriers.c +++ b/src/testbed/gnunet-service-testbed_barriers.c @@ -60,28 +60,6 @@ struct Barrier; -/** - * Message queue for transmitting messages - */ -struct MessageQueue -{ - /** - * next pointer for DLL - */ - struct MessageQueue *next; - - /** - * prev pointer for DLL - */ - struct MessageQueue *prev; - - /** - * The message to be sent - */ - struct GNUNET_MessageHeader *msg; -}; - - /** * Context to be associated with each client */ @@ -105,22 +83,8 @@ struct ClientCtx /** * The client handle */ - struct GNUNET_SERVER_Client *client; - - /** - * the transmission handle - */ - struct GNUNET_SERVER_TransmitHandle *tx; + struct GNUNET_SERVICE_Client *client; - /** - * message queue head - */ - struct MessageQueue *mq_head; - - /** - * message queue tail - */ - struct MessageQueue *mq_tail; }; @@ -169,7 +133,7 @@ struct Barrier /** * The client handle to the master controller */ - struct GNUNET_SERVER_Client *mc; + struct GNUNET_SERVICE_Client *mc; /** * The name of the barrier @@ -199,7 +163,7 @@ struct Barrier /** * Identifier for the timeout task */ - struct GNUNET_SCHEDULER_Task * tout_task; + struct GNUNET_SCHEDULER_Task *tout_task; /** * The status of this barrier @@ -247,102 +211,7 @@ static struct GNUNET_CONTAINER_MultiHashMap *barrier_map; /** * Service context */ -static struct GNUNET_SERVICE_Context *ctx; - - -/** - * Function called to notify a client about the connection - * begin ready to queue more data. "buf" will be - * NULL and "size" zero if the connection was closed for - * writing in the meantime. - * - * @param cls client context - * @param size number of bytes available in buf - * @param buf where the callee should write the message - * @return number of bytes written to buf - */ -static size_t -transmit_ready_cb (void *cls, size_t size, void *buf) -{ - struct ClientCtx *ctx = cls; - struct GNUNET_SERVER_Client *client = ctx->client; - struct MessageQueue *mq; - struct GNUNET_MessageHeader *msg; - size_t wrote; - - ctx->tx = NULL; - if ((0 == size) || (NULL == buf)) - { - GNUNET_assert (NULL != ctx->client); - GNUNET_SERVER_client_drop (ctx->client); - ctx->client = NULL; - return 0; - } - mq = ctx->mq_head; - msg = mq->msg; - wrote = ntohs (msg->size); - GNUNET_assert (size >= wrote); - GNUNET_memcpy (buf, msg, wrote); - GNUNET_CONTAINER_DLL_remove (ctx->mq_head, ctx->mq_tail, mq); - GNUNET_free (mq->msg); - GNUNET_free (mq); - if (NULL != (mq = ctx->mq_head)) - ctx->tx = GNUNET_SERVER_notify_transmit_ready (client, ntohs (msg->size), - MESSAGE_SEND_TIMEOUT (30), - &transmit_ready_cb, ctx); - return wrote; -} - - -/** - * Queue a message into a clients message queue - * - * @param ctx the context associated with the client - * @param msg the message to queue. Will be consumed - */ -static void -queue_message (struct ClientCtx *ctx, struct GNUNET_MessageHeader *msg) -{ - struct MessageQueue *mq; - struct GNUNET_SERVER_Client *client = ctx->client; - - mq = GNUNET_new (struct MessageQueue); - mq->msg = msg; - LOG_DEBUG ("Queueing message of type %u, size %u for sending\n", - ntohs (msg->type), ntohs (msg->size)); - GNUNET_CONTAINER_DLL_insert_tail (ctx->mq_head, ctx->mq_tail, mq); - if (NULL == ctx->tx) - ctx->tx = GNUNET_SERVER_notify_transmit_ready (client, ntohs (msg->size), - MESSAGE_SEND_TIMEOUT (30), - &transmit_ready_cb, ctx); -} - - -/** - * Function to cleanup client context data structure - * - * @param ctx the client context data structure - */ -static void -cleanup_clientctx (struct ClientCtx *ctx) -{ - struct MessageQueue *mq; - - if (NULL != ctx->client) - { - GNUNET_SERVER_client_set_user_context_ (ctx->client, NULL, 0); - GNUNET_SERVER_client_drop (ctx->client); - } - if (NULL != ctx->tx) - GNUNET_SERVER_notify_transmit_ready_cancel (ctx->tx); - if (NULL != (mq = ctx->mq_head)) - { - GNUNET_CONTAINER_DLL_remove (ctx->mq_head, ctx->mq_tail, mq); - GNUNET_free (mq->msg); - GNUNET_free (mq); - } - GNUNET_free (ctx); -} +static struct GNUNET_SERVICE_Handle *ctx; /** @@ -356,16 +225,18 @@ remove_barrier (struct Barrier *barrier) { struct ClientCtx *ctx; - GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (barrier_map, - &barrier->hash, - barrier)); + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multihashmap_remove (barrier_map, + &barrier->hash, + barrier)); while (NULL != (ctx = barrier->head)) { - GNUNET_CONTAINER_DLL_remove (barrier->head, barrier->tail, ctx); - cleanup_clientctx (ctx); + GNUNET_CONTAINER_DLL_remove (barrier->head, + barrier->tail, + ctx); + GNUNET_free (ctx); } GNUNET_free (barrier->name); - GNUNET_SERVER_client_drop (barrier->mc); GNUNET_free (barrier); } @@ -383,7 +254,9 @@ cancel_wrappers (struct Barrier *barrier) while (NULL != (wrapper = barrier->whead)) { GNUNET_TESTBED_barrier_cancel (wrapper->hbarrier); - GNUNET_CONTAINER_DLL_remove (barrier->whead, barrier->wtail, wrapper); + GNUNET_CONTAINER_DLL_remove (barrier->whead, + barrier->wtail, + wrapper); GNUNET_free (wrapper); } } @@ -399,29 +272,33 @@ cancel_wrappers (struct Barrier *barrier) * status=GNUNET_TESTBED_BARRIERSTATUS_ERROR */ static void -send_client_status_msg (struct GNUNET_SERVER_Client *client, +send_client_status_msg (struct GNUNET_SERVICE_Client *client, const char *name, enum GNUNET_TESTBED_BarrierStatus status, const char *emsg) { + struct GNUNET_MQ_Envelope *env; struct GNUNET_TESTBED_BarrierStatusMsg *msg; size_t name_len; - uint16_t msize; - - GNUNET_assert ((NULL == emsg) || (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status)); - name_len = strlen (name); - msize = sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) - + (name_len + 1) - + ((NULL == emsg) ? 0 : (strlen (emsg) + 1)); - msg = GNUNET_malloc (msize); - msg->header.size = htons (msize); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS); + size_t err_len; + + GNUNET_assert ( (NULL == emsg) || + (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status) ); + name_len = strlen (name) + 1; + err_len = ((NULL == emsg) ? 0 : (strlen (emsg) + 1)); + env = GNUNET_MQ_msg_extra (msg, + name_len + err_len, + GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS); msg->status = htons (status); - msg->name_len = htons ((uint16_t) name_len); - GNUNET_memcpy (msg->data, name, name_len); - if (NULL != emsg) - GNUNET_memcpy (msg->data + name_len + 1, emsg, strlen (emsg)); - GST_queue_message (client, &msg->header); + msg->name_len = htons ((uint16_t) name_len - 1); + GNUNET_memcpy (msg->data, + name, + name_len); + GNUNET_memcpy (msg->data + name_len, + emsg, + err_len); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); } @@ -433,82 +310,119 @@ send_client_status_msg (struct GNUNET_SERVER_Client *client, * status=GNUNET_TESTBED_BARRIERSTATUS_ERROR */ static void -send_barrier_status_msg (struct Barrier *barrier, const char *emsg) +send_barrier_status_msg (struct Barrier *barrier, + const char *emsg) { GNUNET_assert (0 != barrier->status); - send_client_status_msg (barrier->mc, barrier->name, barrier->status, emsg); + send_client_status_msg (barrier->mc, + barrier->name, + barrier->status, + emsg); } /** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT messages. This + * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT messages. + * + * @param cls identification of the client + * @param message the actual message + */ +static int +check_barrier_wait (void *cls, + const struct GNUNET_TESTBED_BarrierWait *msg) +{ + return GNUNET_OK; /* always well-formed */ +} + + +/** + * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT messages. This * message should come from peers or a shared helper service using the * testbed-barrier client API (@see gnunet_testbed_barrier_service.h) * * This handler is queued in the main service and will handle the messages sent * either from the testbed driver or from a high level controller * - * @param cls NULL - * @param client identification of the client + * @param cls identification of the client * @param message the actual message */ static void -handle_barrier_wait (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_barrier_wait (void *cls, + const struct GNUNET_TESTBED_BarrierWait *msg) { - const struct GNUNET_TESTBED_BarrierWait *msg; + struct ClientCtx *client_ctx = cls; struct Barrier *barrier; char *name; - struct ClientCtx *client_ctx; struct GNUNET_HashCode key; size_t name_len; uint16_t msize; - msize = ntohs (message->size); - if (msize <= sizeof (struct GNUNET_TESTBED_BarrierWait)) - { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } + msize = ntohs (msg->header.size); if (NULL == barrier_map) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client_ctx->client); return; } - msg = (const struct GNUNET_TESTBED_BarrierWait *) message; name_len = msize - sizeof (struct GNUNET_TESTBED_BarrierWait); name = GNUNET_malloc (name_len + 1); name[name_len] = '\0'; - GNUNET_memcpy (name, msg->name, name_len); - LOG_DEBUG ("Received BARRIER_WAIT for barrier `%s'\n", name); - GNUNET_CRYPTO_hash (name, name_len, &key); + GNUNET_memcpy (name, + msg->name, + name_len); + LOG_DEBUG ("Received BARRIER_WAIT for barrier `%s'\n", + name); + GNUNET_CRYPTO_hash (name, + name_len, + &key); GNUNET_free (name); if (NULL == (barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, &key))) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client_ctx->client); return; } - client_ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientCtx); - if (NULL == client_ctx) + if (NULL != client_ctx->barrier) { - client_ctx = GNUNET_new (struct ClientCtx); - client_ctx->client = client; - GNUNET_SERVER_client_keep (client); - client_ctx->barrier = barrier; - GNUNET_CONTAINER_DLL_insert_tail (barrier->head, barrier->tail, client_ctx); - GNUNET_SERVER_client_set_user_context (client, client_ctx); + GNUNET_break (0); + GNUNET_SERVICE_client_drop (client_ctx->client); + return; } + client_ctx->barrier = barrier; + GNUNET_CONTAINER_DLL_insert_tail (barrier->head, + barrier->tail, + client_ctx); barrier->nreached++; - if ((barrier->num_wbarriers_reached == barrier->num_wbarriers) - && (LOCAL_QUORUM_REACHED (barrier))) + if ( (barrier->num_wbarriers_reached == barrier->num_wbarriers) && + (LOCAL_QUORUM_REACHED (barrier)) ) { barrier->status = GNUNET_TESTBED_BARRIERSTATUS_CROSSED; - send_barrier_status_msg (barrier, NULL); + send_barrier_status_msg (barrier, + NULL); } - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client_ctx->client); +} + + +/** + * Function called when a client connects to the testbed-barrier service. + * + * @param cls NULL + * @param client the connecting client + * @param mq queue to talk to @a client + * @return our `struct ClientCtx` + */ +static void * +connect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + struct GNUNET_MQ_Handle *mq) +{ + struct ClientCtx *client_ctx; + + LOG_DEBUG ("Client connected to testbed-barrier service\n"); + client_ctx = GNUNET_new (struct ClientCtx); + client_ctx->client = client; + return client_ctx; } @@ -521,16 +435,22 @@ handle_barrier_wait (void *cls, struct GNUNET_SERVER_Client *client, * for the last call when the server is destroyed */ static void -disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client) +disconnect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + void *app_ctx) { - struct ClientCtx *client_ctx; + struct ClientCtx *client_ctx = app_ctx; + struct Barrier *barrier = client_ctx->barrier; - if (NULL == client) - return; - client_ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientCtx); - if (NULL == client_ctx) - return; - cleanup_clientctx (client_ctx); + if (NULL != barrier) + { + GNUNET_CONTAINER_DLL_remove (barrier->head, + barrier->tail, + client_ctx); + client_ctx->barrier = NULL; + } + GNUNET_free (client_ctx); + LOG_DEBUG ("Client disconnected from testbed-barrier service\n"); } @@ -542,18 +462,23 @@ disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client) void GST_barriers_init (struct GNUNET_CONFIGURATION_Handle *cfg) { - static const struct GNUNET_SERVER_MessageHandler message_handlers[] = { - {&handle_barrier_wait, NULL, GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT, 0}, - {NULL, NULL, 0, 0} + struct GNUNET_MQ_MessageHandler message_handlers[] = { + GNUNET_MQ_hd_var_size (barrier_wait, + GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT, + struct GNUNET_TESTBED_BarrierWait, + NULL), + GNUNET_MQ_handler_end () }; - struct GNUNET_SERVER_Handle *srv; - - barrier_map = GNUNET_CONTAINER_multihashmap_create (3, GNUNET_YES); - ctx = GNUNET_SERVICE_start ("testbed-barrier", cfg, - GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN); - srv = GNUNET_SERVICE_get_server (ctx); - GNUNET_SERVER_add_handlers (srv, message_handlers); - GNUNET_SERVER_disconnect_notify (srv, &disconnect_cb, NULL); + + LOG_DEBUG ("Launching testbed-barrier service\n"); + barrier_map = GNUNET_CONTAINER_multihashmap_create (3, + GNUNET_YES); + ctx = GNUNET_SERVICE_starT ("testbed-barrier", + cfg, + &connect_cb, + &disconnect_cb, + NULL, + message_handlers); } @@ -594,7 +519,7 @@ GST_barriers_destroy () NULL)); GNUNET_CONTAINER_multihashmap_destroy (barrier_map); GNUNET_assert (NULL != ctx); - GNUNET_SERVICE_stop (ctx); + GNUNET_SERVICE_stoP (ctx); } @@ -606,13 +531,14 @@ GST_barriers_destroy () * @param cls the closure given to GNUNET_TESTBED_barrier_init() * @param name the name of the barrier * @param b_ the barrier handle - * @param status status of the barrier; GNUNET_OK if the barrier is crossed; - * GNUNET_SYSERR upon error - * @param emsg if the status were to be GNUNET_SYSERR, this parameter has the + * @param status status of the barrier; #GNUNET_OK if the barrier is crossed; + * #GNUNET_SYSERR upon error + * @param emsg if the status were to be #GNUNET_SYSERR, this parameter has the * error messsage */ static void -wbarrier_status_cb (void *cls, const char *name, +wbarrier_status_cb (void *cls, + const char *name, struct GNUNET_TESTBED_Barrier *b_, enum GNUNET_TESTBED_BarrierStatus status, const char *emsg) @@ -622,14 +548,17 @@ wbarrier_status_cb (void *cls, const char *name, GNUNET_assert (b_ == wrapper->hbarrier); wrapper->hbarrier = NULL; - GNUNET_CONTAINER_DLL_remove (barrier->whead, barrier->wtail, wrapper); + GNUNET_CONTAINER_DLL_remove (barrier->whead, + barrier->wtail, + wrapper); GNUNET_free (wrapper); switch (status) { case GNUNET_TESTBED_BARRIERSTATUS_ERROR: LOG (GNUNET_ERROR_TYPE_ERROR, "Initialising barrier `%s' failed at a sub-controller: %s\n", - barrier->name, (NULL != emsg) ? emsg : "NULL"); + barrier->name, + (NULL != emsg) ? emsg : "NULL"); cancel_wrappers (barrier); if (NULL == emsg) emsg = "Initialisation failed at a sub-controller"; @@ -686,23 +615,38 @@ fwd_tout_barrier_init (void *cls) } + +/** + * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. + * + * @param cls identification of the client + * @param msg the actual message + * @return #GNUNET_OK if @a msg is well-formed + */ +int +check_barrier_init (void *cls, + const struct GNUNET_TESTBED_BarrierInit *msg) +{ + return GNUNET_OK; /* always well-formed */ +} + + /** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. This + * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. This * message should always come from a parent controller or the testbed API if we * are the root controller. * * This handler is queued in the main service and will handle the messages sent * either from the testbed driver or from a high level controller * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_barrier_init (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_barrier_init (void *cls, + const struct GNUNET_TESTBED_BarrierInit *msg) { - const struct GNUNET_TESTBED_BarrierInit *msg; + struct GNUNET_SERVICE_Client *client = cls; char *name; struct Barrier *barrier; struct Slave *slave; @@ -715,49 +659,45 @@ GST_handle_barrier_init (void *cls, struct GNUNET_SERVER_Client *client, if (NULL == GST_context) { GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } if (client != GST_context->client) { GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } - msize = ntohs (message->size); - if (msize <= sizeof (struct GNUNET_TESTBED_BarrierInit)) - { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - msg = (const struct GNUNET_TESTBED_BarrierInit *) message; + msize = ntohs (msg->header.size); name_len = (size_t) msize - sizeof (struct GNUNET_TESTBED_BarrierInit); name = GNUNET_malloc (name_len + 1); GNUNET_memcpy (name, msg->name, name_len); GNUNET_CRYPTO_hash (name, name_len, &hash); - LOG_DEBUG ("Received BARRIER_INIT for barrier `%s'\n", name); - if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (barrier_map, &hash)) + LOG_DEBUG ("Received BARRIER_INIT for barrier `%s'\n", + name); + if (GNUNET_YES == + GNUNET_CONTAINER_multihashmap_contains (barrier_map, + &hash)) { - - send_client_status_msg (client, name, GNUNET_TESTBED_BARRIERSTATUS_ERROR, + send_client_status_msg (client, + name, + GNUNET_TESTBED_BARRIERSTATUS_ERROR, "A barrier with the same name already exists"); GNUNET_free (name); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } barrier = GNUNET_new (struct Barrier); - GNUNET_memcpy (&barrier->hash, &hash, sizeof (struct GNUNET_HashCode)); + barrier->hash = hash; barrier->quorum = msg->quorum; barrier->name = name; barrier->mc = client; - GNUNET_SERVER_client_keep (client); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (barrier_map, &barrier->hash, barrier, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); /* Propagate barrier init to subcontrollers */ for (cnt = 0; cnt < GST_slave_list_size; cnt++) { @@ -770,7 +710,9 @@ GST_handle_barrier_init (void *cls, struct GNUNET_SERVER_Client *client, } wrapper = GNUNET_new (struct WBarrier); wrapper->barrier = barrier; - GNUNET_CONTAINER_DLL_insert_tail (barrier->whead, barrier->wtail, wrapper); + GNUNET_CONTAINER_DLL_insert_tail (barrier->whead, + barrier->wtail, + wrapper); wrapper->hbarrier = GNUNET_TESTBED_barrier_init_ (slave->controller, barrier->name, barrier->quorum, @@ -792,22 +734,36 @@ GST_handle_barrier_init (void *cls, struct GNUNET_SERVER_Client *client, /** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. This + * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. + * + * @param cls identification of the client + * @param msg the actual message + * @return #GNUNET_OK if @a msg is well-formed + */ +int +check_barrier_cancel (void *cls, + const struct GNUNET_TESTBED_BarrierCancel *msg) +{ + return GNUNET_OK; /* all are well-formed */ +} + + +/** + * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. This * message should always come from a parent controller or the testbed API if we * are the root controller. * * This handler is queued in the main service and will handle the messages sent * either from the testbed driver or from a high level controller * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_barrier_cancel (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_barrier_cancel (void *cls, + const struct GNUNET_TESTBED_BarrierCancel *msg) { - const struct GNUNET_TESTBED_BarrierCancel *msg; + struct GNUNET_SERVICE_Client *client = cls; char *name; struct Barrier *barrier; struct GNUNET_HashCode hash; @@ -817,119 +773,140 @@ GST_handle_barrier_cancel (void *cls, struct GNUNET_SERVER_Client *client, if (NULL == GST_context) { GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } if (client != GST_context->client) { GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } - msize = ntohs (message->size); - if (msize <= sizeof (struct GNUNET_TESTBED_BarrierCancel)) - { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - msg = (const struct GNUNET_TESTBED_BarrierCancel *) message; + msize = ntohs (msg->header.size); name_len = msize - sizeof (struct GNUNET_TESTBED_BarrierCancel); name = GNUNET_malloc (name_len + 1); - GNUNET_memcpy (name, msg->name, name_len); - GNUNET_CRYPTO_hash (name, name_len, &hash); - if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (barrier_map, &hash)) + GNUNET_memcpy (name, + msg->name, + name_len); + LOG_DEBUG ("Received BARRIER_CANCEL for barrier `%s'\n", + name); + GNUNET_CRYPTO_hash (name, + name_len, + &hash); + if (GNUNET_NO == + GNUNET_CONTAINER_multihashmap_contains (barrier_map, + &hash)) { GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } - barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, &hash); + barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, + &hash); GNUNET_assert (NULL != barrier); cancel_wrappers (barrier); remove_barrier (barrier); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); } /** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. + * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. + * + * @param cls identification of the client + * @param msg the actual message + * @return #GNUNET_OK if @a msg is well-formed + */ +int +check_barrier_status (void *cls, + const struct GNUNET_TESTBED_BarrierStatusMsg *msg) +{ + uint16_t msize; + uint16_t name_len; + const char *name; + enum GNUNET_TESTBED_BarrierStatus status; + + msize = ntohs (msg->header.size) - sizeof (*msg); + status = ntohs (msg->status); + if (GNUNET_TESTBED_BARRIERSTATUS_CROSSED != status) + { + GNUNET_break_op (0); /* current we only expect BARRIER_CROSSED + status message this way */ + return GNUNET_SYSERR; + } + name = msg->data; + name_len = ntohs (msg->name_len); + if ((name_len + 1) != msize) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if ('\0' != name[name_len]) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. * This handler is queued in the main service and will handle the messages sent * either from the testbed driver or from a high level controller * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_barrier_status (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_barrier_status (void *cls, + const struct GNUNET_TESTBED_BarrierStatusMsg *msg) { - const struct GNUNET_TESTBED_BarrierStatusMsg *msg; + struct GNUNET_SERVICE_Client *client = cls; struct Barrier *barrier; struct ClientCtx *client_ctx; const char *name; struct GNUNET_HashCode key; - enum GNUNET_TESTBED_BarrierStatus status; - uint16_t msize; uint16_t name_len; + struct GNUNET_MQ_Envelope *env; if (NULL == GST_context) { GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } if (client != GST_context->client) { GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - msize = ntohs (message->size); - if (msize <= sizeof (struct GNUNET_TESTBED_BarrierStatusMsg)) - { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - msg = (const struct GNUNET_TESTBED_BarrierStatusMsg *) message; - status = ntohs (msg->status); - if (GNUNET_TESTBED_BARRIERSTATUS_CROSSED != status) - { - GNUNET_break_op (0); /* current we only expect BARRIER_CROSSED - status message this way */ - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } name = msg->data; name_len = ntohs (msg->name_len); - if ((sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) + name_len + 1) != msize) - { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - if ('\0' != name[name_len]) - { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - GNUNET_CRYPTO_hash (name, name_len, &key); - barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, &key); + LOG_DEBUG ("Received BARRIER_STATUS for barrier `%s'\n", + name); + GNUNET_CRYPTO_hash (name, + name_len, + &key); + barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, + &key); if (NULL == barrier) { GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); while (NULL != (client_ctx = barrier->head)) /* Notify peers */ { - queue_message (client_ctx, GNUNET_copy_message (message)); - GNUNET_CONTAINER_DLL_remove (barrier->head, barrier->tail, client_ctx); + env = GNUNET_MQ_msg_copy (&msg->header); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); + GNUNET_CONTAINER_DLL_remove (barrier->head, + barrier->tail, + client_ctx); + client_ctx->barrier = NULL; } } diff --git a/src/testbed/gnunet-service-testbed_barriers.h b/src/testbed/gnunet-service-testbed_barriers.h index ed5ba309b..2fc3222f8 100644 --- a/src/testbed/gnunet-service-testbed_barriers.h +++ b/src/testbed/gnunet-service-testbed_barriers.h @@ -40,55 +40,88 @@ GST_barriers_init (struct GNUNET_CONFIGURATION_Handle *cfg); * Function to stop the barrier service */ void -GST_barriers_destroy (); +GST_barriers_destroy (void); /** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. This + * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. + * + * @param cls identification of the client + * @param msg the actual message + * @return #GNUNET_OK if @a msg is well-formed + */ +int +check_barrier_init (void *cls, + const struct GNUNET_TESTBED_BarrierInit *msg); + + +/** + * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. This * message should always come from a parent controller or the testbed API if we * are the root controller. * * This handler is queued in the main service and will handle the messages sent * either from the testbed driver or from a high level controller * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_barrier_init (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message); +handle_barrier_init (void *cls, + const struct GNUNET_TESTBED_BarrierInit *msg); /** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. This + * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. + * + * @param cls identification of the client + * @param msg the actual message + * @return #GNUNET_OK if @a msg is well-formed + */ +int +check_barrier_cancel (void *cls, + const struct GNUNET_TESTBED_BarrierCancel *msg); + + +/** + * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. This * message should always come from a parent controller or the testbed API if we * are the root controller. * * This handler is queued in the main service and will handle the messages sent * either from the testbed driver or from a high level controller * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_barrier_cancel (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message); +handle_barrier_cancel (void *cls, + const struct GNUNET_TESTBED_BarrierCancel *msg); + + +/** + * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. + * + * @param cls identification of the client + * @param msg the actual message + * @return #GNUNET_OK if @a msg is well-formed + */ +int +check_barrier_status (void *cls, + const struct GNUNET_TESTBED_BarrierStatusMsg *msg); /** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. + * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. * This handler is queued in the main service and will handle the messages sent * either from the testbed driver or from a high level controller * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_barrier_status (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message); +handle_barrier_status (void *cls, + const struct GNUNET_TESTBED_BarrierStatusMsg *msg); #endif /* GNUNET_SERVER_TESTBED_BARRIERS_H_ */ diff --git a/src/testbed/gnunet-service-testbed_links.c b/src/testbed/gnunet-service-testbed_links.c index b922a8da8..3447a3f34 100644 --- a/src/testbed/gnunet-service-testbed_links.c +++ b/src/testbed/gnunet-service-testbed_links.c @@ -74,6 +74,16 @@ enum LCFContextState */ struct LCFContext { + /** + * The LCFContext + */ + struct LCFContext *next; + + /** + * The LCFContext + */ + struct LCFContext *prev; + /** * The gateway which will pass the link message to delegated host */ @@ -82,7 +92,7 @@ struct LCFContext /** * The client which has asked to perform this operation */ - struct GNUNET_SERVER_Client *client; + struct GNUNET_SERVICE_Client *client; /** * Handle for operations which are forwarded while linking controllers @@ -92,7 +102,7 @@ struct LCFContext /** * The timeout task */ - struct GNUNET_SCHEDULER_Task * timeout_task; + struct GNUNET_SCHEDULER_Task *timeout_task; /** * The id of the operation which created this context @@ -122,28 +132,6 @@ struct LCFContext }; -/** - * Structure of a queue entry in LCFContext request queue - */ -struct LCFContextQueue -{ - /** - * The LCFContext - */ - struct LCFContext *lcf; - - /** - * Head prt for DLL - */ - struct LCFContextQueue *next; - - /** - * Tail ptr for DLL - */ - struct LCFContextQueue *prev; -}; - - /** * Notification context to be used to notify when connection to the neighbour's * controller is opened @@ -260,12 +248,12 @@ struct NeighbourConnectCtxt /** * The client requesting the connection */ - struct GNUNET_SERVER_Client *client; + struct GNUNET_SERVICE_Client *client; /** * Task to be run upon timeout */ - struct GNUNET_SCHEDULER_Task * timeout_task; + struct GNUNET_SCHEDULER_Task *timeout_task; /** * The notification handle associated with the neighbour's connection request @@ -305,14 +293,14 @@ unsigned int GST_slave_list_size; static struct Route **route_list; /** - * The head for the LCF queue + * The LCF queue */ -static struct LCFContextQueue *lcfq_head; +static struct LCFContext *lcf_head; /** * The tail for the LCF queue */ -static struct LCFContextQueue *lcfq_tail; +static struct LCFContext *lcf_tail; /** * The lcf_task handle @@ -334,13 +322,43 @@ static void slave_list_add (struct Slave *slave) { if (slave->host_id >= GST_slave_list_size) - GST_array_grow_large_enough (GST_slave_list, GST_slave_list_size, + GST_array_grow_large_enough (GST_slave_list, + GST_slave_list_size, slave->host_id); GNUNET_assert (NULL == GST_slave_list[slave->host_id]); GST_slave_list[slave->host_id] = slave; } +/** + * Clean up all forwarded operation overlay context matching the + * client given in @a cls. + * + * @param cls a `struct GNUNET_SERVICE_Client *` to match + * @param key unused + * @param value the `struct RegisteredHostContext` to search for @a cls + * @return #GNUNET_OK (continue iterating) + */ +static int +drop_client_entries (void *cls, + const struct GNUNET_HashCode *key, + void *value) +{ + struct GNUNET_SERVICE_Client *client = cls; + struct RegisteredHostContext *rhc = value; + struct ForwardedOverlayConnectContext *focc; + struct ForwardedOverlayConnectContext *foccn; + + for (focc = rhc->focc_dll_head; NULL != focc; focc = foccn) + { + foccn = focc->next; + if (focc->client == client) + GST_cleanup_focc (focc); + } + return GNUNET_OK; +} + + /** * Adds a route to the route list * @@ -394,12 +412,12 @@ GST_route_list_clear () * @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. + * @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, +reghost_free_iterator (void *cls, + const struct GNUNET_HashCode *key, void *value) { struct Slave *slave = cls; @@ -410,10 +428,7 @@ reghost_free_iterator (void *cls, const struct GNUNET_HashCode *key, GNUNET_CONTAINER_multihashmap_remove (slave->reghost_map, key, value)); while (NULL != (focc = rhc->focc_dll_head)) - { - GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc); GST_cleanup_focc (focc); - } GNUNET_free (value); return GNUNET_YES; } @@ -536,12 +551,12 @@ GST_find_dest_route (uint32_t host_id) * NULL if cfg is set! */ static void -send_controller_link_response (struct GNUNET_SERVER_Client *client, +send_controller_link_response (struct GNUNET_SERVICE_Client *client, uint64_t operation_id, - const struct GNUNET_CONFIGURATION_Handle - *cfg, + const struct GNUNET_CONFIGURATION_Handle *cfg, const char *emsg) { + struct GNUNET_MQ_Envelope *env; struct GNUNET_TESTBED_ControllerLinkResponse *msg; char *xconfig; size_t config_size; @@ -552,7 +567,7 @@ send_controller_link_response (struct GNUNET_SERVER_Client *client, xconfig = NULL; xconfig_size = 0; config_size = 0; - msize = sizeof (struct GNUNET_TESTBED_ControllerLinkResponse); + msize = 0; if (NULL != cfg) { xconfig = GNUNET_TESTBED_compress_cfg_ (cfg, @@ -562,22 +577,26 @@ send_controller_link_response (struct GNUNET_SERVER_Client *client, } if (NULL != emsg) msize += strlen (emsg); - msg = GNUNET_malloc (msize); - msg->header.type = htons - (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT); - msg->header.size = htons (msize); + env = GNUNET_MQ_msg_extra (msg, + msize, + GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT); if (NULL == emsg) msg->success = htons (GNUNET_YES); msg->operation_id = GNUNET_htonll (operation_id); msg->config_size = htons ((uint16_t) config_size); if (NULL != xconfig) { - GNUNET_memcpy (&msg[1], xconfig, xconfig_size); + GNUNET_memcpy (&msg[1], + xconfig, + xconfig_size); GNUNET_free (xconfig); } if (NULL != emsg) - GNUNET_memcpy (&msg[1], emsg, strlen (emsg)); - GST_queue_message (client, &msg->header); + GNUNET_memcpy (&msg[1], + emsg, + strlen (emsg)); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); } @@ -597,7 +616,8 @@ lcf_proc_task (void *cls); * @param emsg the error message; NULL if host registration is successful */ static void -lcf_proc_cc (void *cls, const char *emsg) +lcf_proc_cc (void *cls, + const char *emsg) { struct LCFContext *lcf = cls; @@ -622,10 +642,12 @@ lcf_proc_cc (void *cls, const char *emsg) return; registration_error: - LOG (GNUNET_ERROR_TYPE_WARNING, "Host registration failed with message: %s\n", + 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); + lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, + lcf); } @@ -652,11 +674,13 @@ lcf_forwarded_operation_timeout (void *cls) // GST_forwarded_operation_timeout (lcf->fopc, tc); LOG (GNUNET_ERROR_TYPE_WARNING, "A forwarded controller link operation has timed out\n"); - send_controller_link_response (lcf->client, lcf->operation_id, NULL, - "A forwarded controller link operation has " - "timed out\n"); + send_controller_link_response (lcf->client, + lcf->operation_id, + NULL, + "A forwarded controller link operation has timed out\n"); GNUNET_assert (NULL == lcf_proc_task_id); - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); + lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, + lcf); } @@ -669,7 +693,6 @@ static void lcf_proc_task (void *cls) { struct LCFContext *lcf = cls; - struct LCFContextQueue *lcfq; lcf_proc_task_id = NULL; switch (lcf->state) @@ -710,22 +733,21 @@ lcf_proc_task (void *cls) GST_host_list[lcf->slave_host_id], lcf->is_subordinate); lcf->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, &lcf_forwarded_operation_timeout, + GNUNET_SCHEDULER_add_delayed (GST_timeout, + &lcf_forwarded_operation_timeout, lcf); lcf->state = FINISHED; break; case FINISHED: - lcfq = lcfq_head; - GNUNET_assert (lcfq->lcf == lcf); - GNUNET_SERVER_client_drop (lcf->client); if (NULL != lcf->op) GNUNET_TESTBED_operation_done (lcf->op); + GNUNET_CONTAINER_DLL_remove (lcf_head, + lcf_tail, + lcf); 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); + if (NULL != lcf_head) + lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, + lcf_head); } } @@ -770,12 +792,13 @@ slave_event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) * * @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, + * NULL if status is not #GNUNET_OK + * @param status #GNUNET_OK if the startup is successfull; #GNUNET_SYSERR if not, * GNUNET_TESTBED_controller_stop() shouldn't be called in this case */ static void -slave_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, +slave_status_cb (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg, int status) { struct Slave *slave = cls; @@ -789,7 +812,7 @@ slave_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, and as these tasks they depend on the operation queues which are created through GNUNET_TESTBED_controller_connect() and in kill_slave() we call the destructor function GNUNET_TESTBED_controller_disconnect() */ - GST_free_lcfq (); + GST_free_lcf (); kill_slave (slave); destroy_slave (slave); slave = NULL; @@ -819,8 +842,7 @@ slave_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, { if (NULL != lcc->client) { - GNUNET_SERVER_receive_done (lcc->client, GNUNET_OK); - GNUNET_SERVER_client_drop (lcc->client); + GNUNET_SERVICE_client_continue (lcc->client); lcc->client = NULL; } GNUNET_free (lcc); @@ -1051,8 +1073,9 @@ cleanup_ncc (struct NeighbourConnectCtxt *ncc) GST_neighbour_get_connection_cancel (ncc->nh); if (NULL != ncc->timeout_task) GNUNET_SCHEDULER_cancel (ncc->timeout_task); - GNUNET_SERVER_client_drop (ncc->client); - GNUNET_CONTAINER_DLL_remove (ncc_head, ncc_tail, ncc); + GNUNET_CONTAINER_DLL_remove (ncc_head, + ncc_tail, + ncc); GNUNET_free (ncc); } @@ -1061,7 +1084,7 @@ cleanup_ncc (struct NeighbourConnectCtxt *ncc) * Cleans up the neighbour list */ void -GST_neighbour_list_clean() +GST_neighbour_list_clean () { struct Neighbour *n; unsigned int id; @@ -1091,8 +1114,7 @@ GST_get_neighbour (uint32_t id) { if (neighbour_list_size <= id) return NULL; - else - return neighbour_list[id]; + return neighbour_list[id]; } @@ -1118,7 +1140,9 @@ timeout_neighbour_connect (void *cls) struct NeighbourConnectCtxt *ncc = cls; ncc->timeout_task = NULL; - send_controller_link_response (ncc->client, ncc->op_id, NULL, + send_controller_link_response (ncc->client, + ncc->op_id, + NULL, "Could not connect to delegated controller"); cleanup_ncc (ncc); } @@ -1131,7 +1155,8 @@ timeout_neighbour_connect (void *cls) * @param c the handle the neighbour's controller */ static void -neighbour_connect_cb (void *cls, struct GNUNET_TESTBED_Controller *c) +neighbour_connect_cb (void *cls, + struct GNUNET_TESTBED_Controller *c) { struct NeighbourConnectCtxt *ncc = cls; @@ -1139,7 +1164,10 @@ neighbour_connect_cb (void *cls, struct GNUNET_TESTBED_Controller *c) ncc->timeout_task = NULL; ncc->nh = NULL; GST_neighbour_release_connection (ncc->n); - send_controller_link_response (ncc->client, ncc->op_id, NULL, NULL); + send_controller_link_response (ncc->client, + ncc->op_id, + NULL, + NULL); cleanup_ncc (ncc); } @@ -1162,18 +1190,17 @@ GST_create_neighbour (struct GNUNET_TESTBED_Host *host) /** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message + * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_link_controllers (void *cls, + const struct GNUNET_TESTBED_ControllerLinkRequest *msg) { - const struct GNUNET_TESTBED_ControllerLinkRequest *msg; - struct LCFContextQueue *lcfq; + struct GNUNET_SERVICE_Client *client = cls; + struct LCFContext *lcf; struct Route *route; struct Route *new_route; uint64_t op_id; @@ -1183,39 +1210,42 @@ GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client, if (NULL == GST_context) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } - msg = (const struct GNUNET_TESTBED_ControllerLinkRequest *) message; delegated_host_id = ntohl (msg->delegated_host_id); if (delegated_host_id == GST_context->host_id) { GNUNET_break (0); - LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n"); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + LOG (GNUNET_ERROR_TYPE_WARNING, + "Trying to link ourselves\n"); + GNUNET_SERVICE_client_drop (client); return; } if ((delegated_host_id >= GST_host_list_size) || (NULL == GST_host_list[delegated_host_id])) { LOG (GNUNET_ERROR_TYPE_WARNING, - "Delegated host %u not registered with us\n", delegated_host_id); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + "Delegated host %u not registered with us\n", + delegated_host_id); + GNUNET_SERVICE_client_drop (client); return; } slave_host_id = ntohl (msg->slave_host_id); if ((slave_host_id >= GST_host_list_size) || (NULL == GST_host_list[slave_host_id])) { - LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host %u not registered with us\n", + LOG (GNUNET_ERROR_TYPE_WARNING, + "Slave host %u not registered with us\n", slave_host_id); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } if (slave_host_id == delegated_host_id) { - LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n"); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + LOG (GNUNET_ERROR_TYPE_WARNING, + "Slave and delegated host are same\n"); + GNUNET_SERVICE_client_drop (client); return; } op_id = GNUNET_ntohll (msg->operation_id); @@ -1224,7 +1254,6 @@ GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client, struct Slave *slave; struct LinkControllersContext *lcc; - if (1 != msg->is_subordinate) { struct Neighbour *n; @@ -1234,7 +1263,7 @@ GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client, (NULL != neighbour_list[delegated_host_id])) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } LOG_DEBUG ("Received request to establish a link to host %u\n", @@ -1244,37 +1273,42 @@ GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client, ncc->n = n; ncc->op_id = op_id; ncc->client = client; - GNUNET_SERVER_client_keep (client); - ncc->nh = GST_neighbour_get_connection (n, neighbour_connect_cb, ncc); - ncc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, - &timeout_neighbour_connect, - ncc); - GNUNET_CONTAINER_DLL_insert_tail (ncc_head, ncc_tail, ncc); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + ncc->nh = GST_neighbour_get_connection (n, + &neighbour_connect_cb, + ncc); + ncc->timeout_task + = GNUNET_SCHEDULER_add_delayed (GST_timeout, + &timeout_neighbour_connect, + ncc); + GNUNET_CONTAINER_DLL_insert_tail (ncc_head, + ncc_tail, + ncc); + GNUNET_SERVICE_client_continue (client); return; } - if ((delegated_host_id < GST_slave_list_size) && - (NULL != GST_slave_list[delegated_host_id])) + if ( (delegated_host_id < GST_slave_list_size) && + (NULL != GST_slave_list[delegated_host_id]) ) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } LOG_DEBUG ("Received request to start and establish a link to host %u\n", delegated_host_id); slave = GNUNET_new (struct Slave); slave->host_id = delegated_host_id; - slave->reghost_map = GNUNET_CONTAINER_multihashmap_create (100, GNUNET_NO); + slave->reghost_map = GNUNET_CONTAINER_multihashmap_create (100, + GNUNET_NO); slave_list_add (slave); lcc = GNUNET_new (struct LinkControllersContext); lcc->operation_id = op_id; - GNUNET_SERVER_client_keep (client); lcc->client = client; slave->lcc = lcc; - slave->controller_proc = - GNUNET_TESTBED_controller_start (GST_context->master_ip, + slave->controller_proc + = GNUNET_TESTBED_controller_start (GST_context->master_ip, GST_host_list[slave->host_id], - &slave_status_cb, slave); + &slave_status_cb, + slave); new_route = GNUNET_new (struct Route); new_route->dest = delegated_host_id; new_route->thru = GST_context->host_id; @@ -1285,52 +1319,114 @@ GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client, /* Route the request */ if (slave_host_id >= route_list_size) { - LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host"); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + LOG (GNUNET_ERROR_TYPE_WARNING, + "No route towards slave host"); + GNUNET_SERVICE_client_drop (client); return; } - lcfq = GNUNET_new (struct LCFContextQueue); - lcfq->lcf = GNUNET_new (struct LCFContext); - lcfq->lcf->delegated_host_id = delegated_host_id; - lcfq->lcf->slave_host_id = slave_host_id; + lcf = GNUNET_new (struct LCFContext); + lcf->delegated_host_id = delegated_host_id; + lcf->slave_host_id = slave_host_id; route = GST_find_dest_route (slave_host_id); GNUNET_assert (NULL != route); /* because we add routes carefully */ GNUNET_assert (route->dest < GST_slave_list_size); GNUNET_assert (NULL != GST_slave_list[route->dest]); - lcfq->lcf->is_subordinate = msg->is_subordinate; - lcfq->lcf->state = INIT; - lcfq->lcf->operation_id = op_id; - lcfq->lcf->gateway = GST_slave_list[route->dest]; - GNUNET_SERVER_client_keep (client); - lcfq->lcf->client = client; - if (NULL == lcfq_head) + lcf->is_subordinate = msg->is_subordinate; + lcf->state = INIT; + lcf->operation_id = op_id; + lcf->gateway = GST_slave_list[route->dest]; + lcf->client = client; + if (NULL == lcf_head) { GNUNET_assert (NULL == 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); + GNUNET_CONTAINER_DLL_insert_tail (lcf_head, + lcf_tail, + lcf); + lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, + lcf); } else - GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq); + { + GNUNET_CONTAINER_DLL_insert_tail (lcf_head, + lcf_tail, + lcf); + } /* 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); + GNUNET_SERVICE_client_continue (client); return; } - if ((delegated_host_id < route_list_size) && - (NULL != route_list[delegated_host_id])) + if ( (delegated_host_id < route_list_size) && + (NULL != route_list[delegated_host_id]) ) { GNUNET_break_op (0); /* Are you trying to link delegated host twice * with is subordinate flag set to GNUNET_YES? */ - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } new_route = GNUNET_new (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); + GNUNET_SERVICE_client_continue (client); +} + + +/** + * Clean up @a client handle if we stored any via #handle_link_controllers(), + * the given client disconnected. + * + * @param client the client that is history + */ +void +GST_link_notify_disconnect (struct GNUNET_SERVICE_Client *client) +{ + struct NeighbourConnectCtxt *ncc; + struct NeighbourConnectCtxt *nccn; + struct LCFContext *lcf; + struct LCFContext *lcfn; + + for (ncc = ncc_head; NULL != ncc; ncc = nccn) + { + nccn = ncc->next; + if (ncc->client == client) + cleanup_ncc (ncc); + } + for (unsigned int i=0;ireghost_map, + &drop_client_entries, + client); + lcc = slave->lcc; + if (NULL == lcc) + continue; + if (lcc->client == client) + { + slave->lcc = NULL; + GNUNET_free (lcc); + } + } + for (lcf = lcf_head; NULL != lcf; lcf = lcfn) + { + lcfn = lcf->next; + if ( (NULL != lcf) && + (client == lcf->client) ) + { + if (NULL != lcf->op) + GNUNET_TESTBED_operation_done (lcf->op); + GNUNET_CONTAINER_DLL_remove (lcf_head, + lcf_tail, + lcf); + GNUNET_free (lcf); + } + } } @@ -1338,12 +1434,11 @@ GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client, * Cleans up the queue used for forwarding link controllers requests */ void -GST_free_lcfq () +GST_free_lcf () { - struct LCFContextQueue *lcfq; struct LCFContext *lcf; - if (NULL != lcfq_head) + if (NULL != lcf_head) { if (NULL != lcf_proc_task_id) { @@ -1352,16 +1447,15 @@ GST_free_lcfq () } } GNUNET_assert (NULL == lcf_proc_task_id); - for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head) + for (lcf = lcf_head; NULL != lcf; lcf = lcf_head) { - lcf = lcfq->lcf; - GNUNET_SERVER_client_drop (lcf->client); if (NULL != lcf->op) GNUNET_TESTBED_operation_done (lcf->op); if (NULL != lcf->timeout_task) GNUNET_SCHEDULER_cancel (lcf->timeout_task); + GNUNET_CONTAINER_DLL_remove (lcf_head, + lcf_tail, + lcf); GNUNET_free (lcf); - GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq); - GNUNET_free (lcfq); } } diff --git a/src/testbed/gnunet-service-testbed_links.h b/src/testbed/gnunet-service-testbed_links.h index b39851ed7..09764b99a 100644 --- a/src/testbed/gnunet-service-testbed_links.h +++ b/src/testbed/gnunet-service-testbed_links.h @@ -94,7 +94,7 @@ extern unsigned int GST_slave_list_size; * Cleans up the neighbour list */ void -GST_neighbour_list_clean(); +GST_neighbour_list_clean (void); /** @@ -112,7 +112,7 @@ GST_get_neighbour (uint32_t id); * Function to cleanup the neighbour connect contexts */ void -GST_free_nccq (); +GST_free_nccq (void); /** @@ -128,10 +128,9 @@ struct NeighbourConnectNotification; * @param cls the closure given to GST_neighbour_get_connection() * @param controller the controller handle to the neighbour */ -typedef void (*GST_NeigbourConnectNotifyCallback) (void *cls, - struct - GNUNET_TESTBED_Controller - *controller); +typedef void +(*GST_NeigbourConnectNotifyCallback) (void *cls, + struct GNUNET_TESTBED_Controller *controller); /** @@ -181,19 +180,28 @@ GST_create_neighbour (struct GNUNET_TESTBED_Host *host); /** - * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message + * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message); +handle_link_controllers (void *cls, + const struct GNUNET_TESTBED_ControllerLinkRequest *msg); + + +/** + * Clean up @a client handle if we stored any via #handle_link_controllers(), + * the given client disconnected. + * + * @param client the client that is history + */ +void +GST_link_notify_disconnect (struct GNUNET_SERVICE_Client *client); /** * Cleans up the slave list */ void -GST_slave_list_clear (); +GST_slave_list_clear (void); diff --git a/src/testbed/gnunet-service-testbed_oc.c b/src/testbed/gnunet-service-testbed_oc.c index c681c3810..b775f31bd 100644 --- a/src/testbed/gnunet-service-testbed_oc.c +++ b/src/testbed/gnunet-service-testbed_oc.c @@ -168,7 +168,7 @@ struct OverlayConnectContext * The client which has requested for overlay connection. This is used to send * either a success of failure message */ - struct GNUNET_SERVER_Client *client; + struct GNUNET_SERVICE_Client *client; /** * the first peer which is to expect an overlay connection from the second peer. @@ -358,7 +358,11 @@ static struct RemoteOverlayConnectCtx *roccq_tail; void GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc) { - GNUNET_SERVER_client_drop (focc->client); + struct RegisteredHostContext *rhc = focc->rhc; + + GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, + rhc->focc_dll_tail, + focc); GNUNET_free_non_null (focc->orig_msg); GNUNET_free (focc); } @@ -376,10 +380,11 @@ forwarded_overlay_connect_timeout (void *cls) struct RegisteredHostContext *rhc; struct ForwardedOverlayConnectContext *focc; + fopc->timeout_task = NULL; rhc = fopc->cls; focc = rhc->focc_dll_head; - GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc); - LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", focc->peer1, + LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", + focc->peer1, focc->peer2); GST_cleanup_focc (focc); GST_forwarded_operation_timeout (fopc); @@ -407,7 +412,6 @@ forwarded_overlay_connect_listener (void *cls, rhc = fopc->cls; GST_forwarded_operation_reply_relay (cls, msg); focc = rhc->focc_dll_head; - GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc); GST_cleanup_focc (focc); if (NULL != rhc->focc_dll_head) GST_process_next_focc (rhc); @@ -435,22 +439,24 @@ GST_process_next_focc (struct RegisteredHostContext *rhc) GNUNET_assert (GNUNET_YES == peer->is_remote); GNUNET_assert (NULL != (slave = peer->details.remote.slave)); fopc = GNUNET_new (struct ForwardedOperationContext); - GNUNET_SERVER_client_keep (focc->client); fopc->client = focc->client; fopc->operation_id = focc->operation_id; fopc->cls = rhc; fopc->type = OP_OVERLAY_CONNECT; fopc->opc = GNUNET_TESTBED_forward_operation_msg_ (slave->controller, - focc->operation_id, focc->orig_msg, + focc->operation_id, + focc->orig_msg, &forwarded_overlay_connect_listener, fopc); GNUNET_free (focc->orig_msg); focc->orig_msg = NULL; - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, &forwarded_overlay_connect_timeout, + fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, + &forwarded_overlay_connect_timeout, + fopc); + GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, + fopcq_tail, fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); } @@ -533,7 +539,6 @@ cleanup_occ (struct OverlayConnectContext *occ) occ->op_id); GNUNET_free_non_null (occ->emsg); GNUNET_free_non_null (occ->hello); - GNUNET_SERVER_client_drop (occ->client); if (NULL != occ->send_hello_task) GNUNET_SCHEDULER_cancel (occ->send_hello_task); if (NULL != occ->cleanup_task) @@ -609,25 +614,59 @@ timeout_overlay_connect (void *cls) } +/** + * Notify OC subsystem that @a client disconnected. + * + * @param client the client that disconnected + */ +void +GST_notify_client_disconnect_oc (struct GNUNET_SERVICE_Client *client) +{ + struct ForwardedOperationContext *fopc; + struct ForwardedOperationContext *fopcn; + struct OverlayConnectContext *occ; + struct OverlayConnectContext *occn; + + for (fopc = fopcq_head; NULL != fopc; fopc = fopcn) + { + fopcn = fopc->next; + if (fopc->client == client) + { + GNUNET_SCHEDULER_cancel (fopc->timeout_task); + GST_forwarded_operation_timeout (fopc); + } + } + for (occ = occq_head; NULL != occ; occ = occn) + { + occn = occ->next; + if (occ->client == client) + cleanup_occ (occ); + } + // FIXME: implement clean up for client_keep replacements! +} + + + + /** * FIXME. */ static void send_overlay_connect_success_msg (struct OverlayConnectContext *occ) { + struct GNUNET_MQ_Envelope *env; struct GNUNET_TESTBED_ConnectionEventMessage *msg; LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n", occ->op_id); - msg = GNUNET_new (struct GNUNET_TESTBED_ConnectionEventMessage); - msg->header.size = - htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage)); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT); + env = GNUNET_MQ_msg (msg, + GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT); msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT); msg->peer1 = htonl (occ->peer->id); msg->peer2 = htonl (occ->other_peer_id); msg->operation_id = GNUNET_htonll (occ->op_id); - GST_queue_message (occ->client, &msg->header); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (occ->client), + env); } @@ -1314,7 +1353,8 @@ register_host (struct Slave *slave, rhc->state = RHC_INIT; hash = hash_hosts (rhc->reg_host, rhc->host); if ((GNUNET_NO == - GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map, &hash)) || + GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map, + &hash)) || (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map, &hash, @@ -1323,10 +1363,14 @@ register_host (struct Slave *slave, { /* create and add a new registerd host context */ /* add the focc to its queue */ - GNUNET_CONTAINER_multihashmap_put (slave->reghost_map, &hash, rhc, + GNUNET_CONTAINER_multihashmap_put (slave->reghost_map, + &hash, + rhc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - GST_queue_host_registration (slave, host_registration_comp, - rhc, rhc->reg_host); + GST_queue_host_registration (slave, + host_registration_comp, + rhc, + rhc->reg_host); } else { @@ -1352,7 +1396,7 @@ register_host (struct Slave *slave, */ static void forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg, - struct GNUNET_SERVER_Client *client) + struct GNUNET_SERVICE_Client *client) { struct ForwardedOperationContext *fopc; struct Route *route_to_peer2_host; @@ -1388,14 +1432,15 @@ forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg, { LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1, p2); focc = GNUNET_new (struct ForwardedOverlayConnectContext); + focc->rhc = rhc; focc->peer1 = p1; focc->peer2 = p2; focc->peer2_host_id = peer2_host_id; focc->orig_msg = GNUNET_copy_message (&msg->header); focc->operation_id = op_id; focc->client = client; - GNUNET_SERVER_client_keep (client); - GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head, rhc->focc_dll_tail, + GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head, + rhc->focc_dll_tail, focc); return; } @@ -1403,7 +1448,6 @@ forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg, forward: LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1, p2); fopc = GNUNET_new (struct ForwardedOperationContext); - GNUNET_SERVER_client_keep (client); fopc->client = client; fopc->operation_id = op_id; fopc->type = OP_OVERLAY_CONNECT; @@ -1450,7 +1494,8 @@ p2_controller_connect_cb (void *cls, cmsg.operation_id = GNUNET_htonll (occ->op_id); rp2c->opc = GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c, - occ->op_id, &cmsg.header, + occ->op_id, + &cmsg.header, &overlay_connect_get_config, occ); GNUNET_free_non_null (occ->emsg); @@ -1463,18 +1508,16 @@ p2_controller_connect_cb (void *cls, /** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages + * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT messages * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_overlay_connect (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_overlay_connect (void *cls, + const struct GNUNET_TESTBED_OverlayConnectMessage *msg) { - const struct GNUNET_TESTBED_OverlayConnectMessage *msg; + struct GNUNET_SERVICE_Client *client = cls; struct Peer *peer; struct Peer *peer2; struct OverlayConnectContext *occ; @@ -1484,20 +1527,12 @@ GST_handle_overlay_connect (void *cls, uint32_t p2; uint32_t peer2_host_id; - if (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage) != - ntohs (message->size)) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message; p1 = ntohl (msg->peer1); p2 = ntohl (msg->peer2); - if (!VALID_PEER_ID (p1)) + if (! VALID_PEER_ID (p1)) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } peer = GST_peer_list[p1]; @@ -1513,30 +1548,27 @@ GST_handle_overlay_connect (void *cls, if (! VALID_HOST_ID (peer2_host_id)) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, - GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } forward_overlay_connect (msg, client); - GNUNET_SERVER_receive_done (client, - GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } p2n = NULL; occ = GNUNET_new (struct OverlayConnectContext); occ->type = OCC_TYPE_LOCAL; - if (!VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */ + if (! VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */ { if (NULL == (p2n = GST_get_neighbour (peer2_host_id))) { - if (!VALID_HOST_ID (peer2_host_id)) + if (! VALID_HOST_ID (peer2_host_id)) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_WARNING, "0x%llx: Peer %u's host not in our neighbours list\n", operation_id, p2); - GNUNET_SERVER_receive_done (client, - GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); GNUNET_free (occ); return; } @@ -1553,7 +1585,6 @@ GST_handle_overlay_connect (void *cls, GNUNET_CONTAINER_DLL_insert_tail (occq_head, occq_tail, occ); - GNUNET_SERVER_client_keep (client); occ->client = client; occ->other_peer_id = p2; GST_peer_list[p1]->reference_cnt++; @@ -1573,11 +1604,14 @@ GST_handle_overlay_connect (void *cls, occ->op_id, occ->other_peer_id, peer2_host_id); - occ->p2ctx.remote.ncn = - GST_neighbour_get_connection (p2n, &p2_controller_connect_cb, occ); + occ->p2ctx.remote.ncn + = GST_neighbour_get_connection (p2n, + &p2_controller_connect_cb, + occ); break; case OCC_TYPE_REMOTE_SLAVE: - p2_controller_connect_cb (occ, occ->p2ctx.remote.p2c); + p2_controller_connect_cb (occ, + occ->p2ctx.remote.p2c); break; case OCC_TYPE_LOCAL: peer2 = GST_peer_list[occ->other_peer_id]; @@ -1598,7 +1632,7 @@ GST_handle_overlay_connect (void *cls, &overlay_connect_notify, occ); break; } - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); } @@ -1793,64 +1827,72 @@ rocc_cache_get_handle_transport_cb (void *cls, /** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REQUEST_CONNECT messages + * Check #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message + * @return #GNUNET_OK if @a msg is well-formed */ -void -GST_handle_remote_overlay_connect (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +int +check_remote_overlay_connect (void *cls, + const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg) { - const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg; - struct RemoteOverlayConnectCtx *rocc; - struct Peer *peer; - struct GNUNET_PeerIdentity pid; - static char pid_str[16]; uint32_t peer_id; uint16_t msize; uint16_t hsize; - msize = ntohs (message->size); - if (sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) >= msize) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - msg = (const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *) message; + msize = ntohs (msg->header.size); if (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type)) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; + return GNUNET_SYSERR; } hsize = ntohs (msg->hello->size); - if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) != - msize) + if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) != msize) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; + return GNUNET_SYSERR; } peer_id = ntohl (msg->peer); if ((peer_id >= GST_peer_list_size) || - (NULL == (peer = GST_peer_list[peer_id]))) + (NULL == GST_peer_list[peer_id])) { GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; + return GNUNET_SYSERR; } + return GNUNET_OK; +} + + +/** + * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages + * + * @param cls identification of the client + * @param msg the actual message + */ +void +handle_remote_overlay_connect (void *cls, + const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg) +{ + struct GNUNET_SERVICE_Client *client = cls; + struct RemoteOverlayConnectCtx *rocc; + struct Peer *peer; + struct GNUNET_PeerIdentity pid; + static char pid_str[16]; + uint32_t peer_id; + uint16_t hsize; + + hsize = ntohs (msg->hello->size); + peer_id = ntohl (msg->peer); + peer = GST_peer_list[peer_id]; if (GNUNET_YES == peer->is_remote) { struct GNUNET_MessageHeader *msg2; - msg2 = GNUNET_copy_message (message); + msg2 = GNUNET_copy_message (&msg->header); GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller, msg2); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } rocc = GNUNET_new (struct RemoteOverlayConnectCtx); @@ -1872,7 +1914,9 @@ GST_handle_remote_overlay_connect (void *cls, rocc->peer = peer; rocc->peer->reference_cnt++; rocc->hello = GNUNET_malloc (hsize); - GNUNET_memcpy (rocc->hello, msg->hello, hsize); + GNUNET_memcpy (rocc->hello, + msg->hello, + hsize); rocc->tcc.cgh_p2_th = GST_connection_pool_get_handle (peer_id, rocc->peer->details.local.cfg, @@ -1886,8 +1930,7 @@ GST_handle_remote_overlay_connect (void *cls, GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_rocc_task, rocc); - GNUNET_SERVER_receive_done (client, - GNUNET_OK); + GNUNET_SERVICE_client_continue (client); } diff --git a/src/testbed/gnunet-service-testbed_peers.c b/src/testbed/gnunet-service-testbed_peers.c index b55f5a8c8..a977b2b9b 100644 --- a/src/testbed/gnunet-service-testbed_peers.c +++ b/src/testbed/gnunet-service-testbed_peers.c @@ -69,7 +69,7 @@ struct ManageServiceContext /** * The client which requested to manage the peer's service */ - struct GNUNET_SERVER_Client *client; + struct GNUNET_SERVICE_Client *client; /** * Name of the service. @@ -112,7 +112,7 @@ struct PeerReconfigureContext /** * The client which gave this operation to us */ - struct GNUNET_SERVER_Client *client; + struct GNUNET_SERVICE_Client *client; /** * The configuration handle to use as the new template @@ -246,7 +246,8 @@ peer_create_success_cb (void *cls, const struct GNUNET_MessageHeader *msg) remote_peer = fopc->cls; peer_list_add (remote_peer); } - GST_forwarded_operation_reply_relay (fopc, msg); + GST_forwarded_operation_reply_relay (fopc, + msg); } @@ -277,6 +278,115 @@ GST_destroy_peer (struct Peer *peer) } +/** + * Cleanup the context information created for managing a peer's service + * + * @param mctx the ManageServiceContext + */ +static void +cleanup_mctx (struct ManageServiceContext *mctx) +{ + mctx->expired = GNUNET_YES; + GNUNET_CONTAINER_DLL_remove (mctx_head, + mctx_tail, + mctx); + GNUNET_ARM_disconnect (mctx->ah); + GNUNET_assert (0 < mctx->peer->reference_cnt); + mctx->peer->reference_cnt--; + if ( (GNUNET_YES == mctx->peer->destroy_flag) && + (0 == mctx->peer->reference_cnt) ) + GST_destroy_peer (mctx->peer); + GNUNET_free (mctx->service); + GNUNET_free (mctx); +} + + +/** + * Stops a peer + * + * @param peer the peer to stop + * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure + */ +static int +stop_peer (struct Peer *peer) +{ + GNUNET_assert (GNUNET_NO == peer->is_remote); + if (GNUNET_OK != GNUNET_TESTING_peer_kill (peer->details.local.peer)) + return GNUNET_SYSERR; + peer->details.local.is_running = GNUNET_NO; + return GNUNET_OK; +} + + +/** + * Cleans up the given PeerReconfigureContext + * + * @param prc the PeerReconfigureContext + */ +static void +cleanup_prc (struct PeerReconfigureContext *prc) +{ + struct Peer *peer; + + if (VALID_PEER_ID (prc->peer_id)) + { + peer = GST_peer_list [prc->peer_id]; + if (1 != prc->stopped) + { + GNUNET_TESTING_peer_stop_async_cancel (peer->details.local.peer); + stop_peer (peer); /* Stop the peer synchronously */ + } + } + if (NULL != prc->cfg) + GNUNET_CONFIGURATION_destroy (prc->cfg); + GNUNET_CONTAINER_DLL_remove (prc_head, + prc_tail, + prc); + GNUNET_free (prc); +} + + +/** + * Notify peers subsystem that @a client disconnected. + * + * @param client the client that disconnected + */ +void +GST_notify_client_disconnect_peers (struct GNUNET_SERVICE_Client *client) +{ + struct ForwardedOperationContext *fopc; + struct ForwardedOperationContext *fopcn; + struct ManageServiceContext *mctx; + struct ManageServiceContext *mctxn; + struct PeerReconfigureContext *prc; + struct PeerReconfigureContext *prcn; + + for (fopc = fopcq_head; NULL != fopc; fopc = fopcn) + { + fopcn = fopc->next; + if (client == fopc->client) + { + if (OP_PEER_CREATE == fopc->type) + GNUNET_free (fopc->cls); + GNUNET_SCHEDULER_cancel (fopc->timeout_task); + GST_forwarded_operation_timeout (fopc); + } + } + for (mctx = mctx_head; NULL != mctx; mctx = mctxn) + { + mctxn = mctx->next; + if (client == mctx->client) + cleanup_mctx (mctx); + } + for (prc = prc_head; NULL != prc; prc = prcn) + { + prcn = prc->next; + if (client == prc->client) + cleanup_prc (prc); + } +} + + /** * Callback to be called when forwarded peer destroy operation is successfull. We * have to relay the reply msg back to the client @@ -299,22 +409,38 @@ peer_destroy_success_cb (void *cls, const struct GNUNET_MessageHeader *msg) if (0 == remote_peer->reference_cnt) GST_destroy_peer (remote_peer); } - GST_forwarded_operation_reply_relay (fopc, msg); + GST_forwarded_operation_reply_relay (fopc, + msg); +} + + +/** + * Check #GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages + * + * @param cls identification of the client + * @param msg the actual message + * @return #GNUNET_OK if @a msg is well-formed + */ +int +check_peer_create (void *cls, + const struct GNUNET_TESTBED_PeerCreateMessage *msg) +{ + return GNUNET_OK; /* checked later */ } /** - * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages + * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_peer_create (void *cls, + const struct GNUNET_TESTBED_PeerCreateMessage *msg) { - const struct GNUNET_TESTBED_PeerCreateMessage *msg; + struct GNUNET_SERVICE_Client *client = cls; + struct GNUNET_MQ_Envelope *env; struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply; struct GNUNET_CONFIGURATION_Handle *cfg; struct ForwardedOperationContext *fo_ctxt; @@ -323,55 +449,54 @@ GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client, char *emsg; 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 (VALID_PEER_ID (peer_id)) { - (void) GNUNET_asprintf (&emsg, "Peer with ID %u already exists", peer_id); - GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), + (void) GNUNET_asprintf (&emsg, + "Peer with ID %u already exists", + peer_id); + GST_send_operation_fail_msg (client, + GNUNET_ntohll (msg->operation_id), emsg); GNUNET_free (emsg); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } if (UINT32_MAX == peer_id) { - GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), + GST_send_operation_fail_msg (client, + GNUNET_ntohll (msg->operation_id), "Cannot create peer with given ID"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } if (host_id == GST_context->host_id) { /* We are responsible for this peer */ - cfg = GNUNET_TESTBED_extract_config_ (message); + cfg = GNUNET_TESTBED_extract_config_ (&msg->header); if (NULL == cfg) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } - GNUNET_CONFIGURATION_set_value_number (cfg, "TESTBED", "PEERID", + GNUNET_CONFIGURATION_set_value_number (cfg, + "TESTBED", + "PEERID", (unsigned long long) peer_id); - GNUNET_CONFIGURATION_set_value_number (cfg, "PATHS", "PEERID", + GNUNET_CONFIGURATION_set_value_number (cfg, + "PATHS", + "PEERID", (unsigned long long) peer_id); peer = GNUNET_new (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); + LOG_DEBUG ("Creating peer with id: %u\n", + (unsigned int) peer->id); peer->details.local.peer = GNUNET_TESTING_peer_configure (GST_context->system, peer->details.local.cfg, peer->id, @@ -379,24 +504,24 @@ GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client, &emsg); if (NULL == peer->details.local.peer) { - LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg); + 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); + GNUNET_SERVICE_client_drop (client); return; } peer->details.local.is_running = GNUNET_NO; peer_list_add (peer); - reply = GNUNET_new (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage); - reply->header.size = - htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage)); - reply->header.type = - htons (GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS); + env = GNUNET_MQ_msg (reply, + GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS); reply->peer_id = msg->peer_id; reply->operation_id = msg->operation_id; - GST_queue_message (client, &reply->header); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); + GNUNET_SERVICE_client_continue (client); return; } @@ -405,7 +530,7 @@ GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client, if (NULL == route) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); // ? return; } peer = GNUNET_new (struct Peer); @@ -414,7 +539,6 @@ GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client, peer->details.remote.slave = GST_slave_list[route->dest]; peer->details.remote.remote_host_id = host_id; fo_ctxt = GNUNET_new (struct ForwardedOperationContext); - GNUNET_SERVER_client_keep (client); fo_ctxt->client = client; fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id); fo_ctxt->cls = peer; @@ -424,34 +548,34 @@ GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client, [route->dest]->controller, fo_ctxt->operation_id, &msg->header, - peer_create_success_cb, fo_ctxt); + &peer_create_success_cb, + fo_ctxt); fo_ctxt->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, &peer_create_forward_timeout, fo_ctxt); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fo_ctxt); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, + fopcq_tail, + fo_ctxt); + GNUNET_SERVICE_client_continue (client); } /** * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_peer_destroy (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_peer_destroy (void *cls, + const struct GNUNET_TESTBED_PeerDestroyMessage *msg) { - const struct GNUNET_TESTBED_PeerDestroyMessage *msg; + struct GNUNET_SERVICE_Client *client = cls; 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: %llu\n", (unsigned int) peer_id, @@ -460,9 +584,10 @@ GST_handle_peer_destroy (void *cls, { LOG (GNUNET_ERROR_TYPE_ERROR, "Asked to destroy a non existent peer with id: %u\n", peer_id); - GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), + GST_send_operation_fail_msg (client, + GNUNET_ntohll (msg->operation_id), "Peer doesn't exist"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } peer = GST_peer_list[peer_id]; @@ -470,7 +595,6 @@ GST_handle_peer_destroy (void *cls, { /* Forward the destory message to sub controller */ fopc = GNUNET_new (struct ForwardedOperationContext); - GNUNET_SERVER_client_keep (client); fopc->client = client; fopc->cls = peer; fopc->type = OP_PEER_DESTROY; @@ -478,14 +602,18 @@ GST_handle_peer_destroy (void *cls, fopc->opc = GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. slave->controller, - fopc->operation_id, &msg->header, - &peer_destroy_success_cb, fopc); + fopc->operation_id, + &msg->header, + &peer_destroy_success_cb, + fopc); fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, + fopcq_tail, + fopc); + GNUNET_SERVICE_client_continue (client); return; } peer->destroy_flag = GNUNET_YES; @@ -494,8 +622,9 @@ GST_handle_peer_destroy (void *cls, else LOG (GNUNET_ERROR_TYPE_DEBUG, "Delaying peer destroy as peer is currently in use\n"); - GST_send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id)); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GST_send_operation_success_msg (client, + GNUNET_ntohll (msg->operation_id)); + GNUNET_SERVICE_client_continue (client); } @@ -517,54 +646,36 @@ start_peer (struct Peer *peer) /** - * Stops a peer + * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_START_PEER messages * - * @param peer the peer to stop - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ -static int -stop_peer (struct Peer *peer) -{ - GNUNET_assert (GNUNET_NO == peer->is_remote); - if (GNUNET_OK != GNUNET_TESTING_peer_kill (peer->details.local.peer)) - return GNUNET_SYSERR; - peer->details.local.is_running = GNUNET_NO; - return 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 + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_peer_start (void *cls, + const struct GNUNET_TESTBED_PeerStartMessage *msg) { - const struct GNUNET_TESTBED_PeerStartMessage *msg; + struct GNUNET_SERVICE_Client *client = cls; + struct GNUNET_MQ_Envelope *env; 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 (!VALID_PEER_ID (peer_id)) + if (! VALID_PEER_ID (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); + "Asked to start a non existent peer with id: %u\n", + peer_id); + GNUNET_SERVICE_client_continue (client); return; } peer = GST_peer_list[peer_id]; if (GNUNET_YES == peer->is_remote) { fopc = GNUNET_new (struct ForwardedOperationContext); - GNUNET_SERVER_client_keep (client); fopc->client = client; fopc->operation_id = GNUNET_ntohll (msg->operation_id); fopc->type = OP_PEER_START; @@ -578,58 +689,58 @@ GST_handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, + fopcq_tail, + fopc); + GNUNET_SERVICE_client_continue (client); return; } if (GNUNET_OK != start_peer (peer)) { GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), "Failed to start"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } - reply = GNUNET_new (struct GNUNET_TESTBED_PeerEventMessage); - reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); - reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); + env = GNUNET_MQ_msg (reply, + GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START); reply->host_id = htonl (GST_context->host_id); reply->peer_id = msg->peer_id; reply->operation_id = msg->operation_id; - GST_queue_message (client, &reply->header); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); + GNUNET_SERVICE_client_continue (client); } /** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages + * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER messages * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_peer_stop (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_peer_stop (void *cls, + const struct GNUNET_TESTBED_PeerStopMessage *msg) { - const struct GNUNET_TESTBED_PeerStopMessage *msg; + struct GNUNET_SERVICE_Client *client = cls; + struct GNUNET_MQ_Envelope *env; 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", (unsigned int) peer_id); - if (!VALID_PEER_ID (peer_id)) + if (! VALID_PEER_ID (peer_id)) { GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), "Peer not found"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } peer = GST_peer_list[peer_id]; @@ -639,7 +750,6 @@ GST_handle_peer_stop (void *cls, "Forwarding PEER_STOP for peer %u\n", (unsigned int) peer_id); fopc = GNUNET_new (struct ForwardedOperationContext); - GNUNET_SERVER_client_keep (client); fopc->client = client; fopc->operation_id = GNUNET_ntohll (msg->operation_id); fopc->type = OP_PEER_STOP; @@ -657,7 +767,7 @@ GST_handle_peer_stop (void *cls, GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } if (GNUNET_OK != stop_peer (peer)) @@ -668,38 +778,37 @@ GST_handle_peer_stop (void *cls, GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), "Peer not running"); - GNUNET_SERVER_receive_done (client, - GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %u successfully stopped\n", (unsigned int) peer_id); - reply = GNUNET_new (struct GNUNET_TESTBED_PeerEventMessage); - reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); - reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); + env = GNUNET_MQ_msg (reply, + GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP); reply->host_id = htonl (GST_context->host_id); reply->peer_id = msg->peer_id; reply->operation_id = msg->operation_id; - GST_queue_message (client, &reply->header); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); + GNUNET_SERVICE_client_continue (client); GNUNET_TESTING_peer_wait (peer->details.local.peer); } /** - * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages + * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION messages * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_peer_get_config (void *cls, + const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg) { - const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg; + struct GNUNET_SERVICE_Client *client = cls; + struct GNUNET_MQ_Envelope *env; struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply; struct ForwardedOperationContext *fopc; struct Peer *peer; @@ -708,9 +817,7 @@ GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client, 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); LOG_DEBUG ("Received GET_CONFIG for peer %u\n", (unsigned int) peer_id); @@ -719,7 +826,7 @@ GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client, GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), "Peer not found"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } peer = GST_peer_list[peer_id]; @@ -728,7 +835,6 @@ GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client, LOG_DEBUG ("Forwarding PEER_GET_CONFIG for peer: %u\n", (unsigned int) peer_id); fopc = GNUNET_new (struct ForwardedOperationContext); - GNUNET_SERVER_client_keep (client); fopc->client = client; fopc->operation_id = GNUNET_ntohll (msg->operation_id); fopc->type = OP_PEER_INFO; @@ -746,7 +852,7 @@ GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } LOG_DEBUG ("Received PEER_GET_CONFIG for peer: %u\n", @@ -758,47 +864,21 @@ GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client, c_size, &xconfig); GNUNET_free (config); - msize = - xc_size + - sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage); - reply = GNUNET_realloc (xconfig, msize); - (void) memmove (&reply[1], reply, xc_size); - reply->header.size = htons (msize); - reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION); + env = GNUNET_MQ_msg_extra (reply, + xc_size, + GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION); reply->peer_id = msg->peer_id; reply->operation_id = msg->operation_id; GNUNET_TESTING_peer_get_identity (GST_peer_list[peer_id]->details.local.peer, &reply->peer_identity); reply->config_size = htons ((uint16_t) c_size); - GST_queue_message (client, &reply->header); - GNUNET_SERVER_receive_done (client, GNUNET_OK); -} - - -/** - * Cleans up the given PeerReconfigureContext - * - * @param prc the PeerReconfigureContext - */ -static void -cleanup_prc (struct PeerReconfigureContext *prc) -{ - struct Peer *peer; - - if (VALID_PEER_ID (prc->peer_id)) - { - peer = GST_peer_list [prc->peer_id]; - if (1 != prc->stopped) - { - GNUNET_TESTING_peer_stop_async_cancel (peer->details.local.peer); - stop_peer (peer); /* Stop the peer synchronously */ - } - } - if (NULL != prc->cfg) - GNUNET_CONFIGURATION_destroy (prc->cfg); - GNUNET_SERVER_client_drop (prc->client); - GNUNET_CONTAINER_DLL_remove (prc_head, prc_tail, prc); - GNUNET_free (prc); + GNUNET_memcpy (&reply[1], + xconfig, + xc_size); + GNUNET_free (xconfig); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); + GNUNET_SERVICE_client_continue (client); } @@ -886,21 +966,34 @@ prc_stop_cb (void *cls, } +/** + * Check #GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages. + * + * @param cls identification of the client + * @param msg the actual message + * @return #GNUNET_OK if @a msg is well-formed + */ +int +check_peer_reconfigure (void *cls, + const struct GNUNET_TESTBED_PeerReconfigureMessage *msg) +{ + return GNUNET_OK; /* checked later */ +} + + /** * Handler for #GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages. * Should stop the peer asyncronously, destroy it and create it again with the * new configuration. * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_peer_reconfigure (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_peer_reconfigure (void *cls, + const struct GNUNET_TESTBED_PeerReconfigureMessage *msg) { - const struct GNUNET_TESTBED_PeerReconfigureMessage *msg; + struct GNUNET_SERVICE_Client *client = cls; struct Peer *peer; struct GNUNET_CONFIGURATION_Handle *cfg; struct ForwardedOperationContext *fopc; @@ -908,27 +1001,16 @@ GST_handle_peer_reconfigure (void *cls, char *emsg; uint64_t op_id; uint32_t peer_id; - uint16_t msize; - msize = ntohs (message->size); - if (msize <= sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage)) - { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, - GNUNET_SYSERR); - return; - } - msg = (const struct GNUNET_TESTBED_PeerReconfigureMessage *) message; peer_id = ntohl (msg->peer_id); op_id = GNUNET_ntohll (msg->operation_id); - if (!VALID_PEER_ID (peer_id)) + if (! VALID_PEER_ID (peer_id)) { GNUNET_break (0); GST_send_operation_fail_msg (client, op_id, "Peer not found"); - GNUNET_SERVER_receive_done (client, - GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } peer = GST_peer_list[peer_id]; @@ -936,7 +1018,6 @@ GST_handle_peer_reconfigure (void *cls, { LOG_DEBUG ("Forwarding PEER_RECONFIGURE for peer: %u\n", peer_id); fopc = GNUNET_new (struct ForwardedOperationContext); - GNUNET_SERVER_client_keep (client); fopc->client = client; fopc->operation_id = op_id; fopc->type = OP_PEER_RECONFIGURE; @@ -954,7 +1035,7 @@ GST_handle_peer_reconfigure (void *cls, GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } LOG_DEBUG ("Received PEER_RECONFIGURE for peer %u\n", @@ -965,8 +1046,7 @@ GST_handle_peer_reconfigure (void *cls, GST_send_operation_fail_msg (client, op_id, "Peer in use"); - GNUNET_SERVER_receive_done (client, - GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } if (GNUNET_YES == peer->destroy_flag) @@ -975,19 +1055,17 @@ GST_handle_peer_reconfigure (void *cls, GST_send_operation_fail_msg (client, op_id, "Peer is being destroyed"); - GNUNET_SERVER_receive_done (client, - GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } - cfg = GNUNET_TESTBED_extract_config_ (message); + cfg = GNUNET_TESTBED_extract_config_ (&msg->header); if (NULL == cfg) { GNUNET_break (0); GST_send_operation_fail_msg (client, op_id, "Compression error"); - GNUNET_SERVER_receive_done (client, - GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } if (GNUNET_NO == peer->details.local.is_running) @@ -1000,8 +1078,7 @@ GST_handle_peer_reconfigure (void *cls, emsg); GST_send_operation_success_msg (client, op_id); - GNUNET_SERVER_receive_done (client, - GNUNET_OK); + GNUNET_SERVICE_client_continue (client); GNUNET_free_non_null (emsg); return; } @@ -1020,8 +1097,7 @@ GST_handle_peer_reconfigure (void *cls, GST_send_operation_fail_msg (client, op_id, emsg); - GNUNET_SERVER_receive_done (client, - GNUNET_OK); + GNUNET_SERVICE_client_continue (client); GNUNET_free (prc); GNUNET_free (emsg); return; @@ -1030,36 +1106,10 @@ GST_handle_peer_reconfigure (void *cls, prc->peer_id = peer_id; prc->op_id = op_id; prc->client = client; - GNUNET_SERVER_client_keep (client); GNUNET_CONTAINER_DLL_insert_tail (prc_head, prc_tail, prc); - GNUNET_SERVER_receive_done (client, - GNUNET_OK); -} - - -/** - * Cleanup the context information created for managing a peer's service - * - * @param mctx the ManageServiceContext - */ -static void -cleanup_mctx (struct ManageServiceContext *mctx) -{ - mctx->expired = GNUNET_YES; - GNUNET_CONTAINER_DLL_remove (mctx_head, - mctx_tail, - mctx); - GNUNET_SERVER_client_drop (mctx->client); - GNUNET_ARM_disconnect (mctx->ah); - GNUNET_assert (0 < mctx->peer->reference_cnt); - mctx->peer->reference_cnt--; - if ( (GNUNET_YES == mctx->peer->destroy_flag) - && (0 == mctx->peer->reference_cnt) ) - GST_destroy_peer (mctx->peer); - GNUNET_free (mctx->service); - GNUNET_free (mctx); + GNUNET_SERVICE_client_continue (client); } @@ -1211,51 +1261,57 @@ service_manage_result_cb (void *cls, /** - * Handler for GNUNET_TESTBED_ManagePeerServiceMessage message + * Check #GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE message * - * @param cls NULL - * @param client identification of client - * @param message the actual message + * @param cls identification of client + * @param msg the actual message + * @return #GNUNET_OK if @a msg is well-formed */ -void -GST_handle_manage_peer_service (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +int +check_manage_peer_service (void *cls, + const struct GNUNET_TESTBED_ManagePeerServiceMessage *msg) { - const struct GNUNET_TESTBED_ManagePeerServiceMessage *msg; - const char* service; - struct Peer *peer; - char *emsg; - struct GNUNET_ARM_Handle *ah; - struct ManageServiceContext *mctx; - struct ForwardedOperationContext *fopc; - uint64_t op_id; - uint32_t peer_id; uint16_t msize; + const char* service; - - msize = ntohs (message->size); - if (msize <= sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage)) - { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - msg = (const struct GNUNET_TESTBED_ManagePeerServiceMessage *) message; + msize = ntohs (msg->header.size); service = (const char *) &msg[1]; if ('\0' != service[msize - sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage) - 1]) { GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; + return GNUNET_SYSERR; } if (1 < msg->start) { GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; + return GNUNET_SYSERR; } + return GNUNET_OK; +} + + +/** + * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE messages + * + * @param cls identification of client + * @param msg the actual message + */ +void +handle_manage_peer_service (void *cls, + const struct GNUNET_TESTBED_ManagePeerServiceMessage *msg) +{ + struct GNUNET_SERVICE_Client *client = cls; + const char* service; + struct Peer *peer; + char *emsg; + struct GNUNET_ARM_Handle *ah; + struct ManageServiceContext *mctx; + struct ForwardedOperationContext *fopc; + uint64_t op_id; + uint32_t peer_id; + + service = (const char *) &msg[1]; peer_id = ntohl (msg->peer_id); op_id = GNUNET_ntohll (msg->operation_id); LOG_DEBUG ("Received request to manage service %s on peer %u\n", @@ -1277,7 +1333,6 @@ GST_handle_manage_peer_service (void *cls, { /* Forward the destory message to sub controller */ fopc = GNUNET_new (struct ForwardedOperationContext); - GNUNET_SERVER_client_keep (client); fopc->client = client; fopc->cls = peer; fopc->type = OP_MANAGE_SERVICE; @@ -1296,7 +1351,7 @@ GST_handle_manage_peer_service (void *cls, GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } if (GNUNET_NO == peer->details.local.is_running) @@ -1326,7 +1381,6 @@ GST_handle_manage_peer_service (void *cls, peer->reference_cnt++; mctx->op_id = op_id; mctx->ah = ah; - GNUNET_SERVER_client_keep (client); mctx->client = client; mctx->start = msg->start; mctx->service = GNUNET_strdup (service); @@ -1343,14 +1397,14 @@ GST_handle_manage_peer_service (void *cls, GNUNET_ARM_request_service_stop (mctx->ah, service, &service_manage_result_cb, mctx); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; err_ret: LOG (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg); GST_send_operation_fail_msg (client, op_id, emsg); GNUNET_free (emsg); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); } @@ -1432,7 +1486,6 @@ shutdown_peers_reply_cb (void *cls, GNUNET_free (hc); hc = NULL; } - GNUNET_SERVER_client_drop (fo_ctxt->client); GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fo_ctxt); @@ -1443,23 +1496,20 @@ shutdown_peers_reply_cb (void *cls, /** * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages * - * @param cls NULL - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param msg the actual message */ void -GST_handle_shutdown_peers (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_shutdown_peers (void *cls, + const struct GNUNET_TESTBED_ShutdownPeersMessage *msg) { - const struct GNUNET_TESTBED_ShutdownPeersMessage *msg; + struct GNUNET_SERVICE_Client *client = cls; struct HandlerContext_ShutdownPeers *hc; struct Slave *slave; struct ForwardedOperationContext *fo_ctxt; uint64_t op_id; unsigned int cnt; - msg = (const struct GNUNET_TESTBED_ShutdownPeersMessage *) message; LOG_DEBUG ("Received SHUTDOWN_PEERS\n"); /* Stop and destroy all peers */ GST_free_mctxq (); @@ -1481,7 +1531,6 @@ GST_handle_shutdown_peers (void *cls, LOG_DEBUG ("Forwarding SHUTDOWN_PEERS\n"); hc->nslaves++; fo_ctxt = GNUNET_new (struct ForwardedOperationContext); - GNUNET_SERVER_client_keep (client); fo_ctxt->client = client; fo_ctxt->operation_id = op_id; fo_ctxt->cls = hc; @@ -1504,6 +1553,5 @@ GST_handle_shutdown_peers (void *cls, op_id); GNUNET_free (hc); } - GNUNET_SERVER_receive_done (client, - GNUNET_OK); + GNUNET_SERVICE_client_continue (client); } diff --git a/src/testbed/test_testbed_api_barriers.c b/src/testbed/test_testbed_api_barriers.c index 8ee9c41af..01c745a75 100644 --- a/src/testbed/test_testbed_api_barriers.c +++ b/src/testbed/test_testbed_api_barriers.c @@ -50,7 +50,7 @@ struct GNUNET_TESTBED_Barrier *barrier; /** * Identifier for the shutdown task */ -static struct GNUNET_SCHEDULER_Task * shutdown_task; +static struct GNUNET_SCHEDULER_Task *shutdown_task; /** * Result of this test case @@ -85,9 +85,9 @@ do_shutdown (void *cls) * @param cls the closure given to GNUNET_TESTBED_barrier_init() * @param name the name of the barrier * @param barrier the barrier handle - * @param status status of the barrier; GNUNET_OK if the barrier is crossed; - * GNUNET_SYSERR upon error - * @param emsg if the status were to be GNUNET_SYSERR, this parameter has the + * @param status status of the barrier; #GNUNET_OK if the barrier is crossed; + * #GNUNET_SYSERR upon error + * @param emsg if the status were to be #GNUNET_SYSERR, this parameter has the * error messsage */ static void @@ -104,17 +104,20 @@ barrier_cb (void *cls, switch (status) { case GNUNET_TESTBED_BARRIERSTATUS_INITIALISED: - LOG (GNUNET_ERROR_TYPE_INFO, "Barrier initialised\n"); + LOG (GNUNET_ERROR_TYPE_INFO, + "Barrier initialised\n"); old_status = status; return; case GNUNET_TESTBED_BARRIERSTATUS_ERROR: - LOG (GNUNET_ERROR_TYPE_ERROR, "Barrier initialisation failed: %s", + LOG (GNUNET_ERROR_TYPE_ERROR, + "Barrier initialisation failed: %s", (NULL == emsg) ? "unknown reason" : emsg); barrier = NULL; GNUNET_SCHEDULER_shutdown (); return; case GNUNET_TESTBED_BARRIERSTATUS_CROSSED: - LOG (GNUNET_ERROR_TYPE_INFO, "Barrier crossed\n"); + LOG (GNUNET_ERROR_TYPE_INFO, + "Barrier crossed\n"); if (old_status == GNUNET_TESTBED_BARRIERSTATUS_INITIALISED) result = GNUNET_OK; barrier = NULL; @@ -151,13 +154,17 @@ test_master (void *cls, GNUNET_assert (NULL == cls); if (NULL == peers_) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test due to timeout\n"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failing test due to timeout\n"); return; } GNUNET_assert (NUM_PEERS == num_peers); c = GNUNET_TESTBED_run_get_controller_handle (h); - barrier = GNUNET_TESTBED_barrier_init (c, TEST_BARRIER_NAME, 100, - &barrier_cb, NULL); + barrier = GNUNET_TESTBED_barrier_init (c, + TEST_BARRIER_NAME, + 100, + &barrier_cb, + NULL); shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, diff --git a/src/testbed/testbed_api.c b/src/testbed/testbed_api.c index 53f70a1c0..3f2109ecd 100644 --- a/src/testbed/testbed_api.c +++ b/src/testbed/testbed_api.c @@ -1298,8 +1298,13 @@ handle_barrier_status (void *cls, GNUNET_assert (NULL != barrier->cb); if ((GNUNET_YES == barrier->echo) && (GNUNET_TESTBED_BARRIERSTATUS_CROSSED == status)) - GNUNET_TESTBED_queue_message_ (c, GNUNET_copy_message (&msg->header)); - barrier->cb (barrier->cls, name, barrier, status, emsg); + GNUNET_TESTBED_queue_message_ (c, + GNUNET_copy_message (&msg->header)); + barrier->cb (barrier->cls, + name, + barrier, + status, + emsg); if (GNUNET_TESTBED_BARRIERSTATUS_INITIALISED == status) return; /* just initialised; skip cleanup */ diff --git a/src/testbed/testbed_api_barriers.c b/src/testbed/testbed_api_barriers.c index 3761fbbdf..1679756a1 100644 --- a/src/testbed/testbed_api_barriers.c +++ b/src/testbed/testbed_api_barriers.c @@ -105,6 +105,9 @@ handle_status (void *cls, { struct GNUNET_TESTBED_BarrierWaitHandle *h = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got barrier status %d\n", + (int) ntohs (msg->status)); switch (ntohs (msg->status)) { case GNUNET_TESTBED_BARRIERSTATUS_ERROR: @@ -206,6 +209,9 @@ GNUNET_TESTBED_barrier_wait (const char *name, GNUNET_free (h); return NULL; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Waiting on barrier `%s'\n", + name); h->name = GNUNET_strdup (name); h->cb = cb; h->cb_cls = cb_cls; @@ -226,8 +232,8 @@ GNUNET_TESTBED_barrier_wait (const char *name, name_len, GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT); GNUNET_memcpy (msg->name, - name, - name_len); + name, + name_len); GNUNET_MQ_send (h->mq, env); return h; diff --git a/src/util/mq.c b/src/util/mq.c index 3d6f27567..7c13265d8 100644 --- a/src/util/mq.c +++ b/src/util/mq.c @@ -295,9 +295,10 @@ GNUNET_MQ_inject_message (struct GNUNET_MQ_Handle *mq, } done: if (GNUNET_NO == handled) - LOG (GNUNET_ERROR_TYPE_DEBUG, - "No handler for message of type %d\n", - ntohs (mh->type)); + LOG (GNUNET_ERROR_TYPE_INFO, + "No handler for message of type %d and size %d\n", + ntohs (mh->type), + ntohs (mh->size)); } diff --git a/src/util/service_new.c b/src/util/service_new.c index 9929341f4..744adc387 100644 --- a/src/util/service_new.c +++ b/src/util/service_new.c @@ -136,7 +136,7 @@ struct GNUNET_SERVICE_Handle /** * Message handlers to use for all clients. */ - const struct GNUNET_MQ_MessageHandler *handlers; + struct GNUNET_MQ_MessageHandler *handlers; /** * Closure for @e task. @@ -1616,12 +1616,24 @@ GNUNET_SERVICE_starT (const char *service_name, sh->connect_cb = connect_cb; sh->disconnect_cb = disconnect_cb; sh->cb_cls = cls; - sh->handlers = handlers; + if (NULL != handlers) + { + unsigned int i; + + for (i=0;NULL != handlers[i].cb; i++) ; + sh->handlers = GNUNET_new_array (i + 1, + struct GNUNET_MQ_MessageHandler); + GNUNET_memcpy (sh->handlers, + handlers, + i * sizeof (struct GNUNET_MQ_MessageHandler)); + } if (GNUNET_OK != setup_service (sh)) { + GNUNET_free (sh->handlers); GNUNET_free (sh); return NULL; } + GNUNET_SERVICE_resume (sh); return sh; } @@ -1634,7 +1646,13 @@ GNUNET_SERVICE_starT (const char *service_name, void GNUNET_SERVICE_stoP (struct GNUNET_SERVICE_Handle *srv) { + struct GNUNET_SERVICE_Client *client; + + GNUNET_SERVICE_suspend (srv); + while (NULL != (client = srv->clients_head)) + GNUNET_SERVICE_client_drop (client); teardown_service (srv); + GNUNET_free (srv->handlers); GNUNET_free (srv); } @@ -1736,7 +1754,17 @@ GNUNET_SERVICE_ruN_ (int argc, sh.connect_cb = connect_cb; sh.disconnect_cb = disconnect_cb; sh.cb_cls = cls; - sh.handlers = handlers; + if (NULL != handlers) + { + unsigned int i; + + for (i=0;NULL != handlers[i].cb; i++) ; + sh.handlers = GNUNET_new_array (i + 1, + struct GNUNET_MQ_MessageHandler); + GNUNET_memcpy (sh.handlers, + handlers, + i * sizeof (struct GNUNET_MQ_MessageHandler)); + } sh.service_name = service_name; /* setup subsystems */ @@ -1867,7 +1895,7 @@ shutdown: } #endif teardown_service (&sh); - + GNUNET_free (sh.handlers); GNUNET_SPEEDUP_stop_ (); GNUNET_CONFIGURATION_destroy (cfg); GNUNET_free_non_null (logfile);