git-svn-id: http://svn.openzap.org/svn/openzap/trunk@166 a93c3328-9c30-0410-af19-c9cd2b2d52af
This commit is contained in:
Anthony Minessale 2007-05-27 18:14:49 +00:00
parent 605f70877f
commit 9f9b4e45b9
5 changed files with 197 additions and 38 deletions

View File

@ -52,7 +52,8 @@ typedef enum {
TFLAG_OUTBOUND = (1 << 1), TFLAG_OUTBOUND = (1 << 1),
TFLAG_DTMF = (1 << 2), TFLAG_DTMF = (1 << 2),
TFLAG_CODEC = (1 << 3), TFLAG_CODEC = (1 << 3),
TFLAG_BREAK = (1 << 4) TFLAG_BREAK = (1 << 4),
TFLAG_HOLD = (1 << 5)
} TFLAGS; } TFLAGS;
static struct { static struct {
@ -76,6 +77,8 @@ struct private_object {
switch_codec_t write_codec; switch_codec_t write_codec;
switch_frame_t read_frame; switch_frame_t read_frame;
unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
switch_frame_t cng_frame;
unsigned char cng_databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
switch_core_session_t *session; switch_core_session_t *session;
switch_caller_profile_t *caller_profile; switch_caller_profile_t *caller_profile;
unsigned int codec; unsigned int codec;
@ -84,6 +87,7 @@ struct private_object {
switch_mutex_t *mutex; switch_mutex_t *mutex;
switch_mutex_t *flag_mutex; switch_mutex_t *flag_mutex;
zap_channel_t *zchan; zap_channel_t *zchan;
int32_t token_id;
}; };
typedef struct private_object private_t; typedef struct private_object private_t;
@ -111,6 +115,9 @@ static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *ses
tech_pvt->zchan = zchan; tech_pvt->zchan = zchan;
tech_pvt->read_frame.data = tech_pvt->databuf; tech_pvt->read_frame.data = tech_pvt->databuf;
tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf); tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
tech_pvt->cng_frame.data = tech_pvt->cng_databuf;
tech_pvt->cng_frame.buflen = sizeof(tech_pvt->cng_databuf);
memset(tech_pvt->cng_frame.data, 255, tech_pvt->cng_frame.buflen);
switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
switch_core_session_set_private(session, tech_pvt); switch_core_session_set_private(session, tech_pvt);
@ -241,7 +248,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
tech_pvt = switch_core_session_get_private(session); tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL); assert(tech_pvt != NULL);
zap_channel_set_token(tech_pvt->zchan, NULL); zap_channel_clear_token(tech_pvt->zchan, tech_pvt->token_id);
switch (tech_pvt->zchan->type) { switch (tech_pvt->zchan->type) {
case ZAP_CHAN_TYPE_FXO: case ZAP_CHAN_TYPE_FXO:
@ -367,6 +374,17 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
assert(tech_pvt->zchan != NULL); assert(tech_pvt->zchan != NULL);
if (switch_test_flag(tech_pvt, TFLAG_HOLD)) {
switch_yield(tech_pvt->zchan->effective_interval * 1000);
*frame = &tech_pvt->cng_frame;
tech_pvt->cng_frame.datalen = tech_pvt->zchan->packet_len;
tech_pvt->cng_frame.samples = tech_pvt->cng_frame.datalen;
if (tech_pvt->zchan->effective_codec == ZAP_CODEC_SLIN) {
tech_pvt->cng_frame.samples /= 2;
}
return SWITCH_STATUS_SUCCESS;
}
if (!switch_test_flag(tech_pvt, TFLAG_IO)) { if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
@ -420,6 +438,10 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
assert(tech_pvt->zchan != NULL); assert(tech_pvt->zchan != NULL);
if (switch_test_flag(tech_pvt, TFLAG_HOLD)) {
return SWITCH_STATUS_SUCCESS;
}
if (!switch_test_flag(tech_pvt, TFLAG_IO)) { if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
@ -593,12 +615,26 @@ zap_status_t zap_channel_from_event(zap_sigmsg_t *sigmsg, switch_core_session_t
return ZAP_FAIL; return ZAP_FAIL;
} }
switch_copy_string(sigmsg->channel->token, switch_core_session_get_uuid(session), sizeof(sigmsg->channel->token)); if ((tech_pvt->token_id = zap_channel_add_token(sigmsg->channel, switch_core_session_get_uuid(session))) < 0) {
switch_core_session_destroy(&session);
return ZAP_FAIL;
}
*sp = session; *sp = session;
return ZAP_SUCCESS; return ZAP_SUCCESS;
} }
static switch_core_session_t *zap_channel_get_session(zap_channel_t *channel, int32_t id)
{
switch_core_session_t *session = NULL;
if (!switch_strlen_zero(channel->tokens[id])) {
session = switch_core_session_locate(channel->tokens[id]);
}
return session;
}
static ZIO_SIGNAL_CB_FUNCTION(on_fxo_signal) static ZIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
{ {
zap_log(ZAP_LOG_DEBUG, "got sig [%s]\n", zap_signal_event2str(sigmsg->event_id)); zap_log(ZAP_LOG_DEBUG, "got sig [%s]\n", zap_signal_event2str(sigmsg->event_id));
@ -609,18 +645,11 @@ static ZIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
{ {
switch_core_session_t *session = NULL; switch_core_session_t *session = NULL;
switch_channel_t *channel = NULL; switch_channel_t *channel = NULL;
private_t *tech_pvt = NULL;
zap_status_t status; zap_status_t status;
int rwlock = 0;
zap_log(ZAP_LOG_DEBUG, "got sig [%s]\n", zap_signal_event2str(sigmsg->event_id)); 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) { switch(sigmsg->event_id) {
case ZAP_SIGEVENT_START: case ZAP_SIGEVENT_START:
{ {
@ -632,16 +661,48 @@ static ZIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
break; break;
case ZAP_SIGEVENT_STOP: case ZAP_SIGEVENT_STOP:
{ {
if (channel) { while((session = zap_channel_get_session(sigmsg->channel, 0))) {
zap_channel_clear_token(sigmsg->channel, 0);
channel = switch_core_session_get_channel(session);
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
zap_channel_set_token(sigmsg->channel, NULL); switch_core_session_rwunlock(session);
} }
} }
break; break;
}
if (session && rwlock) { case ZAP_SIGEVENT_FLASH:
switch_core_session_rwunlock(session); {
uint32_t i = 0;
for (i = 0; i < sigmsg->channel->token_count; i++) {
if ((session = zap_channel_get_session(sigmsg->channel, i))) {
tech_pvt = switch_core_session_get_private(session);
if (i) {
switch_set_flag_locked(tech_pvt, TFLAG_HOLD);
} else {
switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
}
switch_core_session_rwunlock(session);
}
}
}
case ZAP_SIGEVENT_HOLD:
{
if ((session = zap_channel_get_session(sigmsg->channel, sigmsg->channel->token_count-1))) {
tech_pvt = switch_core_session_get_private(session);
switch_set_flag_locked(tech_pvt, TFLAG_HOLD);
switch_core_session_rwunlock(session);
}
}
break;
case ZAP_SIGEVENT_UNHOLD:
{
if ((session = zap_channel_get_session(sigmsg->channel, sigmsg->channel->token_count-1))) {
tech_pvt = switch_core_session_get_private(session);
switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
switch_core_session_rwunlock(session);
}
}
break;
} }
return status; return status;

View File

@ -157,6 +157,7 @@
#define zap_channel_test_feature(obj, flag) ((obj)->features & flag) #define zap_channel_test_feature(obj, flag) ((obj)->features & flag)
#define zap_channel_set_feature(obj, flag) (obj)->features |= (flag) #define zap_channel_set_feature(obj, flag) (obj)->features |= (flag)
#define zap_channel_clear_feature(obj, flag) (obj)->features &= ~(flag) #define zap_channel_clear_feature(obj, flag) (obj)->features &= ~(flag)
#define zap_channel_set_member_locked(obj, _m, _v) zap_mutex_lock(obj->mutex); obj->_m = _v; zap_mutex_unlock(obj->mutex)
/*! /*!
\brief Test for the existance of a flag on an arbitary object \brief Test for the existance of a flag on an arbitary object
@ -218,6 +219,9 @@ struct zap_event {
void *data; void *data;
}; };
#define ZAP_TOKEN_STRLEN 128
#define ZAP_MAX_TOKENS 10
struct zap_channel { struct zap_channel {
uint32_t span_id; uint32_t span_id;
uint32_t chan_id; uint32_t chan_id;
@ -245,7 +249,8 @@ struct zap_channel {
uint32_t dtmf_off; uint32_t dtmf_off;
teletone_generation_session_t tone_session; teletone_generation_session_t tone_session;
zap_time_t last_event_time; zap_time_t last_event_time;
char token[128]; char tokens[ZAP_MAX_TOKENS+1][ZAP_TOKEN_STRLEN];
uint32_t token_count;
char chan_name[128]; char chan_name[128];
char chan_number[32]; char chan_number[32];
struct zap_span *span; struct zap_span *span;
@ -322,7 +327,9 @@ struct zap_io_interface {
struct zap_span spans[ZAP_MAX_SPANS_INTERFACE]; struct zap_span spans[ZAP_MAX_SPANS_INTERFACE];
}; };
zap_status_t zap_channel_set_token(zap_channel_t *zchan, char *token); void zap_channel_rotate_tokens(zap_channel_t *zchan);
zap_status_t zap_channel_clear_token(zap_channel_t *zchan, int32_t token_id);
zap_status_t zap_channel_add_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_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_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); zap_size_t zap_channel_dequeue_dtmf(zap_channel_t *zchan, char *dtmf, zap_size_t len);

View File

@ -101,13 +101,16 @@ typedef enum {
ZAP_SIGEVENT_TRANSFER, ZAP_SIGEVENT_TRANSFER,
ZAP_SIGEVENT_ANSWER, ZAP_SIGEVENT_ANSWER,
ZAP_SIGEVENT_UP, ZAP_SIGEVENT_UP,
ZAP_SIGEVENT_HOLD,
ZAP_SIGEVENT_UNHOLD,
ZAP_SIGEVENT_FLASH,
ZAP_SIGEVENT_PROGRESS, ZAP_SIGEVENT_PROGRESS,
ZAP_SIGEVENT_PROGRESS_MEDIA, ZAP_SIGEVENT_PROGRESS_MEDIA,
ZAP_SIGEVENT_NOTIFY, ZAP_SIGEVENT_NOTIFY,
ZAP_SIGEVENT_MISC, ZAP_SIGEVENT_MISC,
ZAP_SIGEVENT_INVALID ZAP_SIGEVENT_INVALID
} zap_signal_event_t; } zap_signal_event_t;
#define SIGNAL_STRINGS "START", "STOP", "TRANSFER", "ANSWER", "UP", "PROGRESS", "PROGRESS_MEDIA", "NOTIFY", "MISC", "INVALID" #define SIGNAL_STRINGS "START", "STOP", "TRANSFER", "ANSWER", "UP", "HOLD", "UNHOLD", "FLASH", "PROGRESS", "PROGRESS_MEDIA", "NOTIFY", "MISC", "INVALID"
ZAP_STR2ENUM_P(zap_str2zap_signal_event, zap_signal_event2str, zap_signal_event_t) ZAP_STR2ENUM_P(zap_str2zap_signal_event, zap_signal_event2str, zap_signal_event_t)
typedef enum { typedef enum {
@ -193,6 +196,7 @@ typedef enum {
ZAP_CHANNEL_STATE_DOWN, ZAP_CHANNEL_STATE_DOWN,
ZAP_CHANNEL_STATE_UP, ZAP_CHANNEL_STATE_UP,
ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_HANGUP,
ZAP_CHANNEL_STATE_HOLD,
ZAP_CHANNEL_STATE_DIALTONE, ZAP_CHANNEL_STATE_DIALTONE,
ZAP_CHANNEL_STATE_COLLECT, ZAP_CHANNEL_STATE_COLLECT,
ZAP_CHANNEL_STATE_RING, ZAP_CHANNEL_STATE_RING,
@ -201,7 +205,7 @@ typedef enum {
ZAP_CHANNEL_STATE_IDLE, ZAP_CHANNEL_STATE_IDLE,
ZAP_CHANNEL_STATE_INVALID ZAP_CHANNEL_STATE_INVALID
} zap_channel_state_t; } zap_channel_state_t;
#define CHANNEL_STATE_STRINGS "DOWN", "UP", "HANGUP", "DIALTONE", "COLLECT", "RING", "BUSY", "ATTN", "IDLE", "INVALID" #define CHANNEL_STATE_STRINGS "DOWN", "UP", "HANGUP", "HOLD", "DIALTONE", "COLLECT", "RING", "BUSY", "ATTN", "IDLE", "INVALID"
ZAP_STR2ENUM_P(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t) ZAP_STR2ENUM_P(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t)
typedef enum { typedef enum {
@ -216,7 +220,8 @@ typedef enum {
ZAP_CHANNEL_INTHREAD = (1 << 8), ZAP_CHANNEL_INTHREAD = (1 << 8),
ZAP_CHANNEL_WINK = (1 << 9), ZAP_CHANNEL_WINK = (1 << 9),
ZAP_CHANNEL_FLASH = (1 << 10), ZAP_CHANNEL_FLASH = (1 << 10),
ZAP_CHANNEL_STATE_CHANGE = (1 << 11) ZAP_CHANNEL_STATE_CHANGE = (1 << 11),
ZAP_CHANNEL_HOLD = (1 << 12)
} zap_channel_flag_t; } zap_channel_flag_t;

View File

@ -87,7 +87,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
uint8_t frame[1024]; uint8_t frame[1024];
zap_size_t len, rlen; zap_size_t len, rlen;
zap_tone_type_t tt = ZAP_TONE_DTMF; zap_tone_type_t tt = ZAP_TONE_DTMF;
char dtmf[128]; char dtmf[128] = "";
zap_size_t dtmf_offset = 0; zap_size_t dtmf_offset = 0;
zap_analog_data_t *data = chan->span->analog_data; zap_analog_data_t *data = chan->span->analog_data;
zap_channel_t *closed_chan; zap_channel_t *closed_chan;
@ -119,6 +119,12 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
zap_channel_command(chan, ZAP_COMMAND_GET_INTERVAL, &interval); zap_channel_command(chan, ZAP_COMMAND_GET_INTERVAL, &interval);
zap_buffer_set_loops(dt_buffer, -1); zap_buffer_set_loops(dt_buffer, -1);
memset(&sig, 0, sizeof(sig));
sig.chan_id = chan->chan_id;
sig.span_id = chan->span_id;
sig.channel = chan;
sig.span = chan->span;
while (zap_test_flag(chan, ZAP_CHANNEL_INTHREAD)) { while (zap_test_flag(chan, ZAP_CHANNEL_INTHREAD)) {
zap_wait_flag_t flags = ZAP_READ; zap_wait_flag_t flags = ZAP_READ;
@ -169,20 +175,18 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
switch(chan->state) { switch(chan->state) {
case ZAP_CHANNEL_STATE_UP: case ZAP_CHANNEL_STATE_UP:
{ {
sig.event_id = ZAP_SIGEVENT_UP; if (zap_test_flag(chan, ZAP_CHANNEL_HOLD)) {
sig.event_id = ZAP_SIGEVENT_UNHOLD;
} else {
sig.event_id = ZAP_SIGEVENT_UP;
}
data->sig_cb(&sig); data->sig_cb(&sig);
continue; continue;
} }
break; break;
case ZAP_CHANNEL_STATE_IDLE: case ZAP_CHANNEL_STATE_IDLE:
{ {
memset(&sig, 0, sizeof(sig));
sig.event_id = ZAP_SIGEVENT_START; sig.event_id = ZAP_SIGEVENT_START;
sig.chan_id = chan->chan_id;
sig.span_id = chan->span_id;
sig.channel = chan;
sig.span = chan->span;
zap_copy_string(sig.dnis, dtmf, sizeof(sig.dnis)); zap_copy_string(sig.dnis, dtmf, sizeof(sig.dnis));
data->sig_cb(&sig); data->sig_cb(&sig);
continue; continue;
@ -195,8 +199,18 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
goto done; goto done;
} }
break; break;
case ZAP_CHANNEL_STATE_HOLD:
{
sig.event_id = ZAP_SIGEVENT_HOLD;
data->sig_cb(&sig);
zap_set_flag_locked(chan, ZAP_CHANNEL_HOLD);
zap_set_state_locked(chan, ZAP_CHANNEL_STATE_DIALTONE);
}
break;
case ZAP_CHANNEL_STATE_DIALTONE: case ZAP_CHANNEL_STATE_DIALTONE:
{ {
*dtmf = '\0';
dtmf_offset = 0;
zap_buffer_zero(dt_buffer); zap_buffer_zero(dt_buffer);
teletone_run(&ts, chan->span->tone_map[ZAP_TONEMAP_DIAL]); teletone_run(&ts, chan->span->tone_map[ZAP_TONEMAP_DIAL]);
indicate = 1; indicate = 1;
@ -245,8 +259,8 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
last_digit = 0; last_digit = 0;
} }
if (zap_channel_wait(chan, &flags, interval * 2) == ZAP_FAIL) { if (zap_channel_wait(chan, &flags, interval * 2) != ZAP_SUCCESS) {
goto done; continue;
} }
if (!(flags & ZAP_READ)) { if (!(flags & ZAP_READ)) {
@ -313,12 +327,41 @@ static zap_status_t process_event(zap_span_t *span, zap_event_t *event)
{ {
zap_log(ZAP_LOG_DEBUG, "EVENT [%s][%d:%d]\n", zap_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id); zap_log(ZAP_LOG_DEBUG, "EVENT [%s][%d:%d]\n", zap_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id);
zap_mutex_lock(event->channel->mutex);
switch(event->enum_id) { switch(event->enum_id) {
case ZAP_OOB_ONHOOK: case ZAP_OOB_ONHOOK:
{ {
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_DOWN); zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_DOWN);
} }
break; break;
case ZAP_OOB_FLASH:
{
zap_sigmsg_t sig;
zap_analog_data_t *data = event->channel->span->analog_data;
memset(&sig, 0, sizeof(sig));
sig.chan_id = event->channel->chan_id;
sig.span_id = event->channel->span_id;
sig.channel = event->channel;
sig.span = event->channel->span;
if (event->channel->state == ZAP_CHANNEL_STATE_UP) {
if (event->channel->token_count > 1) {
zap_channel_rotate_tokens(event->channel);
sig.event_id = ZAP_SIGEVENT_FLASH;
data->sig_cb(&sig);
} else {
if (zap_test_flag(event->channel, ZAP_CHANNEL_HOLD)) {
zap_clear_flag_locked(event->channel, ZAP_CHANNEL_HOLD);
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_UP);
} else {
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_HOLD);
}
}
}
}
break;
case ZAP_OOB_OFFHOOK: case ZAP_OOB_OFFHOOK:
{ {
if (!zap_test_flag(event->channel, ZAP_CHANNEL_INTHREAD)) { if (!zap_test_flag(event->channel, ZAP_CHANNEL_INTHREAD)) {
@ -328,7 +371,7 @@ static zap_status_t process_event(zap_span_t *span, zap_event_t *event)
} }
} }
zap_mutex_unlock(event->channel->mutex);
return ZAP_SUCCESS; return ZAP_SUCCESS;
} }

View File

@ -370,16 +370,54 @@ zap_status_t zap_channel_set_event_callback(zap_channel_t *zchan, zio_event_cb_t
return ZAP_SUCCESS; return ZAP_SUCCESS;
} }
zap_status_t zap_channel_set_token(zap_channel_t *zchan, char *token) zap_status_t zap_channel_clear_token(zap_channel_t *zchan, int32_t token_id)
{ {
zap_status_t status = ZAP_FAIL;
zap_mutex_lock(zchan->mutex); zap_mutex_lock(zchan->mutex);
if (token) { if (token_id == -1) {
zap_copy_string(zchan->token, token, sizeof(zchan->token)); memset(zchan->tokens, 0, sizeof(zchan->tokens));
} else { zchan->token_count = 0;
*zchan->token = '\0'; } else if (*zchan->tokens[token_id] != '\0') {
char tokens[ZAP_MAX_TOKENS][ZAP_TOKEN_STRLEN];
int32_t i, count = zchan->token_count;
memcpy(tokens, zchan->tokens, sizeof(tokens));
memset(zchan->tokens, 0, sizeof(zchan->tokens));
zchan->token_count = 0;
for (i = 0; i < count; i++) {
if (i != token_id) {
zap_copy_string(zchan->tokens[zchan->token_count], tokens[i], sizeof(zchan->tokens[zchan->token_count]));
zchan->token_count++;
}
}
status = ZAP_SUCCESS;
} }
zap_mutex_unlock(zchan->mutex); zap_mutex_unlock(zchan->mutex);
return ZAP_SUCCESS;
return status;
}
void zap_channel_rotate_tokens(zap_channel_t *zchan)
{
memmove(zchan->tokens[1], zchan->tokens[0], zchan->token_count * ZAP_TOKEN_STRLEN);
zap_copy_string(zchan->tokens[0], zchan->tokens[zchan->token_count], ZAP_TOKEN_STRLEN);
*zchan->tokens[zchan->token_count] = '\0';
}
zap_status_t zap_channel_add_token(zap_channel_t *zchan, char *token)
{
zap_status_t status = ZAP_FAIL;
zap_mutex_lock(zchan->mutex);
if (zchan->token_count < ZAP_MAX_TOKENS) {
zap_copy_string(zchan->tokens[zchan->token_count], token, sizeof(zchan->tokens[zchan->token_count]));
zchan->token_count++;
}
zap_mutex_unlock(zchan->mutex);
return status;
} }
@ -523,6 +561,10 @@ static zap_status_t zap_channel_reset(zap_channel_t *zchan)
zchan->event_callback = NULL; zchan->event_callback = NULL;
zap_clear_flag(zchan, ZAP_CHANNEL_DTMF_DETECT); zap_clear_flag(zchan, ZAP_CHANNEL_DTMF_DETECT);
zap_clear_flag(zchan, ZAP_CHANNEL_SUPRESS_DTMF); zap_clear_flag(zchan, ZAP_CHANNEL_SUPRESS_DTMF);
zap_clear_flag_locked(zchan, ZAP_CHANNEL_HOLD);
memset(zchan->tokens, 0, sizeof(zchan->tokens));
zchan->token_count = 0;
if (zchan->tone_session.buffer) { if (zchan->tone_session.buffer) {
teletone_destroy_session(&zchan->tone_session); teletone_destroy_session(&zchan->tone_session);
memset(&zchan->tone_session, 0, sizeof(zchan->tone_session)); memset(&zchan->tone_session, 0, sizeof(zchan->tone_session));
@ -605,6 +647,7 @@ zap_status_t zap_channel_close(zap_channel_t **zchan)
assert(check != NULL); assert(check != NULL);
*zchan = NULL; *zchan = NULL;
zap_mutex_lock(check->mutex); zap_mutex_lock(check->mutex);
if (zap_test_flag(check, ZAP_CHANNEL_OPEN)) { if (zap_test_flag(check, ZAP_CHANNEL_OPEN)) {
status = check->zio->close(check); status = check->zio->close(check);