Index: /pjproject/trunk/pjnath/include/pjnath/errno.h
===================================================================
--- /pjproject/trunk/pjnath/include/pjnath/errno.h	(revision 2030)
+++ /pjproject/trunk/pjnath/include/pjnath/errno.h	(revision 2031)
@@ -153,4 +153,9 @@
 /**
  * @hideinitializer
+ * Default destination does not match any ICE candidates
+ */
+#define PJNATH_EICEMISMATCH	    (PJNATH_ERRNO_START+83) /* 370083 */
+/**
+ * @hideinitializer
  * Invalid ICE component ID
  */
Index: /pjproject/trunk/pjnath/include/pjnath/ice_session.h
===================================================================
--- /pjproject/trunk/pjnath/include/pjnath/ice_session.h	(revision 2030)
+++ /pjproject/trunk/pjnath/include/pjnath/ice_session.h	(revision 2031)
@@ -511,5 +511,5 @@
 {
     /**
-     * The ICE agent is in controlled role.
+     * The role is unknown.
      */
     PJ_ICE_SESS_ROLE_UNKNOWN,
Index: /pjproject/trunk/pjnath/include/pjnath/ice_strans.h
===================================================================
--- /pjproject/trunk/pjnath/include/pjnath/ice_strans.h	(revision 2030)
+++ /pjproject/trunk/pjnath/include/pjnath/ice_strans.h	(revision 2031)
@@ -350,4 +350,85 @@
 
 /**
+ * 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.
  *
Index: /pjproject/trunk/pjnath/src/pjnath/errno.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjnath/errno.c	(revision 2030)
+++ /pjproject/trunk/pjnath/src/pjnath/errno.c	(revision 2031)
@@ -59,4 +59,5 @@
     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"),
Index: /pjproject/trunk/pjnath/src/pjnath/ice_strans.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjnath/ice_strans.c	(revision 2030)
+++ /pjproject/trunk/pjnath/src/pjnath/ice_strans.c	(revision 2031)
@@ -701,4 +701,71 @@
 
 /*
+ * 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
  */
@@ -709,15 +776,15 @@
 {
     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);
-
-    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));
+
+    PJ_ASSERT_RETURN(ice_st && ice_st->ice && comp_id && 
+		     comp_id <= ice_st->comp_cnt && count && cand, PJ_EINVAL);
+
+    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;
     }
 
