1 module eventcore.drivers.winapi.dns; 2 3 version (Windows): 4 5 import eventcore.driver; 6 import eventcore.internal.win32; 7 8 9 final class WinAPIEventDriverDNS : EventDriverDNS { 10 @safe: /*@nogc:*/ nothrow: 11 12 DNSLookupID lookupHost(string name, DNSLookupCallback on_lookup_finished) 13 { 14 import std.typecons : scoped; 15 import std.utf : toUTF16z; 16 17 auto id = DNSLookupID(0, 0); 18 19 static immutable ushort[] addrfamilies = [AF_INET, AF_INET6]; 20 21 const(WCHAR)* namew; 22 try namew = name.toUTF16z; 23 catch (Exception e) return DNSLookupID.invalid; 24 25 foreach (af; addrfamilies) { 26 //if (family != af && family != AF_UNSPEC) continue; 27 28 SOCKADDR_STORAGE sa; 29 INT addrlen = sa.sizeof; 30 auto ret = () @trusted { return WSAStringToAddressW(namew, af, null, cast(sockaddr*)&sa, &addrlen); } (); 31 if (ret != 0) continue; 32 33 scope addr = new RefAddress(() @trusted { return cast(sockaddr*)&sa; } (), addrlen); 34 RefAddress[1] addrs; 35 addrs[0] = addr; 36 on_lookup_finished(id, DNSStatus.ok, addrs); 37 return id; 38 } 39 40 version (none) { // Windows 8+ 41 LookupStatus status; 42 status.task = Task.getThis(); 43 status.driver = this; 44 status.finished = false; 45 46 WSAOVERLAPPEDX overlapped; 47 overlapped.Internal = 0; 48 overlapped.InternalHigh = 0; 49 overlapped.hEvent = cast(HANDLE)cast(void*)&status; 50 51 void* aif; 52 ADDRINFOEXW addr_hint; 53 ADDRINFOEXW* addr_ret; 54 addr_hint.ai_family = family; 55 addr_hint.ai_socktype = SOCK_STREAM; 56 addr_hint.ai_protocol = IPPROTO_TCP; 57 58 enforce(GetAddrInfoExW(namew, null, NS_DNS, null, &addr_hint, &addr_ret, null, &overlapped, &onDnsResult, null) == 0, "Failed to lookup host"); 59 while (!status.finished) m_core.yieldForEvent(); 60 enforce(!status.error, "Failed to lookup host: "~to!string(status.error)); 61 62 aif = addr_ret; 63 addr.family = cast(ubyte)addr_ret.ai_family; 64 switch (addr.family) { 65 default: assert(false, "Invalid address family returned from host lookup."); 66 case AF_INET: addr.sockAddrInet4 = *cast(sockaddr_in*)addr_ret.ai_addr; break; 67 case AF_INET6: addr.sockAddrInet6 = *cast(sockaddr_in6*)addr_ret.ai_addr; break; 68 } 69 FreeAddrInfoExW(addr_ret); 70 } else { 71 ADDRINFOW* results; 72 if (auto ret = () @trusted { return GetAddrInfoW(namew, null, null, &results); } ()) { 73 on_lookup_finished(id, DNSStatus.error, null); 74 return id; 75 } 76 77 scope(failure) assert(false); 78 () @trusted { 79 typeof(scoped!RefAddress())[16] addr_storage = [ 80 scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), 81 scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), 82 scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), 83 scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress() 84 ]; 85 RefAddress[16] buf; 86 size_t naddr = 0; 87 while (results) { 88 RefAddress addr = addr_storage[naddr]; 89 addr.set(results.ai_addr, cast(socklen_t)results.ai_addrlen); 90 buf[naddr++] = addr; 91 results = results.ai_next; 92 } 93 94 on_lookup_finished(id, DNSStatus.ok, buf[0 .. naddr]); 95 } (); 96 } 97 98 return id; 99 } 100 101 void cancelLookup(DNSLookupID handle) 102 { 103 if (!isValid(handle)) return; 104 105 assert(false, "TODO!"); 106 } 107 108 override bool isValid(DNSLookupID handle) 109 const { 110 return handle == DNSLookupID(0, 0); 111 } 112 }