pub struct Registration {
pub last_seq: u32,
pub endpoint: EndpointInnerRef,
pub credential: Option<Credential>,
pub contact: Option<Contact>,
pub allow: Allow,
pub public_address: Option<HostWithPort>,
}Expand description
SIP Registration Client
Registration provides functionality for SIP user agent registration
with a SIP registrar server. Registration is the process by which a
SIP user agent informs a registrar server of its current location
and availability for receiving calls.
§Key Features
- User Registration - Registers user agent with SIP registrar
- Authentication Support - Handles digest authentication challenges
- Contact Management - Manages contact URI and expiration
- DNS Resolution - Resolves registrar server addresses
- Automatic Retry - Handles authentication challenges automatically
§Registration Process
- DNS Resolution - Resolves registrar server address
- REGISTER Request - Sends initial REGISTER request
- Authentication - Handles 401/407 challenges if needed
- Confirmation - Receives 200 OK with registration details
- Refresh - Periodically refreshes registration before expiration
§Examples
§Basic Registration
let credential = Credential {
username: "alice".to_string(),
password: "secret123".to_string(),
realm: Some("example.com".to_string()),
};
let mut registration = Registration::new(endpoint.inner.clone(), Some(credential));
let server = rsip::Uri::try_from("sip:sip.example.com").unwrap();
let response = registration.register(server.clone(), None).await?;
if response.status_code == rsip::StatusCode::OK {
println!("Registration successful");
println!("Expires in: {} seconds", registration.expires());
}
}§Registration Loop
let mut registration = Registration::new(endpoint.inner.clone(), Some(credential));
loop {
match registration.register(server.clone(), None).await {
Ok(response) if response.status_code == rsip::StatusCode::OK => {
let expires = registration.expires();
println!("Registered for {} seconds", expires);
// Re-register before expiration (with some margin)
tokio::time::sleep(Duration::from_secs((expires * 3 / 4) as u64)).await;
},
Ok(response) => {
eprintln!("Registration failed: {}", response.status_code);
tokio::time::sleep(Duration::from_secs(30)).await;
},
Err(e) => {
eprintln!("Registration error: {}", e);
tokio::time::sleep(Duration::from_secs(30)).await;
}
}
}§Thread Safety
Registration is not thread-safe and should be used from a single task. The sequence number and state are managed internally and concurrent access could lead to protocol violations.
Fields§
§last_seq: u32§endpoint: EndpointInnerRef§credential: Option<Credential>§contact: Option<Contact>§allow: Allow§public_address: Option<HostWithPort>Public address detected by the server (IP and port)
Implementations§
Source§impl Registration
impl Registration
Sourcepub fn new(endpoint: EndpointInnerRef, credential: Option<Credential>) -> Self
pub fn new(endpoint: EndpointInnerRef, credential: Option<Credential>) -> Self
Create a new registration client
Creates a new Registration instance for registering with a SIP server. The registration will use the provided endpoint for network communication and credentials for authentication if required.
§Parameters
endpoint- Reference to the SIP endpoint for network operationscredential- Optional authentication credentials
§Returns
A new Registration instance ready to perform registration
§Examples
// Registration without authentication
let registration = Registration::new(endpoint.inner.clone(), None);
// Registration with authentication
let credential = Credential {
username: "alice".to_string(),
password: "secret123".to_string(),
realm: Some("example.com".to_string()),
};
let registration = Registration::new(endpoint.inner.clone(), Some(credential));Sourcepub fn discovered_public_address(&self) -> Option<HostWithPort>
pub fn discovered_public_address(&self) -> Option<HostWithPort>
Get the discovered public address
Returns the public IP address and port discovered during the registration process. The SIP server indicates the client’s public address through the ‘received’ and ‘rport’ parameters in Via headers.
This is essential for NAT traversal, as it allows the client to use the correct public address in Contact headers and SDP for subsequent dialogs and media sessions.
§Returns
Some((ip, port))- The discovered public IP address and portNone- No public address has been discovered yet
§Examples
if let Some(public_address) = registration.discovered_public_address() {
println!("Public address: {}", public_address);
// Use this address for Contact headers in dialogs
} else {
println!("No public address discovered yet");
}Sourcepub fn expires(&self) -> u32
pub fn expires(&self) -> u32
Get the registration expiration time
Returns the expiration time in seconds for the current registration. This value is extracted from the Contact header’s expires parameter in the last successful registration response.
§Returns
Expiration time in seconds (default: 50 if not set)
§Examples
let expires = registration.expires();
println!("Registration expires in {} seconds", expires);
// Schedule re-registration before expiration
let refresh_time = expires * 3 / 4; // 75% of expiration time
tokio::time::sleep(Duration::from_secs(refresh_time as u64)).await;Sourcepub async fn register(
&mut self,
server: Uri,
expires: Option<u32>,
) -> Result<Response>
pub async fn register( &mut self, server: Uri, expires: Option<u32>, ) -> Result<Response>
Perform SIP registration with the server
Sends a REGISTER request to the specified SIP server to register the user agent’s current location. This method handles the complete registration process including DNS resolution, authentication challenges, and response processing.
§Parameters
server- SIP server hostname or IP address (e.g., “sip.example.com”)
§Returns
Ok(Response)- Final response from the registration serverErr(Error)- Registration failed due to network or protocol error
§Registration Flow
- DNS Resolution - Resolves server address and transport
- Request Creation - Creates REGISTER request with proper headers
- Initial Send - Sends the registration request
- Authentication - Handles 401/407 challenges if credentials provided
- Response Processing - Returns final response (200 OK or error)
§Response Codes
200 OK- Registration successful401 Unauthorized- Authentication required (handled automatically)403 Forbidden- Registration not allowed404 Not Found- User not found423 Interval Too Brief- Requested expiration too short
§Examples
§Successful Registration
let server = rsip::Uri::try_from("sip:sip.example.com").unwrap();
let response = registration.register(server, None).await?;
match response.status_code {
rsip::StatusCode::OK => {
println!("Registration successful");
// Extract registration details from response
if let Ok(_contact) = response.contact_header() {
println!("Registration confirmed");
}
},
rsip::StatusCode::Forbidden => {
println!("Registration forbidden");
},
_ => {
println!("Registration failed: {}", response.status_code);
}
}§Error Handling
match registration.register(server, None).await {
Ok(response) => {
// Handle response based on status code
},
Err(Error::DnsResolutionError(msg)) => {
eprintln!("DNS resolution failed: {}", msg);
},
Err(Error::TransportLayerError(msg, addr)) => {
eprintln!("Network error to {}: {}", addr, msg);
},
Err(e) => {
eprintln!("Registration error: {}", e);
}
}§Authentication
If credentials are provided during Registration creation, this method will automatically handle authentication challenges:
- Send initial REGISTER request
- Receive 401/407 challenge with authentication parameters
- Calculate authentication response using provided credentials
- Resend REGISTER with Authorization header
- Receive final response
§Contact Header
The method will automatically update the Contact header with the public address discovered during the registration process. This is essential for proper NAT traversal in SIP communications.
If you want to use a specific Contact header, you can set it manually before calling this method.
Sourcepub fn create_nat_aware_contact(
username: &str,
public_address: Option<HostWithPort>,
local_address: &SipAddr,
) -> Contact
pub fn create_nat_aware_contact( username: &str, public_address: Option<HostWithPort>, local_address: &SipAddr, ) -> Contact
Create a NAT-aware Contact header with public address
Creates a Contact header suitable for use in SIP dialogs that takes into account the public address discovered during registration. This is essential for proper NAT traversal in SIP communications.
§Parameters
username- SIP username for the Contact URIpublic_address- Optional public address to use (IP and port)local_address- Fallback local address if no public address available
§Returns
A Contact header with appropriate address for NAT traversal
§Examples
let contact = Registration::create_nat_aware_contact(
"alice",
Some(rsip::HostWithPort {
host: IpAddr::V4(Ipv4Addr::new(203, 0, 113, 1)).into(),
port: Some(5060.into()),
}),
&local_addr,
);Auto Trait Implementations§
impl Freeze for Registration
impl !RefUnwindSafe for Registration
impl Send for Registration
impl Sync for Registration
impl Unpin for Registration
impl !UnwindSafe for Registration
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> PipeAsRef for T
impl<T> PipeAsRef for T
Source§impl<T> PipeBorrow for T
impl<T> PipeBorrow for T
Source§impl<T> PipeDeref for T
impl<T> PipeDeref for T
Source§impl<T> PipeRef for T
impl<T> PipeRef for T
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&Self) -> R,
fn tap<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&Self) -> R,
Source§fn tap_dbg<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&Self) -> R,
fn tap_dbg<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&Self) -> R,
tap in debug builds, and does nothing in release builds.Source§fn tap_mut<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&mut Self) -> R,
fn tap_mut<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&mut Self) -> R,
Source§fn tap_mut_dbg<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&mut Self) -> R,
fn tap_mut_dbg<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&mut Self) -> R,
tap_mut in debug builds, and does nothing in release builds.Source§impl<T, U> TapAsRef<U> for Twhere
U: ?Sized,
impl<T, U> TapAsRef<U> for Twhere
U: ?Sized,
Source§fn tap_ref<F, R>(self, func: F) -> Self
fn tap_ref<F, R>(self, func: F) -> Self
Source§fn tap_ref_dbg<F, R>(self, func: F) -> Self
fn tap_ref_dbg<F, R>(self, func: F) -> Self
tap_ref in debug builds, and does nothing in release builds.Source§fn tap_ref_mut<F, R>(self, func: F) -> Self
fn tap_ref_mut<F, R>(self, func: F) -> Self
Source§impl<T, U> TapBorrow<U> for Twhere
U: ?Sized,
impl<T, U> TapBorrow<U> for Twhere
U: ?Sized,
Source§fn tap_borrow<F, R>(self, func: F) -> Self
fn tap_borrow<F, R>(self, func: F) -> Self
Source§fn tap_borrow_dbg<F, R>(self, func: F) -> Self
fn tap_borrow_dbg<F, R>(self, func: F) -> Self
tap_borrow in debug builds, and does nothing in release builds.Source§fn tap_borrow_mut<F, R>(self, func: F) -> Self
fn tap_borrow_mut<F, R>(self, func: F) -> Self
Source§impl<T> TapDeref for T
impl<T> TapDeref for T
Source§fn tap_deref_dbg<F, R>(self, func: F) -> Self
fn tap_deref_dbg<F, R>(self, func: F) -> Self
tap_deref in debug builds, and does nothing in release builds.Source§fn tap_deref_mut<F, R>(self, func: F) -> Self
fn tap_deref_mut<F, R>(self, func: F) -> Self
self for modification.