[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