Expand description
Websocket stream.
Stream
is a simple wrapper of the underlying IO source,
with small stack buffers to save states.
It is transparent to call Read
or Write
on Stream:
{
// establish connection, handshake
let stream = ...
// read some data
stream.read(&mut buf)?;
// write some data
stream.write(&buf)?;
}
A new established Stream
is in Direct
(default) mode, where
a Read
or Write
leads to at most one syscall, and
an Ok(0)
will be returned if frame head is not completely read or written.
It can be converted to Guarded
mode with Stream::guard
,
which wraps Read
or Write
in a loop, where Ok(0)
is handled internally.
Stream itself does not buffer any payload data during
a Read
or Write
, so there is no extra heap allocation.
Masking payload
Data read from stream are automatically unmasked.
However, data written to stream are NOT automatically masked,
since a Write
call requires an immutable &[u8]
.
A standard client(e.g. StandardClient
)
should mask the payload before sending it;
A non-standard client (e.g. Client
) which holds an empty mask key
can simply skip this step.
The mask key is prepared by ClientRole
,
which can be set or fetched via Stream::set_mask_key
and Stream::mask_key
.
Example:
use std::io::{Read, Write};
use std::net::TcpStream;
use lightws::role::StandardClient;
use lightws::endpoint::Endpoint;
use lightws::frame::{new_mask_key, apply_mask4};
fn write_data() -> std::io::Result<()> {
let mut buf = [0u8; 256];
let mut tcp = TcpStream::connect("example.com:80")?;
let mut ws = Endpoint::<TcpStream, StandardClient>::connect(tcp, &mut buf, "example.com", "/ws")?;
// mask data
let key = new_mask_key();
apply_mask4(key, &mut buf);
// set mask key for next write
ws.set_mask_key(key)?;
// write some data
ws.write_all(&buf)?;
Ok(())
}
Automatic masking
It is annoying to mask the payload each time before a write,
and it will block us from using convenient functions like std::io::copy
.
With unsafe_auto_mask_write
fearure enabled, the provided immutable &[u8]
will be casted
to a mutable &mut [u8]
then payload data can be automatically masked.
This feature only has effects on AutoMaskClientRole
,
where its inner mask key may be updated (depends on
AutoMaskClientRole::UPDATE_MASK_KEY
)
and used to mask the payload before each write.
Other ClientRole
and ServerRole
are not affected. Related code lies in src/stream/detail/write#L118
.
Structs
- Direct read or write.
- Wrapped read or write.
- Websocket stream.