iosignal 5.1.4 → 5.3.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 +163 -0
- package/dist/{io.d.ts → browser/esm/io.d.ts} +10 -12
- package/dist/browser/esm/io.js +23 -0
- package/dist/browser/esm/io.js.map +1 -0
- package/dist/browser/iife/io.js +23 -0
- package/dist/browser/iife/io.js.map +1 -0
- package/dist/{iosignal.cjs → node/iosignal.cjs} +124 -119
- package/dist/{iosignal.js → node/iosignal.js} +123 -118
- package/dist/types/client/IOCore.d.ts +3 -4
- package/dist/types/client/browser/IOWebSocket.d.ts +5 -5
- package/dist/types/common/payload.d.ts +2 -2
- package/package.json +32 -15
- package/dist/io.js +0 -23
- package/dist/io.js.map +0 -1
- package/dist/io.min.js +0 -23
- package/dist/io.min.js.map +0 -1
- package/index.js +0 -26
- package/rollup.config.js +0 -59
- package/src/auth/BohoAuth.js +0 -196
- package/src/auth/key_providers/FileKeyProvider.js +0 -59
- package/src/auth/key_providers/RedisKeyProvider.js +0 -46
- package/src/auth/key_providers/StringKeyProvider.js +0 -54
- package/src/client/CongPacket.js +0 -143
- package/src/client/IOCongSocket.js +0 -92
- package/src/client/IOCore.js +0 -1202
- package/src/client/IOWS.js +0 -78
- package/src/client/browser/IOWebSocket.js +0 -202
- package/src/common/constants.js +0 -210
- package/src/common/payload.js +0 -82
- package/src/common/quotaTable.js +0 -68
- package/src/common/util.js +0 -64
- package/src/server/FileLogger.js +0 -30
- package/src/server/Manager.js +0 -450
- package/src/server/Metrics.js +0 -155
- package/src/server/Remote.js +0 -216
- package/src/server/RemoteCore.js +0 -427
- package/src/server/Server.js +0 -236
- package/src/server/serverOption.js +0 -56
- package/src/services/RedisService.js +0 -53
- package/src/services/constant.js +0 -7
- package/src/services/replyService.js +0 -39
- package/src/services/sudoService.js +0 -85
- package/tsconfig.json +0 -24
package/index.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import pkg from './package.json' with { type: 'json' };
|
|
2
|
-
export const version = pkg.version;
|
|
3
|
-
export { IOCongSocket } from './src/client/IOCongSocket.js'
|
|
4
|
-
export { IOWS as IO } from './src/client/IOWS.js'
|
|
5
|
-
export { pack, CongRx } from './src/client/CongPacket.js'
|
|
6
|
-
export { Server } from './src/server/Server.js'
|
|
7
|
-
export { serverOption } from './src/server/serverOption.js'
|
|
8
|
-
export { FileLogger } from './src/server/FileLogger.js'
|
|
9
|
-
export { getSignalPack, parsePayload, getPayloadFromSignalPack } from './src/common/payload.js'
|
|
10
|
-
export * from './src/common/constants.js'
|
|
11
|
-
export * from './src/common/util.js'
|
|
12
|
-
|
|
13
|
-
// MBP
|
|
14
|
-
export { default as MBP } from 'meta-buffer-pack'
|
|
15
|
-
|
|
16
|
-
// boho auth
|
|
17
|
-
export { default as Boho} from 'boho'
|
|
18
|
-
export { BohoAuth } from './src/auth/BohoAuth.js'
|
|
19
|
-
export { FileKeyProvider } from './src/auth/key_providers/FileKeyProvider.js'
|
|
20
|
-
export { RedisKeyProvider } from './src/auth/key_providers/RedisKeyProvider.js'
|
|
21
|
-
export { StringKeyProvider } from './src/auth/key_providers/StringKeyProvider.js'
|
|
22
|
-
|
|
23
|
-
// services
|
|
24
|
-
export * as replyService from './src/services/replyService.js'
|
|
25
|
-
export * as sudoService from './src/services/sudoService.js'
|
|
26
|
-
export { RedisService } from './src/services/RedisService.js'
|
package/rollup.config.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import resolve from '@rollup/plugin-node-resolve'
|
|
2
|
-
import commonjs from '@rollup/plugin-commonjs'
|
|
3
|
-
import json from '@rollup/plugin-json'
|
|
4
|
-
import terser from '@rollup/plugin-terser'
|
|
5
|
-
import dts from 'rollup-plugin-dts'
|
|
6
|
-
|
|
7
|
-
export default [
|
|
8
|
-
{
|
|
9
|
-
input: './src/client/browser/IOWebSocket.js',
|
|
10
|
-
output: [
|
|
11
|
-
{
|
|
12
|
-
file: './dist/io.js',
|
|
13
|
-
format: 'es',
|
|
14
|
-
sourcemap: true,
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
file: './dist/io.min.js',
|
|
18
|
-
format: 'umd',
|
|
19
|
-
name: 'IO',
|
|
20
|
-
sourcemap: true,
|
|
21
|
-
}
|
|
22
|
-
],
|
|
23
|
-
plugins: [
|
|
24
|
-
resolve({
|
|
25
|
-
preferBuiltins: false
|
|
26
|
-
}),
|
|
27
|
-
commonjs(),
|
|
28
|
-
json(),
|
|
29
|
-
terser()
|
|
30
|
-
]
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
input: './src/client/browser/IOWebSocket.js',
|
|
34
|
-
output: { file: './dist/io.d.ts', format: 'es' },
|
|
35
|
-
plugins: [dts()]
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
,{
|
|
39
|
-
input: './index.js',
|
|
40
|
-
output: [
|
|
41
|
-
{
|
|
42
|
-
file: './dist/iosignal.js',
|
|
43
|
-
format: 'es'
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
file: "./dist/iosignal.cjs",
|
|
47
|
-
format: 'cjs'
|
|
48
|
-
}
|
|
49
|
-
],
|
|
50
|
-
plugins: [
|
|
51
|
-
resolve({
|
|
52
|
-
preferBuiltins: true
|
|
53
|
-
}),
|
|
54
|
-
json(),
|
|
55
|
-
commonjs()
|
|
56
|
-
]
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
]
|
package/src/auth/BohoAuth.js
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import MBP from 'meta-buffer-pack'
|
|
2
|
-
import Boho from 'boho'
|
|
3
|
-
import { quotaTable } from '../common/quotaTable.js'
|
|
4
|
-
import { serverOption } from '../server/serverOption.js'
|
|
5
|
-
import { IOMsg, STATE } from '../common/constants.js'
|
|
6
|
-
import { FileLogger } from '../server/FileLogger.js'
|
|
7
|
-
|
|
8
|
-
const decoder = new TextDecoder()
|
|
9
|
-
export class BohoAuth {
|
|
10
|
-
constructor(keyProvider) {
|
|
11
|
-
if (!keyProvider) {
|
|
12
|
-
throw new Error('BohoAuth must be initialized with a keyProvider.');
|
|
13
|
-
}
|
|
14
|
-
this.keyProvider = keyProvider;
|
|
15
|
-
this.keepOldConnection = true;
|
|
16
|
-
this.authLogger;
|
|
17
|
-
if (serverOption.fileLogger.auth.use) {
|
|
18
|
-
this.authLogger = new FileLogger(serverOption.fileLogger.auth.path)
|
|
19
|
-
console.log('Auth: begin file logger.[auth]')
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
send_auth_fail(peer, reason) {
|
|
24
|
-
if (this.authLogger) {
|
|
25
|
-
let peerInfo = `FAIL #${peer.ssid} reason:${reason} `
|
|
26
|
-
this.authLogger.log(peerInfo)
|
|
27
|
-
}
|
|
28
|
-
// console.log('##### AUTH_FAIL reason: ', reason)
|
|
29
|
-
peer.setState(STATE.AUTH_FAIL)
|
|
30
|
-
// add some delay time.
|
|
31
|
-
setTimeout(e => {
|
|
32
|
-
peer.send(Buffer.from([Boho.BohoMsg.AUTH_FAIL]))
|
|
33
|
-
}, serverOption.auth.delay_auth_fail)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
async verify_auth_req(auth_req, peer) {
|
|
38
|
-
try {
|
|
39
|
-
//1. unpack
|
|
40
|
-
let infoPack = MBP.unpack(auth_req, Boho.Meta.AUTH_REQ)
|
|
41
|
-
if (!infoPack) {
|
|
42
|
-
this.send_auth_fail(peer, 'unpack auth_pack fail');
|
|
43
|
-
return
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
let id = ""
|
|
47
|
-
if (infoPack.id8.includes(0)) {
|
|
48
|
-
id = decoder.decode(infoPack.id8.subarray(0, infoPack.id8.indexOf(0)));
|
|
49
|
-
} else {
|
|
50
|
-
id = decoder.decode(infoPack.id8);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
//2. get key of id from DB
|
|
54
|
-
let authInfo = await this.keyProvider.getAuth(id)
|
|
55
|
-
if (!authInfo) {
|
|
56
|
-
this.send_auth_fail(peer, 'NO ID:' + id);
|
|
57
|
-
return
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (serverOption.debug.showAuthInfo) {
|
|
61
|
-
console.log('[debug]showAuthInfo', authInfo)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
peer.boho.copy_id8(infoPack.id8)
|
|
65
|
-
// type of key
|
|
66
|
-
let authKey;
|
|
67
|
-
const SHA256_HASH_BASE64_LEN = 44
|
|
68
|
-
if (authInfo.key.length == SHA256_HASH_BASE64_LEN) {
|
|
69
|
-
// hashed key
|
|
70
|
-
authKey = Buffer.from(authInfo.key, 'base64')
|
|
71
|
-
peer.boho.copy_key(authKey)
|
|
72
|
-
} else {
|
|
73
|
-
// plain key
|
|
74
|
-
peer.boho.set_key(authInfo.key)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
//3. check hmac
|
|
78
|
-
let auth_res = peer.boho.verify_auth_req(infoPack)
|
|
79
|
-
if (!auth_res) {
|
|
80
|
-
this.send_auth_fail(peer, 'hmac dismatched');
|
|
81
|
-
return
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
//4. get info
|
|
85
|
-
|
|
86
|
-
//5. check duplicate login.
|
|
87
|
-
if (peer.manager.cid2remote.has(authInfo.cid)) {
|
|
88
|
-
let old = peer.manager.cid2remote.get(authInfo.cid)
|
|
89
|
-
console.log('[WARN]DUPLICATE_LOGIN detected.', old.cid)
|
|
90
|
-
old.ping(); // check the connection.
|
|
91
|
-
if (old == peer) {
|
|
92
|
-
console.log('## trying to RELOGIN after login.')
|
|
93
|
-
return
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
let authClearSignal = MBP.pack(
|
|
97
|
-
MBP.MB('#MsgType', '8', IOMsg.AUTH_CLEAR),
|
|
98
|
-
MBP.MB('#reason', 'duplicate login.')
|
|
99
|
-
)
|
|
100
|
-
if (this.keepOldConnection) { // default true
|
|
101
|
-
// keep old connection. reject new connection by sending auth_fail signal.
|
|
102
|
-
// peer.send(authClearSignal)
|
|
103
|
-
if( peer.socketType == 'websocket'){
|
|
104
|
-
this.send_auth_fail(peer, 'duplicate login')
|
|
105
|
-
}else{
|
|
106
|
-
peer.close(); //arduino
|
|
107
|
-
}
|
|
108
|
-
} else {
|
|
109
|
-
// accept new connection. stop the old connection by sending auth_clear signal.
|
|
110
|
-
old.send(authClearSignal)
|
|
111
|
-
peer.close()
|
|
112
|
-
}
|
|
113
|
-
return
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
//6. delete current (or anonymouse)cid if exist.
|
|
117
|
-
if (peer.cid) {
|
|
118
|
-
// console.log('if peer has cid', peer.cid)
|
|
119
|
-
peer.manager.cid2remote.delete(peer.cid)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
//7. setting info.
|
|
123
|
-
peer.did = id
|
|
124
|
-
peer.cid = authInfo.cid
|
|
125
|
-
peer.nick = authInfo.cid // temporary: nick as cid
|
|
126
|
-
if (authInfo.uid) peer.uid = authInfo.uid
|
|
127
|
-
|
|
128
|
-
//8. setting quota level.
|
|
129
|
-
let quotaLevel = serverOption.defaultQuotaIndex;
|
|
130
|
-
if (authInfo.level) quotaLevel = authInfo.level;
|
|
131
|
-
quotaLevel = parseInt(quotaLevel)
|
|
132
|
-
let newQuota = quotaTable[quotaLevel];
|
|
133
|
-
if (!newQuota) {
|
|
134
|
-
let err = 'no index quotaTable for auth.level: ' + quotaLevel
|
|
135
|
-
this.send_auth_fail(peer, err);
|
|
136
|
-
return
|
|
137
|
-
} else {
|
|
138
|
-
peer.level = quotaLevel;
|
|
139
|
-
peer.quota = newQuota;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (peer.level === serverOption.adminLevel) {
|
|
143
|
-
console.log('## LOGIN ADMIN CID:', peer.cid)
|
|
144
|
-
peer.isAdmin = true;
|
|
145
|
-
}
|
|
146
|
-
// send quota.level
|
|
147
|
-
peer.send(Buffer.from([IOMsg.QUOTA_LEVEL, quotaLevel]))
|
|
148
|
-
|
|
149
|
-
//9. set cid2remote
|
|
150
|
-
peer.manager.cid2remote.set(peer.cid, peer)
|
|
151
|
-
//10. send ack.
|
|
152
|
-
peer.send(auth_res)
|
|
153
|
-
peer.setState(STATE.AUTH_RES)
|
|
154
|
-
if (this.authLogger) {
|
|
155
|
-
let peerInfo = `OK #${peer.ssid} cid: ${peer.cid} did:${peer.did}`
|
|
156
|
-
if (peer.isAdmin) peerInfo = "#ADMIN# " + peerInfo
|
|
157
|
-
this.authLogger.log(peerInfo)
|
|
158
|
-
}
|
|
159
|
-
return authInfo
|
|
160
|
-
} catch (error) {
|
|
161
|
-
console.log('verify_auth_req error', error)
|
|
162
|
-
this.send_auth_fail(peer, '[BohoAuth]caught: unknown error:' + error);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
async getAuth(id) {
|
|
167
|
-
return this.keyProvider.getAuth(id);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
async getAuthIdList() {
|
|
171
|
-
if (typeof this.keyProvider.getAuthIdList === 'function') {
|
|
172
|
-
return this.keyProvider.getAuthIdList();
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
async addAuth(id, keyStr, cid, level = 0) {
|
|
177
|
-
if (typeof this.keyProvider.addAuth === 'function') {
|
|
178
|
-
return this.keyProvider.addAuth(id, keyStr, cid, level);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
async delAuth(id) {
|
|
183
|
-
if (typeof this.keyProvider.delAuth === 'function') {
|
|
184
|
-
return this.keyProvider.delAuth(id);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
async save() {
|
|
189
|
-
if (typeof this.keyProvider.save === 'function') {
|
|
190
|
-
return this.keyProvider.save();
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'fs'
|
|
2
|
-
import Boho from 'boho'
|
|
3
|
-
import path from 'path'
|
|
4
|
-
|
|
5
|
-
export class FileKeyProvider {
|
|
6
|
-
constructor(_path) {
|
|
7
|
-
this.AUTH = new Map();
|
|
8
|
-
let pathObj = path.parse(_path)
|
|
9
|
-
this.path = path.resolve(_path)
|
|
10
|
-
console.log('auth from file path:', this.path)
|
|
11
|
-
let ext = pathObj.ext;
|
|
12
|
-
if (ext.toLowerCase() == '.js') {
|
|
13
|
-
// Read auth data from file
|
|
14
|
-
console.log("#JS path:", this.path);
|
|
15
|
-
this.loadAuthInfoFile_JS(this.path)
|
|
16
|
-
} else if (ext.toLowerCase() == '.json') {
|
|
17
|
-
console.log("#JSON path:", this.path);
|
|
18
|
-
this.loadAuthInfoFile_JSON(this.path)
|
|
19
|
-
} else {
|
|
20
|
-
console.log('no authinfofile path.')
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
//loaded when server start.
|
|
25
|
-
loadAuthInfoFile_JS(path) {
|
|
26
|
-
import(path).then((file) => {
|
|
27
|
-
console.log(file.authInfo);
|
|
28
|
-
file.authInfo.forEach(item => {
|
|
29
|
-
this.addAuth(...item)
|
|
30
|
-
})
|
|
31
|
-
console.log('total AUTH INFO size: ', this.AUTH.size)
|
|
32
|
-
}).catch(e => {
|
|
33
|
-
console.log(e)
|
|
34
|
-
})
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
loadAuthInfoFile_JSON(path) {
|
|
38
|
-
let file = readFileSync(path)
|
|
39
|
-
file = new TextDecoder().decode(file)
|
|
40
|
-
let list = JSON.parse(file)
|
|
41
|
-
list.forEach(item => {
|
|
42
|
-
this.addAuth(...item)
|
|
43
|
-
})
|
|
44
|
-
console.log('total AUTH INFO size: ', this.AUTH.size)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async getAuth(id) {
|
|
48
|
-
return this.AUTH.get(id)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async getAuthIdList() {
|
|
52
|
-
return Array.from(this.AUTH.keys())
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
addAuth(id, keyStr, cid, level = 0) {
|
|
56
|
-
let Base64hashKey = Buffer.from(Boho.sha256.hash(keyStr)).toString('base64')
|
|
57
|
-
this.AUTH.set(id, { key: Base64hashKey, cid: cid, level: level })
|
|
58
|
-
}
|
|
59
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import Boho from 'boho'
|
|
2
|
-
const DEVICE_PREFIX = "device:"
|
|
3
|
-
|
|
4
|
-
export class RedisKeyProvider {
|
|
5
|
-
constructor(redisClient) {
|
|
6
|
-
if (!redisClient) {
|
|
7
|
-
throw new Error("RedisKeyProvider constructor: no redisClient")
|
|
8
|
-
}
|
|
9
|
-
this.redis = redisClient
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// get device key from DB. (for Boho auth.)
|
|
13
|
-
async getAuth(id) {
|
|
14
|
-
try {
|
|
15
|
-
let result = await this.redis.hGetAll(DEVICE_PREFIX + id)
|
|
16
|
-
if (result && result.key) return result
|
|
17
|
-
else return null;
|
|
18
|
-
} catch (error) {
|
|
19
|
-
console.log('getAuth', error)
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
//sudoService call
|
|
24
|
-
async getAuthIdList() {
|
|
25
|
-
let result = await this.redis.keys(DEVICE_PREFIX + '*')
|
|
26
|
-
result = result.map(v => {
|
|
27
|
-
return v.split(':')[1]
|
|
28
|
-
})
|
|
29
|
-
if (result) return result
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// add device auth info
|
|
33
|
-
async addAuth(id, keyStr, cid = '', level = 0) {
|
|
34
|
-
let Base64hashKey = Buffer.from(Boho.sha256.hash(keyStr)).toString('base64')
|
|
35
|
-
return this.redis.hSet(DEVICE_PREFIX + id, { 'key': Base64hashKey, 'cid': cid, 'level': level })
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
//sudoService call
|
|
39
|
-
async delAuth(id) {
|
|
40
|
-
return this.redis.del(DEVICE_PREFIX + id)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async save(id) {
|
|
44
|
-
return this.redis.save()
|
|
45
|
-
}
|
|
46
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* StringKeyProvider.js
|
|
3
|
-
*
|
|
4
|
-
* authInfo <String>
|
|
5
|
-
* id: max 8chars
|
|
6
|
-
* key: ~44 base64 chars recomended
|
|
7
|
-
* cid:
|
|
8
|
-
* level: range: 0~255
|
|
9
|
-
* separator: ',' for multiple devices.
|
|
10
|
-
*
|
|
11
|
-
* example => authInfo = 'id1.key1.cid1.255,id2.key2.cid2.200'
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import Boho from 'boho'
|
|
15
|
-
|
|
16
|
-
export class StringKeyProvider {
|
|
17
|
-
constructor(authInfo) {
|
|
18
|
-
|
|
19
|
-
if (!authInfo) {
|
|
20
|
-
throw TypeError("StringKeyProvider constructor() missing authInfo.")
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
let id_keys = authInfo.split(',')
|
|
24
|
-
|
|
25
|
-
this.AUTH = new Map();
|
|
26
|
-
|
|
27
|
-
if (id_keys.length >= 1) {
|
|
28
|
-
id_keys.forEach(v => {
|
|
29
|
-
let [ did, key, cid, level ] = v.split('.')
|
|
30
|
-
level = parseInt(level)
|
|
31
|
-
if (did && key && cid && typeof level == 'number') {
|
|
32
|
-
this.addAuth(did, key, cid, level)
|
|
33
|
-
} else {
|
|
34
|
-
throw TypeError("StringKeyProvider invalid authInfo.")
|
|
35
|
-
}
|
|
36
|
-
})
|
|
37
|
-
} else {
|
|
38
|
-
throw TypeError("StringKeyProvider invalid authInfo.")
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async getAuth(id) {
|
|
44
|
-
return this.AUTH.get(id)
|
|
45
|
-
}
|
|
46
|
-
async getAuthIdList() {
|
|
47
|
-
return Array.from(this.AUTH.keys())
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
addAuth(id, keyStr, cid, level = 0) {
|
|
51
|
-
let Base64hashKey = Buffer.from(Boho.sha256.hash(keyStr)).toString('base64')
|
|
52
|
-
this.AUTH.set(id, { key: Base64hashKey, cid: cid, level: level })
|
|
53
|
-
}
|
|
54
|
-
}
|
package/src/client/CongPacket.js
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { Transform } from 'stream'
|
|
2
|
-
import MBP from 'meta-buffer-pack'
|
|
3
|
-
|
|
4
|
-
export const CongType = {
|
|
5
|
-
TYPE_LEN1: 1,
|
|
6
|
-
TYPE_LEN2: 2,
|
|
7
|
-
TYPE_LEN3: 3,
|
|
8
|
-
TYPE_LEN4: 4
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// support LittleEndian system.
|
|
12
|
-
export function pack(payload) {
|
|
13
|
-
|
|
14
|
-
if( payload.byteLength == undefined ) payload = Buffer.from(payload)
|
|
15
|
-
|
|
16
|
-
if (payload.byteLength < 256) { //one byte len
|
|
17
|
-
return MBP.pack(
|
|
18
|
-
MBP.MB('#type', '8', CongType.TYPE_LEN1),
|
|
19
|
-
MBP.MB('#payloadLen1', '8', payload.byteLength),
|
|
20
|
-
MBP.MB('#payload', payload)
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
} else if (payload.byteLength < 65536) { // 2bytes len
|
|
24
|
-
return MBP.pack(
|
|
25
|
-
MBP.MB('#type', '8', CongType.TYPE_LEN2),
|
|
26
|
-
MBP.MB('#payloadLen2', '16L', payload.byteLength),
|
|
27
|
-
MBP.MB('#payload', payload)
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
} else if (payload.byteLength < 2 ** 24) { // 3bytes len
|
|
31
|
-
let len4Buffer = Buffer.alloc(4)
|
|
32
|
-
len4Buffer.writeUint32LE(payload.byteLength)
|
|
33
|
-
let cropLen3 = len4Buffer.subarray(0, 3)
|
|
34
|
-
return MBP.pack(
|
|
35
|
-
MBP.MB('#type', '8', CongType.TYPE_LEN3),
|
|
36
|
-
MBP.MB('#payloadLen3', cropLen3),
|
|
37
|
-
MBP.MB('#payload', payload)
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
} else { //use 4 bytes.
|
|
41
|
-
return MBP.pack(
|
|
42
|
-
MBP.MB('#type', '8', CongType.TYPE_LEN4),
|
|
43
|
-
MBP.MB('#payloadLen4', '32L', payload.byteLength),
|
|
44
|
-
MBP.MB('#payload', payload)
|
|
45
|
-
)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export class CongRx extends Transform {
|
|
51
|
-
constructor(options) {
|
|
52
|
-
super(options)
|
|
53
|
-
this.buffer = Buffer.alloc(0)
|
|
54
|
-
this.frames = []
|
|
55
|
-
this.rxi = 0;
|
|
56
|
-
this.rxi_zero = 0;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
_transform(chunk, encoding, callback) {
|
|
62
|
-
this.addData(chunk)
|
|
63
|
-
if (this.frames.length > 0) {
|
|
64
|
-
this.frames.forEach(frame => {
|
|
65
|
-
this.push(frame)
|
|
66
|
-
})
|
|
67
|
-
this.frames = []
|
|
68
|
-
}
|
|
69
|
-
callback()
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
addData(chunk) {
|
|
74
|
-
let c = chunk.byteLength;
|
|
75
|
-
let i = 0;
|
|
76
|
-
while (c--) {
|
|
77
|
-
this.rxi++
|
|
78
|
-
if (chunk[i++] == 0) {
|
|
79
|
-
this.rxi_zero++
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (this.buffer.byteLength > 0) {
|
|
84
|
-
this.buffer = Buffer.concat([this.buffer, chunk])
|
|
85
|
-
} else {
|
|
86
|
-
this.buffer = chunk
|
|
87
|
-
}
|
|
88
|
-
this.parse()
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
parse() {
|
|
93
|
-
let head = this.buffer[0]
|
|
94
|
-
let headerLen;
|
|
95
|
-
let payloadSize;
|
|
96
|
-
|
|
97
|
-
if (head == CongType.TYPE_LEN1) {
|
|
98
|
-
headerLen = 2;
|
|
99
|
-
if (this.buffer.byteLength < headerLen) return;
|
|
100
|
-
payloadSize = this.buffer.readUint8(1)
|
|
101
|
-
|
|
102
|
-
} else if (head == CongType.TYPE_LEN2) {
|
|
103
|
-
headerLen = 3;
|
|
104
|
-
if (this.buffer.byteLength < headerLen) return;
|
|
105
|
-
payloadSize = this.buffer.readUint16LE(1)
|
|
106
|
-
|
|
107
|
-
} else if (head == CongType.TYPE_LEN3) {
|
|
108
|
-
headerLen = 4;
|
|
109
|
-
if (this.buffer.byteLength < headerLen) return;
|
|
110
|
-
payloadSize = this.buffer.readUint16LE(1) + this.buffer.readUint8(3) * 65536
|
|
111
|
-
|
|
112
|
-
} else if (head == CongType.TYPE_LEN4) {
|
|
113
|
-
headerLen = 5;
|
|
114
|
-
if (this.buffer.byteLength < headerLen) return;
|
|
115
|
-
payloadSize = this.buffer.readUint32LE(1)
|
|
116
|
-
|
|
117
|
-
} else {
|
|
118
|
-
this.emit('wrong', this.buffer)
|
|
119
|
-
this.buffer = Buffer.alloc(0)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (payloadSize == this.buffer.byteLength - headerLen) {
|
|
124
|
-
this.frames.push(this.buffer.subarray(headerLen))
|
|
125
|
-
this.buffer = Buffer.alloc(0)
|
|
126
|
-
return
|
|
127
|
-
} else if (payloadSize < this.buffer.byteLength - headerLen) {
|
|
128
|
-
this.frames.push(this.buffer.subarray(headerLen, headerLen + payloadSize))
|
|
129
|
-
this.buffer = this.buffer.subarray(headerLen + payloadSize)
|
|
130
|
-
this.parse()
|
|
131
|
-
} else {
|
|
132
|
-
// not ready
|
|
133
|
-
// console.log('+')
|
|
134
|
-
return
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { IOCore } from "./IOCore.js"
|
|
2
|
-
import { SIZE_LIMIT } from "../common/constants.js";
|
|
3
|
-
import { pack, CongRx } from './CongPacket.js'
|
|
4
|
-
import net from 'net'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export class IOCongSocket extends IOCore {
|
|
8
|
-
constructor(url) {
|
|
9
|
-
super(url);
|
|
10
|
-
if (url) this.open();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Closes TCP socket and cleans resources.
|
|
15
|
-
*/
|
|
16
|
-
close() {
|
|
17
|
-
if (this.socket) {
|
|
18
|
-
if (this.congRx) {
|
|
19
|
-
this.socket.unpipe(this.congRx);
|
|
20
|
-
this.congRx.destroy(); // Use destroy() for complete stream cleanup
|
|
21
|
-
this.congRx = null;
|
|
22
|
-
}
|
|
23
|
-
this.socket.removeAllListeners();
|
|
24
|
-
if (!this.socket.destroyed) {
|
|
25
|
-
this.socket.destroy(); // destroy() is sufficient for forceful closing
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
super.close();
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
keepConnection() {
|
|
34
|
-
if (!this.autoReconnect) return;
|
|
35
|
-
// Reconnect only if the socket is fully destroyed and the state is closed.
|
|
36
|
-
if ((!this.socket || this.socket.destroyed)) {
|
|
37
|
-
this.open();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
createConnection(url) {
|
|
43
|
-
// TCP Socket
|
|
44
|
-
let urlObj = new URL(url)
|
|
45
|
-
if (urlObj.protocol != "cong:") {
|
|
46
|
-
urlObj = new URL('cong://' + url)
|
|
47
|
-
}
|
|
48
|
-
this.socket = net.createConnection(urlObj.port, urlObj.hostname)
|
|
49
|
-
this.stateChange('connecting','connecting')
|
|
50
|
-
|
|
51
|
-
this.socket.on('connect', () => {
|
|
52
|
-
this.congRx = new CongRx();
|
|
53
|
-
this.socket.pipe(this.congRx)
|
|
54
|
-
this.congRx.on("data", this.onTCPSocketMessage.bind(this));
|
|
55
|
-
this.emit('open')
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
this.socket.on('error', e => {
|
|
59
|
-
this.emit('error', e)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
this.socket.on('close', () => {
|
|
63
|
-
this.emit('close');
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
onTCPSocketMessage(data) {
|
|
69
|
-
this.rxCounter++;
|
|
70
|
-
this.rxBytes += data.byteLength
|
|
71
|
-
this.lastTxRxTime = Date.now();
|
|
72
|
-
this.emit('socket_data', data);
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
socket_send(data) {
|
|
77
|
-
if (this.socket?.readyState === 'open') {
|
|
78
|
-
let packData = pack(data);
|
|
79
|
-
this.socket.write(packData)
|
|
80
|
-
this.txCounter++;
|
|
81
|
-
this.txBytes += packData.byteLength;
|
|
82
|
-
this.lastTxRxTime = Date.now();
|
|
83
|
-
} else {
|
|
84
|
-
console.log('.')
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|