[svn-commits] file: branch file/pimp_sip_media r380849 - in /team/file/pimp_sip_media: incl...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Feb 5 11:32:51 CST 2013


Author: file
Date: Tue Feb  5 11:32:47 2013
New Revision: 380849

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=380849
Log:
Split up negotiation and application of an SDP media stream.

Modified:
    team/file/pimp_sip_media/include/asterisk/res_sip_session.h
    team/file/pimp_sip_media/res/res_sip_sdp_audio.c
    team/file/pimp_sip_media/res/res_sip_session.c

Modified: team/file/pimp_sip_media/include/asterisk/res_sip_session.h
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_media/include/asterisk/res_sip_session.h?view=diff&rev=380849&r1=380848&r2=380849
==============================================================================
--- team/file/pimp_sip_media/include/asterisk/res_sip_session.h (original)
+++ team/file/pimp_sip_media/include/asterisk/res_sip_session.h Tue Feb  5 11:32:47 2013
@@ -119,7 +119,7 @@
      * \retval <0 There was an error encountered. No further operation will take place and the current negotiation will be abandoned.
      * \retval >0 The stream was handled by this handler. No further handler of this stream type will be called.
      */
-    int (*handle_incoming_sdp_stream)(struct ast_sip_session *session, const struct pjmedia_sdp_session *sdp, struct pjmedia_sdp_media *stream);
+    int (*negotiate_incoming_sdp_stream)(struct ast_sip_session *session, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream);
     /*!
      * \brief Create an SDP media stream and add it to the outgoing SDP offer or answer
      * \param session The session for which media is being added
@@ -129,6 +129,16 @@
      * \retval >0 The handler has a stream to be added to the SDP. No further handler of this stream type will be called.
      */
     int (*create_outgoing_sdp_stream)(struct ast_sip_session *session, struct pjmedia_sdp_session *sdp);
+    /*!
+     * \brief Apply a negotiated SDP media stream
+     * \param session The session for which media is being applied
+     * \param sdp The entire SDP
+     * \param stream The stream which to apply
+     * \retval 0 The stream was not applied by this handler. If there are other registered handlers for this stream type, they will be called.
+     * \retval <0 There was an error encountered. No further operation will take place and the current application will be abandoned.
+     * \retval >0 The stream was handled by this handler. No further handler of this stream type will be called.
+     */
+    int (*apply_negotiated_sdp_stream)(struct ast_sip_session *session, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream);
 	/*! Next item int he list. */
 	AST_LIST_ENTRY(ast_sip_session_sdp_handler) next;
 };

Modified: team/file/pimp_sip_media/res/res_sip_sdp_audio.c
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_media/res/res_sip_sdp_audio.c?view=diff&rev=380849&r1=380848&r2=380849
==============================================================================
--- team/file/pimp_sip_media/res/res_sip_sdp_audio.c (original)
+++ team/file/pimp_sip_media/res/res_sip_sdp_audio.c Tue Feb  5 11:32:47 2013
@@ -54,14 +54,16 @@
 static struct ast_sched_context *sched;
 
 /*! \brief Forward declarations for SDP handler functions */
-static int audio_handle_incoming_sdp_stream(struct ast_sip_session *session, const struct pjmedia_sdp_session *sdp, struct pjmedia_sdp_media *stream);
+static int audio_negotiate_incoming_sdp_stream(struct ast_sip_session *session, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream);
 static int audio_create_outgoing_sdp_stream(struct ast_sip_session *session, struct pjmedia_sdp_session *sdp);
+static int audio_apply_negotiated_sdp_stream(struct ast_sip_session *session, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream);
 
 /*! \brief SDP handler for 'audio' media stream */
 static struct ast_sip_session_sdp_handler audio_sdp_handler = {
 	.id = "audio",
-	.handle_incoming_sdp_stream = audio_handle_incoming_sdp_stream,
+	.negotiate_incoming_sdp_stream = audio_negotiate_incoming_sdp_stream,
 	.create_outgoing_sdp_stream = audio_create_outgoing_sdp_stream,
+	.apply_negotiated_sdp_stream = audio_apply_negotiated_sdp_stream,
 };
 
 /*! \brief Internal function which creates an RTP instance */
@@ -92,29 +94,16 @@
 	return 0;
 }
 
-/*! \brief Function which handles an incoming 'audio' stream */
-static int audio_handle_incoming_sdp_stream(struct ast_sip_session *session, const struct pjmedia_sdp_session *sdp, struct pjmedia_sdp_media *stream)
-{
-	int res = 1, addrs_cnt, format, othercapability = 0;
+/*! \brief Function which negotiates an incoming 'audio' stream */
+static int audio_negotiate_incoming_sdp_stream(struct ast_sip_session *session, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
+{
+	int addrs_cnt;
 	char host[NI_MAXHOST];
 	struct ast_sockaddr *addrs;
-	struct ast_rtp_codecs codecs;
-	const pjmedia_sdp_attr *attr;
-	struct ast_format_cap *cap, *jointcap = NULL, *peercap = NULL;
-//	struct ast_format fmt;
-
-	/* If the stream has been rejected stop media if active */
-	if (!stream->desc.port) {
-		if (session->media.audio) {
-			ast_rtp_instance_stop(session->media.audio);
-		}
-
-		return 1;
-	}
-
-	/* Create an RTP instance if need be */
-	if (!session->media.audio && audio_create_rtp(session)) {
-		return -1;
+
+	/* If no audio formats have been configured reject this stream */
+	if (!ast_format_cap_has_type(session->endpoint->codecs, AST_FORMAT_TYPE_AUDIO)) {
+		return 0;
 	}
 
 	if (!stream->conn) {
@@ -125,88 +114,12 @@
 
 	/* Ensure that the address provided is valid */
 	if ((addrs_cnt = ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC)) <= 0) {
-		ast_log(LOG_ERROR, "Failed to resolve %s\n", host);
-		/* The provided host was actually invalid so we kill the session as it would just end up being broken */
-		if (session->channel) {
-			ast_channel_hangupcause_set(session->channel, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
-		}
-		return -1;
-	}
-
-	/* To properly apply formats to the channel we need to keep track of capabilities */
-	if (!(cap = ast_format_cap_alloc_nolock()) ||
-	    !(peercap = ast_format_cap_alloc_nolock())) {
-		ast_log(LOG_ERROR, "Failed to allocate audio capabilities\n");
-		res = -1;
-		goto cleanup;
-	}
-
-	/* Apply connection information to the RTP instance */
-	ast_sockaddr_set_port(addrs, stream->desc.port);
-	ast_rtp_instance_set_remote_address(session->media.audio, addrs);
-	ast_free(addrs);
-
-	ast_rtp_codecs_payloads_initialize(&codecs);
-
-	/* Iterate through provided formats */
-	for (format = 0; format < stream->desc.fmt_count; format++) {
-		/* The payload is kept as a string for things like t38 but for audio it is always numerical */
-		ast_rtp_codecs_payloads_set_m_type(&codecs, NULL, pj_strtoul(&stream->desc.fmt[format]));
-
-		/* Look for the optional rtpmap attribute */
-		if ((attr = pjmedia_sdp_media_find_attr2(stream, "rtpmap", &stream->desc.fmt[format]))) {
-			pjmedia_sdp_rtpmap *rtpmap;
-
-			/* Interpret the attribute as an rtpmap */
-			if ((pjmedia_sdp_attr_to_rtpmap(session->inv_session->pool_active, attr, &rtpmap)) == PJ_SUCCESS) {
-				char name[32];
-
-				snprintf(name, sizeof(name), "%.*s", (int) pj_strlen(&rtpmap->enc_name), pj_strbuf(&rtpmap->enc_name));
-				ast_rtp_codecs_payloads_set_rtpmap_type_rate(&codecs, NULL, pj_strtoul(&stream->desc.fmt[format]),
-									     "audio", name, 0, rtpmap->clock_rate);
-			}
-		}
-	}
-
-	ast_rtp_codecs_payload_formats(&codecs, peercap, &othercapability);
-
-	/* Using the configured codecs and the codecs in this SDP we determine the joint formats for *audio only* */
-	ast_format_cap_copy(cap, session->endpoint->codecs);
-	ast_format_cap_remove_bytype(cap, AST_FORMAT_TYPE_VIDEO);
-
-	if (!(jointcap = ast_format_cap_joint(cap, peercap))) {
-		char usbuf[64];
-		char thembuf[64];
-		if (session->channel) {
-			ast_channel_hangupcause_set(session->channel, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
-		}
-		ast_getformatname_multiple(usbuf, sizeof(usbuf), cap);
-		ast_getformatname_multiple(thembuf, sizeof(thembuf), peercap);
-		ast_log(LOG_WARNING, "No joint capabilities between our configuration(%s) and incoming SDP(%s)\n", usbuf, thembuf);
-		res = -1;
-		goto cleanup;
-	}
-
-	ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(session->media.audio), session->media.audio);
-
-	/* Now that we have joint formats for audio remove the existing ones from the channel and add the new ones */
-//	ast_format_cap_copy(cap, ast_channel_nativeformats(session->channel));
-//	ast_format_cap_remove_bytype(cap, AST_FORMAT_TYPE_AUDIO);
-//	ast_format_cap_append(cap, jointcap);
-
-	/* Apply the new formats to the channel, potentially changing read/write formats while doing so */
-//	ast_format_cap_copy(ast_channel_nativeformats(session->channel), cap);
-//	ast_codec_choose(&session->endpoint->prefs, cap, 1, &fmt);
-//	ast_set_read_format(session->channel, &fmt);
-//	ast_set_write_format(session->channel, &fmt);
-
-cleanup:
-	ast_format_cap_destroy(peercap);
-	ast_format_cap_destroy(jointcap);
-	ast_format_cap_destroy(cap);
-	ast_rtp_codecs_payloads_destroy(&codecs);
-
-	return res;
+		/* The provided host was actually invalid so we error out this negotiation */
+		return -1;
+	}
+
+	/* pjmedia takes care of the formats and such */
+	return 1;
 }
 
 /*! \brief Function which creates an outgoing 'audio' stream */
@@ -314,6 +227,108 @@
 	sdp->media[sdp->media_count++] = media;
 
 	return 1;
+}
+
+/*! \brief Function which applies a negotiated SDP stream */
+static int audio_apply_negotiated_sdp_stream(struct ast_sip_session *session, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
+{
+	int res = 1, addrs_cnt, format, othercapability = 0;
+	char host[NI_MAXHOST];
+	struct ast_sockaddr *addrs;
+	struct ast_rtp_codecs codecs;
+	const pjmedia_sdp_attr *attr;
+	struct ast_format_cap *cap, *jointcap = NULL, *peercap = NULL;
+	struct ast_format fmt;
+
+	/* Create an RTP instance if need be */
+	if (!session->media.audio && audio_create_rtp(session)) {
+		return -1;
+	}
+
+	if (!stream->conn) {
+		snprintf(host, sizeof(host), "%.*s", (int) pj_strlen(&sdp->conn->addr), pj_strbuf(&sdp->conn->addr));
+	} else {
+		snprintf(host, sizeof(host), "%.*s", (int) pj_strlen(&stream->conn->addr), pj_strbuf(&stream->conn->addr));
+	}
+
+	/* Ensure that the address provided is valid */
+	if ((addrs_cnt = ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC)) <= 0) {
+		/* The provided host was actually invalid so we error out this negotiation */
+		return -1;
+	}
+
+	/* To properly apply formats to the channel we need to keep track of capabilities */
+	if (!(cap = ast_format_cap_alloc_nolock()) ||
+	    !(peercap = ast_format_cap_alloc_nolock())) {
+		ast_log(LOG_ERROR, "Failed to allocate audio capabilities\n");
+		res = -1;
+		goto cleanup;
+	}
+
+	/* Apply connection information to the RTP instance */
+	ast_sockaddr_set_port(addrs, stream->desc.port);
+	ast_rtp_instance_set_remote_address(session->media.audio, addrs);
+	ast_free(addrs);
+
+	ast_rtp_codecs_payloads_initialize(&codecs);
+
+	/* Iterate through provided formats */
+	for (format = 0; format < stream->desc.fmt_count; format++) {
+		/* The payload is kept as a string for things like t38 but for audio it is always numerical */
+		ast_rtp_codecs_payloads_set_m_type(&codecs, NULL, pj_strtoul(&stream->desc.fmt[format]));
+
+		/* Look for the optional rtpmap attribute */
+		if ((attr = pjmedia_sdp_media_find_attr2(stream, "rtpmap", &stream->desc.fmt[format]))) {
+			pjmedia_sdp_rtpmap *rtpmap;
+
+			/* Interpret the attribute as an rtpmap */
+			if ((pjmedia_sdp_attr_to_rtpmap(session->inv_session->pool_active, attr, &rtpmap)) == PJ_SUCCESS) {
+				char name[32];
+
+				snprintf(name, sizeof(name), "%.*s", (int) pj_strlen(&rtpmap->enc_name), pj_strbuf(&rtpmap->enc_name));
+				ast_rtp_codecs_payloads_set_rtpmap_type_rate(&codecs, NULL, pj_strtoul(&stream->desc.fmt[format]),
+									     "audio", name, 0, rtpmap->clock_rate);
+			}
+		}
+	}
+
+	ast_rtp_codecs_payload_formats(&codecs, peercap, &othercapability);
+
+	/* Using the configured codecs and the codecs in this SDP we determine the joint formats for *audio only* */
+	ast_format_cap_copy(cap, session->endpoint->codecs);
+	ast_format_cap_remove_bytype(cap, AST_FORMAT_TYPE_VIDEO);
+
+	if (!(jointcap = ast_format_cap_joint(cap, peercap))) {
+		char usbuf[64], thembuf[64];
+
+		ast_channel_hangupcause_set(session->channel, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
+		ast_getformatname_multiple(usbuf, sizeof(usbuf), cap);
+		ast_getformatname_multiple(thembuf, sizeof(thembuf), peercap);
+		ast_log(LOG_WARNING, "No joint capabilities between our configuration(%s) and incoming SDP(%s)\n", usbuf, thembuf);
+		res = -1;
+		goto cleanup;
+	}
+
+	ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(session->media.audio), session->media.audio);
+
+	/* Now that we have joint formats for audio remove the existing ones from the channel and add the new ones */
+	ast_format_cap_copy(cap, ast_channel_nativeformats(session->channel));
+	ast_format_cap_remove_bytype(cap, AST_FORMAT_TYPE_AUDIO);
+	ast_format_cap_append(cap, jointcap);
+
+	/* Apply the new formats to the channel, potentially changing read/write formats while doing so */
+	ast_format_cap_copy(ast_channel_nativeformats(session->channel), cap);
+	ast_codec_choose(&session->endpoint->prefs, cap, 1, &fmt);
+	ast_set_read_format(session->channel, &fmt);
+	ast_set_write_format(session->channel, &fmt);
+
+cleanup:
+	ast_format_cap_destroy(peercap);
+	ast_format_cap_destroy(jointcap);
+	ast_format_cap_destroy(cap);
+	ast_rtp_codecs_payloads_destroy(&codecs);
+
+	return res;
 }
 
 /*!

Modified: team/file/pimp_sip_media/res/res_sip_session.c
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_media/res/res_sip_session.c?view=diff&rev=380849&r1=380848&r2=380849
==============================================================================
--- team/file/pimp_sip_media/res/res_sip_session.c (original)
+++ team/file/pimp_sip_media/res/res_sip_session.c Tue Feb  5 11:32:47 2013
@@ -172,7 +172,41 @@
 			continue;
 		}
 		AST_LIST_TRAVERSE(&handler_list->list, handler, next) {
-			int res = handler->handle_incoming_sdp_stream(session, sdp, sdp->media[i]);
+			int res = handler->negotiate_incoming_sdp_stream(session, sdp, sdp->media[i]);
+			if (res < 0) {
+				/* Catastrophic failure. Abort! */
+				return -1;
+			} else if (res == 0) {
+				/* Not handled yet. Move to the next handler */
+				continue;
+			} else {
+				/* Handled by this handler. Move to the next stream */
+				break;
+			}
+		}
+	}
+	return 0;
+}
+
+static int handle_negotiated_sdp(struct ast_sip_session *session, const pjmedia_sdp_session *sdp)
+{
+	int i;
+	for (i = 0; i < sdp->media_count; ++i) {
+		/* See if there are registered handlers for this media stream type */
+		char media[20];
+		struct ast_sip_session_sdp_handler *handler;
+		RAII_VAR(struct sdp_handler_list *, handler_list, NULL, ao2_cleanup);
+
+		/* We need a null-terminated version of the media string */
+		ast_copy_pj_str(media, &sdp->media[i]->desc.media, sizeof(media));
+
+		handler_list = ao2_find(sdp_handlers, media, OBJ_KEY);
+		if (!handler_list) {
+			ast_debug(1, "No registered SDP handlers for media type '%s'\n", media);
+			continue;
+		}
+		AST_LIST_TRAVERSE(&handler_list->list, handler, next) {
+			int res = handler->apply_negotiated_sdp_stream(session, sdp, sdp->media[i]);
 			if (res < 0) {
 				/* Catastrophic failure. Abort! */
 				return -1;
@@ -1104,9 +1138,8 @@
 	struct ast_sip_session *session = inv->mod_data[session_module.id];
 	const pjmedia_sdp_session *remote;
 
-	/* TODO: Split up handling of incoming and actual applying */
 	if (pjmedia_sdp_neg_get_active_remote(inv->neg, &remote) == PJ_SUCCESS) {
-		handle_incoming_sdp(session, remote);
+		handle_negotiated_sdp(session, remote);
 	}
 }
 




More information about the svn-commits mailing list