@airterm/protocol 0.2.0 → 0.4.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 +29 -9
- package/dist/direct-negotiation.d.ts +40 -0
- package/dist/direct-negotiation.d.ts.map +1 -0
- package/dist/direct-negotiation.js +169 -0
- package/dist/direct-negotiation.js.map +1 -0
- package/dist/framing.d.ts +4 -1
- package/dist/framing.d.ts.map +1 -1
- package/dist/framing.js +3 -0
- package/dist/framing.js.map +1 -1
- package/dist/index.d.ts +21 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -5
- package/dist/index.js.map +1 -1
- package/dist/messages.d.ts +3 -1
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +20 -6
- package/dist/messages.js.map +1 -1
- package/dist/naming.d.ts +19 -0
- package/dist/naming.d.ts.map +1 -0
- package/dist/naming.js +85 -0
- package/dist/naming.js.map +1 -0
- package/dist/outbound-queue.d.ts +17 -0
- package/dist/outbound-queue.d.ts.map +1 -0
- package/dist/outbound-queue.js +150 -0
- package/dist/outbound-queue.js.map +1 -0
- package/dist/p2p.d.ts +37 -0
- package/dist/p2p.d.ts.map +1 -0
- package/dist/p2p.js +91 -0
- package/dist/p2p.js.map +1 -0
- package/dist/pairing.d.ts +18 -0
- package/dist/pairing.d.ts.map +1 -0
- package/dist/pairing.js +48 -0
- package/dist/pairing.js.map +1 -0
- package/dist/peer-transport.d.ts +31 -0
- package/dist/peer-transport.d.ts.map +1 -0
- package/dist/peer-transport.js +155 -0
- package/dist/peer-transport.js.map +1 -0
- package/dist/relay-usage.d.ts +13 -0
- package/dist/relay-usage.d.ts.map +1 -0
- package/dist/relay-usage.js +18 -0
- package/dist/relay-usage.js.map +1 -0
- package/dist/transport-handoff.d.ts +25 -0
- package/dist/transport-handoff.d.ts.map +1 -0
- package/dist/transport-handoff.js +207 -0
- package/dist/transport-handoff.js.map +1 -0
- package/dist/transport.d.ts +39 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +92 -0
- package/dist/transport.js.map +1 -0
- package/dist/vault.d.ts +51 -0
- package/dist/vault.d.ts.map +1 -0
- package/dist/vault.js +215 -0
- package/dist/vault.js.map +1 -0
- package/dist/webrtc-transport.d.ts +14 -0
- package/dist/webrtc-transport.d.ts.map +1 -0
- package/dist/webrtc-transport.js +106 -0
- package/dist/webrtc-transport.js.map +1 -0
- package/package.json +1 -1
package/dist/naming.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { decodeBase64Url, encodeBase64Url } from './capability.js';
|
|
2
|
+
const encoder = new TextEncoder();
|
|
3
|
+
const forbidden = /[\p{Cc}\p{Cf}]/u;
|
|
4
|
+
export function customName(value) {
|
|
5
|
+
const name = value.trim();
|
|
6
|
+
if (!name || [...name].length > 80 || forbidden.test(value))
|
|
7
|
+
throw new Error('Use 1–80 characters without control characters.');
|
|
8
|
+
return name;
|
|
9
|
+
}
|
|
10
|
+
export function automaticName(value) {
|
|
11
|
+
if (!value.trim() || forbidden.test(value))
|
|
12
|
+
return undefined;
|
|
13
|
+
return [...value].slice(0, 160).join('');
|
|
14
|
+
}
|
|
15
|
+
function canonical(value, length) {
|
|
16
|
+
if (typeof value !== 'string' || value.length > 22000)
|
|
17
|
+
throw new Error('Invalid naming encoding');
|
|
18
|
+
const bytes = decodeBase64Url(value);
|
|
19
|
+
if (encodeBase64Url(bytes) !== value || length !== undefined && bytes.length !== length)
|
|
20
|
+
throw new Error('Invalid naming encoding');
|
|
21
|
+
return bytes;
|
|
22
|
+
}
|
|
23
|
+
function buffer(value) { return value.slice().buffer; }
|
|
24
|
+
function context(identity, sessionId) {
|
|
25
|
+
if (!/^[1-9][0-9]{0,18}$/.test(identity.accountId) || !Number.isSafeInteger(identity.generation) || identity.generation < 1)
|
|
26
|
+
throw new Error('Invalid naming identity');
|
|
27
|
+
canonical(sessionId, 16);
|
|
28
|
+
return encoder.encode(JSON.stringify(['airterm-names', 1, identity.accountId, identity.generation, sessionId]));
|
|
29
|
+
}
|
|
30
|
+
export function validateSessionNames(value) {
|
|
31
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
32
|
+
throw new Error('Invalid names');
|
|
33
|
+
const doc = value;
|
|
34
|
+
if (Object.keys(doc).some(key => !['defaultName', 'alias', 'tabs'].includes(key)) || typeof doc.defaultName !== 'string' || automaticName(doc.defaultName) !== doc.defaultName || !doc.tabs || typeof doc.tabs !== 'object' || Array.isArray(doc.tabs))
|
|
35
|
+
throw new Error('Invalid names');
|
|
36
|
+
if (doc.alias !== undefined && (typeof doc.alias !== 'string' || customName(doc.alias) !== doc.alias))
|
|
37
|
+
throw new Error('Invalid alias');
|
|
38
|
+
const tabs = {};
|
|
39
|
+
for (const [id, title] of Object.entries(doc.tabs)) {
|
|
40
|
+
if (!/^[1-9][0-9]{0,4}$/.test(id) || Number(id) > 65535 || typeof title !== 'string' || customName(title) !== title)
|
|
41
|
+
throw new Error('Invalid tab alias');
|
|
42
|
+
tabs[id] = title;
|
|
43
|
+
}
|
|
44
|
+
return { defaultName: doc.defaultName, ...(doc.alias === undefined ? {} : { alias: doc.alias }), tabs };
|
|
45
|
+
}
|
|
46
|
+
export async function encryptSessionNames(publicKey, identity, sessionId, names) {
|
|
47
|
+
const data = encoder.encode(JSON.stringify(validateSessionNames(names)));
|
|
48
|
+
if (data.length > 11000)
|
|
49
|
+
throw new Error('Naming document is too large');
|
|
50
|
+
const aad = buffer(context(identity, sessionId));
|
|
51
|
+
const raw = crypto.getRandomValues(new Uint8Array(32));
|
|
52
|
+
try {
|
|
53
|
+
const key = await crypto.subtle.importKey('raw', buffer(raw), 'AES-GCM', false, ['encrypt']);
|
|
54
|
+
const rsa = await crypto.subtle.importKey('spki', buffer(canonical(publicKey)), { name: 'RSA-OAEP', hash: 'SHA-256' }, false, ['encrypt']);
|
|
55
|
+
if (rsa.algorithm.modulusLength !== 3072)
|
|
56
|
+
throw new Error('Invalid public key');
|
|
57
|
+
const nonce = crypto.getRandomValues(new Uint8Array(12));
|
|
58
|
+
const envelope = { version: 1, accountId: identity.accountId, generation: identity.generation, sessionId,
|
|
59
|
+
wrappedKey: encodeBase64Url(new Uint8Array(await crypto.subtle.encrypt({ name: 'RSA-OAEP', label: aad }, rsa, buffer(raw)))),
|
|
60
|
+
nonce: encodeBase64Url(nonce), ciphertext: encodeBase64Url(new Uint8Array(await crypto.subtle.encrypt({ name: 'AES-GCM', iv: buffer(nonce), additionalData: aad }, key, buffer(data)))) };
|
|
61
|
+
if (encoder.encode(JSON.stringify(envelope)).length > 16384)
|
|
62
|
+
throw new Error('Naming document is too large');
|
|
63
|
+
return envelope;
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
raw.fill(0);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export async function decryptSessionNames(privateKey, identity, sessionId, envelope) {
|
|
70
|
+
if (!envelope || encoder.encode(JSON.stringify(envelope)).length > 16384 || Object.keys(envelope).sort().join(',') !== 'accountId,ciphertext,generation,nonce,sessionId,version,wrappedKey' || envelope.version !== 1 || envelope.accountId !== identity.accountId || envelope.generation !== identity.generation || envelope.sessionId !== sessionId)
|
|
71
|
+
throw new Error('Invalid naming envelope');
|
|
72
|
+
const aad = buffer(context(identity, sessionId));
|
|
73
|
+
const raw = new Uint8Array(await crypto.subtle.decrypt({ name: 'RSA-OAEP', label: aad }, privateKey, buffer(canonical(envelope.wrappedKey, 384))));
|
|
74
|
+
try {
|
|
75
|
+
if (raw.length !== 32)
|
|
76
|
+
throw new Error('Invalid naming key');
|
|
77
|
+
const key = await crypto.subtle.importKey('raw', buffer(raw), 'AES-GCM', false, ['decrypt']);
|
|
78
|
+
const data = await crypto.subtle.decrypt({ name: 'AES-GCM', iv: buffer(canonical(envelope.nonce, 12)), additionalData: aad }, key, buffer(canonical(envelope.ciphertext)));
|
|
79
|
+
return validateSessionNames(JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(data)));
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
raw.fill(0);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=naming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.js","sourceRoot":"","sources":["../src/naming.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type InnerFrame } from './framing.js';
|
|
2
|
+
export declare const OUTPUT_HIGH_WATER_BYTES: number;
|
|
3
|
+
export declare const OUTPUT_LOW_WATER_BYTES: number;
|
|
4
|
+
export declare const OUTPUT_MAX_PENDING_BYTES: number;
|
|
5
|
+
export declare class OutboundQueue {
|
|
6
|
+
#private;
|
|
7
|
+
private readonly bufferedAmount;
|
|
8
|
+
private readonly write;
|
|
9
|
+
private readonly onBackpressure;
|
|
10
|
+
private readonly onFailure;
|
|
11
|
+
constructor(bufferedAmount: () => number, write: (frame: InnerFrame, done: (error?: Error | null) => void) => void, onBackpressure: (paused: boolean) => void, onFailure: (error: Error) => void);
|
|
12
|
+
get pendingBytes(): number;
|
|
13
|
+
send(frame: InnerFrame): Promise<void>;
|
|
14
|
+
discard(predicate: (frame: InnerFrame) => boolean): void;
|
|
15
|
+
close(error?: Error): void;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=outbound-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbound-queue.d.ts","sourceRoot":"","sources":["../src/outbound-queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAEnE,eAAO,MAAM,uBAAuB,QAAc,CAAC;AACnD,eAAO,MAAM,sBAAsB,QAAa,CAAC;AACjD,eAAO,MAAM,wBAAwB,QAAgB,CAAC;AAUtD,qBAAa,aAAa;;IAYlB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK;IAItB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,SAAS;gBANT,cAAc,EAAE,MAAM,MAAM,EAC5B,KAAK,EAAE,CACpB,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,KACnC,IAAI,EACQ,cAAc,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,EACzC,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI;IAGtD,IAAW,YAAY,IAAI,MAAM,CAIhC;IAEM,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBtC,OAAO,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,GAAG,IAAI;IAWxD,KAAK,CAAC,KAAK,QAA0C,GAAG,IAAI;CAqFtE"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { INNER_HEADER_BYTES } from './framing.js';
|
|
2
|
+
export const OUTPUT_HIGH_WATER_BYTES = 256 * 1_024;
|
|
3
|
+
export const OUTPUT_LOW_WATER_BYTES = 64 * 1_024;
|
|
4
|
+
export const OUTPUT_MAX_PENDING_BYTES = 1_024 * 1_024;
|
|
5
|
+
const FRAME_OVERHEAD_BYTES = INNER_HEADER_BYTES + 18;
|
|
6
|
+
export class OutboundQueue {
|
|
7
|
+
bufferedAmount;
|
|
8
|
+
write;
|
|
9
|
+
onBackpressure;
|
|
10
|
+
onFailure;
|
|
11
|
+
#queue = [];
|
|
12
|
+
#bytes = 0;
|
|
13
|
+
#inFlight;
|
|
14
|
+
#timer;
|
|
15
|
+
#closed = false;
|
|
16
|
+
#paused = false;
|
|
17
|
+
#pumping = false;
|
|
18
|
+
#progressAt = Date.now();
|
|
19
|
+
#lastBuffered = 0;
|
|
20
|
+
constructor(bufferedAmount, write, onBackpressure, onFailure) {
|
|
21
|
+
this.bufferedAmount = bufferedAmount;
|
|
22
|
+
this.write = write;
|
|
23
|
+
this.onBackpressure = onBackpressure;
|
|
24
|
+
this.onFailure = onFailure;
|
|
25
|
+
}
|
|
26
|
+
get pendingBytes() {
|
|
27
|
+
return (this.#bytes + (this.#inFlight?.bytes ?? 0) + this.bufferedAmount());
|
|
28
|
+
}
|
|
29
|
+
send(frame) {
|
|
30
|
+
if (this.#closed)
|
|
31
|
+
return Promise.reject(new Error('Gateway output queue is closed.'));
|
|
32
|
+
if (this.pendingBytes === 0)
|
|
33
|
+
this.#progressAt = Date.now();
|
|
34
|
+
const bytes = frame.payload.byteLength + FRAME_OVERHEAD_BYTES;
|
|
35
|
+
if (this.pendingBytes + bytes > OUTPUT_MAX_PENDING_BYTES) {
|
|
36
|
+
const error = new Error('Gateway output exceeded its 1 MiB limit.');
|
|
37
|
+
this.#fail(error);
|
|
38
|
+
return Promise.reject(error);
|
|
39
|
+
}
|
|
40
|
+
const pending = new Promise((resolve, reject) => {
|
|
41
|
+
this.#queue.push({
|
|
42
|
+
frame: { ...frame, payload: Uint8Array.from(frame.payload) },
|
|
43
|
+
bytes,
|
|
44
|
+
resolve,
|
|
45
|
+
reject,
|
|
46
|
+
});
|
|
47
|
+
this.#bytes += bytes;
|
|
48
|
+
});
|
|
49
|
+
this.#updatePressure();
|
|
50
|
+
this.#pump();
|
|
51
|
+
return pending;
|
|
52
|
+
}
|
|
53
|
+
discard(predicate) {
|
|
54
|
+
for (let index = this.#queue.length - 1; index >= 0; index--) {
|
|
55
|
+
const item = this.#queue[index];
|
|
56
|
+
if (!predicate(item.frame))
|
|
57
|
+
continue;
|
|
58
|
+
this.#queue.splice(index, 1);
|
|
59
|
+
this.#bytes -= item.bytes;
|
|
60
|
+
item.reject(new Error('Relay traffic paused by usage policy.'));
|
|
61
|
+
}
|
|
62
|
+
this.#updatePressure();
|
|
63
|
+
}
|
|
64
|
+
close(error = new Error('Gateway transport changed.')) {
|
|
65
|
+
if (this.#closed)
|
|
66
|
+
return;
|
|
67
|
+
this.#closed = true;
|
|
68
|
+
clearTimeout(this.#timer);
|
|
69
|
+
this.#timer = undefined;
|
|
70
|
+
for (const item of this.#queue.splice(0))
|
|
71
|
+
item.reject(error);
|
|
72
|
+
this.#inFlight?.reject(error);
|
|
73
|
+
this.#inFlight = undefined;
|
|
74
|
+
this.#bytes = 0;
|
|
75
|
+
if (this.#paused)
|
|
76
|
+
this.onBackpressure(false);
|
|
77
|
+
this.#paused = false;
|
|
78
|
+
}
|
|
79
|
+
#pump() {
|
|
80
|
+
if (this.#closed || this.#pumping)
|
|
81
|
+
return;
|
|
82
|
+
this.#pumping = true;
|
|
83
|
+
try {
|
|
84
|
+
while (!this.#closed &&
|
|
85
|
+
this.#inFlight === undefined &&
|
|
86
|
+
this.bufferedAmount() < OUTPUT_HIGH_WATER_BYTES) {
|
|
87
|
+
const item = this.#queue.shift();
|
|
88
|
+
if (item === undefined)
|
|
89
|
+
break;
|
|
90
|
+
this.#bytes -= item.bytes;
|
|
91
|
+
this.#inFlight = item;
|
|
92
|
+
this.write(item.frame, (error) => {
|
|
93
|
+
if (this.#closed || this.#inFlight !== item)
|
|
94
|
+
return;
|
|
95
|
+
if (error != null) {
|
|
96
|
+
this.#fail(error);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
this.#inFlight = undefined;
|
|
100
|
+
this.#progressAt = Date.now();
|
|
101
|
+
item.resolve();
|
|
102
|
+
this.#updatePressure();
|
|
103
|
+
this.#pump();
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
this.#fail(error instanceof Error ? error : new Error(String(error)));
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
this.#pumping = false;
|
|
112
|
+
}
|
|
113
|
+
this.#updatePressure();
|
|
114
|
+
if (!this.#closed &&
|
|
115
|
+
this.pendingBytes > 0 &&
|
|
116
|
+
this.#timer === undefined) {
|
|
117
|
+
this.#timer = setTimeout(() => {
|
|
118
|
+
this.#timer = undefined;
|
|
119
|
+
const buffered = this.bufferedAmount();
|
|
120
|
+
if (buffered < this.#lastBuffered)
|
|
121
|
+
this.#progressAt = Date.now();
|
|
122
|
+
this.#lastBuffered = buffered;
|
|
123
|
+
if (Date.now() - this.#progressAt >= 30_000) {
|
|
124
|
+
this.#fail(new Error('Gateway output stalled for 30 seconds.'));
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
this.#pump();
|
|
128
|
+
}
|
|
129
|
+
}, 10);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
#updatePressure() {
|
|
133
|
+
if (this.#closed)
|
|
134
|
+
return;
|
|
135
|
+
const paused = this.#paused
|
|
136
|
+
? this.pendingBytes >= OUTPUT_LOW_WATER_BYTES
|
|
137
|
+
: this.pendingBytes >= OUTPUT_HIGH_WATER_BYTES;
|
|
138
|
+
if (paused !== this.#paused) {
|
|
139
|
+
this.#paused = paused;
|
|
140
|
+
this.onBackpressure(paused);
|
|
141
|
+
}
|
|
142
|
+
if (this.pendingBytes === 0)
|
|
143
|
+
this.#progressAt = Date.now();
|
|
144
|
+
}
|
|
145
|
+
#fail(error) {
|
|
146
|
+
this.close(error);
|
|
147
|
+
this.onFailure(error);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=outbound-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbound-queue.js","sourceRoot":"","sources":["../src/outbound-queue.ts"],"names":[],"mappings":"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"}
|
package/dist/p2p.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type InnerFrame } from './framing.js';
|
|
2
|
+
export declare const P2P_FEATURE: "p2p-v1";
|
|
3
|
+
export declare const P2P_MIN_BUFFER_BYTES: number;
|
|
4
|
+
export declare const P2P_NEGOTIATION_MS = 10000;
|
|
5
|
+
export declare const P2P_RECOVERY_MS = 30000;
|
|
6
|
+
export declare const DEFAULT_STUN_URLS: string[];
|
|
7
|
+
export type P2PMessage = {
|
|
8
|
+
type: 'accept';
|
|
9
|
+
id: string;
|
|
10
|
+
attempt: boolean;
|
|
11
|
+
} | {
|
|
12
|
+
type: 'configure';
|
|
13
|
+
id: string;
|
|
14
|
+
stun: string[];
|
|
15
|
+
} | {
|
|
16
|
+
type: 'offer' | 'answer';
|
|
17
|
+
id: string;
|
|
18
|
+
sdp: string;
|
|
19
|
+
} | {
|
|
20
|
+
type: 'candidate';
|
|
21
|
+
id: string;
|
|
22
|
+
candidate: string;
|
|
23
|
+
mid: string;
|
|
24
|
+
} | {
|
|
25
|
+
type: 'ready' | 'barrier' | 'commit' | 'committed' | 'fallback' | 'decline' | 'detach' | 'ping' | 'pong';
|
|
26
|
+
id: string;
|
|
27
|
+
};
|
|
28
|
+
export declare function validateStunUrls(value: unknown): string[];
|
|
29
|
+
export declare function decodeP2PMessage(payload: Uint8Array): P2PMessage;
|
|
30
|
+
export declare function p2pFrame(message: P2PMessage): InnerFrame;
|
|
31
|
+
/** A negotiation is bounded in both directions, including rejected messages. */
|
|
32
|
+
export declare class SignalingBudget {
|
|
33
|
+
#private;
|
|
34
|
+
consume(payload: Uint8Array): P2PMessage;
|
|
35
|
+
}
|
|
36
|
+
export declare function directConnectionId(pairing: string, id: string): string;
|
|
37
|
+
//# sourceMappingURL=p2p.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"p2p.d.ts","sourceRoot":"","sources":["../src/p2p.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/D,eAAO,MAAM,WAAW,EAAG,QAAiB,CAAC;AAC7C,eAAO,MAAM,oBAAoB,QAAa,CAAC;AAC/C,eAAO,MAAM,kBAAkB,QAAS,CAAC;AACzC,eAAO,MAAM,eAAe,QAAS,CAAC;AACtC,eAAO,MAAM,iBAAiB,UAAmC,CAAC;AAClE,MAAM,MAAM,UAAU,GAChB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACjE;IACI,IAAI,EACE,OAAO,GACP,SAAS,GACT,QAAQ,GACR,WAAW,GACX,UAAU,GACV,SAAS,GACT,QAAQ,GACR,MAAM,GACN,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACd,CAAC;AAGR,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAkBzD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU,CAmDhE;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU,CAIxD;AAED,gFAAgF;AAChF,qBAAa,eAAe;;IAGjB,OAAO,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU;CASlD;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAItE"}
|
package/dist/p2p.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { InnerFrameType } from './framing.js';
|
|
2
|
+
export const P2P_FEATURE = 'p2p-v1';
|
|
3
|
+
export const P2P_MIN_BUFFER_BYTES = 512 * 1024;
|
|
4
|
+
export const P2P_NEGOTIATION_MS = 10_000;
|
|
5
|
+
export const P2P_RECOVERY_MS = 30_000;
|
|
6
|
+
export const DEFAULT_STUN_URLS = ['stun:stun.l.google.com:19302'];
|
|
7
|
+
const encoder = new TextEncoder();
|
|
8
|
+
export function validateStunUrls(value) {
|
|
9
|
+
if (!Array.isArray(value) ||
|
|
10
|
+
value.length > 4 ||
|
|
11
|
+
value.some((url) => typeof url !== 'string' ||
|
|
12
|
+
url.length > 256 ||
|
|
13
|
+
!/^stun:(?:[a-zA-Z0-9.-]+|\[[a-fA-F0-9:]+\])(?::[0-9]{1,5})?$/.test(url) ||
|
|
14
|
+
(/:([0-9]+)$/.test(url) &&
|
|
15
|
+
(Number(url.match(/:([0-9]+)$/)?.[1]) < 1 ||
|
|
16
|
+
Number(url.match(/:([0-9]+)$/)?.[1]) > 65535))))
|
|
17
|
+
throw new Error('Expected up to four STUN URLs without credentials.');
|
|
18
|
+
return [...value];
|
|
19
|
+
}
|
|
20
|
+
export function decodeP2PMessage(payload) {
|
|
21
|
+
if (payload.byteLength > 34 * 1024)
|
|
22
|
+
throw new Error('P2P message exceeds limit.');
|
|
23
|
+
const value = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(payload));
|
|
24
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
25
|
+
throw new Error('Invalid P2P message.');
|
|
26
|
+
const v = value;
|
|
27
|
+
if (typeof v.id !== 'string' || !/^[a-f0-9]{32}$/.test(v.id))
|
|
28
|
+
throw new Error('Invalid negotiation ID.');
|
|
29
|
+
const id = v.id;
|
|
30
|
+
switch (v.type) {
|
|
31
|
+
case 'accept':
|
|
32
|
+
if (typeof v.attempt !== 'boolean')
|
|
33
|
+
break;
|
|
34
|
+
return { type: v.type, id, attempt: v.attempt };
|
|
35
|
+
case 'configure':
|
|
36
|
+
return { type: v.type, id, stun: validateStunUrls(v.stun) };
|
|
37
|
+
case 'offer':
|
|
38
|
+
case 'answer':
|
|
39
|
+
if (typeof v.sdp !== 'string' ||
|
|
40
|
+
encoder.encode(v.sdp).length > 32 * 1024 ||
|
|
41
|
+
!/^v=0\r?\n/.test(v.sdp) ||
|
|
42
|
+
!/^m=application /m.test(v.sdp) ||
|
|
43
|
+
/^m=(?!application )/m.test(v.sdp))
|
|
44
|
+
break;
|
|
45
|
+
return { type: v.type, id, sdp: v.sdp };
|
|
46
|
+
case 'candidate':
|
|
47
|
+
if (typeof v.candidate !== 'string' ||
|
|
48
|
+
encoder.encode(v.candidate).length > 2048 ||
|
|
49
|
+
!/^candidate:/.test(v.candidate) ||
|
|
50
|
+
typeof v.mid !== 'string' ||
|
|
51
|
+
v.mid.length > 64)
|
|
52
|
+
break;
|
|
53
|
+
return { type: v.type, id, candidate: v.candidate, mid: v.mid };
|
|
54
|
+
case 'ready':
|
|
55
|
+
case 'barrier':
|
|
56
|
+
case 'commit':
|
|
57
|
+
case 'committed':
|
|
58
|
+
case 'fallback':
|
|
59
|
+
case 'decline':
|
|
60
|
+
case 'detach':
|
|
61
|
+
case 'ping':
|
|
62
|
+
case 'pong':
|
|
63
|
+
return { type: v.type, id };
|
|
64
|
+
}
|
|
65
|
+
throw new Error('Invalid P2P message.');
|
|
66
|
+
}
|
|
67
|
+
export function p2pFrame(message) {
|
|
68
|
+
const payload = encoder.encode(JSON.stringify(message));
|
|
69
|
+
decodeP2PMessage(payload);
|
|
70
|
+
return { type: InnerFrameType.P2PControl, ptyId: 0, sequence: 0n, payload };
|
|
71
|
+
}
|
|
72
|
+
/** A negotiation is bounded in both directions, including rejected messages. */
|
|
73
|
+
export class SignalingBudget {
|
|
74
|
+
#bytes = 0;
|
|
75
|
+
#candidates = 0;
|
|
76
|
+
consume(payload) {
|
|
77
|
+
this.#bytes += payload.byteLength;
|
|
78
|
+
if (this.#bytes > 256 * 1024)
|
|
79
|
+
throw new Error('Signaling budget exceeded.');
|
|
80
|
+
const message = decodeP2PMessage(payload);
|
|
81
|
+
if (message.type === 'candidate' && ++this.#candidates > 64)
|
|
82
|
+
throw new Error('Too many ICE candidates.');
|
|
83
|
+
return message;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export function directConnectionId(pairing, id) {
|
|
87
|
+
if (!pairing || !/^[a-f0-9]{32}$/.test(id))
|
|
88
|
+
throw new Error('Invalid direct connection binding.');
|
|
89
|
+
return JSON.stringify(['airterm-direct-v1', pairing, id]);
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=p2p.js.map
|
package/dist/p2p.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"p2p.js","sourceRoot":"","sources":["../src/p2p.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type SealedValue } from './vault.js';
|
|
2
|
+
export interface PairingApproval {
|
|
3
|
+
version: 1;
|
|
4
|
+
pairingId: string;
|
|
5
|
+
accountId: string;
|
|
6
|
+
email: string;
|
|
7
|
+
generation: number;
|
|
8
|
+
publicKey: string;
|
|
9
|
+
fingerprint: string;
|
|
10
|
+
token: string;
|
|
11
|
+
}
|
|
12
|
+
export interface EncryptedPairing extends SealedValue {
|
|
13
|
+
version: 1;
|
|
14
|
+
}
|
|
15
|
+
export declare function validatePairingApproval(value: PairingApproval, pairingId: string): Promise<void>;
|
|
16
|
+
export declare function encryptPairingApproval(value: PairingApproval, secret: Uint8Array): Promise<EncryptedPairing>;
|
|
17
|
+
export declare function decryptPairingApproval(value: EncryptedPairing, secret: Uint8Array, pairingId: string): Promise<PairingApproval>;
|
|
18
|
+
//# sourceMappingURL=pairing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pairing.d.ts","sourceRoot":"","sources":["../src/pairing.ts"],"names":[],"mappings":"AACA,OAAO,EAA0C,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAEtF,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,CAAC,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACjB;AACD,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IAAG,OAAO,EAAE,CAAC,CAAA;CAAE;AAYpE,wBAAsB,uBAAuB,CAAC,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAItG;AACD,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAOlH;AACD,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAUrI"}
|
package/dist/pairing.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { decodeBase64Url, encodeBase64Url } from './capability.js';
|
|
2
|
+
import { publicKeyFingerprint, randomVaultBytes } from './vault.js';
|
|
3
|
+
const bytes = (value) => new Uint8Array(value).buffer;
|
|
4
|
+
function decode(value, size) {
|
|
5
|
+
const result = decodeBase64Url(value);
|
|
6
|
+
if (result.length !== size || encodeBase64Url(result) !== value)
|
|
7
|
+
throw new Error('Invalid pairing value');
|
|
8
|
+
return result;
|
|
9
|
+
}
|
|
10
|
+
async function key(secret, pairingId) {
|
|
11
|
+
if (secret.length !== 32)
|
|
12
|
+
throw new Error('Invalid pairing secret');
|
|
13
|
+
const source = await crypto.subtle.importKey('raw', bytes(secret), 'HKDF', false, ['deriveKey']);
|
|
14
|
+
return crypto.subtle.deriveKey({ name: 'HKDF', hash: 'SHA-256', salt: bytes(decode(pairingId, 16)), info: new TextEncoder().encode('airterm/pairing/v1/approval') }, source, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']);
|
|
15
|
+
}
|
|
16
|
+
export async function validatePairingApproval(value, pairingId) {
|
|
17
|
+
if (!value || value.version !== 1 || value.pairingId !== pairingId || !/^[1-9][0-9]{0,18}$/.test(value.accountId) || !Number.isSafeInteger(value.generation) || value.generation < 1 || typeof value.email !== 'string' || value.email.length > 254 || !/^[^\s@\x00-\x1f\x7f]+@[^\s@\x00-\x1f\x7f]+$/.test(value.email))
|
|
18
|
+
throw new Error('Invalid pairing identity');
|
|
19
|
+
decode(value.token, 32);
|
|
20
|
+
if (await publicKeyFingerprint(value.publicKey) !== value.fingerprint)
|
|
21
|
+
throw new Error('Invalid public key fingerprint');
|
|
22
|
+
}
|
|
23
|
+
export async function encryptPairingApproval(value, secret) {
|
|
24
|
+
await validatePairingApproval(value, value.pairingId);
|
|
25
|
+
const nonce = randomVaultBytes(12);
|
|
26
|
+
const data = new TextEncoder().encode(JSON.stringify(value));
|
|
27
|
+
if (data.length > 4096)
|
|
28
|
+
throw new Error('Oversized pairing approval');
|
|
29
|
+
const ciphertext = await crypto.subtle.encrypt({ name: 'AES-GCM', iv: bytes(nonce), additionalData: new TextEncoder().encode(value.pairingId) }, await key(secret, value.pairingId), bytes(data));
|
|
30
|
+
return { version: 1, nonce: encodeBase64Url(nonce), ciphertext: encodeBase64Url(new Uint8Array(ciphertext)) };
|
|
31
|
+
}
|
|
32
|
+
export async function decryptPairingApproval(value, secret, pairingId) {
|
|
33
|
+
if (!value || value.version !== 1 || typeof value.ciphertext !== 'string' || value.ciphertext.length > 5500)
|
|
34
|
+
throw new Error('Invalid pairing envelope');
|
|
35
|
+
const ciphertext = decodeBase64Url(value.ciphertext);
|
|
36
|
+
if (encodeBase64Url(ciphertext) !== value.ciphertext)
|
|
37
|
+
throw new Error('Invalid pairing encoding');
|
|
38
|
+
const raw = new Uint8Array(await crypto.subtle.decrypt({ name: 'AES-GCM', iv: bytes(decode(value.nonce, 12)), additionalData: new TextEncoder().encode(pairingId) }, await key(secret, pairingId), bytes(ciphertext)));
|
|
39
|
+
try {
|
|
40
|
+
const result = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(raw));
|
|
41
|
+
await validatePairingApproval(result, pairingId);
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
raw.fill(0);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=pairing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pairing.js","sourceRoot":"","sources":["../src/pairing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type InnerFrame } from './framing.js';
|
|
2
|
+
import { type RtcAdapterFactory } from './direct-negotiation.js';
|
|
3
|
+
/** Per-pairing policy. The caller owns relay reconnect and browser-page attempt policy. */
|
|
4
|
+
export declare class PeerTransport {
|
|
5
|
+
#private;
|
|
6
|
+
private readonly options;
|
|
7
|
+
constructor(options: {
|
|
8
|
+
browser: boolean;
|
|
9
|
+
sessionId: string;
|
|
10
|
+
psk: Uint8Array;
|
|
11
|
+
pairing: string;
|
|
12
|
+
factory: RtcAdapterFactory;
|
|
13
|
+
stun: string[];
|
|
14
|
+
relay: (frame: InnerFrame) => Promise<void>;
|
|
15
|
+
frame: (frame: InnerFrame) => void;
|
|
16
|
+
accepted: () => void;
|
|
17
|
+
busy: () => boolean;
|
|
18
|
+
freeze: (frozen: boolean) => void;
|
|
19
|
+
pressure: (paused: boolean) => void;
|
|
20
|
+
changed: (direct: boolean) => void;
|
|
21
|
+
fallback: () => void;
|
|
22
|
+
});
|
|
23
|
+
get direct(): boolean;
|
|
24
|
+
get frozen(): boolean;
|
|
25
|
+
accept(attempt: boolean): void;
|
|
26
|
+
send(frame: InnerFrame): Promise<void>;
|
|
27
|
+
receive(frame: InnerFrame): void;
|
|
28
|
+
fallback(): void;
|
|
29
|
+
close(): void;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=peer-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-transport.d.ts","sourceRoot":"","sources":["../src/peer-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAEH,KAAK,iBAAiB,EACzB,MAAM,yBAAyB,CAAC;AAIjC,2FAA2F;AAC3F,qBAAa,aAAa;;IAUlB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE;QACtB,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,GAAG,EAAE,UAAU,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,iBAAiB,CAAC;QAC3B,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,KAAK,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5C,KAAK,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;QACnC,QAAQ,EAAE,MAAM,IAAI,CAAC;QACrB,IAAI,EAAE,MAAM,OAAO,CAAC;QACpB,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;QAClC,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;QACpC,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;QACnC,QAAQ,EAAE,MAAM,IAAI,CAAC;KACxB;IAEL,IAAW,MAAM,IAAI,OAAO,CAE3B;IACD,IAAW,MAAM,IAAI,OAAO,CAE3B;IACM,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAY9B,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtC,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAyDhC,QAAQ,IAAI,IAAI;IAKhB,KAAK,IAAI,IAAI;CAoDvB"}
|