diff --git a/include/asterisk/sorcery.h b/include/asterisk/sorcery.h index 3a0e1b81a5..a0ec653584 100644 --- a/include/asterisk/sorcery.h +++ b/include/asterisk/sorcery.h @@ -323,6 +323,9 @@ struct ast_sorcery_wizard { /* \brief Callback for whether or not the wizard believes the object is stale */ int (*is_stale)(const struct ast_sorcery *sorcery, void *data, void *object); + + /*! \brief Optional callback for forcing a reload to occur, even if wizard has determined no changes */ + void (*force_reload)(void *data, const struct ast_sorcery *sorcery, const char *type); }; /*! \brief Interface for a sorcery object type observer */ @@ -1059,6 +1062,17 @@ void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type */ void ast_sorcery_reload(const struct ast_sorcery *sorcery); +/*! + * \brief Inform any wizards to reload persistent objects, even if no changes determined + * + * \param sorcery Pointer to a sorcery structure + * + * \since 13.32.0 + * \since 16.9.0 + * \since 17.3.0 + */ +void ast_sorcery_force_reload(const struct ast_sorcery *sorcery); + /*! * \brief Inform any wizards of a specific object type to reload persistent objects * @@ -1067,6 +1081,19 @@ void ast_sorcery_reload(const struct ast_sorcery *sorcery); */ void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type); +/*! + * \brief Inform any wizards of a specific object type to reload persistent objects + * even if no changes determined + * + * \param sorcery Pointer to a sorcery structure + * \param type Name of the object type to reload + * + * \since 13.32.0 + * \since 16.9.0 + * \since 17.3.0 + */ +void ast_sorcery_force_reload_object(const struct ast_sorcery *sorcery, const char *type); + /*! * \brief Increase the reference count of a sorcery structure * diff --git a/main/sorcery.c b/main/sorcery.c index d837845711..0ada81e3f7 100644 --- a/main/sorcery.c +++ b/main/sorcery.c @@ -245,6 +245,9 @@ struct sorcery_load_details { /*! \brief Whether this is a reload or not */ unsigned int reload:1; + + /*! \brief Whether this is forced or not */ + unsigned int force:1; }; /*! \brief Registered sorcery wizards */ @@ -1250,7 +1253,15 @@ static int sorcery_wizard_load(void *obj, void *arg, int flags) struct sorcery_load_details *details = arg; void (*load)(void *data, const struct ast_sorcery *sorcery, const char *type); - load = !details->reload ? wizard->wizard->callbacks.load : wizard->wizard->callbacks.reload; + if (details->reload) { + if (details->force && wizard->wizard->callbacks.force_reload) { + load = wizard->wizard->callbacks.force_reload; + } else { + load = wizard->wizard->callbacks.reload; + } + } else { + load = wizard->wizard->callbacks.load; + } if (load) { NOTIFY_WIZARD_OBSERVERS(wizard->wizard->observers, wizard_loading, @@ -1408,6 +1419,23 @@ void ast_sorcery_reload(const struct ast_sorcery *sorcery) } +void ast_sorcery_force_reload(const struct ast_sorcery *sorcery) +{ + struct sorcery_load_details details = { + .sorcery = sorcery, + .reload = 1, + .force = 1, + }; + + NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loading, + sorcery->module_name, sorcery, 1); + + ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details); + + NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loaded, + sorcery->module_name, sorcery, 1); +} + void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type) { RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup); @@ -1423,6 +1451,22 @@ void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *ty sorcery_object_load(object_type, &details, 0); } +void ast_sorcery_force_reload_object(const struct ast_sorcery *sorcery, const char *type) +{ + RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup); + struct sorcery_load_details details = { + .sorcery = sorcery, + .reload = 1, + .force = 1, + }; + + if (!object_type) { + return; + } + + sorcery_object_load(object_type, &details, 0); +} + void ast_sorcery_ref(struct ast_sorcery *sorcery) { ao2_ref(sorcery, +1); diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index e6937fb3cc..2452e54bef 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -34,6 +34,8 @@ #include "asterisk/statsd.h" #include "asterisk/pbx.h" #include "asterisk/stream.h" +#include "asterisk/stasis.h" +#include "asterisk/security_events.h" /*! \brief Number of buckets for persistent endpoint information */ #define PERSISTENT_BUCKETS 53 @@ -49,6 +51,8 @@ static struct ao2_container *persistent_endpoints; static struct ast_sorcery *sip_sorcery; +static struct stasis_subscription *acl_change_sub; + /*! \brief Hashing function for persistent endpoint information */ static int persistent_endpoint_hash(const void *obj, const int flags) { @@ -1787,6 +1791,16 @@ static void load_all_endpoints(void) ao2_cleanup(endpoints); } +static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, + struct stasis_message *message) +{ + if (stasis_message_type(message) != ast_named_acl_change_type()) { + return; + } + + ast_sorcery_force_reload_object(sip_sorcery, "endpoint"); +} + int ast_res_pjsip_initialize_configuration(void) { if (ast_manager_register_xml(AMI_SHOW_ENDPOINTS, EVENT_FLAG_SYSTEM, ami_show_endpoints) || @@ -2007,6 +2021,10 @@ int ast_res_pjsip_initialize_configuration(void) ast_sip_location_prune_boot_contacts(); + acl_change_sub = stasis_subscribe(ast_security_topic(), acl_change_stasis_cb, NULL); + stasis_subscription_accept_message_type(acl_change_sub, ast_named_acl_change_type()); + stasis_subscription_set_filter(acl_change_sub, STASIS_SUBSCRIPTION_FILTER_SELECTIVE); + return 0; } @@ -2016,6 +2034,7 @@ void ast_res_pjsip_destroy_configuration(void) return; } + acl_change_sub = stasis_unsubscribe_and_join(acl_change_sub); ast_sip_destroy_sorcery_global(); ast_sip_destroy_sorcery_location(); ast_sip_destroy_sorcery_auth(); diff --git a/res/res_pjsip_acl.c b/res/res_pjsip_acl.c index 8caf70344a..3bf0f6fe60 100644 --- a/res/res_pjsip_acl.c +++ b/res/res_pjsip_acl.c @@ -31,6 +31,8 @@ #include "asterisk/logger.h" #include "asterisk/sorcery.h" #include "asterisk/acl.h" +#include "asterisk/stasis.h" +#include "asterisk/security_events.h" /*** DOCUMENTATION @@ -114,6 +116,8 @@ ***/ +static struct stasis_subscription *acl_change_sub; + static int apply_acl(pjsip_rx_data *rdata, struct ast_acl_list *acl) { struct ast_sockaddr addr; @@ -280,6 +284,16 @@ static void *acl_alloc(const char *name) return sip_acl; } +static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, + struct stasis_message *message) +{ + if (stasis_message_type(message) != ast_named_acl_change_type()) { + return; + } + + ast_sorcery_force_reload_object(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE); +} + static int load_module(void) { ast_sorcery_apply_config(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE); @@ -304,12 +318,18 @@ static int load_module(void) ast_sorcery_load_object(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE); + acl_change_sub = stasis_subscribe(ast_security_topic(), acl_change_stasis_cb, NULL); + stasis_subscription_accept_message_type(acl_change_sub, ast_named_acl_change_type()); + stasis_subscription_set_filter(acl_change_sub, STASIS_SUBSCRIPTION_FILTER_SELECTIVE); + ast_sip_register_service(&acl_module); + return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { + acl_change_sub = stasis_unsubscribe_and_join(acl_change_sub); ast_sip_unregister_service(&acl_module); return 0; } diff --git a/res/res_sorcery_config.c b/res/res_sorcery_config.c index 8e5ee205a8..602978924c 100644 --- a/res/res_sorcery_config.c +++ b/res/res_sorcery_config.c @@ -103,6 +103,7 @@ static struct ast_sorcery_wizard config_object_wizard = { .open = sorcery_config_open, .load = sorcery_config_load, .reload = sorcery_config_reload, + .force_reload = sorcery_config_load, .retrieve_id = sorcery_config_retrieve_id, .retrieve_fields = sorcery_config_retrieve_fields, .retrieve_multiple = sorcery_config_retrieve_multiple,