Quickstart¶
Stand up the smallest possible node: one point code, one M3UA peer, one owned subsystem, and a handler that terminates MO-ForwardSM. Then prove the whole termination path without any peer at all, using the built-in loopback seam.
You bring the SIPhon binary
siphon-sigtran is a library, not a server. It runs inside a
SIPhon binary that registers the addon at
startup; see Using it in a SIPhon build. This page
assumes you have that binary (call it siphon).
1. The config¶
One file describes the node. Minimal, single node, every value synthetic
(test PLMN 001/01, +1-555-01xx global titles, decimal point codes):
# sigtran.yaml
node:
point_code: 1000
variant: itu
associations:
- { id: msc-1, adaptation: m3ua, role: server, addrs: [10.1.0.10], port: 2905 }
application_servers:
- { name: msc, traffic_mode: override, routing_context: 100, asps: [msc-1] }
mtp3_routes:
- { dpc: 2000, as: msc, priority: 1 }
sccp:
local_ssns: [8] # we own SSN 8; inbound for it terminates locally
See Configuration for every field. Point your main SIPhon config at it, so the binary loads and configures the node at startup:
2. The script¶
from siphon import gsm_map
@gsm_map.on_operation("mo-forward-sm")
async def on_mo(dlg, arg):
# arg.sm_rp_oa / arg.sm_rp_da / arg.sm_rp_ui are the raw address + TPDU bytes.
dlg.reply(gsm_map.mo_forward_sm_res()) # returnResultLast, in a closing End
dlg.end()
One handler of policy: terminate mobile-originated SMS with an ack. The binary
configured the node from sigtran.yaml; the script just registers handlers.
@gsm_map.on_operation("<name>") names the operation by its kebab-case name (the
same on_<message>("<name>") shape as @smpp.on_pdu); it takes several
pipe-separated, and a bare @gsm_map.on_operation is a catch-all. See the full
selector list in the Script API.
3. Run it¶
Load the script into your composing siphon binary the way you load any SIPhon script, and start it:
The node binds its associations, runs the M3UA handshake as peers connect, and routes. Edit the script, save, and SIPhon hot-reloads it; routing state lives in Rust, so nothing is dropped (Concepts).
4. Prove the path, no peer needed¶
You do not need a live SS7 peer to test the handler. In a test, siphon.configure
builds a node and hands back a Node you can drive: assemble a genuine inbound
Begin (real TCAP in a real SCCP UDT) and push it through the dialogue engine.
# In a test (not the live script — the binary configures the live node).
node = siphon.configure("sigtran.yaml")
begin = node.assemble_begin(op="mo-forward-sm",
called_gt="15550100", called_ssn=8,
calling_gt="15550142")
replies = node.deliver(begin, opc=2000, dpc=1000)
print(f"terminated MO-ForwardSM, {len(replies)} reply MSU(s)")
deliver returns the SCCP payloads the node would send back: here one End
carrying the returnResultLast your handler staged. This is the same seam the
crate's own integration tests drive; see
Testing your handlers.
Next¶
- Do something real: the Cookbook has the four worked recipes (STP, HLR, SMSC, CAMEL SCP).
- Understand the model: Concepts & architecture.
- All the knobs: Configuration and the Script API.
- Ship it: Deployment and Kubernetes & scaling.