diff --git a/libs/openzap/Makefile b/libs/openzap/Makefile index 1fdd40748b..f5cbeee8ab 100644 --- a/libs/openzap/Makefile +++ b/libs/openzap/Makefile @@ -113,7 +113,7 @@ $(SRC)/zap_zt.o: $(SRC)/zap_zt.c dox: cd docs && doxygen $(PWD)/docs/Doxygen.conf -mod_openzap/mod_openzap.so: $(MYLIB) +mod_openzap/mod_openzap.so: $(MYLIB) mod_openzap/mod_openzap.c cd mod_openzap && make mod_openzap: mod_openzap/mod_openzap.so diff --git a/libs/openzap/mod_openzap/mod_openzap.c b/libs/openzap/mod_openzap/mod_openzap.c index 27ca737669..72060facba 100644 --- a/libs/openzap/mod_openzap/mod_openzap.c +++ b/libs/openzap/mod_openzap/mod_openzap.c @@ -47,20 +47,14 @@ struct span_config { static struct span_config SPAN_CONFIG[ZAP_MAX_SPANS_INTERFACE] = {0}; - typedef enum { TFLAG_IO = (1 << 0), - TFLAG_INBOUND = (1 << 1), - TFLAG_OUTBOUND = (1 << 2), - TFLAG_DTMF = (1 << 3), - TFLAG_VOICE = (1 << 4), - TFLAG_HANGUP = (1 << 5), - TFLAG_LINEAR = (1 << 6), - TFLAG_CODEC = (1 << 7), - TFLAG_BREAK = (1 << 8) + TFLAG_OUTBOUND = (1 << 1), + TFLAG_DTMF = (1 << 2), + TFLAG_CODEC = (1 << 3), + TFLAG_BREAK = (1 << 4) } TFLAGS; - static struct { int debug; char *dialplan; @@ -247,13 +241,26 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) tech_pvt = switch_core_session_get_private(session); assert(tech_pvt != NULL); - switch_clear_flag_locked(tech_pvt, TFLAG_IO); - switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); + zap_channel_set_token(tech_pvt->zchan, NULL); - if (tech_pvt->zchan->state != ZAP_CHANNEL_STATE_DOWN) { - zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_BUSY); + switch (tech_pvt->zchan->type) { + case ZAP_CHAN_TYPE_FXO: + case ZAP_CHAN_TYPE_FXS: + { + if (tech_pvt->zchan->state != ZAP_CHANNEL_STATE_DOWN) { + zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_HANGUP); + } + } + break; + default: + { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled type for channel %s\n", switch_channel_get_name(channel)); + } + break; } + switch_clear_flag_locked(tech_pvt, TFLAG_IO); + if (tech_pvt->read_codec.implementation) { switch_core_codec_destroy(&tech_pvt->read_codec); } @@ -287,10 +294,6 @@ static switch_status_t channel_kill_channel(switch_core_session_t *session, int switch (sig) { case SWITCH_SIG_KILL: switch_clear_flag_locked(tech_pvt, TFLAG_IO); - switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); - if (tech_pvt->zchan->state != ZAP_CHANNEL_STATE_DOWN) { - zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_BUSY); - } break; case SWITCH_SIG_BREAK: switch_set_flag_locked(tech_pvt, TFLAG_BREAK); @@ -364,8 +367,8 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch assert(tech_pvt->zchan != NULL); - if (tech_pvt->zchan->state != ZAP_CHANNEL_STATE_UP) { - return SWITCH_STATUS_GENERR; + if (!switch_test_flag(tech_pvt, TFLAG_IO)) { + return SWITCH_STATUS_FALSE; } status = zap_channel_wait(tech_pvt->zchan, &wflags, timeout); @@ -417,10 +420,6 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc assert(tech_pvt->zchan != NULL); - if (tech_pvt->zchan->state != ZAP_CHANNEL_STATE_UP) { - return SWITCH_STATUS_GENERR; - } - if (!switch_test_flag(tech_pvt, TFLAG_IO)) { return SWITCH_STATUS_FALSE; } @@ -545,75 +544,130 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi } -static ZIO_SIGNAL_CB_FUNCTION(on_fxo_signal) -{ - zap_log(ZAP_LOG_DEBUG, "got sig [%s]\n", zap_signal_event2str(sigmsg->event_id)); - return ZAP_SUCCESS; -} -static ZIO_SIGNAL_CB_FUNCTION(on_fxs_signal) +zap_status_t zap_channel_from_event(zap_sigmsg_t *sigmsg, switch_core_session_t **sp) { switch_core_session_t *session = NULL; private_t *tech_pvt = NULL; switch_channel_t *channel = NULL; char name[128]; - zap_log(ZAP_LOG_DEBUG, "got sig [%s]\n", zap_signal_event2str(sigmsg->event_id)); - switch(sigmsg->event_id) { - case ZAP_SIGEVENT_START: - if (!(session = switch_core_session_request(&channel_endpoint_interface, NULL))) { - zap_set_state_locked(sigmsg->channel, ZAP_CHANNEL_STATE_BUSY); - return ZAP_SUCCESS; - } + *sp = NULL; + + if (!(session = switch_core_session_request(&channel_endpoint_interface, NULL))) { + return ZAP_FAIL; + } + + switch_core_session_add_stream(session, NULL); + + tech_pvt = (private_t *) switch_core_session_alloc(session, sizeof(private_t)); + assert(tech_pvt != NULL); + channel = switch_core_session_get_channel(session); + if (tech_init(tech_pvt, session, sigmsg->channel) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Initilization Error!\n"); + switch_core_session_destroy(&session); + return ZAP_FAIL; + } + + tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), + "OpenZAP", + SPAN_CONFIG[sigmsg->span->span_id].dialplan, + sigmsg->channel->chan_name, + sigmsg->channel->chan_number, + NULL, + sigmsg->channel->chan_number, + NULL, + NULL, + (char *) modname, + SPAN_CONFIG[sigmsg->span->span_id].context, + sigmsg->dnis); + assert(tech_pvt->caller_profile != NULL); + + snprintf(name, sizeof(name), "OpenZAP/%s", tech_pvt->caller_profile->destination_number); + switch_channel_set_name(channel, name); + switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); + + switch_channel_set_state(channel, CS_INIT); + if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error spawning thread\n"); + switch_core_session_destroy(&session); + return ZAP_FAIL; + } - switch_core_session_add_stream(session, NULL); - - tech_pvt = (private_t *) switch_core_session_alloc(session, sizeof(private_t)); - assert(tech_pvt != NULL); - channel = switch_core_session_get_channel(session); - if (tech_init(tech_pvt, session, sigmsg->channel) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Initilization Error!\n"); - switch_core_session_destroy(&session); - zap_set_state_locked(sigmsg->channel, ZAP_CHANNEL_STATE_BUSY); - return ZAP_SUCCESS; - } - - tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), - "OpenZAP", - SPAN_CONFIG[sigmsg->span->span_id].dialplan, - sigmsg->channel->chan_name, - sigmsg->channel->chan_number, - NULL, - sigmsg->channel->chan_number, - NULL, - NULL, - (char *) modname, - SPAN_CONFIG[sigmsg->span->span_id].context, - sigmsg->dnis); - assert(tech_pvt->caller_profile != NULL); - - snprintf(name, sizeof(name), "OpenZAP/%s", tech_pvt->caller_profile->destination_number); - switch_channel_set_name(channel, name); - switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); - - switch_channel_set_state(channel, CS_INIT); - if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error spawning thread\n"); - switch_core_session_destroy(&session); - zap_set_state_locked(sigmsg->channel, ZAP_CHANNEL_STATE_BUSY); - return ZAP_SUCCESS; - } - - //zap_set_state_locked(sigmsg->channel, ZAP_CHANNEL_STATE_RING); - - break; - default: - break; - } + switch_copy_string(sigmsg->channel->token, switch_core_session_get_uuid(session), sizeof(sigmsg->channel->token)); + *sp = session; return ZAP_SUCCESS; } +static ZIO_SIGNAL_CB_FUNCTION(on_fxo_signal) +{ + zap_log(ZAP_LOG_DEBUG, "got sig [%s]\n", zap_signal_event2str(sigmsg->event_id)); + return ZAP_SUCCESS; +} +static ZIO_SIGNAL_CB_FUNCTION(on_fxs_signal) +{ + switch_core_session_t *session = NULL; + switch_channel_t *channel = NULL; + zap_status_t status; + int rwlock = 0; + + zap_log(ZAP_LOG_DEBUG, "got sig [%s]\n", zap_signal_event2str(sigmsg->event_id)); + + if (!switch_strlen_zero(sigmsg->channel->token)) { + if ((session = switch_core_session_locate(sigmsg->channel->token))) { + channel = switch_core_session_get_channel(session); + rwlock++; + } + } + + switch(sigmsg->event_id) { + case ZAP_SIGEVENT_START: + { + status = zap_channel_from_event(sigmsg, &session); + if (status != ZAP_SUCCESS) { + zap_set_state_locked(sigmsg->channel, ZAP_CHANNEL_STATE_BUSY); + } + } + break; + case ZAP_SIGEVENT_STOP: + { + if (channel) { + switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + zap_channel_set_token(sigmsg->channel, NULL); + } + } + break; + } + + if (session && rwlock) { + switch_core_session_rwunlock(session); + } + + return status; +} + +static ZIO_SIGNAL_CB_FUNCTION(on_zap_signal) +{ + switch (sigmsg->channel->type) { + case ZAP_CHAN_TYPE_FXO: + { + on_fxo_signal(sigmsg); + } + break; + case ZAP_CHAN_TYPE_FXS: + { + on_fxs_signal(sigmsg); + } + break; + default: + { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled type for channel %d:%d\n", + sigmsg->channel->span_id, sigmsg->channel->chan_id); + } + break; + } +} static void zap_logger(char *file, const char *func, int line, int level, char *fmt, ...) { @@ -710,7 +764,7 @@ static switch_status_t load_config(void) continue; } - if (zap_analog_configure_span(span, tonegroup, to, max, span->trunk_type == ZAP_TRUNK_FXS ? on_fxs_signal : on_fxo_signal) != ZAP_SUCCESS) { + if (zap_analog_configure_span(span, tonegroup, to, max, on_zap_signal) != ZAP_SUCCESS) { zap_log(ZAP_LOG_ERROR, "Error starting OpenZAP span %s:%d\n", mod, span_id); continue; } diff --git a/libs/openzap/src/include/openzap.h b/libs/openzap/src/include/openzap.h index 3475997c50..a4e24f2394 100644 --- a/libs/openzap/src/include/openzap.h +++ b/libs/openzap/src/include/openzap.h @@ -245,8 +245,9 @@ struct zap_channel { uint32_t dtmf_off; teletone_generation_session_t tone_session; zap_time_t last_event_time; - char chan_name[80]; - char chan_number[25]; + char token[128]; + char chan_name[128]; + char chan_number[32]; struct zap_span *span; struct zap_io_interface *zio; }; @@ -321,6 +322,7 @@ struct zap_io_interface { struct zap_span spans[ZAP_MAX_SPANS_INTERFACE]; }; +zap_status_t zap_channel_set_token(zap_channel_t *zchan, char *token); zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t state); zap_status_t zap_span_load_tones(zap_span_t *span, char *mapname); zap_size_t zap_channel_dequeue_dtmf(zap_channel_t *zchan, char *dtmf, zap_size_t len); diff --git a/libs/openzap/src/include/zap_types.h b/libs/openzap/src/include/zap_types.h index cf1b25cf76..236217278f 100644 --- a/libs/openzap/src/include/zap_types.h +++ b/libs/openzap/src/include/zap_types.h @@ -192,6 +192,7 @@ typedef enum { typedef enum { ZAP_CHANNEL_STATE_DOWN, ZAP_CHANNEL_STATE_UP, + ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_DIALTONE, ZAP_CHANNEL_STATE_COLLECT, ZAP_CHANNEL_STATE_RING, @@ -200,7 +201,7 @@ typedef enum { ZAP_CHANNEL_STATE_IDLE, ZAP_CHANNEL_STATE_INVALID } zap_channel_state_t; -#define CHANNEL_STATE_STRINGS "DOWN", "UP", "DIALTONE", "COLLECT", "RING", "BUSY", "ATTN", "IDLE", "INVALID" +#define CHANNEL_STATE_STRINGS "DOWN", "UP", "HANGUP", "DIALTONE", "COLLECT", "RING", "BUSY", "ATTN", "IDLE", "INVALID" ZAP_STR2ENUM_P(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t) typedef enum { diff --git a/libs/openzap/src/zap_analog.c b/libs/openzap/src/zap_analog.c index 0377fc4ad9..3032e0200b 100644 --- a/libs/openzap/src/zap_analog.c +++ b/libs/openzap/src/zap_analog.c @@ -145,6 +145,13 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) } } break; + case ZAP_CHANNEL_STATE_HANGUP: + { + if (state_counter > 2000) { + zap_set_state_locked(chan, ZAP_CHANNEL_STATE_BUSY); + } + } + break; case ZAP_CHANNEL_STATE_UP: case ZAP_CHANNEL_STATE_IDLE: { diff --git a/libs/openzap/src/zap_io.c b/libs/openzap/src/zap_io.c index eff007f119..1c3da3c2c7 100644 --- a/libs/openzap/src/zap_io.c +++ b/libs/openzap/src/zap_io.c @@ -370,6 +370,18 @@ zap_status_t zap_channel_set_event_callback(zap_channel_t *zchan, zio_event_cb_t return ZAP_SUCCESS; } +zap_status_t zap_channel_set_token(zap_channel_t *zchan, char *token) +{ + zap_mutex_lock(zchan->mutex); + if (token) { + zap_copy_string(zchan->token, token, sizeof(zchan->token)); + } else { + *zchan->token = '\0'; + } + zap_mutex_unlock(zchan->mutex); + return ZAP_SUCCESS; +} + zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t state) {