Index: /pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c	(revision 1105)
+++ /pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c	(revision 1106)
@@ -154,5 +154,4 @@
 {
     struct transport_ice *tp_ice = (struct transport_ice*)tp;
-    unsigned comp_id;
     pj_status_t status;
 
@@ -161,6 +160,5 @@
 	return status;
 
-    status = pj_ice_st_create_comp(tp_ice->ice_st, 1, options, start_addr, 
-				   &comp_id);
+    status = pj_ice_st_create_comp(tp_ice->ice_st, 1, options, start_addr);
     if (status != PJ_SUCCESS)
 	return status;
@@ -168,4 +166,5 @@
     if (tp_ice->ice_st->comp_cnt > 1) {
 	pj_sockaddr_in addr;
+	pj_uint16_t port;
 
 	pj_memcpy(&addr, &tp_ice->ice_st->comp[0]->local_addr.ipv4,
@@ -176,7 +175,8 @@
 	    addr.sin_addr.s_addr = 0;
 
-	addr.sin_port = (pj_uint16_t)(pj_ntohs(addr.sin_port)+1);
-	status = pj_ice_st_create_comp(tp_ice->ice_st, 2, options, 
-				       &addr, &comp_id);
+	port = pj_ntohs(addr.sin_port);
+	++port;
+	addr.sin_port = pj_htons(port);
+	status = pj_ice_st_create_comp(tp_ice->ice_st, 2, options, &addr);
 	if (status != PJ_SUCCESS)
 	    return status;
@@ -482,5 +482,5 @@
 	pj_assert(comp->default_cand >= 0);
 	info->rtp_sock = comp->sock;
-	pj_memcpy(&info->rtp_addr_name, 
+	pj_memcpy(&info->rtcp_addr_name, 
 		  &comp->cand_list[comp->default_cand].addr,
 		  sizeof(pj_sockaddr_in));
Index: /pjproject/trunk/pjnath/build/pjnath_test.dsp
===================================================================
--- /pjproject/trunk/pjnath/build/pjnath_test.dsp	(revision 1105)
+++ /pjproject/trunk/pjnath/build/pjnath_test.dsp	(revision 1106)
@@ -51,5 +51,5 @@
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 netapi32.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/pjnath-test-i386-win32-vc6-release.exe"
+# ADD LINK32 mswsock.lib iphlpapi.lib netapi32.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/pjnath-test-i386-win32-vc6-release.exe"
 
 !ELSEIF  "$(CFG)" == "pjnath_test - Win32 Debug"
@@ -75,5 +75,5 @@
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 netapi32.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/pjnath-test-i386-win32-vc6-debug.exe" /pdbtype:sept
+# ADD LINK32 iphlpapi.lib netapi32.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/pjnath-test-i386-win32-vc6-debug.exe" /pdbtype:sept
 
 !ENDIF 
Index: /pjproject/trunk/pjnath/include/pjnath/ice.h
===================================================================
--- /pjproject/trunk/pjnath/include/pjnath/ice.h	(revision 1105)
+++ /pjproject/trunk/pjnath/include/pjnath/ice.h	(revision 1106)
@@ -69,5 +69,5 @@
 
 typedef struct pj_ice pj_ice;
-
+typedef struct pj_ice_check pj_ice_check;
 
 #define PJ_ICE_MAX_CAND	    16
@@ -81,6 +81,5 @@
 typedef struct pj_ice_comp
 {
-    unsigned	     comp_id;
-    int		     nominated_check_id;
+    pj_ice_check	*valid_check;
 } pj_ice_comp;
 
@@ -111,5 +110,5 @@
 
 
-typedef struct pj_ice_check
+struct pj_ice_check
 {
     pj_ice_cand		*lcand;
@@ -118,7 +117,8 @@
     pj_uint64_t		 prio;
     pj_ice_check_state	 state;
+    pj_stun_tx_data	*tdata;
     pj_bool_t		 nominated;
     pj_status_t		 err_code;
-} pj_ice_check;
+};
 
 
@@ -206,4 +206,6 @@
     pj_ice_checklist	 valid_list;
 };
+
+PJ_DECL(const char*) pj_ice_get_cand_type_name(pj_ice_cand_type type);
 
 
Index: /pjproject/trunk/pjnath/include/pjnath/ice_stream_transport.h
===================================================================
--- /pjproject/trunk/pjnath/include/pjnath/ice_stream_transport.h	(revision 1105)
+++ /pjproject/trunk/pjnath/include/pjnath/ice_stream_transport.h	(revision 1106)
@@ -61,7 +61,8 @@
 enum pj_ice_st_option
 {
-    PJ_ICE_ST_OPT_DISABLE_STUN	= 1,
-    PJ_ICE_ST_OPT_DISABLE_RELAY	= 2,
-    PJ_ICE_ST_OPT_NO_PORT_RETRY	= 4,
+    PJ_ICE_ST_OPT_DONT_ADD_CAND = 1,
+    PJ_ICE_ST_OPT_DISABLE_STUN	= 2,
+    PJ_ICE_ST_OPT_DISABLE_RELAY	= 4,
+    PJ_ICE_ST_OPT_NO_PORT_RETRY	= 8,
 };
 
@@ -144,6 +145,11 @@
 					   unsigned comp_id,
 					   pj_uint32_t options,
-					   const pj_sockaddr_in *addr,
-				    	   unsigned *p_itf_id);
+					   const pj_sockaddr_in *addr);
+PJ_DECL(pj_status_t) pj_ice_st_add_cand(pj_ice_st *ice_st,
+					unsigned comp_id,
+					pj_ice_cand_type type,
+					pj_uint16_t local_pref,
+					const pj_sockaddr_in *addr,
+					pj_bool_t set_default);
 
 PJ_DECL(pj_status_t) pj_ice_st_get_comps_status(pj_ice_st *ice_st);
Index: /pjproject/trunk/pjnath/include/pjnath/stun_session.h
===================================================================
--- /pjproject/trunk/pjnath/include/pjnath/stun_session.h	(revision 1105)
+++ /pjproject/trunk/pjnath/include/pjnath/stun_session.h	(revision 1106)
@@ -319,4 +319,24 @@
 
 /**
+ * Cancel outgoing STUN transaction. This operation is only valid for outgoing
+ * STUN request, to cease retransmission of the request and destroy the
+ * STUN client transaction that is used to send the request.
+ *
+ * @param sess	    The STUN session instance.
+ * @param tdata	    The request message previously sent.
+ * @param notify    Specify whether \a on_request_complete() callback should
+ *		    be called.
+ * @param status    If \a on_request_complete() callback is to be called,
+ *		    specify the error status to be given when calling the
+ *		    callback. This error status MUST NOT be PJ_SUCCESS.
+ *
+ * @return	    PJ_SUCCESS if transaction is successfully cancelled.
+ */
+PJ_DECL(pj_status_t) pj_stun_session_cancel_req(pj_stun_session *sess,
+						pj_stun_tx_data *tdata,
+						pj_bool_t notify,
+						pj_status_t status);
+
+/**
  * Application must call this function to notify the STUN session about
  * the arrival of STUN packet. The STUN packet MUST have been checked
Index: /pjproject/trunk/pjnath/src/pjnath-test/ice_test.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjnath-test/ice_test.c	(revision 1105)
+++ /pjproject/trunk/pjnath/src/pjnath-test/ice_test.c	(revision 1106)
@@ -19,5 +19,5 @@
 #include "test.h"
 
-#define THIS_FILE   "ice.c"
+#define THIS_FILE   "ice_test.c"
 
 
@@ -44,11 +44,10 @@
     id->complete = PJ_TRUE;
     id->err_code = status;
-    PJ_LOG(3,(THIS_FILE, "    ICE %s complete %s", id->obj_name,
+    PJ_LOG(3,(THIS_FILE, "     ICE %s complete %s", id->obj_name,
 	      (status==PJ_SUCCESS ? "successfully" : "with failure")));
 }
 
 
-static void on_rx_data(pj_ice_st *icest,
-		       unsigned comp_id, unsigned cand_id,
+static void on_rx_data(pj_ice_st *icest, unsigned comp_id, 
 		       void *pkt, pj_size_t size,
 		       const pj_sockaddr_t *src_addr,
@@ -69,5 +68,4 @@
     }
 
-    PJ_UNUSED_ARG(cand_id);
     PJ_UNUSED_ARG(src_addr);
     PJ_UNUSED_ARG(src_addr_len);
@@ -102,5 +100,5 @@
     icest_cb.on_rx_data = &on_rx_data;
 
-    status = pj_ice_st_create(&stun_cfg, NULL, NULL, &icest_cb, &im);
+    status = pj_ice_st_create(&stun_cfg, "icetest", 2, NULL, &icest_cb, &im);
     if (status != PJ_SUCCESS)
 	return -10;
@@ -127,4 +125,86 @@
 }
 
+
+struct dummy_cand
+{
+    unsigned		 comp_id;
+    pj_ice_cand_type	 type;
+    const char		*addr;
+    unsigned		 port;
+};
+
+static int init_ice_st(pj_ice_st *ice_st,
+		       pj_bool_t add_valid_comp,
+		       unsigned dummy_cnt,
+		       struct dummy_cand cand[])
+{
+    pj_str_t a;
+    pj_status_t status;
+    unsigned i;
+
+    /* Create components */
+    for (i=0; i<ice_st->comp_cnt; ++i) {
+	status = pj_ice_st_create_comp(ice_st, i+1, PJ_ICE_ST_OPT_DONT_ADD_CAND, NULL);
+	if (status != PJ_SUCCESS)
+	    return -21;
+    }
+
+    /* Add dummy candidates */
+    for (i=0; i<dummy_cnt; ++i) {
+	pj_sockaddr_in addr;
+
+	pj_sockaddr_in_init(&addr, pj_cstr(&a, cand[i].addr), (pj_uint16_t)cand[i].port);
+	status = pj_ice_st_add_cand(ice_st, cand[i].comp_id, cand[i].type,
+				    65535, &addr, PJ_FALSE);
+	if (status != PJ_SUCCESS)
+	    return -22;
+    }
+
+    /* Add the real candidate */
+    if (add_valid_comp) {
+	for (i=0; i<ice_st->comp_cnt; ++i) {
+	    status = pj_ice_st_add_cand(ice_st, i+1, PJ_ICE_CAND_TYPE_HOST, 65535,
+					&ice_st->comp[i]->local_addr.ipv4, PJ_TRUE);
+	    if (status != PJ_SUCCESS)
+		return -23;
+	}
+    }
+
+    return 0;
+}
+
+
+/* When ICE completes, both agents should agree on the same candidate pair.
+ * Check that the remote address selected by agent1 is equal to the
+ * local address of selected by agent 2.
+ */
+static int verify_address(pj_ice_st *agent1, pj_ice_st *agent2,
+			  unsigned comp_id)
+{
+    pj_ice_cand *rcand, *lcand;
+    int lcand_id;
+
+    if (agent1->ice->comp[comp_id-1].valid_check == NULL) {
+	PJ_LOG(3,(THIS_FILE, "....error: valid_check not set for comp_id %d", comp_id));
+	return -60;
+    }
+
+    /* Get default remote candidate of agent 1 */
+    rcand = agent1->ice->comp[comp_id-1].valid_check->rcand;
+
+    /* Get default local candidate of agent 2 */
+    pj_ice_find_default_cand(agent2->ice, comp_id, &lcand_id);
+    if (lcand_id < 0)
+	return -62;
+
+    lcand = &agent2->ice->lcand[lcand_id];
+
+    if (pj_memcmp(&rcand->addr, &lcand->addr, sizeof(pj_sockaddr_in))!=0) {
+	PJ_LOG(3,(THIS_FILE, "....error: the selected addresses are incorrect for comp_id %d", comp_id));
+	return -64;
+    }
+
+    return 0;
+}
 
 
@@ -142,6 +222,13 @@
  */
 static int perform_ice_test(const char *title,
+			    pj_bool_t expected_success,
+			    unsigned comp_cnt,
+			    pj_bool_t add_valid_comp,
 			    unsigned wait_before_send,
-			    unsigned max_total_time)
+			    unsigned max_total_time,
+			    unsigned ocand_cnt,
+			    struct dummy_cand ocand[],
+			    unsigned acand_cnt,
+			    struct dummy_cand acand[])
 {
     pj_ice_st *im1, *im2;
@@ -149,9 +236,15 @@
     struct ice_data *id1, *id2;
     pj_timestamp t_start, t_end;
-    pj_ice_cand *rcand;
+    unsigned i;
     pj_str_t data_from_offerer, data_from_answerer;
     pj_status_t status;
 
+#define CHECK_COMPLETE()    if (id1->complete && id2->complete) { \
+				if (t_end.u32.lo==0) pj_get_timestamp(&t_end); \
+			    } else {}
+
     PJ_LOG(3,(THIS_FILE, "...%s", title));
+
+    pj_bzero(&t_end, sizeof(t_end));
 
     pj_bzero(&icest_cb, sizeof(icest_cb));
@@ -160,5 +253,5 @@
 
     /* Create first ICE */
-    status = pj_ice_st_create(&stun_cfg, "offerer", NULL, &icest_cb, &im1);
+    status = pj_ice_st_create(&stun_cfg, "offerer", comp_cnt, NULL, &icest_cb, &im1);
     if (status != PJ_SUCCESS)
 	return -20;
@@ -168,16 +261,11 @@
     im1->user_data = id1;
 
-    /* Add first component */
-    status = pj_ice_st_add_comp(im1, 1);
-    if (status != PJ_SUCCESS)
-	return -21;
-
-    /* Add host candidate */
-    status = pj_ice_st_add_host_interface(im1, 1, 65535, NULL, NULL);
-    if (status != PJ_SUCCESS)
-	return -21;
+    /* Init components */
+    status = init_ice_st(im1, add_valid_comp, ocand_cnt, ocand);
+    if (status != 0)
+	return status;
 
     /* Create second ICE */
-    status = pj_ice_st_create(&stun_cfg, "answerer", NULL, &icest_cb, &im2);
+    status = pj_ice_st_create(&stun_cfg, "answerer", comp_cnt, NULL, &icest_cb, &im2);
     if (status != PJ_SUCCESS)
 	return -25;
@@ -187,13 +275,9 @@
     im2->user_data = id2;
 
-    /* Add first component */
-    status = pj_ice_st_add_comp(im2, 1);
-    if (status != PJ_SUCCESS)
-	return -26;
-
-    /* Add host candidate */
-    status = pj_ice_st_add_host_interface(im2, 1, 65535, NULL, NULL);
-    if (status != PJ_SUCCESS)
-	return -27;
+    /* Init components */
+    status = init_ice_st(im2, add_valid_comp, acand_cnt, acand);
+    if (status != 0)
+	return status;
+
 
     /* Init ICE on im1 */
@@ -217,38 +301,45 @@
 	return -35;
 
+    /* Apply delay to let other checks commence */
+    pj_thread_sleep(40);
+
     /* Mark start time */
     pj_get_timestamp(&t_start);
 
     /* Poll for wait_before_send msecs before we send the first data */
-    for (;;) {
-	pj_timestamp t_now;
-
-	handle_events(1);
-
-	pj_get_timestamp(&t_now);
-	if (pj_elapsed_msec(&t_start, &t_now) >= wait_before_send)
-	    break;
-    }
-
-    /* Send data. It must be successful! */
-    data_from_offerer = pj_str("from offerer");
-    status = pj_ice_send_data(im1->ice, 1, data_from_offerer.ptr, data_from_offerer.slen);
-    if (status != PJ_SUCCESS)
-	return -47;
-
-    data_from_answerer = pj_str("from answerer");
-    status = pj_ice_send_data(im2->ice, 1, data_from_answerer.ptr, data_from_answerer.slen);
-    if (status != PJ_SUCCESS)
-	return -48;
-
-    /* Poll to allow data to be received */
-    for (;;) {
-	pj_timestamp t_now;
-	handle_events(1);
-	pj_get_timestamp(&t_now);
-	if (pj_elapsed_msec(&t_start, &t_now) >= (wait_before_send + 200))
-	    break;
-    }
-
+    if (expected_success) {
+	for (;;) {
+	    pj_timestamp t_now;
+
+	    handle_events(1);
+
+	    CHECK_COMPLETE();
+
+	    pj_get_timestamp(&t_now);
+	    if (pj_elapsed_msec(&t_start, &t_now) >= wait_before_send)
+		break;
+	}
+
+	/* Send data. It must be successful! */
+	data_from_offerer = pj_str("from offerer");
+	status = pj_ice_send_data(im1->ice, 1, data_from_offerer.ptr, data_from_offerer.slen);
+	if (status != PJ_SUCCESS)
+	    return -47;
+
+	data_from_answerer = pj_str("from answerer");
+	status = pj_ice_send_data(im2->ice, 1, data_from_answerer.ptr, data_from_answerer.slen);
+	if (status != PJ_SUCCESS)
+	    return -48;
+
+	/* Poll to allow data to be received */
+	for (;;) {
+	    pj_timestamp t_now;
+	    handle_events(1);
+	    CHECK_COMPLETE();
+	    pj_get_timestamp(&t_now);
+	    if (pj_elapsed_msec(&t_start, &t_now) >= (wait_before_send + 200))
+		break;
+	}
+    }
 
     /* Just wait until both completes, or timed out */
@@ -258,4 +349,5 @@
 	handle_events(1);
 
+	CHECK_COMPLETE();
 	pj_get_timestamp(&t_now);
 	if (pj_elapsed_msec(&t_start, &t_now) >= max_total_time) {
@@ -266,5 +358,15 @@
 
     /* Mark end-time */
-    pj_get_timestamp(&t_end);
+    CHECK_COMPLETE();
+
+    /* If expected to fail, then just check that both fail */
+    if (!expected_success) {
+	/* Check status */
+	if (id1->err_code == PJ_SUCCESS)
+	    return -51;
+	if (id2->err_code == PJ_SUCCESS)
+	    return -52;
+	goto on_return;
+    }
 
     /* Check status */
@@ -275,15 +377,15 @@
 
     /* Verify that offerer gets answerer's transport address */
-    rcand = im1->ice->clist.checks[im1->ice->comp[0].nominated_check_id].rcand;
-    if (pj_memcmp(&rcand->addr, &im2->ice->lcand[0].addr, sizeof(pj_sockaddr_in))!=0) {
-	PJ_LOG(3,(THIS_FILE, "....error: address mismatch"));
-	return -60;
+    for (i=0; i<comp_cnt; ++i) {
+	status = verify_address(im1, im2, i+1);
+	if (status != 0)
+	    return status;
     }
 
     /* And the other way around */
-    rcand = im2->ice->clist.checks[im2->ice->comp[0].nominated_check_id].rcand;
-    if (pj_memcmp(&rcand->addr, &im1->ice->lcand[0].addr, sizeof(pj_sockaddr_in))!=0) {
-	PJ_LOG(3,(THIS_FILE, "....error: address mismatch"));
-	return -70;
+    for (i=0; i<comp_cnt; ++i) {
+	status = verify_address(im2, im1, i+1);
+	if (status != 0)
+	    return status;
     }
 
@@ -309,10 +411,11 @@
 
 
+on_return:
+
     /* Done */
-    PJ_LOG(3,(THIS_FILE, "....success: ICE completed in %d msec", 
+    PJ_LOG(3,(THIS_FILE, "....success: ICE completed in %d msec, waiting..", 
 	      pj_elapsed_msec(&t_start, &t_end)));
 
     /* Wait for some more time */
-    PJ_LOG(3,(THIS_FILE, ".....waiting.."));
     for (;;) {
 	pj_timestamp t_now;
@@ -328,4 +431,5 @@
     pj_ice_st_destroy(im1);
     pj_ice_st_destroy(im2);
+    handle_events(100);
     return 0;
 }
@@ -338,4 +442,15 @@
     pj_ioqueue_t *ioqueue;
     pj_timer_heap_t *timer_heap;
+    enum { D1=500, D2=5000, D3=15000 };
+    struct dummy_cand ocand[] = 
+    {
+	{1, PJ_ICE_CAND_TYPE_SRFLX, "127.1.1.1", 65534 },
+	{2, PJ_ICE_CAND_TYPE_SRFLX, "127.1.1.1", 65535 },
+    };
+    struct dummy_cand acand[] =
+    {
+	{1, PJ_ICE_CAND_TYPE_SRFLX, "127.2.2.2", 65534 },
+	{2, PJ_ICE_CAND_TYPE_SRFLX, "127.2.2.2", 65535 },
+    };
 
     pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);
@@ -345,5 +460,5 @@
     pj_stun_config_init(&stun_cfg, mem, 0, ioqueue, timer_heap);
 
-    pj_log_set_level(5);
+    //pj_log_set_level(4);
 
     /* Basic create/destroy */
@@ -353,15 +468,32 @@
 
     /* Direct communication */
-    rc = perform_ice_test("Direct connection", 500, 1000);
+    rc = perform_ice_test("Simple test (1 component)", PJ_TRUE, 1, PJ_TRUE, D1, D2, 0, NULL, 0, NULL);
+    if (rc != 0)
+	goto on_return;
+
+    /* Failure case (all checks fail) */
+    rc = perform_ice_test("Failure case (all checks fail)", PJ_FALSE, 1, PJ_FALSE, D3, D3, 1, ocand, 1, acand);
     if (rc != 0)
 	goto on_return;
 
     /* Direct communication with invalid address */
-    rc = perform_ice_test("Direct connection with 1 invalid address", 500, 1000);
+    rc = perform_ice_test("With 1 unreachable address", PJ_TRUE, 1, PJ_TRUE, D1, D2, 1, ocand, 0, NULL);
+    if (rc != 0)
+	goto on_return;
+
+    /* Direct communication with invalid address */
+    rc = perform_ice_test("With 2 unreachable addresses (one each)", PJ_TRUE, 1, PJ_TRUE, D1, D2, 1, ocand, 1, acand);
     if (rc != 0)
 	goto on_return;
 
     /* Direct communication with two components */
-    rc = perform_ice_test("Direct connection with two components", 500, 1000);
+    rc = perform_ice_test("With two components (RTP and RTCP)", PJ_TRUE, 2, PJ_TRUE, D1, D2, 0, NULL, 0, NULL);
+    if (rc != 0)
+	goto on_return;
+
+    /* Direct communication with mismatch number of components */
+
+    /* Direct communication with 2 components and 2 invalid address */
+    rc = perform_ice_test("With 2 two components and 2 unreachable address", PJ_TRUE, 2, PJ_TRUE, D1, D2, 1, ocand, 1, acand);
     if (rc != 0)
 	goto on_return;
@@ -370,5 +502,5 @@
 
 on_return:
-    pj_log_set_level(3);
+    //pj_log_set_level(3);
     pj_ioqueue_destroy(stun_cfg.ioqueue);
     pj_pool_release(pool);
Index: /pjproject/trunk/pjnath/src/pjnath-test/test.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjnath-test/test.c	(revision 1105)
+++ /pjproject/trunk/pjnath/src/pjnath-test/test.c	(revision 1106)
@@ -50,9 +50,7 @@
     mem = &caching_pool.factory;
 
-#if 0
     pj_log_set_level(3);
     pj_log_set_decor(PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_TIME | 
                      PJ_LOG_HAS_MICRO_SEC);
-#endif
 
     rc = pj_init();
Index: /pjproject/trunk/pjnath/src/pjnath/ice.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjnath/ice.c	(revision 1105)
+++ /pjproject/trunk/pjnath/src/pjnath/ice.c	(revision 1106)
@@ -57,9 +57,9 @@
 };
 
-#define CHECK_NAME_LEN	    128
-#define LOG4(expr)	    PJ_LOG(4,expr)
-#define LOG5(expr)	    PJ_LOG(4,expr)
-#define GET_LCAND_ID(cand)  (cand - ice->lcand)
-#define GET_CHECK_ID(chk)   (chk - ice->clist.checks)
+#define CHECK_NAME_LEN		128
+#define LOG4(expr)		PJ_LOG(4,expr)
+#define LOG5(expr)		PJ_LOG(4,expr)
+#define GET_LCAND_ID(cand)	(cand - ice->lcand)
+#define GET_CHECK_ID(cl, chk)	(chk - (cl)->checks)
 
 
@@ -131,4 +131,10 @@
 
 
+PJ_DEF(const char*) pj_ice_get_cand_type_name(pj_ice_cand_type type)
+{
+    return cand_type_names[type];
+}
+
+
 /*
  * Create ICE stream session.
@@ -177,6 +183,5 @@
 	pj_ice_comp *comp;
 	comp = &ice->comp[i];
-	comp->comp_id = i+1;
-	comp->nominated_check_id = -1;
+	comp->valid_check = NULL;
     }
 
@@ -412,4 +417,5 @@
 		     foundation && addr && base_addr && addr_len,
 		     PJ_EINVAL);
+    PJ_ASSERT_RETURN(comp_id <= ice->comp_cnt, PJ_EINVAL);
 
     pj_mutex_lock(ice->mutex);
@@ -499,4 +505,5 @@
 
     PJ_ASSERT_RETURN(ice && comp_id && cand_id, PJ_EINVAL);
+    PJ_ASSERT_RETURN(comp_id <= ice->comp_cnt, PJ_EINVAL);
 
     *cand_id = -1;
@@ -586,5 +593,5 @@
 
 static const char *dump_check(char *buffer, unsigned bufsize,
-			      const pj_ice *ice,
+			      const pj_ice_checklist *clist,
 			      const pj_ice_check *check)
 {
@@ -598,6 +605,7 @@
     if (lcand->addr.addr.sa_family == PJ_AF_INET) {
 	len = pj_ansi_snprintf(buffer, bufsize,
-			       "%d: %s:%d-->%s:%d",
-			       GET_CHECK_ID(check),
+			       "%d: [%d] %s:%d-->%s:%d",
+			       GET_CHECK_ID(clist, check),
+			       check->lcand->comp_id,
 			       laddr, (int)pj_ntohs(lcand->addr.ipv4.sin_port),
 			       pj_inet_ntoa(rcand->addr.ipv4.sin_addr),
@@ -628,5 +636,5 @@
 	const pj_ice_check *c = &clist->checks[i];
 	LOG4((ice->obj_name, " %s (%s, state=%s)",
-	     dump_check(buffer, sizeof(buffer), ice, c),
+	     dump_check(buffer, sizeof(buffer), clist, c),
 	     (c->nominated ? "nominated" : "not nominated"), 
 	     check_state_name[c->state]));
@@ -647,5 +655,5 @@
 
     LOG5((ice->obj_name, "Check %s: state changed from %s to %s",
-	 dump_check(buf, sizeof(buf), ice, check),
+	 dump_check(buf, sizeof(buf), &ice->clist, check),
 	 check_state_name[check->state],
 	 check_state_name[st]));
@@ -760,5 +768,6 @@
 
 		LOG5((ice->obj_name, "Check %s pruned",
-		    dump_check(buf, sizeof(buf), ice, &clist->checks[j])));
+		    dump_check(buf, sizeof(buf), &ice->clist, 
+			       &clist->checks[j])));
 
 		pj_array_erase(clist->checks, sizeof(clist->checks[0]),
@@ -813,19 +822,34 @@
     if (check->err_code==PJ_SUCCESS && check->nominated) {
 	pj_ice_comp *comp;
+	char buf[CHECK_NAME_LEN];
 
 	LOG5((ice->obj_name, "Check %d is successful and nominated",
-	     GET_CHECK_ID(check)));
+	     GET_CHECK_ID(&ice->clist, check)));
 
 	for (i=0; i<ice->clist.count; ++i) {
 	    pj_ice_check *c = &ice->clist.checks[i];
-	    if (c->lcand->comp_id == check->lcand->comp_id &&
-		(c->state==PJ_ICE_CHECK_STATE_FROZEN ||
-		 c->state==PJ_ICE_CHECK_STATE_WAITING))
-	    {
-		LOG5((ice->obj_name, 
-		     "Check %d to be failed because state is %s",
-		     i, check_state_name[c->state]));
-		check_set_state(ice, c, PJ_ICE_CHECK_STATE_FAILED,
-				PJ_ECANCELLED);
+	    if (c->lcand->comp_id == check->lcand->comp_id) {
+		if (c->state < PJ_ICE_CHECK_STATE_IN_PROGRESS) {
+		    /* Just fail Frozen/Waiting check */
+		    LOG5((ice->obj_name, 
+			 "Check %s to be failed because state is %s",
+			 dump_check(buf, sizeof(buf), &ice->clist, c), 
+			 check_state_name[c->state]));
+		    check_set_state(ice, c, PJ_ICE_CHECK_STATE_FAILED,
+				    PJ_ECANCELLED);
+
+		} else if (c->state == PJ_ICE_CHECK_STATE_IN_PROGRESS) {
+		    /* State is IN_PROGRESS, cancel transaction */
+		    if (c->tdata) {
+			LOG5((ice->obj_name, 
+			     "Cancelling check %s (In Progress)",
+			     dump_check(buf, sizeof(buf), &ice->clist, c)));
+			pj_stun_session_cancel_req(c->lcand->stun_sess, 
+						   c->tdata, PJ_FALSE, 0);
+			c->tdata = NULL;
+			check_set_state(ice, c, PJ_ICE_CHECK_STATE_FAILED,
+					PJ_ECANCELLED);
+		    }
+		}
 	    }
 	}
@@ -833,11 +857,9 @@
 	/* Update the nominated check for the component */
 	comp = find_comp(ice, check->lcand->comp_id);
-	if (comp->nominated_check_id < 0) {
-	    comp->nominated_check_id = GET_CHECK_ID(check);
+	if (comp->valid_check == NULL) {
+	    comp->valid_check = check;
 	} else {
-	    pj_ice_check *nom_check;
-	    nom_check = &ice->clist.checks[comp->nominated_check_id];
-	    if (nom_check->prio < check->prio)
-		comp->nominated_check_id = GET_CHECK_ID(check);
+	    if (comp->valid_check->prio < check->prio)
+		comp->valid_check = check;
 	}
     }
@@ -878,5 +900,5 @@
      */
     for (i=0; i<ice->comp_cnt; ++i) {
-	if (ice->comp[i].nominated_check_id == -1)
+	if (ice->comp[i].valid_check == NULL)
 	    break;
     }
@@ -950,7 +972,15 @@
     ice->rcand_cnt = 0;
     for (i=0; i<rcand_cnt; ++i) {
-	pj_ice_cand *cn = &ice->rcand[ice->rcand_cnt++];
+	pj_ice_cand *cn = &ice->rcand[ice->rcand_cnt];
+
+	/* Ignore candidate which has no matching component ID */
+	pj_assert(rcand[i].comp_id > 0);
+	if (rcand[i].comp_id==0 || rcand[i].comp_id > ice->comp_cnt) {
+	    continue;
+	}
+
 	pj_memcpy(cn, &rcand[i], sizeof(pj_ice_cand));
 	pj_strdup(ice->pool, &cn->foundation, &rcand[i].foundation);
+	ice->rcand_cnt++;
     }
 
@@ -967,7 +997,5 @@
 		pj_mutex_unlock(ice->mutex);
 		return PJ_ETOOMANY;
-	    } else {
-		clist->count++;
-	    }
+	    } 
 
 	    /* A local candidate is paired with a remote candidate if
@@ -987,4 +1015,6 @@
 
 	    chk->prio = CALC_CHECK_PRIO(ice, lcand, rcand);
+
+	    clist->count++;
 	}
     }
@@ -1027,5 +1057,4 @@
 				 unsigned check_id)
 {
-    pj_stun_tx_data *tdata;
     pj_ice_comp *comp;
     struct req_data *rd;
@@ -1044,9 +1073,10 @@
     LOG5((ice->obj_name, 
 	 "Sending connectivity check for check %s", 
-	 dump_check(buffer, sizeof(buffer), ice, check)));
+	 dump_check(buffer, sizeof(buffer), clist, check)));
 
     /* Create request */
     status = pj_stun_session_create_req(lcand->stun_sess, 
-					PJ_STUN_BINDING_REQUEST, &tdata);
+					PJ_STUN_BINDING_REQUEST, 
+					&check->tdata);
     if (status != PJ_SUCCESS)
 	return status;
@@ -1055,19 +1085,19 @@
      * completes and on_stun_request_complete() callback is called.
      */
-    rd = PJ_POOL_ZALLOC_T(tdata->pool, struct req_data);
+    rd = PJ_POOL_ZALLOC_T(check->tdata->pool, struct req_data);
     rd->ice = ice;
     rd->clist = clist;
     rd->ckid = check_id;
-    tdata->user_data = (void*) rd;
+    check->tdata->user_data = (void*) rd;
 
     /* Add PRIORITY */
     prio = CALC_CAND_PRIO(PJ_ICE_CAND_TYPE_PRFLX, 65535, 
 			  lcand->comp_id);
-    pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, PJ_STUN_ATTR_PRIORITY,
-			      prio);
+    pj_stun_msg_add_uint_attr(check->tdata->pool, check->tdata->msg, 
+			      PJ_STUN_ATTR_PRIORITY, prio);
 
     /* Add USE-CANDIDATE and set this check to nominated */
     if (ice->role == PJ_ICE_ROLE_CONTROLLING) {
-	pj_stun_msg_add_empty_attr(tdata->pool, tdata->msg, 
+	pj_stun_msg_add_empty_attr(check->tdata->pool, check->tdata->msg, 
 				   PJ_STUN_ATTR_USE_CANDIDATE);
 	check->nominated = PJ_TRUE;
@@ -1081,7 +1111,9 @@
     status = pj_stun_session_send_msg(lcand->stun_sess, PJ_FALSE, 
 				      &rcand->addr, 
-				      sizeof(pj_sockaddr_in), tdata);
-    if (status != PJ_SUCCESS)
+				      sizeof(pj_sockaddr_in), check->tdata);
+    if (status != PJ_SUCCESS) {
+	check->tdata = NULL;
 	return status;
+    }
 
     check_set_state(ice, check, PJ_ICE_CHECK_STATE_IN_PROGRESS, PJ_SUCCESS);
@@ -1250,4 +1282,8 @@
     clist = rd->clist;
 
+    /* Mark STUN transaction as complete */
+    pj_assert(tdata == check->tdata);
+    check->tdata = NULL;
+
     pj_mutex_lock(ice->mutex);
 
@@ -1259,5 +1295,5 @@
     LOG4((ice->obj_name, 
 	 "Check %s%s: connectivity check %s",
-	 dump_check(buffer, sizeof(buffer), ice, check),
+	 dump_check(buffer, sizeof(buffer), &ice->clist, check),
 	 (check->nominated ? " (nominated)" : " (not nominated)"),
 	 (status==PJ_SUCCESS ? "SUCCESS" : "FAILED")));
@@ -1501,5 +1537,5 @@
     if (i == ice->rcand_cnt) {
 	rcand = &ice->rcand[ice->rcand_cnt++];
-	rcand->comp_id = comp->comp_id;
+	rcand->comp_id = lcand->comp_id;
 	rcand->type = PJ_ICE_CAND_TYPE_PRFLX;
 	rcand->prio = ap->value;
@@ -1649,7 +1685,6 @@
     pj_ice_comp *comp;
     unsigned cand_id;
-    pj_ice_check *check;
-
-    PJ_ASSERT_RETURN(ice, PJ_EINVAL);
+
+    PJ_ASSERT_RETURN(ice && comp_id && comp_id <= ice->comp_cnt, PJ_EINVAL);
     
     pj_mutex_lock(ice->mutex);
@@ -1661,14 +1696,12 @@
     }
 
-    if (comp->nominated_check_id == -1) {
+    if (comp->valid_check == NULL) {
 	status = PJNATH_EICEINPROGRESS;
 	goto on_return;
     }
 
-    check = &ice->clist.checks[comp->nominated_check_id];
-    cand_id = GET_LCAND_ID(check->lcand);
-
+    cand_id = GET_LCAND_ID(comp->valid_check->lcand);
     status = (*ice->cb.on_tx_pkt)(ice, comp_id, cand_id, data, data_len, 
-				  &check->rcand->addr, 
+				  &comp->valid_check->rcand->addr, 
 				  sizeof(pj_sockaddr_in));
 
Index: /pjproject/trunk/pjnath/src/pjnath/ice_stream_transport.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjnath/ice_stream_transport.c	(revision 1105)
+++ /pjproject/trunk/pjnath/src/pjnath/ice_stream_transport.c	(revision 1106)
@@ -61,4 +61,5 @@
 
 /* Utility: print error */
+#if PJ_LOG_MAX_LEVEL >= 3
 static void ice_st_perror(pj_ice_st *ice_st, const char *title, 
 			  pj_status_t status)
@@ -67,6 +68,9 @@
 
     pj_strerror(status, errmsg, sizeof(errmsg));
-    PJ_LOG(1,(ice_st->obj_name, "%s: %s", title, errmsg));
-}
+    PJ_LOG(3,(ice_st->obj_name, "%s: %s", title, errmsg));
+}
+#else
+#   define ice_st_perror(ice_st, title, status)
+#endif
 
 
@@ -225,4 +229,42 @@
 }
 
+/* Add new candidate */
+static pj_status_t add_cand( pj_ice_st *ice_st,
+			     pj_ice_st_comp *comp,
+			     unsigned comp_id,
+			     pj_ice_cand_type type,
+			     pj_uint16_t local_pref,
+			     const pj_sockaddr_in *addr,
+			     pj_bool_t set_default)
+{
+    pj_ice_st_cand *cand;
+
+    PJ_ASSERT_RETURN(ice_st && comp && addr, PJ_EINVAL);
+    PJ_ASSERT_RETURN(comp->cand_cnt < PJ_ICE_ST_MAX_ALIASES, PJ_ETOOMANY);
+
+    cand = &comp->cand_list[comp->cand_cnt];
+
+    pj_bzero(cand, sizeof(*cand));
+    cand->type = type;
+    cand->status = PJ_SUCCESS;
+    pj_memcpy(&cand->addr, addr, sizeof(pj_sockaddr_in));
+    cand->cand_id = -1;
+    cand->local_pref = local_pref;
+    cand->foundation = calc_foundation(ice_st->pool, type, &addr->sin_addr);
+
+    if (set_default) 
+	comp->default_cand = comp->cand_cnt;
+
+    PJ_LOG(5,(ice_st->obj_name, 
+	      "Candidate %s:%d (type=%s) added to component %d",
+	      pj_inet_ntoa(addr->sin_addr),
+	      (int)pj_ntohs(addr->sin_port), 
+	      pj_ice_get_cand_type_name(type),
+	      comp_id));
+    
+    comp->cand_cnt++;
+    return PJ_SUCCESS;
+}
+
 /*  Create new component (i.e. socket)  */
 static pj_status_t create_component(pj_ice_st *ice_st,
@@ -301,5 +343,7 @@
      * cand_list.
      */
-    if (comp->local_addr.ipv4.sin_addr.s_addr == 0) {
+    if (((options & PJ_ICE_ST_OPT_DONT_ADD_CAND)==0) &&
+	comp->local_addr.ipv4.sin_addr.s_addr == 0) 
+    {
 	/* Socket is bound to INADDR_ANY */
 	unsigned i, ifs_cnt;
@@ -318,62 +362,60 @@
 	status = pj_gethostip(&comp->local_addr.ipv4.sin_addr);
 	if (status != PJ_SUCCESS)
-	    return status;
+	    goto on_error;
 
 	/* Add candidate entry for each interface */
 	for (i=0; i<ifs_cnt; ++i) {
-	    pj_ice_st_cand *cand = &comp->cand_list[i];
-
-	    cand->type = PJ_ICE_CAND_TYPE_HOST;
-	    cand->status = PJ_SUCCESS;
-	    pj_memcpy(&cand->addr, &comp->local_addr, sizeof(pj_sockaddr_in));
-	    cand->addr.ipv4.sin_addr.s_addr = ifs[i].s_addr;
-	    cand->cand_id = -1;
-	    cand->local_pref = 65535;
-	    cand->foundation = calc_foundation(ice_st->pool, 
-					     PJ_ICE_CAND_TYPE_HOST,
-					     &cand->addr.ipv4.sin_addr);
+	    pj_sockaddr_in cand_addr;
+	    pj_bool_t set_default;
+
+	    /* Ignore 127.0.0.0/24 address */
+	    if ((pj_ntohl(ifs[i].s_addr) >> 24)==127)
+		continue;
+
+	    pj_memcpy(&cand_addr, &comp->local_addr, sizeof(pj_sockaddr_in));
+	    cand_addr.sin_addr.s_addr = ifs[i].s_addr;
+
 
 	    /* If the IP address is equal to local address, assign it
 	     * as default candidate.
 	     */
-	    if (cand->addr.ipv4.sin_addr.s_addr ==
-		comp->local_addr.ipv4.sin_addr.s_addr)
-	    {
-		comp->default_cand = i;
+	    if (ifs[i].s_addr == comp->local_addr.ipv4.sin_addr.s_addr) {
+		set_default = PJ_TRUE;
+	    } else {
+		set_default = PJ_FALSE;
 	    }
 
-	    PJ_LOG(5,(ice_st->obj_name, 
-		      "Interface %s:%d added to component %d",
-		      pj_inet_ntoa(cand->addr.ipv4.sin_addr),
-		      (int)pj_ntohs(cand->addr.ipv4.sin_port), comp_id));
+	    status = add_cand(ice_st, comp, comp_id, 
+			      PJ_ICE_CAND_TYPE_HOST, 
+			      (pj_uint16_t)(65535-i), &cand_addr,
+			      set_default);
+	    if (status != PJ_SUCCESS)
+		goto on_error;
 	}
-	comp->cand_cnt = ifs_cnt;
-
-
-    } else {
+
+
+    } else if ((options & PJ_ICE_ST_OPT_DONT_ADD_CAND)==0) {
 	/* Socket is bound to specific address. 
 	 * In this case only add that address as a single entry in the
 	 * cand_list table.
 	 */
-	pj_ice_st_cand *cand = &comp->cand_list[0];
-
-	cand->type = PJ_ICE_CAND_TYPE_HOST;
-	cand->status = PJ_SUCCESS;
-	pj_memcpy(&cand->addr, &comp->local_addr, sizeof(pj_sockaddr_in));
-	cand->cand_id = -1;
-	cand->local_pref = 65535;
-	cand->foundation = calc_foundation(ice_st->pool, 
-					 PJ_ICE_CAND_TYPE_HOST,
-					 &cand->addr.ipv4.sin_addr);
-
-	comp->cand_cnt = 1;
-	comp->default_cand = 0;
-
-	PJ_LOG(5,(ice_st->obj_name, 
-		  "Interface %s:%d added to component %d",
-		  pj_inet_ntoa(cand->addr.ipv4.sin_addr),
-		  (int)pj_ntohs(cand->addr.ipv4.sin_port), comp_id));
-
-    }
+	status = add_cand(ice_st, comp, comp_id, 
+			  PJ_ICE_CAND_TYPE_HOST, 
+			  65535, &comp->local_addr.ipv4,
+			  PJ_TRUE);
+	if (status != PJ_SUCCESS)
+	    goto on_error;
+
+    } else if (options & PJ_ICE_ST_OPT_DONT_ADD_CAND) {
+	/* If application doesn't want to add candidate, just fix local_addr
+	 * in case its value is zero.
+	 */
+	if (comp->local_addr.ipv4.sin_addr.s_addr == 0) {
+	    status = pj_gethostip(&comp->local_addr.ipv4.sin_addr);
+	    if (status != PJ_SUCCESS)
+		return status;
+	}
+    }
+
 
     /* Done */
@@ -569,6 +611,5 @@
 					  unsigned comp_id,
 					  pj_uint32_t options,
-					  const pj_sockaddr_in *addr,
-				    	  unsigned *p_itf_id)
+					  const pj_sockaddr_in *addr)
 {
     pj_ice_st_comp *comp;
@@ -602,10 +643,27 @@
 
     /* Store this component */
-    if (p_itf_id)
-	*p_itf_id = ice_st->comp_cnt;
-
     ice_st->comp[comp_id-1] = comp;
 
     return PJ_SUCCESS;
+}
+
+
+PJ_DEF(pj_status_t) pj_ice_st_add_cand( pj_ice_st *ice_st,
+					unsigned comp_id,
+					pj_ice_cand_type type,
+					pj_uint16_t local_pref,
+					const pj_sockaddr_in *addr,
+					pj_bool_t set_default)
+{
+    pj_ice_st_comp *comp;
+
+
+    PJ_ASSERT_RETURN(ice_st && comp_id && addr, PJ_EINVAL);
+    PJ_ASSERT_RETURN(comp_id <= ice_st->comp_cnt, PJ_EINVAL);
+    PJ_ASSERT_RETURN(ice_st->comp[comp_id-1] != NULL, PJ_EINVALIDOP);
+
+    comp = ice_st->comp[comp_id-1];
+    return add_cand(ice_st, comp, comp_id, type, local_pref, addr, 
+		    set_default);
 }
 
@@ -652,4 +710,6 @@
     /* Must not have ICE */
     PJ_ASSERT_RETURN(ice_st->ice == NULL, PJ_EINVALIDOP);
+    /* Components must have been created */
+    PJ_ASSERT_RETURN(ice_st->comp[0] != NULL, PJ_EINVALIDOP);
 
     /* Init callback */
Index: /pjproject/trunk/pjnath/src/pjnath/stun_session.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjnath/stun_session.c	(revision 1105)
+++ /pjproject/trunk/pjnath/src/pjnath/stun_session.c	(revision 1106)
@@ -678,4 +678,29 @@
 }
 
+/*
+ * Cancel outgoing STUN transaction. 
+ */
+PJ_DEF(pj_status_t) pj_stun_session_cancel_req( pj_stun_session *sess,
+						pj_stun_tx_data *tdata,
+						pj_bool_t notify,
+						pj_status_t notify_status)
+{
+    PJ_ASSERT_RETURN(sess && tdata, PJ_EINVAL);
+    PJ_ASSERT_RETURN(!notify || notify_status!=PJ_SUCCESS, PJ_EINVAL);
+    PJ_ASSERT_RETURN(PJ_STUN_IS_REQUEST(tdata->msg->hdr.type), PJ_EINVAL);
+
+    pj_mutex_lock(sess->mutex);
+
+    if (notify) {
+	(sess->cb.on_request_complete)(sess, notify_status, tdata, NULL);
+    }
+
+    /* Just destroy tdata. This will destroy the transaction as well */
+    pj_stun_msg_destroy_tdata(sess, tdata);
+
+    pj_mutex_unlock(sess->mutex);
+    return PJ_SUCCESS;
+
+}
 
 /* Send response */
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 1105)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 1106)
@@ -564,5 +564,5 @@
 	int next_port;
 
-	status = pjmedia_ice_create(pjsua_var.med_endpt, NULL, 1,
+	status = pjmedia_ice_create(pjsua_var.med_endpt, NULL, 2,
 				    &pjsua_var.stun_cfg, 
 				    &pjsua_var.calls[i].med_tp);
