From 307b0ffad8b5d9804562a7bf2034b549ece17aa5 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthony.minessale@gmail.com>
Date: Tue, 1 Apr 2008 00:38:40 +0000
Subject: [PATCH] update

git-svn-id: http://svn.openzap.org/svn/openzap/trunk@430 a93c3328-9c30-0410-af19-c9cd2b2d52af
---
 libs/openzap/mod_openzap/mod_openzap.c |  2 +
 libs/openzap/src/include/openzap.h     |  2 +
 libs/openzap/src/ss7_boost_client.c    |  2 +
 libs/openzap/src/zap_io.c              | 13 +++++
 libs/openzap/src/zap_ss7_boost.c       | 66 +++++++++++++++++++-------
 5 files changed, 67 insertions(+), 18 deletions(-)

diff --git a/libs/openzap/mod_openzap/mod_openzap.c b/libs/openzap/mod_openzap/mod_openzap.c
index 64d19abdec..d0002ebd16 100644
--- a/libs/openzap/mod_openzap/mod_openzap.c
+++ b/libs/openzap/mod_openzap/mod_openzap.c
@@ -333,6 +333,8 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
 	globals.calls++;
 	switch_mutex_unlock(globals.mutex);
 
+	zap_channel_init(tech_pvt->zchan);
+
 	return SWITCH_STATUS_SUCCESS;
 }
 
diff --git a/libs/openzap/src/include/openzap.h b/libs/openzap/src/include/openzap.h
index 2a02885da2..4cdd259fb8 100644
--- a/libs/openzap/src/include/openzap.h
+++ b/libs/openzap/src/include/openzap.h
@@ -358,6 +358,7 @@ struct zap_channel {
 	uint32_t packet_len;
 	zap_channel_state_t state;
 	zap_channel_state_t last_state;
+	zap_channel_state_t init_state;
 	zap_mutex_t *mutex;
 	teletone_dtmf_detect_state_t dtmf_detect;
 	uint32_t buffer_delay;
@@ -538,6 +539,7 @@ int zap_hash_equalkeys(void *k1, void *k2);
 uint32_t zap_hash_hashfromstring(void *ky);
 uint32_t zap_running(void);
 zap_status_t zap_channel_complete_state(zap_channel_t *zchan);
+zap_status_t zap_channel_init(zap_channel_t *zchan);
 
 ZIO_CODEC_FUNCTION(zio_slin2ulaw);
 ZIO_CODEC_FUNCTION(zio_ulaw2slin);
diff --git a/libs/openzap/src/ss7_boost_client.c b/libs/openzap/src/ss7_boost_client.c
index 53a8c8e726..21690506b1 100644
--- a/libs/openzap/src/ss7_boost_client.c
+++ b/libs/openzap/src/ss7_boost_client.c
@@ -135,6 +135,8 @@ int ss7bc_connection_close(ss7bc_connection_t *mcon)
 		close(mcon->socket);
 	}
 
+	zap_mutex_lock(mcon->mutex);
+	zap_mutex_unlock(mcon->mutex);
 	zap_mutex_destroy(&mcon->mutex);
 	memset(mcon, 0, sizeof(*mcon));
 	mcon->socket = -1;
diff --git a/libs/openzap/src/zap_io.c b/libs/openzap/src/zap_io.c
index b54bacbb26..7be39a47b6 100644
--- a/libs/openzap/src/zap_io.c
+++ b/libs/openzap/src/zap_io.c
@@ -722,6 +722,7 @@ zap_status_t zap_channel_open_any(uint32_t span_id, zap_direction_t direction, c
 	}
 
 	if (span_id && globals.spans[span_id].channel_request) {
+		zap_mutex_unlock(globals.mutex);
 		status = globals.spans[span_id].channel_request(&globals.spans[span_id], direction, caller_data, zchan);
 		goto done;
 	}
@@ -846,6 +847,16 @@ static zap_status_t zap_channel_reset(zap_channel_t *zchan)
 	return ZAP_SUCCESS;
 }
 
+zap_status_t zap_channel_init(zap_channel_t *zchan)
+{
+	if (zchan->init_state != ZAP_CHANNEL_STATE_DOWN) {
+		zap_set_state_locked(zchan, zchan->init_state);
+		zchan->init_state = ZAP_CHANNEL_STATE_DOWN;
+	}
+
+	return ZAP_SUCCESS;
+}
+
 zap_status_t zap_channel_open_chan(zap_channel_t *zchan)
 {
 	zap_status_t status = ZAP_FAIL;
@@ -960,6 +971,8 @@ zap_status_t zap_channel_done(zap_channel_t *zchan)
 	zap_clear_flag_locked(zchan, ZAP_CHANNEL_PROGRESS);
 	zap_clear_flag_locked(zchan, ZAP_CHANNEL_MEDIA);
 	zap_clear_flag_locked(zchan, ZAP_CHANNEL_ANSWERED);
+	zchan->init_state = ZAP_CHANNEL_STATE_DOWN;
+	zap_log(ZAP_LOG_DEBUG, "channel done %u:%u\n", zchan->span_id, zchan->chan_id);
 
 	return ZAP_SUCCESS;
 }
diff --git a/libs/openzap/src/zap_ss7_boost.c b/libs/openzap/src/zap_ss7_boost.c
index 4b0c33a488..fac6cf9840 100644
--- a/libs/openzap/src/zap_ss7_boost.c
+++ b/libs/openzap/src/zap_ss7_boost.c
@@ -101,7 +101,7 @@ static zap_channel_t *find_zchan(zap_span_t *span, ss7bc_event_t *event, int for
 			if (force) {
 				break;
 			}
-			if (zap_test_flag(zchan, ZAP_CHANNEL_INUSE)) {
+			if (zap_test_flag(zchan, ZAP_CHANNEL_INUSE) || zchan->state != ZAP_CHANNEL_STATE_DOWN) {
 				if (zchan->state == ZAP_CHANNEL_STATE_DOWN || zchan->state >= ZAP_CHANNEL_STATE_TERMINATING) {
 					int x = 0;
 					zap_log(ZAP_LOG_WARNING, "Channel %d:%d ~ %d:%d is already in use waiting for it to become available.\n");
@@ -182,6 +182,7 @@ static ZIO_CHANNEL_REQUEST_FUNCTION(ss7_boost_channel_request)
 	if (OUTBOUND_REQUESTS[r].status == BST_READY && OUTBOUND_REQUESTS[r].zchan) {
 		*zchan = OUTBOUND_REQUESTS[r].zchan;
 		status = ZAP_SUCCESS;
+		(*zchan)->init_state = ZAP_CHANNEL_STATE_PROGRESS_MEDIA;
 	} else {
 		status = ZAP_FAIL;
         *zchan = NULL;
@@ -206,16 +207,16 @@ static void handle_call_start_ack(ss7bc_connection_t *mcon, ss7bc_event_t *event
 
 	OUTBOUND_REQUESTS[event->call_setup_id].event = *event;
 
-	if ((zchan = find_zchan(OUTBOUND_REQUESTS[event->call_setup_id].span, event, 1))) {
-		OUTBOUND_REQUESTS[event->call_setup_id].status = BST_READY;
+	if ((zchan = find_zchan(OUTBOUND_REQUESTS[event->call_setup_id].span, event, 0))) {
 		if (zap_channel_open_chan(zchan) != ZAP_SUCCESS) {
 			zap_log(ZAP_LOG_ERROR, "OPEN ERROR [%s]\n", zchan->last_error);
 			release_request_id(event->call_setup_id);
 		} else {
-			zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_PROGRESS_MEDIA);
 			zap_set_flag(zchan, ZAP_CHANNEL_OUTBOUND);
+			zap_set_flag_locked(zchan, ZAP_CHANNEL_INUSE);
 			zchan->extra_id = event->call_setup_id;
 			OUTBOUND_REQUESTS[event->call_setup_id].zchan = zchan;
+			OUTBOUND_REQUESTS[event->call_setup_id].status = BST_READY;
 			return;
 		}
 	} 
@@ -243,17 +244,30 @@ static void handle_call_done(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_e
 	}
 }
 
-static void handle_call_start_nack(ss7bc_connection_t *mcon, ss7bc_event_t *event)
+static void handle_call_start_nack(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event)
 {
-	OUTBOUND_REQUESTS[event->call_setup_id].event = *event;
-	OUTBOUND_REQUESTS[event->call_setup_id].status = BST_FAIL;
-	release_request_id(event->call_setup_id);
-	ss7bc_exec_command(mcon,
-					   event->span,
-					   event->chan,
-					   event->call_setup_id,
-					   SIGBOOST_EVENT_CALL_START_NACK_ACK,
-					   0);
+	
+	if (event->call_setup_id) {
+		OUTBOUND_REQUESTS[event->call_setup_id].event = *event;
+		OUTBOUND_REQUESTS[event->call_setup_id].status = BST_FAIL;
+
+		ss7bc_exec_command(mcon,
+						   event->span,
+						   event->chan,
+						   event->call_setup_id,
+						   SIGBOOST_EVENT_CALL_START_NACK_ACK,
+						   0);
+
+		release_request_id(event->call_setup_id);
+	} else {
+		zap_channel_t *zchan;
+		if ((zchan = find_zchan(span, event, 1))) {
+			assert(!zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND));
+			zchan->caller_data.hangup_cause = event->release_cause;
+			zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_TERMINATING);
+		}
+	}
+
 }
 
 static void handle_call_stop(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event)
@@ -281,6 +295,7 @@ static void handle_call_answer(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc
 	zap_channel_t *zchan;
 	
 	if ((zchan = find_zchan(span, event, 1))) {
+		assert(zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND));
 		zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_UP);
 	} else {
 		zap_log(ZAP_LOG_CRIT, "ANSWER CANT FIND A CHAN %d:%d\n", event->span+1,event->chan+1);
@@ -351,6 +366,12 @@ static void handle_restart_ack(ss7bc_connection_t *mcon, zap_span_t *span, ss7bc
 static int parse_ss7_event(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event)
 {
 	zap_mutex_lock(signal_mutex);
+	
+	if (!zap_running()) {
+		zap_log(ZAP_LOG_WARNING, "System is shutting down.\n");
+		goto end;
+	}
+
 
 	if (zap_test_flag(span, ZAP_SPAN_SUSPENDED) && 
 		event->event_id != SIGBOOST_EVENT_SYSTEM_RESTART_ACK && event->event_id != SIGBOOST_EVENT_HEARTBEAT) {
@@ -399,7 +420,7 @@ static int parse_ss7_event(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_eve
 		handle_call_start_ack(mcon, event);
 		break;
     case SIGBOOST_EVENT_CALL_START_NACK:
-		handle_call_start_nack(mcon, event);
+		handle_call_start_nack(span, mcon, event);
 		break;
     case SIGBOOST_EVENT_CALL_ANSWERED:
 		handle_call_answer(span, mcon, event);
@@ -506,7 +527,6 @@ static __inline__ void state_advance(zap_channel_t *zchan)
 					zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP);
 				}
 			} else {
-
 				if (!(zap_test_flag(zchan, ZAP_CHANNEL_PROGRESS) || zap_test_flag(zchan, ZAP_CHANNEL_MEDIA))) {
 					ss7bc_exec_command(mcon,
 									   zchan->physical_span_id-1,
@@ -536,7 +556,7 @@ static __inline__ void state_advance(zap_channel_t *zchan)
 		break;
 	case ZAP_CHANNEL_STATE_HANGUP:
 		{
-			if (zap_test_flag(zchan, ZAP_CHANNEL_ANSWERED)) {
+			if (zap_test_flag(zchan, ZAP_CHANNEL_ANSWERED) || zap_test_flag(zchan, ZAP_CHANNEL_PROGRESS) || zap_test_flag(zchan, ZAP_CHANNEL_MEDIA)) {
 				ss7bc_exec_command(mcon,
 								   zchan->physical_span_id-1,
 								   zchan->physical_chan_id-1,
@@ -627,11 +647,21 @@ static void *zap_ss7_boost_run(zap_thread_t *me, void *obj)
 					   SIGBOOST_EVENT_SYSTEM_RESTART,
 					   0);
 	
-	while (zap_running() && zap_test_flag(ss7_boost_data, ZAP_SS7_BOOST_RUNNING)) {
+	while (zap_test_flag(ss7_boost_data, ZAP_SS7_BOOST_RUNNING)) {
 		fd_set rfds, efds;
 		struct timeval tv = { 0, ms * 1000 };
 		int max, activity, i = 0;
 		ss7bc_event_t *event = NULL;
+		
+		if (!zap_running()) {
+			ss7bc_exec_command(mcon,
+							   0,
+							   0,
+							   -1,
+							   SIGBOOST_EVENT_SYSTEM_RESTART,
+							   0);
+			break;
+		}
 
 		FD_ZERO(&rfds);
 		FD_ZERO(&efds);