[asterisk-commits] oej: branch oej/pinetestedition-1.8 r383031 - in /team/oej/pinetestedition-1....
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Mar 13 11:01:43 CDT 2013
Author: oej
Date: Wed Mar 13 11:01:39 2013
New Revision: 383031
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=383031
Log:
Adding pinefrog RTCP support
Added:
team/oej/pinetestedition-1.8/patches/pinefrog-rtcp-1.8.diff (with props)
Modified:
team/oej/pinetestedition-1.8/CREDITS
team/oej/pinetestedition-1.8/channels/chan_sip.c
team/oej/pinetestedition-1.8/channels/sip/dialplan_functions.c
team/oej/pinetestedition-1.8/channels/sip/include/sip.h
team/oej/pinetestedition-1.8/include/asterisk/logger.h
team/oej/pinetestedition-1.8/include/asterisk/rtp_engine.h
team/oej/pinetestedition-1.8/main/logger.c
team/oej/pinetestedition-1.8/main/rtp_engine.c
team/oej/pinetestedition-1.8/res/res_rtp_asterisk.c
Modified: team/oej/pinetestedition-1.8/CREDITS
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinetestedition-1.8/CREDITS?view=diff&rev=383031&r1=383030&r2=383031
==============================================================================
--- team/oej/pinetestedition-1.8/CREDITS (original)
+++ team/oej/pinetestedition-1.8/CREDITS Wed Mar 13 11:01:39 2013
@@ -22,6 +22,9 @@
Omnitor AB, Gunnar Hellström, for funding work with videocaps, T.140 RED,
originate with video/text and many more contributions.
+
+Nordicom Norge AS, Kristiansand, Norway, for funding work with RTCP support
+and Call Quality Records.
=== WISHLIST CONTRIBUTERS ===
Jeremy McNamara - SpeeX support
@@ -116,6 +119,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
@@ -217,7 +221,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/pinetestedition-1.8/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinetestedition-1.8/channels/chan_sip.c?view=diff&rev=383031&r1=383030&r2=383031
==============================================================================
--- team/oej/pinetestedition-1.8/channels/chan_sip.c (original)
+++ team/oej/pinetestedition-1.8/channels/chan_sip.c Wed Mar 13 11:01:39 2013
@@ -276,6 +276,7 @@
#include "asterisk/xml.h"
#include "sip/include/dialog.h"
#include "sip/include/dialplan_functions.h"
+#include "sip/include/rtcp.h"
/*** DOCUMENTATION
@@ -671,7 +672,6 @@
{ AST_REDIRECTING_REASON_CALL_FWD_DTE, "unknown"}
};
-
/*! \name DefaultSettings
Default setttings are used as a channel setting and as a default when
configuring devices
@@ -6214,6 +6214,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) {
@@ -6931,6 +6947,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;
@@ -8182,8 +8199,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;
@@ -8246,6 +8265,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);
@@ -9169,6 +9196,7 @@
dialog->owner->uniqueid);
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;
}
@@ -9937,9 +9965,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);
@@ -18216,8 +18244,10 @@
int x = 0, load_realtime;
format_t codec = 0;
int realtimepeers;
+ int realtimertpqos = FALSE;
realtimepeers = ast_check_realtime("sippeers");
+ realtimertpqos = ast_check_realtime("rtpcqr");
if (argc < 4)
return CLI_SHOWUSAGE;
@@ -18851,9 +18881,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:
@@ -18871,6 +18903,7 @@
realtimepeers = ast_check_realtime("sippeers");
realtimeregs = ast_check_realtime("sipregs");
+ realtimertpqos = ast_check_realtime("rtpcqr");
ast_mutex_lock(&authl_lock);
credentials = authl;
@@ -18942,6 +18975,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)));
@@ -18951,6 +18986,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));
@@ -20895,6 +20931,7 @@
if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p))
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 */
@@ -21159,6 +21196,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 */
@@ -21808,16 +21846,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);
}
@@ -24747,6 +24790,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);
@@ -24777,6 +24821,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);
}
@@ -29093,6 +29138,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;
@@ -29523,6 +29570,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/pinetestedition-1.8/channels/sip/dialplan_functions.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinetestedition-1.8/channels/sip/dialplan_functions.c?view=diff&rev=383031&r1=383030&r2=383031
==============================================================================
--- team/oej/pinetestedition-1.8/channels/sip/dialplan_functions.c (original)
+++ team/oej/pinetestedition-1.8/channels/sip/dialplan_functions.c Wed Mar 13 11:01:39 2013
@@ -140,7 +140,9 @@
snprintf(buf, buflen, "%s", ast_sockaddr_stringify(&sa));
} else if (!strcasecmp(args.param, "rtpqos")) {
+/* OEJ - Check this part, different from 1.4 */
struct ast_rtp_instance *rtp = NULL;
+ struct ast_rtp_quality *qos;
if (ast_strlen_zero(args.type)) {
args.type = "audio";
@@ -162,6 +164,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/pinetestedition-1.8/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinetestedition-1.8/channels/sip/include/sip.h?view=diff&rev=383031&r1=383030&r2=383031
==============================================================================
--- team/oej/pinetestedition-1.8/channels/sip/include/sip.h (original)
+++ team/oej/pinetestedition-1.8/channels/sip/include/sip.h Wed Mar 13 11:01:39 2013
@@ -702,6 +702,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 matchexternaddrlocally; /*!< Match externaddr/externhost setting against localnet setting */
@@ -1087,6 +1089,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? */
@@ -1142,6 +1145,12 @@
* The large-scale changes would be a good idea for implementing during an SDP rewrite.
*/
struct offered_media offered_media[OFFERED_MEDIA_COUNT];
+ //struct ast_rtp_quality *audioqual; /*!< Audio: The latest quality report, for realtime storage */
+ //struct ast_rtp_quality *videoqual; /*!< Video: The latest quality report, for realtime storage */
+ 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 */
+
struct ast_cc_config_params *cc_params;
struct sip_epa_entry *epa_entry;
int fromdomainport; /*!< Domain port to show in from field */
Modified: team/oej/pinetestedition-1.8/include/asterisk/logger.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinetestedition-1.8/include/asterisk/logger.h?view=diff&rev=383031&r1=383030&r2=383031
==============================================================================
--- team/oej/pinetestedition-1.8/include/asterisk/logger.h (original)
+++ team/oej/pinetestedition-1.8/include/asterisk/logger.h Wed Mar 13 11:01:39 2013
@@ -181,7 +181,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/pinetestedition-1.8/include/asterisk/rtp_engine.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinetestedition-1.8/include/asterisk/rtp_engine.h?view=diff&rev=383031&r1=383030&r2=383031
==============================================================================
--- team/oej/pinetestedition-1.8/include/asterisk/rtp_engine.h (original)
+++ team/oej/pinetestedition-1.8/include/asterisk/rtp_engine.h Wed Mar 13 11:01:39 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 */
#define AST_RTP_MAX_PT 256
@@ -211,6 +212,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 */
@@ -237,10 +246,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 */
@@ -291,6 +302,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 */
+ int lasttxformat; /*!< Last used codec on transmitted stream */
+ int 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) \
@@ -318,6 +355,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 */
@@ -379,6 +419,15 @@
format_t (*available_formats)(struct ast_rtp_instance *instance, format_t to_endpoint, format_t to_asterisk);
/*! Callback to send CNG */
int (*sendcng)(struct ast_rtp_instance *instance, int level);
+ /*! 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;
};
@@ -1335,6 +1384,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
@@ -1858,6 +1927,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
@@ -1878,6 +1977,22 @@
*/
struct ast_srtp *ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance);
+/*!
+ * \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/pinetestedition-1.8/main/logger.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinetestedition-1.8/main/logger.c?view=diff&rev=383031&r1=383030&r2=383031
==============================================================================
--- team/oej/pinetestedition-1.8/main/logger.c (original)
+++ team/oej/pinetestedition-1.8/main/logger.c Wed Mar 13 11:01:39 2013
@@ -174,6 +174,7 @@
"ERROR",
"VERBOSE",
"DTMF",
+ "CQR",
};
/*! \brief Colors used in the console for logging */
@@ -185,7 +186,7 @@
COLOR_RED,
COLOR_GREEN,
COLOR_BRGREEN,
- 0,
+ COLOR_BRBLUE,
0,
0,
0,
Modified: team/oej/pinetestedition-1.8/main/rtp_engine.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinetestedition-1.8/main/rtp_engine.c?view=diff&rev=383031&r1=383030&r2=383031
==============================================================================
--- team/oej/pinetestedition-1.8/main/rtp_engine.c (original)
+++ team/oej/pinetestedition-1.8/main/rtp_engine.c Wed Mar 13 11:01:39 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
@@ -781,6 +784,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) {
@@ -834,6 +844,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);
@@ -841,6 +852,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;
@@ -1841,11 +1856,58 @@
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_sendcng(struct ast_rtp_instance *instance, int level)
{
if (instance->engine->sendcng) {
return instance->engine->sendcng(instance, level);
}
-
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 */
+}
Added: team/oej/pinetestedition-1.8/patches/pinefrog-rtcp-1.8.diff
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinetestedition-1.8/patches/pinefrog-rtcp-1.8.diff?view=auto&rev=383031
==============================================================================
--- team/oej/pinetestedition-1.8/patches/pinefrog-rtcp-1.8.diff (added)
+++ team/oej/pinetestedition-1.8/patches/pinefrog-rtcp-1.8.diff Wed Mar 13 11:01:39 2013
@@ -1,0 +1,4849 @@
+Index: patches/pinefrog-1.4.diff
+===================================================================
+--- patches/pinefrog-1.4.diff (.../branches/1.8) (revision 0)
++++ patches/pinefrog-1.4.diff (.../team/oej/pinefrog-rtcp-1.8) (revision 383011)
+@@ -0,0 +1,2281 @@
++Index: channels/chan_sip.c
++===================================================================
++--- channels/chan_sip.c (.../branches/1.4) (revision 382456)
+++++ channels/chan_sip.c (.../team/oej/pinefrog-1.4) (revision 382456)
++@@ -478,6 +478,13 @@
++ { SIP_OPT_RESPRIORITY, NOT_SUPPORTED, "resource-priority" },
++ };
++
+++/*! Media types for declaration of RTP streams */
+++enum media_type {
+++ SDP_AUDIO, /* AUDIO class */
+++ SDP_VIDEO,
+++ SDP_IMAGE,
+++/* For later versions that 1.4 we need to add SDP_TEXT for T.140 */
+++};
++
++ /*! \brief SIP Methods we support */
++ #define ALLOWED_METHODS "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO"
++@@ -574,6 +581,8 @@
++ static char global_useragent[AST_MAX_EXTENSION]; /*!< Useragent for the SIP channel */
++ static int allow_external_domains; /*!< Accept calls to external SIP domains? */
++ static int global_callevents; /*!< Whether we send manager events or not */
+++static int global_rtcpevents; /*!< Whether we send manager RTCP events or not */
+++static int global_rtcptimer; /*!< How often, during a call, to report RTCP stats */
++ static int global_t1min; /*!< T1 roundtrip time minimum */
++ static int global_autoframing; /*!< Turn autoframing on or off. */
++ static enum transfermodes global_allowtransfer; /*!< SIP Refer restriction scheme */
++@@ -1042,6 +1051,7 @@
++ int initid; /*!< Auto-congest ID if appropriate (scheduler) */
++ int waitid; /*!< Wait ID for scheduler after 491 or other delays */
++ int autokillid; /*!< Auto-kill ID (scheduler) */
+++ int rtcpeventid; /*!< Scheduler ID for RTCP Events */
++ enum transfermodes allowtransfer; /*!< REFER: restriction scheme */
++ struct sip_refer *refer; /*!< REFER: SIP transfer data structure */
++ enum subscriptiontype subscribed; /*!< SUBSCRIBE: Is this dialog a subscription? */
++@@ -1068,6 +1078,8 @@
++ struct sip_invite_param *options; /*!< Options for INVITE */
++ int autoframing;
++ int hangupcause; /*!< Storage of hangupcause copied from our owner before we disconnect from the AST channel (only used at hangup) */
+++ struct ast_rtp_quality *audioqual; /*!< Audio: The latest quality report, for realtime storage */
+++ struct ast_rtp_quality *videoqual; /*!< Video: The latest quality report, for realtime storage */
++ /*! When receiving an SDP offer, it is important to take note of what media types were offered.
++ * By doing this, even if we don't want to answer a particular media stream with something meaningful, we can
++ * still put an m= line in our answer with the port set to 0.
++@@ -1421,7 +1433,11 @@
++ char **m_buf, size_t *m_size, char **a_buf, size_t *a_size,
++ int debug);
++ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int add_audio, int add_t38);
+++static int send_rtcp_events(const void *data);
+++static void start_rtcp_events(struct sip_pvt *dialog);
+++static void sip_rtcp_report(struct sip_pvt *p, struct ast_rtp *rtp, enum media_type type, int reporttype);
++ static void stop_media_flows(struct sip_pvt *p);
+++static void qos_write_realtime(struct sip_pvt *dialog, struct ast_rtp_quality *qual);
++
++ /*--- Authentication stuff */
++ static int reply_digest(struct sip_pvt *p, struct sip_request *req, char *header, int sipmethod, char *digest, int digest_len);
++@@ -2754,9 +2770,12 @@
++ if (option_debug > 2)
++ ast_log(LOG_DEBUG, "Destroying SIP peer %s\n", peer->name);
++
+++
++ /* Delete it, it needs to disappear */
++- if (peer->call)
+++ if (peer->call) {
++ sip_destroy(peer->call);
+++ peer->call = NULL;
+++ }
++
++ if (peer->mwipvt) /* We have an active subscription, delete it */
++ sip_destroy(peer->mwipvt);
++@@ -3441,11 +3460,25 @@
++ if (dumphistory)
++ sip_dump_history(p);
++
+++ 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)
++ free(p->options);
++
++ if (p->stateid > -1)
++ ast_extension_state_del(p->stateid, NULL);
+++ AST_SCHED_DEL(sched, p->rtcpeventid);
++
++ /* remove any pending extension notify that could be left in
++ * the extension update queue relating to this dialog. */
++@@ -3957,10 +3990,12 @@
++ if (!p->pendinginvite) {
++ char *audioqos = "";
++ char *videoqos = "";
++- if (p->rtp)
++- audioqos = ast_rtp_get_quality(p->rtp, NULL);
++- if (p->vrtp)
++- videoqos = ast_rtp_get_quality(p->vrtp, NULL);
+++ if (p->rtp) {
+++ audioqos = ast_rtp_get_quality(p->rtp);
+++ }
+++ if (p->vrtp) {
+++ videoqos = ast_rtp_get_quality(p->vrtp);
+++ }
++ /* Send a hangup */
++ if (oldowner->_state == AST_STATE_UP) {
++ transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
++@@ -4035,6 +4070,7 @@
++ ast_rtp_new_source(p->rtp);
++ res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
++ ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
+++ start_rtcp_events(p);
++ }
++ ast_mutex_unlock(&p->lock);
++ return res;
++@@ -4846,6 +4882,7 @@
++ ast_mutex_init(&p->lock);
++
++ p->method = intended_method;
+++ p->rtcpeventid = -1;
++ p->initid = -1;
++ p->waitid = -1;
++ p->autokillid = -1;
++@@ -4877,8 +4914,9 @@
++ if (sip_methods[intended_method].need_rtp) {
++ p->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
++ /* If the global videosupport flag is on, we always create a RTP interface for video */
++- if (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT))
+++ if (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT)) {
++ p->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
+++ }
++ if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT))
++ p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr);
++ if (!p->rtp || (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && !p->vrtp)) {
++@@ -4936,6 +4974,12 @@
++ else
++ ast_string_field_set(p, callid, callid);
++ /* Assign default music on hold class */
+++ if (p->rtp) {
+++ ast_rtcp_setcname(p->rtp, p->callid, strlen(p->callid));
+++ }
+++ if (p->vrtp) {
+++ ast_rtcp_setcname(p->vrtp, p->callid, strlen(p->callid));
+++ }
++ ast_string_field_set(p, mohinterpret, default_mohinterpret);
++ ast_string_field_set(p, mohsuggest, default_mohsuggest);
++ p->capability = global_capability;
++@@ -5603,11 +5647,6 @@
++ return;
++ }
++
++-enum media_type {
++- SDP_AUDIO,
++- SDP_VIDEO,
++- SDP_IMAGE,
++-};
++
++ static int get_ip_and_port_from_sdp(struct sip_request *req, const enum media_type media, struct sockaddr_in *sin)
++ {
++@@ -12019,6 +12058,10 @@
++ int realtimepeers;
++ int realtimeusers;
++ char codec_buf[SIPBUFSIZE];
+++ int realtimertpqos = FALSE;
+++#ifdef REALTIME2
+++ realtimertpqos = ast_check_realtime("rtpqos");
+++#endif
++
++ realtimepeers = ast_check_realtime("sippeers");
++ realtimeusers = ast_check_realtime("sipusers");
++@@ -12050,6 +12093,8 @@
++ ast_cli(fd, " From: Domain: %s\n", default_fromdomain);
++ ast_cli(fd, " Record SIP history: %s\n", recordhistory ? "On" : "Off");
++ ast_cli(fd, " Call Events: %s\n", global_callevents ? "On" : "Off");
+++ ast_cli(fd, " RTCP Events: %s\n", global_rtcpevents ? "On" : "Off");
+++ ast_cli(fd, " RTCP Event timer: %d\n", global_rtcptimer);
++ ast_cli(fd, " IP ToS SIP: %s\n", ast_tos2str(global_tos_sip));
++ ast_cli(fd, " IP ToS RTP audio: %s\n", ast_tos2str(global_tos_audio));
++ ast_cli(fd, " IP ToS RTP video: %s\n", ast_tos2str(global_tos_video));
++@@ -12063,6 +12108,7 @@
++ ast_cli(fd, " SIP realtime: Disabled\n" );
++ else
++ ast_cli(fd, " SIP realtime: Enabled\n" );
+++ ast_cli(fd, " QOS realtime reports: %s\n", realtimertpqos ? "Enabled" : "Disabled" );
++
++ ast_cli(fd, "\nGlobal Signalling Settings:\n");
++ ast_cli(fd, "---------------------------\n");
++@@ -13650,6 +13696,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);
++ break;
++ case 407: /* Proxy authentication */
++ case 401: /* Www auth */
++@@ -14046,14 +14093,286 @@
++ }
++ }
++
+++/*! \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)
+++*/
+++static void sip_rtcp_report(struct sip_pvt *p, struct ast_rtp *rtp, enum media_type type, int reporttype)
+++{
+++ struct ast_rtp_quality *qual;
+++ char *rtpqstring = NULL;
+++ int qosrealtime = ast_check_realtime("rtpqos");
+++ unsigned int duration; /* Duration in secs */
+++ int readtrans = FALSE, writetrans = FALSE;
+++
+++ memset(&qual, sizeof(qual), 0);
+++
+++ if (p && p->owner) {
+++ struct ast_channel *bridgepeer = ast_bridged_channel(p->owner);
+++ if (bridgepeer) {
+++ /* Store the bridged peer data while we have it */
+++ ast_rtcp_set_bridged(rtp, p->owner->name, p->owner->uniqueid, S_OR(bridgepeer->name,""), S_OR(bridgepeer->uniqueid,""));
+++ ast_log(LOG_DEBUG, "---- Setting bridged peer name to %s\n", bridgepeer->name);
+++ } else {
+++ ast_rtcp_set_bridged(rtp, p->owner->name, p->owner->uniqueid, NULL, NULL);
+++ }
+++
+++ /* 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) {
+++ /* if we have a translator, the bridge delay is increased, which affects the QoS of the call. */
+++ readtrans = p->owner->readtrans != NULL;
+++ writetrans = p->owner->writetrans != NULL;
+++ ast_rtcp_settranslator(rtp, readtrans ? p->owner->readtrans->t->name : NULL, readtrans ? p->owner->readtrans->t->cost : 0,
+++ writetrans ? p->owner->writetrans->t->name : NULL, writetrans ? p->owner->writetrans->t->cost : 0);
+++
+++ if (option_debug > 1) {
+++ if (readtrans && p->owner->readtrans->t) {
+++ ast_log(LOG_DEBUG, "--- Audio Read translator: %s Cost %d\n", p->owner->readtrans->t->name, p->owner->readtrans->t->cost);
+++ }
+++ if (writetrans && p->owner->writetrans->t) {
+++ ast_log(LOG_DEBUG, "--- Audio Write translator: %s Cost %d\n", p->owner->writetrans->t->name, p->owner->writetrans->t->cost);
+++ }
+++ }
+++ }
+++
+++ }
+++
+++ rtpqstring = ast_rtp_get_quality(rtp);
+++ qual = ast_rtp_get_qualdata(rtp);
+++ if (!qual) {
+++ /* Houston, we got a problem */
+++ return;
+++ }
+++
+++ if (global_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",
+++ p->owner ? p->owner->name : "",
+++ p->owner ? p->owner->uniqueid : "",
+++ qual->bridgedchan[0] ? qual->bridgedchan : "" ,
+++ qual->bridgeduniqueid[0] ? qual->bridgeduniqueid : "",
+++ reporttype == 1 ? "Final" : "Update",
+++ qual->numberofreports == 0 ? "Inactive" : "Active",
+++ duration,
+++ p->callid,
+++ ast_inet_ntoa(qual->them.sin_addr),
+++ type == SDP_AUDIO ? "audio" : (type == SDP_VIDEO ? "video" : "fax") ,
+++ ast_getformatname(qual->lasttxformat),
+++ ast_getformatname(qual->lastrxformat),
+++ qual->local_ssrc,
+++ qual->remote_ssrc,
+++ qual->rtt,
+++ qual->rttmax,
+++ qual->rttmin,
+++ qual->local_jitter,
+++ qual->remote_jitter,
[... 5734 lines stripped ...]
More information about the asterisk-commits
mailing list