atm0s_media_server_transport_sip/sip/
sip_request.rs1use 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}