From 3f80205783bcf6a2ed682f6f21e5b1877d597328 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Thu, 4 Jul 2024 17:15:25 +0200 Subject: rfiles --- src/encoding/headermap.rs | 34 +++++++++++++++++++++++++ src/encoding/headers.rs | 36 +++++++++++++++++++++++++++ src/encoding/method.rs | 23 +++++++++++++++++ src/encoding/mod.rs | 7 ++++++ src/encoding/request.rs | 21 ++++++++++++++++ src/encoding/response.rs | 40 ++++++++++++++++++++++++++++++ src/encoding/status.rs | 63 +++++++++++++++++++++++++++++++++++++++++++++++ src/encoding/uri.rs | 12 +++++++++ src/headermap.rs | 30 ---------------------- src/headers.rs | 36 --------------------------- src/lib.rs | 9 ++----- src/method.rs | 23 ----------------- src/request.rs | 21 ---------------- src/response.rs | 7 ------ src/status.rs | 63 ----------------------------------------------- src/transport/client.rs | 0 src/transport/mod.rs | 1 + src/uri.rs | 12 --------- 18 files changed, 239 insertions(+), 199 deletions(-) create mode 100644 src/encoding/headermap.rs create mode 100644 src/encoding/headers.rs create mode 100644 src/encoding/method.rs create mode 100644 src/encoding/mod.rs create mode 100644 src/encoding/request.rs create mode 100644 src/encoding/response.rs create mode 100644 src/encoding/status.rs create mode 100644 src/encoding/uri.rs delete mode 100644 src/headermap.rs delete mode 100644 src/headers.rs delete mode 100644 src/method.rs delete mode 100644 src/request.rs delete mode 100644 src/response.rs delete mode 100644 src/status.rs create mode 100644 src/transport/client.rs create mode 100644 src/transport/mod.rs delete mode 100644 src/uri.rs (limited to 'src') diff --git a/src/encoding/headermap.rs b/src/encoding/headermap.rs new file mode 100644 index 0000000..313d8b5 --- /dev/null +++ b/src/encoding/headermap.rs @@ -0,0 +1,34 @@ +use super::headers::Header; +use anyhow::Result; +use std::fmt::Display; + +#[derive(Debug)] +pub struct HeaderMap(pub Vec<(String, String)>); + +impl HeaderMap { + pub fn new() -> Self { + Self(vec![]) + } + pub fn add(mut self, h: H) -> Self { + self.0.push((H::NAME.to_string(), format!("{h}"))); + self + } + pub fn get(&self) -> Option> { + self.0 + .iter() + .find(|(k, _)| k == H::NAME) + .map(|(_, v)| H::from_str(v)) + } + pub fn insert_raw(&mut self, key: String, value: String) { + self.0.push((key, value)) + } +} + +impl Display for HeaderMap { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for (k, v) in &self.0 { + write!(f, "{k}: {v}\r\n")?; + } + Ok(()) + } +} diff --git a/src/encoding/headers.rs b/src/encoding/headers.rs new file mode 100644 index 0000000..d837ee5 --- /dev/null +++ b/src/encoding/headers.rs @@ -0,0 +1,36 @@ +use std::{fmt::Display, str::FromStr}; + +macro_rules! header { + ($hname:literal, struct $name:ident($type:ty)) => { + pub struct $name(pub $type); + impl Header for $name { + const NAME: &'static str = $hname; + } + impl Display for $name { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } + } + impl FromStr for $name { + type Err = anyhow::Error; + fn from_str(s: &str) -> Result { + Ok($name(<$type>::from_str(s)?)) + } + } + }; +} + +pub trait Header: FromStr + Display { + const NAME: &'static str; +} + +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)); +header!("From", struct From(String)); +header!("To", struct To(String)); +header!("User-Agent", struct UserAgent(String)); +header!("Allow", struct Allow(String)); diff --git a/src/encoding/method.rs b/src/encoding/method.rs new file mode 100644 index 0000000..5f8110a --- /dev/null +++ b/src/encoding/method.rs @@ -0,0 +1,23 @@ +use std::fmt::Display; + +pub enum Method { + Register, + Invite, + Ack, + Option, + Cancel, + Bye, +} + +impl Display for Method { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + Method::Register => "REGISTER", + Method::Invite => "INVITE", + Method::Ack => "ACK", + Method::Option => "OPTION", + Method::Cancel => "CANCEL", + Method::Bye => "BYE", + }) + } +} diff --git a/src/encoding/mod.rs b/src/encoding/mod.rs new file mode 100644 index 0000000..a7dd227 --- /dev/null +++ b/src/encoding/mod.rs @@ -0,0 +1,7 @@ +pub mod headermap; +pub mod headers; +pub mod method; +pub mod request; +pub mod response; +pub mod status; +pub mod uri; diff --git a/src/encoding/request.rs b/src/encoding/request.rs new file mode 100644 index 0000000..03b93c9 --- /dev/null +++ b/src/encoding/request.rs @@ -0,0 +1,21 @@ +use super::{headermap::HeaderMap, method::Method, uri::Uri}; +use std::fmt::Display; + +pub struct Request { + pub method: Method, + pub uri: Uri, + pub headers: HeaderMap, +} + +impl Display for Request { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + headers, + method, + uri, + } = self; + write!(f, "{method} {uri} SIP/2.0\r\n")?; + write!(f, "{headers}\r\n")?; + Ok(()) + } +} diff --git a/src/encoding/response.rs b/src/encoding/response.rs new file mode 100644 index 0000000..3564b34 --- /dev/null +++ b/src/encoding/response.rs @@ -0,0 +1,40 @@ +use super::headermap::HeaderMap; +use anyhow::{anyhow, bail, Context}; +use std::str::FromStr; + +#[derive(Debug)] +pub struct Response { + pub code: u16, + pub headers: HeaderMap, +} + +impl FromStr for Response { + type Err = anyhow::Error; + fn from_str(s: &str) -> Result { + let mut lines = s.lines(); + let statusline = lines.next().ok_or(anyhow!("status line missing"))?; + let (sipver, rest) = statusline + .split_once(" ") + .ok_or(anyhow!("status line malformed"))?; + let (code, _status_str) = rest + .split_once(" ") + .ok_or(anyhow!("status line malformed"))?; + let code = u16::from_str(code).context("status code")?; + + let Some(ver) = sipver.strip_prefix("SIP/") else { + bail!("sip version malformed"); + }; + if ver != "2.0" { + 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()) + } + + Ok(Self { code, headers }) + } +} diff --git a/src/encoding/status.rs b/src/encoding/status.rs new file mode 100644 index 0000000..de9ea88 --- /dev/null +++ b/src/encoding/status.rs @@ -0,0 +1,63 @@ + +macro_rules! status_enum { + ($v:vis enum $name:ident { $($variant:ident = $value:literal),*, }) => { + $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 } } } + }; +} + +status_enum!( + pub enum Status { + Trying = 100, + Ringing = 180, + CallIsBeingForwarded = 181, + Queued = 182, + SessionProgress = 183, + Ok = 200, + MultipleChoices = 300, + MovedPermanently = 301, + MovedTemporarily = 302, + UseProxy = 305, + AlternativeService = 380, + BadRequest = 400, + Unauthorized = 401, + PaymentRequired = 402, + Forbidden = 403, + NotFound = 404, + MethodNotAllowed = 405, + NotAcceptable = 406, + ProxyAuthenticationRequired = 407, + RequestTimeout = 408, + Gone = 410, + RequestEntityTooLarge = 413, + RequestURITooLarge = 414, + UnsupportedMediaType = 415, + UnsupportedURIScheme = 416, + BadExtension = 420, + ExtensionRequired = 421, + IntervalTooBrief = 423, + TemporarilyNotAvailable = 480, + CallLegTransactionDoesNotExist = 481, + LoopDetected = 482, + TooManyHops = 483, + AddressIncomplete = 484, + Ambiguous = 485, + BusyHere = 486, + RequestTerminated = 487, + NotAcceptableHere = 488, + RequestPending = 491, + Undecipherable = 493, + InternalServerError = 500, + NotImplemented = 501, + BadGateway = 502, + ServiceUnavailable = 503, + ServerTimeout = 504, + SIPVersionNotSupported = 505, + MessageTooLarge = 513, + BusyEverywhere = 600, + Decline = 603, + DoesNotExistAnywhere = 604, + GlobalNotAcceptable = 606, + } +); diff --git a/src/encoding/uri.rs b/src/encoding/uri.rs new file mode 100644 index 0000000..2d77df2 --- /dev/null +++ b/src/encoding/uri.rs @@ -0,0 +1,12 @@ +use std::fmt::Display; + +pub struct Uri { + pub content: String, +} + +impl Display for Uri { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.content)?; + Ok(()) + } +} diff --git a/src/headermap.rs b/src/headermap.rs deleted file mode 100644 index 8712df1..0000000 --- a/src/headermap.rs +++ /dev/null @@ -1,30 +0,0 @@ -use crate::headers::Header; -use anyhow::Result; -use std::fmt::Display; - -pub struct HeaderMap(pub Vec<(String, String)>); - -impl HeaderMap { - pub fn new() -> Self { - Self(vec![]) - } - pub fn add(mut self, h: H) -> Self { - self.0.push((H::NAME.to_string(), format!("{h}"))); - self - } - pub fn get(&self) -> Option> { - self.0 - .iter() - .find(|(k, _)| k == H::NAME) - .map(|(_, v)| H::from_str(v)) - } -} - -impl Display for HeaderMap { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - for (k, v) in &self.0 { - write!(f, "{k}: {v}\r\n")?; - } - Ok(()) - } -} diff --git a/src/headers.rs b/src/headers.rs deleted file mode 100644 index d837ee5..0000000 --- a/src/headers.rs +++ /dev/null @@ -1,36 +0,0 @@ -use std::{fmt::Display, str::FromStr}; - -macro_rules! header { - ($hname:literal, struct $name:ident($type:ty)) => { - pub struct $name(pub $type); - impl Header for $name { - const NAME: &'static str = $hname; - } - impl Display for $name { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } - } - impl FromStr for $name { - type Err = anyhow::Error; - fn from_str(s: &str) -> Result { - Ok($name(<$type>::from_str(s)?)) - } - } - }; -} - -pub trait Header: FromStr + Display { - const NAME: &'static str; -} - -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)); -header!("From", struct From(String)); -header!("To", struct To(String)); -header!("User-Agent", struct UserAgent(String)); -header!("Allow", struct Allow(String)); diff --git a/src/lib.rs b/src/lib.rs index a7dd227..d9935d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,2 @@ -pub mod headermap; -pub mod headers; -pub mod method; -pub mod request; -pub mod response; -pub mod status; -pub mod uri; +pub mod encoding; +pub mod transport; diff --git a/src/method.rs b/src/method.rs deleted file mode 100644 index 5f8110a..0000000 --- a/src/method.rs +++ /dev/null @@ -1,23 +0,0 @@ -use std::fmt::Display; - -pub enum Method { - Register, - Invite, - Ack, - Option, - Cancel, - Bye, -} - -impl Display for Method { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(match self { - Method::Register => "REGISTER", - Method::Invite => "INVITE", - Method::Ack => "ACK", - Method::Option => "OPTION", - Method::Cancel => "CANCEL", - Method::Bye => "BYE", - }) - } -} diff --git a/src/request.rs b/src/request.rs deleted file mode 100644 index 827dae1..0000000 --- a/src/request.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::{headermap::HeaderMap, method::Method, uri::Uri}; -use std::fmt::Display; - -pub struct Request { - pub method: Method, - pub uri: Uri, - pub headers: HeaderMap, -} - -impl Display for Request { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { - headers, - method, - uri, - } = self; - write!(f, "{method} {uri} SIP/2.0\r\n")?; - write!(f, "{headers}\r\n")?; - Ok(()) - } -} diff --git a/src/response.rs b/src/response.rs deleted file mode 100644 index 4403c6e..0000000 --- a/src/response.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::headermap::HeaderMap; - - -pub struct Reponse { - pub code: u16, - pub headers: HeaderMap, -} diff --git a/src/status.rs b/src/status.rs deleted file mode 100644 index de9ea88..0000000 --- a/src/status.rs +++ /dev/null @@ -1,63 +0,0 @@ - -macro_rules! status_enum { - ($v:vis enum $name:ident { $($variant:ident = $value:literal),*, }) => { - $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 } } } - }; -} - -status_enum!( - pub enum Status { - Trying = 100, - Ringing = 180, - CallIsBeingForwarded = 181, - Queued = 182, - SessionProgress = 183, - Ok = 200, - MultipleChoices = 300, - MovedPermanently = 301, - MovedTemporarily = 302, - UseProxy = 305, - AlternativeService = 380, - BadRequest = 400, - Unauthorized = 401, - PaymentRequired = 402, - Forbidden = 403, - NotFound = 404, - MethodNotAllowed = 405, - NotAcceptable = 406, - ProxyAuthenticationRequired = 407, - RequestTimeout = 408, - Gone = 410, - RequestEntityTooLarge = 413, - RequestURITooLarge = 414, - UnsupportedMediaType = 415, - UnsupportedURIScheme = 416, - BadExtension = 420, - ExtensionRequired = 421, - IntervalTooBrief = 423, - TemporarilyNotAvailable = 480, - CallLegTransactionDoesNotExist = 481, - LoopDetected = 482, - TooManyHops = 483, - AddressIncomplete = 484, - Ambiguous = 485, - BusyHere = 486, - RequestTerminated = 487, - NotAcceptableHere = 488, - RequestPending = 491, - Undecipherable = 493, - InternalServerError = 500, - NotImplemented = 501, - BadGateway = 502, - ServiceUnavailable = 503, - ServerTimeout = 504, - SIPVersionNotSupported = 505, - MessageTooLarge = 513, - BusyEverywhere = 600, - Decline = 603, - DoesNotExistAnywhere = 604, - GlobalNotAcceptable = 606, - } -); diff --git a/src/transport/client.rs b/src/transport/client.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/transport/mod.rs b/src/transport/mod.rs new file mode 100644 index 0000000..b9babe5 --- /dev/null +++ b/src/transport/mod.rs @@ -0,0 +1 @@ +pub mod client; diff --git a/src/uri.rs b/src/uri.rs deleted file mode 100644 index 2d77df2..0000000 --- a/src/uri.rs +++ /dev/null @@ -1,12 +0,0 @@ -use std::fmt::Display; - -pub struct Uri { - pub content: String, -} - -impl Display for Uri { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.content)?; - Ok(()) - } -} -- cgit v1.2.3-70-g09d2