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 }