iosignal 4.10.0 → 5.0.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.
@@ -77,6 +77,7 @@ export class IOCore extends EventEmitter<string | symbol, any> {
77
77
  * @type {Boho}
78
78
  */
79
79
  boho: Boho;
80
+ serverTimeNonce: any;
80
81
  /**
81
82
  * Indicates if the connection is TLS (wss).
82
83
  * @type {boolean}
@@ -74,6 +74,6 @@ export default class IO extends IOCore {
74
74
  socket_send(data: BufferSource): void;
75
75
  }
76
76
  export type Boho = import("boho").Boho;
77
- export type MBP = any;
77
+ export type MBP = typeof import("meta-buffer-pack");
78
78
  export type Buffer = import("boho").Buffer;
79
79
  import { IOCore } from "../IOCore.js";
@@ -2,11 +2,14 @@ export type STATE = {
2
2
  CONNECTING: number;
3
3
  OPEN: number;
4
4
  SERVER_READY: number;
5
- AUTH_ACK: number;
6
- CLOSING: number;
7
- READY: number;
5
+ AUTH_REQ: number;
6
+ AUTH_RES: number;
8
7
  AUTH_FAIL: number;
9
8
  AUTH_CLEAR: number;
9
+ CID_REQ: number;
10
+ CID_RES: number;
11
+ READY: number;
12
+ CLOSING: number;
10
13
  CLOSED: number;
11
14
  STOP: number;
12
15
  REDIRECTING: number;
@@ -16,9 +19,7 @@ export namespace STATE {
16
19
  let OPEN: number;
17
20
  let SERVER_READY: number;
18
21
  let AUTH_REQ: number;
19
- let AUTH_NONCE: number;
20
- let AUTH_HMAC: number;
21
- let AUTH_ACK: number;
22
+ let AUTH_RES: number;
22
23
  let AUTH_FAIL: number;
23
24
  let AUTH_CLEAR: number;
24
25
  let CID_REQ: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iosignal",
3
- "version": "4.10.0",
3
+ "version": "5.0.1",
4
4
  "description": "iosignal",
5
5
  "type": "module",
6
6
  "exports": {
@@ -37,7 +37,7 @@
37
37
  "typescript": "^5.8.3"
38
38
  },
39
39
  "dependencies": {
40
- "boho": "^1.1.1",
40
+ "boho": "^2.0.0",
41
41
  "eventemitter3": "^5.0.1",
42
42
  "meta-buffer-pack": "^2.1.0",
43
43
  "ws": "^8.18.3"
@@ -34,10 +34,10 @@ export class BohoAuth {
34
34
  }
35
35
 
36
36
 
37
- async verify_auth_hmac(auth_hmac, peer) {
37
+ async verify_auth_req(auth_req, peer) {
38
38
  try {
39
39
  //1. unpack
40
- let infoPack = MBP.unpack(auth_hmac, Boho.Meta.AUTH_HMAC)
40
+ let infoPack = MBP.unpack(auth_req, Boho.Meta.AUTH_REQ)
41
41
  if (!infoPack) {
42
42
  this.send_auth_fail(peer, 'unpack auth_pack fail');
43
43
  return
@@ -75,8 +75,8 @@ export class BohoAuth {
75
75
  }
76
76
 
77
77
  //3. check hmac
78
- let auth_ack = peer.boho.check_auth_hmac(infoPack)
79
- if (!auth_ack) {
78
+ let auth_res = peer.boho.verify_auth_req(infoPack)
79
+ if (!auth_res) {
80
80
  this.send_auth_fail(peer, 'hmac dismatched');
81
81
  return
82
82
  }
@@ -99,8 +99,12 @@ export class BohoAuth {
99
99
  )
100
100
  if (this.keepOldConnection) { // default true
101
101
  // keep old connection. reject new connection by sending auth_fail signal.
102
- this.send_auth_fail(peer, 'duplicate login')
103
102
  // peer.send(authClearSignal)
103
+ if( peer.socketType == 'websocket'){
104
+ this.send_auth_fail(peer, 'duplicate login')
105
+ }else{
106
+ peer.close(); //arduino
107
+ }
104
108
  } else {
105
109
  // accept new connection. stop the old connection by sending auth_clear signal.
106
110
  old.send(authClearSignal)
@@ -145,8 +149,8 @@ export class BohoAuth {
145
149
  //9. set cid2remote
146
150
  peer.manager.cid2remote.set(peer.cid, peer)
147
151
  //10. send ack.
148
- peer.send(auth_ack)
149
- peer.setState(STATE.AUTH_ACK)
152
+ peer.send(auth_res)
153
+ peer.setState(STATE.AUTH_RES)
150
154
  if (this.authLogger) {
151
155
  let peerInfo = `OK #${peer.ssid} cid: ${peer.cid} did:${peer.did}`
152
156
  if (peer.isAdmin) peerInfo = "#ADMIN# " + peerInfo
@@ -154,7 +158,7 @@ export class BohoAuth {
154
158
  }
155
159
  return authInfo
156
160
  } catch (error) {
157
- console.log('verify_auth_hmac error', error)
161
+ console.log('verify_auth_req error', error)
158
162
  this.send_auth_fail(peer, '[BohoAuth]caught: unknown error:' + error);
159
163
  }
160
164
  }
@@ -114,6 +114,8 @@ export class IOCore extends EventEmitter {
114
114
  * @type {Boho}
115
115
  */
116
116
  this.boho = new Boho()
117
+
118
+ this.serverTimeNonce = Buffer.alloc( Boho.MetaSize.SERVER_TIME_NONCE );
117
119
  /**
118
120
  * Indicates if the connection is TLS (wss).
119
121
  * @type {boolean}
@@ -345,10 +347,13 @@ export class IOCore extends EventEmitter {
345
347
  * @returns {this}
346
348
  */
347
349
  login(id, key) {
348
- this.auth(id, key)
349
- this.useAuth = true
350
- let auth_pack = this.boho.auth_req()
351
- this.send(auth_pack)
350
+ if( this.serverTimeNonce ){
351
+ console.log('iosignal.login serverTimeNonce', this.serverTimeNonce)
352
+ this.auth(id, key)
353
+ this.useAuth = true
354
+ let auth_pack = this.boho.auth_req(this.serverTimeNonce )
355
+ this.send(auth_pack)
356
+ }
352
357
  return this
353
358
  }
354
359
 
@@ -497,12 +502,15 @@ export class IOCore extends EventEmitter {
497
502
  this.redirect(url)
498
503
  break;
499
504
 
500
- case IOMsg.SERVER_READY:
505
+ case Boho.BohoMsg.SERVER_TIME_NONCE: // SERVER_READY
501
506
  this.stateChange('server_ready', 'server_ready')
502
507
  if (this.useAuth) {
503
- this.send(this.boho.auth_req())
504
- // CID_REQ will be called, after auth_ack.
508
+ this.send(this.boho.auth_req(buffer))
509
+ this.stateChange('auth_req','auth_req')
510
+ // CID_REQ will be called, after auth_res.
505
511
  } else {
512
+ // keep server_time_nonce for manual login()
513
+ buffer.copy( this.serverTimeNonce);
506
514
  // CID_REQ here, if not using auth.
507
515
  this.send(Buffer.from([IOMsg.CID_REQ]))
508
516
  }
@@ -549,6 +557,7 @@ export class IOCore extends EventEmitter {
549
557
  > cid_sub message: tag includes cid and @ both : 'cid@*'
550
558
  > ch_sub message: else.
551
559
  */
560
+ // console.log('payloadType', payloadType )
552
561
  switch (payloadType) {
553
562
 
554
563
  case PAYLOAD_TYPE.EMPTY:
@@ -625,26 +634,16 @@ export class IOCore extends EventEmitter {
625
634
  this.testPromise(buffer)
626
635
  break;
627
636
 
628
- case Boho.BohoMsg.AUTH_NONCE:
629
- this.stateChange('auth_nonce','server sent auth_nonce.')
630
- let auth_hmac = this.boho.auth_hmac(buffer)
631
- if (auth_hmac) {
632
- this.send(auth_hmac)
633
- } else {
634
- this.stateChange('auth_fail', 'boho.auth_hmac() invalid auth_nonce.')
635
- }
636
- break;
637
-
638
637
  case Boho.BohoMsg.AUTH_FAIL:
639
638
  this.stateChange('auth_fail', 'auth_fail from server.')
640
639
  break;
641
640
 
642
- case Boho.BohoMsg.AUTH_ACK:
643
- if (this.boho.check_auth_ack_hmac(buffer)) {
644
- this.stateChange('auth_ack', 'server sent auth_ack')
641
+ case Boho.BohoMsg.AUTH_RES:
642
+ if (this.boho.verify_auth_res(buffer)) {
643
+ this.stateChange('auth_res', 'server sent auth_res')
645
644
  this.send(Buffer.from([IOMsg.CID_REQ]))
646
645
  } else {
647
- this.stateChange('auth_fail', 'check_auth_ack_hmac() invalid server_hmac')
646
+ this.stateChange('auth_fail', 'verify_auth_res() invalid server_hmac')
648
647
  }
649
648
  break;
650
649
 
@@ -872,6 +871,7 @@ export class IOCore extends EventEmitter {
872
871
  */
873
872
  signal_e2e(tag, data, key) {
874
873
 
874
+ if( !this.boho.isAuthorized ) return;
875
875
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
876
876
  let tagEncoded = encoder.encode(tag)
877
877
  let dataPack = MBP.B8(data)
@@ -4,11 +4,13 @@
4
4
  * @property {number} CONNECTING
5
5
  * @property {number} OPEN
6
6
  * @property {number} SERVER_READY
7
- * @property {number} AUTH_ACK
8
- * @property {number} CLOSING
9
- * @property {number} READY
7
+ * @property {number} AUTH_REQ
8
+ * @property {number} AUTH_RES
10
9
  * @property {number} AUTH_FAIL
11
10
  * @property {number} AUTH_CLEAR
11
+ * @property {number} CID_REQ
12
+ * @property {number} CID_RES
13
+ * @property {number} READY
12
14
  * @property {number} CLOSING
13
15
  * @property {number} CLOSED
14
16
  * @property {number} STOP
@@ -20,11 +22,10 @@ export const STATE = {
20
22
  OPEN: 1,
21
23
  SERVER_READY: 10,
22
24
  AUTH_REQ: 11,
23
- AUTH_NONCE: 12,
24
- AUTH_HMAC: 13,
25
- AUTH_ACK: 14,
26
- AUTH_FAIL: 15,
27
- AUTH_CLEAR: 16,
25
+ AUTH_RES: 12,
26
+ AUTH_FAIL: 13,
27
+ AUTH_CLEAR: 14,
28
+
28
29
  CID_REQ: 17,
29
30
  CID_RES: 18,
30
31
  READY: 19,
@@ -139,15 +140,7 @@ export let IOMsg = {
139
140
 
140
141
  // DO NOT USE: 0xB0~ 0xBF
141
142
  // Boho module using this numbers.
142
- // AUTH_REQ : 0xB0,
143
- // AUTH_NONCE: 0xB1,
144
- // AUTH_HMAC: 0xB2,
145
- // AUTH_ACK: 0xB3,
146
- // AUTH_FAIL: 0xB4,
147
- // AUTH_EXT: 0xB5,
148
- // ENC_PACK : 0xB6,
149
- // ENC_E2E : 0xB7,
150
- // ENC_488 : 0xB8
143
+
151
144
  // reserved ~0xBF
152
145
 
153
146
  // C. IO status contorl.
@@ -4,7 +4,7 @@ import { serverOption } from './serverOption.js'
4
4
  import { IOMsg, STATE } from '../common/constants.js'
5
5
  import { getSignalPack } from '../common/payload.js';
6
6
  import { FileLogger } from './FileLogger.js'
7
- import { Metric } from './Metric.js'
7
+ import { Metrics } from './Metrics.js'
8
8
 
9
9
  const encoder = new TextEncoder()
10
10
  const decoder = new TextDecoder()
@@ -36,7 +36,7 @@ export class Manager {
36
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.metric = new Metric(this)
39
+ this.metrics = new Metrics(this)
40
40
  this.lastSSID = 0;
41
41
 
42
42
  this.pingIntervalID = setInterval(e => {
@@ -72,7 +72,8 @@ export class Manager {
72
72
  socket.isAlive = true;
73
73
  let remote = new Remote(socket, req, this)
74
74
  this.remotes.add(remote)
75
- remote.send(Buffer.from([IOMsg.SERVER_READY]))
75
+ remote.send( remote.boho.server_time_nonce() )
76
+ remote.send( Buffer.from([ IOMsg.SERVER_READY]) )
76
77
  remote.setState(STATE.SERVER_READY)
77
78
  this.lastSSID = remote.ssid;
78
79
  let connectionInfo = `+ IP:${remote.ip} #${remote.ssid} ${socket.socketType === 'websocket' ? "WS" : "CS"} `;
@@ -402,18 +403,18 @@ export class Manager {
402
403
  }
403
404
 
404
405
  if (serverOption.showChannel > 0) {
405
- this.metric.channels(serverOption.showChannel);
406
+ this.metrics.channels(serverOption.showChannel);
406
407
  }
407
408
  let mode = parseInt(serverOption.showMetric)
408
409
  switch (mode) {
409
410
  case 1:
410
- this.metric.oneline(true);
411
+ this.metrics.oneline(true);
411
412
  break;
412
413
  case 2:
413
- this.metric.getRemotes(true);
414
+ this.metrics.getRemotes(true);
414
415
  break;
415
416
  case 3:
416
- this.metric.getChannelList(true);
417
+ this.metrics.getChannelList(true);
417
418
  break;
418
419
  default:
419
420
  }
@@ -0,0 +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 Metrics {
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
+ uid: remote.uid,
111
+ uptime: Math.trunc((Date.now() - remote.socket.openTime) / 1000),
112
+ tx: remote.socket.txCounter,
113
+ rx: remote.socket.rxCounter,
114
+ txBytes: remote.socket.bytesWritten || remote.socket._socket?.bytesWritten,
115
+ rxBytes: remote.socket.bytesRead || remote.socket._socket?.bytesRead
116
+ }
117
+ } else if (mode == 2) {
118
+ return {
119
+ ip: remote.ip,
120
+ uptime: Math.trunc((Date.now() - remote.socket.openTime) / 1000),
121
+ nick: remote.nick,
122
+ ssid: remote.ssid
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
+
@@ -27,7 +27,7 @@ export class RemoteCore {
27
27
  this.ssid = RemoteCore.ssid++; // ordered index number
28
28
  this.manager = manager;
29
29
 
30
- this.cid = ''; // Communication Id
30
+ this.cid = ''; // Client Id
31
31
  this.did = ''; // Device Id
32
32
  this.uid = ''; // User Id
33
33
  this.nick = ''
@@ -50,7 +50,7 @@ export class RemoteCore {
50
50
  this.state = state
51
51
  if (serverOption.debug.showAuthInfo) {
52
52
  this.stateLog.push( state + ":" + STATE[ state] )
53
- if( state == STATE.AUTH_ACK){
53
+ if( state == STATE.AUTH_RES){
54
54
  console.log('[auth success]', this.cid, this.stateLog.join('>'))
55
55
  }else if( state == STATE.AUTH_FAIL){
56
56
  console.log('[auth_fail]',this.stateLog.join('>'))
@@ -291,29 +291,16 @@ export class RemoteCore {
291
291
  break;
292
292
 
293
293
 
294
- // Auth
294
+ // client's auth requst
295
295
  case Boho.BohoMsg.AUTH_REQ:
296
296
  if (!this.manager.authManager) return
297
297
  if (this.state < STATE.SERVER_READY) {
298
- console.log('protocol error. auth_req before server_ready')
298
+ console.log('protocol error. must called auth_req after server_ready')
299
299
  this.close();
300
300
  }
301
301
  this.setState(STATE.AUTH_REQ)
302
- let auth_nonce_pack = this.boho.auth_nonce()
303
- // console.log('## auth_nonce_pack', auth_nonce_pack )
304
- this.send(auth_nonce_pack)
305
- this.setState(STATE.AUTH_NONCE)
306
- break;
307
-
308
- case Boho.BohoMsg.AUTH_HMAC:
309
- if (!this.manager.authManager) return
310
- if (this.state < STATE.AUTH_NONCE) {
311
- console.log('protocol error. auth_hmac before server_nonce')
312
- this.close();
313
- }
314
- this.setState(STATE.AUTH_HMAC)
315
302
  //async
316
- this.manager.authManager.verify_auth_hmac(message, this)
303
+ this.manager.authManager.verify_auth_req(message, this)
317
304
  .then(authInfo => {
318
305
  if (authInfo?.name) {
319
306
  this.manager.deligateSignal(this, '@$name', authInfo.name)
@@ -321,7 +308,7 @@ export class RemoteCore {
321
308
  // this.manager.sender('@$name', authInfo.name )
322
309
  }
323
310
 
324
- // console.log('[VERIFY AUTH_HMAC] SubClass of BohoAuth return authInfo:', authInfo )
311
+ // console.log('[VERIFY AUTH_REQ] SubClass of BohoAuth return authInfo:', authInfo )
325
312
  })
326
313
  .catch(e => {
327
314
  console.log('authInfo return fail.', e )
@@ -131,25 +131,25 @@ export class Server extends EventEmitter {
131
131
 
132
132
  /**
133
133
  * RPC service register.
134
- * target: service_name <string>
135
- * service: service_module <function module|class instance>
134
+ * service: service_name <string>
135
+ * service_module <function module|class instance>
136
136
  * return this
137
137
  */
138
- attach(target, service_module) {
138
+ attach(service, service_module) {
139
139
 
140
- if( typeof target !== 'string'){
141
- throw new Error(`service( target ,service ) target name is not a string.`)
140
+ if( typeof service !== 'string'){
141
+ throw new Error(`attach service name is not a string.`)
142
142
  }
143
143
  if (!service_module.checkPermission || typeof service_module.checkPermission != 'function') {
144
- throw new Error(`Service ${target} : no checkPermission or not a function.`)
144
+ throw new Error(`Service ${service} : no checkPermission or not a function.`)
145
145
  }
146
146
  if(!service_module.commands || !Array.isArray(service_module.commands) ){
147
- throw new Error(`Service ${target} : no commands or !Array.`)
147
+ throw new Error(`Service ${service} : no commands or !Array.`)
148
148
  }
149
149
 
150
150
  // Service TYPE 1. single call() function.
151
151
  if ( service_module.call && typeof service_module.call == 'function' ) {
152
- this.on(target, (remote, req) => {
152
+ this.on(service, (remote, req) => {
153
153
  try {
154
154
  if (!service_module.checkPermission(remote, req)) {
155
155
  remote.response(req.mid, STATUS.ERROR, "NO_PERMISSION.")
@@ -162,13 +162,13 @@ export class Server extends EventEmitter {
162
162
  remote.response(req.mid, STATUS.ERROR, "UNKNOWN_COMMAND");
163
163
  }
164
164
  } catch (error) {
165
- console.error(`Unhandled Service Error in target [${target}]:`, error);
165
+ console.error(`Unhandled Service Error in service [${service}]:`, error);
166
166
  remote.response(req.mid, STATUS.ERROR, "INTERNAL_SERVER_ERROR");
167
167
  }
168
168
  })
169
169
  } else {
170
170
  // Service TYPE 2. multiple functions.
171
- this.on(target, (remote, req) => {
171
+ this.on(service, (remote, req) => {
172
172
  try {
173
173
  if (!service_module.checkPermission(remote, req)) {
174
174
  remote.response(req.mid, STATUS.ERROR, "NO_PERMISSION.")
@@ -180,13 +180,13 @@ export class Server extends EventEmitter {
180
180
  remote.response(req.mid, STATUS.ERROR, "UNKNOWN_COMMAND");
181
181
  }
182
182
  } catch (error) {
183
- console.error(`Unhandled Service Error in target [${target}]:`, error);
183
+ console.error(`Unhandled Service Error in service [${service}]:`, error);
184
184
  remote.response(req.mid, STATUS.ERROR, "INTERNAL_SERVER_ERROR");
185
185
  }
186
186
  })
187
187
  }
188
- this.serviceNames.add(target)
189
- // console.log(`[Service attached: ${target} ] accept commands: ${service_module.commands}`)
188
+ this.serviceNames.add(service)
189
+ // console.log(`[Service attached: ${service} ] accept commands: ${service_module.commands}`)
190
190
  return this
191
191
  }
192
192
 
@@ -21,18 +21,18 @@ export async function call(remote, req) {
21
21
  let cmd = req.topic;
22
22
  cmd = cmd.toLowerCase()
23
23
  if (cmd == 'cid') {
24
- result = remote.manager.metric.getCIdList()
24
+ result = remote.manager.metrics.getCIdList()
25
25
  } else if (cmd == 'remotes' || cmd == 'clients') {
26
- result = remote.manager.metric.getRemotes()
26
+ result = remote.manager.metrics.getRemotes()
27
27
  } else if (cmd == 'channels') {
28
- result = remote.manager.metric.getChannelList()
28
+ result = remote.manager.metrics.getChannelList()
29
29
  } else if (cmd == 'subscribers') {
30
30
  let ch = req.$[0]
31
- if (ch) result = remote.manager.metric.getSubscribers(ch)
31
+ if (ch) result = remote.manager.metrics.getSubscribers(ch)
32
32
  } else if (cmd == 'remote' || cmd == 'client') {
33
33
  let cid = req.$[0]
34
34
  let mode = req.$[1]
35
- if (cid) result = remote.manager.metric.getRemoteByCId(cid, mode)
35
+ if (cid) result = remote.manager.metrics.getRemoteByCId(cid, mode)
36
36
 
37
37
  } else if (cmd == 'close') {
38
38
  if (req.$[0]) result = remote.manager.closeRemoteByCId(req.$[0])