FreeSwitch代码中2个常修改的具体代码具体位置和简介

FreeSwitch在各种实际应用场景中,在不修改代码的情况下完整的支持业务场景是一件不容易的事情,大部分实际应用场景需要修改FreeSwitch的代码。所以了解清楚FreeSwitch代码是一件FreeSwitch应用必备的技能,本文将对FreeSwitch常修改和调试的常见位置进行介绍。

本文章操作是从freeswitch的1.10.9版本上进行的,过早的版本,或者过于未来的版本可能有改动,如果时间不长应该大同小异。

1.A腿和B腿进行Bridge时媒体包交换的线程函数

2.mod_sofia中处理会话SIP消息的响应函数

1.A腿和B腿进行Bridge时媒体包交换的线程函数

        文件:switch_ivr_bridge.c

        所在行数:356

        函数名:audio_bridge_thread

        关键代码:799行开始

		/* read audio from 1 channel and write it to the other */
		status = switch_core_session_read_frame(session_a, &read_frame, SWITCH_IO_FLAG_NONE, stream_id);

		if (SWITCH_READ_ACCEPTABLE(status)) {
			read_frame_count++;
			if (switch_test_flag(read_frame, SFF_CNG)) {
				if (silence_val) {
					switch_generate_sln_silence((int16_t *) silence_frame.data, silence_frame.samples,
												read_impl.number_of_channels, silence_val);
					read_frame = &silence_frame;
				} else if (!switch_channel_test_flag(chan_b, CF_ACCEPT_CNG)) {
					continue;
				}
			}

			if (switch_channel_test_flag(chan_a, CF_BRIDGE_NOWRITE)) {
				continue;
			}

			if (status != SWITCH_STATUS_BREAK && !switch_channel_test_flag(chan_a, CF_HOLD) && !switch_channel_test_flag(chan_b, CF_LEG_HOLDING)) {
				if (switch_core_session_write_frame(session_b, read_frame, SWITCH_IO_FLAG_NONE, stream_id) != SWITCH_STATUS_SUCCESS) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG,
									  "%s ending bridge by request from write function\n", switch_channel_get_name(chan_b));
					goto end_of_bridge_loop;
				}
			}
		} else {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "%s ending bridge by request from read function\n", switch_channel_get_name(chan_a));
			goto end_of_bridge_loop;
		}

        此部分代码在该函数的一个循环中,从session_a使用switch_core_session_read_frame函数读取音频帧,判断合法后判断是否为CNG帧,如果B腿状态正常则使用switch_core_session_write_frame函数写入到B腿。

2.A腿和B腿进行Bridge时媒体包交换的线程函数

        文件:sofia.c

        所在行数:1465

        函数名:our_sofia_event_callback

        关键代码:1627行开始


	switch (event) {
	case nua_r_get_params:
	case nua_i_fork:
	case nua_r_info:
		break;
	case nua_r_unregister:
	case nua_r_unsubscribe:
	case nua_i_terminated:
	case nua_r_publish:
	case nua_i_error:
	case nua_i_active:
	case nua_r_set_params:
	case nua_i_prack:
	case nua_r_prack:
		break;

	case nua_i_cancel:
        ...
		break;
	case nua_r_cancel:
        ...
		break;
	case nua_i_ack:
        ...
		break;
	case nua_r_ack:
		if (channel)
			switch_channel_set_flag(channel, CF_MEDIA_ACK);
		break;
	case nua_r_shutdown:
		if (status >= 200) {
			sofia_set_pflag(profile, PFLAG_SHUTDOWN);
			su_root_break(profile->s_root);
		}
		break;
	case nua_r_message:
		sofia_handle_sip_r_message(status, profile, nh, sip);
		break;
	case nua_r_invite:
		sofia_handle_sip_r_invite(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
		break;
	case nua_r_options:
		sofia_handle_sip_r_options(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
		break;
	case nua_i_bye:
		sofia_handle_sip_i_bye(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
		break;
	case nua_r_bye:
		sofia_handle_sip_r_bye(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
		break;
	case nua_r_notify:
		if (session) {
			sofia_handle_sip_r_notify(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
		}
		break;
	case nua_i_notify:
		sofia_handle_sip_i_notify(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
		break;
	case nua_r_register:
		sofia_reg_handle_sip_r_register(status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
		break;
	case nua_i_options:
		sofia_handle_sip_i_options(status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
		break;
	case nua_i_invite:
		if (session && sofia_private) {
			if (sofia_private->is_call > 1) {
				sofia_handle_sip_i_reinvite(session, nua, profile, nh, sofia_private, sip, de, tags);
			} else {
				sofia_private->is_call++;
				sofia_handle_sip_i_invite(session, nua, profile, nh, sofia_private, sip, de, tags);
			}
		}
		break;
	case nua_i_publish:
		sofia_presence_handle_sip_i_publish(nua, profile, nh, sofia_private, sip, de, tags);
		break;
	case nua_i_register:
		//nua_respond(nh, SIP_200_OK, SIPTAG_CONTACT(sip->sip_contact), NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
		//nua_handle_destroy(nh);
		sofia_reg_handle_sip_i_register(nua, profile, nh, &sofia_private, sip, de, tags);
		break;
	case nua_i_state:
		sofia_handle_sip_i_state(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
		break;
    ...
    }

        此部分代码处理所有的SIP请求和响应,对于请求类消息,下表举例部分nua的消息类型和对应的SIP消息:

nua事件SIP消息

nua_i_invite

INVITE消息事件

nua_r_invite

响应INVITE的状态码事件,如180、181、183、200、403、404、603等回复INVITE的状态码。

nua_i_prack

PRACK消息事件

nua_r_prack

响应PRACK消息的状态码事件

nua_i_update

UPDATE消息事件

nua_r_update

响应UPDATE消息的状态码事件

nua_i_ack

ACK消息事件
nua_i_cancelCANCEL消息事件
nua_r_cancel响应CANCEL消息的状态码事件
nua_i_byeBYE消息事件
nua_r_bye响应BYE消息的状态码事件

        注意our_sofia_event_callback函数并不是Sofia-SIP库对外回调消息的回调函数,而是FreeSwitch的mod_sofia模块自己的回调函数,Sofia-SIP库对外回调函数是sofia_event_callback。

        our_sofia_event_callback函数处理所有SIP会话的消息,如果区分具体的哪个SIP会话,要根据our_sofia_event_callback函数的sofia_private参数的uuid字段来获取session信息。

        一般情况下our_sofia_event_callback函数不直接处理SIP消息,而是定义了一些处理特定消息的函数,如处理INVITE消息的sofia_handle_sip_i_invite、处理BYE消息的sofia_handle_sip_i_bye函数等。

        对于UPDATE消息、PRACK消息等在不修改代码的情况下可能无法触发回调函数,因为Sofia-SIP库内部会自动处理相关消息, 需要使用Sofia-SIP库提供的NUTAG_APPL_METHOD宏来设定是否回调到上层处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

jkkj1630

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

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

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

打赏作者

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

抵扣说明:

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

余额充值