diff options
author | metamuffin <metamuffin@disroot.org> | 2024-07-06 01:19:02 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-07-06 01:19:02 +0200 |
commit | 5dd0fafce20ed37fdc97dc96539391ebdebffaff (patch) | |
tree | ad93b9e8d0e9c9c7dbe5a858902c2ba0114a47cf /src/encoding | |
parent | a4c52bedef04cfb927f3d7809680fed0425a5125 (diff) | |
download | sip-rs-5dd0fafce20ed37fdc97dc96539391ebdebffaff.tar sip-rs-5dd0fafce20ed37fdc97dc96539391ebdebffaff.tar.bz2 sip-rs-5dd0fafce20ed37fdc97dc96539391ebdebffaff.tar.zst |
generalize to support requests. untested
Diffstat (limited to 'src/encoding')
-rw-r--r-- | src/encoding/headermap.rs | 13 | ||||
-rw-r--r-- | src/encoding/headers.rs | 1 | ||||
-rw-r--r-- | src/encoding/mod.rs | 30 | ||||
-rw-r--r-- | src/encoding/request.rs | 34 | ||||
-rw-r--r-- | src/encoding/response.rs | 9 | ||||
-rw-r--r-- | src/encoding/status.rs | 3 | ||||
-rw-r--r-- | src/encoding/uri.rs | 12 |
7 files changed, 89 insertions, 13 deletions
diff --git a/src/encoding/headermap.rs b/src/encoding/headermap.rs index 65ef8d2..5d1fa0a 100644 --- a/src/encoding/headermap.rs +++ b/src/encoding/headermap.rs @@ -1,5 +1,5 @@ use super::headers::Header; -use anyhow::Result; +use anyhow::{anyhow, Result}; use std::fmt::Display; #[derive(Debug, Clone)] @@ -38,6 +38,17 @@ impl Display for HeaderMap { Ok(()) } } +impl HeaderMap { + pub fn parse<'a>(lines: &mut impl Iterator<Item = &'a str>) -> Result<Self> { + let mut headers = HeaderMap::new(); + for line in lines { + // TODO multiline values + let (key, value) = line.split_once(":").ok_or(anyhow!("header malformed"))?; + headers.insert_raw(key.trim().to_string(), value.trim().to_string()) + } + Ok(headers) + } +} impl FromIterator<(String, String)> for HeaderMap { fn from_iter<T: IntoIterator<Item = (String, String)>>(iter: T) -> Self { diff --git a/src/encoding/headers.rs b/src/encoding/headers.rs index 60dca7f..9e785f0 100644 --- a/src/encoding/headers.rs +++ b/src/encoding/headers.rs @@ -28,6 +28,7 @@ pub trait Header: FromStr<Err = anyhow::Error> + Display { } header!("Content-Length", struct ContentLength(usize)); +header!("Content-Type", struct ContentType(String)); header!("Call-ID", struct CallID(String)); header!("Via", struct Via(String)); header!("Contact", struct Contact(String)); diff --git a/src/encoding/mod.rs b/src/encoding/mod.rs index a7dd227..f0796c8 100644 --- a/src/encoding/mod.rs +++ b/src/encoding/mod.rs @@ -1,3 +1,8 @@ +use std::{fmt::Display, str::FromStr}; + +use request::Request; +use response::Response; + pub mod headermap; pub mod headers; pub mod method; @@ -5,3 +10,28 @@ pub mod request; pub mod response; pub mod status; pub mod uri; + +#[derive(Debug, Clone)] +pub enum Message { + Request(Request), + Response(Response), +} + +impl Display for Message { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Message::Request(r) => write!(f, "{r}"), + Message::Response(r) => write!(f, "{r}"), + } + } +} +impl FromStr for Message { + type Err = anyhow::Error; + fn from_str(s: &str) -> Result<Self, Self::Err> { + if s.starts_with("SIP/") { + Response::from_str(s).map(Message::Response) + } else { + Request::from_str(s).map(Message::Request) + } + } +} diff --git a/src/encoding/request.rs b/src/encoding/request.rs index aecd006..c62bab3 100644 --- a/src/encoding/request.rs +++ b/src/encoding/request.rs @@ -1,5 +1,6 @@ use super::{headermap::HeaderMap, method::Method, uri::Uri}; -use std::fmt::Display; +use anyhow::{anyhow, bail}; +use std::{fmt::Display, str::FromStr}; #[derive(Debug, Clone)] pub struct Request { @@ -20,3 +21,34 @@ impl Display for Request { Ok(()) } } +impl FromStr for Request { + type Err = anyhow::Error; + fn from_str(s: &str) -> Result<Self, Self::Err> { + let mut lines = s.lines(); + let statusline = lines.next().ok_or(anyhow!("status line missing"))?; + let (method, rest) = statusline + .split_once(" ") + .ok_or(anyhow!("status line malformed"))?; + let (uri, sipver) = rest + .split_once(" ") + .ok_or(anyhow!("status line malformed"))?; + + let Some(ver) = sipver.strip_prefix("SIP/") else { + bail!("sip version malformed"); + }; + if ver != "2.0" { + bail!("sip version {ver:?} is not supported"); + } + + let uri = Uri::from_str(uri)?; + + let headers = HeaderMap::parse(&mut lines)?; + let method = Method::from_str(method)?; + + Ok(Self { + headers, + method, + uri, + }) + } +} diff --git a/src/encoding/response.rs b/src/encoding/response.rs index 7ee124f..ffd2878 100644 --- a/src/encoding/response.rs +++ b/src/encoding/response.rs @@ -2,7 +2,7 @@ use super::{headermap::HeaderMap, status::Status}; use anyhow::{anyhow, bail, Context}; use std::{fmt::Display, str::FromStr}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Response { pub status: Status, pub headers: HeaderMap, @@ -28,12 +28,7 @@ impl FromStr for Response { bail!("sip version {ver:?} is not supported"); } - let mut headers = HeaderMap::new(); - for line in lines { - // TODO multiline values - let (key, value) = line.split_once(":").ok_or(anyhow!("header malformed"))?; - headers.insert_raw(key.trim().to_string(), value.trim().to_string()) - } + let headers = HeaderMap::parse(&mut lines)?; let status = Status::from_code(code); Ok(Self { status, headers }) diff --git a/src/encoding/status.rs b/src/encoding/status.rs index f06110d..9fe03d7 100644 --- a/src/encoding/status.rs +++ b/src/encoding/status.rs @@ -1,7 +1,6 @@ - macro_rules! status_enum { ($v:vis enum $name:ident { $($variant:ident = $value:literal),*, }) => { - #[derive(Debug)] + #[derive(Debug, Clone)] $v enum $name { $($variant),*, Other(u16) } impl $name { pub fn from_code(c: u16) -> Self { match c { $($value => Self::$variant),*, x => Self::Other(x) } } } impl $name { pub fn to_code(&self) -> u16 { match self { $(Self::$variant => $value),*, Self::Other(x) => *x } } } diff --git a/src/encoding/uri.rs b/src/encoding/uri.rs index 7aeefdb..a56cad4 100644 --- a/src/encoding/uri.rs +++ b/src/encoding/uri.rs @@ -1,6 +1,6 @@ -use std::fmt::Display; +use std::{fmt::Display, str::FromStr}; -#[derive(Debug,Clone)] +#[derive(Debug, Clone)] pub struct Uri { pub content: String, } @@ -11,3 +11,11 @@ impl Display for Uri { Ok(()) } } +impl FromStr for Uri { + type Err = anyhow::Error; + fn from_str(s: &str) -> Result<Self, Self::Err> { + Ok(Self { + content: s.to_string(), + }) + } +} |