musli_web/ws.rs
1//! The server side of the websocket protocol.
2//!
3//! See [`server()`] for how to use with [axum].
4//!
5//! A connection starts life as a [`Connect`], which cannot send anything.
6//! [`Connect::connect`] performs the [negotiation protocol] and hands back the
7//! [`Server`], so by the time there is anything able to write a message the
8//! [`Format`] it will be encoded with has been agreed with the client. A client
9//! which does not negotiate never gets a [`Server`] at all.
10//!
11//! Handlers are implemented via the [`Handler`] trait, which allows returning
12//! various forms of responses dictated through the [`IntoResponse`] trait. This
13//! is primarily implemented for `bool`, where returning `false` indicates that
14//! the given request kind is not supported.
15//!
16//! A handler can also fail a request by returning an error, see
17//! [Errors](#errors) below.
18//!
19//! A connection can carry the lists of several [`define!`] invocations, such
20//! as one shipped by a library beside the application's own. Either one list
21//! [includes] the other and its handler routes the included requests by
22//! matching on their variant, or the handlers of the two lists are combined
23//! with [`Handler::or`], which routes each request to the handler whose list
24//! knows its id. In both cases a clash between the ids of the lists fails to
25//! compile.
26//!
27//! [`define!`]: crate::api::define
28//! [includes]: crate::api::define#including-other-lists
29//!
30//! ```
31//! use musli_web::api::MessageId;
32//! use musli_web::ws;
33//!
34//! mod api {
35//! use musli::{Decode, Encode};
36//! use musli_web::api;
37//!
38//! #[derive(Encode, Decode)]
39//! pub struct HelloRequest<'de> {
40//! pub message: &'de str,
41//! }
42//!
43//! #[derive(Encode, Decode)]
44//! pub struct HelloResponse<'de> {
45//! pub message: &'de str,
46//! }
47//!
48//! #[derive(Encode, Decode)]
49//! pub struct TickEvent<'de> {
50//! pub message: &'de str,
51//! pub tick: u32,
52//! }
53//!
54//! api::define! {
55//! pub type Hello;
56//!
57//! impl Endpoint for Hello {
58//! impl<'de> Request for HelloRequest<'de>;
59//! type Response<'de> = HelloResponse<'de>;
60//! }
61//!
62//! pub type Tick;
63//!
64//! impl Broadcast for Tick {
65//! impl<'de> Event for TickEvent<'de>;
66//! }
67//! }
68//! }
69//!
70//! #[derive(Debug, Clone)]
71//! enum Broadcast {
72//! Tick { tick: u32 },
73//! }
74//!
75//! #[derive(Clone)]
76//! struct MyHandler;
77//!
78//! impl ws::Handler for MyHandler {
79//! type Id = api::Request;
80//! type Response = Option<()>;
81//!
82//! async fn handle(
83//! &self,
84//! id: Self::Id,
85//! incoming: &mut ws::Incoming<'_>,
86//! outgoing: &mut ws::Outgoing<'_>,
87//! ) -> Self::Response {
88//! tracing::info!("Handling: {id:?}");
89//!
90//! match id {
91//! api::Request::Hello => {
92//! let request = incoming.read::<api::HelloRequest<'_>>()?;
93//!
94//! outgoing.write(api::HelloResponse {
95//! message: request.message,
96//! });
97//!
98//! Some(())
99//! }
100//! api::Request::Unknown(id) => {
101//! tracing::info!("Unknown request id: {}", id.get());
102//! None
103//! }
104//! }
105//! }
106//! }
107//! ```
108//!
109//! # Errors
110//!
111//! A handler whose [`Handler::Response`] is a `Result<T, E>` fails the request
112//! it is handling by returning `Err(E)`. What reaches the client depends on
113//! `E`, see [`ResponseError`]:
114//!
115//! * Anything which implements [`fmt::Display`], such as a `String` or an
116//! `anyhow::Error`, is sent as *text*. The client sees the message through
117//! `web::Error::as_server_error`.
118//! * A [`TypedError<E>`] is sent as a *typed error*. The value it wraps is
119//! encoded in the body format of the connection, just like a response, so
120//! the client can decode it back into `E` with `web::Error::server_error`
121//! instead of parsing a message. Its [`fmt::Display`] text is sent along as
122//! the message, so code which only looks at the message keeps working.
123//! * An error type which implements [`ResponseError`] by hand decides for each
124//! error whether it is typed, which keeps internal failures out of what the
125//! client is told. See [`ResponseError`] for an example.
126//!
127//! Putting the error type in the API crate shared by the server and the client
128//! keeps the two in agreement:
129//!
130//! ```
131//! use core::fmt;
132//!
133//! use musli_web::ws::{self, TypedError};
134//!
135//! mod api {
136//! use musli::{Decode, Encode};
137//! use musli_web::api;
138//!
139//! /// Why the server refused a request.
140//! #[derive(Debug, PartialEq, Encode, Decode)]
141//! pub enum ServerError {
142//! NotFound,
143//! Forbidden { reason: String },
144//! }
145//!
146//! #[derive(Encode, Decode)]
147//! pub struct DeleteRequest {
148//! pub id: u32,
149//! }
150//!
151//! #[derive(Encode, Decode)]
152//! pub struct DeleteResponse;
153//!
154//! api::define! {
155//! pub type Delete;
156//!
157//! impl Endpoint for Delete {
158//! impl Request for DeleteRequest;
159//! type Response<'de> = DeleteResponse;
160//! }
161//! }
162//! }
163//!
164//! impl fmt::Display for api::ServerError {
165//! fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166//! match self {
167//! Self::NotFound => write!(f, "Not found"),
168//! Self::Forbidden { reason } => write!(f, "Forbidden: {reason}"),
169//! }
170//! }
171//! }
172//!
173//! #[derive(Clone)]
174//! struct MyHandler;
175//!
176//! impl ws::Handler for MyHandler {
177//! type Id = api::Request;
178//! type Response = Result<bool, TypedError<api::ServerError>>;
179//!
180//! async fn handle(
181//! &self,
182//! id: Self::Id,
183//! incoming: &mut ws::Incoming<'_>,
184//! outgoing: &mut ws::Outgoing<'_>,
185//! ) -> Self::Response {
186//! match id {
187//! api::Request::Delete => {
188//! let Some(request) = incoming.read::<api::DeleteRequest>() else {
189//! return Ok(false);
190//! };
191//!
192//! if request.id == 0 {
193//! // `?` converts into a `TypedError` too.
194//! return Err(TypedError(api::ServerError::Forbidden {
195//! reason: String::from("The root cannot be deleted"),
196//! }));
197//! }
198//!
199//! outgoing.write(api::DeleteResponse);
200//! Ok(true)
201//! }
202//! api::Request::Unknown(..) => Ok(false),
203//! }
204//! }
205//! }
206//! ```
207//!
208//! On the client, the error such a request fails with decodes back with
209//! `error.server_error::<api::ServerError>()`, which returns `Ok(None)` for an
210//! error which is not typed. See `web::Error::server_error` and
211//! `client::Error::server_error`.
212//!
213//! Errors the server produces on its own, such as for a request no handler
214//! supports or one which could not be decoded, are always text, so a client
215//! should be prepared for a server error which carries no payload.
216//!
217//! # Broadcast origin
218//!
219//! A broadcast can say which channel caused it. When a request over a
220//! channel changes something every client shows, write the resulting
221//! broadcast with [`Server::broadcast_from`] and the [`Incoming::channel`] of
222//! that request as its origin. The client reads the origin back as the
223//! channel of the broadcast packet, so the page which made the change can
224//! recognize its own echo with `web::Packet::is_from` and skip it, while every
225//! other page applies it. There is no need to carry the origin in the body of
226//! the event.
227//!
228//! This relies on channel ids being unique across every connection, since
229//! the broadcast is written by the [`Server`] of each connection and not only
230//! the one the request came in over. That is the default, see
231//! [`ChannelAllocator`].
232//!
233//! ```
234//! use musli_web::api::ChannelId;
235//! use musli_web::ws;
236//! use tokio::sync::broadcast::Sender;
237//!
238//! mod api {
239//! use musli::{Decode, Encode};
240//! use musli_web::api;
241//!
242//! #[derive(Encode, Decode)]
243//! pub struct RenameRequest<'de> {
244//! pub name: &'de str,
245//! }
246//!
247//! #[derive(Encode, Decode)]
248//! pub struct RenameResponse;
249//!
250//! #[derive(Encode, Decode)]
251//! pub struct RenamedEvent<'de> {
252//! pub name: &'de str,
253//! }
254//!
255//! api::define! {
256//! pub type Rename;
257//!
258//! impl Endpoint for Rename {
259//! impl<'de> Request for RenameRequest<'de>;
260//! type Response<'de> = RenameResponse;
261//! }
262//!
263//! pub type Renamed;
264//!
265//! impl Broadcast for Renamed {
266//! impl<'de> Event for RenamedEvent<'de>;
267//! }
268//! }
269//! }
270//!
271//! /// A change which every connection forwards to its client.
272//! #[derive(Clone)]
273//! struct Change {
274//! name: String,
275//! /// The channel whose request made the change.
276//! origin: ChannelId,
277//! }
278//!
279//! #[derive(Clone)]
280//! struct MyHandler {
281//! changes: Sender<Change>,
282//! }
283//!
284//! impl ws::Handler for MyHandler {
285//! type Id = api::Request;
286//! type Response = Option<()>;
287//!
288//! async fn handle(
289//! &self,
290//! id: Self::Id,
291//! incoming: &mut ws::Incoming<'_>,
292//! outgoing: &mut ws::Outgoing<'_>,
293//! ) -> Self::Response {
294//! match id {
295//! api::Request::Rename => {
296//! let request = incoming.read::<api::RenameRequest<'_>>()?;
297//!
298//! _ = self.changes.send(Change {
299//! name: request.name.to_owned(),
300//! origin: incoming.channel(),
301//! });
302//!
303//! outgoing.write(api::RenameResponse);
304//! Some(())
305//! }
306//! api::Request::Unknown(..) => None,
307//! }
308//! }
309//! }
310//!
311//! /// Called by the connection loop of every connection for each change it
312//! /// receives from the shared sender.
313//! fn forward<S>(server: &mut ws::Server<S, MyHandler>, change: &Change) -> Result<(), ws::Error>
314//! where
315//! S: ws::ServerImpl,
316//! ws::Error: From<S::Error>,
317//! {
318//! server.broadcast_from(api::RenamedEvent { name: &change.name }, change.origin)
319//! }
320//! ```
321//!
322//! The client which sent the request compares the origin to its own channel:
323//!
324//! ```text
325//! if packet.is_from(channel.id()) {
326//! // Our own change, which is already shown.
327//! return;
328//! }
329//! ```
330//!
331//! `is_from` is never true for [`ChannelId::NONE`], so a page which has not
332//! opened its channel yet, or a broadcast written with [`Server::broadcast`],
333//! never counts as an echo.
334//!
335//! [`server()`]: crate::axum08::server
336//! [axum]: <https://docs.rs/axum>
337//! [negotiation protocol]: crate::api#negotiating-the-format
338
339use core::convert::Infallible;
340use core::fmt::{self, Write};
341use core::future::Future;
342use core::mem;
343use core::num::NonZeroU16;
344use core::pin::Pin;
345use core::task::{Context, Poll};
346
347use alloc::boxed::Box;
348use alloc::collections::{BTreeSet, VecDeque};
349use alloc::string::String;
350use alloc::sync::Arc;
351use alloc::vec::Vec;
352
353use std::sync::{LazyLock, Mutex, MutexGuard, PoisonError};
354
355use bytes::Bytes;
356use rand::prelude::*;
357use rand::rngs::SmallRng;
358use tokio::task::JoinSet;
359use tokio::time::{Duration, Instant, Sleep};
360
361use crate::Buf;
362use crate::api::{
363 Broadcast, ChannelId, DecodeBody, EncodeBody, ErrorMessage, Event, Format, Id, IdSet,
364 MessageId, Mode, RequestHeader, ResponseHeader, VERSION,
365};
366use crate::buf::{BufPool, InvalidFrame};
367use crate::format;
368
369const MAX_CAPACITY: usize = 1048576;
370const DEFAULT_MAX_IN_FLIGHT: usize = 128;
371const DEFAULT_MAX_OUTBOUND: usize = 8 * 1048576;
372/// The default number of channels one client may hold open at once.
373const DEFAULT_MAX_CHANNELS: usize = 1024;
374const CLOSE_NORMAL: u16 = 1000;
375const CLOSE_PROTOCOL_ERROR: u16 = 1002;
376const CLOSE_POLICY_VIOLATION: u16 = 1008;
377const CLOSE_TIMEOUT: Duration = Duration::from_secs(30);
378const PING_TIMEOUT: Duration = Duration::from_secs(10);
379const DEFAULT_SEED: u64 = 0xdeadbeef;
380
381/// A websocket message.
382#[derive(Debug)]
383pub(crate) enum Message {
384 /// A text message.
385 Text(Bytes),
386 /// A binary message.
387 Binary(Bytes),
388 /// A ping message.
389 Ping(Bytes),
390 /// A pong message.
391 Pong(Bytes),
392 /// A close message.
393 Close,
394}
395
396pub(crate) mod socket_sealed {
397 pub trait Sealed {}
398}
399
400pub(crate) trait SocketImpl
401where
402 Self: self::socket_sealed::Sealed,
403{
404 #[doc(hidden)]
405 type Message;
406
407 #[doc(hidden)]
408 type Error: fmt::Debug;
409
410 #[doc(hidden)]
411 fn poll_next(
412 self: Pin<&mut Self>,
413 ctx: &mut Context<'_>,
414 ) -> Poll<Option<Result<Message, Self::Error>>>;
415
416 #[doc(hidden)]
417 fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>;
418
419 #[doc(hidden)]
420 fn start_send(self: Pin<&mut Self>, item: Self::Message) -> Result<(), Self::Error>;
421
422 #[doc(hidden)]
423 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>;
424}
425
426pub(crate) mod server_sealed {
427 pub trait Sealed {}
428}
429
430/// The details of how a [`Server`] is implemented.
431///
432/// See [`AxumServer`] for an example.
433///
434/// [`AxumServer`]: crate::axum08::AxumServer
435pub trait ServerImpl
436where
437 Self: self::server_sealed::Sealed,
438{
439 #[doc(hidden)]
440 type Error: fmt::Debug;
441
442 #[doc(hidden)]
443 type Message;
444
445 #[doc(hidden)]
446 #[allow(private_bounds)]
447 type Socket: SocketImpl<Message = Self::Message, Error = Self::Error>;
448
449 #[doc(hidden)]
450 fn ping(data: Bytes) -> Self::Message;
451
452 #[doc(hidden)]
453 fn pong(data: Bytes) -> Self::Message;
454
455 #[doc(hidden)]
456 fn binary(data: &[u8]) -> Self::Message;
457
458 #[doc(hidden)]
459 fn text(data: &[u8]) -> Self::Message;
460
461 #[doc(hidden)]
462 fn close(code: u16, reason: &str) -> Self::Message;
463}
464
465#[derive(Debug)]
466enum ErrorKind {
467 #[cfg(feature = "axum-core05")]
468 AxumCore05 {
469 error: axum_core05::Error,
470 },
471 FormatError,
472 InvalidFrame {
473 error: InvalidFrame,
474 },
475 Incoming {
476 error: format::Error,
477 },
478 Outgoing {
479 error: format::Error,
480 },
481 EncodeBroadcastHeader {
482 error: format::Error,
483 },
484 EncodeBroadcast {
485 error: format::Error,
486 },
487 EncodeConnectHeader {
488 error: format::Error,
489 },
490 ErrorMessageHeader {
491 error: format::Error,
492 },
493 ErrorMessage {
494 error: format::Error,
495 },
496 EncodeErrorPayload {
497 error: format::Error,
498 },
499 OutOfBounds {
500 offset: usize,
501 len: usize,
502 },
503 /// The connection went away before the format had been negotiated.
504 NotNegotiated,
505 /// The client sent a message other than a negotiation as its first message.
506 ExpectedNegotiate {
507 id: u16,
508 },
509 /// The client sent a malformed envelope during negotiation.
510 NegotiateHeader {
511 error: format::Error,
512 },
513 /// The client wrote a header this build does not know about, which means it
514 /// is speaking a protocol this server does not have.
515 UnknownHeader {
516 error: format::Error,
517 },
518 /// The client stated a protocol version this server does not speak.
519 UnsupportedVersion {
520 error: format::Error,
521 },
522 /// The client stated an application version other than the one this
523 /// server states, see [`Connect::app_version`].
524 Incompatible {
525 server: u32,
526 client: u32,
527 },
528}
529
530/// The error produced by the server side of the websocket protocol
531#[derive(Debug)]
532pub struct Error {
533 kind: ErrorKind,
534}
535
536impl Error {
537 #[inline]
538 const fn new(kind: ErrorKind) -> Self {
539 Self { kind }
540 }
541
542 pub(crate) fn incoming(error: format::Error) -> Self {
543 Self::new(ErrorKind::Incoming { error })
544 }
545
546 pub(crate) fn outgoing(error: format::Error) -> Self {
547 Self::new(ErrorKind::Outgoing { error })
548 }
549
550 pub(crate) fn encode_broadcast_header(error: format::Error) -> Self {
551 Self::new(ErrorKind::EncodeBroadcastHeader { error })
552 }
553
554 pub(crate) fn encode_broadcast(error: format::Error) -> Self {
555 Self::new(ErrorKind::EncodeBroadcast { error })
556 }
557
558 pub(crate) fn encode_connect_header(error: format::Error) -> Self {
559 Self::new(ErrorKind::EncodeConnectHeader { error })
560 }
561
562 pub(crate) fn encode_error_message_header(error: format::Error) -> Self {
563 Self::new(ErrorKind::ErrorMessageHeader { error })
564 }
565
566 pub(crate) fn encode_error_message(error: format::Error) -> Self {
567 Self::new(ErrorKind::ErrorMessage { error })
568 }
569
570 /// Test if the connection was refused because the client states an
571 /// application version other than the one this server states.
572 ///
573 /// This is what [`Connect::connect`] fails with for a client built against
574 /// a different version of the application's API, see
575 /// [`Connect::app_version`]. It is the client which is out of date (or the
576 /// server), not the connection which is broken, so it is usually worth
577 /// logging at a lower level than other errors.
578 #[inline]
579 pub fn is_incompatible(&self) -> bool {
580 matches!(self.kind, ErrorKind::Incompatible { .. })
581 }
582}
583
584impl fmt::Display for Error {
585 #[inline]
586 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
587 match &self.kind {
588 #[cfg(feature = "axum-core05")]
589 ErrorKind::AxumCore05 { .. } => write!(f, "Error in axum-core"),
590 ErrorKind::FormatError => write!(f, "Error formatting error response"),
591 ErrorKind::InvalidFrame { error } => error.fmt(f),
592 ErrorKind::Incoming { .. } => {
593 write!(f, "Encoding error when decoding incoming message")
594 }
595 ErrorKind::Outgoing { .. } => {
596 write!(f, "Encoding error when encoding outgoing message")
597 }
598 ErrorKind::EncodeBroadcastHeader { .. } => {
599 write!(f, "Encoding error when encoding broadcast header")
600 }
601 ErrorKind::EncodeBroadcast { .. } => {
602 write!(f, "Encoding error when broadcasting message")
603 }
604 ErrorKind::EncodeConnectHeader { .. } => {
605 write!(f, "Encoding error when encoding connect header")
606 }
607 ErrorKind::ErrorMessageHeader { .. } => {
608 write!(f, "Encoding error when encoding error message header")
609 }
610 ErrorKind::ErrorMessage { .. } => {
611 write!(f, "Encoding error when encoding error message")
612 }
613 ErrorKind::EncodeErrorPayload { .. } => {
614 write!(f, "Encoding error when encoding typed error")
615 }
616 ErrorKind::OutOfBounds { offset, len } => {
617 write!(
618 f,
619 "Error when reading message: offset {} is out of bounds for length {}",
620 offset, len
621 )
622 }
623 ErrorKind::NotNegotiated => {
624 write!(f, "Connection closed before the format was negotiated")
625 }
626 ErrorKind::ExpectedNegotiate { id } => {
627 write!(
628 f,
629 "Expected a negotiation as the first message, but got message id {id}"
630 )
631 }
632 ErrorKind::NegotiateHeader { .. } => {
633 write!(f, "Encoding error when decoding negotiation header")
634 }
635 ErrorKind::UnknownHeader { error } => {
636 write!(f, "Client sent a header this server does not know: {error}")
637 }
638 ErrorKind::UnsupportedVersion { error } => {
639 write!(f, "Client speaks a different protocol: {error}")
640 }
641 ErrorKind::Incompatible { server, client } => {
642 write!(
643 f,
644 "Client states application version {client}, this server states {server}"
645 )
646 }
647 }
648 }
649}
650
651impl core::error::Error for Error {
652 #[inline]
653 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
654 match &self.kind {
655 #[cfg(feature = "axum-core05")]
656 ErrorKind::AxumCore05 { error } => Some(error),
657 ErrorKind::Incoming { error } => Some(error),
658 ErrorKind::Outgoing { error } => Some(error),
659 ErrorKind::EncodeBroadcastHeader { error } => Some(error),
660 ErrorKind::EncodeBroadcast { error } => Some(error),
661 ErrorKind::EncodeConnectHeader { error } => Some(error),
662 ErrorKind::ErrorMessageHeader { error } => Some(error),
663 ErrorKind::ErrorMessage { error } => Some(error),
664 ErrorKind::EncodeErrorPayload { error } => Some(error),
665 ErrorKind::NegotiateHeader { error } => Some(error),
666 ErrorKind::UnknownHeader { error } => Some(error),
667 ErrorKind::UnsupportedVersion { error } => Some(error),
668 _ => None,
669 }
670 }
671}
672
673#[cfg(feature = "axum-core05")]
674impl From<axum_core05::Error> for Error {
675 #[inline]
676 fn from(error: axum_core05::Error) -> Self {
677 Self::new(ErrorKind::AxumCore05 { error })
678 }
679}
680
681impl From<ErrorKind> for Error {
682 #[inline]
683 fn from(kind: ErrorKind) -> Self {
684 Self::new(kind)
685 }
686}
687
688impl From<InvalidFrame> for Error {
689 #[inline]
690 fn from(error: InvalidFrame) -> Self {
691 Self::new(ErrorKind::InvalidFrame { error })
692 }
693}
694
695type Result<T, E = Error> = core::result::Result<T, E>;
696
697/// The response meta from handling a request.
698pub struct Response {
699 handled: bool,
700}
701
702/// An error a handler can fail a request with.
703///
704/// This decides what the client receives, see [Errors](self#errors). It is
705/// implemented for:
706///
707/// * Every type which implements [`fmt::Display`], which is sent as text. The
708/// client sees it through `web::Error::as_server_error`.
709/// * [`TypedError<E>`], which is sent as a typed error. The client can decode
710/// it back into `E` with `web::Error::server_error`.
711///
712/// It can also be implemented by hand for an error type which does not
713/// implement [`fmt::Display`], to decide per error whether it is typed. This is
714/// useful to keep internal failures out of the typed error the client sees.
715///
716/// # Examples
717///
718/// ```
719/// use core::fmt;
720///
721/// use musli::{Decode, Encode};
722/// use musli_web::ws::{self, ErrorPayload, ResponseError};
723///
724/// /// The error the client is told about, shared through the API crate.
725/// #[derive(Debug, Encode, Decode)]
726/// pub enum AuthError {
727/// Expired,
728/// Denied,
729/// }
730///
731/// /// What the handler fails with.
732/// enum HandlerError {
733/// Auth(AuthError),
734/// Internal(String),
735/// }
736///
737/// impl ResponseError for HandlerError {
738/// fn fmt_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
739/// match self {
740/// HandlerError::Auth(AuthError::Expired) => write!(f, "Session expired"),
741/// HandlerError::Auth(AuthError::Denied) => write!(f, "Access denied"),
742/// // NB: The details stay on the server.
743/// HandlerError::Internal(..) => write!(f, "Internal error"),
744/// }
745/// }
746///
747/// fn encode_payload(&self, payload: ErrorPayload<'_>) -> Result<(), ws::Error> {
748/// match self {
749/// HandlerError::Auth(error) => payload.encode(error),
750/// // Not encoding anything sends the message alone.
751/// HandlerError::Internal(..) => Ok(()),
752/// }
753/// }
754/// }
755/// ```
756pub trait ResponseError
757where
758 Self: 'static + Send,
759{
760 /// Write the human readable message of the error.
761 ///
762 /// This is sent for every error, typed or not. The client shows it in the
763 /// [`fmt::Display`] of its error and returns it from
764 /// `web::Error::as_server_error`.
765 fn fmt_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
766
767 /// Encode the typed payload of the error, if it has one, by calling
768 /// [`ErrorPayload::encode`].
769 ///
770 /// Returning without encoding anything, which is what the default
771 /// implementation does, sends the message alone. If this errors the
772 /// message is sent alone as well, since the client is better served by
773 /// the message than by no response at all.
774 #[inline]
775 fn encode_payload(&self, payload: ErrorPayload<'_>) -> Result<(), Error> {
776 _ = payload;
777 Ok(())
778 }
779}
780
781impl<E> ResponseError for E
782where
783 E: 'static + Send + fmt::Display,
784{
785 #[inline]
786 fn fmt_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
787 fmt::Display::fmt(self, f)
788 }
789}
790
791impl<E> ResponseError for TypedError<E>
792where
793 E: 'static + Send + fmt::Display + EncodeBody,
794{
795 #[inline]
796 fn fmt_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
797 fmt::Display::fmt(&self.0, f)
798 }
799
800 #[inline]
801 fn encode_payload(&self, payload: ErrorPayload<'_>) -> Result<(), Error> {
802 payload.encode(&self.0)
803 }
804}
805
806/// Where [`ResponseError::encode_payload`] writes the typed payload of an
807/// error.
808pub struct ErrorPayload<'a> {
809 format: Format,
810 out: &'a mut Vec<u8>,
811 encoded: &'a mut bool,
812}
813
814impl ErrorPayload<'_> {
815 /// The format the payload is encoded with, which is the format of the
816 /// connection.
817 #[inline]
818 pub fn format(&self) -> Format {
819 self.format
820 }
821
822 /// Encode `value` as the typed payload of the error.
823 ///
824 /// The client decodes it with `web::Error::server_error`.
825 ///
826 /// # Errors
827 ///
828 /// Errors if `value` cannot be encoded.
829 pub fn encode<T>(self, value: &T) -> Result<(), Error>
830 where
831 T: ?Sized + EncodeBody,
832 {
833 self.out.clear();
834
835 if let Err(error) = self.format.encode(self.out, value) {
836 self.out.clear();
837 return Err(Error::new(ErrorKind::EncodeErrorPayload { error }));
838 }
839
840 *self.encoded = true;
841 Ok(())
842 }
843}
844
845/// Display adapter for the message of a [`ResponseError`].
846struct ErrorMessageDisplay<'a, E>(&'a E)
847where
848 E: ?Sized;
849
850impl<E> fmt::Display for ErrorMessageDisplay<'_, E>
851where
852 E: ?Sized + ResponseError,
853{
854 #[inline]
855 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
856 self.0.fmt_message(f)
857 }
858}
859
860/// A handler error which reaches the client as a typed value.
861///
862/// The wrapped error is encoded in the body format of the connection, and the
863/// client decodes it back with `web::Error::server_error` (or
864/// `client::Error::server_error`). Its [`fmt::Display`] text is sent along as
865/// the message of the error, which is what a client that does not decode the
866/// payload sees. See [Errors](self#errors) for an example.
867///
868/// If the error cannot be encoded the client receives the message alone, as
869/// if it was a plain text error.
870///
871/// This deliberately does not implement [`fmt::Display`] itself, since that
872/// would make it a text error. Use [`TypedError::get`] or the public field to
873/// get at the error.
874///
875/// # Examples
876///
877/// ```
878/// use musli_web::ws::TypedError;
879///
880/// fn check(value: u32) -> Result<u32, TypedError<String>> {
881/// if value == 0 {
882/// // Converted with `From` by the question mark operator.
883/// Err::<(), _>(String::from("Zero is not allowed"))?;
884/// }
885///
886/// Ok(value)
887/// }
888///
889/// let error = check(0).unwrap_err();
890/// assert_eq!(error.get(), "Zero is not allowed");
891/// ```
892#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
893pub struct TypedError<E>(pub E);
894
895impl<E> TypedError<E> {
896 /// Wrap an error.
897 ///
898 /// # Examples
899 ///
900 /// ```
901 /// use musli_web::ws::TypedError;
902 ///
903 /// let error = TypedError::new(42u32);
904 /// assert_eq!(error.into_inner(), 42);
905 /// ```
906 #[inline]
907 pub const fn new(error: E) -> Self {
908 Self(error)
909 }
910
911 /// Get a reference to the wrapped error.
912 #[inline]
913 pub const fn get(&self) -> &E {
914 &self.0
915 }
916
917 /// Unwrap the error.
918 #[inline]
919 pub fn into_inner(self) -> E {
920 self.0
921 }
922}
923
924impl<E> From<E> for TypedError<E> {
925 #[inline]
926 fn from(error: E) -> Self {
927 Self(error)
928 }
929}
930
931/// Trait governing how something can be converted into a response.
932pub trait IntoResponse
933where
934 Self: 'static + Send,
935{
936 /// The error variant being produced, see [`ResponseError`].
937 type Error: ResponseError;
938
939 /// Convert self into a response.
940 fn into_response(self) -> Result<Response, Self::Error>;
941}
942
943/// Implement [`IntoResponse`] for unit types `()`.
944///
945/// This indicates that the request has been handled.
946impl IntoResponse for () {
947 type Error = Infallible;
948
949 #[inline]
950 fn into_response(self) -> Result<Response, Self::Error> {
951 Ok(Response { handled: true })
952 }
953}
954
955/// Implement [`IntoResponse`] for `bool`.
956///
957/// On `true`, this means that the request was supported `false` means that it
958/// wasn't.
959impl IntoResponse for bool {
960 type Error = Infallible;
961
962 #[inline]
963 fn into_response(self) -> Result<Response, Self::Error> {
964 Ok(Response { handled: self })
965 }
966}
967
968/// Implement [`IntoResponse`] for [`Result`] types.
969///
970/// The [`Err`] variant fails the request, and is sent to the client as
971/// described by [`ResponseError`]: anything which implements [`fmt::Display`]
972/// as a text message, and a [`TypedError`] as a typed error.
973///
974/// [`Result`]: core::result::Result
975impl<T, E> IntoResponse for Result<T, E>
976where
977 T: IntoResponse<Error = Infallible>,
978 E: ResponseError,
979{
980 type Error = E;
981
982 #[inline]
983 fn into_response(self) -> Result<Response, E> {
984 match self {
985 Ok(into_response) => match IntoResponse::into_response(into_response) {
986 Ok(response) => Ok(response),
987 Err(error) => match error {},
988 },
989 Err(error) => Err(error),
990 }
991 }
992}
993
994/// Implement [`IntoResponse`] for [`Option`] types.
995///
996/// This will propagate any responses for the interior value if present. If the
997/// value is [`None`] this will be treated as unhandled. This can be useful when
998/// used in combination with [`Incoming::read`] since it returns an [`Option`].
999impl<T> IntoResponse for Option<T>
1000where
1001 T: IntoResponse,
1002{
1003 type Error = T::Error;
1004
1005 #[inline]
1006 fn into_response(self) -> Result<Response, Self::Error> {
1007 match self {
1008 Some(value) => value.into_response(),
1009 None => Ok(Response { handled: false }),
1010 }
1011 }
1012}
1013
1014/// A handler for incoming requests.
1015///
1016/// See [`server()`] for how to use with `axum`.
1017///
1018/// [`server()`]: crate::axum08::server
1019pub trait Handler
1020where
1021 Self: 'static + Send + Clone,
1022{
1023 /// The type of message id used.
1024 type Id: Id;
1025 /// The response type returned by the handler.
1026 type Response: IntoResponse;
1027
1028 /// Indicates that a `channel` has been opened.
1029 ///
1030 /// This indicates that you are communicating with a client that has opened
1031 /// a channel with [`Handle::channel`].
1032 ///
1033 /// After this has been called, you can expected to receive requests from
1034 /// the [`ChannelId`] corresponding to `channel`. The channel id of incoming
1035 /// requests can be inspected with [`Incoming::channel`].
1036 ///
1037 /// [`Handle::channel`]: crate::web::Handle::channel
1038 fn open_channel<'this>(
1039 &'this self,
1040 channel: ChannelId,
1041 ) -> impl Future<Output = ()> + Send + 'this {
1042 async {
1043 _ = channel;
1044 }
1045 }
1046
1047 /// Indicates that a `channel` has been cleanly closed.
1048 ///
1049 /// This indicates that communicating with a client that has opened a
1050 /// channel with [`Handle::channel`] has been cleanly closed, which occurs
1051 /// when the channel is cleanly closed by dropping the last handle to it.
1052 ///
1053 /// [`Handle::channel`]: crate::web::Handle::channel
1054 fn close_channel<'this>(
1055 &'this self,
1056 channel: ChannelId,
1057 ) -> impl Future<Output = ()> + Send + 'this {
1058 async {
1059 _ = channel;
1060 }
1061 }
1062
1063 /// Handle a request.
1064 ///
1065 /// A response which reports the request as handled (such as `()`, `true`
1066 /// or `Ok(())`) must have written a response with [`Outgoing::write`].
1067 /// If it did not, the client is sent an error stating that the handler
1068 /// wrote no response, rather than being left waiting for one.
1069 fn handle<'this>(
1070 &'this self,
1071 id: Self::Id,
1072 incoming: &'this mut Incoming<'_>,
1073 outgoing: &'this mut Outgoing<'_>,
1074 ) -> impl Future<Output = Self::Response> + Send + 'this;
1075
1076 /// Combine this handler with `other`, routing each request to the
1077 /// handler whose list of ids knows it.
1078 ///
1079 /// See [`Or`] for how requests are routed.
1080 #[inline]
1081 fn or<H>(self, other: H) -> Or<Self, H>
1082 where
1083 H: Handler,
1084 {
1085 Or::new(self, other)
1086 }
1087}
1088
1089/// A [`Handler`] which routes each request to one of two handlers, by the ids
1090/// their [`Handler::Id`] types know. Constructed with [`Handler::or`].
1091///
1092/// This is how a library which ships its own [`define!`] list, and a handler
1093/// for it, is carried on the same connection as an application's own list.
1094///
1095/// A request is handled by:
1096///
1097/// * The first handler if its id is in the [`Id::IDS`] of the first handler.
1098/// * Otherwise the second handler if its id is in the [`Id::IDS`] of the
1099/// second handler.
1100/// * Otherwise the first handler, as an unknown id, such as the `Unknown`
1101/// variant of a `Request` enum generated by [`define!`].
1102///
1103/// Both handlers are told about every channel which is opened and closed,
1104/// the first one first.
1105///
1106/// The [`Handler::Id`] of this handler is an [`Either`] of the two, and so is
1107/// its [`Handler::Response`].
1108///
1109/// # Id collisions
1110///
1111/// The two lists may not share an id. This is checked at compile time where
1112/// the handler is constructed, once the code doing so is built: being generic,
1113/// the check is evaluated when the code is compiled to a binary, so `cargo
1114/// check` does not report it. To check it earlier, assert that the [`Id::IDS`]
1115/// of the two lists are disjoint in a `const` item, see [`IdSet`].
1116///
1117/// A handler whose list [includes] the list of the other handler shares every
1118/// one of its ids, so it fails to compile as well. Such a handler instead
1119/// routes the requests of the included list itself, by matching on the
1120/// variant the list was included as.
1121///
1122/// ```compile_fail
1123/// use musli_web::ws::{self, Handler};
1124///
1125/// mod a {
1126/// # use musli::{Decode, Encode};
1127/// # use musli_web::api;
1128/// # #[derive(Encode, Decode)] pub struct HelloRequest;
1129/// api::define! {
1130/// pub type Hello;
1131///
1132/// impl Endpoint for Hello {
1133/// impl Request for HelloRequest;
1134/// type Response<'de> = ();
1135/// }
1136/// }
1137/// }
1138///
1139/// mod b {
1140/// # use musli::{Decode, Encode};
1141/// # use musli_web::api;
1142/// # #[derive(Encode, Decode)] pub struct LoginRequest;
1143/// // Its id is 1, just like `a::Hello`.
1144/// api::define! {
1145/// pub type Login;
1146///
1147/// impl Endpoint for Login {
1148/// impl Request for LoginRequest;
1149/// type Response<'de> = ();
1150/// }
1151/// }
1152/// }
1153///
1154/// # #[derive(Clone)] struct A;
1155/// # impl ws::Handler for A {
1156/// # type Id = a::Request;
1157/// # type Response = bool;
1158/// # async fn handle(&self, _: Self::Id, _: &mut ws::Incoming<'_>, _: &mut ws::Outgoing<'_>) -> bool { false }
1159/// # }
1160/// # #[derive(Clone)] struct B;
1161/// # impl ws::Handler for B {
1162/// # type Id = b::Request;
1163/// # type Response = bool;
1164/// # async fn handle(&self, _: Self::Id, _: &mut ws::Incoming<'_>, _: &mut ws::Outgoing<'_>) -> bool { false }
1165/// # }
1166/// let handler = A.or(B);
1167/// ```
1168///
1169/// [`define!`]: crate::api::define
1170/// [includes]: crate::api::define#including-other-lists
1171///
1172/// # Examples
1173///
1174/// ```
1175/// use musli_web::ws::{self, Handler};
1176///
1177/// /// A library with its own list, which pins its ids to a band which the
1178/// /// application does not use.
1179/// mod auth {
1180/// use musli::{Decode, Encode};
1181/// use musli_web::{api, ws};
1182///
1183/// #[derive(Encode, Decode)]
1184/// pub struct LoginRequest<'de> {
1185/// pub user: &'de str,
1186/// }
1187///
1188/// #[derive(Encode, Decode)]
1189/// pub struct LoginResponse {
1190/// pub ok: bool,
1191/// }
1192///
1193/// api::define! {
1194/// #[musli(id = 32000)]
1195/// pub type Login;
1196///
1197/// impl Endpoint for Login {
1198/// impl<'de> Request for LoginRequest<'de>;
1199/// type Response<'de> = LoginResponse;
1200/// }
1201/// }
1202///
1203/// /// The handler the library ships for its list.
1204/// #[derive(Clone)]
1205/// pub struct AuthHandler;
1206///
1207/// impl ws::Handler for AuthHandler {
1208/// type Id = Request;
1209/// type Response = Option<()>;
1210///
1211/// async fn handle(
1212/// &self,
1213/// id: Self::Id,
1214/// incoming: &mut ws::Incoming<'_>,
1215/// outgoing: &mut ws::Outgoing<'_>,
1216/// ) -> Self::Response {
1217/// match id {
1218/// Request::Login => {
1219/// let request = incoming.read::<LoginRequest<'_>>()?;
1220/// outgoing.write(LoginResponse { ok: request.user == "admin" });
1221/// Some(())
1222/// }
1223/// Request::Unknown(..) => None,
1224/// }
1225/// }
1226/// }
1227/// }
1228///
1229/// mod api {
1230/// use musli::{Decode, Encode};
1231/// use musli_web::api;
1232///
1233/// #[derive(Encode, Decode)]
1234/// pub struct HelloRequest;
1235///
1236/// api::define! {
1237/// pub type Hello;
1238///
1239/// impl Endpoint for Hello {
1240/// impl Request for HelloRequest;
1241/// type Response<'de> = ();
1242/// }
1243/// }
1244/// }
1245///
1246/// #[derive(Clone)]
1247/// struct AppHandler;
1248///
1249/// impl ws::Handler for AppHandler {
1250/// type Id = api::Request;
1251/// type Response = Result<bool, String>;
1252///
1253/// async fn handle(
1254/// &self,
1255/// id: Self::Id,
1256/// incoming: &mut ws::Incoming<'_>,
1257/// outgoing: &mut ws::Outgoing<'_>,
1258/// ) -> Self::Response {
1259/// match id {
1260/// api::Request::Hello => {
1261/// outgoing.write(());
1262/// Ok(true)
1263/// }
1264/// // Ids which neither list knows.
1265/// api::Request::Unknown(..) => Ok(false),
1266/// }
1267/// }
1268/// }
1269///
1270/// let handler = AppHandler.or(auth::AuthHandler);
1271///
1272/// // This is what the server constructs for every request it receives.
1273/// use musli_web::api::Id;
1274///
1275/// assert_eq!(
1276/// <ws::Or<AppHandler, auth::AuthHandler> as Handler>::Id::from_id(auth::Login::ID),
1277/// ws::Either::Second(auth::Request::Login),
1278/// );
1279/// ```
1280///
1281/// With axum, the combined handler is what the server is constructed with:
1282///
1283/// ```no_run
1284/// # mod app {
1285/// # #[derive(musli::Encode, musli::Decode)] pub struct HelloRequest;
1286/// # musli_web::api::define! {
1287/// # pub type Hello;
1288/// # impl Endpoint for Hello { impl Request for HelloRequest; type Response<'de> = (); }
1289/// # }
1290/// # }
1291/// # mod auth {
1292/// # #[derive(musli::Encode, musli::Decode)] pub struct LoginRequest;
1293/// # musli_web::api::define! {
1294/// # #[musli(id = 32000)] pub type Login;
1295/// # impl Endpoint for Login { impl Request for LoginRequest; type Response<'de> = (); }
1296/// # }
1297/// # }
1298/// # #[derive(Clone)] struct AppHandler;
1299/// # impl ws::Handler for AppHandler {
1300/// # type Id = app::Request;
1301/// # type Response = bool;
1302/// # async fn handle(&self, _: Self::Id, _: &mut ws::Incoming<'_>, _: &mut ws::Outgoing<'_>) -> bool { false }
1303/// # }
1304/// # #[derive(Clone)] struct AuthHandler;
1305/// # impl ws::Handler for AuthHandler {
1306/// # type Id = auth::Request;
1307/// # type Response = bool;
1308/// # async fn handle(&self, _: Self::Id, _: &mut ws::Incoming<'_>, _: &mut ws::Outgoing<'_>) -> bool { false }
1309/// # }
1310/// # extern crate axum08 as axum;
1311/// use axum::extract::ws::WebSocket;
1312/// use musli_web::axum08;
1313/// use musli_web::ws::{self, Handler};
1314///
1315/// async fn run(socket: WebSocket) -> Result<(), ws::Error> {
1316/// let mut server = axum08::server(socket, AppHandler.or(AuthHandler))
1317/// .connect()
1318/// .await?;
1319///
1320/// server.run().await
1321/// }
1322/// ```
1323#[derive(Clone)]
1324pub struct Or<A, B> {
1325 first: A,
1326 second: B,
1327}
1328
1329impl<A, B> Or<A, B>
1330where
1331 A: Handler,
1332 B: Handler,
1333{
1334 /// Combine `first` and `second`, see [`Handler::or`].
1335 ///
1336 /// This fails to build if the ids of the two handlers overlap, see [Id
1337 /// collisions](Or#id-collisions).
1338 #[inline]
1339 pub const fn new(first: A, second: B) -> Self {
1340 const {
1341 assert!(
1342 <A::Id as Id>::IDS.is_disjoint(&<B::Id as Id>::IDS),
1343 "The ids of the handlers combined with `ws::Or` overlap"
1344 );
1345 }
1346
1347 Self { first, second }
1348 }
1349
1350 /// Get the first handler.
1351 #[inline]
1352 pub const fn first(&self) -> &A {
1353 &self.first
1354 }
1355
1356 /// Get the second handler.
1357 #[inline]
1358 pub const fn second(&self) -> &B {
1359 &self.second
1360 }
1361}
1362
1363impl<A, B> Handler for Or<A, B>
1364where
1365 A: Handler,
1366 B: Handler,
1367{
1368 type Id = Either<A::Id, B::Id>;
1369 type Response = Either<A::Response, B::Response>;
1370
1371 // NB: Handlers are not `Sync`, so the futures of the inner handlers are
1372 // constructed up front rather than holding on to `&self` across an await.
1373
1374 #[inline]
1375 fn open_channel<'this>(
1376 &'this self,
1377 channel: ChannelId,
1378 ) -> impl Future<Output = ()> + Send + 'this {
1379 let first = self.first.open_channel(channel);
1380 let second = self.second.open_channel(channel);
1381
1382 async move {
1383 first.await;
1384 second.await;
1385 }
1386 }
1387
1388 #[inline]
1389 fn close_channel<'this>(
1390 &'this self,
1391 channel: ChannelId,
1392 ) -> impl Future<Output = ()> + Send + 'this {
1393 let first = self.first.close_channel(channel);
1394 let second = self.second.close_channel(channel);
1395
1396 async move {
1397 first.await;
1398 second.await;
1399 }
1400 }
1401
1402 #[inline]
1403 fn handle<'this>(
1404 &'this self,
1405 id: Self::Id,
1406 incoming: &'this mut Incoming<'_>,
1407 outgoing: &'this mut Outgoing<'_>,
1408 ) -> impl Future<Output = Self::Response> + Send + 'this {
1409 let future = match id {
1410 Either::First(id) => Either::First(self.first.handle(id, incoming, outgoing)),
1411 Either::Second(id) => Either::Second(self.second.handle(id, incoming, outgoing)),
1412 };
1413
1414 async move {
1415 match future {
1416 Either::First(future) => Either::First(future.await),
1417 Either::Second(future) => Either::Second(future.await),
1418 }
1419 }
1420 }
1421}
1422
1423/// One of two values, used by [`Or`] for its ids, responses and errors.
1424///
1425/// As an [`Id`], an id is [`Either::First`] if the first id type knows it,
1426/// [`Either::Second`] if only the second one does, and an unknown id of the
1427/// first id type otherwise, see [`Or`].
1428///
1429/// As an [`IntoResponse`] and a [`ResponseError`] it is whichever of the two
1430/// it holds.
1431#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1432pub enum Either<A, B> {
1433 /// The first value.
1434 First(A),
1435 /// The second value.
1436 Second(B),
1437}
1438
1439impl<A, B> Id for Either<A, B>
1440where
1441 A: Id,
1442 B: Id,
1443{
1444 const IDS: IdSet = IdSet {
1445 __ids: &[],
1446 __includes: &[&A::IDS, &B::IDS],
1447 };
1448
1449 #[inline]
1450 fn id(&self) -> MessageId {
1451 match self {
1452 Either::First(id) => id.id(),
1453 Either::Second(id) => id.id(),
1454 }
1455 }
1456
1457 #[inline]
1458 fn from_id(id: MessageId) -> Self {
1459 match Self::try_from_id(id) {
1460 Some(id) => id,
1461 None => Either::First(A::from_id(id)),
1462 }
1463 }
1464
1465 #[inline]
1466 fn try_from_id(id: MessageId) -> Option<Self> {
1467 if let Some(id) = A::try_from_id(id) {
1468 return Some(Either::First(id));
1469 }
1470
1471 Some(Either::Second(B::try_from_id(id)?))
1472 }
1473
1474 #[doc(hidden)]
1475 fn __do_not_implement_id() {}
1476}
1477
1478impl<A, B> IntoResponse for Either<A, B>
1479where
1480 A: IntoResponse,
1481 B: IntoResponse,
1482{
1483 type Error = Either<A::Error, B::Error>;
1484
1485 #[inline]
1486 fn into_response(self) -> Result<Response, Self::Error> {
1487 match self {
1488 Either::First(response) => response.into_response().map_err(Either::First),
1489 Either::Second(response) => response.into_response().map_err(Either::Second),
1490 }
1491 }
1492}
1493
1494impl<A, B> ResponseError for Either<A, B>
1495where
1496 A: ResponseError,
1497 B: ResponseError,
1498{
1499 #[inline]
1500 fn fmt_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1501 match self {
1502 Either::First(error) => error.fmt_message(f),
1503 Either::Second(error) => error.fmt_message(f),
1504 }
1505 }
1506
1507 #[inline]
1508 fn encode_payload(&self, payload: ErrorPayload<'_>) -> Result<(), Error> {
1509 match self {
1510 Either::First(error) => error.encode_payload(payload),
1511 Either::Second(error) => error.encode_payload(payload),
1512 }
1513 }
1514}
1515
1516struct Pinned<S> {
1517 socket: S,
1518 close_sleep: Sleep,
1519 ping_sleep: Sleep,
1520}
1521
1522impl<S> Pinned<S> {
1523 #[inline]
1524 fn project(self: Pin<&mut Self>) -> (Pin<&mut Sleep>, Pin<&mut Sleep>, Pin<&mut S>) {
1525 unsafe {
1526 let this = self.get_unchecked_mut();
1527 (
1528 Pin::new_unchecked(&mut this.close_sleep),
1529 Pin::new_unchecked(&mut this.ping_sleep),
1530 Pin::new_unchecked(&mut this.socket),
1531 )
1532 }
1533 }
1534}
1535
1536/// The output of a handler task: its result, whether it wrote a response, the
1537/// header of the request it handled, and the buffer it wrote into.
1538type HandlerOutput<H> = (
1539 Result<<H as Handler>::Response, Error>,
1540 bool,
1541 RequestHeader,
1542 Buf,
1543);
1544
1545/// Trait which governs how channel identifiers are allocated with a [`Server`].
1546///
1547/// Every [`Server`] hands the ids it allocates for its client to the
1548/// [`Handler`], and a broadcast names the channel it is sent in. For an id to
1549/// say which connection a channel belongs to it has to be unique among every
1550/// connection the application talks to, so by default every [`Server`] in the
1551/// process allocates from one shared pool, [`Channels::global()`]. Two
1552/// connections never hold the same id at the same time.
1553///
1554/// To scope ids differently, for example to keep the connections of one
1555/// service apart from those of another or to give a test its own ids, pass
1556/// another allocator to [`Connect::with_channel_allocator`]. A
1557/// [`Channels::new()`] is an independent pool which is shared by every clone of
1558/// it.
1559///
1560/// A [`Server`] only frees the ids it allocated itself: when the client closes
1561/// one of its channels, and for every channel still open when the [`Server`]
1562/// is dropped. An id the client names but does not own is ignored, so one
1563/// client cannot release a channel which belongs to another. How many channels
1564/// a client may hold at once is limited by [`Connect::max_channels`].
1565///
1566/// # Examples
1567///
1568/// Giving the connections of one route their own pool of ids:
1569///
1570/// ```
1571/// # extern crate axum08 as axum;
1572/// use axum::extract::ws::WebSocket;
1573/// use musli_web::axum08;
1574/// use musli_web::ws::{self, Channels};
1575///
1576/// # mod api {
1577/// # use musli::{Decode, Encode};
1578/// # use musli_web::api;
1579/// # #[derive(Encode, Decode)]
1580/// # pub struct HelloRequest;
1581/// # #[derive(Encode, Decode)]
1582/// # pub struct HelloResponse;
1583/// # api::define! {
1584/// # pub type Hello;
1585/// # impl Endpoint for Hello {
1586/// # impl Request for HelloRequest;
1587/// # type Response<'de> = HelloResponse;
1588/// # }
1589/// # }
1590/// # }
1591/// # #[derive(Clone)]
1592/// # struct MyHandler;
1593/// # impl ws::Handler for MyHandler {
1594/// # type Id = api::Request;
1595/// # type Response = bool;
1596/// # async fn handle(
1597/// # &self,
1598/// # _: Self::Id,
1599/// # _: &mut ws::Incoming<'_>,
1600/// # _: &mut ws::Outgoing<'_>,
1601/// # ) -> bool {
1602/// # false
1603/// # }
1604/// # }
1605/// async fn connection(socket: WebSocket, channels: Channels) -> Result<(), ws::Error> {
1606/// let mut server = axum08::server(socket, MyHandler)
1607/// .with_channel_allocator(channels)
1608/// .connect()
1609/// .await?;
1610///
1611/// server.run().await
1612/// }
1613///
1614/// // Shared by every connection made with a clone of it, but distinct from
1615/// // the ids of connections which use the default pool.
1616/// let channels = Channels::new();
1617/// # let _ = connection;
1618/// ```
1619pub trait ChannelAllocator {
1620 /// Allocate an id which is not currently allocated, or `None` if every id
1621 /// is in use.
1622 ///
1623 /// Using `0` is equivalent to [`ChannelId::NONE`] so the allocator must
1624 /// never hand out an identifier with this value, since it is equivalent
1625 /// to no channel. A [`Server`] which is handed [`ChannelId::NONE`], or an
1626 /// id it already holds, refuses to open the channel.
1627 fn next(&self) -> Option<ChannelId>;
1628
1629 /// Return an id previously handed out by [`ChannelAllocator::next`] so it
1630 /// can be allocated again.
1631 ///
1632 /// A [`Server`] calls this exactly once for every id it allocated, which
1633 /// can happen while it is being dropped.
1634 fn free(&self, channel: ChannelId);
1635}
1636
1637/// A connection which has not yet completed the [negotiation protocol].
1638///
1639/// This is what [`server()`] hands back, and it is the only way to obtain a
1640/// [`Server`]. Configuration lives here rather than on [`Server`], since every
1641/// setting has to be in place before the first byte goes over the wire.
1642///
1643/// Crucially this type cannot send messages. A [`Server`] — which can — only
1644/// exists once [`Connect::connect`] has resolved, which is precisely the point
1645/// at which the [`Format`] for the connection has been settled. Attempting to
1646/// broadcast before that is a compile error rather than a message the client
1647/// cannot read.
1648///
1649/// [`server()`]: crate::axum08::server
1650/// [negotiation protocol]: crate::api#negotiating-the-format
1651///
1652/// # Examples
1653///
1654/// ```
1655/// # extern crate axum08 as axum;
1656/// # use axum::extract::ws::WebSocket;
1657/// use musli_web::api::Format;
1658/// use musli_web::{axum08, ws};
1659///
1660/// mod api {
1661/// use musli::{Decode, Encode};
1662/// use musli_web::api;
1663///
1664/// #[derive(Encode, Decode)]
1665/// pub struct HelloRequest<'de> {
1666/// pub message: &'de str,
1667/// }
1668///
1669/// #[derive(Encode, Decode)]
1670/// pub struct HelloResponse<'de> {
1671/// pub message: &'de str,
1672/// }
1673///
1674/// api::define! {
1675/// pub type Hello;
1676///
1677/// impl Endpoint for Hello {
1678/// impl<'de> Request for HelloRequest<'de>;
1679/// type Response<'de> = HelloResponse<'de>;
1680/// }
1681/// }
1682/// }
1683///
1684/// #[derive(Clone)]
1685/// struct MyHandler;
1686///
1687/// impl ws::Handler for MyHandler {
1688/// type Id = api::Request;
1689/// type Response = bool;
1690///
1691/// async fn handle(
1692/// &self,
1693/// id: Self::Id,
1694/// incoming: &mut ws::Incoming<'_>,
1695/// outgoing: &mut ws::Outgoing<'_>,
1696/// ) -> bool {
1697/// false
1698/// }
1699/// }
1700///
1701/// # async fn example(socket: WebSocket) -> Result<(), ws::Error> {
1702/// let mut server = axum08::server(socket, MyHandler)
1703/// .with_formats(&[Format::Wire, Format::Json])
1704/// .connect()
1705/// .await?;
1706///
1707/// // Only reachable once the client has negotiated a format.
1708/// server.run().await?;
1709/// # Ok(())
1710/// # }
1711/// ```
1712///
1713/// Skipping the connection step does not compile, since a [`Connect`] has
1714/// nothing to broadcast with:
1715///
1716/// ```compile_fail
1717/// # extern crate axum08 as axum;
1718/// # use axum::extract::ws::WebSocket;
1719/// use musli_web::{axum08, ws};
1720///
1721/// mod api {
1722/// use musli::{Decode, Encode};
1723/// use musli_web::api;
1724///
1725/// #[derive(Encode, Decode)]
1726/// pub struct HelloRequest<'de> {
1727/// pub message: &'de str,
1728/// }
1729///
1730/// #[derive(Encode, Decode)]
1731/// pub struct HelloResponse<'de> {
1732/// pub message: &'de str,
1733/// }
1734///
1735/// #[derive(Encode, Decode)]
1736/// pub struct TickEvent {
1737/// pub tick: u32,
1738/// }
1739///
1740/// api::define! {
1741/// pub type Hello;
1742///
1743/// impl Endpoint for Hello {
1744/// impl<'de> Request for HelloRequest<'de>;
1745/// type Response<'de> = HelloResponse<'de>;
1746/// }
1747///
1748/// pub type Tick;
1749///
1750/// impl Broadcast for Tick {
1751/// impl Event for TickEvent;
1752/// }
1753/// }
1754/// }
1755///
1756/// #[derive(Clone)]
1757/// struct MyHandler;
1758///
1759/// impl ws::Handler for MyHandler {
1760/// type Id = api::Request;
1761/// type Response = bool;
1762///
1763/// async fn handle(
1764/// &self,
1765/// id: Self::Id,
1766/// incoming: &mut ws::Incoming<'_>,
1767/// outgoing: &mut ws::Outgoing<'_>,
1768/// ) -> bool {
1769/// false
1770/// }
1771/// }
1772///
1773/// # async fn example(socket: WebSocket) -> Result<(), ws::Error> {
1774/// let mut server = axum08::server(socket, MyHandler);
1775/// // `Connect` has no `broadcast`, only the `Server` that `connect()` hands
1776/// // back does.
1777/// server.broadcast(api::TickEvent { tick: 1 })?;
1778/// # Ok(())
1779/// # }
1780/// ```
1781pub struct Connect<S, H, C = Channels>
1782where
1783 S: ServerImpl,
1784 H: Handler,
1785{
1786 handler: H,
1787 socket: S::Socket,
1788 channels: C,
1789 seed: u64,
1790 max_capacity: usize,
1791 max_in_flight: usize,
1792 max_outbound: usize,
1793 max_channels: usize,
1794 /// Formats this server is willing to negotiate, or `None` to accept every
1795 /// format it was built with support for.
1796 formats: Option<&'static [Format]>,
1797 /// The application version this server states, or zero for none.
1798 app: u32,
1799}
1800
1801impl<S, H> Connect<S, H, Channels>
1802where
1803 S: ServerImpl,
1804 H: Handler,
1805{
1806 /// Construct a new pending connection with the specified handler.
1807 #[inline]
1808 pub(crate) fn new(socket: S::Socket, handler: H) -> Self {
1809 Self {
1810 handler,
1811 socket,
1812 channels: Channels::global(),
1813 seed: DEFAULT_SEED,
1814 max_capacity: MAX_CAPACITY,
1815 max_in_flight: DEFAULT_MAX_IN_FLIGHT,
1816 max_outbound: DEFAULT_MAX_OUTBOUND,
1817 max_channels: DEFAULT_MAX_CHANNELS,
1818 formats: None,
1819 app: 0,
1820 }
1821 }
1822}
1823
1824impl<S, H, C> Connect<S, H, C>
1825where
1826 S: ServerImpl,
1827 H: Handler,
1828{
1829 /// Associate the specified seed with the connection.
1830 ///
1831 /// This affects the random number generation used for ping messages.
1832 ///
1833 /// By default the seed is a constant value.
1834 #[inline]
1835 pub fn seed(mut self, seed: u64) -> Self {
1836 self.seed = seed;
1837 self
1838 }
1839
1840 /// Allocate the channel ids of this connection from `channels`.
1841 ///
1842 /// By default ids come from [`Channels::global()`], which makes them
1843 /// unique across every connection in the process. Use this to scope them
1844 /// differently, see [`ChannelAllocator`].
1845 #[inline]
1846 pub fn with_channel_allocator<U>(self, channels: U) -> Connect<S, H, U>
1847 where
1848 U: ChannelAllocator,
1849 {
1850 Connect {
1851 handler: self.handler,
1852 socket: self.socket,
1853 channels,
1854 seed: self.seed,
1855 max_capacity: self.max_capacity,
1856 max_in_flight: self.max_in_flight,
1857 max_outbound: self.max_outbound,
1858 max_channels: self.max_channels,
1859 formats: self.formats,
1860 app: self.app,
1861 }
1862 }
1863
1864 /// Get a reference to the handler.
1865 #[inline]
1866 pub fn handler(&self) -> &H {
1867 &self.handler
1868 }
1869
1870 /// Restrict the set of [`Format`]s this server is willing to negotiate.
1871 ///
1872 /// By default every format the crate was built with support for is
1873 /// accepted. A client which asks for a format outside of this set is
1874 /// rejected during the [negotiation protocol] and the connection settles on
1875 /// [`Format::DEFAULT`] instead.
1876 ///
1877 /// Note that this cannot widen the set, a format which was not compiled in
1878 /// is never accepted.
1879 ///
1880 /// [negotiation protocol]: crate::api#negotiating-the-format
1881 #[inline]
1882 pub fn with_formats(mut self, formats: &'static [Format]) -> Self {
1883 self.formats = Some(formats);
1884 self
1885 }
1886
1887 /// Test if this server is willing to negotiate `format`.
1888 #[inline]
1889 pub fn accepts(&self, format: Format) -> bool {
1890 accepts(self.formats, format)
1891 }
1892
1893 /// State the version of the application's API this server speaks.
1894 ///
1895 /// This is a version of *your* protocol, the requests and broadcasts
1896 /// defined with [`api::define!`], as opposed to [`VERSION`] which is the
1897 /// version of the envelope this crate puts around them. Bump it whenever
1898 /// the API changes in a way an older client cannot cope with.
1899 ///
1900 /// The server states it in [`MessageId::SERVER_HELLO`], and a client which
1901 /// was given one too through its own `ServiceBuilder::app_version` compares
1902 /// the two before it negotiates. If they differ the client reports the
1903 /// connection as incompatible instead of opening it, which is what lets a
1904 /// page served by an older build learn that it has to reload. A client
1905 /// which states a different version is also refused here: it gets a close
1906 /// frame and [`Connect::connect`] fails with an error for which
1907 /// [`Error::is_incompatible`] holds.
1908 ///
1909 /// Zero, which is the default, states no version. The check only applies
1910 /// when both peers state one, so a server or a client which does not opt
1911 /// in behaves exactly as if this did not exist. See [application
1912 /// versions].
1913 ///
1914 /// [`api::define!`]: crate::api::define
1915 /// [application versions]: crate::api#application-versions
1916 ///
1917 /// # Examples
1918 ///
1919 /// ```
1920 /// # extern crate axum08 as axum;
1921 /// use axum::extract::ws::WebSocket;
1922 /// use musli_web::axum08;
1923 /// use musli_web::ws;
1924 ///
1925 /// # mod api {
1926 /// # use musli::{Decode, Encode};
1927 /// # use musli_web::api;
1928 /// # #[derive(Encode, Decode)]
1929 /// # pub struct HelloRequest;
1930 /// # #[derive(Encode, Decode)]
1931 /// # pub struct HelloResponse;
1932 /// # api::define! {
1933 /// # pub type Hello;
1934 /// # impl Endpoint for Hello {
1935 /// # impl Request for HelloRequest;
1936 /// # type Response<'de> = HelloResponse;
1937 /// # }
1938 /// # }
1939 /// # }
1940 /// # #[derive(Clone)]
1941 /// # struct MyHandler;
1942 /// # impl ws::Handler for MyHandler {
1943 /// # type Id = api::Request;
1944 /// # type Response = bool;
1945 /// # async fn handle(
1946 /// # &self,
1947 /// # _: Self::Id,
1948 /// # _: &mut ws::Incoming<'_>,
1949 /// # _: &mut ws::Outgoing<'_>,
1950 /// # ) -> bool {
1951 /// # false
1952 /// # }
1953 /// # }
1954 /// /// Bumped whenever the API changes in a way old pages cannot cope with.
1955 /// const APP_VERSION: u32 = 7;
1956 ///
1957 /// async fn connection(socket: WebSocket) -> Result<(), ws::Error> {
1958 /// let server = axum08::server(socket, MyHandler).app_version(APP_VERSION);
1959 ///
1960 /// let mut server = match server.connect().await {
1961 /// Ok(server) => server,
1962 /// // A page from another build, which is told to reload.
1963 /// Err(error) if error.is_incompatible() => return Ok(()),
1964 /// Err(error) => return Err(error),
1965 /// };
1966 ///
1967 /// server.run().await
1968 /// }
1969 /// # let _ = connection;
1970 /// ```
1971 #[inline]
1972 pub fn app_version(mut self, version: u32) -> Self {
1973 self.app = version;
1974 self
1975 }
1976
1977 /// Modify the max allocated capacity of the buffers used for outgoing
1978 /// messages.
1979 ///
1980 /// This is not a hard limit. A message larger than this is still written,
1981 /// but once it has been flushed the allocation is released back down to the
1982 /// specified value rather than being kept for the lifetime of the
1983 /// connection.
1984 ///
1985 /// By default, the capacity is 1 MiB.
1986 #[inline]
1987 pub fn max_capacity(mut self, max_capacity: usize) -> Self {
1988 self.max_capacity = max_capacity;
1989 self
1990 }
1991
1992 /// Modify the max allocated capacity of the outgoing buffers.
1993 ///
1994 /// This is an alias for [`Connect::max_capacity`].
1995 #[inline]
1996 pub fn with_max_capacity(self, max_capacity: usize) -> Self {
1997 self.max_capacity(max_capacity)
1998 }
1999
2000 /// Limit the number of requests which are handled concurrently.
2001 ///
2002 /// Once this many handlers are running, the server stops reading from the
2003 /// socket until one of them has completed. The peer is slowed down rather
2004 /// than disconnected, and nothing it sent is lost.
2005 ///
2006 /// A handler which waits for another request on the same connection to
2007 /// arrive needs this to be large enough for that request to be read.
2008 ///
2009 /// By default, the limit is 128.
2010 ///
2011 /// # Panics
2012 ///
2013 /// Panics if `max_in_flight` is zero, since no request could then ever be
2014 /// handled.
2015 #[inline]
2016 pub fn max_in_flight(mut self, max_in_flight: usize) -> Self {
2017 assert!(max_in_flight > 0, "max_in_flight must be non-zero");
2018 self.max_in_flight = max_in_flight;
2019 self
2020 }
2021
2022 /// Limit the number of bytes queued for the peer before the server stops
2023 /// reading from it.
2024 ///
2025 /// A peer which keeps sending requests but never reads the responses would
2026 /// otherwise make the server buffer an unbounded amount of data. Once this
2027 /// many bytes of responses, errors and broadcasts are waiting to be
2028 /// written, the server stops reading from the socket until the peer has
2029 /// caught up. The peer is slowed down rather than disconnected.
2030 ///
2031 /// This is not a hard limit on memory use. Requests already being handled
2032 /// still queue their responses, and [`Server::broadcast`] is never refused.
2033 ///
2034 /// By default, the limit is 8 MiB.
2035 #[inline]
2036 pub fn max_outbound(mut self, max_outbound: usize) -> Self {
2037 self.max_outbound = max_outbound;
2038 self
2039 }
2040
2041 /// Limit the number of channels the client may hold open at once.
2042 ///
2043 /// Channel ids come from a pool shared with other connections, see
2044 /// [`ChannelAllocator`], so without a limit a single client could take
2045 /// every id there is. A request to open a channel beyond the limit is
2046 /// answered with an error and the connection stays up. Zero refuses every
2047 /// channel.
2048 ///
2049 /// By default, the limit is 1024.
2050 #[inline]
2051 pub fn max_channels(mut self, max_channels: usize) -> Self {
2052 self.max_channels = max_channels;
2053 self
2054 }
2055}
2056
2057impl<S, H, C> Connect<S, H, C>
2058where
2059 S: ServerImpl,
2060 Error: From<S::Error>,
2061 H: Handler,
2062 C: ChannelAllocator,
2063{
2064 /// Perform the [negotiation protocol] and hand back the [`Server`] it
2065 /// produced.
2066 ///
2067 /// This sends [`MessageId::SERVER_HELLO`] and then drives the socket —
2068 /// including keepalive pings — until the client has answered with a
2069 /// [`MessageId::NEGOTIATE`] request and the reply to it has been flushed.
2070 ///
2071 /// Until that has happened the connection has no [`Server`], so there is no
2072 /// way to write a message which the client might not be able to decode.
2073 ///
2074 /// # Errors
2075 ///
2076 /// Errors if the connection goes away before the format has been
2077 /// negotiated, or if the client sends anything other than a negotiation as
2078 /// its first message. Both tear the connection down, since a peer which
2079 /// does not negotiate cannot be talked to safely.
2080 ///
2081 /// [negotiation protocol]: crate::api#negotiating-the-format
2082 pub async fn connect(self) -> Result<Server<S, H, C>, Error> {
2083 let now = Instant::now();
2084
2085 let mut server = Server {
2086 handler: self.handler,
2087 pinned: Box::pin(Pinned {
2088 socket: self.socket,
2089 close_sleep: tokio::time::sleep_until(now + CLOSE_TIMEOUT),
2090 ping_sleep: tokio::time::sleep_until(now + PING_TIMEOUT),
2091 }),
2092 channels: OwnedChannels::new(self.channels, self.max_channels),
2093 closing: false,
2094 pool: BufPool::new(self.max_capacity),
2095 outbound: VecDeque::new(),
2096 outbound_bytes: 0,
2097 max_in_flight: self.max_in_flight,
2098 max_outbound: self.max_outbound,
2099 error: String::new(),
2100 error_payload: Vec::new(),
2101 error_typed: false,
2102 last_ping: None,
2103 rng: SmallRng::seed_from_u64(self.seed),
2104 out: VecDeque::new(),
2105 socket_send: false,
2106 socket_flush: false,
2107 socket_recv: true,
2108 set: JoinSet::new(),
2109 format: Format::DEFAULT,
2110 mode: Mode::DEFAULT,
2111 failure: None,
2112 formats: self.formats,
2113 app: self.app,
2114 };
2115
2116 server.hello()?;
2117 server.negotiate().await?;
2118 Ok(server)
2119 }
2120}
2121
2122/// The error for a peer which went away during negotiation.
2123///
2124/// A failure which was already held explains why better than the peer going
2125/// away does, since it is usually the reason it went away.
2126#[inline]
2127fn gone(failure: Option<Error>) -> Error {
2128 failure.unwrap_or_else(|| Error::new(ErrorKind::NotNegotiated))
2129}
2130
2131/// Test if `formats` is willing to negotiate `format`.
2132#[inline]
2133fn accepts(formats: Option<&'static [Format]>, format: Format) -> bool {
2134 format.is_supported() && formats.is_none_or(|f| f.contains(&format))
2135}
2136
2137/// The server side handle of the websocket protocol.
2138///
2139/// This can only be constructed by completing the [negotiation protocol]
2140/// through [`Connect::connect`], so its mere existence means that the
2141/// [`Format`] used for everything the server originates has been agreed with
2142/// the client.
2143///
2144/// See [`server()`] for how to use with `axum`.
2145///
2146/// [`server()`]: crate::axum08::server
2147/// [negotiation protocol]: crate::api#negotiating-the-format
2148pub struct Server<S, H, C = Channels>
2149where
2150 S: ServerImpl,
2151 H: Handler,
2152 C: ChannelAllocator,
2153{
2154 handler: H,
2155 pinned: Pin<Box<Pinned<S::Socket>>>,
2156 /// The channels the client holds, which are freed when the server is
2157 /// dropped.
2158 channels: OwnedChannels<C>,
2159 closing: bool,
2160 pool: BufPool,
2161 outbound: VecDeque<Buf>,
2162 /// The number of bytes in `outbound` which are yet to be written.
2163 outbound_bytes: usize,
2164 /// Reading stops while this many handlers are running.
2165 max_in_flight: usize,
2166 /// Reading stops while this many bytes are queued in `outbound`.
2167 max_outbound: usize,
2168 /// The message of the error response being sent.
2169 error: String,
2170 /// The typed payload of the error response being sent, which is only
2171 /// valid if `error_typed` is set.
2172 error_payload: Vec<u8>,
2173 /// Whether the error response being sent carries `error_payload`.
2174 error_typed: bool,
2175 last_ping: Option<[u8; 4]>,
2176 rng: SmallRng,
2177 out: VecDeque<S::Message>,
2178 socket_send: bool,
2179 socket_flush: bool,
2180 /// Whether the peer's stream might still produce a message.
2181 ///
2182 /// A stream which has ended reports `Ready(None)` on every poll and
2183 /// registers no waker, so it has to stop being polled once it has ended or
2184 /// it masks every arm of [`Select`] behind it.
2185 socket_recv: bool,
2186 set: JoinSet<HandlerOutput<H>>,
2187 /// The format used for messages the server originates on this connection,
2188 /// as agreed by the [negotiation protocol].
2189 ///
2190 /// [negotiation protocol]: crate::api#negotiating-the-format
2191 format: Format,
2192 /// The mode every frame on this connection is spelled in, as decided by the
2193 /// frame the client negotiated with.
2194 ///
2195 /// [negotiation protocol]: crate::api#negotiating-the-format
2196 mode: Mode,
2197 /// An error which tore the connection down, held until the close frame
2198 /// explaining it has been flushed.
2199 failure: Option<Error>,
2200 /// Formats this server is willing to negotiate, or `None` to accept every
2201 /// format it was built with support for.
2202 formats: Option<&'static [Format]>,
2203 /// The application version this server states, or zero for none.
2204 app: u32,
2205}
2206
2207impl<S, H, C> Server<S, H, C>
2208where
2209 S: ServerImpl,
2210 H: Handler,
2211 C: ChannelAllocator,
2212{
2213 /// Get a reference to the handler.
2214 #[inline]
2215 pub fn handler(&self) -> &H {
2216 &self.handler
2217 }
2218
2219 /// The [`Format`] used for messages this server originates, such as
2220 /// broadcasts.
2221 ///
2222 /// This is fixed for the lifetime of the connection and was agreed with the
2223 /// client by [`Connect::connect`], which is why it is never in doubt here.
2224 #[inline]
2225 pub fn format(&self) -> Format {
2226 self.format
2227 }
2228
2229 /// The [`Mode`] every frame on this connection is spelled in.
2230 ///
2231 /// This is decided by the frame the client negotiated with and is fixed for
2232 /// the lifetime of the connection, see the [wire format].
2233 ///
2234 /// [wire format]: crate::api#wire-format
2235 #[inline]
2236 pub fn mode(&self) -> Mode {
2237 self.mode
2238 }
2239
2240 /// Test if this server is willing to negotiate `format`.
2241 #[inline]
2242 pub fn accepts(&self, format: Format) -> bool {
2243 accepts(self.formats, format)
2244 }
2245}
2246
2247impl<S, H, C> Server<S, H, C>
2248where
2249 S: ServerImpl,
2250 Error: From<S::Error>,
2251 H: Handler,
2252 C: ChannelAllocator,
2253{
2254 /// Drive the socket until the client has negotiated a [`Format`].
2255 ///
2256 /// This is the connection step every peer is forced through, see
2257 /// [`Connect::connect`]. It deliberately understands nothing but
2258 /// [`MessageId::NEGOTIATE`] and the keepalive machinery, so no handler is
2259 /// ever invoked and nothing the user could write is in flight yet.
2260 ///
2261 /// It returns once the format is settled *and* the reply confirming it has
2262 /// been flushed, so the very next thing on the wire can safely use it.
2263 async fn negotiate(&mut self) -> Result<(), Error> {
2264 let mut negotiated = false;
2265 // NB: Held rather than returned immediately so that the close frame
2266 // explaining the violation makes it onto the wire first.
2267 let mut failure = None::<Error>;
2268
2269 loop {
2270 let drained = self.out.is_empty() && !self.socket_flush;
2271
2272 if failure.is_some() && drained {
2273 break;
2274 }
2275
2276 if negotiated && drained && self.outbound.is_empty() {
2277 break;
2278 }
2279
2280 self.handle_send()?;
2281
2282 let result = {
2283 let inner = Select::<S::Socket, H> {
2284 pinned: self.pinned.as_mut(),
2285 wants_socket_recv: self.socket_recv,
2286 wants_socket_send: !self.socket_send,
2287 wants_socket_flush: self.socket_flush,
2288 set: &mut self.set,
2289 };
2290
2291 inner.await
2292 };
2293
2294 match result {
2295 Output::Close => {
2296 return Err(gone(failure));
2297 }
2298 Output::Ping => {
2299 self.handle_ping()?;
2300 }
2301 Output::Recv(message) => {
2302 let Some(message) = message else {
2303 return Err(gone(failure));
2304 };
2305
2306 let message = match message {
2307 Ok(message) => message,
2308 Err(error) => return Err(failure.unwrap_or_else(|| Error::from(error))),
2309 };
2310
2311 match message {
2312 // NB: The frame type is the mode, so the negotiation is
2313 // what tells the server which envelope the rest of the
2314 // connection is spelled in.
2315 Message::Text(bytes) => match self.handle_negotiate(Mode::Text, bytes) {
2316 Ok(()) => negotiated = true,
2317 Err(error) => failure = Some(error),
2318 },
2319 Message::Binary(bytes) => {
2320 match self.handle_negotiate(Mode::Binary, bytes) {
2321 Ok(()) => negotiated = true,
2322 Err(error) => failure = Some(error),
2323 }
2324 }
2325 Message::Ping(payload) => {
2326 self.out.push_back(S::pong(payload));
2327 }
2328 Message::Pong(data) => {
2329 self.handle_pong(data)?;
2330 }
2331 Message::Close => {
2332 return Err(gone(failure));
2333 }
2334 }
2335 }
2336 Output::Send(result) => {
2337 result?;
2338 self.socket_send = true;
2339 }
2340 Output::Flushed(result) => {
2341 result?;
2342 self.socket_flush = false;
2343 }
2344 Output::Handle(..) => {
2345 // NB: No handler can have been spawned yet, since requests
2346 // are only dispatched after negotiation.
2347 }
2348 }
2349 }
2350
2351 match failure {
2352 Some(error) => Err(error),
2353 None => Ok(()),
2354 }
2355 }
2356
2357 /// Process the single message which is legal before a format has been
2358 /// negotiated.
2359 ///
2360 /// Anything else closes the connection, since a peer which skips
2361 /// negotiation cannot be sent broadcasts safely.
2362 fn handle_negotiate(&mut self, mode: Mode, bytes: Bytes) -> Result<(), Error> {
2363 let mut at = 0;
2364
2365 let header: RequestHeader = match format::decode_envelope(mode, &bytes, &mut at) {
2366 Ok(header) => header,
2367 // NB: The version is what says which headers may appear, so a peer
2368 // which does not agree on it is refused before anything else about
2369 // the message is looked at.
2370 Err(error) if error.unsupported_version().is_some() => {
2371 self.out.push_back(S::close(
2372 CLOSE_PROTOCOL_ERROR,
2373 "Unsupported protocol version",
2374 ));
2375 return Err(Error::new(ErrorKind::UnsupportedVersion { error }));
2376 }
2377 Err(error) if error.is_unknown_header() => {
2378 self.out
2379 .push_back(S::close(CLOSE_PROTOCOL_ERROR, "Unknown header"));
2380 return Err(Error::new(ErrorKind::UnknownHeader { error }));
2381 }
2382 Err(error) => {
2383 self.out
2384 .push_back(S::close(CLOSE_PROTOCOL_ERROR, "Invalid request header"));
2385 return Err(Error::new(ErrorKind::NegotiateHeader { error }));
2386 }
2387 };
2388
2389 if MessageId::new(header.id) != Some(MessageId::NEGOTIATE) {
2390 self.out.push_back(S::close(
2391 CLOSE_PROTOCOL_ERROR,
2392 "Expected a negotiation as the first message",
2393 ));
2394
2395 return Err(Error::new(ErrorKind::ExpectedNegotiate { id: header.id }));
2396 }
2397
2398 // NB: Only refused when both sides state a version, so that a peer
2399 // which has not opted in behaves as it always has. A client which
2400 // states a different one was built against another API, and nothing it
2401 // sends can be trusted to mean what this server thinks it does.
2402 if self.app != 0 && header.app != 0 && header.app != self.app {
2403 tracing::debug!(
2404 server = self.app,
2405 client = header.app,
2406 "Incompatible client"
2407 );
2408
2409 self.out.push_back(S::close(
2410 CLOSE_POLICY_VIOLATION,
2411 "Incompatible application version",
2412 ));
2413
2414 return Err(Error::new(ErrorKind::Incompatible {
2415 server: self.app,
2416 client: header.app,
2417 }));
2418 }
2419
2420 // NB: The connection stays up on a rejected format and settles on the
2421 // default instead, which is what the client falls back to. The error
2422 // tells it which formats it could have asked for.
2423 let Some(format) = Format::from_u8(header.format) else {
2424 self.format_error_message(format_args!(
2425 "Unknown format id {}, supported: {}",
2426 header.format,
2427 SupportedFormats(self.formats)
2428 ))?;
2429
2430 self.format = Format::DEFAULT;
2431 return self.send_error(&header);
2432 };
2433
2434 if !self.accepts(format) {
2435 self.format_error_message(format_args!(
2436 "Unsupported format `{format}`, supported: {}",
2437 SupportedFormats(self.formats)
2438 ))?;
2439
2440 tracing::debug!(?format, "Rejected format");
2441 self.format = Format::DEFAULT;
2442 return self.send_error(&header);
2443 }
2444
2445 // NB: A text frame has to be valid UTF-8 in its entirety, so a format
2446 // which is not human readable cannot be carried in one. The connection
2447 // settles on the defaults for both, and the reply which says so goes
2448 // out in the default mode, which is what tells the client.
2449 if !mode.accepts(format) {
2450 self.format_error_message(format_args!(
2451 "Mode `{mode}` cannot carry the `{format}` format"
2452 ))?;
2453
2454 tracing::debug!(?mode, ?format, "Rejected mode");
2455 self.format = Format::DEFAULT;
2456 return self.send_error(&header);
2457 }
2458
2459 tracing::debug!(?mode, ?format, "Negotiated format");
2460 self.format = format;
2461 self.mode = mode;
2462 self.send_negotiated(&header, format)
2463 }
2464
2465 /// Acknowledge a negotiation by echoing the format that was accepted.
2466 fn send_negotiated(&mut self, header: &RequestHeader, format: Format) -> Result<(), Error> {
2467 let mode = self.mode;
2468
2469 let buf = self.pool.with(|buf| {
2470 let mut writer = buf.writer();
2471
2472 let result = writer.envelope(
2473 mode,
2474 &ResponseHeader {
2475 version: VERSION,
2476 serial: header.serial,
2477 broadcast: 0,
2478 error: 0,
2479 format: format.to_u8(),
2480 channel: header.channel,
2481 app: 0,
2482 },
2483 );
2484
2485 result.map_err(Error::encode_connect_header)?;
2486 writer.flush();
2487 Ok::<_, Error>(())
2488 })?;
2489
2490 self.push_outbound(buf);
2491 Ok(())
2492 }
2493
2494 /// Run the server.
2495 ///
2496 /// This must be called to handle buffered outgoing and incoming messages.
2497 pub async fn run(&mut self) -> Result<(), Error> {
2498 loop {
2499 // NB: `socket_flush` is part of this because `start_send` only
2500 // hands a message to the sink. Breaking as soon as the queues are
2501 // empty leaves the close frame in the sink's buffer, never on the
2502 // wire. Waiting is bounded by the deadline `begin_closing` arms.
2503 if self.closing && self.out.is_empty() && self.outbound.is_empty() && !self.socket_flush
2504 {
2505 break;
2506 }
2507
2508 self.handle_send()?;
2509
2510 // NB: Not reading is what pushes back on a peer which sends faster
2511 // than it is answered, or which never reads what it is sent. The
2512 // deadlines, the handlers and the write side are still driven, so
2513 // the connection keeps making progress towards reading again.
2514 let wants_socket_recv = self.socket_recv && !self.is_saturated();
2515
2516 let result = {
2517 let inner = Select::<S::Socket, H> {
2518 pinned: self.pinned.as_mut(),
2519 wants_socket_recv,
2520 wants_socket_send: !self.socket_send,
2521 wants_socket_flush: self.socket_flush,
2522 set: &mut self.set,
2523 };
2524
2525 inner.await
2526 };
2527
2528 match result {
2529 Output::Close => {
2530 // The deadline re-armed by `begin_closing` elapsed, so the
2531 // peer never picked up the close frame which was queued for
2532 // it. Drop the connection rather than queue another one.
2533 if self.closing {
2534 break;
2535 }
2536
2537 self.out
2538 .push_back(S::close(CLOSE_NORMAL, "connection timed out"));
2539 self.begin_closing();
2540 }
2541 Output::Ping => {
2542 self.handle_ping()?;
2543 }
2544 Output::Recv(message) => {
2545 let Some(message) = message else {
2546 // NB: An ended stream is `Ready(None)` on every poll,
2547 // so it has to be fused here or it masks the send and
2548 // flush arms and nothing can ever drain.
2549 self.socket_recv = false;
2550 self.begin_closing();
2551 continue;
2552 };
2553
2554 match message? {
2555 // NB: The mode is fixed by the negotiation, so a frame
2556 // of the other type carries an envelope this connection
2557 // has no way to read.
2558 Message::Text(bytes) => {
2559 if self.mode.is_text() {
2560 self.handle_message(bytes).await?;
2561 } else {
2562 self.out.push_back(S::close(
2563 CLOSE_PROTOCOL_ERROR,
2564 "Unexpected text message",
2565 ));
2566 self.begin_closing();
2567 }
2568 }
2569 Message::Binary(bytes) => {
2570 if self.mode.is_text() {
2571 self.out.push_back(S::close(
2572 CLOSE_PROTOCOL_ERROR,
2573 "Unexpected binary message",
2574 ));
2575 self.begin_closing();
2576 } else {
2577 self.handle_message(bytes).await?;
2578 }
2579 }
2580 Message::Ping(payload) => {
2581 self.out.push_back(S::pong(payload));
2582 }
2583 Message::Pong(data) => {
2584 self.handle_pong(data)?;
2585 }
2586 Message::Close => {
2587 self.begin_closing();
2588 }
2589 }
2590 }
2591 Output::Send(result) => {
2592 if let Err(err) = result {
2593 return Err(Error::from(err));
2594 };
2595
2596 self.socket_send = true;
2597 }
2598 Output::Flushed(result) => {
2599 if let Err(err) = result {
2600 return Err(Error::from(err));
2601 };
2602
2603 self.socket_flush = false;
2604 }
2605 Output::Handle(result, written, header, buf) => {
2606 let err = 'err: {
2607 let res = match result {
2608 Ok(res) => res,
2609 Err(error) => {
2610 self.format_error(error)?;
2611 break 'err true;
2612 }
2613 };
2614
2615 let res = match res.into_response() {
2616 Ok(res) => res,
2617 Err(error) => {
2618 self.format_response_error(&error)?;
2619 break 'err true;
2620 }
2621 };
2622
2623 if !res.handled {
2624 self.format_error_message(format_args!(
2625 "No support for request {}",
2626 header.id
2627 ))?;
2628 break 'err true;
2629 }
2630
2631 // NB: A handled request must be answered, otherwise
2632 // the client waits for a response forever.
2633 if !written {
2634 self.format_error_message(format_args!(
2635 "Handler for request {} wrote no response",
2636 header.id
2637 ))?;
2638 break 'err true;
2639 }
2640
2641 self.push_outbound(buf);
2642 false
2643 };
2644
2645 if err {
2646 self.send_error(&header)?;
2647 }
2648 }
2649 }
2650 }
2651
2652 // NB: Reported only now, so that the close frame explaining it made it
2653 // onto the wire first.
2654 match self.failure.take() {
2655 Some(error) => Err(error),
2656 None => Ok(()),
2657 }
2658 }
2659
2660 /// Write a broadcast message which no channel is credited with.
2661 ///
2662 /// The client sees it with a channel of [`ChannelId::NONE`]. Use
2663 /// [`Server::broadcast_from`] when the broadcast is the result of something
2664 /// a client did over a channel, so that client can tell it apart.
2665 ///
2666 /// Note that the written message is buffered, and will be sent when
2667 /// [`Server::run`] is called.
2668 pub fn broadcast<T>(&mut self, message: T) -> Result<(), Error>
2669 where
2670 T: Event,
2671 {
2672 self.broadcast_from(message, ChannelId::NONE)
2673 }
2674
2675 /// Write a broadcast message which originated from `origin`.
2676 ///
2677 /// The broadcast still reaches every listener of its kind on the client.
2678 /// `origin` only says which channel caused it: it is carried in the
2679 /// broadcast header, and the client reads it back as the channel of the
2680 /// packet, such as `web::Packet::channel`, or tests it with
2681 /// `web::Packet::is_from`. Passing [`ChannelId::NONE`] is the same as
2682 /// [`Server::broadcast`].
2683 ///
2684 /// The typical origin is the [`Incoming::channel`] of the request which
2685 /// made the change being broadcast, so that the page which made it can
2686 /// skip its own echo. The broadcast is usually written by the [`Server`]
2687 /// of every connection, not only the one the request came in over, which
2688 /// works because channel ids are unique across connections by default,
2689 /// see [`ChannelAllocator`]. See [Broadcast origin] for an example.
2690 ///
2691 /// Note that the written message is buffered, and will be sent when
2692 /// [`Server::run`] is called.
2693 ///
2694 /// [Broadcast origin]: self#broadcast-origin
2695 pub fn broadcast_from<T>(&mut self, message: T, origin: ChannelId) -> Result<(), Error>
2696 where
2697 T: Event,
2698 {
2699 tracing::debug!(id = ?<T::Broadcast as Broadcast>::ID, "Broadcast");
2700
2701 let format = self.format;
2702 let mode = self.mode;
2703
2704 let buf = self.pool.with(|buf| {
2705 let mut writer = buf.writer();
2706
2707 writer
2708 .envelope(
2709 mode,
2710 &ResponseHeader {
2711 version: VERSION,
2712 serial: 0,
2713 broadcast: <T::Broadcast as Broadcast>::ID.get(),
2714 error: 0,
2715 format: format.to_u8(),
2716 channel: origin,
2717 app: 0,
2718 },
2719 )
2720 .map_err(Error::encode_broadcast_header)?;
2721
2722 writer
2723 .body(format, &message)
2724 .map_err(Error::encode_broadcast)?;
2725 writer.flush();
2726 Ok::<_, Error>(())
2727 })?;
2728
2729 self.push_outbound(buf);
2730 Ok(())
2731 }
2732
2733 /// Write a broadcast message over a specific connection.
2734 ///
2735 /// Note that the written message is buffered, and will be sent when
2736 /// [`Server::run`] is called.
2737 fn hello(&mut self) -> Result<(), Error> {
2738 tracing::debug!("Hello");
2739
2740 let mut buf = self.pool.get();
2741
2742 let result = (|| {
2743 let mut writer = buf.writer();
2744
2745 writer
2746 // NB: Nothing has been heard from the client yet, so this is
2747 // the one message which cannot be spelled in a negotiated mode.
2748 .envelope(
2749 Mode::DEFAULT,
2750 &ResponseHeader {
2751 version: VERSION,
2752 serial: 0,
2753 broadcast: MessageId::SERVER_HELLO.get(),
2754 error: 0,
2755 // NB: Carries no body, so no format applies.
2756 format: 0,
2757 channel: ChannelId::NONE,
2758 // NB: Stated here, ahead of negotiation, so that a
2759 // client from another build can tell before it has
2760 // agreed to anything.
2761 app: self.app,
2762 },
2763 )
2764 .map_err(Error::encode_broadcast_header)?;
2765
2766 writer.flush();
2767 Ok::<_, Error>(())
2768 })();
2769
2770 if result.is_err() {
2771 self.pool.put(buf);
2772 } else {
2773 self.push_outbound(buf);
2774 }
2775
2776 Ok(())
2777 }
2778
2779 /// Prepare the error response for an error returned by a handler.
2780 fn format_response_error<E>(&mut self, error: &E) -> Result<(), Error>
2781 where
2782 E: ResponseError,
2783 {
2784 self.format_error_message(ErrorMessageDisplay(error))?;
2785
2786 let mut encoded = false;
2787
2788 // NB: Encoded with the connection format, since that is what
2789 // `send_error` writes the rest of the error with.
2790 let payload = ErrorPayload {
2791 format: self.format,
2792 out: &mut self.error_payload,
2793 encoded: &mut encoded,
2794 };
2795
2796 match error.encode_payload(payload) {
2797 Ok(()) => {
2798 self.error_typed = encoded;
2799 }
2800 Err(error) => {
2801 // NB: The message still reaches the client, which is better
2802 // than failing the connection over an error it could not see.
2803 tracing::warn!(
2804 ?error,
2805 "Failed to encode typed error, sending its message only"
2806 );
2807 }
2808 }
2809
2810 Ok(())
2811 }
2812
2813 fn format_error_message(&mut self, error: impl fmt::Display) -> Result<(), Error> {
2814 self.error.clear();
2815 self.error_typed = false;
2816
2817 if write!(self.error, "{error}").is_err() {
2818 self.error.clear();
2819 return Err(Error::new(ErrorKind::FormatError));
2820 }
2821
2822 Ok(())
2823 }
2824
2825 fn format_error(&mut self, error: impl core::error::Error) -> Result<(), Error> {
2826 self.error.clear();
2827 self.error_typed = false;
2828
2829 if write!(self.error, "{error:#}").is_err() {
2830 self.error.clear();
2831 return Err(Error::new(ErrorKind::FormatError));
2832 }
2833
2834 Ok(())
2835 }
2836
2837 #[tracing::instrument(skip(self, bytes))]
2838 async fn handle_message(&mut self, bytes: Bytes) -> Result<(), Error> {
2839 let mut at = 0;
2840
2841 let header: RequestHeader = match format::decode_envelope(self.mode, &bytes, &mut at) {
2842 Ok(header) => header,
2843 // NB: A header this build does not know about means the peer is
2844 // speaking a protocol this one does not have, so the rest of the
2845 // message cannot be acted on even though it parsed. The failure is
2846 // held so the close frame explaining it still reaches the peer.
2847 Err(error) if error.unsupported_version().is_some() => {
2848 tracing::debug!(?error, "Unsupported protocol version");
2849 self.out.push_back(S::close(
2850 CLOSE_PROTOCOL_ERROR,
2851 "Unsupported protocol version",
2852 ));
2853 self.begin_closing();
2854 self.failure
2855 .get_or_insert_with(|| Error::new(ErrorKind::UnsupportedVersion { error }));
2856 return Ok(());
2857 }
2858 Err(error) if error.is_unknown_header() => {
2859 tracing::debug!(?error, "Unknown header");
2860 self.out
2861 .push_back(S::close(CLOSE_PROTOCOL_ERROR, "Unknown header"));
2862 self.begin_closing();
2863 self.failure
2864 .get_or_insert_with(|| Error::new(ErrorKind::UnknownHeader { error }));
2865 return Ok(());
2866 }
2867 Err(error) => {
2868 tracing::debug!(?error, "Invalid request header");
2869 self.out
2870 .push_back(S::close(CLOSE_PROTOCOL_ERROR, "Invalid request header"));
2871 self.begin_closing();
2872 return Ok(());
2873 }
2874 };
2875
2876 let err = 'err: {
2877 let Some(id) = MessageId::new(header.id) else {
2878 self.format_error_message(format_args!("Unsupported message id {}", header.id))?;
2879 break 'err true;
2880 };
2881
2882 match id {
2883 MessageId::CONNECT => {
2884 let channel = match self.channels.open() {
2885 Ok(channel) => channel,
2886 Err(error) => {
2887 self.format_error_message(format_args!("{error}"))?;
2888 break 'err true;
2889 }
2890 };
2891
2892 self.handler.open_channel(channel).await;
2893
2894 let mut buf = self.pool.get();
2895 let mode = self.mode;
2896
2897 let result = (|| {
2898 let mut writer = buf.writer();
2899
2900 let result = writer.envelope(
2901 mode,
2902 &ResponseHeader {
2903 version: VERSION,
2904 serial: header.serial,
2905 broadcast: 0,
2906 error: 0,
2907 format: 0,
2908 channel,
2909 app: 0,
2910 },
2911 );
2912
2913 result.map_err(Error::encode_connect_header)?;
2914 writer.flush();
2915 Ok::<_, Error>(())
2916 })();
2917
2918 if result.is_err() {
2919 self.pool.put(buf);
2920 } else {
2921 self.push_outbound(buf);
2922 }
2923
2924 result?;
2925 break 'err false;
2926 }
2927 MessageId::DISCONNECT => {
2928 // NB: Only a channel this connection opened is closed. An
2929 // id which belongs to some other connection, or to none,
2930 // must not go back into a pool other connections draw
2931 // from.
2932 if self.channels.close(header.channel) {
2933 self.handler.close_channel(header.channel).await;
2934 } else {
2935 tracing::debug!(channel = ?header.channel, "Ignoring close of a channel which is not open");
2936 }
2937
2938 break 'err false;
2939 }
2940 MessageId::NEGOTIATE => {
2941 // NB: The format is settled once and for all by the
2942 // connection step, see `Connect::connect`. Letting it move
2943 // afterwards would mean messages already queued for the old
2944 // format go out under the new one.
2945 let format = self.format;
2946
2947 self.format_error_message(format_args!(
2948 "Format `{format}` has already been negotiated"
2949 ))?;
2950
2951 break 'err true;
2952 }
2953 _ => {
2954 let Some(format) = Format::from_u8(header.format) else {
2955 self.format_error_message(format_args!(
2956 "Unknown format id {}",
2957 header.format
2958 ))?;
2959
2960 break 'err true;
2961 };
2962
2963 if !self.accepts(format) {
2964 self.format_error_message(format_args!(
2965 "Unsupported format `{format}`, supported: {}",
2966 SupportedFormats(self.formats)
2967 ))?;
2968
2969 break 'err true;
2970 }
2971
2972 // NB: The response goes back in the same frame type the
2973 // request arrived in, so a format which cannot be spelled
2974 // that way has nowhere to go.
2975 if !self.mode.accepts(format) {
2976 let mode = self.mode;
2977
2978 self.format_error_message(format_args!(
2979 "Mode `{mode}` cannot carry the `{format}` format"
2980 ))?;
2981
2982 break 'err true;
2983 }
2984
2985 let id = <H::Id as Id>::from_id(id);
2986 self.handle_request(bytes, at, header, id, format);
2987 return Ok(());
2988 }
2989 }
2990 };
2991
2992 if err {
2993 self.send_error(&header)?;
2994 }
2995
2996 Ok(())
2997 }
2998
2999 fn send_error(&mut self, header: &RequestHeader) -> Result<(), Error> {
3000 // NB: Errors are encoded with the connection format rather than the
3001 // format the request asked for, since the request might have failed
3002 // precisely because that format is not supported. The client reads the
3003 // format back out of the response envelope either way.
3004 let format = self.format;
3005 let mode = self.mode;
3006
3007 // NB: Taken so that a later error is never sent with this payload.
3008 let typed = mem::take(&mut self.error_typed);
3009
3010 let error = if typed {
3011 MessageId::TYPED_ERROR_MESSAGE
3012 } else {
3013 MessageId::ERROR_MESSAGE
3014 };
3015
3016 let buf = self.pool.with(|buf| {
3017 // Reset the buffer to the previous start point.
3018 let mut writer = buf.writer();
3019
3020 let result = writer.envelope(
3021 mode,
3022 &ResponseHeader {
3023 version: VERSION,
3024 serial: header.serial,
3025 broadcast: 0,
3026 error: error.get(),
3027 format: format.to_u8(),
3028 channel: header.channel,
3029 app: 0,
3030 },
3031 );
3032
3033 result.map_err(Error::encode_error_message_header)?;
3034
3035 let result = writer.body(
3036 format,
3037 &ErrorMessage {
3038 message: &self.error,
3039 },
3040 );
3041
3042 result.map_err(Error::encode_error_message)?;
3043
3044 // NB: The payload was already encoded with `format`, see
3045 // `format_response_error`.
3046 if typed {
3047 writer.raw(&self.error_payload);
3048 }
3049
3050 writer.flush();
3051 Ok::<_, Error>(())
3052 })?;
3053
3054 self.push_outbound(buf);
3055 Ok(())
3056 }
3057
3058 /// Queue a buffer to be written to the peer.
3059 fn push_outbound(&mut self, buf: Buf) {
3060 self.outbound_bytes = self.outbound_bytes.saturating_add(buf.remaining());
3061 self.outbound.push_back(buf);
3062 }
3063
3064 /// Test if the connection has as much work queued as it is allowed, in
3065 /// which case nothing more is read from the peer until it has drained.
3066 fn is_saturated(&self) -> bool {
3067 self.set.len() >= self.max_in_flight || self.outbound_bytes >= self.max_outbound
3068 }
3069
3070 /// Begin winding the connection down.
3071 ///
3072 /// This re-arms the close deadline so that draining whatever is left to
3073 /// send is bounded too. Re-arming is also what keeps [`Server::run`] from
3074 /// spinning: an elapsed [`Sleep`] reports `Ready` every time it is polled,
3075 /// so leaving it elapsed would make [`Select`] hand back [`Output::Close`]
3076 /// over and over without the loop ever making progress.
3077 fn begin_closing(&mut self) {
3078 if self.closing {
3079 return;
3080 }
3081
3082 self.closing = true;
3083
3084 let (close_sleep, _, _) = self.pinned.as_mut().project();
3085 close_sleep.reset(Instant::now() + CLOSE_TIMEOUT);
3086 }
3087
3088 #[tracing::instrument(skip(self))]
3089 fn handle_ping(&mut self) -> Result<(), Error> {
3090 let (_, mut ping_sleep, _) = self.pinned.as_mut().project();
3091
3092 let payload = self.rng.random::<u32>();
3093 let payload = payload.to_ne_bytes();
3094
3095 self.last_ping = Some(payload);
3096
3097 tracing::debug!(data = ?&payload[..], "Sending ping");
3098
3099 self.out
3100 .push_back(S::ping(Bytes::from_owner(Vec::from(payload))));
3101
3102 let now = Instant::now();
3103 ping_sleep.as_mut().reset(now + PING_TIMEOUT);
3104 Ok(())
3105 }
3106
3107 #[tracing::instrument(skip(self, payload))]
3108 fn handle_pong(&mut self, payload: Bytes) -> Result<(), Error> {
3109 let (close_sleep, ping_sleep, _) = self.pinned.as_mut().project();
3110
3111 tracing::debug!(payload = ?&payload[..], "Pong");
3112
3113 let Some(expected) = self.last_ping else {
3114 tracing::debug!("No ping sent");
3115 return Ok(());
3116 };
3117
3118 if expected[..] != payload[..] {
3119 tracing::debug!(?expected, ?payload, "Pong doesn't match");
3120 return Ok(());
3121 }
3122
3123 let now = Instant::now();
3124
3125 close_sleep.reset(now + CLOSE_TIMEOUT);
3126 ping_sleep.reset(now + PING_TIMEOUT);
3127 self.last_ping = None;
3128 Ok(())
3129 }
3130
3131 #[tracing::instrument(skip(self))]
3132 fn handle_send(&mut self) -> Result<(), Error> {
3133 let (_, _, mut socket) = self.pinned.as_mut().project();
3134
3135 if self.socket_send {
3136 if let Some(message) = self.out.pop_front() {
3137 socket.as_mut().start_send(message)?;
3138 self.socket_flush = true;
3139 self.socket_send = false;
3140 }
3141 }
3142
3143 while self.socket_send {
3144 let Some(buf) = self.outbound.front_mut() else {
3145 break;
3146 };
3147
3148 let Some(frame) = buf.read()? else {
3149 if let Some(buf) = self.outbound.pop_front() {
3150 self.pool.put(buf);
3151 }
3152
3153 // NB: Keeps the count from drifting if anything ever bypasses
3154 // `push_outbound`.
3155 if self.outbound.is_empty() {
3156 self.outbound_bytes = 0;
3157 }
3158
3159 continue;
3160 };
3161
3162 self.outbound_bytes = self
3163 .outbound_bytes
3164 .saturating_sub(frame.len().saturating_add(mem::size_of::<u32>()));
3165
3166 let message = match self.mode {
3167 Mode::Binary => S::binary(frame),
3168 Mode::Text => S::text(frame),
3169 };
3170
3171 socket.as_mut().start_send(message)?;
3172
3173 self.socket_flush = true;
3174 self.socket_send = false;
3175 break;
3176 }
3177
3178 Ok(())
3179 }
3180
3181 fn handle_request(
3182 &mut self,
3183 bytes: Bytes,
3184 offset: usize,
3185 header: RequestHeader,
3186 id: H::Id,
3187 format: Format,
3188 ) {
3189 tracing::debug!(header.serial, ?id, ?format, "Got request");
3190
3191 let mut buf = self.pool.get();
3192 let handler = self.handler.clone();
3193 let mode = self.mode;
3194
3195 self.set.spawn(async move {
3196 if offset > bytes.len() {
3197 let kind = ErrorKind::OutOfBounds {
3198 offset,
3199 len: bytes.len(),
3200 };
3201
3202 return (Err(Error::new(kind)), false, header, buf);
3203 }
3204
3205 let mut incoming = Incoming {
3206 error: None,
3207 buf: &bytes,
3208 at: offset,
3209 format,
3210 channel: header.channel,
3211 };
3212
3213 let mut outgoing = Outgoing {
3214 serial: Some(header.serial),
3215 error: None,
3216 buf: &mut buf,
3217 format,
3218 mode,
3219 channel: header.channel,
3220 };
3221
3222 let response = handler.handle(id, &mut incoming, &mut outgoing).await;
3223 let written = outgoing.serial.is_none();
3224
3225 if let Some(error) = incoming.error.take() {
3226 return (Err(Error::incoming(error)), written, header, buf);
3227 }
3228
3229 if let Some(error) = outgoing.error.take() {
3230 return (Err(Error::outgoing(error)), written, header, buf);
3231 }
3232
3233 (Ok(response), written, header, buf)
3234 });
3235 }
3236}
3237
3238enum Output<E, R> {
3239 /// The connection should be closed.
3240 Close,
3241 /// A ping message was received.
3242 Ping,
3243 /// A message was received.
3244 Recv(Option<Result<Message, E>>),
3245 /// A message is ready to be sent.
3246 Send(Result<(), E>),
3247 /// Outgoing messages have been successfully flushed.
3248 Flushed(Result<(), E>),
3249 /// Handle output, and whether the handler wrote a response.
3250 Handle(Result<R, Error>, bool, RequestHeader, Buf),
3251}
3252
3253struct Select<'a, S, H>
3254where
3255 H: Handler,
3256{
3257 pinned: Pin<&'a mut Pinned<S>>,
3258 wants_socket_recv: bool,
3259 wants_socket_send: bool,
3260 wants_socket_flush: bool,
3261 set: &'a mut JoinSet<HandlerOutput<H>>,
3262}
3263
3264impl<S, H> Future for Select<'_, S, H>
3265where
3266 S: SocketImpl,
3267 H: Handler,
3268{
3269 type Output = Output<S::Error, H::Response>;
3270
3271 #[inline]
3272 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
3273 // NB: Every field is `Unpin`, the pinned state is behind a `Pin` of
3274 // its own.
3275 let this = Pin::get_mut(self);
3276 let (close, ping, mut socket) = this.pinned.as_mut().project();
3277 let wants_socket_recv = this.wants_socket_recv;
3278 let wants_socket_send = this.wants_socket_send;
3279 let wants_socket_flush = this.wants_socket_flush;
3280 let set = &mut this.set;
3281
3282 if close.poll(cx).is_ready() {
3283 return Poll::Ready(Output::Close);
3284 }
3285
3286 if ping.poll(cx).is_ready() {
3287 return Poll::Ready(Output::Ping);
3288 }
3289
3290 if wants_socket_recv {
3291 if let Poll::Ready(output) = socket.as_mut().poll_next(cx) {
3292 return Poll::Ready(Output::Recv(output));
3293 }
3294 }
3295
3296 if wants_socket_send {
3297 if let Poll::Ready(result) = socket.as_mut().poll_ready(cx) {
3298 return Poll::Ready(Output::Send(result));
3299 }
3300 }
3301
3302 if wants_socket_flush {
3303 if let Poll::Ready(result) = socket.as_mut().poll_flush(cx) {
3304 return Poll::Ready(Output::Flushed(result));
3305 }
3306 }
3307
3308 // NB: An empty `JoinSet` is `Ready(None)` and registers no waker, so
3309 // this drops through to `Pending` having registered nothing of its
3310 // own. That is only safe because the two deadlines above are polled
3311 // unconditionally and have registered theirs.
3312 if let Poll::Ready(Some(output)) = set.poll_join_next(cx) {
3313 let output = match output {
3314 Ok(output) => output,
3315 Err(error) => {
3316 tracing::debug!(?error, "Join error in handler task");
3317 return Poll::Ready(Output::Close);
3318 }
3319 };
3320
3321 let (result, written, header, buf) = output;
3322 return Poll::Ready(Output::Handle(result, written, header, buf));
3323 }
3324
3325 Poll::Pending
3326 }
3327}
3328
3329/// The buffer for incoming requests.
3330///
3331/// See [`server()`] for how to use with `axum`.
3332///
3333/// [`server()`]: crate::axum08::server
3334pub struct Incoming<'de> {
3335 error: Option<format::Error>,
3336 buf: &'de [u8],
3337 at: usize,
3338 format: Format,
3339 channel: ChannelId,
3340}
3341
3342impl<'de> Incoming<'de> {
3343 /// The channel over which the incoming request was received.
3344 ///
3345 /// This is [`ChannelId::NONE`] unless the client sent the request over a
3346 /// channel, such as one opened with [`Handle::channel`]. Pass it to
3347 /// [`Server::broadcast_from`] to credit a broadcast to the channel whose
3348 /// request caused it.
3349 ///
3350 /// [`Handle::channel`]: crate::web::Handle::channel
3351 pub fn channel(&self) -> ChannelId {
3352 self.channel
3353 }
3354
3355 /// The [`Format`] the incoming request body is encoded with.
3356 ///
3357 /// This is the format the client declared for this particular request, and
3358 /// is also the format the response will be written with.
3359 #[inline]
3360 pub fn format(&self) -> Format {
3361 self.format
3362 }
3363
3364 /// Read a request and return `Some(T)` if the request was successfully
3365 /// decoded.
3366 ///
3367 /// Note that any failure to decode will be propagated as an error
3368 /// automatically, the user does not have to deal with it themselves.
3369 /// Instead, failure to decode should be treated as if the request was
3370 /// unhandled by returning for example `false` or `Option::None`.
3371 #[inline]
3372 pub fn read<T>(&mut self) -> Option<T>
3373 where
3374 T: DecodeBody<'de>,
3375 {
3376 match self.format.decode(self.buf, &mut self.at) {
3377 Ok(value) => Some(value),
3378 Err(error) => {
3379 self.error = Some(error);
3380 None
3381 }
3382 }
3383 }
3384}
3385
3386/// The buffer for outgoing responses.
3387///
3388/// See [`server()`] for how to use with `axum`.
3389///
3390/// [`server()`]: crate::axum08::server
3391pub struct Outgoing<'a> {
3392 serial: Option<u32>,
3393 error: Option<format::Error>,
3394 buf: &'a mut Buf,
3395 format: Format,
3396 mode: Mode,
3397 channel: ChannelId,
3398}
3399
3400impl Outgoing<'_> {
3401 /// The [`Format`] the response will be encoded with, which is the format
3402 /// the corresponding request declared.
3403 #[inline]
3404 pub fn format(&self) -> Format {
3405 self.format
3406 }
3407
3408 /// The [`Mode`] the response will be spelled in, which is the mode the
3409 /// corresponding request arrived in.
3410 #[inline]
3411 pub fn mode(&self) -> Mode {
3412 self.mode
3413 }
3414
3415 /// Write a response.
3416 ///
3417 /// This can only be called once. Calling this multiple times has no effect.
3418 ///
3419 /// A handler which reports a request as handled must call this, otherwise
3420 /// the client receives an error instead of a response. See
3421 /// [`Handler::handle`].
3422 ///
3423 /// See [`server()`] for how to use with `axum`.
3424 ///
3425 /// [`server()`]: crate::axum08::server
3426 pub fn write<T>(&mut self, value: T)
3427 where
3428 T: EncodeBody,
3429 {
3430 let Some(serial) = self.serial.take() else {
3431 return;
3432 };
3433
3434 let mut writer = self.buf.writer();
3435
3436 let result = writer.envelope(
3437 self.mode,
3438 &ResponseHeader {
3439 version: VERSION,
3440 serial,
3441 broadcast: 0,
3442 error: 0,
3443 format: self.format.to_u8(),
3444 channel: self.channel,
3445 app: 0,
3446 },
3447 );
3448
3449 if let Err(error) = result {
3450 self.error = Some(error);
3451 return;
3452 }
3453
3454 if let Err(error) = writer.body(self.format, &value) {
3455 self.error = Some(error);
3456 }
3457
3458 writer.flush();
3459 }
3460}
3461
3462/// Scramble a sequential channel id into a value that looks random to clients.
3463///
3464/// Uses an odd multiply followed by an XOR-shift (bijective over u16, preserves
3465/// 0, self-inverse).
3466#[inline]
3467fn scramble_channel(x: u16) -> u16 {
3468 let x = x.wrapping_mul(0x9285);
3469 x ^ (x >> 8)
3470}
3471
3472/// Inverse of [`scramble_channel`].
3473#[inline]
3474#[cfg(test)]
3475fn unscramble_channel(x: u16) -> u16 {
3476 let x = x ^ (x >> 8);
3477 x.wrapping_mul(0x964d)
3478}
3479
3480#[test]
3481fn test_scramble() {
3482 assert_eq!(scramble_channel(0), 0);
3483 assert_eq!(unscramble_channel(0), 0);
3484
3485 for i in 1..=u16::MAX {
3486 let scrambled = scramble_channel(i);
3487 let unscrambled = unscramble_channel(scrambled);
3488 assert_eq!(i, unscrambled, "Failed to unscramble channel id");
3489 }
3490}
3491
3492#[derive(Default)]
3493struct ChannelsInner {
3494 last: u16,
3495 free: VecDeque<NonZeroU16>,
3496}
3497
3498/// The pool behind [`Channels::global()`].
3499static GLOBAL_CHANNELS: LazyLock<Channels> = LazyLock::new(Channels::new);
3500
3501/// The default [`ChannelAllocator`], a pool of channel ids.
3502///
3503/// Every clone of a `Channels` allocates from the same pool, so the ids it
3504/// hands out are distinct from one another for as long as they are held. Ids
3505/// are reused once freed.
3506///
3507/// [`Channels::global()`] is the pool every [`Server`] uses unless told
3508/// otherwise, which makes channel ids unique across every connection in the
3509/// process. [`Channels::new()`] is a pool of its own, for when ids should be
3510/// scoped more narrowly, see [`ChannelAllocator`].
3511///
3512/// A pool holds at most [`u16::MAX`] ids at once.
3513#[derive(Clone)]
3514pub struct Channels {
3515 inner: Arc<Mutex<ChannelsInner>>,
3516}
3517
3518impl Channels {
3519 /// Construct a new pool of channel ids which is independent of every other
3520 /// pool, including [`Channels::global()`].
3521 ///
3522 /// # Examples
3523 ///
3524 /// ```
3525 /// use musli_web::ws::{ChannelAllocator, Channels};
3526 ///
3527 /// let channels = Channels::new();
3528 /// let a = channels.next().unwrap();
3529 /// let b = channels.clone().next().unwrap();
3530 /// assert_ne!(a, b);
3531 /// ```
3532 #[inline]
3533 pub fn new() -> Self {
3534 Self {
3535 inner: Arc::new(Mutex::new(ChannelsInner::default())),
3536 }
3537 }
3538
3539 /// The process-wide pool of channel ids, which every [`Server`] allocates
3540 /// from by default.
3541 ///
3542 /// # Examples
3543 ///
3544 /// ```
3545 /// use musli_web::ws::{ChannelAllocator, Channels};
3546 ///
3547 /// let a = Channels::global().next().unwrap();
3548 /// let b = Channels::global().next().unwrap();
3549 /// assert_ne!(a, b);
3550 /// ```
3551 #[inline]
3552 pub fn global() -> Self {
3553 GLOBAL_CHANNELS.clone()
3554 }
3555
3556 #[inline]
3557 fn lock(&self) -> MutexGuard<'_, ChannelsInner> {
3558 // NB: Nothing panics while the lock is held, and the state is valid
3559 // between every statement anyway.
3560 self.inner.lock().unwrap_or_else(PoisonError::into_inner)
3561 }
3562}
3563
3564impl Default for Channels {
3565 /// Same as [`Channels::new()`].
3566 #[inline]
3567 fn default() -> Self {
3568 Self::new()
3569 }
3570}
3571
3572impl ChannelAllocator for Channels {
3573 #[inline]
3574 fn next(&self) -> Option<ChannelId> {
3575 let mut inner = self.lock();
3576
3577 if let Some(id) = inner.free.pop_front() {
3578 return Some(ChannelId::from_u16(id.get()));
3579 }
3580
3581 let id = NonZeroU16::new(inner.last.wrapping_add(1))?;
3582 inner.last = id.get();
3583
3584 tracing::debug!(?id, "Allocated channel id");
3585 Some(ChannelId::from_u16(scramble_channel(id.get())))
3586 }
3587
3588 #[inline]
3589 fn free(&self, id: ChannelId) {
3590 tracing::debug!(?id, "Freeing channel id");
3591
3592 if let Some(id) = NonZeroU16::new(id.raw()) {
3593 self.lock().free.push_back(id);
3594 }
3595 }
3596}
3597
3598/// Why a channel could not be opened.
3599#[derive(Debug, PartialEq, Eq)]
3600enum OpenChannelError {
3601 /// The client already holds as many channels as it may.
3602 Limit(usize),
3603 /// The allocator has no id to hand out.
3604 Exhausted,
3605}
3606
3607impl fmt::Display for OpenChannelError {
3608 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3609 match self {
3610 Self::Limit(limit) => write!(f, "Too many open channels, at most {limit} are allowed"),
3611 Self::Exhausted => f.write_str("No channel id is available"),
3612 }
3613 }
3614}
3615
3616/// The channels one client holds, allocated from `C`.
3617///
3618/// This is what keeps a connection to the ids it was handed: only those are
3619/// ever freed, and every one still held is freed on drop.
3620struct OwnedChannels<C>
3621where
3622 C: ChannelAllocator,
3623{
3624 allocator: C,
3625 open: BTreeSet<ChannelId>,
3626 max: usize,
3627}
3628
3629impl<C> OwnedChannels<C>
3630where
3631 C: ChannelAllocator,
3632{
3633 #[inline]
3634 fn new(allocator: C, max: usize) -> Self {
3635 Self {
3636 allocator,
3637 open: BTreeSet::new(),
3638 max,
3639 }
3640 }
3641
3642 /// Allocate and take hold of a new channel.
3643 fn open(&mut self) -> Result<ChannelId, OpenChannelError> {
3644 if self.open.len() >= self.max {
3645 return Err(OpenChannelError::Limit(self.max));
3646 }
3647
3648 let id = self.allocator.next().ok_or(OpenChannelError::Exhausted)?;
3649
3650 // NB: An allocator which breaks its contract by handing out no
3651 // channel, or one this connection already holds, is refused. Neither
3652 // is freed here: the first was never allocated and the second is
3653 // freed once, when the channel it already names closes.
3654 if id == ChannelId::NONE || !self.open.insert(id) {
3655 return Err(OpenChannelError::Exhausted);
3656 }
3657
3658 Ok(id)
3659 }
3660
3661 /// Release a channel, returning `false` if it is not held.
3662 fn close(&mut self, id: ChannelId) -> bool {
3663 if !self.open.remove(&id) {
3664 return false;
3665 }
3666
3667 self.allocator.free(id);
3668 true
3669 }
3670}
3671
3672impl<C> Drop for OwnedChannels<C>
3673where
3674 C: ChannelAllocator,
3675{
3676 fn drop(&mut self) {
3677 for id in mem::take(&mut self.open) {
3678 self.allocator.free(id);
3679 }
3680 }
3681}
3682
3683/// Renders the formats a server is willing to negotiate, for error messages.
3684struct SupportedFormats(Option<&'static [Format]>);
3685
3686impl fmt::Display for SupportedFormats {
3687 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3688 let mut first = true;
3689
3690 for format in Format::supported() {
3691 if self.0.is_some_and(|formats| !formats.contains(&format)) {
3692 continue;
3693 }
3694
3695 if !first {
3696 f.write_str(", ")?;
3697 }
3698
3699 write!(f, "`{format}`")?;
3700 first = false;
3701 }
3702
3703 if first {
3704 f.write_str("none")?;
3705 }
3706
3707 Ok(())
3708 }
3709}
3710
3711#[cfg(test)]
3712mod tests {
3713 use core::cell::Cell;
3714
3715 use std::thread_local;
3716
3717 use super::*;
3718
3719 /// How many close frames the loop is allowed to manufacture before the test
3720 /// concludes that it is spinning.
3721 ///
3722 /// A close frame is the only observable thing the wind-down path produces,
3723 /// so this is what bounds the test. Without it a regression makes
3724 /// [`Server::run`] loop forever inside a single poll and the test hangs
3725 /// rather than fails.
3726 const CLOSE_BUDGET: usize = 4;
3727
3728 /// How many times a stream which has ended is allowed to be polled before
3729 /// the test concludes that [`Server::run`] is spinning on it.
3730 ///
3731 /// Such a stream reports `Ready(None)` on every poll, so a regression makes
3732 /// the loop poll it forever inside a single task poll and the test hangs
3733 /// rather than fails.
3734 const RECV_BUDGET: usize = 4;
3735
3736 thread_local! {
3737 /// The number of close frames [`TestServerImpl::close`] has handed out
3738 /// on this thread, which is one test.
3739 static CLOSE_FRAMES: Cell<usize> = const { Cell::new(0) };
3740 }
3741
3742 #[derive(Debug)]
3743 enum TestError {}
3744
3745 impl From<TestError> for Error {
3746 #[inline]
3747 fn from(error: TestError) -> Self {
3748 match error {}
3749 }
3750 }
3751
3752 #[derive(Debug, PartialEq, Eq)]
3753 enum TestMessage {
3754 Ping(Bytes),
3755 Pong(Bytes),
3756 Binary(Vec<u8>),
3757 Text(Vec<u8>),
3758 Close(u16),
3759 }
3760
3761 /// A socket which never hears anything from its peer, which is the state a
3762 /// connection is in when its close deadline elapses.
3763 #[derive(Default)]
3764 struct TestSocket {
3765 sent: Vec<TestMessage>,
3766 /// Whether the peer has gone away, which makes the stream report
3767 /// `Ready(None)` on every poll for the rest of its life.
3768 ended: bool,
3769 polls_after_end: usize,
3770 /// Whether the write side has backpressure, which is what a real sink
3771 /// does while the socket buffer it is writing into has not drained.
3772 write_blocked: bool,
3773 /// Messages the peer has sent which are yet to be read.
3774 incoming: VecDeque<Message>,
3775 }
3776
3777 impl socket_sealed::Sealed for TestSocket {}
3778
3779 impl SocketImpl for TestSocket {
3780 type Message = TestMessage;
3781 type Error = TestError;
3782
3783 fn poll_next(
3784 self: Pin<&mut Self>,
3785 _: &mut Context<'_>,
3786 ) -> Poll<Option<Result<Message, Self::Error>>> {
3787 // SAFETY: Nothing in this socket is structurally pinned.
3788 let this = unsafe { Pin::get_unchecked_mut(self) };
3789
3790 if let Some(message) = this.incoming.pop_front() {
3791 return Poll::Ready(Some(Ok(message)));
3792 }
3793
3794 if !this.ended {
3795 return Poll::Pending;
3796 }
3797
3798 this.polls_after_end += 1;
3799
3800 assert!(
3801 this.polls_after_end <= RECV_BUDGET,
3802 "`Server::run` is spinning: an ended stream was polled {} times without any progress",
3803 this.polls_after_end
3804 );
3805
3806 Poll::Ready(None)
3807 }
3808
3809 fn poll_ready(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
3810 // SAFETY: Nothing in this socket is structurally pinned.
3811 if unsafe { Pin::get_unchecked_mut(self) }.write_blocked {
3812 return Poll::Pending;
3813 }
3814
3815 Poll::Ready(Ok(()))
3816 }
3817
3818 fn start_send(self: Pin<&mut Self>, item: Self::Message) -> Result<(), Self::Error> {
3819 // SAFETY: Nothing in this socket is structurally pinned.
3820 unsafe { Pin::get_unchecked_mut(self).sent.push(item) };
3821 Ok(())
3822 }
3823
3824 fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
3825 // SAFETY: Nothing in this socket is structurally pinned.
3826 if unsafe { Pin::get_unchecked_mut(self) }.write_blocked {
3827 return Poll::Pending;
3828 }
3829
3830 Poll::Ready(Ok(()))
3831 }
3832 }
3833
3834 struct TestServerImpl;
3835
3836 impl server_sealed::Sealed for TestServerImpl {}
3837
3838 impl ServerImpl for TestServerImpl {
3839 type Error = TestError;
3840 type Message = TestMessage;
3841 type Socket = TestSocket;
3842
3843 fn ping(data: Bytes) -> Self::Message {
3844 TestMessage::Ping(data)
3845 }
3846
3847 fn pong(data: Bytes) -> Self::Message {
3848 TestMessage::Pong(data)
3849 }
3850
3851 fn binary(data: &[u8]) -> Self::Message {
3852 TestMessage::Binary(data.to_vec())
3853 }
3854
3855 fn text(data: &[u8]) -> Self::Message {
3856 TestMessage::Text(data.to_vec())
3857 }
3858
3859 fn close(code: u16, _: &str) -> Self::Message {
3860 let frames = CLOSE_FRAMES.with(|frames| {
3861 let count = frames.get() + 1;
3862 frames.set(count);
3863 count
3864 });
3865
3866 assert!(
3867 frames <= CLOSE_BUDGET,
3868 "`Server::run` is spinning: {frames} close frames without any progress"
3869 );
3870
3871 TestMessage::Close(code)
3872 }
3873 }
3874
3875 #[derive(Debug)]
3876 struct TestId;
3877
3878 impl Id for TestId {
3879 const IDS: IdSet = IdSet::EMPTY;
3880
3881 fn id(&self) -> MessageId {
3882 MessageId::NEGOTIATE
3883 }
3884
3885 fn from_id(_: MessageId) -> Self {
3886 Self
3887 }
3888
3889 fn try_from_id(_: MessageId) -> Option<Self> {
3890 None
3891 }
3892
3893 fn __do_not_implement_id() {}
3894 }
3895
3896 #[derive(Clone, Default)]
3897 struct TestHandler {
3898 /// Whether requests are never answered, which keeps every handler
3899 /// in flight.
3900 block: bool,
3901 }
3902
3903 impl Handler for TestHandler {
3904 type Id = TestId;
3905 type Response = bool;
3906
3907 async fn handle(&self, _: Self::Id, _: &mut Incoming<'_>, _: &mut Outgoing<'_>) -> bool {
3908 if self.block {
3909 core::future::pending::<()>().await;
3910 }
3911
3912 false
3913 }
3914 }
3915
3916 /// Build a negotiated server whose close deadline elapsed `elapsed` ago.
3917 fn timed_out_server(elapsed: Duration) -> Server<TestServerImpl, TestHandler, Channels> {
3918 server_with(Instant::now() - elapsed)
3919 }
3920
3921 /// The test socket behind the server's pinned state.
3922 fn socket(server: &mut Server<TestServerImpl, TestHandler, Channels>) -> &mut TestSocket {
3923 let (_, _, socket) = server.pinned.as_mut().project();
3924 // SAFETY: Nothing in this socket is structurally pinned.
3925 unsafe { Pin::get_unchecked_mut(socket) }
3926 }
3927
3928 /// A response buffer of the shape a handler leaves behind in `outbound`.
3929 fn response(server: &Server<TestServerImpl, TestHandler, Channels>) -> Buf {
3930 server
3931 .pool
3932 .with(|buf| {
3933 let mut writer = buf.writer();
3934
3935 writer
3936 .envelope(
3937 Mode::DEFAULT,
3938 &ResponseHeader {
3939 version: VERSION,
3940 serial: 1,
3941 broadcast: 0,
3942 error: 0,
3943 format: Format::DEFAULT.to_u8(),
3944 channel: ChannelId::NONE,
3945 app: 0,
3946 },
3947 )
3948 .map_err(Error::encode_connect_header)?;
3949
3950 writer.flush();
3951 Ok::<_, Error>(())
3952 })
3953 .unwrap()
3954 }
3955
3956 /// Build a negotiated server which winds down at `close_deadline`.
3957 fn server_with(close_deadline: Instant) -> Server<TestServerImpl, TestHandler, Channels> {
3958 let now = Instant::now();
3959
3960 Server {
3961 handler: TestHandler::default(),
3962 pinned: Box::pin(Pinned {
3963 socket: TestSocket::default(),
3964 close_sleep: tokio::time::sleep_until(close_deadline),
3965 ping_sleep: tokio::time::sleep_until(now + PING_TIMEOUT),
3966 }),
3967 channels: OwnedChannels::new(Channels::new(), DEFAULT_MAX_CHANNELS),
3968 closing: false,
3969 pool: BufPool::new(MAX_CAPACITY),
3970 outbound: VecDeque::new(),
3971 outbound_bytes: 0,
3972 max_in_flight: DEFAULT_MAX_IN_FLIGHT,
3973 max_outbound: DEFAULT_MAX_OUTBOUND,
3974 error: String::new(),
3975 error_payload: Vec::new(),
3976 error_typed: false,
3977 last_ping: None,
3978 rng: SmallRng::seed_from_u64(DEFAULT_SEED),
3979 out: VecDeque::new(),
3980 socket_send: false,
3981 socket_flush: false,
3982 socket_recv: true,
3983 set: JoinSet::new(),
3984 format: Format::DEFAULT,
3985 mode: Mode::DEFAULT,
3986 failure: None,
3987 formats: None,
3988 app: 0,
3989 }
3990 }
3991
3992 /// An elapsed close deadline must wind the connection down once, rather
3993 /// than being reported by [`Select`] over and over.
3994 ///
3995 /// A [`Sleep`] which has elapsed is `Ready` on every poll, so a close
3996 /// deadline which is left elapsed turns [`Server::run`] into a busy loop
3997 /// which queues an unbounded number of close frames and never returns.
3998 #[tokio::test]
3999 async fn close_deadline_winds_down_once() {
4000 let mut server = timed_out_server(Duration::from_secs(1));
4001
4002 server.run().await.unwrap();
4003
4004 assert_eq!(socket(&mut server).sent, [TestMessage::Close(CLOSE_NORMAL)]);
4005 assert!(server.out.is_empty());
4006 assert!(server.closing);
4007 // The close frame has to reach the wire, not just the sink's buffer.
4008 assert!(!server.socket_flush);
4009 }
4010
4011 /// The close deadline elapsing while the connection is already winding
4012 /// down must tear it down instead of queueing yet another close frame.
4013 #[tokio::test]
4014 async fn close_deadline_while_closing_gives_up() {
4015 let mut server = timed_out_server(Duration::from_secs(1));
4016
4017 // The state left behind by a close frame which the socket has not been
4018 // able to take yet, with the wind-down deadline elapsed on top of it.
4019 server.closing = true;
4020 server.out.push_back(TestMessage::Close(CLOSE_NORMAL));
4021
4022 server.run().await.unwrap();
4023
4024 assert!(socket(&mut server).sent.is_empty());
4025 assert_eq!(server.out.len(), 1);
4026 }
4027
4028 /// A peer which disconnects with a response still queued must not pin the
4029 /// connection task forever.
4030 ///
4031 /// A stream which has ended reports `Ready(None)` on every poll, which sits
4032 /// ahead of the send and flush arms in [`Select`] and used to mask them, so
4033 /// `outbound` could never drain and [`Server::run`] could never reach its
4034 /// break.
4035 ///
4036 /// Nothing here may lean on the close deadline: a loop which never yields
4037 /// is exactly the condition under which the runtime cannot deliver a timer,
4038 /// so the deadline is left a full [`CLOSE_TIMEOUT`] out and this test would
4039 /// hang rather than pass if the wind-down needed it.
4040 #[tokio::test]
4041 async fn ended_stream_drains_outbound() {
4042 let mut server = server_with(Instant::now() + CLOSE_TIMEOUT);
4043
4044 // The state a connection is left in when the peer goes away after its
4045 // request has been handled but before the response reached the socket.
4046 server.closing = true;
4047 server.socket_flush = true;
4048 server.outbound.push_back(response(&server));
4049 socket(&mut server).ended = true;
4050
4051 server.run().await.unwrap();
4052
4053 let sent = socket(&mut server).sent.as_slice();
4054 assert!(matches!(sent, [TestMessage::Binary(..)]));
4055 assert!(server.outbound.is_empty());
4056 assert!(!server.socket_flush);
4057 assert!(!server.socket_recv);
4058 }
4059
4060 /// A peer which is gone while the write side still has backpressure must
4061 /// wind down on the close deadline rather than spin.
4062 ///
4063 /// This is the case which separates fusing the stream from merely polling
4064 /// the send and flush arms ahead of it. Reordering the arms would rescue
4065 /// [`ended_stream_drains_outbound`], where the sink takes the write
4066 /// immediately, but not this: with the write side `Pending` there is no arm
4067 /// left to reach, so a stream which is still polled after it ended hands
4068 /// back `Ready(None)` forever and [`Server::run`] never yields.
4069 ///
4070 /// Fused, [`Select`] returns `Pending`, the task parks, and the deadline
4071 /// gets the chance to fire which the spin used to deny it. Leaning on it
4072 /// here is the point, so the deadline is short.
4073 #[tokio::test]
4074 async fn blocked_write_winds_down_on_deadline() {
4075 let mut server = server_with(Instant::now() + Duration::from_millis(50));
4076
4077 server.closing = true;
4078 server.socket_flush = true;
4079 server.outbound.push_back(response(&server));
4080
4081 {
4082 let socket = socket(&mut server);
4083 socket.ended = true;
4084 socket.write_blocked = true;
4085 }
4086
4087 server.run().await.unwrap();
4088
4089 // Nothing could be delivered, which is the honest outcome against a
4090 // socket which never took the write. Ending at all is what matters.
4091 assert!(socket(&mut server).sent.is_empty());
4092 assert_eq!(server.outbound.len(), 1);
4093 assert!(!server.socket_recv);
4094 }
4095
4096 /// A request as a peer would send it.
4097 fn request(mode: Mode, serial: u32) -> Message {
4098 let mut out = Vec::new();
4099
4100 let header = RequestHeader {
4101 version: VERSION,
4102 serial,
4103 id: 1,
4104 format: Format::DEFAULT.to_u8(),
4105 channel: ChannelId::NONE,
4106 app: 0,
4107 };
4108
4109 format::encode_envelope(mode, &mut out, &header).unwrap();
4110
4111 match mode {
4112 Mode::Binary => Message::Binary(Bytes::from(out)),
4113 Mode::Text => Message::Text(Bytes::from(out)),
4114 }
4115 }
4116
4117 /// A server with `count` requests waiting to be read.
4118 fn flooded_server(count: u32) -> Server<TestServerImpl, TestHandler, Channels> {
4119 let mut server = server_with(Instant::now() + CLOSE_TIMEOUT);
4120 let mode = server.mode;
4121
4122 socket(&mut server)
4123 .incoming
4124 .extend((1..=count).map(|serial| request(mode, serial)));
4125
4126 server
4127 }
4128
4129 /// Run the server until it has nothing left to do short of a deadline.
4130 async fn run_until_idle(server: &mut Server<TestServerImpl, TestHandler, Channels>) {
4131 let result = tokio::time::timeout(Duration::from_millis(100), server.run()).await;
4132 assert!(result.is_err(), "The connection should still be up");
4133 }
4134
4135 /// Requests which are never answered must stop the server from reading
4136 /// more of them, or a peer can make it spawn handlers without bound.
4137 #[tokio::test]
4138 async fn in_flight_handlers_stop_reading() {
4139 let mut server = flooded_server(10);
4140 server.handler = TestHandler { block: true };
4141 server.max_in_flight = 3;
4142
4143 run_until_idle(&mut server).await;
4144
4145 assert_eq!(server.set.len(), 3);
4146 assert_eq!(socket(&mut server).incoming.len(), 7);
4147 }
4148
4149 /// A peer which sends requests but never reads the responses must stop
4150 /// being read from once enough output is queued for it, or it grows the
4151 /// server's memory without bound.
4152 #[tokio::test]
4153 async fn queued_output_stops_reading() {
4154 let mut server = flooded_server(10);
4155 // NB: One request at a time, so that it is the queued output and not
4156 // the number of handlers which holds the rest back.
4157 server.max_in_flight = 1;
4158 server.max_outbound = 1;
4159 socket(&mut server).write_blocked = true;
4160
4161 run_until_idle(&mut server).await;
4162
4163 assert!(server.set.is_empty());
4164 assert_eq!(server.outbound.len(), 1);
4165 assert!(server.outbound_bytes > 0);
4166 assert_eq!(socket(&mut server).incoming.len(), 9);
4167 assert!(socket(&mut server).sent.is_empty());
4168 }
4169
4170 /// Reading resumes once the queued output has been written, so a peer
4171 /// which keeps up is never stalled by the limits.
4172 #[tokio::test]
4173 async fn reading_resumes_once_drained() {
4174 let mut server = flooded_server(10);
4175 server.max_in_flight = 1;
4176 server.max_outbound = 1;
4177
4178 run_until_idle(&mut server).await;
4179
4180 assert!(server.set.is_empty());
4181 assert!(server.outbound.is_empty());
4182 assert_eq!(server.outbound_bytes, 0);
4183 assert!(socket(&mut server).incoming.is_empty());
4184
4185 let sent = &socket(&mut server).sent;
4186 assert_eq!(sent.len(), 10);
4187
4188 assert!(
4189 sent.iter()
4190 .all(|m| matches!(m, TestMessage::Binary(..) | TestMessage::Text(..)))
4191 );
4192 }
4193
4194 /// The ids handed out by every clone of one pool are distinct while held,
4195 /// and a pool of its own is independent of the global one.
4196 #[test]
4197 fn channels_are_distinct_within_a_pool() {
4198 let pool = Channels::new();
4199 let other = pool.clone();
4200
4201 let ids = (0..64)
4202 .map(|n| if n % 2 == 0 { &pool } else { &other })
4203 .map(|pool| pool.next().unwrap())
4204 .collect::<BTreeSet<_>>();
4205
4206 assert_eq!(ids.len(), 64);
4207 assert!(!ids.contains(&ChannelId::NONE));
4208
4209 // NB: The global pool is shared with every test in the binary, so all
4210 // this can rely on is that its clones agree with one another.
4211 let a = Channels::global().next().unwrap();
4212 let b = Channels::global().next().unwrap();
4213 assert_ne!(a, b);
4214 Channels::global().free(a);
4215 Channels::global().free(b);
4216 }
4217
4218 /// A connection only frees the ids it holds, so one client cannot put the
4219 /// live channel of another back into the pool.
4220 #[test]
4221 fn owned_channels_only_close_their_own() {
4222 let pool = Channels::new();
4223 let mut first = OwnedChannels::new(pool.clone(), DEFAULT_MAX_CHANNELS);
4224 let mut second = OwnedChannels::new(pool.clone(), DEFAULT_MAX_CHANNELS);
4225
4226 let a = first.open().unwrap();
4227
4228 assert!(!second.close(a));
4229 assert!(!second.close(ChannelId::NONE));
4230 assert!(!second.close(ChannelId::from_u16(0x1234)));
4231 assert!(pool.lock().free.is_empty());
4232
4233 let b = second.open().unwrap();
4234 assert_ne!(a, b);
4235
4236 // Closing twice frees once.
4237 assert!(first.close(a));
4238 assert!(!first.close(a));
4239 assert_eq!(pool.lock().free.len(), 1);
4240 }
4241
4242 /// Dropping a connection returns every id it still holds, and nothing
4243 /// else.
4244 #[test]
4245 fn owned_channels_free_on_drop() {
4246 let pool = Channels::new();
4247 let mut first = OwnedChannels::new(pool.clone(), DEFAULT_MAX_CHANNELS);
4248 let mut second = OwnedChannels::new(pool.clone(), DEFAULT_MAX_CHANNELS);
4249
4250 let held = [first.open().unwrap(), first.open().unwrap()];
4251 let other = second.open().unwrap();
4252
4253 drop(first);
4254
4255 let freed = pool
4256 .lock()
4257 .free
4258 .iter()
4259 .map(|id| ChannelId::from_u16(id.get()))
4260 .collect::<BTreeSet<_>>();
4261
4262 assert_eq!(freed, BTreeSet::from(held));
4263
4264 // The ids are reused, but never the one the other connection holds.
4265 let reused = [second.open().unwrap(), second.open().unwrap()];
4266 assert_eq!(BTreeSet::from(reused), BTreeSet::from(held));
4267 assert!(!reused.contains(&other));
4268 }
4269
4270 /// A client which holds as many channels as it may is refused another
4271 /// until it closes one, which keeps one client from draining a pool
4272 /// shared with others.
4273 #[test]
4274 fn owned_channels_limit() {
4275 let mut channels = OwnedChannels::new(Channels::new(), 2);
4276
4277 let a = channels.open().unwrap();
4278 channels.open().unwrap();
4279 assert_eq!(channels.open(), Err(OpenChannelError::Limit(2)));
4280
4281 assert!(channels.close(a));
4282 channels.open().unwrap();
4283
4284 let mut none = OwnedChannels::new(Channels::new(), 0);
4285 assert_eq!(none.open(), Err(OpenChannelError::Limit(0)));
4286 }
4287
4288 /// An allocator which hands out no channel, or one already held, is
4289 /// refused, and neither id is freed on its behalf.
4290 #[test]
4291 fn owned_channels_refuse_a_broken_allocator() {
4292 #[derive(Default)]
4293 struct Broken {
4294 next: std::sync::Mutex<Vec<ChannelId>>,
4295 freed: std::sync::Mutex<Vec<ChannelId>>,
4296 }
4297
4298 impl ChannelAllocator for &Broken {
4299 fn next(&self) -> Option<ChannelId> {
4300 self.next.lock().unwrap().pop()
4301 }
4302
4303 fn free(&self, channel: ChannelId) {
4304 self.freed.lock().unwrap().push(channel);
4305 }
4306 }
4307
4308 let one = ChannelId::from_u16(1);
4309 let broken = Broken::default();
4310 broken
4311 .next
4312 .lock()
4313 .unwrap()
4314 .extend([one, ChannelId::NONE, one]);
4315
4316 let mut channels = OwnedChannels::new(&broken, DEFAULT_MAX_CHANNELS);
4317
4318 assert_eq!(channels.open(), Ok(one));
4319 assert_eq!(channels.open(), Err(OpenChannelError::Exhausted));
4320 assert_eq!(channels.open(), Err(OpenChannelError::Exhausted));
4321 assert_eq!(channels.open(), Err(OpenChannelError::Exhausted));
4322
4323 drop(channels);
4324 assert_eq!(*broken.freed.lock().unwrap(), [one]);
4325 }
4326}