offline_protocol/constants.rs
1//! Constants used throughout the offline-protocol crate.
2
3/// Default time-to-live for messages.
4pub const DEFAULT_INITIAL_TTL: u8 = 8;
5
6/// Metadata key for ACK messages indicating which message ID the ACK is for.
7///
8/// Re-exported rather than declared, because a leaf node writes the same key on
9/// the acknowledgements it owes and cannot reach this crate. The one home is
10/// `offline-protocol-sealed`; a second spelling here would be a pair that stops
11/// answering each other with nothing failing to build.
12pub use offline_protocol_sealed::ACK_FOR_KEY;
13
14/// Metadata key for ACK messages indicating the hop count.
15pub const ACK_HOP_COUNT_KEY: &str = "ack_hop_count";
16
17/// Metadata key for ACK messages indicating the transport used.
18pub const ACK_TRANSPORT_KEY: &str = "ack_transport";
19
20/// Metadata key on an ACK that answers a frame without delivering it. Absent
21/// on an ordinary delivery ACK.
22pub const ACK_STATUS_KEY: &str = "ack_status";
23
24/// [`ACK_STATUS_KEY`] value: the recipient can never decrypt the frame it
25/// names (a spent ratchet generation, a dead epoch, or the pending-decryption
26/// queue gave up on it). The sender resends the message once; it is
27/// never `message_delivered`. Still a delivery ACK in shape, so a relay holding
28/// the frame drops it.
29pub const ACK_STATUS_UNDECRYPTABLE: &str = "undecryptable";
30
31/// Metadata key marking a frame the SDK sent on its own: control traffic,
32/// key packages, data-sync frames, receipts, typing, presence, and a 1:1
33/// Welcome no user message is waiting on.
34///
35/// Set to `"1"` in the cleartext envelope so the relay can tell these from
36/// the user's own messages (both are opaque `__MLS_ENC__` ciphertext to it)
37/// and skip the "new message" push for an offline recipient. Frames built
38/// for the application's user-content sends never carry it. Unsigned like
39/// all metadata; receivers ignore it.
40pub const NO_ALERT_KEY: &str = "no_alert";
41
42/// Maximum number of entries in the outbox before evicting oldest entries.
43/// This prevents unbounded memory growth when messages cannot be delivered.
44pub const MAX_OUTBOX_ENTRIES: usize = 500;
45
46/// Absolute cap on a restored outbox entry's total lifetime, as a multiple
47/// of `outbox_max_lifetime_ms`, measured from `first_sent_at`.
48///
49/// The restore path refreshes the carrier-relative TTL of an entry that
50/// lapsed while the process was down (restart ⇒ fresh delivery window).
51/// Without an absolute bound, an app used briefly once past each lifetime
52/// keeps re-granting the entry a fresh window forever, so "expiry is
53/// terminal" would only hold in-process. Past this cap the entry is dropped
54/// at restore with a terminal `message_failed` instead of refreshed
55/// (4 × 7 days = 28 days at the default lifetime).
56pub const OUTBOX_ABSOLUTE_LIFETIME_FACTOR: i32 = 4;
57
58/// Maximum number of messages to keep in history for topology visualization.
59/// This prevents unbounded memory growth while maintaining enough history
60/// for accurate network statistics.
61pub const MAX_MESSAGE_HISTORY: usize = 1000;
62
63/// Number of messages to remove when history exceeds the maximum.
64/// This provides a buffer to avoid frequent cleanup operations.
65pub const HISTORY_CLEANUP_BATCH_SIZE: usize = 100;
66
67/// Threshold for compacting observed stats to prevent unbounded growth.
68pub const OBSERVED_STATS_COMPACT_THRESHOLD: u32 = 10_000;
69
70/// EMA (Exponential Moving Average) alpha for latency tracking.
71pub const LATENCY_EMA_ALPHA: f32 = 0.3;
72
73/// EMA alpha for hop count tracking.
74pub const HOP_COUNT_EMA_ALPHA: f32 = 0.2;
75
76/// Default chunk size for file transfers (32 KB).
77pub const DEFAULT_CHUNK_SIZE: usize = 32 * 1024;
78
79/// Chunk size for BLE file transfers (4 KB).
80/// Reduces BLE double-fragmentation: ~22 BLE fragments per chunk instead of ~240.
81pub const CHUNK_SIZE_BLE: usize = 4 * 1024;
82
83/// Chunk size for Internet file transfers (256 KB).
84/// Fewer round-trips over WebSocket where bandwidth is plentiful.
85pub const CHUNK_SIZE_INTERNET: usize = 256 * 1024;
86
87/// Maximum chunks in flight for BLE media transfers.
88/// BLE's low bandwidth means fewer concurrent chunks to avoid congestion.
89pub const MEDIA_WINDOW_SIZE_BLE: usize = 2;
90
91/// Maximum chunks in flight for Internet media transfers.
92pub const MEDIA_WINDOW_SIZE_INTERNET: usize = 8;
93
94/// Default maximum chunks in flight for media transfers.
95pub const DEFAULT_MEDIA_WINDOW_SIZE: usize = 4;
96
97/// Maximum entries in the dedicated media outbox.
98/// Smaller than the main outbox since the sliding window limits in-flight chunks.
99pub const MAX_MEDIA_OUTBOX_ENTRIES: usize = 100;
100
101/// Maximum persisted outbound media transfer descriptors restored after a
102/// restart (newest-first). Small on purpose: each maps to a
103/// `MediaResendRequired` the app is expected to act on, and concurrent
104/// transfers are already capped per peer.
105pub const MAX_MEDIA_DESCRIPTORS: usize = 16;
106
107/// Maximum concurrent outbound media transfers per recipient when chunks are
108/// MLS-encrypted.
109///
110/// Encrypted chunks share the recipient's 1:1 session ratchet with text, and
111/// the receiver retains out-of-order message keys for only
112/// `SENDER_RATCHET_OUT_OF_ORDER_TOLERANCE` (32) generations. Each transfer
113/// keeps up to `MEDIA_WINDOW_SIZE_INTERNET` (8) chunks in flight, so two
114/// concurrent transfers bound the media-side in-flight gap at 16
115/// generations, leaving room for up to 16 further messages interleaved on
116/// the same ratchet before a delayed chunk's key is deleted. That residual
117/// is not a guarantee: text sends are unbounded, and a chunk delayed while
118/// 32+ interleaved messages decrypt first is permanently undecryptable (the
119/// receiver surfaces this as `MessageDecryptionFailed`). Without this cap,
120/// concurrent transfers alone could push a delayed chunk beyond the
121/// tolerance and permanently stall its transfer.
122pub const MAX_CONCURRENT_MEDIA_TRANSFERS_PER_PEER: usize = 2;
123
124/// How many of a peer's transfer slots the SDK's own document-layer traffic
125/// may occupy at once.
126///
127/// Strictly below [`MAX_CONCURRENT_MEDIA_TRANSFERS_PER_PEER`], and that is
128/// the whole point. A document-layer transfer is invisible to the
129/// application on both sides, so an application whose own `send_media` fails
130/// with [`crate::Error::MediaTransferLimit`] cannot see what is holding the
131/// slots or wait for it to finish. Leaving one slot always reachable keeps
132/// that error explainable by what the application itself is doing.
133pub const MAX_CONCURRENT_INTERNAL_MEDIA_TRANSFERS_PER_PEER: usize = 1;
134
135/// Metadata key indicating preferred transport for a message.
136pub const TRANSPORT_PREFERENCE_KEY: &str = "transport_preference";
137
138/// Transport preference value: prefer internet transport.
139pub const TRANSPORT_PREFERENCE_INTERNET: &str = "internet";
140
141/// Metadata key carrying the original content type on file-chunk messages.
142pub const ORIGINAL_CONTENT_TYPE_KEY: &str = "original_content_type";
143
144/// Maximum number of times a message may be forwarded. Prevents unbounded
145/// forwarding chains from malicious or buggy clients.
146pub const MAX_FORWARD_COUNT: u32 = 100;
147
148/// Maximum messages to send in a single flush operation.
149/// Prevents blocking the process loop when many messages are pending.
150pub const FLUSH_BATCH_LIMIT: usize = 20;