pj_status_t pjsua_media_channel_create_sdp_t38(pjsua_call_id call_id,
pj_pool_t *pool,
const pjmedia_sdp_session *rem_sdp,
pjmedia_sdp_session **p_sdp,
int *sip_status_code,
pj_bool_t createFwRule)
{
enum { MAX_MEDIA = 1 };
pjmedia_sdp_session *sdp;
pjmedia_transport_info tpinfo;
pjsua_call *call = &pjsua_var.calls[call_id];
pj_status_t status;
int i;
# ifdef SUPPORT_METABOLIC_MEDIA_PORT
pj_uint16_t medport;
pj_bool_t portAvaible = PJ_FALSE;
# endif
#if defined(PJSIP_HAS_FIREWALL_FILTER) && PJSIP_HAS_FIREWALL_FILTER!=0
char localIp[CMSIP_STR_40];
pj_uint16_t localPort;
pj_uint16_t localRtcpPort;
pj_str_t ip;
PJ_FIREWALL_RULE* pFwRule = NULL;
#endif
pj_str_t *pBoundIp = &pjsua_var.BoundIp;
int family = AF_INET;
/* Return error if media transport has not been created yet
* (e.g. application is starting)
*/
if (call->med_tp == NULL)
{
return PJ_EBUSY;
}
/* Media index must have been determined before */
pj_assert(call->audio_idx != -1);
/* Create media if it's not created. This could happen when call is
* currently on-hold
*/
if (call->med_tp_st == PJSUA_MED_TP_IDLE)
{
pjsip_role_e role;
role = (rem_sdp ? PJSIP_ROLE_UAS : PJSIP_ROLE_UAC);
status = pjsua_media_channel_init(call_id, role, call->secure_level,
pool, rem_sdp, sip_status_code);
if (status != PJ_SUCCESS)
{
return status;
}
}
/* Get media socket info */
pjmedia_transport_info_init(&tpinfo);
# ifdef SUPPORT_METABOLIC_MEDIA_PORT
#ifdef INCLUDE_VOIP_SUPPORT_IPV6
if (pjsua_var.BoundIp6.slen <= 0 || !strncmp(pjsua_var.BoundIp6.ptr, "::", 2))
{
CMSIP_PRINT("-------use IPv4--------");
family = pj_AF_INET();
pBoundIp = &pjsua_var.BoundIp;
}
else
{
CMSIP_PRINT("-------use IPv6--------");
family = pj_AF_INET6();
pBoundIp = &pjsua_var.BoundIp6;
}
#endif
for (i = 0; i < PJMEDIA_PORT_TEST_COUNT; ++i)
{
medport = pjmedia_endpt_get_mediaPort(pjsua_var.med_endpt);
pjmedia_endpt_set_mediaPort(pjsua_var.med_endpt);
/*test RTP media port*/
status = pjmedia_endpt_test_media_port(*pBoundIp, medport, &portAvaible, family);
if (PJ_FALSE==portAvaible && EADDRINUSE == errno)
{
CMSIP_PRINT("-------address is already used-------");
errno = 0;
continue;
}
else if (PJ_SUCCESS != status)
{
CMSIP_PRINT("----------test media port error-----------");
return status;
}
/*test RTCP media port*/
status = pjmedia_endpt_test_media_port(*pBoundIp, (medport+1), &portAvaible, family);
if (PJ_FALSE==portAvaible && EADDRINUSE == errno)
{
CMSIP_PRINT("-------address is already used-------");
errno = 0;
continue;
}
else if (PJ_SUCCESS != status)
{
CMSIP_PRINT("----------test media port error-----------");
return status;
}
else
{
break;
}
}
if (i >= PJMEDIA_PORT_TEST_COUNT)
{
return status;
}
pjmedia_transport_udp_set_mediaPort(call->med_tp, medport);
# endif
pjmedia_transport_get_info(call->med_tp, &tpinfo);
#if defined(PJSIP_HAS_FIREWALL_FILTER) && PJSIP_HAS_FIREWALL_FILTER!=0
if (createFwRule)
{
for (i = 0; i < PJ_ARRAY_SIZE(call->fwRule); ++i)
{
CMSIP_PRINT("--------ready to delete iptables rule--------");
pFwRule = &call->fwRule[i];
if (pFwRule->destination.slen > 0 && pFwRule->dport > 0)
{
pj_firewall_set_rule_accept(PJ_FIREWALLCFG_DEL, PJ_TRANSPORT_UDP,
&pFwRule->destination, NULL, pFwRule->dport,
NULL, NULL, -1, pj_firewall_get_fwtype(pFwRule->family)
#ifdef INCLUDE_VOIP_SUPPORT_IPV6
, pFwRule->family
#endif /* INCLUDE_VOIP_SUPPORT_IPV6 */
, pjsua_var.tcMark);
}
}
pjmedia_transport_udp_local_info(call->med_orig, localIp, &localPort, &localRtcpPort, &family);
ip = pj_str(localIp);
CMSIP_PRINT("-----add iptables rule(dstIp(%s), localPort(%d), localRtcpPort(%d))",
localIp, localPort, localRtcpPort);
/*����DMZ������ʱ������Է���rtp�ȵ����ʹ�ñ�������DUT VOIP��rtp���ݰ�֮��ֱ��
��DMZ��iptables����ת��������DUT VOIP�����յ����ݰ�������������Ҫ�ڷ���INVITE֮
ǰ�Ϳ�����Ӧ�˿ڡ�by yuchuwei*/
/*now, only support UDP*/
#ifdef INCLUDE_VOIP_SUPPORT_IPV6
if (AF_INET == family)
{
#endif /* INCLUDE_VOIP_SUPPORT_IPV6 */
status = pj_firewall_set_rule_accept(PJ_FIREWALLCFG_ADD, PJ_TRANSPORT_UDP,
&ip, NULL, localPort, NULL, NULL, -1, pjsua_var.fwType
#ifdef INCLUDE_VOIP_SUPPORT_IPV6
, AF_INET
#endif /* INCLUDE_VOIP_SUPPORT_IPV6 */
, pjsua_var.tcMark);
if (status != PJ_SUCCESS)
{
pjsua_perror(THIS_FILE, "Error create Netfilter rule", status);
return status;
}
#ifdef INCLUDE_VOIP_SUPPORT_IPV6
}
#endif /* INCLUDE_VOIP_SUPPORT_IPV6 */
CMSIP_PRINT("=============add iptables rule end====================================");
pFwRule = &call->fwRule[0];
memset(pFwRule, 0, sizeof(PJ_FIREWALL_RULE));
pFwRule->protocol = PJ_TRANSPORT_UDP;
strcpy(pFwRule->dstBuf, localIp);
pFwRule->destination = pj_str(pFwRule->dstBuf);
pFwRule->dport = localPort;
pFwRule->sport = -1;
pFwRule->family = family;
status = pj_firewall_set_rule_accept(PJ_FIREWALLCFG_ADD, PJ_TRANSPORT_UDP,
&ip, NULL, localRtcpPort, NULL, NULL, -1, pj_firewall_get_fwtype(family)
#ifdef INCLUDE_VOIP_SUPPORT_IPV6
, family
#endif /* INCLUDE_VOIP_SUPPORT_IPV6 */
, pjsua_var.tcMark);
if (status != PJ_SUCCESS)
{
#ifdef INCLUDE_VOIP_SUPPORT_IPV6
if (AF_INET == family)
{
#endif /* INCLUDE_VOIP_SUPPORT_IPV6 */
pj_firewall_set_rule_accept(PJ_FIREWALLCFG_DEL, PJ_TRANSPORT_UDP,
&ip, NULL, localPort, NULL, NULL, -1, pjsua_var.fwType
#ifdef INCLUDE_VOIP_SUPPORT_IPV6
, pj_AF_INET()
#endif /* INCLUDE_VOIP_SUPPORT_IPV6 */
, pjsua_var.tcMark);
#ifdef INCLUDE_VOIP_SUPPORT_IPV6
}
#endif /* INCLUDE_VOIP_SUPPORT_IPV6 */
pjsua_perror(THIS_FILE, "Error create Netfilter rule", status);
return status;
}
CMSIP_PRINT("=============add iptables rule end====================================");
pFwRule = &call->fwRule[1];
memset(pFwRule, 0, sizeof(PJ_FIREWALL_RULE));
pFwRule->protocol = PJ_TRANSPORT_UDP;
strcpy(pFwRule->dstBuf, localIp);
pFwRule->destination = pj_str(pFwRule->dstBuf);
pFwRule->dport = localRtcpPort;
pFwRule->sport = -1;
pFwRule->family = family;
}
#endif
/* Create SDP */
status = pjmedia_endpt_create_sdp_t38(pjsua_var.med_endpt, pool, MAX_MEDIA,
&tpinfo.sock_info, &sdp);
if (status != PJ_SUCCESS)
{
if (sip_status_code)
{
*sip_status_code = 500;
}
return status;
}
/* If we're answering and the selected media is not the first media
* in SDP, then fill in the unselected media with with zero port.
* Otherwise we'll crash in transport_encode_sdp() because the media
* lines are not aligned between offer and answer.
*/
if (rem_sdp && call->audio_idx != 0)
{
unsigned i;
for (i=0; i<rem_sdp->media_count; ++i)
{
const pjmedia_sdp_media *rem_m = rem_sdp->media[i];
pjmedia_sdp_media *m;
const pjmedia_sdp_attr *a;
if ((int)i == call->audio_idx)
continue;
m = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media);
pj_strdup(pool, &m->desc.media, &rem_m->desc.media);
pj_strdup(pool, &m->desc.transport, &rem_m->desc.transport);
m->desc.port = 0;
/* Add one format, copy from the offer. And copy the corresponding
* rtpmap and fmtp attributes too.
*/
m->desc.fmt_count = 1;
pj_strdup(pool, &m->desc.fmt[0], &rem_m->desc.fmt[0]);
if ((a=pjmedia_sdp_attr_find2(rem_m->attr_count, rem_m->attr,
"rtpmap", &m->desc.fmt[0])) != NULL)
{
m->attr[m->attr_count++] = pjmedia_sdp_attr_clone(pool, a);
}
if ((a=pjmedia_sdp_attr_find2(rem_m->attr_count, rem_m->attr,
"fmtp", &m->desc.fmt[0])) != NULL)
{
m->attr[m->attr_count++] = pjmedia_sdp_attr_clone(pool, a);
}
if (i==sdp->media_count)
sdp->media[sdp->media_count++] = m;
else {
pj_array_insert(sdp->media, sizeof(sdp->media[0]),
sdp->media_count, i, &m);
++sdp->media_count;
}
}
}
#if SUPPORT_STUN
/* Add NAT info in the SDP */
if (pjsua_var.ua_cfg.nat_type_in_sdp)
{
pjmedia_sdp_attr *a;
pj_str_t value;
char nat_info[80];
value.ptr = nat_info;
if (pjsua_var.ua_cfg.nat_type_in_sdp == 1)
{
value.slen = pj_ansi_snprintf(nat_info, sizeof(nat_info),
"%d", pjsua_var.nat_type);
}
else
{
const char *type_name = pj_stun_get_nat_name(pjsua_var.nat_type);
value.slen = pj_ansi_snprintf(nat_info, sizeof(nat_info),
"%d %s",
pjsua_var.nat_type,
type_name);
}
a = pjmedia_sdp_attr_create(pool, "X-nat", &value);
pjmedia_sdp_attr_add(&sdp->attr_count, sdp->attr, a);
}
#endif /* SUPPORT_STUN */
/* Give the SDP to media transport */
/* pjsip will crash if the result of negotiation is T38 and this media is the peer's second media */
#if 0
status = pjmedia_transport_encode_sdp(call->med_tp, pool, sdp, rem_sdp, call->audio_idx);
#else
if (rem_sdp)
{
status = pjmedia_transport_encode_sdp(call->med_tp, pool, sdp, rem_sdp, call->audio_idx);
} else
{
status = pjmedia_transport_encode_sdp(call->med_tp, pool, sdp, rem_sdp, 0);
}
#endif
if (status != PJ_SUCCESS)
{
if (sip_status_code) *sip_status_code = PJSIP_SC_NOT_ACCEPTABLE;
return status;
}
/* Update currently advertised RTP source address */
pj_memcpy(&call->med_rtp_addr, &tpinfo.sock_info.rtp_addr_name, sizeof(pj_sockaddr));
*p_sdp = sdp;
return PJ_SUCCESS;
}
static void stop_media_session(pjsua_call_id call_id)
{
CMSIP_PRINT("--Now, stop media session-------");
/*ycw-pjsip:here*/
pjsua_call *call = &pjsua_var.calls[call_id];
/*ycw-pjsip-delete conference*/
#if 0
if (call->conf_slot != PJSUA_INVALID_ID) {
if (pjsua_var.mconf) {
pjsua_conf_remove_port(call->conf_slot);
}
call->conf_slot = PJSUA_INVALID_ID;
}
#endif
/*ycw-pjsip*/
PJSUA_LOCK();
if (call->session)
{
/*ycw-pjsip.20111104*/
#if 0
pjmedia_rtcp_stat stat;
if ((call->media_dir & PJMEDIA_DIR_ENCODING)
#if 0
&&
(pjmedia_session_get_stream_stat(call->session, 0, &stat)
== PJ_SUCCESS)
#endif
)
{
/* Save RTP timestamp & sequence, so when media session is
* restarted, those values will be restored as the initial
* RTP timestamp & sequence of the new media session. So in
* the same call session, RTP timestamp and sequence are
* guaranteed to be contigue.
*/
#if 0
call->rtp_tx_seq_ts_set = 1 | (1 << 1);
call->rtp_tx_seq = stat.rtp_tx_last_seq;
call->rtp_tx_ts = stat.rtp_tx_last_ts;
#endif
}
#endif
if (pjsua_var.ua_cfg.cb.on_stream_destroyed)
{
pjsua_var.ua_cfg.cb.on_stream_destroyed(call_id, call->session, 0);
}
pjmedia_session_destroy(call->session, call_id, call->cmHangup
#if defined(PJ_MEDIA_TRANSIT_BY_PJSIP) && 0==PJ_MEDIA_TRANSIT_BY_PJSIP
#if defined(INCLUDE_USB_VOICEMAIL)
, call->isUsbVm
#endif
#endif
# if defined(PJSIP_HAS_FIREWALL_FILTER) && PJSIP_HAS_FIREWALL_FILTER!=0
#ifdef INCLUDE_VOIP_SUPPORT_IPV6
,pj_firewall_get_fwtype(call->fwRule[0].family)
#else
,pjsua_var.fwType
#endif
, pjsua_var.tcMark
#endif
);
call->session = NULL;
PJ_LOG(4,(THIS_FILE, "Media session for call %d is destroyed",
call_id));
}
call->media_st = PJSUA_CALL_MEDIA_NONE;
/*ycw-pjsip*/
PJSUA_UNLOCK();
CMSIP_PRINT("---stop media session. media state is none");
}
pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id)
{
pjsua_call *call = &pjsua_var.calls[call_id];
stop_media_session(call_id);
# if defined(PJ_MEDIA_TRANSIT_BY_PJSIP) && 0==PJ_MEDIA_TRANSIT_BY_PJSIP
if (
# if defined(INCLUDE_USB_VOICEMAIL)
call->isUsbVm == PJ_TRUE
# else
0
# endif
||
# if defined(INCLUDE_PSTN_GATEWAY)
call->isPstn
# else
0
# endif
)
{
# if defined(INCLUDE_USB_VOICEMAIL) || defined(INCLUDE_PSTN_GATEWAY)
pjsua_media_transport_destroy_for_single_call(call_id);
# endif
}
# endif
if (call->med_tp_st != PJSUA_MED_TP_IDLE) {
pjmedia_transport_media_stop(call->med_tp);
call->med_tp_st = PJSUA_MED_TP_IDLE;
}
if (call->med_orig && call->med_tp && call->med_tp != call->med_orig) {
pjmedia_transport_close(call->med_tp);
call->med_tp = call->med_orig;
}
/*ycw-pjsip-delete sound device*/
#if 0
check_snd_dev_idle();
#endif
# if (defined(PJ_MEDIA_TRANSIT_BY_PJSIP) && 0==PJ_MEDIA_TRANSIT_BY_PJSIP) && \
(defined(INCLUDE_PSTN_GATEWAY) || defined(INCLUDE_USB_VOICEMAIL))
call->medTpReady = PJ_FALSE;
# endif
return PJ_SUCCESS;
}
# if 0
/*
* DTMF callback from the stream.
*/
static void dtmf_callback(pjmedia_stream *strm, void *user_data,
int digit)
{
PJ_UNUSED_ARG(strm);
/* For discussions about call mutex protection related to this
* callback, please see ticket #460:
* http://trac.pjsip.org/repos/ticket/460#comment:4
*/
if (pjsua_var.ua_cfg.cb.on_dtmf_digit) {
pjsua_call_id call_id;
call_id = (pjsua_call_id)(long)user_data;
pjsua_var.ua_cfg.cb.on_dtmf_digit(call_id, digit);
}
}
# endif
pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
const pjmedia_sdp_session *local_sdp,
const pjmedia_sdp_session *remote_sdp)
{
pjsua_call *call = &pjsua_var.calls[call_id];
pjmedia_session_info sess_info;
pjmedia_stream_info *si = NULL;
pj_status_t status;
unsigned i;
#if defined(PJSIP_HAS_FIREWALL_FILTER) && PJSIP_HAS_FIREWALL_FILTER!=0
PJ_FIREWALL_RULE* pFwRule = NULL;
#endif
char localIp[CMSIP_STR_40] = {0};
pj_uint16_t rtpPort = 0;
pj_uint16_t rtcpPort = 0;
pj_str_t tmpStr;
int family = AF_INET;
if (!pjsua_var.med_endpt)
{
/* We're being shutdown */
return PJ_EBUSY;
}
/*ycw-pjsip*/
/*we must compare the new stream with the old stram to decide to destroy the old stream or not*/
/* Destroy existing media session, if any. */
#if 0
prev_media_st = call->media_st;
stop_media_session(call->index);
#endif
memset(&sess_info, 0, sizeof(sess_info));
/* Create media session info based on SDP parameters.
*/
status = pjmedia_session_info_from_sdp( call->inv->pool_prov,
pjsua_var.med_endpt,
PJMEDIA_MAX_SDP_MEDIA, &sess_info,
local_sdp, remote_sdp);
if (status != PJ_SUCCESS)
{
return status;
}
for (i = 0; i < sess_info.stream_cnt; ++i)
{
if (sess_info.stream_info[i].dir == PJMEDIA_DIR_NONE)
{
continue;
}
if (sess_info.stream_info[i].ulptime== 0)
{
sess_info.stream_info[i].ulptime = 20;
}
}
/* Update audio index from the negotiated SDP */
call->audio_idx = find_audio_index(local_sdp, PJ_TRUE);
CMSIP_PRINT("---call audio index(%d)---", call->audio_idx);
/* Find which session is audio */
PJ_ASSERT_RETURN(call->audio_idx != -1, PJ_EBUG);
PJ_ASSERT_RETURN(call->audio_idx < (int)sess_info.stream_cnt, PJ_EBUG);
si = &sess_info.stream_info[call->audio_idx];
/* Reset session info with only one media stream */
sess_info.stream_cnt = 1;
CMSIP_PRINT("-----stream cnt(%d)---", sess_info.stream_cnt);
/*ycw-pjsip-t38. Ŀǰֻ֧��һ����*/
if (si != &sess_info.stream_info[0])
{
pj_memcpy(&sess_info.stream_info[0], si, sizeof(pjmedia_stream_info));
si = &sess_info.stream_info[0];
}
pjmedia_transport_udp_local_info(call->med_orig, localIp, &rtpPort, &rtcpPort, &family);
CMSIP_PRINT("Get local rtp network address:%s:%d", localIp, rtpPort);
CMSIP_PRINT("Get local rtcp network address:%s:%d", localIp, rtcpPort);
CMSIP_PRINT("Get local family:%d(AF_INET:%d,AF_INET6:%d)", family, AF_INET, AF_INET6);
tmpStr = pj_str(localIp);
pj_sockaddr_init(family, &si->local_addr, &tmpStr, rtpPort);
pj_sockaddr_init(family, &si->local_rtcp, &tmpStr, rtcpPort);
/*ycw-pjsip-t38*/
/*for the new re-INVITE, we accept all. But, we must check the new stream equal the
old stream or not. If they are same, we need not re-create the stream*/
if (call->session &&
call->session->stream_cnt == sess_info.stream_cnt &&
pjsua_media_stream_info_equal(&call->session->stream_info[0], si)
/*now, just support one stream */)
{
CMSIP_PRINT("----the existed session has the same transport info, do not re-create--");
goto ON_SUCCESS;
}
CMSIP_PRINT("destroy old stream, create new stream.");
/*ycw-pjsip*/
stop_media_session(call->index);
/* Check if no media is active */
if (sess_info.stream_cnt == 0 || si->dir == PJMEDIA_DIR_NONE)
{
/* Call media state */
call->media_st = PJSUA_CALL_MEDIA_NONE;
/* Call media direction */
call->media_dir = PJMEDIA_DIR_NONE;
/* Don't stop transport because we need to transmit keep-alives, and
* also to prevent restarting ICE negotiation. See
* http://trac.pjsip.org/repos/ticket/1094
*/
#if 0
/* Shutdown transport's session */
pjmedia_transport_media_stop(call->med_tp);
call->med_tp_st = PJSUA_MED_TP_IDLE;
/* No need because we need keepalive? */
/* Close upper entry of transport stack */
if (call->med_orig && (call->med_tp != call->med_orig)) {
pjmedia_transport_close(call->med_tp);
call->med_tp = call->med_orig;
}
#endif
}
else
{
pjmedia_transport_info tp_info;
/* Start/restart media transport */
CMSIP_PRINT("----start media transport-------------");
status = pjmedia_transport_media_start(call->med_tp,
call->inv->pool_prov,
local_sdp, remote_sdp,
call->audio_idx);
if (status != PJ_SUCCESS)
return status;
CMSIP_PRINT("-----media transport state is running---------");
call->med_tp_st = PJSUA_MED_TP_RUNNING;
/* Get remote SRTP usage policy */
pjmedia_transport_info_init(&tp_info);
pjmedia_transport_get_info(call->med_tp, &tp_info);
if (tp_info.specific_info_cnt > 0)
{
unsigned i;
for (i = 0; i < tp_info.specific_info_cnt; ++i)
{
if (tp_info.spc_info[i].type == PJMEDIA_TRANSPORT_TYPE_SRTP)
{
pjmedia_srtp_info *srtp_info =
(pjmedia_srtp_info*) tp_info.spc_info[i].buffer;
call->rem_srtp_use = srtp_info->peer_use;
break;
}
}
}
/*ycw-pjsip*/
#if 0
/* Override ptime, if this option is specified. */
if (pjsua_var.media_cfg.ptime != 0)
{
si->param->setting.frm_per_pkt = (pj_uint8_t)
(pjsua_var.media_cfg.ptime / si->param->info.frm_ptime);
if (si->param->setting.frm_per_pkt == 0)
si->param->setting.frm_per_pkt = 1;
}
#endif
/* Disable VAD, if this option is specified. */
if (pjsua_var.media_cfg.no_vad)
{
si->param->setting.vad = 0;
}
/* Optionally, application may modify other stream settings here
* (such as jitter buffer parameters, codec ptime, etc.)
*/
#if 0
si->jb_init = pjsua_var.media_cfg.jb_init;
si->jb_min_pre = pjsua_var.media_cfg.jb_min_pre;
si->jb_max_pre = pjsua_var.media_cfg.jb_max_pre;
si->jb_max = pjsua_var.media_cfg.jb_max;
#endif
/* ycw-pjsip: vbd support */
if (call->request_channel_mode == pj_channel_passthrough)
{
#if 0
si->jb_min_pre = si->jb_max_pre = -2;
#endif
si->vad = si->cng = 0;
}
/* Set SSRC */
#if 0
si->ssrc = call->ssrc;
#endif
/* Set RTP timestamp & sequence, normally these value are intialized
* automatically when stream session created, but for some cases (e.g:
* call reinvite, call update) timestamp and sequence need to be kept
* contigue.
*/
#if 0
si->rtp_ts = call->rtp_tx_ts;
si->rtp_seq = call->rtp_tx_seq;
si->rtp_seq_ts_set = call->rtp_tx_seq_ts_set;
#endif
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
/* Enable/disable stream keep-alive and NAT hole punch. */
si->use_ka = (call->acc_id >= 0) ? pjsua_var.acc[call->acc_id].cfg.use_stream_ka : PJ_TRUE;
#endif
/* Create session based on session info. */
status = pjmedia_session_create( pjsua_var.med_endpt, &sess_info,
&call->med_orig, call, call_id,
# if (!(defined(PJ_MEDIA_TRANSIT_BY_PJSIP) && 0==PJ_MEDIA_TRANSIT_BY_PJSIP) || \
defined(INCLUDE_PSTN_GATEWAY))
&call->dsp_med_tp,
# endif
# if defined(PJ_MEDIA_TRANSIT_BY_PJSIP) && 0==PJ_MEDIA_TRANSIT_BY_PJSIP
# if defined(INCLUDE_USB_VOICEMAIL)
call->isUsbVm,
# endif
# if defined(INCLUDE_PSTN_GATEWAY)
call->isPstn,
# endif
# endif
# if defined(PJSIP_HAS_FIREWALL_FILTER) && PJSIP_HAS_FIREWALL_FILTER!=0
#ifdef INCLUDE_VOIP_SUPPORT_IPV6
pj_firewall_get_fwtype(call->fwRule[0].family),
#else
pjsua_var.fwType,
#endif
pjsua_var.tcMark,
# endif
&call->session );
if (status != PJ_SUCCESS)
{
return status;
}
#if defined(PJSIP_HAS_FIREWALL_FILTER) && PJSIP_HAS_FIREWALL_FILTER!=0
for (i = 0; i < PJ_ARRAY_SIZE(call->fwRule); ++i)
{
pFwRule = &call->fwRule[i];
if (pFwRule->destination.slen > 0 && pFwRule->dport > 0)
{
status = pj_firewall_set_rule_accept(PJ_FIREWALLCFG_DEL, pFwRule->protocol,
&(pFwRule->destination), NULL, pFwRule->dport, NULL, NULL, -1,
pj_firewall_get_fwtype(pFwRule->family)
#ifdef INCLUDE_VOIP_SUPPORT_IPV6
, pFwRule->family
#endif /* INCLUDE_VOIP_SUPPORT_IPV6 */
, pjsua_var.tcMark);
if (status != PJ_SUCCESS)
{
printf("==%s,%d==firewall rule set error!!!!====", __FUNCTION__,
__LINE__);
}
}
memset(pFwRule, 0, sizeof(PJ_FIREWALL_RULE));
}
#endif
CMSIP_PRINT("----session create successfully--------------------------------");
/* If DTMF callback is installed by application, install our
* callback to the session.
*/
if (pjsua_var.ua_cfg.cb.on_dtmf_digit)
{
#if 0
pjmedia_session_set_dtmf_callback(call->session, 0,
&dtmf_callback,
(void*)(long)(call->index));
#endif
}
/* Call media direction */
call->media_dir = si->dir;
/* Call media state */
if (call->local_hold)
{
call->media_st = PJSUA_CALL_MEDIA_LOCAL_HOLD;
}
else if (call->media_dir == PJMEDIA_DIR_DECODING)
{
call->media_st = PJSUA_CALL_MEDIA_REMOTE_HOLD;
}
else
{
call->media_st = PJSUA_CALL_MEDIA_ACTIVE;
}
}
ON_SUCCESS:
/* Print info. */
{
char info[80];
int info_len = 0;
unsigned i;
for (i = 0; i < sess_info.stream_cnt; ++i)
{
int len;
const char *dir;
pjmedia_stream_info *strm_info = &sess_info.stream_info[i];
switch (strm_info->dir)
{
case PJMEDIA_DIR_NONE:
dir = "inactive";
break;
case PJMEDIA_DIR_ENCODING:
dir = "sendonly";
break;
case PJMEDIA_DIR_DECODING:
dir = "recvonly";
break;
case PJMEDIA_DIR_ENCODING_DECODING:
dir = "sendrecv";
break;
default:
dir = "unknown";
break;
}
len = pj_ansi_sprintf( info+info_len,
", stream #%d: %.*s (%s)", i,
(int)strm_info->fmt.encoding_name.slen,
strm_info->fmt.encoding_name.ptr,
dir);
if (len > 0)
{
info_len += len;
}
}
PJ_LOG(4,(THIS_FILE,"Media updates%s", info));
}
return PJ_SUCCESS;
}
在这段代码插入我的一个需求,也就是通知内核态接下来rtp的端口你觉得适合吗