feat(server): handle client close
Release the session a client close names. A close is bound to a session only when the token matches and the datagram arrived from that session's exact endpoint, so holding a token is not by itself authority to tear the session down: a close from a foreign source port, address, family or IPv6 scope leaves the session live, and one close cannot take down a sibling session the same peer opened separately. A token that is unknown, already closed or zero matches nothing and leaves the table untouched; zero is reserved for no-test replies and never issued. Nothing is sent either way. Protocol version 1 defines no acknowledgement for a client close, so a successful close returns the same `Ok(None)` as a rejected one and a delivered close is indistinguishable to the client from a lost one. A standalone `Reply|Close` datagram is tolerated by clients but has no demonstrated use, so none is encoded. Authentication still runs before the session is looked up. That keeps a bad MAC on a live token indistinguishable from an unknown token, and means a close that fails authentication — missing, wrongly keyed, corrupted, or unexpected on a server with no key — cannot remove a session. Trailing bytes after the token stay acceptable: the structural decoder already tolerates them and the server does not re-parse the request. The session table remains the only record of how full the server is, so a close frees capacity immediately and a refused open can succeed once one is released. Close draws no token and touches no other state; the endpoint lookup borrows the table only until the comparison is made, so the removal needs no clone. Echo remains ignored. The test that pinned close as a no-op is replaced by `tests/close.rs`, which covers removal, silence, repeated close, echo after close, endpoint binding, unknown/zero/stale tokens, authentication failure, trailing bytes, sibling sessions and capacity reuse; `unsupported.rs` keeps echo and structurally invalid traffic.
This commit is contained in:
8 files changed
+380
-54
No files matched your search
@@ -29,15 +29,9 @@ impl Session {
|
||||
///
|
||||
/// A session is bound to this endpoint, not merely to its address: address
|
||||
/// family, address, UDP source port and — for IPv6 — the scope identifier
|
||||
/// all form part of its identity. Echo and close processing, once
|
||||
/// implemented, must require both a token match and an exact endpoint match
|
||||
/// before touching a session.
|
||||
//
|
||||
// Read only by tests until then. The endpoint has to be captured at open
|
||||
// time — it is not recoverable later — so this slice stores state whose
|
||||
// production consumer is the next one, and the tests prove it is stored
|
||||
// exactly.
|
||||
#[allow(dead_code)]
|
||||
/// all form part of its identity. Close processing requires both a token
|
||||
/// match and an exact endpoint match before removing a session, and echo
|
||||
/// processing will require the same.
|
||||
pub(crate) fn peer(&self) -> SocketAddr {
|
||||
self.peer
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user