summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2013-02-07 09:35:34 +0000
committerNanang Izzuddin <nanang@teluu.com>2013-02-07 09:35:34 +0000
commitcdb0f86fac81b206ee8e260d2b344e36cb3ac0aa (patch)
treea9d4aa8d94fc7e0ccfce07ff99d4e078008bb14d
parent7b7c7c8b42a8c25b30b07a8cd524cccbb60173b3 (diff)
Close #1602: configurable local port range for ICE transport.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4343 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjlib/include/pj/sock.h18
-rw-r--r--pjlib/src/pj/sock_common.c39
-rw-r--r--pjnath/include/pjnath/stun_sock.h12
-rw-r--r--pjnath/include/pjnath/turn_sock.h17
-rw-r--r--pjnath/src/pjnath/stun_sock.c24
-rw-r--r--pjnath/src/pjnath/turn_sock.c31
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h9
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c14
8 files changed, 152 insertions, 12 deletions
diff --git a/pjlib/include/pj/sock.h b/pjlib/include/pj/sock.h
index 83d35db9..4011f21a 100644
--- a/pjlib/include/pj/sock.h
+++ b/pjlib/include/pj/sock.h
@@ -1166,6 +1166,24 @@ PJ_DECL(pj_status_t) pj_sock_bind_in( pj_sock_t sockfd,
pj_uint32_t addr,
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
/**
* Listen for incoming connection. This function only applies to connection
diff --git a/pjlib/src/pj/sock_common.c b/pjlib/src/pj/sock_common.c
index 7aaf6689..eb338e73 100644
--- a/pjlib/src/pj/sock_common.c
+++ b/pjlib/src/pj/sock_common.c
@@ -24,6 +24,7 @@
#include <pj/ip_helper.h>
#include <pj/os.h>
#include <pj/addr_resolv.h>
+#include <pj/rand.h>
#include <pj/string.h>
#include <pj/compat/socket.h>
@@ -1040,6 +1041,44 @@ PJ_DEF(pj_status_t) pj_getdefaultipinterface(int af, pj_sockaddr *addr)
}
+/*
+ * 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)
diff --git a/pjnath/include/pjnath/stun_sock.h b/pjnath/include/pjnath/stun_sock.h
index db7d1d04..f9e9be2e 100644
--- a/pjnath/include/pjnath/stun_sock.h
+++ b/pjnath/include/pjnath/stun_sock.h
@@ -238,11 +238,21 @@ typedef struct pj_stun_sock_cfg
* address is zero, socket will be bound to INADDR_ANY. If the address
* 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;
+
+ /**
* Specify the STUN keep-alive duration, in seconds. The STUN transport
* does keep-alive by sending STUN Binding request to the STUN server.
* If this value is zero, the PJ_STUN_KEEP_ALIVE_SEC value will be used.
diff --git a/pjnath/include/pjnath/turn_sock.h b/pjnath/include/pjnath/turn_sock.h
index c1250856..f756a3b8 100644
--- a/pjnath/include/pjnath/turn_sock.h
+++ b/pjnath/include/pjnath/turn_sock.h
@@ -141,6 +141,23 @@ typedef struct pj_turn_sock_cfg
*/
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;
diff --git a/pjnath/src/pjnath/stun_sock.c b/pjnath/src/pjnath/stun_sock.c
index 7f6aacd8..725c4c8f 100644
--- a/pjnath/src/pjnath/stun_sock.c
+++ b/pjnath/src/pjnath/stun_sock.c
@@ -32,6 +32,8 @@
#include <pj/rand.h>
+enum { MAX_BIND_RETRY = 100 };
+
struct pj_stun_sock
{
char *obj_name; /* Log identification */
@@ -162,7 +164,9 @@ PJ_DEF(pj_status_t) pj_stun_sock_create( pj_stun_config *stun_cfg,
pj_pool_t *pool;
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;
PJ_ASSERT_RETURN(stun_cfg && cb && p_stun_sock, PJ_EINVAL);
@@ -211,17 +215,17 @@ PJ_DEF(pj_status_t) pj_stun_sock_create( pj_stun_config *stun_cfg,
goto on_error;
/* 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;
diff --git a/pjnath/src/pjnath/turn_sock.c b/pjnath/src/pjnath/turn_sock.c
index 919c0839..08831a4c 100644
--- a/pjnath/src/pjnath/turn_sock.c
+++ b/pjnath/src/pjnath/turn_sock.c
@@ -32,6 +32,10 @@ enum
TIMER_DESTROY
};
+
+enum { MAX_BIND_RETRY = 100 };
+
+
#define INIT 0x1FFFFFFF
struct pj_turn_sock
@@ -102,6 +106,7 @@ PJ_DEF(void) pj_turn_sock_cfg_default(pj_turn_sock_cfg *cfg)
cfg->qos_ignore_error = PJ_TRUE;
}
+
/*
* Create.
*/
@@ -725,6 +730,8 @@ static void turn_on_state(pj_turn_session *sess,
int sock_type;
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
* we're switching to alternate TURN server when either TCP
@@ -750,7 +757,29 @@ static void turn_on_state(pj_turn_session *sess,
return;
}
- /* 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,
(turn_sock->setting.qos_ignore_error?2:1),
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index 5114189d..e3d9dd31 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -2153,6 +2153,15 @@ typedef struct pjsua_transport_config
unsigned port;
/**
+ * 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,
* for example it can point to one of the interface address in the
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c
index f891201a..26a6cb70 100644
--- a/pjsip/src/pjsua-lib/pjsua_media.c
+++ b/pjsip/src/pjsua-lib/pjsua_media.c
@@ -718,6 +718,13 @@ static pj_status_t create_ice_media_transport(
if (acc_cfg->ice_cfg.ice_max_host_cands >= 0)
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;
pj_memcpy(&ice_cfg.stun.cfg.qos_params, &cfg->qos_params,
@@ -743,6 +750,13 @@ static pj_status_t create_ice_media_transport(
ice_cfg.turn.cfg.qos_type = cfg->qos_type;
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;
}
/* Configure packet size for STUN and TURN sockets */