tech_pvt = (private_t *) switch_core_session_get_private(session);
assert(tech_pvt != NULL);
-
+ assert(tech_pvt->zchan != NULL);
+
+ zap_mutex_lock(tech_pvt->zchan->mutex);
+ if (tech_pvt->zchan->state == ZAP_CHANNEL_STATE_TERMINATING) {
+ zap_mutex_unlock(tech_pvt->zchan->mutex);
+ return SWITCH_STATUS_SUCCESS;
+ }
+
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_RINGING:
{
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
- zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
+ zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
} else {
- zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
+ zap_set_state_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
}
}
break;
case SWITCH_MESSAGE_INDICATE_PROGRESS:
{
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
- zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
- zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA);
+ zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
+ zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_MEDIA);
} else {
/* Don't skip messages in the ISDN call setup
* TODO: make the isdn stack smart enough to handle that itself
* until then, this is here for safety...
*/
if (tech_pvt->zchan->state < ZAP_CHANNEL_STATE_PROGRESS) {
- zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
+ zap_set_state_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
}
- zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS_MEDIA);
+ zap_set_state_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS_MEDIA);
}
}
break;
case SWITCH_MESSAGE_INDICATE_ANSWER:
{
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
- zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED);
+ zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED);
} else {
/* Don't skip messages in the ISDN call setup
* TODO: make the isdn stack smart enough to handle that itself
* until then, this is here for safety...
*/
if (tech_pvt->zchan->state < ZAP_CHANNEL_STATE_PROGRESS) {
- zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
+ zap_set_state_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
}
if (tech_pvt->zchan->state < ZAP_CHANNEL_STATE_PROGRESS_MEDIA) {
- zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS_MEDIA);
+ zap_set_state_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS_MEDIA);
}
- zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_UP);
+ zap_set_state_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_UP);
}
}
break;
break;
}
+ zap_mutex_unlock(tech_pvt->zchan->mutex);
return SWITCH_STATUS_SUCCESS;
}
/* The while(0) below throws a conditional expression is constant warning */
#pragma warning(disable:4127)
#endif
+
#define zap_set_state_locked_wait(obj, s) \
do { \
int __safety = 100; \
} \
} while(0);
-#define zap_locked_wait_for_flag_cleared(obj, flag, time) \
+#define zap_wait_for_flag_cleared(obj, flag, time) \
do { \
int __safety = time; \
- while(__safety-- && zap_test_flag(obj, flag)) { \
+ while(__safety-- && zap_test_flag(obj, flag)) { \
+ zap_mutex_unlock(obj->mutex); \
zap_sleep(10); \
+ zap_mutex_lock(obj->mutex); \
} \
if(!__safety) { \
- zap_log(ZAP_LOG_CRIT, "flag %d was never cleared\n", flag); \
+ zap_log(ZAP_LOG_CRIT, "flag %d was never cleared\n", flag); \
} \
} while(0);
+#define zap_set_state_wait(obj, s) \
+ do { \
+ zap_channel_set_state(obj, s, 0); \
+ zap_wait_for_flag_cleared(obj, ZAP_CHANNEL_STATE_CHANGE, 100); \
+ } while(0);
+
+
+typedef enum {
+ ZAP_STATE_CHANGE_FAIL,
+ ZAP_STATE_CHANGE_SUCCESS,
+ ZAP_STATE_CHANGE_SAME,
+} zap_state_change_result_t;
#define zap_set_state_r(obj, s, l, r) if ( obj->state == s ) { \
zap_log(ZAP_LOG_WARNING, "Why bother changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, zap_channel_state2str(obj->state), zap_channel_state2str(s)); r = ZAP_STATE_CHANGE_SAME; \
*/
#define zap_copy_flags(dest, src, flags) (dest)->flags &= ~(flags); (dest)->flags |= ((src)->flags & (flags))
-typedef enum {
- ZAP_STATE_CHANGE_FAIL,
- ZAP_STATE_CHANGE_SUCCESS,
- ZAP_STATE_CHANGE_SAME,
-} zap_state_change_result_t;
-
struct zap_stream_handle {
zap_stream_handle_write_function_t write_function;
zap_stream_handle_raw_write_function_t raw_write_function;
break;
} else {
zchan = NULL;
- zap_log(ZAP_LOG_ERROR, "Channel %d:%d ~ %d:%d is already in use.\n",
+ zap_log(ZAP_LOG_DEBUG, "Channel %d:%d ~ %d:%d is already in use.\n",
span->channels[i]->span_id,
span->channels[i]->chan_id,
span->channels[i]->physical_span_id,
if ((zchan = find_zchan(span, event, 1))) {
int r = 0;
assert(!zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND));
+
+ zchan->call_data = (void*)(intptr_t)event->event_id;
zap_mutex_lock(zchan->mutex);
- zap_set_state_r(zchan, ZAP_CHANNEL_STATE_CANCEL, 0, r);
+ zap_set_state_r(zchan, ZAP_CHANNEL_STATE_TERMINATING, 0, r);
if (r == ZAP_STATE_CHANGE_SUCCESS) {
zchan->caller_data.hangup_cause = event->release_cause;
}
0,
SIGBOOST_EVENT_CALL_STOPPED_ACK,
0);
+ zap_mutex_unlock(zchan->mutex);
return;
} else {
zap_set_state_r(zchan, ZAP_CHANNEL_STATE_TERMINATING, 0, r);
}
}
+static __inline__ void advance_chan_states(zap_channel_t *zchan);
+
/**
* \brief Handler for call start event
* \param span Span where event was fired
zap_channel_t *zchan;
if (!(zchan = find_zchan(span, (sangomabc_short_event_t*)event, 0))) {
- goto error;
+ if (!(zchan = find_zchan(span, (sangomabc_short_event_t*)event, 1))) {
+ zap_log(ZAP_LOG_CRIT, "START CANT FIND CHAN %d:%d AT ALL\n", event->span+1,event->chan+1);
+ goto error;
+ }
+ advance_chan_states(zchan);
+ if (!(zchan = find_zchan(span, (sangomabc_short_event_t*)event, 0))) {
+ zap_log(ZAP_LOG_CRIT, "START CANT FIND CHAN %d:%d EVEN AFTER STATE ADVANCE\n", event->span+1,event->chan+1);
+ goto error;
+ }
}
if (zap_channel_open_chan(zchan) != ZAP_SUCCESS) {
+ zap_log(ZAP_LOG_CRIT, "START CANT OPEN CHAN %d:%d\n", event->span+1,event->chan+1);
goto error;
}
return;
error:
-
- zap_log(ZAP_LOG_CRIT, "START CANT FIND A CHAN %d:%d\n", event->span,event->chan);
-
sangomabc_exec_command(mcon,
event->span,
event->chan,
}
assert(event->call_setup_id <= MAX_REQ_ID);
-
switch(event->event_id) {
-
case SIGBOOST_EVENT_CALL_START:
handle_call_start(span, mcon, (sangomabc_event_t*)event);
break;
case SIGBOOST_EVENT_CALL_START_ACK:
handle_call_start_ack(mcon, event);
break;
- case SIGBOOST_EVENT_CALL_PROGRESS:
+ case SIGBOOST_EVENT_CALL_PROGRESS:
handle_call_progress(mcon, event);
break;
case SIGBOOST_EVENT_CALL_START_NACK:
if (!zap_test_sflag(zchan, SFLAG_SENT_FINAL_MSG)) {
zap_set_sflag_locked(zchan, SFLAG_SENT_FINAL_MSG);
- sangomabc_exec_command(mcon,
- BOOST_SPAN(zchan),
- BOOST_CHAN(zchan),
- 0,
- SIGBOOST_EVENT_CALL_STOPPED_ACK,
- 0);
+ if (zchan->call_data && ((uint32_t)(intptr_t)zchan->call_data == SIGBOOST_EVENT_CALL_START_NACK)) {
+ sangomabc_exec_command(mcon,
+ zchan->physical_span_id-1,
+ zchan->physical_chan_id-1,
+ 0,
+ SIGBOOST_EVENT_CALL_START_NACK_ACK,
+ 0);
+
+ } else {
+ sangomabc_exec_command(mcon,
+ zchan->physical_span_id-1,
+ zchan->physical_chan_id-1,
+ 0,
+ SIGBOOST_EVENT_CALL_STOPPED_ACK,
+ 0);
+ }
}
zchan->sflags = 0;
+ zchan->call_data = NULL;
zap_channel_done(zchan);
}
break;
}
}
break;
- case ZAP_CHANNEL_STATE_CANCEL:
- {
- sig.event_id = ZAP_SIGEVENT_STOP;
- status = sangoma_boost_data->signal_cb(&sig);
- zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
- zap_set_sflag_locked(zchan, SFLAG_SENT_FINAL_MSG);
- sangomabc_exec_command(mcon,
- BOOST_SPAN(zchan),
- BOOST_CHAN(zchan),
- 0,
- SIGBOOST_EVENT_CALL_START_NACK_ACK,
- 0);
- }
- break;
case ZAP_CHANNEL_STATE_TERMINATING:
{
sig.event_id = ZAP_SIGEVENT_STOP;
}
}
+static __inline__ void advance_chan_states(zap_channel_t *zchan)
+{
+ zap_mutex_lock(zchan->mutex);
+ while (zap_test_flag(zchan, ZAP_CHANNEL_STATE_CHANGE)) {
+ zap_clear_flag(zchan, ZAP_CHANNEL_STATE_CHANGE);
+ state_advance(zchan);
+ zap_channel_complete_state(zchan);
+ }
+ zap_mutex_unlock(zchan->mutex);
+}
+
/**
* \brief Initialises outgoing requests array
*/
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{ZAP_CHANNEL_STATE_RING, ZAP_END},
- {ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_CANCEL, ZAP_CHANNEL_STATE_PROGRESS, ZAP_CHANNEL_STATE_PROGRESS_MEDIA, ZAP_END}
+ {ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_TERMINATING, ZAP_CHANNEL_STATE_PROGRESS, ZAP_CHANNEL_STATE_PROGRESS_MEDIA,ZAP_END}
},
{
ZSD_INBOUND,
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
- {ZAP_CHANNEL_STATE_CANCEL, ZAP_CHANNEL_STATE_HANGUP_COMPLETE, ZAP_CHANNEL_STATE_TERMINATING, ZAP_END},
+ {ZAP_CHANNEL_STATE_HANGUP_COMPLETE, ZAP_CHANNEL_STATE_TERMINATING, ZAP_END},
{ZAP_CHANNEL_STATE_DOWN, ZAP_END},
},
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{ZAP_CHANNEL_STATE_PROGRESS, ZAP_CHANNEL_STATE_PROGRESS_MEDIA, ZAP_END},
- {ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_CANCEL, ZAP_CHANNEL_STATE_TERMINATING, ZAP_CHANNEL_STATE_UP, ZAP_CHANNEL_STATE_PROGRESS_MEDIA, ZAP_END},
+ {ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_TERMINATING, ZAP_CHANNEL_STATE_UP, ZAP_CHANNEL_STATE_PROGRESS_MEDIA, ZAP_END},
},
{
ZSD_INBOUND,