Index: pjproject/trunk/pjlib/include/pj/sock.h
===================================================================
--- pjproject/trunk/pjlib/include/pj/sock.h	(revision 4342)
+++ pjproject/trunk/pjlib/include/pj/sock.h	(revision 4343)
@@ -1167,4 +1167,22 @@
 				      pj_uint16_t port);
 
+/**
+ * Bind the IP socket sockfd to the given address and a random port in the
+ * specified range.
+ *
+ * @param sockfd    	The socket desriptor.
+ * @param addr      	The local address and port to bind the socket to.
+ * @param port_range	The port range, relative the to start port number
+ * 			specified in port field in #addr. Note that if the
+ * 			port is zero, this param will be ignored.
+ * @param max_try   	Maximum retries.
+ *
+ * @return	    	Zero on success.
+ */
+PJ_DECL(pj_status_t) pj_sock_bind_random( pj_sock_t sockfd,
+				          const pj_sockaddr_t *addr,
+				          pj_uint16_t port_range,
+				          pj_uint16_t max_try);
+
 #if PJ_HAS_TCP
 /**
Index: pjproject/trunk/pjlib/src/pj/sock_common.c
===================================================================
--- pjproject/trunk/pjlib/src/pj/sock_common.c	(revision 4342)
+++ pjproject/trunk/pjlib/src/pj/sock_common.c	(revision 4343)
@@ -25,4 +25,5 @@
 #include <pj/os.h>
 #include <pj/addr_resolv.h>
+#include <pj/rand.h>
 #include <pj/string.h>
 #include <pj/compat/socket.h>
@@ -1041,4 +1042,42 @@
 
 
+/*
+ * Bind socket at random port.
+ */
+PJ_DEF(pj_status_t) pj_sock_bind_random(  pj_sock_t sockfd,
+				          const pj_sockaddr_t *addr,
+				          pj_uint16_t port_range,
+				          pj_uint16_t max_try)
+{
+    pj_sockaddr bind_addr;
+    int addr_len;
+    pj_uint16_t base_port;
+    pj_status_t status = PJ_SUCCESS;
+
+    PJ_CHECK_STACK();
+
+    PJ_ASSERT_RETURN(addr, PJ_EINVAL);
+
+    pj_sockaddr_cp(&bind_addr, addr);
+    addr_len = pj_sockaddr_get_len(addr);
+    base_port = pj_sockaddr_get_port(addr);
+
+    if (base_port == 0 || port_range == 0) {
+	return pj_sock_bind(sockfd, &bind_addr, addr_len);
+    }
+
+    for (; max_try; --max_try) {
+	pj_uint16_t port;
+	port = (pj_uint16_t)(base_port + pj_rand() % (port_range + 1));
+	pj_sockaddr_set_port(&bind_addr, port);
+	status = pj_sock_bind(sockfd, &bind_addr, addr_len);
+	if (status == PJ_SUCCESS)
+	    break;
+    }
+
+    return status;
+}
+
+
 /* Only need to implement these in DLL build */
 #if defined(PJ_DLL)
Index: pjproject/trunk/pjnath/include/pjnath/stun_sock.h
===================================================================
--- pjproject/trunk/pjnath/include/pjnath/stun_sock.h	(revision 4342)
+++ pjproject/trunk/pjnath/include/pjnath/stun_sock.h	(revision 4343)
@@ -239,7 +239,17 @@
      * is non-zero, socket will be bound to this address only, and the
      * transport will have only one address alias (the \a alias_cnt field
-     * in #pj_stun_sock_info structure.
+     * in #pj_stun_sock_info structure. If the port is set to zero, the
+     * socket will bind at any port (chosen by the OS).
      */
     pj_sockaddr bound_addr;
+
+    /**
+     * Specify the port range for STUN socket binding, relative to the start
+     * port number specified in \a bound_addr. Note that this setting is only
+     * applicable when the start port number is non zero.
+     *
+     * Default value is zero.
+     */
+    pj_uint16_t	port_range;
 
     /**
Index: pjproject/trunk/pjnath/include/pjnath/turn_sock.h
===================================================================
--- pjproject/trunk/pjnath/include/pjnath/turn_sock.h	(revision 4342)
+++ pjproject/trunk/pjnath/include/pjnath/turn_sock.h	(revision 4343)
@@ -141,4 +141,21 @@
      */
     pj_bool_t qos_ignore_error;
+
+    /**
+     * Specify the interface where the socket should be bound to. If the
+     * address is zero, socket will be bound to INADDR_ANY. If the address
+     * is non-zero, socket will be bound to this address only. If the port is
+     * set to zero, the socket will bind at any port (chosen by the OS).
+     */
+    pj_sockaddr bound_addr;
+
+    /**
+     * Specify the port range for TURN socket binding, relative to the start
+     * port number specified in \a bound_addr. Note that this setting is only
+     * applicable when the start port number is non zero.
+     *
+     * Default value is zero.
+     */
+    pj_uint16_t	port_range;
 
 } pj_turn_sock_cfg;
Index: pjproject/trunk/pjnath/src/pjnath/stun_sock.c
===================================================================
--- pjproject/trunk/pjnath/src/pjnath/stun_sock.c	(revision 4342)
+++ pjproject/trunk/pjnath/src/pjnath/stun_sock.c	(revision 4343)
@@ -33,4 +33,6 @@
 
 
+enum { MAX_BIND_RETRY = 100 };
+
 struct pj_stun_sock
 {
@@ -163,5 +165,7 @@
     pj_stun_sock *stun_sock;
     pj_stun_sock_cfg default_cfg;
+    pj_sockaddr bound_addr;
     unsigned i;
+    pj_uint16_t max_bind_retry;
     pj_status_t status;
 
@@ -212,15 +216,15 @@
 
     /* Bind socket */
-    if (pj_sockaddr_has_addr(&cfg->bound_addr)) {
-	status = pj_sock_bind(stun_sock->sock_fd, &cfg->bound_addr,
-			      pj_sockaddr_get_len(&cfg->bound_addr));
-    } else {
-	pj_sockaddr bound_addr;
-
-	pj_sockaddr_init(af, &bound_addr, NULL, 0);
-	status = pj_sock_bind(stun_sock->sock_fd, &bound_addr,
-			      pj_sockaddr_get_len(&bound_addr));
-    }
-
+    max_bind_retry = MAX_BIND_RETRY;
+    if (cfg->port_range && cfg->port_range < max_bind_retry)
+	max_bind_retry = cfg->port_range;
+    pj_sockaddr_init(af, &bound_addr, NULL, 0);
+    if (cfg->bound_addr.addr.sa_family == pj_AF_INET() || 
+	cfg->bound_addr.addr.sa_family == pj_AF_INET6())
+    {
+	pj_sockaddr_cp(&bound_addr, &cfg->bound_addr);
+    }
+    status = pj_sock_bind_random(stun_sock->sock_fd, &bound_addr,
+				 cfg->port_range, max_bind_retry);
     if (status != PJ_SUCCESS)
 	goto on_error;
Index: pjproject/trunk/pjnath/src/pjnath/turn_sock.c
===================================================================
--- pjproject/trunk/pjnath/src/pjnath/turn_sock.c	(revision 4342)
+++ pjproject/trunk/pjnath/src/pjnath/turn_sock.c	(revision 4343)
@@ -33,4 +33,8 @@
 };
 
+
+enum { MAX_BIND_RETRY = 100 };
+
+
 #define INIT	0x1FFFFFFF
 
@@ -103,4 +107,5 @@
 }
 
+
 /*
  * Create.
@@ -726,4 +731,6 @@
 	pj_sock_t sock;
 	pj_activesock_cb asock_cb;
+	pj_sockaddr bound_addr, *cfg_bind_addr;
+	pj_uint16_t max_bind_retry;
 
 	/* Close existing connection, if any. This happens when
@@ -751,5 +758,27 @@
 	}
 
-        /* Apply QoS, if specified */
+	/* Bind socket */
+	cfg_bind_addr = &turn_sock->setting.bound_addr;
+	max_bind_retry = MAX_BIND_RETRY;
+	if (turn_sock->setting.port_range &&
+	    turn_sock->setting.port_range < max_bind_retry)
+	{
+	    max_bind_retry = turn_sock->setting.port_range;
+	}
+	pj_sockaddr_init(turn_sock->af, &bound_addr, NULL, 0);
+	if (cfg_bind_addr->addr.sa_family == pj_AF_INET() || 
+	    cfg_bind_addr->addr.sa_family == pj_AF_INET6())
+	{
+	    pj_sockaddr_cp(&bound_addr, cfg_bind_addr);
+	}
+	status = pj_sock_bind_random(sock, &bound_addr,
+				     turn_sock->setting.port_range,
+				     max_bind_retry);
+	if (status != PJ_SUCCESS) {
+	    pj_turn_sock_destroy(turn_sock);
+	    return;
+	}
+
+	/* Apply QoS, if specified */
 	status = pj_sock_apply_qos2(sock, turn_sock->setting.qos_type,
 				    &turn_sock->setting.qos_params, 
Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 4342)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 4343)
@@ -2154,4 +2154,13 @@
 
     /**
+     * Specify the port range for socket binding, relative to the start
+     * port number specified in \a port. Note that this setting is only
+     * applicable when the start port number is non zero.
+     *
+     * Default value is zero.
+     */
+    unsigned		port_range;
+
+    /**
      * Optional address to advertise as the address of this transport.
      * Application can specify any address or hostname for this field,
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 4342)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 4343)
@@ -719,4 +719,11 @@
 	ice_cfg.stun.max_host_cands = acc_cfg->ice_cfg.ice_max_host_cands;
 
+    /* Copy binding port setting to STUN setting */
+    pj_sockaddr_init(ice_cfg.af, &ice_cfg.stun.cfg.bound_addr,
+		     &cfg->bound_addr, cfg->port);
+    ice_cfg.stun.cfg.port_range = cfg->port_range;
+    if (cfg->port != 0 && ice_cfg.stun.cfg.port_range == 0)
+	ice_cfg.stun.cfg.port_range = pjsua_var.ua_cfg.max_calls * 10;
+
     /* Copy QoS setting to STUN setting */
     ice_cfg.stun.cfg.qos_type = cfg->qos_type;
@@ -744,4 +751,11 @@
 	pj_memcpy(&ice_cfg.turn.cfg.qos_params, &cfg->qos_params,
 		  sizeof(cfg->qos_params));
+
+	/* Copy binding port setting to TURN setting */
+	pj_sockaddr_init(ice_cfg.af, &ice_cfg.turn.cfg.bound_addr,
+			 &cfg->bound_addr, cfg->port);
+	ice_cfg.turn.cfg.port_range = cfg->port_range;
+	if (cfg->port != 0 && ice_cfg.turn.cfg.port_range == 0)
+	    ice_cfg.turn.cfg.port_range = pjsua_var.ua_cfg.max_calls * 10;
     }
 
