active_call/useragent/
registration.rs1use anyhow::Result;
2use rsip::{HostWithPort, Response, StatusCodeKind, Transport};
3use rsipstack::{
4 dialog::{authenticate::Credential, registration::Registration},
5 rsip_ext::RsipResponseExt, transport::SipAddr,
6};
7use serde::{Deserialize, Serialize};
8use std::time::Instant;
9use tokio_util::sync::CancellationToken;
10use tracing::{debug, warn};
11
12use super::public_address::{normalize_transport, should_update_address};
13
14#[derive(Debug, Deserialize, Clone, Serialize)]
15pub struct UserCredential {
16 pub username: String,
17 pub password: String,
18 pub realm: Option<String>,
19}
20
21#[derive(Debug, Deserialize, Clone, Serialize)]
22pub struct RegisterOption {
23 pub server: String,
24 pub username: String,
25 pub display_name: Option<String>,
26 pub disabled: Option<bool>,
27 pub credential: Option<UserCredential>,
28}
29
30impl From<UserCredential> for Credential {
31 fn from(val: UserCredential) -> Self {
32 Credential {
33 username: val.username,
34 password: val.password,
35 realm: val.realm,
36 }
37 }
38}
39
40impl RegisterOption {
41 pub fn aor(&self) -> String {
42 format!("{}@{}", self.username, self.server)
43 }
44}
45
46pub struct RegistrationHandle {
47 pub registration: Registration,
48 pub option: RegisterOption,
49 pub cancel_token: CancellationToken,
50 pub start_time: Instant,
51 pub last_update: Instant,
52 pub last_response: Option<Response>,
53}
54
55impl RegistrationHandle {
56 pub fn should_retry_registration_now(
57 &self,
58 local_addr: &SipAddr,
59 current_contact_address: &HostWithPort,
60 discovered_public_address: Option<&HostWithPort>,
61 ) -> bool {
62 if normalize_transport(local_addr.r#type.as_ref()) != Transport::Udp {
63 return false;
64 }
65
66 discovered_public_address
67 .is_some_and(|address| should_update_address(current_contact_address, address))
68 }
69
70 pub async fn do_register(
71 &mut self,
72 sip_server: &rsip::Uri,
73 expires: Option<u32>,
74 contact: &rsip::typed::Contact,
75 ) -> Result<(u32, Option<HostWithPort>)> {
76 self.registration.contact = Some(contact.clone());
77 let resp = match self
78 .registration
79 .register(sip_server.clone(), expires)
80 .await
81 .map_err(|e| anyhow::anyhow!("Registration failed: {}", e))
82 {
83 Ok(resp) => resp,
84 Err(e) => {
85 warn!("registration failed: {}", e);
86 return Err(anyhow::anyhow!("Registration failed: {}", e));
87 }
88 };
89 debug!(
90 user = self.option.aor(),
91 "registration response: {:?}", resp
92 );
93 match resp.status_code().kind() {
94 StatusCodeKind::Successful => {
95 self.last_update = Instant::now();
96 self.last_response = Some(resp);
97 Ok((
98 self.registration.expires(),
99 self.registration.public_address.clone(),
100 ))
101 }
102 _ => Err(anyhow::anyhow!("{:?}", resp.reason_phrase())),
103 }
104 }
105}