Quickstart¶
Stand up the smallest possible SMSC — an echo that accepts any bind and acks
every submit_sm — then drive load at it. This is the fastest way to see the
whole path work: bind → decode → your Python handler → response.
You bring the SIPhon binary
siphon-smpp is a library, not a server. It runs inside a
SIPhon binary built with the smpp addon
registered. See Using it in a SIPhon build for how the
addon gets composed in; this page assumes you have that binary (call it
siphon). The load harness below can also self-test with no SIPhon at
all.
1. The echo handler¶
This is examples/echo.py
— the hello-world SMSC:
import uuid
from siphon import smpp, log
@smpp.on_bind
async def authorise(bind):
# Wide open — fine for a local echo, NEVER for anything real.
log.info(f"bind from {bind.system_id} @ {bind.client_addr}")
return bind.accept()
@smpp.on_pdu("submit_sm")
async def echo(pdu, session):
message_id = uuid.uuid4().hex[:12]
log.info(f"submit_sm {session.system_id}: "
f"{pdu.source_addr} -> {pdu.destination_addr} "
f"({len(pdu.short_message)} bytes) => {message_id}")
return pdu.reply(message_id=message_id)
Two handlers: one authorises binds (here, everyone), one acks submit_sm with a
freshly minted message_id. That's a valid, if trivial, SMSC.
2. The addon config¶
siphon-smpp reads its own YAML, separate from SIPhon's main config. A minimal inbound-only listener:
Reference it from your main siphon.yaml, and point SIPhon's script at
echo.py:
See Configuration for every knob (outbound binds, routing, TLS, timers, env-var injection).
3. Run it¶
The listener is now up on 0.0.0.0:2775. Bind a transceiver, submit_sm, and
you get an ESME_ROK + message_id back. Edit echo.py, save, and SIPhon
hot-reloads the handlers — the next PDU uses the new code, no restart.
4. Drive load at it¶
The repo ships a standalone load driver,
harness/.
Both ends speak the same smpp34 wire library siphon-smpp uses, so the load path
is faithful to production.
Self-test — no SIPhon needed (mock SMSC + driver, also the CI smoke test):
cd harness
./run.sh self-test # mock SMSC + 50k submit_sm, window 64
COUNT=200000 WINDOW=128 ./run.sh self-test
Against your running echo SMSC:
drive binds one transceiver ESME, keeps --window submits in flight, and
reports throughput plus submit→resp latency percentiles (p50/p90/p99/p999/max).
For a repeatable sweep of the SMPP window (and a markdown table you can paste),
use ./bench.sh; for the aggregate across many parallel binds, ./bench_multi.sh.
See Performance & load testing for what the numbers mean and
how to reproduce them.
Next¶
- Do something real → Building an SMSC gateway: credential-checked binds, prefix routing, DLR correlation back to the ESME.
- Understand the model → Concepts & architecture.
- All the knobs → Configuration and the Script API.
- Ship it → Deployment and Kubernetes & scaling.