@hashtree/worker 0.1.1
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/LICENSE +21 -0
- package/README.md +38 -0
- package/dist/capabilities/blossomBandwidthTracker.d.ts +26 -0
- package/dist/capabilities/blossomBandwidthTracker.d.ts.map +1 -0
- package/dist/capabilities/blossomBandwidthTracker.js +53 -0
- package/dist/capabilities/blossomBandwidthTracker.js.map +1 -0
- package/dist/capabilities/blossomTransport.d.ts +22 -0
- package/dist/capabilities/blossomTransport.d.ts.map +1 -0
- package/dist/capabilities/blossomTransport.js +124 -0
- package/dist/capabilities/blossomTransport.js.map +1 -0
- package/dist/capabilities/connectivity.d.ts +3 -0
- package/dist/capabilities/connectivity.d.ts.map +1 -0
- package/dist/capabilities/connectivity.js +49 -0
- package/dist/capabilities/connectivity.js.map +1 -0
- package/dist/capabilities/idbStorage.d.ts +25 -0
- package/dist/capabilities/idbStorage.d.ts.map +1 -0
- package/dist/capabilities/idbStorage.js +73 -0
- package/dist/capabilities/idbStorage.js.map +1 -0
- package/dist/client.d.ts +54 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +336 -0
- package/dist/client.js.map +1 -0
- package/dist/entry.d.ts +2 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +2 -0
- package/dist/entry.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/iris/identity.d.ts +36 -0
- package/dist/iris/identity.d.ts.map +1 -0
- package/dist/iris/identity.js +78 -0
- package/dist/iris/identity.js.map +1 -0
- package/dist/iris/mediaHandler.d.ts +16 -0
- package/dist/iris/mediaHandler.d.ts.map +1 -0
- package/dist/iris/mediaHandler.js +529 -0
- package/dist/iris/mediaHandler.js.map +1 -0
- package/dist/iris/ndk.d.ts +95 -0
- package/dist/iris/ndk.d.ts.map +1 -0
- package/dist/iris/ndk.js +496 -0
- package/dist/iris/ndk.js.map +1 -0
- package/dist/iris/nostr-wasm.d.ts +14 -0
- package/dist/iris/nostr-wasm.d.ts.map +1 -0
- package/dist/iris/nostr-wasm.js +246 -0
- package/dist/iris/nostr-wasm.js.map +1 -0
- package/dist/iris/nostr.d.ts +60 -0
- package/dist/iris/nostr.d.ts.map +1 -0
- package/dist/iris/nostr.js +207 -0
- package/dist/iris/nostr.js.map +1 -0
- package/dist/iris/protocol.d.ts +574 -0
- package/dist/iris/protocol.d.ts.map +1 -0
- package/dist/iris/protocol.js +16 -0
- package/dist/iris/protocol.js.map +1 -0
- package/dist/iris/signing.d.ts +50 -0
- package/dist/iris/signing.d.ts.map +1 -0
- package/dist/iris/signing.js +299 -0
- package/dist/iris/signing.js.map +1 -0
- package/dist/iris/treeRootCache.d.ts +73 -0
- package/dist/iris/treeRootCache.d.ts.map +1 -0
- package/dist/iris/treeRootCache.js +191 -0
- package/dist/iris/treeRootCache.js.map +1 -0
- package/dist/iris/treeRootSubscription.d.ts +49 -0
- package/dist/iris/treeRootSubscription.d.ts.map +1 -0
- package/dist/iris/treeRootSubscription.js +185 -0
- package/dist/iris/treeRootSubscription.js.map +1 -0
- package/dist/iris/utils/constants.d.ts +76 -0
- package/dist/iris/utils/constants.d.ts.map +1 -0
- package/dist/iris/utils/constants.js +113 -0
- package/dist/iris/utils/constants.js.map +1 -0
- package/dist/iris/utils/errorMessage.d.ts +5 -0
- package/dist/iris/utils/errorMessage.d.ts.map +1 -0
- package/dist/iris/utils/errorMessage.js +8 -0
- package/dist/iris/utils/errorMessage.js.map +1 -0
- package/dist/iris/utils/lruCache.d.ts +26 -0
- package/dist/iris/utils/lruCache.d.ts.map +1 -0
- package/dist/iris/utils/lruCache.js +66 -0
- package/dist/iris/utils/lruCache.js.map +1 -0
- package/dist/iris/webrtc.d.ts +2 -0
- package/dist/iris/webrtc.d.ts.map +1 -0
- package/dist/iris/webrtc.js +3 -0
- package/dist/iris/webrtc.js.map +1 -0
- package/dist/iris/webrtcSignaling.d.ts +37 -0
- package/dist/iris/webrtcSignaling.d.ts.map +1 -0
- package/dist/iris/webrtcSignaling.js +86 -0
- package/dist/iris/webrtcSignaling.js.map +1 -0
- package/dist/iris/worker.d.ts +12 -0
- package/dist/iris/worker.d.ts.map +1 -0
- package/dist/iris/worker.js +1582 -0
- package/dist/iris/worker.js.map +1 -0
- package/dist/iris-entry.d.ts +2 -0
- package/dist/iris-entry.d.ts.map +1 -0
- package/dist/iris-entry.js +2 -0
- package/dist/iris-entry.js.map +1 -0
- package/dist/mediaStreaming.d.ts +7 -0
- package/dist/mediaStreaming.d.ts.map +1 -0
- package/dist/mediaStreaming.js +48 -0
- package/dist/mediaStreaming.js.map +1 -0
- package/dist/p2p/boundedQueue.d.ts +74 -0
- package/dist/p2p/boundedQueue.d.ts.map +1 -0
- package/dist/p2p/boundedQueue.js +112 -0
- package/dist/p2p/boundedQueue.js.map +1 -0
- package/dist/p2p/errorMessage.d.ts +5 -0
- package/dist/p2p/errorMessage.d.ts.map +1 -0
- package/dist/p2p/errorMessage.js +7 -0
- package/dist/p2p/errorMessage.js.map +1 -0
- package/dist/p2p/index.d.ts +7 -0
- package/dist/p2p/index.d.ts.map +1 -0
- package/dist/p2p/index.js +5 -0
- package/dist/p2p/index.js.map +1 -0
- package/dist/p2p/lruCache.d.ts +26 -0
- package/dist/p2p/lruCache.d.ts.map +1 -0
- package/dist/p2p/lruCache.js +65 -0
- package/dist/p2p/lruCache.js.map +1 -0
- package/dist/p2p/protocol.d.ts +10 -0
- package/dist/p2p/protocol.d.ts.map +1 -0
- package/dist/p2p/protocol.js +2 -0
- package/dist/p2p/protocol.js.map +1 -0
- package/dist/p2p/queryForwardingMachine.d.ts +46 -0
- package/dist/p2p/queryForwardingMachine.d.ts.map +1 -0
- package/dist/p2p/queryForwardingMachine.js +144 -0
- package/dist/p2p/queryForwardingMachine.js.map +1 -0
- package/dist/p2p/signaling.d.ts +63 -0
- package/dist/p2p/signaling.d.ts.map +1 -0
- package/dist/p2p/signaling.js +165 -0
- package/dist/p2p/signaling.js.map +1 -0
- package/dist/p2p/webrtcController.d.ts +152 -0
- package/dist/p2p/webrtcController.d.ts.map +1 -0
- package/dist/p2p/webrtcController.js +813 -0
- package/dist/p2p/webrtcController.js.map +1 -0
- package/dist/p2p/webrtcProxy.d.ts +55 -0
- package/dist/p2p/webrtcProxy.d.ts.map +1 -0
- package/dist/p2p/webrtcProxy.js +386 -0
- package/dist/p2p/webrtcProxy.js.map +1 -0
- package/dist/privacyGuards.d.ts +14 -0
- package/dist/privacyGuards.d.ts.map +1 -0
- package/dist/privacyGuards.js +27 -0
- package/dist/privacyGuards.js.map +1 -0
- package/dist/protocol.d.ts +171 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +2 -0
- package/dist/protocol.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/worker.d.ts +2 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +616 -0
- package/dist/worker.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
class SlidingWindowRateLimiter {
|
|
2
|
+
maxEvents;
|
|
3
|
+
windowMs;
|
|
4
|
+
now;
|
|
5
|
+
eventsByPeer = new Map();
|
|
6
|
+
constructor(maxEvents, windowMs, now) {
|
|
7
|
+
this.maxEvents = maxEvents;
|
|
8
|
+
this.windowMs = windowMs;
|
|
9
|
+
this.now = now;
|
|
10
|
+
}
|
|
11
|
+
allow(peerId) {
|
|
12
|
+
const now = this.now();
|
|
13
|
+
const events = this.eventsByPeer.get(peerId) ?? [];
|
|
14
|
+
let firstActiveIndex = 0;
|
|
15
|
+
while (firstActiveIndex < events.length && now - events[firstActiveIndex] >= this.windowMs) {
|
|
16
|
+
firstActiveIndex++;
|
|
17
|
+
}
|
|
18
|
+
if (firstActiveIndex > 0) {
|
|
19
|
+
events.splice(0, firstActiveIndex);
|
|
20
|
+
}
|
|
21
|
+
if (events.length >= this.maxEvents) {
|
|
22
|
+
this.eventsByPeer.set(peerId, events);
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
events.push(now);
|
|
26
|
+
this.eventsByPeer.set(peerId, events);
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
resetPeer(peerId) {
|
|
30
|
+
this.eventsByPeer.delete(peerId);
|
|
31
|
+
}
|
|
32
|
+
clear() {
|
|
33
|
+
this.eventsByPeer.clear();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export class QueryForwardingMachine {
|
|
37
|
+
requestTimeoutMs;
|
|
38
|
+
scheduleTimeout;
|
|
39
|
+
clearScheduledTimeout;
|
|
40
|
+
onForwardTimeout;
|
|
41
|
+
hashesByRequester = new Map();
|
|
42
|
+
inFlightByHash = new Map();
|
|
43
|
+
rateLimiter;
|
|
44
|
+
constructor(config) {
|
|
45
|
+
this.requestTimeoutMs = config.requestTimeoutMs;
|
|
46
|
+
this.scheduleTimeout = config.scheduleTimeout ?? ((callback, delayMs) => setTimeout(callback, delayMs));
|
|
47
|
+
this.clearScheduledTimeout = config.clearScheduledTimeout ?? ((timeoutId) => clearTimeout(timeoutId));
|
|
48
|
+
this.onForwardTimeout = config.onForwardTimeout;
|
|
49
|
+
const now = config.now ?? (() => Date.now());
|
|
50
|
+
const maxForwardsPerPeerWindow = config.maxForwardsPerPeerWindow ?? 64;
|
|
51
|
+
const forwardRateLimitWindowMs = config.forwardRateLimitWindowMs ?? 1000;
|
|
52
|
+
this.rateLimiter = new SlidingWindowRateLimiter(maxForwardsPerPeerWindow, forwardRateLimitWindowMs, now);
|
|
53
|
+
}
|
|
54
|
+
beginForward(hashKey, requesterId, candidateTargets) {
|
|
55
|
+
const targets = candidateTargets.filter(target => target !== requesterId);
|
|
56
|
+
if (targets.length === 0) {
|
|
57
|
+
return { kind: 'no_targets' };
|
|
58
|
+
}
|
|
59
|
+
const existing = this.inFlightByHash.get(hashKey);
|
|
60
|
+
if (existing) {
|
|
61
|
+
this.trackRequester(hashKey, existing.requesters, requesterId);
|
|
62
|
+
return { kind: 'suppressed' };
|
|
63
|
+
}
|
|
64
|
+
if (!this.rateLimiter.allow(requesterId)) {
|
|
65
|
+
return { kind: 'rate_limited' };
|
|
66
|
+
}
|
|
67
|
+
const requesters = new Set();
|
|
68
|
+
this.trackRequester(hashKey, requesters, requesterId);
|
|
69
|
+
const timeoutId = this.scheduleTimeout(() => {
|
|
70
|
+
this.handleForwardTimeout(hashKey);
|
|
71
|
+
}, this.requestTimeoutMs);
|
|
72
|
+
this.inFlightByHash.set(hashKey, { requesters, timeoutId });
|
|
73
|
+
return { kind: 'forward', targets };
|
|
74
|
+
}
|
|
75
|
+
resolveForward(hashKey) {
|
|
76
|
+
return this.clearForward(hashKey, false);
|
|
77
|
+
}
|
|
78
|
+
cancelForward(hashKey) {
|
|
79
|
+
return this.clearForward(hashKey, false);
|
|
80
|
+
}
|
|
81
|
+
removePeer(peerId) {
|
|
82
|
+
const hashes = this.hashesByRequester.get(peerId);
|
|
83
|
+
if (hashes) {
|
|
84
|
+
for (const hashKey of Array.from(hashes)) {
|
|
85
|
+
const inFlight = this.inFlightByHash.get(hashKey);
|
|
86
|
+
if (!inFlight)
|
|
87
|
+
continue;
|
|
88
|
+
inFlight.requesters.delete(peerId);
|
|
89
|
+
if (inFlight.requesters.size === 0) {
|
|
90
|
+
this.clearForward(hashKey, false);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
this.hashesByRequester.delete(peerId);
|
|
95
|
+
this.rateLimiter.resetPeer(peerId);
|
|
96
|
+
}
|
|
97
|
+
stop() {
|
|
98
|
+
for (const hashKey of Array.from(this.inFlightByHash.keys())) {
|
|
99
|
+
this.clearForward(hashKey, false);
|
|
100
|
+
}
|
|
101
|
+
this.hashesByRequester.clear();
|
|
102
|
+
this.rateLimiter.clear();
|
|
103
|
+
}
|
|
104
|
+
isInFlight(hashKey) {
|
|
105
|
+
return this.inFlightByHash.has(hashKey);
|
|
106
|
+
}
|
|
107
|
+
getInFlightCount() {
|
|
108
|
+
return this.inFlightByHash.size;
|
|
109
|
+
}
|
|
110
|
+
handleForwardTimeout(hashKey) {
|
|
111
|
+
this.clearForward(hashKey, true);
|
|
112
|
+
}
|
|
113
|
+
clearForward(hashKey, notifyTimeout) {
|
|
114
|
+
const inFlight = this.inFlightByHash.get(hashKey);
|
|
115
|
+
if (!inFlight)
|
|
116
|
+
return [];
|
|
117
|
+
this.clearScheduledTimeout(inFlight.timeoutId);
|
|
118
|
+
this.inFlightByHash.delete(hashKey);
|
|
119
|
+
const requesterIds = Array.from(inFlight.requesters);
|
|
120
|
+
for (const requesterId of requesterIds) {
|
|
121
|
+
const hashes = this.hashesByRequester.get(requesterId);
|
|
122
|
+
if (!hashes)
|
|
123
|
+
continue;
|
|
124
|
+
hashes.delete(hashKey);
|
|
125
|
+
if (hashes.size === 0) {
|
|
126
|
+
this.hashesByRequester.delete(requesterId);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (notifyTimeout && this.onForwardTimeout) {
|
|
130
|
+
this.onForwardTimeout({ hashKey, requesterIds });
|
|
131
|
+
}
|
|
132
|
+
return requesterIds;
|
|
133
|
+
}
|
|
134
|
+
trackRequester(hashKey, requesters, requesterId) {
|
|
135
|
+
requesters.add(requesterId);
|
|
136
|
+
let hashes = this.hashesByRequester.get(requesterId);
|
|
137
|
+
if (!hashes) {
|
|
138
|
+
hashes = new Set();
|
|
139
|
+
this.hashesByRequester.set(requesterId, hashes);
|
|
140
|
+
}
|
|
141
|
+
hashes.add(hashKey);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=queryForwardingMachine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queryForwardingMachine.js","sourceRoot":"","sources":["../../src/p2p/queryForwardingMachine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { SignalingMessage } from '@hashtree/nostr';
|
|
2
|
+
export declare const SIGNALING_KIND = 25050;
|
|
3
|
+
export declare const HELLO_TAG = "hello";
|
|
4
|
+
export declare const MAX_EVENT_AGE_SEC = 30;
|
|
5
|
+
export interface SignalingEventLike {
|
|
6
|
+
pubkey: string;
|
|
7
|
+
created_at?: number;
|
|
8
|
+
tags: string[][];
|
|
9
|
+
content: string;
|
|
10
|
+
}
|
|
11
|
+
export interface GiftSeal {
|
|
12
|
+
pubkey: string;
|
|
13
|
+
kind: number;
|
|
14
|
+
content: string;
|
|
15
|
+
tags: string[][];
|
|
16
|
+
}
|
|
17
|
+
export interface SignalingTemplate {
|
|
18
|
+
kind: number;
|
|
19
|
+
created_at: number;
|
|
20
|
+
tags: string[][];
|
|
21
|
+
content: string;
|
|
22
|
+
}
|
|
23
|
+
export interface SignalingInnerEvent {
|
|
24
|
+
kind: number;
|
|
25
|
+
content: string;
|
|
26
|
+
tags: string[][];
|
|
27
|
+
}
|
|
28
|
+
export interface SignalingFilters {
|
|
29
|
+
since: number;
|
|
30
|
+
helloFilter: {
|
|
31
|
+
kinds: number[];
|
|
32
|
+
'#l': string[];
|
|
33
|
+
since: number;
|
|
34
|
+
};
|
|
35
|
+
directedFilter: {
|
|
36
|
+
kinds: number[];
|
|
37
|
+
'#p': string[];
|
|
38
|
+
since: number;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
interface SendSignalingMessageOptions<TEvent extends SignalingEventLike> {
|
|
42
|
+
msg: SignalingMessage;
|
|
43
|
+
recipientPubkey?: string;
|
|
44
|
+
signEvent: (template: SignalingTemplate) => Promise<TEvent>;
|
|
45
|
+
giftWrap: (innerEvent: SignalingInnerEvent, recipientPubkey: string) => Promise<TEvent>;
|
|
46
|
+
publish: (event: TEvent) => Promise<void>;
|
|
47
|
+
nowMs?: () => number;
|
|
48
|
+
}
|
|
49
|
+
interface DecodeSignalingEventOptions<TEvent extends SignalingEventLike> {
|
|
50
|
+
event: TEvent;
|
|
51
|
+
giftUnwrap: (event: TEvent) => Promise<GiftSeal | null>;
|
|
52
|
+
nowMs?: () => number;
|
|
53
|
+
maxEventAgeSec?: number;
|
|
54
|
+
}
|
|
55
|
+
export interface DecodedSignalingEvent {
|
|
56
|
+
senderPubkey: string;
|
|
57
|
+
message: SignalingMessage;
|
|
58
|
+
}
|
|
59
|
+
export declare function createSignalingFilters(myPubkey: string, nowMs?: number, maxEventAgeSec?: number): SignalingFilters;
|
|
60
|
+
export declare function sendSignalingMessage<TEvent extends SignalingEventLike>({ msg, recipientPubkey, signEvent, giftWrap, publish, nowMs, }: SendSignalingMessageOptions<TEvent>): Promise<void>;
|
|
61
|
+
export declare function decodeSignalingEvent<TEvent extends SignalingEventLike>({ event, giftUnwrap, nowMs, maxEventAgeSec, }: DecodeSignalingEventOptions<TEvent>): Promise<DecodedSignalingEvent | null>;
|
|
62
|
+
export {};
|
|
63
|
+
//# sourceMappingURL=signaling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signaling.d.ts","sourceRoot":"","sources":["../../src/p2p/signaling.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
export const SIGNALING_KIND = 25050;
|
|
2
|
+
export const HELLO_TAG = 'hello';
|
|
3
|
+
export const MAX_EVENT_AGE_SEC = 30;
|
|
4
|
+
const HELLO_EXPIRATION_SEC = 5 * 60;
|
|
5
|
+
function getSince(nowMs, maxEventAgeSec) {
|
|
6
|
+
return Math.floor((nowMs - maxEventAgeSec * 1000) / 1000);
|
|
7
|
+
}
|
|
8
|
+
function isExpired(event, nowSec, maxEventAgeSec) {
|
|
9
|
+
const createdAt = event.created_at ?? 0;
|
|
10
|
+
if (nowSec - createdAt > maxEventAgeSec) {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
const expirationTag = event.tags.find((tag) => tag[0] === 'expiration');
|
|
14
|
+
if (expirationTag?.[1]) {
|
|
15
|
+
const expiration = Number.parseInt(expirationTag[1], 10);
|
|
16
|
+
if (Number.isFinite(expiration) && expiration < nowSec) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
function normalizeSignalingMessage(raw, senderPubkey) {
|
|
23
|
+
if (!raw || typeof raw !== 'object' || !('type' in raw))
|
|
24
|
+
return null;
|
|
25
|
+
const msg = raw;
|
|
26
|
+
if (typeof msg.type !== 'string')
|
|
27
|
+
return null;
|
|
28
|
+
if ('targetPeerId' in msg &&
|
|
29
|
+
typeof msg.targetPeerId === 'string' &&
|
|
30
|
+
typeof msg.peerId === 'string') {
|
|
31
|
+
return msg;
|
|
32
|
+
}
|
|
33
|
+
if (!('recipient' in msg) || typeof msg.recipient !== 'string' || typeof msg.peerId !== 'string') {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const senderPeerId = msg.peerId.includes(':') ? msg.peerId : `${senderPubkey}:${msg.peerId}`;
|
|
37
|
+
const targetPeerId = msg.recipient;
|
|
38
|
+
switch (msg.type) {
|
|
39
|
+
case 'offer': {
|
|
40
|
+
const offer = msg.offer;
|
|
41
|
+
const sdp = typeof offer === 'string' ? offer : offer?.sdp;
|
|
42
|
+
return sdp ? { type: 'offer', peerId: senderPeerId, targetPeerId, sdp } : null;
|
|
43
|
+
}
|
|
44
|
+
case 'answer': {
|
|
45
|
+
const answer = msg.answer;
|
|
46
|
+
const sdp = typeof answer === 'string' ? answer : answer?.sdp;
|
|
47
|
+
return sdp ? { type: 'answer', peerId: senderPeerId, targetPeerId, sdp } : null;
|
|
48
|
+
}
|
|
49
|
+
case 'candidate': {
|
|
50
|
+
const candidateObj = msg.candidate;
|
|
51
|
+
const candidate = typeof candidateObj === 'string' ? candidateObj : candidateObj?.candidate;
|
|
52
|
+
return candidate
|
|
53
|
+
? {
|
|
54
|
+
type: 'candidate',
|
|
55
|
+
peerId: senderPeerId,
|
|
56
|
+
targetPeerId,
|
|
57
|
+
candidate,
|
|
58
|
+
sdpMLineIndex: typeof candidateObj === 'object' ? candidateObj?.sdpMLineIndex : undefined,
|
|
59
|
+
sdpMid: typeof candidateObj === 'object' ? candidateObj?.sdpMid : undefined,
|
|
60
|
+
}
|
|
61
|
+
: null;
|
|
62
|
+
}
|
|
63
|
+
case 'candidates': {
|
|
64
|
+
const candidates = Array.isArray(msg.candidates)
|
|
65
|
+
? msg.candidates
|
|
66
|
+
.map((entry) => {
|
|
67
|
+
if (typeof entry === 'string') {
|
|
68
|
+
return { candidate: entry };
|
|
69
|
+
}
|
|
70
|
+
if (entry && typeof entry === 'object') {
|
|
71
|
+
const candidateEntry = entry;
|
|
72
|
+
if (typeof candidateEntry.candidate === 'string') {
|
|
73
|
+
return {
|
|
74
|
+
candidate: candidateEntry.candidate,
|
|
75
|
+
sdpMLineIndex: candidateEntry.sdpMLineIndex,
|
|
76
|
+
sdpMid: candidateEntry.sdpMid,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
})
|
|
82
|
+
.filter((entry) => !!entry)
|
|
83
|
+
: [];
|
|
84
|
+
return { type: 'candidates', peerId: senderPeerId, targetPeerId, candidates };
|
|
85
|
+
}
|
|
86
|
+
default:
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export function createSignalingFilters(myPubkey, nowMs = Date.now(), maxEventAgeSec = MAX_EVENT_AGE_SEC) {
|
|
91
|
+
const since = getSince(nowMs, maxEventAgeSec);
|
|
92
|
+
return {
|
|
93
|
+
since,
|
|
94
|
+
helloFilter: {
|
|
95
|
+
kinds: [SIGNALING_KIND],
|
|
96
|
+
'#l': [HELLO_TAG],
|
|
97
|
+
since,
|
|
98
|
+
},
|
|
99
|
+
directedFilter: {
|
|
100
|
+
kinds: [SIGNALING_KIND],
|
|
101
|
+
'#p': [myPubkey],
|
|
102
|
+
since,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
export async function sendSignalingMessage({ msg, recipientPubkey, signEvent, giftWrap, publish, nowMs = () => Date.now(), }) {
|
|
107
|
+
if (recipientPubkey) {
|
|
108
|
+
const wrappedEvent = await giftWrap({
|
|
109
|
+
kind: SIGNALING_KIND,
|
|
110
|
+
content: JSON.stringify(msg),
|
|
111
|
+
tags: [],
|
|
112
|
+
}, recipientPubkey);
|
|
113
|
+
await publish(wrappedEvent);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const createdAt = Math.floor(nowMs() / 1000);
|
|
117
|
+
const event = await signEvent({
|
|
118
|
+
kind: SIGNALING_KIND,
|
|
119
|
+
created_at: createdAt,
|
|
120
|
+
tags: [
|
|
121
|
+
['l', HELLO_TAG],
|
|
122
|
+
['peerId', msg.peerId],
|
|
123
|
+
['expiration', String(createdAt + HELLO_EXPIRATION_SEC)],
|
|
124
|
+
],
|
|
125
|
+
content: '',
|
|
126
|
+
});
|
|
127
|
+
await publish(event);
|
|
128
|
+
}
|
|
129
|
+
export async function decodeSignalingEvent({ event, giftUnwrap, nowMs = () => Date.now(), maxEventAgeSec = MAX_EVENT_AGE_SEC, }) {
|
|
130
|
+
const nowSec = nowMs() / 1000;
|
|
131
|
+
if (isExpired(event, nowSec, maxEventAgeSec)) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
const isHello = event.tags.some((tag) => tag[0] === 'l' && tag[1] === HELLO_TAG);
|
|
135
|
+
if (isHello) {
|
|
136
|
+
const peerIdTag = event.tags.find((tag) => tag[0] === 'peerId');
|
|
137
|
+
if (!peerIdTag?.[1])
|
|
138
|
+
return null;
|
|
139
|
+
return {
|
|
140
|
+
senderPubkey: event.pubkey,
|
|
141
|
+
message: {
|
|
142
|
+
type: 'hello',
|
|
143
|
+
peerId: peerIdTag[1],
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
const seal = await giftUnwrap(event);
|
|
148
|
+
if (!seal?.content) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
const raw = JSON.parse(seal.content);
|
|
153
|
+
const message = normalizeSignalingMessage(raw, seal.pubkey);
|
|
154
|
+
if (!message)
|
|
155
|
+
return null;
|
|
156
|
+
return {
|
|
157
|
+
senderPubkey: seal.pubkey,
|
|
158
|
+
message,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=signaling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signaling.js","sourceRoot":"","sources":["../../src/p2p/signaling.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker WebRTC Controller
|
|
3
|
+
*
|
|
4
|
+
* Controls WebRTC connections from the worker thread.
|
|
5
|
+
* Main thread proxy executes RTCPeerConnection operations.
|
|
6
|
+
*
|
|
7
|
+
* Worker owns:
|
|
8
|
+
* - Peer state tracking
|
|
9
|
+
* - Connection lifecycle decisions
|
|
10
|
+
* - Data protocol (request/response)
|
|
11
|
+
* - Signaling message handling
|
|
12
|
+
*
|
|
13
|
+
* Main thread proxy owns:
|
|
14
|
+
* - RTCPeerConnection instances (not available in workers)
|
|
15
|
+
* - Data channel I/O
|
|
16
|
+
*/
|
|
17
|
+
import type { Store } from '@hashtree/core';
|
|
18
|
+
import type { WebRTCCommand, WebRTCEvent } from './protocol.js';
|
|
19
|
+
import { type SignalingMessage, type PeerPool } from '@hashtree/nostr';
|
|
20
|
+
export interface WebRTCControllerConfig {
|
|
21
|
+
pubkey: string;
|
|
22
|
+
localStore: Store;
|
|
23
|
+
sendCommand: (cmd: WebRTCCommand) => void;
|
|
24
|
+
sendSignaling: (msg: SignalingMessage, recipientPubkey?: string) => Promise<void>;
|
|
25
|
+
getFollows?: () => Set<string>;
|
|
26
|
+
requestTimeout?: number;
|
|
27
|
+
forwardRateLimit?: {
|
|
28
|
+
maxForwardsPerPeerWindow?: number;
|
|
29
|
+
windowMs?: number;
|
|
30
|
+
};
|
|
31
|
+
debug?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare class WebRTCController {
|
|
34
|
+
private myPeerId;
|
|
35
|
+
private peers;
|
|
36
|
+
private localStore;
|
|
37
|
+
private sendCommand;
|
|
38
|
+
private sendSignaling;
|
|
39
|
+
private classifyPeer;
|
|
40
|
+
private requestTimeout;
|
|
41
|
+
private debug;
|
|
42
|
+
private recentRequests;
|
|
43
|
+
private forwardingMachine;
|
|
44
|
+
private poolConfig;
|
|
45
|
+
private helloInterval?;
|
|
46
|
+
private readonly HELLO_INTERVAL;
|
|
47
|
+
constructor(config: WebRTCControllerConfig);
|
|
48
|
+
start(): void;
|
|
49
|
+
stop(): void;
|
|
50
|
+
private sendHello;
|
|
51
|
+
/**
|
|
52
|
+
* Public method to trigger a hello broadcast.
|
|
53
|
+
* Used for testing to force peer discovery after follows are set up.
|
|
54
|
+
*/
|
|
55
|
+
broadcastHello(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Handle incoming signaling message (from Nostr kind 25050)
|
|
58
|
+
*
|
|
59
|
+
* Note: For hello messages, msg.peerId is just the UUID (from Nostr tag).
|
|
60
|
+
* For directed messages (offer/answer/candidate), msg.peerId is already the full
|
|
61
|
+
* pubkey:uuid format from Rust's SignalingMessage.
|
|
62
|
+
*/
|
|
63
|
+
handleSignalingMessage(msg: SignalingMessage, senderPubkey: string): Promise<void>;
|
|
64
|
+
private isMessageForUs;
|
|
65
|
+
private handleHello;
|
|
66
|
+
private handleOffer;
|
|
67
|
+
private handleAnswer;
|
|
68
|
+
private handleIceCandidate;
|
|
69
|
+
private shouldConnect;
|
|
70
|
+
private getPoolCount;
|
|
71
|
+
/**
|
|
72
|
+
* Check if we already have a connection from this pubkey in the 'other' pool.
|
|
73
|
+
* In the 'other' pool, we only allow 1 connection per pubkey to prevent spam.
|
|
74
|
+
*/
|
|
75
|
+
private hasOtherPoolPubkey;
|
|
76
|
+
private createPeer;
|
|
77
|
+
private createOutboundPeer;
|
|
78
|
+
private closePeer;
|
|
79
|
+
/**
|
|
80
|
+
* Handle event from main thread proxy
|
|
81
|
+
*/
|
|
82
|
+
handleProxyEvent(event: WebRTCEvent): void;
|
|
83
|
+
private onPeerCreated;
|
|
84
|
+
private onPeerStateChange;
|
|
85
|
+
private onPeerClosed;
|
|
86
|
+
private onOfferCreated;
|
|
87
|
+
private onAnswerCreated;
|
|
88
|
+
private onDescriptionSet;
|
|
89
|
+
private onIceCandidate;
|
|
90
|
+
private onDataChannelOpen;
|
|
91
|
+
private onDataChannelClose;
|
|
92
|
+
private onDataChannelError;
|
|
93
|
+
private onBufferHigh;
|
|
94
|
+
private onBufferLow;
|
|
95
|
+
private processDeferredRequests;
|
|
96
|
+
private sendDataToPeer;
|
|
97
|
+
private onDataChannelMessage;
|
|
98
|
+
private handleRequest;
|
|
99
|
+
private processRequest;
|
|
100
|
+
private handleResponse;
|
|
101
|
+
private sendResponse;
|
|
102
|
+
private getForwardTargets;
|
|
103
|
+
private forwardRequest;
|
|
104
|
+
private pushToRequesters;
|
|
105
|
+
private clearRequesterMarkers;
|
|
106
|
+
/**
|
|
107
|
+
* Request data from peers
|
|
108
|
+
*/
|
|
109
|
+
get(hash: Uint8Array): Promise<Uint8Array | null>;
|
|
110
|
+
/**
|
|
111
|
+
* Get peer stats for UI
|
|
112
|
+
*/
|
|
113
|
+
getPeerStats(): Array<{
|
|
114
|
+
peerId: string;
|
|
115
|
+
pubkey: string;
|
|
116
|
+
connected: boolean;
|
|
117
|
+
pool: PeerPool;
|
|
118
|
+
requestsSent: number;
|
|
119
|
+
requestsReceived: number;
|
|
120
|
+
responsesSent: number;
|
|
121
|
+
responsesReceived: number;
|
|
122
|
+
bytesSent: number;
|
|
123
|
+
bytesReceived: number;
|
|
124
|
+
forwardedRequests: number;
|
|
125
|
+
forwardedResolved: number;
|
|
126
|
+
forwardedSuppressed: number;
|
|
127
|
+
}>;
|
|
128
|
+
/**
|
|
129
|
+
* Get connected peer count
|
|
130
|
+
*/
|
|
131
|
+
getConnectedCount(): number;
|
|
132
|
+
/**
|
|
133
|
+
* Set pool configuration
|
|
134
|
+
*/
|
|
135
|
+
setPoolConfig(config: {
|
|
136
|
+
follows: {
|
|
137
|
+
max: number;
|
|
138
|
+
satisfied: number;
|
|
139
|
+
};
|
|
140
|
+
other: {
|
|
141
|
+
max: number;
|
|
142
|
+
satisfied: number;
|
|
143
|
+
};
|
|
144
|
+
}): void;
|
|
145
|
+
/**
|
|
146
|
+
* Update identity (pubkey) and restart signaling if already running.
|
|
147
|
+
* This keeps peerId consistent with the current account.
|
|
148
|
+
*/
|
|
149
|
+
setIdentity(pubkey: string): void;
|
|
150
|
+
private log;
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=webrtcController.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webrtcController.d.ts","sourceRoot":"","sources":["../../src/p2p/webrtcController.ts"],"names":[],"mappings":"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"}
|