rust_rcs_core/sip/
sip_message.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::fmt;
16use std::io::Read;
17use std::sync::Arc;
18
19use crate::ffi::log::platform_log;
20use crate::internet::body::Body;
21use crate::internet::body::BodySerializationError;
22use crate::internet::header;
23use crate::internet::header::headers_get_readers;
24use crate::internet::header::Header;
25use crate::internet::header_field::AsHeaderField;
26use crate::internet::header_field::HeaderField;
27
28use crate::io::DynamicChain;
29use crate::io::Serializable;
30
31use crate::sip::sip_dialog::GetDialogHeaders;
32use crate::sip::sip_headers::cseq::AsCSeq;
33
34use crate::util::raw_string::ToInt;
35
36const SIP2_0_BYTES: &[u8] = b"SIP/2.0";
37
38pub const ACK: &[u8] = b"ACK";
39pub const BYE: &[u8] = b"BYE";
40pub const CANCEL: &[u8] = b"CANCEL";
41pub const INVITE: &[u8] = b"INVITE";
42pub const MESSAGE: &[u8] = b"MESSAGE";
43pub const NOTIFY: &[u8] = b"NOTIFY";
44pub const OPTIONS: &[u8] = b"OPTIONS";
45pub const REFER: &[u8] = b"REFER";
46pub const REGISTER: &[u8] = b"REGISTER";
47pub const SUBSCRIBE: &[u8] = b"SUBSCRIBE";
48pub const UPDATE: &[u8] = b"UPDATE";
49
50const LOG_TAG: &str = "sip_message";
51
52pub enum SipVersion {
53    V2_0,
54}
55
56impl ToString for SipVersion {
57    fn to_string(&self) -> String {
58        match self {
59            SipVersion::V2_0 => return String::from("SIP/2.0"),
60        }
61    }
62}
63
64impl fmt::Debug for SipVersion {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        f.write_str("SIP/2.0")
67    }
68}
69
70pub struct SipRequestLine {
71    pub method: Vec<u8>,
72    pub uri: Vec<u8>,
73    pub version: SipVersion,
74}
75
76impl SipRequestLine {
77    pub fn reader(&self) -> SipRequestLineReader {
78        SipRequestLineReader {
79            method: &self.method,
80            uri: &self.uri,
81            version: match self.version {
82                SipVersion::V2_0 => SipVersion::V2_0,
83            },
84            pos: 0,
85        }
86    }
87}
88
89impl Serializable for SipRequestLine {
90    // fn serialize(&self) -> Vec<u8> {
91    //     let mut data = Vec::with_capacity(self.estimated_size());
92    //     data.extend(&self.method);
93    //     data.extend(b" ");
94    //     data.extend(&self.uri);
95    //     match &self.version {
96    //         SipVersion::V2_0 => {
97    //             data.extend(b" SIP/2.0");
98    //         }
99    //     }
100    //     data
101    // }
102
103    fn estimated_size(&self) -> usize {
104        let mut size = 0;
105        size += self.method.len();
106        size += 1;
107        size += self.uri.len();
108        match &self.version {
109            SipVersion::V2_0 => {
110                size += 8;
111            }
112        }
113        size
114    }
115}
116
117impl fmt::Debug for SipRequestLine {
118    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119        write!(
120            f,
121            "{} {} {}",
122            String::from_utf8_lossy(&self.method),
123            String::from_utf8_lossy(&self.uri),
124            self.version.to_string()
125        )
126    }
127}
128
129pub struct SipRequestLineReader<'a> {
130    method: &'a [u8],
131    uri: &'a [u8],
132    version: SipVersion,
133    pos: usize,
134}
135
136impl<'a> Read for SipRequestLineReader<'a> {
137    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
138        let mut i = 0;
139        while self.pos + i < self.method.len() && i < buf.len() {
140            buf[i] = self.method[self.pos + i];
141            i += 1;
142        }
143        while self.pos + i >= self.method.len()
144            && self.pos + i < self.method.len() + 1
145            && i < buf.len()
146        {
147            buf[i] = b' ';
148            i += 1;
149        }
150        while self.pos + i >= self.method.len() + 1
151            && self.pos + i < self.method.len() + 1 + self.uri.len()
152            && i < buf.len()
153        {
154            buf[i] = self.uri[self.pos + i - self.method.len() - 1];
155            i += 1;
156        }
157        match self.version {
158            SipVersion::V2_0 => {
159                while self.pos + i >= self.method.len() + 1 + self.uri.len()
160                    && self.pos + i < self.method.len() + 1 + self.uri.len() + 8
161                    && i < buf.len()
162                {
163                    buf[i] = b" SIP/2.0"[self.pos + i - self.method.len() - 1 - self.uri.len()];
164                    i += 1;
165                }
166            }
167        }
168        self.pos += i;
169        Ok(i)
170    }
171}
172
173pub struct SipResponseLine {
174    pub version: SipVersion,
175    pub status_code: u16,
176    pub reason_phrase: Vec<u8>,
177}
178
179impl SipResponseLine {
180    pub fn reader(&self) -> SipResponseLineReader {
181        SipResponseLineReader {
182            version: match self.version {
183                SipVersion::V2_0 => SipVersion::V2_0,
184            },
185            status_code: format!("{:0>3}", self.status_code),
186            reason_phrase: &self.reason_phrase,
187            pos: 0,
188        }
189    }
190}
191
192impl Serializable for SipResponseLine {
193    // fn serialize(&self) -> Vec<u8> {
194    //     let mut data = Vec::new();
195    //     match self.version {
196    //         SipVersion::V2_0 => {
197    //             data.extend(b"SIP/2.0 ");
198    //         }
199    //     }
200    //     data.extend(self.status_code.to_string().bytes());
201    //     data.extend(b" ");
202    //     data.extend(&self.reason_phrase);
203    //     data
204    // }
205
206    fn estimated_size(&self) -> usize {
207        let mut size = 0;
208        match self.version {
209            SipVersion::V2_0 => {
210                size += 8;
211            }
212        }
213        size += self.status_code.to_string().len();
214        size += 1;
215        size += self.reason_phrase.len();
216        size
217    }
218}
219
220impl fmt::Debug for SipResponseLine {
221    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222        write!(
223            f,
224            "{} {} {}",
225            self.version.to_string(),
226            self.status_code,
227            String::from_utf8_lossy(&self.reason_phrase)
228        )
229    }
230}
231
232pub struct SipResponseLineReader<'a> {
233    version: SipVersion,
234    status_code: String,
235    reason_phrase: &'a [u8],
236    pos: usize,
237}
238
239impl<'a> Read for SipResponseLineReader<'a> {
240    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
241        let mut i = 0;
242        let version_length;
243        match self.version {
244            SipVersion::V2_0 => {
245                version_length = 8;
246                while self.pos + i < 8 && i < buf.len() {
247                    buf[i] = b"SIP/2.0 "[self.pos + i];
248                    i += 1;
249                }
250            }
251        }
252        while self.pos + i >= version_length
253            && self.pos + i < version_length + self.status_code.as_bytes().len()
254            && i < buf.len()
255        {
256            buf[i] = self.status_code.as_bytes()[self.pos + i - version_length];
257            i += 1;
258        }
259        while self.pos + i >= version_length + self.status_code.as_bytes().len()
260            && self.pos + i < version_length + self.status_code.as_bytes().len() + 1
261            && i < buf.len()
262        {
263            buf[i] = b' ';
264            i += 1;
265        }
266        while self.pos + i >= version_length + self.status_code.as_bytes().len() + 1
267            && self.pos + i
268                < version_length + self.status_code.as_bytes().len() + 1 + self.reason_phrase.len()
269            && i < buf.len()
270        {
271            buf[i] = self.reason_phrase
272                [self.pos + i - version_length - self.status_code.as_bytes().len() - 1];
273            i += 1;
274        }
275        self.pos += i;
276        Ok(i)
277    }
278}
279
280pub enum SipFirstLine {
281    Request(SipRequestLine),
282    Response(SipResponseLine),
283}
284
285impl SipFirstLine {
286    pub fn decode_first_line(s: &[u8]) -> Result<Option<(SipFirstLine, usize)>, &str> {
287        let mut iter = s.iter();
288
289        if let Some(position) = iter.position(|c| *c == b'\r') {
290            if let Some(c) = iter.next() {
291                if *c == b'\n' {
292                    let mut iter = s[..position].splitn(3, |c| *c == b' ');
293
294                    if let Some(s1) = iter.next() {
295                        if let Some(s2) = iter.next() {
296                            if let Some(s3) = iter.next() {
297                                if s1 == SIP2_0_BYTES {
298                                    if let Ok(status_code) = s2.to_int() {
299                                        return Ok(Some((
300                                            SipFirstLine::Response(SipResponseLine {
301                                                version: SipVersion::V2_0,
302                                                status_code,
303                                                reason_phrase: s3.to_vec(),
304                                            }),
305                                            s1.len() + 1 + s2.len() + 1 + s3.len() + 2,
306                                        )));
307                                    } else {
308                                        return Err("invalid status code");
309                                    }
310                                } else if s3 == SIP2_0_BYTES {
311                                    return Ok(Some((
312                                        SipFirstLine::Request(SipRequestLine {
313                                            method: s1.to_vec(),
314                                            uri: s2.to_vec(),
315                                            version: SipVersion::V2_0,
316                                        }),
317                                        s1.len() + 1 + s2.len() + 1 + s3.len() + 2,
318                                    )));
319                                } else {
320                                    return Err("unknown sip version");
321                                }
322                            }
323                        }
324                    }
325                } else {
326                    return Err("bad format");
327                }
328            }
329        }
330
331        Ok(None)
332    }
333}
334
335pub enum SipMessage {
336    Request(SipRequestLine, Option<Vec<Header>>, Option<Arc<Body>>),
337    Response(SipResponseLine, Option<Vec<Header>>, Option<Arc<Body>>),
338    Ping,
339    Pong,
340}
341
342impl SipMessage {
343    pub fn new(
344        first_line: SipFirstLine,
345        headers: Option<Vec<Header>>,
346        body: Option<Arc<Body>>,
347    ) -> SipMessage {
348        match first_line {
349            SipFirstLine::Request(line) => SipMessage::Request(line, headers, body),
350            SipFirstLine::Response(line) => SipMessage::Response(line, headers, body),
351        }
352    }
353
354    pub fn new_request(method: &[u8], uri: &[u8]) -> SipMessage {
355        SipMessage::Request(
356            SipRequestLine {
357                method: method.to_vec(),
358                uri: uri.to_vec(),
359                version: SipVersion::V2_0,
360            },
361            None,
362            None,
363        )
364    }
365
366    pub fn new_response(status_code: u16, reason_phrase: &[u8]) -> SipMessage {
367        SipMessage::Response(
368            SipResponseLine {
369                version: SipVersion::V2_0,
370                status_code,
371                reason_phrase: reason_phrase.to_vec(),
372            },
373            None,
374            None,
375        )
376    }
377
378    pub fn headers(&self) -> Option<&[Header]> {
379        match self {
380            SipMessage::Request(_, headers, _) => {
381                if let Some(headers) = headers {
382                    return Some(&*headers);
383                }
384            }
385            SipMessage::Response(_, headers, _) => {
386                if let Some(headers) = headers {
387                    return Some(&*headers);
388                }
389            }
390            _ => {}
391        }
392
393        None
394    }
395
396    pub fn copy_headers(&self) -> Vec<Header> {
397        match self {
398            SipMessage::Request(_, headers, _) => {
399                if let Some(headers) = headers {
400                    return headers.clone();
401                }
402            }
403            SipMessage::Response(_, headers, _) => {
404                if let Some(headers) = headers {
405                    return headers.clone();
406                }
407            }
408            _ => {}
409        }
410
411        Vec::new()
412    }
413
414    pub fn add_header(&mut self, header: Header) {
415        match self {
416            SipMessage::Request(_, headers, _) => match headers {
417                Some(headers) => {
418                    headers.push(header);
419                }
420                None => {
421                    let mut v = Vec::new();
422                    v.push(header);
423                    headers.replace(v);
424                }
425            },
426            SipMessage::Response(_, headers, _) => match headers {
427                Some(headers) => {
428                    headers.push(header);
429                }
430                None => {
431                    let mut v = Vec::new();
432                    v.push(header);
433                    headers.replace(v);
434                }
435            },
436            _ => {}
437        }
438    }
439
440    pub fn add_header_at_front(&mut self, header: Header) {
441        match self {
442            SipMessage::Request(_, headers, _) => match headers {
443                Some(headers) => {
444                    let mut new_headers = Vec::new();
445                    new_headers.push(header);
446                    new_headers.append(headers);
447                    *headers = new_headers;
448                }
449                None => {
450                    let mut v = Vec::new();
451                    v.push(header);
452                    headers.replace(v);
453                }
454            },
455            SipMessage::Response(_, headers, _) => match headers {
456                Some(headers) => {
457                    let mut new_headers = Vec::new();
458                    new_headers.push(header);
459                    new_headers.append(headers);
460                    *headers = new_headers;
461                }
462                None => {
463                    let mut v = Vec::new();
464                    v.push(header);
465                    headers.replace(v);
466                }
467            },
468            _ => {}
469        }
470    }
471
472    pub fn set_body(&mut self, b: Arc<Body>) {
473        match self {
474            SipMessage::Request(_, _, body) => {
475                body.replace(b);
476            }
477            SipMessage::Response(_, _, body) => {
478                body.replace(b);
479            }
480            _ => {}
481        }
482    }
483
484    pub fn get_body(&self) -> Option<Arc<Body>> {
485        match self {
486            SipMessage::Request(_, _, body) | SipMessage::Response(_, _, body) => {
487                if let Some(body) = body {
488                    Some(Arc::clone(body))
489                } else {
490                    None
491                }
492            }
493            _ => None,
494        }
495    }
496
497    pub fn has_body(&self) -> bool {
498        match self {
499            SipMessage::Request(_, _, body) | SipMessage::Response(_, _, body) => body.is_some(),
500            _ => false,
501        }
502    }
503
504    pub fn get_readers<'a>(
505        &'a self,
506        readers: &mut Vec<Box<dyn Read + Send + 'a>>,
507    ) -> Result<(), BodySerializationError> {
508        match &self {
509            SipMessage::Request(line, headers, body) => {
510                readers.push(Box::new(line.reader()));
511                readers.push(Box::new(&b"\r\n"[..]));
512                if let Some(headers) = headers {
513                    headers_get_readers(headers, readers);
514                }
515                readers.push(Box::new(&b"\r\n"[..]));
516                if let Some(body) = body {
517                    readers.push(Box::new(body.reader()?));
518                }
519            }
520            SipMessage::Response(line, headers, body) => {
521                readers.push(Box::new(line.reader()));
522                readers.push(Box::new(&b"\r\n"[..]));
523                if let Some(headers) = headers {
524                    headers_get_readers(headers, readers);
525                }
526                readers.push(Box::new(&b"\r\n"[..]));
527                if let Some(body) = body {
528                    readers.push(Box::new(body.reader()?));
529                }
530            }
531            SipMessage::Ping => {
532                readers.push(Box::new(&b"\r\n\r\n"[..]));
533            }
534            SipMessage::Pong => {
535                readers.push(Box::new(&b"\r\n"[..]));
536            }
537        }
538
539        Ok(())
540    }
541}
542
543impl fmt::Debug for SipMessage {
544    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
545        match self {
546            SipMessage::Request(req_line, headers, body) => f
547                .debug_tuple("SipMessage")
548                .field(req_line)
549                .field(headers)
550                .field(body)
551                .finish(),
552            SipMessage::Response(resp_line, headers, body) => f
553                .debug_tuple("SipMessage")
554                .field(resp_line)
555                .field(headers)
556                .field(body)
557                .finish(),
558            SipMessage::Ping => write!(f, "Ping"),
559            SipMessage::Pong => write!(f, "Pong"),
560        }
561    }
562}
563
564impl fmt::Display for SipMessage {
565    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
566        fmt::Debug::fmt(self, f)
567    }
568}
569
570impl Serializable for SipMessage {
571    // fn serialize(&self) -> Vec<u8> {
572    //     let mut data = Vec::with_capacity(self.estimated_size());
573    //     match &self {
574    //         SipMessage::Request(line, headers, body) => {
575    //             data.extend(line.serialize());
576    //             data.extend(b"\r\n");
577    //             if let Some(headers) = headers {
578    //                 data.extend(headers.serialize());
579    //             }
580    //             data.extend(b"\r\n");
581    //             if let Some(body) = body {
582    //                 data.extend(body.serialize());
583    //             }
584    //         }
585    //         SipMessage::Response(line, headers, body) => {
586    //             data.extend(line.serialize());
587    //             data.extend(b"\r\n");
588    //             if let Some(headers) = headers {
589    //                 data.extend(headers.serialize());
590    //             }
591    //             data.extend(b"\r\n");
592    //             if let Some(body) = body {
593    //                 data.extend(body.serialize());
594    //             }
595    //         }
596    //         SipMessage::Ping => {
597    //             data.extend(b"\r\n\r\n");
598    //         }
599    //         SipMessage::Pong => {
600    //             data.extend(b"\r\n");
601    //         }
602    //     }
603    //     data
604    // }
605
606    fn estimated_size(&self) -> usize {
607        let mut size = 0;
608        match &self {
609            SipMessage::Request(line, headers, body) => {
610                size += line.estimated_size();
611                size += 2;
612                if let Some(headers) = headers {
613                    size += headers.estimated_size();
614                }
615                size += 2;
616                if let Some(body) = body {
617                    size += body.estimated_size();
618                }
619            }
620            SipMessage::Response(line, headers, body) => {
621                size += line.estimated_size();
622                size += 2;
623                if let Some(headers) = headers {
624                    size += headers.estimated_size();
625                }
626                size += 2;
627                if let Some(body) = body {
628                    size += body.estimated_size();
629                }
630            }
631            SipMessage::Ping => {
632                size += 4;
633            }
634            SipMessage::Pong => {
635                size += 2;
636            }
637        }
638        size
639    }
640}
641
642impl GetDialogHeaders for SipMessage {
643    fn get_dialog_headers<'a>(&'a self) -> Option<(&'a Header, HeaderField<'a>, HeaderField<'a>)> {
644        if let Some(headers) = self.headers() {
645            if let (Some(call_id_header), Some(from_header), Some(to_header)) = (
646                header::search(headers, b"Call-ID", true),
647                header::search(headers, b"From", true),
648                header::search(headers, b"To", true),
649            ) {
650                return Some((
651                    call_id_header,
652                    from_header.get_value().as_header_field(),
653                    to_header.get_value().as_header_field(),
654                ));
655            }
656        }
657
658        None
659    }
660}
661
662// to-do: via headers should be attached before send
663pub fn corresponding_cancel(invite_message: &SipMessage) -> Result<SipMessage, &'static str> {
664    match invite_message {
665        SipMessage::Request(req_line, headers, _) => {
666            if let Some(headers) = headers {
667                let call_id_header = header::search(headers, b"Call-ID", true);
668                let cseq_header = header::search(headers, b"CSeq", true);
669                let from_header = header::search(headers, b"From", true);
670                let to_header = header::search(headers, b"To", true);
671                let via_header = header::search(headers, b"Via", true);
672
673                if let (
674                    Some(call_id_header),
675                    Some(cseq_header),
676                    Some(from_header),
677                    Some(to_header),
678                    Some(via_header),
679                ) = (
680                    call_id_header,
681                    cseq_header,
682                    from_header,
683                    to_header,
684                    via_header,
685                ) {
686                    let cseq_header_field = cseq_header.get_value().as_header_field();
687                    let cseq = cseq_header_field.as_cseq();
688                    if let Some(cseq) = cseq {
689                        let mut message = SipMessage::new_request(CANCEL, &req_line.uri);
690
691                        message.add_header(Header::new(
692                            b"Call-ID",
693                            call_id_header.get_value().to_vec(),
694                        ));
695
696                        let cseq = format!("{} CANCEL", cseq.seq);
697
698                        message.add_header(Header::new(b"CSeq", cseq));
699
700                        message.add_header(Header::new(b"From", from_header.get_value().to_vec()));
701
702                        message.add_header(Header::new(b"To", to_header.get_value().to_vec()));
703
704                        message.add_header(Header::new(b"Via", via_header.get_value().to_vec()));
705
706                        return Ok(message);
707                    }
708                }
709            }
710        }
711
712        _ => {}
713    }
714
715    Err("Missing information")
716}
717
718pub fn build_message_data(message: &SipMessage) -> Vec<u8> {
719    platform_log(LOG_TAG, "calling sip_message->build_message_data()");
720
721    let data_size = message.estimated_size();
722    let mut data = Vec::with_capacity(data_size);
723    {
724        let mut readers = Vec::new();
725        match message.get_readers(&mut readers) {
726            Ok(_) => {
727                match DynamicChain::new(readers).read_to_end(&mut data) {
728                    Ok(_) => {}
729                    Err(_) => {
730                        platform_log(LOG_TAG, "build_message_data() read error");
731                        // to-do: early failure
732                    }
733                }
734            }
735            Err(_) => {
736                platform_log(LOG_TAG, "build_message_data() read error");
737                // to-do: early failure
738            }
739        }
740    }
741
742    data
743}