const net = require('net');
const { v4: uuidv4 } = require('uuid');
const {
errorListener, dataListener, closeListener, getSocket,
} = require('./helper');
class SimpleTcpProxy {
/**
* saves proxy and target information, set status to offline and init client_con obj
*
* @param {Object} options Settings for the proxy
* @param {Object} options.proxy Proxy server information
* @param {String} options.proxy.host Proxy IP
* @param {Number} options.proxy.port Proxy Port
* @param {Object} options.target Target server information
* @param {String} options.target.host Target IP
* @param {Number} options.target.port Target Port
*/
constructor(options) {
this.proxy = options.proxy; // host and port from proxy server
this.target = options.target; // host and port from target server
this.status = 'offline'; // server status
this.client_con = {}; // obj for storing all connections
}
/**
* start function of the proxy
* create a new TCP Server
* gives every new client a uuid
* bind listener from proxy and target
* run callback after every connection
*
* @param {Function} callback [opt] func will be called with every new con
* @param {Function} error [opt] error handler
*/
start(callback, error) {
this.server = net.createServer((sock) => { // creating tcp proxy server
// setting up a new connection to the target server
const socket = getSocket(this.target.port, this.target.host);
sock.removeAllListeners('data');
sock.on('data', dataListener(socket)); // bind data listener
socket.on('data', dataListener(sock));
sock.on('error', errorListener(error)); // bind error listener
socket.on('error', errorListener(error));
sock.on('close', closeListener()); // bind listener for close
this.status = 'online'; // set online status
this.client_con[uuidv4()] = socket; // store connection
if (callback) callback(sock, socket); // running callback
}).listen(this.proxy.port, this.proxy.host); // start server
}
/**
* shut down the server and run callback
*
* @param {Function} [callback]
*/
close(callback) {
Object.keys(this.client_con).forEach((key) => { // destroying all connections
if (typeof this.client_con[key].destroy === 'function') this.client_con[key].destroy();
this.client_con[key] = undefined;
delete this.client_con[key];
});
this.status = 'offline'; // set server status to offline
this.server.close(callback); // close server and run callback
}
/**
* static one line function to create a proxy (like in the first version)
*
* @param {Object} options Settings for the proxy
* @param {Object} options.proxy Proxy server information
* @param {String} options.proxy.host Proxy IP
* @param {Number} options.proxy.port Proxy Port
* @param {Object} options.target Target server information
* @param {String} options.target.host Target IP
* @param {Number} options.target.port Target Port
* @param {function(module:net.Socket, module:net.Socket)} [callback]
* callback(proxySocket, clientSocket) => {}; runs after every new connection
* @param {function} [errorFunc] error handler
*/
static run(options, callback, errorFunc) {
const proxy = new this(options); // create new proxy
proxy.start(callback, errorFunc); // start proxy
return proxy;
}
}
module.exports = SimpleTcpProxy;