Index: build_tools/sha1sum-sh
===================================================================
--- build_tools/sha1sum-sh	(.../branches/11)	(revision 385989)
+++ build_tools/sha1sum-sh	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: build_tools/sha1sum-sh
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Date Author Id Revision Yoyo'
\ No newline at end of property
Index: build_tools/menuselect-deps.in
===================================================================
--- build_tools/menuselect-deps.in	(.../branches/11)	(revision 385989)
+++ build_tools/menuselect-deps.in	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -63,7 +63,6 @@
 SYSLOG=@PBX_SYSLOG@
 TONEZONE=@PBX_TONEZONE@
 UNIXODBC=@PBX_UNIXODBC@
-UUID=@PBX_UUID@
 VORBIS=@PBX_VORBIS@
 VPB=@PBX_VPB@
 WINARCH=@PBX_WINARCH@
Index: configure
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: pbx/pbx_spool.c
===================================================================
--- pbx/pbx_spool.c	(.../branches/11)	(revision 385989)
+++ pbx/pbx_spool.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -645,10 +645,9 @@
 	char buf[8192] __attribute__((aligned (sizeof(int))));
 	struct pollfd pfd = { .fd = inotify_fd, .events = POLLIN };
 #else
-	struct timespec nowait = { .tv_sec = 0, .tv_nsec = 1 };
+	struct timespec nowait = { 0, 1 };
 	int inotify_fd = kqueue();
 	struct kevent kev;
-	struct kevent event;
 #endif
 	struct direntry *cur;
 
@@ -679,7 +678,7 @@
 
 #ifndef HAVE_INOTIFY
 	EV_SET(&kev, dirfd(dir), EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, NOTE_WRITE, 0, NULL);
-	if (kevent(inotify_fd, &kev, 1, &event, 1, &nowait) < 0 && errno != 0) {
+	if (kevent(inotify_fd, &kev, 1, NULL, 0, &nowait) < 0 && errno != 0) {
 		ast_log(LOG_ERROR, "Unable to watch directory %s: %s\n", qdir, strerror(errno));
 	}
 #endif
@@ -751,18 +750,8 @@
 		}
 		queue_created_files();
 #else
-			int num_events;
-			/* If queue empty then wait forever */
-			if (next == INT_MAX) {
-				num_events = kevent(inotify_fd, &kev, 1, &event, 1, NULL);
-			} else {
-				struct timespec ts2 = { .tv_sec = (unsigned long int)(next - now), .tv_nsec = 0 };
-				num_events = kevent(inotify_fd, &kev, 1, &event, 1, &ts2);
-			}
-			if ((num_events < 0) || (event.flags == EV_ERROR)) {
-				ast_debug(10, "KEvent error %s\n", strerror(errno));
-				continue;
-			} else if (num_events == 0) {
+			struct timespec ts2 = { next - now, 0 };
+			if (kevent(inotify_fd, NULL, 0, &kev, 1, &ts2) <= 0) {
 				/* Interrupt or timeout, restart calculations */
 				continue;
 			} else {
Index: channels/sig_pri.h
===================================================================
--- channels/sig_pri.h	(.../branches/11)	(revision 385989)
+++ channels/sig_pri.h	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -470,8 +470,6 @@
 	 * appended to the initial_user_tag[].
 	 */
 	unsigned int append_msn_to_user_tag:1;
-	/*! TRUE if a PROCEEDING message needs to unsquelch the received audio. */
-	unsigned int inband_on_proceeding:1;
 #if defined(HAVE_PRI_MCID)
 	/*! \brief TRUE if allow sending MCID request on this span. */
 	unsigned int mcid_send:1;
Index: channels/chan_dahdi.c
===================================================================
--- channels/chan_dahdi.c	(.../branches/11)	(revision 385989)
+++ channels/chan_dahdi.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -1408,7 +1408,6 @@
 			.localdialplan = PRI_NATIONAL_ISDN + 1,
 			.nodetype = PRI_CPE,
 			.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
-			.inband_on_proceeding = 1,
 
 #if defined(HAVE_PRI_CCSS)
 			.cc_ptmp_recall_mode = 1,/* specificRecall */
@@ -12931,7 +12930,6 @@
 							pris[span].pri.layer1_ignored = 0;
 						}
 						pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
-						pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
 						ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
 						ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
 #if defined(HAVE_PRI_MWI)
@@ -18194,8 +18192,6 @@
 #endif	/* defined(HAVE_PRI_MWI) */
 			} else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
 				confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
-			} else if (!strcasecmp(v->name, "inband_on_proceeding")) {
-				confp->pri.pri.inband_on_proceeding = ast_true(v->value);
 #if defined(HAVE_PRI_DISPLAY_TEXT)
 			} else if (!strcasecmp(v->name, "display_send")) {
 				confp->pri.pri.display_flags_send = dahdi_display_text_option(v->value);
Index: channels/chan_sip.c
===================================================================
--- channels/chan_sip.c	(.../branches/11)	(revision 385989)
+++ channels/chan_sip.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -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
@@ -1187,11 +1187,6 @@
 static struct ao2_container *peers;
 static struct ao2_container *peers_by_ip;
 
-/*! \brief  A bogus peer, to be used when authentication should fail */
-static struct sip_peer *bogus_peer;
-/*! \brief  We can recognise the bogus peer by this invalid MD5 hash */
-#define BOGUS_PEER_MD5SECRET "intentionally_invalid_md5_string"
-
 /*! \brief  The register list: Other SIP proxies we register with and receive calls from */
 static struct ast_register_list {
 	ASTOBJ_CONTAINER_COMPONENTS(struct sip_registry);
@@ -1338,7 +1333,7 @@
 static int transmit_response_with_auth(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *rand, enum xmittype reliable, const char *header, int stale);
 static int transmit_provisional_response(struct sip_pvt *p, const char *msg, const struct sip_request *req, int with_sdp);
 static int transmit_response_with_allow(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);
-static void transmit_fake_auth_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable);
+static void transmit_fake_auth_response(struct sip_pvt *p, int sipmethod, struct sip_request *req, enum xmittype reliable);
 static int transmit_request(struct sip_pvt *p, int sipmethod, uint32_t seqno, enum xmittype reliable, int newbranch);
 static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, uint32_t seqno, enum xmittype reliable, int newbranch);
 static int transmit_publish(struct sip_epa_entry *epa_entry, enum sip_publish_type publish_type, const char * const explicit_uri);
@@ -1447,8 +1442,6 @@
 static void ast_quiet_chan(struct ast_channel *chan);
 static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target);
 static int do_magic_pickup(struct ast_channel *channel, const char *extension, const char *context);
-static void set_peer_nat(const struct sip_pvt *p, struct sip_peer *peer);
-static void check_for_nat(const struct ast_sockaddr *them, struct sip_pvt *p);
 
 /*--- Device monitoring and Device/extension state/event handling */
 static int extensionstate_update(const char *context, const char *exten, struct state_notify_data *data, struct sip_pvt *p, int force);
@@ -6520,6 +6513,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) {
 			ao2_ref(p->options->outboundproxy, -1);
@@ -7255,11 +7264,6 @@
 	int res = 0;
 	struct sip_pvt *p = ast_channel_tech_pvt(ast);
 
-	if (!p) {
-		ast_debug(1, "Asked to answer channel %s without tech pvt; ignoring\n",
-				ast_channel_name(ast));
-		return res;
-	}
 	sip_pvt_lock(p);
 	if (ast_channel_state(ast) != AST_STATE_UP) {
 		try_suggested_sip_codec(p);
@@ -7269,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;
@@ -7429,12 +7434,6 @@
 	struct sip_pvt *p = ast_channel_tech_pvt(ast);
 	int res = 0;
 
-	if (!p) {
-		ast_debug(1, "Asked to begin DTMF digit on channel %s with no pvt; ignoring\n",
-				ast_channel_name(ast));
-		return res;
-	}
-
 	sip_pvt_lock(p);
 	switch (ast_test_flag(&p->flags[0], SIP_DTMF)) {
 	case SIP_DTMF_INBAND:
@@ -7459,12 +7458,6 @@
 	struct sip_pvt *p = ast_channel_tech_pvt(ast);
 	int res = 0;
 
-	if (!p) {
-		ast_debug(1, "Asked to end DTMF digit on channel %s with no pvt; ignoring\n",
-				ast_channel_name(ast));
-		return res;
-	}
-
 	sip_pvt_lock(p);
 	switch (ast_test_flag(&p->flags[0], SIP_DTMF)) {
 	case SIP_DTMF_INFO:
@@ -7490,12 +7483,6 @@
 	struct sip_pvt *p = ast_channel_tech_pvt(ast);
 	int res;
 
-	if (!p) {
-		ast_debug(1, "Asked to transfer channel %s with no pvt; ignoring\n",
-				ast_channel_name(ast));
-		return -1;
-	}
-
 	if (dest == NULL)	/* functions below do not take a NULL */
 		dest = "";
 	sip_pvt_lock(p);
@@ -7691,12 +7678,6 @@
 	struct sip_pvt *p = ast_channel_tech_pvt(ast);
 	int res = 0;
 
-	if (!p) {
-		ast_debug(1, "Asked to indicate condition on channel %s with no pvt; ignoring\n",
-				ast_channel_name(ast));
-		return res;
-	}
-
 	sip_pvt_lock(p);
 	switch(condition) {
 	case AST_CONTROL_RINGING:
@@ -8675,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;
@@ -8738,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);
@@ -9780,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;
 	}
@@ -10749,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);
@@ -16061,9 +16053,7 @@
 		ast_verb(3, "Registered SIP '%s' at %s\n", peer->name,
 			ast_sockaddr_stringify(&peer->addr));
 	}
-	sip_pvt_unlock(pvt);
 	sip_poke_peer(peer, 0);
-	sip_pvt_lock(pvt);
 	register_peer_exten(peer, 1);
 
 	/* Save User agent */
@@ -16275,7 +16265,6 @@
 	char a1_hash[256];
 	char resp_hash[256]="";
 	char *c;
-	int is_bogus_peer = 0;
 	int  wrongnonce = FALSE;
 	int  good_response;
 	const char *usednonce = p->nonce;
@@ -16347,14 +16336,8 @@
 
 	sip_digest_parser(c, keys);
 
-	/* We cannot rely on the bogus_peer having a bad md5 value. Someone could
-	 * use it to construct valid auth. */
-	if (md5secret && strcmp(md5secret, BOGUS_PEER_MD5SECRET) == 0) {
-		is_bogus_peer = 1;
-	}
-
 	/* Verify that digest username matches  the username we auth as */
-	if (strcmp(username, keys[K_USER].s) && !is_bogus_peer) {
+	if (strcmp(username, keys[K_USER].s)) {
 		ast_log(LOG_WARNING, "username mismatch, have <%s>, digest has <%s>\n",
 			username, keys[K_USER].s);
 		/* Oops, we're trying something here */
@@ -16393,8 +16376,7 @@
 	}
 
 	good_response = keys[K_RESP].s &&
-			!strncasecmp(keys[K_RESP].s, resp_hash, strlen(resp_hash)) &&
-			!is_bogus_peer; /* lastly, check that the peer isn't the fake peer */
+			!strncasecmp(keys[K_RESP].s, resp_hash, strlen(resp_hash));
 	if (wrongnonce) {
 		if (good_response) {
 			if (sipdebug)
@@ -16620,13 +16602,13 @@
 /*! \brief Send a fake 401 Unauthorized response when the administrator
   wants to hide the names of local devices  from fishers
  */
-static void transmit_fake_auth_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable)
+static void transmit_fake_auth_response(struct sip_pvt *p, int sipmethod, struct sip_request *req, enum xmittype reliable)
 {
 	/* We have to emulate EXACTLY what we'd get with a good peer
 	 * and a bad password, or else we leak information. */
-	const char *response = "401 Unauthorized";
-	const char *reqheader = "Authorization";
-	const char *respheader = "WWW-Authenticate";
+	const char *response = "407 Proxy Authentication Required";
+	const char *reqheader = "Proxy-Authorization";
+	const char *respheader = "Proxy-Authenticate";
 	const char *authtoken;
 	struct ast_str *buf;
 	char *c;
@@ -16641,31 +16623,36 @@
 		[K_LAST] = { NULL, NULL}
 	};
 
+	if (sipmethod == SIP_REGISTER || sipmethod == SIP_SUBSCRIBE) {
+		response = "401 Unauthorized";
+		reqheader = "Authorization";
+		respheader = "WWW-Authenticate";
+	}
 	authtoken = sip_get_header(req, reqheader);
 	if (req->ignore && !ast_strlen_zero(p->nonce) && ast_strlen_zero(authtoken)) {
 		/* This is a retransmitted invite/register/etc, don't reconstruct authentication
 		 * information */
-		transmit_response_with_auth(p, response, req, p->nonce, reliable, respheader, 0);
+		transmit_response_with_auth(p, response, req, p->nonce, 0, respheader, 0);
 		/* Schedule auto destroy in 32 seconds (according to RFC 3261) */
 		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
 		return;
 	} else if (ast_strlen_zero(p->nonce) || ast_strlen_zero(authtoken)) {
 		/* We have no auth, so issue challenge and request authentication */
 		build_nonce(p, 1);
-		transmit_response_with_auth(p, response, req, p->nonce, reliable, respheader, 0);
+		transmit_response_with_auth(p, response, req, p->nonce, 0, respheader, 0);
 		/* Schedule auto destroy in 32 seconds */
 		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
 		return;
 	}
 
 	if (!(buf = ast_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN))) {
-		__transmit_response(p, "403 Forbidden", &p->initreq, reliable);
+		transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
 		return;
 	}
 
 	/* Make a copy of the response and parse it */
 	if (ast_str_set(&buf, 0, "%s", authtoken) == AST_DYNSTR_BUILD_FAILED) {
-		__transmit_response(p, "403 Forbidden", &p->initreq, reliable);
+		transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
 		return;
 	}
 
@@ -16703,7 +16690,7 @@
 		/* Schedule auto destroy in 32 seconds */
 		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
 	} else {
-		__transmit_response(p, "403 Forbidden", &p->initreq, reliable);
+		transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
 	}
 }
 
@@ -16813,7 +16800,7 @@
 	if (!AST_LIST_EMPTY(&domain_list)) {
 		if (!check_sip_domain(domain, NULL, 0)) {
 			if (sip_cfg.alwaysauthreject) {
-				transmit_fake_auth_response(p, &p->initreq, XMIT_UNRELIABLE);
+				transmit_fake_auth_response(p, SIP_REGISTER, &p->initreq, XMIT_UNRELIABLE);
 			} else {
 				transmit_response(p, "404 Not found (unknown domain)", &p->initreq);
 			}
@@ -16840,13 +16827,6 @@
 	}
 	peer = sip_find_peer(name, NULL, TRUE, FINDPEERS, FALSE, 0);
 
-	/* If we don't want username disclosure, use the bogus_peer when a user
-	 * is not found. */
-	if (!peer && sip_cfg.alwaysauthreject && sip_cfg.autocreatepeer == AUTOPEERS_DISABLED) {
-		peer = bogus_peer;
-		sip_ref_peer(peer, "register_verify: ref the bogus_peer");
-	}
-
 	if (!(peer && ast_apply_acl(peer->acl, addr, "SIP Peer ACL: "))) {
 		/* Peer fails ACL check */
 		if (peer) {
@@ -16864,12 +16844,22 @@
 			ast_log(LOG_ERROR, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name);
 			res = AUTH_PEER_NOT_DYNAMIC;
 		} else {
-
-			set_peer_nat(p, peer);
-			if (p->natdetected && ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
-				ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_NAT_FORCE_RPORT);
+			if (ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
+				if (p->natdetected) {
+					ast_set_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT);
+				} else {
+					ast_clear_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT);
+				}
 			}
+			if (ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) {
+				if (p->natdetected) {
+					ast_set_flag(&peer->flags[1], SIP_PAGE2_SYMMETRICRTP);
+				} else {
+					ast_clear_flag(&peer->flags[1], SIP_PAGE2_SYMMETRICRTP);
+				}
+			}
 
+			ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_NAT_FORCE_RPORT);
 			if (!(res = check_auth(p, req, peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri2, XMIT_UNRELIABLE))) {
 				if (sip_cancel_destroy(p))
 					ast_log(LOG_WARNING, "Unable to cancel SIP destruction.  Expect bad things.\n");
@@ -16928,7 +16918,7 @@
 			switch (parse_register_contact(p, peer, req)) {
 			case PARSE_REGISTER_DENIED:
 				ast_log(LOG_WARNING, "Registration denied because of contact ACL\n");
-				transmit_response_with_date(p, "403 Forbidden", req);
+				transmit_response_with_date(p, "403 Forbidden (ACL)", req);
 				res = 0;
 				break;
 			case PARSE_REGISTER_FAILED:
@@ -16956,9 +16946,9 @@
 	}
 	if (!res) {
 		if (send_mwi) {
-			sip_pvt_unlock(p);
+			ao2_unlock(p);
 			sip_send_mwi_to_peer(peer, 0);
-			sip_pvt_lock(p);
+			ao2_lock(p);
 		} else {
 			update_peer_lastmsgssent(peer, -1, 0);
 		}
@@ -16968,7 +16958,7 @@
 		switch (res) {
 		case AUTH_SECRET_FAILED:
 			/* Wrong password in authentication. Go away, don't try again until you fixed it */
-			transmit_response(p, "403 Forbidden", &p->initreq);
+			transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
 			if (global_authfailureevents) {
 				const char *peer_addr = ast_strdupa(ast_sockaddr_stringify_addr(addr));
 				const char *peer_port = ast_strdupa(ast_sockaddr_stringify_port(addr));
@@ -16991,7 +16981,7 @@
 		case AUTH_PEER_NOT_DYNAMIC:
 		case AUTH_ACL_FAILED:
 			if (sip_cfg.alwaysauthreject) {
-				transmit_fake_auth_response(p, &p->initreq, XMIT_UNRELIABLE);
+				transmit_fake_auth_response(p, SIP_REGISTER, &p->initreq, XMIT_UNRELIABLE);
 				if (global_authfailureevents) {
 					const char *peer_addr = ast_strdupa(ast_sockaddr_stringify_addr(addr));
 					const char *peer_port = ast_strdupa(ast_sockaddr_stringify_port(addr));
@@ -17881,67 +17871,6 @@
 	return -1;
 }
 
-/*! \brief Set the peers nat flags if they are using auto_* settings */
-static void set_peer_nat(const struct sip_pvt *p, struct sip_peer *peer)
-{
-
-	if (!p || !peer) {
-		return;
-	}
-
-	if (ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
-		if (p->natdetected) {
-			ast_set_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT);
-		} else {
-			ast_clear_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT);
-		}
-	}
-
-	if (ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) {
-		if (p->natdetected) {
-			ast_set_flag(&peer->flags[1], SIP_PAGE2_SYMMETRICRTP);
-		} else {
-			ast_clear_flag(&peer->flags[1], SIP_PAGE2_SYMMETRICRTP);
-		}
-	}
-}
-
-/*! \brief Check and see if the requesting UA is likely to be behind a NAT.
- *
- * If the requesting NAT is behind NAT, set the * natdetected flag so that
- * later, peers with nat=auto_* can use the value. Also, set the flags so
- * that Asterisk responds identically whether or not a peer exists so as
- * not to leak peer name information.
- */
-static void check_for_nat(const struct ast_sockaddr *addr, struct sip_pvt *p)
-{
-
-	if (!addr || !p) {
-		return;
-	}
-
-	if (ast_sockaddr_cmp(addr, &p->recv)) {
-		char *tmp_str = ast_strdupa(ast_sockaddr_stringify(addr));
-		ast_debug(3, "NAT detected for %s / %s\n", tmp_str, ast_sockaddr_stringify(&p->recv));
-		p->natdetected = 1;
-		if (ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
-			ast_set_flag(&p->flags[0], SIP_NAT_FORCE_RPORT);
-		}
-		if (ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) {
-			ast_set_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP);
-		}
-	} else {
-		p->natdetected = 0;
-		if (ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
-			ast_clear_flag(&p->flags[0], SIP_NAT_FORCE_RPORT);
-		}
-		if (ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) {
-			ast_clear_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP);
-		}
-	}
-
-}
-
 /*! \brief check Via: header for hostname, port and rport request/answer */
 static void check_via(struct sip_pvt *p, const struct sip_request *req)
 {
@@ -18005,7 +17934,29 @@
 
 		ast_sockaddr_set_port(&p->sa, port);
 
-		check_for_nat(&tmp, p);
+		/* Check and see if the requesting UA is likely to be behind a NAT. If they are, set the
+		 * natdetected flag so that later, peers with nat=auto_* can use the value. Also
+		 * set the flags so that Asterisk responds identically whether or not a peer exists
+		 * so as not to leak peer name information. */
+		if (ast_sockaddr_cmp(&tmp, &p->recv)) {
+			char *tmp_str = ast_strdupa(ast_sockaddr_stringify(&tmp));
+			ast_debug(3, "NAT detected for %s / %s\n", tmp_str, ast_sockaddr_stringify(&p->recv));
+			p->natdetected = 1;
+			if (ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
+				ast_set_flag(&p->flags[0], SIP_NAT_FORCE_RPORT);
+			}
+			if (ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) {
+				ast_set_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP);
+			}
+		} else {
+			p->natdetected = 0;
+			if (ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
+				ast_clear_flag(&p->flags[0], SIP_NAT_FORCE_RPORT);
+			}
+			if (ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) {
+				ast_clear_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP);
+			}
+		}
 
 		if (sip_debug_test_pvt(p)) {
 			ast_verbose("Sending to %s (%s)\n",
@@ -18052,19 +18003,7 @@
 			ast_verbose("No matching peer for '%s' from '%s'\n",
 				of, ast_sockaddr_stringify(&p->recv));
 		}
-
-		/* If you don't mind, we can return 404s for devices that do
-		 * not exist: username disclosure. If we allow guests, there
-		 * is no way around that. */
-		if (sip_cfg.allowguest || !sip_cfg.alwaysauthreject) {
-			return AUTH_DONT_KNOW;
-		}
-
-		/* If you do mind, we use a peer that will never authenticate.
-		 * This ensures that we follow the same code path as regular
-		 * auth: less chance for username disclosure. */
-		peer = bogus_peer;
-		sip_ref_peer(peer, "sip_ref_peer: check_peer_ok: must ref bogus_peer so unreffing it does not fail");
+		return AUTH_DONT_KNOW;
 	}
 
 	/*  build_peer, called through sip_find_peer, is not able to check the
@@ -18073,21 +18012,23 @@
 	 *  are set on the peer.  So we check for that here and set the peer's
 	 *  address accordingly.
 	 */
-	set_peer_nat(p, peer);
-
 	if (p->natdetected && ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
+		ast_set_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT);
 		ast_sockaddr_copy(&peer->addr, &p->recv);
 	}
 
+	if (p->natdetected && ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) {
+		ast_set_flag(&peer->flags[1], SIP_PAGE2_SYMMETRICRTP);
+	}
+
 	if (!ast_apply_acl(peer->acl, addr, "SIP Peer ACL: ")) {
 		ast_debug(2, "Found peer '%s' for '%s', but fails host access\n", peer->name, of);
 		sip_unref_peer(peer, "sip_unref_peer: check_peer_ok: from sip_find_peer call, early return of AUTH_ACL_FAILED");
 		return AUTH_ACL_FAILED;
 	}
-	if (debug && peer != bogus_peer) {
+	if (debug)
 		ast_verbose("Found peer '%s' for '%s' from %s\n",
 			peer->name, of, ast_sockaddr_stringify(&p->recv));
-	}
 
 	/* XXX what about p->prefs = peer->prefs; ? */
 	/* Set Frame packetization */
@@ -18370,6 +18311,8 @@
 		} else {
 			res = AUTH_RTP_FAILED;
 		}
+	} else if (sip_cfg.alwaysauthreject) {
+		res = AUTH_FAKE_AUTH; /* reject with fake authorization request */
 	} else {
 		res = AUTH_SECRET_FAILED; /* we don't want any guests, authentication will fail */
 	}
@@ -18504,8 +18447,13 @@
 			return;
 		}
 		if (res < 0) { /* Something failed in authentication */
-			ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From"));
-			transmit_response(p, "403 Forbidden", req);
+			if (res == AUTH_FAKE_AUTH) {
+				ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", sip_get_header(req, "From"));
+				transmit_fake_auth_response(p, SIP_MESSAGE, req, XMIT_UNRELIABLE);
+			} else {
+				ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From"));
+				transmit_response(p, "403 Forbidden", req);
+			}
 			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
 			return;
 		}
@@ -19807,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;
@@ -20451,10 +20401,12 @@
 {
 	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:
 		e->command = "sip show settings";
@@ -20471,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;
@@ -20543,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)));
@@ -20552,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));
@@ -22571,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 */
@@ -22858,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 */
@@ -23314,7 +23272,7 @@
 
 		r->regstate = REG_STATE_REGISTERED;
 		r->regtime = ast_tvnow();		/* Reset time of last successful registration */
-		manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: SIP\r\nUsername: %s\r\nDomain: %s\r\nStatus: %s\r\n", r->username, r->hostname, regstate2str(r->regstate));
+		manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: SIP\r\nDomain: %s\r\nStatus: %s\r\n", r->hostname, regstate2str(r->regstate));
 		r->regattempts = 0;
 		ast_debug(1, "Registration successful\n");
 		if (r->timeout > -1) {
@@ -23567,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);
 }
@@ -24580,8 +24543,13 @@
 			return 0;
 		}
 		if (res < 0) { /* Something failed in authentication */
-			ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From"));
-			transmit_response(p, "403 Forbidden", req);
+			if (res == AUTH_FAKE_AUTH) {
+				ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", sip_get_header(req, "From"));
+				transmit_fake_auth_response(p, SIP_OPTIONS, req, XMIT_UNRELIABLE);
+			} else {
+				ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From"));
+				transmit_response(p, "403 Forbidden", req);
+			}
 			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
 			return 0;
 		}
@@ -25243,8 +25211,13 @@
 			goto request_invite_cleanup;
 		}
 		if (res < 0) { /* Something failed in authentication */
-			ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From"));
-			transmit_response_reliable(p, "403 Forbidden", req);
+			if (res == AUTH_FAKE_AUTH) {
+				ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", sip_get_header(req, "From"));
+				transmit_fake_auth_response(p, SIP_INVITE, req, XMIT_RELIABLE);
+			} else {
+				ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From"));
+				transmit_response_reliable(p, "403 Forbidden", req);
+			}
 			p->invitestate = INV_COMPLETED;
 			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
 			goto request_invite_cleanup;
@@ -25412,7 +25385,7 @@
 
 	/* Session-Timers */
 	if ((p->sipoptions & SIP_OPT_TIMER)) {
-		enum st_refresher_param st_ref_param = SESSION_TIMER_REFRESHER_PARAM_UNKNOWN;
+		enum st_refresher_param st_ref_param;
 
 		/* The UAC has requested session-timers for this session. Negotiate
 		the session refresh interval and who will be the refresher */
@@ -26584,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);
 
@@ -26614,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);
 			}
@@ -27287,13 +27262,18 @@
 		return -1;
 	}
 
-	auth_result = check_user(p, req, SIP_PUBLISH, uri, XMIT_UNRELIABLE, addr);
+	auth_result = check_user(p, req, SIP_PUBLISH, uri, XMIT_RELIABLE, addr);
 	if (auth_result == AUTH_CHALLENGE_SENT) {
 		p->lastinvite = seqno;
 		return 0;
 	} else if (auth_result < 0) {
-		ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From"));
-		transmit_response(p, "403 Forbidden", req);
+		if (auth_result == AUTH_FAKE_AUTH) {
+			ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", sip_get_header(req, "From"));
+			transmit_fake_auth_response(p, SIP_INVITE, req, XMIT_RELIABLE);
+		} else {
+			ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From"));
+			transmit_response_reliable(p, "403 Forbidden", req);
+		}
 		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
 		ast_string_field_set(p, theirtag, NULL);
 		return 0;
@@ -27501,14 +27481,19 @@
 	 * use if !req->ignore, because then we'll end up sending
 	 * a 200 OK if someone retransmits without sending auth */
 	if (p->subscribed == NONE || resubscribe) {
-		res = check_user_full(p, req, SIP_SUBSCRIBE, e, XMIT_UNRELIABLE, addr, &authpeer);
+		res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, addr, &authpeer);
 
 		/* if an authentication response was sent, we are done here */
 		if (res == AUTH_CHALLENGE_SENT)	/* authpeer = NULL here */
 			return 0;
 		if (res != AUTH_SUCCESSFUL) {
-			ast_log(LOG_NOTICE, "Failed to authenticate device %s for SUBSCRIBE\n", sip_get_header(req, "From"));
-			transmit_response(p, "403 Forbidden", req);
+			if (res == AUTH_FAKE_AUTH) {
+				ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", sip_get_header(req, "From"));
+				transmit_fake_auth_response(p, SIP_SUBSCRIBE, req, XMIT_UNRELIABLE);
+			} else {
+				ast_log(LOG_NOTICE, "Failed to authenticate device %s for SUBSCRIBE\n", sip_get_header(req, "From"));
+				transmit_response_reliable(p, "403 Forbidden", req);
+			}
 
 			pvt_set_needdestroy(p, "authentication failed");
 			return 0;
@@ -29002,11 +28987,7 @@
 
 	if (p->stimer->st_ref == SESSION_TIMER_REFRESHER_US) {
 		res = 1;
-		if (T38_ENABLED == p->t38.state) {
-			transmit_reinvite_with_sdp(p, TRUE, TRUE);
-		} else {
-			transmit_reinvite_with_sdp(p, FALSE, TRUE);
-		}
+		transmit_reinvite_with_sdp(p, FALSE, TRUE);
 	} else {
 		p->stimer->st_expirys++;
 		if (p->stimer->st_expirys >= 2) {
@@ -29333,9 +29314,6 @@
 \note	This is done with 60 seconds between each ping,
 	unless forced by cli or manager. If peer is unreachable,
 	we check every 10th second by default.
-\note Do *not* hold a pvt lock while calling this function.
-	This function calls sip_alloc, which can cause a deadlock
-	if another sip_pvt is held.
 */
 static int sip_poke_peer(struct sip_peer *peer, int force)
 {
@@ -29696,22 +29674,6 @@
 		ast_string_field_set(p, peername, ext);
 	/* Recalculate our side, and recalculate Call ID */
 	ast_sip_ouraddrfor(&p->sa, &p->ourip, p);
-	/* When chan_sip is first loaded, we may have a peer entry but it hasn't re-registered yet.
-	   If the peer hasn't re-registered, we have not checked for NAT yet.  With the new
-	   auto_* settings, we need to check for NAT so we do not have one-way audio. */
-	check_for_nat(&p->ourip, p);
-	set_peer_nat(p, p->relatedpeer);
-
-	if (p->natdetected && ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
-		ast_copy_flags(&p->flags[0], &p->relatedpeer->flags[0], SIP_NAT_FORCE_RPORT);
-	}
-
-	if (p->natdetected && ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) {
-		ast_copy_flags(&p->flags[1], &p->relatedpeer->flags[1], SIP_PAGE2_SYMMETRICRTP);
-	}
-
-	do_setnat(p);
-
 	build_via(p);
 
 	/* Change the dialog callid. */
@@ -31125,8 +31087,7 @@
 	struct sip_peer *peer;
 	char *cat, *stringp, *context, *oldregcontext;
 	char newcontexts[AST_MAX_CONTEXT], oldcontexts[AST_MAX_CONTEXT];
-	struct ast_flags mask[3] = {{0}};
-	struct ast_flags setflags[3] = {{0}};
+	struct ast_flags dummy[3];
 	struct ast_flags config_flags = { (reason == CHANNEL_MODULE_LOAD || reason == CHANNEL_ACL_RELOAD) ? 0 : ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) ? 0 : CONFIG_FLAG_FILEUNCHANGED };
 	int auto_sip_domains = FALSE;
 	struct ast_sockaddr old_bindaddr = bindaddr;
@@ -31346,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;
@@ -31371,12 +31334,13 @@
 	ast_clear_flag(&global_flags[1], SIP_PAGE2_TEXTSUPPORT);
 	ast_clear_flag(&global_flags[1], SIP_PAGE2_IGNORESDPVERSION);
 
+
 	/* Read the [general] config section of sip.conf (or from realtime config) */
 	for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
-		if (handle_common_options(&setflags[0], &mask[0], v)) {
+		if (handle_common_options(&global_flags[0], &dummy[0], v)) {
 			continue;
 		}
-		if (handle_t38_options(&setflags[0], &mask[0], v, &global_t38_maxdatagram)) {
+		if (handle_t38_options(&global_flags[0], &dummy[0], v, &global_t38_maxdatagram)) {
 			continue;
 		}
 		/* handle jb conf */
@@ -31384,12 +31348,9 @@
 			continue;
 		}
 
-		/* handle tls conf, don't allow setting of tlsverifyclient as it isn't supported by chan_sip */
-		if (!strcasecmp(v->name, "tlsverifyclient")) {
-			ast_log(LOG_WARNING, "Ignoring unsupported option 'tlsverifyclient'\n");
+		/* handle tls conf */
+		if (!ast_tls_read_conf(&default_tls_cfg, &sip_tls_desc, v->name, v->value)) {
 			continue;
-		} else if (!ast_tls_read_conf(&default_tls_cfg, &sip_tls_desc, v->name, v->value)) {
-			continue;
 		}
 
 		if (!strcasecmp(v->name, "context")) {
@@ -31824,6 +31785,13 @@
 				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);
 		} else if (!strcasecmp(v->name, "authfailureevents")) {
@@ -31918,11 +31886,6 @@
 		}
 	}
 
-	/* Override global defaults if setting found in general section */
-	ast_copy_flags(&global_flags[0], &setflags[0], mask[0].flags);
-	ast_copy_flags(&global_flags[1], &setflags[1], mask[1].flags);
-	ast_copy_flags(&global_flags[2], &setflags[2], mask[2].flags);
-
 	/* For backwards compatibility the corresponding registration timer value is used if subscription timer value isn't set by configuration */
 	if (!min_subexpiry_set) {
 		min_subexpiry = min_expiry;
@@ -33075,7 +33038,6 @@
 /*! \brief Force reload of module from cli */
 static char *sip_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	static struct sip_peer *tmp_peer, *new_peer;
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -33098,18 +33060,6 @@
 	ast_mutex_unlock(&sip_reload_lock);
 	restart_monitor();
 
-	tmp_peer = bogus_peer;
-	/* Create new bogus peer possibly with new global settings. */
-	if ((new_peer = temp_peer("(bogus_peer)"))) {
-		ast_string_field_set(new_peer, md5secret, BOGUS_PEER_MD5SECRET);
-		ast_clear_flag(&new_peer->flags[0], SIP_INSECURE);
-		bogus_peer = new_peer;
-		ao2_t_ref(tmp_peer, -1, "unref the old bogus_peer during reload");
-	} else {
-		ast_log(LOG_ERROR, "Could not update the fake authentication peer.\n");
-		/* You probably have bigger (memory?) issues to worry about though.. */
-	}
-
 	return CLI_SUCCESS;
 }
 
@@ -34328,17 +34278,6 @@
 		return AST_MODULE_LOAD_DECLINE;
 	}
 
-	/* Initialize bogus peer. Can be done first after reload_config() */
-	if (!(bogus_peer = temp_peer("(bogus_peer)"))) {
-		ast_log(LOG_ERROR, "Unable to create bogus_peer for authentication\n");
-		io_context_destroy(io);
-		ast_sched_context_destroy(sched);
-		return AST_MODULE_LOAD_FAILURE;
-	}
-	/* Make sure the auth will always fail. */
-	ast_string_field_set(bogus_peer, md5secret, BOGUS_PEER_MD5SECRET);
-	ast_clear_flag(&bogus_peer->flags[0], SIP_INSECURE);
-
 	/* Prepare the version that does not require DTMF BEGIN frames.
 	 * We need to use tricks such as memcpy and casts because the variable
 	 * has const fields.
@@ -34354,7 +34293,6 @@
 	/* Make sure we can register our sip channel type */
 	if (ast_channel_register(&sip_tech)) {
 		ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n");
-		ao2_t_ref(bogus_peer, -1, "unref the bogus_peer");
 		io_context_destroy(io);
 		ast_sched_context_destroy(sched);
 		return AST_MODULE_LOAD_FAILURE;
@@ -34617,8 +34555,6 @@
 		ast_debug(2, "TCP/TLS thread container did not become empty :(\n");
 	}
 
-	ao2_t_ref(bogus_peer, -1, "unref the bogus_peer");
-
 	ao2_t_ref(peers, -1, "unref the peers table");
 	ao2_t_ref(peers_by_ip, -1, "unref the peers_by_ip table");
 	ao2_t_ref(dialogs, -1, "unref the dialogs table");
Index: channels/chan_iax2.c
===================================================================
--- channels/chan_iax2.c	(.../branches/11)	(revision 385989)
+++ channels/chan_iax2.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -9685,9 +9685,6 @@
 	if (!cur_pkt_buf)
 		AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry);
 
-	to_here->iostate = IAX_IOSTATE_READY;
-	ast_cond_signal(&to_here->cond);
-
 	ast_mutex_unlock(&to_here->lock);
 }
 
@@ -12405,26 +12402,16 @@
 			ast_cond_init(&thread->cond, NULL);
 			ast_mutex_init(&thread->init_lock);
 			ast_cond_init(&thread->init_cond, NULL);
-
-			ast_mutex_lock(&thread->init_lock);
-
 			if (ast_pthread_create_background(&thread->threadid, NULL, iax2_process_thread, thread)) {
 				ast_log(LOG_WARNING, "Failed to create new thread!\n");
 				ast_mutex_destroy(&thread->lock);
 				ast_cond_destroy(&thread->cond);
-				ast_mutex_unlock(&thread->init_lock);
 				ast_mutex_destroy(&thread->init_lock);
 				ast_cond_destroy(&thread->init_cond);
 				ast_free(thread);
 				thread = NULL;
 				continue;
 			}
-			/* Wait for the thread to be ready */
-			ast_cond_wait(&thread->init_cond, &thread->init_lock);
-
-			/* Done with init_lock */
-			ast_mutex_unlock(&thread->init_lock);
-
 			AST_LIST_LOCK(&idle_list);
 			AST_LIST_INSERT_TAIL(&idle_list, thread, list);
 			AST_LIST_UNLOCK(&idle_list);
Index: channels/chan_alsa.c
===================================================================
--- channels/chan_alsa.c	(.../branches/11)	(revision 385989)
+++ channels/chan_alsa.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -478,13 +478,6 @@
 	} else if (r < 0) {
 		ast_log(LOG_ERROR, "Read error: %s\n", snd_strerror(r));
 	}
-
-	/* Return NULL frame on error */
-	if (r < 0) {
-		ast_mutex_unlock(&alsalock);
-		return &f;
-	}
-
 	/* Update positions */
 	readpos += r;
 	left -= r;
Index: channels/sip/include/security_events.h
===================================================================
--- channels/sip/include/security_events.h	(.../branches/11)	(revision 385989)
+++ channels/sip/include/security_events.h	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: channels/sip/include/security_events.h
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+"Author Date Id Rev URL"
\ No newline at end of property
Index: channels/sip/include/sip.h
===================================================================
--- channels/sip/include/sip.h	(.../branches/11)	(revision 385989)
+++ channels/sip/include/sip.h	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -503,6 +503,7 @@
 	AUTH_SECRET_FAILED = -1,
 	AUTH_USERNAME_MISMATCH = -2,
 	AUTH_NOT_FOUND = -3,	/*!< returned by register_verify */
+	AUTH_FAKE_AUTH = -4,
 	AUTH_UNKNOWN_DOMAIN = -5,
 	AUTH_PEER_NOT_DYNAMIC = -6,
 	AUTH_ACL_FAILED = -7,
@@ -749,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 */
@@ -1158,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?  */
@@ -1187,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) */
Index: channels/sip/include/rtcp.h
===================================================================
--- channels/sip/include/rtcp.h	(.../branches/11)	(revision 0)
+++ channels/sip/include/rtcp.h	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -0,0 +1,50 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013 Olle E. Johansson, Edvina AB
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file rtcp.h
+ *
+ * \brief RTCP additional functions
+ *
+ * \author Olle E. Johansson <oej@edvina.net>
+ */
+
+#include "asterisk.h"
+
+#include "asterisk/utils.h"
+#include "asterisk/rtp_engine.h"
+#include "sip.h"
+
+#ifndef _SIP_RTCP_H
+#define _SIP_RTCP_H
+
+/*! \brief Set various data items in the RTP structure, like channel identifier.
+ */
+void sip_rtcp_set_data(struct sip_pvt *dialog, struct ast_rtp_instance *instance, enum media_type type);
+
+int send_rtcp_events(const void *data);
+void start_rtcp_events(struct sip_pvt *dialog, struct ast_sched_context *sched);
+/*
+# For 1.4:
+# static void sip_rtcp_report(struct sip_pvt *p, struct ast_rtp *rtp, enum media_type type, int reporttype);
+*/
+
+void sip_rtcp_report(struct sip_pvt *dialog, struct ast_rtp_instance *instance, enum media_type type, int reporttype);
+//void qos_write_realtime(struct sip_pvt *dialog, struct ast_rtp_quality *qual);
+void qos_write_realtime(struct sip_pvt *dialog, struct ast_rtp_instance_stats *qual);
+
+
+
+#endif /* _SIP_RTCP_H */

Property changes on: channels/sip/include/rtcp.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: channels/sip/rtcp.c
===================================================================
--- channels/sip/rtcp.c	(.../branches/11)	(revision 0)
+++ channels/sip/rtcp.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -0,0 +1,382 @@
+/*
+* Asterisk -- An open source telephony toolkit.
+*
+* Copyright (C) 2013 Olle E. Johansson, Edvina AB
+*
+* See http://www.asterisk.org for more information about
+* the Asterisk project. Please do not directly contact
+* any of the maintainers of this project for assistance;
+* the project provides a web site, mailing lists and IRC
+* channels for your use.
+*
+* This program is free software, distributed under the terms of
+* the GNU General Public License Version 2. See the LICENSE file
+* at the top of the source tree.
+*/
+
+/*! \file rtcp.c
+*
+* \brief RTCP additional functions
+*
+* \author Olle E. Johansson <oej@edvina.net>
+*/
+
+/*** MODULEINFO
+	<support_level>core</support_level>
+***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/utils.h"
+#include "asterisk/manager.h"
+#include "asterisk/logger.h"
+#include "asterisk/translate.h"
+#include "asterisk/rtp_engine.h"
+#include "include/sip.h"
+#include "include/rtcp.h"
+
+/*! \brief Set various data items in the RTP structure, like channel identifier.
+ */
+void sip_rtcp_set_data(struct sip_pvt *dialog, struct ast_rtp_instance *instance, enum media_type type)
+{
+
+	if (dialog && dialog->owner) {
+		struct ast_channel *bridgepeer = ast_bridged_channel(dialog->owner);
+
+		if (bridgepeer) {
+			/* Store the bridged peer data while we have it */
+			ast_rtp_instance_set_bridged_chan(instance, ast_channel_name(dialog->owner), ast_channel_uniqueid(dialog->owner), S_OR(ast_channel_name(bridgepeer), ""), S_OR(ast_channel_uniqueid(bridgepeer), ""));
+			ast_debug(1, "---- Setting bridged peer name to %s\n", ast_channel_name(bridgepeer));
+		} else {
+			ast_rtp_instance_set_bridged_chan(instance, ast_channel_name(dialog->owner), ast_channel_uniqueid(dialog->owner), NULL, NULL);
+		}
+		ast_debug(1, "---- Setting channel name to %s\n", ast_channel_name(dialog->owner));
+
+ 		/* Try to find out if there's active transcoding */
+		/* Currently, the only media stream that has translation is the audio stream. At some point
+		   we might have transcoding for other types of media. */
+		if (type == SDP_AUDIO) {
+			const char *rtname = NULL, *wtname = NULL;
+			struct ast_trans_pvt *rt, *wt;
+
+			/* if we have a translator, the bridge delay is increased, which affects the QoS of the call.  */
+			rt = ast_channel_readtrans(dialog->owner);
+			wt = ast_channel_writetrans(dialog->owner);
+			if (rt) {
+				rtname = rt->t->name;
+			}
+			if (wt) {
+				wtname = wt->t->name;
+			}
+			if (rt || wt) {
+				ast_rtp_instance_set_translator(instance, rtname, rt ? rt->t->comp_cost : (const int) 0,
+					wtname, wt ? wt->t->comp_cost : (const int) 0);
+			}
+		
+			if (option_debug > 1) {
+ 				if (rt && rt->t) {
+ 					ast_debug(1, "--- Audio Read translator: %s Cost %d\n", rt->t->name, rt->t->comp_cost);
+ 				}
+ 				if (wt && wt->t) {
+ 					ast_debug(1, "--- Audio Write translator: %s Cost %d\n", wt->t->name, wt->t->comp_cost);
+ 				}
+			}
+		}
+
+	} else {
+ 		ast_debug(1, "######## Not setting rtcp media data. Dialog %s Dialog owner %s \n", dialog ? "set" : "unset",  dialog->owner ? "set" : "unset");
+	}
+}
+
+/*! \brief send manager report of RTCP 
+	reporttype = 0  means report during call (if configured)
+	reporttype = 1  means endof-call (hangup) report
+	reporttype = 10  means report at end of call leg (like transfer)
+*/
+void sip_rtcp_report(struct sip_pvt *dialog, struct ast_rtp_instance *instance, enum media_type media, int reporttype)
+{
+	struct ast_rtp_instance_stats qual;
+	//char *rtpqstring = NULL;
+	//int qosrealtime = ast_check_realtime("rtpcqr");
+	unsigned int duration;	/* Duration in secs */
+	memset(&qual, 0, sizeof(qual));
+	
+	sip_rtcp_set_data(dialog, instance, media);
+
+	if (ast_rtp_instance_get_stats(instance, &qual, AST_RTP_INSTANCE_STAT_ALL)) {
+ 		ast_debug(1, "######## Did not get any statistics... bad, bad, RTP instance\n");
+		/* Houston, we got a problem */
+		return;
+	}
+	
+	if (dialog->sip_cfg->rtcpevents) {
+		/* 
+		   If numberofreports == 0 we have no incoming RTCP active, thus we can't
+		   get any reliable data to handle packet loss or any RTT timing.
+		*/
+
+		duration = (unsigned int)(ast_tvdiff_ms(ast_tvnow(), qual.start) / 1000);
+		manager_event(EVENT_FLAG_CALL, "RTPQuality", 
+			"Channel: %s\r\n"			/* AST_CHANNEL for this call */
+			"Uniqueid: %s\r\n"			/* AST_CHANNEL for this call */
+			"BridgedChannel: %s\r\n"
+			"BridgedUniqueid: %s\r\n"
+			"RTPreporttype: %s\r\n"
+			"RTPrtcpstatus: %s\r\n"
+			"Duration: %u\r\n"		/* used in cdr_manager */
+			"PvtCallid: %s\r\n"		/* ??? Generic PVT identifier */
+			"RTPipaddress: %s\r\n"
+			"RTPmedia: %s\r\n"		/* Audio, video, text */
+			"RTPsendformat: %s\r\n"
+			"RTPrecvformat: %s\r\n"
+			"RTPlocalssrc: %u\r\n"
+			"RTPremotessrc: %u\r\n"
+			"RTPrtt: %f\r\n"
+			"RTPrttMax: %f\r\n"
+			"RTPrttMin: %f\r\n"
+			"RTPLocalJitter: %f\r\n"
+			"RTPRemoteJitter: %f\r\n" 
+			"RTPInPacketLoss: %d\r\n" 
+			"RTPInLocalPlPercent: %5.2f\r\n"
+			"RTPOutPacketLoss: %d\r\n"
+			"RTPOutPlPercent: %5.2f\r\n"
+			"TranslateRead: %s\r\n"
+			"TranslateReadCost: %d\r\n"
+			"TranslateWrite: %s\r\n"
+			"TranslateWriteCost: %d\r\n"
+			"\r\n", 
+			dialog->owner ? ast_channel_name(dialog->owner) : "",
+			dialog->owner ? ast_channel_uniqueid(dialog->owner) : "",
+			qual.bridgedchannel[0] ? qual.bridgedchannel : "" ,
+			qual.bridgeduniqueid[0] ? qual.bridgeduniqueid : "",
+			reporttype == 1 ? "Final" : "Update",
+			qual.numberofreports == 0 ? "Inactive" : "Active",
+			duration,
+			dialog->callid, 
+			ast_inet_ntoa(qual.them.sin_addr), 	
+			media == SDP_AUDIO ? "audio" : (media == SDP_VIDEO ? "video" : "fax") ,
+			ast_getformatname(&qual.lasttxformat),
+			ast_getformatname(&qual.lastrxformat),
+			qual.local_ssrc, 
+			qual.remote_ssrc,
+			qual.rtt,
+			qual.maxrtt,
+			qual.minrtt,
+			qual.rxjitter,
+			qual.txjitter,
+			qual.rxploss,
+			/* The local counter of lost packets in inbound stream divided with received packets plus lost packets */
+			(qual.remote_txcount + qual.rxploss) > 0 ? (double) qual.rxploss / (qual.remote_txcount + qual.rxploss) * 100 : 0,
+			qual.txploss,
+			/* The remote counter of lost packets (if we got the reports)
+			   divided with our counter of sent packets
+			 */
+			(qual.rxcount + qual.txploss) > 0 ? (double) qual.txploss / qual.rxcount  * 100 : 0,
+			qual.readtranslator, qual.readcost,
+			qual.writetranslator, qual.writecost
+		);
+	}
+
+	/* CDR records are not reliable when it comes to near-death-of-channel events, so we need to store the RTCP
+	   report in realtime when we have it.
+	   Tests have proven that storing to realtime from the call thread is NOT a good thing. Therefore, we just save
+	   the quality report structure in the PVT and let the function that kills the pvt store the stuff in the
+	   monitor thread instead.
+	 */
+	if (reporttype == 1) {
+		ast_log(LOG_DEBUG, "---- Activation qual structure in dialog \n");
+		qual.end = ast_tvnow();
+ 		qual.mediatype = media;
+		if (media == SDP_AUDIO) {  /* Audio */
+			dialog->audioqual = ast_calloc(1, sizeof(struct ast_rtp_instance_stats));
+			(* dialog->audioqual) = qual;
+		} else if (media == SDP_VIDEO) {  /* Video */
+			dialog->videoqual = ast_calloc(1,sizeof(struct ast_rtp_instance_stats));
+			(* dialog->videoqual) = qual;
+		}
+	}
+}
+
+/*! \brief Write quality report to realtime storage */
+void qos_write_realtime(struct sip_pvt *dialog, struct ast_rtp_instance_stats *qual)
+{
+	unsigned int duration;	/* Duration in secs */
+	char buf_duration[10], buf_lssrc[30], buf_rssrc[30];
+	char buf_rtt[10], buf_rttmin[10], buf_rttmax[10];
+	char localjitter[10], remotejitter[10];
+	char buf_readcost[5], buf_writecost[5];
+	char buf_mediatype[10];
+	char buf_remoteip[25];
+	char buf_inpacketloss[25], buf_outpacketloss[25];
+	char buf_outpackets[25], buf_inpackets[25];
+	int qosrealtime = ast_check_realtime("rtpcqr");
+
+
+	if (!qual) {
+		ast_log(LOG_ERROR, "No CQR data provided \n");
+		return;
+	}
+
+	/* Since the CDR is already gone, we need to calculate our own duration.
+	   The CDR duration is the definitive resource for billing, this is
+	   the RTP stream duration which may include early media (ringing and
+	   provider messages). Only useful for measurements.
+	 */
+	if (!ast_tvzero(qual->end) && !ast_tvzero(qual->start)) {
+		duration = (unsigned int)(ast_tvdiff_ms(qual->end, qual->start) / 1000);
+	} else {
+		ast_debug(2, "**** What? No duration? What type of call is THAT? \n");
+		duration = 0;
+	}
+
+	/* Realtime is based on strings, so let's make strings */
+	sprintf(localjitter, "%f", qual->rxjitter);
+	sprintf(remotejitter, "%f", qual->txjitter);
+	sprintf(buf_lssrc, "%u", qual->local_ssrc);
+	sprintf(buf_rssrc, "%u", qual->remote_ssrc);
+	sprintf(buf_rtt, "%.0f", qual->rtt);
+	sprintf(buf_rttmax, "%.0f", qual->maxrtt);
+	sprintf(buf_rttmin, "%.0f", qual->minrtt);
+	sprintf(buf_duration, "%u", duration);
+	sprintf(buf_readcost, "%d", qual->readcost);
+	sprintf(buf_writecost, "%d", qual->writecost);
+	sprintf(buf_mediatype,"%s", qual->mediatype == SDP_AUDIO ? "audio" : (qual->mediatype == SDP_VIDEO ? "video" : "fax") );
+	sprintf(buf_remoteip,"%s", ast_inet_ntoa(qual->them.sin_addr));
+	sprintf(buf_inpacketloss, "%d", qual->rxploss);
+	sprintf(buf_outpacketloss, "%d", qual->txploss);
+	sprintf(buf_inpackets, "%d", qual->rxcount);		/* Silly value. Need to check this */
+	sprintf(buf_outpackets, "%d", qual->txcount);
+	//sprintf(buf_inpackets, "%d", qual->remote_count);	/* Do check again */
+	//sprintf(buf_outpackets, "%d", qual->local_count);
+
+	ast_log(LOG_CQR, "CQR Channel: %s Uid %s Bch %s Buid %s Pvt %s Media %s Lssrc %s Rssrc %s Rip %s Rtt %s:%s:%s Ljitter %s Rjitter %s Rtcpstatus %s Dur %s Pout %s Plossout %s Pin %s Plossin %s\n",
+		qual->channel[0] ? qual->channel : "",
+		qual->uniqueid[0] ? qual->uniqueid : "",
+		qual->bridgedchannel[0] ? qual->bridgedchannel : "" ,
+		qual->bridgeduniqueid[0] ? qual->bridgeduniqueid : "",
+		dialog->callid,
+		buf_mediatype,
+		buf_lssrc,
+		buf_rssrc,
+		buf_remoteip,
+		buf_rtt, buf_rttmax, buf_rttmin,
+		localjitter,
+		remotejitter,
+		qual->numberofreports == 0 ? "Inactive" : "Active",
+		buf_duration,
+		buf_outpackets,
+		buf_outpacketloss,
+		buf_inpackets,
+		buf_inpacketloss);
+
+	if (!qosrealtime) {
+		return;
+	}
+/* Example database schema for MySQL:
+CREATE TABLE `astcqr` (
+  `channel` varchar(50) NOT NULL,
+  `uniqueid` varchar(35) NOT NULL,
+  `bridgedchannel` varchar(50) NOT NULL,
+  `bridgeduniqueid` varchar(35) NOT NULL,
+  `pvtcallid` varchar(80) NOT NULL,
+  `rtpmedia` varchar(50) NOT NULL,
+  `localssrc` varchar(50) NOT NULL,
+  `remotessrc` varchar(50) NOT NULL,
+  `rtt` varchar(10) NOT NULL,
+  `localjitter` varchar(10) NOT NULL,
+  `remotejitter` varchar(10) NOT NULL,
+  `sendformat` varchar(10) NOT NULL,
+  `receiveformat` varchar(10) NOT NULL,
+  `rtcpstatus` varchar(10) NOT NULL,
+  `duration` varchar(10) NOT NULL,
+  `packetsent` varchar(30) NOT NULL,
+  `packetreceived` varchar(30) NOT NULL,
+  `packetlossin` varchar(30) NOT NULL,
+  `packetlossout` varchar(30) NOT NULL,
+  `rttmax` varchar(12) NOT NULL,
+  `rttmin` varchar(12) NOT NULL,
+  `writetranslator` varchar(15) NOT NULL,
+  `readtranslator` varchar(15) NOT NULL,
+  `writecost` varchar(10) NOT NULL,
+  `readcost` varchar(10) NOT NULL,
+  `remoteip` varchar(25) NOT NULL,
+  KEY `ChannelUnique` (`channel`,`uniqueid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='FOr pinefrog stats'
+*/
+
+	ast_store_realtime("rtpcqr", 
+		"channel", qual->channel[0] ? qual->channel : "--no channel--",
+		"uniqueid", qual->uniqueid[0] ? qual->uniqueid : "--no uniqueid --",
+		"bridgedchannel", qual->bridgedchannel[0] ? qual->bridgedchannel : "" ,
+		"bridgeduniqueid", qual->bridgeduniqueid[0] ? qual->bridgeduniqueid : "",
+		"pvtcallid", dialog->callid, 
+		"rtpmedia", buf_mediatype, 
+		"localssrc", buf_lssrc, 
+		"remotessrc", buf_rssrc,
+		"remoteip", buf_remoteip,
+		"rtt", buf_rtt, 
+		"rttmax", buf_rttmax, 
+		"rttmin", buf_rttmin, 
+		"localjitter", localjitter, 
+		"remotejitter", remotejitter, 
+		"sendformat", ast_getformatname(&qual->lasttxformat),
+		"receiveformat", ast_getformatname(&qual->lastrxformat),
+		"rtcpstatus", qual->numberofreports == 0 ? "Inactive" : "Active",
+		"duration", buf_duration,
+		"writetranslator", qual->writetranslator[0] ? qual->writetranslator : "",
+		"writecost", buf_writecost,
+		"readtranslator", qual->readtranslator[0] ? qual->readtranslator : "",
+		"readcost", buf_readcost,
+		"packetlossin", buf_inpacketloss,
+		"packetlossout", buf_outpacketloss,
+		"packetsent", buf_outpackets,
+		"packetreceived", buf_inpackets,
+		NULL);
+}
+
+/*! \brief Send RTCP manager events */
+int send_rtcp_events(const void *data)
+{
+	struct sip_pvt *dialog = (struct sip_pvt *) data;
+	ast_log(LOG_DEBUG, "***** SENDING RTCP EVENT \n");
+
+	if (dialog->rtp && !ast_rtp_instance_isactive(dialog->rtp)) {
+		ast_debug(1, "          ***** Activating RTCP report \n");
+		sip_rtcp_report(dialog, dialog->rtp, SDP_AUDIO, FALSE);
+	} else {
+		ast_debug(1, "          ***** NOT Activating RTCP report \n");
+	}
+	if (dialog->vrtp && !ast_rtp_instance_isactive(dialog->vrtp)) {
+		sip_rtcp_report(dialog, dialog->vrtp, SDP_VIDEO, FALSE);
+	}
+	return (dialog->sip_cfg ? dialog->sip_cfg->rtcptimer : 0);
+}
+
+/*! \brief Activate RTCP events at start of call */
+void start_rtcp_events(struct sip_pvt *dialog, struct ast_sched_context *sched)
+{
+	ast_debug(2, "***** STARTING SENDING RTCP EVENT \n");
+	/* Check if it's already active */
+
+	if (dialog->rtp && !ast_rtp_instance_isactive(dialog->rtp)) {
+		sip_rtcp_set_data(dialog, dialog->rtp, SDP_AUDIO);
+	}
+	if (dialog->vrtp && !ast_rtp_instance_isactive(dialog->vrtp)) {
+		sip_rtcp_set_data(dialog, dialog->vrtp, SDP_VIDEO);
+	}
+
+	if (!dialog->sip_cfg->rtcpevents || !dialog->sip_cfg->rtcptimer) {
+		ast_debug(2, "***** NOT SENDING RTCP EVENTS \n");
+		return;
+	}
+
+	if (dialog->rtcpeventid != -1) {
+		return;
+	}
+
+
+	/*! \brief Schedule events */
+	dialog->rtcpeventid = ast_sched_add(sched, dialog->sip_cfg->rtcptimer * 1000, send_rtcp_events, dialog);
+}

Property changes on: channels/sip/rtcp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: channels/sip/security_events.c
===================================================================
--- channels/sip/security_events.c	(.../branches/11)	(revision 385989)
+++ channels/sip/security_events.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -342,6 +342,9 @@
 		/* with sip_cfg.alwaysauthreject on, generates 2 events */
 		sip_report_invalid_peer(p);
 		break;
+	case AUTH_FAKE_AUTH:
+		sip_report_invalid_peer(p);
+		break;
 	case AUTH_UNKNOWN_DOMAIN:
 		snprintf(aclname, sizeof(aclname), "domain_must_match");
 		sip_report_failed_acl(p, aclname);

Property changes on: channels/sip/security_events.c
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+"Author Date Id Rev URL"
\ No newline at end of property
Index: channels/sip/dialplan_functions.c
===================================================================
--- channels/sip/dialplan_functions.c	(.../branches/11)	(revision 385989)
+++ channels/sip/dialplan_functions.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -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;
Index: channels/sig_ss7.c
===================================================================
--- channels/sig_ss7.c	(.../branches/11)	(revision 385989)
+++ channels/sig_ss7.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: channels/sig_ss7.c
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Author Date Id Revision'
\ No newline at end of property
Index: channels/chan_multicast_rtp.c
===================================================================
--- channels/chan_multicast_rtp.c	(.../branches/11)	(revision 385989)
+++ channels/chan_multicast_rtp.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: channels/chan_multicast_rtp.c
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Author Date Id Revision'
\ No newline at end of property
Index: channels/sig_ss7.h
===================================================================
--- channels/sig_ss7.h	(.../branches/11)	(revision 385989)
+++ channels/sig_ss7.h	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: channels/sig_ss7.h
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Author Date Id Revision'
\ No newline at end of property
Index: channels/sig_pri.c
===================================================================
--- channels/sig_pri.c	(.../branches/11)	(revision 385989)
+++ channels/sig_pri.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -6410,10 +6410,6 @@
 
 							snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
 							pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
-							ast_channel_lock(c);
-							ast_channel_dialed(c)->number.plan = e->ring.calledplan;
-							ast_channel_unlock(c);
-
 							if (e->ring.redirectingreason >= 0) {
 								/* This is now just a status variable.  Use REDIRECTING() dialplan function. */
 								pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
@@ -6552,9 +6548,6 @@
 
 							snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
 							pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
-							ast_channel_lock(c);
-							ast_channel_dialed(c)->number.plan = e->ring.calledplan;
-							ast_channel_unlock(c);
 
 							sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.subcmds,
 								e->ring.call);
@@ -6752,11 +6745,9 @@
 					/* Bring voice path up */
 					pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
 					pri->pvts[chanpos]->progress = 1;
-					sig_pri_set_dialing(pri->pvts[chanpos], 0);
 					sig_pri_open_media(pri->pvts[chanpos]);
-				} else if (pri->inband_on_proceeding) {
-					sig_pri_set_dialing(pri->pvts[chanpos], 0);
 				}
+				sig_pri_set_dialing(pri->pvts[chanpos], 0);
 				sig_pri_unlock_private(pri->pvts[chanpos]);
 				break;
 			case PRI_EVENT_FACILITY:
Index: CREDITS
===================================================================
--- CREDITS	(.../branches/11)	(revision 385989)
+++ CREDITS	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -25,6 +25,9 @@
 
 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
 Nick Seraphin - RDNIS 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)
Index: tests/test_poll.c
===================================================================
--- tests/test_poll.c	(.../branches/11)	(revision 385989)
+++ tests/test_poll.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: tests/test_poll.c
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Date Author Id Revision Yoyo'
\ No newline at end of property
Index: tests/test_func_file.c
===================================================================
--- tests/test_func_file.c	(.../branches/11)	(revision 385989)
+++ tests/test_func_file.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: tests/test_func_file.c
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Date Author Id Revision Yoyo'
\ No newline at end of property
Index: tests/test_locale.c
===================================================================
--- tests/test_locale.c	(.../branches/11)	(revision 385989)
+++ tests/test_locale.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: tests/test_locale.c
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Date Author Id Revision Yoyo'
\ No newline at end of property
Index: tests/test_expr.c
===================================================================
--- tests/test_expr.c	(.../branches/11)	(revision 385989)
+++ tests/test_expr.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: tests/test_expr.c
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Date Author Id Revision Yoyo'
\ No newline at end of property
Index: configure.ac
===================================================================
--- configure.ac	(.../branches/11)	(revision 385989)
+++ configure.ac	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -474,7 +474,6 @@
 AST_EXT_LIB_SETUP([TINFO], [Term Info], [tinfo])
 AST_EXT_LIB_SETUP([TONEZONE], [tonezone], [tonezone])
 AST_EXT_LIB_SETUP([UNIXODBC], [unixODBC], [unixodbc])
-AST_EXT_LIB_SETUP([UUID], [UUID], [uuid])
 AST_EXT_LIB_SETUP([VORBIS], [Vorbis], [vorbis])
 AST_EXT_LIB_SETUP([VPB], [Voicetronix API], [vpb])
 AST_EXT_LIB_SETUP([X11], [X11], [x11])
@@ -2201,8 +2200,6 @@
 
 AST_EXT_LIB_CHECK([TONEZONE], [tonezone], [tone_zone_find], [dahdi/tonezone.h], [${tonezone_extra} ${DAHDI_INCLUDE}])
 
-AST_EXT_LIB_CHECK([UUID], [uuid], [uuid_generate_random], [uuid/uuid.h])
-
 if test "${OSARCH}" = "OpenBSD";
 then
 	AST_EXT_LIB_CHECK([VORBIS], [vorbis], [vorbis_info_init], [vorbis/codec.h], [-lm -lvorbisenc -lvorbisfile -logg])
Index: apps/app_saycounted.c
===================================================================
--- apps/app_saycounted.c	(.../branches/11)	(revision 385989)
+++ apps/app_saycounted.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: apps/app_saycounted.c
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Date Author Id Revision Yoyo'
\ No newline at end of property
Index: apps/app_mixmonitor.c
===================================================================
--- apps/app_mixmonitor.c	(.../branches/11)	(revision 385989)
+++ apps/app_mixmonitor.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -1042,7 +1042,7 @@
 	return 0;
 }
 
-static int stop_mixmonitor_full(struct ast_channel *chan, const char *data)
+static int stop_mixmonitor_exec(struct ast_channel *chan, const char *data)
 {
 	struct ast_datastore *datastore = NULL;
 	char *parse = "";
@@ -1096,12 +1096,6 @@
 	return 0;
 }
 
-static int stop_mixmonitor_exec(struct ast_channel *chan, const char *data)
-{
-	stop_mixmonitor_full(chan, data);
-	return 0;
-}
-
 static char *handle_cli_mixmonitor(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct ast_channel *chan;
@@ -1321,7 +1315,7 @@
 		return AMI_SUCCESS;
 	}
 
-	res = stop_mixmonitor_full(c, mixmonitor_id);
+	res = stop_mixmonitor_exec(c, mixmonitor_id);
 
 	if (res) {
 		astman_send_error(s, m, "Could not stop monitoring channel");
Index: apps/app_meetme.c
===================================================================
--- apps/app_meetme.c	(.../branches/11)	(revision 385989)
+++ apps/app_meetme.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -5916,16 +5916,7 @@
 			ringing_trunk = sla_choose_ringing_trunk(ringing_station->station, &s_trunk_ref, 1);
 			ast_mutex_unlock(&sla.lock);
 			if (!ringing_trunk) {
-				/* This case happens in a bit of a race condition.  If two stations answer
-				 * the outbound call at the same time, the first one will get connected to
-				 * the trunk.  When the second one gets here, it will not see any trunks
-				 * ringing so we have no idea what to conect it to.  So, we just hang up
-				 * on it. */
 				ast_debug(1, "Found no ringing trunk for station '%s' to answer!\n", ringing_station->station->name);
-				ast_dial_join(ringing_station->station->dial);
-				ast_dial_destroy(ringing_station->station->dial);
-				ringing_station->station->dial = NULL;
-				ast_free(ringing_station);
 				break;
 			}
 			/* Track the channel that answered this trunk */
Index: apps/app_voicemail.c
===================================================================
--- apps/app_voicemail.c	(.../branches/11)	(revision 385989)
+++ apps/app_voicemail.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -1677,14 +1677,6 @@
 	return res;
 }
 
-/*!
- * \brief Check if configuration file is valid
- */
-static inline int valid_config(const struct ast_config *cfg)
-{
-	return cfg && cfg != CONFIG_STATUS_FILEINVALID;
-}
-
 /*! 
  * \brief The handler for the change password option.
  * \param vmu The voicemail user to work with.
@@ -1721,7 +1713,7 @@
 		}
 		/* Fall-through */
 	case OPT_PWLOC_VOICEMAILCONF:
-		if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && valid_config(cfg)) {
+		if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
 			while ((category = ast_category_browse(cfg, category))) {
 				if (!strcasecmp(category, vmu->context)) {
 					if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
@@ -1750,17 +1742,14 @@
 				reset_user_pw(vmu->context, vmu->mailbox, newpassword);
 				ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
 				ast_config_text_file_save(VOICEMAIL_CONFIG, cfg, "AppVoicemail");
-				ast_config_destroy(cfg);
 				break;
 			}
-
-			ast_config_destroy(cfg);
 		}
 		/* Fall-through */
 	case OPT_PWLOC_USERSCONF:
 		/* check users.conf and update the password stored for the mailbox */
 		/* if no vmsecret entry exists create one. */
-		if ((cfg = ast_config_load("users.conf", config_flags)) && valid_config(cfg)) {
+		if ((cfg = ast_config_load("users.conf", config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
 			ast_debug(4, "we are looking for %s\n", vmu->mailbox);
 			for (category = ast_category_browse(cfg, NULL); category; category = ast_category_browse(cfg, category)) {
 				ast_debug(4, "users.conf: %s\n", category);
@@ -1794,8 +1783,6 @@
 				ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
 				ast_config_text_file_save("users.conf", cfg, "AppVoicemail");
 			}
-
-			ast_config_destroy(cfg);
 		}
 	}
 }
@@ -4150,7 +4137,7 @@
 			res = -1;
 			break;
 		}
-		if (valid_config(cfg)) {
+		if (cfg && cfg != CONFIG_STATUS_FILEINVALID) {
 			if (!(idata.context = ast_variable_retrieve(cfg, "message", "context"))) {
 				idata.context = "";
 			}
@@ -4206,7 +4193,7 @@
 	if (obj) {
 		ast_odbc_release_obj(obj);
 	}
-	if (valid_config(cfg))
+	if (cfg)
 		ast_config_destroy(cfg);
 	if (fdm != MAP_FAILED)
 		munmap(fdm, fdlen);
@@ -4685,7 +4672,7 @@
 	if (strlen(fromfile) < sizeof(fromfile) - 5) {
 		strcat(fromfile, ".txt");
 	}
-	if (!(msg_cfg = ast_config_load(fromfile, config_flags)) || !(valid_config(msg_cfg))) {
+	if (!(msg_cfg = ast_config_load(fromfile, config_flags))) {
 		ast_debug(1, "Config load for message text file '%s' failed\n", fromfile);
 		return;
 	}
@@ -5077,7 +5064,7 @@
 			if (strlen(fromfile) < sizeof(fromfile) - 5) {
 				strcat(fromfile, ".txt");
 			}
-			if ((msg_cfg = ast_config_load(fromfile, config_flags)) && valid_config(msg_cfg)) {
+			if ((msg_cfg = ast_config_load(fromfile, config_flags))) {
 				if ((v = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
 					ast_copy_string(origcallerid, v, sizeof(origcallerid));
 				}
@@ -5915,10 +5902,7 @@
 		if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
 			ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
 		} else {
-			snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &",
-				externnotify, S_OR(context, "\"\""),
-				extension, newvoicemails,
-				oldvoicemails, urgentvoicemails);
+			snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &", externnotify, context, extension, newvoicemails, oldvoicemails, urgentvoicemails);
 			ast_debug(1, "Executing %s\n", arguments);
 			ast_safe_system(arguments);
 		}
@@ -7563,7 +7547,7 @@
 	strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
 	strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
 
-	if ((msg_cfg = ast_config_load(textfile, config_flags)) && valid_config(msg_cfg) && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
+	if ((msg_cfg = ast_config_load(textfile, config_flags)) && msg_cfg != CONFIG_STATUS_FILEINVALID && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
 		*duration = atoi(duration_str);
 	} else {
 		*duration = 0;
@@ -7599,7 +7583,7 @@
 			*duration = 0;
 
 			/* if we can't read the message metadata, stop now */
-			if (!valid_config(msg_cfg)) {
+			if (!msg_cfg) {
 				cmd = 0;
 				break;
 			}
@@ -7683,7 +7667,7 @@
 		}
 	}
 
-	if (valid_config(msg_cfg))
+	if (msg_cfg)
 		ast_config_destroy(msg_cfg);
 	if (prepend_duration)
 		*duration = prepend_duration;
@@ -8443,7 +8427,7 @@
 	snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
 	RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
 	msg_cfg = ast_config_load(filename, config_flags);
-	if (!valid_config(msg_cfg)) {
+	if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
 		ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
 		return 0;
 	}
@@ -8521,7 +8505,7 @@
 		}
 	}
 
-	if (!valid_config(msg_cfg)) {
+	if (!msg_cfg) {
 		ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
 		return 0;
 	}
@@ -13578,7 +13562,7 @@
 	struct ast_flags config_flags = { 0 };
 
 	pwconf = ast_config_load(secretfn, config_flags);
-	if (valid_config(pwconf)) {
+	if (pwconf) {
 		const char *val = ast_variable_retrieve(pwconf, "general", "password");
 		if (val) {
 			ast_copy_string(password, val, passwordlen);
@@ -14065,7 +14049,7 @@
 	fputs("00000002 => 9999,Mrs. Test\n", file);
 	fclose(file);
 
-	if (!(cfg = ast_config_load(config_filename, config_flags)) || !valid_config(cfg)) {
+	if (!(cfg = ast_config_load(config_filename, config_flags))) {
 		res = AST_TEST_FAIL;
 		goto cleanup;
 	}
@@ -14383,7 +14367,7 @@
 	RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
 	msg_cfg = ast_config_load(filename, config_flags);
 	DISPOSE(vms->curdir, vms->curmsg);
-	if (!valid_config(msg_cfg)) {
+	if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
 		ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
 		return 0;
 	}
@@ -14545,9 +14529,9 @@
 		break;
 	}
 
+#ifndef IMAP_STORAGE
 	ast_config_destroy(msg_cfg);
 
-#ifndef IMAP_STORAGE
 	if (!res) {
 		make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
 		vms->heard[msg] = 1;
@@ -14826,8 +14810,8 @@
 
 	AST_LIST_LOCK(&users);
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&users, vmu, list) {
-		if (!strcmp(context, vmu->context)
-			&& !strcmp(mailbox, vmu->mailbox)) {
+		if (!strncmp(context, vmu->context, sizeof(context))
+			&& !strncmp(mailbox, vmu->mailbox, sizeof(mailbox))) {
 			AST_LIST_REMOVE_CURRENT(list);
 			ast_free(vmu);
 			break;
Index: apps/app_queue.c
===================================================================
--- apps/app_queue.c	(.../branches/11)	(revision 385989)
+++ apps/app_queue.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -9828,9 +9828,6 @@
 	res |= ast_manager_unregister("QueuePause");
 	res |= ast_manager_unregister("QueueLog");
 	res |= ast_manager_unregister("QueuePenalty");
-	res |= ast_manager_unregister("QueueReload");
-	res |= ast_manager_unregister("QueueReset");
-	res |= ast_manager_unregister("QueueMemberRingInUse");
 	res |= ast_unregister_application(app_aqm);
 	res |= ast_unregister_application(app_rqm);
 	res |= ast_unregister_application(app_pqm);
Index: doc/Makefile
===================================================================
--- doc/Makefile	(.../branches/11)	(revision 385989)
+++ doc/Makefile	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: doc/Makefile
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Date Author Id Revision Yoyo'
\ No newline at end of property
Index: UPGRADE.txt
===================================================================
--- UPGRADE.txt	(.../branches/11)	(revision 385989)
+++ UPGRADE.txt	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -20,10 +20,6 @@
 ===
 ===========================================================
 
-From 11.4 to 11.5:
-* The default settings for chan_sip are now overriden properly by the general
-  settings in sip.conf.  Please look over your settings upon upgrading.
-
 From 11.3 to 11.4:
 * Added the 'n' option to MeetMe to prevent application of the DENOISE function
   to a channel joining a conference. Some channel drivers that vary the number
@@ -31,10 +27,6 @@
   if a denoiser is attached to the channel; this option gives them the ability
   to remove the denoiser without having to unload func_speex.
 
-* The Registry AMI event for SIP registrations will now always include the
-  Username field. A previous bug fix missed an instance where it was not
-  included; that has been corrected in this release.
-
 From 11.2.0 to 11.2.1:
 * Asterisk would previously not output certain error messages when a remote
   console attempted to connect to Asterisk and no instance of Asterisk was
Index: addons/res_config_mysql.c
===================================================================
--- addons/res_config_mysql.c	(.../branches/11)	(revision 385989)
+++ addons/res_config_mysql.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -937,7 +937,7 @@
 		return NULL;
 	}
 
-	ast_str_set(&sql, 0, "SELECT category, var_name, var_val, cat_metric FROM %s WHERE filename='%s' and commented=0 ORDER BY filename, category, cat_metric desc, var_metric asc, var_name, var_val, id", table, file);
+	ast_str_set(&sql, 0, "SELECT category, var_name, var_val, cat_metric FROM %s WHERE filename='%s' and commented=0 ORDER BY filename, cat_metric desc, var_metric asc, category, var_name, var_val, id", table, file);
 
 	ast_debug(1, "MySQL RealTime: Static SQL: %s\n", ast_str_buffer(sql));
 
Index: README.pinefrog-rtcp
===================================================================
--- README.pinefrog-rtcp	(.../branches/11)	(revision 0)
+++ README.pinefrog-rtcp	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -0,0 +1,162 @@
+Olle E. Johansson
+oej@edvina.net
+
+2013-03-14
+
+
+
+
+
+
+Pinefrog - RTCP cleanup and additions
+-------------------------------------
+
+This branch is aimed at porting the code in pinefrog-1.4, which is now a few years old,
+to Asterisk 1.8 and hopefully (with some help) to Asterisk trunk to be integrated.
+The 1.4 code has been running in production for years in universities, call centers
+and service providers.
+
+The 1.8 port of Pinefrog is supported by Nordicom, Norway (http://www.nordicom.no). 
+The 1.4 work was sponsored by several companies, including ClearIT AB, Sweden.
+
+Status of 11 port
+------------------
+2013-03-13	Started
+
+Todo for 11
+------------
+DONE: - Add support of outbound and inbound SDES. The SDES includes a stream identifier, CNAME. 
+DONE: - Add support of outbound SDES end and goodbye
+DONE: - Add manager events at end-of call
+DONE: - Add realtime storage of RTCP reports
+DONE: - Add time manager events (configured in sip.conf)
+DONE: - Add more information to RTCP debug
+DONE: - Add more data aggregation to ast_rtcp structure (from svn trunk really)
+- Add RTCP for p2p RTP bridges. Needs to be tested and validated.
+
+Background
+==========
+RTCP, as defined in RFC 3550, is a protocol that co-exists with RTP, the protocol used
+for realtime multimedia in VoIP. RTCP gives the endpoints a tool to exchange data about
+the media streams exchanged. As a result, both ends can get informaiton about the
+latency for data sent in both directions, packet loss and jitter for each media stream.
+
+A VoIP call is at least two media streams and they can have different properties in
+regards of quality. A router or switch in the middle could have a lot of outbound traffic,
+causing delays and possible packet loss. This might not affect inbound traffic.
+
+In Asterisk, the RTCP handler is part of the RTP module. The RTP module produces RTCP
+report that can be added to channel variables, cdr logs or sent through AMI.
+
+In 1.4, the data used is mostly based on the latest report, it's not aggregated. This
+is fixed in trunk.
+
+In both implementations (and the 1.6 releases in between) the RTCP support is not
+very complete.
+
+- It doesn't handle RTCP SDES packets
+- It doesn't send RTCP END packets at end of session
+- It doesn't handle receiving END packets
+- It doesn't handle re-invites in a good way.
+- It seems to mix sender and receiver reports, thus mixing data from two streams 
+    - when does this happen, if at all?
+
+RTCP and NAT
+------------
+I suspect that RTCP doesn't traverse NAT very well in our implementation. For RTP,
+we start with sending media to probe NAT. I've added emtpy RTCP RR+SDES CNAME packets
+to start probing a NAT (if Asterisk is behind a NAT). I am afraid that very few devices
+do that early on.
+The idea is (like RTP)
+ - Send a few RTCP packets in the start of the session.
+ - The receiver can then apply symmetric RTCP and start sending to the NAT outside port
+   that we're sending from and we'll get their packets.
+
+Todo
+----
+- When CNAME changes, we have a different stream and need to restart the stats.
+  Should we add ability to produce multiple RTCP reports for one "call" and aggregate them?
+  The different parts might have different properties.
+- Document realtime storage format. Add missing fields.
+- BUG: RTCP is halted during hold. It should not stop.
+- During HOLD, send RTCP SR reports without report block, only the header and no chunks 
+
+Open Issues
+-----------
+Bridged channel ID is hard to get.
+
+The CQR and the final manager report lacks the bridged channel identifiers in too many cases. One leg of
+the call gets it, but not both. 
+This will affect realtime as well, so we need to copy the channel name to a stored variable while it exists.
+
+Do we have a counter of consecutive lost packets? How do we measure lost packets on inbound
+stream? Gaps in seq numbers or just the sender reports from the other end compared with received 
+no of packets?
+
+
+
+Ideas and thoughts for the future
+---------------------------------
+- Asterisk propagates jitter and packet loss over a bridge (especially the p2p RTP bridge).
+  If the call is transfered on the OTHER side of the bridge, we have a new call with new
+  properties. Maybe events like this should generate a new SDES and reset RTCP?
+  Part A of the call can have very different properties than part B. If I have a call with
+  someone internally, that then transfers me to a call with someone on the Internet, the
+  call quality (jitter etc) will change dramatically. This will require some sort of CONTROL
+  packet over the bridge, informing about changes on the other side of the bridge (masq).
+- Can we have some sort of ring buffer for the latest RTCP reports for a device (peer) 
+  and use that to determine the status of the connection to the peer?
+- Can we use the RTCP APP packet for relaying events in joined bridges, like meetme?
+- What should we use as CNAME? Currently SIP call ID.
+- Separate on the IPs of different media servers. IE we can have one SIP peer with
+  multiple media IPs with different properties
+
+Scenarios to test
+------------------
+- normal bridged call
+- RTP p2p bridged call
+- Nat traversal - Asterisk outside of NAT and inside (as client to external service)
+- Call hold
+- Call with music-on-hold
+
+Database structure
+-------------------
+Example database schema for MySQL:
+
+CREATE TABLE `astcqr` (
+  `channel` varchar(50) NOT NULL,
+  `uniqueid` varchar(35) NOT NULL,
+  `bridgedchannel` varchar(50) NOT NULL,
+  `bridgeduniqueid` varchar(35) NOT NULL,
+  `pvtcallid` varchar(80) NOT NULL,
+  `rtpmedia` varchar(50) NOT NULL,
+  `localssrc` varchar(50) NOT NULL,
+  `remotessrc` varchar(50) NOT NULL,
+  `rtt` varchar(10) NOT NULL,
+  `localjitter` varchar(10) NOT NULL,
+  `remotejitter` varchar(10) NOT NULL,
+  `sendformat` varchar(10) NOT NULL,
+  `receiveformat` varchar(10) NOT NULL,
+  `rtcpstatus` varchar(10) NOT NULL,
+  `duration` varchar(10) NOT NULL,
+  `packetsent` varchar(30) NOT NULL,
+  `packetreceived` varchar(30) NOT NULL,
+  `packetlossin` varchar(30) NOT NULL,
+  `packetlossout` varchar(30) NOT NULL,
+  `rttmax` varchar(12) NOT NULL,
+  `rttmin` varchar(12) NOT NULL,
+  `writetranslator` varchar(15) NOT NULL,
+  `readtranslator` varchar(15) NOT NULL,
+  `writecost` varchar(10) NOT NULL,
+  `readcost` varchar(10) NOT NULL,
+  `remoteip` varchar(25) NOT NULL,
+  KEY `ChannelUnique` (`channel`,`uniqueid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='FOr pinefrog stats'
+
+Realtime configuration
+========================
+In extconfig.conf add
+
+rtpcqr => mysql,asterisk,astcqr
+
+

Property changes on: README.pinefrog-rtcp
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: Makefile
===================================================================
--- Makefile	(.../branches/11)	(revision 385989)
+++ Makefile	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -360,7 +360,7 @@
 	+@$(SUBMAKE) $(MOD_SUBDIRS_EMBED_LDFLAGS)
 	+@$(SUBMAKE) $(MOD_SUBDIRS_EMBED_LIBS)
 
-$(SUBDIRS): makeopts .lastclean main/version.c include/asterisk/build.h include/asterisk/buildopts.h defaults.h makeopts.embed_rules
+$(SUBDIRS): makeopts cleantest main/version.c include/asterisk/build.h include/asterisk/buildopts.h defaults.h makeopts.embed_rules
 
 ifeq ($(findstring $(OSARCH), mingw32 cygwin ),)
     # Non-windows:
@@ -386,25 +386,25 @@
 $(OTHER_SUBDIRS): makeopts
 	+@_ASTCFLAGS="$(OTHER_SUBDIR_CFLAGS) $(_ASTCFLAGS)" ASTCFLAGS="$(ASTCFLAGS)" _ASTLDFLAGS="$(_ASTLDFLAGS)" ASTLDFLAGS="$(ASTLDFLAGS)" $(SUBMAKE) --no-builtin-rules -C $@ SUBDIR=$@ all
 
-defaults.h: makeopts .lastclean build_tools/make_defaults_h
+defaults.h: makeopts build_tools/make_defaults_h
 	@build_tools/make_defaults_h > $@.tmp
 	@cmp -s $@.tmp $@ || mv $@.tmp $@
 	@rm -f $@.tmp
 
-main/version.c: FORCE .lastclean
+main/version.c: FORCE
 	@build_tools/make_version_c > $@.tmp
 	@cmp -s $@.tmp $@ || mv $@.tmp $@
 	@rm -f $@.tmp
 
-include/asterisk/buildopts.h: menuselect.makeopts .lastclean
+include/asterisk/buildopts.h: menuselect.makeopts
 	@build_tools/make_buildopts_h > $@.tmp
 	@cmp -s $@.tmp $@ || mv $@.tmp $@
 	@rm -f $@.tmp
 
-# build.h must depend on .lastclean, or parallel make may wipe it out after it's
-# been created.
-include/asterisk/build.h: .lastclean
-	@build_tools/make_build_h > $@
+include/asterisk/build.h:
+	@build_tools/make_build_h > $@.tmp
+	@cmp -s $@.tmp $@ || mv $@.tmp $@
+	@rm -f $@.tmp
 
 $(SUBDIRS_CLEAN):
 	+@$(SUBMAKE) -C $(@:-clean=) clean
@@ -458,7 +458,7 @@
 	done
 	$(MAKE) -C sounds install
 
-doc/core-en_US.xml: makeopts .lastclean $(foreach dir,$(MOD_SUBDIRS),$(shell $(GREP) -l "language=\"en_US\"" $(dir)/*.c $(dir)/*.cc 2>/dev/null))
+doc/core-en_US.xml: makeopts $(foreach dir,$(MOD_SUBDIRS),$(shell $(GREP) -l "language=\"en_US\"" $(dir)/*.c $(dir)/*.cc 2>/dev/null))
 	@printf "Building Documentation For: "
 	@echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > $@
 	@echo "<!DOCTYPE docs SYSTEM \"appdocsxml.dtd\">" >> $@
@@ -472,7 +472,7 @@
 	@echo
 	@echo "</docs>" >> $@
 
-doc/full-en_US.xml: makeopts .lastclean $(foreach dir,$(MOD_SUBDIRS),$(shell $(GREP) -l "language=\"en_US\"" $(dir)/*.c $(dir)/*.cc 2>/dev/null))
+doc/full-en_US.xml: makeopts $(foreach dir,$(MOD_SUBDIRS),$(shell $(GREP) -l "language=\"en_US\"" $(dir)/*.c $(dir)/*.cc 2>/dev/null))
 ifeq ($(PYTHON),:)
 	@echo "--------------------------------------------------------------------------"
 	@echo "---        Please install python to build full documentation           ---"
@@ -822,8 +822,8 @@
 # .cleancount is the global clean count, and .lastclean is the
 # last clean count we had
 
-.lastclean: .cleancount
-	@$(MAKE) clean
+cleantest:
+	@cmp -s .cleancount .lastclean || $(MAKE) clean
 	@[ -f "$(DESTDIR)$(ASTDBDIR)/astdb.sqlite3" ] || [ ! -f "$(DESTDIR)$(ASTDBDIR)/astdb" ] || [ ! -f menuselect.makeopts ] || grep -q MENUSELECT_UTILS=.*astdb2sqlite3 menuselect.makeopts || (sed -i.orig -e's/MENUSELECT_UTILS=\(.*\)/MENUSELECT_UTILS=\1 astdb2sqlite3/' menuselect.makeopts && echo "Updating menuselect.makeopts to include astdb2sqlite3" && echo "Original version backed up to menuselect.makeopts.orig")
 
 $(SUBDIRS_UNINSTALL):
@@ -901,19 +901,19 @@
 		CFLAGS="$(BUILD_CFLAGS)" LDFLAGS="$(BUILD_LDFLAGS)" \
 		$(MAKE) -C menuselect CONFIGURE_SILENT="--silent"
 
-menuselect/menuselect: menuselect/makeopts .lastclean
+menuselect/menuselect: menuselect/makeopts cleantest
 	+$(MAKE_MENUSELECT) menuselect
 
-menuselect/cmenuselect: menuselect/makeopts .lastclean
+menuselect/cmenuselect: menuselect/makeopts cleantest
 	+$(MAKE_MENUSELECT) cmenuselect
 
-menuselect/gmenuselect: menuselect/makeopts .lastclean
+menuselect/gmenuselect: menuselect/makeopts cleantest
 	+$(MAKE_MENUSELECT) gmenuselect
 
-menuselect/nmenuselect: menuselect/makeopts .lastclean
+menuselect/nmenuselect: menuselect/makeopts cleantest
 	+$(MAKE_MENUSELECT) nmenuselect
 
-menuselect/makeopts: makeopts .lastclean
+menuselect/makeopts: makeopts cleantest
 	+$(MAKE_MENUSELECT) makeopts
 
 menuselect-tree: $(foreach dir,$(filter-out main,$(MOD_SUBDIRS)),$(wildcard $(dir)/*.c) $(wildcard $(dir)/*.cc)) build_tools/cflags.xml build_tools/cflags-devmode.xml sounds/sounds.xml build_tools/embed_modules.xml utils/utils.xml agi/agi.xml configure makeopts
@@ -944,6 +944,7 @@
 .PHONY: full
 .PHONY: _full
 .PHONY: prereqs
+.PHONY: cleantest
 .PHONY: uninstall
 .PHONY: _uninstall
 .PHONY: uninstall-all
Index: funcs/func_curl.c
===================================================================
--- funcs/func_curl.c	(.../branches/11)	(revision 385989)
+++ funcs/func_curl.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -581,7 +581,6 @@
 	struct ast_datastore *store = NULL;
 	int hashcompat = 0;
 	AST_LIST_HEAD(global_curl_info, curl_settings) *list = NULL;
-	char curl_errbuf[CURL_ERROR_SIZE + 1]; /* add one to be safe */
 
 	if (buf) {
 		*buf = '\0';
@@ -643,20 +642,8 @@
 		curl_easy_setopt(*curl, CURLOPT_POSTFIELDS, args.postdata);
 	}
 
-	/* Temporarily assign a buffer for curl to write errors to. */
-	curl_errbuf[0] = curl_errbuf[CURL_ERROR_SIZE] = '\0';
-	curl_easy_setopt(*curl, CURLOPT_ERRORBUFFER, curl_errbuf);
+	curl_easy_perform(*curl);
 
-	if (curl_easy_perform(*curl) != 0) {
-		ast_log(LOG_WARNING, "%s ('%s')\n", curl_errbuf, args.url);
-	}
-
-	/* Reset buffer to NULL so curl doesn't try to write to it when the
-	 * buffer is deallocated. Documentation is vague about allowing NULL
-	 * here, but the source allows it. See: "typecheck: allow NULL to unset
-	 * CURLOPT_ERRORBUFFER" (62bcf005f4678a93158358265ba905bace33b834). */
-	curl_easy_setopt(*curl, CURLOPT_ERRORBUFFER, (char*)NULL);
-
 	if (store) {
 		AST_LIST_UNLOCK(list);
 	}
@@ -678,11 +665,20 @@
 			int rowcount = 0;
 			while (fields && values && (piece = strsep(&remainder, "&"))) {
 				char *name = strsep(&piece, "=");
-				struct ast_flags mode = (hashcompat == HASHCOMPAT_LEGACY ? ast_uri_http_legacy : ast_uri_http);
-				if (piece) {
-					ast_uri_decode(piece, mode);
+				/* Do this before the decode, because if something has encoded
+				 * a literal plus-sign, we don't want to translate that to a
+				 * space. */
+				if (hashcompat == HASHCOMPAT_LEGACY) {
+					if (piece) {
+						ast_uri_decode(piece, ast_uri_http_legacy);
+					}
+					ast_uri_decode(name, ast_uri_http_legacy);
+				} else {
+					if (piece) {
+						ast_uri_decode(piece, ast_uri_http);
+					}
+					ast_uri_decode(name, ast_uri_http);
 				}
-				ast_uri_decode(name, mode);
 				ast_str_append(&fields, 0, "%s%s", rowcount ? "," : "", ast_str_set_escapecommas(&escapebuf, 0, name, INT_MAX));
 				ast_str_append(&values, 0, "%s%s", rowcount ? "," : "", ast_str_set_escapecommas(&escapebuf, 0, S_OR(piece, ""), INT_MAX));
 				rowcount++;
Index: funcs/func_channel.c
===================================================================
--- funcs/func_channel.c	(.../branches/11)	(revision 385989)
+++ funcs/func_channel.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -77,20 +77,6 @@
 			<parameter name="item" required="true">
 				<para>Standard items (provided by all channel technologies) are:</para>
 				<enumlist>
-					<enum name="amaflags">
-						<para>R/W the Automatic Message Accounting (AMA) flags on the channel.
-						When read from a channel, the integer value will always be returned.
-						When written to a channel, both the string format or integer value
-						is accepted.</para>
-						<enumlist>
-							<enum name="1"><para><literal>OMIT</literal></para></enum>
-							<enum name="2"><para><literal>BILLING</literal></para></enum>
-							<enum name="3"><para><literal>DOCUMENTATION</literal></para></enum>
-						</enumlist>
-					</enum>
-					<enum name="accountcode">
-						<para>R/W the channel's account code.</para>
-					</enum>
 					<enum name="audioreadformat">
 						<para>R/O format currently being read.</para>
 					</enum>
Index: autoconf/ast_ext_lib.m4
===================================================================
--- autoconf/ast_ext_lib.m4	(.../branches/11)	(revision 385989)
+++ autoconf/ast_ext_lib.m4	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -112,9 +112,9 @@
    # if --with-$1=DIR has been specified, use it.
    if test "x${$1_DIR}" != "x"; then
       if test -d ${$1_DIR}/lib; then
-         pbxlibdir="-L${$1_DIR}/lib"
+      	 pbxlibdir="-L${$1_DIR}/lib"
       else
-         pbxlibdir="-L${$1_DIR}"
+      	 pbxlibdir="-L${$1_DIR}"
       fi
    fi
    pbxfuncname="$3"
Index: include/asterisk/bridging_features.h
===================================================================
--- include/asterisk/bridging_features.h	(.../branches/11)	(revision 385989)
+++ include/asterisk/bridging_features.h	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: include/asterisk/bridging_features.h
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Author Date Id Revision'
\ No newline at end of property
Index: include/asterisk/select.h
===================================================================
--- include/asterisk/select.h	(.../branches/11)	(revision 385989)
+++ include/asterisk/select.h	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: include/asterisk/select.h
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Date Author Id Revision Yoyo'
\ No newline at end of property
Index: include/asterisk/bridging_technology.h
===================================================================
--- include/asterisk/bridging_technology.h	(.../branches/11)	(revision 385989)
+++ include/asterisk/bridging_technology.h	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: include/asterisk/bridging_technology.h
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Author Date Id Revision'
\ No newline at end of property
Index: include/asterisk/rtp_engine.h
===================================================================
--- include/asterisk/rtp_engine.h	(.../branches/11)	(revision 385989)
+++ include/asterisk/rtp_engine.h	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -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
Index: include/asterisk/translate.h
===================================================================
--- include/asterisk/translate.h	(.../branches/11)	(revision 385989)
+++ include/asterisk/translate.h	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -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 */
Index: include/asterisk/logger.h
===================================================================
--- include/asterisk/logger.h	(.../branches/11)	(revision 385989)
+++ include/asterisk/logger.h	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -209,8 +209,19 @@
 #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
  * \param module the name of module
Index: include/asterisk/autoconfig.h.in
===================================================================
--- include/asterisk/autoconfig.h.in	(.../branches/11)	(revision 385989)
+++ include/asterisk/autoconfig.h.in	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -1016,9 +1016,6 @@
 /* Define to 1 if `utime(file, NULL)' sets file's timestamp to the present. */
 #undef HAVE_UTIME_NULL
 
-/* Define to 1 if you have the UUID library. */
-#undef HAVE_UUID
-
 /* Define to 1 if your system can support larger than default select bitmasks.
    */
 #undef HAVE_VARIABLE_FDSET
@@ -1229,6 +1226,11 @@
 /* Define to 1 if running on Darwin. */
 #undef _DARWIN_UNLIMITED_SELECT
 
+/* Enable large inode numbers on Mac OS X 10.5.  */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
 /* Number of bits in a file offset, on hosts where this is settable. */
 #undef _FILE_OFFSET_BITS
 
Index: main/cdr.c
===================================================================
--- main/cdr.c	(.../branches/11)	(revision 385989)
+++ main/cdr.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -115,8 +115,6 @@
 static int batchsafeshutdown;
 static const int BATCH_SAFE_SHUTDOWN_DEFAULT = 1;
 
-AST_MUTEX_DEFINE_STATIC(cdr_sched_lock);
-
 AST_MUTEX_DEFINE_STATIC(cdr_batch_lock);
 
 /* these are used to wake up the CDR thread when there's work to do */
@@ -1351,24 +1349,17 @@
 {
 	ast_cdr_submit_batch(0);
 	/* manually reschedule from this point in time */
-	ast_mutex_lock(&cdr_sched_lock);
 	cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
-	ast_mutex_unlock(&cdr_sched_lock);
 	/* returning zero so the scheduler does not automatically reschedule */
 	return 0;
 }
 
-/*! Do not hold the batch lock while calling this function */
 static void submit_unscheduled_batch(void)
 {
-	/* Prevent two deletes from happening at the same time */
-	ast_mutex_lock(&cdr_sched_lock);
 	/* this is okay since we are not being called from within the scheduler */
 	AST_SCHED_DEL(sched, cdr_sched);
 	/* schedule the submission to occur ASAP (1 ms) */
 	cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL);
-	ast_mutex_unlock(&cdr_sched_lock);
-
 	/* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
 	ast_mutex_lock(&cdr_pending_lock);
 	ast_cond_signal(&cdr_pending_cond);
@@ -1379,7 +1370,6 @@
 {
 	struct ast_cdr_batch_item *newtail;
 	int curr;
-	int submit_batch = 0;
 
 	if (!cdr)
 		return;
@@ -1426,14 +1416,10 @@
 
 	/* if we have enough stuff to post, then do it */
 	if (curr >= (batchsize - 1)) {
-		submit_batch = 1;
+		submit_unscheduled_batch();
 	}
+
 	ast_mutex_unlock(&cdr_batch_lock);
-
-	/* Don't call submit_unscheduled_batch with the cdr_batch_lock held */
-	if (submit_batch) {
-		submit_unscheduled_batch();
-	}
 }
 
 static void *do_cdr(void *data)
@@ -1579,9 +1565,7 @@
 	}
 
 	/* don't run the next scheduled CDR posting while reloading */
-	ast_mutex_lock(&cdr_sched_lock);
 	AST_SCHED_DEL(sched, cdr_sched);
-	ast_mutex_unlock(&cdr_sched_lock);
 
 	for (v = ast_variable_browse(config, "general"); v; v = v->next) {
 		if (!strcasecmp(v->name, "enable")) {
@@ -1622,9 +1606,7 @@
 	if (enabled && !batchmode) {
 		ast_log(LOG_NOTICE, "CDR simple logging enabled.\n");
 	} else if (enabled && batchmode) {
-		ast_mutex_lock(&cdr_sched_lock);
 		cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
-		ast_mutex_unlock(&cdr_sched_lock);
 		ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %d or time %d seconds.\n", batchsize, batchtime);
 	} else {
 		ast_log(LOG_NOTICE, "CDR logging disabled, data will be lost.\n");
@@ -1636,9 +1618,7 @@
 		ast_cond_init(&cdr_pending_cond, NULL);
 		if (ast_pthread_create_background(&cdr_thread, NULL, do_cdr, NULL) < 0) {
 			ast_log(LOG_ERROR, "Unable to start CDR thread.\n");
-			ast_mutex_lock(&cdr_sched_lock);
 			AST_SCHED_DEL(sched, cdr_sched);
-			ast_mutex_unlock(&cdr_sched_lock);
 		} else {
 			ast_cli_register(&cli_submit);
 			ast_register_atexit(ast_cdr_engine_term);
Index: main/manager.c
===================================================================
--- main/manager.c	(.../branches/11)	(revision 385989)
+++ main/manager.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -7563,15 +7563,7 @@
 	for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
 		val = var->value;
 
-		/* read tls config options while preventing unsupported options from being set */
-		if (strcasecmp(var->name, "tlscafile")
-			&& strcasecmp(var->name, "tlscapath")
-			&& strcasecmp(var->name, "tlscadir")
-			&& strcasecmp(var->name, "tlsverifyclient")
-			&& strcasecmp(var->name, "tlsdontverifyserver")
-			&& strcasecmp(var->name, "tlsclientmethod")
-			&& strcasecmp(var->name, "sslclientmethod")
-			&& !ast_tls_read_conf(&ami_tls_cfg, &amis_desc, var->name, val)) {
+		if (!ast_tls_read_conf(&ami_tls_cfg, &amis_desc, var->name, val)) {
 			continue;
 		}
 
Index: main/http.c
===================================================================
--- main/http.c	(.../branches/11)	(revision 385989)
+++ main/http.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -229,7 +229,7 @@
 		goto out403;
 	}
 
-	/* Disallow any funny filenames at all (checking first character only??) */
+	/* Disallow any funny filenames at all */
 	if ((uri[0] < 33) || strchr("./|~@#$%^&*() \t", uri[0])) {
 		goto out403;
 	}
@@ -244,7 +244,6 @@
 
 	if (!(mtype = ast_http_ftype2mtype(ftype))) {
 		snprintf(wkspace, sizeof(wkspace), "text/%s", S_OR(ftype, "plain"));
-		mtype = wkspace;
 	}
 
 	/* Cap maximum length */
@@ -262,12 +261,12 @@
 		goto out404;
 	}
 
-	if (strstr(path, "/private/") && !astman_is_authed(ast_http_manid_from_vars(headers))) {
+	fd = open(path, O_RDONLY);
+	if (fd < 0) {
 		goto out403;
 	}
 
-	fd = open(path, O_RDONLY);
-	if (fd < 0) {
+	if (strstr(path, "/private/") && !astman_is_authed(ast_http_manid_from_vars(headers))) {
 		goto out403;
 	}
 
@@ -290,7 +289,6 @@
 	}
 
 	if ( (http_header = ast_str_create(255)) == NULL) {
-		close(fd);
 		return -1;
 	}
 
@@ -595,8 +593,6 @@
 	AST_RWLIST_UNLOCK(&uris);
 }
 
-#define MAX_POST_CONTENT 1025
-
 /*
  * get post variables from client Request Entity-Body, if content type is
  * application/x-www-form-urlencoded
@@ -629,13 +625,6 @@
 		return NULL;
 	}
 
-	if (content_length > MAX_POST_CONTENT - 1) {
-		ast_log(LOG_WARNING, "Excessively long HTTP content. %d is greater than our max of %d\n",
-				content_length, MAX_POST_CONTENT);
-		ast_http_send(ser, AST_HTTP_POST, 413, "Request Entity Too Large", NULL, NULL, 0, 0);
-		return NULL;
-	}
-
 	buf = ast_malloc(content_length + 1);
 	if (!buf) {
 		return NULL;
@@ -1063,17 +1052,8 @@
 		v = ast_variable_browse(cfg, "general");
 		for (; v; v = v->next) {
 
-			/* read tls config options while preventing unsupported options from being set */
-			if (strcasecmp(v->name, "tlscafile")
-				&& strcasecmp(v->name, "tlscapath")
-				&& strcasecmp(v->name, "tlscadir")
-				&& strcasecmp(v->name, "tlsverifyclient")
-				&& strcasecmp(v->name, "tlsdontverifyserver")
-				&& strcasecmp(v->name, "tlsclientmethod")
-				&& strcasecmp(v->name, "sslclientmethod")
-				&& strcasecmp(v->name, "tlscipher")
-				&& strcasecmp(v->name, "sslcipher")
-				&& !ast_tls_read_conf(&http_tls_cfg, &https_desc, v->name, v->value)) {
+			/* handle tls conf */
+			if (!ast_tls_read_conf(&http_tls_cfg, &https_desc, v->name, v->value)) {
 				continue;
 			}
 
Index: main/devicestate.c
===================================================================
--- main/devicestate.c	(.../branches/11)	(revision 385989)
+++ main/devicestate.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -705,7 +705,7 @@
 static void devstate_change_collector_cb(const struct ast_event *event, void *data)
 {
 	struct devstate_change *sc;
-	const char *device, *cachable_str;
+	const char *device;
 	const struct ast_eid *eid;
 	uint32_t state;
 	enum ast_devstate_cache cachable = AST_DEVSTATE_CACHABLE;
@@ -713,6 +713,7 @@
 	device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
 	eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID);
 	state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
+	cachable = ast_event_get_ie_uint(event, AST_EVENT_IE_CACHABLE);
 
 	if (ast_strlen_zero(device) || !eid) {
 		ast_log(LOG_ERROR, "Invalid device state change event received\n");
@@ -725,16 +726,6 @@
 	strcpy(sc->device, device);
 	sc->eid = *eid;
 	sc->state = state;
-
-	/* For 'cachable' we cannot use ast_event_get_ie_uint(), it overwrites the default of AST_DEVSTATE_CACHABLE we
-	 * have already setup for 'cachable', if for whatever reason the AST_EVENT_IE_CACHABLE wasn't
-	 * posted in the event ast_event_get_ie_uint() is going will return 0,
-	 * which equates to AST_DEVSTATE_NOT_CACHABLE the first enumeration in 'ast_devstate_cache'.
-	 */
-
-	if ((cachable_str = ast_event_get_ie_str(event, AST_EVENT_IE_CACHABLE))) {
-		sscanf(cachable_str, "%30u", &cachable);
-	}
 	sc->cachable = cachable;
 
 	ast_mutex_lock(&devstate_collector.lock);
Index: main/format_pref.c
===================================================================
--- main/format_pref.c	(.../branches/11)	(revision 385989)
+++ main/format_pref.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -317,7 +317,7 @@
 /*! \brief Pick a codec */
 struct ast_format *ast_codec_choose(struct ast_codec_pref *pref, struct ast_format_cap *cap, int find_best, struct ast_format *result)
 {
-	int x, slot, found = 0;
+	int x, slot, found;
 	size_t f_len = 0;
 	const struct ast_format_list *f_list = ast_format_list_get(&f_len);
 
Index: main/logger.c
===================================================================
--- main/logger.c	(.../branches/11)	(revision 385989)
+++ main/logger.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -191,6 +191,7 @@
 	"ERROR",
 	"VERBOSE",
 	"DTMF",
+	"CQR",
 };
 
 /*! \brief Colors used in the console for logging */
@@ -202,6 +203,7 @@
 	COLOR_RED,
 	COLOR_GREEN,
 	COLOR_BRGREEN,
+	COLOR_BRBLUE,
 	0,
 	0,
 	0,
@@ -210,7 +212,6 @@
 	0,
 	0,
 	0,
-	0,
 	COLOR_BRBLUE,
 	COLOR_BRBLUE,
 	COLOR_BRBLUE,
Index: main/tcptls.c
===================================================================
--- main/tcptls.c	(.../branches/11)	(revision 385989)
+++ main/tcptls.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -373,11 +373,6 @@
 		cfg->enabled = 0;
 		return 0;
 	}
-
-	SSL_CTX_set_verify(cfg->ssl_ctx,
-		ast_test_flag(&cfg->flags, AST_SSL_VERIFY_CLIENT) ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE,
-		NULL);
-
 	if (!ast_strlen_zero(cfg->certfile)) {
 		char *tmpprivate = ast_strlen_zero(cfg->pvtfile) ? cfg->certfile : cfg->pvtfile;
 		if (SSL_CTX_use_certificate_file(cfg->ssl_ctx, cfg->certfile, SSL_FILETYPE_PEM) == 0) {
Index: main/rtp_engine.c
===================================================================
--- main/rtp_engine.c	(.../branches/11)	(revision 385989)
+++ main/rtp_engine.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -21,6 +21,9 @@
  * \brief Pluggable RTP Architecture
  *
  * \author Joshua Colp <jcolp@digium.com>
+ *
+ * Improved RTCP support by
+ * \author Olle E. Johansson  <oej@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);
 
@@ -976,6 +987,10 @@
 
 	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;
 	cs[1] = c1;
@@ -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) {
Index: configs/cli_aliases.conf.sample
===================================================================
--- configs/cli_aliases.conf.sample	(.../branches/11)	(revision 385989)
+++ configs/cli_aliases.conf.sample	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -26,7 +26,7 @@
 hangup request=channel request hangup
 originate=channel originate
 help=core show help
-pri intense debug span=pri set debug intense span
+pri intense debug span=pri set debug 2 span
 reload=module reload
 
 ; CLI Alias Templates
Index: configs/res_curl.conf.sample
===================================================================
--- configs/res_curl.conf.sample	(.../branches/11)	(revision 385989)
+++ configs/res_curl.conf.sample	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: configs/res_curl.conf.sample
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Date Author Id Revision Yoyo'
\ No newline at end of property
Index: configs/chan_dahdi.conf.sample
===================================================================
--- configs/chan_dahdi.conf.sample	(.../branches/11)	(revision 385989)
+++ configs/chan_dahdi.conf.sample	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -196,18 +196,6 @@
 ;
 ;resetinterval = 3600
 ;
-; Assume inband audio may be present when a PROCEEDING message is received.
-; Q.931 Section 5.1.2 says the network cannot assume that the CPE side has
-; attached to the B channel at this time without explicitly sending the
-; progress indicator ie informing the CPE side to attach to the B channel
-; for audio.  However, some non-compliant ISDN switches send a PROCEEDING
-; without the progress indicator ie indicating inband audio is available and
-; assume that the CPE device has connected the media path for listening to
-; ringback and other messages.
-; Default yes in current release branches for backward compatibility.
-;
-;inband_on_proceeding=yes
-;
 ; Overlap dialing mode (sending overlap digits)
 ; Cannot be changed on a reload.
 ;
Index: configs/extconfig.conf.sample
===================================================================
--- configs/extconfig.conf.sample	(.../branches/11)	(revision 385989)
+++ configs/extconfig.conf.sample	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -58,17 +58,13 @@
 ; start at 1 and be sequential (i.e. if you have only priorities 1, 2,
 ; and 4, then 4 will be ignored, because there is no 3).
 ;
-;
-; Possible driver backends:
-;
 ; "odbc" is shown in the examples below, but is not the only valid realtime
-; engine.  Here are several of the possible options:
+; engine.  There is:
 ;    odbc ... res_config_odbc
 ;    sqlite ... res_config_sqlite
 ;    pgsql ... res_config_pgsql
 ;    curl ... res_config_curl
 ;    ldap ... res_config_ldap
-;    mysql ... res_config_mysql (available via add-ons in menuselect)
 ;
 ; Note: The res_config_pgsql and res_config_sqlite backends configure the
 ; database used in their respective configuration files and ignore the
@@ -86,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
Index: makeopts.in
===================================================================
--- makeopts.in	(.../branches/11)	(revision 385989)
+++ makeopts.in	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -283,9 +283,6 @@
 UNIXODBC_INCLUDE=@UNIXODBC_INCLUDE@
 UNIXODBC_LIB=@UNIXODBC_LIB@
 
-UUID_INCLUDE=@UUID_INCLUDE@
-UUID_LIB=@UUID_LIB@
-
 VORBIS_INCLUDE=@VORBIS_INCLUDE@
 VORBIS_LIB=@VORBIS_LIB@
 
Index: res/res_rtp_multicast.c
===================================================================
--- res/res_rtp_multicast.c	(.../branches/11)	(revision 385989)
+++ res/res_rtp_multicast.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -90,8 +90,6 @@
 	unsigned int ssrc;
 	/*! Sequence number, used when creating/sending the RTP packet */
 	uint16_t seqno;
-	unsigned int lastts;	
-	struct timeval txcore;
 };
 
 /* Forward Declarations */
@@ -142,30 +140,6 @@
 	return 0;
 }
 
-static int rtp_get_rate(struct ast_format *format)
-{
-        return (format->id == AST_FORMAT_G722) ? 8000 : ast_format_rate(format);
-}
-
-static unsigned int calc_txstamp(struct multicast_rtp *rtp, struct timeval *delivery)
-{
-        struct timeval t;
-        long ms;
-
-        if (ast_tvzero(rtp->txcore)) {
-                rtp->txcore = ast_tvnow();
-                rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
-        }
-
-        t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
-        if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
-                ms = 0;
-        }
-        rtp->txcore = t;
-
-        return (unsigned int) ms;
-}
-
 /*! \brief Helper function which populates a control packet with useful information and sends it */
 static int multicast_send_control_packet(struct ast_rtp_instance *instance, struct multicast_rtp *multicast, int command)
 {
@@ -236,8 +210,6 @@
 	struct ast_sockaddr remote_address;
 	int hdrlen = 12, res = 0, codec;
 	unsigned char *rtpheader;
-	unsigned int ms = calc_txstamp(multicast, &frame->delivery);
-	int rate = rtp_get_rate(&frame->subclass.format) / 1000;
 
 	/* We only accept audio, nothing else */
 	if (frame->frametype != AST_FRAME_VOICE) {
@@ -253,21 +225,12 @@
 	if (frame->offset < hdrlen) {
 		f = ast_frdup(frame);
 	}
-	
-	/* Calucate last TS */
-	multicast->lastts = multicast->lastts + ms * rate;
-	
+
 	/* Construct an RTP header for our packet */
 	rtpheader = (unsigned char *)(f->data.ptr - hdrlen);
 	put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno)));
-	put_unaligned_uint32(rtpheader + 4, htonl(multicast->lastts));
-	
-	if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) {
-		put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8));
-	} 
-	else {
-		put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc));
-	}
+	put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8));
+	put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc));
 
 	/* Increment sequence number and wrap to 0 if it overflows 16 bits. */
 	multicast->seqno = 0xFFFF & (multicast->seqno + 1);

Property changes on: res/res_rtp_multicast.c
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Author Date Id Revision'
\ No newline at end of property
Index: res/res_config_ldap.c
===================================================================
--- res/res_config_ldap.c	(.../branches/11)	(revision 385989)
+++ res/res_config_ldap.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -1236,14 +1236,14 @@
 	}
 
 	mods_size = 2; /* one for the first param/value pair and one for the the terminating NULL */
-	ldap_mods = ldap_memcalloc(sizeof(LDAPMod *), mods_size);
-	ldap_mods[0] = ldap_memcalloc(1, sizeof(LDAPMod));
+	ldap_mods = ast_calloc(sizeof(LDAPMod *), mods_size);
+	ldap_mods[0] = ast_calloc(1, sizeof(LDAPMod));
 
 	ldap_mods[0]->mod_op = LDAP_MOD_REPLACE;
-	ldap_mods[0]->mod_type = ldap_strdup(newparam);
+	ldap_mods[0]->mod_type = ast_strdup(newparam);
 
 	ldap_mods[0]->mod_values = ast_calloc(sizeof(char *), 2);
-	ldap_mods[0]->mod_values[0] = ldap_strdup(newval);
+	ldap_mods[0]->mod_values[0] = ast_strdup(newval);
 
 	while ((newparam = va_arg(ap, const char *))) {
 		newparam = convert_attribute_name_to_ldap(table_config, newparam);
@@ -1253,7 +1253,7 @@
 		for (i = 0; i < mods_size - 1; i++) {
 			if (ldap_mods[i]&& !strcmp(ldap_mods[i]->mod_type, newparam)) {
 				/* We have the parameter allready, adding the value as a semicolon delimited value */
-				ldap_mods[i]->mod_values[0] = ldap_memrealloc(ldap_mods[i]->mod_values[0], sizeof(char) * (strlen(ldap_mods[i]->mod_values[0]) + strlen(newval) + 2));
+				ldap_mods[i]->mod_values[0] = ast_realloc(ldap_mods[i]->mod_values[0], sizeof(char) * (strlen(ldap_mods[i]->mod_values[0]) + strlen(newval) + 2));
 				strcat(ldap_mods[i]->mod_values[0], ";");
 				strcat(ldap_mods[i]->mod_values[0], newval);
 				mod_exists = 1;	
@@ -1264,12 +1264,12 @@
 		/* create new mod */
 		if (!mod_exists) {
 			mods_size++;
-			ldap_mods = ldap_memrealloc(ldap_mods, sizeof(LDAPMod *) * mods_size);
+			ldap_mods = ast_realloc(ldap_mods, sizeof(LDAPMod *) * mods_size);
 			ldap_mods[mods_size - 1] = NULL;
 			
-			ldap_mods[mods_size - 2] = ldap_memcalloc(1, sizeof(LDAPMod));
+			ldap_mods[mods_size - 2] = ast_calloc(1, sizeof(LDAPMod));
 
-			ldap_mods[mods_size - 2]->mod_type = ldap_memcalloc(sizeof(char), strlen(newparam) + 1);
+			ldap_mods[mods_size - 2]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1);
 			strcpy(ldap_mods[mods_size - 2]->mod_type, newparam);
 
 			if (strlen(newval) == 0) {
@@ -1277,8 +1277,8 @@
 			} else {
 				ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_REPLACE;
 
-				ldap_mods[mods_size - 2]->mod_values = ldap_memcalloc(sizeof(char *), 2);
-				ldap_mods[mods_size - 2]->mod_values[0] = ldap_memcalloc(sizeof(char), strlen(newval) + 1);
+				ldap_mods[mods_size - 2]->mod_values = ast_calloc(sizeof(char *), 2);
+				ldap_mods[mods_size - 2]->mod_values[0] = ast_calloc(sizeof(char), strlen(newval) + 1);
 				strcpy(ldap_mods[mods_size - 2]->mod_values[0], newval);
 			}
 		}
Index: res/res_format_attr_h264.c
===================================================================
--- res/res_format_attr_h264.c	(.../branches/11)	(revision 385989)
+++ res/res_format_attr_h264.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -41,14 +41,8 @@
 /*! \brief Value that indicates an attribute is actually unset */
 #define H264_ATTR_KEY_UNSET UINT8_MAX
 
-/*! \brief Maximum size for SPS / PPS values in sprop-parameter-sets attribute
- *   if you change this value then you must change H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT
- *   as well. */
+/*! \brief Maximum size for SPS / PPS values in sprop-parameter-sets attribute */
 #define H264_MAX_SPS_PPS_SIZE 16
-/*! \brief This is used when executing sscanf on buffers of H264_MAX_SPS_PPS_SIZE
- *   length. It must ALWAYS be a string literal representation of one less than
- *   H264_MAX_SPS_PPS_SIZE */
-#define H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "15"
 
 enum h264_attr_keys {
 	H264_ATTR_KEY_PROFILE_IDC,
@@ -117,8 +111,7 @@
 			format_attr->format_attr[H264_ATTR_KEY_PROFILE_IDC] = ((val2 >> 16) & 0xFF);
 			format_attr->format_attr[H264_ATTR_KEY_PROFILE_IOP] = ((val2 >> 8) & 0xFF);
 			format_attr->format_attr[H264_ATTR_KEY_LEVEL] = (val2 & 0xFF);
-		} else if (sscanf(attrib, "sprop-parameter-sets=%" H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "[^','],%" H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "s", sps, pps) == 2) {
-			/* XXX sprop-parameter-sets can actually be of unlimited length. This may need to be addressed later. */
+		} else if (sscanf(attrib, "sprop-parameter-sets=%[^','],%s", sps, pps) == 2) {
 			unsigned char spsdecoded[H264_MAX_SPS_PPS_SIZE] = { 0, }, ppsdecoded[H264_MAX_SPS_PPS_SIZE] = { 0, };
 			int i;
 
Index: res/res_timing_kqueue.c
===================================================================
--- res/res_timing_kqueue.c	(.../branches/11)	(revision 385989)
+++ res/res_timing_kqueue.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: res/res_timing_kqueue.c
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Date Author Id Revision Yoyo'
\ No newline at end of property
Index: res/res_rtp_asterisk.c
===================================================================
--- res/res_rtp_asterisk.c	(.../branches/11)	(revision 385989)
+++ res/res_rtp_asterisk.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -29,7 +29,6 @@
  */
 
 /*** MODULEINFO
-	<depend>uuid</depend>
 	<support_level>core</support_level>
  ***/
 
@@ -86,13 +85,33 @@
 
 #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
 
 #define DEFAULT_DTMF_TIMEOUT (150 * (8000 / 1000))	/*!< samples */
@@ -123,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 */
@@ -165,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
@@ -220,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;
@@ -263,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 */
@@ -296,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. */
@@ -314,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;
@@ -336,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 */
@@ -389,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);
@@ -1022,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,
@@ -1480,7 +1535,7 @@
 		rtp->passthrough = 0;
 	}
 
-	if ((*in & 0xC0) && res_srtp && srtp && res_srtp->unprotect(srtp, buf, &len, rtcp) < 0) {
+	if ((*in > 1) && res_srtp && srtp && res_srtp->unprotect(srtp, buf, &len, rtcp) < 0) {
 	   return -1;
 	}
 
@@ -1546,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)
 {
@@ -1792,6 +1865,9 @@
 	rtp->rekeyid = -1;
 #endif
 
+	gettimeofday(&rtp->start, NULL);
+	rtp->isactive = 1;
+
 	return 0;
 }
 
@@ -2160,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;
@@ -2172,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;
@@ -2221,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);
 	rtcpheader[2] = htonl(rtp->themssrc);
@@ -2231,13 +2307,14 @@
 	rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
 	rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
 
-	/*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos
-	  it can change mid call, and SDES can't) */
-	rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
-	rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
-	rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
-	len += 12;
 
+ 	start = &rtcpheader[len/4];
+ 	len +=8; /* SKip header for now */
+ 	len = add_sdes_bodypart(rtp, &rtcpheader[len/4], len, SDES_CNAME);
+ 	len = add_sdes_bodypart(rtp, &rtcpheader[len/4], len, SDES_END);
+ 	/* Now, add header when we know the actual length */
+ 	add_sdes_header(rtp, start, len);
+
 	ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
 
 	res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, &remote_address, &ice);
@@ -2269,15 +2346,16 @@
 }
 
 /*! \brief Send RTCP sender's report */
-static int ast_rtcp_write_sr(struct ast_rtp_instance *instance)
+static int ast_rtcp_write_sr(struct ast_rtp_instance *instance, int goodbye)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
 	int res;
-	int len = 0;
+	int len = 0;	/* Measured in chunks of four bytes */
+	int srlen = 0;
 	struct timeval now;
 	unsigned int now_lsw;
 	unsigned int now_msw;
-	unsigned int *rtcpheader;
+	unsigned int *rtcpheader, *start;
 	unsigned int lost;
 	unsigned int extended;
 	unsigned int expected;
@@ -2302,7 +2380,8 @@
 	}
 
 	gettimeofday(&now, NULL);
-	timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
+	timeval2ntp(now, &now_msw, &now_lsw); /* fill these ones in from utils.c*/
+	/* Set the header for sender's report */
 	rtcpheader = (unsigned int *)bdata;
 	rtcpheader[1] = htonl(rtp->ssrc);               /* Our SSRC */
 	rtcpheader[2] = htonl(now_msw);                 /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
@@ -2337,13 +2416,23 @@
 
 	rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
 
-	/* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */
-	/* it can change mid call, and SDES can't) */
-	rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
-	rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
-	rtcpheader[(len/4)+2] = htonl(0x01 << 24);                    /* Empty for the moment */
-	len += 12;
 
+ 	start = &rtcpheader[len/4];
+ 	srlen = len;
+ 	len +=8; /* SKip header for now */
+ 	len = add_sdes_bodypart(rtp, &rtcpheader[len/4], len, SDES_CNAME);
+ 	len = add_sdes_bodypart(rtp, &rtcpheader[len/4], len, SDES_END);
+ 	/* Now, add header when we know the actual length */
+ 	add_sdes_header(rtp, start, len - srlen);
+  
+ 	if (goodbye) {
+ 		/* An additional RTCP block */
+ 		rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_BYE << 16) | 1);
+ 		len += 4;
+ 		rtcpheader[len/4] = htonl(rtp->ssrc);               /* Our SSRC */
+ 		len += 4;
+ 	}
+ 
 	ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
 
 	res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, &remote_address, &ice);
@@ -2370,11 +2459,11 @@
 		ast_verbose("  Sent packets: %u\n", rtp->txcount);
 		ast_verbose("  Sent octets: %u\n", rtp->txoctetcount);
 		ast_verbose("  Report block:\n");
-		ast_verbose("  Fraction lost: %u\n", fraction);
-		ast_verbose("  Cumulative loss: %u\n", lost);
-		ast_verbose("  IA jitter: %.4f\n", rtp->rxjitter);
-		ast_verbose("  Their last SR: %u\n", rtp->rtcp->themrxlsr);
-		ast_verbose("  DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
+		ast_verbose("    Fraction lost (since last report): %u\n", fraction);
+		ast_verbose("    Cumulative loss: %u\n", lost);
+		ast_verbose("    IA jitter: %.4f\n", rtp->rxjitter);
+		ast_verbose("    Their last SR: %u\n", rtp->rtcp->themrxlsr);
+		ast_verbose("    Delay since last SR (DLSR): %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
 	}
 	manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To: %s\r\n"
 					    "OurSSRC: %u\r\n"
@@ -2417,9 +2506,9 @@
 	}
 
 	if (rtp->txcount > rtp->rtcp->lastsrtxcount) {
-		res = ast_rtcp_write_sr(instance);
+		res = ast_rtcp_write_sr(instance, 0);
 	} else {
-		res = ast_rtcp_write_rr(instance);
+		res = ast_rtcp_write_rr(instance, 0);
 	}
 
 	if (!res) {
@@ -2538,15 +2627,7 @@
 			rtp->txcount++;
 			rtp->txoctetcount += (res - hdrlen);
 
-			if (rtp->rtcp && rtp->rtcp->schedid < 1) {
-				ast_debug(1, "Starting RTCP transmission on RTP instance '%p'\n", 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");
-				}
-			}
+			ast_rtcp_schedule(instance);
 		}
 
 		update_address_with_ice_candidate(rtp, COMPONENT_RTP, &remote_address);
@@ -2608,6 +2689,12 @@
 	struct ast_format subclass;
 	int codec;
 
+	if (ast_test_flag(rtp, FLAG_HOLD)) {
+		/* This stream is on hold, just keep on happily and don't do anything */
+		ast_debug(1, "** Frame muted since we're on hold. \n");
+		return 0;
+	}
+
 	ast_rtp_instance_get_remote_address(instance, &remote_address);
 
 	/* If we don't actually know the remote address don't even bother doing anything */
@@ -2756,20 +2843,23 @@
 		d=-d;
 	rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
 
-	if (rtp->rtcp) {
-		if (rtp->rxjitter > rtp->rtcp->maxrxjitter)
-			rtp->rtcp->maxrxjitter = rtp->rxjitter;
-		if (rtp->rtcp->rxjitter_count == 1)
-			rtp->rtcp->minrxjitter = rtp->rxjitter;
-		if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
-			rtp->rtcp->minrxjitter = rtp->rxjitter;
+	if (!rtp->rtcp) {
+		return;
+	}
+	if (rtp->rxjitter > rtp->rtcp->maxrxjitter)
+		rtp->rtcp->maxrxjitter = rtp->rxjitter;
+	if (rtp->rtcp->rxjitter_count == 1) {
+		rtp->rtcp->minrxjitter = rtp->rxjitter;
+	}
+	if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter) {
+		rtp->rtcp->minrxjitter = rtp->rxjitter;
+	}
 
-		normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count);
-		rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count);
+	normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count);
+	rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count);
 
-		rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current;
-		rtp->rtcp->rxjitter_count++;
-	}
+	rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current;
+	rtp->rtcp->rxjitter_count++;
 }
 
 static struct ast_frame *create_dtmf_frame(struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
@@ -3066,8 +3156,10 @@
 	struct ast_sockaddr addr;
 	unsigned char rtcpdata[8192 + AST_FRIENDLY_OFFSET];
 	unsigned int *rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
-	int res, packetwords, position = 0;
 	struct ast_frame *f = &ast_null_frame;
+	int j, res, packetwords, position = 0;
+	char *sdes;
+	unsigned int sdeslength, sdestype;
 
 	/* Read in RTCP data from the socket */
 	if ((res = rtcp_recvfrom(instance, rtcpdata + AST_FRIENDLY_OFFSET,
@@ -3109,7 +3201,7 @@
 		return &ast_null_frame;
 	}
 
-	packetwords = res / 4;
+	packetwords = res / 4;	 /* Each RTCP segment is 32 bits */
 
 	if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
 		/* Send to whoever sent to us */
@@ -3121,8 +3213,15 @@
 		}
 	}
 
-	ast_debug(1, "Got RTCP report of %d bytes\n", res);
+	if (rtcp_debug_test_addr(&addr)) {
+		ast_debug(1, "Got RTCP report of %d bytes - %d messages\n", res, packetwords);
+	}
 
+	/* Process a compound packet 
+	   - A compound packet should start with a sender or receiver report. BYE can start as well
+		(seen in implementations) 
+	   -  Packet length should be a multiple of four bytes
+	*/
 	while (position < packetwords) {
 		int i, pt, rc;
 		unsigned int length, dlsr, lsr, msw, lsw, comp;
@@ -3130,24 +3229,33 @@
 		double rttsec, reported_jitter, reported_normdev_jitter_current, normdevrtt_current, reported_lost, reported_normdev_lost_current;
 		uint64_t rtt = 0;
 
-		i = position;
-		length = ntohl(rtcpheader[i]);
-		pt = (length & 0xff0000) >> 16;
-		rc = (length & 0x1f000000) >> 24;
-		length &= 0xffff;
+  		i = position;
+ 		if (rtcp_debug_test_addr(&addr)) {
+ 			ast_debug(3, "***** Debug - position = %d\n", position     );
+ 		}
+  		length = ntohl(rtcpheader[i]);
+ 		pt = (length & 0xff0000) >> 16;		/* Packet type */
+ 		rc = (length & 0x1f000000) >> 24;	/* Number of chunks, i.e. streams reported */
+  		length &= 0xffff;
+  
+  		if ((i + length) > packetwords) {
+ 			if (option_debug || rtpdebug) {
+ 				ast_log(LOG_WARNING, "RTCP Read too short - packet type %d position %d\n", pt, i);
+ 			}
+ 			return f;
+  		}
+  
 
-		if ((i + length) > packetwords) {
-			if (rtpdebug)
-				ast_debug(1, "RTCP Read too short\n");
-			return &ast_null_frame;
-		}
-
 		if (rtcp_debug_test_addr(&addr)) {
 			ast_verbose("\n\nGot RTCP from %s\n",
 				    ast_sockaddr_stringify(&addr));
 			ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
 			ast_verbose("Reception reports: %d\n", rc);
-			ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
+			ast_verbose("   SSRC of packet sender: %u (%x)", ntohl(rtcpheader[i + 1]), ntohl(rtcpheader[i + 1]));
+			ast_verbose("   (Position %d of %d)\n", i, packetwords);
+			if (rc == 0) {  
+				ast_verbose("   Empty - no reports! \n");
+			}
 		}
 
 		i += 2; /* Advance past header and ssrc */
@@ -3156,27 +3264,46 @@
 			continue;
 		}
 
+
+		if (rc == 0 && pt == RTCP_PT_RR) {	/* We're receiving a receiver report with no reports, which is ok */
+			position += (length + 1);
+			continue;
+		}
+		if (pt == RTCP_PT_SR) {
+			rtp->rtcp->rec_sr_count++;
+		} else if (pt == RTCP_PT_RR) {
+			rtp->rtcp->rec_rr_count++;
+		}
 		switch (pt) {
-		case RTCP_PT_SR:
-			gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
-			rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
-			rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
-			rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
+		case RTCP_PT_SR:	/* Sender's report - about what they have sent us */
+			if (rtcp_debug_test_addr(&addr)) {
+				ast_verbose("    - RTCP SR (sender report) from %s\n", ast_sockaddr_stringify(&rtp->rtcp->them));
+			}
+			/* Don't handle multiple reception reports (rc > 1) yet */
+			gettimeofday(&rtp->rtcp->rxlsr, NULL); /* To be able to populate the dlsr */
+			rtp->rtcp->spc = ntohl(rtcpheader[i + 3]);	/* Sender packet count */
+			rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);	/* Sender octet count */
 
+ 			rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
+     
+ 			if (rtcp_debug_test_addr(&addr)) {
+				ast_verbose("      NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
+				ast_verbose("      RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
+				ast_verbose("      SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
+				ast_verbose("      RC (number of reports) %d\n", rc);
+ 			}
+			i += 5;	/* Sender's info report is five bytes */
+ 			if (rc < 1)
+ 				break;
+
+		case RTCP_PT_RR:	/* Receiver report - data about what we have sent to them */
 			if (rtcp_debug_test_addr(&addr)) {
-				ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
-				ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
-				ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
+				ast_verbose("Received a RTCP RR (receiver report) from %s\n", ast_sockaddr_stringify(&rtp->rtcp->them));
 			}
-			i += 5;
-			if (rc < 1)
-				break;
-			/* Intentional fall through */
-		case RTCP_PT_RR:
-			/* Don't handle multiple reception reports (rc > 1) yet */
 			/* Calculate RTT per RFC */
 			gettimeofday(&now, NULL);
 			timeval2ntp(now, &msw, &lsw);
+			/* Get timing */ 
 			if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
 				comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
 				lsr = ntohl(rtcpheader[i + 4]);
@@ -3198,13 +3325,16 @@
 				if (comp - dlsr >= lsr) {
 					rtp->rtcp->accumulated_transit += rttsec;
 
-					if (rtp->rtcp->rtt_count == 0)
+					if (rtp->rtcp->rtt_count == 0) {
 						rtp->rtcp->minrtt = rttsec;
+					}
 
-					if (rtp->rtcp->maxrtt<rttsec)
+					if (rtp->rtcp->maxrtt<rttsec) {
 						rtp->rtcp->maxrtt = rttsec;
-					if (rtp->rtcp->minrtt>rttsec)
+					}
+					if (rtp->rtcp->minrtt > rttsec || rtp->rtcp->minrtt == 0) {
 						rtp->rtcp->minrtt = rttsec;
+					}
 
 					normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count);
 
@@ -3325,8 +3455,9 @@
 			}
 			break;
 		case RTCP_PT_FUR:
-			if (rtcp_debug_test_addr(&addr))
-				ast_verbose("Received an RTCP Fast Update Request\n");
+			if (rtcp_debug_test_addr(&addr)) {
+				ast_verbose("Received an RTCP Fast Update Request from %s\n", ast_sockaddr_stringify(&rtp->rtcp->them));
+			}
 			rtp->f.frametype = AST_FRAME_CONTROL;
 			rtp->f.subclass.integer = AST_CONTROL_VIDUPDATE;
 			rtp->f.datalen = 0;
@@ -3336,23 +3467,139 @@
 			f = &rtp->f;
 			break;
 		case RTCP_PT_SDES:
-			if (rtcp_debug_test_addr(&addr))
-				ast_verbose("Received an SDES from %s\n",
-					    ast_sockaddr_stringify(&rtp->rtcp->them));
+			/* SDES messages are divided into chunks, each one containing one or
+			   several items. Each chunk is for a different CSRC, so it is not really
+			   relevant in most cases of voip calls - unless you have an advanced
+			   mixer in the network that separates the different streams with CSRC 
+
+			   A chunk starts with SSRC/CSRC (four bytes), then SDES items 
+			   In the SDES message, there can be several items, ending with SDES_END
+			   The length of the all items is length - header 
+			   Chunk starts on a 32-bit boundary and needs padding by 0's
+		
+			   the "rc" variable contains the number of chunks 
+			   When we start, we're beyond the SSRC and starts with SDES items in the
+			   first chunk.
+			
+				an SDES item is one byte of type, one byte of length then data 
+				(no null termination). Text is UTF-8.
+				the last item is a zero (END) type with no length indication.
+			*/
+			
+			j = i * 4;
+			sdes = (char *) &rtcpheader[i];
+			if (rtcp_debug_test_addr(&addr)) {
+				ast_verbose("   Received an SDES from %s - Total length %d (%d bytes)\n", ast_sockaddr_stringify(&rtp->rtcp->them), length-i, ((length-i)*4) - 6);
+			}
+			while (j < length * 4) {
+				sdestype = (int) *sdes;
+				sdes++;
+				sdeslength = (int) *sdes;
+				sdes++;
+				if (rtcp_debug_test_addr(&addr)) {
+					ast_verbose(" --- SDES Type %u, Length %u Curj %d)\n", sdestype, sdeslength, j);
+				}
+				switch (sdestype) {
+				case SDES_CNAME:
+					if (!ast_strlen_zero(rtp->rtcp->theircname)) {
+						if (strncmp(rtp->rtcp->theircname, sdes, sdeslength)) {
+							ast_log(LOG_WARNING, "New RTP stream received (new RTCP CNAME for session. Old name: %s\n", rtp->rtcp->theircname);
+						}
+					}
+					strncpy(rtp->rtcp->theircname, sdes, sdeslength);
+					rtp->rtcp->theircname[sdeslength + 1] = '\0';
+					rtp->rtcp->theircnamelength = sdeslength;
+					if (rtcp_debug_test_addr(&addr)) {
+						ast_verbose(" --- SDES CNAME (utf8) %s\n", rtp->rtcp->theircname);
+					}
+					break;
+				case SDES_TOOL:
+					if (rtcp_debug_test_addr(&addr)) {
+						ast_verbose(" --- SDES TOOL \n");
+					}
+					break;
+				case SDES_NAME:
+					if (rtcp_debug_test_addr(&addr)) {
+						ast_verbose(" --- SDES NAME \n");
+					}
+					break;
+				case SDES_EMAIL:
+					if (rtcp_debug_test_addr(&addr)) {
+						ast_verbose(" --- SDES EMAIL \n");
+					}
+					break;
+				case SDES_PHONE:
+					if (rtcp_debug_test_addr(&addr)) {
+						ast_verbose(" --- SDES PHONE \n");
+					}
+					break;
+				case SDES_LOC:
+					if (rtcp_debug_test_addr(&addr)) {
+						ast_verbose(" --- SDES LOC \n");
+					}
+					break;
+				case SDES_NOTE:
+					if (rtcp_debug_test_addr(&addr)) {
+						ast_verbose(" --- SDES NOTE \n");
+					}
+					break;
+				case SDES_PRIV:
+					if (rtcp_debug_test_addr(&addr)) {
+						ast_verbose(" --- SDES PRIV \n");
+					}
+					break;
+				case SDES_END:
+					if (rtcp_debug_test_addr(&addr)) {
+						ast_verbose(" --- SDES END \n");
+					}
+					break;
+				case SDES_APSI:
+					if (rtcp_debug_test_addr(&addr)) {
+						ast_verbose(" --- SDES APSI \n");
+					}
+					break;
+				}
+				j += 2 + sdeslength;	/* Header (1 byte) + length */
+				sdes += sdeslength;
+				if (sdestype == SDES_END) {
+					break;	/* The while loop */
+				}
+			}
+
 			break;
-		case RTCP_PT_BYE:
-			if (rtcp_debug_test_addr(&addr))
-				ast_verbose("Received a BYE from %s\n",
-					    ast_sockaddr_stringify(&rtp->rtcp->them));
+		case RTCP_PT_NACK:
+			if (rtcp_debug_test_addr(&addr)) {
+				ast_verbose("   Received a RTCP NACK from %s\n", ast_sockaddr_stringify(&rtp->rtcp->them));
+			}
 			break;
+ 		case RTCP_PT_BYE:
+			if (rtcp_debug_test_addr(&addr)) {
+				ast_verbose("   Received a RTCP BYE from %s\n", ast_sockaddr_stringify(&rtp->rtcp->them));
+			}
+ 			break;
+		case RTCP_PT_XR:
+			if (rtcp_debug_test_addr(&addr)) {
+				ast_verbose("   Received a RTCP Extended Report (XR) packet from %s\n", ast_sockaddr_stringify(&rtp->rtcp->them));
+			}
+			break;
+		case RTCP_PT_APP:
+			if (rtcp_debug_test_addr(&addr)) {
+				ast_verbose("   Received a RTCP APP packet from %s\n", ast_sockaddr_stringify(&rtp->rtcp->them));
+			}
+			break;
+		case RTCP_PT_IJ:
+			if (rtcp_debug_test_addr(&addr)) {
+				ast_verbose("   Received a RTCP IJ from %s\n", ast_sockaddr_stringify(&rtp->rtcp->them));
+			}
+			break;
 		default:
-			ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s\n",
-				  pt, ast_sockaddr_stringify(&rtp->rtcp->them));
+			ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s\n", pt, ast_sockaddr_stringify(&rtp->rtcp->them));
 			break;
 		}
 		position += (length + 1);
-	}
+	}	/* While loop */
 
+	/* OEJ CHECK next line */
 	rtp->rtcp->rtcp_info = 1;
 
 	return f;
@@ -3367,6 +3614,10 @@
 	int reconstruct = ntohl(rtpheader[0]);
 	struct ast_sockaddr remote_address = { {0,} };
 	int ice;
+	struct timeval rxtime; 
+	unsigned int timestamp;
+	int rate;
+	unsigned int ms;
 
 	/* Get fields from packet */
 	payload = (reconstruct & 0x7f0000) >> 16;
@@ -3395,12 +3646,31 @@
 		ast_clear_flag(rtp, FLAG_NEED_MARKER_BIT);
 	}
 
+	/* Calculate timestamp for reception of the packet */
+	timestamp = ntohl(rtpheader[1]);
+	calc_rxstamp(&rxtime, rtp, timestamp, mark);
+
+	ast_format_copy(&bridged->lasttxformat, ast_rtp_codecs_get_payload_format(ast_rtp_instance_get_codecs(instance1), bridged_payload));
+	ast_format_copy(&rtp->lastrxformat, ast_rtp_codecs_get_payload_format(ast_rtp_instance_get_codecs(instance1), bridged_payload));
+
+ 	rate = rtp_get_rate(&rtp->lastrxformat) / 1000;
+
+	/* Now, calculate tx timestamp */
+	ms = calc_txstamp(rtp, &rxtime);
+	if (bridged_payload == AST_FRAME_VOICE) {
+		bridged->lastts = bridged->lastts + ms * rate;
+	} else if (bridged_payload == AST_FRAME_VIDEO) {
+		bridged->lastts = bridged->lastts + ms * 90;
+		/* This is not exact, but a best effort example that can be improved */
+	}
+
 	/* Reconstruct part of the packet */
 	reconstruct &= 0xFF80FFFF;
 	reconstruct |= (bridged_payload << 16);
 	reconstruct |= (mark << 23);
 	rtpheader[0] = htonl(reconstruct);
 
+
 	ast_rtp_instance_get_remote_address(instance1, &remote_address);
 
 	if (ast_sockaddr_isnull(&remote_address)) {
@@ -3428,6 +3698,9 @@
 		return 0;
 	}
 
+	bridged->txcount++;
+	bridged->txoctetcount += (res - hdrlen);
+
 	update_address_with_ice_candidate(rtp, COMPONENT_RTP, &remote_address);
 
 	if (rtp_debug_test_addr(&remote_address)) {
@@ -3483,7 +3756,7 @@
 
 	/* Make sure the data that was read in is actually enough to make up an RTP packet */
 	if (res < hdrlen) {
-		ast_log(LOG_WARNING, "RTP Read too short\n");
+		ast_log(LOG_WARNING, "RTP Read too short (%d expecting %d)\n", res, hdrlen);
 		return &ast_null_frame;
 	}
 
@@ -3573,10 +3846,6 @@
 		}
 	}
 
-	/* If we are directly bridged to another instance send the audio directly out */
-	if (ast_rtp_instance_get_bridged(instance) && !bridge_p2p_rtp_write(instance, rtpheader, res, hdrlen)) {
-		return &ast_null_frame;
-	}
 
 	/* If the version is not what we expected by this point then just drop the packet */
 	if (version != 2) {
@@ -3617,6 +3886,15 @@
 
 	rtp->rxssrc = ssrc;
 
+	/* Schedule RTCP report transmissions if possible */
+	ast_rtcp_schedule(instance);
+
+	/* This needs to be after RTCP calculations to get more RTCP data */
+	/* If we are directly bridged to another instance send the audio directly out */
+	if (ast_rtp_instance_get_bridged(instance) && !bridge_p2p_rtp_write(instance, rtpheader, res, hdrlen)) {
+		return &ast_null_frame;
+	}
+
 	/* Remove any padding bytes that may be present */
 	if (padding) {
 		res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
@@ -4065,6 +4343,45 @@
 	AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_SSRC, -1, stats->local_ssrc, rtp->ssrc);
 	AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_SSRC, -1, stats->remote_ssrc, rtp->themssrc);
 
+	AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_START, -1, stats->start, rtp->start);
+	if (stat == AST_RTP_INSTANCE_STAT_IP || stat == AST_RTP_INSTANCE_STAT_ALL) {
+		memcpy(&stats->them, &rtp->rtcp->them, sizeof(stats->them));
+	}
+	if (stat == AST_RTP_INSTANCE_STAT_LOCAL_CNAME || stat == AST_RTP_INSTANCE_STAT_ALL) {
+		memcpy(&stats->ourcname, &rtp->rtcp->ourcname, rtp->rtcp->ourcnamelength);	/* UTF8 safe */
+		stats->ourcnamelength = rtp->rtcp->ourcnamelength;
+	}
+	if (stat == AST_RTP_INSTANCE_STAT_REMOTE_CNAME || stat == AST_RTP_INSTANCE_STAT_ALL) {
+		memcpy(&stats->theircname, &rtp->rtcp->theircname, rtp->rtcp->theircnamelength);	/* UTF8 safe */
+		stats->theircnamelength = rtp->rtcp->theircnamelength;
+	}
+
+	/* To fix */
+	stats->readcost = rtp->rtcp->readcost;
+        stats->writecost = rtp->rtcp->writecost;
+	stats->lasttxformat = rtp->lasttxformat;
+	stats->lastrxformat = rtp->lastrxformat;
+	if (!ast_strlen_zero(rtp->rtcp->readtranslator)) {
+		ast_copy_string(stats->readtranslator, rtp->rtcp->readtranslator, sizeof(stats->readtranslator));
+	}
+	if (!ast_strlen_zero(rtp->rtcp->writetranslator)) {
+		ast_copy_string(stats->writetranslator, rtp->rtcp->writetranslator, sizeof(stats->writetranslator));
+	}
+	if (!ast_strlen_zero(rtp->rtcp->readtranslator)) {
+		ast_copy_string(stats->readtranslator, rtp->rtcp->readtranslator, sizeof(stats->readtranslator));
+	}
+	if (!ast_strlen_zero(rtp->rtcp->channel)) {
+		ast_copy_string(stats->channel, rtp->rtcp->channel, sizeof(stats->channel));
+	}
+	if (!ast_strlen_zero(rtp->rtcp->bridgedchannel)) {
+		ast_copy_string(stats->bridgedchannel, rtp->rtcp->bridgedchannel, sizeof(stats->bridgedchannel));
+	}
+	if (!ast_strlen_zero(rtp->rtcp->uniqueid)) {
+		ast_copy_string(stats->uniqueid, rtp->rtcp->uniqueid, sizeof(stats->uniqueid));
+	}
+	if (!ast_strlen_zero(rtp->rtcp->bridgeduniqueid)) {
+		ast_copy_string(stats->bridgeduniqueid, rtp->rtcp->bridgeduniqueid, sizeof(stats->bridgeduniqueid));
+	}
 	return 0;
 }
 
@@ -4094,11 +4411,36 @@
 	ast_sockaddr_from_sin(suggestion, &suggestion_tmp);
 }
 
+/* \brief Put stream on/off hold, mute outbound RTP but keep
+	RTP keepalives and RTCP going
+ */
+static void ast_rtp_hold(struct ast_rtp_instance *instance, int status)
+{
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+	if (status) {
+		ast_debug(3, "##### HOLDING RTCP, Have a nice silent day \n");
+		ast_set_flag(rtp, FLAG_HOLD);
+	} else {
+		ast_debug(3, "##### UNHOLDING RTCP, You will get audio now. \n");
+		ast_clear_flag(rtp, FLAG_HOLD);
+	}
+}
+
+/*! \brief STOP the media streams, END the session. 
+	Note: This is not hold. This is shutting down all the fun.
+*/
 static void ast_rtp_stop(struct ast_rtp_instance *instance)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
 	struct ast_sockaddr addr = { {0,} };
 
+ 	ast_debug(3, "##### Stopping RTP, Sending good bye and cleaning up.\n");
+ 
+ 	/* Send RTCP goodbye packet */
+ 	if (rtp->isactive && rtp->rtcp) {
+ 		ast_rtcp_write_sr(instance, 1);
+ 	}
+
 #ifdef HAVE_OPENSSL_SRTP
 	AST_SCHED_DEL_UNREF(rtp->sched, rtp->rekeyid, ao2_ref(instance, -1));
 #endif
@@ -4123,6 +4465,7 @@
 	}
 
 	ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
+	rtp->isactive = 0;
 }
 
 static int ast_rtp_qos_set(struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
@@ -4132,6 +4475,91 @@
 	return ast_set_qos(rtp->s, tos, cos, desc);
 }
 
+
+/*! \brief set RTP cname used to describe session in RTCP sdes messages */
+void ast_rtcp_setcname(struct ast_rtp_instance *instance, const char *cname, size_t length)
+{
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+
+	if (!rtp || !rtp->rtcp) {
+		return;
+	}
+	if (length > 255) {
+		length=255;
+	}
+	ast_copy_string(rtp->rtcp->ourcname, cname, length+1);
+	rtp->rtcp->ourcnamelength = length;
+	if (option_debug > 3) {
+		ast_log(LOG_DEBUG, "--- Copied CNAME %s to RTCP structure (length %d)\n", cname, (int) length);
+	}
+}
+
+/*! \brief set the name of the bridged channel
+
+At the time when we write the report there might not be a bridge, so we need
+to store this so we can correlate the reports. If a channel changes bridge,
+it can be reset by first setting it to an empty string, then setting to 
+a new name 
+*/
+void ast_rtcp_set_bridged(struct ast_rtp_instance *instance, const char *channel, const char *uniqueid, const char *bridgedchan, const char *bridgeduniqueid)
+{
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+
+	if (!rtp) {		/* For some reason, there's no RTP */
+		ast_debug(1, "??????????????? NO RTP \n");
+		return;
+	}
+	if (!rtp->rtcp) {	/* No RTCP? Strange */
+		ast_debug(1, "??????????????? NO RTCP \n");
+		return;
+	}
+	/* If we already have data, don't replace it. 
+		NOTE: Should we replace it at a masquerade or something? Hmm.
+	*/
+	if (!ast_strlen_zero(channel) && !rtp->rtcp->channel[0]) {
+		ast_debug(1, "!!!!!! Setting channel name to %s\n", channel);
+		ast_copy_string(rtp->rtcp->channel, channel, sizeof(rtp->rtcp->channel));
+	}
+	if (!ast_strlen_zero(uniqueid) && !rtp->rtcp->uniqueid[0]) {
+		ast_debug(1, "!!!!!! Setting unique id to %s\n", uniqueid);
+		ast_copy_string(rtp->rtcp->uniqueid, uniqueid, sizeof(rtp->rtcp->uniqueid));
+	}
+	if (!ast_strlen_zero(bridgedchan)) {
+		ast_debug(1, "!!!!!! Setting bridged channel name to %s\n", bridgedchan);
+		ast_copy_string(rtp->rtcp->bridgedchannel, bridgedchan, sizeof(rtp->rtcp->bridgedchannel));
+	} else {
+		if(rtp->rtcp->bridgedchannel[0] != '\0') {
+			ast_debug(1, "!!!!!! Keeping bridged channel name %s\n", rtp->rtcp->bridgedchannel);
+		}
+		//rtp->rtcp->bridgedchan[0] = '\0';
+	}
+	if (!ast_strlen_zero(bridgeduniqueid)) {
+		ast_debug(1, "!!!!!! Setting bridged unique id to %s\n", bridgeduniqueid);
+		ast_copy_string(rtp->rtcp->bridgeduniqueid, bridgeduniqueid, sizeof(rtp->rtcp->bridgeduniqueid));
+	} else {
+		if(rtp->rtcp->bridgeduniqueid[0] != '\0') {
+			ast_debug(1, "!!!!!! Keeping bridged unique id \n");
+		}
+	}
+}
+
+
+/*! \brief Set the transcoding variables for the QoS reports */
+void ast_rtcp_set_translator(struct ast_rtp_instance *instance, const char *readtranslator, const int readcost, const char *writetranslator, const int writecost)
+{
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+	if (!rtp || !rtp->rtcp) {
+		return;
+	}
+	ast_copy_string(rtp->rtcp->readtranslator, S_OR(readtranslator,""), sizeof(rtp->rtcp->readtranslator));
+	ast_copy_string(rtp->rtcp->writetranslator, S_OR(writetranslator,""), sizeof(rtp->rtcp->writetranslator));
+	rtp->rtcp->readcost = readcost;
+	rtp->rtcp->writecost = writecost;
+	
+}
+
+
+
 /*! \brief generate comfort noice (CNG) */
 static int ast_rtp_sendcng(struct ast_rtp_instance *instance, int level)
 {
@@ -4199,6 +4627,120 @@
 }
 #endif
 
+/*! \brief Check if rtp stream is active */
+static int ast_rtp_isactive(struct ast_rtp_instance *instance)
+{
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+	return rtp->isactive ? 0 : 1;
+}
+
+/*! \brief Basically add SSRC */
+static int add_sdes_header(struct ast_rtp *rtp, unsigned int *rtcp_packet, int len)
+{
+	/* 2 is version, 1 is number of chunks, then RTCP packet type (SDES) and length */
+	*rtcp_packet = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | ((len/4)-1));
+
+	rtcp_packet++;	/* Move 32 bits ahead for the header */
+	*rtcp_packet = htonl(rtp->ssrc);               /* Our SSRC */
+	rtcp_packet ++;
+
+	/* Header + SSRC */
+	return len + 8;
+}
+
+static int add_sdes_bodypart(struct ast_rtp *rtp, unsigned int *rtcp_packet, int len, int type)
+{
+	int cnamelen;
+	int sdeslen = 0;
+	char *sdes;
+
+	sdes = (char *) rtcp_packet;
+	switch (type) {
+	case SDES_CNAME:
+		cnamelen = (int) rtp->rtcp->ourcnamelength;
+
+		*sdes = SDES_CNAME;
+		sdes++;
+		*sdes = (char) cnamelen;
+		sdes++;
+		strncpy(sdes, rtp->rtcp->ourcname, cnamelen);	/* NO terminating 0 */
+
+		/* THere must be a multiple of four bytes in the packet */
+		sdeslen = cnamelen;
+		break;
+	case SDES_END:
+		*sdes = SDES_END;
+		sdes++;
+		*sdes = (char) 0;
+		sdes++;
+		sdeslen = 2;
+	}
+	len += sdeslen + (sdeslen % 4 == 0 ? 0 : 4 - (sdeslen % 4)) ;
+
+	return len;
+}
+
+/*! \brief Send emtpy RTCP receiver's report and SDES message 
+ 	Mainly used to open NAT sessions  */
+static int ast_rtcp_write_empty_frame(struct ast_rtp_instance *instance)
+{
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+	char bdata[512];
+	unsigned int *rtcpheader, *start;
+	int fd, len, res;
+
+	if (!rtp || !rtp->rtcp) {
+		return 0;
+	} 
+	ast_debug(1,  "************ ---- About to send empty RTCP packet\n");
+	fd = rtp->rtcp->s;
+	
+	if (fd == -1) {
+		ast_debug(1, "--- No file descriptor to use \n");
+	}
+	
+	if (!ast_sockaddr_isnull(&rtp->rtcp->them)) { /* This'll stop rtcp for this rtp session */
+		ast_verbose("RTCP SR transmission error, rtcp halted\n");
+		AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+		return 0;
+	}
+	if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
+		ast_debug(1,  "---- About to send empty RTCP packet\n");
+	}
+	rtcpheader = (unsigned int *)bdata;
+	/* Add a RR header with no reports (chunks = 0) - The RFC says that it's always needed 
+		first in a compound packet.
+	 */
+	rtcpheader[0] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_RR << 16) | 1);
+	rtcpheader[1] = htonl(rtp->ssrc);
+	len = 8;
+	start = &rtcpheader[len/4];
+	len +=8; /* SKip header for now */
+	len = add_sdes_bodypart(rtp, &rtcpheader[len/4], len, SDES_CNAME);
+	len = add_sdes_bodypart(rtp, &rtcpheader[len/4], len, SDES_END);
+	/* Now, add header when we know the actual length */
+	add_sdes_header(rtp, start, len);
+
+	res = sendto(fd, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
+
+	if (res < 0) {
+		ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
+		/* Remove the scheduler */
+		AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+		return 0;
+	}
+
+	rtp->rtcp->rr_count++;
+
+	if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
+		ast_verbose("\n* Sending Empty RTCP RR to %s  Our SSRC: %u\n",
+			ast_sockaddr_stringify(&rtp->rtcp->them),
+			rtp->ssrc);
+	}
+
+	return res;
+}
+
 static char *rtp_do_debug_ip(struct ast_cli_args *a)
 {
 	char *arg = ast_strdupa(a->argv[4]);
@@ -4210,8 +4752,7 @@
 		return CLI_FAILURE;
 	}
 	rtpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
-	ast_cli(a->fd, "RTP Debugging Enabled for address: %s\n",
-		ast_sockaddr_stringify(&rtpdebugaddr));
+	ast_cli(a->fd, "RTP Debugging Enabled for address: %s\n", ast_sockaddr_stringify(&rtpdebugaddr));
 	rtpdebug = 1;
 	return CLI_SUCCESS;
 }
Index: res/res_mutestream.c
===================================================================
--- res/res_mutestream.c	(.../branches/11)	(revision 385989)
+++ res/res_mutestream.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -35,7 +35,7 @@
 
 #include "asterisk.h"
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 89545 $")
 
 #include "asterisk/options.h"
 #include "asterisk/logger.h"

Property changes on: res/res_mutestream.c
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+"Author Date Id Revision"
\ No newline at end of property
Index: res/res_xmpp.c
===================================================================
--- res/res_xmpp.c	(.../branches/11)	(revision 385989)
+++ res/res_xmpp.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -700,10 +700,10 @@
 /*! \brief Comparator function for XMPP resource */
 static int xmpp_resource_cmp(void *obj, void *arg, int flags)
 {
-	struct ast_xmpp_resource *resource1 = obj;
+	struct ast_xmpp_resource *resource1 = obj, *resource2 = arg;
 	const char *resource = arg;
 
-	return !strcmp(resource1->resource, resource) ? CMP_MATCH | CMP_STOP : 0;
+	return !strcmp(resource1->resource, flags & OBJ_KEY ? resource : resource2->resource) ? CMP_MATCH | CMP_STOP : 0;
 }
 
 /*! \brief Destructor callback function for XMPP buddy */
@@ -1328,15 +1328,14 @@
 		return IKS_FILTER_EAT;
 	}
 	if (!strcasecmp(iks_name(item_content), "state")) {
-		if ((cachable_str = iks_find_attrib(item_content, "cachable"))) {
+		device_state = iks_find_cdata(item, "state");
+		if ((cachable_str = iks_find_cdata(item, "cachable"))) {
 			sscanf(cachable_str, "%30d", &cachable);
 		}
-		device_state = iks_find_cdata(item, "state");
 		if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE,
 					    AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_STATE,
 					    AST_EVENT_IE_PLTYPE_UINT, ast_devstate_val(device_state), AST_EVENT_IE_EID,
 					    AST_EVENT_IE_PLTYPE_RAW, &pubsub_eid, sizeof(pubsub_eid),
-					    AST_EVENT_IE_CACHABLE, AST_EVENT_IE_PLTYPE_UINT, cachable,
 					    AST_EVENT_IE_END))) {
 			return IKS_FILTER_EAT;
 		}
@@ -1546,7 +1545,7 @@
 		return -1;
 	}
 
-	if (ast_strlen_zero(jid.resource) || !(resource = ao2_callback(buddy->resources, 0, xmpp_resource_cmp, jid.resource))) {
+	if (ast_strlen_zero(jid.resource) || !(resource = ao2_find(buddy->resources, jid.resource, OBJ_KEY))) {
 		resource = ao2_callback(buddy->resources, OBJ_NODATA, xmpp_resource_immediate, NULL);
 	}
 
@@ -1617,7 +1616,7 @@
 		return -1;
 	}
 
-	if (ast_strlen_zero(jid.resource) || !(resource = ao2_callback(buddy->resources, 0, xmpp_resource_cmp, jid.resource))) {
+	if (ast_strlen_zero(jid.resource) || !(resource = ao2_find(buddy->resources, jid.resource, OBJ_KEY))) {
 		resource = ao2_callback(buddy->resources, OBJ_NODATA, xmpp_resource_immediate, NULL);
 	}
 
@@ -2345,7 +2344,7 @@
 		return IKS_FILTER_EAT;
 	}
 
-	if (!(resource = ao2_callback(buddy->resources, 0, xmpp_resource_cmp, pak->from->resource))) {
+	if (!(resource = ao2_find(buddy->resources, pak->from->resource, OBJ_KEY))) {
 		ao2_ref(buddy, -1);
 		return IKS_FILTER_EAT;
 	}
@@ -3138,7 +3137,7 @@
 
 	ao2_lock(buddy->resources);
 
-	if (!(resource = ao2_callback(buddy->resources, OBJ_NOLOCK, xmpp_resource_cmp, pak->from->resource))) {
+	if (!(resource = ao2_find(buddy->resources, pak->from->resource, OBJ_KEY | OBJ_NOLOCK))) {
 		/* Only create the new resource if it is not going away - in reality this should not happen */
 		if (status != STATUS_DISAPPEAR) {
 			if (!(resource = ao2_alloc(sizeof(*resource), xmpp_resource_destructor))) {
@@ -3637,8 +3636,8 @@
 			cfg->client->jid = iks_id_new(cfg->client->stack, cfg->user);
 		}
 
-		if (!cfg->client->jid || ast_strlen_zero(cfg->client->jid->user)) {
-			ast_log(LOG_ERROR, "Jabber identity '%s' could not be created for client '%s' - client not active\n", cfg->user, cfg->name);
+		if (!cfg->client->jid) {
+			ast_log(LOG_ERROR, "Jabber identity could not be created for client '%s' - client not active\n", cfg->name);
 			return -1;
 		}
 
Index: res/res_jabber.c
===================================================================
--- res/res_jabber.c	(.../branches/11)	(revision 385989)
+++ res/res_jabber.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -3339,15 +3339,14 @@
 		return IKS_FILTER_EAT;
 	}
 	if (!strcasecmp(iks_name(item_content), "state")) {
-		if ((cachable_str = iks_find_attrib(item_content, "cachable"))) {
+		device_state = iks_find_cdata(item, "state");
+		if ((cachable_str = iks_find_cdata(item, "cachable"))) {
 			sscanf(cachable_str, "%30d", &cachable);
 		}
-		device_state = iks_find_cdata(item, "state");
 		if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE,
 					    AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_STATE,
 					    AST_EVENT_IE_PLTYPE_UINT, ast_devstate_val(device_state), AST_EVENT_IE_EID,
 					    AST_EVENT_IE_PLTYPE_RAW, &pubsub_eid, sizeof(pubsub_eid),
-					    AST_EVENT_IE_CACHABLE, AST_EVENT_IE_PLTYPE_UINT, cachable,
 					    AST_EVENT_IE_END))) {
 			return IKS_FILTER_EAT;
 		}
Index: res/res_config_curl.c
===================================================================
--- res/res_config_curl.c	(.../branches/11)	(revision 385989)
+++ res/res_config_curl.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -463,7 +463,7 @@
 {
 	struct ast_str *query, *buffer;
 	char *elm, field[256];
-	int type, size, i = 0;
+	int type, size;
 
 	if (!ast_custom_function_find("CURL")) {
 		ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
@@ -484,9 +484,7 @@
 		type = va_arg(ap, require_type);
 		size = va_arg(ap, int);
 		ast_uri_encode(elm, field, sizeof(field), ast_uri_http);
-		ast_str_append(&query, 0, "%s%s=%s%%3A%d",
-			i > 0 ? "&" : "",
-			field,
+		ast_str_append(&query, 0, "%s=%s%%3A%d", field,
 			type == RQ_CHAR ? "char" :
 			type == RQ_INTEGER1 ? "integer1" :
 			type == RQ_UINTEGER1 ? "uinteger1" :
@@ -502,7 +500,6 @@
 			type == RQ_DATETIME ? "datetime" :
 			type == RQ_FLOAT ? "float" :
 			"unknown", size);
-		i++;
 	}
 
 	ast_str_append(&query, 0, ")}");
Index: codecs/codec_resample.c
===================================================================
--- codecs/codec_resample.c	(.../branches/11)	(revision 385989)
+++ codecs/codec_resample.c	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -113,7 +113,7 @@
 	int res = 0;
 	int x, y, idx = 0;
 
-	trans_size = ARRAY_LEN(id_list) * (ARRAY_LEN(id_list) - 1);
+	trans_size = ARRAY_LEN(id_list) * ARRAY_LEN(id_list);
 	if (!(translators = ast_calloc(1, sizeof(struct ast_translator) * trans_size))) {
 		return AST_MODULE_LOAD_FAILURE;
 	}
Index: codecs/Makefile
===================================================================
--- codecs/Makefile	(.../branches/11)	(revision 385989)
+++ codecs/Makefile	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -53,8 +53,8 @@
 	for dir in $(SUB_DIRS); do \
 		$(MAKE) -C $$dir clean; \
 	done
-	rm -f g722/*.[oai]
-	rm -f speex/*.[oai]
+	rm -f g722/*.[oa]
+	rm -f speex/*.[oa]
 
 .PHONY: $(SUB_DIRS)
 
Index: contrib/realtime/postgresql/realtime.sql
===================================================================
--- contrib/realtime/postgresql/realtime.sql	(.../branches/11)	(revision 385989)
+++ contrib/realtime/postgresql/realtime.sql	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -39,7 +39,7 @@
 callerid character varying(80),
 canreinvite character varying(3) DEFAULT 'yes',
 context character varying(80),
-defaultip character varying(45),
+defaultip character varying(15),
 dtmfmode character varying(7),
 fromuser character varying(80),
 fromdomain character varying(80),
Index: contrib/realtime/mysql/voicemail_data.sql
===================================================================
--- contrib/realtime/mysql/voicemail_data.sql	(.../branches/11)	(revision 385989)
+++ contrib/realtime/mysql/voicemail_data.sql	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: contrib/realtime/mysql/voicemail_data.sql
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Date Author Id Revision Yoyo'
\ No newline at end of property
Index: contrib/realtime/mysql/musiconhold.sql
===================================================================
--- contrib/realtime/mysql/musiconhold.sql	(.../branches/11)	(revision 385989)
+++ contrib/realtime/mysql/musiconhold.sql	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: contrib/realtime/mysql/musiconhold.sql
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Date Author Id Revision Yoyo'
\ No newline at end of property
Index: contrib/realtime/mysql/queue_log.sql
===================================================================
--- contrib/realtime/mysql/queue_log.sql	(.../branches/11)	(revision 385989)
+++ contrib/realtime/mysql/queue_log.sql	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: contrib/realtime/mysql/queue_log.sql
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Date Author Id Revision Yoyo'
\ No newline at end of property
Index: contrib/realtime/mysql/sippeers.sql
===================================================================
--- contrib/realtime/mysql/sippeers.sql	(.../branches/11)	(revision 385989)
+++ contrib/realtime/mysql/sippeers.sql	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)
@@ -5,19 +5,19 @@
 CREATE TABLE IF NOT EXISTS `sippeers` (
       `id` int(11) NOT NULL AUTO_INCREMENT,
       `name` varchar(10) NOT NULL,
-      `ipaddr` varchar(45) DEFAULT NULL,
+      `ipaddr` varchar(15) DEFAULT NULL,
       `port` int(5) DEFAULT NULL,
       `regseconds` int(11) DEFAULT NULL,
       `defaultuser` varchar(10) DEFAULT NULL,
-      `fullcontact` varchar(80) DEFAULT NULL,
+      `fullcontact` varchar(35) DEFAULT NULL,
       `regserver` varchar(20) DEFAULT NULL,
       `useragent` varchar(20) DEFAULT NULL,
       `lastms` int(11) DEFAULT NULL,
       `host` varchar(40) DEFAULT NULL,
       `type` enum('friend','user','peer') DEFAULT NULL,
       `context` varchar(40) DEFAULT NULL,
-      `permit` varchar(95) DEFAULT NULL,
-      `deny` varchar(95) DEFAULT NULL,
+      `permit` varchar(40) DEFAULT NULL,
+      `deny` varchar(40) DEFAULT NULL,
       `secret` varchar(40) DEFAULT NULL,
       `md5secret` varchar(40) DEFAULT NULL,
       `remotesecret` varchar(40) DEFAULT NULL,
@@ -56,7 +56,7 @@
       `fromdomain` varchar(40) DEFAULT NULL,
       `fromuser` varchar(40) DEFAULT NULL,
       `qualify` varchar(40) DEFAULT NULL,
-      `defaultip` varchar(45) DEFAULT NULL,
+      `defaultip` varchar(40) DEFAULT NULL,
       `rtptimeout` int(11) DEFAULT NULL,
       `rtpholdtimeout` int(11) DEFAULT NULL,
       `sendrpid` enum('yes','no') DEFAULT NULL,
@@ -66,8 +66,8 @@
       `timerb` int(11) DEFAULT NULL,
       `qualifyfreq` int(11) DEFAULT NULL,
       `constantssrc` enum('yes','no') DEFAULT NULL,
-      `contactpermit` varchar(95) DEFAULT NULL,
-      `contactdeny` varchar(95) DEFAULT NULL,
+      `contactpermit` varchar(40) DEFAULT NULL,
+      `contactdeny` varchar(40) DEFAULT NULL,
       `usereqphone` enum('yes','no') DEFAULT NULL,
       `textsupport` enum('yes','no') DEFAULT NULL,
       `faxdetect` enum('yes','no') DEFAULT NULL,
Index: contrib/realtime/mysql/voicemail_messages.sql
===================================================================
--- contrib/realtime/mysql/voicemail_messages.sql	(.../branches/11)	(revision 385989)
+++ contrib/realtime/mysql/voicemail_messages.sql	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: contrib/realtime/mysql/voicemail_messages.sql
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Date Author Id Revision Yoyo'
\ No newline at end of property
Index: BSDmakefile
===================================================================
--- BSDmakefile	(.../branches/11)	(revision 385989)
+++ BSDmakefile	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: BSDmakefile
___________________________________________________________________
Modified: svn:keywords
## -1 +1 ##
-Author Date Id Revision
+'Date Author Id Revision Yoyo'
\ No newline at end of property
Index: .
===================================================================
--- .	(.../branches/11)	(revision 385989)
+++ .	(.../team/oej/pinefrog-rtcp-11)	(revision 385989)

Property changes on: .
___________________________________________________________________
Modified: branch-1.8-blocked
## -1 +1 ##
-/branches/1.8:379091,384779,385008
+/branches/1.8:379091
\ No newline at end of property
Modified: branch-1.8-merged
## -1 +1 ##
-/branches/1.8:1-378147,378164,378356,378375,378427,378455-378456,378486,378514,378554,378591,378733,378776,378933,378967,379001,379145,379178,379226,379276,379310,379342,379392,379547,379608,379718,379825,379885,379963,380210,380254,380297,380347,380364,380451,380458,380520,380572,380611,380696,380853,380973,381216,381281,381364,381466,381668,381770,381847,381916,381939,381975,382021,382087,382107,382110,382171,382227,382233,382409,382513,382847,382939,382942,383061,383120,383124,383165,383340,383460,383667,383796,383835,383839,383863,384048,384118,384162,384325,384410,384544,384640,384685,385047,385170,385190,385402,385429,385551,385593,385633,385636,385683,385745,385916
+/branches/1.8:1-378147,378164,378356,378375,378427,378455-378456,378486,378514,378554,378591,378733,378776,378933,378967,379001,379145,379178,379226,379276,379310,379342,379392,379547,379608,379718,379825,379885,379963,380210,380254,380297,380347,380364,380451,380458,380520,380572,380611,380696,380853,380973,381216,381281,381364,381466,381668,381770,381847,381916,381939,381975,382021,382087,382107,382110,382171,382227,382233,382409,382513
\ No newline at end of property
Added: svnmerge-integrated
## -0,0 +1 ##
+/branches/11:1-382828
\ No newline at end of property
Added: automerge-email
## -0,0 +1 ##
+oej@edvina.net
\ No newline at end of property
