1 module upromised.dns; 2 import deimos.libuv.uv : uv_getaddrinfo, uv_getaddrinfo_t, uv_freeaddrinfo, uv_loop_t, uv_interface_address_t, uv_interface_addresses, uv_free_interface_addresses; 3 import deimos.libuv._d : addrinfo; 4 import std.socket : Address; 5 import upromised.promise : DelegatePromise, Promise; 6 import upromised.memory : getSelf, gcretain, gcrelease; 7 import upromised.uv : uvCheck; 8 version(Posix) { 9 public import core.sys.posix.netdb : sockaddr, sockaddr_in, sockaddr_in6; 10 } else version(Windows) { 11 public import core.sys.windows.winsock2 : sockaddr, sockaddr_in, sockaddr_in6; 12 } 13 14 Address[] toAddress(const(addrinfo)* each) nothrow { 15 Address[] r; 16 while (each !is null) { 17 r ~= each.ai_addr.toAddress(each.ai_addrlen); 18 each = each.ai_next; 19 } 20 return r; 21 } 22 23 Address toAddress(const(sockaddr)* each, size_t len = 16) nothrow { 24 import std.socket : AddressFamily, InternetAddress, Internet6Address, UnknownAddressReference; 25 26 if (each is null) { 27 return null; 28 } else if (each.sa_family == AddressFamily.INET) { 29 return new InternetAddress(*cast(sockaddr_in*)each); 30 } else if (each.sa_family == AddressFamily.INET6) { 31 return new Internet6Address(*cast(sockaddr_in6*)each); 32 } else { 33 ubyte[] copy = new ubyte[len]; 34 copy[] = (cast(const(ubyte)*)(each))[0..len]; 35 return new UnknownAddressReference(cast(sockaddr*)copy.ptr, cast(int)copy.length); 36 } 37 } 38 39 Promise!(Address[]) getAddrinfo(uv_loop_t* ctx, const(char)[] node, ushort port) nothrow { 40 import std.conv : to; 41 return getAddrinfo(ctx, node, port.to!string); 42 } 43 Promise!(Address[]) getAddrinfo(uv_loop_t* ctx, const(char)[] node, const(char)[] service) nothrow { 44 import std..string : toStringz; 45 auto r = new GetAddrinfoPromise; 46 47 if (node !is null) { 48 r.node = node.toStringz; 49 } 50 51 if (service !is null) { 52 r.service = service.toStringz; 53 } 54 55 gcretain(r); 56 int err = uv_getaddrinfo(ctx, &r.self, (rSelf, status, res) nothrow { 57 auto r = getSelf!GetAddrinfoPromise(rSelf); 58 if (status.uvCheck(r)) return; 59 r.resolve(res.toAddress); 60 uv_freeaddrinfo(res); 61 }, r.node, r.service, null); 62 err.uvCheck(r); 63 r.finall(() => gcrelease(r)); 64 return r; 65 } 66 private class GetAddrinfoPromise : DelegatePromise!(Address[]) { 67 const(char)* node; 68 const(char)* service; 69 uv_getaddrinfo_t self; 70 } 71 72 Address[] listLocalAddresses() { 73 import std.array : array; 74 import std.algorithm : filter, map; 75 import std.socket : AddressFamily; 76 77 uv_interface_address_t* info; 78 int count; 79 uv_interface_addresses(&info, &count); 80 scope(exit) uv_free_interface_addresses(info, count); 81 82 return info[0..count] 83 .filter!((x) => !x.is_internal) 84 .map!((x) { 85 if (x.address.address4.sin_family == AddressFamily.INET6) { 86 return toAddress(cast(const(sockaddr)*)&x.address.address6, x.address.address6.sizeof); 87 } else { 88 return toAddress(cast(const(sockaddr)*)&x.address.address4, x.address.address4.sizeof); 89 } 90 }).array; 91 }