ftth_rsipstack/transaction/
mod.rs

1use crate::transport::{SipAddr, SipConnection};
2use key::TransactionKey;
3use std::time::Duration;
4use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
5use transaction::Transaction;
6
7pub mod endpoint;
8pub mod key;
9pub mod message;
10mod timer;
11pub mod transaction;
12pub use endpoint::Endpoint;
13pub use endpoint::EndpointBuilder;
14#[cfg(test)]
15mod tests;
16
17pub const TO_TAG_LEN: usize = 8;
18pub const BRANCH_LEN: usize = 12;
19pub const CNONCE_LEN: usize = 8;
20pub const CALL_ID_LEN: usize = 22;
21pub struct IncomingRequest {
22    pub request: rsip::Request,
23    pub connection: SipConnection,
24    pub from: SipAddr,
25}
26
27pub type TransactionReceiver = UnboundedReceiver<Transaction>;
28pub type TransactionSender = UnboundedSender<Transaction>;
29
30/// SIP Transaction State
31///
32/// `TransactionState` represents the various states a SIP transaction can be in
33/// during its lifecycle. These states implement the transaction state machines
34/// defined in RFC 3261 for both client and server transactions.
35///
36/// # States
37///
38/// * `Nothing` - Initial state for client transactions created
39/// * `Calling` - Initial state for client transactions when request is sent or received
40/// * `Trying` - Request has been sent/received, waiting for response/processing
41/// * `Proceeding` - Provisional response received/sent (1xx except 100 Trying)
42/// * `Completed` - Final response received/sent, waiting for ACK (INVITE) or cleanup
43/// * `Confirmed` - ACK received/sent for INVITE transactions
44/// * `Terminated` - Transaction has completed and is being cleaned up
45///
46/// # State Transitions
47///
48/// ## Client Non-INVITE Transaction
49/// ```text
50/// Nothing → Calling → Trying → Proceeding → Completed → Terminated
51/// ```
52///
53/// ## Client INVITE Transaction  
54/// ```text
55/// Nothing → Calling → Trying → Proceeding → Completed → Terminated
56///                                      ↓
57///                                   Confirmed → Terminated
58/// ```
59///
60/// ## Server Transactions
61/// ```text
62/// Calling → Trying → Proceeding → Completed → Terminated
63///                           ↓
64///                         Confirmed → Terminated (INVITE only)
65/// ```
66///
67/// # Examples
68///
69/// ```rust
70/// use rsipstack::transaction::TransactionState;
71///
72/// let state = TransactionState::Proceeding;
73/// match state {
74///     TransactionState::Nothing => println!("Transaction starting"),
75///     TransactionState::Calling => println!("Request sent"),
76///     TransactionState::Trying => println!("Request sent/received"),
77///     TransactionState::Proceeding => println!("Provisional response"),
78///     TransactionState::Completed => println!("Final response"),
79///     TransactionState::Confirmed => println!("ACK received/sent"),
80///     TransactionState::Terminated => println!("Transaction complete"),
81/// }
82/// ```
83#[derive(Debug, Clone, PartialEq)]
84pub enum TransactionState {
85    Nothing,
86    Calling,
87    Trying,
88    Proceeding,
89    Completed,
90    Confirmed,
91    Terminated,
92}
93
94impl std::fmt::Display for TransactionState {
95    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96        match self {
97            TransactionState::Nothing => write!(f, "Nothing"),
98            TransactionState::Calling => write!(f, "Calling"),
99            TransactionState::Trying => write!(f, "Trying"),
100            TransactionState::Proceeding => write!(f, "Proceeding"),
101            TransactionState::Completed => write!(f, "Completed"),
102            TransactionState::Confirmed => write!(f, "Confirmed"),
103            TransactionState::Terminated => write!(f, "Terminated"),
104        }
105    }
106}
107/// SIP Transaction Type
108///
109/// `TransactionType` distinguishes between the four types of SIP transactions
110/// as defined in RFC 3261. Each type has different behavior for retransmissions,
111/// timers, and state transitions.
112///
113/// # Types
114///
115/// * `ClientInvite` - Client-side INVITE transaction (UAC INVITE)
116/// * `ClientNonInvite` - Client-side non-INVITE transaction (UAC non-INVITE)
117/// * `ServerInvite` - Server-side INVITE transaction (UAS INVITE)
118/// * `ServerNonInvite` - Server-side non-INVITE transaction (UAS non-INVITE)
119///
120/// # Characteristics
121///
122/// ## Client INVITE
123/// * Longer timeouts due to human interaction
124/// * ACK handling for 2xx responses
125/// * CANCEL support for early termination
126///
127/// ## Client Non-INVITE
128/// * Shorter timeouts for automated responses
129/// * No ACK required
130/// * Simpler state machine
131///
132/// ## Server INVITE
133/// * Must handle ACK for final responses
134/// * Supports provisional responses
135/// * Complex retransmission rules
136///
137/// ## Server Non-INVITE
138/// * Simple request/response pattern
139/// * No ACK handling
140/// * Faster completion
141///
142/// # Examples
143///
144/// ```rust
145/// use rsipstack::transaction::TransactionType;
146/// use rsip::Method;
147///
148/// fn get_transaction_type(method: &Method, is_client: bool) -> TransactionType {
149///     match (method, is_client) {
150///         (Method::Invite, true) => TransactionType::ClientInvite,
151///         (Method::Invite, false) => TransactionType::ServerInvite,
152///         (_, true) => TransactionType::ClientNonInvite,
153///         (_, false) => TransactionType::ServerNonInvite,
154///     }
155/// }
156/// ```
157#[derive(Debug, PartialEq)]
158pub enum TransactionType {
159    ClientInvite,
160    ClientNonInvite,
161    ServerInvite,
162    ServerNonInvite,
163}
164impl std::fmt::Display for TransactionType {
165    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
166        match self {
167            TransactionType::ClientInvite => write!(f, "ClientInvite"),
168            TransactionType::ClientNonInvite => write!(f, "ClientNonInvite"),
169            TransactionType::ServerInvite => write!(f, "ServerInvite"),
170            TransactionType::ServerNonInvite => write!(f, "ServerNonInvite"),
171        }
172    }
173}
174/// SIP Transaction Timers
175///
176/// `TransactionTimer` represents the various timers used in SIP transactions
177/// as defined in RFC 3261. These timers ensure reliable message delivery
178/// and proper transaction cleanup.
179///
180/// # Timer Types
181///
182/// * `TimerA` - Retransmission timer for client transactions (unreliable transport)
183/// * `TimerB` - Transaction timeout timer for client transactions
184/// * `TimerD` - Wait timer for response retransmissions (client)
185/// * `TimerE` - Retransmission timer for non-INVITE server transactions
186/// * `TimerF` - Transaction timeout timer for non-INVITE server transactions
187/// * `TimerK` - Wait timer for ACK (server INVITE transactions)
188/// * `TimerG` - Retransmission timer for INVITE server transactions
189/// * `TimerCleanup` - Internal cleanup timer for transaction removal
190///
191/// # Timer Values (RFC 3261)
192///
193/// * T1 = 500ms (RTT estimate)
194/// * T2 = 4s (maximum retransmit interval)
195/// * T4 = 5s (maximum duration a message will remain in the network)
196///
197/// ## Timer Calculations
198/// * Timer A: starts at T1, doubles each retransmission up to T2
199/// * Timer B: 64*T1 (32 seconds)
200/// * Timer D: 32 seconds for unreliable, 0 for reliable transports
201/// * Timer E: starts at T1, doubles up to T2
202/// * Timer F: 64*T1 (32 seconds)
203/// * Timer G: starts at T1, doubles up to T2
204/// * Timer K: T4 for unreliable, 0 for reliable transports
205///
206/// # Examples
207///
208/// ```rust
209/// use rsipstack::transaction::{TransactionTimer, key::{TransactionKey, TransactionRole}};
210/// use std::time::Duration;
211///
212/// # fn example() -> rsipstack::Result<()> {
213/// // Create a mock request to generate a transaction key
214/// let request = rsip::Request {
215///     method: rsip::Method::Register,
216///     uri: rsip::Uri::try_from("sip:example.com")?,
217///     headers: vec![
218///         rsip::Header::Via("SIP/2.0/UDP example.com:5060;branch=z9hG4bKnashds".into()),
219///         rsip::Header::CSeq("1 REGISTER".into()),
220///         rsip::Header::From("Alice <sip:alice@example.com>;tag=1928301774".into()),
221///         rsip::Header::CallId("a84b4c76e66710@pc33.atlanta.com".into()),
222///     ].into(),
223///     version: rsip::Version::V2,
224///     body: Default::default(),
225/// };
226/// let key = TransactionKey::from_request(&request, TransactionRole::Client)?;
227///
228/// let timer = TransactionTimer::TimerA(key.clone(), Duration::from_millis(500));
229/// match timer {
230///     TransactionTimer::TimerA(key, duration) => {
231///         println!("Timer A fired for transaction {}", key);
232///     },
233///     TransactionTimer::TimerB(key) => {
234///         println!("Transaction {} timed out", key);
235///     },
236///     _ => {}
237/// }
238/// # Ok(())
239/// # }
240/// ```
241///
242/// # Usage
243///
244/// Timers are automatically managed by the transaction layer:
245/// * Started when entering appropriate states
246/// * Cancelled when leaving states or receiving responses
247/// * Fire events that drive state machine transitions
248/// * Handle retransmissions and timeouts
249pub enum TransactionTimer {
250    TimerA(TransactionKey, Duration),
251    TimerB(TransactionKey),
252    TimerC(TransactionKey),
253    TimerD(TransactionKey),
254    TimerK(TransactionKey),
255    TimerG(TransactionKey, Duration),
256    TimerCleanup(TransactionKey),
257}
258
259impl TransactionTimer {
260    pub fn key(&self) -> &TransactionKey {
261        match self {
262            TransactionTimer::TimerA(key, _) => key,
263            TransactionTimer::TimerB(key) => key,
264            TransactionTimer::TimerC(key) => key,
265            TransactionTimer::TimerD(key) => key,
266            TransactionTimer::TimerG(key, _) => key,
267            TransactionTimer::TimerK(key) => key,
268            TransactionTimer::TimerCleanup(key) => key,
269        }
270    }
271}
272
273impl std::fmt::Display for TransactionTimer {
274    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275        match self {
276            TransactionTimer::TimerA(key, duration) => {
277                write!(f, "TimerA: {} {}", key, duration.as_millis())
278            }
279            TransactionTimer::TimerB(key) => write!(f, "TimerB: {}", key),
280            TransactionTimer::TimerC(key) => write!(f, "TimerC: {}", key),
281            TransactionTimer::TimerD(key) => write!(f, "TimerD: {}", key),
282            TransactionTimer::TimerG(key, duration) => {
283                write!(f, "TimerG: {} {}", key, duration.as_millis())
284            }
285            TransactionTimer::TimerK(key) => write!(f, "TimerK: {}", key),
286            TransactionTimer::TimerCleanup(key) => write!(f, "TimerCleanup: {}", key),
287        }
288    }
289}
290
291pub fn make_via_branch() -> rsip::Param {
292    rsip::Param::Branch(format!("z9hG4bK{}", random_text(BRANCH_LEN)).into())
293}
294
295pub fn make_call_id(domain: Option<&str>) -> rsip::headers::CallId {
296    format!(
297        "{}@{}",
298        random_text(CALL_ID_LEN),
299        domain.unwrap_or("restsend.com")
300    )
301    .into()
302}
303
304pub fn make_tag() -> rsip::param::Tag {
305    random_text(TO_TAG_LEN).into()
306}
307
308pub fn random_text(count: usize) -> String {
309    use rand::Rng;
310    rand::rng()
311        .sample_iter(rand::distr::Alphanumeric)
312        .take(count)
313        .map(char::from)
314        .collect::<String>()
315}