One filter language for the command line, the config file, vCon export and MCP tools
Where sipnab accepts a filter expression, how to try one before you rely on it, and what a value the capture could not measure matches.
In short
sipnab is a tool that reads recorded or live phone-call traffic. It lets you pick out the calls you care about with a short written condition. An example is “calls that failed with code 488”.
The same condition works everywhere sipnab asks which calls you mean:
- on the command line,
- in the settings file,
- when saving call records,
- in automated pass/fail checks,
- in the tools an AI assistant uses.
A value the recording does not contain matches no condition at all. An example is call quality on a call that carried no audio.
Who this is for
- Anyone who writes a sipnab filter more than once.
- Anyone who keeps one in a settings file, a test suite or an assistant’s instructions.
What it does
A filter selects dialogs.
- One dialog is one SIP call or other SIP conversation, from its first request to its last reply.
- SIP is the signaling protocol that sets up and ends phone calls.
The filter language compares fields of a dialog, such as response_code,
duration or rtp.mos. It combines comparisons with AND, OR and NOT.
sipnab accepts the same text in each of these places:
| Where | What you write |
|---|---|
| Command line | --filter <EXPR> |
| Settings file | expression under [filter] |
| Saving calls as vCon files | --export-vcon-when <EXPR> |
| Pass/fail rules for automated tests | scope = "filter:<EXPR>" in a rule read by the MCP tool evaluate_expectations |
| MCP tools that list dialogs | the filter parameter of list_dialogs, find_problems and others |
A vCon is a standard JSON file that holds one conversation’s record. MCP (Model Context Protocol) is the interface an AI assistant uses to call sipnab’s tools.
Ten names stand for preset expressions: problems, slow-setup,
short-calls, one-way, nat-issues, codec-asym, ptime-asym,
payload-asym, duration-asym and late-media.
--filterfirst checks whether its argument is one of these names.- It treats it as an expression only when it is not.
- Five of the names also have their own flag (
--problems,--slow-setup,--short-calls,--one-way,--nat-issues). - The MCP tool
find_problemstakes them in itskindslist.
What a build needs
Nothing needs enabling. The filter language is part of every sipnab build.
--export-vcon-whenand the MCP tools need a build with thevconandmcpfeatures.sipnab --versionlists the features a binary carries.
Select calls with a filter
These commands use tests/pcap-samples/sip-488-codec-reject.pcapng. It is a
recording (pcap file) that ships in the sipnab repository. It holds four
dialogs.
-Nselects command-line mode instead of the interactive screen.-qhides informational log lines.--no-cli-printsuppresses the per-message output. So sipnab prints only the report.
The output below has the trailing spaces at the ends of the report lines removed.
The steps:
- Select the dialogs that failed with response code 488:
sipnab -N -q -I tests/pcap-samples/sip-488-codec-reject.pcapng --filter "response_code == 488" --report --no-cli-print
Call-ID From To State Code Duration Msgs PDD Tags
-------------------------------------------------------------------------------------------------------------------------
codec-reject-synth caller callee Failed 488 0s 7 - -
- Save the same dialogs as vCon files, using the same expression. sipnab
creates the directory
vconsin the current directory:
sipnab -N -q -I tests/pcap-samples/sip-488-codec-reject.pcapng --export-vcon-when "response_code == 488" --export-vcon-dir vcons --no-cli-print
Wrote 1 vCon container(s) to 'vcons'.
- Use a preset name instead of an expression.
short-callsexpands toduration < 3.0 AND state == 'Completed'.- That holds while the short-call threshold is at its default of 3 seconds:
sipnab -N -q -I tests/pcap-samples/sip-488-codec-reject.pcapng --filter short-calls --report --no-cli-print
Call-ID From To State Code Duration Msgs PDD Tags
-------------------------------------------------------------------------------------------------------------------------
options-ping-a-synth@192.16... keepalive keepalive Completed 200 0s 2 - -
options-ping-b-synth@192.16... keepalive keepalive Completed 200 0s 2 - -
options-ping-c-synth@198.51... ping probe Completed 200 0s 2 - -
--short-calls and --filter "duration < 3.0 AND state == 'Completed'"
print the same three dialogs on this file.
Check an expression before you rely on it
The MCP tool validate_filter does three things:
- It parses an expression.
- It counts the dialogs it matches.
- It returns no dialog rows.
Run against the same file, a call with {"expr":"short-calls"} returned:
{"error":null,"expr":"short-calls","schema_version":1,"source_exhausted":true,"source_stopped_early":false,"total_dialogs":4,"total_matched":3,"valid":true}
An expression that does not parse is not an error for this tool. A call with
{"expr":"response_code == == 5"} returned:
"valid":false,"total_matched":null,- the parser’s message in
error. It names position 17 and marks it with a caret.
total_matched is null rather than 0. So no reader can take it as “parsed,
and matched nothing”.
Other MCP tools, such as list_dialogs, reject the same expression with a
JSON-RPC error (code -32602).
Limits
- A value the capture could not measure matches no comparison.
- These fields are unknown when there is nothing to measure them from:
pdd(post-dial delay),setup_time,rtp.mos(call-quality score),rtp.jitterandrtp.loss.- The media fields need RTP (the packets that carry the audio).
- The timing fields need a captured INVITE or
200 OK.
- An unknown value matches no numeric operator,
!=included. response_codeis unknown while a call is still in progress.tests/pcap-samples/b2bua-asterisk.pcapngholds 12 dialogs and media for 2 of them. On it,--filter "rtp.mos != 3.0"selects only those 2.- To select calls without media, use
rtp.packets == 0, which is a real count, or the fieldno_media.
- These fields are unknown when there is nothing to measure them from:
rtp.orphanedis not a field.- The parser rejects it with
hint: unknown field 'rtp.orphaned'and exit code 2. - An orphaned stream is an RTP stream that no dialog claims. So a dialog field cannot describe it.
- Two places list orphaned streams: the “Orphaned Streams” section of
--report, andGET /v1/streams?orphaned=trueon the REST API.
- The parser rejects it with
--call-report <CALL-ID>is not narrowed by--filter. It names one call. So it prints that call whatever the filter says.- The language has no comment syntax. A line starting with
#is a parse error. - String comparisons are case-sensitive.
=~takes a regular expression in Rust regex syntax. - The per-message match is a separate option.
-e/--matchtests a regular expression against each raw SIP message.- Once one message in a dialog matches, it shows every later message of that dialog.
- Inside a filter expression, the
payloadfield does the same test per dialog.
Terms used here
- SIP: the protocol that sets up, changes and ends phone calls over IP.
- Dialog: one SIP conversation, such as one call, from first request to last reply.
- RTP: the protocol that carries the audio of a call.
- pcap: a file format for recorded network traffic.
- INVITE / 200 OK: the SIP request that starts a call, and the reply that accepts it.
- Response code: the three-digit number in a SIP reply. 400 and above means failure.
- MOS: Mean Opinion Score, an estimate of call quality from 1 to 5.
- Post-dial delay (PDD): time from the call request to the first reply. That reply shows the far end is ringing or answering.
- vCon: a standard JSON file format for one conversation’s record.
- MCP: Model Context Protocol, the interface AI assistants use to call tools.
- JSON-RPC error: the error form MCP uses for a call it refuses.
- REST API: sipnab’s HTTP interface for other programs.