Registration

Struct Registration 

Source
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

  1. DNS Resolution - Resolves registrar server address
  2. REGISTER Request - Sends initial REGISTER request
  3. Authentication - Handles 401/407 challenges if needed
  4. Confirmation - Receives 200 OK with registration details
  5. 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

Source

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 operations
  • credential - 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));
Source

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 port
  • None - 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");
}
Source

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;
Source

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 server
  • Err(Error) - Registration failed due to network or protocol error
§Registration Flow
  1. DNS Resolution - Resolves server address and transport
  2. Request Creation - Creates REGISTER request with proper headers
  3. Initial Send - Sends the registration request
  4. Authentication - Handles 401/407 challenges if credentials provided
  5. Response Processing - Returns final response (200 OK or error)
§Response Codes
  • 200 OK - Registration successful
  • 401 Unauthorized - Authentication required (handled automatically)
  • 403 Forbidden - Registration not allowed
  • 404 Not Found - User not found
  • 423 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:

  1. Send initial REGISTER request
  2. Receive 401/407 challenge with authentication parameters
  3. Calculate authentication response using provided credentials
  4. Resend REGISTER with Authorization header
  5. 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.

Source

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 URI
  • public_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§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into a target type. Read more
Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows 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
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows 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
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Pipe for T

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R

Pipes a value into a function that cannot ordinarily be called in suffix position. Read more
Source§

impl<T> PipeAsRef for T

Source§

fn pipe_as_ref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: AsRef<T>, T: 'a, R: 'a,

Pipes a trait borrow into a function that cannot normally be called in suffix position. Read more
Source§

fn pipe_as_mut<'a, T, R>(&'a mut self, func: impl FnOnce(&'a mut T) -> R) -> R
where Self: AsMut<T>, T: 'a, R: 'a,

Pipes a trait mutable borrow into a function that cannot normally be called in suffix position. Read more
Source§

impl<T> PipeBorrow for T

Source§

fn pipe_borrow<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Borrow<T>, T: 'a, R: 'a,

Pipes a trait borrow into a function that cannot normally be called in suffix position. Read more
Source§

fn pipe_borrow_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: BorrowMut<T>, T: 'a, R: 'a,

Pipes a trait mutable borrow into a function that cannot normally be called in suffix position. Read more
Source§

impl<T> PipeDeref for T

Source§

fn pipe_deref<'a, R>(&'a self, func: impl FnOnce(&'a Self::Target) -> R) -> R
where Self: Deref, R: 'a,

Pipes a dereference into a function that cannot normally be called in suffix position. Read more
Source§

fn pipe_deref_mut<'a, R>( &'a mut self, func: impl FnOnce(&'a mut Self::Target) -> R, ) -> R
where Self: DerefMut, R: 'a,

Pipes a mutable dereference into a function that cannot normally be called in suffix position. Read more
Source§

impl<T> PipeRef for T

Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Pipes a reference into a function that cannot ordinarily be called in suffix position. Read more
Source§

fn pipe_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Pipes a mutable reference into a function that cannot ordinarily be called in suffix position. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .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
where Self: BorrowMut<B>, B: ?Sized,

Calls .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
where Self: AsRef<R>, R: ?Sized,

Calls .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
where Self: AsMut<R>, R: ?Sized,

Calls .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
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> Tap for T

Source§

fn tap<F, R>(self, func: F) -> Self
where F: FnOnce(&Self) -> R,

Provides immutable access for inspection. Read more
Source§

fn tap_dbg<F, R>(self, func: F) -> Self
where F: FnOnce(&Self) -> R,

Calls tap in debug builds, and does nothing in release builds.
Source§

fn tap_mut<F, R>(self, func: F) -> Self
where F: FnOnce(&mut Self) -> R,

Provides mutable access for modification. Read more
Source§

fn tap_mut_dbg<F, R>(self, func: F) -> Self
where F: FnOnce(&mut Self) -> R,

Calls tap_mut in debug builds, and does nothing in release builds.
Source§

impl<T, U> TapAsRef<U> for T
where U: ?Sized,

Source§

fn tap_ref<F, R>(self, func: F) -> Self
where Self: AsRef<T>, F: FnOnce(&T) -> R,

Provides immutable access to the reference for inspection.
Source§

fn tap_ref_dbg<F, R>(self, func: F) -> Self
where Self: AsRef<T>, F: FnOnce(&T) -> R,

Calls tap_ref in debug builds, and does nothing in release builds.
Source§

fn tap_ref_mut<F, R>(self, func: F) -> Self
where Self: AsMut<T>, F: FnOnce(&mut T) -> R,

Provides mutable access to the reference for modification.
Source§

fn tap_ref_mut_dbg<F, R>(self, func: F) -> Self
where Self: AsMut<T>, F: FnOnce(&mut T) -> R,

Calls tap_ref_mut in debug builds, and does nothing in release builds.
Source§

impl<T, U> TapBorrow<U> for T
where U: ?Sized,

Source§

fn tap_borrow<F, R>(self, func: F) -> Self
where Self: Borrow<T>, F: FnOnce(&T) -> R,

Provides immutable access to the borrow for inspection. Read more
Source§

fn tap_borrow_dbg<F, R>(self, func: F) -> Self
where Self: Borrow<T>, F: FnOnce(&T) -> R,

Calls tap_borrow in debug builds, and does nothing in release builds.
Source§

fn tap_borrow_mut<F, R>(self, func: F) -> Self
where Self: BorrowMut<T>, F: FnOnce(&mut T) -> R,

Provides mutable access to the borrow for modification.
Source§

fn tap_borrow_mut_dbg<F, R>(self, func: F) -> Self
where Self: BorrowMut<T>, F: FnOnce(&mut T) -> R,

Calls tap_borrow_mut in debug builds, and does nothing in release builds.
Source§

impl<T> TapDeref for T

Source§

fn tap_deref<F, R>(self, func: F) -> Self
where Self: Deref, F: FnOnce(&Self::Target) -> R,

Immutably dereferences self for inspection.
Source§

fn tap_deref_dbg<F, R>(self, func: F) -> Self
where Self: Deref, F: FnOnce(&Self::Target) -> R,

Calls tap_deref in debug builds, and does nothing in release builds.
Source§

fn tap_deref_mut<F, R>(self, func: F) -> Self
where Self: DerefMut, F: FnOnce(&mut Self::Target) -> R,

Mutably dereferences self for modification.
Source§

fn tap_deref_mut_dbg<F, R>(self, func: F) -> Self
where Self: DerefMut, F: FnOnce(&mut Self::Target) -> R,

Calls tap_deref_mut in debug builds, and does nothing in release builds.
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into a target type. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,