Packages

Elixir libraries and OTP behaviours for building telecom applications with SIP protocol and media handling

Current section

Files

Jump to
parrot_platform lib parrot sip headers supported.ex
Raw

lib/parrot/sip/headers/supported.ex

defmodule Parrot.Sip.Headers.Supported do
@moduledoc """
Module for working with SIP Supported headers as defined in RFC 3261 Section 20.37.
The Supported header field enumerates all the extensions supported
by the User Agent Client (UAC) or User Agent Server (UAS). The Supported
header field contains a list of option tags, described in Section 19.2 of RFC 3261.
The Supported header plays a key role in SIP capability negotiation:
- Declaring optional extensions that the UA understands
- Enabling feature negotiation between endpoints
- Working with Require and Proxy-Require headers for mandatory features
- Facilitating backward compatibility and protocol extensibility
Common option tags include:
- 100rel: Reliable provisional responses (RFC 3262)
- timer: Session timers (RFC 4028)
- replaces: Call transfer (RFC 3891)
- path: Path extension for registrations (RFC 3327)
- gruu: Globally Routable User Agent URIs (RFC 5627)
References:
- RFC 3261 Section 19.2: Option Tags
- RFC 3261 Section 20.32: Require Header Field
- RFC 3261 Section 20.37: Supported Header Field
- RFC 3261 Section 20.40: Unsupported Header Field
- IANA SIP Option Tags Registry
"""
@doc """
Creates a new Supported header with the specified options.
## Examples
iex> Parrot.Sip.Headers.Supported.new(["path", "100rel"])
["path", "100rel"]
"""
@spec new([String.t()]) :: [String.t()]
def new(options) when is_list(options), do: options
@doc """
Parses a Supported header string into a list of option tags.
## Examples
iex> Parrot.Sip.Headers.Supported.parse("path, 100rel")
["path", "100rel"]
iex> Parrot.Sip.Headers.Supported.parse("")
[]
"""
@spec parse(String.t()) :: [String.t()]
def parse(""), do: []
def parse(string) when is_binary(string) do
string
|> String.split(",")
|> Enum.map(&String.trim/1)
|> Enum.filter(&(&1 != ""))
end
@doc """
Formats a list of Supported options as a string.
## Examples
iex> Parrot.Sip.Headers.Supported.format(["path", "100rel"])
"path, 100rel"
iex> Parrot.Sip.Headers.Supported.format([])
""
"""
@spec format([String.t()]) :: String.t()
def format([]), do: ""
def format(options) when is_list(options) do
Enum.join(options, ", ")
end
@doc """
Adds an option to the Supported header.
## Examples
iex> Parrot.Sip.Headers.Supported.add(["path"], "100rel")
["path", "100rel"]
iex> Parrot.Sip.Headers.Supported.add(["path", "100rel"], "path")
["path", "100rel"]
"""
@spec add([String.t()], String.t()) :: [String.t()]
def add(options, option) when is_list(options) and is_binary(option) do
if option in options do
options
else
options ++ [option]
end
end
@doc """
Removes an option from the Supported header.
## Examples
iex> Parrot.Sip.Headers.Supported.remove(["path", "100rel"], "path")
["100rel"]
iex> Parrot.Sip.Headers.Supported.remove(["path"], "100rel")
["path"]
"""
@spec remove([String.t()], String.t()) :: [String.t()]
def remove(options, option) when is_list(options) and is_binary(option) do
Enum.filter(options, &(&1 != option))
end
@doc """
Checks if a specific option is supported.
## Examples
iex> Parrot.Sip.Headers.Supported.supports?(["path", "100rel"], "path")
true
iex> Parrot.Sip.Headers.Supported.supports?(["path"], "100rel")
false
"""
@spec supports?([String.t()], String.t()) :: boolean()
def supports?(options, option) when is_list(options) and is_binary(option) do
option in options
end
end