]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
bridging: Add creation timestamps
authorsungtae kim <sungtae@messagebird.com>
Fri, 8 Feb 2019 21:32:18 +0000 (22:32 +0100)
committersungtae kim <sungtae@messagebird.com>
Sun, 3 Mar 2019 13:10:28 +0000 (14:10 +0100)
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

include/asterisk/bridge.h
include/asterisk/stasis_bridges.h
main/bridge.c
main/stasis_bridges.c
res/ari/ari_model_validators.c
res/ari/ari_model_validators.h
rest-api/api-docs/bridges.json

index e7f9ca6d0553b4baa06cae2d71cdbdc6381fef1f..6349a8cf2e4f1af33ada9518b927f51c2292ab05 100644 (file)
@@ -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. */
index 05d356cc2c144a7d4cbb6d07f442dc100e68b8df..e2e49c5b70b3571327a00567cc304cd243d3b6b5 100644 (file)
@@ -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;
 };
 
 /*!
index 17e25b6996e253b7893500139138fadb954b8046..fcc96ef3957f4e565747c6356fdd822e2e78f7db 100644 (file)
@@ -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, "<unknown>"),
-                       S_OR(snapshot->technology, "<unknown>"));
+                       S_OR(snapshot->technology, "<unknown>"),
+                       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, "<unknown>"));
        ast_cli(a->fd, "Technology: %s\n", S_OR(snapshot->technology, "<unknown>"));
+       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;
index 0de41973fdcdf64cdbe029aa1e4c3200cb97aa8b..383242a816eca4e2791409035bedd2174b39f30c 100644 (file)
@@ -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;
index 7bd3c26b1092316e1692634974c65f4b17bb512a..17952b04958678f7c70253cf94d5486e80e397a9 100644 (file)
@@ -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;
index ed86ae83bde76d007bb3efd0d413ff7e1d244450..4fedddf440bc3efb1bf138e95fdcf6ecc2ffa4ec 100644 (file)
@@ -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)
index 3eefa16df7f837ab0f7e3747f241d428a2c5ffe6..78bd3afadf55bd019ade3aacd11ee93a9dc1f3d9 100644 (file)
                                        "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"
                                }
                        }
                }