Parrot.Sip.Transaction (Parrot Platform v0.0.1-alpha.3)

Implementation of SIP transaction management according to RFC 3261 Section 17.

A SIP transaction consists of a single request and any responses to that request, which include zero or more provisional responses and one or more final responses. Transactions are a fundamental component of the SIP protocol, providing reliability, message sequencing, and state management.

As defined in RFC 3261, there are four types of transactions:

  • INVITE Client Transaction (Section 17.1.1)
  • Non-INVITE Client Transaction (Section 17.1.2)
  • INVITE Server Transaction (Section 17.2.1)
  • Non-INVITE Server Transaction (Section 17.2.2)

Each transaction type has its own state machine and handling rules.

This module provides functionality for:

  • Creating client and server transactions
  • Generating transaction IDs and branch parameters
  • Managing transaction state transitions
  • Handling transaction timeouts and retransmissions
  • Correlating responses to requests

This module provides the pure functional implementation of SIP transactions. For stateful transaction management, see Parrot.Sip.TransactionStatem.

References:

  • RFC 3261: SIP: Session Initiation Protocol (https://tools.ietf.org/html/rfc3261)
    • Section 17: Transactions
    • Section 8.1.1.7: Transaction Identifier
    • Section 17.1: Client Transaction
    • Section 17.2: Server Transaction

Summary

Functions

Creates a new client transaction for an INVITE request.

Creates a new server transaction for an INVITE request.

Creates a new client transaction for a non-INVITE request.

Creates a new server transaction for a non-INVITE request.

Determines the transaction type based on a message.

Facade function for generating a transaction branch parameter.

Facade function for generating a transaction ID based on the message type.

Generates a transaction ID based on the transaction parameters.

Handles SIP transaction state machine events.

Checks if a transaction is a client transaction.

Checks if a transaction is a server transaction.

Checks if a transaction is terminated.

Checks if a transaction matches the given request.

Checks if a transaction matches the given response.

Processes a request within a server transaction.

Processes a response within a client transaction.

Sends a final response (2xx-6xx) in a server transaction.

Sends a provisional response (1xx) in a server transaction.

Starts a client transaction by sending the initial request.

Starts a server transaction upon receiving an initial request.

Terminates a transaction, canceling all timers.

Facade function for validating a SIP message for transaction processing.

Types

t()

@type t() :: %Parrot.Sip.Transaction{
  branch: String.t(),
  created_at: integer(),
  id: String.t(),
  last_response: Parrot.Sip.Message.t() | nil,
  method: atom(),
  request: Parrot.Sip.Message.t(),
  role: :uas | :uac | nil,
  state: transaction_state(),
  timer_a: reference() | nil,
  timer_b: reference() | nil,
  timer_c: reference() | nil,
  timer_d: reference() | nil,
  timer_e: reference() | nil,
  timer_f: reference() | nil,
  timer_g: reference() | nil,
  timer_h: reference() | nil,
  timer_i: reference() | nil,
  timer_j: reference() | nil,
  timer_k: reference() | nil,
  type: transaction_type()
}

transaction_state()

@type transaction_state() ::
  :init
  | :calling
  | :proceeding
  | :completed
  | :confirmed
  | :terminated
  | :trying
  | :completed

transaction_type()

@type transaction_type() ::
  :invite_client | :non_invite_client | :invite_server | :non_invite_server

Functions

create_invite_client(request)

@spec create_invite_client(Parrot.Sip.Message.t()) :: {:ok, t()}

Creates a new client transaction for an INVITE request.

Parameters

  • request: The SIP INVITE request that initiates the transaction

Returns

  • {:ok, transaction}: A new transaction struct

create_invite_server(request)

@spec create_invite_server(Parrot.Sip.Message.t()) :: {:ok, t()}

Creates a new server transaction for an INVITE request.

Parameters

  • request: The SIP INVITE request received

Returns

  • {:ok, transaction}: A new transaction struct

create_non_invite_client(request)

@spec create_non_invite_client(Parrot.Sip.Message.t()) :: {:ok, t()}

Creates a new client transaction for a non-INVITE request.

Parameters

  • request: The SIP request that initiates the transaction

Returns

  • {:ok, transaction}: A new transaction struct

create_non_invite_server(request)

@spec create_non_invite_server(Parrot.Sip.Message.t()) :: {:ok, t()}

Creates a new server transaction for a non-INVITE request.

Parameters

  • request: The SIP request received

Returns

  • {:ok, transaction}: A new transaction struct

determine_transaction_type(message)

@spec determine_transaction_type(Parrot.Sip.Message.t()) :: transaction_type()

Determines the transaction type based on a message.

RFC 3261 Section 17

generate_branch(message)

@spec generate_branch(Parrot.Sip.Message.t()) :: String.t()

Facade function for generating a transaction branch parameter.

This function initially delegates to ERSIP but will gradually be replaced with our pure Elixir implementation.

RFC 3261 Section 8.1.1.7

generate_id(message)

@spec generate_id(Parrot.Sip.Message.t()) :: String.t()

Facade function for generating a transaction ID based on the message type.

RFC 3261 Section 17

generate_transaction_id(type, branch, request)

@spec generate_transaction_id(transaction_type(), String.t(), Parrot.Sip.Message.t()) ::
  String.t()

Generates a transaction ID based on the transaction parameters.

Parameters

  • type: The transaction type
  • branch: The branch parameter from the Via header
  • request: The SIP request

Returns

  • A string representing the transaction ID

handle_event(event, transaction)

@spec handle_event(term(), t()) :: {t(), [term()]}

Handles SIP transaction state machine events.

This function processes an event for the given transaction, returning the updated transaction struct and a list of actions for the transaction server to execute.

Parameters

  • event - The event to process (e.g., {:send, response}, {:received, request}, {:timer, :g})
  • transaction - The %Parrot.Sip.Transaction{} struct representing the current transaction state

Returns

  • {new_transaction, actions} - The updated transaction and a list of actions (atoms or tuples)

Example

{new_trans, actions} = Parrot.Sip.Transaction.handle_event({:send, response}, transaction)

Supported actions include:

  • {:send_response, response}
  • {:send_request, request}
  • {:start_timer, timer_name, timeout_ms}
  • {:cancel_timer, timer_name}
  • :terminate_transaction
  • :ignore

is_client_transaction?(transaction)

@spec is_client_transaction?(t()) :: boolean()

Checks if a transaction is a client transaction.

Parameters

  • transaction: The transaction to check

Returns

  • true if the transaction is a client transaction, false otherwise

is_server_transaction?(transaction)

@spec is_server_transaction?(t()) :: boolean()

Checks if a transaction is a server transaction.

Parameters

  • transaction: The transaction to check

Returns

  • true if the transaction is a server transaction, false otherwise

is_terminated?(transaction)

@spec is_terminated?(t()) :: boolean()

Checks if a transaction is terminated.

Parameters

  • transaction: The transaction to check

Returns

  • true if the transaction is terminated, false otherwise

matches_request?(transaction, request)

@spec matches_request?(t(), Parrot.Sip.Message.t()) :: boolean()

Checks if a transaction matches the given request.

Parameters

  • transaction: The transaction to check
  • request: The request to match against

Returns

  • true if the transaction matches the request, false otherwise

matches_response?(transaction, response)

@spec matches_response?(t(), Parrot.Sip.Message.t()) :: boolean()

Checks if a transaction matches the given response.

Parameters

  • transaction: The transaction to check
  • response: The response to match against

Returns

  • true if the transaction matches the response, false otherwise

receive_request(request, transaction)

@spec receive_request(Parrot.Sip.Message.t(), t()) :: {:ok, t()}

Processes a request within a server transaction.

Updates the transaction state based on the received request.

Parameters

  • request: The SIP request received
  • transaction: The current transaction state

Returns

  • {:ok, updated_transaction}: The updated transaction

receive_response(response, transaction)

@spec receive_response(Parrot.Sip.Message.t(), t()) :: {:ok, t()}

Processes a response within a client transaction.

Updates the transaction state based on the received response.

Parameters

  • response: The SIP response received
  • transaction: The current transaction state

Returns

  • {:ok, updated_transaction}: The updated transaction

send_final_response(response, transaction)

@spec send_final_response(Parrot.Sip.Message.t(), t()) :: {:ok, t()}

Sends a final response (2xx-6xx) in a server transaction.

Parameters

  • response: The SIP response to send
  • transaction: The current transaction state

Returns

  • {:ok, updated_transaction}: The updated transaction

send_provisional_response(response, transaction)

@spec send_provisional_response(Parrot.Sip.Message.t(), t()) :: {:ok, t()}

Sends a provisional response (1xx) in a server transaction.

Parameters

  • response: The SIP response to send
  • transaction: The current transaction state

Returns

  • {:ok, updated_transaction}: The updated transaction

start_client_transaction(transaction)

@spec start_client_transaction(t()) :: {:ok, t()}

Starts a client transaction by sending the initial request.

Parameters

  • transaction: The transaction to start

Returns

  • {:ok, updated_transaction}: The updated transaction

start_server_transaction(transaction)

@spec start_server_transaction(t()) :: {:ok, t()}

Starts a server transaction upon receiving an initial request.

Parameters

  • transaction: The transaction to start

Returns

  • {:ok, updated_transaction}: The updated transaction

terminate(transaction)

@spec terminate(t()) :: {:ok, t()}

Terminates a transaction, canceling all timers.

Parameters

  • transaction: The transaction to terminate

Returns

  • {:ok, updated_transaction}: The updated transaction

validate_message(message)

@spec validate_message(Parrot.Sip.Message.t()) ::
  {:ok, Parrot.Sip.Message.t()} | {:error, String.t()}

Facade function for validating a SIP message for transaction processing.

This function performs validation on the message according to RFC 3261 requirements for transaction handling.

RFC 3261 Section 17