Howwise RSS
VoIP & Phone Systems10 min read

Softphone Mobile SIP Push Notifications: Fix Missed Calls

Short answer

Softphone mobile SIP push notifications fix missed calls by waking a suspended app through FCM or APNs when an INVITE arrives, so the phone needs no constant keepalives. Without push, iOS and Android suspend the socket and CGNAT drops the mapping.

Key takeaways
  • Missed calls on mobile come from three separate failures: a suspended app, an expired NAT mapping, or a network handover that kills the connection.
  • Standard Asterisk has no built-in push, so you need a push-capable proxy or a vendor client and PBX pair that supports it.
  • A registration expiry of 120 to 600 seconds with push is a good balance; 30 to 60 seconds drains battery and 3600 seconds hides dead NAT mappings.
  • Use TLS on port 5061 with SDES SRTP, direct_media=no and rewrite_contact=yes for remote extensions, and protect the PBX with fail2ban and IP rules.
  • Capture the traffic with sngrep: INVITE sent with no reply means a dead path or sleeping app, while a re-REGISTER after the INVITE means push was too slow.

Why do mobile SIP softphones miss incoming calls?

A SIP phone on a desk keeps a socket open and waits for INVITEs. A phone in a pocket cannot. iOS suspends background apps within seconds, and Android applies Doze and App Standby, which defer network access. Vendor battery managers on Xiaomi, Huawei and Samsung devices go further and kill the process outright. When the socket is gone, the INVITE from the PBX has nowhere to land.

The second cause sits in the network. On 4G, carrier-grade NAT (CGNAT) creates a mapping when the phone sends REGISTER, and it deletes idle UDP mappings quickly, often in roughly 30 to 120 seconds. TCP and TLS mappings often last a few minutes. After the mapping expires, the PBX still holds a contact that points at a dead public address and port, and the INVITE is silently dropped.

The third cause is handover. When the phone moves from Wi-Fi to 4G, its IP address changes. Existing TCP or TLS connections break, and the PBX keeps the old contact until it expires or a qualify check fails. Registrations only recover when the client notices and registers again.

Failure modeTypical symptomHow to confirm
Suspended or killed appPhone rings only after you open the appINVITE leaves the PBX, no response; contact is still shown as reachable
Expired NAT mappingWorks for a minute after registering, then calls failContact status turns Unavailable after a qualify; calls work right after a fresh REGISTER
Network handoverCalls fail after leaving Wi-Fi or entering a buildingContact source IP differs from the phone's current IP; no new REGISTER seen

How do softphone mobile SIP push notifications actually work?

Push splits the job in two. The app keeps no connection open. Instead it registers its push token with the PBX or a push proxy. When a call arrives, the proxy sends a message through FCM on Android or APNs on iOS, which the operating system is allowed to deliver even to a sleeping device.

On iOS this must be a PushKit VoIP push, which wakes the app and obliges it to report the call to CallKit immediately. On Android it should be a high-priority FCM data message, since normal-priority messages can be delayed by Doze.

  1. A caller dials the extension and the PBX or proxy receives the INVITE.
  2. The proxy finds the stored contact, sees it carries push parameters, and sends the push to FCM or APNs.
  3. The OS wakes the app, which opens a connection and sends a fresh REGISTER.
  4. The proxy forwards the held INVITE to the new contact, and the phone rings.
  5. The user answers and media flows.
Warning: There is a timing race. Waking the app, opening TLS and re-registering takes roughly 1 to 5 seconds on a good network and longer on a poor one. If the proxy forwards the INVITE once and does not hold it, the first attempt can time out. A good push proxy buffers the INVITE until the new REGISTER arrives. Plain Asterisk does not do this, which is why a ring time of 25 to 30 seconds and a retry matter.

Which push options work with Asterisk and FreePBX?

Standard Asterisk has no built-in push gateway. The res_pjsip_notify module only sends NOTIFY messages and cannot wake an app. You need a component that talks to FCM and APNs, and the client has to be built to work with that component.

The client and the push backend must match. A generic softphone from an app store cannot receive push from a PBX that does not know its token format.

OptionHow it delivers pushNotes
FreePBX with Sangoma Connect (formerly Zulu) or commercial UCP modulesSangoma-operated push service tied to the Sangoma clientEasiest for FreePBX; client and PBX must be the supported pair and licensed
Kamailio or OpenSIPS in front of Asterisk with a push moduleProxy holds the INVITE, sends push, forwards after re-REGISTERMost flexible and correct; needs SIP proxy skills and your own push credentials or a compatible client
Linphone flexisipFlexisip push notification module, used with the Linphone appOpen source; typically placed as a front proxy for Asterisk
Grandstream Wave or Zoiper with a push serviceVendor push relay that the client registers withCheck that the vendor supports your PBX type and region before committing
Bria or provider-hosted push (for example from a SIP trunk provider)Provider-side push proxyWorks when the extension is hosted by the provider, not necessarily your own Asterisk
3CX-style appsBuilt in, but tied to that PBXNot usable with Asterisk
Tip: Before buying licences, test one extension from the real phone on 4G with the app fully closed. A demo on Wi-Fi with the app in the foreground proves nothing.

What PJSIP settings keep a remote extension reachable?

Registration expiry is a trade-off. Very short values such as 30 to 60 seconds keep the NAT mapping fresh but wake the radio constantly and drain the battery. Values like 3600 seconds are easy on the battery but hide a dead mapping for up to an hour. With push, 120 to 600 seconds is a sensible range because the keepalive is no longer what makes calls arrive. Without push, stay near the low end and keep the keepalive below the carrier timeout.

On Asterisk, qualify_frequency sends OPTIONS to the contact and keeps the mapping alive while also marking dead contacts unavailable. Values of 30 to 60 seconds suit UDP behind CGNAT. Clients can also send a double CRLF ping per RFC 5626, which is cheaper than a full OPTIONS exchange.

The settings below are a starting point for a remote extension using TLS and SDES SRTP. Names follow Asterisk PJSIP; adjust the endpoint ID and secrets.

[transport-tls]
type=transport
protocol=tls
bind=0.0.0.0:5061
cert_file=/etc/letsencrypt/live/pbx.example.com/fullchain.pem
priv_key_file=/etc/letsencrypt/live/pbx.example.com/privkey.pem
method=tlsv1_2
external_signaling_address=pbx.example.com
external_media_address=203.0.113.10
local_net=192.168.1.0/24

[2001]
type=endpoint
transport=transport-tls
context=from-internal
disallow=all
allow=opus,ulaw
auth=2001
aors=2001
direct_media=no
rewrite_contact=yes
force_rport=yes
rtp_symmetric=yes
rtp_keepalive=15
media_encryption=sdes
media_encryption_optimistic=no
timers=yes

[2001]
type=aor
max_contacts=1
remove_existing=yes
qualify_frequency=45
minimum_expiration=120
default_expiration=300
maximum_expiration=600

[2001]
type=auth
auth_type=userpass
username=2001
password=Use-A-Long-Random-Secret-Here
Tip: remove_existing=yes with max_contacts=1 makes a new registration replace the stale one, which is exactly what you want after a Wi-Fi to 4G handover. Allow more contacts only if the user really has two devices registered.

TLS, SRTP, VPN or WebRTC: which transport should I choose?

TLS on 5061 is the sensible default for plain SIP over the internet. It resists casual interception, and a TCP-based connection typically survives CGNAT longer than idle UDP. Use a valid public certificate such as Let's Encrypt so clients verify the server without installing custom certificates. SDES SRTP encrypts media but exposes keys in signalling, so it is only acceptable over TLS. DTLS-SRTP is used by WebRTC clients. ZRTP has little support among softphones.

TLS does not solve handover. A changed IP breaks the TCP session, so the client must detect the change and register again. Good clients do this on network-change events.

A VPN such as WireGuard keeps the PBX private, so no SIP is exposed. The costs are battery use, the OS sometimes stopping the VPN, and the fact that a sleeping app still needs push to ring reliably. WireGuard's PersistentKeepalive of 25 seconds helps NAT but costs power. Use a VPN when push is unavailable or policy forbids exposing SIP.

ApproachBatteryReliabilitySecuritySetup effort
Push-enabled softphone over TLS/SRTPGoodHighGoodMedium to high
Plain SIP over TLS with short keepalivePoor to fairMedium; fails when app is killedGoodLow
VPN (WireGuard or OpenVPN) plus softphoneFair to poorMedium; still needs push for sleeping appsVery good, PBX not exposedMedium
WebRTC over WSS clientFairMedium; browser or app must stay awake unless push-backedGoodMedium

How do I harden an internet-exposed PBX and set up phones?

Once remote phones connect directly, the PBX is a target within minutes. Never leave SIP on UDP 5060 open to the world without protection.

Use strong random secrets, disable anonymous and guest calls (allow_guest=no in the PJSIP general settings), and prefer TLS 5061 over 5060. Run fail2ban against the Asterisk security log, restrict by country or IP where possible, and consider placing Kamailio or an SBC in front for rate limiting. Open only the ports you need, including your RTP range (18000 to 20000 on FreePBX by default; check Settings > Asterisk SIP Settings if you have changed it).

The example below opens TLS signalling and the matching default FreePBX RTP range. If you change the range in Asterisk SIP Settings, change the firewall rule to match.

  1. Android: set the app's battery usage to Unrestricted, allow notifications, and turn off any vendor optimization (Xiaomi Autostart, Huawei App launch manual management, Samsung Never sleeping apps).
  2. iOS: enable Background App Refresh and notifications for the app, allow Critical or Time Sensitive alerts where offered, and avoid Low Power Mode on phones that must ring.
  3. Set the app to start on boot, and keep Wi-Fi on during sleep so home networks do not drop the phone.
  4. Prefer Opus or G.711 over G.729, which needs licences and degrades under packet loss, and keep the RTP range open and forwarded.
ufw allow 5061/tcp
ufw allow 18000:20000/udp
Warning: Exposing SIP without fail2ban or an allow-list typically leads to brute-force attempts and toll fraud. Test your firewall rules from outside the network before going live.

How do I troubleshoot which failure is causing missed calls?

Work from the PBX outward. First confirm what Asterisk believes about the phone, then look at the packets. Test the same phone on 4G and on Wi-Fi to separate NAT problems from app problems.

The diagnosis in the capture is usually clear. If the INVITE leaves the PBX and nothing comes back, the path is dead or the app is asleep. If a fresh REGISTER arrives only after the INVITE, push worked but too slowly. If the contact's source IP is not the phone's current address, a handover left a stale contact.

  1. Run pjsip show contacts and check status and RTT; Unavailable or a very old registration points to an expired mapping.
  2. Turn on pjsip set logger on and place a test call with the app closed.
  3. Capture with sngrep and watch for INVITE, 100 Trying, 180 Ringing or a 408 Request Timeout and 480 Temporarily Unavailable.
  4. Compare timestamps between the INVITE and the contact's last REGISTER.
  5. Repeat on 4G, then on Wi-Fi, then after switching networks mid-session.
  6. Check the ring time (Dial timeout of 25 to 30 seconds) so voicemail does not answer before the push-woken app can ring.
asterisk -rx "pjsip show contacts"
asterisk -rx "pjsip show endpoint 2001"
asterisk -rx "pjsip set logger on"
asterisk -rx "rtp set debug on"
sngrep -d any port 5061 or port 5060

Common questions

Why does my iPhone SIP softphone not ring when the app is closed?

iOS suspends the app and closes its socket, so the INVITE is never received. Only a PushKit VoIP push from a push-capable PBX or proxy can wake it. A client that registers directly with plain Asterisk and no push backend will not ring when closed.

Does FreePBX have mobile push notifications built in?

Open-source Asterisk does not. FreePBX offers push through Sangoma's commercial clients and services, such as Sangoma Connect, which depend on the matching modules and licensing. Other clients need a separate push proxy in front of the PBX.

Why does a SIP client drain the battery on 4G?

A short registration expiry and frequent keepalives wake the cellular radio again and again. Each wake-up keeps the modem in a high-power state for several seconds. Push lets the client stop frequent keepalives and use longer expiry values.

What keepalive interval should I use behind carrier NAT?

Keep it below the shortest NAT timeout you expect, which can be around 30 seconds for UDP on some carriers. A qualify_frequency of 30 to 60 seconds is common, and TCP or TLS can often use longer intervals. Measure on your own carrier by finding when calls start failing.

Do I still need push if I use a VPN?

Yes, for reliable ringing. The VPN protects traffic and hides the PBX, but the OS can still suspend the app and its tunnel, so incoming INVITEs may not be handled. Push is what wakes the device.

Related topics:sippush notificationsasteriskfreepbxsoftphone