sip-bridge-mx

A WIP Bridge between SIP over Websocket+Webrtc and MatrixRTC (Webrtc via Matrix signaling)
git clone git://archive.git.mtrnord.blog/MTRNord/sip-bridge-mx.git
Log | Files | Refs | README | LICENSE

sip.rs (27147B)


      1 use std::{future::Future, sync::Arc, time::Duration};
      2 
      3 use fastwebsockets::{handshake, FragmentCollector, OpCode, Payload};
      4 use hyper::{
      5     header::{CONNECTION, UPGRADE},
      6     upgrade::Upgraded,
      7     Body, Request, Version,
      8 };
      9 use local_ip_address::local_ip;
     10 use matrix_sdk::{ruma::events::room::message::RoomMessageEventContent, Room};
     11 use rsip::{
     12     prelude::{HasHeaders, HeadersExt, UntypedHeader},
     13     services::DigestGenerator,
     14     Header,
     15 };
     16 use secrecy::{ExposeSecret, SecretString};
     17 use tokio::{net::TcpStream, time::sleep};
     18 use tokio_rustls::{
     19     rustls::{ClientConfig, OwnedTrustAnchor},
     20     TlsConnector,
     21 };
     22 use tracing::{error, info, warn};
     23 use uuid::Uuid;
     24 use webrtc::peer_connection::{
     25     peer_connection_state::RTCPeerConnectionState, sdp::session_description::RTCSessionDescription,
     26     RTCPeerConnection,
     27 };
     28 
     29 use crate::{CallID, SipAuthInfo};
     30 
     31 fn tls_connector() -> color_eyre::Result<TlsConnector> {
     32     let mut root_store = tokio_rustls::rustls::RootCertStore::empty();
     33 
     34     root_store.add_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().map(|ta| {
     35         OwnedTrustAnchor::from_subject_spki_name_constraints(
     36             ta.subject,
     37             ta.spki,
     38             ta.name_constraints,
     39         )
     40     }));
     41 
     42     let config = ClientConfig::builder()
     43         .with_safe_defaults()
     44         .with_root_certificates(root_store)
     45         .with_no_client_auth();
     46 
     47     Ok(TlsConnector::from(Arc::new(config)))
     48 }
     49 
     50 // Connect to the SIP server using a websocket connection and rsip library
     51 async fn connect(sip_server_domain: String) -> color_eyre::Result<FragmentCollector<Upgraded>> {
     52     let tcp_stream = TcpStream::connect(format!("{sip_server_domain}:443")).await?;
     53     let tls_connector = tls_connector()?;
     54     let domain = tokio_rustls::rustls::ServerName::try_from(sip_server_domain.as_str())
     55         .map_err(|_| std::io::Error::new(std::io::ErrorKind::InvalidInput, "invalid dnsname"))?;
     56 
     57     let tls_stream = tls_connector.connect(domain, tcp_stream).await?;
     58 
     59     let req = Request::builder()
     60         .method("GET")
     61         .uri("/ws")
     62         .version(Version::HTTP_11)
     63         .header("Host", sip_server_domain)
     64         .header(UPGRADE, "websocket")
     65         .header(CONNECTION, "Upgrade")
     66         .header("Sec-WebSocket-Key", handshake::generate_key())
     67         .header("Sec-WebSocket-Protocol", "sip")
     68         .header("Sec-WebSocket-Version", "13")
     69         .body(Body::empty())?;
     70 
     71     let (ws, _) = handshake::client(&SpawnExecutor, req, tls_stream).await?;
     72     Ok(FragmentCollector::new(ws))
     73 }
     74 
     75 // Tie hyper's executor to tokio runtime
     76 struct SpawnExecutor;
     77 
     78 impl<Fut> hyper::rt::Executor<Fut> for SpawnExecutor
     79 where
     80     Fut: Future + Send + 'static,
     81     Fut::Output: Send + 'static,
     82 {
     83     fn execute(&self, fut: Fut) {
     84         tokio::task::spawn(fut);
     85     }
     86 }
     87 
     88 pub async fn handle_sip_connection(
     89     mut outgoing_messages: tokio::sync::mpsc::Receiver<SIPRequest>,
     90     call_id: CallID,
     91     sip_server_domain: String,
     92     sip_server: String,
     93     sip_username: String,
     94     sip_password: SecretString,
     95 ) -> color_eyre::Result<()> {
     96     let mut ws = connect(sip_server_domain).await?;
     97     info!("Connected to SIP server");
     98     info!("Sending register request");
     99 
    100     // Register with SIP server
    101     let base_register_request =
    102         generate_base_register_request(call_id, sip_server.clone(), sip_username.clone())?;
    103     ws.write_frame(fastwebsockets::Frame::text(
    104         fastwebsockets::Payload::Borrowed(base_register_request.to_string().as_bytes()),
    105     ))
    106     .await?;
    107 
    108     // Get the response
    109     let frame = ws.read_frame().await?;
    110     let response = if let OpCode::Text = frame.opcode {
    111         let response = String::from_utf8(frame.payload.to_vec())?;
    112         info!("Got response: {}", response);
    113         rsip::Response::try_from(response.as_str())?
    114     } else {
    115         error!(
    116             "Got unexpected response: {:?} - {:?}",
    117             frame.opcode, frame.payload
    118         );
    119         return Err(color_eyre::eyre::eyre!("Got unexpected response"));
    120     };
    121 
    122     let register_request = generate_request_with_auth(
    123         response,
    124         None,
    125         base_register_request,
    126         sip_server,
    127         sip_username,
    128         sip_password,
    129     )?;
    130     ws.write_frame(fastwebsockets::Frame::text(
    131         fastwebsockets::Payload::Borrowed(register_request.to_string().as_bytes()),
    132     ))
    133     .await?;
    134 
    135     // Get the response
    136     let frame = ws.read_frame().await?;
    137     if let OpCode::Text = frame.opcode {
    138         let response = String::from_utf8(frame.payload.to_vec())?;
    139         info!("Got response: {}", response);
    140     } else {
    141         error!(
    142             "Got unexpected response: {:?} - {:?}",
    143             frame.opcode, frame.payload
    144         );
    145         return Err(color_eyre::eyre::eyre!("Got unexpected response"));
    146     }
    147 
    148     loop {
    149         tokio::select! {
    150             Ok(frame) = ws.read_frame() => {
    151                 if let OpCode::Close = frame.opcode {
    152                     break;
    153                 }
    154 
    155                 // Send out message if we have one
    156                 if let Ok(message) = outgoing_messages.try_recv() {
    157                     ws.write_frame(fastwebsockets::Frame::text(
    158                         fastwebsockets::Payload::Borrowed(message.message.to_string().as_bytes()),
    159                     ))
    160                     .await?;
    161 
    162                     let mut responses = Vec::with_capacity(message.response_count + 1);
    163                     for _ in 0..message.response_count {
    164                         let frame =  ws.read_frame().await?;
    165                         match frame.opcode {
    166                             OpCode::Text | OpCode::Binary => {
    167                                 if !frame.payload.is_empty() {
    168                                     if let Ok(message) = String::from_utf8(frame.payload.to_vec()) {
    169                                         // Empty and BYE responses cannot be parsed
    170                                         if !message.is_empty() && !message.starts_with("BYE") && message != "\r\n\r\n" {
    171                                             //debug!("Got message: {:?}", message);
    172                                             responses.push(rsip::Response::try_from(message.as_str())?);
    173                                         }
    174                                     } else {
    175                                         warn!("Got invalid UTF-8 message");
    176                                     }
    177                                 }
    178                             }
    179                             _ => {}
    180                         }
    181                     }
    182 
    183                    let _ = message.response_channel.send(responses);
    184                 }
    185            },
    186            _ = sleep(Duration::from_millis(500)) => {
    187                 // Keep the connection alive
    188                 ws.write_frame(fastwebsockets::Frame::new(
    189                     true,
    190                     OpCode::Ping,
    191                     None,
    192                     Payload::Owned(vec![]),
    193                 ))
    194                 .await?;
    195            },
    196         }
    197     }
    198 
    199     Ok(())
    200 }
    201 
    202 fn generate_base_register_request(
    203     call_id: CallID,
    204     sip_server: String,
    205     sip_username: String,
    206 ) -> color_eyre::Result<rsip::SipMessage> {
    207     let mut headers: rsip::Headers = Default::default();
    208 
    209     let base_uri = rsip::Uri {
    210         // TODO: Is it sip or Sips?
    211         scheme: Some(rsip::Scheme::Sip),
    212         auth: Some((sip_username.clone(), None::<String>).into()),
    213         host_with_port: rsip::Domain::from(sip_server.clone()).into(),
    214         ..Default::default()
    215     };
    216 
    217     let my_local_ip = local_ip()?;
    218     headers.push(
    219         rsip::typed::Via {
    220             version: rsip::Version::V2,
    221             transport: rsip::Transport::Wss,
    222             uri: rsip::Uri {
    223                 host_with_port: (rsip::Domain::from(my_local_ip.to_string()), 5060).into(),
    224                 ..Default::default()
    225             },
    226             params: vec![rsip::Param::Branch(rsip::param::Branch::new(
    227                 // TODO: This should be generated. Note that `z9hG4bK` is a cookie and the whole thing MUST be unique for every request we send
    228                 "z9hG4bKnashds7",
    229             ))],
    230         }
    231         .into(),
    232     );
    233 
    234     headers.push(rsip::headers::MaxForwards::default().into());
    235 
    236     headers.push(
    237         rsip::typed::From {
    238             display_name: Some(sip_username.clone()),
    239             uri: base_uri.clone(),
    240             params: vec![rsip::Param::Tag(rsip::param::Tag::new("a73kszlfl"))],
    241         }
    242         .into(),
    243     );
    244 
    245     headers.push(
    246         rsip::typed::To {
    247             display_name: Some(sip_username.clone()),
    248             uri: base_uri.clone(),
    249             params: Default::default(),
    250         }
    251         .into(),
    252     );
    253     headers.push(rsip::headers::CallId::new(call_id.0).into());
    254 
    255     headers.push(
    256         rsip::typed::CSeq {
    257             // TODO: I guess we need to keep track of this?
    258             seq: 1,
    259             method: rsip::Method::Register,
    260         }
    261         .into(),
    262     );
    263     headers.push(
    264         rsip::typed::Contact {
    265             display_name: None,
    266             uri: base_uri,
    267             params: Default::default(),
    268         }
    269         .into(),
    270     );
    271 
    272     headers.push(rsip::headers::UserAgent::new("matrix_sip_bridge").into());
    273     headers.push(rsip::headers::ContentLength::default().into());
    274 
    275     Ok(rsip::Request {
    276         method: rsip::Method::Register,
    277         uri: rsip::Uri {
    278             scheme: Some(rsip::Scheme::Sip),
    279             host_with_port: rsip::Domain::from(sip_server).into(),
    280             ..Default::default()
    281         },
    282         version: rsip::Version::V2,
    283         headers,
    284         body: Default::default(),
    285     }
    286     .into())
    287 }
    288 
    289 pub fn generate_request_with_auth(
    290     response: rsip::Response,
    291     auth: Option<rsip::Auth>,
    292     mut base_request: rsip::SipMessage,
    293     sip_server: String,
    294     sip_username: String,
    295     sip_password: SecretString,
    296 ) -> color_eyre::Result<rsip::SipMessage> {
    297     let www_authenticate_header: rsip::headers::typed::WwwAuthenticate = response
    298         .headers()
    299         .iter()
    300         .find_map(|header| match header {
    301             Header::WwwAuthenticate(header) => Some(header.clone()),
    302             _ => None,
    303         })
    304         .ok_or_else(|| color_eyre::eyre::eyre!("Missing WWW-Authenticate header"))?
    305         .try_into()?;
    306 
    307     let cnonce = Uuid::new_v4().to_string();
    308 
    309     // We can safely assume its a request message and extract the method
    310     let method = match base_request {
    311         rsip::SipMessage::Request(ref request) => request.method,
    312         _ => {
    313             return Err(color_eyre::eyre::eyre!(
    314                 "Expected a request message but got a response"
    315             ))
    316         }
    317     };
    318 
    319     let auth_digest = DigestGenerator {
    320         username: &sip_username,
    321         password: sip_password.expose_secret(),
    322         realm: &www_authenticate_header.realm,
    323         nonce: &www_authenticate_header.nonce,
    324         uri: &rsip::Uri {
    325             scheme: Some(rsip::Scheme::Sip),
    326             host_with_port: rsip::Domain::from(sip_server.clone()).into(),
    327             auth: auth.clone(),
    328             ..Default::default()
    329         },
    330         method: &method,
    331         qop: Some(rsip::headers::auth::AuthQop::Auth {
    332             cnonce: cnonce.clone(),
    333             nc: 1,
    334         })
    335         .as_ref(),
    336         algorithm: www_authenticate_header
    337             .algorithm
    338             .ok_or_else(|| color_eyre::eyre::eyre!("WWW-Authenticate header missing algorithm"))?,
    339     }
    340     .compute();
    341 
    342     let auth_header = rsip::headers::typed::Authorization {
    343         scheme: rsip::headers::auth::Scheme::Digest,
    344         username: sip_username,
    345         realm: www_authenticate_header.realm,
    346         nonce: www_authenticate_header.nonce,
    347         uri: rsip::Uri {
    348             scheme: Some(rsip::Scheme::Sip),
    349             host_with_port: rsip::Domain::from(sip_server).into(),
    350             auth,
    351             ..Default::default()
    352         },
    353         response: auth_digest,
    354         opaque: www_authenticate_header.opaque,
    355         algorithm: www_authenticate_header.algorithm,
    356         qop: Some(rsip::headers::auth::AuthQop::Auth { cnonce, nc: 1 }),
    357     };
    358 
    359     if let rsip::SipMessage::Request(request) = &mut base_request {
    360         request.headers_mut().push(auth_header.into());
    361     }
    362     // We also need to increase the CSeq
    363     let cseq = base_request.cseq_header_mut()?;
    364     cseq.mut_seq(cseq.seq()? + 1)?;
    365 
    366     Ok(base_request)
    367 }
    368 
    369 pub fn generate_new_branch(base_request: rsip::Request) -> color_eyre::Result<rsip::SipMessage> {
    370     // Change the branch param in the via header
    371     let via_header = base_request.via_header()?;
    372     let new_params: Vec<_> = via_header
    373         .params()?
    374         .iter()
    375         .map(|param| match param {
    376             rsip::Param::Branch(_) => rsip::Param::Branch(rsip::param::Branch::new("12345")),
    377             _ => param.clone(),
    378         })
    379         .collect();
    380     // We cant mutate the params directly so we have to replace the whole thing
    381     let new_header = rsip::typed::Via {
    382         version: via_header.version()?,
    383         transport: via_header.trasnport()?,
    384         uri: via_header.uri().clone()?,
    385         params: new_params,
    386     };
    387     // Sadly we can also not replace the via so we need to recreate the whole request
    388 
    389     let headers: Vec<_> = base_request
    390         .headers()
    391         .iter()
    392         .map(|header| match header {
    393             Header::Via(_) => Header::Via(new_header.clone().into()),
    394             _ => header.clone(),
    395         })
    396         .collect();
    397     Ok(rsip::Request {
    398         method: base_request.method,
    399         uri: base_request.uri.clone(),
    400         version: base_request.version,
    401         headers: headers.into(),
    402         body: base_request.body.clone(),
    403     }
    404     .into())
    405 }
    406 
    407 /// We first generate a request and expect a response with a WWW-Authenticate header
    408 /// We then return an ACK and then a new INVITE request with the Authorization header
    409 pub async fn generate_invite_base_request(
    410     call_id: CallID,
    411     sip_uri: rsip::Uri,
    412     sdp: String,
    413     sip_server: String,
    414     sip_username: String,
    415 ) -> color_eyre::Result<rsip::SipMessage> {
    416     let mut headers: rsip::Headers = Default::default();
    417 
    418     let base_uri = rsip::Uri {
    419         // TODO: Is it sip or Sips?
    420         scheme: Some(rsip::Scheme::Sip),
    421         auth: Some((sip_username, None::<String>).into()),
    422         host_with_port: rsip::Domain::from(sip_server).into(),
    423         ..Default::default()
    424     };
    425 
    426     let my_local_ip = local_ip()?;
    427     headers.push(
    428         rsip::typed::Via {
    429             version: rsip::Version::V2,
    430             transport: rsip::Transport::Wss,
    431             uri: rsip::Uri {
    432                 host_with_port: my_local_ip.into(),
    433                 ..Default::default()
    434             },
    435             params: vec![rsip::Param::Branch(rsip::param::Branch::new(
    436                 // TODO: This should be generated. Note that `z9hG4bK` is a cookie and the whole thing MUST be unique for every request we send
    437                 "z9hG4bKnashds7",
    438             ))],
    439         }
    440         .into(),
    441     );
    442 
    443     headers.push(
    444         rsip::typed::From {
    445             display_name: Some("sip_bridge".into()),
    446             uri: base_uri.clone(),
    447             params: vec![rsip::Param::Tag(rsip::param::Tag::new("a73kszlfl"))],
    448         }
    449         .into(),
    450     );
    451 
    452     headers.push(
    453         rsip::typed::To {
    454             display_name: None,
    455             uri: sip_uri.clone(),
    456             params: Default::default(),
    457         }
    458         .into(),
    459     );
    460 
    461     headers.push(rsip::headers::CallId::new(call_id.0).into());
    462 
    463     headers.push(
    464         rsip::typed::CSeq {
    465             // TODO: I guess we need to keep track of this?
    466             seq: 1,
    467             method: rsip::Method::Invite,
    468         }
    469         .into(),
    470     );
    471 
    472     headers.push(
    473         rsip::typed::Contact {
    474             display_name: None,
    475             uri: base_uri,
    476             params: vec![rsip::Param::Transport(rsip::Transport::Wss)],
    477         }
    478         .into(),
    479     );
    480 
    481     headers.push(rsip::headers::MaxForwards::default().into());
    482     headers.push(rsip::headers::ContentType::new("application/sdp").into());
    483 
    484     headers.push(rsip::headers::UserAgent::new("matrix_sip_bridge").into());
    485 
    486     headers.push(rsip::headers::ContentLength::new(sdp.len().to_string()).into());
    487 
    488     Ok(rsip::Request {
    489         method: rsip::Method::Invite,
    490         uri: sip_uri,
    491         version: rsip::Version::V2,
    492         headers,
    493         body: sdp.as_bytes().to_vec(),
    494     }
    495     .into())
    496 }
    497 
    498 pub fn generate_ack_request(
    499     call_id: CallID,
    500     cseq: u32,
    501     response_uri: rsip::Uri,
    502     branch: rsip::param::Branch,
    503     sip_uri: rsip::Uri,
    504     sip_server: String,
    505     sip_username: String,
    506 ) -> color_eyre::Result<rsip::SipMessage> {
    507     let mut headers: rsip::Headers = Default::default();
    508 
    509     let base_uri = rsip::Uri {
    510         // TODO: Is it sip or Sips?
    511         scheme: Some(rsip::Scheme::Sip),
    512         auth: Some((sip_username, None::<String>).into()),
    513         host_with_port: rsip::Domain::from(sip_server).into(),
    514         ..Default::default()
    515     };
    516 
    517     let my_local_ip = local_ip()?;
    518     headers.push(
    519         rsip::typed::Via {
    520             version: rsip::Version::V2,
    521             transport: rsip::Transport::Wss,
    522             uri: rsip::Uri {
    523                 host_with_port: my_local_ip.into(),
    524                 ..Default::default()
    525             },
    526             params: vec![rsip::Param::Branch(branch)],
    527         }
    528         .into(),
    529     );
    530 
    531     headers.push(
    532         rsip::typed::From {
    533             display_name: Some("sip_bridge".into()),
    534             uri: base_uri.clone(),
    535             params: vec![rsip::Param::Tag(rsip::param::Tag::new("a73kszlfl"))],
    536         }
    537         .into(),
    538     );
    539 
    540     headers.push(
    541         rsip::typed::To {
    542             display_name: None,
    543             uri: sip_uri.clone(),
    544             params: Default::default(),
    545         }
    546         .into(),
    547     );
    548 
    549     headers.push(rsip::headers::CallId::new(call_id.0).into());
    550 
    551     headers.push(
    552         rsip::typed::CSeq {
    553             // TODO: I guess we need to keep track of this?
    554             seq: cseq,
    555             method: rsip::Method::Ack,
    556         }
    557         .into(),
    558     );
    559 
    560     headers.push(rsip::headers::MaxForwards::default().into());
    561     headers.push(rsip::headers::ContentLength::default().into());
    562 
    563     Ok(rsip::Request {
    564         method: rsip::Method::Ack,
    565         uri: response_uri,
    566         version: rsip::Version::V2,
    567         headers,
    568         body: Default::default(),
    569     }
    570     .into())
    571 }
    572 
    573 pub struct SIPRequest {
    574     message: rsip::SipMessage,
    575     /// This is the count of responses that are going to be returned. This is NOT the count we need to use
    576     response_count: usize,
    577     response_channel: tokio::sync::oneshot::Sender<Vec<rsip::Response>>,
    578 }
    579 
    580 impl SIPRequest {
    581     fn new(
    582         message: rsip::SipMessage,
    583         response_count: usize,
    584     ) -> (Self, tokio::sync::oneshot::Receiver<Vec<rsip::Response>>) {
    585         let (tx, rx) = tokio::sync::oneshot::channel();
    586         (
    587             SIPRequest {
    588                 message,
    589                 response_count,
    590                 response_channel: tx,
    591             },
    592             rx,
    593         )
    594     }
    595 }
    596 
    597 pub async fn send_invite(
    598     sip_address: String,
    599     ws_sender: tokio::sync::mpsc::Sender<SIPRequest>,
    600     call_id: CallID,
    601     peer_connection: Arc<RTCPeerConnection>,
    602     room: Room,
    603     auth_info: SipAuthInfo,
    604 ) -> color_eyre::Result<()> {
    605     info!("Gathering ICE candidates");
    606 
    607     // Set the handler for Peer connection state
    608     // This will notify you when the peer has connected/disconnected
    609     let address_clone = sip_address.clone();
    610     let room_clone = room.clone();
    611     peer_connection.on_peer_connection_state_change(Box::new(move |s: RTCPeerConnectionState| {
    612         info!("Peer Connection State has changed: {s}");
    613 
    614         let room_clone = room_clone.clone();
    615         if s == RTCPeerConnectionState::Failed {
    616             // Wait until PeerConnection has had no network activity for 30 seconds or another failure. It may be reconnected using an ICE Restart.
    617             // Use webrtc.PeerConnectionStateDisconnected if you are interested in detecting faster timeout.
    618             // Note that the PeerConnection may come back from PeerConnectionStateDisconnected.
    619             info!("Peer Connection has gone to failed exiting: Done forwarding");
    620 
    621             let error_message = RoomMessageEventContent::notice_plain(format!(
    622                 "🚨Call to {} has ended🚨",
    623                 address_clone.clone()
    624             ));
    625             return Box::pin(async move {
    626                 room_clone
    627                     .clone()
    628                     .send(error_message, None)
    629                     .await
    630                     .expect("Failed to send error message");
    631             });
    632         } else if s == RTCPeerConnectionState::Connected {
    633             let call_message = RoomMessageEventContent::notice_plain(format!(
    634                 "Call to {} connected",
    635                 address_clone.clone()
    636             ));
    637             return Box::pin(async move {
    638                 room_clone
    639                     .clone()
    640                     .send(call_message, None)
    641                     .await
    642                     .expect("Failed to send error message");
    643             });
    644         } else if s == RTCPeerConnectionState::Connecting {
    645             let call_message = RoomMessageEventContent::notice_plain(format!(
    646                 "Call to {} connecting",
    647                 address_clone.clone()
    648             ));
    649             return Box::pin(async move {
    650                 room_clone
    651                     .clone()
    652                     .send(call_message, None)
    653                     .await
    654                     .expect("Failed to send error message");
    655             });
    656         }
    657 
    658         Box::pin(async {})
    659     }));
    660 
    661     peer_connection.on_negotiation_needed(Box::new(move || {
    662         error!("Negotiation needed");
    663         Box::pin(async {})
    664     }));
    665 
    666     // Create an offer to send to the sip side
    667     let offer = peer_connection.create_offer(None).await?;
    668     peer_connection.set_local_description(offer.clone()).await?;
    669 
    670     // Create channel that is blocked until ICE Gathering is complete
    671     let mut gather_complete = peer_connection.gathering_complete_promise().await;
    672 
    673     // Block until ICE Gathering is complete, disabling trickle ICE
    674     // we do this because we only can exchange one signaling message
    675     // in a production application you should exchange ICE Candidates via OnICECandidate
    676     let _ = gather_complete.recv().await;
    677 
    678     info!("Got ICE candidates");
    679 
    680     let offer = peer_connection.create_offer(None).await?;
    681     peer_connection.set_local_description(offer.clone()).await?;
    682 
    683     info!("Sending offer: {}", offer.sdp);
    684 
    685     // Get the user, scheme and domain from the sip address if it is starting with sip: or sips:
    686     // Otherwise treat it as a number for the user. The domain will be the default domain
    687     let uri = if sip_address.starts_with("sip:") {
    688         rsip::Uri::try_from(sip_address.clone())?
    689     } else {
    690         rsip::Uri {
    691             scheme: Some(rsip::Scheme::Sip),
    692             host_with_port: rsip::Domain::from(auth_info.address.clone()).into(),
    693             auth: Some(rsip::Auth {
    694                 user: sip_address.to_owned(),
    695                 password: None,
    696             }),
    697             ..Default::default()
    698         }
    699     };
    700 
    701     // Send invite to SIP Side
    702     let invite_request = generate_invite_base_request(
    703         call_id.clone(),
    704         uri.clone(),
    705         offer.sdp,
    706         auth_info.address.clone(),
    707         auth_info.username.clone(),
    708     )
    709     .await?;
    710 
    711     // Send base request
    712     let (ws_request, responses) = SIPRequest::new(invite_request.clone(), 1);
    713     ws_sender.send(ws_request).await?;
    714 
    715     let responses = responses.await?;
    716     let invite_response = match responses.first() {
    717         Some(response) => response,
    718         None => {
    719             return Err(color_eyre::eyre::eyre!("Got no response on invite"));
    720         }
    721     };
    722     info!("Got invite response: {}", invite_response);
    723 
    724     // Send ack
    725     // Get response branch of via header
    726     let params = invite_response.via_header()?.params()?;
    727     let via_branch = match params.iter().find_map(|param| match param {
    728         rsip::param::Param::Branch(branch) => Some(branch),
    729         _ => None,
    730     }) {
    731         Some(branch) => branch,
    732         None => {
    733             return Err(color_eyre::eyre::eyre!("Got no branch in response"));
    734         }
    735     };
    736     let ack = generate_ack_request(
    737         call_id.clone(),
    738         1,
    739         uri.clone(),
    740         via_branch.clone(),
    741         uri.clone(),
    742         auth_info.address.clone(),
    743         auth_info.username.clone(),
    744     )?;
    745     let (ws_request, _) = SIPRequest::new(ack.clone(), 0);
    746     ws_sender.send(ws_request).await?;
    747 
    748     // Send new invite with auth
    749     // Extract request from sipmessage (we know its a request because we just sent one)
    750     let invite_request = match invite_request {
    751         rsip::SipMessage::Request(request) => request,
    752         _ => {
    753             return Err(color_eyre::eyre::eyre!(
    754                 "Expected a request message but got a response"
    755             ))
    756         }
    757     };
    758     let invite_request = generate_new_branch(invite_request)?;
    759     let invite_with_auth_request = generate_request_with_auth(
    760         invite_response.clone(),
    761         uri.auth.clone(),
    762         invite_request,
    763         auth_info.address.clone(),
    764         auth_info.username.clone(),
    765         auth_info.password,
    766     )?;
    767     let (ws_request, invite_authed_responses) =
    768         SIPRequest::new(invite_with_auth_request.clone(), 2);
    769     ws_sender.send(ws_request).await?;
    770 
    771     let invite_authed_responses = invite_authed_responses.await?;
    772     let invite_authed_response = match invite_authed_responses.last() {
    773         Some(response) => response,
    774         None => {
    775             return Err(color_eyre::eyre::eyre!("Got no response on invite"));
    776         }
    777     };
    778     info!("Last invite authed response: {}", invite_authed_response);
    779 
    780     let resp_body = invite_authed_response.body();
    781     let resp_body = String::from_utf8(resp_body.to_vec())?;
    782     info!("Got response body: {}", resp_body);
    783     let answer = RTCSessionDescription::answer(resp_body)?;
    784     info!("Got answer: {:#?}", answer);
    785 
    786     peer_connection.set_remote_description(answer).await?;
    787 
    788     // Get the contact uri from the response
    789     let contact_uri = invite_authed_response.contact_header().unwrap().uri()?;
    790     // Send ack
    791     // Get response branch of via header
    792     let params = invite_authed_response.via_header()?.params()?;
    793     let via_branch = match params.iter().find_map(|param| match param {
    794         rsip::param::Param::Branch(branch) => Some(branch),
    795         _ => None,
    796     }) {
    797         Some(branch) => branch,
    798         None => {
    799             return Err(color_eyre::eyre::eyre!("Got no branch in response"));
    800         }
    801     };
    802     let ack = generate_ack_request(
    803         call_id,
    804         2,
    805         contact_uri,
    806         via_branch.clone(),
    807         uri,
    808         auth_info.address,
    809         auth_info.username,
    810     )?;
    811 
    812     let (ws_request, _) = SIPRequest::new(ack.clone(), 0);
    813     ws_sender.send(ws_request).await?;
    814 
    815     let call_message = RoomMessageEventContent::notice_plain(format!(
    816         "Dialed out to {} with call ID {}",
    817         sip_address, 0
    818     ));
    819 
    820     room.send(call_message, None).await?;
    821 
    822     Ok(())
    823 }