@cliz/inlets
Version:
Cloud Native Tunnel
71 lines (70 loc) • 2.73 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.forward = void 0;
const cli_1 = require("@cliz/cli");
const doreamon_1 = require("@zodash/doreamon");
const net = require("net");
const debug = require('debug')('inlets:forward');
async function forward(options) {
var _a;
const logger = doreamon_1.default.logger.getLogger('forward');
const servers = (_a = options === null || options === void 0 ? void 0 : options.servers) !== null && _a !== void 0 ? _a : [];
logger.info(`total servers: ${servers.length}`);
const portUsed = {};
for (const server of servers) {
if (portUsed[server.localPort]) {
logger.error(`forward error: port(${server.localPort}) used internal`);
continue;
}
portUsed[server.localPort] = true;
try {
await serve(server);
}
catch (error) {
logger.error('forward error:', error);
}
}
}
exports.forward = forward;
async function serve(options) {
const { localHost = '127.0.0.1', localPort, remoteHost, remotePort, } = options;
const logger = doreamon_1.default.logger.getLogger(`${localHost}:${localPort}:${remoteHost}:${remotePort}`);
if (!await cli_1.api.network.isPortAvailable(localPort)) {
throw new Error(`port(${localPort}) is used`);
}
const connect = async () => {
try {
const server = net.createServer(socket => {
const clientIP = socket.remoteAddress;
logger.info(`client(${clientIP}) connected`);
const remoteSocket = net.connect(remotePort, remoteHost);
socket.on('error', (error) => {
logger.error('local socket error:', error);
});
socket.on('close', (had_error) => {
logger.info('local socket close, has error ? ', had_error);
});
remoteSocket.on('error', (error) => {
logger.error('remote socket error:', error);
});
remoteSocket.pipe(socket);
socket.pipe(remoteSocket);
});
server.on('error', (error) => {
logger.error('tcp server error:', error);
});
server.on('close', (error) => {
logger.error('tcp server close:', error);
});
server.listen(localPort, localHost, () => {
logger.info('start success');
});
}
catch (error) {
await doreamon_1.default.delay(1000);
logger.info('reconnect:', error);
await connect();
}
};
await connect();
}