sip_codec/
codec.rs

1//! # A tokio-codec for sending and receiving SIP messages
2use std::io;
3use std::num::NonZeroUsize;
4
5use bytes::BytesMut;
6use nom::Err::{Error, Failure, Incomplete};
7use tokio_codec::{Decoder, Encoder};
8
9use crate::Message;
10use crate::parser::parse_request;
11
12/// # A [tokio-codec] for sending and receiving SIP messages
13///
14/// `SIPCodec` will automatically turn raw text into [`Message`]s, and vice versa. This can
15/// be used to easily interface with tokio streams, as they have built-in support for codecs.
16/// See the [Tokio docs] on framed streams for more.
17///
18/// Currently, it only supports decoding SIP requests.
19///
20/// [tokio-codec]: https://docs.rs/tokio-codec/
21/// [Tokio docs]: https://tokio.rs/docs/going-deeper/frames/
22#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
23pub struct SIPCodec {
24	max_size: Option<NonZeroUsize>,
25}
26
27impl Default for SIPCodec {
28	fn default() -> Self {
29		Self { max_size: NonZeroUsize::new(2_000_000) }
30	}
31}
32
33impl Decoder for SIPCodec {
34	type Item = Message;
35	type Error = std::io::Error;
36
37	fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
38		match parse_request(&src[..]) {
39			Err(Incomplete(_)) | Err(Error(_)) => Ok(None),
40			Err(Failure(err)) => Err(io::Error::new(
41				io::ErrorKind::InvalidData,
42				format!("{:?}", err),
43			)),
44			Ok((remaining, req)) => {
45				let remaining_size = remaining.as_ptr() as usize - src.as_ptr() as usize;
46				src.split_to(remaining_size);
47				Ok(Some(Message::Request(req)))
48			}
49		}
50	}
51}
52
53impl Encoder for SIPCodec {
54	type Item = Message;
55	type Error = std::io::Error;
56
57	fn encode(&mut self, item: Self::Item, buf: &mut BytesMut) -> Result<(), Self::Error> {
58		match item {
59			Message::Response(res) => {
60				res.write_buf(buf);
61			}
62			Message::Request(_req) => unimplemented!()
63		}
64		Ok(())
65	}
66}
67
68#[cfg(test)]
69mod tests {
70	use bytes::BytesMut;
71	use http::header::HeaderValue;
72	use http::HeaderMap;
73	use tokio_codec::Decoder;
74
75	use crate::{Message, Request, SIPCodec};
76
77	#[test]
78	fn test() {
79		let mut bytes = BytesMut::new();
80		let mut codec = SIPCodec::default();
81		let initial = b"GET sip:user@server:port SIP/2.0\r\na:b\r\nContent-length: 7\r\n\r\nabcdef";
82		bytes.extend_from_slice(initial);
83		assert_eq!(None, codec.decode(&mut bytes).unwrap());
84		bytes.extend_from_slice(b"g");
85		let expected = {
86			let mut headers = HeaderMap::new();
87			headers.insert("a", HeaderValue::from_static("b"));
88			headers.insert("content-length", HeaderValue::from_static("7"));
89			Some(Message::Request(Request {
90				method: "GET".into(),
91				uri: "sip:user@server:port".into(),
92				sip_version: Default::default(),
93				headers,
94				body: b"abcdefg".to_vec(),
95			}))
96		};
97		assert_eq!(expected, codec.decode(&mut bytes).unwrap());
98	}
99}