[asterisk-commits] mjordan: branch group/pinefrog-rtcp-trunk r385680 - in /team/group/pinefrog-r...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sun Apr 14 19:58:52 CDT 2013
Author: mjordan
Date: Sun Apr 14 19:58:50 2013
New Revision: 385680
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=385680
Log:
Merge oej's pinefrog-rtcp-11 branch to trunk
Added:
team/group/pinefrog-rtcp-trunk/
- copied from r385638, trunk/
team/group/pinefrog-rtcp-trunk/channels/sip/include/rtcp.h (with props)
team/group/pinefrog-rtcp-trunk/channels/sip/rtcp.c (with props)
Modified:
team/group/pinefrog-rtcp-trunk/CREDITS
team/group/pinefrog-rtcp-trunk/channels/chan_sip.c
team/group/pinefrog-rtcp-trunk/channels/sip/dialplan_functions.c
team/group/pinefrog-rtcp-trunk/channels/sip/include/sip.h
team/group/pinefrog-rtcp-trunk/contrib/realtime/mysql/sippeers.sql
team/group/pinefrog-rtcp-trunk/contrib/realtime/postgresql/realtime.sql
team/group/pinefrog-rtcp-trunk/include/asterisk/logger.h
team/group/pinefrog-rtcp-trunk/include/asterisk/rtp_engine.h
team/group/pinefrog-rtcp-trunk/main/logger.c
team/group/pinefrog-rtcp-trunk/main/rtp_engine.c
team/group/pinefrog-rtcp-trunk/res/res_rtp_asterisk.c
Modified: team/group/pinefrog-rtcp-trunk/CREDITS
URL: http://svnview.digium.com/svn/asterisk/team/group/pinefrog-rtcp-trunk/CREDITS?view=diff&rev=385680&r1=385638&r2=385680
==============================================================================
--- team/group/pinefrog-rtcp-trunk/CREDITS (original)
+++ team/group/pinefrog-rtcp-trunk/CREDITS Sun Apr 14 19:58:50 2013
@@ -39,6 +39,9 @@
* Voop AS, Nuvio Inc, Inotel S.A and Foniris Telecom A/S - funding for
rewrite of SIP transfers
+
+Nordicom Norge AS, Kristiansand, Norway, for funding work with RTCP support
+and Call Quality Records.
=== WISHLIST CONTRIBUTERS ===
@@ -153,6 +156,7 @@
transfer support, SIP presence support, SIP call state updates
(dialog-info), QUEUE_EXISTS function, device state provider
architecture, multiparking (together with mvanbaak), meetme and
+ RTCP improvements, Call Quality Records,
parking device states, MiniVM - the small voicemail system,
many documentation updates/corrections, and many bug fixes.
oej(AT)edvina.net, http://edvina.net
@@ -265,8 +269,8 @@
implementation Developers: Marc Blanchet, Simon Perreault and
Jean-Philippe Dionne
- * ClearIT AB, Sweden - res_mutestream, queue_exists and various other
- patches (developed by oej)
+ * ClearIT AB, Sweden - res_mutestream, queue_exists, RTCP improvements
+ and various other patches (developed by oej)
* Despegar.com, Argentina - AstData API implementation, also sponsored
by Google as part of the gsoc/2009 program (developed by Eliel)
Modified: team/group/pinefrog-rtcp-trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/group/pinefrog-rtcp-trunk/channels/chan_sip.c?view=diff&rev=385680&r1=385638&r2=385680
==============================================================================
--- team/group/pinefrog-rtcp-trunk/channels/chan_sip.c (original)
+++ team/group/pinefrog-rtcp-trunk/channels/chan_sip.c Sun Apr 14 19:58:50 2013
@@ -293,6 +293,7 @@
#include "sip/include/dialog.h"
#include "sip/include/dialplan_functions.h"
#include "sip/include/security_events.h"
+#include "sip/include/rtcp.h"
#include "asterisk/sip_api.h"
#include "asterisk/app.h"
@@ -740,7 +741,6 @@
{ AST_REDIRECTING_REASON_SEND_TO_VM, "send_to_vm"},
};
-
/*! \name DefaultSettings
Default setttings are used as a channel setting and as a default when
configuring devices
@@ -6618,6 +6618,22 @@
if (dumphistory)
sip_dump_history(p);
+
+ AST_SCHED_DEL(sched, p->rtcpeventid);
+
+ if (p->audioqual) {
+ /* We have a quality report to write to realtime before we leave this world. */
+ qos_write_realtime(p, p->audioqual);
+ free(p->audioqual);
+ p->audioqual = NULL;
+ }
+ if (p->videoqual) {
+ /* We have a quality report to write to realtime before we leave this world. */
+ qos_write_realtime(p, p->videoqual);
+ free(p->videoqual);
+ p->videoqual = NULL;
+ }
+
if (p->options) {
if (p->options->outboundproxy) {
@@ -7368,6 +7384,7 @@
ast_rtp_instance_update_source(p->rtp);
res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, FALSE, TRUE);
ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
+ start_rtcp_events(p, sched);
}
sip_pvt_unlock(p);
return res;
@@ -8774,8 +8791,10 @@
set_socket_transport(&p->socket, SIP_TRANSPORT_UDP);
}
+ p->sip_cfg = &sip_cfg;
p->socket.fd = -1;
p->method = intended_method;
+ p->rtcpeventid = -1;
p->initid = -1;
p->waitid = -1;
p->reinviteid = -1;
@@ -8837,6 +8856,14 @@
build_callid_pvt(p);
else
ast_string_field_set(p, callid, callid);
+
+ /* Set cnames for the RTCP SDES */
+ if (p->rtp) {
+ ast_rtp_instance_setcname(p->rtp, p->callid, strlen(p->callid));
+ }
+ if (p->vrtp) {
+ ast_rtp_instance_setcname(p->vrtp, p->callid, strlen(p->callid));
+ }
/* Assign default music on hold class */
ast_string_field_set(p, mohinterpret, default_mohinterpret);
ast_string_field_set(p, mohsuggest, default_mohsuggest);
@@ -9879,6 +9906,7 @@
ast_channel_uniqueid(dialog->owner));
append_history(dialog, holdstate ? "Hold" : "Unhold", "%s", ast_str_buffer(req->data));
if (!holdstate) { /* Put off remote hold */
+ ast_rtp_instance_hold(dialog->rtp, 0); /* Turn off RTP hold */
ast_clear_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD); /* Clear both flags */
return;
}
@@ -10794,9 +10822,9 @@
S_OR(p->mohsuggest, NULL),
!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
}
- if (sendonly)
- ast_rtp_instance_stop(p->rtp);
- /* RTCP needs to go ahead, even if we're on hold!!! */
+ if (sendonly == 1 || sendonly == 2) { /* sendonly (from the other side) or inactive */
+ ast_rtp_instance_hold(p->rtp, 1);
+ }
/* Activate a re-invite */
ast_queue_frame(p->owner, &ast_null_frame);
change_hold_state(p, req, TRUE, sendonly);
@@ -20765,9 +20793,11 @@
{
int realtimepeers;
int realtimeregs;
+ int realtimertpqos;
char codec_buf[SIPBUFSIZE];
const char *msg; /* temporary msg pointer */
struct sip_auth_container *credentials;
+
switch (cmd) {
case CLI_INIT:
@@ -20785,6 +20815,7 @@
realtimepeers = ast_check_realtime("sippeers");
realtimeregs = ast_check_realtime("sipregs");
+ realtimertpqos = ast_check_realtime("rtpcqr");
ast_mutex_lock(&authl_lock);
credentials = authl;
@@ -20858,6 +20889,8 @@
}
ast_cli(a->fd, " Record SIP history: %s\n", AST_CLI_ONOFF(recordhistory));
ast_cli(a->fd, " Call Events: %s\n", AST_CLI_ONOFF(sip_cfg.callevents));
+ ast_cli(a->fd, " RTCP Events: %s\n", AST_CLI_ONOFF(sip_cfg.rtcpevents));
+ ast_cli(a->fd, " RTCP Event timer: %d\n", sip_cfg.rtcptimer);
ast_cli(a->fd, " Auth. Failure Events: %s\n", AST_CLI_ONOFF(global_authfailureevents));
ast_cli(a->fd, " T.38 support: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT)));
@@ -20867,6 +20900,7 @@
ast_cli(a->fd, " SIP realtime: Disabled\n" );
else
ast_cli(a->fd, " SIP realtime: Enabled\n" );
+ ast_cli(a->fd, " QoS realtime reports: %s\n", realtimertpqos ? "Enabled" : "Disabled" );
ast_cli(a->fd, " Qualify Freq : %d ms\n", global_qualifyfreq);
ast_cli(a->fd, " Q.850 Reason header: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[1], SIP_PAGE2_Q850_REASON)));
ast_cli(a->fd, " Store SIP_CAUSE: %s\n", AST_CLI_YESNO(global_store_sip_cause));
@@ -22893,6 +22927,7 @@
ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n");
}
check_pendings(p);
+ start_rtcp_events(p, sched);
break;
case 180: /* 180 Ringing */
@@ -23180,6 +23215,7 @@
ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, TRUE);
check_pendings(p);
+ start_rtcp_events(p, sched);
break;
case 407: /* Proxy authentication */
@@ -23911,16 +23947,21 @@
}
}
-/*! \brief Immediately stop RTP, VRTP and UDPTL as applicable */
+/*! \brief Immediately stop RTP, VRTP, TEXT and UDPTL as applicable */
static void stop_media_flows(struct sip_pvt *p)
{
/* Immediately stop RTP, VRTP and UDPTL as applicable */
- if (p->rtp)
+ if (p->rtp && !ast_rtp_instance_isactive(p->rtp)) {
+ sip_rtcp_report(p, p->rtp, SDP_AUDIO, TRUE);
ast_rtp_instance_stop(p->rtp);
- if (p->vrtp)
+ }
+ if (p->vrtp && !ast_rtp_instance_isactive(p->vrtp)) {
+ sip_rtcp_report(p, p->vrtp, SDP_VIDEO, TRUE);
ast_rtp_instance_stop(p->vrtp);
- if (p->trtp)
+ }
+ if (p->trtp && !ast_rtp_instance_isactive(p->trtp)) {
ast_rtp_instance_stop(p->trtp);
+ }
if (p->udptl)
ast_udptl_stop(p->udptl);
}
@@ -26912,6 +26953,7 @@
if (p->rtp && (quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
+ sip_rtcp_report(p, p->rtp, SDP_AUDIO, TRUE);
if (p->do_history) {
append_history(p, "RTCPaudio", "Quality:%s", quality);
@@ -26942,6 +26984,7 @@
}
if (p->vrtp && (quality = ast_rtp_instance_get_quality(p->vrtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
+ sip_rtcp_report(p, p->rtp, SDP_VIDEO, TRUE);
if (p->do_history) {
append_history(p, "RTCPvideo", "Quality:%s", quality);
}
@@ -31696,6 +31739,8 @@
/* Misc settings for the channel */
global_relaxdtmf = FALSE;
sip_cfg.callevents = DEFAULT_CALLEVENTS;
+ sip_cfg.rtcpevents = FALSE;
+ sip_cfg.rtcptimer = 0; /* Only report at end of call (default) */
global_authfailureevents = FALSE;
global_t1 = DEFAULT_TIMER_T1;
global_timer_b = 64 * DEFAULT_TIMER_T1;
@@ -32175,6 +32220,13 @@
} else {
ast_log(LOG_WARNING, "Invalid qualifyfreq number '%s' at line %d of %s\n", v->value, v->lineno, config);
global_qualifyfreq = DEFAULT_QUALIFYFREQ;
+ }
+ } else if (!strcasecmp(v->name, "rtcpevents")) {
+ sip_cfg.rtcpevents = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "rtcpeventtimer")) {
+ if (sscanf(v->value, "%30d", &sip_cfg.rtcptimer) != 1) {
+ ast_log(LOG_WARNING, "RTCP event timer needs to be value (seconds between reports) at line %d of sip.conf\n", v->lineno);
+ sip_cfg.rtcptimer = 0;
}
} else if (!strcasecmp(v->name, "callevents")) {
sip_cfg.callevents = ast_true(v->value);
Modified: team/group/pinefrog-rtcp-trunk/channels/sip/dialplan_functions.c
URL: http://svnview.digium.com/svn/asterisk/team/group/pinefrog-rtcp-trunk/channels/sip/dialplan_functions.c?view=diff&rev=385680&r1=385638&r2=385680
==============================================================================
--- team/group/pinefrog-rtcp-trunk/channels/sip/dialplan_functions.c (original)
+++ team/group/pinefrog-rtcp-trunk/channels/sip/dialplan_functions.c Sun Apr 14 19:58:50 2013
@@ -162,6 +162,11 @@
if (!ast_rtp_instance_get_quality(rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf))) {
return -1;
}
+#ifdef OEJ
+ if (!ast_rtp_instance_get_qualdata(rtp, ???, &qos)) {
+ this_needs_some_love;
+ }
+#endif
ast_copy_string(buf, quality_buf, buflen);
return res;
Added: team/group/pinefrog-rtcp-trunk/channels/sip/include/rtcp.h
URL: http://svnview.digium.com/svn/asterisk/team/group/pinefrog-rtcp-trunk/channels/sip/include/rtcp.h?view=auto&rev=385680
==============================================================================
--- team/group/pinefrog-rtcp-trunk/channels/sip/include/rtcp.h (added)
+++ team/group/pinefrog-rtcp-trunk/channels/sip/include/rtcp.h Sun Apr 14 19:58:50 2013
@@ -1,0 +1,50 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013 Olle E. Johansson, Edvina AB
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file rtcp.h
+ *
+ * \brief RTCP additional functions
+ *
+ * \author Olle E. Johansson <oej at edvina.net>
+ */
+
+#include "asterisk.h"
+
+#include "asterisk/utils.h"
+#include "asterisk/rtp_engine.h"
+#include "sip.h"
+
+#ifndef _SIP_RTCP_H
+#define _SIP_RTCP_H
+
+/*! \brief Set various data items in the RTP structure, like channel identifier.
+ */
+void sip_rtcp_set_data(struct sip_pvt *dialog, struct ast_rtp_instance *instance, enum media_type type);
+
+int send_rtcp_events(const void *data);
+void start_rtcp_events(struct sip_pvt *dialog, struct ast_sched_context *sched);
+/*
+# For 1.4:
+# static void sip_rtcp_report(struct sip_pvt *p, struct ast_rtp *rtp, enum media_type type, int reporttype);
+*/
+
+void sip_rtcp_report(struct sip_pvt *dialog, struct ast_rtp_instance *instance, enum media_type type, int reporttype);
+//void qos_write_realtime(struct sip_pvt *dialog, struct ast_rtp_quality *qual);
+void qos_write_realtime(struct sip_pvt *dialog, struct ast_rtp_instance_stats *qual);
+
+
+
+#endif /* _SIP_RTCP_H */
Propchange: team/group/pinefrog-rtcp-trunk/channels/sip/include/rtcp.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/group/pinefrog-rtcp-trunk/channels/sip/include/rtcp.h
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/group/pinefrog-rtcp-trunk/channels/sip/include/rtcp.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/group/pinefrog-rtcp-trunk/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/team/group/pinefrog-rtcp-trunk/channels/sip/include/sip.h?view=diff&rev=385680&r1=385638&r2=385680
==============================================================================
--- team/group/pinefrog-rtcp-trunk/channels/sip/include/sip.h (original)
+++ team/group/pinefrog-rtcp-trunk/channels/sip/include/sip.h Sun Apr 14 19:58:50 2013
@@ -754,6 +754,8 @@
int compactheaders; /*!< send compact sip headers */
int allow_external_domains; /*!< Accept calls to external SIP domains? */
int callevents; /*!< Whether we send manager events or not */
+ int rtcpevents; /*!< Whether we send manager RTCP events or not */
+ int rtcptimer; /*!< How often, during a call, to report RTCP stats */
int regextenonqualify; /*!< Whether to add/remove regexten when qualifying peers */
int legacy_useroption_parsing; /*!< Whether to strip useroptions in URI via semicolons */
int send_diversion; /*!< Whether to Send SIP Diversion headers */
@@ -1163,6 +1165,7 @@
int waitid; /*!< Wait ID for scheduler after 491 or other delays */
int reinviteid; /*!< Reinvite in case of provisional, but no final response */
int autokillid; /*!< Auto-kill ID (scheduler) */
+ int rtcpeventid; /*!< Scheduler ID for RTCP Events */
int t38id; /*!< T.38 Response ID */
struct sip_refer *refer; /*!< REFER: SIP transfer data structure */
enum subscriptiontype subscribed; /*!< SUBSCRIBE: Is this dialog a subscription? */
@@ -1192,6 +1195,9 @@
struct sip_srtp *srtp; /*!< Structure to hold Secure RTP session data for audio */
struct sip_srtp *vsrtp; /*!< Structure to hold Secure RTP session data for video */
struct sip_srtp *tsrtp; /*!< Structure to hold Secure RTP session data for text */
+ struct ast_rtp_instance_stats *audioqual; /*!< Audio: The latest quality report, for realtime storage */
+ struct ast_rtp_instance_stats *videoqual; /*!< Video: The latest quality report, for realtime storage */
+ struct sip_settings *sip_cfg; /*! Which sip_cfg is associated with this dialog */
int red; /*!< T.140 RTP Redundancy */
int hangupcause; /*!< Storage of hangupcause copied from our owner before we disconnect from the AST channel (only used at hangup) */
Added: team/group/pinefrog-rtcp-trunk/channels/sip/rtcp.c
URL: http://svnview.digium.com/svn/asterisk/team/group/pinefrog-rtcp-trunk/channels/sip/rtcp.c?view=auto&rev=385680
==============================================================================
--- team/group/pinefrog-rtcp-trunk/channels/sip/rtcp.c (added)
+++ team/group/pinefrog-rtcp-trunk/channels/sip/rtcp.c Sun Apr 14 19:58:50 2013
@@ -1,0 +1,382 @@
+/*
+* Asterisk -- An open source telephony toolkit.
+*
+* Copyright (C) 2013 Olle E. Johansson, Edvina AB
+*
+* See http://www.asterisk.org for more information about
+* the Asterisk project. Please do not directly contact
+* any of the maintainers of this project for assistance;
+* the project provides a web site, mailing lists and IRC
+* channels for your use.
+*
+* This program is free software, distributed under the terms of
+* the GNU General Public License Version 2. See the LICENSE file
+* at the top of the source tree.
+*/
+
+/*! \file rtcp.c
+*
+* \brief RTCP additional functions
+*
+* \author Olle E. Johansson <oej at edvina.net>
+*/
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/utils.h"
+#include "asterisk/manager.h"
+#include "asterisk/logger.h"
+#include "asterisk/translate.h"
+#include "asterisk/rtp_engine.h"
+#include "include/sip.h"
+#include "include/rtcp.h"
+
+/*! \brief Set various data items in the RTP structure, like channel identifier.
+ */
+void sip_rtcp_set_data(struct sip_pvt *dialog, struct ast_rtp_instance *instance, enum media_type type)
+{
+
+ if (dialog && dialog->owner) {
+ struct ast_channel *bridgepeer = ast_bridged_channel(dialog->owner);
+
+ if (bridgepeer) {
+ /* Store the bridged peer data while we have it */
+ ast_rtp_instance_set_bridged_chan(instance, ast_channel_name(dialog->owner), ast_channel_uniqueid(dialog->owner), S_OR(ast_channel_name(bridgepeer), ""), S_OR(ast_channel_uniqueid(bridgepeer), ""));
+ ast_debug(1, "---- Setting bridged peer name to %s\n", ast_channel_name(bridgepeer));
+ } else {
+ ast_rtp_instance_set_bridged_chan(instance, ast_channel_name(dialog->owner), ast_channel_uniqueid(dialog->owner), NULL, NULL);
+ }
+ ast_debug(1, "---- Setting channel name to %s\n", ast_channel_name(dialog->owner));
+
+ /* Try to find out if there's active transcoding */
+ /* Currently, the only media stream that has translation is the audio stream. At some point
+ we might have transcoding for other types of media. */
+ if (type == SDP_AUDIO) {
+ const char *rtname = NULL, *wtname = NULL;
+ struct ast_trans_pvt *rt, *wt;
+
+ /* if we have a translator, the bridge delay is increased, which affects the QoS of the call. */
+ rt = ast_channel_readtrans(dialog->owner);
+ wt = ast_channel_writetrans(dialog->owner);
+ if (rt) {
+ rtname = rt->t->name;
+ }
+ if (wt) {
+ wtname = wt->t->name;
+ }
+ if (rt || wt) {
+ ast_rtp_instance_set_translator(instance, rtname, rt ? rt->t->comp_cost : (const int) 0,
+ wtname, wt ? wt->t->comp_cost : (const int) 0);
+ }
+
+ if (option_debug > 1) {
+ if (rt && rt->t) {
+ ast_debug(1, "--- Audio Read translator: %s Cost %d\n", rt->t->name, rt->t->comp_cost);
+ }
+ if (wt && wt->t) {
+ ast_debug(1, "--- Audio Write translator: %s Cost %d\n", wt->t->name, wt->t->comp_cost);
+ }
+ }
+ }
+
+ } else {
+ ast_debug(1, "######## Not setting rtcp media data. Dialog %s Dialog owner %s \n", dialog ? "set" : "unset", dialog->owner ? "set" : "unset");
+ }
+}
+
+/*! \brief send manager report of RTCP
+ reporttype = 0 means report during call (if configured)
+ reporttype = 1 means endof-call (hangup) report
+ reporttype = 10 means report at end of call leg (like transfer)
+*/
+void sip_rtcp_report(struct sip_pvt *dialog, struct ast_rtp_instance *instance, enum media_type media, int reporttype)
+{
+ struct ast_rtp_instance_stats qual;
+ //char *rtpqstring = NULL;
+ //int qosrealtime = ast_check_realtime("rtpcqr");
+ unsigned int duration; /* Duration in secs */
+ memset(&qual, 0, sizeof(qual));
+
+ sip_rtcp_set_data(dialog, instance, media);
+
+ if (ast_rtp_instance_get_stats(instance, &qual, AST_RTP_INSTANCE_STAT_ALL)) {
+ ast_debug(1, "######## Did not get any statistics... bad, bad, RTP instance\n");
+ /* Houston, we got a problem */
+ return;
+ }
+
+ if (dialog->sip_cfg->rtcpevents) {
+ /*
+ If numberofreports == 0 we have no incoming RTCP active, thus we can't
+ get any reliable data to handle packet loss or any RTT timing.
+ */
+
+ duration = (unsigned int)(ast_tvdiff_ms(ast_tvnow(), qual.start) / 1000);
+ manager_event(EVENT_FLAG_CALL, "RTPQuality",
+ "Channel: %s\r\n" /* AST_CHANNEL for this call */
+ "Uniqueid: %s\r\n" /* AST_CHANNEL for this call */
+ "BridgedChannel: %s\r\n"
+ "BridgedUniqueid: %s\r\n"
+ "RTPreporttype: %s\r\n"
+ "RTPrtcpstatus: %s\r\n"
+ "Duration: %u\r\n" /* used in cdr_manager */
+ "PvtCallid: %s\r\n" /* ??? Generic PVT identifier */
+ "RTPipaddress: %s\r\n"
+ "RTPmedia: %s\r\n" /* Audio, video, text */
+ "RTPsendformat: %s\r\n"
+ "RTPrecvformat: %s\r\n"
+ "RTPlocalssrc: %u\r\n"
+ "RTPremotessrc: %u\r\n"
+ "RTPrtt: %f\r\n"
+ "RTPrttMax: %f\r\n"
+ "RTPrttMin: %f\r\n"
+ "RTPLocalJitter: %f\r\n"
+ "RTPRemoteJitter: %f\r\n"
+ "RTPInPacketLoss: %d\r\n"
+ "RTPInLocalPlPercent: %5.2f\r\n"
+ "RTPOutPacketLoss: %d\r\n"
+ "RTPOutPlPercent: %5.2f\r\n"
+ "TranslateRead: %s\r\n"
+ "TranslateReadCost: %d\r\n"
+ "TranslateWrite: %s\r\n"
+ "TranslateWriteCost: %d\r\n"
+ "\r\n",
+ dialog->owner ? ast_channel_name(dialog->owner) : "",
+ dialog->owner ? ast_channel_uniqueid(dialog->owner) : "",
+ qual.bridgedchannel[0] ? qual.bridgedchannel : "" ,
+ qual.bridgeduniqueid[0] ? qual.bridgeduniqueid : "",
+ reporttype == 1 ? "Final" : "Update",
+ qual.numberofreports == 0 ? "Inactive" : "Active",
+ duration,
+ dialog->callid,
+ ast_inet_ntoa(qual.them.sin_addr),
+ media == SDP_AUDIO ? "audio" : (media == SDP_VIDEO ? "video" : "fax") ,
+ ast_getformatname(&qual.lasttxformat),
+ ast_getformatname(&qual.lastrxformat),
+ qual.local_ssrc,
+ qual.remote_ssrc,
+ qual.rtt,
+ qual.maxrtt,
+ qual.minrtt,
+ qual.rxjitter,
+ qual.txjitter,
+ qual.rxploss,
+ /* The local counter of lost packets in inbound stream divided with received packets plus lost packets */
+ (qual.remote_txcount + qual.rxploss) > 0 ? (double) qual.rxploss / (qual.remote_txcount + qual.rxploss) * 100 : 0,
+ qual.txploss,
+ /* The remote counter of lost packets (if we got the reports)
+ divided with our counter of sent packets
+ */
+ (qual.rxcount + qual.txploss) > 0 ? (double) qual.txploss / qual.rxcount * 100 : 0,
+ qual.readtranslator, qual.readcost,
+ qual.writetranslator, qual.writecost
+ );
+ }
+
+ /* CDR records are not reliable when it comes to near-death-of-channel events, so we need to store the RTCP
+ report in realtime when we have it.
+ Tests have proven that storing to realtime from the call thread is NOT a good thing. Therefore, we just save
+ the quality report structure in the PVT and let the function that kills the pvt store the stuff in the
+ monitor thread instead.
+ */
+ if (reporttype == 1) {
+ ast_log(LOG_DEBUG, "---- Activation qual structure in dialog \n");
+ qual.end = ast_tvnow();
+ qual.mediatype = media;
+ if (media == SDP_AUDIO) { /* Audio */
+ dialog->audioqual = ast_calloc(1, sizeof(struct ast_rtp_instance_stats));
+ (* dialog->audioqual) = qual;
+ } else if (media == SDP_VIDEO) { /* Video */
+ dialog->videoqual = ast_calloc(1,sizeof(struct ast_rtp_instance_stats));
+ (* dialog->videoqual) = qual;
+ }
+ }
+}
+
+/*! \brief Write quality report to realtime storage */
+void qos_write_realtime(struct sip_pvt *dialog, struct ast_rtp_instance_stats *qual)
+{
+ unsigned int duration; /* Duration in secs */
+ char buf_duration[10], buf_lssrc[30], buf_rssrc[30];
+ char buf_rtt[10], buf_rttmin[10], buf_rttmax[10];
+ char localjitter[10], remotejitter[10];
+ char buf_readcost[5], buf_writecost[5];
+ char buf_mediatype[10];
+ char buf_remoteip[25];
+ char buf_inpacketloss[25], buf_outpacketloss[25];
+ char buf_outpackets[25], buf_inpackets[25];
+ int qosrealtime = ast_check_realtime("rtpcqr");
+
+
+ if (!qual) {
+ ast_log(LOG_ERROR, "No CQR data provided \n");
+ return;
+ }
+
+ /* Since the CDR is already gone, we need to calculate our own duration.
+ The CDR duration is the definitive resource for billing, this is
+ the RTP stream duration which may include early media (ringing and
+ provider messages). Only useful for measurements.
+ */
+ if (!ast_tvzero(qual->end) && !ast_tvzero(qual->start)) {
+ duration = (unsigned int)(ast_tvdiff_ms(qual->end, qual->start) / 1000);
+ } else {
+ ast_debug(2, "**** What? No duration? What type of call is THAT? \n");
+ duration = 0;
+ }
+
+ /* Realtime is based on strings, so let's make strings */
+ sprintf(localjitter, "%f", qual->rxjitter);
+ sprintf(remotejitter, "%f", qual->txjitter);
+ sprintf(buf_lssrc, "%u", qual->local_ssrc);
+ sprintf(buf_rssrc, "%u", qual->remote_ssrc);
+ sprintf(buf_rtt, "%.0f", qual->rtt);
+ sprintf(buf_rttmax, "%.0f", qual->maxrtt);
+ sprintf(buf_rttmin, "%.0f", qual->minrtt);
+ sprintf(buf_duration, "%u", duration);
+ sprintf(buf_readcost, "%d", qual->readcost);
+ sprintf(buf_writecost, "%d", qual->writecost);
+ sprintf(buf_mediatype,"%s", qual->mediatype == SDP_AUDIO ? "audio" : (qual->mediatype == SDP_VIDEO ? "video" : "fax") );
+ sprintf(buf_remoteip,"%s", ast_inet_ntoa(qual->them.sin_addr));
+ sprintf(buf_inpacketloss, "%d", qual->rxploss);
+ sprintf(buf_outpacketloss, "%d", qual->txploss);
+ sprintf(buf_inpackets, "%d", qual->rxcount); /* Silly value. Need to check this */
+ sprintf(buf_outpackets, "%d", qual->txcount);
+ //sprintf(buf_inpackets, "%d", qual->remote_count); /* Do check again */
+ //sprintf(buf_outpackets, "%d", qual->local_count);
+
+ ast_log(LOG_CQR, "CQR Channel: %s Uid %s Bch %s Buid %s Pvt %s Media %s Lssrc %s Rssrc %s Rip %s Rtt %s:%s:%s Ljitter %s Rjitter %s Rtcpstatus %s Dur %s Pout %s Plossout %s Pin %s Plossin %s\n",
+ qual->channel[0] ? qual->channel : "",
+ qual->uniqueid[0] ? qual->uniqueid : "",
+ qual->bridgedchannel[0] ? qual->bridgedchannel : "" ,
+ qual->bridgeduniqueid[0] ? qual->bridgeduniqueid : "",
+ dialog->callid,
+ buf_mediatype,
+ buf_lssrc,
+ buf_rssrc,
+ buf_remoteip,
+ buf_rtt, buf_rttmax, buf_rttmin,
+ localjitter,
+ remotejitter,
+ qual->numberofreports == 0 ? "Inactive" : "Active",
+ buf_duration,
+ buf_outpackets,
+ buf_outpacketloss,
+ buf_inpackets,
+ buf_inpacketloss);
+
+ if (!qosrealtime) {
+ return;
+ }
+/* Example database schema for MySQL:
+CREATE TABLE `astcqr` (
+ `channel` varchar(50) NOT NULL,
+ `uniqueid` varchar(35) NOT NULL,
+ `bridgedchannel` varchar(50) NOT NULL,
+ `bridgeduniqueid` varchar(35) NOT NULL,
+ `pvtcallid` varchar(80) NOT NULL,
+ `rtpmedia` varchar(50) NOT NULL,
+ `localssrc` varchar(50) NOT NULL,
+ `remotessrc` varchar(50) NOT NULL,
+ `rtt` varchar(10) NOT NULL,
+ `localjitter` varchar(10) NOT NULL,
+ `remotejitter` varchar(10) NOT NULL,
+ `sendformat` varchar(10) NOT NULL,
+ `receiveformat` varchar(10) NOT NULL,
+ `rtcpstatus` varchar(10) NOT NULL,
+ `duration` varchar(10) NOT NULL,
+ `packetsent` varchar(30) NOT NULL,
+ `packetreceived` varchar(30) NOT NULL,
+ `packetlossin` varchar(30) NOT NULL,
+ `packetlossout` varchar(30) NOT NULL,
+ `rttmax` varchar(12) NOT NULL,
+ `rttmin` varchar(12) NOT NULL,
+ `writetranslator` varchar(15) NOT NULL,
+ `readtranslator` varchar(15) NOT NULL,
+ `writecost` varchar(10) NOT NULL,
+ `readcost` varchar(10) NOT NULL,
+ `remoteip` varchar(25) NOT NULL,
+ KEY `ChannelUnique` (`channel`,`uniqueid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='FOr pinefrog stats'
+*/
+
+ ast_store_realtime("rtpcqr",
+ "channel", qual->channel[0] ? qual->channel : "--no channel--",
+ "uniqueid", qual->uniqueid[0] ? qual->uniqueid : "--no uniqueid --",
+ "bridgedchannel", qual->bridgedchannel[0] ? qual->bridgedchannel : "" ,
+ "bridgeduniqueid", qual->bridgeduniqueid[0] ? qual->bridgeduniqueid : "",
+ "pvtcallid", dialog->callid,
+ "rtpmedia", buf_mediatype,
+ "localssrc", buf_lssrc,
+ "remotessrc", buf_rssrc,
+ "remoteip", buf_remoteip,
+ "rtt", buf_rtt,
+ "rttmax", buf_rttmax,
+ "rttmin", buf_rttmin,
+ "localjitter", localjitter,
+ "remotejitter", remotejitter,
+ "sendformat", ast_getformatname(&qual->lasttxformat),
+ "receiveformat", ast_getformatname(&qual->lastrxformat),
+ "rtcpstatus", qual->numberofreports == 0 ? "Inactive" : "Active",
+ "duration", buf_duration,
+ "writetranslator", qual->writetranslator[0] ? qual->writetranslator : "",
+ "writecost", buf_writecost,
+ "readtranslator", qual->readtranslator[0] ? qual->readtranslator : "",
+ "readcost", buf_readcost,
+ "packetlossin", buf_inpacketloss,
+ "packetlossout", buf_outpacketloss,
+ "packetsent", buf_outpackets,
+ "packetreceived", buf_inpackets,
+ NULL);
+}
+
+/*! \brief Send RTCP manager events */
+int send_rtcp_events(const void *data)
+{
+ struct sip_pvt *dialog = (struct sip_pvt *) data;
+ ast_log(LOG_DEBUG, "***** SENDING RTCP EVENT \n");
+
+ if (dialog->rtp && !ast_rtp_instance_isactive(dialog->rtp)) {
+ ast_debug(1, " ***** Activating RTCP report \n");
+ sip_rtcp_report(dialog, dialog->rtp, SDP_AUDIO, FALSE);
+ } else {
+ ast_debug(1, " ***** NOT Activating RTCP report \n");
+ }
+ if (dialog->vrtp && !ast_rtp_instance_isactive(dialog->vrtp)) {
+ sip_rtcp_report(dialog, dialog->vrtp, SDP_VIDEO, FALSE);
+ }
+ return (dialog->sip_cfg ? dialog->sip_cfg->rtcptimer : 0);
+}
+
+/*! \brief Activate RTCP events at start of call */
+void start_rtcp_events(struct sip_pvt *dialog, struct ast_sched_context *sched)
+{
+ ast_debug(2, "***** STARTING SENDING RTCP EVENT \n");
+ /* Check if it's already active */
+
+ if (dialog->rtp && !ast_rtp_instance_isactive(dialog->rtp)) {
+ sip_rtcp_set_data(dialog, dialog->rtp, SDP_AUDIO);
+ }
+ if (dialog->vrtp && !ast_rtp_instance_isactive(dialog->vrtp)) {
+ sip_rtcp_set_data(dialog, dialog->vrtp, SDP_VIDEO);
+ }
+
+ if (!dialog->sip_cfg->rtcpevents || !dialog->sip_cfg->rtcptimer) {
+ ast_debug(2, "***** NOT SENDING RTCP EVENTS \n");
+ return;
+ }
+
+ if (dialog->rtcpeventid != -1) {
+ return;
+ }
+
+
+ /*! \brief Schedule events */
+ dialog->rtcpeventid = ast_sched_add(sched, dialog->sip_cfg->rtcptimer * 1000, send_rtcp_events, dialog);
+}
Propchange: team/group/pinefrog-rtcp-trunk/channels/sip/rtcp.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/group/pinefrog-rtcp-trunk/channels/sip/rtcp.c
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/group/pinefrog-rtcp-trunk/channels/sip/rtcp.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/group/pinefrog-rtcp-trunk/contrib/realtime/mysql/sippeers.sql
URL: http://svnview.digium.com/svn/asterisk/team/group/pinefrog-rtcp-trunk/contrib/realtime/mysql/sippeers.sql?view=diff&rev=385680&r1=385638&r2=385680
==============================================================================
--- team/group/pinefrog-rtcp-trunk/contrib/realtime/mysql/sippeers.sql (original)
+++ team/group/pinefrog-rtcp-trunk/contrib/realtime/mysql/sippeers.sql Sun Apr 14 19:58:50 2013
@@ -5,19 +5,19 @@
CREATE TABLE IF NOT EXISTS `sippeers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) NOT NULL,
- `ipaddr` varchar(45) DEFAULT NULL,
+ `ipaddr` varchar(15) DEFAULT NULL,
`port` int(5) DEFAULT NULL,
`regseconds` int(11) DEFAULT NULL,
`defaultuser` varchar(10) DEFAULT NULL,
- `fullcontact` varchar(80) DEFAULT NULL,
+ `fullcontact` varchar(35) DEFAULT NULL,
`regserver` varchar(20) DEFAULT NULL,
`useragent` varchar(20) DEFAULT NULL,
`lastms` int(11) DEFAULT NULL,
`host` varchar(40) DEFAULT NULL,
`type` enum('friend','user','peer') DEFAULT NULL,
`context` varchar(40) DEFAULT NULL,
- `permit` varchar(95) DEFAULT NULL,
- `deny` varchar(95) DEFAULT NULL,
+ `permit` varchar(40) DEFAULT NULL,
+ `deny` varchar(40) DEFAULT NULL,
`secret` varchar(40) DEFAULT NULL,
`md5secret` varchar(40) DEFAULT NULL,
`remotesecret` varchar(40) DEFAULT NULL,
@@ -56,7 +56,7 @@
`fromdomain` varchar(40) DEFAULT NULL,
`fromuser` varchar(40) DEFAULT NULL,
`qualify` varchar(40) DEFAULT NULL,
- `defaultip` varchar(45) DEFAULT NULL,
+ `defaultip` varchar(40) DEFAULT NULL,
`rtptimeout` int(11) DEFAULT NULL,
`rtpholdtimeout` int(11) DEFAULT NULL,
`sendrpid` enum('yes','no') DEFAULT NULL,
@@ -66,8 +66,8 @@
`timerb` int(11) DEFAULT NULL,
`qualifyfreq` int(11) DEFAULT NULL,
`constantssrc` enum('yes','no') DEFAULT NULL,
- `contactpermit` varchar(95) DEFAULT NULL,
- `contactdeny` varchar(95) DEFAULT NULL,
+ `contactpermit` varchar(40) DEFAULT NULL,
+ `contactdeny` varchar(40) DEFAULT NULL,
`usereqphone` enum('yes','no') DEFAULT NULL,
`textsupport` enum('yes','no') DEFAULT NULL,
`faxdetect` enum('yes','no') DEFAULT NULL,
Modified: team/group/pinefrog-rtcp-trunk/contrib/realtime/postgresql/realtime.sql
URL: http://svnview.digium.com/svn/asterisk/team/group/pinefrog-rtcp-trunk/contrib/realtime/postgresql/realtime.sql?view=diff&rev=385680&r1=385638&r2=385680
==============================================================================
--- team/group/pinefrog-rtcp-trunk/contrib/realtime/postgresql/realtime.sql (original)
+++ team/group/pinefrog-rtcp-trunk/contrib/realtime/postgresql/realtime.sql Sun Apr 14 19:58:50 2013
@@ -40,7 +40,7 @@
canreinvite character varying(3) DEFAULT 'yes',
supportpath character varying(3) DEFAULT 'no',
context character varying(80),
-defaultip character varying(45),
+defaultip character varying(15),
dtmfmode character varying(7),
fromuser character varying(80),
fromdomain character varying(80),
Modified: team/group/pinefrog-rtcp-trunk/include/asterisk/logger.h
URL: http://svnview.digium.com/svn/asterisk/team/group/pinefrog-rtcp-trunk/include/asterisk/logger.h?view=diff&rev=385680&r1=385638&r2=385680
==============================================================================
--- team/group/pinefrog-rtcp-trunk/include/asterisk/logger.h (original)
+++ team/group/pinefrog-rtcp-trunk/include/asterisk/logger.h Sun Apr 14 19:58:50 2013
@@ -209,7 +209,18 @@
#endif
#define AST_LOG_DTMF __LOG_DTMF, _A_
-#define NUMLOGLEVELS 32
+#ifdef LOG_CQR
+#undef LOG_CQR
+#endif
+#define __LOG_CQR 7
+#define LOG_CQR __LOG_CQR, _A_
+
+#ifdef AST_LOG_CQR
+#undef AST_LOG_CQR
+#endif
+#define AST_LOG_CQR __LOG_CQR, _A_
+
+#define NUMLOGLEVELS 64 /* Highest bit */
/*!
* \brief Get the debug level for a module
Modified: team/group/pinefrog-rtcp-trunk/include/asterisk/rtp_engine.h
URL: http://svnview.digium.com/svn/asterisk/team/group/pinefrog-rtcp-trunk/include/asterisk/rtp_engine.h?view=diff&rev=385680&r1=385638&r2=385680
==============================================================================
--- team/group/pinefrog-rtcp-trunk/include/asterisk/rtp_engine.h (original)
+++ team/group/pinefrog-rtcp-trunk/include/asterisk/rtp_engine.h Sun Apr 14 19:58:50 2013
@@ -74,6 +74,7 @@
#include "asterisk/netsock2.h"
#include "asterisk/sched.h"
#include "asterisk/res_srtp.h"
+#include "asterisk/channel.h"
/* Maximum number of payloads supported */
#if defined(LOW_MEMORY)
@@ -215,6 +216,14 @@
AST_RTP_INSTANCE_STAT_LOCAL_SSRC,
/*! Retrieve remote SSRC */
AST_RTP_INSTANCE_STAT_REMOTE_SSRC,
+ /*! Retrieve local CNAME */
+ AST_RTP_INSTANCE_STAT_LOCAL_CNAME,
+ /*! Retrieve remote SDES */
+ AST_RTP_INSTANCE_STAT_REMOTE_CNAME,
+ /*! Retrieve start time */
+ AST_RTP_INSTANCE_STAT_START,
+ /*! Retrieve IP Address */
+ AST_RTP_INSTANCE_STAT_IP,
};
/* Codes for RTP-specific data - not defined by our AST_FORMAT codes */
@@ -246,10 +255,12 @@
unsigned int txcount;
/*! Number of packets received */
unsigned int rxcount;
+
/*! Jitter on transmitted packets */
double txjitter;
/*! Jitter on received packets */
double rxjitter;
+
/*! Maximum jitter on remote side */
double remote_maxjitter;
/*! Minimum jitter on remote side */
@@ -300,6 +311,32 @@
unsigned int local_ssrc;
/*! Their SSRC */
unsigned int remote_ssrc;
+
+ /* --- Pinefrog additions */
+ /*! Remote: Number of packets transmitted */
+ unsigned int remote_txcount;
+ /*! Remote: Number of packets received */
+ unsigned int remote_rxcount;
+ char channel[AST_MAX_EXTENSION]; /*!< Name of channel */
+ char uniqueid[AST_MAX_EXTENSION]; /*!< uniqueid of channel */
+ char bridgedchannel[AST_MAX_EXTENSION]; /*!< Name of bridged channel */
+ char bridgeduniqueid[AST_MAX_EXTENSION]; /*!< uniqueid of bridged channel */
+ unsigned int numberofreports; /*!< Number of reports received from remote end */
+ struct ast_format lasttxformat; /*!< Last used codec on transmitted stream */
+ struct ast_format lastrxformat; /*!< Last used codec on received stream */
+ struct sockaddr_in them; /*!< The IP address used for media by remote end */
+ struct sockaddr_in us; /*!< The IP address used for media by our end */
+ char ourcname[255]; /*!< Our SDES RTP session name (CNAME) */
+ size_t ourcnamelength; /*!< Length of CNAME (utf8) */
+ char theircname[255]; /*!< Their SDES RTP session name (CNAME) */
+ size_t theircnamelength; /*!< Length of CNAME (utf8) */
+ struct timeval start; /*!< When the stream started */
+ struct timeval end; /*!< When the stream ended */
+ char writetranslator[80]; /*!< Translator used when writing */
+ char readtranslator[80]; /*!< Translator providing frames when reading */
+ int writecost; /*!< Cost in milliseconds for encoding/decoding 1 second of outbound media */
+ int readcost; /*!< Cost in milliseconds for encoding/decoding 1 second of inbound media */
+ int mediatype; /*! Type of media */
};
#define AST_RTP_STAT_SET(current_stat, combined, placement, value) \
@@ -420,6 +457,9 @@
int (*destroy)(struct ast_rtp_instance *instance);
/*! Callback for writing out a frame */
int (*write)(struct ast_rtp_instance *instance, struct ast_frame *frame);
+ /*! Callback for stopping the outbound RTP media for an instance,
+ but keeping the RTCP flow (and the RTP keepalives if needed) */
+ void (*hold)(struct ast_rtp_instance *instance, int status);
/*! Callback for stopping the RTP instance */
void (*stop)(struct ast_rtp_instance *instance);
/*! Callback for starting RFC2833 DTMF transmission */
@@ -481,6 +521,15 @@
struct ast_rtp_engine_ice *ice;
/*! Callback to pointer for optional DTLS SRTP support */
struct ast_rtp_engine_dtls *dtls;
+ /*! Callback to check if a media stram is active */
+ int (*isactive)(struct ast_rtp_instance *instance);
+ /*! Callback to set CNAME in rtcp */
+ void (*setcname)(struct ast_rtp_instance *instance, const char *cname, size_t length);
+ /*! Callback to set information about bridged channel for CQR record */
+ void (*set_bridged_chan)(struct ast_rtp_instance *instance, const char *channel, const char *uniqueid, const char *bridgedchan, const char *bridgeduniqueid);
[... 1341 lines stripped ...]
More information about the asterisk-commits
mailing list