netget/server/coap/observe.rs
1//! Observe (RFC 7641) for the CoAP server: who is observing what, and which notification a
2//! client's ACK or RST answers. Pure and synchronous, like `blockwise.rs`.
3//!
4//! An observer is an endpoint and a token (§3.1). A GET with Observe 0 that the model answers
5//! with a 2.xx registers one, and the response carries an Observe sequence number; a GET with
6//! Observe 1 on the same token removes it (§3.6). The model then pushes state with
7//! `coap_notify`, which reaches every observer of the path.
8//!
9//! An observation also ends when the client says so on the message layer: a **RST** in reply
10//! to a notification (§3.6, the "forget me" a client sends when it has lost interest), or a
11//! Confirmable notification that is never acknowledged (§4.5). Both need the notification's
12//! message id mapped back to its observer, which is what [`Observers::record`] keeps.
13//!
14//! A registration is a claim about an address the server cannot verify — UDP source addresses
15//! are spoofable — so the registry bounds what one claim can cost: [`MAX_OBSERVERS_PER_IP`]
16//! registrations per source IP, and every registration expires [`OBSERVER_MAX_AGE`] after it
17//! was last *confirmed* (registered, re-registered, or a Confirmable notification to it was
18//! acknowledged). An observer that has gone unconfirmed for half that age gets its next
19//! notification as Confirmable whatever `coap_notify` asked for, which is RFC 7641 §4.5's
20//! "at least every 24 hours": a live client acknowledges it and stays, a spoofed address does
21//! not and is removed when the retransmissions run out.
22
23use std::collections::{HashMap, VecDeque};
24use std::net::SocketAddr;
25use std::time::Duration;
26
27use crate::server::connection::ConnectionId;
28use crate::utils::clock::Instant;
29
30/// Observers one server holds at once. A registration past this is served as an ordinary
31/// response without the Observe option, which is how RFC 7641 §4.1 says "not observable":
32/// the client learns it is not registered rather than waiting for notifications that never
33/// come.
34pub const MAX_OBSERVERS: usize = 64;
35
36/// Observers one source IP may hold at once, whatever its ports and tokens. A registration
37/// past this is served without Observe, like one past [`MAX_OBSERVERS`], so one address — or
38/// one spoofed victim — cannot take the whole registry.
39pub const MAX_OBSERVERS_PER_IP: usize = 4;
40
41/// How long a registration lasts without being confirmed. RFC 7641 §4.5 requires a
42/// Confirmable notification at least every 24 hours; a registration nobody has confirmed for
43/// that long is presumed gone and removed.
44pub const OBSERVER_MAX_AGE: Duration = Duration::from_secs(24 * 60 * 60);
45
46/// Notification message ids remembered so a RST can be matched to its observer. A client
47/// answers a notification within ACK_TIMEOUT or not at all, so a window this wide is generous
48/// even at one notification per observer per second. ACKs are matched against the pending
49/// Confirmable notifications instead, which this window does not bound: a Confirmable
50/// notification that falls out of it is still waited for.
51pub const RECENT_NOTIFICATIONS: usize = 256;
52
53/// Observe sequence numbers are 24 bits (§4.4).
54pub const SEQUENCE_MASK: u32 = 0x00FF_FFFF;
55
56/// One registration.
57#[derive(Debug, Clone, PartialEq, Eq)]
58pub struct Observer {
59 pub peer: SocketAddr,
60 pub token: Vec<u8>,
61 pub path: String,
62 pub query: Option<String>,
63 /// The Block2 size the client asked for on registration, if it asked; notifications larger
64 /// than one block are split at this size.
65 pub block_szx: Option<u8>,
66 pub connection_id: ConnectionId,
67}
68
69/// What a registration did.
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub enum Registered {
72 Added,
73 /// The same endpoint and token re-registered (§4.1): the entry is refreshed, not doubled.
74 Replaced,
75 /// [`MAX_OBSERVERS`] are registered already.
76 Full,
77 /// The peer's IP holds [`MAX_OBSERVERS_PER_IP`] registrations already.
78 PeerFull,
79}
80
81/// A notification recently sent, kept only so a RST can be matched to its observer.
82#[derive(Debug, Clone)]
83struct Sent {
84 peer: SocketAddr,
85 message_id: u16,
86 token: Vec<u8>,
87}
88
89#[derive(Debug, Clone)]
90struct Entry {
91 observer: Observer,
92 /// When the registration was last confirmed: registered, re-registered, or acknowledged.
93 confirmed: Instant,
94}
95
96/// The registry.
97#[derive(Debug)]
98pub struct Observers {
99 list: Vec<Entry>,
100 cap: usize,
101 per_ip: usize,
102 max_age: Duration,
103 sequence: u32,
104 /// The last [`RECENT_NOTIFICATIONS`] notifications, for matching a RST.
105 sent: VecDeque<Sent>,
106 /// Confirmable notifications still waiting for their ACK, by (peer, message id), holding
107 /// the observer's token. Never evicted by age or count: an entry leaves only when it is
108 /// acknowledged, reset, superseded by a newer Confirmable notification to the same
109 /// observer (RFC 7641 §4.5.2), its observer is deregistered, or its retransmission task
110 /// [`settle`](Observers::settle)s it. At most one per observer, so at most `cap`.
111 pending: HashMap<(SocketAddr, u16), Vec<u8>>,
112}
113
114impl Default for Observers {
115 fn default() -> Self {
116 Observers::new(MAX_OBSERVERS, MAX_OBSERVERS_PER_IP, OBSERVER_MAX_AGE)
117 }
118}
119
120impl Observers {
121 pub fn new(cap: usize, per_ip: usize, max_age: Duration) -> Observers {
122 Observers {
123 list: Vec::new(),
124 cap,
125 per_ip,
126 max_age,
127 // 0 and 1 are the register/deregister values in a request; starting past them
128 // keeps a notification's sequence from reading like one in a packet capture.
129 sequence: 2,
130 sent: VecDeque::new(),
131 pending: HashMap::new(),
132 }
133 }
134
135 pub fn len(&self) -> usize {
136 self.list.len()
137 }
138
139 pub fn is_empty(&self) -> bool {
140 self.list.is_empty()
141 }
142
143 /// The next sequence number. Strictly increasing modulo 2^24, shared by every resource —
144 /// §4.4 needs only that one observer's notifications increase.
145 pub fn next_sequence(&mut self) -> u32 {
146 let seq = self.sequence & SEQUENCE_MASK;
147 self.sequence = (self.sequence + 1) & SEQUENCE_MASK;
148 seq
149 }
150
151 /// Register `observer`, confirmed as of `now`. The same endpoint and token re-registering
152 /// replaces its entry and renews its confirmation; a new one is refused past
153 /// [`MAX_OBSERVERS_PER_IP`] for its IP or [`MAX_OBSERVERS`] in all.
154 pub fn register(&mut self, observer: Observer, now: Instant) -> Registered {
155 if let Some(existing) = self
156 .list
157 .iter_mut()
158 .find(|e| e.observer.peer == observer.peer && e.observer.token == observer.token)
159 {
160 *existing = Entry {
161 observer,
162 confirmed: now,
163 };
164 return Registered::Replaced;
165 }
166 let ip = observer.peer.ip();
167 if self
168 .list
169 .iter()
170 .filter(|e| e.observer.peer.ip() == ip)
171 .count()
172 >= self.per_ip
173 {
174 return Registered::PeerFull;
175 }
176 if self.list.len() >= self.cap {
177 return Registered::Full;
178 }
179 self.list.push(Entry {
180 observer,
181 confirmed: now,
182 });
183 Registered::Added
184 }
185
186 /// Remove every registration not confirmed within the maximum age, returning them.
187 pub fn expire(&mut self, now: Instant) -> Vec<Observer> {
188 let max_age = self.max_age;
189 let mut expired = Vec::new();
190 self.list.retain(|e| {
191 let keep = now.saturating_duration_since(e.confirmed) < max_age;
192 if !keep {
193 expired.push(e.observer.clone());
194 }
195 keep
196 });
197 for observer in &expired {
198 self.pending
199 .retain(|(p, _), t| !(*p == observer.peer && *t == observer.token));
200 }
201 expired
202 }
203
204 /// Whether the next notification to this observer must be Confirmable because it has gone
205 /// unconfirmed for half the maximum age (RFC 7641 §4.5).
206 pub fn needs_confirmation(&self, peer: SocketAddr, token: &[u8], now: Instant) -> bool {
207 let half = self.max_age / 2;
208 self.list.iter().any(|e| {
209 e.observer.peer == peer
210 && e.observer.token == token
211 && now.saturating_duration_since(e.confirmed) >= half
212 })
213 }
214
215 /// Remove the observation `peer` holds under `token`. True if there was one.
216 pub fn deregister(&mut self, peer: SocketAddr, token: &[u8]) -> bool {
217 let before = self.list.len();
218 self.list
219 .retain(|e| !(e.observer.peer == peer && e.observer.token == token));
220 self.pending
221 .retain(|(p, _), t| !(*p == peer && t.as_slice() == token));
222 before != self.list.len()
223 }
224
225 /// Every observer of `path`, in registration order.
226 pub fn of_path(&self, path: &str) -> Vec<Observer> {
227 self.list
228 .iter()
229 .filter(|e| e.observer.path == path)
230 .map(|e| e.observer.clone())
231 .collect()
232 }
233
234 /// Every registration, for the dashboard and the docs.
235 pub fn all(&self) -> Vec<Observer> {
236 self.list.iter().map(|e| e.observer.clone()).collect()
237 }
238
239 /// Remember that a notification went to `peer` with `message_id`. A `confirmable` one is
240 /// also held as pending until it is acknowledged or settled, replacing any earlier pending
241 /// notification to the same observer — only the newest is retransmitted (RFC 7641 §4.5.2).
242 pub fn record(&mut self, peer: SocketAddr, message_id: u16, token: &[u8], confirmable: bool) {
243 self.sent
244 .retain(|s| !(s.peer == peer && s.message_id == message_id));
245 self.sent.push_back(Sent {
246 peer,
247 message_id,
248 token: token.to_vec(),
249 });
250 while self.sent.len() > RECENT_NOTIFICATIONS {
251 self.sent.pop_front();
252 }
253 self.pending.remove(&(peer, message_id));
254 if confirmable {
255 self.pending
256 .retain(|(p, _), t| !(*p == peer && t.as_slice() == token));
257 self.pending.insert((peer, message_id), token.to_vec());
258 }
259 }
260
261 /// An empty ACK from `peer`. True if it acknowledged a pending Confirmable notification,
262 /// which also renews the observer's confirmation as of `now`.
263 pub fn acknowledge(&mut self, peer: SocketAddr, message_id: u16, now: Instant) -> bool {
264 let Some(token) = self.pending.remove(&(peer, message_id)) else {
265 return false;
266 };
267 if let Some(entry) = self
268 .list
269 .iter_mut()
270 .find(|e| e.observer.peer == peer && e.observer.token == token)
271 {
272 entry.confirmed = now;
273 }
274 true
275 }
276
277 /// Whether a Confirmable notification is still waiting for its ACK: it is pending and its
278 /// observer is still registered. A notification that is not pending was acknowledged,
279 /// reset, superseded or settled — never merely forgotten, because pending entries are not
280 /// evicted.
281 pub fn awaiting_ack(&self, peer: SocketAddr, message_id: u16) -> bool {
282 self.pending.get(&(peer, message_id)).is_some_and(|token| {
283 self.list
284 .iter()
285 .any(|e| e.observer.peer == peer && &e.observer.token == token)
286 })
287 }
288
289 /// Stop waiting for an ACK to this notification: its retransmission task has ended.
290 pub fn settle(&mut self, peer: SocketAddr, message_id: u16) {
291 self.pending.remove(&(peer, message_id));
292 }
293
294 /// Confirmable notifications waiting for their ACK.
295 pub fn pending_len(&self) -> usize {
296 self.pending.len()
297 }
298
299 /// A RST from `peer`: if it answers a notification, that observation ends (§3.6). Returns
300 /// the observer removed.
301 pub fn reset(&mut self, peer: SocketAddr, message_id: u16) -> Option<Observer> {
302 let token = match self.pending.remove(&(peer, message_id)) {
303 Some(token) => token,
304 None => self
305 .sent
306 .iter()
307 .find(|s| s.peer == peer && s.message_id == message_id)?
308 .token
309 .clone(),
310 };
311 let observer = self
312 .list
313 .iter()
314 .find(|e| e.observer.peer == peer && e.observer.token == token)
315 .map(|e| e.observer.clone())?;
316 self.deregister(peer, &token);
317 Some(observer)
318 }
319}