Metadata-Version: 2.4
Name: sip-ladder
Version: 2026.5.25.4
Summary: Generate SIP call-flow (ladder) diagrams from pcap files. Mermaid + SVG output.
Author-email: Ryan Malloy <ryan@supported.systems>
License: MIT
License-File: LICENSE
Keywords: ladder,mermaid,pcap,sequence-diagram,sip,sngrep,svg,voip
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Telecommunications Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Communications :: Internet Phone
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Requires-Dist: dpkt>=1.9.8
Requires-Dist: drawsvg>=2.4.1
Requires-Dist: typer>=0.25.1
Description-Content-Type: text/markdown

# sip-ladder

Generate SIP call-flow (ladder) diagrams from pcap files.

Reads a pcap, parses SIP messages, groups them into calls by `Call-ID`, and
renders the resulting message flow as either a [Mermaid sequence diagram](https://mermaid.js.org/syntax/sequenceDiagram.html)
(text, embeddable in Markdown) or a standalone SVG.

The diagram algorithm is ported from [sngrep](https://github.com/irontec/sngrep)'s
ncurses "Call Flow" view (`src/curses/ui_call_flow.c`), with one improvement:
sngrep treats every distinct `IP:port` as a separate actor column, so a proxy
listening on `:5060` and originating on `:5061` shows up twice. `sip-ladder`
uses `Via` and `Contact` headers to merge those into a single logical actor.

## Install

```bash
uv tool install sip-ladder
# or, ad-hoc:
uvx sip-ladder trace.pcap -o flow.mmd
```

## Example output

Given a pcap containing a basic INVITE flow, `sip-ladder` produces:

```mermaid
---
title: demo-1-simple@atlanta.example INVITE → 200
---
sequenceDiagram
    autonumber
    participant A as alice@192.0.2.10
    participant B as 192.0.2.20:5060
    A->>B: INVITE
    B-->>A: 100 Trying
    B-->>A: 180 Ringing
    B-->>A: 200 OK (INVITE)
    A->>B: ACK
    A->>B: BYE
```

The pcap that produced this — plus a redirect call and a REFER-based transfer — lives in
[`examples/build_demo_pcap.py`](examples/build_demo_pcap.py). Run it locally to regenerate:

```bash
uv run python examples/build_demo_pcap.py
# Produces examples/demo-call-flow.{pcap,mmd,svg}
```

GitHub, GitLab, Obsidian, and most modern Markdown viewers render the Mermaid block above as a
sequence diagram. On platforms that don't (PyPI's README renderer, plain-text consumers), the
fenced code block remains readable as-is.

## CLI

```bash
sip-ladder trace.pcap                   # render all calls as Mermaid to stdout
sip-ladder trace.pcap -o flow.mmd       # write Mermaid to file
sip-ladder trace.pcap -o flow.svg       # extension drives format
sip-ladder trace.pcap --list            # list calls without rendering
sip-ladder trace.pcap --call-id abc...  # render just one call
```

## Library

```python
from sip_ladder import read_pcap, render_mermaid, render_svg

for call in read_pcap("trace.pcap"):
    print(f"{call.call_id}  {call.from_uri} -> {call.to_uri}  ({call.final_response})")
    open(f"{call.call_id}.mmd", "w").write(render_mermaid(call))
    render_svg(call, f"{call.call_id}.svg")
```

## Scope

In-scope for the initial release:

- Offline pcap analysis (UDP and best-effort TCP)
- SIP message parsing (RFC 3261 — common cases)
- Mermaid + SVG renderers
- Via-aware actor reconciliation
- Retransmit detection via CSeq match

Out-of-scope (deferred):

- Live capture (libpcap, HEP/EEP listener, sngrep subprocess streaming)
- RTP / MOS analysis
- TLS decryption
- SIP-over-WebSocket
- Interactive HTML

The architecture leaves clean seams to add these later without restructuring.

## License

MIT.
