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.
Files changed (3) hide show
  1. package/package.json +1 -1
  2. package/src/lib.js +116 -77
  3. package/src/types.ts +9 -24
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-tcp-tunnel",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "js tcp tunnel",
5
5
  "main": "index.js",
6
6
  "type": "module",
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, TUNNEL_TCP_CLIENT_HELPER, TUNNEL_TCP_DATA_CONNECT, TUNNEL_TCP_DATA_LISTEN, TUNNEL_TCP_DATA_PINGPONG, TUNNEL_TCP_SERVER_HELPER, TunnelTcpClientHelperParam, TunnelTcpServerHelperParam} from './types.js'
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
- /** @type{TUNNEL_TCP_SERVER_HELPER} */
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
- let encodeWriter = encode.writable.getWriter()
930
- if (DEBUG_TUNNEL_TCP) {
931
- let writer = encodeWriter
932
- encodeWriter = new WritableStream({
933
- async write(chunk) {
934
- tcpTunnelDataSend += chunk.length
935
- let data = parseTcpTunnelData(chunk)
936
- console.info('send', printTcpTunnelData(data))
937
- writer.write(chunk)
938
- }
939
- }).getWriter()
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
- decode.readable.pipeTo(new WritableStream({
943
- /**
944
- * @param {Uint8Array<ArrayBuffer>} buffer
945
- */
946
- async write(buffer) {
947
- try {
948
- await dispatchClientBufferData(param, setup, listenKeyParamMap, channelMap, encodeWriter, buffer)
949
- } catch (error) {
950
- console.error('decode.readable.pipeTo.write', error.message)
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
- let outParam = param
956
- let listenParams = new Set()
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 function setup() {
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 function listen(param) {
986
- listenParams.add(param)
987
- console.info('listenParams size', listenParams.size)
988
- if (outParam.clientDataId < 1) {
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: outParam.clientDataId,
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 function connect(param) {
1058
+ async connect(param) {
1015
1059
  let key_iv = await buildKeyIv(param.clientKey, 10)
1016
1060
  let server = net.createServer((socket) => {
1017
- let channelId = outParam.uniqueId++
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: outParam.clientDataId,
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
- outParam.signal.addEventListener('abort', () => { server.close() })
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 TUNNEL_TCP_SERVER_HELPER = {
62
- readable: ReadableStream<Uint8Array<ArrayBuffer>>
63
- writable: WritableStream<Uint8Array<ArrayBuffer>>
64
- reader: ReadableStreamDefaultReader<Uint8Array<ArrayBuffer>>
65
- writer: WritableStreamDefaultWriter<Uint8Array<ArrayBuffer>>
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 TUNNEL_TCP_CLIENT_HELPER = {
70
- readable: ReadableStream<Uint8Array<ArrayBuffer>>
71
- writable: WritableStream<Uint8Array<ArrayBuffer>>
72
- reader: ReadableStreamDefaultReader<Uint8Array<ArrayBuffer>>
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