summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2016-11-14 06:13:01 +0000
committerNanang Izzuddin <nanang@teluu.com>2016-11-14 06:13:01 +0000
commite297e570a9b9eebe2209f3013972d560eae31f1a (patch)
treea8b2d7ffda16c83b6ff42649cecb62ea584058f0
parent5edcbe5108e722951f3dc1f6453a33d25184973c (diff)
Re #1971: Request IPv4 relay address to an IPv6 TURN server for IPv6-IPv4 connectivity.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@5481 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjnath/include/pjnath/config.h2
-rw-r--r--pjnath/include/pjnath/turn_session.h10
-rw-r--r--pjnath/src/pjnath/ice_strans.c15
-rw-r--r--pjnath/src/pjnath/turn_session.c33
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c31
5 files changed, 81 insertions, 10 deletions
diff --git a/pjnath/include/pjnath/config.h b/pjnath/include/pjnath/config.h
index d5f69164..90dde5f3 100644
--- a/pjnath/include/pjnath/config.h
+++ b/pjnath/include/pjnath/config.h
@@ -263,7 +263,7 @@
* Default: 2
*/
#ifndef PJ_ICE_MAX_TURN
-# define PJ_ICE_MAX_TURN 2
+# define PJ_ICE_MAX_TURN 3
#endif
diff --git a/pjnath/include/pjnath/turn_session.h b/pjnath/include/pjnath/turn_session.h
index e4ae4d7b..cc3d5d8d 100644
--- a/pjnath/include/pjnath/turn_session.h
+++ b/pjnath/include/pjnath/turn_session.h
@@ -330,6 +330,16 @@ typedef struct pj_turn_alloc_param
*/
int ka_interval;
+ /**
+ * The requested ADDRESS-FAMILY. Default is zero to request relay with
+ * address family matched to the one specified in TURN session creation.
+ * Valid values are zero, pj_AF_INET(), and pj_AF_INET6().
+ *
+ * Default value is zero.
+ */
+ int af;
+
+
} pj_turn_alloc_param;
diff --git a/pjnath/src/pjnath/ice_strans.c b/pjnath/src/pjnath/ice_strans.c
index 19e3bb12..1b0148de 100644
--- a/pjnath/src/pjnath/ice_strans.c
+++ b/pjnath/src/pjnath/ice_strans.c
@@ -1991,6 +1991,21 @@ static void turn_on_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state,
/* Set default candidate to relay */
comp->default_cand = (unsigned)(cand - comp->cand_list);
+ /* Prefer IPv4 relay as default candidate for better connectivity
+ * with IPv4 endpoints.
+ */
+ if (cand->addr.addr.sa_family != pj_AF_INET()) {
+ for (i=0; i<comp->cand_cnt; ++i) {
+ if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_RELAYED &&
+ comp->cand_list[i].addr.addr.sa_family == pj_AF_INET() &&
+ comp->cand_list[i].status == PJ_SUCCESS)
+ {
+ comp->default_cand = i;
+ break;
+ }
+ }
+ }
+
PJ_LOG(4,(comp->ice_st->obj_name,
"Comp %d: TURN allocation complete, relay address is %s",
comp->comp_id,
diff --git a/pjnath/src/pjnath/turn_session.c b/pjnath/src/pjnath/turn_session.c
index 521bf978..d3ff6ced 100644
--- a/pjnath/src/pjnath/turn_session.c
+++ b/pjnath/src/pjnath/turn_session.c
@@ -724,6 +724,12 @@ PJ_DEF(pj_status_t) pj_turn_session_alloc(pj_turn_session *sess,
sess->state<=PJ_TURN_STATE_RESOLVED,
PJ_EINVALIDOP);
+ /* Verify address family in allocation param */
+ if (param && param->af) {
+ PJ_ASSERT_RETURN(param->af==pj_AF_INET() || param->af==pj_AF_INET6(),
+ PJ_EINVAL);
+ }
+
pj_grp_lock_acquire(sess->grp_lock);
if (param && param != &sess->alloc_param)
@@ -770,11 +776,21 @@ PJ_DEF(pj_status_t) pj_turn_session_alloc(pj_turn_session *sess,
sess->alloc_param.lifetime);
}
- /* Include ADDRESS-FAMILY for IPv6 request */
- if (sess->af == pj_AF_INET6()) {
- enum { IPV6_AF_TYPE = 0x02 << 24 };
- pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,
- PJ_STUN_ATTR_REQ_ADDR_TYPE, IPV6_AF_TYPE);
+ /* Include ADDRESS-FAMILY if requested */
+ if (sess->alloc_param.af || sess->af == pj_AF_INET6()) {
+ enum { IPV4_AF_TYPE = 0x01 << 24,
+ IPV6_AF_TYPE = 0x02 << 24 };
+
+ if (sess->alloc_param.af == pj_AF_INET6() ||
+ (sess->alloc_param.af == 0 && sess->af == pj_AF_INET6()))
+ {
+ pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,
+ PJ_STUN_ATTR_REQ_ADDR_TYPE, IPV6_AF_TYPE);
+ } else if (sess->alloc_param.af == pj_AF_INET()) {
+ /* For IPv4, only add the attribute when explicitly requested */
+ pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,
+ PJ_STUN_ATTR_REQ_ADDR_TYPE, IPV4_AF_TYPE);
+ }
}
/* Server address must be set */
@@ -1358,7 +1374,12 @@ static void on_allocate_success(pj_turn_session *sess,
"RELAY-ADDRESS attribute"));
return;
}
- if (raddr_attr && raddr_attr->sockaddr.addr.sa_family != sess->af) {
+ if (raddr_attr &&
+ ((sess->alloc_param.af != 0 &&
+ raddr_attr->sockaddr.addr.sa_family != sess->alloc_param.af) ||
+ (sess->alloc_param.af == 0 &&
+ raddr_attr->sockaddr.addr.sa_family != sess->af)))
+ {
on_session_fail(sess, method, PJNATH_EINSTUNMSG,
pj_cstr(&s, "Error: Mismatched RELAY-ADDRESS "
"address family"));
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c
index a2dfc118..8bca8700 100644
--- a/pjsip/src/pjsua-lib/pjsua_media.c
+++ b/pjsip/src/pjsua-lib/pjsua_media.c
@@ -926,10 +926,16 @@ static pj_status_t create_ice_media_transport(
if (acc_cfg->turn_cfg.enable_turn) {
ice_cfg.turn_tp_cnt = 1;
pj_ice_strans_turn_cfg_default(&ice_cfg.turn_tp[0]);
- if (use_ipv6 && PJ_ICE_MAX_TURN >= 2) {
- ice_cfg.turn_tp_cnt = 2;
+ if (use_ipv6 && PJ_ICE_MAX_TURN >= 3) {
+ ice_cfg.turn_tp_cnt = 3;
+
pj_ice_strans_turn_cfg_default(&ice_cfg.turn_tp[1]);
ice_cfg.turn_tp[1].af = pj_AF_INET6();
+
+ /* Additional candidate: IPv4 relay via IPv6 TURN server */
+ pj_ice_strans_turn_cfg_default(&ice_cfg.turn_tp[2]);
+ ice_cfg.turn_tp[2].af = pj_AF_INET6();
+ ice_cfg.turn_tp[2].alloc_param.af = pj_AF_INET();
}
/* Configure TURN server */
@@ -956,6 +962,13 @@ static pj_status_t create_ice_media_transport(
pj_memcpy(&ice_cfg.turn_tp[1].auth_cred,
&acc_cfg->turn_cfg.turn_auth_cred,
sizeof(ice_cfg.turn_tp[1].auth_cred));
+
+ ice_cfg.turn_tp[2].server = ice_cfg.turn_tp[0].server;
+ ice_cfg.turn_tp[2].port = ice_cfg.turn_tp[0].port;
+ ice_cfg.turn_tp[2].conn_type = ice_cfg.turn_tp[0].conn_type;
+ pj_memcpy(&ice_cfg.turn_tp[2].auth_cred,
+ &acc_cfg->turn_cfg.turn_auth_cred,
+ sizeof(ice_cfg.turn_tp[2].auth_cred));
}
/* Configure QoS setting */
@@ -966,6 +979,10 @@ static pj_status_t create_ice_media_transport(
ice_cfg.turn_tp[1].cfg.qos_type = cfg->qos_type;
pj_memcpy(&ice_cfg.turn_tp[1].cfg.qos_params, &cfg->qos_params,
sizeof(cfg->qos_params));
+
+ ice_cfg.turn_tp[2].cfg.qos_type = cfg->qos_type;
+ pj_memcpy(&ice_cfg.turn_tp[2].cfg.qos_params, &cfg->qos_params,
+ sizeof(cfg->qos_params));
}
/* Configure binding address */
@@ -983,12 +1000,20 @@ static pj_status_t create_ice_media_transport(
&IN6_ADDR_ANY, (pj_uint16_t)cfg->port);
ice_cfg.turn_tp[1].cfg.port_range =
ice_cfg.turn_tp[0].cfg.port_range;
+
+ pj_sockaddr_init(pj_AF_INET6(),
+ &ice_cfg.turn_tp[2].cfg.bound_addr,
+ &IN6_ADDR_ANY, (pj_uint16_t)cfg->port);
+ ice_cfg.turn_tp[2].cfg.port_range =
+ ice_cfg.turn_tp[0].cfg.port_range;
}
/* Configure max packet size */
ice_cfg.turn_tp[0].cfg.max_pkt_size = PJMEDIA_MAX_MRU;
- if (use_ipv6 && ice_cfg.turn_tp_cnt > 1)
+ if (use_ipv6 && ice_cfg.turn_tp_cnt > 1) {
ice_cfg.turn_tp[1].cfg.max_pkt_size = PJMEDIA_MAX_MRU;
+ ice_cfg.turn_tp[2].cfg.max_pkt_size = PJMEDIA_MAX_MRU;
+ }
}
pj_bzero(&ice_cb, sizeof(pjmedia_ice_cb));