<p>sungtae kim has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/11200">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res/res_ari: Added ARI resource /ari/channels/{channelId}/rtp_statistics<br><br>Added ARI resource for channel statistics.<br>GET /ari/channels/{channelId}/rtp_statistics : It returns given<br>channel's rtp statistics detail.<br><br>ASTERISK-28320<br><br>Change-Id: I4343eec070438cec13f2a4f22e7fd9e574381376<br>---<br>M include/asterisk/rtp_engine.h<br>M main/rtp_engine.c<br>M res/ari/ari_model_validators.c<br>M res/ari/ari_model_validators.h<br>M res/ari/resource_channels.c<br>M res/ari/resource_channels.h<br>M res/res_ari_channels.c<br>M rest-api/api-docs/channels.json<br>8 files changed, 861 insertions(+), 2 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/00/11200/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h</span><br><span>index 4b25e30..75300cc 100644</span><br><span>--- a/include/asterisk/rtp_engine.h</span><br><span>+++ b/include/asterisk/rtp_engine.h</span><br><span>@@ -2382,6 +2382,20 @@</span><br><span> struct stasis_message_type *ast_rtp_rtcp_received_type(void);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Convert given stat instance into json format</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param stats</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval A json format stat</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_json *ast_rtp_convert_stats_json(const struct ast_rtp_instance_stats *stats);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Retrieve statistics about an RTP instance in json format</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval json object of stats</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_json *ast_rtp_instance_get_stats_all_json(struct ast_rtp_instance *instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span>  * \since 12</span><br><span>  * \brief \ref stasis topic for RTP and RTCP related messages</span><br><span>  *</span><br><span>diff --git a/main/rtp_engine.c b/main/rtp_engine.c</span><br><span>index 9b197d7..e1a1e0b 100644</span><br><span>--- a/main/rtp_engine.c</span><br><span>+++ b/main/rtp_engine.c</span><br><span>@@ -258,6 +258,20 @@</span><br><span> </span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Set given json object into target with name</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param target Target json.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param name key of given object.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param obj Json value will be set.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#define SET_AST_JSON_OBJ(target, name, obj) ({                                      \</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_json *j_tmp = obj;                                           \</span><br><span style="color: hsl(120, 100%, 40%);">+     if (j_tmp) {                                            \</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_json_object_set(target, name, j_tmp);                                               \</span><br><span style="color: hsl(120, 100%, 40%);">+     }                                               \</span><br><span style="color: hsl(120, 100%, 40%);">+})</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span>  * \internal</span><br><span>  * \brief Destructor for \c ast_rtp_payload_type</span><br><span>  */</span><br><span>@@ -2800,3 +2814,77 @@</span><br><span> {</span><br><span>        rtp->last_rx = time;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_json *ast_rtp_convert_stats_json(const struct ast_rtp_instance_stats *stats)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_json *j_res;</span><br><span style="color: hsl(120, 100%, 40%);">+       int ret;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    j_res = ast_json_object_create();</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!j_res) {</span><br><span style="color: hsl(120, 100%, 40%);">+         return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* set mandatory items */</span><br><span style="color: hsl(120, 100%, 40%);">+     ret = ast_json_object_set(j_res, "txcount", ast_json_integer_create(stats->txcount));</span><br><span style="color: hsl(120, 100%, 40%);">+    ret |= ast_json_object_set(j_res, "rxcount", ast_json_integer_create(stats->rxcount));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ret |= ast_json_object_set(j_res, "txploss", ast_json_integer_create(stats->txploss));</span><br><span style="color: hsl(120, 100%, 40%);">+   ret |= ast_json_object_set(j_res, "rxploss", ast_json_integer_create(stats->rxploss));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ret |= ast_json_object_set(j_res, "local_ssrc", ast_json_integer_create(stats->local_ssrc));</span><br><span style="color: hsl(120, 100%, 40%);">+     ret |= ast_json_object_set(j_res, "remote_ssrc", ast_json_integer_create(stats->remote_ssrc));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ret |= ast_json_object_set(j_res, "txoctetcount", ast_json_integer_create(stats->txoctetcount));</span><br><span style="color: hsl(120, 100%, 40%);">+ ret |= ast_json_object_set(j_res, "rxoctetcount", ast_json_integer_create(stats->rxoctetcount));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ret |= ast_json_object_set(j_res, "channel_uniqueid", ast_json_string_create(stats->channel_uniqueid));</span><br><span style="color: hsl(120, 100%, 40%);">+  if (ret) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_WARNING, "Could not create rtp statistics info. channel: %s\n", stats->channel_uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_json_unref(j_res);</span><br><span style="color: hsl(120, 100%, 40%);">+                return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* set other items */</span><br><span style="color: hsl(120, 100%, 40%);">+ SET_AST_JSON_OBJ(j_res, "txjitter", ast_json_real_create(stats->txjitter));</span><br><span style="color: hsl(120, 100%, 40%);">+      SET_AST_JSON_OBJ(j_res, "rxjitter", ast_json_real_create(stats->rxjitter));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    SET_AST_JSON_OBJ(j_res, "remote_maxjitter", ast_json_real_create(stats->remote_maxjitter));</span><br><span style="color: hsl(120, 100%, 40%);">+      SET_AST_JSON_OBJ(j_res, "remote_minjitter", ast_json_real_create(stats->remote_minjitter));</span><br><span style="color: hsl(120, 100%, 40%);">+      SET_AST_JSON_OBJ(j_res, "remote_normdevjitter", ast_json_real_create(stats->remote_normdevjitter));</span><br><span style="color: hsl(120, 100%, 40%);">+      SET_AST_JSON_OBJ(j_res, "remote_stdevjitter", ast_json_real_create(stats->remote_stdevjitter));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        SET_AST_JSON_OBJ(j_res, "local_maxjitter", ast_json_real_create(stats->local_maxjitter));</span><br><span style="color: hsl(120, 100%, 40%);">+        SET_AST_JSON_OBJ(j_res, "local_minjitter", ast_json_real_create(stats->local_minjitter));</span><br><span style="color: hsl(120, 100%, 40%);">+        SET_AST_JSON_OBJ(j_res, "local_normdevjitter", ast_json_real_create(stats->local_normdevjitter));</span><br><span style="color: hsl(120, 100%, 40%);">+        SET_AST_JSON_OBJ(j_res, "local_stdevjitter", ast_json_real_create(stats->local_stdevjitter));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  SET_AST_JSON_OBJ(j_res, "remote_maxrxploss", ast_json_real_create(stats->remote_maxrxploss));</span><br><span style="color: hsl(120, 100%, 40%);">+    SET_AST_JSON_OBJ(j_res, "remote_minrxploss", ast_json_real_create(stats->remote_minrxploss));</span><br><span style="color: hsl(120, 100%, 40%);">+    SET_AST_JSON_OBJ(j_res, "remote_normdevrxploss", ast_json_real_create(stats->remote_normdevrxploss));</span><br><span style="color: hsl(120, 100%, 40%);">+    SET_AST_JSON_OBJ(j_res, "remote_stdevrxploss", ast_json_real_create(stats->remote_stdevrxploss));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      SET_AST_JSON_OBJ(j_res, "local_maxrxploss", ast_json_real_create(stats->local_maxrxploss));</span><br><span style="color: hsl(120, 100%, 40%);">+      SET_AST_JSON_OBJ(j_res, "local_minrxploss", ast_json_real_create(stats->local_minrxploss));</span><br><span style="color: hsl(120, 100%, 40%);">+      SET_AST_JSON_OBJ(j_res, "local_normdevrxploss", ast_json_real_create(stats->local_normdevrxploss));</span><br><span style="color: hsl(120, 100%, 40%);">+      SET_AST_JSON_OBJ(j_res, "local_stdevrxploss", ast_json_real_create(stats->local_stdevrxploss));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        SET_AST_JSON_OBJ(j_res, "rtt", ast_json_real_create(stats->rtt));</span><br><span style="color: hsl(120, 100%, 40%);">+        SET_AST_JSON_OBJ(j_res, "maxrtt", ast_json_real_create(stats->maxrtt));</span><br><span style="color: hsl(120, 100%, 40%);">+  SET_AST_JSON_OBJ(j_res, "minrtt", ast_json_real_create(stats->minrtt));</span><br><span style="color: hsl(120, 100%, 40%);">+  SET_AST_JSON_OBJ(j_res, "normdevrtt", ast_json_real_create(stats->normdevrtt));</span><br><span style="color: hsl(120, 100%, 40%);">+  SET_AST_JSON_OBJ(j_res, "stdevrtt", ast_json_real_create(stats->stdevrtt));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return j_res;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_json *ast_rtp_instance_get_stats_all_json(struct ast_rtp_instance *instance)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_rtp_instance_stats stats = {0,};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if(ast_rtp_instance_get_stats(instance, &stats, AST_RTP_INSTANCE_STAT_ALL)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return ast_rtp_convert_stats_json(&stats);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/res/ari/ari_model_validators.c b/res/ari/ari_model_validators.c</span><br><span>index 071a24d..0b75f2b 100644</span><br><span>--- a/res/ari/ari_model_validators.c</span><br><span>+++ b/res/ari/ari_model_validators.c</span><br><span>@@ -1346,6 +1346,379 @@</span><br><span>     return ast_ari_validate_dialplan_cep;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int ast_ari_validate_rtpstat(struct ast_json *json)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int res = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_json_iter *iter;</span><br><span style="color: hsl(120, 100%, 40%);">+   int has_channel_uniqueid = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int has_local_ssrc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       int has_remote_ssrc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      int has_rxcount = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  int has_rxoctetcount = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     int has_rxploss = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  int has_txcount = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  int has_txoctetcount = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     int has_txploss = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if (strcmp("channel_uniqueid", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    has_channel_uniqueid = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                     prop_is_valid = ast_ari_validate_string(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field channel_uniqueid failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                               res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("local_maxjitter", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field local_maxjitter failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                                res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("local_maxrxploss", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field local_maxrxploss failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                               res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("local_minjitter", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field local_minjitter failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                                res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("local_minrxploss", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field local_minrxploss failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                               res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("local_normdevjitter", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field local_normdevjitter failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                            res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("local_normdevrxploss", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field local_normdevrxploss failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                           res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("local_ssrc", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    has_local_ssrc = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                   prop_is_valid = ast_ari_validate_int(</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field local_ssrc failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                             res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("local_stdevjitter", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field local_stdevjitter failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                              res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("local_stdevrxploss", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field local_stdevrxploss failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                             res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("maxrtt", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field maxrtt failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                         res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("minrtt", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field minrtt failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                         res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("normdevrtt", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field normdevrtt failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                             res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("remote_maxjitter", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field remote_maxjitter failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                               res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("remote_maxrxploss", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field remote_maxrxploss failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                              res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("remote_minjitter", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field remote_minjitter failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                               res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("remote_minrxploss", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field remote_minrxploss failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                              res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("remote_normdevjitter", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field remote_normdevjitter failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                           res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("remote_normdevrxploss", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field remote_normdevrxploss failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                          res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("remote_ssrc", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    has_remote_ssrc = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                  prop_is_valid = ast_ari_validate_int(</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field remote_ssrc failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                            res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("remote_stdevjitter", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field remote_stdevjitter failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                             res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("remote_stdevrxploss", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field remote_stdevrxploss failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                            res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("rtt", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field rtt failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                            res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("rxcount", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    has_rxcount = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                      prop_is_valid = ast_ari_validate_int(</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field rxcount failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                                res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("rxjitter", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field rxjitter failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                               res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("rxoctetcount", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    has_rxoctetcount = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                 prop_is_valid = ast_ari_validate_int(</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field rxoctetcount failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                           res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("rxploss", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    has_rxploss = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                      prop_is_valid = ast_ari_validate_int(</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field rxploss failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                                res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("stdevrtt", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field stdevrtt failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                               res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("txcount", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    has_txcount = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                      prop_is_valid = ast_ari_validate_int(</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field txcount failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                                res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("txjitter", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    prop_is_valid = ast_ari_validate_double(</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field txjitter failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                               res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("txoctetcount", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    has_txoctetcount = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                 prop_is_valid = ast_ari_validate_int(</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field txoctetcount failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                           res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp("txploss", ast_json_object_iter_key(iter)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       int prop_is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+                    has_txploss = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                      prop_is_valid = ast_ari_validate_int(</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_json_object_iter_value(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (!prop_is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "ARI RTPstat field txploss failed validation\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                                res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                {</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_log(LOG_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                            "ARI RTPstat has undocumented field %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                          ast_json_object_iter_key(iter));</span><br><span style="color: hsl(120, 100%, 40%);">+                      res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!has_channel_uniqueid) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_ERROR, "ARI RTPstat missing required field channel_uniqueid\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!has_local_ssrc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_log(LOG_ERROR, "ARI RTPstat missing required field local_ssrc\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!has_remote_ssrc) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(LOG_ERROR, "ARI RTPstat missing required field remote_ssrc\n");</span><br><span style="color: hsl(120, 100%, 40%);">+             res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!has_rxcount) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_log(LOG_ERROR, "ARI RTPstat missing required field rxcount\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!has_rxoctetcount) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(LOG_ERROR, "ARI RTPstat missing required field rxoctetcount\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!has_rxploss) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_log(LOG_ERROR, "ARI RTPstat missing required field rxploss\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!has_txcount) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_log(LOG_ERROR, "ARI RTPstat missing required field txcount\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!has_txoctetcount) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(LOG_ERROR, "ARI RTPstat missing required field txoctetcount\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!has_txploss) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_log(LOG_ERROR, "ARI RTPstat missing required field txploss\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return res;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ari_validator ast_ari_validate_rtpstat_fn(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  return ast_ari_validate_rtpstat;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int ast_ari_validate_bridge(struct ast_json *json)</span><br><span> {</span><br><span>     int res = 1;</span><br><span>diff --git a/res/ari/ari_model_validators.h b/res/ari/ari_model_validators.h</span><br><span>index 54e852f..e5c803a 100644</span><br><span>--- a/res/ari/ari_model_validators.h</span><br><span>+++ b/res/ari/ari_model_validators.h</span><br><span>@@ -479,6 +479,24 @@</span><br><span> ari_validator ast_ari_validate_dialplan_cep_fn(void);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Validator for RTPstat.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * A statistics of a RTP.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param json JSON object to validate.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns True (non-zero) if valid.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns False (zero) if invalid.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_ari_validate_rtpstat(struct ast_json *json);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Function pointer to ast_ari_validate_rtpstat().</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See \ref ast_ari_model_validators.h for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ari_validator ast_ari_validate_rtpstat_fn(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span>  * \brief Validator for Bridge.</span><br><span>  *</span><br><span>  * The merging of media from one or more channels.</span><br><span>@@ -1484,6 +1502,39 @@</span><br><span>  * - context: string (required)</span><br><span>  * - exten: string (required)</span><br><span>  * - priority: long (required)</span><br><span style="color: hsl(120, 100%, 40%);">+ * RTPstat</span><br><span style="color: hsl(120, 100%, 40%);">+ * - channel_uniqueid: string (required)</span><br><span style="color: hsl(120, 100%, 40%);">+ * - local_maxjitter: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - local_maxrxploss: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - local_minjitter: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - local_minrxploss: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - local_normdevjitter: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - local_normdevrxploss: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - local_ssrc: int (required)</span><br><span style="color: hsl(120, 100%, 40%);">+ * - local_stdevjitter: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - local_stdevrxploss: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - maxrtt: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - minrtt: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - normdevrtt: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - remote_maxjitter: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - remote_maxrxploss: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - remote_minjitter: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - remote_minrxploss: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - remote_normdevjitter: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - remote_normdevrxploss: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - remote_ssrc: int (required)</span><br><span style="color: hsl(120, 100%, 40%);">+ * - remote_stdevjitter: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - remote_stdevrxploss: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - rtt: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - rxcount: int (required)</span><br><span style="color: hsl(120, 100%, 40%);">+ * - rxjitter: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - rxoctetcount: int (required)</span><br><span style="color: hsl(120, 100%, 40%);">+ * - rxploss: int (required)</span><br><span style="color: hsl(120, 100%, 40%);">+ * - stdevrtt: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - txcount: int (required)</span><br><span style="color: hsl(120, 100%, 40%);">+ * - txjitter: double</span><br><span style="color: hsl(120, 100%, 40%);">+ * - txoctetcount: int (required)</span><br><span style="color: hsl(120, 100%, 40%);">+ * - txploss: int (required)</span><br><span>  * Bridge</span><br><span>  * - bridge_class: string (required)</span><br><span>  * - bridge_type: string (required)</span><br><span>diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c</span><br><span>index f5065f5..bdb3534 100644</span><br><span>--- a/res/ari/resource_channels.c</span><br><span>+++ b/res/ari/resource_channels.c</span><br><span>@@ -48,10 +48,13 @@</span><br><span> #include "asterisk/format_cache.h"</span><br><span> #include "asterisk/core_local.h"</span><br><span> #include "asterisk/dial.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/max_forwards.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/rtp_engine.h"</span><br><span> #include "resource_channels.h"</span><br><span> </span><br><span> #include <limits.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*!</span><br><span>  * \brief Finds the control object for a channel, filling the response with an</span><br><span>  * error, if appropriate.</span><br><span>@@ -1531,3 +1534,59 @@</span><br><span>                 args->snoop_id,</span><br><span>           response);</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_ari_channels_rtpstatistics(struct ast_variable *headers,</span><br><span style="color: hsl(120, 100%, 40%);">+          struct ast_ari_channels_rtpstatistics_args *args,</span><br><span style="color: hsl(120, 100%, 40%);">+             struct ast_ari_response *response)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+      RAII_VAR(struct ast_rtp_instance *, rtp, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_json *j_res;</span><br><span style="color: hsl(120, 100%, 40%);">+       const struct ast_channel_tech *tech;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_rtp_glue *glue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  chan = ast_channel_get_by_name(args->channel_id);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!chan) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_ari_response_error(response, 404, "Not Found",</span><br><span style="color: hsl(120, 100%, 40%);">+                  "Channel not found");</span><br><span style="color: hsl(120, 100%, 40%);">+               return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_channel_lock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+       tech = ast_channel_tech(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!tech) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_channel_unlock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_ari_response_error(response, 404, "Not Found",</span><br><span style="color: hsl(120, 100%, 40%);">+                  "Channel's tech not found");</span><br><span style="color: hsl(120, 100%, 40%);">+            return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   glue = ast_rtp_instance_get_glue(tech->type);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!glue) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_channel_unlock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_ari_response_error(response, 403, "Forbidden",</span><br><span style="color: hsl(120, 100%, 40%);">+                  "Unsupported channel type");</span><br><span style="color: hsl(120, 100%, 40%);">+                return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   glue->get_rtp_info(chan, &rtp);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!rtp) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_channel_unlock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_ari_response_error(response, 404, "Not Found",</span><br><span style="color: hsl(120, 100%, 40%);">+                  "RTP info not found");</span><br><span style="color: hsl(120, 100%, 40%);">+              return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   j_res = ast_rtp_instance_get_stats_all_json(rtp);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!j_res) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_channel_unlock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_ari_response_error(response, 404, "Not Found",</span><br><span style="color: hsl(120, 100%, 40%);">+                  "Statistics not found");</span><br><span style="color: hsl(120, 100%, 40%);">+            return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_channel_unlock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_ari_response_ok(response, j_res);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/res/ari/resource_channels.h b/res/ari/resource_channels.h</span><br><span>index b9e5d02..3077297 100644</span><br><span>--- a/res/ari/resource_channels.h</span><br><span>+++ b/res/ari/resource_channels.h</span><br><span>@@ -737,5 +737,18 @@</span><br><span>  * \param[out] response HTTP response</span><br><span>  */</span><br><span> void ast_ari_channels_snoop_channel_with_id(struct ast_variable *headers, struct ast_ari_channels_snoop_channel_with_id_args *args, struct ast_ari_response *response);</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Argument struct for ast_ari_channels_rtpstatistics() */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_ari_channels_rtpstatistics_args {</span><br><span style="color: hsl(120, 100%, 40%);">+      /*! Channel's id */</span><br><span style="color: hsl(120, 100%, 40%);">+       const char *channel_id;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief RTP stats on a channel.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param headers HTTP headers</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param args Swagger parameters</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] response HTTP response</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_ari_channels_rtpstatistics(struct ast_variable *headers, struct ast_ari_channels_rtpstatistics_args *args, struct ast_ari_response *response);</span><br><span> </span><br><span> #endif /* _ASTERISK_RESOURCE_CHANNELS_H */</span><br><span>diff --git a/res/res_ari_channels.c b/res/res_ari_channels.c</span><br><span>index a69887c..5119d64 100644</span><br><span>--- a/res/res_ari_channels.c</span><br><span>+++ b/res/res_ari_channels.c</span><br><span>@@ -2391,6 +2391,64 @@</span><br><span> fin: __attribute__((unused))</span><br><span>      return;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Parameter parsing callback for /channels/{channelId}/rtp_statistics.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param get_params GET parameters in the HTTP request.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param path_vars Path variables extracted from the request.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param headers HTTP headers.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] response Response to the HTTP request.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void ast_ari_channels_rtpstatistics_cb(</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_tcptls_session_instance *ser,</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_variable *get_params, struct ast_variable *path_vars,</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_ari_channels_rtpstatistics_args args = {};</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *i;</span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(AST_DEVMODE)</span><br><span style="color: hsl(120, 100%, 40%);">+     int is_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+ int code;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* AST_DEVMODE */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = path_vars; i; i = i->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (strcmp(i->name, "channelId") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 args.channel_id = (i->value);</span><br><span style="color: hsl(120, 100%, 40%);">+              } else</span><br><span style="color: hsl(120, 100%, 40%);">+                {}</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_ari_channels_rtpstatistics(headers, &args, response);</span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(AST_DEVMODE)</span><br><span style="color: hsl(120, 100%, 40%);">+       code = response->response_code;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (code) {</span><br><span style="color: hsl(120, 100%, 40%);">+       case 0: /* Implementation is still a stub, or the code wasn't set */</span><br><span style="color: hsl(120, 100%, 40%);">+              is_valid = response->message == NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 500: /* Internal Server Error */</span><br><span style="color: hsl(120, 100%, 40%);">+ case 501: /* Not Implemented */</span><br><span style="color: hsl(120, 100%, 40%);">+       case 404: /* Channel cannot be found. */</span><br><span style="color: hsl(120, 100%, 40%);">+              is_valid = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+         break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              if (200 <= code && code <= 299) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       is_valid = ast_ari_validate_rtpstat(</span><br><span style="color: hsl(120, 100%, 40%);">+                          response->message);</span><br><span style="color: hsl(120, 100%, 40%);">+                } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/rtp_statistics\n", code);</span><br><span style="color: hsl(120, 100%, 40%);">+                   is_valid = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!is_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/rtp_statistics\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_ari_response_error(response, 500,</span><br><span style="color: hsl(120, 100%, 40%);">+                 "Internal Server Error", "Response validation failed");</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* AST_DEVMODE */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+fin: __attribute__((unused))</span><br><span style="color: hsl(120, 100%, 40%);">+   return;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> /*! \brief REST handler for /api-docs/channels.json */</span><br><span> static struct stasis_rest_handlers channels_channelId_continue = {</span><br><span>@@ -2545,6 +2603,15 @@</span><br><span>      .children = { &channels_channelId_snoop_snoopId, }</span><br><span> };</span><br><span> /*! \brief REST handler for /api-docs/channels.json */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct stasis_rest_handlers channels_channelId_rtp_statistics = {</span><br><span style="color: hsl(120, 100%, 40%);">+      .path_segment = "rtp_statistics",</span><br><span style="color: hsl(120, 100%, 40%);">+   .callbacks = {</span><br><span style="color: hsl(120, 100%, 40%);">+                [AST_HTTP_GET] = ast_ari_channels_rtpstatistics_cb,</span><br><span style="color: hsl(120, 100%, 40%);">+   },</span><br><span style="color: hsl(120, 100%, 40%);">+    .num_children = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+    .children = {  }</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief REST handler for /api-docs/channels.json */</span><br><span> static struct stasis_rest_handlers channels_channelId = {</span><br><span>    .path_segment = "channelId",</span><br><span>       .is_wildcard = 1,</span><br><span>@@ -2553,8 +2620,8 @@</span><br><span>            [AST_HTTP_POST] = ast_ari_channels_originate_with_id_cb,</span><br><span>             [AST_HTTP_DELETE] = ast_ari_channels_hangup_cb,</span><br><span>      },</span><br><span style="color: hsl(0, 100%, 40%);">-      .num_children = 14,</span><br><span style="color: hsl(0, 100%, 40%);">-     .children = { &channels_channelId_continue,&channels_channelId_move,&channels_channelId_redirect,&channels_channelId_answer,&channels_channelId_ring,&channels_channelId_dtmf,&channels_channelId_mute,&channels_channelId_hold,&channels_channelId_moh,&channels_channelId_silence,&channels_channelId_play,&channels_channelId_record,&channels_channelId_variable,&channels_channelId_snoop, }</span><br><span style="color: hsl(120, 100%, 40%);">+     .num_children = 15,</span><br><span style="color: hsl(120, 100%, 40%);">+   .children = { &channels_channelId_continue,&channels_channelId_move,&channels_channelId_redirect,&channels_channelId_answer,&channels_channelId_ring,&channels_channelId_dtmf,&channels_channelId_mute,&channels_channelId_hold,&channels_channelId_moh,&channels_channelId_silence,&channels_channelId_play,&channels_channelId_record,&channels_channelId_variable,&channels_channelId_snoop,&channels_channelId_rtp_statistics, }</span><br><span> };</span><br><span> /*! \brief REST handler for /api-docs/channels.json */</span><br><span> static struct stasis_rest_handlers channels = {</span><br><span>diff --git a/rest-api/api-docs/channels.json b/rest-api/api-docs/channels.json</span><br><span>index afe95dc..4d26b54 100644</span><br><span>--- a/rest-api/api-docs/channels.json</span><br><span>+++ b/rest-api/api-docs/channels.json</span><br><span>@@ -1511,6 +1511,34 @@</span><br><span>                                        ]</span><br><span>                            }</span><br><span>                    ]</span><br><span style="color: hsl(120, 100%, 40%);">+             },</span><br><span style="color: hsl(120, 100%, 40%);">+            {</span><br><span style="color: hsl(120, 100%, 40%);">+                     "path": "/channels/{channelId}/rtp_statistics",</span><br><span style="color: hsl(120, 100%, 40%);">+                   "description": "Get RTP statistics information for RTP on a channel",</span><br><span style="color: hsl(120, 100%, 40%);">+                     "operations": [</span><br><span style="color: hsl(120, 100%, 40%);">+                             {</span><br><span style="color: hsl(120, 100%, 40%);">+                                     "httpMethod": "GET",</span><br><span style="color: hsl(120, 100%, 40%);">+                                      "summary": "RTP stats on a channel.",</span><br><span style="color: hsl(120, 100%, 40%);">+                                     "nickname": "rtpstatistics",</span><br><span style="color: hsl(120, 100%, 40%);">+                                      "responseClass": "RTPstat",</span><br><span style="color: hsl(120, 100%, 40%);">+                                       "parameters": [</span><br><span style="color: hsl(120, 100%, 40%);">+                                             {</span><br><span style="color: hsl(120, 100%, 40%);">+                                                     "name": "channelId",</span><br><span style="color: hsl(120, 100%, 40%);">+                                                      "description": "Channel's id",</span><br><span style="color: hsl(120, 100%, 40%);">+                                                        "paramType": "path",</span><br><span style="color: hsl(120, 100%, 40%);">+                                                      "required": true,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                   "allowMultiple": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                     "dataType": "string"</span><br><span style="color: hsl(120, 100%, 40%);">+                                              }</span><br><span style="color: hsl(120, 100%, 40%);">+                                     ],</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "errorResponses": [</span><br><span style="color: hsl(120, 100%, 40%);">+                                         {</span><br><span style="color: hsl(120, 100%, 40%);">+                                                     "code": 404,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                        "reason": "Channel cannot be found."</span><br><span style="color: hsl(120, 100%, 40%);">+                                              }</span><br><span style="color: hsl(120, 100%, 40%);">+                                     ]</span><br><span style="color: hsl(120, 100%, 40%);">+                             }</span><br><span style="color: hsl(120, 100%, 40%);">+                     ]</span><br><span>            }</span><br><span>    ],</span><br><span>   "models": {</span><br><span>@@ -1554,6 +1582,172 @@</span><br><span>                              }</span><br><span>                    }</span><br><span>            },</span><br><span style="color: hsl(120, 100%, 40%);">+            "RTPstat": {</span><br><span style="color: hsl(120, 100%, 40%);">+                        "id": "RTPstat",</span><br><span style="color: hsl(120, 100%, 40%);">+                  "description": "A statistics of a RTP.",</span><br><span style="color: hsl(120, 100%, 40%);">+                  "properties": {</span><br><span style="color: hsl(120, 100%, 40%);">+                             "txcount": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                        "required": true,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   "type": "int",</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "description": "Number of packets transmitted."</span><br><span style="color: hsl(120, 100%, 40%);">+                           },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "rxcount": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                        "required": true,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   "type": "int",</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "description": "Number of packets received."</span><br><span style="color: hsl(120, 100%, 40%);">+                              },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "txjitter": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                       "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Jitter on transmitted packets."</span><br><span style="color: hsl(120, 100%, 40%);">+                           },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "rxjitter": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                       "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Jitter on received packets."</span><br><span style="color: hsl(120, 100%, 40%);">+                              },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "remote_maxjitter": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                       "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Maximum jitter on remote side."</span><br><span style="color: hsl(120, 100%, 40%);">+                           },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "remote_minjitter": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                       "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Minimum jitter on remote side."</span><br><span style="color: hsl(120, 100%, 40%);">+                           },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "remote_normdevjitter": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                   "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Average jitter on remote side."</span><br><span style="color: hsl(120, 100%, 40%);">+                           },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "remote_stdevjitter": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                     "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Standard deviation jitter on remote side."</span><br><span style="color: hsl(120, 100%, 40%);">+                                },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "local_maxjitter": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                        "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Maximum jitter on local side."</span><br><span style="color: hsl(120, 100%, 40%);">+                            },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "local_minjitter": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                        "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Minimum jitter on local side."</span><br><span style="color: hsl(120, 100%, 40%);">+                            },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "local_normdevjitter": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Average jitter on local side."</span><br><span style="color: hsl(120, 100%, 40%);">+                            },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "local_stdevjitter": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                      "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Standard deviation jitter on local side."</span><br><span style="color: hsl(120, 100%, 40%);">+                         },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "txploss": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                        "required": true,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   "type": "int",</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "description": "Number of transmitted packets lost."</span><br><span style="color: hsl(120, 100%, 40%);">+                              },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "rxploss": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                        "required": true,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   "type": "int",</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "description": "Number of received packets lost."</span><br><span style="color: hsl(120, 100%, 40%);">+                         },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "remote_maxrxploss": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                      "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Maximum number of packets lost on remote side."</span><br><span style="color: hsl(120, 100%, 40%);">+                           },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "remote_minrxploss": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                      "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Minimum number of packets lost on remote side."</span><br><span style="color: hsl(120, 100%, 40%);">+                           },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "remote_normdevrxploss": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Average number of packets lost on remote side."</span><br><span style="color: hsl(120, 100%, 40%);">+                           },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "remote_stdevrxploss": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Standard deviation packets lost on remote side."</span><br><span style="color: hsl(120, 100%, 40%);">+                          },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "local_maxrxploss": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                       "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Maximum number of packets lost on local side."</span><br><span style="color: hsl(120, 100%, 40%);">+                            },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "local_minrxploss": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                       "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Minimum number of packets lost on local side."</span><br><span style="color: hsl(120, 100%, 40%);">+                            },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "local_normdevrxploss": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                   "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Average number of packets lost on local side."</span><br><span style="color: hsl(120, 100%, 40%);">+                            },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "local_stdevrxploss": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                     "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Standard deviation packets lost on local side."</span><br><span style="color: hsl(120, 100%, 40%);">+                           },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "rtt": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Total round trip time."</span><br><span style="color: hsl(120, 100%, 40%);">+                           },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "maxrtt": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Maximum round trip time."</span><br><span style="color: hsl(120, 100%, 40%);">+                         },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "minrtt": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Minimum round trip time."</span><br><span style="color: hsl(120, 100%, 40%);">+                         },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "normdevrtt": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                     "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Average round trip time."</span><br><span style="color: hsl(120, 100%, 40%);">+                         },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "stdevrtt": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                       "required": false,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  "type": "double",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "Standard deviation round trip time."</span><br><span style="color: hsl(120, 100%, 40%);">+                              },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "local_ssrc": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                     "required": true,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   "type": "int",</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "description": "Our SSRC."</span><br><span style="color: hsl(120, 100%, 40%);">+                                },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "remote_ssrc": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "required": true,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   "type": "int",</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "description": "Their SSRC."</span><br><span style="color: hsl(120, 100%, 40%);">+                              },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "txoctetcount": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                   "required": true,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   "type": "int",</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "description": "Number of octets transmitted."</span><br><span style="color: hsl(120, 100%, 40%);">+                            },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "rxoctetcount": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                   "required": true,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   "type": "int",</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "description": "Number of octets received."</span><br><span style="color: hsl(120, 100%, 40%);">+                               },</span><br><span style="color: hsl(120, 100%, 40%);">+                            "channel_uniqueid": {</span><br><span style="color: hsl(120, 100%, 40%);">+                                       "required": true,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   "type": "string",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "description": "The Asterisk channel's unique ID that owns this instance."</span><br><span style="color: hsl(120, 100%, 40%);">+                            }</span><br><span style="color: hsl(120, 100%, 40%);">+                     }</span><br><span style="color: hsl(120, 100%, 40%);">+             },</span><br><span>           "Channel": {</span><br><span>                       "id": "Channel",</span><br><span>                         "description": "A specific communication connection between Asterisk and an Endpoint.",</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/11200">change 11200</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/11200"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-Change-Id: I4343eec070438cec13f2a4f22e7fd9e574381376 </div>
<div style="display:none"> Gerrit-Change-Number: 11200 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: sungtae kim <pchero21@gmail.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>