residue
Advanced tools
Comparing version 2.3.19 to 3.0.0
# Change Log | ||
## [3.0.0] | ||
- ResidueClient constructible to create unique instances for various clients | ||
## [2.3.18] | ||
@@ -4,0 +7,0 @@ - Fixed warning log |
16
index.js
'use strict'; | ||
try { | ||
module.exports = require('residue-native'); | ||
module.exports = require('./src/native'); | ||
module.exports = require('residue-native'); | ||
module.exports = require('./src/native'); | ||
} catch (e) { | ||
if (e.message.indexOf('Cannot find module \'residue-native\'') === -1) { | ||
// User is trying to use residue-native and getting error so we display | ||
// the error message | ||
console.log(e.message); | ||
} | ||
module.exports = require('./src/residue'); | ||
if (e.message.indexOf('Cannot find module \'residue-native\'') === -1) { | ||
// User is trying to use residue-native and getting error so we display | ||
// the error message | ||
console.log(e.message); | ||
} | ||
module.exports = require('./src/residue'); | ||
} |
{ | ||
"name": "residue", | ||
"version": "2.3.19", | ||
"version": "3.0.0", | ||
"description": "Library to interact with residue server seamlessly.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -11,3 +11,3 @@ ﷽ | ||
A very simple, secure Node.js library to interact with residue seamlessly. | ||
Secure Node.js library to interact with residue server seamlessly. | ||
@@ -49,5 +49,8 @@ This module provides interface for connecting and interacting with residue server seamlessly, means, once you are connected this module takes care of expired tokens and clients and keep itself updated with latest tokens and ping server when needed to stay alive. | ||
```js | ||
var residue = require('residue'); | ||
var logger = residue.getLogger('sample-app'); | ||
const ResidueClient = require('residue'); | ||
const residue = new ResidueClient(); | ||
const logger = residue.getLogger('sample-app'); | ||
const confFile = 'client.conf.json'; | ||
@@ -54,0 +57,0 @@ if (residue.loadConfiguration(confFile)) { |
@@ -22,62 +22,68 @@ // | ||
const Logger = function(id) { | ||
this.id = id; | ||
this.id = id; | ||
// we don't need this because binary comes with CreateLoggerAutomatically flag set | ||
// (see CMakeLists.txt) but will still do it so we have it available before hand | ||
residue_native.register_logger(this.id); | ||
// we don't need this because binary comes with CreateLoggerAutomatically flag set | ||
// (see CMakeLists.txt) but will still do it so we have it available before hand | ||
residue_native.register_logger(this.id); | ||
this.trace = (fmt, ...args) => this._write_log(CommonUtils.LoggingLevels.Trace, undefined, fmt, ...args); | ||
this.debug = (fmt, ...args) => this._write_log(CommonUtils.LoggingLevels.Debug, undefined, fmt, ...args); | ||
this.fatal = (fmt, ...args) => this._write_log(CommonUtils.LoggingLevels.Fatal, undefined, fmt, ...args); | ||
this.error = (fmt, ...args) => this._write_log(CommonUtils.LoggingLevels.Error, undefined, fmt, ...args); | ||
this.warn = (fmt, ...args) => this._write_log(CommonUtils.LoggingLevels.Warning, undefined, fmt, ...args); | ||
this.info = (fmt, ...args) => this._write_log(CommonUtils.LoggingLevels.Info, undefined, fmt, ...args); | ||
this.verbose = (vlevel, fmt, ...args) => this._write_log(CommonUtils.LoggingLevels.Verbose, vlevel, fmt, ...args); | ||
this.trace = (fmt, ...args) => this._write_log(CommonUtils.LoggingLevels.Trace, undefined, fmt, ...args); | ||
this.debug = (fmt, ...args) => this._write_log(CommonUtils.LoggingLevels.Debug, undefined, fmt, ...args); | ||
this.fatal = (fmt, ...args) => this._write_log(CommonUtils.LoggingLevels.Fatal, undefined, fmt, ...args); | ||
this.error = (fmt, ...args) => this._write_log(CommonUtils.LoggingLevels.Error, undefined, fmt, ...args); | ||
this.warn = (fmt, ...args) => this._write_log(CommonUtils.LoggingLevels.Warning, undefined, fmt, ...args); | ||
this.info = (fmt, ...args) => this._write_log(CommonUtils.LoggingLevels.Info, undefined, fmt, ...args); | ||
this.verbose = (vlevel, fmt, ...args) => this._write_log(CommonUtils.LoggingLevels.Verbose, vlevel, fmt, ...args); | ||
// private members | ||
// private members | ||
this._source_base_index = 5; | ||
this._write_log = (level, vlevel, fmt, ...args) => { | ||
const fullMessage = CommonUtils.translateArgs(true, ...args); | ||
this._source_base_index = 5; | ||
this._write_log = (level, vlevel, fmt, ...args) => { | ||
const fullMessage = CommonUtils.translateArgs(true, ...args); | ||
residue_native.write_log(this.id, | ||
this.log_sources.getSourceFile(), | ||
this.log_sources.getSourceLine(), | ||
this.log_sources.getSourceFunc(), | ||
util.format(fmt, ...fullMessage), | ||
level, | ||
vlevel); | ||
} | ||
residue_native.write_log(this.id, | ||
this.log_sources.getSourceFile(), | ||
this.log_sources.getSourceLine(), | ||
this.log_sources.getSourceFunc(), | ||
util.format(fmt, ...fullMessage), | ||
level, | ||
vlevel); | ||
} | ||
this.log_sources = { | ||
base_idx: 6, | ||
getSourceFile: () => CommonUtils.getSourceFile(this.log_sources.base_idx), | ||
getSourceLine: () => CommonUtils.getSourceLine(this.log_sources.base_idx), | ||
getSourceFunc: () => CommonUtils.getSourceFunc(this.log_sources.base_idx), | ||
}; | ||
this.log_sources = { | ||
base_idx: 6, | ||
getSourceFile: () => CommonUtils.getSourceFile(this.log_sources.base_idx), | ||
getSourceLine: () => CommonUtils.getSourceLine(this.log_sources.base_idx), | ||
getSourceFunc: () => CommonUtils.getSourceFunc(this.log_sources.base_idx), | ||
}; | ||
}; | ||
const loadConfiguration = (jsonOrFilename) => { | ||
const ResidueClient = function() { | ||
this.version = residue_native.version; | ||
this.type = () => 'native'; | ||
this.connect = (json) => { | ||
if (typeof json === 'object') { | ||
loadConfiguration(json); | ||
} | ||
residue_native.connect(); | ||
}; | ||
this.disconnect = residue_native.disconnect; | ||
this.isConnected = residue_native.is_connected; | ||
this.getLogger = (id) => (new Logger(id)); | ||
this.loadConfiguration = (jsonOrFilename) => { | ||
const conf = CommonUtils.confJson(jsonOrFilename); | ||
if (conf === false) { | ||
console.error('Please select JSON or JSON filename that contains configurations'); | ||
return false; | ||
console.error('Please select JSON or JSON filename that contains configurations'); | ||
return false; | ||
} | ||
residue_native.configure(conf); | ||
return true; | ||
}; | ||
}; | ||
const connect = (json) => { | ||
if (typeof json === 'object') { | ||
loadConfiguration(json); | ||
} | ||
residue_native.connect(); | ||
}; | ||
exports.version = residue_native.version; | ||
exports.type = () => 'native'; | ||
exports.loadConfiguration = loadConfiguration; | ||
exports.connect = connect; | ||
exports.disconnect = residue_native.disconnect; | ||
exports.isConnected = residue_native.is_connected; | ||
exports.getLogger = (id) => (new Logger(id)); | ||
module.exports = ResidueClient; |
1020
src/residue.js
@@ -9,3 +9,3 @@ // | ||
// takes care of lost connections, expired clients | ||
// and keep itself updated with parameters and touch server when | ||
// and keep itself updated with parameters and touch server when | ||
// needed to stay alive. | ||
@@ -20,3 +20,3 @@ // | ||
"use strict"; | ||
"use strict"; | ||
@@ -32,54 +32,15 @@ const fs = require('fs'); | ||
try { | ||
crypto = require('crypto'); | ||
crypto = require('crypto'); | ||
} catch (err) { | ||
console.log('residue package requires crypto (https://nodejs.org/api/crypto.html). It is disabled in your version of node!'); | ||
console.log('residue package requires crypto (https://nodejs.org/api/crypto.html). It is disabled in your version of node!'); | ||
} | ||
const Params = { | ||
// user provided options for seamless connection | ||
// app, host, connect_port | ||
options: {}, | ||
const DEBUGGING = true; | ||
const VERBOSE_LEVEL = 9; | ||
// connecting object containing: | ||
// client_id, age, date_created, key, logging_port | ||
connection: null, | ||
// rsa_key is keypair object | ||
rsa_key: null, | ||
// server_rsa_key is keypair object | ||
server_rsa_key: null, | ||
// whether connected to the server or not | ||
connected: false, | ||
// Underlying sockets | ||
connection_socket: new net.Socket(), | ||
logging_socket: new net.Socket(), | ||
// Debug logging | ||
debugging: false, | ||
verboseLevel: 0, | ||
// Status for sockets | ||
logging_socket_connected: false, | ||
// callbacks on specific occasions | ||
send_request_backlog_callbacks: [], | ||
logging_socket_callbacks: [], | ||
// locks for mutex | ||
locks: {}, | ||
}; | ||
Params.locks[Params.connection_socket.address().port] = false; | ||
Params.locks[Params.logging_socket.address().port] = false; | ||
// Various connection types accepted by the server | ||
const ConnectType = { | ||
Connect: 1, | ||
Acknowledgement: 2, | ||
Touch: 3 | ||
CONN: 1, | ||
ACK: 2, | ||
TOUCH: 3, | ||
}; | ||
@@ -97,330 +58,407 @@ | ||
const isNormalInteger = (str) => { | ||
var n = Math.floor(Number(str)); | ||
return String(n) === str && n >= 0; | ||
}; | ||
// Logger interface for user to send log messages to server | ||
const Logger = function(id, client) { | ||
this.id = id; | ||
this.client = client; | ||
this.info = (format, ...args) => this._write(CommonUtils.LoggingLevels.Info, 0, format, ...args); | ||
this.error = (format, ...args) => this._write(CommonUtils.LoggingLevels.Error, 0, format, ...args); | ||
this.debug = (format, ...args) => this._write(CommonUtils.LoggingLevels.Debug, 0, format, ...args); | ||
this.warn = (format, ...args) => this._write(CommonUtils.LoggingLevels.Warning, 0, format, ...args); | ||
this.trace = (format, ...args) => this._write(CommonUtils.LoggingLevels.Trace, 0, format, ...args); | ||
this.fatal = (format, ...args) => this._write(CommonUtils.LoggingLevels.Fatal, 0, format, ...args); | ||
this.verbose = (vlevel, format, ...args) => this._write(CommonUtils.LoggingLevels.Verbose, vlevel, format, ...args); | ||
//private members | ||
this._write = (level, vlevel, format, ...args) => client._sendLogRequest(level, | ||
this.id, | ||
this._logSources.getSourceFile(), | ||
this._logSources.getSourceLine(), | ||
this._logSources.getSourceFunc(), | ||
vlevel, | ||
undefined, | ||
format, | ||
...args); | ||
this._logSources = { | ||
baseIndex: 6, | ||
getSourceFile: () => CommonUtils.getSourceFile(this._logSources.baseIndex), | ||
getSourceLine: () => CommonUtils.getSourceLine(this._logSources.baseIndex), | ||
getSourceFunc: () => CommonUtils.getSourceFunc(this._logSources.baseIndex), | ||
}; | ||
}; | ||
// Utility static functions | ||
const Utils = { | ||
log: (m) => console.log(m), | ||
log: (m, ...args) => { | ||
console.log(m, ...args); | ||
}, | ||
debugLog: (m) => { | ||
if (Params.debugging) { | ||
console.log(m); | ||
} | ||
}, | ||
debugLog: (m, ...args) => { | ||
if (DEBUGGING) { | ||
console.log(`DEBUG: `, m, ...args); | ||
} | ||
}, | ||
traceLog: (m) => Utils.debugLog(`TRACE: ${m}`), | ||
traceLog: (m, ...args) => { | ||
if (DEBUGGING) { | ||
console.log(`TRACE: `, m, ...args); | ||
} | ||
}, | ||
vLog: (l, m) => { | ||
if (Params.debugging && l <= Params.verboseLevel) { | ||
console.log(m); | ||
} | ||
}, | ||
vLog: (level, m, ...args) => { | ||
if (DEBUGGING && level <= VERBOSE_LEVEL) { | ||
console.log(`VERBOSE ${level}: `, m, ...args); | ||
} | ||
}, | ||
hasFlag: (f) => { | ||
if (Params.connection === null) { | ||
return false; | ||
} | ||
return (Params.connection.flags & f) !== 0; | ||
}, | ||
hasFlag: (f, connection) => { | ||
if (connection === null) { | ||
return false; | ||
} | ||
return (connection.flags & f) !== 0; | ||
}, | ||
// Encode Base64 | ||
base64Encode: (str) => new Buffer(str).toString('base64'), | ||
// Encode Base64 | ||
base64Encode: str => new Buffer(str).toString('base64'), | ||
base64Decode: (encoded) => new Buffer(encoded, 'base64').toString('utf-8'), | ||
base64Decode: encoded => new Buffer(encoded, 'base64').toString('utf-8'), | ||
// Get current date in microseconds | ||
now: () => parseInt((new Date()).getTime() / 1000, 10), | ||
getCipherAlgorithm: keyHex => `aes-${(keyHex.length / 2) * 8}-cbc`, | ||
getTimestamp: () => Utils.now(), | ||
encrypt: (request, connection) => { | ||
let encryptedRequest; | ||
try { | ||
let iv = new Buffer(crypto.randomBytes(16), 'hex'); | ||
let cipher = crypto.createCipheriv(Utils.getCipherAlgorithm(connection.key), new Buffer(connection.key, 'hex'), iv); | ||
return iv.toString('hex') + ':' + connection.client_id + ':' + cipher.update(request, 'utf-8', 'base64') + cipher.final('base64') + PACKET_DELIMITER; | ||
} catch (err) { | ||
Utils.debugLog(err); | ||
} | ||
return ''; | ||
}, | ||
// Send request to the server | ||
// This function decides whether to back-log the request or dispatch it to | ||
// the server | ||
sendRequest: (request, socket, nolock /* = false */, compress /* = false */) => { | ||
if (typeof nolock === 'undefined') { | ||
nolock = false; | ||
} | ||
if (typeof compress === 'undefined') { | ||
compress = false; | ||
} | ||
if (!nolock && Params.locks[socket.address().port]) { | ||
Params.send_request_backlog_callbacks.push(function() { | ||
Utils.debugLog('Sending request via callback'); | ||
Utils.sendRequest(request, socket, false, compress); | ||
}); | ||
return; | ||
} | ||
let finalRequest = JSON.stringify(request); | ||
if (compress) { | ||
finalRequest = new Buffer(zlib.deflateSync(finalRequest)).toString('base64'); | ||
} | ||
const encryptedRequest = Utils.encrypt(finalRequest); | ||
Utils.vLog(9, 'Payload (Plain): ' + encryptedRequest); | ||
Utils.vLog(8, 'Locking ' + socket.address().port); | ||
Params.locks[socket.address().port] = true; | ||
try { | ||
Utils.debugLog('Sending...'); | ||
socket.write(encryptedRequest, 'utf-8', function() { | ||
Params.locks[socket.address().port] = false; | ||
Utils.vLog(8, 'Unlocking ' + socket.address().port); | ||
setTimeout(function() { | ||
if (Params.send_request_backlog_callbacks.length > 0) { | ||
const cb = Params.send_request_backlog_callbacks.splice(0, 1)[0]; | ||
cb(); | ||
} | ||
}, 10); | ||
}); | ||
} catch (e) { | ||
Utils.vLog(8, 'Unlocking ' + socket.address().port + ' [because of exception]'); | ||
Params.locks[socket.address().port] = false; | ||
Utils.debugLog('Error while writing to socket...'); | ||
Utils.debugLog(e); | ||
} | ||
}, | ||
// Decrypt response from the server using symmetric key | ||
decrypt: (data, connection) => { | ||
if (connection === null) { | ||
return null; | ||
} | ||
try { | ||
const resp = data.split(':'); | ||
const iv = resp[0]; | ||
const clientId = resp.length === 3 ? resp[1] : ''; | ||
const actualData = resp.length === 3 ? resp[2] : resp[1]; | ||
const binaryData = new Buffer(actualData, 'base64'); | ||
Utils.vLog(8, 'Reading ' + data.trim() + ' >>> parts: ' + iv + ' >>> ' + actualData.trim() + ' >>> ' + connection.key); | ||
let decipher = crypto.createDecipheriv(Utils.getCipherAlgorithm(connection.key), new Buffer(connection.key, 'hex'), new Buffer(iv, 'hex')); | ||
decipher.setAutoPadding(false); | ||
getCipherAlgorithm: (keyHex) => { | ||
return `aes-${(keyHex.length / 2) * 8}-cbc`; | ||
}, | ||
let plain = decipher.update(binaryData, 'base64', 'utf-8'); | ||
plain += decipher.final('utf-8'); | ||
// Remove non-ascii characters from decrypted text ! Argggh! | ||
plain = plain.replace(/[^A-Za-z 0-9 \.,\?""!@#\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*/g, ''); | ||
return plain; | ||
} catch (err) { | ||
Utils.vLog(9, 'decrypt-error: ', err); | ||
} | ||
encrypt: (request) => { | ||
let encryptedRequest; | ||
try { | ||
let iv = new Buffer(crypto.randomBytes(16), 'hex'); | ||
let cipher = crypto.createCipheriv(Utils.getCipherAlgorithm(Params.connection.key), new Buffer(Params.connection.key, 'hex'), iv); | ||
return iv.toString('hex') + ':' + Params.connection.client_id + ':' + cipher.update(request, 'utf-8', 'base64') + cipher.final('base64') + PACKET_DELIMITER; | ||
} catch (err) { | ||
Utils.debugLog(err); | ||
} | ||
return ''; | ||
}, | ||
return null; | ||
}, | ||
// Decrypt response from the server using symmetric key | ||
decrypt: (data) => { | ||
if (Params.connection === null) { | ||
return null; | ||
} | ||
try { | ||
const resp = data.split(':'); | ||
const iv = resp[0]; | ||
const clientId = resp.length === 3 ? resp[1] : ''; | ||
const actualData = resp.length === 3 ? resp[2] : resp[1]; | ||
const binaryData = new Buffer(actualData, 'base64'); | ||
Utils.vLog(8, 'Reading ' + data.trim() + ' >>> parts: ' + iv + ' >>> ' + actualData.trim() + ' >>> ' + Params.connection.key); | ||
let decipher = crypto.createDecipheriv(Utils.getCipherAlgorithm(Params.connection.key), new Buffer(Params.connection.key, 'hex'), new Buffer(iv, 'hex')); | ||
decipher.setAutoPadding(false); | ||
extractPublicKey: privateKey => new NodeRSA(privateKey.key).exportKey('public'), | ||
let plain = decipher.update(binaryData, 'base64', 'utf-8'); | ||
plain += decipher.final('utf-8'); | ||
// Remove non-ascii characters from decrypted text ! Argggh! | ||
plain = plain.replace(/[^A-Za-z 0-9 \.,\?""!@#\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*/g, ''); | ||
return plain; | ||
} catch (err) { | ||
Utils.vLog(9, 'decrypt-error: '); | ||
Utils.vLog(9, err); | ||
} | ||
generateKeypair: (keySize) => { | ||
const key = new NodeRSA({ | ||
b: keySize | ||
}); | ||
key.setOptions({ | ||
encryptionScheme: 'pkcs1' | ||
}); | ||
Utils.debugLog('Key generated'); | ||
return { | ||
privatePEM: key.exportKey('private'), | ||
publicPEM: key.exportKey('public'), | ||
}; | ||
}, | ||
return null; | ||
}, | ||
// Decrypt response from the server using asymetric key | ||
decryptRSA: (response, privateKey) => { | ||
try { | ||
return crypto.privateDecrypt(privateKey, new Buffer(response.toString(), 'base64')).toString('utf-8'); | ||
} catch (err) { | ||
Utils.log(err); | ||
} | ||
return null; | ||
}, | ||
extractPublicKey: (privateKey) => { | ||
const key = new NodeRSA(privateKey.key); | ||
return key.exportKey('public'); | ||
}, | ||
// Encrypts string using key | ||
encryptRSA: (str, publicKey) => { | ||
try { | ||
return crypto.publicEncrypt(publicKey, new Buffer(str, 'utf-8')).toString('base64'); | ||
} catch (err) { | ||
Utils.log(err); | ||
} | ||
return null; | ||
}, | ||
generateKeypair: (keySize) => { | ||
const key = new NodeRSA({b: keySize}); | ||
key.setOptions({encryptionScheme: 'pkcs1'}); | ||
Utils.debugLog('Key generated'); | ||
return { | ||
privatePEM: key.exportKey('private'), | ||
publicPEM: key.exportKey('public'), | ||
}; | ||
}, | ||
// Get current date in microseconds | ||
now: () => parseInt((new Date()).getTime() / 1000, 10), | ||
// Decrypt response from the server using asymetric key | ||
decryptRSA: (response, privateKey) => { | ||
try { | ||
return crypto.privateDecrypt(privateKey, new Buffer(response.toString(), 'base64')).toString('utf-8'); | ||
} catch (err) { | ||
Utils.log(err); | ||
} | ||
return null; | ||
}, | ||
getTimestamp: () => Utils.now(), | ||
// Encrypts string using key | ||
encryptRSA: (str, publicKey) => { | ||
try { | ||
return crypto.publicEncrypt(publicKey, new Buffer(str, 'utf-8')).toString('base64'); | ||
} catch (err) { | ||
Utils.log(err); | ||
} | ||
return null; | ||
} | ||
// Returns UTC time | ||
getCurrentTimeUTC: () => { | ||
const newDate = new Date(); | ||
return newDate.getTime() + newDate.getTimezoneOffset() * 60000; | ||
}, | ||
}; | ||
// Handle response from the server on connection requests | ||
Params.connection_socket.on('data', (data) => { | ||
let decryptedData = Utils.decrypt(data.toString()); | ||
const ResidueClient = function() { | ||
this.params = { | ||
// user provided options for seamless connection | ||
// app, host, connect_port | ||
options: {}, | ||
// connecting object containing: | ||
// client_id, age, date_created, key, logging_port | ||
connection: null, | ||
// rsaKey is keypair object | ||
rsaKey: null, | ||
// serverRsaKey is keypair object | ||
serverRsaKey: null, | ||
// whether connected to the server or not | ||
connected: false, | ||
// Underlying sockets | ||
connectionSocket: new net.Socket(), | ||
loggingSocket: new net.Socket(), | ||
// Status for sockets | ||
isLoggingSocketConnected: false, | ||
// callbacks on specific occasions | ||
sendRequestBacklogCallbacks: [], | ||
loggingSocketCallbacks: [], | ||
// locks for mutex | ||
locks: {}, | ||
}; | ||
this.params.locks[this.params.connectionSocket.address().port] = false; | ||
this.params.locks[this.params.loggingSocket.address().port] = false; | ||
// Send request to the server | ||
// This function decides whether to back-log the request or dispatch it to | ||
// the server | ||
this._sendRequest = (request, socket, nolock /* = false */ , compress /* = false */ ) => { | ||
if (typeof nolock === 'undefined') { | ||
nolock = false; | ||
} | ||
if (typeof compress === 'undefined') { | ||
compress = false; | ||
} | ||
if (!nolock && this.params.locks[socket.address().port]) { | ||
this.params.sendRequestBacklogCallbacks.push(() => { | ||
Utils.debugLog('Sending request via callback'); | ||
this.sendRequest(request, socket, false, compress); | ||
}); | ||
return; | ||
} | ||
let finalRequest = JSON.stringify(request); | ||
if (compress) { | ||
finalRequest = new Buffer(zlib.deflateSync(finalRequest)).toString('base64'); | ||
} | ||
const encryptedRequest = Utils.encrypt(finalRequest, this.params.connection); | ||
Utils.vLog(9, 'Payload (Plain): ', encryptedRequest); | ||
Utils.vLog(8, 'Locking ' + socket.address().port); | ||
this.params.locks[socket.address().port] = true; | ||
try { | ||
Utils.debugLog('Sending...'); | ||
const self = this; | ||
socket.write(encryptedRequest, 'utf-8', () => { | ||
self.params.locks[socket.address().port] = false; | ||
Utils.vLog(8, 'Unlocking ' + socket.address().port); | ||
setTimeout(() => { | ||
if (self.params.sendRequestBacklogCallbacks.length > 0) { | ||
const cb = this.params.sendRequestBacklogCallbacks.splice(0, 1)[0]; | ||
cb(); | ||
} | ||
}, 10); | ||
}); | ||
} catch (e) { | ||
Utils.vLog(8, 'Unlocking ' + socket.address().port + ' [because of exception]', e); | ||
this.params.locks[socket.address().port] = false; | ||
Utils.debugLog('Error while writing to socket...'); | ||
Utils.debugLog(e); | ||
} | ||
}; | ||
// Handle response from the server on connection requests | ||
this.params.connectionSocket.on('data', (data) => { | ||
let decryptedData = Utils.decrypt(data.toString(), this.params.connection); | ||
if (decryptedData === null) { | ||
decryptedData = Utils.decryptRSA(data, Params.rsa_key.privateKey); | ||
decryptedData = Utils.decryptRSA(data, this.params.rsaKey.privateKey); | ||
} | ||
if (decryptedData === null) { | ||
Utils.log('Unable to read response: ' + data); | ||
return; | ||
Utils.log('Unable to read response: ' + data); | ||
return; | ||
} | ||
const dataJson = JSON.parse(decryptedData.toString()); | ||
Utils.vLog(8, 'Connection: '); | ||
Utils.vLog(8, dataJson); | ||
Utils.vLog(8, 'Connection: ', dataJson); | ||
if (dataJson.status === 0 && typeof dataJson.key !== 'undefined' && dataJson.ack === 0) { | ||
Utils.debugLog('Connecting to Residue Server...(ack)'); | ||
// connection re-estabilished | ||
Params.disconnected_by_remote = false; | ||
Params.connection = dataJson; | ||
// Need to acknowledge | ||
const request = { | ||
_t: Utils.getTimestamp(), | ||
type: ConnectType.Acknowledgement, | ||
client_id: Params.connection.client_id | ||
}; | ||
Utils.sendRequest(request, Params.connection_socket, true); | ||
Utils.debugLog('Connecting to Residue Server...(ack)'); | ||
// connection re-estabilished | ||
this.params.disconnected_by_remote = false; | ||
this.params.connection = dataJson; | ||
// Need to acknowledge | ||
const request = { | ||
_t: Utils.getTimestamp(), | ||
type: ConnectType.ACK, | ||
client_id: this.params.connection.client_id | ||
}; | ||
this._sendRequest(request, this.params.connectionSocket, true); | ||
} else if (dataJson.status === 0 && typeof dataJson.key !== 'undefined' && dataJson.ack === 1) { | ||
Utils.debugLog('Estabilishing full connection...'); | ||
Params.connection = dataJson; | ||
Params.connected = true; | ||
Utils.vLog(8, `Connection socket: ${Params.connection_socket.address().port}`); | ||
if (!Params.logging_socket_connected) { | ||
Params.logging_socket.connect(Params.connection.logging_port, Params.options.host, function() { | ||
Utils.log(`Connected to Residue (v${Params.connection.server_info.version})!`); | ||
Params.logging_socket_connected = true; | ||
Utils.vLog(8, `Logging socket: ${Params.logging_socket.address().port}`); | ||
Params.connecting = false; | ||
const callbackCounts = Params.logging_socket_callbacks.length; | ||
for (let idx = 0; idx < callbackCounts; ++idx) { | ||
const cb = Params.logging_socket_callbacks.splice(0, 1)[0]; | ||
cb(); | ||
} | ||
}); | ||
} else { | ||
Params.connecting = false; | ||
const callbackCounts = Params.logging_socket_callbacks.length; | ||
for (let idx = 0; idx < callbackCounts; ++idx) { | ||
const cb = Params.logging_socket_callbacks.splice(0, 1)[0]; | ||
cb(); | ||
} | ||
Utils.debugLog('Estabilishing full connection...'); | ||
this.params.connection = dataJson; | ||
this.params.connected = true; | ||
Utils.vLog(8, `Connection socket: ${this.params.connectionSocket.address().port}`); | ||
if (!this.params.isLoggingSocketConnected) { | ||
this.params.loggingSocket.connect(this.params.connection.logging_port, this.params.options.host, () => { | ||
Utils.log(`Connected to Residue (v${this.params.connection.server_info.version})!`); | ||
this.params.isLoggingSocketConnected = true; | ||
Utils.vLog(8, `Logging socket: ${this.params.loggingSocket.address().port}`); | ||
this.params.connecting = false; | ||
const callbackCounts = this.params.loggingSocketCallbacks.length; | ||
for (let idx = 0; idx < callbackCounts; ++idx) { | ||
const cb = this.params.loggingSocketCallbacks.splice(0, 1)[0]; | ||
cb(); | ||
} | ||
}); | ||
} else { | ||
this.params.connecting = false; | ||
const callbackCounts = this.params.loggingSocketCallbacks.length; | ||
for (let idx = 0; idx < callbackCounts; ++idx) { | ||
// trigger all the pending callbacks from backlog | ||
this.params.loggingSocketCallbacks.splice(0, 1)[0](); | ||
} | ||
} | ||
} else { | ||
Utils.log('Error while connecting to server: '); | ||
Utils.log(dataJson); | ||
Params.connecting = false; | ||
Utils.log('Error while connecting to server: '); | ||
Utils.log(dataJson); | ||
this.params.connecting = false; | ||
} | ||
}); | ||
}); | ||
// Handle when connection is destroyed | ||
Params.connection_socket.on('close', () => { | ||
// Handle when connection is destroyed | ||
this.params.connectionSocket.on('close', () => { | ||
Utils.log('Remote connection closed!'); | ||
if (Params.connected) { | ||
Params.disconnected_by_remote = true; | ||
if (this.params.connected) { | ||
this.params.disconnected_by_remote = true; | ||
} | ||
disconnect(); | ||
}); | ||
this.disconnect(); | ||
}); | ||
Params.connection_socket.on('error', (error) => { | ||
this.params.connectionSocket.on('error', (error) => { | ||
Utils.log('Error occurred while connecting to residue server'); | ||
Utils.log(error); | ||
}); | ||
}); | ||
// Handle destruction of connection to logging server | ||
this.params.loggingSocket.on('close', () => { | ||
this.params.isLoggingSocketConnected = false; | ||
}); | ||
// Handle destruction of connection to logging server | ||
Params.logging_socket.on('close', () => { | ||
Params.logging_socket_connected = false; | ||
}); | ||
// Notice we do not have any handler for loggingSocket response | ||
// this is because that is async connection | ||
this.params.loggingSocket.on('data', () => {}); | ||
// Notice we do not have any handler for logging_socket response | ||
// this is because that is async connection | ||
Params.logging_socket.on('data', (data) => { | ||
}); | ||
const shouldTouch = () => { | ||
if (!Params.connected || Params.connecting) { | ||
// Can't touch | ||
return false; | ||
this._shouldTouch = () => { | ||
if (!this.params.connected || this.params.connecting) { | ||
// Can't touch | ||
return false; | ||
} | ||
if (Params.connection.age === 0) { | ||
// Always alive! | ||
return false; | ||
if (this.params.connection.age === 0) { | ||
// Always alive! | ||
return false; | ||
} | ||
return Params.connection.age - (Utils.now() - Params.connection.date_created) < TOUCH_THRESHOLD; | ||
} | ||
return this.params.connection.age - (Utils.now() - this.params.connection.date_created) < TOUCH_THRESHOLD; | ||
}; | ||
const touch = () => { | ||
if (Params.connected) { | ||
if (Params.connecting) { | ||
Utils.debugLog('Still touching...'); | ||
return; | ||
} | ||
if (isClientValid()) { | ||
Utils.debugLog('Touching...'); | ||
const request = { | ||
_t: Utils.getTimestamp(), | ||
type: ConnectType.Touch, | ||
client_id: Params.connection.client_id | ||
}; | ||
Utils.sendRequest(request, Params.connection_socket); | ||
Params.connecting = true; | ||
} else { | ||
Utils.log('Could not touch, client already dead ' + (Params.connection.date_created + Params.connection.age) + ' < ' + Utils.now()); | ||
} | ||
this._touch = () => { | ||
if (this.params.connected) { | ||
if (this.params.connecting) { | ||
Utils.debugLog('Still touching...'); | ||
return; | ||
} | ||
if (this._isClientValid()) { | ||
Utils.debugLog('Touching...'); | ||
const request = { | ||
_t: Utils.getTimestamp(), | ||
type: ConnectType.TOUCH, | ||
client_id: this.params.connection.client_id | ||
}; | ||
this._sendRequest(request, this.params.connectionSocket); | ||
this.params.connecting = true; | ||
} else { | ||
Utils.log('Could not touch, client already dead ' + (this.params.connection.date_created + this.params.connection.age) + ' < ' + Utils.now()); | ||
} | ||
} | ||
} | ||
}; | ||
const isClientValid = () => { | ||
if (!Params.connected) { | ||
return false; | ||
this._isClientValid = () => { | ||
if (!this.params.connected) { | ||
return false; | ||
} | ||
if (Params.connection.age == 0) { | ||
return true; | ||
if (this.params.connection.age == 0) { | ||
return true; | ||
} | ||
return Params.connection.date_created + Params.connection.age >= Utils.now(); | ||
} | ||
return this.params.connection.date_created + this.params.connection.age >= Utils.now(); | ||
}; | ||
// Returns UTC time | ||
const getCurrentTimeUTC = () => { | ||
const newDate = new Date(); | ||
return newDate.getTime() + newDate.getTimezoneOffset() * 60000; | ||
} | ||
// Send log request to the server. No response is expected | ||
const sendLogRequest = (level, loggerId, sourceFile, sourceLine, sourceFunc, verboseLevel, logDatetime, format, ...args) => { | ||
// Send log request to the server. No response is expected | ||
this._sendLogRequest = (level, loggerId, sourceFile, sourceLine, sourceFunc, verboseLevel, logDatetime, format, ...args) => { | ||
let datetime = logDatetime; | ||
if (typeof datetime === 'undefined') { | ||
datetime = Params.options.utc_time ? getCurrentTimeUTC() : new Date().getTime(); | ||
if (Params.options.time_offset) { | ||
datetime += (1000 * Params.options.time_offset); // offset is in seconds | ||
} | ||
datetime = this.params.options.utc_time ? Utils.getCurrentTimeUTC() : new Date().getTime(); | ||
if (this.params.options.time_offset) { | ||
datetime += (1000 * this.params.options.time_offset); // offset is in seconds | ||
} | ||
} | ||
if (Params.connecting) { | ||
Utils.debugLog('Still connecting...'); | ||
Params.logging_socket_callbacks.push(() => { | ||
sendLogRequest(level, loggerId, sourceFile, sourceLine, sourceFunc, verboseLevel, datetime, format, ...args); | ||
}); | ||
return; | ||
if (this.params.connecting) { | ||
Utils.debugLog('Still connecting...'); | ||
this.params.loggingSocketCallbacks.push(() => { | ||
this._sendLogRequest(level, loggerId, sourceFile, sourceLine, sourceFunc, verboseLevel, datetime, format, ...args); | ||
}); | ||
return; | ||
} | ||
if (!Params.connected) { | ||
Utils.log('Not connected to the server yet'); | ||
if (Params.disconnected_by_remote) { | ||
Utils.debugLog('Queueing...'); | ||
Params.logging_socket_callbacks.push(() => { | ||
sendLogRequest(level, loggerId, sourceFile, sourceLine, sourceFunc, verboseLevel, datetime, format, ...args); | ||
}); | ||
const totalListener = Params.connection_socket.listenerCount('connect'); | ||
if (totalListener >= 1) { | ||
Utils.log('Checking for connection...' + totalListener); | ||
Params.connection_socket.emit('connect'); | ||
} else { | ||
Utils.log('Retrying to connect...'); | ||
connect(Params.options); | ||
} | ||
if (!this.params.connected) { | ||
Utils.log('Not connected to the server yet'); | ||
if (this.params.disconnected_by_remote) { | ||
Utils.debugLog('Queueing...'); | ||
this.params.loggingSocketCallbacks.push(() => { | ||
this._sendLogRequest(level, loggerId, sourceFile, sourceLine, sourceFunc, verboseLevel, datetime, format, ...args); | ||
}); | ||
const totalListener = this.params.connectionSocket.listenerCount('connect'); | ||
if (totalListener >= 1) { | ||
Utils.log('Checking for connection...' + totalListener); | ||
this.params.connectionSocket.emit('connect'); | ||
} else { | ||
Utils.log('Retrying to connect...'); | ||
connect(this.params.options); | ||
} | ||
return; | ||
} | ||
return; | ||
} | ||
@@ -430,216 +468,184 @@ | ||
if (!isClientValid()) { | ||
Utils.debugLog('Resetting connection...'); | ||
Params.logging_socket_callbacks.push(() => { | ||
Utils.debugLog('Sending log from log callback... [' + loggerId + ']'); | ||
sendLogRequest(level, loggerId, sourceFile, sourceLine, sourceFunc, verboseLevel, datetime, format, ...args); | ||
}); | ||
Utils.debugLog('Destroying connection socket'); | ||
Params.connection_socket.destroy(); | ||
Params.logging_socket.destroy(); | ||
disconnect(); | ||
connect(Params.options); | ||
return; | ||
if (!this._isClientValid()) { | ||
Utils.debugLog('Resetting connection...'); | ||
this.params.loggingSocketCallbacks.push(() => { | ||
Utils.debugLog('Sending log from log callback... [' + loggerId + ']'); | ||
sendLogRequest(level, loggerId, sourceFile, sourceLine, sourceFunc, verboseLevel, datetime, format, ...args); | ||
}); | ||
Utils.debugLog('Destroying connection socket'); | ||
this.params.connectionSocket.destroy(); | ||
this.params.loggingSocket.destroy(); | ||
disconnect(); | ||
connect(this.params.options); | ||
return; | ||
} | ||
if (shouldTouch()) { | ||
Utils.debugLog('Touching first...'); | ||
Params.logging_socket_callbacks.push(() => { | ||
Utils.debugLog('Sending log from touch callback... [' + loggerId + ']'); | ||
sendLogRequest(level, loggerId, sourceFile, sourceLine, sourceFunc, verboseLevel, datetime, format, ...args); | ||
}); | ||
touch(); | ||
return; | ||
if (this._shouldTouch()) { | ||
Utils.debugLog('Touching first...'); | ||
this.params.loggingSocketCallbacks.push(() => { | ||
Utils.debugLog('Sending log from touch callback... [' + loggerId + ']'); | ||
this._sendLogRequest(level, loggerId, sourceFile, sourceLine, sourceFunc, verboseLevel, datetime, format, ...args); | ||
}); | ||
this._touch(); | ||
return; | ||
} | ||
Utils.debugLog('Sending log request [' + loggerId + ']...'); | ||
Utils.debugLog('Sending log request [' + loggerId + ']...'); | ||
const fullMessage = CommonUtils.translateArgs(true, ...args); | ||
const request = { | ||
_t: Utils.getTimestamp(), | ||
datetime: datetime, | ||
logger: loggerId, | ||
msg: util.format(format, ...fullMessage), | ||
file: sourceFile, | ||
line: sourceLine, | ||
func: sourceFunc, | ||
app: Params.options.application_id, | ||
level: level, | ||
_t: Utils.getTimestamp(), | ||
datetime: datetime, | ||
logger: loggerId, | ||
msg: util.format(format, ...fullMessage), | ||
file: sourceFile, | ||
line: sourceLine, | ||
func: sourceFunc, | ||
app: this.params.options.application_id, | ||
level: level, | ||
}; | ||
if (typeof verboseLevel !== 'undefined') { | ||
request.vlevel = verboseLevel; | ||
request.vlevel = verboseLevel; | ||
} | ||
Utils.sendRequest(request, Params.logging_socket, false, Utils.hasFlag(Flag.COMPRESSION)); | ||
} | ||
this._sendRequest(request, this.params.loggingSocket, false, Utils.hasFlag(Flag.COMPRESSION, this.params.connection)); | ||
}; | ||
const isNormalInteger = (str) => { | ||
var n = Math.floor(Number(str)); | ||
return String(n) === str && n >= 0; | ||
} | ||
// public exported functions | ||
const loadConfiguration = (jsonOrFilename) => { | ||
const conf = CommonUtils.confJson(jsonOrFilename); | ||
if (conf === false) { | ||
console.error('Please select JSON or JSON filename that contains configurations'); | ||
return false; | ||
} | ||
Params.options = JSON.parse(conf); | ||
Utils.log('Configuration loaded'); | ||
return true; | ||
} | ||
this.version = () => require('./../package.json').version; | ||
// Securily connect to residue server using defined options | ||
const connect = (options) => { | ||
if (Params.connected && Params.connection !== null) { | ||
Utils.log('Already connected to the server with ID [' + Params.connection.client_id + ']') | ||
return; | ||
this.type = () => 'js'; | ||
this.isConnected = () => this.params.connected; | ||
// Securily connect to residue server using defined options | ||
this.connect = (options) => { | ||
if (this.params.connected && this.params.connection !== null) { | ||
Utils.log('Already connected to the server with ID [' + this.params.connection.client_id + ']') | ||
return; | ||
} | ||
Params.connecting = true; | ||
this.params.connecting = true; | ||
try { | ||
Params.options = typeof options === 'undefined' ? Params.options : options; | ||
// Normalize | ||
if (typeof Params.options.url !== 'undefined') { | ||
const parts = Params.options.url.split(':'); | ||
if (parts.length < 2 || !isNormalInteger(parts[1])) { | ||
throw 'Invalid URL format for residue'; | ||
this.params.options = typeof options === 'undefined' ? this.params.options : options; | ||
// Normalize | ||
if (typeof this.params.options.url !== 'undefined') { | ||
const parts = this.params.options.url.split(':'); | ||
if (parts.length < 2 || !isNormalInteger(parts[1])) { | ||
throw 'Invalid URL format for residue'; | ||
} | ||
this.params.options.host = parts[0]; | ||
this.params.options.connect_port = parseInt(parts[1]); | ||
} | ||
if (typeof this.params.options.client_id === 'undefined' && | ||
typeof this.params.options.client_private_key === 'undefined') { | ||
// Generate new key for key-exchange | ||
const keySize = this.params.options.rsaKey_size || 2048; | ||
Utils.log('Generating ' + keySize + '-bit key...'); | ||
const generatedKey = Utils.generateKeypair(keySize); | ||
this.params.rsaKey = { | ||
isGenerated: true, | ||
privateKey: { | ||
key: generatedKey.privatePEM, | ||
padding: crypto.constants.RSA_PKCS1_PADDING, | ||
}, | ||
publicKey: { | ||
key: generatedKey.publicPEM, | ||
padding: crypto.constants.RSA_PKCS1_PADDING, | ||
} | ||
Params.options.host = parts[0]; | ||
Params.options.connect_port = parseInt(parts[1]); | ||
}; | ||
Utils.debugLog('Key generated'); | ||
} else { | ||
this.params.rsaKey = { | ||
generated: false, | ||
privateKey: { | ||
key: fs.readFileSync(path.resolve(this.params.options.client_private_key)).toString(), | ||
passphrase: this.params.options.client_key_secret ? | ||
new Buffer(this.params.options.client_key_secret, 'hex').toString('utf-8') : null, | ||
padding: crypto.constants.RSA_PKCS1_PADDING, | ||
}, | ||
publicKey: { | ||
padding: crypto.constants.RSA_PKCS1_PADDING, | ||
} | ||
}; | ||
if (typeof this.params.options.client_public_key !== 'undefined') { | ||
this.params.rsaKey.publicKey.key = fs.readFileSync(path.resolve(this.params.options.client_public_key)).toString(); | ||
} else { | ||
if (this.params.rsaKey.privateKey.passphrase === null) { | ||
this.params.rsaKey.publicKey.key = Utils.extractPublicKey(this.params.rsaKey.privateKey); | ||
} else { | ||
throw 'ERROR: You specified client_key_secret and did not provide client_public_key. We cannot extract public-key for encrypted private keys. Please provide public key manually'; | ||
} | ||
} | ||
if (typeof Params.options.client_id === 'undefined' && | ||
typeof Params.options.client_private_key === 'undefined') { | ||
// Generate new key for key-exchange | ||
const keySize = Params.options.rsa_key_size || 2048; | ||
Utils.log('Generating ' + keySize + '-bit key...'); | ||
const generatedKey = Utils.generateKeypair(keySize); | ||
Params.rsa_key = { | ||
isGenerated: true, | ||
privateKey: { | ||
key: generatedKey.privatePEM, | ||
padding: crypto.constants.RSA_PKCS1_PADDING, | ||
}, | ||
publicKey: { | ||
key: generatedKey.publicPEM, | ||
padding: crypto.constants.RSA_PKCS1_PADDING, | ||
} | ||
}; | ||
Utils.debugLog('Key generated'); | ||
Utils.vLog(8, 'Known client...'); | ||
} | ||
if (typeof this.params.options.server_public_key !== 'undefined') { | ||
this.params.serverRsaKey = { | ||
publicKey: { | ||
key: fs.readFileSync(path.resolve(this.params.options.server_public_key)).toString(), | ||
padding: crypto.constants.RSA_PKCS1_PADDING, | ||
}, | ||
}; | ||
} | ||
Utils.log('Intializing connection...'); | ||
this.params.connectionSocket.connect(this.params.options.connect_port, this.params.options.host, () => { | ||
let request = { | ||
_t: Utils.getTimestamp(), | ||
type: ConnectType.CONN, | ||
}; | ||
if (this.params.rsaKey.isGenerated) { | ||
request.rsa_public_key = Utils.base64Encode(this.params.rsaKey.publicKey.key); | ||
} else { | ||
Params.rsa_key = { | ||
generated: false, | ||
privateKey: { | ||
key: fs.readFileSync(path.resolve(Params.options.client_private_key)).toString(), | ||
passphrase: Params.options.client_key_secret | ||
? new Buffer(Params.options.client_key_secret, 'hex').toString('utf-8') : null, | ||
padding: crypto.constants.RSA_PKCS1_PADDING, | ||
}, | ||
publicKey: { | ||
padding: crypto.constants.RSA_PKCS1_PADDING, | ||
} | ||
}; | ||
if (typeof Params.options.client_public_key !== 'undefined') { | ||
Params.rsa_key.publicKey.key = fs.readFileSync(path.resolve(Params.options.client_public_key)).toString(); | ||
} else { | ||
if (Params.rsa_key.privateKey.passphrase === null) { | ||
Params.rsa_key.publicKey.key = Utils.extractPublicKey(Params.rsa_key.privateKey); | ||
} else { | ||
throw 'ERROR: You specified client_key_secret and did not provide client_public_key. We cannot extract public-key for encrypted private keys. Please provide public key manually'; | ||
} | ||
} | ||
Utils.vLog(8, 'Known client...'); | ||
request.client_id = this.params.options.client_id; | ||
} | ||
if (typeof Params.options.server_public_key !== 'undefined') { | ||
Params.server_rsa_key = { | ||
publicKey: { | ||
key: fs.readFileSync(path.resolve(Params.options.server_public_key)).toString(), | ||
padding: crypto.constants.RSA_PKCS1_PADDING, | ||
}, | ||
}; | ||
let r = JSON.stringify(request); | ||
if (this.params.serverRsaKey !== null) { | ||
r = Utils.encryptRSA(r, this.params.serverRsaKey.publicKey); | ||
} | ||
Utils.log('Intializing connection...'); | ||
Params.connection_socket.connect(Params.options.connect_port, Params.options.host, () => { | ||
let request = { | ||
_t: Utils.getTimestamp(), | ||
type: ConnectType.Connect, | ||
}; | ||
if (Params.rsa_key.isGenerated) { | ||
request.rsa_public_key = Utils.base64Encode(Params.rsa_key.publicKey.key); | ||
} else { | ||
request.client_id = Params.options.client_id; | ||
} | ||
let r = JSON.stringify(request); | ||
if (Params.server_rsa_key !== null) { | ||
r = Utils.encryptRSA(r, Params.server_rsa_key.publicKey); | ||
} | ||
const fullReq = r + PACKET_DELIMITER; | ||
Params.connection_socket.write(fullReq); | ||
}); | ||
const fullReq = r + PACKET_DELIMITER; | ||
this.params.connectionSocket.write(fullReq); | ||
}); | ||
} catch (e) { | ||
Utils.log('Error occurred while connecting to residue server'); | ||
Utils.log(e); | ||
Params.connecting = false; | ||
Utils.log('Error occurred while connecting to residue server'); | ||
Utils.log(e); | ||
this.params.connecting = false; | ||
} | ||
} | ||
}; | ||
// Disconnect from the server safely. | ||
const disconnect = () => { | ||
// Disconnect from the server safely. | ||
this.disconnect = () => { | ||
Utils.traceLog('disconnect()'); | ||
Params.connected = false; | ||
Params.connecting = false; | ||
Params.connection = null; | ||
Params.logging_socket_connected = false; | ||
if (Params.connected) { | ||
try { | ||
if (Params.connection_socket.destroyed) { | ||
Utils.log('Disconnecting gracefully...'); | ||
Params.logging_socket.end(); | ||
} else { | ||
Utils.log('Disconnecting...'); | ||
// Following will call 'close' -> disconnect -> gracefully close | ||
Params.connection_socket.end(); | ||
} | ||
} catch (err) { | ||
this.params.connected = false; | ||
this.params.connecting = false; | ||
this.params.connection = null; | ||
this.params.isLoggingSocketConnected = false; | ||
if (this.params.connected) { | ||
try { | ||
if (this.params.connectionSocket.destroyed) { | ||
Utils.log('Disconnecting gracefully...'); | ||
this.params.loggingSocket.end(); | ||
} else { | ||
Utils.log('Disconnecting...'); | ||
// Following will call 'close' -> disconnect -> gracefully close | ||
this.params.connectionSocket.end(); | ||
} | ||
} catch (err) { | ||
} | ||
} | ||
} | ||
}; | ||
// Logger interface for user to send log messages to server | ||
const Logger = function(id) { | ||
this.id = id; | ||
this.loadConfiguration = (jsonOrFilename) => { | ||
const conf = CommonUtils.confJson(jsonOrFilename); | ||
if (conf === false) { | ||
console.error('Please select JSON or JSON filename that contains configurations'); | ||
return false; | ||
} | ||
this.params.options = JSON.parse(conf); | ||
Utils.log('Configuration loaded'); | ||
return true; | ||
}; | ||
this.info = (format, ...args) => this._write_log(CommonUtils.LoggingLevels.Info, 0, format, ...args); | ||
this.error = (format, ...args) => this._write_log(CommonUtils.LoggingLevels.Error, 0, format, ...args); | ||
this.debug = (format, ...args) => this._write_log(CommonUtils.LoggingLevels.Debug, 0, format, ...args); | ||
this.warn = (format, ...args) => this._write_log(CommonUtils.LoggingLevels.Warning, 0, format, ...args); | ||
this.trace = (format, ...args) => this._write_log(CommonUtils.LoggingLevels.Trace, 0, format, ...args); | ||
this.fatal = (format, ...args) => this._write_log(CommonUtils.LoggingLevels.Fatal, 0, format, ...args); | ||
this.verbose = (vlevel, format, ...args) => this._write_log(CommonUtils.LoggingLevels.Verbose, vlevel, format, ...args); | ||
this.getLogger = id => new Logger(id, this); | ||
}; | ||
//private members | ||
this._write_log = (level, vlevel, format, ...args) => sendLogRequest(level, | ||
this.id, | ||
this.log_sources.getSourceFile(), | ||
this.log_sources.getSourceLine(), | ||
this.log_sources.getSourceFunc(), | ||
vlevel, | ||
undefined, | ||
format, | ||
...args); | ||
this.log_sources = { | ||
base_idx: 6, | ||
getSourceFile: () => CommonUtils.getSourceFile(this.log_sources.base_idx), | ||
getSourceLine: () => CommonUtils.getSourceLine(this.log_sources.base_idx), | ||
getSourceFunc: () => CommonUtils.getSourceFunc(this.log_sources.base_idx), | ||
}; | ||
} | ||
exports.version = () => require('./../package.json').version; | ||
exports.type = () => 'js'; | ||
exports.loadConfiguration = loadConfiguration; | ||
exports.connect = connect; | ||
exports.disconnect = disconnect; | ||
exports.isConnected = () => Params.connected; | ||
exports.getLogger = (id) => (new Logger(id)); | ||
module.exports = ResidueClient; |
659
122
34286