@cliz/inlets
Version:
Cloud Native Tunnel
93 lines (92 loc) • 3.57 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const net = require("net");
const doreamon_1 = require("@zodash/doreamon");
const hmac = require("@zodash/hmac");
const constants_1 = require("../../common/constants");
const debug = require('debug')('inlets:client:tcp');
const logger = doreamon_1.default.logger.getLogger('client:tcp');
async function tcp(options) {
const ip = getSocketIP(options.remoteHost, options.remotePort);
let remote = null;
const local = connect(options.localPort, options.localHost, 'local', {
onClose() {
remote === null || remote === void 0 ? void 0 : remote.destroy();
},
onConnect() {
remote = connect(options.remotePort, options.remoteHost, 'remote');
const r = remote;
remote.on('data', (data) => {
if (r.isAuthenticated)
return;
const _ok = data.slice(0, constants_1.TUNNEL_TCP_OK_FLAG.length).toString();
const rest = data.slice(constants_1.TUNNEL_TCP_OK_FLAG.length);
if (_ok !== constants_1.TUNNEL_TCP_OK_FLAG) {
const error = data.slice(constants_1.TUNNEL_TCP_OK_FLAG.length, 32).toString();
logger.error(`[remote][${ip}] error: ${error}`);
return;
}
logger.info(`[remote][${ip}] authenticated`);
r.isAuthenticated = true;
local.pipe(remote);
remote.pipe(local);
if (rest.length !== 0) {
local.write(rest);
}
});
logger.info(`[remote][${ip}] authenticating`);
const signedSecret = options.authType === 'credentials'
? options.clientSecret
: options.token;
const signature = hmac.hmacSHA256(options.id, signedSecret);
const _data = [
constants_1.TUNNEL_TCP_FLAG,
options.id,
options.requestId,
signature,
].join('');
remote.write(_data);
},
});
}
exports.default = tcp;
function connect(port, host, name, options) {
const ip = getSocketIP(host, port);
const socket = net.connect(port, host, () => {
var _a;
logger.info(`[${name}][${ip}] socket connected`);
(_a = options === null || options === void 0 ? void 0 : options.onConnect) === null || _a === void 0 ? void 0 : _a.call(options);
});
onError(socket, name, ip);
onClose(socket, name, ip, options === null || options === void 0 ? void 0 : options.onClose);
onEnd(socket, name, ip);
return socket;
}
function onError(socket, name, ip) {
socket.on('error', (error) => {
if (/ECONNREFUSED/.test(error.message)) {
logger.error(`[${name}][${ip}] port is not available now`);
return;
}
logger.error(`[${name}][${ip}] socket error:`, error);
});
}
function onClose(socket, name, ip, callback) {
socket.on('close', (hadError) => {
if (!hadError) {
logger.info(`[${name}][${ip}] socket close normal`);
}
else {
logger.error(`[${name}][${ip}] socket close error`);
}
callback === null || callback === void 0 ? void 0 : callback();
});
}
function onEnd(socket, name, ip) {
socket.on('end', () => {
logger.info(`[${name}][${ip}] socket end`);
});
}
function getSocketIP(host, port) {
return `${host}:${port}`;
}