Packages
smppex
0.0.3
3.3.0
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
retired
3.1.0
retired
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
2.4.0
2.3.3
2.3.2
2.3.1
2.3.0
2.2.9
2.2.8
2.2.7
2.2.6
2.2.5
2.2.4
2.2.3
2.2.2
2.2.1
2.2.0
2.1.0
2.0.1
2.0.0
1.0.1
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.12
0.1.11
0.1.10
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
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
SMPP 3.4 protocol and framework implemented in Elixir
Current section
Files
Jump to
Current section
Files
lib/smppex/esme/sync.ex
defmodule SMPPEX.ESME.Sync do
use SMPPEX.ESME
alias SMPPEX.ESME
alias SMPPEX.Pdu
require Logger
@default_timeout 5000
# Public interface
def start_link(host, port, opts \\ []) do
ESME.start_link(host, port, {__MODULE__, %{from: nil, pdu: nil, additional_pdus: [], state: :free}}, opts)
end
@spec request(esme :: pid, pdu :: Pdu.t, timeout :: non_neg_integer) :: {:ok, resp :: Pdu.t} | :timeout | :stop | {:error, reason :: term}
def request(esme, pdu, timeout \\ @default_timeout) do
try do
ESME.call(esme, {:request, pdu}, timeout)
catch
:exit, {:timeout, _} -> :timeout
end
end
@type awaited :: {:pdu, Pdu.t} | {:resp, Pdu.t} | {:timeout, Pdu.t} | {:error, Pdu.t, reason :: any}
@spec wait_for_pdus(esme :: pid, timeout :: non_neg_integer) :: [awaited] | :timeout | :stop
def wait_for_pdus(esme, timeout \\ @default_timeout) do
try do
ESME.call(esme, :wait_for_pdus, timeout)
catch
:exit, {:timeout, _} -> :timeout
end
end
def pdus(esme, timeout \\ @default_timeout) do
ESME.call(esme, :pdus, timeout)
end
def stop(esme) do
ESME.stop(esme)
end
# ESME callbacks
def handle_call({:request, pdu}, from, st) do
ESME.send_pdu(self, pdu)
new_st = %{ st | from: from, pdu: pdu, state: :wait_for_resp }
{:noreply, new_st}
end
def handle_call(:pdus, _from, st) do
do_get_pdus(st)
end
def handle_call(:wait_for_pdus, from, st) do
case st.additional_pdus do
[_ | _] -> do_get_pdus(st)
[] ->
new_st = %{ st | from: from, state: :wait_for_pdus }
{:noreply, new_st}
end
end
def handle_resp(pdu, original_pdu, st) do
case st.pdu != nil and Pdu.same?(original_pdu, st.pdu) and st.state == :wait_for_resp do
true ->
GenServer.reply(st.from, {:ok, pdu})
do_set_free(st)
false ->
do_push_to_waiting({:resp, pdu, original_pdu}, st)
end
end
def handle_resp_timeout(pdu, st) do
case Pdu.same?(pdu, st.pdu) and st.state == :wait_for_resp do
true ->
GenServer.reply(st.from, :timeout)
do_set_free(st)
false ->
do_push_to_waiting({:timeout, pdu}, st)
end
end
def handle_pdu(pdu, st) do
do_push_to_waiting({:pdu, pdu}, st)
end
def handle_stop(st) do
case st.from do
nil -> :nop
from -> GenServer.reply(from, :stop)
end
end
def handle_send_pdu_result(pdu, result, st) do
case result do
:ok -> st
{:error, error} ->
case Pdu.same?(pdu, st.pdu) and st.state == :wait_for_resp do
true ->
GenServer.reply(st.from, {:error, error})
do_set_free(st)
false ->
do_push_to_waiting({:error, pdu, error}, st)
end
end
end
def do_push_to_waiting(pdu_info, st) do
pdus = [pdu_info | st.additional_pdus]
case st.state == :wait_for_pdus do
true ->
GenServer.reply(st.from, pdus)
%{ do_set_free(st) | additional_pdus: [] }
false ->
%{ st | additional_pdus: pdus }
end
end
defp do_set_free(st), do: %{ st | from: nil, pdu: nil, state: :free }
defp do_get_pdus(st) do
pdus = st.additional_pdus
new_st = %{ st | additional_pdus: [] }
{:reply, pdus, new_st}
end
end