Added new API's in ICE stream transport to assist offer/answer negotiation: pj_ice_strans_has_sess(), pj_ice_strans_sess_is_running(), pj_ice_strans_sess_is_complete(), pj_ice_strans_get_running_comp_cnt(), pj_ice_strans_get_ufrag_pwd(), and PJNATH_EICEMISMATCH error code.
 


git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@2031 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjnath/include/pjnath/errno.h b/pjnath/include/pjnath/errno.h
index 3cd3320..bc7aed4 100644
--- a/pjnath/include/pjnath/errno.h
+++ b/pjnath/include/pjnath/errno.h
@@ -152,6 +152,11 @@
 #define PJNATH_EICEFAILED	    (PJNATH_ERRNO_START+82) /* 370082 */
 /**
  * @hideinitializer
+ * Default destination does not match any ICE candidates
+ */
+#define PJNATH_EICEMISMATCH	    (PJNATH_ERRNO_START+83) /* 370083 */
+/**
+ * @hideinitializer
  * Invalid ICE component ID
  */
 #define PJNATH_EICEINCOMPID	    (PJNATH_ERRNO_START+86) /* 370086 */
diff --git a/pjnath/include/pjnath/ice_session.h b/pjnath/include/pjnath/ice_session.h
index 87b723a..a417435 100644
--- a/pjnath/include/pjnath/ice_session.h
+++ b/pjnath/include/pjnath/ice_session.h
@@ -510,7 +510,7 @@
 typedef enum pj_ice_sess_role
 {
     /**
-     * The ICE agent is in controlled role.
+     * The role is unknown.
      */
     PJ_ICE_SESS_ROLE_UNKNOWN,
 
diff --git a/pjnath/include/pjnath/ice_strans.h b/pjnath/include/pjnath/ice_strans.h
index 8097b38..25e05f6 100644
--- a/pjnath/include/pjnath/ice_strans.h
+++ b/pjnath/include/pjnath/ice_strans.h
@@ -349,6 +349,87 @@
 					    const pj_str_t *local_passwd);
 
 /**
+ * Check if the ICE stream transport has the ICE session created. The
+ * ICE session is created with #pj_ice_strans_init_ice().
+ *
+ * @param ice_st	The ICE stream transport.
+ *
+ * @return		PJ_TRUE if #pj_ice_strans_init_ice() has been
+ *			called.
+ */
+PJ_DECL(pj_bool_t) pj_ice_strans_has_sess(pj_ice_strans *ice_st);
+
+
+/**
+ * Check if ICE negotiation is still running.
+ *
+ * @param ice_st	The ICE stream transport.
+ *
+ * @return		PJ_TRUE if ICE session has been created and ICE 
+ *			negotiation negotiation is in progress.
+ */
+PJ_DECL(pj_bool_t) pj_ice_strans_sess_is_running(pj_ice_strans *ice_st);
+
+
+/**
+ * Check if ICE negotiation has completed.
+ *
+ * @param ice_st	The ICE stream transport.
+ *
+ * @return		PJ_TRUE if ICE session has been created and the
+ *			negotiation is complete.
+ */
+PJ_DECL(pj_bool_t) pj_ice_strans_sess_is_complete(pj_ice_strans *ice_st);
+
+
+/**
+ * Get the current/running component count. If ICE negotiation has not
+ * been started, the number of components will be equal to the number
+ * when the ICE stream transport was created. Once negotiation been
+ * started, the number of components will be the lowest number of 
+ * component between local and remote agents.
+ *
+ * @param ice_st	The ICE stream transport.
+ *
+ * @return		The running number of components.
+ */
+PJ_DECL(unsigned) pj_ice_strans_get_running_comp_cnt(pj_ice_strans *ice_st);
+
+
+/**
+ * Get the ICE username fragment and password of the ICE session. The
+ * local username fragment and password can only be retrieved once ICE
+ * session has been created with #pj_ice_strans_init_ice(). The remote
+ * username fragment and password can only be retrieved once ICE session
+ * has been started with #pj_ice_strans_start_ice().
+ *
+ * Note that the string returned by this function is only valid throughout
+ * the duration of the ICE session, and the application must not modify
+ * these strings. Once the ICE session has been stopped with
+ * #pj_ice_strans_stop_ice(), the pointer in the string will no longer be
+ * valid.
+ *
+ * @param ice_st	The ICE stream transport.
+ * @param loc_ufrag	Optional pointer to receive ICE username fragment
+ *			of local endpoint from the ICE session.
+ * @param loc_pwd	Optional pointer to receive ICE password of local
+ *			endpoint from the ICE session.
+ * @param rem_ufrag	Optional pointer to receive ICE username fragment
+ *			of remote endpoint from the ICE session.
+ * @param rem_pwd	Optional pointer to receive ICE password of remote
+ *			endpoint from the ICE session.
+ *
+ * @return		PJ_SUCCESS if the strings have been retrieved
+ *			successfully.
+ */
+PJ_DECL(pj_status_t) pj_ice_strans_get_ufrag_pwd(pj_ice_strans *ice_st,
+						 pj_str_t *loc_ufrag,
+						 pj_str_t *loc_pwd,
+						 pj_str_t *rem_ufrag,
+						 pj_str_t *rem_pwd);
+
+
+/**
  * Enumerate the local candidates for the specified component.
  *
  * @param ice_st	The ICE stream transport.
diff --git a/pjnath/src/pjnath/errno.c b/pjnath/src/pjnath/errno.c
index e71fa63..888e8cd 100644
--- a/pjnath/src/pjnath/errno.c
+++ b/pjnath/src/pjnath/errno.c
@@ -58,6 +58,7 @@
     PJ_BUILD_ERR( PJNATH_ENOICE,	    "ICE session not available"),
     PJ_BUILD_ERR( PJNATH_EICEINPROGRESS,    "ICE check is in progress"),
     PJ_BUILD_ERR( PJNATH_EICEFAILED,	    "All ICE checklists failed"),
+    PJ_BUILD_ERR( PJNATH_EICEMISMATCH,	    "Default target doesn't match any ICE candidates"),
     PJ_BUILD_ERR( PJNATH_EICEINCOMPID,	    "Invalid ICE component ID"),
     PJ_BUILD_ERR( PJNATH_EICEINCANDID,	    "Invalid ICE candidate ID"),
     PJ_BUILD_ERR( PJNATH_EICEINSRCADDR,	    "Source address mismatch"),
diff --git a/pjnath/src/pjnath/ice_strans.c b/pjnath/src/pjnath/ice_strans.c
index 34b74f0..85a2593 100644
--- a/pjnath/src/pjnath/ice_strans.c
+++ b/pjnath/src/pjnath/ice_strans.c
@@ -700,6 +700,73 @@
 }
 
 /*
+ * Check if the ICE stream transport has the ICE session created. 
+ */
+PJ_DEF(pj_bool_t) pj_ice_strans_has_sess(pj_ice_strans *ice_st)
+{
+    PJ_ASSERT_RETURN(ice_st, PJ_FALSE);
+    return ice_st->ice != NULL;
+}
+
+/*
+ * Check if ICE negotiation is still running.
+ */
+PJ_DEF(pj_bool_t) pj_ice_strans_sess_is_running(pj_ice_strans *ice_st)
+{
+    return ice_st && ice_st->ice && ice_st->ice->rcand_cnt &&
+	   !pj_ice_strans_sess_is_complete(ice_st);
+}
+
+
+/*
+ * Check if ICE negotiation has completed.
+ */
+PJ_DEF(pj_bool_t) pj_ice_strans_sess_is_complete(pj_ice_strans *ice_st)
+{
+    return ice_st && ice_st->ice && ice_st->ice->is_complete;
+}
+
+
+/*
+ * Get the current/running component count.
+ */
+PJ_DEF(unsigned) pj_ice_strans_get_running_comp_cnt(pj_ice_strans *ice_st)
+{
+    PJ_ASSERT_RETURN(ice_st, PJ_EINVAL);
+
+    if (ice_st->ice && ice_st->ice->rcand_cnt) {
+	return (ice_st->comp_cnt < ice_st->ice->rcand_cnt) ?
+		    ice_st->comp_cnt : ice_st->ice->rcand_cnt;
+    } else {
+	return ice_st->comp_cnt;
+    }
+}
+
+
+/*
+ * Get the ICE username fragment and password of the ICE session.
+ */
+PJ_DEF(pj_status_t) pj_ice_strans_get_ufrag_pwd( pj_ice_strans *ice_st,
+						 pj_str_t *loc_ufrag,
+						 pj_str_t *loc_pwd,
+						 pj_str_t *rem_ufrag,
+						 pj_str_t *rem_pwd)
+{
+    PJ_ASSERT_RETURN(ice_st && ice_st->ice, PJ_EINVALIDOP);
+
+    if (loc_ufrag) *loc_ufrag = ice_st->ice->rx_ufrag;
+    if (loc_pwd) *loc_pwd = ice_st->ice->rx_pass;
+
+    if (rem_ufrag || rem_pwd) {
+	PJ_ASSERT_RETURN(ice_st->ice->rcand_cnt != 0, PJ_EINVALIDOP);
+	if (rem_ufrag) *rem_ufrag = ice_st->ice->tx_ufrag;
+	if (rem_pwd) *rem_pwd = ice_st->ice->tx_pass;
+    }
+
+    return PJ_SUCCESS;
+}
+
+/*
  * Enum candidates
  */
 PJ_DEF(pj_status_t) pj_ice_strans_enum_cands(pj_ice_strans *ice_st,
@@ -708,17 +775,17 @@
 					     pj_ice_sess_cand cand[])
 {
     unsigned i, cnt;
-    pj_ice_strans_comp *comp;
 
-    PJ_ASSERT_RETURN(ice_st && comp_id && comp_id <= ice_st->comp_cnt &&
-		     count && cand, PJ_EINVAL);
+    PJ_ASSERT_RETURN(ice_st && ice_st->ice && comp_id && 
+		     comp_id <= ice_st->comp_cnt && count && cand, PJ_EINVAL);
 
-    comp = ice_st->comp[comp_id - 1];
-    cnt = comp->cand_cnt;
-    cnt = (cnt > *count) ? *count : cnt;
-
-    for (i=0; i<cnt; ++i) {
-	pj_memcpy(&cand[i], &comp->cand_list[i], sizeof(pj_ice_sess_cand));
+    cnt = 0;
+    for (i=0; i<ice_st->ice->lcand_cnt && cnt<*count; ++i) {
+	if (ice_st->ice->lcand[i].comp_id != comp_id)
+	    continue;
+	pj_memcpy(&cand[cnt], &ice_st->ice->lcand[i],
+		  sizeof(pj_ice_sess_cand));
+	++cnt;
     }
 
     *count = cnt;