From 33890e032acc7c284e2ab82f2ccbc72ae8c2092f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 11 May 2010 08:26:46 +0000 Subject: [PATCH] arm fix --- src/arm/gnunet-service-arm.c | 12 +- src/arm/gnunet-service-manager.c | 699 +++++++++---------- src/arm/gnunet_service_arm_.h | 23 + src/statistics/test_statistics_api_data.conf | 4 +- src/util/server.c | 2 +- 5 files changed, 346 insertions(+), 394 deletions(-) diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c index a630f5b1a..f38b6b044 100644 --- a/src/arm/gnunet-service-arm.c +++ b/src/arm/gnunet-service-arm.c @@ -469,6 +469,7 @@ start_service (struct GNUNET_SERVER_Client *client, const char *servicename) signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN); return; } + stop_listening (servicename); sl = find_name (servicename); if (sl != NULL) { @@ -1047,11 +1048,14 @@ run (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting default services `%s'\n", defaultservices); #endif - pos = strtok (defaultservices, " "); - while (pos != NULL) + if (0 < strlen (defaultservices)) { - start_service (NULL, pos); - pos = strtok (NULL, " "); + pos = strtok (defaultservices, " "); + while (pos != NULL) + { + start_service (NULL, pos); + pos = strtok (NULL, " "); + } } GNUNET_free (defaultservices); } diff --git a/src/arm/gnunet-service-manager.c b/src/arm/gnunet-service-manager.c index 01ede9f33..c80c12aa5 100644 --- a/src/arm/gnunet-service-manager.c +++ b/src/arm/gnunet-service-manager.c @@ -35,111 +35,85 @@ #define DEBUG_SERVICE_MANAGER GNUNET_NO -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) -#define BUFFER_SIZE (63 * 1024) -#define REASON_CLIENT 1 -#define REASON_SERVICE 2 - -static char **defaultServicesList; -static int numDefaultServices = 0; -static const struct GNUNET_CONFIGURATION_Handle *cfg; -static struct GNUNET_SCHEDULER_Handle *scheduler; -struct StartedService -{ - const char *serviceName; - struct StartedService *next; -}; +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) -static struct StartedService *startedServices = NULL; +#define BUFFER_SIZE (63 * 1024) +#define REASON_CLIENT 1 -/* Functions prototypes */ -static void -receiveFromClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); -static void -receiveFromService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); +#define REASON_SERVICE 2 struct ServiceListeningInfo { struct ServiceListeningInfo *next; + struct ServiceListeningInfo *prev; - const char *serviceName; + + char *serviceName; + struct sockaddr *service_addr; + socklen_t service_addr_len; - struct sockaddr client_addr; - socklen_t client_addr_len; + struct GNUNET_NETWORK_Handle *listeningSocket; + GNUNET_SCHEDULER_TaskIdentifier acceptTask; }; -static struct ServiceListeningInfo *serviceListeningInfoList_head; -static struct ServiceListeningInfo *serviceListeningInfoList_tail; - /** * Information of the connection: client-arm-service */ -struct ServiceInfo +struct ForwardedConnection { - const char *serviceName; struct GNUNET_NETWORK_Handle *armClientSocket; + struct GNUNET_NETWORK_Handle *armServiceSocket; - struct sockaddr *service_addr; - socklen_t service_addr_len; + + struct ServiceListeningInfo *listen_info; + + char serviceBuffer[BUFFER_SIZE]; + char clientBuffer[BUFFER_SIZE]; - ssize_t clientBufferDataLength; + + char client_addr[32]; + char *clientBufferPos; - char serviceBuffer[BUFFER_SIZE]; - ssize_t serviceBufferDataLength; + char *serviceBufferPos; + GNUNET_SCHEDULER_TaskIdentifier clientReceivingTask; + GNUNET_SCHEDULER_TaskIdentifier serviceReceivingTask; - GNUNET_SCHEDULER_TaskIdentifier acceptTask; + + ssize_t clientBufferDataLength; + + ssize_t serviceBufferDataLength; + + socklen_t client_addr_len; + }; -static struct ServiceInfo * -newServiceInfo (const char *serviceName, struct sockaddr *service_addr, - socklen_t service_addr_len) -{ - struct ServiceInfo *serviceInfo = - GNUNET_malloc (sizeof (struct ServiceInfo)); - serviceInfo->serviceName = serviceName; - serviceInfo->service_addr = service_addr; - serviceInfo->service_addr_len = service_addr_len; - serviceInfo->serviceBufferPos = serviceInfo->serviceBuffer; - serviceInfo->clientBufferPos = serviceInfo->clientBuffer; - return serviceInfo; -} +static char **defaultServicesList; +static unsigned int numDefaultServices; -static struct ServiceListeningInfo * -newServiceListeningInfo (const char *serviceName, - struct sockaddr *sa, socklen_t service_addr_len, - struct GNUNET_NETWORK_Handle *listeningSocket) -{ - struct ServiceListeningInfo *serviceListeningInfo = - GNUNET_malloc (sizeof (struct ServiceListeningInfo)); +static const struct GNUNET_CONFIGURATION_Handle *cfg; - serviceListeningInfo->client_addr_len = - sizeof (serviceListeningInfo->client_addr); - serviceListeningInfo->serviceName = serviceName; - serviceListeningInfo->service_addr = sa; - serviceListeningInfo->service_addr_len = service_addr_len; - serviceListeningInfo->listeningSocket = listeningSocket; - GNUNET_CONTAINER_DLL_insert (serviceListeningInfoList_head, - serviceListeningInfoList_tail, - serviceListeningInfo); - return serviceListeningInfo; -} +static struct GNUNET_SCHEDULER_Handle *scheduler; + +static struct ServiceListeningInfo *serviceListeningInfoList_head; + +static struct ServiceListeningInfo *serviceListeningInfoList_tail; #if DEBUG_SERVICE_MANAGER static void printDefaultServicesList () { - int i; + unsigned int i; for (i = 0; i < numDefaultServices; i++) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Service: %s\n", defaultServicesList[i]); @@ -153,30 +127,34 @@ printDefaultServicesList () * @param services space separated string of default services */ static void -addDefaultServicesToList (char *services) +addDefaultServicesToList (const char *services) { - int i = 0; + unsigned int i = 0; char *token; + char *s; - /* How many services are there */ - while (services[i] != '\0') + if (strlen (services) == 0) + return; + s = GNUNET_strdup (services); + token = strtok (s, " "); + while (NULL != token) { - if (services[i] == ' ') - { - numDefaultServices++; - } - i++; + numDefaultServices++; + token = strtok (NULL, " "); } - numDefaultServices++; - defaultServicesList = GNUNET_malloc (numDefaultServices * sizeof (char *)); - token = strtok ((char *) services, " "); + GNUNET_free (s); + defaultServicesList = GNUNET_malloc (numDefaultServices * sizeof (char *)); i = 0; + s = GNUNET_strdup (services); + token = strtok (s, " "); while (NULL != token) { - defaultServicesList[i++] = token; + defaultServicesList[i++] = GNUNET_strdup (token); token = strtok (NULL, " "); } + GNUNET_free (s); + GNUNET_assert (i == numDefaultServices); } /** @@ -187,245 +165,217 @@ addDefaultServicesToList (char *services) static int isInDefaultList (const char *serviceName) { - int i; + unsigned int i; for (i = 0; i < numDefaultServices; i++) - { - if (strcmp (serviceName, defaultServicesList[i]) == 0) - return GNUNET_YES; - } - return GNUNET_NO; -} - - -static int -isServiceAlreadyStarted (const char *serviceName) -{ - struct StartedService *service; - service = startedServices; - while (NULL != service) - { - if (strcmp (service->serviceName, serviceName) == 0) - return GNUNET_OK; - service = service->next; - } + if (strcmp (serviceName, defaultServicesList[i]) == 0) + return GNUNET_YES; return GNUNET_NO; } static void -setStartedService (const char *serviceName) -{ - if (startedServices == NULL) - { - startedServices = GNUNET_malloc (sizeof (struct StartedService)); - startedServices->serviceName = GNUNET_strdup (serviceName); - startedServices->next = NULL; - } - else - { - struct StartedService *service = - GNUNET_malloc (sizeof (struct StartedService)); - service->serviceName = GNUNET_strdup (serviceName); - service->next = startedServices; - startedServices = service; - } -} - - -static void -closeClientAndServiceSockets (struct ServiceInfo *serviceInfo, int reason) +closeClientAndServiceSockets (struct ForwardedConnection *fc, int reason) { - if (NULL != serviceInfo->armClientSocket) + if (NULL != fc->armClientSocket) { if (0 != (REASON_SERVICE & reason)) - GNUNET_SCHEDULER_cancel (scheduler, serviceInfo->clientReceivingTask); + GNUNET_SCHEDULER_cancel (scheduler, fc->clientReceivingTask); if (GNUNET_SYSERR == - GNUNET_NETWORK_socket_close (serviceInfo->armClientSocket)) + GNUNET_NETWORK_socket_close (fc->armClientSocket)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close"); - serviceInfo->armClientSocket = NULL; + fc->armClientSocket = NULL; } - if (NULL != serviceInfo->armServiceSocket) + if (NULL != fc->armServiceSocket) { if (0 != (REASON_CLIENT & reason)) GNUNET_SCHEDULER_cancel (scheduler, - serviceInfo->serviceReceivingTask); + fc->serviceReceivingTask); if (GNUNET_SYSERR == - GNUNET_NETWORK_socket_close (serviceInfo->armServiceSocket)) + GNUNET_NETWORK_socket_close (fc->armServiceSocket)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close"); - serviceInfo->armServiceSocket = NULL; + fc->armServiceSocket = NULL; } - - GNUNET_free (serviceInfo); + GNUNET_free (fc->listen_info->serviceName); + GNUNET_free (fc->listen_info->service_addr); + GNUNET_free (fc->listen_info); + GNUNET_free (fc); } +static void +receiveFromClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); + +static void +receiveFromService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); + + /** * Forward messages sent from service to client * - * @param cls callback data, for the communication between client and service + * @param cls callback data, struct ForwardedConnection for the communication between client and service * @param tc context */ static void forwardToClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct ServiceInfo *serviceInfo = cls; + struct ForwardedConnection *fc = cls; ssize_t numberOfBytesSent; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) { /* Ignore shutdown signal, reschedule yourself */ GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, - serviceInfo->armClientSocket, - &forwardToClient, serviceInfo); + fc->armClientSocket, + &forwardToClient, fc); return; } /* Forwarding service response to client */ numberOfBytesSent = - GNUNET_NETWORK_socket_send (serviceInfo->armClientSocket, - serviceInfo->serviceBufferPos, - serviceInfo->serviceBufferDataLength); + GNUNET_NETWORK_socket_send (fc->armClientSocket, + fc->serviceBufferPos, + fc->serviceBufferDataLength); if ((numberOfBytesSent == GNUNET_SYSERR) || (numberOfBytesSent == 0)) { /* Error occured or connection closed by client */ - closeClientAndServiceSockets (serviceInfo, + closeClientAndServiceSockets (fc, (REASON_CLIENT & REASON_SERVICE)); return; } - else if (numberOfBytesSent < serviceInfo->serviceBufferDataLength) + else if (numberOfBytesSent < fc->serviceBufferDataLength) { /* Not all service data were sent to client */ - serviceInfo->serviceBufferPos += numberOfBytesSent; - serviceInfo->serviceBufferDataLength = - serviceInfo->serviceBufferDataLength - numberOfBytesSent; + fc->serviceBufferPos += numberOfBytesSent; + fc->serviceBufferDataLength -= numberOfBytesSent; /* Scheduling writing again for completing the remaining data to be sent */ GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, - serviceInfo->armClientSocket, - &forwardToClient, serviceInfo); + fc->armClientSocket, + &forwardToClient, fc); } else { /* Data completely sent */ - serviceInfo->serviceBufferPos = serviceInfo->serviceBuffer; + fc->serviceBufferPos = fc->serviceBuffer; } /* Now we are ready to receive more data, rescheduling receiving from Service */ - serviceInfo->serviceReceivingTask = + fc->serviceReceivingTask = GNUNET_SCHEDULER_add_read_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, - serviceInfo->armServiceSocket, - &receiveFromService, serviceInfo); + fc->armServiceSocket, + &receiveFromService, fc); } /** * Receive service messages sent by the service and forward it to client * - * @param cls callback data, serviceInfo struct for the communication between client and service + * @param cls callback data, struct ForwardedConnection for the communication between client and service * @param tc context */ static void receiveFromService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - - struct ServiceInfo *serviceInfo = cls; + struct ForwardedConnection *fc = cls; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) { /* Neglect shutdown signal, reschedule yourself */ - serviceInfo->serviceReceivingTask = + fc->serviceReceivingTask = GNUNET_SCHEDULER_add_read_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, - serviceInfo->armServiceSocket, - &receiveFromService, serviceInfo); + fc->armServiceSocket, + &receiveFromService, fc); return; } - serviceInfo->serviceBufferDataLength = - GNUNET_NETWORK_socket_recv (serviceInfo->armServiceSocket, - serviceInfo->serviceBuffer, BUFFER_SIZE); + fc->serviceBufferDataLength = + GNUNET_NETWORK_socket_recv (fc->armServiceSocket, + fc->serviceBuffer, BUFFER_SIZE); - if (serviceInfo->serviceBufferDataLength <= 0) + if (fc->serviceBufferDataLength <= 0) { /* The service has closed the connection or an error occured */ - if (serviceInfo->serviceBufferDataLength == 0) - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - _("Service `%s' closed connection! \n"), - serviceInfo->serviceName); + if (fc->serviceBufferDataLength == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + _("Service `%s' closed connection! \n"), + fc->listen_info->serviceName); + } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Error receiving from service:%d\n"), errno); + _("Error receiving from service: %s\n"), + STRERROR (errno)); } - closeClientAndServiceSockets (serviceInfo, REASON_SERVICE); + closeClientAndServiceSockets (fc, REASON_SERVICE); return; } /* Forwarding Service data to Client */ GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, - serviceInfo->armClientSocket, - &forwardToClient, serviceInfo); + fc->armClientSocket, + &forwardToClient, fc); } /** * Forward client message to service * - * @param cls callback data, serviceInfo struct for the communication between client and service + * @param cls callback data, struct ForwardedConnection for the communication between client and service * @param tc context */ static void forwardToService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct ServiceInfo *serviceInfo = cls; + struct ForwardedConnection *fc = cls; ssize_t numberOfBytesSent; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) { - /* Neglect shutdown signal, reschedule yourself */ + /* Neglect shutdown signal, reschedule ourself */ GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, - serviceInfo->armServiceSocket, - &forwardToService, serviceInfo); + fc->armServiceSocket, + &forwardToService, fc); return; } /* Forwarding client's message to service */ numberOfBytesSent = - GNUNET_NETWORK_socket_send (serviceInfo->armServiceSocket, - serviceInfo->clientBufferPos, - serviceInfo->clientBufferDataLength); + GNUNET_NETWORK_socket_send (fc->armServiceSocket, + fc->clientBufferPos, + fc->clientBufferDataLength); if ((numberOfBytesSent == GNUNET_SYSERR) || (numberOfBytesSent == 0)) { /* Error occured or connection closed by service */ - closeClientAndServiceSockets (serviceInfo, + closeClientAndServiceSockets (fc, (REASON_CLIENT & REASON_SERVICE)); return; } - else if (numberOfBytesSent < serviceInfo->clientBufferDataLength) + if (numberOfBytesSent < fc->clientBufferDataLength) { /* Not all client data were sent to the service */ - serviceInfo->clientBufferPos += numberOfBytesSent; - serviceInfo->clientBufferDataLength = - serviceInfo->clientBufferDataLength - numberOfBytesSent; + fc->clientBufferPos += numberOfBytesSent; + fc->clientBufferDataLength -= numberOfBytesSent; /* Scheduling writing again for completing the remaining data to be sent */ GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, - serviceInfo->armServiceSocket, - &forwardToService, serviceInfo); + fc->armServiceSocket, + &forwardToService, fc); } else { /* Data completely sent */ - serviceInfo->clientBufferPos = serviceInfo->clientBuffer; + fc->clientBufferPos = fc->clientBuffer; } /* Now, we are ready to receive more data. Rescheduling the receiving from client */ - serviceInfo->clientReceivingTask = + fc->clientReceivingTask = GNUNET_SCHEDULER_add_read_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, - serviceInfo->armClientSocket, - &receiveFromClient, serviceInfo); + fc->armClientSocket, + &receiveFromClient, fc); } @@ -434,48 +384,49 @@ forwardToService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * Message sent from client to service (faked by ARM, since it's the first connection), * ARM will receive the message and forward it to the running service * - * @param cls callback data, serviceInfo struct for the communication between client and service + * @param cls callback data, struct ForwardedConnection for the communication between client and service * @param tc context */ static void receiveFromClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct ServiceInfo *serviceInfo = cls; + struct ForwardedConnection *fc = cls; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) { - /* Neglect the shutdown signal, schedule yourself */ - serviceInfo->clientReceivingTask = + /* Neglect the shutdown signal, schedule ourselves */ + fc->clientReceivingTask = GNUNET_SCHEDULER_add_read_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, - serviceInfo->armClientSocket, - &receiveFromClient, serviceInfo); + fc->armClientSocket, + &receiveFromClient, fc); return; } /* Receive client's message */ - serviceInfo->clientBufferDataLength = - GNUNET_NETWORK_socket_recv (serviceInfo->armClientSocket, - serviceInfo->clientBuffer, BUFFER_SIZE); + fc->clientBufferDataLength = + GNUNET_NETWORK_socket_recv (fc->armClientSocket, + fc->clientBuffer, BUFFER_SIZE); - if (serviceInfo->clientBufferDataLength <= 0) + if (fc->clientBufferDataLength <= 0) { /* The client has closed the connection or and error occured */ - if (serviceInfo->clientBufferDataLength == 0) + if (fc->clientBufferDataLength == 0) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Client closed connection with service:`%s'\n"), - serviceInfo->serviceName); + fc->listen_info->serviceName); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Error receiving from client!:%d \n"), errno); - closeClientAndServiceSockets (serviceInfo, REASON_CLIENT); + _("Error receiving from client: %s \n"), + STRERROR (errno)); + closeClientAndServiceSockets (fc, REASON_CLIENT); return; } /* Forwarding request to service */ GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, - serviceInfo->armServiceSocket, - &forwardToService, serviceInfo); + fc->armServiceSocket, + &forwardToService, fc); } @@ -483,21 +434,21 @@ receiveFromClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * ARM connects to the just created service, * starts the processes for relaying messages between the client and the service * - * @param cls callback data, serviceInfo struct for the communication between client and service + * @param cls callback data, struct ForwardedConnection for the communication between client and service * @param tc context */ static void connectToService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct ServiceInfo *serviceInfo = cls; + struct ForwardedConnection *fc = cls; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) { /* Service is not up. Unable to proceed */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to start service `%s': timeout\n"), - serviceInfo->serviceName); - closeClientAndServiceSockets (serviceInfo, + fc->listen_info->serviceName); + closeClientAndServiceSockets (fc, (REASON_CLIENT & REASON_SERVICE)); return; } @@ -505,80 +456,72 @@ connectToService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to start service `%s': shutdown\n"), - serviceInfo->serviceName); - closeClientAndServiceSockets (serviceInfo, + fc->listen_info->serviceName); + closeClientAndServiceSockets (fc, (REASON_CLIENT & REASON_SERVICE)); return; } GNUNET_break (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Service `%s' started\n"), - serviceInfo->serviceName); - - /* Now service is up and running, connect to it */ - serviceInfo->armServiceSocket = - GNUNET_NETWORK_socket_create (serviceInfo->service_addr->sa_family, + fc->listen_info->serviceName); + fc->armServiceSocket = + GNUNET_NETWORK_socket_create (fc->listen_info->service_addr->sa_family, SOCK_STREAM, 0); - if (NULL == serviceInfo->armServiceSocket) + if (NULL == fc->armServiceSocket) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("Unable to start service `%s': failed to create socket\n"), - serviceInfo->serviceName); - closeClientAndServiceSockets (serviceInfo, + _ ("Unable to start service `%s': %s\n"), + fc->listen_info->serviceName, + STRERROR (errno)); + closeClientAndServiceSockets (fc, (REASON_CLIENT & REASON_SERVICE)); return; } - if ((GNUNET_SYSERR == - GNUNET_NETWORK_socket_connect (serviceInfo->armServiceSocket, - serviceInfo->service_addr, - serviceInfo->service_addr_len)) + GNUNET_NETWORK_socket_connect (fc->armServiceSocket, + fc->listen_info->service_addr, + fc->listen_info->service_addr_len)) && (EINPROGRESS != errno)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to start service `%s': failed to connect\n"), - serviceInfo->serviceName); - closeClientAndServiceSockets (serviceInfo, + fc->listen_info->serviceName); + closeClientAndServiceSockets (fc, (REASON_CLIENT & REASON_SERVICE)); return; } - /* Handling requests from client to service */ - serviceInfo->clientReceivingTask = - GNUNET_SCHEDULER_add_read_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, - serviceInfo->armClientSocket, - &receiveFromClient, serviceInfo); - - /* Handling service responses to client */ - serviceInfo->serviceReceivingTask = - GNUNET_SCHEDULER_add_read_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, - serviceInfo->armServiceSocket, - &receiveFromService, serviceInfo); + fc->clientReceivingTask = + GNUNET_SCHEDULER_add_read_net (scheduler, + GNUNET_TIME_UNIT_FOREVER_REL, + fc->armClientSocket, + &receiveFromClient, fc); + fc->serviceReceivingTask = + GNUNET_SCHEDULER_add_read_net (scheduler, + GNUNET_TIME_UNIT_FOREVER_REL, + fc->armServiceSocket, + &receiveFromService, fc); } -static void -stopServiceListeningSockets (struct ServiceListeningInfo - *serviceListeningInfo) +void stop_listening (const char *serviceName) { - struct ServiceListeningInfo *pos = serviceListeningInfoList_head; - struct ServiceListeningInfo *tmp; + struct ServiceListeningInfo *pos; + struct ServiceListeningInfo *next; - while (NULL != pos) + next = serviceListeningInfoList_head; + while (NULL != (pos = next)) { - if ((strcmp (pos->serviceName, serviceListeningInfo->serviceName) == 0) - && (pos != serviceListeningInfo)) - { - GNUNET_SCHEDULER_cancel (scheduler, pos->acceptTask); - GNUNET_NETWORK_socket_close (pos->listeningSocket); - tmp = pos; - pos = pos->next; - GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head, - serviceListeningInfoList_tail, tmp); - GNUNET_free (tmp->service_addr); - GNUNET_free (tmp); - continue; - } - pos = pos->next; + next = pos->next; + if (strcmp (pos->serviceName, serviceName) != 0) + continue; + GNUNET_SCHEDULER_cancel (scheduler, pos->acceptTask); + GNUNET_NETWORK_socket_close (pos->listeningSocket); + GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head, + serviceListeningInfoList_tail, + pos); + GNUNET_free (pos->serviceName); + GNUNET_free (pos->service_addr); + GNUNET_free (pos); } } @@ -587,136 +530,124 @@ stopServiceListeningSockets (struct ServiceListeningInfo * First connection has come to the listening socket associated with the service, * create the service in order to relay the incoming connection to it * - * @param cls callback data, serviceInfo struct for the communication between client and service + * @param cls callback data, struct ServiceListeningInfo describing a listen socket * @param tc context */ static void acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ServiceListeningInfo *serviceListeningInfo = cls; - struct ServiceInfo *serviceInfo; + struct ForwardedConnection *fc; + serviceListeningInfo->acceptTask = GNUNET_SCHEDULER_NO_TASK; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; - - if ((NULL == startedServices) - || (GNUNET_NO == - isServiceAlreadyStarted (serviceListeningInfo->serviceName))) + fc = GNUNET_malloc (sizeof (struct ForwardedConnection)); + fc->listen_info = serviceListeningInfo; + fc->serviceBufferPos = fc->serviceBuffer; + fc->clientBufferPos = fc->clientBuffer; + fc->client_addr_len = sizeof (fc->client_addr); + fc->armClientSocket = GNUNET_NETWORK_socket_accept (serviceListeningInfo->listeningSocket, + (struct sockaddr*) fc->client_addr, + &fc->client_addr_len); + if (NULL == fc->armClientSocket) { - /* First request to receive at all, or first request to connect to that service */ - /* Accept client's connection */ - serviceInfo = - newServiceInfo (serviceListeningInfo->serviceName, - serviceListeningInfo->service_addr, - serviceListeningInfo->service_addr_len); - serviceInfo->armClientSocket = - GNUNET_NETWORK_socket_accept (serviceListeningInfo->listeningSocket, - &(serviceListeningInfo->client_addr), - &(serviceListeningInfo-> - client_addr_len)); - if (NULL == serviceInfo->armClientSocket) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("Unable to accept connection for service `%s': Invalid socket\n"), - serviceListeningInfo->serviceName); - return; - } - - - /* - * Close listening socket, start service, - * and stop all listening sockets associated with that service - * and free their correspondent ServiceInfo objects - */ - GNUNET_NETWORK_socket_close (serviceListeningInfo->listeningSocket); - start_service (NULL, serviceListeningInfo->serviceName); - setStartedService (serviceListeningInfo->serviceName); - stopServiceListeningSockets (serviceListeningInfo); - - /* Notify me when the service is up and running */ - GNUNET_CLIENT_service_test (scheduler, - serviceListeningInfo->serviceName, cfg, - TIMEOUT, &connectToService, serviceInfo); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Unable to accept connection for service `%s': %s\n"), + serviceListeningInfo->serviceName, + STRERROR (errno)); + GNUNET_free (fc); + serviceListeningInfo->acceptTask = + GNUNET_SCHEDULER_add_read_net (scheduler, + GNUNET_TIME_UNIT_FOREVER_REL, + serviceListeningInfo->listeningSocket, + &acceptConnection, + serviceListeningInfo); + return; } + GNUNET_NETWORK_socket_close (serviceListeningInfo->listeningSocket); + GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head, + serviceListeningInfoList_tail, + serviceListeningInfo); + start_service (NULL, serviceListeningInfo->serviceName); + GNUNET_CLIENT_service_test (scheduler, + serviceListeningInfo->serviceName, + cfg, + TIMEOUT, + &connectToService, + fc); } /** - * Creating a listening socket for each of the service's addresses and wait for the first incoming connection to it + * Creating a listening socket for each of the service's addresses and + * wait for the first incoming connection to it * - * @param addrs list of addresses associated with the service - * @param addr_lens list containing length for each of the addresses in addrs - * @param numOfAddresses length of the addr_lens array + * @param sa address associated with the service + * @param addr_len length of sa * @param serviceName the name of the service in question */ static void -createListeningSocket (struct sockaddr **addrs, socklen_t * addr_lens, - int numOfAddresses, char *serviceName) +createListeningSocket (struct sockaddr *sa, + socklen_t addr_len, + const char *serviceName) { - int i; struct GNUNET_NETWORK_Handle *socket; - struct sockaddr *sa; - socklen_t addr_len; struct ServiceListeningInfo *serviceListeningInfo; - for (i = 0; i < numOfAddresses; i++) + switch (sa->sa_family) { - sa = addrs[i]; - addr_len = addr_lens[i]; - switch (sa->sa_family) - { - case AF_INET: - socket = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0); - break; - case AF_INET6: - socket = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); - break; - default: - socket = NULL; - break; - } - if (NULL == socket) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unable to create socket for service %s", serviceName); - continue; - } - - /* Bind */ - if (GNUNET_NETWORK_socket_bind - (socket, (const struct sockaddr *) sa, addr_len) != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Unable to bind listening socket for service `%s'\n"), - serviceName); - continue; - } - - /* Listen */ - if (GNUNET_NETWORK_socket_listen (socket, 5) != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Error listening socket for service `%s'\n"), - serviceName); - } - - serviceListeningInfo = - newServiceListeningInfo (serviceName, sa, addr_len, socket); - serviceListeningInfo->listeningSocket = socket; - serviceListeningInfo->serviceName = serviceName; - serviceListeningInfo->service_addr = sa; - serviceListeningInfo->service_addr_len = addr_len; - - /* Wait for the first incoming connection */ - serviceListeningInfo->acceptTask = - GNUNET_SCHEDULER_add_read_net (scheduler, - GNUNET_TIME_UNIT_FOREVER_REL, socket, - &acceptConnection, - serviceListeningInfo); + case AF_INET: + socket = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0); + break; + case AF_INET6: + socket = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); + break; + default: + socket = NULL; + break; + } + if (NULL == socket) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to create socket for service %s", serviceName); + GNUNET_free (sa); + return; + } + if (GNUNET_NETWORK_socket_bind + (socket, (const struct sockaddr *) sa, addr_len) != GNUNET_OK) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Unable to bind listening socket for service `%s'\n"), + serviceName); + GNUNET_free (sa); + return; + } + if (GNUNET_NETWORK_socket_listen (socket, 5) != GNUNET_OK) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Error listening socket for service `%s'\n"), + serviceName); + GNUNET_NETWORK_socket_close (socket); + GNUNET_free (sa); + return; } + serviceListeningInfo = GNUNET_malloc (sizeof (struct ServiceListeningInfo)); + serviceListeningInfo->serviceName = GNUNET_strdup (serviceName); + serviceListeningInfo->service_addr = sa; + serviceListeningInfo->service_addr_len = addr_len; + serviceListeningInfo->listeningSocket = socket; + serviceListeningInfo->acceptTask = + GNUNET_SCHEDULER_add_read_net (scheduler, + GNUNET_TIME_UNIT_FOREVER_REL, socket, + &acceptConnection, + serviceListeningInfo); + GNUNET_CONTAINER_DLL_insert (serviceListeningInfoList_head, + serviceListeningInfoList_tail, + serviceListeningInfo); } + /** * Callback function, checks whether the current tokens are representing a service, * gets its addresses and create listening socket for it. @@ -728,37 +659,30 @@ createListeningSocket (struct sockaddr **addrs, socklen_t * addr_lens, */ static void checkPortNumberCB (void *cls, - const char *section, const char *option, const char *value) + const char *section, + const char *option, + const char *value) { - /* The service shouldn't be a default service */ - if ((strcmp (section, "arm") != 0) - && (strcmp (option, "PORT") == 0) - && (isInDefaultList (section) == GNUNET_NO)) - { - /* then the section is representing a service */ - struct sockaddr **addrs; - socklen_t *addr_lens; - int ret; - - ret = - GNUNET_SERVICE_get_server_addresses (section, cfg, &addrs, - &addr_lens); - if (ret == GNUNET_SYSERR) - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Unable to resolve host name for service `%s'\n"), - section); - else if (ret != GNUNET_NO) - { - /* Addresses found for service */ - createListeningSocket (addrs, addr_lens, ret, (char *) section); - } - else - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("No addresses for service `%s' in configuration\n"), - section); - } + struct sockaddr **addrs; + socklen_t *addr_lens; + int ret; + unsigned int i; + + if ( (strcmp (section, "arm") == 0) || + (strcmp (option, "PORT") != 0) || + (isInDefaultList (section) == GNUNET_YES) ) + return; + if (0 >= (ret = GNUNET_SERVICE_get_server_addresses (section, cfg, &addrs, + &addr_lens))) + return; + /* this will free (or capture) addrs[i] for i in 0..ret */ + for (i = 0; i < ret; i++) + createListeningSocket (addrs[i], addr_lens[i], section); + GNUNET_free (addrs); + GNUNET_free (addr_lens); } + /** * Entry point to the Service Manager * @@ -770,18 +694,17 @@ prepareServices (const struct GNUNET_CONFIGURATION_Handle *configurationHandle, struct GNUNET_SCHEDULER_Handle *sched) { char *defaultServicesString; + scheduler = sched; cfg = configurationHandle; - /* Split the default services into a list */ GNUNET_CONFIGURATION_get_value_string (cfg, "arm", "DEFAULTSERVICES", &defaultServicesString); addDefaultServicesToList (defaultServicesString); - + GNUNET_free (defaultServicesString); #if DEBUG_SERVICE_MANAGER printDefaultServicesList (); #endif - /* Spot the services from the configuration and create a listening socket for each */ GNUNET_CONFIGURATION_iterate (cfg, &checkPortNumberCB, NULL); } diff --git a/src/arm/gnunet_service_arm_.h b/src/arm/gnunet_service_arm_.h index fe31b688c..d44f22864 100644 --- a/src/arm/gnunet_service_arm_.h +++ b/src/arm/gnunet_service_arm_.h @@ -1,3 +1,23 @@ +/* + This file is part of GNUnet. + (C) 2010 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + /** * @file arm/gnunet_service_arm_.h * @brief function prototypes for gnunet_service_arm.c, and gnunet_service_manager.c @@ -9,6 +29,9 @@ void start_service (struct GNUNET_SERVER_Client *client, const char *servicename); + +void stop_listening (const char *serviceName); + void prepareServices (const struct GNUNET_CONFIGURATION_Handle *configurationHandle, struct GNUNET_SCHEDULER_Handle *sched); diff --git a/src/statistics/test_statistics_api_data.conf b/src/statistics/test_statistics_api_data.conf index 7f69a74ad..41cfd9596 100644 --- a/src/statistics/test_statistics_api_data.conf +++ b/src/statistics/test_statistics_api_data.conf @@ -7,4 +7,6 @@ PORT = 22353 [arm] PORT = 22354 -DEFAULTSERVICES = +DEFAULTSERVICES = +# DEBUG = YES + diff --git a/src/util/server.c b/src/util/server.c index e34897f76..832f4ed58 100644 --- a/src/util/server.c +++ b/src/util/server.c @@ -480,7 +480,7 @@ GNUNET_SERVER_create (struct GNUNET_SCHEDULER_Handle *sched, if (j == 0) { if (errno != 0) - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); GNUNET_free (lsocks); lsocks = NULL; } -- 2.25.1