diff options
author | Nanang Izzuddin <nanang@teluu.com> | 2013-02-07 09:35:34 +0000 |
---|---|---|
committer | Nanang Izzuddin <nanang@teluu.com> | 2013-02-07 09:35:34 +0000 |
commit | cdb0f86fac81b206ee8e260d2b344e36cb3ac0aa (patch) | |
tree | a9d4aa8d94fc7e0ccfce07ff99d4e078008bb14d | |
parent | 7b7c7c8b42a8c25b30b07a8cd524cccbb60173b3 (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.h | 18 | ||||
-rw-r--r-- | pjlib/src/pj/sock_common.c | 39 | ||||
-rw-r--r-- | pjnath/include/pjnath/stun_sock.h | 12 | ||||
-rw-r--r-- | pjnath/include/pjnath/turn_sock.h | 17 | ||||
-rw-r--r-- | pjnath/src/pjnath/stun_sock.c | 24 | ||||
-rw-r--r-- | pjnath/src/pjnath/turn_sock.c | 31 | ||||
-rw-r--r-- | pjsip/include/pjsua-lib/pjsua.h | 9 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_media.c | 14 |
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 */ |