void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status) { ftdm_sigmsg_t sig; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)ftdmchan->span->signal_data; ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Signalling link status changed to %s\n", ftdm_signaling_status2str(status)); memset(&sig, 0, sizeof(sig)); sig.chan_id = ftdmchan->chan_id; sig.span_id = ftdmchan->span_id; sig.channel = ftdmchan; sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; sig.ev_data.sigstatus.status = status; ftdm_span_send_signal(ftdmchan->span, &sig); if (FTDM_SPAN_IS_BRI(ftdmchan->span)) { sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) { ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING); ftdm_sched_timer(signal_data->sched, "delayed_setup", 1000, sngisdn_delayed_setup, (void*) sngisdn_info, NULL); } } return; }
void on_wat_sms_ind(unsigned char span_id, wat_sms_event_t *sms_event) { //printf("on_wat_sms_ind\r\n"); ftdm_span_t *span = NULL; ftdm_channel_t *ftdmchan; ftdm_gsm_span_data_t *gsm_data = NULL; if(!(span = GetSpanByID(span_id, &gsm_data))) { return; } ftdmchan = gsm_data->dchan; { ftdm_sms_data_t sms_data; memset(&sms_data, 0, sizeof(sms_data)); strncpy(sms_data.from, sms_event->from.digits, sizeof(sms_data.from)); strncpy(sms_data.body, sms_event->content.data, sizeof(sms_data.body)); ftdm_sigmsg_t sigev; memset(&sigev, 0, sizeof(sigev)); sigev.event_id = FTDM_SIGEVENT_SMS; sigev.channel = ftdmchan ; gsm_data->dchan->caller_data.priv = (void *)&sms_data; ftdm_span_send_signal(span, &sigev); } // SEND_STATE_SIGNAL(FTDM_SIGEVENT_SMS); return; }
void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len) { uint8_t *raw_data; ftdm_sigmsg_t sigev; ftdm_channel_t *ftdmchan = NULL; sngisdn_frame_info_t frame_info; memset(&sigev, 0, sizeof(sigev)); /* Note: Mapped raw trace assume only exclusive b-channel selection is used. i.e the b-channel selected on outgoing SETUP is always used for the call */ if (sngisdn_get_frame_info(data, data_len, dir, &frame_info) == FTDM_SUCCESS) { if (sngisdn_map_call(signal_data, frame_info, &ftdmchan) == FTDM_SUCCESS) { sigev.call_id = ftdmchan->caller_data.call_id; sigev.span_id = ftdmchan->physical_span_id; sigev.chan_id = ftdmchan->physical_chan_id; sigev.channel = ftdmchan; } sigev.event_id = FTDM_SIGEVENT_TRACE_RAW; sigev.ev_data.trace.dir = dir; sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q931; raw_data = ftdm_malloc(data_len); ftdm_assert(raw_data, "Failed to malloc"); memcpy(raw_data, data, data_len); sigev.raw.data = raw_data; sigev.raw.len = data_len; sigev.raw.autofree = 1; ftdm_span_send_signal(signal_data->ftdm_span, &sigev); } }
void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status) { ftdm_sigmsg_t sig; ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Signalling link status changed to %s\n", ftdm_signaling_status2str(status)); memset(&sig, 0, sizeof(sig)); sig.chan_id = ftdmchan->chan_id; sig.span_id = ftdmchan->span_id; sig.channel = ftdmchan; sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; sig.raw_data = &status; ftdm_span_send_signal(ftdmchan->span, &sig); return; }
void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len) { uint8_t *raw_data; ftdm_sigmsg_t sigev; memset(&sigev, 0, sizeof(sigev)); sigev.span_id = signal_data->ftdm_span->span_id; sigev.chan_id = signal_data->dchan->chan_id; sigev.channel = signal_data->dchan; sigev.event_id = FTDM_SIGEVENT_TRACE_RAW; sigev.ev_data.trace.dir = dir; sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q921; raw_data = ftdm_malloc(data_len); ftdm_assert(raw_data, "Failed to malloc"); memcpy(raw_data, data, data_len); sigev.raw.data = raw_data; sigev.raw.len = data_len; ftdm_span_send_signal(signal_data->ftdm_span, &sigev); }
void sngisdn_send_signal(sngisdn_chan_data_t *sngisdn_info, ftdm_signal_event_t event_id) { ftdm_sigmsg_t sigev; ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; memset(&sigev, 0, sizeof(sigev)); sigev.chan_id = ftdmchan->chan_id; sigev.span_id = ftdmchan->span_id; sigev.channel = ftdmchan; sigev.event_id = event_id; if (sngisdn_info->variables) { /* * variables now belongs to the ftdm core, and * will be cleared after sigev is processed by user. Set * local pointer to NULL so we do not attempt to * destroy it */ sigev.variables = sngisdn_info->variables; sngisdn_info->variables = NULL; } if (sngisdn_info->raw_data) { /* * raw_data now belongs to the ftdm core, and * will be cleared after sigev is processed by user. Set * local pointer to NULL so we do not attempt to * destroy it */ sigev.raw.data = sngisdn_info->raw_data; sigev.raw.len = sngisdn_info->raw_data_len; sngisdn_info->raw_data = NULL; sngisdn_info->raw_data_len = 0; } ftdm_span_send_signal(ftdmchan->span, &sigev); }
FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const char *func, int line, ftdm_channel_t *fchan) { uint8_t hindex = 0; ftdm_time_t diff = 0; ftdm_channel_state_t state = fchan->state; if (fchan->state_status == FTDM_STATE_STATUS_COMPLETED) { ftdm_assert_return(!ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE), FTDM_FAIL, "State change flag set but state is not completed\n"); return FTDM_SUCCESS; } ftdm_usrmsg_free(&fchan->usrmsg); ftdm_clear_flag(fchan, FTDM_CHANNEL_STATE_CHANGE); if (state == FTDM_CHANNEL_STATE_PROGRESS) { ftdm_set_flag(fchan, FTDM_CHANNEL_PROGRESS); } else if (state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) { ftdm_set_flag(fchan, FTDM_CHANNEL_PROGRESS); ftdm_test_and_set_media(fchan); } else if (state == FTDM_CHANNEL_STATE_UP) { ftdm_set_flag(fchan, FTDM_CHANNEL_PROGRESS); ftdm_set_flag(fchan, FTDM_CHANNEL_ANSWERED); ftdm_test_and_set_media(fchan); } else if (state == FTDM_CHANNEL_STATE_DIALING) { ftdm_sigmsg_t msg; memset(&msg, 0, sizeof(msg)); msg.channel = fchan; msg.event_id = FTDM_SIGEVENT_DIALING; ftdm_span_send_signal(fchan->span, &msg); } else if (state == FTDM_CHANNEL_STATE_HANGUP) { ftdm_set_echocancel_call_end(fchan); } /* MAINTENANCE WARNING * we're assuming an indication performed * via state change will involve a single state change */ ftdm_ack_indication(fchan, fchan->indication, FTDM_SUCCESS); hindex = (fchan->hindex == 0) ? (ftdm_array_len(fchan->history) - 1) : (fchan->hindex - 1); ftdm_assert(!fchan->history[hindex].end_time, "End time should be zero!\n"); fchan->history[hindex].end_time = ftdm_current_time_in_ms(); fchan->state_status = FTDM_STATE_STATUS_COMPLETED; diff = fchan->history[hindex].end_time - fchan->history[hindex].time; ftdm_log_chan_ex(fchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Completed state change from %s to %s in %llums\n", ftdm_channel_state2str(fchan->last_state), ftdm_channel_state2str(state), diff); if (ftdm_test_flag(fchan, FTDM_CHANNEL_BLOCKING)) { ftdm_clear_flag(fchan, FTDM_CHANNEL_BLOCKING); ftdm_interrupt_signal(fchan->state_completed_interrupt); } return FTDM_SUCCESS; }
static ftdm_status_t state_advance(ftdm_channel_t *ftdmchan) { ftdm_status_t status; ftdm_sigmsg_t sig; pritap_t *pritap = ftdmchan->span->signal_data; pritap_t *peer_pritap = pritap->peerspan->signal_data; ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "processing state %s\n", ftdm_channel_state2str(ftdmchan->state)); memset(&sig, 0, sizeof(sig)); sig.chan_id = ftdmchan->chan_id; sig.span_id = ftdmchan->span_id; sig.channel = ftdmchan; ftdm_channel_complete_state(ftdmchan); switch (ftdmchan->state) { case FTDM_CHANNEL_STATE_DOWN: { ftdm_channel_t *fchan = ftdmchan; /* Destroy the peer data first */ if (fchan->call_data) { ftdm_channel_t *peerchan = fchan->call_data; ftdm_channel_t *pchan = peerchan; ftdm_channel_lock(peerchan); pchan->call_data = NULL; pchan->pflags = 0; ftdm_channel_close(&pchan); ftdm_channel_unlock(peerchan); } else { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "No call data?\n"); } ftdmchan->call_data = NULL; ftdmchan->pflags = 0; ftdm_channel_close(&fchan); } break; case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: case FTDM_CHANNEL_STATE_HANGUP: break; case FTDM_CHANNEL_STATE_UP: { if (ftdm_test_pflag(ftdmchan, PRITAP_NETWORK_ANSWER)) { ftdm_clear_pflag(ftdmchan, PRITAP_NETWORK_ANSWER); sig.event_id = FTDM_SIGEVENT_UP; ftdm_span_send_signal(ftdmchan->span, &sig); } } break; case FTDM_CHANNEL_STATE_RING: { sig.event_id = FTDM_SIGEVENT_START; /* The ring interface (where the setup was received) is the peer, since we RING the channel * where PROCEED/PROGRESS is received */ ftdm_sigmsg_add_var(&sig, "pritap_ring_interface", PRITAP_GET_INTERFACE(peer_pritap->iface)); if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); } } break; case FTDM_CHANNEL_STATE_TERMINATING: { if (ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP) { sig.event_id = FTDM_SIGEVENT_STOP; status = ftdm_span_send_signal(ftdmchan->span, &sig); } ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } break; default: { ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "ignoring state change from %s to %s\n", ftdm_channel_state2str(ftdmchan->last_state), ftdm_channel_state2str(ftdmchan->state)); } break; } return FTDM_SUCCESS; }