void sngisdn_delayed_connect(void* p_sngisdn_info) { sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; ftdm_mutex_lock(ftdmchan->mutex); ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed CONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId); sngisdn_snd_connect(ftdmchan); ftdm_mutex_unlock(ftdmchan->mutex); return; }
static ftdm_status_t att_courtesy_vru(ftdm_channel_t *ftdmchan, sngisdn_transfer_type_t type, char* args) { char dtmf_digits[64]; ftdm_status_t status = FTDM_FAIL; sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; char *p = args; uint8_t forced_answer = 0; switch (signal_data->switchtype) { case SNGISDN_SWITCH_5ESS: case SNGISDN_SWITCH_4ESS: break; default: ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "AT&T Courtesy Transfer not supported for switchtype\n"); return FTDM_FAIL; } while (!ftdm_strlen_zero(p)) { if (!isdigit(*p) && *p != 'w' && *p != 'W') { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot transfer to non-numeric number:%s\n", args); return FTDM_FAIL; } p++; } ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Performing AT&T Courtesy Transfer-VRU%s to %s\n", (type == SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA) ?"--data" : "", args); sprintf(dtmf_digits, "*8w%s", args); ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending digits %s\n", dtmf_digits); switch (ftdmchan->last_state) { case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: /* Call has to be in answered state - so send a CONNECT message if we did not answer this call yet */ forced_answer++; sngisdn_snd_connect(ftdmchan); /* fall-through */ case FTDM_CHANNEL_STATE_UP: memset(&sngisdn_info->transfer_data.tdata.att_courtesy_vru.dtmf_digits, 0, sizeof(sngisdn_info->transfer_data.tdata.att_courtesy_vru.dtmf_digits)); sngisdn_info->transfer_data.type = type; /* We will be polling the channel for IO so that we can receive the DTMF events, * Disable user RX otherwise it is a race between who calls channel_read */ ftdm_set_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED); ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_DTMF_DETECT, NULL); ftdm_channel_command(ftdmchan, FTDM_COMMAND_SEND_DTMF, dtmf_digits); if (type == SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA) { /* We need to save transfer data, so we can send it in the disconnect msg */ const char *val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "transfer_data"); if (ftdm_strlen_zero(val)) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot perform data transfer because transfer_data variable is not set\n"); goto done; } if (strlen(val) > COURTESY_TRANSFER_MAX_DATA_SIZE) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Data exceeds max size (len:%"FTDM_SIZE_FMT" max:%d), cannot perform transfer\n", strlen(val), COURTESY_TRANSFER_MAX_DATA_SIZE); goto done; } memcpy(sngisdn_info->transfer_data.tdata.att_courtesy_vru.data, val, strlen(val)); } ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); if (forced_answer) { /* Notify the user that we answered the call */ sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_UP); } if (signal_data->transfer_timeout) { ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "courtesy_transfer_timeout", signal_data->transfer_timeout, att_courtesy_transfer_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_CHAN_TIMER_ATT_TRANSFER]); } status = FTDM_SUCCESS; break; default: ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot perform transfer in state %s\n", ftdm_channel_state2str(ftdmchan->state)); break; } done: return status; }