From 356a34fad249df915e594af1379ca4656963d50c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Mon, 23 Jan 2017 21:37:35 +0100 Subject: [PATCH] Implement simple (synchronous) DNS lookup for the WinAPI driver. --- README.md | 2 +- dub.sdl | 1 + lib/ws2_32.lib | Bin 0 -> 19968 bytes source/eventcore/drivers/winapi.d | 87 +++++++++++++++- source/eventcore/internal/win32.d | 163 ++++++++++++++++++++++++++++++ 5 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 lib/ws2_32.lib create mode 100644 source/eventcore/internal/win32.d diff --git a/README.md b/README.md index a97c815..39a3268 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Feature | SelectEventDriver | EpollEventDriver | WinAPIEventDriver | Kq TCP Sockets | yes | yes | — | yes UDP Sockets | yes | yes | — | yes USDS | yes | yes | — | yes -DNS | yes | yes | — | yes +DNS | yes | yes | yes | yes Timers | yes | yes | yes | yes Events | yes | yes | yes | yes Unix Signals | yes² | yes² | — | — diff --git a/dub.sdl b/dub.sdl index d207b87..b717909 100644 --- a/dub.sdl +++ b/dub.sdl @@ -7,6 +7,7 @@ targetType "library" libs "anl" platform="linux" libs "ws2_32" "user32" platform="windows" +sourceFiles "lib/ws2_32.lib" platform="windows-x86-dmd" dependency "taggedalgebraic" version="~>0.10.4" diff --git a/lib/ws2_32.lib b/lib/ws2_32.lib new file mode 100644 index 0000000000000000000000000000000000000000..ec2490a55c9529bf04b9ba2422ad8e274212c5ff GIT binary patch literal 19968 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 literal 0 HcmV?d00001 diff --git a/source/eventcore/drivers/winapi.d b/source/eventcore/drivers/winapi.d index 4c35631..0b3ab80 100644 --- a/source/eventcore/drivers/winapi.d +++ b/source/eventcore/drivers/winapi.d @@ -13,6 +13,7 @@ import eventcore.driver; import eventcore.drivers.timer; import eventcore.internal.consumablequeue : ConsumableQueue; import eventcore.internal.utils; +import eventcore.internal.win32; import taggedalgebraic; import core.sys.windows.windows; import core.sys.windows.winsock2; @@ -357,7 +358,91 @@ final class WinAPIEventDriverDNS : EventDriverDNS { DNSLookupID lookupHost(string name, DNSLookupCallback on_lookup_finished) { - assert(false, "TODO!"); + import std.typecons : scoped; + import std.utf : toUTF16z; + + auto id = DNSLookupID(0); + + static immutable ushort[] addrfamilies = [AF_INET, AF_INET6]; + + const(WCHAR)* namew; + try namew = name.toUTF16z; + catch (Exception e) return DNSLookupID.invalid; + + foreach (af; addrfamilies) { + //if (family != af && family != AF_UNSPEC) continue; + + SOCKADDR_STORAGE sa; + INT addrlen = sa.sizeof; + auto ret = () @trusted { return WSAStringToAddressW(namew, af, null, cast(sockaddr*)&sa, &addrlen); } (); + if (ret != 0) continue; + + scope addr = new RefAddress(() @trusted { return cast(sockaddr*)&sa; } (), addrlen); + RefAddress[1] addrs; + addrs[0] = addr; + on_lookup_finished(id, DNSStatus.ok, addrs); + return id; + } + + version(none){ // Windows 8+ + LookupStatus status; + status.task = Task.getThis(); + status.driver = this; + status.finished = false; + + WSAOVERLAPPEDX overlapped; + overlapped.Internal = 0; + overlapped.InternalHigh = 0; + overlapped.hEvent = cast(HANDLE)cast(void*)&status; + + void* aif; + ADDRINFOEXW addr_hint; + ADDRINFOEXW* addr_ret; + addr_hint.ai_family = family; + addr_hint.ai_socktype = SOCK_STREAM; + addr_hint.ai_protocol = IPPROTO_TCP; + + enforce(GetAddrInfoExW(namew, null, NS_DNS, null, &addr_hint, &addr_ret, null, &overlapped, &onDnsResult, null) == 0, "Failed to lookup host"); + while( !status.finished ) m_core.yieldForEvent(); + enforce(!status.error, "Failed to lookup host: "~to!string(status.error)); + + aif = addr_ret; + addr.family = cast(ubyte)addr_ret.ai_family; + switch(addr.family){ + default: assert(false, "Invalid address family returned from host lookup."); + case AF_INET: addr.sockAddrInet4 = *cast(sockaddr_in*)addr_ret.ai_addr; break; + case AF_INET6: addr.sockAddrInet6 = *cast(sockaddr_in6*)addr_ret.ai_addr; break; + } + FreeAddrInfoExW(addr_ret); + } else { + ADDRINFOW* results; + if (auto ret = () @trusted { return GetAddrInfoW(namew, null, null, &results); } ()) { + on_lookup_finished(id, DNSStatus.error, null); + return id; + } + + scope(failure) assert(false); + () @trusted { + typeof(scoped!RefAddress())[16] addr_storage = [ + scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), + scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), + scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), + scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress() + ]; + RefAddress[16] buf; + size_t naddr = 0; + while (results) { + RefAddress addr = addr_storage[naddr]; + addr.set(results.ai_addr, results.ai_addrlen); + buf[naddr++] = addr; + results = results.ai_next; + } + + on_lookup_finished(id, DNSStatus.ok, buf[0 .. naddr]); + } (); + } + + return id; } void cancelLookup(DNSLookupID handle) diff --git a/source/eventcore/internal/win32.d b/source/eventcore/internal/win32.d new file mode 100644 index 0000000..549cdea --- /dev/null +++ b/source/eventcore/internal/win32.d @@ -0,0 +1,163 @@ +module eventcore.internal.win32; + +version(Windows): + +public import core.sys.windows.windows; +public import core.sys.windows.winsock2; + +extern(System) nothrow @nogc: + +BOOL GetFileSizeEx(HANDLE hFile, long *lpFileSize); + +enum { + FD_READ = 0x0001, + FD_WRITE = 0x0002, + FD_OOB = 0x0004, + FD_ACCEPT = 0x0008, + FD_CONNECT = 0x0010, + FD_CLOSE = 0x0020, + FD_QOS = 0x0040, + FD_GROUP_QOS = 0x0080, + FD_ROUTING_INTERFACE_CHANGE = 0x0100, + FD_ADDRESS_LIST_CHANGE = 0x0200 +} + + +enum { + WSA_FLAG_OVERLAPPED = 0x01 +} + +enum { + WSAPROTOCOL_LEN = 255, + MAX_PROTOCOL_CHAIN = 7, +} + +enum WSA_IO_PENDING = 997; + +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; +} + +struct WSAPROTOCOLCHAIN { + int ChainLen; + DWORD[MAX_PROTOCOL_CHAIN] ChainEntries; +} + +struct WSABUF { + size_t len; + ubyte *buf; +} + +struct ADDRINFOEXW { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + LPCWSTR ai_canonname; + sockaddr* ai_addr; + void* ai_blob; + size_t ai_bloblen; + GUID* ai_provider; + ADDRINFOEXW* ai_next; +} + +struct ADDRINFOA { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + LPSTR ai_canonname; + sockaddr* ai_addr; + ADDRINFOA* ai_next; +} + +struct ADDRINFOW { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + LPWSTR ai_canonname; + sockaddr* ai_addr; + ADDRINFOW* ai_next; +} + +struct WSAPROTOCOL_INFO { + 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; + CHAR[WSAPROTOCOL_LEN+1] szProtocol; +} +alias SOCKADDR = sockaddr; + +alias LPWSAOVERLAPPED_COMPLETION_ROUTINEX = void function(DWORD, DWORD, WSAOVERLAPPEDX*, DWORD); +alias LPLOOKUPSERVICE_COMPLETION_ROUTINE = void function(DWORD, DWORD, WSAOVERLAPPEDX*); +alias LPCONDITIONPROC = void*; +alias LPTRANSMIT_FILE_BUFFERS = void*; + +SOCKET WSAAccept(SOCKET s, sockaddr *addr, INT* addrlen, LPCONDITIONPROC lpfnCondition, DWORD_PTR dwCallbackData); +int WSAAsyncSelect(SOCKET s, HWND hWnd, uint wMsg, sizediff_t lEvent); +SOCKET WSASocketW(int af, int type, int protocol, WSAPROTOCOL_INFOW *lpProtocolInfo, uint g, DWORD dwFlags); +int WSARecv(SOCKET s, WSABUF* lpBuffers, DWORD dwBufferCount, DWORD* lpNumberOfBytesRecvd, DWORD* lpFlags, in WSAOVERLAPPEDX* lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINEX lpCompletionRoutine); +int WSASend(SOCKET s, in WSABUF* lpBuffers, DWORD dwBufferCount, DWORD* lpNumberOfBytesSent, DWORD dwFlags, in WSAOVERLAPPEDX* lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINEX lpCompletionRoutine); +int WSASendDisconnect(SOCKET s, WSABUF* lpOutboundDisconnectData); +INT WSAStringToAddressA(in LPTSTR AddressString, INT AddressFamily, in WSAPROTOCOL_INFO* lpProtocolInfo, SOCKADDR* lpAddress, INT* lpAddressLength); +INT WSAStringToAddressW(in LPWSTR AddressString, INT AddressFamily, in WSAPROTOCOL_INFOW* lpProtocolInfo, SOCKADDR* lpAddress, INT* lpAddressLength); +INT WSAAddressToStringW(in SOCKADDR* lpsaAddress, DWORD dwAddressLength, in WSAPROTOCOL_INFO* lpProtocolInfo, LPWSTR lpszAddressString, DWORD* lpdwAddressStringLength); +int GetAddrInfoExW(LPCWSTR pName, LPCWSTR pServiceName, DWORD dwNameSpace, GUID* lpNspId, const ADDRINFOEXW *pHints, ADDRINFOEXW **ppResult, timeval *timeout, WSAOVERLAPPEDX* lpOverlapped, LPLOOKUPSERVICE_COMPLETION_ROUTINE lpCompletionRoutine, HANDLE* lpNameHandle); +int GetAddrInfoW(LPCWSTR pName, LPCWSTR pServiceName, const ADDRINFOW *pHints, ADDRINFOW **ppResult); +int getaddrinfo(LPCSTR pName, LPCSTR pServiceName, const ADDRINFOA *pHints, ADDRINFOA **ppResult); +void FreeAddrInfoW(ADDRINFOW* pAddrInfo); +void FreeAddrInfoExW(ADDRINFOEXW* pAddrInfo); +void freeaddrinfo(ADDRINFOA* ai); +BOOL TransmitFile(SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesToWrite, DWORD nNumberOfBytesPerSend, OVERLAPPED* lpOverlapped, LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, DWORD dwFlags); + +struct WSAOVERLAPPEDX { + ULONG_PTR Internal; + ULONG_PTR InternalHigh; + union { + struct { + DWORD Offset; + DWORD OffsetHigh; + } + PVOID Pointer; + } + HANDLE hEvent; +}