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