summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/asterisk/stasis.h40
-rw-r--r--include/asterisk/stasis_app.h7
-rw-r--r--include/asterisk/stasis_bridges.h7
-rw-r--r--include/asterisk/stasis_channels.h7
-rw-r--r--include/asterisk/stasis_endpoints.h5
-rw-r--r--main/json.c2
-rw-r--r--main/rtp_engine.c17
-rw-r--r--main/stasis_bridges.c87
-rw-r--r--main/stasis_channels.c57
-rw-r--r--main/stasis_endpoints.c12
-rw-r--r--main/stasis_message.c6
-rw-r--r--res/ari/resource_bridges.c8
-rw-r--r--res/ari/resource_channels.c22
-rw-r--r--res/ari/resource_endpoints.c22
-rw-r--r--res/res_stasis.c44
-rw-r--r--res/stasis/app.c51
16 files changed, 314 insertions, 80 deletions
diff --git a/include/asterisk/stasis.h b/include/asterisk/stasis.h
index 955bdc3fc..6bc5171e0 100644
--- a/include/asterisk/stasis.h
+++ b/include/asterisk/stasis.h
@@ -187,6 +187,36 @@ struct stasis_message_type;
struct stasis_message;
/*!
+ * \brief Structure containing callbacks for Stasis message sanitization
+ *
+ * \note If either callback is implemented, both should be implemented since
+ * not all callers may have access to the full snapshot.
+ */
+struct stasis_message_sanitizer {
+ /*!
+ * \brief Callback which determines whether a channel should be sanitized from
+ * a message based on the channel's unique ID
+ *
+ * \param channel_id The unique ID of the channel
+ *
+ * \retval non-zero if the channel should be left out of the message
+ * \retval zero if the channel should remain in the message
+ */
+ int (*channel_id)(const char *channel_id);
+
+ /*!
+ * \brief Callback which determines whether a channel should be sanitized from
+ * a message based on the channel's snapshot
+ *
+ * \param snapshot A snapshot generated from the channel
+ *
+ * \retval non-zero if the channel should be left out of the message
+ * \retval zero if the channel should remain in the message
+ */
+ int (*channel_snapshot)(const struct ast_channel_snapshot *snapshot);
+};
+
+/*!
* \brief Virtual table providing methods for messages.
* \since 12
*/
@@ -198,17 +228,19 @@ struct stasis_message_vtable {
* The returned object should be ast_json_unref()'ed.
*
* \param message Message to convert to JSON string.
+ * \param sanitize Snapshot sanitization callback.
+ *
* \return Newly allocated JSON message.
* \return \c NULL on error.
* \return \c NULL if JSON format is not supported.
*/
- struct ast_json *(*to_json)(struct stasis_message *message);
+ struct ast_json *(*to_json)(struct stasis_message *message, const struct stasis_message_sanitizer *sanitize);
/*!
* \brief Build the AMI representation of the message.
*
* May be \c NULL, or may return \c NULL, to indicate no representation.
- * The returned object should be ao2_cleankup()'ed.
+ * The returned object should be ao2_cleanup()'ed.
*
* \param message Message to convert to AMI string.
* \return Newly allocated \ref ast_manager_event_blob.
@@ -292,11 +324,13 @@ const struct timeval *stasis_message_timestamp(const struct stasis_message *msg)
* be ast_json_unref()'ed.
*
* \param message Message to convert to JSON string.
+ * \param sanitize Snapshot sanitization callback.
+ *
* \return Newly allocated string with JSON message.
* \return \c NULL on error.
* \return \c NULL if JSON format is not supported.
*/
-struct ast_json *stasis_message_to_json(struct stasis_message *message);
+struct ast_json *stasis_message_to_json(struct stasis_message *message, struct stasis_message_sanitizer *sanitize);
/*!
* \brief Build the AMI representation of the message.
diff --git a/include/asterisk/stasis_app.h b/include/asterisk/stasis_app.h
index 801b7adb2..4ef55b193 100644
--- a/include/asterisk/stasis_app.h
+++ b/include/asterisk/stasis_app.h
@@ -532,6 +532,13 @@ void stasis_app_ref(void);
*/
void stasis_app_unref(void);
+/*!
+ * \brief Get the Stasis message sanitizer for app_stasis applications
+ *
+ * \retval The stasis message sanitizer
+ */
+struct stasis_message_sanitizer *stasis_app_get_sanitizer(void);
+
/*! @} */
#endif /* _ASTERISK_STASIS_APP_H */
diff --git a/include/asterisk/stasis_bridges.h b/include/asterisk/stasis_bridges.h
index d82bcffaf..9412bf0b7 100644
--- a/include/asterisk/stasis_bridges.h
+++ b/include/asterisk/stasis_bridges.h
@@ -231,10 +231,15 @@ void ast_bridge_publish_leave(struct ast_bridge *bridge, struct ast_channel *cha
/*!
* \brief Build a JSON object from a \ref ast_bridge_snapshot.
+ *
+ * \param snapshot The bridge snapshot to convert to JSON
+ * \param sanitize The message sanitizer to use on the snapshot
+ *
* \return JSON object representing bridge snapshot.
* \return \c NULL on error
*/
-struct ast_json *ast_bridge_snapshot_to_json(const struct ast_bridge_snapshot *snapshot);
+struct ast_json *ast_bridge_snapshot_to_json(const struct ast_bridge_snapshot *snapshot,
+ const struct stasis_message_sanitizer *sanitize);
/*!
* \brief Pair showing a bridge snapshot and a specific channel snapshot belonging to the bridge
diff --git a/include/asterisk/stasis_channels.h b/include/asterisk/stasis_channels.h
index 7d9c3efdc..519a4b676 100644
--- a/include/asterisk/stasis_channels.h
+++ b/include/asterisk/stasis_channels.h
@@ -541,10 +541,15 @@ void ast_publish_channel_state(struct ast_channel *chan);
/*!
* \brief Build a JSON object from a \ref ast_channel_snapshot.
+ *
+ * \param snapshot The snapshot to convert to JSON
+ * \param sanitize The message sanitizer to use on the snapshot
+ *
* \return JSON object representing channel snapshot.
* \return \c NULL on error
*/
-struct ast_json *ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot);
+struct ast_json *ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot,
+ const struct stasis_message_sanitizer *sanitize);
/*!
* \brief Compares the context, exten and priority of two snapshots.
diff --git a/include/asterisk/stasis_endpoints.h b/include/asterisk/stasis_endpoints.h
index 0ba233bf8..1d56a8fea 100644
--- a/include/asterisk/stasis_endpoints.h
+++ b/include/asterisk/stasis_endpoints.h
@@ -208,11 +208,14 @@ struct ast_endpoint_snapshot *ast_endpoint_latest_snapshot(const char *tech,
* \brief Build a JSON object from a \ref ast_endpoint_snapshot.
*
* \param snapshot Endpoint snapshot.
+ * \param sanitize The message sanitizer to use on the snapshot
+ *
* \return JSON object representing endpoint snapshot.
* \return \c NULL on error
*/
struct ast_json *ast_endpoint_snapshot_to_json(
- const struct ast_endpoint_snapshot *snapshot);
+ const struct ast_endpoint_snapshot *snapshot,
+ const struct stasis_message_sanitizer *sanitize);
/*!
* \brief Initialization function for endpoint stasis support.
diff --git a/main/json.c b/main/json.c
index ce4c6cfc9..066a5df17 100644
--- a/main/json.c
+++ b/main/json.c
@@ -690,7 +690,7 @@ struct ast_json *ast_json_vpack(char const *format, va_list ap)
struct ast_json *r = NULL;
if (format) {
r = (struct ast_json *)json_vpack_ex(&error, 0, format, ap);
- if (!r) {
+ if (!r && !ast_strlen_zero(error.text)) {
ast_log(LOG_ERROR,
"Error building JSON from '%s': %s.\n",
format, error.text);
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index b02c6bb1b..c63bab0ea 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -1780,13 +1780,14 @@ static struct ast_manager_event_blob *rtcp_report_to_ami(struct stasis_message *
ast_str_buffer(packet_string));
}
-static struct ast_json *rtcp_report_to_json(struct stasis_message *msg)
+static struct ast_json *rtcp_report_to_json(struct stasis_message *msg,
+ const struct stasis_message_sanitizer *sanitize)
{
struct rtcp_message_payload *payload = stasis_message_data(msg);
RAII_VAR(struct ast_json *, json_rtcp_report, NULL, ast_json_unref);
RAII_VAR(struct ast_json *, json_rtcp_report_blocks, NULL, ast_json_unref);
RAII_VAR(struct ast_json *, json_rtcp_sender_info, NULL, ast_json_unref);
- struct ast_json * json_payload;
+ RAII_VAR(struct ast_json *, json_channel, NULL, ast_json_unref);
int i;
json_rtcp_report_blocks = ast_json_array_create();
@@ -1835,11 +1836,17 @@ static struct ast_json *rtcp_report_to_json(struct stasis_message *msg)
return NULL;
}
- json_payload = ast_json_pack("{s: O, s: O, s: O}",
- "channel", payload->snapshot ? ast_channel_snapshot_to_json(payload->snapshot) : ast_json_null(),
+ if (payload->snapshot) {
+ json_channel = ast_channel_snapshot_to_json(payload->snapshot, sanitize);
+ if (!json_channel) {
+ return NULL;
+ }
+ }
+
+ return ast_json_pack("{s: O, s: O, s: O}",
+ "channel", payload->snapshot ? json_channel : ast_json_null(),
"rtcp_report", json_rtcp_report,
"blob", payload->blob);
- return json_payload;
}
static void rtp_rtcp_report_dtor(void *obj)
diff --git a/main/stasis_bridges.c b/main/stasis_bridges.c
index 7d078f9d0..b92d048bc 100644
--- a/main/stasis_bridges.c
+++ b/main/stasis_bridges.c
@@ -135,9 +135,15 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_message *message);
static struct ast_manager_event_blob *blind_transfer_to_ami(struct stasis_message *message);
-static struct ast_json *ast_channel_entered_bridge_to_json(struct stasis_message *msg);
-static struct ast_json *ast_channel_left_bridge_to_json(struct stasis_message *msg);
-static struct ast_json *ast_bridge_merge_message_to_json(struct stasis_message *msg);
+static struct ast_json *ast_channel_entered_bridge_to_json(
+ struct stasis_message *msg,
+ const struct stasis_message_sanitizer *sanitize);
+static struct ast_json *ast_channel_left_bridge_to_json(
+ struct stasis_message *msg,
+ const struct stasis_message_sanitizer *sanitize);
+static struct ast_json *ast_bridge_merge_message_to_json(
+ struct stasis_message *msg,
+ const struct stasis_message_sanitizer *sanitize);
static struct stasis_cp_all *bridge_cache_all;
@@ -316,17 +322,25 @@ static struct ast_bridge_merge_message *bridge_merge_message_create(struct ast_b
return msg;
}
-static struct ast_json *ast_bridge_merge_message_to_json(struct stasis_message *msg)
+static struct ast_json *ast_bridge_merge_message_to_json(
+ struct stasis_message *msg,
+ const struct stasis_message_sanitizer *sanitize)
{
- struct ast_bridge_merge_message *merge;
+ struct ast_bridge_merge_message *merge = stasis_message_data(msg);
+ RAII_VAR(struct ast_json *, json_bridge_to,
+ ast_bridge_snapshot_to_json(merge->to, sanitize), ast_json_unref);
+ RAII_VAR(struct ast_json *, json_bridge_from,
+ ast_bridge_snapshot_to_json(merge->from, sanitize), ast_json_unref);
- merge = stasis_message_data(msg);
+ if (!json_bridge_to || !json_bridge_from) {
+ return NULL;
+ }
- return ast_json_pack("{s: s, s: o, s: o, s: o}",
+ return ast_json_pack("{s: s, s: o, s: O, s: O}",
"type", "BridgeMerged",
"timestamp", ast_json_timeval(*stasis_message_timestamp(msg), NULL),
- "bridge", ast_bridge_snapshot_to_json(merge->to),
- "bridge_from", ast_bridge_snapshot_to_json(merge->from));
+ "bridge", json_bridge_to,
+ "bridge_from", json_bridge_from);
}
void ast_bridge_publish_merge(struct ast_bridge *to, struct ast_bridge *from)
@@ -443,45 +457,63 @@ static struct ast_json *simple_bridge_channel_event(
const char *type,
struct ast_bridge_snapshot *bridge_snapshot,
struct ast_channel_snapshot *channel_snapshot,
- const struct timeval *tv)
+ const struct timeval *tv,
+ const struct stasis_message_sanitizer *sanitize)
{
- return ast_json_pack("{s: s, s: o, s: o, s: o}",
+ RAII_VAR(struct ast_json *, json_bridge,
+ ast_bridge_snapshot_to_json(bridge_snapshot, sanitize), ast_json_unref);
+ RAII_VAR(struct ast_json *, json_channel,
+ ast_channel_snapshot_to_json(channel_snapshot, sanitize), ast_json_unref);
+
+ if (!json_bridge || !json_channel) {
+ return NULL;
+ }
+
+ return ast_json_pack("{s: s, s: o, s: O, s: O}",
"type", type,
"timestamp", ast_json_timeval(*tv, NULL),
- "bridge", ast_bridge_snapshot_to_json(bridge_snapshot),
- "channel", ast_channel_snapshot_to_json(channel_snapshot));
+ "bridge", json_bridge,
+ "channel", json_channel);
}
-struct ast_json *ast_channel_entered_bridge_to_json(struct stasis_message *msg)
+struct ast_json *ast_channel_entered_bridge_to_json(
+ struct stasis_message *msg,
+ const struct stasis_message_sanitizer *sanitize)
{
struct ast_bridge_blob *obj = stasis_message_data(msg);
return simple_bridge_channel_event("ChannelEnteredBridge", obj->bridge,
- obj->channel, stasis_message_timestamp(msg));
+ obj->channel, stasis_message_timestamp(msg), sanitize);
}
-struct ast_json *ast_channel_left_bridge_to_json(struct stasis_message *msg)
+struct ast_json *ast_channel_left_bridge_to_json(
+ struct stasis_message *msg,
+ const struct stasis_message_sanitizer *sanitize)
{
struct ast_bridge_blob *obj = stasis_message_data(msg);
return simple_bridge_channel_event("ChannelLeftBridge", obj->bridge,
- obj->channel, stasis_message_timestamp(msg));
+ obj->channel, stasis_message_timestamp(msg), sanitize);
}
-typedef struct ast_json *(*json_item_serializer_cb)(void *obj);
-
-static struct ast_json *container_to_json_array(struct ao2_container *items, json_item_serializer_cb item_cb)
+static struct ast_json *container_to_json_array(struct ao2_container *items,
+ const struct stasis_message_sanitizer *sanitize)
{
RAII_VAR(struct ast_json *, json_items, ast_json_array_create(), ast_json_unref);
- void *item;
+ char *item;
struct ao2_iterator it;
if (!json_items) {
return NULL;
}
- it = ao2_iterator_init(items, 0);
- while ((item = ao2_iterator_next(&it))) {
- if (ast_json_array_append(json_items, item_cb(item))) {
+ for (it = ao2_iterator_init(items, 0);
+ (item = ao2_iterator_next(&it)); ao2_cleanup(item)) {
+ if (sanitize && sanitize->channel_id && sanitize->channel_id(item)) {
+ continue;
+ }
+
+ if (ast_json_array_append(json_items, ast_json_string_create(item))) {
+ ao2_cleanup(item);
ao2_iterator_destroy(&it);
return NULL;
}
@@ -500,7 +532,9 @@ static const char *capability2str(uint32_t capabilities)
}
}
-struct ast_json *ast_bridge_snapshot_to_json(const struct ast_bridge_snapshot *snapshot)
+struct ast_json *ast_bridge_snapshot_to_json(
+ const struct ast_bridge_snapshot *snapshot,
+ const struct stasis_message_sanitizer *sanitize)
{
RAII_VAR(struct ast_json *, json_bridge, NULL, ast_json_unref);
struct ast_json *json_channels;
@@ -509,8 +543,7 @@ struct ast_json *ast_bridge_snapshot_to_json(const struct ast_bridge_snapshot *s
return NULL;
}
- json_channels = container_to_json_array(snapshot->channels,
- (json_item_serializer_cb)ast_json_string_create);
+ json_channels = container_to_json_array(snapshot->channels, sanitize);
if (!json_channels) {
return NULL;
}
diff --git a/main/stasis_channels.c b/main/stasis_channels.c
index f178df35b..38aac982e 100644
--- a/main/stasis_channels.c
+++ b/main/stasis_channels.c
@@ -755,11 +755,15 @@ void ast_publish_channel_state(struct ast_channel *chan)
stasis_publish(ast_channel_topic(chan), message);
}
-struct ast_json *ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot)
+struct ast_json *ast_channel_snapshot_to_json(
+ const struct ast_channel_snapshot *snapshot,
+ const struct stasis_message_sanitizer *sanitize)
{
RAII_VAR(struct ast_json *, json_chan, NULL, ast_json_unref);
- if (snapshot == NULL) {
+ if (snapshot == NULL
+ || (sanitize && sanitize->channel_snapshot
+ && sanitize->channel_snapshot(snapshot))) {
return NULL;
}
@@ -817,8 +821,10 @@ int ast_channel_snapshot_caller_id_equal(
strcmp(old_snapshot->caller_name, new_snapshot->caller_name) == 0;
}
-static struct ast_json *channel_blob_to_json(struct stasis_message *message,
- const char *type)
+static struct ast_json *channel_blob_to_json(
+ struct stasis_message *message,
+ const char *type,
+ const struct stasis_message_sanitizer *sanitize)
{
RAII_VAR(struct ast_json *, out, NULL, ast_json_unref);
struct ast_channel_blob *channel_blob = stasis_message_data(message);
@@ -844,8 +850,13 @@ static struct ast_json *channel_blob_to_json(struct stasis_message *message,
/* For global channel messages, the snapshot is optional */
if (snapshot) {
- res |= ast_json_object_set(out, "channel",
- ast_channel_snapshot_to_json(snapshot));
+ struct ast_json *json_channel = ast_channel_snapshot_to_json(snapshot, sanitize);
+
+ if (!json_channel) {
+ return NULL;
+ }
+
+ res |= ast_json_object_set(out, "channel", json_channel);
}
if (res != 0) {
@@ -855,7 +866,9 @@ static struct ast_json *channel_blob_to_json(struct stasis_message *message,
return ast_json_ref(out);
}
-static struct ast_json *dtmf_end_to_json(struct stasis_message *message)
+static struct ast_json *dtmf_end_to_json(
+ struct stasis_message *message,
+ const struct stasis_message_sanitizer *sanitize)
{
struct ast_channel_blob *channel_blob = stasis_message_data(message);
struct ast_json *blob = channel_blob->blob;
@@ -863,43 +876,59 @@ static struct ast_json *dtmf_end_to_json(struct stasis_message *message)
const char *direction =
ast_json_string_get(ast_json_object_get(blob, "direction"));
const struct timeval *tv = stasis_message_timestamp(message);
+ struct ast_json *json_channel = ast_channel_snapshot_to_json(snapshot, sanitize);
/* Only present received DTMF end events as JSON */
if (strcasecmp("Received", direction) != 0) {
return NULL;
}
+ if (!json_channel) {
+ return NULL;
+ }
+
return ast_json_pack("{s: s, s: o, s: O, s: O, s: o}",
"type", "ChannelDtmfReceived",
"timestamp", ast_json_timeval(*tv, NULL),
"digit", ast_json_object_get(blob, "digit"),
"duration_ms", ast_json_object_get(blob, "duration_ms"),
- "channel", ast_channel_snapshot_to_json(snapshot));
+ "channel", json_channel);
}
-static struct ast_json *user_event_to_json(struct stasis_message *message)
+static struct ast_json *user_event_to_json(
+ struct stasis_message *message,
+ const struct stasis_message_sanitizer *sanitize)
{
struct ast_channel_blob *channel_blob = stasis_message_data(message);
struct ast_json *blob = channel_blob->blob;
struct ast_channel_snapshot *snapshot = channel_blob->snapshot;
const struct timeval *tv = stasis_message_timestamp(message);
+ struct ast_json *json_channel = ast_channel_snapshot_to_json(snapshot, sanitize);
+
+ if (!json_channel) {
+ return NULL;
+ }
return ast_json_pack("{s: s, s: o, s: O, s: O, s: o}",
"type", "ChannelUserevent",
"timestamp", ast_json_timeval(*tv, NULL),
"eventname", ast_json_object_get(blob, "eventname"),
"userevent", blob,
- "channel", ast_channel_snapshot_to_json(snapshot));
+ "channel", json_channel);
}
-static struct ast_json *varset_to_json(struct stasis_message *message)
+static struct ast_json *varset_to_json(
+ struct stasis_message *message,
+ const struct stasis_message_sanitizer *sanitize)
{
- return channel_blob_to_json(message, "ChannelVarset");
+ return channel_blob_to_json(message, "ChannelVarset", sanitize);
}
-static struct ast_json *hangup_request_to_json(struct stasis_message *message)
+static struct ast_json *hangup_request_to_json(
+ struct stasis_message *message,
+ const struct stasis_message_sanitizer *sanitize)
{
- return channel_blob_to_json(message, "ChannelHangupRequest");
+ return channel_blob_to_json(message, "ChannelHangupRequest", sanitize);
}
/*!
diff --git a/main/stasis_endpoints.c b/main/stasis_endpoints.c
index 096770a3d..81c4f15a3 100644
--- a/main/stasis_endpoints.c
+++ b/main/stasis_endpoints.c
@@ -237,7 +237,8 @@ static const char *endpoint_snapshot_get_id(struct stasis_message *message)
struct ast_json *ast_endpoint_snapshot_to_json(
- const struct ast_endpoint_snapshot *snapshot)
+ const struct ast_endpoint_snapshot *snapshot,
+ const struct stasis_message_sanitizer *sanitize)
{
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
struct ast_json *channel_array;
@@ -264,7 +265,14 @@ struct ast_json *ast_endpoint_snapshot_to_json(
channel_array = ast_json_object_get(json, "channel_ids");
ast_assert(channel_array != NULL);
for (i = 0; i < snapshot->num_channels; ++i) {
- int res = ast_json_array_append(channel_array,
+ int res;
+
+ if (sanitize && sanitize->channel_id
+ && sanitize->channel_id(snapshot->channel_ids[i])) {
+ continue;
+ }
+
+ res = ast_json_array_append(channel_array,
ast_json_string_create(snapshot->channel_ids[i]));
if (res != 0) {
return NULL;
diff --git a/main/stasis_message.c b/main/stasis_message.c
index b25d1f25a..240845aff 100644
--- a/main/stasis_message.c
+++ b/main/stasis_message.c
@@ -161,7 +161,9 @@ struct ast_manager_event_blob *stasis_message_to_ami(struct stasis_message *msg)
return INVOKE_VIRTUAL(to_ami, msg);
}
-struct ast_json *stasis_message_to_json(struct stasis_message *msg)
+struct ast_json *stasis_message_to_json(
+ struct stasis_message *msg,
+ struct stasis_message_sanitizer *sanitize)
{
- return INVOKE_VIRTUAL(to_json, msg);
+ return INVOKE_VIRTUAL(to_json, msg, sanitize);
}
diff --git a/res/ari/resource_bridges.c b/res/ari/resource_bridges.c
index 7c4fed29b..e09bea6b5 100644
--- a/res/ari/resource_bridges.c
+++ b/res/ari/resource_bridges.c
@@ -605,7 +605,7 @@ void ast_ari_bridges_get(struct ast_variable *headers,
}
ast_ari_response_ok(response,
- ast_bridge_snapshot_to_json(snapshot));
+ ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer()));
}
void ast_ari_bridges_destroy(struct ast_variable *headers,
@@ -656,7 +656,9 @@ void ast_ari_bridges_list(struct ast_variable *headers,
while ((obj = ao2_iterator_next(&i))) {
RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
struct ast_bridge_snapshot *snapshot = stasis_message_data(msg);
- if (ast_json_array_append(json, ast_bridge_snapshot_to_json(snapshot))) {
+ struct ast_json *json_bridge = ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
+
+ if (!json_bridge || ast_json_array_append(json, json_bridge)) {
ast_ari_response_alloc_failed(response);
return;
}
@@ -689,5 +691,5 @@ void ast_ari_bridges_create(struct ast_variable *headers,
}
ast_ari_response_ok(response,
- ast_bridge_snapshot_to_json(snapshot));
+ ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer()));
}
diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c
index dc0058fa5..75d56d924 100644
--- a/res/ari/resource_channels.c
+++ b/res/ari/resource_channels.c
@@ -593,7 +593,7 @@ void ast_ari_channels_get(struct ast_variable *headers,
ast_assert(snapshot != NULL);
ast_ari_response_ok(response,
- ast_channel_snapshot_to_json(snapshot));
+ ast_channel_snapshot_to_json(snapshot, NULL));
}
void ast_ari_channels_hangup(struct ast_variable *headers,
@@ -639,6 +639,7 @@ void ast_ari_channels_list(struct ast_variable *headers,
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
struct ao2_iterator i;
void *obj;
+ struct stasis_message_sanitizer *sanitize = stasis_app_get_sanitizer();
cache = ast_channel_cache();
if (!cache) {
@@ -661,14 +662,23 @@ void ast_ari_channels_list(struct ast_variable *headers,
return;
}
- i = ao2_iterator_init(snapshots, 0);
- while ((obj = ao2_iterator_next(&i))) {
+ for (i = ao2_iterator_init(snapshots, 0);
+ (obj = ao2_iterator_next(&i)); ao2_cleanup(obj)) {
RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
struct ast_channel_snapshot *snapshot = stasis_message_data(msg);
- int r = ast_json_array_append(
- json, ast_channel_snapshot_to_json(snapshot));
+ int r;
+
+ if (sanitize && sanitize->channel_snapshot
+ && sanitize->channel_snapshot(snapshot)) {
+ continue;
+ }
+
+ r = ast_json_array_append(
+ json, ast_channel_snapshot_to_json(snapshot, NULL));
if (r != 0) {
ast_ari_response_alloc_failed(response);
+ ao2_cleanup(obj);
+ ao2_iterator_destroy(&i);
return;
}
}
@@ -769,7 +779,7 @@ void ast_ari_channels_originate(struct ast_variable *headers,
stasis_app_subscribe(args->app, uris, 1, NULL);
}
- ast_ari_response_ok(response, ast_channel_snapshot_to_json(snapshot));
+ ast_ari_response_ok(response, ast_channel_snapshot_to_json(snapshot, NULL));
ast_channel_unref(chan);
}
diff --git a/res/ari/resource_endpoints.c b/res/ari/resource_endpoints.c
index 14f9e0576..c37f4968e 100644
--- a/res/ari/resource_endpoints.c
+++ b/res/ari/resource_endpoints.c
@@ -31,6 +31,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astobj2.h"
#include "asterisk/stasis.h"
+#include "asterisk/stasis_app.h"
#include "asterisk/stasis_endpoints.h"
#include "asterisk/channel.h"
@@ -69,8 +70,15 @@ void ast_ari_endpoints_list(struct ast_variable *headers,
while ((obj = ao2_iterator_next(&i))) {
RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
struct ast_endpoint_snapshot *snapshot = stasis_message_data(msg);
- int r = ast_json_array_append(
- json, ast_endpoint_snapshot_to_json(snapshot));
+ struct ast_json *json_endpoint = ast_endpoint_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
+ int r;
+
+ if (!json_endpoint) {
+ return;
+ }
+
+ r = ast_json_array_append(
+ json, json_endpoint);
if (r != 0) {
ast_ari_response_alloc_failed(response);
return;
@@ -121,14 +129,20 @@ void ast_ari_endpoints_list_by_tech(struct ast_variable *headers,
while ((obj = ao2_iterator_next(&i))) {
RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
struct ast_endpoint_snapshot *snapshot = stasis_message_data(msg);
+ struct ast_json *json_endpoint;
int r;
if (strcasecmp(args->tech, snapshot->tech) != 0) {
continue;
}
+ json_endpoint = ast_endpoint_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
+ if (!json_endpoint) {
+ continue;
+ }
+
r = ast_json_array_append(
- json, ast_endpoint_snapshot_to_json(snapshot));
+ json, json_endpoint);
if (r != 0) {
ast_ari_response_alloc_failed(response);
return;
@@ -151,7 +165,7 @@ void ast_ari_endpoints_get(struct ast_variable *headers,
return;
}
- json = ast_endpoint_snapshot_to_json(snapshot);
+ json = ast_endpoint_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
if (!json) {
ast_ari_response_alloc_failed(response);
return;
diff --git a/res/res_stasis.c b/res/res_stasis.c
index e5fe1f691..e21941210 100644
--- a/res/res_stasis.c
+++ b/res/res_stasis.c
@@ -627,6 +627,7 @@ static int send_start_msg(struct app *app, struct ast_channel *chan,
struct ast_json *json_args;
int i;
+ struct stasis_message_sanitizer *sanitize = stasis_app_get_sanitizer();
ast_assert(chan != NULL);
@@ -636,11 +637,16 @@ static int send_start_msg(struct app *app, struct ast_channel *chan,
return -1;
}
+ if (sanitize && sanitize->channel_snapshot
+ && sanitize->channel_snapshot(snapshot)) {
+ return 0;
+ }
+
msg = ast_json_pack("{s: s, s: o, s: [], s: o}",
"type", "StasisStart",
"timestamp", ast_json_timeval(ast_tvnow(), NULL),
"args",
- "channel", ast_channel_snapshot_to_json(snapshot));
+ "channel", ast_channel_snapshot_to_json(snapshot, NULL));
if (!msg) {
return -1;
}
@@ -665,6 +671,7 @@ static int send_end_msg(struct app *app, struct ast_channel *chan)
{
RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
+ struct stasis_message_sanitizer *sanitize = stasis_app_get_sanitizer();
ast_assert(chan != NULL);
@@ -674,10 +681,15 @@ static int send_end_msg(struct app *app, struct ast_channel *chan)
return -1;
}
+ if (sanitize && sanitize->channel_snapshot
+ && sanitize->channel_snapshot(snapshot)) {
+ return 0;
+ }
+
msg = ast_json_pack("{s: s, s: o, s: o}",
"type", "StasisEnd",
"timestamp", ast_json_timeval(ast_tvnow(), NULL),
- "channel", ast_channel_snapshot_to_json(snapshot));
+ "channel", ast_channel_snapshot_to_json(snapshot, NULL));
if (!msg) {
return -1;
}
@@ -1153,6 +1165,34 @@ static int unload_module(void)
return 0;
}
+/* \brief Sanitization callback for channel snapshots */
+static int channel_snapshot_sanitizer(const struct ast_channel_snapshot *snapshot)
+{
+ if (!snapshot || !(snapshot->tech_properties & AST_CHAN_TP_INTERNAL)) {
+ return 0;
+ }
+ return 1;
+}
+
+/* \brief Sanitization callback for channel unique IDs */
+static int channel_id_sanitizer(const char *id)
+{
+ RAII_VAR(struct ast_channel_snapshot *, snapshot, ast_channel_snapshot_get_latest(id), ao2_cleanup);
+
+ return channel_snapshot_sanitizer(snapshot);
+}
+
+/* \brief Sanitization callbacks for communication to Stasis applications */
+struct stasis_message_sanitizer app_sanitizer = {
+ .channel_id = channel_id_sanitizer,
+ .channel_snapshot = channel_snapshot_sanitizer,
+};
+
+struct stasis_message_sanitizer *stasis_app_get_sanitizer(void)
+{
+ return &app_sanitizer;
+}
+
static int load_module(void)
{
apps_registry = ao2_container_alloc(APPS_NUM_BUCKETS, app_hash, app_compare);
diff --git a/res/stasis/app.c b/res/stasis/app.c
index 99af6ee57..433d3adb5 100644
--- a/res/stasis/app.c
+++ b/res/stasis/app.c
@@ -276,7 +276,7 @@ static void sub_default_handler(void *data, struct stasis_subscription *sub,
}
/* By default, send any message that has a JSON representation */
- json = stasis_message_to_json(message);
+ json = stasis_message_to_json(message, stasis_app_get_sanitizer());
if (!json) {
return;
}
@@ -295,10 +295,16 @@ static struct ast_json *simple_channel_event(
struct ast_channel_snapshot *snapshot,
const struct timeval *tv)
{
+ struct ast_json *json_channel = ast_channel_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
+
+ if (!json_channel) {
+ return NULL;
+ }
+
return ast_json_pack("{s: s, s: o, s: o}",
"type", type,
"timestamp", ast_json_timeval(*tv, NULL),
- "channel", ast_channel_snapshot_to_json(snapshot));
+ "channel", json_channel);
}
static struct ast_json *channel_created_event(
@@ -312,12 +318,18 @@ static struct ast_json *channel_destroyed_event(
struct ast_channel_snapshot *snapshot,
const struct timeval *tv)
{
+ struct ast_json *json_channel = ast_channel_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
+
+ if (!json_channel) {
+ return NULL;
+ }
+
return ast_json_pack("{s: s, s: o, s: i, s: s, s: o}",
"type", "ChannelDestroyed",
"timestamp", ast_json_timeval(*tv, NULL),
"cause", snapshot->hangupcause,
"cause_txt", ast_cause2str(snapshot->hangupcause),
- "channel", ast_channel_snapshot_to_json(snapshot));
+ "channel", json_channel);
}
static struct ast_json *channel_state_change_event(
@@ -353,6 +365,7 @@ static struct ast_json *channel_dialplan(
const struct timeval *tv)
{
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+ struct ast_json *json_channel;
/* No Newexten event on cache clear or first event */
if (!old_snapshot || !new_snapshot) {
@@ -368,12 +381,17 @@ static struct ast_json *channel_dialplan(
return NULL;
}
+ json_channel = ast_channel_snapshot_to_json(new_snapshot, stasis_app_get_sanitizer());
+ if (!json_channel) {
+ return NULL;
+ }
+
return ast_json_pack("{s: s, s: o, s: s, s: s, s: o}",
"type", "ChannelDialplan",
"timestamp", ast_json_timeval(*tv, NULL),
"dialplan_app", new_snapshot->appl,
"dialplan_app_data", new_snapshot->data,
- "channel", ast_channel_snapshot_to_json(new_snapshot));
+ "channel", json_channel);
}
static struct ast_json *channel_callerid(
@@ -382,6 +400,7 @@ static struct ast_json *channel_callerid(
const struct timeval *tv)
{
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+ struct ast_json *json_channel;
/* No NewCallerid event on cache clear or first event */
if (!old_snapshot || !new_snapshot) {
@@ -392,13 +411,18 @@ static struct ast_json *channel_callerid(
return NULL;
}
+ json_channel = ast_channel_snapshot_to_json(new_snapshot, stasis_app_get_sanitizer());
+ if (!json_channel) {
+ return NULL;
+ }
+
return ast_json_pack("{s: s, s: o, s: i, s: s, s: o}",
"type", "ChannelCallerId",
"timestamp", ast_json_timeval(*tv, NULL),
"caller_presentation", new_snapshot->caller_pres,
"caller_presentation_txt", ast_describe_caller_presentation(
new_snapshot->caller_pres),
- "channel", ast_channel_snapshot_to_json(new_snapshot));
+ "channel", json_channel);
}
static channel_snapshot_monitor channel_monitors[] = {
@@ -448,10 +472,16 @@ static struct ast_json *simple_endpoint_event(
struct ast_endpoint_snapshot *snapshot,
const struct timeval *tv)
{
+ struct ast_json *json_endpoint = ast_endpoint_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
+
+ if (!json_endpoint) {
+ return NULL;
+ }
+
return ast_json_pack("{s: s, s: o, s: o}",
"type", type,
"timestamp", ast_json_timeval(*tv, NULL),
- "endpoint", ast_endpoint_snapshot_to_json(snapshot));
+ "endpoint", json_endpoint);
}
static void sub_endpoint_update_handler(void *data,
@@ -489,10 +519,15 @@ static struct ast_json *simple_bridge_event(
struct ast_bridge_snapshot *snapshot,
const struct timeval *tv)
{
+ struct ast_json *json_bridge = ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
+ if (!json_bridge) {
+ return NULL;
+ }
+
return ast_json_pack("{s: s, s: o, s: o}",
"type", type,
"timestamp", ast_json_timeval(*tv, NULL),
- "bridge", ast_bridge_snapshot_to_json(snapshot));
+ "bridge", json_bridge);
}
static void sub_bridge_update_handler(void *data,
@@ -521,7 +556,7 @@ static void sub_bridge_update_handler(void *data,
if (!new_snapshot) {
json = simple_bridge_event("BridgeDestroyed", old_snapshot, tv);
} else if (!old_snapshot) {
- json = simple_bridge_event("BridgeCreated", old_snapshot, tv);
+ json = simple_bridge_event("BridgeCreated", new_snapshot, tv);
}
if (!json) {