smppex v0.3.1 SMPPEX.MC behaviour
Module for implementing custom SMPP MC entities.
In general, an SMPP MC entity represents a TCP server, which accepts connections
and handles them. The TCP server is represented by a Ranch listener started
by start/2
call. On new connection the listener spawns SMPPEX.Session
process
coupled with SMPPEX.MC
GenServer
handler. The session interacts with the socket
while the MC handler keeps state and does actual PDU handling. One also interacts with
MC handler to send PDUs, PDU replies, etc.
The session makes all requests to the MC handler process syncronously (via GenServer.call
),
while the MC handler process makes only asyncronous(via GenServer.cast
) requests to the session.
This is made intentionally since this allows:
- to avoid any kind of deadlocks while the session and the MC handler process interact actively;
- to control incoming SMPP message rate to avoid overflooding;
- not to lose any control over connection because of the asyncronous nature of TCP implementation in OTP.
To implement an MC entitiy, one should implement several callbacks for MC handler processes
(SMPPEX.MC
behaviour). The most proper way to do it is to use
SMPPEX.MC
:
defmodule MyMC do
use SMPPEX.MC
# ...Callback implementation
end
In this case all callbacks have reasonable defaults.
Note that SMPPEX.MC
does not have a start_link
method since SMPPEX.MC
instances (handler processes)
are launched when a Ranch listener created by start/2
receives a new incoming connection.
Summary
Functions
Makes a syncronous call to MC handler
Makes an asyncronous call to MC handler
Sends reply to previously received PDU from the MC handler
Sends outcoming PDU from the MC handler
Starts listener for MC entitiy
Stops MC listener and all its sessions
Stops MC handler asyncronously
Callbacks
Invoked for handling call/3
calls
Invoked for handling cast/2
calls
Invoked for handling generic messages sent to the MC handler process
Invoked when MC session was stopped abnormally and wasn’t able to
handle sent PDUs without resps in handle_stop
Invoked when the MC handler receives an incoming PDU (which is not a response PDU)
Invoked when the MC handler receives a response to a previously sent PDU
Invoked when the MC handler does not receive a response to a previously sent PDU for the specified timeout
Invoked when the SMPP session successfully sent PDU to transport or failed to do this
Invoked when the SMPP session is about to stop
Invoked when the listener has accepted a connection and tries to created an SMPPEX.MC
.
The Ranch acceptor handling the connection is busy till the function returns
Types
request :: term
send_pdu_result :: :ok | {:error, term}
socket :: port | :ssl.sslsocket
state :: term
transport :: module
Functions
Specs
call(pid, term, timeout) :: term
Makes a syncronous call to MC handler.
The call is handled by handle_call/3
MC callback.
Specs
cast(pid, term) :: :ok
Makes an asyncronous call to MC handler.
The call is handled by handle_cast/2
MC callback.
Specs
reply(mc :: pid, pdu :: SMPPEX.Pdu.t, reply_pdu :: SMPPEX.Pdu.t) :: :ok
Sends reply to previously received PDU from the MC handler.
The whole command is sent to the MC handler asyncronously. The further lifecycle of the response PDU can be traced through callbacks.
Specs
send_pdu(mc :: pid, pdu :: SMPPEX.Pdu.t) :: :ok
Sends outcoming PDU from the MC handler.
The whole command is sent to the MC handler asyncronously. The further lifecycle of the PDU can be traced through callbacks.
Specs
start({module, args :: term}, opts :: Keyword.t) ::
{:ok, listener_ref :: :ranch.ref} |
{:error, reason :: term}
Starts listener for MC entitiy.
module
is the callback module which should implement SMPPEX.MC
behaviour.
args
is the argument passed to the init
callback.
opts
is a keyword list of different options:
:transport
is Ranch transport used for TCP connections: eitherranch_tcp
(the default) orranch_ssl
;:transport_opts
is a list of Ranch transport options. The major option is{:port, port}
. The port is set to0
by default, which means that the listener will accept connections on a random free port.:acceptor_count
is the number of Ranch listener acceptors, 50 by default.:gen_server_opts
is a list of options passed directly to the underlyingGenServer.start_link
call, the default is[]
;:mc_opts
is a keyword list of MC options::timer_resolution
is interval of internalticks
on which time related events happen, like checking timeouts for pdus, checking SMPP timers, etc. The default is 100 ms;:session_init_limit
is the maximum time for which the MC handler waits an incoming bind request. If no bind request is received within this interval of time, MC handler stops. The default value is 10000 ms;:enquire_link_limit
is value for enquire_link SMPP timer, i.e. the interval of SMPP session inactivity after which enquire_link PDU is send to “ping” the connetion. The default value is 30000 ms;:enquire_link_resp_limit
is the maximum time for which MC handler waits for enquire_link PDU response. If the response is not received within this interval of time and no activity from the peer occurs, the session is then considered dead and the MC handler stops. The default value is 30000 ms;:inactivity_limit
is the maximum time for which the peer is allowed not to send PDUs (which are not response PDUs). If no such PDUs are received within this interval of time, MC handler stops. The default is infinity ms;:response_limit
is the maximum time to wait for a response for a previously sent PDU. If the response is not received within this interval,handle_resp_timeout
callback is triggered for the original pdu. If the response is received later, it is discarded. The default value is 60000 ms. If:mc_opts
list of options is ommited, all options take their default values.
The returned value is either {:ok, ref}
or {:error, reason}
. The ref
can be later used
to stop the whole MC listener and all sessions received by it.
Specs
stop(:ranch.ref) :: :ok
Stops MC listener and all its sessions.
The very moment of the SMPP session termination can be traced via handle_stop
callback.
Callbacks
Specs
handle_call(request, from :: GenServer.from, state) ::
{:reply, reply :: term, state} |
{:noreply, state}
Invoked for handling call/3
calls.
The callback is called syncronously for handling.
The returned values have the same meaning as in GenServer
handle_call
callback
(but note that only two kinds of responses are possible). In case of delaying a reply ({:noreply, state}
callback result)
it can be later send using GenServer.reply(from, reply)
Invoked for handling cast/2
calls.
The callback is called asyncronously.
The returned value is used as the new state.
Invoked for handling generic messages sent to the MC handler process.
The returned value is used as the new state.
Specs
handle_lost_pdus(mc_conn :: pid, reason :: term, pdus :: [SMPPEX.Pdu.t]) :: any
Invoked when MC session was stopped abnormally and wasn’t able to
handle sent PDUs without resps in handle_stop
.
Since the MC session is already stopped, the callback does not receive state, but the former pid of MC session, the reason of its termination and unconfirmed PDUs.
The returned value is ignored.
Specs
handle_pdu(pdu :: SMPPEX.Pdu.t, state) :: state
Invoked when the MC handler receives an incoming PDU (which is not a response PDU).
The returned value is used as the new state.
Specs
handle_resp(pdu :: SMPPEX.Pdu.t, original_pdu :: SMPPEX.Pdu.t, state) :: state
Invoked when the MC handler receives a response to a previously sent PDU.
pdu
argument contains the received response PDU, original_pdu
contains
the previously sent pdu for which the handled response is received.
The returned value is used as the new state.
Specs
handle_resp_timeout(pdu :: SMPPEX.Pdu.t, state) :: state
Invoked when the MC handler does not receive a response to a previously sent PDU for the specified timeout.
pdu
argument contains the PDU for which no response was received. If the response
will be received later it will be dropped (with an info
log message).
The returned value is used as the new state.
Specs
handle_send_pdu_result(pdu :: SMPPEX.Pdu.t, send_pdu_result :: SMPPEX.SMPPHandler.send_pdu_result, state) :: state
Invoked when the SMPP session successfully sent PDU to transport or failed to do this.
pdu
argument contains the PDU for which send status is reported. send_pdu_result
can be
either :ok
or {:error, reason}
.
The returned value is used as the new state.
Specs
handle_stop(reason :: term, lost_pdus :: [SMPPEX.Pdu.t], state) :: {exit_reason :: term, state}
Invoked when the SMPP session is about to stop.
lost_pdus
contains sent PDUs which have not received resps (and will never
receive since the session terminates).
reason
contains one of the following:
:custom
— session manually stopped by call toMC.stop_session
;{:parse_error, error}
— error in parsing incoming SMPP packet occured;:socket_closed
— peer closed socket;{:socket_error, error}
— socket error occured;{:timers, reason}
— session closed by timers.
The return value is {stop_reason, new_state}
. The session GenServer will stop
with stop_reason
.
Invoked when the listener has accepted a connection and tries to created an SMPPEX.MC
.
The Ranch acceptor handling the connection is busy till the function returns.
args
argument is taken directly from start/2
call. socket
and transport
arguments
are Ranch socket and transport respectively. They can be used, for example, to inspect
peer address, etc.
The return value should be either {:ok, state}
, then MC handler will successfully start and returned
state will be later passed to the other callbacks, or {:stop, reason}
, then MC handler GenServer
will stop
and the connection closed.