aboutsummaryrefslogtreecommitdiff
path: root/src/encoding
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-07-06 01:19:02 +0200
committermetamuffin <metamuffin@disroot.org>2024-07-06 01:19:02 +0200
commit5dd0fafce20ed37fdc97dc96539391ebdebffaff (patch)
treead93b9e8d0e9c9c7dbe5a858902c2ba0114a47cf /src/encoding
parenta4c52bedef04cfb927f3d7809680fed0425a5125 (diff)
downloadsip-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.rs13
-rw-r--r--src/encoding/headers.rs1
-rw-r--r--src/encoding/mod.rs30
-rw-r--r--src/encoding/request.rs34
-rw-r--r--src/encoding/response.rs9
-rw-r--r--src/encoding/status.rs3
-rw-r--r--src/encoding/uri.rs12
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(),
+ })
+ }
+}