diff --git a/docs/evidence/third-sip-capture-root-cause-20260917.json b/docs/evidence/third-sip-capture-root-cause-20260917.json new file mode 100644 index 0000000..dc5e1c3 --- /dev/null +++ b/docs/evidence/third-sip-capture-root-cause-20260917.json @@ -0,0 +1,91 @@ +{ + "record_version": "1.0", + "recorded_at_utc": "2026-09-17T06:37:48Z", + "scope": "packet-captured root-cause validation for mka75518625770806", + "code_commit": "668c12e", + "deployment": { + "region": "cn-beijing", + "instance_id": "i-2zeimnh6hq53q4srr3o2", + "private_ip": "172.16.0.123", + "public_ip": "123.56.71.98", + "eip_allocation_id": "eip-2zeevfsaxzwuue2szy7xb", + "asterisk_network": "host", + "asterisk_container": "agent-call-asterisk" + }, + "security_group": { + "provider_signaling_source": "160.202.254.79/32", + "provider_media_source_observed_before": "111.9.126.254/32", + "diagnostic_udp_scope": "1/65535 from the two provider IPs only", + "global_udp_open": false + }, + "call": { + "original_number": "18625770806", + "callee_prefix": "mka755", + "effective_sip_user": "mka75518625770806", + "sip_destination": "160.202.254.79:5060", + "caller_id": "KQ91526", + "execution_id": "exec_cell_1789627067521622369_1", + "call_id": "call_4c435bdbf3af488884b9ad879b8045b3", + "started_at_utc": "2026-09-17T06:37:44Z", + "ended_at_utc": "2026-09-17T06:37:48Z", + "attempts": 1, + "retries": 0, + "status": "failed_before_answer", + "reason_code": "CALL_NOT_ANSWERED", + "media_packets_in": 0, + "media_packets_out": 0, + "turns": [], + "recording_valid": false + }, + "packet_capture": { + "pcap": ".local/agent-call-third/capture-call2-20260917.pcap", + "pcap_sha256": "09f2707ccab64948a07d06be4150a1cda2469b151efc39ca2be2d574bec222f82", + "decoded_summary": ".local/agent-call-third/capture-call2-packets-20260917.txt", + "decoded_summary_sha256": "dd5438d142169b8344fa2c2fce1c243aac53506d2e244cd7df722d2895ff11aa", + "packet_count": 20, + "provider_signaling_packets": 4, + "provider_media_ip_packets": 0, + "local_rtp_range_packets": 0, + "sip_exchange": [ + "172.16.0.123:5060 -> 160.202.254.79:5060 INVITE sip:mka75518625770806@160.202.254.79:5060", + "160.202.254.79:5060 -> 172.16.0.123:5060 100 Trying", + "160.202.254.79:5060 -> 172.16.0.123:5060 480 Temporarily Unavailable", + "172.16.0.123:5060 -> 160.202.254.79:5060 ACK" + ], + "timing": "480 arrived about 465 ms after 100 Trying", + "sdp_sent": { + "public_media_address": "123.56.71.98", + "local_rtp_port": 10076, + "codec": "PCMA/8000" + }, + "provider_observed_transport": "Via received=123.56.71.98; rport=5060" + }, + "asterisk_observation": { + "external_media_channel": "UnicastRTP/127.0.0.1:45667 answered and joined the bridge", + "target_channel": "Called mka75518625770806@provider-primary", + "target_bridge_state": "never reached answered media state", + "host_firewall": "no matching nft rule observed", + "final_active_channels": 0, + "asterisk_log": ".local/agent-call-third/capture-call2-asterisk-20260917.log", + "asterisk_log_sha256": "67954f3a5b12f6fae0f3c637c9cec5607f7a57c4859a1f54daf104c0a7a58ced" + }, + "root_cause": { + "confirmed_for_this_attempt": "SIP provider returned 480 Temporarily Unavailable before answering; no 200/SDP answer was sent, therefore no RTP could exist", + "our_side": "EIP/NAT, SIP signaling source, outbound SDP address, PCMA offer, security-group source scope, externalMedia initialization, and ACK path were observed working", + "provider_side_or_line_contract": "provider route/availability, account/caller authorization, or the required called-number format/prefix mka755 remains the active fault boundary", + "not_proven": "The earlier call that reached 200 OK but showed zero inbound RTP was not reproduced in this capture; this pcap cannot determine post-200 RTP behavior" + }, + "actions": { + "our_code_fix": "committed as 668c12e", + "security_group": "source-limited full UDP rules retained for diagnosis", + "automatic_redial": false, + "temporary_cell_rabbitmq_capture_cleanup": true, + "ecs_and_eip_retained": true + }, + "next_request_to_provider": [ + "Confirm whether mka755 must be prepended to 18625770806 on this trunk", + "Confirm KQ91526 is authorized for this destination and line", + "Check why VOS3000 returned 480 Temporarily Unavailable and whether the route was available at 2026-09-17 06:37:47 UTC", + "For a call that reaches 200 OK, provide the actual RTP source IP/CIDR and confirm that RTP is sent to 123.56.71.98" + ] +} diff --git a/docs/部署接入_运行说明.md b/docs/部署接入_运行说明.md index 259762a..4f28c46 100644 --- a/docs/部署接入_运行说明.md +++ b/docs/部署接入_运行说明.md @@ -228,6 +228,8 @@ python3 deploy/render_asterisk.py --config .local/asterisk.json 真实 Cell 的 `externalMedia` 通道创建后,变量可能要等 `StasisStart` 才可查询;必须在通道就绪后重试读取 `UNICASTRTP_LOCAL_ADDRESS` 与 `UNICASTRTP_LOCAL_PORT`,以此建立向 Asterisk 的 RTP 发送目标。`addChannel` 在通道未进入 Stasis 时的 `400/404/409/422` 只能有限重试,成功后才能标记已入桥;收到目标 `Up` 后还必须通过 `GET /bridges/{id}` 确认 externalMedia 与目标都在同一桥内,不能只看 `Up` 就开始 AI。RTP 接收需校验来源 peer、PCMA payload type 和 SSRC。ARI originate 的 `timeout` 单位是秒,不是毫秒。实时录音必须先 `POST /recordings/live/{name}/stop`,再轮询读取 stored file,不能用 DELETE 丢弃录音后伪装成有效结果。 +2026-09-17 对第三组 `mka75518625770806` 做带 PJSIP logger 的 UDP 抓包:EIP/NAT、5060 信令、`From KQ91526`、PCMA SDP 和 ACK 均正常;服务商 `160.202.254.79` 在收到 INVITE 后返回 `100 Trying`,约 465ms 后返回 `480 Temporarily Unavailable`,未发送 200/SDP,因此该次没有 RTP 是“呼叫未建立”的必然结果,不应继续从端口范围或 Cell 音频链路猜测。抓包记录见 `docs/evidence/third-sip-capture-root-cause-20260917.json`;后续需服务商确认线路可用性、主叫授权及 `mka755` 被叫格式。 + ```bash # 默认为检查,不启动容器。 bash deploy/asterisk.sh