[asterisk-commits] oej: branch oej/pinefrog-rtcp-11 r383047 - in /team/oej/pinefrog-rtcp-11: ./ ...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Mar 14 06:16:08 CDT 2013
Author: oej
Date: Thu Mar 14 06:16:03 2013
New Revision: 383047
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=383047
Log:
And here it is. Tadaaa! Pinefrog for Asterisk 11. Not tested yet. I REALLY look forward to
getting YOUR test results from this branch! Thank you! I do APPRECIATE your efforts to support
this work! You're a pal!
Modified:
team/oej/pinefrog-rtcp-11/CREDITS
team/oej/pinefrog-rtcp-11/channels/chan_sip.c
team/oej/pinefrog-rtcp-11/channels/sip/dialplan_functions.c
team/oej/pinefrog-rtcp-11/channels/sip/include/sip.h
team/oej/pinefrog-rtcp-11/configs/extconfig.conf.sample
team/oej/pinefrog-rtcp-11/include/asterisk/logger.h
team/oej/pinefrog-rtcp-11/include/asterisk/rtp_engine.h
team/oej/pinefrog-rtcp-11/include/asterisk/translate.h
team/oej/pinefrog-rtcp-11/main/logger.c
team/oej/pinefrog-rtcp-11/main/rtp_engine.c
team/oej/pinefrog-rtcp-11/res/res_rtp_asterisk.c
Modified: team/oej/pinefrog-rtcp-11/CREDITS
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-rtcp-11/CREDITS?view=diff&rev=383047&r1=383046&r2=383047
==============================================================================
--- team/oej/pinefrog-rtcp-11/CREDITS (original)
+++ team/oej/pinefrog-rtcp-11/CREDITS Thu Mar 14 06:16:03 2013
@@ -24,6 +24,9 @@
originate with video/text and many more contributions.
ClearIT AB for work with meetme, res_mutestream, RTCP, manager and tonezones
+
+Nordicom Norge AS, Kristiansand, Norway, for funding work with RTCP support
+and Call Quality Records.
=== WISHLIST CONTRIBUTERS ===
Jeremy McNamara - SpeeX support
@@ -118,6 +121,7 @@
SIP presence support, SIP call state updates (dialog-info),
QUEUE_EXISTS function, device state provider architecture,
multiparking (together with mvanbaak), meetme and parking device states,
+ RTCP improvements, Call Quality Records,
MiniVM - the small voicemail system, many documentation
updates/corrections, and many bug fixes.
oej(AT)edvina.net, http://edvina.net
@@ -219,7 +223,8 @@
Viagenie, Canada - IPv6 support in socket layers and SIP 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/oej/pinefrog-rtcp-11/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-rtcp-11/channels/chan_sip.c?view=diff&rev=383047&r1=383046&r2=383047
==============================================================================
--- team/oej/pinefrog-rtcp-11/channels/chan_sip.c (original)
+++ team/oej/pinefrog-rtcp-11/channels/chan_sip.c Thu Mar 14 06:16:03 2013
@@ -281,6 +281,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"
/*** DOCUMENTATION
@@ -724,7 +725,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
@@ -6512,6 +6512,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) {
@@ -7257,6 +7273,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;
@@ -8639,8 +8656,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;
@@ -8702,6 +8721,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);
@@ -9744,6 +9771,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;
}
@@ -10713,9 +10741,9 @@
ast_queue_control_data(p->owner, AST_CONTROL_HOLD,
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);
@@ -19727,8 +19755,10 @@
int x = 0, load_realtime;
struct ast_format codec;
int realtimepeers;
+ int realtimertpqos = FALSE;
realtimepeers = ast_check_realtime("sippeers");
+ realtimertpqos = ast_check_realtime("rtpcqr");
if (argc < 4)
return CLI_SHOWUSAGE;
@@ -20371,9 +20401,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:
@@ -20391,6 +20423,7 @@
realtimepeers = ast_check_realtime("sippeers");
realtimeregs = ast_check_realtime("sipregs");
+ realtimertpqos = ast_check_realtime("rtpcqr");
ast_mutex_lock(&authl_lock);
credentials = authl;
@@ -20463,6 +20496,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)));
@@ -20472,6 +20507,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));
@@ -22491,6 +22527,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 */
@@ -22778,6 +22815,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 */
@@ -23487,16 +23525,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);
}
@@ -26514,6 +26557,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);
@@ -26544,6 +26588,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);
}
@@ -31262,6 +31307,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;
@@ -31737,6 +31784,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/oej/pinefrog-rtcp-11/channels/sip/dialplan_functions.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-rtcp-11/channels/sip/dialplan_functions.c?view=diff&rev=383047&r1=383046&r2=383047
==============================================================================
--- team/oej/pinefrog-rtcp-11/channels/sip/dialplan_functions.c (original)
+++ team/oej/pinefrog-rtcp-11/channels/sip/dialplan_functions.c Thu Mar 14 06:16:03 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;
Modified: team/oej/pinefrog-rtcp-11/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-rtcp-11/channels/sip/include/sip.h?view=diff&rev=383047&r1=383046&r2=383047
==============================================================================
--- team/oej/pinefrog-rtcp-11/channels/sip/include/sip.h (original)
+++ team/oej/pinefrog-rtcp-11/channels/sip/include/sip.h Thu Mar 14 06:16:03 2013
@@ -750,6 +750,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 */
@@ -1159,6 +1161,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? */
@@ -1188,6 +1191,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) */
Modified: team/oej/pinefrog-rtcp-11/configs/extconfig.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-rtcp-11/configs/extconfig.conf.sample?view=diff&rev=383047&r1=383046&r2=383047
==============================================================================
--- team/oej/pinefrog-rtcp-11/configs/extconfig.conf.sample (original)
+++ team/oej/pinefrog-rtcp-11/configs/extconfig.conf.sample Thu Mar 14 06:16:03 2013
@@ -82,6 +82,7 @@
;acls => odbc,asterisk
;musiconhold => mysql,general
;queue_log => mysql,general
+;rtpcqr => mysql,general,astcqr ; RTP Call Quality Records
;
;
; While most dynamic realtime engines are automatically used when defined in
Modified: team/oej/pinefrog-rtcp-11/include/asterisk/logger.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-rtcp-11/include/asterisk/logger.h?view=diff&rev=383047&r1=383046&r2=383047
==============================================================================
--- team/oej/pinefrog-rtcp-11/include/asterisk/logger.h (original)
+++ team/oej/pinefrog-rtcp-11/include/asterisk/logger.h Thu Mar 14 06:16:03 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/oej/pinefrog-rtcp-11/include/asterisk/rtp_engine.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-rtcp-11/include/asterisk/rtp_engine.h?view=diff&rev=383047&r1=383046&r2=383047
==============================================================================
--- team/oej/pinefrog-rtcp-11/include/asterisk/rtp_engine.h (original)
+++ team/oej/pinefrog-rtcp-11/include/asterisk/rtp_engine.h Thu Mar 14 06:16:03 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 */
@@ -483,6 +523,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);
+ /*! Callback to set translation information for the CQR record */
+ void (*set_translator) (struct ast_rtp_instance *instance, const char *readtranslator, const int readcost, const char *writetranslator, const int writecost);
+ int (*rtcp_write_empty)(struct ast_rtp_instance *instance);
/*! Linked list information */
AST_RWLIST_ENTRY(ast_rtp_engine) entry;
};
@@ -1508,6 +1557,26 @@
int ast_rtp_instance_set_qos(struct ast_rtp_instance *instance, int tos, int cos, const char *desc);
/*!
+ * \brief Stop the RTP outbound media in a stream, but keep the RTCP flow going
+ * And propably RTP keepalives too.
+ *
+ * \param instance Instance that media is no longer going to at this time
+ *
+ * Example usage:
+ *
+ * \code
+ * ast_rtp_instance_stop(instance);
+ * \endcode
+ *
+ * This tells the RTP engine being used for the instance pointed to by instance
+ * that media is no longer going to it at this time, but may in the future.
+ * Keep the RTCP flow happy
+ *
+ * \since 1.42
+ */
+void ast_rtp_instance_hold(struct ast_rtp_instance *instance, int status);
+
+/*!
* \brief Stop an RTP instance
*
* \param instance Instance that media is no longer going to at this time
@@ -2032,6 +2101,36 @@
int ast_rtp_instance_sendcng(struct ast_rtp_instance *instance, int level);
/*!
+ * \brief Send empty RTCP report
+ *
+ * \param instance The RTP instance
+ * \param fd File descriptor to use
+ *
+ * \retval 0 Success
+ * \retval non-zero Failure
+ */
+int ast_rtcp_write_empty(struct ast_rtp_instance *instance);
+
+
+/*!
+ * \brief Check if RTP stream is active
+ *
+ * \param instance The RTP instance
+ *
+ * \retval 0 Active (success)
+ * \retval -1 Not supported by RTP engine, 1 Not active
+ */
+int ast_rtp_instance_isactive(struct ast_rtp_instance *instance);
+
+/*!
+ * \brief Set the name of the RTP session (used in RTCP)
+ * \param cname Session name (UTF 8 possible)
+ * \param length Name of string (needed for UTF 8 always)
+ *
+ */
+int ast_rtp_instance_setcname(struct ast_rtp_instance *instance, const char *cname, size_t length);
+
+/*!
* \brief Add or replace the SRTP policies for the given RTP instance
*
* \param instance the RTP instance
@@ -2108,6 +2207,22 @@
*/
void ast_rtp_dtls_cfg_free(struct ast_rtp_dtls_cfg *dtls_cfg);
+/*!
+ * \brief set the channel information for the CQR records
+ *
+ * \retval 0 on success
+ * \retval -1 not implemented by RTP engine
+ */
+int ast_rtp_instance_set_bridged_chan(struct ast_rtp_instance *instance, const char *channel, const char *uniqueid, const char *bridgedchan, const char *bridgeduniqueid);
+
+/*!
+ * \brief set the channel translator information for the CQR records
+ *
+ * \retval 0 on success
+ * \retval -1 not implemented by RTP engine
+ */
+int ast_rtp_instance_set_translator(struct ast_rtp_instance *instance, const char *readtranslator, const int readcost, const char *writetranslator, const int writecost);
+
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
Modified: team/oej/pinefrog-rtcp-11/include/asterisk/translate.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-rtcp-11/include/asterisk/translate.h?view=diff&rev=383047&r1=383046&r2=383047
==============================================================================
--- team/oej/pinefrog-rtcp-11/include/asterisk/translate.h (original)
+++ team/oej/pinefrog-rtcp-11/include/asterisk/translate.h Thu Mar 14 06:16:03 2013
@@ -141,7 +141,7 @@
* on translation cost table. */
int comp_cost; /*!< Cost value associated with this translator based
* on computation time. This cost value is computed based
- * on the time required to translate sample data. */
+ * on the time required to translate sample data. */
int (*newpvt)(struct ast_trans_pvt *); /*!< initialize private data
* associated with the translator */
Modified: team/oej/pinefrog-rtcp-11/main/logger.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-rtcp-11/main/logger.c?view=diff&rev=383047&r1=383046&r2=383047
==============================================================================
--- team/oej/pinefrog-rtcp-11/main/logger.c (original)
+++ team/oej/pinefrog-rtcp-11/main/logger.c Thu Mar 14 06:16:03 2013
@@ -191,6 +191,7 @@
"ERROR",
"VERBOSE",
"DTMF",
+ "CQR",
};
/*! \brief Colors used in the console for logging */
@@ -202,7 +203,7 @@
COLOR_RED,
COLOR_GREEN,
COLOR_BRGREEN,
- 0,
+ COLOR_BRBLUE,
0,
0,
0,
Modified: team/oej/pinefrog-rtcp-11/main/rtp_engine.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-rtcp-11/main/rtp_engine.c?view=diff&rev=383047&r1=383046&r2=383047
==============================================================================
--- team/oej/pinefrog-rtcp-11/main/rtp_engine.c (original)
+++ team/oej/pinefrog-rtcp-11/main/rtp_engine.c Thu Mar 14 06:16:03 2013
@@ -21,6 +21,9 @@
* \brief Pluggable RTP Architecture
*
* \author Joshua Colp <jcolp at digium.com>
+ *
+ * Improved RTCP support by
+ * \author Olle E. Johansson <oej at edvina.net>
*/
/*** MODULEINFO
@@ -915,6 +918,13 @@
return instance->engine->qos ? instance->engine->qos(instance, tos, cos, desc) : -1;
}
+void ast_rtp_instance_hold(struct ast_rtp_instance *instance, int status)
+{
+ if (instance->engine->hold) {
+ instance->engine->hold(instance, status);
+ }
+}
+
void ast_rtp_instance_stop(struct ast_rtp_instance *instance)
{
if (instance->engine->stop) {
@@ -968,6 +978,7 @@
return AST_BRIDGE_FAILED_NOWARN;
}
+ /* Now let go of the channel locks and be on our way */
ast_channel_unlock(c0);
ast_channel_unlock(c1);
@@ -975,6 +986,10 @@
instance1->bridged = instance0;
ast_poll_channel_add(c0, c1);
+
+ /* Kick the RTCP stream going by sending one empty stupid little packet */
+ ast_rtcp_write_empty(instance0);
+ ast_rtcp_write_empty(instance1);
/* Hop into a loop waiting for a frame from either channel */
cs[0] = c0;
@@ -2065,6 +2080,56 @@
return instance->srtp;
}
+
+int ast_rtp_instance_isactive(struct ast_rtp_instance *instance)
+{
+ if (instance->engine->isactive) {
+ return instance->engine->isactive(instance);
+ }
+ return -1;
+}
+
+int ast_rtcp_write_empty(struct ast_rtp_instance *instance)
+{
+ if (instance->engine->rtcp_write_empty) {
+ instance->engine->rtcp_write_empty(instance);
+ return 0;
+ }
+ return -1;
+}
+
+int ast_rtp_instance_setcname(struct ast_rtp_instance *instance, const char *cname, size_t length)
+{
+ if (instance->engine->setcname) {
+ instance->engine->setcname(instance, cname, length);
+ return 0;
+ }
+
+ return -1; /* Function does not exist */
+}
+
+int ast_rtp_instance_set_bridged_chan(struct ast_rtp_instance *instance, const char *channel, const char *uniqueid, const char *bridgedchan, const char *bridgeduniqueid)
+{
+ if (instance->engine->set_bridged_chan) {
+ instance->engine->set_bridged_chan(instance, channel, uniqueid, bridgedchan, bridgeduniqueid);
+ return 0;
+ }
+
+ return -1; /* Function does not exist */
+}
+
+
+int ast_rtp_instance_set_translator(struct ast_rtp_instance *instance, const char *readtranslator, const int readcost, const char *writetranslator, const int writecost)
+{
+ if (instance->engine->set_translator) {
+ instance->engine->set_translator(instance, readtranslator, readcost, writetranslator, writecost);
+ return 0;
+ }
+
+ return -1; /* Function does not exist */
+}
+
+
int ast_rtp_instance_sendcng(struct ast_rtp_instance *instance, int level)
{
if (instance->engine->sendcng) {
Modified: team/oej/pinefrog-rtcp-11/res/res_rtp_asterisk.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-rtcp-11/res/res_rtp_asterisk.c?view=diff&rev=383047&r1=383046&r2=383047
==============================================================================
--- team/oej/pinefrog-rtcp-11/res/res_rtp_asterisk.c (original)
+++ team/oej/pinefrog-rtcp-11/res/res_rtp_asterisk.c Thu Mar 14 06:16:03 2013
@@ -85,12 +85,32 @@
#define TURN_ALLOCATION_WAIT_TIME 2000
-#define RTCP_PT_FUR 192
-#define RTCP_PT_SR 200
-#define RTCP_PT_RR 201
-#define RTCP_PT_SDES 202
-#define RTCP_PT_BYE 203
-#define RTCP_PT_APP 204
+#define RTCP_PT_FUR 192 /*!< FIR - Full Intra-frame request (h.261) */
+#define RTCP_PT_NACK 193 /*!< NACK - Negative acknowledgement (h.261) */
+#define RTCP_PT_IJ 195 /*!< IJ - RFC 5450 Extended Inter-arrival jitter report */
+#define RTCP_PT_SR 200 /*!< SR - RFC 3550 Sender report */
+#define RTCP_PT_RR 201 /*!< RR - RFC 3550 Receiver report */
+#define RTCP_PT_SDES 202 /*!< SDES - Source Description */
+#define RTCP_PT_BYE 203 /*!< BYE - Goodbye */
+#define RTCP_PT_APP 204 /*!< APP - Application defined */
+#define RTCP_PT_RTPFB 205 /*!< RTPFB - Generic RTP feedback RFC 4585 */
+#define RTCP_PT_PSFB 206 /*!< PSFB - Payload specific data RFC 4585 */
+#define RTCP_PT_XR 207 /*!< XR - Extended report - RFC3611 */
+
+/*! \brief RFC 3550 RTCP SDES Item types */
+enum rtcp_sdes {
+ SDES_END = 0, /*!< End of SDES list */
+ SDES_CNAME = 1, /*!< Canonical name */
+ SDES_NAME = 2, /*!< User name */
+ SDES_EMAIL = 3, /*!< User's e-mail address */
+ SDES_PHONE = 4, /*!< User's phone number */
+ SDES_LOC = 5, /*!< Geographic user location */
+ SDES_TOOL = 6, /*!< Name of application or tool */
+ SDES_NOTE = 7, /*!< Notice about the source */
+ SDES_PRIV = 8, /*!< SDES Private extensions */
+ SDES_H323_CADDR = 9, /*!< H.323 Callable address */
+ SDES_APSI = 10, /*!< Application Specific Identifier (RFC 6776) */
+};
#define RTP_MTU 1200
@@ -122,7 +142,7 @@
static int rtpend = DEFAULT_RTP_END; /*!< Last port for RTP sessions (set in rtp.conf) */
static int rtpdebug; /*!< Are we debugging? */
static int rtcpdebug; /*!< Are we debugging RTCP? */
-static int rtcpstats; /*!< Are we debugging RTCP? */
+static int rtcpstats; /*!< Are we gathering stats? */
static int rtcpinterval = RTCP_DEFAULT_INTERVALMS; /*!< Time between rtcp reports in millisecs */
static struct ast_sockaddr rtpdebugaddr; /*!< Debug packets to/from this host */
static struct ast_sockaddr rtcpdebugaddr; /*!< Debug RTCP packets to/from this host */
@@ -164,6 +184,7 @@
#define FLAG_NAT_INACTIVE_NOWARN (1 << 1)
#define FLAG_NEED_MARKER_BIT (1 << 3)
#define FLAG_DTMF_COMPENSATE (1 << 4)
+#define FLAG_HOLD (1 << 4) /* This RTP stream is put on hold by someone else, a:sendonly */
#define TRANSPORT_SOCKET_RTP 1
#define TRANSPORT_SOCKET_RTCP 2
@@ -219,20 +240,22 @@
unsigned int dtmf_timeout; /*!< When this timestamp is reached we consider END frame lost and forcibly abort digit */
unsigned int dtmfsamples;
enum ast_rtp_dtmf_mode dtmfmode; /*!< The current DTMF mode of the RTP stream */
+
/* DTMF Transmission Variables */
unsigned int lastdigitts;
- char sending_digit; /*!< boolean - are we sending digits */
- char send_digit; /*!< digit we are sending */
+ char sending_digit; /*!< boolean - are we sending digits */
+ char send_digit; /*!< digit we are sending */
int send_payload;
int send_duration;
unsigned int flags;
struct timeval rxcore;
struct timeval txcore;
double drxcore; /*!< The double representation of the first received packet */
+ struct timeval start; /*!< When the stream started (we can't depend on CDRs) */
struct timeval lastrx; /*!< timeval when we last received a packet */
struct timeval dtmfmute;
+ struct timeval holdstart; /*!< When the stream was put on hold */
struct ast_smoother *smoother;
- int *ioid;
unsigned short seqno; /*!< Sequence number, RFC 3550, page 13. */
unsigned short rxseqno;
struct ast_sched_context *sched;
@@ -262,6 +285,7 @@
ast_cond_t cond; /*!< Condition for signaling */
unsigned int passthrough:1; /*!< Bit to indicate that the received packet should be passed through */
unsigned int ice_started:1; /*!< Bit to indicate ICE connectivity checks have started */
+ unsigned int isactive:1; /*!< Whether the RTP stream is active or not */
char remote_ufrag[256]; /*!< The remote ICE username */
char remote_passwd[256]; /*!< The remote ICE password */
@@ -295,11 +319,18 @@
* this structure is analogous to ast_rtp, which tracks a RTP session,
* it is logical to think of this as a RTCP session.
*
+ * On the other hand, RTCP SDES defines the names for the actual
+ * RTP session so it's one session - RTP and RTCP together (OEJ)
+ *
* RTCP packet is defined on page 9 of RFC 3550.
*
*/
struct ast_rtcp {
int rtcp_info;
+ 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) */
int s; /*!< Socket */
struct ast_sockaddr us; /*!< Socket representation of the local endpoint. */
struct ast_sockaddr them; /*!< Socket representation of the remote endpoint. */
@@ -313,17 +344,19 @@
int schedid; /*!< Schedid returned from ast_sched_add() to schedule RTCP-transmissions*/
unsigned int rr_count; /*!< number of RRs we've sent, not including report blocks in SR's */
unsigned int sr_count; /*!< number of SRs we've sent */
+ unsigned int rec_rr_count; /*!< Number of RRs we've received */
+ unsigned int rec_sr_count; /*!< Number of SRs we've received */
unsigned int lastsrtxcount; /*!< Transmit packet count when last SR sent */
double accumulated_transit; /*!< accumulated a-dlsr-lsr */
double rtt; /*!< Last reported rtt */
unsigned int reported_jitter; /*!< The contents of their last jitter entry in the RR */
unsigned int reported_lost; /*!< Reported lost packets in their RR */
- double reported_maxjitter;
- double reported_minjitter;
+ double reported_maxjitter; /*!< The contents of their max jitter entry received by us */
+ double reported_minjitter; /*!< The contents of their min jitter entry received by us */
double reported_normdev_jitter;
double reported_stdev_jitter;
- unsigned int reported_jitter_count;
+ unsigned int reported_jitter_count; /*! Number of reports received */
double reported_maxlost;
double reported_minlost;
@@ -335,25 +368,33 @@
double minrxlost;
double normdev_rxlost;
double stdev_rxlost;
- unsigned int rxlost_count;
+ unsigned int rxlost_count; /*! Number of reports received */
double maxrxjitter;
double minrxjitter;
double normdev_rxjitter;
double stdev_rxjitter;
- unsigned int rxjitter_count;
+ unsigned int rxjitter_count; /*! Number of reports received */
double maxrtt;
double minrtt;
double normdevrtt;
double stdevrtt;
- unsigned int rtt_count;
+ unsigned int rtt_count; /*! Number of reports received */
+ char bridgedchannel[AST_MAX_EXTENSION]; /*!< Bridged channel name */
+ char bridgeduniqueid[AST_MAX_EXTENSION]; /*!< Bridged channel uniqueid */
+ char channel[AST_MAX_EXTENSION]; /*!< Our channel name */
+ char uniqueid[AST_MAX_EXTENSION]; /*!< Our channel uniqueid */
+ char readtranslator[80]; /* Translation done on reading audio from PBX */
+ char writetranslator[80]; /* Translation done on writing audio to PBX - bridged channel */
+ int readcost; /* Delay in milliseconds for translation of 1 second of audio */
+ int writecost; /* Delay in milliseconds for translation of 1 second of audio */
};
struct rtp_red {
struct ast_frame t140; /*!< Primary data */
struct ast_frame t140red; /*!< Redundant t140*/
unsigned char pt[AST_RED_MAX_GENERATION]; /*!< Payload types for redundancy data */
- unsigned char ts[AST_RED_MAX_GENERATION]; /*!< Time stamps */
+unsigned char ts[AST_RED_MAX_GENERATION]; /*!< Time stamps */
unsigned char len[AST_RED_MAX_GENERATION]; /*!< length of each generation */
int num_gen; /*!< Number of generations */
int schedid; /*!< Timer id */
@@ -388,9 +429,18 @@
static int ast_rtp_get_stat(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat);
static int ast_rtp_dtmf_compatible(struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1);
static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username);
+static void ast_rtp_hold(struct ast_rtp_instance *instance, int status);
static void ast_rtp_stop(struct ast_rtp_instance *instance);
static int ast_rtp_qos_set(struct ast_rtp_instance *instance, int tos, int cos, const char* desc);
static int ast_rtp_sendcng(struct ast_rtp_instance *instance, int level);
+static int ast_rtcp_write(const void *data);
+static void ast_rtcp_setcname(struct ast_rtp_instance *instance, const char *cname, size_t length);
+static void ast_rtcp_set_bridged(struct ast_rtp_instance *instance, const char *channel, const char *uniqueid, const char *bridgedchan, const char *bridgeduniqueid);
+void ast_rtcp_set_translator(struct ast_rtp_instance *instance, const char *readtranslator, const int readcost, const char *writetranslator, const int writecost);
+static int ast_rtp_isactive(struct ast_rtp_instance *instance);
+static int add_sdes_bodypart(struct ast_rtp *rtp, unsigned int *rtcp_packet, int len, int type);
+static int add_sdes_header(struct ast_rtp *rtp, unsigned int *rtcp_packet, int len);
+static int ast_rtcp_write_empty_frame(struct ast_rtp_instance *instance);
#ifdef HAVE_OPENSSL_SRTP
static int ast_rtp_activate(struct ast_rtp_instance *instance);
@@ -1021,9 +1071,15 @@
.dtmf_compatible = ast_rtp_dtmf_compatible,
.stun_request = ast_rtp_stun_request,
.stop = ast_rtp_stop,
+ .hold = ast_rtp_hold,
.qos = ast_rtp_qos_set,
.sendcng = ast_rtp_sendcng,
.ice = &ast_rtp_ice,
+ .setcname = ast_rtcp_setcname,
+ .set_bridged_chan = ast_rtcp_set_bridged,
+ .set_translator = ast_rtcp_set_translator,
+ .isactive = ast_rtp_isactive,
+ .rtcp_write_empty = ast_rtcp_write_empty_frame,
#ifdef HAVE_OPENSSL_SRTP
.dtls = &ast_rtp_dtls,
.activate = ast_rtp_activate,
@@ -1545,6 +1601,24 @@
return interval;
}
+/*! \brief Schedule RTCP transmissions for RTP channel */
+static void ast_rtcp_schedule(struct ast_rtp_instance *instance)
+{
+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+
+ /* Do not schedule RR if RTCP isn't run */
+ if (rtp->rtcp && !ast_sockaddr_isnull(&rtp->rtcp->them) && rtp->rtcp->schedid < 1) {
+ /* Schedule transmission of Receiver Report */
+ ast_rtcp_write_empty(instance);
+ ao2_ref(instance, +1);
+ rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, instance);
+ if (rtp->rtcp->schedid < 0) {
+ ao2_ref(instance, -1);
+ ast_log(LOG_WARNING, "scheduling RTCP transmission failed.\n");
+ }
+ }
+}
+
/*! \brief Calculate normal deviation */
static double normdev_compute(double normdev, double sample, unsigned int sample_count)
{
@@ -1790,6 +1864,9 @@
#ifdef HAVE_OPENSSL_SRTP
rtp->rekeyid = -1;
#endif
+
+ gettimeofday(&rtp->start, NULL);
+ rtp->isactive = 1;
return 0;
}
@@ -2159,7 +2236,7 @@
}
/*! \brief Send RTCP recipient's report */
-static int ast_rtcp_write_rr(struct ast_rtp_instance *instance)
+static int ast_rtcp_write_rr(struct ast_rtp_instance *instance, int goodbye)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
int res;
@@ -2171,7 +2248,7 @@
unsigned int received_interval;
int lost_interval;
struct timeval now;
- unsigned int *rtcpheader;
+ unsigned int *rtcpheader, *start;
char bdata[1024];
struct timeval dlsr;
int fraction;
@@ -2220,7 +2297,7 @@
fraction = (lost_interval << 8) / expected_interval;
gettimeofday(&now, NULL);
timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
- rtcpheader = (unsigned int *)bdata;
+ rtcpheader = (unsigned int *) bdata;
rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
rtcpheader[1] = htonl(rtp->ssrc);
[... 913 lines stripped ...]
More information about the asterisk-commits
mailing list