portmp
Version:
port mapping. A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet. support TCP & UDP
1,453 lines (1,407 loc) • 144 kB
JavaScript
#!/usr/bin/env node
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var require$$3 = require('fs');
var require$$0 = require('events');
var require$$1 = require('net');
var require$$0$1 = require('dgram');
var require$$1$1 = require('child_process');
var require$$2 = require('path');
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
var cli = {};
var Server = {};
var TCPPacket$1 = {};
// 处理TCP粘包的问题
Object.defineProperty(TCPPacket$1, "__esModule", { value: true });
TCPPacket$1.TCPDataPacket = TCPPacket$1.TCPBufferHandler = TCPPacket$1.TCPPacket = void 0;
class TCPPacket {
GenTCPBuffer() {
let l = 8;
if (this.Data != null) {
l += this.Data.length;
}
let buffer = Buffer.allocUnsafe(l);
buffer.writeUInt32LE(l, 0);
buffer.writeUInt32LE(this.Cmd, 4);
if (this.Data != null) {
this.Data.copy(buffer, 8, 0);
}
return buffer;
}
GetJsonData() {
if (this.Data) {
let jsonStr = this.Data.toString('utf8');
return JSON.parse(jsonStr);
}
return null;
}
SetJsonData(obj) {
let jsonStr = JSON.stringify(obj);
this.Data = Buffer.from(jsonStr, 'utf8');
}
}
TCPPacket$1.TCPPacket = TCPPacket;
class TCPBufferHandler {
constructor() {
this.recvdBuffer = null;
}
put(buffer) {
if (this.recvdBuffer != null) {
this.recvdBuffer = Buffer.concat([this.recvdBuffer, buffer], this.recvdBuffer.length + buffer.length);
}
else {
this.recvdBuffer = buffer;
}
}
tryGetTCPPacket() {
if (this.recvdBuffer == null || this.recvdBuffer.length == 0) {
return null;
}
if (this.recvdBuffer.length < 4) {
return null;
}
var packetDataLength = this.recvdBuffer.readUInt32LE(0);
if (this.recvdBuffer.length < packetDataLength) {
return null;
}
let packet = new TCPPacket();
packet.Length = packetDataLength;
packet.Cmd = this.recvdBuffer.readUInt32LE(4);
let dataLength = packetDataLength - 8;
if (dataLength > 0) {
let data = this.recvdBuffer.subarray(8, 8 + dataLength);
packet.Data = data;
}
let remainLength = this.recvdBuffer.length - packetDataLength;
if (remainLength == 0) {
this.recvdBuffer = null;
}
else {
let data = this.recvdBuffer.subarray(packetDataLength);
this.recvdBuffer = data;
}
return packet;
}
}
TCPPacket$1.TCPBufferHandler = TCPBufferHandler;
class TCPDataPacket {
UnSerialize(data) {
if (data.length >= 8) {
this.mappingId = data.readUInt32LE(0);
this.pipeId = data.readUInt32LE(4);
if (data.length > 8) {
this.buffer = data.subarray(8);
}
}
}
Serialize() {
let length = 8;
if (this.buffer) {
length += this.buffer.length;
}
let data = Buffer.allocUnsafe(length);
data.writeUint32LE(this.mappingId, 0);
data.writeUint32LE(this.pipeId, 4);
if (this.buffer && this.buffer.length > 0) {
this.buffer.copy(data, 8, 0);
}
return data;
}
}
TCPPacket$1.TCPDataPacket = TCPDataPacket;
var TCPServer$1 = {};
var once$1 = {exports: {}};
// Returns a wrapper function that returns a wrapped callback
// The wrapper function should do some stuff, and return a
// presumably different callback function.
// This makes sure that own properties are retained, so that
// decorations and such are not lost along the way.
var wrappy_1 = wrappy$1;
function wrappy$1 (fn, cb) {
if (fn && cb) return wrappy$1(fn)(cb)
if (typeof fn !== 'function')
throw new TypeError('need wrapper function')
Object.keys(fn).forEach(function (k) {
wrapper[k] = fn[k];
});
return wrapper
function wrapper() {
var args = new Array(arguments.length);
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i];
}
var ret = fn.apply(this, args);
var cb = args[args.length-1];
if (typeof ret === 'function' && ret !== cb) {
Object.keys(cb).forEach(function (k) {
ret[k] = cb[k];
});
}
return ret
}
}
var wrappy = wrappy_1;
once$1.exports = wrappy(once);
once$1.exports.strict = wrappy(onceStrict);
once.proto = once(function () {
Object.defineProperty(Function.prototype, 'once', {
value: function () {
return once(this)
},
configurable: true
});
Object.defineProperty(Function.prototype, 'onceStrict', {
value: function () {
return onceStrict(this)
},
configurable: true
});
});
function once (fn) {
var f = function () {
if (f.called) return f.value
f.called = true;
return f.value = fn.apply(this, arguments)
};
f.called = false;
return f
}
function onceStrict (fn) {
var f = function () {
if (f.called)
throw new Error(f.onceError)
f.called = true;
return f.value = fn.apply(this, arguments)
};
var name = fn.name || 'Function wrapped with `once`';
f.onceError = name + " shouldn't be called more than once";
f.called = false;
return f
}
var onceExports = once$1.exports;
var __awaiter$9 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault$7 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(TCPServer$1, "__esModule", { value: true });
TCPServer$1.TCPSession = TCPServer$1.TCPServer = TCPServer$1.TCPOptions = void 0;
const events_1$4 = __importDefault$7(require$$0);
const net_1$1 = __importDefault$7(require$$1);
const once_1$2 = __importDefault$7(onceExports);
const TCPPacket_1$5 = TCPPacket$1;
class TCPOptions {
constructor() {
this.usePacket = false;
}
}
TCPServer$1.TCPOptions = TCPOptions;
class TCPServer extends events_1$4.default {
constructor(options) {
super();
this.options = options;
}
setServer(port) {
this.port = port;
}
start() {
return __awaiter$9(this, void 0, void 0, function* () {
let promise = new Promise((resolve, reject) => {
resolve = (0, once_1$2.default)(resolve);
let server = this.server = new net_1$1.default.Server();
server.on('listening', () => {
// 监听成功
resolve(true);
});
server.on('error', (err) => {
// 监听发生错误
resolve(false);
});
server.on('close', () => {
// 关闭的时候
this.emit('close');
});
server.on('connection', (socket) => {
// 新连接
let session = new TCPSession(this.options, socket);
this.emit('newConnect', session);
});
// server.on('drop', (data?: net.DropArgument) => {
// // 新连接被丢弃 什么都不处理
// });
server.listen(this.port);
});
return promise;
});
}
close() {
if (this.server) {
let server = this.server;
this.server = null;
server.close();
}
}
on(...args) {
super.on.call(this, ...args);
return this;
}
}
TCPServer$1.TCPServer = TCPServer;
class TCPSession extends events_1$4.default {
constructor(options, socket) {
super();
this.isAuthed = false;
this.socket = socket;
this.options = options;
if (this.options.usePacket) {
this.initTCPBufferHandler();
}
socket.on("error", (error) => {
// 发生错误了
this.close();
});
socket.on("close", () => {
// 关闭了
this.close();
});
socket.on("end", () => {
// 对方说结束了
this.close();
});
socket.on("timeout", () => {
// 超时了 需要手动关闭链接
this.close();
});
socket.on("data", (data) => {
// 有数据来了
this.onReceiveData(data);
});
}
initTCPBufferHandler() {
this.bufferHandler = new TCPPacket_1$5.TCPBufferHandler();
}
start() {
return __awaiter$9(this, void 0, void 0, function* () {
return true;
});
}
close() {
if (this.socket) {
let socket = this.socket;
this.socket = null;
socket.end();
socket.destroy();
this.emit('close');
}
}
write(buffer) {
if (buffer)
if (this.socket)
this.socket.write(buffer);
}
writePacket(packet) {
if (packet)
this.write(packet.GenTCPBuffer());
}
onReceiveData(data) {
this.emit('data', data);
if (this.bufferHandler) {
this.bufferHandler.put(data);
while (true) {
let packet = this.bufferHandler.tryGetTCPPacket();
if (packet)
this.emit('packet', packet);
else
break;
}
}
}
on(...args) {
super.on.call(this, ...args);
return this;
}
}
TCPServer$1.TCPSession = TCPSession;
var PortMappingManager$1 = {};
var Pipe$1 = {};
var __awaiter$8 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault$6 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(Pipe$1, "__esModule", { value: true });
Pipe$1.Pipe = void 0;
const events_1$3 = __importDefault$6(require$$0);
var EventSide;
(function (EventSide) {
EventSide[EventSide["Left"] = 1] = "Left";
EventSide[EventSide["Right"] = 2] = "Right";
})(EventSide || (EventSide = {}));
class EventInfo {
}
class EventQueue {
constructor() {
this.queue = [];
}
get length() {
return this.queue.length;
}
EnQueue(evnet) {
this.queue.push(evnet);
}
DeQueue() {
return this.queue.shift();
}
Clear() {
this.queue = [];
}
}
class Pipe extends events_1$3.default {
constructor(left, right) {
super();
this.isReady = false;
this.eventQueue = new EventQueue();
this.left = left;
this.right = right;
}
link() {
return __awaiter$8(this, void 0, void 0, function* () {
this.left.on('close', () => {
let eventInfo = new EventInfo();
eventInfo.side = EventSide.Left;
eventInfo.name = 'close';
this.enQueue(eventInfo);
});
this.left.on('data', (buffer) => {
let eventInfo = new EventInfo();
eventInfo.side = EventSide.Left;
eventInfo.name = 'data';
eventInfo.buffer = buffer;
this.enQueue(eventInfo);
});
this.right.on('close', () => {
let eventInfo = new EventInfo();
eventInfo.side = EventSide.Right;
eventInfo.name = 'close';
this.enQueue(eventInfo);
});
this.right.on('data', (buffer) => {
let eventInfo = new EventInfo();
eventInfo.side = EventSide.Right;
eventInfo.name = 'data';
eventInfo.buffer = buffer;
this.enQueue(eventInfo);
});
let leftSucc = yield this.left.start();
if (leftSucc) {
let rightSucc = yield this.right.start();
if (rightSucc) {
this.isReady = true;
this.onReady();
return true;
}
}
this.close();
return false;
});
}
onReady() {
this.tryExecQueue();
}
enQueue(evnet) {
this.eventQueue.EnQueue(evnet);
this.tryExecQueue();
}
tryExecQueue() {
while (true) {
if (this.eventQueue.length == 0) {
break;
}
if (!this.isReady) {
break;
}
if (!this.left || !this.right) {
break;
}
let evnet = this.eventQueue.DeQueue();
if (evnet.side == EventSide.Left) {
if (evnet.name == 'close') {
this.close();
}
else if (evnet.name == 'data') {
this.right.write(evnet.buffer);
}
}
else if (evnet.side == EventSide.Right) {
if (evnet.name == 'close') {
this.close();
}
else if (evnet.name == 'data') {
this.left.write(evnet.buffer);
}
}
}
}
close() {
let left = this.left;
let right = this.right;
if (left && right) {
this.left = null;
this.right = null;
left.close();
right.close();
this.emit('close');
}
}
onReceiveTunnleData(buffer) {
let tunnleWrapper = this.tunnleWrapper;
tunnleWrapper.onReceiveData(buffer);
}
}
Pipe$1.Pipe = Pipe;
var TCPClient$1 = {};
var __awaiter$7 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault$5 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(TCPClient$1, "__esModule", { value: true });
TCPClient$1.TCPClient = void 0;
const events_1$2 = __importDefault$5(require$$0);
const net_1 = __importDefault$5(require$$1);
const once_1$1 = __importDefault$5(onceExports);
const TCPPacket_1$4 = TCPPacket$1;
class TCPClient extends events_1$2.default {
constructor(options) {
super();
this.isAuthed = false;
this.connected = false;
this.socket = new net_1.default.Socket();
this.options = options;
if (this.options.usePacket) {
this.initTCPBufferHandler();
}
}
setClient(port, address = '127.0.0.1') {
this.port = port;
this.address = address;
}
initTCPBufferHandler() {
this.bufferHandler = new TCPPacket_1$4.TCPBufferHandler();
}
start() {
return __awaiter$7(this, void 0, void 0, function* () {
let promise = new Promise((resolve, reject) => {
resolve = (0, once_1$1.default)(resolve);
if (this.connected) {
resolve(false);
return;
}
if (!this.socket) {
resolve(false);
return;
}
this.connected = true;
let socket = this.socket;
socket.on("error", (error) => {
// 发生错误了
this.close();
resolve(false);
});
socket.on("close", () => {
// 关闭了
this.close();
});
socket.on("end", () => {
// 对方说结束了
this.close();
});
socket.on("timeout", () => {
// 超时了 需要手动关闭链接
this.close();
});
socket.on("data", (data) => {
// 有数据来了
this.onReceiveData(data);
});
socket.on("ready", () => {
// 连接成功
resolve(true);
});
socket.connect(this.port, this.address);
});
return promise;
});
}
close() {
if (this.socket) {
let socket = this.socket;
this.socket = null;
socket.end();
socket.destroy();
this.emit('close');
}
}
write(buffer) {
if (buffer)
if (this.socket)
this.socket.write(buffer);
}
writePacket(packet) {
if (packet)
this.write(packet.GenTCPBuffer());
}
onReceiveData(data) {
this.emit('data', data);
if (this.bufferHandler) {
this.bufferHandler.put(data);
while (true) {
let packet = this.bufferHandler.tryGetTCPPacket();
if (packet)
this.emit('packet', packet);
else
break;
}
}
}
on(...args) {
super.on.call(this, ...args);
return this;
}
}
TCPClient$1.TCPClient = TCPClient;
var CMD$1 = {};
Object.defineProperty(CMD$1, "__esModule", { value: true });
CMD$1.CMD = void 0;
var CMD;
(function (CMD) {
CMD[CMD["Hello"] = 1] = "Hello";
CMD[CMD["Ping"] = 2] = "Ping";
CMD[CMD["Heartbeat"] = 3] = "Heartbeat";
CMD[CMD["New_PortMapping"] = 4] = "New_PortMapping";
CMD[CMD["TCP_Connected"] = 5] = "TCP_Connected";
CMD[CMD["TCP_Data"] = 6] = "TCP_Data";
CMD[CMD["TCP_Closed"] = 7] = "TCP_Closed";
})(CMD || (CMD$1.CMD = CMD = {}));
var UDPSocket = {};
var __awaiter$6 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault$4 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(UDPSocket, "__esModule", { value: true });
UDPSocket.UDPServer = UDPSocket.UDPSessionManager = UDPSocket.UDPSession = UDPSocket.UDPClient = void 0;
const events_1$1 = __importDefault$4(require$$0);
const once_1 = __importDefault$4(onceExports);
class UDPClient extends events_1$1.default {
constructor(socket) {
super();
this.socket = socket;
}
setClient(port, address = '127.0.0.1') {
this.port = port;
this.address = address;
}
start() {
return __awaiter$6(this, void 0, void 0, function* () {
if (!this.socket) {
return false;
}
let promise = new Promise((resolve, reject) => {
resolve = (0, once_1.default)(resolve);
reject = (0, once_1.default)(reject);
let socket = this.socket;
socket.on("error", (error) => {
console.error(error);
this.close();
resolve(false);
});
socket.on("listening", () => {
resolve(true);
});
socket.on("close", () => {
this.close();
});
socket.on("message", (data, rinfo) => {
this.onData(data, rinfo);
});
socket.bind(0); // 让系统分配localport
});
return promise;
});
}
onData(buffer, rinfo) {
if (rinfo.address == this.address && rinfo.port == this.port) {
this.onReceiveData(buffer);
}
}
onReceiveData(buffer) {
if (buffer)
this.emit('data', buffer);
}
write(buffer) {
if (buffer && this.socket)
this.socket.send(buffer, this.port, this.address);
}
close() {
let socket = this.socket;
if (socket) {
this.socket = null;
socket.close();
this.emit('close');
}
}
on(...args) {
super.on.call(this, ...args);
return this;
}
once(...args) {
super.once.call(this, ...args);
return this;
}
}
UDPSocket.UDPClient = UDPClient;
class UDPSession extends events_1$1.default {
constructor() {
super(...arguments);
this.closed = false;
}
start() {
return __awaiter$6(this, void 0, void 0, function* () {
return true;
});
}
onReceiveData(buffer) {
if (!this.closed) {
this.activeTime = Date.now();
this.emit('data', buffer);
}
}
write(buffer) {
if (!this.closed) {
this.activeTime = Date.now();
this.server.write(buffer, this.port, this.address);
}
}
close() {
if (!this.closed) {
this.closed = true;
this.emit('close');
}
}
on(...args) {
super.on.call(this, ...args);
return this;
}
once(...args) {
super.once.call(this, ...args);
return this;
}
}
UDPSocket.UDPSession = UDPSession;
class UDPSessionManager {
constructor() {
this.mapByStr = new Map();
this.intervalTimer = null;
}
AddNew(udpSession) {
this.mapByStr.set(udpSession.ipPort, udpSession);
}
GetByIPPort(ipPort) {
return this.mapByStr.get(ipPort);
}
Del(udpSession) {
this.mapByStr.delete(udpSession.ipPort);
}
startCheck() {
this.intervalTimer = setInterval(() => {
this.checkDeadSession();
}, 1000);
}
stopCheck() {
if (this.intervalTimer) {
clearInterval(this.intervalTimer);
this.intervalTimer = null;
}
}
checkDeadSession() {
let toCloses = [];
let now = Date.now();
for (const session of this.mapByStr.values()) {
let dt = now - session.activeTime;
if (dt > 10) { // 5s
toCloses.push(session);
}
}
for (const session of toCloses) {
session.close();
}
}
}
UDPSocket.UDPSessionManager = UDPSessionManager;
class UDPServer extends events_1$1.default {
constructor(socket) {
super();
this.sessionManager = new UDPSessionManager();
this.socket = socket;
}
setServer(port) {
this.port = port;
}
start() {
return __awaiter$6(this, void 0, void 0, function* () {
let promise = new Promise((resolve, reject) => {
resolve = (0, once_1.default)(resolve);
reject = (0, once_1.default)(reject);
let socket = this.socket;
socket.on("error", (error) => {
console.error(error);
this.close();
resolve(false);
});
socket.on("listening", () => {
this.onReady();
resolve(true);
});
socket.on("close", () => {
this.close();
});
socket.on("message", (data, rinfo) => {
this.onData(data, rinfo);
});
socket.bind(this.port);
});
return promise;
});
}
onReady() {
this.sessionManager.startCheck();
this.emit('ready');
}
onData(buffer, rinfo) {
let ipPort = rinfo.address + rinfo.port;
let session = this.sessionManager.GetByIPPort(ipPort);
if (!session) {
session = new UDPSession();
session.server = this;
session.ipPort = ipPort;
session.address = rinfo.address;
session.port = rinfo.port;
session.once('close', () => {
this.sessionManager.Del(session);
});
this.sessionManager.AddNew(session);
this.emit('newConnect', session);
}
session.onReceiveData(buffer);
this.emit('data', session, buffer, rinfo);
}
write(buffer, port, address) {
if (buffer && this.socket)
this.socket.send(buffer, port, address);
}
close() {
if (!this.socket) {
let socket = this.socket;
this.socket = null;
socket.close();
this.sessionManager.stopCheck();
this.emit('close');
}
}
on(...args) {
super.on.call(this, ...args);
return this;
}
once(...args) {
super.once.call(this, ...args);
return this;
}
}
UDPSocket.UDPServer = UDPServer;
var TCPTunnleWrapper$1 = {};
var __awaiter$5 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault$3 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(TCPTunnleWrapper$1, "__esModule", { value: true });
TCPTunnleWrapper$1.TCPTunnleWrapper = void 0;
const events_1 = __importDefault$3(require$$0);
const CMD_1$3 = CMD$1;
const TCPPacket_1$3 = TCPPacket$1;
class TCPTunnleWrapper extends events_1.default {
constructor(packetable, mappingId, pipeId) {
super();
this.packetable = packetable;
this.mappingId = mappingId;
this.pipeId = pipeId;
}
onReceiveData(buffer) {
if (this.packetable) {
this.emit('data', buffer);
}
}
write(buffer) {
if (buffer && this.packetable) {
if (typeof buffer === 'string') {
buffer = Buffer.from(buffer);
}
let packet = new TCPPacket_1$3.TCPPacket();
packet.Cmd = CMD_1$3.CMD.TCP_Data;
let dataPacket = new TCPPacket_1$3.TCPDataPacket();
dataPacket.mappingId = this.mappingId;
dataPacket.pipeId = this.pipeId;
dataPacket.buffer = buffer;
packet.Data = dataPacket.Serialize();
this.packetable.writePacket(packet);
}
}
close() {
if (this.packetable) {
let packetable = this.packetable;
this.packetable = null;
this.emitCloseEvent(packetable);
}
}
emitCloseEvent(packetable) {
let packet = new TCPPacket_1$3.TCPPacket();
packet.Cmd = CMD_1$3.CMD.TCP_Closed;
let dataPacket = new TCPPacket_1$3.TCPDataPacket();
dataPacket.mappingId = this.mappingId;
dataPacket.pipeId = this.pipeId;
packet.Data = dataPacket.Serialize();
packetable.writePacket(packet);
this.emit('close');
}
start() {
return __awaiter$5(this, void 0, void 0, function* () {
return true;
});
}
on(...args) {
super.on.call(this, ...args);
return this;
}
}
TCPTunnleWrapper$1.TCPTunnleWrapper = TCPTunnleWrapper;
var __awaiter$4 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault$2 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(PortMappingManager$1, "__esModule", { value: true });
PortMappingManager$1.PortMappingManager = PortMappingManager$1.PortMapping = PortMappingManager$1.UID = void 0;
const dgram_1$1 = __importDefault$2(require$$0$1);
const TCPServer_1$3 = TCPServer$1;
const Pipe_1$1 = Pipe$1;
const TCPClient_1$2 = TCPClient$1;
const CMD_1$2 = CMD$1;
const TCPPacket_1$2 = TCPPacket$1;
const UDPSocket_1$1 = UDPSocket;
const TCPTunnleWrapper_1 = TCPTunnleWrapper$1;
class UID {
static GetUID() {
return UID.uid++;
}
}
PortMappingManager$1.UID = UID;
UID.uid = 1;
class PortMapping {
constructor(isServer, tunnel, forwardInfo) {
this.map = new Map();
this.isServer = isServer;
this.tunnel = tunnel;
this.forwardInfo = forwardInfo;
}
start() {
return __awaiter$4(this, void 0, void 0, function* () {
if (!this.isServer) {
return true;
}
if (this.forwardInfo.type == 'tcp') {
let options = new TCPServer_1$3.TCPOptions();
options.usePacket = false;
let tcpServer = new TCPServer_1$3.TCPServer(options);
tcpServer.setServer(this.forwardInfo.fromPort);
let succ = yield tcpServer.start();
if (!succ) {
console.error('本地代理启动失败!');
}
else {
this.tcpServer = tcpServer;
console.log(`tcp proxy server port:${this.forwardInfo.fromPort}`);
tcpServer.on('newConnect', (rometeSession) => {
this.onServerNewConnect(rometeSession);
});
}
return succ;
}
else {
let udpServer = new UDPSocket_1$1.UDPServer(dgram_1$1.default.createSocket('udp4'));
udpServer.setServer(this.forwardInfo.fromPort);
let succ = yield udpServer.start();
if (!succ) {
console.error('本地代理启动失败!');
}
else {
this.udpServer = udpServer;
console.log(`udp proxy server port:${this.forwardInfo.fromPort}`);
udpServer.on('newConnect', (rometeSession) => {
this.onServerNewConnect(rometeSession);
});
}
return succ;
}
});
}
onServerNewConnect(rometeSession) {
return __awaiter$4(this, void 0, void 0, function* () {
let pipeId = UID.GetUID();
let tcpPacket = new TCPPacket_1$2.TCPPacket();
tcpPacket.Cmd = CMD_1$2.CMD.TCP_Connected;
let dataPacket = new TCPPacket_1$2.TCPDataPacket();
dataPacket.mappingId = this.forwardInfo.mappingId;
dataPacket.pipeId = pipeId;
tcpPacket.Data = dataPacket.Serialize();
this.tunnel.writePacket(tcpPacket);
let tcpTunnleWrapper = new TCPTunnleWrapper_1.TCPTunnleWrapper(this.tunnel, this.forwardInfo.mappingId, pipeId);
let pipe = new Pipe_1$1.Pipe(tcpTunnleWrapper, rometeSession);
pipe.tunnleWrapper = tcpTunnleWrapper;
pipe.on('close', () => {
this.connectionClose(pipeId);
});
this.map.set(pipeId, pipe);
let succ = yield pipe.link();
if (!succ) {
console.error(`远程代理 本地session创建失败! pipeId=${pipeId}`);
}
});
}
onClientNewConnect(mappingId, pipeId) {
return __awaiter$4(this, void 0, void 0, function* () {
if (this.isServer) {
return false;
}
if (this.map.has(pipeId)) {
return false;
}
if (this.forwardInfo.type == 'tcp') {
let options = new TCPServer_1$3.TCPOptions();
options.usePacket = false;
let leftSession = new TCPClient_1$2.TCPClient(options);
leftSession.setClient(this.forwardInfo.targetPort, this.forwardInfo.targetAddr);
let tcpTunnleWrapper = new TCPTunnleWrapper_1.TCPTunnleWrapper(this.tunnel, mappingId, pipeId);
let pipe = new Pipe_1$1.Pipe(leftSession, tcpTunnleWrapper);
pipe.tunnleWrapper = tcpTunnleWrapper;
pipe.on('close', () => {
this.connectionClose(pipeId);
});
this.map.set(pipeId, pipe);
let succ = yield pipe.link();
if (!succ) {
console.error(`远程代理 本地session创建失败! id=${pipeId}`);
}
return succ;
}
else {
let leftSession = new UDPSocket_1$1.UDPClient(dgram_1$1.default.createSocket('udp4'));
leftSession.setClient(this.forwardInfo.targetPort, this.forwardInfo.targetAddr);
let tcpTunnleWrapper = new TCPTunnleWrapper_1.TCPTunnleWrapper(this.tunnel, mappingId, pipeId);
let pipe = new Pipe_1$1.Pipe(leftSession, tcpTunnleWrapper);
pipe.tunnleWrapper = tcpTunnleWrapper;
pipe.on('close', () => {
this.connectionClose(pipeId);
});
this.map.set(pipeId, pipe);
let succ = yield pipe.link();
if (!succ) {
console.error(`远程代理 本地session创建失败! id=${pipeId}`);
}
return succ;
}
});
}
connectionClose(pipeId) {
this.map.delete(pipeId);
}
onReceiveTunnleData(buffer, pipeId) {
if (this.map.has(pipeId)) {
var pipe = this.map.get(pipeId);
pipe.onReceiveTunnleData(buffer);
}
}
onReceiveTunnleClose(pipeId) {
if (this.map.has(pipeId)) {
var pipe = this.map.get(pipeId);
pipe.close();
}
}
close() {
let pipes = [];
for (const item of this.map.values()) {
pipes.push(item);
}
this.map = new Map(); // clear
for (const item of pipes) {
item.close();
}
if (this.tcpServer) {
let server = this.tcpServer;
this.tcpServer = null;
server.close();
}
if (this.udpServer) {
let server = this.udpServer;
this.udpServer = null;
server.close();
}
}
}
PortMappingManager$1.PortMapping = PortMapping;
class PortMappingManager {
constructor() {
this.portMappingMap = new Map();
}
newPortMapping(tcpSession, mappingId, portMapping) {
return __awaiter$4(this, void 0, void 0, function* () {
if (!this.portMappingMap.has(tcpSession)) {
this.portMappingMap.set(tcpSession, new Map());
}
this.portMappingMap.get(tcpSession).set(mappingId, portMapping);
let succ = yield portMapping.start();
return succ;
});
}
onRecvTunnleConnect(tcpSession, mappingId, pipeId) {
let map = this.portMappingMap.get(tcpSession);
if (map) {
let portMapping = map.get(mappingId);
if (portMapping) {
portMapping.onClientNewConnect(mappingId, pipeId);
}
}
}
onRecvTunnleClose(tcpSession, mappingId, pipeId) {
let map = this.portMappingMap.get(tcpSession);
if (map) {
let portMapping = map.get(mappingId);
if (portMapping) {
portMapping.onReceiveTunnleClose(pipeId);
}
}
}
onRecvTunnleData(tcpSession, mappingId, pipeId, buffer) {
let map = this.portMappingMap.get(tcpSession);
if (map) {
let portMapping = map.get(mappingId);
if (portMapping) {
portMapping.onReceiveTunnleData(buffer, pipeId);
}
}
}
close(tcpSession) {
let map = this.portMappingMap.get(tcpSession);
if (map) {
this.portMappingMap.delete(tcpSession);
for (const portMapping of map.values()) {
portMapping.close();
}
}
}
}
PortMappingManager$1.PortMappingManager = PortMappingManager;
var ForwardInfo$1 = {};
var Utils = {};
Object.defineProperty(Utils, "__esModule", { value: true });
Utils.hashCode = void 0;
function hashCode(strKey) {
var hash = 0;
if (strKey != null) {
for (var i = 0; i < strKey.length; i++) {
hash = hash * 31 + strKey.charCodeAt(i);
hash = uintValue(hash);
}
}
return hash;
}
Utils.hashCode = hashCode;
function uintValue(num) {
// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number
// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators#bitwise_shift_operators
// 位运算符规则
// 1.浮点数去掉小数后变成整数
// 2.将整数取低32位变成int32
// 3.>>> 无符号右移 返回的结果是uint32
// 4.其他位运算符 返回的结果是int32
num &= 0xFFFFFFFF; // int32
return num >>> 0; // uint32
}
Object.defineProperty(ForwardInfo$1, "__esModule", { value: true });
ForwardInfo$1.ForwardInfo = void 0;
const Utils_1 = Utils;
class ForwardInfo {
constructor(jsonObj) {
this.mappingId = 0;
this.isLocalForward = false;
this.from(jsonObj);
}
from(jsonObj) {
if (jsonObj) {
Object.assign(this, jsonObj);
this.mappingId = (0, Utils_1.hashCode)(this.type + this.targetAddr + this.targetPort + this.fromPort);
}
}
static From(jsonObj) {
return new ForwardInfo(jsonObj);
}
}
ForwardInfo$1.ForwardInfo = ForwardInfo;
var __awaiter$3 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(Server, "__esModule", { value: true });
Server.startServer = void 0;
const TCPPacket_1$1 = TCPPacket$1;
const TCPServer_1$2 = TCPServer$1;
const PortMappingManager_1$1 = PortMappingManager$1;
const CMD_1$1 = CMD$1;
const ForwardInfo_1$1 = ForwardInfo$1;
let startServer = (port = 7666, validKeys = []) => __awaiter$3(void 0, void 0, void 0, function* () {
let mappingManager = new PortMappingManager_1$1.PortMappingManager();
let options = new TCPServer_1$2.TCPOptions();
options.usePacket = true;
let tcpServer = new TCPServer_1$2.TCPServer(options);
tcpServer.setServer(port);
tcpServer.on("newConnect", (tcpSession) => {
tcpSession.on('packet', (packet) => {
if (packet.Cmd == CMD_1$1.CMD.Hello) {
if (validKeys.length > 0) {
let hello = packet.GetJsonData();
if (hello && hello.authKey) {
if (validKeys.includes(hello.authKey)) {
tcpSession.isAuthed = true;
}
else {
tcpSession.isAuthed = false;
}
}
}
else {
tcpSession.isAuthed = true;
}
let resPacket = new TCPPacket_1$1.TCPPacket();
resPacket.Cmd = CMD_1$1.CMD.Hello;
resPacket.SetJsonData({ isAuthed: tcpSession.isAuthed });
tcpSession.writePacket(resPacket);
}
if (!tcpSession.isAuthed) {
tcpSession.close();
return;
}
if (packet.Cmd == CMD_1$1.CMD.New_PortMapping) {
let forwardInfos = packet.GetJsonData();
forwardInfos = forwardInfos.map((v) => ForwardInfo_1$1.ForwardInfo.From(v));
let isServer = true;
for (const forwardInfo of forwardInfos) {
let portMapping = new PortMappingManager_1$1.PortMapping(isServer, tcpSession, forwardInfo);
mappingManager.newPortMapping(tcpSession, forwardInfo.mappingId, portMapping);
}
}
else if (packet.Cmd == CMD_1$1.CMD.TCP_Closed) {
let dataPacket = new TCPPacket_1$1.TCPDataPacket();
dataPacket.UnSerialize(packet.Data);
mappingManager.onRecvTunnleClose(tcpSession, dataPacket.mappingId, dataPacket.pipeId);
}
else if (packet.Cmd == CMD_1$1.CMD.TCP_Data) {
let dataPacket = new TCPPacket_1$1.TCPDataPacket();
dataPacket.UnSerialize(packet.Data);
mappingManager.onRecvTunnleData(tcpSession, dataPacket.mappingId, dataPacket.pipeId, dataPacket.buffer);
}
});
tcpSession.on('close', () => {
mappingManager.close(tcpSession);
});
});
return yield tcpServer.start();
});
Server.startServer = startServer;
var Client = {};
var __awaiter$2 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(Client, "__esModule", { value: true });
Client.startClient = void 0;
const CMD_1 = CMD$1;
const TCPPacket_1 = TCPPacket$1;
const TCPServer_1$1 = TCPServer$1;
const TCPClient_1$1 = TCPClient$1;
const PortMappingManager_1 = PortMappingManager$1;
let startClient = (forwardInfos, remotePort = 7666, remoteAddr = '127.0.0.1', authKey = '') => __awaiter$2(void 0, void 0, void 0, function* () {
let mappingManager = new PortMappingManager_1.PortMappingManager();
let options = new TCPServer_1$1.TCPOptions();
options.usePacket = true;
let tcpClient = new TCPClient_1$1.TCPClient(options);
tcpClient.setClient(remotePort, remoteAddr);
{
tcpClient.on('close', () => {
mappingManager.close(tcpClient);
});
tcpClient.on('packet', (packet) => {
if (packet.Cmd == CMD_1.CMD.Hello) {
let hello = packet.GetJsonData();
if (hello && hello.isAuthed) {
tcpClient.isAuthed = true;
}
else {
tcpClient.isAuthed = false;
}
if (tcpClient.isAuthed) {
let packet = new TCPPacket_1.TCPPacket();
packet.Cmd = CMD_1.CMD.New_PortMapping;
packet.SetJsonData(forwardInfos);
tcpClient.writePacket(packet);
let isServer = false;
for (const forwardInfo of forwardInfos) {
let portMapping = new PortMappingManager_1.PortMapping(isServer, tcpClient, forwardInfo);
mappingManager.newPortMapping(tcpClient, forwardInfo.mappingId, portMapping);
}
}
}
if (!tcpClient.isAuthed) {
tcpClient.close();
return;
}
if (packet.Cmd == CMD_1.CMD.New_PortMapping) {
packet.GetJsonData();
}
else if (packet.Cmd == CMD_1.CMD.TCP_Connected) {
let dataPacket = new TCPPacket_1.TCPDataPacket();
dataPacket.UnSerialize(packet.Data);
mappingManager.onRecvTunnleConnect(tcpClient, dataPacket.mappingId, dataPacket.pipeId);
}
else if (packet.Cmd == CMD_1.CMD.TCP_Closed) {
let dataPacket = new TCPPacket_1.TCPDataPacket();
dataPacket.UnSerialize(packet.Data);
mappingManager.onRecvTunnleClose(tcpClient, dataPacket.mappingId, dataPacket.pipeId);
}
else if (packet.Cmd == CMD_1.CMD.TCP_Data) {
let dataPacket = new TCPPacket_1.TCPDataPacket();
dataPacket.UnSerialize(packet.Data);
mappingManager.onRecvTunnleData(tcpClient, dataPacket.mappingId, dataPacket.pipeId, dataPacket.buffer);
}
});
}
let succ = yield tcpClient.start();
if (succ) {
let packet = new TCPPacket_1.TCPPacket();
packet.Cmd = CMD_1.CMD.Hello;
packet.SetJsonData({ authKey: authKey });
tcpClient.writePacket(packet);
let intervalTimer = setInterval(() => {
let packet = new TCPPacket_1.TCPPacket();
packet.Cmd = CMD_1.CMD.Heartbeat;
packet.SetJsonData({ authKey: authKey });
tcpClient.writePacket(packet);
}, 1000);
tcpClient.on('close', () => {
clearInterval(intervalTimer);
});
}
return succ;
});
Client.startClient = startClient;
var commander = {exports: {}};
var argument = {};
var error = {};
// @ts-check
/**
* CommanderError class
* @class
*/
let CommanderError$1 = class CommanderError extends Error {
/**
* Constructs the CommanderError class
* @param {number} exitCode suggested exit code which could be used with process.exit
* @param {string} code an id string representing the error
* @param {string} message human-readable description of the error
* @constructor
*/
constructor(exitCode, code, message) {
super(message);
// properly capture stack trace in Node.js
Error.captureStackTrace(this, this.constructor);
this.name = this.constructor.name;
this.code = code;
this.exitCode = exitCode;
this.nestedError = undefined;
}
};
/**
* InvalidArgumentError class
* @class
*/
let InvalidArgumentError$2 = class InvalidArgumentError extends CommanderError$1 {
/**
* Constructs the InvalidArgumentError class
* @param {string} [message] explanation of why argument is invalid
* @constructor
*/
constructor(message) {
super(1, 'commander.invalidArgument', message);
// properly capture stack trace in Node.js
Error.captureSt