@cliz/inlets
Version:
Cloud Native Tunnel
82 lines (81 loc) • 2.89 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TCPStreamOverWebSocket = void 0;
const net = require("net");
const doreamon_1 = require("@zodash/doreamon");
const debug = require('debug')('inlets:tcp-stream-over-ws');
const logger = doreamon_1.default.logger.getLogger('tcp-stream-over-ws');
class TCPStreamOverWebSocket {
constructor(streamId, localPort, localHost, adapter) {
this.isClosed = false;
this.streamId = streamId;
this.adapter = adapter;
this.localSocket = net.connect(localPort, localHost);
this.setupLocalSocket();
this.setupWebSocketHandlers();
}
setupLocalSocket() {
this.localSocket.on('connect', () => {
logger.info(`[${this.streamId}] Local socket connected`);
});
this.localSocket.on('data', async (data) => {
if (this.isClosed)
return;
try {
await this.adapter.sendTCPData(this.streamId, data);
}
catch (error) {
logger.error(`[${this.streamId}] Failed to send TCP data over WebSocket:`, error);
this.close();
}
});
this.localSocket.on('error', (error) => {
logger.error(`[${this.streamId}] Local socket error:`, error);
this.close();
});
this.localSocket.on('close', () => {
logger.info(`[${this.streamId}] Local socket closed`);
this.close();
});
this.localSocket.on('end', () => {
logger.info(`[${this.streamId}] Local socket ended`);
this.close();
});
}
setupWebSocketHandlers() {
this.unsubscribe = this.adapter.onTCPData(async (streamId, data) => {
if (streamId !== this.streamId || this.isClosed)
return;
try {
if (this.localSocket.writable) {
const writeResult = this.localSocket.write(data);
if (!writeResult) {
this.localSocket.once('drain', () => {
debug(`[${this.streamId}] Local socket drained`);
});
}
}
}
catch (error) {
logger.error(`[${this.streamId}] Failed to write to local socket:`, error);
this.close();
}
});
}
close() {
if (this.isClosed)
return;
this.isClosed = true;
if (this.unsubscribe) {
this.unsubscribe();
this.unsubscribe = undefined;
}
if (this.localSocket && !this.localSocket.destroyed) {
this.localSocket.destroy();
}
}
isClosedStream() {
return this.isClosed;
}
}
exports.TCPStreamOverWebSocket = TCPStreamOverWebSocket;