iosignal 1.6.1 → 1.7.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 (51) hide show
  1. package/README.md +254 -247
  2. package/auth_file.json +13 -13
  3. package/auth_file.mjs +23 -23
  4. package/dist/iosignal.cjs +2 -2
  5. package/dist/iosignal.esm.js.map +1 -1
  6. package/dist/iosignal.min.js.map +1 -1
  7. package/index.js +19 -19
  8. package/indexWebBrowser.js +13 -13
  9. package/package.json +60 -59
  10. package/rollup.config.js +69 -69
  11. package/src/api/RedisAPI.js +65 -68
  12. package/src/api/api_constant.js +7 -7
  13. package/src/api/api_reply.js +31 -34
  14. package/src/api/api_sudo.js +91 -96
  15. package/src/auth/Auth_Env.js +76 -78
  16. package/src/auth/Auth_File.js +71 -75
  17. package/src/auth/Auth_Redis.js +44 -50
  18. package/src/auth/BohoAuth.js +164 -168
  19. package/src/client/CongPacket.js +141 -150
  20. package/src/client/IOCongSocket.js +81 -88
  21. package/src/client/IOCore.js +822 -851
  22. package/src/client/IOWS.js +80 -81
  23. package/src/client/IOWebSocket.js +111 -112
  24. package/src/common/constants.js +148 -159
  25. package/src/common/payload.js +81 -82
  26. package/src/common/quotaTable.js +68 -68
  27. package/src/common/util.js +61 -61
  28. package/src/server/FileLogger.js +30 -30
  29. package/src/server/Manager.js +433 -449
  30. package/src/server/Metric.js +155 -154
  31. package/src/server/Remote.js +207 -0
  32. package/src/server/{ServerRemoteCore.js → RemoteCore.js} +439 -467
  33. package/src/server/Server.js +163 -166
  34. package/src/server/serverOption.js +56 -56
  35. package/test-browser/favicon.ico +0 -0
  36. package/test-browser/index.html +96 -93
  37. package/test-browser/server.js +11 -11
  38. package/test-client-nodejs/client.cjs +17 -17
  39. package/test-client-nodejs/client.mjs +17 -17
  40. package/test-client-nodejs/client_api_reply.mjs +15 -15
  41. package/test-client-nodejs/stateChange.mjs +19 -19
  42. package/test-server/server-Auth_Env.js +19 -19
  43. package/test-server/server-Auth_File.js +12 -12
  44. package/test-server/server-api_reply.js +6 -6
  45. package/test-server/server-api_sudo.js +7 -7
  46. package/test-server/server-commonjs.cjs +8 -8
  47. package/test-server/server-esm.mjs +20 -19
  48. package/test-server/simple-server.mjs +11 -11
  49. package/test-signal-payloadType/signalPack.js +34 -34
  50. package/test-signal-payloadType/signaling.js +60 -60
  51. package/src/server/ServerRemote.js +0 -227
@@ -1,154 +1,155 @@
1
- import { memoryUsage } from 'process';
2
- import { ENC_MODE } from '../common/constants.js'
3
-
4
- const MAX = 10
5
- let period = 10000
6
-
7
- export class Metric{
8
- constructor(manager){
9
- this.manager = manager;
10
-
11
- this.metricsPack= {
12
- remotes:[0],
13
- channels:[0],
14
- txBytes:[0],
15
- rxBytes:[0],
16
- unixTime: [Math.floor( Date.now() /1000)],
17
- period: 0
18
- }
19
-
20
- this.tickId = setInterval( e=>{
21
-
22
- this.metricsPack.remotes.push( this.manager.remotes.size )
23
- if(this.metricsPack.remotes.length > MAX ) this.metricsPack.remotes.shift()
24
-
25
- this.metricsPack.channels.push( this.manager.channel_map.size )
26
- if(this.metricsPack.channels.length > MAX ) this.metricsPack.channels.shift()
27
-
28
-
29
- this.metricsPack.txBytes.push( this.manager.txBytes )
30
- if(this.metricsPack.txBytes.length > MAX ) this.metricsPack.txBytes.shift()
31
-
32
- this.metricsPack.rxBytes.push( this.manager.rxBytes )
33
- if(this.metricsPack.rxBytes.length > MAX ) this.metricsPack.rxBytes.shift()
34
-
35
- this.metricsPack.unixTime = Math.floor( Date.now() /1000)
36
- this.metricsPack.period = period;
37
- this.manager.txBytes = 0
38
- this.manager.rxBytes = 0
39
-
40
-
41
- },10000)
42
- }
43
-
44
-
45
-
46
- oneline(prn){
47
- let memoryUse = memoryUsage();
48
- let memoryInfo = [{
49
- ...memoryUse
50
- }]
51
-
52
- if ( prn ) console.table(memoryInfo, [ 'rss','heapTotal','heapUsed', 'external','arrayBuffers' ]);
53
-
54
- let metric = [{
55
- lastSSID: this.manager.lastSSID,
56
- remotes: this.manager.remotes.size,
57
- channels: this.manager.channel_map.size,
58
- txBytes: this.manager.txBytes,
59
- rxBytes: this.manager.rxBytes,
60
- }]
61
-
62
- if ( prn ) console.table(metric, [ 'lastSSID', 'remotes', 'channels','txBytes','rxBytes' ]);
63
-
64
- return metric[0]
65
- }
66
-
67
- getRemotes( prn ){
68
- let remoteList = Array.from(this.manager.remotes.values())
69
- let remoteStates = remoteList.map(v=>{
70
- return "#"+v.ssid+":"+ v.cid +"("+v.state+")"
71
- })
72
- if (prn ) console.table(remoteStates)
73
- return remoteStates
74
- }
75
- getCIdList( prn ){
76
- let CIdList = Array.from(this.manager.cid2remote.keys())
77
- if (prn ) console.table(CIdList)
78
- return CIdList
79
- }
80
-
81
- getChannelList(prn){
82
- let chList = Array.from(this.manager.channel_map.keys())
83
- if (prn ) console.table(chList)
84
- return chList
85
- }
86
-
87
- getSubscribers(ch){
88
- let list = [];
89
- if( this.manager.channel_map.has(ch)){
90
- let subscribers = this.manager.channel_map.get(ch) //set
91
- subscribers.forEach( c =>{
92
- list.push(c.cid)
93
- })
94
- }
95
- // console.log(list)
96
- return list
97
- }
98
-
99
- getRemoteByCId( cid , mode = 1){
100
-
101
- if( this.manager.cid2remote.has(cid)){
102
- let remote = this.manager.cid2remote.get(cid)
103
- if(mode == 1){
104
- return {
105
- ip: remote.ip,
106
- id: remote.cid,
107
- ssid: remote.ssid,
108
- cid: remote.cid,
109
- uptime: Math.trunc( ( Date.now() - remote.socket.openTime ) / 1000),
110
- tx: remote.socket.txCounter,
111
- rx: remote.socket.rxCounter,
112
- txBytes: remote.socket.bytesWritten || remote.socket._socket?.bytesWritten,
113
- rxBytes: remote.socket.bytesRead || remote.socket._socket?.bytesRead
114
- }
115
- }else if( mode == 2){
116
- return {
117
- ip: remote.ip,
118
- uptime: Math.trunc( ( Date.now() - remote.socket.openTime ) / 1000),
119
- nick: remote.nick,
120
- ssid: remote.ssid,
121
- echo: remote.lastEchoMessage
122
- }
123
- }else if( mode == 3){
124
- return {
125
- ip: remote.ip,
126
- uptime: Math.trunc( ( Date.now() - remote.socket.openTime ) / 1000),
127
- nick: remote.nick,
128
- ssid: remote.ssid,
129
- isSecure: remote.TLS,
130
- isAuth: remote.boho.isAuthorized,
131
- encMode: ENC_MODE[remote.encMode]
132
- }
133
- }else if( mode == 4){
134
- let channels = Array.from( remote.channels.keys() )
135
- let set_memory = Array.from( remote.memory.keys() )
136
- let retain_signal = Array.from( remote.retain_signal.keys() )
137
- return {
138
- ip: remote.ip,
139
- uptime: Math.trunc( ( Date.now() - remote.socket.openTime ) / 1000),
140
- channels: channels,
141
- set: set_memory,
142
- retain: retain_signal
143
- }
144
- }
145
-
146
- }else{
147
- return { result: "nop" }
148
- }
149
-
150
- }
151
-
152
-
153
- }
154
-
1
+ import { memoryUsage } from 'process';
2
+ import { ENC_MODE } from '../common/constants.js'
3
+
4
+ const MAX = 10
5
+ let period = 10000
6
+
7
+ export class Metric {
8
+ constructor(manager) {
9
+ this.manager = manager;
10
+
11
+ this.metricsPack = {
12
+ remotes: [0],
13
+ channels: [0],
14
+ txBytes: [0],
15
+ rxBytes: [0],
16
+ unixTime: [Math.floor(Date.now() / 1000)],
17
+ period: 0
18
+ }
19
+
20
+ this.tickId = setInterval(e => {
21
+
22
+ this.metricsPack.remotes.push(this.manager.remotes.size)
23
+ if (this.metricsPack.remotes.length > MAX) this.metricsPack.remotes.shift()
24
+
25
+ this.metricsPack.channels.push(this.manager.channel_map.size)
26
+ if (this.metricsPack.channels.length > MAX) this.metricsPack.channels.shift()
27
+
28
+
29
+ this.metricsPack.txBytes.push(this.manager.txBytes)
30
+ if (this.metricsPack.txBytes.length > MAX) this.metricsPack.txBytes.shift()
31
+
32
+ this.metricsPack.rxBytes.push(this.manager.rxBytes)
33
+ if (this.metricsPack.rxBytes.length > MAX) this.metricsPack.rxBytes.shift()
34
+
35
+ this.metricsPack.unixTime = Math.floor(Date.now() / 1000)
36
+ this.metricsPack.period = period;
37
+ this.manager.txBytes = 0
38
+ this.manager.rxBytes = 0
39
+
40
+
41
+ }, 10000)
42
+ }
43
+
44
+
45
+
46
+ oneline(prn) {
47
+ let memoryUse = memoryUsage();
48
+ let memoryInfo = [{
49
+ ...memoryUse
50
+ }]
51
+
52
+ if (prn) console.table(memoryInfo, ['rss', 'heapTotal', 'heapUsed', 'external', 'arrayBuffers']);
53
+
54
+ let metric = [{
55
+ lastSSID: this.manager.lastSSID,
56
+ remotes: this.manager.remotes.size,
57
+ channels: this.manager.channel_map.size,
58
+ txBytes: this.manager.txBytes,
59
+ rxBytes: this.manager.rxBytes,
60
+ }]
61
+
62
+ if (prn) console.table(metric, ['lastSSID', 'remotes', 'channels', 'txBytes', 'rxBytes']);
63
+
64
+ return metric[0]
65
+ }
66
+
67
+ getRemotes(prn) {
68
+ let remoteList = Array.from(this.manager.remotes.values())
69
+ let remoteStates = remoteList.map(v => {
70
+ return "#" + v.ssid + ":" + v.cid + "(" + v.state + ")"
71
+ })
72
+ if (prn) console.table(remoteStates)
73
+ return remoteStates
74
+ }
75
+
76
+ getCIdList(prn) {
77
+ let CIdList = Array.from(this.manager.cid2remote.keys())
78
+ if (prn) console.table(CIdList)
79
+ return CIdList
80
+ }
81
+
82
+ getChannelList(prn) {
83
+ let chList = Array.from(this.manager.channel_map.keys())
84
+ if (prn) console.table(chList)
85
+ return chList
86
+ }
87
+
88
+ getSubscribers(ch) {
89
+ let list = [];
90
+ if (this.manager.channel_map.has(ch)) {
91
+ let subscribers = this.manager.channel_map.get(ch) //set
92
+ subscribers.forEach(c => {
93
+ list.push(c.cid)
94
+ })
95
+ }
96
+ // console.log(list)
97
+ return list
98
+ }
99
+
100
+ getRemoteByCId(cid, mode = 1) {
101
+
102
+ if (this.manager.cid2remote.has(cid)) {
103
+ let remote = this.manager.cid2remote.get(cid)
104
+ if (mode == 1) {
105
+ return {
106
+ ip: remote.ip,
107
+ id: remote.cid,
108
+ ssid: remote.ssid,
109
+ cid: remote.cid,
110
+ uptime: Math.trunc((Date.now() - remote.socket.openTime) / 1000),
111
+ tx: remote.socket.txCounter,
112
+ rx: remote.socket.rxCounter,
113
+ txBytes: remote.socket.bytesWritten || remote.socket._socket?.bytesWritten,
114
+ rxBytes: remote.socket.bytesRead || remote.socket._socket?.bytesRead
115
+ }
116
+ } else if (mode == 2) {
117
+ return {
118
+ ip: remote.ip,
119
+ uptime: Math.trunc((Date.now() - remote.socket.openTime) / 1000),
120
+ nick: remote.nick,
121
+ ssid: remote.ssid,
122
+ echo: remote.lastEchoMessage
123
+ }
124
+ } else if (mode == 3) {
125
+ return {
126
+ ip: remote.ip,
127
+ uptime: Math.trunc((Date.now() - remote.socket.openTime) / 1000),
128
+ nick: remote.nick,
129
+ ssid: remote.ssid,
130
+ isSecure: remote.TLS,
131
+ isAuth: remote.boho.isAuthorized,
132
+ encMode: ENC_MODE[remote.encMode]
133
+ }
134
+ } else if (mode == 4) {
135
+ let channels = Array.from(remote.channels.keys())
136
+ let set_memory = Array.from(remote.memory.keys())
137
+ let retain_signal = Array.from(remote.retain_signal.keys())
138
+ return {
139
+ ip: remote.ip,
140
+ uptime: Math.trunc((Date.now() - remote.socket.openTime) / 1000),
141
+ channels: channels,
142
+ set: set_memory,
143
+ retain: retain_signal
144
+ }
145
+ }
146
+
147
+ } else {
148
+ return { result: "nop" }
149
+ }
150
+
151
+ }
152
+
153
+
154
+ }
155
+
@@ -0,0 +1,207 @@
1
+ import { pack, CongRx } from '../client/CongPacket.js'
2
+ import { RemoteCore } from './RemoteCore.js';
3
+ import { serverOption } from './serverOption.js';
4
+ import { IOMsg } from '../common/constants.js';
5
+ import * as util from '../common/util.js'
6
+
7
+ const decoder = new TextDecoder()
8
+
9
+ export class Remote extends RemoteCore {
10
+ constructor(socket, req, manager) {
11
+ super(socket, manager);
12
+ this.socketType = socket.socketType
13
+
14
+ if (this.socketType === 'websocket') {
15
+ this.TLS = req.headers["x-forwarded-proto"] === 'https' ? true : false;
16
+ this.ip = this.getRemoteIP(req);
17
+ } else {
18
+ this.TLS = false;
19
+ this.ip = this.getRemoteIP(socket.remoteAddress)
20
+ }
21
+
22
+
23
+ if (util.isPrivateIP(this.ip)) {
24
+ // connection from local or private network has default private channel.
25
+ this.HOME_CHANNEL = 'PRIVATE:'
26
+ this.privateNode = true
27
+ } else {
28
+ // The HOME_CHANNEL is defined by the global IP address value.
29
+ this.HOME_CHANNEL = 'IP:' + util.getIPv4HexString(this.ip)
30
+ }
31
+
32
+
33
+ if (this.socketType === 'websocket') {
34
+ if (serverOption.debug.slow) {
35
+ socket.on("message", this.onTimeDelayMessage.bind(this));
36
+ } else {
37
+ socket.on("message", this.onSocketMessage.bind(this));
38
+ }
39
+ socket.on("pong", this.receiveMonitor.bind(this));
40
+ socket.on("ping", this.receiveMonitor.bind(this));
41
+ socket.on("error", (e) => { console.log('Websocket error', e, e.code) });
42
+ socket.onclose = (e) => {
43
+ this.manager.removeRemote(this);
44
+ };
45
+ } else { // TCP else
46
+ this.congRx = new CongRx();
47
+ socket.on('data', data => { this.congRx.write(data) })
48
+
49
+ this.congRx.on('wrong', this.onWrongCongPacketMessage.bind(this))
50
+ // readable.pipe( destination )
51
+ // tcpSocket -> congRx(parser) -> onMessage
52
+ // socket.pipe( this.congRx )
53
+
54
+ if (serverOption.debug.slow) {
55
+ this.congRx.on('data', this.onTimeDelayMessage.bind(this))
56
+ } else {
57
+ this.congRx.on('data', this.onSocketMessage.bind(this))
58
+ }
59
+
60
+ socket.on('error', e => { console.log('TCP Socket error', e) })
61
+ socket.on('close', e => {
62
+ this.manager.removeRemote(this);
63
+ })
64
+
65
+ }
66
+ }
67
+
68
+ onWrongCongPacketMessage(message) {
69
+ /*
70
+ * three category CongSocket connection.
71
+ 1. anonymouse, tcp connection.
72
+ > no cid_req, no auth_req
73
+ > It's attacker. close it.
74
+ 2. not authorized but cid ready connnection.
75
+ > anonymouse remote client.
76
+ > allowed some wrong(broken) message. small quota.
77
+ 3. authorized remote connection.
78
+ > allowed some wrong(broken) message. large quota.
79
+ */
80
+ if (this.cid) { // category 2 and 3.
81
+ // temporary broken message.
82
+ // console.log('wrong congpack from user:', Date(), this.ip, this.ssid, this.cid)
83
+ } else {
84
+ // attacker
85
+ let msg = ""
86
+ try {
87
+ msg = decoder.decode(message)
88
+ } catch (error) {
89
+ msg += 'Len: ' + message.byteLength
90
+ }
91
+
92
+ // console.log('attacker message:', attackMsg)
93
+ if (this.manager.attackLogger) {
94
+ let attackMsg = `> ${this.ssid} ${this.ip} ${msg}`
95
+ this.manager.attackLogger.log(attackMsg)
96
+ }
97
+
98
+ this.close(true);
99
+ }
100
+ }
101
+
102
+
103
+ permissionChecker() {
104
+ // type1.
105
+ // accept some traffic before authorize.
106
+ const limitBytes = 100
107
+
108
+ let txBytes = this.socket.bytesWritten || this.socket._socket?.bytesWritten
109
+ let rxBytes = this.socket.bytesRead || this.socket._socket?.bytesRead
110
+
111
+ if (txBytes == undefined) txBytes = 0
112
+ if (rxBytes == undefined) rxBytes = 0
113
+
114
+ }
115
+
116
+
117
+ // any type of received messages: message, ping, pong
118
+ receiveMonitor() {
119
+ this.socket.rxCounter++
120
+ this.socket.isAlive = true;
121
+ }
122
+
123
+ isConnectionHTTPS(req) {
124
+ //In case of reverse proxy environment. i.e. using nginx proxy_pass.
125
+ return req.headers["x-forwarded-proto"]; //https or undefined
126
+ }
127
+
128
+ getRemoteIP(req) { //req or ip string
129
+ let ip;
130
+ if (req && req.headers) {
131
+ ip = req.headers["x-forwarded-for"];
132
+ if (ip == undefined) ip = req.socket.remoteAddress;
133
+ } else {
134
+ ip = req;
135
+ }
136
+
137
+ if (ip) {
138
+ if (ip.indexOf("::ffff:") == 0) ip = ip.substring(7);
139
+ if (ip == "::1") ip = "127.0.0.1";
140
+ } else {
141
+ ip = "0.0.0.0";
142
+ }
143
+ return ip;
144
+ }
145
+
146
+ ping() {
147
+ if (this.socketType === 'websocket') {
148
+ this.socket.ping()
149
+ this.socket.txCounter++
150
+ } else {
151
+ this.send(Buffer.from([IOMsg.PING]))
152
+ }
153
+ }
154
+
155
+ pong() {
156
+ if (this.socketType === 'websocket') {
157
+ this.socket.pong()
158
+ this.socket.txCounter++
159
+ } else {
160
+ this.send(Buffer.from([IOMsg.PONG]))
161
+ }
162
+ }
163
+
164
+ getTraffic() {
165
+ let txb = this.socket.bytesWritten || this.socket._socket?.bytesWritten
166
+ let rxb = this.socket.bytesRead || this.socket._socket?.bytesRead
167
+ let tx = this.socket.txCounter
168
+ let rx = this.socket.rxCounter
169
+ let traffic = { tx, txb, rx, rxb }
170
+ }
171
+
172
+ close(terminateNow = false) {
173
+ this.getTraffic()
174
+ if (this.socketType === 'websocket') {
175
+ if (terminateNow) this.socket.terminate();
176
+ else this.socket.close();
177
+ } else {
178
+ if (terminateNow) this.socket.destroy();
179
+ else this.socket.end();
180
+ }
181
+ }
182
+
183
+ send(message, isBinary) {
184
+ this.manager.txBytes += message.byteLength;
185
+ this.socket.txCounter++;
186
+ if (this.socketType === 'websocket') {
187
+ if (this.socket.readyState === 1) {
188
+ if (isBinary != undefined) {
189
+ this.socket.send(message, { binary: isBinary });
190
+ } else {
191
+ this.socket.send(message);
192
+ }
193
+ } else {
194
+ this.close(true)
195
+ }
196
+
197
+ } else { //CongSocket
198
+ if (this.socket.readyState == 'open') {
199
+ this.socket.write(pack(message))
200
+ } else {
201
+ this.close(true)
202
+ }
203
+ }
204
+
205
+ }
206
+
207
+ }