Merge git@git.freeswitch.org:freeswitch

This commit is contained in:
Steve Underwood 2010-05-12 23:24:12 +08:00
commit d4bb8b019e
19 changed files with 705 additions and 12699 deletions

View File

@ -71,18 +71,28 @@
<macro name="voicemail_menu">
<input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
<match>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
<!-- To listen to new messages -->
<action function="play-file" data="voicemail/vm-listen_new.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
<action function="execute" data="sleep(100)"/>
<!-- To listen to saved messages -->
<action function="play-file" data="voicemail/vm-listen_saved.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$3" method="pronounced" type="name_spelled"/>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
<action function="execute" data="sleep(100)"/>
<!-- For advanced options -->
<action function="play-file" data="voicemail/vm-advanced.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$4" method="pronounced" type="name_phonetic"/>
<action function="say" data="$3" method="pronounced" type="name_spelled"/>
<action function="execute" data="sleep(100)"/>
<!-- To exit -->
<action function="play-file" data="voicemail/vm-to_exit.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$4" method="pronounced" type="name_phonetic"/>
</match>
</input>
</macro>
@ -90,21 +100,34 @@
<macro name="voicemail_config_menu">
<input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
<match>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
<!-- To record a greeting -->
<action function="play-file" data="voicemail/vm-to_record_greeting.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
<action function="execute" data="sleep(100)"/>
<!-- To choose greeting -->
<action function="play-file" data="voicemail/vm-choose_greeting.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$3" method="pronounced" type="name_spelled"/>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
<action function="execute" data="sleep(100)"/>
<!-- To record your name -->
<action function="play-file" data="voicemail/vm-record_name2.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$4" method="pronounced" type="name_spelled"/>
<action function="say" data="$3" method="pronounced" type="name_spelled"/>
<action function="execute" data="sleep(100)"/>
<!-- To change password -->
<action function="play-file" data="voicemail/vm-change_password.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$5" method="pronounced" type="name_spelled"/>
<action function="say" data="$4" method="pronounced" type="name_spelled"/>
<action function="execute" data="sleep(100)"/>
<!-- To return to main menu -->
<action function="play-file" data="voicemail/vm-main_menu.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$5" method="pronounced" type="name_spelled"/>
</match>
</input>
</macro>

View File

@ -0,0 +1,10 @@
CC=gcc
CFLAGS=-Wall -I/usr/local/freeswitch/include
LDFLAGS=-L/usr/local/freeswitch/lib -lfreetdm
ftdmstart: ftdmstart.o
clean:
rm -rf ftdmstart.o

View File

@ -0,0 +1,476 @@
/*
* Copyright (c) 2010, Sangoma Technologies
* Moises Silva <moy@sangoma.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Sample program for the boost signaling absraction.
* Usage: testboostalone <spanno-1> <spanno-2> ... -d [number-to-dial-if-any]
* compile this program linking to the freetdm library (ie -lfreetdm)
**/
#ifndef __linux__
#define _CRT_SECURE_NO_WARNINGS 1
#endif
#include <signal.h>
#include "freetdm.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* arbitrary limit for max calls in this sample program */
#define MAX_CALLS 255
/* some timers (in seconds) to fake responses in incoming calls */
#define PROGRESS_TIMER 1
#define ANSWER_TIMER 5
#define HANGUP_TIMER 15
/* simple variable used to stop the application */
static int app_running = 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 void interrupt_requested(int signal)
{
app_running = 0;
}
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);
}
/* hangup the call */
static void send_hangup(ftdm_channel_t *channel)
{
int spanid = ftdm_channel_get_span_id(channel);
int chanid = ftdm_channel_get_id(channel);
ftdm_log(FTDM_LOG_NOTICE, "-- Requesting hangup in channel %d:%d\n", spanid, chanid);
ftdm_channel_call_hangup(channel);
}
/* send answer for an incoming call */
static void send_answer(ftdm_channel_t *channel)
{
/* we move the channel signaling state machine to UP (answered) */
int spanid = ftdm_channel_get_span_id(channel);
int chanid = ftdm_channel_get_id(channel);
ftdm_log(FTDM_LOG_NOTICE, "-- Requesting answer in channel %d:%d\n", spanid, chanid);
ftdm_channel_call_answer(channel);
schedule_timer(channel, HANGUP_TIMER, send_hangup);
}
/* send progress for an incoming */
static void send_progress(ftdm_channel_t *channel)
{
/* we move the channel signaling state machine to UP (answered) */
int spanid = ftdm_channel_get_span_id(channel);
int chanid = ftdm_channel_get_id(channel);
ftdm_log(FTDM_LOG_NOTICE, "-- Requesting progress\n", spanid, chanid);
ftdm_channel_call_indicate(channel, FTDM_CHANNEL_INDICATE_PROGRESS);
schedule_timer(channel, ANSWER_TIMER, send_answer);
}
/* This function will be called in an undetermined signaling thread, you must not do
* any blocking operations here or the signaling stack may delay other call event processing
* The arguments for this function are defined in FIO_SIGNAL_CB_FUNCTION prototype, I just
* name them here for your convenience:
* ftdm_sigmsg_t *sigmsg
* - The sigmsg structure contains the ftdm_channel structure that represents the channel where
* the event occurred and the event_id of the signaling event that just occurred.
* */
static FIO_SIGNAL_CB_FUNCTION(on_signaling_event)
{
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_progress);
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\n", sigmsg->span_id, sigmsg->chan_id);
/* 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 */
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 any timer for this channel */
release_timers(sigmsg->channel);
/* acknowledge the hangup */
ftdm_channel_call_hangup(sigmsg->channel);
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;
}
static void place_call(const ftdm_span_t *span, const char *number)
{
ftdm_channel_t *ftdmchan = NULL;
ftdm_caller_data_t caller_data = {{ 0 }};
ftdm_status_t status = FTDM_FAIL;
/* set destiny number */
ftdm_set_string(caller_data.dnis.digits, number);
/* set callerid */
ftdm_set_string(caller_data.cid_name, "testsangomaboost");
ftdm_set_string(caller_data.cid_num.digits, "1234");
/* request to search for an outgoing channel top down with the given caller data.
* it is also an option to use ftdm_channel_open_by_group to let freetdm hunt
* an available channel in a given group instead of per span
* */
status = ftdm_channel_open_by_span(ftdm_span_get_id(span), FTDM_TOP_DOWN, &caller_data, &ftdmchan);
if (status != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Failed to originate call\n");
return;
}
g_outgoing_channel = ftdmchan;
/* set the caller data for the outgoing channel */
ftdm_channel_set_caller_data(ftdmchan, &caller_data);
status = ftdm_channel_call_place(ftdmchan);
if (status != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Failed to originate call\n");
return;
}
/* this is required to initialize the outgoing channel */
ftdm_channel_init(ftdmchan);
}
#define ARRLEN(arr) (sizeof(arr)/sizeof(arr[0]))
int main(int argc, char *argv[])
{
/* span names can be any null-terminated string, does not need to be a wanpipe port */
int span_numbers[32];
char span_names[ARRLEN(span_numbers)][ARRLEN(span_numbers)];
const char *spanname = NULL;
char wpchans[25];
unsigned configured = 0;
int i, spanno;
int numspans = 0;
ftdm_status_t status;
ftdm_span_t *span_list[ARRLEN(span_numbers)];
ftdm_span_t *span;
ftdm_channel_config_t chan_config;
ftdm_conf_parameter_t parameters[20];
char *todial = NULL;
int32_t ticks = 0;
/* register a handler to shutdown things properly */
#ifdef _WIN64
// still trying to figure this one out otherwise triggers error
if (signal(SIGINT, interrupt_requested) < 0) {
#else
if (signal(SIGINT, interrupt_requested) == SIG_ERR) {
#endif
fprintf(stderr, "Could not set the SIGINT signal handler: %s\n", strerror(errno));
exit(-1);
}
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-' && argv[i][1] == 'd') {
i++;
if (i >= argc) {
fprintf(stderr, "Error, -d specified but no number to dial!\n");
exit(1);
}
todial = argv[i];
if (!strlen(todial)) {
todial = NULL;
}
printf("Number to dial: %s\n", todial);
continue;
}
spanno = atoi(argv[i]);
span_numbers[numspans] = spanno;
snprintf(span_names[numspans], sizeof(span_names[numspans]), "wanpipe%d", spanno);
numspans++;
}
if (!numspans) {
fprintf(stderr, "please specify a at least 1 wanpipe port number\n");
exit(-1);
}
/* clear any outstanding timers */
memset(&g_timers, 0, sizeof(g_timers));
/* set the logging level to use */
ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG);
/* this is optional.
* cpu monitor is a default feature in freetdm that launches 1 thread
* to monitor system-wide CPU usage. If it goes above a predefined threshold
* it will stop accepting calls to try to protect the quality of current calls */
ftdm_cpu_monitor_disable();
/* Initialize the FTDM library */
if (ftdm_global_init() != FTDM_SUCCESS) {
fprintf(stderr, "Error loading FreeTDM\n");
exit(-1);
}
/* create the schedule mutex */
ftdm_mutex_create(&g_schedule_mutex);
/* now we can start creating spans */
memset(&chan_config, 0, sizeof(chan_config));
strncpy(chan_config.group_name, "mygroup", sizeof(chan_config.group_name)-1);
chan_config.group_name[sizeof(chan_config.group_name)-1] = 0;
for (i = 0; i < numspans; i++) {
spanname = span_names[i];
/* "wanpipe" is the special I/O identifier for Sangoma devices */
ftdm_log(FTDM_LOG_NOTICE, "Creating span %s\n", spanname);
status = ftdm_span_create("wanpipe", spanname, &span_list[i]);
if (status != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to create span %s\n", spanname);
goto done;
}
span = span_list[i];
spanno = span_numbers[i];
/* set the trunk type for the span */
ftdm_span_set_trunk_type(span_list[i], FTDM_TRUNK_T1);
/* configure B channels (syntax for wanpipe channels is span:low_chan-high_chan) */
chan_config.type = FTDM_CHAN_TYPE_B;
snprintf(wpchans, sizeof(wpchans), "%d:1-23", spanno);
ftdm_configure_span_channels(span, wpchans, &chan_config, &configured);
ftdm_log(FTDM_LOG_NOTICE, "registered %d b channels\n", configured);
}
/* At this point FreeTDM is ready to be used, the spans defined in freetdm.conf have the basic I/O board configuration
* but no telephony signaling configuration at all. */
ftdm_log(FTDM_LOG_NOTICE, "FreeTDM loaded ...\n");
/* now we can start configuring signaling for the previously created spans */
for (i = 0; i < numspans; i++) {
spanname = span_names[i];
/* Retrieve a span by name (as specified in ftdm_span_create()) */
if (ftdm_span_find_by_name(spanname, &span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span %s\n", ftdm_span_get_name(span));
goto done;
}
/* prepare the configuration parameters that will be sent down to the signaling stack, the array of paramters must be terminated by an
* array element with a null .var member */
/* for sangoma_boost signaling (abstraction signaling used by Sangoma for PRI, BRI and SS7) the first parameter you must send
* is sigmod, which must be either sangoma_prid, if you have the PRI stack available, or sangoma_brid for the BRI stack */
parameters[0].var = "sigmod";
parameters[0].val = "sangoma_prid";
/* following parameters are signaling stack specific, this ones are for PRI */
parameters[1].var = "switchtype";
parameters[1].val = "national";
parameters[2].var = "signalling";
parameters[2].val = "pri_cpe";
/*
* parameters[3].var = "nfas_primary";
* parameters[3].val = "4"; //span number
*
* parameters[4].var = "nfas_secondary";
* parameters[4].val = "2"; //span number
*
* parameters[5].var = "nfas_group";
* parameters[5].val = "1";
* */
/* the last parameter .var member must be NULL! */
parameters[3].var = NULL;
/* send the configuration values down to the stack */
if (ftdm_configure_span_signaling(span, "sangoma_boost", on_signaling_event, parameters) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error configuring sangoma_boost signaling abstraction in span %s\n", ftdm_span_get_name(span));
goto done;
}
}
/* configuration succeeded, we can proceed now to start each span
* This step will launch at least 1 background (may be more, depending on the signaling stack used)
* to handle *ALL* signaling events for this span, your on_signaling_event callback will be called always
* in one of those infraestructure threads and you MUST NOT block in that handler to avoid delays and errors
* in the signaling processing for any call.
* */
for (i = 0; i < numspans; i++) {
spanname = span_names[i];
/* Retrieve a span by name (as specified in ftdm_span_create()) */
if (ftdm_span_find_by_name(spanname, &span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span %s\n", ftdm_span_get_name(span));
goto done;
}
if (ftdm_span_start(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Failing starting signaling on span %s\n", ftdm_span_get_name(span));
goto done;
}
}
app_running = 1;
/* Retrieve the first created span to place the call (if dialing was specified) */
if (ftdm_span_find(1, &span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span 1\n");
goto done;
}
/* The application thread can go on and do anything else, like waiting for a shutdown signal */
while(ftdm_running() && app_running) {
ftdm_sleep(1000);
run_timers();
ticks++;
if (!(ticks % 10) && todial && !g_outgoing_channel) {
ftdm_log(FTDM_LOG_NOTICE, "Originating call to number %s\n", todial);
place_call(span, todial);
}
}
done:
ftdm_log(FTDM_LOG_NOTICE, "Shutting down FreeTDM ...\n");
ftdm_mutex_destroy(&g_schedule_mutex);
/* whenever you're done, this function will shutdown the signaling threads in any span that was started */
ftdm_global_destroy();
printf("Terminated!\n");
sleep(2);
exit(0);
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
*/

View File

@ -27,11 +27,12 @@
#include <stdio.h>
FT_DECLARE(void) ftdm_dso_destroy(ftdm_dso_lib_t *lib) {
FT_DECLARE(ftdm_status_t) ftdm_dso_destroy(ftdm_dso_lib_t *lib) {
if (lib && *lib) {
FreeLibrary(*lib);
*lib = NULL;
}
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_dso_lib_t) ftdm_dso_open(const char *path, char **err) {
@ -78,11 +79,20 @@ FT_DECLARE(void*) ftdm_dso_func_sym(ftdm_dso_lib_t lib, const char *sym, char **
#include <dlfcn.h>
FT_DECLARE(void) ftdm_dso_destroy(ftdm_dso_lib_t *lib) {
FT_DECLARE(ftdm_status_t) ftdm_dso_destroy(ftdm_dso_lib_t *lib) {
int rc;
if (lib && *lib) {
dlclose(*lib);
rc = dlclose(*lib);
if (rc) {
ftdm_log(FTDM_LOG_ERROR, "Failed to close lib %p: %s\n", *lib, dlerror());
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "lib %p was closed with success\n", *lib);
*lib = NULL;
return FTDM_SUCCESS;
}
ftdm_log(FTDM_LOG_ERROR, "Invalid pointer provided to ftdm_dso_destroy\n");
return FTDM_FAIL;
}
FT_DECLARE(ftdm_dso_lib_t) ftdm_dso_open(const char *path, char **err) {
@ -93,7 +103,7 @@ FT_DECLARE(ftdm_dso_lib_t) ftdm_dso_open(const char *path, char **err) {
return lib;
}
FT_DECLARE(void*) ftdm_dso_func_sym(ftdm_dso_lib_t lib, const char *sym, char **err) {
FT_DECLARE(void *) ftdm_dso_func_sym(ftdm_dso_lib_t lib, const char *sym, char **err) {
void *func = dlsym(lib, sym);
if (!func) {
*err = ftdm_strdup(dlerror());

View File

@ -522,17 +522,41 @@ FT_DECLARE(ftdm_status_t) ftdm_span_stop(ftdm_span_t *span)
return FTDM_FAIL;
}
FT_DECLARE(ftdm_status_t) ftdm_span_create(ftdm_io_interface_t *fio, ftdm_span_t **span, const char *name)
FT_DECLARE(ftdm_status_t) ftdm_span_create(const char *iotype, const char *name, ftdm_span_t **span)
{
ftdm_span_t *new_span = NULL;
ftdm_io_interface_t *fio = NULL;
ftdm_status_t status = FTDM_FAIL;
char buf[128] = "";
ftdm_assert(fio != NULL, "No IO provided\n");
ftdm_assert_return(iotype != NULL, FTDM_FAIL, "No IO type provided\n");
ftdm_assert_return(name != NULL, FTDM_FAIL, "No span name provided\n");
*span = NULL;
ftdm_mutex_lock(globals.mutex);
if (!(fio = (ftdm_io_interface_t *) hashtable_search(globals.interface_hash, (void *)iotype))) {
ftdm_load_module_assume(iotype);
if ((fio = (ftdm_io_interface_t *) hashtable_search(globals.interface_hash, (void *)iotype))) {
ftdm_log(FTDM_LOG_INFO, "Auto-loaded I/O module '%s'\n", iotype);
}
}
ftdm_mutex_unlock(globals.mutex);
if (!fio) {
ftdm_log(FTDM_LOG_CRIT, "failure creating span, no such I/O type '%s'\n", iotype);
return FTDM_FAIL;
}
if (!fio->configure_span) {
ftdm_log(FTDM_LOG_CRIT, "failure creating span, no configure_span method for I/O type '%s'\n", iotype);
return FTDM_FAIL;
}
ftdm_mutex_lock(globals.mutex);
if (globals.span_index < FTDM_MAX_SPANS_INTERFACE) {
new_span = ftdm_calloc(sizeof(*new_span), 1);
ftdm_assert(new_span, "allocating span failed\n");
status = ftdm_mutex_create(&new_span->mutex);
@ -556,11 +580,11 @@ FT_DECLARE(ftdm_status_t) ftdm_span_create(ftdm_io_interface_t *fio, ftdm_span_t
ftdm_mutex_unlock(globals.span_mutex);
if (!name) {
char buf[128] = "";
snprintf(buf, sizeof(buf), "span%d", new_span->span_id);
name = buf;
}
new_span->name = ftdm_strdup(name);
new_span->type = ftdm_strdup(iotype);
ftdm_span_add(new_span);
*span = new_span;
status = FTDM_SUCCESS;
@ -1657,6 +1681,16 @@ FT_DECLARE(const char *) ftdm_channel_get_span_name(const ftdm_channel_t *ftdmch
return ftdmchan->span->name;
}
FT_DECLARE(void) ftdm_span_set_trunk_type(ftdm_span_t *span, ftdm_trunk_type_t type)
{
span->trunk_type = type;
}
FT_DECLARE(ftdm_trunk_type_t) ftdm_span_get_trunk_type(const ftdm_span_t *span)
{
return span->trunk_type;
}
FT_DECLARE(uint32_t) ftdm_span_get_id(const ftdm_span_t *span)
{
return span->span_id;
@ -3227,7 +3261,15 @@ static ftdm_status_t ftdm_set_channels_alarms(ftdm_span_t *span, int currindex)
FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const char* str, ftdm_channel_config_t *chan_config, unsigned *configured)
{
int currindex = span->chan_count;
int currindex;
ftdm_assert_return(span != NULL, FTDM_EINVAL, "span is null\n");
ftdm_assert_return(chan_config != NULL, FTDM_EINVAL, "config is null\n");
ftdm_assert_return(configured != NULL, FTDM_EINVAL, "configured pointer is null\n");
ftdm_assert_return(span->fio != NULL, FTDM_EINVAL, "span with no I/O configured\n");
ftdm_assert_return(span->fio->configure_span != NULL, FTDM_NOTIMPL, "span I/O with no channel configuration implemented\n");
currindex = span->chan_count;
*configured = 0;
*configured = span->fio->configure_span(span, str, chan_config->type, chan_config->name, chan_config->number);
if (!*configured) {
@ -3235,18 +3277,24 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const
return FTDM_FAIL;
}
if (ftdm_group_add_channels(span, currindex, chan_config->group_name) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%d:Failed to add channels to group %s\n", span->span_id, chan_config->group_name);
return FTDM_FAIL;
}
if (ftdm_set_channels_alarms(span, currindex) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%d:Failed to set channel alarms\n", span->span_id);
return FTDM_FAIL;
if (chan_config->group_name[0]) {
if (ftdm_group_add_channels(span, currindex, chan_config->group_name) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%d:Failed to add channels to group %s\n", span->span_id, chan_config->group_name);
return FTDM_FAIL;
}
}
if (ftdm_set_channels_gains(span, currindex, chan_config->rxgain, chan_config->txgain) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%d:Failed to set channel gains\n", span->span_id);
return FTDM_FAIL;
}
if (ftdm_set_channels_alarms(span, currindex) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%d:Failed to set channel alarms\n", span->span_id);
return FTDM_FAIL;
}
return FTDM_SUCCESS;
}
@ -3260,7 +3308,6 @@ static ftdm_status_t load_config(void)
int intparam = 0;
ftdm_span_t *span = NULL;
unsigned configured = 0, d = 0;
ftdm_io_interface_t *fio = NULL;
ftdm_analog_start_type_t tmp;
ftdm_size_t len = 0;
ftdm_channel_config_t chan_config;
@ -3271,7 +3318,7 @@ static ftdm_status_t load_config(void)
if (!ftdm_config_open_file(&cfg, cfg_name)) {
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "Reading FreeTDM configuration file\n");
while (ftdm_config_next_pair(&cfg, &var, &val)) {
if (*cfg.category == '#') {
if (cfg.catno != catno) {
@ -3300,33 +3347,9 @@ static ftdm_status_t load_config(void)
*name++ = '\0';
}
ftdm_mutex_lock(globals.mutex);
if (!(fio = (ftdm_io_interface_t *) hashtable_search(globals.interface_hash, type))) {
ftdm_load_module_assume(type);
if ((fio = (ftdm_io_interface_t *) hashtable_search(globals.interface_hash, type))) {
ftdm_log(FTDM_LOG_INFO, "auto-loaded '%s'\n", type);
}
}
ftdm_mutex_unlock(globals.mutex);
if (!fio) {
ftdm_log(FTDM_LOG_CRIT, "failure creating span, no such type '%s'\n", type);
span = NULL;
continue;
}
if (!fio->configure_span) {
ftdm_log(FTDM_LOG_CRIT, "failure creating span, no configure_span method for '%s'\n", type);
span = NULL;
continue;
}
if (ftdm_span_create(fio, &span, name) == FTDM_SUCCESS) {
span->type = ftdm_strdup(type);
d = 0;
if (ftdm_span_create(type, name, &span) == FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_DEBUG, "created span %d (%s) of type %s\n", span->span_id, span->name, type);
d = 0;
} else {
ftdm_log(FTDM_LOG_CRIT, "failure creating span of type %s\n", type);
span = NULL;
@ -3341,8 +3364,9 @@ static ftdm_status_t load_config(void)
ftdm_log(FTDM_LOG_DEBUG, "span %d [%s]=[%s]\n", span->span_id, var, val);
if (!strcasecmp(var, "trunk_type")) {
span->trunk_type = ftdm_str2ftdm_trunk_type(val);
ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s'\n", ftdm_trunk_type2str(span->trunk_type));
ftdm_trunk_type_t trtype = ftdm_str2ftdm_trunk_type(val);
ftdm_span_set_trunk_type(span, trtype);
ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s'\n", ftdm_trunk_type2str(trtype));
} else if (!strcasecmp(var, "name")) {
if (!strcasecmp(val, "undef")) {
chan_config.name[0] = '\0';
@ -3371,7 +3395,7 @@ static ftdm_status_t load_config(void)
ftdm_analog_start_type2str(span->start_type));
}
if (span->trunk_type == FTDM_TRUNK_FXO) {
unsigned chans_configured = 0;
unsigned chans_configured = 0;
chan_config.type = FTDM_CHAN_TYPE_FXO;
if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) {
configured += chans_configured;

View File

@ -40,7 +40,8 @@
typedef enum {
FTDM_SANGOMA_BOOST_RUNNING = (1 << 0),
FTDM_SANGOMA_BOOST_RESTARTING = (1 << 1)
FTDM_SANGOMA_BOOST_RESTARTING = (1 << 1),
FTDM_SANGOMA_BOOST_EVENTS_RUNNING = (1 << 2),
} ftdm_sangoma_boost_flag_t;
typedef struct ftdm_sangoma_boost_data {

View File

@ -1721,12 +1721,12 @@ static __inline__ ftdm_status_t check_events(ftdm_span_t *span, int ms_timeout)
*/
static void *ftdm_sangoma_events_run(ftdm_thread_t *me, void *obj)
{
ftdm_span_t *span = (ftdm_span_t *) obj;
ftdm_span_t *span = (ftdm_span_t *) obj;
ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
unsigned errs = 0;
while (ftdm_test_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING) && ftdm_running()) {
if (check_events(span,100) != FTDM_SUCCESS) {
while (ftdm_test_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_EVENTS_RUNNING) && ftdm_running()) {
if (check_events(span, 100) != FTDM_SUCCESS) {
if (errs++ > 50) {
ftdm_log(FTDM_LOG_ERROR, "Too many event errors, quitting sangoma events thread\n");
return NULL;
@ -1734,6 +1734,10 @@ static void *ftdm_sangoma_events_run(ftdm_thread_t *me, void *obj)
}
}
ftdm_log(FTDM_LOG_DEBUG, "Sangoma Boost Events thread ended.\n");
ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_EVENTS_RUNNING);
return NULL;
}
@ -2138,12 +2142,13 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_boost_destroy)
const void *key = NULL;
void *val = NULL;
ftdm_dso_lib_t lib;
ftdm_log(FTDM_LOG_DEBUG, "Destroying sangoma boost module\n");
for (i = hashtable_first(g_boost_modules_hash); i; i = hashtable_next(i)) {
hashtable_this(i, &key, NULL, &val);
if (key && val) {
sigmod = val;
lib = sigmod->pvt;
ftdm_log(FTDM_LOG_DEBUG, "destroying sigmod %s\n", sigmod->name);
ftdm_dso_destroy(&lib);
}
}
@ -2159,18 +2164,23 @@ static ftdm_status_t ftdm_sangoma_boost_start(ftdm_span_t *span)
int err;
ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
ftdm_set_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING);
err=ftdm_thread_create_detached(ftdm_sangoma_boost_run, span);
err = ftdm_thread_create_detached(ftdm_sangoma_boost_run, span);
if (err) {
ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING);
return err;
}
// launch the events thread to handle HW DTMF and possibly
// other events in the future
err=ftdm_thread_create_detached(ftdm_sangoma_events_run, span);
ftdm_set_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_EVENTS_RUNNING);
err = ftdm_thread_create_detached(ftdm_sangoma_events_run, span);
if (err) {
ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_EVENTS_RUNNING);
ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING);
}
return err;
}
@ -2179,12 +2189,16 @@ static ftdm_status_t ftdm_sangoma_boost_stop(ftdm_span_t *span)
int cnt = 50;
ftdm_status_t status = FTDM_SUCCESS;
ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
if (sangoma_boost_data->sigmod) {
/* I think stopping the span before destroying the queue makes sense
otherwise may be boost events would still arrive when the queue is already destroyed! */
status = sangoma_boost_data->sigmod->stop_span(span);
if (status != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to stop span %s boost signaling\n", span->name);
return FTDM_FAIL;
}
ftdm_queue_enqueue(sangoma_boost_data->boost_queue, NULL);
return status;
}
while (ftdm_test_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING) && cnt-- > 0) {
@ -2197,6 +2211,17 @@ static ftdm_status_t ftdm_sangoma_boost_stop(ftdm_span_t *span)
return FTDM_FAIL;
}
cnt = 50;
while (ftdm_test_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_EVENTS_RUNNING) && cnt-- > 0) {
ftdm_log(FTDM_LOG_DEBUG, "Waiting for boost events thread\n");
ftdm_sleep(100);
}
if (!cnt) {
ftdm_log(FTDM_LOG_CRIT, "it seems boost events thread in span %s may be stuck, we may segfault :-(\n", span->name);
return FTDM_FAIL;
}
if (sangoma_boost_data->sigmod) {
ftdm_queue_destroy(&sangoma_boost_data->boost_queue);
}

View File

@ -67,7 +67,8 @@ typedef enum {
FTDM_MEMERR, /*!< Memory error, most likely allocation failure */
FTDM_TIMEOUT, /*!< Operation timed out (ie: polling on a device)*/
FTDM_NOTIMPL, /*!< Operation not implemented */
FTDM_BREAK /*!< Request the caller to perform a break (context-dependant, ie: stop getting DNIS/ANI) */
FTDM_BREAK, /*!< Request the caller to perform a break (context-dependant, ie: stop getting DNIS/ANI) */
FTDM_EINVAL /*!< Invalid argument */
} ftdm_status_t;
/*! \brief FreeTDM bool type. */
@ -299,6 +300,23 @@ typedef enum {
/*! \brief Move from string to ftdm_signal_event_t and viceversa */
FTDM_STR2ENUM_P(ftdm_str2ftdm_signal_event, ftdm_signal_event2str, ftdm_signal_event_t)
/*! \brief Span trunk types */
typedef enum {
FTDM_TRUNK_E1,
FTDM_TRUNK_T1,
FTDM_TRUNK_J1,
FTDM_TRUNK_BRI,
FTDM_TRUNK_BRI_PTMP,
FTDM_TRUNK_FXO,
FTDM_TRUNK_FXS,
FTDM_TRUNK_EM,
FTDM_TRUNK_NONE
} ftdm_trunk_type_t;
#define TRUNK_STRINGS "E1", "T1", "J1", "BRI", "BRI_PTMP", "FXO", "FXS", "EM", "NONE"
/*! \brief Move from string to ftdm_trunk_type_t and viceversa */
FTDM_STR2ENUM_P(ftdm_str2ftdm_trunk_type, ftdm_trunk_type2str, ftdm_trunk_type_t)
/*! \brief Basic channel configuration provided to ftdm_configure_span_channels */
typedef struct ftdm_channel_config {
char name[FTDM_MAX_NAME_STR_SZ];
@ -809,14 +827,18 @@ FT_DECLARE(const char *) ftdm_span_get_last_error(const ftdm_span_t *span);
/*!
* \brief Create a new span (not needed if you are using freetdm.conf)
*
* \param fio The I/O interface the span will use
* \param span Pointer to store the create span
* \param iotype The I/O interface type this span will use.
* This depends on the available I/O modules
* ftmod_wanpipe = "wanpipe" (Sangoma)
* ftmod_zt = "zt" (DAHDI or Zaptel)
* ftmod_pika "pika" (this one is most likely broken)
* \param name Name for the span
* \param span Pointer to store the create span
*
* \retval FTDM_SUCCESS success (the span was created)
* \retval FTDM_FAIL failure (span was not created)
*/
FT_DECLARE(ftdm_status_t) ftdm_span_create(ftdm_io_interface_t *fio, ftdm_span_t **span, const char *name);
FT_DECLARE(ftdm_status_t) ftdm_span_create(const char *iotype, const char *name, ftdm_span_t **span);
/*!
* \brief Add a new channel to a span
@ -1144,8 +1166,39 @@ FT_DECLARE(ftdm_status_t) ftdm_conf_node_add_param(ftdm_conf_node_t *node, const
* \return FTDM_FAIL failure
*/
FT_DECLARE(ftdm_status_t) ftdm_conf_node_destroy(ftdm_conf_node_t *node);
/*!
* \brief Create and configure channels in the given span
*
* \param span The span container
* \param str The channel range null terminated string. "1-10", "24" etc
* \param chan_config The basic channel configuration for each channel within the range
* \param configured Pointer where the number of channels configured will be stored
*
* \return FTDM_SUCCESS success
* \return FTDM_FAIL failure
*/
FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const char *str, ftdm_channel_config_t *chan_config, unsigned *configured);
/*!
* \brief Set the trunk type for a span
* This must be called before configuring any channels within the span
*
* \param span The span
* \param type The trunk type
*
*/
FT_DECLARE(void) ftdm_span_set_trunk_type(ftdm_span_t *span, ftdm_trunk_type_t type);
/*!
* \brief Get the trunk type for a span
*
* \param span The span
*
* \return The span trunk type
*/
FT_DECLARE(ftdm_trunk_type_t) ftdm_span_get_trunk_type(const ftdm_span_t *span);
/*!
* \brief Return the channel identified by the provided id
*

View File

@ -17,6 +17,7 @@
*
*/
#include "freetdm.h"
#ifndef _FTDM_DSO_H
#define _FTDM_DSO_H
@ -28,7 +29,7 @@ extern "C" {
typedef void (*ftdm_func_ptr_t) (void);
typedef void * ftdm_dso_lib_t;
FT_DECLARE(void) ftdm_dso_destroy(ftdm_dso_lib_t *lib);
FT_DECLARE(ftdm_status_t) ftdm_dso_destroy(ftdm_dso_lib_t *lib);
FT_DECLARE(ftdm_dso_lib_t) ftdm_dso_open(const char *path, char **err);
FT_DECLARE(void *) ftdm_dso_func_sym(ftdm_dso_lib_t lib, const char *sym, char **err);

View File

@ -111,20 +111,6 @@ typedef enum {
#define TONEMAP_STRINGS "NONE", "DIAL", "RING", "BUSY", "FAIL1", "FAIL2", "FAIL3", "ATTN", "CALLWAITING-CAS", "CALLWAITING-SAS", "CALLWAITING-ACK", "INVALID"
FTDM_STR2ENUM_P(ftdm_str2ftdm_tonemap, ftdm_tonemap2str, ftdm_tonemap_t)
typedef enum {
FTDM_TRUNK_E1,
FTDM_TRUNK_T1,
FTDM_TRUNK_J1,
FTDM_TRUNK_BRI,
FTDM_TRUNK_BRI_PTMP,
FTDM_TRUNK_FXO,
FTDM_TRUNK_FXS,
FTDM_TRUNK_EM,
FTDM_TRUNK_NONE
} ftdm_trunk_type_t;
#define TRUNK_STRINGS "E1", "T1", "J1", "BRI", "BRI_PTMP", "FXO", "FXS", "EM", "NONE"
FTDM_STR2ENUM_P(ftdm_str2ftdm_trunk_type, ftdm_trunk_type2str, ftdm_trunk_type_t)
typedef enum {
FTDM_ANALOG_START_KEWL,
FTDM_ANALOG_START_LOOP,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,50 +0,0 @@
***************
*** 3410,3420 ****
}
if (test_eflag(member->conference, EFLAG_VOLUME_IN_MEMBER) &&
data && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_add_event_member_data(member, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "volume-in-member");
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Volume-Level", "%u", member->volume_in_level);
switch_event_fire(&event);
}
return SWITCH_STATUS_SUCCESS;
}
--- 3410,3420 ----
}
if (test_eflag(member->conference, EFLAG_VOLUME_IN_MEMBER) &&
data && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_add_event_member_data(member, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "volume-in-member");
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Volume-Level", "%d", member->volume_in_level);
switch_event_fire(&event);
}
return SWITCH_STATUS_SUCCESS;
}
***************
*** 3437,3447 ****
}
if (test_eflag(member->conference, EFLAG_VOLUME_OUT_MEMBER) && data &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_add_event_member_data(member, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "volume-out-member");
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Volume-Level", "%u", member->volume_out_level);
switch_event_fire(&event);
}
return SWITCH_STATUS_SUCCESS;
}
--- 3437,3447 ----
}
if (test_eflag(member->conference, EFLAG_VOLUME_OUT_MEMBER) && data &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_add_event_member_data(member, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "volume-out-member");
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Volume-Level", "%d", member->volume_out_level);
switch_event_fire(&event);
}
return SWITCH_STATUS_SUCCESS;
}

View File

@ -50,10 +50,6 @@
#include <switch.h>
/* Defaults */
static char SQL_LOOKUP[] = "SELECT %s AS nibble_balance FROM %s WHERE %s='%s'";
static char SQL_SAVE[] = "UPDATE %s SET %s=%s-%f WHERE %s='%s'";
typedef struct {
switch_time_t lastts; /* Last time we did any billing */
float total; /* Total amount billed so far */
@ -300,7 +296,6 @@ static void transfer_call(switch_core_session_t *session, char *destination)
/* At this time, billing never succeeds if you don't have a database. */
static switch_status_t bill_event(float billamount, const char *billaccount, switch_channel_t *channel)
{
switch_stream_handle_t sql_stream = { 0 };
char *sql = NULL, *dsql = NULL;
switch_odbc_statement_handle_t stmt = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
@ -318,11 +313,9 @@ static switch_status_t bill_event(float billamount, const char *billaccount, swi
sql = globals.custom_sql_save;
}
} else {
SWITCH_STANDARD_STREAM(sql_stream);
sql_stream.write_function(&sql_stream, SQL_SAVE, globals.db_table, globals.db_column_cash,
globals.db_column_cash, billamount, globals.db_column_account, billaccount);
sql = dsql = switch_mprintf("UPDATE %s SET %s=%s-%f WHERE %s='%s'", globals.db_table, globals.db_column_cash,
globals.db_column_cash, billamount, globals.db_column_account, billaccount);
sql = (char *) sql_stream.data;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doing update query\n[%s]\n", sql);
@ -339,23 +332,18 @@ static switch_status_t bill_event(float billamount, const char *billaccount, swi
}
switch_safe_free(dsql);
switch_safe_free(sql_stream.data);
return status;
}
static float get_balance(const char *billaccount, switch_channel_t *channel)
{
switch_stream_handle_t sql_stream = { 0 };
char *sql = NULL;
char *dsql = NULL, *sql = NULL;
nibblebill_results_t pdata;
float balance = 0.00f;
SWITCH_STANDARD_STREAM(sql_stream);
if (!switch_odbc_available()) {
balance = -1.00f;
goto end;
return -1.00f;
}
memset(&pdata, 0, sizeof(pdata));
@ -363,13 +351,15 @@ static float get_balance(const char *billaccount, switch_channel_t *channel)
if (globals.custom_sql_lookup) {
if (switch_string_var_check_const(globals.custom_sql_lookup) || switch_string_has_escaped_data(globals.custom_sql_lookup)) {
sql = switch_channel_expand_variables(channel, globals.custom_sql_lookup);
if (sql != globals.custom_sql_lookup) dsql = sql;
} else {
sql = globals.custom_sql_lookup;
}
} else {
sql_stream.write_function(&sql_stream, SQL_LOOKUP, globals.db_column_cash, globals.db_table, globals.db_column_account, billaccount);
sql = sql_stream.data;
sql = dsql = switch_mprintf("SELECT %s AS nibble_balance FROM %s WHERE %s='%s'",
globals.db_column_cash, globals.db_table, globals.db_column_account, billaccount);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doing lookup query\n[%s]\n", sql);
if (switch_odbc_handle_callback_exec(globals.master_odbc, sql, nibblebill_callback, &pdata, NULL) != SWITCH_ODBC_SUCCESS) {
@ -377,19 +367,13 @@ static float get_balance(const char *billaccount, switch_channel_t *channel)
/* Return -1 for safety */
balance = -1.00f;
goto end;
} else {
/* Successfully retrieved! */
balance = pdata.balance;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Retrieved current balance for account %s (balance = %f)\n", billaccount, balance);
}
end:
if (sql != globals.custom_sql_lookup && sql != sql_stream.data) {
switch_safe_free(sql);
}
switch_safe_free(sql_stream.data);
switch_safe_free(dsql);
return balance;
}

View File

@ -1,462 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* mod_sndfile.c -- Framework Demo Module
*
*/
#include <switch.h>
#include <sndfile.h>
SWITCH_MODULE_LOAD_FUNCTION(mod_sndfile_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sndfile_shutdown);
SWITCH_MODULE_DEFINITION(mod_sndfile, mod_sndfile_load, mod_sndfile_shutdown, NULL);
static switch_memory_pool_t *module_pool = NULL;
static struct {
switch_hash_t *format_hash;
} globals;
struct format_map {
char *ext;
char *uext;
uint32_t format;
};
struct sndfile_context {
SF_INFO sfinfo;
SNDFILE *handle;
};
typedef struct sndfile_context sndfile_context;
static switch_status_t sndfile_file_open(switch_file_handle_t *handle, const char *path)
{
sndfile_context *context;
int mode = 0;
char *ext;
struct format_map *map = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
char *alt_path = NULL, *last, *ldup = NULL;
size_t alt_len = 0;
int rates[4] = { 8000, 16000, 32000, 48000 };
int i;
#ifdef WIN32
char ps = '\\';
#else
char ps = '/';
#endif
if ((ext = strrchr(path, '.')) == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Format\n");
return SWITCH_STATUS_GENERR;
}
ext++;
if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) {
mode += SFM_READ;
}
if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
if (switch_test_flag(handle, SWITCH_FILE_WRITE_APPEND)) {
mode += SFM_RDWR;
} else {
mode += SFM_WRITE;
}
}
if (!mode) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Mode!\n");
return SWITCH_STATUS_GENERR;
}
if ((context = switch_core_alloc(handle->memory_pool, sizeof(*context))) == 0) {
return SWITCH_STATUS_MEMERR;
}
map = switch_core_hash_find(globals.format_hash, ext);
if (mode & SFM_WRITE) {
context->sfinfo.channels = handle->channels;
context->sfinfo.samplerate = handle->samplerate;
if (handle->samplerate == 8000 || handle->samplerate == 16000 ||
handle->samplerate == 24000 || handle->samplerate == 32000 || handle->samplerate == 48000 ||
handle->samplerate == 11025 || handle->samplerate == 22050 || handle->samplerate == 44100) {
context->sfinfo.format |= SF_FORMAT_PCM_16;
}
}
if (map) {
context->sfinfo.format |= map->format;
}
if (!strcmp(ext, "r8") || !strcmp(ext, "raw")) {
context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16;
context->sfinfo.channels = 1;
context->sfinfo.samplerate = 8000;
} else if (!strcmp(ext, "r16")) {
context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16;
context->sfinfo.channels = 1;
context->sfinfo.samplerate = 16000;
} else if (!strcmp(ext, "r24")) {
context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_24;
context->sfinfo.channels = 1;
context->sfinfo.samplerate = 24000;
} else if (!strcmp(ext, "r32")) {
context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_32;
context->sfinfo.channels = 1;
context->sfinfo.samplerate = 32000;
} else if (!strcmp(ext, "gsm")) {
context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_GSM610;
context->sfinfo.channels = 1;
context->sfinfo.samplerate = 8000;
} else if (!strcmp(ext, "ul")) {
context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_ULAW;
context->sfinfo.channels = 1;
context->sfinfo.samplerate = 8000;
} else if (!strcmp(ext, "al")) {
context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_ALAW;
context->sfinfo.channels = 1;
context->sfinfo.samplerate = 8000;
} else if (!strcmp(ext, "adpcm")) {
context->sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM;
context->sfinfo.channels = 1;
context->sfinfo.samplerate = 8000;
}
if ((mode & SFM_WRITE) && sf_format_check(&context->sfinfo) == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error : file format is invalid (0x%08X).\n", context->sfinfo.format);
return SWITCH_STATUS_GENERR;
}
alt_len = strlen(path) + 10;
switch_zmalloc(alt_path, alt_len);
switch_copy_string(alt_path, path, alt_len);
/* This block attempts to add the sample rate to the path
if the sample rate is already present in the path it does nothing
and reverts to the original file name.
*/
if ((last = strrchr(alt_path, ps))) {
last++;
#ifdef WIN32
if (strrchr(last, '/')) {
last = strrchr(alt_path, '/'); /* do not swallow a forward slash if they are intermixed under windows */
last++;
}
#endif
ldup = strdup(last);
switch_assert(ldup);
switch_snprintf(last, alt_len - (last - alt_path), "%d%s%s", handle->samplerate, SWITCH_PATH_SEPARATOR, ldup);
if ((context->handle = sf_open(alt_path, mode, &context->sfinfo))) {
path = alt_path;
} else {
/* Try to find the file at the highest rate possible if we can't find one that matches the exact rate.
If we don't find any, we will default back to the original file name.
*/
for (i = 3; i >= 0; i--) {
switch_snprintf(last, alt_len - (last - alt_path), "%d%s%s", rates[i], SWITCH_PATH_SEPARATOR, ldup);
if ((context->handle = sf_open(alt_path, mode, &context->sfinfo))) {
path = alt_path;
break;
}
}
}
}
if (!context->handle) {
if ((context->handle = sf_open(path, mode, &context->sfinfo)) == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening File [%s] [%s]\n", path, sf_strerror(context->handle));
status = SWITCH_STATUS_GENERR;
goto end;
}
}
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opening File [%s] rate %dhz\n", path, context->sfinfo.samplerate);
handle->samples = (unsigned int) context->sfinfo.frames;
handle->samplerate = context->sfinfo.samplerate;
handle->channels = (uint8_t) context->sfinfo.channels;
handle->format = context->sfinfo.format;
handle->sections = context->sfinfo.sections;
handle->seekable = context->sfinfo.seekable;
handle->speed = 0;
handle->private_info = context;
if (switch_test_flag(handle, SWITCH_FILE_WRITE_APPEND)) {
handle->pos = sf_seek(context->handle, 0, SEEK_END);
} else {
sf_count_t frames = 0;
sf_command(context->handle, SFC_FILE_TRUNCATE, &frames, sizeof(frames));
}
end:
switch_safe_free(alt_path);
switch_safe_free(ldup);
return status;
}
static switch_status_t sndfile_file_truncate(switch_file_handle_t *handle, int64_t offset)
{
sndfile_context *context = handle->private_info;
sf_command(context->handle, SFC_FILE_TRUNCATE, &offset, sizeof(offset));
handle->pos = 0;
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t sndfile_file_close(switch_file_handle_t *handle)
{
sndfile_context *context = handle->private_info;
sf_close(context->handle);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t sndfile_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
{
sndfile_context *context = handle->private_info;
if (!handle->seekable) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "File is not seekable\n");
return SWITCH_STATUS_NOTIMPL;
}
*cur_sample = (unsigned int) sf_seek(context->handle, samples, whence);
handle->pos = *cur_sample;
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t sndfile_file_read(switch_file_handle_t *handle, void *data, size_t *len)
{
size_t inlen = *len;
sndfile_context *context = handle->private_info;
if (switch_test_flag(handle, SWITCH_FILE_DATA_RAW)) {
*len = (size_t) sf_read_raw(context->handle, data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_INT)) {
*len = (size_t) sf_readf_int(context->handle, (int *) data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_SHORT)) {
*len = (size_t) sf_readf_short(context->handle, (short *) data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_FLOAT)) {
*len = (size_t) sf_readf_float(context->handle, (float *) data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_DOUBLE)) {
*len = (size_t) sf_readf_double(context->handle, (double *) data, inlen);
} else {
*len = (size_t) sf_readf_int(context->handle, (int *) data, inlen);
}
handle->pos += *len;
handle->sample_count += *len;
return *len ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
}
static switch_status_t sndfile_file_write(switch_file_handle_t *handle, void *data, size_t *len)
{
size_t inlen = *len;
sndfile_context *context = handle->private_info;
if (switch_test_flag(handle, SWITCH_FILE_DATA_RAW)) {
*len = (size_t) sf_write_raw(context->handle, data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_INT)) {
*len = (size_t) sf_writef_int(context->handle, (int *) data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_SHORT)) {
*len = (size_t) sf_writef_short(context->handle, (short *) data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_FLOAT)) {
*len = (size_t) sf_writef_float(context->handle, (float *) data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_DOUBLE)) {
*len = (size_t) sf_writef_double(context->handle, (double *) data, inlen);
} else {
*len = (size_t) sf_writef_int(context->handle, (int *) data, inlen);
}
handle->sample_count += *len;
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t sndfile_file_set_string(switch_file_handle_t *handle, switch_audio_col_t col, const char *string)
{
sndfile_context *context = handle->private_info;
return sf_set_string(context->handle, (int) col, string) ? SWITCH_STATUS_FALSE : SWITCH_STATUS_SUCCESS;
}
static switch_status_t sndfile_file_get_string(switch_file_handle_t *handle, switch_audio_col_t col, const char **string)
{
sndfile_context *context = handle->private_info;
const char *s;
if ((s = sf_get_string(context->handle, (int) col))) {
*string = s;
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
/* Registration */
static char **supported_formats;
static switch_status_t setup_formats(void)
{
SF_FORMAT_INFO info;
SF_INFO sfinfo;
char buffer[128];
int format, major_count, subtype_count, m, s;
int len, x, skip;
char *extras[] = { "r8", "r16", "r24", "r32", "gsm", "ul", "al", "adpcm", NULL };
int exlen = (sizeof(extras) / sizeof(extras[0]));
buffer[0] = 0;
sf_command(NULL, SFC_GET_LIB_VERSION, buffer, sizeof(buffer));
if (strlen(buffer) < 1) {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR, "Line %d: could not retrieve lib version.\n", __LINE__);
return SWITCH_STATUS_FALSE;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "\nLibSndFile Version : %s Supported Formats\n", buffer);
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO, "================================================================================\n");
sf_command(NULL, SFC_GET_FORMAT_MAJOR_COUNT, &major_count, sizeof(int));
sf_command(NULL, SFC_GET_FORMAT_SUBTYPE_COUNT, &subtype_count, sizeof(int));
sfinfo.channels = 1;
len = ((major_count + (exlen + 2)) * sizeof(char *));
supported_formats = switch_core_permanent_alloc(len);
len = 0;
for (m = 0; m < major_count; m++) {
skip = 0;
info.format = m;
sf_command(NULL, SFC_GET_FORMAT_MAJOR, &info, sizeof(info));
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO, "%s (extension \"%s\")\n", info.name, info.extension);
for (x = 0; x < len; x++) {
if (supported_formats[x] == info.extension) {
skip++;
break;
}
}
if (!skip) {
char *p;
struct format_map *map = switch_core_permanent_alloc(sizeof(*map));
switch_assert(map);
map->ext = switch_core_permanent_strdup(info.extension);
map->uext = switch_core_permanent_strdup(info.extension);
map->format = info.format;
if (map->ext) {
for (p = map->ext; *p; p++) {
*p = (char) switch_tolower(*p);
}
switch_core_hash_insert(globals.format_hash, map->ext, map);
}
if (map->uext) {
for (p = map->uext; *p; p++) {
*p = (char) switch_toupper(*p);
}
switch_core_hash_insert(globals.format_hash, map->uext, map);
}
supported_formats[len++] = (char *) info.extension;
}
format = info.format;
for (s = 0; s < subtype_count; s++) {
info.format = s;
sf_command(NULL, SFC_GET_FORMAT_SUBTYPE, &info, sizeof(info));
format = (format & SF_FORMAT_TYPEMASK) | info.format;
sfinfo.format = format;
/*
if (sf_format_check(&sfinfo)) {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, " %s\n", info.name);
}
*/
}
}
for (m = 0; m < exlen; m++) {
supported_formats[len++] = extras[m];
}
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_NOTICE, "================================================================================\n");
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_sndfile_load)
{
switch_file_interface_t *file_interface;
if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
return SWITCH_STATUS_TERM;
}
switch_core_hash_init(&globals.format_hash, module_pool);
if (setup_formats() != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
}
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
file_interface->interface_name = modname;
file_interface->extens = supported_formats;
file_interface->file_open = sndfile_file_open;
file_interface->file_close = sndfile_file_close;
file_interface->file_truncate = sndfile_file_truncate;
file_interface->file_read = sndfile_file_read;
file_interface->file_write = sndfile_file_write;
file_interface->file_seek = sndfile_file_seek;
file_interface->file_set_string = sndfile_file_set_string;
file_interface->file_get_string = sndfile_file_get_string;
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sndfile_shutdown)
{
switch_core_hash_destroy(&globals.format_hash);
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
*/

View File

@ -1,38 +0,0 @@
***************
*** 5555,5561 ****
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "EventConsumer_pop" "', argument " "2"" of type '" "int""'");
}
arg2 = static_cast< int >(val2);
result = (Event *)(arg1)->pop(arg2);
resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Event, SWIG_POINTER_OWN | 0 );
return resultobj;
fail:
--- 5555,5563 ----
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "EventConsumer_pop" "', argument " "2"" of type '" "int""'");
}
arg2 = static_cast< int >(val2);
+ Py_BEGIN_ALLOW_THREADS;
result = (Event *)(arg1)->pop(arg2);
+ Py_END_ALLOW_THREADS;
resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Event, SWIG_POINTER_OWN | 0 );
return resultobj;
fail:
***************
*** 5577,5583 ****
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "EventConsumer_pop" "', argument " "1"" of type '" "EventConsumer *""'");
}
arg1 = reinterpret_cast< EventConsumer * >(argp1);
result = (Event *)(arg1)->pop();
resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Event, SWIG_POINTER_OWN | 0 );
return resultobj;
fail:
--- 5579,5587 ----
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "EventConsumer_pop" "', argument " "1"" of type '" "EventConsumer *""'");
}
arg1 = reinterpret_cast< EventConsumer * >(argp1);
+ Py_BEGIN_ALLOW_THREADS;
result = (Event *)(arg1)->pop();
+ Py_END_ALLOW_THREADS;
resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Event, SWIG_POINTER_OWN | 0 );
return resultobj;
fail:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1331,7 +1331,7 @@ static const char *switch_inet_ntop4(const unsigned char *src, char *dst, size_t
return strcpy(dst, tmp);
}
#if HAVE_SIN6 || (defined(NTDDI_VERSION) && (NTDDI_VERSION < NTDDI_VISTA))
#if HAVE_SIN6 || defined(NTDDI_VERSION)
/* const char *
* inet_ntop6(src, dst, size)
* convert IPv6 binary address into presentation (printable) format
@ -1488,7 +1488,7 @@ SWITCH_DECLARE(char *) get_addr6(char *buf, switch_size_t len, struct sockaddr_i
*buf = '\0';
if (sa) {
#if defined(NTDDI_VERSION) && (NTDDI_VERSION < NTDDI_VISTA)
#if defined(NTDDI_VERSION)
switch_inet_ntop6((unsigned char*)sa, buf, len);
#else
inet_ntop(AF_INET6, sa, buf, len);