[svn-commits] file: branch file/rtp_engine r129106 - in /team/file/rtp_engine: channels/ in...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Jul 8 12:34:44 CDT 2008


Author: file
Date: Tue Jul  8 12:34:43 2008
New Revision: 129106

URL: http://svn.digium.com/view/asterisk?view=rev&rev=129106
Log:
Eep! Commit stuff so far. This includes some API changes to the RTP engine stuff plus about half of the changes required for chan_sip, and the basic core of the RTP stack converted over.

Modified:
    team/file/rtp_engine/channels/chan_sip.c
    team/file/rtp_engine/include/asterisk/rtp_engine.h
    team/file/rtp_engine/main/rtp_engine.c
    team/file/rtp_engine/res/res_rtp_asterisk.c

Modified: team/file/rtp_engine/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/file/rtp_engine/channels/chan_sip.c?view=diff&rev=129106&r1=129105&r2=129106
==============================================================================
--- team/file/rtp_engine/channels/chan_sip.c (original)
+++ team/file/rtp_engine/channels/chan_sip.c Tue Jul  8 12:34:43 2008
@@ -156,7 +156,7 @@
 #include "asterisk/pbx.h"
 #include "asterisk/sched.h"
 #include "asterisk/io.h"
-#include "asterisk/rtp.h"
+#include "asterisk/rtp_engine.h"
 #include "asterisk/udptl.h"
 #include "asterisk/acl.h"
 #include "asterisk/manager.h"
@@ -1357,9 +1357,9 @@
 	struct sip_peer *relatedpeer;		/*!< If this dialog is related to a peer, which one 
 							Used in peerpoke, mwi subscriptions */
 	struct sip_registry *registry;		/*!< If this is a REGISTER dialog, to which registry */
-	struct ast_rtp *rtp;			/*!< RTP Session */
-	struct ast_rtp *vrtp;			/*!< Video RTP session */
-	struct ast_rtp *trtp;			/*!< Text RTP session */
+	struct ast_rtp_instance *rtp;			/*!< RTP Session */
+	struct ast_rtp_instance *vrtp;			/*!< Video RTP session */
+	struct ast_rtp_instance *trtp;			/*!< Text RTP session */
 	struct sip_pkt *packets;		/*!< Packets scheduled for re-transmission */
 	struct sip_history_head *history;	/*!< History of this SIP dialog */
 	size_t history_entries;			/*!< Number of entires in the history */
@@ -2144,14 +2144,6 @@
 static int handle_response_register(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
 static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
 
-/*----- RTP interface functions */
-static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp,  struct ast_rtp *trtp, int codecs, int nat_active);
-static enum ast_rtp_get_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
-static enum ast_rtp_get_result sip_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
-static enum ast_rtp_get_result sip_get_trtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
-static int sip_get_codec(struct ast_channel *chan);
-static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p, int *faxdetect);
-
 /*------ T38 Support --------- */
 static int sip_handle_t38_reinvite(struct ast_channel *chan, struct sip_pvt *pvt, int reinvite); 
 static int transmit_response_with_t38_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans);
@@ -2195,8 +2187,8 @@
 	.fixup = sip_fixup,			/* called with chan locked */
 	.send_digit_begin = sip_senddigit_begin,	/* called with chan unlocked */
 	.send_digit_end = sip_senddigit_end,
-	.bridge = ast_rtp_bridge,			/* XXX chan unlocked ? */
-	.early_bridge = ast_rtp_early_bridge,
+//	.bridge = ast_rtp_bridge,			/* XXX chan unlocked ? */
+//	.early_bridge = ast_rtp_early_bridge,
 	.send_text = sip_sendtext,		/* called with chan locked */
 	.func_channel_read = acf_channel_read,
 	.queryoption = sip_queryoption,
@@ -2268,18 +2260,6 @@
 			return cur->x;
 	return errorvalue;
 }
-
-
-/*! \brief Interface structure with callbacks used to connect to RTP module */
-static struct ast_rtp_protocol sip_rtp = {
-	.type = "SIP",
-	.get_rtp_info = sip_get_rtp_peer,
-	.get_vrtp_info = sip_get_vrtp_peer,
-	.get_trtp_info = sip_get_trtp_peer,
-	.set_rtp_peer = sip_set_rtp_peer,
-	.get_codec = sip_get_codec,
-};
-
 
 /*! \brief SIP TCP connection handler */
 static void *sip_tcp_worker_fn(void *data)
@@ -4051,11 +4031,11 @@
 
 	if (p->rtp) {
 		ast_debug(1, "Setting NAT on RTP to %s\n", mode);
-		ast_rtp_setnat(p->rtp, natflags);
+		ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_NAT, natflags);
 	}
 	if (p->vrtp) {
 		ast_debug(1, "Setting NAT on VRTP to %s\n", mode);
-		ast_rtp_setnat(p->vrtp, natflags);
+		ast_rtp_instance_set_prop(p->vrtp, AST_RTP_PROPERTY_NAT, natflags);
 	}
 	if (p->udptl) {
 		ast_debug(1, "Setting NAT on UDPTL to %s\n", mode);
@@ -4063,7 +4043,7 @@
 	}
 	if (p->trtp) {
 		ast_debug(1, "Setting NAT on TRTP to %s\n", mode);
-		ast_rtp_setnat(p->trtp, natflags);
+		ast_rtp_instance_set_prop(p->trtp, AST_RTP_PROPERTY_NAT, natflags);
 	}
 }
 
@@ -4149,11 +4129,11 @@
 	ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
 	dialog->capability = peer->capability;
 	if ((!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) || !(dialog->capability & AST_FORMAT_VIDEO_MASK)) && dialog->vrtp) {
-		ast_rtp_destroy(dialog->vrtp);
+		ast_rtp_instance_destroy(dialog->vrtp);
 		dialog->vrtp = NULL;
 	}
 	if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_TEXTSUPPORT) && dialog->trtp) {
-		ast_rtp_destroy(dialog->trtp);
+		ast_rtp_instance_destroy(dialog->trtp);
 		dialog->trtp = NULL;
 	}
 	dialog->prefs = peer->prefs;
@@ -4168,28 +4148,24 @@
 	do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE);
 
 	if (dialog->rtp) { /* Audio */
-		ast_rtp_setdtmf(dialog->rtp, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
-		ast_rtp_setdtmfcompensate(dialog->rtp, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
-		ast_rtp_set_rtptimeout(dialog->rtp, peer->rtptimeout);
-		ast_rtp_set_rtpholdtimeout(dialog->rtp, peer->rtpholdtimeout);
-		ast_rtp_set_rtpkeepalive(dialog->rtp, peer->rtpkeepalive);
+		ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
+		ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
+//		ast_rtp_set_rtptimeout(dialog->rtp, peer->rtptimeout);
+//		ast_rtp_set_rtpholdtimeout(dialog->rtp, peer->rtpholdtimeout);
+//		ast_rtp_set_rtpkeepalive(dialog->rtp, peer->rtpkeepalive);
 		/* Set Frame packetization */
-		ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs);
+		ast_rtp_instance_packetization_set(dialog->rtp, &dialog->prefs);
 		dialog->autoframing = peer->autoframing;
 	}
 	if (dialog->vrtp) { /* Video */
-		ast_rtp_setdtmf(dialog->vrtp, 0);
-		ast_rtp_setdtmfcompensate(dialog->vrtp, 0);
-		ast_rtp_set_rtptimeout(dialog->vrtp, peer->rtptimeout);
-		ast_rtp_set_rtpholdtimeout(dialog->vrtp, peer->rtpholdtimeout);
-		ast_rtp_set_rtpkeepalive(dialog->vrtp, peer->rtpkeepalive);
+//		ast_rtp_set_rtptimeout(dialog->vrtp, peer->rtptimeout);
+//		ast_rtp_set_rtpholdtimeout(dialog->vrtp, peer->rtpholdtimeout);
+//		ast_rtp_set_rtpkeepalive(dialog->vrtp, peer->rtpkeepalive);
 	}
 	if (dialog->trtp) { /* Realtime text */
-		ast_rtp_setdtmf(dialog->trtp, 0);
-		ast_rtp_setdtmfcompensate(dialog->trtp, 0);
-		ast_rtp_set_rtptimeout(dialog->trtp, peer->rtptimeout);
-		ast_rtp_set_rtpholdtimeout(dialog->trtp, peer->rtpholdtimeout);
-		ast_rtp_set_rtpkeepalive(dialog->trtp, peer->rtpkeepalive);
+//		ast_rtp_set_rtptimeout(dialog->trtp, peer->rtptimeout);
+//		ast_rtp_set_rtpholdtimeout(dialog->trtp, peer->rtpholdtimeout);
+//		ast_rtp_set_rtpkeepalive(dialog->trtp, peer->rtpkeepalive);
 	}
 
 	ast_string_field_set(dialog, peername, peer->name);
@@ -4535,15 +4511,13 @@
 		p->notify_headers = NULL;
 	}
 	if (p->rtp) {
-		ast_rtp_destroy(p->rtp);
+		ast_rtp_instance_destroy(p->rtp);
 	}
 	if (p->vrtp) {
-		ast_rtp_destroy(p->vrtp);
+		ast_rtp_instance_destroy(p->vrtp);
 	}
 	if (p->trtp) {
-		while (ast_rtp_get_bridged(p->trtp))
-			usleep(1);
-		ast_rtp_destroy(p->trtp);
+		ast_rtp_instance_destroy(p->trtp);
 	}
 	if (p->udptl)
 		ast_udptl_destroy(p->udptl);
@@ -4880,7 +4854,7 @@
 	struct sip_pvt *p = ast->tech_pvt;
 	int needcancel = FALSE;
 	int needdestroy = 0;
-	struct ast_channel *oldowner = ast;
+//	struct ast_channel *oldowner = ast;
 
 	if (!p) {
 		ast_debug(1, "Asked to hangup channel that was not connected\n");
@@ -5004,43 +4978,11 @@
 			}
 
 			if (!p->pendinginvite) {
-				struct ast_channel *bridge = ast_bridged_channel(oldowner);
-				char *audioqos = "";
-				char *videoqos = "";
-				char *textqos = "";
-
-				if (p->rtp)
-					ast_rtp_set_vars(oldowner, p->rtp);
-
-				if (bridge) {
-					struct sip_pvt *q = bridge->tech_pvt;
-
-					if (IS_SIP_TECH(bridge->tech) && q->rtp)
-						ast_rtp_set_vars(bridge, q->rtp);
-				}
-
-				if (p->vrtp)
-					videoqos = ast_rtp_get_quality(p->vrtp, NULL, RTPQOS_SUMMARY);
-				if (p->trtp)
-					textqos = ast_rtp_get_quality(p->trtp, NULL, RTPQOS_SUMMARY);
+//				struct ast_channel *bridge = ast_bridged_channel(oldowner);
+
 				/* Send a hangup */
 				transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
 
-				/* Get RTCP quality before end of call */
-				if (p->do_history) {
-					if (p->rtp)
-						append_history(p, "RTCPaudio", "Quality:%s", audioqos);
-					if (p->vrtp)
-						append_history(p, "RTCPvideo", "Quality:%s", videoqos);
-					if (p->trtp)
-						append_history(p, "RTCPtext", "Quality:%s", textqos);
-				}
-				if (p->rtp && oldowner)
-					pbx_builtin_setvar_helper(oldowner, "RTPAUDIOQOS", audioqos);
-				if (p->vrtp && oldowner)
-					pbx_builtin_setvar_helper(oldowner, "RTPVIDEOQOS", videoqos);
-				if (p->trtp && oldowner)
-					pbx_builtin_setvar_helper(oldowner, "RTPTEXTQOS", textqos);
 			} else {
 				/* Note we will need a BYE when this all settles out
 				   but we can't send one while we have "INVITE" outstanding. */
@@ -5098,7 +5040,7 @@
 			change_t38_state(p, T38_ENABLED);
 			res = transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
 		} else {
-			ast_rtp_new_source(p->rtp);
+			ast_rtp_instance_new_source(p->rtp);
 			res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, FALSE);
 		}
 	}
@@ -5133,12 +5075,12 @@
 				if ((ast->_state != AST_STATE_UP) &&
 				    !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
 				    !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
-					ast_rtp_new_source(p->rtp);
+					ast_rtp_instance_new_source(p->rtp);
 					transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE);
 					ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);	
 				}
 				p->lastrtptx = time(NULL);
-				res = ast_rtp_write(p->rtp, frame);
+				res = ast_rtp_instance_write(p->rtp, frame);
 			}
 			sip_pvt_unlock(p);
 		}
@@ -5155,7 +5097,7 @@
 					ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);	
 				}
 				p->lastrtptx = time(NULL);
-				res = ast_rtp_write(p->vrtp, frame);
+				res = ast_rtp_instance_write(p->vrtp, frame);
 			}
 			sip_pvt_unlock(p);
 		}
@@ -5164,7 +5106,7 @@
 		if (p) {
 			sip_pvt_lock(p);
 			if (p->red) {
-				red_buffer_t140(p->trtp, frame);
+//				red_buffer_t140(p->trtp, frame);
 			} else {
 				if (p->trtp) {
 					/* Activate text early media */
@@ -5175,7 +5117,7 @@
 						ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);	
 					}
 					p->lastrtptx = time(NULL);
-					res = ast_rtp_write(p->trtp, frame);
+//					res = ast_rtp_write(p->trtp, frame);
 				}
 			}
 			sip_pvt_unlock(p);
@@ -5238,7 +5180,7 @@
 		   redirect of both channels). Note that a channel can not be masqueraded *into*
 		   a native bridge. So there is no danger that this breaks a native bridge that
 		   should stay up. */
-		sip_set_rtp_peer(newchan, NULL, NULL, 0, 0, 0);
+//		sip_set_rtp_peer(newchan, NULL, NULL, 0, 0, 0);
 		ret = 0;
 	}
 	ast_debug(3, "SIP Fixup: New owner for dialogue %s: %s (Old parent: %s)\n", p->callid, p->owner->name, oldchan->name);
@@ -5259,7 +5201,7 @@
 		break;
 	case SIP_DTMF_RFC2833:
 		if (p->rtp)
-			ast_rtp_senddigit_begin(p->rtp, digit);
+			ast_rtp_instance_dtmf_begin(p->rtp, digit);
 		break;
 	default:
 		break;
@@ -5284,7 +5226,7 @@
 		break;
 	case SIP_DTMF_RFC2833:
 		if (p->rtp)
-			ast_rtp_senddigit_end(p->rtp, digit);
+			ast_rtp_instance_dtmf_end(p->rtp, digit);
 		break;
 	case SIP_DTMF_INBAND:
 		res = -1; /* Tell Asterisk to stop inband indications */
@@ -5382,11 +5324,11 @@
 		res = -1;
 		break;
 	case AST_CONTROL_HOLD:
-		ast_rtp_new_source(p->rtp);
+		ast_rtp_instance_new_source(p->rtp);
 		ast_moh_start(ast, data, p->mohinterpret);
 		break;
 	case AST_CONTROL_UNHOLD:
-		ast_rtp_new_source(p->rtp);
+		ast_rtp_instance_new_source(p->rtp);
 		ast_moh_stop(ast);
 		break;
 	case AST_CONTROL_VIDUPDATE:	/* Request a video frame update */
@@ -5419,7 +5361,7 @@
 		}
 		break;
 	case AST_CONTROL_SRCUPDATE:
-		ast_rtp_new_source(p->rtp);
+		ast_rtp_instance_new_source(p->rtp);
 		break;
 	case -1:
 		res = -1;
@@ -11794,11 +11736,11 @@
 			p->jointcapability &= p->peercapability;
 		p->maxcallbitrate = peer->maxcallbitrate;
 		if ((!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) || !(p->capability & AST_FORMAT_VIDEO_MASK)) && p->vrtp) {
-			ast_rtp_destroy(p->vrtp);
+			ast_rtp_instance_destroy(p->vrtp);
 			p->vrtp = NULL;
 		}
 		if ((!ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) || !(p->capability & AST_FORMAT_TEXT_MASK)) && p->trtp) {
-			ast_rtp_destroy(p->trtp);
+			ast_rtp_instance_destroy(p->trtp);
 			p->trtp = NULL;
  		}
 		if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
@@ -21658,157 +21600,6 @@
 	}
 }
 
-
-/*! \brief Returns null if we can't reinvite audio (part of RTP interface) */
-static enum ast_rtp_get_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
-{
-	struct sip_pvt *p = NULL;
-	enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
-
-	if (!(p = chan->tech_pvt))
-		return AST_RTP_GET_FAILED;
-
-	sip_pvt_lock(p);
-	if (!(p->rtp)) {
-		sip_pvt_unlock(p);
-		return AST_RTP_GET_FAILED;
-	}
-
-	*rtp = p->rtp;
-
-	if (ast_rtp_getnat(*rtp) && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT))
-		res = AST_RTP_TRY_PARTIAL;
-	else if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
-		res = AST_RTP_TRY_NATIVE;
-	else if (ast_test_flag(&global_jbconf, AST_JB_FORCED))
-		res = AST_RTP_GET_FAILED;
-
-	sip_pvt_unlock(p);
-
-	return res;
-}
-
-/*! \brief Returns null if we can't reinvite video (part of RTP interface) */
-static enum ast_rtp_get_result sip_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
-{
-	struct sip_pvt *p = NULL;
-	enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
-	
-	if (!(p = chan->tech_pvt))
-		return AST_RTP_GET_FAILED;
-
-	sip_pvt_lock(p);
-	if (!(p->vrtp)) {
-		sip_pvt_unlock(p);
-		return AST_RTP_GET_FAILED;
-	}
-
-	*rtp = p->vrtp;
-
-	if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
-		res = AST_RTP_TRY_NATIVE;
-
-	sip_pvt_unlock(p);
-
-	return res;
-}
-
-/*! \brief Returns null if we can't reinvite text (part of RTP interface) */
-static enum ast_rtp_get_result sip_get_trtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
-{
-	struct sip_pvt *p = NULL;
-	enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
-	
-	if (!(p = chan->tech_pvt))
-		return AST_RTP_GET_FAILED;
-
-	sip_pvt_lock(p);
-	if (!(p->trtp)) {
-		sip_pvt_unlock(p);
-		return AST_RTP_GET_FAILED;
-	}
-
-	*rtp = p->trtp;
-
-	if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
-		res = AST_RTP_TRY_NATIVE;
-
-	sip_pvt_unlock(p);
-
-	return res;
-}
-
-/*! \brief Set the RTP peer for this call */
-static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
-{
-	struct sip_pvt *p;
-	int changed = 0;
-
-	p = chan->tech_pvt;
-	if (!p) 
-		return -1;
-
-	/* Disable early RTP bridge  */
-	if (chan->_state != AST_STATE_UP && !global_directrtpsetup) 	/* We are in early state */
-		return 0;
-
-	sip_pvt_lock(p);
-	if (p->alreadygone) {
-		/* If we're destroyed, don't bother */
-		sip_pvt_unlock(p);
-		return 0;
-	}
-
-	/* if this peer cannot handle reinvites of the media stream to devices
-	   that are known to be behind a NAT, then stop the process now
-	*/
-	if (nat_active && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT)) {
-		sip_pvt_unlock(p);
-		return 0;
-	}
-
-	if (rtp) {
-		changed |= ast_rtp_get_peer(rtp, &p->redirip);
-	} else if (p->redirip.sin_addr.s_addr || ntohs(p->redirip.sin_port) != 0) {
-		memset(&p->redirip, 0, sizeof(p->redirip));
-		changed = 1;
-	}
-	if (vrtp) {
-		changed |= ast_rtp_get_peer(vrtp, &p->vredirip);
-	} else if (p->vredirip.sin_addr.s_addr || ntohs(p->vredirip.sin_port) != 0) {
-		memset(&p->vredirip, 0, sizeof(p->vredirip));
-		changed = 1;
-	}
-	if (trtp) {
-		changed |= ast_rtp_get_peer(trtp, &p->tredirip);
-	} else if (p->tredirip.sin_addr.s_addr || ntohs(p->tredirip.sin_port) != 0) {
-		memset(&p->tredirip, 0, sizeof(p->tredirip));
-		changed = 1;
-	}
-	if (codecs && (p->redircodecs != codecs)) {
-		p->redircodecs = codecs;
-		changed = 1;
-	}
-	if (changed && !ast_test_flag(&p->flags[0], SIP_GOTREFER) && !ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) {
-		if (chan->_state != AST_STATE_UP) {	/* We are in early state */
-			if (p->do_history)
-				append_history(p, "ExtInv", "Initial invite sent with remote bridge proposal.");
-			ast_debug(1, "Early remote bridge setting SIP '%s' - Sending media to %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr));
-		} else if (!p->pendinginvite) {		/* We are up, and have no outstanding invite */
-			ast_debug(3, "Sending reinvite on SIP '%s' - It's audio soon redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr));
-			transmit_reinvite_with_sdp(p, FALSE, FALSE);
-		} else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
-			ast_debug(3, "Deferring reinvite on SIP '%s' - It's audio will be redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr));
-			/* We have a pending Invite. Send re-invite when we're done with the invite */
-			ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);	
-		}
-	}
-	/* Reset lastrtprx timer */
-	p->lastrtprx = p->lastrtptx = time(NULL);
-	sip_pvt_unlock(p);
-	return 0;
-}
-
 static char *synopsis_dtmfmode = "Change the dtmfmode for a SIP call";
 static char *descrip_dtmfmode = "  SIPDtmfMode(inband|info|rfc2833): Changes the dtmfmode for a SIP call\n";
 static char *app_dtmfmode = "SIPDtmfMode";
@@ -22166,9 +21957,6 @@
 	/* Register all CLI functions for SIP */
 	ast_cli_register_multiple(cli_sip, sizeof(cli_sip)/ sizeof(struct ast_cli_entry));
 
-	/* Tell the RTP subdriver that we're here */
-	ast_rtp_proto_register(&sip_rtp);
-
 	/* Tell the UDPTL subdriver that we're here */
 	ast_udptl_proto_register(&sip_udptl);
 
@@ -22239,9 +22027,6 @@
 	/* Unregister CLI commands */
 	ast_cli_unregister_multiple(cli_sip, sizeof(cli_sip) / sizeof(struct ast_cli_entry));
 
-	/* Disconnect from the RTP subsystem */
-	ast_rtp_proto_unregister(&sip_rtp);
-
 	/* Disconnect from UDPTL */
 	ast_udptl_proto_unregister(&sip_udptl);
 

Modified: team/file/rtp_engine/include/asterisk/rtp_engine.h
URL: http://svn.digium.com/view/asterisk/team/file/rtp_engine/include/asterisk/rtp_engine.h?view=diff&rev=129106&r1=129105&r2=129106
==============================================================================
--- team/file/rtp_engine/include/asterisk/rtp_engine.h (original)
+++ team/file/rtp_engine/include/asterisk/rtp_engine.h Tue Jul  8 12:34:43 2008
@@ -39,11 +39,18 @@
 	AST_RTP_PROPERTY_DTMF_COMPENSATE, /*!< Expect unreliable DTMF from remote party */
 	AST_RTP_PROPERTY_STUN,            /*!< Use STUN */
 	AST_RTP_PROPERTY_RED,             /*!< Use RED */
+	AST_RTP_PROPERTY_RTCP,            /*!< Use RTCP */
 	AST_RTP_PROPERTY_MAX,             /*!< Maximum number of properties supported */
 };
 
 enum ast_rtp_options {
 	AST_RTP_OPT_G726_NONSTANDARD = (1 << 0),
+};
+
+enum ast_rtp_glue_result {
+	AST_RTP_GLUE_RESULT_FORBID = 0,
+	AST_RTP_GLUE_RESULT_DIRECT,
+	AST_RTP_GLUE_RESULT_LOCAL,
 };
 
 /* Codes for RTP-specific data - not defined by our AST_FORMAT codes */
@@ -59,6 +66,9 @@
 struct ast_rtp_payload_type {
 	int isAstFormat; /*!< Is this an Asterisk value? */
 	int code;        /*!< Actual internal value */
+};
+
+struct ast_rtp_instance_stats {
 };
 
 struct ast_rtp_engine {
@@ -73,7 +83,9 @@
 	void (*prop_set)(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value); /*!< Callback for when an RTP property is set */
 	void (*payload_set)(struct ast_rtp_instance *instance, int payload, int AstFormat, int format); /*!< Callback for when a payload is set */
 	void (*packetization_set)(struct ast_rtp_instance *instance, struct ast_codec_pref *pref);      /*!< Callback for setting codec packetization preferences */
+	int (*get_stats)(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats);      /*!< Callback for retrieving statistics about the session */
 	struct ast_frame *(*read)(struct ast_rtp_instance *instance);                                   /*!< Callback for reading a frame in */
+	enum ast_bridge_result (*bridge)(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1); /*!< Callback for bridging two RTP instances together */
 	AST_RWLIST_ENTRY(ast_rtp_engine) entry;                                                         /*!< Linked list information */
 };
 
@@ -116,11 +128,12 @@
 /*! \brief Create a new RTP instance
  *
  * \param engine_name Name of the engine to use for the RTP instance
+ * \param glue The glue to use when bridging
  *
  * \retval non-NULL success
  * \retval NULL failure
  */
-struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name);
+struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name, struct ast_rtp_glue *glue);
 
 /*! \brief Destroy an RTP instance
  *

Modified: team/file/rtp_engine/main/rtp_engine.c
URL: http://svn.digium.com/view/asterisk/team/file/rtp_engine/main/rtp_engine.c?view=diff&rev=129106&r1=129105&r2=129106
==============================================================================
--- team/file/rtp_engine/main/rtp_engine.c (original)
+++ team/file/rtp_engine/main/rtp_engine.c Tue Jul  8 12:34:43 2008
@@ -180,7 +180,7 @@
 	return current_engine ? 0 : -1;
 }
 
-struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name)
+struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name, struct ast_rtp_glue *glue)
 {
 	struct ast_rtp_instance *instance = NULL;
 	struct ast_rtp_engine *engine = NULL;
@@ -215,6 +215,7 @@
 		return NULL;
 	}
 	instance->engine = engine;
+	instance->glue = glue;
 
 	/* And pass it off to the engine to setup */
 	if (instance->engine->new(instance)) {

Modified: team/file/rtp_engine/res/res_rtp_asterisk.c
URL: http://svn.digium.com/view/asterisk/team/file/rtp_engine/res/res_rtp_asterisk.c?view=diff&rev=129106&r1=129105&r2=129106
==============================================================================
--- team/file/rtp_engine/res/res_rtp_asterisk.c (original)
+++ team/file/rtp_engine/res/res_rtp_asterisk.c Tue Jul  8 12:34:43 2008
@@ -35,7 +35,6 @@
 #include <fcntl.h>
 #include <math.h> 
 
-#include "asterisk/rtp_engine.h"
 #include "asterisk/stun.h"
 #include "asterisk/pbx.h"
 #include "asterisk/frame.h"
@@ -48,6 +47,8 @@
 #include "asterisk/cli.h"
 #include "asterisk/manager.h"
 #include "asterisk/unaligned.h"
+#include "asterisk/module.h"
+#include "asterisk/rtp_engine.h"
 
 #define MAX_TIMESTAMP_SKEW	640
 
@@ -66,6 +67,8 @@
 #define RTP_MTU		1200
 
 #define DEFAULT_DTMF_TIMEOUT 3000	/*!< samples */
+
+#define ZFONE_PROFILE_ID 0x505a
 
 static int dtmftimeout = DEFAULT_DTMF_TIMEOUT;
 
@@ -87,22 +90,6 @@
 	STRICT_RTP_LEARN,    /*! Accept next packet as source */
 	STRICT_RTP_CLOSED,   /*! Drop all RTP packets not coming from source that was learned */
 };
-
-/* Uncomment this to enable more intense native bridging, but note: this is currently buggy */
-/* #define P2P_INTENSE */
-
-/*!
- * \brief Structure representing a RTP session.
- *
- * RTP session is defined on page 9 of RFC 3550: "An association among a set of participants communicating with RTP.  A participant may be involved in multiple RTP sessions at the same time [...]"
- *
- */
-/*! \brief The value of each payload format mapping: */
-struct rtpPayloadType {
-	int isAstFormat; 	/*!< whether the following code is an AST_FORMAT */
-	int code;
-};
-
 
 /*! \brief RTP session description */
 struct ast_rtp {
@@ -143,14 +130,11 @@
 	unsigned int dtmfsamples;
 	/* DTMF Transmission Variables */
 	unsigned int lastdigitts;
-	char sending_digit;	/*!< boolean - are we sending digits */
+	unsigned int sending_digit:1;	/*!< boolean - are we sending digits */
 	char send_digit;	/*!< digit we are sending */
 	int send_payload;
 	int send_duration;
-	int nat;
 	unsigned int flags;
-	struct sockaddr_in us;		/*!< Socket representation of the local endpoint. */
-	struct sockaddr_in them;	/*!< Socket representation of the remote endpoint. */
 	struct timeval rxcore;
 	struct timeval txcore;
 	double drxcore;                 /*!< The double representation of the first received packet */
@@ -163,62 +147,14 @@
 	struct sched_context *sched;
 	struct io_context *io;
 	void *data;
-	ast_rtp_callback callback;
-#ifdef P2P_INTENSE
-	ast_mutex_t bridge_lock;
-#endif
-	struct rtpPayloadType current_RTP_PT[MAX_RTP_PT];
-	int rtp_lookup_code_cache_isAstFormat; /*!< a cache for the result of rtp_lookup_code(): */
-	int rtp_lookup_code_cache_code;
-	int rtp_lookup_code_cache_result;
 	struct ast_rtcp *rtcp;
-	struct ast_codec_pref pref;
 	struct ast_rtp *bridged;        /*!< Who we are Packet bridged to */
 
 	enum strict_rtp_state strict_rtp_state; /*!< Current state that strict RTP protection is in */
 	struct sockaddr_in strict_rtp_address;  /*!< Remote address information for strict RTP purposes */
 
-	int set_marker_bit:1;           /*!< Whether to set the marker bit or not */
-	struct rtp_red *red;
+	unsigned int set_marker_bit:1;           /*!< Whether to set the marker bit or not */
 };
-
-static struct ast_frame *red_t140_to_red(struct rtp_red *red);
-static int red_write(const void *data);
- 
-struct rtp_red {
-	struct ast_frame t140;  /*!< Primary data  */
-	struct ast_frame t140red;   /*!< Redundant t140*/
-	unsigned char pt[RED_MAX_GENERATION];  /*!< Payload types for redundancy data */
-	unsigned char ts[RED_MAX_GENERATION]; /*!< Time stamps */
-	unsigned char len[RED_MAX_GENERATION]; /*!< length of each generation */
-	int num_gen; /*!< Number of generations */
-	int schedid; /*!< Timer id */
-	int ti; /*!< How long to buffer data before send */
-	unsigned char t140red_data[64000];  
-	unsigned char buf_data[64000]; /*!< buffered primary data */
-	int hdrlen; 
-	long int prev_ts;
-};
-
-/* Forward declarations */
-static int ast_rtcp_write(const void *data);
-static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw);
-static int ast_rtcp_write_sr(const void *data);
-static int ast_rtcp_write_rr(const void *data);
-static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp);
-static int ast_rtp_senddigit_continuation(struct ast_rtp *rtp);
-int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit);
-
-#define FLAG_3389_WARNING		(1 << 0)
-#define FLAG_NAT_ACTIVE			(3 << 1)
-#define FLAG_NAT_INACTIVE		(0 << 1)
-#define FLAG_NAT_INACTIVE_NOWARN	(1 << 1)
-#define FLAG_HAS_DTMF			(1 << 3)
-#define FLAG_P2P_SENT_MARK              (1 << 4)
-#define FLAG_P2P_NEED_DTMF              (1 << 5)
-#define FLAG_CALLBACK_MODE              (1 << 6)
-#define FLAG_DTMF_COMPENSATE            (1 << 7)
-#define FLAG_HAS_STUN                   (1 << 8)
 
 /*!
  * \brief Structure defining an RTCP session.
@@ -250,10 +186,6 @@
 	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 */
-	char quality[AST_MAX_USER_FIELD];
-	char quality_jitter[AST_MAX_USER_FIELD];
-	char quality_loss[AST_MAX_USER_FIELD];
-	char quality_rtt[AST_MAX_USER_FIELD];
 
 	double reported_maxjitter;
 	double reported_minjitter;
@@ -283,936 +215,572 @@
 	double normdevrtt;
 	double stdevrtt;
 	unsigned int rtt_count;
-	int sendfur;
 };
 
-size_t ast_rtp_alloc_size(void)
-{
-	return sizeof(struct ast_rtp);
-}
-
-/*! \brief List of current sessions */
-static AST_RWLIST_HEAD_STATIC(protos, ast_rtp_protocol);
-
-static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
-{
-	unsigned int sec, usec, frac;
-	sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
-	usec = tv.tv_usec;
-	frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
-	*msw = sec;
-	*lsw = frac;
-}
-
-int ast_rtp_fd(struct ast_rtp *rtp)
-{
-	return rtp->s;
-}
-
-int ast_rtcp_fd(struct ast_rtp *rtp)
-{
-	if (rtp->rtcp)
-		return rtp->rtcp->s;
-	return -1;
-}
-
-unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
-{
-	unsigned int interval;
-	/*! \todo XXX Do a more reasonable calculation on this one
-	 * Look in RFC 3550 Section A.7 for an example*/
-	interval = rtcpinterval;
-	return interval;
-}
-
-/* \brief Put RTP timeout timers on hold during another transaction, like T.38 */
-void ast_rtp_set_rtptimers_onhold(struct ast_rtp *rtp)
-{
-	rtp->rtptimeout = (-1) * rtp->rtptimeout;
-	rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
-}
-
-/*! \brief Set rtp timeout */
-void ast_rtp_set_rtptimeout(struct ast_rtp *rtp, int timeout)
-{
-	rtp->rtptimeout = timeout;
-}
-
-/*! \brief Set rtp hold timeout */
-void ast_rtp_set_rtpholdtimeout(struct ast_rtp *rtp, int timeout)
-{
-	rtp->rtpholdtimeout = timeout;
-}
-
-/*! \brief set RTP keepalive interval */
-void ast_rtp_set_rtpkeepalive(struct ast_rtp *rtp, int period)
-{
-	rtp->rtpkeepalive = period;
-}
-
-/*! \brief Get rtp timeout */
-int ast_rtp_get_rtptimeout(struct ast_rtp *rtp)
-{
-	if (rtp->rtptimeout < 0)	/* We're not checking, but remembering the setting (during T.38 transmission) */
+/* Forward Declarations */
+static int ast_rtp_new(struct ast_rtp_instance *instance);
+static int ast_rtp_destroy(struct ast_rtp_instance *instance);
+static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit);
+static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit);
+static void ast_rtp_new_source(struct ast_rtp_instance *instance);
+static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame);
+static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance);
+
+/* RTP Engine Declaration */
+static struct ast_rtp_engine asterisk_rtp_engine = {
+	.name = "asterisk",
+	.new = ast_rtp_new,
+	.destroy = ast_rtp_destroy,
+	.dtmf_begin = ast_rtp_dtmf_begin,
+	.dtmf_end = ast_rtp_dtmf_end,
+	.new_source = ast_rtp_new_source,
+	.write = ast_rtp_write,
+	.read = ast_rtp_read,
+};
+
+static inline int rtp_debug_test_addr(struct sockaddr_in *addr)
+{
+	if (!rtpdebug) {
 		return 0;
-	return rtp->rtptimeout;
-}
-
-/*! \brief Get rtp hold timeout */
-int ast_rtp_get_rtpholdtimeout(struct ast_rtp *rtp)
-{
-	if (rtp->rtptimeout < 0)	/* We're not checking, but remembering the setting (during T.38 transmission) */
-		return 0;
-	return rtp->rtpholdtimeout;
-}
-
-/*! \brief Get RTP keepalive interval */
-int ast_rtp_get_rtpkeepalive(struct ast_rtp *rtp)
-{
-	return rtp->rtpkeepalive;
-}
-
-void ast_rtp_set_data(struct ast_rtp *rtp, void *data)
-{
-	rtp->data = data;
-}
-
-void ast_rtp_set_callback(struct ast_rtp *rtp, ast_rtp_callback callback)
-{
-	rtp->callback = callback;
-}
-
-void ast_rtp_setnat(struct ast_rtp *rtp, int nat)
-{
-	rtp->nat = nat;
-}
-
-int ast_rtp_getnat(struct ast_rtp *rtp)
-{
-	return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
-}
-
-void ast_rtp_setdtmf(struct ast_rtp *rtp, int dtmf)
-{
-	ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
-}
-
-void ast_rtp_setdtmfcompensate(struct ast_rtp *rtp, int compensate)
-{
-	ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
-}
-
-void ast_rtp_setstun(struct ast_rtp *rtp, int stun_enable)
-{
-	ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
-}
-
-static void rtp_bridge_lock(struct ast_rtp *rtp)
-{
-#ifdef P2P_INTENSE
-	ast_mutex_lock(&rtp->bridge_lock);
-#endif
-	return;
-}
-
-static void rtp_bridge_unlock(struct ast_rtp *rtp)
-{
-#ifdef P2P_INTENSE
-	ast_mutex_unlock(&rtp->bridge_lock);
-#endif
-	return;
-}
-
-/*! \brief Calculate normal deviation */
-static double normdev_compute(double normdev, double sample, unsigned int sample_count)
-{
-	normdev = normdev * sample_count + sample;
-	sample_count++;
-
-	return normdev / sample_count;
-}
-
-static double stddev_compute(double stddev, double sample, double normdev, double normdev_curent, unsigned int sample_count)
-{
-/*
-		for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf
-		return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1));
-		we can compute the sigma^2 and that way we would have to do the sqrt only 1 time at the end and would save another pow 2 compute
-		optimized formula
-*/
-#define SQUARE(x) ((x) * (x))
-
-	stddev = sample_count * stddev;
-	sample_count++;
-
-	return stddev + 
-	       ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) + 
-	       ( SQUARE(sample - normdev_curent) / sample_count );
-
-#undef SQUARE
-}
-
-static struct ast_frame *send_dtmf(struct ast_rtp *rtp, enum ast_frame_type type)
-{
-	if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) ||
-	     (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
-		ast_debug(1, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr));
-		rtp->resp = 0;
-		rtp->dtmfsamples = 0;
-		return &ast_null_frame;
-	}
-	ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr));
-	if (rtp->resp == 'X') {
-		rtp->f.frametype = AST_FRAME_CONTROL;
-		rtp->f.subclass = AST_CONTROL_FLASH;
-	} else {
-		rtp->f.frametype = type;
-		rtp->f.subclass = rtp->resp;
-	}
-	rtp->f.datalen = 0;
-	rtp->f.samples = 0;
-	rtp->f.mallocd = 0;
-	rtp->f.src = "RTP";
-	return &rtp->f;
+	}
 	
-}
-
-static inline int rtp_debug_test_addr(struct sockaddr_in *addr)
-{
-	if (rtpdebug == 0)
-		return 0;
 	if (rtpdebugaddr.sin_addr.s_addr) {
 		if (((ntohs(rtpdebugaddr.sin_port) != 0)
 		     && (rtpdebugaddr.sin_port != addr->sin_port))
 		    || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
 			return 0;
 	}
+	
 	return 1;
 }
 
 static inline int rtcp_debug_test_addr(struct sockaddr_in *addr)
 {
-	if (rtcpdebug == 0)
+	if (!rtcpdebug) {
 		return 0;
+	}
+	
 	if (rtcpdebugaddr.sin_addr.s_addr) {
 		if (((ntohs(rtcpdebugaddr.sin_port) != 0)
 		     && (rtcpdebugaddr.sin_port != addr->sin_port))
 		    || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
 			return 0;
 	}
+	
 	return 1;
 }
 
-
-static struct ast_frame *process_cisco_dtmf(struct ast_rtp *rtp, unsigned char *data, int len)
-{
-	unsigned int event;
-	char resp = 0;
-	struct ast_frame *f = NULL;
-	unsigned char seq;
-	unsigned int flags;
-	unsigned int power;
-
-	/* We should have at least 4 bytes in RTP data */
-	if (len < 4)
-		return f;
-
-	/*	The format of Cisco RTP DTMF packet looks like next:
-		+0				- sequence number of DTMF RTP packet (begins from 1,
-						  wrapped to 0)
-		+1				- set of flags
-		+1 (bit 0)		- flaps by different DTMF digits delimited by audio
-						  or repeated digit without audio???
-		+2 (+4,+6,...)	- power level? (rises from 0 to 32 at begin of tone
-						  then falls to 0 at its end)
-		+3 (+5,+7,...)	- detected DTMF digit (0..9,*,#,A-D,...)
-		Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
-		by each new packet and thus provides some redudancy.
+static int create_new_socket(const char *type)
+{
+	int sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+	if (sock < 0) {
+		if (!type) {
+			type = "RTP/RTCP";
+		}
+		ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
+	} else {
+		long flags = fcntl(sock, F_GETFL);
+		fcntl(sock, F_SETFL, flags | O_NONBLOCK);
+#ifdef SO_NO_CHECK
+		if (nochecksums) {
+			setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
+		}
+#endif
+	}
+
+	return sock;
+}
+
+static int ast_rtp_new(struct ast_rtp_instance *instance)
+{
+	struct ast_rtp *rtp = NULL;
+
+	/* Create a new RTP structure to hold all of our data */
+	if (!(rtp = ast_calloc(1, sizeof(*rtp)))) {
+		return -1;
+	}
+
+	/* Create a new socket for us to listen on and use */
+	if ((rtp->s = create_new_socket("RTP")) < 0) {
+		ast_free(rtp);
+		return -1;
+	}
+
+	/* Now actually find a free RTP port to use */
+
+	/* Associate the RTP structure with the RTP instance and be done */
+	instance->data = rtp;
+
+	return 0;
+}
+
+static int ast_rtp_destroy(struct ast_rtp_instance *instance)
+{
+	struct ast_rtp *rtp = instance->data;
+
+	/* Destroy the smoother that was smoothing out audio if present */
+	if (rtp->smoother) {
+		ast_smoother_free(rtp->smoother);
+	}
+
+	/* Close our own socket so we no longer get packets */
+	if (rtp->s > -1) {
+		close(rtp->s);
+	}
+
+	/* Destroy RTCP if it was being used */
+	if (rtp->rtcp) {
+		AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+		close(rtp->rtcp->s);
+		ast_free(rtp->rtcp);
+	}
+
+	/* Finally destroy ourselves */ 
+	ast_free(rtp);
+
+	return 0;
+}
+
+static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
+{
+	struct ast_rtp *rtp = instance->data;
+	int hdrlen = 12, res = 0, i = 0, payload = 101;
+	char data[256];
+	unsigned int *rtpheader = (unsigned int*)data;
+	
+	/* If we have no remote address information bail out now */
+	if (!instance->remote_address.sin_addr.s_addr || !instance->remote_address.sin_port) {
+		return -1;
+	}
+	
+	/* Convert given digit into what we want to transmit */
+	if ((digit <= '9') && (digit >= '0')) {
+		digit -= '0';
+	} else if (digit == '*') {
+		digit = 10;
+	} else if (digit == '#') {
+		digit = 11;
+	} else if ((digit >= 'A') && (digit <= 'D')) {
+		digit = digit - 'A' + 12;
+	} else if ((digit >= 'a') && (digit <= 'd')) {
+		digit = digit - 'a' + 12;
+	} else {
+		ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
+		return -1;
+	}
+
+	/* Grab the payload that they expect the RFC2833 packet to be received in */
+	payload = ast_rtp_instance_payload_code(instance, 0, AST_RTP_DTMF);
+
+	/* Create the actual packet that we will be sending */
+	rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
+	rtpheader[1] = htonl(rtp->lastdigitts);
+	rtpheader[2] = htonl(rtp->ssrc);
+
+	/* Actually send the packet */
+	for (i = 0; i < 2; i++) {
+		rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
+		res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &instance->remote_address, sizeof(instance->remote_address));
+		if (res < 0) {
+			ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
+				ast_inet_ntoa(instance->remote_address.sin_addr), ntohs(instance->remote_address.sin_port), strerror(errno));
+		}
+		if (rtp_debug_test_addr(&instance->remote_address)) {
+			ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+				    ast_inet_ntoa(instance->remote_address.sin_addr),
+				    ntohs(instance->remote_address.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
+		}
+		rtp->seqno++;
+		rtp->send_duration += 160;
+		rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
+        }
+
+	/* Record that we are in the process of sending a digit and information needed to continue doing so */
+	rtp->sending_digit = 1;
+	rtp->send_digit = digit;
+	rtp->send_payload = payload;
+	
+	return 0;
+}
+
+static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
+{
+	struct ast_rtp *rtp = instance->data;

[... 3946 lines stripped ...]



More information about the svn-commits mailing list