Skip to main content

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