@steve02081504/fount-p2p 0.0.4 → 0.0.6
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/core/bytes_codec.mjs +0 -27
- package/core/constants.mjs +0 -31
- package/core/hexIds.mjs +0 -13
- package/crypto/key.mjs +14 -15
- package/dag/canonicalize_row.mjs +5 -5
- package/dag/index.mjs +0 -73
- package/dag/storage.mjs +0 -22
- package/discovery/mdns.mjs +4 -4
- package/discovery/nostr.mjs +3 -3
- package/federation/chunk_fetch_pending.mjs +3 -3
- package/federation/chunk_fetch_scheduler.mjs +3 -3
- package/federation/dag_order_cache.mjs +3 -3
- package/federation/entity_key_chain.mjs +0 -9
- package/federation/topo_order_memo.mjs +3 -18
- package/files/assemble.mjs +55 -39
- package/files/assemble_stream.mjs +96 -44
- package/files/chunk_provider_registry.mjs +0 -6
- package/files/chunk_responder.mjs +1 -1
- package/files/chunk_store.mjs +1 -11
- package/files/evfs.mjs +74 -47
- package/files/manifest.mjs +11 -2
- package/files/manifest_acl_registry.mjs +0 -6
- package/files/transfer_key.mjs +21 -15
- package/files/transfer_key_registry.mjs +9 -16
- package/governance/branch.mjs +0 -11
- package/governance/join_pow.mjs +17 -17
- package/link/channel_mux.mjs +9 -7
- package/link/frame.mjs +5 -5
- package/link/handshake.mjs +17 -17
- package/link/link.mjs +33 -33
- package/mailbox/deliver_or_store.mjs +13 -13
- package/mailbox/importance.mjs +0 -33
- package/mailbox/settings.mjs +0 -9
- package/mailbox/wire.mjs +4 -4
- package/node/denylist.mjs +0 -24
- package/node/network.mjs +0 -51
- package/node/personal_block.mjs +0 -35
- package/node/reputation_store.mjs +5 -14
- package/node/retention_policy.mjs +8 -23
- package/overlay/index.mjs +6 -6
- package/package.json +1 -1
- package/registries/event_type.mjs +0 -12
- package/registries/inbound.mjs +8 -30
- package/reputation/engine.mjs +0 -11
- package/rooms/scoped_link.mjs +18 -18
- package/schemas/part_query.mjs +156 -0
- package/timeline/append_core.mjs +3 -3
- package/transport/group_link_set.mjs +30 -30
- package/transport/ice_servers.mjs +0 -8
- package/transport/link_registry.mjs +13 -13
- package/transport/peer_identity_maps.mjs +0 -58
- package/transport/peer_pool.mjs +4 -4
- package/transport/remote_user_room.mjs +0 -12
- package/transport/rtc_connection_budget.mjs +2 -0
- package/transport/user_room.mjs +13 -24
- package/trust_graph/cache.mjs +0 -13
- package/trust_graph/engine.mjs +0 -24
- package/utils/async_mutex.mjs +0 -9
- package/wire/group_part.mjs +3 -3
- package/wire/part_fanout.mjs +0 -19
- package/wire/part_ingress.mjs +14 -14
- package/wire/part_query.mjs +486 -0
- package/wire/part_query.tunables.json +14 -0
- package/wire/part_query_cache.mjs +101 -0
|
@@ -34,61 +34,3 @@ export function pruneStaleRosterEntries(peerToNode, nodeToPeer, livePeerIds) {
|
|
|
34
34
|
}
|
|
35
35
|
return stale
|
|
36
36
|
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* 创建 peer id 与 nodeHash 双向映射及 roster 查询辅助。
|
|
40
|
-
* @param {object} [opts] 选项
|
|
41
|
-
* @param {() => Iterable<string>} [opts.getLivePeerIds] 获取当前在线 peer id 的回调
|
|
42
|
-
* @param {(stale: Array<{ peerId: string, remoteNodeHash?: string }>) => void} [opts.onStalePruned] stale 条目被清理时的回调
|
|
43
|
-
* @returns {{ peerToNode: Map<string, string>, nodeToPeer: Map<string, string>, getRoster: () => Array<{ peerId: string, remoteNodeHash: string | undefined }>, getPeerIdByNodeHash: (nodeHash: string) => string | null, onPeerLeave: (peerId: string) => void }} 映射与查询接口
|
|
44
|
-
*/
|
|
45
|
-
export function createPeerIdentityMaps(opts = {}) {
|
|
46
|
-
/** @type {Map<string, string>} */
|
|
47
|
-
const peerToNode = new Map()
|
|
48
|
-
/** @type {Map<string, string>} */
|
|
49
|
-
const nodeToPeer = new Map()
|
|
50
|
-
const getLivePeerIds = typeof opts.getLivePeerIds === 'function' ? opts.getLivePeerIds : null
|
|
51
|
-
const onStalePruned = typeof opts.onStalePruned === 'function' ? opts.onStalePruned : null
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* 根据 live peer 集合清理 stale 映射。
|
|
55
|
-
* @returns {void}
|
|
56
|
-
*/
|
|
57
|
-
const reconcile = () => {
|
|
58
|
-
if (!getLivePeerIds) return
|
|
59
|
-
const stale = pruneStaleRosterEntries(peerToNode, nodeToPeer, getLivePeerIds())
|
|
60
|
-
if (stale.length && onStalePruned) onStalePruned(stale)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return {
|
|
64
|
-
peerToNode,
|
|
65
|
-
nodeToPeer,
|
|
66
|
-
/**
|
|
67
|
-
* 返回当前 roster(会先 reconcile stale 条目)。
|
|
68
|
-
* @returns {Array<{ peerId: string, remoteNodeHash: string | undefined }>} roster 列表
|
|
69
|
-
*/
|
|
70
|
-
getRoster() {
|
|
71
|
-
reconcile()
|
|
72
|
-
return [...peerToNode.entries()].map(([peerId, remoteNodeHash]) => ({ peerId, remoteNodeHash }))
|
|
73
|
-
},
|
|
74
|
-
/**
|
|
75
|
-
* 按 nodeHash 查找对应 peer id。
|
|
76
|
-
* @param {string} targetNodeHash 目标节点 64 hex
|
|
77
|
-
* @returns {string | null} 对端 id;无映射时为 null
|
|
78
|
-
*/
|
|
79
|
-
getPeerIdByNodeHash(targetNodeHash) {
|
|
80
|
-
reconcile()
|
|
81
|
-
return nodeToPeer.get(String(targetNodeHash).trim().toLowerCase()) || null
|
|
82
|
-
},
|
|
83
|
-
/**
|
|
84
|
-
* peer 离线时从映射中移除。
|
|
85
|
-
* @param {string} peerId 离线的 peer id
|
|
86
|
-
* @returns {void}
|
|
87
|
-
*/
|
|
88
|
-
onPeerLeave(peerId) {
|
|
89
|
-
const remote = peerToNode.get(peerId)
|
|
90
|
-
if (remote) nodeToPeer.delete(remote)
|
|
91
|
-
peerToNode.delete(peerId)
|
|
92
|
-
},
|
|
93
|
-
}
|
|
94
|
-
}
|
package/transport/peer_pool.mjs
CHANGED
|
@@ -141,7 +141,7 @@ export function selectExploreWithSourceQuota(exploreIds, exploreSources, k, maxP
|
|
|
141
141
|
* selfNodeHash: string,
|
|
142
142
|
* inRoomNodeHashes?: Set<string> | string[] 群内在线 node_id;有则优先,仅全不可达时用 explore 中非房内节点
|
|
143
143
|
* hintSources?: Map<string, string> explore 节点来源(用于配额)
|
|
144
|
-
* }}
|
|
144
|
+
* }} options 选取参数(roster、peers、rep、limits、selfNodeHash)
|
|
145
145
|
* @returns {string[]} 目标 Trystero peerId 列表(去重,长度 ≤ maxPeers)
|
|
146
146
|
*/
|
|
147
147
|
export function selectPeerIdsFromPool({ roster, peers, rep, limits, selfNodeHash, inRoomNodeHashes, hintSources }) {
|
|
@@ -212,7 +212,7 @@ export function selectPeerIdsFromPool({ roster, peers, rep, limits, selfNodeHash
|
|
|
212
212
|
* peers: { trustedPeers: string[], explorePeers: string[], blockedPeers: string[], hintSources?: Map<string, string> },
|
|
213
213
|
* limits: ReturnType<typeof resolveFederationPoolLimits>,
|
|
214
214
|
* anchors?: Iterable<string>,
|
|
215
|
-
* }}
|
|
215
|
+
* }} options 选取参数(members、selfNodeHash、rep、peers、limits、anchors)
|
|
216
216
|
* @returns {string[]} 应建链的 nodeHash 列表(去重)
|
|
217
217
|
*/
|
|
218
218
|
export function selectLinkTargetsFromMembers({ members, selfNodeHash, rep, peers, limits, anchors = [] }) {
|
|
@@ -245,7 +245,7 @@ export function selectLinkTargetsFromMembers({ members, selfNodeHash, rep, peers
|
|
|
245
245
|
* rep: { byNodeHash?: Record<string, { score?: number }> },
|
|
246
246
|
* hints: string[],
|
|
247
247
|
* limits: ReturnType<typeof resolveFederationPoolLimits>,
|
|
248
|
-
* }}
|
|
248
|
+
* }} options 合并参数(peers、rep、hints、limits)
|
|
249
249
|
* @returns {{ trustedPeers: string[], explorePeers: string[] }} 更新后的 trusted/explore 列表
|
|
250
250
|
*/
|
|
251
251
|
export function applyPexHints({ peers, rep, hints, limits }) {
|
|
@@ -275,7 +275,7 @@ export function applyPexHints({ peers, rep, hints, limits }) {
|
|
|
275
275
|
* rep: { byNodeHash?: Record<string, { score?: number }> },
|
|
276
276
|
* roster: Array<{ remoteNodeHash?: string }>,
|
|
277
277
|
* limits: ReturnType<typeof resolveFederationPoolLimits>,
|
|
278
|
-
* }}
|
|
278
|
+
* }} options roster 更新参数(peers、rep、roster、limits)
|
|
279
279
|
* @returns {{ trustedPeers: string[], explorePeers: string[] }} 更新后的 trusted/explore 列表
|
|
280
280
|
*/
|
|
281
281
|
export function applyRosterToPeerPool({ peers, rep, roster, limits }) {
|
|
@@ -95,15 +95,3 @@ export async function ensureRemoteUserRoom(username, targetNodeHash) {
|
|
|
95
95
|
inflights.set(key, task)
|
|
96
96
|
return await task
|
|
97
97
|
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* 释放目标节点的远端用户房间连接。
|
|
101
|
-
* @param {string} targetNodeHash 目标节点 64 hex
|
|
102
|
-
* @returns {void}
|
|
103
|
-
*/
|
|
104
|
-
export function releaseRemoteUserRoom(targetNodeHash) {
|
|
105
|
-
const key = targetNodeHash.toLowerCase()
|
|
106
|
-
const slot = slots.get(key)
|
|
107
|
-
if (slot) void Promise.resolve(slot.leave()).catch(() => { })
|
|
108
|
-
slots.delete(key)
|
|
109
|
-
}
|
package/transport/user_room.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import { attachMailboxWire } from '../mailbox/wire.mjs'
|
|
|
4
4
|
import { ensureNodeDefaults, getNodeHash } from '../node/identity.mjs'
|
|
5
5
|
import { registerFederationRoomProvider } from '../registries/room_provider.mjs'
|
|
6
6
|
import { attachPartWire } from '../wire/part_ingress.mjs'
|
|
7
|
+
import { attachPartQueryWire } from '../wire/part_query.mjs'
|
|
7
8
|
|
|
8
9
|
import { listLinks, sendToNodeLink, subscribeScope, getLinkRegistry } from './link_registry.mjs'
|
|
9
10
|
import { USER_ROOM_SCOPE } from './room_scopes.mjs'
|
|
@@ -90,12 +91,12 @@ function activeLinkRoster() {
|
|
|
90
91
|
|
|
91
92
|
/**
|
|
92
93
|
* 初始化 node scope 订阅与 wire 派发(幂等)。
|
|
93
|
-
* @param {{ replicaUsername?: string }}
|
|
94
|
+
* @param {{ replicaUsername?: string }} wireContext 入站上下文
|
|
94
95
|
* @returns {Promise<void>}
|
|
95
96
|
*/
|
|
96
|
-
async function ensureNodeScopeRuntime(
|
|
97
|
+
async function ensureNodeScopeRuntime(wireContext) {
|
|
97
98
|
if (nodeScopeCleanup) return
|
|
98
|
-
nodeScopeReplicaUsername = String(
|
|
99
|
+
nodeScopeReplicaUsername = String(wireContext.replicaUsername || nodeScopeReplicaUsername || '')
|
|
99
100
|
nodeScopeCleanup = subscribeScope('node', (senderNodeHash, envelope) => {
|
|
100
101
|
const handlers = nodeActionHandlers.get(String(envelope?.action || ''))
|
|
101
102
|
if (!handlers?.size) return
|
|
@@ -104,11 +105,12 @@ async function ensureNodeScopeRuntime(ctx) {
|
|
|
104
105
|
})
|
|
105
106
|
const wire = createNodeScopeWire()
|
|
106
107
|
nodeScopeWire = wire
|
|
107
|
-
attachPartWire({ replicaUsername:
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
attachPartWire({ replicaUsername: wireContext.replicaUsername }, wire)
|
|
109
|
+
attachPartQueryWire({ replicaUsername: wireContext.replicaUsername }, wire)
|
|
110
|
+
attachMailboxWire({ replicaUsername: wireContext.replicaUsername }, wire)
|
|
111
|
+
attachUserRoomChunkHandlers(wireContext.replicaUsername || '', wire)
|
|
110
112
|
for (const hook of nodeScopeWireHooks)
|
|
111
|
-
try { hook(
|
|
113
|
+
try { hook(wireContext.replicaUsername || '', wire) } catch { /* ignore */ }
|
|
112
114
|
}
|
|
113
115
|
|
|
114
116
|
/**
|
|
@@ -160,10 +162,10 @@ export function resolveUserRoomCredentials() {
|
|
|
160
162
|
}
|
|
161
163
|
|
|
162
164
|
/**
|
|
163
|
-
* @param {{ replicaUsername?: string }} [
|
|
165
|
+
* @param {{ replicaUsername?: string }} [wireContext] 入站上下文(part/mailbox 派发用)
|
|
164
166
|
* @returns {Promise<UserRoomSlot | null>} 用户级联邦房间槽
|
|
165
167
|
*/
|
|
166
|
-
export async function ensureUserRoom(
|
|
168
|
+
export async function ensureUserRoom(wireContext = {}) {
|
|
167
169
|
if (userRoomSlot) return userRoomSlot
|
|
168
170
|
if (userRoomInflight) return await userRoomInflight
|
|
169
171
|
|
|
@@ -171,7 +173,7 @@ export async function ensureUserRoom(ctx = {}) {
|
|
|
171
173
|
ensureNodeDefaults()
|
|
172
174
|
try {
|
|
173
175
|
await getLinkRegistry().ensureRuntime()
|
|
174
|
-
await ensureNodeScopeRuntime(
|
|
176
|
+
await ensureNodeScopeRuntime(wireContext)
|
|
175
177
|
const creds = resolveUserRoomCredentials()
|
|
176
178
|
/** @type {UserRoomSlot} */
|
|
177
179
|
userRoomSlot = {
|
|
@@ -217,17 +219,6 @@ export async function ensureUserRoom(ctx = {}) {
|
|
|
217
219
|
return await userRoomInflight
|
|
218
220
|
}
|
|
219
221
|
|
|
220
|
-
/**
|
|
221
|
-
* @returns {void}
|
|
222
|
-
*/
|
|
223
|
-
export function invalidateUserRoom() {
|
|
224
|
-
userRoomSlot = null
|
|
225
|
-
userRoomInflight = null
|
|
226
|
-
nodeScopeWire = null
|
|
227
|
-
nodeScopeReplicaUsername = ''
|
|
228
|
-
nodeScopeCleanup = null
|
|
229
|
-
}
|
|
230
|
-
|
|
231
222
|
/**
|
|
232
223
|
* @param {string} username 副本用户名
|
|
233
224
|
* @param {string} actionName 节点 scope action
|
|
@@ -247,9 +238,7 @@ export async function deliverToUserRoomPeers(username, actionName, payload, exce
|
|
|
247
238
|
.filter(({ peerId }) => peerId && peerId !== exceptPeerId)]
|
|
248
239
|
for (let swapIndex = peers.length - 1; swapIndex > 0; swapIndex--) {
|
|
249
240
|
const pickIndex = Math.floor(Math.random() * (swapIndex + 1))
|
|
250
|
-
|
|
251
|
-
peers[swapIndex] = peers[pickIndex]
|
|
252
|
-
peers[pickIndex] = tmp
|
|
241
|
+
;[peers[swapIndex], peers[pickIndex]] = [peers[pickIndex], peers[swapIndex]]
|
|
253
242
|
}
|
|
254
243
|
for (const { peerId } of peers)
|
|
255
244
|
try {
|
package/trust_graph/cache.mjs
CHANGED
|
@@ -4,13 +4,6 @@ let revision = 0
|
|
|
4
4
|
|
|
5
5
|
const DEFAULT_TTL_MS = 30_000
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* @returns {number} 当前 revision
|
|
9
|
-
*/
|
|
10
|
-
export function getTrustGraphRevision() {
|
|
11
|
-
return revision
|
|
12
|
-
}
|
|
13
|
-
|
|
14
7
|
/**
|
|
15
8
|
* @returns {void}
|
|
16
9
|
*/
|
|
@@ -36,9 +29,3 @@ export async function getCachedTrustGraph(username, build, ttlMs = DEFAULT_TTL_M
|
|
|
36
29
|
cacheByUsername.set(key, { graph, builtAt: now, revision })
|
|
37
30
|
return graph
|
|
38
31
|
}
|
|
39
|
-
|
|
40
|
-
/** @returns {void} 测试用 */
|
|
41
|
-
export function clearTrustGraphCache() {
|
|
42
|
-
cacheByUsername.clear()
|
|
43
|
-
revision = 0
|
|
44
|
-
}
|
package/trust_graph/engine.mjs
CHANGED
|
@@ -17,30 +17,6 @@ import trustGraphTunables from './tunables.json' with { type: 'json' }
|
|
|
17
17
|
* }} TrustGraphInputs
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
/**
|
|
21
|
-
* @returns {typeof trustGraphTunables} 默认 tunables
|
|
22
|
-
*/
|
|
23
|
-
export function defaultTrustGraphTunables() {
|
|
24
|
-
return trustGraphTunables
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @param {Map<string, TrustNode>} byNode 累积图
|
|
29
|
-
* @param {string} scopeId scope 标识
|
|
30
|
-
* @param {string} nodeHash 64 位十六进制
|
|
31
|
-
* @param {number} score 信誉分
|
|
32
|
-
*/
|
|
33
|
-
export function mergeTrustNode(byNode, scopeId, nodeHash, score) {
|
|
34
|
-
const previous = byNode.get(nodeHash)
|
|
35
|
-
if (previous) {
|
|
36
|
-
const seenCount = previous.scopeIds.length
|
|
37
|
-
previous.score = (previous.score * seenCount + score) / (seenCount + 1)
|
|
38
|
-
if (!previous.scopeIds.includes(scopeId)) previous.scopeIds.push(scopeId)
|
|
39
|
-
return
|
|
40
|
-
}
|
|
41
|
-
byNode.set(nodeHash, { nodeHash, score, scopeIds: [scopeId] })
|
|
42
|
-
}
|
|
43
|
-
|
|
44
20
|
/**
|
|
45
21
|
* @param {TrustGraphInputs} inputs 图输入
|
|
46
22
|
* @param {typeof trustGraphTunables} [tunables] tunables
|
package/utils/async_mutex.mjs
CHANGED
|
@@ -58,12 +58,3 @@ export async function withAsyncMutex(key, fn) {
|
|
|
58
58
|
}
|
|
59
59
|
})
|
|
60
60
|
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* @param {string} keyPrefix 前缀
|
|
64
|
-
* @returns {(key: string, fn: () => Promise<T>) => Promise<T>} 带前缀的 mutex 函数
|
|
65
|
-
* @template T
|
|
66
|
-
*/
|
|
67
|
-
export function asyncMutexForPrefix(keyPrefix) {
|
|
68
|
-
return (key, fn) => withAsyncMutex(`${keyPrefix}:${key}`, fn)
|
|
69
|
-
}
|
package/wire/group_part.mjs
CHANGED
|
@@ -29,14 +29,14 @@ function wrapWireOn(wire, groupId) {
|
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* 群联邦房间挂载 part_wire(要求线载荷带 `groupId`)。
|
|
32
|
-
* @param {{ replicaUsername?: string }}
|
|
32
|
+
* @param {{ replicaUsername?: string }} wireContext 入站上下文
|
|
33
33
|
* @param {string} groupId 群 ID
|
|
34
34
|
* @param {import('./part_ingress.mjs').PartWireAdapter} wire Trystero 适配器
|
|
35
35
|
* @param {{ allowPartInvoke?: (payload: object) => boolean }} [options] 入站过滤
|
|
36
36
|
* @returns {void}
|
|
37
37
|
*/
|
|
38
|
-
export function attachGroupPartWire(
|
|
39
|
-
attachPartWire(
|
|
38
|
+
export function attachGroupPartWire(wireContext, groupId, wire, options = {}) {
|
|
39
|
+
attachPartWire(wireContext, {
|
|
40
40
|
send: wire.send.bind(wire),
|
|
41
41
|
on: wrapWireOn(wire, groupId),
|
|
42
42
|
}, options)
|
package/wire/part_fanout.mjs
CHANGED
|
@@ -50,22 +50,3 @@ export async function collectPartInvokeResponses(username, partpath, invoke, tim
|
|
|
50
50
|
|
|
51
51
|
return waitForResponses
|
|
52
52
|
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* 单向 part_invoke fanout(mailbox put 等)。
|
|
56
|
-
* @param {string} username 用户
|
|
57
|
-
* @param {string} partpath part 路径
|
|
58
|
-
* @param {import('./part_invoke.mjs').PartInvoke} invoke 调用体
|
|
59
|
-
* @param {number} limit fanout 上限
|
|
60
|
-
* @param {string} [nodeHash] 来源节点
|
|
61
|
-
* @param {string} [groupId] 群上下文
|
|
62
|
-
* @returns {Promise<number>} 发送次数
|
|
63
|
-
*/
|
|
64
|
-
export async function fanoutPartInvoke(username, partpath, invoke, limit, nodeHash, groupId) {
|
|
65
|
-
return requireTrustGraphProvider(DEFAULT_TRUST_GRAPH_OWNER).fanoutToTopNodes(username, 'part_invoke', buildPartInvokePayload({
|
|
66
|
-
partpath,
|
|
67
|
-
invoke,
|
|
68
|
-
nodeHash,
|
|
69
|
-
groupId,
|
|
70
|
-
}), limit)
|
|
71
|
-
}
|
package/wire/part_ingress.mjs
CHANGED
|
@@ -45,16 +45,16 @@ function parsePartTimelinePut(data, partpath) {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
|
-
* @param {PartWireContext}
|
|
48
|
+
* @param {PartWireContext} wireContext 入站上下文
|
|
49
49
|
* @param {object} payload part_invoke 请求
|
|
50
50
|
* @returns {Promise<PartInvokeResponse | null>} RPC 处理器返回值
|
|
51
51
|
*/
|
|
52
|
-
async function dispatchPartInvoke(
|
|
52
|
+
async function dispatchPartInvoke(wireContext, payload) {
|
|
53
53
|
const partpath = normalizePartpath(payload?.partpath)
|
|
54
54
|
const invoke = payload?.invoke
|
|
55
55
|
if (!partpath || !isPlainObject(invoke)) return null
|
|
56
56
|
return dispatchRpcInbound({
|
|
57
|
-
replicaUsername:
|
|
57
|
+
replicaUsername: wireContext.replicaUsername,
|
|
58
58
|
requesterNodeHash: payload.nodeHash ? String(payload.nodeHash).trim() : null,
|
|
59
59
|
groupId: payload.groupId ? String(payload.groupId).trim() : undefined,
|
|
60
60
|
peerId: payload.peerId,
|
|
@@ -70,12 +70,12 @@ async function dispatchPartInvoke(ctx, payload) {
|
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
72
|
* 挂载 part_timeline_put / part_invoke / part_invoke_response。
|
|
73
|
-
* @param {PartWireContext}
|
|
73
|
+
* @param {PartWireContext} wireContext 入站上下文
|
|
74
74
|
* @param {PartWireAdapter} wire Trystero 适配器
|
|
75
75
|
* @param {{ allowPartInvoke?: (payload: object) => boolean }} [options] 入站过滤
|
|
76
76
|
* @returns {void}
|
|
77
77
|
*/
|
|
78
|
-
export function attachPartWire(
|
|
78
|
+
export function attachPartWire(wireContext, wire, options = {}) {
|
|
79
79
|
wire.on('part_timeline_put', data => {
|
|
80
80
|
if (!isPlainObject(data)) return
|
|
81
81
|
const partpath = normalizePartpath(data.partpath)
|
|
@@ -83,7 +83,7 @@ export function attachPartWire(ctx, wire, options = {}) {
|
|
|
83
83
|
const message = parsePartTimelinePut(data, partpath)
|
|
84
84
|
if (!message) return
|
|
85
85
|
void dispatchDeliveryInbound({
|
|
86
|
-
replicaUsername:
|
|
86
|
+
replicaUsername: wireContext.replicaUsername,
|
|
87
87
|
requesterNodeHash: data.nodeHash ? String(data.nodeHash).trim() : null,
|
|
88
88
|
}, message)
|
|
89
89
|
})
|
|
@@ -93,9 +93,9 @@ export function attachPartWire(ctx, wire, options = {}) {
|
|
|
93
93
|
if (options.allowPartInvoke?.(data) === false) return
|
|
94
94
|
const payload = { ...data, peerId }
|
|
95
95
|
if (payload.requestId)
|
|
96
|
-
void handleIncomingPartInvokeRequest(
|
|
96
|
+
void handleIncomingPartInvokeRequest(wireContext, payload, wire, peerId)
|
|
97
97
|
else
|
|
98
|
-
void handleIncomingPartInvokeFireAndForget(
|
|
98
|
+
void handleIncomingPartInvokeFireAndForget(wireContext, payload, wire, peerId)
|
|
99
99
|
})
|
|
100
100
|
|
|
101
101
|
wire.on('part_invoke_response', (data, peerId) => {
|
|
@@ -105,17 +105,17 @@ export function attachPartWire(ctx, wire, options = {}) {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
/**
|
|
108
|
-
* @param {PartWireContext}
|
|
108
|
+
* @param {PartWireContext} wireContext 入站上下文
|
|
109
109
|
* @param {object} payload part_invoke 请求(含 requestId)
|
|
110
110
|
* @param {PartWireAdapter} wire 发送适配器
|
|
111
111
|
* @param {string} peerId 对端
|
|
112
112
|
* @returns {Promise<void>}
|
|
113
113
|
*/
|
|
114
|
-
export async function handleIncomingPartInvokeRequest(
|
|
114
|
+
export async function handleIncomingPartInvokeRequest(wireContext, payload, wire, peerId) {
|
|
115
115
|
const partpath = normalizePartpath(payload?.partpath)
|
|
116
116
|
if (!partpath || !payload.requestId) return
|
|
117
117
|
|
|
118
|
-
const response = await dispatchPartInvoke(
|
|
118
|
+
const response = await dispatchPartInvoke(wireContext, { ...payload, peerId })
|
|
119
119
|
if (response == null || !isPartInvokeResponse(response)) return
|
|
120
120
|
|
|
121
121
|
try {
|
|
@@ -129,17 +129,17 @@ export async function handleIncomingPartInvokeRequest(ctx, payload, wire, peerId
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
/**
|
|
132
|
-
* @param {PartWireContext}
|
|
132
|
+
* @param {PartWireContext} wireContext 入站上下文
|
|
133
133
|
* @param {object} payload part_invoke 请求(无 requestId)
|
|
134
134
|
* @param {PartWireAdapter} wire 发送适配器
|
|
135
135
|
* @param {string} peerId 对端
|
|
136
136
|
* @returns {Promise<void>}
|
|
137
137
|
*/
|
|
138
|
-
export async function handleIncomingPartInvokeFireAndForget(
|
|
138
|
+
export async function handleIncomingPartInvokeFireAndForget(wireContext, payload, wire, peerId) {
|
|
139
139
|
const partpath = normalizePartpath(payload?.partpath)
|
|
140
140
|
if (!partpath) return
|
|
141
141
|
|
|
142
|
-
const response = await dispatchPartInvoke(
|
|
142
|
+
const response = await dispatchPartInvoke(wireContext, { ...payload, peerId })
|
|
143
143
|
const followUp = unwrapPartInvokeResult(response)
|
|
144
144
|
if (!isPartInvoke(followUp)) return
|
|
145
145
|
try {
|