]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
The AUDIORTPQOS and VIDEORTPQOS variables are not fully functional in some
authorRussell Bryant <russell@russellbryant.com>
Mon, 26 Mar 2007 17:45:55 +0000 (17:45 +0000)
committerRussell Bryant <russell@russellbryant.com>
Mon, 26 Mar 2007 17:45:55 +0000 (17:45 +0000)
because they get set in sip_hangup.  So, there are common situations where
the variables will not be available in the dialplan at all.  So, this patch
provides an alternate method for getting to this information by introducing
AUDIORTPQOS and VIDEORTPQOS dialplan functions.
(issue #9370, patch by Corydon76, with some testing by blitzrage)

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@59207 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c
include/asterisk/rtp.h
main/rtp.c

index 6b14d052d637aef615c788c11cf9c335fb9efcd2..37f530d637e1462e6cd53b66ec7e009db3d7a52f 100644 (file)
@@ -3392,9 +3392,9 @@ static int sip_hangup(struct ast_channel *ast)
                                char *audioqos = "";
                                char *videoqos = "";
                                if (p->rtp)
-                                       audioqos = ast_rtp_get_quality(p->rtp);
+                                       audioqos = ast_rtp_get_quality(p->rtp, NULL);
                                if (p->vrtp)
-                                       videoqos = ast_rtp_get_quality(p->vrtp);
+                                       videoqos = ast_rtp_get_quality(p->vrtp, NULL);
                                /* Send a hangup */
                                transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
 
@@ -14127,6 +14127,53 @@ static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req)
        }
 }
 
+static int acf_audiortpqos_read(struct ast_channel *chan, char *funcname, char *args, char *buf, size_t buflen)
+{
+       struct ast_rtp_quality qos;
+       struct sip_pvt *p = chan->tech_pvt;
+       char *all = "";
+
+       /* Sanity check */
+       if (chan->tech != &sip_tech && chan->tech != &sip_tech_info) {
+               ast_log(LOG_ERROR, "Cannot call %s on a non-SIP channel\n", funcname);
+       }
+
+       memset(buf, 0, buflen);
+       memset(&qos, 0, sizeof(qos));
+
+       if (strcmp(funcname, "AUDIORTPQOS") == 0) {
+               all = ast_rtp_get_quality(p->rtp, &qos);
+       } else if (strcmp(funcname, "VIDEORTPQOS") == 0) {
+               all = ast_rtp_get_quality(p->vrtp, &qos);
+       }
+
+       if (strcasecmp(args, "local_ssrc") == 0)
+               snprintf(buf, buflen, "%u", qos.local_ssrc);
+       else if (strcasecmp(args, "local_lostpackets") == 0)
+               snprintf(buf, buflen, "%u", qos.local_lostpackets);
+       else if (strcasecmp(args, "local_jitter") == 0)
+               snprintf(buf, buflen, "%.0lf", qos.local_jitter * 1000.0);
+       else if (strcasecmp(args, "local_count") == 0)
+               snprintf(buf, buflen, "%u", qos.local_count);
+       else if (strcasecmp(args, "remote_ssrc") == 0)
+               snprintf(buf, buflen, "%u", qos.remote_ssrc);
+       else if (strcasecmp(args, "remote_lostpackets") == 0)
+               snprintf(buf, buflen, "%u", qos.remote_lostpackets);
+       else if (strcasecmp(args, "remote_jitter") == 0)
+               snprintf(buf, buflen, "%.0lf", qos.remote_jitter * 1000.0);
+       else if (strcasecmp(args, "remote_count") == 0)
+               snprintf(buf, buflen, "%u", qos.remote_count);
+       else if (strcasecmp(args, "rtt") == 0)
+               snprintf(buf, buflen, "%.0lf", qos.rtt * 1000.0);
+       else if (strcasecmp(args, "all") == 0)
+               ast_copy_string(buf, all, buflen);
+       else {
+               ast_log(LOG_WARNING, "Unrecognized argument '%s' to %s\n", args, funcname);
+               return -1;
+       }
+       return 0;
+}
+
 /*! \brief Handle incoming BYE request */
 static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
 {
@@ -14148,14 +14195,14 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
        if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY) || p->owner) {
                char *audioqos, *videoqos;
                if (p->rtp) {
-                       audioqos = ast_rtp_get_quality(p->rtp);
+                       audioqos = ast_rtp_get_quality(p->rtp, NULL);
                        if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY))
                                append_history(p, "RTCPaudio", "Quality:%s", audioqos);
                        if (p->owner)
                                pbx_builtin_setvar_helper(p->owner, "RTPAUDIOQOS", audioqos);
                }
                if (p->vrtp) {
-                       videoqos = ast_rtp_get_quality(p->vrtp);
+                       videoqos = ast_rtp_get_quality(p->vrtp, NULL);
                        if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY))
                                append_history(p, "RTCPvideo", "Quality:%s", videoqos);
                        if (p->owner)
@@ -17321,6 +17368,44 @@ static struct ast_cli_entry cli_sip[] = {
        sip_reload_usage },
 };
 
+struct ast_custom_function acf_audiortpqos = {
+       .name = "AUDIORTPQOS",
+       .synopsis = "Retrieve statistics about an RTP audio stream",
+       .desc =
+"The following statistics may be retrieved:\n"
+"  local_ssrc         - Local SSRC (stream ID)\n"
+"  local_lostpackets  - Local lost packets\n"
+"  local_jitter       - Local calculated jitter\n"
+"  local_count        - Number of received packets\n"
+"  remote_ssrc        - Remote SSRC (stream ID)\n"
+"  remote_lostpackets - Remote lost packets\n"
+"  remote_jitter      - Remote reported jitter\n"
+"  remote_count       - Number of transmitted packets\n"
+"  rtt                - Round trip time\n"
+"  all                - All statistics (in a form suited to logging, but not for parsing)",
+       .syntax = "AUDIORTPQOS(<field>)",
+       .read = acf_audiortpqos_read,
+};
+
+struct ast_custom_function acf_videortpqos = {
+       .name = "VIDEORTPQOS",
+       .synopsis = "Retrieve statistics about an RTP audio stream",
+       .desc =
+"The following statistics may be retrieved:\n"
+"  local_ssrc         - Local SSRC (stream ID)\n"
+"  local_lostpackets  - Local lost packets\n"
+"  local_jitter       - Local calculated jitter\n"
+"  local_count        - Number of received packets\n"
+"  remote_ssrc        - Remote SSRC (stream ID)\n"
+"  remote_lostpackets - Remote lost packets\n"
+"  remote_jitter      - Remote reported jitter\n"
+"  remote_count       - Number of transmitted packets\n"
+"  rtt                - Round trip time\n"
+"  all                - All statistics (in a form suited to logging, but not for parsing)",
+       .syntax = "AUDIORTPQOS(<field>)",
+       .read = acf_audiortpqos_read,
+};
+
 /*! \brief PBX load module - initialization */
 static int load_module(void)
 {
@@ -17370,6 +17455,8 @@ static int load_module(void)
        ast_custom_function_register(&sippeer_function);
        ast_custom_function_register(&sipchaninfo_function);
        ast_custom_function_register(&checksipdomain_function);
+       ast_custom_function_register(&acf_audiortpqos);
+       ast_custom_function_register(&acf_videortpqos);
 
        /* Register manager commands */
        ast_manager_register2("SIPpeers", EVENT_FLAG_SYSTEM, manager_sip_show_peers,
@@ -17399,6 +17486,8 @@ static int unload_module(void)
        ast_custom_function_unregister(&sippeer_function);
        ast_custom_function_unregister(&sip_header_function);
        ast_custom_function_unregister(&checksipdomain_function);
+       ast_custom_function_unregister(&acf_audiortpqos);
+       ast_custom_function_unregister(&acf_videortpqos);
 
        /* Unregister dial plan applications */
        ast_unregister_application(app_dtmfmode);
index 501068987bc9f8dc762cf5cfbb094687547b570d..cbcb6aae64f5e88a7c0e9143ae62f08aa09d058c 100644 (file)
@@ -77,6 +77,18 @@ struct ast_rtp_protocol {
        AST_LIST_ENTRY(ast_rtp_protocol) list;
 };
 
+struct ast_rtp_quality {
+       unsigned int local_ssrc;          /* Our SSRC */
+       unsigned int local_lostpackets;   /* Our lost packets */
+       double       local_jitter;        /* Our calculated jitter */
+       unsigned int local_count;         /* Number of received packets */
+       unsigned int remote_ssrc;         /* Their SSRC */
+       unsigned int remote_lostpackets;  /* Their lost packets */
+       double       remote_jitter;       /* Their reported jitter */
+       unsigned int remote_count;        /* Number of transmitted packets */
+       double       rtt;                 /* Round trip time */
+};
+
 
 #define FLAG_3389_WARNING              (1 << 0)
 
@@ -206,7 +218,7 @@ int ast_rtp_early_bridge(struct ast_channel *dest, struct ast_channel *src);
 void ast_rtp_stop(struct ast_rtp *rtp);
 
 /*! \brief Return RTCP quality string */
-char *ast_rtp_get_quality(struct ast_rtp *rtp);
+char *ast_rtp_get_quality(struct ast_rtp *rtp, struct ast_rtp_quality *qual);
 
 /*! \brief Send an H.261 fast update request. Some devices need this rather than the XML message  in SIP */
 int ast_rtcp_send_h261fur(void *data);
index a2a6a344b68cb8f659e444658867889ef8cd7026..42074146a5e3dbabab6103a5613889c85beaa7d1 100644 (file)
@@ -2024,7 +2024,7 @@ void ast_rtp_reset(struct ast_rtp *rtp)
        rtp->rxseqno = 0;
 }
 
-char *ast_rtp_get_quality(struct ast_rtp *rtp)
+char *ast_rtp_get_quality(struct ast_rtp *rtp, struct ast_rtp_quality *qual)
 {
        /*
        *ssrc          our ssrc
@@ -2035,8 +2035,20 @@ char *ast_rtp_get_quality(struct ast_rtp *rtp)
        *txjitter      reported jitter of the other end
        *txcount       transmitted packets
        *rlp           remote lost packets
+       *rtt           round trip time
        */
-       
+
+       if (qual) {
+               qual->local_ssrc = rtp->ssrc;
+               qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
+               qual->local_jitter = rtp->rxjitter;
+               qual->local_count = rtp->rxcount;
+               qual->remote_ssrc = rtp->themssrc;
+               qual->remote_lostpackets = rtp->rtcp->reported_lost;
+               qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
+               qual->remote_count = rtp->txcount;
+               qual->rtt = rtp->rtcp->rtt;
+       }
        snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", rtp->ssrc, rtp->themssrc, rtp->rtcp->expected_prior - rtp->rtcp->received_prior, rtp->rxjitter, rtp->rxcount, (double)rtp->rtcp->reported_jitter/65536., rtp->txcount, rtp->rtcp->reported_lost, rtp->rtcp->rtt);
        
        return rtp->rtcp->quality;