summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2008-12-11 17:25:50 +0000
committerNanang Izzuddin <nanang@teluu.com>2008-12-11 17:25:50 +0000
commit39541e28cda932b119776631e1bbe1e6859f50af (patch)
treee1e369576881500820b9988a479f0ba716f0dbdc
parent1e493f5512415ff4de0beb4903a5bdf5e89941a4 (diff)
Ticket #661: Fixed transport ICE in verifying possibilities of RTCP settings in the SDP.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2376 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjmedia/src/pjmedia/transport_ice.c128
-rw-r--r--pjsip-apps/src/test-pjsua/scripts-sendto/200_ice_success_3.py35
-rw-r--r--pjsip-apps/src/test-pjsua/scripts-sendto/200_ice_success_4.py35
3 files changed, 144 insertions, 54 deletions
diff --git a/pjmedia/src/pjmedia/transport_ice.c b/pjmedia/src/pjmedia/transport_ice.c
index 907259dd..046961c0 100644
--- a/pjmedia/src/pjmedia/transport_ice.c
+++ b/pjmedia/src/pjmedia/transport_ice.c
@@ -594,6 +594,14 @@ static pj_status_t encode_session_in_sdp(struct transport_ice *tp_ice,
/* ICE has failed, application should have terminated this call */
}
+ /* Removing a=rtcp line when there is only one component. */
+ if (comp_cnt == 1) {
+ attr = pjmedia_sdp_attr_find(m->attr_count, m->attr, &STR_RTCP, NULL);
+ if (attr)
+ pjmedia_sdp_attr_remove(&m->attr_count, m->attr, attr);
+ }
+
+
return PJ_SUCCESS;
}
@@ -748,9 +756,9 @@ static pj_status_t verify_ice_sdp(struct transport_ice *tp_ice,
struct sdp_state *sdp_state)
{
const pjmedia_sdp_media *rem_m;
- const pjmedia_sdp_attr *attr, *ufrag_attr, *pwd_attr;
+ const pjmedia_sdp_attr *ufrag_attr, *pwd_attr;
const pjmedia_sdp_conn *rem_conn;
- pj_bool_t comp1_found=PJ_FALSE, comp2_found=PJ_FALSE;
+ pj_bool_t comp1_found=PJ_FALSE, comp2_found=PJ_FALSE, has_rtcp=PJ_FALSE;
pj_sockaddr rem_conn_addr, rtcp_addr;
unsigned i;
pj_status_t status;
@@ -767,7 +775,7 @@ static pj_status_t verify_ice_sdp(struct transport_ice *tp_ice,
}
/* Verify that default target for each component matches one of the
- * candidatefor the component. Otherwise stop ICE with ICE ice_mismatch
+ * candidate for the component. Otherwise stop ICE with ICE ice_mismatch
* error.
*/
@@ -793,55 +801,62 @@ static pj_status_t verify_ice_sdp(struct transport_ice *tp_ice,
if (status != PJ_SUCCESS)
return status;
- /* Component 2 is a=rtcp line, if present. */
- attr = pjmedia_sdp_attr_find(rem_m->attr_count, rem_m->attr,
- &STR_RTCP, NULL);
- if (attr && tp_ice->comp_cnt > 1) {
- pjmedia_sdp_rtcp_attr rtcp_attr;
+ if (tp_ice->comp_cnt > 1) {
+ const pjmedia_sdp_attr *attr;
- status = pjmedia_sdp_attr_get_rtcp(attr, &rtcp_attr);
- if (status != PJ_SUCCESS) {
- /* Error parsing a=rtcp attribute */
- return status;
- }
-
- if (rtcp_attr.addr.slen) {
- /* Verify address family matches */
- if ((tp_ice->af==pj_AF_INET() &&
- pj_strcmp(&rtcp_attr.addr_type, &STR_IP4)!=0) ||
- (tp_ice->af==pj_AF_INET6() &&
- pj_strcmp(&rtcp_attr.addr_type, &STR_IP6)!=0))
- {
- return PJMEDIA_SDP_ETPORTNOTEQUAL;
- }
+ /* Get default RTCP candidate from a=rtcp line, if present, otherwise
+ * calculate default RTCP candidate from default RTP target.
+ */
+ attr = pjmedia_sdp_attr_find(rem_m->attr_count, rem_m->attr,
+ &STR_RTCP, NULL);
+ has_rtcp = (attr != NULL);
+
+ if (attr) {
+ pjmedia_sdp_rtcp_attr rtcp_attr;
- /* Assign RTCP address */
- status = pj_sockaddr_init(tp_ice->af, &rtcp_addr,
- &rtcp_attr.addr,
- (pj_uint16_t)rtcp_attr.port);
+ status = pjmedia_sdp_attr_get_rtcp(attr, &rtcp_attr);
if (status != PJ_SUCCESS) {
- return PJMEDIA_SDP_EINRTCP;
+ /* Error parsing a=rtcp attribute */
+ return status;
}
- } else {
- /* Assign RTCP address */
- status = pj_sockaddr_init(tp_ice->af, &rtcp_addr,
- NULL,
- (pj_uint16_t)rtcp_attr.port);
- if (status != PJ_SUCCESS) {
- return PJMEDIA_SDP_EINRTCP;
+
+ if (rtcp_attr.addr.slen) {
+ /* Verify address family matches */
+ if ((tp_ice->af==pj_AF_INET() &&
+ pj_strcmp(&rtcp_attr.addr_type, &STR_IP4)!=0) ||
+ (tp_ice->af==pj_AF_INET6() &&
+ pj_strcmp(&rtcp_attr.addr_type, &STR_IP6)!=0))
+ {
+ return PJMEDIA_SDP_ETPORTNOTEQUAL;
+ }
+
+ /* Assign RTCP address */
+ status = pj_sockaddr_init(tp_ice->af, &rtcp_addr,
+ &rtcp_attr.addr,
+ (pj_uint16_t)rtcp_attr.port);
+ if (status != PJ_SUCCESS) {
+ return PJMEDIA_SDP_EINRTCP;
+ }
+ } else {
+ /* Assign RTCP address */
+ status = pj_sockaddr_init(tp_ice->af, &rtcp_addr,
+ NULL,
+ (pj_uint16_t)rtcp_attr.port);
+ if (status != PJ_SUCCESS) {
+ return PJMEDIA_SDP_EINRTCP;
+ }
+ pj_sockaddr_copy_addr(&rtcp_addr, &rem_conn_addr);
}
- pj_sockaddr_copy_addr(&rtcp_addr, &rem_conn_addr);
+ } else {
+ unsigned rtcp_port;
+
+ rtcp_port = pj_sockaddr_get_port(&rem_conn_addr) + 1;
+ pj_sockaddr_cp(&rtcp_addr, &rem_conn_addr);
+ pj_sockaddr_set_port(&rtcp_addr, (pj_uint16_t)rtcp_port);
}
-
- sdp_state->match_comp_cnt = 2;
-
- } else {
- /* Don't have RTCP component */
- comp2_found = PJ_TRUE;
- sdp_state->match_comp_cnt = 1;
}
- /* Find the default address in a=candidate attributes.
+ /* Find the default addresses in a=candidate attributes.
*/
for (i=0; i<rem_m->attr_count; ++i) {
pj_ice_sess_cand cand;
@@ -863,28 +878,33 @@ static pj_status_t verify_ice_sdp(struct transport_ice *tp_ice,
if (!comp1_found && cand.comp_id==COMP_RTP &&
pj_sockaddr_cmp(&rem_conn_addr, &cand.addr)==0)
{
- /* Found */
comp1_found = PJ_TRUE;
- if (comp1_found && comp2_found)
- break;
} else if (!comp2_found && cand.comp_id==COMP_RTCP &&
pj_sockaddr_cmp(&rtcp_addr, &cand.addr)==0)
{
- /* Found */
comp2_found = PJ_TRUE;
- if (comp1_found && comp2_found)
- break;
}
+ if (cand.comp_id == COMP_RTCP)
+ has_rtcp = PJ_TRUE;
+
+ if (comp1_found && (comp2_found || tp_ice->comp_cnt==1))
+ break;
}
- if (!comp1_found || !comp2_found) {
- /* ICE ice_mismatch */
- sdp_state->ice_mismatch = PJ_TRUE;
- } else {
+ /* Check matched component count and ice_mismatch */
+ if (comp1_found && (tp_ice->comp_cnt==1 || !has_rtcp)) {
+ sdp_state->match_comp_cnt = 1;
+ sdp_state->ice_mismatch = PJ_FALSE;
+ } else if (comp1_found && comp2_found) {
+ sdp_state->match_comp_cnt = 2;
sdp_state->ice_mismatch = PJ_FALSE;
+ } else {
+ sdp_state->match_comp_cnt = (tp_ice->comp_cnt > 1 && has_rtcp)? 2 : 1;
+ sdp_state->ice_mismatch = PJ_TRUE;
}
+
/* Detect remote restarting session */
if (pj_ice_strans_has_sess(tp_ice->ice_st) &&
(pj_ice_strans_sess_is_running(tp_ice->ice_st) ||
diff --git a/pjsip-apps/src/test-pjsua/scripts-sendto/200_ice_success_3.py b/pjsip-apps/src/test-pjsua/scripts-sendto/200_ice_success_3.py
new file mode 100644
index 00000000..2c741e44
--- /dev/null
+++ b/pjsip-apps/src/test-pjsua/scripts-sendto/200_ice_success_3.py
@@ -0,0 +1,35 @@
+# $Id$
+import inc_sip as sip
+import inc_sdp as sdp
+
+sdp = \
+"""
+v=0
+o=- 0 0 IN IP4 127.0.0.1
+s=pjmedia
+c=IN IP4 127.0.0.1
+t=0 0
+m=audio 4000 RTP/AVP 0 101
+a=ice-ufrag:1234
+a=ice-pwd:5678
+a=rtpmap:0 PCMU/8000
+a=sendrecv
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-15
+a=candidate:XX 1 UDP 1234 127.0.0.1 4000 typ host
+a=candidate:YY 2 UDP 1234 127.0.0.1 4001 typ host
+"""
+
+args = "--null-audio --use-ice --auto-answer 200 --max-calls 1"
+include = ["a=ice-ufrag", # must have ICE
+ "a=candidate:[0-9a-zA-Z]+ 2 UDP" # must have RTCP component
+ ]
+exclude = [
+ "ice-mismatch" # must not mismatch
+ ]
+
+sendto_cfg = sip.SendtoCfg( "caller sends two components without a=rtcp line",
+ pjsua_args=args, sdp=sdp, resp_code=200,
+ resp_inc=include, resp_exc=exclude,
+ enable_buffer = True)
+
diff --git a/pjsip-apps/src/test-pjsua/scripts-sendto/200_ice_success_4.py b/pjsip-apps/src/test-pjsua/scripts-sendto/200_ice_success_4.py
new file mode 100644
index 00000000..0ec3849c
--- /dev/null
+++ b/pjsip-apps/src/test-pjsua/scripts-sendto/200_ice_success_4.py
@@ -0,0 +1,35 @@
+# $Id$
+import inc_sip as sip
+import inc_sdp as sdp
+
+sdp = \
+"""
+v=0
+o=- 0 0 IN IP4 127.0.0.1
+s=pjmedia
+c=IN IP4 127.0.0.1
+t=0 0
+m=audio 4000 RTP/AVP 0 101
+a=rtcp:4382 IN IP4 192.168.0.4
+a=ice-ufrag:1234
+a=ice-pwd:5678
+a=rtpmap:0 PCMU/8000
+a=sendrecv
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-15
+a=candidate:XX 1 UDP 1234 127.0.0.1 4000 typ host
+a=candidate:YY 2 UDP 1234 127.0.0.2 4002 typ host
+"""
+
+args = "--null-audio --use-ice --auto-answer 200 --max-calls 1 --ice-no-rtcp"
+include = ["a=ice-ufrag"] # must have ICE
+exclude = [
+ "ice-mismatch", # must not mismatch
+ "a=candidate:[0-9a-zA-Z]+ 2 UDP" # must not have RTCP component
+ ]
+
+sendto_cfg = sip.SendtoCfg( "pjsua with --ice-no-rtcp ignores RTCP things in the SDP",
+ pjsua_args=args, sdp=sdp, resp_code=200,
+ resp_inc=include, resp_exc=exclude,
+ enable_buffer = True)
+