Skip to content

v0.5.0

Choose a tag to compare

@sboily sboily released this 11 Jun 11:10
· 8 commits to main since this release

SIP conformance overhaul and a major feature batch: this release makes
aiosipua hold its own against real-world SIP servers and adds the
signaling features a voice-AI backend needs.

Breaking changes

  • SipUAC.send_cancel(call) replaces send_cancel(dialog, remote_addr)
    the CANCEL is built from the original INVITE (same branch and CSeq,
    RFC 3261 §9.1), which is what proxies require to match it.
  • SipMessage.body is now bytes (SIP bodies are octet streams). Read or
    write text bodies through the new message.text property; parse_sdp
    raises a TypeError pointing at .text if handed bytes.

Conformance fixes

  • Digest authentication rewritten per RFC 7616: qop="auth" (cnonce/nc),
    SHA-256 (RFC 8760) alongside MD5, opaque echoed — challenges from
    Asterisk/FreeSWITCH/Kamailio now succeed.
  • re-INVITE 200s are ACKed with their own CSeq; on_answer no longer replays.
  • In-dialog requests are validated against the dialog (wrong tags → 481,
    non-increasing CSeq → 500); CANCEL matches the INVITE transaction by branch.
  • SDP answers mirror every offered m-line in order, port 0 for rejected
    streams (RFC 3264 §6).
  • received/rport stamped on incoming Vias (RFC 3581); advertised_addr
    on UAC/UAS for NATed signaling.

New features

  • Reliability: 200 OK retransmitted until ACK over UDP, reliable
    provisionals with PRACK/100rel (RFC 3262), automatic transaction expiry.
  • REGISTER client with auto-refresh, 423 handling, and expiry watchdog.
  • UPDATE (RFC 3311) and blind transfer via REFER (RFC 3515) with
    transfer-progress NOTIFYs.
  • Session timers (RFC 4028): UPDATE refreshes and dead-call watchdogs.
  • IPv6 end to end: bracketed literals in Via/Contact/URIs, IN IP6 SDP.

Hardening

  • Header-injection guards on all header setters; size caps on header count,
    TCP header bytes, and declared body length; required-header validation.
  • Parser survives the RFC 4475 torture suite and holds two hypothesis-checked
    invariants: only ValueError on arbitrary input, and a stable wire format
    after one normalization pass.

344 → 524 tests; every module under strict mypy.