Merge branch 'master' of git.freeswitch.org:freeswitch
This commit is contained in:
commit
7f82a41a85
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -85,6 +85,7 @@ private slots:
|
|||
void updateCallTimers();
|
||||
void debugConsoleTriggered();
|
||||
void debugEventsTriggered();
|
||||
void applyPreprocessors(QStringList);
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="freetdm.lib libsangoma.lib"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories=""$(OutDir)";"C:\Program Files\Sangoma\lib""
|
||||
AdditionalLibraryDirectories=""$(OutDir)";"C:\Program Files\Sangoma\api\lib\x86""
|
||||
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=""$(OutDir)";../../../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=""$(OutDir)";../../../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)"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue