Skip to content

Latest commit

 

History

128 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SipBot

Crates.io Documentation

A flexible, high-performance SIP bot implementation in Rust, designed for testing and simulating SIP call flows. It uses rsipstack for signaling and supports customizable call handling stages including ringing, answering, media playback, echo, and automatic hangup.

The media transport uses rustrtc.

Features

  • Multi-Account Support: Configure multiple SIP accounts in a single instance.
  • Flexible Call Flow Stages:
    • Ringing (Stage 1): Send 180 Ringing or 183 Session Progress with custom ringback tone (WAV).
    • Answer (Stage 2): Auto-answer calls with 200 OK.
    • Media Handling:
      • Play: Play a specified .wav file.
      • Echo: Echo received RTP packets back to the sender (Latency testing).
      • Local: Use local audio device for playback and capture (Mic/Speaker).
    • Hangup (Stage 3): Automatically hang up after a configurable duration or reject calls with specific SIP codes.
  • Outbound Calls: Ability to initiate calls to a target URI. With --local, the caller plays remote early media (CRBT / 彩铃) on the speaker when the peer sends 183 with SDP.
  • Call Recording: (Experimental) Record call audio to WAV files. (Requires configuration)
  • DTMF (RFC 2833): Send DTMF digits via keyboard during single calls; receive and log DTMF events from remote endpoints. Supports scheduled DTMF flows: --dtmf-flows "1s:2,1.5s:#".
  • Hold/Resume (Re-INVITE): Automatically send hold/resume re-INVITEs at scheduled times. Supports --reinvite-flows "5s:hold,10s:resume" — ideal for testing RFC 3264 SDP direction negotiation and RTP silence during hold.
  • Audio Quality Analysis: Per-call audio quality monitoring with RMS, clipping, DC offset, zero-crossing rate, spectral tilt, shrill/muffled classification, and sample-rate mismatch detection.
  • Registration: Supports SIP registration with authentication (WIP).

Quick start

Install the sipbot from crates.io.

cargo install sipbot

Build from source

Linux users can build a static binary with musl for maximum compatibility:

cargo build -r --target x86_64-unknown-linux-musl --no-default-features

CLI Usage

You can also run sipbot with CLI arguments for quick testing.

Global Options

  • -C, --conf <FILE>: Path to the configuration file.
  • -E, --external <IP>: External IP address for SDP (NAT traversal).
  • -v, --verbose: Enable verbose logging.

Initiate a Call

cargo run -- call -t sip:user@domain -u sipbot --play audio.wav --hangup 10 --total 10 --cps 2
  • -t, --target <TARGET>: Target URI (e.g., sip:user@domain).
  • -u, --username <USER>: Username (e.g., sipbot). Alias: --caller.
  • --auth-user <USER>: Auth username (optional).
  • --password <PASS>: Auth password.
  • --register [DOMAIN]: Register to SIP server before calling (optional domain).
  • --hangup <SECONDS>: Hangup after seconds.
  • --play <FILE>: Play file (wav).
  • --local: Use local audio device for playback and capture. Also plays remote early media (CRBT / 彩铃) to the speaker when the peer sends 183 Session Progress with SDP.
  • --record <FILE>: Record to file (wav). If multiple calls are made, the filename will be suffixed with the call index (e.g., record_1.wav).
  • --srtp: Enable SRTP/SDES.
  • --nack: Enable NACK.
  • --jitter: Enable Jitter Buffer.
  • --total <COUNT>: Total number of calls to make (default: 1).
  • --cps <COUNT>: Calls per second (default: 1).
  • --cancel-prob <PROB>: Cancel probability (0-99%) (default: 0).
  • --codecs <LIST>: Codecs to use (e.g., opus,g722,pcmu).
  • --audio-quality: Enable per-call audio quality analysis (RMS, clipping, DC offset, spectral tilt, shrill/muffled detection).
  • --csv-output <FILE>: Output periodic statistics to CSV file.
  • --csv-interval <SECONDS>: CSV output interval in seconds (default: 5).
  • --from <USER>: From URI user part for outbound calls (e.g., anonymous).
  • -H, --header <HEADER>: Add custom SIP header (e.g., -H 'X-Custom: value'). Can be used multiple times.
  • --dtmf-flows <FLOW>: Scheduled DTMF flow after answer (e.g., "1s:2,1.5s:#" sends 2 after 1s, # after 1.5s).
  • --reinvite-flows <FLOW>: Scheduled re-INVITE flow after answer (e.g., "5s:hold,10s:resume" sends hold after 5s, resume after 10s).
  • --info-flows <FLOW>: Scheduled in-dialog SIP INFO after answer (e.g., "3s:application/json:{\"k\":\"v\"};5s:application/dtmf-relay:Signal=5"). Entries are semicolon-separated, each <delay>:<content_type>:<body>; use \n for newlines in the body.

Tip: When making a single call (--total 1), you can send DTMF digits by typing them in the terminal. Supported: 0-9, *, #, A-D. Press q to quit the DTMF reader.

cargo run -- wait --addr 0.0.0.0:5060 -u sipbot --answer welcome.wav
  • -a, --addr <ADDR>: Bind address (e.g., 0.0.0.0:5060).
  • -u, --username <USER>: Username (e.g., sipbot).
  • -d, --domain <DOMAIN>: Domain/Realm (e.g., 127.0.0.1). Alias: --realm.
  • --auth-user <USER>: Auth username (optional).
  • -p, --password <PASS>: Password for registration.
  • --register [DOMAIN]: Register to SIP server (optional domain).
  • --ringback [<FILE>]: Ringback file (wav). Flag without value = built-in ringing.wav: sends 183, plays it to the end, then answers.
  • --ring-duration <SECONDS>: Ring duration in seconds (optional with --ringback; caps playback).
  • --answer <FILE>: Answer and play file (wav).
  • --echo: Answer and echo.
  • --local: Answer and use local audio device.
  • --hangup <SECONDS>: Hangup after seconds.
  • --reject <CODE>: Reject with code (e.g. 486, 603).
  • --reject-prob <PROB>: Randomly reject call with probability 1-99% (default code 480).
  • --srtp: Enable SRTP/SDES.
  • --nack: Enable NACK.
  • --jitter: Enable Jitter Buffer.
  • --codecs <LIST>: Codecs to use (e.g., opus,g722,pcmu).
  • --audio-quality: Enable per-call audio quality analysis.
  • -H, --header <HEADER>: Add custom SIP header (e.g., -H 'X-Custom: value'). Can be used multiple times.
  • --record <FILE>: Record to file (wav). If multiple calls arrive, the filename is suffixed with a timestamp and call id (e.g., out_20260730090500_abc.wav).
  • --refer-reject <CODE>: Reject inbound REFER with this status code (e.g. 405, 486).

Note: wait --record <FILE> records each incoming call to a uniquely-named file derived from the base name. Alternatively, you can set the recorders directory in a configuration file to write timestamped files there.

Other Commands

  • options: Send OPTIONS request.
  • info: Send INFO request.

Web Answer Test Server (serve)

sipbot serve starts a web UI + REST/WebSocket API plus one SIP bot per configured account — a self-service "answer test" workbench:

sipbot serve --conf serve.toml --http 0.0.0.0:8080
# open http://localhost:8080

Features

  • 策略模板 (per-account, hot-reloadable from the UI):
    • 标准被叫: 180 ringing N secs → 200 OK → echo/play → hangup
    • 运营商彩铃: 183 with ringback SDP → answer after playback/N secs
    • 来电报号: answer → play announcement ("XX来电") → in-call stream jump (new SSRC + fresh seq/ts bases, no re-INVITE — mimics carrier media handoff)
    • 拒接: play tone via 183 then respond 486/603 (or reject immediately)
    • SDP 跳变 (sdp_jump): the 200 OK answer SDP differs from the 183 SDP (new SSRC/port/codec/ts/seq) — verify receiver robustness
    • Custom caller matching (match_caller = "138*|139*"), per-strategy codecs, scheduled DTMF flows, hangup modes (remote / after N secs / playback)
  • 观测: per-call SIP message trace, SDP offer/183/200 capture + diff view, live RTP/RTCP stats (packets/loss/RTT/NACK/seq-gap/ts-jump), DTMF events, WAV recordings playback
  • 控制: hang up a live call, send DTMF digits from the UI
  • 外呼测试: start outbound test calls (play/echo, DTMF flows, CPS/total) from the UI via an ephemeral caller bot
  • 媒体文件: list / preview / upload-overwrite WAV files used by strategies
  • 传输: per-account udp / tcp / ws / wss; media modes rtp / srtp / webrtc (+NACK, jitter buffer)

Example serve.toml

Accounts (SIP identity) and strategies (reusable answer behavior) are separate entities; accounts bind a strategy by name, one strategy can serve many accounts.

addr = "0.0.0.0:35060"           # default UDP/TCP bind (per-account override below)
recorders = "./recordings"       # WAV recordings directory
media_dir = "./wavs"             # UI-manageable announcement/media files
records_dir = "./records"        # persisted call records (JSON per call, survives restart)
http_addr = "0.0.0.0:8080"       # web UI/API

# ── reusable strategies ──
[[strategies]]
name = "彩铃-报号-跳变"
# match_caller = "138*|139*"     # only answer matching callers
codecs = ["pcmu", "pcma", "g722", "opus"]

[strategies.ring]
duration_secs = 3                # 0 = answer immediately
ringback = "wavs/crbt.wav"       # 183 early media; "" = built-in; omit = 180

[strategies.announce]
file = "wavs/announce.wav"       # "XX来电" announcement ({{caller}} supported)
jump_after = true                # in-call stream jump: new SSRC/seq/ts, no re-INVITE
# jump_codec = "g722"            # optional codec switch on jump

[strategies.answer]
action = "echo"                  # play | echo

sdp_jump = true                  # 200 OK SDP differs from 183 (new SSRC/port/codec)
jump_codecs = ["pcmu"]

dtmf_flows = "1s:2,2s:#"

[strategies.hangup]
mode = "after"                   # remote (wait for peer BYE) | after | playback
after_secs = 30

[[strategies]]
name = "秒拒"
[strategies.reject]
code = 486
tone = "wavs/busy.wav"           # play tone via 183, then 486
delay_secs = 2

# ── accounts: pure SIP identity + strategy binding ──
[[accounts]]
username = "1001"
domain = "127.0.0.1"
password = "123456"
register = true
strategy = "彩铃-报号-跳变"
# transport = "udp"              # udp | tcp | ws | wss
# transport_addr = "0.0.0.0:35061"  # omit → auto port allocation
# transport_ws_url = "wss://host:8443/ws"

[[accounts]]
username = "1002"
domain = "127.0.0.1"
strategy = "秒拒"
  • Strategy/account edits in the UI are written back to serve.toml and applied immediately (account bots are hot-reloaded; ports auto-allocated per account).
  • Accounts may also keep legacy inline strategy fields (ring/answer/hangup/...) instead of binding a named strategy.
  • Call records: every finished call is flushed as JSON (sip_trace, SDP offer/183/200, jump events, DTMF, final RTP/RTCP stats, recording path) into records_dir and reloaded on startup — history survives restarts.

REST / WebSocket API

Method/Path Description
GET/PUT /api/config read / update+persist+hot-reload config
GET /api/accounts accounts + registration status
GET /api/calls · POST /api/calls call list · start outbound test call
GET /api/calls/{id} full detail: sip trace, SDP, DTMF, jumps, stats
POST /api/calls/{id}/hangup · .../dtmf control a live call
GET /api/recordings · GET /recordings/{file} recordings list / WAV
GET /api/media · POST/DELETE /api/media/{file} · GET /media/{file} media files
WS /ws live SIP messages, call states, DTMF events

Typical Usage Examples

1. Echo Test (Latency & Connectivity)

Answer incoming calls and echo the audio back to the caller. This is perfect for testing network latency and packet loss.

sipbot wait --username echo-bot --echo

2. Intercom Mode (Local Audio)

Use your computer's microphone and speakers to talk to a SIP endpoint.

# Answer incoming calls with local audio
sipbot wait --username intercom --local

# Outbound call: hear remote CRBT/彩铃 on 183, then talk after answer
sipbot call -t sip:user@domain -u sipbot --local

3. Automated Announcement

Answer calls, play a welcome message, and hang up after 10 seconds.

sipbot wait --username announcement --answer welcome.wav --hangup 10

4. Custom SIP Headers

Add custom SIP headers to outgoing calls and incoming responses:

# Outgoing call with custom headers
sipbot call -t sip:user@domain -u caller -H 'X-Call-Type: test' -H 'X-Session-ID: 12345' --hangup 5

# Incoming call handling with custom headers in response
sipbot wait --username responder --answer welcome.wav -H 'X-Server-ID: bot-01' -H 'X-Region: US-West'
sipbot wait --username announcer --answer welcome.wav --hangup 10

4. Load Testing (Outbound)

Make 100 calls to a target, with 5 calls per second, playing an audio file for 30 seconds each.

sipbot call -t sip:100@192.168.1.10 --play music.wav --total 100 --cps 5 --hangup 30

5. High-Quality Audio (G.722)

SipBot supports G.722 (16kHz) for high-definition audio. It automatically negotiates the best codec.

# Make a call using G.722 if supported by the remote end
sipbot call -t sip:hd-user@domain --play high_res.wav

6. Call Recording

Record all incoming calls to a specific directory. (Requires recorders path in config.toml)

# In config.toml:
# recorders = "./wavs"

sipbot wait --username recorder-bot

7. Send DTMF Digits During a Call

Make a single call and send DTMF digits interactively from the terminal:

sipbot call -t sip:user@domain -u sipbot --hangup 30
# Type digits (0-9, *, #, A-D) and press Enter to send DTMF
# Press 'q' to quit the DTMF reader

8. Hold/Resume (Re-INVITE) Testing

Test hold/resume re-INVITE flows between two sipbot instances. The caller sends a hold re-INVITE after 4s, then resume after 12s.

# Terminal 1 — Callee (echo mode)
sipbot wait --addr 0.0.0.0:5061 --username bob --echo

# Terminal 2 — Caller (auto hold at 4s, resume at 12s, hangup at 25s)
sipbot call --target sip:bob@127.0.0.1:5061 --username alice \
  --reinvite-flows "4s:hold,12s:resume" --hangup 25

9. Audio Quality Analysis

Enable per-call audio quality analysis to detect clipping, silence, shrill/muffled audio, and sample rate mismatches:

# Outbound call with audio quality monitoring
sipbot call -t sip:user@domain -u sipbot --hangup 30 --audio-quality

# Wait for calls with audio quality monitoring
sipbot wait --username quality-bot --echo --audio-quality

Configuration

Create a config.toml file in the root directory. The configuration allows you to define the behavior for each account.

Example config.toml

# Global settings
addr = "0.0.0.0:5060"           # Local bind address
external_ip = "1.2.3.4"         # External IP for SDP (NAT traversal)
recorders = "/tmp/recorders"    # Directory for recordings (Required for recording)

[[accounts]]
username = "1001"
domain = "sip.example.com"
password = "secretpassword"
register = true                 # Enable registration
reject_prob = 20                # Randomly reject 20% of calls with 480
codecs = ["opus", "g722", "pcmu"]  # Preferred codecs
headers = [                     # Custom SIP headers
    "X-Server-ID: sipbot-01",
    "X-Region: US-West",
    "X-Environment: production"
]

# --- Call Handling Flow ---

# Stage 1: Ringing
# If 'ringback' is a file path, sends 183 Session Progress and plays the file.
# If 'ringback' is "" (empty), sends 183 and plays the built-in ringing.wav, answering when it finishes.
# If 'ringback' is omitted, sends 180 Ringing and waits 'duration_secs'.
[accounts.ring]
duration_secs = 5
# ringback = "sounds/ringback.wav"
# ringback = ""

# Stage 2: Answer
# Answer the call (200 OK) and perform an action.
[accounts.answer]
action = "play"                 # Options: "play", "echo", "local"
wav_file = "sounds/welcome.wav" # Required if action is "play"

# [accounts.answer]
# action = "echo"               # Alternative: Echo test

# [accounts.answer]
# action = "local"              # Alternative: Use local audio device (Mic/Speaker)

# Stage 3: Hangup
# Automatically hang up after the media finishes or a timeout.
[accounts.hangup]
code = 200                      # SIP code (not fully used for BYE yet, mainly for rejection)
after_secs = 10                 # Send BYE after 10 seconds

Configuration Reference

  • addr: (Optional) The local IP and port to bind to. Defaults to 0.0.0.0:35060.
  • external_ip: (Optional) The external IP address to use in SDP offers/answers (useful for NAT).
  • recorders: (Optional) Path to save call recordings.
  • accounts: List of account configurations.
    • username: SIP username.
    • auth_username: (Optional) SIP authentication username.
    • domain: SIP domain/registrar.
    • password: SIP password.
    • proxy: (Optional) SIP proxy server address.
    • register: (Bool) Whether to register with the domain.
    • reject_prob: (Optional) Probability (1-99) to randomly reject incoming calls with 480.
    • cancel_prob: (Optional) Probability (1-99) to randomly cancel outgoing calls.
    • target: (Optional) URI to call on startup (for outbound bot).
    • record: (Optional) Recording file path.
    • srtp_enabled: (Bool) Enable SRTP/SDES.
    • nack_enabled: (Bool) Enable RTP NACK.
    • jitter_buffer_enabled: (Bool) Enable Jitter Buffer.
    • dtmf_flows: (String) Scheduled DTMF digits after answer (e.g., "1s:2,1.5s:#").
    • reinvite_flows: (String) Scheduled hold/resume re-INVITEs after answer (e.g., "5s:hold,10s:resume").
    • codecs: (Array) List of preferred codecs (e.g., ["opus", "g722", "pcmu"]).
    • headers: (Array) List of custom SIP headers to include in INVITE requests and 200 OK responses (e.g., ["X-Custom-Header: value", "X-Call-ID: 12345"]).
    • audio_quality: (Optional) Enable per-call audio quality analysis. Example:
      [accounts.audio_quality]
      enabled = true
      sample_rate_check = true
      clipping_threshold = 0.95
      shrill_threshold = 0.65
      muffled_threshold = 0.15
      silence_threshold_rms = 50.0
      report_interval = 100
    • codecs: (Optional) List of preferred codecs (e.g., ["opus", "g722", "pcmu"]).
    • early_media: Configuration for the early media phase (183).
      • wav_file: (Optional) Path to WAV file.
      • local: (Optional) true to use local audio device for capture and playback.
    • ring: Configuration for the ringing phase.
      • duration_secs: How long to stay in ringing state.
      • ringback: (Optional) Path to WAV file for early media (183).
      • local: (Optional) true to use local audio device for capture and playback.
    • answer: Configuration for the answered phase.
      • action: play, echo or local.
      • wav_file: Path to WAV file (if action is play).
    • hangup: Configuration for ending the call.
      • code: SIP status code (used for rejection if no answer config exists).
      • after_secs: (Optional) Time in seconds to wait before sending BYE.

Benchmarking and Testing

SipBot is designed to facilitate SIP performance testing and benchmarking by simulating multiple callers and callees with customizable behaviors.

Example Scenario

To run a benchmark, you typically need two instances of SipBot: one for caller and another for callee. they will register on sip server with alice and bob respectively.

Callee Configuration (callee.toml)

This bot listens for incoming calls, rings for a few seconds, and randomly rejects 50% of the calls to test error handling.

# Local bind address for the callee
addr = "0.0.0.0:3333" 

[[accounts]]
register = true
proxy = "127.0.0.1:15060" # sip server address
username = "alice"
domain = "127.0.0.1"
password = "123456"
reject_prob = 20   # 20% probability to reject incoming calls

[accounts.hangup]
code = 486         # reject with code 486

[accounts.ring]
duration_secs = 3  # Wait for 3 seconds in ringing state before answering

Caller Configuration (caller.toml)

This bot initiates calls to a target, with a 30% chance of canceling the call before it is answered.

# Local bind address for the caller
addr = "0.0.0.0:4444" 

[[accounts]]
register = true
proxy = "127.0.0.1:15060"
username = "bob"
domain = "127.0.0.1"
password = "123456"
target = "sip:alice@127.0.0.1" # The destination to call

# Probability to randomly cancel calls
cancel_prob = 30

[accounts.hangup]
after_secs = 5     # If the call is answered, hang up (send BYE) after 5 seconds
code = 486         # currectly not used for caller

Note: if cancel_prob is set, caller will randomly deside cancel before or after ringing 50:50.

How to Run

  1. Start the Sip Server

  2. Start the Callee: The callee should be running first to receive calls.

    cargo run -- wait --conf callee.toml
  3. Start the Caller: The caller initiates the calls. You can use --total and --cps to control the load.

    # Make 100 total calls, with a rate of 3 calls per second
    sipbot --conf caller.toml call --total 100 --cps 3

License

MIT

About

A simple SIP answer/call cli tool with media

Resources

Stars

17 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages