diff options
Diffstat (limited to 'src/arm')
-rw-r--r-- | src/arm/Makefile.in | 2 | ||||
-rw-r--r-- | src/arm/arm.conf.in | 2 | ||||
-rw-r--r-- | src/arm/arm.h | 21 | ||||
-rw-r--r-- | src/arm/arm_api.c | 498 | ||||
-rw-r--r-- | src/arm/do_start_process.c | 1 | ||||
-rw-r--r-- | src/arm/gnunet-arm.c | 56 | ||||
-rw-r--r-- | src/arm/gnunet-service-arm.c | 354 | ||||
-rw-r--r-- | src/arm/mockup-service.c | 31 | ||||
-rw-r--r-- | src/arm/test_exponential_backoff.c | 88 |
9 files changed, 635 insertions, 418 deletions
diff --git a/src/arm/Makefile.in b/src/arm/Makefile.in index 584cc06..122ab3c 100644 --- a/src/arm/Makefile.in +++ b/src/arm/Makefile.in @@ -223,6 +223,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBADD_DL = @LIBADD_DL@ @@ -256,6 +257,7 @@ LT_DLLOADERS = @LT_DLLOADERS@ LT_DLPREOPEN = @LT_DLPREOPEN@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ +MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ diff --git a/src/arm/arm.conf.in b/src/arm/arm.conf.in index c1f408f..e72e420 100644 --- a/src/arm/arm.conf.in +++ b/src/arm/arm.conf.in @@ -7,7 +7,7 @@ CONFIG = $DEFAULTCONFIG BINARY = gnunet-service-arm ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; -DEFAULTSERVICES = topology hostlist +DEFAULTSERVICES = topology hostlist dht nse mesh fs UNIXPATH = /tmp/gnunet-service-arm.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES diff --git a/src/arm/arm.h b/src/arm/arm.h index 4b9da6f..2188410 100644 --- a/src/arm/arm.h +++ b/src/arm/arm.h @@ -51,6 +51,27 @@ struct GNUNET_ARM_ResultMessage */ uint32_t status; }; + +/** + * Reply from ARM to client for the + * GNUNET_MESSAGE_TYPE_ARM_LIST request followed by count + * '\0' terminated strings. header->size contains the + * total size (including all strings). + */ +struct GNUNET_ARM_ListResultMessage +{ + /** + * Reply to client is of type GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT + */ + struct GNUNET_MessageHeader header; + + /** + * Number of '\0' terminated strings that follow + * this message. + */ + uint16_t count; +}; + GNUNET_NETWORK_STRUCT_END #endif diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c index 0f4ae6a..1b78d33 100644 --- a/src/arm/arm_api.c +++ b/src/arm/arm_api.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009, 2010 Christian Grothoff (and other contributing authors) + (C) 2009, 2010, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -52,7 +52,6 @@ struct GNUNET_ARM_Handle }; - /** * Context for handling the shutdown of a service. */ @@ -84,9 +83,9 @@ struct ShutdownContext void *cont_cls; /** - * Result of the operation + * Handle for transmission request. */ - enum GNUNET_ARM_ProcessStatus confirmed; + struct GNUNET_CLIENT_TransmitHandle *th; }; @@ -106,45 +105,23 @@ static void service_shutdown_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct ShutdownContext *shutdown_ctx = cls; - const struct GNUNET_ARM_ResultMessage *rmsg; - if (msg == NULL) + if (NULL != msg) { - if (shutdown_ctx->cont != NULL) - { - if (shutdown_ctx->confirmed == GNUNET_ARM_PROCESS_SHUTDOWN) - { - /* shutdown is now complete, as we waited for the network disconnect... */ - shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_ARM_PROCESS_DOWN); - } - else - { - /* communication error */ - shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR); - } - } + /* We just expected a disconnect! Report the error and be done with it... */ + GNUNET_break (0); + shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR); GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); - GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); + GNUNET_CLIENT_disconnect (shutdown_ctx->sock); GNUNET_free (shutdown_ctx); return; } - if (ntohs (msg->size) == - sizeof (struct GNUNET_ARM_ResultMessage)) - { - rmsg = (const struct GNUNET_ARM_ResultMessage*) msg; - shutdown_ctx->confirmed = (enum GNUNET_ARM_ProcessStatus) ntohl (rmsg->status); - if (shutdown_ctx->confirmed != GNUNET_ARM_PROCESS_SHUTDOWN) - { - /* ARM is not shutting down, well, report the error and be done with it... */ - shutdown_ctx->cont (shutdown_ctx->cont_cls, shutdown_ctx->confirmed); - GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); - GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); - GNUNET_free (shutdown_ctx); - return; - } - } - GNUNET_CLIENT_receive (shutdown_ctx->sock, &service_shutdown_handler, - shutdown_ctx, GNUNET_TIME_UNIT_FOREVER_REL); + if (NULL != shutdown_ctx->cont) + /* shutdown is now complete, as we waited for the network disconnect... */ + shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_ARM_PROCESS_DOWN); + GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); + GNUNET_CLIENT_disconnect (shutdown_ctx->sock); + GNUNET_free (shutdown_ctx); } @@ -161,7 +138,7 @@ service_shutdown_cancel (void *cls, struct ShutdownContext *shutdown_ctx = cls; shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_ARM_PROCESS_COMMUNICATION_TIMEOUT); - GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); + GNUNET_CLIENT_disconnect (shutdown_ctx->sock); GNUNET_free (shutdown_ctx); } @@ -178,19 +155,19 @@ service_shutdown_cancel (void *cls, static size_t write_shutdown (void *cls, size_t size, void *buf) { - struct GNUNET_MessageHeader *msg; struct ShutdownContext *shutdown_ctx = cls; + struct GNUNET_MessageHeader *msg; + shutdown_ctx->th = NULL; if (size < sizeof (struct GNUNET_MessageHeader)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - _("Failed to transmit shutdown request to client.\n")); - shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR); - GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); - GNUNET_free (shutdown_ctx); - return 0; /* client disconnected */ - } - + { + LOG (GNUNET_ERROR_TYPE_WARNING, + _("Failed to transmit shutdown request to client.\n")); + shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR); + GNUNET_CLIENT_disconnect (shutdown_ctx->sock); + GNUNET_free (shutdown_ctx); + return 0; /* client disconnected */ + } GNUNET_CLIENT_receive (shutdown_ctx->sock, &service_shutdown_handler, shutdown_ctx, GNUNET_TIME_UNIT_FOREVER_REL); shutdown_ctx->cancel_task = @@ -229,12 +206,10 @@ arm_service_shutdown (struct GNUNET_CLIENT_Connection *sock, shutdown_ctx->cont_cls = cont_cls; shutdown_ctx->sock = sock; shutdown_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); - shutdown_ctx->confirmed = GNUNET_ARM_PROCESS_COMMUNICATION_ERROR; - /* FIXME: store return value? */ - GNUNET_CLIENT_notify_transmit_ready (sock, - sizeof (struct GNUNET_MessageHeader), - timeout, GNUNET_YES, &write_shutdown, - shutdown_ctx); + shutdown_ctx->th = GNUNET_CLIENT_notify_transmit_ready (sock, + sizeof (struct GNUNET_MessageHeader), + timeout, GNUNET_NO, &write_shutdown, + shutdown_ctx); } @@ -269,7 +244,7 @@ void GNUNET_ARM_disconnect (struct GNUNET_ARM_Handle *h) { if (h->client != NULL) - GNUNET_CLIENT_disconnect (h->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (h->client); GNUNET_CONFIGURATION_destroy (h->cfg); GNUNET_free (h); } @@ -345,22 +320,18 @@ arm_service_report (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) char *lopostfix; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) - { -#if DEBUG_ARM - LOG (GNUNET_ERROR_TYPE_DEBUG, "Looks like `%s' is already running.\n", - "gnunet-service-arm"); -#endif - /* arm is running! */ - if (pos->callback != NULL) - pos->callback (pos->cls, GNUNET_ARM_PROCESS_ALREADY_RUNNING); - GNUNET_free (pos); - return; - } -#if DEBUG_ARM + { + LOG (GNUNET_ERROR_TYPE_DEBUG, "Looks like `%s' is already running.\n", + "gnunet-service-arm"); + /* arm is running! */ + if (pos->callback != NULL) + pos->callback (pos->cls, GNUNET_ARM_PROCESS_ALREADY_RUNNING); + GNUNET_free (pos); + return; + } LOG (GNUNET_ERROR_TYPE_DEBUG, "Looks like `%s' is not running, will start it.\n", "gnunet-service-arm"); -#endif if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (pos->h->cfg, "arm", "PREFIX", &loprefix)) @@ -372,33 +343,33 @@ arm_service_report (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (pos->h->cfg, "arm", "BINARY", &binary)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - _ - ("Configuration failes to specify option `%s' in section `%s'!\n"), - "BINARY", "arm"); - if (pos->callback != NULL) - pos->callback (pos->cls, GNUNET_ARM_PROCESS_UNKNOWN); - GNUNET_free (pos); - GNUNET_free (loprefix); - GNUNET_free (lopostfix); - return; - } + { + LOG (GNUNET_ERROR_TYPE_WARNING, + _ + ("Configuration failes to specify option `%s' in section `%s'!\n"), + "BINARY", "arm"); + if (pos->callback != NULL) + pos->callback (pos->cls, GNUNET_ARM_PROCESS_UNKNOWN); + GNUNET_free (pos); + GNUNET_free (loprefix); + GNUNET_free (lopostfix); + return; + } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (pos->h->cfg, "arm", "CONFIG", &config)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - _("Configuration fails to specify option `%s' in section `%s'!\n"), - "CONFIG", "arm"); - if (pos->callback != NULL) - pos->callback (pos->cls, GNUNET_ARM_PROCESS_UNKNOWN); - GNUNET_free (binary); - GNUNET_free (pos); - GNUNET_free (loprefix); - GNUNET_free (lopostfix); - return; - } + { + LOG (GNUNET_ERROR_TYPE_WARNING, + _("Configuration fails to specify option `%s' in section `%s'!\n"), + "CONFIG", "arm"); + if (pos->callback != NULL) + pos->callback (pos->cls, GNUNET_ARM_PROCESS_UNKNOWN); + GNUNET_free (binary); + GNUNET_free (pos); + GNUNET_free (loprefix); + GNUNET_free (lopostfix); + return; + } if ((GNUNET_YES == GNUNET_CONFIGURATION_have_value (pos->h->cfg, "TESTING", "WEAKRANDOM")) && (GNUNET_YES == @@ -407,26 +378,20 @@ arm_service_report (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) && (GNUNET_NO == GNUNET_CONFIGURATION_have_value (pos->h->cfg, "TESTING", "HOSTFILE"))) - { - /* Means we are ONLY running locally */ - /* we're clearly running a test, don't daemonize */ - proc = do_start_process (GNUNET_NO, - NULL, loprefix, binary, "-c", config, -#if DEBUG_ARM - "-L", "DEBUG", -#endif - /* no daemonization! */ - lopostfix, NULL); - } + { + /* Means we are ONLY running locally */ + /* we're clearly running a test, don't daemonize */ + proc = do_start_process (GNUNET_NO, + NULL, loprefix, binary, "-c", config, + /* no daemonization! */ + lopostfix, NULL); + } else - { - proc = do_start_process (GNUNET_NO, - NULL, loprefix, binary, "-c", config, -#if DEBUG_ARM - "-L", "DEBUG", -#endif - "-d", lopostfix, NULL); - } + { + proc = do_start_process (GNUNET_NO, + NULL, loprefix, binary, "-c", config, + "-d", lopostfix, NULL); + } GNUNET_free (binary); GNUNET_free (config); GNUNET_free (loprefix); @@ -461,26 +426,24 @@ handle_response (void *cls, const struct GNUNET_MessageHeader *msg) if ((msg == NULL) || (ntohs (msg->size) != sizeof (struct GNUNET_ARM_ResultMessage))) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - _ - ("Error receiving response to `%s' request from ARM for service `%s'\n"), - (sc->type == GNUNET_MESSAGE_TYPE_ARM_START) ? "START" : "STOP", - (const char *) &sc[1]); - GNUNET_CLIENT_disconnect (sc->h->client, GNUNET_NO); - sc->h->client = GNUNET_CLIENT_connect ("arm", sc->h->cfg); - GNUNET_assert (NULL != sc->h->client); - if (sc->callback != NULL) - sc->callback (sc->cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR); - GNUNET_free (sc); - return; - } + { + LOG (GNUNET_ERROR_TYPE_WARNING, + _ + ("Error receiving response to `%s' request from ARM for service `%s'\n"), + (sc->type == GNUNET_MESSAGE_TYPE_ARM_START) ? "START" : "STOP", + (const char *) &sc[1]); + GNUNET_CLIENT_disconnect (sc->h->client); + sc->h->client = GNUNET_CLIENT_connect ("arm", sc->h->cfg); + GNUNET_assert (NULL != sc->h->client); + if (sc->callback != NULL) + sc->callback (sc->cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR); + GNUNET_free (sc); + return; + } res = (const struct GNUNET_ARM_ResultMessage *) msg; -#if DEBUG_ARM LOG (GNUNET_ERROR_TYPE_DEBUG, "Received response from ARM for service `%s': %u\n", (const char *) &sc[1], ntohs (msg->type)); -#endif status = (enum GNUNET_ARM_ProcessStatus) ntohl (res->status); if (sc->callback != NULL) sc->callback (sc->cls, status); @@ -510,19 +473,17 @@ change_service (struct GNUNET_ARM_Handle *h, const char *service_name, slen = strlen (service_name) + 1; if (slen + sizeof (struct GNUNET_MessageHeader) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) - { - GNUNET_break (0); - if (cb != NULL) - cb (cb_cls, GNUNET_NO); - return; - } -#if DEBUG_ARM + { + GNUNET_break (0); + if (cb != NULL) + cb (cb_cls, GNUNET_NO); + return; + } LOG (GNUNET_ERROR_TYPE_DEBUG, (type == GNUNET_MESSAGE_TYPE_ARM_START) ? _("Requesting start of service `%s'.\n") : _("Requesting termination of service `%s'.\n"), service_name); -#endif sctx = GNUNET_malloc (sizeof (struct RequestContext) + slen); sctx->h = h; sctx->callback = cb; @@ -539,20 +500,19 @@ change_service (struct GNUNET_ARM_Handle *h, const char *service_name, GNUNET_TIME_absolute_get_remaining (sctx->timeout), GNUNET_YES, &handle_response, sctx)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - (type == - GNUNET_MESSAGE_TYPE_ARM_START) ? - _("Error while trying to transmit request to start `%s' to ARM\n") - : - _("Error while trying to transmit request to stop `%s' to ARM\n"), - (const char *) &service_name); - if (cb != NULL) - cb (cb_cls, GNUNET_SYSERR); - GNUNET_free (sctx); - GNUNET_free (msg); - return; - } + { + LOG (GNUNET_ERROR_TYPE_WARNING, + (type == + GNUNET_MESSAGE_TYPE_ARM_START) + ? _("Error while trying to transmit request to start `%s' to ARM\n") + : _("Error while trying to transmit request to stop `%s' to ARM\n"), + (const char *) &service_name); + if (cb != NULL) + cb (cb_cls, GNUNET_SYSERR); + GNUNET_free (sctx); + GNUNET_free (msg); + return; + } GNUNET_free (msg); } @@ -576,38 +536,36 @@ GNUNET_ARM_start_service (struct GNUNET_ARM_Handle *h, struct GNUNET_CLIENT_Connection *client; size_t slen; -#if DEBUG_ARM LOG (GNUNET_ERROR_TYPE_DEBUG, _("Asked to start service `%s' within %llu ms\n"), service_name, (unsigned long long) timeout.rel_value); -#endif if (0 == strcasecmp ("arm", service_name)) - { - slen = strlen ("arm") + 1; - sctx = GNUNET_malloc (sizeof (struct RequestContext) + slen); - sctx->h = h; - sctx->callback = cb; - sctx->cls = cb_cls; - sctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); - memcpy (&sctx[1], service_name, slen); - GNUNET_CLIENT_service_test ("arm", h->cfg, timeout, &arm_service_report, - sctx); - return; - } + { + slen = strlen ("arm") + 1; + sctx = GNUNET_malloc (sizeof (struct RequestContext) + slen); + sctx->h = h; + sctx->callback = cb; + sctx->cls = cb_cls; + sctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); + memcpy (&sctx[1], service_name, slen); + GNUNET_CLIENT_service_test ("arm", h->cfg, timeout, &arm_service_report, + sctx); + return; + } if (h->client == NULL) + { + client = GNUNET_CLIENT_connect ("arm", h->cfg); + if (client == NULL) { - client = GNUNET_CLIENT_connect ("arm", h->cfg); - if (client == NULL) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "arm_api, GNUNET_CLIENT_connect returned NULL\n"); - cb (cb_cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR); - return; - } LOG (GNUNET_ERROR_TYPE_DEBUG, - "arm_api, GNUNET_CLIENT_connect returned non-NULL\n"); - h->client = client; + "arm_api, GNUNET_CLIENT_connect returned NULL\n"); + cb (cb_cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR); + return; } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "arm_api, GNUNET_CLIENT_connect returned non-NULL\n"); + h->client = client; + } LOG (GNUNET_ERROR_TYPE_DEBUG, "arm_api, h->client non-NULL\n"); change_service (h, service_name, timeout, cb, cb_cls, GNUNET_MESSAGE_TYPE_ARM_START); @@ -654,28 +612,190 @@ GNUNET_ARM_stop_service (struct GNUNET_ARM_Handle *h, LOG (GNUNET_ERROR_TYPE_INFO, _("Stopping service `%s' within %llu ms\n"), service_name, (unsigned long long) timeout.rel_value); if (h->client == NULL) + { + client = GNUNET_CLIENT_connect ("arm", h->cfg); + if (client == NULL) { - client = GNUNET_CLIENT_connect ("arm", h->cfg); - if (client == NULL) - { - cb (cb_cls, GNUNET_SYSERR); - return; - } - h->client = client; - } - if (0 == strcasecmp ("arm", service_name)) - { - arm_shutdown_ctx = GNUNET_malloc (sizeof (struct ARM_ShutdownContext)); - arm_shutdown_ctx->cb = cb; - arm_shutdown_ctx->cb_cls = cb_cls; - arm_service_shutdown (h->client, timeout, &arm_shutdown_callback, - arm_shutdown_ctx); - h->client = NULL; + cb (cb_cls, GNUNET_SYSERR); return; } + h->client = client; + } + if (0 == strcasecmp ("arm", service_name)) + { + arm_shutdown_ctx = GNUNET_malloc (sizeof (struct ARM_ShutdownContext)); + arm_shutdown_ctx->cb = cb; + arm_shutdown_ctx->cb_cls = cb_cls; + arm_service_shutdown (h->client, timeout, &arm_shutdown_callback, + arm_shutdown_ctx); + h->client = NULL; + return; + } change_service (h, service_name, timeout, cb, cb_cls, GNUNET_MESSAGE_TYPE_ARM_STOP); } +/** + * Internal state for a list request with ARM. + */ +struct ListRequestContext +{ + + /** + * Pointer to our handle with ARM. + */ + struct GNUNET_ARM_Handle *h; + + /** + * Function to call with a status code for the requested operation. + */ + GNUNET_ARM_List_Callback callback; + + /** + * Closure for "callback". + */ + void *cls; + + /** + * Timeout for the operation. + */ + struct GNUNET_TIME_Absolute timeout; +}; + + +/** + * Process a response from ARM for the list request. + * + * @param cls the list request context + * @param msg the response + */ +static void +handle_list_response (void *cls, const struct GNUNET_MessageHeader *msg) +{ + struct ListRequestContext *sc = cls; + const struct GNUNET_ARM_ListResultMessage *res; + const char *pos; + uint16_t size_check; + uint16_t rcount; + uint16_t msize; + + if (NULL == msg) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "Error receiving response to LIST request from ARM\n"); + GNUNET_CLIENT_disconnect (sc->h->client); + sc->h->client = GNUNET_CLIENT_connect ("arm", sc->h->cfg); + GNUNET_assert (NULL != sc->h->client); + if (sc->callback != NULL) + sc->callback (sc->cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR, 0, NULL); + GNUNET_free (sc); + return; + } + + if (NULL == sc->callback) + { + GNUNET_break (0); + GNUNET_free (sc); + return; + } + msize = ntohs (msg->size); + if ( (msize < sizeof ( struct GNUNET_ARM_ListResultMessage)) || + (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT) ) + { + GNUNET_break (0); + sc->callback (sc->cls, GNUNET_NO, 0, NULL); + GNUNET_free (sc); + return; + } + size_check = 0; + res = (const struct GNUNET_ARM_ListResultMessage *) msg; + rcount = ntohs (res->count); + { + const char *list[rcount]; + unsigned int i; + + pos = (const char *)&res[1]; + for (i=0; i<rcount; i++) + { + const char *end = memchr (pos, 0, msize - size_check); + if (NULL == end) + { + GNUNET_break (0); + sc->callback (sc->cls, GNUNET_NO, 0, NULL); + GNUNET_free (sc); + return; + } + list[i] = pos; + size_check += (end - pos) + 1; + pos = end + 1; + } + sc->callback (sc->cls, GNUNET_YES, rcount, list); + } + GNUNET_free (sc); +} + + +/** + * List all running services. + * + * @param h handle to ARM + * @param timeout how long to wait before failing for good + * @param cb callback to invoke when service is ready + * @param cb_cls closure for callback + */ +void +GNUNET_ARM_list_running_services (struct GNUNET_ARM_Handle *h, + struct GNUNET_TIME_Relative timeout, + GNUNET_ARM_List_Callback cb, void *cb_cls) +{ + struct ListRequestContext *sctx; + struct GNUNET_MessageHeader msg; + struct GNUNET_CLIENT_Connection *client; + + if (h->client == NULL) + { + client = GNUNET_CLIENT_connect ("arm", h->cfg); + if (client == NULL) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "arm_api, GNUNET_CLIENT_connect returned NULL\n"); + cb (cb_cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR, 0, NULL); + return; + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "arm_api, GNUNET_CLIENT_connect returned non-NULL\n"); + h->client = client; + } + + sctx = GNUNET_malloc (sizeof (struct RequestContext)); + sctx->h = h; + sctx->callback = cb; + sctx->cls = cb_cls; + sctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); + msg.size = htons (sizeof (struct GNUNET_MessageHeader)); + msg.type = htons (GNUNET_MESSAGE_TYPE_ARM_LIST); + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Requesting LIST from ARM service with timeout: %llu ms\n", + (unsigned long long)timeout.rel_value); + + if (GNUNET_OK != + GNUNET_CLIENT_transmit_and_get_response (sctx->h->client, + &msg, + GNUNET_TIME_absolute_get_remaining + (sctx->timeout), + GNUNET_YES, + &handle_list_response, + sctx)) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "Error while trying to transmit request to list services to ARM\n"); + if (cb != NULL) + cb (cb_cls, GNUNET_SYSERR, 0, NULL); + GNUNET_free (sctx); + return; + } +} + /* end of arm_api.c */ diff --git a/src/arm/do_start_process.c b/src/arm/do_start_process.c index 865ea8e..4554f57 100644 --- a/src/arm/do_start_process.c +++ b/src/arm/do_start_process.c @@ -7,6 +7,7 @@ * limitation that it does NOT allow passing command line arguments * with spaces to the new process. * + * @param pipe_control should a pipe be used to send signals to the child? * @param lsocks array of listen sockets to dup starting at fd3 (systemd-style), or NULL * @param first_arg first argument for argv (may be an empty string) * @param ... more arguments, NULL terminated diff --git a/src/arm/gnunet-arm.c b/src/arm/gnunet-arm.c index 65700ee..58aa709 100644 --- a/src/arm/gnunet-arm.c +++ b/src/arm/gnunet-arm.c @@ -49,6 +49,11 @@ #define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) /** + * Timeout for listing all running services. + */ +#define LIST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) + +/** * Set if we are to shutdown all services (including ARM). */ static int end; @@ -74,6 +79,11 @@ static int delete; static int quiet; /** + * Set if we should print a list of currently running services. + */ +static int list; + +/** * Set to the name of a service to start. */ static char *init; @@ -193,6 +203,29 @@ confirm_cb (void *cls, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } +/** + * Callback invoked with the list of running services. + * Reports to the user and then runs the next phase in the FSM. + * + * @param cls currently not used + * @param result result of the operation + * @param count number of running services + * @param list copy of the list of running services + */ +static void +list_cb (void *cls, int result, unsigned int count, const char *const*list) +{ + unsigned int i; + + if ( (result != GNUNET_YES) || (NULL == list) ) + { + FPRINTF (stderr, "%s", _("Error communicating with ARM. ARM not running?\n")); + return; + } + FPRINTF (stdout, "%s", _("Running services:\n")); + for (i=0; i<count; i++) + FPRINTF (stdout, "%s\n", list[i]); +} /** * Main function that will be run by the scheduler. @@ -318,7 +351,7 @@ cps_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) start = 1; restart = 0; h = GNUNET_ARM_connect (cfg, NULL); - if (h == NULL) + if (NULL == h) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fatal error initializing ARM API.\n")); @@ -328,6 +361,25 @@ cps_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_SCHEDULER_add_now (&cps_loop, NULL); return; } + break; + case 5: + if (list) { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Going to list all running services controlled by ARM.\n"); + + if (NULL == h) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Fatal error initializing ARM API.\n")); + return; + } + + GNUNET_ARM_list_running_services (h, + (0 == + timeout.rel_value) ? LIST_TIMEOUT : + timeout, &list_cb, NULL); + return; + } /* Fall through */ default: /* last phase */ GNUNET_ARM_disconnect (h); @@ -371,6 +423,8 @@ main (int argc, char *const *argv) {'T', "timeout", NULL, gettext_noop ("timeout for completing current operation"), GNUNET_YES, &GNUNET_GETOPT_set_ulong, &temp_timeout_ms}, + {'I', "info", NULL, gettext_noop ("List currently running services"), + GNUNET_NO, &GNUNET_GETOPT_set_one, &list}, GNUNET_GETOPT_OPTION_END }; diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c index f4430ed..ce91043 100644 --- a/src/arm/gnunet-service-arm.c +++ b/src/arm/gnunet-service-arm.c @@ -146,6 +146,12 @@ struct ServiceList struct GNUNET_TIME_Absolute restart_at; /** + * Time we asked the service to shut down (used to calculate time it took + * the service to terminate). + */ + struct GNUNET_TIME_Absolute killed_at; + + /** * Is this service to be started by default (or did a client tell us explicitly * to start it)? GNUNET_NO if the service is started only upon 'accept' on a * listen socket or possibly explicitly by a client changing the value. @@ -308,11 +314,9 @@ start_process (struct ServiceList *sl) use_debug = GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "DEBUG"); /* actually start process */ -#if DEBUG_ARM GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting service `%s' using binary `%s' and configuration `%s'\n", sl->name, sl->binary, sl->config); -#endif GNUNET_assert (NULL == sl->proc); if (GNUNET_YES == use_debug) sl->proc = @@ -357,10 +361,8 @@ write_result (void *cls, size_t size, void *buf) _("Could not send status result to client\n")); return 0; /* error, not much we can do */ } -#if DEBUG_ARM GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending status response %u to client\n", (unsigned int) *res); -#endif GNUNET_assert (size >= sizeof (struct GNUNET_ARM_ResultMessage)); msg = buf; msg->header.size = htons (sizeof (struct GNUNET_ARM_ResultMessage)); @@ -370,6 +372,43 @@ write_result (void *cls, size_t size, void *buf) return sizeof (struct GNUNET_ARM_ResultMessage); } +/** + * Transmit the list of running services. + * + * @param cls pointer to struct GNUNET_ARM_ListResultMessage with the message + * @param size number of bytes available in buf + * @param buf where to copy the message, NULL on error + * @return number of bytes copied to buf + */ +static size_t +write_list_result (void *cls, size_t size, void *buf) +{ + struct GNUNET_ARM_ListResultMessage *msg = cls; + struct GNUNET_ARM_ListResultMessage *rslt; + size_t rslt_size; + + if (buf == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Could not send list result to client\n")); + return 0; /* error, not much we can do */ + } + + GNUNET_assert (size >= msg->header.size); + rslt = buf; + rslt->header.size = htons (msg->header.size); + rslt->header.type = htons (msg->header.type); + rslt->count = htons (msg->count); + + size_t list_size = msg->header.size + - sizeof (struct GNUNET_ARM_ListResultMessage); + memcpy (&rslt[1], &msg[1], list_size); + + rslt_size = msg->header.size; + GNUNET_free (msg); + return rslt_size; +} + /** * Signal our client that we will start or stop the @@ -455,7 +494,7 @@ static void create_listen_socket (struct sockaddr *sa, socklen_t addr_len, struct ServiceList *sl) { - const static int on = 1; + static int on = 1; struct GNUNET_NETWORK_Handle *sock; struct ServiceListeningInfo *sli; @@ -566,7 +605,7 @@ handle_start (void *cls, struct GNUNET_SERVER_Client *client, const char *servicename; struct ServiceList *sl; uint16_t size; - + size = ntohs (message->size); size -= sizeof (struct GNUNET_MessageHeader); servicename = (const char *) &message[1]; @@ -652,17 +691,73 @@ handle_stop (void *cls, struct GNUNET_SERVER_Client *client, signal_result (client, servicename, GNUNET_ARM_PROCESS_ALREADY_DOWN); return; } -#if DEBUG_ARM GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending kill signal to service `%s', waiting for process to die.\n", servicename); -#endif + sl->killed_at = GNUNET_TIME_absolute_get (); if (0 != GNUNET_OS_process_kill (sl->proc, SIGTERM)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); sl->killing_client = client; GNUNET_SERVER_client_keep (client); } +/** + * Handle LIST-message. + * + * @param cls closure (always NULL) + * @param client identification of the client + * @param message the actual message + */ +static void +handle_list (void *cls, struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) +{ + struct GNUNET_ARM_ListResultMessage *msg; + size_t string_list_size; + size_t total_size; + struct ServiceList *sl; + uint16_t count; + + if (NULL == client) + return; + + count = 0; + string_list_size = 0; + /* first count the running processes get their name's size */ + for (sl = running_head; sl != NULL; sl = sl->next) + { + if (sl->proc != NULL) + { + string_list_size += strlen (sl->name); + string_list_size += strlen (sl->binary); + string_list_size += 4; + count++; + } + } + total_size = sizeof (struct GNUNET_ARM_ListResultMessage) + + string_list_size; + msg = GNUNET_malloc (total_size); + msg->header.size = total_size; + msg->header.type = GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT; + msg->count = count; + + char *pos = (char *)&msg[1]; + for (sl = running_head; sl != NULL; sl = sl->next) + { + if (sl->proc != NULL) + { + size_t s = strlen (sl->name) + strlen (sl->binary) + 4; + GNUNET_snprintf(pos, s, "%s (%s)", sl->name, sl->binary); + pos += s; + } + } + + GNUNET_SERVER_notify_transmit_ready (client, + msg->header.size, + GNUNET_TIME_UNIT_FOREVER_REL, + &write_list_result, msg); + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} /** * We are done with everything. Stop remaining @@ -698,46 +793,47 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct ServiceListeningInfo *sli; if (GNUNET_SCHEDULER_NO_TASK != child_restart_task) - { - GNUNET_SCHEDULER_cancel (child_restart_task); - child_restart_task = GNUNET_SCHEDULER_NO_TASK; - } + { + GNUNET_SCHEDULER_cancel (child_restart_task); + child_restart_task = GNUNET_SCHEDULER_NO_TASK; + } in_shutdown = GNUNET_YES; /* first, stop listening */ for (pos = running_head; NULL != pos; pos = pos->next) - { - while (NULL != (sli = pos->listen_head)) - { - GNUNET_CONTAINER_DLL_remove (pos->listen_head, - pos->listen_tail, sli); - if (sli->accept_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (sli->accept_task); - sli->accept_task = GNUNET_SCHEDULER_NO_TASK; - } - GNUNET_break (GNUNET_OK == - GNUNET_NETWORK_socket_close (sli->listen_socket)); - GNUNET_free (sli->service_addr); - GNUNET_free (sli); - } - } + { + while (NULL != (sli = pos->listen_head)) + { + GNUNET_CONTAINER_DLL_remove (pos->listen_head, + pos->listen_tail, sli); + if (sli->accept_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (sli->accept_task); + sli->accept_task = GNUNET_SCHEDULER_NO_TASK; + } + GNUNET_break (GNUNET_OK == + GNUNET_NETWORK_socket_close (sli->listen_socket)); + GNUNET_free (sli->service_addr); + GNUNET_free (sli); + } + } /* then, shutdown all existing service processes */ nxt = running_head; while (NULL != (pos = nxt)) + { + nxt = pos->next; + if (pos->proc != NULL) { - nxt = pos->next; - if (pos->proc != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping service `%s'\n", - pos->name); - if (0 != GNUNET_OS_process_kill (pos->proc, SIGTERM)) - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); - } - else - { - free_service (pos); - } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping service `%s'\n", + pos->name); + pos->killed_at = GNUNET_TIME_absolute_get (); + if (0 != GNUNET_OS_process_kill (pos->proc, SIGTERM)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + } + else + { + free_service (pos); } + } /* finally, should all service processes be already gone, terminate for real */ if (running_head == NULL) do_shutdown (); @@ -767,56 +863,53 @@ delayed_restart_task (void *cls, /* check for services that need to be restarted due to * configuration changes or because the last restart failed */ for (sl = running_head; NULL != sl; sl = sl->next) + { + if (NULL != sl->proc) + continue; + /* service is currently not running */ + if (GNUNET_TIME_absolute_get_remaining (sl->restart_at).rel_value == + 0) { - if (sl->proc == NULL) - { - /* service is currently not running */ - if (GNUNET_TIME_absolute_get_remaining (sl->restart_at).rel_value == - 0) - { - /* restart is now allowed */ - if (sl->is_default) - { - /* process should run by default, start immediately */ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Restarting service `%s'.\n"), sl->name); - start_process (sl); - } - else - { - /* process is run on-demand, ensure it is re-started if there is demand */ - for (sli = sl->listen_head; NULL != sli; sli = sli->next) - if (GNUNET_SCHEDULER_NO_TASK == sli->accept_task) - { - /* accept was actually paused, so start it again */ - sli->accept_task = - GNUNET_SCHEDULER_add_read_net - (GNUNET_TIME_UNIT_FOREVER_REL, sli->listen_socket, - &accept_connection, sli); - } - } - } - else - { - /* update calculation for earliest time to reactivate a service */ - lowestRestartDelay = - GNUNET_TIME_relative_min (lowestRestartDelay, - GNUNET_TIME_absolute_get_remaining - (sl->restart_at)); - } - } + /* restart is now allowed */ + if (sl->is_default) + { + /* process should run by default, start immediately */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Restarting service `%s'.\n"), sl->name); + start_process (sl); + } + else + { + /* process is run on-demand, ensure it is re-started if there is demand */ + for (sli = sl->listen_head; NULL != sli; sli = sli->next) + if (GNUNET_SCHEDULER_NO_TASK == sli->accept_task) + { + /* accept was actually paused, so start it again */ + sli->accept_task = + GNUNET_SCHEDULER_add_read_net + (GNUNET_TIME_UNIT_FOREVER_REL, sli->listen_socket, + &accept_connection, sli); + } + } } - if (lowestRestartDelay.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value) + else { -#if DEBUG_ARM - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Will restart process in %llums\n", - (unsigned long long) lowestRestartDelay.rel_value); -#endif - child_restart_task = - GNUNET_SCHEDULER_add_delayed_with_priority (lowestRestartDelay, - GNUNET_SCHEDULER_PRIORITY_IDLE, - &delayed_restart_task, NULL); + /* update calculation for earliest time to reactivate a service */ + lowestRestartDelay = + GNUNET_TIME_relative_min (lowestRestartDelay, + GNUNET_TIME_absolute_get_remaining + (sl->restart_at)); } + } + if (lowestRestartDelay.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Will restart process in %llums\n", + (unsigned long long) lowestRestartDelay.rel_value); + child_restart_task = + GNUNET_SCHEDULER_add_delayed_with_priority (lowestRestartDelay, + GNUNET_SCHEDULER_PRIORITY_IDLE, + &delayed_restart_task, NULL); + } } @@ -861,11 +954,11 @@ maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) next = pos->next; if (pos->proc == NULL) - { - if (GNUNET_YES == in_shutdown) - free_service (pos); - continue; - } + { + if (GNUNET_YES == in_shutdown) + free_service (pos); + continue; + } if ((GNUNET_SYSERR == (ret = GNUNET_OS_process_status (pos->proc, &statusType, &statusCode))) @@ -873,21 +966,28 @@ maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) || (statusType == GNUNET_OS_PROCESS_RUNNING))) continue; if (statusType == GNUNET_OS_PROCESS_EXITED) - { - statstr = _( /* process termination method */ "exit"); - statcode = statusCode; - } + { + statstr = _( /* process termination method */ "exit"); + statcode = statusCode; + } else if (statusType == GNUNET_OS_PROCESS_SIGNALED) - { - statstr = _( /* process termination method */ "signal"); - statcode = statusCode; - } + { + statstr = _( /* process termination method */ "signal"); + statcode = statusCode; + } else - { - statstr = _( /* process termination method */ "unknown"); - statcode = 0; - } - GNUNET_OS_process_close (pos->proc); + { + statstr = _( /* process termination method */ "unknown"); + statcode = 0; + } + if (0 != pos->killed_at.abs_value) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Service `%s' took %llu ms to terminate\n"), + pos->name, + GNUNET_TIME_absolute_get_duration (pos->killed_at).rel_value); + } + GNUNET_OS_process_destroy (pos->proc); pos->proc = NULL; if (NULL != pos->killing_client) { @@ -948,41 +1048,6 @@ maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** - * Transmit our shutdown acknowledgement to the client. - * - * @param cls the 'struct GNUNET_SERVER_Client' - * @param size number of bytes available in buf - * @param buf where to write the message - * @return number of bytes written - */ -static size_t -transmit_shutdown_ack (void *cls, size_t size, void *buf) -{ - struct GNUNET_SERVER_Client *client = cls; - struct GNUNET_ARM_ResultMessage *msg; - - if (size < sizeof (struct GNUNET_ARM_ResultMessage)) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Failed to transmit shutdown ACK.\n")); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return 0; /* client disconnected */ - } - /* Make the connection flushing for the purpose of ACK transmitting, - * needed on W32 to ensure that the message is even received, harmless - * on other platforms... */ - GNUNET_break (GNUNET_OK == GNUNET_SERVER_client_disable_corking (client)); - msg = (struct GNUNET_ARM_ResultMessage *) buf; - msg->header.type = htons (GNUNET_MESSAGE_TYPE_ARM_RESULT); - msg->header.size = htons (sizeof (struct GNUNET_ARM_ResultMessage)); - msg->status = htonl ((uint32_t) GNUNET_ARM_PROCESS_SHUTDOWN); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - GNUNET_SERVER_client_drop (client); - return sizeof (struct GNUNET_ARM_ResultMessage); -} - - -/** * Handler for SHUTDOWN message. * * @param cls closure (refers to service) @@ -994,11 +1059,6 @@ handle_shutdown (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { GNUNET_SCHEDULER_shutdown (); - GNUNET_SERVER_client_keep (client); - GNUNET_SERVER_notify_transmit_ready (client, - sizeof (struct GNUNET_ARM_ResultMessage), - GNUNET_TIME_UNIT_FOREVER_REL, - &transmit_shutdown_ack, client); GNUNET_SERVER_client_persist_ (client); } @@ -1114,6 +1174,8 @@ run (void *cls, struct GNUNET_SERVER_Handle *serv, {&handle_stop, NULL, GNUNET_MESSAGE_TYPE_ARM_STOP, 0}, {&handle_shutdown, NULL, GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN, sizeof (struct GNUNET_MessageHeader)}, + {&handle_list, NULL, GNUNET_MESSAGE_TYPE_ARM_LIST, + sizeof (struct GNUNET_MessageHeader)}, {NULL, NULL, 0, 0} }; char *defaultservices; @@ -1123,7 +1185,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *serv, cfg = c; server = serv; GNUNET_assert (serv != NULL); - GNUNET_SERVER_ignore_shutdown (serv, GNUNET_YES); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); child_death_task = @@ -1201,7 +1262,8 @@ main (int argc, char *const *argv) GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); ret = (GNUNET_OK == - GNUNET_SERVICE_run (argc, argv, "arm", GNUNET_YES, &run, NULL)) ? 0 : 1; + GNUNET_SERVICE_run (argc, argv, "arm", + GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN, &run, NULL)) ? 0 : 1; GNUNET_SIGNAL_handler_uninstall (shc_chld); shc_chld = NULL; GNUNET_DISK_pipe_close (sigpipe); diff --git a/src/arm/mockup-service.c b/src/arm/mockup-service.c index 1e97488..d989699 100644 --- a/src/arm/mockup-service.c +++ b/src/arm/mockup-service.c @@ -29,30 +29,6 @@ #include "gnunet_time_lib.h" -static size_t -transmit_shutdown_ack (void *cls, size_t size, void *buf) -{ - struct GNUNET_SERVER_Client *client = cls; - struct GNUNET_MessageHeader *msg; - - if (size < sizeof (struct GNUNET_MessageHeader)) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Failed to transmit shutdown ACK.\n")); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return 0; /* client disconnected */ - } - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting shutdown ACK.\n")); - - msg = (struct GNUNET_MessageHeader *) buf; - msg->type = htons (GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN); - msg->size = htons (sizeof (struct GNUNET_MessageHeader)); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - GNUNET_SERVER_client_drop (client); - return sizeof (struct GNUNET_MessageHeader); -} - /** * Handler for SHUTDOWN message. * @@ -64,14 +40,8 @@ static void handle_shutdown (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { - GNUNET_SERVER_client_keep (client); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Initiating shutdown as requested by client.\n")); - - GNUNET_SERVER_notify_transmit_ready (client, - sizeof (struct GNUNET_MessageHeader), - GNUNET_TIME_UNIT_FOREVER_REL, - &transmit_shutdown_ack, client); GNUNET_SERVER_client_persist_ (client); GNUNET_SCHEDULER_shutdown (); } @@ -87,7 +57,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, {NULL, NULL, 0, 0} }; /* process client requests */ - GNUNET_SERVER_ignore_shutdown (server, GNUNET_YES); GNUNET_SERVER_add_handlers (server, handlers); } diff --git a/src/arm/test_exponential_backoff.c b/src/arm/test_exponential_backoff.c index edd5cbf..77bd9e2 100644 --- a/src/arm/test_exponential_backoff.c +++ b/src/arm/test_exponential_backoff.c @@ -113,59 +113,47 @@ service_shutdown_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct ShutdownContext *shutdown_ctx = cls; - if ((msg == NULL) && (shutdown_ctx->confirmed != GNUNET_YES)) - { - /* Means the other side closed the connection and never confirmed a shutdown */ - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Service handle shutdown before ACK!\n"); - if (shutdown_ctx->cont != NULL) - shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR); - GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); - GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); - GNUNET_free (shutdown_ctx); - } - else if ((msg == NULL) && (shutdown_ctx->confirmed == GNUNET_YES)) - { + if (msg == NULL) + { #if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service shutdown complete.\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service shutdown complete.\n"); #endif - if (shutdown_ctx->cont != NULL) - shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_NO); - - GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); - GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); - GNUNET_free (shutdown_ctx); - } - else - { - GNUNET_assert (ntohs (msg->size) == - sizeof (struct GNUNET_MessageHeader)); - switch (ntohs (msg->type)) - { - case GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN: + if (shutdown_ctx->cont != NULL) + shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_NO); + + GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); + GNUNET_CLIENT_disconnect (shutdown_ctx->sock); + GNUNET_free (shutdown_ctx); + return; + } + GNUNET_assert (ntohs (msg->size) == + sizeof (struct GNUNET_MessageHeader)); + switch (ntohs (msg->type)) + { + case GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN: #if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received confirmation for service shutdown.\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received confirmation for service shutdown.\n"); #endif - shutdown_ctx->confirmed = GNUNET_YES; - GNUNET_CLIENT_receive (shutdown_ctx->sock, - &service_shutdown_handler, shutdown_ctx, - GNUNET_TIME_UNIT_FOREVER_REL); - break; - default: /* Fall through */ - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Service shutdown refused!\n"); - if (shutdown_ctx->cont != NULL) - shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_YES); - - GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); - GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); - GNUNET_free (shutdown_ctx); - break; - } - } + shutdown_ctx->confirmed = GNUNET_YES; + GNUNET_CLIENT_receive (shutdown_ctx->sock, + &service_shutdown_handler, shutdown_ctx, + GNUNET_TIME_UNIT_FOREVER_REL); + break; + default: /* Fall through */ + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Service shutdown refused!\n"); + if (shutdown_ctx->cont != NULL) + shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_YES); + + GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); + GNUNET_CLIENT_disconnect (shutdown_ctx->sock); + GNUNET_free (shutdown_ctx); + break; + } } + /** * Shutting down took too long, cancel receive and return error. * @@ -180,7 +168,7 @@ service_shutdown_cancel (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "service_shutdown_cancel called!\n"); shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR); - GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); + GNUNET_CLIENT_disconnect (shutdown_ctx->sock); GNUNET_free (shutdown_ctx); } @@ -205,7 +193,7 @@ write_shutdown (void *cls, size_t size, void *buf) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Failed to transmit shutdown request to client.\n")); shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR); - GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); + GNUNET_CLIENT_disconnect (shutdown_ctx->sock); GNUNET_free (shutdown_ctx); return 0; /* client disconnected */ } @@ -358,7 +346,7 @@ kill_task (void *cbData, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_assert (doNothingConnection != NULL); if (trialCount == 12) { - GNUNET_CLIENT_disconnect (doNothingConnection, GNUNET_NO); + GNUNET_CLIENT_disconnect (doNothingConnection); GNUNET_ARM_stop_service (arm, "do-nothing", TIMEOUT, &arm_notify_stop, NULL); ok = 0; |