assert(tech_pvt->ftdmchan != NULL);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
-
+
ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROCEED);
return SWITCH_STATUS_SUCCESS;
}
char *v = h->name + FREETDM_VAR_PREFIX_LEN;
if (!zstr(v)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s=%s to channel %d:%d\n", v, h->value, span_id, chan_id);
- ftdm_channel_add_var(ftdmchan, v, h->value);
+ ftdm_call_add_var(&caller_data, v, h->value);
}
}
}
switch_channel_set_variable_printf(channel, "freetdm_chan_number", "%d", chanid);
switch_channel_set_variable_printf(channel, "freetdm_bearer_capability", "%d", channel_caller_data->bearer_capability);
switch_channel_set_variable_printf(channel, "freetdm_bearer_layer1", "%d", channel_caller_data->bearer_layer1);
+
if (globals.sip_headers) {
switch_channel_set_variable(channel, "sip_h_X-FreeTDM-SpanName", ftdm_channel_get_span_name(sigmsg->channel));
switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-SpanNumber", "%d", spanid);
ftdm_channel_get_current_var(curr, &var_name, &var_value);
snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name);
switch_channel_set_variable_printf(channel, name, "%s", var_value);
+ }
+
+ /* Add any call variable to the dial plan */
+ iter = ftdm_call_get_var_iterator(channel_caller_data, iter);
+ for (curr = iter ; curr; curr = ftdm_iterator_next(curr)) {
+ ftdm_call_get_current_var(curr, &var_name, &var_value);
+ snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name);
+ switch_channel_set_variable_printf(channel, name, "%s", var_value);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call Variable: %s=%s\n", name, var_value);
}
ftdm_iterator_free(iter);
+
switch_channel_set_state(channel, CS_INIT);
if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
ftdm_status_t status;
uint32_t spanid;
uint32_t chanid;
- ftdm_caller_data_t *callerdata;
+ ftdm_caller_data_t *caller_data;
spanid = ftdm_channel_get_span_id(sigmsg->channel);
chanid = ftdm_channel_get_id(sigmsg->channel);
- callerdata = ftdm_channel_get_caller_data(sigmsg->channel);
+ caller_data = ftdm_channel_get_caller_data(sigmsg->channel);
ftdm_log(FTDM_LOG_DEBUG, "got FXO sig %d:%d [%s]\n", spanid, chanid, ftdm_signal_event2str(sigmsg->event_id));
switch_set_flag_locked(tech_pvt, TFLAG_DEAD);
ftdm_channel_clear_token(sigmsg->channel, 0);
channel = switch_core_session_get_channel(session);
- switch_channel_hangup(channel, callerdata->hangup_cause);
+ switch_channel_hangup(channel, caller_data->hangup_cause);
ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session));
switch_core_session_rwunlock(session);
}
}
}
break;
- case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
-
+ case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
+
default:
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n",
}
}
break;
- case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
+ case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
+
case FTDM_SIGEVENT_STOP:
{
private_t *tech_pvt = NULL;
}
break;
- case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
-
+ case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
+
/* on DNIS received from the R2 forward side, return status == FTDM_BREAK to stop requesting DNIS */
case FTDM_SIGEVENT_COLLECTED_DIGIT:
{
switch(sigmsg->event_id) {
case FTDM_SIGEVENT_START:
{
- ftdm_channel_add_var(sigmsg->channel, "screening_ind", ftdm_screening2str(caller_data->screen));
- ftdm_channel_add_var(sigmsg->channel, "presentation_ind", ftdm_presentation2str(caller_data->pres));
+ ftdm_call_add_var(caller_data, "screening_ind", ftdm_screening2str(caller_data->screen));
+ ftdm_call_add_var(caller_data, "presentation_ind", ftdm_presentation2str(caller_data->pres));
return ftdm_channel_from_event(sigmsg, &session);
}
break;
- case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
-
+ case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
+
case FTDM_SIGEVENT_STOP:
case FTDM_SIGEVENT_RESTART:
{
}
break;
case FTDM_SIGEVENT_PROCEED:
- case FTDM_SIGEVENT_MSG:
+ case FTDM_SIGEVENT_FACILITY:
/* FS does not have handlers for these messages, so ignore them for now */
break;
default:
ftdm_time_t time_last_throttle_log = 0;
ftdm_time_t time_current_throttle_log = 0;
+static ftdm_iterator_t *get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter);
+
static int time_is_init = 0;
static void time_init(void)
if (!ftdmchan->dtmf_off) {
ftdmchan->dtmf_off = FTDM_DEFAULT_DTMF_OFF;
}
-
+
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
+
memset(ftdmchan->dtmf_hangup_buf, '\0', ftdmchan->span->dtmf_hangup_len);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE)) {
return FTDM_SUCCESS;
}
+FT_DECLARE(ftdm_status_t) _ftdm_channel_call_send_msg(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_sigmsg_t *sigmsg)
+{
+ ftdm_status_t status = FTDM_FAIL;
+ ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel");
+#ifdef __WINDOWS__
+ UNREFERENCED_PARAMETER(file);
+ UNREFERENCED_PARAMETER(func);
+ UNREFERENCED_PARAMETER(line);
+#endif
+
+ ftdm_channel_lock(ftdmchan);
+ if (ftdmchan->span->send_msg) {
+ status = ftdmchan->span->send_msg(ftdmchan, sigmsg);
+ } else {
+ status = FTDM_NOTIMPL;
+ ftdm_log(FTDM_LOG_ERROR, "send_msg method not implemented in this span!\n");
+ }
+ ftdm_channel_unlock(ftdmchan);
+ return status;
+}
+
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 = FTDM_FAIL;
return status;
}
+FT_DECLARE(void) ftdm_call_clear_data(ftdm_caller_data_t *caller_data)
+{
+ ftdm_call_clear_vars(caller_data);
+ memset(caller_data.raw_data, 0, sizeof(raw_data));
+ caller_data->raw_data_len = 0;
+ return;
+}
+
+FT_DECLARE(ftdm_status_t) ftdm_call_clear_vars(ftdm_caller_data_t *caller_data)
+{
+ if (caller_data->variables) {
+ hashtable_destroy(caller_data->variables);
+ }
+ caller_data->variables = NULL;
+ return FTDM_SUCCESS;
+}
+
+FT_DECLARE(ftdm_status_t) ftdm_call_remove_var(ftdm_caller_data_t *caller_data, const char *var_name)
+{
+ if (caller_data->variables) {
+ hashtable_remove(caller_data->variables, (void *)var_name);
+ }
+
+ return FTDM_SUCCESS;
+}
+
+
+FT_DECLARE(ftdm_status_t) ftdm_call_add_var(ftdm_caller_data_t *caller_data, const char *var_name, const char *value)
+{
+ char *t_name = 0, *t_val = 0;
+
+ if (!var_name || !value) {
+ return FTDM_FAIL;
+ }
+
+ if (!caller_data->variables) {
+ /* initialize on first use */
+ caller_data->variables = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys);
+ ftdm_assert_return(caller_data->variables, FTDM_FAIL, "Failed to create hash table\n");
+ }
+
+ t_name = ftdm_strdup(var_name);
+ t_val = ftdm_strdup(value);
+ hashtable_insert(caller_data->variables, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE);
+ return FTDM_SUCCESS;
+}
+
+FT_DECLARE(const char *) ftdm_call_get_var(ftdm_caller_data_t *caller_data, const char *var_name)
+{
+ const char *var = NULL;
+
+ if (!caller_data->variables || !var_name) {
+ return NULL;
+ }
+
+ var = (const char *)hashtable_search(((struct hashtable*)caller_data->variables), (void *)var_name);
+ return var;
+}
+
+FT_DECLARE(ftdm_iterator_t *) ftdm_call_get_var_iterator(const ftdm_caller_data_t *caller_data, ftdm_iterator_t *iter)
+{
+ ftdm_hash_iterator_t *hashiter = NULL;
+ hashiter = caller_data->variables == NULL ? NULL : hashtable_first(caller_data->variables);
+
+ if (hashiter == NULL) {
+ return NULL;
+ }
+
+ if (!(iter = get_iterator(FTDM_ITERATOR_VARS, iter))) {
+ return NULL;
+ }
+ iter->pvt.hashiter = hashiter;
+ return iter;
+}
+
+FT_DECLARE(ftdm_status_t) ftdm_call_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val)
+{
+ const void *key = NULL;
+ void *val = NULL;
+
+ *var_name = NULL;
+ *var_val = NULL;
+
+ ftdm_assert_return(iter && (iter->type == FTDM_ITERATOR_VARS) && iter->pvt.hashiter, FTDM_FAIL, "Cannot get variable from invalid iterator!\n");
+
+ hashtable_this(iter->pvt.hashiter, &key, NULL, &val);
+
+ *var_name = key;
+ *var_val = val;
+
+ return FTDM_SUCCESS;
+}
+
+
static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan)
{
ftdm_channel_lock(ftdmchan);
return status;
}
+
FT_DECLARE(const char *) ftdm_channel_get_var(ftdm_channel_t *ftdmchan, const char *var_name)
{
const char *var = NULL;
static ftdm_status_t ftdm_span_trigger_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
{
- return span->signal_cb(sigmsg);
+ ftdm_status_t status = span->signal_cb(sigmsg);
+ if (sigmsg->channel) {
+ ftdm_call_clear_data(&(sigmsg->channel->caller_data));
+ }
+ return status;
}
static ftdm_status_t ftdm_span_queue_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
}
done:
+
if (sigmsg->channel) {
ftdm_mutex_unlock(sigmsg->channel->mutex);
}
case FTDM_CHANNEL_STATE_GET_CALLERID:
{
if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
+ /* By default, we do not send a progress indicator in the proceed */
+ ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
+
sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
- sngisdn_snd_proceed(ftdmchan);
+ sngisdn_snd_proceed(ftdmchan, prog_ind);
}
/* Wait in this state until we get FACILITY msg */
}
ftdm_span_send_signal(ftdmchan->span, &sigev);
} else {
if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
+ /* By default, we do not send a progress indicator in the proceed */
+ ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
+
sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
- sngisdn_snd_proceed(ftdmchan);
+ sngisdn_snd_proceed(ftdmchan, prog_ind);
}
}
}
return;
}
+static FIO_CHANNEL_SEND_MSG_FUNCTION(ftdm_sangoma_isdn_send_msg)
+{
+ ftdm_status_t status = FTDM_FAIL;
+
+ switch (sigmsg->event_id) {
+ case FTDM_SIGEVENT_RESTART:
+ /* TODO: Send a channel restart here */
+ /* Implement me */
+ break;
+ case FTDM_SIGEVENT_FACILITY:
+ sngisdn_snd_fac_req(ftdmchan);
+ break;
+ default:
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Unsupported signalling msg requested\n");
+ status = FTDM_BREAK;
+ }
+ ftdm_call_clear_data(&ftdmchan->caller_data);
+ return status;
+}
+
static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_isdn_outgoing_call)
{
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
span->stop = ftdm_sangoma_isdn_stop;
span->signal_type = FTDM_SIGTYPE_ISDN;
span->outgoing_call = ftdm_sangoma_isdn_outgoing_call;
+ span->send_msg = ftdm_sangoma_isdn_send_msg;
span->channel_request = NULL;
span->signal_cb = sig_cb;
span->get_channel_sig_status = ftdm_sangoma_isdn_get_chan_sig_status;
/* Outbound Call Control functions */
void sngisdn_snd_setup(ftdm_channel_t *ftdmchan);
void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan);
-void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan);
+void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
void sngisdn_snd_connect(ftdm_channel_t *ftdmchan);
void sngisdn_rcv_sng_assert(char *message);
ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
+ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb);
ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display);
ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd);
ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
-ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t data_len);
+ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t data_len);
ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
+ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb);
ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt);
ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind);
ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
-ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t *data_len);
+ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len);
uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability);
break;
}
-#if 0
- /* Export ftdmchan variables here if we need to */
- ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1");
-#endif
/* Fill in call information */
get_calling_num(ftdmchan, &conEvnt->cgPtyNmb);
+ get_calling_num2(ftdmchan, &conEvnt->cgPtyNmb2);
get_called_num(ftdmchan, &conEvnt->cdPtyNmb);
get_redir_num(ftdmchan, &conEvnt->redirNmb);
get_calling_subaddr(ftdmchan, &conEvnt->cgPtySad);
{
ftdm_sigmsg_t sigev;
if (facEvnt->facElmt.facStr.pres) {
- get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len);
+ get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len-2);
}
memset(&sigev, 0, sizeof(sigev));
sigev.chan_id = ftdmchan->chan_id;
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
- sigev.event_id = FTDM_SIGEVENT_MSG;
+ sigev.event_id = FTDM_SIGEVENT_FACILITY;
ftdm_span_send_signal(ftdmchan->span, &sigev);
}
break;
set_called_num(ftdmchan, &conEvnt.cdPtyNmb);
set_calling_num(ftdmchan, &conEvnt.cgPtyNmb);
+ set_calling_num2(ftdmchan, &conEvnt.cgPtyNmb2);
set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad);
set_redir_num(ftdmchan, &conEvnt.redirNmb);
set_calling_name(ftdmchan, &conEvnt);
}
-void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
+void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind)
{
CnStEvnt cnStEvnt;
-
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
+ set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
+ ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROCEED (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
+ ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, signal_data->dchan_id, sngisdn_info->ces)) {
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
+ ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
+ ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_con_response(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
memset(&facEvnt, 0, sizeof(facEvnt));
- set_facility_ie_str(ftdmchan, &facEvnt.facElmt.facStr.val[2], (ftdm_size_t*)&facEvnt.facElmt.facStr.len);
+ if (set_facility_ie_str(ftdmchan, &facEvnt.facElmt.facStr.val[2], (uint8_t*)&facEvnt.facElmt.facStr.len) != FTDM_SUCCESS) {
+ /* No point in sending a FACILITY message if there is no Facility IE to transmit */
+ return;
+ }
+ ftdm_call_clear_data(&ftdmchan->caller_data);
+ facEvnt.facElmt.eh.pres = PRSNT_NODEF;
+ facEvnt.facElmt.facStr.pres = PRSNT_NODEF;
facEvnt.facElmt.facStr.val[0] = 0x1C;
- facEvnt.facElmt.facStr.val[1] = facEvnt.facElmt.facStr.len;
+ facEvnt.facElmt.facStr.val[1] = (uint8_t)facEvnt.facElmt.facStr.len;
+ facEvnt.facElmt.facStr.len +=2; /* Need to include the size of identifier + len */
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending FACILITY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
//ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ\n");
+ ftdm_call_clear_data(&ftdmchan->caller_data);
+
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_con_status(signal_data->cc_id, 0, 0, &cnStEvnt, MI_INFO, signal_data->dchan_id, sngisdn_info->ces)) {
memset(&staEvnt, 0, sizeof(StaEvnt));
+ ftdm_call_clear_data(&ftdmchan->caller_data);
+
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Status ENQ on suId:%d suInstId:%u spInstId:%d dchan:%d ces:%d\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_status_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &staEvnt, MI_STATENQ)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused Status ENQ request\n");
discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT;
set_facility_ie(ftdmchan, &discEvnt.facilityStr);
+ ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) {
}
set_facility_ie(ftdmchan, &relEvnt.facilityStr);
+ ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, suInstId, spInstId);
return FTDM_SUCCESS;
}
+ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
+{
+ ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
+ if (cgPtyNmb->eh.pres != PRSNT_NODEF) {
+ return FTDM_FAIL;
+ }
+
+ if (cgPtyNmb->screenInd.pres == PRSNT_NODEF) {
+ ftdm_call_add_var(caller_data, "isdn.cg_pty2.screen_ind", ftdm_screening2str(cgPtyNmb->screenInd.val));
+ }
+
+ if (cgPtyNmb->presInd0.pres == PRSNT_NODEF) {
+ ftdm_call_add_var(caller_data, "isdn.cg_pty2.presentation_ind", ftdm_presentation2str(cgPtyNmb->presInd0.val));
+ }
+
+ if (cgPtyNmb->nmbPlanId.pres == PRSNT_NODEF) {
+ ftdm_call_add_var(caller_data, "isdn.cg_pty2.npi", ftdm_npi2str(cgPtyNmb->nmbPlanId.val));
+ }
+
+ if (cgPtyNmb->typeNmb1.pres == PRSNT_NODEF) {
+ ftdm_call_add_var(caller_data, "isdn.cg_pty2.ton", ftdm_ton2str(cgPtyNmb->typeNmb1.val));
+ }
+
+ if (cgPtyNmb->nmbDigits.pres == PRSNT_NODEF) {
+ char digits_string [32];
+ memcpy(digits_string, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len);
+ digits_string[cgPtyNmb->nmbDigits.len] = '\0';
+ ftdm_call_add_var(caller_data, "isdn.cg_pty2.digits", digits_string);
+ }
+ memcpy(&caller_data->ani, &caller_data->cid_num, sizeof(caller_data->ani));
+ return FTDM_SUCCESS;
+}
+
ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
memcpy(subaddress, (char*)cgPtySad->sadInfo.val, cgPtySad->sadInfo.len);
subaddress[cgPtySad->sadInfo.len] = '\0';
- ftdm_channel_add_var(ftdmchan, "isdn.calling_subaddr", subaddress);
+ ftdm_call_add_var(&ftdmchan->caller_data, "isdn.calling_subaddr", subaddress);
return FTDM_SUCCESS;
}
return get_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, facilityStr->facilityStr.len);
}
-ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t data_len)
+ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t data_len)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) {
- if (data_len > sizeof(caller_data->raw_data)-2) {
- ftdm_log(FTDM_LOG_CRIT, "Length of Facility IE exceeds maximum length\n");
- return FTDM_FAIL;
- }
-
+ /* size of facilityStr->facilityStr.len is a uint8_t so no need to check
+ for overflow here as facilityStr->facilityStr.len will always be smaller
+ than sizeof(caller_data->raw_data) */
+
memset(caller_data->raw_data, 0, sizeof(caller_data->raw_data));
/* Always include Facility IE identifier + len so this can be used as a sanity check by the user */
caller_data->raw_data[0] = SNGISDN_Q931_FACILITY_IE_ID;
val = SNGISDN_PROGIND_DESCR_INVALID;
break;
}
- ftdm_channel_add_var(ftdmchan, "isdn.prog_ind.descr", ftdm_sngisdn_progind_descr2str(val));
+ ftdm_call_add_var(&ftdmchan->caller_data, "isdn.prog_ind.descr", ftdm_sngisdn_progind_descr2str(val));
}
if (progInd->location.pres) {
val = SNGISDN_PROGIND_LOC_INVALID;
break;
}
- ftdm_channel_add_var(ftdmchan, "isdn.prog_ind.loc", ftdm_sngisdn_progind_loc2str(val));
+ ftdm_call_add_var(&ftdmchan->caller_data, "isdn.prog_ind.loc", ftdm_sngisdn_progind_loc2str(val));
}
return FTDM_SUCCESS;
}
return FTDM_SUCCESS;
}
+ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
+{
+ const char* string = NULL;
+ uint8_t len,val;
+ ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
+
+ string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.digits");
+ if ((string == NULL) || !(*string)) {
+ return FTDM_FAIL;
+ }
+
+ cgPtyNmb->eh.pres = PRSNT_NODEF;
+
+ len = strlen(string);
+ cgPtyNmb->nmbDigits.len = len;
+
+ cgPtyNmb->nmbDigits.pres = PRSNT_NODEF;
+ memcpy(cgPtyNmb->nmbDigits.val, string, len);
+
+ /* Screening Indicator */
+ cgPtyNmb->screenInd.pres = PRSNT_NODEF;
+
+ val = FTDM_SCREENING_INVALID;
+ string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.screening_ind");
+ if ((string != NULL) && (*string)) {
+ val = ftdm_str2ftdm_screening(string);
+ }
+
+ /* isdn.cg_pty2.screen_ind does not exist or we could not parse its value */
+ if (val == FTDM_SCREENING_INVALID) {
+ /* default to caller data screening ind */
+ cgPtyNmb->screenInd.val = caller_data->screen;
+ } else {
+ cgPtyNmb->screenInd.val = val;
+ }
+
+ /* Presentation Indicator */
+ cgPtyNmb->presInd0.pres = PRSNT_NODEF;
+
+ val = FTDM_PRES_INVALID;
+ string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.presentation_ind");
+ if ((string != NULL) && (*string)) {
+ val = ftdm_str2ftdm_presentation(string);
+ }
+
+ if (val == FTDM_PRES_INVALID) {
+ cgPtyNmb->presInd0.val = caller_data->pres;
+ } else {
+ cgPtyNmb->presInd0.val = val;
+ }
+
+ /* Numbering Plan Indicator */
+ cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
+
+ val = FTDM_NPI_INVALID;
+ string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.npi");
+ if ((string != NULL) && (*string)) {
+ val = ftdm_str2ftdm_npi(string);
+ }
+
+ if (val == FTDM_NPI_INVALID) {
+ cgPtyNmb->nmbPlanId.val = caller_data->cid_num.plan;
+ } else {
+ cgPtyNmb->nmbPlanId.val = val;
+ }
+
+ cgPtyNmb->typeNmb1.pres = PRSNT_NODEF;
+
+ /* Type of Number */
+ val = FTDM_TON_INVALID;
+ string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.ton");
+ if ((string != NULL) && (*string)) {
+ val = ftdm_str2ftdm_ton(string);
+ }
+
+ if (val == FTDM_TON_INVALID) {
+ cgPtyNmb->typeNmb1.val = caller_data->cid_num.type;
+ } else {
+ cgPtyNmb->typeNmb1.val = val;
+ }
+ return FTDM_SUCCESS;
+}
+
ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
{
const char* clg_subaddr = NULL;
- clg_subaddr = ftdm_channel_get_var(ftdmchan, "isdn.calling_subaddr");
+ clg_subaddr = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.calling_subaddr");
if ((clg_subaddr != NULL) && (*clg_subaddr)) {
unsigned len = strlen (clg_subaddr);
cgPtySad->eh.pres = PRSNT_NODEF;
ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr)
{
ftdm_status_t status;
- status = set_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, (ftdm_size_t*)&facilityStr->facilityStr.len);
+ status = set_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, (uint8_t*)&(facilityStr->facilityStr.len));
if (status == FTDM_SUCCESS) {
facilityStr->eh.pres = PRSNT_NODEF;
facilityStr->facilityStr.pres = PRSNT_NODEF;
return status;
}
-ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t *data_len)
+ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len)
{
+ int len;
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (caller_data->raw_data_len > 0 && caller_data->raw_data[0] == SNGISDN_Q931_FACILITY_IE_ID) {
- *data_len = caller_data->raw_data[1];
- memcpy(data, &caller_data->raw_data[2], *data_len);
+ len = caller_data->raw_data[1];
+ memcpy(data, &caller_data->raw_data[2], len);
+ *data_len = len;
return FTDM_SUCCESS;
}
return FTDM_FAIL;
int descr = prog_ind.descr;
int loc = prog_ind.loc;
- str = ftdm_channel_get_var(ftdmchan, "isdn.prog_ind.descr");
+ str = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.prog_ind.descr");
if (str && *str) {
/* User wants to override progress indicator */
descr = ftdm_str2ftdm_sngisdn_progind_descr(str);
return FTDM_SUCCESS;
}
- str = ftdm_channel_get_var(ftdmchan, "isdn.prog_ind.loc");
- if (str && *str) {
+ str = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.prog_ind.loc");
+ if (str && *str) {
loc = ftdm_str2ftdm_sngisdn_progind_loc(str);
}
if (loc == SNGISDN_PROGIND_LOC_INVALID) {
/* add any special variables for the dialplan */
sprintf(nadi, "%d", siConEvnt->cgPtyNum.natAddrInd.val);
- ftdm_channel_add_var(ftdmchan, "ss7_clg_nadi", nadi);
+ ftdm_call_add_var(&ftdmchan->caller_data, "ss7_clg_nadi", nadi);
sprintf(nadi, "%d", siConEvnt->cdPtyNum.natAddrInd.val);
- ftdm_channel_add_var(ftdmchan, "ss7_cld_nadi", nadi);
+ ftdm_call_add_var(&ftdmchan->caller_data, "ss7_cld_nadi", nadi);
/* check if a COT test is requested */
copy_cgPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cgPtyNum);
/* check if the user would like a custom NADI value for the calling Pty Num */
- clg_nadi = ftdm_channel_get_var(ftdmchan, "ss7_clg_nadi");
+ clg_nadi = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_clg_nadi");
if ((clg_nadi != NULL) && (*clg_nadi)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling NADI value \"%s\"\n", clg_nadi);
iam.cgPtyNum.natAddrInd.val = atoi(clg_nadi);
SS7_DEBUG_CHAN(ftdmchan,"No user supplied NADI value found for CLG, using \"%d\"\n", iam.cgPtyNum.natAddrInd.val);
}
- cld_nadi = ftdm_channel_get_var(ftdmchan, "ss7_cld_nadi");
+ cld_nadi = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_cld_nadi");
if ((cld_nadi != NULL) && (*cld_nadi)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called NADI value \"%s\"\n", cld_nadi);
iam.cdPtyNum.natAddrInd.val = atoi(cld_nadi);
}
/* check if the user would like us to send a clg_sub-address */
- clg_subAddr = ftdm_channel_get_var(ftdmchan, "ss7_clg_subaddr");
+ clg_subAddr = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_clg_subaddr");
if ((clg_subAddr != NULL) && (*clg_subAddr)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling Sub-Address value \"%s\"\n", clg_subAddr);
}
/* check if the user would like us to send a cld_sub-address */
- cld_subAddr = ftdm_channel_get_var(ftdmchan, "ss7_cld_subaddr");
+ cld_subAddr = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_cld_subaddr");
if ((cld_subAddr != NULL) && (*cld_subAddr)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called Sub-Address value \"%s\"\n", cld_subAddr);
iam.cgPtyNum.natAddrInd.val,
ftdmchan->caller_data.dnis.digits,
iam.cdPtyNum.natAddrInd.val);
-
+
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
ADDRCMPLT);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ACM\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
5);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ANM\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx REL cause=%d \n",
sngss7_info->circuit->cic,
ftdmchan->caller_data.hangup_cause );
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
&rlc);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RLC\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC-RLC\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLO\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLA\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBL\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBA\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx LPA\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->rx_grs.range));
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->tx_grs.range));
-
+
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/* clean out the saved data */
memset(&sngss7_span->rx_cgb, 0x0, sizeof(sngss7_group_data_t));
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/* clean out the saved data */
memset(&sngss7_span->rx_cgu, 0x0, sizeof(sngss7_group_data_t));
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/* clean out the saved data */
memset(&sngss7_span->tx_cgb, 0x0, sizeof(sngss7_group_data_t));
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/* clean out the saved data */
memset(&sngss7_span->tx_cgu, 0x0, sizeof(sngss7_group_data_t));
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
uint8_t plan;
} ftdm_number_t;
+typedef void * ftdm_variable_container_t;
+
/*! \brief Caller information */
typedef struct ftdm_caller_data {
char cid_date[8]; /*!< Caller ID date */
char collected[25]; /*!< Collected digits so far */
int hangup_cause; /*!< Hangup cause */
char raw_data[1024]; /*!< Protocol specific raw caller data */
- uint32_t raw_data_len; /* !< Raw data length */
+ uint32_t raw_data_len; /*!< Raw data length */
/* these 2 are undocumented right now, only used by boost: */
/* bearer capability */
ftdm_bearer_cap_t bearer_capability;
/* user information layer 1 protocol */
ftdm_user_layer1_prot_t bearer_layer1;
+ ftdm_variable_container_t variables; /*!<variables attached to this call */
} ftdm_caller_data_t;
/*! \brief Tone type */
FTDM_SIGEVENT_RESTART, /*!< Restart has been requested. Typically you hangup your call resources here */
FTDM_SIGEVENT_SIGSTATUS_CHANGED, /*!< Signaling protocol status changed (ie: D-chan up), see new status in raw_data ftdm_sigmsg_t member */
FTDM_SIGEVENT_COLLISION, /*!< Outgoing call was dropped because an incoming call arrived at the same time */
- FTDM_SIGEVENT_MSG, /*!< We received an in-call msg */
+ FTDM_SIGEVENT_FACILITY, /* !< In call facility event */
FTDM_SIGEVENT_INVALID
} ftdm_signal_event_t;
#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROCEED", "PROGRESS", \
ftdm_channel_t *channel; /*!< Related channel */
uint32_t chan_id; /*!< easy access to chan id */
uint32_t span_id; /*!< easy access to span_id */
- ftdm_signaling_status_t sigstatus; /*!< Signaling status (valid if event_id is FTDM_SIGEVENT_SIGSTATUS_CHANGED) */
+ ftdm_signaling_status_t sigstatus; /*!< Signaling status (valid if event_id is FTDM_SIGEVENT_SIGSTATUS_CHANGED) */
void *raw_data; /*!< Message specific data if any */
uint32_t raw_data_len; /*!< Data len in case is needed */
};
* You don't need these unless your implementing an I/O interface module (most users don't) */
#define FIO_CHANNEL_REQUEST_ARGS (ftdm_span_t *span, uint32_t chan_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
#define FIO_CHANNEL_OUTGOING_CALL_ARGS (ftdm_channel_t *ftdmchan)
+#define FIO_CHANNEL_SEND_MSG_ARGS (ftdm_channel_t *ftdmchan, ftdm_sigmsg_t *sigmsg)
#define FIO_CHANNEL_SET_SIG_STATUS_ARGS (ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status)
#define FIO_CHANNEL_GET_SIG_STATUS_ARGS (ftdm_channel_t *ftdmchan, ftdm_signaling_status_t *status)
#define FIO_SPAN_SET_SIG_STATUS_ARGS (ftdm_span_t *span, ftdm_signaling_status_t status)
* You don't need these unless your implementing an I/O interface module (most users don't) */
typedef ftdm_status_t (*fio_channel_request_t) FIO_CHANNEL_REQUEST_ARGS ;
typedef ftdm_status_t (*fio_channel_outgoing_call_t) FIO_CHANNEL_OUTGOING_CALL_ARGS ;
+typedef ftdm_status_t (*fio_channel_send_msg_t) FIO_CHANNEL_SEND_MSG_ARGS;
typedef ftdm_status_t (*fio_channel_set_sig_status_t) FIO_CHANNEL_SET_SIG_STATUS_ARGS;
typedef ftdm_status_t (*fio_channel_get_sig_status_t) FIO_CHANNEL_GET_SIG_STATUS_ARGS;
typedef ftdm_status_t (*fio_span_set_sig_status_t) FIO_SPAN_SET_SIG_STATUS_ARGS;
* You don't need these unless your implementing an I/O interface module (most users don't) */
#define FIO_CHANNEL_REQUEST_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_REQUEST_ARGS
#define FIO_CHANNEL_OUTGOING_CALL_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_OUTGOING_CALL_ARGS
+#define FIO_CHANNEL_SEND_MSG_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_SEND_MSG_ARGS
#define FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_SET_SIG_STATUS_ARGS
#define FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_GET_SIG_STATUS_ARGS
#define FIO_SPAN_SET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_SPAN_SET_SIG_STATUS_ARGS
/*! \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 Send a message on a call */
+#define ftdm_channel_call_send_msg(ftdmchan, sigmsg) _ftdm_channel_call_send_msg(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (sigmsg))
+
+/*! \brief Send a signal on a call recording the source code point where it was called (see ftdm_channel_call_send_msg for an easy to use macro) */
+FT_DECLARE(ftdm_status_t) _ftdm_channel_call_send_msg(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_sigmsg_t *sigmsg);
+
/*! \brief Hangup the call without cause */
#define ftdm_channel_call_hangup(ftdmchan) _ftdm_channel_call_hangup(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
*/
FT_DECLARE(ftdm_status_t) ftdm_iterator_free(ftdm_iterator_t *iter);
+/*! \brief Add a custom variable to the call
+ * \note This variables may be used by signaling modules to override signaling parameters
+ * \todo Document which signaling variables are available
+ * */
+FT_DECLARE(ftdm_status_t) ftdm_call_add_var(ftdm_caller_data_t *caller_data, const char *var_name, const char *value);
+
+/*! \brief Get a custom variable from the call.
+ * \note The variable pointer returned is only valid during the callback receiving SIGEVENT. */
+FT_DECLARE(const char *) ftdm_call_get_var(ftdm_caller_data_t *caller_data, const char *var_name);
+
+/*! \brief Get an iterator to iterate over the channel variables
+ * \param caller_data The signal msg structure containing the variables
+ * \param iter Optional iterator. You can reuse an old iterator (not previously freed) to avoid the extra allocation of a new iterator.
+ * \note The iterator pointer returned is only valid while the signal message and it'll be destroyed when the signal message is processed.
+ * This iterator is completely non-thread safe, if you are adding variables or removing variables while iterating
+ * results are unpredictable
+ */
+FT_DECLARE(ftdm_iterator_t *) ftdm_call_get_var_iterator(const ftdm_caller_data_t *caller_data, ftdm_iterator_t *iter);
+
+/*! \brief Get variable name and value for the current iterator position */
+FT_DECLARE(ftdm_status_t) ftdm_call_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val);
+
+/*! \brief Clear all variables attached to the call
+ * \note Variables are cleared at the end of each call back, so it is not necessary for the user to call this function.
+ * \todo Document which signaling variables are available
+ * */
+FT_DECLARE(ftdm_status_t) ftdm_call_clear_vars(ftdm_caller_data_t *caller_data);
+
+/*! \brief Remove a variable attached to the call
+ * \note Removes a variable that was attached to the call.
+ * \todo Document which call variables are available
+ * */
+FT_DECLARE(ftdm_status_t) ftdm_call_remove_var(ftdm_caller_data_t *caller_data, const char *var_name);
+
+/*! \brief Clears all the temporary data attached to this call
+ * \note Clears caller_data->variables and caller_data->raw_data.
+ * */
+FT_DECLARE(void) ftdm_call_clear_data(ftdm_caller_data_t *caller_data);
+
/*! \brief Get the span pointer associated to the channel */
FT_DECLARE(ftdm_span_t *) ftdm_channel_get_span(const ftdm_channel_t *ftdmchan);
teletone_multi_tone_t tone_finder[FTDM_TONEMAP_INVALID+1];
ftdm_channel_t *channels[FTDM_MAX_CHANNELS_SPAN+1];
fio_channel_outgoing_call_t outgoing_call;
+ fio_channel_send_msg_t send_msg;
fio_channel_set_sig_status_t set_channel_sig_status;
fio_channel_get_sig_status_t get_channel_sig_status;
fio_span_set_sig_status_t set_span_sig_status;