Skip to main content

sipx_sip/transaction/
mod.rs

1//! Transactions (RFC 3261 §17, amended by RFC 6026).
2//!
3//! Four state machines, all of them sans-IO: they read no clock, own no socket and spawn
4//! nothing. Time arrives as [`Timer`] inputs and leaves as [`Output::SetTimer`]. That is what
5//! makes retransmission behaviour — the part of SIP that is hardest to get right and hardest
6//! to test — reachable from an ordinary unit test with no sleeping and no flakiness.
7//!
8//! The state tables in `docs/specs/sip-transaction.md` are the specification; this code is
9//! written from them and the tests walk them row by row.
10
11mod client;
12mod key;
13mod layer;
14mod server;
15mod timing;
16
17pub use client::{ClientState, ClientTransaction};
18pub use key::TransactionKey;
19pub use layer::{Dispatch, TransactionLayer, sent_messages, tu_events};
20pub use server::{ServerState, ServerTransaction};
21pub use timing::{Timer, Timers};
22
23use std::time::Duration;
24
25use crate::message::{Message, Request, Response};
26
27/// Something the driver must do on the transaction's behalf.
28///
29/// Order matters and is preserved: a `Send` always precedes the `SetTimer` that will
30/// retransmit it, so a retransmission timer can never start before the thing it retransmits
31/// has gone out.
32#[derive(Debug, Clone)]
33pub enum Output {
34    /// Put this message on the wire.
35    Send(Box<Message>),
36    /// Arrange for [`Timer`] to fire after this long.
37    SetTimer {
38        /// Which timer.
39        timer: Timer,
40        /// How long from now.
41        after: Duration,
42    },
43    /// Cancel a timer that has not fired.
44    ClearTimer(Timer),
45    /// Hand this to the transaction user.
46    ToTu(Box<TuEvent>),
47    /// The transaction is over; the layer above should drop it.
48    Terminated(Reason),
49}
50
51impl Output {
52    fn send(message: Message) -> Self {
53        Self::Send(Box::new(message))
54    }
55
56    fn to_tu(event: TuEvent) -> Self {
57        Self::ToTu(Box::new(event))
58    }
59}
60
61/// What the transaction has to tell the transaction user.
62#[derive(Debug, Clone)]
63pub enum TuEvent {
64    /// A request arrived that the TU has not seen before.
65    ///
66    /// A retransmission never produces this: the transaction answers those itself. Without
67    /// that, a UDP peer that misses one response makes the application process the same
68    /// REGISTER seven times.
69    Request(Box<Request>),
70    /// A response arrived.
71    ///
72    /// Under RFC 6026 a 2xx to an INVITE can arrive more than once — a forking proxy produces
73    /// exactly that — and each one is delivered. Two 200s for one INVITE is a fork, not a bug.
74    Response(Box<Response>),
75    /// An ACK for a 2xx response, which is a separate transaction and therefore the TU's
76    /// business (RFC 3261 §13.2.2.4, RFC 6026).
77    Ack(Box<Request>),
78    /// No answer within 64·T1.
79    Timeout,
80    /// The transport could not deliver.
81    TransportError,
82}
83
84/// Why a transaction ended.
85#[derive(Debug, Clone, Copy, PartialEq, Eq)]
86pub enum Reason {
87    /// It ran its course.
88    Completed,
89    /// Nothing was heard within 64·T1.
90    Timeout,
91    /// The transport failed.
92    TransportError,
93}
94
95/// Whether the transport delivers reliably, which decides half the timer behaviour.
96#[derive(Debug, Clone, Copy, PartialEq, Eq)]
97pub enum Reliability {
98    /// TCP, TLS, WebSocket: no retransmission timers, and the absorption timers fire at once.
99    Reliable,
100    /// UDP: retransmit until answered.
101    Unreliable,
102}
103
104impl Reliability {
105    /// Whether this transport retransmits.
106    #[must_use]
107    pub fn is_reliable(self) -> bool {
108        matches!(self, Self::Reliable)
109    }
110}