res_stasis: Auto-create context and extens on Stasis app launch.

At AstriCon, there was a strong desire for the ability to completely
bypass dialplan when using ARI. This is possible through the automatic
creation of a context and a couple of extensions whenever an application
is started.

For example, if you have an application named 'ari-example', a context
named 'stasis-ari-example' will be automatically created whenever this
application is started as long as one does not already exist. Two
extensions (a match-all extension for Stasis and a 'h' extension) are
created within this context. Any endpoint that registers to Asterisk
within this context will send all calls to the corresponding Stasis
application. When the application is destroyed, the context is removed.

ASTERISK-28104 #close

Change-Id: Ie35bd93075e05b05e3ae129a83c9426931b7ebac
This commit is contained in:
Ben Ford 2019-01-29 10:48:49 -06:00 committed by Benjamin Keith Ford
parent 6ccf1155d1
commit 1051e1dd18
2 changed files with 33 additions and 0 deletions

View File

@ -12,6 +12,14 @@
--- Functionality changes from Asterisk 16.1.0 to Asterisk 16.2.0 ------------
------------------------------------------------------------------------------
ARI
------------------
* Whenever an ARI application is started, a context will be created for it
automatically as long as one does not already exist, following the format
'stasis-<app_name>'. Two extensions are also added to this context: a match-all
extension, and the 'h' extension. Any phone that registers under this context
will place all calls to the corresponding Stasis application.
res_pjsip
------------------
* Added "send_contact_status_on_update_registration" global configuration option

View File

@ -296,6 +296,8 @@ static int forwards_sort(const void *obj_left, const void *obj_right, int flags)
static void app_dtor(void *obj)
{
struct stasis_app *app = obj;
size_t size = strlen("stasis-") + strlen(app->name) + 1;
char context_name[size];
ast_verb(1, "Destroying Stasis app %s\n", app->name);
@ -303,6 +305,11 @@ static void app_dtor(void *obj)
ast_assert(app->bridge_router == NULL);
ast_assert(app->endpoint_router == NULL);
/* If we created a context for this application, remove it */
strcpy(context_name, "stasis-");
strcat(context_name, app->name);
ast_context_destroy_by_name(context_name, "res_stasis");
ao2_cleanup(app->topic);
app->topic = NULL;
ao2_cleanup(app->forwards);
@ -940,6 +947,8 @@ struct stasis_app *app_create(const char *name, stasis_app_cb handler, void *dat
RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
size_t size;
int res = 0;
size_t context_size = strlen("stasis-") + strlen(name) + 1;
char context_name[context_size];
ast_assert(name != NULL);
ast_assert(handler != NULL);
@ -1018,6 +1027,22 @@ struct stasis_app *app_create(const char *name, stasis_app_cb handler, void *dat
app->handler = handler;
app->data = ao2_bump(data);
/* Create a context, a match-all extension, and a 'h' extension for this application. Note that
* this should only be done if a context does not already exist. */
strcpy(context_name, "stasis-");
strcat(context_name, name);
if (!ast_context_find(context_name)) {
if (!ast_context_find_or_create(NULL, NULL, context_name, "res_stasis")) {
ast_log(LOG_WARNING, "Could not create context '%s' for Stasis application '%s'\n", context_name, name);
} else {
ast_add_extension(context_name, 0, "_.", 1, NULL, NULL, "Stasis", ast_strdup(name), ast_free_ptr, "res_stasis");
ast_add_extension(context_name, 0, "h", 1, NULL, NULL, "NoOp", NULL, NULL, "res_stasis");
}
} else {
ast_log(LOG_WARNING, "Not creating context '%s' for Stasis application '%s' because it already exists\n",
context_name, name);
}
ao2_ref(app, +1);
return app;
}