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

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Mar 6 16:41:11 CST 2013


Author: mmichelson
Date: Wed Mar  6 16:41:08 2013
New Revision: 382547

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=382547
Log:
Retransmit reinvite if a 491 response is received.

Tested with SIPp. This works fine as long as conditions
are nominal.

I've managed to come across a few situations that
result in Asterisk crashes because transaction state
handlers are not careful enough to make sure they don't
operate when in an invalid state.


Modified:
    team/mmichelson/direct_media/include/asterisk/res_sip_session.h
    team/mmichelson/direct_media/res/res_sip_session.c

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=382547&r1=382546&r2=382547
==============================================================================
--- team/mmichelson/direct_media/include/asterisk/res_sip_session.h (original)
+++ team/mmichelson/direct_media/include/asterisk/res_sip_session.h Wed Mar  6 16:41:08 2013
@@ -19,6 +19,8 @@
 #ifndef _RES_SIP_SESSION_H
 #define _RES_SIP_SESSION_H
 
+/* Needed for pj_timer_entry definition */
+#include "pjlib.h"
 #include "asterisk/linkedlists.h"
 /* Needed for AST_MAX_EXTENSION constant */
 #include "asterisk/channel.h"
@@ -95,6 +97,8 @@
 	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;
+	/* When we need to reschedule a reinvite, we use this structure to do it */
+	pj_timer_entry rescheduled_reinvite;
 };
 
 /*!

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=382547&r1=382546&r2=382547
==============================================================================
--- team/mmichelson/direct_media/res/res_sip_session.c (original)
+++ team/mmichelson/direct_media/res/res_sip_session.c Wed Mar  6 16:41:08 2013
@@ -555,6 +555,7 @@
 {
 	struct ast_sip_session *session = obj;
 	struct ast_sip_session_supplement *supplement;
+	struct ast_sip_session_delayed_request *delay;
 
 	ast_debug(3, "Destroying SIP session with endpoint %s\n",
 			S_OR(ast_sorcery_object_get_id(session->endpoint), "outbound"));
@@ -568,6 +569,9 @@
 	ast_taskprocessor_unreference(session->serializer);
 	ao2_cleanup(session->datastores);
 	AST_LIST_HEAD_DESTROY(&session->supplements);
+	while ((delay = AST_LIST_REMOVE_HEAD(&session->delayed_requests, next))) {
+		ast_free(delay);
+	}
 	ao2_cleanup(session->endpoint);
 }
 
@@ -969,6 +973,39 @@
 	return handled;
 }
 
+static int really_resend_reinvite(void *data)
+{
+	struct ast_sip_session *session = data;
+
+	ast_sip_session_send_reinvite(session, NULL);
+	ao2_ref(session, -1);
+	return 0;
+}
+
+static void resend_reinvite(pj_timer_heap_t *timer, pj_timer_entry *entry)
+{
+	struct ast_sip_session *session = entry->user_data;
+
+	ast_sip_push_task(session->serializer, really_resend_reinvite, session);
+}
+
+static void reschedule_reinvite(struct ast_sip_session *session)
+{
+	pjsip_inv_session *inv = session->inv_session;
+	pj_time_val tv;
+	tv.sec = 0;
+	if (inv->role == PJSIP_ROLE_UAC) {
+		tv.msec = 2100 + ast_random() % 2000;
+	} else {
+		tv.msec = ast_random() % 2000;
+	}
+
+	pj_timer_entry_init(&session->rescheduled_reinvite, 0, session, resend_reinvite);
+
+	ao2_ref(session, +1);
+	pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &session->rescheduled_reinvite, &tv);
+}
+
 static void session_on_tsx_state(pjsip_transaction *tsx, pjsip_event *event)
 {
 	pjsip_inv_session *inv;
@@ -976,11 +1013,19 @@
 	ast_log(LOG_NOTICE, "Just curious if we're getting called back? State is %s\n", pjsip_tsx_state_str(tsx->state));
 	dlg = pjsip_tsx_get_dlg(tsx);
 	inv = pjsip_dlg_get_inv_session(dlg);
-	if (tsx->method.id == PJSIP_INVITE_METHOD && tsx->state == PJSIP_TSX_STATE_TERMINATED) {
+	if (tsx->method.id == PJSIP_INVITE_METHOD) {
 		struct ast_sip_session *session = inv->mod_data[session_module.id];
-		queue_delayed_request(session);
-		if (session->endpoint->direct_media && session->channel) {
-			ast_queue_control(session->channel, AST_CONTROL_SRCCHANGE);
+		if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
+			queue_delayed_request(session);
+			if (session->endpoint->direct_media && session->channel) {
+				ast_queue_control(session->channel, AST_CONTROL_SRCCHANGE);
+			}
+		} else if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
+			/* This means we got a non 2XX final response to our outgoing INVITE */
+			if (tsx->status_code == PJSIP_SC_REQUEST_PENDING) {
+				reschedule_reinvite(session);
+			}
+			ast_log(LOG_NOTICE, "Hey, we got response %d for our INVITE\n", tsx->status_code);
 		}
 	}
 }




More information about the asterisk-commits mailing list