mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-03 11:25:35 +00:00
Continue events when ARI WebSocket reconnects
This patch addresses a bug in the /ari/events WebSocket in handling reconnects. When a Stasis application's associated WebSocket was disconnected and reconnected, it would not receive events for any channels or bridges it was subscribed to. The fix was to lazily clean up Stasis application registrations, instead of removing them as soon as the WebSocket goes away. When an application is unregistered at the WebSocket level, the underlying application is simply deactivated. If the application WebSocket is reconnected, the application is reactivated for the new connection. To avoid memory leaks from lingering, unused application, the application list is cleaned up whenever new applications are registered/unregistered. (closes issue ASTERISK-21970) Review: https://reviewboard.asterisk.org/r/2678/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@395120 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -564,6 +564,11 @@ int stasis_app_exec(struct ast_channel *chan, const char *app_name, int argc,
|
||||
"Stasis app '%s' not registered\n", app_name);
|
||||
return -1;
|
||||
}
|
||||
if (!app_is_active(app)) {
|
||||
ast_log(LOG_ERROR,
|
||||
"Stasis app '%s' not active\n", app_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
control = control_create(chan);
|
||||
if (!control) {
|
||||
@@ -575,7 +580,7 @@ int stasis_app_exec(struct ast_channel *chan, const char *app_name, int argc,
|
||||
res = app_send_start_msg(app, chan, argc, argv);
|
||||
if (res != 0) {
|
||||
ast_log(LOG_ERROR,
|
||||
"Error sending start message to %s\n", app_name);
|
||||
"Error sending start message to '%s'\n", app_name);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -662,6 +667,29 @@ int stasis_app_send(const char *app_name, struct ast_json *message)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cleanup_cb(void *obj, void *arg, int flags)
|
||||
{
|
||||
struct app *app = obj;
|
||||
|
||||
if (!app_is_finished(app)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ast_verb(1, "Cleaning up application '%s'\n", app_name(app));
|
||||
|
||||
return CMP_MATCH;
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Clean up any old apps that we don't need any more.
|
||||
*/
|
||||
static void cleanup(void)
|
||||
{
|
||||
ao2_callback(apps_registry, OBJ_MULTIPLE | OBJ_NODATA | OBJ_UNLINK,
|
||||
cleanup_cb, NULL);
|
||||
}
|
||||
|
||||
int stasis_app_register(const char *app_name, stasis_app_cb handler, void *data)
|
||||
{
|
||||
RAII_VAR(struct app *, app, NULL, ao2_cleanup);
|
||||
@@ -671,15 +699,6 @@ int stasis_app_register(const char *app_name, stasis_app_cb handler, void *data)
|
||||
app = ao2_find(apps_registry, app_name, OBJ_KEY | OBJ_NOLOCK);
|
||||
|
||||
if (app) {
|
||||
RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
|
||||
|
||||
msg = ast_json_pack("{s: s, s: s}",
|
||||
"type", "ApplicationReplaced",
|
||||
"application", app_name);
|
||||
if (msg) {
|
||||
app_send(app, msg);
|
||||
}
|
||||
|
||||
app_update(app, handler, data);
|
||||
} else {
|
||||
app = app_create(app_name, handler, data);
|
||||
@@ -690,15 +709,34 @@ int stasis_app_register(const char *app_name, stasis_app_cb handler, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
/* We lazily clean up the apps_registry, because it's good enough to
|
||||
* prevent memory leaks, and we're lazy.
|
||||
*/
|
||||
cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void stasis_app_unregister(const char *app_name)
|
||||
{
|
||||
if (app_name) {
|
||||
ao2_cleanup(ao2_find(
|
||||
apps_registry, app_name, OBJ_KEY | OBJ_UNLINK));
|
||||
RAII_VAR(struct app *, app, NULL, ao2_cleanup);
|
||||
|
||||
if (!app_name) {
|
||||
return;
|
||||
}
|
||||
|
||||
app = ao2_find(apps_registry, app_name, OBJ_KEY);
|
||||
if (!app) {
|
||||
ast_log(LOG_ERROR,
|
||||
"Stasis app '%s' not registered\n", app_name);
|
||||
return;
|
||||
}
|
||||
|
||||
app_deactivate(app);
|
||||
|
||||
/* There's a decent chance that app is ready for cleanup. Go ahead
|
||||
* and clean up, just in case
|
||||
*/
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void stasis_app_ref(void)
|
||||
|
Reference in New Issue
Block a user