Packages
sippet
0.2.1
1.0.16
1.0.15
1.0.14
1.0.13
1.0.12
1.0.11
1.0.10
1.0.9
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
An Elixir Session Initiation Protocol (SIP) stack.
Current section
Files
Jump to
Current section
Files
lib/sippet/transports.ex
defmodule Sippet.Transports do
@moduledoc """
The `Sippet.Transports` is responsible for the actual transmission of requests
and responses over network transports.
Network transport protocols are implemented following the
`Sippet.Transports.Plug` behavior, and they are configured as:
config :sippet, Sippet.Transports,
udp: Sippet.Transports.UDP.Plug
Whenever a message is received by a plug, the `Sippet.Transports.Queue` is
used to process, validate and route it through the transaction layer or core.
"""
import Supervisor.Spec
alias Sippet.Message, as: Message
alias Sippet.Message.RequestLine, as: RequestLine
alias Sippet.Message.StatusLine, as: StatusLine
alias Sippet.Transports.Pool, as: Pool
alias Sippet.URI, as: URI
@doc """
Starts the transport process hierarchy.
"""
@spec start_link() :: Supervisor.on_start
def start_link() do
children = [
Pool.spec() |
plugs_specs()
]
options = [
strategy: :one_for_one,
name: __MODULE__
]
Supervisor.start_link(children, options)
end
defp plugs_specs() do
Application.get_env(:sippet, __MODULE__, [])
|> plugs_specs([])
end
defp plugs_specs([], result), do: result
defp plugs_specs([{_protocol, module} | rest], result),
do: plugs_specs(rest, [worker(module, []) | result])
@doc """
Sends a message to the network.
If specified, the `transaction` will receive the transport error if occurs.
See `Sippet.Transactions.receive_error/2`.
This function may block the caller temporarily due to resource constraints.
"""
@spec send_message(Message.t, GenServer.server | nil) :: :ok
def send_message(message, transaction \\ nil) do
{protocol, host, port} = get_destination(message)
plug = protocol |> to_plug()
apply(plug, :send_message, [message, host, port, transaction])
end
defp get_destination(%Message{target: target}) when is_tuple(target) do
target
end
defp get_destination(%Message{start_line: %StatusLine{},
headers: %{via: via}} = message) do
{_version, protocol, {host, port}, params} = hd(via)
{host, port} =
if Message.response?(message) do
host =
case params do
%{"received" => received} -> received
_otherwise -> host
end
port =
case params do
%{"rport" => rport} -> Integer.parse(rport)
_otherwise -> port
end
{host, port}
else
{host, port}
end
{protocol, host, port}
end
defp get_destination(%Message{start_line:
%RequestLine{request_uri: uri}} = request) do
host = uri.host
port = uri.port
params = URI.decode_parameters(uri.parameters)
protocol =
if params |> Map.has_key?("transport") do
case String.downcase(params["transport"]) do
"dccp" -> :dccp
"dtls" -> :dtls
"sctp" -> :sctp
"stomp" -> :stomp
"tcp" -> :tcp
"tls" -> :tls
"udp" -> :udp
"ws" -> :ws
"wss" -> :wss
other -> other
end
else
{_version, protocol, _sent_by, _params} =
hd(request.headers.via)
protocol
end
{protocol, host, port}
end
defp to_plug(protocol) do
Application.get_env(:sippet, Sippet.Transports)
|> Keyword.fetch!(protocol)
end
@doc """
Verifies if the transport protocol used to send the given message is
reliable.
"""
@spec reliable?(Message.t) :: boolean
def reliable?(%Message{headers: %{via: via}}) do
{_version, protocol, _host_and_port, _params} = hd(via)
plug = protocol |> to_plug()
apply(plug, :reliable?, [])
end
end