From 2d0b24743f4b1e5e6c5086cf09e74a32a9c9c741 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Mon, 15 Apr 2013 10:43:28 -0500
Subject: [PATCH] move callstate changes down to take place after the core
 states have run

---
 src/mod/endpoints/mod_sofia/mod_sofia.c |  2 ++
 src/switch_channel.c                    | 20 +++++++++++++++-----
 src/switch_core_state_machine.c         |  1 +
 3 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c
index 37f67deb41..5f70f4f9b6 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.c
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.c
@@ -542,6 +542,8 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
 					switch_snprintf(reason, sizeof(reason), "SIP;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause));
 				}
 			}
+
+			switch_channel_set_variable(channel, "call_completed_elsewhere", "true");
 		}
 
 		if (switch_channel_test_flag(channel, CF_ANSWERED) || sofia_test_flag(tech_pvt, TFLAG_ANS)) {
diff --git a/src/switch_channel.c b/src/switch_channel.c
index 27a5b24d7d..1ee95d0746 100644
--- a/src/switch_channel.c
+++ b/src/switch_channel.c
@@ -2393,6 +2393,11 @@ SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *chann
 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "ringing");
 	}
 
+	if (channel->hangup_cause) {
+		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hangup-Cause", switch_channel_cause2str(channel->hangup_cause));
+	}
+
+
 	switch_core_session_get_read_impl(channel->session, &impl);
 
 	if (impl.iananame) {
@@ -3060,7 +3065,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_chan
 		switch_mutex_unlock(channel->state_mutex);
 
 
-		switch_channel_set_callstate(channel, CCS_HANGUP);
+
 		channel->hangup_cause = hangup_cause;
 		switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Hangup %s [%s] [%s]\n",
 						  channel->name, state_names[last_state], switch_channel_cause2str(channel->hangup_cause));
@@ -3084,7 +3089,6 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_chan
 		}
 
 		if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HANGUP) == SWITCH_STATUS_SUCCESS) {
-			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hangup-Cause", switch_channel_cause2str(hangup_cause));
 			switch_channel_event_set_data(channel, event);
 			switch_event_fire(&event);
 		}
@@ -3106,7 +3110,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready_value(swi
 	if (!switch_channel_test_flag(channel, CF_RING_READY) && !switch_channel_test_flag(channel, CF_ANSWERED)) {
 		switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Ring-Ready %s!\n", channel->name);
 		switch_channel_set_flag_value(channel, CF_RING_READY, rv);
-		switch_channel_set_callstate(channel, CCS_RINGING);
+
 
 		if (channel->caller_profile && channel->caller_profile->times) {
 			switch_mutex_lock(channel->profile_mutex);
@@ -3134,6 +3138,8 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready_value(swi
 		switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_RING_VARIABLE);
 		switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_RING_VARIABLE);
 
+		switch_channel_set_callstate(channel, CCS_RINGING);
+
 		return SWITCH_STATUS_SUCCESS;
 	}
 
@@ -3210,7 +3216,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_pre_answered(switch_
 		switch_channel_check_zrtp(channel);
 		switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Pre-Answer %s!\n", channel->name);
 		switch_channel_set_flag(channel, CF_EARLY_MEDIA);
-		switch_channel_set_callstate(channel, CCS_EARLY);
+		
 		switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "EARLY MEDIA");
 
 		if (channel->caller_profile && channel->caller_profile->times) {
@@ -3256,6 +3262,8 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_pre_answered(switch_
 			switch_core_session_rwunlock(other_session);
 		}
 
+		switch_channel_set_callstate(channel, CCS_EARLY);
+
 		return SWITCH_STATUS_SUCCESS;
 	}
 
@@ -3473,7 +3481,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_answered(switch_chan
 
 	switch_channel_check_zrtp(channel);
 	switch_channel_set_flag(channel, CF_ANSWERED);
-	switch_channel_set_callstate(channel, CCS_ACTIVE);
+
 
 	if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_ANSWER) == SWITCH_STATUS_SUCCESS) {
 		switch_channel_event_set_data(channel, event);
@@ -3531,6 +3539,8 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_answered(switch_chan
 
 	switch_core_recovery_track(channel->session);
 
+	switch_channel_set_callstate(channel, CCS_ACTIVE);
+
 	return SWITCH_STATUS_SUCCESS;
 }
 
diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c
index 6cbf2d3f71..5281d912d6 100644
--- a/src/switch_core_state_machine.c
+++ b/src/switch_core_state_machine.c
@@ -684,6 +684,7 @@ SWITCH_DECLARE(void) switch_core_session_hangup_state(switch_core_session_t *ses
 		api_hook(session, hook_var, use_session);
 	}
 
+	switch_channel_set_callstate(session->channel, CCS_HANGUP);
 	switch_set_flag(session, SSF_HANGUP);
 
 }