add call waiting
git-svn-id: http://svn.openzap.org/svn/openzap/trunk@243 a93c3328-9c30-0410-af19-c9cd2b2d52af
This commit is contained in:
parent
6f5e521686
commit
1761662524
|
@ -86,7 +86,6 @@ 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;
|
|
||||||
uint32_t wr_error;
|
uint32_t wr_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,6 +105,54 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
|
||||||
static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
|
static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
|
||||||
|
|
||||||
|
|
||||||
|
static switch_core_session_t *zap_channel_get_session(zap_channel_t *channel, int32_t id)
|
||||||
|
{
|
||||||
|
switch_core_session_t *session = NULL;
|
||||||
|
|
||||||
|
if (id > ZAP_MAX_TOKENS) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!switch_strlen_zero(channel->tokens[id])) {
|
||||||
|
session = switch_core_session_locate(channel->tokens[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cycle_foreground(zap_channel_t *zchan, int flash) {
|
||||||
|
uint32_t i = 0;
|
||||||
|
switch_core_session_t *session;
|
||||||
|
switch_channel_t *channel;
|
||||||
|
private_t *tech_pvt;
|
||||||
|
|
||||||
|
for (i = 0; i < zchan->token_count; i++) {
|
||||||
|
if ((session = zap_channel_get_session(zchan, i))) {
|
||||||
|
tech_pvt = switch_core_session_get_private(session);
|
||||||
|
channel = switch_core_session_get_channel(session);
|
||||||
|
if (zchan->token_count == 1 && flash) {
|
||||||
|
if (switch_test_flag(tech_pvt, TFLAG_HOLD)) {
|
||||||
|
switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
|
||||||
|
} else {
|
||||||
|
switch_set_flag_locked(tech_pvt, TFLAG_HOLD);
|
||||||
|
}
|
||||||
|
} else if (i) {
|
||||||
|
switch_set_flag_locked(tech_pvt, TFLAG_HOLD);
|
||||||
|
} else {
|
||||||
|
switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
|
||||||
|
if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
|
||||||
|
switch_channel_mark_answered(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch_core_session_rwunlock(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *session, zap_channel_t *zchan)
|
static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *session, zap_channel_t *zchan)
|
||||||
{
|
{
|
||||||
char *dname = NULL;
|
char *dname = NULL;
|
||||||
|
@ -247,7 +294,8 @@ 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_clear_token(tech_pvt->zchan, tech_pvt->token_id);
|
|
||||||
|
zap_channel_clear_token(tech_pvt->zchan, switch_core_session_get_uuid(session));
|
||||||
|
|
||||||
switch (tech_pvt->zchan->type) {
|
switch (tech_pvt->zchan->type) {
|
||||||
case ZAP_CHAN_TYPE_FXO:
|
case ZAP_CHAN_TYPE_FXO:
|
||||||
|
@ -260,9 +308,13 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
|
||||||
case ZAP_CHAN_TYPE_FXS:
|
case ZAP_CHAN_TYPE_FXS:
|
||||||
{
|
{
|
||||||
if (tech_pvt->zchan->state != ZAP_CHANNEL_STATE_DOWN) {
|
if (tech_pvt->zchan->state != ZAP_CHANNEL_STATE_DOWN) {
|
||||||
|
if (tech_pvt->zchan->token_count) {
|
||||||
|
cycle_foreground(tech_pvt->zchan, 0);
|
||||||
|
} else {
|
||||||
zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_HANGUP);
|
zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_HANGUP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
@ -639,15 +691,15 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
|
||||||
status = zap_channel_open(span_id, chan_id, &zchan);
|
status = zap_channel_open(span_id, chan_id, &zchan);
|
||||||
} else {
|
} else {
|
||||||
status = zap_channel_open_any(span_id, ZAP_TOP_DOWN, &zchan);
|
status = zap_channel_open_any(span_id, ZAP_TOP_DOWN, &zchan);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (status != ZAP_SUCCESS) {
|
if (status != ZAP_SUCCESS) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No channels available\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No channels available\n");
|
||||||
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
|
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ((*new_session = switch_core_session_request(&channel_endpoint_interface, pool)) != 0) {
|
if ((*new_session = switch_core_session_request(&channel_endpoint_interface, pool)) != 0) {
|
||||||
private_t *tech_pvt;
|
private_t *tech_pvt;
|
||||||
switch_channel_t *channel;
|
switch_channel_t *channel;
|
||||||
|
@ -676,13 +728,27 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
|
||||||
|
|
||||||
switch_channel_set_flag(channel, CF_OUTBOUND);
|
switch_channel_set_flag(channel, CF_OUTBOUND);
|
||||||
switch_channel_set_state(channel, CS_INIT);
|
switch_channel_set_state(channel, CS_INIT);
|
||||||
if ((tech_pvt->token_id = zap_channel_add_token(zchan, switch_core_session_get_uuid(*new_session))) < 0) {
|
if (zap_channel_add_token(zchan, switch_core_session_get_uuid(*new_session), zchan->token_count) != ZAP_SUCCESS) {
|
||||||
switch_core_session_destroy(new_session);
|
switch_core_session_destroy(new_session);
|
||||||
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
|
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
zap_channel_outgoing_call(zchan);
|
|
||||||
|
if (zap_channel_outgoing_call(zchan) != ZAP_SUCCESS) {
|
||||||
|
if (tech_pvt->read_codec.implementation) {
|
||||||
|
switch_core_codec_destroy(&tech_pvt->read_codec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tech_pvt->write_codec.implementation) {
|
||||||
|
switch_core_codec_destroy(&tech_pvt->write_codec);
|
||||||
|
}
|
||||||
|
switch_core_session_destroy(new_session);
|
||||||
|
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return SWITCH_CAUSE_SUCCESS;
|
return SWITCH_CAUSE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -758,7 +824,7 @@ zap_status_t zap_channel_from_event(zap_sigmsg_t *sigmsg, switch_core_session_t
|
||||||
return ZAP_FAIL;
|
return ZAP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((tech_pvt->token_id = zap_channel_add_token(sigmsg->channel, switch_core_session_get_uuid(session))) < 0) {
|
if (zap_channel_add_token(sigmsg->channel, switch_core_session_get_uuid(session), 0) != ZAP_SUCCESS) {
|
||||||
switch_core_session_destroy(&session);
|
switch_core_session_destroy(&session);
|
||||||
return ZAP_FAIL;
|
return ZAP_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -767,20 +833,6 @@ zap_status_t zap_channel_from_event(zap_sigmsg_t *sigmsg, switch_core_session_t
|
||||||
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 (id > ZAP_MAX_TOKENS) {
|
|
||||||
return 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)
|
||||||
{
|
{
|
||||||
|
@ -853,24 +905,7 @@ static ZIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
|
||||||
|
|
||||||
case ZAP_SIGEVENT_FLASH:
|
case ZAP_SIGEVENT_FLASH:
|
||||||
{
|
{
|
||||||
uint32_t i = 0;
|
cycle_foreground(sigmsg->channel, 1);
|
||||||
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 (sigmsg->channel->token_count == 1) {
|
|
||||||
if (switch_test_flag(tech_pvt, TFLAG_HOLD)) {
|
|
||||||
switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
|
|
||||||
} else {
|
|
||||||
switch_set_flag_locked(tech_pvt, TFLAG_HOLD);
|
|
||||||
}
|
|
||||||
} else if (i) {
|
|
||||||
switch_set_flag_locked(tech_pvt, TFLAG_HOLD);
|
|
||||||
} else {
|
|
||||||
switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
|
|
||||||
}
|
|
||||||
switch_core_session_rwunlock(session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -446,8 +446,8 @@ void zap_channel_rotate_tokens(zap_channel_t *zchan);
|
||||||
void zap_channel_clear_detected_tones(zap_channel_t *zchan);
|
void zap_channel_clear_detected_tones(zap_channel_t *zchan);
|
||||||
void zap_channel_clear_needed_tones(zap_channel_t *zchan);
|
void zap_channel_clear_needed_tones(zap_channel_t *zchan);
|
||||||
zap_status_t zap_channel_send_fsk_data(zap_channel_t *zchan, zap_fsk_data_state_t *fsk_data, float db_level);
|
zap_status_t zap_channel_send_fsk_data(zap_channel_t *zchan, zap_fsk_data_state_t *fsk_data, float db_level);
|
||||||
zap_status_t zap_channel_clear_token(zap_channel_t *zchan, int32_t token_id);
|
zap_status_t zap_channel_clear_token(zap_channel_t *zchan, const char *token);
|
||||||
zap_status_t zap_channel_add_token(zap_channel_t *zchan, char *token);
|
zap_status_t zap_channel_add_token(zap_channel_t *zchan, char *token, int end);
|
||||||
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);
|
||||||
|
|
|
@ -97,9 +97,12 @@ typedef enum {
|
||||||
ZAP_TONEMAP_FAIL2,
|
ZAP_TONEMAP_FAIL2,
|
||||||
ZAP_TONEMAP_FAIL3,
|
ZAP_TONEMAP_FAIL3,
|
||||||
ZAP_TONEMAP_ATTN,
|
ZAP_TONEMAP_ATTN,
|
||||||
|
ZAP_TONEMAP_CALLWAITING_CAS,
|
||||||
|
ZAP_TONEMAP_CALLWAITING_SAS,
|
||||||
|
ZAP_TONEMAP_CALLWAITING_ACK,
|
||||||
ZAP_TONEMAP_INVALID
|
ZAP_TONEMAP_INVALID
|
||||||
} zap_tonemap_t;
|
} zap_tonemap_t;
|
||||||
#define TONEMAP_STRINGS "NONE", "DIAL", "RING", "BUSY", "FAIL1", "FAIL2", "FAIL3", "ATTN", "INVALID"
|
#define TONEMAP_STRINGS "NONE", "DIAL", "RING", "BUSY", "FAIL1", "FAIL2", "FAIL3", "ATTN", "CALLWAITING-CAS", "CALLWAITING-SAS", "CALLWAITING-ACK", "INVALID"
|
||||||
ZAP_STR2ENUM_P(zap_str2zap_tonemap, zap_tonemap2str, zap_tonemap_t)
|
ZAP_STR2ENUM_P(zap_str2zap_tonemap, zap_tonemap2str, zap_tonemap_t)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -254,10 +257,11 @@ typedef enum {
|
||||||
ZAP_CHANNEL_STATE_GENRING,
|
ZAP_CHANNEL_STATE_GENRING,
|
||||||
ZAP_CHANNEL_STATE_DIALING,
|
ZAP_CHANNEL_STATE_DIALING,
|
||||||
ZAP_CHANNEL_STATE_GET_CALLERID,
|
ZAP_CHANNEL_STATE_GET_CALLERID,
|
||||||
|
ZAP_CHANNEL_STATE_CALLWAITING,
|
||||||
ZAP_CHANNEL_STATE_INVALID
|
ZAP_CHANNEL_STATE_INVALID
|
||||||
} zap_channel_state_t;
|
} zap_channel_state_t;
|
||||||
#define CHANNEL_STATE_STRINGS "DOWN", "UP", "HANGUP", "HOLD", "DIALTONE", "COLLECT", \
|
#define CHANNEL_STATE_STRINGS "DOWN", "UP", "HANGUP", "HOLD", "DIALTONE", "COLLECT", \
|
||||||
"RING", "BUSY", "ATTN", "IDLE", "GENRING", "DIALING", "GET_CALLERID", "INVALID"
|
"RING", "BUSY", "ATTN", "IDLE", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", "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 {
|
||||||
|
|
|
@ -46,13 +46,16 @@ static ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxo_outgoing_call)
|
||||||
zap_thread_create_detached(zap_analog_channel_run, zchan);
|
zap_thread_create_detached(zap_analog_channel_run, zchan);
|
||||||
return ZAP_SUCCESS;
|
return ZAP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ZAP_FAIL;
|
return ZAP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxs_outgoing_call)
|
static ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxs_outgoing_call)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!zap_test_flag(zchan, ZAP_CHANNEL_INTHREAD)) {
|
if (zap_test_flag(zchan, ZAP_CHANNEL_INTHREAD)) {
|
||||||
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_CALLWAITING);
|
||||||
|
} else {
|
||||||
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_GENRING);
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_GENRING);
|
||||||
zap_thread_create_detached(zap_analog_channel_run, zchan);
|
zap_thread_create_detached(zap_analog_channel_run, zchan);
|
||||||
}
|
}
|
||||||
|
@ -106,6 +109,51 @@ static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void send_caller_id(zap_channel_t *chan)
|
||||||
|
{
|
||||||
|
zap_fsk_data_state_t fsk_data;
|
||||||
|
uint8_t databuf[1024] = "";
|
||||||
|
char time_str[9];
|
||||||
|
struct tm tm;
|
||||||
|
time_t now;
|
||||||
|
zap_mdmf_type_t mt = MDMF_INVALID;
|
||||||
|
|
||||||
|
time(&now);
|
||||||
|
#ifdef WIN32
|
||||||
|
_tzset();
|
||||||
|
_localtime64_s(&tm, &now);
|
||||||
|
#else
|
||||||
|
localtime_r(&now, &tm);
|
||||||
|
#endif
|
||||||
|
strftime(time_str, sizeof(time_str), "%m%d%H%M", &tm);
|
||||||
|
|
||||||
|
zap_fsk_data_init(&fsk_data, databuf, sizeof(databuf));
|
||||||
|
zap_fsk_data_add_mdmf(&fsk_data, MDMF_DATETIME, (uint8_t *) time_str, 8);
|
||||||
|
|
||||||
|
if (zap_strlen_zero(chan->caller_data.cid_num)) {
|
||||||
|
mt = MDMF_NO_NUM;
|
||||||
|
zap_set_string(chan->caller_data.cid_num, "O");
|
||||||
|
} else if (!strcasecmp(chan->caller_data.cid_num, "P") || !strcasecmp(chan->caller_data.cid_num, "O")) {
|
||||||
|
mt = MDMF_NO_NUM;
|
||||||
|
} else {
|
||||||
|
mt = MDMF_PHONE_NUM;
|
||||||
|
}
|
||||||
|
zap_fsk_data_add_mdmf(&fsk_data, mt, (uint8_t *) chan->caller_data.cid_num, (uint8_t)strlen(chan->caller_data.cid_num));
|
||||||
|
|
||||||
|
if (zap_strlen_zero(chan->caller_data.cid_name)) {
|
||||||
|
mt = MDMF_NO_NAME;
|
||||||
|
zap_set_string(chan->caller_data.cid_name, "O");
|
||||||
|
} else if (!strcasecmp(chan->caller_data.cid_name, "P") || !strcasecmp(chan->caller_data.cid_name, "O")) {
|
||||||
|
mt = MDMF_NO_NAME;
|
||||||
|
} else {
|
||||||
|
mt = MDMF_PHONE_NAME;
|
||||||
|
}
|
||||||
|
zap_fsk_data_add_mdmf(&fsk_data, mt, (uint8_t *) chan->caller_data.cid_name, (uint8_t)strlen(chan->caller_data.cid_name));
|
||||||
|
|
||||||
|
zap_fsk_data_add_checksum(&fsk_data);
|
||||||
|
zap_channel_send_fsk_data(chan, &fsk_data, -14);
|
||||||
|
}
|
||||||
|
|
||||||
static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
|
static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
|
||||||
{
|
{
|
||||||
zap_channel_t *chan = (zap_channel_t *) obj;
|
zap_channel_t *chan = (zap_channel_t *) obj;
|
||||||
|
@ -231,6 +279,37 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ZAP_CHANNEL_STATE_CALLWAITING:
|
||||||
|
{
|
||||||
|
int done = 0;
|
||||||
|
|
||||||
|
if (chan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] == 1) {
|
||||||
|
send_caller_id(chan);
|
||||||
|
chan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]++;
|
||||||
|
} else if (state_counter > 600 && !chan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]) {
|
||||||
|
send_caller_id(chan);
|
||||||
|
chan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]++;
|
||||||
|
} else if (state_counter > 1000 && !chan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]) {
|
||||||
|
done = 1;
|
||||||
|
} else if (state_counter > 10000) {
|
||||||
|
if (chan->fsk_buffer) {
|
||||||
|
zap_buffer_zero(chan->fsk_buffer);
|
||||||
|
} else {
|
||||||
|
zap_buffer_create(&chan->fsk_buffer, 128, 128, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ts.user_data = chan->fsk_buffer;
|
||||||
|
teletone_run(&ts, chan->span->tone_map[ZAP_TONEMAP_CALLWAITING_SAS]);
|
||||||
|
ts.user_data = dt_buffer;
|
||||||
|
done = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done) {
|
||||||
|
zap_set_state_locked(chan, ZAP_CHANNEL_STATE_UP);
|
||||||
|
zap_clear_flag_locked(chan, ZAP_CHANNEL_STATE_CHANGE);
|
||||||
|
chan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
case ZAP_CHANNEL_STATE_UP:
|
case ZAP_CHANNEL_STATE_UP:
|
||||||
case ZAP_CHANNEL_STATE_IDLE:
|
case ZAP_CHANNEL_STATE_IDLE:
|
||||||
{
|
{
|
||||||
|
@ -267,7 +346,6 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
|
||||||
zap_buffer_zero(chan->fsk_buffer);
|
zap_buffer_zero(chan->fsk_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (chan->type == ZAP_CHAN_TYPE_FXS && zap_test_flag(chan, ZAP_CHANNEL_RINGING)) {
|
if (chan->type == ZAP_CHAN_TYPE_FXS && zap_test_flag(chan, ZAP_CHANNEL_RINGING)) {
|
||||||
zap_channel_command(chan, ZAP_COMMAND_GENERATE_RING_OFF, NULL);
|
zap_channel_command(chan, ZAP_COMMAND_GENERATE_RING_OFF, NULL);
|
||||||
}
|
}
|
||||||
|
@ -321,49 +399,24 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
|
||||||
indicate = 1;
|
indicate = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ZAP_CHANNEL_STATE_CALLWAITING:
|
||||||
|
{
|
||||||
|
chan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] = 0;
|
||||||
|
if (chan->fsk_buffer) {
|
||||||
|
zap_buffer_zero(chan->fsk_buffer);
|
||||||
|
} else {
|
||||||
|
zap_buffer_create(&chan->fsk_buffer, 128, 128, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ts.user_data = chan->fsk_buffer;
|
||||||
|
teletone_run(&ts, chan->span->tone_map[ZAP_TONEMAP_CALLWAITING_SAS]);
|
||||||
|
teletone_run(&ts, chan->span->tone_map[ZAP_TONEMAP_CALLWAITING_CAS]);
|
||||||
|
ts.user_data = dt_buffer;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ZAP_CHANNEL_STATE_GENRING:
|
case ZAP_CHANNEL_STATE_GENRING:
|
||||||
{
|
{
|
||||||
zap_fsk_data_state_t fsk_data;
|
send_caller_id(chan);
|
||||||
uint8_t databuf[1024] = "";
|
|
||||||
char time_str[9];
|
|
||||||
struct tm tm;
|
|
||||||
time_t now;
|
|
||||||
zap_mdmf_type_t mt = MDMF_INVALID;
|
|
||||||
|
|
||||||
time(&now);
|
|
||||||
#ifdef WIN32
|
|
||||||
_tzset();
|
|
||||||
_localtime64_s(&tm, &now);
|
|
||||||
#else
|
|
||||||
localtime_r(&now, &tm);
|
|
||||||
#endif
|
|
||||||
strftime(time_str, sizeof(time_str), "%m%d%H%M", &tm);
|
|
||||||
|
|
||||||
zap_fsk_data_init(&fsk_data, databuf, sizeof(databuf));
|
|
||||||
zap_fsk_data_add_mdmf(&fsk_data, MDMF_DATETIME, (uint8_t *) time_str, 8);
|
|
||||||
|
|
||||||
if (zap_strlen_zero(chan->caller_data.cid_num)) {
|
|
||||||
mt = MDMF_NO_NUM;
|
|
||||||
zap_set_string(chan->caller_data.cid_num, "O");
|
|
||||||
} else if (!strcasecmp(chan->caller_data.cid_num, "P") || !strcasecmp(chan->caller_data.cid_num, "O")) {
|
|
||||||
mt = MDMF_NO_NUM;
|
|
||||||
} else {
|
|
||||||
mt = MDMF_PHONE_NUM;
|
|
||||||
}
|
|
||||||
zap_fsk_data_add_mdmf(&fsk_data, mt, (uint8_t *) chan->caller_data.cid_num, (uint8_t)strlen(chan->caller_data.cid_num));
|
|
||||||
|
|
||||||
if (zap_strlen_zero(chan->caller_data.cid_name)) {
|
|
||||||
mt = MDMF_NO_NAME;
|
|
||||||
zap_set_string(chan->caller_data.cid_name, "O");
|
|
||||||
} else if (!strcasecmp(chan->caller_data.cid_name, "P") || !strcasecmp(chan->caller_data.cid_name, "O")) {
|
|
||||||
mt = MDMF_NO_NAME;
|
|
||||||
} else {
|
|
||||||
mt = MDMF_PHONE_NAME;
|
|
||||||
}
|
|
||||||
zap_fsk_data_add_mdmf(&fsk_data, mt, (uint8_t *) chan->caller_data.cid_name, (uint8_t)strlen(chan->caller_data.cid_name));
|
|
||||||
|
|
||||||
zap_fsk_data_add_checksum(&fsk_data);
|
|
||||||
zap_channel_send_fsk_data(chan, &fsk_data, -14);
|
|
||||||
//zap_channel_command(chan, ZAP_COMMAND_TRACE_OUTPUT, "/tmp/outbound.ul");
|
//zap_channel_command(chan, ZAP_COMMAND_TRACE_OUTPUT, "/tmp/outbound.ul");
|
||||||
zap_channel_command(chan, ZAP_COMMAND_GENERATE_RING_ON, NULL);
|
zap_channel_command(chan, ZAP_COMMAND_GENERATE_RING_ON, NULL);
|
||||||
}
|
}
|
||||||
|
@ -575,13 +628,18 @@ static zap_status_t process_event(zap_span_t *span, zap_event_t *event)
|
||||||
break;
|
break;
|
||||||
case ZAP_OOB_FLASH:
|
case ZAP_OOB_FLASH:
|
||||||
{
|
{
|
||||||
|
if (event->channel->state == ZAP_CHANNEL_STATE_CALLWAITING) {
|
||||||
|
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_UP);
|
||||||
|
zap_clear_flag_locked(event->channel, ZAP_CHANNEL_STATE_CHANGE);
|
||||||
|
event->channel->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
sig.event_id = ZAP_SIGEVENT_FLASH;
|
|
||||||
zap_channel_rotate_tokens(event->channel);
|
zap_channel_rotate_tokens(event->channel);
|
||||||
|
|
||||||
if (zap_test_flag(event->channel, ZAP_CHANNEL_HOLD)) {
|
if (zap_test_flag(event->channel, ZAP_CHANNEL_HOLD)) {
|
||||||
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_UP);
|
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_UP);
|
||||||
} else {
|
} else {
|
||||||
|
sig.event_id = ZAP_SIGEVENT_FLASH;
|
||||||
data->sig_cb(&sig);
|
data->sig_cb(&sig);
|
||||||
if (event->channel->token_count == 1) {
|
if (event->channel->token_count == 1) {
|
||||||
zap_set_flag_locked(event->channel, ZAP_CHANNEL_HOLD);
|
zap_set_flag_locked(event->channel, ZAP_CHANNEL_HOLD);
|
||||||
|
|
|
@ -426,9 +426,14 @@ zap_status_t zap_channel_send_fsk_data(zap_channel_t *zchan, zap_fsk_data_state_
|
||||||
if (!zchan->fsk_buffer) {
|
if (!zchan->fsk_buffer) {
|
||||||
zap_buffer_create(&zchan->fsk_buffer, 128, 128, 0);
|
zap_buffer_create(&zchan->fsk_buffer, 128, 128, 0);
|
||||||
}
|
}
|
||||||
zap_fsk_modulator_init(&fsk_trans, FSK_BELL202, zchan->rate, fsk_data, db_level, 180, 5, 180, zchan_fsk_write_sample, zchan);
|
if (zchan->token_count > 1) {
|
||||||
|
zap_fsk_modulator_init(&fsk_trans, FSK_BELL202, zchan->rate, fsk_data, db_level, 80, 5, 0, zchan_fsk_write_sample, zchan);
|
||||||
|
zap_fsk_modulator_send_all((&fsk_trans));
|
||||||
|
} else {
|
||||||
|
zap_fsk_modulator_init(&fsk_trans, FSK_BELL202, zchan->rate, fsk_data, db_level, 180, 5, 300, zchan_fsk_write_sample, zchan);
|
||||||
zap_fsk_modulator_send_all((&fsk_trans));
|
zap_fsk_modulator_send_all((&fsk_trans));
|
||||||
zchan->buffer_delay = 3500 / zchan->effective_interval;
|
zchan->buffer_delay = 3500 / zchan->effective_interval;
|
||||||
|
}
|
||||||
return ZAP_SUCCESS;
|
return ZAP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,15 +446,15 @@ 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_clear_token(zap_channel_t *zchan, int32_t token_id)
|
zap_status_t zap_channel_clear_token(zap_channel_t *zchan, const char *token)
|
||||||
{
|
{
|
||||||
zap_status_t status = ZAP_FAIL;
|
zap_status_t status = ZAP_FAIL;
|
||||||
|
|
||||||
zap_mutex_lock(zchan->mutex);
|
zap_mutex_lock(zchan->mutex);
|
||||||
if (token_id == -1) {
|
if (token == NULL) {
|
||||||
memset(zchan->tokens, 0, sizeof(zchan->tokens));
|
memset(zchan->tokens, 0, sizeof(zchan->tokens));
|
||||||
zchan->token_count = 0;
|
zchan->token_count = 0;
|
||||||
} else if (*zchan->tokens[token_id] != '\0') {
|
} else if (*token != '\0') {
|
||||||
char tokens[ZAP_MAX_TOKENS][ZAP_TOKEN_STRLEN];
|
char tokens[ZAP_MAX_TOKENS][ZAP_TOKEN_STRLEN];
|
||||||
int32_t i, count = zchan->token_count;
|
int32_t i, count = zchan->token_count;
|
||||||
memcpy(tokens, zchan->tokens, sizeof(tokens));
|
memcpy(tokens, zchan->tokens, sizeof(tokens));
|
||||||
|
@ -457,7 +462,7 @@ zap_status_t zap_channel_clear_token(zap_channel_t *zchan, int32_t token_id)
|
||||||
zchan->token_count = 0;
|
zchan->token_count = 0;
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
if (i != token_id) {
|
if (strcmp(tokens[i], token)) {
|
||||||
zap_copy_string(zchan->tokens[zchan->token_count], tokens[i], sizeof(zchan->tokens[zchan->token_count]));
|
zap_copy_string(zchan->tokens[zchan->token_count], tokens[i], sizeof(zchan->tokens[zchan->token_count]));
|
||||||
zchan->token_count++;
|
zchan->token_count++;
|
||||||
}
|
}
|
||||||
|
@ -479,16 +484,21 @@ void zap_channel_rotate_tokens(zap_channel_t *zchan)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zap_status_t zap_channel_add_token(zap_channel_t *zchan, char *token)
|
zap_status_t zap_channel_add_token(zap_channel_t *zchan, char *token, int end)
|
||||||
{
|
{
|
||||||
zap_status_t status = ZAP_FAIL;
|
zap_status_t status = ZAP_FAIL;
|
||||||
|
|
||||||
zap_mutex_lock(zchan->mutex);
|
zap_mutex_lock(zchan->mutex);
|
||||||
if (zchan->token_count < ZAP_MAX_TOKENS) {
|
if (zchan->token_count < ZAP_MAX_TOKENS) {
|
||||||
|
if (end) {
|
||||||
|
zap_copy_string(zchan->tokens[zchan->token_count++], token, ZAP_TOKEN_STRLEN);
|
||||||
|
} else {
|
||||||
memmove(zchan->tokens[1], zchan->tokens[0], zchan->token_count * ZAP_TOKEN_STRLEN);
|
memmove(zchan->tokens[1], zchan->tokens[0], zchan->token_count * ZAP_TOKEN_STRLEN);
|
||||||
zap_copy_string(zchan->tokens[0], token, ZAP_TOKEN_STRLEN);
|
zap_copy_string(zchan->tokens[0], token, ZAP_TOKEN_STRLEN);
|
||||||
zchan->token_count++;
|
zchan->token_count++;
|
||||||
}
|
}
|
||||||
|
status = ZAP_SUCCESS;
|
||||||
|
}
|
||||||
zap_mutex_unlock(zchan->mutex);
|
zap_mutex_unlock(zchan->mutex);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -672,6 +682,9 @@ zap_status_t zap_channel_open_chan(zap_channel_t *zchan)
|
||||||
if ((status = zap_mutex_trylock(zchan->mutex)) != ZAP_SUCCESS) {
|
if ((status = zap_mutex_trylock(zchan->mutex)) != ZAP_SUCCESS) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = ZAP_FAIL;
|
||||||
|
|
||||||
if (zap_test_flag(zchan, ZAP_CHANNEL_READY)) {
|
if (zap_test_flag(zchan, ZAP_CHANNEL_READY)) {
|
||||||
status = zchan->span->zio->open(zchan);
|
status = zchan->span->zio->open(zchan);
|
||||||
if (status == ZAP_SUCCESS) {
|
if (status == ZAP_SUCCESS) {
|
||||||
|
@ -698,7 +711,10 @@ zap_status_t zap_channel_open(uint32_t span_id, uint32_t chan_id, zap_channel_t
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zap_test_flag(check, ZAP_CHANNEL_READY) && !zap_test_flag(check, ZAP_CHANNEL_INUSE)) {
|
status = ZAP_FAIL;
|
||||||
|
|
||||||
|
if (zap_test_flag(check, ZAP_CHANNEL_READY) && (!zap_test_flag(check, ZAP_CHANNEL_INUSE) ||
|
||||||
|
(check->type == ZAP_CHAN_TYPE_FXS && check->token_count == 1))) {
|
||||||
if (!zap_test_flag(check, ZAP_CHANNEL_OPEN)) {
|
if (!zap_test_flag(check, ZAP_CHANNEL_OPEN)) {
|
||||||
status = check->zio->open(check);
|
status = check->zio->open(check);
|
||||||
if (status == ZAP_SUCCESS) {
|
if (status == ZAP_SUCCESS) {
|
||||||
|
@ -714,7 +730,6 @@ zap_status_t zap_channel_open(uint32_t span_id, uint32_t chan_id, zap_channel_t
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
zap_mutex_unlock(globals.mutex);
|
zap_mutex_unlock(globals.mutex);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -1453,6 +1468,9 @@ zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *data
|
||||||
if(*digit_str) {
|
if(*digit_str) {
|
||||||
zio_event_cb_t event_callback = NULL;
|
zio_event_cb_t event_callback = NULL;
|
||||||
|
|
||||||
|
if (zchan->state == ZAP_CHANNEL_STATE_CALLWAITING && (*digit_str == 'D' || *digit_str == 'A')) {
|
||||||
|
zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]++;
|
||||||
|
} else {
|
||||||
zap_channel_queue_dtmf(zchan, digit_str);
|
zap_channel_queue_dtmf(zchan, digit_str);
|
||||||
|
|
||||||
if (zchan->span->event_callback) {
|
if (zchan->span->event_callback) {
|
||||||
|
@ -1479,6 +1497,7 @@ zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1523,10 +1542,10 @@ zap_status_t zap_channel_write(zap_channel_t *zchan, void *data, zap_size_t data
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!zchan->buffer_delay || --zchan->buffer_delay == 0) {
|
if (!zchan->buffer_delay || --zchan->buffer_delay == 0) {
|
||||||
if (zchan->fsk_buffer && (blen = zap_buffer_inuse(zchan->fsk_buffer))) {
|
if (zchan->dtmf_buffer && (blen = zap_buffer_inuse(zchan->dtmf_buffer))) {
|
||||||
buffer = zchan->fsk_buffer;
|
|
||||||
} else if (zchan->dtmf_buffer && (blen = zap_buffer_inuse(zchan->dtmf_buffer))) {
|
|
||||||
buffer = zchan->dtmf_buffer;
|
buffer = zchan->dtmf_buffer;
|
||||||
|
} else if (zchan->fsk_buffer && (blen = zap_buffer_inuse(zchan->fsk_buffer))) {
|
||||||
|
buffer = zchan->fsk_buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue