freeswithc 對接運營商落地閘道器
阿新 • • 發佈:2018-12-10
freeswithc “Auto Changing audio port from” 原理解析
整體環境
在對接外部運營商的落地閘道器的時候,流程圖如下,core區的機器無法連線到外網,需要在外網區域增加一臺轉發伺服器fs,來達到內網和外部手機的通訊
dmz區IP:100.69.208.59
core區IP:100.69.216.126
對接所做配置檔案修改
撥出的配置
- core區修改dialplan/default.xml ,新增如下,轉接到dmz區的伺服器上
<extension name="out-dmz">
<condition field="destination_number" expression="^0(.*)$">
<action application="bridge" data="sofia/external/sip: [email protected]:5060"/>
</condition>
</extension>
- dmz區的external統一由dialplan/public/00_inbound_did.xml 來處理,新增 如下程式碼,轉接到IMS閘道器上
<extension name="test-to-ims"> <condition field="destination_number" expression="^10(.*)$"> <action application="set" data="domain_name=$${domain}"/> <action application="bridge" data="sofia/gateway/ims/99$1"/> </condition> </extension>
- 增加了 IMS閘道器 增加sip_profiles/external/gateway.xml 檔案,如下配置 ;
<include> <gateway name="ims"> <param name="username" value="075533614xxx"/> <param name="password" value="none"/> <param name="proxy" value="122.13.xx.xx:5060"/> <param name="register" value="false"/> </gateway> </include>
- 由於在撥出的時候invite 中的sdp會替換成dmz區的內網IP,所以需要在internal.xml中修改ext-rtp-ip為對映的外網IP如:112.xxx.xxx.xxx ;否者會出現呼叫能通但是沒有語音
呼入的配置
- public下的xml 增加外部呼入的規則,如下我寫定轉接到core區的1000,也可以做一個IVR分機撥號的功能;
<extension name="test-to-core">
<condition field="destination_number" expression="^(07553361xxxx)$">
<action application="set" data="domain_name=$${domain}"/>
<action application="bridge" data="sofia/external/sip:[email protected]:5060"/>
</condition>
</extension>
- core區的public下的xml增加1000的撥號規則,轉到internal的1000上
<extension name="public_test">
<condition field="destination_number" expression="^(10[01][0-9])$">
<action application="transfer" data="$1 XML default"/>
</condition>
</extension>
3. 由於在呼入的時候,回覆invite 的包中的sdp會替換成dmz區的內網IP,所以需要在external.xml中修改ext-rtp-ip為對映的外網IP如:112.xxx.xxx.xxx ;否者會出現入能通但是沒有語音
疑問點1:
撥出的時候dmz的internal.xml修改了回覆invite中的sdp的IP資訊為外網IP,按理說應該core區訪問不了外網IP的。
解答:
在日誌中看到如下日誌,core區的freesiwtch會把dmz區的rtp-ip從外網112.95.xx.xx自動changing 到dmz內網IP:100.69.208.59,因為core區給126-》dmz,dmz會給126傳送RTP包做一個auto changing port用
[INFO] switch_rtp.c:7497 Auto Changing audio port from 112.95.xxx.xxx:20604 to 100.69.208.59:20604
原理:
freeswitch如下圖
麻煩:當B處於NAT後,A的RTP流從freeswitch是不能到B的(因為B為內網的IP),而且交換信令的時候,不可能給出NAT後的B的RPT IP和埠
解決:前期freeswitch的RTP-IP給到B,B會給FS發rtp流,以便FS能知道B的真實NAT後的IP和埠(這也是auto changing port的原理),freeswitch會監聽UDP的 IP和埠以便接受B傳送過來的RTP流
rtp_common_read 程式碼中有設定switch_rtp_set_remote_address 設定RTP遠端地址的操作
if (bytes && rtp_session->flags[SWITCH_RTP_FLAG_AUTOADJ] && switch_sockaddr_get_port(rtp_session->rtp_from_addr)) {
if (!switch_cmp_addr(rtp_session->rtp_from_addr, rtp_session->remote_addr)) {
if (++rtp_session->autoadj_tally >= rtp_session->autoadj_threshold) {
const char *err;
uint32_t old = rtp_session->remote_port;
const char *tx_host;
const char *old_host;
char bufa[50], bufb[50];
char adj_port[6];
tx_host = switch_get_addr(bufa, sizeof(bufa), rtp_session->rtp_from_addr);
old_host = switch_get_addr(bufb, sizeof(bufb), rtp_session->remote_addr);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO,
"Auto Changing %s port from %s:%u to %s:%u\n", rtp_type(rtp_session), old_host, old, tx_host,
switch_sockaddr_get_port(rtp_session->rtp_from_addr));
rtp_session->auto_adj_used = 1;
switch_rtp_set_remote_address(rtp_session, tx_host, switch_sockaddr_get_port(rtp_session->rtp_from_addr), 0, SWITCH_FALSE, &err);
疑問點2:
ext-sip-ip 設定成外網IP後,sip信令將使用外網IP來通訊,導致core和dmz區不能正常sip互動