summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell Bryant <russell@russellbryant.com>2007-03-26 17:51:27 +0000
committerRussell Bryant <russell@russellbryant.com>2007-03-26 17:51:27 +0000
commit08e3a9bdc82ec4bb2b9fc24c8a4887a03c085d71 (patch)
treebb9a4f8a98d5844711b2d23378a49d0921f3f588
parente4a7d1b35f62943d28a738e8a0e21413216d01d9 (diff)
Merged revisions 59207 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r59207 | russell | 2007-03-26 12:45:55 -0500 (Mon, 26 Mar 2007) | 7 lines The AUDIORTPQOS and VIDEORTPQOS variables are not fully functional in some 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/trunk@59208 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--channels/chan_sip.c122
-rw-r--r--include/asterisk/rtp.h15
-rw-r--r--main/rtp.c16
3 files changed, 144 insertions, 9 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 07ba786be..b054465a2 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -3686,11 +3686,11 @@ static int sip_hangup(struct ast_channel *ast)
char *videoqos = "";
char *textqos = "";
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);
if (p->trtp)
- textqos = ast_rtp_get_quality(p->trtp);
+ textqos = ast_rtp_get_quality(p->trtp, NULL);
/* Send a hangup */
transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
@@ -14800,6 +14800,55 @@ 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);
+ } else if (strcmp(funcname, "TEXTRTPQOS") == 0) {
+ all = ast_rtp_get_quality(p->trtp, &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)
{
@@ -14823,14 +14872,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, *textqos;
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)
@@ -18081,6 +18130,63 @@ 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,
+};
+
+struct ast_custom_function acf_textrtpqos = {
+ .name = "TEXTRTPQOS",
+ .synopsis = "Retrieve statistics about an RTP text 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 = "TEXTRTPQOS(<field>)",
+ .read = acf_audiortpqos_read,
+};
+
/*! \brief PBX load module - initialization */
static int load_module(void)
{
@@ -18130,6 +18236,9 @@ 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);
+ ast_custom_function_register(&acf_textrtpqos);
/* Register manager commands */
ast_manager_register2("SIPpeers", EVENT_FLAG_SYSTEM, manager_sip_show_peers,
@@ -18159,6 +18268,9 @@ 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);
+ ast_custom_function_unregister(&acf_textrtpqos);
/* Unregister dial plan applications */
ast_unregister_application(app_dtmfmode);
diff --git a/include/asterisk/rtp.h b/include/asterisk/rtp.h
index 5eea063db..47cc26212 100644
--- a/include/asterisk/rtp.h
+++ b/include/asterisk/rtp.h
@@ -84,6 +84,17 @@ 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 */
+};
/*! RTP callback structure */
typedef int (*ast_rtp_callback)(struct ast_rtp *rtp, struct ast_frame *f, void *data);
@@ -219,12 +230,12 @@ int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src, i
having to send a re-invite later */
int ast_rtp_early_bridge(struct ast_channel *c0, struct ast_channel *c1);
-
+/*! \brief Return RTCP quality string */
+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);
-char *ast_rtp_get_quality(struct ast_rtp *rtp); /*! \brief Return RTCP quality string */
void ast_rtp_init(void); /*! Initialize RTP subsystem */
int ast_rtp_reload(void); /*! reload rtp configuration */
void ast_rtp_new_init(struct ast_rtp *rtp);
diff --git a/main/rtp.c b/main/rtp.c
index 4c45c5b3e..486ff6189 100644
--- a/main/rtp.c
+++ b/main/rtp.c
@@ -2128,7 +2128,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
@@ -2139,8 +2139,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;