1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! Protocol constants shared between server and client.
/// Fixed chunk size for fragmented transfers (2 MiB).
pub const CHUNK_SIZE: u64 = 2 * 1024 * 1024;
/// Constant sliding-window size for streaming (64 KiB).
pub const STREAM_BUF_SIZE: usize = 64 * 1024;
/// Maximum default concurrent connections in the WASM engine.
pub const DEFAULT_CONCURRENCY: usize = 4;
/// Default in-flight chunk window for a single file's upload.
///
/// Kept independent of (and larger than) [`DEFAULT_CONCURRENCY`] so one file
/// keeps many chunks in flight on high-latency links — enough to fill the
/// bandwidth-delay product and avoid the "fill, drain, fill" stutter that a
/// tiny window (== concurrency) causes. It also sets an upper bound that
/// still works within browser per-origin connection limits (~6 for HTTP/1.1).
pub const DEFAULT_UPLOAD_WINDOW: usize = 8;
/// Default in-flight chunk window for a single file's **download**.
///
/// The tus-style parallel download fetches a large file as many concurrent
/// byte-range GETs, so a single file's throughput is bounded by bandwidth
/// instead of `chunk_size / RTT` (the same bandwidth-delay-product fill that
/// [`DEFAULT_UPLOAD_WINDOW`] provides for uploads). Independent of
/// `concurrency` (cross-file) and of the upload window. Kept modest because
/// the WASM engine buffers in-flight chunks in a reorder map so it can emit
/// them to the SDK strictly in order (append-mode writes); the buffer bound
/// is `window * download_chunk_size`.
pub const DEFAULT_DOWNLOAD_WINDOW: usize = 4;
/// Default chunk size for parallel (byte-range) downloads — 256 KiB.
///
/// Deliberately smaller than the 2 MiB upload chunk: the WASM engine holds
/// up to `download_window` of these in a reorder buffer while waiting for
/// them to arrive in order, so `window * chunk_size` (4 × 256 KiB = 1 MiB by
/// default) is the engine's worst-case extra allocation — comfortably under
/// the ~2 MiB per-file memory budget.
pub const DEFAULT_DOWNLOAD_CHUNK_SIZE: u64 = 256 * 1024;
/// A file with fewer remaining bytes than this stays on the sequential
/// single-connection download path; larger files use the parallel range-GET
/// path (which has per-request overhead that only pays off at size).
pub const MIN_PARALLEL_DOWNLOAD_BYTES: u64 = 512 * 1024;
/// Server-side TTL after which an unfinished "session" upload temp (and its
/// `.blocks` range sidecar) is considered stale and garbage-collected.
///
/// tus `Expiration`-style: a client that vanishes mid-upload would otherwise
/// leave its shared temp behind forever; the server sweeps temps older than
/// this. Uploads that are actively being written keep their temp fresh, so
/// this never interrupts an in-flight transfer.
pub const DEFAULT_SESSION_TTL: Duration = from_secs;
/// Default maximum retry count for a failed chunk before failing the task.
pub const MAX_RETRIES: u32 = 3;
/// Default cap for a single upload (100 GiB, configurable by the server).
pub const DEFAULT_MAX_UPLOAD_SIZE: u64 = 100 * 1024 * 1024 * 1024;
/// HTTP header advertising the compression algorithm on a body stream.
///
/// Value is a [`CompressionFormat`](crate::compress::CompressionFormat)
/// name (e.g. `zrip`). Mirrored by `Content-Encoding` when applicable.
pub const HEADER_COMPRESS: &str = "x-libfw-compress";
/// HTTP header carrying JSON-encoded [`FileMeta`](crate::metadata::FileMeta)
/// for an upload or download.
pub const HEADER_FILE_META: &str = "x-libfw-file-meta";
/// HTTP header carrying the byte offset to resume an interrupted upload.
pub const HEADER_OFFSET: &str = "x-libfw-offset";
/// HTTP header marking an upload request as the FINAL chunk of a file.
///
/// When present (value `1`/`true`), the server verifies that the resulting
/// file size equals the declared `x-libfw-file-meta` size before committing,
/// so a client cannot commit a truncated file. Absent (older clients) skips
/// the check — the header is optional and backward compatible.
pub const HEADER_FINAL: &str = "x-libfw-final";
/// HTTP header carrying a per-upload **session id**.
///
/// When present, the upload uses the concurrent "session" protocol: each
/// chunk carries its ABSOLUTE `x-libfw-offset` and is written into a shared
/// per-session temp file (positional writes), and the final
/// `x-libfw-final` request commits it. This lets a client pipeline many
/// chunks in flight (hiding round-trip latency) instead of serializing one
/// request per chunk. Absent → legacy per-request sequential upload.
///
/// A session id should be **stable for a given file version** (derived from
/// the ETag) so an interrupted upload can be found again on resume: the
/// shared temp file is keyed by this id, and the server persists which byte
/// ranges have already been received (see [`HEADER_SESSION_STATUS`]).
pub const HEADER_SESSION: &str = "x-libfw-session";
/// HTTP header turning a session `POST` into a **status probe**.
///
/// When present (value `1`/`probe`) on a session request, the server does
/// NOT write the body. Instead it opens (creating if needed) the shared
/// per-session temp and replies with the JSON-encoded byte ranges already
/// received for that session: `{"ranges": [[start,end], ...]}`. The client
/// uses this to compute which blocks are still missing and re-send only
/// those — a BitTorrent-style "only retransmit the broken parts" resume.
///
/// Absent (older clients) keeps the previous behavior; legacy servers that
/// ignore this header simply write nothing for the empty probe body and
/// return an empty range set, which degrades to a full re-send (idempotent
/// positional writes make that correct too).
pub const HEADER_SESSION_STATUS: &str = "x-libfw-session-status";
/// HTTP header carrying the (optional) transfer version handshake.
pub const HEADER_PROTOCOL: &str = "x-libfw-protocol";
/// Protocol name used in the handshake header.
pub const PROTOCOL_NAME: &str = "libfw";
/// Protocol version used in the handshake header.
pub const PROTOCOL_VERSION: &str = "1";
/// The canonical `x-libfw-protocol` header value (e.g. `libfw/1`).
///
/// Both the server and the WASM client must agree on this exact value; the
/// server rejects (426) requests that explicitly advertise a different one.
/// Keep in sync with [`PROTOCOL_NAME`] / [`PROTOCOL_VERSION`].
/// Whether a received `x-libfw-protocol` handshake value is compatible with
/// this build of the library.