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
1.6.0
Russell Bryant 18 years ago
parent e4a7d1b35f
commit 08e3a9bdc8

@ -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);

@ -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);

@ -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;

Loading…
Cancel
Save