View Source Sippet.Message (Sippet v1.0.16)

Message primitive for composing SIP messages. Build a SIP message with the Sippet.Message struct.

request =
  Sippet.Message.build_request("INVITE", "sip:joe@example.com")
  |> Sippet.Message.put_header(:to,
      {"", Sippet.URI.parse!("sip:joe@example.com"), %{}})
  ...

Summary

Functions

Returns a SIP request created from its basic elements.

Returns a SIP response created from its basic elements.

Returns a SIP response with a custom reason phrase.

Creates an unique local branch (72-bit random string, 7+12 characters long).

Creates an unique Call-ID (120-bit random string, 20 characters long).

Creates a local tag (48-bit random string, 8 characters long).

Deletes all header values in message.

Deletes the last value of header in message.

Deletes the first value of header in message.

Drops all given headers from message.

Fetches the value for a specific key in the given message.

Fetches all values for a specific header and returns it in a tuple.

Fetches all values for a specific header in the given message, erroring out if message doesn't contain header.

Fetches the last value of a specific header and returns it in a tuple.

Fetches the last value of a specific header in the given message, erroring out if message doesn't contain header.

Fetches the first value of a specific header and returns it in a tuple.

Fetches the first value of a specific header in the given message, erroring out if message doesn't contain header.

Gets the value from key and updates it, all in one pass.

Gets the values from header and updates it, all in one pass.

Gets the last value from header and updates it, all in one pass.

Gets the first value from header and updates it, all in one pass.

Gets all values for a specific header in message.

Gets the last value of a specific header in message.

Gets the first value of a specific header in message.

Extracts the remote address and port from an incoming request inspecting the Via header. If ;rport is present, use it instead of the topmost Via port, if ;received is present, use it instead of the topmost Via host.

Returns whether a given header exists in the given message.

Returns a list of all known methods, as a list of uppercase strings.

Returns a list of all known transport protocols, as a list of uppercase strings.

Returns the RFC 3261 compliance magic cookie, inserted in via-branch parameters.

Parses a SIP message header block as received by the transport layer.

Parses a SIP message header block as received by the transport layer.

Returns and removes the value associated with key in message.

Returns and removes the values associated with header in message.

Returns and removes the last value associated with header in message.

Returns and removes the first value associated with header in message.

Puts the value under header on the message.

Puts the value under header on the message, as last element.

Puts the value under header on the message, as front element.

Puts the value under header on the message unless the header already exists.

Evaluates fun and puts the result under header in message unless header is already present.

Shortcut to check if the message is a request.

Shortcut to check if the message is a response.

Returns the iodata representation of the given Sippet.Message struct.

Converts a string representing a known method into an atom, otherwise as an uppercase string.

Converts a string representing a known protocol into an atom, otherwise as an uppercase string.

Returns a response created from a request, using a given status code.

Returns a response created from a request, using a given status code and a custom reason phrase.

Returns the string representation of the given Sippet.Message struct.

Updates the header in message with the given function.

Updates the last header value in message with the given function.

Updates the first header value in message with the given function.

Checks whether a message is valid.

Checks whether a message is valid, also checking if it corresponds to the indicated incoming transport tuple {protocol, host, port}.

Validates if a message is valid, returning errors if found.

Validates if a message is valid, also checking if it corresponds to the indicated incoming transport tuple {protocol, host, port}. It returns the error if found.

Types

@type auth_params() :: {scheme :: binary(), params()}
@type header() :: atom() | binary()
@type headers() :: %{
  optional(:accept) => [type_subtype_params(), ...],
  optional(:accept_encoding) => [token_params(), ...],
  optional(:accept_language) => [token_params(), ...],
  optional(:alert_info) => [uri_params(), ...],
  optional(:allow) => [token(), ...],
  optional(:authentication_info) => params(),
  optional(:authorization) => [auth_params(), ...],
  :call_id => token(),
  optional(:call_info) => [uri_params(), ...],
  optional(:contact) => <<_::1>> | [name_uri_params(), ...],
  optional(:content_disposition) => token_params(),
  optional(:content_encoding) => [token(), ...],
  optional(:content_language) => [token(), ...],
  optional(:content_length) => integer(),
  optional(:content_type) => type_subtype_params(),
  :cseq => {integer(), method()},
  optional(:date) => NaiveDateTime.t(),
  optional(:error_info) => [uri_params(), ...],
  optional(:expires) => integer(),
  :from => name_uri_params(),
  optional(:in_reply_to) => [token(), ...],
  :max_forwards => integer(),
  optional(:mime_version) => {major :: integer(), minor :: integer()},
  optional(:min_expires) => integer(),
  optional(:organization) => binary(),
  optional(:priority) => token(),
  optional(:proxy_authenticate) => [auth_params(), ...],
  optional(:proxy_authorization) => [auth_params(), ...],
  optional(:proxy_require) => [token(), ...],
  optional(:reason) => {binary(), params()},
  optional(:record_route) => [name_uri_params(), ...],
  optional(:reply_to) => name_uri_params(),
  optional(:require) => [token(), ...],
  optional(:retry_after) => {integer(), binary(), params()},
  optional(:route) => [name_uri_params(), ...],
  optional(:server) => binary(),
  optional(:subject) => binary(),
  optional(:supported) => [token(), ...],
  optional(:timestamp) => {timestamp :: float(), delay :: float()},
  :to => name_uri_params(),
  optional(:unsupported) => [token(), ...],
  optional(:user_agent) => binary(),
  :via => [via_value(), ...],
  optional(:warning) => [{integer(), agent :: binary(), binary()}, ...],
  optional(:www_authenticate) => [auth_params(), ...],
  optional(binary()) => [binary(), ...]
}
@type method() :: atom() | binary()
@type multiple_value() ::
  token_params()
  | type_subtype_params()
  | uri_params()
  | name_uri_params()
  | via_value()
  | auth_params()
  | params()
  | {code :: integer(), agent :: binary(), text :: binary()}
@type name_uri_params() :: {display_name :: binary(), uri :: Sippet.URI.t(), params()}
@type params() :: %{required(binary()) => binary()}
@type protocol() :: atom() | binary()
@type request() :: %Sippet.Message{
  body: term(),
  headers: term(),
  start_line: Sippet.Message.RequestLine.t(),
  target: term()
}
@type response() :: %Sippet.Message{
  body: term(),
  headers: term(),
  start_line: Sippet.Message.StatusLine.t(),
  target: term()
}
@type single_value() ::
  binary()
  | integer()
  | {sequence :: integer(), method()}
  | {major :: integer(), minor :: integer()}
  | token_params()
  | type_subtype_params()
  | uri_params()
  | name_uri_params()
  | {delta_seconds :: integer(), comment :: binary(), params()}
  | {timestamp :: integer(), delay :: integer()}
  | <<_::1>>
  | [name_uri_params(), ...]
  | NaiveDateTime.t()
@type t() :: %Sippet.Message{
  body: binary() | nil,
  headers: %{required(header()) => value()},
  start_line: Sippet.Message.RequestLine.t() | Sippet.Message.StatusLine.t(),
  target:
    nil | {protocol :: atom() | binary(), host :: binary(), dport :: integer()}
}
@type token() :: binary()
@type token_params() :: {token :: binary(), params()}
@type type_subtype_params() :: {{type :: binary(), subtype :: binary()}, params()}
@type uri() :: Sippet.URI.t()
@type uri_params() :: {display_name :: binary(), uri :: Sippet.URI.t(), params()}
@type value() :: single_value() | [multiple_value()]
@type via_value() ::
  {{major :: integer(), minor :: integer()}, protocol(),
   {host :: binary(), port :: integer()}, params()}

Functions

Link to this function

build_request(method, request_uri)

View Source
@spec build_request(method(), uri() | binary()) :: request()

Returns a SIP request created from its basic elements.

If the method is a binary and is a known method, it will be converted to a lowercase atom; otherwise, it will be stored as an uppercase string. If method is an atom, it will be just kept.

If the request_uri is a binary, it will be parsed as a Sippet.URI struct. Otherwise, if it's already a Sippet.URI, it will be stored unmodified.

The newly created struct has an empty header map, and the body is nil.

Examples:

iex> req1 = Sippet.Message.build_request(:invite, "sip:foo@bar.com")
%Sippet.Message{body: nil, headers: %{},
 start_line: %Sippet.Message.RequestLine{method: :invite,
  request_uri: %Sippet.URI{authority: "foo@bar.com", headers: nil,
   host: "bar.com", parameters: nil, port: 5060, scheme: "sip",
   userinfo: "foo"}, version: {2, 0}}, target: nil}
iex> req2 = Sippet.Message.build_request("INVITE", "sip:foo@bar.com")
iex> request_uri = Sippet.URI.parse!("sip:foo@bar.com")
iex> req3 = Sippet.Message.build_request("INVITE", request_uri)
iex> req1 == req2 and req2 == req3
true
@spec build_response(100..699 | Sippet.Message.StatusLine.t()) ::
  response() | no_return()

Returns a SIP response created from its basic elements.

The status parameter can be a Sippet.Message.StatusLine struct or an integer in the range 100..699 representing the SIP response status code. In the latter case, a default reason phrase will be obtained from a default set; if there's none, then an exception will be raised.

Examples:

iex> resp1 = Sippet.Message.build_response 200
%Sippet.Message{body: nil, headers: %{},
 start_line: %Sippet.Message.StatusLine{reason_phrase: "OK", status_code: 200,
  version: {2, 0}}, target: nil}
iex> status_line = Sippet.Message.StatusLine.new(200)
iex> resp2 = status_line |> Sippet.Message.build_response
iex> resp1 == resp2
true
Link to this function

build_response(status_code, reason_phrase)

View Source
@spec build_response(100..699, String.t()) :: response()

Returns a SIP response with a custom reason phrase.

The status_code should be an integer in the range 100..699 representing the SIP status code, and reason_phrase a binary representing the reason phrase text.

iex> Sippet.Message.build_response 400, "Bad Lorem Ipsum"
%Sippet.Message{body: nil, headers: %{},
 start_line: %Sippet.Message.StatusLine{reason_phrase: "Bad Lorem Ipsum",
  status_code: 400, version: {2, 0}}, target: nil}
@spec create_branch() :: binary()

Creates an unique local branch (72-bit random string, 7+12 characters long).

Example:

Sippet.Message.create_branch
"z9hG4bKuQpiub9h7fBb"
@spec create_call_id() :: binary()

Creates an unique Call-ID (120-bit random string, 20 characters long).

Example

Sippet.create_call_id
"NlV4TfQwkmPlNJkyHPpF"
@spec create_tag() :: binary()

Creates a local tag (48-bit random string, 8 characters long).

Example:

Sippet.Message.create_tag
"lnTMo9Zn"
Link to this function

delete_header(message, header)

View Source
@spec delete_header(t(), header()) :: t()

Deletes all header values in message.

Examples:

iex> request =
...>   Sippet.Message.build_request(:invite, "sip:foo@bar.com")
...>   |> Sippet.Message.put_header(:content_language, ["en-US", "de-DE"])
...>   |> Sippet.Message.put_header(:max_forwards, 70)
iex> request |> Sippet.Message.delete_header(:content_language)
%Sippet.Message{body: nil, headers: %{max_forwards: 70},
 start_line: %Sippet.Message.RequestLine{method: :invite,
  request_uri: %Sippet.URI{authority: "foo@bar.com", headers: nil,
   host: "bar.com", parameters: nil, port: 5060, scheme: "sip",
   userinfo: "foo"}, version: {2, 0}}, target: nil}
Link to this function

delete_header_back(message, header)

View Source
@spec delete_header_back(t(), header()) :: t()

Deletes the last value of header in message.

Examples:

iex> request =
...>   Sippet.Message.build_request(:invite, "sip:foo@bar.com")
...>   |> Sippet.Message.put_header(:content_language, ["en-US", "de-DE"])
...>   |> Sippet.Message.put_header(:max_forwards, 70)
iex> request |> Sippet.Message.delete_header_back(:content_language)
%Sippet.Message{body: nil,
 headers: %{content_language: ["en-US"], max_forwards: 70},
 start_line: %Sippet.Message.RequestLine{method: :invite,
  request_uri: %Sippet.URI{authority: "foo@bar.com", headers: nil,
   host: "bar.com", parameters: nil, port: 5060, scheme: "sip",
   userinfo: "foo"}, version: {2, 0}}, target: nil}
Link to this function

delete_header_front(message, header)

View Source
@spec delete_header_front(t(), header()) :: t()

Deletes the first value of header in message.

Examples:

iex> request =
...>   Sippet.Message.build_request(:invite, "sip:foo@bar.com")
...>   |> Sippet.Message.put_header(:content_language, ["en-US", "de-DE"])
...>   |> Sippet.Message.put_header(:max_forwards, 70)
iex> request |> Sippet.Message.delete_header_front(:content_language)
%Sippet.Message{body: nil,
 headers: %{content_language: ["de-DE"], max_forwards: 70},
 start_line: %Sippet.Message.RequestLine{method: :invite,
  request_uri: %Sippet.URI{authority: "foo@bar.com", headers: nil,
   host: "bar.com", parameters: nil, port: 5060, scheme: "sip",
   userinfo: "foo"}, version: {2, 0}}, target: nil}
Link to this function

drop_headers(message, headers)

View Source
@spec drop_headers(t(), [header()]) :: t()

Drops all given headers from message.

Examples:

iex> request =
...>   Sippet.Message.build_request(:invite, "sip:foo@bar.com")
...>   |> Sippet.Message.put_header(:content_language, ["en-US", "de-DE"])
...>   |> Sippet.Message.put_header(:max_forwards, 70)
iex> request |> Sippet.Message.drop_headers([:content_language, :max_forwards])
%Sippet.Message{body: nil, headers: %{},
 start_line: %Sippet.Message.RequestLine{method: :invite,
  request_uri: %Sippet.URI{authority: "foo@bar.com", headers: nil,
   host: "bar.com", parameters: nil, port: 5060, scheme: "sip",
   userinfo: "foo"}, version: {2, 0}}, target: nil}

Fetches the value for a specific key in the given message.

Link to this function

fetch_header(message, header)

View Source
@spec fetch_header(t(), header()) :: {:ok, value()} | :error

Fetches all values for a specific header and returns it in a tuple.

If the header does not exist, returns :error.

Examples:

iex> request =
...>   Sippet.Message.build_request(:invite, "sip:foo@bar.com")
...>   |> Sippet.Message.put_header(:content_language, ["en-US", "de-DE"])
...>   |> Sippet.Message.put_header(:max_forwards, 70)
iex> request |> Sippet.Message.fetch_header(:content_language)
{:ok, ["en-US", "de-DE"]}
iex> request |> Sippet.Message.fetch_header(:cseq)
:error
Link to this function

fetch_header!(message, header)

View Source
@spec fetch_header!(t(), header()) :: value() | no_return()

Fetches all values for a specific header in the given message, erroring out if message doesn't contain header.

If message contains the given header, all corresponding values are returned in a list. If message doesn't contain the header, a KeyError exception is raised.

Link to this function

fetch_header_back(message, header)

View Source
@spec fetch_header_back(t(), header()) :: {:ok, multiple_value()} | :error

Fetches the last value of a specific header and returns it in a tuple.

If the header does not exist, or the value is not a list, returns :error. If the header exists but it is an empty list, returns {:ok, nil}.

Examples:

iex> request =
...>   Sippet.Message.build_request(:invite, "sip:foo@bar.com")
...>   |> Sippet.Message.put_header(:content_language, ["en-US", "de-DE"])
...>   |> Sippet.Message.put_header(:max_forwards, 70)
iex> request |> Sippet.Message.fetch_header_back(:content_language)
{:ok, "de-DE"}
iex> request |> Sippet.Message.fetch_header_back(:max_forwards)
:error
iex> request |> Sippet.Message.fetch_header_back(:cseq)
:error
Link to this function

fetch_header_back!(message, header)

View Source
@spec fetch_header_back!(t(), header()) :: multiple_value() | no_return()

Fetches the last value of a specific header in the given message, erroring out if message doesn't contain header.

If message contains the given header, the last value is returned, which may be nil case the values list is empty. If message doesn't contain the header, a KeyError exception is raised.

Link to this function

fetch_header_front(message, header)

View Source
@spec fetch_header_front(t(), header()) :: {:ok, multiple_value()} | :error

Fetches the first value of a specific header and returns it in a tuple.

If the header does not exist, or the value is not a list, returns :error. If the header exists but it is an empty list, returns {:ok, nil}.

Examples:

iex> request =
...>   Sippet.Message.build_request(:invite, "sip:foo@bar.com")
...>   |> Sippet.Message.put_header(:content_language, ["en-US", "de-DE"])
...>   |> Sippet.Message.put_header(:max_forwards, 70)
iex> request |> Sippet.Message.fetch_header_front(:content_language)
{:ok, "en-US"}
iex> request |> Sippet.Message.fetch_header_front(:max_forwards)
:error
iex> request |> Sippet.Message.fetch_header_front(:cseq)
:error
Link to this function

fetch_header_front!(message, header)

View Source
@spec fetch_header_front!(t(), header()) :: multiple_value() | no_return()

Fetches the first value of a specific header in the given message, erroring out if message doesn't contain header.

If message contains the given header, the first value is returned, which may be nil case the values list is empty. If message doesn't contain the header, a KeyError exception is raised.

Link to this function

get_and_update(message, key, fun)

View Source

Gets the value from key and updates it, all in one pass.

About the same as Map.get_and_update/3 except that this function actually does not remove the key from the struct case the passed function returns :pop; it puts nil for :start_line, :body and :target ands %{} for the :headers key.

Link to this function

get_and_update_header(message, header, fun)

View Source
@spec get_and_update_header(t(), header(), (value() -> {get, value()} | :pop)) ::
  {get, t()}
when get: value()

Gets the values from header and updates it, all in one pass.

fun is called with the current values under header in message (or nil if key is not present in message) and must return a two-element tuple: the "get" value (the retrieved values, which can be operated on before being returned) and the new values to be stored under header in the resulting new message. fun may also return :pop, which means all current values shall be removed from message and returned (making this function behave like Sippet.Message.pop_header(message, header). The returned value is a tuple with the "get" value returned by fun and a new message with the updated values under header.

Link to this function

get_and_update_header_back(message, header, fun)

View Source
@spec get_and_update_header_back(
  t(),
  header(),
  (multiple_value() -> {get, multiple_value()} | :pop)
) ::
  {get, t()}
when get: multiple_value()

Gets the last value from header and updates it, all in one pass.

fun is called with the current last value under header in message (or nil if key is not present in message) and must return a two-element tuple: the "get" value (the retrieved value, which can be operated on before being returned) and the new value to be stored under header in the resulting new message. fun may also return :pop, which means the current value shall be removed from message and returned (making this function behave like Sippet.Message.pop_header_back(message, header). The returned value is a tuple with the "get" value returned by fun and a new message with the updated values under header.

Link to this function

get_and_update_header_front(message, header, fun)

View Source
@spec get_and_update_header_front(
  t(),
  header(),
  (multiple_value() -> {get, multiple_value()} | :pop)
) ::
  {get, t()}
when get: multiple_value()

Gets the first value from header and updates it, all in one pass.

fun is called with the current first value under header in message (or nil if key is not present in message) and must return a two-element tuple: the "get" value (the retrieved value, which can be operated on before being returned) and the new value to be stored under header in the resulting new message. fun may also return :pop, which means the current value shall be removed from message and returned (making this function behave like Sippet.Message.pop_header_front(message, header). The returned value is a tuple with the "get" value returned by fun and a new message with the updated values under header.

Link to this function

get_header(message, header, default \\ nil)

View Source
@spec get_header(t(), header(), any()) :: value() | any()

Gets all values for a specific header in message.

If header is present in message, then all values are returned in a list. Otherwise, default is returned (which is nil unless specified otherwise).

Link to this function

get_header_back(message, header, default \\ nil)

View Source
@spec get_header_back(t(), header(), any()) :: multiple_value() | any()

Gets the last value of a specific header in message.

If header is present in message, then the last value is returned. Otherwise, default is returned (which is nil unless specified otherwise).

Link to this function

get_header_front(message, header, default \\ nil)

View Source
@spec get_header_front(t(), header(), any()) :: multiple_value() | any()

Gets the first value of a specific header in message.

If header is present in message, then the first value is returned. Otherwise, default is returned (which is nil unless specified otherwise).

@spec get_remote(request()) ::
  {:ok, {protocol :: atom() | binary(), host :: binary(), port :: integer()}}
  | {:error, reason :: term()}

Extracts the remote address and port from an incoming request inspecting the Via header. If ;rport is present, use it instead of the topmost Via port, if ;received is present, use it instead of the topmost Via host.

Link to this function

has_header?(message, header)

View Source
@spec has_header?(t(), header()) :: boolean()

Returns whether a given header exists in the given message.

Examples:

iex> request =
...>   Sippet.Message.build_request(:invite, "sip:foo@bar.com")
...>   |> Sippet.Message.put_header(:cseq, {1, :invite})
iex> request |> Sippet.Message.has_header?(:cseq)
true
@spec known_methods() :: [String.t()]

Returns a list of all known methods, as a list of uppercase strings.

Example:

iex> Sippet.Message.known_methods()
["ACK", "BYE", "CANCEL", "INFO", "INVITE", "MESSAGE", "NOTIFY", "OPTIONS",
 "PRACK", "PUBLISH", "PULL", "PUSH", "REFER", "REGISTER", "STORE", "SUBSCRIBE",
 "UPDATE"]
@spec known_protocols() :: [String.t()]

Returns a list of all known transport protocols, as a list of uppercase strings.

Example:

iex> Sippet.Message.known_protocols()
["AMQP", "DCCP", "DTLS", "SCTP", "STOMP", "TCP", "TLS", "UDP", "WS", "WSS"]
@spec magic_cookie() :: binary()

Returns the RFC 3261 compliance magic cookie, inserted in via-branch parameters.

Example:

iex> Sippet.Message.magic_cookie
"z9hG4bK"
@spec parse(iodata()) :: {:ok, t()} | {:error, atom()}

Parses a SIP message header block as received by the transport layer.

In order to correctly set the message body, you have to verify the :content_length header; if it exists, it reflects the body size and you have to set it manually on the returned message.

@spec parse!(String.t() | charlist()) :: t() | no_return()

Parses a SIP message header block as received by the transport layer.

Raises if the string is an invalid SIP header.

In order to correctly set the message body, you have to verify the :content_length header; if it exists, it reflects the body size and you have to set it manually on the returned message.

Link to this function

pop(message, key, default \\ nil)

View Source

Returns and removes the value associated with key in message.

About the same as Map.pop/3 except that this function actually does not remove the key from the struct case the passed function returns :pop; it puts nil for :start_line, :body and :target ands %{} for the :headers key.

Link to this function

pop_header(message, header, default \\ nil)

View Source
@spec pop_header(t(), header(), any()) :: {value() | any(), t()}

Returns and removes the values associated with header in message.

If header is present in message with values [value], {[value], new_message} is returned where new_message is the result of removing header from message. If header is not present in message, {default, message} is returned.

Link to this function

pop_header_back(message, header, default \\ nil)

View Source
@spec pop_header_back(t(), header(), any()) :: {multiple_value() | any(), t()}

Returns and removes the last value associated with header in message.

If header is present in message with values values, {List.last(values), new_message} is returned where new_message is the result of removing List.last(values) from header. If header is not present in message or it is an empty list, {default, message} is returned. When the header results in an empty list, message gets updated by removing the header.

Link to this function

pop_header_front(message, header, default \\ nil)

View Source
@spec pop_header_front(t(), header(), any()) :: {multiple_value() | any(), t()}

Returns and removes the first value associated with header in message.

If header is present in message with values values, {List.first(values), new_message} is returned where new_message is the result of removing List.first(values) from header. If header is not present in message or it is an empty list, {default, message} is returned. When the header results in an empty list, message gets updated by removing the header.

Link to this function

put_header(message, header, value)

View Source
@spec put_header(t(), header(), value()) :: t()

Puts the value under header on the message.

If the header already exists, it will be overridden.

Examples:

iex> request = Sippet.Message.build_request(:invite, "sip:foo@bar.com")
iex> request |> Sippet.Message.put_header(:cseq, {1, :invite})
%Sippet.Message{body: nil, headers: %{cseq: {1, :invite}},
 start_line: %Sippet.Message.RequestLine{method: :invite,
  request_uri: %Sippet.URI{authority: "foo@bar.com", headers: nil,
   host: "bar.com", parameters: nil, port: 5060, scheme: "sip",
   userinfo: "foo"}, version: {2, 0}}, target: nil}
Link to this function

put_header_back(message, header, value)

View Source
@spec put_header_back(t(), header(), multiple_value()) :: t()

Puts the value under header on the message, as last element.

If the parameter value is nil, then the empty list will be appended to the header.

Examples:

iex> Sippet.Message.build_request(:invite, "sip:foo@bar.com")
...> |> Sippet.Message.put_header_back(:content_language, "en-US")
...> |> Sippet.Message.put_header_back(:content_language, "de-DE")
%Sippet.Message{body: nil, headers: %{content_language: ["en-US", "de-DE"]},
 start_line: %Sippet.Message.RequestLine{method: :invite,
  request_uri: %Sippet.URI{authority: "foo@bar.com", headers: nil,
   host: "bar.com", parameters: nil, port: 5060, scheme: "sip",
   userinfo: "foo"}, version: {2, 0}}, target: nil}
Link to this function

put_header_front(message, header, value)

View Source
@spec put_header_front(t(), header(), multiple_value()) :: t()

Puts the value under header on the message, as front element.

If the parameter value is nil, then the empty list will be prefixed to the header.

Examples:

iex> Sippet.Message.build_request(:invite, "sip:foo@bar.com")
...> |> Sippet.Message.put_header_front(:content_language, "de-DE")
...> |> Sippet.Message.put_header_front(:content_language, "en-US")
%Sippet.Message{body: nil, headers: %{content_language: ["en-US", "de-DE"]},
 start_line: %Sippet.Message.RequestLine{method: :invite,
  request_uri: %Sippet.URI{authority: "foo@bar.com", headers: nil,
   host: "bar.com", parameters: nil, port: 5060, scheme: "sip",
   userinfo: "foo"}, version: {2, 0}}, target: nil}
Link to this function

put_new_header(message, header, value)

View Source
@spec put_new_header(t(), header(), value()) :: t()

Puts the value under header on the message unless the header already exists.

Examples:

iex> Sippet.Message.build_request(:invite, "sip:foo@bar.com")
...> |> Sippet.Message.put_new_header(:max_forwards, 70)
...> |> Sippet.Message.put_new_header(:max_forwards, 1)
%Sippet.Message{body: nil, headers: %{max_forwards: 70},
 start_line: %Sippet.Message.RequestLine{method: :invite,
  request_uri: %Sippet.URI{authority: "foo@bar.com", headers: nil,
   host: "bar.com", parameters: nil, port: 5060, scheme: "sip",
   userinfo: "foo"}, version: {2, 0}}, target: nil}
Link to this function

put_new_lazy_header(message, header, fun)

View Source
@spec put_new_lazy_header(t(), header(), (-> value())) :: t()

Evaluates fun and puts the result under header in message unless header is already present.

This function is useful in case you want to compute the value to put under header only if header is not already present (e.g., the value is expensive to calculate or generally difficult to setup and teardown again).

Examples:

iex> Sippet.Message.build_request(:invite, "sip:foo@bar.com")
...> |> Sippet.Message.put_new_lazy_header(:max_forwards, fn -> 70 end)
...> |> Sippet.Message.put_new_lazy_header(:max_forwards, fn -> 1 end)
%Sippet.Message{body: nil, headers: %{max_forwards: 70},
 start_line: %Sippet.Message.RequestLine{method: :invite,
  request_uri: %Sippet.URI{authority: "foo@bar.com", headers: nil,
   host: "bar.com", parameters: nil, port: 5060, scheme: "sip",
   userinfo: "foo"}, version: {2, 0}}, target: nil}
@spec request?(t()) :: boolean()

Shortcut to check if the message is a request.

Examples:

iex> req = Sippet.Message.build_request :invite, "sip:foo@bar.com"
iex> req |> Sippet.Message.request?
true
@spec response?(t()) :: boolean()

Shortcut to check if the message is a response.

Examples:

iex> resp = Sippet.Message.build_response 200
iex> resp |> Sippet.Message.response?
true
@spec to_iodata(t()) :: iodata()

Returns the iodata representation of the given Sippet.Message struct.

@spec to_method(String.t()) :: method()

Converts a string representing a known method into an atom, otherwise as an uppercase string.

Example:

iex> Sippet.Message.to_method("INVITE")
:invite

iex> Sippet.Message.to_method("InViTe")
:invite

iex> Sippet.Message.to_method("aaa")
"AAA"
@spec to_protocol(String.t()) :: protocol()

Converts a string representing a known protocol into an atom, otherwise as an uppercase string.

Example:

iex> Sippet.Message.to_protocol("UDP")
:udp

iex> Sippet.Message.to_protocol("uDp")
:udp

iex> Sippet.Message.to_protocol("aaa")
"AAA"
Link to this function

to_response(request, status)

View Source
@spec to_response(request(), integer() | Sippet.Message.StatusLine.t()) ::
  response() | no_return()

Returns a response created from a request, using a given status code.

The request should be a valid SIP request, or an exception will be thrown.

The status parameter can be a Sippet.Message.StatusLine struct or an integer in the range 100..699 representing the SIP response status code. In the latter case, a default reason phrase will be obtained from a default set; if there's none, then an exception will be raised.

Example:

request =
  """
  REGISTER sips:ss2.biloxi.example.com SIP/2.0
  Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashds7
  Max-Forwards: 70
  From: Bob <sips:bob@biloxi.example.com>;tag=a73kszlfl
  To: Bob <sips:bob@biloxi.example.com>
  Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
  CSeq: 1 REGISTER
  Contact: <sips:bob@client.biloxi.example.com>
  Content-Length: 0
  """ |> Sippet.Message.parse!()
request |> Sippet.Message.to_response(200) |> IO.puts
SIP/2.0 200 OK
Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashds7
To: "Bob" <sips:bob@biloxi.example.com>;tag=K2fizKkV
From: "Bob" <sips:bob@biloxi.example.com>;tag=a73kszlfl
CSeq: 1 REGISTER
Content-Length: 0
Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com


:ok
Link to this function

to_response(request, status_code, reason_phrase)

View Source
@spec to_response(request(), integer(), String.t()) :: response()

Returns a response created from a request, using a given status code and a custom reason phrase.

The request should be a valid SIP request, or an exception will be thrown.

The status_code parameter should be an integer in the range 100..699 representing the SIP response status code. A default reason phrase will be obtained from a default set; if there's none, then an exception will be raised.

The reason_phrase can be any textual representation of the reason phrase the application needs to generate, in binary.

Example:

request =
  """
  REGISTER sips:ss2.biloxi.example.com SIP/2.0
  Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashds7
  Max-Forwards: 70
  From: Bob <sips:bob@biloxi.example.com>;tag=a73kszlfl
  To: Bob <sips:bob@biloxi.example.com>
  Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
  CSeq: 1 REGISTER
  Contact: <sips:bob@client.biloxi.example.com>
  Content-Length: 0
  """ |> Sippet.Message.parse!()
request |> Sippet.Message.to_response(400, "Bad Lorem Ipsum") |> IO.puts
SIP/2.0 400 Bad Lorem Ipsum
Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashds7
To: "Bob" <sips:bob@biloxi.example.com>;tag=K2fizKkV
From: "Bob" <sips:bob@biloxi.example.com>;tag=a73kszlfl
CSeq: 1 REGISTER
Content-Length: 0
Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com


:ok
@spec to_string(t()) :: binary()

Returns the string representation of the given Sippet.Message struct.

Link to this function

update_header(message, header, initial \\ nil, fun)

View Source
@spec update_header(t(), header(), value() | nil, (value() -> value())) :: t()

Updates the header in message with the given function.

If header is present in message with value value, fun is invoked with argument value and its result is used as the new value of header. If header is not present in message, initial is inserted as the value of header.

Link to this function

update_header_back(message, header, initial \\ nil, fun)

View Source
@spec update_header_back(
  t(),
  header(),
  value() | nil,
  (multiple_value() -> multiple_value())
) :: t()

Updates the last header value in message with the given function.

If header is present in message with value [value], fun is invoked with for last element of [value] and its result is used as the new value of header back. If header is not present in message, or it is an empty list, initial is inserted as the single value of header.

Link to this function

update_header_front(message, header, initial \\ nil, fun)

View Source
@spec update_header_front(
  t(),
  header(),
  value() | nil,
  (multiple_value() -> multiple_value())
) :: t()

Updates the first header value in message with the given function.

If header is present in message with value [value], fun is invoked with for first element of [value] and its result is used as the new value of header front. If header is not present in message, or it is an empty list, initial is inserted as the single value of header.

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

Checks whether a message is valid.

@spec valid?(t(), {protocol(), host :: String.t(), port :: integer()}) :: boolean()

Checks whether a message is valid, also checking if it corresponds to the indicated incoming transport tuple {protocol, host, port}.

@spec validate(t()) :: :ok | {:error, reason :: term()}

Validates if a message is valid, returning errors if found.

@spec validate(t(), {protocol(), host :: String.t(), port :: integer()}) ::
  :ok | {:error, reason :: term()}

Validates if a message is valid, also checking if it corresponds to the indicated incoming transport tuple {protocol, host, port}. It returns the error if found.