summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRiza Sulistyo <riza@teluu.com>2014-06-19 05:07:12 +0000
committerRiza Sulistyo <riza@teluu.com>2014-06-19 05:07:12 +0000
commit727da5e28aa110f7931b696f1b1ba74e805bb9b4 (patch)
treef512a06809c4607bc07cd0c877f549a1ba09e580
parent97ebde15f373555da8309c7ebe657a2492b818b6 (diff)
Re #1771: Implement run-time configuration to set specific socket option.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4860 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjlib/include/pj/sock.h37
-rw-r--r--pjlib/include/pj/ssl_sock.h16
-rw-r--r--pjlib/src/pj/sock_bsd.c44
-rw-r--r--pjlib/src/pj/sock_linux_kernel.c30
-rw-r--r--pjlib/src/pj/ssl_sock_common.c2
-rw-r--r--pjlib/src/pj/ssl_sock_ossl.c27
-rw-r--r--pjsip/include/pjsip/sip_transport_tcp.h8
-rw-r--r--pjsip/include/pjsip/sip_transport_tls.h18
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h8
-rw-r--r--pjsip/src/pjsip/sip_transport_tcp.c16
-rw-r--r--pjsip/src/pjsip/sip_transport_tls.c14
-rw-r--r--pjsip/src/pjsua-lib/pjsua_core.c8
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c8
13 files changed, 235 insertions, 1 deletions
diff --git a/pjlib/include/pj/sock.h b/pjlib/include/pj/sock.h
index b7d1cb05..44d0fecd 100644
--- a/pjlib/include/pj/sock.h
+++ b/pjlib/include/pj/sock.h
@@ -616,6 +616,32 @@ typedef struct pj_ip_mreq {
pj_in_addr imr_interface; /**< local IP address of interface. */
} pj_ip_mreq;
+/* Maximum number of socket options. */
+#define PJ_MAX_SOCKOPT_PARAMS 4
+
+/**
+ * Options to be set for the socket.
+ */
+typedef struct pj_sockopt_params
+{
+ /* The number of options to be applied. */
+ unsigned cnt;
+
+ /* Array of options to be applied. */
+ struct {
+ /* The level at which the option is defined. */
+ int level;
+
+ /* Option name. */
+ int optname;
+
+ /* Pointer to the buffer in which the option is specified. */
+ void *optval;
+
+ /* Buffer size of the buffer pointed by optval. */
+ int optlen;
+ } options[PJ_MAX_SOCKOPT_PARAMS];
+} pj_sockopt_params;
/*****************************************************************************
*
@@ -1305,6 +1331,17 @@ PJ_DECL(pj_status_t) pj_sock_setsockopt( pj_sock_t sockfd,
const void *optval,
int optlen);
+/**
+ * Set socket options associated with a socket. This method will apply all the
+ * options specified, and ignore any errors that might be raised.
+ *
+ * @param sockfd The socket descriptor.
+ * @param params The socket options.
+ *
+ * @return PJ_SUCCESS or the last error code.
+ */
+PJ_DECL(pj_status_t) pj_sock_setsockopt_params( pj_sock_t sockfd,
+ const pj_sockopt_params *params);
/**
* Helper function to set socket buffer size using #pj_sock_setsockopt()
diff --git a/pjlib/include/pj/ssl_sock.h b/pjlib/include/pj/ssl_sock.h
index 0d24a494..23843717 100644
--- a/pjlib/include/pj/ssl_sock.h
+++ b/pjlib/include/pj/ssl_sock.h
@@ -749,6 +749,22 @@ typedef struct pj_ssl_sock_param
*/
pj_bool_t qos_ignore_error;
+ /**
+ * Specify options to be set on the transport.
+ *
+ * By default there is no options.
+ *
+ */
+ pj_sockopt_params sockopt_params;
+
+ /**
+ * Specify if the transport should ignore any errors when setting the
+ * sockopt parameters.
+ *
+ * Default: PJ_TRUE
+ *
+ */
+ pj_bool_t sockopt_ignore_error;
} pj_ssl_sock_param;
diff --git a/pjlib/src/pj/sock_bsd.c b/pjlib/src/pj/sock_bsd.c
index 107f5247..1688668b 100644
--- a/pjlib/src/pj/sock_bsd.c
+++ b/pjlib/src/pj/sock_bsd.c
@@ -26,6 +26,8 @@
#include <pj/errno.h>
#include <pj/unicode.h>
+#define THIS_FILE "sock_bsd.c"
+
/*
* Address families conversion.
* The values here are indexed based on pj_addr_family.
@@ -765,14 +767,54 @@ PJ_DEF(pj_status_t) pj_sock_setsockopt( pj_sock_t sock,
const void *optval,
int optlen)
{
+ int status;
PJ_CHECK_STACK();
- if (setsockopt(sock, level, optname, (const char*)optval, optlen) != 0)
+
+#if (defined(PJ_WIN32) && PJ_WIN32) || (defined(PJ_SUNOS) && PJ_SUNOS)
+ /* Some opt may still need int value (e.g:SO_EXCLUSIVEADDRUSE in win32). */
+ status = setsockopt(sock,
+ level,
+ ((optname&0xff00)==0xff00)?(int)optname|0xffff0000:optname,
+ (const char*)optval, optlen);
+#else
+ status = setsockopt(sock, level, optname, (const char*)optval, optlen);
+#endif
+
+ if (status != 0)
return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
else
return PJ_SUCCESS;
}
/*
+ * Set socket option.
+ */
+PJ_DEF(pj_status_t) pj_sock_setsockopt_params( pj_sock_t sockfd,
+ const pj_sockopt_params *params)
+{
+ unsigned int i = 0;
+ pj_status_t retval = PJ_SUCCESS;
+ PJ_CHECK_STACK();
+ PJ_ASSERT_RETURN(params, PJ_EINVAL);
+
+ for (;i<params->cnt && i<PJ_MAX_SOCKOPT_PARAMS;++i) {
+ pj_status_t status = pj_sock_setsockopt(sockfd,
+ (pj_uint16_t)params->options[i].level,
+ (pj_uint16_t)params->options[i].optname,
+ params->options[i].optval,
+ params->options[i].optlen);
+ if (status != PJ_SUCCESS) {
+ retval = status;
+ PJ_PERROR(4,(THIS_FILE, status,
+ "Warning: error applying sock opt %d",
+ params->options[i].optname));
+ }
+ }
+
+ return retval;
+}
+
+/*
* Connect socket.
*/
PJ_DEF(pj_status_t) pj_sock_connect( pj_sock_t sock,
diff --git a/pjlib/src/pj/sock_linux_kernel.c b/pjlib/src/pj/sock_linux_kernel.c
index 89c2f0e0..899b486e 100644
--- a/pjlib/src/pj/sock_linux_kernel.c
+++ b/pjlib/src/pj/sock_linux_kernel.c
@@ -36,6 +36,8 @@
#include <asm/ioctls.h> /* FIONBIO */
#include <linux/utsname.h> /* for pj_gethostname() */
+#define THIS_FILE "sock_linux_kernel.c"
+
/*
* Address families conversion.
* The values here are indexed based on pj_addr_family-0xFF00.
@@ -626,6 +628,34 @@ PJ_DEF(pj_status_t) pj_sock_setsockopt( pj_sock_t sockfd,
}
/*
+ * Set socket option.
+ */
+PJ_DEF(pj_status_t) pj_sock_setsockopt_params( pj_sock_t sockfd,
+ const pj_sockopt_params *params)
+{
+ unsigned int i = 0;
+ pj_status_t retval = PJ_SUCCESS;
+ PJ_CHECK_STACK();
+ PJ_ASSERT_RETURN(params, PJ_EINVAL);
+
+ for (;i<params->cnt && i<PJ_MAX_SOCKOPT_PARAMS;++i) {
+ pj_status_t status = pj_sock_setsockopt(sockfd,
+ params->options[i].level,
+ params->options[i].optname,
+ params->options[i].optval,
+ params->options[i].optlen);
+ if (status != PJ_SUCCESS) {
+ retval = status;
+ PJ_PERROR(4,(THIS_FILE, status,
+ "Warning: error applying sock opt %d",
+ params->options[i].optname));
+ }
+ }
+
+ return retval;
+}
+
+/*
* Shutdown socket.
*/
#if PJ_HAS_TCP
diff --git a/pjlib/src/pj/ssl_sock_common.c b/pjlib/src/pj/ssl_sock_common.c
index 67a8d63c..60248372 100644
--- a/pjlib/src/pj/ssl_sock_common.c
+++ b/pjlib/src/pj/ssl_sock_common.c
@@ -41,6 +41,8 @@ PJ_DEF(void) pj_ssl_sock_param_default(pj_ssl_sock_param *param)
param->qos_type = PJ_QOS_TYPE_BEST_EFFORT;
param->qos_ignore_error = PJ_TRUE;
+ param->sockopt_ignore_error = PJ_TRUE;
+
/* Security config */
param->proto = PJ_SSL_SOCK_PROTO_DEFAULT;
}
diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c
index 7c7b6d00..3aa85b0d 100644
--- a/pjlib/src/pj/ssl_sock_ossl.c
+++ b/pjlib/src/pj/ssl_sock_ossl.c
@@ -1650,6 +1650,14 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
if (status != PJ_SUCCESS && !ssock->param.qos_ignore_error)
goto on_return;
+ /* Apply socket options, if specified */
+ if (ssock->param.sockopt_params.cnt) {
+ status = pj_sock_setsockopt_params(ssock->sock,
+ &ssock->param.sockopt_params);
+ if (status != PJ_SUCCESS && !ssock->param.sockopt_ignore_error)
+ goto on_return;
+ }
+
/* Update local address */
ssock->addr_len = src_addr_len;
status = pj_sock_getsockname(ssock->sock, &ssock->local_addr,
@@ -2452,9 +2460,19 @@ PJ_DEF(pj_status_t) pj_ssl_sock_start_accept (pj_ssl_sock_t *ssock,
status = pj_sock_apply_qos2(ssock->sock, ssock->param.qos_type,
&ssock->param.qos_params, 2,
ssock->pool->obj_name, NULL);
+
if (status != PJ_SUCCESS && !ssock->param.qos_ignore_error)
goto on_error;
+ /* Apply socket options, if specified */
+ if (ssock->param.sockopt_params.cnt) {
+ status = pj_sock_setsockopt_params(ssock->sock,
+ &ssock->param.sockopt_params);
+
+ if (status != PJ_SUCCESS && !ssock->param.sockopt_ignore_error)
+ goto on_error;
+ }
+
/* Bind socket */
status = pj_sock_bind(ssock->sock, localaddr, addr_len);
if (status != PJ_SUCCESS)
@@ -2537,6 +2555,15 @@ PJ_DECL(pj_status_t) pj_ssl_sock_start_connect(pj_ssl_sock_t *ssock,
if (status != PJ_SUCCESS && !ssock->param.qos_ignore_error)
goto on_error;
+ /* Apply socket options, if specified */
+ if (ssock->param.sockopt_params.cnt) {
+ status = pj_sock_setsockopt_params(ssock->sock,
+ &ssock->param.sockopt_params);
+
+ if (status != PJ_SUCCESS && !ssock->param.sockopt_ignore_error)
+ goto on_error;
+ }
+
/* Bind socket */
status = pj_sock_bind(ssock->sock, localaddr, addr_len);
if (status != PJ_SUCCESS)
diff --git a/pjsip/include/pjsip/sip_transport_tcp.h b/pjsip/include/pjsip/sip_transport_tcp.h
index 28169fcc..a97f845f 100644
--- a/pjsip/include/pjsip/sip_transport_tcp.h
+++ b/pjsip/include/pjsip/sip_transport_tcp.h
@@ -104,6 +104,14 @@ typedef struct pjsip_tcp_transport_cfg
*/
pj_qos_params qos_params;
+ /**
+ * Specify options to be set on the transport.
+ *
+ * By default there is no options.
+ *
+ */
+ pj_sockopt_params sockopt_params;
+
} pjsip_tcp_transport_cfg;
diff --git a/pjsip/include/pjsip/sip_transport_tls.h b/pjsip/include/pjsip/sip_transport_tls.h
index 00d8fe76..b6deafc7 100644
--- a/pjsip/include/pjsip/sip_transport_tls.h
+++ b/pjsip/include/pjsip/sip_transport_tls.h
@@ -205,6 +205,23 @@ typedef struct pjsip_tls_setting
*/
pj_bool_t qos_ignore_error;
+ /**
+ * Specify options to be set on the transport.
+ *
+ * By default there is no options.
+ *
+ */
+ pj_sockopt_params sockopt_params;
+
+ /**
+ * Specify if the transport should ignore any errors when setting the
+ * sockopt parameters.
+ *
+ * Default: PJ_TRUE
+ *
+ */
+ pj_bool_t sockopt_ignore_error;
+
} pjsip_tls_setting;
@@ -234,6 +251,7 @@ PJ_INLINE(void) pjsip_tls_setting_default(pjsip_tls_setting *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;
+ tls_opt->sockopt_ignore_error = PJ_TRUE;
}
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index 895d9bd8..8e0e3156 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -2296,6 +2296,14 @@ typedef struct pjsua_transport_config
*/
pj_qos_params qos_params;
+ /**
+ * Specify options to be set on the transport.
+ *
+ * By default there is no options.
+ *
+ */
+ pj_sockopt_params sockopt_params;
+
} pjsua_transport_config;
diff --git a/pjsip/src/pjsip/sip_transport_tcp.c b/pjsip/src/pjsip/sip_transport_tcp.c
index 6a0eaffb..70ae300e 100644
--- a/pjsip/src/pjsip/sip_transport_tcp.c
+++ b/pjsip/src/pjsip/sip_transport_tcp.c
@@ -60,6 +60,7 @@ struct tcp_listener
pj_sockaddr bound_addr;
pj_qos_type qos_type;
pj_qos_params qos_params;
+ pj_sockopt_params sockopt_params;
};
@@ -284,6 +285,8 @@ PJ_DEF(pj_status_t) pjsip_tcp_transport_start3(
listener->qos_type = cfg->qos_type;
pj_memcpy(&listener->qos_params, &cfg->qos_params,
sizeof(cfg->qos_params));
+ pj_memcpy(&listener->sockopt_params, &cfg->sockopt_params,
+ sizeof(cfg->sockopt_params));
pj_ansi_strcpy(listener->factory.obj_name, "tcplis");
if (listener->factory.type==PJSIP_TRANSPORT_TCP6)
@@ -316,6 +319,10 @@ PJ_DEF(pj_status_t) pjsip_tcp_transport_start3(
}
}
+ /* Apply socket options, if specified */
+ if (cfg->sockopt_params.cnt)
+ status = pj_sock_setsockopt_params(sock, &cfg->sockopt_params);
+
/* Bind address may be different than factory.local_addr because
* factory.local_addr will be resolved below.
*/
@@ -918,6 +925,11 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
2, listener->factory.obj_name,
"outgoing SIP TCP socket");
+ /* Apply socket options, if specified */
+ if (listener->sockopt_params.cnt)
+ status = pj_sock_setsockopt_params(sock, &listener->sockopt_params);
+
+
/* Bind to listener's address and any port */
pj_bzero(&local_addr, sizeof(local_addr));
pj_sockaddr_cp(&local_addr, &listener->bound_addr);
@@ -1036,6 +1048,10 @@ static pj_bool_t on_accept_complete(pj_activesock_t *asock,
2, listener->factory.obj_name,
"incoming SIP TCP socket");
+ /* Apply socket options, if specified */
+ if (listener->sockopt_params.cnt)
+ status = pj_sock_setsockopt_params(sock, &listener->sockopt_params);
+
/* tcp_create() expect pj_sockaddr, so copy src_addr to temporary var,
* just in case.
*/
diff --git a/pjsip/src/pjsip/sip_transport_tls.c b/pjsip/src/pjsip/sip_transport_tls.c
index ac7b2840..a86b398c 100644
--- a/pjsip/src/pjsip/sip_transport_tls.c
+++ b/pjsip/src/pjsip/sip_transport_tls.c
@@ -349,6 +349,13 @@ PJ_DEF(pj_status_t) pjsip_tls_transport_start2( pjsip_endpoint *endpt,
pj_memcpy(&ssock_param.qos_params, &listener->tls_setting.qos_params,
sizeof(ssock_param.qos_params));
+ ssock_param.sockopt_ignore_error =
+ listener->tls_setting.sockopt_ignore_error;
+ /* Copy the sockopt */
+ pj_memcpy(&ssock_param.sockopt_params,
+ &listener->tls_setting.sockopt_params,
+ sizeof(listener->tls_setting.sockopt_params));
+
has_listener = PJ_FALSE;
switch(listener->tls_setting.method) {
@@ -953,6 +960,13 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
pj_memcpy(&ssock_param.qos_params, &listener->tls_setting.qos_params,
sizeof(ssock_param.qos_params));
+ ssock_param.sockopt_ignore_error =
+ listener->tls_setting.sockopt_ignore_error;
+ /* Copy the sockopt */
+ pj_memcpy(&ssock_param.sockopt_params,
+ &listener->tls_setting.sockopt_params,
+ sizeof(listener->tls_setting.sockopt_params));
+
switch(listener->tls_setting.method) {
case PJSIP_TLSV1_METHOD:
ssock_param.proto = PJ_SSL_SOCK_PROTO_TLS1;
diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c
index 79c69b3e..f76bc5e7 100644
--- a/pjsip/src/pjsua-lib/pjsua_core.c
+++ b/pjsip/src/pjsua-lib/pjsua_core.c
@@ -1964,6 +1964,10 @@ static pj_status_t create_sip_udp_sock(int af,
&cfg->qos_params,
2, THIS_FILE, "SIP UDP socket");
+ /* Apply sockopt, if specified */
+ if (cfg->sockopt_params.cnt)
+ status = pj_sock_setsockopt_params(sock, &cfg->sockopt_params);
+
/* Bind socket */
status = pj_sock_bind(sock, &bind_addr, pj_sockaddr_get_len(&bind_addr));
if (status != PJ_SUCCESS) {
@@ -2186,6 +2190,10 @@ PJ_DEF(pj_status_t) pjsua_transport_create( pjsip_transport_type_e type,
pj_memcpy(&tcp_cfg.qos_params, &cfg->qos_params,
sizeof(cfg->qos_params));
+ /* Copy the sockopt */
+ pj_memcpy(&tcp_cfg.sockopt_params, &cfg->sockopt_params,
+ sizeof(tcp_cfg.sockopt_params));
+
/* Create the TCP transport */
status = pjsip_tcp_transport_start3(pjsua_var.endpt, &tcp_cfg, &tcp);
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c
index 62de7668..af0799aa 100644
--- a/pjsip/src/pjsua-lib/pjsua_media.c
+++ b/pjsip/src/pjsua-lib/pjsua_media.c
@@ -298,6 +298,10 @@ static pj_status_t create_rtp_rtcp_sock(pjsua_call_media *call_med,
&cfg->qos_params,
2, THIS_FILE, "RTP socket");
+ /* Apply sockopt, if specified */
+ if (cfg->sockopt_params.cnt)
+ status = pj_sock_setsockopt_params(sock[0], &cfg->sockopt_params);
+
/* Bind RTP socket */
pj_sockaddr_set_port(&bound_addr, acc->next_rtp_port);
status=pj_sock_bind(sock[0], &bound_addr,
@@ -321,6 +325,10 @@ static pj_status_t create_rtp_rtcp_sock(pjsua_call_media *call_med,
&cfg->qos_params,
2, THIS_FILE, "RTCP socket");
+ /* Apply sockopt, if specified */
+ if (cfg->sockopt_params.cnt)
+ status = pj_sock_setsockopt_params(sock[1], &cfg->sockopt_params);
+
/* Bind RTCP socket */
pj_sockaddr_set_port(&bound_addr, (pj_uint16_t)(acc->next_rtp_port+1));
status=pj_sock_bind(sock[1], &bound_addr,