Merge branch 'master' of git.freeswitch.org:freeswitch

This commit is contained in:
Anthony Minessale 2010-04-12 11:09:02 -05:00
commit 7f82a41a85
31 changed files with 2043 additions and 1297 deletions

View File

@ -117,7 +117,7 @@
</extension>
<extension name="redial">
<condition field="destination_number" expression="^870$">
<condition field="destination_number" expression="^(redial|870)$">
<action application="transfer" data="${hash(select/${domain_name}-last_dial/${caller_id_number})}"/>
</condition>
</extension>

View File

@ -179,10 +179,26 @@ void MainWindow::debugConsoleTriggered()
}
void MainWindow::applyPreprocessors(QStringList cmds)
{
if (g_FSHost.getCurrentActiveCall().isNull()) return;
QString uuid = g_FSHost.getCurrentActiveCall().data()->getUuid();
foreach(QString cmd, cmds)
{
switch_stream_handle_t stream = { 0 };
SWITCH_STANDARD_STREAM(stream);
switch_api_execute("uuid_preprocess", QString("%1 %2").arg(uuid, cmd).toAscii().data(), NULL, &stream);
switch_safe_free(stream.data);
}
}
void MainWindow::prefTriggered()
{
if (!preferences)
{
preferences = new PrefDialog();
connect(preferences, SIGNAL(preprocessorsApplied(QStringList)), this, SLOT(applyPreprocessors(QStringList)));
}
preferences->raise();
preferences->show();

View File

@ -85,6 +85,7 @@ private slots:
void updateCallTimers();
void debugConsoleTriggered();
void debugEventsTriggered();
void applyPreprocessors(QStringList);
private:
Ui::MainWindow *ui;

View File

@ -15,6 +15,7 @@ PrefDialog::PrefDialog(QWidget *parent) :
_pref_accounts = new PrefAccounts(ui);
_mod_portaudio = new PrefPortaudio(ui, this);
connect(_mod_portaudio, SIGNAL(preprocessorsApplied(QStringList)), this, SIGNAL(preprocessorsApplied(QStringList)));
_mod_sofia = new PrefSofia(ui, this);
readConfig();
}

View File

@ -26,6 +26,9 @@ protected:
private slots:
void writeConfig();
signals:
void preprocessorsApplied(QStringList);
private:
void readConfig();
QSettings *_settings;

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,28 @@ PrefPortaudio::PrefPortaudio(Ui::PrefDialog *ui, QObject *parent) :
connect(_ui->PaRingdevTestBtn, SIGNAL(clicked()), this, SLOT(ringdevTest()));
connect(_ui->PaLoopTestBtn, SIGNAL(clicked()), this, SLOT(loopTest()));
connect(_ui->PaRefreshDevListBtn, SIGNAL(clicked()), this, SLOT(refreshDevList()));
connect(_ui->btnApplyPreprocessor, SIGNAL(toggled(bool)), this, SLOT(applyPreprocessors(bool)));
}
void PrefPortaudio::applyPreprocessors(bool state)
{
QStringList cmds;
if (!state)
{
cmds.append("stop");
}
else
{
if (_ui->checkAECRead->isChecked()) cmds.append(QString("recho_cancel=%1").arg(_ui->spinAECTail->value()));
if (_ui->checkAECWrite->isChecked()) cmds.append(QString("wecho_cancel=%1").arg(_ui->spinAECTail->value()));
if (_ui->checkESRead->isChecked()) cmds.append(QString("recho_suppress=%1").arg(_ui->spinESDb->value()));
if (_ui->checkESWrite->isChecked()) cmds.append(QString("wecho_suppress=%1").arg(_ui->spinESDb->value()));
if (_ui->checkNSRead->isChecked()) cmds.append(QString("rnoise_suppress=%1").arg(_ui->spinNSDb->value()));
if (_ui->checkNSWrite->isChecked()) cmds.append(QString("wnoise_suppress=%1").arg(_ui->spinNSDb->value()));
if (_ui->checkAGCRead->isChecked()) cmds.append(QString("ragc=%1").arg(_ui->spinAGC->value()));
if (_ui->checkAGCWrite->isChecked()) cmds.append(QString("wagc=%1").arg(_ui->spinAGC->value()));
}
emit preprocessorsApplied(cmds);
}
void PrefPortaudio::ringdevTest()

View File

@ -24,6 +24,11 @@ private slots:
void ringdevTest();
void loopTest();
void refreshDevList();
void applyPreprocessors(bool);
signals:
void preprocessorsApplied(QStringList);
private:
void getPaDevlist(void);
QSettings *_settings;

View File

@ -326,10 +326,34 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\src\include\freetdm.h"
>
</File>
<File
RelativePath="..\src\include\fsk.h"
>
</File>
<File
RelativePath="..\src\include\ftdm_buffer.h"
>
</File>
<File
RelativePath="..\src\include\ftdm_config.h"
>
</File>
<File
RelativePath="..\src\include\ftdm_dso.h"
>
</File>
<File
RelativePath="..\src\include\ftdm_threadmutex.h"
>
</File>
<File
RelativePath="..\src\include\ftdm_types.h"
>
</File>
<File
RelativePath="..\src\include\g711.h"
>
@ -358,34 +382,10 @@
RelativePath="..\src\include\libteletone_generate.h"
>
</File>
<File
RelativePath="..\src\include\freetdm.h"
>
</File>
<File
RelativePath="..\src\include\uart.h"
>
</File>
<File
RelativePath="..\src\include\ftdm_buffer.h"
>
</File>
<File
RelativePath="..\src\include\ftdm_config.h"
>
</File>
<File
RelativePath="..\src\include\ftdm_dso.h"
>
</File>
<File
RelativePath="..\src\include\ftdm_threadmutex.h"
>
</File>
<File
RelativePath="..\src\include\ftdm_types.h"
>
</File>
</Filter>
<Filter
Name="Source Files"
@ -396,6 +396,38 @@
RelativePath="..\src\fsk.c"
>
</File>
<File
RelativePath="..\src\ftdm_buffer.c"
>
</File>
<File
RelativePath="..\src\ftdm_callerid.c"
>
</File>
<File
RelativePath="..\src\ftdm_config.c"
>
</File>
<File
RelativePath="..\src\ftdm_cpu_monitor.c"
>
</File>
<File
RelativePath="..\src\ftdm_dso.c"
>
</File>
<File
RelativePath="..\src\ftdm_io.c"
>
</File>
<File
RelativePath="..\src\ftdm_queue.c"
>
</File>
<File
RelativePath="..\src\ftdm_threadmutex.c"
>
</File>
<File
RelativePath="..\src\g711.c"
>
@ -420,34 +452,6 @@
RelativePath="..\src\uart.c"
>
</File>
<File
RelativePath="..\src\ftdm_buffer.c"
>
</File>
<File
RelativePath="..\src\ftdm_callerid.c"
>
</File>
<File
RelativePath="..\src\ftdm_config.c"
>
</File>
<File
RelativePath="..\src\ftdm_dso.c"
>
</File>
<File
RelativePath="..\src\ftdm_io.c"
>
</File>
<File
RelativePath="..\src\ftdm_queue.c"
>
</File>
<File
RelativePath="..\src\ftdm_threadmutex.c"
>
</File>
</Filter>
</Files>
<Globals>

View File

@ -61,6 +61,9 @@ struct ftdm_cpu_monitor_stats
double last_percentage_of_idle_time;
#ifdef __linux__
/* the cpu feature gets disabled on errors */
int disabled;
/* all of these are the Linux jiffies last retrieved count */
unsigned long long last_user_time;
unsigned long long last_system_time;
@ -97,15 +100,23 @@ static ftdm_status_t ftdm_cpu_read_stats(struct ftdm_cpu_monitor_stats *p,
{
// the output of proc should not change that often from one kernel to other
// see fs/proc/proc_misc.c or fs/proc/stat.c in the Linux kernel for more details
// also man 5 proc is useful
#define CPU_ELEMENTS 8 // change this if you change the format string
#define CPU_INFO_FORMAT "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu"
// also man 5 proc is useful.
#define CPU_ELEMENTS_1 7 // change this if you change the format string
#define CPU_INFO_FORMAT_1 "cpu %llu %llu %llu %llu %llu %llu %llu"
#define CPU_ELEMENTS_2 8 // change this if you change the format string
#define CPU_INFO_FORMAT_2 "cpu %llu %llu %llu %llu %llu %llu %llu %llu"
#define CPU_ELEMENTS_3 9 // change this if you change the format string
#define CPU_INFO_FORMAT_3 "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu"
static const char procfile[] = "/proc/stat";
int rc = 0;
int myerrno = 0;
int elements = 0;
const char *cpustr = NULL;
char statbuff[1024];
unsigned long long guest = 0;
if (!p->initd) {
p->procfd = open(procfile, O_RDONLY, 0);
@ -131,12 +142,26 @@ static ftdm_status_t ftdm_cpu_read_stats(struct ftdm_cpu_monitor_stats *p,
return FTDM_FAIL;
}
elements = sscanf(cpustr, CPU_INFO_FORMAT, user, nice, system, idle, iowait, irq, softirq, steal);
if (elements != CPU_ELEMENTS) {
ftdm_log(FTDM_LOG_ERROR, "wrong format for Linux proc cpu statistics: expected %d elements, but just found %d\n", CPU_ELEMENTS, elements);
return FTDM_FAIL;
/* test each of the known formats starting from the bigger one */
elements = sscanf(cpustr, CPU_INFO_FORMAT_3, user, nice, system, idle, iowait, irq, softirq, steal, &guest);
if (elements == CPU_ELEMENTS_3) {
user += guest; /* guest operating system's run in user space */
return FTDM_SUCCESS;
}
return FTDM_SUCCESS;
elements = sscanf(cpustr, CPU_INFO_FORMAT_2, user, nice, system, idle, iowait, irq, softirq, steal);
if (elements == CPU_ELEMENTS_2) {
return FTDM_SUCCESS;
}
elements = sscanf(cpustr, CPU_INFO_FORMAT_1, user, nice, system, idle, iowait, irq, softirq);
if (elements == CPU_ELEMENTS_1) {
*steal = 0;
return FTDM_SUCCESS;
}
ftdm_log(FTDM_LOG_ERROR, "Unexpected format for Linux proc cpu statistics:%s\n", cpustr);
return FTDM_FAIL;
}
#endif
@ -146,8 +171,13 @@ FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time (struct ftdm_cpu_monitor
unsigned long long user, nice, system, idle, iowait, irq, softirq, steal;
unsigned long long usertime, kerneltime, idletime, totaltime, halftime;
*idle_percentage = 100.0;
if (p->disabled) {
return FTDM_FAIL;
}
if (ftdm_cpu_read_stats(p, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal)) {
ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve Linux CPU statistics\n");
ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve Linux CPU statistics - disabling cpu monitor\n");
p->disabled = 1;
return FTDM_FAIL;
}
@ -201,28 +231,31 @@ FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time (struct ftdm_cpu_monitor
return FTDM_SUCCESS;
}
#elif defined (WIN32) || defined (WIN64)
#elif defined (__WINDOWS__)
FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_stats *p, double *idle_percentage)
{
FILETIME idleTime;
FILETIME kernelTime;
FILETIME userTime;
int64_t i64UserTime;
int64_t i64KernelTime;
int64_t i64IdleTime;
if (!::GetSystemTimes(&idleTime, &kernelTime, &userTime)) {
return false;
if (!GetSystemTimes(&idleTime, &kernelTime, &userTime)) {
return FTDM_FAIL;
}
__int64 i64UserTime = (__int64)userTime.dwLowDateTime | ((__int64)userTime.dwHighDateTime << 32);
i64UserTime = (int64_t)userTime.dwLowDateTime | ((int64_t)userTime.dwHighDateTime << 32);
__int64 i64KernelTime = (__int64)kernelTime.dwLowDateTime | ((__int64)kernelTime.dwHighDateTime << 32);
i64KernelTime = (int64_t)kernelTime.dwLowDateTime | ((int64_t)kernelTime.dwHighDateTime << 32);
__int64 i64IdleTime = (__int64)idleTime.dwLowDateTime | ((__int64)idleTime.dwHighDateTime << 32);
i64IdleTime = (int64_t)idleTime.dwLowDateTime | ((int64_t)idleTime.dwHighDateTime << 32);
if (p->valid_last_times) {
__int64 i64User = i64UserTime - p->i64LastUserTime;
__int64 i64Kernel = i64KernelTime - p->i64LastKernelTime;
__int64 i64Idle = i64IdleTime - p->i64LastIdleTime;
__int64 i64System = i64User + i64Kernel;
int64_t i64User = i64UserTime - p->i64LastUserTime;
int64_t i64Kernel = i64KernelTime - p->i64LastKernelTime;
int64_t i64Idle = i64IdleTime - p->i64LastIdleTime;
int64_t i64System = i64User + i64Kernel;
*idle_percentage = 100.0 * i64Idle / i64System;
} else {
*idle_percentage = 100.0;
@ -240,7 +273,8 @@ FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_
#else
/* Unsupported */
FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_stats *p, double *idle_percentage)
{
{'
*idle_percentate = 100.0;
return FTDM_FAIL;
}
#endif

View File

@ -2855,6 +2855,7 @@ static ftdm_status_t load_config(void)
ftdm_config_t cfg;
char *var, *val;
int catno = -1;
int intparam = 0;
int currindex = 0;
ftdm_span_t *span = NULL;
unsigned configured = 0, d = 0;
@ -3059,14 +3060,16 @@ static ftdm_status_t load_config(void)
ftdm_log(FTDM_LOG_ERROR, "Invalid cpu monitoring interval %s\n", val);
}
} else if (!strncasecmp(var, "cpu_set_alarm_threshold", sizeof("cpu_set_alarm_threshold")-1)) {
if (atoi(val) > 0 && atoi(val) < 100) {
globals.cpu_monitor.set_alarm_threshold = atoi(val);
intparam = atoi(val);
if (intparam > 0 && intparam < 100) {
globals.cpu_monitor.set_alarm_threshold = (uint8_t)intparam;
} else {
ftdm_log(FTDM_LOG_ERROR, "Invalid cpu alarm set threshold %s\n", val);
}
} else if (!strncasecmp(var, "cpu_reset_alarm_threshold", sizeof("cpu_reset_alarm_threshold")-1)) {
if (atoi(val) > 0 && atoi(val) < 100) {
globals.cpu_monitor.reset_alarm_threshold = atoi(val);
intparam = atoi(val);
if (intparam > 0 && intparam < 100) {
globals.cpu_monitor.reset_alarm_threshold = (uint8_t)intparam;
if (globals.cpu_monitor.reset_alarm_threshold > globals.cpu_monitor.set_alarm_threshold) {
globals.cpu_monitor.reset_alarm_threshold = globals.cpu_monitor.set_alarm_threshold - 10;
ftdm_log(FTDM_LOG_ERROR, "Cpu alarm reset threshold must be lower than set threshold"
@ -3404,6 +3407,9 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_signaling(const char *type, ftdm_s
if (mod->configure_span_signaling) {
status = mod->configure_span_signaling(span, sig_cb, parameters);
if (status == FTDM_SUCCESS && ftdm_test_flag(span, FTDM_SPAN_USE_CHAN_QUEUE)) {
status = ftdm_queue_create(&span->pendingchans, SPAN_PENDING_CHANS_QUEUE_SIZE);
}
} else {
ftdm_log(FTDM_LOG_ERROR, "Module %s did not implement the signaling configuration method\n", type);
}
@ -3652,6 +3658,9 @@ static void *ftdm_cpu_monitor_run(ftdm_thread_t *me, void *obj)
ftdm_delete_cpu_monitor(cpu_stats);
monitor->running = 0;
return NULL;
#ifdef __WINDOWS__
UNREFERENCED_PARAMETER(me);
#endif
}
static ftdm_status_t ftdm_cpu_monitor_start(void)

View File

@ -314,7 +314,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_wait(ftdm_interrupt_t *interrupt, int m
num++;
ints[1] = interrupt->device;
}
res = WaitForMultipleObjects(num, &ints, FALSE, ms >= 0 ? ms : INFINITE);
res = WaitForMultipleObjects(num, ints, FALSE, ms >= 0 ? ms : INFINITE);
switch (res) {
case WAIT_TIMEOUT:
return FTDM_TIMEOUT;
@ -366,7 +366,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_signal(ftdm_interrupt_t *interrupt)
{
ftdm_assert_return(interrupt != NULL, FTDM_FAIL, "Interrupt is null!\n");
#ifdef WIN32
if (!SetEvent(interrupt->interrupt)) {
if (!SetEvent(interrupt->event)) {
ftdm_log(FTDM_LOG_ERROR, "Failed to signal interrupt\n");
return FTDM_FAIL;
}
@ -400,10 +400,42 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_destroy(ftdm_interrupt_t **ininterrupt)
FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interrupts[], ftdm_size_t size, int ms)
{
#ifndef WIN32
int i;
int res = 0;
int numdevices = 0;
unsigned i;
#if defined(__WINDOWS__)
DWORD res = 0;
HANDLE ints[20];
if (size > (ftdm_array_len(ints)/2)) {
/* improve if needed: dynamically allocate the list of interrupts *only* when exceeding the default size */
ftdm_log(FTDM_LOG_CRIT, "Unsupported size of interrupts: %d, implement me!\n", size);
return FTDM_FAIL;
}
for (i = 0; i < size; i++) {
ints[i] = interrupts[i]->event;
if (interrupts[i]->device != FTDM_INVALID_SOCKET) {
ints[i+numdevices] = interrupts[i]->device;
numdevices++;
}
}
res = WaitForMultipleObjects(size+numdevices, ints, FALSE, ms >= 0 ? ms : INFINITE);
switch (res) {
case WAIT_TIMEOUT:
return FTDM_TIMEOUT;
case WAIT_FAILED:
case WAIT_ABANDONED: /* is it right to fail with abandoned? */
return FTDM_FAIL;
default:
if (res >= (size+numdevices)) {
ftdm_log(FTDM_LOG_ERROR, "Error waiting for freetdm interrupt event (WaitForSingleObject returned %d)\n", res);
return FTDM_FAIL;
}
/* fall-through to FTDM_SUCCESS at the end of the function */
}
#elif defined(__linux__)
int res = 0;
char pipebuf[255];
struct pollfd ints[size*2];
@ -432,6 +464,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
return FTDM_TIMEOUT;
}
/* check for events in the pipes, NOT in the devices */
for (i = 0; i < size; i++) {
if (ints[i].revents & POLLIN) {
res = read(ints[i].fd, pipebuf, sizeof(pipebuf));
@ -440,7 +473,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
}
}
}
#else
#endif
return FTDM_SUCCESS;
}

View File

@ -356,7 +356,7 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
ftdm_set_string(event.calling_name, caller_data->cid_name);
ftdm_set_string(event.rdnis.digits, caller_data->rdnis.digits);
if (strlen(caller_data->rdnis.digits)) {
event.rdnis.digits_count = strlen(caller_data->rdnis.digits)+1;
event.rdnis.digits_count = (uint8_t)strlen(caller_data->rdnis.digits)+1;
event.rdnis.ton = caller_data->rdnis.type;
event.rdnis.npi = caller_data->rdnis.plan;
}
@ -474,7 +474,7 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(sangoma_boost_outgoing_call)
ftdm_set_string(event.calling_name, ftdmchan->caller_data.cid_name);
ftdm_set_string(event.rdnis.digits, ftdmchan->caller_data.rdnis.digits);
if (strlen(ftdmchan->caller_data.rdnis.digits)) {
event.rdnis.digits_count = strlen(ftdmchan->caller_data.rdnis.digits)+1;
event.rdnis.digits_count = (uint8_t)strlen(ftdmchan->caller_data.rdnis.digits)+1;
event.rdnis.ton = ftdmchan->caller_data.rdnis.type;
event.rdnis.npi = ftdmchan->caller_data.rdnis.plan;
}

View File

@ -67,7 +67,7 @@
Name="VCLinkerTool"
AdditionalDependencies="freetdm.lib libsangoma.lib"
LinkIncremental="2"
AdditionalLibraryDirectories="&quot;$(OutDir)&quot;;&quot;C:\Program Files\Sangoma\lib&quot;"
AdditionalLibraryDirectories="&quot;$(OutDir)&quot;;&quot;C:\Program Files\Sangoma\api\lib\x86&quot;"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
@ -96,6 +96,83 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../src/include;../../../src/isdn/include;../../../wanpipe/include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="freetdm.lib libsangoma.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="&quot;$(OutDir)&quot;;../../../wanpipe/api/lib/x86"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
@ -174,83 +251,6 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../src/include;../../../src/isdn/include;../../../wanpipe/include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="freetdm.lib libsangoma.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="&quot;$(OutDir)&quot;;../../../wanpipe/api/lib/x86"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"

View File

@ -101,8 +101,6 @@ static struct {
FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event);
FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event);
#define WP_INVALID_SOCKET -1
/**
* \brief Poll for event on a wanpipe socket
* \param fd Wanpipe socket descriptor
@ -224,7 +222,7 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
}
for(x = start; x < end; x++) {
ftdm_channel_t *chan;
ftdm_socket_t sockfd = WP_INVALID_SOCKET;
ftdm_socket_t sockfd = FTDM_INVALID_SOCKET;
const char *dtmf = "none";
if (!strncasecmp(span->name, "smg_prid_nfas", 8) && span->trunk_type == FTDM_TRUNK_T1 && x == 24) {
#ifdef LIBSANGOMA_VERSION
@ -236,7 +234,7 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
sockfd = tdmv_api_open_span_chan(spanno, x);
}
if (sockfd == WP_INVALID_SOCKET) {
if (sockfd == FTDM_INVALID_SOCKET) {
ftdm_log(FTDM_LOG_ERROR, "Failed to open wanpipe device span %d channel %d\n", spanno, x);
continue;
}
@ -1166,9 +1164,8 @@ static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
}
#endif
if (ftdmchan->sockfd > -1) {
close(ftdmchan->sockfd);
ftdmchan->sockfd = WP_INVALID_SOCKET;
if (ftdmchan->sockfd != FTDM_INVALID_SOCKET) {
sangoma_close(&ftdmchan->sockfd);
}
return FTDM_SUCCESS;

View File

@ -43,8 +43,6 @@
#include "libsangoma.h"
#if defined(__WINDOWS__)
/* remove this when http://jira.freeswitch.org/browse/FSBUILD-259 wanpipe issue is fixed */
#define WINDOWS_BUILD_BROKEN 1
/*! Backward compatible defines - current code is all using the old names*/
#define sangoma_open_tdmapi_span_chan sangoma_open_api_span_chan
#define sangoma_open_tdmapi_span sangoma_open_api_span
@ -96,8 +94,6 @@ static struct {
ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event);
ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event);
#define WP_INVALID_SOCKET -1
/**
* \brief Poll for event on a wanpipe socket
* \param fd Wanpipe socket descriptor
@ -219,7 +215,7 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
}
for(x = start; x < end; x++) {
zap_channel_t *chan;
zap_socket_t sockfd = WP_INVALID_SOCKET;
zap_socket_t sockfd = ZAP_INVALID_SOCKET;
const char *dtmf = "none";
if (!strncasecmp(span->name, "smg_prid_nfas", 8) && span->trunk_type == ZAP_TRUNK_T1 && x == 24) {
#ifdef LIBSANGOMA_VERSION
@ -231,7 +227,7 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
sockfd = tdmv_api_open_span_chan(spanno, x);
}
if (sockfd == WP_INVALID_SOCKET) {
if (sockfd == ZAP_INVALID_SOCKET) {
zap_log(ZAP_LOG_ERROR, "Failed to open wanpipe device span %d channel %d\n", spanno, x);
continue;
}
@ -587,29 +583,24 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
break;
case ZAP_COMMAND_ENABLE_ECHOCANCEL:
{
#ifndef WINDOWS_BUILD_BROKEN
err=sangoma_tdm_enable_hwec(zchan->sockfd, &tdm_api);
if (err) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "HWEC Enable Failed");
return ZAP_FAIL;
}
#endif /* WINDOWS_BUILD_BROKEN */
}
break;
case ZAP_COMMAND_DISABLE_ECHOCANCEL:
{
#ifndef WINDOWS_BUILD_BROKEN
err=sangoma_tdm_disable_hwec(zchan->sockfd, &tdm_api);
if (err) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "HWEC Disable Failed");
return ZAP_FAIL;
}
#endif /* WINDOWS_BUILD_BROKEN */
}
break;
case ZAP_COMMAND_ENABLE_LOOP:
{
#ifndef WINDOWS_BUILD_BROKEN
#ifdef WP_API_FEATURE_LOOP
err=sangoma_tdm_enable_loop(zchan->sockfd, &tdm_api);
if (err) {
@ -617,11 +608,9 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
return ZAP_FAIL;
}
#endif
#endif /* WINDOWS_BUILD_BROKEN */
}
case ZAP_COMMAND_DISABLE_LOOP:
{
#ifndef WINDOWS_BUILD_BROKEN
#ifdef WP_API_FEATURE_LOOP
err=sangoma_tdm_disable_loop(zchan->sockfd, &tdm_api);
if (err) {
@ -629,7 +618,6 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
return ZAP_FAIL;
}
#endif
#endif /* WINDOWS_BUILD_BROKEN */
}
case ZAP_COMMAND_SET_INTERVAL:
{
@ -1163,9 +1151,8 @@ static ZIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
}
#endif
if (zchan->sockfd > -1) {
close(zchan->sockfd);
zchan->sockfd = WP_INVALID_SOCKET;
if (zchan->sockfd != ZAP_INVALID_SOCKET) {
sangoma_close(&zchan->sockfd);
}
return ZAP_SUCCESS;

76
scripts/setup-git.sh Executable file
View File

@ -0,0 +1,76 @@
#!/bin/bash
##### -*- mode:shell-script; indent-tabs-mode:nil; sh-basic-offset:2 -*-
##### setup git properly for FreeSWITCH
if [ ! -d .git ]; then
echo "error: must be run from within the top level of a FreeSWITCH git tree." 1>&2
exit 1;
fi
err () {
echo "error: $1" 1>&2
exit 1
}
if ! git config user.name >/dev/null 2>&1; then
name=$(git config user.name)
[ -z "$name" ] \
&& [ -n "$NAME" ] && name="$NAME" || name=""
echo -n "What is your name? [$name]: "
read name_
[ -n "$name_" ] && name="$name_"
[ -z "$name" ] && err "Your name is required."
git config --global user.name "$name"
fi
if ! git config user.email >/dev/null 2>&1; then
email=$(git config user.email)
[ -z "$email" ] \
&& [ -n "$EMAIL" ] && email="$EMAIL" || email=""
echo -n "What is your email? [$email]: "
read email_
[ -n "$email_" ] && email="$email_"
[ -z "$email" ] && err "Your email is required."
git config --global user.email "$email"
fi
git config branch.master.rebase true
cat 1>&2 <<EOF
----------------------------------------------------------------------
Git has been configured for FS successfully.
branch.master.rebase has been set to true
This means that when you do a 'git pull' to fetch remote changes,
your local changes will be rebased on top of the remote changes.
This does NOT rewrite history on the remote FS repo, but it does
change the commit hashes in your local tree.
If you really want to merge rather than rebasing, run:
git merge <commit>
See 'man git-config' for more information.
EOF
[ -n "$name" ] \
&& cat 1>&2 <<EOF
Your name has been set to: $name
via 'git config --global user.name "$name"
EOF
[ -n "$name" ] \
&& cat 1>&2 <<EOF
Your email has been set to: $email
via 'git config --global user.email "$email"
EOF
cat 1>&2 <<EOF
----------------------------------------------------------------------
EOF

View File

@ -298,6 +298,10 @@ static char *get_bridge_data(switch_memory_pool_t *pool, char *dialed_number, ch
switch_core_sprintf(pool, "[lcr_carrier=%s,lcr_rate=%s%s%s%s%s]%s%s%s%s%s", cur_route->carrier_name, cur_route->rate_str, user_rate, codec, cid,
header, cur_route->gw_prefix, cur_route->prefix, destination_number, cur_route->suffix, cur_route->gw_suffix);
if (session && (switch_string_var_check_const(data) || switch_string_has_escaped_data(data))) {
data = switch_channel_expand_variables(switch_core_session_get_channel(session), data);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Returning Dialstring %s\n", data);
return data;
}

View File

@ -186,10 +186,14 @@ static void tts_commandline_speech_flush_tts(switch_speech_handle_t *sh)
{
tts_commandline_t *info = (tts_commandline_t *) sh->private_info;
assert(info != NULL);
switch_core_file_close(info->fh);
if (unlink(info->file) != 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Sound file [%s] delete failed\n", info->file);
if (info->fh != NULL && info->fh->file_interface != NULL) {
switch_core_file_close(info->fh);
}
if (switch_file_exists(info->file, NULL) == SWITCH_STATUS_SUCCESS) {
if (unlink(info->file) != 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Sound file [%s] delete failed\n", info->file);
}
}
}

View File

@ -6,26 +6,25 @@ package Net::Skinny;
use strict;
use warnings;
use IO::Socket;
require IO::Socket;
use Net::Skinny::Protocol qw/:all/;
our(@ISA);
@ISA = qw(IO::Socket::INET);
our @ISA = qw(IO::Socket::INET);
sub new {
shift->SUPER::new(PeerPort => 2000, @_);
}
sub send_data
sub send_raw
{
my $self = shift;
my $type = shift;
my $data = shift;
my $len = length($data)+4;
my $raw = shift;
my $len = length($raw)+4;
printf "Sending message (length=%d, type=%s (%X))", $len, Net::Skinny::Protocol::skinny_message_type2str($type), $type;
$self->send(
pack("VVV", $len, 0, $type).
$data);
$self->send(pack("VVV", $len, 0, $type).$raw);
printf ".\n";
}
@ -33,11 +32,8 @@ sub send_message
{
my $self = shift;
my $type = shift;
return Net::Skinny::Message->new(
$self,
$type,
@_
)->send();
my $message = Net::Skinny::Message->new($type, @_);
return $self->send_raw($message->type(), $message->raw());
}
sub receive_message
@ -58,20 +54,26 @@ sub receive_message
printf "type=%s (%X))", Net::Skinny::Protocol::skinny_message_type2str($type), $type;
if($len > 4) {
$self->recv($buf, $len-4);
} else {
$buf = '';
}
printf ".\n";
return Net::Skinny::Message->new_raw($type, $buf);
}
sub sleep
{
my $self = shift;
my $t = shift;
my %args = @_;
$args{'quiet'} = 0 if not $args{'quiet'};
printf "Sleeping %d seconds", $t;
while(--$t){
sleep(1);
printf "." if $t % 10;
printf "_" unless $t % 10;
if(!$args{'quiet'}) {
printf "." if $t % 10;
printf "_" unless $t % 10;
}
}
printf ".\n";
}

View File

@ -0,0 +1,94 @@
# Copyright (c) 2010 Mathieu Parent <math.parent@gmail.com>.
# All rights reserved. This program is free software; you can redistribute it
# and/or modify it under the same terms as Perl itself.
package Net::Skinny::Client;
use strict;
use warnings;
use Config;
use threads;
use threads::shared;
use Thread::Queue;
require Net::Skinny;
use Net::Skinny::Protocol qw/:all/;
use Net::Skinny::Message;
our(@ISA);
@ISA = qw(Net::Skinny);
my $keep_alive_thread;
my $keep_alives :shared;
our $kept_self;
my $messages_send_queue;
my $messages_receive_queue;
$Config{useithreads} or die('Recompile Perl with threads to run this program.');
sub new {
$kept_self = shift->SUPER::new(@_);
$messages_send_queue = Thread::Queue->new();
$messages_receive_queue = Thread::Queue->new();
threads->create(\&send_messages_thread_func);
threads->create(\&receive_messages_thread_func);
return $kept_self;
}
sub send_message {
my $self = shift;
$messages_send_queue->enqueue(\@_);
}
sub receive_message {
my $self = shift;
my $message = $messages_receive_queue->dequeue();
if($message->type() == 0x100) {#keepaliveack
if(1) {
lock($keep_alives);
$keep_alives--;
}
$message = $messages_receive_queue->dequeue();
}
return $message;
}
sub launch_keep_alive_thread
{
if(!$keep_alive_thread) {
$keep_alive_thread = threads->create(\&keep_alive_thread_func);
} else {
print "keep-alive thread is already running\n";
}
return $keep_alive_thread;
}
sub keep_alive_thread_func
{
while($kept_self) {
if(1) {
lock($keep_alives);
$keep_alives++;
$kept_self->send_message(KEEP_ALIVE_MESSAGE);
} #mutex unlocked
$kept_self->sleep(30, quiet => 0);
}
}
sub send_messages_thread_func
{
while(my $message = $messages_send_queue->dequeue()) {
my $type = shift @$message;
$kept_self->SUPER::send_message($type, @$message);
}
}
sub receive_messages_thread_func
{
while(1) {
$messages_receive_queue->enqueue($kept_self->SUPER::receive_message());
}
}
1;

View File

@ -7,54 +7,96 @@ package Net::Skinny::Message;
use strict;
use warnings;
use threads;
use threads::shared;
use Net::Skinny::Protocol qw/:all/;
use Data::Dumper;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(send);
sub new {
sub new_empty {
my $class = shift;
my $self = {};
bless $self, $class;
$self->{'socket'} = shift;
$self->{'type'} = shift;
%{$self->{'data'}} = @_;
return $ self;
$self->{'type'} = undef;
$self->{'data'} = undef;
$self->{'raw'} = undef;
return $self;
}
sub send {
sub new {
my $self = shift->new_empty();
$self->type(shift);
$self->data(@_) if @_;
return $self;
}
sub new_raw {
my $self = shift->new_empty();
$self->type(shift);
$self->raw(shift);
return $self;
}
sub type
{
my $self = shift;
my $struct = Net::Skinny::Protocol::skinny_message_struct($self->{'type'});
my $raw = '';
my $parsed_count = 0;
for my $info ( @$struct) {
last if !defined($self->{'data'}{@$info[1]});
if(@$info[0] eq 'char') {
$raw .= pack("a".@$info[2], $self->{'data'}{@$info[1]});
} elsif(@$info[0] eq 'uint32_t') {
$raw .= pack("V".@$info[2], $self->{'data'}{@$info[1]});
} elsif(@$info[0] eq 'uint16_t') {
$raw .= pack("n".@$info[2], $self->{'data'}{@$info[1]});
} elsif(@$info[0] eq 'struct in_addr') {
$raw .= pack("V".@$info[2], $self->{'data'}{@$info[1]});
} elsif(@$info[0] eq 'struct station_capabilities') {
$raw .= $self->{'data'}{@$info[1]};
} else {
printf "Unknown type: %s\n", @$info[0];
return;
}
$parsed_count++;
my $type = @_ ? shift : undef;
if(defined($type)) {
$self->{'type'} = $type;
}
if($parsed_count != scalar(keys %{$self->{'data'}})) {
printf "Incomplete message (type=%s (%X)) %d out of %d\n", Net::Skinny::Protocol::skinny_message_type2str($self->{'type'}), $self->{'type'},
$parsed_count, scalar(keys %{$self->{'data'}});
print Dumper(@$struct);
return;
return $self->{'type'};
}
sub data
{
my $self = shift;
my @data = @_;
if(@data) {
%{$self->{'data'}} = @data;
$self->{'raw'} = undef;
} elsif(!defined($self->{'data'})) {
printf "Conversion from raw to data not implemented\n";
}
$self->{'socket'}->send_data($self->{'type'}, $raw);
return $self->{'data'};
}
sub raw
{
my $self = shift;
my $raw = shift || undef;
if(defined($raw)) {
$self->{'raw'} = $raw;
$self->{'data'} = undef;
}
if(!defined($self->{'raw'})) {
my $struct = Net::Skinny::Protocol::skinny_message_struct($self->{'type'});
my $raw = '';
my $parsed_count = 0;
for my $info ( @$struct) {
last if !defined($self->{'data'}{@$info[1]});
if(@$info[0] eq 'char') {
$raw .= pack("a".@$info[2], $self->{'data'}{@$info[1]});
} elsif(@$info[0] eq 'uint32_t') {
$raw .= pack("V".@$info[2], $self->{'data'}{@$info[1]});
} elsif(@$info[0] eq 'uint16_t') {
$raw .= pack("n".@$info[2], $self->{'data'}{@$info[1]});
} elsif(@$info[0] eq 'struct in_addr') {
$raw .= pack("V".@$info[2], $self->{'data'}{@$info[1]});
} elsif(@$info[0] eq 'struct station_capabilities') {
$raw .= $self->{'data'}{@$info[1]};
} else {
printf "Unknown type: %s\n", @$info[0];
return;
}
$parsed_count++;
}
if($parsed_count != scalar(keys %{$self->{'data'}})) {
printf "Incomplete message (type=%s (%X)) %d out of %d\n", Net::Skinny::Protocol::skinny_message_type2str($self->{'type'}), $self->{'type'},
$parsed_count, scalar(keys %{$self->{'data'}});
return;
}
$self->{'raw'} = $raw;
}
return $self->{'raw'};
}
1;

View File

@ -8,7 +8,6 @@ use strict;
no strict "refs";
use warnings;
use Carp;
use Data::Dumper;
require Exporter;
our @ISA = qw(Exporter);
@ -69,7 +68,6 @@ sub _find {
printf "Unparsed line '%s' in %s\n", $_, $struct_name;
}
}
#print "$name: ".Dumper($struct{$name});
}
}
@sub{@_};
@ -77,6 +75,7 @@ sub _find {
sub skinny_message_type2str {
my $message_type = shift;
return "UndefinedTypeMessage" if !defined($message_type);
keys %const;
while (my ($key, $value) = each %const) {

View File

@ -221,7 +221,7 @@ char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *l
"SELECT channel_uuid, line_instance "
"FROM skinny_active_lines "
"WHERE %s AND %s AND %s "
"ORDER BY channel_uuid DESC",
"ORDER BY call_state, channel_uuid", /* off hook first */
device_condition, line_instance_condition, call_id_condition
))) {
skinny_execute_sql_callback(profile, profile->sql_mutex, sql,
@ -235,14 +235,22 @@ char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *l
return helper.channel_uuid;
}
#ifdef SWITCH_DEBUG_RWLOCKS
switch_core_session_t * skinny_profile_perform_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id, const char *file, const char *func, int line)
#else
switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id)
#endif
{
char *uuid;
switch_core_session_t *result = NULL;
uuid = skinny_profile_find_session_uuid(profile, listener, line_instance_p, call_id);
if(!zstr(uuid)) {
#ifdef SWITCH_DEBUG_RWLOCKS
result = switch_core_session_perform_locate(uuid, file, func, line);
#else
result = switch_core_session_locate(uuid);
#endif
if(!result) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unable to find session %s on %s:%d, line %d\n",
@ -357,7 +365,9 @@ struct skinny_line_get_state_helper {
int skinny_line_get_state_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct skinny_line_get_state_helper *helper = pArg;
helper->call_state = atoi(argv[0]);
if (helper->call_state == -1) {
helper->call_state = atoi(argv[0]);
}
return 0;
}
@ -383,10 +393,12 @@ uint32_t skinny_line_get_state(listener_t *listener, uint32_t line_instance, uin
}
switch_assert(call_id_condition);
helper.call_state = -1;
if ((sql = switch_mprintf(
"SELECT call_state FROM skinny_active_lines "
"WHERE device_name='%s' AND device_instance=%d "
"AND %s AND %s",
"AND %s AND %s "
"ORDER BY call_state, channel_uuid", /* off hook first */
listener->device_name, listener->device_instance,
line_instance_condition, call_id_condition
))) {
@ -531,6 +543,7 @@ void tech_init(private_t *tech_pvt, skinny_profile_t *profile, switch_core_sessi
switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
tech_pvt->call_id = ++profile->next_call_id;
tech_pvt->party_id = tech_pvt->call_id;
tech_pvt->profile = profile;
switch_core_session_set_private(session, tech_pvt);
tech_pvt->session = session;
@ -633,16 +646,7 @@ int channel_on_hangup_callback(void *pArg, int argc, char **argv, char **columnN
send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_OFF);
send_clear_prompt_status(listener, line_instance, call_id);
if(call_state == SKINNY_CONNECTED) { /* calling parties */
send_close_receive_channel(listener,
call_id, /* uint32_t conference_id, */
helper->tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
call_id /* uint32_t conference_id2, */
);
send_stop_media_transmission(listener,
call_id, /* uint32_t conference_id, */
helper->tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
call_id /* uint32_t conference_id2, */
);
skinny_session_stop_media(helper->tech_pvt->session, listener, line_instance);
}
skinny_line_set_state(listener, line_instance, call_id, SKINNY_ON_HOOK);
@ -650,7 +654,6 @@ int channel_on_hangup_callback(void *pArg, int argc, char **argv, char **columnN
/* TODO: DefineTimeDate */
send_set_speaker_mode(listener, SKINNY_SPEAKER_OFF);
send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, call_id);
}
return 0;
}
@ -1229,6 +1232,9 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
switch_clear_flag_locked(listener, LFLAG_RUNNING);
break;
}
if (!listener_is_ready(listener)) {
break;
}
if (!request) {
continue;
@ -1473,7 +1479,7 @@ static switch_status_t load_skinny_config(void)
}
profile = switch_core_alloc(profile_pool, sizeof(skinny_profile_t));
profile->pool = profile_pool;
profile->name = profile_name;
profile->name = switch_core_strdup(profile->pool, profile_name);
switch_mutex_init(&profile->listener_mutex, SWITCH_MUTEX_NESTED, profile->pool);
switch_mutex_init(&profile->sql_mutex, SWITCH_MUTEX_NESTED, profile->pool);
switch_mutex_init(&profile->sock_mutex, SWITCH_MUTEX_NESTED, profile->pool);

View File

@ -189,7 +189,12 @@ switch_status_t skinny_profile_dump(const skinny_profile_t *profile, switch_stre
switch_status_t skinny_profile_find_listener_by_device_name(skinny_profile_t *profile, const char *device_name, listener_t **listener);
switch_status_t skinny_profile_find_listener_by_device_name_and_instance(skinny_profile_t *profile, const char *device_name, uint32_t device_instance, listener_t **listener);
char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id);
#ifdef SWITCH_DEBUG_RWLOCKS
switch_core_session_t * skinny_profile_perform_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id, const char *file, const char *func, int line);
#define skinny_profile_find_session(profile, listener, line_instance_p, call_id) skinny_profile_perform_find_session(profile, listener, line_instance_p, call_id, __FILE__, __SWITCH_FUNC__, __LINE__)
#else
switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id);
#endif
switch_status_t dump_device(skinny_profile_t *profile, const char *device_name, switch_stream_handle_t *stream);
/*****************************************************************************/

View File

@ -446,19 +446,20 @@ switch_status_t skinny_create_ingoing_session(listener_t *listener, uint32_t *li
line_instance = *line_instance_p;
if((nsession = skinny_profile_find_session(listener->profile, listener, line_instance_p, 0))) {
switch_core_session_rwunlock(nsession);
if(skinny_line_get_state(listener, *line_instance_p, 0) == SKINNY_OFF_HOOK) {
/* Reuse existing session */
*session = nsession;
return SWITCH_STATUS_SUCCESS;
}
skinny_session_hold_line(nsession, listener, *line_instance_p);
switch_core_session_rwunlock(nsession);
}
*line_instance_p = line_instance;
if(*line_instance_p == 0) {
*line_instance_p = 1;
}
skinny_hold_active_calls(listener);
skinny_line_get(listener, *line_instance_p, &button);
if (!button || !button->shortname) {
@ -494,7 +495,11 @@ switch_status_t skinny_create_ingoing_session(listener_t *listener, uint32_t *li
"Error Creating Session thread\n");
goto error;
}
if (switch_core_session_read_lock(nsession) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(nsession), SWITCH_LOG_CRIT,
"Error Locking Session\n");
goto error;
}
if (!(tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(nsession),
NULL, listener->profile->dialplan,
button->shortname, button->name,
@ -543,6 +548,49 @@ done:
return SWITCH_STATUS_SUCCESS;
}
struct skinny_session_process_dest_helper {
private_t *tech_pvt;
listener_t *listener;
uint32_t line_instance;
};
int skinny_session_process_dest_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct skinny_session_process_dest_helper *helper = pArg;
listener_t *listener = NULL;
char *device_name = argv[0];
uint32_t device_instance = atoi(argv[1]);
/* uint32_t position = atoi(argv[2]); */
uint32_t line_instance = atoi(argv[3]);
/* char *label = argv[4]; */
/* char *value = argv[5]; */
/* char *caller_name = argv[6]; */
/* uint32_t ring_on_idle = atoi(argv[7]); */
/* uint32_t ring_on_active = atoi(argv[8]); */
/* uint32_t busy_trigger = atoi(argv[9]); */
/* char *forward_all = argv[10]; */
/* char *forward_busy = argv[11]; */
/* char *forward_noanswer = argv[12]; */
/* uint32_t noanswer_duration = atoi(argv[13]); */
/* char *channel_uuid = argv[14]; */
/* uint32_t call_id = atoi(argv[15]); */
/* uint32_t call_state = atoi(argv[16]); */
skinny_profile_find_listener_by_device_name_and_instance(helper->tech_pvt->profile, device_name, device_instance, &listener);
if(listener) {
if(!strcmp(device_name, helper->listener->device_name)
&& (device_instance == helper->listener->device_instance)
&& (line_instance == helper->line_instance)) {/* the calling line */
/* nothing */
} else {
/* TODO: capture and check what should happen here*/
skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_IN_USE_REMOTELY);
}
}
return 0;
}
switch_status_t skinny_session_process_dest(switch_core_session_t *session, listener_t *listener, uint32_t line_instance, char *dest, char append_dest, uint32_t backspace)
{
switch_channel_t *channel = NULL;
@ -555,31 +603,43 @@ switch_status_t skinny_session_process_dest(switch_core_session_t *session, list
channel = switch_core_session_get_channel(session);
tech_pvt = switch_core_session_get_private(session);
if(!dest) {
if(append_dest == '\0') {/* no digit yet */
send_start_tone(listener, SKINNY_TONE_DIALTONE, 0, line_instance, tech_pvt->call_id);
} else {
if(strlen(tech_pvt->caller_profile->destination_number) == 0) {/* first digit */
send_stop_tone(listener, line_instance, tech_pvt->call_id);
send_select_soft_keys(listener, line_instance, tech_pvt->call_id,
SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT, 0xffff);
}
if (!dest) {
if (backspace) { /* backspace */
*tech_pvt->caller_profile->destination_number++ = '\0';
}
if (append_dest != '\0' && !backspace) {/* append digit */
tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool,
"%s%c", tech_pvt->caller_profile->destination_number, append_dest);
}
if (strlen(tech_pvt->caller_profile->destination_number) == 0) {/* no digit yet */
send_start_tone(listener, SKINNY_TONE_DIALTONE, 0, line_instance, tech_pvt->call_id);
if(backspace) {
send_select_soft_keys(listener, line_instance, tech_pvt->call_id, SKINNY_KEY_SET_OFF_HOOK, 0xffff);
/* TODO: How to clear the screen? */
}
} else if (strlen(tech_pvt->caller_profile->destination_number) == 1) {/* first digit */
send_stop_tone(listener, line_instance, tech_pvt->call_id);
send_select_soft_keys(listener, line_instance, tech_pvt->call_id,
SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT, 0xffff);
}
} else {
tech_pvt->caller_profile->destination_number = switch_core_strdup(tech_pvt->caller_profile->pool,
dest);
}
/* TODO Number is complete -> check against dialplan */
if((strlen(tech_pvt->caller_profile->destination_number) >= 4) || dest) {
if ((strlen(tech_pvt->caller_profile->destination_number) >= 4) || dest) {
struct skinny_session_process_dest_helper helper = {0};
send_dialed_number(listener, tech_pvt->caller_profile->destination_number, line_instance, tech_pvt->call_id);
skinny_line_set_state(listener, line_instance, tech_pvt->call_id, SKINNY_PROCEED);
skinny_send_call_info(session, listener, line_instance);
skinny_session_start_media(session, listener, line_instance);
}
switch_core_session_rwunlock(session);
skinny_session_start_media(session, listener, line_instance);
helper.tech_pvt = tech_pvt;
helper.listener = listener;
helper.line_instance = line_instance;
skinny_session_walk_lines(tech_pvt->profile, switch_core_session_get_uuid(session), skinny_session_process_dest_callback, &helper);
}
return SWITCH_STATUS_SUCCESS;
}
@ -603,8 +663,6 @@ switch_status_t skinny_session_ring_out(switch_core_session_t *session, listener
line_instance, tech_pvt->call_id);
skinny_send_call_info(session, listener, line_instance);
switch_core_session_rwunlock(session);
return SWITCH_STATUS_SUCCESS;
}
@ -643,16 +701,14 @@ int skinny_session_answer_callback(void *pArg, int argc, char **argv, char **col
if(!strcmp(device_name, helper->listener->device_name)
&& (device_instance == helper->listener->device_instance)
&& (line_instance == helper->line_instance)) {/* the answering line */
send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, helper->tech_pvt->call_id);
send_set_speaker_mode(listener, SKINNY_SPEAKER_ON);
/* nothing */
} else {
send_define_current_time_date(listener);
send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON);
skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_OFF_HOOK);
/* send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, SKINNY_KEY_SET_OFF_HOOK, 0xffff); */
/* display_prompt_status(listener, 0, "\200\000",
line_instance, tech_pvt->call_id); */
send_activate_call_plane(listener, line_instance);
skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_IN_USE_REMOTELY);
send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, 10, 0x0002);
send_display_prompt_status(listener, 0, "\200\037", line_instance, helper->tech_pvt->call_id);
send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, helper->tech_pvt->call_id);
}
}
return 0;
@ -671,6 +727,12 @@ switch_status_t skinny_session_answer(switch_core_session_t *session, listener_t
channel = switch_core_session_get_channel(session);
tech_pvt = switch_core_session_get_private(session);
send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, tech_pvt->call_id);
send_set_speaker_mode(listener, SKINNY_SPEAKER_ON);
send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON);
skinny_line_set_state(listener, line_instance, tech_pvt->call_id, SKINNY_OFF_HOOK);
send_activate_call_plane(listener, line_instance);
helper.tech_pvt = tech_pvt;
helper.listener = listener;
helper.line_instance = line_instance;
@ -679,8 +741,6 @@ switch_status_t skinny_session_answer(switch_core_session_t *session, listener_t
skinny_session_start_media(session, listener, line_instance);
switch_core_session_rwunlock(session);
return SWITCH_STATUS_SUCCESS;
}
@ -717,8 +777,6 @@ switch_status_t skinny_session_start_media(switch_core_session_t *session, liste
tech_pvt->call_id);
skinny_send_call_info(session, listener, line_instance);
switch_core_session_rwunlock(session);
return SWITCH_STATUS_SUCCESS;
}
@ -734,22 +792,129 @@ switch_status_t skinny_session_hold_line(switch_core_session_t *session, listene
channel = switch_core_session_get_channel(session);
tech_pvt = switch_core_session_get_private(session);
/* TODO */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Hold is not implemented yet. Hanging up the line.\n");
skinny_session_stop_media(session, listener, line_instance);
switch_ivr_hold(session, NULL, 1);
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
switch_core_session_rwunlock(session);
send_define_current_time_date(listener);
send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_WINK);
skinny_line_set_state(listener, line_instance, tech_pvt->call_id, SKINNY_HOLD);
send_select_soft_keys(listener, line_instance, tech_pvt->call_id, SKINNY_KEY_SET_ON_HOLD, 0xffff);
send_display_prompt_status(listener, 0, "\200\003",
line_instance, tech_pvt->call_id);
skinny_send_call_info(tech_pvt->session, listener, line_instance);
send_set_speaker_mode(listener, SKINNY_SPEAKER_OFF);
send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, tech_pvt->call_id);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_session_unhold_line(switch_core_session_t *session, listener_t *listener, uint32_t line_instance)
{
/* TODO */
switch_channel_t *channel = NULL;
private_t *tech_pvt = NULL;
switch_assert(session);
switch_assert(listener);
switch_assert(listener->profile);
channel = switch_core_session_get_channel(session);
tech_pvt = switch_core_session_get_private(session);
skinny_hold_active_calls(listener);
send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, tech_pvt->call_id);
send_set_speaker_mode(listener, SKINNY_SPEAKER_ON);
send_select_soft_keys(listener, line_instance, tech_pvt->call_id, SKINNY_KEY_SET_RING_OUT, 0xffff);
skinny_session_start_media(session, listener, line_instance);
switch_ivr_unhold(session);
send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_session_stop_media(switch_core_session_t *session, listener_t *listener, uint32_t line_instance)
{
switch_channel_t *channel = NULL;
private_t *tech_pvt = NULL;
switch_assert(session);
switch_assert(listener);
switch_assert(listener->profile);
channel = switch_core_session_get_channel(session);
tech_pvt = switch_core_session_get_private(session);
send_close_receive_channel(listener,
tech_pvt->call_id, /* uint32_t conference_id, */
tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
tech_pvt->call_id /* uint32_t conference_id2, */
);
send_stop_media_transmission(listener,
tech_pvt->call_id, /* uint32_t conference_id, */
tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
tech_pvt->call_id /* uint32_t conference_id2, */
);
return SWITCH_STATUS_SUCCESS;
}
struct skinny_hold_active_calls_helper {
listener_t *listener;
};
int skinny_hold_active_calls_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct skinny_hold_active_calls_helper *helper = pArg;
switch_core_session_t *session;
/* char *device_name = argv[0]; */
/* uint32_t device_instance = atoi(argv[1]); */
/* uint32_t position = atoi(argv[2]); */
uint32_t line_instance = atoi(argv[3]);
/* char *label = argv[4]; */
/* char *value = argv[5]; */
/* char *caller_name = argv[6]; */
/* uint32_t ring_on_idle = atoi(argv[7]); */
/* uint32_t ring_on_active = atoi(argv[8]); */
/* uint32_t busy_trigger = atoi(argv[9]); */
/* char *forward_all = argv[10]; */
/* char *forward_busy = argv[11]; */
/* char *forward_noanswer = argv[12]; */
/* uint32_t noanswer_duration = atoi(argv[13]); */
/* char *channel_uuid = argv[14]; */
uint32_t call_id = atoi(argv[15]);
/* uint32_t call_state = atoi(argv[16]); */
session = skinny_profile_find_session(helper->listener->profile, helper->listener, &line_instance, call_id);
if(session) {
skinny_session_hold_line(session, helper->listener, line_instance);
switch_core_session_rwunlock(session);
}
return 0;
}
switch_status_t skinny_hold_active_calls(listener_t *listener)
{
struct skinny_hold_active_calls_helper helper = {0};
char *sql;
helper.listener = listener;
if ((sql = switch_mprintf(
"SELECT skinny_lines.*, channel_uuid, call_id, call_state "
"FROM skinny_active_lines "
"INNER JOIN skinny_lines "
"ON skinny_active_lines.device_name = skinny_lines.device_name "
"AND skinny_active_lines.device_instance = skinny_lines.device_instance "
"AND skinny_active_lines.line_instance = skinny_lines.line_instance "
"WHERE skinny_lines.device_name='%s' AND skinny_lines.device_instance=%d AND call_state=%d",
listener->device_name, listener->device_instance, SKINNY_CONNECTED))) {
skinny_execute_sql_callback(listener->profile, listener->profile->sql_mutex, sql, skinny_hold_active_calls_callback, &helper);
switch_safe_free(sql);
}
return SWITCH_STATUS_SUCCESS;
}
/*****************************************************************************/
/* SKINNY BUTTONS */
/*****************************************************************************/
@ -1480,6 +1645,9 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r
}
}
}
if (xroot) {
switch_xml_free(xroot);
}
status = SWITCH_STATUS_SUCCESS;
@ -1789,10 +1957,26 @@ switch_status_t skinny_handle_soft_key_set_request(listener_t *listener, skinny_
message->data.soft_key_set.total_soft_key_set_count = 11;
/* TODO fill the set */
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[0] = SOFTKEY_REDIAL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[1] = SOFTKEY_NEWCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[0] = SOFTKEY_NEWCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[2] = SOFTKEY_ENDCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT].soft_key_template_index[0] = SOFTKEY_BACKSPACE;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT].soft_key_template_index[2] = SOFTKEY_ENDCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[0] = SOFTKEY_ENDCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[0] = SOFTKEY_ENDCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[1] = SOFTKEY_HOLD;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[2] = SOFTKEY_NEWCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[0] = SOFTKEY_ANSWER;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[1] = SOFTKEY_ENDCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[2] = SOFTKEY_NEWCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[0] = SOFTKEY_NEWCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[1] = SOFTKEY_RESUME;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[2] = SOFTKEY_ENDCALL;
skinny_send_reply(listener, message);
@ -1931,7 +2115,6 @@ switch_status_t skinny_handle_soft_key_event_message(listener_t *listener, skinn
case SOFTKEY_NEWCALL:
status = skinny_create_ingoing_session(listener, &line_instance, &session);
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
skinny_session_process_dest(session, listener, line_instance, NULL, '\0', 0);
break;
@ -1942,6 +2125,13 @@ switch_status_t skinny_handle_soft_key_event_message(listener_t *listener, skinn
status = skinny_session_hold_line(session, listener, line_instance);
}
break;
case SOFTKEY_BACKSPACE:
session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.soft_key_event.call_id);
if(session) {
skinny_session_process_dest(session, listener, line_instance, NULL, '\0', 1);
}
break;
case SOFTKEY_ENDCALL:
session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.soft_key_event.call_id);
@ -1967,7 +2157,7 @@ switch_status_t skinny_handle_soft_key_event_message(listener_t *listener, skinn
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unknown SoftKeyEvent type while busy: %d.\n", request->data.soft_key_event.event);
"Unknown SoftKeyEvent type: %d.\n", request->data.soft_key_event.event);
}
if(session) {
@ -2002,6 +2192,11 @@ switch_status_t skinny_handle_off_hook_message(listener_t *listener, skinny_mess
skinny_session_process_dest(session, listener, line_instance, NULL, '\0', 0);
}
if(session) {
switch_core_session_rwunlock(session);
}
return SWITCH_STATUS_SUCCESS;
}
@ -2037,6 +2232,11 @@ switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_mess
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown Stimulus Type Received [%d]\n", request->data.stimulus.instance_type);
}
if(session) {
switch_core_session_rwunlock(session);
}
return SWITCH_STATUS_SUCCESS;
}
@ -2118,9 +2318,13 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste
}
switch_channel_mark_answered(channel);
switch_core_session_rwunlock(session);
}
end:
if(session) {
switch_core_session_rwunlock(session);
}
return status;
}
@ -2171,6 +2375,9 @@ switch_status_t skinny_handle_keypad_button_message(listener_t *listener, skinny
switch_channel_queue_dtmf(channel, &dtmf);
}
}
}
if(session) {
switch_core_session_rwunlock(session);
}
@ -2195,9 +2402,12 @@ switch_status_t skinny_handle_on_hook_message(listener_t *listener, skinny_messa
channel = switch_core_session_get_channel(session);
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
}
if(session) {
switch_core_session_rwunlock(session);
}
return status;
}

View File

@ -630,6 +630,8 @@ switch_status_t skinny_session_answer(switch_core_session_t *session, listener_t
switch_status_t skinny_session_start_media(switch_core_session_t *session, listener_t *listener, uint32_t line_instance);
switch_status_t skinny_session_hold_line(switch_core_session_t *session, listener_t *listener, uint32_t line_instance);
switch_status_t skinny_session_unhold_line(switch_core_session_t *session, listener_t *listener, uint32_t line_instance);
switch_status_t skinny_session_stop_media(switch_core_session_t *session, listener_t *listener, uint32_t line_instance);
switch_status_t skinny_hold_active_calls(listener_t *listener);
void skinny_line_get(listener_t *listener, uint32_t instance, struct line_stat_res_message **button);
void skinny_speed_dial_get(listener_t *listener, uint32_t instance, struct speed_dial_stat_res_message **button);

View File

@ -15,6 +15,7 @@ use Sys::Hostname;
use Net::Skinny;
use Net::Skinny::Protocol qw/:all/;
use Net::Skinny::Message;
use Net::Skinny::Client;
#Config
my $skinny_server = hostname;
@ -23,13 +24,13 @@ my $device_ip = 10+256*(11+256*(12+256*13)); # 10.11.12.13
#======
$| = 1;
my $socket = Net::Skinny->new(
my $socket = Net::Skinny::Client->new(
PeerAddr => $skinny_server,
PeerPort => 2000,
);
if(!$socket) {
print "Unable to connect to server\n";
printf "Unable to connect to server %s\n", $skinny_server;
exit 1;
}
# =============================================================================
@ -84,11 +85,8 @@ $socket->send_message(
count => 2
);
for(my $i = 0; $i < 1; $i++) {
$socket->sleep(5);
$socket->send_message(KEEP_ALIVE_MESSAGE);
$socket->receive_message(); # keepaliveack
}
$socket->launch_keep_alive_thread();
$socket->sleep(5);
#NewCall

View File

@ -77,6 +77,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co
switch_status_t status = SWITCH_STATUS_FALSE;
const char *ct = "text/html";
sofia_destination_t *dst = NULL;
char *to_uri = NULL;
if (!to) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing To: header.\n");
@ -98,9 +99,17 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co
user = prof;
prof = NULL;
}
if (!strncasecmp(user, "sip:", 4)) {
to_uri = user;
}
if ((host = strchr(user, '@'))) {
*host++ = '\0';
if (!to_uri) {
*host++ = '\0';
} else {
host++;
}
if (!prof)
prof = host;
}
@ -118,7 +127,8 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co
host = prof;
}
}
if (!sofia_reg_find_reg_url(profile, user, host, buf, sizeof(buf))) {
if (!to_uri && !sofia_reg_find_reg_url(profile, user, host, buf, sizeof(buf))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find user. [%s][%s]\n", user, host);
goto end;
}
@ -152,7 +162,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co
switch_safe_free(fp);
}
if (!(dst = sofia_glue_get_destination(buf))) {
if (!(dst = sofia_glue_get_destination(to_uri ? to_uri : buf))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
goto end;
}
@ -162,7 +172,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co
status = SWITCH_STATUS_SUCCESS;
/* if this cries, add contact here too, change the 1 to 0 and omit the safe_free */
msg_nh = nua_handle(profile->nua, NULL, TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)),
SIPTAG_FROM_STR(from), NUTAG_URL(contact), SIPTAG_TO_STR(dst->to), SIPTAG_CONTACT_STR(profile->url), TAG_END());
SIPTAG_FROM_STR(from), TAG_IF(contact, NUTAG_URL(contact)), SIPTAG_TO_STR(dst->to), SIPTAG_CONTACT_STR(profile->url), TAG_END());
nua_handle_bind(msg_nh, &mod_sofia_globals.destroy_private);
nua_message(msg_nh, SIPTAG_CONTENT_TYPE_STR(ct), SIPTAG_PAYLOAD_STR(body), TAG_END());

View File

@ -21403,21 +21403,36 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_variable_partner(void *
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_var_check(void * jarg1, char * jarg2, char * jarg3, int jarg4, int jarg5) {
SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_var_check(void * jarg1, char * jarg2, char * jarg3, int jarg4) {
int jresult ;
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
switch_bool_t arg4 ;
switch_bool_t arg5 ;
switch_status_t result;
arg1 = (switch_channel_t *)jarg1;
arg2 = (char *)jarg2;
arg3 = (char *)jarg3;
arg4 = (switch_bool_t)jarg4;
arg5 = (switch_bool_t)jarg5;
result = (switch_status_t)switch_channel_export_variable_var_check(arg1,(char const *)arg2,(char const *)arg3,arg4,arg5);
result = (switch_status_t)switch_channel_export_variable_var_check(arg1,(char const *)arg2,(char const *)arg3,arg4);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_printf(void * jarg1, char * jarg2, char * jarg3) {
int jresult ;
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
void *arg4 = 0 ;
switch_status_t result;
arg1 = (switch_channel_t *)jarg1;
arg2 = (char *)jarg2;
arg3 = (char *)jarg3;
result = (switch_status_t)switch_channel_export_variable_printf(arg1,(char const *)arg2,(char const *)arg3,arg4);
jresult = result;
return jresult;
}

View File

@ -2904,8 +2904,13 @@ public class freeswitch {
return ret;
}
public static switch_status_t switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel channel, string varname, string value, switch_bool_t var_check, switch_bool_t nolocal) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, value, (int)var_check, (int)nolocal);
public static switch_status_t switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel channel, string varname, string value, switch_bool_t var_check) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, value, (int)var_check);
return ret;
}
public static switch_status_t switch_channel_export_variable_printf(SWIGTYPE_p_switch_channel channel, string varname, string fmt) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_printf(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, fmt);
return ret;
}
@ -10215,7 +10220,10 @@ class freeswitchPINVOKE {
public static extern string switch_channel_get_variable_partner(HandleRef jarg1, string jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_export_variable_var_check")]
public static extern int switch_channel_export_variable_var_check(HandleRef jarg1, string jarg2, string jarg3, int jarg4, int jarg5);
public static extern int switch_channel_export_variable_var_check(HandleRef jarg1, string jarg2, string jarg3, int jarg4);
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_export_variable_printf")]
public static extern int switch_channel_export_variable_printf(HandleRef jarg1, string jarg2, string jarg3);
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_variable_dup")]
public static extern string switch_channel_get_variable_dup(HandleRef jarg1, string jarg2, int jarg3);