add server status

This commit is contained in:
VincentChanX
2017-04-06 18:32:59 +08:00
parent 42cf14642d
commit 0a8481de48
4 changed files with 35 additions and 4 deletions

View File

@@ -2,7 +2,7 @@ const TCPRelay = require('./tcprelay').TCPRelay;
const local = require('commander'); const local = require('commander');
local local
.version('0.1.3') .version('0.1.4')
.option('-m --method [method]', 'encryption method, default: aes-256-cfb') .option('-m --method [method]', 'encryption method, default: aes-256-cfb')
.option('-k --password [password]', 'password') .option('-k --password [password]', 'password')
.option('-s --server-address [address]', 'server address') .option('-s --server-address [address]', 'server address')

View File

@@ -1,6 +1,6 @@
{ {
"name": "shadowsocks-over-websocket", "name": "shadowsocks-over-websocket",
"version": "0.1.3", "version": "0.1.4",
"description": "A fast tunnel proxy that helps you bypass firewalls", "description": "A fast tunnel proxy that helps you bypass firewalls",
"main": "tcprelay.js", "main": "tcprelay.js",
"scripts": { "scripts": {

View File

@@ -2,7 +2,7 @@ const TCPRelay = require('./tcprelay').TCPRelay;
const server = require('commander'); const server = require('commander');
server server
.version('0.1.3') .version('0.1.4')
.option('-m --method [method]', 'encryption method, default: aes-256-cfb') .option('-m --method [method]', 'encryption method, default: aes-256-cfb')
.option('-k --password [password]', 'password') .option('-k --password [password]', 'password')
.option('-s --server-address [address]', 'server address') .option('-s --server-address [address]', 'server address')

View File

@@ -61,7 +61,12 @@ const STAGE = {
5: 'STAGE_STREAM' 5: 'STAGE_STREAM'
}; };
const SERVER_STATUS_INIT = 0;
const SERVER_STATUS_RUNNING = 1;
const SERVER_STATUS_STOPPED = 2;
var globalConnectionId = 1; var globalConnectionId = 1;
var connections = {};
function parseAddressHeader(data, offset) { function parseAddressHeader(data, offset) {
var addressType = data.readUInt8(offset); var addressType = data.readUInt8(offset);
@@ -88,10 +93,10 @@ function parseAddressHeader(data, offset) {
}; };
} }
// client <=> local <=> server <=> target
function TCPRelay(config, isLocal, logLevel) { function TCPRelay(config, isLocal, logLevel) {
this.isLocal = isLocal; this.isLocal = isLocal;
this.server = null; this.server = null;
this.status = SERVER_STATUS_INIT;
this.config = require('./config.json'); this.config = require('./config.json');
if (config) { if (config) {
this.config = Object.assign(this.config, config); this.config = Object.assign(this.config, config);
@@ -112,17 +117,29 @@ TCPRelay.prototype.bootstrap = function() {
TCPRelay.prototype.stop = function() { TCPRelay.prototype.stop = function() {
var self = this; var self = this;
var connId = null;
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
if (self.server) { if (self.server) {
self.server.close(function() { self.server.close(function() {
resolve(); resolve();
}); });
for (connId in connections) {
if (connections[connId]) {
self.isLocal ? connections[connId].destroy() : connections[connId].terminate();
}
}
} else { } else {
resolve(); resolve();
} }
}); });
}; };
TCPRelay.prototype.getStatus = function() {
return this.status;
};
TCPRelay.prototype.init = function() { TCPRelay.prototype.init = function() {
var self = this; var self = this;
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
@@ -139,6 +156,10 @@ TCPRelay.prototype.init = function() {
server.on('connection', function(connection) { server.on('connection', function(connection) {
return self.handleConnectionByLocal(connection); return self.handleConnectionByLocal(connection);
}); });
server.on('close', function() {
self.logger.info('server is closed');
self.status = SERVER_STATUS_STOPPED;
});
server.listen(port, address); server.listen(port, address);
} else { } else {
server = self.server = new WebSocket.Server({ server = self.server = new WebSocket.Server({
@@ -153,10 +174,12 @@ TCPRelay.prototype.init = function() {
} }
server.on('error', function(error) { server.on('error', function(error) {
self.logger.error('an error of', self.getServerName(), 'occured', error); self.logger.error('an error of', self.getServerName(), 'occured', error);
self.status = SERVER_STATUS_STOPPED;
reject(error); reject(error);
}); });
server.on('listening', function() { server.on('listening', function() {
self.logger.info(self.getServerName(), 'is listening on', address + ':' + port); self.logger.info(self.getServerName(), 'is listening on', address + ':' + port);
self.status = SERVER_STATUS_RUNNING;
resolve(); resolve();
}); });
}); });
@@ -181,6 +204,7 @@ TCPRelay.prototype.handleConnectionByServer = function(connection) {
var dataCache = []; var dataCache = [];
logger.info(`[${connectionId}]: accept connection from local`); logger.info(`[${connectionId}]: accept connection from local`);
connections[connectionId] = connection;
connection.on('message', function(data) { connection.on('message', function(data) {
data = encryptor.decrypt(data); data = encryptor.decrypt(data);
logger.info(`[${connectionId}]: read data[length = ${data.length}] from local connection at stage[${STAGE[stage]}]`); logger.info(`[${connectionId}]: read data[length = ${data.length}] from local connection at stage[${STAGE[stage]}]`);
@@ -258,10 +282,13 @@ TCPRelay.prototype.handleConnectionByServer = function(connection) {
}); });
connection.on('close', function(hadError) { connection.on('close', function(hadError) {
logger.info(`[${connectionId}]: close event[had error = ${hadError}] of connection has been triggered`); logger.info(`[${connectionId}]: close event[had error = ${hadError}] of connection has been triggered`);
connections[connectionId] = null;
targetConnection && targetConnection.destroy();
}); });
connection.on('error', function(error) { connection.on('error', function(error) {
logger.error(`[${connectionId}]: an error of connection occured`, error); logger.error(`[${connectionId}]: an error of connection occured`, error);
connection.terminate(); connection.terminate();
connections[connectionId] = null;
targetConnection && targetConnection.end(); targetConnection && targetConnection.end();
}); });
} }
@@ -286,6 +313,7 @@ TCPRelay.prototype.handleConnectionByLocal = function(connection) {
var dataCache = []; var dataCache = [];
logger.info(`[${connectionId}]: accept connection from client`); logger.info(`[${connectionId}]: accept connection from client`);
connections[connectionId] = connection;
connection.setKeepAlive(true, 10000); connection.setKeepAlive(true, 10000);
connection.on('data', function(data) { connection.on('data', function(data) {
logger.info(`[${connectionId}]: read data[length = ${data.length}] from client connection at stage[${STAGE[stage]}]`); logger.info(`[${connectionId}]: read data[length = ${data.length}] from client connection at stage[${STAGE[stage]}]`);
@@ -389,12 +417,15 @@ TCPRelay.prototype.handleConnectionByLocal = function(connection) {
logger.info(`[${connectionId}]: close event[had error = ${hadError}] of client connection has been triggered`); logger.info(`[${connectionId}]: close event[had error = ${hadError}] of client connection has been triggered`);
stage = STAGE_DESTROYED; stage = STAGE_DESTROYED;
canWriteToLocalConnection = false; canWriteToLocalConnection = false;
connections[connectionId] = null;
serverConnection && serverConnection.terminate();
}); });
connection.on('error', function(error) { connection.on('error', function(error) {
logger.error(`[${connectionId}]: an error of client connection occured`, error); logger.error(`[${connectionId}]: an error of client connection occured`, error);
stage = STAGE_DESTROYED; stage = STAGE_DESTROYED;
connection.destroy(); connection.destroy();
canWriteToLocalConnection = false; canWriteToLocalConnection = false;
connections[connectionId] = null;
serverConnection && serverConnection.close(); serverConnection && serverConnection.close();
}); });
} }