ZAP_CHANNEL_STATE_IDLE,
ZAP_CHANNEL_STATE_TERMINATING,
ZAP_CHANNEL_STATE_HANGUP,
+ ZAP_CHANNEL_STATE_HANGUP_COMPLETE,
ZAP_CHANNEL_STATE_INVALID
} zap_channel_state_t;
#define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \
"RING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \
- "RESTART", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "HANGUP", "INVALID"
+ "RESTART", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "HANGUP", "HANGUP_COMPLETE", "INVALID"
ZAP_STR2ENUM_P(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t)
typedef enum {
}
+zap_status_t zap_channel_complete_state(zap_channel_t *zchan)
+{
+ zap_channel_state_t state = zchan->state;
+
+ if (state == ZAP_CHANNEL_STATE_PROGRESS) {
+ zap_set_flag(zchan, ZAP_CHANNEL_PROGRESS);
+ } else if (state == ZAP_CHANNEL_STATE_UP) {
+ zap_set_flag(zchan, ZAP_CHANNEL_PROGRESS);
+ zap_set_flag(zchan, ZAP_CHANNEL_MEDIA);
+ zap_set_flag(zchan, ZAP_CHANNEL_ANSWERED);
+ } else if (state == ZAP_CHANNEL_STATE_PROGRESS_MEDIA) {
+ zap_set_flag(zchan, ZAP_CHANNEL_PROGRESS);
+ zap_set_flag(zchan, ZAP_CHANNEL_MEDIA);
+ }
+
+ return ZAP_SUCCESS;
+}
+
+
zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t state)
{
int ok = 1;
}
if (ok) {
- if (state == ZAP_CHANNEL_STATE_PROGRESS) {
- zap_set_flag(zchan, ZAP_CHANNEL_PROGRESS);
- } else if (state == ZAP_CHANNEL_STATE_UP) {
- zap_set_flag(zchan, ZAP_CHANNEL_PROGRESS);
- zap_set_flag(zchan, ZAP_CHANNEL_MEDIA);
- zap_set_flag(zchan, ZAP_CHANNEL_ANSWERED);
- } else if (state == ZAP_CHANNEL_STATE_PROGRESS_MEDIA) {
- zap_set_flag(zchan, ZAP_CHANNEL_PROGRESS);
- zap_set_flag(zchan, ZAP_CHANNEL_MEDIA);
- }
-
if (zchan->state == ZAP_CHANNEL_STATE_DOWN) {
zchan->span->active_count++;
} else if (state == ZAP_CHANNEL_STATE_DOWN) {
return r + 1;
}
-static zap_channel_t *find_zchan(zap_span_t *span, ss7bc_event_t *event)
+static zap_channel_t *find_zchan(zap_span_t *span, ss7bc_event_t *event, int force)
{
int i;
zap_channel_t *zchan = NULL;
for(i = 0; i <= span->chan_count; i++) {
if (span->channels[i].physical_span_id == event->span+1 && span->channels[i].physical_chan_id == event->chan+1) {
zchan = &span->channels[i];
+ if (force) {
+ break;
+ }
if (zap_test_flag(zchan, ZAP_CHANNEL_INUSE)) {
if (zchan->state == ZAP_CHANNEL_STATE_DOWN || zchan->state >= ZAP_CHANNEL_STATE_TERMINATING) {
int x = 0;
break;
}
}
+
zap_mutex_unlock(signal_mutex);
return zchan;
OUTBOUND_REQUESTS[event->call_setup_id].event = *event;
- if ((zchan = find_zchan(OUTBOUND_REQUESTS[event->call_setup_id].span, event))) {
+ if ((zchan = find_zchan(OUTBOUND_REQUESTS[event->call_setup_id].span, event, 1))) {
OUTBOUND_REQUESTS[event->call_setup_id].status = BST_READY;
if (zap_channel_open_chan(zchan) != ZAP_SUCCESS) {
zap_log(ZAP_LOG_ERROR, "OPEN ERROR [%s]\n", zchan->last_error);
}
+static void handle_call_done(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event)
+{
+ zap_channel_t *zchan;
+
+ if ((zchan = find_zchan(span, event, 1))) {
+
+ zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
+ } else {
+ zap_log(ZAP_LOG_CRIT, "DONE CANT FIND A CHAN %d:%d\n", event->span+1,event->chan+1);
+ }
+}
+
static void handle_call_start_nack(ss7bc_connection_t *mcon, ss7bc_event_t *event)
{
OUTBOUND_REQUESTS[event->call_setup_id].event = *event;
{
zap_channel_t *zchan;
- if ((zchan = find_zchan(span, event))) {
+ if ((zchan = find_zchan(span, event, 1))) {
zchan->caller_data.hangup_cause = event->release_cause;
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_TERMINATING);
} else {
{
zap_channel_t *zchan;
- if ((zchan = find_zchan(span, event))) {
+ if ((zchan = find_zchan(span, event, 1))) {
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);
{
zap_channel_t *zchan;
- if (!(zchan = find_zchan(span, event))) {
+ if (!(zchan = find_zchan(span, event, 0))) {
goto error;
}
case SIGBOOST_EVENT_HEARTBEAT:
handle_heartbeat(mcon, event);
break;
- case SIGBOOST_EVENT_CALL_START_NACK_ACK:
- //handle_call_start_nack_ack(event);
- break;
case SIGBOOST_EVENT_CALL_STOPPED_ACK:
- //handle_call_stop_ack(event);
+ case SIGBOOST_EVENT_CALL_START_NACK_ACK:
+ handle_call_done(span, mcon, event);
break;
case SIGBOOST_EVENT_INSERT_CHECK_LOOP:
//handle_call_loop_start(event);
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP);
}
} else {
-
+ ss7bc_exec_command(mcon,
+ zchan->physical_span_id-1,
+ zchan->physical_chan_id-1,
+ 0,
+ SIGBOOST_EVENT_CALL_START_ACK,
+ 0);
}
}
break;
break;
case ZAP_CHANNEL_STATE_RESTART:
{
- if (zchan->last_state > ZAP_CHANNEL_STATE_HANGUP) {
+ if (zchan->last_state != ZAP_CHANNEL_STATE_HANGUP && zchan->last_state != ZAP_CHANNEL_STATE_DOWN) {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP);
} else {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP);
}
} else {
- ss7bc_exec_command(mcon,
- zchan->physical_span_id-1,
- zchan->physical_chan_id-1,
- 0,
- SIGBOOST_EVENT_CALL_START_ACK,
- 0);
+
+ if (!(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,
+ 0,
+ SIGBOOST_EVENT_CALL_START_ACK,
+ 0);
+ }
ss7bc_exec_command(mcon,
zchan->physical_span_id-1,
{
}
break;
+ case ZAP_CHANNEL_STATE_HANGUP_COMPLETE:
+ {
+ zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
+ }
+ break;
case ZAP_CHANNEL_STATE_HANGUP:
{
if (zap_test_flag(zchan, ZAP_CHANNEL_ANSWERED)) {
0,
SIGBOOST_EVENT_CALL_START_NACK,
zchan->caller_data.hangup_cause);
- }
- zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
-
+ }
}
break;
case ZAP_CHANNEL_STATE_TERMINATING:
if (zap_test_flag((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE)) {
zap_mutex_lock(signal_mutex);
state_advance(&span->channels[j]);
+ zap_channel_complete_state(&span->channels[j]);
zap_mutex_unlock(signal_mutex);
zap_clear_flag_locked((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE);
}