Skip to content

Calls

What works without a server – and what does not

Section titled “What works without a server – and what does not”

It helps to separate two things:

Signalling – ringing, accepting, declining, hanging up – runs over every transport. So it also works completely offline, over Bluetooth and Wi-Fi Direct.

The media – sound and picture – run over native WebRTC tracks. That requires a WebRTC connection.

On the same Wi-Fi both come about without a server: the connection handshake also runs over the ordinary transports, encrypted. Voice and video calls at home or in an office therefore work entirely serverlessly.

Over the internet the brokering needs a point of contact and – as with any WebRTC service – an additional forwarding server behind strict mobile NAT. The connection details exchanged in the process are themselves already end-to-end encrypted; no call content ever travels through the brokering.

Video calls run in portrait at 30 frames per second, hardware accelerated. The resolution is negotiated by both sides together: Full HD (1080×1920) only when both devices are clearly capable – otherwise 720p (720×1280). The sender therefore caps to the weaker partner, so it does not have to decode more than it can manage.

On top of that there is a bitrate cap per tier and permission for WebRTC to reduce resolution and frame rate under CPU or network load. For smooth 1080p roughly 2–4 Mbit/s should be available in each direction.

Honestly, from measurement: 720p reduces bandwidth and encoder input, but it is no cure-all for the CPU load of a video call. On a mid-range device the load spreads over encoder, rendering, network, camera and audio – such a device stays at its real-time limit during a video call.

During the call: switch camera, turn the camera off, your own preview as a small picture-in-picture. Voice calls use Opus with echo cancellation and a jitter buffer.

Every call appears in the chat as an entry – outgoing, incoming, declined, missed, no answer, each separately for voice and video.

An internal field test found the only finding of the 0.4x series with a privacy dimension here, and it belongs on this page:

Previously, plain data connections negotiated audio as well, and the answering side attached its microphone to every such negotiation. A device could therefore unintentionally stream microphone audio to the contact over the – encrypted – data channel. On top of that, the audio session stayed open after hanging up.

No third party got to hear any of it; the sound went encrypted to the contact and nowhere else. It was a clear malfunction all the same.

It is fixed like this:

  • Data connections negotiate no media whatsoever any more.
  • Your own tracks are attached only to the partner of your own active call, bound tightly to the identifier of that specific call.
  • The call connection is closed completely when you hang up.

Measured on two devices: exactly one active voice session per device during the call, zero after hanging up – even after a long wait.

A second finding from the same round: accept and decline from the call notification carried no call identifier. Android re-delivers task intents from the overview – if such a stale intent met an offer that happened to be ringing, a call was accepted without being asked.

Today accept and decline are bound firmly to the identifier of their call. Old intents without a matching identifier fizzle out harmlessly.

  • No group calls.
  • Over the internet the brokering is a central point – anyone who does not want that calls on the local network or runs the brokering themselves.
  • Call signals carry no proof of freshness. A network observer can re-deliver recorded signals; at worst that disrupts an ongoing call. The accept path is additionally protected against repeated intents.