Implement simple (synchronous) DNS lookup for the WinAPI driver.
This commit is contained in:
parent
e8a0968ded
commit
356a34fad2
|
@ -30,7 +30,7 @@ Feature | SelectEventDriver | EpollEventDriver | WinAPIEventDriver | Kq
|
||||||
TCP Sockets | yes | yes | — | yes
|
TCP Sockets | yes | yes | — | yes
|
||||||
UDP Sockets | yes | yes | — | yes
|
UDP Sockets | yes | yes | — | yes
|
||||||
USDS | yes | yes | — | yes
|
USDS | yes | yes | — | yes
|
||||||
DNS | yes | yes | — | yes
|
DNS | yes | yes | yes | yes
|
||||||
Timers | yes | yes | yes | yes
|
Timers | yes | yes | yes | yes
|
||||||
Events | yes | yes | yes | yes
|
Events | yes | yes | yes | yes
|
||||||
Unix Signals | yes² | yes² | — | —
|
Unix Signals | yes² | yes² | — | —
|
||||||
|
|
1
dub.sdl
1
dub.sdl
|
@ -7,6 +7,7 @@ targetType "library"
|
||||||
|
|
||||||
libs "anl" platform="linux"
|
libs "anl" platform="linux"
|
||||||
libs "ws2_32" "user32" platform="windows"
|
libs "ws2_32" "user32" platform="windows"
|
||||||
|
sourceFiles "lib/ws2_32.lib" platform="windows-x86-dmd"
|
||||||
|
|
||||||
dependency "taggedalgebraic" version="~>0.10.4"
|
dependency "taggedalgebraic" version="~>0.10.4"
|
||||||
|
|
||||||
|
|
BIN
lib/ws2_32.lib
Normal file
BIN
lib/ws2_32.lib
Normal file
Binary file not shown.
|
@ -13,6 +13,7 @@ import eventcore.driver;
|
||||||
import eventcore.drivers.timer;
|
import eventcore.drivers.timer;
|
||||||
import eventcore.internal.consumablequeue : ConsumableQueue;
|
import eventcore.internal.consumablequeue : ConsumableQueue;
|
||||||
import eventcore.internal.utils;
|
import eventcore.internal.utils;
|
||||||
|
import eventcore.internal.win32;
|
||||||
import taggedalgebraic;
|
import taggedalgebraic;
|
||||||
import core.sys.windows.windows;
|
import core.sys.windows.windows;
|
||||||
import core.sys.windows.winsock2;
|
import core.sys.windows.winsock2;
|
||||||
|
@ -357,7 +358,91 @@ final class WinAPIEventDriverDNS : EventDriverDNS {
|
||||||
|
|
||||||
DNSLookupID lookupHost(string name, DNSLookupCallback on_lookup_finished)
|
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)
|
void cancelLookup(DNSLookupID handle)
|
||||||
|
|
163
source/eventcore/internal/win32.d
Normal file
163
source/eventcore/internal/win32.d
Normal file
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in a new issue