[asterisk-commits] file: branch file/pimp_sip_media r380849 - in /team/file/pimp_sip_media: incl...
SVN commits to the Asterisk project
asterisk-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 asterisk-commits
mailing list