static switch_status_t channel_on_destroy(switch_core_session_t *session) { ctdm_private_t *tech_pvt = switch_core_session_get_private(session); if ((tech_pvt = switch_core_session_get_private(session))) { if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to enable echo cancellation.\n"); } 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_unset_read_codec(session); switch_core_session_unset_write_codec(session); ftdm_channel_close(&tech_pvt->ftdm_channel); } return SWITCH_STATUS_SUCCESS; }
void sngisdn_delayed_disconnect(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); if (ftdmchan->caller_data.hangup_cause == IN_CCNORTTODEST || ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) { ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId); sngisdn_snd_disconnect(ftdmchan); if (ftdmchan->caller_data.hangup_cause == IN_CCNORTTODEST) { ftdm_channel_t *close_chan = ftdmchan; ftdm_channel_close(&close_chan); } } ftdm_mutex_unlock(ftdmchan->mutex); return; }
static ftdm_status_t ftdm_gsm_state_advance(ftdm_channel_t *ftdmchan) { ftdm_log_chan(ftdmchan, STATE_ADVANCE_LOG_LEVEL , "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state)); ftdm_channel_complete_state(ftdmchan); switch (ftdmchan->state) { /* starting an incoming call */ case FTDM_CHANNEL_STATE_COLLECT: { } break; /* starting an outgoing call */ case FTDM_CHANNEL_STATE_DIALING: { uint32_t interval = 0; ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting outgoing call with interval %d\n", interval); { ftdm_gsm_span_data_t *gsm_data; gsm_data = ftdmchan->span->signal_data; gsm_data->call_id = g_outbound_call_id++; wat_con_event_t con_event; memset(&con_event, 0, sizeof(con_event)); ftdm_set_string(con_event.called_num.digits, ftdmchan->caller_data.dnis.digits); ftdm_log(FTDM_LOG_DEBUG, "Dialing number %s\n", con_event.called_num.digits); wat_con_req(ftdmchan->span->span_id, gsm_data->call_id , &con_event); SEND_STATE_SIGNAL(FTDM_SIGEVENT_DIALING); } } break; /* incoming call was offered */ case FTDM_CHANNEL_STATE_RING: /* notify the user about the new call */ ftdm_log(FTDM_LOG_INFO, "Answering Incomming Call\r\n"); SEND_STATE_SIGNAL(FTDM_SIGEVENT_START); break; /* the call is making progress */ case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: { SEND_STATE_SIGNAL(FTDM_SIGEVENT_PROGRESS_MEDIA); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); } break; /* the call was answered */ case FTDM_CHANNEL_STATE_UP: { if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { SEND_STATE_SIGNAL(FTDM_SIGEVENT_UP); } else { ftdm_gsm_span_data_t *gsm_data; gsm_data = ftdmchan->span->signal_data; wat_con_cfm(ftdmchan->span->span_id, gsm_data->call_id); } } break; /* just got hangup */ case FTDM_CHANNEL_STATE_HANGUP: { ftdm_gsm_span_data_t *gsm_data; gsm_data = ftdmchan->span->signal_data; wat_rel_req(ftdmchan->span->span_id, gsm_data->call_id); gsm_data->call_id = 0; SEND_STATE_SIGNAL(FTDM_SIGEVENT_STOP); } break; case FTDM_CHANNEL_STATE_TERMINATING: { SEND_STATE_SIGNAL(FTDM_SIGEVENT_STOP); } break; /* finished call for good */ case FTDM_CHANNEL_STATE_DOWN: { ftdm_channel_t *closed_chan; closed_chan = ftdmchan; ftdm_channel_close(&closed_chan); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "State processing ended.\n"); SEND_STATE_SIGNAL(FTDM_SIGEVENT_STOP); } break; /* INDICATE_RINGING doesn't apply to MFC/R2. maybe we could generate a tone */ case FTDM_CHANNEL_STATE_RINGING: ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RINGING indicated, ignoring it as it doesn't apply to MFC/R2\n"); SEND_STATE_SIGNAL(FTDM_SIGEVENT_RINGING); break; /* put the r2 channel back to IDLE, close ftdmchan and set it's state as DOWN */ case FTDM_CHANNEL_STATE_RESET: { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RESET indicated, putting the R2 channel back to IDLE\n"); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } break; default: { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Unhandled channel state change: %s\n", ftdm_channel_state2str(ftdmchan->state)); } break; } return FTDM_SUCCESS; }
int main(int argc, char *argv[]) { ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG); ftdm_channel_t *chan; unsigned ms = 20; ftdm_codec_t codec = FTDM_CODEC_SLIN; unsigned runs = 1; int spanid, chanid; ftdm_unused_arg(argc); ftdm_unused_arg(argv); if (ftdm_global_init() != FTDM_SUCCESS) { fprintf(stderr, "Error loading FreeTDM\n"); exit(-1); } printf("FreeTDM loaded\n"); top: //if (ftdm_channel_open_any("wanpipe", 0, FTDM_TOP_DOWN, &chan) == FTDM_SUCCESS) { if (ftdm_channel_open(1, 1, &chan) == FTDM_SUCCESS) { int x = 0; spanid = ftdm_channel_get_span_id(chan); chanid = ftdm_channel_get_id(chan); printf("opened channel %d:%d\n", spanid, chanid); #if 1 if (ftdm_channel_command(chan, FTDM_COMMAND_SET_INTERVAL, &ms) == FTDM_SUCCESS) { ms = 0; ftdm_channel_command(chan, FTDM_COMMAND_GET_INTERVAL, &ms); printf("interval set to %u\n", ms); } else { printf("set interval failed [%s]\n", ftdm_channel_get_last_error(chan)); } #endif if (ftdm_channel_command(chan, FTDM_COMMAND_SET_CODEC, &codec) == FTDM_SUCCESS) { codec = 1; ftdm_channel_command(chan, FTDM_COMMAND_GET_CODEC, &codec); printf("codec set to %u\n", codec); } else { printf("set codec failed [%s]\n", ftdm_channel_get_last_error(chan)); } for(x = 0; x < 25; x++) { unsigned char buf[2048]; ftdm_size_t len = sizeof(buf); ftdm_wait_flag_t flags = FTDM_READ; if (ftdm_channel_wait(chan, &flags, -1) == FTDM_FAIL) { printf("wait FAIL! %u [%s]\n", (unsigned)len, ftdm_channel_get_last_error(chan)); } if (flags & FTDM_READ) { if (ftdm_channel_read(chan, buf, &len) == FTDM_SUCCESS) { printf("READ: %u\n", (unsigned)len); } else { printf("READ FAIL! %u [%s]\n", (unsigned)len, ftdm_channel_get_last_error(chan)); break; } } else { printf("wait fail [%s]\n", ftdm_channel_get_last_error(chan)); } } ftdm_channel_close(&chan); } else { printf("open fail [%s]\n", ftdm_channel_get_last_error(chan)); } if(--runs) { goto top; } ftdm_global_destroy(); return 0; }
static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause) { const char *szchanid = switch_event_get_header(var_event, kCHAN_ID), *span_name = switch_event_get_header(var_event, kSPAN_NAME), *szprebuffer_len = switch_event_get_header(var_event, kPREBUFFER_LEN); int chan_id; int span_id; switch_caller_profile_t *caller_profile; ftdm_span_t *span; ftdm_channel_t *chan; switch_channel_t *channel; char name[128]; const char *dname; ftdm_codec_t codec; uint32_t interval; ctdm_private_t *tech_pvt = NULL; if (zstr(szchanid) || zstr(span_name)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Both ["kSPAN_ID"] and ["kCHAN_ID"] have to be set.\n"); goto fail; } chan_id = atoi(szchanid); if (ftdm_span_find_by_name(span_name, &span) == FTDM_SUCCESS) { span_id = ftdm_span_get_id(span); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find span [%s]\n", span_name); goto fail; } if (!(*new_session = switch_core_session_request(ctdm.endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, 0, pool))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't request session.\n"); goto fail; } channel = switch_core_session_get_channel(*new_session); if (ftdm_channel_open_ph(span_id, chan_id, &chan) != FTDM_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't open span or channel.\n"); goto fail; } span = ftdm_channel_get_span(chan); tech_pvt = switch_core_session_alloc(*new_session, sizeof *tech_pvt); tech_pvt->chan_id = chan_id; tech_pvt->span_id = span_id; tech_pvt->ftdm_channel = chan; tech_pvt->session = *new_session; tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf); tech_pvt->read_frame.data = tech_pvt->databuf; tech_pvt->prebuffer_len = zstr(szprebuffer_len) ? 0 : atoi(szprebuffer_len); switch_core_session_set_private(*new_session, tech_pvt); caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); switch_channel_set_caller_profile(channel, caller_profile); snprintf(name, sizeof(name), "tdm/%d:%d", span_id, chan_id); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name); switch_channel_set_name(channel, name); switch_channel_set_state(channel, CS_INIT); if (FTDM_SUCCESS != ftdm_channel_command(chan, FTDM_COMMAND_GET_CODEC, &codec)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve channel codec.\n"); return SWITCH_STATUS_GENERR; } if (FTDM_SUCCESS != ftdm_channel_command(chan, FTDM_COMMAND_GET_INTERVAL, &interval)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve channel interval.\n"); return SWITCH_STATUS_GENERR; } if (FTDM_SUCCESS != ftdm_channel_command(chan, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tech_pvt->prebuffer_len)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set channel pre buffer size.\n"); return SWITCH_STATUS_GENERR; } if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to set enable echo cancellation.\n"); } switch(codec) { case FTDM_CODEC_ULAW: { dname = "PCMU"; } break; case FTDM_CODEC_ALAW: { dname = "PCMA"; } break; case FTDM_CODEC_SLIN: { dname = "L16"; } break; default: { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid codec value retrieved from channel, codec value: %d\n", codec); goto fail; } } if (switch_core_codec_init(&tech_pvt->read_codec, dname, NULL, 8000, interval, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); goto fail; } else { if (switch_core_codec_init(&tech_pvt->write_codec, dname, NULL, 8000, interval, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); switch_core_codec_destroy(&tech_pvt->read_codec); goto fail; } } if (switch_core_session_set_read_codec(*new_session, &tech_pvt->read_codec) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set read codec?\n"); goto fail; } if (switch_core_session_set_write_codec(*new_session, &tech_pvt->write_codec) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set write codec?\n"); } if (switch_core_session_thread_launch(*new_session) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't start session thread.\n"); goto fail; } switch_channel_mark_answered(channel); return SWITCH_CAUSE_SUCCESS; fail: if (tech_pvt) { if (tech_pvt->ftdm_channel) { ftdm_channel_close(&tech_pvt->ftdm_channel); } 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); } } if (*new_session) { switch_core_session_destroy(new_session); } return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; }
static void launch_channel(struct sangoma_pri *spri, int channo) { pid_t pid; int fd = 0, file = 0, inlen = 0, outlen = 0; unsigned char inframe[MAX_BYTES], outframe[MAX_BYTES]; fd_set readfds; int mtu_mru=BYTES / 2; int err; ftdm_channel_t *chan; ftdm_codec_t codec = FTDM_CODEC_SLIN; unsigned ms = 20; unsigned int lead = 50; int ifd = -1; ftdm_tone_type_t tt = FTDM_TONE_DTMF; char dtmf[] = "1234567890"; int loops = 0; pid = fork(); if (pid) { pidmap[channo-1].pid = pid; printf("-- Launching process %d to handle channel %d\n", pid, channo); return; } signal(SIGINT, handle_SIGINT); //ifd = open("/nfs/sounds/ptest.raw", O_WRONLY|O_CREAT|O_TRUNC, 777); memset(inframe, 0, MAX_BYTES); memset(outframe, 0, MAX_BYTES); if (ftdm_channel_open(spri->span, channo, &chan) != FTDM_SUCCESS) { printf("DEBUG cant open fd!\n"); } #if 1 if (ftdm_channel_command(chan, FTDM_COMMAND_SET_CODEC, &codec) != FTDM_SUCCESS) { printf("Critical Error: Failed to set driver codec!\n"); ftdm_channel_close(&chan); exit(-1); } #endif #if 1 if (ftdm_channel_command(chan, FTDM_COMMAND_ENABLE_DTMF_DETECT, &tt) != FTDM_SUCCESS) { printf("Critical Error: Failed to set dtmf detect!\n"); ftdm_channel_close(&chan); exit(-1); } ftdm_channel_set_event_callback(chan, my_ftdm_event_handler); #endif if (ftdm_channel_command(chan, FTDM_COMMAND_SET_INTERVAL, &ms) != FTDM_SUCCESS) { printf("Critical Error: Failed to set codec interval!\n"); ftdm_channel_close(&chan); exit(-1); } file = open("sound.raw", O_RDONLY); if (file < 0) { printf("Critical Error: Failed to open sound file!\n"); ftdm_channel_close(&chan); exit(-1); } while(ready) { ftdm_wait_flag_t flags = FTDM_READ; ftdm_size_t len; loops++; if (lead) { lead--; } if (!lead && loops == 300) { #if 1 if (ftdm_channel_command(chan, FTDM_COMMAND_SEND_DTMF, dtmf) != FTDM_SUCCESS) { printf("Critical Error: Failed to send dtmf\n"); ftdm_channel_close(&chan); exit(-1); } #endif } if (ftdm_channel_wait(chan, &flags, 2000) != FTDM_SUCCESS) { printf("wait FAIL! [%s]\n", chan->last_error); break; } if (flags & FTDM_READ) { len = MAX_BYTES; if (ftdm_channel_read(chan, inframe, &len) == FTDM_SUCCESS) { //printf("READ: %d\n", len); //write(ifd, inframe, len); if(!lead && (outlen = read(file, outframe, len)) <= 0) { break; } } else { printf("READ FAIL! %d [%s]\n", len, chan->last_error); break; } if (lead) { continue; } ftdm_channel_write(chan, outframe, sizeof(outframe), &len); } else { printf("BREAK"); break; } } printf("loop done\n"); //sangoma_get_full_cfg(fd, &tdm_api); close(file); //close(ifd); pri_hangup(spri->pri, channo, 16); if (ftdm_channel_close(&chan) != FTDM_SUCCESS) { printf("Critical Error: Failed to close channel [%s]\n", chan->last_error); } printf("Call Handler: Process Finished\n"); exit(0); }
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; }