Skip to main content

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}