Skip to main content

siphon-control (Python)

Python client for the SIPhon external control plane (siphon-control.v1) — an ARI/ESL-class rail for driving handed-over calls out of process. Built with PyO3 over the async Rust client, so the wire is hidden: no manual JSON, no request-id bookkeeping.

Two connection modes

The plane runs in one of two modes; both are exposed here and share the SAME @on_call decorator and the SAME Call handle — only the transport differs.

  • Inbound-persistent (ControlClient) — the app dials siphon and holds one long-lived socket (does the hello handshake). Simplest to reason about; use it for development and single-process controllers.
  • Per-call-connect (ControlServer) — siphon dials the app per handed-over call, so the app is a WebSocket server. Each accepted connection owns exactly one call and the first frame is a pushed StasisStart (no hello). This is the documented production default for multi-pod controllers: because the accepting socket is the call, "the audio lands on the wrong pod" can't happen.

Inbound-persistent

import asyncio
from siphon_control import ControlClient, ControlError

client = ControlClient(app="ivr-app", token="s3cr3t",
                       url="ws://siphon:9090/control/ws")

@client.on_call
async def handle(call):
    await call.answer()
    try:
        await call.transfer("sip:agent@pbx")   # REFER, awaits correlated reply
    except ControlError as error:
        print("transfer rejected:", error.code)

asyncio.run(client.run())

Per-call-connect

import asyncio
from siphon_control import ControlServer, ControlError

server = ControlServer(app="ivr-app", token="s3cr3t", bind="0.0.0.0:8790")

@server.on_call
async def handle(call):
    await call.answer()
    try:
        await call.transfer("sip:agent@pbx")
    except ControlError as error:
        print("transfer rejected:", error.code)

asyncio.run(server.serve())

API

ControlClient (inbound-persistent)

  • ControlClient(app, token, url=…, protocol=1, reply_timeout_ms=…, reconnect_backoff_ms=…)
  • @client.on_call — register an async (or sync) per-call handler.
  • await client.connect() / await client.run() — connect / drive (reconnect + resync).
  • await client.command(verb, module=None, target=None, args=None) — the generic {module, verb, target, args} primitive for any adapter (SIP today; SMPP/SS7 later).
  • await client.describe() — adapter schema.
  • client.shutdown() — stop the client and unblock run().

ControlServer (per-call-connect)

  • ControlServer(app, token, bind="0.0.0.0:8790", reply_timeout_ms=…)bind is the address the app listens on for siphon to dial; the token is validated on the incoming upgrade.
  • @server.on_call — the SAME decorator + Call handle as ControlClient.
  • await server.bind() — bind the listener; resolves to the bound address string (bind to …:0 to learn the ephemeral port before siphon dials in).
  • server.local_addr — the bound address once bind() / serve() has run, else None.
  • await server.serve() / await server.run() — accept siphon's per-call dials forever (stop by cancelling the task).

Call (shared by both modes)

  • Call verbs: answer(), answer_with(code, …), progress(), reject(code, reason), hangup(reason=None), refer(to) / transfer(to), set_header(name, value), get_header(name), set_var(key, value), get_var(key), command(verb, args=None), next_event().
  • Media verbs play_file(file) / dtmf(digits) raise ControlError with code == "unsupported_verb" until the server implements media.

Errors

A rejected command raises ControlError carrying a stable .code (not_found, forbidden, unsupported_verb, unauthorized, …).

Build

maturin develop        # into the active venv
maturin build --release

The target interpreter is free-threaded CPython 3.14t (the SIPhon runtime); the wheel also loads on a standard GIL build.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

siphon_control-0.1.0.tar.gz (47.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

siphon_control-0.1.0-cp314-cp314-manylinux_2_34_x86_64.whl (1.7 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.34+ x86-64

File details

Details for the file siphon_control-0.1.0.tar.gz.

File metadata

  • Download URL: siphon_control-0.1.0.tar.gz
  • Upload date:
  • Size: 47.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.16 {"installer":{"name":"uv","version":"0.9.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for siphon_control-0.1.0.tar.gz
Algorithm Hash digest
SHA256 91fd38eca2b308f0ed950b218fbef8b775a47fa7b591d3e80edb244d1d794a91
MD5 1ee0d3e8f37496aba0ef3ef9f048ee6d
BLAKE2b-256 0158e8bd6445dce7f493f44606abe6361a4226fc2544704c7edeaa7de3b02da5

See more details on using hashes here.

File details

Details for the file siphon_control-0.1.0-cp314-cp314-manylinux_2_34_x86_64.whl.

File metadata

  • Download URL: siphon_control-0.1.0-cp314-cp314-manylinux_2_34_x86_64.whl
  • Upload date:
  • Size: 1.7 MB
  • Tags: CPython 3.14, manylinux: glibc 2.34+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.16 {"installer":{"name":"uv","version":"0.9.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for siphon_control-0.1.0-cp314-cp314-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 2cfcea36f1478c7b8def78b75c3af3159362e3b9be5910c62054909468522e2c
MD5 d27079265e546e45604b5aacafda86f3
BLAKE2b-256 05e20a988712f5b119e0f16184ae107284d99d5e7a5d1def7cab50fdb89361f4

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.2

9 files

0.1.1

9 files

This release

0.1.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page