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}