[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