Parrot.Sip.Headers.Via (Parrot Platform v0.0.1-alpha.2)
Module for working with SIP Via headers as defined in RFC 3261 Section 20.42.
The Via header is used to record the route taken by a SIP request and to route responses back along the same path. Each SIP element (proxy or UAC) that sends a request adds a Via header with its own address, while responses follow the Via headers in reverse order.
The Via header contains:
- Protocol and version (e.g., "SIP/2.0")
- Transport protocol (e.g., UDP, TCP, TLS)
- Sent-by address (hostname or IP address and optional port)
- Branch parameter (a unique transaction identifier)
- Optional parameters (e.g., received, rport, maddr)
Via headers are critical for:
- Loop detection (using the branch parameter)
- Response routing (following the Via chain backwards)
- NAT traversal (using received/rport parameters)
The branch parameter starting with "z9hG4bK" indicates compliance with RFC 3261 (Section 8.1.1.7) and forms part of the transaction identifier.
This module supports both IPv4 and IPv6 addresses. IPv6 addresses in Via headers must be enclosed in square brackets as specified in RFC 3261 Section 25.1.
References:
- RFC 3261 Section 8.1.1.7: Transaction Identifier
- RFC 3261 Section 18.2.1: Sending Responses
- RFC 3261 Section 20.42: Via Header Field
- RFC 3261 Section 25.1: IPv6 References
- RFC 3581: Symmetric Response Routing (rport parameter)
Summary
Functions
Gets the branch parameter from a Via header.
Ensures that the branch parameter in a Via header is RFC 3261 compliant.
Converts a Via header to a string representation.
Formats a list of Via headers for SIP message serialization.
Generates a unique branch parameter for a Via header.
Gets a parameter from a Via header.
Checks if a parameter exists in the Via header.
Creates a new Via header.
Creates a new Via header with a randomly generated branch parameter.
Parses a Via header string into a Via struct.
Gets the received parameter from a Via header.
Checks if the branch parameter in a Via header is RFC 3261 compliant.
Gets the rport parameter from a Via header.
Returns a tuple {topmost, rest}
where topmost
is the first Via header and rest
is the remaining Via structs (or nil if only one) from a SIP message struct.
Returns the topmost (first) Via header from a SIP message struct.
Adds or updates a parameter in a Via header.
Types
Functions
Gets the branch parameter from a Via header.
Returns the branch parameter value or nil if not present.
Examples
iex> via = Parrot.Sip.Headers.Via.new("example.com", "udp", nil, %{"branch" => "z9hG4bKabc"})
iex> Parrot.Sip.Headers.Via.branch(via)
"z9hG4bKabc"
Ensures that the branch parameter in a Via header is RFC 3261 compliant.
If the branch parameter is already compliant, returns the Via header unchanged. If not, adds the magic cookie "z9hG4bK" to the beginning of the branch. If no branch is present, generates a new one.
Examples
iex> via = Parrot.Sip.Headers.Via.new("example.com")
iex> via = Parrot.Sip.Headers.Via.with_parameter(via, "branch", "abc123")
iex> via = Parrot.Sip.Headers.Via.ensure_rfc3261_branch(via)
iex> Parrot.Sip.Headers.Via.branch(via)
"z9hG4bKabc123"
Converts a Via header to a string representation.
Examples
iex> via = Parrot.Sip.Headers.Via.new("example.com", :udp, 5060, %{"branch" => "z9hG4bKabc"})
iex> Parrot.Sip.Headers.Via.format(via)
"SIP/2.0/UDP example.com:5060;branch=z9hG4bKabc"
Formats a list of Via headers for SIP message serialization.
Multiple Via headers are formatted on separate lines in SIP messages.
Examples
iex> via1 = Parrot.Sip.Headers.Via.new("proxy1.com", :udp, 5060)
iex> via2 = Parrot.Sip.Headers.Via.new("proxy2.com", :tcp, 5061)
iex> Parrot.Sip.Headers.Via.format_list([via1, via2])
"SIP/2.0/UDP proxy1.com:5060, SIP/2.0/TCP proxy2.com:5061"
@spec generate_branch() :: String.t()
Generates a unique branch parameter for a Via header.
Delegates to Parrot.Sip.Branch.generate/0
.
Examples
iex> Parrot.Sip.Headers.Via.generate_branch()
"z9hG4bK..." # output will vary
Gets a parameter from a Via header.
Examples
iex> via = Parrot.Sip.Headers.Via.new("example.com", "udp", nil, %{"rport" => "5060"})
iex> Parrot.Sip.Headers.Via.get_parameter(via, "rport")
"5060"
Checks if a parameter exists in the Via header.
Examples
iex> via = Parrot.Sip.Headers.Via.new("example.com")
iex> via = Parrot.Sip.Headers.Via.with_parameter(via, "branch", "z9hG4bKabc")
iex> Parrot.Sip.Headers.Via.has_parameter?(via, "branch")
true
iex> Parrot.Sip.Headers.Via.has_parameter?(via, "received")
false
Creates a new Via header.
Examples
iex> Parrot.Sip.Headers.Via.new("example.com")
%Parrot.Sip.Headers.Via{
protocol: "SIP",
version: "2.0",
transport: :udp,
host: "example.com",
port: nil,
host_type: :hostname,
parameters: %{}
}
Creates a new Via header with a randomly generated branch parameter.
Examples
iex> via = Parrot.Sip.Headers.Via.new_with_branch("example.com")
iex> Parrot.Sip.Headers.Via.branch(via) |> String.starts_with?("z9hG4bK")
true
Parses a Via header string into a Via struct.
Examples
iex> Parrot.Sip.Headers.Via.parse("SIP/2.0/UDP server10.biloxi.com:5060;branch=z9hG4bKnashds8")
%Parrot.Sip.Headers.Via{protocol: "SIP", version: "2.0", transport: :udp, host: "server10.biloxi.com", port: 5060, host_type: :hostname, parameters: %{"branch" => "z9hG4bKnashds8"}}
iex> Parrot.Sip.Headers.Via.parse("SIP/2.0/UDP [2001:db8::1]:5060;branch=z9hG4bK776asdhds")
%Parrot.Sip.Headers.Via{protocol: "SIP", version: "2.0", transport: :udp, host: "[2001:db8::1]", port: 5060, host_type: :ipv6, parameters: %{"branch" => "z9hG4bK776asdhds"}}
Gets the received parameter from a Via header.
Examples
iex> via = Parrot.Sip.Headers.Via.new("example.com", "udp", nil, %{"received" => "203.0.113.1"})
iex> Parrot.Sip.Headers.Via.received(via)
"203.0.113.1"
Checks if the branch parameter in a Via header is RFC 3261 compliant.
A branch parameter is RFC 3261 compliant if it starts with the magic cookie "z9hG4bK".
Examples
iex> via = Parrot.Sip.Headers.Via.new("example.com")
iex> via = Parrot.Sip.Headers.Via.with_parameter(via, "branch", "z9hG4bKabc123")
iex> Parrot.Sip.Headers.Via.rfc3261_compliant_branch?(via)
true
iex> via = Parrot.Sip.Headers.Via.new("example.com")
iex> via = Parrot.Sip.Headers.Via.with_parameter(via, "branch", "abc123")
iex> Parrot.Sip.Headers.Via.rfc3261_compliant_branch?(via)
false
Gets the rport parameter from a Via header.
Examples
iex> via = Parrot.Sip.Headers.Via.new("example.com", "udp", nil, %{"rport" => "5060"})
iex> Parrot.Sip.Headers.Via.rport(via)
"5060"
Returns a tuple {topmost, rest}
where topmost
is the first Via header and rest
is the remaining Via structs (or nil if only one) from a SIP message struct.
Examples
iex> Parrot.Sip.Headers.Via.take_topmost(message)
{%Parrot.Sip.Headers.Via{host: "host1", ...}, [rest...]}
Returns the topmost (first) Via header from a SIP message struct.
Examples
iex> Parrot.Sip.Headers.Via.topmost(message)
%Parrot.Sip.Headers.Via{host: "host1", ...}
Adds or updates a parameter in a Via header.
Examples
iex> via = Parrot.Sip.Headers.Via.new("example.com")
iex> Parrot.Sip.Headers.Via.with_parameter(via, "received", "192.0.2.1")
%Parrot.Sip.Headers.Via{parameters: %{"received" => "192.0.2.1"}, ...}