libsip/core/
message.rs

1use nom::{branch::alt, character::*, IResult};
2
3use std::fmt;
4
5use crate::{
6    core::{code::error_code_to_str, method::parse_method, version::parse_version},
7    headers::parse_header,
8    parse::{parse_byte_vec, parse_u32, slice_to_string},
9    uri::parse_uri,
10    SipMessageExt, *,
11};
12
13/// Sip Protocol Message.
14#[derive(Debug, PartialEq, Clone)]
15pub enum SipMessage {
16    Request {
17        method: Method,
18        uri: Uri,
19        version: Version,
20        headers: Headers,
21        body: Vec<u8>,
22    },
23    Response {
24        code: u32,
25        version: Version,
26        headers: Headers,
27        body: Vec<u8>,
28    },
29}
30
31impl SipMessage {
32    /// Determine if this is a SIP request.
33    pub fn is_request(&self) -> bool {
34        if let SipMessage::Request { .. } = self {
35            true
36        } else {
37            false
38        }
39    }
40
41    /// Determine if this is a SIP response.
42    pub fn is_response(&self) -> bool {
43        if let SipMessage::Response { .. } = self {
44            true
45        } else {
46            false
47        }
48    }
49
50    pub fn method(&self) -> Option<Method> {
51        match self {
52            Self::Request { method, .. } => Some(*method),
53            Self::Response { .. } => self.cseq().map(|(_, method)| method),
54        }
55    }
56
57    /// Retreive the SIP response's status code.
58    /// Returns None for requests.
59    pub fn status_code(&self) -> Option<u32> {
60        if let SipMessage::Response { code, .. } = self {
61            Some(*code)
62        } else {
63            None
64        }
65    }
66
67    /// Retreive the body of this SIP Message.
68    pub fn body(&self) -> &Vec<u8> {
69        match self {
70            SipMessage::Request { body, .. } => body,
71            SipMessage::Response { body, .. } => body,
72        }
73    }
74
75    /// Retreive a mutable reference to the SIP Messages body.
76    pub fn body_mut(&mut self) -> &mut Vec<u8> {
77        match self {
78            SipMessage::Request { body, .. } => body,
79            SipMessage::Response { body, .. } => body,
80        }
81    }
82
83    /// Retreive headers from the SIP message.
84    pub fn headers(&self) -> &Headers {
85        match self {
86            SipMessage::Request { headers, .. } => headers,
87            SipMessage::Response { headers, .. } => headers,
88        }
89    }
90
91    /// Retreive a mutable reference to the SIP Message's header list.
92    pub fn headers_mut(&mut self) -> &mut Headers {
93        match self {
94            SipMessage::Request { headers, .. } => headers,
95            SipMessage::Response { headers, .. } => headers,
96        }
97    }
98}
99
100impl fmt::Display for SipMessage {
101    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
102        match self {
103            SipMessage::Request {
104                method,
105                uri,
106                version,
107                headers,
108                body,
109            } => {
110                writeln!(f, "{} {} {}\r", method, uri, version)?;
111                display_headers_and_body(f, headers, body)
112            },
113            SipMessage::Response {
114                code,
115                version,
116                headers,
117                body,
118            } => {
119                if let Some(desc) = error_code_to_str(*code) {
120                    writeln!(f, "{} {} {}\r", version, code, desc)?;
121                } else {
122                    writeln!(f, "{} {}\r", version, code)?;
123                }
124                display_headers_and_body(f, headers, body)
125            },
126        }
127    }
128}
129
130/// Write the headers and body of a SIP message.
131pub fn display_headers_and_body(
132    f: &mut fmt::Formatter,
133    headers: &Headers,
134    body: &[u8],
135) -> Result<(), fmt::Error> {
136    for header in headers.iter() {
137        writeln!(f, "{}\r", header)?;
138    }
139    writeln!(f, "\r")?;
140    f.write_str(&String::from_utf8_lossy(&body))?;
141    Ok(())
142}
143
144/// Parse SIP headers recursivily
145pub fn parse_headers<'a, E: ParseError<&'a [u8]>>(
146    input: &'a [u8],
147) -> IResult<&'a [u8], Headers, E> {
148    let mut headers = Headers(vec![]);
149    let mut input = input;
150    while let Ok((data, value)) = parse_header::<E>(input) {
151        headers.push(value);
152        input = data;
153    }
154    Ok((input, headers))
155}
156
157use nom::{
158    bytes::complete::{tag, take_while},
159    character::complete::char,
160    combinator::{map_res, opt},
161    error::ParseError,
162};
163
164/// Parse a SIP message assuming it is a SIP response.
165pub fn parse_response<'a, E: ParseError<&'a [u8]>>(
166    input: &'a [u8],
167) -> IResult<&'a [u8], SipMessage, E> {
168    let (input, version) = parse_version::<E>(input)?;
169    let (input, _) = char(' ')(input)?;
170    let (input, code) = map_res(take_while(is_digit), parse_u32)(input)?;
171    let (input, _) = char(' ')(input)?;
172    let (input, _) = opt(map_res::<_, _, _, _, E, _, _>(
173        take_while(|item| is_alphabetic(item) || is_space(item)),
174        slice_to_string,
175    ))(input)?;
176    let (input, _) = opt(char(' '))(input)?;
177    let (input, _) = tag("\r\n")(input)?;
178    let (input, headers) = parse_headers::<E>(input)?;
179    let (input, _) = tag("\r\n")(input)?;
180    let (input, body) = parse_byte_vec::<E>(input)?;
181    Ok((
182        input,
183        SipMessage::Response {
184            code,
185            version,
186            headers,
187            body,
188        },
189    ))
190}
191
192/// Parse a SIP message assuming it is a SIP request.
193pub fn parse_request<'a, E: ParseError<&'a [u8]>>(
194    input: &'a [u8],
195) -> IResult<&'a [u8], SipMessage, E> {
196    let (input, method) = parse_method(input)?;
197    let (input, _) = char(' ')(input)?;
198    let (input, uri) = parse_uri(input)?;
199    let (input, _) = char(' ')(input)?;
200    let (input, version) = parse_version(input)?;
201    let (input, _) = opt(char(' '))(input)?;
202    let (input, _) = tag("\r\n")(input)?;
203    let (input, headers) = parse_headers(input)?;
204    let (input, _) = tag("\r\n")(input)?;
205    let (input, body) = parse_byte_vec(input)?;
206    Ok((
207        input,
208        SipMessage::Request {
209            method,
210            uri,
211            version,
212            headers,
213            body,
214        },
215    ))
216}
217
218/// This is the main parsing function for libsip.
219pub fn parse_message<'a, E: ParseError<&'a [u8]>>(
220    input: &'a [u8],
221) -> IResult<&'a [u8], SipMessage, E> {
222    alt::<_, _, E, _>((parse_request::<E>, parse_response::<E>))(input)
223}