pub struct WebSocket<T, S: WebSocketType>where
T: RngCore,{
pub state: WebSocketState,
/* private fields */
}
Expand description
Websocket client and server implementation
Fields§
§state: WebSocketState
Implementations§
Source§impl<T, Type> WebSocket<T, Type>where
T: RngCore,
Type: WebSocketType,
impl<T, Type> WebSocket<T, Type>where
T: RngCore,
Type: WebSocketType,
Sourcepub fn new_client(rng: T) -> WebSocketClient<T>
pub fn new_client(rng: T) -> WebSocketClient<T>
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::WebSocketClient::new_client(rand::thread_rng());
assert_eq!(ws::WebSocketState::None, ws_client.state);
Sourcepub fn new_server() -> WebSocketServer
pub fn new_server() -> WebSocketServer
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);
Source§impl<T> WebSocket<T, Server>where
T: RngCore,
impl<T> WebSocket<T, Server>where
T: RngCore,
Sourcepub fn server_accept(
&mut self,
sec_websocket_key: &WebSocketKey,
sec_websocket_protocol: Option<&WebSocketSubProtocol>,
to: &mut [u8],
) -> Result<usize>
pub fn server_accept( &mut self, sec_websocket_key: &WebSocketKey, sec_websocket_protocol: Option<&WebSocketSubProtocol>, to: &mut [u8], ) -> Result<usize>
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
Source§impl<T> WebSocket<T, Client>where
T: RngCore,
impl<T> WebSocket<T, Client>where
T: RngCore,
Sourcepub fn client_connect(
&mut self,
websocket_options: &WebSocketOptions<'_>,
to: &mut [u8],
) -> Result<(usize, WebSocketKey)>
pub fn client_connect( &mut self, websocket_options: &WebSocketOptions<'_>, to: &mut [u8], ) -> Result<(usize, WebSocketKey)>
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::WebSocketClient::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
Sourcepub fn client_accept(
&mut self,
sec_websocket_key: &WebSocketKey,
from: &[u8],
) -> Result<(usize, Option<WebSocketSubProtocol>)>
pub fn client_accept( &mut self, sec_websocket_key: &WebSocketKey, from: &[u8], ) -> Result<(usize, Option<WebSocketSubProtocol>)>
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::WebSocketClient::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 (len, sub_protocol) = ws_client.client_accept(&ws_key, server_response_html.as_bytes())
.unwrap();
assert_eq!(159, len);
assert_eq!("chat", sub_protocol.unwrap());
§Errors
- Returns
HttpResponseCodeInvalid
if the HTTP response code is not101 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
Source§impl<T, Type> WebSocket<T, Type>where
T: RngCore,
Type: WebSocketType,
impl<T, Type> WebSocket<T, Type>where
T: RngCore,
Type: WebSocketType,
Sourcepub fn read(
&mut self,
from: &[u8],
to: &mut [u8],
) -> Result<WebSocketReadResult>
pub fn read( &mut self, from: &[u8], to: &mut [u8], ) -> Result<WebSocketReadResult>
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 thefrom
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::WebSocketClient::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 thefrom
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
Sourcepub fn write(
&mut self,
message_type: WebSocketSendMessageType,
end_of_message: bool,
from: &[u8],
to: &mut [u8],
) -> Result<usize>
pub fn write( &mut self, message_type: WebSocketSendMessageType, end_of_message: bool, from: &[u8], to: &mut [u8], ) -> Result<usize>
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 theto
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 withend_of_message
set tofalse
and the final call set totrue
Sourcepub fn close(
&mut self,
close_status: WebSocketCloseStatusCode,
status_description: Option<&str>,
to: &mut [u8],
) -> Result<usize>
pub fn close( &mut self, close_status: WebSocketCloseStatusCode, status_description: Option<&str>, to: &mut [u8], ) -> Result<usize>
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 theto
buffer is too small to fit the websocket frame header (2-14 bytes) plus the payload. Consider sending a smaller status_description