1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//! WebSocket (RFC 6455) with `permessage-deflate` (RFC 7692), zero
//! third-party dependencies. A `no_std + alloc` protocol core
//! ([`frame`], [`utf8`], [`handshake`], [`session`]) plus thin `std`
//! adapters in [`crate::courierust_server`] and
//! [`crate::courierust_client`].
//!
//! What is unusual here:
//!
//! * Servers write payloads straight from the caller's buffer; clients
//! mask in 16 KiB windows. Frame headers are parsed out of the read
//! buffer without copying.
//! * [`session::Session::poll_message`] never blocks and never drops
//! partial state, so one state machine drives both a blocking worker
//! and an event-loop reactor.
//! * Non-minimal length encodings, reserved bits without a negotiated
//! extension, unknown opcodes, fragmented or oversized control frames,
//! duplicate `Sec-WebSocket-Key`/`Version` headers and a wrong masking
//! direction are rejected before a byte is buffered for the
//! application.
//! * Text is validated incrementally, so a character split across frames
//! is accepted and an illegal sequence is rejected at the byte that
//! makes it illegal (after inflating, for `permessage-deflate`).
//! * `max_frame`, `max_message`, `max_fragments`, a ≤32 KiB
//! decompression window and a cap on the inflated size bound every
//! per-connection cost.
//! * [`handshake::OriginPolicy`] compares `Origin` with the request's own
//! origin, believing `X-Forwarded-*` only from a peer inside a
//! configured [`handshake::IpNet`].
//!
//! ```no_run
//! # #[cfg(feature = "std")]
//! # fn main() -> courierust::Result<()> {
//! use courierust::courierust_ws::{FrameWriter, MaskSource, Session, SessionConfig, VecSink};
//! use courierust::courierust_io::{BufReader, SliceReader};
//!
//! // A session over any transport the crate already speaks. A client
//! // would use `MaskSource::Random`; a server never masks.
//! let reader = BufReader::new(SliceReader::new(&[]), 4096);
//! let writer = FrameWriter::new(VecSink::new(), MaskSource::None, None);
//! let mut session = Session::new(reader, writer, SessionConfig::default());
//! session.send_text("hello")?;
//! session.flush()?;
//! # Ok(())
//! # }
//! # #[cfg(not(feature = "std"))]
//! # fn main() {}
//! ```
pub use ;
pub use ;
pub use ;
pub use Utf8Validator;
pub use ;