atm0s_media_server_transport_sip/sip/
sip_request.rs

1use std::fmt::Debug;
2
3use rsip::{
4    headers::{Authorization, ContentLength, ContentType, UserAgent},
5    prelude::ToTypedHeader,
6    typed::Contact,
7    StatusCode,
8};
9
10use super::sip_response::SipResponse;
11
12#[derive(Debug)]
13pub enum RequiredHeader {
14    CallId,
15    CSeq,
16    From,
17    To,
18    Via,
19}
20
21#[derive(Debug)]
22pub enum SipRequestError {
23    Missing(RequiredHeader),
24}
25
26#[derive(Clone, PartialEq, Eq)]
27pub struct SipRequest {
28    pub raw: rsip::Request,
29    pub call_id: rsip::headers::CallId,
30    pub cseq: rsip::headers::typed::CSeq,
31    pub from: rsip::headers::typed::From,
32    pub to: rsip::headers::typed::To,
33    pub via: rsip::headers::typed::Via,
34    pub timestamp: Option<rsip::headers::Timestamp>,
35}
36
37impl Debug for SipRequest {
38    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39        f.debug_struct("SipRequest")
40            .field("method", &self.raw.method)
41            .field("call_id", &self.call_id)
42            .field("cseq", &self.cseq)
43            .field("from", &self.from)
44            .field("to", &self.to)
45            .field("via", &self.via)
46            .field("timestamp", &self.timestamp)
47            .finish()
48    }
49}
50
51impl SipRequest {
52    pub fn from(sip_request: rsip::Request) -> Result<Self, SipRequestError> {
53        let mut call_id: Option<rsip::headers::CallId> = None;
54        let mut cseq: Option<rsip::headers::typed::CSeq> = None;
55        let mut from: Option<rsip::headers::typed::From> = None;
56        let mut to: Option<rsip::headers::typed::To> = None;
57        let mut via: Option<rsip::headers::typed::Via> = None;
58        let mut timestamp: Option<rsip::headers::Timestamp> = None;
59
60        for header in sip_request.headers.iter() {
61            match header {
62                rsip::Header::CallId(header) => {
63                    call_id = Some(header.clone());
64                }
65                rsip::Header::CSeq(header) => {
66                    cseq = Some(header.clone().into_typed().expect("Should be valid CSeq"));
67                }
68                rsip::Header::From(header) => {
69                    from = Some(header.clone().into_typed().expect("Should be valid From"));
70                }
71                rsip::Header::To(header) => {
72                    to = Some(header.clone().into_typed().expect("Should be valid To"));
73                }
74                rsip::Header::Via(header) => {
75                    via = Some(header.clone().into_typed().expect("Should be valid Via"));
76                }
77                rsip::Header::Timestamp(header) => {
78                    timestamp = Some(header.clone());
79                }
80                _ => {}
81            }
82        }
83
84        if call_id.is_none() {
85            return Err(SipRequestError::Missing(RequiredHeader::CallId));
86        }
87        if cseq.is_none() {
88            return Err(SipRequestError::Missing(RequiredHeader::CSeq));
89        }
90        if from.is_none() {
91            return Err(SipRequestError::Missing(RequiredHeader::From));
92        }
93        if to.is_none() {
94            return Err(SipRequestError::Missing(RequiredHeader::To));
95        }
96        if via.is_none() {
97            return Err(SipRequestError::Missing(RequiredHeader::Via));
98        }
99
100        Ok(Self {
101            raw: sip_request,
102            call_id: call_id.expect("Must some"),
103            cseq: cseq.expect("Must some"),
104            from: from.expect("Must some"),
105            to: to.expect("Must some"),
106            via: via.expect("Must some"),
107            timestamp,
108        })
109    }
110
111    pub fn method(&self) -> &rsip::Method {
112        &self.raw.method
113    }
114
115    pub fn digest_uri(&self) -> String {
116        self.raw.uri().to_string()
117    }
118
119    pub fn body_str(&self) -> String {
120        String::from_utf8_lossy(&self.raw.body).to_string()
121    }
122
123    pub fn header_authorization(&self) -> Option<&Authorization> {
124        for header in self.raw.headers.iter() {
125            match header {
126                rsip::Header::Authorization(auth) => return Some(auth),
127                _ => {}
128            }
129        }
130        None
131    }
132
133    pub fn header_contact(&self) -> Option<Contact> {
134        for header in self.raw.headers.iter() {
135            match header {
136                rsip::Header::Contact(contact) => return Some(contact.typed().ok()?),
137                _ => {}
138            }
139        }
140        None
141    }
142
143    pub fn build_response(&self, code: StatusCode, body: Option<(ContentType, Vec<u8>)>) -> SipResponse {
144        let mut headers: rsip::Headers = Default::default();
145        headers.push(rsip::Header::Via(self.via.clone().into()));
146        headers.push(rsip::Header::From(self.from.clone().into()));
147        headers.push(rsip::Header::To(self.to.clone().into()));
148        headers.push(rsip::Header::CallId(self.call_id.clone()));
149        headers.push(rsip::Header::CSeq(self.cseq.clone().into()));
150        let body_len = body.as_ref().map(|(_, body)| body.len()).unwrap_or(0);
151        headers.push(rsip::Header::ContentLength(ContentLength::from(body_len as u32)));
152        headers.push(rsip::Header::UserAgent(UserAgent::from("8xff-sip-media-server")));
153
154        if let Some((content_type, _)) = &body {
155            headers.push(rsip::Header::ContentType(content_type.clone()));
156        }
157
158        if code == StatusCode::Trying {
159            if let Some(ts) = &self.timestamp {
160                headers.push(rsip::Header::Timestamp(ts.clone()));
161            }
162        }
163
164        SipResponse::from(rsip::Response {
165            status_code: code,
166            headers,
167            version: rsip::Version::V2,
168            body: body.map(|(_, body)| body).unwrap_or(vec![]),
169        })
170        .expect("Should be valid response")
171    }
172
173    pub fn to_bytes(self) -> bytes::Bytes {
174        self.raw.into()
175    }
176}