pj_status_t pjsua_media_channel_create_sdp(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];
pjmedia_sdp_neg_state sdp_neg_state = PJMEDIA_SDP_NEG_STATE_NULL;
pj_status_t status;
/*ycw-pjsip-codec*/
#if 1
pjsua_acc* acc = NULL;
unsigned i;
pj_str_t* codec = NULL;
pjsua_codec_info c[32];
unsigned count = PJ_ARRAY_SIZE(c);/*ycw-pjsip. Must init, or there would be a error.*/
#endif
pj_bool_t offer_has_telephone_evt = PJ_FALSE;
# ifdef SUPPORT_METABOLIC_MEDIA_PORT
pj_uint16_t medport;
pj_bool_t portAvaible = PJ_TRUE;
# 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;
# if defined(SUPPORT_IPCALL_NO_ACCOUNT) && SUPPORT_IPCALL_NO_ACCOUNT!=0
if (call->acc_id>=0)
{
# endif
acc = &pjsua_var.acc[call->acc_id];
# if defined(SUPPORT_IPCALL_NO_ACCOUNT) && SUPPORT_IPCALL_NO_ACCOUNT!=0
}
# endif
CMSIP_PRINT("--call[%d],account[%d], rem_sdp[%p]", call_id, call->acc_id, rem_sdp);
/* Return error if media transport has not been created yet
* (e.g. application is starting)
*/
if (call->med_tp == NULL)
{
return PJ_EBUSY;
}
/*ycw-pjsip-codec*/
if (
# if defined(INCLUDE_PSTN_GATEWAY)
(PJ_TRUE == call->isPstn)
# else
0
# endif
||
# if (defined(SUPPORT_FAX_T38) && SUPPORT_FAX_T38!=0)
(PJ_TRUE == call->isFaxPassthrough)
# else
0
# endif
||
# if (defined(PJ_MEDIA_TRANSIT_BY_PJSIP) && 0==PJ_MEDIA_TRANSIT_BY_PJSIP) && \
defined(INCLUDE_USB_VOICEMAIL)
PJ_TRUE == call->isUsbVm
# else
0
# endif
||
# if (defined(NUM_VOICEAPP_CHANNELS) && 0!=NUM_VOICEAPP_CHANNELS)
PJ_TRUE == call->isVoiceapp
# else
0
# endif
)
{
# if defined(INCLUDE_PSTN_GATEWAY) || \
((defined(PJ_MEDIA_TRANSIT_BY_PJSIP) && 0==PJ_MEDIA_TRANSIT_BY_PJSIP)&& defined(INCLUDE_USB_VOICEMAIL))\
|| (defined(SUPPORT_FAX_T38) && SUPPORT_FAX_T38!=0) || (defined(NUM_VOICEAPP_CHANNELS) && 0!=NUM_VOICEAPP_CHANNELS)
pjsua_codec_mgr_switch_to_lite();
# endif
}
else
{
pjsua_codec_mgr_switch_to_full();
}
pjsua_enum_codecs(c, &count);
for(i = 0; i < count; ++i)
{
codec = &c[i].codec_id;
status = pjsua_codec_set_priority(codec, PJMEDIA_CODEC_PRIO_NORMAL);
if (status != PJ_SUCCESS)
{
pjsua_perror(THIS_FILE, "Error reset codecs' priority!", status);
return status;
}
}
# if defined(SUPPORT_IPCALL_NO_ACCOUNT) && SUPPORT_IPCALL_NO_ACCOUNT!=0
if (acc)
{
# endif
CMSIP_PRINT("------------haha,I can use account(%d)---", acc->index);
for (i = 0, count = 0; i < acc->cfg.codec_cnt; ++i)
{
codec = &acc->cfg.codecs[i];
if (PJ_TRUE == pjsua_codec_mgr_codec_is_exist(codec))
{
status = pjsua_codec_set_priority(codec, PJMEDIA_CODEC_PRIO_HIGHEST - i);
if (status != PJ_SUCCESS)
{
pjsua_perror(THIS_FILE, "Error reset codecs' priority!", status);
return status;
}
++count;
}
}
# if defined(SUPPORT_IPCALL_NO_ACCOUNT) && SUPPORT_IPCALL_NO_ACCOUNT!=0
}
# endif
if (rem_sdp && rem_sdp->media_count != 0)
{
pj_bool_t srtp_active;
#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
# if defined(SUPPORT_IPCALL_NO_ACCOUNT) && SUPPORT_IPCALL_NO_ACCOUNT!=0
if (acc)
{
# endif
srtp_active = pjsua_var.acc[call->acc_id].cfg.use_srtp;
# if defined(SUPPORT_IPCALL_NO_ACCOUNT) && SUPPORT_IPCALL_NO_ACCOUNT!=0
}
else
{
srtp_active = PJ_FALSE;
}
# endif
#else
srtp_active = PJ_FALSE;
#endif
call->audio_idx = find_audio_index(rem_sdp, srtp_active);
if (call->audio_idx == -1)
{
/* No audio in the offer. We can't accept this */
PJ_LOG(4,(THIS_FILE,
"Unable to accept SDP offer without audio for call %d",
call_id));
return PJMEDIA_SDP_EINMEDIA;
}
CMSIP_PRINT("---select Media Index[%d] for call[%d]", call->audio_idx, call->index);
}
/* 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)
{
/*ycw-pjsip:�����Ҫ��̬�������䣬���������ʵ��*/
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 SDP negotiator state */
if (call->inv && call->inv->neg)
{
sdp_neg_state = pjmedia_sdp_neg_get_state(call->inv->neg);
}
/* 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);
CMSIP_PRINT("-------Media port is (%d)----", medport);
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)
{
CMSIP_PRINT("--------test media port error----------");
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);
#ifdef INCLUDE_VOIP_SUPPORT_IPV6
if (AF_INET == family)
{
#endif /* INCLUDE_VOIP_SUPPORT_IPV6 */
/*����DMZ������ʱ������Է���rtp�ȵ����ʹ�ñ�������DUT VOIP��rtp���ݰ�֮��ֱ��
��DMZ��iptables����ת��������DUT VOIP�����յ����ݰ�������������Ҫ�ڷ���INVITE֮
ǰ�Ϳ�����Ӧ�˿ڡ�by yuchuwei*/
/*now, only support UDP*/
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 */
/*ycw-pjsip.Current only one media*/
if (rem_sdp && rem_sdp->media_count > 0)
{
int k;
pjmedia_sdp_media* m = rem_sdp->media[0];
pjmedia_sdp_attr* attr = NULL;
pjmedia_sdp_rtpmap rtpmap;
for (k = 0; k < m->desc.fmt_count; ++k)
{
attr = pjmedia_sdp_media_find_attr2(m, "rtpmap", &m->desc.fmt[k]);
if (!attr) continue;
pjmedia_sdp_attr_get_rtpmap(attr, &rtpmap);
if (!pj_stricmp2(&rtpmap.enc_name, "telephone-event"))
{
offer_has_telephone_evt = PJ_TRUE;
}
}
}
/*ycw-pjsip-ptime*/
#if 0
status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, pool, MAX_MEDIA,
&tpinfo.sock_info, &sdp);
#else
status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, pool, MAX_MEDIA,
&tpinfo.sock_info,
# if defined(SUPPORT_IPCALL_NO_ACCOUNT) && SUPPORT_IPCALL_NO_ACCOUNT!=0
acc ? acc->cfg.ptime : PJSUA_DEFAULT_LOCAL_PTIME,
# else
acc->cfg.ptime,
# endif
offer_has_telephone_evt, &sdp);
#endif
if (status != PJ_SUCCESS)
{
if (sip_status_code)
{
*sip_status_code = 500;
}
return status;
}
/* If we're answering or updating the session with a new offer,
* 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 (call->audio_idx != 0 && (rem_sdp || sdp_neg_state==PJMEDIA_SDP_NEG_STATE_DONE))
{
unsigned i;
const pjmedia_sdp_session *ref_sdp = rem_sdp;
if (!ref_sdp)
{
/* We are updating session with a new offer */
status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &ref_sdp);
pj_assert(status == PJ_SUCCESS);
}
CMSIP_PRINT("--ref sdp's media count[%d]", ref_sdp->media_count);
for (i=0; i<ref_sdp->media_count; ++i)
{
const pjmedia_sdp_media *ref_m = ref_sdp->media[i];
pjmedia_sdp_media *m;
if ((int)i == call->audio_idx)
{
continue;
}
m = pjmedia_sdp_media_clone_deactivate(pool, ref_m);
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 */
status = pjmedia_transport_encode_sdp(call->med_tp, pool, sdp, rem_sdp,
call->audio_idx);
if (status != PJ_SUCCESS)
{
if (sip_status_code)
{
*sip_status_code = PJSIP_SC_NOT_ACCEPTABLE;
}
return status;
}
char buf[16];
int len = snprintf(buf,"%d", medport);
int fd = open("/proc/voip_port", O_WRONLY);
if (fd > 0 )
{
write(fd, buf, len);
close(fd);
}
else
{
close(fd);
CMSIP_PRINT("--------open /proc/voip_port error----------");
}
#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
/* Check if SRTP is in optional mode and configured to use duplicated
* media, i.e: secured and unsecured version, in the SDP offer.
*/
if (!rem_sdp && acc &&
pjsua_var.acc[call->acc_id].cfg.use_srtp == PJMEDIA_SRTP_OPTIONAL &&
pjsua_var.acc[call->acc_id].cfg.srtp_optional_dup_offer)
{
unsigned i;
for (i = 0; i < sdp->media_count; ++i) {
pjmedia_sdp_media *m = sdp->media[i];
/* Check if this media is unsecured but has SDP "crypto"
* attribute.
*/
if (pj_stricmp2(&m->desc.transport, "RTP/AVP") == 0 &&
pjmedia_sdp_media_find_attr2(m, "crypto", NULL) != NULL)
{
if (i == (unsigned)call->audio_idx &&
sdp_neg_state == PJMEDIA_SDP_NEG_STATE_DONE)
{
/* This is a session update, and peer has chosen the
* unsecured version, so let's make this unsecured too.
*/
pjmedia_sdp_media_remove_all_attr(m, "crypto");
} else {
/* This is new offer, duplicate media so we'll have
* secured (with "RTP/SAVP" transport) and and unsecured
* versions.
*/
pjmedia_sdp_media *new_m;
/* Duplicate this media and apply secured transport */
new_m = pjmedia_sdp_media_clone(pool, m);
pj_strdup2(pool, &new_m->desc.transport, "RTP/SAVP");
/* Remove the "crypto" attribute in the unsecured media */
pjmedia_sdp_media_remove_all_attr(m, "crypto");
/* Insert the new media before the unsecured media */
if (sdp->media_count < PJMEDIA_MAX_SDP_MEDIA) {
pj_array_insert(sdp->media, sizeof(new_m),
sdp->media_count, i, &new_m);
++sdp->media_count;
++i;
}
}
}
}
}
#endif
/* 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;
}/src/pjsua-lib/pjsua_media.c:2169:34: error: 'medport' undeclared (first use in this function)
int len = snprintf(buf,"%d", medport);
^
../src/pjsua-lib/pjsua_media.c:2169:34: note: each undeclared identifier is reported only once for each function it appears in
../src/pjsua-lib/pjsua_media.c:2169:28: warning: passing argument 2 of 'snprintf' makes integer from pointer without a cast
int len = snprintf(buf,"%d", medport);
^
In file included from ../../pjlib/include/pj/compat/string.h:39:0,
from ../../pjlib/include/pj/string.h:29,
from ../include/pjsip/sip_transport_tls.h:30,
from ../include/pjsip.h:45,
最新发布