#include "asterisk/res_pjsip.h"
#include "include/res_pjsip_private.h"
+#include "asterisk/pbx.h"
#include "asterisk/sorcery.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/ast_version.h"
return cfg;
}
+/*
+ * There is ever only one global section, so we can use a single global
+ * value here to track the regcontext through reloads.
+ */
+static char *previous_regcontext = NULL;
+
+static int check_regcontext(const struct global_config *cfg)
+{
+ char *current = NULL;
+
+ if (previous_regcontext && !strcmp(previous_regcontext, cfg->regcontext)) {
+ /* Nothing changed so nothing to do */
+ return 0;
+ }
+
+ if (!ast_strlen_zero(cfg->regcontext)) {
+ current = ast_strdup(cfg->regcontext);
+ if (!current) {
+ return -1;
+ }
+
+ if (ast_sip_persistent_endpoint_add_to_regcontext(cfg->regcontext)) {
+ ast_free(current);
+ return -1;
+ }
+ }
+
+ if (!ast_strlen_zero(previous_regcontext)) {
+ ast_context_destroy_by_name(previous_regcontext, "PJSIP");
+ ast_free(previous_regcontext);
+ previous_regcontext = NULL;
+ }
+
+ if (current) {
+ previous_regcontext = current;
+ }
+
+ return 0;
+}
+
static int global_apply(const struct ast_sorcery *sorcery, void *obj)
{
struct global_config *cfg = obj;
ast_sip_add_global_request_header("User-Agent", cfg->useragent, 1);
ast_sip_add_global_response_header("Server", cfg->useragent, 1);
+ if (check_regcontext(cfg)) {
+ return -1;
+ }
+
ao2_t_global_obj_replace_unref(global_cfg, cfg, "Applying global settings");
return 0;
}
ast_sorcery_instance_observer_remove(sorcery, &observer_callbacks_global);
+ if (previous_regcontext) {
+ ast_context_destroy_by_name(previous_regcontext, "PJSIP");
+ ast_free(previous_regcontext);
+ }
+
ao2_t_global_obj_release(global_cfg, "Module is unloading");
return 0;
}
+
int ast_sip_initialize_sorcery_global(void)
{
struct ast_sorcery *sorcery = ast_sip_get_sorcery();
*/
void ast_sip_destroy_transport_management(void);
+/*!
+ * \internal
+ * \brief Add online persistent endpoints to the given regcontext
+ *
+ * \param regcontext The context to add endpoints to
+ *
+ * \retval -1 on error, 0 on success
+ */
+int ast_sip_persistent_endpoint_add_to_regcontext(const char *regcontext);
+
#endif /* RES_PJSIP_PRIVATE_H_ */
ast_endpoint_shutdown(persistent->endpoint);
}
+static int add_to_regcontext(void *obj, void *arg, int flags)
+{
+ struct sip_persistent_endpoint *persistent = obj;
+ const char *regcontext = arg;
+
+ if (ast_endpoint_get_state(persistent->endpoint) == AST_ENDPOINT_ONLINE) {
+ if (!ast_exists_extension(NULL, regcontext, ast_endpoint_get_resource(
+ persistent->endpoint), 1, NULL)) {
+ ast_add_extension(regcontext, 1, ast_endpoint_get_resource(persistent->endpoint), 1, NULL, NULL,
+ "Noop", ast_strdup(ast_endpoint_get_resource(persistent->endpoint)), ast_free_ptr, "PJSIP");
+ }
+ }
+
+ return 0;
+}
+
+int ast_sip_persistent_endpoint_add_to_regcontext(const char *regcontext)
+{
+ if (ast_strlen_zero(regcontext)) {
+ return 0;
+ }
+
+ /* Make sure the regcontext exists */
+ if (!ast_context_find_or_create(NULL, NULL, regcontext, "PJSIP")) {
+ ast_log(LOG_ERROR, "Failed to create regcontext '%s'\n", regcontext);
+ return -1;
+ }
+
+ /* Add any online endpoints */
+ ao2_callback(persistent_endpoints, OBJ_NODATA, add_to_regcontext, (void *)regcontext);
+ return 0;
+}
+
int ast_sip_persistent_endpoint_update_state(const char *endpoint_name, enum ast_endpoint_state state)
{
struct sip_persistent_endpoint *persistent;
if (!ast_strlen_zero(regcontext)) {
if (!ast_exists_extension(NULL, regcontext, ast_endpoint_get_resource(persistent->endpoint), 1, NULL)) {
ast_add_extension(regcontext, 1, ast_endpoint_get_resource(persistent->endpoint), 1, NULL, NULL,
- "Noop", ast_strdup(ast_endpoint_get_resource(persistent->endpoint)), ast_free_ptr, "SIP");
+ "Noop", ast_strdup(ast_endpoint_get_resource(persistent->endpoint)), ast_free_ptr, "PJSIP");
}
}