js-tcp-tunnel 1.1.0 → 1.1.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 +116 -77
- package/src/types.ts +9 -24
package/package.json
CHANGED
package/src/lib.js
CHANGED
|
@@ -6,9 +6,10 @@ import https from 'node:https'
|
|
|
6
6
|
import { ReadableStream, TransformStream, WritableStream } from 'node:stream/web'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
+
* @import { ReadableStreamDefaultReader, WritableStreamDefaultWriter } from 'node:stream/web'
|
|
9
10
|
* @import {WebSocketServer} from 'ws'
|
|
10
11
|
* @import Router from '@koa/router'
|
|
11
|
-
* @import {SocketChannel, TCP_TUNNEL_DATA,
|
|
12
|
+
* @import {ConnectParam, ListenParam, SocketChannel, TCP_TUNNEL_DATA, TUNNEL_TCP_DATA_CONNECT, TUNNEL_TCP_DATA_LISTEN, TUNNEL_TCP_DATA_PINGPONG, TunnelTcpClientHelperParam, TunnelTcpServerHelperParam} from './types.js'
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
const DEBUG_TUNNEL_TCP = false
|
|
@@ -871,6 +872,9 @@ export function createTunnelTcpServerHelper(param) {
|
|
|
871
872
|
if (DEBUG_TUNNEL_TCP) {
|
|
872
873
|
let writer = encodeWriter
|
|
873
874
|
encodeWriter = new WritableStream({
|
|
875
|
+
/**
|
|
876
|
+
* @param {Uint8Array<ArrayBuffer>} chunk
|
|
877
|
+
*/
|
|
874
878
|
async write(chunk) {
|
|
875
879
|
tcpTunnelDataSend += chunk.length
|
|
876
880
|
let data = parseTcpTunnelData(chunk)
|
|
@@ -881,6 +885,9 @@ export function createTunnelTcpServerHelper(param) {
|
|
|
881
885
|
}
|
|
882
886
|
|
|
883
887
|
decode.readable.pipeTo(new WritableStream({
|
|
888
|
+
/**
|
|
889
|
+
* @param {Uint8Array<ArrayBuffer>} chunk
|
|
890
|
+
*/
|
|
884
891
|
async write(chunk) {
|
|
885
892
|
try {
|
|
886
893
|
await dispatchServerBufferData(param, encodeWriter, chunk)
|
|
@@ -901,66 +908,112 @@ export function createTunnelTcpServerHelper(param) {
|
|
|
901
908
|
buffer: new Uint8Array(0),
|
|
902
909
|
}))
|
|
903
910
|
|
|
904
|
-
|
|
905
|
-
let helper = { readable: encode.readable, writable: decode.writable, reader: null, writer: null, dstId: id, }
|
|
906
|
-
return helper
|
|
911
|
+
return new TunnelTcpServerHelper(id, encode, decode)
|
|
907
912
|
}
|
|
908
913
|
|
|
909
914
|
/**
|
|
910
915
|
* @param {TunnelTcpClientHelperParam} param
|
|
911
916
|
*/
|
|
912
917
|
export function createTunnelTcpClientHelper(param) {
|
|
913
|
-
/** @type{Map<number,SocketChannel>} */
|
|
914
|
-
let channelMap = new Map()
|
|
915
|
-
|
|
916
|
-
/** @type{Map<string,{host:string;port:number;key_iv:[CryptoKey, Uint8Array<ArrayBuffer>]}>} */
|
|
917
|
-
let listenKeyParamMap = new Map()
|
|
918
|
-
|
|
919
918
|
let server_key_iv = buildKeyIv(param.serverKey, 10)
|
|
920
|
-
|
|
921
|
-
param.signal.addEventListener('abort', () => {
|
|
922
|
-
channelMap.values().forEach(o => {
|
|
923
|
-
o.socket.destroy()
|
|
924
|
-
})
|
|
925
|
-
})
|
|
926
|
-
|
|
927
919
|
let encode = createEncodeStream(server_key_iv)
|
|
928
920
|
let decode = createDecodeStream(server_key_iv)
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
921
|
+
return new TunnelTcpClientHelper(param, encode, decode)
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
export class TunnelTcpServerHelper {
|
|
925
|
+
dstId = 0
|
|
926
|
+
/** @type{ReadableStream<Uint8Array<ArrayBuffer>>} */
|
|
927
|
+
readable = null
|
|
928
|
+
/** @type{WritableStream<Uint8Array<ArrayBuffer>>} */
|
|
929
|
+
writable = null
|
|
930
|
+
/** @type{ReadableStreamDefaultReader<Uint8Array<ArrayBuffer>>} */
|
|
931
|
+
reader = null
|
|
932
|
+
/** @type{WritableStreamDefaultWriter<Uint8Array<ArrayBuffer>>} */
|
|
933
|
+
writer = null
|
|
934
|
+
/**
|
|
935
|
+
* @param {number} id
|
|
936
|
+
* @param {TransformStream<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>} encode
|
|
937
|
+
* @param {TransformStream<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>} decode
|
|
938
|
+
*/
|
|
939
|
+
constructor(id, encode, decode) {
|
|
940
|
+
this.dstId = id
|
|
941
|
+
this.readable = encode.readable
|
|
942
|
+
this.writable = decode.writable
|
|
940
943
|
}
|
|
944
|
+
}
|
|
941
945
|
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
946
|
+
export class TunnelTcpClientHelper {
|
|
947
|
+
/** @type{ReadableStream<Uint8Array<ArrayBuffer>>} */
|
|
948
|
+
readable = null
|
|
949
|
+
/** @type{WritableStream<Uint8Array<ArrayBuffer>>} */
|
|
950
|
+
writable = null
|
|
951
|
+
/** @type{ReadableStreamDefaultReader<Uint8Array<ArrayBuffer>>} */
|
|
952
|
+
reader = null
|
|
953
|
+
/** @type{WritableStreamDefaultWriter<Uint8Array<ArrayBuffer>>} */
|
|
954
|
+
writer = null
|
|
955
|
+
/** @type{TunnelTcpClientHelperParam} */
|
|
956
|
+
param = null
|
|
957
|
+
|
|
958
|
+
/** @type{Map<number,SocketChannel>} */
|
|
959
|
+
channelMap = new Map()
|
|
960
|
+
/** @type{Map<string,{host:string;port:number;key_iv:[CryptoKey, Uint8Array<ArrayBuffer>]}>} */
|
|
961
|
+
listenKeyParamMap = new Map()
|
|
962
|
+
/** @type{Set<ListenParam>} */
|
|
963
|
+
listenParams = new Set()
|
|
964
|
+
/** @type{WritableStreamDefaultWriter<Uint8Array<ArrayBuffer>>} */
|
|
965
|
+
encodeWriter = null
|
|
966
|
+
|
|
967
|
+
/**
|
|
968
|
+
* @param {TunnelTcpClientHelperParam} param
|
|
969
|
+
* @param {TransformStream<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>} encode
|
|
970
|
+
* @param {TransformStream<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>} decode
|
|
971
|
+
*/
|
|
972
|
+
constructor(param, encode, decode) {
|
|
973
|
+
this.param = param
|
|
974
|
+
this.readable = encode.readable
|
|
975
|
+
this.writable = decode.writable
|
|
976
|
+
|
|
977
|
+
param.signal.addEventListener('abort', () => {
|
|
978
|
+
this.channelMap.values().forEach(o => {
|
|
979
|
+
o.socket.destroy()
|
|
980
|
+
})
|
|
981
|
+
})
|
|
982
|
+
|
|
983
|
+
this.encodeWriter = encode.writable.getWriter()
|
|
984
|
+
if (DEBUG_TUNNEL_TCP) {
|
|
985
|
+
let writer = this.encodeWriter
|
|
986
|
+
this.encodeWriter = new WritableStream({
|
|
987
|
+
async write(chunk) {
|
|
988
|
+
tcpTunnelDataSend += chunk.length
|
|
989
|
+
let data = parseTcpTunnelData(chunk)
|
|
990
|
+
console.info('send', printTcpTunnelData(data))
|
|
991
|
+
writer.write(chunk)
|
|
992
|
+
}
|
|
993
|
+
}).getWriter()
|
|
952
994
|
}
|
|
953
|
-
}))
|
|
954
995
|
|
|
955
|
-
|
|
956
|
-
|
|
996
|
+
const thiz = this
|
|
997
|
+
decode.readable.pipeTo(new WritableStream({
|
|
998
|
+
/**
|
|
999
|
+
* @param {Uint8Array<ArrayBuffer>} buffer
|
|
1000
|
+
*/
|
|
1001
|
+
async write(buffer) {
|
|
1002
|
+
try {
|
|
1003
|
+
await dispatchClientBufferData(param, () => thiz.setup(), thiz.listenKeyParamMap, thiz.channelMap, thiz.encodeWriter, buffer)
|
|
1004
|
+
} catch (error) {
|
|
1005
|
+
console.error('decode.readable.pipeTo.write', error.message)
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
}))
|
|
1009
|
+
}
|
|
957
1010
|
|
|
958
|
-
async
|
|
959
|
-
channelMap.forEach((channel) => {
|
|
960
|
-
channel.srcId = param.clientDataId
|
|
1011
|
+
async setup() {
|
|
1012
|
+
this.channelMap.forEach((channel) => {
|
|
1013
|
+
channel.srcId = this.param.clientDataId
|
|
961
1014
|
/** @type{TUNNEL_TCP_DATA_PINGPONG} */
|
|
962
1015
|
let pingData = { time: Date.now() }
|
|
963
|
-
encodeWriter.write(buildTcpTunnelData({
|
|
1016
|
+
this.encodeWriter.write(buildTcpTunnelData({
|
|
964
1017
|
type: TUNNEL_TCP_TYPE_PING,
|
|
965
1018
|
srcId: channel.srcId,
|
|
966
1019
|
srcChannel: channel.srcChannel,
|
|
@@ -969,34 +1022,29 @@ export function createTunnelTcpClientHelper(param) {
|
|
|
969
1022
|
buffer: Uint8Array_from(JSON.stringify(pingData)),
|
|
970
1023
|
}))
|
|
971
1024
|
})
|
|
972
|
-
for (const param of listenParams) {
|
|
973
|
-
await listen(param)
|
|
1025
|
+
for (const param of this.listenParams) {
|
|
1026
|
+
await this.listen(param)
|
|
974
1027
|
}
|
|
975
1028
|
}
|
|
976
1029
|
|
|
977
1030
|
/**
|
|
978
|
-
* @param {
|
|
979
|
-
* clientKey?:string;
|
|
980
|
-
* tunnelKey:string;
|
|
981
|
-
* host?:string;
|
|
982
|
-
* port:number;
|
|
983
|
-
* }} param
|
|
1031
|
+
* @param {ListenParam} param
|
|
984
1032
|
*/
|
|
985
|
-
async
|
|
986
|
-
listenParams.add(param)
|
|
987
|
-
console.info('listenParams size', listenParams.size)
|
|
988
|
-
if (
|
|
1033
|
+
async listen(param) {
|
|
1034
|
+
this.listenParams.add(param)
|
|
1035
|
+
console.info('listenParams size', this.listenParams.size)
|
|
1036
|
+
if (this.param.clientDataId < 1) {
|
|
989
1037
|
console.info('skip send listen dataId == 0')
|
|
990
1038
|
return
|
|
991
1039
|
}
|
|
992
1040
|
let key = sha512(param.tunnelKey)
|
|
993
1041
|
let key_iv = await buildKeyIv(param.clientKey, 10)
|
|
994
|
-
listenKeyParamMap.set(key, { host: param.host, port: param.port, key_iv })
|
|
1042
|
+
this.listenKeyParamMap.set(key, { host: param.host, port: param.port, key_iv })
|
|
995
1043
|
/** @type{TUNNEL_TCP_DATA_LISTEN} */
|
|
996
1044
|
let listenData = { key: key }
|
|
997
|
-
await encodeWriter.write(buildTcpTunnelData({
|
|
1045
|
+
await this.encodeWriter.write(buildTcpTunnelData({
|
|
998
1046
|
type: TUNNEL_TCP_TYPE_LISTEN,
|
|
999
|
-
srcId:
|
|
1047
|
+
srcId: this.param.clientDataId,
|
|
1000
1048
|
srcChannel: 0,
|
|
1001
1049
|
dstId: 0,
|
|
1002
1050
|
dstChannel: 0,
|
|
@@ -1005,19 +1053,15 @@ export function createTunnelTcpClientHelper(param) {
|
|
|
1005
1053
|
}
|
|
1006
1054
|
|
|
1007
1055
|
/**
|
|
1008
|
-
* @param {
|
|
1009
|
-
* clientKey?:string;
|
|
1010
|
-
* tunnelKey: string;
|
|
1011
|
-
* port: number;
|
|
1012
|
-
* }} param
|
|
1056
|
+
* @param {ConnectParam} param
|
|
1013
1057
|
*/
|
|
1014
|
-
async
|
|
1058
|
+
async connect(param) {
|
|
1015
1059
|
let key_iv = await buildKeyIv(param.clientKey, 10)
|
|
1016
1060
|
let server = net.createServer((socket) => {
|
|
1017
|
-
let channelId =
|
|
1061
|
+
let channelId = this.param.uniqueId++
|
|
1018
1062
|
socket.on('error', (err) => {
|
|
1019
1063
|
console.error('createTunnelTcpClientHelper on socket error', err.message)
|
|
1020
|
-
channelMap.delete(channelId)
|
|
1064
|
+
this.channelMap.delete(channelId)
|
|
1021
1065
|
})
|
|
1022
1066
|
/** @type{TUNNEL_TCP_DATA_CONNECT} */
|
|
1023
1067
|
let connectData = { key: sha512(param.tunnelKey) }
|
|
@@ -1025,7 +1069,7 @@ export function createTunnelTcpClientHelper(param) {
|
|
|
1025
1069
|
let channel = {
|
|
1026
1070
|
writer: Writable.toWeb(socket).getWriter(),
|
|
1027
1071
|
socket,
|
|
1028
|
-
srcId:
|
|
1072
|
+
srcId: this.param.clientDataId,
|
|
1029
1073
|
srcChannel: channelId,
|
|
1030
1074
|
dstId: 0,
|
|
1031
1075
|
dstChannel: 0,
|
|
@@ -1033,8 +1077,8 @@ export function createTunnelTcpClientHelper(param) {
|
|
|
1033
1077
|
key_iv,
|
|
1034
1078
|
notify: null,
|
|
1035
1079
|
}
|
|
1036
|
-
channelMap.set(channelId, channel)
|
|
1037
|
-
encodeWriter.write(buildTcpTunnelData({
|
|
1080
|
+
this.channelMap.set(channelId, channel)
|
|
1081
|
+
this.encodeWriter.write(buildTcpTunnelData({
|
|
1038
1082
|
type: TUNNEL_TCP_TYPE_CONNECT,
|
|
1039
1083
|
srcId: channel.srcId,
|
|
1040
1084
|
srcChannel: channel.srcChannel,
|
|
@@ -1046,13 +1090,8 @@ export function createTunnelTcpClientHelper(param) {
|
|
|
1046
1090
|
server.on('error', (err) => {
|
|
1047
1091
|
console.error('createTunnelTcpClientHelper connect on server error', err.message)
|
|
1048
1092
|
})
|
|
1049
|
-
|
|
1093
|
+
this.param.signal.addEventListener('abort', () => { server.close() })
|
|
1050
1094
|
}
|
|
1051
|
-
|
|
1052
|
-
/** @type{TUNNEL_TCP_CLIENT_HELPER} */
|
|
1053
|
-
let helper = { readable: encode.readable, writable: decode.writable, reader: null, writer: null, listen, connect, param: outParam }
|
|
1054
|
-
return helper
|
|
1055
|
-
|
|
1056
1095
|
}
|
|
1057
1096
|
|
|
1058
1097
|
|
package/src/types.ts
CHANGED
|
@@ -58,34 +58,19 @@ export type TUNNEL_TCP_SERVER = {
|
|
|
58
58
|
encodeWriter: WritableStreamDefaultWriter<Uint8Array>
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
export type
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
dstId: number
|
|
61
|
+
export type ListenParam = {
|
|
62
|
+
clientKey?: string;
|
|
63
|
+
tunnelKey: string;
|
|
64
|
+
host?: string;
|
|
65
|
+
port: number;
|
|
67
66
|
}
|
|
68
67
|
|
|
69
|
-
export type
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
writer: WritableStreamDefaultWriter<Uint8Array<ArrayBuffer>>
|
|
74
|
-
param: TunnelTcpClientHelperParam
|
|
75
|
-
listen: (param: {
|
|
76
|
-
clientKey?: string
|
|
77
|
-
tunnelKey: string
|
|
78
|
-
host?: string
|
|
79
|
-
port: number
|
|
80
|
-
}) => Promise<void>
|
|
81
|
-
connect: (param: {
|
|
82
|
-
clientKey?: string
|
|
83
|
-
tunnelKey: string
|
|
84
|
-
port: number
|
|
85
|
-
}) => Promise<void>
|
|
68
|
+
export type ConnectParam = {
|
|
69
|
+
clientKey?: string;
|
|
70
|
+
tunnelKey: string;
|
|
71
|
+
port: number;
|
|
86
72
|
}
|
|
87
73
|
|
|
88
|
-
|
|
89
74
|
export type SocketChannel = {
|
|
90
75
|
writer: WritableStreamDefaultWriter<Uint8Array<ArrayBuffer>>
|
|
91
76
|
socket: net.Socket
|