tungstenite/protocol/mod.rs
1//! Generic WebSocket message stream.
2
3pub mod frame;
4
5mod message;
6
7pub use self::{frame::CloseFrame, message::Message};
8
9use self::{
10 frame::{
11 coding::{CloseCode, Control as OpCtl, Data as OpData, OpCode},
12 Frame, FrameCodec,
13 },
14 message::{IncompleteMessage, MessageType},
15};
16use crate::{
17 error::{CapacityError, Error, ProtocolError, Result},
18 extensions::{compression::DecompressionError, Extensions, ExtensionsConfig},
19 protocol::frame::Utf8Bytes,
20};
21use log::*;
22use std::{
23 io::{self, Read, Write},
24 mem::replace,
25 usize,
26};
27
28/// Indicates a Client or Server role of the websocket
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum Role {
31 /// This socket is a server
32 Server,
33 /// This socket is a client
34 Client,
35}
36
37/// The configuration for WebSocket connection.
38///
39/// # Example
40/// ```
41/// # use tungstenite::protocol::WebSocketConfig;;
42/// let conf = WebSocketConfig::default()
43/// .read_buffer_size(256 * 1024)
44/// .write_buffer_size(256 * 1024);
45/// ```
46#[derive(Debug, Clone, Copy)]
47#[non_exhaustive]
48pub struct WebSocketConfig {
49 /// Read buffer capacity. This buffer is eagerly allocated and used for receiving
50 /// messages.
51 ///
52 /// For high read load scenarios a larger buffer, e.g. 128 KiB, improves performance.
53 ///
54 /// For scenarios where you expect a lot of connections and don't need high read load
55 /// performance a smaller buffer, e.g. 4 KiB, would be appropriate to lower total
56 /// memory usage.
57 ///
58 /// The default value is 128 KiB.
59 pub read_buffer_size: usize,
60 /// The target minimum size of the write buffer to reach before writing the data
61 /// to the underlying stream.
62 /// The default value is 128 KiB.
63 ///
64 /// If set to `0` each message will be eagerly written to the underlying stream.
65 /// It is often more optimal to allow them to buffer a little, hence the default value.
66 ///
67 /// Note: [`flush`](WebSocket::flush) will always fully write the buffer regardless.
68 pub write_buffer_size: usize,
69 /// The max size of the write buffer in bytes. Setting this can provide backpressure
70 /// in the case the write buffer is filling up due to write errors.
71 /// The default value is unlimited.
72 ///
73 /// Note: The write buffer only builds up past [`write_buffer_size`](Self::write_buffer_size)
74 /// when writes to the underlying stream are failing. So the **write buffer can not
75 /// fill up if you are not observing write errors even if not flushing**.
76 ///
77 /// Note: Should always be at least [`write_buffer_size + 1 message`](Self::write_buffer_size)
78 /// and probably a little more depending on error handling strategy.
79 pub max_write_buffer_size: usize,
80 /// The maximum size of an incoming message. `None` means no size limit. The default value is 64 MiB
81 /// which should be reasonably big for all normal use-cases but small enough to prevent
82 /// memory eating by a malicious user.
83 pub max_message_size: Option<usize>,
84 /// The maximum size of a single incoming message frame. `None` means no size limit. The limit is for
85 /// frame payload NOT including the frame header. The default value is 16 MiB which should
86 /// be reasonably big for all normal use-cases but small enough to prevent memory eating
87 /// by a malicious user.
88 pub max_frame_size: Option<usize>,
89 /// When set to `true`, the server will accept and handle unmasked frames
90 /// from the client. According to the RFC 6455, the server must close the
91 /// connection to the client in such cases, however it seems like there are
92 /// some popular libraries that are sending unmasked frames, ignoring the RFC.
93 /// By default this option is set to `false`, i.e. according to RFC 6455.
94 pub accept_unmasked_frames: bool,
95 /// Configuration for optional extensions to the base websocket protocol.
96 ///
97 /// Some extensions may require optional features to be enabled at build
98 /// time to be supported.
99 pub extensions: ExtensionsConfig,
100}
101
102impl Default for WebSocketConfig {
103 fn default() -> Self {
104 Self {
105 read_buffer_size: 128 * 1024,
106 write_buffer_size: 128 * 1024,
107 max_write_buffer_size: usize::MAX,
108 max_message_size: Some(64 << 20),
109 max_frame_size: Some(16 << 20),
110 accept_unmasked_frames: false,
111 extensions: ExtensionsConfig::default(),
112 }
113 }
114}
115
116impl WebSocketConfig {
117 /// Set [`Self::read_buffer_size`].
118 pub fn read_buffer_size(mut self, read_buffer_size: usize) -> Self {
119 self.read_buffer_size = read_buffer_size;
120 self
121 }
122
123 /// Set [`Self::write_buffer_size`].
124 pub fn write_buffer_size(mut self, write_buffer_size: usize) -> Self {
125 self.write_buffer_size = write_buffer_size;
126 self
127 }
128
129 /// Set [`Self::max_write_buffer_size`].
130 pub fn max_write_buffer_size(mut self, max_write_buffer_size: usize) -> Self {
131 self.max_write_buffer_size = max_write_buffer_size;
132 self
133 }
134
135 /// Set [`Self::max_message_size`].
136 pub fn max_message_size(mut self, max_message_size: Option<usize>) -> Self {
137 self.max_message_size = max_message_size;
138 self
139 }
140
141 /// Set [`Self::max_frame_size`].
142 pub fn max_frame_size(mut self, max_frame_size: Option<usize>) -> Self {
143 self.max_frame_size = max_frame_size;
144 self
145 }
146
147 /// Set [`Self::accept_unmasked_frames`].
148 pub fn accept_unmasked_frames(mut self, accept_unmasked_frames: bool) -> Self {
149 self.accept_unmasked_frames = accept_unmasked_frames;
150 self
151 }
152
153 /// Panic if values are invalid.
154 pub(crate) fn assert_valid(&self) {
155 assert!(
156 self.max_write_buffer_size > self.write_buffer_size,
157 "WebSocketConfig::max_write_buffer_size must be greater than write_buffer_size, \
158 see WebSocketConfig docs`"
159 );
160 }
161}
162
163/// WebSocket input-output stream.
164///
165/// This is THE structure you want to create to be able to speak the WebSocket protocol.
166/// It may be created by calling `connect`, `accept` or `client` functions.
167///
168/// Use [`WebSocket::read`], [`WebSocket::send`] to received and send messages.
169#[derive(Debug)]
170pub struct WebSocket<Stream> {
171 /// The underlying socket.
172 socket: Stream,
173 /// The context for managing a WebSocket.
174 context: WebSocketContext,
175}
176
177impl<Stream> WebSocket<Stream> {
178 /// Convert a raw socket into a WebSocket without performing a handshake.
179 ///
180 /// Call this function if you're using Tungstenite as a part of a web framework
181 /// or together with an existing one. If you need an initial handshake, use
182 /// `connect()` or `accept()` functions of the crate to construct a websocket.
183 ///
184 /// # Panics
185 /// Panics if config is invalid e.g. `max_write_buffer_size <= write_buffer_size`.
186 pub fn from_raw_socket(stream: Stream, role: Role, config: Option<WebSocketConfig>) -> Self {
187 WebSocket { socket: stream, context: WebSocketContext::new(role, config) }
188 }
189
190 /// Convert a raw socket into a WebSocket without performing a handshake.
191 pub fn from_raw_socket_with_extensions(
192 stream: Stream,
193 role: Role,
194 config: Option<WebSocketConfig>,
195 extensions: Extensions,
196 ) -> Self {
197 let mut context = WebSocketContext::new(role, config);
198 context.extensions = extensions;
199 WebSocket { socket: stream, context }
200 }
201
202 /// Convert a raw socket into a WebSocket without performing a handshake.
203 ///
204 /// Call this function if you're using Tungstenite as a part of a web framework
205 /// or together with an existing one. If you need an initial handshake, use
206 /// `connect()` or `accept()` functions of the crate to construct a websocket.
207 ///
208 /// # Panics
209 /// Panics if config is invalid e.g. `max_write_buffer_size <= write_buffer_size`.
210 pub fn from_partially_read(
211 stream: Stream,
212 part: Vec<u8>,
213 role: Role,
214 config: Option<WebSocketConfig>,
215 ) -> Self {
216 Self::from_partially_read_with_extensions(stream, part, role, config, Extensions::default())
217 }
218
219 pub(crate) fn from_partially_read_with_extensions(
220 stream: Stream,
221 part: Vec<u8>,
222 role: Role,
223 config: Option<WebSocketConfig>,
224 extensions: Extensions,
225 ) -> Self {
226 WebSocket {
227 socket: stream,
228 context: WebSocketContext::from_partially_read_with_extensions(
229 part, role, config, extensions,
230 ),
231 }
232 }
233
234 /// Consumes the `WebSocket` and returns the underlying stream.
235 pub fn into_inner(self) -> Stream {
236 self.socket
237 }
238
239 /// Returns a shared reference to the inner stream.
240 pub fn get_ref(&self) -> &Stream {
241 &self.socket
242 }
243 /// Returns a mutable reference to the inner stream.
244 pub fn get_mut(&mut self) -> &mut Stream {
245 &mut self.socket
246 }
247
248 /// Change the configuration.
249 ///
250 /// # Panics
251 /// Panics if config is invalid e.g. `max_write_buffer_size <= write_buffer_size`.
252 pub fn set_config(&mut self, set_func: impl FnOnce(&mut WebSocketConfig)) {
253 self.context.set_config(set_func);
254 }
255
256 /// Read the configuration.
257 pub fn get_config(&self) -> &WebSocketConfig {
258 self.context.get_config()
259 }
260
261 /// Check if it is possible to read messages.
262 ///
263 /// Reading is impossible after receiving `Message::Close`. It is still possible after
264 /// sending close frame since the peer still may send some data before confirming close.
265 pub fn can_read(&self) -> bool {
266 self.context.can_read()
267 }
268
269 /// Check if it is possible to write messages.
270 ///
271 /// Writing gets impossible immediately after sending or receiving `Message::Close`.
272 pub fn can_write(&self) -> bool {
273 self.context.can_write()
274 }
275}
276
277impl<Stream: Read + Write> WebSocket<Stream> {
278 /// Read a message from stream, if possible.
279 ///
280 /// This will also queue responses to ping and close messages. These responses
281 /// will be written and flushed on the next call to [`read`](Self::read),
282 /// [`write`](Self::write) or [`flush`](Self::flush).
283 ///
284 /// # Closing the connection
285 /// When the remote endpoint decides to close the connection this will return
286 /// the close message with an optional close frame.
287 ///
288 /// You should continue calling [`read`](Self::read), [`write`](Self::write) or
289 /// [`flush`](Self::flush) to drive the reply to the close frame until [`Error::ConnectionClosed`]
290 /// is returned. Once that happens it is safe to drop the underlying connection.
291 pub fn read(&mut self) -> Result<Message> {
292 self.context.read(&mut self.socket)
293 }
294
295 /// Writes and immediately flushes a message.
296 /// Equivalent to calling [`write`](Self::write) then [`flush`](Self::flush).
297 pub fn send(&mut self, message: Message) -> Result<()> {
298 self.write(message)?;
299 self.flush()
300 }
301
302 /// Write a message to the provided stream, if possible.
303 ///
304 /// A subsequent call should be made to [`flush`](Self::flush) to flush writes.
305 ///
306 /// In the event of stream write failure the message frame will be stored
307 /// in the write buffer and will try again on the next call to [`write`](Self::write)
308 /// or [`flush`](Self::flush).
309 ///
310 /// If the write buffer would exceed the configured [`WebSocketConfig::max_write_buffer_size`]
311 /// [`Err(WriteBufferFull(msg_frame))`](Error::WriteBufferFull) is returned.
312 ///
313 /// This call will generally not flush. However, if there are queued automatic messages
314 /// they will be written and eagerly flushed.
315 ///
316 /// For example, upon receiving ping messages tungstenite queues pong replies automatically.
317 /// The next call to [`read`](Self::read), [`write`](Self::write) or [`flush`](Self::flush)
318 /// will write & flush the pong reply. This means you should not respond to ping frames manually.
319 ///
320 /// You can however send pong frames manually in order to indicate a unidirectional heartbeat
321 /// as described in [RFC 6455](https://tools.ietf.org/html/rfc6455#section-5.5.3). Note that
322 /// if [`read`](Self::read) returns a ping, you should [`flush`](Self::flush) before passing
323 /// a custom pong to [`write`](Self::write), otherwise the automatic queued response to the
324 /// ping will not be sent as it will be replaced by your custom pong message.
325 ///
326 /// # Errors
327 /// - If the WebSocket's write buffer is full, [`Error::WriteBufferFull`] will be returned
328 /// along with the equivalent passed message frame.
329 /// - If the connection is closed and should be dropped, this will return [`Error::ConnectionClosed`].
330 /// - If you try again after [`Error::ConnectionClosed`] was returned either from here or from
331 /// [`read`](Self::read), [`Error::AlreadyClosed`] will be returned. This indicates a program
332 /// error on your part.
333 /// - [`Error::Io`] is returned if the underlying connection returns an error
334 /// (consider these fatal except for WouldBlock).
335 /// - [`Error::Capacity`] if your message size is bigger than the configured max message size.
336 pub fn write(&mut self, message: Message) -> Result<()> {
337 self.context.write(&mut self.socket, message)
338 }
339
340 /// Flush writes.
341 ///
342 /// Ensures all messages previously passed to [`write`](Self::write) and automatic
343 /// queued pong responses are written & flushed into the underlying stream.
344 pub fn flush(&mut self) -> Result<()> {
345 self.context.flush(&mut self.socket)
346 }
347
348 /// Close the connection.
349 ///
350 /// This function guarantees that the close frame will be queued.
351 /// There is no need to call it again. Calling this function is
352 /// the same as calling `write(Message::Close(..))`.
353 ///
354 /// After queuing the close frame you should continue calling [`read`](Self::read) or
355 /// [`flush`](Self::flush) to drive the close handshake to completion.
356 ///
357 /// The websocket RFC defines that the underlying connection should be closed
358 /// by the server. Tungstenite takes care of this asymmetry for you.
359 ///
360 /// When the close handshake is finished (we have both sent and received
361 /// a close message), [`read`](Self::read) or [`flush`](Self::flush) will return
362 /// [Error::ConnectionClosed] if this endpoint is the server.
363 ///
364 /// If this endpoint is a client, [Error::ConnectionClosed] will only be
365 /// returned after the server has closed the underlying connection.
366 ///
367 /// It is thus safe to drop the underlying connection as soon as [Error::ConnectionClosed]
368 /// is returned from [`read`](Self::read) or [`flush`](Self::flush).
369 pub fn close(&mut self, code: Option<CloseFrame>) -> Result<()> {
370 self.context.close(&mut self.socket, code)
371 }
372
373 /// Old name for [`read`](Self::read).
374 #[deprecated(note = "Use `read`")]
375 pub fn read_message(&mut self) -> Result<Message> {
376 self.read()
377 }
378
379 /// Old name for [`send`](Self::send).
380 #[deprecated(note = "Use `send`")]
381 pub fn write_message(&mut self, message: Message) -> Result<()> {
382 self.send(message)
383 }
384
385 /// Old name for [`flush`](Self::flush).
386 #[deprecated(note = "Use `flush`")]
387 pub fn write_pending(&mut self) -> Result<()> {
388 self.flush()
389 }
390}
391
392/// A context for managing WebSocket stream.
393#[derive(Debug)]
394pub struct WebSocketContext {
395 /// Server or client?
396 role: Role,
397 /// encoder/decoder of frame.
398 frame: FrameCodec,
399 /// The state of processing, either "active" or "closing".
400 state: WebSocketState,
401 /// Receive: an incomplete message being processed.
402 incomplete: Option<IncompleteMessage>,
403 /// Send in addition to regular messages E.g. "pong" or "close".
404 additional_send: Option<Frame>,
405 /// True indicates there is an additional message (like a pong)
406 /// that failed to flush previously and we should try again.
407 unflushed_additional: bool,
408 /// The configuration for the websocket session.
409 config: WebSocketConfig,
410 // Container for extensions.
411 extensions: Extensions,
412}
413
414impl WebSocketContext {
415 /// Create a WebSocket context that manages a post-handshake stream.
416 ///
417 /// # Panics
418 /// Panics if config is invalid e.g. `max_write_buffer_size <= write_buffer_size`.
419 pub fn new(role: Role, config: Option<WebSocketConfig>) -> Self {
420 let conf = config.unwrap_or_default();
421 Self::_new(
422 role,
423 FrameCodec::new(conf.read_buffer_size),
424 conf,
425 conf.extensions.into_unnegotiated_context(role),
426 )
427 }
428
429 /// Create a WebSocket context that manages an post-handshake stream.
430 ///
431 /// # Panics
432 /// Panics if config is invalid e.g. `max_write_buffer_size <= write_buffer_size`.
433 pub fn from_partially_read(part: Vec<u8>, role: Role, config: Option<WebSocketConfig>) -> Self {
434 let conf = config.unwrap_or_default();
435 let extensions = conf.extensions.into_unnegotiated_context(role);
436 Self::_new(
437 role,
438 FrameCodec::from_partially_read(part, conf.read_buffer_size),
439 conf,
440 extensions,
441 )
442 }
443
444 /// Create a WebSocket context for a post-handshake stream with the enabled extensions.
445 ///
446 /// Where [`WebSocketContext::from_partially_read`] infers the enabled
447 /// extensions from the [`WebSocketConfig`], this allows the caller to
448 /// explicitly sets the extensions in use for the connection.
449 pub(crate) fn from_partially_read_with_extensions(
450 part: Vec<u8>,
451 role: Role,
452 config: Option<WebSocketConfig>,
453 extensions: Extensions,
454 ) -> Self {
455 let conf = config.unwrap_or_default();
456 Self::_new(
457 role,
458 FrameCodec::from_partially_read(part, conf.read_buffer_size),
459 conf,
460 extensions,
461 )
462 }
463
464 fn _new(
465 role: Role,
466 mut frame: FrameCodec,
467 config: WebSocketConfig,
468 extensions: Extensions,
469 ) -> Self {
470 config.assert_valid();
471 frame.set_max_out_buffer_len(config.max_write_buffer_size);
472 frame.set_out_buffer_write_len(config.write_buffer_size);
473 Self {
474 role,
475 frame,
476 state: WebSocketState::Active,
477 incomplete: None,
478 additional_send: None,
479 unflushed_additional: false,
480 config,
481 extensions,
482 }
483 }
484
485 /// Change the configuration.
486 ///
487 /// # Panics
488 /// Panics if config is invalid e.g. `max_write_buffer_size <= write_buffer_size`.
489 pub fn set_config(&mut self, set_func: impl FnOnce(&mut WebSocketConfig)) {
490 set_func(&mut self.config);
491 self.config.assert_valid();
492 self.frame.set_max_out_buffer_len(self.config.max_write_buffer_size);
493 self.frame.set_out_buffer_write_len(self.config.write_buffer_size);
494 }
495
496 /// Read the configuration.
497 pub fn get_config(&self) -> &WebSocketConfig {
498 &self.config
499 }
500
501 /// Check if it is possible to read messages.
502 ///
503 /// Reading is impossible after receiving `Message::Close`. It is still possible after
504 /// sending close frame since the peer still may send some data before confirming close.
505 pub fn can_read(&self) -> bool {
506 self.state.can_read()
507 }
508
509 /// Check if it is possible to write messages.
510 ///
511 /// Writing gets impossible immediately after sending or receiving `Message::Close`.
512 pub fn can_write(&self) -> bool {
513 self.state.is_active()
514 }
515
516 /// Read a message from the provided stream, if possible.
517 ///
518 /// This function sends pong and close responses automatically.
519 /// However, it never blocks on write.
520 pub fn read<Stream>(&mut self, stream: &mut Stream) -> Result<Message>
521 where
522 Stream: Read + Write,
523 {
524 // Do not read from already closed connections.
525 self.state.check_not_terminated()?;
526
527 loop {
528 if self.additional_send.is_some() || self.unflushed_additional {
529 // Since we may get ping or close, we need to reply to the messages even during read.
530 match self.flush(stream) {
531 Ok(_) => {}
532 Err(Error::Io(err)) if err.kind() == io::ErrorKind::WouldBlock => {
533 // If blocked continue reading, but try again later
534 self.unflushed_additional = true;
535 }
536 Err(err) => return Err(err),
537 }
538 } else if self.role == Role::Server && !self.state.can_read() {
539 self.state = WebSocketState::Terminated;
540 return Err(Error::ConnectionClosed);
541 }
542
543 // If we get here, either write blocks or we have nothing to write.
544 // Thus if read blocks, just let it return WouldBlock.
545 if let Some(message) = self.read_message_frame(stream)? {
546 trace!("Received message {message}");
547 return Ok(message);
548 }
549 }
550 }
551
552 /// Write a message to the provided stream.
553 ///
554 /// A subsequent call should be made to [`flush`](Self::flush) to flush writes.
555 ///
556 /// In the event of stream write failure the message frame will be stored
557 /// in the write buffer and will try again on the next call to [`write`](Self::write)
558 /// or [`flush`](Self::flush).
559 ///
560 /// If the write buffer would exceed the configured [`WebSocketConfig::max_write_buffer_size`]
561 /// [`Err(WriteBufferFull(msg_frame))`](Error::WriteBufferFull) is returned.
562 pub fn write<Stream>(&mut self, stream: &mut Stream, message: Message) -> Result<()>
563 where
564 Stream: Read + Write,
565 {
566 // When terminated, return AlreadyClosed.
567 self.state.check_not_terminated()?;
568
569 // Do not write after sending a close frame.
570 if !self.state.is_active() {
571 return Err(Error::Protocol(ProtocolError::SendAfterClosing));
572 }
573
574 let mut prepare_data_frame = |data, opdata| -> Result<Frame, ProtocolError> {
575 const IS_FINAL: bool = true;
576 if let Some(compressor) = self.extensions.per_message_compressor() {
577 let compressed = compressor(&data)?;
578 return Ok(Frame::compressed_message(compressed, opdata, IS_FINAL));
579 }
580 Ok(Frame::message(data, OpCode::Data(opdata), IS_FINAL))
581 };
582
583 let frame = match message {
584 Message::Text(data) => prepare_data_frame(data.into(), OpData::Text)?,
585 Message::Binary(data) => prepare_data_frame(data, OpData::Binary)?,
586 Message::Ping(data) => Frame::ping(data),
587 Message::Pong(data) => {
588 self.set_additional(Frame::pong(data));
589 // Note: user pongs can be user flushed so no need to flush here
590 return self._write(stream, None).map(|_| ());
591 }
592 Message::Close(code) => return self.close(stream, code),
593 Message::Frame(f) => f,
594 };
595
596 let should_flush = self._write(stream, Some(frame))?;
597 if should_flush {
598 self.flush(stream)?;
599 }
600 Ok(())
601 }
602
603 /// Flush writes.
604 ///
605 /// Ensures all messages previously passed to [`write`](Self::write) and automatically
606 /// queued pong responses are written & flushed into the `stream`.
607 #[inline]
608 pub fn flush<Stream>(&mut self, stream: &mut Stream) -> Result<()>
609 where
610 Stream: Read + Write,
611 {
612 self._write(stream, None)?;
613 self.frame.write_out_buffer(stream)?;
614 stream.flush()?;
615 self.unflushed_additional = false;
616 Ok(())
617 }
618
619 /// Writes any data in the out_buffer, `additional_send` and given `data`.
620 ///
621 /// Does **not** flush.
622 ///
623 /// Returns true if the write contents indicate we should flush immediately.
624 fn _write<Stream>(&mut self, stream: &mut Stream, data: Option<Frame>) -> Result<bool>
625 where
626 Stream: Read + Write,
627 {
628 if let Some(data) = data {
629 self.buffer_frame(stream, data)?;
630 }
631
632 // Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in
633 // response, unless it already received a Close frame. It SHOULD
634 // respond with Pong frame as soon as is practical. (RFC 6455)
635 let should_flush = if let Some(msg) = self.additional_send.take() {
636 trace!("Sending pong/close");
637 match self.buffer_frame(stream, msg) {
638 Err(Error::WriteBufferFull(msg)) => {
639 // if an system message would exceed the buffer put it back in
640 // `additional_send` for retry. Otherwise returning this error
641 // may not make sense to the user, e.g. calling `flush`.
642 if let Message::Frame(msg) = *msg {
643 self.set_additional(msg);
644 false
645 } else {
646 unreachable!()
647 }
648 }
649 Err(err) => return Err(err),
650 Ok(_) => true,
651 }
652 } else {
653 self.unflushed_additional
654 };
655
656 // If we're closing and there is nothing to send anymore, we should close the connection.
657 if self.role == Role::Server && !self.state.can_read() {
658 // The underlying TCP connection, in most normal cases, SHOULD be closed
659 // first by the server, so that it holds the TIME_WAIT state and not the
660 // client (as this would prevent it from re-opening the connection for 2
661 // maximum segment lifetimes (2MSL), while there is no corresponding
662 // server impact as a TIME_WAIT connection is immediately reopened upon
663 // a new SYN with a higher seq number). (RFC 6455)
664 self.frame.write_out_buffer(stream)?;
665 self.state = WebSocketState::Terminated;
666 Err(Error::ConnectionClosed)
667 } else {
668 Ok(should_flush)
669 }
670 }
671
672 /// Close the connection.
673 ///
674 /// This function guarantees that the close frame will be queued.
675 /// There is no need to call it again. Calling this function is
676 /// the same as calling `send(Message::Close(..))`.
677 pub fn close<Stream>(&mut self, stream: &mut Stream, code: Option<CloseFrame>) -> Result<()>
678 where
679 Stream: Read + Write,
680 {
681 if let WebSocketState::Active = self.state {
682 self.state = WebSocketState::ClosedByUs;
683 let frame = Frame::close(code);
684 self._write(stream, Some(frame))?;
685 }
686 self.flush(stream)
687 }
688
689 /// Try to decode one message frame. May return None.
690 fn read_message_frame(&mut self, stream: &mut impl Read) -> Result<Option<Message>> {
691 let frame = match self
692 .frame
693 .read_frame(
694 stream,
695 self.config.max_frame_size,
696 matches!(self.role, Role::Server),
697 self.config.accept_unmasked_frames,
698 )
699 .check_connection_reset(self.state)?
700 {
701 None => {
702 // Connection closed by peer
703 return match replace(&mut self.state, WebSocketState::Terminated) {
704 WebSocketState::ClosedByPeer | WebSocketState::CloseAcknowledged => {
705 Err(Error::ConnectionClosed)
706 }
707 _ => Err(Error::Protocol(ProtocolError::ResetWithoutClosingHandshake)),
708 };
709 }
710 Some(frame) => frame,
711 };
712
713 if !self.state.can_read() {
714 return Err(Error::Protocol(ProtocolError::ReceivedAfterClosing));
715 }
716
717 let (is_compressed, decompressor) = {
718 let decompressor = self.extensions.per_message_decompressor();
719 let hdr = frame.header();
720 // Per RFC 6455, the RSV1, RSV2, and RSV3 bits
721 //
722 // MUST be 0 unless an extension is negotiated that defines
723 // meanings for non-zero values. If a nonzero value is
724 // received and none of the negotiated extensions defines the
725 // meaning of such a nonzero value, the receiving endpoint
726 // MUST _Fail the WebSocket Connection_.
727 //
728 // Per RFC 7692:
729 //
730 // This document allocates the RSV1 bit of the WebSocket
731 // header for PMCEs and calls the bit the "Per-Message
732 // Compressed" bit. On a WebSocket connection where a PMCE is
733 // in use, this bit indicates whether a message is compressed
734 // or not.
735 if (hdr.rsv1 && decompressor.is_none()) || hdr.rsv2 || hdr.rsv3 {
736 return Err(Error::Protocol(ProtocolError::NonZeroReservedBits));
737 }
738
739 let decompressor_with_size_limit = decompressor.map(|mut f| {
740 let incomplete_len =
741 self.incomplete.as_ref().map(IncompleteMessage::len).unwrap_or(0);
742 let message_max = self.config.max_message_size.unwrap_or(usize::MAX);
743
744 move |bytes, is_final| {
745 let decompress_limit = message_max.saturating_sub(incomplete_len);
746
747 f(bytes, is_final, decompress_limit).map_err(|e| match e {
748 DecompressionError::SizeLimitReached => {
749 Error::Capacity(CapacityError::MessageTooLong {
750 size: incomplete_len.saturating_add(decompress_limit),
751 max_size: message_max,
752 })
753 }
754 DecompressionError::Decompression(e) => {
755 Error::Protocol(ProtocolError::CompressionFailure(e))
756 }
757 })
758 }
759 });
760
761 (hdr.rsv1, decompressor_with_size_limit)
762 };
763
764 if self.role == Role::Client && frame.is_masked() {
765 // A client MUST close a connection if it detects a masked frame. (RFC 6455)
766 return Err(Error::Protocol(ProtocolError::MaskedFrameFromServer));
767 }
768
769 match frame.header().opcode {
770 OpCode::Control(ctl) => {
771 drop(decompressor);
772 match ctl {
773 // All control frames MUST have a payload length of 125 bytes or less
774 // and MUST NOT be fragmented. (RFC 6455)
775 _ if !frame.header().is_final => {
776 Err(Error::Protocol(ProtocolError::FragmentedControlFrame))
777 }
778 _ if frame.payload().len() > 125 => {
779 Err(Error::Protocol(ProtocolError::ControlFrameTooBig))
780 }
781 // Per RFC 7692:
782 //
783 // An endpoint MUST NOT set the "Per-Message
784 // Compressed" bit of control frames and non-first
785 // fragments of a data message. An endpoint receiving
786 // such a frame MUST _Fail the WebSocket Connection_.
787 _ if is_compressed => {
788 Err(Error::Protocol(ProtocolError::CompressedControlFrame))
789 }
790 OpCtl::Close => Ok(self.do_close(frame.into_close()?).map(Message::Close)),
791 OpCtl::Reserved(i) => {
792 Err(Error::Protocol(ProtocolError::UnknownControlFrameType(i)))
793 }
794 OpCtl::Ping => {
795 let data = frame.into_payload();
796 // No ping processing after we sent a close frame.
797 if self.state.is_active() {
798 self.set_additional(Frame::pong(data.clone()));
799 }
800 Ok(Some(Message::Ping(data)))
801 }
802 OpCtl::Pong => Ok(Some(Message::Pong(frame.into_payload()))),
803 }
804 }
805
806 OpCode::Data(data) => {
807 let fin = frame.header().is_final;
808 let payload = frame.into_payload();
809
810 let decompressor = match data {
811 OpData::Continue => {
812 // Per RFC 7692:
813 //
814 // An endpoint MUST NOT set the "Per-Message
815 // Compressed" bit of control frames and non-first
816 // fragments of a data message. An endpoint receiving
817 // such a frame MUST _Fail the WebSocket Connection_.
818 if is_compressed {
819 return Err(Error::Protocol(ProtocolError::CompressedContinueFrame));
820 }
821
822 let incomplete_compressed =
823 self.incomplete.as_ref().map_or(false, IncompleteMessage::compressed);
824 match (incomplete_compressed, &decompressor) {
825 (false, _) => None,
826 (true, Some(_)) => decompressor,
827 (true, None) => {
828 // This is a continuation frame that was
829 // received with compression disabled, but the
830 // initial frame of the message was received
831 // with compression *enabled* and RSV1 set.
832 //
833 // The only way to get here is to manually
834 // disable compression for a stream after it's
835 // been established, which is arguably operator
836 // error. This is incorrect enough that it's
837 // not worth spending a lot of code on, but it's
838 // better to return an error here than crash.
839 log::debug!("compression was disabled between receiving frames");
840 return Err(Error::Protocol(
841 ProtocolError::CompressedContinueFrame,
842 ));
843 }
844 }
845 }
846 OpData::Text | OpData::Binary => decompressor.filter(|_| is_compressed),
847 OpData::Reserved(_) => None,
848 };
849 let payload = decompressor
850 .map(|mut decompressor| decompressor(&payload, fin))
851 .transpose()?
852 .unwrap_or(payload);
853
854 let payload = match (data, self.incomplete.as_mut()) {
855 (OpData::Continue, None) => Err(ProtocolError::UnexpectedContinueFrame),
856 (OpData::Continue, Some(incomplete)) => {
857 incomplete.extend(payload, self.config.max_message_size)?;
858 Ok(None)
859 }
860 (_, Some(_)) => Err(ProtocolError::ExpectedFragment(data)),
861 (OpData::Text, _) => Ok(Some((payload, MessageType::Text))),
862 (OpData::Binary, _) => Ok(Some((payload, MessageType::Binary))),
863 (OpData::Reserved(i), _) => Err(ProtocolError::UnknownDataFrameType(i)),
864 }?;
865
866 match (payload, fin) {
867 (None, true) => Ok(Some(self.incomplete.take().unwrap().complete()?)),
868 (None, false) => Ok(None),
869 (Some((payload, t)), true) => {
870 check_max_size(payload.len(), self.config.max_message_size)?;
871 match t {
872 MessageType::Text => Ok(Some(Message::Text(payload.try_into()?))),
873 MessageType::Binary => Ok(Some(Message::Binary(payload))),
874 }
875 }
876 (Some((payload, t)), false) => {
877 let mut incomplete = match is_compressed {
878 #[cfg(feature = "deflate")]
879 true => IncompleteMessage::new_compressed(t),
880 _ => IncompleteMessage::new(t),
881 };
882 incomplete.extend(payload, self.config.max_message_size)?;
883 self.incomplete = Some(incomplete);
884 Ok(None)
885 }
886 }
887 }
888 } // match opcode
889 }
890
891 /// Received a close frame. Tells if we need to return a close frame to the user.
892 #[allow(clippy::option_option)]
893 fn do_close(&mut self, close: Option<CloseFrame>) -> Option<Option<CloseFrame>> {
894 debug!("Received close frame: {close:?}");
895 match self.state {
896 WebSocketState::Active => {
897 self.state = WebSocketState::ClosedByPeer;
898
899 let close = close.map(|frame| {
900 if !frame.code.is_allowed() {
901 CloseFrame {
902 code: CloseCode::Protocol,
903 reason: Utf8Bytes::from_static("Protocol violation"),
904 }
905 } else {
906 frame
907 }
908 });
909
910 let reply = Frame::close(close.clone());
911 debug!("Replying to close with {reply:?}");
912 self.set_additional(reply);
913
914 Some(close)
915 }
916 WebSocketState::ClosedByPeer | WebSocketState::CloseAcknowledged => {
917 // It is already closed, just ignore.
918 None
919 }
920 WebSocketState::ClosedByUs => {
921 // We received a reply.
922 self.state = WebSocketState::CloseAcknowledged;
923 Some(close)
924 }
925 WebSocketState::Terminated => unreachable!(),
926 }
927 }
928
929 /// Write a single frame into the write-buffer.
930 fn buffer_frame<Stream>(&mut self, stream: &mut Stream, mut frame: Frame) -> Result<()>
931 where
932 Stream: Read + Write,
933 {
934 match self.role {
935 Role::Server => {}
936 Role::Client => {
937 // 5. If the data is being sent by the client, the frame(s) MUST be
938 // masked as defined in Section 5.3. (RFC 6455)
939 frame.set_random_mask();
940 }
941 }
942
943 trace!("Sending frame: {frame:?}");
944 self.frame.buffer_frame(stream, frame).check_connection_reset(self.state)
945 }
946
947 /// Replace `additional_send` if it is currently a `Pong` message.
948 fn set_additional(&mut self, add: Frame) {
949 let empty_or_pong = self
950 .additional_send
951 .as_ref()
952 .map_or(true, |f| f.header().opcode == OpCode::Control(OpCtl::Pong));
953 if empty_or_pong {
954 self.additional_send.replace(add);
955 }
956 }
957}
958
959fn check_max_size(size: usize, max_size: Option<usize>) -> crate::Result<()> {
960 if let Some(max_size) = max_size {
961 if size > max_size {
962 return Err(Error::Capacity(CapacityError::MessageTooLong { size, max_size }));
963 }
964 }
965 Ok(())
966}
967
968/// The current connection state.
969#[derive(Debug, PartialEq, Eq, Clone, Copy)]
970enum WebSocketState {
971 /// The connection is active.
972 Active,
973 /// We initiated a close handshake.
974 ClosedByUs,
975 /// The peer initiated a close handshake.
976 ClosedByPeer,
977 /// The peer replied to our close handshake.
978 CloseAcknowledged,
979 /// The connection does not exist anymore.
980 Terminated,
981}
982
983impl WebSocketState {
984 /// Tell if we're allowed to process normal messages.
985 fn is_active(self) -> bool {
986 matches!(self, WebSocketState::Active)
987 }
988
989 /// Tell if we should process incoming data. Note that if we send a close frame
990 /// but the remote hasn't confirmed, they might have sent data before they receive our
991 /// close frame, so we should still pass those to client code, hence ClosedByUs is valid.
992 fn can_read(self) -> bool {
993 matches!(self, WebSocketState::Active | WebSocketState::ClosedByUs)
994 }
995
996 /// Check if the state is active, return error if not.
997 fn check_not_terminated(self) -> Result<()> {
998 match self {
999 WebSocketState::Terminated => Err(Error::AlreadyClosed),
1000 _ => Ok(()),
1001 }
1002 }
1003}
1004
1005/// Translate "Connection reset by peer" into `ConnectionClosed` if appropriate.
1006trait CheckConnectionReset {
1007 fn check_connection_reset(self, state: WebSocketState) -> Self;
1008}
1009
1010impl<T> CheckConnectionReset for Result<T> {
1011 fn check_connection_reset(self, state: WebSocketState) -> Self {
1012 match self {
1013 Err(Error::Io(io_error)) => Err({
1014 if !state.can_read() && io_error.kind() == io::ErrorKind::ConnectionReset {
1015 Error::ConnectionClosed
1016 } else {
1017 Error::Io(io_error)
1018 }
1019 }),
1020 x => x,
1021 }
1022 }
1023}
1024
1025#[cfg(test)]
1026mod tests {
1027 use super::{Message, Role, WebSocket, WebSocketConfig};
1028 use crate::error::{CapacityError, Error};
1029 use crate::extensions::ExtensionsConfig;
1030
1031 use std::{io, io::Cursor};
1032
1033 struct WriteMoc<Stream>(Stream);
1034
1035 impl<Stream> io::Write for WriteMoc<Stream> {
1036 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1037 Ok(buf.len())
1038 }
1039 fn flush(&mut self) -> io::Result<()> {
1040 Ok(())
1041 }
1042 }
1043
1044 impl<Stream: io::Read> io::Read for WriteMoc<Stream> {
1045 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
1046 self.0.read(buf)
1047 }
1048 }
1049
1050 #[test]
1051 fn receive_messages() {
1052 let incoming = Cursor::new(vec![
1053 0x89, 0x02, 0x01, 0x02, 0x8a, 0x01, 0x03, 0x01, 0x07, 0x48, 0x65, 0x6c, 0x6c, 0x6f,
1054 0x2c, 0x20, 0x80, 0x06, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x82, 0x03, 0x01, 0x02,
1055 0x03,
1056 ]);
1057 let mut socket = WebSocket::from_raw_socket(WriteMoc(incoming), Role::Client, None);
1058 assert_eq!(socket.read().unwrap(), Message::Ping(vec![1, 2].into()));
1059 assert_eq!(socket.read().unwrap(), Message::Pong(vec![3].into()));
1060 assert_eq!(socket.read().unwrap(), Message::Text("Hello, World!".into()));
1061 assert_eq!(socket.read().unwrap(), Message::Binary(vec![0x01, 0x02, 0x03].into()));
1062 }
1063
1064 #[test]
1065 fn size_limiting_text_fragmented() {
1066 let incoming = Cursor::new(vec![
1067 0x01, 0x07, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x80, 0x06, 0x57, 0x6f, 0x72,
1068 0x6c, 0x64, 0x21,
1069 ]);
1070 let limit = WebSocketConfig { max_message_size: Some(10), ..WebSocketConfig::default() };
1071 let mut socket = WebSocket::from_raw_socket(WriteMoc(incoming), Role::Client, Some(limit));
1072
1073 assert!(matches!(
1074 socket.read(),
1075 Err(Error::Capacity(CapacityError::MessageTooLong { size: 13, max_size: 10 }))
1076 ));
1077 }
1078
1079 #[test]
1080 fn size_limiting_binary() {
1081 let incoming = Cursor::new(vec![0x82, 0x03, 0x01, 0x02, 0x03]);
1082 let limit = WebSocketConfig { max_message_size: Some(2), ..WebSocketConfig::default() };
1083 let mut socket = WebSocket::from_raw_socket(WriteMoc(incoming), Role::Client, Some(limit));
1084
1085 assert!(matches!(
1086 socket.read(),
1087 Err(Error::Capacity(CapacityError::MessageTooLong { size: 3, max_size: 2 }))
1088 ));
1089 }
1090
1091 #[cfg(feature = "deflate")]
1092 #[test]
1093 fn per_message_deflate_compression() {
1094 // Example frames from RFC 7692 Section 7.2.3.2
1095
1096 use crate::{extensions::compression, protocol::FrameCodec};
1097
1098 let mut stream = Cursor::new(Vec::new());
1099
1100 let config = WebSocketConfig {
1101 extensions: ExtensionsConfig {
1102 permessage_deflate: Some(compression::deflate::DeflateConfig::default()),
1103 },
1104 ..Default::default()
1105 };
1106 let mut socket = WebSocket::from_raw_socket(&mut stream, Role::Client, Some(config));
1107
1108 // The same message sent twice should compress better the second time
1109 // because context takeover is enabled.
1110 socket.write(Message::Text("Hello".into())).unwrap();
1111 socket.write(Message::Text("Hello".into())).unwrap();
1112 socket.flush().unwrap();
1113
1114 let written = stream.into_inner();
1115 let mut codec = FrameCodec::new(written.len());
1116
1117 let mut stream = Cursor::new(written);
1118 let first_frame = codec.read_frame(&mut stream, None, true, false).unwrap().unwrap();
1119 let second_frame = codec.read_frame(&mut stream, None, true, false).unwrap().unwrap();
1120
1121 assert_eq!(
1122 first_frame.payload(),
1123 // First frame payload, from the RFC
1124 &[0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00]
1125 );
1126
1127 assert_eq!(
1128 second_frame.payload(),
1129 // Second frame payload, from the RFC
1130 &[0xf2, 0x00, 0x11, 0x00, 0x00]
1131 );
1132 }
1133
1134 #[cfg(feature = "deflate")]
1135 #[test]
1136 fn per_message_deflate_decompression() {
1137 // Example frames from RFC 7692 Section 7.2.3.2
1138
1139 use crate::extensions::compression::deflate::DeflateConfig;
1140
1141 let incoming =
1142 Cursor::new(&[0x41, 0x03, 0xf2, 0x48, 0xcd, 0x80, 0x04, 0xc9, 0xc9, 0x07, 0x00]);
1143 let config = WebSocketConfig {
1144 extensions: ExtensionsConfig { permessage_deflate: Some(DeflateConfig::default()) },
1145 ..Default::default()
1146 };
1147 let mut socket = WebSocket::from_raw_socket(WriteMoc(incoming), Role::Client, Some(config));
1148
1149 assert_eq!(socket.read().unwrap(), Message::Text("Hello".into()));
1150 }
1151
1152 #[test]
1153 fn per_message_compression_not_recognized() {
1154 // Without the extension configuration, frames with the RSV1 bit set are rejected.
1155
1156 let incoming =
1157 Cursor::new(&[0x41, 0x03, 0xf2, 0x48, 0xcd, 0x80, 0x04, 0xc9, 0xc9, 0x07, 0x00]);
1158 let config =
1159 WebSocketConfig { extensions: ExtensionsConfig::default(), ..Default::default() };
1160 let mut socket = WebSocket::from_raw_socket(WriteMoc(incoming), Role::Client, Some(config));
1161
1162 assert!(matches!(
1163 socket.read().unwrap_err(),
1164 Error::Protocol(crate::error::ProtocolError::NonZeroReservedBits)
1165 ));
1166 }
1167
1168 #[cfg(feature = "deflate")]
1169 #[test]
1170 fn per_message_compression_decompress_respects_message_size_limit() {
1171 use crate::extensions::compression::deflate::test::very_compressed;
1172 use crate::extensions::compression::deflate::DeflateConfig;
1173 use crate::protocol::frame::{
1174 coding::{Data, OpCode},
1175 FrameHeader,
1176 };
1177
1178 let _ = env_logger::try_init();
1179
1180 let base_config = WebSocketConfig {
1181 extensions: ExtensionsConfig {
1182 permessage_deflate: Some(DeflateConfig::default()),
1183 ..Default::default()
1184 },
1185 ..Default::default()
1186 };
1187
1188 fn make_message(frame_count: usize) -> Vec<u8> {
1189 let mut is_first = true;
1190 let mut output = Vec::new();
1191
1192 for (frame, is_final) in very_compressed::make_frames(frame_count) {
1193 let is_first = std::mem::replace(&mut is_first, false);
1194 let header = FrameHeader {
1195 opcode: OpCode::Data(if is_first { Data::Binary } else { Data::Continue }),
1196 rsv1: is_first,
1197 is_final,
1198 ..Default::default()
1199 };
1200 header.format(frame.len() as u64, &mut output).unwrap();
1201 output.extend_from_slice(&frame);
1202 }
1203 output
1204 }
1205
1206 // With the default configuration, a short message of these frames is fine.
1207 {
1208 let input = Cursor::new(make_message(4));
1209 let mut socket =
1210 WebSocket::from_raw_socket(input, Role::Client, Some(base_config.clone()));
1211
1212 let message = socket.read().unwrap();
1213 assert_eq!(
1214 message,
1215 Message::Binary(
1216 bytes::BytesMut::zeroed(4 * very_compressed::DECOMPRESSED_LEN).into()
1217 )
1218 );
1219 }
1220
1221 // The maximum frame size limits on-the-wire frame size, not
1222 // decompressed size, so this still decompresses.
1223 {
1224 let input = Cursor::new(make_message(2));
1225 const MAX_FRAME_SIZE: usize = very_compressed::DECOMPRESSED_LEN - 1;
1226
1227 let mut socket = WebSocket::from_raw_socket(
1228 input,
1229 Role::Client,
1230 Some(base_config.clone().max_frame_size(Some(MAX_FRAME_SIZE))),
1231 );
1232
1233 let message = socket.read().unwrap();
1234 assert_eq!(
1235 message,
1236 Message::Binary(
1237 bytes::BytesMut::zeroed(2 * very_compressed::DECOMPRESSED_LEN).into()
1238 )
1239 );
1240 }
1241
1242 // With a reduced maximum message size, decompressing the whole message
1243 // fails.
1244 {
1245 let input = Cursor::new(make_message(5));
1246 const MAX_MESSAGE_SIZE: usize = 3 * very_compressed::DECOMPRESSED_LEN;
1247
1248 let mut socket = WebSocket::from_raw_socket(
1249 input,
1250 Role::Client,
1251 Some(base_config.clone().max_message_size(Some(MAX_MESSAGE_SIZE))),
1252 );
1253
1254 let error = socket.read().unwrap_err();
1255 assert!(matches!(
1256 error,
1257 Error::Capacity(CapacityError::MessageTooLong {
1258 size: _,
1259 max_size: MAX_MESSAGE_SIZE
1260 })
1261 ));
1262 }
1263 }
1264}