#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]);
* @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);
}
/**
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);
}
* 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);
}
* 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;
}
{
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);
}
}
* 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.
*/
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
*
*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);
}