diff --git a/dub.json b/dub.json index bc086988..0c94f8a2 100644 --- a/dub.json +++ b/dub.json @@ -13,6 +13,7 @@ "money": "~>3.0.2" }, "targetType": "sourceLibrary", + "libs-windows": ["ws2_32"], "-ddoxTool": "scod", "configurations": [ { diff --git a/src/dpq2/connection.d b/src/dpq2/connection.d index ffd0377b..898834a9 100644 --- a/src/dpq2/connection.d +++ b/src/dpq2/connection.d @@ -207,27 +207,55 @@ class Connection } /// Obtains duplicate file descriptor number of the connection socket to the server + version(Posix) socket_t posixSocketDuplicate() { - version(Windows) - { - assert(false, "FIXME: implement socket duplication"); - } - else // Posix OS - { - import core.sys.posix.unistd: dup; + import core.sys.posix.unistd: dup; - return cast(socket_t) dup(cast(socket_t) posixSocket); - } + static assert(socket_t.sizeof == int.sizeof); + + return cast(socket_t) dup(cast(socket_t) posixSocket); + } + + /// Obtains duplicate file descriptor number of the connection socket to the server + version(Windows) + SOCKET posixSocketDuplicate() + { + import core.stdc.stdlib: malloc, free; + import core.sys.windows.winbase: GetCurrentProcessId; + + auto protocolInfo = cast(WSAPROTOCOL_INFOW*) malloc(WSAPROTOCOL_INFOW.sizeof); + scope(failure) free(protocolInfo); + + int dupStatus = WSADuplicateSocketW(posixSocket, GetCurrentProcessId, protocolInfo); + + if(dupStatus) + throw new ConnectionException("WSADuplicateSocketW error, code "~WSAGetLastError().to!string); + + SOCKET s = WSASocketW( + FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, + protocolInfo, + 0, + 0 + ); + + if(s == INVALID_SOCKET) + throw new ConnectionException("WSASocket error, code "~WSAGetLastError().to!string); + + return s; } /// Obtains std.socket.Socket of the connection to the server /// - /// Due to a limitation of Socket actually for the Socket creation + /// Due to a limitation of Dlang Socket actually for the Socket creation /// duplicate of internal posix socket will be used. Socket socket() { - return new Socket(posixSocketDuplicate, AddressFamily.UNSPEC); + version(Windows) static assert(SOCKET.sizeof == socket_t.sizeof); + + return new Socket(cast(socket_t) posixSocketDuplicate, AddressFamily.UNSPEC); } /// Returns the error message most recently generated by an operation on the connection @@ -401,6 +429,58 @@ class Connection } } +// Socket duplication stuff for Win32 +version(Windows) +private +{ + import core.sys.windows.windef; + import core.sys.windows.basetyps: GUID; + + alias GROUP = uint; + + enum INVALID_SOCKET = 0; + enum FROM_PROTOCOL_INFO =-1; + enum MAX_PROTOCOL_CHAIN = 7; + enum WSAPROTOCOL_LEN = 255; + + struct WSAPROTOCOLCHAIN + { + int ChainLen; + DWORD[MAX_PROTOCOL_CHAIN] ChainEntries; + } + + struct WSAPROTOCOL_INFOW + { + DWORD dwServiceFlags1; + DWORD dwServiceFlags2; + DWORD dwServiceFlags3; + DWORD dwServiceFlags4; + DWORD dwProviderFlags; + GUID ProviderId; + DWORD dwCatalogEntryId; + WSAPROTOCOLCHAIN ProtocolChain; + int iVersion; + int iAddressFamily; + int iMaxSockAddr; + int iMinSockAddr; + int iSocketType; + int iProtocol; + int iProtocolMaxOffset; + int iNetworkByteOrder; + int iSecurityScheme; + DWORD dwMessageSize; + DWORD dwProviderReserved; + WCHAR[WSAPROTOCOL_LEN+1] szProtocol; + } + + extern(Windows) nothrow @nogc + { + import core.sys.windows.winsock2: WSAGetLastError; + int WSADuplicateSocketW(SOCKET s, DWORD dwProcessId, WSAPROTOCOL_INFOW* lpProtocolInfo); + SOCKET WSASocketW(int af, int type, int protocol, WSAPROTOCOL_INFOW*, GROUP, DWORD dwFlags); + } +} + private auto keyValToPQparamsArrays(in string[string] keyValueParams) { static struct PQparamsArrays