static struct ast_json *peerstatus_to_json(struct stasis_message *msg, const struct stasis_message_sanitizer *sanitize) { struct ast_endpoint_blob *obj = stasis_message_data(msg); struct ast_json *json_endpoint; struct ast_json *json_peer; struct ast_json *json_final; const struct timeval *tv = stasis_message_timestamp(msg); json_endpoint = ast_endpoint_snapshot_to_json(obj->snapshot, NULL); if (!json_endpoint) { return NULL; } json_peer = ast_json_object_create(); if (!json_peer) { ast_json_unref(json_endpoint); return NULL; } /* Copy all fields from the blob */ ast_json_object_update(json_peer, obj->blob); json_final = ast_json_pack("{s: s, s: o, s: o, s: o }", "type", "PeerStatusChange", "timestamp", ast_json_timeval(*tv, NULL), "endpoint", json_endpoint, "peer", json_peer); if (!json_final) { ast_json_unref(json_endpoint); ast_json_unref(json_peer); } return json_final; }
static void sub_bridge_update_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message) { struct ast_json *json = NULL; struct stasis_app *app = data; struct ast_bridge_snapshot_update *update; const struct timeval *tv; update = stasis_message_data(message); tv = stasis_message_timestamp(message); if (!update->new_snapshot) { json = simple_bridge_event("BridgeDestroyed", update->old_snapshot, tv); } else if (!update->old_snapshot) { json = simple_bridge_event("BridgeCreated", update->new_snapshot, tv); } else if (update->new_snapshot && update->old_snapshot && strcmp(update->new_snapshot->video_source_id, update->old_snapshot->video_source_id)) { json = simple_bridge_event("BridgeVideoSourceChanged", update->new_snapshot, tv); if (json && !ast_strlen_zero(update->old_snapshot->video_source_id)) { ast_json_object_set(json, "old_video_source_id", ast_json_string_create(update->old_snapshot->video_source_id)); } } if (json) { app_send(app, json); ast_json_unref(json); } if (!update->new_snapshot && update->old_snapshot) { unsubscribe(app, "bridge", update->old_snapshot->uniqueid, 1); } }
static struct ast_json *contactstatus_to_json(struct stasis_message *msg, const struct stasis_message_sanitizer *sanitize) { struct ast_endpoint_blob *obj = stasis_message_data(msg); struct ast_json *json_endpoint; struct ast_json *json_final; const struct timeval *tv = stasis_message_timestamp(msg); json_endpoint = ast_endpoint_snapshot_to_json(obj->snapshot, NULL); if (!json_endpoint) { return NULL; } json_final = ast_json_pack("{s: s, s: o, s: o, s: { s: s, s: s, s: s, s: s } } ", "type", "ContactStatusChange", "timestamp", ast_json_timeval(*tv, NULL), "endpoint", json_endpoint, "contact_info", "uri", ast_json_string_get(ast_json_object_get(obj->blob, "uri")), "contact_status", ast_json_string_get(ast_json_object_get(obj->blob, "contact_status")), "aor", ast_json_string_get(ast_json_object_get(obj->blob, "aor")), "roundtrip_usec", ast_json_string_get(ast_json_object_get(obj->blob, "roundtrip_usec"))); if (!json_final) { ast_json_unref(json_endpoint); } return json_final; }
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; struct ast_channel_snapshot *snapshot = channel_blob->snapshot; 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", json_channel); }
static void sub_endpoint_update_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message) { RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); struct stasis_app *app = data; struct stasis_cache_update *update; struct ast_endpoint_snapshot *new_snapshot; struct ast_endpoint_snapshot *old_snapshot; const struct timeval *tv; ast_assert(stasis_message_type(message) == stasis_cache_update_type()); update = stasis_message_data(message); ast_assert(update->type == ast_endpoint_snapshot_type()); new_snapshot = stasis_message_data(update->new_snapshot); old_snapshot = stasis_message_data(update->old_snapshot); if (new_snapshot) { tv = stasis_message_timestamp(update->new_snapshot); json = simple_endpoint_event("EndpointStateChange", new_snapshot, tv); if (!json) { return; } app_send(app, json); } if (!new_snapshot && old_snapshot) { unsubscribe(app, "endpoint", old_snapshot->id, 1); } }
static void sub_bridge_update_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message) { RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); struct stasis_app *app = data; struct stasis_cache_update *update; struct ast_bridge_snapshot *new_snapshot; struct ast_bridge_snapshot *old_snapshot; const struct timeval *tv; ast_assert(stasis_message_type(message) == stasis_cache_update_type()); update = stasis_message_data(message); ast_assert(update->type == ast_bridge_snapshot_type()); new_snapshot = stasis_message_data(update->new_snapshot); old_snapshot = stasis_message_data(update->old_snapshot); tv = update->new_snapshot ? stasis_message_timestamp(update->new_snapshot) : stasis_message_timestamp(message); if (!new_snapshot) { json = simple_bridge_event("BridgeDestroyed", old_snapshot, tv); } else if (!old_snapshot) { json = simple_bridge_event("BridgeCreated", new_snapshot, tv); } else if (new_snapshot && old_snapshot && strcmp(new_snapshot->video_source_id, old_snapshot->video_source_id)) { json = simple_bridge_event("BridgeVideoSourceChanged", new_snapshot, tv); if (json && !ast_strlen_zero(old_snapshot->video_source_id)) { ast_json_object_set(json, "old_video_source_id", ast_json_string_create(old_snapshot->video_source_id)); } } if (json) { app_send(app, json); } if (!new_snapshot && old_snapshot) { unsubscribe(app, "bridge", old_snapshot->uniqueid, 1); } }
static void sub_channel_update_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message) { struct stasis_app *app = data; struct stasis_cache_update *update; struct ast_channel_snapshot *new_snapshot; struct ast_channel_snapshot *old_snapshot; const struct timeval *tv; int i; ast_assert(stasis_message_type(message) == stasis_cache_update_type()); update = stasis_message_data(message); ast_assert(update->type == ast_channel_snapshot_type()); new_snapshot = stasis_message_data(update->new_snapshot); old_snapshot = stasis_message_data(update->old_snapshot); /* Pull timestamp from the new snapshot, or from the update message * when there isn't one. */ tv = update->new_snapshot ? stasis_message_timestamp(update->new_snapshot) : stasis_message_timestamp(message); for (i = 0; i < ARRAY_LEN(channel_monitors); ++i) { RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref); msg = channel_monitors[i](old_snapshot, new_snapshot, tv); if (msg) { app_send(app, msg); } } if (!new_snapshot && old_snapshot) { unsubscribe(app, "channel", old_snapshot->uniqueid, 1); } }
/*! \internal \brief convert multi object blob to ari json */ static struct ast_json *multi_user_event_to_json( struct stasis_message *message, const struct stasis_message_sanitizer *sanitize) { RAII_VAR(struct ast_json *, out, NULL, ast_json_unref); struct ast_multi_object_blob *multi = stasis_message_data(message); struct ast_json *blob = multi->blob; const struct timeval *tv = stasis_message_timestamp(message); enum stasis_user_multi_object_snapshot_type type; int i; out = ast_json_object_create(); if (!out) { return NULL; } ast_json_object_set(out, "type", ast_json_string_create("ChannelUserevent")); ast_json_object_set(out, "timestamp", ast_json_timeval(*tv, NULL)); ast_json_object_set(out, "eventname", ast_json_string_create(ast_json_string_get((ast_json_object_get(blob, "eventname"))))); ast_json_object_set(out, "userevent", ast_json_deep_copy(blob)); for (type = 0; type < STASIS_UMOS_MAX; ++type) { for (i = 0; i < AST_VECTOR_SIZE(&multi->snapshots[type]); ++i) { struct ast_json *json_object = NULL; char *name = NULL; void *snapshot = AST_VECTOR_GET(&multi->snapshots[type], i); switch (type) { case STASIS_UMOS_CHANNEL: json_object = ast_channel_snapshot_to_json(snapshot, sanitize); name = "channel"; break; case STASIS_UMOS_BRIDGE: json_object = ast_bridge_snapshot_to_json(snapshot, sanitize); name = "bridge"; break; case STASIS_UMOS_ENDPOINT: json_object = ast_endpoint_snapshot_to_json(snapshot, sanitize); name = "endpoint"; break; } if (json_object) { ast_json_object_set(out, name, json_object); } } } return ast_json_ref(out); }
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); struct ast_json *blob = channel_blob->blob; struct ast_channel_snapshot *snapshot = channel_blob->snapshot; const struct timeval *tv = stasis_message_timestamp(message); int res = 0; if (blob == NULL || ast_json_is_null(blob)) { out = ast_json_object_create(); } else { /* blobs are immutable, so shallow copies are fine */ out = ast_json_copy(blob); } if (!out) { return NULL; } res |= ast_json_object_set(out, "type", ast_json_string_create(type)); res |= ast_json_object_set(out, "timestamp", ast_json_timeval(*tv, NULL)); /* For global channel messages, the snapshot is optional */ if (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) { return NULL; } return ast_json_ref(out); }
static struct ast_json *dial_to_json( struct stasis_message *message, const struct stasis_message_sanitizer *sanitize) { struct ast_multi_channel_blob *payload = stasis_message_data(message); struct ast_json *blob = ast_multi_channel_blob_get_json(payload); struct ast_json *caller_json = ast_channel_snapshot_to_json(ast_multi_channel_blob_get_channel(payload, "caller"), sanitize); struct ast_json *peer_json = ast_channel_snapshot_to_json(ast_multi_channel_blob_get_channel(payload, "peer"), sanitize); struct ast_json *forwarded_json = ast_channel_snapshot_to_json(ast_multi_channel_blob_get_channel(payload, "forwarded"), sanitize); struct ast_json *json; const struct timeval *tv = stasis_message_timestamp(message); int res = 0; json = ast_json_pack("{s: s, s: o, s: O, s: O, s: O}", "type", "Dial", "timestamp", ast_json_timeval(*tv, NULL), "dialstatus", ast_json_object_get(blob, "dialstatus"), "forward", ast_json_object_get(blob, "forward"), "dialstring", ast_json_object_get(blob, "dialstring")); if (!json) { ast_json_unref(caller_json); ast_json_unref(peer_json); ast_json_unref(forwarded_json); return NULL; } if (caller_json) { res |= ast_json_object_set(json, "caller", caller_json); } if (peer_json) { res |= ast_json_object_set(json, "peer", peer_json); } if (forwarded_json) { res |= ast_json_object_set(json, "forwarded", forwarded_json); } if (res) { ast_json_unref(json); return NULL; } return json; }
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", json_channel); }
/*! * \brief Router callback for \ref stasis_cache_update messages. * \param data Data pointer given when added to router. * \param sub This subscription. * \param topic The topic the message was posted to. This is not necessarily the * topic you subscribed to, since messages may be forwarded between * topics. * \param message The message itself. */ static void updates(void *data, struct stasis_subscription *sub, struct stasis_message *message) { /* Since this came from a message router, we know the type of the * message. We can cast the data without checking its type. */ struct stasis_cache_update *update = stasis_message_data(message); /* We're only interested in channel snapshots, so check the type * of the underlying message. */ if (ast_channel_snapshot_type() != update->type) { return; } /* There are three types of cache updates. * !old && new -> Initial cache entry * old && new -> Updated cache entry * old && !new -> Cache entry removed. */ if (!update->old_snapshot && update->new_snapshot) { /* Initial cache entry; count a channel creation */ ast_statsd_log("channels.count", AST_STATSD_COUNTER, 1); } else if (update->old_snapshot && !update->new_snapshot) { /* Cache entry removed. Compute the age of the channel and post * that, as well as decrementing the channel count. */ struct ast_channel_snapshot *last; int64_t age; last = stasis_message_data(update->old_snapshot); age = ast_tvdiff_ms(*stasis_message_timestamp(message), last->creationtime); ast_statsd_log("channels.calltime", AST_STATSD_TIMER, age); /* And decrement the channel count */ ast_statsd_log("channels.count", AST_STATSD_COUNTER, -1); } }
static void sub_channel_update_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message) { struct stasis_app *app = data; struct ast_channel_snapshot_update *update = stasis_message_data(message); int i; for (i = 0; i < ARRAY_LEN(channel_monitors); ++i) { struct ast_json *msg; msg = channel_monitors[i](update->old_snapshot, update->new_snapshot, stasis_message_timestamp(message)); if (msg) { app_send(app, msg); ast_json_unref(msg); } } if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) { unsubscribe(app, "channel", update->new_snapshot->base->uniqueid, 1); } }