pub struct WebsocketFrameDecoder { /* private fields */ }
Expand description
A low-level WebSocket frames decoder.
It is a push parser: you can add offer it bytes that come from a socket and it emites events.
You typically need two loops to process incoming data: outer loop reads chunks of data from sockets, inner loop supplies this chunk to the decoder instance until no more events get emitted.
Example usage:
use std::io::Read;
use tungstenite::{protocol::Role, Message};
use websocket_sans_io::{FrameInfo, Opcode, WebsocketFrameEvent};
fn main() {
let (tunstenite_end, mut sansio_end) = pipe::bipipe();
std::thread::spawn(move || {
let mut tunstenite =
tungstenite::protocol::WebSocket::from_raw_socket(tunstenite_end, Role::Client, None);
tunstenite
.send(Message::Text("Hello, world\n".to_owned()))
.unwrap();
});
let mut frame_decoder = websocket_sans_io::WebsocketFrameDecoder::new();
let mut result = Vec::<u8>::new();
let mut buf = [0u8; 1024];
// This loop should handle multi-frame message and control messages interrupting stream of data frames,
// but it does not reply to WebSocket pings
'read_loop: loop {
let n = sansio_end.read(&mut buf).unwrap();
let mut processed_offset = 0;
'decode_chunk_loop: loop {
let unprocessed_part_of_buf = &mut buf[processed_offset..n];
let ret = frame_decoder.add_data(unprocessed_part_of_buf).unwrap();
processed_offset += ret.consumed_bytes;
if ret.event.is_none() && ret.consumed_bytes == 0 {
break 'decode_chunk_loop;
}
match ret.event {
Some(WebsocketFrameEvent::PayloadChunk {
original_opcode: Opcode::Text,
}) => {
result.extend_from_slice(&unprocessed_part_of_buf[0..ret.consumed_bytes]);
}
Some(WebsocketFrameEvent::End {
frame_info: FrameInfo { fin: true, .. },
original_opcode: Opcode::Text,
}) => break 'read_loop,
_ => (),
}
}
}
assert_eq!(result, b"Hello, world\n");
}
Any sequence of bytes result in a some (sensial or not) WebsocketFrameEvent
sequence (exception: when large_frames
crate feature is disabled).
You may want to validate it (e.g. using FrameInfo::is_reasonable
method) before using.
Implementations§
Source§impl WebsocketFrameDecoder
impl WebsocketFrameDecoder
Sourcepub fn add_data<'a, 'b>(
&'a mut self,
data: &'b mut [u8],
) -> Result<WebsocketFrameDecoderAddDataResult, FrameDecoderError>
pub fn add_data<'a, 'b>( &'a mut self, data: &'b mut [u8], ) -> Result<WebsocketFrameDecoderAddDataResult, FrameDecoderError>
Add some bytes to the decoder and return events, if any.
Call this function again if any of the following conditions are met:
- When new incoming data is available on the socket
- When previous invocation of
add_data
returned nonzeroWebsocketFrameDecoderAddDataResult::consumed_bytes
. - When previous invocation of
add_data
returned non-None
WebsocketFrameDecoderAddDataResult::event
.
You may need call it with empty data
buffer to get some final WebsocketFrameEvent::End
.
Input buffer needs to be mutable because it is also used to transform (unmask) payload content chunks in-place.
Sourcepub fn eof_valid(&self) -> bool
pub fn eof_valid(&self) -> bool
There is no incomplete WebSocket frame at this moment and EOF is valid here.
This method is not related to Opcode::ConnectionClose
in any way.
Trait Implementations§
Source§impl Clone for WebsocketFrameDecoder
impl Clone for WebsocketFrameDecoder
Source§fn clone(&self) -> WebsocketFrameDecoder
fn clone(&self) -> WebsocketFrameDecoder
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read more