[asterisk-commits] kharwell: branch kharwell/pimp_sip_media_neg r384805 - in /team/kharwell/pimp...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Apr 4 17:57:34 CDT 2013


Author: kharwell
Date: Thu Apr  4 17:57:30 2013
New Revision: 384805

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=384805
Log:
initial changes for media negotiation rules

Modified:
    team/kharwell/pimp_sip_media_neg/channels/chan_gulp.c
    team/kharwell/pimp_sip_media_neg/include/asterisk/res_sip_session.h
    team/kharwell/pimp_sip_media_neg/res/res_sip_sdp_rtp.c
    team/kharwell/pimp_sip_media_neg/res/res_sip_session.c

Modified: team/kharwell/pimp_sip_media_neg/channels/chan_gulp.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_media_neg/channels/chan_gulp.c?view=diff&rev=384805&r1=384804&r2=384805
==============================================================================
--- team/kharwell/pimp_sip_media_neg/channels/chan_gulp.c (original)
+++ team/kharwell/pimp_sip_media_neg/channels/chan_gulp.c Thu Apr  4 17:57:30 2013
@@ -77,6 +77,19 @@
 			<para>Returns a properly formatted dial string for dialing all contacts on an AOR.</para>
 		</description>
 	</function>
+	<function name="MEDIA_OFFER" language="en_US">
+		<synopsis>
+			Media and codec offerings to be set on an outbound channel prior to dialing.
+		</synopsis>
+		<syntax>
+			<parameter name="media" required="true">
+				<para>types of media offered</para>
+			</parameter>
+		</syntax>
+		<description>
+			<para>Returns the codecs offered based upon the media choice</para>
+		</description>
+	</function>
  ***/
 
 static const char desc[] = "Gulp SIP Channel";
@@ -245,6 +258,159 @@
 	.read = gulp_dial_contacts,
 };
 
+struct media_offering {
+	const char *name;
+	int (*get)(struct ast_sip_session *, char *, size_t len);
+	int (*set)(struct ast_sip_session *, const char *);
+
+	AST_LIST_ENTRY(media_offering) next;
+};
+
+AST_RWLIST_HEAD_STATIC(media_offerings, media_offering);
+
+static int register_media_offering(struct media_offering *obj)
+{
+	SCOPED_LOCK(lock, &media_offerings, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
+	AST_RWLIST_INSERT_TAIL(&media_offerings, obj, next);
+	ast_module_ref(ast_module_info->self);
+	return 0;
+}
+
+static void unregister_media_offering(struct media_offering *obj)
+{
+	struct media_offering *i;
+	SCOPED_LOCK(lock, &media_offerings, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
+	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&media_offerings, i, next) {
+		if (obj == i) {
+			AST_RWLIST_REMOVE_CURRENT(next);
+			ast_module_unref(ast_module_info->self);
+			break;
+		}
+	}
+	AST_RWLIST_TRAVERSE_SAFE_END;
+}
+
+static int media_offer_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+{
+	struct gulp_pvt *pvt = ast_channel_tech_pvt(chan);
+	struct media_offering *i;
+
+	if (!pvt->session->outgoing_caps) {
+		return 0;
+	}
+
+	AST_LIST_TRAVERSE(&media_offerings, i, next) {
+		if (!strcmp(data, i->name) && i->get) {
+			return i->get(pvt->session, buf, len);
+		}
+	}
+
+	ast_log(LOG_WARNING, "Function %s: reading given media %s is not supported\n", cmd, data);
+	return 0;
+}
+
+static int media_offer_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
+{
+	struct gulp_pvt *pvt = ast_channel_tech_pvt(chan);
+	struct media_offering *i;
+
+	if (!pvt->session->outgoing_caps) {
+		pvt->session->outgoing_caps = ast_format_cap_alloc_nolock();
+	}
+
+	AST_LIST_TRAVERSE(&media_offerings, i, next) {
+		if (!strcmp(data, i->name) && i->set) {
+			return i->set(pvt->session, value);
+		}
+	}
+
+	ast_log(LOG_WARNING, "Function %s: writing given media %s is not supported\n", cmd, data);
+	return 0;
+}
+
+static struct ast_custom_function media_offer_function = {
+	.name = "MEDIA_OFFER",
+	.read = media_offer_read,
+	.write = media_offer_write
+};
+
+static int media_offer_av_get(struct ast_sip_session *session, char *buf, size_t len, enum ast_format_type media_type)
+{
+	struct ast_format fmt;
+	const char *name;
+	int size = 0;
+
+	ast_format_cap_iter_start(session->outgoing_caps);
+	while (!ast_format_cap_iter_next(session->outgoing_caps, &fmt)) {
+		if (AST_FORMAT_GET_TYPE(fmt.id) != media_type) {
+			continue;
+		}
+
+		name = ast_rtp_lookup_mime_subtype2(1, &fmt, 0, 0);
+
+		if (ast_strlen_zero(name)) {
+			continue;
+		}
+
+		/* add one since we'll include a comma */
+		size = strlen(name) + 1;
+		len -= size;
+		if ((len) < 0) {
+			break;
+		}
+		
+		strncat(buf, name, size);
+		strncat(buf, ",", 1);
+	}
+	ast_format_cap_iter_end(session->outgoing_caps);
+	
+	if (size) {
+		/* remove the extra comma */
+		buf[strlen(buf) - 1] = '\0';
+	}
+	return 0;
+}
+
+static int media_offer_av_set(struct ast_sip_session *session, const char *value, enum ast_format_type media_type)
+{
+	ast_format_cap_remove_bytype(session->outgoing_caps, media_type);
+	ast_parse_allow_disallow(NULL, session->outgoing_caps, value, 1);
+
+	return 0;
+}
+
+static int media_offer_audio_get(struct ast_sip_session *session, char *buf, size_t len)
+{
+	return media_offer_av_get(session, buf, len, AST_FORMAT_TYPE_AUDIO);
+}
+
+static int media_offer_audio_set(struct ast_sip_session *session, const char *value)
+{
+	return media_offer_av_set(session, value, AST_FORMAT_TYPE_AUDIO);
+}
+
+static struct media_offering audio_offering = {
+	.name = "audio",
+	.get = media_offer_audio_get,
+	.set = media_offer_audio_set
+};
+
+static int media_offer_video_get(struct ast_sip_session *session, char *buf, size_t len)
+{
+	return media_offer_av_get(session, buf, len, AST_FORMAT_TYPE_VIDEO);
+}
+
+static int media_offer_video_set(struct ast_sip_session *session, const char *value)
+{
+	return media_offer_av_set(session, value, AST_FORMAT_TYPE_VIDEO);
+}
+
+static struct media_offering video_offering = {
+	.name = "video",
+	.get = media_offer_video_get,
+	.set = media_offer_video_set
+};
+
 /*! \brief Function called by RTP engine to get local audio RTP peer */
 static enum ast_rtp_glue_result gulp_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
 {
@@ -851,7 +1017,7 @@
 		return -1;
 	}
 
-	ast_sip_session_send_request(session, packet);
+	ast_sip_session_send_request_with_sdp(session, packet);
 
 	ao2_ref(session, -1);
 	return 0;
@@ -1316,6 +1482,13 @@
 		goto end;
 	}
 
+	if (ast_custom_function_register(&media_offer_function)) {
+		ast_log(LOG_WARNING, "Unable to register MEDIA_OFFER dialplan function\n");
+	} else {
+		register_media_offering(&audio_offering);
+		register_media_offering(&video_offering);
+	}
+
 	if (ast_sip_session_register_supplement(&gulp_supplement)) {
 		ast_log(LOG_ERROR, "Unable to register Gulp supplement\n");
 		goto end;
@@ -1330,6 +1503,10 @@
 	return 0;
 
 end:
+	unregister_media_offering(&video_offering);
+	unregister_media_offering(&audio_offering);
+	ast_custom_function_unregister(&media_offer_function);
+
 	ast_custom_function_unregister(&gulp_dial_contacts_function);
 	ast_channel_unregister(&gulp_tech);
 	ast_rtp_glue_unregister(&gulp_rtp_glue);
@@ -1346,7 +1523,12 @@
 /*! \brief Unload the Gulp channel from Asterisk */
 static int unload_module(void)
 {
+	unregister_media_offering(&video_offering);
+	unregister_media_offering(&audio_offering);
+	ast_custom_function_unregister(&media_offer_function);
+
 	ast_sip_session_unregister_supplement(&gulp_supplement);
+
 	ast_custom_function_unregister(&gulp_dial_contacts_function);
 	ast_channel_unregister(&gulp_tech);
 	ast_rtp_glue_unregister(&gulp_rtp_glue);

Modified: team/kharwell/pimp_sip_media_neg/include/asterisk/res_sip_session.h
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_media_neg/include/asterisk/res_sip_session.h?view=diff&rev=384805&r1=384804&r2=384805
==============================================================================
--- team/kharwell/pimp_sip_media_neg/include/asterisk/res_sip_session.h (original)
+++ team/kharwell/pimp_sip_media_neg/include/asterisk/res_sip_session.h Thu Apr  4 17:57:30 2013
@@ -99,6 +99,8 @@
 	struct ast_format_cap *direct_media_cap;
 	/* Requested capabilities */
 	struct ast_format_cap *req_caps;
+	/* Capabilities set by dialplan for an outgoing request */
+	struct ast_format_cap *outgoing_caps;
 };
 
 typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *session, pjsip_tx_data *tdata);
@@ -436,6 +438,18 @@
 void ast_sip_session_send_request(struct ast_sip_session *session, pjsip_tx_data *tdata);
 
 /*!
+ * \brief Send a SIP request
+ *
+ * This will first create an sdp to add to the outgoing request and then will
+ * send the SIP request specified in tdata and call into any registered
+ * supplements' outgoing_request callback.
+ *
+ * \param session The session to which to send the request
+ * \param tdata The request to send
+ */
+void ast_sip_session_send_request_with_sdp(struct ast_sip_session *session, pjsip_tx_data *tdata);
+
+/*!
  * \brief Send a SIP request and get called back when a response is received
  *
  * This will send the request out exactly the same as ast_sip_send_request() does.

Modified: team/kharwell/pimp_sip_media_neg/res/res_sip_sdp_rtp.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_media_neg/res/res_sip_sdp_rtp.c?view=diff&rev=384805&r1=384804&r2=384805
==============================================================================
--- team/kharwell/pimp_sip_media_neg/res/res_sip_sdp_rtp.c (original)
+++ team/kharwell/pimp_sip_media_neg/res/res_sip_sdp_rtp.c Thu Apr  4 17:57:30 2013
@@ -557,7 +557,9 @@
 		return -1;
 	}
 
-	if (direct_media_enabled) {
+	if (!ast_format_cap_is_empty(session->outgoing_caps)) {
+		ast_format_cap_copy(caps, session->outgoing_caps);		
+	} else if (direct_media_enabled) {
 		ast_format_cap_joint_copy(session->endpoint->codecs, session->direct_media_cap, caps);
 	} else if (ast_format_cap_is_empty(session->req_caps)) {
 		ast_format_cap_copy(caps, session->endpoint->codecs);

Modified: team/kharwell/pimp_sip_media_neg/res/res_sip_session.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_media_neg/res/res_sip_session.c?view=diff&rev=384805&r1=384804&r2=384805
==============================================================================
--- team/kharwell/pimp_sip_media_neg/res/res_sip_session.c (original)
+++ team/kharwell/pimp_sip_media_neg/res/res_sip_session.c Thu Apr  4 17:57:30 2013
@@ -773,6 +773,18 @@
 	ast_sip_session_send_request_with_cb(session, tdata, NULL);
 }
 
+void ast_sip_session_send_request_with_sdp(struct ast_sip_session *session, pjsip_tx_data *tdata)
+{
+	pjmedia_sdp_session *offer = create_local_sdp(session->inv_session, session, NULL);
+
+	if (offer) {
+		pjsip_inv_set_local_sdp(session->inv_session, offer);
+		ast_sip_session_send_request(session, tdata);
+	} else {
+		pjsip_inv_terminate(session->inv_session, 500, PJ_FALSE);
+	}
+}
+
 /*!
  * \brief Called when the PJSIP core loads us
  *
@@ -872,6 +884,7 @@
 	}
 	ao2_cleanup(session->endpoint);
 	ast_format_cap_destroy(session->req_caps);
+	ast_format_cap_destroy(session->outgoing_caps);
 }
 
 static int add_supplements(struct ast_sip_session *session)
@@ -965,7 +978,6 @@
 	pjsip_dialog *dlg;
 	struct pjsip_inv_session *inv_session;
 	RAII_VAR(struct ast_sip_session *, session, NULL, ao2_cleanup);
-	pjmedia_sdp_session *offer;
 
 	/* If no location has been provided use the AOR list from the endpoint itself */
 	if (ast_strlen_zero(location)) {
@@ -1020,13 +1032,10 @@
 	}
 
 	ast_format_cap_copy(session->req_caps, req_caps);
-	if ((pjsip_dlg_add_usage(dlg, &session_module, NULL) != PJ_SUCCESS) ||
-	    !(offer = create_local_sdp(inv_session, session, NULL))) {
+	if ((pjsip_dlg_add_usage(dlg, &session_module, NULL) != PJ_SUCCESS)) {
 		pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
 		return NULL;
 	}
-
-	pjsip_inv_set_local_sdp(inv_session, offer);
 
 	ao2_ref(session, +1);
 	return session;




More information about the asterisk-commits mailing list