Skip to content

Commit

Permalink
fix(ntpClient): Intercept dns lookup calls for our ntp server as well
Browse files Browse the repository at this point in the history
  • Loading branch information
Hypfer committed Feb 9, 2021
1 parent 54ca606 commit c7095a7
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 36 deletions.
117 changes: 81 additions & 36 deletions lib/DnsHack.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,51 +16,96 @@ const Logger = require("./Logger");
I'm sorry.
*/
class DnsHack {
/**
*
* @param {object} options
* @param {import("./Configuration")} options.config
*/
constructor(options) {
const self = this;

const realLookup = dns.lookup;
this.config = options.config;
this.hosts = {
mqtt: undefined,
ntp: undefined
}

dns.lookup = function lookupResolveHack(hostname, options, callback) {
if (typeof options === "function") {
callback = options;
return realLookup(hostname, options, callback);
}

if (
Object.getOwnPropertyNames(options).length === 2 &&
options.family === undefined
) {
//This sorta looks like something that might be a request from the MQTT client
//Time to take a look at the stacktrace to make sure
//Doing this after checking the previous condition saves us from creating a stacktrace
//on each udp send which would be horrible for the performance
const stack = new Error().stack;

if (stack.includes("lookupAndConnect")) { //nodejs internal function
Logger.trace("Intercepting dns.lookup call for", hostname);

dns.resolve4(hostname, (err, addresses) => {
if (err && err.code === "ENOTFOUND") {
dns.resolve6(hostname, (err, addresses) => {
if (err) {
if(dns.lookup.name === "lookupResolveHack") {
throw new Error("Tried to Monkey-patch dns.lookup multiple times. Aborting");
}

this.config.onUpdate(async (key) => {
if (key === "mqtt" || key === "ntpClient") {
this.updateHosts();
}
});
this.updateHosts();


const realLookup = dns.lookup;

dns.lookup = function lookupResolveHack(hostname, options, callback) {
if (typeof options === "function") {
callback = options;
return realLookup(hostname, options, callback);
}

if (
(
Object.getOwnPropertyNames(options).length === 2 &&
options.family === undefined
) || hostname === self.hosts.mqtt || hostname === self.hosts.ntp
) {
//This sorta looks like something that might be a request from the MQTT client
//Time to take a look at the stacktrace to make sure
//Doing this after checking the previous condition saves us from creating a stacktrace
//on each udp send which would be horrible for the performance
const stack = new Error().stack;

if (
stack.includes("lookupAndConnect") || //nodejs internal function
hostname === self.hosts.mqtt || hostname === self.hosts.ntp
) {
Logger.trace("Intercepting dns.lookup call for", hostname);

dns.resolve4(hostname, (err, addresses) => {
if (err && err.code === "ENOTFOUND") {
dns.resolve6(hostname, (err, addresses) => {
if (err) {
callback(err);
} else {
callback(null, addresses[0], 6);
}
});
} else if (err) {
callback(err);
} else {
callback(null, addresses[0], 6);
callback(null, addresses[0], 4);
}
});
} else if (err) {
callback(err);
} else {
callback(null, addresses[0], 4);
return realLookup(hostname, options, callback);
}
});
} else {
return realLookup(hostname, options, callback);
}
} else {
return realLookup(hostname, options, callback);
} else {
return realLookup(hostname, options, callback);
}
};

dns.lookup.__promisify__ = realLookup.__promisify__;
}
};

dns.lookup.__promisify__ = realLookup.__promisify__;
/**
* @private
*/
updateHosts() {
const mqttConfig = this.config.get("mqtt");
const ntpConfig = this.config.get("ntpClient");

this.hosts.mqtt = mqttConfig.server;
this.hosts.ntp = ntpConfig.server;
}
}

module.exports = null;
module.exports = DnsHack;
3 changes: 3 additions & 0 deletions lib/Valetudo.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const NTPClient = require("./NTPClient");
const Webserver = require("./webserver/WebServer");
const MqttClient = require("./mqtt/MqttClient");
const Configuration = require("./Configuration");
const DnsHack = require("./DnsHack");
const Logger = require("./Logger");
const Tools = require("./Tools");

Expand All @@ -18,6 +19,8 @@ class Valetudo {
Logger.error("Initialising Logger: " + e);
}

this.dnsHack = new DnsHack({config: this.config});

try {
const robotImplementation = ValetudoRobotFactory.getRobotImplementation(this.config);

Expand Down

0 comments on commit c7095a7

Please sign in to comment.