@steve02081504/fount-p2p 0.0.8 → 0.0.9
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/discovery/bt/index.mjs +8 -14
- package/discovery/index.mjs +12 -17
- package/files/chunk_responder.mjs +4 -8
- package/link/rtc.mjs +1 -1
- package/package.json +1 -1
- package/transport/link_registry.mjs +2 -8
package/discovery/bt/index.mjs
CHANGED
|
@@ -252,14 +252,15 @@ export function createBluetoothDiscoveryProvider() {
|
|
|
252
252
|
|
|
253
253
|
/**
|
|
254
254
|
* Central:按 peer hint 连接并对端 signal characteristic 写短包。
|
|
255
|
+
* 无 hint 时返回 false(正常降级,不算错误)。
|
|
255
256
|
* @param {string} topic 信令 topic
|
|
256
257
|
* @param {string} to 目标 nodeHash
|
|
257
258
|
* @param {Uint8Array} bytes 载荷
|
|
258
|
-
* @returns {Promise<
|
|
259
|
+
* @returns {Promise<boolean>} 是否投递
|
|
259
260
|
*/
|
|
260
261
|
async function sendSignalViaGatt(topic, to, bytes) {
|
|
261
262
|
const hint = getBtPeerHint(to)
|
|
262
|
-
if (!hint)
|
|
263
|
+
if (!hint) return false
|
|
263
264
|
const blob = Buffer.from(JSON.stringify({
|
|
264
265
|
topic: String(topic),
|
|
265
266
|
to: String(to),
|
|
@@ -324,20 +325,13 @@ export function createBluetoothDiscoveryProvider() {
|
|
|
324
325
|
finally {
|
|
325
326
|
try { await peripheral.disconnectAsync() } catch { /* ignore */ }
|
|
326
327
|
}
|
|
328
|
+
return true
|
|
327
329
|
}
|
|
328
330
|
|
|
329
331
|
return {
|
|
330
332
|
id: 'bt',
|
|
331
333
|
priority: 20,
|
|
332
334
|
caps: { canDiscover: true, canSignal: true, canRelay: false },
|
|
333
|
-
/**
|
|
334
|
-
* 是否具备对该 peer 的 GATT 信令能力(需未过期 BT peer hint)。
|
|
335
|
-
* @param {string} to 目标 nodeHash
|
|
336
|
-
* @returns {boolean} 有 hint 则可尝试
|
|
337
|
-
*/
|
|
338
|
-
canSignalTo(to) {
|
|
339
|
-
return !!getBtPeerHint(to)
|
|
340
|
-
},
|
|
341
335
|
/**
|
|
342
336
|
* 广播指定 topic 的 advert。
|
|
343
337
|
* @param {string} topic advert 主题
|
|
@@ -364,14 +358,14 @@ export function createBluetoothDiscoveryProvider() {
|
|
|
364
358
|
return addListener(advertListeners, String(topic), onAdvert)
|
|
365
359
|
},
|
|
366
360
|
/**
|
|
367
|
-
* 经 GATT 向近场 peer
|
|
361
|
+
* 经 GATT 向近场 peer 发送信令;无 peer hint 时返回 false。
|
|
368
362
|
* @param {string} topic 信令 topic
|
|
369
363
|
* @param {string} to 目标 nodeHash
|
|
370
364
|
* @param {Uint8Array} bytes 载荷
|
|
371
|
-
* @returns {Promise<
|
|
365
|
+
* @returns {Promise<boolean>} 是否投递
|
|
372
366
|
*/
|
|
373
|
-
|
|
374
|
-
|
|
367
|
+
sendSignal(topic, to, bytes) {
|
|
368
|
+
return sendSignalViaGatt(topic, to, bytes)
|
|
375
369
|
},
|
|
376
370
|
/**
|
|
377
371
|
* 监听经本机 peripheral signal characteristic 写入的信令。
|
package/discovery/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @typedef {{ id: string, priority: number, caps: { canDiscover?: boolean, canSignal?: boolean, canRelay?: boolean }, advertise?: (topic: string, bytes: Uint8Array) => (() => void) | Promise<() => void>, subscribe?: (topic: string, onAdvert: (bytes: Uint8Array, meta?: object) => void) => (() => void) | Promise<() => void>,
|
|
1
|
+
/** @typedef {{ id: string, priority: number, caps: { canDiscover?: boolean, canSignal?: boolean, canRelay?: boolean }, advertise?: (topic: string, bytes: Uint8Array) => (() => void) | Promise<() => void>, subscribe?: (topic: string, onAdvert: (bytes: Uint8Array, meta?: object) => void) => (() => void) | Promise<() => void>, sendSignal?: (topic: string, to: string, bytes: Uint8Array) => boolean | void | Promise<boolean | void>, onSignal?: (topic: string, onSignal: (bytes: Uint8Array, meta?: object) => void) => (() => void) | Promise<() => void> }} DiscoveryProvider */
|
|
2
2
|
|
|
3
3
|
/** @type {Map<string, DiscoveryProvider>} */
|
|
4
4
|
const providers = new Map()
|
|
@@ -33,6 +33,7 @@ export function listDiscoveryProviders() {
|
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* 通过所有可用 provider 广播 topic advert。
|
|
36
|
+
* 单路失败静默(正常降级);其它 provider 仍可成功。
|
|
36
37
|
* @param {string} topic advert 主题
|
|
37
38
|
* @param {Uint8Array} bytes advert 载荷
|
|
38
39
|
* @returns {Promise<() => void>} 统一取消函数
|
|
@@ -45,10 +46,7 @@ export async function advertiseTopic(topic, bytes) {
|
|
|
45
46
|
try {
|
|
46
47
|
cleanup = await provider.advertise(topic, bytes)
|
|
47
48
|
}
|
|
48
|
-
catch
|
|
49
|
-
console.warn(`p2p: discovery advertise failed for ${provider.id}`, error)
|
|
50
|
-
continue
|
|
51
|
-
}
|
|
49
|
+
catch { continue }
|
|
52
50
|
if (typeof cleanup === 'function') cleanups.push(cleanup)
|
|
53
51
|
}
|
|
54
52
|
return () => {
|
|
@@ -59,6 +57,7 @@ export async function advertiseTopic(topic, bytes) {
|
|
|
59
57
|
|
|
60
58
|
/**
|
|
61
59
|
* 通过所有可用 provider 订阅 topic advert。
|
|
60
|
+
* 单路失败静默(正常降级)。
|
|
62
61
|
* @param {string} topic advert 主题
|
|
63
62
|
* @param {(bytes: Uint8Array, meta?: object) => void} onAdvert advert 回调
|
|
64
63
|
* @returns {Promise<() => void>} 统一取消函数
|
|
@@ -71,10 +70,7 @@ export async function subscribeTopic(topic, onAdvert) {
|
|
|
71
70
|
try {
|
|
72
71
|
cleanup = await provider.subscribe(topic, onAdvert)
|
|
73
72
|
}
|
|
74
|
-
catch
|
|
75
|
-
console.warn(`p2p: discovery subscribe failed for ${provider.id}`, error)
|
|
76
|
-
continue
|
|
77
|
-
}
|
|
73
|
+
catch { continue }
|
|
78
74
|
if (typeof cleanup === 'function') cleanups.push(cleanup)
|
|
79
75
|
}
|
|
80
76
|
return () => {
|
|
@@ -85,6 +81,8 @@ export async function subscribeTopic(topic, onAdvert) {
|
|
|
85
81
|
|
|
86
82
|
/**
|
|
87
83
|
* 通过 discovery provider 发送信令。
|
|
84
|
+
* provider 返回 `false` = 本路不可达(正常降级,不计成功);其它返回值 / void = 已投递。
|
|
85
|
+
* 单路 throw 静默;全部未投递才 throw。
|
|
88
86
|
* @param {string} topic 信令 topic
|
|
89
87
|
* @param {string} to 目标节点标识
|
|
90
88
|
* @param {Uint8Array} bytes 信令载荷
|
|
@@ -95,19 +93,19 @@ export async function sendSignal(topic, to, bytes) {
|
|
|
95
93
|
if (!capable.length) throw new Error('p2p: no discovery provider can signal')
|
|
96
94
|
let sent = false
|
|
97
95
|
let lastError = null
|
|
98
|
-
for (const provider of capable)
|
|
99
|
-
await Promise.resolve(provider.sendSignal(topic, to, bytes))
|
|
100
|
-
|
|
96
|
+
for (const provider of capable) try {
|
|
97
|
+
if (await Promise.resolve(provider.sendSignal(topic, to, bytes)) !== false)
|
|
98
|
+
sent = true
|
|
101
99
|
}
|
|
102
100
|
catch (error) {
|
|
103
101
|
lastError = error
|
|
104
|
-
console.warn(`p2p: discovery signal failed for ${provider.id}`, error)
|
|
105
102
|
}
|
|
106
103
|
if (!sent) throw lastError || new Error('p2p: no discovery provider delivered signal')
|
|
107
104
|
}
|
|
108
105
|
|
|
109
106
|
/**
|
|
110
107
|
* 通过所有可用 provider 监听信令。
|
|
108
|
+
* 单路失败静默(正常降级)。
|
|
111
109
|
* @param {string} topic 信令 topic
|
|
112
110
|
* @param {(bytes: Uint8Array, meta?: object) => void} onSignal 信令回调
|
|
113
111
|
* @returns {Promise<() => void>} 统一取消函数
|
|
@@ -120,10 +118,7 @@ export async function listenSignals(topic, onSignal) {
|
|
|
120
118
|
try {
|
|
121
119
|
cleanup = await provider.onSignal(topic, onSignal)
|
|
122
120
|
}
|
|
123
|
-
catch
|
|
124
|
-
console.warn(`p2p: discovery signal listener failed for ${provider.id}`, error)
|
|
125
|
-
continue
|
|
126
|
-
}
|
|
121
|
+
catch { continue }
|
|
127
122
|
if (typeof cleanup === 'function') cleanups.push(cleanup)
|
|
128
123
|
}
|
|
129
124
|
return () => {
|
|
@@ -94,14 +94,12 @@ export function attachTrustGraphFedChunkResponder(username, room, fedOut, guardG
|
|
|
94
94
|
*/
|
|
95
95
|
const send = () => {
|
|
96
96
|
try { sendChunkData(resp, pid) }
|
|
97
|
-
catch
|
|
98
|
-
console.warn('federation: trust-graph chunk response failed', error)
|
|
99
|
-
}
|
|
97
|
+
catch { /* peer gone — normal */ }
|
|
100
98
|
}
|
|
101
99
|
if (fedOut) fedOut.enqueue(6, send)
|
|
102
100
|
else send()
|
|
103
101
|
})
|
|
104
|
-
})().catch(
|
|
102
|
+
})().catch(() => { /* peer/handler race — normal degrade */ })
|
|
105
103
|
})
|
|
106
104
|
|
|
107
105
|
getChunkData(data => {
|
|
@@ -120,14 +118,12 @@ export function attachTrustGraphFedChunkResponder(username, room, fedOut, guardG
|
|
|
120
118
|
*/
|
|
121
119
|
const send = () => {
|
|
122
120
|
try { sendManifestData(resp, pid) }
|
|
123
|
-
catch
|
|
124
|
-
console.warn('federation: trust-graph manifest response failed', error)
|
|
125
|
-
}
|
|
121
|
+
catch { /* peer gone — normal */ }
|
|
126
122
|
}
|
|
127
123
|
if (fedOut) fedOut.enqueue(6, send)
|
|
128
124
|
else send()
|
|
129
125
|
})
|
|
130
|
-
})().catch(
|
|
126
|
+
})().catch(() => { /* peer/handler race — normal degrade */ })
|
|
131
127
|
})
|
|
132
128
|
|
|
133
129
|
getManifestData(data => {
|
package/link/rtc.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { wrapRtcPeerConnectionForMdns } from '../transport/rtc_mdns_filter.mjs'
|
|
|
8
8
|
* libdatachannel 的原生线程在 pc.close() 后仍需时间回收;进程退出时若原生资源未同步销毁,
|
|
9
9
|
* Windows 上会触发堆损坏(退出码 0xC0000374)。
|
|
10
10
|
*/
|
|
11
|
-
const { cleanup = undefined } = await import('node-datachannel').catch(
|
|
11
|
+
const { cleanup = undefined } = await import('node-datachannel').catch(() => ({}))
|
|
12
12
|
process.on('exit', () => {
|
|
13
13
|
try { cleanup?.() } catch { /* already torn down */ }
|
|
14
14
|
})
|
package/package.json
CHANGED
|
@@ -347,9 +347,7 @@ export function createLinkRegistry(options = {}) {
|
|
|
347
347
|
})
|
|
348
348
|
if (typeof stop === 'function') stopLinkListeners.push(stop)
|
|
349
349
|
}
|
|
350
|
-
catch
|
|
351
|
-
console.warn(`p2p: link provider listening failed for ${provider.id}`, error)
|
|
352
|
-
}
|
|
350
|
+
catch { /* provider listen unavailable — normal degrade */ }
|
|
353
351
|
|
|
354
352
|
if (listDiscoveryProviders().length) {
|
|
355
353
|
stopSignalListener = await listenSignals(selfTopic, bytes => {
|
|
@@ -591,16 +589,12 @@ export function createLinkRegistry(options = {}) {
|
|
|
591
589
|
// soft-fail 返回 null(不 throw);必须 continue 才能落到更低 level。
|
|
592
590
|
const link = await dialOfferAnswer(provider, normalized)
|
|
593
591
|
if (link) return link
|
|
594
|
-
console.warn(`p2p: link dial failed for ${provider.id}: soft-fail`)
|
|
595
592
|
continue
|
|
596
593
|
}
|
|
597
594
|
const link = await dialProvider(provider, normalized)
|
|
598
595
|
if (link) return link
|
|
599
|
-
console.warn(`p2p: link dial failed for ${provider.id}: soft-fail`)
|
|
600
|
-
}
|
|
601
|
-
catch (error) {
|
|
602
|
-
console.warn(`p2p: link dial failed for ${provider.id}: ${error?.message ?? error}`)
|
|
603
596
|
}
|
|
597
|
+
catch { /* dial failed — try next provider */ }
|
|
604
598
|
|
|
605
599
|
return null
|
|
606
600
|
})().finally(() => inflights.delete(normalized))
|