Index: /pjproject/trunk/pjnath/include/pjnath/stun_auth.h
===================================================================
--- /pjproject/trunk/pjnath/include/pjnath/stun_auth.h	(revision 1868)
+++ /pjproject/trunk/pjnath/include/pjnath/stun_auth.h	(revision 1869)
@@ -278,4 +278,7 @@
  * @param pool		If response is to be created, then memory will
  *			be allocated from this pool.
+ * @param auth_key	Optional pointer to receive authentication key to
+ *			calculate MESSAGE-INTEGRITY of the response, if
+ *			the response needs to be authenticated.
  * @param p_response	Optional pointer to receive the response message
  *			then the credential in the request fails to
@@ -292,4 +295,5 @@
 					          pj_stun_auth_cred *cred,
 					          pj_pool_t *pool,
+						  pj_str_t *auth_key,
 					          pj_stun_msg **p_response);
 
Index: /pjproject/trunk/pjnath/src/pjnath-test/stun.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjnath-test/stun.c	(revision 1868)
+++ /pjproject/trunk/pjnath/src/pjnath-test/stun.c	(revision 1869)
@@ -656,5 +656,5 @@
 
 		status = pj_stun_authenticate_request(buf, len, msg, 
-						      &cred, pool, NULL);
+						      &cred, pool, NULL, NULL);
 		if (status != PJ_SUCCESS) {
 		    char errmsg[PJ_ERR_MSG_SIZE];
Index: /pjproject/trunk/pjnath/src/pjnath/stun_auth.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjnath/stun_auth.c	(revision 1868)
+++ /pjproject/trunk/pjnath/src/pjnath/stun_auth.c	(revision 1869)
@@ -122,4 +122,5 @@
 					         pj_stun_auth_cred *cred,
 					         pj_pool_t *pool,
+						 pj_str_t *auth_key,
 					         pj_stun_msg **p_response)
 {
@@ -333,4 +334,8 @@
 				 NULL, &realm, &nonce, p_response);
 	    }
+	    if (auth_key) {
+		pj_stun_create_key(pool, auth_key, &realm, 
+				   &auser->value, &password);
+	    }
 	    return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_STALE_NONCE);
 	}
Index: /pjproject/trunk/pjnath/src/pjnath/stun_session.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjnath/stun_session.c	(revision 1868)
+++ /pjproject/trunk/pjnath/src/pjnath/stun_session.c	(revision 1869)
@@ -860,4 +860,5 @@
 {
     pj_stun_msg *response;
+    pj_str_t auth_key;
     pj_status_t status;
 
@@ -866,8 +867,8 @@
 
     status = pj_stun_authenticate_request(pkt, pkt_len, msg, sess->cred,
-				          tmp_pool, &response);
+				          tmp_pool, &auth_key, &response);
     if (status != PJ_SUCCESS && response != NULL) {
 	PJ_LOG(5,(SNAME(sess), "Message authentication failed"));
-	send_response(sess, tmp_pool, response, NULL, PJ_FALSE, 
+	send_response(sess, tmp_pool, response, &auth_key, PJ_FALSE, 
 		      src_addr, src_addr_len);
     }
Index: /pjproject/trunk/pjnath/src/pjnath/turn_session.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjnath/turn_session.c	(revision 1868)
+++ /pjproject/trunk/pjnath/src/pjnath/turn_session.c	(revision 1869)
@@ -219,4 +219,7 @@
     }
 
+    /* Attach ourself to STUN session */
+    pj_stun_session_set_user_data(sess->stun, sess);
+
     /* Replace mutex in STUN session with a NULL mutex, since access to
      * STUN session is serialized.
Index: /pjproject/trunk/pjnath/src/pjnath/turn_udp.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjnath/turn_udp.c	(revision 1868)
+++ /pjproject/trunk/pjnath/src/pjnath/turn_udp.c	(revision 1869)
@@ -20,4 +20,5 @@
 #include <pj/assert.h>
 #include <pj/errno.h>
+#include <pj/log.h>
 #include <pj/pool.h>
 #include <pj/ioqueue.h>
@@ -113,4 +114,13 @@
     }
 
+    /* Bind to any */
+    pj_sockaddr_init(af, &udp_rel->src_addr, NULL, 0);
+    status = pj_sock_bind(udp_rel->sock, &udp_rel->src_addr, 
+			  pj_sockaddr_get_len(&udp_rel->src_addr));
+    if (status != PJ_SUCCESS) {
+	pj_turn_udp_destroy(udp_rel);
+	return status;
+    }
+
     /* Register to ioqeuue */
     pj_bzero(&ioq_cb, sizeof(ioq_cb));
@@ -256,5 +266,7 @@
                              pj_ssize_t bytes_read)
 {
+    enum { MAX_RETRY = 10 };
     pj_turn_udp *udp_rel;
+    int retry = 0;
     pj_status_t status;
 
@@ -271,5 +283,4 @@
 	bytes_read = sizeof(udp_rel->pkt);
 	udp_rel->src_addr_len = sizeof(udp_rel->src_addr);
-
 	status = pj_ioqueue_recvfrom(udp_rel->key, op_key,
 				     udp_rel->pkt, &bytes_read, 0,
@@ -277,8 +288,16 @@
 				     &udp_rel->src_addr_len);
 
-	if (status != PJ_EPENDING && status != PJ_SUCCESS)
+	if (status != PJ_EPENDING && status != PJ_SUCCESS) {
+	    char errmsg[PJ_ERR_MSG_SIZE];
+
+	    pj_strerror(status, errmsg, sizeof(errmsg));
+	    PJ_LOG(4,(udp_rel->pool->obj_name,
+		      "ioqueue recvfrom error: %s", errmsg));
+
 	    bytes_read = -status;
-
-    } while (status != PJ_EPENDING && status != PJ_ECANCELLED);
+	}
+
+    } while (status != PJ_EPENDING && status != PJ_ECANCELLED &&
+	     ++retry < MAX_RETRY);
 
 }
Index: /pjproject/trunk/pjnath/src/pjturn-client/client_main.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjturn-client/client_main.c	(revision 1868)
+++ /pjproject/trunk/pjnath/src/pjturn-client/client_main.c	(revision 1869)
@@ -133,5 +133,5 @@
 	len = sizeof(addr);
 	CHECK( pj_sock_getsockname(g.peer[i].sock, &addr, &len) );
-	port = pj_sockaddr_get_port(&g.peer[i].addr);
+	port = pj_sockaddr_get_port(&addr);
 
 	CHECK( pj_gethostip(pj_AF_INET(), &g.peer[i].addr) );
@@ -358,5 +358,8 @@
 	pj_turn_udp_get_info(g.udp_rel, &info);
 	strcpy(client_state, pj_turn_state_name(info.state));
-	pj_sockaddr_print(&info.relay_addr, relay_addr, sizeof(relay_addr), 3);
+	if (info.state >= PJ_TURN_STATE_READY)
+	    pj_sockaddr_print(&info.relay_addr, relay_addr, sizeof(relay_addr), 3);
+	else
+	    strcpy(relay_addr, "0.0.0.0:0");
     } else {
 	strcpy(client_state, "NULL");
@@ -372,7 +375,7 @@
     puts("|             CLIENT                |             PEER-0             |");
     puts("|                                   |                                |");
-    printf("| State     : %12s          | Address: %21s |\n",
+    printf("| State     : %-12s          | Address: %-21s |\n",
 	   client_state, peer0_addr);
-    printf("| Relay addr: %21s |                                |\n",
+    printf("| Relay addr: %-21s |                                |\n",
 	   relay_addr);
     puts("|                                   | 0  Send data to relay address  |");
@@ -380,5 +383,5 @@
     puts("| S[01]  Send data to peer 0/1      |             PEER-1             |");
     puts("| B[01]  BindChannel to peer 0/1    |                                |");
-    printf("| X      Delete allocation          | Address: %21s |\n",
+    printf("| X      Delete allocation          | Address: %-21s |\n",
 	  peer1_addr);
     puts("+-----------------------------------+                                |");
Index: /pjproject/trunk/pjnath/src/pjturn-srv/auth.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjturn-srv/auth.c	(revision 1868)
+++ /pjproject/trunk/pjnath/src/pjturn-srv/auth.c	(revision 1869)
@@ -56,4 +56,27 @@
 {
     /* Nothing to do */
+}
+
+
+PJ_DEF(pj_status_t) pj_turn_get_cred( const pj_stun_msg *msg,
+				      void *user_data,
+				      pj_pool_t *pool,
+				      pj_str_t *realm,
+				      pj_str_t *username,
+				      pj_str_t *nonce,
+				      int *data_type,
+				      pj_str_t *data)
+{
+    PJ_UNUSED_ARG(msg);
+    PJ_UNUSED_ARG(pool);
+    PJ_UNUSED_ARG(user_data);
+
+    *realm = pj_str(g_realm);
+    *username = pj_str(g_cred[0].username);
+    *nonce = pj_str(THE_NONCE);
+    *data_type = 0;
+    *data = pj_str(g_cred[0].passwd);
+
+    return PJ_SUCCESS;
 }
 
Index: /pjproject/trunk/pjnath/src/pjturn-srv/auth.h
===================================================================
--- /pjproject/trunk/pjnath/src/pjturn-srv/auth.h	(revision 1868)
+++ /pjproject/trunk/pjnath/src/pjturn-srv/auth.h	(revision 1869)
@@ -62,4 +62,16 @@
 
 /**
+ * Get credential.
+ */
+PJ_DECL(pj_status_t) pj_turn_get_cred(const pj_stun_msg *msg,
+				      void *user_data,
+				      pj_pool_t *pool,
+				      pj_str_t *realm,
+				      pj_str_t *username,
+				      pj_str_t *nonce,
+				      int *data_type,
+				      pj_str_t *data);
+
+/**
  * This function is called to get the password for the specified username.
  * This function is also used to check whether the username is valid.
Index: /pjproject/trunk/pjnath/src/pjturn-srv/main.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjturn-srv/main.c	(revision 1868)
+++ /pjproject/trunk/pjnath/src/pjturn-srv/main.c	(revision 1869)
@@ -18,4 +18,7 @@
  */
 #include "turn.h"
+#include "auth.h"
+
+#define REALM	"pjsip.org"
 
 int err(const char *title, pj_status_t status)
@@ -39,5 +42,10 @@
 	return err("pj_init() error", status);
 
+    pjlib_util_init();
+    pjnath_init();
+
     pj_caching_pool_init(&cp, NULL, 0);
+
+    pj_turn_auth_init(REALM);
 
     status = pj_turn_srv_create(&cp.factory, &srv);
@@ -45,5 +53,6 @@
 	return err("Error creating server", status);
 
-    status = pj_turn_listener_create_udp(srv, pj_AF_INET(), NULL, 3478, 1, 0, &listener);
+    status = pj_turn_listener_create_udp(srv, pj_AF_INET(), NULL, 
+					 PJ_STUN_PORT, 1, 0, &listener);
     if (status != PJ_SUCCESS)
 	return err("Error creating listener", status);
Index: /pjproject/trunk/pjnath/src/pjturn-srv/server.c
===================================================================
--- /pjproject/trunk/pjnath/src/pjturn-srv/server.c	(revision 1868)
+++ /pjproject/trunk/pjnath/src/pjturn-srv/server.c	(revision 1869)
@@ -148,5 +148,5 @@
     srv->core.cred.data.dyn_cred.user_data = srv;
     srv->core.cred.data.dyn_cred.get_auth = &pj_turn_get_auth;
-    srv->core.cred.data.dyn_cred.get_cred = &pj_turn_srv_get_cred;
+    srv->core.cred.data.dyn_cred.get_cred = &pj_turn_get_cred;
     srv->core.cred.data.dyn_cred.get_password = &pj_turn_get_password;
     srv->core.cred.data.dyn_cred.verify_nonce = &pj_turn_verify_nonce;
