dsh-mobile-plugin 0.1.82 → 0.1.84
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 +8 -5
- package/lib/client.js +43 -50
- package/lib/impl.js +2 -2
- package/lib/mirror/pusher.cjs +2 -0
- package/lib/mobile/archive-clean.js +15 -38
- package/lib/mobile/completion.js +58 -36
- package/lib/mobile/session-cache.js +31 -24
- package/lib/mobile/session-send.js +3 -2
- package/lib/relay/tunnel.js +30 -9
- package/lib/session-cleanup.cjs +96 -17
- package/lib/shell/device-ota.js +81 -51
- package/lib/shell/manager.js +22 -3
- package/lib/shell/ota-package.js +237 -0
- package/lib/sidecar-facade-worker.cjs +65 -9
- package/package.json +1 -1
|
@@ -160,6 +160,41 @@ function snapshotRead(info) {
|
|
|
160
160
|
}
|
|
161
161
|
return body
|
|
162
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* 「这份配置里哪几项决定隧道要重建」。
|
|
165
|
+
*
|
|
166
|
+
* 只有决定**连到哪台、以谁的身份连**的字段在这里。配对码、名字、局域网候选都
|
|
167
|
+
* 不在此列——它们能在现有连接上重报一次注册信息就生效(见 reannounceRegistration)。
|
|
168
|
+
*
|
|
169
|
+
* 为什么要把这条显式写出来:以前 `configure()` 是无条件 `stopServices()` 把隧道和
|
|
170
|
+
* 局域网代理一起拆了重建,于是每次配置下发(哪怕一个字段没变)都是一次全断。真机
|
|
171
|
+
* 现场就是「切个网络,接下来几秒点什么都失败」,宿主日志里是一串「隧道关闭 + 局域网
|
|
172
|
+
* 代理开始监听」,跑几小时后内存堆到几个 G 把宿主撑爆。
|
|
173
|
+
*/
|
|
174
|
+
function tunnelSignature(c) {
|
|
175
|
+
return JSON.stringify([Boolean(c.enabled), c.relayUrl || '', c.instanceId || '', c.upstreamPort || 0, c.registerSecret || ''])
|
|
176
|
+
}
|
|
177
|
+
/** 「这份配置里哪几项决定局域网代理要重建」。 */
|
|
178
|
+
function lanSignature(c) {
|
|
179
|
+
return JSON.stringify([Boolean(c.enabled), Boolean(c.lanEnabled), c.lanPort || 0, c.upstreamPort || 0, c.instanceId || '', c.pairingCode || '', c.lanSecret || ''])
|
|
180
|
+
}
|
|
181
|
+
/** 「这份配置里哪几项决定网络监视器要不要重排」。 */
|
|
182
|
+
function monitorSignature(c) {
|
|
183
|
+
return JSON.stringify([Boolean(c.enabled), c.relayUrl || '', Boolean(c.lanEnabled)])
|
|
184
|
+
}
|
|
185
|
+
/** 当前应该上报给中转的局域网候选。 */
|
|
186
|
+
function currentLanUrls() { return config.lanEnabled ? lanUrls(lanUrlPort()) : [] }
|
|
187
|
+
/**
|
|
188
|
+
* 局域网候选变了:只重报注册信息,**不重建隧道**。
|
|
189
|
+
*
|
|
190
|
+
* 重建一次要把手机所有在途请求连同局域网监听一起拆掉,而这条路径(地址变化、实际
|
|
191
|
+
* 端口与首选端口不一致)本来就只是「名片上的地址要更新」。隧道还没连上时不用额外
|
|
192
|
+
* 做事:下一次 startTunnel 会按当前状态现算候选。
|
|
193
|
+
*/
|
|
194
|
+
function reannounceRegistration() {
|
|
195
|
+
if (!tunnel) return
|
|
196
|
+
tunnel.updateRegistration({ lanUrls: currentLanUrls() })
|
|
197
|
+
}
|
|
163
198
|
function stopNetworkMonitor() {
|
|
164
199
|
if (networkTimer) { clearInterval(networkTimer); networkTimer = null }
|
|
165
200
|
}
|
|
@@ -178,8 +213,7 @@ function startNetworkMonitor() {
|
|
|
178
213
|
const current = lanUrls(lanUrlPort())
|
|
179
214
|
if (JSON.stringify(current) === JSON.stringify(previous)) return
|
|
180
215
|
previous = current
|
|
181
|
-
|
|
182
|
-
startTunnel()
|
|
216
|
+
reannounceRegistration()
|
|
183
217
|
}, NETWORK_POLL_MS)
|
|
184
218
|
}
|
|
185
219
|
function stopLan() {
|
|
@@ -196,7 +230,7 @@ function startTunnel() {
|
|
|
196
230
|
relayUrl: core.tunnelWsUrl(config.relayUrl), instanceId: config.instanceId, pairingCode: config.pairingCode,
|
|
197
231
|
name: config.name, upstream: upstream(),
|
|
198
232
|
registerSecret: config.registerSecret,
|
|
199
|
-
lanUrls:
|
|
233
|
+
lanUrls: currentLanUrls(),
|
|
200
234
|
readSnapshot: snapshotRead,
|
|
201
235
|
// 实例身份守卫:只有还活着的那个隧道实例才许改状态。onClose / onPairRequest /
|
|
202
236
|
// start().catch 都有这道闸,只有 onRegistered 漏了——而它恰恰是最容易迟到的一个
|
|
@@ -251,9 +285,9 @@ function startLan() {
|
|
|
251
285
|
if (bound > 0) lanBoundPort = bound
|
|
252
286
|
publishState()
|
|
253
287
|
// 实际端口和首选端口不同时,中转侧那份 lanUrls(注册时随 metadata 上报的)
|
|
254
|
-
//
|
|
255
|
-
//
|
|
256
|
-
if (changed
|
|
288
|
+
// 带的就是首选端口,手机从公网拿到的局域网候选全是死地址。重报一次注册信息就
|
|
289
|
+
// 够了——重建隧道会把手机在途请求全掐掉,代价远大于这条名片更新。
|
|
290
|
+
if (changed) reannounceRegistration()
|
|
257
291
|
}).catch(error => { if (lan === current) { lanState = 'error'; lanError = error instanceof Error ? error.message : String(error); publishState() } })
|
|
258
292
|
}
|
|
259
293
|
async function configure(next) {
|
|
@@ -265,12 +299,34 @@ async function configure(next) {
|
|
|
265
299
|
if (typeof next.upstreamPort !== 'number' || !Number.isInteger(next.upstreamPort) || next.upstreamPort < 1 || next.upstreamPort > 65535) throw new Error('invalid upstreamPort')
|
|
266
300
|
if (next.lanPort !== undefined && (!Number.isInteger(next.lanPort) || next.lanPort < 1024 || next.lanPort > 65535)) throw new Error('invalid lanPort')
|
|
267
301
|
if (next.registerSecret !== undefined && (typeof next.registerSecret !== 'string' || next.registerSecret.length > 512)) throw new Error('invalid registerSecret')
|
|
268
|
-
|
|
302
|
+
// 只重建真正变了的那一半:
|
|
303
|
+
// - 决定隧道「连到哪台、以谁的身份连」的字段变了才重建隧道;
|
|
304
|
+
// - 决定局域网监听的字段变了才重建局域网代理;
|
|
305
|
+
// - 其余(配对码 / 名字 / 局域网候选)在现有连接上重报一次注册信息即可。
|
|
306
|
+
// 无条件全拆全建就是「每隔几分钟断一次 + 内存一直涨」的根因,别改回去。
|
|
307
|
+
const previous = config
|
|
308
|
+
const tunnelNeedsRebuild = tunnelSignature(previous) !== tunnelSignature(next)
|
|
309
|
+
const lanNeedsRebuild = lanSignature(previous) !== lanSignature(next)
|
|
310
|
+
const monitorNeedsRestart = monitorSignature(previous) !== monitorSignature(next)
|
|
269
311
|
config = { ...next }
|
|
270
|
-
if (
|
|
312
|
+
if (tunnelNeedsRebuild) {
|
|
313
|
+
stopTunnel()
|
|
271
314
|
startTunnel()
|
|
315
|
+
}
|
|
316
|
+
if (lanNeedsRebuild) {
|
|
317
|
+
stopLan()
|
|
318
|
+
startLan()
|
|
319
|
+
}
|
|
320
|
+
if (!tunnelNeedsRebuild && tunnel) {
|
|
321
|
+
const patch = {}
|
|
322
|
+
if (previous.pairingCode !== config.pairingCode) patch.pairingCode = config.pairingCode
|
|
323
|
+
if (previous.name !== config.name) patch.name = config.name
|
|
324
|
+
if (lanNeedsRebuild) patch.lanUrls = currentLanUrls()
|
|
325
|
+
if (Object.keys(patch).length) tunnel.updateRegistration(patch)
|
|
326
|
+
}
|
|
327
|
+
if (monitorNeedsRestart) {
|
|
328
|
+
stopNetworkMonitor()
|
|
272
329
|
startNetworkMonitor()
|
|
273
|
-
if (config.lanEnabled) startLan()
|
|
274
330
|
}
|
|
275
331
|
return status()
|
|
276
332
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mobile-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.84",
|
|
4
4
|
"description": "Mobile API (/api/mobile/v1) and relay client for the DSH mobile app — desktop profile build (0.2.0-rc.2 compatible, peers resolved by the host)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|