smppex v0.3.0 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:
:transportis Ranch transport used for TCP connections: eitherranch_tcp(the default) orranch_ssl;:transport_optsis a list of Ranch transport options. The major option is{:port, port}. The port is set to0by default, which means that the listener will accept connections on a random free port.:acceptor_countis the number of Ranch listener acceptors, 50 by default.:gen_server_optsis a list of options passed directly to the underlyingGenServer.start_linkcall, the default is[];:mc_optsis a keyword list of MC options::timer_resolutionis interval of internaltickson which time related events happen, like checking timeouts for pdus, checking SMPP timers, etc. The default is 100 ms;:session_init_limitis 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_limitis 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_limitis 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_limitis 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_limitis the maximum time to wait for a response for a previously sent PDU. If the response is not received within this interval,handle_resp_timeoutcallback is triggered for the original pdu. If the response is received later, it is discarded. The default value is 60000 ms. If:mc_optslist 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.