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
|
||||
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² | — | —
|
||||
|
|
1
dub.sdl
1
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"
|
||||
|
||||
|
|
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.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)
|
||||
|
|
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