parent
66236e58a9
commit
8ae2dc83c9
9 changed files with 1312 additions and 0 deletions
@ -0,0 +1,13 @@ |
|||||||
|
{ |
||||||
|
"name": "wiot-director", |
||||||
|
"version": "0.0.1", |
||||||
|
"description": "Director for wIoT systems.", |
||||||
|
"main": "index.js", |
||||||
|
"repository": "https://wiot.js.org", |
||||||
|
"author": "iotcat", |
||||||
|
"license": "MIT", |
||||||
|
"dependencies": { |
||||||
|
"express": "^4.17.1", |
||||||
|
"log4js": "^6.3.0" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
data/ |
@ -0,0 +1,59 @@ |
|||||||
|
const logger = require(__dirname + '/modules/log.js')(); |
||||||
|
const nodetable = require(__dirname + '/modules/nodetable.js')(logger); |
||||||
|
const node = require(__dirname + '/modules/node.js')(logger, nodetable); |
||||||
|
const ns = require(__dirname + '/modules/ns.js')(logger, node); |
||||||
|
const api = require(__dirname + '/modules/api.js')(logger, node, ns); |
||||||
|
|
||||||
|
|
||||||
|
let OnlineBoard = []; |
||||||
|
|
||||||
|
setInterval(async ()=>{ |
||||||
|
//console.log(await node.good.restart());
|
||||||
|
//console.log('ddd')
|
||||||
|
//console.log(await node.good.refresh());
|
||||||
|
//console.log(await node.good.setNS('ccc', '192.168.3.253', 6789));
|
||||||
|
//console.log(await node.good.checkNS('ccc', '111.111.11.11', 6789));
|
||||||
|
//console.log(await node.good.setFunc('333Func', 'tmr.create():alarm(3000, tmr.ALARM_AUTO, function() print("hello") end)'));
|
||||||
|
|
||||||
|
/*l = await ns.get(['good', 'good3'], { |
||||||
|
'good': { |
||||||
|
'good3': { |
||||||
|
port: 22, |
||||||
|
ip: '111.222.333.44' |
||||||
|
} |
||||||
|
} |
||||||
|
})*/ |
||||||
|
|
||||||
|
let online = []; |
||||||
|
|
||||||
|
Object.keys(node).forEach(nid => { |
||||||
|
if(node[nid].status){ |
||||||
|
online.push(nid); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
if(online.some(nid => OnlineBoard.indexOf(nid) == -1)){ |
||||||
|
OnlineBoard = online; |
||||||
|
await ns.set(await ns.get(online/*, { |
||||||
|
'good': { |
||||||
|
'good3': { |
||||||
|
port: 22, |
||||||
|
ip: '111.222.333.44' |
||||||
|
} |
||||||
|
}, |
||||||
|
'good3': { |
||||||
|
'good': { |
||||||
|
port: 22, |
||||||
|
ip: '111.222.333.44' |
||||||
|
} |
||||||
|
}, |
||||||
|
}*/)) |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
},15000) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,140 @@ |
|||||||
|
module.exports = (logger, node, ns) => { |
||||||
|
|
||||||
|
|
||||||
|
const log = logger.getLogger('weblog'); |
||||||
|
const express = require('express'); |
||||||
|
const app = express() |
||||||
|
const port = 3001; |
||||||
|
|
||||||
|
app.get('/', (req, res) => { |
||||||
|
res.send('Hello World!') |
||||||
|
}) |
||||||
|
|
||||||
|
app.listen(port, () => { |
||||||
|
log.info('API web server begin at ', port); |
||||||
|
}) |
||||||
|
|
||||||
|
function isJson(str) { |
||||||
|
try { |
||||||
|
if (typeof JSON.parse(str) == "object") { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} catch(e) { |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
app.get('/status', (req, res) => { |
||||||
|
if(!req.query.hasOwnProperty('query')){ |
||||||
|
res.status(500).send(); |
||||||
|
return; |
||||||
|
} |
||||||
|
if(!isJson(req.query.query)){ |
||||||
|
res.status(500).send(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
let query = JSON.parse(req.query.query); |
||||||
|
|
||||||
|
let resData = {}; |
||||||
|
query.forEach(nid => { |
||||||
|
if(node.hasOwnProperty(nid)){ |
||||||
|
resData[nid] = {}; |
||||||
|
resData[nid].status = node[nid].status; |
||||||
|
resData[nid].funcID = node[nid].info.funcID; |
||||||
|
resData[nid].port = node[nid].info.localport; |
||||||
|
resData[nid].ip = node[nid].info.localip; |
||||||
|
resData[nid].ns = node[nid].ns; |
||||||
|
resData[nid].heap = node[nid].info.heap; |
||||||
|
resData[nid].spiff = node[nid].info.spiff; |
||||||
|
resData[nid].HeartbeatInterval = node[nid].info.HeartbeatInterval; |
||||||
|
resData[nid].LastUpTime = node[nid].info.LastUpTime; |
||||||
|
resData[nid].LastActiveTime = node[nid].info.LastActiveTime; |
||||||
|
resData[nid].LastRefreshTime = node[nid].LastRefreshTime; |
||||||
|
resData[nid].LastRestartTime = node[nid].LastRestartTime; |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
res.send(resData); |
||||||
|
log.info('[status]', JSON.stringify(req.query.query)); |
||||||
|
}) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
app.get('/setFunc', async (req, res) => { |
||||||
|
if(!req.query.hasOwnProperty('nid') || !req.query.hasOwnProperty('funcID') || !req.query.hasOwnProperty('func')){ |
||||||
|
res.status(500).send(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
let nid = req.query.nid, |
||||||
|
funcID = req.query.funcID, |
||||||
|
func = new Buffer(req.query.func, 'base64').toString() |
||||||
|
|
||||||
|
if(!node.hasOwnProperty(nid)){ |
||||||
|
res.status(404).send(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
if(!node[nid].status){ |
||||||
|
res.status(503).send(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
let status = await node[nid].setFunc(funcID, func); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
res.send({status: status}); |
||||||
|
log.info('[setFunc]', '<'+nid+'>', funcID, status); |
||||||
|
}) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
app.get('/restart', async (req, res) => { |
||||||
|
if(!req.query.hasOwnProperty('nid')){ |
||||||
|
res.status(500).send(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
let nid = req.query.nid; |
||||||
|
|
||||||
|
if(!node.hasOwnProperty(nid)){ |
||||||
|
res.status(404).send(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
if(!node[nid].status){ |
||||||
|
res.status(503).send(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
let status = await node[nid].restart(); |
||||||
|
res.send({status: status}); |
||||||
|
log.info('[restart]', '<'+nid+'>', status); |
||||||
|
}) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
app.get('/log', (req, res) => { |
||||||
|
if(!req.query.hasOwnProperty('type') || !req.query.hasOwnProperty('start')){ |
||||||
|
res.status(500).send(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
res.send(); |
||||||
|
log.info('[log]', req.query.type); |
||||||
|
}) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return null; |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
module.exports = (node, nodetable) => { |
||||||
|
|
||||||
|
const LOG_PATH = __dirname + '/../data/log/'; |
||||||
|
|
||||||
|
|
||||||
|
const log4js = require('log4js'); |
||||||
|
|
||||||
|
|
||||||
|
log4js.configure({ |
||||||
|
appenders: { |
||||||
|
flow: {type: 'file', filename: LOG_PATH + 'flow.log'}, |
||||||
|
access: {type: 'file', filename: LOG_PATH + 'access.log'}, |
||||||
|
event: {type: 'file', filename: LOG_PATH + 'event.log'}, |
||||||
|
nslog: {type: 'file', filename: LOG_PATH + 'ns.log'}, |
||||||
|
weblog: {type: 'file', filename: LOG_PATH + 'web.log'}, |
||||||
|
console: { type: 'console' } |
||||||
|
}, |
||||||
|
categories: { |
||||||
|
flow: {appenders: [/*'flow',*/ 'console'], level: 'info' }, |
||||||
|
//access: { appenders: ['access'], level: 'info' },
|
||||||
|
event: {appenders: [/*'event', */'console'], level: 'info' }, |
||||||
|
nslog: {appenders: [/*'nslog',*/ 'console'], level: 'info' }, |
||||||
|
weblog: {appenders: [/*'weblog',*/ 'console'], level: 'info' }, |
||||||
|
default: { appenders: ['console'], level: 'info' } |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
return log4js; |
||||||
|
} |
@ -0,0 +1,281 @@ |
|||||||
|
module.exports = (logger, nodetable) => { |
||||||
|
|
||||||
|
|
||||||
|
let nodes = {} |
||||||
|
const CMD_DELAY = 200; |
||||||
|
|
||||||
|
let delay = (time_ms) => new Promise(resolve => { |
||||||
|
setTimeout(()=>{ |
||||||
|
resolve(); |
||||||
|
}, time_ms); |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const event = logger.getLogger('event'); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
nodetable.newNode((nid, info) => { |
||||||
|
nodes[nid] = { |
||||||
|
send: (name, body, isudp) => { |
||||||
|
return nodetable.outgo(nid, { |
||||||
|
to: nid, |
||||||
|
from: "director", |
||||||
|
name: name, |
||||||
|
body: body |
||||||
|
}, isudp); |
||||||
|
}, |
||||||
|
triggers: { |
||||||
|
income: [ |
||||||
|
function(name, body){ |
||||||
|
if(name == '__getInfo'){ |
||||||
|
nodes[nid].info.localport = body.port; |
||||||
|
nodes[nid].info.localip = body.ip; |
||||||
|
nodes[nid].info.funcID = body.funcID; |
||||||
|
nodes[nid].info.HeartbeatInterval = body.HeartbeatInterval; |
||||||
|
nodes[nid].ns = body.ns; |
||||||
|
nodes[nid].LastRefreshTime = new Date().valueOf(); |
||||||
|
} |
||||||
|
}, |
||||||
|
function(name, body){ |
||||||
|
if(name == '__checkNS'){ |
||||||
|
if(!nodes[nid].rns.hasOwnProperty(body.from) || nodes[nid].rns[body.from].ip != body.ip || nodes[nid].rns[body.from].port != body.port){ |
||||||
|
nodes[nid].rns[body.from] = body; |
||||||
|
nodes[nid].rns[body.from].updated = true; |
||||||
|
} |
||||||
|
nodes[nid].rns[body.from].LastCheckTime = new Date().valueOf(); |
||||||
|
} |
||||||
|
} |
||||||
|
], |
||||||
|
connect: [], |
||||||
|
disconnect: [], |
||||||
|
restart: [], |
||||||
|
error: [] |
||||||
|
}, |
||||||
|
LastRefreshTime: 0, |
||||||
|
LastRestartTime: 0, |
||||||
|
ns: {}, |
||||||
|
rns: {}, |
||||||
|
on: (type, cb) => { |
||||||
|
nodes[nid].triggers[type].push(cb); |
||||||
|
}, |
||||||
|
restart: () => new Promise((resolve) => { |
||||||
|
let restartTime = new Date().valueOf(); |
||||||
|
let counter = 100; |
||||||
|
nodes[nid].send('__restart', ''); |
||||||
|
let timer = () => { |
||||||
|
setTimeout(()=>{ |
||||||
|
if(nodes[nid].info.LastUpTime < restartTime){ |
||||||
|
if(counter){ |
||||||
|
if(nodes[nid].info.LastActiveTime > restartTime + 500){ |
||||||
|
nodes[nid].send('__restart', ''); |
||||||
|
restartTime = new Date().valueOf(); |
||||||
|
counter = 100; |
||||||
|
} |
||||||
|
timer(); |
||||||
|
counter --; |
||||||
|
}else{ |
||||||
|
resolve(false); |
||||||
|
return; |
||||||
|
} |
||||||
|
}else{ |
||||||
|
event.info('[CMD]', '<'+nid+'>', '__restart'); |
||||||
|
resolve(true); |
||||||
|
return; |
||||||
|
} |
||||||
|
}, 300); |
||||||
|
}; |
||||||
|
timer(); |
||||||
|
}), |
||||||
|
refresh: () => new Promise((resolve) => { |
||||||
|
let startTime = new Date().valueOf(); |
||||||
|
let counter = 100; |
||||||
|
nodes[nid].send('__getInfo', ''); |
||||||
|
let timer = () => { |
||||||
|
setTimeout(async ()=>{ |
||||||
|
if(nodes[nid].LastRefreshTime < startTime){ |
||||||
|
if(counter){ |
||||||
|
if(counter == 70 || counter == 40){ |
||||||
|
nodes[nid].send('__getInfo', ''); |
||||||
|
} |
||||||
|
timer(); |
||||||
|
counter--; |
||||||
|
}else{ |
||||||
|
resolve(false); |
||||||
|
return; |
||||||
|
} |
||||||
|
}else{ |
||||||
|
await delay(CMD_DELAY) |
||||||
|
event.info('[CMD]', '<'+nid+'>', '__refresh'); |
||||||
|
resolve(true); |
||||||
|
return; |
||||||
|
} |
||||||
|
}, 300); |
||||||
|
}; |
||||||
|
timer(); |
||||||
|
}), |
||||||
|
setNS: (nsArr) => new Promise(async (resolve) => { |
||||||
|
|
||||||
|
|
||||||
|
let checkLocalNS = () => Object.keys(nodes[nid].ns).every(id => { |
||||||
|
if(nsArr.hasOwnProperty(id) && nodes[nid].ns[id].ip == nsArr[id].ip && nodes[nid].ns[id].port == nsArr[id].port){ |
||||||
|
return true; |
||||||
|
}else{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
}) && Object.keys(nsArr).every(id => { |
||||||
|
if(nodes[nid].ns.hasOwnProperty(id) && nodes[nid].ns[id].ip == nsArr[id].ip && nodes[nid].ns[id].port == nsArr[id].port){ |
||||||
|
return true; |
||||||
|
}else{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(checkLocalNS()){ |
||||||
|
resolve(true); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
let body = {}; |
||||||
|
Object.keys(nsArr).forEach(id => { |
||||||
|
body[id] = { |
||||||
|
ip: nsArr[id].ip, |
||||||
|
port: nsArr[id].port |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
nodes[nid].send('__setNS', body); |
||||||
|
|
||||||
|
|
||||||
|
await delay(CMD_DELAY); |
||||||
|
|
||||||
|
if(checkLocalNS()){ |
||||||
|
event.info('[CMD]', '<'+nid+'>', '__setNS', JSON.stringify(Object.keys(body))); |
||||||
|
resolve(true); |
||||||
|
}else{ |
||||||
|
resolve(false); |
||||||
|
} |
||||||
|
|
||||||
|
}), |
||||||
|
checkNS: (id, ip, port) => new Promise(async (resolve) => { |
||||||
|
|
||||||
|
nodes[nid].send('__checkNS', { |
||||||
|
to: id, |
||||||
|
from: nid, |
||||||
|
ip: ip, |
||||||
|
port: port |
||||||
|
}, true); |
||||||
|
|
||||||
|
await delay(CMD_DELAY); |
||||||
|
|
||||||
|
nodes[nid].send('__checkNS', { |
||||||
|
to: id, |
||||||
|
from: nid, |
||||||
|
ip: ip, |
||||||
|
port: port |
||||||
|
},true); |
||||||
|
|
||||||
|
await delay(CMD_DELAY); |
||||||
|
|
||||||
|
event.info('[CMD]', '<'+nid+'>', '__checkNS', id); |
||||||
|
resolve(); |
||||||
|
|
||||||
|
}), |
||||||
|
setFunc: (id, func) => new Promise(async resolve => { |
||||||
|
let restartTime = new Date().valueOf(); |
||||||
|
let counter = 100; |
||||||
|
if(nodes[nid].info.funcID == id) { |
||||||
|
resolve(true); |
||||||
|
return;
|
||||||
|
} |
||||||
|
nodes[nid].send('__setFunc', { |
||||||
|
func: { |
||||||
|
id: id, |
||||||
|
online: func |
||||||
|
} |
||||||
|
}); |
||||||
|
let timer = () => { |
||||||
|
setTimeout(()=>{ |
||||||
|
if(nodes[nid].info.LastUpTime < restartTime || nodes[nid].info.funcID != id){ |
||||||
|
if(counter){ |
||||||
|
if(nodes[nid].info.LastActiveTime > restartTime + 500){ |
||||||
|
nodes[nid].send('__setFunc', { |
||||||
|
func: { |
||||||
|
id: id, |
||||||
|
online: func |
||||||
|
} |
||||||
|
}); |
||||||
|
restartTime = new Date().valueOf(); |
||||||
|
//counter = 100;
|
||||||
|
} |
||||||
|
timer(); |
||||||
|
counter --; |
||||||
|
}else{ |
||||||
|
resolve(false); |
||||||
|
return; |
||||||
|
} |
||||||
|
}else{ |
||||||
|
event.info('[CMD]', '<'+nid+'>', '__setFunc', id, func); |
||||||
|
resolve(true); |
||||||
|
return; |
||||||
|
} |
||||||
|
}, 300); |
||||||
|
}; |
||||||
|
timer(); |
||||||
|
}) |
||||||
|
}; |
||||||
|
nodes[nid].info = info; |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
nodetable.connect((nid, info) => { |
||||||
|
nodes[nid].status = true; |
||||||
|
if(new Date().valueOf() < nodes[nid].info.LastUpTime + nodes[nid].info.HeartbeatInterval){ |
||||||
|
nodes[nid].triggers.restart.forEach(cb => { |
||||||
|
cb(); |
||||||
|
}); |
||||||
|
nodes[nid].LastRestartTime = new Date().valueOf(); |
||||||
|
event.info('[RESTART]', '<'+nid+'>', '{'+info.funcID+'}'); |
||||||
|
} |
||||||
|
nodes[nid].triggers.connect.forEach(cb => { |
||||||
|
cb(); |
||||||
|
}); |
||||||
|
event.info('[CONNECT]', '<'+nid+'>', '{'+info.funcID+'}'); |
||||||
|
|
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
nodetable.disconnect((nid, info) => { |
||||||
|
nodes[nid].status = false; |
||||||
|
nodes[nid].triggers.disconnect.forEach(cb => { |
||||||
|
cb(); |
||||||
|
}); |
||||||
|
event.info('[DISCONNECT]', '<'+nid+'>', '{'+info.funcID+'}'); |
||||||
|
}); |
||||||
|
|
||||||
|
nodetable.income((nid, info, data) => { |
||||||
|
nodes[nid].status = true; |
||||||
|
nodes[nid].triggers.income.forEach(cb => { |
||||||
|
cb(data.name, data.body); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
nodetable.error((nid, info) => { |
||||||
|
nodes[nid].triggers.error.forEach(cb => { |
||||||
|
cb(info.error); |
||||||
|
}); |
||||||
|
event.error('[ERROR]', '<'+nid+'>', '{'+info.funcID+'}', info.error); |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
return nodes; |
||||||
|
} |
@ -0,0 +1,269 @@ |
|||||||
|
module.exports = (logger, host = '0.0.0.0', port = 6789) => { |
||||||
|
|
||||||
|
let cbArr = { |
||||||
|
income: [], |
||||||
|
outgo: [], |
||||||
|
forward: [], |
||||||
|
newNode: [], |
||||||
|
connect: [], |
||||||
|
disconnect: [], |
||||||
|
error: [] |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
let o = { |
||||||
|
income: cb => { //cb(nid, info{funcID, error}, data)
|
||||||
|
cbArr.income.push(cb); |
||||||
|
}, |
||||||
|
forward: cb => { //cb(nid, info{funcID, error}, data)
|
||||||
|
cbArr.forward.push(cb); |
||||||
|
}, |
||||||
|
outgo: (nid, data, isudp) => { |
||||||
|
if(!nidtable.hasOwnProperty(nid) || !nidtable[nid].socket || (!nidtable[nid].status && !isudp)){ |
||||||
|
flow.error('[OUTGOING]', '<nid lookup failure>', data.to+'<--'+data.from, data.name, data.body); |
||||||
|
return false; |
||||||
|
} |
||||||
|
try{ |
||||||
|
let raw = JSON.stringify(data); |
||||||
|
if(raw.length>1300){ |
||||||
|
let rawArr = []; |
||||||
|
let flag = require('md5')(Math.random()).substring(0,1); |
||||||
|
let n = 1300; |
||||||
|
for (let i = 0; i < raw.length/n; i++) { |
||||||
|
let prefix = '&'; |
||||||
|
if(i == 0){ |
||||||
|
prefix = '^'; |
||||||
|
} |
||||||
|
if(i >= raw.length/n - 1){ |
||||||
|
prefix = '$'; |
||||||
|
} |
||||||
|
setTimeout(()=>{ |
||||||
|
console.log(prefix + flag + raw.slice(n*i, n*(i+1))) |
||||||
|
nidtable[nid].socket.write(prefix + flag + raw.slice(n*i, n*(i+1))); |
||||||
|
}, i*2); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
}else{ |
||||||
|
nidtable[nid].socket.write(raw); |
||||||
|
} |
||||||
|
if(!isudp) nidtable[nid].status = false; |
||||||
|
}catch(e){ |
||||||
|
flow.error('[OUTGOING]', '<nid lookup failure>', data.to+'<--'+data.from, data.name, data.body); |
||||||
|
} |
||||||
|
|
||||||
|
cbArr.outgo.forEach(cb => { |
||||||
|
cb(nid, nidtable[nid], data); |
||||||
|
}); |
||||||
|
flow.log('[OUTGOING]', data.from + '-->' + data.to, data.name, data.body); |
||||||
|
return true; |
||||||
|
}, |
||||||
|
newNode: cb => { |
||||||
|
cbArr.newNode.push(cb); |
||||||
|
}, |
||||||
|
connect: cb => { |
||||||
|
cbArr.connect.push(cb); |
||||||
|
}, |
||||||
|
disconnect: cb => { |
||||||
|
cbArr.disconnect.push(cb); |
||||||
|
}, |
||||||
|
error: cb => { |
||||||
|
cbArr.error.push(cb); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let nidtable = {} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function isJson(str) { |
||||||
|
try { |
||||||
|
if (typeof JSON.parse(str) == "object") { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} catch(e) { |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
const net = require('net'); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const flow = logger.getLogger('flow'); |
||||||
|
const access = logger.getLogger('access'); |
||||||
|
|
||||||
|
|
||||||
|
const server = net.createServer((socket) => { |
||||||
|
access.trace('Unspecified', socket.remoteAddress+':'+socket.remotePort, 'New TCP request.'); |
||||||
|
socket.setKeepAlive(true); |
||||||
|
let nid = null; |
||||||
|
socket.on('data', (data) => { |
||||||
|
data = data.toString(); |
||||||
|
if(!isJson(data)){ |
||||||
|
access.error(nid, socket.remoteAddress+':'+socket.remotePort, 'Data is not JSON! Data::'+data); |
||||||
|
return; |
||||||
|
} |
||||||
|
data = JSON.parse(data); |
||||||
|
|
||||||
|
if(data.hasOwnProperty('nid') && data.hasOwnProperty('funcID') && data.hasOwnProperty('port') && data.hasOwnProperty('ip') && data.hasOwnProperty('HeartbeatInterval') && data.hasOwnProperty('uptime')){ |
||||||
|
nid = data.nid; |
||||||
|
let isNew = false; |
||||||
|
if(!nidtable.hasOwnProperty(nid)){ |
||||||
|
nidtable[nid] = {}; |
||||||
|
isNew = true; |
||||||
|
} |
||||||
|
if(nidtable[nid].socket){ |
||||||
|
nidtable[nid].socket.destroy(); |
||||||
|
nidtable[nid].socket = null; |
||||||
|
nidtable[nid].ip = null; |
||||||
|
nidtable[nid].port = null; |
||||||
|
access.info(nid, socket.remoteAddress+':'+socket.remotePort, '[CLOSE]'); |
||||||
|
cbArr.disconnect.forEach(cb => { |
||||||
|
cb(nid, nidtable[nid]); |
||||||
|
}); |
||||||
|
} |
||||||
|
nidtable[nid].status = true; |
||||||
|
nidtable[nid].funcID = data.funcID; |
||||||
|
nidtable[nid].localport = data.port; |
||||||
|
nidtable[nid].localip = data.ip; |
||||||
|
nidtable[nid].HeartbeatInterval = data.HeartbeatInterval; |
||||||
|
nidtable[nid].LastUpTime = new Date().valueOf() - data.uptime*1000; |
||||||
|
nidtable[nid].LastActiveTime = new Date().valueOf(); |
||||||
|
nidtable[nid].ip = socket.remoteAddress; |
||||||
|
nidtable[nid].port = socket.remotePort; |
||||||
|
nidtable[nid].socket = socket; |
||||||
|
|
||||||
|
socket.setTimeout(2.2 * nidtable[nid].HeartbeatInterval); |
||||||
|
|
||||||
|
|
||||||
|
if(isNew){ |
||||||
|
cbArr.newNode.forEach(cb => { |
||||||
|
cb(nid, nidtable[nid]); |
||||||
|
}); |
||||||
|
} |
||||||
|
if(data.hasOwnProperty('error') && data.error){ |
||||||
|
nidtable[nid].error = data.error; |
||||||
|
cbArr.error.forEach(cb => { |
||||||
|
cb(nid, nidtable[nid]); |
||||||
|
}); |
||||||
|
} |
||||||
|
cbArr.connect.forEach(cb => { |
||||||
|
cb(nid, nidtable[nid]); |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
access.info(nid, socket.remoteAddress+':'+socket.remotePort, 'New TCP connection. Data::', JSON.stringify(data)); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if(!nid){ |
||||||
|
access.error(nid, socket.remoteAddress+':'+socket.remotePort, 'No nid is specified. Data::', data); |
||||||
|
return; |
||||||
|
} |
||||||
|
nidtable[nid].LastActiveTime = new Date().valueOf(); |
||||||
|
nidtable[nid].status = true; |
||||||
|
|
||||||
|
if(data.hasOwnProperty('uptime') && data.hasOwnProperty('heap') && data.hasOwnProperty('spiff')){ |
||||||
|
nidtable[nid].LastUpTime = new Date().valueOf() - data.uptime*1000; |
||||||
|
nidtable[nid].heap = data.heap; |
||||||
|
nidtable[nid].spiff = data.spiff; |
||||||
|
access.info(nid, socket.remoteAddress+':'+socket.remotePort, '[HEARTBEAT]', data); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if(!data.hasOwnProperty('from') || !data.hasOwnProperty('to') || !data.hasOwnProperty('name') || !data.hasOwnProperty('body')){ |
||||||
|
access.error(nid, socket.remoteAddress+':'+socket.remotePort, 'Illegal package format. Data::', data); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
if(data.to != 'director'){ |
||||||
|
if(nidtable.hasOwnProperty(data.to)){ |
||||||
|
try{ |
||||||
|
nidtable[data.to].socket.write(JSON.stringify(data)); |
||||||
|
flow.log('[FORWARD]', data.to+'<--'+data.from, data.name, data.body); |
||||||
|
}catch(e){console.error(e)} |
||||||
|
}else{ |
||||||
|
flow.error('[FORWARD]', '<nid lookup failure>', data.to+'<--'+data.from, data.name, data.body); |
||||||
|
} |
||||||
|
cbArr.forward.forEach(cb => { |
||||||
|
cb(nid, nidtable[nid], data); |
||||||
|
}); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
if(data.to == 'director'){ |
||||||
|
cbArr.income.forEach(cb => { |
||||||
|
cb(nid, nidtable[nid], data); |
||||||
|
}); |
||||||
|
flow.log('[INCOMING]', data.to+'<--'+data.from, data.name, data.body ); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}); |
||||||
|
|
||||||
|
socket.setTimeout(60 * 1000); |
||||||
|
socket.on('timeout', () => { |
||||||
|
access.info(nid, socket.remoteAddress+':'+socket.remotePort, '[TIMEOUT]', 'After', socket.timeout, 'ms'); |
||||||
|
try{ |
||||||
|
nidtable[nid].socket = null; |
||||||
|
nidtable[nid].ip = null; |
||||||
|
nidtable[nid].port = null; |
||||||
|
nidtable[nid].status = false; |
||||||
|
access.info(nid, socket.remoteAddress+':'+socket.remotePort, '[CLOSE]'); |
||||||
|
cbArr.disconnect.forEach(cb => { |
||||||
|
cb(nid, nidtable[nid]); |
||||||
|
}); |
||||||
|
}catch(e){ |
||||||
|
delete nidtable[nid]; |
||||||
|
} |
||||||
|
|
||||||
|
socket.destroy(); |
||||||
|
}); |
||||||
|
|
||||||
|
socket.on('error', function(err){ |
||||||
|
access.error(nid, socket.remoteAddress+':'+socket.remotePort, '[ERROR]', 'Exist unsent package'); |
||||||
|
}); |
||||||
|
|
||||||
|
socket.on('close', function(err){ |
||||||
|
if(nid && nidtable[nid].socket === socket){ |
||||||
|
nidtable[nid].socket = null; |
||||||
|
nidtable[nid].ip = null; |
||||||
|
nidtable[nid].port = null; |
||||||
|
nidtable[nid].status = false; |
||||||
|
access.info(nid, socket.remoteAddress+':'+socket.remotePort, '[CLOSE]'); |
||||||
|
cbArr.disconnect.forEach(cb => { |
||||||
|
cb(nid, nidtable[nid]); |
||||||
|
}); |
||||||
|
} |
||||||
|
}) |
||||||
|
}).on('error', (err) => { |
||||||
|
|
||||||
|
access.error('[ERROR]', 'Exist unsent package'); |
||||||
|
}); |
||||||
|
|
||||||
|
// Grab an arbitrary unused port.
|
||||||
|
server.listen({ |
||||||
|
host: host, |
||||||
|
port: port, |
||||||
|
exclusive: true |
||||||
|
}, () => { |
||||||
|
access.info('TCP Server Begin at ', host + ':' + port); |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return o; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,74 @@ |
|||||||
|
module.exports = (logger, node, nodetable) => { |
||||||
|
|
||||||
|
|
||||||
|
const log = logger.getLogger('nslog'); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const NS_DELAY = 2000; |
||||||
|
|
||||||
|
|
||||||
|
let delay = (time_ms) => new Promise(resolve => { |
||||||
|
setTimeout(()=>{ |
||||||
|
resolve(); |
||||||
|
}, time_ms); |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let o = { |
||||||
|
get: (nodeArr, refer) => new Promise(async resolve => { |
||||||
|
let list = []; |
||||||
|
nodeArr.forEach(nid => { |
||||||
|
if(node.hasOwnProperty(nid)){ |
||||||
|
list.push(nid); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
let nsList = {}; |
||||||
|
let beginTime = new Date().valueOf(); |
||||||
|
for(nid1 of list){ |
||||||
|
for(nid2 of list){ |
||||||
|
if(nid1 != nid2){ |
||||||
|
log.info('[CHECK]', nid2, '-->', nid1); |
||||||
|
await node[nid2].checkNS(nid1, refer && refer[nid2] && refer[nid2][nid1] && refer[nid2][nid1].ip || node[nid1].info.localip, refer && refer[nid2] && refer[nid2][nid1] && refer[nid2][nid1].port || node[nid1].info.localport) |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
await delay(NS_DELAY); |
||||||
|
|
||||||
|
list.forEach(nid => { |
||||||
|
Object.keys(node[nid].rns).forEach(nid2 => { |
||||||
|
let rns = node[nid].rns[nid2]; |
||||||
|
if(rns.LastCheckTime > beginTime){ |
||||||
|
log.info('[VERIFIED]', nid2, '-->', nid); |
||||||
|
if(!nsList.hasOwnProperty(nid2)){ |
||||||
|
nsList[nid2] = {}; |
||||||
|
} |
||||||
|
nsList[nid2][nid] = { |
||||||
|
ip: rns.ip, |
||||||
|
port: rns.port |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
resolve(nsList); |
||||||
|
|
||||||
|
}), |
||||||
|
set: (nsList) => new Promise(async resolve => { |
||||||
|
let status = true; |
||||||
|
Object.keys(nsList).forEach(async nidf => { |
||||||
|
log.info('[SET]', nidf, '::', JSON.stringify(nsList[nidf])); |
||||||
|
status = status && await node[nidf].setNS(nsList[nidf]); |
||||||
|
}); |
||||||
|
resolve(status); |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return o; |
||||||
|
} |
@ -0,0 +1,446 @@ |
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. |
||||||
|
# yarn lockfile v1 |
||||||
|
|
||||||
|
|
||||||
|
accepts@~1.3.7: |
||||||
|
version "1.3.7" |
||||||
|
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" |
||||||
|
integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== |
||||||
|
dependencies: |
||||||
|
mime-types "~2.1.24" |
||||||
|
negotiator "0.6.2" |
||||||
|
|
||||||
|
array-flatten@1.1.1: |
||||||
|
version "1.1.1" |
||||||
|
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" |
||||||
|
integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= |
||||||
|
|
||||||
|
body-parser@1.19.0: |
||||||
|
version "1.19.0" |
||||||
|
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" |
||||||
|
integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== |
||||||
|
dependencies: |
||||||
|
bytes "3.1.0" |
||||||
|
content-type "~1.0.4" |
||||||
|
debug "2.6.9" |
||||||
|
depd "~1.1.2" |
||||||
|
http-errors "1.7.2" |
||||||
|
iconv-lite "0.4.24" |
||||||
|
on-finished "~2.3.0" |
||||||
|
qs "6.7.0" |
||||||
|
raw-body "2.4.0" |
||||||
|
type-is "~1.6.17" |
||||||
|
|
||||||
|
bytes@3.1.0: |
||||||
|
version "3.1.0" |
||||||
|
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" |
||||||
|
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== |
||||||
|
|
||||||
|
content-disposition@0.5.3: |
||||||
|
version "0.5.3" |
||||||
|
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" |
||||||
|
integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== |
||||||
|
dependencies: |
||||||
|
safe-buffer "5.1.2" |
||||||
|
|
||||||
|
content-type@~1.0.4: |
||||||
|
version "1.0.4" |
||||||
|
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" |
||||||
|
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== |
||||||
|
|
||||||
|
cookie-signature@1.0.6: |
||||||
|
version "1.0.6" |
||||||
|
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" |
||||||
|
integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= |
||||||
|
|
||||||
|
cookie@0.4.0: |
||||||
|
version "0.4.0" |
||||||
|
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" |
||||||
|
integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== |
||||||
|
|
||||||
|
date-format@^2.1.0: |
||||||
|
version "2.1.0" |
||||||
|
resolved "https://registry.yarnpkg.com/date-format/-/date-format-2.1.0.tgz#31d5b5ea211cf5fd764cd38baf9d033df7e125cf" |
||||||
|
integrity sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA== |
||||||
|
|
||||||
|
date-format@^3.0.0: |
||||||
|
version "3.0.0" |
||||||
|
resolved "https://registry.yarnpkg.com/date-format/-/date-format-3.0.0.tgz#eb8780365c7d2b1511078fb491e6479780f3ad95" |
||||||
|
integrity sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w== |
||||||
|
|
||||||
|
debug@2.6.9: |
||||||
|
version "2.6.9" |
||||||
|
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" |
||||||
|
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== |
||||||
|
dependencies: |
||||||
|
ms "2.0.0" |
||||||
|
|
||||||
|
debug@^4.1.1: |
||||||
|
version "4.3.1" |
||||||
|
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" |
||||||
|
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== |
||||||
|
dependencies: |
||||||
|
ms "2.1.2" |
||||||
|
|
||||||
|
depd@~1.1.2: |
||||||
|
version "1.1.2" |
||||||
|
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" |
||||||
|
integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= |
||||||
|
|
||||||
|
destroy@~1.0.4: |
||||||
|
version "1.0.4" |
||||||
|
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" |
||||||
|
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= |
||||||
|
|
||||||
|
ee-first@1.1.1: |
||||||
|
version "1.1.1" |
||||||
|
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" |
||||||
|
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= |
||||||
|
|
||||||
|
encodeurl@~1.0.2: |
||||||
|
version "1.0.2" |
||||||
|
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" |
||||||
|
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= |
||||||
|
|
||||||
|
escape-html@~1.0.3: |
||||||
|
version "1.0.3" |
||||||
|
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" |
||||||
|
integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= |
||||||
|
|
||||||
|
etag@~1.8.1: |
||||||
|
version "1.8.1" |
||||||
|
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" |
||||||
|
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= |
||||||
|
|
||||||
|
express@^4.17.1: |
||||||
|
version "4.17.1" |
||||||
|
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" |
||||||
|
integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== |
||||||
|
dependencies: |
||||||
|
accepts "~1.3.7" |
||||||
|
array-flatten "1.1.1" |
||||||
|
body-parser "1.19.0" |
||||||
|
content-disposition "0.5.3" |
||||||
|
content-type "~1.0.4" |
||||||
|
cookie "0.4.0" |
||||||
|
cookie-signature "1.0.6" |
||||||
|
debug "2.6.9" |
||||||
|
depd "~1.1.2" |
||||||
|
encodeurl "~1.0.2" |
||||||
|
escape-html "~1.0.3" |
||||||
|
etag "~1.8.1" |
||||||
|
finalhandler "~1.1.2" |
||||||
|
fresh "0.5.2" |
||||||
|
merge-descriptors "1.0.1" |
||||||
|
methods "~1.1.2" |
||||||
|
on-finished "~2.3.0" |
||||||
|
parseurl "~1.3.3" |
||||||
|
path-to-regexp "0.1.7" |
||||||
|
proxy-addr "~2.0.5" |
||||||
|
qs "6.7.0" |
||||||
|
range-parser "~1.2.1" |
||||||
|
safe-buffer "5.1.2" |
||||||
|
send "0.17.1" |
||||||
|
serve-static "1.14.1" |
||||||
|
setprototypeof "1.1.1" |
||||||
|
statuses "~1.5.0" |
||||||
|
type-is "~1.6.18" |
||||||
|
utils-merge "1.0.1" |
||||||
|
vary "~1.1.2" |
||||||
|
|
||||||
|
finalhandler@~1.1.2: |
||||||
|
version "1.1.2" |
||||||
|
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" |
||||||
|
integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== |
||||||
|
dependencies: |
||||||
|
debug "2.6.9" |
||||||
|
encodeurl "~1.0.2" |
||||||
|
escape-html "~1.0.3" |
||||||
|
on-finished "~2.3.0" |
||||||
|
parseurl "~1.3.3" |
||||||
|
statuses "~1.5.0" |
||||||
|
unpipe "~1.0.0" |
||||||
|
|
||||||
|
flatted@^2.0.1: |
||||||
|
version "2.0.2" |
||||||
|
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" |
||||||
|
integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== |
||||||
|
|
||||||
|
forwarded@~0.1.2: |
||||||
|
version "0.1.2" |
||||||
|
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" |
||||||
|
integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= |
||||||
|
|
||||||
|
fresh@0.5.2: |
||||||
|
version "0.5.2" |
||||||
|
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" |
||||||
|
integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= |
||||||
|
|
||||||
|
fs-extra@^8.1.0: |
||||||
|
version "8.1.0" |
||||||
|
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" |
||||||
|
integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== |
||||||
|
dependencies: |
||||||
|
graceful-fs "^4.2.0" |
||||||
|
jsonfile "^4.0.0" |
||||||
|
universalify "^0.1.0" |
||||||
|
|
||||||
|
graceful-fs@^4.1.6, graceful-fs@^4.2.0: |
||||||
|
version "4.2.6" |
||||||
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" |
||||||
|
integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== |
||||||
|
|
||||||
|
http-errors@1.7.2: |
||||||
|
version "1.7.2" |
||||||
|
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" |
||||||
|
integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== |
||||||
|
dependencies: |
||||||
|
depd "~1.1.2" |
||||||
|
inherits "2.0.3" |
||||||
|
setprototypeof "1.1.1" |
||||||
|
statuses ">= 1.5.0 < 2" |
||||||
|
toidentifier "1.0.0" |
||||||
|
|
||||||
|
http-errors@~1.7.2: |
||||||
|
version "1.7.3" |
||||||
|
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" |
||||||
|
integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== |
||||||
|
dependencies: |
||||||
|
depd "~1.1.2" |
||||||
|
inherits "2.0.4" |
||||||
|
setprototypeof "1.1.1" |
||||||
|
statuses ">= 1.5.0 < 2" |
||||||
|
toidentifier "1.0.0" |
||||||
|
|
||||||
|
iconv-lite@0.4.24: |
||||||
|
version "0.4.24" |
||||||
|
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" |
||||||
|
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== |
||||||
|
dependencies: |
||||||
|
safer-buffer ">= 2.1.2 < 3" |
||||||
|
|
||||||
|
inherits@2.0.3: |
||||||
|
version "2.0.3" |
||||||
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" |
||||||
|
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= |
||||||
|
|
||||||
|
inherits@2.0.4: |
||||||
|
version "2.0.4" |
||||||
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" |
||||||
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== |
||||||
|
|
||||||
|
ipaddr.js@1.9.1: |
||||||
|
version "1.9.1" |
||||||
|
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" |
||||||
|
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== |
||||||
|
|
||||||
|
jsonfile@^4.0.0: |
||||||
|
version "4.0.0" |
||||||
|
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" |
||||||
|
integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= |
||||||
|
optionalDependencies: |
||||||
|
graceful-fs "^4.1.6" |
||||||
|
|
||||||
|
log4js@^6.3.0: |
||||||
|
version "6.3.0" |
||||||
|
resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.3.0.tgz#10dfafbb434351a3e30277a00b9879446f715bcb" |
||||||
|
integrity sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw== |
||||||
|
dependencies: |
||||||
|
date-format "^3.0.0" |
||||||
|
debug "^4.1.1" |
||||||
|
flatted "^2.0.1" |
||||||
|
rfdc "^1.1.4" |
||||||
|
streamroller "^2.2.4" |
||||||
|
|
||||||
|
media-typer@0.3.0: |
||||||
|
version "0.3.0" |
||||||
|
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" |
||||||
|
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= |
||||||
|
|
||||||
|
merge-descriptors@1.0.1: |
||||||
|
version "1.0.1" |
||||||
|
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" |
||||||
|
integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= |
||||||
|
|
||||||
|
methods@~1.1.2: |
||||||
|
version "1.1.2" |
||||||
|
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" |
||||||
|
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= |
||||||
|
|
||||||
|
mime-db@1.46.0: |
||||||
|
version "1.46.0" |
||||||
|
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.46.0.tgz#6267748a7f799594de3cbc8cde91def349661cee" |
||||||
|
integrity sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ== |
||||||
|
|
||||||
|
mime-types@~2.1.24: |
||||||
|
version "2.1.29" |
||||||
|
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.29.tgz#1d4ab77da64b91f5f72489df29236563754bb1b2" |
||||||
|
integrity sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ== |
||||||
|
dependencies: |
||||||
|
mime-db "1.46.0" |
||||||
|
|
||||||
|
mime@1.6.0: |
||||||
|
version "1.6.0" |
||||||
|
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" |
||||||
|
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== |
||||||
|
|
||||||
|
ms@2.0.0: |
||||||
|
version "2.0.0" |
||||||
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" |
||||||
|
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= |
||||||
|
|
||||||
|
ms@2.1.1: |
||||||
|
version "2.1.1" |
||||||
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" |
||||||
|
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== |
||||||
|
|
||||||
|
ms@2.1.2: |
||||||
|
version "2.1.2" |
||||||
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" |
||||||
|
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== |
||||||
|
|
||||||
|
negotiator@0.6.2: |
||||||
|
version "0.6.2" |
||||||
|
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" |
||||||
|
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== |
||||||
|
|
||||||
|
on-finished@~2.3.0: |
||||||
|
version "2.3.0" |
||||||
|
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" |
||||||
|
integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= |
||||||
|
dependencies: |
||||||
|
ee-first "1.1.1" |
||||||
|
|
||||||
|
parseurl@~1.3.3: |
||||||
|
version "1.3.3" |
||||||
|
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" |
||||||
|
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== |
||||||
|
|
||||||
|
path-to-regexp@0.1.7: |
||||||
|
version "0.1.7" |
||||||
|
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" |
||||||
|
integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= |
||||||
|
|
||||||
|
proxy-addr@~2.0.5: |
||||||
|
version "2.0.6" |
||||||
|
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" |
||||||
|
integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== |
||||||
|
dependencies: |
||||||
|
forwarded "~0.1.2" |
||||||
|
ipaddr.js "1.9.1" |
||||||
|
|
||||||
|
qs@6.7.0: |
||||||
|
version "6.7.0" |
||||||
|
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" |
||||||
|
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== |
||||||
|
|
||||||
|
range-parser@~1.2.1: |
||||||
|
version "1.2.1" |
||||||
|
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" |
||||||
|
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== |
||||||
|
|
||||||
|
raw-body@2.4.0: |
||||||
|
version "2.4.0" |
||||||
|
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" |
||||||
|
integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== |
||||||
|
dependencies: |
||||||
|
bytes "3.1.0" |
||||||
|
http-errors "1.7.2" |
||||||
|
iconv-lite "0.4.24" |
||||||
|
unpipe "1.0.0" |
||||||
|
|
||||||
|
rfdc@^1.1.4: |
||||||
|
version "1.3.0" |
||||||
|
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" |
||||||
|
integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== |
||||||
|
|
||||||
|
safe-buffer@5.1.2: |
||||||
|
version "5.1.2" |
||||||
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" |
||||||
|
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== |
||||||
|
|
||||||
|
"safer-buffer@>= 2.1.2 < 3": |
||||||
|
version "2.1.2" |
||||||
|
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" |
||||||
|
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== |
||||||
|
|
||||||
|
send@0.17.1: |
||||||
|
version "0.17.1" |
||||||
|
resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" |
||||||
|
integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== |
||||||
|
dependencies: |
||||||
|
debug "2.6.9" |
||||||
|
depd "~1.1.2" |
||||||
|
destroy "~1.0.4" |
||||||
|
encodeurl "~1.0.2" |
||||||
|
escape-html "~1.0.3" |
||||||
|
etag "~1.8.1" |
||||||
|
fresh "0.5.2" |
||||||
|
http-errors "~1.7.2" |
||||||
|
mime "1.6.0" |
||||||
|
ms "2.1.1" |
||||||
|
on-finished "~2.3.0" |
||||||
|
range-parser "~1.2.1" |
||||||
|
statuses "~1.5.0" |
||||||
|
|
||||||
|
serve-static@1.14.1: |
||||||
|
version "1.14.1" |
||||||
|
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" |
||||||
|
integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== |
||||||
|
dependencies: |
||||||
|
encodeurl "~1.0.2" |
||||||
|
escape-html "~1.0.3" |
||||||
|
parseurl "~1.3.3" |
||||||
|
send "0.17.1" |
||||||
|
|
||||||
|
setprototypeof@1.1.1: |
||||||
|
version "1.1.1" |
||||||
|
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" |
||||||
|
integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== |
||||||
|
|
||||||
|
"statuses@>= 1.5.0 < 2", statuses@~1.5.0: |
||||||
|
version "1.5.0" |
||||||
|
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" |
||||||
|
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= |
||||||
|
|
||||||
|
streamroller@^2.2.4: |
||||||
|
version "2.2.4" |
||||||
|
resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-2.2.4.tgz#c198ced42db94086a6193608187ce80a5f2b0e53" |
||||||
|
integrity sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ== |
||||||
|
dependencies: |
||||||
|
date-format "^2.1.0" |
||||||
|
debug "^4.1.1" |
||||||
|
fs-extra "^8.1.0" |
||||||
|
|
||||||
|
toidentifier@1.0.0: |
||||||
|
version "1.0.0" |
||||||
|
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" |
||||||
|
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== |
||||||
|
|
||||||
|
type-is@~1.6.17, type-is@~1.6.18: |
||||||
|
version "1.6.18" |
||||||
|
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" |
||||||
|
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== |
||||||
|
dependencies: |
||||||
|
media-typer "0.3.0" |
||||||
|
mime-types "~2.1.24" |
||||||
|
|
||||||
|
universalify@^0.1.0: |
||||||
|
version "0.1.2" |
||||||
|
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" |
||||||
|
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== |
||||||
|
|
||||||
|
unpipe@1.0.0, unpipe@~1.0.0: |
||||||
|
version "1.0.0" |
||||||
|
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" |
||||||
|
integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= |
||||||
|
|
||||||
|
utils-merge@1.0.1: |
||||||
|
version "1.0.1" |
||||||
|
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" |
||||||
|
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= |
||||||
|
|
||||||
|
vary@~1.1.2: |
||||||
|
version "1.1.2" |
||||||
|
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" |
||||||
|
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= |
Loading…
Reference in new issue