ICE (work in progress): integration with PJSUA

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@1098 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjmedia/include/pjmedia.h b/pjmedia/include/pjmedia.h
index 10d81c0..6db9bbe 100644
--- a/pjmedia/include/pjmedia.h
+++ b/pjmedia/include/pjmedia.h
@@ -54,6 +54,7 @@
 #include <pjmedia/splitcomb.h>
 #include <pjmedia/tonegen.h>
 #include <pjmedia/transport.h>
+#include <pjmedia/transport_ice.h>
 #include <pjmedia/transport_udp.h>
 #include <pjmedia/wav_playlist.h>
 #include <pjmedia/wav_port.h>
diff --git a/pjmedia/include/pjmedia/transport.h b/pjmedia/include/pjmedia/transport.h
index 4b2450b..1e7d67d 100644
--- a/pjmedia/include/pjmedia/transport.h
+++ b/pjmedia/include/pjmedia/transport.h
@@ -178,6 +178,11 @@
  */
 struct pjmedia_transport_op
 {
+    /**
+     * Get media socket info from the specified transport.
+     *
+     * Application should call #pjmedia_transport_get_info() instead
+     */
     pj_status_t (*get_info)(pjmedia_transport *tp,
 			    pjmedia_sock_info *info);
 
@@ -254,6 +259,20 @@
 typedef struct pjmedia_transport_op pjmedia_transport_op;
 
 
+/** 
+ * Media transport type.
+ */
+typedef enum pjmedia_transport_type
+{
+    /** Media transport using standard UDP */
+    PJMEDIA_TRANSPORT_TYPE_UDP,
+
+    /** Media transport using ICE */
+    PJMEDIA_TRANSPORT_TYPE_ICE
+
+} pjmedia_transport_type;
+
+
 /**
  * This structure declares stream transport. A stream transport is called
  * by the stream to transmit a packet, and will notify stream when
@@ -262,13 +281,27 @@
 struct pjmedia_transport
 {
     /** Transport name (for logging purpose). */
-    char		  name[PJ_MAX_OBJ_NAME];
+    char		     name[PJ_MAX_OBJ_NAME];
+
+    /** Transport type. */
+    pjmedia_transport_type   type;
 
     /** Transport's "virtual" function table. */
-    pjmedia_transport_op *op;
+    pjmedia_transport_op    *op;
 };
 
 
+/**
+ * Get media socket info from the specified transport. The socket info
+ * contains information about the local address of this transport, and
+ * would be needed for example to fill in the "c=" and "m=" line of local 
+ * SDP.
+ *
+ * @param tp	    The transport.
+ * @param info	    Media socket info to be initialized.
+ *
+ * @return	    PJ_SUCCESS on success.
+ */
 PJ_INLINE(pj_status_t) pjmedia_transport_get_info(pjmedia_transport *tp,
 						  pjmedia_sock_info *info)
 {
diff --git a/pjmedia/include/pjmedia/transport_ice.h b/pjmedia/include/pjmedia/transport_ice.h
index fa4deeb..e676730 100644
--- a/pjmedia/include/pjmedia/transport_ice.h
+++ b/pjmedia/include/pjmedia/transport_ice.h
@@ -41,21 +41,21 @@
 
 PJ_DECL(pj_status_t) pjmedia_ice_create(pjmedia_endpt *endpt,
 					const char *name,
+					unsigned comp_cnt,
 					pj_stun_config *stun_cfg,
-					pj_dns_resolver *resolver,
-					pj_bool_t enable_relay,
-					const pj_str_t *stun_name,
 					pjmedia_transport **p_tp);
 PJ_DECL(pj_status_t) pjmedia_ice_destroy(pjmedia_transport *tp);
 
+PJ_DECL(pj_ice_st*) pjmedia_ice_get_ice_st(pjmedia_transport *tp);
+
 
 PJ_DECL(pj_status_t) pjmedia_ice_init_ice(pjmedia_transport *tp,
 					  pj_ice_role role,
 					  const pj_str_t *local_ufrag,
 					  const pj_str_t *local_passwd);
-PJ_DECL(pj_status_t) pjmedia_ice_build_sdp(pjmedia_transport *tp,
-					   pj_pool_t *pool,
-					   pjmedia_sdp_session *sdp);
+PJ_DECL(pj_status_t) pjmedia_ice_modify_sdp(pjmedia_transport *tp,
+					    pj_pool_t *pool,
+					    pjmedia_sdp_session *sdp);
 PJ_DECL(pj_status_t) pjmedia_ice_start_ice(pjmedia_transport *tp,
 					   pj_pool_t *pool,
 					   pjmedia_sdp_session *rem_sdp);
diff --git a/pjmedia/src/pjmedia/transport_ice.c b/pjmedia/src/pjmedia/transport_ice.c
index 98e89fb..2023a1d 100644
--- a/pjmedia/src/pjmedia/transport_ice.c
+++ b/pjmedia/src/pjmedia/transport_ice.c
@@ -25,7 +25,7 @@
     pjmedia_transport	 base;
     pj_ice_st		*ice_st;
 
-    void  *user_data;
+    void  *stream;
     void (*rtp_cb)(void*,
 		   const void*,
 		   pj_ssize_t);
@@ -41,7 +41,7 @@
 static pj_status_t tp_get_info(pjmedia_transport *tp,
 			       pjmedia_sock_info *info);
 static pj_status_t tp_attach( pjmedia_transport *tp,
-			      void *user_data,
+			      void *stream,
 			      const pj_sockaddr_t *rem_addr,
 			      const pj_sockaddr_t *rem_rtcp,
 			      unsigned addr_len,
@@ -92,15 +92,14 @@
 
 PJ_DEF(pj_status_t) pjmedia_ice_create(pjmedia_endpt *endpt,
 				       const char *name,
+				       unsigned comp_cnt,
 				       pj_stun_config *stun_cfg,
-				       pj_dns_resolver *resolver,
-				       pj_bool_t enable_relay,
-				       const pj_str_t *stun_name,
-				       pjmedia_transport **p_tp)
+	    			       pjmedia_transport **p_tp)
 {
     pj_ice_st *ice_st;
     pj_ice_st_cb ice_st_cb;
     struct transport_ice *tp_ice;
+    unsigned i;
     pj_status_t status;
 
     PJ_UNUSED_ARG(endpt);
@@ -117,24 +116,11 @@
     if (status != PJ_SUCCESS)
 	return status;
 
-    /* Add component 1 (RTP) */
-    status = pj_ice_st_add_comp(ice_st, 1);
-    if (status != PJ_SUCCESS) 
-	goto on_error;
-
-    /* Add host candidates. */
-    status = pj_ice_st_add_all_host_interfaces(ice_st, 1, 0, PJ_FALSE, NULL);
-    if (status != PJ_SUCCESS)
-	goto on_error;
-
-    /* Configure STUN server for ICE */
-    if (stun_name) {
-	status = pj_ice_st_set_stun(ice_st, resolver, enable_relay, stun_name);
+    /* Add components */
+    for (i=0; i<comp_cnt; ++i) {
+	status = pj_ice_st_add_comp(ice_st, i+1);
 	if (status != PJ_SUCCESS) 
 	    goto on_error;
-
-	/* Add STUN candidates */
-	status = pj_ice_st_add_stun_interface(ice_st, 1, 0, PJ_FALSE, NULL);
     }
 
     /* Create transport instance and attach to ICE */
@@ -142,6 +128,7 @@
     tp_ice->ice_st = ice_st;
     pj_ansi_strcpy(tp_ice->base.name, ice_st->obj_name);
     tp_ice->base.op = &tp_ice_op;
+    tp_ice->base.type = PJMEDIA_TRANSPORT_TYPE_ICE;
 
     ice_st->user_data = (void*)tp_ice;
 
@@ -157,19 +144,28 @@
 }
 
 
-PJ_DEF(pj_status_t) pjmedia_ice_close(pjmedia_transport *tp)
+PJ_DEF(pj_status_t) pjmedia_ice_destroy(pjmedia_transport *tp)
 {
     struct transport_ice *tp_ice = (struct transport_ice*)tp;
 
     if (tp_ice->ice_st) {
 	pj_ice_st_destroy(tp_ice->ice_st);
-	tp_ice->ice_st = NULL;
+	//Must not touch tp_ice after ice_st is destroyed!
+	//(it has the pool)
+	//tp_ice->ice_st = NULL;
     }
 
     return PJ_SUCCESS;
 }
 
 
+PJ_DECL(pj_ice_st*) pjmedia_ice_get_ice_st(pjmedia_transport *tp)
+{
+    struct transport_ice *tp_ice = (struct transport_ice*)tp;
+    return tp_ice->ice_st;
+}
+
+
 PJ_DEF(pj_status_t) pjmedia_ice_init_ice(pjmedia_transport *tp,
 					 pj_ice_role role,
 					 const pj_str_t *local_ufrag,
@@ -180,9 +176,9 @@
 }
 
 
-PJ_DEF(pj_status_t) pjmedia_ice_build_sdp(pjmedia_transport *tp,
-					  pj_pool_t *pool,
-					  pjmedia_sdp_session *sdp)
+PJ_DEF(pj_status_t) pjmedia_ice_modify_sdp(pjmedia_transport *tp,
+					   pj_pool_t *pool,
+					   pjmedia_sdp_session *sdp)
 {
     struct transport_ice *tp_ice = (struct transport_ice*)tp;
     enum { MAXLEN = 256 };
@@ -202,7 +198,7 @@
 				   &tp_ice->ice_st->ice->rx_pass);
     sdp->attr[sdp->attr_count++] = attr;
 
-    /* Add all candidates */
+    /* Add all candidates (to media level) */
     cand_cnt = pj_ice_get_cand_cnt(tp_ice->ice_st->ice);
     for (i=0; i<cand_cnt; ++i) {
 	pj_ice_cand *cand;
@@ -255,7 +251,7 @@
 
 	value = pj_str(buffer);
 	attr = pjmedia_sdp_attr_create(pool, "candidate", &value);
-	sdp->attr[sdp->attr_count++] = attr;
+	sdp->media[0]->attr[sdp->media[0]->attr_count++] = attr;
     }
 
     /* Done */
@@ -377,10 +373,10 @@
 
     /* Get all candidates */
     cand_cnt = 0;
-    for (i=0; i<rem_sdp->attr_count; ++i) {
+    for (i=0; i<rem_sdp->media[0]->attr_count; ++i) {
 	pjmedia_sdp_attr *attr;
 
-	attr = rem_sdp->attr[i];
+	attr = rem_sdp->media[0]->attr[i];
 	if (pj_strcmp2(&attr->name, "candidate")!=0)
 	    continue;
 
@@ -441,7 +437,7 @@
 
 
 static pj_status_t tp_attach( pjmedia_transport *tp,
-			      void *user_data,
+			      void *stream,
 			      const pj_sockaddr_t *rem_addr,
 			      const pj_sockaddr_t *rem_rtcp,
 			      unsigned addr_len,
@@ -454,7 +450,7 @@
 {
     struct transport_ice *tp_ice = (struct transport_ice*)tp;
 
-    tp_ice->user_data = user_data;
+    tp_ice->stream = stream;
     tp_ice->rtp_cb = rtp_cb;
     tp_ice->rtcp_cb = rtcp_cb;
 
@@ -473,7 +469,7 @@
 
     tp_ice->rtp_cb = NULL;
     tp_ice->rtcp_cb = NULL;
-    tp_ice->user_data = NULL;
+    tp_ice->stream = NULL;
 
     PJ_UNUSED_ARG(strm);
 }
@@ -514,9 +510,9 @@
     struct transport_ice *tp_ice = (struct transport_ice*) ice_st->user_data;
 
     if (comp_id==1 && tp_ice->rtp_cb)
-	(*tp_ice->rtp_cb)(tp_ice->user_data, pkt, size);
+	(*tp_ice->rtp_cb)(tp_ice->stream, pkt, size);
     else if (comp_id==2 && tp_ice->rtcp_cb)
-	(*tp_ice->rtcp_cb)(tp_ice->user_data, pkt, size);
+	(*tp_ice->rtcp_cb)(tp_ice->stream, pkt, size);
 
     PJ_UNUSED_ARG(cand_id);
     PJ_UNUSED_ARG(src_addr);
diff --git a/pjmedia/src/pjmedia/transport_udp.c b/pjmedia/src/pjmedia/transport_udp.c
index 3325be0..2bf570e 100644
--- a/pjmedia/src/pjmedia/transport_udp.c
+++ b/pjmedia/src/pjmedia/transport_udp.c
@@ -239,6 +239,7 @@
     tp->options = options;
     pj_ansi_strcpy(tp->base.name, name);
     tp->base.op = &transport_udp_op;
+    tp->base.type = PJMEDIA_TRANSPORT_TYPE_UDP;
 
     /* Copy socket infos */
     tp->rtp_sock = si->rtp_sock;