diff --git a/res/res_pjsip.c b/res/res_pjsip.c index 81816a5fa06513b361e51f4508ecc2cd9d4b1e06..be40c42622048730cd90faaeb9c26de3ed293bc5 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -935,6 +935,19 @@ <configOption name="compactheaders" default="no"> <synopsis>Use the short forms of common SIP header names.</synopsis> </configOption> + <configOption name="threadpool_initial_size" default="0"> + <synopsis>Initial number of threads in the res_pjsip threadpool.</synopsis> + </configOption> + <configOption name="threadpool_auto_increment" default="5"> + <synopsis>The amount by which the number of threads is incremented when necessary.</synopsis> + </configOption> + <configOption name="threadpool_idle_timeout" default="60"> + <synopsis>Number of seconds before an idle thread should be disposed of.</synopsis> + </configOption> + <configOption name="threadpool_max_size" default="0"> + <synopsis>Maximum number of threads in the res_pjsip threadpool. + A value of 0 indicates no maximum.</synopsis> + </configOption> </configObject> <configObject name="global"> <synopsis>Options that apply globally to all SIP communications</synopsis> @@ -1760,26 +1773,12 @@ static void remove_request_headers(pjsip_endpoint *endpt) static int load_module(void) { - /* The third parameter is just copied from - * example code from PJLIB. This can be adjusted - * if necessary. + /* The third parameter is just copied from + * example code from PJLIB. This can be adjusted + * if necessary. */ pj_status_t status; - - /* XXX For the time being, create hard-coded threadpool - * options. Just bump up by five threads every time we - * don't have any available threads. Idle threads time - * out after a minute. No maximum size - */ - struct ast_threadpool_options options = { - .version = AST_THREADPOOL_OPTIONS_VERSION, - .auto_increment = 5, - .max_size = 0, - .idle_timeout = 60, - .initial_size = 0, - .thread_start = sip_thread_start, - }; - sip_threadpool = ast_threadpool_create("SIP", NULL, &options); + struct ast_threadpool_options options; if (pj_init() != PJ_SUCCESS) { return AST_MODULE_LOAD_DECLINE; @@ -1812,6 +1811,14 @@ static int load_module(void) goto error; } + sip_get_threadpool_options(&options); + options.thread_start = sip_thread_start; + sip_threadpool = ast_threadpool_create("SIP", NULL, &options); + if (!sip_threadpool) { + ast_log(LOG_ERROR, "Failed to create SIP threadpool. Aborting load\n"); + goto error; + } + pjsip_tsx_layer_init_module(ast_pjsip_endpoint); pjsip_ua_init_module(ast_pjsip_endpoint, NULL); diff --git a/res/res_pjsip/config_system.c b/res/res_pjsip/config_system.c index b1f13898bf62c134089450ca5b94c2d28f2965d6..f499e8a233a53046953e4f2e068e297c1770c7ca 100644 --- a/res/res_pjsip/config_system.c +++ b/res/res_pjsip/config_system.c @@ -24,6 +24,7 @@ #include "asterisk/res_pjsip.h" #include "asterisk/sorcery.h" #include "include/res_pjsip_private.h" +#include "asterisk/threadpool.h" #define TIMER_T1_MIN 100 #define DEFAULT_TIMER_T1 500 @@ -37,8 +38,27 @@ struct system_config { unsigned int timerb; /*! Should we use short forms for headers? */ unsigned int compactheaders; + struct { + /*! Initial number of threads in the threadpool */ + int initial_size; + /*! The amount by which the number of threads is incremented when necessary */ + int auto_increment; + /*! Thread idle timeout in seconds */ + int idle_timeout; + /*! Maxumum number of threads in the threadpool */ + int max_size; + } threadpool; }; +static struct ast_threadpool_options sip_threadpool_options = { + .version = AST_THREADPOOL_OPTIONS_VERSION, +}; + +void sip_get_threadpool_options(struct ast_threadpool_options *threadpool_options) +{ + *threadpool_options = sip_threadpool_options; +} + static struct ast_sorcery *system_sorcery; static void *system_alloc(const char *name) @@ -77,11 +97,19 @@ static int system_apply(const struct ast_sorcery *system_sorcery, void *obj) pjsip_use_compact_form = PJ_TRUE; } + sip_threadpool_options.initial_size = system->threadpool.initial_size; + sip_threadpool_options.auto_increment = system->threadpool.auto_increment; + sip_threadpool_options.idle_timeout = system->threadpool.idle_timeout; + sip_threadpool_options.max_size = system->threadpool.max_size; + return 0; } int ast_sip_initialize_system(void) { + RAII_VAR(struct ao2_container *, system_configs, NULL, ao2_cleanup); + RAII_VAR(struct system_config *, system, NULL, ao2_cleanup); + system_sorcery = ast_sorcery_open(); if (!system_sorcery) { ast_log(LOG_ERROR, "Failed to open SIP system sorcery\n"); @@ -105,8 +133,35 @@ int ast_sip_initialize_system(void) OPT_UINT_T, 0, FLDSET(struct system_config, timerb)); ast_sorcery_object_field_register(system_sorcery, "system", "compactheaders", "no", OPT_BOOL_T, 1, FLDSET(struct system_config, compactheaders)); + ast_sorcery_object_field_register(system_sorcery, "system", "threadpool_initial_size", "0", + OPT_UINT_T, 0, FLDSET(struct system_config, threadpool.initial_size)); + ast_sorcery_object_field_register(system_sorcery, "system", "threadpool_auto_increment", "5", + OPT_UINT_T, 0, FLDSET(struct system_config, threadpool.auto_increment)); + ast_sorcery_object_field_register(system_sorcery, "system", "threadpool_idle_timeout", "60", + OPT_UINT_T, 0, FLDSET(struct system_config, threadpool.idle_timeout)); + ast_sorcery_object_field_register(system_sorcery, "system", "threadpool_max_size", "0", + OPT_UINT_T, 0, FLDSET(struct system_config, threadpool.max_size)); ast_sorcery_load(system_sorcery); + system_configs = ast_sorcery_retrieve_by_fields(system_sorcery, "system", + AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); + + if (ao2_container_count(system_configs)) { + return 0; + } + + /* No config present, allocate one and apply defaults */ + system = ast_sorcery_alloc(system_sorcery, "system", NULL); + if (!system) { + ast_log(LOG_ERROR, "Unable to allocate default system config.\n"); + return -1; + } + + if (system_apply(system_sorcery, system)) { + ast_log(LOG_ERROR, "Failed to apply default system config.\n"); + return -1; + } + return 0; } diff --git a/res/res_pjsip/include/res_pjsip_private.h b/res/res_pjsip/include/res_pjsip_private.h index 6011b25bf5bde2fa5e79f9c5a3ccca0d1dd5e711..2b7a82b3fe13d13bded36fd4c8721733c17247ff 100644 --- a/res/res_pjsip/include/res_pjsip_private.h +++ b/res/res_pjsip/include/res_pjsip_private.h @@ -76,4 +76,9 @@ int ast_sip_initialize_global(void); */ void ast_res_pjsip_cleanup_options_handling(void); +/*! + * \brief Get threadpool options + */ +void sip_get_threadpool_options(struct ast_threadpool_options *threadpool_options); + #endif /* RES_PJSIP_PRIVATE_H_ */