$(GN_LIBINTL)
gnunet_service_arm_SOURCES = \
- gnunet-service-arm.c gnunet_service_arm_.h \
- gnunet-service-manager.c
+ gnunet-service-arm.c gnunet-service-arm.h \
+ gnunet-service-arm_interceptor.c
gnunet_service_arm_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
$(GN_LIBINTL)
#include "gnunet_protocols.h"
#include "gnunet_service_lib.h"
#include "gnunet_signal_lib.h"
-#include "gnunet_service_arm_.h"
+#include "gnunet-service-arm.h"
#include "arm.h"
--- /dev/null
+/*
+ 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
+ * @author Safey Abdel Halim
+ */
+
+#ifndef GNUNET_SERVICE_ARM__H
+#define GNUNET_SERVICE_ARM__H
+
+void start_service (struct GNUNET_SERVER_Client *client,
+ const char *servicename);
+
+/**
+ * Stop listening for connections to a service.
+ *
+ * @param serviceName name of service to stop listening for
+ * @return GNUNET_OK if we stopped to listen, GNUNET_NO if we were
+ * not listening
+ */
+int stop_listening (const char *serviceName);
+
+void prepareServices (const struct GNUNET_CONFIGURATION_Handle
+ *configurationHandle,
+ struct GNUNET_SCHEDULER_Handle *sched);
+
+#endif
--- /dev/null
+/*
+ This file is part of GNUnet.
+ (C) 2009, 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_interceptor.c
+ * @brief listen to incoming connections from clients to services,
+ * start services for which incoming an incoming connection occur,
+ * and relay communication between the client and the service for
+ * that first incoming connection.
+ *
+ * @author Safey Abdel Halim
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_service_lib.h"
+#include "gnunet_configuration_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_client_lib.h"
+#include "gnunet_container_lib.h"
+#include "gnunet-service-arm.h"
+
+
+#define DEBUG_SERVICE_MANAGER GNUNET_NO
+
+#define BUFFER_SIZE (64 * 1024)
+
+/**
+ * Problem forwarding from client to service.
+ */
+#define REASON_CLIENT_TO_SERVICE 1
+
+/**
+ * Problem forwarding from service to client.
+ */
+#define REASON_SERVICE_TO_CLIENT 2
+
+/**
+ * Problem in both directions.
+ */
+#define REASON_ERROR 3
+
+
+/**
+ *
+ */
+struct ServiceListeningInfo
+{
+ /**
+ * This is a linked list.
+ */
+ struct ServiceListeningInfo *next;
+
+ /**
+ * This is a linked list.
+ */
+ struct ServiceListeningInfo *prev;
+
+ /**
+ * Name of the service being forwarded.
+ */
+ char *serviceName;
+
+ /**
+ *
+ */
+ struct sockaddr *service_addr;
+
+ /**
+ *
+ */
+ socklen_t service_addr_len;
+
+ /**
+ * Our listening socket.
+ */
+ struct GNUNET_NETWORK_Handle *listeningSocket;
+
+ /**
+ * Task doing the accepting.
+ */
+ GNUNET_SCHEDULER_TaskIdentifier acceptTask;
+};
+
+/**
+ * Information of the connection: client-arm-service
+ */
+struct ForwardedConnection
+{
+ /**
+ *
+ */
+ struct GNUNET_NETWORK_Handle *armClientSocket;
+
+ /**
+ *
+ */
+ struct GNUNET_NETWORK_Handle *armServiceSocket;
+
+ /**
+ *
+ */
+ struct ServiceListeningInfo *listen_info;
+
+ /**
+ *
+ */
+ char service_to_client_buffer[BUFFER_SIZE];
+
+ /**
+ *
+ */
+ char client_to_service_buffer[BUFFER_SIZE];
+
+ /**
+ *
+ */
+ char client_addr[32];
+
+ /**
+ *
+ */
+ const char *client_to_service_bufferPos;
+
+ /**
+ *
+ */
+ const char *service_to_client_bufferPos;
+
+ /**
+ * Timeout for forwarding.
+ */
+ struct GNUNET_TIME_Absolute timeout;
+
+ /**
+ * Current back-off value.
+ */
+ struct GNUNET_TIME_Relative back_off;
+
+ /**
+ * Task that tries to initiate forwarding.
+ */
+ GNUNET_SCHEDULER_TaskIdentifier start_task;
+
+ /**
+ *
+ */
+ GNUNET_SCHEDULER_TaskIdentifier client_to_service_task;
+
+ /**
+ *
+ */
+ GNUNET_SCHEDULER_TaskIdentifier service_to_client_task;
+
+ /**
+ *
+ */
+ ssize_t client_to_service_bufferDataLength;
+
+ /**
+ *
+ */
+ ssize_t service_to_client_bufferDataLength;
+
+ /**
+ *
+ */
+ socklen_t client_addr_len;
+
+ /**
+ * Have we ever successfully written data to the service?
+ */
+ int first_write_done;
+};
+
+
+/**
+ * Array with the names of the services started by default.
+ */
+static char **defaultServicesList;
+
+/**
+ * Size of the defaultServicesList array.
+ */
+static unsigned int numDefaultServices;
+
+/**
+ *
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ *
+ */
+static struct GNUNET_SCHEDULER_Handle *scheduler;
+
+/**
+ *
+ */
+static struct ServiceListeningInfo *serviceListeningInfoList_head;
+
+/**
+ *
+ */
+static struct ServiceListeningInfo *serviceListeningInfoList_tail;
+
+
+/**
+ * Put the default services represented by a space separated string into an array of strings
+ *
+ * @param services space separated string of default services
+ */
+static void
+addDefaultServicesToList (const char *services)
+{
+ unsigned int i;
+ const char *token;
+ char *s;
+
+ if (strlen (services) == 0)
+ return;
+ s = GNUNET_strdup (services);
+ token = strtok (s, " ");
+ while (NULL != token)
+ {
+ numDefaultServices++;
+ token = strtok (NULL, " ");
+ }
+ GNUNET_free (s);
+
+ defaultServicesList = GNUNET_malloc (numDefaultServices * sizeof (char *));
+ i = 0;
+ s = GNUNET_strdup (services);
+ token = strtok (s, " ");
+ while (NULL != token)
+ {
+ defaultServicesList[i++] = GNUNET_strdup (token);
+ token = strtok (NULL, " ");
+ }
+ GNUNET_free (s);
+ GNUNET_assert (i == numDefaultServices);
+}
+
+/**
+ * Checks whether the serviceName is in the list of default services
+ *
+ * @param serviceName string to check its existance in the list
+ * @return GNUNET_YES if the service is started by default
+ */
+static int
+isInDefaultList (const char *serviceName)
+{
+ unsigned int i;
+ for (i = 0; i < numDefaultServices; i++)
+ if (strcmp (serviceName, defaultServicesList[i]) == 0)
+ return GNUNET_YES;
+ return GNUNET_NO;
+}
+
+
+/**
+ * Close forwarded connection (partial or full).
+ *
+ * @param fc connection to close
+ * @param reason which direction to close
+ */
+static void
+closeClientAndServiceSockets (struct ForwardedConnection *fc,
+ int reason)
+{
+ if (0 != (REASON_SERVICE_TO_CLIENT & reason))
+ {
+#if DEBUG_SERVICE_MANAGER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Stopping forwarding from service to client\n",
+ fc->listen_info->serviceName);
+#endif
+ if (fc->service_to_client_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (scheduler, fc->service_to_client_task);
+ fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ if (fc->armClientSocket != NULL)
+ GNUNET_NETWORK_socket_shutdown (fc->armClientSocket,
+ SHUT_WR);
+ if (fc->armServiceSocket != NULL)
+ GNUNET_NETWORK_socket_shutdown (fc->armServiceSocket,
+ SHUT_RD);
+ }
+ if (0 != (REASON_CLIENT_TO_SERVICE & reason))
+ {
+#if DEBUG_SERVICE_MANAGER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Stopping forwarding from client to service\n",
+ fc->listen_info->serviceName);
+#endif
+ if (fc->client_to_service_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (scheduler,
+ fc->client_to_service_task);
+ fc->client_to_service_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ if (fc->armClientSocket != NULL)
+ GNUNET_NETWORK_socket_shutdown (fc->armClientSocket,
+ SHUT_RD);
+ if (fc->armServiceSocket != NULL)
+ GNUNET_NETWORK_socket_shutdown (fc->armServiceSocket,
+ SHUT_WR);
+ }
+ if ( (fc->client_to_service_task != GNUNET_SCHEDULER_NO_TASK) ||
+ (fc->service_to_client_task != GNUNET_SCHEDULER_NO_TASK) )
+ return;
+#if DEBUG_SERVICE_MANAGER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Closing forwarding connection (done with both directions)\n");
+#endif
+ if (fc->start_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (scheduler,
+ fc->start_task);
+ if ( (NULL != fc->armClientSocket) &&
+ (GNUNET_SYSERR ==
+ GNUNET_NETWORK_socket_close (fc->armClientSocket)) )
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close");
+ if ( (NULL != fc->armServiceSocket) &&
+ (GNUNET_SYSERR ==
+ GNUNET_NETWORK_socket_close (fc->armServiceSocket)) )
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close");
+ 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);
+
+
+/**
+ *
+ */
+static void
+start_forwarding (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+
+/**
+ * Forward messages sent from service to client
+ *
+ * @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 ForwardedConnection *fc = cls;
+ ssize_t numberOfBytesSent;
+
+ fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
+ if (GNUNET_YES != GNUNET_NETWORK_fdset_isset (tc->write_ready,
+ fc->armClientSocket))
+ {
+ fc->service_to_client_task =
+ GNUNET_SCHEDULER_add_write_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ fc->armClientSocket,
+ &forwardToClient, fc);
+ return;
+ }
+ /* Forwarding service response to client */
+ numberOfBytesSent =
+ GNUNET_NETWORK_socket_send (fc->armClientSocket,
+ fc->service_to_client_bufferPos,
+ fc->service_to_client_bufferDataLength);
+ if (numberOfBytesSent <= 0)
+ {
+ if ( (errno != EPIPE) &&
+ (errno != ECONNRESET) )
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to forward %u bytes of data to client: %s\n",
+ fc->service_to_client_bufferDataLength,
+ STRERROR (errno));
+ closeClientAndServiceSockets (fc,
+ REASON_SERVICE_TO_CLIENT);
+ return;
+ }
+#if DEBUG_SERVICE_MANAGER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Forwarded %d bytes to client\n",
+ numberOfBytesSent);
+#endif
+ if (numberOfBytesSent < fc->service_to_client_bufferDataLength)
+ {
+ fc->service_to_client_bufferPos += numberOfBytesSent;
+ fc->service_to_client_bufferDataLength -= numberOfBytesSent;
+ fc->service_to_client_task =
+ GNUNET_SCHEDULER_add_write_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ fc->armClientSocket,
+ &forwardToClient,
+ fc);
+ return;
+ }
+ fc->service_to_client_task =
+ GNUNET_SCHEDULER_add_read_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ fc->armServiceSocket,
+ &receiveFromService,
+ fc);
+}
+
+
+/**
+ * Receive service messages sent by the service and forward it to client
+ *
+ * @param cls callback data, struct ForwardedConnection for the communication between client and service
+ * @param tc scheduler context
+ */
+static void
+receiveFromService (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct ForwardedConnection *fc = cls;
+ struct GNUNET_TIME_Relative rem;
+
+ fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
+ if ( (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) &&
+ (fc->first_write_done != GNUNET_YES) )
+ {
+ closeClientAndServiceSockets (fc, REASON_ERROR);
+ return;
+ }
+ if (GNUNET_YES != GNUNET_NETWORK_fdset_isset (tc->read_ready,
+ fc->armServiceSocket))
+ {
+ fc->service_to_client_task =
+ GNUNET_SCHEDULER_add_read_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ fc->armServiceSocket,
+ &receiveFromService, fc);
+ return;
+ }
+ fc->service_to_client_bufferPos = fc->service_to_client_buffer;
+ fc->service_to_client_bufferDataLength =
+ GNUNET_NETWORK_socket_recv (fc->armServiceSocket,
+ fc->service_to_client_buffer,
+ BUFFER_SIZE);
+ if (fc->service_to_client_bufferDataLength <= 0)
+ {
+ if (fc->service_to_client_bufferDataLength == 0)
+ {
+#if DEBUG_SERVICE_MANAGER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Service `%s' stopped sending data.\n",
+ fc->listen_info->serviceName);
+#endif
+ }
+ if (fc->first_write_done != GNUNET_YES)
+ {
+ fc->service_to_client_bufferDataLength = 0;
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_NETWORK_socket_close (fc->armServiceSocket));
+ fc->armServiceSocket = NULL;
+ if ( (fc->client_to_service_bufferDataLength > 0) &&
+ (fc->client_to_service_task != GNUNET_SCHEDULER_NO_TASK) )
+ {
+ GNUNET_SCHEDULER_cancel (scheduler,
+ fc->client_to_service_task);
+ fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ fc->back_off = GNUNET_TIME_relative_multiply (fc->back_off, 2);
+#if DEBUG_SERVICE_MANAGER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Failed to connected to service `%s' at `%s', will try again in %llu ms\n",
+ fc->listen_info->serviceName,
+ GNUNET_a2s (fc->listen_info->service_addr,
+ fc->listen_info->service_addr_len),
+ (unsigned long long) GNUNET_TIME_relative_min (fc->back_off,
+ rem).value);
+#endif
+ rem = GNUNET_TIME_absolute_get_remaining (fc->timeout);
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task);
+ fc->start_task
+ = GNUNET_SCHEDULER_add_delayed (scheduler,
+ GNUNET_TIME_relative_min (fc->back_off,
+ rem),
+ &start_forwarding,
+ fc);
+ }
+ else
+ {
+#if DEBUG_SERVICE_MANAGER
+ if (fc->service_to_client_bufferDataLength != 0)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Error receiving from service: %s\n",
+ STRERROR (errno));
+#endif
+ closeClientAndServiceSockets (fc, REASON_SERVICE_TO_CLIENT);
+ }
+ return;
+ }
+ fc->first_write_done = GNUNET_YES;
+#if DEBUG_SERVICE_MANAGER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received %d bytes for client\n",
+ fc->service_to_client_bufferDataLength);
+#endif
+ fc->service_to_client_task =
+ GNUNET_SCHEDULER_add_write_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ fc->armClientSocket,
+ &forwardToClient, fc);
+}
+
+
+/**
+ * Forward client message to service
+ *
+ * @param cls callback data, struct ForwardedConnection for the communication between client and service
+ * @param tc scheduler context
+ */
+static void
+forwardToService (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct ForwardedConnection *fc = cls;
+ ssize_t numberOfBytesSent;
+ struct GNUNET_TIME_Relative rem;
+
+ fc->client_to_service_task = GNUNET_SCHEDULER_NO_TASK;
+ if ( (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) &&
+ (fc->first_write_done != GNUNET_YES) )
+ {
+ closeClientAndServiceSockets (fc, REASON_ERROR);
+ return;
+ }
+ if (GNUNET_YES != GNUNET_NETWORK_fdset_isset (tc->write_ready,
+ fc->armServiceSocket))
+ {
+ fc->client_to_service_task =
+ GNUNET_SCHEDULER_add_write_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ fc->armServiceSocket,
+ &forwardToService, fc);
+ return;
+ }
+ numberOfBytesSent =
+ GNUNET_NETWORK_socket_send (fc->armServiceSocket,
+ fc->client_to_service_bufferPos,
+ fc->client_to_service_bufferDataLength);
+ if (numberOfBytesSent <= 0)
+ {
+ if (GNUNET_YES != fc->first_write_done)
+ {
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_NETWORK_socket_close (fc->armServiceSocket));
+ fc->armServiceSocket = NULL;
+ if ( (fc->service_to_client_bufferDataLength == 0) &&
+ (fc->service_to_client_task != GNUNET_SCHEDULER_NO_TASK) )
+ {
+ GNUNET_SCHEDULER_cancel (scheduler,
+ fc->service_to_client_task);
+ fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ fc->back_off = GNUNET_TIME_relative_multiply (fc->back_off, 2);
+#if DEBUG_SERVICE_MANAGER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Failed to connect to service `%s' at `%s', will try again in %llu ms\n",
+ fc->listen_info->serviceName,
+ GNUNET_a2s (fc->listen_info->service_addr,
+ fc->listen_info->service_addr_len),
+ (unsigned long long) GNUNET_TIME_relative_min (fc->back_off,
+ rem).value);
+#endif
+ rem = GNUNET_TIME_absolute_get_remaining (fc->timeout);
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task);
+ fc->start_task
+ = GNUNET_SCHEDULER_add_delayed (scheduler,
+ GNUNET_TIME_relative_min (fc->back_off,
+ rem),
+ &start_forwarding,
+ fc);
+ }
+ else
+ {
+ if ( (errno != EPIPE) &&
+ (errno != ECONNRESET) )
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to forward data to service: %s\n",
+ STRERROR (errno));
+ closeClientAndServiceSockets (fc,
+ REASON_CLIENT_TO_SERVICE);
+ }
+ return;
+ }
+#if DEBUG_SERVICE_MANAGER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Forwarded %d bytes to service\n",
+ numberOfBytesSent);
+#endif
+ fc->first_write_done = GNUNET_YES;
+ if (numberOfBytesSent < fc->client_to_service_bufferDataLength)
+ {
+ fc->client_to_service_bufferPos += numberOfBytesSent;
+ fc->client_to_service_bufferDataLength -= numberOfBytesSent;
+ fc->client_to_service_task =
+ GNUNET_SCHEDULER_add_write_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ fc->armServiceSocket,
+ &forwardToService, fc);
+ return;
+ }
+ fc->client_to_service_task =
+ GNUNET_SCHEDULER_add_read_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ fc->armClientSocket,
+ &receiveFromClient, fc);
+}
+
+
+/**
+ * Read data from the client and then forward it to the 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 ForwardedConnection *fc = cls;
+
+ fc->client_to_service_task = GNUNET_SCHEDULER_NO_TASK;
+ if (GNUNET_YES != GNUNET_NETWORK_fdset_isset (tc->read_ready,
+ fc->armClientSocket))
+ {
+ fc->client_to_service_task =
+ GNUNET_SCHEDULER_add_read_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ fc->armClientSocket,
+ &receiveFromClient, fc);
+ return;
+ }
+ fc->client_to_service_bufferPos = fc->client_to_service_buffer;
+ fc->client_to_service_bufferDataLength =
+ GNUNET_NETWORK_socket_recv (fc->armClientSocket,
+ fc->client_to_service_buffer,
+ BUFFER_SIZE);
+ if (fc->client_to_service_bufferDataLength <= 0)
+ {
+ if (fc->client_to_service_bufferDataLength == 0)
+ {
+#if DEBUG_SERVICE_MANAGER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Client closed connection with service `%s'\n",
+ fc->listen_info->serviceName);
+#endif
+ }
+ else
+ {
+#if DEBUG_SERVICE_MANAGER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Error receiving from client: %s\n",
+ STRERROR (errno));
+#endif
+ }
+ closeClientAndServiceSockets (fc, REASON_CLIENT_TO_SERVICE);
+ return;
+ }
+#if DEBUG_SERVICE_MANAGER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received %d bytes for service\n",
+ fc->client_to_service_bufferDataLength);
+#endif
+ if (fc->armServiceSocket != NULL)
+ fc->client_to_service_task =
+ GNUNET_SCHEDULER_add_write_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ fc->armServiceSocket,
+ &forwardToService, fc);
+}
+
+
+/**
+ *
+ */
+static void
+start_forwarding (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct ForwardedConnection *fc = cls;
+ struct GNUNET_TIME_Relative rem;
+
+ fc->start_task = GNUNET_SCHEDULER_NO_TASK;
+ if ( (NULL != tc) &&
+ (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Unable to forward to service `%s': shutdown\n"),
+ fc->listen_info->serviceName);
+ closeClientAndServiceSockets (fc, REASON_ERROR);
+ return;
+ }
+ rem = GNUNET_TIME_absolute_get_remaining (fc->timeout);
+ if (rem.value == 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Unable to forward to service `%s': timeout before connect\n"),
+ fc->listen_info->serviceName);
+ closeClientAndServiceSockets (fc, REASON_ERROR);
+ return;
+ }
+ fc->armServiceSocket =
+ GNUNET_NETWORK_socket_create (fc->listen_info->service_addr->sa_family,
+ SOCK_STREAM, 0);
+ if (NULL == fc->armServiceSocket)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _ ("Unable to start service `%s': %s\n"),
+ fc->listen_info->serviceName,
+ STRERROR (errno));
+ closeClientAndServiceSockets (fc, REASON_ERROR);
+ return;
+ }
+ if ( (GNUNET_SYSERR ==
+ GNUNET_NETWORK_socket_connect (fc->armServiceSocket,
+ fc->listen_info->service_addr,
+ fc->listen_info->service_addr_len)) &&
+ (errno != EINPROGRESS) )
+ {
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_NETWORK_socket_close (fc->armServiceSocket));
+ fc->armServiceSocket = NULL;
+ fc->back_off = GNUNET_TIME_relative_multiply (fc->back_off, 2);
+ #if DEBUG_SERVICE_MANAGER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Failed to connected to service `%s' at `%s', will try again in %llu ms\n",
+ fc->listen_info->serviceName,
+ GNUNET_a2s (fc->listen_info->service_addr,
+ fc->listen_info->service_addr_len),
+ (unsigned long long) GNUNET_TIME_relative_min (fc->back_off,
+ rem).value);
+#endif
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task);
+ fc->start_task
+ = GNUNET_SCHEDULER_add_delayed (scheduler,
+ GNUNET_TIME_relative_min (fc->back_off,
+ rem),
+ &start_forwarding,
+ fc);
+ return;
+ }
+#if DEBUG_SERVICE_MANAGER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connected to service, now starting forwarding\n");
+#endif
+ if (fc->client_to_service_task == GNUNET_SCHEDULER_NO_TASK)
+ {
+ if (fc->client_to_service_bufferDataLength == 0)
+ fc->client_to_service_task =
+ GNUNET_SCHEDULER_add_read_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ fc->armClientSocket,
+ &receiveFromClient, fc);
+ else
+ fc->client_to_service_task =
+ GNUNET_SCHEDULER_add_write_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ fc->armServiceSocket,
+ &forwardToService, fc);
+ }
+ if (fc->service_to_client_task == GNUNET_SCHEDULER_NO_TASK)
+ {
+ if (fc->service_to_client_bufferDataLength == 0)
+ fc->service_to_client_task =
+ GNUNET_SCHEDULER_add_read_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ fc->armServiceSocket,
+ &receiveFromService, fc);
+ else
+ fc->service_to_client_task =
+ GNUNET_SCHEDULER_add_write_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ fc->armClientSocket,
+ &forwardToClient, fc);
+ }
+}
+
+
+
+/**
+ *
+ */
+int
+stop_listening (const char *serviceName)
+{
+ struct ServiceListeningInfo *pos;
+ struct ServiceListeningInfo *next;
+ int ret;
+
+ ret = GNUNET_NO;
+ next = serviceListeningInfoList_head;
+ while (NULL != (pos = next))
+ {
+ next = pos->next;
+ if ( (serviceName != NULL) &&
+ (strcmp (pos->serviceName, serviceName) != 0) )
+ continue;
+ if (pos->acceptTask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (scheduler, pos->acceptTask);
+ GNUNET_break (GNUNET_OK ==
+ 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);
+ ret = GNUNET_OK;
+ }
+ return ret;
+}
+
+
+/**
+ * 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, 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 ForwardedConnection *fc;
+
+ serviceListeningInfo->acceptTask = GNUNET_SCHEDULER_NO_TASK;
+ if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
+ return;
+ fc = GNUNET_malloc (sizeof (struct ForwardedConnection));
+ fc->listen_info = serviceListeningInfo;
+ fc->service_to_client_bufferPos = fc->service_to_client_buffer;
+ fc->client_to_service_bufferPos = fc->client_to_service_buffer;
+ 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)
+ {
+ 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_break (GNUNET_OK ==
+ GNUNET_NETWORK_socket_close (serviceListeningInfo->listeningSocket));
+ GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head,
+ serviceListeningInfoList_tail,
+ serviceListeningInfo);
+ start_service (NULL, serviceListeningInfo->serviceName);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Service `%s' started\n"),
+ fc->listen_info->serviceName);
+ fc->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_SERVICE_TIMEOUT);
+ fc->back_off = GNUNET_TIME_UNIT_MILLISECONDS;
+ fc->client_to_service_task =
+ GNUNET_SCHEDULER_add_read_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ fc->armClientSocket,
+ &receiveFromClient, fc);
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task);
+ fc->start_task
+ = GNUNET_SCHEDULER_add_now (scheduler,
+ &start_forwarding,
+ fc);
+}
+
+
+/**
+ * Creating a listening socket for each of the service's addresses and
+ * wait for the first incoming connection to it
+ *
+ * @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 *sa,
+ socklen_t addr_len,
+ const char *serviceName)
+{
+ const static int on = 1;
+ struct GNUNET_NETWORK_Handle *sock;
+ struct ServiceListeningInfo *serviceListeningInfo;
+
+ switch (sa->sa_family)
+ {
+ case AF_INET:
+ sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0);
+ break;
+ case AF_INET6:
+ sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
+ break;
+ default:
+ sock = NULL;
+ break;
+ }
+ if (NULL == sock)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Unable to create socket for service `%s'"),
+ serviceName);
+ GNUNET_free (sa);
+ return;
+ }
+ if (GNUNET_NETWORK_socket_setsockopt
+ (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK)
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ "setsockopt");
+#ifdef IPV6_V6ONLY
+ if ( (sa->sa_family == AF_INET6) &&
+ (GNUNET_NETWORK_socket_setsockopt
+ (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK))
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ "setsockopt");
+#endif
+
+ if (GNUNET_NETWORK_socket_bind
+ (sock, (const struct sockaddr *) sa, addr_len) != GNUNET_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Unable to bind listening socket for service `%s' to address `%s': %s\n"),
+ serviceName,
+ GNUNET_a2s (sa, addr_len),
+ STRERROR (errno));
+ GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
+ GNUNET_free (sa);
+ return;
+ }
+ if (GNUNET_NETWORK_socket_listen (sock, 5) != GNUNET_OK)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+ "listen");
+ GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
+ GNUNET_free (sa);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("ARM now monitors connections to service `%s' at `%s'\n"),
+ serviceName,
+ GNUNET_a2s (sa, addr_len));
+ serviceListeningInfo = GNUNET_malloc (sizeof (struct ServiceListeningInfo));
+ serviceListeningInfo->serviceName = GNUNET_strdup (serviceName);
+ serviceListeningInfo->service_addr = sa;
+ serviceListeningInfo->service_addr_len = addr_len;
+ serviceListeningInfo->listeningSocket = sock;
+ serviceListeningInfo->acceptTask =
+ GNUNET_SCHEDULER_add_read_net (scheduler,
+ GNUNET_TIME_UNIT_FOREVER_REL, sock,
+ &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.
+ *
+ * @param cls callback data, not used
+ * @param section configuration section
+ * @param option configuration option
+ * @param value the option's value
+ */
+static void
+checkPortNumberCB (void *cls,
+ const char *section,
+ const char *option,
+ const char *value)
+{
+ struct sockaddr **addrs;
+ socklen_t *addr_lens;
+ int ret;
+ unsigned int i;
+
+ if ( (strcasecmp (section, "arm") == 0) ||
+ (strcasecmp (option, "AUTOSTART") != 0) ||
+ (strcasecmp (value, "YES") != 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 = 0; i < ret; i++)
+ createListeningSocket (addrs[i], addr_lens[i], section);
+ GNUNET_free (addrs);
+ GNUNET_free (addr_lens);
+}
+
+
+/**
+ * Entry point to the Service Manager
+ *
+ * @param configurationHandle configuration to use to get services
+ * @param sched scheduler to handle clients and services communications
+ */
+void
+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 */
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_string (cfg, "arm", "DEFAULTSERVICES",
+ &defaultServicesString))
+ {
+ addDefaultServicesToList (defaultServicesString);
+ GNUNET_free (defaultServicesString);
+ }
+ /* Spot the services from the configuration and create a listening
+ socket for each */
+ GNUNET_CONFIGURATION_iterate (cfg, &checkPortNumberCB, NULL);
+}
+
+/* end of gnunet-service-arm_interceptor.c */
+++ /dev/null
-/*
- This file is part of GNUnet.
- (C) 2009, 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-manager.c
- * @brief listen to incoming connections from clients to services,
- * start services for which incoming an incoming connection occur,
- * and relay communication between the client and the service for
- * that first incoming connection.
- *
- * @author Safey Abdel Halim
- * @author Christian Grothoff
- */
-
-#include "platform.h"
-#include "gnunet_service_lib.h"
-#include "gnunet_configuration_lib.h"
-#include "gnunet_constants.h"
-#include "gnunet_client_lib.h"
-#include "gnunet_container_lib.h"
-#include "gnunet_service_arm_.h"
-
-
-#define DEBUG_SERVICE_MANAGER GNUNET_NO
-
-#define BUFFER_SIZE (64 * 1024)
-
-/**
- * Problem forwarding from client to service.
- */
-#define REASON_CLIENT_TO_SERVICE 1
-
-/**
- * Problem forwarding from service to client.
- */
-#define REASON_SERVICE_TO_CLIENT 2
-
-/**
- * Problem in both directions.
- */
-#define REASON_ERROR 3
-
-
-/**
- *
- */
-struct ServiceListeningInfo
-{
- /**
- * This is a linked list.
- */
- struct ServiceListeningInfo *next;
-
- /**
- * This is a linked list.
- */
- struct ServiceListeningInfo *prev;
-
- /**
- * Name of the service being forwarded.
- */
- char *serviceName;
-
- /**
- *
- */
- struct sockaddr *service_addr;
-
- /**
- *
- */
- socklen_t service_addr_len;
-
- /**
- * Our listening socket.
- */
- struct GNUNET_NETWORK_Handle *listeningSocket;
-
- /**
- * Task doing the accepting.
- */
- GNUNET_SCHEDULER_TaskIdentifier acceptTask;
-};
-
-/**
- * Information of the connection: client-arm-service
- */
-struct ForwardedConnection
-{
- /**
- *
- */
- struct GNUNET_NETWORK_Handle *armClientSocket;
-
- /**
- *
- */
- struct GNUNET_NETWORK_Handle *armServiceSocket;
-
- /**
- *
- */
- struct ServiceListeningInfo *listen_info;
-
- /**
- *
- */
- char service_to_client_buffer[BUFFER_SIZE];
-
- /**
- *
- */
- char client_to_service_buffer[BUFFER_SIZE];
-
- /**
- *
- */
- char client_addr[32];
-
- /**
- *
- */
- const char *client_to_service_bufferPos;
-
- /**
- *
- */
- const char *service_to_client_bufferPos;
-
- /**
- * Timeout for forwarding.
- */
- struct GNUNET_TIME_Absolute timeout;
-
- /**
- * Current back-off value.
- */
- struct GNUNET_TIME_Relative back_off;
-
- /**
- * Task that tries to initiate forwarding.
- */
- GNUNET_SCHEDULER_TaskIdentifier start_task;
-
- /**
- *
- */
- GNUNET_SCHEDULER_TaskIdentifier client_to_service_task;
-
- /**
- *
- */
- GNUNET_SCHEDULER_TaskIdentifier service_to_client_task;
-
- /**
- *
- */
- ssize_t client_to_service_bufferDataLength;
-
- /**
- *
- */
- ssize_t service_to_client_bufferDataLength;
-
- /**
- *
- */
- socklen_t client_addr_len;
-
- /**
- * Have we ever successfully written data to the service?
- */
- int first_write_done;
-};
-
-
-/**
- * Array with the names of the services started by default.
- */
-static char **defaultServicesList;
-
-/**
- * Size of the defaultServicesList array.
- */
-static unsigned int numDefaultServices;
-
-/**
- *
- */
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- *
- */
-static struct GNUNET_SCHEDULER_Handle *scheduler;
-
-/**
- *
- */
-static struct ServiceListeningInfo *serviceListeningInfoList_head;
-
-/**
- *
- */
-static struct ServiceListeningInfo *serviceListeningInfoList_tail;
-
-
-/**
- * Put the default services represented by a space separated string into an array of strings
- *
- * @param services space separated string of default services
- */
-static void
-addDefaultServicesToList (const char *services)
-{
- unsigned int i;
- const char *token;
- char *s;
-
- if (strlen (services) == 0)
- return;
- s = GNUNET_strdup (services);
- token = strtok (s, " ");
- while (NULL != token)
- {
- numDefaultServices++;
- token = strtok (NULL, " ");
- }
- GNUNET_free (s);
-
- defaultServicesList = GNUNET_malloc (numDefaultServices * sizeof (char *));
- i = 0;
- s = GNUNET_strdup (services);
- token = strtok (s, " ");
- while (NULL != token)
- {
- defaultServicesList[i++] = GNUNET_strdup (token);
- token = strtok (NULL, " ");
- }
- GNUNET_free (s);
- GNUNET_assert (i == numDefaultServices);
-}
-
-/**
- * Checks whether the serviceName is in the list of default services
- *
- * @param serviceName string to check its existance in the list
- * @return GNUNET_YES if the service is started by default
- */
-static int
-isInDefaultList (const char *serviceName)
-{
- unsigned int i;
- for (i = 0; i < numDefaultServices; i++)
- if (strcmp (serviceName, defaultServicesList[i]) == 0)
- return GNUNET_YES;
- return GNUNET_NO;
-}
-
-
-/**
- * Close forwarded connection (partial or full).
- *
- * @param fc connection to close
- * @param reason which direction to close
- */
-static void
-closeClientAndServiceSockets (struct ForwardedConnection *fc,
- int reason)
-{
- if (0 != (REASON_SERVICE_TO_CLIENT & reason))
- {
-#if DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Stopping forwarding from service to client\n",
- fc->listen_info->serviceName);
-#endif
- if (fc->service_to_client_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (scheduler, fc->service_to_client_task);
- fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
- }
- if (fc->armClientSocket != NULL)
- GNUNET_NETWORK_socket_shutdown (fc->armClientSocket,
- SHUT_WR);
- if (fc->armServiceSocket != NULL)
- GNUNET_NETWORK_socket_shutdown (fc->armServiceSocket,
- SHUT_RD);
- }
- if (0 != (REASON_CLIENT_TO_SERVICE & reason))
- {
-#if DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Stopping forwarding from client to service\n",
- fc->listen_info->serviceName);
-#endif
- if (fc->client_to_service_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (scheduler,
- fc->client_to_service_task);
- fc->client_to_service_task = GNUNET_SCHEDULER_NO_TASK;
- }
- if (fc->armClientSocket != NULL)
- GNUNET_NETWORK_socket_shutdown (fc->armClientSocket,
- SHUT_RD);
- if (fc->armServiceSocket != NULL)
- GNUNET_NETWORK_socket_shutdown (fc->armServiceSocket,
- SHUT_WR);
- }
- if ( (fc->client_to_service_task != GNUNET_SCHEDULER_NO_TASK) ||
- (fc->service_to_client_task != GNUNET_SCHEDULER_NO_TASK) )
- return;
-#if DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Closing forwarding connection (done with both directions)\n");
-#endif
- if (fc->start_task != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (scheduler,
- fc->start_task);
- if ( (NULL != fc->armClientSocket) &&
- (GNUNET_SYSERR ==
- GNUNET_NETWORK_socket_close (fc->armClientSocket)) )
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close");
- if ( (NULL != fc->armServiceSocket) &&
- (GNUNET_SYSERR ==
- GNUNET_NETWORK_socket_close (fc->armServiceSocket)) )
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close");
- 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);
-
-
-/**
- *
- */
-static void
-start_forwarding (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-
-/**
- * Forward messages sent from service to client
- *
- * @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 ForwardedConnection *fc = cls;
- ssize_t numberOfBytesSent;
-
- fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
- if (GNUNET_YES != GNUNET_NETWORK_fdset_isset (tc->write_ready,
- fc->armClientSocket))
- {
- fc->service_to_client_task =
- GNUNET_SCHEDULER_add_write_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armClientSocket,
- &forwardToClient, fc);
- return;
- }
- /* Forwarding service response to client */
- numberOfBytesSent =
- GNUNET_NETWORK_socket_send (fc->armClientSocket,
- fc->service_to_client_bufferPos,
- fc->service_to_client_bufferDataLength);
- if (numberOfBytesSent <= 0)
- {
- if ( (errno != EPIPE) &&
- (errno != ECONNRESET) )
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to forward %u bytes of data to client: %s\n",
- fc->service_to_client_bufferDataLength,
- STRERROR (errno));
- closeClientAndServiceSockets (fc,
- REASON_SERVICE_TO_CLIENT);
- return;
- }
-#if DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Forwarded %d bytes to client\n",
- numberOfBytesSent);
-#endif
- if (numberOfBytesSent < fc->service_to_client_bufferDataLength)
- {
- fc->service_to_client_bufferPos += numberOfBytesSent;
- fc->service_to_client_bufferDataLength -= numberOfBytesSent;
- fc->service_to_client_task =
- GNUNET_SCHEDULER_add_write_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armClientSocket,
- &forwardToClient,
- fc);
- return;
- }
- fc->service_to_client_task =
- GNUNET_SCHEDULER_add_read_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armServiceSocket,
- &receiveFromService,
- fc);
-}
-
-
-/**
- * Receive service messages sent by the service and forward it to client
- *
- * @param cls callback data, struct ForwardedConnection for the communication between client and service
- * @param tc scheduler context
- */
-static void
-receiveFromService (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct ForwardedConnection *fc = cls;
- struct GNUNET_TIME_Relative rem;
-
- fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
- if ( (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) &&
- (fc->first_write_done != GNUNET_YES) )
- {
- closeClientAndServiceSockets (fc, REASON_ERROR);
- return;
- }
- if (GNUNET_YES != GNUNET_NETWORK_fdset_isset (tc->read_ready,
- fc->armServiceSocket))
- {
- fc->service_to_client_task =
- GNUNET_SCHEDULER_add_read_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armServiceSocket,
- &receiveFromService, fc);
- return;
- }
- fc->service_to_client_bufferPos = fc->service_to_client_buffer;
- fc->service_to_client_bufferDataLength =
- GNUNET_NETWORK_socket_recv (fc->armServiceSocket,
- fc->service_to_client_buffer,
- BUFFER_SIZE);
- if (fc->service_to_client_bufferDataLength <= 0)
- {
- if (fc->service_to_client_bufferDataLength == 0)
- {
-#if DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Service `%s' stopped sending data.\n",
- fc->listen_info->serviceName);
-#endif
- }
- if (fc->first_write_done != GNUNET_YES)
- {
- fc->service_to_client_bufferDataLength = 0;
- GNUNET_break (GNUNET_OK ==
- GNUNET_NETWORK_socket_close (fc->armServiceSocket));
- fc->armServiceSocket = NULL;
- if ( (fc->client_to_service_bufferDataLength > 0) &&
- (fc->client_to_service_task != GNUNET_SCHEDULER_NO_TASK) )
- {
- GNUNET_SCHEDULER_cancel (scheduler,
- fc->client_to_service_task);
- fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
- }
- fc->back_off = GNUNET_TIME_relative_multiply (fc->back_off, 2);
-#if DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Failed to connected to service `%s' at `%s', will try again in %llu ms\n",
- fc->listen_info->serviceName,
- GNUNET_a2s (fc->listen_info->service_addr,
- fc->listen_info->service_addr_len),
- (unsigned long long) GNUNET_TIME_relative_min (fc->back_off,
- rem).value);
-#endif
- rem = GNUNET_TIME_absolute_get_remaining (fc->timeout);
- GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task);
- fc->start_task
- = GNUNET_SCHEDULER_add_delayed (scheduler,
- GNUNET_TIME_relative_min (fc->back_off,
- rem),
- &start_forwarding,
- fc);
- }
- else
- {
-#if DEBUG_SERVICE_MANAGER
- if (fc->service_to_client_bufferDataLength != 0)
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Error receiving from service: %s\n",
- STRERROR (errno));
-#endif
- closeClientAndServiceSockets (fc, REASON_SERVICE_TO_CLIENT);
- }
- return;
- }
- fc->first_write_done = GNUNET_YES;
-#if DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received %d bytes for client\n",
- fc->service_to_client_bufferDataLength);
-#endif
- fc->service_to_client_task =
- GNUNET_SCHEDULER_add_write_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armClientSocket,
- &forwardToClient, fc);
-}
-
-
-/**
- * Forward client message to service
- *
- * @param cls callback data, struct ForwardedConnection for the communication between client and service
- * @param tc scheduler context
- */
-static void
-forwardToService (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct ForwardedConnection *fc = cls;
- ssize_t numberOfBytesSent;
- struct GNUNET_TIME_Relative rem;
-
- fc->client_to_service_task = GNUNET_SCHEDULER_NO_TASK;
- if ( (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) &&
- (fc->first_write_done != GNUNET_YES) )
- {
- closeClientAndServiceSockets (fc, REASON_ERROR);
- return;
- }
- if (GNUNET_YES != GNUNET_NETWORK_fdset_isset (tc->write_ready,
- fc->armServiceSocket))
- {
- fc->client_to_service_task =
- GNUNET_SCHEDULER_add_write_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armServiceSocket,
- &forwardToService, fc);
- return;
- }
- numberOfBytesSent =
- GNUNET_NETWORK_socket_send (fc->armServiceSocket,
- fc->client_to_service_bufferPos,
- fc->client_to_service_bufferDataLength);
- if (numberOfBytesSent <= 0)
- {
- if (GNUNET_YES != fc->first_write_done)
- {
- GNUNET_break (GNUNET_OK ==
- GNUNET_NETWORK_socket_close (fc->armServiceSocket));
- fc->armServiceSocket = NULL;
- if ( (fc->service_to_client_bufferDataLength == 0) &&
- (fc->service_to_client_task != GNUNET_SCHEDULER_NO_TASK) )
- {
- GNUNET_SCHEDULER_cancel (scheduler,
- fc->service_to_client_task);
- fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
- }
- fc->back_off = GNUNET_TIME_relative_multiply (fc->back_off, 2);
-#if DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Failed to connect to service `%s' at `%s', will try again in %llu ms\n",
- fc->listen_info->serviceName,
- GNUNET_a2s (fc->listen_info->service_addr,
- fc->listen_info->service_addr_len),
- (unsigned long long) GNUNET_TIME_relative_min (fc->back_off,
- rem).value);
-#endif
- rem = GNUNET_TIME_absolute_get_remaining (fc->timeout);
- GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task);
- fc->start_task
- = GNUNET_SCHEDULER_add_delayed (scheduler,
- GNUNET_TIME_relative_min (fc->back_off,
- rem),
- &start_forwarding,
- fc);
- }
- else
- {
- if ( (errno != EPIPE) &&
- (errno != ECONNRESET) )
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to forward data to service: %s\n",
- STRERROR (errno));
- closeClientAndServiceSockets (fc,
- REASON_CLIENT_TO_SERVICE);
- }
- return;
- }
-#if DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Forwarded %d bytes to service\n",
- numberOfBytesSent);
-#endif
- fc->first_write_done = GNUNET_YES;
- if (numberOfBytesSent < fc->client_to_service_bufferDataLength)
- {
- fc->client_to_service_bufferPos += numberOfBytesSent;
- fc->client_to_service_bufferDataLength -= numberOfBytesSent;
- fc->client_to_service_task =
- GNUNET_SCHEDULER_add_write_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armServiceSocket,
- &forwardToService, fc);
- return;
- }
- fc->client_to_service_task =
- GNUNET_SCHEDULER_add_read_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armClientSocket,
- &receiveFromClient, fc);
-}
-
-
-/**
- * Read data from the client and then forward it to the 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 ForwardedConnection *fc = cls;
-
- fc->client_to_service_task = GNUNET_SCHEDULER_NO_TASK;
- if (GNUNET_YES != GNUNET_NETWORK_fdset_isset (tc->read_ready,
- fc->armClientSocket))
- {
- fc->client_to_service_task =
- GNUNET_SCHEDULER_add_read_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armClientSocket,
- &receiveFromClient, fc);
- return;
- }
- fc->client_to_service_bufferPos = fc->client_to_service_buffer;
- fc->client_to_service_bufferDataLength =
- GNUNET_NETWORK_socket_recv (fc->armClientSocket,
- fc->client_to_service_buffer,
- BUFFER_SIZE);
- if (fc->client_to_service_bufferDataLength <= 0)
- {
- if (fc->client_to_service_bufferDataLength == 0)
- {
-#if DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Client closed connection with service `%s'\n",
- fc->listen_info->serviceName);
-#endif
- }
- else
- {
-#if DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Error receiving from client: %s\n",
- STRERROR (errno));
-#endif
- }
- closeClientAndServiceSockets (fc, REASON_CLIENT_TO_SERVICE);
- return;
- }
-#if DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received %d bytes for service\n",
- fc->client_to_service_bufferDataLength);
-#endif
- if (fc->armServiceSocket != NULL)
- fc->client_to_service_task =
- GNUNET_SCHEDULER_add_write_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armServiceSocket,
- &forwardToService, fc);
-}
-
-
-/**
- *
- */
-static void
-start_forwarding (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct ForwardedConnection *fc = cls;
- struct GNUNET_TIME_Relative rem;
-
- fc->start_task = GNUNET_SCHEDULER_NO_TASK;
- if ( (NULL != tc) &&
- (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Unable to forward to service `%s': shutdown\n"),
- fc->listen_info->serviceName);
- closeClientAndServiceSockets (fc, REASON_ERROR);
- return;
- }
- rem = GNUNET_TIME_absolute_get_remaining (fc->timeout);
- if (rem.value == 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to forward to service `%s': timeout before connect\n"),
- fc->listen_info->serviceName);
- closeClientAndServiceSockets (fc, REASON_ERROR);
- return;
- }
- fc->armServiceSocket =
- GNUNET_NETWORK_socket_create (fc->listen_info->service_addr->sa_family,
- SOCK_STREAM, 0);
- if (NULL == fc->armServiceSocket)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _ ("Unable to start service `%s': %s\n"),
- fc->listen_info->serviceName,
- STRERROR (errno));
- closeClientAndServiceSockets (fc, REASON_ERROR);
- return;
- }
- if ( (GNUNET_SYSERR ==
- GNUNET_NETWORK_socket_connect (fc->armServiceSocket,
- fc->listen_info->service_addr,
- fc->listen_info->service_addr_len)) &&
- (errno != EINPROGRESS) )
- {
- GNUNET_break (GNUNET_OK ==
- GNUNET_NETWORK_socket_close (fc->armServiceSocket));
- fc->armServiceSocket = NULL;
- fc->back_off = GNUNET_TIME_relative_multiply (fc->back_off, 2);
- #if DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Failed to connected to service `%s' at `%s', will try again in %llu ms\n",
- fc->listen_info->serviceName,
- GNUNET_a2s (fc->listen_info->service_addr,
- fc->listen_info->service_addr_len),
- (unsigned long long) GNUNET_TIME_relative_min (fc->back_off,
- rem).value);
-#endif
- GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task);
- fc->start_task
- = GNUNET_SCHEDULER_add_delayed (scheduler,
- GNUNET_TIME_relative_min (fc->back_off,
- rem),
- &start_forwarding,
- fc);
- return;
- }
-#if DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Connected to service, now starting forwarding\n");
-#endif
- if (fc->client_to_service_task == GNUNET_SCHEDULER_NO_TASK)
- {
- if (fc->client_to_service_bufferDataLength == 0)
- fc->client_to_service_task =
- GNUNET_SCHEDULER_add_read_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armClientSocket,
- &receiveFromClient, fc);
- else
- fc->client_to_service_task =
- GNUNET_SCHEDULER_add_write_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armServiceSocket,
- &forwardToService, fc);
- }
- if (fc->service_to_client_task == GNUNET_SCHEDULER_NO_TASK)
- {
- if (fc->service_to_client_bufferDataLength == 0)
- fc->service_to_client_task =
- GNUNET_SCHEDULER_add_read_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armServiceSocket,
- &receiveFromService, fc);
- else
- fc->service_to_client_task =
- GNUNET_SCHEDULER_add_write_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armClientSocket,
- &forwardToClient, fc);
- }
-}
-
-
-
-/**
- *
- */
-int
-stop_listening (const char *serviceName)
-{
- struct ServiceListeningInfo *pos;
- struct ServiceListeningInfo *next;
- int ret;
-
- ret = GNUNET_NO;
- next = serviceListeningInfoList_head;
- while (NULL != (pos = next))
- {
- next = pos->next;
- if ( (serviceName != NULL) &&
- (strcmp (pos->serviceName, serviceName) != 0) )
- continue;
- if (pos->acceptTask != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (scheduler, pos->acceptTask);
- GNUNET_break (GNUNET_OK ==
- 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);
- ret = GNUNET_OK;
- }
- return ret;
-}
-
-
-/**
- * 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, 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 ForwardedConnection *fc;
-
- serviceListeningInfo->acceptTask = GNUNET_SCHEDULER_NO_TASK;
- if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
- return;
- fc = GNUNET_malloc (sizeof (struct ForwardedConnection));
- fc->listen_info = serviceListeningInfo;
- fc->service_to_client_bufferPos = fc->service_to_client_buffer;
- fc->client_to_service_bufferPos = fc->client_to_service_buffer;
- 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)
- {
- 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_break (GNUNET_OK ==
- GNUNET_NETWORK_socket_close (serviceListeningInfo->listeningSocket));
- GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head,
- serviceListeningInfoList_tail,
- serviceListeningInfo);
- start_service (NULL, serviceListeningInfo->serviceName);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Service `%s' started\n"),
- fc->listen_info->serviceName);
- fc->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_SERVICE_TIMEOUT);
- fc->back_off = GNUNET_TIME_UNIT_MILLISECONDS;
- fc->client_to_service_task =
- GNUNET_SCHEDULER_add_read_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armClientSocket,
- &receiveFromClient, fc);
- GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task);
- fc->start_task
- = GNUNET_SCHEDULER_add_now (scheduler,
- &start_forwarding,
- fc);
-}
-
-
-/**
- * Creating a listening socket for each of the service's addresses and
- * wait for the first incoming connection to it
- *
- * @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 *sa,
- socklen_t addr_len,
- const char *serviceName)
-{
- const static int on = 1;
- struct GNUNET_NETWORK_Handle *sock;
- struct ServiceListeningInfo *serviceListeningInfo;
-
- switch (sa->sa_family)
- {
- case AF_INET:
- sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0);
- break;
- case AF_INET6:
- sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
- break;
- default:
- sock = NULL;
- break;
- }
- if (NULL == sock)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to create socket for service `%s'"),
- serviceName);
- GNUNET_free (sa);
- return;
- }
- if (GNUNET_NETWORK_socket_setsockopt
- (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK)
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
- "setsockopt");
-#ifdef IPV6_V6ONLY
- if ( (sa->sa_family == AF_INET6) &&
- (GNUNET_NETWORK_socket_setsockopt
- (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK))
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
- "setsockopt");
-#endif
-
- if (GNUNET_NETWORK_socket_bind
- (sock, (const struct sockaddr *) sa, addr_len) != GNUNET_OK)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to bind listening socket for service `%s' to address `%s': %s\n"),
- serviceName,
- GNUNET_a2s (sa, addr_len),
- STRERROR (errno));
- GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
- GNUNET_free (sa);
- return;
- }
- if (GNUNET_NETWORK_socket_listen (sock, 5) != GNUNET_OK)
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
- "listen");
- GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
- GNUNET_free (sa);
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("ARM now monitors connections to service `%s' at `%s'\n"),
- serviceName,
- GNUNET_a2s (sa, addr_len));
- serviceListeningInfo = GNUNET_malloc (sizeof (struct ServiceListeningInfo));
- serviceListeningInfo->serviceName = GNUNET_strdup (serviceName);
- serviceListeningInfo->service_addr = sa;
- serviceListeningInfo->service_addr_len = addr_len;
- serviceListeningInfo->listeningSocket = sock;
- serviceListeningInfo->acceptTask =
- GNUNET_SCHEDULER_add_read_net (scheduler,
- GNUNET_TIME_UNIT_FOREVER_REL, sock,
- &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.
- *
- * @param cls callback data, not used
- * @param section configuration section
- * @param option configuration option
- * @param value the option's value
- */
-static void
-checkPortNumberCB (void *cls,
- const char *section,
- const char *option,
- const char *value)
-{
- struct sockaddr **addrs;
- socklen_t *addr_lens;
- int ret;
- unsigned int i;
-
- if ( (strcasecmp (section, "arm") == 0) ||
- (strcasecmp (option, "AUTOSTART") != 0) ||
- (strcasecmp (value, "YES") != 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 = 0; i < ret; i++)
- createListeningSocket (addrs[i], addr_lens[i], section);
- GNUNET_free (addrs);
- GNUNET_free (addr_lens);
-}
-
-
-/**
- * Entry point to the Service Manager
- *
- * @param configurationHandle configuration to use to get services
- * @param sched scheduler to handle clients and services communications
- */
-void
-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 */
- if (GNUNET_OK ==
- GNUNET_CONFIGURATION_get_value_string (cfg, "arm", "DEFAULTSERVICES",
- &defaultServicesString))
- {
- addDefaultServicesToList (defaultServicesString);
- GNUNET_free (defaultServicesString);
- }
- /* Spot the services from the configuration and create a listening
- socket for each */
- GNUNET_CONFIGURATION_iterate (cfg, &checkPortNumberCB, NULL);
-}
-
-/* end of gnunet-service-manager.c */
+++ /dev/null
-/*
- 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
- * @author Safey Abdel Halim
- */
-
-#ifndef GNUNET_SERVICE_ARM__H
-#define GNUNET_SERVICE_ARM__H
-
-void start_service (struct GNUNET_SERVER_Client *client,
- const char *servicename);
-
-/**
- * Stop listening for connections to a service.
- *
- * @param serviceName name of service to stop listening for
- * @return GNUNET_OK if we stopped to listen, GNUNET_NO if we were
- * not listening
- */
-int stop_listening (const char *serviceName);
-
-void prepareServices (const struct GNUNET_CONFIGURATION_Handle
- *configurationHandle,
- struct GNUNET_SCHEDULER_Handle *sched);
-
-#endif