### Server WebSocket Handshake and Communication Source: https://docs.rs/soketto/0.8.1/soketto/index.html Example of setting up a server to listen for incoming TCP connections, perform a WebSocket handshake, and then exchange text or binary data. It demonstrates accepting the client, transitioning to a WebSocket connection, and echoing received data. ```rust use soketto::{handshake::{Server, ClientRequest, server::Response}}; // First, we listen for incoming connections. let listener = tokio::net::TcpListener::bind("...").await?; let mut incoming = TcpListenerStream::new(listener); while let Some(socket) = incoming.next().await { // For each incoming connection we perform a handshake. let mut server = Server::new(socket?.compat()); let websocket_key = { let req = server.receive_request().await?; req.key() }; // Here we accept the client unconditionally. let accept = Response::Accept { key: websocket_key, protocol: None }; server.send_response(&accept).await?; // And we can finally transition to a websocket connection. let (mut sender, mut receiver) = server.into_builder().finish(); let mut data = Vec::new(); let data_type = receiver.receive_data(&mut data).await?; if data_type.is_text() { sender.send_text(std::str::from_utf8(&data)?).await? } else { sender.send_binary(&data).await? } sender.close().await?; } ``` -------------------------------- ### Create a Boxed Integer Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Example of allocating memory on the heap and placing an integer value into it using Box::new. ```rust let five = Box::new(5); ``` -------------------------------- ### Deflate Extension Implementation Source: https://docs.rs/soketto/0.8.1/src/soketto/extension/deflate.rs.html The core structure and initialization logic for the Deflate extension, including parameter setup for client and server modes. ```rust 1// Copyright (c) 2019 Parity Technologies (UK) Ltd. 2// 3// Licensed under the Apache License, Version 2.0 4// or the MIT 5// license , at your 6// option. All files in the project carrying such notice may not be copied, 7// modified, or distributed except according to those terms. 8 9//! Deflate compression extension mostly conformant with [RFC 7692][rfc7692]. 10//! 11//! [rfc7692]: https://tools.ietf.org/html/rfc7692 12 13use crate::{ 14 as_u64, 15 base::{Header, OpCode}, 16 connection::Mode, 17 extension::{Extension, Param}, 18 BoxedError, Storage, 19}; 20use flate2::{write::DeflateDecoder, Compress, Compression, FlushCompress, Status}; 21use std::{ 22 convert::TryInto, 23 io::{self, Write}, 24 mem, 25}; 26 27const SERVER_NO_CONTEXT_TAKEOVER: &str = "server_no_context_takeover"; 28const SERVER_MAX_WINDOW_BITS: &str = "server_max_window_bits"; 29 30const CLIENT_NO_CONTEXT_TAKEOVER: &str = "client_no_context_takeover"; 31const CLIENT_MAX_WINDOW_BITS: &str = "client_max_window_bits"; 32 33/// The deflate extension type. 34/// 35/// The extension does currently not support max. window bits other than the 36/// default, which is 15 and will ask for no context takeover during handshake. 37#[derive(Debug)] 38pub struct Deflate { 39 mode: Mode, 40 enabled: bool, 41 buffer: Vec, 42 params: Vec>, 43 our_max_window_bits: u8, 44 their_max_window_bits: u8, 45 await_last_fragment: bool, 46} 47 48impl Deflate { 49 /// Create a new deflate extension either on client or server side. 50 pub fn new(mode: Mode) -> Self { 51 let params = match mode { 52 Mode::Server => Vec::new(), 53 Mode::Client => { 54 let mut params = Vec::new(); 55 params.push(Param::new(SERVER_NO_CONTEXT_TAKEOVER)); 56 params.push(Param::new(CLIENT_NO_CONTEXT_TAKEOVER)); 57 params.push(Param::new(CLIENT_MAX_WINDOW_BITS)); 58 params 59 } 60 }; 61 Deflate { 62 mode, 63 enabled: false, 64 buffer: Vec::new(), 65 params, 66 our_max_window_bits: 15, 67 their_max_window_bits: 15, 68 await_last_fragment: false, 69 } 70 } ``` -------------------------------- ### Finish Builder and Get Sender/Receiver Source: https://docs.rs/soketto/0.8.1/soketto/connection/struct.Builder.html Completes the configuration and returns a Sender/Receiver pair representing the established WebSocket connection. ```rust pub fn finish(self) -> (Sender, Receiver) ``` -------------------------------- ### Server Handshake and Connection Handling Source: https://docs.rs/soketto/0.8.1/src/soketto/lib.rs.html Illustrates setting up a WebSocket server, listening for incoming connections, and performing the handshake. It shows how to receive requests, send responses, and transition to a WebSocket connection for data exchange. ```rust use tokio_util::compat::TokioAsyncReadCompatExt; use tokio_stream::{wrappers::TcpListenerStream, StreamExt}; use soketto::{handshake::{Server, ClientRequest, server::Response}}; // First, we listen for incoming connections. let listener = tokio::net::TcpListener::bind("...").await?; let mut incoming = TcpListenerStream::new(listener); while let Some(socket) = incoming.next().await { // For each incoming connection we perform a handshake. let mut server = Server::new(socket?.compat()); let websocket_key = { let req = server.receive_request().await?; req.key() }; // Here we accept the client unconditionally. let accept = Response::Accept { key: websocket_key, protocol: None }; server.send_response(&accept).await?; // And we can finally transition to a websocket connection. let (mut sender, mut receiver) = server.into_builder().finish(); let mut data = Vec::new(); let data_type = receiver.receive_data(&mut data).await?; if data_type.is_text() { sender.send_text(std::str::from_utf8(&data)?).await? } else { sender.send_binary(&data).await? } sender.close().await?; } ``` -------------------------------- ### Get Mutable Slice of Buffer Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Returns a mutable slice starting at the current position. The slice length is between 0 and `BufMut::remaining_mut()`. Note that this can be shorter than the total remaining capacity, allowing for non-continuous buffer implementations. ```rust fn chunk_mut(&mut self) -> &mut UninitSlice ``` -------------------------------- ### Get Type ID Source: https://docs.rs/soketto/0.8.1/soketto/base/struct.Header.html Gets the TypeId of the Header. Part of the Any trait implementation. ```rust fn type_id(&self) -> TypeId> ``` -------------------------------- ### Client Configuration Methods Source: https://docs.rs/soketto/0.8.1/soketto/handshake/client/struct.Client.html Methods for configuring the client before initiating the handshake. ```APIDOC ## Configuration Methods ### Description Methods to configure the client instance before calling the handshake method. ### Parameters - **set_buffer** (BytesMut) - Override the buffer used for request/response handling. - **set_headers** (Header) - Set connection headers to a slice. - **add_protocol** (str) - Add a protocol to be included in the handshake. - **add_extension** (Extension) - Add an extension to be included in the handshake. ``` -------------------------------- ### Get Payload Length Source: https://docs.rs/soketto/0.8.1/soketto/base/struct.Header.html Retrieves the length of the payload in bytes. ```rust pub fn payload_len(&self) -> usize> ``` -------------------------------- ### Create New WebSocket Handshake Server Source: https://docs.rs/soketto/0.8.1/src/soketto/handshake/http.rs.html Initializes a new server handshake with default empty extensions and buffer. Use `add_extension` to configure supported extensions. ```rust pub fn new() -> Self { Server { extensions: Vec::new(), buffer: BytesMut::new() } } ``` -------------------------------- ### Get WebSocket Frame Header OpCode Source: https://docs.rs/soketto/0.8.1/src/soketto/base.rs.html Returns the `OpCode` of the WebSocket frame. ```rust pub fn opcode(&self) -> OpCode { self.opcode } ``` -------------------------------- ### Type ID Method Source: https://docs.rs/soketto/0.8.1/soketto/connection/struct.Sender.html Gets the `TypeId` of the sender, useful for runtime type identification. ```rust fn type_id(&self) -> TypeId ``` -------------------------------- ### Create New Builder Source: https://docs.rs/soketto/0.8.1/soketto/connection/struct.Builder.html Initializes a new Builder with a given async I/O resource and mode. Ensure a successful handshake has been performed before using this. ```rust pub fn new(socket: T, mode: Mode) -> Self ``` -------------------------------- ### Get WebSocket Frame Header Payload Length Source: https://docs.rs/soketto/0.8.1/src/soketto/base.rs.html Returns the payload length of the WebSocket frame. ```rust pub fn payload_len(&self) -> usize { self.payload_len } ``` -------------------------------- ### Box::new_uninit_in Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Constructs a new box with uninitialized contents in the provided allocator. This is a nightly-only experimental API. ```APIDOC ## Box::new_uninit_in ### Description Constructs a new box with uninitialized contents in the provided allocator. ### Method Associated Function ### Endpoint N/A (Associated function) ### Parameters - **alloc** (A) - Required - The allocator to use. ### Request Example N/A (Associated function) ### Response #### Success Response (Returns a Box, A>) - **Box, A>** - The new Box with uninitialized contents. #### Response Example ```rust #![feature(allocator_api)] use std::alloc::System; let mut five = Box::::new_uninit_in(System); // Deferred initialization: five.write(5); let five = unsafe { five.assume_init() }; assert_eq!(*five, 5) ``` ``` -------------------------------- ### LocalSpawn Implementation Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Methods for spawning and managing local tasks. ```APIDOC ## LocalSpawn Methods ### fn spawn_local_obj(&self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> Spawns a future that will be run to completion. ### fn status_local(&self) -> Result<(), SpawnError> Determines whether the executor is able to spawn new tasks. ``` -------------------------------- ### Get WebSocket Frame Header Mask Source: https://docs.rs/soketto/0.8.1/src/soketto/base.rs.html Returns the mask value of the WebSocket frame header. ```rust pub fn mask(&self) -> u32 { self.mask } ``` -------------------------------- ### Extension::configure Method Source: https://docs.rs/soketto/0.8.1/soketto/extension/trait.Extension.html Configures the extension with parameters received from the peer during handshake negotiation. This method allows the extension to enable itself based on the negotiated parameters. ```rust fn configure(&mut self, params: &[Param<'_>]) -> Result<(), BoxedError>; ``` -------------------------------- ### Get Opcode Source: https://docs.rs/soketto/0.8.1/soketto/base/struct.Header.html Retrieves the OpCode from the header. This indicates the type of message (e.g., text, binary). ```rust pub fn opcode(&self) -> OpCode> ``` -------------------------------- ### Try to Create a Zeroed Uninitialized Box (Nightly) Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html An experimental API to create a Box with zeroed memory, returning an error on allocation failure. Requires the 'allocator_api' feature and unsafe for initialization. ```rust #![feature(allocator_api)] let zero = Box::::try_new_zeroed()?; let zero = unsafe { zero.assume_init() }; assert_eq!(*zero, 0); ``` -------------------------------- ### Get Mask Source: https://docs.rs/soketto/0.8.1/soketto/base/struct.Header.html Retrieves the mask value used for masking the payload. Only relevant if 'masked' flag is set. ```rust pub fn mask(&self) -> u32> ``` -------------------------------- ### Manually Create Box from Scratch Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Manually allocate memory using a custom allocator and then construct a Box using `Box::from_raw_in`. Requires careful handling of memory layout and initialization. ```rust #![feature(allocator_api, slice_ptr_get)] use std::alloc::{Allocator, Layout, System}; unsafe { let ptr = System.allocate(Layout::new::())?.as_mut_ptr() as *mut i32; // In general .write is required to avoid attempting to destruct // the (uninitialized) previous contents of `ptr`, though for this // simple example `*ptr = 5` would have worked as well. ptr.write(5); let x = Box::from_raw_in(ptr, System); } ``` -------------------------------- ### Get Maximum Data Size for Codec Source: https://docs.rs/soketto/0.8.1/src/soketto/base.rs.html Retrieves the configured maximum payload length in bytes that the codec supports. ```rust pub fn max_data_size(&self) -> usize { self.max_data_size } ``` -------------------------------- ### Builder Configuration Source: https://docs.rs/soketto/0.8.1/soketto/connection/struct.Builder.html Methods for configuring a Soketto WebSocket connection builder. ```APIDOC ## Builder Methods ### `Builder::new(socket: T, mode: Mode) -> Self` Creates a new `Builder` instance. - **socket**: The underlying asynchronous I/O resource (must implement `AsyncRead` and `AsyncWrite`, and be `Unpin`). - **mode**: The WebSocket communication mode. **Note**: This should only be used after a successful handshake. ### `Builder::set_buffer(&mut self, b: BytesMut)` Sets a custom buffer for the connection. - **b**: The `BytesMut` buffer to use. ### `Builder::add_extensions(&mut self, extensions: I)` Adds extensions to be used with this connection. - **extensions**: An iterator of extensions to add. Only enabled extensions will be considered. ### `Builder::set_max_message_size(&mut self, max: usize)` Sets the maximum size for a complete WebSocket message. - **max**: The maximum allowed size in bytes. Note that extensions might further increase the total message size. ### `Builder::set_max_frame_size(&mut self, max: usize)` Sets the maximum size for a single WebSocket frame payload. - **max**: The maximum allowed frame payload size in bytes. ### `Builder::finish(self) -> (Sender, Receiver)` Constructs and returns a configured `Sender` and `Receiver` pair for the WebSocket connection. ``` -------------------------------- ### Try to Create an Uninitialized Box (Nightly) Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html An experimental API to create a Box with uninitialized contents, returning an error on allocation failure. Requires the 'allocator_api' feature and unsafe for initialization. ```rust #![feature(allocator_api)] let mut five = Box::::try_new_uninit()?; // Deferred initialization: five.write(5); let five = unsafe { five.assume_init() }; assert_eq!(*five, 5); ``` -------------------------------- ### Get Reserved Bits from Codec Source: https://docs.rs/soketto/0.8.1/src/soketto/base.rs.html Returns the currently configured reserved bits as a tuple of booleans (rsv1, rsv2, rsv3). ```rust pub fn reserved_bits(&self) -> (bool, bool, bool) { let r = self.reserved_bits; (r & 4 == 4, r & 2 == 2, r & 1 == 1) } ``` -------------------------------- ### Equivalent Manual Cleanup using Box::from_raw Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Demonstrates an equivalent manual cleanup of a raw pointer by converting it back to a Box and then dropping the Box. This leverages the Box destructor for cleanup. ```rust let x = Box::new(String::from("Hello")); let ptr = Box::into_raw(x); unsafe { drop(Box::from_raw(ptr)); } ``` -------------------------------- ### Get WebSocket Frame Header Masked Flag Source: https://docs.rs/soketto/0.8.1/src/soketto/base.rs.html Returns the current state of the `masked` flag in the WebSocket frame header. ```rust pub fn is_masked(&self) -> bool { self.masked } ``` -------------------------------- ### Create and Initialize an Uninitialized Box Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Demonstrates creating a Box with uninitialized contents and then writing to it. Requires unsafe block for assumption of initialization. ```rust let mut five = Box::::new_uninit(); // Deferred initialization: five.write(5); let five = unsafe { five.assume_init() }; assert_eq!(*five, 5) ``` -------------------------------- ### Get WebSocket Frame Header Rsv3 Flag Source: https://docs.rs/soketto/0.8.1/src/soketto/base.rs.html Returns the current state of the `rsv3` flag in the WebSocket frame header. ```rust pub fn is_rsv3(&self) -> bool { self.rsv3 } ``` -------------------------------- ### Try to Create a Boxed Integer (Nightly) Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html An experimental API to attempt heap allocation and value placement, returning an error if allocation fails. Requires the 'allocator_api' feature. ```rust #![feature(allocator_api)] let five = Box::try_new(5)?; ``` -------------------------------- ### Get WebSocket Frame Header Rsv2 Flag Source: https://docs.rs/soketto/0.8.1/src/soketto/base.rs.html Returns the current state of the `rsv2` flag in the WebSocket frame header. ```rust pub fn is_rsv2(&self) -> bool { self.rsv2 } ``` -------------------------------- ### Box Implementations Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Provides documentation for various methods available on the Box type, including creation, uninitialized allocation, pinning, and conversion from raw pointers. ```APIDOC ## Box Implementations ### `impl Box` (1.0.0) #### `pub fn new(x: T) -> Box` Allocates memory on the heap and then places `x` into it. This doesn’t actually allocate if `T` is zero-sized. ##### Examples ```rust let five = Box::new(5); ``` #### `pub fn new_uninit() -> Box>` Constructs a new box with uninitialized contents. ##### Examples ```rust let mut five = Box::::new_uninit(); // Deferred initialization: five.write(5); let five = unsafe { five.assume_init() }; assert_eq!(*five, 5) ``` #### `pub fn new_zeroed() -> Box>` 🔬This is a nightly-only experimental API. (`new_zeroed_alloc`) Constructs a new `Box` with uninitialized contents, with the memory being filled with `0` bytes. ##### Examples ```rust #![feature(new_zeroed_alloc)] let zero = Box::::new_zeroed(); let zero = unsafe { zero.assume_init() }; assert_eq!(*zero, 0) ``` #### `pub fn pin(x: T) -> Pin>` Constructs a new `Pin>`. If `T` does not implement `Unpin`, then `x` will be pinned in memory and unable to be moved. #### `pub fn try_new(x: T) -> Result, AllocError>` 🔬This is a nightly-only experimental API. (`allocator_api`) Allocates memory on the heap then places `x` into it, returning an error if the allocation fails. ##### Examples ```rust #![feature(allocator_api)] let five = Box::try_new(5)?; ``` #### `pub fn try_new_uninit() -> Result>, AllocError>` 🔬This is a nightly-only experimental API. (`allocator_api`) Constructs a new box with uninitialized contents on the heap, returning an error if the allocation fails. ##### Examples ```rust #![feature(allocator_api)] let mut five = Box::::try_new_uninit()?; // Deferred initialization: five.write(5); let five = unsafe { five.assume_init() }; assert_eq!(*five, 5); ``` #### `pub fn try_new_zeroed() -> Result>, AllocError>` 🔬This is a nightly-only experimental API. (`allocator_api`) Constructs a new `Box` with uninitialized contents, with the memory being filled with `0` bytes on the heap. ##### Examples ```rust #![feature(allocator_api)] let zero = Box::::try_new_zeroed()?; let zero = unsafe { zero.assume_init() }; assert_eq!(*zero, 0); ``` ### `impl Box` where T: ?Sized (1.4.0) #### `pub unsafe fn from_raw(raw: *mut T) -> Box` Constructs a box from a raw pointer. After calling this function, the raw pointer is owned by the resulting `Box`. Specifically, the `Box` destructor will call the destructor of `T` and free the allocated memory. For this to be safe, the memory must have been allocated in accordance with the memory layout used by `Box` . ##### Safety This function is unsafe because improper use may lead to memory problems. For example, a double-free may occur if the function is called twice on the same raw pointer. The raw pointer must point to a block of memory allocated by the global allocator. The safety conditions are described in the memory layout section. ##### Examples ```rust let x = Box::new(5); let ptr = Box::into_raw(x); let x = unsafe { Box::from_raw(ptr) }; ``` ```rust use std::alloc::{alloc, Layout}; unsafe { let ptr = alloc(Layout::new::()) as *mut i32; // In general .write is required to avoid attempting to destruct // the (uninitialized) previous contents of `ptr`, though for this // simple example `*ptr = 5` would have worked as well. ptr.write(5); let x = Box::from_raw(ptr); } ``` #### `pub unsafe fn from_non_null(ptr: NonNull) -> Box` 🔬This is a nightly-only experimental API. (`box_vec_non_null`) Constructs a box from a `NonNull` pointer. After calling this function, the `NonNull` pointer is owned by the resulting `Box`. Specifically, the `Box` destructor will call the destructor of `T` and free the allocated memory. For this to be safe, the memory must have been allocated in accordance with the memory layout used by `Box` . ``` -------------------------------- ### Get WebSocket Frame Header Rsv1 Flag Source: https://docs.rs/soketto/0.8.1/src/soketto/base.rs.html Returns the current state of the `rsv1` flag in the WebSocket frame header. ```rust pub fn is_rsv1(&self) -> bool { self.rsv1 } ``` -------------------------------- ### Client Handshake and Connection Source: https://docs.rs/soketto/0.8.1/src/soketto/lib.rs.html Demonstrates how to perform a client-side WebSocket handshake and establish a connection. Requires a TCP connection and handles server responses, including acceptance, redirection, or rejection. ```rust use tokio_util::compat::TokioAsyncReadCompatExt; use soketto::handshake::{Client, ServerResponse}; // First, we need to establish a TCP connection. let socket = tokio::net::TcpStream::connect("...").await?; // Then we configure the client handshake. let mut client = Client::new(socket.compat(), "...", "/"); // And finally we perform the handshake and handle the result. let (mut sender, mut receiver) = match client.handshake().await? { ServerResponse::Accepted { .. } => client.into_builder().finish(), ServerResponse::Redirect { status_code, location } => unimplemented!("follow location URL"), ServerResponse::Rejected { status_code } => unimplemented!("handle failure") }; // Over the established websocket connection we can send sender.send_text("some text").await?; sender.send_text("some more text").await?; sender.flush().await?; // ... and receive data. let mut data = Vec::new(); receiver.receive_data(&mut data).await?; ``` -------------------------------- ### Get WebSocket Frame Header Fin Flag Source: https://docs.rs/soketto/0.8.1/src/soketto/base.rs.html Returns the current state of the `fin` flag in the WebSocket frame header. ```rust pub fn is_fin(&self) -> bool { self.fin } ``` -------------------------------- ### Client Handshake Initialization Source: https://docs.rs/soketto/0.8.1/src/soketto/handshake/client.rs.html Provides methods to create and configure a new client handshake instance. ```APIDOC ## Client Handshake ### Description Represents a client-side websocket handshake. It allows for configuring headers, protocols, and extensions before initiating the handshake. ### Methods #### `new(socket: T, host: &'a str, resource: &'a str) -> Self` Creates a new client handshake instance. - **socket** (T): The underlying asynchronous I/O resource. - **host** (&'a str): The HTTP host to send the handshake to. - **resource** (&'a str): The HTTP resource path. #### `set_buffer(&mut self, b: BytesMut) -> &mut Self` Overrides the buffer used for request/response handling. - **b** (BytesMut): The new buffer to use. #### `take_buffer(&mut self) -> BytesMut` Extracts the current buffer. #### `set_headers(&mut self, h: &'a [Header]) -> &mut Self` Sets connection headers to a slice. The caller is responsible for validity and avoiding conflicts. - **h** (&'a [Header]): The slice of headers to set. #### `add_protocol(&mut self, p: &'a str) -> &mut Self` Adds a protocol to be included in the handshake request. - **p** (&'a str): The protocol string to add. #### `add_extension(&mut self, e: Box) -> &mut Self` Adds an extension to be included in the handshake request. - **e** (Box): The extension to add. #### `drain_extensions(&mut self) -> impl Iterator> + '_` Retrieves all configured extensions, consuming them from the client. #### `handshake(&mut self) -> Result` Initiates the client handshake request to the server and returns the server's response. - **Returns**: `Result`: The server's response or an error if the handshake fails. #### `into_builder(self) -> connection::Builder` Consumes the handshake and returns a `connection::Builder` for establishing the websocket connection. #### `into_inner(self) -> T` Consumes the handshake and returns the underlying socket. ### Example ```rust use soketto::handshake::{Client, ClientFuture}; use futures::executor::block_on; use tokio::net::TcpStream; let socket = block_on(TcpStream::connect("127.0.0.1:8080")); let mut handshake = Client::new(socket.unwrap(), "127.0.0.1:8080", "/"); // Optionally configure headers, protocols, extensions handshake.add_protocol("chat"); // Perform the handshake // let response = block_on(handshake.handshake()); ``` ``` -------------------------------- ### Get Minimum of Two Incoming Data Source: https://docs.rs/soketto/0.8.1/soketto/data/enum.Incoming.html Returns the minimum of two Incoming data values. This is a convenience method for comparisons. ```rust fn min(self, other: Self) -> Self where Self: Sized, ``` -------------------------------- ### Configure Window Bits Source: https://docs.rs/soketto/0.8.1/src/soketto/extension/deflate.rs.html Methods to set the maximum window bits for server and client. These require the extension to be in client mode and values must be between 9 and 15. ```rust 81 pub fn set_max_server_window_bits(&mut self, max: u8) { 82 assert!(self.mode == Mode::Client, "setting max. server window bits requires client mode"); 83 assert!(max > 8 && max <= 15, "max. server window bits have to be within 9 ..= 15"); 84 self.their_max_window_bits = max; // upper bound of the server's window 85 let mut p = Param::new(SERVER_MAX_WINDOW_BITS); 86 p.set_value(Some(max.to_string())); 87 self.params.push(p) 88 } 89 90 /// Set the client's max. window bits. 91 /// 92 /// The value must be within 9 ..= 15. 93 /// The extension must be in client mode. 94 /// 95 /// The parameter informs the server that even if it doesn't include the 96 /// "client_max_window_bits" extension parameter in the response with a 97 /// value greater than the one in the negotiation offer or if it doesn't 98 /// include the extension parameter at all, the client is not going to 99 /// use an LZ77 sliding window size greater than one given here. 100 /// The server may also respond with a smaller value which allows the client 101 /// to reduce its sliding window even more. 102 pub fn set_max_client_window_bits(&mut self, max: u8) { 103 assert!(self.mode == Mode::Client, "setting max. client window bits requires client mode"); 104 assert!(max > 8 && max <= 15, "max. client window bits have to be within 9 ..= 15"); 105 self.our_max_window_bits = max; // upper bound of the client's window 106 if let Some(p) = self.params.iter_mut().find(|p| p.name() == CLIENT_MAX_WINDOW_BITS) { 107 p.set_value(Some(max.to_string())); 108 } else { 109 let mut p = Param::new(CLIENT_MAX_WINDOW_BITS); 110 p.set_value(Some(max.to_string())); 111 self.params.push(p) 112 } 113 } ``` -------------------------------- ### Get Maximum of Two Incoming Data Source: https://docs.rs/soketto/0.8.1/soketto/data/enum.Incoming.html Returns the maximum of two Incoming data values. This is a convenience method for comparisons. ```rust fn max(self, other: Self) -> Self where Self: Sized, ``` -------------------------------- ### Error::cause Implementation (Deprecated) Source: https://docs.rs/soketto/0.8.1/soketto/handshake/http/type.Error.html A deprecated method for getting the underlying cause of the error. Use `Error::source` which supports downcasting. ```rust fn cause(&self) -> Option<&dyn Error> ``` -------------------------------- ### Box::try_new_uninit_in Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Constructs a new box with uninitialized contents in the provided allocator, returning an error if the allocation fails. This is a nightly-only experimental API. ```APIDOC ## Box::try_new_uninit_in ### Description Constructs a new box with uninitialized contents in the provided allocator, returning an error if the allocation fails. ### Method Associated Function ### Endpoint N/A (Associated function) ### Parameters - **alloc** (A) - Required - The allocator to use. ### Request Example N/A (Associated function) ### Response #### Success Response (Returns a Result, A>, AllocError>) - **Result, A>, AllocError>** - Ok containing the new Box on success, or an AllocError on failure. #### Response Example ```rust #![feature(allocator_api)] use std::alloc::System; let mut five = Box::::try_new_uninit_in(System)?; // Deferred initialization: five.write(5); let five = unsafe { five.assume_init() }; assert_eq!(*five, 5); ``` ``` -------------------------------- ### Box::from_raw_in Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Constructs a box from a raw pointer in the given allocator. This is a nightly-only experimental API. ```APIDOC ## unsafe Box::from_raw_in(raw: *mut T, alloc: A) -> Box ### Description Constructs a box from a raw pointer in the given allocator. The Box destructor will call the destructor of T and free the memory. ### Parameters #### Request Body - **raw** (*mut T) - Required - The raw pointer to wrap. - **alloc** (A) - Required - The allocator instance. ### Response #### Success Response (200) - **Box** - The resulting Box instance. ``` -------------------------------- ### Error::description Implementation (Deprecated) Source: https://docs.rs/soketto/0.8.1/soketto/handshake/http/type.Error.html A deprecated method for getting a string description of the error. Prefer using the Display implementation or `to_string()` instead. ```rust fn description(&self) -> &str ``` -------------------------------- ### Configure Server Max Window Bits Source: https://docs.rs/soketto/0.8.1/src/soketto/extension/deflate.rs.html Configures the server's maximum window bits for permessage-deflate. Handles client offers and sets server parameters. ```rust SERVER_MAX_WINDOW_BITS => { if let Some(Ok(v)) = p.value().map(|s| s.parse::()) { // The RFC allows 8 to 15 bits, but due to zlib limitations we // only support 9 to 15. if v < 9 || v > 15 { log::debug!("unacceptable server_max_window_bits: {}", v); return Ok(()); } let mut x = Param::new(SERVER_MAX_WINDOW_BITS); x.set_value(Some(v.to_string())); self.params.push(x); self.our_max_window_bits = v; } else { log::debug!("invalid server_max_window_bits: {:?}", p.value()); return Ok(()); } } ``` -------------------------------- ### Get Mutable Remaining Bytes Count Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Returns the number of bytes that can be written from the current position to the end of the buffer. Use this to check available space before writing. ```rust fn remaining_mut(&self) -> usize ``` -------------------------------- ### Encode Client Handshake Request Source: https://docs.rs/soketto/0.8.1/src/soketto/handshake/client.rs.html Generates the HTTP GET request string for the websocket handshake. This includes setting the Host, Upgrade, Connection, and Sec-WebSocket-Key headers. ```rust fn encode_request(&mut self) { let nonce: [u8; 16] = rand::random(); base64::engine::general_purpose::STANDARD .encode_slice(nonce, &mut self.nonce) .expect("encoding to base64 is exactly 16 bytes; qed"); self.buffer.extend_from_slice(b"GET "); self.buffer.extend_from_slice(self.resource.as_bytes()); self.buffer.extend_from_slice(b" HTTP/1.1"); self.buffer.extend_from_slice(b"\r\nHost: "); self.buffer.extend_from_slice(self.host.as_bytes()); self.buffer.extend_from_slice(b"\r\nUpgrade: websocket\r\nConnection: Upgrade"); self.buffer.extend_from_slice(b"\r\nSec-WebSocket-Key: "); self.buffer.extend_from_slice(&self.nonce); } ``` -------------------------------- ### try_new_zeroed_in Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Constructs a new Box with uninitialized contents, filling memory with 0 bytes using the provided allocator. Returns an error if allocation fails. This is a nightly-only experimental API. ```APIDOC ## POST /try_new_zeroed_in ### Description Constructs a new `Box` with uninitialized contents, with the memory being filled with `0` bytes in the provided allocator, returning an error if the allocation fails. ### Method POST ### Endpoint `/try_new_zeroed_in` ### Parameters #### Query Parameters - **alloc** (Allocator) - Required - The allocator to use for memory allocation. ### Request Body - **T** (type) - Required - The type of the value to be stored in the Box. ### Request Example ```json { "T": "u32" } ``` ### Response #### Success Response (200) - **Box, A>** (Box) - A Box containing uninitialized memory filled with zeros. #### Error Response (400) - **AllocError** (Error) - An error indicating that the memory allocation failed. #### Response Example ```json { "Box, System>": "..." } ``` ``` -------------------------------- ### Convert configuration to connection builder Source: https://docs.rs/soketto/0.8.1/src/soketto/handshake/http.rs.html Transforms a configuration instance into a connection builder for a given asynchronous stream. ```rust pub fn into_builder(mut self, socket: T) -> connection::Builder { let mut builder = connection::Builder::new(socket, Mode::Server); builder.set_buffer(self.buffer); builder.add_extensions(self.extensions.drain(..)); builder } ``` -------------------------------- ### Equivalent Manual Cleanup using Box::from_non_null Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Demonstrates an equivalent manual cleanup of a NonNull pointer by converting it back to a Box and then dropping the Box. This leverages the Box destructor for cleanup. Requires the `box_vec_non_null` feature. ```rust #![feature(box_vec_non_null)] let x = Box::new(String::from("Hello")); let non_null = Box::into_non_null(x); unsafe { drop(Box::from_non_null(non_null)); } ``` -------------------------------- ### Extension Trait Definition Source: https://docs.rs/soketto/0.8.1/src/soketto/extension.rs.html Defines the core `Extension` trait for implementing custom websocket extensions. It includes methods for checking enablement, getting the extension name and parameters, configuring the extension, and encoding/decoding frames. Implementations should consider the handshake differences between client and server. ```rust pub trait Extension: std::fmt::Debug { /// Is this extension enabled? fn is_enabled(&self) -> bool; /// The name of this extension. fn name(&self) -> &str; /// The parameters this extension wants to send for negotiation. fn params(&self) -> &[Param]; /// Configure this extension with the parameters received from negotiation. fn configure(&mut self, params: &[Param]) -> Result<(), BoxedError>; /// Encode a frame, given as frame header and payload data. fn encode(&mut self, header: &mut Header, data: &mut Storage) -> Result<(), BoxedError>; /// Decode a frame. /// /// The frame header is given, as well as the accumulated payload data, i.e. /// the concatenated payload data of all message fragments. fn decode(&mut self, header: &mut Header, data: &mut Vec) -> Result<(), BoxedError>; /// The reserved bits this extension uses. fn reserved_bits(&self) -> (bool, bool, bool) { (false, false, false) } } ``` -------------------------------- ### Initialize Client Handshake Source: https://docs.rs/soketto/0.8.1/src/soketto/handshake/client.rs.html Creates a new client handshake instance for a given socket, host, and resource. The socket must implement AsyncRead and AsyncWrite. ```rust pub fn new(socket: T, host: &'a str, resource: &'a str) -> Self { Client { socket, host, resource, headers: &[], nonce: [0; 24], protocols: Vec::new(), extensions: Vec::new(), buffer: BytesMut::new(), } } ``` -------------------------------- ### Create Uninitialized Box with Custom Allocator Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Constructs a new Box with uninitialized contents using a provided allocator. Deferred initialization is possible. This is a nightly-only experimental API. ```rust #![feature(allocator_api)] use std::alloc.System; let mut five = Box::::new_uninit_in(System); // Deferred initialization: five.write(5); let five = unsafe { five.assume_init() }; assert_eq!(*five, 5) ``` -------------------------------- ### Try Create Uninitialized Box with Custom Allocator Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Attempts to construct a new Box with uninitialized contents using a provided allocator, returning an error if the allocation fails. This is a nightly-only experimental API. ```rust #![feature(allocator_api)] use std::alloc.System; let mut five = Box::::try_new_uninit_in(System)?; // Deferred initialization: five.write(5); let five = unsafe { five.assume_init() }; assert_eq!(*five, 5); ``` -------------------------------- ### CloneToUninit Implementation (Nightly) Source: https://docs.rs/soketto/0.8.1/soketto/connection/enum.Mode.html Nightly-only experimental API for copying data to an uninitialized memory location. Requires the Clone trait. ```rust unsafe fn clone_to_uninit(&self, dest: *mut u8) ``` -------------------------------- ### Try Create Box with Custom Allocator Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Attempts to allocate memory using a specified allocator and place a value into it, returning an error if the allocation fails. This is a nightly-only experimental API. ```rust #![feature(allocator_api)] use std::alloc.System; let five = Box::try_new_in(5, System)?; ``` -------------------------------- ### Perform WebSocket Client Handshake Source: https://docs.rs/soketto/0.8.1/index.html Establishes a WebSocket connection as a client by upgrading a TCP stream and handling the handshake response. ```rust use soketto::handshake::{Client, ServerResponse}; // First, we need to establish a TCP connection. let socket = tokio::net::TcpStream::connect("...").await?; // Then we configure the client handshake. let mut client = Client::new(socket.compat(), "...", "/"); // And finally we perform the handshake and handle the result. let (mut sender, mut receiver) = match client.handshake().await? { ServerResponse::Accepted { .. } => client.into_builder().finish(), ServerResponse::Redirect { status_code, location } => unimplemented!("follow location URL"), ServerResponse::Rejected { status_code } => unimplemented!("handle failure") }; // Over the established websocket connection we can send sender.send_text("some text").await?; sender.send_text("some more text").await?; sender.flush().await?; // ... and receive data. let mut data = Vec::new(); receiver.receive_data(&mut data).await?; ``` -------------------------------- ### Configure WebSocket Extensions Source: https://docs.rs/soketto/0.8.1/src/soketto/handshake.rs.html Parses the Sec-WebSocket-Extensions header and configures the provided extensions with their parameters. Handles comma-separated extensions and semicolon-separated parameters. ```rust fn configure_extensions(extensions: &mut [Box], line: &str) -> Result<(), Error> { for e in line.split(',') { let mut ext_parts = e.split(';'); if let Some(name) = ext_parts.next() { let name = name.trim(); if let Some(ext) = extensions.iter_mut().find(|x| x.name().eq_ignore_ascii_case(name)) { let mut params = Vec::new(); for p in ext_parts { let mut key_value = p.split('='); if let Some(key) = key_value.next().map(str::trim) { let val = key_value.next().map(|v| v.trim().trim_matches('"')); let mut p = Param::new(key); p.set_value(val); params.push(p) } } ext.configure(¶ms).map_err(Error::Extension)? } } } Ok(()) } ``` -------------------------------- ### Create a Zeroed Uninitialized Box (Nightly) Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Uses a nightly-only feature to create a Box with memory initialized to zero bytes. Requires unsafe block for assumption of initialization. ```rust #![feature(new_zeroed_alloc)] let zero = Box::::new_zeroed(); let zero = unsafe { zero.assume_init() }; assert_eq!(*zero, 0) ``` -------------------------------- ### Configure Client Max Window Bits Source: https://docs.rs/soketto/0.8.1/src/soketto/extension/deflate.rs.html Configures the client's maximum window bits for permessage-deflate. Adjusts based on server offers and zlib limitations. ```rust CLIENT_MAX_WINDOW_BITS => { if let Some(Ok(v)) = p.value().map(|s| s.parse::()) { if v < 8 || v > 15 { log::debug!("unacceptable client_max_window_bits: {}", v); return Ok(()); } use std::cmp::{max, min}; // Due to zlib limitations we have to use 9 as a lower bound // here, even if the server allowed us to go down to 8 bits. self.our_max_window_bits = min(self.our_max_window_bits, max(9, v)); } } ``` -------------------------------- ### Builder::finish Source: https://docs.rs/soketto/0.8.1/src/soketto/connection.rs.html Completes the builder configuration and creates the `Sender`/`Receiver` pair for the websocket connection. ```rust pub fn finish(self) -> (Sender, Receiver) { let (rhlf, whlf) = self.socket.split(); ``` -------------------------------- ### Extension::params Method Source: https://docs.rs/soketto/0.8.1/soketto/extension/trait.Extension.html Provides the parameters that this extension wishes to negotiate. These parameters are sent during the handshake to inform the other peer about the extension's configuration. ```rust fn params(&self) -> &[Param<'_>]; ``` -------------------------------- ### Create Box from Manually Allocated Memory Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Shows how to create a Box from a raw pointer obtained via manual memory allocation using std::alloc. This operation is unsafe. ```rust use std::alloc::{alloc, Layout}; unsafe { let ptr = alloc(Layout::new::()) as *mut i32; // In general .write is required to avoid attempting to destruct // the (uninitialized) previous contents of `ptr`, though for this // simple example `*ptr = 5` would have worked as well. ptr.write(5); let x = Box::from_raw(ptr); } ``` -------------------------------- ### Implement OpCode Formatting and Conversion Source: https://docs.rs/soketto/0.8.1/src/soketto/base.rs.html Provides Display implementation for OpCode and handles conversion between u8 and OpCode using TryFrom and From traits. ```rust 96impl fmt::Display for OpCode { 97 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 98 match self { 99 OpCode::Continue => f.write_str("Continue"), 100 OpCode::Text => f.write_str("Text"), 101 OpCode::Binary => f.write_str("Binary"), 102 OpCode::Close => f.write_str("Close"), 103 OpCode::Ping => f.write_str("Ping"), 104 OpCode::Pong => f.write_str("Pong"), 105 OpCode::Reserved3 => f.write_str("Reserved:3"), 106 OpCode::Reserved4 => f.write_str("Reserved:4"), 107 OpCode::Reserved5 => f.write_str("Reserved:5"), 108 OpCode::Reserved6 => f.write_str("Reserved:6"), 109 OpCode::Reserved7 => f.write_str("Reserved:7"), 110 OpCode::Reserved11 => f.write_str("Reserved:11"), 111 OpCode::Reserved12 => f.write_str("Reserved:12"), 112 OpCode::Reserved13 => f.write_str("Reserved:13"), 113 OpCode::Reserved14 => f.write_str("Reserved:14"), 114 OpCode::Reserved15 => f.write_str("Reserved:15"), 115 } 116 } 117} 118 119/// Error returned by `OpCode::try_from` if an unknown opcode 120/// number is encountered. 121#[derive(Clone, Debug)] 122pub struct UnknownOpCode(()); 123 124impl fmt::Display for UnknownOpCode { 125 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 126 f.write_str("unknown opcode") 127 } 128} 129 130impl std::error::Error for UnknownOpCode {} 131 132impl TryFrom for OpCode { 133 type Error = UnknownOpCode; 134 135 fn try_from(val: u8) -> Result { 136 match val { 137 0 => Ok(OpCode::Continue), 138 1 => Ok(OpCode::Text), 139 2 => Ok(OpCode::Binary), 140 3 => Ok(OpCode::Reserved3), 141 4 => Ok(OpCode::Reserved4), 142 5 => Ok(OpCode::Reserved5), 143 6 => Ok(OpCode::Reserved6), 144 7 => Ok(OpCode::Reserved7), 145 8 => Ok(OpCode::Close), 146 9 => Ok(OpCode::Ping), 147 10 => Ok(OpCode::Pong), 148 11 => Ok(OpCode::Reserved11), 149 12 => Ok(OpCode::Reserved12), 150 13 => Ok(OpCode::Reserved13), 151 14 => Ok(OpCode::Reserved14), 152 15 => Ok(OpCode::Reserved15), 153 _ => Err(UnknownOpCode(())), 154 } 155 } 156} 157 158impl From for u8 { 159 fn from(opcode: OpCode) -> u8 { 160 match opcode { 161 OpCode::Continue => 0, 162 OpCode::Text => 1, 163 OpCode::Binary => 2, 164 OpCode::Close => 8, 165 OpCode::Ping => 9, 166 OpCode::Pong => 10, ``` -------------------------------- ### Create a Take Adaptor for Reading Bytes Source: https://docs.rs/soketto/0.8.1/soketto/type.BoxedError.html Creates an adaptor that reads at most a specified number of bytes from the buffer. Useful for limiting read operations. ```rust fn take(self, limit: usize) -> Take where Self: Sized, ```