summaryrefslogtreecommitdiff
path: root/pjmedia
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2008-09-11 18:43:59 +0000
committerNanang Izzuddin <nanang@teluu.com>2008-09-11 18:43:59 +0000
commit6a8bb2b1cd06a7e85d5cd9544bd8f7ea754610e1 (patch)
tree09f27a402520d969b6fdf5e76f17a013afa3c6bc /pjmedia
parent0413bbf70ebb13b2c17168bcf75eb12b271b4efd (diff)
Ticket #616: Updated ICE transport to have a default option to switch RTP transmission to source address if remote doesn't use ICE.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2276 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia')
-rw-r--r--pjmedia/include/pjmedia/transport_ice.h40
-rw-r--r--pjmedia/src/pjmedia/transport_ice.c116
2 files changed, 150 insertions, 6 deletions
diff --git a/pjmedia/include/pjmedia/transport_ice.h b/pjmedia/include/pjmedia/transport_ice.h
index c3d07400..9c96cf3f 100644
--- a/pjmedia/include/pjmedia/transport_ice.h
+++ b/pjmedia/include/pjmedia/transport_ice.h
@@ -62,6 +62,23 @@ typedef struct pjmedia_ice_cb
/**
+ * Options that can be specified when creating ICE transport.
+ */
+enum pjmedia_transport_ice_options
+{
+ /**
+ * Normally when remote doesn't use ICE, the ICE transport will
+ * continuously check the source address of incoming packets to see
+ * if it is different than the configured remote address, and switch
+ * the remote address to the source address of the packet if they
+ * are different after several packets are received.
+ * Specifying this option will disable this feature.
+ */
+ PJMEDIA_ICE_NO_SRC_ADDR_CHECKING = 1
+};
+
+
+/**
* Create the Interactive Connectivity Establishment (ICE) media transport
* using the specified configuration. When STUN or TURN (or both) is used,
* the creation operation will complete asynchronously, when STUN resolution
@@ -94,6 +111,29 @@ PJ_DECL(pj_status_t) pjmedia_ice_create(pjmedia_endpt *endpt,
const pjmedia_ice_cb *cb,
pjmedia_transport **p_tp);
+
+/**
+ * The same as @pjmedia_ice_create with additional \a options param.
+ *
+ * @param endpt The media endpoint.
+ * @param name Optional name to identify this ICE media transport
+ * for logging purposes.
+ * @param comp_cnt Number of components to be created.
+ * @param cfg Pointer to configuration settings.
+ * @param cb Optional structure containing ICE specific callbacks.
+ * @param options Options, see #pjmedia_transport_ice_options.
+ * @param p_tp Pointer to receive the media transport instance.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_ice_create2(pjmedia_endpt *endpt,
+ const char *name,
+ unsigned comp_cnt,
+ const pj_ice_strans_cfg *cfg,
+ const pjmedia_ice_cb *cb,
+ unsigned options,
+ pjmedia_transport **p_tp);
+
PJ_END_DECL
diff --git a/pjmedia/src/pjmedia/transport_ice.c b/pjmedia/src/pjmedia/transport_ice.c
index 2e833665..99964aab 100644
--- a/pjmedia/src/pjmedia/transport_ice.c
+++ b/pjmedia/src/pjmedia/transport_ice.c
@@ -49,6 +49,7 @@ struct transport_ice
pjmedia_transport base;
pj_pool_t *pool;
int af;
+ unsigned options; /**< Transport options. */
unsigned comp_cnt;
pj_ice_strans *ice_st;
@@ -58,11 +59,17 @@ struct transport_ice
pj_bool_t initial_sdp;
enum oa_role oa_role; /**< Last role in SDP offer/answer */
- struct sdp_state rem_offer_state;/**< Describes the remote offer */
+ struct sdp_state rem_offer_state;/**< Describes the remote offer */
void *stream;
- pj_sockaddr_in remote_rtp;
- pj_sockaddr_in remote_rtcp;
+ pj_sockaddr remote_rtp;
+ pj_sockaddr remote_rtcp;
+ unsigned addr_len; /**< Length of addresses. */
+
+ pj_bool_t use_ice;
+ pj_sockaddr rtp_src_addr; /**< Actual source RTP address. */
+ pj_sockaddr rtcp_src_addr; /**< Actual source RTCP address. */
+ unsigned rtp_src_cnt; /**< How many pkt from this addr. */
unsigned tx_drop_pct; /**< Percent of tx pkts to drop. */
unsigned rx_drop_pct; /**< Percent of rx pkts to drop. */
@@ -181,6 +188,20 @@ PJ_DEF(pj_status_t) pjmedia_ice_create(pjmedia_endpt *endpt,
const pjmedia_ice_cb *cb,
pjmedia_transport **p_tp)
{
+ return pjmedia_ice_create2(endpt, name, comp_cnt, cfg, cb, 0, p_tp);
+}
+
+/*
+ * Create ICE media transport.
+ */
+PJ_DEF(pj_status_t) pjmedia_ice_create2(pjmedia_endpt *endpt,
+ const char *name,
+ unsigned comp_cnt,
+ const pj_ice_strans_cfg *cfg,
+ const pjmedia_ice_cb *cb,
+ unsigned options,
+ pjmedia_transport **p_tp)
+{
pj_pool_t *pool;
pj_ice_strans_cb ice_st_cb;
struct transport_ice *tp_ice;
@@ -193,12 +214,14 @@ PJ_DEF(pj_status_t) pjmedia_ice_create(pjmedia_endpt *endpt,
tp_ice = PJ_POOL_ZALLOC_T(pool, struct transport_ice);
tp_ice->pool = pool;
tp_ice->af = cfg->af;
+ tp_ice->options = options;
tp_ice->comp_cnt = comp_cnt;
pj_ansi_strcpy(tp_ice->base.name, pool->obj_name);
tp_ice->base.op = &transport_ice_op;
tp_ice->base.type = PJMEDIA_TRANSPORT_TYPE_ICE;
tp_ice->initial_sdp = PJ_TRUE;
tp_ice->oa_role = ROLE_NONE;
+ tp_ice->use_ice = PJ_FALSE;
if (cb)
pj_memcpy(&tp_ice->cb, cb, sizeof(pjmedia_ice_cb));
@@ -241,6 +264,8 @@ static void set_no_ice(struct transport_ice *tp_ice, const char *reason,
}
pj_ice_strans_stop_ice(tp_ice->ice_st);
+
+ tp_ice->use_ice = PJ_FALSE;
}
@@ -1357,6 +1382,7 @@ static pj_status_t transport_media_start(pjmedia_transport *tp,
}
/* Done */
+ tp_ice->use_ice = PJ_TRUE;
return PJ_SUCCESS;
}
@@ -1422,6 +1448,7 @@ static pj_status_t transport_attach (pjmedia_transport *tp,
pj_memcpy(&tp_ice->remote_rtp, rem_addr, addr_len);
pj_memcpy(&tp_ice->remote_rtcp, rem_rtcp, addr_len);
+ tp_ice->addr_len = addr_len;
return PJ_SUCCESS;
}
@@ -1460,7 +1487,7 @@ static pj_status_t transport_send_rtp(pjmedia_transport *tp,
return pj_ice_strans_sendto(tp_ice->ice_st, 1,
pkt, size, &tp_ice->remote_rtp,
- sizeof(pj_sockaddr_in));
+ tp_ice->addr_len);
}
@@ -1514,10 +1541,87 @@ static void ice_on_rx_data(pj_ice_strans *ice_st, unsigned comp_id,
(*tp_ice->rtp_cb)(tp_ice->stream, pkt, size);
- } else if (comp_id==2 && tp_ice->rtcp_cb)
+ /* See if source address of RTP packet is different than the
+ * configured address, and switch RTP remote address to
+ * source packet address after several consecutive packets
+ * have been received.
+ */
+ if (!tp_ice->use_ice &&
+ (tp_ice->options & PJMEDIA_ICE_NO_SRC_ADDR_CHECKING) == 0 &&
+ pj_sockaddr_cmp(&tp_ice->remote_rtp, src_addr) != 0 )
+ {
+ /* Check if the source address is recognized. */
+ if (pj_sockaddr_cmp(src_addr, &tp_ice->rtp_src_addr) != 0) {
+ /* Remember the new source address. */
+ pj_sockaddr_cp(&tp_ice->rtp_src_addr, src_addr);
+
+ /* Reset counter */
+ tp_ice->rtp_src_cnt = 0;
+ }
+
+ tp_ice->rtp_src_cnt++;
+
+ if (tp_ice->rtp_src_cnt >= PJMEDIA_RTP_NAT_PROBATION_CNT) {
+
+ char addr_text[80];
+
+ /* Set remote RTP address to source address */
+ pj_sockaddr_cp(&tp_ice->remote_rtp, &tp_ice->rtp_src_addr);
+ tp_ice->addr_len = pj_sockaddr_get_len(&tp_ice->remote_rtp);
+
+ /* Reset counter */
+ tp_ice->rtp_src_cnt = 0;
+
+ PJ_LOG(4,(tp_ice->base.name,
+ "Remote RTP address switched to %s",
+ pj_sockaddr_print(&tp_ice->remote_rtp, addr_text,
+ sizeof(addr_text), 3)));
+
+ /* Also update remote RTCP address if actual RTCP source
+ * address is not heard yet.
+ */
+ if (!pj_sockaddr_has_addr(&tp_ice->rtcp_src_addr)) {
+ pj_uint16_t port;
+
+ pj_sockaddr_cp(&tp_ice->remote_rtcp, &tp_ice->remote_rtp);
+
+ port = (pj_uint16_t)
+ (pj_sockaddr_get_port(&tp_ice->remote_rtp)+1);
+ pj_sockaddr_set_port(&tp_ice->remote_rtcp, port);
+
+ PJ_LOG(4,(tp_ice->base.name,
+ "Remote RTCP address switched to %s",
+ pj_sockaddr_print(&tp_ice->remote_rtcp, addr_text,
+ sizeof(addr_text), 3)));
+
+ }
+ }
+ }
+ } else if (comp_id==2 && tp_ice->rtcp_cb) {
(*tp_ice->rtcp_cb)(tp_ice->stream, pkt, size);
- PJ_UNUSED_ARG(src_addr);
+ /* Check if RTCP source address is the same as the configured
+ * remote address, and switch the address when they are
+ * different.
+ */
+ if (!tp_ice->use_ice &&
+ (tp_ice->options & PJMEDIA_ICE_NO_SRC_ADDR_CHECKING)==0 &&
+ pj_sockaddr_cmp(&tp_ice->remote_rtcp, src_addr) != 0)
+ {
+ char addr_text[80];
+
+ pj_sockaddr_cp(&tp_ice->remote_rtcp, src_addr);
+ pj_sockaddr_cp(&tp_ice->rtcp_src_addr, src_addr);
+
+ pj_assert(tp_ice->addr_len == pj_sockaddr_get_len(src_addr));
+
+ PJ_LOG(4,(tp_ice->base.name,
+ "Remote RTCP address switched to %s",
+ pj_sockaddr_print(&tp_ice->remote_rtcp, addr_text,
+ sizeof(addr_text), 3)));
+ }
+ }
+
PJ_UNUSED_ARG(src_addr_len);
}