FT_DECLARE(void) ftdm_buffer_destroy(ftdm_buffer_t **buffer) { if (*buffer) { ftdm_safe_free((*buffer)->data); ftdm_safe_free(*buffer); } *buffer = NULL; }
ftdm_status_t sngisdn_transfer(ftdm_channel_t *ftdmchan) { const char* args; char *p; char *type = NULL; char *target = NULL; ftdm_status_t status = FTDM_FAIL; sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; unsigned i; args = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "transfer_arg"); if (ftdm_strlen_zero(args)) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot perform transfer because call_transfer_arg variable is not set\n"); goto done; } type = ftdm_strdup(args); if ((p = strchr(type, '/'))) { target = ftdm_strdup(p+1); *p = '\0'; } if (ftdm_strlen_zero(type) || ftdm_strlen_zero(target)) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Invalid parameters for transfer %s, expected <type>/<target>\n", args); goto done; } if (sngisdn_info->transfer_data.type != SNGISDN_TRANSFER_NONE) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot perform transfer because an existing transfer transfer is pending (%s)\n", sngisdn_transfer_type2str(sngisdn_info->transfer_data.type)); goto done; } ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Transfer requested type:%s target:%s\n", type, target); for (i = 0; i < ftdm_array_len(transfer_interfaces); i++ ) { if (!strcasecmp(transfer_interfaces[i].name, type)) { /* Depending on the transfer type, the transfer function may change the * channel state to UP, or last_state, but the transfer function will always result in * an immediate state change if FTDM_SUCCESS is returned */ status = transfer_interfaces[i].func(ftdmchan, transfer_interfaces[i].type, target); goto done; } } ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Invalid transfer type:%s\n", type); done: if (status != FTDM_SUCCESS) { ftdm_set_state(ftdmchan, ftdmchan->last_state); } ftdm_safe_free(type); ftdm_safe_free(target); return status; }
FT_DECLARE(ftdm_status_t) ftdm_sched_destroy(ftdm_sched_t **insched) { ftdm_sched_t *sched = NULL; ftdm_timer_t *timer; ftdm_timer_t *deltimer; ftdm_assert_return(insched != NULL, FTDM_EINVAL, "sched is null!\n"); ftdm_assert_return(*insched != NULL, FTDM_EINVAL, "sched is null!\n"); sched = *insched; /* since destroying a sched may affect the global list, we gotta check */ ftdm_mutex_lock(sched_globals.mutex); /* if we're head, replace head with our next (whatever our next is, even null will do) */ if (sched == sched_globals.freeruns) { sched_globals.freeruns = sched->next; } /* if we have a previous member (then we were not head) set our previous next to our next */ if (sched->prev) { sched->prev->next = sched->next; } /* if we have a next then set their prev to our prev (if we were head prev will be null and sched->next is already the new head) */ if (sched->next) { sched->next->prev = sched->prev; } ftdm_mutex_unlock(sched_globals.mutex); /* now grab the sched mutex */ ftdm_mutex_lock(sched->mutex); timer = sched->timers; while (timer) { deltimer = timer; timer = timer->next; ftdm_safe_free(deltimer); } ftdm_log(FTDM_LOG_DEBUG, "Destroying schedule %s\n", sched->name); ftdm_mutex_unlock(sched->mutex); ftdm_mutex_destroy(&sched->mutex); ftdm_safe_free(sched); *insched = NULL; return FTDM_SUCCESS; }
hashtable_destroy(struct hashtable *h) { unsigned int i; struct entry *e, *f; struct entry **table = h->table; for (i = 0; i < h->tablelength; i++) { e = table[i]; while (NULL != e) { f = e; e = e->next; if (f->flags & HASHTABLE_FLAG_FREE_KEY) freekey(f->k); if (f->flags & HASHTABLE_FLAG_FREE_VALUE) ftdm_safe_free(f->v); ftdm_safe_free(f); } } ftdm_safe_free(h->table); ftdm_safe_free(h); }
void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len) { char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */ sngisdn_decode_q931(data_str, data, data_len); ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] %s FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str); ftdm_safe_free(data_str); }
int hashtable_iterator_remove(struct hashtable_itr *itr) { struct entry *remember_e, *remember_parent; int ret; /* Do the removal */ if (NULL == (itr->parent)) { /* element is head of a chain */ itr->h->table[itr->index] = itr->e->next; } else { /* element is mid-chain */ itr->parent->next = itr->e->next; } /* itr->e is now outside the hashtable */ remember_e = itr->e; itr->h->entrycount--; freekey(remember_e->k); /* Advance the iterator, correcting the parent */ remember_parent = itr->parent; ret = hashtable_iterator_advance(itr); if (itr->parent == remember_e) { itr->parent = remember_parent; } ftdm_safe_free(remember_e); return ret; }
FT_DECLARE(ftdm_status_t) ftdm_buffer_create(ftdm_buffer_t **buffer, ftdm_size_t blocksize, ftdm_size_t start_len, ftdm_size_t max_len) { ftdm_buffer_t *new_buffer; new_buffer = ftdm_malloc(sizeof(*new_buffer)); if (new_buffer) { memset(new_buffer, 0, sizeof(*new_buffer)); if (start_len) { new_buffer->data = ftdm_malloc(start_len); if (!new_buffer->data) { ftdm_safe_free(new_buffer); return FTDM_MEMERR; } memset(new_buffer->data, 0, start_len); } new_buffer->max_len = max_len; new_buffer->datalen = start_len; new_buffer->id = buffer_id++; new_buffer->blocksize = blocksize; new_buffer->head = new_buffer->data; *buffer = new_buffer; return FTDM_SUCCESS; } return FTDM_MEMERR; }
create_hashtable(unsigned int minsize, unsigned int (*hashf) (void*), int (*eqf) (void*,void*)) { struct hashtable *h; unsigned int pindex, size = primes[0]; /* Check requested hashtable isn't too large */ if (minsize > (1u << 30)) return NULL; /* Enforce size as prime */ for (pindex=0; pindex < prime_table_length; pindex++) { if (primes[pindex] > minsize) { size = primes[pindex]; break; } } h = (struct hashtable *)ftdm_malloc(sizeof(struct hashtable)); if (NULL == h) return NULL; /*oom*/ h->table = (struct entry **)ftdm_malloc(sizeof(struct entry*) * size); if (NULL == h->table) { ftdm_safe_free(h); return NULL; } /*oom*/ memset(h->table, 0, size * sizeof(struct entry *)); h->tablelength = size; h->primeindex = pindex; h->entrycount = 0; h->hashfn = hashf; h->eqfn = eqf; h->loadlimit = (unsigned int) ceil(size * max_load_factor); return h; }
void dsp_uart_destroy(dsp_uart_handle_t **handle) { if (*handle) { ftdm_safe_free(*handle); *handle = NULL; } }
/*****************************************************************************/ FT_DECLARE(void *) /* returns value associated with key */ hashtable_remove(struct hashtable *h, void *k) { /* TODO: consider compacting the table when the load factor drops enough, * or provide a 'compact' method. */ struct entry *e; struct entry **pE; void *v; unsigned int hashvalue, index; hashvalue = hash(h,k); index = indexFor(h->tablelength,hash(h,k)); pE = &(h->table[index]); e = *pE; while (NULL != e) { /* Check hash value to short circuit heavier comparison */ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) { *pE = e->next; h->entrycount--; v = e->v; if (e->flags & HASHTABLE_FLAG_FREE_KEY) { freekey(e->k); } ftdm_safe_free(e); return v; } pE = &(e->next); e = e->next; } return NULL; }
static int hashtable_expand(struct hashtable *h) { /* Double the size of the table to accomodate more entries */ struct entry **newtable; struct entry *e; struct entry **pE; unsigned int newsize, i, index; /* Check we're not hitting max capacity */ if (h->primeindex == (prime_table_length - 1)) return 0; newsize = primes[++(h->primeindex)]; newtable = (struct entry **)ftdm_malloc(sizeof(struct entry*) * newsize); if (NULL != newtable) { memset(newtable, 0, newsize * sizeof(struct entry *)); /* This algorithm is not 'stable'. ie. it reverses the list * when it transfers entries between the tables */ for (i = 0; i < h->tablelength; i++) { while (NULL != (e = h->table[i])) { h->table[i] = e->next; index = indexFor(newsize,e->h); e->next = newtable[index]; newtable[index] = e; } } ftdm_safe_free(h->table); h->table = newtable; } /* Plan B: realloc instead */ else { newtable = (struct entry **) realloc(h->table, newsize * sizeof(struct entry *)); if (NULL == newtable) { (h->primeindex)--; return 0; } h->table = newtable; memset(newtable[h->tablelength], 0, newsize - h->tablelength); for (i = 0; i < h->tablelength; i++) { for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) { index = indexFor(newsize,e->h); if (index == i) { pE = &(e->next); } else { *pE = e->next; e->next = newtable[index]; newtable[index] = e; } } } } h->tablelength = newsize; h->loadlimit = (unsigned int) ceil(newsize * max_load_factor); return -1; }
static void * FTDM_THREAD_CALLING_CONVENTION thread_launch(void *args) { void *exit_val; ftdm_thread_t *thread = (ftdm_thread_t *)args; exit_val = thread->function(thread, thread->private_data); #ifndef WIN32 pthread_attr_destroy(&thread->attribute); #endif ftdm_safe_free(thread); return exit_val; }
FT_DECLARE(ftdm_status_t) ftdm_conf_node_create(const char *name, ftdm_conf_node_t **node, ftdm_conf_node_t *parent) { ftdm_conf_node_t *newnode; ftdm_conf_node_t *sibling = NULL; ftdm_assert_return(name != NULL, FTDM_FAIL, "null node name"); newnode = ftdm_calloc(1, sizeof(**node)); if (!newnode) { return FTDM_MEMERR; } strncpy(newnode->name, name, sizeof(newnode->name)-1); newnode->name[sizeof(newnode->name)-1] = 0; newnode->parameters = ftdm_calloc(PARAMETERS_CHUNK_SIZE, sizeof(*newnode->parameters)); if (!newnode->parameters) { ftdm_safe_free(newnode); return FTDM_MEMERR; } newnode->t_parameters = PARAMETERS_CHUNK_SIZE; if (parent) { /* store who my parent is */ newnode->parent = parent; /* arrange them in FIFO order (newnode should be last) */ if (!parent->child) { /* we're the first node being added */ parent->child = newnode; } else { if (!parent->last) { /* we're the second node being added */ parent->last = newnode; parent->child->next = newnode; newnode->prev = parent->child; } else { /* we're the third or Nth node to be added */ sibling = parent->last; sibling->next = newnode; parent->last = newnode; newnode->prev = sibling; } } } *node = newnode; return FTDM_SUCCESS; }
FT_DECLARE(ftdm_status_t) ftdm_interrupt_create(ftdm_interrupt_t **ininterrupt, ftdm_socket_t device) { ftdm_interrupt_t *interrupt = NULL; #ifndef WIN32 int fds[2]; #endif ftdm_assert_return(ininterrupt != NULL, FTDM_FAIL, "interrupt double pointer is null!\n"); interrupt = ftdm_calloc(1, sizeof(*interrupt)); if (!interrupt) { ftdm_log(FTDM_LOG_ERROR, "Failed to allocate interrupt memory\n"); return FTDM_FAIL; } interrupt->device = device; #ifdef WIN32 interrupt->event = CreateEvent(NULL, FALSE, FALSE, NULL); if (!interrupt->event) { ftdm_log(FTDM_LOG_ERROR, "Failed to allocate interrupt event\n"); goto failed; } #else if (pipe(fds)) { ftdm_log(FTDM_LOG_ERROR, "Failed to allocate interrupt pipe: %s\n", strerror(errno)); goto failed; } interrupt->readfd = fds[0]; interrupt->writefd = fds[1]; #endif *ininterrupt = interrupt; return FTDM_SUCCESS; failed: if (interrupt) { #ifndef WIN32 if (interrupt->readfd) { close(interrupt->readfd); close(interrupt->writefd); interrupt->readfd = -1; interrupt->writefd = -1; } #endif ftdm_safe_free(interrupt); } return FTDM_FAIL; }
FT_DECLARE(ftdm_status_t) ftdm_mutex_destroy(ftdm_mutex_t **mutex) { ftdm_mutex_t *mp = *mutex; *mutex = NULL; if (!mp) { return FTDM_FAIL; } #ifdef WIN32 DeleteCriticalSection(&mp->mutex); #else if (pthread_mutex_destroy(&mp->mutex)) return FTDM_FAIL; #endif ftdm_safe_free(mp); return FTDM_SUCCESS; }
FT_DECLARE(ftdm_status_t) ftdm_interrupt_destroy(ftdm_interrupt_t **ininterrupt) { ftdm_interrupt_t *interrupt = NULL; ftdm_assert_return(ininterrupt != NULL, FTDM_FAIL, "Interrupt null when destroying!\n"); interrupt = *ininterrupt; #ifdef WIN32 CloseHandle(interrupt->event); #else close(interrupt->readfd); close(interrupt->writefd); interrupt->readfd = -1; interrupt->writefd = -1; #endif ftdm_safe_free(interrupt); *ininterrupt = NULL; return FTDM_SUCCESS; }
FT_DECLARE(ftdm_status_t) ftdm_thread_create_detached_ex(ftdm_thread_function_t func, void *data, ftdm_size_t stack_size) { ftdm_thread_t *thread = NULL; ftdm_status_t status = FTDM_FAIL; if (!func || !(thread = (ftdm_thread_t *)ftdm_malloc(sizeof(ftdm_thread_t)))) { goto done; } thread->private_data = data; thread->function = func; thread->stack_size = stack_size; #if defined(WIN32) thread->handle = (void *)_beginthreadex(NULL, (unsigned)thread->stack_size, (unsigned int (__stdcall *)(void *))thread_launch, thread, 0, NULL); if (!thread->handle) { goto fail; } CloseHandle(thread->handle); status = FTDM_SUCCESS; goto done; #else if (pthread_attr_init(&thread->attribute) != 0) goto fail; if (pthread_attr_setdetachstate(&thread->attribute, PTHREAD_CREATE_DETACHED) != 0) goto failpthread; if (thread->stack_size && pthread_attr_setstacksize(&thread->attribute, thread->stack_size) != 0) goto failpthread; if (pthread_create(&thread->handle, &thread->attribute, thread_launch, thread) != 0) goto failpthread; status = FTDM_SUCCESS; goto done; failpthread: pthread_attr_destroy(&thread->attribute); #endif fail: if (thread) { ftdm_safe_free(thread); } done: return status; }
void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...) { char *data; int ret; va_list ap; va_start(ap, fmt); ret = ftdm_vasprintf(&data, fmt, ap); if (ret == -1) { return; } switch (level) { case SNG_LOGLEVEL_DEBUG: ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s\n", data); break; case SNG_LOGLEVEL_WARN: if ( strncmp(data, "Invalid Q.921/Q.931 frame", 25) ) { ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data); } break; case SNG_LOGLEVEL_INFO: ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data); break; case SNG_LOGLEVEL_STATS: ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data); break; case SNG_LOGLEVEL_ERROR: ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s\n", data); /*ftdm_assert(0, "Got an error from stack");*/ break; case SNG_LOGLEVEL_CRIT: ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s\n", data); /* ftdm_assert(0, "Got an error from stack"); */ break; default: ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data); break; } ftdm_safe_free(data); return; }
// Commnand API entry point static FIO_API_FUNCTION(ftdm_gsm_api) { char *mycmd = NULL, *argv[10] = { 0 }; int argc = 0; int i; ftdm_status_t status = FTDM_FAIL; ftdm_status_t syntax = FTDM_FAIL; if (data) { mycmd = ftdm_strdup(data); argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); } if(argc > 0) { for(i=0;i<sizeof(GSM_COMMANDS)/sizeof(GSM_COMMANDS[0]);i++) { if(strcasecmp(argv[0],GSM_COMMANDS[i].CMD)==0) { if(argc -1 >= GSM_COMMANDS[i].Argc) { syntax = FTDM_SUCCESS; status = GSM_COMMANDS[i].Handler(stream, &argv[1], argc-1); } break; } } } if(FTDM_SUCCESS != syntax) { stream->write_function(stream, "%s", FT_SYNTAX); } else if(FTDM_SUCCESS != status) { stream->write_function(stream, "%s Command Failed\r\n", GSM_COMMANDS[i].CMD); } ftdm_safe_free(mycmd); return FTDM_SUCCESS; }
static FIO_API_FUNCTION(ftdm_pritap_api) { char *mycmd = NULL, *argv[10] = { 0 }; int argc = 0; if (data) { mycmd = ftdm_strdup(data); argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); } if (argc > 2) { if (!strcasecmp(argv[0], "debug")) { ftdm_span_t *span = NULL; if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) { pritap_t *pritap = span->signal_data; if (span->start != ftdm_pritap_start) { stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); goto done; } pri_set_debug(pritap->pri, parse_debug(argv[2])); stream->write_function(stream, "%s: +OK debug set.\n", __FILE__); goto done; } else { stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); goto done; } } } stream->write_function(stream, "%s: -ERR invalid command.\n", __FILE__); done: ftdm_safe_free(mycmd); return FTDM_SUCCESS; }
FT_DECLARE(ftdm_status_t) ftdm_sched_cancel_timer(ftdm_sched_t *sched, ftdm_timer_id_t timerid) { ftdm_status_t status = FTDM_FAIL; ftdm_timer_t *timer; ftdm_assert_return(sched != NULL, FTDM_EINVAL, "sched is null!\n"); if (!timerid) { return FTDM_SUCCESS; } ftdm_mutex_lock(sched->mutex); /* look for the timer and destroy it */ for (timer = sched->timers; timer; timer = timer->next) { if (timer->id == timerid) { if (timer == sched->timers) { /* it's the head timer, put a new head */ sched->timers = timer->next; } if (timer->prev) { timer->prev->next = timer->next; } if (timer->next) { timer->next->prev = timer->prev; } ftdm_safe_free(timer); status = FTDM_SUCCESS; break; } } ftdm_mutex_unlock(sched->mutex); return status; }
FT_DECLARE(ftdm_status_t) ftdm_sched_create(ftdm_sched_t **sched, const char *name) { ftdm_sched_t *newsched = NULL; ftdm_assert_return(sched != NULL, FTDM_EINVAL, "invalid pointer\n"); ftdm_assert_return(name != NULL, FTDM_EINVAL, "invalid sched name\n"); *sched = NULL; newsched = ftdm_calloc(1, sizeof(*newsched)); if (!newsched) { return FTDM_MEMERR; } if (ftdm_mutex_create(&newsched->mutex) != FTDM_SUCCESS) { goto failed; } ftdm_set_string(newsched->name, name); newsched->currid = 1; *sched = newsched; ftdm_log(FTDM_LOG_DEBUG, "Created schedule %s\n", name); return FTDM_SUCCESS; failed: ftdm_log(FTDM_LOG_CRIT, "Failed to create schedule\n"); if (newsched) { if (newsched->mutex) { ftdm_mutex_destroy(&newsched->mutex); } ftdm_safe_free(newsched); } return FTDM_FAIL; }
/** * \brief Initialises an freetdm Wanpipe span from a configuration string * \param span FreeTDM span * \param str Configuration string * \param type FreeTDM span type * \param name FreeTDM span name * \param number FreeTDM span number * \return Success or failure */ static FIO_CONFIGURE_SPAN_FUNCTION(wanpipe_configure_span) { int items, i; char *mydata, *item_list[10]; char *sp, *ch, *mx; unsigned char cas_bits = 0; int channo; int spanno; int top = 0; unsigned configured = 0; assert(str != NULL); mydata = ftdm_strdup(str); assert(mydata != NULL); items = ftdm_separate_string(mydata, ',', item_list, (sizeof(item_list) / sizeof(item_list[0]))); for(i = 0; i < items; i++) { sp = item_list[i]; if ((ch = strchr(sp, ':'))) { *ch++ = '\0'; } if (!(sp && ch)) { ftdm_log(FTDM_LOG_ERROR, "No valid wanpipe span and channel was specified\n"); continue; } channo = atoi(ch); spanno = atoi(sp); if (channo < 0) { ftdm_log(FTDM_LOG_ERROR, "Invalid channel number %d\n", channo); continue; } if (spanno < 0) { ftdm_log(FTDM_LOG_ERROR, "Invalid span number %d\n", channo); continue; } if ((mx = strchr(ch, '-'))) { mx++; top = atoi(mx) + 1; } else { top = channo + 1; } if (top < 0) { ftdm_log(FTDM_LOG_ERROR, "Invalid range number %d\n", top); continue; } if (FTDM_CHAN_TYPE_CAS == type && ftdm_config_get_cas_bits(ch, &cas_bits)) { ftdm_log(FTDM_LOG_ERROR, "Failed to get CAS bits in CAS channel\n"); continue; } configured += wp_open_range(span, spanno, channo, top, type, name, number, cas_bits); } ftdm_safe_free(mydata); return configured; }
FT_DECLARE(ftdm_status_t) ftdm_sched_run(ftdm_sched_t *sched) { ftdm_status_t status = FTDM_FAIL; ftdm_timer_t *runtimer; ftdm_timer_t *timer; ftdm_sched_callback_t callback; int ms = 0; int rc = -1; void *data; struct timeval now; ftdm_assert_return(sched != NULL, FTDM_EINVAL, "sched is null!\n"); tryagain: ftdm_mutex_lock(sched->mutex); rc = gettimeofday(&now, NULL); if (rc == -1) { ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve time of day\n"); goto done; } timer = sched->timers; while (timer) { runtimer = timer; timer = runtimer->next; ms = ((runtimer->time.tv_sec - now.tv_sec) * 1000) + ((runtimer->time.tv_usec - now.tv_usec) / 1000); if (ms <= 0) { if (runtimer == sched->timers) { sched->timers = runtimer->next; if (sched->timers) { sched->timers->prev = NULL; } } callback = runtimer->callback; data = runtimer->usrdata; if (runtimer->next) { runtimer->next->prev = runtimer->prev; } if (runtimer->prev) { runtimer->prev->next = runtimer->next; } runtimer->id = 0; ftdm_safe_free(runtimer); /* avoid deadlocks by releasing the sched lock before triggering callbacks */ ftdm_mutex_unlock(sched->mutex); callback(data); /* after calling a callback we must start the scanning again since the * callback or some other thread may have added or cancelled timers to * the linked list */ goto tryagain; } } status = FTDM_SUCCESS; done: ftdm_mutex_unlock(sched->mutex); #ifdef __WINDOWS__ UNREFERENCED_PARAMETER(sched); #endif return status; }
static ftdm_status_t parse_trunkgroup(const char *_trunkgroup) { int i; char *p, *name, *dchan_span, *backup_span, *trunkgroup; uint8_t num_spans = 0; ftdm_status_t ret = FTDM_SUCCESS; trunkgroup = ftdm_strdup(_trunkgroup); p = name = dchan_span = backup_span = NULL; /* format: name, num_chans, dchan_span, [backup_span] */ i = 0; for (p = strtok(trunkgroup, ","); p; p = strtok(NULL, ",")) { while (*p == ' ') { p++; } switch(i++) { case 0: name = ftdm_strdup(p); break; case 1: num_spans = atoi(p); break; case 2: dchan_span = ftdm_strdup(p); break; case 3: backup_span = ftdm_strdup(p); } } if (!name || !dchan_span || num_spans <= 0) { ftdm_log(FTDM_LOG_ERROR, "Invalid parameters for trunkgroup:%s\n", _trunkgroup); ret = FTDM_FAIL; goto done; } for (i = 0; i < g_sngisdn_data.num_nfas; i++) { if (!ftdm_strlen_zero(g_sngisdn_data.nfass[i].name) && !strcasecmp(g_sngisdn_data.nfass[i].name, name)) { /* We already configured this trunkgroup */ goto done; } } /* Trunk group was not found, need to configure it */ strncpy(g_sngisdn_data.nfass[i].name, name, sizeof(g_sngisdn_data.nfass[i].name)); g_sngisdn_data.nfass[i].num_spans = num_spans; strncpy(g_sngisdn_data.nfass[i].dchan_span_name, dchan_span, sizeof(g_sngisdn_data.nfass[i].dchan_span_name)); if (backup_span) { strncpy(g_sngisdn_data.nfass[i].backup_span_name, backup_span, sizeof(g_sngisdn_data.nfass[i].backup_span_name)); } g_sngisdn_data.num_nfas++; done: ftdm_safe_free(trunkgroup); ftdm_safe_free(name); ftdm_safe_free(dchan_span); ftdm_safe_free(backup_span); return ret; }
static ftdm_status_t parse_spanmap(const char *_spanmap, ftdm_span_t *span) { int i; char *p, *name, *spanmap; uint8_t logical_span_id = 0; ftdm_status_t ret = FTDM_SUCCESS; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; spanmap = ftdm_strdup(_spanmap); p = name = NULL; i = 0; for (p = strtok(spanmap, ","); p; p = strtok(NULL, ",")) { while (*p == ' ') { p++; } switch(i++) { case 0: name = ftdm_strdup(p); break; case 1: logical_span_id = atoi(p); break; } } if (!name) { ftdm_log(FTDM_LOG_ERROR, "Invalid spanmap syntax %s\n", _spanmap); ret = FTDM_FAIL; goto done; } for (i = 0; i < g_sngisdn_data.num_nfas; i++) { if (!ftdm_strlen_zero(g_sngisdn_data.nfass[i].name) && !strcasecmp(g_sngisdn_data.nfass[i].name, name)) { signal_data->nfas.trunk = &g_sngisdn_data.nfass[i]; break; } } if (!signal_data->nfas.trunk) { ftdm_log(FTDM_LOG_ERROR, "Could not find trunkgroup with name %s\n", name); ret = FTDM_FAIL; goto done; } if (signal_data->nfas.trunk->spans[logical_span_id]) { ftdm_log(FTDM_LOG_ERROR, "trunkgroup:%s already had a span with logical span id:%d\n", name, logical_span_id); } else { signal_data->nfas.trunk->spans[logical_span_id] = signal_data; signal_data->nfas.interface_id = logical_span_id; } if (!strcasecmp(signal_data->ftdm_span->name, signal_data->nfas.trunk->dchan_span_name)) { signal_data->nfas.sigchan = SNGISDN_NFAS_DCHAN_PRIMARY; signal_data->nfas.trunk->dchan = signal_data; } if (!strcasecmp(signal_data->ftdm_span->name, signal_data->nfas.trunk->backup_span_name)) { signal_data->nfas.sigchan = SNGISDN_NFAS_DCHAN_BACKUP; signal_data->nfas.trunk->backup = signal_data; } done: ftdm_safe_free(spanmap); ftdm_safe_free(name); return ret; }