From: sungtae kim Date: Fri, 8 Feb 2019 21:32:18 +0000 (+0100) Subject: bridging: Add creation timestamps X-Git-Tag: 13.26.0-rc1~29^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4dd4dbd;p=thirdparty%2Fasterisk.git bridging: Add creation timestamps This small feature will help to checking the bridge's status to figure out which bridge is in old/zombie or not. Also added detail items for the 'bridge show *' cli to provide more detail info. And added creation item to the ARI as well. ASTERISK-28279 Change-Id: I460238c488eca4d216b9176576211cb03286e040 --- diff --git a/include/asterisk/bridge.h b/include/asterisk/bridge.h index e7f9ca6d05..6349a8cf2e 100644 --- a/include/asterisk/bridge.h +++ b/include/asterisk/bridge.h @@ -321,6 +321,8 @@ struct ast_bridge { /*! Immutable bridge UUID. */ AST_STRING_FIELD(uniqueid); ); + /*! The time of bridge creation */ + struct timeval creationtime; }; /*! \brief Bridge base class virtual method table. */ diff --git a/include/asterisk/stasis_bridges.h b/include/asterisk/stasis_bridges.h index 05d356cc2c..e2e49c5b70 100644 --- a/include/asterisk/stasis_bridges.h +++ b/include/asterisk/stasis_bridges.h @@ -62,6 +62,8 @@ struct ast_bridge_snapshot { enum ast_bridge_video_mode_type video_mode; /*! Unique ID of the channel providing video, if one exists */ AST_STRING_FIELD_EXTENDED(video_source_id); + /*! The time of bridge creation */ + struct timeval creationtime; }; /*! diff --git a/main/bridge.c b/main/bridge.c index 17e25b6996..fcc96ef395 100644 --- a/main/bridge.c +++ b/main/bridge.c @@ -813,6 +813,8 @@ struct ast_bridge *bridge_base_init(struct ast_bridge *self, uint32_t capabiliti return NULL; } + self->creationtime = ast_tvnow(); + return self; } @@ -5012,8 +5014,8 @@ static char *complete_bridge_stasis(const char *word) static char *handle_bridge_show_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { -#define FORMAT_HDR "%-36s %5s %-15s %s\n" -#define FORMAT_ROW "%-36s %5u %-15s %s\n" +#define FORMAT_HDR "%-36s %5s %-15s %-15s %s\n" +#define FORMAT_ROW "%-36s %5u %-15s %-15s %s\n" RAII_VAR(struct ao2_container *, cached_bridges, NULL, ao2_cleanup); struct ao2_iterator iter; @@ -5036,17 +5038,21 @@ static char *handle_bridge_show_all(struct ast_cli_entry *e, int cmd, struct ast return CLI_SUCCESS; } - ast_cli(a->fd, FORMAT_HDR, "Bridge-ID", "Chans", "Type", "Technology"); + ast_cli(a->fd, FORMAT_HDR, "Bridge-ID", "Chans", "Type", "Technology", "Duration"); iter = ao2_iterator_init(cached_bridges, 0); for (; (msg = ao2_iterator_next(&iter)); ao2_ref(msg, -1)) { struct ast_bridge_snapshot *snapshot = stasis_message_data(msg); + char print_time[32]; + + ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->creationtime.tv_sec, print_time, sizeof(print_time)); ast_cli(a->fd, FORMAT_ROW, snapshot->uniqueid, snapshot->num_channels, S_OR(snapshot->subclass, ""), - S_OR(snapshot->technology, "")); + S_OR(snapshot->technology, ""), + print_time); } ao2_iterator_destroy(&iter); return CLI_SUCCESS; @@ -5078,6 +5084,7 @@ static char *handle_bridge_show_specific(struct ast_cli_entry *e, int cmd, struc { RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); struct ast_bridge_snapshot *snapshot; + char print_time[32]; switch (cmd) { case CLI_INIT: @@ -5104,10 +5111,18 @@ static char *handle_bridge_show_specific(struct ast_cli_entry *e, int cmd, struc } snapshot = stasis_message_data(msg); + ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->creationtime.tv_sec, print_time, sizeof(print_time)); + ast_cli(a->fd, "Id: %s\n", snapshot->uniqueid); ast_cli(a->fd, "Type: %s\n", S_OR(snapshot->subclass, "")); ast_cli(a->fd, "Technology: %s\n", S_OR(snapshot->technology, "")); + ast_cli(a->fd, "Subclass: %s\n", snapshot->subclass); + ast_cli(a->fd, "Creator: %s\n", snapshot->creator); + ast_cli(a->fd, "Name: %s\n", snapshot->name); + ast_cli(a->fd, "Video-Source-Id: %s\n", snapshot->video_source_id); ast_cli(a->fd, "Num-Channels: %u\n", snapshot->num_channels); + ast_cli(a->fd, "Num-Active: %u\n", snapshot->num_active); + ast_cli(a->fd, "Duration: %s\n", print_time); ao2_callback(snapshot->channels, OBJ_NODATA, bridge_show_specific_print_channel, a); return CLI_SUCCESS; diff --git a/main/stasis_bridges.c b/main/stasis_bridges.c index 0de41973fd..383242a816 100644 --- a/main/stasis_bridges.c +++ b/main/stasis_bridges.c @@ -277,6 +277,7 @@ struct ast_bridge_snapshot *ast_bridge_snapshot_create(struct ast_bridge *bridge snapshot->capabilities = bridge->technology->capabilities; snapshot->num_channels = bridge->num_channels; snapshot->num_active = bridge->num_active; + snapshot->creationtime = bridge->creationtime; snapshot->video_mode = bridge->softmix.video_mode.mode; if (snapshot->video_mode == AST_BRIDGE_VIDEO_MODE_SINGLE_SRC && bridge->softmix.video_mode.mode_data.single_src_data.chan_vsrc) { @@ -610,7 +611,7 @@ struct ast_json *ast_bridge_snapshot_to_json( return NULL; } - json_bridge = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o, s: s}", + json_bridge = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o, s: o, s: s}", "id", snapshot->uniqueid, "technology", snapshot->technology, "bridge_type", capability2str(snapshot->capabilities), @@ -618,6 +619,7 @@ struct ast_json *ast_bridge_snapshot_to_json( "creator", snapshot->creator, "name", snapshot->name, "channels", json_channels, + "creationtime", ast_json_timeval(snapshot->creationtime, NULL), "video_mode", ast_bridge_video_mode_to_string(snapshot->video_mode)); if (!json_bridge) { return NULL; diff --git a/res/ari/ari_model_validators.c b/res/ari/ari_model_validators.c index 7bd3c26b10..17952b0495 100644 --- a/res/ari/ari_model_validators.c +++ b/res/ari/ari_model_validators.c @@ -1353,6 +1353,7 @@ int ast_ari_validate_bridge(struct ast_json *json) int has_bridge_class = 0; int has_bridge_type = 0; int has_channels = 0; + int has_creationtime = 0; int has_creator = 0; int has_id = 0; int has_name = 0; @@ -1390,6 +1391,16 @@ int ast_ari_validate_bridge(struct ast_json *json) res = 0; } } else + if (strcmp("creationtime", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_creationtime = 1; + prop_is_valid = ast_ari_validate_date( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI Bridge field creationtime failed validation\n"); + res = 0; + } + } else if (strcmp("creator", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_creator = 1; @@ -1471,6 +1482,11 @@ int ast_ari_validate_bridge(struct ast_json *json) res = 0; } + if (!has_creationtime) { + ast_log(LOG_ERROR, "ARI Bridge missing required field creationtime\n"); + res = 0; + } + if (!has_creator) { ast_log(LOG_ERROR, "ARI Bridge missing required field creator\n"); res = 0; diff --git a/res/ari/ari_model_validators.h b/res/ari/ari_model_validators.h index ed86ae83bd..4fedddf440 100644 --- a/res/ari/ari_model_validators.h +++ b/res/ari/ari_model_validators.h @@ -1470,6 +1470,7 @@ ari_validator ast_ari_validate_application_fn(void); * - bridge_class: string (required) * - bridge_type: string (required) * - channels: List[string] (required) + * - creationtime: Date (required) * - creator: string (required) * - id: string (required) * - name: string (required) diff --git a/rest-api/api-docs/bridges.json b/rest-api/api-docs/bridges.json index 3eefa16df7..78bd3afadf 100644 --- a/rest-api/api-docs/bridges.json +++ b/rest-api/api-docs/bridges.json @@ -731,6 +731,11 @@ "type": "string", "description": "The ID of the channel that is the source of video in this bridge, if one exists.", "required": false + }, + "creationtime": { + "required": true, + "type": "Date", + "description": "Timestamp when bridge was created" } } }