1#![no_std]
2
3pub use crypto::process_sec_websocket_key;
4pub use framer::{WsRxFramer, WsTxFramer};
5pub use url::WsUrl;
6
7#[cfg(feature = "alloc")]
8pub use url::WsUrlOwned;
9
10#[cfg(feature = "alloc")]
11extern crate alloc;
12
13mod consts;
14mod crypto;
15mod framer;
16mod url;
17
18#[derive(Debug, Clone)]
19pub struct WsFrameHeader {
21 pub fin: bool,
22 pub rsv1: bool,
23 pub rsv2: bool,
24 pub rsv3: bool,
25 pub opcode: u8,
26 pub mask: bool,
27 pub masking_key: [u8; 4],
28 pub payload_len: usize,
29 offset: usize,
30}
31
32#[allow(dead_code)]
33#[derive(Debug, Clone)]
34pub enum WsFrame<'a> {
37 Text(&'a str),
38 Binary(&'a [u8]),
39 Close(u16, &'a str),
40 Ping(&'a [u8]),
41 Pong(&'a [u8]),
42 Unknown,
43}
44
45#[cfg(feature = "alloc")]
46#[allow(dead_code)]
47#[derive(Debug, Clone)]
48pub enum WsFrameOwned {
51 Text(alloc::string::String),
52 Binary(alloc::vec::Vec<u8>),
53 Close(u16, alloc::string::String),
54 Ping(alloc::vec::Vec<u8>),
55 Pong(alloc::vec::Vec<u8>),
56 Unknown,
57}
58
59impl<'a> WsFrame<'a> {
60 pub fn opcode(&self) -> u8 {
62 match self {
63 WsFrame::Text(_) => 1,
64 WsFrame::Binary(_) => 2,
65 WsFrame::Close(..) => 8,
66 WsFrame::Ping(_) => 9,
67 WsFrame::Pong(_) => 10,
68 WsFrame::Unknown => 0,
69 }
70 }
71
72 pub(crate) fn from_data(header: &WsFrameHeader, buf: &'a mut [u8]) -> Self {
74 if header.mask {
75 for (i, x) in buf.iter_mut().enumerate() {
76 let key = header.masking_key[i % 4];
77 *x ^= key;
78 }
79 }
80
81 match header.opcode {
82 1 => Self::Text(unsafe { core::str::from_utf8_unchecked(buf) }),
83 2 => Self::Binary(buf),
84 8 => Self::Close(u16::from_be_bytes([buf[0], buf[1]]), unsafe {
85 core::str::from_utf8_unchecked(&buf[2..])
86 }),
87 9 => Self::Ping(buf),
88 10 => Self::Pong(buf),
89 _ => Self::Unknown,
90 }
91 }
92
93 pub fn data(&self) -> &'a [u8] {
95 match self {
96 WsFrame::Text(str) => str.as_bytes(),
97 WsFrame::Binary(byt) => byt,
98 WsFrame::Close(_, reason) => reason.as_bytes(),
99 WsFrame::Ping(byt) => byt,
100 WsFrame::Pong(byt) => byt,
101 WsFrame::Unknown => &[],
102 }
103 }
104}
105
106#[cfg(feature = "alloc")]
107impl<'a> WsFrameOwned {
108 pub fn into_ref(&'a self) -> WsFrame<'a> {
109 match self {
110 WsFrameOwned::Text(string) => WsFrame::Text(&string),
111 WsFrameOwned::Binary(vec) => WsFrame::Binary(&vec),
112 WsFrameOwned::Close(code, reason) => WsFrame::Close(*code, &reason),
113 WsFrameOwned::Ping(vec) => WsFrame::Ping(&vec),
114 WsFrameOwned::Pong(vec) => WsFrame::Pong(&vec),
115 WsFrameOwned::Unknown => WsFrame::Unknown,
116 }
117 }
118}
119
120pub(crate) fn rng_fill(buf: &mut [u8]) {
121 #[cfg(feature = "getrandom02")]
122 {
123 _ = getrandom02::getrandom(buf);
124 }
125
126 #[cfg(feature = "getrandom03")]
127 {
128 _ = getrandom03::fill(buf);
129 }
130}