diff --git a/modules/renderer/dns/dns_resolver.ts b/modules/renderer/dns/dns_resolver.ts index ca54d2f..396ccf5 100644 --- a/modules/renderer/dns/dns_resolver.ts +++ b/modules/renderer/dns/dns_resolver.ts @@ -1,245 +1,38 @@ /// - window["require_setup"](module); - -import * as dns_handler from "dns"; +import * as dns_handler from "teaclient_dns"; namespace _dns { - type Lookup = (hostname: string, callback: (err: NodeJS.ErrnoException, result: R) => void) => void; - type AsyncLookup = (hostname: string, timeout: number) => Promise; - function make_async(fun: Lookup) : AsyncLookup { - return (hostname, timeout) => { - return new Promise((resolve, reject) => { - const timeout_id = setTimeout(() => { - reject("timeout"); - }, timeout); - fun(hostname, (err, result) => { - clearTimeout(timeout_id); - if(err) { - if(err.errno as any == "ENOTFOUND" || err.errno as any == "ENODATA") { - resolve(null); - return; - } - - reject(err); - } else - resolve(result); - }) - }); - }; - } - - const async_resolve_srv = make_async(dns_handler.resolveSrv); - const async_resolve_cname = make_async(dns_handler.resolveCname); - const async_resolve_a = make_async(dns_handler.resolve4); - const async_resolve_aaaa = make_async(dns_handler.resolve6); - const async_resolve_any = make_async(dns_handler.resolveAny); - - export interface AddressTarget { - target_ip: string; - target_port?: number; - } - export interface ResolveOptions extends dns.ResolveOptions { - log?: (message: string, ...args: any[]) => void; - override_port?: number; - } - export function supported() { return true; } - export async function resolve_address(address: string, _options?: ResolveOptions) : Promise { - if(address === "localhost") { - return { - target_ip: "localhost" - }; - } - - const options: ResolveOptions = {}; - Object.assign(options, dns.default_options); - Object.assign(options, _options || {}); - - if(options.max_depth <= 0) - throw "max depth exceeded"; - - if(typeof(options.log) !== "function") - options.log = (message, ...args) => console.debug("[DNS] " + message, ...args); - - const mod_options: ResolveOptions = {}; - Object.assign(mod_options, options); - mod_options.max_depth = mod_options.max_depth - 1; - mod_options.allow_srv = false; - mod_options.log = (message, ...args) => options.log(" " + message, ...args); - - options.log("Resolving %s", address); - - let response: AddressTarget; - if(typeof(options.allow_aaaa) !== "boolean" || options.allow_aaaa) { - const aaaa_response: string[] | undefined | null = await async_resolve_aaaa(address, options.timeout).catch(error => { - options.log("AAAA record resolved unsuccessfully (%o)", error); - return Promise.resolve(undefined); - }) as any; - - - if(typeof(aaaa_response) !== "undefined") { - if(!aaaa_response || aaaa_response.length == 0) - options.log("No AAAA records found"); - else { - options.log("Resolved AAAA records: %o. Returning: %s", aaaa_response, aaaa_response[0]); - response = { - target_ip: aaaa_response[0], - target_port: options.override_port - }; - } - } - } - if(!response && (typeof(options.allow_a) !== "boolean" || options.allow_a)) { - const a_response: string[] | undefined | null = await async_resolve_a(address, options.timeout).catch(error => { - options.log("A record resolved unsuccessfully (%o)", error); - return Promise.resolve(undefined); - }) as any; - - if(typeof(a_response) !== "undefined") { - if(!a_response || a_response.length == 0) - options.log("No A records found"); - else { - options.log("Resolved A records: %o. Returning: %s", a_response, a_response[0]); - response = { - target_ip: a_response[0], - target_port: options.override_port - }; - } + export async function resolve_address(address: ServerAddress, _options?: dns.ResolveOptions) : Promise { + /* backwards compatibility */ + if(typeof(address) === "string") { + address = { + host: address, + port: 9987 } } - if(!response && (typeof(options.allow_any) !== "boolean" || options.allow_any)) { - const any_response: dns_handler.AnyRecord[] = await async_resolve_any(address, options.timeout).catch(error => { - options.log("ANY record resolved unsuccessfully (%o)", error); - return Promise.resolve(undefined); + return new Promise((resolve, reject) => { + dns_handler.resolve_cr(address.host, address.port, result => { + if(typeof(result) === "string") + reject(result); + else + resolve({ + target_ip: result.host, + target_port: result.port + }); }); - - - if(typeof(any_response) !== "undefined") { - if(!any_response || any_response.length == 0) - options.log("No ANY records found"); - else { - options.log("Resolved ANY records: %o.", any_response); - for(const record of any_response) { - if(record.type === "A") { - const a_record = record as dns_handler.AnyARecord; - options.log("Returning A record from ANY query: %s", a_record.address); - return { - target_ip: a_record.address, - target_port: options.override_port - }; - } else if(record.type === "AAAA") { - const aaaa_record = record as dns_handler.AnyAaaaRecord; - options.log("Returning AAAA record from ANY query: %s", aaaa_record.address); - return { - target_ip: aaaa_record.address, - target_port: options.override_port - }; - } - } - } - } - } - - if(typeof(options.allow_srv) !== "boolean" || options.allow_srv) { - const response: dns_handler.SrvRecord[] = await async_resolve_srv("_ts3._udp." + address, options.timeout).catch(error => { - options.log("SRV resolve unsuccessfully (%o)", error); - return Promise.resolve(undefined); - }); - - if(typeof(response) !== "undefined") { - if(!response || response.length == 0) - options.log("No SRV records found"); - else { - const sorted = response.sort((a, b) => b.weight - a.weight); - const original_port = mod_options.override_port; - options.log("Resolved SRV records: %o", sorted); - for(const entry of sorted) { - options.log("Resolving SRV record: %o", entry); - mod_options.override_port = entry.port || mod_options.override_port; - const resp = await resolve_address(entry.name, mod_options).catch(error => { - options.log("SRV entry resolved unsuccessfully (%o)", error); - return Promise.resolve(undefined); - }); - if(resp) { - options.log("SRV entry resolved to %o. Found result", resp); - return resp; - } else { - options.log("No response for SRV record"); - } - } - mod_options.override_port = original_port; - } - } - } - - /* resolve CNAME in the last step, else may the A records will be empty! */ - if(typeof(options.allow_cname) !== "boolean" || options.allow_cname) { - const cname_response: string[] = await async_resolve_cname(address, options.timeout).catch(error => { - options.log("CName resolved unsuccessfully (%o)", error); - return Promise.resolve(undefined); - }); - - if(typeof(cname_response) !== "undefined") { - if(!cname_response || cname_response.length == 0) - options.log("No CNAME records found"); - else { - options.log("Resolved %d CNAME records", cname_response.length); - for(const entry of cname_response) { - options.log("Resolving CNAME record: %o", entry); - const resp = await resolve_address(entry, mod_options).catch(error => { - options.log("Failed to resolve resolved CName (%o)", error); - return Promise.resolve(undefined); - }); - if(resp) { - options.log("CName entry resolved to %o. Found result", resp); - return resp; - } else { - options.log("No response for CName record"); - } - } - response = undefined; /* overridden by a CNAME */ - } - } - } - - /* - const lookup_result = await new Promise((resolve, reject) => { - const timeout = setTimeout(() => { - reject("timeout"); - }, options.timeout); - dns_handler.lookup(address, { - hints: dns_handler.ADDRCONFIG | dns_handler.V4MAPPED, - all: true, - family: 0 - }, (error, result, family) => { - clearTimeout(timeout); - console.log(result); - if(error) { - if(error.errno as any == "ENOTFOUND" || error.errno as any == "ENODATA") { - resolve(null); - return; - } - - reject(error); - } else - resolve(result); - }); - }).catch(error => { - options.log("General lookup failed: %o", error); - return Promise.resolve(undefined); - }); - console.log(lookup_result); - */ - if(response) - return response; - options.log("No records found, no result."); - return undefined; + }) } - - dns_handler.setServers(["8.8.8.8", "8.8.8.4", "1.1.1.1"]); } -Object.assign(window["dns"] || (window["dns"] = {} as any), _dns); \ No newline at end of file +Object.assign(window["dns"] || (window["dns"] = {} as any), _dns); +loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, { + name: "Native DNS initialized", + function: async () => { + dns_handler.initialize(); + }, + priority: 10 +}); \ No newline at end of file