Skip to content

Commit

Permalink
Re #1771: Implement run-time configuration to set specific socket opt…
Browse files Browse the repository at this point in the history
…ion.

git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4860 74dad513-b988-da41-8d7b-12977e46ad98
  • Loading branch information
riza committed Jun 19, 2014
1 parent dc07b70 commit c543e6e
Show file tree
Hide file tree
Showing 13 changed files with 235 additions and 1 deletion.
37 changes: 37 additions & 0 deletions pjlib/include/pj/sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/*****************************************************************************
*
Expand Down Expand Up @@ -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()
Expand Down
16 changes: 16 additions & 0 deletions pjlib/include/pj/ssl_sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
44 changes: 43 additions & 1 deletion pjlib/src/pj/sock_bsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -765,13 +767,53 @@ 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.
*/
Expand Down
30 changes: 30 additions & 0 deletions pjlib/src/pj/sock_linux_kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -625,6 +627,34 @@ PJ_DEF(pj_status_t) pj_sock_setsockopt( pj_sock_t sockfd,
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,
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.
*/
Expand Down
2 changes: 2 additions & 0 deletions pjlib/src/pj/ssl_sock_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
27 changes: 27 additions & 0 deletions pjlib/src/pj/ssl_sock_ossl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions pjsip/include/pjsip/sip_transport_tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand Down
18 changes: 18 additions & 0 deletions pjsip/include/pjsip/sip_transport_tls.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand Down Expand Up @@ -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;
}


Expand Down
8 changes: 8 additions & 0 deletions pjsip/include/pjsua-lib/pjsua.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand Down
16 changes: 16 additions & 0 deletions pjsip/src/pjsip/sip_transport_tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};


Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
*/
Expand Down
14 changes: 14 additions & 0 deletions pjsip/src/pjsip/sip_transport_tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
Loading

0 comments on commit c543e6e

Please sign in to comment.