js-tcp-tunnel 1.1.1 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/lib.js +50 -78
- package/src/lib.test.js +651 -651
- package/src/types.ts +1 -1
package/package.json
CHANGED
package/src/lib.js
CHANGED
|
@@ -308,7 +308,6 @@ export function printTcpTunnelData(data) {
|
|
|
308
308
|
[TUNNEL_TCP_TYPE_CLOSE]: 'TUNNEL_TCP_TYPE_CLOSE ',
|
|
309
309
|
[TUNNEL_TCP_TYPE_PING]: 'TUNNEL_TCP_TYPE_PING ',
|
|
310
310
|
[TUNNEL_TCP_TYPE_PONG]: 'TUNNEL_TCP_TYPE_PONG ',
|
|
311
|
-
[TUNNEL_TCP_TYPE_ACK]: 'TUNNEL_TCP_TYPE_ACK ',
|
|
312
311
|
}[data.type]} recv: ${(tcpTunnelDataRecv)} send: ${(tcpTunnelDataSend)} size:${data.buffer.length}`
|
|
313
312
|
}
|
|
314
313
|
|
|
@@ -421,7 +420,6 @@ export const TUNNEL_TCP_TYPE_ERROR = 0x8117f762
|
|
|
421
420
|
export const TUNNEL_TCP_TYPE_CLOSE = 0x72fd6470
|
|
422
421
|
export const TUNNEL_TCP_TYPE_PING = 0x4768e1ba
|
|
423
422
|
export const TUNNEL_TCP_TYPE_PONG = 0x106f43fb
|
|
424
|
-
export const TUNNEL_TCP_TYPE_ACK = 0xc5870539
|
|
425
423
|
|
|
426
424
|
/**
|
|
427
425
|
* @param {TCP_TUNNEL_DATA} box
|
|
@@ -532,46 +530,15 @@ export function createTimeBufferedTransformStream(bufferTime) {
|
|
|
532
530
|
export function pipeSocketDataWithChannel(channelMap, channelId, encodeWriter) {
|
|
533
531
|
let channel = channelMap.get(channelId)
|
|
534
532
|
let socket = channel.socket
|
|
535
|
-
let signal = Promise_withResolvers()
|
|
536
|
-
signal.resolve()
|
|
537
533
|
let sendPackSize = 0
|
|
538
|
-
let remoteRecvPackSize = 0
|
|
539
|
-
channel.notify = (size) => {
|
|
540
|
-
remoteRecvPackSize = size
|
|
541
|
-
signal.resolve()
|
|
542
|
-
}
|
|
543
534
|
let [clientKey, clientIv] = channel.key_iv
|
|
544
535
|
let bufferedTransform = createTimeBufferedTransformStream(50)
|
|
545
|
-
let backPressureTimer = null
|
|
546
536
|
Readable.toWeb(socket).pipeThrough(bufferedTransform).pipeTo(new WritableStream({
|
|
547
537
|
/**
|
|
548
538
|
* @param {Uint8Array<ArrayBuffer>} chunk
|
|
549
539
|
*/
|
|
550
540
|
async write(chunk) {
|
|
551
541
|
const buffer = await encrypt(chunk, clientKey, clientIv)
|
|
552
|
-
let bufferPackSize = sendPackSize - remoteRecvPackSize
|
|
553
|
-
if (DEBUG_TUNNEL_TCP) {
|
|
554
|
-
console.warn('bufferPackSize:', bufferPackSize)
|
|
555
|
-
}
|
|
556
|
-
if (bufferPackSize > 10) {
|
|
557
|
-
signal.resolve()
|
|
558
|
-
signal = Promise_withResolvers()
|
|
559
|
-
const s = signal
|
|
560
|
-
backPressureTimer = setTimeout(() => {
|
|
561
|
-
s.resolve()
|
|
562
|
-
console.error('pipeSocketDataWithChannel timeout close channel')
|
|
563
|
-
sendPackSize = 0
|
|
564
|
-
this.close()
|
|
565
|
-
}, 10_000).unref()
|
|
566
|
-
if (DEBUG_TUNNEL_TCP) {
|
|
567
|
-
console.info('stop wait signal', ' sendPackSize:', sendPackSize, ' recvPackSize:', remoteRecvPackSize, ' bufferPackSize:', bufferPackSize)
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
await signal.promise
|
|
571
|
-
if (backPressureTimer) {
|
|
572
|
-
clearTimeout(backPressureTimer)
|
|
573
|
-
backPressureTimer = null
|
|
574
|
-
}
|
|
575
542
|
await encodeWriter.write(buildTcpTunnelData({
|
|
576
543
|
type: TUNNEL_TCP_TYPE_DATA,
|
|
577
544
|
srcId: channel.srcId,
|
|
@@ -579,10 +546,12 @@ export function pipeSocketDataWithChannel(channelMap, channelId, encodeWriter) {
|
|
|
579
546
|
dstId: channel.dstId,
|
|
580
547
|
dstChannel: channel.dstChannel,
|
|
581
548
|
buffer: buffer,
|
|
582
|
-
})).catch((err) => { console.error('web stream write error', err.message) })
|
|
549
|
+
})).catch((err) => { console.error(channelId, 'web stream write error', err.message) })
|
|
583
550
|
sendPackSize++
|
|
584
551
|
},
|
|
585
552
|
async close() {
|
|
553
|
+
channelMap.delete(channelId)
|
|
554
|
+
socket.destroy()
|
|
586
555
|
encodeWriter.write(buildTcpTunnelData({
|
|
587
556
|
type: TUNNEL_TCP_TYPE_CLOSE,
|
|
588
557
|
srcId: channel.srcId,
|
|
@@ -590,15 +559,24 @@ export function pipeSocketDataWithChannel(channelMap, channelId, encodeWriter) {
|
|
|
590
559
|
dstId: channel.dstId,
|
|
591
560
|
dstChannel: channel.dstChannel,
|
|
592
561
|
buffer: new Uint8Array(0),
|
|
593
|
-
})).catch((err) => { console.error('web stream write error', err.message) })
|
|
594
|
-
channelMap.delete(channelId)
|
|
595
|
-
socket.destroy()
|
|
562
|
+
})).catch((err) => { console.error(channelId, 'pipeSocketDataWithChannel.close web stream write error', err.message) })
|
|
596
563
|
}
|
|
597
564
|
})).catch((err) => {
|
|
598
|
-
console.error('web stream error', err.message)
|
|
565
|
+
console.error(channelId, 'pipeSocketDataWithChannel web stream error', err.message, encodeWriter.desiredSize)
|
|
566
|
+
channelMap.delete(channelId)
|
|
567
|
+
socket.destroy()
|
|
568
|
+
encodeWriter.write(buildTcpTunnelData({
|
|
569
|
+
type: TUNNEL_TCP_TYPE_CLOSE,
|
|
570
|
+
srcId: channel.srcId,
|
|
571
|
+
srcChannel: channel.srcChannel,
|
|
572
|
+
dstId: channel.dstId,
|
|
573
|
+
dstChannel: channel.dstChannel,
|
|
574
|
+
buffer: new Uint8Array(0),
|
|
575
|
+
})).catch((err) => { console.error(channelId, 'web stream write error', err.message) })
|
|
599
576
|
})
|
|
600
577
|
socket.on('error', (err) => {
|
|
601
|
-
console.error('pipeSocketDataWithChannel on error ', err.message)
|
|
578
|
+
console.error(channelId, 'pipeSocketDataWithChannel on error ', err.message)
|
|
579
|
+
channelMap.delete(channelId)
|
|
602
580
|
encodeWriter.write(buildTcpTunnelData({
|
|
603
581
|
type: TUNNEL_TCP_TYPE_ERROR,
|
|
604
582
|
srcId: channel.srcId,
|
|
@@ -606,7 +584,18 @@ export function pipeSocketDataWithChannel(channelMap, channelId, encodeWriter) {
|
|
|
606
584
|
dstId: channel.dstId,
|
|
607
585
|
dstChannel: channel.dstChannel,
|
|
608
586
|
buffer: new Uint8Array(0),
|
|
609
|
-
})).catch((err) => { console.error('web stream write error', err.message) })
|
|
587
|
+
})).catch((err) => { console.error(channelId, 'web stream write error', err.message) })
|
|
588
|
+
})
|
|
589
|
+
socket.on('close', () => {
|
|
590
|
+
console.error(channelId, 'pipeSocketDataWithChannel on close ')
|
|
591
|
+
encodeWriter.write(buildTcpTunnelData({
|
|
592
|
+
type: TUNNEL_TCP_TYPE_CLOSE,
|
|
593
|
+
srcId: channel.srcId,
|
|
594
|
+
srcChannel: channel.srcChannel,
|
|
595
|
+
dstId: channel.dstId,
|
|
596
|
+
dstChannel: channel.dstChannel,
|
|
597
|
+
buffer: new Uint8Array(0),
|
|
598
|
+
})).catch((err) => { console.error(channelId, 'pipeSocketDataWithChannel web stream write error', err.message) })
|
|
610
599
|
channelMap.delete(channelId)
|
|
611
600
|
})
|
|
612
601
|
}
|
|
@@ -710,8 +699,8 @@ async function dispatchClientBufferData(param, setup, listenKeyParamMap, channel
|
|
|
710
699
|
srcChannel: channelId,
|
|
711
700
|
dstChannel: data.srcChannel,
|
|
712
701
|
recvPackSize: 0,
|
|
702
|
+
writableNeedDrainCount: 0,
|
|
713
703
|
key_iv,
|
|
714
|
-
notify: null,
|
|
715
704
|
}
|
|
716
705
|
channelMap.set(channelId, channel)
|
|
717
706
|
connectSocket.on('connect', () => {
|
|
@@ -803,48 +792,25 @@ async function dispatchClientBufferData(param, setup, listenKeyParamMap, channel
|
|
|
803
792
|
let [clientKey, clientIv] = channel.key_iv
|
|
804
793
|
let buffer = await decrypt(data.buffer, clientKey, clientIv)
|
|
805
794
|
if (buffer.length > 0) {
|
|
806
|
-
|
|
795
|
+
channel.socket.write(buffer)
|
|
796
|
+
if (channel.socket.writableNeedDrain) {
|
|
797
|
+
channel.writableNeedDrainCount++
|
|
798
|
+
} else {
|
|
799
|
+
channel.writableNeedDrainCount = 0
|
|
800
|
+
}
|
|
801
|
+
if (channel.writableNeedDrainCount > 100) {
|
|
802
|
+
console.error(channelId, 'scoket.destroy() on writableNeedDrainCount>100', channel.writableNeedDrainCount)
|
|
803
|
+
channelMap.delete(channelId)
|
|
804
|
+
channel.socket.destroy()
|
|
805
|
+
}
|
|
807
806
|
}
|
|
808
807
|
channel.recvPackSize++
|
|
809
|
-
await sendAck(encodeWriter, channel)
|
|
810
|
-
} else {
|
|
811
|
-
await closeRemoteChannel(encodeWriter, data)
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
if (data.type == TUNNEL_TCP_TYPE_ACK) {
|
|
815
|
-
let channelId = data.dstChannel
|
|
816
|
-
let channel = channelMap.get(channelId)
|
|
817
|
-
if (channel) {
|
|
818
|
-
channel.srcId = data.dstId
|
|
819
|
-
channel.dstId = data.srcId
|
|
820
|
-
let size = readUInt32LE(data.buffer, 0)
|
|
821
|
-
channel.notify(size)
|
|
822
808
|
} else {
|
|
823
809
|
await closeRemoteChannel(encodeWriter, data)
|
|
824
810
|
}
|
|
825
811
|
}
|
|
826
812
|
}
|
|
827
813
|
|
|
828
|
-
/**
|
|
829
|
-
* @param {WritableStreamDefaultWriter<Uint8Array>} encodeWriter
|
|
830
|
-
* @param {SocketChannel} channel
|
|
831
|
-
*/
|
|
832
|
-
export async function sendAck(encodeWriter, channel) {
|
|
833
|
-
if (channel.recvPackSize % 5 != 0) {
|
|
834
|
-
return
|
|
835
|
-
}
|
|
836
|
-
let sizeBuffer = new Uint8Array(4)
|
|
837
|
-
writeUInt32LE(sizeBuffer, channel.recvPackSize, 0)
|
|
838
|
-
await encodeWriter.write(buildTcpTunnelData({
|
|
839
|
-
type: TUNNEL_TCP_TYPE_ACK,
|
|
840
|
-
srcId: channel.srcId,
|
|
841
|
-
srcChannel: channel.srcChannel,
|
|
842
|
-
dstId: channel.dstId,
|
|
843
|
-
dstChannel: channel.dstChannel,
|
|
844
|
-
buffer: sizeBuffer,
|
|
845
|
-
}))
|
|
846
|
-
}
|
|
847
|
-
|
|
848
814
|
/**
|
|
849
815
|
* @param {WritableStreamDefaultWriter<Uint8Array>} encodeWriter
|
|
850
816
|
* @param {TCP_TUNNEL_DATA} data
|
|
@@ -1060,9 +1026,15 @@ export class TunnelTcpClientHelper {
|
|
|
1060
1026
|
let server = net.createServer((socket) => {
|
|
1061
1027
|
let channelId = this.param.uniqueId++
|
|
1062
1028
|
socket.on('error', (err) => {
|
|
1063
|
-
console.error('
|
|
1029
|
+
console.error(channelId, 'TunnelTcpClientHelper.connect.onconnect socket error', err.message)
|
|
1064
1030
|
this.channelMap.delete(channelId)
|
|
1065
1031
|
})
|
|
1032
|
+
socket.on('end', () => {
|
|
1033
|
+
console.info(channelId, 'TunnelTcpClientHelper.connect.onconnect socket end')
|
|
1034
|
+
})
|
|
1035
|
+
socket.on('close', () => {
|
|
1036
|
+
console.info(channelId, 'TunnelTcpClientHelper.connect.onconnect socket close')
|
|
1037
|
+
})
|
|
1066
1038
|
/** @type{TUNNEL_TCP_DATA_CONNECT} */
|
|
1067
1039
|
let connectData = { key: sha512(param.tunnelKey) }
|
|
1068
1040
|
/** @type{SocketChannel} */
|
|
@@ -1074,8 +1046,8 @@ export class TunnelTcpClientHelper {
|
|
|
1074
1046
|
dstId: 0,
|
|
1075
1047
|
dstChannel: 0,
|
|
1076
1048
|
recvPackSize: 0,
|
|
1049
|
+
writableNeedDrainCount: 0,
|
|
1077
1050
|
key_iv,
|
|
1078
|
-
notify: null,
|
|
1079
1051
|
}
|
|
1080
1052
|
this.channelMap.set(channelId, channel)
|
|
1081
1053
|
this.encodeWriter.write(buildTcpTunnelData({
|
|
@@ -1088,7 +1060,7 @@ export class TunnelTcpClientHelper {
|
|
|
1088
1060
|
}))
|
|
1089
1061
|
}).listen(param.port)
|
|
1090
1062
|
server.on('error', (err) => {
|
|
1091
|
-
console.error('
|
|
1063
|
+
console.error('TunnelTcpClientHelper.connect server error', err.message)
|
|
1092
1064
|
})
|
|
1093
1065
|
this.param.signal.addEventListener('abort', () => { server.close() })
|
|
1094
1066
|
}
|