aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-07-06 17:37:35 +0200
committermetamuffin <metamuffin@disroot.org>2024-07-06 17:37:35 +0200
commit7aa211a8d7ae2efeebd9362699a1aea4b5690e3d (patch)
treee0af8720ee3b770688600a8ea025de2ce81e5017
parent7177367ae41a5e2d6ed401f60ee1455812dd8ffb (diff)
downloadsip-rs-7aa211a8d7ae2efeebd9362699a1aea4b5690e3d.tar
sip-rs-7aa211a8d7ae2efeebd9362699a1aea4b5690e3d.tar.bz2
sip-rs-7aa211a8d7ae2efeebd9362699a1aea4b5690e3d.tar.zst
start on sdp impl
-rw-r--r--examples/server.rs22
-rw-r--r--src/encoding/mod.rs9
-rw-r--r--src/encoding/request.rs3
-rw-r--r--src/encoding/response.rs15
-rw-r--r--src/encoding/status.rs2
-rw-r--r--src/lib.rs1
-rw-r--r--src/sdp/mod.rs56
-rw-r--r--src/transaction/auth.rs2
-rw-r--r--src/transaction/mod.rs4
-rw-r--r--src/transport/udp.rs11
10 files changed, 109 insertions, 16 deletions
diff --git a/examples/server.rs b/examples/server.rs
index 60a2b33..b58557a 100644
--- a/examples/server.rs
+++ b/examples/server.rs
@@ -9,12 +9,13 @@ use sip::{
method::Method,
response::Response,
status::Status,
+ uri::Uri,
},
transaction::TransactionUser,
- transport::tcp::TcpTransport,
+ transport::{tcp::TcpTransport, udp::UdpTransport},
};
use tokio::{
- net::{TcpListener, TcpStream},
+ net::{TcpListener, TcpStream, UdpSocket},
spawn,
};
@@ -23,6 +24,7 @@ async fn main() -> Result<()> {
env_logger::init_from_env("LOG");
let listener = TcpListener::bind("0.0.0.0:5060").await?;
info!("tcp listener bound to {}", listener.local_addr().unwrap());
+
loop {
let (stream, addr) = listener.accept().await?;
info!("connect {addr}");
@@ -51,11 +53,17 @@ async fn handle_client(stream: TcpStream, addr: SocketAddr) -> Result<()> {
Response {
status: Status::Ok,
headers: HeaderMap::new()
- .add(Contact(format!("<sip:{username}@{addr}>;expires=600")))
- .add(From(to.0))
- .add(To(from.0))
- .add(UserAgent("siptest v0.1.0".to_string()))
- .add(ContentLength(0)),
+ .add(Contact {
+ display_name: None,
+ uri: Uri {
+ content: format!("sip:username@{addr}"),
+ },
+ params: ";expires=600".to_string(),
+ })
+ .add(to)
+ .add(from)
+ .add(UserAgent("siptest v0.1.0".to_string())),
+ body: String::new(),
},
)
.await?;
diff --git a/src/encoding/mod.rs b/src/encoding/mod.rs
index f0796c8..816aa01 100644
--- a/src/encoding/mod.rs
+++ b/src/encoding/mod.rs
@@ -35,3 +35,12 @@ impl FromStr for Message {
}
}
}
+
+impl Message {
+ pub fn body_mut(&mut self) -> &mut String {
+ match self {
+ Message::Request(r) => &mut r.body,
+ Message::Response(r) => &mut r.body,
+ }
+ }
+}
diff --git a/src/encoding/request.rs b/src/encoding/request.rs
index c62bab3..ab41b7c 100644
--- a/src/encoding/request.rs
+++ b/src/encoding/request.rs
@@ -7,6 +7,7 @@ pub struct Request {
pub method: Method,
pub uri: Uri,
pub headers: HeaderMap,
+ pub body: String,
}
impl Display for Request {
@@ -15,6 +16,7 @@ impl Display for Request {
headers,
method,
uri,
+ ..
} = self;
write!(f, "{method} {uri} SIP/2.0\r\n")?;
write!(f, "{headers}\r\n")?;
@@ -46,6 +48,7 @@ impl FromStr for Request {
let method = Method::from_str(method)?;
Ok(Self {
+ body: String::new(),
headers,
method,
uri,
diff --git a/src/encoding/response.rs b/src/encoding/response.rs
index ffd2878..0b7996c 100644
--- a/src/encoding/response.rs
+++ b/src/encoding/response.rs
@@ -6,6 +6,7 @@ use std::{fmt::Display, str::FromStr};
pub struct Response {
pub status: Status,
pub headers: HeaderMap,
+ pub body: String,
}
impl FromStr for Response {
@@ -31,14 +32,22 @@ impl FromStr for Response {
let headers = HeaderMap::parse(&mut lines)?;
let status = Status::from_code(code);
- Ok(Self { status, headers })
+ Ok(Self {
+ status,
+ headers,
+ body: String::new(),
+ })
}
}
impl Display for Response {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- let Self { status, headers } = self;
+ let Self {
+ status,
+ headers,
+ body,
+ } = self;
write!(f, "SIP/2.0 {} {status:?}\r\n", status.to_code())?;
- write!(f, "{headers}\r\n")?;
+ write!(f, "{headers}\r\n{body}")?;
Ok(())
}
}
diff --git a/src/encoding/status.rs b/src/encoding/status.rs
index 9fe03d7..61b2d2a 100644
--- a/src/encoding/status.rs
+++ b/src/encoding/status.rs
@@ -1,6 +1,6 @@
macro_rules! status_enum {
($v:vis enum $name:ident { $($variant:ident = $value:literal),*, }) => {
- #[derive(Debug, Clone)]
+ #[derive(Debug, Clone, Eq, PartialEq, Hash)]
$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/lib.rs b/src/lib.rs
index 6c6cc3b..905922b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,3 +2,4 @@
pub mod encoding;
pub mod transport;
pub mod transaction;
+pub mod sdp;
diff --git a/src/sdp/mod.rs b/src/sdp/mod.rs
new file mode 100644
index 0000000..635c182
--- /dev/null
+++ b/src/sdp/mod.rs
@@ -0,0 +1,56 @@
+use anyhow::{anyhow, bail};
+use std::str::FromStr;
+
+pub struct SessionDescription {
+ version: String,
+ originator: String,
+ session_name: String,
+ session_information: Option<String>,
+ description_uri: Option<String>,
+ email_address: Option<String>,
+ phone_number: Option<String>,
+ connection_information: Vec<String>,
+ bandwidth: Vec<String>,
+ time_descriptions: Vec<TimeDescription>,
+ time_zone_adjustments: Option<String>,
+ encryption_key: Option<String>,
+ session_attribute: Vec<String>,
+ media_descriptions: Vec<MediaDescription>,
+}
+
+pub struct TimeDescription {
+ time: String,
+ repeat_times: Vec<String>,
+}
+
+pub struct MediaDescription {
+ name: String,
+ title: String,
+ connection_information: String,
+}
+
+impl FromStr for SessionDescription {
+ type Err = anyhow::Error;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let mut version = None;
+ let mut originator = None;
+ let mut session_name = None;
+ let mut session_information = None;
+ let mut description_uri = None;
+ let mut email_address = None;
+ let mut phone_number = None;
+ let mut connection_information = Vec::new();
+ let mut bandwidth = Vec::new();
+ for line in s.lines() {
+ let (r#type, value) = line.split_once("=").ok_or(anyhow!("sdp line invalid"))?;
+ match r#type {
+ "v" => version = Some(value.to_string()),
+ "o" => originator = Some(value.to_string()),
+ "s" => session_name = Some(value.to_string()),
+ "s" => session_name = Some(value.to_string()),
+ x => bail!("unknown sdp type ({x:?})"),
+ }
+ }
+ Ok(Self {})
+ }
+}
diff --git a/src/transaction/auth.rs b/src/transaction/auth.rs
index f64bb4b..1b3a100 100644
--- a/src/transaction/auth.rs
+++ b/src/transaction/auth.rs
@@ -14,7 +14,7 @@ impl Authorization {
username: &str,
password: &str,
) -> Result<Authorization> {
- let challenge = failed_response.headers.get::<WWWAuthenticate>().unwrap()?;
+ let challenge = failed_response.headers.get_res::<WWWAuthenticate>()?;
Ok(Authorization {
response: response_digest(
diff --git a/src/transaction/mod.rs b/src/transaction/mod.rs
index 601b134..3368c47 100644
--- a/src/transaction/mod.rs
+++ b/src/transaction/mod.rs
@@ -2,7 +2,7 @@ pub mod auth;
use crate::{
encoding::{
- headers::{CSeq, CallID},
+ headers::{CSeq, CallID, ContentLength},
request::Request,
response::Response,
Message,
@@ -66,6 +66,7 @@ impl<T: Transport> TransactionUser<T> {
.get::<CallID>()
.ok_or(anyhow!("call-id is mandatory"))??,
);
+ resp.headers.insert(ContentLength(resp.body.len()));
self.transport.send(Message::Response(resp)).await?;
Ok(())
}
@@ -74,6 +75,7 @@ impl<T: Transport> TransactionUser<T> {
let seq = self.sequence.fetch_add(1, Ordering::Relaxed);
let cseq = CSeq(seq, request.method);
request.headers.insert(cseq);
+ request.headers.insert(ContentLength(request.body.len()));
let (tx, rx) = channel(4);
diff --git a/src/transport/udp.rs b/src/transport/udp.rs
index 78ca4f2..c0d7829 100644
--- a/src/transport/udp.rs
+++ b/src/transport/udp.rs
@@ -1,6 +1,6 @@
use super::Transport;
use crate::encoding::Message;
-use anyhow::Result;
+use anyhow::{anyhow, Result};
use log::debug;
use std::str::FromStr;
use tokio::net::UdpSocket;
@@ -19,8 +19,13 @@ impl Transport for UdpTransport {
let mut buf = [0; 1024];
let size = self.sock.recv(&mut buf).await?;
let message = String::from_utf8(buf[..size].to_vec())?;
- debug!("<- {message}");
- Message::from_str(message.trim_end())
+ let (head, body) = message
+ .split_once("\r\n\r\n")
+ .ok_or(anyhow!("header end missing"))?;
+ debug!("<- {head}\n\n{body}");
+ let mut mesg = Message::from_str(head.trim_end())?;
+ *mesg.body_mut() = body.to_string();
+ Ok(mesg)
}
async fn send(&self, request: Message) -> Result<()> {
debug!("-> {request}");