openrtc-file-transfer 0.1.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/LICENSE ADDED
@@ -0,0 +1 @@
1
+ See the OpenRTC repository LICENSE for terms.
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # openrtc-file-transfer
2
+
3
+ Optional file-transfer protocol for OpenRTC applications. It operates only on
4
+ the public `client.channels` API; OpenRTC core remains message-agnostic.
5
+
6
+ ```ts
7
+ import { createFileTransferProtocol } from 'openrtc-file-transfer';
8
+
9
+ const files = createFileTransferProtocol(client);
10
+ const stop = files.onIncoming(({ file }) => saveBlob(file.blob, file.name));
11
+ await files.send(deviceId, selectedFile, { onProgress: console.log });
12
+ ```
13
+
14
+ The package owns reusable framing, bounded validation, acknowledgement,
15
+ progress, cancellation, and optional SHA-256 verification. Applications own
16
+ file pickers, destination paths, acceptance policy, persistent queues, history,
17
+ billing, and notifications. Native applications should provide a streaming
18
+ `ReceiveSink`, the wire-compatible Rust `openrtc-file-transfer` crate, or a
19
+ host-side file adapter instead of buffering large files in the WebView. A
20
+ custom sink receiving SHA-256-protected transfers must implement
21
+ `verifySha256`; verification fails closed rather than silently accepting an
22
+ unchecked native file. Resume uses a declared `offset`: the sender starts at
23
+ that byte and the receiver accepts it only when its sink reports the exact
24
+ application-verified `resumeOffset`.
@@ -0,0 +1,70 @@
1
+ import type { OpenRTCClient, RuntimeChannelDescriptor } from 'openrtc';
2
+ export declare const FILE_TRANSFER_CHANNEL: RuntimeChannelDescriptor;
3
+ export interface FileTransferHeader {
4
+ version: 1;
5
+ transferId: string;
6
+ name: string;
7
+ size: number;
8
+ /** Existing verified prefix length. Sender transmits bytes from this offset. */
9
+ offset?: number;
10
+ mimeType: string;
11
+ sha256?: string;
12
+ metadata?: Record<string, string>;
13
+ }
14
+ export interface TransferProgress {
15
+ transferId: string;
16
+ transferredBytes: number;
17
+ totalBytes: number;
18
+ direction: 'send' | 'receive';
19
+ }
20
+ export interface ReceivedFile {
21
+ transferId: string;
22
+ name: string;
23
+ mimeType: string;
24
+ size: number;
25
+ blob: Blob;
26
+ sha256?: string;
27
+ metadata?: Record<string, string>;
28
+ remoteNodeId: string;
29
+ }
30
+ export interface ReceiveSink<Result = unknown> {
31
+ /** Must equal the requested header offset for a resumed transfer. */
32
+ resumeOffset?: number;
33
+ write(chunk: Uint8Array): Promise<void>;
34
+ close(): Promise<Result>;
35
+ abort(reason: unknown): Promise<void>;
36
+ /** Verify a sender-declared digest without requiring WebView buffering. */
37
+ verifySha256?(expectedHex: string): Promise<boolean>;
38
+ }
39
+ export interface IncomingTransfer<Result = ReceivedFile> {
40
+ header: FileTransferHeader;
41
+ remoteNodeId: string;
42
+ result: Result;
43
+ }
44
+ export interface FileTransferProtocolOptions<Result = ReceivedFile> {
45
+ channel?: RuntimeChannelDescriptor;
46
+ chunkBytes?: number;
47
+ maxHeaderBytes?: number;
48
+ maxFileBytes?: number;
49
+ createReceiveSink?: (header: FileTransferHeader, remoteNodeId: string) => Promise<ReceiveSink<Result>>;
50
+ }
51
+ export interface SendFileOptions {
52
+ transferId?: string;
53
+ metadata?: Record<string, string>;
54
+ integrity?: 'none' | 'sha256';
55
+ offsetBytes?: number;
56
+ signal?: AbortSignal;
57
+ onProgress?: (progress: TransferProgress) => void;
58
+ }
59
+ export interface ReceiveFileOptions<Result> {
60
+ signal?: AbortSignal;
61
+ onProgress?: (progress: TransferProgress) => void;
62
+ onFile: (transfer: IncomingTransfer<Result>) => void | Promise<void>;
63
+ onError?: (error: Error) => void;
64
+ }
65
+ export declare function createFileTransferProtocol<Result = ReceivedFile>(client: OpenRTCClient, options?: FileTransferProtocolOptions<Result>): {
66
+ send(deviceId: string, file: File, sendOptions?: SendFileOptions): Promise<string>;
67
+ onIncoming(receiveOptions: ReceiveFileOptions<Result>): () => void;
68
+ dispose(): void;
69
+ };
70
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,240 @@
1
+ export const FILE_TRANSFER_CHANNEL = {
2
+ id: 'openrtc.file-transfer.v1',
3
+ kind: 'transfer',
4
+ ownership: 'shared',
5
+ peerModel: 'device-first',
6
+ routing: 'stream-envelope',
7
+ readiness: 'settled-peer',
8
+ description: 'Versioned OpenRTC file-transfer protocol',
9
+ };
10
+ const ACK_OK = 0x01;
11
+ const ACK_REJECTED = 0x02;
12
+ const DEFAULT_CHUNK_BYTES = 64 * 1024;
13
+ const DEFAULT_MAX_HEADER_BYTES = 64 * 1024;
14
+ const DEFAULT_MAX_BUFFERED_FILE_BYTES = 256 * 1024 * 1024;
15
+ class ByteReader {
16
+ constructor(stream) {
17
+ this.buffer = new Uint8Array(0);
18
+ this.ended = false;
19
+ this.reader = stream.getReader();
20
+ }
21
+ async fill(count, signal) {
22
+ while (this.buffer.byteLength < count && !this.ended) {
23
+ throwIfAborted(signal);
24
+ const next = await this.reader.read();
25
+ if (next.done) {
26
+ this.ended = true;
27
+ break;
28
+ }
29
+ if (!next.value?.byteLength)
30
+ continue;
31
+ const merged = new Uint8Array(this.buffer.byteLength + next.value.byteLength);
32
+ merged.set(this.buffer);
33
+ merged.set(next.value, this.buffer.byteLength);
34
+ this.buffer = merged;
35
+ }
36
+ }
37
+ async exact(count, signal) {
38
+ await this.fill(count, signal);
39
+ if (this.buffer.byteLength < count)
40
+ throw new Error('file transfer stream ended early');
41
+ const value = this.buffer.slice(0, count);
42
+ this.buffer = this.buffer.slice(count);
43
+ return value;
44
+ }
45
+ async some(max, signal) {
46
+ if (!this.buffer.byteLength)
47
+ await this.fill(1, signal);
48
+ if (!this.buffer.byteLength)
49
+ return null;
50
+ const count = Math.min(max, this.buffer.byteLength);
51
+ const value = this.buffer.slice(0, count);
52
+ this.buffer = this.buffer.slice(count);
53
+ return value;
54
+ }
55
+ async cancel(reason) {
56
+ await this.reader.cancel(reason).catch(() => undefined);
57
+ }
58
+ }
59
+ function throwIfAborted(signal) {
60
+ if (signal?.aborted)
61
+ throw signal.reason ?? new DOMException('Transfer aborted', 'AbortError');
62
+ }
63
+ function transferId() {
64
+ return globalThis.crypto?.randomUUID?.() ?? `transfer-${Date.now()}-${Math.random().toString(16).slice(2)}`;
65
+ }
66
+ function encodeHeader(header, maxBytes) {
67
+ const body = new TextEncoder().encode(JSON.stringify(header));
68
+ if (body.byteLength > maxBytes)
69
+ throw new Error(`file transfer header exceeds ${maxBytes} bytes`);
70
+ const frame = new Uint8Array(4 + body.byteLength);
71
+ new DataView(frame.buffer).setUint32(0, body.byteLength, false);
72
+ frame.set(body, 4);
73
+ return frame;
74
+ }
75
+ function parseHeader(bytes, maxFileBytes) {
76
+ const value = JSON.parse(new TextDecoder().decode(bytes));
77
+ if (value.version !== 1 || typeof value.transferId !== 'string' || !value.transferId.trim()) {
78
+ throw new Error('invalid file transfer header version or transferId');
79
+ }
80
+ if (typeof value.name !== 'string' || !value.name.trim() || /[\\/\0]/.test(value.name)) {
81
+ throw new Error('invalid file transfer name');
82
+ }
83
+ if (!Number.isSafeInteger(value.size) || value.size < 0 || value.size > maxFileBytes) {
84
+ throw new Error(`invalid file transfer size; maximum is ${maxFileBytes} bytes`);
85
+ }
86
+ if (value.offset !== undefined && (!Number.isSafeInteger(value.offset) || value.offset < 0 || value.offset > value.size)) {
87
+ throw new Error('invalid file transfer resume offset');
88
+ }
89
+ if (typeof value.mimeType !== 'string')
90
+ throw new Error('invalid file transfer MIME type');
91
+ if (value.sha256 !== undefined && !/^[a-f0-9]{64}$/i.test(value.sha256)) {
92
+ throw new Error('invalid file transfer SHA-256 digest');
93
+ }
94
+ return value;
95
+ }
96
+ async function sha256(blob) {
97
+ if (!globalThis.crypto?.subtle)
98
+ throw new Error('SHA-256 integrity requires Web Crypto');
99
+ const digest = await globalThis.crypto.subtle.digest('SHA-256', await blob.arrayBuffer());
100
+ return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, '0')).join('');
101
+ }
102
+ function bufferedSink(header, remoteNodeId) {
103
+ const chunks = [];
104
+ return {
105
+ async write(chunk) { chunks.push(chunk.slice()); },
106
+ async close() {
107
+ const blob = new Blob(chunks, { type: header.mimeType });
108
+ return {
109
+ transferId: header.transferId,
110
+ name: header.name,
111
+ mimeType: header.mimeType,
112
+ size: header.size,
113
+ blob,
114
+ sha256: header.sha256,
115
+ metadata: header.metadata,
116
+ remoteNodeId,
117
+ };
118
+ },
119
+ async abort() { chunks.length = 0; },
120
+ };
121
+ }
122
+ export function createFileTransferProtocol(client, options = {}) {
123
+ const channel = options.channel ?? FILE_TRANSFER_CHANNEL;
124
+ const chunkBytes = options.chunkBytes ?? DEFAULT_CHUNK_BYTES;
125
+ const maxHeaderBytes = options.maxHeaderBytes ?? DEFAULT_MAX_HEADER_BYTES;
126
+ const maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_BUFFERED_FILE_BYTES;
127
+ if (!Number.isSafeInteger(chunkBytes) || chunkBytes <= 0)
128
+ throw new Error('chunkBytes must be positive');
129
+ client.channels.register(channel);
130
+ return {
131
+ async send(deviceId, file, sendOptions = {}) {
132
+ if (file.size > maxFileBytes)
133
+ throw new Error(`file exceeds ${maxFileBytes} byte transfer limit`);
134
+ throwIfAborted(sendOptions.signal);
135
+ const id = sendOptions.transferId ?? transferId();
136
+ const header = {
137
+ version: 1,
138
+ transferId: id,
139
+ name: file.name,
140
+ size: file.size,
141
+ offset: sendOptions.offsetBytes && sendOptions.offsetBytes > 0 ? sendOptions.offsetBytes : undefined,
142
+ mimeType: file.type || 'application/octet-stream',
143
+ metadata: sendOptions.metadata,
144
+ sha256: sendOptions.integrity === 'sha256' ? await sha256(file) : undefined,
145
+ };
146
+ const offset = header.offset ?? 0;
147
+ if (!Number.isSafeInteger(offset) || offset < 0 || offset > file.size) {
148
+ throw new Error('offsetBytes must be within the selected file');
149
+ }
150
+ const stream = await client.channels.openBi(deviceId, channel.id);
151
+ const writer = stream.writable.getWriter();
152
+ try {
153
+ await writer.write(encodeHeader(header, maxHeaderBytes));
154
+ let sent = offset;
155
+ sendOptions.onProgress?.({ transferId: id, transferredBytes: sent, totalBytes: file.size, direction: 'send' });
156
+ while (sent < file.size) {
157
+ throwIfAborted(sendOptions.signal);
158
+ const chunk = new Uint8Array(await file.slice(sent, sent + chunkBytes).arrayBuffer());
159
+ await writer.write(chunk);
160
+ sent += chunk.byteLength;
161
+ sendOptions.onProgress?.({ transferId: id, transferredBytes: sent, totalBytes: file.size, direction: 'send' });
162
+ }
163
+ await writer.close();
164
+ }
165
+ catch (error) {
166
+ await writer.abort(error).catch(() => undefined);
167
+ throw error;
168
+ }
169
+ const ack = await new ByteReader(stream.readable).exact(1, sendOptions.signal);
170
+ if (ack[0] !== ACK_OK)
171
+ throw new Error(ack[0] === ACK_REJECTED ? 'file transfer rejected' : 'invalid file transfer acknowledgement');
172
+ return id;
173
+ },
174
+ onIncoming(receiveOptions) {
175
+ return client.channels.onIncomingChannel(channel.id, (incoming) => {
176
+ if (incoming.type !== 'bi')
177
+ return false;
178
+ const stream = incoming.stream;
179
+ void (async () => {
180
+ const reader = new ByteReader(stream.readable);
181
+ const writer = stream.writable.getWriter();
182
+ let sink;
183
+ try {
184
+ const lengthBytes = await reader.exact(4, receiveOptions.signal);
185
+ const headerLength = new DataView(lengthBytes.buffer, lengthBytes.byteOffset, 4).getUint32(0, false);
186
+ if (!headerLength || headerLength > maxHeaderBytes)
187
+ throw new Error(`invalid file transfer header length ${headerLength}`);
188
+ const header = parseHeader(await reader.exact(headerLength, receiveOptions.signal), maxFileBytes);
189
+ sink = options.createReceiveSink
190
+ ? await options.createReceiveSink(header, incoming.remoteNodeId)
191
+ : bufferedSink(header, incoming.remoteNodeId);
192
+ const offset = header.offset ?? 0;
193
+ if (offset > 0 && sink.resumeOffset !== offset) {
194
+ throw new Error(`receive sink cannot resume at offset ${offset}`);
195
+ }
196
+ let received = offset;
197
+ receiveOptions.onProgress?.({ transferId: header.transferId, transferredBytes: received, totalBytes: header.size, direction: 'receive' });
198
+ while (received < header.size) {
199
+ throwIfAborted(receiveOptions.signal);
200
+ const chunk = await reader.some(Math.min(chunkBytes, header.size - received), receiveOptions.signal);
201
+ if (!chunk)
202
+ throw new Error('file transfer stream ended before declared size');
203
+ await sink.write(chunk);
204
+ received += chunk.byteLength;
205
+ receiveOptions.onProgress?.({ transferId: header.transferId, transferredBytes: received, totalBytes: header.size, direction: 'receive' });
206
+ }
207
+ const result = await sink.close();
208
+ if (header.sha256) {
209
+ const verified = sink.verifySha256
210
+ ? await sink.verifySha256(header.sha256)
211
+ : result && typeof result === 'object' && 'blob' in result
212
+ ? await sha256(result.blob) === header.sha256.toLowerCase()
213
+ : false;
214
+ if (!verified)
215
+ throw new Error('file transfer integrity check failed');
216
+ }
217
+ await writer.write(new Uint8Array([ACK_OK]));
218
+ await writer.close();
219
+ await receiveOptions.onFile({ header, remoteNodeId: incoming.remoteNodeId, result });
220
+ }
221
+ catch (error) {
222
+ await sink?.abort(error).catch(() => undefined);
223
+ receiveOptions.onError?.(error instanceof Error ? error : new Error(String(error)));
224
+ await reader.cancel(error);
225
+ // Do not let a peer that stopped reading its ACK stream
226
+ // suppress local error reporting through backpressure.
227
+ void writer.write(new Uint8Array([ACK_REJECTED]))
228
+ .then(() => writer.close())
229
+ .catch(() => writer.abort(error).catch(() => undefined));
230
+ }
231
+ })();
232
+ return true;
233
+ });
234
+ },
235
+ dispose() {
236
+ client.channels.unregister(channel.id);
237
+ },
238
+ };
239
+ }
240
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "openrtc-file-transfer",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "description": "Optional, transport-independent file transfer protocol for OpenRTC named channels.",
8
+ "license": "SEE LICENSE IN LICENSE",
9
+ "main": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "files": ["dist", "LICENSE", "README.md"],
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js"
16
+ },
17
+ "./package.json": "./package.json"
18
+ },
19
+ "scripts": {
20
+ "build": "rm -rf dist && tsc",
21
+ "test": "vitest run",
22
+ "test:deterministic": "vitest run",
23
+ "prepublishOnly": "pnpm run build && pnpm run test"
24
+ },
25
+ "peerDependencies": {
26
+ "openrtc": "^0.2.1"
27
+ },
28
+ "devDependencies": {
29
+ "openrtc": "workspace:*",
30
+ "typescript": "^5.8.3",
31
+ "vitest": "^4.0.18"
32
+ }
33
+ }