ARI event type filtering

Event type filtering is now enabled, and configurable per application. An app is
now able to specify which events are sent to the application by configuring an
allowed and/or disallowed list(s). This can be done by issuing the following:

PUT /applications/{applicationName}/eventFilter

And then enumerating the allowed/disallowed event types as a body parameter.

ASTERISK-28106

Change-Id: I9671ba1fcdb3b6c830b553d4c5365aed5d588d5b
This commit is contained in:
Kevin Harwell
2019-02-08 14:48:27 -06:00
committed by George Joseph
parent 0eb27e1970
commit 8681fc9db7
11 changed files with 402 additions and 5 deletions

View File

@@ -65,6 +65,10 @@ struct stasis_app {
enum stasis_app_subscription_model subscription_model;
/*! Whether or not someone wants to see debug messages about this app */
int debug;
/*! An array of allowed events types for this application */
struct ast_json *events_allowed;
/*! An array of disallowed events types for this application */
struct ast_json *events_disallowed;
/*! Name of the Stasis application */
char name[];
};
@@ -303,6 +307,12 @@ static void app_dtor(void *obj)
app->forwards = NULL;
ao2_cleanup(app->data);
app->data = NULL;
ast_json_unref(app->events_allowed);
app->events_allowed = NULL;
ast_json_unref(app->events_disallowed);
app->events_disallowed = NULL;
}
static void call_forwarded_handler(struct stasis_app *app, struct stasis_message *message)
@@ -1603,3 +1613,119 @@ void stasis_app_unregister_event_sources(void)
stasis_app_unregister_event_source(&bridge_event_source);
stasis_app_unregister_event_source(&channel_event_source);
}
struct ast_json *stasis_app_event_filter_to_json(struct stasis_app *app, struct ast_json *json)
{
if (!app || !json) {
return json;
}
ast_json_object_set(json, "events_allowed", app->events_allowed ?
ast_json_ref(app->events_allowed) : ast_json_array_create());
ast_json_object_set(json, "events_disallowed", app->events_disallowed ?
ast_json_ref(app->events_disallowed) : ast_json_array_create());
return json;
}
static int app_event_filter_set(struct stasis_app *app, struct ast_json **member,
struct ast_json *filter, const char *filter_type)
{
if (filter && ast_json_typeof(filter) == AST_JSON_OBJECT) {
if (!ast_json_object_size(filter)) {
/* If no filters are specified then reset this filter type */
filter = NULL;
} else {
/* Otherwise try to get the filter array for this type */
filter = ast_json_object_get(filter, filter_type);
if (!filter) {
/* A filter type exists, but not this one, so don't update */
return 0;
}
}
}
/* At this point the filter object should be an array */
if (filter && ast_json_typeof(filter) != AST_JSON_ARRAY) {
ast_log(LOG_ERROR, "Invalid json type event filter - app: %s, filter: %s\n",
app->name, filter_type);
return -1;
}
if (filter) {
/* Confirm that at least the type names are specified */
struct ast_json *obj;
int i;
for (i = 0; i < ast_json_array_size(filter) &&
(obj = ast_json_array_get(filter, i)); ++i) {
if (ast_strlen_zero(ast_json_object_string_get(obj, "type"))) {
ast_log(LOG_ERROR, "Filter event must have a type - app: %s, "
"filter: %s\n", app->name, filter_type);
return -1;
}
}
}
ao2_lock(app);
ast_json_unref(*member);
*member = filter ? ast_json_ref(filter) : NULL;
ao2_unlock(app);
return 0;
}
static int app_events_allowed_set(struct stasis_app *app, struct ast_json *filter)
{
return app_event_filter_set(app, &app->events_allowed, filter, "allowed");
}
static int app_events_disallowed_set(struct stasis_app *app, struct ast_json *filter)
{
return app_event_filter_set(app, &app->events_disallowed, filter, "disallowed");
}
int stasis_app_event_filter_set(struct stasis_app *app, struct ast_json *filter)
{
return app_events_disallowed_set(app, filter) || app_events_allowed_set(app, filter);
}
static int app_event_filter_matched(struct ast_json *array, struct ast_json *event, int empty)
{
struct ast_json *obj;
int i;
if (!array || !ast_json_array_size(array)) {
return empty;
}
for (i = 0; i < ast_json_array_size(array) &&
(obj = ast_json_array_get(array, i)); ++i) {
if (ast_strings_equal(ast_json_object_string_get(obj, "type"),
ast_json_object_string_get(event, "type"))) {
return 1;
}
}
return 0;
}
int stasis_app_event_allowed(const char *app_name, struct ast_json *event)
{
struct stasis_app *app = stasis_app_get_by_name(app_name);
int res;
if (!app) {
return 0;
}
ao2_lock(app);
res = !app_event_filter_matched(app->events_disallowed, event, 0) &&
app_event_filter_matched(app->events_allowed, event, 1);
ao2_unlock(app);
ao2_ref(app, -1);
return res;
}