iosignal 0.0.1 → 1.0.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 (47) hide show
  1. package/README.md +170 -0
  2. package/auth_file.json +13 -0
  3. package/auth_file.mjs +23 -0
  4. package/dist/iosignal.cjs +2 -0
  5. package/dist/iosignal.esm.js +3 -0
  6. package/dist/iosignal.esm.js.map +1 -0
  7. package/dist/iosignal.min.js +3 -0
  8. package/dist/iosignal.min.js.map +1 -0
  9. package/img/iosignal_stack.png +0 -0
  10. package/index.js +19 -0
  11. package/indexWebBrowser.js +13 -0
  12. package/package.json +48 -6
  13. package/rollup.config.js +69 -0
  14. package/src/api/RedisAPI.js +68 -0
  15. package/src/api/api_constant.js +7 -0
  16. package/src/api/api_reply.js +34 -0
  17. package/src/api/api_sudo.js +96 -0
  18. package/src/auth/Auth_Env.js +78 -0
  19. package/src/auth/Auth_File.js +75 -0
  20. package/src/auth/Auth_Redis.js +50 -0
  21. package/src/auth/BohoAuth.js +168 -0
  22. package/src/client/CongPacket.js +150 -0
  23. package/src/client/IOCongSocket.js +88 -0
  24. package/src/client/IOCore.js +959 -0
  25. package/src/client/IOWS.js +81 -0
  26. package/src/client/IOWebSocket.js +96 -0
  27. package/src/common/constants.js +159 -0
  28. package/src/common/quotaTable.js +61 -0
  29. package/src/common/util.js +61 -0
  30. package/src/server/FileLogger.js +30 -0
  31. package/src/server/Manager.js +521 -0
  32. package/src/server/Metric.js +154 -0
  33. package/src/server/Server.js +136 -0
  34. package/src/server/ServerRemote.js +235 -0
  35. package/src/server/ServerRemoteCore.js +467 -0
  36. package/src/server/serverOption.js +55 -0
  37. package/test-browser/favicon.ico +0 -0
  38. package/test-browser/index.html +93 -0
  39. package/test-browser/server.js +8 -0
  40. package/test-client-nodejs/client.cjs +17 -0
  41. package/test-client-nodejs/client.mjs +17 -0
  42. package/test-server/server-commonjs.cjs +8 -0
  43. package/test-server/server-esm.mjs +19 -0
  44. package/test-server/test-Auth_Env.js +17 -0
  45. package/test-server/test-Auth_File.js +9 -0
  46. package/test-server/test-api_reply.js +10 -0
  47. package/test-server/test-api_sudo.js +11 -0
@@ -0,0 +1,467 @@
1
+ import { webcrypto } from 'crypto';
2
+ import { MBP } from 'meta-buffer-pack'
3
+ import { Boho, BohoMsg, MetaSize } from 'boho'
4
+ import { serverOption } from './serverOption.js';
5
+ import { IOMsg, ENC_MODE, CLIENT_STATE } from '../common/constants.js'
6
+ import { quotaTable } from '../common/quotaTable.js'
7
+
8
+ const decoder = new TextDecoder()
9
+
10
+ const NB = MBP.NB
11
+ const MB = MBP.MB
12
+
13
+
14
+ export class ServerRemoteCore {
15
+ constructor(socket, manager) {
16
+
17
+ this.socket = socket;
18
+ socket.isAlive = true;
19
+ socket.txCounter = 0;
20
+ socket.rxCounter = 0;
21
+ socket.openTime = Date.now()
22
+
23
+ this.boho = new Boho()
24
+ this.encMode = ENC_MODE.AUTO;
25
+ this.channels = new Set(); // subscribed tags
26
+ this.retain_signal = new Map();
27
+
28
+ this.ssid = ServerRemoteCore.ssid++; // ordered index number
29
+ this.manager = manager;
30
+
31
+ this.cid; // Communication Id
32
+ this.did; // Device Id
33
+ this.uid;
34
+ this.nick = ""
35
+
36
+
37
+ this.lastEchoMessage = "N"
38
+ this.privateNode = false
39
+ this.HOME_CHANNEL = ""
40
+ this.level = serverOption.defaultQuotaIndex;
41
+ this.quota = quotaTable[this.level];
42
+ this.isAdmin = false;
43
+
44
+ this.state;
45
+ this.stateLog = [];
46
+ this.setState(CLIENT_STATE.INIT)
47
+
48
+ }
49
+
50
+ static ssid = 1;
51
+
52
+
53
+
54
+ setState(state) {
55
+ this.state = state
56
+ if (serverOption.debug.showAuthInfo) {
57
+ this.stateLog.push(state)
58
+ console.log(this.stateLog.join('>'))
59
+ }
60
+ }
61
+
62
+ getState(){
63
+ return this.state
64
+ }
65
+
66
+ getStateName(){
67
+ //state <number>
68
+ //value of constant STATES.NAME < number >
69
+ //type of constant STATES.NAME name < string uppercase >
70
+ //stateName,eventName <string lowercase>
71
+ return ( CLIENT_STATE[ this.state ]).toLowerCase()
72
+ }
73
+
74
+
75
+ showMessageLog(message, isBinary) {
76
+ let from = this.boho.isAuthorized ? ` id: ${this.did}(${this.cid})` : ""
77
+ if (isBinary) {
78
+ let msgTypeName = IOMsg[message[0]]
79
+ if (!msgTypeName) msgTypeName = BohoMsg[message[0]]
80
+ msgTypeName = '#' + this.ssid + '(' + this.cid + ') [ ' + msgTypeName + ' ]';
81
+ if (message.byteLength > 40) {
82
+ console.log(msgTypeName + from + ' LEN:', message.length);
83
+ } else {
84
+ console.log(msgTypeName + from, message);
85
+ }
86
+
87
+ } else {
88
+ console.log(from + '[TEXT MSG] %s', message);
89
+ }
90
+ }
91
+
92
+ rxQuotaChecker(message) {
93
+ let rxBytes = message.byteLength
94
+ this.manager.rxBytes += rxBytes;
95
+
96
+ if (serverOption.useQuota.signalSize && (rxBytes > this.quota.signalSize)) {
97
+ console.log('## quota: size over')
98
+ this.send(Buffer.from([IOMsg.OVER_SIZE]))
99
+ if (serverOption.useQuota.disconnect) this.close();
100
+ return false;
101
+ }
102
+
103
+ // todo:
104
+ // traffic rate :
105
+
106
+ return true;
107
+ }
108
+
109
+ //
110
+ onTimeDelayMessage(message, isBinary = true) {
111
+ setTimeout(() => {
112
+ this.onSocketMessage(message, isBinary)
113
+ }
114
+ , serverOption.debug.delay)
115
+ }
116
+ // CongSocket or WebSocket
117
+ onSocketMessage(message, isBinary = true) {
118
+
119
+ this.receiveMonitor() // rx data and ping pong : timeout check
120
+ if (!this.rxQuotaChecker(message)) return
121
+
122
+ if (serverOption.showMessage === 'message') this.showMessageLog(message, isBinary)
123
+
124
+ let msgType, decoded
125
+
126
+ if (isBinary) {
127
+ msgType = message[0]
128
+
129
+ if (msgType === BohoMsg.ENC_488) {
130
+ // let from = this.boho.isAuthorized ? this.cid : "anonymous"
131
+ // console.log(`>> [E488] from: ${from} LEN ${message.byteLength}`)
132
+ // console.log( "ENC buffer", message)
133
+ try {
134
+ decoded = this.boho.decrypt_488(message)
135
+ } catch (err) {
136
+ console.log('-- E488 DEC_FAIL', err)
137
+ return
138
+ }
139
+
140
+ if (decoded) {
141
+ msgType = decoded[0]
142
+ message = decoded // signal message
143
+ // console.log('[D]', IOMsg[ msgType] )
144
+ } else {
145
+ return
146
+ }
147
+
148
+ } else if (msgType === BohoMsg.ENC_E2E) { // End to End Signal
149
+ try {
150
+ decoded = this.boho.decrypt_488(message)
151
+ } catch (err) {
152
+ console.log('-- E2E DEC_FAIL', err)
153
+ return
154
+ }
155
+ // console.log('e2e unpack:', decoded )
156
+ if (decoded) {
157
+ msgType = decoded[0]
158
+ message.set(decoded, MetaSize.ENC_488) // set decoded signal_e2e headaer.
159
+ message = message.subarray(MetaSize.ENC_488) // reset offset.
160
+ // console.log('[D]', IOMsg[ msgType] )
161
+ } else {
162
+ return
163
+ }
164
+
165
+ } else {
166
+ // console.log( `[P] ${ IOMsg[ msgType] || BohoMsg[cmd]} LEN: ${message.byteLength}` )
167
+ }
168
+
169
+ switch (msgType) {
170
+ case IOMsg.PING:
171
+ // console.log('-- ping from:' , this.cid )
172
+ this.pong();
173
+ break;
174
+
175
+ case IOMsg.PONG:
176
+ // console.log('<-pong')
177
+ break;
178
+
179
+ case IOMsg.CID_REQ:
180
+ if (this.state < CLIENT_STATE.SENT_SERVER_READY) {
181
+ // console.log('protocol error. cid_req before server_ready')
182
+ this.close()
183
+ }
184
+ if (!this.cid) {
185
+ this.cid = '?' + webcrypto.getRandomValues(Buffer.alloc(3)).toString('base64url')
186
+ this.manager.cid2remote.set(this.cid, this)
187
+ }
188
+
189
+ // console.log('<< SENDING CID_RES:', this.cid)
190
+ this.send_enc_mode(MBP.pack(
191
+ MB('#cid_ack', '8', IOMsg.CID_RES),
192
+ MB('#cid', this.cid)
193
+ ))
194
+
195
+ this.setState(CLIENT_STATE.CID_READY)
196
+ break;
197
+
198
+
199
+ case IOMsg.ECHO: // TEXT only
200
+ try {
201
+ let msg = decoder.decode(message.subarray(1))
202
+ this.lastEchoMessage = msg
203
+ } catch (error) {
204
+ // console.log('ECHO message is not a text')
205
+ }
206
+ this.send(message, isBinary)
207
+ break;
208
+
209
+ case IOMsg.IAM: // iam
210
+ if(message.byteLength > 1){
211
+ let iamInfo = message.subarray(1)
212
+ this.nick = decoder.decode(iamInfo)
213
+ console.log('iam nick reset', this.nick)
214
+ }
215
+ this.iamResponse()
216
+ break;
217
+
218
+ case IOMsg.SIGNAL_E2E:
219
+ case IOMsg.SIGNAL:
220
+ if (message.byteLength >= 3) {
221
+ let tagLen = message.readUInt8(1)
222
+ if (message.byteLength >= tagLen + 2) {
223
+ let tag = message.subarray(2, 2 + tagLen)
224
+ tag = decoder.decode(tag)
225
+ this.manager.sender(tag, this, message )
226
+ }
227
+ }
228
+ break;
229
+
230
+
231
+
232
+ case IOMsg.UNSUBSCRIBE:
233
+ if (message.byteLength == 2) {
234
+ this.manager.unsubscribe([""], this)
235
+ } else if (message.byteLength >= 3) {
236
+ let tagLen = message.readUInt8(1)
237
+
238
+ if (message.byteLength == tagLen + 2) {
239
+ let tag = message.subarray(2, 2 + tagLen)
240
+ tag = decoder.decode(tag)
241
+ // console.log('unsub: tag', tag)
242
+ let tagList = tag.split(',')
243
+ this.manager.unsubscribe(tagList, this)
244
+ }
245
+ }
246
+ break;
247
+
248
+
249
+ case IOMsg.SUBSCRIBE: // 1byte tagLen
250
+ if (message.byteLength >= 3) {
251
+ let tagLen = message.readUInt8(1)
252
+ if (message.byteLength == tagLen + 2) {
253
+ let tag = message.subarray(2, 2 + tagLen)
254
+ tag = decoder.decode(tag)
255
+ let tagList = tag.split(',')
256
+ // console.log('-- SUBSCRIBE req splittagList', tagList)
257
+ this.manager.subscribe(tagList, this)
258
+ }
259
+ }
260
+ break;
261
+
262
+ case IOMsg.SUBSCRIBE_REQ: // 2bytes tagLen
263
+ // console.log('#####recv sub_req ', message, message.byteLength )
264
+ if (message.byteLength >= 6) {
265
+ let msgID = message.readUInt16BE(1)
266
+ let tagLen = message.readUInt16BE(3)
267
+ if (message.byteLength == tagLen + 5) {
268
+ let tag = message.subarray(5, 5 + tagLen)
269
+ tag = decoder.decode(tag)
270
+ let tagList = tag.split(',')
271
+ // console.log('>> SUBSCRIBE_REQ from:', this.cid, tagList)
272
+ let size = this.manager.subscribe(tagList, this)
273
+
274
+ // this.response(msgID, 0, { size: size })
275
+ this.response(msgID, 0)
276
+ } else {
277
+ this.response(msgID, 255 )
278
+ }
279
+ }
280
+ break;
281
+
282
+
283
+ case IOMsg.REQUEST: //api request
284
+ try {
285
+ let req = MBP.unpack( message )
286
+ // console.log('request unpack req', req)
287
+ if(req){
288
+ // console.log('request target:', req.target, 'topic:', req.topic)
289
+ if( !req.target || !req.topic ) return
290
+ if(this.manager.server.apiNames.has(req.target)){
291
+ this.manager.server.emit( req.target, this , req )
292
+ }else{
293
+ console.log('UnKnown API req: ', req.target)
294
+ }
295
+ }
296
+ } catch (e) {
297
+ console.log('request catch error', e)
298
+ }
299
+ break;
300
+
301
+
302
+ case IOMsg.CLOSE:
303
+ if (message.byteLength > 1) {
304
+ let reason = decoder.decode(message.subarray(1))
305
+ console.log('>> CLOSE reason:', reason)
306
+ this.close();
307
+ }
308
+ break;
309
+
310
+
311
+ // Auth
312
+ case BohoMsg.AUTH_REQ:
313
+ if (!this.manager.authManager) return
314
+ if (this.state < CLIENT_STATE.SENT_SERVER_READY) {
315
+ // console.log('protocol error. auth_req before server_ready')
316
+ this.close();
317
+ }
318
+ this.setState(CLIENT_STATE.RECV_AUTH_REQ)
319
+ let auth_nonce_pack = this.boho.auth_nonce()
320
+ // console.log('## auth_nonce_pack', auth_nonce_pack )
321
+ this.send(auth_nonce_pack)
322
+ this.setState(CLIENT_STATE.SENT_SERVER_NONCE)
323
+ break;
324
+
325
+ case BohoMsg.AUTH_HMAC:
326
+ if (!this.manager.authManager) return
327
+ if (this.state < CLIENT_STATE.SENT_SERVER_NONCE) {
328
+ // console.log('protocol error. auth_hmac before server_nonce')
329
+ this.close();
330
+ }
331
+ this.setState(CLIENT_STATE.RECV_AUTH_HMAC)
332
+ //async
333
+ this.manager.authManager.verify_auth_hmac(message, this)
334
+ .then(authInfo=>{
335
+ if(authInfo){
336
+ this.manager.deligateSignal(remote, '@$name', authInfo.name)
337
+ // console.log('device login success authInfo', authInfo)
338
+ // this.manager.sender('@$name', authInfo.name )
339
+ }
340
+
341
+ })
342
+ .catch(e=>{
343
+
344
+ })
345
+
346
+ return;
347
+
348
+ default:
349
+ // console.log('unknown MsgType:',msgType,' from:', this.ip, this.ssid, this.cid )
350
+
351
+ }
352
+
353
+ } else {
354
+ // TEXT FRAME
355
+ try {
356
+ let textMessage = decoder.decode(message)
357
+ // console.log('text buffer:',textMessage )
358
+ // console.log('text buffer:',message.toString('hex') )
359
+ this.manager.server.emit('text_message', textMessage, this)
360
+ } catch (error) {
361
+
362
+ }
363
+ }
364
+
365
+ }
366
+
367
+
368
+ response(msgId, statusCode, body) {
369
+ // console.log('response body', body)
370
+ if( body ){
371
+
372
+ this.send_enc_mode( MBP.pack(
373
+ MB('#type', '8', IOMsg.RESPONSE_MBP),
374
+ MB('status','8', statusCode),
375
+ MB('mid','16', msgId),
376
+ MB('body',body)
377
+ ))
378
+
379
+ }else{
380
+ this.send_enc_mode( MBP.pack(
381
+ MB('#type','8', IOMsg.RESPONSE_MBP),
382
+ MB('status','8', statusCode),
383
+ MB('mid','16', msgId)
384
+ ))
385
+
386
+ }
387
+
388
+ }
389
+
390
+
391
+ send_enc_mode(data, useEncryption = false) {
392
+
393
+ if (this.encMode === ENC_MODE.YES ||
394
+ this.encMode === ENC_MODE.AUTO &&
395
+ !this.TLS && this.boho.isAuthorized
396
+ ) useEncryption = true;
397
+
398
+ // console.log('svr useEnc', useEncryption, data )
399
+
400
+ if (useEncryption && data[0] == IOMsg.SIGNAL_E2E) {
401
+ // E2E는,
402
+ // 서버는 수신자와 암호통신하는경우, 헤더부분만 암호화 하고, 데이타 부분은 그대로 전달해야한다.
403
+ let tagLen = data[1];
404
+
405
+ // let tagInfo = decoder.decode( data.subarray( 2, 2 + tagLen) )
406
+ // console.log('server bypass E2E signal taginfo:', tagInfo )
407
+
408
+ let encHeader = this.boho.encrypt_488(data.subarray(0, 3 + tagLen))
409
+ // console.log('size check:', encHeader.byteLength == (tagLen + 3 + 21 ) )
410
+ encHeader[0] = BohoMsg.ENC_E2E
411
+ // encHeader 크기가 21(enc_488)크기 만큼 커짐. tagLen+3 + 21
412
+ let newEncBuffer = Buffer.concat([encHeader, data.subarray(3 + tagLen)])
413
+
414
+ // console.log('ENC_E2E', newEncBuffer)
415
+ this.send(newEncBuffer)
416
+
417
+ } else if (useEncryption) {
418
+ let encPack = this.boho.encrypt_488(data)
419
+ if (encPack) {
420
+ // console.log('send *S* LEN:', encPack.byteLength)
421
+ this.send(encPack)
422
+ } else {
423
+ console.log('encryption FAIL: NO DATA TRANSIT')
424
+ }
425
+ } else {
426
+ // console.log('send -N-')
427
+ this.send(data)
428
+
429
+ }
430
+
431
+ }
432
+
433
+
434
+
435
+ iamResponse(info = "") {
436
+
437
+ if (info == "") {
438
+ //send general info
439
+ let channels = []
440
+ for (let tag of this.channels.keys()) {
441
+ channels.push(tag)
442
+ }
443
+
444
+ info = {
445
+ "ssid": this.ssid,
446
+ "uid": this.uid,
447
+ "cid": this.cid,
448
+ "did": this.did,
449
+ "nick": this.nick,
450
+ "ip": this.ip
451
+ , 'tag': channels
452
+ }
453
+ }
454
+
455
+ let pack = MBP.pack(
456
+ MB('#MsgType', '8', IOMsg.IAM_RES),
457
+ MB('#info', info)
458
+ )
459
+ this.send_enc_mode(pack)
460
+ }
461
+
462
+ // storeSet(topic, ...args){
463
+ // this.manager.set( this, topic, ...args )
464
+ // }
465
+
466
+ }
467
+
@@ -0,0 +1,55 @@
1
+
2
+
3
+ export let serverOption = {
4
+ clientTracking: false,
5
+ port: 7777,
6
+ congPort: null,
7
+ timeout: 50000,
8
+ showMessage: 'none',
9
+ showMetric: 0,
10
+ showChannel: 0,
11
+ monitorPeriod: 5000,
12
+ fileLogger:{
13
+ connection: {
14
+ use: false,
15
+ path: 'connection.log'
16
+ },
17
+ auth: {
18
+ use: false,
19
+ path: 'auth.log'
20
+ },
21
+ attack:{
22
+ use: false,
23
+ path:'attack.log'
24
+ }
25
+ },
26
+ useQuota:{
27
+ signalSize: false,
28
+ publishCounter: false,
29
+ trafficRate: false,
30
+ disconnect: false
31
+ },
32
+ defaultQuotaIndex: 0,
33
+ adminLevel: 255,
34
+
35
+ debug:{
36
+ slow: false,
37
+ delay: 500,
38
+ showAuthInfo: false
39
+ },
40
+
41
+ retain:{
42
+ isAvailable: true,
43
+ limitSize: 100000,
44
+ limitCounter: 1000
45
+ },
46
+
47
+ auth:{
48
+ delay_auth_fail: 1000,
49
+ },
50
+
51
+ memberOnly: false
52
+
53
+ }
54
+
55
+
Binary file
@@ -0,0 +1,93 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Document</title>
8
+ <style>
9
+ #messageView{
10
+ border: 1px solid red;
11
+ padding: 2em;
12
+ }
13
+ </style>
14
+ </head>
15
+ <body>
16
+ <h2>Simple pub sub example.</h2>
17
+ <p>you should start server first.</p>
18
+ <p>this index.html load two types of modules. </p>
19
+ <h5>1. IIFE: iosignal.min.js</h5>
20
+ <p>use global name: IO </p>
21
+ <p>IO has props: Boho, MBP, Buffer,, </p>
22
+ <h5>2. ESM: iosignal.esm.js</h5>
23
+ <p> check the console.</p>
24
+ <h2>message log</h2>
25
+ <div id="messageView">...</div>
26
+ <script src="../dist/iosignal.min.js"></script>
27
+ <script>
28
+ console.log('IIFE:')
29
+ console.log('IO', IO)
30
+ console.log('MBP', IO.MBP )
31
+ console.log('Buffer', IO.Buffer)
32
+ console.log('Boho', IO.Boho )
33
+ console.log('sha256.hash("hi")', IO.Boho.sha256.hash('hi'))
34
+
35
+ var ESM_IO ;
36
+ var io1 = new IO('ws://localhost:7777')
37
+ var io2 = new IO('ws://localhost:7777')
38
+ var io3 = new IO('ws://localhost:7777')
39
+
40
+ io1.on('error', errorHandler )
41
+ io2.on('error', errorHandler )
42
+ io3.on('error', errorHandler )
43
+
44
+ let channelName = 'io'
45
+ // classic style subsribing
46
+ io1.on('ready',e=>{
47
+ io1.subscribe(channelName)
48
+ io1.on(channelName, (...args)=>{
49
+ // console.log('io1 received', args )
50
+ let msg = '[io1] ' + JSON.stringify( args )
51
+ addMessage(msg)
52
+ })
53
+ })
54
+
55
+ // modern style subscribing
56
+ io2.listen(channelName, (...args)=>{
57
+ // console.log('io2 receive', args )
58
+ let msg = '[io2] ' + JSON.stringify( args )
59
+ addMessage(msg)
60
+ })
61
+
62
+ setInterval(e=>{
63
+ io3.signal(channelName, 'single string') // single string payload
64
+ io3.signal(channelName, Date.now(), 'a', 2 , {key: 3} ) //multiple payload
65
+ io3.signal(channelName ) // pure signal without payload.
66
+ },3000)
67
+
68
+ function addMessage(msg){
69
+
70
+ let p = document.createElement('p')
71
+ p.textContent = msg
72
+ let v = document.querySelector('#messageView')
73
+ if(v.childElementCount > 20) v.innerHTML = ""
74
+ v.prepend( p )
75
+ }
76
+
77
+ function errorHandler(e){
78
+ console.log(e.target)
79
+ addMessage('ws.error')
80
+ }
81
+ </script>
82
+ <script type="module">
83
+ import { IO, Boho, MBP, Buffer, sha256 } from "../dist/iosignal.esm.js"
84
+ ESM_IO = IO
85
+ console.log('ESM:')
86
+ console.log('IO', IO)
87
+ console.log('Boho', Boho )
88
+ console.log('MBP', MBP )
89
+ console.log('Buffer', Buffer)
90
+ console.log('sha256.hash("hi")', sha256.hash('hi'))
91
+ </script>
92
+ </body>
93
+ </html>
@@ -0,0 +1,8 @@
1
+ import { Server, serverOption } from 'iosignal'
2
+
3
+ serverOption.showMetric = 2;
4
+ serverOption.showMessage = 'message';
5
+ const server = new Server( serverOption )
6
+
7
+ console.log( 'serverOption:', serverOption )
8
+
@@ -0,0 +1,17 @@
1
+
2
+ const { IO } = require('iosignal')
3
+
4
+ const io = new IO('wss://io.remocon.kr/ws')
5
+
6
+ io.on('ready', ()=>{
7
+ console.log('ready cid:', io.cid)
8
+ io.signal('#screen','playToggle')
9
+ });
10
+
11
+ io.listen('#notify', (...args)=>{
12
+ console.log( args )
13
+ })
14
+
15
+ io.on('error',err=>{
16
+ console.log('err', err)
17
+ })
@@ -0,0 +1,17 @@
1
+
2
+ import { IO } from "iosignal"
3
+
4
+ const io = new IO('wss://io.remocon.kr/ws')
5
+
6
+ io.on('ready', ()=>{
7
+ console.log('ready cid:', io.cid)
8
+ io.signal('#screen','playToggle')
9
+ });
10
+
11
+ io.listen('#notify', (...args)=>{
12
+ console.log( args )
13
+ })
14
+
15
+ io.on('error',err=>{
16
+ console.log('err', err)
17
+ })
@@ -0,0 +1,8 @@
1
+ let { Server, serverOption } = require('iosignal')
2
+
3
+ serverOption.showMetric = 2;
4
+ // serverOption.port = 7777 // default. websocket port 7777 will be open.
5
+ serverOption.congPort = 8888 // additional tcp cong port open. for Arduino like devices.
6
+ const server = new Server( serverOption )
7
+ console.log( 'serverOption:', serverOption )
8
+
@@ -0,0 +1,19 @@
1
+ import { Server, serverOption } from '../index.js'
2
+
3
+ // serverOption.showMetric = 2;
4
+ // serverOption.showMessage = 'message';
5
+ // serverOption.port = '6666'
6
+ // serverOption.congPort = '6667'
7
+
8
+ const server = new Server( serverOption )
9
+ console.log( 'serverOption:', serverOption )
10
+
11
+ // text message handler (No binary message)
12
+ // print text message
13
+ // then reply.
14
+ server.on('text_message', (msg, remote)=>{
15
+ console.log('text_message from(cid): ', remote.cid, msg.toString() )
16
+ let result = { msg: msg, yourcid: remote.cid , date: new Date().toUTCString() }
17
+ let res = JSON.stringify( result )
18
+ remote.send( res )
19
+ })