ftth_rsip/message/
request.rs

1#[doc(hidden)]
2pub use tokenizer::Tokenizer;
3
4use crate::{
5    common::{
6        method::{self, Method},
7        uri::{self, Uri},
8        version::{self, Version},
9    },
10    headers::{header, Headers},
11    Error, SipMessage,
12};
13use std::convert::{TryFrom, TryInto};
14
15/// Request reprsents a SIP request message, which contains a [Method](crate::Method),
16/// a [Uri](crate::Uri), a [Version](crate::Version), [Headers](crate::Headers) and a
17/// body, represented as a `Vec<u8>`, thus not checked for UTF-8 compliance.
18///
19/// A Request can easily be transformed to a [SipMessage](crate::SipMessage).
20/// Also it can be converted to a `String`, `&str`, or `Bytes`, all using the underlying `Debug`
21/// trait.
22///
23/// In order to access specific [headers](crate::headers::untyped), you should take a look on the
24/// [HeadersExt](crate::message::HeadersExt) trait that is automatically implemented for any type
25/// that has implemented the [HasHeaders](crate::message::HasHeaders) trait, which Request
26/// implements it.
27#[derive(Debug, PartialEq, Eq, Clone)]
28pub struct Request {
29    pub method: Method,
30    pub uri: Uri,
31    pub version: Version,
32    pub headers: Headers,
33    pub body: Vec<u8>,
34}
35
36impl Request {
37    pub fn method(&self) -> &Method {
38        &self.method
39    }
40
41    pub fn uri(&self) -> &Uri {
42        &self.uri
43    }
44
45    pub fn version(&self) -> &Version {
46        &self.version
47    }
48
49    pub fn body(&self) -> &Vec<u8> {
50        &self.body
51    }
52
53    pub fn body_mut(&mut self) -> &mut Vec<u8> {
54        &mut self.body
55    }
56}
57
58impl super::HasHeaders for Request {
59    fn headers(&self) -> &Headers {
60        &self.headers
61    }
62
63    fn headers_mut(&mut self) -> &mut Headers {
64        &mut self.headers
65    }
66}
67
68impl std::fmt::Display for Request {
69    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70        write!(
71            f,
72            "{} {} {}\r\n{}\r\n{}",
73            self.method,
74            self.uri,
75            self.version,
76            self.headers,
77            String::from_utf8_lossy(&self.body)
78        )
79    }
80}
81
82impl TryFrom<SipMessage> for Request {
83    type Error = crate::Error;
84
85    fn try_from(sip_message: crate::SipMessage) -> Result<Self, Self::Error> {
86        match sip_message {
87            crate::SipMessage::Request(request) => Ok(request),
88            crate::SipMessage::Response(_) => Err(Error::Unexpected(
89                "Can't convert a models::SipMessage::Response into Request !".into(),
90            )),
91        }
92    }
93}
94
95impl TryFrom<&[u8]> for Request {
96    type Error = Error;
97
98    fn try_from(from: &[u8]) -> Result<Self, Self::Error> {
99        Tokenizer::tokenize(from)?.1.try_into()
100    }
101}
102
103impl TryFrom<Vec<u8>> for Request {
104    type Error = Error;
105
106    fn try_from(from: Vec<u8>) -> Result<Self, Self::Error> {
107        Tokenizer::tokenize(&from)?.1.try_into()
108    }
109}
110
111impl TryFrom<&str> for Request {
112    type Error = Error;
113
114    fn try_from(from: &str) -> Result<Self, Self::Error> {
115        Tokenizer::tokenize(from.as_bytes())?.1.try_into()
116    }
117}
118
119impl TryFrom<String> for Request {
120    type Error = Error;
121
122    fn try_from(from: String) -> Result<Self, Self::Error> {
123        Tokenizer::tokenize(from.as_bytes())?.1.try_into()
124    }
125}
126
127impl TryFrom<bytes::Bytes> for Request {
128    type Error = Error;
129
130    fn try_from(from: bytes::Bytes) -> Result<Self, Self::Error> {
131        Tokenizer::tokenize(&from)?.1.try_into()
132    }
133}
134
135impl From<Request> for String {
136    fn from(req: Request) -> Self {
137        req.to_string()
138    }
139}
140
141impl From<Request> for Vec<u8> {
142    fn from(req: Request) -> Self {
143        req.to_string().into_bytes()
144    }
145}
146
147impl From<Request> for bytes::Bytes {
148    fn from(req: Request) -> Self {
149        Self::from(req.to_string())
150    }
151}
152
153#[doc(hidden)]
154pub mod tokenizer {
155    use super::{header, method, uri, version, Request};
156    use crate::{Error, IResult, NomError, TokenizerError};
157    use std::convert::TryInto;
158
159    impl<'a> TryInto<Request> for Tokenizer<'a> {
160        type Error = Error;
161
162        fn try_into(self) -> Result<Request, Error> {
163            Ok(Request {
164                method: self.method.try_into()?,
165                uri: self.uri.try_into()?,
166                version: self.version.try_into()?,
167                headers: self
168                    .headers
169                    .into_iter()
170                    .map(TryInto::try_into)
171                    .collect::<Result<Vec<_>, Error>>()?
172                    .into(),
173                body: self.body.into(),
174            })
175        }
176    }
177
178    #[derive(Debug, PartialEq, Eq)]
179    pub struct Tokenizer<'a> {
180        pub method: method::Tokenizer<'a, &'a [u8], u8>,
181        pub uri: uri::Tokenizer<'a, &'a [u8], u8>,
182        pub version: version::Tokenizer<'a, &'a [u8], u8>,
183        pub headers: Vec<header::Tokenizer<'a>>,
184        pub body: &'a [u8],
185    }
186
187    impl<'a> Tokenizer<'a> {
188        pub fn tokenize(part: &'a [u8]) -> IResult<Self> {
189            use crate::parser_utils::is_empty_or_fail_with;
190            use nom::{
191                branch::alt,
192                bytes::complete::{tag, take_until},
193                multi::many0,
194                sequence::tuple,
195            };
196
197            let (rem, (method, _, uri, _, version, _)) = tuple((
198                method::Tokenizer::tokenize,
199                tag(" "),
200                uri::Tokenizer::tokenize,
201                tag(" "),
202                version::Tokenizer::tokenize,
203                tag("\r\n"),
204            ))(part)?;
205
206            let (body, (raw_headers, _)) = alt((
207                tuple((take_until("\r\n\r\n"), tag("\r\n\r\n"))),
208                tuple((take_until("\r\n"), tag("\r\n"))),
209            ))(rem)
210            .map_err(|_: NomError<'a>| TokenizerError::from(("headers", rem)).into())?;
211            let (rem, headers) = many0(header::Tokenizer::tokenize)(raw_headers)?;
212            is_empty_or_fail_with(rem, ("headers", rem))?;
213
214            Ok((
215                &[],
216                Self {
217                    method,
218                    uri,
219                    version,
220                    headers,
221                    body,
222                },
223            ))
224        }
225    }
226}