settings and resolver
parent
8b502811a4
commit
1c28f62f36
|
@ -1,10 +1,10 @@
|
|||
import {LogCategory, logError, logInfo, logTrace} from "./log";
|
||||
import { LogCategory, logError, logInfo, logTrace } from "./log";
|
||||
import * as loader from "tc-loader";
|
||||
import {Stage} from "tc-loader";
|
||||
import {Registry} from "./events";
|
||||
import {tr} from "./i18n/localize";
|
||||
import {CallOnce, ignorePromise} from "tc-shared/proto";
|
||||
import {getStorageAdapter} from "tc-shared/StorageAdapter";
|
||||
import { Stage } from "tc-loader";
|
||||
import { Registry } from "./events";
|
||||
import { tr } from "./i18n/localize";
|
||||
import { CallOnce, ignorePromise } from "tc-shared/proto";
|
||||
import { getStorageAdapter } from "tc-shared/StorageAdapter";
|
||||
|
||||
/*
|
||||
* TODO: Sync settings across renderer instances
|
||||
|
@ -14,17 +14,17 @@ export type RegistryValueType = boolean | number | string | object;
|
|||
export type RegistryValueTypeNames = "boolean" | "number" | "string" | "object";
|
||||
|
||||
export type RegistryValueTypeMapping<T> = T extends boolean ? "boolean" :
|
||||
T extends number ? "number" :
|
||||
T extends string ? "string" :
|
||||
T extends object ? "object" :
|
||||
never;
|
||||
T extends number ? "number" :
|
||||
T extends string ? "string" :
|
||||
T extends object ? "object" :
|
||||
never;
|
||||
|
||||
export interface RegistryKey<ValueType extends RegistryValueType> {
|
||||
key: string;
|
||||
valueType: RegistryValueTypeMapping<ValueType>;
|
||||
|
||||
fallbackKeys?: string | string[];
|
||||
fallbackImports?: {[key: string]:(value: string) => ValueType};
|
||||
fallbackImports?: { [key: string]: (value: string) => ValueType };
|
||||
|
||||
description?: string;
|
||||
|
||||
|
@ -37,7 +37,7 @@ export interface ValuedRegistryKey<ValueType extends RegistryValueType> extends
|
|||
|
||||
const UPDATE_DIRECT: boolean = true;
|
||||
|
||||
function decodeValueFromString<T extends RegistryValueType>(input: string, type: RegistryValueTypeMapping<T>) : T {
|
||||
function decodeValueFromString<T extends RegistryValueType>(input: string, type: RegistryValueTypeMapping<T>): T {
|
||||
switch (type) {
|
||||
case "string":
|
||||
return input as any;
|
||||
|
@ -60,7 +60,7 @@ function decodeValueFromString<T extends RegistryValueType>(input: string, type:
|
|||
}
|
||||
}
|
||||
|
||||
export function encodeSettingValueToString<T extends RegistryValueType>(input: T) : string {
|
||||
export function encodeSettingValueToString<T extends RegistryValueType>(input: T): string {
|
||||
switch (typeof input) {
|
||||
case "string":
|
||||
return input;
|
||||
|
@ -83,24 +83,24 @@ export function resolveSettingKey<ValueType extends RegistryValueType, DefaultTy
|
|||
key: RegistryKey<ValueType>,
|
||||
resolver: (key: string) => string | undefined | null,
|
||||
defaultValue: DefaultType
|
||||
) : ValueType | DefaultType {
|
||||
): ValueType | DefaultType {
|
||||
let value = resolver(key.key);
|
||||
|
||||
const keys = [key.key];
|
||||
if(Array.isArray(key.fallbackKeys)) {
|
||||
if (Array.isArray(key.fallbackKeys)) {
|
||||
keys.push(...key.fallbackKeys);
|
||||
}
|
||||
|
||||
for(const resolveKey of keys) {
|
||||
for (const resolveKey of keys) {
|
||||
value = resolver(resolveKey);
|
||||
if(typeof value !== "string") {
|
||||
if (typeof value !== "string") {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (key.valueType) {
|
||||
case "number":
|
||||
case "boolean":
|
||||
if(value.length === 0) {
|
||||
if (value.length === 0) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
@ -109,9 +109,9 @@ export function resolveSettingKey<ValueType extends RegistryValueType, DefaultTy
|
|||
break;
|
||||
}
|
||||
|
||||
if(key.fallbackImports) {
|
||||
if (key.fallbackImports) {
|
||||
const fallbackValueImporter = key.fallbackImports[resolveKey];
|
||||
if(fallbackValueImporter) {
|
||||
if (fallbackValueImporter) {
|
||||
return fallbackValueImporter(value);
|
||||
}
|
||||
}
|
||||
|
@ -129,21 +129,21 @@ export class UrlParameterParser {
|
|||
this.url = url;
|
||||
}
|
||||
|
||||
private getParameter(key: string) : string | undefined {
|
||||
private getParameter(key: string): string | undefined {
|
||||
const value = this.url.searchParams.get(key);
|
||||
if(value === null) {
|
||||
if (value === null) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return decodeURIComponent(value);
|
||||
}
|
||||
|
||||
getValue<V extends RegistryValueType, DV>(key: RegistryKey<V>, defaultValue: DV) : V | DV;
|
||||
getValue<V extends RegistryValueType>(key: ValuedRegistryKey<V>, defaultValue?: V) : V;
|
||||
getValue<V extends RegistryValueType, DV>(key: RegistryKey<V> | ValuedRegistryKey<V>, defaultValue: DV) : V | DV {
|
||||
if(arguments.length > 1) {
|
||||
getValue<V extends RegistryValueType, DV>(key: RegistryKey<V>, defaultValue: DV): V | DV;
|
||||
getValue<V extends RegistryValueType>(key: ValuedRegistryKey<V>, defaultValue?: V): V;
|
||||
getValue<V extends RegistryValueType, DV>(key: RegistryKey<V> | ValuedRegistryKey<V>, defaultValue: DV): V | DV {
|
||||
if (arguments.length > 1) {
|
||||
return resolveSettingKey(key, key => this.getParameter(key), defaultValue);
|
||||
} else if("defaultValue" in key) {
|
||||
} else if ("defaultValue" in key) {
|
||||
return resolveSettingKey(key, key => this.getParameter(key), key.defaultValue);
|
||||
} else {
|
||||
throw tr("missing value");
|
||||
|
@ -155,14 +155,14 @@ export class UrlParameterBuilder {
|
|||
private parameters = {};
|
||||
|
||||
setValue<V extends RegistryValueType>(key: RegistryKey<V>, value: V) {
|
||||
if(value === undefined) {
|
||||
if (value === undefined) {
|
||||
delete this.parameters[key.key];
|
||||
} else {
|
||||
this.parameters[key.key] = encodeURIComponent(encodeSettingValueToString(value));
|
||||
}
|
||||
}
|
||||
|
||||
build() : string {
|
||||
build(): string {
|
||||
return Object.keys(this.parameters).map(key => `${key}=${this.parameters[key]}`).join("&");
|
||||
}
|
||||
}
|
||||
|
@ -174,12 +174,12 @@ export class UrlParameterBuilder {
|
|||
export namespace AppParameters {
|
||||
export const Instance = new UrlParameterParser(new URL(window.location.href));
|
||||
|
||||
export function getValue<V extends RegistryValueType, DV>(key: RegistryKey<V>, defaultValue: DV) : V | DV;
|
||||
export function getValue<V extends RegistryValueType>(key: ValuedRegistryKey<V>, defaultValue?: V) : V;
|
||||
export function getValue<V extends RegistryValueType, DV>(key: RegistryKey<V> | ValuedRegistryKey<V>, defaultValue: DV) : V | DV {
|
||||
if(arguments.length > 1) {
|
||||
export function getValue<V extends RegistryValueType, DV>(key: RegistryKey<V>, defaultValue: DV): V | DV;
|
||||
export function getValue<V extends RegistryValueType>(key: ValuedRegistryKey<V>, defaultValue?: V): V;
|
||||
export function getValue<V extends RegistryValueType, DV>(key: RegistryKey<V> | ValuedRegistryKey<V>, defaultValue: DV): V | DV {
|
||||
if (arguments.length > 1) {
|
||||
return Instance.getValue(key, defaultValue);
|
||||
} else if("defaultValue" in key) {
|
||||
} else if ("defaultValue" in key) {
|
||||
return Instance.getValue(key);
|
||||
} else {
|
||||
throw tr("missing value");
|
||||
|
@ -408,12 +408,12 @@ export class Settings {
|
|||
static readonly KEY_FLAG_CONNECT_DEFAULT: ValuedRegistryKey<boolean> = {
|
||||
key: "connect_default",
|
||||
valueType: "boolean",
|
||||
defaultValue: false
|
||||
defaultValue: true
|
||||
};
|
||||
static readonly KEY_CONNECT_ADDRESS: ValuedRegistryKey<string> = {
|
||||
key: "connect_address",
|
||||
valueType: "string",
|
||||
defaultValue: undefined
|
||||
defaultValue: "tea.lp.kle.li"
|
||||
};
|
||||
static readonly KEY_CONNECT_PROFILE: ValuedRegistryKey<string> = {
|
||||
key: "connect_profile",
|
||||
|
@ -448,7 +448,7 @@ export class Settings {
|
|||
|
||||
static readonly KEY_CONNECT_NO_DNSPROXY: ValuedRegistryKey<boolean> = {
|
||||
key: "connect_no_dnsproxy",
|
||||
defaultValue: false,
|
||||
defaultValue: true,
|
||||
valueType: "boolean",
|
||||
};
|
||||
|
||||
|
@ -616,7 +616,7 @@ export class Settings {
|
|||
/* defaultValue: <users download directory> */
|
||||
};
|
||||
|
||||
static readonly KEY_IPC_REMOTE_ADDRESS: RegistryKey<string> = {
|
||||
static readonly KEY_IPC_REMOTE_ADDRESS: RegistryKey<string> = {
|
||||
key: "ipc-address",
|
||||
valueType: "string"
|
||||
};
|
||||
|
@ -913,8 +913,8 @@ export class Settings {
|
|||
static readonly KEYS = (() => {
|
||||
const result = [];
|
||||
|
||||
for(const key of Object.keys(Settings)) {
|
||||
if(!key.toUpperCase().startsWith("KEY_")) {
|
||||
for (const key of Object.keys(Settings)) {
|
||||
if (!key.toUpperCase().startsWith("KEY_")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -943,13 +943,13 @@ export class Settings {
|
|||
const json = await getStorageAdapter().get("settings.global");
|
||||
|
||||
try {
|
||||
if(json === null) {
|
||||
if (json === null) {
|
||||
logInfo(LogCategory.GENERAL, tr("Found no settings. Creating new client settings."));
|
||||
this.settingsCache = {};
|
||||
} else {
|
||||
this.settingsCache = JSON.parse(json);
|
||||
}
|
||||
} catch(error) {
|
||||
} catch (error) {
|
||||
this.settingsCache = {};
|
||||
logError(LogCategory.GENERAL, tr("Failed to load global settings!\nJson: %s\nError: %o"), json, error);
|
||||
|
||||
|
@ -957,7 +957,7 @@ export class Settings {
|
|||
//FIXME: Readd this
|
||||
//createErrorModal(tr("Failed to load global settings"), tr("Failed to load global client settings!\nLookup console for more information.")).open();
|
||||
};
|
||||
if(!loader.finished()) {
|
||||
if (!loader.finished()) {
|
||||
loader.register_task(loader.Stage.LOADED, {
|
||||
priority: 0,
|
||||
name: "Settings error",
|
||||
|
@ -969,18 +969,18 @@ export class Settings {
|
|||
}
|
||||
|
||||
this.saveWorker = setInterval(() => {
|
||||
if(this.updated) {
|
||||
if (this.updated) {
|
||||
this.save();
|
||||
}
|
||||
}, 5 * 1000);
|
||||
}
|
||||
|
||||
getValue<V extends RegistryValueType, DV>(key: RegistryKey<V>, defaultValue: DV) : V | DV;
|
||||
getValue<V extends RegistryValueType>(key: ValuedRegistryKey<V>, defaultValue?: V) : V;
|
||||
getValue<V extends RegistryValueType, DV>(key: RegistryKey<V> | ValuedRegistryKey<V>, defaultValue: DV) : V | DV {
|
||||
if(arguments.length > 1) {
|
||||
getValue<V extends RegistryValueType, DV>(key: RegistryKey<V>, defaultValue: DV): V | DV;
|
||||
getValue<V extends RegistryValueType>(key: ValuedRegistryKey<V>, defaultValue?: V): V;
|
||||
getValue<V extends RegistryValueType, DV>(key: RegistryKey<V> | ValuedRegistryKey<V>, defaultValue: DV): V | DV {
|
||||
if (arguments.length > 1) {
|
||||
return resolveSettingKey(key, key => this.settingsCache[key], defaultValue);
|
||||
} else if("defaultValue" in key) {
|
||||
} else if ("defaultValue" in key) {
|
||||
return resolveSettingKey(key, key => this.settingsCache[key], key.defaultValue);
|
||||
} else {
|
||||
debugger;
|
||||
|
@ -988,17 +988,17 @@ export class Settings {
|
|||
}
|
||||
}
|
||||
|
||||
setValue<T extends RegistryValueType>(key: RegistryKey<T>, value?: T){
|
||||
if(value === null) {
|
||||
setValue<T extends RegistryValueType>(key: RegistryKey<T>, value?: T) {
|
||||
if (value === null) {
|
||||
value = undefined;
|
||||
}
|
||||
|
||||
if(this.settingsCache[key.key] === value) {
|
||||
if (this.settingsCache[key.key] === value) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldValue = this.settingsCache[key.key];
|
||||
if(value === undefined) {
|
||||
if (value === undefined) {
|
||||
delete this.settingsCache[key.key];
|
||||
} else {
|
||||
this.settingsCache[key.key] = encodeSettingValueToString(value);
|
||||
|
@ -1014,21 +1014,21 @@ export class Settings {
|
|||
});
|
||||
logTrace(LogCategory.GENERAL, tr("Changing global setting %s to %o"), key.key, value);
|
||||
|
||||
if(UPDATE_DIRECT) {
|
||||
if (UPDATE_DIRECT) {
|
||||
this.save();
|
||||
}
|
||||
}
|
||||
|
||||
globalChangeListener<T extends RegistryValueType>(key: RegistryKey<T>, listener: (newValue: T) => void) : () => void {
|
||||
globalChangeListener<T extends RegistryValueType>(key: RegistryKey<T>, listener: (newValue: T) => void): () => void {
|
||||
return this.events.on("notify_setting_changed", event => {
|
||||
if(event.setting === key.key && event.mode === "global") {
|
||||
if (event.setting === key.key && event.mode === "global") {
|
||||
listener(event.newCastedValue);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private async doSave() {
|
||||
if(this.saveState === "none") {
|
||||
if (this.saveState === "none") {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1040,7 +1040,7 @@ export class Settings {
|
|||
} catch (error) {
|
||||
logError(LogCategory.GENERAL, tr("Failed to save global settings: %o"), error);
|
||||
}
|
||||
} while(this.saveState !== "saving");
|
||||
} while (this.saveState !== "saving");
|
||||
|
||||
this.saveState = "none";
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import {LogCategory, logError, logTrace, logWarn} from "tc-shared/log";
|
||||
import {tr} from "tc-shared/i18n/localize";
|
||||
import {default_options, DNSAddress, DNSResolveResult, ResolveOptions} from "tc-shared/dns";
|
||||
import {executeDnsRequest, RRType} from "./api";
|
||||
import { LogCategory, logError, logTrace, logWarn } from "tc-shared/log";
|
||||
import { tr } from "tc-shared/i18n/localize";
|
||||
import { default_options, DNSAddress, DNSResolveResult, ResolveOptions } from "tc-shared/dns";
|
||||
import { executeDnsRequest, RRType } from "./api";
|
||||
|
||||
interface DNSResolveMethod {
|
||||
name() : string;
|
||||
resolve(address: DNSAddress) : Promise<DNSAddress | undefined>;
|
||||
name(): string;
|
||||
resolve(address: DNSAddress): Promise<DNSAddress | undefined>;
|
||||
}
|
||||
|
||||
class LocalhostResolver implements DNSResolveMethod {
|
||||
|
@ -14,7 +14,7 @@ class LocalhostResolver implements DNSResolveMethod {
|
|||
}
|
||||
|
||||
async resolve(address: DNSAddress): Promise<DNSAddress | undefined> {
|
||||
if(address.hostname === "localhost") {
|
||||
if (address.hostname === "localhost") {
|
||||
return {
|
||||
hostname: "127.0.0.1",
|
||||
port: address.port
|
||||
|
@ -26,6 +26,20 @@ class LocalhostResolver implements DNSResolveMethod {
|
|||
|
||||
}
|
||||
|
||||
class FakeResolver implements DNSResolveMethod {
|
||||
name(): string {
|
||||
return "fake resolver";
|
||||
}
|
||||
|
||||
async resolve(address: DNSAddress): Promise<DNSAddress | undefined> {
|
||||
return {
|
||||
hostname: "tea.lp.kle.li",
|
||||
port: address.port
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class IPResolveMethod implements DNSResolveMethod {
|
||||
readonly v6: boolean;
|
||||
|
||||
|
@ -40,7 +54,7 @@ class IPResolveMethod implements DNSResolveMethod {
|
|||
|
||||
async resolve(address: DNSAddress): Promise<DNSAddress | undefined> {
|
||||
const answer = await executeDnsRequest(address.hostname, this.v6 ? RRType.AAAA : RRType.A);
|
||||
if(!answer.length) {
|
||||
if (!answer.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
@ -72,10 +86,10 @@ class SRVResolveMethod implements DNSResolveMethod {
|
|||
async resolve(address: DNSAddress): Promise<DNSAddress | undefined> {
|
||||
const answer = await executeDnsRequest((this.application ? this.application + "." : "") + address.hostname, RRType.SRV);
|
||||
|
||||
const records: {[key: number]: ParsedSVRRecord[]} = {};
|
||||
for(const record of answer) {
|
||||
const records: { [key: number]: ParsedSVRRecord[] } = {};
|
||||
for (const record of answer) {
|
||||
const parts = record.data.split(" ");
|
||||
if(parts.length !== 4) {
|
||||
if (parts.length !== 4) {
|
||||
logWarn(LogCategory.DNS, tr("Failed to parse SRV record %s. Invalid split length."), record);
|
||||
continue;
|
||||
}
|
||||
|
@ -84,7 +98,7 @@ class SRVResolveMethod implements DNSResolveMethod {
|
|||
const weight = parseInt(parts[1]);
|
||||
const port = parseInt(parts[2]);
|
||||
|
||||
if((priority < 0 || priority > 65535) || (weight < 0 || weight > 65535) || (port < 0 || port > 65535)) {
|
||||
if ((priority < 0 || priority > 65535) || (weight < 0 || weight > 65535) || (port < 0 || port > 65535)) {
|
||||
logWarn(LogCategory.DNS, tr("Failed to parse SRV record %s. Malformed data."), record);
|
||||
continue;
|
||||
}
|
||||
|
@ -99,35 +113,35 @@ class SRVResolveMethod implements DNSResolveMethod {
|
|||
|
||||
/* get the record with the highest priority */
|
||||
const priority_strings = Object.keys(records);
|
||||
if(!priority_strings.length) {
|
||||
if (!priority_strings.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let highestPriority: ParsedSVRRecord[];
|
||||
for(const priority_str of priority_strings) {
|
||||
if(!highestPriority || !highestPriority.length) {
|
||||
for (const priority_str of priority_strings) {
|
||||
if (!highestPriority || !highestPriority.length) {
|
||||
highestPriority = records[priority_str];
|
||||
}
|
||||
|
||||
if(highestPriority[0].priority < parseInt(priority_str)) {
|
||||
if (highestPriority[0].priority < parseInt(priority_str)) {
|
||||
highestPriority = records[priority_str];
|
||||
}
|
||||
}
|
||||
|
||||
if(!highestPriority.length) {
|
||||
if (!highestPriority.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/* select randomly one record */
|
||||
let record: ParsedSVRRecord;
|
||||
const max_weight = highestPriority.map(e => e.weight).reduce((a, b) => a + b, 0);
|
||||
if(max_weight == 0) {
|
||||
if (max_weight == 0) {
|
||||
record = highestPriority[Math.floor(Math.random() * highestPriority.length)];
|
||||
} else {
|
||||
let rnd = Math.random() * max_weight;
|
||||
for(let i = 0; i < highestPriority.length; i++) {
|
||||
for (let i = 0; i < highestPriority.length; i++) {
|
||||
rnd -= highestPriority[i].weight;
|
||||
if(rnd > 0) {
|
||||
if (rnd > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -136,7 +150,7 @@ class SRVResolveMethod implements DNSResolveMethod {
|
|||
}
|
||||
}
|
||||
|
||||
if(!record) {
|
||||
if (!record) {
|
||||
/* shall never happen */
|
||||
record = highestPriority[0];
|
||||
}
|
||||
|
@ -165,7 +179,7 @@ class SRV_IPResolveMethod implements DNSResolveMethod {
|
|||
|
||||
async resolve(address: DNSAddress): Promise<DNSAddress | undefined> {
|
||||
const srvAddress = await this.srvResolver.resolve(address);
|
||||
if(!srvAddress) {
|
||||
if (!srvAddress) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
@ -190,7 +204,7 @@ class DomainRootResolveMethod implements DNSResolveMethod {
|
|||
|
||||
async resolve(address: DNSAddress): Promise<DNSAddress | undefined> {
|
||||
const parts = address.hostname.split(".");
|
||||
if(parts.length < 3) {
|
||||
if (parts.length < 3) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
@ -203,7 +217,7 @@ class DomainRootResolveMethod implements DNSResolveMethod {
|
|||
|
||||
class TeaSpeakDNSResolve {
|
||||
readonly address: DNSAddress;
|
||||
private resolvers: {[key: string]:{ resolver: DNSResolveMethod, after: string[] }} = {};
|
||||
private resolvers: { [key: string]: { resolver: DNSResolveMethod, after: string[] } } = {};
|
||||
private resolving = false;
|
||||
private timeout;
|
||||
|
||||
|
@ -218,15 +232,15 @@ class TeaSpeakDNSResolve {
|
|||
}
|
||||
|
||||
registerResolver(resolver: DNSResolveMethod, ...after: (string | DNSResolveMethod)[]) {
|
||||
if(this.resolving) {
|
||||
if (this.resolving) {
|
||||
throw tr("resolver is already resolving");
|
||||
}
|
||||
|
||||
this.resolvers[resolver.name()] = { resolver: resolver, after: after.map(e => typeof e === "string" ? e : e.name()) };
|
||||
}
|
||||
|
||||
resolve(timeout: number) : Promise<DNSAddress> {
|
||||
if(this.resolving) {
|
||||
resolve(timeout: number): Promise<DNSAddress> {
|
||||
if (this.resolving) {
|
||||
throw tr("already resolving");
|
||||
}
|
||||
this.resolving = true;
|
||||
|
@ -263,52 +277,53 @@ class TeaSpeakDNSResolve {
|
|||
let invoke_count = 0;
|
||||
|
||||
_main_loop:
|
||||
for(const resolver_name of Object.keys(this.resolvers)) {
|
||||
if(this.resolving_resolvers.findIndex(e => e === resolver_name) !== -1) continue;
|
||||
if(this.finished_resolvers.findIndex(e => e === resolver_name) !== -1) continue;
|
||||
for (const resolver_name of Object.keys(this.resolvers)) {
|
||||
if (this.resolving_resolvers.findIndex(e => e === resolver_name) !== -1) continue;
|
||||
if (this.finished_resolvers.findIndex(e => e === resolver_name) !== -1) continue;
|
||||
|
||||
const resolver = this.resolvers[resolver_name];
|
||||
for(const after of resolver.after)
|
||||
if(this.finished_resolvers.findIndex(e => e === after) === -1) continue _main_loop;
|
||||
const resolver = this.resolvers[resolver_name];
|
||||
for (const after of resolver.after)
|
||||
if (this.finished_resolvers.findIndex(e => e === after) === -1) continue _main_loop;
|
||||
|
||||
invoke_count++;
|
||||
logTrace(LogCategory.DNS, tr(" Executing resolver %s"), resolver_name);
|
||||
invoke_count++;
|
||||
logTrace(LogCategory.DNS, tr(" Executing resolver %s"), resolver_name);
|
||||
|
||||
this.resolving_resolvers.push(resolver_name);
|
||||
resolver.resolver.resolve(this.address).then(result => {
|
||||
if(!this.resolving || !this.callback_success) return; /* resolve has been finished already */
|
||||
this.finished_resolvers.push(resolver_name);
|
||||
this.resolving_resolvers.push(resolver_name);
|
||||
resolver.resolver.resolve(this.address).then(result => {
|
||||
if (!this.resolving || !this.callback_success) return; /* resolve has been finished already */
|
||||
this.finished_resolvers.push(resolver_name);
|
||||
|
||||
if(!result) {
|
||||
logTrace(LogCategory.DNS, tr(" Resolver %s returned an empty response."), resolver_name);
|
||||
this.invoke_resolvers();
|
||||
return;
|
||||
}
|
||||
|
||||
logTrace(LogCategory.DNS, tr(" Successfully resolved address %s:%d to %s:%d via resolver %s"),
|
||||
this.address.hostname, this.address.port,
|
||||
result.hostname, result.port,
|
||||
resolver_name);
|
||||
this.callback_success(result);
|
||||
}).catch(error => {
|
||||
if(!this.resolving || !this.callback_success) return; /* resolve has been finished already */
|
||||
this.finished_resolvers.push(resolver_name);
|
||||
|
||||
logTrace(LogCategory.DNS, tr(" Resolver %s ran into an error: %o"), resolver_name, error);
|
||||
if (!result) {
|
||||
logTrace(LogCategory.DNS, tr(" Resolver %s returned an empty response."), resolver_name);
|
||||
this.invoke_resolvers();
|
||||
}).then(() => {
|
||||
this.resolving_resolvers.remove(resolver_name);
|
||||
if(!this.resolving_resolvers.length && this.resolving)
|
||||
this.invoke_resolvers();
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(invoke_count === 0 && !this.resolving_resolvers.length && this.resolving) {
|
||||
logTrace(LogCategory.DNS, tr(" Successfully resolved address %s:%d to %s:%d via resolver %s"),
|
||||
this.address.hostname, this.address.port,
|
||||
result.hostname, result.port,
|
||||
resolver_name);
|
||||
this.callback_success(result);
|
||||
}).catch(error => {
|
||||
if (!this.resolving || !this.callback_success) return; /* resolve has been finished already */
|
||||
this.finished_resolvers.push(resolver_name);
|
||||
|
||||
logTrace(LogCategory.DNS, tr(" Resolver %s ran into an error: %o"), resolver_name, error);
|
||||
this.invoke_resolvers();
|
||||
}).then(() => {
|
||||
this.resolving_resolvers.remove(resolver_name);
|
||||
if (!this.resolving_resolvers.length && this.resolving)
|
||||
this.invoke_resolvers();
|
||||
});
|
||||
}
|
||||
|
||||
if (invoke_count === 0 && !this.resolving_resolvers.length && this.resolving) {
|
||||
this.callback_fail("no response");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const kResolverFake = new FakeResolver();
|
||||
const kResolverLocalhost = new LocalhostResolver();
|
||||
|
||||
const kResolverIpV4 = new IPResolveMethod(false);
|
||||
|
@ -320,14 +335,16 @@ const resolverSrvTS3 = new SRV_IPResolveMethod(new SRVResolveMethod("_ts3._udp")
|
|||
const resolverDrSrvTS = new DomainRootResolveMethod(resolverSrvTS);
|
||||
const resolverDrSrvTS3 = new DomainRootResolveMethod(resolverSrvTS3);
|
||||
|
||||
export async function resolveTeaSpeakServerAddress(address: DNSAddress, _options?: ResolveOptions) : Promise<DNSResolveResult> {
|
||||
export async function resolveTeaSpeakServerAddress(address: DNSAddress, _options?: ResolveOptions): Promise<DNSResolveResult> {
|
||||
try {
|
||||
const options = Object.assign({}, default_options);
|
||||
Object.assign(options, _options);
|
||||
|
||||
const resolver = new TeaSpeakDNSResolve(address);
|
||||
|
||||
resolver.registerResolver(kResolverLocalhost);
|
||||
resolver.registerResolver(kResolverFake);
|
||||
|
||||
resolver.registerResolver(kResolverLocalhost, kResolverFake);
|
||||
|
||||
resolver.registerResolver(resolverSrvTS, kResolverLocalhost);
|
||||
resolver.registerResolver(resolverSrvTS3, kResolverLocalhost);
|
||||
|
@ -340,7 +357,7 @@ export async function resolveTeaSpeakServerAddress(address: DNSAddress, _options
|
|||
resolver.registerResolver(kResolverIpV6, kResolverIpV4);
|
||||
|
||||
const response = await resolver.resolve(options.timeout || 5000);
|
||||
if(!response) {
|
||||
if (!response) {
|
||||
return {
|
||||
status: "empty-result"
|
||||
};
|
||||
|
@ -352,7 +369,7 @@ export async function resolveTeaSpeakServerAddress(address: DNSAddress, _options
|
|||
resolvedAddress: response
|
||||
};
|
||||
} catch (error) {
|
||||
if(typeof error !== "string") {
|
||||
if (typeof error !== "string") {
|
||||
logError(LogCategory.DNS, tr("Failed to resolve %o: %o"), address, error);
|
||||
error = tr("lookup the console");
|
||||
}
|
||||
|
@ -364,9 +381,9 @@ export async function resolveTeaSpeakServerAddress(address: DNSAddress, _options
|
|||
}
|
||||
}
|
||||
|
||||
export async function resolveAddressIpV4(address: string) : Promise<string> {
|
||||
export async function resolveAddressIpV4(address: string): Promise<string> {
|
||||
const result = await executeDnsRequest(address, RRType.A);
|
||||
if(!result.length) return undefined;
|
||||
if (!result.length) return undefined;
|
||||
|
||||
return result[0].data;
|
||||
}
|
Loading…
Reference in New Issue