From 8e69e8e735dc8cd4156aea7f48441eb51ab6ff8c Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Mon, 17 May 2010 14:36:10 -0400 Subject: [PATCH] freetdm: clean up state change macros and functions to improve logging --- libs/freetdm/mod_freetdm/mod_freetdm.c | 42 ------ libs/freetdm/src/ftdm_io.c | 137 +++++++++++------- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 4 +- .../ftmod_sangoma_boost/ftmod_sangoma_boost.c | 28 ++-- libs/freetdm/src/include/freetdm.h | 35 ++++- libs/freetdm/src/include/private/ftdm_core.h | 64 ++------ 6 files changed, 143 insertions(+), 167 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index b3c0b4d67d..a5355b2f33 100644 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -830,59 +830,17 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session, switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_RINGING: { -#if 0 - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { - ftdm_set_flag(tech_pvt->ftdmchan, FTDM_CHANNEL_PROGRESS); - } else { - ftdm_set_state_wait(tech_pvt->ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); - } -#else ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROGRESS); -#endif } break; case SWITCH_MESSAGE_INDICATE_PROGRESS: { -#if 0 - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { - ftdm_set_flag(tech_pvt->ftdmchan, FTDM_CHANNEL_PROGRESS); - ftdm_set_flag(tech_pvt->ftdmchan, FTDM_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->ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { - ftdm_set_state_wait(tech_pvt->ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); - } - ftdm_set_state_wait(tech_pvt->ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); - } -#else ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA); -#endif } break; case SWITCH_MESSAGE_INDICATE_ANSWER: { -#if 0 - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { - ftdm_set_flag(tech_pvt->ftdmchan, FTDM_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->ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { - ftdm_set_state_wait(tech_pvt->ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); - } - if (tech_pvt->ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS_MEDIA) { - ftdm_set_state_wait(tech_pvt->ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); - } - ftdm_set_state_wait(tech_pvt->ftdmchan, FTDM_CHANNEL_STATE_UP); - } -#else ftdm_channel_call_answer(tech_pvt->ftdmchan); -#endif } break; default: diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index c34d4d18a4..088bd2f093 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1139,39 +1139,48 @@ static int ftdm_parse_state_map(ftdm_channel_t *ftdmchan, ftdm_channel_state_t s return ok; } -FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int lock) +/* this function MUST be called with the channel lock held. If waitrq == 1, the channel will be unlocked/locked (never call it with waitrq == 1 with an lock recursivity > 1) */ +#define DEFAULT_WAIT_TIME 1000 +FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int waitrq) { int ok = 1; - + int waitms = DEFAULT_WAIT_TIME; + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY)) { + ftdm_log(file, func, line, FTDM_LOG_LEVEL_ERROR, "%d:%d Ignored state change request from %s to %s, the channel is not ready\n", + ftdmchan->span_id, ftdmchan->chan_id, + ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); return FTDM_FAIL; } if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_SUSPENDED)) { if (state != FTDM_CHANNEL_STATE_RESTART && state != FTDM_CHANNEL_STATE_DOWN) { + ftdm_log(file, func, line, FTDM_LOG_LEVEL_ERROR, "%d:%d Ignored state change request from %s to %s, span %s is suspended\n", + ftdmchan->span_id, ftdmchan->chan_id, + ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state), ftdmchan->span->name); return FTDM_FAIL; } } - if (lock) { - ftdm_mutex_lock(ftdmchan->mutex); - } - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_log(FTDM_LOG_CRIT, "Ignored state change request from %s to %s, the previous state change has not been processed yet\n", + ftdm_log(file, func, line, FTDM_LOG_LEVEL_ERROR, "%d:%d Ignored state change request from %s to %s, the previous state change has not been processed yet\n", + ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); - if (lock) { - ftdm_mutex_unlock(ftdmchan->mutex); - } return FTDM_FAIL; } + if (ftdmchan->state == state) { + ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "%d:%d Why bother changing state from %s to %s\n", + ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); + return FTDM_FAIL; + } if (ftdmchan->span->state_map) { ok = ftdm_parse_state_map(ftdmchan, state, ftdmchan->span->state_map); goto end; } + /* basic core state validation (by-passed if the signaling module provides a state_map) */ switch(ftdmchan->state) { case FTDM_CHANNEL_STATE_HANGUP: case FTDM_CHANNEL_STATE_TERMINATING: @@ -1248,15 +1257,14 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(ftdm_channel_t *ftdmchan, ftdm_ break; } - end: - - if (state == ftdmchan->state) { - ok = 0; - } - +end: if (ok) { - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); + ftdm_log(file, func, line, FTDM_LOG_LEVEL_DEBUG, "%d:%d Changed state from %s to %s\n", + ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); + ftdmchan->last_state = ftdmchan->state; + ftdmchan->state = state; + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); ftdm_mutex_lock(ftdmchan->span->mutex); ftdm_set_flag(ftdmchan->span, FTDM_SPAN_STATE_CHANGE); @@ -1264,13 +1272,37 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(ftdm_channel_t *ftdmchan, ftdm_ ftdm_queue_enqueue(ftdmchan->span->pendingchans, ftdmchan); } ftdm_mutex_unlock(ftdmchan->span->mutex); - - ftdmchan->last_state = ftdmchan->state; - ftdmchan->state = state; + } else { + ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "%d:%d VETO state change from %s to %s\n", + ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); } - if (lock) { + /* there is an inherent race here between set and check of the change flag but we do not care because + * the flag should never last raised for more than a few ms for any state change */ + while (waitrq && waitms > 0) { + /* give a chance to the signaling stack to process it */ ftdm_mutex_unlock(ftdmchan->mutex); + + ftdm_sleep(10); + waitms -= 10; + + ftdm_mutex_lock(ftdmchan->mutex); + + /* if the flag is no longer set, the state change was processed (or is being processed) */ + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { + break; + } + + /* if the state is no longer what we set, the state change was + * obviously processed (and the current state change flag is for other state change) */ + if (ftdmchan->state != state) { + break; + } + } + + if (waitms <= 0) { + ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "%d:%d state change from %s to %s was most likely not processed after aprox %dms\n", + ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->last_state), ftdm_channel_state2str(state), DEFAULT_WAIT_TIME); } return ok ? FTDM_SUCCESS : FTDM_FAIL; @@ -1548,7 +1580,7 @@ static ftdm_status_t ftdm_channel_reset(ftdm_channel_t *ftdmchan) FT_DECLARE(ftdm_status_t) ftdm_channel_init(ftdm_channel_t *ftdmchan) { if (ftdmchan->init_state != FTDM_CHANNEL_STATE_DOWN) { - ftdm_set_state_locked(ftdmchan, ftdmchan->init_state); + ftdm_set_state(ftdmchan, ftdmchan->init_state); ftdmchan->init_state = FTDM_CHANNEL_STATE_DOWN; } @@ -1765,30 +1797,31 @@ FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_done(const ftdm_channel_t *ftdmc return condition; } -FT_DECLARE(ftdm_status_t) ftdm_channel_call_hold(ftdm_channel_t *ftdmchan) +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) { ftdm_channel_lock(ftdmchan); ftdm_set_flag(ftdmchan, FTDM_CHANNEL_HOLD); - ftdm_set_state_wait(ftdmchan, FTDM_CHANNEL_STATE_DIALTONE); + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_DIALTONE, 1); ftdm_channel_unlock(ftdmchan); return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) ftdm_channel_call_unhold(ftdm_channel_t *ftdmchan) +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_unhold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) { ftdm_channel_lock(ftdmchan); if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_HOLD)) { - ftdm_set_state_wait(ftdmchan, FTDM_CHANNEL_STATE_UP); + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 1); } ftdm_channel_unlock(ftdmchan); return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) ftdm_channel_call_answer(ftdm_channel_t *ftdmchan) +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) { ftdm_channel_lock(ftdmchan); if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_ANSWERED)) { + ftdm_channel_unlock(ftdmchan); return FTDM_SUCCESS; } @@ -1801,24 +1834,24 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_call_answer(ftdm_channel_t *ftdmchan) } if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { - ftdm_set_state_wait(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); } if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS_MEDIA) { - ftdm_set_state_wait(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1); } - ftdm_set_state_wait(ftdmchan, FTDM_CHANNEL_STATE_UP); + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 1); ftdm_channel_unlock(ftdmchan); return FTDM_SUCCESS; } - -static ftdm_status_t call_hangup(ftdm_channel_t *chan) +/* lock must be acquired by the caller! */ +static ftdm_status_t call_hangup(ftdm_channel_t *chan, const char *file, const char *func, int line) { if (chan->state != FTDM_CHANNEL_STATE_DOWN) { - ftdm_set_state_wait(chan, FTDM_CHANNEL_STATE_HANGUP); + ftdm_channel_set_state(file, func, line, chan, FTDM_CHANNEL_STATE_HANGUP, 1); } else { /* the signaling stack did not touch the state, * core is responsible from clearing flags and stuff */ @@ -1827,22 +1860,22 @@ static ftdm_status_t call_hangup(ftdm_channel_t *chan) return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) ftdm_channel_call_hangup_with_cause(ftdm_channel_t *ftdmchan, ftdm_call_cause_t cause) +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup_with_cause(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_call_cause_t cause) { ftdm_channel_lock(ftdmchan); ftdmchan->caller_data.hangup_cause = cause; - call_hangup(ftdmchan); + call_hangup(ftdmchan, file, func, line); ftdm_channel_unlock(ftdmchan); return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) ftdm_channel_call_hangup(ftdm_channel_t *ftdmchan) +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) { ftdm_channel_lock(ftdmchan); - call_hangup(ftdmchan); + call_hangup(ftdmchan, file, func, line); ftdm_channel_unlock(ftdmchan); return FTDM_SUCCESS; } @@ -1911,48 +1944,54 @@ FT_DECLARE(uint32_t) ftdm_channel_get_ph_span_id(const ftdm_channel_t *ftdmchan) return id; } -FT_DECLARE(ftdm_status_t) ftdm_channel_call_indicate(ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication) +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication) { + ftdm_status_t status = FTDM_SUCCESS; + ftdm_channel_lock(ftdmchan); switch (indication) { /* FIXME: ring and busy cannot be used with all signaling stacks * (particularly isdn stacks I think, we should emulate or just move to hangup with busy cause) */ case FTDM_CHANNEL_INDICATE_RING: - ftdm_set_state_locked_wait(ftdmchan, FTDM_CHANNEL_STATE_RING); + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RING, 1); break; case FTDM_CHANNEL_INDICATE_BUSY: - ftdm_set_state_locked_wait(ftdmchan, FTDM_CHANNEL_STATE_BUSY); + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_BUSY, 1); break; case FTDM_CHANNEL_INDICATE_PROGRESS: if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_PROGRESS); + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS); } else { - ftdm_set_state_locked_wait(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); } break; case FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA: if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_PROGRESS); - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_MEDIA); + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS); + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_MEDIA); } else { if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { - ftdm_set_state_locked_wait(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); } - ftdm_set_state_locked_wait(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1); } break; default: - ftdm_log(FTDM_LOG_WARNING, "Do not know how to indicate %d\n", indication); - return FTDM_FAIL; + ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Do not know how to indicate %d\n", indication); + status = FTDM_FAIL; + break; } + + ftdm_channel_unlock(ftdmchan); + return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) ftdm_channel_call_place(ftdm_channel_t *ftdmchan) +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) { ftdm_status_t status; diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index a3396ae0ad..564a812496 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -174,7 +174,7 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call) ft_r2_clean_call(ftdmchan->call_data); R2CALL(ftdmchan)->chanstate = FTDM_CHANNEL_STATE_DOWN; - ftdm_channel_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING, 0); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING); ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND); R2CALL(ftdmchan)->ftdm_started = 1; ftdm_mutex_unlock(ftdmchan->mutex); @@ -224,7 +224,7 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan) } ft_r2_clean_call(ftdmchan->call_data); R2CALL(ftdmchan)->chanstate = FTDM_CHANNEL_STATE_DOWN; - ftdm_channel_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT, 0); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); ftdm_mutex_unlock(ftdmchan->mutex); status = ftdm_thread_create_detached(ftdm_r2_channel_run, ftdmchan); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c index 69b6a22055..572b394bf0 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c @@ -649,10 +649,10 @@ static void handle_call_start_ack(sangomabc_connection_t *mcon, sangomabc_short_ ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA || ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS) { ftdm_log(FTDM_LOG_CRIT, "FTDMCHAN CALL ACK STATE UP -> Changed to TERMINATING %d:%d\n", event_span, event_chan); - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, 0, r); + ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, r); } else if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP || ftdm_test_sflag(ftdmchan, SFLAG_HANGUP)) { ftdm_log(FTDM_LOG_CRIT, "FTDMCHAN CALL ACK STATE HANGUP -> Changed to HANGUP COMPLETE %d:%d\n", event_span, event_chan); - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, 0, r); + ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, r); } else { ftdm_log(FTDM_LOG_CRIT, "FTDMCHAN STATE INVALID State %s on IN CALL ACK %d:%d\n", ftdm_channel_state2str(ftdmchan->state), event_span, event_chan); @@ -711,7 +711,7 @@ static void handle_call_done(ftdm_span_t *span, sangomabc_connection_t *mcon, sa goto done; } - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, 0, r); + ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, r); if (r) { ftdm_mutex_unlock(ftdmchan->mutex); return; @@ -799,8 +799,8 @@ static void handle_call_start_nack(ftdm_span_t *span, sangomabc_connection_t *mc CALL_DATA(ftdmchan)->last_event_id = event->event_id; ftdm_mutex_lock(ftdmchan->mutex); - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, 0, r); - if (r == FTDM_STATE_CHANGE_SUCCESS) { + ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, r); + if (r == FTDM_SUCCESS) { ftdmchan->caller_data.hangup_cause = event->release_cause; } ftdm_mutex_unlock(ftdmchan->mutex); @@ -882,10 +882,10 @@ static void handle_call_stop(ftdm_span_t *span, sangomabc_connection_t *mcon, sa ftdm_mutex_unlock(ftdmchan->mutex); return; } else { - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, 0, r); + ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, r); } - if (r == FTDM_STATE_CHANGE_SUCCESS) { + if (r == FTDM_SUCCESS) { ftdmchan->caller_data.hangup_cause = event->release_cause; } @@ -928,7 +928,7 @@ static void handle_call_answer(ftdm_span_t *span, sangomabc_connection_t *mcon, } else { int r = 0; - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_UP, 0, r); + ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_UP, r); } ftdm_mutex_unlock(ftdmchan->mutex); } else { @@ -969,11 +969,11 @@ static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, s ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS) { ftdm_log(FTDM_LOG_CRIT, "s%dc%d: FTDMCHAN STATE UP -> Changed to TERMINATING\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, 0, r); + ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, r); } else if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP || ftdm_test_sflag(ftdmchan, SFLAG_HANGUP)) { ftdm_log(FTDM_LOG_CRIT, "s%dc%d: FTDMCHAN STATE HANGUP -> Changed to HANGUP COMPLETE\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, 0, r); + ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, r); } else if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) { ftdm_log(FTDM_LOG_WARNING, "s%dc%d: Collision, hanging up incoming call\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); @@ -983,7 +983,7 @@ static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, s * when receiving call start nack we move the channel from DOWN to TERMINATING ( cuz we already * hangup here ) and the channel gets stuck in terminating forever. So at this point we're trusting * the other side to send the call start nack ( or proceed with the call ) - * ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, 0, r); + * ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, r); */ } else { ftdm_log(FTDM_LOG_ERROR, "s%dc%d: rejecting incoming call in channel state %s\n", @@ -1076,7 +1076,7 @@ static void handle_call_loop_start(ftdm_span_t *span, sangomabc_connection_t *mc return; } - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP, 0, res); + ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP, res); if (res != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "yay, could not set the state of the channel to IN_LOOP, loop will fail\n"); ftdm_channel_done(ftdmchan); @@ -1100,7 +1100,7 @@ static void handle_call_loop_stop(ftdm_span_t *span, sangomabc_connection_t *mco ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); /* even when we did not sent a msg we set this flag to avoid sending call stop in the DOWN state handler */ ftdm_set_flag(ftdmchan, SFLAG_SENT_FINAL_MSG); - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_DOWN, 0, res); + ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_DOWN, res); } /** @@ -1627,7 +1627,7 @@ static __inline__ void check_state(ftdm_span_t *span) ftdm_mutex_lock(span->channels[j]->mutex); ftdm_clear_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE); if (susp && span->channels[j]->state != FTDM_CHANNEL_STATE_DOWN) { - ftdm_channel_set_state(span->channels[j], FTDM_CHANNEL_STATE_RESTART, 0); + ftdm_set_state(span->channels[j], FTDM_CHANNEL_STATE_RESTART); } state_advance(span->channels[j]); ftdm_channel_complete_state(span->channels[j]); diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 4754edc946..cf73969862 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -587,25 +587,46 @@ typedef enum { FT_DECLARE(ftdm_status_t) ftdm_global_set_queue_handler(ftdm_queue_handler_t *handler); /*! \brief Answer call */ -FT_DECLARE(ftdm_status_t) ftdm_channel_call_answer(ftdm_channel_t *ftdmchan); +#define ftdm_channel_call_answer(ftdmchan) _ftdm_channel_call_answer(__FILE__, __FUNCTION__, __LINE__, (ftdmchan)) + +/*! \brief Answer call recording the source code point where the it was called (see ftdm_channel_call_answer for an easy to use macro) */ +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan); /*! \brief Place an outgoing call */ -FT_DECLARE(ftdm_status_t) ftdm_channel_call_place(ftdm_channel_t *ftdmchan); +#define ftdm_channel_call_place(ftdmchan) _ftdm_channel_call_place(__FILE__, __FUNCTION__, __LINE__, (ftdmchan)) + +/*! \brief Place an outgoing call recording the source code point where it was called (see ftdm_channel_call_place for an easy to use macro) */ +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan); /*! \brief Indicate a new condition in an incoming call */ -FT_DECLARE(ftdm_status_t) ftdm_channel_call_indicate(ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication); +#define ftdm_channel_call_indicate(ftdmchan, indication) _ftdm_channel_call_indicate(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (indication)) + +/*! \brief Indicate a new condition in an incoming call recording the source code point where it was called (see ftdm_channel_call_indicate for an easy to use macro) */ +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication); /*! \brief Hangup the call without cause */ -FT_DECLARE(ftdm_status_t) ftdm_channel_call_hangup(ftdm_channel_t *ftdmchan); +#define ftdm_channel_call_hangup(ftdmchan) _ftdm_channel_call_hangup(__FILE__, __FUNCTION__, __LINE__, (ftdmchan)) + +/*! \brief Hangup the call without cause recording the source code point where it was called (see ftdm_channel_call_hangup for an easy to use macro)*/ +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan); /*! \brief Hangup the call with cause */ -FT_DECLARE(ftdm_status_t) ftdm_channel_call_hangup_with_cause(ftdm_channel_t *ftdmchan, ftdm_call_cause_t); +#define ftdm_channel_call_hangup_with_cause(ftdmchan, cause) _ftdm_channel_call_hangup_with_cause(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (cause)) + +/*! \brief Hangup the call with cause recording the source code point where it was called (see ftdm_channel_call_hangup_with_cause for an easy to use macro) */ +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup_with_cause(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_call_cause_t); /*! \brief Put a call on hold (if supported by the signaling stack) */ -FT_DECLARE(ftdm_status_t) ftdm_channel_call_hold(ftdm_channel_t *ftdmchan); +#define ftdm_channel_call_hold(ftdmchan) _ftdm_channel_call_hold(__FILE__, __FUNCTION__, __LINE__, (ftdmchan)) + +/*! \brief Put a call on hold recording the source code point where it was called (see ftdm_channel_call_hold for an easy to use macro) */ +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan); /*! \brief Unhold a call */ -FT_DECLARE(ftdm_status_t) ftdm_channel_call_unhold(ftdm_channel_t *ftdmchan); +#define ftdm_channel_call_unhold(ftdmchan) _ftdm_channel_call_unhold(__FILE__, __FUNCTION__, __LINE__, (ftdmchan)) + +/*! \brief Unhold a call recording the source code point where it was called (see ftdm_channel_call_unhold for an easy to use macro) */ +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_unhold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan); /*! \brief Check if the call is answered already */ FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_answered(const ftdm_channel_t *ftdmchan); diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index c1144b1e86..a900b0d808 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -189,42 +189,23 @@ extern "C" { #define ftdm_clear_sflag_locked(obj, flag) assert(obj->mutex != NULL); ftdm_mutex_lock(obj->mutex); (obj)->sflags &= ~(flag); ftdm_mutex_unlock(obj->mutex); +#define ftdm_set_state(obj, s) ftdm_channel_set_state(__FILE__, __FUNCTION__, __LINE__, obj, s, 0); \ -#define ftdm_set_state_locked(obj, s) if ( obj->state == s ) { \ - ftdm_log(FTDM_LOG_WARNING, "Why bother changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, ftdm_channel_state2str(obj->state), ftdm_channel_state2str(s)); \ - } else if (ftdm_test_flag(obj, FTDM_CHANNEL_READY)) { \ - ftdm_channel_state_t st = obj->state; \ - ftdm_channel_set_state(obj, s, 1); \ - if (obj->state == s) ftdm_log(FTDM_LOG_DEBUG, "Changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, ftdm_channel_state2str(st), ftdm_channel_state2str(s)); \ - else ftdm_log(FTDM_LOG_WARNING, "VETO Changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, ftdm_channel_state2str(st), ftdm_channel_state2str(s)); \ - } +#define ftdm_set_state_locked(obj, s) \ + do { \ + ftdm_channel_lock(obj); \ + ftdm_channel_set_state(__FILE__, __FUNCTION__, __LINE__, obj, s, 0); \ + ftdm_channel_unlock(obj); \ + } while(0); -#define ftdm_set_state(obj, s) if ( obj->state == s ) { \ - ftdm_log(FTDM_LOG_WARNING, "Why bother changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, ftdm_channel_state2str(obj->state), ftdm_channel_state2str(s)); \ - } else if (ftdm_test_flag(obj, FTDM_CHANNEL_READY)) { \ - ftdm_channel_state_t st = obj->state; \ - ftdm_channel_set_state(obj, s, 0); \ - if (obj->state == s) ftdm_log(FTDM_LOG_DEBUG, "Changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, ftdm_channel_state2str(st), ftdm_channel_state2str(s)); \ - else ftdm_log(FTDM_LOG_WARNING, "VETO Changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, ftdm_channel_state2str(st), ftdm_channel_state2str(s)); \ - } +#define ftdm_set_state_r(obj, s, r) r = ftdm_channel_set_state(__FILE__, __FUNCTION__, __LINE__, obj, s, 0); #ifdef _MSC_VER /* The while(0) below throws a conditional expression is constant warning */ #pragma warning(disable:4127) #endif -#define ftdm_set_state_locked_wait(obj, s) \ - do { \ - int __safety = 100; \ - ftdm_set_state_locked(obj, s); \ - while(__safety-- && ftdm_test_flag(obj, FTDM_CHANNEL_STATE_CHANGE)) { \ - ftdm_sleep(10); \ - } \ - if(!__safety) { \ - ftdm_log(FTDM_LOG_CRIT, "State change not completed\n"); \ - } \ - } while(0); - +/* this macro assumes obj is locked! */ #define ftdm_wait_for_flag_cleared(obj, flag, time) \ do { \ int __safety = time; \ @@ -238,23 +219,6 @@ extern "C" { } \ } while(0); -#define ftdm_set_state_wait(obj, s) \ - do { \ - ftdm_channel_set_state(obj, s, 0); \ - ftdm_wait_for_flag_cleared(obj, FTDM_CHANNEL_STATE_CHANGE, 100); \ - } while(0); - - -#define ftdm_set_state_r(obj, s, l, r) if ( obj->state == s ) { \ - if (s != FTDM_CHANNEL_STATE_HANGUP) ftdm_log(FTDM_LOG_WARNING, "Why bother changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, ftdm_channel_state2str(obj->state), ftdm_channel_state2str(s)); r = FTDM_STATE_CHANGE_SAME; \ - } else if (ftdm_test_flag(obj, FTDM_CHANNEL_READY)) { \ - int st = obj->state; \ - r = (ftdm_channel_set_state(obj, s, l) == FTDM_SUCCESS) ? FTDM_STATE_CHANGE_SUCCESS : FTDM_STATE_CHANGE_FAIL; \ - if (obj->state == s) {ftdm_log(FTDM_LOG_DEBUG, "Changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, ftdm_channel_state2str(st), ftdm_channel_state2str(s));} \ - else ftdm_log(FTDM_LOG_WARNING, "VETO Changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, ftdm_channel_state2str(st), ftdm_channel_state2str(s)); \ - } - - #define ftdm_is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119) /*! @@ -265,13 +229,6 @@ extern "C" { */ #define ftdm_copy_flags(dest, src, flags) (dest)->flags &= ~(flags); (dest)->flags |= ((src)->flags & (flags)) -/*! \brief channel state change result */ -typedef enum { - FTDM_STATE_CHANGE_FAIL, - FTDM_STATE_CHANGE_SUCCESS, - FTDM_STATE_CHANGE_SAME, -} ftdm_state_change_result_t; - struct ftdm_stream_handle { ftdm_stream_handle_write_function_t write_function; ftdm_stream_handle_raw_write_function_t raw_write_function; @@ -533,7 +490,8 @@ FT_DECLARE(ftdm_status_t) ftdm_fsk_data_add_checksum(ftdm_fsk_data_state_t *stat FT_DECLARE(ftdm_status_t) ftdm_fsk_data_add_sdmf(ftdm_fsk_data_state_t *state, const char *date, char *number); FT_DECLARE(ftdm_status_t) ftdm_channel_send_fsk_data(ftdm_channel_t *ftdmchan, ftdm_fsk_data_state_t *fsk_data, float db_level); -FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int lock); +FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(const char *file, const char *func, int line, + ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int wait); FT_DECLARE(ftdm_status_t) ftdm_span_load_tones(ftdm_span_t *span, const char *mapname); FT_DECLARE(ftdm_time_t) ftdm_current_time_in_ms(void);