diff --git a/include/asterisk/stasis.h b/include/asterisk/stasis.h index 62ed1ed1a0..0373eeb35e 100644 --- a/include/asterisk/stasis.h +++ b/include/asterisk/stasis.h @@ -744,6 +744,16 @@ struct stasis_topic_pool *stasis_topic_pool_create(struct stasis_topic *pooled_t */ struct stasis_topic *stasis_topic_pool_get_topic(struct stasis_topic_pool *pool, const char *topic_name); +/*! + * \brief Check if a topic exists in a pool + * \param pool Pool to check + * \param topic_name Name of the topic to check + * \retval 1 exists + * \retval 0 does not exist + * \since 13.23.0 + */ +int stasis_topic_pool_topic_exists(const struct stasis_topic_pool *pool, const char *topic_name); + /*! \addtogroup StasisTopicsAndMessages * @{ */ diff --git a/main/devicestate.c b/main/devicestate.c index 637c05b594..7dcbe82900 100644 --- a/main/devicestate.c +++ b/main/devicestate.c @@ -714,7 +714,7 @@ int ast_publish_device_state_full( { RAII_VAR(struct ast_device_state_message *, device_state, NULL, ao2_cleanup); RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); - struct stasis_topic *device_specific_topic; + struct stasis_topic *topic; ast_assert(!ast_strlen_zero(device)); @@ -733,12 +733,28 @@ int ast_publish_device_state_full( return -1; } - device_specific_topic = ast_device_state_topic(device); - if (!device_specific_topic) { + /* When a device state is to be cached it is likely that something + * external will either be monitoring it or will want to pull the + * information from the cache, so we always publish to the device + * specific topic. Cachable updates traditionally come from such things + * as a SIP or PJSIP device. + * When a device state is not to be cached we only publish to its + * specific topic if something has already created the topic. Publishing + * to its topic otherwise would create the topic, which may not be + * necessary as it could be an ephemeral device. Uncachable updates + * traditionally come from such things as Local channels. + */ + if (cachable || stasis_topic_pool_topic_exists(device_state_topic_pool, device)) { + topic = ast_device_state_topic(device); + } else { + topic = ast_device_state_topic_all(); + } + + if (!topic) { return -1; } - stasis_publish(device_specific_topic, message); + stasis_publish(topic, message); return 0; } diff --git a/main/stasis.c b/main/stasis.c index 32540117b9..1616debf3e 100644 --- a/main/stasis.c +++ b/main/stasis.c @@ -1196,6 +1196,19 @@ struct stasis_topic *stasis_topic_pool_get_topic(struct stasis_topic_pool *pool, return topic_pool_entry->topic; } +int stasis_topic_pool_topic_exists(const struct stasis_topic_pool *pool, const char *topic_name) +{ + struct topic_pool_entry *topic_pool_entry; + + topic_pool_entry = ao2_find(pool->pool_container, topic_name, OBJ_SEARCH_KEY); + if (!topic_pool_entry) { + return 0; + } + + ao2_ref(topic_pool_entry, -1); + return 1; +} + void stasis_log_bad_type_access(const char *name) { #ifdef AST_DEVMODE