[asterisk-commits] mmichelson: trunk r201583 - in /trunk: channels/ include/asterisk/ main/ res/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Jun 18 10:20:31 CDT 2009


Author: mmichelson
Date: Thu Jun 18 10:20:17 2009
New Revision: 201583

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=201583
Log:
Trunk implementation of setting an alternate RTP source.

This contains the interface by which we can let an rtp instance know
that it might start receiving audio from a new source. This is similar
in nature to revision 197588 of Asterisk 1.4.

Review: https://reviewboard.asterisk.org/r/276


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

Modified: trunk/channels/chan_sip.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/channels/chan_sip.c?view=diff&rev=201583&r1=201582&r2=201583
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Thu Jun 18 10:20:17 2009
@@ -7781,6 +7781,63 @@
 	return FALSE;
 }
 
+enum media_type {
+	SDP_AUDIO,
+	SDP_VIDEO,
+};
+
+static int get_ip_and_port_from_sdp(struct sip_request *req, const enum media_type media, struct sockaddr_in *sin)
+{
+	const char *m;
+	const char *c;
+	int miterator = req->sdp_start;
+	int citerator = req->sdp_start;
+	int x = 0;
+	int numberofports;
+	int len;
+	char host[258] = ""; /*Initialize to empty so we will know if we have any input */
+	struct ast_hostent audiohp;
+	struct hostent *hp;
+
+	c = get_sdp_iterate(&citerator, req, "c");
+	if (sscanf(c, "IN IP4 %256s", host) != 1) {
+		ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
+		/* Continue since there may be a valid host in a c= line specific to the audio stream */
+	}
+	/* We only want the m and c lines for audio */
+	while ((m = get_sdp_iterate(&miterator, req, "m"))) {
+		if ((media == SDP_AUDIO && ((sscanf(m, "audio %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
+		    (sscanf(m, "audio %d RTP/AVP %n", &x, &len) == 1 && len > 0))) ||
+			(media == SDP_VIDEO && ((sscanf(m, "video %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
+		    (sscanf(m, "video %d RTP/AVP %n", &x, &len) == 1 && len > 0)))) {
+			/* See if there's a c= line for this media stream.
+			 * XXX There is no guarantee that we'll be grabbing the c= line for this
+			 * particular media stream here. However, this is the same logic used in process_sdp.
+			 */
+			c = get_sdp_iterate(&citerator, req, "c");
+			if (!ast_strlen_zero(c)) {
+				sscanf(c, "IN IP4 %256s", host);
+			}
+			break;
+		}
+	}
+
+	if (ast_strlen_zero(host) || x == 0) {
+		ast_log(LOG_WARNING, "Failed to read an alternate host or port in SDP. Expect %s problems\n", media == SDP_AUDIO ? "audio" : "video");
+		return -1;
+	}
+
+	hp = ast_gethostbyname(host, &audiohp);
+	if (!hp) {
+		ast_log(LOG_WARNING, "Could not look up IP address of alternate hostname. Expect %s problems\n", media == SDP_AUDIO? "audio" : "video");
+		return -1;
+	}
+
+	memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
+	sin->sin_port = htons(x);
+	return 0;
+}
+
 /*! \brief Process SIP SDP offer, select formats and activate RTP channels
 	If offer is rejected, we will not change any properties of the call
  	Return 0 on success, a negative value on errors.
@@ -19907,6 +19964,21 @@
 		} else {
 			/* We already have a pending invite. Sorry. You are on hold. */
 			p->glareinvite = seqno;
+			if (p->rtp && find_sdp(req)) {
+				struct sockaddr_in sin;
+				if (get_ip_and_port_from_sdp(req, SDP_AUDIO, &sin)) {
+					ast_log(LOG_WARNING, "Failed to set an alternate media source on glared reinvite. Audio may not work properly on this call.\n");
+				} else {
+					ast_rtp_instance_set_alt_remote_address(p->rtp, &sin);
+				}
+				if (p->vrtp) {
+					if (get_ip_and_port_from_sdp(req, SDP_VIDEO, &sin)) {
+						ast_log(LOG_WARNING, "Failed to set an alternate media source on glared reinvite. Video may not work properly on this call.\n");
+					} else {
+						ast_rtp_instance_set_alt_remote_address(p->vrtp, &sin);
+					}
+				}
+			}
 			transmit_response_reliable(p, "491 Request Pending", req);
 			ast_debug(1, "Got INVITE on call where we already have pending INVITE, deferring that - %s\n", p->callid);
 			/* Don't destroy dialog here */

Modified: trunk/include/asterisk/rtp_engine.h
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/include/asterisk/rtp_engine.h?view=diff&rev=201583&r1=201582&r2=201583
==============================================================================
--- trunk/include/asterisk/rtp_engine.h (original)
+++ trunk/include/asterisk/rtp_engine.h Thu Jun 18 10:20:17 2009
@@ -323,6 +323,8 @@
 	void (*packetization_set)(struct ast_rtp_instance *instance, struct ast_codec_pref *pref);
 	/*! Callback for setting the remote address that RTP is to be sent to */
 	void (*remote_address_set)(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
+	/*! Callback for setting an alternate remote address */
+	void (*alt_remote_address_set)(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
 	/*! Callback for changing DTMF mode */
 	int (*dtmf_mode_set)(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode);
 	/*! Callback for retrieving statistics */
@@ -639,6 +641,28 @@
 int ast_rtp_instance_set_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
 
 /*!
+ * \brief Set the address of an an alternate RTP address to receive from
+ *
+ * \param instance The RTP instance to change the address on
+ * \param address Address to set it to
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ *
+ * Example usage:
+ *
+ * \code
+ * ast_rtp_instance_set_alt_remote_address(instance, &sin);
+ * \endcode
+ *
+ * This changes the alternate remote address that RTP will be sent to on instance to the address given in the sin
+ * structure.
+ *
+ * \since 1.6.3
+ */
+int ast_rtp_instance_set_alt_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
+
+/*!
  * \brief Set the address that we are expecting to receive RTP on
  *
  * \param instance The RTP instance to change the address on

Modified: trunk/main/rtp_engine.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/main/rtp_engine.c?view=diff&rev=201583&r1=201582&r2=201583
==============================================================================
--- trunk/main/rtp_engine.c (original)
+++ trunk/main/rtp_engine.c Thu Jun 18 10:20:17 2009
@@ -50,6 +50,8 @@
 	struct sockaddr_in local_address;
 	/*! Address that we are sending RTP to */
 	struct sockaddr_in remote_address;
+	/*! Alternate address that we are receiving RTP from */
+	struct sockaddr_in alt_remote_address;
 	/*! Instance that we are bridged to if doing remote or local bridging */
 	struct ast_rtp_instance *bridged;
 	/*! Payload and packetization information */
@@ -368,6 +370,20 @@
 
 	if (instance->engine->remote_address_set) {
 		instance->engine->remote_address_set(instance, &instance->remote_address);
+	}
+
+	return 0;
+}
+
+int ast_rtp_instance_set_alt_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
+{
+	instance->alt_remote_address.sin_addr = address->sin_addr;
+	instance->alt_remote_address.sin_port = address->sin_port;
+
+	/* oink */
+
+	if (instance->engine->alt_remote_address_set) {
+		instance->engine->alt_remote_address_set(instance, &instance->alt_remote_address);
 	}
 
 	return 0;

Modified: trunk/res/res_rtp_asterisk.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/res/res_rtp_asterisk.c?view=diff&rev=201583&r1=201582&r2=201583
==============================================================================
--- trunk/res/res_rtp_asterisk.c (original)
+++ trunk/res/res_rtp_asterisk.c Thu Jun 18 10:20:17 2009
@@ -166,6 +166,7 @@
 
 	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 */
+	struct sockaddr_in alt_rtp_address; /*!<Alternate remote address information */
 
 	struct rtp_red *red;
 };
@@ -257,6 +258,7 @@
 static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value);
 static int ast_rtp_fd(struct ast_rtp_instance *instance, int rtcp);
 static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
+static void ast_rtp_alt_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
 static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations);
 static int rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame);
 static int ast_rtp_local_bridge(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1);
@@ -278,6 +280,7 @@
 	.prop_set = ast_rtp_prop_set,
 	.fd = ast_rtp_fd,
 	.remote_address_set = ast_rtp_remote_address_set,
+	.alt_remote_address_set = ast_rtp_alt_remote_address_set,
 	.red_init = rtp_red_init,
 	.red_buffer = rtp_red_buffer,
 	.local_bridge = ast_rtp_local_bridge,
@@ -1878,8 +1881,14 @@
 		rtp->strict_rtp_state = STRICT_RTP_CLOSED;
 	} else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
 		if ((rtp->strict_rtp_address.sin_addr.s_addr != sin.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sin.sin_port)) {
-			ast_debug(1, "Received RTP packet from %s:%d, dropping due to strict RTP protection. Expected it to be from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
-			return &ast_null_frame;
+			/* Hmm, not the strict addres. Perhaps we're getting audio from the alternate? */
+			if ((rtp->alt_rtp_address.sin_addr.s_addr == sin.sin_addr.s_addr) && (rtp->alt_rtp_address.sin_port == sin.sin_port)) {
+				/* ooh, we did! You're now the new expected address, son! */
+				rtp->strict_rtp_address = sin;
+			} else  {
+				ast_debug(1, "Received RTP packet from %s:%d, dropping due to strict RTP protection. Expected it to be from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
+				return &ast_null_frame;
+			}
 		}
 	}
 
@@ -2200,6 +2209,18 @@
 	return;
 }
 
+static void ast_rtp_alt_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin)
+{
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+
+	/* No need to futz with rtp->rtcp here because ast_rtcp_read is already able to adjust if receiving
+	 * RTCP from an "unexpected" source
+	 */
+	rtp->alt_rtp_address = *sin;
+
+	return;
+}
+
 /*! \brief Write t140 redundacy frame
  * \param data primary data to be buffered
  */




More information about the asterisk-commits mailing list