FreeSwitch默认收到A-leg的UPDATE消息后不会发送给B-leg,通过修改代码的方式增加一个update_passthrough变量字段来控制UPDATE消息A到B腿转发的功能。
如果是在早期媒体阶段也需要转发UPDATE消息,可以通过update_passthrough_on_early来控制是否在早期媒体阶段转发UPDATE消息。
由于A腿和B腿之间使用消息队列进行通信,UPDATE消息一般使用SWITCH_MESSAGE_INDICATE_DISPLAY消息进行传输,即A腿向B腿发送一个SWITCH_MESSAGE_INDICATE_DISPLAY消息,B腿收到后根据情况进行UPDATE操作,但FreeSwitch内部也有很多功能对消息队列进行了SWITCH_MESSAGE_INDICATE_DISPLAY消息发送,如果贸然改动可能导致A腿并没有收到UPDATE消息,B腿却发出去一个UPDATE消息,这时需要在A腿发往B腿消息中增加一个变量来证明此消息使来源于A腿。
本文章改动是从freeswitch的1.10.6版本上进行的改动,过早的版本,或者过于未来的版本可能有改动,如果时间不长应该大同小异。
1.首先处理A腿接收UPDATE消息的部分:
进入freeswitch源码的src/mod/endpoints/mod_sofia/sofia.c里面的sofia_update_callee_id函数,找到其中的如下代码:
if (switch_channel_inbound_display(channel)) {
if (!strcmp(caller_profile->caller_id_name, name) && !strcmp(caller_profile->caller_id_number, number)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s Same Caller ID \"%s\" <%s>\n", switch_channel_get_name(channel), name, number);
send = 0;
} else {
caller_profile->caller_id_name = switch_sanitize_number(switch_core_strdup(caller_profile->pool, name));
caller_profile->caller_id_number = switch_sanitize_number(switch_core_strdup(caller_profile->pool, number));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Update Caller ID to \"%s\" <%s>\n", switch_channel_get_name(channel), name, number);
}
} else {
if (!strcmp(caller_profile->callee_id_name, name) && !strcmp(caller_profile->callee_id_number, number)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s Same Callee ID \"%s\" <%s>\n", switch_channel_get_name(channel), name, number);
send = 0;
} else {
caller_profile->callee_id_name = switch_sanitize_number(switch_core_strdup(caller_profile->pool, name));
caller_profile->callee_id_number = switch_sanitize_number(switch_core_strdup(caller_profile->pool, number));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Update Callee ID to \"%s\" <%s>\n", switch_channel_get_name(channel), name, number);
if (lazy || (att && !switch_channel_get_partner_uuid(channel))) {
switch_channel_flip_cid(channel);
}
}
}
if (send) {
if (switch_event_create(&event, SWITCH_EVENT_CALL_UPDATE) == SWITCH_STATUS_SUCCESS) {
const char *uuid = switch_channel_get_partner_uuid(channel);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Direction", "RECV");
if (uuid) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridged-To", uuid);
}
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
sofia_send_callee_id(session, NULL, NULL);
}
将其修改为如下代码:
if (switch_channel_inbound_display(channel)) {
if (!strcmp(caller_profile->caller_id_name, name) && !strcmp(caller_profile->caller_id_number, number)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s Same Caller ID \"%s\" <%s>\n", switch_channel_get_name(channel), name, number);
//通过判断update_passthrough变量来决定是否传输update消息到b-leg
if (!switch_true(switch_channel_get_variable(channel, "update_passthrough"))) {
send = 0;
}
} else {
caller_profile->caller_id_name = switch_sanitize_number(switch_core_strdup(caller_profile->pool, name));
caller_profile->caller_id_number = switch_sanitize_number(switch_core_strdup(caller_profile->pool, number));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Update Caller ID to \"%s\" <%s>\n", switch_channel_get_name(channel), name, number);
}
} else {
if (!strcmp(caller_profile->callee_id_name, name) && !strcmp(caller_profile->callee_id_number, number)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s Same Callee ID \"%s\" <%s>\n", switch_channel_get_name(channel), name, number);
//通过判断update_passthrough变量来决定是否传输update消息到b-leg
if (!switch_true(switch_channel_get_variable(channel, "update_passthrough"))) {
send = 0;
}
} else {
caller_profile->callee_id_name = switch_sanitize_number(switch_core_strdup(caller_profile->pool, name));
caller_profile->callee_id_number = switch_sanitize_number(switch_core_strdup(caller_profile->pool, number));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Update Callee ID to \"%s\" <%s>\n", switch_channel_get_name(channel), name, number);
if (lazy || (att && !switch_channel_get_partner_uuid(channel))) {
switch_channel_flip_cid(channel);
}
}
}
if (send) {
//通过update_passthrough来决定是否透传sdp
if (switch_true(switch_channel_get_variable(channel, "update_passthrough"))) {
//定义变量储存b腿信息
switch_core_session_t *other_session;
switch_channel_t *other_channel;
//获取b-leg的session和channel
if ((val = switch_channel_get_partner_uuid(channel))
&& (other_session = switch_core_session_locate(val))) {
//获取b腿channel
other_channel = switch_core_session_get_channel(other_session);
//将sdp信息设置到SWITCH_B_SDP_VARIABLE变量
switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, sip->sip_payload->pl_data);
//获取成功后b-leg被锁定,需要解锁,否则会造成通道锁死
switch_core_session_rwunlock(other_session);
}
}
if (switch_event_create(&event, SWITCH_EVENT_CALL_UPDATE) == SWITCH_STATUS_SUCCESS) {
const char *uuid = switch_channel_get_partner_uuid(channel);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Direction", "RECV");
if (uuid) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridged-To", uuid);
}
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
sofia_send_callee_id(session, NULL, NULL);
}
再找到src/mod/endpoints/mod_sofia/sofia.c里面的sofia_send_callee_id函数,找到其中的如下代码:
if ((uuid = switch_channel_get_partner_uuid(channel)) && (session_b = switch_core_session_locate(uuid))) {
switch_core_session_message_t *msg;
//switch_channel_t *channel_b = switch_core_session_get_channel(session_b);
//switch_channel_set_profile_var(channel_b, "callee_id_name", name);
//switch_channel_set_profile_var(channel_b, "callee_id_number", number);
msg = switch_core_session_alloc(session_b, sizeof(*msg));
MESSAGE_STAMP_FFL(msg);
msg->message_id = SWITCH_MESSAGE_INDICATE_DISPLAY;
msg->string_array_arg[0] = switch_core_session_strdup(session_b, name);
msg->string_array_arg[1] = switch_core_session_strdup(session_b, number);
msg->from = __FILE__;
switch_core_session_queue_message(session_b, msg);
switch_core_session_rwunlock(session_b);
}
将其修改为:
if ((uuid = switch_channel_get_partner_uuid(channel)) && (session_b = switch_core_session_locate(uuid))) {
switch_core_session_message_t *msg;
//switch_channel_t *channel_b = switch_core_session_get_channel(session_b);
//switch_channel_set_profile_var(channel_b, "callee_id_name", name);
//switch_channel_set_profile_var(channel_b, "callee_id_number", number);
msg = switch_core_session_alloc(session_b, sizeof(*msg));
MESSAGE_STAMP_FFL(msg);
msg->message_id = SWITCH_MESSAGE_INDICATE_DISPLAY;
msg->string_array_arg[0] = switch_core_session_strdup(session_b, name);
msg->string_array_arg[1] = switch_core_session_strdup(session_b, number);
//增加下面这行代码,主要原因是freeswitch内部也会发送SWITCH_MESSAGE_INDICATE_DISPLAY消息
//增加一个update_from_aleg的变量,确保SWITCH_MESSAGE_INDICATE_DISPLAY消息是从a腿过来的,而不是freeswitch内部消息,B腿收到后判断update_from_aleg变量再进行转发
msg->string_array_arg[2] = switch_core_session_strdup(session_b, "update_from_aleg");
msg->from = __FILE__;
switch_core_session_queue_message(session_b, msg);
switch_core_session_rwunlock(session_b);
}
2.然后处理B腿发送UPDATE消息的部分代码:
进入freeswitch源码的src/mod/endpoints/mod_sofia/mod_sofia.c里面的sofia_receive_message函数,找到其中的如下代码:
case SWITCH_MESSAGE_INDICATE_DISPLAY:
{
const char *name = NULL, *number = NULL;
const char *call_info = NULL;
if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SEND_DISPLAY_UPDATE)) {
goto end_lock;
}
name = msg->string_array_arg[0];
number = msg->string_array_arg[1];
call_info = switch_channel_get_variable(channel, "presence_call_info_full");
if (!zstr(name) && strcmp(name, "_undef_")) {
char message[256] = "";
const char *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent");
const char *allow = switch_channel_get_variable(tech_pvt->channel, "sip_allow");
switch_event_t *event;
int update_allowed = 0;
const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
check_decode(name, tech_pvt->session);
if (allow) {
update_allowed = !!switch_stristr("UPDATE", allow);
}
if (zstr(number)) {
number = tech_pvt->caller_profile->destination_number;
}
switch_ivr_eavesdrop_update_display(session, name, number);
if (!sofia_test_flag(tech_pvt, TFLAG_UPDATING_DISPLAY) && switch_channel_test_flag(channel, CF_ANSWERED)) {
if (zstr(tech_pvt->last_sent_callee_id_name) || strcmp(tech_pvt->last_sent_callee_id_name, name) ||
zstr(tech_pvt->last_sent_callee_id_number) || strcmp(tech_pvt->last_sent_callee_id_number, number)) {
if (switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote)) {
snprintf(message, sizeof(message), "X-FS-Display-Name: %s\nX-FS-Display-Number: %s\n", name, number);
if (switch_channel_test_flag(tech_pvt->channel, CF_LAZY_ATTENDED_TRANSFER)) {
snprintf(message + strlen(message), sizeof(message) - strlen(message), "X-FS-Lazy-Attended-Transfer: true\n");
switch_channel_clear_flag(tech_pvt->channel, CF_LAZY_ATTENDED_TRANSFER);
switch_channel_clear_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER);
}
if (switch_channel_test_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER)) {
snprintf(message + strlen(message), sizeof(message) - strlen(message), "X-FS-Attended-Transfer: true\n");
switch_channel_clear_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER);
}
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/update_display"),
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
} else if (ua && switch_stristr("snom", ua)) {
const char *ver_str = NULL;
int version = 0;
ver_str = switch_stristr( "/", ua);
if ( ver_str ) {
char *argv[4] = { 0 };
char *dotted = strdup( ver_str + 1 );
switch_assert(dotted);
switch_separate_string(dotted, '.', argv, (sizeof(argv) / sizeof(argv[0])));
if ( argv[0] && argv[1] && argv[2] ) {
version = ( atoi(argv[0]) * 10000 ) + ( atoi(argv[1]) * 100 ) + atoi(argv[2]);
}
switch_safe_free( dotted );
}
if ( version >= 80424 ) {
if (zstr(name)) {
snprintf(message, sizeof(message), "From: %s\r\nTo:\r\n", number);
} else {
snprintf(message, sizeof(message), "From: \"%s\" %s\r\nTo:\r\n", name, number);
}
} else {
if (zstr(name)) {
snprintf(message, sizeof(message), "From:\r\nTo: %s\r\n", number);
} else {
snprintf(message, sizeof(message), "From:\r\nTo: \"%s\" %s\r\n", name, number);
}
}
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), SIPTAG_PAYLOAD_STR(message), TAG_END());
} else if (update_allowed && ua && (switch_stristr("polycom", ua) ||
(switch_stristr("aastra", ua) && !switch_stristr("Intelligate", ua)) ||
(switch_stristr("cisco/spa50", ua) ||
switch_stristr("cisco/spa525", ua)) ||
switch_stristr("cisco/spa30", ua) ||
switch_stristr("Grandstream", ua) ||
switch_stristr("Yealink", ua) ||
switch_stristr("Mitel", ua) ||
switch_stristr("Panasonic", ua))) {
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <sip:%s@%s>", name, number, tech_pvt->profile->sipip);
sofia_set_flag_locked(tech_pvt, TFLAG_UPDATING_DISPLAY);
nua_update(tech_pvt->nh,
NUTAG_SESSION_TIMER(tech_pvt->session_timeout),
NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher),
NUTAG_UPDATE_REFRESH(tech_pvt->update_refresher),
TAG_IF(!zstr(tech_pvt->privacy), SIPTAG_PRIVACY_STR(tech_pvt->privacy)),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
TAG_IF(!zstr(tech_pvt->route_uri), NUTAG_PROXY(tech_pvt->route_uri)),
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
}
tech_pvt->last_sent_callee_id_name = switch_core_session_strdup(tech_pvt->session, name);
tech_pvt->last_sent_callee_id_number = switch_core_session_strdup(tech_pvt->session, number);
if (switch_event_create(&event, SWITCH_EVENT_CALL_UPDATE) == SWITCH_STATUS_SUCCESS) {
const char *uuid = switch_channel_get_partner_uuid(channel);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Direction", "SEND");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sent-Callee-ID-Name", name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sent-Callee-ID-Number", number);
//switch_channel_set_profile_var(channel, "callee_id_name", name);
//switch_channel_set_profile_var(channel, "callee_id_number", number);
if (uuid) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridged-To", uuid);
}
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Not sending same id again \"%s\" <%s>\n", name, number);
}
}
}
}
break;
在1995行代码处可以看到sofia模块默认接收到SWITCH_MESSAGE_INDICATE_DISPLAY消息后,需要进入CF_ANSWER状态才可以发送update消息,部分场景下,早起媒体阶段也希望能转发update消息,可以按照如下方式修改:
case SWITCH_MESSAGE_INDICATE_DISPLAY:
{
const char *name = NULL, *number = NULL;
const char *call_info = NULL;
if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SEND_DISPLAY_UPDATE)) {
goto end_lock;
}
name = msg->string_array_arg[0];
number = msg->string_array_arg[1];
call_info = switch_channel_get_variable(channel, "presence_call_info_full");
if (!zstr(name) && strcmp(name, "_undef_")) {
char message[256] = "";
const char *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent");
const char *allow = switch_channel_get_variable(tech_pvt->channel, "sip_allow");
switch_event_t *event;
int update_allowed = 0;
const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
check_decode(name, tech_pvt->session);
if (allow) {
update_allowed = !!switch_stristr("UPDATE", allow);
}
if (zstr(number)) {
number = tech_pvt->caller_profile->destination_number;
}
switch_ivr_eavesdrop_update_display(session, name, number);
//如果在早期媒体阶段的UPDATE消息,可以不判断CF_ANSWERED,通过判断update_passthrough_on_early和update_from_aleg来决定是否转发
if (!sofia_test_flag(tech_pvt, TFLAG_UPDATING_DISPLAY) &&
(switch_channel_test_flag(channel, CF_ANSWERED) ||
(switch_true(switch_channel_get_variable(channel, "update_passthrough_on_early")) &&
msg->string_array_arg[2] &&
0 == strcmp(msg->string_array_arg[2], "update_from_aleg")
)
)
) {
if (zstr(tech_pvt->last_sent_callee_id_name) || strcmp(tech_pvt->last_sent_callee_id_name, name) ||
zstr(tech_pvt->last_sent_callee_id_number) || strcmp(tech_pvt->last_sent_callee_id_number, number)) {
if (switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote)) {
snprintf(message, sizeof(message), "X-FS-Display-Name: %s\nX-FS-Display-Number: %s\n", name, number);
if (switch_channel_test_flag(tech_pvt->channel, CF_LAZY_ATTENDED_TRANSFER)) {
snprintf(message + strlen(message), sizeof(message) - strlen(message), "X-FS-Lazy-Attended-Transfer: true\n");
switch_channel_clear_flag(tech_pvt->channel, CF_LAZY_ATTENDED_TRANSFER);
switch_channel_clear_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER);
}
if (switch_channel_test_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER)) {
snprintf(message + strlen(message), sizeof(message) - strlen(message), "X-FS-Attended-Transfer: true\n");
switch_channel_clear_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER);
}
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/update_display"),
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
} else if (ua && switch_stristr("snom", ua)) {
const char *ver_str = NULL;
int version = 0;
ver_str = switch_stristr( "/", ua);
if ( ver_str ) {
char *argv[4] = { 0 };
char *dotted = strdup( ver_str + 1 );
switch_assert(dotted);
switch_separate_string(dotted, '.', argv, (sizeof(argv) / sizeof(argv[0])));
if ( argv[0] && argv[1] && argv[2] ) {
version = ( atoi(argv[0]) * 10000 ) + ( atoi(argv[1]) * 100 ) + atoi(argv[2]);
}
switch_safe_free( dotted );
}
if ( version >= 80424 ) {
if (zstr(name)) {
snprintf(message, sizeof(message), "From: %s\r\nTo:\r\n", number);
} else {
snprintf(message, sizeof(message), "From: \"%s\" %s\r\nTo:\r\n", name, number);
}
} else {
if (zstr(name)) {
snprintf(message, sizeof(message), "From:\r\nTo: %s\r\n", number);
} else {
snprintf(message, sizeof(message), "From:\r\nTo: \"%s\" %s\r\n", name, number);
}
}
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), SIPTAG_PAYLOAD_STR(message), TAG_END());
} else if (update_allowed && ua && (switch_stristr("polycom", ua) ||
(switch_stristr("aastra", ua) && !switch_stristr("Intelligate", ua)) ||
(switch_stristr("cisco/spa50", ua) ||
switch_stristr("cisco/spa525", ua)) ||
switch_stristr("cisco/spa30", ua) ||
switch_stristr("Grandstream", ua) ||
switch_stristr("Yealink", ua) ||
switch_stristr("Mitel", ua) ||
switch_stristr("Panasonic", ua))) {
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <sip:%s@%s>", name, number, tech_pvt->profile->sipip);
sofia_set_flag_locked(tech_pvt, TFLAG_UPDATING_DISPLAY);
nua_update(tech_pvt->nh,
NUTAG_SESSION_TIMER(tech_pvt->session_timeout),
NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher),
NUTAG_UPDATE_REFRESH(tech_pvt->update_refresher),
TAG_IF(!zstr(tech_pvt->privacy), SIPTAG_PRIVACY_STR(tech_pvt->privacy)),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
TAG_IF(!zstr(tech_pvt->route_uri), NUTAG_PROXY(tech_pvt->route_uri)),
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
} else if (update_allowed &&
switch_true(switch_channel_get_variable(channel, "update_passthrough")) &&
msg->string_array_arg[2] &&
0 == strcmp(msg->string_array_arg[2], "update_from_aleg")) {
//获取A腿的sdp
const char *b_sdp = NULL;
b_sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE);
if (b_sdp) {
switch_core_media_set_local_sdp(session, b_sdp, SWITCH_TRUE);
//此时SDP中的媒体地址还是A腿刚收到的,如果是BYPASS模式则无需理会
//但如果非BYPASS模式则需要更新SDP中的媒体地址和端口
if (!switch_channel_test_flag(channel, CF_PROXY_MODE)) {
switch_core_media_patch_sdp(tech_pvt->session);
}
}
//设置UPDATE的消息锁,收到对应的200OK后会解锁
sofia_set_flag_locked(tech_pvt, TFLAG_UPDATING_DISPLAY);
//调用sofia发送update消息
nua_update(tech_pvt->nh,
NUTAG_SESSION_TIMER(tech_pvt->session_timeout),
NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher),
NUTAG_UPDATE_REFRESH(tech_pvt->update_refresher),
TAG_IF(!zstr(tech_pvt->privacy), SIPTAG_PRIVACY_STR(tech_pvt->privacy)),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
TAG_IF(!zstr(tech_pvt->route_uri), NUTAG_PROXY(tech_pvt->route_uri)),
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
TAG_IF(tech_pvt->mparams.local_sdp_str, SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str)),
TAG_END());
}
tech_pvt->last_sent_callee_id_name = switch_core_session_strdup(tech_pvt->session, name);
tech_pvt->last_sent_callee_id_number = switch_core_session_strdup(tech_pvt->session, number);
if (switch_event_create(&event, SWITCH_EVENT_CALL_UPDATE) == SWITCH_STATUS_SUCCESS) {
const char *uuid = switch_channel_get_partner_uuid(channel);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Direction", "SEND");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sent-Callee-ID-Name", name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sent-Callee-ID-Number", number);
//switch_channel_set_profile_var(channel, "callee_id_name", name);
//switch_channel_set_profile_var(channel, "callee_id_number", number);
if (uuid) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridged-To", uuid);
}
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Not sending same id again \"%s\" <%s>\n", name, number);
}
}
}
}
break;
3.修改拨号计划,设置对应的变量:
<extension name="test-update">
<condition field="destination_number" expression="^(10[01][0-9])$">
<!-- 设置A腿相关变量 -->
<action application="set" data="update_passthrough=on"/>
<action application="set" data="update_passthrough_on_early=on"/>
<!-- 在bridge中设置B腿相关变量 -->
<action application="bridge" data="{update_passthrough=on,update_passthrough_on_early=on}sofia/internal/188xxxxxxxx@gateway.com"/>
</condition>
</extension>
至此,通过WireShark抓包验证,FreeSwitch完成了UPDATE消息透传功能。