rust_rcs_core/sip/sip_parser.rs
1// Copyright 2023 宋昊文
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::sync::Arc;
16
17use crate::internet::body::Body;
18use crate::internet::header;
19use crate::internet::header::{Header, HeaderSearch};
20use crate::internet::header_field::AsHeaderField;
21use crate::internet::headers::content_type::AsContentType;
22use crate::internet::syntax;
23use crate::util::raw_string::{StrEq, ToInt};
24
25use super::sip_message::{SipFirstLine, SipMessage};
26
27enum ParsingState {
28 Empty,
29 ReadingFirstLine,
30 ReadingHeaders(Option<SipFirstLine>, Option<Vec<Header>>, Option<Vec<u8>>),
31 ExpectingBody(Option<SipFirstLine>, Option<Vec<Header>>, usize),
32}
33
34pub struct SipParser {
35 buffer: Vec<u8>,
36 p: usize,
37 state: ParsingState,
38}
39
40impl SipParser {
41 pub fn new() -> SipParser {
42 SipParser {
43 buffer: Vec::new(),
44 p: 0,
45 state: ParsingState::Empty,
46 }
47 }
48
49 pub fn feed(&mut self, data: &[u8]) {
50 self.buffer.extend_from_slice(data);
51 }
52
53 pub fn produce(&mut self) -> Result<Option<SipMessage>, &str> {
54 'outer: loop {
55 match &mut self.state {
56 ParsingState::Empty => {
57 if self.p < self.buffer.len() {
58 let c1 = self.buffer[self.p];
59
60 if c1 == b'\r' {
61 if self.p + 1 < self.buffer.len() {
62 let c2 = self.buffer[self.p + 1];
63
64 if c2 == b'\n' {
65 if self.p + 3 < self.buffer.len() {
66 let c3 = self.buffer[self.p + 2];
67 let c4 = self.buffer[self.p + 3];
68
69 if c3 == b'\r' && c4 == b'\n' {
70 self.p = self.p + 4;
71
72 return Ok(Some(SipMessage::Ping));
73 }
74 }
75
76 self.p = self.p + 2;
77
78 return Ok(Some(SipMessage::Pong));
79 } else {
80 return Err("dangling Carriage Return\n");
81 }
82 } else {
83 return Ok(None);
84 }
85 }
86
87 self.state = ParsingState::ReadingFirstLine;
88 } else {
89 return Ok(None);
90 }
91 }
92
93 ParsingState::ReadingFirstLine => {
94 let buf = &self.buffer[self.p..];
95
96 if let Ok(o) = SipFirstLine::decode_first_line(buf) {
97 match o {
98 Some((first_line, consumed)) => {
99 self.p = self.p + consumed;
100 self.state = ParsingState::ReadingHeaders(
101 Some(first_line),
102 Some(Vec::new()),
103 Some(Vec::new()),
104 );
105 }
106
107 None => return Ok(None),
108 }
109 } else {
110 return Err("error decoding first line");
111 }
112 }
113
114 ParsingState::ReadingHeaders(first_line, message_headers, line) => {
115 let mut first_fold: Option<usize> = None;
116 let mut last_fold: usize = 0;
117
118 'inner: loop {
119 let chunk = &self.buffer[self.p + last_fold..];
120
121 let mut iter = chunk.iter();
122
123 if let Some(position) = iter.position(|c| *c == b'\r') {
124 if let Some(c) = iter.next() {
125 if *c == b'\n' {
126 if last_fold + position == 0 {
127 self.p = self.p + 2;
128 let mut content_length: Option<usize> = None;
129 if let Some(headers) = message_headers {
130 if let Some(content_length_header) =
131 header::search(headers, b"Content-Length", true)
132 {
133 if let Ok(i) =
134 content_length_header.get_value().to_int()
135 {
136 content_length = Some(i);
137 }
138 }
139 }
140
141 if let Some(content_length) = content_length {
142 self.state = ParsingState::ExpectingBody(
143 first_line.take(),
144 message_headers.take(),
145 content_length,
146 );
147 continue 'outer;
148 } else {
149 return Err("require explicit content-length");
150 }
151 }
152
153 if let Some(c) = iter.next() {
154 if *c == b'\t' {
155 if first_fold.is_none() {
156 first_fold = Some(position);
157 }
158 last_fold = last_fold + position + 3;
159 if let Some(line) = line {
160 line.extend_from_slice(&chunk[..position]);
161 line.push(b' ');
162 } else {
163 panic!("line value missing for no obvious reason")
164 }
165 continue 'inner;
166 }
167 }
168
169 if let Some(mut line) = line.take() {
170 line.extend_from_slice(&chunk[..position]);
171 let mut iter = line.iter();
172
173 if let Some(idx) = iter.position(|c| *c == b':') {
174 if let Some(first_fold) = first_fold {
175 if first_fold < idx {
176 return Err("obsolete line foldings are not allowed in header names");
177 }
178 }
179 match message_headers {
180 Some(headers) => {
181 headers.push(Header::new(
182 syntax::trim(&line[..idx]).to_vec(),
183 syntax::trim(&line[idx + 1..]).to_vec(),
184 ));
185 self.p = self.p + last_fold + position + 2;
186 self.state = ParsingState::ReadingHeaders(
187 first_line.take(),
188 message_headers.take(),
189 Some(Vec::new()),
190 );
191 continue 'outer;
192 }
193 None => {
194 panic!("message_headers value missing for no obvious reason")
195 }
196 }
197 } else {
198 return Err("require header name");
199 }
200 } else {
201 panic!("line value missing for no obvious reason")
202 }
203 } else {
204 return Err("dangling Carriage Return");
205 }
206 }
207 }
208
209 return Ok(None);
210 }
211 }
212
213 ParsingState::ExpectingBody(first_line, message_headers, content_length) => {
214 if self.p + *content_length <= self.buffer.len() {
215 if let Some(headers) = message_headers {
216 let mut construct_flag: Option<i32> = None;
217 let mut boundary: Option<Vec<u8>> = None;
218
219 for header in HeaderSearch::new(headers, b"Content-Type", true) {
220 let field = header.get_value().as_header_field();
221 if let Some(content_type) = field.as_content_type() {
222 if content_type.major_type.equals_bytes(b"message", true) {
223 construct_flag = Some(1);
224 } else if content_type
225 .major_type
226 .equals_bytes(b"multipart", true)
227 {
228 construct_flag = Some(2);
229 boundary = Some(content_type.boundary.to_vec());
230 } else {
231 construct_flag = Some(0);
232 }
233 }
234 }
235
236 if *content_length == 0 {
237 let ok = Ok(Some(SipMessage::new(
238 first_line.take().unwrap(),
239 message_headers.take(),
240 None,
241 )));
242 self.buffer = self.buffer.split_off(self.p);
243 self.p = 0;
244 self.state = ParsingState::Empty;
245 return ok;
246 }
247
248 match construct_flag {
249 Some(flag) => match flag {
250 0 => {
251 let body = Body::construct_raw(
252 &self.buffer[self.p..self.p + *content_length],
253 );
254 let ok = Ok(Some(SipMessage::new(
255 first_line.take().unwrap(),
256 message_headers.take(),
257 Some(Arc::new(body)),
258 )));
259 self.buffer =
260 self.buffer.split_off(self.p + *content_length);
261 self.p = 0;
262 self.state = ParsingState::Empty;
263 return ok;
264 }
265 1 => match Body::construct_message(
266 &self.buffer[self.p..self.p + *content_length],
267 ) {
268 Ok(body) => {
269 let ok = Ok(Some(SipMessage::new(
270 first_line.take().unwrap(),
271 message_headers.take(),
272 Some(Arc::new(body)),
273 )));
274 self.buffer =
275 self.buffer.split_off(self.p + *content_length);
276 self.p = 0;
277 self.state = ParsingState::Empty;
278 return ok;
279 }
280 Err(e) => {
281 return Err(e);
282 }
283 },
284 2 => {
285 if let Some(boundary) = boundary {
286 match Body::construct_multipart(
287 &self.buffer[self.p..self.p + *content_length],
288 &boundary,
289 ) {
290 Ok(body) => {
291 let ok = Ok(Some(SipMessage::new(
292 first_line.take().unwrap(),
293 message_headers.take(),
294 Some(Arc::new(body)),
295 )));
296 self.buffer = self
297 .buffer
298 .split_off(self.p + *content_length);
299 self.p = 0;
300 self.state = ParsingState::Empty;
301 return ok;
302 }
303 Err(e) => {
304 return Err(e);
305 }
306 }
307 } else {
308 return Err("missing multipart boundary");
309 }
310 }
311 _ => {
312 panic!("impossible condition")
313 }
314 },
315 None => {
316 panic!("require explicit content-type")
317 }
318 }
319 }
320
321 return Err("seriously?");
322 } else {
323 return Ok(None);
324 }
325 }
326 }
327 }
328 }
329}