1use crate::{FrameParseError, Message};
2
3pub struct Frame {
5 inner_op_code: u8,
6 masking_key: Option<u32>,
7 pub message: Message
9}
10
11impl Frame {
12 pub const FIN_RSV: u8 = 0x80;
14
15 pub const OP_CODE_CONTINUATION: u8 = 0x00;
19 pub const OP_CODE_TEXT: u8 = 0x01;
21 pub const OP_CODE_BINARY: u8 = 0x02;
23 pub const OP_CODE_CLOSE: u8 = 0x08;
25 pub const OP_CODE_PING: u8 = 0x09;
27 pub const OP_CODE_PONG: u8 = 0x0A;
29
30 pub fn op_code(&self) -> u8 {
32 self.inner_op_code
33 }
34
35 pub fn parse<A: AsRef<[u8]>>(content: A) -> Result<Frame, FrameParseError> {
37 let candidate = content.as_ref();
38
39 if candidate.is_empty() {
40 return Err(FrameParseError::NullContent);
42 }
43
44 if ((candidate[0] ^ !Frame::FIN_RSV) >> 4) != 0x0f {
46 return Err(FrameParseError::WrongFinRSV);
47 }
48
49 let min_length = candidate[1] & (!0x80);
51 let (length, mut offset) = if min_length == 126 {
52 if candidate.len() < 4 {
53 return Err(FrameParseError::Malformed)
54 }
55 (u16::from_be_bytes([candidate[2], candidate[3]]) as usize, 4usize)
56 } else if min_length == 127 {
57 if candidate.len() < 10 {
58 return Err(FrameParseError::Malformed)
59 }
60 (u64::from_be_bytes([candidate[2], candidate[3], candidate[4], candidate[5], candidate[6], candidate[7], candidate[8], candidate[9]]) as usize, 10usize)
61 } else {
62 (min_length as usize, 2usize)
63 };
64
65 let masking_key = if 0x80 == (candidate[1] & 0x80) {
67 if candidate.len() < offset + 4 {
68 return Err(FrameParseError::Incomplete{expected: length + offset + 4, obtained: candidate.len()})
70 }
71
72 offset += 4;
73 Some([candidate[offset - 4], candidate[offset - 3], candidate[offset - 2], candidate[offset - 1]])
75 } else {
76 None
77 };
78 let inner_op_code = (candidate[0] << 4) >> 4;
80 let mut payload = candidate.get(offset..offset+length).ok_or_else(|| FrameParseError::Incomplete{expected: length + offset, obtained: candidate.len()})?.to_vec();
81 if let Some(masking_key) = &masking_key {
82 payload = payload.into_iter().enumerate().map(|(idx, v)| {
84 let j = idx % 4;
86 v ^ masking_key[j]
87 }).collect();
88 }
89 let message = match inner_op_code {
90 Frame::OP_CODE_TEXT => Message::Text(String::from_utf8(payload).map_err(|e| FrameParseError::InvalidUtf8(e))?),
91 Frame::OP_CODE_BINARY => Message::Binary(payload),
92 Frame::OP_CODE_PING => Message::Ping(payload),
93 Frame::OP_CODE_PONG => Message::Pong(payload),
94 Frame::OP_CODE_CLOSE => Message::Close,
95 _ => return Err(FrameParseError::UnsupportedOpCode)
96 };
97
98 Ok(Frame {
99 inner_op_code,
100 masking_key: masking_key.map(u32::from_be_bytes),
101 message
102 })
103 }
104
105 pub fn text<A: Into<String>>(text: A) -> Frame {
107 let payload = text.into();
108 let message = Message::Text(payload);
109 Frame {
110 inner_op_code: Frame::OP_CODE_TEXT,
111 masking_key: None,
112 message
113 }
114 }
115
116 pub fn ping<A: Into<Vec<u8>>>(payload: A) -> Frame {
118 let payload = payload.into();
119 let message = Message::Ping(payload);
120 Frame {
121 inner_op_code: Frame::OP_CODE_PING,
122 masking_key: None,
123 message
124 }
125 }
126
127 pub fn pong<A: Into<Vec<u8>>>(payload: A) -> Frame {
129 let payload = payload.into();
130 let message = Message::Pong(payload);
131 Frame {
132 inner_op_code: Frame::OP_CODE_PONG,
133 masking_key: None,
134 message
135 }
136 }
137
138 pub fn binary<A: Into<Vec<u8>>>(binary: A) -> Frame {
140 let payload = binary.into();
141 let message = Message::Binary(payload);
142 Frame {
143 inner_op_code: Frame::OP_CODE_BINARY,
144 masking_key: None,
145 message
146 }
147 }
148
149 pub fn close() -> Frame {
151 let masking_key = None; Frame {
153 inner_op_code: Frame::OP_CODE_CLOSE,
154 masking_key,
155 message: Message::Close
156 }
157 }
158
159 pub fn get_message(&self) -> &Message {
161 &self.message
162 }
163
164 pub fn is_close(&self) -> bool {
166 self.inner_op_code == Frame::OP_CODE_CLOSE
167 }
168}
169
170impl From<Frame> for Message {
171 fn from(source: Frame) -> Message {
172 source.message
173 }
174}
175
176impl From<Frame> for Vec<u8> {
177 fn from(source: Frame) -> Vec<u8> {
178 let mut content = vec![Frame::FIN_RSV ^ source.inner_op_code];
179 let mut payload: Vec<u8> = source.message.into();
180 let payload_length = payload.len();
181 if payload_length < 126 {
182 content.push(payload_length as u8 | if source.masking_key.is_some() {0x80} else {0x00});
183 } else if payload_length <= u16::MAX.into() {
184 content.push(126u8 | if source.masking_key.is_some() {0x80} else {0x00});
185 content.extend((payload_length as u16).to_be_bytes());
187 } else {
188 content.push(127u8 | if source.masking_key.is_some() {0x80} else {0x00});
189 content.extend((payload_length as u64).to_be_bytes());
191 }
192
193 if let Some(masking_key) = &source.masking_key {
194 let masking_bytes = masking_key.to_be_bytes();
195 payload = payload.into_iter().enumerate().map(|(idx, v)| {
196 let j = idx % 4;
198 v ^ masking_bytes[j]
199 }).collect();
200 content.extend(masking_bytes);
202 }
203 if !payload.is_empty() {
204 content.extend(payload);
205 }
206
207 content
208 }
209}