[][src]Struct embedded_websocket::WebSocket

pub struct WebSocket<T> where
    T: RngCore
{ pub state: WebSocketState, // some fields omitted }

Websocket client and server implementation

Fields

state: WebSocketState

Methods

impl<T> WebSocket<T> where
    T: RngCore
[src]

pub fn new_client(rng: T) -> WebSocket<T>[src]

Creates a new websocket client by passing in a required random number generator

Examples

use embedded_websocket as ws;
use rand;
let mut ws_client = ws::WebSocket::new_client(rand::thread_rng());

assert_eq!(ws::WebSocketState::None, ws_client.state);

pub fn new_server() -> WebSocketServer[src]

Creates a new websocket server. Note that you must use the WebSocketServer type and not the generic WebSocket type for this call or you will get a 'type annotations needed' compilation error.

Examples

use embedded_websocket as ws;
let mut ws_server = ws::WebSocketServer::new_server();

assert_eq!(ws::WebSocketState::None, ws_server.state);

pub fn server_accept(
    &mut self,
    sec_websocket_key: &WebSocketKey,
    sec_websocket_protocol: Option<&WebSocketSubProtocol>,
    to: &mut [u8]
) -> Result<usize>
[src]

Used by the server to accept an incoming client connection and build a websocket upgrade http response string. The client http header should be read with the read_http_header function and the result should be passed to this function.

Websocket state will change from None -> Open if successful, otherwise None -> Aborted

Examples

use embedded_websocket as ws;
let mut buffer: [u8; 1000] = [0; 1000];
let mut ws_server = ws::WebSocketServer::new_server();
let ws_key = ws::WebSocketKey::from("Z7OY1UwHOx/nkSz38kfPwg==");
let sub_protocol = ws::WebSocketSubProtocol::from("chat");
let len = ws_server
    .server_accept(&ws_key, Some(&sub_protocol), &mut buffer)
    .unwrap();
let response = std::str::from_utf8(&buffer[..len]).unwrap();

assert_eq!("HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Protocol: chat\r\nSec-WebSocket-Accept: ptPnPeDOTo6khJlzmLhOZSh2tAY=\r\n\r\n", response);

Errors

There should be no way for a user provided input to return the errors listed below as the input is already constrained.

  • The http response is built with a stack allocated 1KB buffer and it should be impossible for it to return an Unknown error if that buffer is too small. However, this is better than a panic and it will do so if the response header is too large to fit in the buffer
  • This function can return an Utf8Error if there was an error with the generation of the accept string. This should also be impossible but an error is preferable to a panic
  • Returns WebsocketAlreadyOpen if called on a websocket that is already open

Panics

Panics with Server websocket expected if the user calls this function as a client websocket. This function should be use with a websocket created using new_server()

pub fn client_connect(
    &mut self,
    websocket_options: &WebSocketOptions,
    to: &mut [u8]
) -> Result<(usize, WebSocketKey)>
[src]

Used by the client to initiate a websocket opening handshake

Examples

use embedded_websocket as ws;
let mut buffer: [u8; 2000] = [0; 2000];
let mut ws_client = ws::WebSocket::new_client(rand::thread_rng());
let sub_protocols = ["chat", "superchat"];
let websocket_options = ws::WebSocketOptions {
    path: "/chat",
    host: "localhost",
    origin: "http://localhost",
    sub_protocols: Some(&sub_protocols),
    additional_headers: None,
};

let (len, web_socket_key) = ws_client.client_connect(&websocket_options, &mut buffer).unwrap();

let actual_http = std::str::from_utf8(&buffer[..len]).unwrap();
let mut expected_http = String::new();
expected_http.push_str("GET /chat HTTP/1.1\r\nHost: localhost\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: ");
expected_http.push_str(web_socket_key.as_str());
expected_http.push_str("\r\nOrigin: http://localhost\r\nSec-WebSocket-Protocol: chat, superchat\r\nSec-WebSocket-Version: 13\r\n\r\n");
assert_eq!(expected_http.as_str(), actual_http);

Errors

  • The http response is built with a stack allocated 1KB buffer and will return an Unknown error if that buffer is too small. This would happen is the user supplied too many additional headers or the sub-protocol string is too large
  • This function can return an Utf8Error if there was an error with the generation of the accept string. This should be impossible but an error is preferable to a panic
  • Returns WebsocketAlreadyOpen if called on a websocket that is already open

Panics

Panics with Client websocket expected if the user calls this function as a server websocket. This function should be use with a websocket created using new_client()

pub fn client_accept(
    &mut self,
    sec_websocket_key: &WebSocketKey,
    from: &[u8]
) -> Result<Option<WebSocketSubProtocol>>
[src]

Used by a websocket client for checking the server response to an opening handshake (sent using the client_connect function). If the client requested one or more sub protocols the server will choose one (or none) and you get that in the result

Examples

use embedded_websocket as ws;
let mut ws_client = ws::WebSocket::new_client(rand::thread_rng());
let ws_key = ws::WebSocketKey::from("Z7OY1UwHOx/nkSz38kfPwg==");
let server_response_html = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Protocol: chat\r\nSec-WebSocket-Accept: ptPnPeDOTo6khJlzmLhOZSh2tAY=\r\n\r\n";    ///
let (sub_protocol) = ws_client.client_accept(&ws_key, server_response_html.as_bytes())
    .unwrap();

assert_eq!("chat", sub_protocol.unwrap());

Errors

  • Returns HttpResponseCodeInvalid if the HTTP response code is not 101 Switching Protocols
  • Returns AcceptStringInvalid if the web server failed to return a valid accept string
  • Returns HttpHeader(Version) or some other varient if the HTTP response is not well formed
  • Returns WebsocketAlreadyOpen if called on a websocket that is already open

Panics

Panics with Client websocket expected if the user calls this function as a server websocket. This function should be use with a websocket created using new_client()

pub fn read(
    &mut self,
    from: &[u8],
    to: &mut [u8]
) -> Result<WebSocketReadResult>
[src]

Reads the payload from a websocket frame in buffer from into a buffer to and returns metadata about the frame.

Since this function is designed to be called in a memory constrained system we may not read the entire payload in one go. In each of the scenarios below the read_result.end_of_message flag would be false:

  • The payload is fragmented into multiple websocket frames (as per the websocket spec)
  • The from buffer does not hold the entire websocket frame. For example if only part of the frame was read or if the from buffer is too small to hold an entire websocket frame
  • The to buffer is too small to hold the entire websocket frame payload

If the function returns read_result.end_of_message false then the next call to the function should not include data that has already been passed into the function. The websocket remembers the websocket frame header and is able to process the rest of the payload correctly. If the from buffer contains multiple websocket frames then only one of them will be returned at a time and the user must make multiple calls to the function by taking note of read_result.len_from which tells you how many bytes were read from the from buffer

Examples

use embedded_websocket as ws;
//                    h   e   l   l   o
let buffer1 = [129,5,104,101,108,108,111];
let mut buffer2: [u8; 128] = [0; 128];
let mut ws_client = ws::WebSocket::new_client(rand::thread_rng());
ws_client.state = ws::WebSocketState::Open; // skip the opening handshake
let ws_result = ws_client.read(&buffer1, &mut buffer2).unwrap();

assert_eq!("hello".as_bytes(), &buffer2[..ws_result.len_to]);

Errors

  • Returns WebSocketNotOpen when the websocket is not open when this function is called
  • Returns InvalidOpCode if the websocket frame contains an invalid opcode
  • Returns UnexpectedContinuationFrame if we receive a continuation frame without first receiving a non-continuation frame with an opcode describing the payload
  • Returns ReadFrameIncomplete if the from buffer does not contain a full websocket header (typically 2-14 bytes depending on the payload)
  • Returns InvalidFrameLength if the frame length cannot be decoded

pub fn write(
    &mut self,
    message_type: WebSocketSendMessageType,
    end_of_message: bool,
    from: &[u8],
    to: &mut [u8]
) -> Result<usize>
[src]

Writes the payload in from to a websocket frame in to

  • message_type - The type of message to send: Text, Binary or CloseReply
  • end_of_message - False to fragment a frame into multiple smaller frames. The last frame should set this to true
  • from - The buffer containing the payload to encode
  • to - The the buffer to save the websocket encoded payload to. Returns the number of bytes written to the to buffer

Examples

use embedded_websocket as ws;
let mut buffer: [u8; 1000] = [0; 1000];
let mut ws_server = ws::WebSocketServer::new_server();
ws_server.state = ws::WebSocketState::Open; // skip the opening handshake
let len = ws_server.write(ws::WebSocketSendMessageType::Text, true, "hello".as_bytes(),
    &mut buffer).unwrap();

//                     h   e   l   l   o
let expected = [129,5,104,101,108,108,111];
assert_eq!(&expected, &buffer[..len]);

Errors

  • Returns WebSocketNotOpen when the websocket is not open when this function is called
  • Returns WriteToBufferTooSmall when the to buffer is too small to fit the websocket frame header (2-14 bytes) plus the payload. Consider fragmenting the messages by making multiple write calls with end_of_message set to false and the final call set to true

pub fn close(
    &mut self,
    close_status: WebSocketCloseStatusCode,
    status_description: Option<&str>,
    to: &mut [u8]
) -> Result<usize>
[src]

Initiates a close handshake. Both the client and server may initiate a close handshake. If successful the function changes the websocket state from Open -> CloseSent

Errors

  • Returns WebSocketNotOpen when the websocket is not open when this function is called
  • Returns WriteToBufferTooSmall when the to buffer is too small to fit the websocket frame header (2-14 bytes) plus the payload. Consider sending a smaller status_description

Auto Trait Implementations

impl<T> Send for WebSocket<T> where
    T: Send

impl<T> Sync for WebSocket<T> where
    T: Sync

Blanket Implementations

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> From<T> for T[src]

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Same<T> for T

type Output = T

Should always be Self