SMPP Inbound Lua Agent

Introduction

The SMPPInboundLuaAgent is an asynchronous helper for Lua scripts running within the LogicApp. It is used for accepting (and responding to) inbound SMPP requests from within an already-running Lua script.

Note the similarities and the critical difference between this SMPP Inbound Lua agent, and the SMPP Lua Service. Both handle an inbound received SMPP-S-REQUEST message which is sent by the SMPPApp when it receives an inbound SMPP “deliver_sm” or “submit_sm”. Both are part of the N2TTG product.

The difference is:

SMPP Inbound Agent API methods are accessed via the “n2.n2svcd.smpp_inbound_agent” module:

local smpp_inbound_agent = require "n2.n2svcd.smpp_inbound_agent"

Configuring SMPPInboundLuaAgent

The SMPPInboundLuaAgent is configured within a LogicApp.

    <?xml version="1.0" encoding="utf-8"?>
    <n2svcd>
      ...
      <applications>
        ...
        <application name="Logic" module="LogicApp">
          <include>
            <lib>../apps/logic/lib</lib>
          </include>
          <parameters>
            ...
            <parameter name="default_lua_lib_path" value="../../n2ttg/lua/lib/?.lua;../lua/lib/?.lua"/>
          </parameters>
          <config>
            <services>
              ...
            </services>
            <agents>
              <agent module="SMPPApp::SMPPInboundLuaAgent" libs="../../n2ttg/apps/smpp/lib"/>
            </agents>
          </config>
        </application>
        ...
      </application>
      ...
    </n2svcd>

Under normal installation, the following agent attributes apply:

Parameter Name Type XML Type Description
module SMPPApp::SMPPInboundLuaAgent Attribute [Required] The module name containing the Lua Agent code.
libs ../apps/smpp/lib Element Location of the module for SMPPInboundLuaAgent.

The SMPPInboundLuaAgent API

All methods may raise a Lua Error in the case of exception, including:

The SMPPInboundLuaAgent API can be loaded as follows.

local smpp_inbound_agent = require "n2.n2svcd.smpp_inbound_agent"

.register [Asynchronous]

Registers interest in a specific “destination_addr” field for a “submit_sm” or “deliver_sm” SMPP which is expected to be received in an SMPP-S-REQUEST message sent by an SMPPApp in the near future.

The registration will fail if another in-progress Lua script currently has an active registration for the same destination address. Note that the registration is valid for both “deliver_sm” and “submit_sm” messages.

The registration will fail if this in-progress script already has an open registration. It is not possible for a Lua script to register for two or more “destination_addr” field values simultaneously.

The registration is for an exact matching “destination_addr” field value. Prefix/Suffix/Pattern matching is not supported.

The registration will remain active until:

The register method takes the following parameter.

Parameter Type Description
destination_addr String The exact match SMPP "destination_addr" for which this script registers interest.

This method returns nil.

[Fragment] Example (Register destination address):

    ...
    smpp_inbound_agent.register ("641234567" })
    ...

.deregister [Asynchronous]

De-Registers interest in a previously registered “destination_addr”.

This is not typically necessary, since deregistration occurs automatically in the following cases:

The deregister method takes the following parameter.

Parameter Type Description
destination_addr String The exact match SMPP "destination_addr" for which this script registers interest.

This method returns nil.

[Fragment] Example (De-Register destination address):

    ...
    smpp_inbound_agent.deregister ("641234567" })
    ...

.expect_request [Asynchronous]

The expect_request method waits until an inbound SMPP request is received with a “destination_addr” field equal to the value specified in the previous register method.

This method accepts the following parameters:

Field Type Description
seconds Number Override the default SMPP Inbound timer.
(Default = configured timer for SMPP Inbound Agent).

The expect_request method returns a result structure which takes the same format as the smpp object of the received SMPP-S-REQUEST message.

[Fragment] Example (Expect SMPP Request):

    smpp_inbound_agent.register ("614143007000" })

    local arg_SMPP = smpp_inbound_agent.expect_request ()

    local failmsg = match.string ('pdu', arg_SMPP.pdu, 'submit_sm')
    if (failmsg) then error (failmsg) end

    match.kpath_integer (arg_SMPP, 'command_id', 4)
    match.kpath_exists (arg_SMPP, 'command_status', false)
    match.kpath_exists (arg_SMPP, 'fields.message_id', false)

    smpp_inbound_agent.match_submit_sm_fields (arg_SMPP.fields, { destination_addr = '614143007000', short_message_text = 'Never outfox the fox.', source_addr = '7722' })

.match_submit_sm_fields [Synchronous]

The match_submit_sm_fields method compares the actual received request fields for an inbound “submit_sm” against an expected argument structure.

The match pass/fail results will be recorded against the Lua instance’s trace log. In general, you will typically only wish to use this method within Lua scripts which are run by a service which is part of the IN Tester framework, such as the REST Tester Lua Service.

This method accepts the following parameters.

Field Type Description
actual Table A (typically nested) table structure defining the actual fields of the received "submit_sm".
This is typical the .fields attribute of the result from a call to the expect_result.
For the structure of this parameter, see Tester Internals (SMPP Operations).
expected Table A (typically nested) table structure defining the expected attributes of the operation we have just received.
For the structure of this parameter, see Tester Internals (SMPP Operations).

If the global TRACE_LEVEL == 0, then this method will not create any match records, will not perform any match checks, and will return nil.

The match_submit_sm_fields method returns nil.

[Fragment] Example (Decode/Match ETSI PlayAnnouncement):

    smpp_inbound_agent.register ("614143007000" })

    local arg_SMPP = smpp_inbound_agent.expect_request (3)
    local failmsg = match.string ('pdu', arg_SMPP.pdu, 'submit_sm')
    if (failmsg) then error (failmsg) end

    match.kpath_integer (arg_SMPP, 'command_id', 4)
    match.kpath_exists (arg_SMPP, 'command_status', false)
    match.kpath_exists (arg_SMPP, 'fields.message_id', false)

    smpp_inbound_agent.match_submit_sm_fields (arg_SMPP.fields, { destination_addr = '614143007000', short_message_text = 'Never outfox the fox.', source_addr = '7722' })

.match_deliver_sm_fields [Synchronous]

The match_deliver_sm_fields method compares the actual received request fields for an inbound “deliver_sm” against an expected argument structure.

The match pass/fail results will be recorded against the Lua instance’s trace log. In general, you will typically only wish to use this method within Lua scripts which are run by a service which is part of the IN Tester framework, such as the REST Tester Lua Service.

This method accepts the following parameters.

Field Type Description
actual Table A (typically nested) table structure defining the actual fields of the received "deliver_sm".
This is typical the .fields attribute of the result from a call to the expect_result.
For the structure of this parameter, see Tester Internals (SMPP Operations).
expected Table A (typically nested) table structure defining the expected attributes of the operation we have just received.
For the structure of this parameter, see Tester Internals (SMPP Operations).

If the global TRACE_LEVEL == 0, then this method will not create any match records, will not perform any match checks, and will return nil.

The match_deliver_sm_fields method returns nil.

[Fragment] Example (Decode/Match ETSI PlayAnnouncement):

    smpp_inbound_agent.register ("614143007000" })

    local arg_SMPP = smpp_inbound_agent.expect_request (3)
    local failmsg = match.string ('pdu', arg_SMPP.pdu, 'deliver_sm')
    if (failmsg) then error (failmsg) end

    match.kpath_integer (arg_SMPP, 'command_id', 4)
    match.kpath_exists (arg_SMPP, 'command_status', false)
    match.kpath_exists (arg_SMPP, 'fields.message_id', false)

    smpp_inbound_agent.match_deliver_sm_fields (arg_SMPP.fields, { destination_addr = '614143007000', short_message_text = 'Never outfox the fox.', source_addr = '7722' })

.response [Synchronous]

Following a successful call to expect_request, the Lua processing script using the SMPP Inbound API should use the response method to send back the ACK/NACK response to the sending client (via the SMPPApp).

The Lua script may call the response method directly, although it is simpler to call either the ok or nok methods as described below.

If a Lua script using the SMPP Inbound API receives an inbound request but does not explicitly perform response (using the response, ok, or nok methods) then the end of script cleanup will automatically send a failure response back to the client.

The handling SMPPApp will send the appropriate submit_sm_resp or deliver_sm_resp message back to the originating client, as appropriate to the original inbound request.

The response method takes a single response parameter.

Parameter Type Description
response Table A Lua Table with the same structure described under "Script Return Parameters", i.e. which has the structure of the `smpp` object of the [SMPP-S-RESPONSE message](../../../../n2svcd/technical_guide/messages/smpp_s_messages.html#smpp-s-request).

Note that the Message ID field is only relevant for submit_sm_resp.

After the response method returns, the SMPP response has been handled, and the return value of the handler method is now ignored.

The response method returns nil.

[Fragment] Example Early Response success specifying message ID:

    ...
    smpp_inbound_agent.response ({ command_status = 0, message_id = assigned_id })

    [post-processing logic after SMPP transaction is finished]
    ...

[Fragment] Example Early Response failure:

    ...
    smpp_inbound_agent.response ({ command_status = 0x44 })

    [post-processing logic after SMPP transaction is finished]
    ...

.ok [Synchronous]

The ok method is a short-cut for the early sending of a successful response, i.e. one with command_status = ESME_OK = 0.

The ok method takes a single optional parameter.

Parameter Type Description
message_id String Optional message ID field to include in the response, for submit_sm handling only.

The ok method returns nil.

[Fragment] Example Early Response success specifying message ID:

    ...
    smpp_inbound_agent.ok (assigned_id)

    [post-processing logic after SMPP transaction is finished]
    ...

.nok [Synchronous]

The nok method is a short-cut for the early sending of an unsuccessful response, i.e. one with command_status not equal to ESME_OK = 0.

The nok method takes a single mandatory parameter.

Parameter Type Description
command_status Integer Mandatory non-zero command status.

The nok method returns nil.

[Fragment] Example Early Response failure:

    ...
    smpp_inbound_agent.nok (0x44)

    [post-processing logic after SMPP transaction is finished]
    ...

Constants

The following SMPP constants are defined on the returned smpp_inbound_agent object.

SMPP Command Status Constants

The following constants are the pre-defined, non-reserved SMPP 3.4 constant command status values.

-- SMPP Command Status Constants.
smpp_inbound_agent.ESME_ROK  = 0x00000000               -- No Error
smpp_inbound_agent.ESME_RINVMSGLEN  = 0x00000001        -- Message Length is invalid
smpp_inbound_agent.ESME_RINVCMDLEN  = 0x00000002        -- Command Length is invalid
smpp_inbound_agent.ESME_RINVCMDID  = 0x00000003         -- Invalid Command ID
smpp_inbound_agent.ESME_RINVBNDSTS  = 0x00000004        -- Incorrect BIND Status for given command
smpp_inbound_agent.ESME_RALYBND  = 0x00000005           -- ESME Already in Bound State
smpp_inbound_agent.ESME_RINVPRTFLG  = 0x00000006        -- Invalid Priority Flag
smpp_inbound_agent.ESME_RINVREGDLVFLG  = 0x00000007     -- Invalid Registered Delivery Flag
smpp_inbound_agent.ESME_RSYSERR  = 0x00000008           -- System Error
smpp_inbound_agent.ESME_RINVSRCADR  = 0x0000000A        -- Invalid Source Address
smpp_inbound_agent.ESME_RINVDSTADR  = 0x0000000B        -- Invalid Dest Addr
smpp_inbound_agent.ESME_RINVMSGID  = 0x0000000C         -- Message ID is invalid
smpp_inbound_agent.ESME_RBINDFAIL  = 0x0000000D         -- Bind Failed
smpp_inbound_agent.ESME_RINVPASWD  = 0x0000000E         -- Invalid Password
smpp_inbound_agent.ESME_RINVSYSID  = 0x0000000F         -- Invalid System ID
smpp_inbound_agent.ESME_RCANCELFAIL  = 0x00000011       -- Cancel SM Failed
smpp_inbound_agent.ESME_RREPLACEFAIL  = 0x00000013      -- Replace SM Failed
smpp_inbound_agent.ESME_RMSGQFUL  = 0x00000014          -- Message Queue Full
smpp_inbound_agent.ESME_RINVSERTYP  = 0x00000015        -- Invalid Service Type
smpp_inbound_agent.ESME_RINVNUMDESTS  = 0x00000033      -- Invalid number of destinations
smpp_inbound_agent.ESME_RINVDLNAME  = 0x00000034        -- Invalid Distribution List name
smpp_inbound_agent.ESME_RINVDESTFLAG  = 0x00000040      -- Destination flag is invalid (submit_multi)
smpp_inbound_agent.ESME_RINVSUBREP  = 0x00000042        -- Invalid 'submit with replace' request (i.e. submit_sm with replace_if_present_flag set)
smpp_inbound_agent.ESME_RINVESMCLASS  = 0x00000043      -- Invalid esm_class field data
smpp_inbound_agent.ESME_RCNTSUBDL  = 0x00000044         -- Cannot Submit to Distribution List
smpp_inbound_agent.ESME_RSUBMITFAIL  = 0x00000045       -- submit_sm or submit_multi failed
smpp_inbound_agent.ESME_RINVSRCTON  = 0x00000048        -- Invalid Source address TON
smpp_inbound_agent.ESME_RINVSRCNPI  = 0x00000049        -- Invalid Source address NPI
smpp_inbound_agent.ESME_RINVDSTTON  = 0x00000050        -- Invalid Destination address TON
smpp_inbound_agent.ESME_RINVDSTNPI  = 0x00000051        -- Invalid Destination address NPI
smpp_inbound_agent.ESME_RINVSYSTYP  = 0x00000053        -- Invalid system_type field
smpp_inbound_agent.ESME_RINVREPFLAG  = 0x00000054       -- Invalid replace_if_present flag
smpp_inbound_agent.ESME_RINVNUMMSGS  = 0x00000055       -- Invalid number of messages
smpp_inbound_agent.ESME_RTHROTTLED  = 0x00000058        -- Throttling error (ESME has exceeded allowed message limits)
smpp_inbound_agent.ESME_RINVSCHED  = 0x00000061         -- Invalid Scheduled Delivery Time
smpp_inbound_agent.ESME_RINVEXPIRY  = 0x00000062        -- Invalid message (Expiry time)
smpp_inbound_agent.ESME_RINVDFTMSGID  = 0x00000063      -- Predefined Message Invalid or Not Found
smpp_inbound_agent.ESME_RX_T_APPN  = 0x00000064         -- ESME Receiver Temporary App Error Code
smpp_inbound_agent.ESME_RX_P_APPN  = 0x00000065         -- ESME Receiver Permanent App Error Code
smpp_inbound_agent.ESME_RX_R_APPN  = 0x00000066         -- ESME Receiver Reject Message Error Code
smpp_inbound_agent.ESME_RQUERYFAIL  = 0x00000067        -- query_sm request failed
smpp_inbound_agent.ESME_RINVOPTPARSTREAM  = 0x000000C0, -- Error in the optional part of the PDU Body.
smpp_inbound_agent.ESME_ROPTPARNOTALLWD  = 0x000000C1   -- Optional Parameter not allowed
smpp_inbound_agent.ESME_RINVPARLEN  = 0x000000C2        -- Invalid Parameter Length.
smpp_inbound_agent.ESME_RMISSINGOPTPARAM  = 0x000000C3, -- Expected Optional Parameter missing
smpp_inbound_agent.ESME_RINVOPTPARAMVAL  = 0x000000C4   -- Invalid Optional Parameter Value
smpp_inbound_agent.ESME_RDELIVERYFAILURE  = 0x000000FE, -- Delivery Failure (data_sm_resp)
smpp_inbound_agent.ESME_RUNKNOWNERR  = 0x000000FF       -- Unknown Error