iosignal 1.6.0 → 1.7.0

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 (45) hide show
  1. package/dist/iosignal.cjs +2 -2
  2. package/dist/iosignal.esm.js +1 -1
  3. package/dist/iosignal.esm.js.map +1 -1
  4. package/dist/iosignal.min.js +1 -1
  5. package/dist/iosignal.min.js.map +1 -1
  6. package/indexWebBrowser.js +1 -1
  7. package/package.json +2 -2
  8. package/src/api/RedisAPI.js +23 -26
  9. package/src/api/api_reply.js +12 -15
  10. package/src/api/api_sudo.js +67 -72
  11. package/src/auth/Auth_Env.js +7 -9
  12. package/src/auth/Auth_File.js +31 -35
  13. package/src/auth/Auth_Redis.js +15 -21
  14. package/src/auth/BohoAuth.js +68 -72
  15. package/src/client/CongPacket.js +15 -24
  16. package/src/client/IOCongSocket.js +26 -33
  17. package/src/client/IOCore.js +6 -35
  18. package/src/client/IOWS.js +22 -23
  19. package/src/client/IOWebSocket.js +11 -7
  20. package/src/common/constants.js +21 -32
  21. package/src/common/payload.js +47 -48
  22. package/src/common/quotaTable.js +10 -10
  23. package/src/common/util.js +38 -38
  24. package/src/server/FileLogger.js +9 -9
  25. package/src/server/Manager.js +39 -55
  26. package/src/server/Metric.js +54 -53
  27. package/src/server/Remote.js +207 -0
  28. package/src/server/{ServerRemoteCore.js → RemoteCore.js} +53 -81
  29. package/src/server/Server.js +22 -25
  30. package/src/server/serverOption.js +10 -10
  31. package/test-browser/index.html +30 -26
  32. package/test-browser/server.js +1 -1
  33. package/test-client-nodejs/client.cjs +6 -6
  34. package/test-client-nodejs/client.mjs +6 -6
  35. package/test-client-nodejs/client_api_reply.mjs +8 -8
  36. package/test-client-nodejs/stateChange.mjs +7 -7
  37. package/test-server/server-Auth_Env.js +2 -2
  38. package/test-server/server-Auth_File.js +1 -1
  39. package/test-server/server-api_reply.js +2 -2
  40. package/test-server/server-api_sudo.js +3 -3
  41. package/test-server/server-esm.mjs +9 -8
  42. package/test-server/simple-server.mjs +6 -6
  43. package/test-signal-payloadType/signalPack.js +1 -1
  44. package/test-signal-payloadType/signaling.js +4 -4
  45. package/src/server/ServerRemote.js +0 -227
@@ -1,5 +1,5 @@
1
1
  import { MBP } from 'meta-buffer-pack'
2
- import { ServerRemote } from './ServerRemote.js'
2
+ import { Remote } from './Remote.js'
3
3
  import { serverOption } from './serverOption.js'
4
4
  import { IOMsg, CLIENT_STATE } from '../common/constants.js'
5
5
  import { getSignalPack } from '../common/payload.js';
@@ -9,35 +9,33 @@ import { Metric } from './Metric.js'
9
9
  const encoder = new TextEncoder()
10
10
  const decoder = new TextDecoder()
11
11
 
12
- export class Manager{
12
+ export class Manager {
13
13
 
14
- constructor( server, authManager ) {
14
+ constructor(server, authManager) {
15
15
  this.server = server;
16
16
  this.txBytes = 0;
17
17
  this.rxBytes = 0;
18
18
 
19
19
  this.authManager = authManager;
20
- // TIP. authManager module is option.
21
- // if exist: used by ServerRemoteCore for the auth. process.
22
20
 
23
21
  this.connectionLogger;
24
22
  if (serverOption.fileLogger.connection.use) {
25
- this.connectionLogger = new FileLogger( serverOption.fileLogger.connection.path)
26
- console.log('Manager: begin file logger [connection]')
23
+ this.connectionLogger = new FileLogger(serverOption.fileLogger.connection.path)
24
+ // console.log('Manager: begin file logger [connection]')
27
25
  }
28
26
 
29
27
  this.attackLogger;
30
- if( serverOption.fileLogger.attack.use ){
31
- this.attackLogger = new FileLogger( serverOption.fileLogger.attack.path )
32
- console.log('Manager: begin file logger.[attack]')
28
+ if (serverOption.fileLogger.attack.use) {
29
+ this.attackLogger = new FileLogger(serverOption.fileLogger.attack.path)
30
+ // console.log('Manager: begin file logger.[attack]')
33
31
  }
34
32
 
35
- this.remotes = new Set(); // total ServerRemotes
36
- this.channel_map = new Map() // key: channelName value: < ServerRemote : Set >
33
+ this.remotes = new Set(); // total remotes
34
+ this.cid2remote = new Map(); // key: cid -> value: remote
35
+ this.retain_messages = new Map() // key: tag, data: signalMessage
36
+ this.channel_map = new Map() // key: channelName -> value: < remote : Set >
37
37
  this.CHANNEL_PREFIX = 'CH:'
38
38
  this.CID_PREFIX = 'CID:'
39
- this.cid2remote = new Map(); // map:[ key:cid -> value:remote ]
40
- this.retain_messages = new Map() // key: tag, data: signalMessage
41
39
  this.metric = new Metric(this)
42
40
  this.lastSSID = 0;
43
41
 
@@ -56,14 +54,14 @@ export class Manager{
56
54
  } else {
57
55
  remo.ping()
58
56
  }
59
- // console.log('<< PING')
57
+
60
58
  });
61
59
  }, serverOption.timeout);
62
60
 
63
61
  if (serverOption.showMetric) {
64
62
  this.monitIntervalID = setInterval((e) => {
65
- this.monitor()
66
- }, serverOption.monitorPeriod);
63
+ this.monitor()
64
+ }, serverOption.monitorPeriod);
67
65
  }
68
66
 
69
67
 
@@ -72,7 +70,7 @@ export class Manager{
72
70
 
73
71
  addRemote(socket, req) {
74
72
  socket.isAlive = true;
75
- let remote = new ServerRemote(socket, req, this)
73
+ let remote = new Remote(socket, req, this)
76
74
  this.remotes.add(remote)
77
75
  remote.send(Buffer.from([IOMsg.SERVER_READY]))
78
76
  remote.setState(CLIENT_STATE.SENT_SERVER_READY)
@@ -84,7 +82,7 @@ export class Manager{
84
82
 
85
83
 
86
84
  removeRemote(remote) {
87
- // console.log('#### manager.removeRemote()', remote.cid, remote.uid)
85
+
88
86
  let remoteInfo = `- IP:${remote.ip} #${remote.ssid} cid:${remote.cid} ${remote?.socket.socketType === 'websocket' ? "WS" : "CS"} `
89
87
  if (this.connectionLogger) this.connectionLogger.log(remoteInfo)
90
88
  this.deligateSignal(remote, '@state', 'close')
@@ -97,16 +95,16 @@ export class Manager{
97
95
  // console.log(`-- channel [ ${ch} ] removes subscriber id: ${remote.cid} `)
98
96
  remotes.delete(remote)
99
97
  if (remotes.size == 0) this.channel_map.delete(ch)
100
- }else{
98
+ } else {
101
99
  // console.log('no such a ch: ', ch )
102
100
  }
103
101
  }
104
102
 
105
103
  // retain message policy
106
- // type 1. keep if authUser, delete if anonymouse.
107
- if( remote.boho.isAuthorized ){
104
+ // type 1. ( isAuthorizedUser) ? keep : delete.
105
+ if (remote.boho.isAuthorized) {
108
106
  //keep retain signal.
109
- }else{
107
+ } else {
110
108
  // anonymouse: remove the cid publish channel
111
109
  for (let ch of remote.retain_signal.keys()) {
112
110
  // console.log('cid retain_signal.keys:', ch )
@@ -114,17 +112,17 @@ export class Manager{
114
112
  if (this.channel_map.has(ch)) {
115
113
  this.channel_map.delete(ch)
116
114
  // console.log(`-- deleted cid pub ch [ ${ch} ]. cid publisher id: ${remote.cid} `)
117
- }else{
115
+ } else {
118
116
  // console.log('no such a retain_signal tag: ', ch )
119
117
  }
120
118
  }
121
119
  }
122
-
123
120
 
124
- if( remote.uid && this.server.apiNames.has('account')){
125
- let req = { topic:'detachUserRemote'}
121
+
122
+ if (remote.uid && this.server.apiNames.has('account')) {
123
+ let req = { topic: 'detachUserRemote' }
126
124
  req.args = ['caller:manager.removeRemote']
127
- this.server.emit('account', remote, req )
125
+ this.server.emit('account', remote, req)
128
126
  }
129
127
 
130
128
  this.remotes.delete(remote)
@@ -134,7 +132,7 @@ export class Manager{
134
132
  }
135
133
 
136
134
 
137
- // unix wall like
135
+ // it's like unix wall command.
138
136
  serverSignal(obj) {
139
137
  let sigPack = MBP.pack(
140
138
  MBP.MB('#MsgType', '8', IOMsg.SERVER_SIGNAL),
@@ -171,40 +169,38 @@ export class Manager{
171
169
  this.sender(tag, remote, sigPack)
172
170
  }
173
171
 
174
- adminSignal( cid, message){
172
+ adminSignal(cid, message) {
175
173
  if (this.cid2remote.has(cid)) {
176
174
  this.cid2remote.get(cid).send_enc_mode(message)
177
- // return ['ok', 1]
178
175
  return
179
- }else{
176
+ } else {
180
177
  return "no cid"
181
178
  }
182
179
  }
183
180
 
184
- serverSignalTo( tag, ...args ){
181
+ serverSignalTo(tag, ...args) {
185
182
  let cid = tag.split('@')[0]
186
183
  let topic = tag.split('@')[1]
187
- let sigPack = getSignalPack( '@'+topic, ...args )
188
- // console.log('tag split', cid )
184
+ let sigPack = getSignalPack('@' + topic, ...args)
189
185
  if (cid && this.cid2remote.has(cid)) {
190
186
  let targetRemote = this.cid2remote.get(cid)
191
- console.log('target', targetRemote.state ,targetRemote.cid )
187
+ console.log('target', targetRemote.state, targetRemote.cid)
192
188
  targetRemote.send_enc_mode(sigPack)
193
189
  return
194
- }else{
190
+ } else {
195
191
  return "no cid"
196
192
  }
197
193
  }
198
194
 
199
195
  sender(tag, remote, message) {
200
- if(serverOption.memberOnly && !remote.boho.isAuthorized){
196
+ if (serverOption.memberOnly && !remote.boho.isAuthorized) {
201
197
  // console.log("## MemberOnly, reject unAuthorized remote." )
202
198
  remote.send(Buffer.from([IOMsg.SERVER_CLEAR_AUTH]))
203
199
  remote.close()
204
200
  return ['err', 'not autrized']
205
201
  }
206
202
 
207
- if( tag.indexOf('$') == 0 ) return ['err', 'prefix $ is reserved for userSet tag.']
203
+ if (tag.indexOf('$') == 0) return ['err', 'prefix $ is reserved for userSet tag.']
208
204
 
209
205
  let cidIndex = tag.indexOf('@');
210
206
  if (cidIndex === 0) {
@@ -214,10 +210,8 @@ export class Manager{
214
210
  tag = remote.cid + tag;
215
211
  message = this.getNewSignalTagMessage(message, tag)
216
212
 
217
- // console.log('cid_pub new tag:', tag, this.getSignalTag(message ))
218
213
  } else if (cidIndex > 0) {
219
214
  // uni-cast.
220
- // console.log('unicast to:', tag)
221
215
  let targetCId = tag.split('@')[0];
222
216
  if (this.cid2remote.has(targetCId)) {
223
217
  //rm cid from tag.
@@ -229,8 +223,6 @@ export class Manager{
229
223
  return ['ok', 1]
230
224
  }
231
225
  return ['err', 'Invalid cid']
232
- // pub message from cid.
233
- // you already subscribe the cid.
234
226
  } else {
235
227
  // console.log('ch_pub tag:', tag)
236
228
  //else channel publish message
@@ -247,7 +239,7 @@ export class Manager{
247
239
  // (blank)#topic -> home_channel#topic.
248
240
  if (tag.indexOf('#') === 0) {
249
241
  tag = remote.HOME_CHANNEL + tag;
250
- } else if( tag.includes('@')){
242
+ } else if (tag.includes('@')) {
251
243
  tag = this.CID_PREFIX + tag;
252
244
  } else {
253
245
  tag = this.CHANNEL_PREFIX + tag;
@@ -265,11 +257,9 @@ export class Manager{
265
257
  // cid retain signal stored inside remote.
266
258
  let retainTag = tag.split('@')[1]
267
259
  remote.retain_signal.set(retainTag, message)
268
- // console.log('## cid retain tag, size: ', retainTag, remote.retain_signal.size)
269
260
  } else {
270
261
  // channel retain signal stored inside manager.
271
262
  this.retain_messages.set(tag, message)
272
- // console.log('## channel retain tag, size: ', tag, this.retain_messages.size)
273
263
  }
274
264
 
275
265
  } else {
@@ -315,11 +305,10 @@ export class Manager{
315
305
 
316
306
 
317
307
  subscribe(chArr, remote) {
318
- // console.log('ChannelManager:: subscribe: ',chArr)
319
308
  chArr.forEach(tag => {
320
309
  if (tag.indexOf('#') === 0) {
321
310
  tag = remote.HOME_CHANNEL + tag
322
- } else if( tag.includes('@')){
311
+ } else if (tag.includes('@')) {
323
312
  tag = this.CID_PREFIX + tag;
324
313
  } else {
325
314
  tag = this.CHANNEL_PREFIX + tag
@@ -331,11 +320,9 @@ export class Manager{
331
320
  } else {
332
321
  this.channel_map.set(tag, new Set([remote]))
333
322
  }
334
- // console.log('Manager::map:', this.channel_map.keys() )
335
323
 
336
324
  // 2.add to remote channels.
337
325
  remote.channels.add(tag)
338
- // console.log('remote.channels set.', remote.channels )
339
326
 
340
327
  // 3. send retain message if available.
341
328
  if (tag.includes('$')
@@ -356,8 +343,7 @@ export class Manager{
356
343
  } else if (this.retain_messages.has(tag)) {
357
344
  retainMessage = this.retain_messages.get(tag)
358
345
  }
359
- // console.log('send retainMessage buffer',retainMessage)
360
- if(retainMessage) remote.send_enc_mode(retainMessage)
346
+ if (retainMessage) remote.send_enc_mode(retainMessage)
361
347
 
362
348
  }
363
349
 
@@ -384,7 +370,7 @@ export class Manager{
384
370
  // substitution home_channel
385
371
  if (ch.indexOf('#') === 0) {
386
372
  ch = remote.HOME_CHANNEL + ch;
387
- } else if( ch.includes('@')){
373
+ } else if (ch.includes('@')) {
388
374
  ch = this.CID_PREFIX + ch;
389
375
  } else {
390
376
  ch = this.CHANNEL_PREFIX + ch;
@@ -418,13 +404,11 @@ export class Manager{
418
404
  this.metric.channels(serverOption.showChannel);
419
405
  }
420
406
  let mode = parseInt(serverOption.showMetric)
421
- console.log('monitor metric type:', mode)
422
407
  switch (mode) {
423
408
  case 1:
424
409
  this.metric.oneline(true);
425
410
  break;
426
411
  case 2:
427
- // this.metric.getCIdList(true);
428
412
  this.metric.getRemotes(true);
429
413
  break;
430
414
  case 3:
@@ -4,52 +4,52 @@ import { ENC_MODE } from '../common/constants.js'
4
4
  const MAX = 10
5
5
  let period = 10000
6
6
 
7
- export class Metric{
8
- constructor(manager){
7
+ export class Metric {
8
+ constructor(manager) {
9
9
  this.manager = manager;
10
10
 
11
- this.metricsPack= {
12
- remotes:[0],
13
- channels:[0],
14
- txBytes:[0],
15
- rxBytes:[0],
16
- unixTime: [Math.floor( Date.now() /1000)],
11
+ this.metricsPack = {
12
+ remotes: [0],
13
+ channels: [0],
14
+ txBytes: [0],
15
+ rxBytes: [0],
16
+ unixTime: [Math.floor(Date.now() / 1000)],
17
17
  period: 0
18
18
  }
19
19
 
20
- this.tickId = setInterval( e=>{
20
+ this.tickId = setInterval(e => {
21
21
 
22
- this.metricsPack.remotes.push( this.manager.remotes.size )
23
- if(this.metricsPack.remotes.length > MAX ) this.metricsPack.remotes.shift()
22
+ this.metricsPack.remotes.push(this.manager.remotes.size)
23
+ if (this.metricsPack.remotes.length > MAX) this.metricsPack.remotes.shift()
24
24
 
25
- this.metricsPack.channels.push( this.manager.channel_map.size )
26
- if(this.metricsPack.channels.length > MAX ) this.metricsPack.channels.shift()
25
+ this.metricsPack.channels.push(this.manager.channel_map.size)
26
+ if (this.metricsPack.channels.length > MAX) this.metricsPack.channels.shift()
27
27
 
28
-
29
- this.metricsPack.txBytes.push( this.manager.txBytes )
30
- if(this.metricsPack.txBytes.length > MAX ) this.metricsPack.txBytes.shift()
31
28
 
32
- this.metricsPack.rxBytes.push( this.manager.rxBytes )
33
- if(this.metricsPack.rxBytes.length > MAX ) this.metricsPack.rxBytes.shift()
29
+ this.metricsPack.txBytes.push(this.manager.txBytes)
30
+ if (this.metricsPack.txBytes.length > MAX) this.metricsPack.txBytes.shift()
34
31
 
35
- this.metricsPack.unixTime = Math.floor( Date.now() /1000)
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
36
  this.metricsPack.period = period;
37
37
  this.manager.txBytes = 0
38
38
  this.manager.rxBytes = 0
39
-
40
39
 
41
- },10000)
40
+
41
+ }, 10000)
42
42
  }
43
43
 
44
44
 
45
45
 
46
- oneline(prn){
46
+ oneline(prn) {
47
47
  let memoryUse = memoryUsage();
48
48
  let memoryInfo = [{
49
49
  ...memoryUse
50
50
  }]
51
51
 
52
- if ( prn ) console.table(memoryInfo, [ 'rss','heapTotal','heapUsed', 'external','arrayBuffers' ]);
52
+ if (prn) console.table(memoryInfo, ['rss', 'heapTotal', 'heapUsed', 'external', 'arrayBuffers']);
53
53
 
54
54
  let metric = [{
55
55
  lastSSID: this.manager.lastSSID,
@@ -59,36 +59,37 @@ export class Metric{
59
59
  rxBytes: this.manager.rxBytes,
60
60
  }]
61
61
 
62
- if ( prn ) console.table(metric, [ 'lastSSID', 'remotes', 'channels','txBytes','rxBytes' ]);
62
+ if (prn) console.table(metric, ['lastSSID', 'remotes', 'channels', 'txBytes', 'rxBytes']);
63
63
 
64
64
  return metric[0]
65
65
  }
66
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+")"
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
71
  })
72
- if (prn ) console.table(remoteStates)
72
+ if (prn) console.table(remoteStates)
73
73
  return remoteStates
74
74
  }
75
- getCIdList( prn ){
76
- let CIdList = Array.from(this.manager.cid2remote.keys())
77
- if (prn ) console.table(CIdList)
75
+
76
+ getCIdList(prn) {
77
+ let CIdList = Array.from(this.manager.cid2remote.keys())
78
+ if (prn) console.table(CIdList)
78
79
  return CIdList
79
80
  }
80
81
 
81
- getChannelList(prn){
82
- let chList = Array.from(this.manager.channel_map.keys())
83
- if (prn ) console.table(chList)
82
+ getChannelList(prn) {
83
+ let chList = Array.from(this.manager.channel_map.keys())
84
+ if (prn) console.table(chList)
84
85
  return chList
85
86
  }
86
87
 
87
- getSubscribers(ch){
88
+ getSubscribers(ch) {
88
89
  let list = [];
89
- if( this.manager.channel_map.has(ch)){
90
+ if (this.manager.channel_map.has(ch)) {
90
91
  let subscribers = this.manager.channel_map.get(ch) //set
91
- subscribers.forEach( c =>{
92
+ subscribers.forEach(c => {
92
93
  list.push(c.cid)
93
94
  })
94
95
  }
@@ -96,54 +97,54 @@ export class Metric{
96
97
  return list
97
98
  }
98
99
 
99
- getRemoteByCId( cid , mode = 1){
100
+ getRemoteByCId(cid, mode = 1) {
100
101
 
101
- if( this.manager.cid2remote.has(cid)){
102
+ if (this.manager.cid2remote.has(cid)) {
102
103
  let remote = this.manager.cid2remote.get(cid)
103
- if(mode == 1){
104
+ if (mode == 1) {
104
105
  return {
105
106
  ip: remote.ip,
106
107
  id: remote.cid,
107
108
  ssid: remote.ssid,
108
109
  cid: remote.cid,
109
- uptime: Math.trunc( ( Date.now() - remote.socket.openTime ) / 1000),
110
+ uptime: Math.trunc((Date.now() - remote.socket.openTime) / 1000),
110
111
  tx: remote.socket.txCounter,
111
112
  rx: remote.socket.rxCounter,
112
113
  txBytes: remote.socket.bytesWritten || remote.socket._socket?.bytesWritten,
113
114
  rxBytes: remote.socket.bytesRead || remote.socket._socket?.bytesRead
114
115
  }
115
- }else if( mode == 2){
116
+ } else if (mode == 2) {
116
117
  return {
117
118
  ip: remote.ip,
118
- uptime: Math.trunc( ( Date.now() - remote.socket.openTime ) / 1000),
119
+ uptime: Math.trunc((Date.now() - remote.socket.openTime) / 1000),
119
120
  nick: remote.nick,
120
121
  ssid: remote.ssid,
121
122
  echo: remote.lastEchoMessage
122
123
  }
123
- }else if( mode == 3){
124
+ } else if (mode == 3) {
124
125
  return {
125
126
  ip: remote.ip,
126
- uptime: Math.trunc( ( Date.now() - remote.socket.openTime ) / 1000),
127
+ uptime: Math.trunc((Date.now() - remote.socket.openTime) / 1000),
127
128
  nick: remote.nick,
128
129
  ssid: remote.ssid,
129
130
  isSecure: remote.TLS,
130
131
  isAuth: remote.boho.isAuthorized,
131
- encMode: ENC_MODE[remote.encMode]
132
+ encMode: ENC_MODE[remote.encMode]
132
133
  }
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() )
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())
137
138
  return {
138
139
  ip: remote.ip,
139
- uptime: Math.trunc( ( Date.now() - remote.socket.openTime ) / 1000),
140
+ uptime: Math.trunc((Date.now() - remote.socket.openTime) / 1000),
140
141
  channels: channels,
141
142
  set: set_memory,
142
143
  retain: retain_signal
143
144
  }
144
145
  }
145
146
 
146
- }else{
147
+ } else {
147
148
  return { result: "nop" }
148
149
  }
149
150
 
@@ -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
+ }