111 lines
2.8 KiB
JavaScript
111 lines
2.8 KiB
JavaScript
const treeKill = require('tree-kill');
|
|
const sanitizer = require('../utils/sanitizer.js');
|
|
const { isWindows } = require('../helpers/platform.js');
|
|
const { spawnAsyncJSONPromise } = require('../helpers/spawn-promise.js');
|
|
|
|
class Session {
|
|
#id;
|
|
#addr;
|
|
#token;
|
|
#hostId;
|
|
#process;
|
|
#targetId;
|
|
#proxyDetails;
|
|
|
|
/**
|
|
* Initialize a session to a controller address
|
|
* using target details.
|
|
* @param {string} addr
|
|
* @param {string} targetId
|
|
* @param {string} token
|
|
* @param {string} hostId
|
|
*/
|
|
constructor(addr, targetId, token, hostId) {
|
|
this.#addr = addr;
|
|
this.#targetId = targetId;
|
|
this.#token = token;
|
|
this.#hostId = hostId;
|
|
}
|
|
|
|
/**
|
|
* Session id
|
|
* @return {string}
|
|
*/
|
|
get id() {
|
|
return this.#id;
|
|
}
|
|
|
|
/**
|
|
* @return {boolean}
|
|
*/
|
|
get isRunning() {
|
|
return this.#process && !this.#process.killed;
|
|
}
|
|
|
|
/**
|
|
* Using cli, initialize a session to a target.
|
|
* Tracks local proxy details if successful.
|
|
*/
|
|
start() {
|
|
const command = this.cliCommand();
|
|
return spawnAsyncJSONPromise(command).then((spawnedSession) => {
|
|
this.#process = spawnedSession.childProcess;
|
|
this.#proxyDetails = spawnedSession.response;
|
|
this.#process = spawnedSession.childProcess;
|
|
this.#id = this.#proxyDetails.session_id;
|
|
return this.#proxyDetails;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Stop proxy process used by session.
|
|
*/
|
|
stop() {
|
|
return new Promise((resolve, reject) => {
|
|
if (this.isRunning) {
|
|
this.#process.on('close', () => resolve());
|
|
this.#process.on('error', (e) => reject(e));
|
|
/**
|
|
* On Windows OS, a spawned process uses cmd.exe to initiate a session.
|
|
* Hence, captured process.pid corresponds to cmd.exe instead of session.
|
|
* To avoid orphaned session processes and due to lack of node support
|
|
* to handle killing processes cleanly in this scenario,
|
|
* kill entire dependent process tree on Windows.
|
|
*/
|
|
isWindows() ? treeKill(this.#process.pid) : this.#process.kill();
|
|
} else {
|
|
// Do nothing when process isn't running
|
|
resolve();
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Generate cli command for session.
|
|
* @returns {[]}
|
|
*/
|
|
cliCommand() {
|
|
const sanitized = {
|
|
target_id: sanitizer.base62EscapeAndValidate(this.#targetId),
|
|
token: sanitizer.base62EscapeAndValidate(this.#token),
|
|
addr: sanitizer.urlValidate(this.#addr),
|
|
};
|
|
|
|
const command = [
|
|
'connect',
|
|
`-target-id=${sanitized.target_id}`,
|
|
`-token=${sanitized.token}`,
|
|
`-addr=${sanitized.addr}`,
|
|
'-format=json',
|
|
];
|
|
|
|
if (this.#hostId) {
|
|
sanitized.host_id = sanitizer.base62EscapeAndValidate(this.#hostId);
|
|
command.push(`-host-id=${sanitized.host_id}`);
|
|
}
|
|
return command;
|
|
}
|
|
}
|
|
|
|
module.exports = Session;
|