Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "ftdm_core.h"
- #include "ftdm_state.h"
- #include "freetdm.h"
- #include <stdlib.h>
- /* some timers (in seconds) to fake responses in incoming calls */
- #define MAX_CALLS 255
- #define PROGRESS_TIMER 1
- #define ANSWER_TIMER 5
- #define HANGUP_TIMER 15
- #define SANGOMA_CARD
- #undef LIBPRI_CARD
- #define TELCO_SIDE
- #ifdef TELCO_SIDE
- #undef TERMINAL_SIDE
- #define HUNTING_GROUP_ID 1
- #else
- #define TERMINAL_SIDE
- #define TERMINAL_SIDE_CALLS
- #define HUNTING_GROUP_ID 2
- #endif
- #define MAKE_CALLS
- #define E1_SPANS 4
- /* simple variable used to stop the application */
- static int app_running = 0;
- static int global_call_count = 0;
- typedef void (*expired_function_t)(ftdm_channel_t *channel);
- typedef struct dummy_timer_s {
- int time;
- ftdm_channel_t *channel;
- expired_function_t expired;
- } dummy_timer_t;
- /* dummy second resolution timers */
- static dummy_timer_t g_timers[MAX_CALLS];
- /* mutex to protect the timers (both, the test thread and the signaling thread may modify them) */
- static ftdm_mutex_t *g_schedule_mutex;
- /* unique outgoing channel */
- static ftdm_channel_t *g_outgoing_channel = NULL;
- static int callAnswered = 0;
- static char extCallId[100] = { 0 };
- /* private data attached to each fs session */
- struct private_object {
- unsigned int flags;
- unsigned int codec;
- unsigned int codecs;
- unsigned short samprate;
- ftdm_channel_t *ftdmchan;
- uint32_t wr_error;
- };
- /* private data attached to FTDM channels (only FXS for now) */
- typedef struct chan_pvt {
- unsigned int flags;
- } chan_pvt_t;
- typedef struct private_object private_t;
- struct span_config {
- ftdm_span_t *span;
- char dialplan[80];
- char context[80];
- char dial_regex[256];
- char fail_dial_regex[256];
- char hold_music[256];
- char type[256];
- const char *limit_backend;
- int limit_calls;
- int limit_seconds;
- chan_pvt_t pvts[FTDM_MAX_CHANNELS_SPAN];
- };
- static ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg)
- {
- uint32_t spanid, chanid;
- char name[128];
- ftdm_caller_data_t *channel_caller_data = ftdm_channel_get_caller_data(sigmsg->channel);
- spanid = ftdm_channel_get_span_id(sigmsg->channel);
- chanid = ftdm_channel_get_id(sigmsg->channel);
- snprintf(name, sizeof(name), "FreeTDM/%u:%u/%s", spanid, chanid, channel_caller_data->dnis.digits);
- ftdm_log(FTDM_LOG_NOTICE, "freetdm span name %s\n", name);
- return FTDM_SUCCESS;
- }
- static void schedule_timer(ftdm_channel_t *channel, int sec, expired_function_t expired)
- {
- int i;
- ftdm_mutex_lock(g_schedule_mutex);
- for (i = 0; i < sizeof(g_timers)/sizeof(g_timers[0]); i++) {
- /* check the timer slot is free to use */
- if (!g_timers[i].time) {
- g_timers[i].time = sec;
- g_timers[i].channel = channel;
- g_timers[i].expired = expired;
- ftdm_mutex_unlock(g_schedule_mutex);
- return;
- }
- }
- ftdm_log(FTDM_LOG_ERROR, "Failed to schedule timer\n");
- ftdm_mutex_unlock(g_schedule_mutex);
- }
- static void run_timers(void)
- {
- int i;
- void *channel;
- expired_function_t expired_func = NULL;
- ftdm_mutex_lock(g_schedule_mutex);
- for (i = 0; i < sizeof(g_timers)/sizeof(g_timers[0]); i++) {
- /* if there's time left, decrement */
- if (g_timers[i].time) {
- g_timers[i].time--;
- }
- /* if time expired and we have an expired function, call it */
- if (!g_timers[i].time && g_timers[i].expired) {
- expired_func = g_timers[i].expired;
- channel = g_timers[i].channel;
- memset(&g_timers[i], 0, sizeof(g_timers[i]));
- expired_func(channel);
- }
- }
- ftdm_mutex_unlock(g_schedule_mutex);
- }
- static void release_timers(ftdm_channel_t *channel)
- {
- int i;
- ftdm_mutex_lock(g_schedule_mutex);
- for (i = 0; i < sizeof(g_timers)/sizeof(g_timers[0]); i++) {
- /* clear any timer belonging to the given channel */
- if (g_timers[i].channel == channel) {
- memset(&g_timers[i], 0, sizeof(g_timers[i]));
- }
- }
- ftdm_mutex_unlock(g_schedule_mutex);
- }
- /* send answer for an incoming call */
- static void send_answer(ftdm_channel_t *channel)
- {
- /* we move the channel signaling state machine to UP (answered) */
- ftdm_log(FTDM_LOG_NOTICE, "-- Requesting answer in channel %d:%d\n", channel->span_id, channel->chan_id);
- ftdm_channel_call_answer(channel);
- callAnswered = 1;
- }
- /* send progress for an incoming */
- static void send_progress(ftdm_channel_t *channel)
- {
- /* we move the channel signaling state machine to UP (answered) */
- ftdm_log(FTDM_LOG_NOTICE, "-- Requesting progress\n", channel->span_id, channel->chan_id);
- ftdm_channel_call_indicate(channel, FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA);
- schedule_timer(channel, ANSWER_TIMER, send_answer);
- }
- /* send ringing for an incoming */
- static void send_ringing(ftdm_channel_t *channel)
- {
- /* we move the channel signaling state machine to UP (answered) */
- ftdm_log(FTDM_LOG_NOTICE, "-- Requesting ringing\n", channel->span_id, channel->chan_id);
- ftdm_channel_call_indicate(channel, FTDM_CHANNEL_INDICATE_RINGING);
- schedule_timer(channel, ANSWER_TIMER, send_progress);
- }
- /* send proceed for an incoming */
- static void send_proceed(ftdm_channel_t *channel)
- {
- /* we move the channel signaling state machine to UP (answered) */
- ftdm_log(FTDM_LOG_NOTICE, "-- Requesting proceed\n", channel->span_id, channel->chan_id);
- ftdm_channel_call_indicate(channel, FTDM_CHANNEL_INDICATE_PROCEED);
- schedule_timer(channel, ANSWER_TIMER, send_ringing);
- }
- static void place_call(void)
- {
- // return ;
- ftdm_usrmsg_t usrmsg;
- uint8_t *my_facility_ie = ftdm_calloc(1, 200); /*memory has to be allocated using ftdm_calloc !! */
- unsigned my_facility_ie_len = 0;
- memset(&usrmsg, 0, sizeof(usrmsg));
- my_facility_ie[my_facility_ie_len++] = 0xEE;
- my_facility_ie[my_facility_ie_len++] = 0xFF;
- my_facility_ie[my_facility_ie_len++] = 0x5C;
- my_facility_ie[my_facility_ie_len++] = 0x5D;
- my_facility_ie[my_facility_ie_len++] = 0x6E;
- my_facility_ie[my_facility_ie_len++] = 0x7F;
- ftdm_caller_data_t caller_data = {{ 0 }};
- /* set destiny number */
- ftdm_set_string(caller_data.dnis.digits, "2223");
- /* set callerid */
- ftdm_set_string(caller_data.cid_name, "testsangomaboost");
- ftdm_set_string(caller_data.cid_num.digits, "1234");
- /* set the caller data for the outgoing channel */
- ftdm_hunting_scheme_t hunting;
- memset(&hunting, 0, sizeof(hunting));
- hunting.mode_data.span.direction = FTDM_TOP_DOWN;
- hunting.mode = FTDM_HUNT_SPAN;
- hunting.mode_data.span.span_id = 3;
- #ifdef MAKE_CALLS
- ftdm_status_t status = FTDM_SUCCESS;
- ftdm_log(FTDM_LOG_ERROR, "testapp placing call, raw_len: %d\n", usrmsg.raw.len);
- int callcount = 0;
- struct timeval td_start,td_end;
- if(gettimeofday(&td_start,NULL))
- {
- printf("time failed\n");
- exit(1);
- }
- while ((callcount < global_call_count) && (status == FTDM_SUCCESS)) // place as many calls as succeeds
- {
- char caller[25], called[25];
- snprintf(caller, sizeof(caller), "0259682345");
- snprintf(called, sizeof(called), "02595682345");
- ftdm_set_string(caller_data.dnis.digits, called);
- ftdm_set_string(caller_data.cid_num.digits, caller);
- caller_data.priv = (void *) (&extCallId[callcount]);
- status = ftdm_call_place_ex(&caller_data, &hunting, &usrmsg);
- callcount++;
- if (status != FTDM_SUCCESS)
- {
- ftdm_log(FTDM_LOG_ERROR, "Failed to originate call %d\n", status);
- //return;
- break;
- }
- }
- if(gettimeofday(&td_end,NULL))
- {
- printf("time failed\n");
- exit(1);
- }
- long elapsed = 1000000.0 * (td_end.tv_sec -td_start.tv_sec);
- elapsed += (td_end.tv_usec - td_start.tv_usec);
- ftdm_log(FTDM_LOG_ERROR, "placing %d calls took %dms\n", callcount, elapsed);
- #endif // TERMINAL_SIDE
- ftdm_log(FTDM_LOG_ERROR, "Call originated, call_id returned: %d\n", caller_data.call_id);
- }
- static FIO_SIGNAL_CB_FUNCTION(on_signaling_event)
- {
- ftdm_log(FTDM_LOG_NOTICE, "XXX CALLBACK\n");
- /* Inside event call-back function */
- ftdm_iterator_t *iter = NULL;
- ftdm_iterator_t *curr = NULL;
- const char *var_name = NULL;
- const char *var_value = NULL;
- ftdm_status_t retval;
- ftdm_log(FTDM_LOG_NOTICE, ">***** ***** ****** ******\n");
- /* Read all variables attached to this event */
- iter = ftdm_sigmsg_get_var_iterator(sigmsg, iter);
- for (curr = iter ; curr; curr = ftdm_iterator_next(curr))
- {
- ftdm_get_current_var(curr, &var_name, &var_value);
- ftdm_log(FTDM_LOG_NOTICE, "Call Variable: %s=%s\n", var_name, var_value);
- }
- ftdm_iterator_free(iter);
- ftdm_log(FTDM_LOG_NOTICE, "<***** ***** ****** ******\n");
- ftdm_log(FTDM_LOG_NOTICE, "RAW>***** ***** ****** ******\n");
- /* Inside event call-back function */
- ftdm_log(FTDM_LOG_NOTICE, "raw.len: %d\n", sigmsg->raw.len);
- ftdm_size_t len;
- uint8_t *mydata;
- if (ftdm_sigmsg_get_raw_data(sigmsg, (void**)&mydata, &len) == FTDM_SUCCESS)
- {
- /* raw data is available, do something with mydata here */
- for (int i = 0; i < len; i++)
- {
- ftdm_log(FTDM_LOG_NOTICE, "0x%x ", mydata[i]);
- }
- ftdm_log(FTDM_LOG_NOTICE, "\n");
- }
- /* Once this function returns, raw data will be free'd inside FreeTDM */
- ftdm_log(FTDM_LOG_NOTICE, "RAW<***** ***** ****** ******\n");
- switch (sigmsg->event_id)
- {
- /* This event signals the start of an incoming call */
- case FTDM_SIGEVENT_START:
- ftdm_log(FTDM_LOG_NOTICE, "Incoming call received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id);
- schedule_timer(sigmsg->channel, PROGRESS_TIMER, send_proceed);
- g_outgoing_channel = sigmsg->channel;
- if (g_outgoing_channel != NULL)
- {
- ftdm_log(FTDM_LOG_NOTICE, "XXX outgoing channel assigned\n");
- }
- ftdm_log(FTDM_LOG_WARNING, "NATIVE CODEC: %d\n", g_outgoing_channel->native_codec);
- ftdm_log(FTDM_LOG_WARNING, "EFFECT CODEC: %d\n", g_outgoing_channel->effective_codec);
- retval = ftdm_channel_command(sigmsg->channel,FTDM_COMMAND_ENABLE_DTMF_DETECT, NULL);
- ftdm_log(FTDM_LOG_NOTICE, "dtmf enabling retval%d\n", retval);
- return ftdm_channel_from_event(sigmsg);
- break;
- /* This event signals progress on an outgoing call */
- case FTDM_SIGEVENT_PROGRESS_MEDIA:
- ftdm_log(FTDM_LOG_NOTICE, "Progress message received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id);
- break;
- /* This event signals answer in an outgoing call */
- case FTDM_SIGEVENT_UP:
- ftdm_log(FTDM_LOG_NOTICE, "Answer received in channel %d:%d extCallId %d\n", sigmsg->span_id, sigmsg->chan_id, *((char *)sigmsg->call_priv));
- /* now the channel is answered and we can use
- * ftdm_channel_wait() to wait for input/output in a channel (equivalent to poll() or select())
- * ftdm_channel_read() to read available data in a channel
- * ftdm_channel_write() to write to the channel */
- g_outgoing_channel = sigmsg->channel;
- callAnswered = 1;
- retval = 0;
- ftdm_log(FTDM_LOG_NOTICE, "dtmf enabling retval%d\n", retval);
- break;
- /* This event signals hangup from the other end */
- case FTDM_SIGEVENT_STOP:
- ftdm_log(FTDM_LOG_NOTICE, "Hangup received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id);
- if (g_outgoing_channel == sigmsg->channel) {
- g_outgoing_channel = NULL;
- }
- release_timers(sigmsg->channel);
- ftdm_set_state_locked(sigmsg->channel, FTDM_CHANNEL_STATE_HANGUP);
- break;
- case FTDM_SIGEVENT_RESTART:
- ftdm_log(FTDM_LOG_NOTICE, "Restart received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id);
- break;
- case FTDM_SIGEVENT_PROGRESS:
- ftdm_log(FTDM_LOG_NOTICE, "Progress received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id);
- break;
- case FTDM_SIGEVENT_RINGING:
- ftdm_log(FTDM_LOG_NOTICE, "Ringing received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id);
- break;
- case FTDM_SIGEVENT_PROCEED:
- ftdm_log(FTDM_LOG_NOTICE, " proceed received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id);
- break;
- case FTDM_SIGEVENT_FACILITY:
- ftdm_log(FTDM_LOG_NOTICE, " facility received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id);
- break;
- case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
- ftdm_log(FTDM_LOG_NOTICE, "status changed received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id);
- break;
- default:
- ftdm_log(FTDM_LOG_WARNING, "Unhandled event %s in channel %d:%d\n", ftdm_signal_event2str(sigmsg->event_id),
- sigmsg->span_id, sigmsg->chan_id);
- break;
- }
- return FTDM_SUCCESS;
- }
- int main(int argc, char *argv[])
- {
- ftdm_global_set_default_logger(7);
- int ako = 0;
- for (; ako < sizeof(extCallId); ako++)
- {
- extCallId[ako] = ako;
- }
- ftdm_conf_parameter_t parameters[20];
- ftdm_span_t *span[4];
- if (ftdm_global_init() != FTDM_SUCCESS)
- {
- fprintf(stderr, "Error loading FreeTDM\n");
- exit(-1);
- }
- ftdm_mutex_create(&g_schedule_mutex);
- ftdm_global_configuration();
- printf("MY own FreeTDM loaded\n");
- //global_call_count = atoi(argv[1]);
- global_call_count = 1;
- int i = 0;
- for(i = 0; i<E1_SPANS; i++)
- {
- if (ftdm_span_find(i+1, &span[i]) != FTDM_SUCCESS)
- {
- fprintf(stderr, "Error finding FreeTDM span\n");
- goto done;
- }
- /* following parameters are signaling stack specific, this ones are for PRI */
- #ifdef SANGOMA_CARD
- parameters[0].var = "switchtype";
- parameters[0].val = "euroisdn";
- parameters[1].var = "interface";
- #ifdef TERMINAL_SIDE
- parameters[1].val = "pri_cpe";
- #endif // TERMINAL_SIDE
- #ifdef TELCO_SIDE
- if (i == 1)
- {
- parameters[1].val = "pri_cpe";
- }
- else
- {
- parameters[1].val = "pri_net";
- }
- #endif // TELCO_SIDE
- parameters[2].var = "outbound-bearer_cap";
- parameters[2].val = "unrestricted-digital";
- parameters[3].var = "outbound-bearer_layer1";
- parameters[3].val = "alaw";
- parameters[4].var = "overlap";
- parameters[4].val = "yes";
- parameters[5].var = "facility-ie-decode";
- parameters[5].val = "no";
- parameters[6].var = NULL;
- #endif
- #ifdef LIBPRI_CARD
- parameters[0].var = "switch";
- parameters[0].val = "euroisdn";
- parameters[1].var = "mode";
- #ifdef TERMINAL_SIDE
- parameters[1].val = "cpe";
- #endif // TERMINAL_SIDE
- #ifdef TELCO_SIDE
- parameters[1].val = "net";
- #endif // TELCO_SIDE
- parameters[2].var = "debug";
- parameters[2].val = "all";
- parameters[3].var = NULL;
- #endif
- /* send the configuration values down to the stack */
- #ifdef LIBPRI_CARD
- if (ftdm_configure_span_signaling(span[i], "libpri", on_signaling_event, parameters) != FTDM_SUCCESS)
- {
- #endif
- #ifdef SANGOMA_CARD
- if (ftdm_configure_span_signaling(span[i], "sangoma_isdn", on_signaling_event, parameters) != FTDM_SUCCESS)
- {
- #endif
- goto done;
- }
- ftdm_span_start(span[i]);
- }
- /* OK SPANS ARE STARTED */
- int32_t ticks = 0;
- ftdm_wait_flag_t wflags = FTDM_READ;
- ftdm_size_t len = 0, bufLen = 0;
- unsigned char dataBuff[160];
- unsigned char to = 20;
- unsigned long globalRead = 0, inbufferdatalen = 0, inbuffercurrentread = 144000;
- /* read the prebuferred voice data in binary file */
- unsigned char inbuffer[800000];
- FILE *inFile;
- if((inFile = fopen("sample_binin", "rb")))
- {
- inbufferdatalen = fread(inbuffer, 1, sizeof(inbuffer), inFile);
- fclose(inFile);
- }
- printf("inbufferdatalelu %lu \n", inbufferdatalen);
- app_running = 1;
- /* The application thread can go on and do anything else, like waiting for a shutdown signal */
- while(ftdm_running() && app_running && ticks < 300000000)
- {
- if (callAnswered == 0)
- {
- ftdm_sleep(1000);
- }
- run_timers();
- if (ticks == 20)
- {
- place_call();
- }
- ftdm_log(FTDM_LOG_ERROR, "ticks %d\n", ticks);
- ticks++;
- if (callAnswered && (g_outgoing_channel != NULL))
- {
- // ftdm_sleep(1);
- int sp = 0;
- to = 20;
- char needWait = 1;
- for (sp = 0; sp < 2; sp++)
- {
- ftdm_iterator_t *channelSpanIterator = ftdm_span_get_chan_iterator(span[sp], NULL);
- do
- {
- ftdm_channel_t *ftdmchan = ftdm_iterator_current(channelSpanIterator);
- if (ftdmchan == NULL)
- {
- ftdm_log(FTDM_LOG_WARNING, "iterator current returned NULL\n");
- break;
- }
- channelSpanIterator = ftdm_iterator_next(channelSpanIterator);
- unsigned char channelId = ftdm_channel_get_id(ftdmchan);
- unsigned char spanId = ftdm_channel_get_span_id(ftdmchan);
- if (channelId == 31)
- {
- // Skip the D-chan
- break;
- }
- if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN))
- {
- // Channel is not open
- ftdm_log(FTDM_LOG_WARNING, "Channel is not openedi s %d ch %d\n", spanId, channelId);
- continue;
- }
- unsigned int llen = ftdm_channel_get_io_packet_len(ftdmchan);
- ftdm_log(FTDM_LOG_ERROR, "channel packet length %d s %d ch %d\n", llen, spanId, channelId);
- ftdm_status_t ftdmret = FTDM_SUCCESS;
- wflags = FTDM_READ | FTDM_WRITE ;
- if (needWait)
- {
- ftdmret = ftdm_channel_wait(ftdmchan, &wflags, 20);
- to = 0;
- if (ftdmret == FTDM_FAIL)
- {
- ftdm_log(FTDM_LOG_WARNING, "r wait failed s %d ch %d\n", spanId, channelId);
- break;
- }
- if (ftdmret == FTDM_TIMEOUT)
- {
- ftdm_log(FTDM_LOG_WARNING, "r wait timeouted s %d ch %d\n", spanId, channelId);
- break;
- }
- if (!(wflags & FTDM_READ))
- {
- ftdm_log(FTDM_LOG_WARNING, "read not possibles %d ch %d wf 0x%x\n", spanId, channelId, wflags);
- break;
- }
- if (!(wflags & FTDM_WRITE))
- {
- ftdm_log(FTDM_LOG_WARNING, "write not possibles %d ch %d wf 0x%x\n", spanId, channelId, wflags);
- break;
- }
- needWait = 0;
- }
- bufLen = sizeof(dataBuff);
- int read = 1;
- /* measurement loop */
- while (read)
- {
- if (ftdm_channel_read(ftdmchan, dataBuff, &bufLen) != FTDM_SUCCESS)
- {
- ftdm_log(FTDM_LOG_WARNING, "r failed to read from device s %d ch %d\n", spanId, channelId);
- read = 0;
- }
- else
- {
- globalRead += bufLen;
- if (bufLen != 160)
- {
- ftdm_log(FTDM_LOG_ERROR, "XXXXX different buflen %d\n ", bufLen);
- }
- len = bufLen;
- if ((1== ftdm_channel_get_id(ftdmchan)) && (sp == 0))
- {
- //originator
- if (ftdm_channel_write(ftdmchan, inbuffer + inbuffercurrentread , 80, &len) != FTDM_SUCCESS)
- {
- ftdm_log(FTDM_LOG_WARNING, "failed to write to device s %d ch %d\n", spanId, channelId);
- }
- else
- {
- ftdm_log(FTDM_LOG_ERROR, "buflen %d lenn %d written s %d ch %d\n", bufLen, len, spanId, channelId);
- if (len != bufLen)
- {
- ftdm_log(FTDM_LOG_ERROR, "requested %d written %d\n", bufLen, len);
- }
- FILE *outrFile;
- if((outrFile = fopen("orbinout", "a")))
- {
- fwrite(dataBuff, 1, len, outrFile);
- fclose(outrFile);
- }
- FILE *outFile;
- if((outFile = fopen("owbinout", "a")))
- {
- fwrite(inbuffer + inbuffercurrentread, 1, len, outFile);
- fclose(outFile);
- }
- inbuffercurrentread += len;
- if (inbuffercurrentread >= inbufferdatalen)
- {
- inbuffercurrentread = 144000;
- }
- }
- }
- else if ((1== ftdm_channel_get_id(ftdmchan)) && (sp == 1))
- {
- // acceptor
- if (ftdm_channel_write(ftdmchan, dataBuff, bufLen, &len) != FTDM_SUCCESS)
- {
- ftdm_log(FTDM_LOG_WARNING, "failed to write to device s %d ch %d\n", spanId, channelId);
- }
- else
- {
- ftdm_log(FTDM_LOG_ERROR, "buflen %d lenn %d written s %d ch %d\n", bufLen, len, spanId, channelId);
- if (len != bufLen)
- {
- ftdm_log(FTDM_LOG_ERROR, "requested %d written %d\n", bufLen, len);
- }
- FILE *outawFile;
- if((outawFile = fopen("awbinout", "a")))
- {
- fwrite(dataBuff, 1, len, outawFile);
- fclose(outawFile);
- }
- }
- }
- }
- }
- }
- while (channelSpanIterator);
- ftdm_iterator_free(channelSpanIterator);
- }
- }
- }
- done:
- ftdm_global_destroy();
- return 1;
- }
Add Comment
Please, Sign In to add comment