freeswitch 32秒自动挂断问题
说明:
- 首次发表日期:2024-08-23
- 参考:
- https://serverfault.com/questions/1008661/freeswitch-drops-calls-after-32-seconds
- https://blog.csdn.net/qq_32110203/article/details/141126033
- https://stackoverflow.com/questions/73708045/freeswitch-outbound-calls-dropping-after-about-30-seconds-due-to-ack-timeout
回顾一下SIP呼叫流程:
- 主叫向被叫发送INVITE消息请求建立SIP会话
- 被叫回复100 Trying消息,表示收到请求了
- 然后被叫电话开始振铃,并回复180 Ringing通知主叫我这边开始振铃了
- 被叫这边有人接了电话,被叫发送200 OK消息给主叫
- 主叫收到200 OK消息后,向被叫回复ACK消息以作证实
- 现在,主叫和被叫已经开始通话了,通话语音是通过SIP之外的RTP包传递的
- 最后,一方挂断电话并向另一方发送BYE消息,另一方收到消息后回复200 OK消息
- 通话完毕。
使用sngrep抓包:
sudo apt-get install sngrep
sudo sngrep
打电话,等自动挂断后,进入查看最新的记录:
┬───────── ──────────┬───────── ──────────┬
│ INVITE (SDP) │ │
│ ──────────────────────────> │ │
│ 100 Trying │
│ <──────────────────────────────────────────────────────── │
│ 180 Ringing │
│ <──────────────────────────────────────────────────────── │
│ 200 Ok (SDP) │
│ <──────────────────────────────────────────────────────── │
│ ACK │
│ ────────────────────────────────────────────────────────> │
│ BYE │
│ ────────────────────────────────────────────────────────> │
│ 200 Ok │
│ <──────────────────────────────────────────────────────── │
发现ACK部分是红色的,移动向下方向键到ACK,可以看到:
ACK sip:1001@192.168.31.23:55778;transport=tcp SIP/2.0
Via: SIP/2.0/TCP 113.83.194.236;branch=z9hG4bKvKUDev3DQ7a0H
Max-Forwards: 70
From: "Extension 1009" <sip:1009@192.168.31.25>;tag=atey5H2BZB78Q
To: <sip:1001@192.168.31.23:55777;transport=tcp>;tag=yMlYjfV
Call-ID: 102cf5a8-db9c-123d-ecbb-00155d006606
CSeq: 87636657 ACK
Contact: <sip:mod_sofia@113.83.194.236:5060;transport=tcp>
Content-Length: 0
可以看到主叫向被叫发送的ACK消息中,Contact的IP地址并非本地IP地址,因此导致被叫接受不到消息,ACK事务超时(默认32秒)后,主叫向被叫发送BYE消息来挂断电话。
解决方案:
修改 /etc/freeswitch/sip_profiles/internal.xml
中
<param name="ext-rtp-ip" value="$${external_rtp_ip}"/>
<param name="ext-sip-ip" value="$${external_sip_ip}"/>
将其注释,然后添加修正:
<param name="ext-rtp-ip" value="$${local_ip_v4}"/>
<param name="ext-sip-ip" value="$${local_ip_v4}"/>
将传输协议从TCP修改为UDP协议可能有用。