iosignal 1.4.1 → 1.5.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.
- package/README.md +247 -240
- package/auth_file.json +13 -13
- package/auth_file.mjs +23 -23
- package/dist/iosignal.cjs +1 -1
- package/dist/iosignal.esm.js.map +1 -1
- package/dist/iosignal.min.js.map +1 -1
- package/index.js +19 -19
- package/indexWebBrowser.js +13 -13
- package/package.json +59 -60
- package/rollup.config.js +69 -69
- package/src/api/RedisAPI.js +68 -68
- package/src/api/api_constant.js +7 -7
- package/src/api/api_reply.js +34 -34
- package/src/api/api_sudo.js +96 -96
- package/src/auth/Auth_Env.js +78 -78
- package/src/auth/Auth_File.js +75 -75
- package/src/auth/Auth_Redis.js +50 -50
- package/src/auth/BohoAuth.js +168 -168
- package/src/client/CongPacket.js +150 -150
- package/src/client/IOCongSocket.js +88 -88
- package/src/client/IOCore.js +851 -851
- package/src/client/IOWS.js +81 -81
- package/src/client/IOWebSocket.js +95 -95
- package/src/common/constants.js +159 -159
- package/src/common/payload.js +82 -82
- package/src/common/quotaTable.js +68 -68
- package/src/common/util.js +61 -61
- package/src/server/FileLogger.js +30 -30
- package/src/server/Manager.js +449 -456
- package/src/server/Metric.js +154 -154
- package/src/server/Server.js +166 -148
- package/src/server/ServerRemote.js +227 -227
- package/src/server/ServerRemoteCore.js +467 -467
- package/src/server/serverOption.js +56 -55
- package/test-browser/favicon.ico +0 -0
- package/test-browser/index.html +92 -92
- package/test-browser/server.js +11 -11
- package/test-client-nodejs/client.cjs +17 -17
- package/test-client-nodejs/client.mjs +17 -17
- package/test-client-nodejs/client_api_reply.mjs +15 -15
- package/test-client-nodejs/stateChange.mjs +19 -19
- package/test-server/server-Auth_Env.js +19 -19
- package/test-server/server-Auth_File.js +12 -12
- package/test-server/server-api_reply.js +6 -6
- package/test-server/server-api_sudo.js +7 -7
- package/test-server/server-commonjs.cjs +8 -8
- package/test-server/server-esm.mjs +19 -19
- package/test-server/simple-server.mjs +11 -11
- package/test-signal-payloadType/signalPack.js +34 -34
- package/test-signal-payloadType/signaling.js +60 -60
package/src/server/Manager.js
CHANGED
|
@@ -1,456 +1,449 @@
|
|
|
1
|
-
import { MBP } from 'meta-buffer-pack'
|
|
2
|
-
import { ServerRemote } from './ServerRemote.js'
|
|
3
|
-
import { serverOption } from './serverOption.js'
|
|
4
|
-
import { IOMsg, CLIENT_STATE } from '../common/constants.js'
|
|
5
|
-
import { getSignalPack } from '../common/payload.js';
|
|
6
|
-
import { FileLogger } from './FileLogger.js'
|
|
7
|
-
import { Metric } from './Metric.js'
|
|
8
|
-
|
|
9
|
-
const encoder = new TextEncoder()
|
|
10
|
-
const decoder = new TextDecoder()
|
|
11
|
-
|
|
12
|
-
export class Manager{
|
|
13
|
-
|
|
14
|
-
constructor( server, authManager
|
|
15
|
-
this.server = server;
|
|
16
|
-
this.txBytes = 0;
|
|
17
|
-
this.rxBytes = 0;
|
|
18
|
-
|
|
19
|
-
this.authManager = authManager;
|
|
20
|
-
// TIP. authManager module is option.
|
|
21
|
-
// if exist: used by ServerRemoteCore for the auth. process.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
this.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this.
|
|
43
|
-
|
|
44
|
-
this.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if (this.connectionLogger) this.connectionLogger.log(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
let
|
|
158
|
-
let
|
|
159
|
-
let
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
if(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
//
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
// console.log('
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
} else {
|
|
332
|
-
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
remote.channels.
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
case
|
|
431
|
-
this.metric.
|
|
432
|
-
break;
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
} else {
|
|
451
|
-
return 0
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
}
|
|
1
|
+
import { MBP } from 'meta-buffer-pack'
|
|
2
|
+
import { ServerRemote } from './ServerRemote.js'
|
|
3
|
+
import { serverOption } from './serverOption.js'
|
|
4
|
+
import { IOMsg, CLIENT_STATE } from '../common/constants.js'
|
|
5
|
+
import { getSignalPack } from '../common/payload.js';
|
|
6
|
+
import { FileLogger } from './FileLogger.js'
|
|
7
|
+
import { Metric } from './Metric.js'
|
|
8
|
+
|
|
9
|
+
const encoder = new TextEncoder()
|
|
10
|
+
const decoder = new TextDecoder()
|
|
11
|
+
|
|
12
|
+
export class Manager{
|
|
13
|
+
|
|
14
|
+
constructor( server, authManager ) {
|
|
15
|
+
this.server = server;
|
|
16
|
+
this.txBytes = 0;
|
|
17
|
+
this.rxBytes = 0;
|
|
18
|
+
|
|
19
|
+
this.authManager = authManager;
|
|
20
|
+
// TIP. authManager module is option.
|
|
21
|
+
// if exist: used by ServerRemoteCore for the auth. process.
|
|
22
|
+
|
|
23
|
+
this.connectionLogger;
|
|
24
|
+
if (serverOption.fileLogger.connection.use) {
|
|
25
|
+
this.connectionLogger = new FileLogger( serverOption.fileLogger.connection.path)
|
|
26
|
+
console.log('Manager: begin file logger [connection]')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
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]')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this.remotes = new Set(); // total ServerRemotes
|
|
36
|
+
this.channel_map = new Map() // key: channelName value: < ServerRemote : Set >
|
|
37
|
+
this.CHANNEL_PREFIX = 'CH:'
|
|
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
|
+
this.metric = new Metric(this)
|
|
42
|
+
this.lastSSID = 0;
|
|
43
|
+
|
|
44
|
+
this.pingIntervalID = setInterval(e => {
|
|
45
|
+
this.remotes.forEach(function each(remo) {
|
|
46
|
+
let socket = remo.socket;
|
|
47
|
+
if (socket.isAlive === false) {
|
|
48
|
+
console.log('## timeout. cid:', remo.cid)
|
|
49
|
+
remo.close();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
socket.txCounter++;
|
|
53
|
+
socket.isAlive = false;
|
|
54
|
+
if (remo.socketType === 'websocket') {
|
|
55
|
+
socket.ping();
|
|
56
|
+
} else {
|
|
57
|
+
remo.ping()
|
|
58
|
+
}
|
|
59
|
+
// console.log('<< PING')
|
|
60
|
+
});
|
|
61
|
+
}, serverOption.timeout);
|
|
62
|
+
|
|
63
|
+
if (serverOption.showMetric) {
|
|
64
|
+
this.monitIntervalID = setInterval((e) => {
|
|
65
|
+
this.monitor()
|
|
66
|
+
}, serverOption.monitorPeriod);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
addRemote(socket, req) {
|
|
74
|
+
socket.isAlive = true;
|
|
75
|
+
let remote = new ServerRemote(socket, req, this)
|
|
76
|
+
this.remotes.add(remote)
|
|
77
|
+
remote.send(Buffer.from([IOMsg.SERVER_READY]))
|
|
78
|
+
remote.setState(CLIENT_STATE.SENT_SERVER_READY)
|
|
79
|
+
this.lastSSID = remote.ssid;
|
|
80
|
+
let connectionInfo = `+ IP:${remote.ip} #${remote.ssid} ${socket.socketType === 'websocket' ? "WS" : "CS"} `;
|
|
81
|
+
// console.log( connectionInfo)
|
|
82
|
+
if (this.connectionLogger) this.connectionLogger.log(connectionInfo)
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
removeRemote(remote) {
|
|
87
|
+
// console.log('#### manager.removeRemote()', remote.cid, remote.uid)
|
|
88
|
+
let remoteInfo = `- IP:${remote.ip} #${remote.ssid} cid:${remote.cid} ${remote?.socket.socketType === 'websocket' ? "WS" : "CS"} `
|
|
89
|
+
if (this.connectionLogger) this.connectionLogger.log(remoteInfo)
|
|
90
|
+
this.deligateSignal(remote, '@state', 'close')
|
|
91
|
+
this.deligateSignal(remote, '@$state', 'close')
|
|
92
|
+
|
|
93
|
+
// remove subscriber
|
|
94
|
+
for (let ch of remote.channels.keys()) {
|
|
95
|
+
if (this.channel_map.has(ch)) {
|
|
96
|
+
const remotes = this.channel_map.get(ch)
|
|
97
|
+
// console.log(`-- channel [ ${ch} ] removes subscriber id: ${remote.cid} `)
|
|
98
|
+
remotes.delete(remote)
|
|
99
|
+
if (remotes.size == 0) this.channel_map.delete(ch)
|
|
100
|
+
}else{
|
|
101
|
+
// console.log('no such a ch: ', ch )
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// retain message policy
|
|
106
|
+
// type 1. keep if authUser, delete if anonymouse.
|
|
107
|
+
if( remote.boho.isAuthorized ){
|
|
108
|
+
//keep retain signal.
|
|
109
|
+
}else{
|
|
110
|
+
// anonymouse: remove the cid publish channel
|
|
111
|
+
for (let ch of remote.retain_signal.keys()) {
|
|
112
|
+
// console.log('cid retain_signal.keys:', ch )
|
|
113
|
+
ch = this.CID_PREFIX + remote.cid + '@' + ch
|
|
114
|
+
if (this.channel_map.has(ch)) {
|
|
115
|
+
this.channel_map.delete(ch)
|
|
116
|
+
// console.log(`-- deleted cid pub ch [ ${ch} ]. cid publisher id: ${remote.cid} `)
|
|
117
|
+
}else{
|
|
118
|
+
// console.log('no such a retain_signal tag: ', ch )
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
if( remote.uid && this.server.apiNames.has('account')){
|
|
125
|
+
let req = { topic:'detachUserRemote'}
|
|
126
|
+
req.args = ['caller:manager.removeRemote']
|
|
127
|
+
this.server.emit('account', remote, req )
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
this.remotes.delete(remote)
|
|
131
|
+
this.cid2remote.delete(remote.cid)
|
|
132
|
+
remote = null
|
|
133
|
+
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
// unix wall like
|
|
138
|
+
serverSignal(obj) {
|
|
139
|
+
let sigPack = MBP.pack(
|
|
140
|
+
MBP.MB('#MsgType', '8', IOMsg.SERVER_SIGNAL),
|
|
141
|
+
MBP.MB('#signalObject', obj)
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
this.remotes.forEach(remote => {
|
|
145
|
+
remote.send_enc_mode(sigPack)
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
getSignalTag(buffer) {
|
|
150
|
+
let tagLen = buffer.readUint8(1)
|
|
151
|
+
let tagBuf = buffer.subarray(2, 2 + tagLen)
|
|
152
|
+
let tag = decoder.decode(tagBuf)
|
|
153
|
+
return tag
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
getNewSignalTagMessage(buffer, newTag) {
|
|
157
|
+
let msgType = buffer[0]
|
|
158
|
+
let tagLen = buffer.readUint8(1)
|
|
159
|
+
let newTagBuf = encoder.encode(newTag)
|
|
160
|
+
let newTagLen = newTagBuf.byteLength;
|
|
161
|
+
let payloadCunk = buffer.subarray(2 + tagLen)
|
|
162
|
+
let newBuffer = Buffer.concat([Buffer.from([msgType, newTagLen]), newTagBuf, payloadCunk])
|
|
163
|
+
return newBuffer
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
// signaling to the cid subscribers.
|
|
168
|
+
// example. sending cid close signal.
|
|
169
|
+
deligateSignal(remote, tag, ...args) {
|
|
170
|
+
let sigPack = getSignalPack(tag, ...args)
|
|
171
|
+
this.sender(tag, remote, sigPack)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
adminSignal( cid, message){
|
|
175
|
+
if (this.cid2remote.has(cid)) {
|
|
176
|
+
this.cid2remote.get(cid).send_enc_mode(message)
|
|
177
|
+
// return ['ok', 1]
|
|
178
|
+
return
|
|
179
|
+
}else{
|
|
180
|
+
return "no cid"
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
serverSignalTo( tag, ...args ){
|
|
185
|
+
let cid = tag.split('@')[0]
|
|
186
|
+
let topic = tag.split('@')[1]
|
|
187
|
+
let sigPack = getSignalPack( '@'+topic, ...args )
|
|
188
|
+
// console.log('tag split', cid )
|
|
189
|
+
if (cid && this.cid2remote.has(cid)) {
|
|
190
|
+
let targetRemote = this.cid2remote.get(cid)
|
|
191
|
+
console.log('target', targetRemote.state ,targetRemote.cid )
|
|
192
|
+
targetRemote.send_enc_mode(sigPack)
|
|
193
|
+
return
|
|
194
|
+
}else{
|
|
195
|
+
return "no cid"
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
sender(tag, remote, message) {
|
|
200
|
+
if(serverOption.memberOnly && !remote.boho.isAuthorized){
|
|
201
|
+
// console.log("## MemberOnly, reject unAuthorized remote." )
|
|
202
|
+
remote.send(Buffer.from([IOMsg.SERVER_CLEAR_AUTH]))
|
|
203
|
+
remote.close()
|
|
204
|
+
return ['err', 'not autrized']
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if( tag.indexOf('$') == 0 ) return ['err', 'prefix $ is reserved for userSet tag.']
|
|
208
|
+
|
|
209
|
+
let cidIndex = tag.indexOf('@');
|
|
210
|
+
if (cidIndex === 0) {
|
|
211
|
+
// ** CID_PUB multi-cast
|
|
212
|
+
// [cid_pub] @topic , @$retainTopic
|
|
213
|
+
// modify signalpack with cid_appneded tag.
|
|
214
|
+
tag = remote.cid + tag;
|
|
215
|
+
message = this.getNewSignalTagMessage(message, tag)
|
|
216
|
+
|
|
217
|
+
// console.log('cid_pub new tag:', tag, this.getSignalTag(message ))
|
|
218
|
+
} else if (cidIndex > 0) {
|
|
219
|
+
// uni-cast.
|
|
220
|
+
// console.log('unicast to:', tag)
|
|
221
|
+
let targetCId = tag.split('@')[0];
|
|
222
|
+
if (this.cid2remote.has(targetCId)) {
|
|
223
|
+
//rm cid from tag.
|
|
224
|
+
let ommitCIdTag = '@' + tag.split('@')[1]
|
|
225
|
+
// console.log('uni-cast tag change from', tag, 'to' , ommitCIdTag )
|
|
226
|
+
message = this.getNewSignalTagMessage(message, ommitCIdTag)
|
|
227
|
+
// console.log(`origin tag: ${tag} omitTag: ${this.getSignalTag(message)}`)
|
|
228
|
+
this.cid2remote.get(targetCId).send_enc_mode(message)
|
|
229
|
+
return ['ok', 1]
|
|
230
|
+
}
|
|
231
|
+
return ['err', 'Invalid cid']
|
|
232
|
+
// pub message from cid.
|
|
233
|
+
// you already subscribe the cid.
|
|
234
|
+
} else {
|
|
235
|
+
// console.log('ch_pub tag:', tag)
|
|
236
|
+
//else channel publish message
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* multi-cast:
|
|
242
|
+
* channel_publish
|
|
243
|
+
* or cid_publish
|
|
244
|
+
*/
|
|
245
|
+
|
|
246
|
+
// HOME_CHANNEL substitution.
|
|
247
|
+
// (blank)#topic -> home_channel#topic.
|
|
248
|
+
if (tag.indexOf('#') === 0) {
|
|
249
|
+
tag = remote.HOME_CHANNEL + tag;
|
|
250
|
+
} else if( tag.includes('@')){
|
|
251
|
+
tag = this.CID_PREFIX + tag;
|
|
252
|
+
} else {
|
|
253
|
+
tag = this.CHANNEL_PREFIX + tag;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// retain signal message
|
|
257
|
+
if (tag.includes('$')
|
|
258
|
+
// && remote.boho.isAuthorized
|
|
259
|
+
&& serverOption.retain.isAvailable
|
|
260
|
+
&& serverOption.retain.limitCounter > this.retain_messages.size
|
|
261
|
+
&& serverOption.retain.limitSize > message.byteLength
|
|
262
|
+
) {
|
|
263
|
+
// cid retain signal
|
|
264
|
+
if (tag.includes('@')) {
|
|
265
|
+
// cid retain signal stored inside remote.
|
|
266
|
+
let retainTag = tag.split('@')[1]
|
|
267
|
+
remote.retain_signal.set(retainTag, message)
|
|
268
|
+
// console.log('## cid retain tag, size: ', retainTag, remote.retain_signal.size)
|
|
269
|
+
} else {
|
|
270
|
+
// channel retain signal stored inside manager.
|
|
271
|
+
this.retain_messages.set(tag, message)
|
|
272
|
+
// console.log('## channel retain tag, size: ', tag, this.retain_messages.size)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
} else {
|
|
276
|
+
// console.log('no retain. serverOption.retain:', serverOption.retain )
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
let sentCounter = 0;
|
|
280
|
+
if (this.channel_map.has(tag)) {
|
|
281
|
+
// console.log('raw channel_map matched tag:', tag)
|
|
282
|
+
let remotes = this.channel_map.get(tag);
|
|
283
|
+
if (remotes.size >= 1) {
|
|
284
|
+
let limit;
|
|
285
|
+
if (serverOption.useQuota.publishCounter) {
|
|
286
|
+
limit = Math.min(remote.quota.publishCounter, remotes.size)
|
|
287
|
+
} else {
|
|
288
|
+
limit = remotes.size;
|
|
289
|
+
}
|
|
290
|
+
let peers = remotes.values();
|
|
291
|
+
while (sentCounter < limit) {
|
|
292
|
+
let c = peers.next().value
|
|
293
|
+
if (!c) {
|
|
294
|
+
// console.log('## null remote' )
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
if (c !== remote) {
|
|
298
|
+
c.send_enc_mode(message);
|
|
299
|
+
sentCounter++;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (serverOption.useQuota.publishCounter) {
|
|
304
|
+
// console.log(`pub >> [${tag}] sent: ${sentCounter} [use quota limit: ${remote.quota.publishCounter }] total: ${remotes.size} subscribers. ` )
|
|
305
|
+
} else {
|
|
306
|
+
// console.log(`pub >> [${tag}] sent: ${sentCounter} [no quota limit] total: ${remotes.size} subscribers. ` )
|
|
307
|
+
}
|
|
308
|
+
return ['ok', sentCounter]
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// console.log('-- No subscriber. ch: ' , tag )
|
|
312
|
+
return ['err', 'No subscriber.']
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
subscribe(chArr, remote) {
|
|
318
|
+
// console.log('ChannelManager:: subscribe: ',chArr)
|
|
319
|
+
chArr.forEach(tag => {
|
|
320
|
+
if (tag.indexOf('#') === 0) {
|
|
321
|
+
tag = remote.HOME_CHANNEL + tag
|
|
322
|
+
} else if( tag.includes('@')){
|
|
323
|
+
tag = this.CID_PREFIX + tag;
|
|
324
|
+
} else {
|
|
325
|
+
tag = this.CHANNEL_PREFIX + tag
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// 1. set channel map
|
|
329
|
+
if (this.channel_map.has(tag)) {
|
|
330
|
+
this.channel_map.get(tag).add(remote)
|
|
331
|
+
} else {
|
|
332
|
+
this.channel_map.set(tag, new Set([remote]))
|
|
333
|
+
}
|
|
334
|
+
// console.log('Manager::map:', this.channel_map.keys() )
|
|
335
|
+
|
|
336
|
+
// 2.add to remote channels.
|
|
337
|
+
remote.channels.add(tag)
|
|
338
|
+
// console.log('remote.channels set.', remote.channels )
|
|
339
|
+
|
|
340
|
+
// 3. send retain message if available.
|
|
341
|
+
if (tag.includes('$')
|
|
342
|
+
&& serverOption.retain.isAvailable
|
|
343
|
+
) {
|
|
344
|
+
let retainMessage;
|
|
345
|
+
if (tag.includes('@')) {
|
|
346
|
+
let cid = tag.split('@')[0]
|
|
347
|
+
cid = cid.split(this.CID_PREFIX)[1]
|
|
348
|
+
let retainTag = tag.split('@')[1]
|
|
349
|
+
if (this.cid2remote.has(cid)) {
|
|
350
|
+
retainMessage = this.cid2remote.get(cid).retain_signal.get(retainTag)
|
|
351
|
+
} else {
|
|
352
|
+
// console.log('cid subscribe is rejected. not online:', cid)
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
} else if (this.retain_messages.has(tag)) {
|
|
357
|
+
retainMessage = this.retain_messages.get(tag)
|
|
358
|
+
}
|
|
359
|
+
// console.log('send retainMessage buffer',retainMessage)
|
|
360
|
+
if(retainMessage) remote.send_enc_mode(retainMessage)
|
|
361
|
+
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
})
|
|
365
|
+
return remote.channels.size;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
unsubscribe(chArr, remote) {
|
|
369
|
+
//unsubscribe all channels of the remote.
|
|
370
|
+
if (chArr.length == 1 && chArr[0] == "") {
|
|
371
|
+
|
|
372
|
+
remote.channels.forEach(ch => {
|
|
373
|
+
if (this.channel_map.has(ch)) {
|
|
374
|
+
let remotes = this.channel_map.get(ch)
|
|
375
|
+
remotes.delete(remote)
|
|
376
|
+
if (remotes.size == 0) this.channel_map.delete(ch)
|
|
377
|
+
}
|
|
378
|
+
})
|
|
379
|
+
remote.channels.clear();
|
|
380
|
+
|
|
381
|
+
} else {
|
|
382
|
+
// unsubscribe each channels.
|
|
383
|
+
chArr.forEach(ch => {
|
|
384
|
+
// substitution home_channel
|
|
385
|
+
if (ch.indexOf('#') === 0) {
|
|
386
|
+
ch = remote.HOME_CHANNEL + ch;
|
|
387
|
+
} else if( ch.includes('@')){
|
|
388
|
+
ch = this.CID_PREFIX + ch;
|
|
389
|
+
} else {
|
|
390
|
+
ch = this.CHANNEL_PREFIX + ch;
|
|
391
|
+
}
|
|
392
|
+
// console.log('-- Manager::unsubscribe:', ch )
|
|
393
|
+
|
|
394
|
+
// delete manager map.
|
|
395
|
+
if (this.channel_map.has(ch)) {
|
|
396
|
+
let remotes = this.channel_map.get(ch)
|
|
397
|
+
remotes.delete(remote)
|
|
398
|
+
if (remotes.size == 0) this.channel_map.delete(ch)
|
|
399
|
+
} else {
|
|
400
|
+
// console.log('##no such a ch', ch )
|
|
401
|
+
}
|
|
402
|
+
remote.channels.delete(ch)
|
|
403
|
+
})
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// console.log( '-- result unsub:', remote.channels )
|
|
407
|
+
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
monitor() {
|
|
412
|
+
if (process.stdout.isTTY) {
|
|
413
|
+
process.stdout.cursorTo(0, 0)
|
|
414
|
+
process.stdout.clearScreenDown()
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (serverOption.showChannel > 0) {
|
|
418
|
+
this.metric.channels(serverOption.showChannel);
|
|
419
|
+
}
|
|
420
|
+
let mode = parseInt(serverOption.showMetric)
|
|
421
|
+
console.log('monitor metric type:', mode)
|
|
422
|
+
switch (mode) {
|
|
423
|
+
case 1:
|
|
424
|
+
this.metric.oneline(true);
|
|
425
|
+
break;
|
|
426
|
+
case 2:
|
|
427
|
+
// this.metric.getCIdList(true);
|
|
428
|
+
this.metric.getRemotes(true);
|
|
429
|
+
break;
|
|
430
|
+
case 3:
|
|
431
|
+
this.metric.getChannelList(true);
|
|
432
|
+
break;
|
|
433
|
+
default:
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
closeRemoteByCId(cid) {
|
|
440
|
+
if (this.cid2remote.has(cid)) {
|
|
441
|
+
this.cid2remote.get(cid).close()
|
|
442
|
+
return 1
|
|
443
|
+
} else {
|
|
444
|
+
return 0
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
}
|