Advanced 15 min SIP 488

488 Not Acceptable Here — Codec Mismatch

Belirtiler

- SIP calls fail during setup with 488 Not Acceptable Here — the INVITE is sent but no ringing occurs and the call is rejected immediately after SDP negotiation
- Audio-only calls work but video calls consistently receive 488 when attempting to negotiate a video codec to an endpoint that does not support video
- Calls between two endpoints on the same PBX succeed, but calls crossing a SIP trunk to a different carrier fail with 488 — indicating a codec or SRTP policy difference
- The SIP INVITE body contains an SDP offer listing available codecs; the 488 response includes a warning header or SDP answer with an empty media section indicating no codec intersection
- Enabling a legacy codec (G.711 PCMU/PCMA) on both sides resolves the 488, confirming the issue is codec intersection, not signaling

Kök Nedenler

  • Caller and callee are configured with incompatible audio codecs — for example, the caller offers only Opus and G.722 while the callee only accepts G.711 (PCMU/PCMA), leaving no intersection in the SDP offer/answer exchange
  • A SIP proxy or SBC between the endpoints is stripping or modifying the SDP body — removing codec entries from the m= line or changing the payload type numbers so the callee sees an SDP offer with codecs it does not recognize
  • Codec licensing restrictions cause the PBX to offer only a subset of codecs — some PBX vendors license G.729 or G.722 separately and may silently omit them from the SDP if the license is absent
  • SRTP (encrypted media) is required by one endpoint (e.g., a WebRTC client that mandates DTLS-SRTP) but the other side only supports plain RTP, causing the entire media section to be rejected
  • A video call is attempted to an audio-only SIP phone — the INVITE SDP contains a video m= line, the phone responds 488 because it cannot negotiate any video codec even though audio would succeed

Tanı

**Step 1: Inspect the INVITE SDP and the 488 response**
```bash
sngrep -d eth0 port 5060
# Select the INVITE → press Enter to expand
# Read the SDP offer in the INVITE body:
# m=audio 20000 RTP/AVP 0 8 18
# a=rtpmap:0 PCMU/8000
# a=rtpmap:8 PCMA/8000
# a=rtpmap:18 G729/8000
# Then read the SDP in the 488 response (if present)
# or look for a Warning: header
```

**Step 2: Check codec configuration on both endpoints**
```bash
# Asterisk — show codec list for a peer
asterisk -rx 'sip show peer <extension> | grep Codecs'
# Expected output: Codecs: (ulaw|alaw|g722|g729)
# If 'none' or only proprietary codecs → codec problem
```

**Step 3: Verify SRTP/RTP compatibility**
```bash
# In the SDP, look for the transport field:
# m=audio 20000 RTP/AVP 0 → plain RTP
# m=audio 20000 RTP/SAVP 0 → SRTP required
# m=audio 20000 UDP/TLS/RTP/SAVPF → DTLS-SRTP (WebRTC)
# Mismatch between RTP/AVP and RTP/SAVP always causes 488
```

**Step 4: Test with a minimal SDP (G.711 only)**
```bash
# In Asterisk sip.conf or pjsip.conf, temporarily force G.711 only:
# allow=ulaw
# disallow=all (first line)
# If the call succeeds → codec intersection was the issue
asterisk -rx 'sip reload'
```

**Step 5: Check if an intermediate SIP proxy is mangling the SDP**
```bash
# Compare SDP in INVITE as sent vs SDP received at the callee
# Capture on both sides:
# Caller side: tcpdump -i eth0 -w caller-side.pcap port 5060
# Callee side: tcpdump -i eth0 -w callee-side.pcap port 5060
# Open both in Wireshark and compare m= lines
# Differences indicate SDP mangling by the proxy
```

Çözüm

**Fix 1: Configure a common baseline codec on both endpoints**
```ini
# Asterisk sip.conf — enable G.711 as universal fallback
[general]
disallow=all
allow=ulaw ; G.711 PCMU — universally supported
allow=alaw ; G.711 PCMA — European standard
allow=g722 ; HD voice, widely supported
allow=g729 ; Bandwidth-efficient (license required)
```

**Fix 2: Enable codec transcoding on the PBX**
```bash
# Asterisk — ensure transcoding modules are loaded
asterisk -rx 'module show like codec'
# Load Opus transcoding (requires asterisk-opus package)
asterisk -rx 'module load codec_opus.so'
# With transcoding, the PBX can bridge Opus (WebRTC) to G.711 (legacy phone)
```

**Fix 3: Align SRTP policy between endpoints**
```ini
# Asterisk pjsip.conf — disable SRTP if the trunk does not support it
[my-trunk]
type=endpoint
media_encryption=no ; plain RTP
# Or require SRTP on both sides:
media_encryption=sdes ; SRTP with SDES key exchange
```

**Fix 4: Strip video from audio-only calls**
```ini
# Asterisk extensions.conf — force audio-only before dialing
exten => _X.,1,Set(CHANNEL(videocodec)=)
same => n,Dial(PJSIP/${EXTEN}@trunk,30)
```

**Fix 5: If a proxy is mangling SDP — bypass or configure it**
```ini
# On FreeSWITCH — disable SDP mangling in the SBC profile
<param name='inbound-bypass-media' value='false'/>
<param name='bypass-media-after-bridge' value='false'/>
# Or configure the proxy to pass SDP transparently (passthrough mode)
```

Önleme

- **Always include G.711 (PCMU and PCMA) in every codec list** as a universal fallback — it is supported by virtually every SIP endpoint and prevents 488 from codec intersection failures
- **Document codec policies per trunk** — maintain a table of which codecs each SIP carrier or internal system supports to catch mismatches before provisioning new devices
- **Test new endpoint onboarding with a loopback call** to a known-good extension before putting the device into production, confirming codec negotiation succeeds end to end
- **Configure codec preference order** (most preferred first) on the PBX so that higher-quality codecs are selected when both sides support them, with G.711 as the guaranteed fallback
- **Align SRTP policies across your entire SIP infrastructure** — decide whether encryption is mandatory, optional, or disabled, and enforce it consistently so mixed-mode SRTP/RTP boundaries do not surface as 488 errors at call setup time

İlgili Durum Kodları

İlgili Terimler