sidetone

How it works

It sits in the middle of every call.

sidetone is a back-to-back user agent with its own media relay: both legs of every call, and the audio, pass through it. That costs more than a proxy that points two ends at each other, and it is what makes the call records accurate, NAT traversal reliable, and the PBX features possible in the same program.

Phones and browsers on one side, a provider on the other, sidetone in the middle of every call Desk phones and browsers register over UDP, TCP, TLS, WS on your network, or at home sidetone one binary, one data file Your provider a SIP trunk: your numbers, the outside world SIP + audio SIP + audio both legs of the call, and the audio, pass through the middle

Behind NAT, each peer is told the address it can reach.

A phone on your network is told your address on that network; a provider on the internet, or a phone at home, is told the public one. The public address is learned from what the provider saw your registration come from, so there is nothing to look up and nothing to configure unless the server has no trunk that registers.

Configuration

A snapshot, swapped whole.

Everything operational lives in the database behind the REST API: users, trunks, routes, numbers, groups, queues, menus, hours, settings. A write is committed, the configuration is rebuilt, and the new snapshot is published, all under one lock; every new call reads the current one, and a call already in progress keeps the one it started with. That is why nothing restarts, and why saving a setting never drops a call.

What a server needs before it has a database, it takes from the command line or the environment: where to listen, where the data goes, and the first administrator's token.

Built from

Nothing to install beside it.

  • Written in Go; one static binary, no CGO
  • SQLite inside it: no database server
  • REST API, described at /openapi.json
  • Prometheus metrics and structured logs
  • The recent log and SIP messages on a debug page
  • Credentials kept as hashes; the API on localhost unless you say otherwise
  • G.711 always, G.722 where both ends have it; no transcoding
  • SRTP per leg; WebRTC for browsers with DTLS-SRTP

The design document in the repository says why each of these was chosen, and what was rejected. Read it before proposing a feature; most of the obvious ones have been considered.