diff --git a/index.js b/index.js index fb8a8756dc08cf4ea33939e6fb0fd5765606ec46..bf3ff2755899b622059a738dd36aeba45283ccf4 100644 --- a/index.js +++ b/index.js @@ -1,85 +1,127 @@ const https = require('https'); const express = require('express'); - -// Initialize -// -------------------------------------------------------- - -const app = express(); +const { error } = require('console'); const config = require('./config'); -config.init(); - const db = require('./database'); -db.init(); - -// Sync records from master -// -------------------------------------------------------- +const knotdns = require('./knotdns'); -console.log("Syncing records from " + config.config().master.address + "/ ..."); - -https.get(config.config().master.address + '/dyndns-list?id=' + config.config().master.myId + '&key=' + config.config().master.key, (res) => { - if (res.statusCode > 299) { - process.exit(2); - return; - } - - let response = ''; - - res.on('data', (chunk) => response += chunk); - - res.on('end', () => { - db.clearDomains().then(() => { - knotdns.clearZone().then(() => { - console.log("Purged existing domains"); - try { - records = JSON.parse(response); - - async function loadRecords(records) { - for (const r of records) { - const domain = r.domain.split(".")[0]; - const token = r.token; - const ip = r.ip; - - if (ip == "null") { - await db.registerDomain(domain, token); - console.log("Registering record without IP: " + domain); - } else { - await db.insertDomain(domain, token, ip); - await knotdns.updateRecord(domain, ip); - console.log("Registering domain " + domain + " to " + ip); +// number of times to try syncing DNS records from master before giving up +const retryMax = 5; + + +// Synchronizes current DNS records from master +function syncRecords() { + return new Promise((resolve, reject) => { + https.get(config.config().master.address + '/dyndns-list?id=' + config.config().master.myId + '&key=' + config.config().master.key, (res) => { + if (res.statusCode > 299) { + const errormsg = 'Bad HTTP status code from ' + config.config().master.address + ' : ' + res.statusCode; + reject(errormsg); + return; + } + + let response = ''; + + res.on('data', (chunk) => response += chunk); + + res.on('end', () => { + db.clearDomains().then(() => { + knotdns.clearZone().then(() => { + console.log("Purged existing domains"); + try { + records = JSON.parse(response); + + async function loadRecords(records) { + for (const r of records) { + const domain = r.domain.split(".")[0]; + const token = r.token; + const ip = r.ip; + + if (ip == "null") { + await db.registerDomain(domain, token); + console.log("Registering record without IP: " + domain); + } else { + await db.insertDomain(domain, token, ip); + await knotdns.updateRecord(domain, ip); + console.log("Registering domain " + domain + " to " + ip); + } + } + resolve(); + return; } - }; - } - loadRecords(records); - } catch (error) { - console.error("Error parsing records from master: ", error); - process.exit(1); - } - }) + loadRecords(records); + } catch (error) { + const errormsg = "Error parsing records from master: " + error; + reject(errormsg); + return; + } + }) + }) + }); + }).on('error', (error) => { + const errormsg = "Could not sync records from master: " + error; + reject(errormsg); + return; + }); + }) +} + + +// Start HTTP server and process record updates +function handleUpdates() { + return new Promise((resolve, reject) => { + const registerMW = require('./middleware/registerMW'); + const replyMW = require('./middleware/replyMW'); + const updateMW = require('./middleware/updateMW'); + + // register a new dyndns record + app.get('/register', registerMW(), replyMW()); + + // update an existing dyndns record + app.get('/update', updateMW(), replyMW()); + + const server_port = config.config().listenPort; + const server_domain = config.config().listenAddress; + app.listen(server_port, server_domain, function () { + console.log(`This server is listening on http://${server_domain}:${server_port}`); + resolve(); + }); + }) +} + + +// Try syncing from master a few times and then serve DNS update requests +function syncAndRun(retries) { + console.log("Syncing records from " + config.config().master.address + "/ ..."); + + syncRecords().then(() => { + handleUpdates(); + }) + .catch((errormsg) => { + console.error(errormsg); + if (retries < retryMax) { + console.error("Retrying in 1 min."); + setTimeout(() => { + syncAndRun(retries + 1); + }, 60000); + } else { + console.error("Giving up."); + process.exit(1); + } }) - }); -}).on('error', (error) => { - console.error("Could not sync records from master: ", error); - process.exit(1); -}); -// Register and serve endpoints +} + +// Initialize // -------------------------------------------------------- -const registerMW = require('./middleware/registerMW'); -const replyMW = require('./middleware/replyMW'); -const updateMW = require('./middleware/updateMW'); -const { error } = require('console'); -const knotdns = require('./knotdns'); +const app = express(); -// register a new dyndns record -app.get('/register', registerMW(), replyMW()); +config.init(); +db.init(); -// update an existing dyndns record -app.get('/update', updateMW(), replyMW()); +// Sync records from master then serve requests +// -------------------------------------------------------- -const server_port = config.config().listenPort; -const server_domain = config.config().listenAddress; -app.listen(server_port, server_domain, function () { - console.log(`This server is listening on http://${server_domain}:${server_port}`); -}); \ No newline at end of file +var retries = 0; +syncAndRun(retries);