Browse Source

LibCore: Implement System::socketpair on Windows

stasoid 6 tháng trước cách đây
mục cha
commit
97147b4aa0

+ 1 - 0
Libraries/LibCore/System.h

@@ -32,6 +32,7 @@
 #    include <termios.h>
 #    include <termios.h>
 #    include <utime.h>
 #    include <utime.h>
 #else
 #else
+#    include "SockAddr-Win.h"
 #    define O_CLOEXEC O_NOINHERIT
 #    define O_CLOEXEC O_NOINHERIT
 using sighandler_t = void (*)(int);
 using sighandler_t = void (*)(int);
 using socklen_t = int;
 using socklen_t = int;

+ 107 - 0
Libraries/LibCore/SystemWindows.cpp

@@ -189,4 +189,111 @@ int getpid()
     return GetCurrentProcessId();
     return GetCurrentProcessId();
 }
 }
 
 
+/* https://github.com/ncm/selectable-socketpair
+Copyright 2007, 2010 by Nathan C. Myers <ncm@cantrip.org>
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    Redistributions of source code must retain the above copyright notice, this
+    list of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+    The name of the author must not be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+static int dumb_socketpair(SOCKET socks[2], int make_overlapped)
+{
+    union {
+        struct sockaddr_in inaddr;
+        struct sockaddr addr;
+    } a;
+    SOCKET listener;
+    int e;
+    socklen_t addrlen = sizeof(a.inaddr);
+    DWORD flags = (make_overlapped ? WSA_FLAG_OVERLAPPED : 0);
+    int reuse = 1;
+
+    if (socks == 0) {
+        WSASetLastError(WSAEINVAL);
+        return SOCKET_ERROR;
+    }
+    socks[0] = socks[1] = -1;
+
+    listener = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (listener == INVALID_SOCKET)
+        return SOCKET_ERROR;
+
+    memset(&a, 0, sizeof(a));
+    a.inaddr.sin_family = AF_INET;
+    a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+    a.inaddr.sin_port = 0;
+
+    for (;;) {
+        if (::setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, (socklen_t)sizeof(reuse)) == -1)
+            break;
+        if (bind(listener, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR)
+            break;
+
+        memset(&a, 0, sizeof(a));
+        if (getsockname(listener, &a.addr, &addrlen) == SOCKET_ERROR)
+            break;
+        // win32 getsockname may only set the port number, p=0.0005.
+        // ( http://msdn.microsoft.com/library/ms738543.aspx ):
+        a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+        a.inaddr.sin_family = AF_INET;
+
+        if (::listen(listener, 1) == SOCKET_ERROR)
+            break;
+
+        socks[0] = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, flags);
+        if (socks[0] == INVALID_SOCKET)
+            break;
+        if (connect(socks[0], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR)
+            break;
+
+        socks[1] = ::accept(listener, NULL, NULL);
+        if (socks[1] == INVALID_SOCKET)
+            break;
+
+        closesocket(listener);
+        return 0;
+    }
+
+    e = WSAGetLastError();
+    closesocket(listener);
+    closesocket(socks[0]);
+    closesocket(socks[1]);
+    WSASetLastError(e);
+    socks[0] = socks[1] = -1;
+    return SOCKET_ERROR;
+}
+
+ErrorOr<void> socketpair(int domain, int type, int protocol, int sv[2])
+{
+    if (domain != AF_LOCAL || type != SOCK_STREAM || protocol != 0)
+        return Error::from_string_literal("Unsupported argument value");
+
+    SOCKET socks[2] = {};
+    if (dumb_socketpair(socks, true))
+        return Error::from_windows_error();
+
+    sv[0] = handle_to_fd(socks[0], SocketHandle);
+    sv[1] = handle_to_fd(socks[1], SocketHandle);
+    return {};
+}
+
 }
 }