[asterisk-commits] mmichelson: branch mmichelson/direct_media r382478 - in /team/mmichelson/dire...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Mar 5 17:37:52 CST 2013


Author: mmichelson
Date: Tue Mar  5 17:37:49 2013
New Revision: 382478

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=382478
Log:
Progress on direct media work.

For now, I'm operating with one simple setting: Allow or don't allow
direct media.

In my tests, there are some issues:

1) Transmission of the reinvites to the endpoints is inconsistent.
Sometimes no reinvites are sent. Sometimes a reinvite is sent to one
party. Sometimes reinvites are sent to both parties.

2) In the case where any reinvites are sent, then when the call ends,
Asterisk crashes. It appears to be due to the fact that a reinvite is
sent to a party immediately followed by a BYE. This makes it so that
when the 200 OK for the reinvite arrives, we access data that has been
released already.


Modified:
    team/mmichelson/direct_media/channels/chan_gulp.c
    team/mmichelson/direct_media/include/asterisk/res_sip.h
    team/mmichelson/direct_media/include/asterisk/res_sip_session.h
    team/mmichelson/direct_media/res/res_sip/sip_configuration.c
    team/mmichelson/direct_media/res/res_sip_sdp_audio.c
    team/mmichelson/direct_media/res/res_sip_session.c

Modified: team/mmichelson/direct_media/channels/chan_gulp.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/direct_media/channels/chan_gulp.c?view=diff&rev=382478&r1=382477&r2=382478
==============================================================================
--- team/mmichelson/direct_media/channels/chan_gulp.c (original)
+++ team/mmichelson/direct_media/channels/chan_gulp.c Tue Mar  5 17:37:49 2013
@@ -112,14 +112,26 @@
 static enum ast_rtp_glue_result gulp_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
 {
 	struct ast_sip_session *session = ast_channel_tech_pvt(chan);
+	struct ast_sip_endpoint *endpoint = session->endpoint;
+
+	ast_log(LOG_NOTICE, "Trying the get_rtp_peer method for endpoint %s\n", ast_sorcery_object_get_id(endpoint));
 
 	if (!session || !session->media[AST_SIP_MEDIA_AUDIO].rtp) {
+		ast_log(LOG_NOTICE, "Big time failure for direct media...\n");
 		return AST_RTP_GLUE_RESULT_FORBID;
 	}
 
 	ao2_ref(session->media[AST_SIP_MEDIA_AUDIO].rtp, +1);
 	*instance = session->media[AST_SIP_MEDIA_AUDIO].rtp;
 
+	ast_assert(endpoint != NULL);
+	if (endpoint->direct_media) {
+		ast_log(LOG_NOTICE, "Saying that remote bridging will work\n");
+		return AST_RTP_GLUE_RESULT_REMOTE;
+	}
+
+	ast_log(LOG_NOTICE, "Remote bridgin won't work...\n");
+
 	return AST_RTP_GLUE_RESULT_LOCAL;
 }
 
@@ -128,10 +140,63 @@
 {
 }
 
+static int send_direct_media_reinvite(void *data)
+{
+	RAII_VAR(struct ast_sip_session *, session, data, ao2_cleanup);
+
+	ast_log(LOG_NOTICE, "Should be calling method to send a reinvite now\n");
+
+	return ast_sip_session_send_reinvite(session, NULL);
+}
+
 /*! \brief Function called by RTP engine to change where the remote party should send media */
-static int gulp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *tpeer, const struct ast_format_cap *cap, int nat_active)
-{
-	return -1;
+static int gulp_set_rtp_peer(struct ast_channel *chan,
+		struct ast_rtp_instance *rtp,
+		struct ast_rtp_instance *vrtp,
+		struct ast_rtp_instance *tpeer,
+		const struct ast_format_cap *cap,
+		int nat_active)
+{
+	/* We can figure out whether we need to send the reinvite in this
+	 * function. We ultimately will push a task in the session's serializer
+	 * to send the reinvite out.
+	 */
+	struct ast_sip_session *session = ast_channel_tech_pvt(chan);
+	int changed = 0;
+
+	ast_log(LOG_NOTICE, "Are we getting told to send a reinvite?\n");
+
+	if (rtp) {
+		struct ast_sip_session_media *audio = &session->media[AST_SIP_MEDIA_AUDIO];
+		changed = ast_rtp_instance_get_and_cmp_remote_address(rtp, &audio->direct_media_addr);
+		if (audio->rtp) {
+			ast_channel_lock(chan);
+			ast_channel_set_fd(chan, 1, -1);
+			ast_channel_unlock(chan);
+			ast_rtp_instance_set_prop(audio->rtp, AST_RTP_PROPERTY_RTCP, 0);
+		}
+	} else {
+		struct ast_sip_session_media *audio = &session->media[AST_SIP_MEDIA_AUDIO];
+		ast_sockaddr_setnull(&audio->direct_media_addr);
+		changed = 1;
+		if (audio->rtp) {
+			ast_rtp_instance_set_prop(audio->rtp, AST_RTP_PROPERTY_RTCP, 1);
+			ast_channel_lock(chan);
+			ast_channel_set_fd(chan, 1, ast_rtp_instance_fd(audio->rtp, 1));
+			ast_channel_unlock(chan);
+		}
+	}
+
+	if (changed) {
+		/* Queue a reinvite to be sent. We'll care about
+		 * transaction states and the like once the task
+		 * comes up
+		 */
+		ao2_ref(session, +1);
+		ast_sip_push_task(session->serializer, send_direct_media_reinvite, session);
+	}
+
+	return 0;
 }
 
 /*! \brief Local glue for interacting with the RTP engine core */
@@ -665,6 +730,7 @@
 	ast_parse_allow_disallow(&endpoint->prefs, endpoint->codecs, "ulaw", 1);
 	endpoint->min_se = 90;
 	endpoint->sess_expires = 1800;
+	endpoint->direct_media = 1;
 
 	if (!(session = ast_sip_session_create_outgoing(endpoint, req_data->dest))) {
 		return -1;

Modified: team/mmichelson/direct_media/include/asterisk/res_sip.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/direct_media/include/asterisk/res_sip.h?view=diff&rev=382478&r1=382477&r2=382478
==============================================================================
--- team/mmichelson/direct_media/include/asterisk/res_sip.h (original)
+++ team/mmichelson/direct_media/include/asterisk/res_sip.h Tue Mar  5 17:37:49 2013
@@ -260,6 +260,8 @@
 	unsigned int qualify_frequency;
 	/*! Method(s) by which the endpoint should be identified. */
 	enum ast_sip_endpoint_identifier_type ident_method;
+	/*! Boolean indicating if direct_media is permissible */
+	unsigned int direct_media;
 };
 
 /*!

Modified: team/mmichelson/direct_media/include/asterisk/res_sip_session.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/direct_media/include/asterisk/res_sip_session.h?view=diff&rev=382478&r1=382477&r2=382478
==============================================================================
--- team/mmichelson/direct_media/include/asterisk/res_sip_session.h (original)
+++ team/mmichelson/direct_media/include/asterisk/res_sip_session.h Tue Mar  5 17:37:49 2013
@@ -22,6 +22,8 @@
 #include "asterisk/linkedlists.h"
 /* Needed for AST_MAX_EXTENSION constant */
 #include "asterisk/channel.h"
+/* Needed for ast_sockaddr struct */
+#include "asterisk/netsock.h"
 
 /* Forward declarations */
 struct ast_sip_endpoint;
@@ -55,8 +57,15 @@
 struct ast_sip_session_media {
 	/*! \brief RTP instance itself */
 	struct ast_rtp_instance *rtp;
+	/*! \brief Direct media address */
+	struct ast_sockaddr direct_media_addr;
 	/*! \brief Stream is on hold */
 	unsigned int held:1;
+};
+
+struct ast_sip_session_delayed_request {
+	char method[15];
+	AST_LIST_ENTRY(ast_sip_session_delayed_request) next;
 };
 
 /*!
@@ -84,6 +93,8 @@
 	struct ast_sip_session_media media[AST_SIP_MEDIA_SIZE];
 	/* Serializer for tasks relating to this SIP session */
 	struct ast_taskprocessor *serializer;
+	/* Requests that could not be sent due to current inv_session state */
+	AST_LIST_HEAD_NOLOCK(, ast_sip_session_delayed_request) delayed_requests;
 };
 
 /*!

Modified: team/mmichelson/direct_media/res/res_sip/sip_configuration.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/direct_media/res/res_sip/sip_configuration.c?view=diff&rev=382478&r1=382477&r2=382478
==============================================================================
--- team/mmichelson/direct_media/res/res_sip/sip_configuration.c (original)
+++ team/mmichelson/direct_media/res/res_sip/sip_configuration.c Tue Mar  5 17:37:49 2013
@@ -307,6 +307,7 @@
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "timers_sess_expires", "1800", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, sess_expires));
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "auth", "", auth_handler, NULL, 0, 0);
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "identify_by", "username,location", ident_handler, NULL, 0, 0);
+	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "direct_media", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, direct_media));
 
 	if (ast_sip_initialize_sorcery_transport(sip_sorcery)) {
 		ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");

Modified: team/mmichelson/direct_media/res/res_sip_sdp_audio.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/direct_media/res/res_sip_sdp_audio.c?view=diff&rev=382478&r1=382477&r2=382478
==============================================================================
--- team/mmichelson/direct_media/res/res_sip_sdp_audio.c (original)
+++ team/mmichelson/direct_media/res/res_sip_sdp_audio.c Tue Mar  5 17:37:49 2013
@@ -167,7 +167,11 @@
 	media->desc.transport = STR_RTP_AVP;
 
 	/* Add connection level details */
-	ast_rtp_instance_get_local_address(session->media[AST_SIP_MEDIA_AUDIO].rtp, &addr);
+	if (!ast_sockaddr_isnull(&session->media[AST_SIP_MEDIA_AUDIO].direct_media_addr)) {
+		ast_sockaddr_copy(&addr, &session->media[AST_SIP_MEDIA_AUDIO].direct_media_addr);
+	} else {
+		ast_rtp_instance_get_local_address(session->media[AST_SIP_MEDIA_AUDIO].rtp, &addr);
+	}
 	media->conn->net_type = STR_IN;
 	media->conn->addr_type = (ast_sockaddr_is_ipv6(&addr) && !ast_sockaddr_is_ipv4_mapped(&addr)) ? STR_IP6 : STR_IP4;
 	pj_strdup2(pool, &media->conn->addr, ast_sockaddr_stringify_addr_remote(&addr));

Modified: team/mmichelson/direct_media/res/res_sip_session.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/direct_media/res/res_sip_session.c?view=diff&rev=382478&r1=382477&r2=382478
==============================================================================
--- team/mmichelson/direct_media/res/res_sip_session.c (original)
+++ team/mmichelson/direct_media/res/res_sip_session.c Tue Mar  5 17:37:49 2013
@@ -349,9 +349,72 @@
 	return 0;
 }
 
+static void send_delayed_request(struct ast_sip_session *session)
+{
+	struct ast_sip_session_delayed_request *delay;
+
+	delay = AST_LIST_REMOVE_HEAD(&session->delayed_requests, next);
+	if (!delay) {
+		/* No delayed request to send, so just return */
+		return;
+	}
+
+	ast_log(LOG_NOTICE, "Sending delayed %s message to %s\n", delay->method, ast_sorcery_object_get_id(session->endpoint));
+
+	if (!strcmp(delay->method, "INVITE")) {
+		ast_sip_session_send_reinvite(session, NULL);
+	} else if (!strcmp(delay->method, "BYE")) {
+		pjsip_tx_data *tdata;
+		pjsip_inv_end_session(session->inv_session, 500, 0, &tdata);
+		ast_sip_session_send_request(session, tdata);
+	}
+	ast_free(delay);
+	return;
+}
+
+static int delay_request(struct ast_sip_session *session, const char *method)
+{
+	struct ast_sip_session_delayed_request *delay = ast_calloc(1, sizeof(*delay));
+	if (!delay) {
+		return -1;
+	}
+	ast_copy_string(delay->method, method, sizeof(delay->method));
+	AST_LIST_INSERT_TAIL(&session->delayed_requests, delay, next);
+	return 0;
+}
+
 int ast_sip_session_send_reinvite(struct ast_sip_session *session, int (*response_cb)(struct ast_sip_session *session, struct pjsip_rx_data *rdata))
 {
-	/* XXX STUB */
+	pjsip_inv_session *inv_session = session->inv_session;
+	pjmedia_sdp_session *reinvite_sdp;
+	const pjmedia_sdp_session *last_sdp;
+	pjsip_tx_data *tdata;
+
+	if (inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
+		/* Don't try to do anything with a hung-up call */
+		ast_log(LOG_NOTICE, "Not sending because of disconnected state...\n");
+		return 0;
+	}
+
+	if (inv_session->invite_tsx) {
+		/* We can't send a reinvite yet, so delay it */
+		ast_log(LOG_NOTICE, "Delaying sending reinvite...\n");
+		return delay_request(session, "INVITE");
+	}
+
+	ast_log(LOG_NOTICE, "Out of curiosity, the inv state is %s\n", pjsip_inv_state_name(inv_session->state));
+
+	if (pjmedia_sdp_neg_was_answer_remote(inv_session->neg)) {
+		pjmedia_sdp_neg_get_active_remote(inv_session->neg, &last_sdp);
+	} else {
+		pjmedia_sdp_neg_get_active_local(inv_session->neg, &last_sdp);
+	}
+	reinvite_sdp = create_local_sdp(inv_session, session, last_sdp);
+	if (pjsip_inv_reinvite(inv_session, NULL, reinvite_sdp, &tdata)) {
+		ast_log(LOG_NOTICE, "Failing to create reinvite properly?\n");
+		return 0;
+	}
+	ast_sip_session_send_request(session, tdata);
 	return 0;
 }
 
@@ -364,6 +427,21 @@
 
 void ast_sip_session_send_request(struct ast_sip_session *session, pjsip_tx_data *tdata)
 {
+	pjsip_inv_session *inv_session = session->inv_session;
+
+	if (inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
+		/* Don't try to do anything with a hung-up call */
+		ast_log(LOG_NOTICE, "Not sending because of disconnected state...\n");
+		return;
+	}
+
+	if (inv_session->invite_tsx) {
+		/* We can't send a request yet, so delay it */
+		char method[15];
+		ast_log(LOG_NOTICE, "Delaying sending reinvite...\n");
+		ast_copy_pj_str(method, &tdata->msg->line.req.method.name, sizeof(method));
+		delay_request(session, method);
+	}
 	handle_outgoing_request(session, tdata);
 	pjsip_inv_send_msg(session->inv_session, tdata);
 	return;
@@ -515,6 +593,7 @@
 		}
 	}
 	inv_session->mod_data[session_module.id] = session;
+	AST_LIST_HEAD_INIT_NOLOCK(&session->delayed_requests);
 	ao2_ref(session, +1);
 	return session;
 }
@@ -1021,6 +1100,11 @@
 	if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
 		session_end(session);
 	}
+
+	if (inv->state == PJSIP_INV_STATE_CONFIRMED) {
+		/* We may have a delayed request to send */
+		send_delayed_request(session);
+	}
 }
 
 static void session_inv_on_new_session(pjsip_inv_session *inv, pjsip_event *e)




More information about the asterisk-commits mailing list