1mod decode;
2mod frame_head;
3mod frame_payload;
4
5pub use decode::*;
6pub use frame_head::*;
7pub use frame_payload::*;
8
9use crate::message::WsMessageKind;
10use futures::prelude::*;
11use std::error::Error;
12use std::io::Cursor;
13use std::io::Write;
14use strum::Display;
15
16#[derive(Copy, Clone, Debug)]
17pub enum WsFrame {
18 Control(WsControlFrame),
19 Data(WsDataFrame),
20}
21
22impl WsFrame {
23 pub fn decode<T: AsyncRead + Unpin>(transport: T) -> FrameDecoder<T> {
24 FrameDecoderState::new().restore(transport)
25 }
26 pub fn encode(frame_head: FrameHead, frame_payload: &[u8], buffer: &mut [u8]) -> usize {
29 assert_eq!(frame_head.payload_len, frame_payload.len() as u64);
30 let total = frame_head.len_bytes() + frame_payload.len();
31 frame_head.encode(buffer);
32 let payload_buffer = &mut buffer[frame_head.len_bytes()..total];
33 payload_buffer.copy_from_slice(frame_payload);
34 payload_mask(frame_head.mask, 0, payload_buffer);
35 return total;
36 }
37 pub fn encode_vec(frame_head: FrameHead, frame_payload: &[u8]) -> Vec<u8> {
38 let mut buffer = vec![0u8; frame_head.len_bytes() + frame_payload.len()];
39 WsFrame::encode(frame_head, frame_payload, &mut *buffer);
40 buffer
41 }
42}
43
44#[derive(Copy, Clone, Debug)]
45pub enum WsFrameKind {
46 Control(WsControlFrameKind),
47 Data(WsDataFrameKind),
48}
49
50impl WsFrameKind {
51 pub fn max_payload_len(self) -> u64 {
52 match self {
53 WsFrameKind::Control(_) => 125,
54 WsFrameKind::Data(_) => 1073741824,
55 }
56 }
57 pub fn opcode(self) -> WsOpcode {
58 match self {
59 WsFrameKind::Control(frame) => frame.opcode(),
60 WsFrameKind::Data(frame) => frame.opcode(),
61 }
62 }
63 pub fn is_control(self) -> bool {
64 match self {
65 WsFrameKind::Control(_) => true,
66 WsFrameKind::Data(_) => false,
67 }
68 }
69}
70
71#[derive(Display, Copy, Clone, Debug, Eq, PartialEq)]
72pub enum WsDataFrameKind {
73 Text,
74 Binary,
75 Continuation,
76}
77
78impl WsDataFrameKind {
79 pub fn opcode(self) -> WsOpcode {
80 match self {
81 WsDataFrameKind::Text => WsOpcode::Text,
82 WsDataFrameKind::Binary => WsOpcode::Binary,
83 WsDataFrameKind::Continuation => WsOpcode::Continuation,
84 }
85 }
86 pub fn message_kind(self) -> Option<WsMessageKind> {
87 match self {
88 WsDataFrameKind::Text => Some(WsMessageKind::Text),
89 WsDataFrameKind::Binary => Some(WsMessageKind::Binary),
90 WsDataFrameKind::Continuation => None,
91 }
92 }
93 pub fn frame_kind(self) -> WsFrameKind {
94 WsFrameKind::Data(self)
95 }
96}
97
98#[derive(Copy, Clone, Debug, Eq, PartialEq)]
99pub enum WsControlFrameKind {
100 Ping,
101 Pong,
102 Close,
103}
104
105impl WsControlFrameKind {
106 pub fn opcode(self) -> WsOpcode {
107 match self {
108 WsControlFrameKind::Ping => WsOpcode::Ping,
109 WsControlFrameKind::Pong => WsOpcode::Pong,
110 WsControlFrameKind::Close => WsOpcode::Close,
111 }
112 }
113 pub fn frame_kind(self) -> WsFrameKind {
114 WsFrameKind::Control(self)
115 }
116}
117
118#[derive(Copy, Clone, Debug)]
119pub struct WsDataFrame {
120 pub(crate) kind: WsDataFrameKind,
121 pub(crate) fin: bool,
122 pub(crate) mask: [u8; 4],
123 pub(crate) payload_len: u64,
124}
125
126impl WsDataFrame {
127 pub fn payload_reader(&self) -> FramePayloadReaderState {
128 FramePayloadReaderState::new(self.mask, self.payload_len)
129 }
130 pub fn kind(&self) -> WsDataFrameKind {
131 self.kind
132 }
133 pub fn fin(&self) -> bool {
134 self.fin
135 }
136 pub fn mask(&self) -> [u8; 4] {
137 self.mask
138 }
139 pub fn payload_len(&self) -> u64 {
140 self.payload_len
141 }
142}
143
144#[derive(Copy, Clone, Debug)]
145pub struct WsControlFrame {
146 pub(crate) kind: WsControlFrameKind,
147 pub(crate) payload: WsControlFramePayload,
148}
149
150impl WsControlFrame {
151 pub fn new(kind: WsControlFrameKind, payload: &[u8]) -> Self {
152 let payload = WsControlFramePayload::new(payload);
153 Self { kind, payload }
154 }
155 pub fn payload(&self) -> &[u8] {
156 &self.payload.data()
157 }
158 pub fn kind(&self) -> WsControlFrameKind {
159 self.kind
160 }
161 pub fn head(&self, mask: [u8; 4]) -> FrameHead {
162 FrameHead {
163 fin: true,
164 opcode: self.kind.opcode(),
165 mask,
166 payload_len: self.payload().len() as u64,
167 }
168 }
169}
170
171#[derive(Copy, Clone, Debug)]
172pub(crate) struct WsControlFramePayload {
173 pub(crate) len: u8,
174 pub(crate) buffer: [u8; 125],
175}
176
177impl WsControlFramePayload {
178 pub(crate) fn new(data: &[u8]) -> Self {
179 let len = data.len().min(125);
180 let payload = &data[0..len];
181 let mut buffer = [0u8; 125];
182 buffer[0..len].copy_from_slice(payload);
183 Self {
184 len: len as u8,
185 buffer,
186 }
187 }
188 pub(crate) fn data(&self) -> &[u8] {
189 &self.buffer[0..self.len()]
190 }
191 pub(crate) fn len(&self) -> usize {
192 self.len as usize
193 }
194 pub(crate) fn close_body(&self) -> Result<Option<(u16, &str)>, CloseBodyError> {
195 match self.len() {
196 0 => Ok(None),
197 1 => Err(CloseBodyError::BodyTooShort),
198 _ => {
199 let data = self.data();
200 let code = u16::from_be_bytes([data[0], data[1]]);
201 match code {
202 0..=999 | 1004..=1006 | 1016..=2999 => Err(CloseBodyError::InvalidCode),
203 code => match std::str::from_utf8(&data[2..]) {
204 Ok(reason) => Ok(Some((code, reason))),
205 Err(_) => Err(CloseBodyError::InvalidUtf8),
206 },
207 }
208 }
209 }
210 }
211}
212
213#[derive(thiserror::Error, Debug)]
214pub enum CloseBodyError {
215 #[error("close frame body is too short")]
216 BodyTooShort,
217 #[error("invalid utf8 in close body reason")]
218 InvalidUtf8,
219 #[error("invalid close frame body code")]
220 InvalidCode,
221}
222
223impl<E: Error> From<(u16, &E)> for WsControlFramePayload {
224 fn from(err: (u16, &E)) -> Self {
225 let mut buffer = [0u8; 125];
226 buffer[0..2].copy_from_slice(&err.0.to_be_bytes());
227 let mut cursor = Cursor::new(&mut buffer[2..]);
228 write!(cursor, "{}", err.1).ok();
229 let len = 2 + cursor.position() as u8;
230 WsControlFramePayload { len, buffer }
231 }
232}