FreeSwitch 修改代码使UPDATE消息和对应的SDP进行A到B腿透传功能

本文介绍如何修改FreeSwitch源码,使其在收到A腿UPDATE消息后转发给B腿,涉及sofia_update_callee_id、sofia_send_callee_id和sofia_receive_message函数的修改,以及如何在早期媒体阶段控制UPDATE消息的转发,并通过设置变量确保消息来源。最后通过WireShark验证了UPDATE消息的透传功能。
摘要由CSDN通过智能技术生成

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消息透传功能。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jkkj1630

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值