/*
This file is part of GNUnet.
- (C) 2009, 2010 Christian Grothoff (and other contributing authors)
+ (C) 2009, 2010, 2011 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
#define DEBUG_SERVICE_MANAGER GNUNET_EXTRA_LOGGING
-#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 ForwardedConnection;
-
/**
*
*/
*/
struct GNUNET_NETWORK_Handle *listeningSocket;
- /**
- *
- */
- struct ForwardedConnection *fc;
-
/**
* 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;
-
- /**
- * Reference count (the structure is freed when it reaches zero)
- */
- int reference_count;
-};
/**
* Array with the names of the services started by default.
}
-/**
- * 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");
-#endif
- 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");
-#endif
- 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 DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Closing forwarding connection (done with both directions)\n");
-#endif
- fc->reference_count -= 1;
- if (fc->reference_count <= 0)
- {
- if ((NULL != fc->armClientSocket) &&
- (GNUNET_SYSERR == GNUNET_NETWORK_socket_close (fc->armClientSocket)))
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close");
- fc->armClientSocket = NULL;
- }
- if ((NULL != fc->armServiceSocket) &&
- (GNUNET_SYSERR == GNUNET_NETWORK_socket_close (fc->armServiceSocket)))
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close");
- fc->armServiceSocket = NULL;
- }
- if (fc->listen_info != NULL)
- {
- if (fc->listen_info->serviceName != NULL)
- {
- GNUNET_free (fc->listen_info->serviceName);
- fc->listen_info->serviceName = NULL;
- }
- if (fc->listen_info->service_addr != NULL)
- {
- GNUNET_free (fc->listen_info->service_addr);
- fc->listen_info->service_addr = NULL;
- }
- GNUNET_free (fc->listen_info);
- fc->listen_info = NULL;
- }
- GNUNET_free (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);
-
-
-/**
- * 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);
-
-
-/**
- *
- */
-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 (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 (GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armClientSocket, &forwardToClient,
- fc);
- return;
- }
- fc->service_to_client_task =
- GNUNET_SCHEDULER_add_read_net (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 (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 DEBUG_SERVICE_MANAGER
- if (fc->service_to_client_bufferDataLength == 0)
- {
- 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 (fc->client_to_service_task);
- fc->client_to_service_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).rel_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 (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 (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 (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 (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).rel_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 (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 (GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armServiceSocket, &forwardToService,
- fc);
- return;
- }
- fc->client_to_service_task =
- GNUNET_SCHEDULER_add_read_net (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 (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 (GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armServiceSocket, &forwardToService,
- fc);
- else
- /* We have not added any task with fc as a closure, so we're
- * dropping our reference to fc
- */
- fc->reference_count -= 1;
-}
-
-
-static void
-fc_acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct ServiceListeningInfo *sli = cls;
- struct ForwardedConnection *fc = sli->fc;
-
- if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY))
- {
- GNUNET_assert (GNUNET_OK ==
- GNUNET_NETWORK_socket_close (sli->listeningSocket));
- closeClientAndServiceSockets (fc, REASON_ERROR);
- GNUNET_free (sli);
- return;
- }
-#if DEBUG_SERVICE_MANAGER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Connected to service, now starting forwarding\n");
-#endif
- fc->armServiceSocket = sli->listeningSocket;
- GNUNET_free (fc->listen_info->service_addr);
- fc->listen_info->service_addr = sli->service_addr;
- fc->listen_info->service_addr_len = sli->service_addr_len;
- /* Drop fc reference count prematurely, it'll be incremented
- * once or twice in the following conditional branches.
- * This is, apparently, the place where reference count increases
- * past 1.
- */
- fc->reference_count -= 1;
- 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 (GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armClientSocket,
- &receiveFromClient, fc);
- else
- fc->client_to_service_task =
- GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armServiceSocket,
- &forwardToService, fc);
- fc->reference_count += 1;
- }
- 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 (GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armServiceSocket,
- &receiveFromService, fc);
- else
- fc->service_to_client_task =
- GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armClientSocket, &forwardToClient,
- fc);
- fc->reference_count += 1;
- }
- GNUNET_free (sli);
-}
-
-
-static struct ServiceListeningInfo *
-service_try_to_connect (const struct sockaddr *addr, int pf, socklen_t addrlen,
- struct ForwardedConnection *fc)
-{
- struct GNUNET_NETWORK_Handle *sock;
- struct ServiceListeningInfo *serviceListeningInfo;
-
- sock = GNUNET_NETWORK_socket_create (pf, SOCK_STREAM, 0);
- if (sock == NULL)
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
- return NULL;
- }
- if ((GNUNET_SYSERR == GNUNET_NETWORK_socket_connect (sock, addr, addrlen)) &&
- (errno != EINPROGRESS))
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "connect");
- GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
- return NULL;
- }
- serviceListeningInfo = GNUNET_malloc (sizeof (struct ServiceListeningInfo));
- serviceListeningInfo->serviceName = NULL;
- serviceListeningInfo->service_addr = GNUNET_malloc (addrlen);
- memcpy (serviceListeningInfo->service_addr, addr, addrlen);
- serviceListeningInfo->service_addr_len = addrlen;
- serviceListeningInfo->listeningSocket = sock;
- serviceListeningInfo->fc = fc;
- serviceListeningInfo->acceptTask =
- GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
- serviceListeningInfo->listeningSocket,
- &fc_acceptConnection,
- serviceListeningInfo);
- return serviceListeningInfo;
-}
-
-
-/**
- *
- */
-static void
-start_forwarding (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct ForwardedConnection *fc = cls;
- struct ServiceListeningInfo *sc;
- struct sockaddr_in target_ipv4;
- struct sockaddr_in6 target_ipv6;
- const struct sockaddr_in *v4;
- const struct sockaddr_in6 *v6;
- char listen_address[INET6_ADDRSTRLEN];
-
- 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;
- }
- if (0 == GNUNET_TIME_absolute_get_remaining (fc->timeout).rel_value)
- {
- 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;
- }
- switch (fc->listen_info->service_addr->sa_family)
- {
- case AF_UNSPEC:
- GNUNET_break (0);
- closeClientAndServiceSockets (fc, REASON_ERROR);
- return;
- case AF_INET:
- v4 = (const struct sockaddr_in *) fc->listen_info->service_addr;
- inet_ntop (fc->listen_info->service_addr->sa_family,
- (const void *) &v4->sin_addr, listen_address, INET_ADDRSTRLEN);
- if (0 == strncmp (listen_address, "0.0.0.0", 7))
- {
- /* connect to [::1] and 127.0.0.1 instead of [::] and 0.0.0.0 */
- memset (&target_ipv4, 0, sizeof (target_ipv4));
- GNUNET_assert (1 ==
- inet_pton (AF_INET, "127.0.0.1", &target_ipv4.sin_addr));
- target_ipv4.sin_family = AF_INET;
- target_ipv4.sin_port = v4->sin_port;
- v4 = &target_ipv4;
- }
- sc = service_try_to_connect ((const struct sockaddr *) v4, PF_INET,
- sizeof (struct sockaddr_in), fc);
- break;
- case AF_INET6:
- v6 = (struct sockaddr_in6 *) fc->listen_info->service_addr;
- inet_ntop (fc->listen_info->service_addr->sa_family,
- (const void *) &v6->sin6_addr, listen_address, INET6_ADDRSTRLEN);
- if ((strncmp (listen_address, "[::]:", 5) == 0) ||
- (strncmp (listen_address, "::", 2) == 0))
- {
- memset (&target_ipv6, 0, sizeof (target_ipv6));
- target_ipv6.sin6_addr = in6addr_loopback;
- target_ipv6.sin6_family = AF_INET6;
- target_ipv6.sin6_port = v6->sin6_port;
- v6 = &target_ipv6;
- }
- sc = service_try_to_connect ((const struct sockaddr *) v6, PF_INET6,
- sizeof (struct sockaddr_in6), fc);
- break;
- case AF_UNIX:
- sc = service_try_to_connect (fc->listen_info->service_addr, PF_UNIX,
- fc->listen_info->service_addr_len, fc);
- break;
- default:
- GNUNET_break (0);
- closeClientAndServiceSockets (fc, REASON_ERROR);
- return;
- }
- if (NULL == sc)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to start service `%s': %s\n"),
- fc->listen_info->serviceName, STRERROR (errno));
- closeClientAndServiceSockets (fc, REASON_ERROR);
- return;
- }
-}
-
-
/**
*
*/
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);
-
-
-static void
-accept_and_forward (struct ServiceListeningInfo *serviceListeningInfo)
-{
- struct ForwardedConnection *fc;
-
- fc = GNUNET_malloc (sizeof (struct ForwardedConnection));
- fc->reference_count = 1;
- 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);
- GNUNET_CONTAINER_DLL_insert (serviceListeningInfoList_head,
- serviceListeningInfoList_tail,
- serviceListeningInfo);
- serviceListeningInfo->acceptTask =
- GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- serviceListeningInfo->listeningSocket,
- &acceptConnection, serviceListeningInfo);
- return;
- }
- GNUNET_break (GNUNET_OK ==
- GNUNET_NETWORK_socket_close
- (serviceListeningInfo->listeningSocket));
- start_service (NULL, serviceListeningInfo->serviceName, NULL);
- 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 (GNUNET_TIME_UNIT_FOREVER_REL,
- fc->armClientSocket, &receiveFromClient,
- fc);
- GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task);
- /* We're creating another chain of tasks for this fc that
- * will have its own reference to it.
- */
- fc->reference_count += 1;
- fc->start_task = GNUNET_SCHEDULER_add_now (&start_forwarding, fc);
-}
-
/**
* First connection has come to the listening socket associated with the service,
struct ServiceListeningInfo *next;
SOCKTYPE *lsocks;
unsigned int ls;
- int use_lsocks;
sli->acceptTask = GNUNET_SCHEDULER_NO_TASK;
if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
return;
GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head,
serviceListeningInfoList_tail, sli);
- use_lsocks = GNUNET_YES;
- if ((GNUNET_YES ==
- GNUNET_CONFIGURATION_have_value (cfg, "arm",
- "ENABLE_INTERCEPTOR")) &&
- (GNUNET_YES ==
- GNUNET_CONFIGURATION_get_value_yesno (cfg, "arm",
- "ENABLE_INTERCEPTOR")) )
- use_lsocks = GNUNET_NO;
- if (GNUNET_YES != use_lsocks)
- {
- accept_and_forward (sli);
- return;
- }
lsocks = NULL;
ls = 0;
next = serviceListeningInfoList_head;