use anyhow::Result; use log::{info, warn}; use sip::{ encoding::{ headermap::HeaderMap, headers::{Contact, From, To, UserAgent, Via}, method::Method, response::Response, status::Status, }, transaction::TransactionUser, transport::tcp::TcpTransport, }; use std::net::SocketAddr; use tokio::{ net::{TcpListener, TcpStream}, spawn, }; #[tokio::main] 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}"); spawn(async move { if let Err(e) = handle_client(stream, addr).await { warn!("client error: {e}") } info!("disconnect {addr}") }); } } async fn handle_client(stream: TcpStream, addr: SocketAddr) -> Result<()> { let transport = TcpTransport::new(stream).await?; let tu = TransactionUser::new(transport); loop { let req = tu.process_incoming().await?; if req.method == Method::Register { let from: From = req.headers.get_res()?; let to: To = req.headers.get_res()?; let via: Via = req.headers.get_res()?; let contact: Contact = req.headers.get_res()?; info!( "({addr}) Registered {}", contact.uri.localpart.as_ref().unwrap() ); tu.respond( &req, Response { status: Status::Ok, headers: HeaderMap::new() .add(contact) .add(via) .add(to) .add(from) .add(UserAgent("siptest v0.1.0".to_string())), body: String::new(), }, ) .await?; } if req.method == Method::Invite {} } }