Author: rmudgett Date: Wed Mar 11 10:26:32 2015 New Revision: 432767 URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=432767 Log: res_pjsip: Fix pjsip.conf type=global object default value handling.
When a type=global section is not defined in pjsip.conf the global defaults are not applied. As a result the mandatory Max-Forwards header is not added to SIP messages for res_pjsip/chan_pjsip. The handling of pjsip.conf type=global objects has several problems: 1) If the global object is missing the defaults are not applied. 2) If the global object is missing the default_outbound_endpoint's default value is not returned by ast_sip_global_default_outbound_endpoint(). 3) Defines are needed so default values only need to be changed in one place. * Added a sorcery instance observer callback to check if there were any type=global sections loaded. If there were more than one then issue an error message. If there were none then apply the global defaults. * Fixed ast_sip_global_default_outbound_endpoint() to return the documented default when no type=global object is defined. * Made defines for the global default values. * Increased the default_useragent[] size because SVN version strings can get lengthy and 128 characters may not be enough. * Fixed an off-nominal code path ref leak in global_alloc() if the string fields fail to initialize. * Eliminated RAII_VAR in get_global_cfg() and ast_sip_global_default_outbound_endpoint(). ASTERISK-24807 #close Reported by: Anatoli Review: https://reviewboard.asterisk.org/r/4467/ ........ Merged revisions 432766 from http://svn.asterisk.org/svn/asterisk/branches/13 Modified: trunk/ (props changed) trunk/include/asterisk/res_pjsip.h trunk/res/res_pjsip/config_global.c trunk/res/res_pjsip/pjsip_configuration.c Propchange: trunk/ ------------------------------------------------------------------------------ Binary property 'branch-13-merged' - no diff available. Modified: trunk/include/asterisk/res_pjsip.h URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/res_pjsip.h?view=diff&rev=432767&r1=432766&r2=432767 ============================================================================== --- trunk/include/asterisk/res_pjsip.h (original) +++ trunk/include/asterisk/res_pjsip.h Wed Mar 11 10:26:32 2015 @@ -1627,7 +1627,22 @@ int ast_sip_add_global_request_header(const char *name, const char *value, int replace); int ast_sip_add_global_response_header(const char *name, const char *value, int replace); +/*! + * \brief Initialize global type on a sorcery instance + * + * \retval -1 failure + * \retval 0 success + */ int ast_sip_initialize_sorcery_global(void); + +/*! + * \brief Destroy global type on a sorcery instance + * \since 13.3.0 + * + * \retval -1 failure + * \retval 0 success + */ +int ast_sip_destroy_sorcery_global(void); /*! * \brief Retrieves the value associated with the given key. Modified: trunk/res/res_pjsip/config_global.c URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_pjsip/config_global.c?view=diff&rev=432767&r1=432766&r2=432767 ============================================================================== --- trunk/res/res_pjsip/config_global.c (original) +++ trunk/res/res_pjsip/config_global.c Wed Mar 11 10:26:32 2015 @@ -27,10 +27,13 @@ #include "asterisk/ast_version.h" #define DEFAULT_MAX_FORWARDS 70 +#define DEFAULT_KEEPALIVE_INTERVAL 0 #define DEFAULT_USERAGENT_PREFIX "Asterisk PBX" #define DEFAULT_OUTBOUND_ENDPOINT "default_outbound_endpoint" - -static char default_useragent[128]; +#define DEFAULT_DEBUG "no" +#define DEFAULT_ENDPOINT_IDENTIFIER_ORDER "ip,username,anonymous" + +static char default_useragent[256]; struct global_config { SORCERY_OBJECT(details); @@ -57,9 +60,11 @@ static void *global_alloc(const char *name) { - struct global_config *cfg = ast_sorcery_generic_alloc(sizeof(*cfg), global_destructor); - + struct global_config *cfg; + + cfg = ast_sorcery_generic_alloc(sizeof(*cfg), global_destructor); if (!cfg || ast_string_field_init(cfg, 100)) { + ao2_cleanup(cfg); return NULL; } @@ -81,78 +86,148 @@ static struct global_config *get_global_cfg(void) { - RAII_VAR(struct ao2_container *, globals, ast_sorcery_retrieve_by_fields( - ast_sip_get_sorcery(), "global", AST_RETRIEVE_FLAG_MULTIPLE, - NULL), ao2_cleanup); - + struct global_config *cfg; + struct ao2_container *globals; + + globals = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "global", + AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); if (!globals) { return NULL; } - return ao2_find(globals, NULL, 0); + cfg = ao2_find(globals, NULL, 0); + ao2_ref(globals, -1); + return cfg; } char *ast_sip_global_default_outbound_endpoint(void) { - RAII_VAR(struct global_config *, cfg, get_global_cfg(), ao2_cleanup); - - if (!cfg) { - return NULL; - } - - return ast_strdup(cfg->default_outbound_endpoint); + char *str; + struct global_config *cfg; + + cfg = get_global_cfg(); + if (!cfg) { + return ast_strdup(DEFAULT_OUTBOUND_ENDPOINT); + } + + str = ast_strdup(cfg->default_outbound_endpoint); + ao2_ref(cfg, -1); + return str; } char *ast_sip_get_debug(void) { char *res; - struct global_config *cfg = get_global_cfg(); - - if (!cfg) { - return ast_strdup("no"); + struct global_config *cfg; + + cfg = get_global_cfg(); + if (!cfg) { + return ast_strdup(DEFAULT_DEBUG); } res = ast_strdup(cfg->debug); ao2_ref(cfg, -1); - return res; } char *ast_sip_get_endpoint_identifier_order(void) { char *res; - struct global_config *cfg = get_global_cfg(); - - if (!cfg) { - return ast_strdup("ip,username,anonymous"); + struct global_config *cfg; + + cfg = get_global_cfg(); + if (!cfg) { + return ast_strdup(DEFAULT_ENDPOINT_IDENTIFIER_ORDER); } res = ast_strdup(cfg->endpoint_identifier_order); ao2_ref(cfg, -1); - return res; } unsigned int ast_sip_get_keep_alive_interval(void) { unsigned int interval; - struct global_config *cfg = get_global_cfg(); - - if (!cfg) { - return 0; + struct global_config *cfg; + + cfg = get_global_cfg(); + if (!cfg) { + return DEFAULT_KEEPALIVE_INTERVAL; } interval = cfg->keep_alive_interval; ao2_ref(cfg, -1); - return interval; } +/*! + * \internal + * \brief Observer to set default global object if none exist. + * + * \param name Module name owning the sorcery instance. + * \param sorcery Instance being observed. + * \param object_type Name of object being observed. + * \param reloaded Non-zero if the object is being reloaded. + * + * \return Nothing + */ +static void global_loaded_observer(const char *name, const struct ast_sorcery *sorcery, const char *object_type, int reloaded) +{ + struct ao2_container *globals; + struct global_config *cfg; + + if (strcmp(object_type, "global")) { + /* Not interested */ + return; + } + + globals = ast_sorcery_retrieve_by_fields(sorcery, "global", + AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); + if (globals) { + int count; + + count = ao2_container_count(globals); + ao2_ref(globals, -1); + + if (1 < count) { + ast_log(LOG_ERROR, + "At most one pjsip.conf type=global object can be defined. You have %d defined.\n", + count); + return; + } + if (count) { + return; + } + } + + ast_debug(1, "No pjsip.conf type=global object exists so applying defaults.\n"); + cfg = ast_sorcery_alloc(sorcery, "global", NULL); + if (!cfg) { + return; + } + global_apply(sorcery, cfg); + ao2_ref(cfg, -1); +} + +static const struct ast_sorcery_instance_observer observer_callbacks_global = { + .object_type_loaded = global_loaded_observer, +}; + +int ast_sip_destroy_sorcery_global(void) +{ + struct ast_sorcery *sorcery = ast_sip_get_sorcery(); + + ast_sorcery_instance_observer_remove(sorcery, &observer_callbacks_global); + + return 0; +} + int ast_sip_initialize_sorcery_global(void) { struct ast_sorcery *sorcery = ast_sip_get_sorcery(); - snprintf(default_useragent, sizeof(default_useragent), "%s %s", DEFAULT_USERAGENT_PREFIX, ast_get_version()); + snprintf(default_useragent, sizeof(default_useragent), "%s %s", + DEFAULT_USERAGENT_PREFIX, ast_get_version()); ast_sorcery_apply_default(sorcery, "global", "config", "pjsip.conf,criteria=type=global"); @@ -161,18 +236,26 @@ } ast_sorcery_object_field_register(sorcery, "global", "type", "", OPT_NOOP_T, 0, 0); - ast_sorcery_object_field_register(sorcery, "global", "max_forwards", __stringify(DEFAULT_MAX_FORWARDS), - OPT_UINT_T, 0, FLDSET(struct global_config, max_forwards)); + ast_sorcery_object_field_register(sorcery, "global", "max_forwards", + __stringify(DEFAULT_MAX_FORWARDS), + OPT_UINT_T, 0, FLDSET(struct global_config, max_forwards)); ast_sorcery_object_field_register(sorcery, "global", "user_agent", default_useragent, - OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, useragent)); - ast_sorcery_object_field_register(sorcery, "global", "default_outbound_endpoint", DEFAULT_OUTBOUND_ENDPOINT, - OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, default_outbound_endpoint)); - ast_sorcery_object_field_register(sorcery, "global", "debug", "no", - OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, debug)); - ast_sorcery_object_field_register(sorcery, "global", "endpoint_identifier_order", "ip,username,anonymous", - OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, endpoint_identifier_order)); - ast_sorcery_object_field_register(sorcery, "global", "keep_alive_interval", "", - OPT_UINT_T, 0, FLDSET(struct global_config, keep_alive_interval)); + OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, useragent)); + ast_sorcery_object_field_register(sorcery, "global", "default_outbound_endpoint", + DEFAULT_OUTBOUND_ENDPOINT, + OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, default_outbound_endpoint)); + ast_sorcery_object_field_register(sorcery, "global", "debug", DEFAULT_DEBUG, + OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, debug)); + ast_sorcery_object_field_register(sorcery, "global", "endpoint_identifier_order", + DEFAULT_ENDPOINT_IDENTIFIER_ORDER, + OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, endpoint_identifier_order)); + ast_sorcery_object_field_register(sorcery, "global", "keep_alive_interval", + __stringify(DEFAULT_KEEPALIVE_INTERVAL), + OPT_UINT_T, 0, FLDSET(struct global_config, keep_alive_interval)); + + if (ast_sorcery_instance_observer_add(sorcery, &observer_callbacks_global)) { + return -1; + } return 0; } Modified: trunk/res/res_pjsip/pjsip_configuration.c URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_pjsip/pjsip_configuration.c?view=diff&rev=432767&r1=432766&r2=432767 ============================================================================== --- trunk/res/res_pjsip/pjsip_configuration.c (original) +++ trunk/res/res_pjsip/pjsip_configuration.c Wed Mar 11 10:26:32 2015 @@ -1842,6 +1842,7 @@ void ast_res_pjsip_destroy_configuration(void) { + ast_sip_destroy_sorcery_global(); ast_sip_destroy_sorcery_location(); ast_sip_destroy_sorcery_auth(); ast_sip_destroy_sorcery_transport(); -- _____________________________________________________________________ -- Bandwidth and Colocation Provided by http://www.api-digital.com -- svn-commits mailing list To UNSUBSCRIBE or update options visit: http://lists.digium.com/mailman/listinfo/svn-commits