264 lines
11 KiB
JavaScript
264 lines
11 KiB
JavaScript
const { Worker } = require('worker_threads')
|
|
module.exports = (s,config,lang) => {
|
|
const { getConnectionDetails } = require('./libs/connectDetails.js')(s,config,lang)
|
|
const { modifyConfiguration, getConfiguration } = require('../system/utils.js')(config)
|
|
const sshDisabled = config.noCentralSsh === true;
|
|
const queuedSshRestart = {}
|
|
if(!s.connectedMgmtServers)s.connectedMgmtServers = {}
|
|
function parseNewConnectionAddress(serverIp){
|
|
let parsedIp = `${serverIp}`
|
|
if(parsedIp.indexOf('://') === -1)parsedIp = `ws://${parsedIp}`
|
|
if(parsedIp.split(':').length === 2)parsedIp = `ws://${parsedIp}:8663`
|
|
return parsedIp;
|
|
}
|
|
function getManagementServers(){
|
|
const response = { ok: true }
|
|
response.mgmtServers = config.mgmtServers || {};
|
|
return response
|
|
}
|
|
async function setManagementServers(mgmtServers){
|
|
const response = { ok: true }
|
|
config = Object.assign(config,{ mgmtServers })
|
|
const currentConfig = await getConfiguration()
|
|
currentConfig.mgmtServer = mgmtServers;
|
|
const configError = await modifyConfiguration(currentConfig)
|
|
if(configError){
|
|
response.ok = false;
|
|
response.err = configError
|
|
s.systemLog(configError)
|
|
}
|
|
return response
|
|
}
|
|
async function addManagementServer(serverIp, p2pKey){
|
|
const response = { ok: true }
|
|
const parsedIp = parseNewConnectionAddress(serverIp)
|
|
const currentConfig = await getConfiguration();
|
|
if(!currentConfig.mgmtServers)currentConfig.mgmtServers = {};
|
|
currentConfig.mgmtServers[serverIp] = p2pKey;
|
|
config = Object.assign(config, { mgmtServers: currentConfig.mgmtServers })
|
|
const configError = await modifyConfiguration(currentConfig)
|
|
if(configError){
|
|
response.ok = false;
|
|
response.err = configError
|
|
s.systemLog(configError)
|
|
}
|
|
return response
|
|
}
|
|
async function removeManagementServer(serverIp, p2pKey){
|
|
const response = { ok: true }
|
|
let foundMatching = false;
|
|
const currentConfig = await getConfiguration();
|
|
if(!currentConfig.mgmtServers)currentConfig.mgmtServers = {};
|
|
const currentPeerConnectKey = currentConfig.mgmtServers[serverIp];
|
|
if(currentPeerConnectKey === p2pKey){
|
|
foundMatching = true
|
|
delete(currentConfig.mgmtServers[serverIp])
|
|
config = Object.assign(config, { mgmtServers: currentConfig.mgmtServers })
|
|
const configError = await modifyConfiguration(currentConfig)
|
|
if(configError){
|
|
response.ok = false;
|
|
response.err = configError
|
|
s.systemLog(configError)
|
|
}
|
|
}else{
|
|
response.ok = false;
|
|
response.msg = 'Peer Connect Key not matching! Cannot disconnect.';
|
|
}
|
|
return response
|
|
}
|
|
function terminateSshToManagement(serverIp){
|
|
if(s.connectedMgmtServers[serverIp]){
|
|
s.connectedMgmtServers[serverIp].sshWorker.terminate()
|
|
delete(s.connectedMgmtServers[serverIp].sshWorker)
|
|
}
|
|
}
|
|
async function queueToggleSshToManagement(serverIp, p2pKey, onlyClose){
|
|
if(sshDisabled)return;
|
|
clearTimeout(queuedSshRestart[serverIp])
|
|
queuedSshRestart[serverIp] = setTimeout(() => {
|
|
delete(queuedSshRestart[serverIp])
|
|
if(onlyClose){
|
|
terminateSshToManagement(serverIp)
|
|
}else{
|
|
provideSshToManagement(serverIp, p2pKey)
|
|
}
|
|
},1000 * 60)
|
|
}
|
|
async function provideSshToManagement(serverIp, p2pKey){
|
|
if(sshDisabled)return;
|
|
if(queuedSshRestart[serverIp]){
|
|
clearTimeout(queuedSshRestart[serverIp]);
|
|
return s.connectedMgmtServers[serverIp].sshWorker
|
|
}
|
|
const configFromFile = await getConfiguration()
|
|
const wsServerParts = serverIp.split(':')
|
|
wsServerParts[serverIp.includes('://') ? 2 : 1] = configFromFile.sshSocketPort || 9021
|
|
const wsServer = wsServerParts.join(':')
|
|
console.log('Central SSH Connector Starting...', wsServer)
|
|
const worker = new Worker(`${__dirname}/libs/centralConnect/ssh.js`, {
|
|
workerData: {
|
|
config: configFromFile,
|
|
wsServer: wsServer,
|
|
peerConnectKey: p2pKey,
|
|
}
|
|
});
|
|
worker.on('message', async (data) => {
|
|
switch(data.f){
|
|
case'restart':
|
|
s.systemLog('Restarting SSH Connection...', serverIp)
|
|
worker.terminate()
|
|
break;
|
|
}
|
|
});
|
|
worker.on('error', (err) => {
|
|
console.error('cameraPeer SSH Error', serverIp, err)
|
|
});
|
|
worker.on('exit', (code) => {
|
|
if(!s.connectedMgmtServers[serverIp].wantTerminate){
|
|
console.log('cameraPeer SSH Exited, Restarting...', serverIp, code)
|
|
s.connectedMgmtServers[serverIp].sshWorker = provideSshToManagement(serverIp, p2pKey)
|
|
}else{
|
|
console.log('cameraPeer SSH Exited, NOT Restarting...', serverIp, code)
|
|
}
|
|
});
|
|
return worker
|
|
}
|
|
async function connectToManagementServer(serverIp, p2pKey){
|
|
if(!config.userHasSubscribed){
|
|
return console.log(lang.centralManagementNotEnabled)
|
|
}
|
|
if(s.connectedMgmtServers[serverIp]){
|
|
disconnectFromManagmentServer(serverIp)
|
|
}
|
|
s.connectedMgmtServers[serverIp] = {}
|
|
const configFromFile = await getConfiguration()
|
|
configFromFile.timezone = config.timezone;
|
|
console.log('Central Worker Starting...', serverIp)
|
|
const worker = new Worker(`${__dirname}/libs/centralConnect/index.js`, {
|
|
workerData: {
|
|
config: configFromFile,
|
|
serverIp,
|
|
p2pKey,
|
|
}
|
|
});
|
|
worker.on('message', async (data) => {
|
|
switch(data.f){
|
|
case'authenticated':
|
|
const sshWorker = await provideSshToManagement(serverIp, p2pKey)
|
|
s.connectedMgmtServers[serverIp].sshWorker = sshWorker;
|
|
break;
|
|
case'connectDetailsRequest':
|
|
getConnectionDetails().then((connectDetails) => {
|
|
worker.postMessage({ f: 'connectDetails', connectDetails })
|
|
}).catch((error) => {
|
|
console.error('FAILED TO GET connectDetails', serverIp, error)
|
|
worker.postMessage({ f: 'connectDetails', connectDetails: {} })
|
|
})
|
|
break;
|
|
case'modifyConfiguration':
|
|
console.log('Editing Configuration...', serverIp, data.data.form)
|
|
const configFromFile = await getConfiguration()
|
|
const mgmtServers = JSON.stringify(configFromFile.mgmtServers)
|
|
const newConfig = data.data.form;
|
|
const mgmtServersFromNewConfig = JSON.stringify(configFromFile.mgmtServers)
|
|
if(mgmtServers !== mgmtServersFromNewConfig){
|
|
resetAllManagementServers()
|
|
}
|
|
modifyConfiguration(newConfig)
|
|
break;
|
|
case'restart':
|
|
s.systemLog('Restarting Central Connection...', serverIp)
|
|
worker.terminate()
|
|
break;
|
|
}
|
|
});
|
|
worker.on('error', (err) => {
|
|
console.error('cameraPeer Error', serverIp, err)
|
|
});
|
|
worker.on('exit', (code) => {
|
|
console.log('cameraPeer Exited, Restarting...', serverIp, code)
|
|
if(!s.connectedMgmtServers[serverIp].wantTerminate)connectToManagementServer(serverIp, p2pKey)
|
|
});
|
|
s.connectedMgmtServers[serverIp].worker = worker;
|
|
s.connectedMgmtServers[serverIp].wantTerminate = false;
|
|
}
|
|
function disconnectFromManagmentServer(serverIp){
|
|
const mgmtConnection = s.connectedMgmtServers[serverIp];
|
|
try{
|
|
if(!mgmtConnection)return;
|
|
mgmtConnection.wantTerminate = true;
|
|
mgmtConnection.worker.terminate();
|
|
}catch(err){
|
|
s.debugLog('disconnectFromManagmentServer ERR',err)
|
|
}
|
|
try{
|
|
terminateSshToManagement(serverIp);
|
|
}catch(err){
|
|
s.debugLog('disconnectFromManagmentSshServer ERR',err)
|
|
}
|
|
}
|
|
function resetConnectionToManagementServer(serverIp){
|
|
const mgmtConnection = s.connectedMgmtServers[serverIp];
|
|
if(!mgmtConnection)return;
|
|
mgmtConnection.wantTerminate = false;
|
|
mgmtConnection.worker.terminate();
|
|
try{
|
|
terminateSshToManagement(serverIp);
|
|
}catch(err){
|
|
s.debugLog('resetConnectionToManagementSshServer ERR',err)
|
|
}
|
|
}
|
|
function resetAllManagementServers(){
|
|
for(serverIp in s.connectedMgmtServers){
|
|
disconnectFromManagmentServer(serverIp)
|
|
}
|
|
connectAllManagementServers()
|
|
}
|
|
async function connectAllManagementServers(){
|
|
const configFromFile = await getConfiguration()
|
|
const mgmtServers = configFromFile.mgmtServers
|
|
if(mgmtServers){
|
|
for(serverIp in mgmtServers){
|
|
var p2pKey = mgmtServers[serverIp]
|
|
await connectToManagementServer(serverIp, p2pKey)
|
|
}
|
|
}else{
|
|
console.log(`Management Server Connection Not Configured!`)
|
|
}
|
|
}
|
|
async function migrateOldConfiguration(){
|
|
await addManagementServer(config.managementServer, config.peerConnectKey)
|
|
await connectToManagementServer(config.managementServer, config.peerConnectKey)
|
|
const configFromFile = await getConfiguration()
|
|
delete(configFromFile.managementServer)
|
|
delete(configFromFile.peerConnectKey)
|
|
modifyConfiguration(configFromFile)
|
|
}
|
|
async function sendMessageToAllConnectedServers(data){
|
|
for(let serverIp in s.connectedMgmtServers){
|
|
try{
|
|
s.connectedMgmtServers[serverIp].worker.postMessage(data)
|
|
}catch(err){
|
|
s.debugLog(err.toString())
|
|
}
|
|
}
|
|
}
|
|
if(config.autoRestartManagementConnectionInterval){
|
|
setInterval(() => {
|
|
resetAllManagementServers()
|
|
}, 1000 * 60 * 15)
|
|
}
|
|
return {
|
|
getManagementServers,
|
|
addManagementServer,
|
|
removeManagementServer,
|
|
connectToManagementServer,
|
|
disconnectFromManagmentServer,
|
|
resetConnectionToManagementServer,
|
|
resetAllManagementServers,
|
|
connectAllManagementServers,
|
|
migrateOldConfiguration,
|
|
sendMessageToAllConnectedServers,
|
|
}
|
|
}
|