FreeSwitch当使用bridge方式桥接起AB腿时,B腿回复的部分状态码中携带的某些字段,并不会透传给A腿,由于部分字段的缺失会导致A腿方向的会话无法确定异常的状态原因,以422消息举例:
本文章是在FreeSwitch 1.10.9的代码基础上进行的改动,过早的版本,或者过于未来的版本可能有改动,如果时间不长应该大同小异。
1.422消息的用途
当uac发起初始INVITE请求时,会携带Session-Expire头域指定会话的刷新时间和刷新方,格式为:
Session-Expire: 90;refresher=uac
上面的例子代表,会话刷新消息的超时时间为90秒,由uac来刷新消息。
uas收到后由于不同终端、设备等原因可能认为90秒更新频率过高,要求uac重新发起INVITE,并加大Session-Expire,将使用422响应码回复uac端。uas端进行422响应时会携带一个名为Min-SE的头域来指定最小的更新时间,单位为秒。
2.FreeSwitch当前处理
由于FreeSwitch对于回复INVITE消息的状态码的特殊头域未做任和处理,需要手动修改代码进行处理。
3.代码修改
1.修改sofia.c文件
找到以第6650行代码开始的在sofia_handle_sip_r_invite函数内的这部分,增加如下代码:
if (status >= 400) {
char status_str[5];
switch_snprintf(status_str, sizeof(status_str), "%d", status);
switch_channel_set_variable(channel, "sip_invite_failure_status", status_str);
switch_channel_set_variable(channel, "sip_invite_failure_phrase", phrase);
switch_channel_set_variable_partner(channel, "sip_invite_failure_status", status_str);
switch_channel_set_variable_partner(channel, "sip_invite_failure_phrase", phrase);
//增加下面的代码
if (sip->sip_min_se) {
switch_channel_set_variable_partner(channel, "sip_422_min_se", sip_header_as_string(nua_handle_get_home(nh), (void *)sip->sip_min_se));
}
//增加代码结束
} else {
switch_channel_set_variable_partner(channel, "sip_invite_failure_status", NULL);
switch_channel_set_variable_partner(channel, "sip_invite_failure_phrase", NULL);
}
2.修改mod_sofia.c文件
找到第551行开始的这部分代码,代码所在函数是sofia_on_hangup函数,增加如下代码:
char *resp_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
const char *phrase;
char *added_headers = NULL;
//增加下面的代码
const char *min_se_header = switch_channel_get_variable(tech_pvt->channel, "sip_422_min_se");
//增加代码结束
if (tech_pvt->respond_phrase) {
//phrase = su_strdup(nua_handle_home(tech_pvt->nh), tech_pvt->respond_phrase);
phrase = tech_pvt->respond_phrase;
} else {
phrase = sip_status_phrase(sip_cause);
}
继续找到sofia_on_hangup函数内,626行如下代码,增加如下代码
nua_respond(tech_pvt->nh, sip_cause, phrase,
TAG_IF(!zstr(reason), SIPTAG_REASON_STR(reason)),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers)),
TAG_IF(!zstr(resp_headers), SIPTAG_HEADER_STR(resp_headers)),
TAG_IF(!zstr(added_headers), SIPTAG_HEADER_STR(added_headers)),
TAG_IF(tech_pvt->respond_dest, SIPTAG_CONTACT_STR(tech_pvt->respond_dest)),
TAG_IF(!zstr(max_forwards), SIPTAG_MAX_FORWARDS_STR(max_forwards)),
//增加下面的代码
TAG_IF(!zstr(min_se_header), SIPTAG_MIN_SE_STR(min_se_header)),
//增加代码结束
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
修改完,重新编译运行即可。