{"id":50665974,"url":"https://github.com/csicar/rsipstack-server","last_synced_at":"2026-06-08T06:05:52.290Z","repository":{"id":361798182,"uuid":"1224967380","full_name":"csicar/rsipstack-server","owner":"csicar","description":"Example sip server build on top of rvsip, rtp and sdp","archived":false,"fork":false,"pushed_at":"2026-06-01T10:22:10.000Z","size":80,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-01T11:04:22.883Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/csicar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-29T20:12:29.000Z","updated_at":"2026-05-24T19:43:20.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/csicar/rsipstack-server","commit_stats":null,"previous_names":["csicar/rsipstack-server"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/csicar/rsipstack-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csicar%2Frsipstack-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csicar%2Frsipstack-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csicar%2Frsipstack-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csicar%2Frsipstack-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/csicar","download_url":"https://codeload.github.com/csicar/rsipstack-server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csicar%2Frsipstack-server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34050264,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-08T06:05:30.587Z","updated_at":"2026-06-08T06:05:52.267Z","avatar_url":"https://github.com/csicar.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rsipstack-server\n\nA generic VoIP server library built with Rust using [rsipstack](https://crates.io/crates/rsipstack). Define custom audio processing via an actor-style interface with channels.\n\n## Features\n\n- **SIP Protocol Support**: Full SIP call handling via rsipstack\n- **Codec Support**: Opus, PCMU (G.711 μ-law), PCMA (G.711 A-law)\n- **Actor-Style Audio Interface**: Receive/send audio via tokio channels\n- **Pluggable Audio Handlers**: Implement the `AudioHandler` trait for custom processing\n- **Concurrent Calls**: Handles multiple simultaneous calls\n- **NAT Traversal**: Optional external IP configuration\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│                       SIP Server                            │\n├─────────────────────────────────────────────────────────────┤\n│  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐   │\n│  │ SIP Endpoint │───▶│ Dialog Layer │───▶│ Call Handler │   │\n│  │  (rsipstack) │    │  (rsipstack) │    │              │   │\n│  └──────────────┘    └──────────────┘    └───────┬──────┘   │\n│                                                  │          │\n│                                          ┌───────▼───────┐  │\n│                                          │ Media Session │  │\n│                                          │   (per call)  │  │\n│                                          └───────┬───────┘  │\n│                                                  │          │\n│                           ┌──────────────────────┼──────────┤\n│                           │                      │          │\n│                     ┌─────▼─────┐          ┌─────▼─────┐    │\n│                     │ audio_in  │          │ audio_out │    │\n│                     │ (channel) │          │ (channel) │    │\n│                     └─────┬─────┘          └─────▲─────┘    │\n│                           │                      │          │\n│                           └──────────┬───────────┘          │\n│                                      │                      │\n│                              ┌───────▼───────┐              │\n│                              │ AudioHandler  │              │\n│                              │ (your impl)   │              │\n│                              └───────────────┘              │\n└─────────────────────────────────────────────────────────────┘\n```\n\n## Usage\n\nAdd to your `Cargo.toml`:\n\n```toml\n[dependencies]\nrsipstack-server = \"0.1\"\n```\n\n### Basic Example\n\n```rust\nuse rsipstack_server::{\n    async_trait, mpsc, AudioFrame, AudioHandler,\n    CancellationToken, ServerConfig, SipHeaders, SipServer\n};\n\n// Define your audio handler\nstruct EchoHandler;\n\n#[async_trait]\nimpl AudioHandler for EchoHandler {\n    async fn process(\n        \u0026self,\n        mut audio_in: mpsc::UnboundedReceiver\u003cAudioFrame\u003e,\n        audio_out: mpsc::UnboundedSender\u003cAudioFrame\u003e,\n        cancel_token: CancellationToken,\n        _headers: SipHeaders,\n    ) {\n        loop {\n            tokio::select! {\n                _ = cancel_token.cancelled() =\u003e break,\n                frame = audio_in.recv() =\u003e {\n                    match frame {\n                        Some(f) =\u003e { let _ = audio_out.send(f); }\n                        None =\u003e break,\n                    }\n                }\n            }\n        }\n    }\n}\n\n#[tokio::main]\nasync fn main() -\u003e anyhow::Result\u003c()\u003e {\n    let config = ServerConfig {\n        port: 5060,\n        rtp_start_port: 10000,\n        ..Default::default()\n    };\n\n    // Pass a factory closure that creates handlers for each call\n    let server = SipServer::new(config, || EchoHandler).await?;\n    server.run().await?;\n    Ok(())\n}\n```\n\n### AudioHandler Trait\n\nThe `AudioHandler` trait is the core interface for custom audio processing:\n\n```rust\n#[async_trait]\npub trait AudioHandler: Send + Sync {\n    async fn process(\n        \u0026self,\n        audio_in: mpsc::UnboundedReceiver\u003cAudioFrame\u003e,\n        audio_out: mpsc::UnboundedSender\u003cAudioFrame\u003e,\n        cancel_token: CancellationToken,\n        headers: SipHeaders,\n    );\n}\n```\n\n- `audio_in`: Receives `AudioFrame`s from the remote peer\n- `audio_out`: Send `AudioFrame`s to the remote peer\n- `cancel_token`: Signals when the call ends\n- `headers`: SIP headers from the INVITE request\n\n### AudioFrame\n\n```rust\npub struct AudioFrame {\n    /// Decoded PCM samples at 48kHz, 960 samples per frame (20ms)\n    pub samples: Vec\u003ci16\u003e,\n}\n```\n\nThe library handles all RTP details (timestamps, sequence numbers, SSRC) internally.\nYou only work with decoded PCM audio samples.\n\n## Examples\n\n### Echo Server\n\nA complete echo server example is included:\n\n```bash\ncargo run --example echo_server -- --port 5060 --rtp-start-port 10000\n```\n\n### Testing with sipp\n\n```bash\nsipp -sn uac \u003cserver-ip\u003e:5060 -m 1\n```\n\n### Testing with a SIP softphone\n\n1. Configure your softphone for direct calling (no registration)\n2. Call `sip:server@\u003cserver-ip\u003e:5060`\n3. The server will process audio according to your handler\n\n## Configuration\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `port` | 5060 | SIP listening port |\n| `bind_addr` | auto | Bind address (defaults to first non-loopback interface) |\n| `external_ip` | none | External IP for NAT traversal |\n| `rtp_start_port` | 10000 | Starting port for RTP media (even number) |\n\n## Project Structure\n\n```\nrsipstack-server/\n├── src/\n│   ├── lib.rs            # Library entry point, public API\n│   ├── server.rs         # SIP server setup and request routing\n│   ├── call_handler.rs   # INVITE handling, media session setup\n│   ├── media/\n│   │   ├── session.rs    # RTP socket management, audio channels\n│   │   ├── rtp.rs        # RTP packet parsing and building\n│   │   └── sdp.rs        # SDP offer/answer generation\n│   └── audio/\n│       └── handler.rs    # AudioHandler trait definition\n└── examples/\n    └── echo_server.rs    # Echo server example\n```\n\n## Use Cases\n\n- Audio echo/loopback testing\n- Audio recording\n- Text-to-speech playback\n- Audio mixing/conferencing\n- Voice activity detection\n- AI voice assistants\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcsicar%2Frsipstack-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcsicar%2Frsipstack-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcsicar%2Frsipstack-server/lists"}