config_system.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2013, Digium, Inc.
00005  *
00006  * Mark Michelson <mmichelson@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 #include "asterisk.h"
00020 
00021 #include <pjsip.h>
00022 #include <pjlib.h>
00023 
00024 #include "asterisk/res_pjsip.h"
00025 #include "asterisk/sorcery.h"
00026 #include "include/res_pjsip_private.h"
00027 #include "asterisk/threadpool.h"
00028 #include "asterisk/dns.h"
00029 #include "asterisk/res_pjsip_cli.h"
00030 
00031 #define TIMER_T1_MIN 100
00032 #define DEFAULT_TIMER_T1 500
00033 #define DEFAULT_TIMER_B 32000
00034 
00035 struct system_config {
00036    SORCERY_OBJECT(details);
00037    /*! Transaction Timer T1 value */
00038    unsigned int timert1;
00039    /*! Transaction Timer B value */
00040    unsigned int timerb;
00041    /*! Should we use short forms for headers? */
00042    unsigned int compactheaders;
00043    struct {
00044       /*! Initial number of threads in the threadpool */
00045       int initial_size;
00046       /*! The amount by which the number of threads is incremented when necessary */
00047       int auto_increment;
00048       /*! Thread idle timeout in seconds */
00049       int idle_timeout;
00050       /*! Maxumum number of threads in the threadpool */
00051       int max_size;
00052    } threadpool;
00053    /*! Nonzero to disable switching from UDP to TCP transport */
00054    unsigned int disable_tcp_switch;
00055 };
00056 
00057 static struct ast_threadpool_options sip_threadpool_options = {
00058    .version = AST_THREADPOOL_OPTIONS_VERSION,
00059 };
00060 
00061 void sip_get_threadpool_options(struct ast_threadpool_options *threadpool_options)
00062 {
00063    *threadpool_options = sip_threadpool_options;
00064 }
00065 
00066 static struct ast_sorcery *system_sorcery;
00067 
00068 static void *system_alloc(const char *name)
00069 {
00070    struct system_config *system = ast_sorcery_generic_alloc(sizeof(*system), NULL);
00071 
00072    if (!system) {
00073       return NULL;
00074    }
00075 
00076    return system;
00077 }
00078 
00079 static int system_apply(const struct ast_sorcery *system_sorcery, void *obj)
00080 {
00081    struct system_config *system = obj;
00082    int min_timerb;
00083 
00084    if (system->timert1 < TIMER_T1_MIN) {
00085       ast_log(LOG_WARNING, "Timer T1 setting is too low. Setting to %d\n", TIMER_T1_MIN);
00086       system->timert1 = TIMER_T1_MIN;
00087    }
00088 
00089    min_timerb = 64 * system->timert1;
00090 
00091    if (system->timerb < min_timerb) {
00092       ast_log(LOG_WARNING, "Timer B setting is too low. Setting to %d\n", min_timerb);
00093       system->timerb = min_timerb;
00094    }
00095 
00096    pjsip_cfg()->tsx.t1 = system->timert1;
00097    pjsip_cfg()->tsx.td = system->timerb;
00098 
00099    if (system->compactheaders) {
00100       extern pj_bool_t pjsip_use_compact_form;
00101 
00102       pjsip_use_compact_form = PJ_TRUE;
00103    }
00104 
00105    sip_threadpool_options.initial_size = system->threadpool.initial_size;
00106    sip_threadpool_options.auto_increment = system->threadpool.auto_increment;
00107    sip_threadpool_options.idle_timeout = system->threadpool.idle_timeout;
00108    sip_threadpool_options.max_size = system->threadpool.max_size;
00109 
00110    pjsip_cfg()->endpt.disable_tcp_switch =
00111       system->disable_tcp_switch ? PJ_TRUE : PJ_FALSE;
00112 
00113    return 0;
00114 }
00115 
00116 static struct system_config *get_system_cfg(void)
00117 {
00118    struct system_config *cfg;
00119    struct ao2_container *systems;
00120    systems = ast_sorcery_retrieve_by_fields(system_sorcery, "system",
00121       AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
00122 
00123    if (!systems) {
00124       return NULL;
00125    }
00126 
00127    cfg = ao2_find(systems, NULL, 0);
00128    ao2_ref(systems, -1);
00129    return cfg;
00130 }
00131 
00132 int sip_cli_print_system(struct ast_sip_cli_context *context)
00133 {
00134    struct system_config *cfg = get_system_cfg();
00135 
00136    if (!cfg) {
00137       cfg = ast_sorcery_alloc(system_sorcery, "system", NULL);
00138       if (!cfg) {
00139          return -1;
00140       }
00141    }
00142 
00143    ast_str_append(&context->output_buffer, 0, "\nSystem Settings:\n\n");
00144    ast_sip_cli_print_sorcery_objectset(cfg, context, 0);
00145 
00146    ao2_ref(cfg, -1);
00147    return 0;
00148 }
00149 
00150 int ast_sip_initialize_system(void)
00151 {
00152    RAII_VAR(struct ao2_container *, system_configs, NULL, ao2_cleanup);
00153    RAII_VAR(struct system_config *, system, NULL, ao2_cleanup);
00154 
00155    system_sorcery = ast_sorcery_open();
00156    if (!system_sorcery) {
00157       ast_log(LOG_ERROR, "Failed to open SIP system sorcery\n");
00158       return -1;
00159    }
00160 
00161    ast_sorcery_apply_default(system_sorcery, "system", "config", "pjsip.conf,criteria=type=system");
00162 
00163    if (ast_sorcery_object_register_no_reload(system_sorcery, "system", system_alloc, NULL, system_apply)) {
00164       ast_log(LOG_ERROR, "Failed to register with sorcery (is res_sorcery_config loaded?)\n");
00165       ast_sorcery_unref(system_sorcery);
00166       system_sorcery = NULL;
00167       return -1;
00168    }
00169 
00170    ast_sorcery_object_field_register(system_sorcery, "system", "type", "", OPT_NOOP_T, 0, 0);
00171    ast_sorcery_object_field_register(system_sorcery, "system", "timer_t1", __stringify(DEFAULT_TIMER_T1),
00172          OPT_UINT_T, 0, FLDSET(struct system_config, timert1));
00173    ast_sorcery_object_field_register(system_sorcery, "system", "timer_b", __stringify(DEFAULT_TIMER_B),
00174          OPT_UINT_T, 0, FLDSET(struct system_config, timerb));
00175    ast_sorcery_object_field_register(system_sorcery, "system", "compact_headers", "no",
00176          OPT_BOOL_T, 1, FLDSET(struct system_config, compactheaders));
00177    ast_sorcery_object_field_register(system_sorcery, "system", "threadpool_initial_size", "0",
00178          OPT_UINT_T, 0, FLDSET(struct system_config, threadpool.initial_size));
00179    ast_sorcery_object_field_register(system_sorcery, "system", "threadpool_auto_increment", "5",
00180          OPT_UINT_T, 0, FLDSET(struct system_config, threadpool.auto_increment));
00181    ast_sorcery_object_field_register(system_sorcery, "system", "threadpool_idle_timeout", "60",
00182          OPT_UINT_T, 0, FLDSET(struct system_config, threadpool.idle_timeout));
00183    ast_sorcery_object_field_register(system_sorcery, "system", "threadpool_max_size", "0",
00184          OPT_UINT_T, 0, FLDSET(struct system_config, threadpool.max_size));
00185    ast_sorcery_object_field_register(system_sorcery, "system", "disable_tcp_switch", "yes",
00186          OPT_BOOL_T, 1, FLDSET(struct system_config, disable_tcp_switch));
00187 
00188    ast_sorcery_load(system_sorcery);
00189 
00190    system_configs = ast_sorcery_retrieve_by_fields(system_sorcery, "system",
00191       AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
00192 
00193    if (ao2_container_count(system_configs)) {
00194       return 0;
00195    }
00196 
00197    /* No config present, allocate one and apply defaults */
00198    system = ast_sorcery_alloc(system_sorcery, "system", NULL);
00199    if (!system) {
00200       ast_log(LOG_ERROR, "Unable to allocate default system config.\n");
00201       ast_sorcery_unref(system_sorcery);
00202       return -1;
00203    }
00204 
00205    if (system_apply(system_sorcery, system)) {
00206       ast_log(LOG_ERROR, "Failed to apply default system config.\n");
00207       ast_sorcery_unref(system_sorcery);
00208       return -1;
00209    }
00210 
00211    return 0;
00212 }
00213 
00214 void ast_sip_destroy_system(void)
00215 {
00216    ast_sorcery_unref(system_sorcery);
00217 }
00218 
00219 static int system_create_resolver_and_set_nameservers(void *data)
00220 {
00221    struct ao2_container *discovered_nameservers;
00222    struct ao2_iterator it_nameservers;
00223    char *nameserver;
00224    pj_status_t status;
00225    pj_dns_resolver *resolver;
00226    pj_str_t nameservers[PJ_DNS_RESOLVER_MAX_NS];
00227    unsigned int count = 0;
00228 
00229    discovered_nameservers = ast_dns_get_nameservers();
00230    if (!discovered_nameservers) {
00231       ast_log(LOG_ERROR, "Could not retrieve local system nameservers, resorting to system resolution\n");
00232       return 0;
00233    }
00234 
00235    if (!ao2_container_count(discovered_nameservers)) {
00236       ast_log(LOG_ERROR, "There are no local system nameservers configured, resorting to system resolution\n");
00237       ao2_ref(discovered_nameservers, -1);
00238       return -1;
00239    }
00240 
00241    if (!(resolver = pjsip_endpt_get_resolver(ast_sip_get_pjsip_endpoint()))) {
00242       status = pjsip_endpt_create_resolver(ast_sip_get_pjsip_endpoint(), &resolver);
00243       if (status != PJ_SUCCESS) {
00244          ast_log(LOG_ERROR, "Could not create DNS resolver(%d), resorting to system resolution\n", status);
00245          ao2_ref(discovered_nameservers, -1);
00246          return 0;
00247       }
00248    }
00249 
00250    it_nameservers = ao2_iterator_init(discovered_nameservers, 0);
00251    while ((nameserver = ao2_iterator_next(&it_nameservers))) {
00252       pj_strset2(&nameservers[count++], nameserver);
00253       ao2_ref(nameserver, -1);
00254 
00255       if (count == (PJ_DNS_RESOLVER_MAX_NS - 1)) {
00256          break;
00257       }
00258    }
00259    ao2_iterator_destroy(&it_nameservers);
00260 
00261    status = pj_dns_resolver_set_ns(resolver, count, nameservers, NULL);
00262 
00263    /* Since we no longer need the nameservers we can drop the list of them */
00264    ao2_ref(discovered_nameservers, -1);
00265 
00266    if (status != PJ_SUCCESS) {
00267       ast_log(LOG_ERROR, "Could not set nameservers on DNS resolver in PJSIP(%d), resorting to system resolution\n",
00268          status);
00269       return 0;
00270    }
00271 
00272    if (!pjsip_endpt_get_resolver(ast_sip_get_pjsip_endpoint())) {
00273       status = pjsip_endpt_set_resolver(ast_sip_get_pjsip_endpoint(), resolver);
00274       if (status != PJ_SUCCESS) {
00275          ast_log(LOG_ERROR, "Could not set DNS resolver in PJSIP(%d), resorting to system resolution\n", status);
00276          return 0;
00277       }
00278    }
00279 
00280    return 0;
00281 }
00282 
00283 void ast_sip_initialize_dns(void)
00284 {
00285    ast_sip_push_task_synchronous(NULL, system_create_resolver_and_set_nameservers, NULL);
00286 }

Generated on Thu Apr 16 06:27:31 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6