Packages
sippet
0.4.7
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/transactions/server/invite.ex
defmodule Sippet.Transactions.Server.Invite do
@moduledoc false
use Sippet.Transactions.Server, initial_state: :proceeding
alias Sippet.Message, as: Message
alias Sippet.Message.StatusLine, as: StatusLine
alias Sippet.Transactions.Server.State, as: State
@t2 4000
@before_trying 200
@timer_g 500
@timer_h 64 * @timer_g
@timer_i 5000 # timer I is 5s
def init(%State{key: key} = data) do
# add an alias for incoming ACK requests for status codes != 200
%{key | method: :ack}
|> Sippet.Transactions.Registry.register_alias()
super(data)
end
defp retry({past_wait, passed_time},
%State{extras: %{last_response: last_response}} = data) do
send_response(last_response, data)
new_delay = min(past_wait * 2, @t2)
{:keep_state_and_data, [{:state_timeout, new_delay,
{new_delay, passed_time + new_delay}}]}
end
def proceeding(:enter, _old_state, %State{request: request} = data) do
receive_request(request, data)
{:keep_state_and_data, [{:state_timeout, @before_trying, :still_trying}]}
end
def proceeding(:state_timeout, :still_trying,
%State{request: request} = data) do
response = request |> Message.to_response(100)
data = send_response(response, data)
{:keep_state, data}
end
def proceeding(:cast, {:incoming_request, _request},
%State{extras: %{last_response: last_response}} = data) do
send_response(last_response, data)
:keep_state_and_data
end
def proceeding(:cast, {:incoming_request, _request}, _data),
do: :keep_state_and_data
def proceeding(:cast, {:outgoing_response, response}, data) do
data = send_response(response, data)
case StatusLine.status_code_class(response.start_line) do
1 -> {:keep_state, data}
2 -> {:stop, :normal, data}
_ -> {:next_state, :completed, data}
end
end
def proceeding(:cast, {:error, reason}, data),
do: shutdown(reason, data)
def proceeding(event_type, event_content, data),
do: unhandled_event(event_type, event_content, data)
def completed(:enter, _old_state, %State{request: request}) do
actions =
if reliable?(request) do
[{:state_timeout, @timer_h, {@timer_h, @timer_h}}]
else
[{:state_timeout, @timer_g, {@timer_g, @timer_g}}]
end
{:keep_state_and_data, actions}
end
def completed(:state_timeout, time_event, data) do
{_past_wait, passed_time} = time_event
if passed_time >= @timer_h do
timeout(data)
else
retry(time_event, data)
end
end
def completed(:cast, {:incoming_request, request},
%State{extras: %{last_response: last_response}} = data) do
case request.start_line.method do
:invite ->
send_response(last_response, data)
:keep_state_and_data
:ack ->
{:next_state, :confirmed, data}
_otherwise ->
shutdown(:invalid_method, data)
end
end
def completed(:cast, {:error, reason}, data),
do: shutdown(reason, data)
def completed(event_type, event_content, data),
do: unhandled_event(event_type, event_content, data)
def confirmed(:enter, _old_state, %State{request: request} = data) do
if reliable?(request) do
{:stop, :normal, data}
else
{:keep_state_and_data, [{:state_timeout, @timer_i, nil}]}
end
end
def confirmed(:state_timeout, _nil, data),
do: {:stop, :normal, data}
def confirmed(:cast, {:incoming_request, _request}, _data),
do: :keep_state_and_data
def confirmed(:cast, {:error, _reason}, _data),
do: :keep_state_and_data
def confirmed(event_type, event_content, data),
do: unhandled_event(event_type, event_content, data)
end