Skip to content

SMPP operation coverage

siphon-smpp has full SMPP 3.4 operation coverage — every meaningful PDU dispatches to a script handler with a sensible default when you don't register one. Built on smpp34 1.2.

The tables below list, for each PDU, which decorator it dispatches to and what happens with no handler registered.

Inbound — an ESME binds to you (server)

PDU Dispatched to Default (no handler)
bind_transceiver @smpp.on_bind reject — closed by default
bind_transmitter / bind_receiver reject ESME_RINVSYSID (transceiver only)
submit_sm @smpp.on_pdu("submit_sm") ESME_ROK ack
submit_sm_multi @smpp.on_pdu("submit_sm_multi") (pdu.destinations) reject ESME_RSYSERR
data_sm @smpp.on_pdu("data_sm") reject ESME_RSYSERR
cancel_sm @smpp.on_pdu("cancel_sm") reject ESME_RCANCELFAIL
query_sm @smpp.on_pdu("query_sm")pdu.reply_query(…) reject ESME_RQUERYFAIL
replace_sm @smpp.on_pdu("replace_sm") reject ESME_RREPLACEFAIL
enquire_link runtime (keep-alive) auto-ack
unbind runtime + @smpp.on_session("unbound") accept

The defaults are deliberately conservative: message management PDUs (cancel/query/replace) reject unless you implement them, because a silent success would be a lie. submit_sm acks by default only so an echo works out of the box — a real gateway always handles it.

Throttling happens before dispatch

If a session exceeds server.max_msg_per_sec and server.throttle_action is reject, the runtime answers ESME_RTHROTTLED itself — your handler doesn't run for that PDU. With the default pace action it delays the response instead. See Configuration → Throttling.

Outbound — you bind to a remote SMSC (client)

These arrive on your outbound binds.

PDU Dispatched to Default (no handler)
deliver_sm (incl. DLR) @smpp.on_pdu("deliver_sm") ESME_ROK ack
data_sm @smpp.on_pdu("data_sm") reject ESME_RSYSERR
alert_notification @smpp.on_pdu("alert_notification") no-op

deliver_sm is where delivery receipts come back: pdu.is_dlr flags a receipt and pdu.receipt is the parsed dict. Correlating that receipt back to the originating ESME is the heart of the gateway walkthrough.

Send helpers

The other half — PDUs you originate. Outbound helpers target a bind by name; inbound helpers target a bound ESME by session_id.

Helper Direction Backed by (smpp34)
submit_via → outbound bind SMSC::submit_sm
submit_multi_via → outbound bind SMSC::send_submit_sm_multi
data_via → outbound bind SMSC::send_data_sm
cancel_via → outbound bind SMSC::send_cancel_sm
query_via → outbound bind SMSC::send_query_sm
replace_via → outbound bind SMSC::send_replace_sm
deliver_to → bound ESME (session_id) ESME::send_deliver_sm
data_to → bound ESME ESME::send_data_sm
alert_to → bound ESME ESME::send_alert_notification

See the Script API for signatures and return types.

Scope

siphon-smpp is pure SMPP — ESME ↔ SMSC, DLRs, message management, store-and-forward. It is intentionally not an interworking gateway: it does not translate SMPP to other protocols. That keeps the addon a clean, commodity SMPP building block; higher-level interworking is out of scope and lives in your own application logic above it.