aboutsummaryrefslogtreecommitdiff
path: root/src/encoding
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-07-05 02:27:48 +0200
committermetamuffin <metamuffin@disroot.org>2024-07-05 02:27:48 +0200
commit384ddd782b989218ceb55b7147aa8698425d1464 (patch)
tree5bfb61317db2e9260129b53b8444f3c79a0bc708 /src/encoding
parent3f80205783bcf6a2ed682f6f21e5b1877d597328 (diff)
downloadsip-rs-384ddd782b989218ceb55b7147aa8698425d1464.tar
sip-rs-384ddd782b989218ceb55b7147aa8698425d1464.tar.bz2
sip-rs-384ddd782b989218ceb55b7147aa8698425d1464.tar.zst
simpletransaction works
Diffstat (limited to 'src/encoding')
-rw-r--r--src/encoding/headermap.rs18
-rw-r--r--src/encoding/headers.rs71
-rw-r--r--src/encoding/method.rs18
-rw-r--r--src/encoding/request.rs1
-rw-r--r--src/encoding/uri.rs1
5 files changed, 104 insertions, 5 deletions
diff --git a/src/encoding/headermap.rs b/src/encoding/headermap.rs
index 313d8b5..2f9f097 100644
--- a/src/encoding/headermap.rs
+++ b/src/encoding/headermap.rs
@@ -13,11 +13,17 @@ impl HeaderMap {
self.0.push((H::NAME.to_string(), format!("{h}")));
self
}
- pub fn get<H: Header>(&self) -> Option<Result<H>> {
+ pub fn insert<H: Header>(&mut self, h: H) {
+ self.0.push((H::NAME.to_string(), format!("{h}")));
+ }
+ pub fn get_raw(&self, name: &str) -> Option<&str> {
self.0
.iter()
- .find(|(k, _)| k == H::NAME)
- .map(|(_, v)| H::from_str(v))
+ .find(|(k, _)| k.eq_ignore_ascii_case(name))
+ .map(|(_, v)| v.as_str())
+ }
+ pub fn get<H: Header>(&self) -> Option<Result<H>> {
+ self.get_raw(H::NAME).map(H::from_str)
}
pub fn insert_raw(&mut self, key: String, value: String) {
self.0.push((key, value))
@@ -32,3 +38,9 @@ impl Display for HeaderMap {
Ok(())
}
}
+
+impl FromIterator<(String, String)> for HeaderMap {
+ fn from_iter<T: IntoIterator<Item = (String, String)>>(iter: T) -> Self {
+ Self(Vec::from_iter(iter))
+ }
+}
diff --git a/src/encoding/headers.rs b/src/encoding/headers.rs
index d837ee5..6bffc7e 100644
--- a/src/encoding/headers.rs
+++ b/src/encoding/headers.rs
@@ -1,7 +1,10 @@
+use super::{headermap::HeaderMap, method::Method};
+use anyhow::{anyhow, bail};
use std::{fmt::Display, str::FromStr};
macro_rules! header {
($hname:literal, struct $name:ident($type:ty)) => {
+ #[derive(Debug)]
pub struct $name(pub $type);
impl Header for $name {
const NAME: &'static str = $hname;
@@ -26,7 +29,6 @@ pub trait Header: FromStr<Err = anyhow::Error> + Display {
header!("Content-Length", struct ContentLength(usize));
header!("Call-ID", struct CallID(String));
-header!("CSeq", struct CSeq(String));
header!("Via", struct Via(String));
header!("Contact", struct Contact(String));
header!("Max-Forwards", struct MaxForwards(usize));
@@ -34,3 +36,70 @@ header!("From", struct From(String));
header!("To", struct To(String));
header!("User-Agent", struct UserAgent(String));
header!("Allow", struct Allow(String));
+
+#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
+pub struct CSeq(pub u32, pub Method);
+
+impl Header for CSeq {
+ const NAME: &'static str = "CSeq";
+}
+impl Display for CSeq {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{} {}", self.0, self.1)
+ }
+}
+impl FromStr for CSeq {
+ type Err = anyhow::Error;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let (seq, method) = s.split_once(" ").ok_or(anyhow!("method missing"))?;
+ Ok(CSeq(seq.parse()?, method.parse()?))
+ }
+}
+
+#[derive(Debug)]
+pub struct WWWAuthenticate {
+ pub realm: String,
+ pub nonce: String,
+}
+impl Header for WWWAuthenticate {
+ const NAME: &'static str = "WWW-Authenticate";
+}
+impl Display for WWWAuthenticate {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "Digest realm={:?}, nonce={:?}", self.realm, self.nonce)
+ }
+}
+impl FromStr for WWWAuthenticate {
+ type Err = anyhow::Error;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ // TODO this is totally wrong
+ let kvs = s
+ .strip_prefix("Digest ")
+ .ok_or(anyhow!("type not digest"))?
+ .split(", ")
+ .map(|e| {
+ let Some((k, v)) = e.split_once("=") else {
+ bail!("not a KV-pair")
+ };
+ Ok((
+ k.to_string(),
+ v.strip_prefix("\"")
+ .ok_or(anyhow!("start quote missing"))?
+ .strip_suffix("\"")
+ .ok_or(anyhow!("end quote missing"))?
+ .to_string(),
+ ))
+ })
+ .try_collect::<HeaderMap>()?;
+ Ok(WWWAuthenticate {
+ realm: kvs
+ .get_raw("realm")
+ .ok_or(anyhow!("realm missing"))?
+ .to_string(),
+ nonce: kvs
+ .get_raw("nonce")
+ .ok_or(anyhow!("nonce missing"))?
+ .to_string(),
+ })
+ }
+}
diff --git a/src/encoding/method.rs b/src/encoding/method.rs
index 5f8110a..73829b0 100644
--- a/src/encoding/method.rs
+++ b/src/encoding/method.rs
@@ -1,5 +1,7 @@
-use std::fmt::Display;
+use anyhow::bail;
+use std::{fmt::Display, str::FromStr};
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Method {
Register,
Invite,
@@ -21,3 +23,17 @@ impl Display for Method {
})
}
}
+impl FromStr for Method {
+ type Err = anyhow::Error;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ Ok(match s {
+ "REGISTER" => Method::Register,
+ "INVITE" => Method::Invite,
+ "ACK" => Method::Ack,
+ "OPTION" => Method::Option,
+ "CANCEL" => Method::Cancel,
+ "BYE" => Method::Bye,
+ _ => bail!("unknown method"),
+ })
+ }
+}
diff --git a/src/encoding/request.rs b/src/encoding/request.rs
index 03b93c9..124522c 100644
--- a/src/encoding/request.rs
+++ b/src/encoding/request.rs
@@ -1,6 +1,7 @@
use super::{headermap::HeaderMap, method::Method, uri::Uri};
use std::fmt::Display;
+#[derive(Debug)]
pub struct Request {
pub method: Method,
pub uri: Uri,
diff --git a/src/encoding/uri.rs b/src/encoding/uri.rs
index 2d77df2..64572ba 100644
--- a/src/encoding/uri.rs
+++ b/src/encoding/uri.rs
@@ -1,5 +1,6 @@
use std::fmt::Display;
+#[derive(Debug)]
pub struct Uri {
pub content: String,
}