[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r18473 - in gnunet/src: arm include util
From: |
gnunet |
Subject: |
[GNUnet-SVN] r18473 - in gnunet/src: arm include util |
Date: |
Tue, 6 Dec 2011 18:58:40 +0100 |
Author: grothoff
Date: 2011-12-06 18:58:40 +0100 (Tue, 06 Dec 2011)
New Revision: 18473
Modified:
gnunet/src/arm/do_start_process.c
gnunet/src/arm/gnunet-service-arm.c
gnunet/src/arm/gnunet-service-arm.h
gnunet/src/arm/gnunet-service-arm_interceptor.c
gnunet/src/include/gnunet_network_lib.h
gnunet/src/include/gnunet_os_lib.h
gnunet/src/include/platform.h
gnunet/src/util/network.c
gnunet/src/util/os_priority.c
gnunet/src/util/service.c
Log:
Implement passing sockets in IPC on W32 (#1975)
Modified: gnunet/src/arm/do_start_process.c
===================================================================
--- gnunet/src/arm/do_start_process.c 2011-12-06 17:29:30 UTC (rev 18472)
+++ gnunet/src/arm/do_start_process.c 2011-12-06 17:58:40 UTC (rev 18473)
@@ -13,7 +13,7 @@
* @return PID of the started process, -1 on error
*/
static struct GNUNET_OS_Process *
-do_start_process (const int *lsocks, const char *first_arg, ...)
+do_start_process (const SOCKTYPE *lsocks, const char *first_arg, ...)
{
va_list ap;
char **argv;
Modified: gnunet/src/arm/gnunet-service-arm.c
===================================================================
--- gnunet/src/arm/gnunet-service-arm.c 2011-12-06 17:29:30 UTC (rev 18472)
+++ gnunet/src/arm/gnunet-service-arm.c 2011-12-06 17:58:40 UTC (rev 18473)
@@ -331,7 +331,7 @@
* @param lsocks -1 terminated list of listen sockets to pass (systemd style),
or NULL
*/
static void
-start_process (struct ServiceList *sl, const int *lsocks)
+start_process (struct ServiceList *sl, const SOCKTYPE *lsocks)
{
char *loprefix;
char *options;
@@ -422,7 +422,7 @@
*/
int
start_service (struct GNUNET_SERVER_Client *client, const char *servicename,
- const int *lsocks)
+ const SOCKTYPE *lsocks)
{
struct ServiceList *sl;
char *binary;
Modified: gnunet/src/arm/gnunet-service-arm.h
===================================================================
--- gnunet/src/arm/gnunet-service-arm.h 2011-12-06 17:29:30 UTC (rev 18472)
+++ gnunet/src/arm/gnunet-service-arm.h 2011-12-06 17:58:40 UTC (rev 18473)
@@ -37,7 +37,7 @@
*/
int
start_service (struct GNUNET_SERVER_Client *client, const char *servicename,
- const int *lsocks);
+ const SOCKTYPE *lsocks);
/**
* Stop listening for connections to a service.
Modified: gnunet/src/arm/gnunet-service-arm_interceptor.c
===================================================================
--- gnunet/src/arm/gnunet-service-arm_interceptor.c 2011-12-06 17:29:30 UTC
(rev 18472)
+++ gnunet/src/arm/gnunet-service-arm_interceptor.c 2011-12-06 17:58:40 UTC
(rev 18473)
@@ -980,9 +980,9 @@
struct ServiceListeningInfo *sli = cls;
struct ServiceListeningInfo *pos;
struct ServiceListeningInfo *next;
- int *lsocks;
+ SOCKTYPE *lsocks;
unsigned int ls;
- int use_lsocks;
+ int disable_lsocks;
sli->acceptTask = GNUNET_SCHEDULER_NO_TASK;
if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
@@ -1025,11 +1025,19 @@
GNUNET_NETWORK_get_fd (sli->listeningSocket));
GNUNET_free (sli->listeningSocket); /* deliberately no closing! */
GNUNET_free (sli->service_addr);
+#if WINDOWS
+ GNUNET_array_append (lsocks, ls, INVALID_SOCKET);
+#else
GNUNET_array_append (lsocks, ls, -1);
+#endif
start_service (NULL, sli->serviceName, lsocks);
ls = 0;
while (lsocks[ls] != -1)
+#if WINDOWS
+ GNUNET_break (0 == closesocket (lsocks[ls++]));
+#else
GNUNET_break (0 == close (lsocks[ls++]));
+#endif
GNUNET_array_grow (lsocks, ls, 0);
GNUNET_free (sli->serviceName);
GNUNET_free (sli);
Modified: gnunet/src/include/gnunet_network_lib.h
===================================================================
--- gnunet/src/include/gnunet_network_lib.h 2011-12-06 17:29:30 UTC (rev
18472)
+++ gnunet/src/include/gnunet_network_lib.h 2011-12-06 17:58:40 UTC (rev
18473)
@@ -96,7 +96,7 @@
* @return NULL on error (including not supported on target platform)
*/
struct GNUNET_NETWORK_Handle *
-GNUNET_NETWORK_socket_box_native (int fd);
+GNUNET_NETWORK_socket_box_native (SOCKTYPE fd);
/**
@@ -320,8 +320,7 @@
const struct GNUNET_NETWORK_Handle *desc);
-#ifdef __MINGW32__
-/* TODO: maybe #ifdef WINDOWS? -ndurner */
+#if WINDOWS
/**
* Add a W32 file handle to the fd set
* @param fds fd set
Modified: gnunet/src/include/gnunet_os_lib.h
===================================================================
--- gnunet/src/include/gnunet_os_lib.h 2011-12-06 17:29:30 UTC (rev 18472)
+++ gnunet/src/include/gnunet_os_lib.h 2011-12-06 17:58:40 UTC (rev 18473)
@@ -275,7 +275,7 @@
* @return pointer to process structure of the new process, NULL on error
*/
struct GNUNET_OS_Process *
-GNUNET_OS_start_process_v (const int *lsocks, const char *filename,
+GNUNET_OS_start_process_v (const SOCKTYPE *lsocks, const char *filename,
char *const argv[]);
Modified: gnunet/src/include/platform.h
===================================================================
--- gnunet/src/include/platform.h 2011-12-06 17:29:30 UTC (rev 18472)
+++ gnunet/src/include/platform.h 2011-12-06 17:58:40 UTC (rev 18473)
@@ -246,4 +246,12 @@
#define MAKE_UNALIGNED(val) val
#endif
+#if WINDOWS
+#define FDTYPE HANDLE
+#define SOCKTYPE SOCKET
+#else
+#define FDTYPE int
+#define SOCKTYPE int
#endif
+
+#endif
Modified: gnunet/src/util/network.c
===================================================================
--- gnunet/src/util/network.c 2011-12-06 17:29:30 UTC (rev 18472)
+++ gnunet/src/util/network.c 2011-12-06 17:58:40 UTC (rev 18473)
@@ -377,13 +377,20 @@
* @return NULL on error (including not supported on target platform)
*/
struct GNUNET_NETWORK_Handle *
-GNUNET_NETWORK_socket_box_native (int fd)
+GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
{
+ struct GNUNET_NETWORK_Handle *ret;
#if MINGW
- return NULL;
+ unsigned long i;
+ DWORD d;
+ /* FIXME: Find a better call to check that FD is valid */
+ if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL)
!= 0)
+ return NULL; /* invalid FD */
+ ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
+ ret->fd = fd;
+ ret->af = AF_UNSPEC;
+ return ret;
#else
- struct GNUNET_NETWORK_Handle *ret;
-
if (fcntl (fd, F_GETFD) < 0)
return NULL; /* invalid FD */
ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
Modified: gnunet/src/util/os_priority.c
===================================================================
--- gnunet/src/util/os_priority.c 2011-12-06 17:29:30 UTC (rev 18472)
+++ gnunet/src/util/os_priority.c 2011-12-06 17:58:40 UTC (rev 18473)
@@ -852,7 +852,8 @@
* @return process ID of the new process, -1 on error
*/
struct GNUNET_OS_Process *
-GNUNET_OS_start_process_v (const int *lsocks, const char *filename,
+GNUNET_OS_start_process_v (const SOCKTYPE *lsocks,
+ const char *filename,
char *const argv[])
{
#if ENABLE_WINDOWS_WORKAROUNDS
@@ -979,7 +980,7 @@
char path[MAX_PATH + 1];
- char *our_env[3] = { NULL, NULL, NULL };
+ char *our_env[5] = { NULL, NULL, NULL, NULL, NULL };
char *env_block = NULL;
char *pathbuf;
DWORD pathbuf_len, alloc_len;
@@ -988,8 +989,12 @@
char *libdir;
char *ptr;
char *non_const_filename;
+ struct GNUNET_DISK_PipeHandle *lsocks_pipe;
+ const struct GNUNET_DISK_FileHandle *lsocks_write_fd;
+ HANDLE lsocks_read;
+ HANDLE lsocks_write;
- GNUNET_assert (lsocks == NULL);
+ int fail;
/* Search in prefix dir (hopefully - the directory from which
* the current module was loaded), bindir and libdir, then in PATH
@@ -1103,7 +1108,26 @@
GNUNET_free (path);
return NULL;
}
+ if (lsocks != NULL)
+ {
+ lsocks_pipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO);
+ if (lsocks_pipe == NULL)
+ {
+ GNUNET_free (cmd);
+ GNUNET_free (path);
+ GNUNET_DISK_pipe_close (lsocks_pipe);
+ return NULL;
+ }
+ lsocks_write_fd = GNUNET_DISK_pipe_handle (lsocks_pipe,
+ GNUNET_DISK_PIPE_END_WRITE);
+ GNUNET_DISK_internal_file_handle_ (lsocks_write_fd,
+ &lsocks_write, sizeof (HANDLE));
+ GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle
+ (lsocks_pipe,
GNUNET_DISK_PIPE_END_READ),
+ &lsocks_read, sizeof (HANDLE));
+ }
+
#if DEBUG_OS
LOG (GNUNET_ERROR_TYPE_DEBUG, "Opened the parent end of the pipe `%s'\n",
childpipename);
@@ -1111,17 +1135,31 @@
GNUNET_asprintf (&our_env[0], "%s=", GNUNET_OS_CONTROL_PIPE);
GNUNET_asprintf (&our_env[1], "%s", childpipename);
- our_env[2] = NULL;
+ GNUNET_free (childpipename);
+ if (lsocks == NULL)
+ our_env[2] = NULL;
+ else
+ {
+ /*This will tell the child that we're going to send lsocks over the pipe*/
+ GNUNET_asprintf (&our_env[2], "%s=", "GNUNET_OS_READ_LSOCKS");
+ GNUNET_asprintf (&our_env[3], "%lu", lsocks_read);
+ our_env[4] = NULL;
+ }
env_block = CreateCustomEnvTable (our_env);
- GNUNET_free (our_env[0]);
- GNUNET_free (our_env[1]);
+ GNUNET_free_non_null (our_env[0]);
+ GNUNET_free_non_null (our_env[1]);
+ GNUNET_free_non_null (our_env[2]);
+ GNUNET_free_non_null (our_env[3]);
- if (!CreateProcess
- (path, cmd, NULL, NULL, FALSE, DETACHED_PROCESS | CREATE_SUSPENDED,
+ if (!CreateProcessA
+ (path, cmd, NULL, NULL, TRUE, DETACHED_PROCESS | CREATE_SUSPENDED,
env_block, NULL, &start, &proc))
{
SetErrnoFromWinError (GetLastError ());
LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "CreateProcess");
+ GNUNET_DISK_npipe_close (control_pipe);
+ if (lsocks != NULL)
+ GNUNET_DISK_pipe_close (lsocks_pipe);
GNUNET_free (env_block);
GNUNET_free (cmd);
return NULL;
@@ -1140,6 +1178,85 @@
CloseHandle (proc.hThread);
GNUNET_free (cmd);
+ if (lsocks == NULL)
+ return gnunet_proc;
+
+ GNUNET_DISK_pipe_close_end (lsocks_pipe, GNUNET_DISK_PIPE_END_READ);
+
+ /* This is a replacement for "goto error" that doesn't use goto */
+ fail = 1;
+ do
+ {
+ int wrote;
+ uint64_t size, count, i;
+
+ /* Tell the number of sockets */
+ for (count = 0; lsocks && lsocks[count] != INVALID_SOCKET; count++);
+
+ wrote = GNUNET_DISK_file_write (lsocks_write_fd, &count, sizeof (count));
+ if (wrote != sizeof (count))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write %u count bytes to
the child: %u\n", sizeof (count), GetLastError ());
+ break;
+ }
+ for (i = 0; lsocks && lsocks[i] != INVALID_SOCKET; i++)
+ {
+ WSAPROTOCOL_INFOA pi;
+ /* Get a socket duplication info */
+ if (SOCKET_ERROR == WSADuplicateSocketA (lsocks[i], gnunet_proc->pid,
&pi))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to duplicate an
socket[%llu]: %u\n", i, GetLastError ());
+ LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "CreateProcess");
+ break;
+ }
+ /* Synchronous I/O is not nice, but we can't schedule this:
+ * lsocks will be closed/freed by the caller soon, and until
+ * the child creates a duplicate, closing a socket here will
+ * close it for good.
+ */
+ /* Send the size of the structure
+ * (the child might be built with different headers...)
+ */
+ size = sizeof (pi);
+ wrote = GNUNET_DISK_file_write (lsocks_write_fd, &size, sizeof (size));
+ if (wrote != sizeof (size))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write %u size[%llu]
bytes to the child: %u\n", sizeof (size), i, GetLastError ());
+ break;
+ }
+ /* Finally! Send the data */
+ wrote = GNUNET_DISK_file_write (lsocks_write_fd, &pi, sizeof (pi));
+ if (wrote != sizeof (pi))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write %u socket[%llu]
bytes to the child: %u\n", sizeof (pi), i, GetLastError ());
+ break;
+ }
+ }
+ /* This will block us until the child makes a final read or closes
+ * the pipe (hence no 'wrote' check), since we have to wait for it
+ * to duplicate the last socket, before we return and start closing
+ * our own copies)
+ */
+ wrote = GNUNET_DISK_file_write (lsocks_write_fd, &count, sizeof (count));
+ fail = 0;
+ }
+ while (fail);
+
+ GNUNET_DISK_file_sync (lsocks_write_fd);
+ GNUNET_DISK_pipe_close (lsocks_pipe);
+
+ if (fail)
+ {
+ /* If we can't pass on the socket(s), the child will block forever,
+ * better put it out of its misery.
+ */
+ TerminateProcess (gnunet_proc->handle, 0);
+ CloseHandle (gnunet_proc->handle);
+ GNUNET_DISK_npipe_close (gnunet_proc->control_pipe);
+ GNUNET_free (gnunet_proc);
+ return NULL;
+ }
+
return gnunet_proc;
#endif
}
Modified: gnunet/src/util/service.c
===================================================================
--- gnunet/src/util/service.c 2011-12-06 17:29:30 UTC (rev 18472)
+++ gnunet/src/util/service.c 2011-12-06 17:58:40 UTC (rev 18473)
@@ -1079,7 +1079,90 @@
}
+#ifdef MINGW
/**
+ * @return GNUNET_YES if ok, GNUNET_NO if not ok (must bind yourself),
+ * and GNUNET_SYSERR on error.
+ */
+static int
+receive_sockets_from_parent (struct GNUNET_SERVICE_Context *sctx)
+{
+ const char *env_buf;
+ int fail;
+ uint64_t count, i;
+ HANDLE lsocks_pipe;
+
+ env_buf = getenv ("GNUNET_OS_READ_LSOCKS");
+ if ((env_buf == NULL) || (strlen (env_buf) <= 0))
+ {
+ return GNUNET_NO;
+ }
+ /* Using W32 API directly here, because this pipe will
+ * never be used outside of this function, and it's just too much of a bother
+ * to create a GNUnet API that boxes a HANDLE (the way it is done with socks)
+ */
+ lsocks_pipe = (HANDLE) strtoul (env_buf, NULL, 10);
+ if (lsocks_pipe == 0 || lsocks_pipe == INVALID_HANDLE_VALUE)
+ return GNUNET_NO;
+
+ fail = 1;
+ do
+ {
+ int ret;
+ int fail2;
+ DWORD rd;
+
+ ret = ReadFile (lsocks_pipe, &count, sizeof (count), &rd, NULL);
+ if (ret == 0 || rd != sizeof (count) || count == 0)
+ break;
+ sctx->lsocks =
+ GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (count + 1));
+
+ fail2 = 1;
+ for (i = 0; i < count; i++)
+ {
+ WSAPROTOCOL_INFOA pi;
+ uint64_t size;
+ SOCKET s;
+ ret = ReadFile (lsocks_pipe, &size, sizeof (size), &rd, NULL);
+ if (ret == 0 || rd != sizeof (size) || size != sizeof (pi))
+ break;
+ ret = ReadFile (lsocks_pipe, &pi, sizeof (pi), &rd, NULL);
+ if (ret == 0 || rd != sizeof (pi))
+ break;
+ s = WSASocketA (pi.iAddressFamily, pi.iSocketType, pi.iProtocol, &pi, 0,
WSA_FLAG_OVERLAPPED);
+ sctx->lsocks[i] = GNUNET_NETWORK_socket_box_native (s);
+ if (sctx->lsocks[i] == NULL)
+ break;
+ else if (i == count - 1)
+ fail2 = 0;
+ }
+ if (fail2)
+ break;
+ sctx->lsocks[count] = NULL;
+ fail = 0;
+ }
+ while (fail);
+
+ CloseHandle (lsocks_pipe);
+
+ if (fail)
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("Could not access a pre-bound socket, will try to bind myself\n"));
+ for (i = 0; sctx->lsocks[i] != NULL && i < count; i++)
+ GNUNET_break (0 == GNUNET_NETWORK_socket_close (sctx->lsocks[i]));
+ GNUNET_free (sctx->lsocks);
+ sctx->lsocks = NULL;
+ return GNUNET_NO;
+ }
+
+ return GNUNET_YES;
+}
+#endif
+
+
+/**
* Setup addr, addrlen, idle_timeout
* based on configuration!
*
@@ -1175,6 +1258,12 @@
unsetenv ("LISTEN_PID");
unsetenv ("LISTEN_FDS");
}
+#else
+ if (getenv ("GNUNET_OS_READ_LSOCKS") != NULL)
+ {
+ receive_sockets_from_parent (sctx);
+ putenv ("GNUNET_OS_READ_LSOCKS=");
+ }
#endif
if ((sctx->lsocks == NULL) &&
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r18473 - in gnunet/src: arm include util,
gnunet <=