Each node reports itself, and carries three limits that run out
independently. All three are enforced: a call past one is refused before it
is answered, so the calls already up keep their audio.
A relayed call costs 0 units. Opus against G.711 costs 2, G.729 or iLBC
against Opus costs 4, G.726 against G.711 costs 1, and a virtual agent adds 3 — so the transcode figure is what a node
actually runs out of, and a node can be comfortable on channels and out of
budget. The Overview shows each as in use / limit.
The audio-streaming module this project builds is free for ten concurrent
streams, and a call past the module’s own limit is not refused by it — it is
answered and silent. That is why the node refuses first, and why the
default is 8: live assist draws on the same ten.
When the machine itself is loaded
A counted limit can only see calls. On a box shared with anything else — a database, a mail server, other sites — a neighbour taking a core is not a channel, and every gauge still reads fine while audio breaks on every call at once. So the node also watches the machine:
Calls this platform chose to make — campaigns, API-placed AI calls — are shed
first; a person who clicked to call is refused only when everything is. The
Overview shows a badge while it is happening, with what the machine was doing.
An API call refused this way answers
503 node_busy with Retry-After: 30:
“try again shortly”, as distinct from 422, “this request is wrong”.
Keeping transcode low
Both legs agreeing on a codec lets the switch relay rather than transcode. That is the difference between near-zero CPU and the most expensive thing the system does — see extensions.Which codecs a node speaks
Opus and G.711 always. G.729, iLBC and G.726 are separate modules, built with the switch (deploy/node/build-g729.sh, deploy/node/build-codecs.sh)
and loaded only where they are installed. A node without one still takes the
call: every codec profile and every sensible trunk list keeps G.711 behind its
first choice, so the call connects in G.711 instead. verify.sh names any
module that is installed and not loaded.
On a trunk they are ticked, not typed — see
a trunk’s codecs. Through the API the names
are G729, iLBC and G726-32: the rate is part of the name, and a bare
G726 is refused because the switch would drop it from the offer without saying
so. When a trunk is pinned to a node, its editor says so if a ticked codec’s
module is not loaded there.
Admission control
A node refuses new calls beyond its configured session limit rather than degrading everything already in progress. The switch’s own limit is per second as well as total, and it is shared with everything arriving inbound — which is why a wide outbound campaign competes with your tenants’ incoming calls. The same is true of a carrier: a trunk’s channel limit counts both directions, because that is what the carrier contracted. Where a dialling burst must not be able to fill it, set the trunk’s outbound channel limit as well — it caps the outgoing share and reserves the rest for calls arriving. See trunks.The name desk phones use
A node’s Handset server name (e.g.sip.firet.one) is what every
extension’s handset settings name as the server. It is display only — nothing
is written to the switch — but a phone using TLS on 5061 needs it: the phone
checks the certificate against the server it was given, and a certificate names
a host, not an address. Leave it empty and extensions show the advertised
address, which is fine for UDP and TCP on 5060.
The switch listens for SIP on IPv4 only. A name with an IPv6 (AAAA) record
sends a phone that prefers IPv6 to an address nothing answers on.
An organisation’s handsets are shown the node chosen on the organisation, or the
only node there is. With several nodes and none chosen, the handset settings say
so instead of guessing.