config_global.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 "include/res_pjsip_private.h"
00026 #include "asterisk/sorcery.h"
00027 #include "asterisk/ast_version.h"
00028 #include "asterisk/res_pjsip_cli.h"
00029 
00030 #define DEFAULT_MAX_FORWARDS 70
00031 #define DEFAULT_KEEPALIVE_INTERVAL 0
00032 #define DEFAULT_USERAGENT_PREFIX "Asterisk PBX"
00033 #define DEFAULT_OUTBOUND_ENDPOINT "default_outbound_endpoint"
00034 #define DEFAULT_DEBUG "no"
00035 #define DEFAULT_ENDPOINT_IDENTIFIER_ORDER "ip,username,anonymous"
00036 
00037 static char default_useragent[256];
00038 
00039 struct global_config {
00040    SORCERY_OBJECT(details);
00041    AST_DECLARE_STRING_FIELDS(
00042       AST_STRING_FIELD(useragent);
00043       AST_STRING_FIELD(default_outbound_endpoint);
00044       /*! Debug logging yes|no|host */
00045       AST_STRING_FIELD(debug);
00046       /*! Order by which endpoint identifiers are checked (comma separated list) */
00047       AST_STRING_FIELD(endpoint_identifier_order);
00048    );
00049    /* Value to put in Max-Forwards header */
00050    unsigned int max_forwards;
00051    /* The interval at which to send keep alive messages to active connection-oriented transports */
00052    unsigned int keep_alive_interval;
00053 };
00054 
00055 static void global_destructor(void *obj)
00056 {
00057    struct global_config *cfg = obj;
00058 
00059    ast_string_field_free_memory(cfg);
00060 }
00061 
00062 static void *global_alloc(const char *name)
00063 {
00064    struct global_config *cfg;
00065 
00066    cfg = ast_sorcery_generic_alloc(sizeof(*cfg), global_destructor);
00067    if (!cfg || ast_string_field_init(cfg, 100)) {
00068       ao2_cleanup(cfg);
00069       return NULL;
00070    }
00071 
00072    return cfg;
00073 }
00074 
00075 static int global_apply(const struct ast_sorcery *sorcery, void *obj)
00076 {
00077    struct global_config *cfg = obj;
00078    char max_forwards[10];
00079 
00080    snprintf(max_forwards, sizeof(max_forwards), "%u", cfg->max_forwards);
00081 
00082    ast_sip_add_global_request_header("Max-Forwards", max_forwards, 1);
00083    ast_sip_add_global_request_header("User-Agent", cfg->useragent, 1);
00084    ast_sip_add_global_response_header("Server", cfg->useragent, 1);
00085    return 0;
00086 }
00087 
00088 static struct global_config *get_global_cfg(void)
00089 {
00090    struct global_config *cfg;
00091    struct ao2_container *globals;
00092 
00093    globals = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "global",
00094       AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
00095    if (!globals) {
00096       return NULL;
00097    }
00098 
00099    cfg = ao2_find(globals, NULL, 0);
00100    ao2_ref(globals, -1);
00101    return cfg;
00102 }
00103 
00104 char *ast_sip_global_default_outbound_endpoint(void)
00105 {
00106    char *str;
00107    struct global_config *cfg;
00108 
00109    cfg = get_global_cfg();
00110    if (!cfg) {
00111       return ast_strdup(DEFAULT_OUTBOUND_ENDPOINT);
00112    }
00113 
00114    str = ast_strdup(cfg->default_outbound_endpoint);
00115    ao2_ref(cfg, -1);
00116    return str;
00117 }
00118 
00119 char *ast_sip_get_debug(void)
00120 {
00121    char *res;
00122    struct global_config *cfg;
00123 
00124    cfg = get_global_cfg();
00125    if (!cfg) {
00126       return ast_strdup(DEFAULT_DEBUG);
00127    }
00128 
00129    res = ast_strdup(cfg->debug);
00130    ao2_ref(cfg, -1);
00131    return res;
00132 }
00133 
00134 char *ast_sip_get_endpoint_identifier_order(void)
00135 {
00136    char *res;
00137    struct global_config *cfg;
00138 
00139    cfg = get_global_cfg();
00140    if (!cfg) {
00141       return ast_strdup(DEFAULT_ENDPOINT_IDENTIFIER_ORDER);
00142    }
00143 
00144    res = ast_strdup(cfg->endpoint_identifier_order);
00145    ao2_ref(cfg, -1);
00146    return res;
00147 }
00148 
00149 unsigned int ast_sip_get_keep_alive_interval(void)
00150 {
00151    unsigned int interval;
00152    struct global_config *cfg;
00153 
00154    cfg = get_global_cfg();
00155    if (!cfg) {
00156       return DEFAULT_KEEPALIVE_INTERVAL;
00157    }
00158 
00159    interval = cfg->keep_alive_interval;
00160    ao2_ref(cfg, -1);
00161    return interval;
00162 }
00163 
00164 /*!
00165  * \internal
00166  * \brief Observer to set default global object if none exist.
00167  *
00168  * \param name Module name owning the sorcery instance.
00169  * \param sorcery Instance being observed.
00170  * \param object_type Name of object being observed.
00171  * \param reloaded Non-zero if the object is being reloaded.
00172  *
00173  * \return Nothing
00174  */
00175 static void global_loaded_observer(const char *name, const struct ast_sorcery *sorcery, const char *object_type, int reloaded)
00176 {
00177    struct ao2_container *globals;
00178    struct global_config *cfg;
00179 
00180    if (strcmp(object_type, "global")) {
00181       /* Not interested */
00182       return;
00183    }
00184 
00185    globals = ast_sorcery_retrieve_by_fields(sorcery, "global",
00186       AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
00187    if (globals) {
00188       int count;
00189 
00190       count = ao2_container_count(globals);
00191       ao2_ref(globals, -1);
00192 
00193       if (1 < count) {
00194          ast_log(LOG_ERROR,
00195             "At most one pjsip.conf type=global object can be defined.  You have %d defined.\n",
00196             count);
00197          return;
00198       }
00199       if (count) {
00200          return;
00201       }
00202    }
00203 
00204    ast_debug(1, "No pjsip.conf type=global object exists so applying defaults.\n");
00205    cfg = ast_sorcery_alloc(sorcery, "global", NULL);
00206    if (!cfg) {
00207       return;
00208    }
00209    global_apply(sorcery, cfg);
00210    ao2_ref(cfg, -1);
00211 }
00212 
00213 static const struct ast_sorcery_instance_observer observer_callbacks_global = {
00214    .object_type_loaded = global_loaded_observer,
00215 };
00216 
00217 int sip_cli_print_global(struct ast_sip_cli_context *context)
00218 {
00219    struct global_config *cfg = get_global_cfg();
00220 
00221    if (!cfg) {
00222       cfg = ast_sorcery_alloc(ast_sip_get_sorcery(), "global", NULL);
00223       if (!cfg) {
00224          return -1;
00225       }
00226    }
00227 
00228    ast_str_append(&context->output_buffer, 0, "\nGlobal Settings:\n\n");
00229    ast_sip_cli_print_sorcery_objectset(cfg, context, 0);
00230 
00231    ao2_ref(cfg, -1);
00232    return 0;
00233 }
00234 
00235 int ast_sip_destroy_sorcery_global(void)
00236 {
00237    struct ast_sorcery *sorcery = ast_sip_get_sorcery();
00238 
00239    ast_sorcery_instance_observer_remove(sorcery, &observer_callbacks_global);
00240 
00241    return 0;
00242 }
00243 
00244 int ast_sip_initialize_sorcery_global(void)
00245 {
00246    struct ast_sorcery *sorcery = ast_sip_get_sorcery();
00247 
00248    snprintf(default_useragent, sizeof(default_useragent), "%s %s",
00249       DEFAULT_USERAGENT_PREFIX, ast_get_version());
00250 
00251    ast_sorcery_apply_default(sorcery, "global", "config", "pjsip.conf,criteria=type=global");
00252 
00253    if (ast_sorcery_object_register(sorcery, "global", global_alloc, NULL, global_apply)) {
00254       return -1;
00255    }
00256 
00257    ast_sorcery_object_field_register(sorcery, "global", "type", "", OPT_NOOP_T, 0, 0);
00258    ast_sorcery_object_field_register(sorcery, "global", "max_forwards",
00259       __stringify(DEFAULT_MAX_FORWARDS),
00260       OPT_UINT_T, 0, FLDSET(struct global_config, max_forwards));
00261    ast_sorcery_object_field_register(sorcery, "global", "user_agent", default_useragent,
00262       OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, useragent));
00263    ast_sorcery_object_field_register(sorcery, "global", "default_outbound_endpoint",
00264       DEFAULT_OUTBOUND_ENDPOINT,
00265       OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, default_outbound_endpoint));
00266    ast_sorcery_object_field_register(sorcery, "global", "debug", DEFAULT_DEBUG,
00267       OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, debug));
00268    ast_sorcery_object_field_register(sorcery, "global", "endpoint_identifier_order",
00269       DEFAULT_ENDPOINT_IDENTIFIER_ORDER,
00270       OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, endpoint_identifier_order));
00271    ast_sorcery_object_field_register(sorcery, "global", "keep_alive_interval",
00272       __stringify(DEFAULT_KEEPALIVE_INTERVAL),
00273       OPT_UINT_T, 0, FLDSET(struct global_config, keep_alive_interval));
00274 
00275    if (ast_sorcery_instance_observer_add(sorcery, &observer_callbacks_global)) {
00276       return -1;
00277    }
00278 
00279    return 0;
00280 }

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