ProCat Solutions
Silence on the line: what SIP, RTP and a PSTN bridge taught us
A customer support system pulled us into telephony. Codecs, one-way audio behind NAT, SIP trunks, IVR, WebRTC and how we measure call quality.
When a call connects and only one party can hear the other, the culprit is almost always NAT. We learned that in the first months of this year, when a customer support system needed inbound and outbound calls wired into an existing web application. Until then we had only known telephony from the outside. Anyone who has worked with VoIP for years will find little new here. A web developer starting out may save a few weeks.

It looks like HTTP. It isn’t
SIP (Session Initiation Protocol) is a text-based request-response protocol with headers and status codes, so a web developer assumes they understand it. But SIP only handles setting up and tearing down the call (INVITE, ACK, BYE). The audio travels on an entirely separate channel, RTP, over UDP. What ties the two together is the IP address and port described in the SDP, and that is exactly where most failures happen.
Codecs are the second surprise. G.711 (alaw, mulaw) runs uncompressed at 64 kbit/s and every device understands it. G.722 offers wider bandwidth. Opus comes from the WebRTC world and copes well with network jitter. If the two sides cannot agree on a common codec, the call connects and there is silence. If something in the middle transcodes, it eats CPU and adds latency. You need to know this before sizing any infrastructure.
One-way audio
The classic failure: the call connects, one party hears the other, the other hears nothing. The private IP address in the SIP message is unreachable from the far side, and the RTP packets go to the wrong place.
On every deployment we check that:
- the SIP server’s external address is set explicitly, not guessed from the network interface,
- the RTP port range (typically several thousand UDP ports) is open on the firewall, and the range on the server matches the firewall rule,
- SIP components running in Docker use host networking, or the RTP range is explicitly published; port forwarding on a bridge network across several thousand UDP ports is a bad idea,
- the WebRTC side has a STUN server and, when needed, a TURN server, because a browser behind symmetric NAT cannot get out any other way.
Settings such as rtp_symmetric and other “trust the address the packet came from” options help a lot. They do not fix everything.

Trunk and bridge
To call and receive real phone numbers, a system needs a connection to the public switched telephone network (PSTN). Today an operator almost always provides it over a SIP trunk: we get a SIP account or IP-based authentication, and the operator forwards calls into the traditional network.
For us, the “PSTN bridge” is the component sitting between our own system (web application, WebRTC clients, audio processing) and the SIP trunk. It routes calls, normalises number formats (E.164), handles authentication and writes call detail records (CDRs). The trunk credentials must never reach the client: the browser registers with the bridge, and only the bridge talks to the operator.
Choosing a trunk means testing several providers. Audio quality, call setup time and error-code handling differ significantly, and the documentation rarely matches reality.
Press one
Interactive voice response (IVR) is, technically, a state machine: it plays audio files, waits for DTMF tones and routes accordingly. Three things matter in practice:
- DTMF can arrive in three ways (in-band as audio, as an RFC 2833 RTP event, or as a SIP INFO message), and if two elements of the chain negotiated different ones, the keypress is lost,
- we keep the IVR menu structure in the application database, outside the PBX configuration, so the customer can edit it themselves,
- the “nobody picks up” case matters at least as much as a successful connection: voicemail, a callback request or forwarding must always be defined.
Where call routing meets the web application (who is calling, which customer, who should take the call) is where telephony and software development converge. It is also where we see the most business value.
By the numbers
In telephony, “it works” is not a yes-or-no answer. A call can connect and still stutter, lag or echo. On every call we measure and log:
- packet loss, jitter and round-trip time from the RTCP reports,
- call setup time (from INVITE to 200 OK),
- why the call ended (normal, rejected, timeout, network error), with the SIP status code,
- the estimated MOS value, so trends can be tracked with a single number.
The data is stored both as Prometheus metrics and in the call record. When a complaint comes in, we can look up exactly what happened.
Telephony is far less forgiving than the web. There is no reload button, and the user hears straight away when something is wrong. The quality of the infrastructure really matters here, which is what makes the field attractive. In the coming months we will also write about GSM modems and SMS sending, which came up alongside voice.