diff --git a/pjlib/include/pj/ssl_sock.h b/pjlib/include/pj/ssl_sock.h index 534c9144e..bfad5af2d 100644 --- a/pjlib/include/pj/ssl_sock.h +++ b/pjlib/include/pj/ssl_sock.h @@ -710,6 +710,14 @@ typedef struct pj_ssl_sock_param */ pj_str_t server_name; + /** + * Specify if SO_REUSEADDR should be used for listening socket. This + * option will only be used with accept() operation. + * + * Default is PJ_FALSE. + */ + pj_bool_t reuse_addr; + /** * QoS traffic type to be set on this transport. When application wants * to apply QoS tagging to the transport, it's preferable to set this diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c index b774c6745..b5098d22f 100644 --- a/pjlib/src/pj/ssl_sock_ossl.c +++ b/pjlib/src/pj/ssl_sock_ossl.c @@ -2377,6 +2377,18 @@ PJ_DEF(pj_status_t) pj_ssl_sock_start_accept (pj_ssl_sock_t *ssock, if (status != PJ_SUCCESS) goto on_error; + /* Apply SO_REUSEADDR */ + if (ssock->param.reuse_addr) { + int enabled = 1; + status = pj_sock_setsockopt(ssock->sock, pj_SOL_SOCKET(), + pj_SO_REUSEADDR(), + &enabled, sizeof(enabled)); + if (status != PJ_SUCCESS) { + PJ_PERROR(4,(ssock->pool->obj_name, status, + "Warning: error applying SO_REUSEADDR")); + } + } + /* Apply QoS, if specified */ status = pj_sock_apply_qos2(ssock->sock, ssock->param.qos_type, &ssock->param.qos_params, 2, diff --git a/pjsip/include/pjsip/sip_config.h b/pjsip/include/pjsip/sip_config.h index bc895c590..430dde221 100644 --- a/pjsip/include/pjsip/sip_config.h +++ b/pjsip/include/pjsip/sip_config.h @@ -568,6 +568,24 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void) #endif +/** + * Specify whether TCP listener should use SO_REUSEADDR option. This constant + * will be used as the default value for the "reuse_addr" field in the + * pjsip_tcp_transport_cfg structure. + * + * Default is FALSE on Windows and TRUE on non-Windows. + * + * @see PJSIP_TLS_TRANSPORT_REUSEADDR + */ +#ifndef PJSIP_TCP_TRANSPORT_REUSEADDR +# if defined(PJ_WIN32) && PJ_WIN32 +# define PJSIP_TCP_TRANSPORT_REUSEADDR 0 +# else +# define PJSIP_TCP_TRANSPORT_REUSEADDR 1 +# endif +#endif + + /** * Set the interval to send keep-alive packet for TCP transports. * If the value is zero, keep-alive will be disabled for TCP. @@ -676,6 +694,21 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void) #endif +/** + * Specify whether TLS listener should use SO_REUSEADDR option. + * + * Default is FALSE on Windows and TRUE on non-Windows. + * + * @see PJSIP_TCP_TRANSPORT_REUSEADDR + */ +#ifndef PJSIP_TLS_TRANSPORT_REUSEADDR +# if defined(PJ_WIN32) && PJ_WIN32 +# define PJSIP_TLS_TRANSPORT_REUSEADDR 0 +# else +# define PJSIP_TLS_TRANSPORT_REUSEADDR 1 +# endif +#endif + /* Endpoint. */ #define PJSIP_MAX_TIMER_COUNT (2*pjsip_cfg()->tsx.max_count + \ diff --git a/pjsip/include/pjsip/sip_transport_tcp.h b/pjsip/include/pjsip/sip_transport_tcp.h index fc4940e38..7e7bc1399 100644 --- a/pjsip/include/pjsip/sip_transport_tcp.h +++ b/pjsip/include/pjsip/sip_transport_tcp.h @@ -63,6 +63,12 @@ typedef struct pjsip_tcp_transport_cfg */ pj_sockaddr bind_addr; + /** + * Should SO_REUSEADDR be used for the listener socket. + * Default value is PJSIP_TCP_TRANSPORT_REUSEADDR. + */ + pj_bool_t reuse_addr; + /** * Optional published address, which is the address to be * advertised as the address of this SIP transport. diff --git a/pjsip/include/pjsip/sip_transport_tls.h b/pjsip/include/pjsip/sip_transport_tls.h index 1f8ee431a..00d8fe76d 100644 --- a/pjsip/include/pjsip/sip_transport_tls.h +++ b/pjsip/include/pjsip/sip_transport_tls.h @@ -173,6 +173,12 @@ typedef struct pjsip_tls_setting */ pj_time_val timeout; + /** + * Should SO_REUSEADDR be used for the listener socket. + * Default value is PJSIP_TLS_TRANSPORT_REUSEADDR. + */ + pj_bool_t reuse_addr; + /** * QoS traffic type to be set on this transport. When application wants * to apply QoS tagging to the transport, it's preferable to set this @@ -225,6 +231,7 @@ typedef struct pjsip_tls_state_info PJ_INLINE(void) pjsip_tls_setting_default(pjsip_tls_setting *tls_opt) { pj_memset(tls_opt, 0, sizeof(*tls_opt)); + tls_opt->reuse_addr = PJSIP_TLS_TRANSPORT_REUSEADDR; tls_opt->qos_type = PJ_QOS_TYPE_BEST_EFFORT; tls_opt->qos_ignore_error = PJ_TRUE; } diff --git a/pjsip/src/pjsip/sip_transport_tcp.c b/pjsip/src/pjsip/sip_transport_tcp.c index fa515d281..38bd42ae3 100644 --- a/pjsip/src/pjsip/sip_transport_tcp.c +++ b/pjsip/src/pjsip/sip_transport_tcp.c @@ -217,6 +217,7 @@ PJ_DEF(void) pjsip_tcp_transport_cfg_default(pjsip_tcp_transport_cfg *cfg, cfg->af = af; pj_sockaddr_init(cfg->af, &cfg->bind_addr, NULL, 0); cfg->async_cnt = 1; + cfg->reuse_addr = PJSIP_TCP_TRANSPORT_REUSEADDR; } @@ -298,6 +299,17 @@ PJ_DEF(pj_status_t) pjsip_tcp_transport_start3( 2, listener->factory.obj_name, "SIP TCP listener socket"); + /* Apply SO_REUSEADDR */ + if (cfg->reuse_addr) { + int enabled = 1; + status = pj_sock_setsockopt(sock, pj_SOL_SOCKET(), pj_SO_REUSEADDR(), + &enabled, sizeof(enabled)); + if (status != PJ_SUCCESS) { + PJ_PERROR(4,(listener->factory.obj_name, status, + "Warning: error applying SO_REUSEADDR")); + } + } + /* Bind address may be different than factory.local_addr because * factory.local_addr will be resolved below. */ diff --git a/pjsip/src/pjsip/sip_transport_tls.c b/pjsip/src/pjsip/sip_transport_tls.c index 2e703c6bf..06244e534 100644 --- a/pjsip/src/pjsip/sip_transport_tls.c +++ b/pjsip/src/pjsip/sip_transport_tls.c @@ -337,6 +337,7 @@ PJ_DEF(pj_status_t) pjsip_tls_transport_start2( pjsip_endpoint *endpt, ssock_param.read_buffer_size = PJSIP_MAX_PKT_LEN; ssock_param.ciphers_num = listener->tls_setting.ciphers_num; ssock_param.ciphers = listener->tls_setting.ciphers; + ssock_param.reuse_addr = listener->tls_setting.reuse_addr; ssock_param.qos_type = listener->tls_setting.qos_type; ssock_param.qos_ignore_error = listener->tls_setting.qos_ignore_error; pj_memcpy(&ssock_param.qos_params, &listener->tls_setting.qos_params,