Extract XP-only functions when initializing the IOCP port
authorNick Mathewson <nickm@torproject.org>
Thu, 29 Oct 2009 18:30:43 +0000 (18:30 +0000)
committerNick Mathewson <nickm@torproject.org>
Thu, 29 Oct 2009 18:30:43 +0000 (18:30 +0000)
svn:r1479

event_iocp.c
iocp-internal.h

index 4c144af687133a44b205db3f16f554d41205c742..b4350ef63955e1209e0dc418c0732ca2df676ec4 100644 (file)
@@ -28,6 +28,7 @@
 #include <windows.h>
 #include <process.h>
 #include <stdio.h>
+#include <mswsock.h>
 
 #include "event2/util.h"
 #include "util-internal.h"
@@ -98,12 +99,73 @@ event_iocp_port_associate(struct event_iocp_port *port, evutil_socket_t fd,
        return 0;
 }
 
+static void *
+get_extension_function(SOCKET s, const GUID *which_fn)
+{
+       void *ptr = NULL;
+       DWORD bytes=0;
+       WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
+           (GUID*)which_fn, sizeof(*which_fn),
+           &ptr, sizeof(ptr),
+           &bytes, NULL, NULL);
+
+       /* No need to detect errors here: if ptr is set, then we have a good
+          function pointer.  Otherwise, we should behave as if we had no
+          function pointer.
+       */
+       return ptr;
+}
+
+/* Mingw doesn't have these in its mswsock.h.  The values are copied from
+   wine.h.   Perhaps if we copy them exactly, the cargo will come again.
+*/
+#ifndef WSAID_ACCEPTEX
+#define WSAID_ACCEPTEX \
+       {0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
+#endif
+#ifndef WSAID_CONNECTEX
+#define WSAID_CONNECTEX \
+       {0x25a207b9,0xddf3,0x4660,{0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e}}
+#endif
+#ifndef WSAID_GETACCEPTEXSOCKADDRS
+#define WSAID_GETACCEPTEXSOCKADDRS \
+       {0xb5367df2,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
+#endif
+
+static void
+init_extension_functions(struct win32_extension_fns *ext)
+{
+       const GUID acceptex = WSAID_ACCEPTEX;
+       const GUID connectex = WSAID_CONNECTEX;
+       const GUID getacceptexsockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
+       SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
+       if (s == INVALID_SOCKET)
+               return;
+       ext->AcceptEx = get_extension_function(s, &acceptex);
+       ext->ConnectEx = get_extension_function(s, &connectex);
+       ext->GetAcceptExSockaddrs = get_extension_function(s,
+           &getacceptexsockaddrs);
+       closesocket(s);
+}
+
+static struct win32_extension_fns the_extension_fns;
+static int extension_fns_initialized = 0;
+
+const struct win32_extension_fns *
+event_get_win32_extension_fns(void)
+{
+       return &the_extension_fns;
+}
+
 struct event_iocp_port *
 event_iocp_port_launch(void)
 {
        struct event_iocp_port *port;
        int i;
 
+       if (!extension_fns_initialized)
+               init_extension_functions(&the_extension_fns);
+
        if (!(port = mm_calloc(1, sizeof(struct event_iocp_port))))
                return NULL;
        port->n_threads = 2;
index d743bd54207a079f1f926ef7a36755517bf41060..31024cc10ee34d852c74d2fbc23ecbd07e874ade 100644 (file)
@@ -53,6 +53,21 @@ struct event_overlapped {
        iocp_callback cb;
 };
 
+/* Mingw's headers don't define LPFN_ACCEPTEX. */
+
+typedef BOOL (WINAPI *AcceptExPtr)(SOCKET, SOCKET, PVOID, DWORD, DWORD, DWORD, LPDWORD, LPOVERLAPPED);
+typedef BOOL (WINAPI *ConnectExPtr)(SOCKET, const struct sockaddr *, int, PVOID, DWORD, LPDWORD, LPOVERLAPPED);
+typedef void (WINAPI *GetAcceptExSockaddrsPtr)(PVOID, DWORD, DWORD, DWORD, LPSOCKADDR *, LPINT, LPSOCKADDR *, LPINT);
+
+/** Internal use only. Holds pointers to functions that only some versions of
+    Windows provide.
+ */
+struct win32_extension_fns {
+       AcceptExPtr AcceptEx;
+       ConnectExPtr ConnectEx;
+       GetAcceptExSockaddrsPtr GetAcceptExSockaddrs;
+};
+
 /**
     Internal use only. Stores a Windows IO Completion port, along with
     related data.
@@ -73,9 +88,11 @@ struct event_iocp_port {
        HANDLE *threads;
        /** Number of threads currently open on this port. */
        short n_live_threads;
-       /* A semaphore to signal when we are done shutting down. */
+       /** A semaphore to signal when we are done shutting down. */
        HANDLE *shutdownSemaphore;
 };
+
+const struct win32_extension_fns *event_get_win32_extension_fns(void);
 #else
 /* Dummy definition so we can test-compile more things on unix. */
 struct event_overlapped {